Add lock/unlock for YAZ log writes YAZ-843
[yaz-moved-to-github.git] / src / log.c
index 38ecac7..8bc5ad0 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -105,25 +105,20 @@ static unsigned int next_log_bit = YLOG_LAST_BIT<<1; /* first dynamic bit */
 
 static YAZ_MUTEX log_mutex = 0;
 
-static void yaz_log_lock(void)
+void yaz_log_lock(void)
 {
     yaz_mutex_enter(log_mutex);
 }
 
-static void yaz_log_unlock(void)
+void yaz_log_unlock(void)
 {
     yaz_mutex_leave(log_mutex);
 }
 
-static void internal_log_init(void)
+void yaz_log_init_globals(void)
 {
-    static int mutex_init_flag = 0; /* not yet initialized */
     char *env;
 
-    if (mutex_init_flag)
-        return;
-    mutex_init_flag = 1; /* here, 'cause nmem_mutex_create may call yaz_log */
-
     if (log_mutex == 0)
         yaz_mutex_create(&log_mutex);
 #if YAZ_POSIX_THREADS
@@ -134,7 +129,6 @@ static void internal_log_init(void)
         l_level = yaz_log_mask_str_x(env, l_level);
 }
 
-
 FILE *yaz_log_file(void)
 {
     FILE *f = 0;
@@ -158,7 +152,7 @@ void yaz_log_close(void)
 
 void yaz_log_init_file(const char *fname)
 {
-    internal_log_init();
+    yaz_init_globals();
 
     yaz_log_close();
     if (fname)
@@ -218,7 +212,7 @@ static void rotate_log(const char *cur_fname)
 
 void yaz_log_init_level(int level)
 {
-    internal_log_init();
+    yaz_init_globals();
     if ( (l_level & YLOG_FLUSH) != (level & YLOG_FLUSH) )
     {
         l_level = level;
@@ -271,7 +265,7 @@ void yaz_log_init_prefix2(const char *prefix)
 
 void yaz_log_init(int level, const char *prefix, const char *fname)
 {
-    internal_log_init();
+    yaz_init_globals();
     yaz_log_init_level(level);
     yaz_log_init_prefix(prefix);
     if (fname && *fname)
@@ -338,13 +332,14 @@ static void yaz_log_open_check(struct tm *tm, int force, const char *filemode)
 #ifdef WIN32
         yaz_log_close();
 #endif
-        new_file = fopen(cur_filename, filemode);
+        if (!strncmp(cur_filename, "fd=", 3))
+            new_file = fdopen(atoi(cur_filename + 3), filemode);
+        else
+            new_file = fopen(cur_filename, filemode);
         if (new_file)
         {
             yaz_log_close();
             yaz_log_info.log_file = new_file;
-            if (l_level & YLOG_FLUSH)
-                setvbuf(yaz_log_info.log_file, 0, _IONBF, 0);
         }
         else
         {
@@ -390,7 +385,8 @@ static void yaz_strftime(char *dst, size_t sz,
     strftime(dst, sz, fmt, tm);
 }
 
-static void yaz_log_to_file(int level, const char *log_message)
+static void yaz_log_to_file(int level, const char *fmt, va_list ap,
+                            const char *error_cp)
 {
     FILE *file;
     time_t ti = time(0);
@@ -400,8 +396,6 @@ static void yaz_log_to_file(int level, const char *log_message)
     struct tm *tm;
 #endif
 
-    internal_log_init();
-
     yaz_log_lock();
 #if HAVE_LOCALTIME_R
     localtime_r(&ti, tm);
@@ -454,9 +448,12 @@ static void yaz_log_to_file(int level, const char *log_message)
                 strcat(tid, " ");
         }
 
-        fprintf(file, "%s%s%s%s %s%s\n", tbuf, yaz_log_info.l_prefix,
-                tid, flags, yaz_log_info.l_prefix2,
-                log_message);
+        fprintf(file, "%s%s%s%s %s", tbuf, yaz_log_info.l_prefix,
+                tid, flags, yaz_log_info.l_prefix2);
+        vfprintf(file, fmt, ap);
+        if (error_cp)
+            fprintf(file, " [%s]", error_cp);
+        fputs("\n", file);
         if (l_level & YLOG_FLUSH)
             fflush(file);
     }
@@ -466,40 +463,43 @@ static void yaz_log_to_file(int level, const char *log_message)
 void yaz_log(int level, const char *fmt, ...)
 {
     va_list ap;
-    char buf[4096];
     FILE *file;
     int o_level = level;
+    char *error_cp = 0, error_buf[128];
 
-    internal_log_init();
+    if (o_level & YLOG_ERRNO)
+    {
+        yaz_strerror(error_buf, sizeof(error_buf));
+        error_cp = error_buf;
+    }
+    yaz_init_globals();
     if (!(level & l_level))
         return;
     va_start(ap, fmt);
 
-    /* 30 is enough for our 'rest of output' message */
-    yaz_vsnprintf(buf, sizeof(buf)-30, fmt, ap);
-    if (strlen(buf) >= sizeof(buf)-31)
-        strcat(buf, " [rest of output omitted]");
-
-    if (o_level & YLOG_ERRNO)
+    file = yaz_log_file();
+    if (start_hook_func || hook_func || end_hook_func)
     {
-        size_t remain = sizeof(buf) - strlen(buf);
-        if (remain > 100) /* reasonable minimum space for error */
-        {
-            strcat(buf, " [");
-            yaz_strerror(buf+strlen(buf), remain-5); /* 5 due to extra [] */
-            strcat(buf, "]");
-        }
+        char buf[1024];
+        /* 30 is enough for our 'rest of output' message */
+        yaz_vsnprintf(buf, sizeof(buf)-30, fmt, ap);
+        if (strlen(buf) >= sizeof(buf)-31)
+            strcat(buf, " [rest of output omitted]");
+        if (start_hook_func)
+            (*start_hook_func)(o_level, buf, start_hook_info);
+        if (hook_func)
+            (*hook_func)(o_level, buf, hook_info);
+        if (file)
+            yaz_log_to_file(level, fmt, ap, error_cp);
+        if (end_hook_func)
+            (*end_hook_func)(o_level, buf, end_hook_info);
     }
-    va_end (ap);
-    if (start_hook_func)
-        (*start_hook_func)(o_level, buf, start_hook_info);
-    if (hook_func)
-        (*hook_func)(o_level, buf, hook_info);
-    file = yaz_log_file();
-    if (file)
-        yaz_log_to_file(level, buf);
-    if (end_hook_func)
-        (*end_hook_func)(o_level, buf, end_hook_info);
+    else
+    {
+        if (file)
+            yaz_log_to_file(level, fmt, ap, error_cp);
+    }
+    va_end(ap);
 }
 
 void yaz_log_time_format(const char *fmt)
@@ -564,7 +564,7 @@ int yaz_log_module_level(const char *name)
     int i;
     char clean[255];
     char *n = clean_name(name, strlen(name), clean, sizeof(clean));
-    internal_log_init();
+    yaz_init_globals();
 
     for (i = 0; mask_names[i].name; i++)
         if (0==strcmp(n, mask_names[i].name))
@@ -581,15 +581,16 @@ int yaz_log_module_level(const char *name)
 
 int yaz_log_mask_str(const char *str)
 {
-    internal_log_init(); /* since l_level may be affected */
+    yaz_init_globals(); /* since l_level may be affected */
     return yaz_log_mask_str_x(str, l_level);
 }
 
+/* this function is called by yaz_log_init_globals & yaz_init_globals
+   and, thus, may not call any of them indirectly */
 int yaz_log_mask_str_x(const char *str, int level)
 {
     const char *p;
 
-    internal_log_init();
     while (*str)
     {
         int negated = 0;