41 #include "log.h" |
41 #include "log.h" |
42 #include "../util/strbuf.h" |
42 #include "../util/strbuf.h" |
43 #include "../util/io.h" |
43 #include "../util/io.h" |
44 #include "../util/atomic.h" |
44 #include "../util/atomic.h" |
45 |
45 |
46 #include <ucx/map.h> |
46 #include <cx/hash_map.h> |
47 #include <ucx/list.h> |
47 #include <cx/linked_list.h> |
|
48 #include <cx/compare.h> |
48 |
49 |
49 static int is_initialized = 0; |
50 static int is_initialized = 0; |
50 |
51 |
51 static int log_file_fd; |
52 static int log_file_fd; |
52 static int log_level = 0; |
53 static int log_level = 0; |
53 |
54 |
54 static uint32_t log_dup_count = 0; |
55 static uint32_t log_dup_count = 0; |
55 static UcxList *log_dup_list = NULL; |
56 static CxList *log_dup_list = NULL; |
56 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; |
57 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; |
57 |
58 |
58 WSBool main_is_daemon(void); |
59 WSBool main_is_daemon(void); |
59 |
60 |
60 /* |
61 /* |
108 int init_log_file(LogConfig *cfg) { |
109 int init_log_file(LogConfig *cfg) { |
109 if(is_initialized) { |
110 if(is_initialized) { |
110 return 0; |
111 return 0; |
111 } |
112 } |
112 |
113 |
|
114 log_dup_list = cxPointerLinkedListCreate(cxDefaultAllocator, cx_cmp_ptr); |
|
115 |
113 /* open the log file */ |
116 /* open the log file */ |
114 mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; |
117 mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; |
115 log_file_fd = open(cfg->file, O_WRONLY | O_CREAT | O_APPEND, mode); |
118 log_file_fd = open(cfg->file, O_WRONLY | O_CREAT | O_APPEND, mode); |
116 if(log_file_fd == -1) { |
119 if(log_file_fd == -1) { |
117 log_ereport(LOG_FAILURE, "Cannot open log file %s: %s", cfg->file, strerror(errno)); |
120 log_ereport(LOG_FAILURE, "Cannot open log file %s: %s", cfg->file, strerror(errno)); |
163 if(ui_buffer == NULL) { |
166 if(ui_buffer == NULL) { |
164 return; /* TODO: critical error, exit */ |
167 return; /* TODO: critical error, exit */ |
165 } |
168 } |
166 } |
169 } |
167 |
170 |
168 sstr_t s; |
171 cxstring s; |
169 s.ptr = str; |
172 s.ptr = str; |
170 s.length = len; |
173 s.length = len; |
171 |
174 |
172 sbuf_append(ui_buffer, s); |
175 sbuf_append(ui_buffer, s); |
173 sbuf_put(ui_buffer, '\n'); |
176 sbuf_put(ui_buffer, '\n'); |
193 char *msg = malloc(len + 1); |
196 char *msg = malloc(len + 1); |
194 memcpy(msg, str, len); |
197 memcpy(msg, str, len); |
195 msg[len] = '\n'; |
198 msg[len] = '\n'; |
196 |
199 |
197 pthread_mutex_lock(&mutex); |
200 pthread_mutex_lock(&mutex); |
198 UCX_FOREACH(elm, log_dup_list) { |
201 CxIterator i = cxListIterator(log_dup_list, 0); |
199 LogDup *dup = elm->data; |
202 cx_foreach(LogDup *, dup, i) { |
200 dup->write(dup->cookie, msg, len + 1); |
203 dup->write(dup->cookie, msg, len + 1); |
201 } |
204 } |
202 pthread_mutex_unlock(&mutex); |
205 pthread_mutex_unlock(&mutex); |
203 |
206 |
204 free(msg); |
207 free(msg); |
205 } |
208 } |
206 } |
209 } |
207 |
210 |
208 sstr_t log_get_prefix(int level) { |
211 cxmutstr log_get_prefix(int level) { |
209 time_t t = time(NULL); |
212 time_t t = time(NULL); |
210 |
213 |
211 sstr_t d; |
214 cxmutstr d; |
212 d.ptr = NULL; |
215 d.ptr = NULL; |
213 d.length = 0; |
216 d.length = 0; |
214 |
217 |
215 struct tm date; |
218 struct tm date; |
216 localtime_r(&t, &date); |
219 localtime_r(&t, &date); |
236 return d; |
239 return d; |
237 } |
240 } |
238 |
241 |
239 void log_add_logdup(LogDup *dup) { |
242 void log_add_logdup(LogDup *dup) { |
240 pthread_mutex_lock(&mutex); |
243 pthread_mutex_lock(&mutex); |
241 log_dup_list = ucx_list_append(log_dup_list, dup); |
244 cxListAdd(log_dup_list, dup); |
242 ws_atomic_inc32(&log_dup_count); |
245 ws_atomic_inc32(&log_dup_count); |
243 pthread_mutex_unlock(&mutex); |
246 pthread_mutex_unlock(&mutex); |
244 } |
247 } |
245 |
248 |
246 void log_remove_logdup(LogDup *ldup) { |
249 void log_remove_logdup(LogDup *ldup) { |
247 pthread_mutex_lock(&mutex); |
250 pthread_mutex_lock(&mutex); |
248 UcxList *elm = log_dup_list; |
251 CxIterator i = cxListIterator(log_dup_list, 0); |
249 while(elm) { |
252 WSBool finished = 0; |
250 if(elm->data == ldup) { |
253 cx_foreach(LogDup *, dup, i) { |
251 log_dup_list = ucx_list_remove(log_dup_list, elm); |
254 if(finished) break; |
|
255 if(dup == ldup) { |
|
256 i.remove = 1; |
|
257 finished = 1; |
252 ws_atomic_dec32(&log_dup_count); |
258 ws_atomic_dec32(&log_dup_count); |
253 break; |
|
254 } |
259 } |
255 elm = elm->next; |
|
256 } |
260 } |
257 pthread_mutex_unlock(&mutex); |
261 pthread_mutex_unlock(&mutex); |
258 } |
262 } |
259 |
263 |
260 |
264 |
276 } |
280 } |
277 if(!can_log[degree]) { |
281 if(!can_log[degree]) { |
278 return 0; |
282 return 0; |
279 } |
283 } |
280 |
284 |
281 sstr_t lmsg; |
285 cxmutstr lmsg; |
282 lmsg.ptr = NULL; |
286 lmsg.ptr = NULL; |
283 |
287 |
284 /* create log message prefix */ |
288 /* create log message prefix */ |
285 sstr_t lpre = log_get_prefix(degree); |
289 cxmutstr lpre = log_get_prefix(degree); |
286 |
290 |
287 /* format message */ |
291 /* format message */ |
288 int len = vasprintf(&lmsg.ptr, format, args); |
292 int len = vasprintf(&lmsg.ptr, format, args); |
289 lmsg.length = len; |
293 lmsg.length = len; |
290 |
294 |
291 /* create message string */ |
295 /* create message string */ |
292 sstr_t message = sstrcat(2, lpre, lmsg); |
296 cxmutstr message = cx_strcat(2, lpre, lmsg); |
293 |
297 |
294 /* write message to the log file */ |
298 /* write message to the log file */ |
295 log_file_writeln(message.ptr, message.length); |
299 log_file_writeln(message.ptr, message.length); |
296 |
300 |
297 /* cleanup */ |
301 /* cleanup */ |
334 /* |
338 /* |
335 * access log |
339 * access log |
336 * This source file only manages access log files. IO is performed directly |
340 * This source file only manages access log files. IO is performed directly |
337 * by AddLog safs. |
341 * by AddLog safs. |
338 */ |
342 */ |
339 LogFile* get_access_log_file(scstr_t file) { |
343 LogFile* get_access_log_file(cxstring file) { |
340 // TODO: this looks dubious |
344 // TODO: this looks dubious |
341 |
345 |
342 if(!access_log_files) { |
346 if(!access_log_files) { |
343 access_log_files = ucx_map_new(4); |
347 access_log_files = cxHashMapCreate(cxDefaultAllocator, 4); |
344 } |
348 } |
345 |
349 |
346 if(file.ptr == NULL || file.length == 0) { |
350 if(file.ptr == NULL || file.length == 0) { |
347 return NULL; |
351 return NULL; |
348 } |
352 } |
349 |
353 |
350 LogFile *log = ucx_map_sstr_get(access_log_files, file); |
354 CxHashKey key = cx_hash_key_bytes((unsigned const char*)file.ptr, file.length); |
|
355 LogFile *log = cxMapGet(access_log_files, key); |
351 if(log != NULL) { |
356 if(log != NULL) { |
352 ws_atomic_inc32(&log->ref); |
357 ws_atomic_inc32(&log->ref); |
353 return log; |
358 return log; |
354 } |
359 } |
355 |
360 |