source: mainline/uspace/srv/logger/namespace.c@ 14de4106

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

Make logger runnable again

  • Property mode set to 100644
File size: 6.9 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
42struct logging_namespace {
43 fibril_mutex_t guard;
44 size_t writers_count;
45 fibril_condvar_t reader_appeared_cv;
46 bool has_reader;
47 const char *name;
48 link_t link;
49 prodcons_t messages;
50};
51
52static FIBRIL_MUTEX_INITIALIZE(namespace_list_guard);
53static LIST_INITIALIZE(namespace_list);
54
55log_message_t *message_create(const char *name, log_level_t level)
56{
57 log_message_t *message = malloc(sizeof(log_message_t));
58 if (message == NULL)
59 return NULL;
60
61 message->message = str_dup(name);
62 if (message->message == NULL) {
63 free(message);
64 return NULL;
65 }
66
67 message->level = level;
68 link_initialize(&message->link);
69
70 return message;
71}
72
73void message_destroy(log_message_t *message)
74{
75 assert(message);
76 free(message->message);
77 free(message);
78}
79
80static logging_namespace_t *namespace_find_no_lock(const char *name)
81{
82 list_foreach(namespace_list, it) {
83 logging_namespace_t *namespace = list_get_instance(it, logging_namespace_t, link);
84 if (str_cmp(namespace->name, name) == 0) {
85 return namespace;
86 }
87 }
88
89 return NULL;
90}
91
92static logging_namespace_t *namespace_create_no_lock(const char *name)
93{
94 logging_namespace_t *existing = namespace_find_no_lock(name);
95 if (existing != NULL) {
96 return NULL;
97 }
98
99 logging_namespace_t *namespace = malloc(sizeof(logging_namespace_t));
100 if (namespace == NULL) {
101 return NULL;
102 }
103
104 namespace->name = str_dup(name);
105 if (namespace->name == NULL) {
106 free(namespace);
107 return NULL;
108 }
109
110 fibril_mutex_initialize(&namespace->guard);
111 fibril_condvar_initialize(&namespace->reader_appeared_cv);
112 prodcons_initialize(&namespace->messages);
113 namespace->has_reader = false;
114 namespace->writers_count = 0;
115 link_initialize(&namespace->link);
116
117 list_append(&namespace->link, &namespace_list);
118
119 return namespace;
120}
121
122
123logging_namespace_t *namespace_create(const char *name)
124{
125 fibril_mutex_lock(&namespace_list_guard);
126 logging_namespace_t *result = namespace_create_no_lock(name);
127 fibril_mutex_unlock(&namespace_list_guard);
128 return result;
129}
130
131const char *namespace_get_name(logging_namespace_t *namespace)
132{
133 assert(namespace);
134 return namespace->name;
135}
136
137static void namespace_destroy_careful(logging_namespace_t *namespace)
138{
139 assert(namespace);
140 fibril_mutex_lock(&namespace_list_guard);
141
142 fibril_mutex_lock(&namespace->guard);
143 if (namespace->has_reader || (namespace->writers_count > 0)) {
144 fibril_mutex_unlock(&namespace->guard);
145 fibril_mutex_unlock(&namespace_list_guard);
146 return;
147 }
148
149 list_remove(&namespace->link);
150
151 fibril_mutex_unlock(&namespace->guard);
152 fibril_mutex_unlock(&namespace_list_guard);
153
154 // TODO - destroy pending messages
155 free(namespace->name);
156 free(namespace);
157}
158
159void namespace_destroy(logging_namespace_t *namespace)
160{
161 namespace_destroy_careful(namespace);
162}
163
164logging_namespace_t *namespace_reader_attach(const char *name)
165{
166 logging_namespace_t *namespace = NULL;
167
168 fibril_mutex_lock(&namespace_list_guard);
169
170 namespace = namespace_find_no_lock(name);
171
172 if (namespace != NULL) {
173 fibril_mutex_lock(&namespace->guard);
174 namespace->has_reader = true;
175 fibril_condvar_broadcast(&namespace->reader_appeared_cv);
176 fibril_mutex_unlock(&namespace->guard);
177 }
178
179 fibril_mutex_unlock(&namespace_list_guard);
180
181 return namespace;
182}
183
184logging_namespace_t *namespace_writer_attach(const char *name)
185{
186 logging_namespace_t *namespace = NULL;
187
188 fibril_mutex_lock(&namespace_list_guard);
189
190 namespace = namespace_find_no_lock(name);
191
192 if (namespace == NULL) {
193 namespace = namespace_create_no_lock(name);
194 }
195
196 fibril_mutex_lock(&namespace->guard);
197 namespace->writers_count++;
198 fibril_mutex_unlock(&namespace->guard);
199
200 fibril_mutex_unlock(&namespace_list_guard);
201
202 return namespace;
203}
204
205void namespace_reader_detach(logging_namespace_t *namespace)
206{
207 fibril_mutex_lock(&namespace->guard);
208 namespace->has_reader = false;
209 fibril_condvar_broadcast(&namespace->reader_appeared_cv);
210 fibril_mutex_unlock(&namespace->guard);
211
212 namespace_destroy_careful(namespace);
213}
214
215void namespace_writer_detach(logging_namespace_t *namespace)
216{
217 fibril_mutex_lock(&namespace->guard);
218 assert(namespace->writers_count > 0);
219 namespace->writers_count--;
220 fibril_mutex_unlock(&namespace->guard);
221
222 namespace_destroy_careful(namespace);
223}
224
225bool namespace_has_reader(logging_namespace_t *namespace)
226{
227 fibril_mutex_lock(&namespace->guard);
228 bool has_reader = namespace->has_reader;
229 fibril_mutex_unlock(&namespace->guard);
230 return has_reader;
231}
232
233void namespace_wait_for_reader_change(logging_namespace_t *namespace, bool *has_reader_now)
234{
235 fibril_mutex_lock(&namespace->guard);
236 bool had_reader = namespace->has_reader;
237 while (had_reader == namespace->has_reader) {
238 fibril_condvar_wait(&namespace->reader_appeared_cv, &namespace->guard);
239 }
240 *has_reader_now = namespace->has_reader;
241 fibril_mutex_unlock(&namespace->guard);
242}
243
244
245void namespace_add_message(logging_namespace_t *namespace, const char *message, log_level_t level)
246{
247 if (level <= DEFAULT_LOGGING_LEVEL) {
248 printf("[%s %d]: %s\n", namespace->name, level, message);
249 }
250
251 fibril_mutex_lock(&namespace->guard);
252 if (namespace->has_reader) {
253 log_message_t *msg = message_create(message, level);
254 if (msg != NULL) {
255 prodcons_produce(&namespace->messages, &msg->link);
256 }
257 }
258 fibril_mutex_unlock(&namespace->guard);
259}
260
261log_message_t *namespace_get_next_message(logging_namespace_t *namespace)
262{
263 link_t *message = prodcons_consume(&namespace->messages);
264
265 return list_get_instance(message, log_message_t, link);
266}
267
268
269/**
270 * @}
271 */
Note: See TracBrowser for help on using the repository browser.