1 /*
2  * This file is part of the zlog Library.
3  *
4  * Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
5  *
6  * Licensed under the LGPL v2.1, see the file COPYING in base directory.
7  */
8 
9 #include "fmacros.h"
10 
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <stdarg.h>
14 #include <string.h>
15 #include <pthread.h>
16 
17 #include "conf.h"
18 #include "category_table.h"
19 #include "record_table.h"
20 #include "mdc.h"
21 #include "zc_defs.h"
22 #include "rule.h"
23 #include "version.h"
24 
25 /*******************************************************************************/
26 extern char *zlog_git_sha1;
27 /*******************************************************************************/
28 static pthread_rwlock_t zlog_env_lock = PTHREAD_RWLOCK_INITIALIZER;
29 zlog_conf_t *zlog_env_conf;
30 static pthread_key_t zlog_thread_key;
31 static zc_hashtable_t *zlog_env_categories;
32 static zc_hashtable_t *zlog_env_records;
33 static zlog_category_t *zlog_default_category;
34 static size_t zlog_env_reload_conf_count;
35 static int zlog_env_is_init = 0;
36 static int zlog_env_init_version = 0;
37 /*******************************************************************************/
38 /* inner no need thread-safe */
zlog_fini_inner(void)39 static void zlog_fini_inner(void)
40 {
41 	/* pthread_key_delete(zlog_thread_key); */
42 	/* never use pthread_key_delete,
43 	 * it will cause other thread can't release zlog_thread_t
44 	 * after one thread call pthread_key_delete
45 	 * also key not init will cause a core dump
46 	 */
47 
48 	if (zlog_env_categories) zlog_category_table_del(zlog_env_categories);
49 	zlog_env_categories = NULL;
50 	zlog_default_category = NULL;
51 	if (zlog_env_records) zlog_record_table_del(zlog_env_records);
52 	zlog_env_records = NULL;
53 	if (zlog_env_conf) zlog_conf_del(zlog_env_conf);
54 	zlog_env_conf = NULL;
55 	return;
56 }
57 
zlog_clean_rest_thread(void)58 static void zlog_clean_rest_thread(void)
59 {
60 	zlog_thread_t *a_thread;
61 	a_thread = pthread_getspecific(zlog_thread_key);
62 	if (!a_thread) return;
63 	zlog_thread_del(a_thread);
64 	return;
65 }
66 
zlog_init_inner(const char * confpath)67 static int zlog_init_inner(const char *confpath)
68 {
69 	int rc = 0;
70 
71 	/* the 1st time in the whole process do init */
72 	if (zlog_env_init_version == 0) {
73 		/* clean up is done by OS when a thread call pthread_exit */
74 		rc = pthread_key_create(&zlog_thread_key, (void (*) (void *)) zlog_thread_del);
75 		if (rc) {
76 			zc_error("pthread_key_create fail, rc[%d]", rc);
77 			goto err;
78 		}
79 
80 		/* if some thread do not call pthread_exit, like main thread
81 		 * atexit will clean it
82 		 */
83 		rc = atexit(zlog_clean_rest_thread);
84 		if (rc) {
85 			zc_error("atexit fail, rc[%d]", rc);
86 			goto err;
87 		}
88 		zlog_env_init_version++;
89 	} /* else maybe after zlog_fini() and need not create pthread_key */
90 
91 	zlog_env_conf = zlog_conf_new(confpath);
92 	if (!zlog_env_conf) {
93 		zc_error("zlog_conf_new[%s] fail", confpath);
94 		goto err;
95 	}
96 
97 	zlog_env_categories = zlog_category_table_new();
98 	if (!zlog_env_categories) {
99 		zc_error("zlog_category_table_new fail");
100 		goto err;
101 	}
102 
103 	zlog_env_records = zlog_record_table_new();
104 	if (!zlog_env_records) {
105 		zc_error("zlog_record_table_new fail");
106 		goto err;
107 	}
108 
109 	return 0;
110 err:
111 	zlog_fini_inner();
112 	return -1;
113 }
114 
115 /*******************************************************************************/
zlog_init(const char * confpath)116 int zlog_init(const char *confpath)
117 {
118 	int rc;
119 	zc_debug("------zlog_init start------");
120 	zc_debug("------compile time[%s %s], version[%s]------", __DATE__, __TIME__, ZLOG_VERSION);
121 
122 	rc = pthread_rwlock_wrlock(&zlog_env_lock);
123 	if (rc) {
124 		zc_error("pthread_rwlock_wrlock fail, rc[%d]", rc);
125 		return -1;
126 	}
127 
128 	if (zlog_env_is_init) {
129 		zc_error("already init, use zlog_reload pls");
130 		goto err;
131 	}
132 
133 
134 	if (zlog_init_inner(confpath)) {
135 		zc_error("zlog_init_inner[%s] fail", confpath);
136 		goto err;
137 	}
138 
139 	zlog_env_is_init = 1;
140 	zlog_env_init_version++;
141 
142 	zc_debug("------zlog_init success end------");
143 	rc = pthread_rwlock_unlock(&zlog_env_lock);
144 	if (rc) {
145 		zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc);
146 		return -1;
147 	}
148 	return 0;
149 err:
150 	zc_error("------zlog_init fail end------");
151 	rc = pthread_rwlock_unlock(&zlog_env_lock);
152 	if (rc) {
153 		zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc);
154 		return -1;
155 	}
156 	return -1;
157 }
158 
dzlog_init(const char * confpath,const char * cname)159 int dzlog_init(const char *confpath, const char *cname)
160 {
161 	int rc = 0;
162 	zc_debug("------dzlog_init start------");
163 	zc_debug("------compile time[%s %s], version[%s]------",
164 			__DATE__, __TIME__, ZLOG_VERSION);
165 
166 	rc = pthread_rwlock_wrlock(&zlog_env_lock);
167 	if (rc) {
168 		zc_error("pthread_rwlock_wrlock fail, rc[%d]", rc);
169 		return -1;
170 	}
171 
172 	if (zlog_env_is_init) {
173 		zc_error("already init, use zlog_reload pls");
174 		goto err;
175 	}
176 
177 	if (zlog_init_inner(confpath)) {
178 		zc_error("zlog_init_inner[%s] fail", confpath);
179 		goto err;
180 	}
181 
182 	zlog_default_category = zlog_category_table_fetch_category(
183 				zlog_env_categories,
184 				cname,
185 				zlog_env_conf->rules);
186 	if (!zlog_default_category) {
187 		zc_error("zlog_category_table_fetch_category[%s] fail", cname);
188 		goto err;
189 	}
190 
191 	zlog_env_is_init = 1;
192 	zlog_env_init_version++;
193 
194 	zc_debug("------dzlog_init success end------");
195 	rc = pthread_rwlock_unlock(&zlog_env_lock);
196 	if (rc) {
197 		zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc);
198 		return -1;
199 	}
200 	return 0;
201 err:
202 	zc_error("------dzlog_init fail end------");
203 	rc = pthread_rwlock_unlock(&zlog_env_lock);
204 	if (rc) {
205 		zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc);
206 		return -1;
207 	}
208 	return -1;
209 }
210 /*******************************************************************************/
zlog_reload(const char * confpath)211 int zlog_reload(const char *confpath)
212 {
213 	int rc = 0;
214 	int i = 0;
215 	zlog_conf_t *new_conf = NULL;
216 	zlog_rule_t *a_rule;
217 	int c_up = 0;
218 
219 	zc_debug("------zlog_reload start------");
220 	rc = pthread_rwlock_wrlock(&zlog_env_lock);
221 	if (rc) {
222 		zc_error("pthread_rwlock_wrlock fail, rc[%d]", rc);
223 		return -1;
224 	}
225 
226 	if (!zlog_env_is_init) {
227 		zc_error("never call zlog_init() or dzlog_init() before");
228 		goto quit;
229 	}
230 
231 	/* use last conf file */
232 	if (confpath == NULL) confpath = zlog_env_conf->file;
233 
234 	/* reach reload period */
235 	if (confpath == (char*)-1) {
236 		/* test again, avoid other threads already reloaded */
237 		if (zlog_env_reload_conf_count > zlog_env_conf->reload_conf_period) {
238 			confpath = zlog_env_conf->file;
239 		} else {
240 			/* do nothing, already done */
241 			goto quit;
242 		}
243 	}
244 
245 	/* reset counter, whether automaticlly or mannually */
246 	zlog_env_reload_conf_count = 0;
247 
248 	new_conf = zlog_conf_new(confpath);
249 	if (!new_conf) {
250 		zc_error("zlog_conf_new fail");
251 		goto err;
252 	}
253 
254 	zc_arraylist_foreach(new_conf->rules, i, a_rule) {
255 		zlog_rule_set_record(a_rule, zlog_env_records);
256 	}
257 
258 	if (zlog_category_table_update_rules(zlog_env_categories, new_conf->rules)) {
259 		c_up = 0;
260 		zc_error("zlog_category_table_update fail");
261 		goto err;
262 	} else {
263 		c_up = 1;
264 	}
265 
266 	zlog_env_init_version++;
267 
268 	if (c_up) zlog_category_table_commit_rules(zlog_env_categories);
269 	zlog_conf_del(zlog_env_conf);
270 	zlog_env_conf = new_conf;
271 	zc_debug("------zlog_reload success, total init verison[%d] ------", zlog_env_init_version);
272 	rc = pthread_rwlock_unlock(&zlog_env_lock);
273 	if (rc) {
274 		zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc);
275 		return -1;
276 	}
277 	return 0;
278 err:
279 	/* fail, roll back everything */
280 	zc_warn("zlog_reload fail, use old conf file, still working");
281 	if (new_conf) zlog_conf_del(new_conf);
282 	if (c_up) zlog_category_table_rollback_rules(zlog_env_categories);
283 	zc_error("------zlog_reload fail, total init version[%d] ------", zlog_env_init_version);
284 	rc = pthread_rwlock_unlock(&zlog_env_lock);
285 	if (rc) {
286 		zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc);
287 		return -1;
288 	}
289 	return -1;
290 quit:
291 	zc_debug("------zlog_reload do nothing------");
292 	rc = pthread_rwlock_unlock(&zlog_env_lock);
293 	if (rc) {
294 		zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc);
295 		return -1;
296 	}
297 	return 0;
298 }
299 /*******************************************************************************/
zlog_fini(void)300 void zlog_fini(void)
301 {
302 	int rc = 0;
303 
304 	zc_debug("------zlog_fini start------");
305 	rc = pthread_rwlock_wrlock(&zlog_env_lock);
306 	if (rc) {
307 		zc_error("pthread_rwlock_wrlock fail, rc[%d]", rc);
308 		return;
309 	}
310 
311 	if (!zlog_env_is_init) {
312 		zc_error("before finish, must zlog_init() or dzlog_init() fisrt");
313 		goto exit;
314 	}
315 
316 	zlog_fini_inner();
317 	zlog_env_is_init = 0;
318 
319 exit:
320 	zc_debug("------zlog_fini end------");
321 	rc = pthread_rwlock_unlock(&zlog_env_lock);
322 	if (rc) {
323 		zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc);
324 		return;
325 	}
326 	return;
327 }
328 /*******************************************************************************/
zlog_get_category(const char * cname)329 zlog_category_t *zlog_get_category(const char *cname)
330 {
331 	int rc = 0;
332 	zlog_category_t *a_category = NULL;
333 
334 	zc_assert(cname, NULL);
335 	zc_debug("------zlog_get_category[%s] start------", cname);
336 	rc = pthread_rwlock_wrlock(&zlog_env_lock);
337 	if (rc) {
338 		zc_error("pthread_rwlock_wrlock fail, rc[%d]", rc);
339 		return NULL;
340 	}
341 
342 	if (!zlog_env_is_init) {
343 		zc_error("never call zlog_init() or dzlog_init() before");
344 		a_category = NULL;
345 		goto err;
346 	}
347 
348 	a_category = zlog_category_table_fetch_category(
349 				zlog_env_categories,
350 				cname,
351 				zlog_env_conf->rules);
352 	if (!a_category) {
353 		zc_error("zlog_category_table_fetch_category[%s] fail", cname);
354 		goto err;
355 	}
356 
357 	zc_debug("------zlog_get_category[%s] success, end------ ", cname);
358 	rc = pthread_rwlock_unlock(&zlog_env_lock);
359 	if (rc) {
360 		zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc);
361 		return NULL;
362 	}
363 	return a_category;
364 err:
365 	zc_error("------zlog_get_category[%s] fail, end------ ", cname);
366 	rc = pthread_rwlock_unlock(&zlog_env_lock);
367 	if (rc) {
368 		zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc);
369 		return NULL;
370 	}
371 	return NULL;
372 }
373 
dzlog_set_category(const char * cname)374 int dzlog_set_category(const char *cname)
375 {
376 	int rc = 0;
377 	zc_assert(cname, -1);
378 
379 	zc_debug("------dzlog_set_category[%s] start------", cname);
380 	rc = pthread_rwlock_wrlock(&zlog_env_lock);
381 	if (rc) {
382 		zc_error("pthread_rwlock_wrlock fail, rc[%d]", rc);
383 		return -1;
384 	}
385 
386 	if (!zlog_env_is_init) {
387 		zc_error("never call zlog_init() or dzlog_init() before");
388 		goto err;
389 	}
390 
391 	zlog_default_category = zlog_category_table_fetch_category(
392 				zlog_env_categories,
393 				cname,
394 				zlog_env_conf->rules);
395 	if (!zlog_default_category) {
396 		zc_error("zlog_category_table_fetch_category[%s] fail", cname);
397 		goto err;
398 	}
399 
400 	zc_debug("------dzlog_set_category[%s] end, success------ ", cname);
401 	rc = pthread_rwlock_unlock(&zlog_env_lock);
402 	if (rc) {
403 		zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc);
404 		return -1;
405 	}
406 	return 0;
407 err:
408 	zc_error("------dzlog_set_category[%s] end, fail------ ", cname);
409 	rc = pthread_rwlock_unlock(&zlog_env_lock);
410 	if (rc) {
411 		zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc);
412 		return -1;
413 	}
414 	return -1;
415 }
416 /*******************************************************************************/
417 #define zlog_fetch_thread(a_thread, fail_goto) do {  \
418 	int rd = 0;  \
419 	a_thread = pthread_getspecific(zlog_thread_key);  \
420 	if (!a_thread) {  \
421 		a_thread = zlog_thread_new(zlog_env_init_version,  \
422 				zlog_env_conf->buf_size_min, zlog_env_conf->buf_size_max, \
423 				zlog_env_conf->time_cache_count); \
424 		if (!a_thread) {  \
425 			zc_error("zlog_thread_new fail");  \
426 			goto fail_goto;  \
427 		}  \
428   \
429 		rd = pthread_setspecific(zlog_thread_key, a_thread);  \
430 		if (rd) {  \
431 			zlog_thread_del(a_thread);  \
432 			zc_error("pthread_setspecific fail, rd[%d]", rd);  \
433 			goto fail_goto;  \
434 		}  \
435 	}  \
436   \
437 	if (a_thread->init_version != zlog_env_init_version) {  \
438 		/* as mdc is still here, so can not easily del and new */ \
439 		rd = zlog_thread_rebuild_msg_buf(a_thread, \
440 				zlog_env_conf->buf_size_min, \
441 				zlog_env_conf->buf_size_max);  \
442 		if (rd) {  \
443 			zc_error("zlog_thread_resize_msg_buf fail, rd[%d]", rd);  \
444 			goto fail_goto;  \
445 		}  \
446   \
447 		rd = zlog_thread_rebuild_event(a_thread, zlog_env_conf->time_cache_count);  \
448 		if (rd) {  \
449 			zc_error("zlog_thread_resize_msg_buf fail, rd[%d]", rd);  \
450 			goto fail_goto;  \
451 		}  \
452 		a_thread->init_version = zlog_env_init_version;  \
453 	}  \
454 } while (0)
455 
456 /*******************************************************************************/
zlog_put_mdc(const char * key,const char * value)457 int zlog_put_mdc(const char *key, const char *value)
458 {
459 	int rc = 0;
460 	zlog_thread_t *a_thread;
461 
462 	zc_assert(key, -1);
463 	zc_assert(value, -1);
464 
465 	rc = pthread_rwlock_rdlock(&zlog_env_lock);
466 	if (rc) {
467 		zc_error("pthread_rwlock_wrlock fail, rc[%d]", rc);
468 		return -1;
469 	}
470 
471 	if (!zlog_env_is_init) {
472 		zc_error("never call zlog_init() or dzlog_init() before");
473 		goto err;
474 	}
475 
476 	zlog_fetch_thread(a_thread, err);
477 
478 	if (zlog_mdc_put(a_thread->mdc, key, value)) {
479 		zc_error("zlog_mdc_put fail, key[%s], value[%s]", key, value);
480 		goto err;
481 	}
482 
483 	rc = pthread_rwlock_unlock(&zlog_env_lock);
484 	if (rc) {
485 		zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc);
486 		return -1;
487 	}
488 	return 0;
489 err:
490 	rc = pthread_rwlock_unlock(&zlog_env_lock);
491 	if (rc) {
492 		zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc);
493 		return -1;
494 	}
495 	return -1;
496 }
497 
zlog_get_mdc(char * key)498 char *zlog_get_mdc(char *key)
499 {
500 	int rc = 0;
501 	char *value = NULL;
502 	zlog_thread_t *a_thread;
503 
504 	zc_assert(key, NULL);
505 
506 	rc = pthread_rwlock_rdlock(&zlog_env_lock);
507 	if (rc) {
508 		zc_error("pthread_rwlock_rdlock fail, rc[%d]", rc);
509 		return NULL;
510 	}
511 
512 	if (!zlog_env_is_init) {
513 		zc_error("never call zlog_init() or dzlog_init() before");
514 		goto err;
515 	}
516 
517 	a_thread = pthread_getspecific(zlog_thread_key);
518 	if (!a_thread) {
519 		zc_error("thread not found, maybe not use zlog_put_mdc before");
520 		goto err;
521 	}
522 
523 	value = zlog_mdc_get(a_thread->mdc, key);
524 	if (!value) {
525 		zc_error("key[%s] not found in mdc", key);
526 		goto err;
527 	}
528 
529 	rc = pthread_rwlock_unlock(&zlog_env_lock);
530 	if (rc) {
531 		zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc);
532 		return NULL;
533 	}
534 	return value;
535 err:
536 	rc = pthread_rwlock_unlock(&zlog_env_lock);
537 	if (rc) {
538 		zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc);
539 		return NULL;
540 	}
541 	return NULL;
542 }
543 
zlog_remove_mdc(char * key)544 void zlog_remove_mdc(char *key)
545 {
546 	int rc = 0;
547 	zlog_thread_t *a_thread;
548 
549 	zc_assert(key, );
550 
551 	rc = pthread_rwlock_rdlock(&zlog_env_lock);
552 	if (rc) {
553 		zc_error("pthread_rwlock_rdlock fail, rc[%d]", rc);
554 		return;
555 	}
556 
557 	if (!zlog_env_is_init) {
558 		zc_error("never call zlog_init() or dzlog_init() before");
559 		goto exit;
560 	}
561 
562 	a_thread = pthread_getspecific(zlog_thread_key);
563 	if (!a_thread) {
564 		zc_error("thread not found, maybe not use zlog_put_mdc before");
565 		goto exit;
566 	}
567 
568 	zlog_mdc_remove(a_thread->mdc, key);
569 
570 exit:
571 	rc = pthread_rwlock_unlock(&zlog_env_lock);
572 	if (rc) {
573 		zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc);
574 		return;
575 	}
576 	return;
577 }
578 
zlog_clean_mdc(void)579 void zlog_clean_mdc(void)
580 {
581 	int rc = 0;
582 	zlog_thread_t *a_thread;
583 
584 	rc = pthread_rwlock_rdlock(&zlog_env_lock);
585 	if (rc) {;
586 		zc_error("pthread_rwlock_rdlock fail, rc[%d]", rc);
587 		return;
588 	}
589 
590 	if (!zlog_env_is_init) {
591 		zc_error("never call zlog_init() or dzlog_init() before");
592 		goto exit;
593 	}
594 
595 	a_thread = pthread_getspecific(zlog_thread_key);
596 	if (!a_thread) {
597 		zc_error("thread not found, maybe not use zlog_put_mdc before");
598 		goto exit;
599 	}
600 
601 	zlog_mdc_clean(a_thread->mdc);
602 
603 exit:
604 	rc = pthread_rwlock_unlock(&zlog_env_lock);
605 	if (rc) {
606 		zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc);
607 		return;
608 	}
609 	return;
610 }
611 
612 /*******************************************************************************/
vzlog(zlog_category_t * category,const char * file,size_t filelen,const char * func,size_t funclen,long line,int level,const char * format,va_list args)613 void vzlog(zlog_category_t * category,
614 	const char *file, size_t filelen,
615 	const char *func, size_t funclen,
616 	long line, int level,
617 	const char *format, va_list args)
618 {
619 	zlog_thread_t *a_thread;
620 
621 	/* The bitmap determination here is not under the protection of rdlock.
622 	 * It may be changed by other CPU by zlog_reload() halfway.
623 	 *
624 	 * Old or strange value may be read here,
625 	 * but it is safe, the bitmap is valid as long as category exist,
626 	 * And will be the right value after zlog_reload()
627 	 *
628 	 * For speed up, if one log will not be ouput,
629 	 * There is no need to aquire rdlock.
630 	 */
631 	if (zlog_category_needless_level(category, level)) return;
632 
633 	pthread_rwlock_rdlock(&zlog_env_lock);
634 
635 	if (!zlog_env_is_init) {
636 		zc_error("never call zlog_init() or dzlog_init() before");
637 		goto exit;
638 	}
639 
640 	zlog_fetch_thread(a_thread, exit);
641 
642 	zlog_event_set_fmt(a_thread->event,
643 		category->name, category->name_len,
644 		file, filelen, func, funclen, line, level,
645 		format, args);
646 
647 	if (zlog_category_output(category, a_thread)) {
648 		zc_error("zlog_output fail, srcfile[%s], srcline[%ld]", file, line);
649 		goto exit;
650 	}
651 
652 	if (zlog_env_conf->reload_conf_period &&
653 		++zlog_env_reload_conf_count > zlog_env_conf->reload_conf_period ) {
654 		/* under the protection of lock read env conf */
655 		goto reload;
656 	}
657 
658 exit:
659 	pthread_rwlock_unlock(&zlog_env_lock);
660 	return;
661 reload:
662 	pthread_rwlock_unlock(&zlog_env_lock);
663 	/* will be wrlock, so after unlock */
664 	if (zlog_reload((char *)-1)) {
665 		zc_error("reach reload-conf-period but zlog_reload fail, zlog-chk-conf [file] see detail");
666 	}
667 	return;
668 }
669 
hzlog(zlog_category_t * category,const char * file,size_t filelen,const char * func,size_t funclen,long line,int level,const void * buf,size_t buflen)670 void hzlog(zlog_category_t *category,
671 	const char *file, size_t filelen,
672 	const char *func, size_t funclen,
673 	long line, int level,
674 	const void *buf, size_t buflen)
675 {
676 	zlog_thread_t *a_thread;
677 
678 	if (zlog_category_needless_level(category, level)) return;
679 
680 	pthread_rwlock_rdlock(&zlog_env_lock);
681 
682 	if (!zlog_env_is_init) {
683 		zc_error("never call zlog_init() or dzlog_init() before");
684 		goto exit;
685 	}
686 
687 	zlog_fetch_thread(a_thread, exit);
688 
689 	zlog_event_set_hex(a_thread->event,
690 		category->name, category->name_len,
691 		file, filelen, func, funclen, line, level,
692 		buf, buflen);
693 
694 	if (zlog_category_output(category, a_thread)) {
695 		zc_error("zlog_output fail, srcfile[%s], srcline[%ld]", file, line);
696 		goto exit;
697 	}
698 
699 	if (zlog_env_conf->reload_conf_period &&
700 		++zlog_env_reload_conf_count > zlog_env_conf->reload_conf_period ) {
701 		/* under the protection of lock read env conf */
702 		goto reload;
703 	}
704 
705 exit:
706 	pthread_rwlock_unlock(&zlog_env_lock);
707 	return;
708 reload:
709 	pthread_rwlock_unlock(&zlog_env_lock);
710 	/* will be wrlock, so after unlock */
711 	if (zlog_reload((char *)-1)) {
712 		zc_error("reach reload-conf-period but zlog_reload fail, zlog-chk-conf [file] see detail");
713 	}
714 	return;
715 }
716 
717 /*******************************************************************************/
718 /* for speed up, copy from vzlog */
vdzlog(const char * file,size_t filelen,const char * func,size_t funclen,long line,int level,const char * format,va_list args)719 void vdzlog(const char *file, size_t filelen,
720 	const char *func, size_t funclen,
721 	long line, int level,
722 	const char *format, va_list args)
723 {
724 	zlog_thread_t *a_thread;
725 
726 	if (zlog_category_needless_level(zlog_default_category, level)) return;
727 
728 	pthread_rwlock_rdlock(&zlog_env_lock);
729 
730 	if (!zlog_env_is_init) {
731 		zc_error("never call zlog_init() or dzlog_init() before");
732 		goto exit;
733 	}
734 
735 	/* that's the differnce, must judge default_category in lock */
736 	if (!zlog_default_category) {
737 		zc_error("zlog_default_category is null,"
738 			"dzlog_init() or dzlog_set_cateogry() is not called above");
739 		goto exit;
740 	}
741 
742 	zlog_fetch_thread(a_thread, exit);
743 
744 	zlog_event_set_fmt(a_thread->event,
745 		zlog_default_category->name, zlog_default_category->name_len,
746 		file, filelen, func, funclen, line, level,
747 		format, args);
748 
749 	if (zlog_category_output(zlog_default_category, a_thread)) {
750 		zc_error("zlog_output fail, srcfile[%s], srcline[%ld]", file, line);
751 		goto exit;
752 	}
753 
754 	if (zlog_env_conf->reload_conf_period &&
755 		++zlog_env_reload_conf_count > zlog_env_conf->reload_conf_period ) {
756 		/* under the protection of lock read env conf */
757 		goto reload;
758 	}
759 
760 exit:
761 	pthread_rwlock_unlock(&zlog_env_lock);
762 	return;
763 reload:
764 	pthread_rwlock_unlock(&zlog_env_lock);
765 	/* will be wrlock, so after unlock */
766 	if (zlog_reload((char *)-1)) {
767 		zc_error("reach reload-conf-period but zlog_reload fail, zlog-chk-conf [file] see detail");
768 	}
769 	return;
770 }
771 
hdzlog(const char * file,size_t filelen,const char * func,size_t funclen,long line,int level,const void * buf,size_t buflen)772 void hdzlog(const char *file, size_t filelen,
773 	const char *func, size_t funclen,
774 	long line, int level,
775 	const void *buf, size_t buflen)
776 {
777 	zlog_thread_t *a_thread;
778 
779 	if (zlog_category_needless_level(zlog_default_category, level)) return;
780 
781 	pthread_rwlock_rdlock(&zlog_env_lock);
782 
783 	if (!zlog_env_is_init) {
784 		zc_error("never call zlog_init() or dzlog_init() before");
785 		goto exit;
786 	}
787 
788 	/* that's the differnce, must judge default_category in lock */
789 	if (!zlog_default_category) {
790 		zc_error("zlog_default_category is null,"
791 			"dzlog_init() or dzlog_set_cateogry() is not called above");
792 		goto exit;
793 	}
794 
795 	zlog_fetch_thread(a_thread, exit);
796 
797 	zlog_event_set_hex(a_thread->event,
798 		zlog_default_category->name, zlog_default_category->name_len,
799 		file, filelen, func, funclen, line, level,
800 		buf, buflen);
801 
802 	if (zlog_category_output(zlog_default_category, a_thread)) {
803 		zc_error("zlog_output fail, srcfile[%s], srcline[%ld]", file, line);
804 		goto exit;
805 	}
806 
807 	if (zlog_env_conf->reload_conf_period &&
808 		++zlog_env_reload_conf_count > zlog_env_conf->reload_conf_period ) {
809 		/* under the protection of lock read env conf */
810 		goto reload;
811 	}
812 
813 exit:
814 	pthread_rwlock_unlock(&zlog_env_lock);
815 	return;
816 reload:
817 	pthread_rwlock_unlock(&zlog_env_lock);
818 	/* will be wrlock, so after unlock */
819 	if (zlog_reload((char *)-1)) {
820 		zc_error("reach reload-conf-period but zlog_reload fail, zlog-chk-conf [file] see detail");
821 	}
822 	return;
823 }
824 
825 /*******************************************************************************/
zlog(zlog_category_t * category,const char * file,size_t filelen,const char * func,size_t funclen,long line,const int level,const char * format,...)826 void zlog(zlog_category_t * category,
827 	const char *file, size_t filelen, const char *func, size_t funclen,
828 	long line, const int level,
829 	const char *format, ...)
830 {
831 	zlog_thread_t *a_thread;
832 	va_list args;
833 
834 	if (category && zlog_category_needless_level(category, level)) return;
835 
836 	pthread_rwlock_rdlock(&zlog_env_lock);
837 
838 	if (!zlog_env_is_init) {
839 		zc_error("never call zlog_init() or dzlog_init() before");
840 		goto exit;
841 	}
842 
843 	zlog_fetch_thread(a_thread, exit);
844 
845 	va_start(args, format);
846 	zlog_event_set_fmt(a_thread->event, category->name, category->name_len,
847 		file, filelen, func, funclen, line, level,
848 		format, args);
849 	if (zlog_category_output(category, a_thread)) {
850 		zc_error("zlog_output fail, srcfile[%s], srcline[%ld]", file, line);
851 		va_end(args);
852 		goto exit;
853 	}
854 	va_end(args);
855 
856 	if (zlog_env_conf->reload_conf_period &&
857 		++zlog_env_reload_conf_count > zlog_env_conf->reload_conf_period ) {
858 		/* under the protection of lock read env conf */
859 		goto reload;
860 	}
861 
862 exit:
863 	pthread_rwlock_unlock(&zlog_env_lock);
864 	return;
865 reload:
866 	pthread_rwlock_unlock(&zlog_env_lock);
867 	/* will be wrlock, so after unlock */
868 	if (zlog_reload((char *)-1)) {
869 		zc_error("reach reload-conf-period but zlog_reload fail, zlog-chk-conf [file] see detail");
870 	}
871 	return;
872 }
873 
874 /*******************************************************************************/
dzlog(const char * file,size_t filelen,const char * func,size_t funclen,long line,int level,const char * format,...)875 void dzlog(const char *file, size_t filelen, const char *func, size_t funclen, long line, int level,
876 	const char *format, ...)
877 {
878 	zlog_thread_t *a_thread;
879 	va_list args;
880 
881 
882 	pthread_rwlock_rdlock(&zlog_env_lock);
883 
884 	if (!zlog_env_is_init) {
885 		zc_error("never call zlog_init() or dzlog_init() before");
886 		goto exit;
887 	}
888 
889 	/* that's the differnce, must judge default_category in lock */
890 	if (!zlog_default_category) {
891 		zc_error("zlog_default_category is null,"
892 			"dzlog_init() or dzlog_set_cateogry() is not called above");
893 		goto exit;
894 	}
895 
896 	if (zlog_category_needless_level(zlog_default_category, level)) goto exit;
897 
898 	zlog_fetch_thread(a_thread, exit);
899 
900 	va_start(args, format);
901 	zlog_event_set_fmt(a_thread->event,
902 		zlog_default_category->name, zlog_default_category->name_len,
903 		file, filelen, func, funclen, line, level,
904 		format, args);
905 
906 	if (zlog_category_output(zlog_default_category, a_thread)) {
907 		zc_error("zlog_output fail, srcfile[%s], srcline[%ld]", file, line);
908 		va_end(args);
909 		goto exit;
910 	}
911 	va_end(args);
912 
913 	if (zlog_env_conf->reload_conf_period &&
914 		++zlog_env_reload_conf_count > zlog_env_conf->reload_conf_period ) {
915 		/* under the protection of lock read env conf */
916 		goto reload;
917 	}
918 
919 exit:
920 	pthread_rwlock_unlock(&zlog_env_lock);
921 	return;
922 reload:
923 	pthread_rwlock_unlock(&zlog_env_lock);
924 	/* will be wrlock, so after unlock */
925 	if (zlog_reload((char *)-1)) {
926 		zc_error("reach reload-conf-period but zlog_reload fail, zlog-chk-conf [file] see detail");
927 	}
928 	return;
929 }
930 
931 /*******************************************************************************/
zlog_profile(void)932 void zlog_profile(void)
933 {
934 	int rc = 0;
935 	rc = pthread_rwlock_rdlock(&zlog_env_lock);
936 	if (rc) {
937 		zc_error("pthread_rwlock_wrlock fail, rc[%d]", rc);
938 		return;
939 	}
940 	zc_warn("------zlog_profile start------ ");
941 	zc_warn("is init:[%d]", zlog_env_is_init);
942 	zc_warn("init version:[%d]", zlog_env_init_version);
943 	zlog_conf_profile(zlog_env_conf, ZC_WARN);
944 	zlog_record_table_profile(zlog_env_records, ZC_WARN);
945 	zlog_category_table_profile(zlog_env_categories, ZC_WARN);
946 	if (zlog_default_category) {
947 		zc_warn("-default_category-");
948 		zlog_category_profile(zlog_default_category, ZC_WARN);
949 	}
950 	zc_warn("------zlog_profile end------ ");
951 	rc = pthread_rwlock_unlock(&zlog_env_lock);
952 	if (rc) {
953 		zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc);
954 		return;
955 	}
956 	return;
957 }
958 /*******************************************************************************/
zlog_set_record(const char * rname,zlog_record_fn record_output)959 int zlog_set_record(const char *rname, zlog_record_fn record_output)
960 {
961 	int rc = 0;
962 	int rd = 0;
963 	zlog_rule_t *a_rule;
964 	zlog_record_t *a_record;
965 	int i = 0;
966 
967 	zc_assert(rname, -1);
968 	zc_assert(record_output, -1);
969 
970 	rd = pthread_rwlock_wrlock(&zlog_env_lock);
971 	if (rd) {
972 		zc_error("pthread_rwlock_rdlock fail, rd[%d]", rd);
973 		return -1;
974 	}
975 
976 	if (!zlog_env_is_init) {
977 		zc_error("never call zlog_init() or dzlog_init() before");
978 		goto zlog_set_record_exit;
979 	}
980 
981 	a_record = zlog_record_new(rname, record_output);
982 	if (!a_record) {
983 		rc = -1;
984 		zc_error("zlog_record_new fail");
985 		goto zlog_set_record_exit;
986 	}
987 
988 	rc = zc_hashtable_put(zlog_env_records, a_record->name, a_record);
989 	if (rc) {
990 		zlog_record_del(a_record);
991 		zc_error("zc_hashtable_put fail");
992 		goto zlog_set_record_exit;
993 	}
994 
995 	zc_arraylist_foreach(zlog_env_conf->rules, i, a_rule) {
996 		zlog_rule_set_record(a_rule, zlog_env_records);
997 	}
998 
999       zlog_set_record_exit:
1000 	rd = pthread_rwlock_unlock(&zlog_env_lock);
1001 	if (rd) {
1002 		zc_error("pthread_rwlock_unlock fail, rd=[%d]", rd);
1003 		return -1;
1004 	}
1005 	return rc;
1006 }
1007