[libmultipath] move the async logger in libmultipath
authorChristophe Varoqui <root@xa-s05.(none)>
Fri, 4 Nov 2005 08:17:33 +0000 (09:17 +0100)
committerChristophe Varoqui <root@xa-s05.(none)>
Fri, 4 Nov 2005 08:17:33 +0000 (09:17 +0100)
Brian Wong, Pillardata, suggested and implemented this to avoid
cross dependencies.

libmultipath/Makefile
libmultipath/debug.c
libmultipath/debug.h
libmultipath/log.c [new file with mode: 0644]
libmultipath/log.h [new file with mode: 0644]
libmultipath/log_pthread.c [new file with mode: 0644]
libmultipath/log_pthread.h [new file with mode: 0644]
multipathd/Makefile

index 0bba4fb..0e2bfa3 100644 (file)
@@ -10,7 +10,8 @@ OBJS = memory.o parser.o vector.o devmapper.o callout.o \
        hwtable.o blacklist.o util.o dmparser.o config.o \
        structs.o cache.o discovery.o propsel.o dict.o \
        pgpolicies.o debug.o regex.o defaults.o uevent.o \
-       switchgroup.o uxsock.o print.o alias.o
+       switchgroup.o uxsock.o print.o alias.o log_pthread.o \
+       log.o
 
 CFLAGS = -pipe -g -Wall -Wunused -Wstrict-prototypes
 
index 7bb7d2d..4c46c23 100644 (file)
@@ -3,7 +3,7 @@
 #include <stdarg.h>
 
 #if DAEMON
-#include "../multipathd/log_pthread.h"
+#include "log_pthread.h"
 #endif
 
 #include "config.h"
index fbccabd..f5e5d10 100644 (file)
@@ -4,7 +4,8 @@ void dlog (int sink, int prio, char * fmt, ...);
 
 #include <pthread.h>
 #include <stdarg.h>
-#include "../multipathd/log_pthread.h"
+
+#include "log_pthread.h"
 
 int logsink;
 
