source: mainline/uspace/srv/logger/namespace.c@ ebbc8a74

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since ebbc8a74 was ebbc8a74, checked in by Vojtech Horky <vojtechhorky@…>, 13 years ago

Remove premature optimizations

  • Property mode set to 100644
File size: 7.7 KB
RevLine 
[1f2dd20]1/*
2 * Copyright (c) 2012 Vojtech Horky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup logger
30 * @{
31 */
32#include <assert.h>
33#include <malloc.h>
34#include <str.h>
35#include <stdio.h>
[494f417]36#include <errno.h>
[1f2dd20]37#include "logger.h"
38
39/** @file
40 * Logging namespaces.
41 */
42
[793cce15]43#define CONTEXT_SIZE 16
44
45typedef struct {
46 const char *name;
47 log_level_t level;
48} logging_context_t;
[76d92db1]49
[1f2dd20]50struct logging_namespace {
51 fibril_mutex_t guard;
[ef5be68]52 size_t writers_count;
[76d92db1]53 FILE *logfile;
[6e9e12b]54 log_level_t level;
[1f2dd20]55 const char *name;
[6e9e12b]56
[793cce15]57 // FIXME: make dynamic
58 size_t context_count;
59 logging_context_t context[CONTEXT_SIZE];
60
[1f2dd20]61 link_t link;
62};
63
64static FIBRIL_MUTEX_INITIALIZE(namespace_list_guard);
65static LIST_INITIALIZE(namespace_list);
66
[793cce15]67static log_level_t namespace_get_actual_log_level(logging_namespace_t *namespace, sysarg_t context)
[0a6a996]68{
69 fibril_mutex_lock(&namespace->guard);
[793cce15]70 if (context >= namespace->context_count) {
71 fibril_mutex_unlock(&namespace->guard);
[80d8885]72 fprintf(stderr, "Invalid context!\n");
[793cce15]73 return LVL_FATAL;
74 }
75 log_level_t level = namespace->context[context].level;
[0a6a996]76 fibril_mutex_unlock(&namespace->guard);
77
78 if (level == LOG_LEVEL_USE_DEFAULT)
79 level = get_default_logging_level();
80
81 return level;
82}
83
[1f2dd20]84static logging_namespace_t *namespace_find_no_lock(const char *name)
85{
86 list_foreach(namespace_list, it) {
87 logging_namespace_t *namespace = list_get_instance(it, logging_namespace_t, link);
88 if (str_cmp(namespace->name, name) == 0) {
89 return namespace;
90 }
91 }
92
93 return NULL;
94}
95
[01b8c2e4]96static logging_namespace_t *namespace_create_no_lock(const char *name)
[1f2dd20]97{
98 logging_namespace_t *existing = namespace_find_no_lock(name);
99 if (existing != NULL) {
100 return NULL;
101 }
102
103 logging_namespace_t *namespace = malloc(sizeof(logging_namespace_t));
104 if (namespace == NULL) {
105 return NULL;
106 }
107
108 namespace->name = str_dup(name);
109 if (namespace->name == NULL) {
110 free(namespace);
111 return NULL;
112 }
113
[76d92db1]114 char *logfilename;
115 int rc = asprintf(&logfilename, "/log/%s", name);
116 if (rc < 0) {
117 free(namespace->name);
118 free(namespace);
119 return NULL;
120 }
121 namespace->logfile = fopen(logfilename, "a");
122 free(logfilename);
123 if (namespace->logfile == NULL) {
124 free(namespace->name);
125 free(namespace);
126 return NULL;
127 }
128
[0a6a996]129 namespace->level = LOG_LEVEL_USE_DEFAULT;
[76d92db1]130
[793cce15]131 namespace->context_count = 1;
132 namespace->context[0].name = "";
133 namespace->context[0].level = LOG_LEVEL_USE_DEFAULT;
134
[1f2dd20]135 fibril_mutex_initialize(&namespace->guard);
[ef5be68]136 namespace->writers_count = 0;
[1f2dd20]137 link_initialize(&namespace->link);
138
139 list_append(&namespace->link, &namespace_list);
140
141 return namespace;
142}
143
[01b8c2e4]144
145logging_namespace_t *namespace_create(const char *name)
146{
147 fibril_mutex_lock(&namespace_list_guard);
148 logging_namespace_t *result = namespace_create_no_lock(name);
149 fibril_mutex_unlock(&namespace_list_guard);
150 return result;
151}
152
[1f2dd20]153const char *namespace_get_name(logging_namespace_t *namespace)
154{
155 assert(namespace);
156 return namespace->name;
157}
158
159static void namespace_destroy_careful(logging_namespace_t *namespace)
160{
161 assert(namespace);
162 fibril_mutex_lock(&namespace_list_guard);
163
164 fibril_mutex_lock(&namespace->guard);
[6e9e12b]165 if (namespace->writers_count > 0) {
[1f2dd20]166 fibril_mutex_unlock(&namespace->guard);
167 fibril_mutex_unlock(&namespace_list_guard);
168 return;
169 }
170
171 list_remove(&namespace->link);
172
173 fibril_mutex_unlock(&namespace->guard);
174 fibril_mutex_unlock(&namespace_list_guard);
175
176 // TODO - destroy pending messages
[76d92db1]177 fclose(namespace->logfile);
[1f2dd20]178 free(namespace->name);
179 free(namespace);
180}
181
182void namespace_destroy(logging_namespace_t *namespace)
183{
184 namespace_destroy_careful(namespace);
185}
186
[ef5be68]187logging_namespace_t *namespace_writer_attach(const char *name)
188{
189 logging_namespace_t *namespace = NULL;
190
191 fibril_mutex_lock(&namespace_list_guard);
192
193 namespace = namespace_find_no_lock(name);
194
195 if (namespace == NULL) {
[01b8c2e4]196 namespace = namespace_create_no_lock(name);
[ef5be68]197 }
198
199 fibril_mutex_lock(&namespace->guard);
200 namespace->writers_count++;
201 fibril_mutex_unlock(&namespace->guard);
202
203 fibril_mutex_unlock(&namespace_list_guard);
204
205 return namespace;
206}
207
[1f2dd20]208void namespace_writer_detach(logging_namespace_t *namespace)
209{
210 fibril_mutex_lock(&namespace->guard);
[ef5be68]211 assert(namespace->writers_count > 0);
212 namespace->writers_count--;
[1f2dd20]213 fibril_mutex_unlock(&namespace->guard);
214
215 namespace_destroy_careful(namespace);
216}
217
[494f417]218int namespace_change_level(logging_namespace_t *namespace, log_level_t level)
219{
220 if (level >= LVL_LIMIT)
221 return ERANGE;
222
223 fibril_mutex_lock(&namespace->guard);
224 namespace->level = level;
[793cce15]225 for (size_t i = 0; i < namespace->context_count; i++) {
226 namespace->context[i].level = level;
227 }
[494f417]228 fibril_mutex_unlock(&namespace->guard);
229
230 return EOK;
231}
232
233
[793cce15]234bool namespace_has_reader(logging_namespace_t *namespace, sysarg_t context, log_level_t level)
[f6bc83a]235{
[793cce15]236 return level <= namespace_get_actual_log_level(namespace, context);
237}
238
239int namespace_create_context(logging_namespace_t *namespace, const char *name)
240{
241 int rc;
242 fibril_mutex_lock(&namespace->guard);
243 if (namespace->context_count >= CONTEXT_SIZE) {
244 rc = ELIMIT;
245 goto leave;
246 }
247
248 namespace->context[namespace->context_count].level
249 = LOG_LEVEL_USE_DEFAULT;
250 namespace->context[namespace->context_count].name
251 = str_dup(name);
252 if (namespace->context[namespace->context_count].name == NULL) {
253 rc = ENOMEM;
254 goto leave;
255 }
256 rc = (int) namespace->context_count;
257 namespace->context_count++;
258
259
260leave:
261 fibril_mutex_unlock(&namespace->guard);
262 return rc;
[f6bc83a]263}
[1f2dd20]264
[80d8885]265int namespace_change_context_level(logging_namespace_t *namespace, const char *context, log_level_t new_level)
[2e39656]266{
[80d8885]267 if (new_level >= LVL_LIMIT)
268 return ERANGE;
269
270 int rc;
[2e39656]271 fibril_mutex_lock(&namespace->guard);
[80d8885]272 for (size_t i = 0; i < namespace->context_count; i++) {
273 if (str_cmp(namespace->context[i].name, context) == 0) {
274 namespace->context[i].level = new_level;
275 rc = EOK;
276 goto leave;
277 }
[2e39656]278 }
[80d8885]279 rc = ENOENT;
280
281leave:
282 fibril_mutex_unlock(&namespace->guard);
283 return rc;
284}
285
[793cce15]286void namespace_add_message(logging_namespace_t *namespace, const char *message, sysarg_t context, log_level_t level)
[1f2dd20]287{
[793cce15]288 if (level <= namespace_get_actual_log_level(namespace, context)) {
[1c67b41]289 const char *level_name = log_level_str(level);
[793cce15]290 if (context == 0) {
291 printf("[%s %s]: %s\n",
292 namespace->name, level_name, message);
293 fprintf(namespace->logfile, "%s: %s\n",
294 level_name, message);
295 } else {
296 const char *context_name = namespace->context[context].name;
297 printf("[%s/%s %s]: %s\n",
298 namespace->name, context_name, level_name, message);
299 fprintf(namespace->logfile, "[%s] %s: %s\n",
300 context_name, level_name, message);
301 }
[76d92db1]302 fflush(namespace->logfile);
[6e9e12b]303 fflush(stdout);
[76d92db1]304 }
[1f2dd20]305}
306
307
308/**
309 * @}
310 */
Note: See TracBrowser for help on using the repository browser.