1/*
2 INTEL CONFIDENTIAL
3 Copyright 2009 Intel Corporation All Rights Reserved.
4 The source code contained or described herein and all documents related to the source code ("Material") are owned by Intel Corporation or its suppliers or licensors. Title to the Material remains with Intel Corporation or its suppliers and licensors. The Material contains trade secrets and proprietary and confidential information of Intel or its suppliers and licensors. The Material is protected by worldwide copyright and trade secret laws and treaty provisions. No part of the Material may be used, copied, reproduced, modified, published, uploaded, posted, transmitted, distributed, or disclosed in any way without Intel’s prior express written permission.
5
6 No license under any patent, copyright, trade secret or other intellectual property right is granted to or conferred upon you by disclosure or delivery of the Materials, either expressly, by implication, inducement, estoppel or otherwise. Any license under such intellectual property rights must be express and approved by Intel in writing.
7 */
8
9#include <glib.h>
10#include <string.h>
11#include "mixlog.h"
12
13#define MIX_DELOG_COMPS "MIX_DELOG_COMPS"
14#define MIX_DELOG_FILES "MIX_DELOG_FILES"
15#define MIX_DELOG_FUNCS "MIX_DELOG_FUNCS"
16#define MIX_LOG_ENABLE "MIX_LOG_ENABLE"
17#define MIX_DELOG_DELIMITERS " ,;"
18
19#define MIX_LOG_LEVEL "MIX_LOG_LEVEL"
20
21static GStaticMutex g_mutex = G_STATIC_MUTEX_INIT;
22
23#ifdef MIX_LOG_USE_HT
24static GHashTable *g_defile_ht = NULL, *g_defunc_ht = NULL, *g_decom_ht = NULL;
25static gint g_mix_log_level = MIX_LOG_LEVEL_VERBOSE;
26static gint g_refcount = 0;
27
28#define mix_log_destroy_ht(ht) if(ht) { g_hash_table_destroy(ht); ht = NULL; }
29
30void mix_log_get_ht(GHashTable **ht, const gchar *var) {
31
32	const char *delog_list = NULL;
33	char *item = NULL;
34	if (!ht || !var) {
35		return;
36	}
37
38	delog_list = g_getenv(var);
39	if (!delog_list) {
40		return;
41	}
42
43	if (*ht == NULL) {
44		*ht = g_hash_table_new(g_str_hash, g_str_equal);
45		if (*ht == NULL) {
46			return;
47		}
48	}
49
50	item = strtok((char *) delog_list, MIX_DELOG_DELIMITERS);
51	while (item != NULL) {
52		g_hash_table_insert(*ht, item, "true");
53		item = strtok(NULL, MIX_DELOG_DELIMITERS);
54	}
55}
56
57void mix_log_initialize_func() {
58
59	const gchar *mix_log_level = NULL;
60	g_static_mutex_lock(&g_mutex);
61
62	if (g_refcount == 0) {
63
64		mix_log_level = g_getenv(MIX_LOG_LEVEL);
65		if (mix_log_level) {
66			g_mix_log_level = atoi(mix_log_level);
67		}
68
69		mix_log_get_ht(&g_decom_ht, MIX_DELOG_COMPS);
70		mix_log_get_ht(&g_defile_ht, MIX_DELOG_FILES);
71		mix_log_get_ht(&g_defunc_ht, MIX_DELOG_FUNCS);
72	}
73
74	g_refcount++;
75
76	g_static_mutex_unlock(&g_mutex);
77}
78
79void mix_log_finalize_func() {
80
81	g_static_mutex_lock(&g_mutex);
82
83	g_refcount--;
84
85	if (g_refcount == 0) {
86		mix_log_destroy_ht(g_decom_ht);
87		mix_log_destroy_ht(g_defile_ht);
88		mix_log_destroy_ht(g_defunc_ht);
89
90		g_mix_log_level = MIX_LOG_LEVEL_VERBOSE;
91	}
92
93	if (g_refcount < 0) {
94		g_refcount = 0;
95	}
96
97	g_static_mutex_unlock(&g_mutex);
98}
99
100void mix_log_func(const gchar* comp, gint level, const gchar *file,
101		const gchar *func, gint line, const gchar *format, ...) {
102
103	va_list args;
104	static gchar* loglevel[4] = {"**ERROR", "*WARNING", "INFO", "VERBOSE"};
105
106	if (!format) {
107		return;
108	}
109
110	g_static_mutex_lock(&g_mutex);
111
112	if (level > g_mix_log_level) {
113		goto exit;
114	}
115
116	if (g_decom_ht) {
117		if (g_hash_table_lookup(g_decom_ht, comp)) {
118			goto exit;
119		}
120	}
121
122	if (g_defile_ht) {
123		if (g_hash_table_lookup(g_defile_ht, file)) {
124			goto exit;
125		}
126	}
127
128	if (g_defunc_ht) {
129		if (g_hash_table_lookup(g_defunc_ht, func)) {
130			goto exit;
131		}
132	}
133
134	if(level > MIX_LOG_LEVEL_VERBOSE) {
135		level = MIX_LOG_LEVEL_VERBOSE;
136	}
137	if(level < MIX_LOG_LEVEL_ERROR) {
138		level = MIX_LOG_LEVEL_ERROR;
139	}
140
141	g_print("%s : %s : %s : ", loglevel[level - 1], file, func);
142
143	va_start(args, format);
144	g_vprintf(format, args);
145	va_end(args);
146
147	exit: g_static_mutex_unlock(&g_mutex);
148}
149
150#else /* MIX_LOG_USE_HT */
151
152gboolean mix_shall_delog(const gchar *name, const gchar *var) {
153
154	const char *delog_list = NULL;
155	char *item = NULL;
156	gboolean delog = FALSE;
157
158	if (!name || !var) {
159		return delog;
160	}
161
162	delog_list = g_getenv(var);
163	if (!delog_list) {
164		return delog;
165	}
166
167	item = strtok((char *) delog_list, MIX_DELOG_DELIMITERS);
168	while (item != NULL) {
169		if (strcmp(item, name) == 0) {
170			delog = TRUE;
171			break;
172		}
173		item = strtok(NULL, MIX_DELOG_DELIMITERS);
174	}
175
176	return delog;
177}
178
179gboolean mix_log_enabled() {
180
181	const char *value = NULL;
182	value = g_getenv(MIX_LOG_ENABLE);
183	if(!value) {
184		return FALSE;
185	}
186
187	if(value[0] == '0') {
188		return FALSE;
189	}
190	return TRUE;
191}
192
193void mix_log_func(const gchar* comp, gint level, const gchar *file,
194		const gchar *func, gint line, const gchar *format, ...) {
195
196	va_list args;
197	static gchar* loglevel[4] = { "**ERROR", "*WARNING", "INFO", "VERBOSE" };
198
199	const gchar *env_mix_log_level = NULL;
200	gint mix_log_level_threhold = MIX_LOG_LEVEL_VERBOSE;
201
202	if(!mix_log_enabled()) {
203		return;
204	}
205
206	if (!format) {
207		return;
208	}
209
210	g_static_mutex_lock(&g_mutex);
211
212	/* log level */
213	env_mix_log_level = g_getenv(MIX_LOG_LEVEL);
214	if (env_mix_log_level) {
215		mix_log_level_threhold = atoi(env_mix_log_level);
216	}
217
218	if (level > mix_log_level_threhold) {
219		goto exit;
220	}
221
222	/* component */
223	if (mix_shall_delog(comp, MIX_DELOG_COMPS)) {
224		goto exit;
225	}
226
227	/* files */
228	if (mix_shall_delog(file, MIX_DELOG_FILES)) {
229		goto exit;
230	}
231
232	/* functions */
233	if (mix_shall_delog(func, MIX_DELOG_FUNCS)) {
234		goto exit;
235	}
236
237	if (level > MIX_LOG_LEVEL_VERBOSE) {
238		level = MIX_LOG_LEVEL_VERBOSE;
239	}
240	if (level < MIX_LOG_LEVEL_ERROR) {
241		level = MIX_LOG_LEVEL_ERROR;
242	}
243
244	g_print("%s : %s : %s : ", loglevel[level - 1], file, func);
245
246	va_start(args, format);
247	g_vprintf(format, args);
248	va_end(args);
249
250exit:
251	g_static_mutex_unlock(&g_mutex);
252}
253
254
255#endif /* MIX_LOG_USE_HT */
256
257
258