diff --git a/test/pitytest11/src/AbstractPityUnit.cc b/test/pitytest11/src/AbstractPityUnit.cc index dce26a6..e8c7fa4 100644 --- a/test/pitytest11/src/AbstractPityUnit.cc +++ b/test/pitytest11/src/AbstractPityUnit.cc @@ -25,18 +25,29 @@ namespace pEp { // static int AbstractPityUnit::procUnitsCount = 0; + AbstractPityUnit::AbstractPityUnit(const std::string &name, ExecutionMode exec_mode) : + PityTree(*this, name), + _exec_mode{ exec_mode } + { + _init(); + } + AbstractPityUnit::AbstractPityUnit( - AbstractPityUnit *const parent, + AbstractPityUnit &parent, const std::string &name, ExecutionMode exec_mode) : - _parent{ parent }, - _name{ _normalizeName(name) }, _exec_mode{ exec_mode } + PityTree(*this, name, parent), + _exec_mode{ exec_mode } + { + _init(); + } + + void AbstractPityUnit::_init() { logger_debug.set_instancename(getPath()); - if (!_isRootUnit()) { - parent->_addChildUnit(*this); + if (!isRoot()) { // Inherit - procUnitNr = _parent->procUnitNr; + procUnitNr = getParent()->procUnitNr; //Or update if procUnit if (_isProcessUnit()) { _createTransport(); @@ -47,36 +58,18 @@ namespace pEp { procUnitNr = procUnitsCount; } } - - std::string AbstractPityUnit::getName() const + // static + void AbstractPityUnit::setGlobalRootDir(const std::string &dir) { - return _name; + AbstractPityUnit::_global_root_dir = dir; } - // name is alphanumeric only (everything else will be replaced by an underscore) // static - std::string AbstractPityUnit::_normalizeName(std::string name) + std::string AbstractPityUnit::getGlobalRootDir() { - replace_if( - name.begin(), - name.end(), - [](char c) -> bool { return !isalnum(c); }, - '_'); - - return name; + return AbstractPityUnit::_global_root_dir; } - std::string AbstractPityUnit::getPath() const - { - std::string ret; - - if (!_isRootUnit()) { - ret = _parent->getPath() + "/" + getName(); - } else { - ret = getName(); - } - return ret; - } // For: // RootUnit - "" @@ -86,13 +79,13 @@ namespace pEp { std::string AbstractPityUnit::getPathShort() const { std::string ret; - if (_isRootUnit()) { + if (isRoot()) { ret = getName(); } else { if (_isProcessUnit()) { ret += ".../" + getName(); } else { - if (&(parentingProcessUnit()) == (_parent)) { + if (&(parentingProcessUnit()) == (getParent())) { ret = parentingProcessUnit().getPathShort() + "/" + getName(); } else { ret = parentingProcessUnit().getPathShort() + "/.../" + getName(); @@ -102,22 +95,17 @@ namespace pEp { return ret; } - AbstractPityUnit *AbstractPityUnit::getParent() const - { - return _parent; - } - // Every process has its own dir inside its rootUnitDir // All other units inherit processDir from their Root/ProcessUnit std::string AbstractPityUnit::processDir() { - if (_isRootUnit()) { + if (isRoot()) { return _rootUnitDir(); } else { if (_isProcessUnit()) { return _rootUnitDir() + getName() + "/"; } else { - return _parent->processDir(); + return getParent()->processDir(); } } } @@ -125,36 +113,24 @@ namespace pEp { // Every RootUnit has its own dir std::string AbstractPityUnit::_rootUnitDir() { - return getGlobalRootDir() + rootUnit()->getName() + "/"; + return getGlobalRootDir() + getRoot().getName() + "/"; } // Every process has its own dir inside its rootUnitDir // All other units inherit transportDir from their Root/ProcessUnit std::string AbstractPityUnit::transportDir() { - if (_isRootUnit()) { + if (isRoot()) { throw std::runtime_error("No transport dir"); } else { if (_isProcessUnit()) { return processDir() + "inbox/"; } else { - return _parent->transportDir(); + return getParent()->transportDir(); } } } - // static - void AbstractPityUnit::setGlobalRootDir(const std::string &dir) - { - AbstractPityUnit::_global_root_dir = dir; - } - - // static - std::string AbstractPityUnit::getGlobalRootDir() - { - return AbstractPityUnit::_global_root_dir; - } - void AbstractPityUnit::run() { pEpLogClass("called"); @@ -163,8 +139,8 @@ namespace pEp { setenv("HOME", processDir().c_str(), true); - if (_isRootUnit()) { - _init(); + if (isRoot()) { + _initrun(); } // Execute in fork and wait here until process ends @@ -182,7 +158,7 @@ namespace pEp { throw std::invalid_argument(to_string(_exec_mode) + " - not implemented"); } - if (_isRootUnit()) { + if (isRoot()) { _waitChildProcesses(); } } @@ -202,9 +178,9 @@ namespace pEp { ret = builder.str(); if (recursive) { - if (!_children.empty()) { + if (!getChildren().empty()) { indent++; - for (const std::pair child : _children) { + for (const auto child : getChildren()) { ret += child.second.to_string(true, indent); } indent--; @@ -236,8 +212,8 @@ namespace pEp { void AbstractPityUnit::recreateDirsRecursively() { Utils::dir_recreate(processDir()); - if (!_children.empty()) { - for (const std::pair child : _children) { + if (!getChildren().empty()) { + for (const auto child : getChildren()) { child.second.recreateDirsRecursively(); } } @@ -250,10 +226,10 @@ namespace pEp { Endpoints &AbstractPityUnit::transportEndpoints() { - if (_isRootUnit()) { + if (isRoot()) { return _transport_endpoints; } else { - return rootUnit()->transportEndpoints(); + return getRoot().transportEndpoints(); } } @@ -286,7 +262,7 @@ namespace pEp { } // PRIVATE --------------------------------------------------------------------------------- - void AbstractPityUnit::_init() + void AbstractPityUnit::_initrun() { logH1("PityTest Starting..."); _logRaw("RootUnit: " + getPathShort()); @@ -310,8 +286,8 @@ namespace pEp { void AbstractPityUnit::_runChildren() const { - if (!_children.empty()) { - for (const std::pair child : _children) { + if (!getChildren().empty()) { + for (const auto child : getChildren()) { child.second.run(); } } @@ -350,11 +326,6 @@ namespace pEp { } } - void AbstractPityUnit::_addChildUnit(AbstractPityUnit &unit) - { - _children.insert(std::pair(unit.getName(), unit)); - } - bool AbstractPityUnit::_isProcessUnit() const { bool ret = false; @@ -365,30 +336,12 @@ namespace pEp { return ret; } - bool AbstractPityUnit::_isRootUnit() const - { - if (_parent == nullptr) { - return true; - } else { - return false; - } - } - - AbstractPityUnit *AbstractPityUnit::rootUnit() - { - if (!_isRootUnit()) { - return _parent->rootUnit(); - } else { - return this; - } - } - const AbstractPityUnit &AbstractPityUnit::parentingProcessUnit() const { - if (_isRootUnit() || _isProcessUnit()) { + if (isRoot() || _isProcessUnit()) { return *this; } else { - return _parent->parentingProcessUnit(); + return getParent()->parentingProcessUnit(); } } @@ -409,8 +362,8 @@ namespace pEp { if (_transport != nullptr) { ret = _transport.get(); } else { - if (!_isRootUnit()) { - ret = _parent->transport(); + if (!isRoot()) { + ret = getParent()->transport(); } } return ret; @@ -449,7 +402,6 @@ namespace pEp { } } - Utils::Color AbstractPityUnit::_termColor() const { return _colForProcUnitNr(procUnitNr); @@ -465,4 +417,3 @@ namespace pEp { } // namespace PityTest11 } // namespace pEp - diff --git a/test/pitytest11/src/AbstractPityUnit.hh b/test/pitytest11/src/AbstractPityUnit.hh index 4f664df..e0511ba 100644 --- a/test/pitytest11/src/AbstractPityUnit.hh +++ b/test/pitytest11/src/AbstractPityUnit.hh @@ -7,6 +7,7 @@ #include "../../../src/pEpLog.hh" #include "../../../src/std_utils.hh" #include "fs_mutex.hh" +#include "PityTree.hh" #include "PityTransport.hh" #include #include @@ -18,7 +19,7 @@ namespace pEp { namespace PityTest11 { - class AbstractPityUnit { + class AbstractPityUnit : public PityTree { public: enum class ExecutionMode { @@ -30,8 +31,9 @@ namespace pEp { INHERIT }; + AbstractPityUnit(const std::string& name, ExecutionMode exec_mode = ExecutionMode::FUNCTION); AbstractPityUnit( - AbstractPityUnit* const parent, + AbstractPityUnit& parent, const std::string& name, ExecutionMode exec_mode = ExecutionMode::FUNCTION); @@ -40,13 +42,9 @@ namespace pEp { static std::string getGlobalRootDir(); // Read-Only - std::string getName() const; - std::string getPath() const; std::string getPathShort() const; std::string processDir(); // own process dir std::string transportDir(); - AbstractPityUnit* getParent() const; - bool _isRootUnit() const; // true if has no parent // Main funcs void run(); @@ -61,8 +59,6 @@ namespace pEp { void logH3(const std::string& msg) const; // Util - static std::string _normalizeName( - std::string name); //TODO HACK in PityTransport this should be private void recreateDirsRecursively(); //Transport @@ -87,17 +83,13 @@ namespace pEp { // METHODS // Execution void _init(); + void _initrun(); void _run(); virtual void _runSelf() = 0; void _runChildren() const; void _executeInFork(std::function func, bool wait_child) const; void _waitChildProcesses() const; - - // Modify - void _addChildUnit(AbstractPityUnit& unit); - - AbstractPityUnit* rootUnit(); const AbstractPityUnit& parentingProcessUnit() const; // Query @@ -107,13 +99,9 @@ namespace pEp { // Transport void _createTransport(); - // Fields // ------ - AbstractPityUnit* _parent; //nullptr if RootUnit - std::map _children; // map to guarantee uniqueness of sibling-names static std::string _global_root_dir; - const std::string _name; int procUnitNr; ExecutionMode _exec_mode; static int procUnitsCount; // will be increased in every constructor diff --git a/test/pitytest11/src/PityTree.hh b/test/pitytest11/src/PityTree.hh new file mode 100644 index 0000000..543d9fa --- /dev/null +++ b/test/pitytest11/src/PityTree.hh @@ -0,0 +1,59 @@ +// This file is under GNU General Public License 3.0 +// see LICENSE.txt + +#ifndef PITYTEST_PITYTREE_HH +#define PITYTEST_PITYTREE_HH + +//#include "../../../src/pEpLog.hh" +#include +#include +#include +#include +#include +#include + +namespace pEp { + namespace PityTest11 { + template + class PityTree { + // TODO: NEEEEED THIS +// static_assert(std::is_base_of, T>::value, "PityTree must be a base of T"); + public: + using Children = std::map; + + explicit PityTree(T& self, const std::string& name); + explicit PityTree(T& self, const std::string& name, T& parent); + + T& add(T& node); + + T* getParent() const; + Children getChildren() const; + + T& getRoot(); + + std::string getName() const; + std::string getPath() const; + bool isRoot() const; // true if has no parent + + std::string to_string(bool recursive = true, int indent = 0); + + //TODO HACK in PityTransport, this should be private + static std::string _normalizeName(std::string name); + + virtual ~PityTree() = default; + + protected: + void setParent(T* const parent); + + private: + // Fields + const std::string _nodename; + T& _self; + T* _parent = nullptr; //nullptr if RootUnit + Children _children; // map to guarantee uniqueness of sibling-names + }; + }; // namespace PityTest11 +}; // namespace pEp + +#include "PityTree.hxx" +#endif diff --git a/test/pitytest11/src/PityTree.hxx b/test/pitytest11/src/PityTree.hxx new file mode 100644 index 0000000..2ec4773 --- /dev/null +++ b/test/pitytest11/src/PityTree.hxx @@ -0,0 +1,139 @@ +// This file is under GNU General Public License 3.0 +// see LICENSE.txt + +#ifndef PITYTEST_PITYTREE_HXX +#define PITYTEST_PITYTREE_HXX + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace pEp { + namespace PityTest11 { + + template + PityTree::PityTree(T& self, const std::string &name) : + _self{ self }, _nodename{ _normalizeName(name) } + { + } + + template + PityTree::PityTree(T& self, const std::string &name, T& parent) : + _self(self), _nodename{ _normalizeName(name) } + { + parent.add(_self); + } + + template + T& PityTree::add(T& node) + { + node.setParent(&_self); + _children.insert(std::pair(node.getName(), node)); + return node; + } + + template + void PityTree::setParent(T *parent) + { + _parent = parent; + } + + template + T *PityTree::getParent() const + { + return _parent; + } + + template + bool PityTree::isRoot() const + { + if (_parent == nullptr) { + return true; + } else { + return false; + } + } + + template + std::string PityTree::getName() const + { + return _nodename; + } + + template + std::string PityTree::getPath() const + { + std::string ret; + + if (!isRoot()) { + ret = _parent->getPath() + "/" + getName(); + } else { + ret = getName(); + } + return ret; + } + + template + std::string PityTree::to_string(bool recursive, int indent) + { + std::string ret; + std::stringstream builder; + builder << std::string(indent * 4, ' '); + builder << getName(); + builder << std::endl; + ret = builder.str(); + + if (recursive) { + if (!getChildren().empty()) { + indent++; + for (auto child : getChildren()) { + ret += child.second.to_string(true, indent); + } + indent--; + } + } + return ret; + } + + template + T& PityTree::getRoot() + { + if (!isRoot()) { + return _parent->getRoot(); + } else { + return _self; + } + } + + template + typename PityTree::Children PityTree::getChildren() const + { + return _children; + } + + // name is alphanumeric only (everything else will be replaced by an underscore) + // static + template + std::string PityTree::_normalizeName(std::string name) + { + replace_if( + name.begin(), + name.end(), + [](char c) -> bool { return !isalnum(c); }, + '_'); + + return name; + } + } // namespace PityTest11 +} // namespace pEp + +#endif \ No newline at end of file