source: mainline/uspace/srv/logger/namespace.c@ 2e39656

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

Check for log readers in separate fibril

Do not even try to send when no reader was announced.

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