vfs_trace: replace use of Avl_string by Dictionary

issue #4780
This commit is contained in:
Sebastian Sumpf 2023-03-09 21:59:56 +01:00 committed by Christian Helmuth
parent ae0e0c118e
commit c14007f559
3 changed files with 136 additions and 158 deletions

View File

@ -0,0 +1,129 @@
/*
* \brief A dictionary of dictionaries that form a directory structure
* \author Sebastian Sumpf
* \date 2023-03-09
*/
/*
* Copyright (C) 2023 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _DIRECTORY_DICTIONARY_H_
#define _DIRECTORY_DICTIONARY_H_
#include <util/dictionary.h>
#include "session_label.h"
namespace Vfs {
class Label;
class Trace_node;
class Trace_directory;
using Dictionary = Genode::Dictionary<Vfs::Trace_node, Vfs::Label>;
};
struct Vfs::Label : Genode::String<32>
{
using String::String;
};
class Vfs::Trace_node : public Dictionary::Element
{
private:
Allocator &_alloc;
Trace::Subject_id const _id;
Dictionary _dict { };
/* add version to duplicates (like "idle" or "cross" */
Label _thread_name(Session_label const &thread_name)
{
if (!_dict.exists(thread_name)) return Label(thread_name);
unsigned version { 0 };
while (true) {
Label label { thread_name, ".", ++version };
if (!_dict.exists(label)) return label;
}
}
public:
Trace_node(Allocator &alloc, Dictionary &dict, Session_label const &label,
Trace::Subject_id const id = 0)
:
Dictionary::Element(dict, Label(label)),
_alloc(alloc), _id(id)
{ }
void insert(Session_label const &label,
Session_label const &thread_name,
Trace::Subject_id const id)
{
/* leaf node -> thread_name<.version> */
if (!label.valid()) {
new (_alloc) Trace_node(_alloc, _dict, _thread_name(thread_name), id);
return;
}
_dict.with_element(label.first_element(),
[&] (Trace_node &node) {
node.insert(label.suffix(), thread_name, id); },
[&]() {
/* no match add first element of label to this dict */
Trace_node *node = new (_alloc) Trace_node(_alloc, _dict, label.first_element());
node->insert(label.suffix(), thread_name, id);
}
);
}
void xml(Xml_generator &xml) const
{
_dict.for_each([&] (Trace_node const &node) {
if (node.id() == 0)
xml.node("dir", [&] () {
xml.attribute("name", node.name);
node.xml(xml);
});
else
xml.node("trace_node", [&] () {
xml.attribute("name", node.name);
xml.attribute("id", node.id().id);
node.xml(xml);
});
});
}
Trace::Subject_id const &id() const { return _id; }
};
class Vfs::Trace_directory
{
private:
Allocator &_alloc;
Dictionary _root_dict { };
Trace_node _root { _alloc, _root_dict, Session_label() };
public:
Trace_directory(Allocator &alloc) : _alloc(alloc) { }
void insert(Trace::Subject_info const &info, Trace::Subject_id const id)
{
_root.insert(info.session_label(), info.thread_name(), id);
}
void xml(Xml_generator &xml)
{
_root.xml(xml);
}
};
#endif /* _DIRECTORY_DICTIONARY_H_ */

View File

