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 #include "fmacros.h"
9 #include <string.h>
10 #include <stdlib.h>
11 #include <errno.h>
12 
13 #include "category.h"
14 #include "rule.h"
15 #include "zc_defs.h"
16 
zlog_category_profile(zlog_category_t * a_category,int flag)17 void zlog_category_profile(zlog_category_t *a_category, int flag)
18 {
19 	int i;
20 	zlog_rule_t *a_rule;
21 
22 	zc_assert(a_category,);
23 	zc_profile(flag, "--category[%p][%s][%p]--",
24 			a_category,
25 			a_category->name,
26 			a_category->fit_rules);
27 	if (a_category->fit_rules) {
28 		zc_arraylist_foreach(a_category->fit_rules, i, a_rule) {
29 			zlog_rule_profile(a_rule, flag);
30 		}
31 	}
32 	return;
33 }
34 
35 /*******************************************************************************/
zlog_category_del(zlog_category_t * a_category)36 void zlog_category_del(zlog_category_t * a_category)
37 {
38 	zc_assert(a_category,);
39 	if (a_category->fit_rules) zc_arraylist_del(a_category->fit_rules);
40 	free(a_category);
41 	zc_debug("zlog_category_del[%p]", a_category);
42 	return;
43 }
44 
45 /* overlap one rule's level bitmap to cateogry,
46  * so category can judge whether a log level will be output by itself
47  * It is safe when configure is reloaded, when rule will be released an recreated
48  */
zlog_cateogry_overlap_bitmap(zlog_category_t * a_category,zlog_rule_t * a_rule)49 static void zlog_cateogry_overlap_bitmap(zlog_category_t * a_category, zlog_rule_t *a_rule)
50 {
51 	int i;
52 	for(i = 0; i < sizeof(a_rule->level_bitmap); i++) {
53 		a_category->level_bitmap[i] |= a_rule->level_bitmap[i];
54 	}
55 }
56 
zlog_category_obtain_rules(zlog_category_t * a_category,zc_arraylist_t * rules)57 static int zlog_category_obtain_rules(zlog_category_t * a_category, zc_arraylist_t * rules)
58 {
59 	int i;
60 	int count = 0;
61 	int fit = 0;
62 	zlog_rule_t *a_rule;
63 	zlog_rule_t *wastebin_rule = NULL;
64 
65 	/* before set, clean last fit rules first */
66 	if (a_category->fit_rules) zc_arraylist_del(a_category->fit_rules);
67 
68 	memset(a_category->level_bitmap, 0x00, sizeof(a_category->level_bitmap));
69 
70 	a_category->fit_rules = zc_arraylist_new(NULL);
71 	if (!(a_category->fit_rules)) {
72 		zc_error("zc_arraylist_new fail");
73 		return -1;
74 	}
75 
76 	/* get match rules from all rules */
77 	zc_arraylist_foreach(rules, i, a_rule) {
78 		fit = zlog_rule_match_category(a_rule, a_category->name);
79 		if (fit) {
80 			if (zc_arraylist_add(a_category->fit_rules, a_rule)) {
81 				zc_error("zc_arrylist_add fail");
82 				goto err;
83 			}
84 			zlog_cateogry_overlap_bitmap(a_category, a_rule);
85 			count++;
86 		}
87 
88 		if (zlog_rule_is_wastebin(a_rule)) {
89 			wastebin_rule = a_rule;
90 		}
91 	}
92 
93 	if (count == 0) {
94 		if (wastebin_rule) {
95 			zc_debug("category[%s], no match rules, use wastebin_rule", a_category->name);
96 			if (zc_arraylist_add(a_category->fit_rules, wastebin_rule)) {
97 				zc_error("zc_arrylist_add fail");
98 				goto err;
99 			}
100 			zlog_cateogry_overlap_bitmap(a_category, wastebin_rule);
101 			count++;
102 		} else {
103 			zc_debug("category[%s], no match rules & no wastebin_rule", a_category->name);
104 		}
105 	}
106 
107 	return 0;
108 err:
109 	zc_arraylist_del(a_category->fit_rules);
110 	a_category->fit_rules = NULL;
111 	return -1;
112 }
113 
zlog_category_new(const char * name,zc_arraylist_t * rules)114 zlog_category_t *zlog_category_new(const char *name, zc_arraylist_t * rules)
115 {
116 	size_t len;
117 	zlog_category_t *a_category;
118 
119 	zc_assert(name, NULL);
120 	zc_assert(rules, NULL);
121 
122 	len = strlen(name);
123 	if (len > sizeof(a_category->name) - 1) {
124 		zc_error("name[%s] too long", name);
125 		return NULL;
126 	}
127 	a_category = calloc(1, sizeof(zlog_category_t));
128 	if (!a_category) {
129 		zc_error("calloc fail, errno[%d]", errno);
130 		return NULL;
131 	}
132 	strcpy(a_category->name, name);
133 	a_category->name_len = len;
134 	if (zlog_category_obtain_rules(a_category, rules)) {
135 		zc_error("zlog_category_fit_rules fail");
136 		goto err;
137 	}
138 
139 	zlog_category_profile(a_category, ZC_DEBUG);
140 	return a_category;
141 err:
142 	zlog_category_del(a_category);
143 	return NULL;
144 }
145 /*******************************************************************************/
146 /* update success: fit_rules 1, fit_rules_backup 1 */
147 /* update fail: fit_rules 0, fit_rules_backup 1 */
zlog_category_update_rules(zlog_category_t * a_category,zc_arraylist_t * new_rules)148 int zlog_category_update_rules(zlog_category_t * a_category, zc_arraylist_t * new_rules)
149 {
150 	zc_assert(a_category, -1);
151 	zc_assert(new_rules, -1);
152 
153 	/* 1st, mv fit_rules fit_rules_backup */
154 	if (a_category->fit_rules_backup) zc_arraylist_del(a_category->fit_rules_backup);
155 	a_category->fit_rules_backup = a_category->fit_rules;
156 	a_category->fit_rules = NULL;
157 
158 	memcpy(a_category->level_bitmap_backup, a_category->level_bitmap,
159 			sizeof(a_category->level_bitmap));
160 
161 	/* 2nd, obtain new_rules to fit_rules */
162 	if (zlog_category_obtain_rules(a_category, new_rules)) {
163 		zc_error("zlog_category_obtain_rules fail");
164 		a_category->fit_rules = NULL;
165 		return -1;
166 	}
167 
168 	/* keep the fit_rules_backup not change, return */
169 	return 0;
170 }
171 
172 /* commit fail: fit_rules_backup != 0 */
173 /* commit success: fit_rules 1, fit_rules_backup 0 */
zlog_category_commit_rules(zlog_category_t * a_category)174 void zlog_category_commit_rules(zlog_category_t * a_category)
175 {
176 	zc_assert(a_category,);
177 	if (!a_category->fit_rules_backup) {
178 		zc_warn("a_category->fit_rules_backup is NULL, never update before");
179 		return;
180 	}
181 
182 	zc_arraylist_del(a_category->fit_rules_backup);
183 	a_category->fit_rules_backup = NULL;
184 	memset(a_category->level_bitmap_backup, 0x00,
185 			sizeof(a_category->level_bitmap_backup));
186 	return;
187 }
188 
189 /* rollback fail: fit_rules_backup != 0 */
190 /* rollback success: fit_rules 1, fit_rules_backup 0 */
191 /* so whether update succes or not, make things back to old */
zlog_category_rollback_rules(zlog_category_t * a_category)192 void zlog_category_rollback_rules(zlog_category_t * a_category)
193 {
194 	zc_assert(a_category,);
195 	if (!a_category->fit_rules_backup) {
196 		zc_warn("a_category->fit_rules_backup in NULL, never update before");
197 		return;
198 	}
199 
200 	if (a_category->fit_rules) {
201 		/* update success, rm new and backup */
202 		zc_arraylist_del(a_category->fit_rules);
203 		a_category->fit_rules = a_category->fit_rules_backup;
204 		a_category->fit_rules_backup = NULL;
205 	} else {
206 		/* update fail, just backup */
207 		a_category->fit_rules = a_category->fit_rules_backup;
208 		a_category->fit_rules_backup = NULL;
209 	}
210 
211 	memcpy(a_category->level_bitmap, a_category->level_bitmap_backup,
212 			sizeof(a_category->level_bitmap));
213 	memset(a_category->level_bitmap_backup, 0x00,
214 			sizeof(a_category->level_bitmap_backup));
215 
216 	return; /* always success */
217 }
218 
219 /*******************************************************************************/
220 
zlog_category_output(zlog_category_t * a_category,zlog_thread_t * a_thread)221 int zlog_category_output(zlog_category_t * a_category, zlog_thread_t * a_thread)
222 {
223 	int i;
224 	int rc = 0;
225 	zlog_rule_t *a_rule;
226 
227 	/* go through all match rules to output */
228 	zc_arraylist_foreach(a_category->fit_rules, i, a_rule) {
229 		rc = zlog_rule_output(a_rule, a_thread);
230 	}
231 
232 	return rc;
233 }
234