root/src/utils/noit_log.c

Revision 31a4ef41bbf9b94c8ab2584710738251cec46ffe, 8.1 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 6 years ago)

fix up the open... appears to work now.

  • 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   if(noit_hash_store(&noit_loggers, ls->name, strlen(ls->name), ls) == 0) {
155     free(ls->name);
156     free(ls);
157     return NULL;
158   }
159   return ls;
160 }
161
162 noit_log_stream_t
163 noit_log_stream_new_on_file(const char *path, noit_hash_table *config) {
164   return noit_log_stream_new(path, "file", path, config);
165 }
166
167 noit_log_stream_t
168 noit_log_stream_new(const char *name, const char *type, const char *path,
169                     noit_hash_table *config) {
170   noit_log_stream_t ls, saved;
171   struct _noit_log_stream tmpbuf;
172   ls = calloc(1, sizeof(*ls));
173   ls->name = strdup(name);
174   ls->path = path ? strdup(path) : NULL;
175   ls->enabled = 1;
176   ls->config = config;
177   if(!type)
178     ls->ops = NULL;
179   else if(!noit_hash_retrieve(&noit_logops, type, strlen(type),
180                               (void **)&ls->ops))
181     goto freebail;
182  
183   if(ls->ops && ls->ops->openop(ls)) goto freebail;
184
185   saved = noit_log_stream_find(name);
186   if(saved) {
187     memcpy(&tmpbuf, saved, sizeof(*saved));
188     memcpy(saved, ls, sizeof(*saved));
189     memcpy(ls, &tmpbuf, sizeof(*saved));
190     noit_log_stream_free(ls);
191     ls = saved;
192   }
193   else
194     if(noit_hash_store(&noit_loggers, ls->name, strlen(ls->name), ls) == 0)
195       goto freebail;
196
197   return ls;
198
199  freebail:
200     free(ls->name);
201     if(ls->path) free(ls->path);
202     free(ls);
203     return NULL;
204 }
205
206 noit_log_stream_t
207 noit_log_stream_find(const char *name) {
208   noit_log_stream_t ls;
209   if(noit_hash_retrieve(&noit_loggers, name, strlen(name), (void **)&ls)) {
210     return ls;
211   }
212   return NULL;
213 }
214
215 void
216 noit_log_stream_remove(const char *name) {
217   noit_hash_delete(&noit_loggers, name, strlen(name), NULL, NULL);
218 }
219
220 void
221 noit_log_stream_add_stream(noit_log_stream_t ls, noit_log_stream_t outlet) {
222   struct _noit_log_stream_outlet_list *newnode;
223   newnode = calloc(1, sizeof(*newnode));
224   newnode->outlet = outlet;
225   newnode->next = ls->outlets;
226   ls->outlets = newnode;
227 }
228
229 noit_log_stream_t
230 noit_log_stream_remove_stream(noit_log_stream_t ls, const char *name) {
231   noit_log_stream_t outlet;
232   struct _noit_log_stream_outlet_list *node, *tmp;
233   if(!ls->outlets) return NULL;
234   if(!strcmp(ls->outlets->outlet->name, name)) {
235     node = ls->outlets;
236     ls->outlets = node->next;
237     outlet = node->outlet;
238     free(node);
239     return outlet;
240   }
241   for(node = ls->outlets; node->next; node = node->next) {
242     if(!strcmp(node->next->outlet->name, name)) {
243       /* splice */
244       tmp = node->next;
245       node->next = tmp->next;
246       /* pluck */
247       outlet = tmp->outlet;
248       /* shed */
249       free(tmp);
250       /* return */
251       return outlet;
252     }
253   }
254   return NULL;
255 }
256
257 void noit_log_stream_reopen(noit_log_stream_t ls) {
258   struct _noit_log_stream_outlet_list *node;
259   if(ls->ops) ls->ops->reopenop(ls);
260   for(node = ls->outlets; node; node = node->next) {
261     noit_log_stream_reopen(node->outlet);
262   }
263 }
264
265 void
266 noit_log_stream_close(noit_log_stream_t ls) {
267   if(ls->ops) ls->ops->closeop(ls);
268 }
269
270 void
271 noit_log_stream_free(noit_log_stream_t ls) {
272   if(ls) {
273     struct _noit_log_stream_outlet_list *node;
274     if(ls->name) free(ls->name);
275     if(ls->path) free(ls->path);
276     while(ls->outlets) {
277       node = ls->outlets->next;
278       free(ls->outlets);
279       ls->outlets = node;
280     }
281     if(ls->config) {
282       noit_hash_destroy(ls->config, free, free);
283       free(ls->config);
284     }
285     free(ls);
286   }
287 }
288
289 void
290 noit_vlog(noit_log_stream_t ls, struct timeval *now,
291           const char *file, int line,
292           const char *format, va_list arg) {
293   char buffer[4096];
294   struct _noit_log_stream_outlet_list *node;
295 #ifdef va_copy
296   va_list copy;
297 #endif
298
299   if(ls->enabled) {
300     int len;
301     if(ls->ops) {
302 #ifdef va_copy
303       va_copy(copy, arg);
304       len = vsnprintf(buffer, sizeof(buffer), format, copy);
305       va_end(copy);
306 #else
307       len = vsnprintf(buffer, sizeof(buffer), format, arg);
308 #endif
309       ls->ops->writeop(ls, buffer, len); /* Not much one can do about errors */
310     }
311
312     for(node = ls->outlets; node; node = node->next) {
313   #ifdef va_copy
314       va_copy(copy, arg);
315       noit_vlog(node->outlet, now, file, line, format, copy);
316       va_end(copy);
317   #else
318       noit_vlog(node->outlet, now, file, line, format, arg);
319   #endif
320     }
321   }
322 }
323
324 void
325 noit_log(noit_log_stream_t ls, struct timeval *now,
326          const char *file, int line, const char *format, ...) {
327   va_list arg;
328   va_start(arg, format);
329   noit_vlog(ls, now, file, line, format, arg);
330   va_end(arg);
331 }
332
Note: See TracBrowser for help on using the browser.