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