3535
3636#include <m-buffer.h>
3737#include <m-string.h>
38+ #include <m-atomic.h>
3839
3940/// Number of events to buffer to I/O thread
4041#define BSL_LOG_QUEUE_SIZE 100
@@ -82,14 +83,48 @@ static void BSL_LogEvent_event_deinit(BSL_LogEvent_event_t *obj)
8283 string_clear (obj -> context );
8384}
8485
86+ static void BSL_LogEvent_event_init_set (BSL_LogEvent_event_t * obj , const BSL_LogEvent_event_t * src )
87+ {
88+ obj -> thread = src -> thread ;
89+ obj -> timestamp = src -> timestamp ;
90+ obj -> severity = src -> severity ;
91+ string_init_set (obj -> context , src -> context );
92+ string_init_set (obj -> message , src -> message );
93+ }
94+
95+ static void BSL_LogEvent_event_init_move (BSL_LogEvent_event_t * obj , BSL_LogEvent_event_t * src )
96+ {
97+ obj -> thread = src -> thread ;
98+ obj -> timestamp = src -> timestamp ;
99+ obj -> severity = src -> severity ;
100+ string_init_move (obj -> context , src -> context );
101+ string_init_move (obj -> message , src -> message );
102+ }
103+
104+ static void BSL_LogEvent_event_set (BSL_LogEvent_event_t * obj , const BSL_LogEvent_event_t * src )
105+ {
106+ obj -> thread = src -> thread ;
107+ obj -> timestamp = src -> timestamp ;
108+ obj -> severity = src -> severity ;
109+ string_set (obj -> context , src -> context );
110+ string_set (obj -> message , src -> message );
111+ }
112+
85113/// OPLIST for BSL_LogEvent_event_t
86- #define M_OPL_BSL_LogEvent_event_t () (INIT(API_2(BSL_LogEvent_event_init)), CLEAR(API_2(BSL_LogEvent_event_deinit)))
114+ #define M_OPL_BSL_LogEvent_event_t () \
115+ (INIT(API_2(BSL_LogEvent_event_init)), INIT_SET(API_6(BSL_LogEvent_event_init_set)), \
116+ INIT_MOVE(API_6(BSL_LogEvent_event_init_move)), SET(API_6(BSL_LogEvent_event_set)), \
117+ CLEAR(API_2(BSL_LogEvent_event_deinit)))
87118
88119// NOLINTBEGIN
89120/// @cond Doxygen_Suppress
90- M_BUFFER_DEF (BSL_LogEvent_queue , BSL_LogEvent_event_t , BSL_LOG_QUEUE_SIZE , M_BUFFER_THREAD_SAFE | M_BUFFER_BLOCKING )
121+ M_BUFFER_DEF (BSL_LogEvent_queue , BSL_LogEvent_event_t , BSL_LOG_QUEUE_SIZE ,
122+ M_BUFFER_THREAD_SAFE | M_BUFFER_BLOCKING | M_BUFFER_PUSH_INIT_POP_MOVE )
91123/// @endcond
92124
125+ /// Shared least severity
126+ static atomic_int least_severity = LOG_DEBUG ;
127+
93128/// Shared safe queue
94129static BSL_LogEvent_queue_t event_queue ;
95130/// Sink thread ID
@@ -156,17 +191,19 @@ static void write_log(const BSL_LogEvent_event_t *event)
156191
157192static void * work_sink (void * arg _U_ )
158193{
159- while (true)
194+ bool running = true;
195+ while (running )
160196 {
161197 BSL_LogEvent_event_t event ;
162198 BSL_LogEvent_queue_pop (& event , event_queue );
163199 if (string_empty_p (event .message ))
164200 {
165- BSL_LogEvent_event_deinit (& event );
166- break ;
201+ running = false;
202+ }
203+ else
204+ {
205+ write_log (& event );
167206 }
168-
169- write_log (& event );
170207 BSL_LogEvent_event_deinit (& event );
171208 }
172209 return NULL ;
@@ -198,6 +235,7 @@ void BSL_closelog(void)
198235 BSL_LogEvent_event_t event ;
199236 BSL_LogEvent_event_init (& event );
200237 BSL_LogEvent_queue_push (event_queue , event );
238+ BSL_LogEvent_event_deinit (& event );
201239
202240 int res = pthread_join (thr_sink , NULL );
203241 if (res )
@@ -214,12 +252,59 @@ void BSL_closelog(void)
214252 {
215253 atomic_store (& thr_valid , false);
216254 }
255+
256+ // no consumer after join above
257+ BSL_LogEvent_queue_clear (event_queue );
258+ }
259+
260+ int BSL_LogGetSeverity (int * severity , const char * name )
261+ {
262+ CHKERR1 (severity )
263+ CHKERR1 (name )
264+
265+ for (size_t ix = 0 ; ix < sizeof (sev_names ) / sizeof (const char * ); ++ ix )
266+ {
267+ if (!sev_names [ix ])
268+ {
269+ continue ;
270+ }
271+ if (strcasecmp (sev_names [ix ], name ) == 0 )
272+ {
273+ * severity = (int )ix ;
274+ return 0 ;
275+ }
276+ }
277+ return 2 ;
278+ }
279+
280+ void BSL_LogSetLeastSeverity (int severity )
281+ {
282+ if ((severity < 0 ) || (severity > LOG_DEBUG ))
283+ {
284+ return ;
285+ }
286+
287+ atomic_store (& least_severity , severity );
288+ }
289+
290+ bool BSL_LogIsEnabledFor (int severity )
291+ {
292+ if ((severity < 0 ) || (severity > LOG_DEBUG ))
293+ {
294+ return false;
295+ }
296+
297+ const int limit = atomic_load (& least_severity );
298+ // lower severity has higher define value
299+ const bool enabled = (limit >= severity );
300+
301+ return enabled ;
217302}
218303
219304// NOLINTBEGIN
220305void BSL_LogEvent (int severity , const char * filename , int lineno , const char * funcname , const char * format , ...)
221306{
222- if ((severity < 0 ) || ( severity > LOG_DEBUG ))
307+ if (! BSL_LogIsEnabledFor (severity ))
223308 {
224309 return ;
225310 }
@@ -251,28 +336,25 @@ void BSL_LogEvent(int severity, const char *filename, int lineno, const char *fu
251336 va_end (val );
252337 }
253338
254- if (string_empty_p (event .message ))
255- {
256- // ignore empty messages
257- BSL_LogEvent_event_deinit (& event );
258- return ;
259- }
260-
261- if (atomic_load (& thr_valid ))
262- {
263- BSL_LogEvent_queue_push (event_queue , event );
264- }
265- else
339+ // ignore empty messages
340+ if (!string_empty_p (event .message ))
266341 {
267- BSL_LogEvent_event_t manual ;
268- BSL_LogEvent_event_init (& manual );
269- manual .severity = LOG_CRIT ;
270- string_set_str (manual .message , "BSL_LogEvent() called before BSL_openlog()" );
271- write_log (& manual );
272- BSL_LogEvent_event_deinit (& manual );
342+ if (atomic_load (& thr_valid ))
343+ {
344+ BSL_LogEvent_queue_push (event_queue , event );
345+ }
346+ else
347+ {
348+ BSL_LogEvent_event_t manual ;
349+ BSL_LogEvent_event_init (& manual );
350+ manual .severity = LOG_CRIT ;
351+ string_set_str (manual .message , "BSL_LogEvent() called before BSL_openlog()" );
352+ write_log (& manual );
353+ BSL_LogEvent_event_deinit (& manual );
273354
274- write_log (& event );
275- BSL_LogEvent_event_deinit ( & event );
355+ write_log (& event );
356+ }
276357 }
358+ BSL_LogEvent_event_deinit (& event );
277359}
278360// NOLINTEND
0 commit comments