diff --git a/libmultipath/log.c b/libmultipath/log.c
new file mode 100644 (file)
index 0000000..2bc81b5
--- /dev/null
@@ -0,0 +1,186 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <syslog.h>
+
+#include "memory.h"
+#include "log.h"
+
+#define ALIGN(len, s) (((len)+(s)-1)/(s)*(s))
+
+#if LOGDBG
+static void dump_logarea (void)
+{
+       struct logmsg * msg;
+       
+       logdbg(stderr, "\n==== area: start addr = %p, end addr = %p ====\n",
+               la->start, la->end);
+       logdbg(stderr, "|addr     |next     |prio|msg\n");
+
+       for (msg = (struct logmsg *)la->head; (void *)msg != la->tail;
+            msg = msg->next)
+               logdbg(stderr, "|%p |%p |%i   |%s\n", (void *)msg, msg->next,
+                               msg->prio, (char *)&msg->str);
+
+       logdbg(stderr, "|%p |%p |%i   |%s\n", (void *)msg, msg->next,
+                       msg->prio, (char *)&msg->str);
+
+       logdbg(stderr, "\n\n");
+}
+#endif
+               
+static int logarea_init (int size)
+{
+       logdbg(stderr,"enter logarea_init\n");
+       la = (struct logarea *)MALLOC(sizeof(struct logarea));
+       
+       if (!la)
+               return 1;
+
+       if (size < MAX_MSG_SIZE)
+               size = DEFAULT_AREA_SIZE;
+
+       la->start = MALLOC(size);
+       memset(la->start, 0, size);
+
+       if (!la->start) {
+               FREE(la);
+               return 1;
+       }
+
+       la->empty = 1;
+       la->end = la->start + size;
+       la->head = la->start;
+       la->tail = la->start;
+
+       la->buff = MALLOC(MAX_MSG_SIZE + sizeof(struct logmsg));
+
+       if (!la->buff) {
+               FREE(la->start);
+               FREE(la);
+               return 1;
+       }
+       return 0;
+
+}
+
+int log_init(char *program_name, int size)
+{
+       logdbg(stderr,"enter log_init\n");
+       openlog(program_name, 0, LOG_DAEMON);
+
+       if (logarea_init(size))
+               return 1;
+
+       return 0;
+}
+
+void free_logarea (void)
+{
+       FREE(la->start);
+       FREE(la->buff);
+       FREE(la);
+       return;
+}
+
+void log_close (void)
+{
+       free_logarea();
+       closelog();
+
+       return;
+}
+
+int log_enqueue (int prio, const char * fmt, va_list ap)
+{
+       int len, fwd;
+       char buff[MAX_MSG_SIZE];
+       struct logmsg * msg;
+       struct logmsg * lastmsg;
+
+       lastmsg = (struct logmsg *)la->tail;
+
+       if (!la->empty) {
+               fwd = sizeof(struct logmsg) + 
+                     strlen((char *)&lastmsg->str) * sizeof(char) + 1;
+               la->tail += ALIGN(fwd, sizeof(void *));
+       }
+       vsnprintf(buff, MAX_MSG_SIZE, fmt, ap);
+       len = ALIGN(sizeof(struct logmsg) + strlen(buff) * sizeof(char) + 1,
+                   sizeof(void *));
+
+       /* not enough space on tail : rewind */
+       if (la->head <= la->tail && len > (la->end - la->tail)) {
+               logdbg(stderr, "enqueue: rewind tail to %p\n", la->tail);
+               la->tail = la->start;
+
+               if (la->empty)
+                       la->head = la->start;
+       }
+
+       /* not enough space on head : drop msg */
+       if (la->head > la->tail && len >= (la->head - la->tail)) {
+               logdbg(stderr, "enqueue: log area overrun, drop msg\n");
+
+               if (!la->empty)
+                       la->tail = lastmsg;
+
+               return 1;
+       }
+
+       /* ok, we can stage the msg in the area */
+       la->empty = 0;
+       msg = (struct logmsg *)la->tail;
+       msg->prio = prio;
+       memcpy((void *)&msg->str, buff, strlen(buff));
+       lastmsg->next = la->tail;
+       msg->next = la->head;
+
+       logdbg(stderr, "enqueue: %p, %p, %i, %s\n", (void *)msg, msg->next,
+               msg->prio, (char *)&msg->str);
+
+#if LOGDBG
+       dump_logarea();
+#endif
+       return 0;
+}
+
+int log_dequeue (void * buff)
+{
+       struct logmsg * src = (struct logmsg *)la->head;
+       struct logmsg * dst = (struct logmsg *)buff;
+       struct logmsg * lst = (struct logmsg *)la->tail;
+
+       if (la->empty)
+               return 1;
+
+       int len = strlen((char *)&src->str) * sizeof(char) +
+                 sizeof(struct logmsg) + 1;
+
+       dst->prio = src->prio;
+       memcpy(dst, src,  len);
+
+       if (la->tail == la->head)
+               la->empty = 1; /* we purge the last logmsg */
+       else {
+               la->head = src->next;
+               lst->next = la->head;
+       }
+       logdbg(stderr, "dequeue: %p, %p, %i, %s\n",
+               (void *)src, src->next, src->prio, (char *)&src->str);
+
+       memset((void *)src, 0,  len);
+
+       return la->empty;
+}
+
+/*
+ * this one can block under memory pressure
+ */
+void log_syslog (void * buff)
+{
+       struct logmsg * msg = (struct logmsg *)buff;
+
+       syslog(msg->prio, "%s", (char *)&msg->str);
+}
diff --git a/libmultipath/log.h b/libmultipath/log.h
new file mode 100644 (file)
index 0000000..c697118
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef LOG_H
+#define LOG_H
+
+#define DEFAULT_AREA_SIZE 8192
+#define MAX_MSG_SIZE 128
+
+#ifndef LOGLEVEL
+#define LOGLEVEL 5
+#endif
+
+#if LOGDBG
+#define logdbg(file, fmt, args...) fprintf(file, fmt, ##args)
+#else
+#define logdbg(file, fmt, args...) do {} while (0)
+#endif
+
+struct logmsg {
+       short int prio;
+       void * next;
+       char * str;
+};
+
+struct logarea {
+       int empty;
+       void * head;
+       void * tail;
+       void * start;
+       void * end;
+       char * buff;
+};
+
+struct logarea * la;
+
+int log_init (char * progname, int size);
+void log_close (void);
+int log_enqueue (int prio, const char * fmt, va_list ap);
+int log_dequeue (void *);
+void log_syslog (void *);
+void dump_logmsg (void *);
+void free_logarea (void);
+
+#endif /* LOG_H */
diff --git a/libmultipath/log_pthread.c b/libmultipath/log_pthread.c
new file mode 100644 (file)
index 0000000..3ac13a7
--- /dev/null
@@ -0,0 +1,92 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <pthread.h>
+#include <sys/mman.h>
+
+#include <memory.h>
+
+#include "log_pthread.h"
+#include "log.h"
+
+void log_safe (int prio, char * fmt, va_list ap)
+{
+       pthread_mutex_lock(logq_lock);
+       //va_start(ap, fmt);
+       log_enqueue(prio, fmt, ap);
+       va_end(ap);
+       pthread_mutex_unlock(logq_lock);
+
+       pthread_mutex_lock(logev_lock);
+       pthread_cond_signal(logev_cond);
+       pthread_mutex_unlock(logev_lock);
+}
+
+static void flush_logqueue (void)
+{
+       int empty;
+
+       do {
+               pthread_mutex_lock(logq_lock);
+               empty = log_dequeue(la->buff);
+               pthread_mutex_unlock(logq_lock);
+               log_syslog(la->buff);
+       } while (empty == 0);
+}
+
+static void * log_thread (void * et)
+{
+       mlockall(MCL_CURRENT | MCL_FUTURE);
+       logdbg(stderr,"enter log_thread\n");
+
+       while (1) {
+               pthread_mutex_lock(logev_lock);
+               pthread_cond_wait(logev_cond, logev_lock);
+               pthread_mutex_unlock(logev_lock);
+
+               flush_logqueue();
+       }
+}
+
+void log_thread_start (void)
+{
+       pthread_attr_t attr;
+       
+       logdbg(stderr,"enter log_thread_start\n");
+
+       logq_lock = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
+       logev_lock = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
+       logev_cond = (pthread_cond_t *) malloc(sizeof(pthread_cond_t));
+       
+       pthread_mutex_init(logq_lock, NULL);
+       pthread_mutex_init(logev_lock, NULL);
+       pthread_cond_init(logev_cond, NULL);
+       
+       pthread_attr_init(&attr);
+       pthread_attr_setstacksize(&attr, 64 * 1024);
+
+       if (log_init("multipathd", 0)) {
+               fprintf(stderr,"can't initialize log buffer\n");
+               exit(1);
+       }
+       pthread_create(&log_thr, &attr, log_thread, NULL);
+
+       return;
+}
+
+void log_thread_stop (void)
+{
+       logdbg(stderr,"enter log_thread_stop\n");
+
+       pthread_mutex_lock(logq_lock);
+       pthread_cancel(log_thr);
+       pthread_mutex_unlock(logq_lock);
+
+       flush_logqueue();
+
+       pthread_mutex_destroy(logq_lock);
+       pthread_mutex_destroy(logev_lock);
+       pthread_cond_destroy(logev_cond);
+
+       free_logarea();
+}      
diff --git a/libmultipath/log_pthread.h b/libmultipath/log_pthread.h
new file mode 100644 (file)
index 0000000..7c902c7
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _LOG_PTHREAD_H
+#define _LOG_PTHREAD_H
+
+pthread_t log_thr;
+
+pthread_mutex_t *logq_lock;
+pthread_mutex_t *logev_lock;
+pthread_cond_t *logev_cond;
+
+void log_safe(int prio, char * fmt, va_list ap);
+void log_thread_start(void);
+void log_thread_stop(void);
+
+#endif /* _LOG_PTHREAD_H */
index f977078..98d2d91 100644 (file)
@@ -27,7 +27,7 @@ LDFLAGS = -lpthread -ldevmapper -lsysfs -lreadline -lncurses -lm
 #
 # object files
 #
-OBJS = main.o log.o log_pthread.o pidfile.o uxlsnr.o uxclnt.o cli.o cli_handlers.o \
+OBJS = main.o pidfile.o uxlsnr.o uxclnt.o cli.o cli_handlers.o \
        $(MULTIPATHLIB)-glibc.a $(CHECKERSLIB)-glibc.a \