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