LCOV - code coverage report
Current view: top level - gdk - gdk_tracer.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 149 265 56.2 %
Date: 2024-12-19 23:10:26 Functions: 14 25 56.0 %

          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      288835 : get_timestamp(char *datetime, size_t dtsz)
     114             : {
     115      288835 :         time_t now = time(NULL);
     116      288968 :         struct tm tmp;
     117      288968 :         (void) localtime_r(&now, &tmp);
     118      289657 :         strftime(datetime, dtsz, "%Y-%m-%d %H:%M:%S", &tmp);
     119             : 
     120      289657 :         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      288662 : 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      288662 :         int bytes_written;
     528      288662 :         char buffer[512];       /* should be plenty big enough for a message */
     529      288662 :         va_list va;
     530      288662 :         char ts[TS_SIZE];
     531      288662 :         char *msg = NULL;
     532      288662 :         bool isexit;
     533      288662 :         static char file_prefix[] = __FILE__;
     534      288662 :         static size_t prefix_length = (size_t) -1;
     535             : 
     536      288662 :         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      288662 :         if (prefix_length != 0 &&
     545      288995 :             strncmp(file, file_prefix, prefix_length) == 0)
     546      288658 :                 file += prefix_length;
     547             : 
     548      288662 :         va_start(va, fmt);
     549      288662 :         int pad = (int) strlen(file);
     550      288662 :         pad = (pad > 40) ? 0 : 40 - pad;
     551      288662 :         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      289185 :         if (bytes_written > 0 && bytes_written < (int) sizeof(buffer)) {
     565      289431 :                 msg = buffer + bytes_written;
     566             :         } else {
     567             :                 /* exceedingly unlikely that we ever come here */
     568             :                 msg = buffer;
     569             :                 bytes_written = 0;
     570             :         }
     571      289185 :         bytes_written = vsnprintf(msg,
     572             :                                   sizeof(buffer) - bytes_written,
     573             :                                   fmt, va);
     574      289185 :         isexit = strstr(msg, EXITING_MSG) != NULL;
     575      289185 :         va_end(va);
     576      289185 :         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        3931 :                 return;
     580             :         }
     581      289185 :         char *p;
     582      289185 :         if ((p = strchr(buffer, '\n')) != NULL)
     583      152990 :                 *p = '\0';
     584             : 
     585      289185 :         if (comp == GDK && level <= M_ERROR) {
     586             :                 /* append message to GDKerrbuf (if set) */
     587        1583 :                 char *buf = GDKerrbuf;
     588        1583 :                 if (buf) {
     589        1581 :                         size_t n = strlen(buf);
     590        4743 :                         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      289185 :         if ((adapter_t) ATOMIC_GET(&cur_adapter) == MBEDDED)
     601             :                 return;
     602             : 
     603      289009 :         MT_lock_set(&GDKtracer_lock);
     604      289667 :         if (interrupted)
     605           0 :                 reinit();
     606             : 
     607      289667 :         if (level <= M_WARNING || (ATOMIC_GET(&GDKdebug) & TESTINGMASK)) {
     608      580335 :                 fprintf(level <= M_ERROR && !isexit ? stderr : stdout,
     609             :                         "#%s%s%s: %s: %s: %s%s%s\n",
     610             :                         add_ts ? ts : "",
     611      289485 :                         add_ts ? ": " : "",
     612      289485 :                         MT_thread_getname(), func, level_str[level] + 2,
     613             :                         msg, syserr ? ": " : "",
     614             :                         syserr ? syserr : "");
     615      289485 :                 if (active_tracer == NULL || active_tracer == stderr || !write_to_tracer) {
     616        3755 :                         MT_lock_unset(&GDKtracer_lock);
     617        3755 :                         return;
     618             :                 }
     619             :         }
     620      285912 :         if (active_tracer == NULL) {
     621           0 :                 MT_lock_unset(&GDKtracer_lock);
     622           0 :                 return;
     623             :         }
     624      285912 :         if (syserr)
     625           0 :                 fprintf(active_tracer, "%s: %s\n", buffer, syserr);
     626             :         else
     627      285912 :                 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      285912 :         if (level == cur_flush_level || level <= M_ERROR)
     636       41066 :                 fflush(active_tracer);
     637      285912 :         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             : }

Generated by: LCOV version 1.14