LCOV - code coverage report
Current view: top level - gdk - gdk_tracer.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 145 261 55.6 %
Date: 2025-03-25 21:27:32 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, 2025 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 TRC_NAME(BASIC)
      19             : #define DEFAULT_LOG_LEVEL TRC_NAME(M_ERROR)
      20             : #define DEFAULT_FLUSH_LEVEL TRC_NAME(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) TRC_NAME(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      333193 : get_timestamp(char *datetime, size_t dtsz)
     114             : {
     115      333193 :         time_t now = time(NULL);
     116      333347 :         struct tm tmp;
     117      333347 :         (void) localtime_r(&now, &tmp);
     118      333944 :         strftime(datetime, dtsz, "%Y-%m-%d %H:%M:%S", &tmp);
     119             : 
     120      333944 :         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         709 : GDKtracer_init_trace_file(const char *dbpath, const char *dbtrace)
     128             : {
     129         709 :         char *fn;
     130             : 
     131             :         /* we use malloc/free instead of GDKmalloc/GDKfree to avoid
     132             :          * possible recursion */
     133             : #undef malloc
     134             : #undef free
     135         709 :         if (dbtrace == NULL) {
     136         709 :                 write_to_tracer = false;
     137         709 :                 if (dbpath == NULL) {
     138         350 :                         active_tracer = stderr;
     139         350 :                         return GDK_SUCCEED;
     140             :                 }
     141         359 :                 size_t fnl = strlen(dbpath) + strlen(DIR_SEP_STR) + strlen(FILE_NAME) + 1;
     142         359 :                 fn = malloc(fnl);
     143         359 :                 if (fn == NULL) {
     144           0 :                         GDK_TRACER_EXCEPTION("malloc failure\n");
     145           0 :                         active_tracer = stderr;
     146           0 :                         return GDK_FAIL;
     147             :                 }
     148         359 :                 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         359 :         free(file_name);
     169         359 :         file_name = fn;
     170             : 
     171         359 :         active_tracer = MT_fopen(file_name, "a");
     172             : 
     173         359 :         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         349 : _GDKtracer_init_basic_adptr(void)
     197             : {
     198         349 :         return GDKtracer_init_trace_file(GDKgetenv("gdk_dbpath"),
     199             :                                          GDKgetenv("gdk_dbtrace"));
     200             : }
     201             : 
     202             : static void
     203         356 : set_level_for_layer(int layer, log_level_t level)
     204             : {
     205         356 :         const char *tok = NULL;
     206             : 
     207             :         // make sure we initialize before changing the component level
     208         356 :         MT_lock_set(&GDKtracer_lock);
     209         356 :         if (file_name == NULL) {
     210           1 :                 _GDKtracer_init_basic_adptr();
     211             :         }
     212         356 :         MT_lock_unset(&GDKtracer_lock);
     213             : 
     214       10680 :         for (int i = 0; i < TRC_NAME(COMPONENTS_COUNT); i++) {
     215       10324 :                 if (layer == TRC_NAME(MDB_ALL)) {
     216       10324 :                         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 TRC_NAME(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 TRC_NAME(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 TRC_NAME(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         356 :         MT_lock_set(&GDKtracer_lock);
     239       10680 :         GDK_TRACER_RESET_OUTPUT();
     240         356 :         MT_lock_unset(&GDKtracer_lock);
     241         356 : }
     242             : 
     243             : static inline adapter_t
     244           1 : find_adapter(const char *adptr)
     245             : {
     246           1 :         if (adptr == NULL)
     247             :                 return TRC_NAME(ADAPTERS_COUNT);
     248             : 
     249           3 :         for (int i = 0; i < (int) TRC_NAME(ADAPTERS_COUNT); i++) {
     250           3 :                 if (strcasecmp(adapter_str[i], adptr) == 0) {
     251           1 :                         return (adapter_t) i;
     252             :                 }
     253             :         }
     254             :         return TRC_NAME(ADAPTERS_COUNT);
     255             : }
     256             : 
     257             : static inline log_level_t
     258         473 : find_level(const char *lvl)
     259             : {
     260         473 :         if (lvl == NULL)
     261             :                 return TRC_NAME(LOG_LEVELS_COUNT);
     262             : 
     263        2246 :         for (int i = 0; i < (int) TRC_NAME(LOG_LEVELS_COUNT); i++) {
     264        2246 :                 if (strcasecmp(level_str[i] + 2, lvl) == 0) {
     265         473 :                         return (log_level_t) i;
     266             :                 }
     267             :         }
     268             :         return TRC_NAME(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 TRC_NAME(LAYERS_COUNT);
     276           0 :         for (int i = 0; i < (int) TRC_NAME(LAYERS_COUNT); i++) {
     277           0 :                 if (strcasecmp(layer_str[i], layer) == 0) {
     278           0 :                         return (layer_t) i;
     279             :                 }
     280             :         }
     281             :         return TRC_NAME(LAYERS_COUNT);
     282             : }
     283             : 
     284             : static inline component_t
     285        5467 : find_component(const char *comp)
     286             : {
     287             :         /* special case for the (currently) three components that end in _ */
     288        5467 :         if (comp == NULL || *comp == 0 || comp[strlen(comp) - 1] == '_')
     289             :                 return TRC_NAME(COMPONENTS_COUNT);
     290             : 
     291       49604 :         for (int i = 0; i < (int) TRC_NAME(COMPONENTS_COUNT); i++) {
     292       49604 :                 if (strcasecmp(component_str[i], comp) == 0) {
     293        5467 :                         return (component_t) i;
     294             :                 }
     295             :         }
     296             :         return TRC_NAME(COMPONENTS_COUNT);
     297             : }
     298             : 
     299             : 
     300             : 
     301             : /**
     302             :  *
     303             :  * API CALLS
     304             :  *
     305             :  */
     306             : static volatile sig_atomic_t interrupted = 0;
     307             : 
     308             : void
     309           0 : GDKtracer_reinit_basic(int sig)
     310             : {
     311           0 :         (void) sig;
     312           0 :         interrupted = 1;
     313           0 : }
     314             : 
     315             : static void
     316           0 : reinit(void)
     317             : {
     318             :         /* called locked */
     319             : 
     320           0 :         interrupted = 0;
     321             : 
     322             :         // GDKtracer needs to reopen the file only in
     323             :         // case the adapter is BASIC
     324           0 :         if ((adapter_t) ATOMIC_GET(&cur_adapter) != TRC_NAME(BASIC))
     325             :                 return;
     326             : 
     327           0 :         if (active_tracer) {
     328           0 :                 if (active_tracer != stderr)
     329           0 :                         fclose(active_tracer);
     330             :                 else
     331           0 :                         fflush(active_tracer);
     332           0 :                 active_tracer = NULL;
     333             :         }
     334           0 :         _GDKtracer_init_basic_adptr();
     335             : }
     336             : 
     337             : 
     338             : gdk_return
     339         356 : GDKtracer_stop(void)
     340             : {
     341         356 :         set_level_for_layer(TRC_NAME(MDB_ALL), DEFAULT_LOG_LEVEL);
     342         356 :         if (active_tracer) {
     343         356 :                 if (active_tracer != stderr)
     344         355 :                         fclose(active_tracer);
     345             :                 else
     346           1 :                         fflush(active_tracer);
     347         356 :                 active_tracer = NULL;
     348             :         }
     349         356 :         return GDK_SUCCEED;
     350             : }
     351             : 
     352             : gdk_return
     353         473 : GDKtracer_set_component_level(const char *comp, const char *lvl)
     354             : {
     355         473 :         log_level_t level = find_level(lvl);
     356         473 :         component_t component = find_component(comp);
     357             : 
     358         473 :         if (level == TRC_NAME(LOG_LEVELS_COUNT)) {
     359           0 :                 GDKerror("unknown level\n");
     360           0 :                 return GDK_FAIL;
     361             :         }
     362         473 :         if (component == TRC_NAME(COMPONENTS_COUNT)) {
     363           0 :                 GDKerror("unknown component\n");
     364           0 :                 return GDK_FAIL;
     365             :         }
     366             : 
     367             :         // make sure we initialize before changing the component level
     368         473 :         MT_lock_set(&GDKtracer_lock);
     369         473 :         if (file_name == NULL) {
     370         348 :                 _GDKtracer_init_basic_adptr();
     371             :         }
     372         473 :         write_to_tracer |= level > DEFAULT_LOG_LEVEL;
     373         473 :         MT_lock_unset(&GDKtracer_lock);
     374             : 
     375         473 :         ATOMIC_SET(&lvl_per_component[component], (ATOMIC_BASE_TYPE) level);
     376             : 
     377         473 :         return GDK_SUCCEED;
     378             : }
     379             : 
     380             : const char *
     381         238 : GDKtracer_get_component_level(const char *comp)
     382             : {
     383         238 :         component_t component = find_component(comp);
     384             : 
     385         238 :         if (component == TRC_NAME(COMPONENTS_COUNT)) {
     386           0 :                 GDKerror("unknown component\n");
     387           0 :                 return NULL;
     388             :         }
     389         238 :         return level_str[ATOMIC_GET(&lvl_per_component[component])];
     390             : }
     391             : 
     392             : 
     393             : gdk_return
     394        4756 : GDKtracer_reset_component_level(const char *comp)
     395             : {
     396        4756 :         component_t component = find_component(comp);
     397             : 
     398        4756 :         if (component == TRC_NAME(COMPONENTS_COUNT)) {
     399           0 :                 GDKerror("unknown component\n");
     400           0 :                 return GDK_FAIL;
     401             :         }
     402        4756 :         ATOMIC_SET(&lvl_per_component[component], (ATOMIC_BASE_TYPE) DEFAULT_LOG_LEVEL);
     403        4756 :         MT_lock_set(&GDKtracer_lock);
     404       64426 :         GDK_TRACER_RESET_OUTPUT();
     405        4756 :         MT_lock_unset(&GDKtracer_lock);
     406             : 
     407        4756 :         return GDK_SUCCEED;
     408             : }
     409             : 
     410             : 
     411             : gdk_return
     412           0 : GDKtracer_set_layer_level(const char *layer, const char *lvl)
     413             : {
     414           0 :         layer_t lyr = find_layer(layer);
     415           0 :         log_level_t level = find_level(lvl);
     416           0 :         if (level == TRC_NAME(LOG_LEVELS_COUNT)) {
     417           0 :                 GDKerror("unknown level\n");
     418           0 :                 return GDK_FAIL;
     419             :         }
     420           0 :         if (lyr == TRC_NAME(LAYERS_COUNT)) {
     421           0 :                 GDKerror("unknown layer\n");
     422           0 :                 return GDK_FAIL;
     423             :         }
     424             : 
     425           0 :         set_level_for_layer(lyr, level);
     426           0 :         return GDK_SUCCEED;
     427             : }
     428             : 
     429             : 
     430             : gdk_return
     431           0 : GDKtracer_reset_layer_level(const char *layer)
     432             : {
     433           0 :         layer_t lyr = find_layer(layer);
     434           0 :         if (lyr == TRC_NAME(LAYERS_COUNT)) {
     435           0 :                 GDKerror("unknown layer\n");
     436           0 :                 return GDK_FAIL;
     437             :         }
     438             : 
     439           0 :         set_level_for_layer(lyr, DEFAULT_LOG_LEVEL);
     440           0 :         return GDK_SUCCEED;
     441             : }
     442             : 
     443             : 
     444             : gdk_return
     445           0 : GDKtracer_set_flush_level(const char *lvl)
     446             : {
     447           0 :         log_level_t level = find_level(lvl);
     448           0 :         if (level == TRC_NAME(LOG_LEVELS_COUNT)) {
     449           0 :                 GDKerror("unknown level\n");
     450           0 :                 return GDK_FAIL;
     451             :         }
     452             : 
     453           0 :         cur_flush_level = level;
     454           0 :         return GDK_SUCCEED;
     455             : }
     456             : 
     457             : 
     458             : gdk_return
     459           0 : GDKtracer_reset_flush_level(void)
     460             : {
     461           0 :         cur_flush_level = DEFAULT_FLUSH_LEVEL;
     462           0 :         return GDK_SUCCEED;
     463             : }
     464             : 
     465             : 
     466             : gdk_return
     467           1 : GDKtracer_set_adapter(const char *adapter)
     468             : {
     469           1 :         adapter_t adptr = find_adapter(adapter);
     470           1 :         if (adptr == TRC_NAME(ADAPTERS_COUNT)) {
     471           0 :                 GDKerror("unknown adapter\n");
     472           0 :                 return GDK_FAIL;
     473             :         }
     474             : 
     475             :         // Here when switching between adapters we can open/close the file
     476             :         // But it is not so important to keep it open in case the adapter switches
     477             :         // From BASIC to other => close the file
     478             :         // From other to BASIC => open the file
     479             : 
     480           1 :         ATOMIC_SET(&cur_adapter, adptr);
     481             : 
     482           1 :         return GDK_SUCCEED;
     483             : }
     484             : 
     485             : 
     486             : gdk_return
     487           0 : GDKtracer_reset_adapter(void)
     488             : {
     489           0 :         ATOMIC_SET(&cur_adapter, DEFAULT_ADAPTER);
     490           0 :         return GDK_SUCCEED;
     491             : }
     492             : 
     493             : static bool add_ts;             /* add timestamp to error message to stderr */
     494             : 
     495             : gdk_return
     496         360 : GDKtracer_init(const char *dbpath, const char *dbtrace)
     497             : {
     498         360 :         MT_lock_set(&GDKtracer_lock);
     499             : #ifdef _MSC_VER
     500             :         add_ts = GetFileType(GetStdHandle(STD_ERROR_HANDLE)) != FILE_TYPE_PIPE;
     501             : #else
     502         360 :         add_ts = isatty(2) || lseek(2, 0, SEEK_CUR) != (off_t) -1 || errno != ESPIPE;
     503             : #endif
     504         360 :         gdk_return rc = GDKtracer_init_trace_file(dbpath, dbtrace);
     505         360 :         MT_lock_unset(&GDKtracer_lock);
     506         360 :         return rc;
     507             : }
     508             : 
     509             : gdk_return
     510           0 : GDKtracer_set_tracefile(const char *tracefile)
     511             : {
     512           0 :         return GDKtracer_init(NULL, tracefile);
     513             : }
     514             : 
     515             : void
     516      332866 : GDKtracer_log(const char *file, const char *func, int lineno,
     517             :               log_level_t level, component_t comp,
     518             :               const char *syserr,
     519             :               const char *fmt, ...)
     520             : {
     521      332866 :         int bytes_written;
     522      332866 :         char buffer[512];       /* should be plenty big enough for a message */
     523      332866 :         va_list va;
     524      332866 :         char ts[TS_SIZE];
     525      332866 :         char *msg = NULL;
     526      332866 :         bool isexit;
     527      332866 :         static char file_prefix[] = __FILE__;
     528      332866 :         static size_t prefix_length = (size_t) -1;
     529             : 
     530      332866 :         if (prefix_length == (size_t) -1) {
     531             :                 /* first time, calculate prefix of file name */
     532         194 :                 msg = strstr(file_prefix, "gdk" DIR_SEP_STR "gdk_tracer.c");
     533         194 :                 if (msg == NULL)
     534           0 :                         prefix_length = 0;
     535             :                 else
     536         194 :                         prefix_length = (size_t) (msg - file_prefix);
     537             :         }
     538      332866 :         if (prefix_length != 0 &&
     539      333223 :             strncmp(file, file_prefix, prefix_length) == 0)
     540      333109 :                 file += prefix_length;
     541             : 
     542      332866 :         va_start(va, fmt);
     543      332866 :         int pad = (int) strlen(file);
     544      332866 :         pad = (pad > 40) ? 0 : 40 - pad;
     545      332866 :         bytes_written = snprintf(buffer, sizeof(buffer),
     546             :                                  "%s "                /* timestamp */
     547             :                                  "%10s "      /* level */
     548             :                                  "%-8s "      /* component */
     549             :                                  "%-20s "     /* thread name */
     550             :                                  "%s:%-5d %*s"        /* file, lineno, pad */
     551             :                                  "%-20s ",    /* function */
     552             :                                  get_timestamp(ts, sizeof(ts)),
     553             :                                  level_str[level],
     554             :                                  component_str[comp],
     555             :                                  MT_thread_getname(),
     556             :                                  file, lineno, pad, "",
     557             :                                  func);
     558      333342 :         if (bytes_written > 0 && bytes_written < (int) sizeof(buffer)) {
     559      333580 :                 msg = buffer + bytes_written;
     560             :         } else {
     561             :                 /* exceedingly unlikely that we ever come here */
     562             :                 msg = buffer;
     563             :                 bytes_written = 0;
     564             :         }
     565      333342 :         bytes_written = vsnprintf(msg,
     566             :                                   sizeof(buffer) - bytes_written,
     567             :                                   fmt, va);
     568      333342 :         isexit = strstr(msg, EXITING_MSG) != NULL;
     569      333342 :         va_end(va);
     570      333342 :         if (bytes_written < 0) {
     571           0 :                 if ((adapter_t) ATOMIC_GET(&cur_adapter) != TRC_NAME(MBEDDED))
     572           0 :                         GDK_TRACER_EXCEPTION("Failed to write logs\n");
     573       12493 :                 return;
     574             :         }
     575      333342 :         char *p;
     576      333342 :         if ((p = strchr(buffer, '\n')) != NULL)
     577      197321 :                 *p = '\0';
     578             : 
     579      333342 :         if (level <= TRC_NAME(M_ERROR) && (comp == TRC_NAME(GDK) || comp == TRC_NAME(GEOM))) {
     580             :                 /* append message to GDKerrbuf (if set) */
     581        1601 :                 char *buf = GDKerrbuf;
     582        1601 :                 if (buf) {
     583        1599 :                         size_t n = strlen(buf);
     584        4797 :                         snprintf(buf + n, GDKMAXERRLEN - n,
     585             :                                  "%s%s: %s%s%s\n",
     586             :                                  isexit ? "" : GDKERROR,
     587             :                                  func, msg,
     588             :                                  syserr ? ": " : "",
     589             :                                  syserr ? syserr : "");
     590             :                 }
     591             :         }
     592             : 
     593             :         /* don't write to file in embedded case, but set the GDK error buffer */
     594      333342 :         if ((adapter_t) ATOMIC_GET(&cur_adapter) == TRC_NAME(MBEDDED))
     595             :                 return;
     596             : 
     597      333146 :         MT_lock_set(&GDKtracer_lock);
     598      333951 :         if (interrupted)
     599           0 :                 reinit();
     600             : 
     601      333951 :         if (level <= TRC_NAME(M_WARNING) || (ATOMIC_GET(&GDKdebug) & TESTINGMASK)) {
     602      677418 :                 fprintf(level <= TRC_NAME(M_ERROR) && !isexit ? stderr : stdout,
     603             :                         "#%s%s%s: %s: %s: %s%s%s\n",
     604             :                         add_ts ? ts : "",
     605      333756 :                         add_ts ? ": " : "",
     606      333756 :                         MT_thread_getname(), func, level_str[level] + 2,
     607             :                         msg, syserr ? ": " : "",
     608             :                         syserr ? syserr : "");
     609      333756 :                 if (active_tracer == NULL || active_tracer == stderr || !write_to_tracer) {
     610       12297 :                         MT_lock_unset(&GDKtracer_lock);
     611       12297 :                         return;
     612             :                 }
     613             :         }
     614      321654 :         if (active_tracer == NULL) {
     615           0 :                 MT_lock_unset(&GDKtracer_lock);
     616           0 :                 return;
     617             :         }
     618      321654 :         if (syserr)
     619           0 :                 fprintf(active_tracer, "%s: %s\n", buffer, syserr);
     620             :         else
     621      321654 :                 fprintf(active_tracer, "%s\n", buffer);
     622             : 
     623             :         // Flush the current buffer in case the event is
     624             :         // important depending on the flush-level
     625             :         // Always flush CRITICAL and ERROR messages - prevent cases
     626             :         // like mserver5 refusing to start due to allocated port
     627             :         // and the error is never reported to the user because it
     628             :         // is still in the buffer which it never gets flushed.
     629      321654 :         if (level == cur_flush_level || level <= TRC_NAME(M_ERROR))
     630       41171 :                 fflush(active_tracer);
     631      321654 :         MT_lock_unset(&GDKtracer_lock);
     632             : }
     633             : 
     634             : 
     635             : gdk_return
     636           0 : GDKtracer_flush_buffer(void)
     637             : {
     638           0 :         if (active_tracer)
     639           0 :                 fflush(active_tracer);
     640           0 :         return GDK_SUCCEED;
     641             : }
     642             : 
     643             : 
     644             : gdk_return
     645           0 : GDKtracer_fill_comp_info(BAT *id, BAT *component, BAT *log_level)
     646             : {
     647           0 :         for (int i = 0; i < TRC_NAME(COMPONENTS_COUNT); i++) {
     648           0 :                 if (BUNappend(id, &i, false) != GDK_SUCCEED)
     649           0 :                         return GDK_FAIL;
     650             : 
     651           0 :                 if (BUNappend(component, component_str[i], false) != GDK_SUCCEED)
     652             :                         return GDK_FAIL;
     653             : 
     654           0 :                 if (BUNappend(log_level, level_str[ATOMIC_GET(&lvl_per_component[i])], false) != GDK_SUCCEED)
     655             :                         return GDK_FAIL;
     656             :         }
     657             : 
     658           0 :         return GDK_SUCCEED;
     659             : }

Generated by: LCOV version 1.14