Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : #include "monetdb_config.h"
14 : #include "gdk.h"
15 : #include "gdk_private.h"
16 : #include "mutils.h"
17 :
18 : #define DEFAULT_ADAPTER BASIC
19 : #define DEFAULT_LOG_LEVEL M_ERROR
20 : #define DEFAULT_FLUSH_LEVEL M_DEBUG
21 :
22 : #define FILE_NAME "mdbtrace.log"
23 :
24 : #define AS_STR(x) #x
25 : #define STR(x) AS_STR(x)
26 :
27 : #define GENERATE_STRING(STRING) #STRING,
28 :
29 : static FILE *active_tracer;
30 : MT_Lock GDKtracer_lock = MT_LOCK_INITIALIZER(GDKtracer_lock);
31 :
32 : static char *file_name;
33 :
34 : static ATOMIC_TYPE cur_adapter = ATOMIC_VAR_INIT(DEFAULT_ADAPTER);
35 :
36 : static log_level_t cur_flush_level = DEFAULT_FLUSH_LEVEL;
37 :
38 : static bool write_to_tracer = false;
39 :
40 : #define GENERATE_LOG_LEVEL(COMP) ATOMIC_VAR_INIT((ATOMIC_BASE_TYPE) DEFAULT_LOG_LEVEL),
41 : ATOMIC_TYPE lvl_per_component[] = {
42 : FOREACH_COMP(GENERATE_LOG_LEVEL)
43 : };
44 :
45 : static const char *adapter_str[] = {
46 : FOREACH_ADPTR(GENERATE_STRING)
47 : };
48 :
49 : static const char *layer_str[] = {
50 : FOREACH_LAYER(GENERATE_STRING)
51 : };
52 :
53 : static const char *component_str[] = {
54 : FOREACH_COMP(GENERATE_STRING)
55 : };
56 :
57 : static const char *level_str[] = {
58 : FOREACH_LEVEL(GENERATE_STRING)
59 : };
60 :
61 :
62 : #define MXW "20"
63 :
64 : #define TS_SIZE ((size_t) 20) /* buffer size needed for timestamp */
65 :
66 :
67 : /*
68 : * GDKtracer Stream Macros
69 : */
70 : // Exception
71 : #define GDK_TRACER_EXCEPTION(MSG) \
72 : fprintf(stderr, \
73 : "%s " \
74 : "%-"MXW"s " \
75 : "%"MXW"s:%d " \
76 : "%"MXW"s " \
77 : "%-"MXW"s " \
78 : "%-"MXW"s # "MSG, \
79 : get_timestamp((char[TS_SIZE]){0}, TS_SIZE), \
80 : __FILE__, \
81 : __func__, \
82 : __LINE__, \
83 : STR(M_CRITICAL), \
84 : STR(GDK_TRACER), \
85 : MT_thread_getname());
86 : #define GDK_TRACER_EXCEPTION2(MSG, ...) \
87 : fprintf(stderr, \
88 : "%s " \
89 : "%-"MXW"s " \
90 : "%"MXW"s:%d " \
91 : "%"MXW"s " \
92 : "%-"MXW"s " \
93 : "%-"MXW"s # "MSG, \
94 : get_timestamp((char[TS_SIZE]){0}, TS_SIZE), \
95 : __FILE__, \
96 : __func__, \
97 : __LINE__, \
98 : STR(M_CRITICAL), \
99 : STR(GDK_TRACER), \
100 : MT_thread_getname(), \
101 : __VA_ARGS__);
102 :
103 :
104 : #define GDK_TRACER_RESET_OUTPUT() \
105 : do { \
106 : write_to_tracer = false; \
107 : for (int i = 0; !write_to_tracer && i < (int) COMPONENTS_COUNT; i++) { \
108 : write_to_tracer = (log_level_t) ATOMIC_GET(&lvl_per_component[i]) > DEFAULT_LOG_LEVEL; \
109 : } \
110 : } while(0)
111 :
112 : static inline char *
113 288772 : get_timestamp(char *datetime, size_t dtsz)
114 : {
115 288772 : time_t now = time(NULL);
116 288955 : struct tm tmp;
117 288955 : (void) localtime_r(&now, &tmp);
118 289722 : strftime(datetime, dtsz, "%Y-%m-%d %H:%M:%S", &tmp);
119 :
120 289722 : return datetime;
121 : }
122 :
123 :
124 : // When BASIC adapter is active, all the log messages are getting printed to a file.
125 : // This function prepares a file in order to write the contents of the buffer when necessary.
126 : static gdk_return
127 697 : GDKtracer_init_trace_file(const char *dbpath, const char *dbtrace)
128 : {
129 697 : char *fn;
130 :
131 : /* we use malloc/free instead of GDKmalloc/GDKfree to avoid
132 : * possible recursion */
133 : #undef malloc
134 : #undef free
135 697 : if (dbtrace == NULL) {
136 697 : write_to_tracer = false;
137 697 : if (dbpath == NULL) {
138 344 : active_tracer = stderr;
139 344 : return GDK_SUCCEED;
140 : }
141 353 : size_t fnl = strlen(dbpath) + strlen(DIR_SEP_STR) + strlen(FILE_NAME) + 1;
142 353 : fn = malloc(fnl);
143 353 : if (fn == NULL) {
144 0 : GDK_TRACER_EXCEPTION("malloc failure\n");
145 0 : active_tracer = stderr;
146 0 : return GDK_FAIL;
147 : }
148 353 : if (strconcat_len(fn, fnl, dbpath, DIR_SEP_STR, FILE_NAME, NULL)
149 : >= fnl) {
150 : /* cannot happen */
151 0 : goto too_long;
152 : }
153 : } else {
154 0 : write_to_tracer = true;
155 0 : size_t fnl = strlen(dbtrace) + 1;
156 0 : fn = malloc(fnl);
157 0 : if (fn == NULL) {
158 0 : GDK_TRACER_EXCEPTION("malloc failure\n");
159 0 : active_tracer = stderr;
160 0 : return GDK_FAIL;
161 : }
162 0 : if (strcpy_len(fn, dbtrace, fnl)
163 : >= fnl) {
164 : /* cannot happen */
165 0 : goto too_long;
166 : }
167 : }
168 353 : free(file_name);
169 353 : file_name = fn;
170 :
171 353 : active_tracer = MT_fopen(file_name, "a");
172 :
173 353 : if (active_tracer == NULL) {
174 0 : GDK_TRACER_EXCEPTION2("Failed to open %s: %s\n", file_name,
175 0 : GDKstrerror(errno, (char[64]){0}, 64));
176 : /* uninitialize */
177 0 : free(file_name);
178 0 : file_name = NULL;
179 0 : active_tracer = stderr;
180 0 : return GDK_FAIL;
181 : }
182 :
183 : return GDK_SUCCEED;
184 :
185 0 : too_long:
186 0 : GDK_TRACER_EXCEPTION("path name for dbtrace file too long\n");
187 : /* uninitialize */
188 0 : free(fn);
189 0 : free(file_name);
190 0 : file_name = NULL;
191 0 : active_tracer = stderr;
192 0 : return GDK_FAIL;
193 : }
194 :
195 : static gdk_return
196 343 : _GDKtracer_init_basic_adptr(void)
197 : {
198 343 : return GDKtracer_init_trace_file(GDKgetenv("gdk_dbpath"),
199 : GDKgetenv("gdk_dbtrace"));
200 : }
201 :
202 : static void
203 350 : set_level_for_layer(int layer, log_level_t level)
204 : {
205 350 : const char *tok = NULL;
206 :
207 : // make sure we initialize before changing the component level
208 350 : MT_lock_set(&GDKtracer_lock);
209 350 : if (file_name == NULL) {
210 1 : _GDKtracer_init_basic_adptr();
211 : }
212 350 : MT_lock_unset(&GDKtracer_lock);
213 :
214 9450 : for (int i = 0; i < COMPONENTS_COUNT; i++) {
215 9100 : if (layer == MDB_ALL) {
216 9100 : ATOMIC_SET(&lvl_per_component[i], (ATOMIC_BASE_TYPE) level);
217 : } else {
218 0 : tok = component_str[i];
219 :
220 0 : switch (layer) {
221 0 : case SQL_ALL:
222 0 : if (strncmp(tok, "SQL_", 4) == 0)
223 0 : ATOMIC_SET(&lvl_per_component[i], (ATOMIC_BASE_TYPE) level);
224 : break;
225 0 : case MAL_ALL:
226 0 : if (strncmp(tok, "MAL_", 4) == 0)
227 0 : ATOMIC_SET(&lvl_per_component[i], (ATOMIC_BASE_TYPE) level);
228 : break;
229 0 : case GDK_ALL:
230 0 : if (strncmp(tok, "GDK", 3) == 0)
231 0 : ATOMIC_SET(&lvl_per_component[i], (ATOMIC_BASE_TYPE) level);
232 : break;
233 : default:
234 : break;
235 : }
236 : }
237 : }
238 350 : MT_lock_set(&GDKtracer_lock);
239 9450 : GDK_TRACER_RESET_OUTPUT();
240 350 : MT_lock_unset(&GDKtracer_lock);
241 350 : }
242 :
243 : static inline adapter_t
244 1 : find_adapter(const char *adptr)
245 : {
246 1 : if (adptr == NULL)
247 : return ADAPTERS_COUNT;
248 :
249 3 : for (int i = 0; i < (int) ADAPTERS_COUNT; i++) {
250 3 : if (strcasecmp(adapter_str[i], adptr) == 0) {
251 1 : return (adapter_t) i;
252 : }
253 : }
254 : return ADAPTERS_COUNT;
255 : }
256 :
257 : static inline log_level_t
258 464 : find_level(const char *lvl)
259 : {
260 464 : if (lvl == NULL)
261 : return LOG_LEVELS_COUNT;
262 :
263 2204 : for (int i = 0; i < (int) LOG_LEVELS_COUNT; i++) {
264 2204 : if (strcasecmp(level_str[i] + 2, lvl) == 0) {
265 464 : return (log_level_t) i;
266 : }
267 : }
268 : return LOG_LEVELS_COUNT;
269 : }
270 :
271 : static inline layer_t
272 0 : find_layer(const char *layer)
273 : {
274 0 : if (layer == NULL)
275 : return LAYERS_COUNT;
276 0 : for (int i = 0; i < (int) LAYERS_COUNT; i++) {
277 0 : if (strcasecmp(layer_str[i], layer) == 0) {
278 0 : return (layer_t) i;
279 : }
280 : }
281 : return LAYERS_COUNT;
282 : }
283 :
284 : static inline component_t
285 4628 : find_component(const char *comp)
286 : {
287 : /* special case for the (currently) three components that end in _ */
288 4628 : if (comp == NULL || *comp == 0 || comp[strlen(comp) - 1] == '_')
289 : return COMPONENTS_COUNT;
290 4628 : if (strcasecmp(comp, "io") == 0)
291 : comp = "io_";
292 4252 : else if (strcasecmp(comp, "bat") == 0)
293 : comp = "bat_";
294 3876 : else if (strcasecmp(comp, "check") == 0)
295 376 : comp = "check_";
296 :
297 33152 : for (int i = 0; i < (int) COMPONENTS_COUNT; i++) {
298 33152 : if (strcasecmp(component_str[i], comp) == 0) {
299 4628 : return (component_t) i;
300 : }
301 : }
302 : return COMPONENTS_COUNT;
303 : }
304 :
305 :
306 :
307 : /**
308 : *
309 : * API CALLS
310 : *
311 : */
312 : static volatile sig_atomic_t interrupted = 0;
313 :
314 : void
315 0 : GDKtracer_reinit_basic(int sig)
316 : {
317 0 : (void) sig;
318 0 : interrupted = 1;
319 0 : }
320 :
321 : static void
322 0 : reinit(void)
323 : {
324 : /* called locked */
325 :
326 0 : interrupted = 0;
327 :
328 : // GDKtracer needs to reopen the file only in
329 : // case the adapter is BASIC
330 0 : if ((adapter_t) ATOMIC_GET(&cur_adapter) != BASIC)
331 : return;
332 :
333 0 : if (active_tracer) {
334 0 : if (active_tracer != stderr)
335 0 : fclose(active_tracer);
336 : else
337 0 : fflush(active_tracer);
338 0 : active_tracer = NULL;
339 : }
340 0 : _GDKtracer_init_basic_adptr();
341 : }
342 :
343 :
344 : gdk_return
345 350 : GDKtracer_stop(void)
346 : {
347 350 : set_level_for_layer(MDB_ALL, DEFAULT_LOG_LEVEL);
348 350 : if (active_tracer) {
349 350 : if (active_tracer != stderr)
350 349 : fclose(active_tracer);
351 : else
352 1 : fflush(active_tracer);
353 350 : active_tracer = NULL;
354 : }
355 350 : return GDK_SUCCEED;
356 : }
357 :
358 : gdk_return
359 464 : GDKtracer_set_component_level(const char *comp, const char *lvl)
360 : {
361 464 : log_level_t level = find_level(lvl);
362 464 : component_t component = find_component(comp);
363 :
364 464 : if (level == LOG_LEVELS_COUNT) {
365 0 : GDKerror("unknown level\n");
366 0 : return GDK_FAIL;
367 : }
368 464 : if (component == COMPONENTS_COUNT) {
369 0 : GDKerror("unknown component\n");
370 0 : return GDK_FAIL;
371 : }
372 :
373 : // make sure we initialize before changing the component level
374 464 : MT_lock_set(&GDKtracer_lock);
375 464 : if (file_name == NULL) {
376 342 : _GDKtracer_init_basic_adptr();
377 : }
378 464 : write_to_tracer |= level > DEFAULT_LOG_LEVEL;
379 464 : MT_lock_unset(&GDKtracer_lock);
380 :
381 464 : ATOMIC_SET(&lvl_per_component[component], (ATOMIC_BASE_TYPE) level);
382 :
383 464 : return GDK_SUCCEED;
384 : }
385 :
386 : const char *
387 204 : GDKtracer_get_component_level(const char *comp)
388 : {
389 204 : component_t component = find_component(comp);
390 :
391 204 : if (component == COMPONENTS_COUNT) {
392 0 : GDKerror("unknown component\n");
393 0 : return NULL;
394 : }
395 204 : return level_str[ATOMIC_GET(&lvl_per_component[component])];
396 : }
397 :
398 :
399 : gdk_return
400 3960 : GDKtracer_reset_component_level(const char *comp)
401 : {
402 3960 : component_t component = find_component(comp);
403 :
404 3960 : if (component == COMPONENTS_COUNT) {
405 0 : GDKerror("unknown component\n");
406 0 : return GDK_FAIL;
407 : }
408 3960 : ATOMIC_SET(&lvl_per_component[component], (ATOMIC_BASE_TYPE) DEFAULT_LOG_LEVEL);
409 3960 : MT_lock_set(&GDKtracer_lock);
410 54348 : GDK_TRACER_RESET_OUTPUT();
411 3960 : MT_lock_unset(&GDKtracer_lock);
412 :
413 3960 : return GDK_SUCCEED;
414 : }
415 :
416 :
417 : gdk_return
418 0 : GDKtracer_set_layer_level(const char *layer, const char *lvl)
419 : {
420 0 : layer_t lyr = find_layer(layer);
421 0 : log_level_t level = find_level(lvl);
422 0 : if (level == LOG_LEVELS_COUNT) {
423 0 : GDKerror("unknown level\n");
424 0 : return GDK_FAIL;
425 : }
426 0 : if (lyr == LAYERS_COUNT) {
427 0 : GDKerror("unknown layer\n");
428 0 : return GDK_FAIL;
429 : }
430 :
431 0 : set_level_for_layer(lyr, level);
432 0 : return GDK_SUCCEED;
433 : }
434 :
435 :
436 : gdk_return
437 0 : GDKtracer_reset_layer_level(const char *layer)
438 : {
439 0 : layer_t lyr = find_layer(layer);
440 0 : if (lyr == LAYERS_COUNT) {
441 0 : GDKerror("unknown layer\n");
442 0 : return GDK_FAIL;
443 : }
444 :
445 0 : set_level_for_layer(lyr, DEFAULT_LOG_LEVEL);
446 0 : return GDK_SUCCEED;
447 : }
448 :
449 :
450 : gdk_return
451 0 : GDKtracer_set_flush_level(const char *lvl)
452 : {
453 0 : log_level_t level = find_level(lvl);
454 0 : if (level == LOG_LEVELS_COUNT) {
455 0 : GDKerror("unknown level\n");
456 0 : return GDK_FAIL;
457 : }
458 :
459 0 : cur_flush_level = level;
460 0 : return GDK_SUCCEED;
461 : }
462 :
463 :
464 : gdk_return
465 0 : GDKtracer_reset_flush_level(void)
466 : {
467 0 : cur_flush_level = DEFAULT_FLUSH_LEVEL;
468 0 : return GDK_SUCCEED;
469 : }
470 :
471 :
472 : gdk_return
473 1 : GDKtracer_set_adapter(const char *adapter)
474 : {
475 1 : adapter_t adptr = find_adapter(adapter);
476 1 : if (adptr == ADAPTERS_COUNT) {
477 0 : GDKerror("unknown adapter\n");
478 0 : return GDK_FAIL;
479 : }
480 :
481 : // Here when switching between adapters we can open/close the file
482 : // But it is not so important to keep it open in case the adapter switches
483 : // From BASIC to other => close the file
484 : // From other to BASIC => open the file
485 :
486 1 : ATOMIC_SET(&cur_adapter, adptr);
487 :
488 1 : return GDK_SUCCEED;
489 : }
490 :
491 :
492 : gdk_return
493 0 : GDKtracer_reset_adapter(void)
494 : {
495 0 : ATOMIC_SET(&cur_adapter, DEFAULT_ADAPTER);
496 0 : return GDK_SUCCEED;
497 : }
498 :
499 : static bool add_ts; /* add timestamp to error message to stderr */
500 :
501 : gdk_return
502 354 : GDKtracer_init(const char *dbpath, const char *dbtrace)
503 : {
504 354 : MT_lock_set(&GDKtracer_lock);
505 : #ifdef _MSC_VER
506 : add_ts = GetFileType(GetStdHandle(STD_ERROR_HANDLE)) != FILE_TYPE_PIPE;
507 : #else
508 354 : add_ts = isatty(2) || lseek(2, 0, SEEK_CUR) != (off_t) -1 || errno != ESPIPE;
509 : #endif
510 354 : gdk_return rc = GDKtracer_init_trace_file(dbpath, dbtrace);
511 354 : MT_lock_unset(&GDKtracer_lock);
512 354 : return rc;
513 : }
514 :
515 : gdk_return
516 0 : GDKtracer_set_tracefile(const char *tracefile)
517 : {
518 0 : return GDKtracer_init(NULL, tracefile);
519 : }
520 :
521 : void
522 288809 : GDKtracer_log(const char *file, const char *func, int lineno,
523 : log_level_t level, component_t comp,
524 : const char *syserr,
525 : const char *fmt, ...)
526 : {
527 288809 : int bytes_written;
528 288809 : char buffer[512]; /* should be plenty big enough for a message */
529 288809 : va_list va;
530 288809 : char ts[TS_SIZE];
531 288809 : char *msg = NULL;
532 288809 : bool isexit;
533 288809 : static char file_prefix[] = __FILE__;
534 288809 : static size_t prefix_length = (size_t) -1;
535 :
536 288809 : if (prefix_length == (size_t) -1) {
537 : /* first time, calculate prefix of file name */
538 182 : msg = strstr(file_prefix, "gdk" DIR_SEP_STR "gdk_tracer.c");
539 182 : if (msg == NULL)
540 0 : prefix_length = 0;
541 : else
542 182 : prefix_length = (size_t) (msg - file_prefix);
543 : }
544 288809 : if (prefix_length != 0 &&
545 289127 : strncmp(file, file_prefix, prefix_length) == 0)
546 288620 : file += prefix_length;
547 :
548 288809 : va_start(va, fmt);
549 288809 : int pad = (int) strlen(file);
550 288809 : pad = (pad > 40) ? 0 : 40 - pad;
551 288809 : bytes_written = snprintf(buffer, sizeof(buffer),
552 : "%s " /* timestamp */
553 : "%10s " /* level */
554 : "%-8s " /* component */
555 : "%-20s " /* thread name */
556 : "%s:%-5d %*s" /* file, lineno, pad */
557 : "%-20s ", /* function */
558 : get_timestamp(ts, sizeof(ts)),
559 : level_str[level],
560 : component_str[comp],
561 : MT_thread_getname(),
562 : file, lineno, pad, "",
563 : func);
564 289271 : if (bytes_written > 0 && bytes_written < (int) sizeof(buffer)) {
565 289465 : msg = buffer + bytes_written;
566 : } else {
567 : /* exceedingly unlikely that we ever come here */
568 : msg = buffer;
569 : bytes_written = 0;
570 : }
571 289271 : bytes_written = vsnprintf(msg,
572 : sizeof(buffer) - bytes_written,
573 : fmt, va);
574 289271 : isexit = strstr(msg, EXITING_MSG) != NULL;
575 289271 : va_end(va);
576 289271 : if (bytes_written < 0) {
577 0 : if ((adapter_t) ATOMIC_GET(&cur_adapter) != MBEDDED)
578 0 : GDK_TRACER_EXCEPTION("Failed to write logs\n");
579 3929 : return;
580 : }
581 289271 : char *p;
582 289271 : if ((p = strchr(buffer, '\n')) != NULL)
583 153050 : *p = '\0';
584 :
585 289271 : if (comp == GDK && level <= M_ERROR) {
586 : /* append message to GDKerrbuf (if set) */
587 1600 : char *buf = GDKerrbuf;
588 1600 : if (buf) {
589 1598 : size_t n = strlen(buf);
590 4794 : snprintf(buf + n, GDKMAXERRLEN - n,
591 : "%s%s: %s%s%s\n",
592 : isexit ? "" : GDKERROR,
593 : func, msg,
594 : syserr ? ": " : "",
595 : syserr ? syserr : "");
596 : }
597 : }
598 :
599 : /* don't write to file in embedded case, but set the GDK error buffer */
600 289271 : if ((adapter_t) ATOMIC_GET(&cur_adapter) == MBEDDED)
601 : return;
602 :
603 289097 : MT_lock_set(&GDKtracer_lock);
604 289726 : if (interrupted)
605 0 : reinit();
606 :
607 289726 : if (level <= M_WARNING || (ATOMIC_GET(&GDKdebug) & TESTINGMASK)) {
608 580453 : fprintf(level <= M_ERROR && !isexit ? stderr : stdout,
609 : "#%s%s%s: %s: %s: %s%s%s\n",
610 : add_ts ? ts : "",
611 289544 : add_ts ? ": " : "",
612 289544 : MT_thread_getname(), func, level_str[level] + 2,
613 : msg, syserr ? ": " : "",
614 : syserr ? syserr : "");
615 289544 : if (active_tracer == NULL || active_tracer == stderr || !write_to_tracer) {
616 3755 : MT_lock_unset(&GDKtracer_lock);
617 3755 : return;
618 : }
619 : }
620 285971 : if (active_tracer == NULL) {
621 0 : MT_lock_unset(&GDKtracer_lock);
622 0 : return;
623 : }
624 285971 : if (syserr)
625 0 : fprintf(active_tracer, "%s: %s\n", buffer, syserr);
626 : else
627 285971 : fprintf(active_tracer, "%s\n", buffer);
628 :
629 : // Flush the current buffer in case the event is
630 : // important depending on the flush-level
631 : // Always flush CRITICAL and ERROR messages - prevent cases
632 : // like mserver5 refusing to start due to allocated port
633 : // and the error is never reported to the user because it
634 : // is still in the buffer which it never gets flushed.
635 285971 : if (level == cur_flush_level || level <= M_ERROR)
636 41168 : fflush(active_tracer);
637 285971 : MT_lock_unset(&GDKtracer_lock);
638 : }
639 :
640 :
641 : gdk_return
642 0 : GDKtracer_flush_buffer(void)
643 : {
644 0 : if (active_tracer)
645 0 : fflush(active_tracer);
646 0 : return GDK_SUCCEED;
647 : }
648 :
649 :
650 : gdk_return
651 0 : GDKtracer_fill_comp_info(BAT *id, BAT *component, BAT *log_level)
652 : {
653 0 : for (int i = 0; i < COMPONENTS_COUNT; i++) {
654 0 : if (BUNappend(id, &i, false) != GDK_SUCCEED)
655 0 : return GDK_FAIL;
656 :
657 0 : if (BUNappend(component, component_str[i], false) != GDK_SUCCEED)
658 : return GDK_FAIL;
659 :
660 0 : if (BUNappend(log_level, level_str[ATOMIC_GET(&lvl_per_component[i])], false) != GDK_SUCCEED)
661 : return GDK_FAIL;
662 : }
663 :
664 0 : return GDK_SUCCEED;
665 : }
|