From 9ae9204df2cb87ca5ec164d024a30380d70df495 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Thu, 19 Feb 2015 13:15:28 +0100 Subject: [PATCH] Cli: Don't parse objects/changes on each AddObject() call refs #8488 --- lib/cli/nodeupdateconfigcommand.cpp | 25 +++++++++++++++---------- lib/cli/repositoryobjectcommand.cpp | 13 +++++++++++-- lib/cli/repositoryutility.cpp | 25 +++++++++++++------------ lib/cli/repositoryutility.hpp | 15 ++++++++------- 4 files changed, 47 insertions(+), 31 deletions(-) diff --git a/lib/cli/nodeupdateconfigcommand.cpp b/lib/cli/nodeupdateconfigcommand.cpp index 581c49d4d..741800def 100644 --- a/lib/cli/nodeupdateconfigcommand.cpp +++ b/lib/cli/nodeupdateconfigcommand.cpp @@ -85,7 +85,12 @@ int NodeUpdateConfigCommand::Run(const boost::program_options::variables_map& vm Utility::LoadExtensionLibrary("icinga"); + /* cache all existing object configs only once and pass it to AddObject() */ std::vector object_paths = RepositoryUtility::GetObjects(); + /* cache all existing changes only once and pass it to AddObject() */ + Array::Ptr changes = new Array(); + RepositoryUtility::GetChangeLog(boost::bind(RepositoryUtility::CollectChange, _1, changes)); + std::vector nodes = NodeUtility::GetNodes(); /* first make sure that all nodes are valid and should not be removed */ @@ -122,7 +127,7 @@ int NodeUpdateConfigCommand::Run(const boost::program_options::variables_map& vm Dictionary::Ptr host_attrs = new Dictionary(); host_attrs->Set("name", host); - RepositoryUtility::RemoveObject(host, "Host", host_attrs); //this removes all services for this host as well + RepositoryUtility::RemoveObject(host, "Host", host_attrs, changes); //this removes all services for this host as well } } @@ -131,11 +136,11 @@ int NodeUpdateConfigCommand::Run(const boost::program_options::variables_map& vm Dictionary::Ptr zone_attrs = new Dictionary(); zone_attrs->Set("name", zone); - RepositoryUtility::RemoveObject(zone, "Zone", zone_attrs); + RepositoryUtility::RemoveObject(zone, "Zone", zone_attrs, changes); Dictionary::Ptr endpoint_attrs = new Dictionary(); endpoint_attrs->Set("name", endpoint); - RepositoryUtility::RemoveObject(endpoint, "Endpoint", endpoint_attrs); + RepositoryUtility::RemoveObject(endpoint, "Endpoint", endpoint_attrs, changes); } else { /* get the current node */ Dictionary::Ptr new_node = inventory->Get(old_node_name); @@ -169,7 +174,7 @@ int NodeUpdateConfigCommand::Run(const boost::program_options::variables_map& vm Dictionary::Ptr host_attrs = new Dictionary(); host_attrs->Set("name", old_host); - RepositoryUtility::RemoveObject(old_host, "Host", host_attrs); //this will remove all services for this host too + RepositoryUtility::RemoveObject(old_host, "Host", host_attrs, changes); //this will remove all services for this host too } else { /* host exists, now check all services for this host */ Array::Ptr old_services = kv.second; @@ -194,7 +199,7 @@ int NodeUpdateConfigCommand::Run(const boost::program_options::variables_map& vm Dictionary::Ptr service_attrs = new Dictionary(); service_attrs->Set("name", old_service); service_attrs->Set("host_name", old_host); - RepositoryUtility::RemoveObject(old_service, "Service", service_attrs); + RepositoryUtility::RemoveObject(old_service, "Service", service_attrs, changes); } } } @@ -231,7 +236,7 @@ int NodeUpdateConfigCommand::Run(const boost::program_options::variables_map& vm host_imports->Add("satellite-host"); //default host node template host_attrs->Set("import", host_imports); - if (!RepositoryUtility::AddObject(zone, "Host", host_attrs)) { + if (!RepositoryUtility::AddObject(object_paths, zone, "Host", host_attrs, changes)) { Log(LogCritical, "cli") << "Cannot add node host '" << zone << "' to the config repository!\n"; } @@ -290,7 +295,7 @@ int NodeUpdateConfigCommand::Run(const boost::program_options::variables_map& vm host_imports->Add("satellite-host"); //default host node template host_attrs->Set("import", host_imports); - RepositoryUtility::AddObject(host, "Host", host_attrs); + RepositoryUtility::AddObject(object_paths, host, "Host", host_attrs, changes); } /* special condition: what if the host was blacklisted before, but the services should be generated? */ @@ -348,7 +353,7 @@ int NodeUpdateConfigCommand::Run(const boost::program_options::variables_map& vm service_imports->Add("satellite-service"); //default service node template service_attrs->Set("import", service_imports); - if (!RepositoryUtility::AddObject(service, "Service", service_attrs)) + if (!RepositoryUtility::AddObject(object_paths, service, "Service", service_attrs, changes)) continue; } } @@ -371,7 +376,7 @@ int NodeUpdateConfigCommand::Run(const boost::program_options::variables_map& vm Log(LogInformation, "cli") << "Adding endpoint '" << endpoint << "' to the repository."; - if (!RepositoryUtility::AddObject(endpoint, "Endpoint", endpoint_attrs)) { + if (!RepositoryUtility::AddObject(object_paths, endpoint, "Endpoint", endpoint_attrs, changes)) { Log(LogCritical, "cli") << "Cannot add node endpoint '" << endpoint << "' to the config repository!\n"; } @@ -406,7 +411,7 @@ int NodeUpdateConfigCommand::Run(const boost::program_options::variables_map& vm Log(LogInformation, "cli") << "Adding zone '" << zone << "' to the repository."; - if (!RepositoryUtility::AddObject(zone, "Zone", zone_attrs)) { + if (!RepositoryUtility::AddObject(object_paths, zone, "Zone", zone_attrs, changes)) { Log(LogCritical, "cli") << "Cannot add node zone '" << zone << "' to the config repository!\n"; } diff --git a/lib/cli/repositoryobjectcommand.cpp b/lib/cli/repositoryobjectcommand.cpp index 650791528..e50b45faa 100644 --- a/lib/cli/repositoryobjectcommand.cpp +++ b/lib/cli/repositoryobjectcommand.cpp @@ -176,10 +176,19 @@ int RepositoryObjectCommand::Run(const boost::program_options::variables_map& vm if (m_Command == RepositoryCommandAdd) { Utility::LoadExtensionLibrary("icinga"); - RepositoryUtility::AddObject(name, m_Type, attrs); + + std::vector object_paths = RepositoryUtility::GetObjects(); + + Array::Ptr changes = new Array(); + RepositoryUtility::GetChangeLog(boost::bind(RepositoryUtility::CollectChange, _1, changes)); + + RepositoryUtility::AddObject(object_paths, name, m_Type, attrs, changes); } else if (m_Command == RepositoryCommandRemove) { + Array::Ptr changes = new Array(); + RepositoryUtility::GetChangeLog(boost::bind(RepositoryUtility::CollectChange, _1, changes)); + /* pass attrs for service->host_name requirement */ - RepositoryUtility::RemoveObject(name, m_Type, attrs); + RepositoryUtility::RemoveObject(name, m_Type, attrs, changes); } else if (m_Command == RepositoryCommandSet) { Log(LogWarning, "cli") << "Not supported yet. Please check the roadmap at https://dev.icinga.org\n"; diff --git a/lib/cli/repositoryutility.cpp b/lib/cli/repositoryutility.cpp index cd3c5974a..12a44f868 100644 --- a/lib/cli/repositoryutility.cpp +++ b/lib/cli/repositoryutility.cpp @@ -199,9 +199,8 @@ public: }; /* modify objects and write changelog */ -bool RepositoryUtility::AddObject(const String& name, const String& type, const Dictionary::Ptr& attrs) +bool RepositoryUtility::AddObject(const std::vector& object_paths, const String& name, const String& type, const Dictionary::Ptr& attrs, const Array::Ptr& changes) { - std::vector object_paths = GetObjects(); String pattern; if (type == "Service") @@ -264,7 +263,7 @@ bool RepositoryUtility::AddObject(const String& name, const String& type, const } } - if (CheckChangeExists(change)) { + if (CheckChangeExists(change, changes)) { Log(LogWarning, "cli") << "Change '" << change->Get("command") << "' for type '" << change->Get("type") << "' and name '" << change->Get("name") @@ -273,10 +272,13 @@ bool RepositoryUtility::AddObject(const String& name, const String& type, const return false; } + /* store the cached change */ + changes->Add(change); + return WriteObjectToRepositoryChangeLog(path, change); } -bool RepositoryUtility::RemoveObject(const String& name, const String& type, const Dictionary::Ptr& attrs) +bool RepositoryUtility::RemoveObject(const String& name, const String& type, const Dictionary::Ptr& attrs, const Array::Ptr& changes) { /* add a new changelog entry by timestamp */ String path = GetRepositoryChangeLogPath() + "/" + Convert::ToString(Utility::GetTime()) + "-" + type + "-" + SHA256(name) + ".change"; @@ -289,7 +291,7 @@ bool RepositoryUtility::RemoveObject(const String& name, const String& type, con change->Set("command", "remove"); change->Set("attrs", attrs); //required for service->host_name - if (CheckChangeExists(change)) { + if (CheckChangeExists(change, changes)) { Log(LogWarning, "cli") << "Change '" << change->Get("command") << "' for type '" << change->Get("type") << "' and name '" << change->Get("name") @@ -298,6 +300,9 @@ bool RepositoryUtility::RemoveObject(const String& name, const String& type, con return false; } + /* store the cached change */ + changes->Add(change); + return WriteObjectToRepositoryChangeLog(path, change); } @@ -307,16 +312,12 @@ bool RepositoryUtility::SetObjectAttribute(const String& name, const String& typ return true; } -bool RepositoryUtility::CheckChangeExists(const Dictionary::Ptr& change) +bool RepositoryUtility::CheckChangeExists(const Dictionary::Ptr& change, const Array::Ptr& changes) { Dictionary::Ptr attrs = change->Get("attrs"); - Array::Ptr changelog = new Array(); - - GetChangeLog(boost::bind(RepositoryUtility::CollectChange, _1, changelog)); - - ObjectLock olock(changelog); - BOOST_FOREACH(const Dictionary::Ptr& entry, changelog) { + ObjectLock olock(changes); + BOOST_FOREACH(const Dictionary::Ptr& entry, changes) { if (entry->Get("type") != change->Get("type")) continue; diff --git a/lib/cli/repositoryutility.hpp b/lib/cli/repositoryutility.hpp index 2f8480195..7e24cdd7f 100644 --- a/lib/cli/repositoryutility.hpp +++ b/lib/cli/repositoryutility.hpp @@ -52,18 +52,23 @@ public: static void PrintChangeLog(std::ostream& fp); - static bool AddObject(const String& name, const String& type, const Dictionary::Ptr& attrs); - static bool RemoveObject(const String& name, const String& type, const Dictionary::Ptr& attrs); + static bool AddObject(const std::vector& object_paths, const String& name, const String& type, const Dictionary::Ptr& attrs, const Array::Ptr& changes); + static bool RemoveObject(const String& name, const String& type, const Dictionary::Ptr& attrs, const Array::Ptr& changes); - static bool CheckChangeExists(const Dictionary::Ptr& change); + static bool CheckChangeExists(const Dictionary::Ptr& change, const Array::Ptr& changes); static bool SetObjectAttribute(const String& name, const String& type, const String& attr, const Value& val); static bool CommitChangeLog(void); static bool ClearChangeLog(void); static bool ChangeLogHasPendingChanges(void); + static bool GetChangeLog(const boost::function& callback); + static void CollectChangeLog(const String& change_file, std::vector& changelog); + static void CollectChange(const Dictionary::Ptr& change, Array::Ptr& changes); static std::vector GetObjects(void); + static void CollectObjects(const String& object_file, std::vector& objects); + private: RepositoryUtility(void); @@ -75,17 +80,13 @@ private: const Value& val, const Dictionary::Ptr& attrs); /* repository.d */ - static void CollectObjects(const String& object_file, std::vector& objects); static bool WriteObjectToRepository(const String& path, const String& name, const String& type, const Dictionary::Ptr& item); static Dictionary::Ptr GetObjectFromRepository(const String& filename); /* changelog */ - static void CollectChangeLog(const String& change_file, std::vector& changelog); static bool WriteObjectToRepositoryChangeLog(const String& path, const Dictionary::Ptr& item); static Dictionary::Ptr GetObjectFromRepositoryChangeLog(const String& filename); - static bool GetChangeLog(const boost::function& callback); - static void CollectChange(const Dictionary::Ptr& change, Array::Ptr& changes); static void CommitChange(const Dictionary::Ptr& change, const String& path); static void ClearChange(const Dictionary::Ptr& change, const String& path);