root/src/utils/noit_log.c

Revision 06f58e662d9dcb103af43ff53f3bd7e72248cea4, 8.7 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 6 years ago)

prep for jlog transit over SSL

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2007, OmniTI Computer Consulting, Inc.
3  * All rights reserved.
4  */
5
6 #define DEFAULT_JLOG_SUBSCRIBER "stratcond"
7
8 #include "noit_defines.h"
9 #include <stdio.h>
10 #include <fcntl.h>
11 #include <unistd.h>
12 #include <sys/time.h>
13
14 #include "utils/noit_log.h"
15 #include "utils/noit_hash.h"
16 #include "jlog/jlog.h"
17
18 static noit_hash_table noit_loggers = NOIT_HASH_EMPTY;
19 static noit_hash_table noit_logops = NOIT_HASH_EMPTY;
20 noit_log_stream_t noit_stderr = NULL;
21 noit_log_stream_t noit_error = NULL;
22 noit_log_stream_t noit_debug = NULL;
23
24 static int
25 posix_logio_open(noit_log_stream_t ls) {
26   int fd;
27   fd = open(ls->path, O_CREAT|O_WRONLY|O_APPEND);
28   if(fd < 0) {
29     ls->op_ctx = NULL;
30     return -1;
31   }
32   ls->op_ctx = (void *)fd;
33   return 0;
34 }
35 static int
36 posix_logio_reopen(noit_log_stream_t ls) {
37   if(ls->path) {
38     int newfd, oldfd;
39     oldfd = (int)ls->op_ctx;
40     newfd = open(ls->path, O_CREAT|O_WRONLY|O_APPEND);
41     if(newfd >= 0) {
42       ls->op_ctx = (void *)newfd;
43       if(oldfd >= 0) close(oldfd);
44       return 0;
45     }
46   }
47   return -1;
48 }
49 static int
50 posix_logio_write(noit_log_stream_t ls, const void *buf, size_t len) {
51   int fd;
52   fd = (int)ls->op_ctx;
53   if(fd < 0) return -1;
54   return write(fd, buf, len);
55 }
56 static int
57 posix_logio_close(noit_log_stream_t ls) {
58   int fd;
59   fd = (int)ls->op_ctx;
60   return close(fd);
61 }
62 static logops_t posix_logio_ops = {
63   posix_logio_open,
64   posix_logio_reopen,
65   posix_logio_write,
66   posix_logio_close,
67 };
68
69 static int
70 jlog_logio_open(noit_log_stream_t ls) {
71   jlog_ctx *log = NULL;
72   if(!ls->path) return -1;
73   log = jlog_new(ls->path);
74   if(!log) return -1;
75   /* Open the writer. */
76   if(jlog_ctx_open_writer(log)) {
77     /* If that fails, we'll give one attempt at initiailizing it. */
78     /* But, since we attempted to open it as a writer, it is tainted. */
79     /* path: close, new, init, close, new, writer, add subscriber */
80     jlog_ctx_close(log);
81     log = jlog_new(ls->path);
82     if(jlog_ctx_init(log)) {
83       noitL(noit_error, "Cannot init jlog writer: %s\n",
84             jlog_ctx_err_string(log));
85       jlog_ctx_close(log);
86       return -1;
87     }
88     /* After it is initialized, we can try to reopen it as a writer. */
89     jlog_ctx_close(log);
90     log = jlog_new(ls->path);
91     if(jlog_ctx_open_writer(log)) {
92       noitL(noit_error, "Cannot open jlog writer: %s\n",
93             jlog_ctx_err_string(log));
94       jlog_ctx_close(log);
95       return -1;
96     }
97     /* The first time we open after an init, we should add the subscriber. */
98     jlog_ctx_add_subscriber(log, DEFAULT_JLOG_SUBSCRIBER, JLOG_BEGIN);
99   }
100   ls->op_ctx = log;
101   return 0;
102 }
103 static int
104 jlog_logio_reopen(noit_log_stream_t ls) {
105   return 0;
106 }
107 static int
108 jlog_logio_write(noit_log_stream_t ls, const void *buf, size_t len) {
109   if(!ls->op_ctx) return -1;
110   if(jlog_ctx_write((jlog_ctx *)ls->op_ctx, buf, len) != 0)
111     return -1;
112   return len;
113 }
114 static int
115 jlog_logio_close(noit_log_stream_t ls) {
116   if(ls->op_ctx) {
117     jlog_ctx_close((jlog_ctx *)ls->op_ctx);
118     ls->op_ctx = NULL;
119   }
120   return 0;
121 }
122 static logops_t jlog_logio_ops = {
123   jlog_logio_open,
124   jlog_logio_reopen,
125   jlog_logio_write,
126   jlog_logio_close,
127 };
128
129 void
130 noit_log_init() {
131   noit_hash_init(&noit_loggers);
132   noit_hash_init(&noit_logops);
133   noit_register_logops("file", &posix_logio_ops);
134   noit_register_logops("jlog", &jlog_logio_ops);
135   noit_stderr = noit_log_stream_new_on_fd("stderr", 2, NULL);
136   noit_error = noit_log_stream_new("error", NULL, NULL, NULL);
137   noit_debug = noit_log_stream_new("debug", NULL, NULL, NULL);
138 }
139
140 void
141 noit_register_logops(const char *name, logops_t *ops) {
142   noit_hash_store(&noit_logops, strdup(name), strlen(name), ops);
143 }
144
145 noit_log_stream_t
146 noit_log_stream_new_on_fd(const char *name, int fd, noit_hash_table *config) {
147   noit_log_stream_t ls;
148   ls = calloc(1, sizeof(*ls));
149   ls->name = strdup(name);
150   ls->ops = &posix_logio_ops;
151   ls->op_ctx = (void *)fd;
152   ls->enabled = 1;
153   ls->config = config;
154   /* This double strdup of ls->name is needed, look for the next one
155    * for an explanation.
156    */
157   if(noit_hash_store(&noit_loggers,
158                      strdup(ls->name), strlen(ls->name), ls) == 0) {
159     free(ls->name);
160     free(ls);
161     return NULL;
162   }
163   return ls;
164 }
165
166 noit_log_stream_t
167 noit_log_stream_new_on_file(const char *path, noit_hash_table *config) {
168   return noit_log_stream_new(path, "file", path, config);
169 }
170
171 noit_log_stream_t
172 noit_log_stream_new(const char *name, const char *type, const char *path,
173                     noit_hash_table *config) {
174   noit_log_stream_t ls, saved;
175   struct _noit_log_stream tmpbuf;
176   ls = calloc(1, sizeof(*ls));
177   ls->name = strdup(name);
178   ls->path = path ? strdup(path) : NULL;
179   ls->type = type ? strdup(type) : NULL;
180   ls->enabled = 1;
181   ls->config = config;
182   if(!type)
183     ls->ops = NULL;
184   else if(!noit_hash_retrieve(&noit_logops, type, strlen(type),
185                               (void **)&ls->ops))
186     goto freebail;
187  
188   if(ls->ops && ls->ops->openop(ls)) goto freebail;
189
190   saved = noit_log_stream_find(name);
191   if(saved) {
192     memcpy(&tmpbuf, saved, sizeof(*saved));
193     memcpy(saved, ls, sizeof(*saved));
194     memcpy(ls, &tmpbuf, sizeof(*saved));
195     noit_log_stream_free(ls);
196     ls = saved;
197   }
198   else
199     /* We strdup the name *again*.  We'going to kansas city shuffle the
200      * ls later (see memcpy above).  However, if don't strdup, then the
201      * noit_log_stream_free up there will sweep our key right our from
202      * under us.
203      */
204     if(noit_hash_store(&noit_loggers,
205                        strdup(ls->name), strlen(ls->name), ls) == 0)
206       goto freebail;
207
208   return ls;
209
210  freebail:
211   fprintf(stderr, "Failed to instantiate logger(%s,%s,%s)\n",
212           name, type ? type : "[null]", path ? path : "[null]");
213   free(ls->name);
214   if(ls->path) free(ls->path);
215   if(ls->type) free(ls->type);
216   free(ls);
217   return NULL;
218 }
219
220 noit_log_stream_t
221 noit_log_stream_find(const char *name) {
222   noit_log_stream_t ls;
223   if(noit_hash_retrieve(&noit_loggers, name, strlen(name), (void **)&ls)) {
224     return ls;
225   }
226   return NULL;
227 }
228
229 void
230 noit_log_stream_remove(const char *name) {
231   noit_hash_delete(&noit_loggers, name, strlen(name), NULL, NULL);
232 }
233
234 void
235 noit_log_stream_add_stream(noit_log_stream_t ls, noit_log_stream_t outlet) {
236   struct _noit_log_stream_outlet_list *newnode;
237   newnode = calloc(1, sizeof(*newnode));
238   newnode->outlet = outlet;
239   newnode->next = ls->outlets;
240   ls->outlets = newnode;
241 }
242
243 noit_log_stream_t
244 noit_log_stream_remove_stream(noit_log_stream_t ls, const char *name) {
245   noit_log_stream_t outlet;
246   struct _noit_log_stream_outlet_list *node, *tmp;
247   if(!ls->outlets) return NULL;
248   if(!strcmp(ls->outlets->outlet->name, name)) {
249     node = ls->outlets;
250     ls->outlets = node->next;
251     outlet = node->outlet;
252     free(node);
253     return outlet;
254   }
255   for(node = ls->outlets; node->next; node = node->next) {
256     if(!strcmp(node->next->outlet->name, name)) {
257       /* splice */
258       tmp = node->next;
259       node->next = tmp->next;
260       /* pluck */
261       outlet = tmp->outlet;
262       /* shed */
263       free(tmp);
264       /* return */
265       return outlet;
266     }
267   }
268   return NULL;
269 }
270
271 void noit_log_stream_reopen(noit_log_stream_t ls) {
272   struct _noit_log_stream_outlet_list *node;
273   if(ls->ops) ls->ops->reopenop(ls);
274   for(node = ls->outlets; node; node = node->next) {
275     noit_log_stream_reopen(node->outlet);
276   }
277 }
278
279 void
280 noit_log_stream_close(noit_log_stream_t ls) {
281   if(ls->ops) ls->ops->closeop(ls);
282 }
283
284 void
285 noit_log_stream_free(noit_log_stream_t ls) {
286   if(ls) {
287     struct _noit_log_stream_outlet_list *node;
288     if(ls->name) free(ls->name);
289     if(ls->path) free(ls->path);
290     while(ls->outlets) {
291       node = ls->outlets->next;
292       free(ls->outlets);
293       ls->outlets = node;
294     }
295     if(ls->config) {
296       noit_hash_destroy(ls->config, free, free);
297       free(ls->config);
298     }
299     free(ls);
300   }
301 }
302
303 void
304 noit_vlog(noit_log_stream_t ls, struct timeval *now,
305           const char *file, int line,
306           const char *format, va_list arg) {
307   char buffer[4096];
308   struct _noit_log_stream_outlet_list *node;
309 #ifdef va_copy
310   va_list copy;
311 #endif
312
313   if(ls->enabled) {
314     int len;
315     if(ls->ops) {
316 #ifdef va_copy
317       va_copy(copy, arg);
318       len = vsnprintf(buffer, sizeof(buffer), format, copy);
319       va_end(copy);
320 #else
321       len = vsnprintf(buffer, sizeof(buffer), format, arg);
322 #endif
323       ls->ops->writeop(ls, buffer, len); /* Not much one can do about errors */
324     }
325
326     for(node = ls->outlets; node; node = node->next) {
327   #ifdef va_copy
328       va_copy(copy, arg);
329       noit_vlog(node->outlet, now, file, line, format, copy);
330       va_end(copy);
331   #else
332       noit_vlog(node->outlet, now, file, line, format, arg);
333   #endif
334     }
335   }
336 }
337
338 void
339 noit_log(noit_log_stream_t ls, struct timeval *now,
340          const char *file, int line, const char *format, ...) {
341   va_list arg;
342   va_start(arg, format);
343   noit_vlog(ls, now, file, line, format, arg);
344   va_end(arg);
345 }
346
Note: See TracBrowser for help on using the browser.