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