diff --git a/repos/gems/src/lib/vfs/trace/directory_dictionary.h b/repos/gems/src/lib/vfs/trace/directory_dictionary.h new file mode 100644 index 0000000000..0242fb1db1 --- /dev/null +++ b/repos/gems/src/lib/vfs/trace/directory_dictionary.h @@ -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 +#include "session_label.h" + +namespace Vfs { + class Label; + class Trace_node; + class Trace_directory; + + using Dictionary = Genode::Dictionary; +}; + + +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_ */ diff --git a/repos/gems/src/lib/vfs/trace/directory_tree.h b/repos/gems/src/lib/vfs/trace/directory_tree.h deleted file mode 100644 index 7930740548..0000000000 --- a/repos/gems/src/lib/vfs/trace/directory_tree.h +++ /dev/null @@ -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 -#include "session_label.h" - - -namespace Vfs { - class Directory_tree; - class Trace_node; - struct Label; -} - - -namespace Genode { - template class Avl_node_tree; -} - - -template -class Genode::Avl_node_tree : public NT -{ - protected: - - using Tree = Avl_tree; - using Node = Avl_node; - - 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 -{ - 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(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(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 -{ - 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_ */ diff --git a/repos/gems/src/lib/vfs/trace/vfs.cc b/repos/gems/src/lib/vfs/trace/vfs.cc index a857a34bd3..8f5abb9a5c 100644 --- a/repos/gems/src/lib/vfs/trace/vfs.cc +++ b/repos/gems/src/lib/vfs/trace/vfs.cc @@ -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 #include -#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"; }