source: mainline/uspace/srv/logger/namespace.c@ 494f417

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

Allow changing level of individual namespaces

  • Property mode set to 100644
File size: 6.3 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
[76d92db1]43
[1f2dd20]44struct logging_namespace {
45 fibril_mutex_t guard;
[ef5be68]46 size_t writers_count;
[6e9e12b]47 fibril_condvar_t level_changed_cv;
[76d92db1]48 FILE *logfile;
[6e9e12b]49 log_level_t level;
[1f2dd20]50 const char *name;
[6e9e12b]51
[1f2dd20]52 link_t link;
53};
54
55static FIBRIL_MUTEX_INITIALIZE(namespace_list_guard);
56static LIST_INITIALIZE(namespace_list);
57
[0a6a996]58static log_level_t namespace_get_actual_log_level(logging_namespace_t *namespace)
59{
60 fibril_mutex_lock(&namespace->guard);
61 log_level_t level = namespace->level;
62 fibril_mutex_unlock(&namespace->guard);
63
64 if (level == LOG_LEVEL_USE_DEFAULT)
65 level = get_default_logging_level();
66
67 return level;
68}
69
[1f2dd20]70static logging_namespace_t *namespace_find_no_lock(const char *name)
71{
72 list_foreach(namespace_list, it) {
73 logging_namespace_t *namespace = list_get_instance(it, logging_namespace_t, link);
74 if (str_cmp(namespace->name, name) == 0) {
75 return namespace;
76 }
77 }
78
79 return NULL;
80}
81
[01b8c2e4]82static logging_namespace_t *namespace_create_no_lock(const char *name)
[1f2dd20]83{
84 logging_namespace_t *existing = namespace_find_no_lock(name);
85 if (existing != NULL) {
86 return NULL;
87 }
88
89 logging_namespace_t *namespace = malloc(sizeof(logging_namespace_t));
90 if (namespace == NULL) {
91 return NULL;
92 }
93
94 namespace->name = str_dup(name);
95 if (namespace->name == NULL) {
96 free(namespace);
97 return NULL;
98 }
99
[76d92db1]100 char *logfilename;
101 int rc = asprintf(&logfilename, "/log/%s", name);
102 if (rc < 0) {
103 free(namespace->name);
104 free(namespace);
105 return NULL;
106 }
107 namespace->logfile = fopen(logfilename, "a");
108 free(logfilename);
109 if (namespace->logfile == NULL) {
110 free(namespace->name);
111 free(namespace);
112 return NULL;
113 }
114
[0a6a996]115 namespace->level = LOG_LEVEL_USE_DEFAULT;
[76d92db1]116
[1f2dd20]117 fibril_mutex_initialize(&namespace->guard);
[6e9e12b]118 fibril_condvar_initialize(&namespace->level_changed_cv);
[ef5be68]119 namespace->writers_count = 0;
[1f2dd20]120 link_initialize(&namespace->link);
121
122 list_append(&namespace->link, &namespace_list);
123
124 return namespace;
125}
126
[01b8c2e4]127
128logging_namespace_t *namespace_create(const char *name)
129{
130 fibril_mutex_lock(&namespace_list_guard);
131 logging_namespace_t *result = namespace_create_no_lock(name);
132 fibril_mutex_unlock(&namespace_list_guard);
133 return result;
134}
135
[1f2dd20]136const char *namespace_get_name(logging_namespace_t *namespace)
137{
138 assert(namespace);
139 return namespace->name;
140}
141
142static void namespace_destroy_careful(logging_namespace_t *namespace)
143{
144 assert(namespace);
145 fibril_mutex_lock(&namespace_list_guard);
146
147 fibril_mutex_lock(&namespace->guard);
[6e9e12b]148 if (namespace->writers_count > 0) {
[1f2dd20]149 fibril_mutex_unlock(&namespace->guard);
150 fibril_mutex_unlock(&namespace_list_guard);
151 return;
152 }
153
154 list_remove(&namespace->link);
155
156 fibril_mutex_unlock(&namespace->guard);
157 fibril_mutex_unlock(&namespace_list_guard);
158
159 // TODO - destroy pending messages
[76d92db1]160 fclose(namespace->logfile);
[1f2dd20]161 free(namespace->name);
162 free(namespace);
163}
164
165void namespace_destroy(logging_namespace_t *namespace)
166{
167 namespace_destroy_careful(namespace);
168}
169
[ef5be68]170logging_namespace_t *namespace_writer_attach(const char *name)
171{
172 logging_namespace_t *namespace = NULL;
173
174 fibril_mutex_lock(&namespace_list_guard);
175
176 namespace = namespace_find_no_lock(name);
177
178 if (namespace == NULL) {
[01b8c2e4]179 namespace = namespace_create_no_lock(name);
[ef5be68]180 }
181
182 fibril_mutex_lock(&namespace->guard);
183 namespace->writers_count++;
184 fibril_mutex_unlock(&namespace->guard);
185
186 fibril_mutex_unlock(&namespace_list_guard);
187
188 return namespace;
189}
190
[1f2dd20]191void namespace_writer_detach(logging_namespace_t *namespace)
192{
193 fibril_mutex_lock(&namespace->guard);
[ef5be68]194 assert(namespace->writers_count > 0);
195 namespace->writers_count--;
[1f2dd20]196 fibril_mutex_unlock(&namespace->guard);
197
198 namespace_destroy_careful(namespace);
199}
200
[494f417]201int namespace_change_level(logging_namespace_t *namespace, log_level_t level)
202{
203 if (level >= LVL_LIMIT)
204 return ERANGE;
205
206 fibril_mutex_lock(&namespace->guard);
207 namespace->level = level;
208 fibril_condvar_broadcast(&namespace->level_changed_cv);
209 fibril_mutex_unlock(&namespace->guard);
210
211 return EOK;
212}
213
214
[76d92db1]215bool namespace_has_reader(logging_namespace_t *namespace, log_level_t level)
[f6bc83a]216{
[0a6a996]217 return level <= namespace_get_actual_log_level(namespace);
[f6bc83a]218}
[1f2dd20]219
[2e39656]220void namespace_wait_for_reader_change(logging_namespace_t *namespace, bool *has_reader_now)
221{
222 fibril_mutex_lock(&namespace->guard);
[6e9e12b]223 log_level_t previous_level = namespace->level;
224 while (previous_level == namespace->level) {
225 fibril_condvar_wait(&namespace->level_changed_cv, &namespace->guard);
[2e39656]226 }
[6e9e12b]227 *has_reader_now = true;
[2e39656]228 fibril_mutex_unlock(&namespace->guard);
229}
230
[1f2dd20]231
232void namespace_add_message(logging_namespace_t *namespace, const char *message, log_level_t level)
233{
[0a6a996]234 if (level <= namespace_get_actual_log_level(namespace)) {
[1c67b41]235 const char *level_name = log_level_str(level);
236 printf("[%s %s]: %s\n", namespace->name, level_name, message);
237 fprintf(namespace->logfile, "%s: %s\n", level_name, message);
[76d92db1]238 fflush(namespace->logfile);
[6e9e12b]239 fflush(stdout);
[76d92db1]240 }
[1f2dd20]241}
242
243
244/**
245 * @}
246 */
Note: See TracBrowser for help on using the repository browser.