source: mainline/uspace/srv/logger/namespace.c@ 1f2dd20

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

Start working on logger service

The logger service is started as an init task and log_msg functions
sends messages to it.

  • Property mode set to 100644
File size: 5.6 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 bool has_writer;
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;
116 namespace->has_writer = true;
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);
137 if (namespace->has_reader || namespace->has_writer) {
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
177void namespace_reader_detach(logging_namespace_t *namespace)
178{
179 fibril_mutex_lock(&namespace->guard);
180 namespace->has_reader = false;
181 fibril_mutex_unlock(&namespace->guard);
182
183 namespace_destroy_careful(namespace);
184}
185
186void namespace_writer_detach(logging_namespace_t *namespace)
187{
188 fibril_mutex_lock(&namespace->guard);
189 namespace->has_writer = false;
190 fibril_mutex_unlock(&namespace->guard);
191
192 namespace_destroy_careful(namespace);
193}
194
195
196
197void namespace_add_message(logging_namespace_t *namespace, const char *message, log_level_t level)
198{
199 if (level <= DEFAULT_LOGGING_LEVEL) {
200 printf("[%s %d]: %s\n", namespace->name, level, message);
201 }
202
203 fibril_mutex_lock(&namespace->guard);
204 if (namespace->has_reader) {
205 log_message_t *msg = message_create(message, level);
206 if (msg != NULL) {
207 prodcons_produce(&namespace->messages, &msg->link);
208 }
209 }
210 fibril_mutex_unlock(&namespace->guard);
211}
212
213log_message_t *namespace_get_next_message(logging_namespace_t *namespace)
214{
215 link_t *message = prodcons_consume(&namespace->messages);
216
217 return list_get_instance(message, log_message_t, link);
218}
219
220
221/**
222 * @}
223 */
Note: See TracBrowser for help on using the repository browser.