@ -1,150 +0,0 @@
/*
* \brief A tree of AVL trees that forms a directory structure
* \author Sebastian Sumpf
* \date 2019-06-14
*/
/*
* Copyright (C) 2019 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _DIRECTORY_TREE_H_
#define _DIRECTORY_TREE_H_
#include <util/avl_string.h>
#include "session_label.h"
namespace Vfs {
class Directory_tree;
class Trace_node;
struct Label;
}
namespace Genode {
template <typename> class Avl_node_tree;
}
template <typename NT>
class Genode::Avl_node_tree : public NT
{
protected:
using Tree = Avl_tree<NT>;
using Node = Avl_node<NT>;
Tree _tree { };
public:
using NT::NT;
void insert(Node *node) { _tree.insert(node); }
Tree &tree() { return _tree; }
Node *find_by_name(char const *name)
{
if (!_tree.first()) return nullptr;
Node *node = _tree.first()->find_by_name(name);
return node;
}
};
struct Vfs::Label : Genode::String<32>
{
using String::String;
};
class Vfs::Trace_node : public Vfs::Label,
public Avl_node_tree<Genode::Avl_string_base>
{
private:
Allocator &_alloc;
Trace::Subject_id const _id;
Trace_node *_find_by_name(char const *name)
{
Node *node = find_by_name(name);
return node ? static_cast<Trace_node *>(node) : nullptr;
}
public:
Trace_node(Genode::Allocator &alloc, Session_label const &label,
Trace::Subject_id const id = 0)
: Vfs::Label(label), Avl_node_tree(string()),
_alloc(alloc), _id(id)
{ }
Trace_node &insert(Session_label const &label)
{
if (!label.valid()) return *this;
Trace_node *node = _find_by_name(label.first_element().string());
if (!node) {
node = new(_alloc) Trace_node(_alloc, label.first_element());
Avl_node_tree::insert(node);
}
return node->insert(label.suffix());
}
void xml(Genode::Xml_generator &xml) const
{
_tree.for_each([&] (Genode::Avl_string_base const &name) {
Trace_node const &node = static_cast<Trace_node const &>(name);
if (node.id() == 0)
xml.node("dir", [&] () {
xml.attribute("name", node.name());
node.xml(xml);
});
else
xml.node("trace_node", [&] () {
xml.attribute("name", node.name());
xml.attribute("id", node.id().id);
node.xml(xml);
});
});
}
Trace::Subject_id const &id() const { return _id; }
};
class Vfs::Directory_tree : public Genode::Avl_tree<Trace_node>
{
private:
Allocator &_alloc;
Trace_node _root { _alloc, Session_label() };
public:
Directory_tree(Genode::Allocator &alloc)
: _alloc(alloc) { }
void insert(Trace::Subject_info const &info, Trace::Subject_id const id)
{
Trace_node &leaf = _root.insert(info.session_label());
Trace_node *node = new (_alloc) Trace_node(_alloc, info.thread_name(), id);
leaf.Avl_node_tree::insert(node);
}
void xml(Genode::Xml_generator &xml)
{
_root.xml(xml);
}
};
#endif /* _DIRECTORY_TREE_H_ */

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2019 Genode Labs GmbH
* Copyright (C) 2023 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
@ -22,8 +22,7 @@
#include <trace_session/connection.h>
#include <trace/trace_buffer.h>
#include "directory_tree.h"
#include "directory_dictionary.h"
namespace Vfs_trace {
@ -349,7 +348,7 @@ struct Vfs_trace::Local_factory : File_system_factory
Trace::Connection _trace;
Trace::Policy_id _policy_id { 0 };
Directory_tree _tree { _env.alloc() };
Trace_directory _directory { _env.alloc() };
void _install_null_policy()
{
@ -392,7 +391,7 @@ struct Vfs_trace::Local_factory : File_system_factory
if (info.state() == Trace::Subject_info::DEAD)
return;
_tree.insert(info, id);
_directory.insert(info, id);
});
_install_null_policy();
@ -415,11 +414,11 @@ class Vfs_trace::File_system : private Local_factory,
typedef String<512*1024> Config;
static char const *_config(Vfs::Env &vfs_env, Directory_tree &tree)
static char const *_config(Vfs::Env &vfs_env, Trace_directory &directory)
{
char *buf = (char *)vfs_env.alloc().alloc(Config::capacity());
Xml_generator xml(buf, Config::capacity(), "node", [&] () {
tree.xml(xml);
directory.xml(xml);
});
return buf;
@ -429,7 +428,7 @@ class Vfs_trace::File_system : private Local_factory,
File_system(Vfs::Env &vfs_env, Genode::Xml_node node)
: Local_factory(vfs_env, node),
Vfs::Dir_file_system(vfs_env, Xml_node(_config(vfs_env, _tree)), *this)
Vfs::Dir_file_system(vfs_env, Xml_node(_config(vfs_env, _directory)), *this)
{ }
char const *type() override { return "trace"; }