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

Generated by: LCOV version 1.14