2 * Copyright (c) 2012 Vojtech Horky
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
30 * @defgroup logger Logging service.
31 * @brief HelenOS logging service.
38 #include <ipc/services.h>
39 #include <ipc/logger.h>
41 #include <io/logctl.h>
46 #include <str_error.h>
50 static int handle_namespace_level_change(sysarg_t new_level
)
53 int rc
= async_data_write_accept(&namespace_name
, true, 0, 0, 0, NULL
);
58 logging_namespace_t
*namespace = namespace_writer_attach((const char *) namespace_name
);
60 if (namespace == NULL
)
63 rc
= namespace_change_level(namespace, (log_level_t
) new_level
);
64 namespace_writer_detach(namespace);
69 static int handle_context_level_change(sysarg_t new_level
)
72 int rc
= async_data_write_accept(&namespace_name
, true, 0, 0, 0, NULL
);
77 logging_namespace_t
*namespace = namespace_writer_attach((const char *) namespace_name
);
79 if (namespace == NULL
)
83 rc
= async_data_write_accept(&context_name
, true, 0, 0, 0, NULL
);
85 namespace_writer_detach(namespace);
89 rc
= namespace_change_context_level(namespace, context_name
, new_level
);
91 namespace_writer_detach(namespace);
96 static void connection_handler_control(void)
98 printf(NAME
"/control: new client.\n");
102 ipc_callid_t callid
= async_get_call(&call
);
104 if (!IPC_GET_IMETHOD(call
))
109 switch (IPC_GET_IMETHOD(call
)) {
110 case LOGGER_CTL_GET_DEFAULT_LEVEL
:
111 async_answer_1(callid
, EOK
, get_default_logging_level());
113 case LOGGER_CTL_SET_DEFAULT_LEVEL
:
114 rc
= set_default_logging_level(IPC_GET_ARG1(call
));
115 async_answer_0(callid
, rc
);
117 case LOGGER_CTL_SET_NAMESPACE_LEVEL
:
118 rc
= handle_namespace_level_change(IPC_GET_ARG1(call
));
119 async_answer_0(callid
, rc
);
121 case LOGGER_CTL_SET_CONTEXT_LEVEL
:
122 rc
= handle_context_level_change(IPC_GET_ARG1(call
));
123 async_answer_0(callid
, rc
);
126 async_answer_0(callid
, EINVAL
);
131 printf(NAME
"/control: client terminated.\n");
134 static logging_namespace_t
*find_namespace_and_attach_writer(void)
137 ipc_callid_t callid
= async_get_call(&call
);
139 if (IPC_GET_IMETHOD(call
) != LOGGER_REGISTER
) {
140 async_answer_0(callid
, EINVAL
);
145 int rc
= async_data_write_accept(&name
, true, 1, MAX_NAMESPACE_LENGTH
, 0, NULL
);
146 async_answer_0(callid
, rc
);
152 logging_namespace_t
*result
= namespace_writer_attach((const char *) name
);
159 static int handle_receive_message(logging_namespace_t
*namespace, sysarg_t context
, int level
)
161 bool skip_message
= !namespace_has_reader(namespace, context
, level
);
163 /* Abort the actual message buffer transfer. */
167 if (!async_data_write_receive(&callid
, &size
))
170 async_answer_0(callid
, rc
);
175 int rc
= async_data_write_accept(&message
, true, 0, 0, 0, NULL
);
180 namespace_add_message(namespace, message
, context
, level
);
187 static int handle_create_context(logging_namespace_t
*namespace, sysarg_t
*idx
)
190 int rc
= async_data_write_accept(&name
, true, 0, 0, 0, NULL
);
195 rc
= namespace_create_context(namespace, name
);
202 *idx
= (sysarg_t
) rc
;
206 static void connection_handler_sink(logging_namespace_t
*namespace)
208 printf(NAME
"/sink: new client %s.\n", namespace_get_name(namespace));
212 ipc_callid_t callid
= async_get_call(&call
);
214 if (!IPC_GET_IMETHOD(call
))
220 switch (IPC_GET_IMETHOD(call
)) {
221 case LOGGER_CREATE_CONTEXT
:
222 rc
= handle_create_context(namespace, &arg
);
223 async_answer_1(callid
, rc
, arg
);
226 rc
= handle_receive_message(namespace, IPC_GET_ARG1(call
), IPC_GET_ARG2(call
));
227 async_answer_0(callid
, rc
);
230 async_answer_0(callid
, EINVAL
);
235 printf(NAME
"/sink: client %s terminated.\n", namespace_get_name(namespace));
236 namespace_writer_detach(namespace);
239 static void connection_handler(ipc_callid_t iid
, ipc_call_t
*icall
, void *arg
)
241 logger_interface_t iface
= IPC_GET_ARG1(*icall
);
243 logging_namespace_t
*namespace = NULL
;
246 case LOGGER_INTERFACE_CONTROL
:
247 async_answer_0(iid
, EOK
);
248 connection_handler_control();
250 case LOGGER_INTERFACE_SINK
:
251 /* First call has to be the registration. */
252 async_answer_0(iid
, EOK
);
253 namespace = find_namespace_and_attach_writer();
254 if (namespace == NULL
) {
255 fprintf(stderr
, NAME
": failed to register namespace.\n");
258 connection_handler_sink(namespace);
261 async_answer_0(iid
, EINVAL
);
266 int main(int argc
, char *argv
[])
268 printf(NAME
": HelenOS Logging Service\n");
270 /* Get default logging level from sysinfo (if available). */
271 log_level_t boot_logging_level
= LVL_NOTE
;
272 int rc
= logctl_get_boot_level(&boot_logging_level
);
274 set_default_logging_level(boot_logging_level
);
276 printf(NAME
": Warn: failed to get logging level from sysinfo: %s.\n",
279 async_set_client_connection(connection_handler
);
281 rc
= service_register(SERVICE_LOGGER
);
283 printf(NAME
": failed to register: %s.\n", str_error(rc
));
287 printf(NAME
": Accepting connections\n");