committed by
Norman Feske
parent
3af80e2d88
commit
3c25710f43
33
run/log_tee.run
Normal file
33
run/log_tee.run
Normal file
@@ -0,0 +1,33 @@
|
||||
build "core init server/log_tee test/printf"
|
||||
|
||||
create_boot_directory
|
||||
|
||||
install_config {
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="LOG"/>
|
||||
<service name="RM"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> </any-service>
|
||||
</default-route>
|
||||
|
||||
<start name="log_tee">
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<provides> <service name="LOG"/> </provides>
|
||||
</start>
|
||||
|
||||
<start name="test-printf">
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<route>
|
||||
<any-service> <child name="log_tee"/> <parent/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
</config>
|
||||
}
|
||||
|
||||
build_boot_image "core init log_tee test-printf"
|
||||
|
||||
append qemu_args "-nographic -m 64"
|
||||
|
||||
run_genode_until {child "test-printf" exited with exit value 0} 10
|
||||
41
src/server/log_tee/README
Normal file
41
src/server/log_tee/README
Normal file
@@ -0,0 +1,41 @@
|
||||
Log_tee is a LOG shim server that writes client messages to
|
||||
dedicated LOG sessions as well as a global component log. The
|
||||
effect is that log messages are duplicated into two streams.
|
||||
|
||||
This component pays for each client session from its own quota,
|
||||
client quota donations are forwarded to the LOG backends. This
|
||||
is to prevent naive client donations from being depleted before
|
||||
reaching the final logging destination.
|
||||
|
||||
Example: log messages should be written to the file-system,
|
||||
the screen, and the kernel log.
|
||||
|
||||
⇊
|
||||
log_tee → terminal_log (on-screen)
|
||||
⇊
|
||||
log_tee → parent (kernel)
|
||||
⇊
|
||||
fs_log (file-system)
|
||||
|
||||
!
|
||||
! <start name="terminal_log"> ... </start>
|
||||
! <start name="fs_log"> ... </start>
|
||||
!
|
||||
! <start name="log_tee_2">
|
||||
! <binary name="log_tee"/>
|
||||
! <resource name="RAM" quantum="4M"/>
|
||||
! <provides> <service name="LOG"/> </provides>
|
||||
! <route>
|
||||
! <service name="LOG" label=""> <child name="terminal_log"/> </service>
|
||||
! <service name="LOG"> <child name="log_tee_1"/> </service>
|
||||
! </start>
|
||||
!
|
||||
! <start name="log_tee_1">
|
||||
! <binary name="log_tee"/>
|
||||
! <resource name="RAM" quantum="4M"/>
|
||||
! <provides> <service name="LOG"/> </provides>
|
||||
! <route>
|
||||
! <service name="LOG" label=""> <parent/> </service>
|
||||
! <service name="LOG"> <child name="fs_log"/> </service>
|
||||
! </start>
|
||||
!
|
||||
109
src/server/log_tee/component.cc
Normal file
109
src/server/log_tee/component.cc
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* \brief Server that duplicates log streams
|
||||
* \author Emery Hemingway
|
||||
* \date 2016-07-28
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <log_session/connection.h>
|
||||
#include <root/component.h>
|
||||
#include <base/component.h>
|
||||
#include <base/session_label.h>
|
||||
#include <base/log.h>
|
||||
#include <base/snprintf.h>
|
||||
#include <util/list.h>
|
||||
|
||||
namespace Log_tee {
|
||||
|
||||
using namespace Genode;
|
||||
class Session_component;
|
||||
class Root_component;
|
||||
|
||||
}
|
||||
|
||||
|
||||
class Log_tee::Session_component : public Rpc_object<Log_session>
|
||||
{
|
||||
private:
|
||||
|
||||
/* craft our own connection to get a label in */
|
||||
struct Log_connection : Connection<Log_session>, Log_session_client
|
||||
{
|
||||
Log_connection(Env &env, char const *args)
|
||||
:
|
||||
Connection<Log_session>(env, session(env.parent(), args)),
|
||||
Log_session_client(cap())
|
||||
{ }
|
||||
} _log;
|
||||
|
||||
char _prefix[Session_label::capacity()+3];
|
||||
|
||||
public:
|
||||
|
||||
Session_component(Env &env, Session_label const &label, char const *args)
|
||||
: _log(env, args)
|
||||
{ snprintf(_prefix, sizeof(_prefix), "[%s] ", label.string()); }
|
||||
|
||||
size_t write(Log_session::String const &msg) override
|
||||
{
|
||||
/* write to the dedicated client log session */
|
||||
size_t n = _log.write(msg);
|
||||
|
||||
/* write to our own log session */
|
||||
log((char const *)_prefix, msg.string());
|
||||
|
||||
return n;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Log_tee::Root_component :
|
||||
public Genode::Root_component<Log_tee::Session_component>
|
||||
{
|
||||
private:
|
||||
|
||||
Env &_env;
|
||||
|
||||
protected:
|
||||
|
||||
Log_tee::Session_component *_create_session(char const *args) override
|
||||
{
|
||||
Session_label const label = label_from_args(args);
|
||||
|
||||
try { return new (md_alloc()) Session_component(_env, label, args); }
|
||||
catch (Genode::Parent::Service_denied) { throw Root::Unavailable(); }
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Root_component(Env &env, Allocator &alloc)
|
||||
:
|
||||
Genode::Root_component<Log_tee::Session_component>(env.ep(), alloc),
|
||||
_env(env)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
Genode::size_t Component::stack_size() { return 2*1024*sizeof(Genode::addr_t); }
|
||||
|
||||
void Component::construct(Genode::Env &env)
|
||||
{
|
||||
/*
|
||||
* Client sessions are not allocated on seperate dataspaces,
|
||||
* they are allocated on a heap against the component's own
|
||||
* RAM quota. The session RAM donation is passed verbatim to
|
||||
* the backend session.
|
||||
*/
|
||||
|
||||
static Genode::Heap heap(env.ram(), env.rm());
|
||||
static Log_tee::Root_component root(env, heap);
|
||||
|
||||
env.parent().announce(env.ep().manage(root));
|
||||
}
|
||||
3
src/server/log_tee/target.mk
Normal file
3
src/server/log_tee/target.mk
Normal file
@@ -0,0 +1,3 @@
|
||||
TARGET := log_tee
|
||||
SRC_CC := component.cc
|
||||
LIBS := base
|
||||
Reference in New Issue
Block a user