mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-31 08:25:38 +00:00
server/fs_log: improve client isolation
Use a seperate handle at each session. Use SEEK_TAIL to append messages to files. Increase packet buffer. Refactor to component framework. Fixes #1777 Issue #2060
This commit is contained in:
parent
6018f594cf
commit
482576fabb
@ -341,8 +341,8 @@ class Genode::Path_base
|
|||||||
|
|
||||||
|
|
||||||
template <unsigned MAX_LEN>
|
template <unsigned MAX_LEN>
|
||||||
class Genode::Path : public Path_base {
|
class Genode::Path : public Path_base
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
char _buf[MAX_LEN];
|
char _buf[MAX_LEN];
|
||||||
@ -371,8 +371,16 @@ class Genode::Path : public Path_base {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Path(Path const &other) : Path_base(_buf, sizeof(_buf), other._buf) { }
|
||||||
|
|
||||||
|
Path& operator=(Path const &other)
|
||||||
|
{
|
||||||
|
Genode::strncpy(_buf, other._buf, MAX_LEN);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
template <unsigned N>
|
template <unsigned N>
|
||||||
Path& operator=(Path<N> &other)
|
Path& operator=(Path<N> const &other)
|
||||||
{
|
{
|
||||||
Genode::strncpy(_buf, other._buf, MAX_LEN);
|
Genode::strncpy(_buf, other._buf, MAX_LEN);
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -20,6 +20,8 @@ set config {
|
|||||||
<service name="RAM"/>
|
<service name="RAM"/>
|
||||||
<service name="RM"/>
|
<service name="RM"/>
|
||||||
<service name="ROM"/>
|
<service name="ROM"/>
|
||||||
|
<service name="IO_PORT"/>
|
||||||
|
<service name="IRQ"/>
|
||||||
</parent-provides>
|
</parent-provides>
|
||||||
<default-route>
|
<default-route>
|
||||||
<any-service> <parent/> <any-child/> </any-service>
|
<any-service> <parent/> <any-child/> </any-service>
|
||||||
@ -67,4 +69,4 @@ build_boot_image "core init ld.lib.so bomb timer vfs fs_log"
|
|||||||
|
|
||||||
append qemu_args " -nographic"
|
append qemu_args " -nographic"
|
||||||
|
|
||||||
run_genode_until "Done\. Going to sleep\." $timeout
|
run_genode_until {.*\[0] Done\..*\n} $timeout
|
||||||
|
@ -9,6 +9,9 @@ through session policy, as well the option to merge the logs of any
|
|||||||
session matching a given policy. When a merged policy label contains a
|
session matching a given policy. When a merged policy label contains a
|
||||||
trailing "->", the log filename takes the name of the next label element.
|
trailing "->", the log filename takes the name of the next label element.
|
||||||
|
|
||||||
|
When a default-policy node specifies a merge, all sessions are merged into
|
||||||
|
the file "/log".
|
||||||
|
|
||||||
:Example configuration:
|
:Example configuration:
|
||||||
! <start name="log_file">
|
! <start name="log_file">
|
||||||
! <resource name="RAM" quantum="1M"/>
|
! <resource name="RAM" quantum="1M"/>
|
||||||
@ -16,7 +19,7 @@ trailing "->", the log filename takes the name of the next label element.
|
|||||||
! <config>
|
! <config>
|
||||||
! <policy label="nic_drv" truncate="no"/>
|
! <policy label="nic_drv" truncate="no"/>
|
||||||
! <policy label_prefix="cli_monitor -> " merge="yes"/>
|
! <policy label_prefix="cli_monitor -> " merge="yes"/>
|
||||||
! <policy truncate="yes"/>
|
! <default-policy truncate="yes"/>
|
||||||
! </config>
|
! </config>
|
||||||
! </start>
|
! </start>
|
||||||
|
|
||||||
|
@ -1,97 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief File object shared between log sessions
|
|
||||||
* \author Emery Hemingway
|
|
||||||
* \date 2015-06-09
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2015 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _FS_LOG__LOG_FILE_H_
|
|
||||||
#define _FS_LOG__LOG_FILE_H_
|
|
||||||
|
|
||||||
/* Genode includes */
|
|
||||||
#include <log_session/log_session.h>
|
|
||||||
#include <file_system_session/file_system_session.h>
|
|
||||||
|
|
||||||
namespace Fs_log {
|
|
||||||
|
|
||||||
using namespace Genode;
|
|
||||||
using namespace File_system;
|
|
||||||
|
|
||||||
class Log_file;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class Fs_log::Log_file : public List<Log_file>::Element
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
char _dir_path[ MAX_PATH_LEN];
|
|
||||||
char _file_name[MAX_NAME_LEN];
|
|
||||||
File_system::Session &_fs;
|
|
||||||
File_handle _handle;
|
|
||||||
seek_off_t _offset;
|
|
||||||
int _clients;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
Log_file(File_system::Session &fs, File_handle handle,
|
|
||||||
char const *dir_path, char const *file_name,
|
|
||||||
seek_off_t offset)
|
|
||||||
:
|
|
||||||
_fs(fs), _handle(handle), _offset(offset), _clients(0)
|
|
||||||
{
|
|
||||||
strncpy(_dir_path, dir_path, sizeof(_dir_path));
|
|
||||||
strncpy(_file_name, file_name, sizeof(_file_name));
|
|
||||||
}
|
|
||||||
|
|
||||||
~Log_file() { _fs.close(_handle); }
|
|
||||||
|
|
||||||
bool match(char const *dir, char const *filename) const
|
|
||||||
{
|
|
||||||
return
|
|
||||||
(strcmp(_dir_path, dir, MAX_PATH_LEN) == 0) &&
|
|
||||||
(strcmp(_file_name, filename, MAX_NAME_LEN) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void incr() { ++_clients; }
|
|
||||||
void decr() { --_clients; }
|
|
||||||
int client_count() const { return _clients; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a log message to the packet buffer.
|
|
||||||
*/
|
|
||||||
size_t write(char const *msg, size_t msg_len)
|
|
||||||
{
|
|
||||||
File_system::Session::Tx::Source &source = *_fs.tx();
|
|
||||||
|
|
||||||
File_system::Packet_descriptor raw_packet;
|
|
||||||
if (!source.ready_to_submit())
|
|
||||||
raw_packet = source.get_acked_packet();
|
|
||||||
else
|
|
||||||
raw_packet = source.alloc_packet(Log_session::String::MAX_SIZE);
|
|
||||||
|
|
||||||
File_system::Packet_descriptor
|
|
||||||
packet(raw_packet,
|
|
||||||
_handle, File_system::Packet_descriptor::WRITE,
|
|
||||||
msg_len, _offset);
|
|
||||||
|
|
||||||
_offset += msg_len;
|
|
||||||
|
|
||||||
char *buf = source.packet_content(packet);
|
|
||||||
memcpy(buf, msg, msg_len);
|
|
||||||
|
|
||||||
source.submit_packet(packet);
|
|
||||||
return msg_len;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -13,16 +13,17 @@
|
|||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <base/heap.h>
|
#include <base/heap.h>
|
||||||
#include <os/path.h>
|
|
||||||
#include <file_system_session/connection.h>
|
#include <file_system_session/connection.h>
|
||||||
#include <file_system/util.h>
|
#include <file_system/util.h>
|
||||||
#include <root/component.h>
|
#include <os/path.h>
|
||||||
#include <os/server.h>
|
|
||||||
#include <os/session_policy.h>
|
#include <os/session_policy.h>
|
||||||
|
#include <base/heap.h>
|
||||||
|
#include <base/attached_rom_dataspace.h>
|
||||||
|
#include <root/component.h>
|
||||||
|
#include <base/component.h>
|
||||||
#include <base/log.h>
|
#include <base/log.h>
|
||||||
|
|
||||||
/* Local includes */
|
/* Local includes */
|
||||||
#include "log_file.h"
|
|
||||||
#include "session.h"
|
#include "session.h"
|
||||||
|
|
||||||
namespace Fs_log {
|
namespace Fs_log {
|
||||||
@ -31,35 +32,34 @@ namespace Fs_log {
|
|||||||
using namespace File_system;
|
using namespace File_system;
|
||||||
|
|
||||||
class Root_component;
|
class Root_component;
|
||||||
struct Main;
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
BLOCK_SIZE = Log_session::String::MAX_SIZE,
|
PACKET_SIZE = Log_session::String::MAX_SIZE,
|
||||||
QUEUE_SIZE = File_system::Session::TX_QUEUE_SIZE,
|
QUEUE_SIZE = File_system::Session::TX_QUEUE_SIZE,
|
||||||
TX_BUF_SIZE = BLOCK_SIZE * (QUEUE_SIZE*2 + 1)
|
TX_BUF_SIZE = PACKET_SIZE * (QUEUE_SIZE+2)
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef Genode::Path<File_system::MAX_PATH_LEN> Path;
|
typedef Genode::Path<File_system::MAX_PATH_LEN> Path;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Fs_log::Root_component :
|
class Fs_log::Root_component :
|
||||||
public Genode::Root_component<Fs_log::Session_component>
|
public Genode::Root_component<Fs_log::Session_component>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Allocator_avl _write_alloc;
|
Genode::Env &_env;
|
||||||
File_system::Connection _fs;
|
Genode::Attached_rom_dataspace _config_rom { _env, "config" };
|
||||||
List<Log_file> _log_files;
|
Genode::Heap _heap { _env.ram(), _env.rm() };
|
||||||
|
Allocator_avl _tx_alloc { &_heap };
|
||||||
|
File_system::Connection _fs
|
||||||
|
{ _env, _tx_alloc, "", "/", true, TX_BUF_SIZE };
|
||||||
|
|
||||||
Log_file *lookup(char const *dir, char const *filename)
|
void _update_config() { _config_rom.update(); }
|
||||||
{
|
|
||||||
for (Log_file *file = _log_files.first(); file; file = file->next())
|
|
||||||
if (file->match(dir, filename))
|
|
||||||
return file;
|
|
||||||
|
|
||||||
return 0;
|
Genode::Signal_handler<Root_component> _config_handler
|
||||||
}
|
{ _env.ep(), *this, &Root_component::_update_config };
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
@ -67,30 +67,29 @@ class Fs_log::Root_component :
|
|||||||
{
|
{
|
||||||
using namespace File_system;
|
using namespace File_system;
|
||||||
|
|
||||||
char dir_path[MAX_PATH_LEN];
|
size_t ram_quota =
|
||||||
|
Arg_string::find_arg(args, "ram_quota").aligned_size();
|
||||||
|
if (ram_quota < sizeof(Session_component))
|
||||||
|
throw Root::Quota_exceeded();
|
||||||
|
|
||||||
|
Path dir_path;
|
||||||
char file_name[MAX_NAME_LEN];
|
char file_name[MAX_NAME_LEN];
|
||||||
|
|
||||||
dir_path[0] = '/';
|
|
||||||
|
|
||||||
bool truncate = false;
|
|
||||||
Session_label const session_label = label_from_args(args);
|
Session_label const session_label = label_from_args(args);
|
||||||
char const *label_str = session_label.string();
|
char const *label_str = session_label.string();
|
||||||
char const *label_prefix = "";
|
char const *label_prefix = "";
|
||||||
|
bool truncate = false;
|
||||||
strncpy(dir_path+1, label_str, MAX_PATH_LEN-1);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Session_policy policy(session_label);
|
Session_policy policy(session_label, _config_rom.xml());
|
||||||
truncate = policy.attribute_value("truncate", truncate);
|
truncate = policy.attribute_value("truncate", truncate);
|
||||||
|
bool merge = policy.attribute_value("merge", false);
|
||||||
|
|
||||||
if (policy.attribute_value("merge", false)
|
/* only a match on 'label_prefix' can be merged */
|
||||||
&& policy.has_attribute("label_prefix")) {
|
if (merge && policy.has_type("policy")
|
||||||
|
&& (!(policy.has_attribute("label")
|
||||||
if (!dir_path[1]) {
|
|| policy.has_attribute("label_suffix"))))
|
||||||
Genode::error("cannot merge an empty policy label");
|
{
|
||||||
throw Root::Unavailable();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* split the label between what will be the log file
|
* split the label between what will be the log file
|
||||||
* and what will be prepended to messages in the file
|
* and what will be prepended to messages in the file
|
||||||
@ -100,103 +99,75 @@ class Fs_log::Root_component :
|
|||||||
if (strcmp(label_str+i, " -> ", 4))
|
if (strcmp(label_str+i, " -> ", 4))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
dir_path[i+1] = '\0';
|
|
||||||
label_prefix = label_str+i+4;
|
label_prefix = label_str+i+4;
|
||||||
|
{
|
||||||
|
char tmp[128];
|
||||||
|
strncpy(tmp, label_str, min(sizeof(tmp), i+1));
|
||||||
|
dir_path = path_from_label<Path>(tmp);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
if (dir_path == "/")
|
||||||
} catch (Session_policy::No_policy_defined) { }
|
dir_path = path_from_label<Path>(label_str);
|
||||||
|
|
||||||
|
} else if (!policy.has_type("default-policy")) {
|
||||||
{
|
dir_path = path_from_label<Path>(label_str);
|
||||||
/* Parse out a directory and file name. */
|
|
||||||
size_t len = strlen(dir_path);
|
|
||||||
size_t start = 1;
|
|
||||||
for (size_t i = 1; i < len;) {
|
|
||||||
/* Replace any slashes in label elements. */
|
|
||||||
if (dir_path[i] == '/') dir_path[i] = '_';
|
|
||||||
if (strcmp(" -> ", dir_path+i, 4) == 0) {
|
|
||||||
dir_path[i++] = '/';
|
|
||||||
strncpy(dir_path+i, dir_path+i+3, MAX_PATH_LEN-i);
|
|
||||||
start = i;
|
|
||||||
i += 3;
|
|
||||||
} else ++i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy the remainder to the file name. */
|
} catch (Session_policy::No_policy_defined) {
|
||||||
snprintf(file_name, MAX_NAME_LEN, "%s.log", dir_path+start);
|
dir_path = path_from_label<Path>(label_str);
|
||||||
|
|
||||||
/* Terminate the directory path. */
|
|
||||||
dir_path[(start == 1) ? start : start-1] = '\0';
|
|
||||||
|
|
||||||
/* Rewrite any slashes in the name. */
|
|
||||||
for (char *p = file_name; *p; ++p)
|
|
||||||
if (*p == '/') *p = '_';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Log_file *file = lookup(dir_path, file_name);
|
if (dir_path == "/") {
|
||||||
if (!file) try {
|
strncpy(file_name, "log", sizeof(file_name));
|
||||||
|
label_prefix = label_str;
|
||||||
|
} else {
|
||||||
|
dir_path.append(".log");
|
||||||
|
strncpy(file_name, dir_path.last_element(), sizeof(file_name));
|
||||||
|
dir_path.strip_last_element();
|
||||||
|
dir_path.remove_trailing('/');
|
||||||
|
}
|
||||||
|
|
||||||
Dir_handle dir_handle = ensure_dir(_fs, dir_path);
|
char const *errstr;
|
||||||
|
try {
|
||||||
|
|
||||||
|
Dir_handle dir_handle = ensure_dir(_fs, dir_path.base());
|
||||||
Handle_guard dir_guard(_fs, dir_handle);
|
Handle_guard dir_guard(_fs, dir_handle);
|
||||||
File_handle handle;
|
File_handle handle;
|
||||||
seek_off_t offset = 0;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
handle = _fs.file(dir_handle, file_name,
|
handle = _fs.file(dir_handle, file_name,
|
||||||
File_system::WRITE_ONLY, false);
|
File_system::WRITE_ONLY, false);
|
||||||
|
|
||||||
if (truncate)
|
/* don't truncate at every new child session */
|
||||||
|
if (truncate && (strcmp(label_prefix, "") == 0))
|
||||||
_fs.truncate(handle, 0);
|
_fs.truncate(handle, 0);
|
||||||
else
|
|
||||||
offset = _fs.status(handle).size;
|
|
||||||
|
|
||||||
} catch (File_system::Lookup_failed) {
|
} catch (File_system::Lookup_failed) {
|
||||||
handle = _fs.file(dir_handle, file_name,
|
handle = _fs.file(dir_handle, file_name,
|
||||||
File_system::WRITE_ONLY, true);
|
File_system::WRITE_ONLY, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
file = new (env()->heap())
|
return new (md_alloc()) Session_component(_fs, handle, label_prefix);
|
||||||
Log_file(_fs, handle, dir_path, file_name, offset);
|
|
||||||
|
|
||||||
_log_files.insert(file);
|
|
||||||
|
|
||||||
} catch (Permission_denied) {
|
|
||||||
error(Path(file_name, dir_path), ": permission denied");
|
|
||||||
|
|
||||||
} catch (No_space) {
|
|
||||||
error("file system out of space");
|
|
||||||
|
|
||||||
} catch (Out_of_metadata) {
|
|
||||||
error("file system server out of metadata");
|
|
||||||
|
|
||||||
} catch (Invalid_name) {
|
|
||||||
error(Path(file_name, dir_path), ": invalid path");
|
|
||||||
|
|
||||||
} catch (Name_too_long) {
|
|
||||||
error(Path(file_name, dir_path), ": name too long");
|
|
||||||
|
|
||||||
} catch (...) {
|
|
||||||
error("cannot open log file ", Path(file_name, dir_path));
|
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!file)
|
catch (Permission_denied) {
|
||||||
|
errstr = "permission denied"; }
|
||||||
|
catch (No_space) {
|
||||||
|
errstr = "file system out of space"; }
|
||||||
|
catch (Out_of_metadata) {
|
||||||
|
errstr = "file system server out of metadata"; }
|
||||||
|
catch (Invalid_name) {
|
||||||
|
errstr = "invalid path"; }
|
||||||
|
catch (Name_too_long) {
|
||||||
|
errstr = "name too long"; }
|
||||||
|
catch (...) {
|
||||||
|
errstr = "unhandled error"; }
|
||||||
|
|
||||||
|
Genode::error("cannot open log file ",
|
||||||
|
(char const *)dir_path.base(),
|
||||||
|
", ", errstr);
|
||||||
throw Root::Unavailable();
|
throw Root::Unavailable();
|
||||||
|
|
||||||
if (*label_prefix)
|
|
||||||
return new (md_alloc()) Labeled_session_component(label_prefix, *file);
|
|
||||||
return new (md_alloc()) Unlabeled_session_component(*file);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _destroy_session(Session_component *session)
|
|
||||||
{
|
|
||||||
Log_file *file = session->file();
|
|
||||||
destroy(md_alloc(), session);
|
|
||||||
if (file->client_count() < 1) {
|
|
||||||
_log_files.remove(file);
|
|
||||||
destroy(env()->heap(), file);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -204,39 +175,32 @@ class Fs_log::Root_component :
|
|||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
Root_component(Server::Entrypoint &ep, Allocator &alloc)
|
Root_component(Genode::Env &env, Genode::Allocator &md_alloc)
|
||||||
:
|
:
|
||||||
Genode::Root_component<Session_component>(&ep.rpc_ep(), &alloc),
|
Genode::Root_component<Session_component>(&env.ep().rpc_ep(), &md_alloc),
|
||||||
_write_alloc(env()->heap()),
|
_env(env)
|
||||||
_fs(_write_alloc, TX_BUF_SIZE)
|
{
|
||||||
{ }
|
_config_rom.sigh(_config_handler);
|
||||||
|
|
||||||
|
/* fill the ack queue with packets so sessions never need to alloc */
|
||||||
|
File_system::Session::Tx::Source &source = *_fs.tx();
|
||||||
|
for (int i = 0; i < QUEUE_SIZE-1; ++i)
|
||||||
|
source.submit_packet(source.alloc_packet(PACKET_SIZE));
|
||||||
|
|
||||||
|
env.parent().announce(env.ep().manage(*this));
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Fs_log::Main
|
|
||||||
|
/***************
|
||||||
|
** Component **
|
||||||
|
***************/
|
||||||
|
|
||||||
|
Genode::size_t Component::stack_size() { return 4*1024*sizeof(long); }
|
||||||
|
|
||||||
|
void Component::construct(Genode::Env &env)
|
||||||
{
|
{
|
||||||
Server::Entrypoint &ep;
|
static Genode::Sliced_heap sliced_heap { env.ram(), env.rm() };
|
||||||
|
static Fs_log::Root_component root { env, sliced_heap };
|
||||||
Sliced_heap sliced_heap = { env()->ram_session(), env()->rm_session() };
|
|
||||||
|
|
||||||
Root_component root { ep, sliced_heap };
|
|
||||||
|
|
||||||
Main(Server::Entrypoint &ep)
|
|
||||||
: ep(ep)
|
|
||||||
{ Genode::env()->parent()->announce(ep.manage(root)); }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/************
|
|
||||||
** Server **
|
|
||||||
************/
|
|
||||||
|
|
||||||
namespace Server {
|
|
||||||
|
|
||||||
char const* name() { return "fs_log_ep"; }
|
|
||||||
|
|
||||||
size_t stack_size() { return 3*512*sizeof(long); }
|
|
||||||
|
|
||||||
void construct(Entrypoint &ep) { static Fs_log::Main inst(ep); }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2015 Genode Labs GmbH
|
* Copyright (C) 2016 Genode Labs GmbH
|
||||||
*
|
*
|
||||||
* This file is part of the Genode OS framework, which is distributed
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
@ -21,98 +21,94 @@
|
|||||||
#include <log_session/log_session.h>
|
#include <log_session/log_session.h>
|
||||||
#include <file_system_session/file_system_session.h>
|
#include <file_system_session/file_system_session.h>
|
||||||
#include <base/rpc_server.h>
|
#include <base/rpc_server.h>
|
||||||
|
#include <base/snprintf.h>
|
||||||
/* Local includes */
|
#include <base/log.h>
|
||||||
#include "log_file.h"
|
|
||||||
|
|
||||||
namespace Fs_log {
|
namespace Fs_log {
|
||||||
|
|
||||||
|
enum { MAX_LABEL_LEN = 128 };
|
||||||
|
|
||||||
class Session_component;
|
class Session_component;
|
||||||
class Unlabeled_session_component;
|
|
||||||
class Labeled_session_component;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Fs_log::Session_component : public Rpc_object<Log_session, Unlabeled_session_component>
|
class Fs_log::Session_component : public Genode::Rpc_object<Genode::Log_session>
|
||||||
{
|
|
||||||
protected:
|
|
||||||
|
|
||||||
Log_file &_log_file;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Session_component(Log_file &log_file)
|
|
||||||
: _log_file(log_file) { _log_file.incr(); }
|
|
||||||
|
|
||||||
~Session_component() { _log_file.decr(); }
|
|
||||||
|
|
||||||
Log_file *file() const { return &_log_file; }
|
|
||||||
|
|
||||||
virtual size_t write(String const &string) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Fs_log::Unlabeled_session_component : public Session_component
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
Unlabeled_session_component(Log_file &log_file)
|
|
||||||
: Session_component(log_file) { }
|
|
||||||
|
|
||||||
/*****************
|
|
||||||
** Log session **
|
|
||||||
*****************/
|
|
||||||
|
|
||||||
size_t write(Log_session::String const &msg)
|
|
||||||
{
|
|
||||||
if (!msg.valid_string()) {
|
|
||||||
Genode::error("corrupted string");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
char const *msg_str = msg.string();
|
|
||||||
size_t msg_len = Genode::strlen(msg_str);
|
|
||||||
|
|
||||||
return _log_file.write(msg_str, msg_len);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class Fs_log::Labeled_session_component : public Session_component
|
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
char _label[Log_session::String::MAX_SIZE];
|
char _label_buf[MAX_LABEL_LEN];
|
||||||
size_t _label_len;
|
Genode::size_t const _label_len;
|
||||||
|
|
||||||
|
File_system::Session &_fs;
|
||||||
|
File_system::File_handle const _handle;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
Session_component(File_system::Session &fs,
|
||||||
* Constructor
|
File_system::File_handle handle,
|
||||||
*/
|
char const *label)
|
||||||
Labeled_session_component(char const *label, Log_file &log_file)
|
:
|
||||||
: Session_component(log_file)
|
_label_len(Genode::strlen(label) ? Genode::strlen(label)+3 : 0),
|
||||||
|
_fs(fs), _handle(handle)
|
||||||
{
|
{
|
||||||
snprintf(_label, sizeof(_label), "[%s] ", label);
|
if (_label_len)
|
||||||
_label_len = strlen(_label);
|
Genode::snprintf(_label_buf, MAX_LABEL_LEN, "[%s] ", label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~Session_component()
|
||||||
|
{
|
||||||
|
_fs.sync(_handle);
|
||||||
|
_fs.close(_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*****************
|
/*****************
|
||||||
** Log session **
|
** Log session **
|
||||||
*****************/
|
*****************/
|
||||||
|
|
||||||
size_t write(Log_session::String const &msg)
|
Genode::size_t write(Log_session::String const &msg)
|
||||||
{
|
{
|
||||||
if (!msg.valid_string()) {
|
using namespace Genode;
|
||||||
Genode::error("corrupted string");
|
|
||||||
|
if (!msg.is_valid_string()) {
|
||||||
|
Genode::error("received corrupted string");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char const *msg_str = msg.string();
|
size_t msg_len = strlen(msg.string());
|
||||||
size_t msg_len = Genode::strlen(msg_str);
|
|
||||||
|
|
||||||
_log_file.write(_label, _label_len);
|
File_system::Session::Tx::Source &source = *_fs.tx();
|
||||||
return _log_file.write(msg_str, msg_len);
|
|
||||||
|
File_system::Packet_descriptor packet(
|
||||||
|
source.get_acked_packet(),
|
||||||
|
_handle, File_system::Packet_descriptor::WRITE,
|
||||||
|
msg_len, File_system::SEEK_TAIL);
|
||||||
|
|
||||||
|
char *buf = source.packet_content(packet);
|
||||||
|
|
||||||
|
if (_label_len) {
|
||||||
|
memcpy(buf, _label_buf, _label_len);
|
||||||
|
|
||||||
|
if (_label_len+msg_len > Log_session::String::MAX_SIZE) {
|
||||||
|
packet.length(msg_len);
|
||||||
|
source.submit_packet(packet);
|
||||||
|
|
||||||
|
packet = File_system::Packet_descriptor(
|
||||||
|
source.get_acked_packet(),
|
||||||
|
_handle, File_system::Packet_descriptor::WRITE,
|
||||||
|
msg_len, File_system::SEEK_TAIL);
|
||||||
|
|
||||||
|
buf = source.packet_content(packet);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
buf += _label_len;
|
||||||
|
packet.length(_label_len+msg_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buf, msg.string(), msg_len);
|
||||||
|
|
||||||
|
source.submit_packet(packet);
|
||||||
|
return msg_len;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
TARGET = fs_log
|
TARGET = fs_log
|
||||||
SRC_CC = main.cc
|
SRC_CC = main.cc
|
||||||
LIBS = base config server
|
LIBS = base
|
||||||
|
@ -67,3 +67,4 @@ rust
|
|||||||
xml_node
|
xml_node
|
||||||
fpu
|
fpu
|
||||||
ds_ownership
|
ds_ownership
|
||||||
|
fs_log
|
||||||
|
Loading…
x
Reference in New Issue
Block a user