multipath-tools: add alias_prefix to multipath.conf.5
[multipath-tools/.git] / libmultipath / log.c
1 /*
2  * Copyright (c) 2005 Christophe Varoqui
3  * Copyright (c) 2005 Benjamin Marzinski, Redhat
4  * Copyright (c) 2005 Jun'ichi Nomura, NEC
5  */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <stdarg.h>
9 #include <string.h>
10 #include <syslog.h>
11 #include <time.h>
12
13 #include "memory.h"
14 #include "log.h"
15
16 #define ALIGN(len, s) (((len)+(s)-1)/(s)*(s))
17
18 #if LOGDBG
19 static void dump_logarea (void)
20 {
21         struct logmsg * msg;
22
23         logdbg(stderr, "\n==== area: start addr = %p, end addr = %p ====\n",
24                 la->start, la->end);
25         logdbg(stderr, "|addr     |next     |prio|msg\n");
26
27         for (msg = (struct logmsg *)la->head; (void *)msg != la->tail;
28              msg = msg->next)
29                 logdbg(stderr, "|%p |%p |%i   |%s\n", (void *)msg, msg->next,
30                                 msg->prio, (char *)&msg->str);
31
32         logdbg(stderr, "|%p |%p |%i   |%s\n", (void *)msg, msg->next,
33                         msg->prio, (char *)&msg->str);
34
35         logdbg(stderr, "\n\n");
36 }
37 #endif
38
39 static int logarea_init (int size)
40 {
41         logdbg(stderr,"enter logarea_init\n");
42         la = (struct logarea *)MALLOC(sizeof(struct logarea));
43
44         if (!la)
45                 return 1;
46
47         if (size < MAX_MSG_SIZE)
48                 size = DEFAULT_AREA_SIZE;
49
50         la->start = MALLOC(size);
51         if (!la->start) {
52                 FREE(la);
53                 return 1;
54         }
55         memset(la->start, 0, size);
56
57         la->empty = 1;
58         la->end = la->start + size;
59         la->head = la->start;
60         la->tail = la->start;
61
62         la->buff = MALLOC(MAX_MSG_SIZE + sizeof(struct logmsg));
63
64         if (!la->buff) {
65                 FREE(la->start);
66                 FREE(la);
67                 return 1;
68         }
69         return 0;
70
71 }
72
73 int log_init(char *program_name, int size)
74 {
75         logdbg(stderr,"enter log_init\n");
76         openlog(program_name, 0, LOG_DAEMON);
77
78         if (logarea_init(size))
79                 return 1;
80
81         return 0;
82 }
83
84 void free_logarea (void)
85 {
86         FREE(la->start);
87         FREE(la->buff);
88         FREE(la);
89         return;
90 }
91
92 void log_close (void)
93 {
94         free_logarea();
95         closelog();
96
97         return;
98 }
99
100 void log_reset (char *program_name)
101 {
102         closelog();
103         tzset();
104         openlog(program_name, 0, LOG_DAEMON);
105 }
106
107 int log_enqueue (int prio, const char * fmt, va_list ap)
108 {
109         int len, fwd;
110         char buff[MAX_MSG_SIZE];
111         struct logmsg * msg;
112         struct logmsg * lastmsg;
113
114         lastmsg = (struct logmsg *)la->tail;
115
116         if (!la->empty) {
117                 fwd = sizeof(struct logmsg) +
118                       strlen((char *)&lastmsg->str) * sizeof(char) + 1;
119                 la->tail += ALIGN(fwd, sizeof(void *));
120         }
121         vsnprintf(buff, MAX_MSG_SIZE, fmt, ap);
122         len = ALIGN(sizeof(struct logmsg) + strlen(buff) * sizeof(char) + 1,
123                     sizeof(void *));
124
125         /* not enough space on tail : rewind */
126         if (la->head <= la->tail && len > (la->end - la->tail)) {
127                 logdbg(stderr, "enqueue: rewind tail to %p\n", la->tail);
128                 if (la->head == la->start ) {
129                         logdbg(stderr, "enqueue: can not rewind tail, drop msg\n");
130                         la->tail = lastmsg;
131                         return 1;  /* can't reuse */
132                 }
133                 la->tail = la->start;
134
135                 if (la->empty)
136                         la->head = la->start;
137         }
138
139         /* not enough space on head : drop msg */
140         if (la->head > la->tail && len >= (la->head - la->tail)) {
141                 logdbg(stderr, "enqueue: log area overrun, drop msg\n");
142
143                 if (!la->empty)
144                         la->tail = lastmsg;
145
146                 return 1;
147         }
148
149         /* ok, we can stage the msg in the area */
150         la->empty = 0;
151         msg = (struct logmsg *)la->tail;
152         msg->prio = prio;
153         memcpy((void *)&msg->str, buff, strlen(buff) + 1);
154         lastmsg->next = la->tail;
155         msg->next = la->head;
156
157         logdbg(stderr, "enqueue: %p, %p, %i, %s\n", (void *)msg, msg->next,
158                 msg->prio, (char *)&msg->str);
159
160 #if LOGDBG
161         dump_logarea();
162 #endif
163         return 0;
164 }
165
166 int log_dequeue (void * buff)
167 {
168         struct logmsg * src = (struct logmsg *)la->head;
169         struct logmsg * dst = (struct logmsg *)buff;
170         struct logmsg * lst = (struct logmsg *)la->tail;
171
172         if (la->empty)
173                 return 1;
174
175         int len = strlen((char *)&src->str) * sizeof(char) +
176                   sizeof(struct logmsg) + 1;
177
178         dst->prio = src->prio;
179         memcpy(dst, src,  len);
180
181         if (la->tail == la->head)
182                 la->empty = 1; /* we purge the last logmsg */
183         else {
184                 la->head = src->next;
185                 lst->next = la->head;
186         }
187         logdbg(stderr, "dequeue: %p, %p, %i, %s\n",
188                 (void *)src, src->next, src->prio, (char *)&src->str);
189
190         memset((void *)src, 0,  len);
191
192         return 0;
193 }
194
195 /*
196  * this one can block under memory pressure
197  */
198 void log_syslog (void * buff)
199 {
200         struct logmsg * msg = (struct logmsg *)buff;
201
202         syslog(msg->prio, "%s", (char *)&msg->str);
203 }