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
RevLine 
[cba45af]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
[f039dba]40static FIBRIL_MUTEX_INITIALIZE(log_list_guard);
41static LIST_INITIALIZE(log_list);
42
43
[ae2c925]44static logger_log_t *find_log_by_name_and_parent_no_list_lock(const char *name, logger_log_t *parent)
[cba45af]45{
[f039dba]46 list_foreach(log_list, it) {
47 logger_log_t *log = list_get_instance(it, logger_log_t, link);
[ae2c925]48 if ((parent == log->parent) && (str_cmp(log->name, name) == 0))
[cba45af]49 return log;
50 }
51
52 return NULL;
53}
54
[f5da671]55static int create_dest(const char *name, logger_dest_t **dest)
[cba45af]56{
[f039dba]57 logger_dest_t *result = malloc(sizeof(logger_dest_t));
[f5da671]58 if (result == NULL)
59 return ENOMEM;
[90dc458]60 int rc = asprintf(&result->filename, "/log/%s", name);
[f5da671]61 if (rc < 0) {
62 free(result);
63 return ENOMEM;
64 }
[90dc458]65 result->logfile = NULL;
66 fibril_mutex_initialize(&result->guard);
[f5da671]67 *dest = result;
68 return EOK;
[f039dba]69}
[cba45af]70
[ae2c925]71static logger_log_t *create_log_no_locking(const char *name, logger_log_t *parent)
[f039dba]72{
[ae2c925]73 logger_log_t *result = calloc(1, sizeof(logger_log_t));
74 if (result == NULL)
75 return NULL;
[cba45af]76
77 result->name = str_dup(name);
[ae2c925]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 */
[f039dba]86 if (parent == NULL) {
87 result->full_name = str_dup(name);
[ae2c925]88 if (result->full_name == NULL)
89 goto error;
90 int rc = create_dest(name, &result->dest);
[f5da671]91 if (rc != EOK)
[ae2c925]92 goto error;
[f039dba]93 } else {
[ae2c925]94 int rc = asprintf(&result->full_name, "%s/%s",
[f5da671]95 parent->full_name, name);
96 if (rc < 0)
[ae2c925]97 goto error;
[f039dba]98 result->dest = parent->dest;
99 }
[cba45af]100
[ae2c925]101 /* Following initializations cannot fail. */
102 result->logged_level = LOG_LEVEL_USE_DEFAULT;
103 fibril_mutex_initialize(&result->guard);
[cba45af]104 link_initialize(&result->link);
[ae2c925]105 result->parent = parent;
[cba45af]106
[ae2c925]107 return result;
[cba45af]108
[ae2c925]109error:
110 free(result->name);
111 free(result->full_name);
112 free(result);
113 return NULL;
[f5da671]114
[ae2c925]115}
[f5da671]116
[1dec7cb]117logger_log_t *find_or_create_log_and_lock(const char *name, sysarg_t parent_id)
[ae2c925]118{
119 logger_log_t *result = NULL;
120 logger_log_t *parent = (logger_log_t *) parent_id;
[cba45af]121
[ae2c925]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;
[92e963f]129 list_append(&result->link, &log_list);
[90dc458]130 }
131
[ae2c925]132 fibril_mutex_lock(&result->guard);
[f5da671]133
[ae2c925]134leave:
[f08ab0f]135 fibril_mutex_unlock(&log_list_guard);
136
[ae2c925]137 return result;
[cba45af]138}
139
[1dec7cb]140logger_log_t *find_log_by_name_and_lock(const char *name)
[cba45af]141{
[f039dba]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) {
[3cf862f]148 fibril_mutex_lock(&log->guard);
[f039dba]149 result = log;
150 break;
151 }
[cba45af]152 }
[f039dba]153 fibril_mutex_unlock(&log_list_guard);
[cba45af]154
[f039dba]155 return result;
[cba45af]156}
157
[1dec7cb]158logger_log_t *find_log_by_id_and_lock(sysarg_t id)
[cba45af]159{
[f039dba]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) {
[3cf862f]166 fibril_mutex_lock(&log->guard);
[f039dba]167 result = log;
168 break;
169 }
[cba45af]170 }
[f039dba]171 fibril_mutex_unlock(&log_list_guard);
[cba45af]172
[f039dba]173 return result;
[cba45af]174}
175
[f039dba]176static log_level_t get_actual_log_level(logger_log_t *log)
[cba45af]177{
[f039dba]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;
[cba45af]186}
187
[f039dba]188bool shall_log_message(logger_log_t *log, log_level_t level)
189{
[3cf862f]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
[1dec7cb]196void log_unlock(logger_log_t *log)
[3cf862f]197{
198 assert(fibril_mutex_is_locked(&log->guard));
199 fibril_mutex_unlock(&log->guard);
[f039dba]200}
[cba45af]201
[90dc458]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
[cba45af]220/**
221 * @}
222 */
Note: See TracBrowser for help on using the repository browser.