diff --git a/dds-agent/src/CommanderChannel.cpp b/dds-agent/src/CommanderChannel.cpp index 1719a50b..1082258d 100644 --- a/dds-agent/src/CommanderChannel.cpp +++ b/dds-agent/src/CommanderChannel.cpp @@ -259,6 +259,27 @@ bool CCommanderChannel::on_cmdSHUTDOWN(SCommandAttachmentImpl::ptr_ { deleteAgentIDFile(); LOG(info) << "The Agent [" << m_id << "] received cmdSHUTDOWN."; + + // Remove global Assets + { + lock_guard lock(m_mutexGlobalAssets); + for (const auto& asset : m_globalAssets) + { + try + { + if (!fs::exists(asset) || !fs::is_regular_file(asset)) + continue; + + fs::remove(asset); + LOG(info) << "Removing global asset: " << asset.generic_string(); + } + catch (...) + { + } + } + m_globalAssets.clear(); + } + // return false to let connection manager to catch this message as well return false; } @@ -512,8 +533,29 @@ bool CCommanderChannel::on_cmdASSIGN_USER_TASK(SCommandAttachmentImplgetName() << ".asset"; - fs::path pathAsset(dir); - pathAsset /= assetFileName.str(); + fs::path pathAsset; + switch (asset->getAssetVisibility()) + { + case CTopoAsset::EVisibility::Task: + pathAsset = dir; + pathAsset /= assetFileName.str(); + + // If local asset exists, we will overwrite it. No skiping. + + slot->m_taskAssets.push_back(pathAsset); + break; + case CTopoAsset::EVisibility::Global: + pathAsset = CUserDefaults::instance().getDDSPath(); + pathAsset /= assetFileName.str(); + + // Create global Asset only once. Skip if exists. + if (fs::exists(pathAsset)) + continue; + + lock_guard lock(m_mutexGlobalAssets); + m_globalAssets.push_back(pathAsset); + break; + } LOG(info) << "Creating task ASSET for taskID " << slot->m_taskID << ": " << pathAsset.generic_string(); ofstream f(pathAsset.generic_string()); @@ -525,8 +567,6 @@ bool CCommanderChannel::on_cmdASSIGN_USER_TASK(SCommandAttachmentImplgetValue(); f.flush(); - - slot->m_assets.push_back(pathAsset); } return true; @@ -1062,12 +1102,18 @@ void CCommanderChannel::taskExited(uint64_t _slotID, int _exitCode) } // Remove tasks assets - for (const auto& asset : slot.m_assets) + for (const auto& asset : slot.m_taskAssets) { - if (fs::exists(asset) && fs::is_regular_file(asset)) - fs::remove(asset); + try + { + if (fs::exists(asset) && fs::is_regular_file(asset)) + fs::remove(asset); + } + catch (...) + { + } } - slot.m_assets.clear(); + slot.m_taskAssets.clear(); // Save values before we reset them SUserTaskDoneCmd cmd; diff --git a/dds-agent/src/CommanderChannel.h b/dds-agent/src/CommanderChannel.h index 38ac7f2c..ca0e0096 100644 --- a/dds-agent/src/CommanderChannel.h +++ b/dds-agent/src/CommanderChannel.h @@ -17,11 +17,11 @@ namespace dds { using slotId_t = uint64_t; using taskId_t = uint64_t; + using assets_t = std::vector; struct SSlotInfo { using container_t = std::map; - using assets_t = std::vector; slotId_t m_id{ 0 }; std::string m_sUsrExe; @@ -34,7 +34,7 @@ namespace dds std::string m_collectionName; std::string m_taskName; pid_t m_pid{ 0 }; - assets_t m_assets; + assets_t m_taskAssets; }; class CCommanderChannel : public protocol_api::CClientChannelImpl @@ -153,6 +153,8 @@ namespace dds std::mutex m_mutexSlots; SSlotInfo::container_t m_slots; size_t m_nSlots{ 0 }; + std::mutex m_mutexGlobalAssets; + assets_t m_globalAssets; timerPtr_t m_resourceMonitorTimer; std::string m_groupName; }; diff --git a/dds-topology-lib/src/TopoAsset.cpp b/dds-topology-lib/src/TopoAsset.cpp index 5e7c90ec..8688dd3d 100644 --- a/dds-topology-lib/src/TopoAsset.cpp +++ b/dds-topology-lib/src/TopoAsset.cpp @@ -31,6 +31,7 @@ void CTopoAsset::initFromPropertyTree(const boost::property_tree::ptree& _pt) { const ptree& assetPT = FindElementInPropertyTree(CTopoBase::EType::ASSET, getName(), _pt.get_child("topology")); setAssetType(TagToAssetType(assetPT.get(".type", ""))); + setAssetVisibility(TagToAssetVisibility(assetPT.get(".visibility", ""))); setValue(assetPT.get(".value", "")); } catch (exception& error) // ptree_error, runtime_error @@ -46,6 +47,7 @@ void CTopoAsset::saveToPropertyTree(boost::property_tree::ptree& _pt) std::string tag("topology.asset."); _pt.put(tag + ".name", getName()); _pt.put(tag + ".type", AssetTypeToTag(getAssetType())); + _pt.put(tag + ".visibility", AssetVisibilityToTag(getAssetVisibility())); _pt.put(tag + ".value", getValue()); } catch (exception& error) // ptree_error, runtime_error @@ -74,10 +76,21 @@ void CTopoAsset::setAssetType(const CTopoAsset::EType& _val) m_type = _val; } +CTopoAsset::EVisibility CTopoAsset::getAssetVisibility() const +{ + return m_visibility; +} + +void CTopoAsset::setAssetVisibility(const CTopoAsset::EVisibility& _val) +{ + m_visibility = _val; +} + string CTopoAsset::toString() const { stringstream ss; - ss << "Asset: name=" << getName() << " type=" << AssetTypeToTag(getAssetType()) << " value=" << getValue(); + ss << "Asset: name=" << getName() << " type=" << AssetTypeToTag(getAssetType()) + << " visibility=" << AssetVisibilityToTag(getAssetVisibility()) << " value=" << getValue(); return ss.str(); } @@ -90,6 +103,7 @@ ostream& operator<<(ostream& _strm, const CTopoAsset& _requirement) string CTopoAsset::hashString() const { stringstream ss; - ss << "|Asset|" << getName() << "|" << AssetTypeToTag(getAssetType()) << "|" << getValue() << "|"; + ss << "|Asset|" << getName() << "|" << AssetTypeToTag(getAssetType()) << "|" + << AssetVisibilityToTag(getAssetVisibility()) << "|" << getValue() << "|"; return ss.str(); } diff --git a/dds-topology-lib/src/TopoAsset.h b/dds-topology-lib/src/TopoAsset.h index 7ce23677..1f1ce480 100644 --- a/dds-topology-lib/src/TopoAsset.h +++ b/dds-topology-lib/src/TopoAsset.h @@ -25,6 +25,12 @@ namespace dds Inline }; + enum class EVisibility + { + Task, ///< The asset is visiable only for the task it is assigned to + Global ///< The asset is visiable for all tasks of the given session. + }; + using Ptr_t = std::shared_ptr; using PtrVector_t = std::vector; @@ -46,6 +52,9 @@ namespace dds CTopoAsset::EType getAssetType() const; void setAssetType(const CTopoAsset::EType& _val); + CTopoAsset::EVisibility getAssetVisibility() const; + void setAssetVisibility(const CTopoAsset::EVisibility& _val); + /// \brief Returns string representation of an object. /// \return String representation of an object. virtual std::string toString() const; @@ -59,8 +68,9 @@ namespace dds virtual std::string hashString() const; private: - std::string m_value; ///< Asset value - CTopoAsset::EType m_type{ CTopoAsset::EType::Inline }; ///< Asset type + std::string m_value; ///< Asset value + CTopoAsset::EType m_type{ CTopoAsset::EType::Inline }; ///< Asset type + CTopoAsset::EVisibility m_visibility{ CTopoAsset::EVisibility::Task }; /// < Asset visibility }; } // namespace topology_api } // namespace dds diff --git a/dds-topology-lib/src/TopoUtils.cpp b/dds-topology-lib/src/TopoUtils.cpp index 52253313..565bcf10 100644 --- a/dds-topology-lib/src/TopoUtils.cpp +++ b/dds-topology-lib/src/TopoUtils.cpp @@ -117,7 +117,7 @@ namespace dds throw runtime_error("Property access type with name " + _name + " does not exist."); } - std::string PropertyAccessTypeToTag(CTopoProperty::EAccessType _type) + string PropertyAccessTypeToTag(CTopoProperty::EAccessType _type) { switch (_type) { @@ -132,7 +132,7 @@ namespace dds } } - CTopoProperty::EScopeType TagToPropertyScopeType(const std::string& _name) + CTopoProperty::EScopeType TagToPropertyScopeType(const string& _name) { if (_name == "collection") return CTopoProperty::EScopeType::COLLECTION; @@ -142,7 +142,7 @@ namespace dds throw runtime_error("Property scope type with name " + _name + " does not exist."); } - std::string PropertyScopeTypeToTag(CTopoProperty::EScopeType _type) + string PropertyScopeTypeToTag(CTopoProperty::EScopeType _type) { switch (_type) { @@ -171,7 +171,7 @@ namespace dds throw runtime_error("Host pattern type with name " + _name + " does not exist."); } - std::string RequirementTypeToTag(CTopoRequirement::EType _type) + string RequirementTypeToTag(CTopoRequirement::EType _type) { switch (_type) { @@ -198,7 +198,7 @@ namespace dds throw runtime_error("Asset type type with name " + _name + " does not exist."); } - std::string AssetTypeToTag(CTopoAsset::EType _type) + string AssetTypeToTag(CTopoAsset::EType _type) { switch (_type) { @@ -209,7 +209,30 @@ namespace dds } } - CTopoTrigger::EConditionType TagToConditionType(const std::string& _name) + CTopoAsset::EVisibility TagToAssetVisibility(const string& _name) + { + if (_name == "task") + return CTopoAsset::EVisibility::Task; + else if (_name == "global") + return CTopoAsset::EVisibility::Global; + else + throw runtime_error("Asset visibility type with name " + _name + " does not exist."); + } + + string AssetVisibilityToTag(CTopoAsset::EVisibility _val) + { + switch (_val) + { + case CTopoAsset::EVisibility::Task: + return "task"; + case CTopoAsset::EVisibility::Global: + return "global"; + default: + throw runtime_error("Topology element not found."); + } + } + + CTopoTrigger::EConditionType TagToConditionType(const string& _name) { if (_name == "TaskCrashed") return CTopoTrigger::EConditionType::TaskCrashed; @@ -217,7 +240,7 @@ namespace dds throw runtime_error("Condition type with name " + _name + " does not exist."); } - std::string ConditionTypeToTag(CTopoTrigger::EConditionType _type) + string ConditionTypeToTag(CTopoTrigger::EConditionType _type) { switch (_type) { @@ -228,7 +251,7 @@ namespace dds } } - CTopoTrigger::EActionType TagToActionType(const std::string& _name) + CTopoTrigger::EActionType TagToActionType(const string& _name) { if (_name == "RestartTask") return CTopoTrigger::EActionType::RestartTask; @@ -236,7 +259,7 @@ namespace dds throw runtime_error("Action type with name " + _name + " does not exist."); } - std::string ActionTypeToTag(CTopoTrigger::EActionType _type) + string ActionTypeToTag(CTopoTrigger::EActionType _type) { switch (_type) { diff --git a/dds-topology-lib/src/TopoUtils.h b/dds-topology-lib/src/TopoUtils.h index 0f627ef1..518fc524 100644 --- a/dds-topology-lib/src/TopoUtils.h +++ b/dds-topology-lib/src/TopoUtils.h @@ -45,6 +45,10 @@ namespace dds std::string AssetTypeToTag(CTopoAsset::EType _type); + CTopoAsset::EVisibility TagToAssetVisibility(const std::string& _name); + + std::string AssetVisibilityToTag(CTopoAsset::EVisibility _val); + CTopoTrigger::EConditionType TagToConditionType(const std::string& _name); std::string ConditionTypeToTag(CTopoTrigger::EConditionType _type); diff --git a/dds-topology-lib/tests/Test.cpp b/dds-topology-lib/tests/Test.cpp index 870ea9c5..356e7b69 100644 --- a/dds-topology-lib/tests/Test.cpp +++ b/dds-topology-lib/tests/Test.cpp @@ -573,6 +573,14 @@ BOOST_AUTO_TEST_CASE(test_dds_topo_utils) // AssetTypeToTag BOOST_CHECK(AssetTypeToTag(CTopoAsset::EType::Inline) == "inline"); + // TagToAssetVisibility + BOOST_CHECK(TagToAssetVisibility("task") == CTopoAsset::EVisibility::Task); + BOOST_CHECK(TagToAssetVisibility("global") == CTopoAsset::EVisibility::Global); + + // AssetVisibilityToTag + BOOST_CHECK(AssetVisibilityToTag(CTopoAsset::EVisibility::Task) == "task"); + BOOST_CHECK(AssetVisibilityToTag(CTopoAsset::EVisibility::Global) == "global"); + // DeclTagToTopoType BOOST_CHECK_THROW(DeclTagToTopoType(""), runtime_error); BOOST_CHECK_THROW(DeclTagToTopoType("topobase"), runtime_error); @@ -1054,7 +1062,13 @@ BOOST_AUTO_TEST_CASE(test_dds_topology_assets) CTopoAsset::Ptr_t asset = casted1->getAssets()[0]; BOOST_CHECK(asset->getName() == "asset1"); BOOST_CHECK(asset->getAssetType() == CTopoAsset::EType::Inline); + BOOST_CHECK(asset->getAssetVisibility() == CTopoAsset::EVisibility::Task); BOOST_CHECK(asset->getValue() == asset1TestData); + + CTopoAsset::Ptr_t asset2 = casted1->getAssets()[1]; + BOOST_CHECK(asset->getName() == "asset2"); + BOOST_CHECK(asset->getAssetType() == CTopoAsset::EType::Inline); + BOOST_CHECK(asset->getAssetVisibility() == CTopoAsset::EVisibility::Global); } BOOST_AUTO_TEST_SUITE_END() diff --git a/dds-topology-lib/tests/topology_test_assets.xml b/dds-topology-lib/tests/topology_test_assets.xml index 7a2e6357..fd7a8463 100644 --- a/dds-topology-lib/tests/topology_test_assets.xml +++ b/dds-topology-lib/tests/topology_test_assets.xml @@ -9,8 +9,69 @@ - + + @@ -36,6 +97,7 @@ asset1 + asset2 diff --git a/res/topology.xsd b/res/topology.xsd index 412dab99..65770444 100644 --- a/res/topology.xsd +++ b/res/topology.xsd @@ -122,9 +122,17 @@ + + + + + + + +