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

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

Use log level names when printing instead of numbers

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