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

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

Logger: namespace can have more writers

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