source: mainline/uspace/srv/logger/logs.c@ b6933f3

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

Bugfix: do not append to list twice

  • Property mode set to 100644
File size: 5.7 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 <errno.h>
37#include "logger.h"
38
39
40static FIBRIL_MUTEX_INITIALIZE(log_list_guard);
41static LIST_INITIALIZE(log_list);
42
43
44static logger_log_t *find_log_by_name_and_parent_no_list_lock(const char *name, logger_log_t *parent)
45{
46 list_foreach(log_list, it) {
47 logger_log_t *log = list_get_instance(it, logger_log_t, link);
48 if ((parent == log->parent) && (str_cmp(log->name, name) == 0))
49 return log;
50 }
51
52 return NULL;
53}
54
55static int create_dest(const char *name, logger_dest_t **dest)
56{
57 logger_dest_t *result = malloc(sizeof(logger_dest_t));
58 if (result == NULL)
59 return ENOMEM;
60 int rc = asprintf(&result->filename, "/log/%s", name);
61 if (rc < 0) {
62 free(result);
63 return ENOMEM;
64 }
65 result->logfile = NULL;
66 fibril_mutex_initialize(&result->guard);
67 *dest = result;
68 return EOK;
69}
70
71static logger_log_t *create_log_no_locking(const char *name, logger_log_t *parent)
72{
73 logger_log_t *result = calloc(1, sizeof(logger_log_t));
74 if (result == NULL)
75 return NULL;
76
77 result->name = str_dup(name);
78 if (result->name == NULL)
79 goto error;
80
81 /*
82 * Notice that we create new dest as the last
83 * operation that can fail and thus there is no code
84 * to deallocate dest.
85 */
86 if (parent == NULL) {
87 result->full_name = str_dup(name);
88 if (result->full_name == NULL)
89 goto error;
90 int rc = create_dest(name, &result->dest);
91 if (rc != EOK)
92 goto error;
93 } else {
94 int rc = asprintf(&result->full_name, "%s/%s",
95 parent->full_name, name);
96 if (rc < 0)
97 goto error;
98 result->dest = parent->dest;
99 }
100
101 /* Following initializations cannot fail. */
102 result->logged_level = LOG_LEVEL_USE_DEFAULT;
103 fibril_mutex_initialize(&result->guard);
104 link_initialize(&result->link);
105 result->parent = parent;
106
107 return result;
108
109error:
110 free(result->name);
111 free(result->full_name);
112 free(result);
113 return NULL;
114
115}
116
117logger_log_t *find_or_create_log_and_lock(const char *name, sysarg_t parent_id)
118{
119 logger_log_t *result = NULL;
120 logger_log_t *parent = (logger_log_t *) parent_id;
121
122 fibril_mutex_lock(&log_list_guard);
123
124 result = find_log_by_name_and_parent_no_list_lock(name, parent);
125 if (result == NULL) {
126 result = create_log_no_locking(name, parent);
127 if (result == NULL)
128 goto leave;
129 list_append(&result->link, &log_list);
130 }
131
132 fibril_mutex_lock(&result->guard);
133
134leave:
135 fibril_mutex_unlock(&log_list_guard);
136
137 return result;
138}
139
140logger_log_t *find_log_by_name_and_lock(const char *name)
141{
142 logger_log_t *result = NULL;
143
144 fibril_mutex_lock(&log_list_guard);
145 list_foreach(log_list, it) {
146 logger_log_t *log = list_get_instance(it, logger_log_t, link);
147 if (str_cmp(log->full_name, name) == 0) {
148 fibril_mutex_lock(&log->guard);
149 result = log;
150 break;
151 }
152 }
153 fibril_mutex_unlock(&log_list_guard);
154
155 return result;
156}
157
158logger_log_t *find_log_by_id_and_lock(sysarg_t id)
159{
160 logger_log_t *result = NULL;
161
162 fibril_mutex_lock(&log_list_guard);
163 list_foreach(log_list, it) {
164 logger_log_t *log = list_get_instance(it, logger_log_t, link);
165 if ((sysarg_t) log == id) {
166 fibril_mutex_lock(&log->guard);
167 result = log;
168 break;
169 }
170 }
171 fibril_mutex_unlock(&log_list_guard);
172
173 return result;
174}
175
176static log_level_t get_actual_log_level(logger_log_t *log)
177{
178 /* Find recursively proper log level. */
179 if (log->logged_level == LOG_LEVEL_USE_DEFAULT) {
180 if (log->parent == NULL)
181 return get_default_logging_level();
182 else
183 return get_actual_log_level(log->parent);
184 }
185 return log->logged_level;
186}
187
188bool shall_log_message(logger_log_t *log, log_level_t level)
189{
190 fibril_mutex_lock(&log_list_guard);
191 bool result = level <= get_actual_log_level(log);
192 fibril_mutex_unlock(&log_list_guard);
193 return result;
194}
195
196void log_unlock(logger_log_t *log)
197{
198 assert(fibril_mutex_is_locked(&log->guard));
199 fibril_mutex_unlock(&log->guard);
200}
201
202void write_to_log(logger_log_t *log, log_level_t level, const char *message)
203{
204 assert(fibril_mutex_is_locked(&log->guard));
205 assert(log->dest != NULL);
206 fibril_mutex_lock(&log->dest->guard);
207 if (log->dest->logfile == NULL)
208 log->dest->logfile = fopen(log->dest->filename, "a");
209
210 if (log->dest->logfile != NULL) {
211 fprintf(log->dest->logfile, "[%s] %s: %s\n",
212 log->full_name, log_level_str(level),
213 (const char *) message);
214 fflush(log->dest->logfile);
215 }
216
217 fibril_mutex_unlock(&log->dest->guard);
218}
219
220/**
221 * @}
222 */
Note: See TracBrowser for help on using the repository browser.