object.h \
process.cpp \
process.h \
+ qstring.cpp \
+ qstring.h \
ringbuffer.cpp \
ringbuffer.h \
scriptfunction.cpp \
unix.h \
utility.cpp \
utility.h \
- variant.cpp \
- variant.h \
+ value.cpp \
+ value.h \
win32.cpp \
win32.h
break;
Event::ProcessEvents(boost::get_system_time() + boost::posix_time::milliseconds(sleep * 1000));
+
+ DynamicObject::FinishTx();
+ DynamicObject::BeginTx();
}
}
*
* @returns The path.
*/
-string Application::GetExePath(void) const
+String Application::GetExePath(void) const
{
- static string result;
+ static String result;
- if (!result.empty())
+ if (!result.IsEmpty())
return result;
- string executablePath;
+ String executablePath;
#ifndef _WIN32
- string argv0 = m_Arguments[0];
+ String argv0 = m_Arguments[0];
char buffer[MAXPATHLEN];
if (getcwd(buffer, sizeof(buffer)) == NULL)
throw_exception(PosixException("getcwd failed", errno));
- string workingDirectory = buffer;
+ String workingDirectory = buffer;
if (argv0[0] != '/')
executablePath = workingDirectory + "/" + argv0;
else
executablePath = argv0;
- if (argv0.find_first_of('/') == string::npos) {
+ bool foundSlash = false;
+ for (int i = 0; i < argv0.GetLength(); i++) {
+ if (argv0[i] == '/') {
+ foundSlash = true;
+ break;
+ }
+ }
+
+ if (!foundSlash) {
const char *pathEnv = getenv("PATH");
if (pathEnv != NULL) {
- vector<string> paths;
+ vector<String> paths;
boost::algorithm::split(paths, pathEnv, boost::is_any_of(":"));
bool foundPath = false;
- BOOST_FOREACH(string& path, paths) {
- string pathTest = path + "/" + argv0;
+ BOOST_FOREACH(String& path, paths) {
+ String pathTest = path + "/" + argv0;
- if (access(pathTest.c_str(), X_OK) == 0) {
+ if (access(pathTest.CStr(), X_OK) == 0) {
executablePath = pathTest;
foundPath = true;
break;
}
if (!foundPath) {
- executablePath.clear();
+ executablePath.Clear();
throw_exception(runtime_error("Could not determine executable path."));
}
}
}
- if (realpath(executablePath.c_str(), buffer) == NULL)
+ if (realpath(executablePath.CStr(), buffer) == NULL)
throw_exception(PosixException("realpath failed", errno));
result = buffer;
m_Arguments.clear();
for (int i = 0; i < argc; i++)
- m_Arguments.push_back(string(argv[i]));
+ m_Arguments.push_back(String(argv[i]));
+
+ DynamicObject::BeginTx();
if (IsDebugging()) {
result = Main(m_Arguments);
Logger::Write(LogCritical, "base", "---");
Logger::Write(LogCritical, "base", "Exception: " + Utility::GetTypeName(typeid(ex)));
- Logger::Write(LogCritical, "base", "Message: " + string(ex.what()));
+ Logger::Write(LogCritical, "base", "Message: " + String(ex.what()));
return EXIT_FAILURE;
}
}
+ DynamicObject::FinishTx();
+
return result;
}
-void Application::UpdatePidFile(const string& filename)
+void Application::UpdatePidFile(const String& filename)
{
ClosePidFile();
/* There's just no sane way of getting a file descriptor for a
* C++ ofstream which is why we're using FILEs here. */
- m_PidFile = fopen(filename.c_str(), "w");
+ m_PidFile = fopen(filename.CStr(), "w");
if (m_PidFile == NULL)
throw_exception(runtime_error("Could not open PID file '" + filename + "'"));
int Run(int argc, char **argv);
- virtual int Main(const vector<string>& args) = 0;
+ virtual int Main(const vector<String>& args) = 0;
static void Shutdown(void);
static bool IsMainThread(void);
- void UpdatePidFile(const string& filename);
+ void UpdatePidFile(const String& filename);
void ClosePidFile(void);
protected:
void RunEventLoop(void);
- string GetExePath(void) const;
+ String GetExePath(void) const;
private:
static Application::Ptr m_Instance; /**< The application instance. */
static bool m_ShuttingDown; /**< Whether the application is in the process of
shutting down. */
- vector<string> m_Arguments; /**< Command-line arguments */
+ vector<String> m_Arguments; /**< Command-line arguments */
FILE *m_PidFile; /**< The PID file */
static bool m_Debugging; /**< Whether debugging is enabled. */
static boost::thread::id m_MainThreadID; /**< ID of the main thread. */
<ClCompile Include="netstring.cpp" />
<ClCompile Include="object.cpp" />
<ClCompile Include="process.cpp" />
+ <ClCompile Include="qstring.cpp" />
<ClCompile Include="ringbuffer.cpp" />
<ClCompile Include="scriptfunction.cpp" />
<ClCompile Include="scripttask.cpp" />
<ClCompile Include="tlsclient.cpp" />
<ClCompile Include="unix.cpp" />
<ClCompile Include="utility.cpp" />
- <ClCompile Include="variant.cpp" />
+ <ClCompile Include="value.cpp" />
<ClCompile Include="win32.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="fifo.h" />
<ClInclude Include="ioqueue.h" />
<ClInclude Include="netstring.h" />
+ <ClInclude Include="qstring.h" />
<ClInclude Include="scriptfunction.h" />
<ClInclude Include="scripttask.h" />
<ClInclude Include="logger.h" />
<ClInclude Include="tlsclient.h" />
<ClInclude Include="unix.h" />
<ClInclude Include="utility.h" />
- <ClInclude Include="variant.h" />
+ <ClInclude Include="value.h" />
<ClInclude Include="win32.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ClCompile Include="utility.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
- <ClCompile Include="variant.cpp">
- <Filter>Quelldateien</Filter>
- </ClCompile>
<ClCompile Include="win32.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="dynamicobject.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
+ <ClCompile Include="value.cpp">
+ <Filter>Quelldateien</Filter>
+ </ClCompile>
+ <ClCompile Include="qstring.cpp">
+ <Filter>Quelldateien</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="application.h">
<ClInclude Include="utility.h">
<Filter>Headerdateien</Filter>
</ClInclude>
- <ClInclude Include="variant.h">
- <Filter>Headerdateien</Filter>
- </ClInclude>
<ClInclude Include="logger.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="dynamicobject.h">
<Filter>Headerdateien</Filter>
</ClInclude>
+ <ClInclude Include="value.h">
+ <Filter>Headerdateien</Filter>
+ </ClInclude>
+ <ClInclude Include="qstring.h">
+ <Filter>Headerdateien</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Quelldateien">
if (!IsLocal())
throw_exception(runtime_error("Component objects must be local."));
- string path;
+ String path;
#ifdef _WIN32
path = GetName() + ".dll";
#else /* _WIN32 */
Logger::Write(LogInformation, "base", "Loading component '" + GetName() + "' (using library '" + path + "')");
#ifdef _WIN32
- HMODULE hModule = LoadLibrary(path.c_str());
+ HMODULE hModule = LoadLibrary(path.CStr());
if (hModule == NULL)
throw_exception(Win32Exception("LoadLibrary('" + path + "') failed", GetLastError()));
#else /* _WIN32 */
- lt_dlhandle hModule = lt_dlopen(path.c_str());
+ lt_dlhandle hModule = lt_dlopen(path.CStr());
if (hModule == NULL) {
throw_exception(runtime_error("Could not load module '" + path + "': " + lt_dlerror()));
}
impl->m_Config = this;
- SetImplementation(impl);
-
impl->Start();
+ m_Impl = impl;
}
Component::~Component(void)
{
- IComponent::Ptr impl = GetImplementation();
-
- if (impl)
- impl->Stop();
-}
-
-IComponent::Ptr Component::GetImplementation(void) const
-{
- IComponent::Ptr impl;
- GetTag("impl", &impl);
- return impl;
-}
-
-void Component::SetImplementation(const IComponent::Ptr& impl)
-{
- SetTag("impl", impl);
+ if (m_Impl)
+ m_Impl->Stop();
}
/**
*
* @param componentDirectory The directory.
*/
-void Component::AddSearchDir(const string& componentDirectory)
+void Component::AddSearchDir(const String& componentDirectory)
{
#ifdef _WIN32
- SetDllDirectory(componentDirectory.c_str());
+ SetDllDirectory(componentDirectory.CStr());
#else /* _WIN32 */
- lt_dladdsearchdir(componentDirectory.c_str());
+ lt_dladdsearchdir(componentDirectory.CStr());
#endif /* _WIN32 */
}
Component(const Dictionary::Ptr& properties);
~Component(void);
- static void AddSearchDir(const string& componentDirectory);
+ static void AddSearchDir(const String& componentDirectory);
private:
- IComponent::Ptr GetImplementation(void) const;
- void SetImplementation(const IComponent::Ptr& impl);
+ IComponent::Ptr m_Impl;
};
typedef IComponent *(*CreateComponentFunction)(void);
using namespace icinga;
+/**
+ * Retrieves a value from the dictionary.
+ *
+ * @param key The key whose value should be retrieved.
+ * @returns The value or an empty value if the key was not found.
+ */
+Value Dictionary::Get(const String& key) const
+{
+ map<String, Value>::const_iterator it;
+ it = m_Data.find(key);
+
+ if (it == m_Data.end())
+ return Value();
+
+ return it->second;
+}
+
+/**
+ * Sets a value in the dictionary.
+ *
+ * @param key The key.
+ * @param value The value.
+ */
+void Dictionary::Set(const String& key, const Value& value)
+{
+ if (value.IsEmpty()) {
+ Remove(key);
+ return;
+ }
+
+ pair<map<String, Value>::iterator, bool> ret;
+ ret = m_Data.insert(make_pair(key, value));
+ if (!ret.second)
+ ret.first->second = value;
+
+ OnItemModified(key, value);
+}
+
+/**
+ * Adds an unnamed value to the dictionary.
+ *
+ * @param value The value.
+ * @returns The key that was used to add the new item.
+ */
+String Dictionary::Add(const Value& value)
+{
+ Dictionary::Iterator it;
+ String key;
+ long index = GetLength();
+ do {
+ stringstream s;
+ s << "_" << index;
+ index++;
+
+ key = s.str();
+ it = m_Data.find(key);
+ } while (it != m_Data.end());
+
+ Set(key, value);
+ return key;
+}
+
/**
* Returns an iterator to the beginning of the dictionary.
*
* @param key The key.
* @returns true if the dictionary contains the key, false otherwise.
*/
-bool Dictionary::Contains(const string& key) const
+bool Dictionary::Contains(const String& key) const
{
return (m_Data.find(key) != m_Data.end());
}
*
* @param key The key.
*/
-void Dictionary::Remove(const string& key)
+void Dictionary::Remove(const String& key)
{
Dictionary::Iterator it;
it = m_Data.find(key);
return;
m_Data.erase(it);
+
+ OnItemModified(key, Value());
+}
+
+/**
+ * Removes the item specified by the iterator from the dictionary.
+ *
+ * @param it The iterator.
+ */
+void Dictionary::Remove(Dictionary::Iterator it)
+{
+ String key = it->first;
+ m_Data.erase(it);
+
+ OnItemModified(key, Value());
}
/**
throw_exception(invalid_argument("JSON type must be cJSON_Object."));
for (cJSON *i = json->child; i != NULL; i = i->next) {
- dictionary->Set(i->string, Variant::FromJson(i));
+ dictionary->Set(i->string, Value::FromJson(i));
}
return dictionary;
cJSON *json = cJSON_CreateObject();
try {
- string key;
- Variant value;
+ String key;
+ Value value;
BOOST_FOREACH(tie(key, value), m_Data) {
- cJSON_AddItemToObject(json, key.c_str(), value.ToJson());
+ cJSON_AddItemToObject(json, key.CStr(), value.ToJson());
}
} catch (...) {
cJSON_Delete(json);
return json;
}
+
+void Dictionary::OnItemModified(const String& key, const Value& value)
+{ }
typedef shared_ptr<Dictionary> Ptr;
typedef weak_ptr<Dictionary> WeakPtr;
- typedef map<string, Variant>::iterator Iterator;
-
- /**
- * Retrieves a value from the dictionary.
- *
- * @param key The key.
- * @param[out] value Pointer to the value.
- * @returns true if the value was retrieved, false otherwise.
- */
- template<typename T>
- bool Get(const string& key, T *value) const
- {
- map<string, Variant>::const_iterator i = m_Data.find(key);
-
- if (i == m_Data.end())
- return false;
-
- *value = static_cast<T>(i->second);
-
- return true;
- }
-
- /**
- * Sets a value in the dictionary.
- *
- * @param key The key.
- * @param value The value.
- */
- template<typename T>
- void Set(const string& key, const T& value)
- {
- pair<typename map<string, Variant>::iterator, bool> ret;
- ret = m_Data.insert(make_pair(key, value));
- if (!ret.second)
- ret.first->second = value;
- }
-
- /**
- * Adds an unnamed value to the dictionary.
- *
- * @param value The value.
- * @returns The key that was used to add the new item.
- */
- template<typename T>
- string Add(const T& value)
- {
- Iterator it;
- string key;
- long index = GetLength();
- do {
- stringstream s;
- s << "_" << index;
- index++;
-
- key = s.str();
- it = m_Data.find(key);
- } while (it != m_Data.end());
-
- Set(key, value);
- return key;
- }
-
- bool Contains(const string& key) const;
+ typedef map<String, Value>::iterator Iterator;
+
+ Value Get(const String& key) const;
+ void Set(const String& key, const Value& value);
+ String Add(const Value& value);
+ bool Contains(const String& key) const;
Iterator Begin(void);
Iterator End(void);
long GetLength(void) const;
- void Remove(const string& key);
+ void Remove(const String& key);
+ void Remove(Iterator it);
static Dictionary::Ptr FromJson(cJSON *json);
cJSON *ToJson(void) const;
+ virtual void OnItemModified(const String& key, const Value& value);
+
private:
- map<string, Variant> m_Data;
+ map<String, Value> m_Data;
};
inline Dictionary::Iterator range_begin(Dictionary::Ptr x)
using namespace icinga;
-map<pair<string, string>, Dictionary::Ptr> DynamicObject::m_PersistentTags;
-boost::signal<void (const DynamicObject::Ptr&)> DynamicObject::OnCommitted;
-boost::signal<void (const DynamicObject::Ptr&)> DynamicObject::OnRemoved;
-
-DynamicObject::DynamicObject(const Dictionary::Ptr& properties)
- : m_Properties(properties), m_Tags(boost::make_shared<Dictionary>())
-{
- /* restore the object's tags */
- map<pair<string, string>, Dictionary::Ptr>::iterator it;
- it = m_PersistentTags.find(make_pair(GetType(), GetName()));
- if (it != m_PersistentTags.end()) {
- m_Tags = it->second;
- m_PersistentTags.erase(it);
+map<pair<String, String>, Dictionary::Ptr> DynamicObject::m_PersistentUpdates;
+double DynamicObject::m_CurrentTx = 0;
+set<DynamicObject::Ptr> DynamicObject::m_ModifiedObjects;
+
+boost::signal<void (const DynamicObject::Ptr&, const String& name)> DynamicObject::OnAttributeChanged;
+boost::signal<void (const DynamicObject::Ptr&)> DynamicObject::OnRegistered;
+boost::signal<void (const DynamicObject::Ptr&)> DynamicObject::OnUnregistered;
+boost::signal<void (const set<DynamicObject::Ptr>&)> DynamicObject::OnTransactionClosing;
+
+DynamicObject::DynamicObject(const Dictionary::Ptr& serializedObject)
+ : m_ConfigTx(0)
+{
+ RegisterAttribute("__name", Attribute_Config);
+ RegisterAttribute("__type", Attribute_Config);
+ RegisterAttribute("__local", Attribute_Config);
+ RegisterAttribute("__abstract", Attribute_Config);
+ RegisterAttribute("__source", Attribute_Local);
+ RegisterAttribute("methods", Attribute_Config);
+
+ /* apply state from the config item/remote update */
+ ApplyUpdate(serializedObject, true);
+
+ /* restore the object's persistent state */
+ map<pair<String, String>, Dictionary::Ptr>::iterator it;
+ it = m_PersistentUpdates.find(make_pair(GetType(), GetName()));
+ if (it != m_PersistentUpdates.end()) {
+ Logger::Write(LogDebug, "base", "Restoring persistent state "
+ "for object " + GetType() + ":" + GetName());
+ ApplyUpdate(it->second, true);
+ m_PersistentUpdates.erase(it);
}
}
-void DynamicObject::SetProperties(const Dictionary::Ptr& properties)
+Dictionary::Ptr DynamicObject::BuildUpdate(double sinceTx, int attributeTypes) const
{
- m_Properties = properties;
+ DynamicObject::AttributeConstIterator it;
+
+ Dictionary::Ptr attrs = boost::make_shared<Dictionary>();
+
+ for (it = m_Attributes.begin(); it != m_Attributes.end(); it++) {
+ if (it->second.Type == Attribute_Transient)
+ continue;
+
+ if ((it->second.Type & attributeTypes) == 0)
+ continue;
+
+ if (it->second.Tx == 0)
+ continue;
+
+ if (it->second.Tx < sinceTx && !(it->second.Type == Attribute_Config && m_ConfigTx >= sinceTx))
+ continue;
+
+ Dictionary::Ptr attr = boost::make_shared<Dictionary>();
+ attr->Set("data", it->second.Data);
+ attr->Set("type", it->second.Type);
+ attr->Set("tx", it->second.Tx);
+
+ attrs->Set(it->first, attr);
+ }
+
+ Dictionary::Ptr update = boost::make_shared<Dictionary>();
+ update->Set("attrs", attrs);
+
+ if (m_ConfigTx >= sinceTx && attributeTypes & Attribute_Config)
+ update->Set("configTx", m_ConfigTx);
+ else if (attrs->GetLength() == 0)
+ return Dictionary::Ptr();
+
+ return update;
}
-Dictionary::Ptr DynamicObject::GetProperties(void) const
+void DynamicObject::ApplyUpdate(const Dictionary::Ptr& serializedUpdate, bool suppressEvents)
{
- return m_Properties;
+ double configTx = 0;
+ if (serializedUpdate->Contains("configTx")) {
+ configTx = serializedUpdate->Get("configTx");
+
+ if (configTx > m_ConfigTx)
+ ClearAttributesByType(Attribute_Config);
+ }
+
+ Dictionary::Ptr attrs = serializedUpdate->Get("attrs");
+
+ Dictionary::Iterator it;
+ for (it = attrs->Begin(); it != attrs->End(); it++) {
+ if (!it->second.IsObjectType<Dictionary>())
+ continue;
+
+ Dictionary::Ptr attr = it->second;
+
+ Value data = attr->Get("data");
+ int type = attr->Get("type");
+ double tx = attr->Get("tx");
+
+ if (type & Attribute_Config)
+ RegisterAttribute(it->first, Attribute_Config);
+
+ if (!HasAttribute(it->first))
+ RegisterAttribute(it->first, static_cast<DynamicAttributeType>(type));
+
+ InternalSetAttribute(it->first, data, tx, suppressEvents);
+ }
}
-void DynamicObject::SetTags(const Dictionary::Ptr& tags)
+void DynamicObject::SanitizeUpdate(const Dictionary::Ptr& serializedUpdate, int allowedTypes)
{
- m_Tags = tags;
+ if ((allowedTypes & Attribute_Config) == 0)
+ serializedUpdate->Remove("configTx");
+
+ Dictionary::Ptr attrs = serializedUpdate->Get("attrs");
+
+ Dictionary::Iterator prev, it;
+ for (it = attrs->Begin(); it != attrs->End(); ) {
+ if (!it->second.IsObjectType<Dictionary>())
+ continue;
+
+ Dictionary::Ptr attr = it->second;
+
+ int type = attr->Get("type");
+
+ if (type == 0 || type & ~allowedTypes) {
+ prev = it;
+ it++;
+ attrs->Remove(prev);
+ continue;
+ }
+
+ it++;
+ }
}
-Dictionary::Ptr DynamicObject::GetTags(void) const
+void DynamicObject::RegisterAttribute(const String& name, DynamicAttributeType type)
{
- return m_Tags;
+ DynamicAttribute attr;
+ attr.Type = type;
+ attr.Tx = 0;
+
+ pair<DynamicObject::AttributeIterator, bool> tt;
+ tt = m_Attributes.insert(make_pair(name, attr));
+
+ if (!tt.second)
+ tt.first->second.Type = type;
}
-string DynamicObject::GetType(void) const
+void DynamicObject::SetAttribute(const String& name, const Value& data)
{
- string type;
- GetProperties()->Get("__type", &type);
- return type;
+ InternalSetAttribute(name, data, GetCurrentTx());
}
-string DynamicObject::GetName(void) const
+void DynamicObject::InternalSetAttribute(const String& name, const Value& data, double tx, bool suppressEvent)
{
- string name;
- GetProperties()->Get("__name", &name);
- return name;
+ DynamicAttribute attr;
+ attr.Type = Attribute_Transient;
+ attr.Data = data;
+ attr.Tx = tx;
+
+ pair<DynamicObject::AttributeIterator, bool> tt;
+ tt = m_Attributes.insert(make_pair(name, attr));
+
+ if (!tt.second && tx >= tt.first->second.Tx) {
+ tt.first->second.Data = data;
+ tt.first->second.Tx = tx;
+ }
+
+ if (tt.first->second.Type & Attribute_Config)
+ m_ConfigTx = tx;
+
+ if (!suppressEvent) {
+ m_ModifiedObjects.insert(GetSelf());
+ DynamicObject::OnAttributeChanged(GetSelf(), name);
+ }
}
-bool DynamicObject::IsLocal(void) const
+Value DynamicObject::InternalGetAttribute(const String& name) const
{
- bool value = false;
- GetProperties()->Get("__local", &value);
- return value;
+ DynamicObject::AttributeConstIterator it;
+ it = m_Attributes.find(name);
+
+ if (it == m_Attributes.end())
+ return Value();
+ else
+ return it->second.Data;
}
-bool DynamicObject::IsAbstract(void) const
+void DynamicObject::ClearAttribute(const String& name)
{
- bool value = false;
- GetProperties()->Get("__abstract", &value);
- return value;
+ SetAttribute(name, Value());
}
-void DynamicObject::SetSource(const string& value)
+bool DynamicObject::HasAttribute(const String& name) const
{
- GetProperties()->Set("__source", value);
+ return (m_Attributes.find(name) != m_Attributes.end());
}
-string DynamicObject::GetSource(void) const
+void DynamicObject::ClearAttributesByType(DynamicAttributeType type)
{
- string value;
- GetProperties()->Get("__source", &value);
- return value;
+ DynamicObject::AttributeIterator prev, at;
+ for (at = m_Attributes.begin(); at != m_Attributes.end(); ) {
+ if (at->second.Type == type) {
+ prev = at;
+ at++;
+ m_Attributes.erase(prev);
+
+ continue;
+ }
+
+ at++;
+ }
+}
+
+DynamicObject::AttributeConstIterator DynamicObject::AttributeBegin(void) const
+{
+ return m_Attributes.begin();
+}
+
+DynamicObject::AttributeConstIterator DynamicObject::AttributeEnd(void) const
+{
+ return m_Attributes.end();
+}
+
+String DynamicObject::GetType(void) const
+{
+ String type;
+ GetAttribute("__type", &type);
+ return type;
+}
+
+String DynamicObject::GetName(void) const
+{
+ String name;
+ GetAttribute("__name", &name);
+ return name;
+}
+
+bool DynamicObject::IsLocal(void) const
+{
+ long local = 0;
+ GetAttribute("__local", &local);
+ return (local != 0);
+}
+
+bool DynamicObject::IsAbstract(void) const
+{
+ long abstract = 0;
+ GetAttribute("__abstract", &abstract);
+ return (abstract != 0);
}
-void DynamicObject::SetCommitTimestamp(double ts)
+void DynamicObject::SetSource(const String& value)
{
- GetProperties()->Set("__tx", ts);
+ SetAttribute("__source", value);
}
-double DynamicObject::GetCommitTimestamp(void) const
+String DynamicObject::GetSource(void) const
{
- double value = 0;
- GetProperties()->Get("__tx", &value);
- return value;
+ String source;
+ GetAttribute("__source", &source);
+ return source;
}
-void DynamicObject::Commit(void)
+void DynamicObject::Register(void)
{
assert(Application::IsMainThread());
ti = GetAllObjects().insert(make_pair(GetType(), DynamicObject::NameMap()));
ti.first->second.insert(make_pair(GetName(), GetSelf()));
- SetCommitTimestamp(Utility::GetTime());
-
- OnCommitted(GetSelf());
+ OnRegistered(GetSelf());
}
void DynamicObject::Unregister(void)
tt->second.erase(nt);
- OnRemoved(GetSelf());
+ OnUnregistered(GetSelf());
}
-DynamicObject::Ptr DynamicObject::GetObject(const string& type, const string& name)
+DynamicObject::Ptr DynamicObject::GetObject(const String& type, const String& name)
{
DynamicObject::TypeMap::iterator tt;
tt = GetAllObjects().find(type);
return make_pair(GetAllObjects().begin(), GetAllObjects().end());
}
-pair<DynamicObject::NameMap::iterator, DynamicObject::NameMap::iterator> DynamicObject::GetObjects(const string& type)
+pair<DynamicObject::NameMap::iterator, DynamicObject::NameMap::iterator> DynamicObject::GetObjects(const String& type)
{
pair<DynamicObject::TypeMap::iterator, bool> ti;
ti = GetAllObjects().insert(make_pair(type, DynamicObject::NameMap()));
return make_pair(ti.first->second.begin(), ti.first->second.end());
}
-void DynamicObject::RemoveTag(const string& key)
-{
- GetTags()->Remove(key);
-}
-
-ScriptTask::Ptr DynamicObject::InvokeMethod(const string& method,
- const vector<Variant>& arguments, ScriptTask::CompletionCallback callback)
+ScriptTask::Ptr DynamicObject::InvokeMethod(const String& method,
+ const vector<Value>& arguments, ScriptTask::CompletionCallback callback)
{
Dictionary::Ptr methods;
- string funcName;
- if (!GetProperty("methods", &methods) || !methods->Get(method, &funcName))
+ if (!GetAttribute("methods", &methods) || !methods->Contains(method))
return ScriptTask::Ptr();
+ String funcName = methods->Get(method);
+
ScriptFunction::Ptr func = ScriptFunction::GetByName(funcName);
if (!func)
return task;
}
-void DynamicObject::DumpObjects(const string& filename)
+void DynamicObject::DumpObjects(const String& filename)
{
Logger::Write(LogInformation, "base", "Dumping program state to file '" + filename + "'");
ofstream fp;
- fp.open(filename.c_str());
+ fp.open(filename.CStr());
if (!fp)
throw_exception(runtime_error("Could not open '" + filename + "' file"));
persistentObject->Set("type", object->GetType());
persistentObject->Set("name", object->GetName());
+ int types = Attribute_Replicated;
+
/* only persist properties for replicated objects or for objects
* that are marked as persistent */
- if (!object->GetSource().empty() /*|| object->IsPersistent()*/)
- persistentObject->Set("properties", object->GetProperties());
+ if (!object->GetSource().IsEmpty() /*|| object->IsPersistent()*/) {
+ types |= Attribute_Config;
+ persistentObject->Set("create", true);
+ } else {
+ persistentObject->Set("create", false);
+ }
+
+ Dictionary::Ptr update = object->BuildUpdate(0, types);
+
+ if (!update)
+ continue;
- persistentObject->Set("tags", object->GetTags());
+ persistentObject->Set("update", update);
- Variant value = persistentObject;
- string json = value.Serialize();
+ Value value = persistentObject;
+ String json = value.Serialize();
- /* This is quite ugly, unfortunatelly Netstring requires an IOQueue object */
- Netstring::WriteStringToIOQueue(fifo.get(), json);
+ /* This is quite ugly, unfortunatelly NetString requires an IOQueue object */
+ NetString::WriteStringToIOQueue(fifo.get(), json);
size_t count;
while ((count = fifo->GetAvailableBytes()) > 0) {
}
}
-void DynamicObject::RestoreObjects(const string& filename)
+void DynamicObject::RestoreObjects(const String& filename)
{
Logger::Write(LogInformation, "base", "Restoring program state from file '" + filename + "'");
std::ifstream fp;
- fp.open(filename.c_str());
+ fp.open(filename.CStr());
/* TODO: Fix this horrible mess. */
FIFO::Ptr fifo = boost::make_shared<FIFO>();
fifo->Write(buffer, fp.gcount());
}
- string message;
- while (Netstring::ReadStringFromIOQueue(fifo.get(), &message)) {
- Variant value = Variant::Deserialize(message);
+ String message;
+ while (NetString::ReadStringFromIOQueue(fifo.get(), &message)) {
+ Value value = Value::Deserialize(message);
if (!value.IsObjectType<Dictionary>())
throw_exception(runtime_error("JSON objects in the program state file must be dictionaries."));
Dictionary::Ptr persistentObject = value;
- string type;
- if (!persistentObject->Get("type", &type))
- continue;
-
- string name;
- if (!persistentObject->Get("name", &name))
- continue;
-
- Dictionary::Ptr tags;
- if (!persistentObject->Get("tags", &tags))
- continue;
+ String type = persistentObject->Get("type");
+ String name = persistentObject->Get("name");
+ int create = persistentObject->Get("create");
+ Dictionary::Ptr update = persistentObject->Get("update");
- Dictionary::Ptr properties;
- if (persistentObject->Get("properties", &properties)) {
- DynamicObject::Ptr object = Create(type, properties);
- object->SetTags(tags);
- object->Commit();
+ if (create != 0) {
+ DynamicObject::Ptr object = Create(type, update);
+ object->Register();
} else {
/* keep non-replicated objects until another config object with
* the same name is created (which is when we restore its tags) */
- m_PersistentTags[make_pair(type, name)] = tags;
+ m_PersistentUpdates[make_pair(type, name)] = update;
}
}
}
return classes;
}
-void DynamicObject::RegisterClass(const string& type, DynamicObject::Factory factory)
+void DynamicObject::RegisterClass(const String& type, DynamicObject::Factory factory)
{
if (GetObjects(type).first != GetObjects(type).second)
throw_exception(runtime_error("Cannot register class for type '" +
GetClasses()[type] = factory;
}
-DynamicObject::Ptr DynamicObject::Create(const string& type, const Dictionary::Ptr& properties)
+DynamicObject::Ptr DynamicObject::Create(const String& type, const Dictionary::Ptr& properties)
{
DynamicObject::ClassMap::iterator it;
it = GetClasses().find(type);
else
return boost::make_shared<DynamicObject>(properties);
}
+
+double DynamicObject::GetCurrentTx(void)
+{
+ assert(m_CurrentTx != 0);
+
+ return m_CurrentTx;
+}
+
+void DynamicObject::BeginTx(void)
+{
+ m_CurrentTx = Utility::GetTime();
+}
+
+void DynamicObject::FinishTx(void)
+{
+ OnTransactionClosing(m_ModifiedObjects);
+ m_ModifiedObjects.clear();
+
+ m_CurrentTx = 0;
+}
namespace icinga
{
+enum DynamicAttributeType
+{
+ Attribute_Transient = 1,
+
+ /* Unlike transient attributes local attributes are persisted
+ * in the program state file. */
+ Attribute_Local = 2,
+
+ /* Replicated attributes are sent to other daemons for which
+ * replication is enabled. */
+ Attribute_Replicated = 4,
+
+ /* Attributes read from the config file are implicitly marked
+ * as config attributes. */
+ Attribute_Config = 8,
+};
+
+struct DynamicAttribute
+{
+ Value Data;
+ DynamicAttributeType Type;
+ double Tx;
+};
+
/**
* A dynamic object that can be instantiated from the configuration file.
*
typedef function<DynamicObject::Ptr (const Dictionary::Ptr&)> Factory;
- typedef map<string, Factory> ClassMap;
- typedef map<string, DynamicObject::Ptr> NameMap;
- typedef map<string, NameMap> TypeMap;
+ typedef map<String, Factory> ClassMap;
+ typedef map<String, DynamicObject::Ptr> NameMap;
+ typedef map<String, NameMap> TypeMap;
- DynamicObject(const Dictionary::Ptr& properties);
+ typedef map<String, DynamicAttribute> AttributeMap;
+ typedef AttributeMap::iterator AttributeIterator;
+ typedef AttributeMap::const_iterator AttributeConstIterator;
- void SetProperties(const Dictionary::Ptr& config);
- Dictionary::Ptr GetProperties(void) const;
+ DynamicObject(const Dictionary::Ptr& serializedObject);
- template<typename T>
- bool GetProperty(const string& key, T *value) const
- {
- return GetProperties()->Get(key, value);
- }
+ Dictionary::Ptr BuildUpdate(double sinceTx, int attributeTypes) const;
+ void ApplyUpdate(const Dictionary::Ptr& serializedUpdate, bool suppressEvents = false);
+ static void SanitizeUpdate(const Dictionary::Ptr& serializedUpdate, int allowedTypes);
- void SetTags(const Dictionary::Ptr& tags);
- Dictionary::Ptr GetTags(void) const;
+ void RegisterAttribute(const String& name, DynamicAttributeType type);
- template<typename T>
- void SetTag(const string& key, const T& value)
- {
- GetTags()->Set(key, value);
- }
+ void SetAttribute(const String& name, const Value& data);
template<typename T>
- bool GetTag(const string& key, T *value) const
+ bool GetAttribute(const String& name, T *retval) const
{
- return GetTags()->Get(key, value);
+ Value data = InternalGetAttribute(name);
+
+ if (data.IsEmpty())
+ return false;
+
+ *retval = static_cast<T>(data);
+ return true;
}
- void RemoveTag(const string& key);
+ void ClearAttribute(const String& name);
- ScriptTask::Ptr InvokeMethod(const string& method,
- const vector<Variant>& arguments, ScriptTask::CompletionCallback callback);
+ bool HasAttribute(const String& name) const;
- string GetType(void) const;
- string GetName(void) const;
+ void ClearAttributesByType(DynamicAttributeType type);
+
+ AttributeConstIterator AttributeBegin(void) const;
+ AttributeConstIterator AttributeEnd(void) const;
+
+ static boost::signal<void (const DynamicObject::Ptr&, const String& name)> OnAttributeChanged;
+ static boost::signal<void (const DynamicObject::Ptr&)> OnRegistered;
+ static boost::signal<void (const DynamicObject::Ptr&)> OnUnregistered;
+ static boost::signal<void (const set<DynamicObject::Ptr>&)> OnTransactionClosing;
+
+ ScriptTask::Ptr InvokeMethod(const String& method,
+ const vector<Value>& arguments, ScriptTask::CompletionCallback callback);
+
+ String GetType(void) const;
+ String GetName(void) const;
bool IsLocal(void) const;
bool IsAbstract(void) const;
- void SetSource(const string& value);
- string GetSource(void) const;
+ void SetSource(const String& value);
+ String GetSource(void) const;
- double GetCommitTimestamp(void) const;
+ void SetTx(double tx);
+ double GetTx(void) const;
- void Commit(void);
+ void Register(void);
void Unregister(void);
- static DynamicObject::Ptr GetObject(const string& type, const string& name);
+ static DynamicObject::Ptr GetObject(const String& type, const String& name);
static pair<TypeMap::iterator, TypeMap::iterator> GetTypes(void);
- static pair<NameMap::iterator, NameMap::iterator> GetObjects(const string& type);
+ static pair<NameMap::iterator, NameMap::iterator> GetObjects(const String& type);
- static void DumpObjects(const string& filename);
- static void RestoreObjects(const string& filename);
+ static void DumpObjects(const String& filename);
+ static void RestoreObjects(const String& filename);
- static void RegisterClass(const string& type, Factory factory);
- static DynamicObject::Ptr Create(const string& type, const Dictionary::Ptr& properties);
+ static void RegisterClass(const String& type, Factory factory);
+ static DynamicObject::Ptr Create(const String& type, const Dictionary::Ptr& properties);
- static boost::signal<void (const DynamicObject::Ptr&)> OnCommitted;
- static boost::signal<void (const DynamicObject::Ptr&)> OnRemoved;
+ static double GetCurrentTx(void);
+ static void BeginTx(void);
+ static void FinishTx(void);
private:
+ void InternalSetAttribute(const String& name, const Value& data, double tx, bool suppressEvent = false);
+ Value InternalGetAttribute(const String& name) const;
+
static ClassMap& GetClasses(void);
static TypeMap& GetAllObjects(void);
- Dictionary::Ptr m_Properties;
- Dictionary::Ptr m_Tags;
+ AttributeMap m_Attributes;
+ double m_ConfigTx;
- static map<pair<string, string>, Dictionary::Ptr> m_PersistentTags;
+ static map<pair<String, String>, Dictionary::Ptr> m_PersistentUpdates;
+ static double m_CurrentTx;
- void SetCommitTimestamp(double ts);
+ static set<DynamicObject::Ptr> m_ModifiedObjects;
};
class RegisterClassHelper
{
public:
- RegisterClassHelper(const string& name, DynamicObject::Factory factory)
+ RegisterClassHelper(const String& name, DynamicObject::Factory factory)
{
DynamicObject::RegisterClass(name, factory);
}
*
* @returns The description.
*/
-string Exception::GetMessage(void) const
+String Exception::GetMessage(void) const
{
return m_Message;
}
*/
const char *Exception::what(void) const throw()
{
- return m_Message.c_str();
+ return m_Message.CStr();
}
/**
*
* @param message The description.
*/
-void Exception::SetMessage(string message)
+void Exception::SetMessage(String message)
{
m_Message = message;
}
* Formats an Win32 error code.
*
* @param code The error code.
- * @returns A string describing the error.
+ * @returns A String describing the error.
*/
-string Win32Exception::FormatErrorCode(int code)
+String Win32Exception::FormatErrorCode(int code)
{
char *message;
- string result = "Unknown error.";
+ String result = "Unknown error.";
DWORD rc = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM, NULL, code, 0, (char *)&message,
0, NULL);
if (rc != 0) {
- result = string(message);
+ result = String(message);
LocalFree(message);
/* remove trailing new-line characters */
* Formats a Posix error code.
*
* @param code The error code.
- * @returns A string describing the error.
+ * @returns A String describing the error.
*/
-string PosixException::FormatErrorCode(int code)
+String PosixException::FormatErrorCode(int code)
{
return strerror(code);
}
* Formats an OpenSSL error code.
*
* @param code The error code.
- * @returns A string describing the error.
+ * @returns A String describing the error.
*/
-string OpenSSLException::FormatErrorCode(int code)
+String OpenSSLException::FormatErrorCode(int code)
{
const char *message = ERR_error_string(code, NULL);
: m_Message(), m_Code(0)
{ }
- Exception(string message)
+ Exception(String message)
: m_Message(message), m_Code(0)
{ }
- Exception(string message, int code)
+ Exception(String message, int code)
: m_Message(message), m_Code(code)
{ }
{ }
int GetCode(void) const;
- string GetMessage(void) const;
+ String GetMessage(void) const;
virtual const char *what(void) const throw();
protected:
void SetCode(int code);
- void SetMessage(string message);
+ void SetMessage(String message);
private:
- string m_Message;
+ String m_Message;
int m_Code;
};
inline klass(void) : Exception() \
{ } \
\
- inline klass(string message) \
+ inline klass(String message) \
: Exception(message) \
{ } \
}
* @param message An error message.
* @param errorCode A Win32 error code.
*/
- inline Win32Exception(const string& message, int errorCode)
+ inline Win32Exception(const String& message, int errorCode)
: Exception(message + ": " + FormatErrorCode(errorCode), errorCode)
{ }
/**
- * Returns a string that describes the Win32 error.
+ * Returns a String that describes the Win32 error.
*
* @param code The Win32 error code.
* @returns A description of the error.
*/
- static string FormatErrorCode(int code);
+ static String FormatErrorCode(int code);
};
#endif /* _WIN32 */
* @param message An error message.
* @param errorCode A Posix (errno) error code.
*/
- inline PosixException(const string& message, int errorCode)
+ inline PosixException(const String& message, int errorCode)
: Exception(message + ": " + FormatErrorCode(errorCode), errorCode)
{ }
/**
- * Returns a string that describes the Posix error.
+ * Returns a String that describes the Posix error.
*
* @param code The Posix error code.
* @returns A description of the error.
*/
- static string FormatErrorCode(int code);
+ static String FormatErrorCode(int code);
};
/**
* @param message An error message.
* @param errorCode An OpenSSL error code.
*/
- inline OpenSSLException(const string& message, int errorCode)
+ inline OpenSSLException(const String& message, int errorCode)
: Exception(message + ": " + FormatErrorCode(errorCode), errorCode)
{ }
/**
- * Returns a string that describes the OpenSSL error.
+ * Returns a String that describes the OpenSSL error.
*
* @param code The OpenSSL error code.
* @returns A description of the error.
*/
- static string FormatErrorCode(int code);
+ static String FormatErrorCode(int code);
};
}
#include <algorithm>
#include <deque>
-using std::string;
using std::vector;
using std::map;
using std::list;
using std::multimap;
using std::pair;
using std::deque;
+using std::make_pair;
using std::stringstream;
using std::istream;
# define I2_BASE_API I2_IMPORT
#endif /* I2_BASE_BUILD */
+#include "qstring.h"
#include "utility.h"
#include "object.h"
#include "exception.h"
#include "event.h"
-#include "variant.h"
+#include "value.h"
#include "dictionary.h"
#include "ringbuffer.h"
#include "timer.h"
Logger::Logger(const Dictionary::Ptr& properties)
: DynamicObject(properties)
{
+ RegisterAttribute("type", Attribute_Config);
+ RegisterAttribute("path", Attribute_Config);
+ RegisterAttribute("severity", Attribute_Config);
+
if (!IsLocal())
throw_exception(runtime_error("Logger objects must be local."));
- string type;
- if (!GetProperty("type", &type))
+ String type;
+ if (!GetAttribute("type", &type))
throw_exception(runtime_error("Logger objects must have a 'type' property."));
ILogger::Ptr impl;
throw_exception(invalid_argument("Syslog is not supported on Windows."));
#endif /* _WIN32 */
} else if (type == "file") {
- string path;
- if (!GetProperty("path", &path))
+ String path;
+ if (!GetAttribute("path", &path))
throw_exception(invalid_argument("'log' object of type 'file' must have a 'path' property"));
StreamLogger::Ptr slogger = boost::make_shared<StreamLogger>();
}
impl->m_Config = this;
- SetImplementation(impl);
+ m_Impl = impl;
}
/**
* @param facility The log facility.
* @param message The message.
*/
-void Logger::Write(LogSeverity severity, const string& facility,
- const string& message)
+void Logger::Write(LogSeverity severity, const String& facility,
+ const String& message)
{
LogEntry entry;
entry.Timestamp = Utility::GetTime();
*/
LogSeverity Logger::GetMinSeverity(void) const
{
- string strSeverity;
- LogSeverity severity = LogInformation;
- if (GetProperty("severity", &strSeverity))
- severity = Logger::StringToSeverity(strSeverity);
-
- return severity;
+ String strSeverity = "information";
+ GetAttribute("severity", &strSeverity);
+ return Logger::StringToSeverity(strSeverity);
}
/**
Logger::Ptr logger = dynamic_pointer_cast<Logger>(object);
if (entry.Severity >= logger->GetMinSeverity())
- logger->GetImplementation()->ProcessLogEntry(entry);
+ logger->m_Impl->ProcessLogEntry(entry);
}
}
-ILogger::Ptr Logger::GetImplementation(void) const
-{
- ILogger::Ptr impl;
- GetTag("impl", &impl);
- return impl;
-}
-
-void Logger::SetImplementation(const ILogger::Ptr& impl)
-{
- SetTag("impl", impl);
-}
-
-string Logger::SeverityToString(LogSeverity severity)
+String Logger::SeverityToString(LogSeverity severity)
{
switch (severity) {
case LogDebug:
}
}
-LogSeverity Logger::StringToSeverity(const string& severity)
+LogSeverity Logger::StringToSeverity(const String& severity)
{
if (severity == "debug")
return LogDebug;
struct LogEntry {
double Timestamp;
LogSeverity Severity;
- string Facility;
- string Message;
+ String Facility;
+ String Message;
};
/**
Logger(const Dictionary::Ptr& properties);
- static void Write(LogSeverity severity, const string& facility,
- const string& message);
+ static void Write(LogSeverity severity, const String& facility,
+ const String& message);
- static string SeverityToString(LogSeverity severity);
- static LogSeverity StringToSeverity(const string& severity);
+ static String SeverityToString(LogSeverity severity);
+ static LogSeverity StringToSeverity(const String& severity);
LogSeverity GetMinSeverity(void) const;
private:
LogSeverity m_MinSeverity;
-
- ILogger::Ptr GetImplementation(void) const;
- void SetImplementation(const ILogger::Ptr& impl);
+ ILogger::Ptr m_Impl;
static void ForwardLogEntry(const LogEntry& entry);
};
using namespace icinga;
/**
- * Reads data from an IOQueue in netstring format.
+ * Reads data from an IOQueue in netString format.
*
* @param fifo The IOQueue to read from.
- * @param[out] str The string that has been read from the FIFO.
- * @returns true if a complete string was read from the FIFO, false otherwise.
+ * @param[out] str The String that has been read from the FIFO.
+ * @returns true if a complete String was read from the FIFO, false otherwise.
* @exception invalid_argument The input stream is invalid.
- * @see https://github.com/PeterScott/netstring-c/blob/master/netstring.c
+ * @see https://github.com/PeterScott/netString-c/blob/master/netString.c
*/
-bool Netstring::ReadStringFromIOQueue(IOQueue *queue, string *str)
+bool NetString::ReadStringFromIOQueue(IOQueue *queue, String *str)
{
size_t buffer_length = queue->GetAvailableBytes();
- /* minimum netstring length is 3 */
+ /* minimum netString length is 3 */
if (buffer_length < 3)
return false;
/* no leading zeros allowed */
if (buffer[0] == '0' && isdigit(buffer[1])) {
free(buffer);
- throw_exception(invalid_argument("Invalid netstring (leading zero)"));
+ throw_exception(invalid_argument("Invalid netString (leading zero)"));
}
size_t len, i;
/* check for the colon delimiter */
if (buffer[i] != ':') {
free(buffer);
- throw_exception(invalid_argument("Invalid Netstring (missing :)"));
+ throw_exception(invalid_argument("Invalid NetString (missing :)"));
}
- /* check for the comma delimiter after the string */
+ /* check for the comma delimiter after the String */
if (buffer[i + 1 + len] != ',') {
free(buffer);
- throw_exception(invalid_argument("Invalid Netstring (missing ,)"));
+ throw_exception(invalid_argument("Invalid NetString (missing ,)"));
}
- *str = string(&buffer[i + 1], &buffer[i + 1 + len]);
+ *str = String(&buffer[i + 1], &buffer[i + 1 + len]);
free(buffer);
}
/**
- * Writes data into a FIFO using the netstring format.
+ * Writes data into a FIFO using the netString format.
*
* @param fifo The FIFO.
- * @param str The string that is to be written.
+ * @param str The String that is to be written.
*/
-void Netstring::WriteStringToIOQueue(IOQueue *queue, const string& str)
+void NetString::WriteStringToIOQueue(IOQueue *queue, const String& str)
{
stringstream prefixbuf;
- prefixbuf << str.size() << ":";
+ prefixbuf << str.GetLength() << ":";
- string prefix = prefixbuf.str();
- queue->Write(prefix.c_str(), prefix.size());
- queue->Write(str.c_str(), str.size());
+ String prefix = prefixbuf.str();
+ queue->Write(prefix.CStr(), prefix.GetLength());
+ queue->Write(str.CStr(), str.GetLength());
queue->Write(",", 1);
}
{
/**
- * Helper functions for reading/writing messages in the netstring format.
+ * Helper functions for reading/writing messages in the netString format.
*
- * @see http://cr.yp.to/proto/netstrings.txt
+ * @see http://cr.yp.to/proto/netStrings.txt
*
* @ingroup base
*/
-class I2_BASE_API Netstring
+class I2_BASE_API NetString
{
public:
- static bool ReadStringFromIOQueue(IOQueue *queue, string *message);
- static void WriteStringToIOQueue(IOQueue *queue, const string& message);
+ static bool ReadStringFromIOQueue(IOQueue *queue, String *message);
+ static void WriteStringToIOQueue(IOQueue *queue, const String& message);
private:
- Netstring(void);
+ NetString(void);
};
}
deque<Process::Ptr> Process::m_Tasks;
condition_variable Process::m_TasksCV;
-Process::Process(const string& command)
+Process::Process(const String& command)
: AsyncTask<Process, ProcessResult>(), m_Command(command), m_UsePopen(false)
{
if (!m_ThreadCreated) {
m_Result.ExecutionStart = Utility::GetTime();
#ifdef _MSC_VER
- m_FP = _popen(m_Command.c_str(), "r");
+ m_FP = _popen(m_Command.CStr(), "r");
#else /* _MSC_VER */
if (!m_UsePopen) {
m_PCloseArg = new popen_noshell_pass_to_pclose;
- m_FP = popen_noshell_compat(m_Command.c_str(), "r",
+ m_FP = popen_noshell_compat(m_Command.CStr(), "r",
(popen_noshell_pass_to_pclose *)m_PCloseArg);
if (m_FP == NULL)
}
if (m_UsePopen)
- m_FP = popen(m_Command.c_str(), "r");
+ m_FP = popen(m_Command.CStr(), "r");
#endif /* _MSC_VER */
if (m_FP == NULL)
if (!feof(m_FP))
return true;
- string output = m_OutputStream.str();
+ String output = m_OutputStream.str();
int status, exitcode;
#ifdef _MSC_VER
/* cmd.exe returns error code 1 (warning) when the plugin
* could not be executed - change the exit status to "unknown"
* when we have no plugin output. */
- if (output.empty())
+ if (output.IsEmpty())
exitcode = 128;
#endif /* _MSC_VER */
double ExecutionStart;
double ExecutionEnd;
long ExitStatus;
- string Output;
+ String Output;
};
class I2_BASE_API Process : public AsyncTask<Process, ProcessResult>
static const int MaxTasksPerThread = 128;
- Process(const string& command);
+ Process(const String& command);
private:
static bool m_ThreadCreated;
- string m_Command;
+ String m_Command;
FILE *m_FP;
stringstream m_OutputStream;
--- /dev/null
+#include "i2-base.h"
+
+using namespace icinga;
+
+const size_t String::NPos = std::string::npos;
+
+String::String(void)
+{ }
+
+String::String(const char *data)
+ : m_Data(data)
+{ }
+
+String::String(const std::string& data)
+ : m_Data(data)
+{ }
+
+String::String(const String& other)
+ : m_Data(other.m_Data)
+{ }
+
+String& String::operator=(const String& rhs)
+{
+ m_Data = rhs.m_Data;
+ return *this;
+}
+
+String& String::operator=(const std::string& rhs)
+{
+ m_Data = rhs;
+ return *this;
+}
+
+String& String::operator=(const char *rhs)
+{
+ m_Data = rhs;
+ return *this;
+}
+
+const char& String::operator[](size_t pos) const
+{
+ return m_Data[pos];
+}
+
+char& String::operator[](size_t pos)
+{
+ return m_Data[pos];
+}
+
+String& String::operator+=(const String& rhs)
+{
+ m_Data += rhs.m_Data;
+ return *this;
+}
+
+String& String::operator+=(const char *rhs)
+{
+ m_Data += rhs;
+ return *this;
+}
+
+bool String::IsEmpty(void) const
+{
+ return m_Data.empty();
+}
+
+bool String::operator<(const String& rhs) const
+{
+ return m_Data < rhs.m_Data;
+}
+
+String::operator const std::string&(void) const
+{
+ return m_Data;
+}
+
+const char *String::CStr(void) const
+{
+ return m_Data.c_str();
+}
+
+void String::Clear(void)
+{
+ m_Data.clear();
+ }
+
+size_t String::GetLength(void) const
+{
+ return m_Data.size();
+}
+
+size_t String::FindFirstOf(const char *s, size_t pos) const
+{
+ return m_Data.find_first_of(s, pos);
+}
+
+String String::SubStr(size_t first, size_t second) const
+{
+ return m_Data.substr(first, second);
+}
+
+void String::Replace(size_t first, size_t second, const String& str)
+{
+ m_Data.replace(first, second, str);
+}
+
+void String::Trim(void)
+{
+ boost::algorithm::trim(m_Data);
+}
+
+void String::swap(String& str)
+{
+ m_Data.swap(str.m_Data);
+}
+
+String::Iterator String::erase(String::Iterator first, String::Iterator last)
+{
+ return m_Data.erase(first, last);
+}
+
+String::Iterator String::Begin(void)
+{
+ return m_Data.begin();
+}
+
+String::ConstIterator String::Begin(void) const
+{
+ return m_Data.begin();
+}
+
+String::Iterator String::End(void)
+{
+ return m_Data.end();
+}
+
+String::ConstIterator String::End(void) const
+{
+ return m_Data.end();
+}
+
+ostream& icinga::operator<<(ostream& stream, const String& str)
+{
+ stream << static_cast<std::string>(str);
+ return stream;
+}
+
+istream& icinga::operator>>(istream& stream, String& str)
+{
+ std::string tstr;
+ stream >> tstr;
+ str = tstr;
+ return stream;
+}
+
+String icinga::operator+(const String& lhs, const String& rhs)
+{
+ return static_cast<std::string>(lhs) + static_cast<std::string>(rhs);
+}
+
+String icinga::operator+(const String& lhs, const char *rhs)
+{
+ return static_cast<std::string>(lhs) + rhs;
+}
+
+String icinga::operator+(const char *lhs, const String& rhs)
+{
+ return lhs + static_cast<std::string>(rhs);
+}
+
+bool icinga::operator==(const String& lhs, const String& rhs)
+{
+ return static_cast<std::string>(lhs) == static_cast<std::string>(rhs);
+}
+
+bool icinga::operator==(const String& lhs, const char *rhs)
+{
+ return static_cast<std::string>(lhs) == rhs;
+}
+
+bool icinga::operator==(const char *lhs, const String& rhs)
+{
+ return lhs == static_cast<std::string>(rhs);
+}
+
+String::Iterator icinga::range_begin(String& x)
+{
+ return x.Begin();
+}
+
+String::ConstIterator icinga::range_begin(const String& x)
+{
+ return x.Begin();
+}
+
+String::Iterator icinga::range_end(String& x)
+{
+ return x.End();
+}
+
+String::ConstIterator icinga::range_end(const String& x)
+{
+ return x.End();
+}
+
--- /dev/null
+#ifndef STRING_H
+#define STRING_H
+
+namespace icinga {
+
+/**
+ * String class.
+ *
+ * Rationale: The std::string class has an ambiguous assignment
+ * operator when used in conjunction with the Value class.
+ */
+class I2_BASE_API String
+{
+public:
+ typedef std::string::iterator Iterator;
+ typedef std::string::const_iterator ConstIterator;
+
+ String(void);
+ String(const char *data);
+ String(const std::string& data);
+
+ template<typename InputIterator>
+ String(InputIterator begin, InputIterator end)
+ : m_Data(begin, end)
+ { }
+
+ String(const String& other);
+
+ String& operator=(const String& rhs);
+ String& operator=(const std::string& rhs);
+ String& operator=(const char *rhs);
+
+ const char& operator[](size_t pos) const;
+ char& operator[](size_t pos);
+
+ String& operator+=(const String& rhs);
+ String& operator+=(const char *rhs);
+
+ bool IsEmpty(void) const;
+
+ bool operator<(const String& rhs) const;
+
+ operator const std::string&(void) const;
+
+ const char *CStr(void) const;
+ void Clear(void);
+ size_t GetLength(void) const;
+
+ size_t FindFirstOf(const char *s, size_t pos = 0) const;
+ String SubStr(size_t first, size_t second) const;
+ void Replace(size_t first, size_t second, const String& str);
+
+ template<typename Predicate>
+ vector<String> Split(const Predicate& predicate)
+ {
+ vector<String> tokens;
+ boost::algorithm::split(tokens, m_Data, predicate);
+ return tokens;
+ }
+
+ void Trim(void);
+
+ void swap(String& str);
+ Iterator erase(Iterator first, Iterator last);
+
+ Iterator Begin(void);
+ ConstIterator Begin(void) const;
+ Iterator End(void);
+ ConstIterator End(void) const;
+
+ static const size_t NPos;
+
+private:
+ std::string m_Data;
+};
+
+I2_BASE_API ostream& operator<<(ostream& stream, const String& str);
+I2_BASE_API istream& operator>>(istream& stream, String& str);
+
+I2_BASE_API String operator+(const String& lhs, const String& rhs);
+I2_BASE_API String operator+(const String& lhs, const char *rhs);
+I2_BASE_API String operator+(const char *lhs, const String& rhs);
+
+I2_BASE_API bool operator==(const String& lhs, const String& rhs);
+I2_BASE_API bool operator==(const String& lhs, const char *rhs);
+I2_BASE_API bool operator==(const char *lhs, const String& rhs);
+
+I2_BASE_API String::Iterator range_begin(String& x);
+I2_BASE_API String::ConstIterator range_begin(const String& x);
+I2_BASE_API String::Iterator range_end(String& x);
+I2_BASE_API String::ConstIterator range_end(const String& x);
+
+}
+
+namespace boost
+{
+
+template<>
+struct range_mutable_iterator<icinga::String>
+{
+ typedef icinga::String::Iterator type;
+};
+
+template<>
+struct range_const_iterator<icinga::String>
+{
+ typedef icinga::String::ConstIterator type;
+};
+
+}
+
+#endif /* STRING_H */
using namespace icinga;
-map<string, ScriptFunction::Ptr> ScriptFunction::m_Functions;
+map<String, ScriptFunction::Ptr> ScriptFunction::m_Functions;
ScriptFunction::ScriptFunction(const Callback& function)
: m_Callback(function)
{ }
-void ScriptFunction::Register(const string& name, const ScriptFunction::Ptr& function)
+void ScriptFunction::Register(const String& name, const ScriptFunction::Ptr& function)
{
m_Functions[name] = function;
}
-void ScriptFunction::Unregister(const string& name)
+void ScriptFunction::Unregister(const String& name)
{
m_Functions.erase(name);
}
-ScriptFunction::Ptr ScriptFunction::GetByName(const string& name)
+ScriptFunction::Ptr ScriptFunction::GetByName(const String& name)
{
- map<string, ScriptFunction::Ptr>::iterator it;
+ map<String, ScriptFunction::Ptr>::iterator it;
it = m_Functions.find(name);
return it->second;
}
-void ScriptFunction::Invoke(const ScriptTask::Ptr& task, const vector<Variant>& arguments)
+void ScriptFunction::Invoke(const ScriptTask::Ptr& task, const vector<Value>& arguments)
{
m_Callback(task, arguments);
}
typedef shared_ptr<ScriptFunction> Ptr;
typedef weak_ptr<ScriptFunction> WeakPtr;
- typedef function<void (const shared_ptr<ScriptTask>&, const vector<Variant>& arguments)> Callback;
+ typedef function<void (const shared_ptr<ScriptTask>&, const vector<Value>& arguments)> Callback;
ScriptFunction(const Callback& function);
- static void Register(const string& name, const ScriptFunction::Ptr& function);
- static void Unregister(const string& name);
- static ScriptFunction::Ptr GetByName(const string& name);
+ static void Register(const String& name, const ScriptFunction::Ptr& function);
+ static void Unregister(const String& name);
+ static ScriptFunction::Ptr GetByName(const String& name);
- void Invoke(const shared_ptr<ScriptTask>& task, const vector<Variant>& arguments);
+ void Invoke(const shared_ptr<ScriptTask>& task, const vector<Value>& arguments);
private:
Callback m_Callback;
- static map<string, ScriptFunction::Ptr> m_Functions;
+ static map<String, ScriptFunction::Ptr> m_Functions;
};
}
using namespace icinga;
-ScriptTask::ScriptTask(const ScriptFunction::Ptr& function, const vector<Variant>& arguments)
- : AsyncTask<ScriptTask, Variant>(), m_Function(function), m_Arguments(arguments)
+ScriptTask::ScriptTask(const ScriptFunction::Ptr& function, const vector<Value>& arguments)
+ : AsyncTask<ScriptTask, Value>(), m_Function(function), m_Arguments(arguments)
{ }
void ScriptTask::Run(void)
namespace icinga
{
-class I2_BASE_API ScriptTask : public AsyncTask<ScriptTask, Variant>
+class I2_BASE_API ScriptTask : public AsyncTask<ScriptTask, Value>
{
public:
typedef shared_ptr<ScriptTask> Ptr;
typedef weak_ptr<ScriptTask> WeakPtr;
- ScriptTask(const ScriptFunction::Ptr& function, const vector<Variant>& arguments);
+ ScriptTask(const ScriptFunction::Ptr& function, const vector<Value>& arguments);
protected:
virtual void Run(void);
private:
ScriptFunction::Ptr m_Function;
- vector<Variant> m_Arguments;
+ vector<Value> m_Arguments;
};
}
/**
* Formats a sockaddr in a human-readable way.
*
- * @returns A string describing the sockaddr.
+ * @returns A String describing the sockaddr.
*/
-string Socket::GetAddressFromSockaddr(sockaddr *address, socklen_t len)
+String Socket::GetAddressFromSockaddr(sockaddr *address, socklen_t len)
{
char host[NI_MAXHOST];
char service[NI_MAXSERV];
}
/**
- * Returns a string describing the local address of the socket.
+ * Returns a String describing the local address of the socket.
*
- * @returns A string describing the local address.
+ * @returns A String describing the local address.
*/
-string Socket::GetClientAddress(void)
+String Socket::GetClientAddress(void)
{
mutex::scoped_lock lock(m_Mutex);
}
/**
- * Returns a string describing the peer address of the socket.
+ * Returns a String describing the peer address of the socket.
*
- * @returns A string describing the peer address.
+ * @returns A String describing the peer address.
*/
-string Socket::GetPeerAddress(void)
+String Socket::GetPeerAddress(void)
{
mutex::scoped_lock lock(m_Mutex);
* @param message The error message.
* @param errorCode The error code.
*/
-SocketException::SocketException(const string& message, int errorCode)
+SocketException::SocketException(const String& message, int errorCode)
{
#ifdef _WIN32
- string details = Win32Exception::FormatErrorCode(errorCode);
+ String details = Win32Exception::FormatErrorCode(errorCode);
#else /* _WIN32 */
- string details = PosixException::FormatErrorCode(errorCode);
+ String details = PosixException::FormatErrorCode(errorCode);
#endif /* _WIN32 */
- string msg = message + ": " + details;
- SetMessage(msg.c_str());
+ String msg = message + ": " + details;
+ SetMessage(msg.CStr());
}
void Socket::ReadThreadProc(void)
void Close(void);
- string GetClientAddress(void);
- string GetPeerAddress(void);
+ String GetClientAddress(void);
+ String GetPeerAddress(void);
mutex& GetMutex(void) const;
void ExceptionEventHandler(void);
- static string GetAddressFromSockaddr(sockaddr *address, socklen_t len);
+ static String GetAddressFromSockaddr(sockaddr *address, socklen_t len);
};
/**
class SocketException : public Exception
{
public:
- SocketException(const string& message, int errorCode);
+ SocketException(const String& message, int errorCode);
};
}
delete m_Stream;
}
-void StreamLogger::OpenFile(const string& filename)
+void StreamLogger::OpenFile(const String& filename)
{
ofstream *stream = new ofstream();
try {
- stream->open(filename.c_str(), ofstream::out | ofstream::trunc);
+ stream->open(filename.CStr(), ofstream::out | ofstream::trunc);
if (!stream->good())
throw_exception(runtime_error("Could not open logfile '" + filename + "'"));
StreamLogger(std::ostream *stream);
~StreamLogger(void);
- void OpenFile(const string& filename);
+ void OpenFile(const String& filename);
protected:
virtual void ProcessLogEntry(const LogEntry& entry);
assert(!"Invalid severity specified.");
}
- syslog(severity | LOG_USER, "%s", entry.Message.c_str());
+ syslog(severity | LOG_USER, "%s", entry.Message.CStr());
}
#endif /* _WIN32 */
* @param node The node.
* @param service The service.
*/
-void TcpClient::Connect(const string& node, const string& service)
+void TcpClient::Connect(const String& node, const String& service)
{
m_Role = RoleOutbound;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
- int rc = getaddrinfo(node.c_str(), service.c_str(), &hints, &result);
+ int rc = getaddrinfo(node.CStr(), service.CStr(), &hints, &result);
if (rc < 0)
throw_exception(SocketException("getaddrinfo() failed", GetLastSocketError()));
TcpClientRole GetRole(void) const;
- void Connect(const string& node, const string& service);
+ void Connect(const String& node, const String& service);
boost::signal<void (const TcpClient::Ptr&)> OnConnected;
boost::signal<void (const TcpClient::Ptr&)> OnDataAvailable;
* @param service The service.
* @param family The address family for the socket.
*/
-void TcpSocket::Bind(string service, int family)
+void TcpSocket::Bind(String service, int family)
{
- Bind(string(), service, family);
+ Bind(String(), service, family);
}
/**
* @param service The service.
* @param family The address family for the socket.
*/
-void TcpSocket::Bind(string node, string service, int family)
+void TcpSocket::Bind(String node, String service, int family)
{
addrinfo hints;
addrinfo *result;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
- if (getaddrinfo(node.empty() ? NULL : node.c_str(),
- service.c_str(), &hints, &result) < 0)
+ if (getaddrinfo(node.IsEmpty() ? NULL : node.CStr(),
+ service.CStr(), &hints, &result) < 0)
throw_exception(SocketException("getaddrinfo() failed", GetLastSocketError()));
int fd = INVALID_SOCKET;
typedef shared_ptr<TcpSocket> Ptr;
typedef weak_ptr<TcpSocket> WeakPtr;
- void Bind(string service, int family);
- void Bind(string node, string service, int family);
+ void Bind(String service, int family);
+ void Bind(String node, String service, int family);
private:
void MakeSocket(int family);
* @param ti A type_info object.
* @returns The type name of the object.
*/
-string Utility::GetTypeName(const type_info& ti)
+String Utility::GetTypeName(const type_info& ti)
{
- string klass = ti.name();
+ String klass = ti.name();
#ifdef HAVE_GCC_ABI_DEMANGLE
int status;
- char *realname = abi::__cxa_demangle(klass.c_str(), 0, 0, &status);
+ char *realname = abi::__cxa_demangle(klass.CStr(), 0, 0, &status);
if (realname != NULL) {
- klass = string(realname);
+ klass = String(realname);
free(realname);
}
#endif /* HAVE_GCC_ABI_DEMANGLE */
* @param cakey CA certificate chain file.
* @returns An SSL context.
*/
-shared_ptr<SSL_CTX> Utility::MakeSSLContext(string pubkey, string privkey, string cakey)
+shared_ptr<SSL_CTX> Utility::MakeSSLContext(String pubkey, String privkey, String cakey)
{
InitializeOpenSSL();
SSL_CTX_set_mode(sslContext.get(), SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
- if (!SSL_CTX_use_certificate_chain_file(sslContext.get(), pubkey.c_str()))
+ if (!SSL_CTX_use_certificate_chain_file(sslContext.get(), pubkey.CStr()))
throw_exception(OpenSSLException("Could not load public X509 key file", ERR_get_error()));
- if (!SSL_CTX_use_PrivateKey_file(sslContext.get(), privkey.c_str(), SSL_FILETYPE_PEM))
+ if (!SSL_CTX_use_PrivateKey_file(sslContext.get(), privkey.CStr(), SSL_FILETYPE_PEM))
throw_exception(OpenSSLException("Could not load private X509 key file", ERR_get_error()));
- if (!SSL_CTX_load_verify_locations(sslContext.get(), cakey.c_str(), NULL))
+ if (!SSL_CTX_load_verify_locations(sslContext.get(), cakey.CStr(), NULL))
throw_exception(OpenSSLException("Could not load public CA key file", ERR_get_error()));
STACK_OF(X509_NAME) *cert_names;
- cert_names = SSL_load_client_CA_file(cakey.c_str());
+ cert_names = SSL_load_client_CA_file(cakey.CStr());
if (cert_names == NULL)
throw_exception(OpenSSLException("SSL_load_client_CA_file() failed", ERR_get_error()));
* @param certificate The X509 certificate.
* @returns The common name.
*/
-string Utility::GetCertificateCN(const shared_ptr<X509>& certificate)
+String Utility::GetCertificateCN(const shared_ptr<X509>& certificate)
{
char buffer[256];
* @param pemfile The filename.
* @returns An X509 certificate.
*/
-shared_ptr<X509> Utility::GetX509Certificate(string pemfile)
+shared_ptr<X509> Utility::GetX509Certificate(String pemfile)
{
X509 *cert;
BIO *fpcert = BIO_new(BIO_s_file());
if (fpcert == NULL)
throw_exception(OpenSSLException("BIO_new failed", ERR_get_error()));
- if (BIO_read_filename(fpcert, pemfile.c_str()) < 0)
+ if (BIO_read_filename(fpcert, pemfile.CStr()) < 0)
throw_exception(OpenSSLException("BIO_read_filename failed", ERR_get_error()));
cert = PEM_read_bio_X509_AUX(fpcert, NULL, NULL, NULL);
* Performs wildcard pattern matching.
*
* @param pattern The wildcard pattern.
- * @param text The string that should be checked.
+ * @param text The String that should be checked.
* @returns true if the wildcard pattern matches, false otherwise.
*/
-bool Utility::Match(string pattern, string text)
+bool Utility::Match(String pattern, String text)
{
- return (match(pattern.c_str(), text.c_str()) == 0);
+ return (match(pattern.CStr(), text.CStr()) == 0);
}
/**
* @param path The full path.
* @returns The directory.
*/
-string Utility::DirName(const string& path)
+String Utility::DirName(const String& path)
{
- char *dir = strdup(path.c_str());
- string result;
+ char *dir = strdup(path.CStr());
+ String result;
if (dir == NULL)
throw_exception(bad_alloc());
* @param path The full path.
* @returns The filename.
*/
-string Utility::BaseName(const string& path)
+String Utility::BaseName(const String& path)
{
- char *dir = strdup(path.c_str());
- string result;
+ char *dir = strdup(path.CStr());
+ String result;
if (dir == NULL)
throw_exception(bad_alloc());
class I2_BASE_API Utility
{
public:
- static string GetTypeName(const type_info& ti);
+ static String GetTypeName(const type_info& ti);
static void Daemonize(void);
- static shared_ptr<SSL_CTX> MakeSSLContext(string pubkey, string privkey, string cakey);
- static string GetCertificateCN(const shared_ptr<X509>& certificate);
- static shared_ptr<X509> GetX509Certificate(string pemfile);
+ static shared_ptr<SSL_CTX> MakeSSLContext(String pubkey, String privkey, String cakey);
+ static String GetCertificateCN(const shared_ptr<X509>& certificate);
+ static shared_ptr<X509> GetX509Certificate(String pemfile);
- static bool Match(string pattern, string text);
+ static bool Match(String pattern, String text);
- static string DirName(const string& path);
- static string BaseName(const string& path);
+ static String DirName(const String& path);
+ static String BaseName(const String& path);
static void NullDeleter(void *obj);
*
* @returns true if the variant is empty, false otherwise.
*/
-bool Variant::IsEmpty(void) const
+bool Value::IsEmpty(void) const
{
return (m_Value.type() == typeid(boost::blank));
}
-bool Variant::IsScalar(void) const
+bool Value::IsScalar(void) const
{
return !IsEmpty() && !IsObject();
}
-bool Variant::IsObject(void) const
+bool Value::IsObject(void) const
{
return !IsEmpty() && (m_Value.type() == typeid(Object::Ptr));
}
-Variant Variant::FromJson(cJSON *json)
+Value Value::FromJson(cJSON *json)
{
if (json->type == cJSON_Number)
return json->valuedouble;
else if (json->type == cJSON_String)
- return json->valuestring;
+ return String(json->valuestring);
else if (json->type == cJSON_True)
return 1;
else if (json->type == cJSON_False)
else if (json->type == cJSON_Object)
return Dictionary::FromJson(json);
else if (json->type == cJSON_NULL)
- return Variant();
+ return Value();
else
throw_exception(invalid_argument("Unsupported JSON type."));
}
-string Variant::Serialize(void) const
+String Value::Serialize(void) const
{
cJSON *json = ToJson();
char *jsonString;
- if (!Application::GetInstance()->IsDebugging())
+ if (Application::GetInstance()->IsDebugging())
jsonString = cJSON_Print(json);
else
jsonString = cJSON_PrintUnformatted(json);
cJSON_Delete(json);
- string result = jsonString;
+ String result = jsonString;
free(jsonString);
return result;
}
-cJSON *Variant::ToJson(void) const
+cJSON *Value::ToJson(void) const
{
if (m_Value.type() == typeid(long)) {
return cJSON_CreateNumber(boost::get<long>(m_Value));
} else if (m_Value.type() == typeid(double)) {
return cJSON_CreateNumber(boost::get<double>(m_Value));
- } else if (m_Value.type() == typeid(string)) {
- return cJSON_CreateString(boost::get<string>(m_Value).c_str());
+ } else if (m_Value.type() == typeid(String)) {
+ return cJSON_CreateString(boost::get<String>(m_Value).CStr());
} else if (m_Value.type() == typeid(Object::Ptr)) {
if (IsObjectType<Dictionary>()) {
Dictionary::Ptr dictionary = *this;
}
}
-Variant Variant::Deserialize(const string& jsonString)
+Value Value::Deserialize(const String& jsonString)
{
- cJSON *json = cJSON_Parse(jsonString.c_str());
+ cJSON *json = cJSON_Parse(jsonString.CStr());
if (!json)
- throw_exception(runtime_error("Invalid JSON string"));
+ throw_exception(runtime_error("Invalid JSON String"));
- Variant value = FromJson(json);
+ Value value = FromJson(json);
cJSON_Delete(json);
return value;
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
-#ifndef VARIANT_H
-#define VARIANT_H
+#ifndef VALUE_H
+#define VALUE_H
struct cJSON;
*
* @ingroup base
*/
-class I2_BASE_API Variant
+class I2_BASE_API Value
{
public:
- inline Variant(void)
+ inline Value(void)
: m_Value()
{ }
- inline Variant(int value)
- : m_Value(static_cast<long>(value))
- { }
-
- inline Variant(long value)
+ inline Value(int value)
: m_Value(value)
{ }
- inline Variant(double value)
- : m_Value(value)
+ inline Value(long value)
+ : m_Value(double(value))
{ }
- inline Variant(bool value)
- : m_Value(static_cast<long>(value))
+ inline Value(double value)
+ : m_Value(value)
{ }
- inline Variant(const string& value)
+ inline Value(const String& value)
: m_Value(value)
{ }
- inline Variant(const char *value)
- : m_Value(string(value))
+ inline Value(const char *value)
+ : m_Value(String(value))
{ }
template<typename T>
- inline Variant(const shared_ptr<T>& value)
+ inline Value(const shared_ptr<T>& value)
+ : m_Value()
{
+ if (!value)
+ return;
+
Object::Ptr object = dynamic_pointer_cast<Object>(value);
if (!object)
m_Value = object;
}
- operator long(void) const
- {
- if (m_Value.type() != typeid(long)) {
- if (m_Value.type() == typeid(double)) {
- // TODO: log this?
- return boost::get<double>(m_Value);
- } else {
- return boost::lexical_cast<long>(m_Value);
- }
- } else {
- return boost::get<long>(m_Value);
- }
- }
-
operator double(void) const
{
if (m_Value.type() != typeid(double)) {
}
}
- operator bool(void) const
+ operator String(void) const
{
- return (static_cast<long>(*this) != 0);
- }
+ if (IsEmpty())
+ return String();
- operator string(void) const
- {
- if (m_Value.type() != typeid(string)) {
- string result = boost::lexical_cast<string>(m_Value);
+ if (m_Value.type() != typeid(String)) {
+ String result = boost::lexical_cast<String>(m_Value);
m_Value = result;
- return result;
- } else {
- return boost::get<string>(m_Value);
}
+
+ return boost::get<String>(m_Value);
}
template<typename T>
return (dynamic_pointer_cast<T>(boost::get<Object::Ptr>(m_Value)));
}
- static Variant FromJson(cJSON *json);
+ static Value FromJson(cJSON *json);
cJSON *ToJson(void) const;
- string Serialize(void) const;
- static Variant Deserialize(const string& jsonString);
+ String Serialize(void) const;
+ static Value Deserialize(const String& jsonString);
private:
- mutable boost::variant<boost::blank, long, double, string, Object::Ptr> m_Value;
+ mutable boost::variant<boost::blank, double, String, Object::Ptr> m_Value;
};
}
-#endif /* VARIANT_H */
+#endif /* VALUE_H */
libcib.la
libcib_la_SOURCES = \
- checkresult.cpp \
checkresult.h \
checkresultmessage.cpp \
checkresultmessage.h \
+++ /dev/null
-/******************************************************************************
- * Icinga 2 *
- * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
- * *
- * This program is free software; you can redistribute it and/or *
- * modify it under the terms of the GNU General Public License *
- * as published by the Free Software Foundation; either version 2 *
- * of the License, or (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the Free Software Foundation *
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
- ******************************************************************************/
-
-#include "i2-cib.h"
-
-using namespace icinga;
-
-CheckResult::CheckResult(void)
- : MessagePart()
-{ }
-
-CheckResult::CheckResult(const MessagePart& message)
- : MessagePart(message)
-{ }
-
-void CheckResult::SetScheduleStart(double ts)
-{
- Set("schedule_start", ts);
-}
-
-double CheckResult::GetScheduleStart(void) const
-{
- double value = 0;
- Get("schedule_start", &value);
- return value;
-}
-
-void CheckResult::SetScheduleEnd(double ts)
-{
- Set("schedule_end", ts);
-}
-
-double CheckResult::GetScheduleEnd(void) const
-{
- double value = 0;
- Get("schedule_end", &value);
- return value;
-}
-
-void CheckResult::SetExecutionStart(double ts)
-{
- Set("execution_start", ts);
-}
-
-double CheckResult::GetExecutionStart(void) const
-{
- double value = 0;
- Get("execution_start", &value);
- return value;
-}
-
-void CheckResult::SetExecutionEnd(double ts)
-{
- Set("execution_end", ts);
-}
-
-double CheckResult::GetExecutionEnd(void) const
-{
- double value = 0;
- Get("execution_end", &value);
- return value;
-}
-
-void CheckResult::SetState(ServiceState state)
-{
- Set("state", static_cast<long>(state));
-}
-
-ServiceState CheckResult::GetState(void) const
-{
- long value = StateUnknown;
- Get("state", &value);
- return static_cast<ServiceState>(value);
-}
-
-void CheckResult::SetOutput(string output)
-{
- Set("output", output);
-}
-
-string CheckResult::GetOutput(void) const
-{
- string value;
- Get("output", &value);
- return value;
-}
-
-void CheckResult::SetPerformanceDataRaw(const string& pd)
-{
- Set("performance_data_raw", pd);
-}
-
-string CheckResult::GetPerformanceDataRaw(void) const
-{
- string value;
- Get("performance_data_raw", &value);
- return value;
-}
-
-void CheckResult::SetPerformanceData(const Dictionary::Ptr& pd)
-{
- Set("performance_data", pd);
-}
-
-Dictionary::Ptr CheckResult::GetPerformanceData(void) const
-{
- Dictionary::Ptr value;
- Get("performance_data", &value);
- return value;
-}
namespace icinga
{
-class I2_CIB_API CheckResult : public MessagePart
+/*struct CheckResult
{
-public:
- CheckResult(void);
- CheckResult(const MessagePart& message);
-
- void SetScheduleStart(double ts);
- double GetScheduleStart(void) const;
-
- void SetScheduleEnd(double ts);
- double GetScheduleEnd(void) const;
-
- void SetExecutionStart(double ts);
- double GetExecutionStart(void) const;
-
- void SetExecutionEnd(double ts);
- double GetExecutionEnd(void) const;
-
- void SetState(ServiceState state);
- ServiceState GetState(void) const;
-
- void SetOutput(string output);
- string GetOutput(void) const;
-
- void SetPerformanceDataRaw(const string& pd);
- string GetPerformanceDataRaw(void) const;
-
- void SetPerformanceData(const Dictionary::Ptr& pd);
- Dictionary::Ptr GetPerformanceData(void) const;
-};
+ static const char *ScheduleStart = "schedule_start";
+ static const char *ScheduleEnd = "schedule_end";
+ static const char *ExecutionStart = "execution_start";
+ static const char *ExecutionEnd = "execution_end";
+ static const char *State = "state";
+ static const char *Output = "output";
+ static const char *PerformanceDataRaw = "performance_data_raw";
+ static const char *PerformanceData = "performance_data";
+
+private:
+ CheckResult();
+};*/
}
using namespace icinga;
-bool CheckResultMessage::GetService(string *service) const
+bool CheckResultMessage::GetService(String *service) const
{
return Get("service", service);
}
-void CheckResultMessage::SetService(const string& service)
+void CheckResultMessage::SetService(const String& service)
{
Set("service", service);
}
-bool CheckResultMessage::GetCheckResult(CheckResult *cr) const
-{
- Dictionary::Ptr obj;
- if (Get("result", &obj)) {
- *cr = CheckResult(MessagePart(obj));
- return true;
- }
- return false;
-}
-
-void CheckResultMessage::SetCheckResult(CheckResult cr)
-{
- Set("result", cr.GetDictionary());
-}
CheckResultMessage(void) : MessagePart() { }
CheckResultMessage(const MessagePart& message) : MessagePart(message) { }
- bool GetService(string *service) const;
- void SetService(const string& service);
-
- bool GetCheckResult(CheckResult *cr) const;
- void SetCheckResult(CheckResult cr);
+ bool GetService(String *service) const;
+ void SetService(const String& service);
};
}
</Link>
</ItemDefinitionGroup>
<ItemGroup>
- <ClInclude Include="checkresult.h" />
<ClInclude Include="cib.h" />
<ClInclude Include="host.h" />
<ClInclude Include="hostgroup.h" />
<ClInclude Include="checkresultmessage.h" />
</ItemGroup>
<ItemGroup>
- <ClCompile Include="checkresult.cpp" />
<ClCompile Include="cib.cpp" />
<ClCompile Include="host.cpp" />
<ClCompile Include="hostgroup.cpp" />
</Filter>
</ItemGroup>
<ItemGroup>
- <ClInclude Include="checkresult.h">
- <Filter>Headerdateien</Filter>
- </ClInclude>
<ClInclude Include="cib.h">
<Filter>Headerdateien</Filter>
</ClInclude>
</ClInclude>
</ItemGroup>
<ItemGroup>
- <ClCompile Include="checkresult.cpp">
- <Filter>Quelldateien</Filter>
- </ClCompile>
<ClCompile Include="cib.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
REGISTER_CLASS(Host);
-string Host::GetAlias(void) const
+Host::Host(const Dictionary::Ptr& properties)
+ : DynamicObject(properties)
{
- string value;
+ RegisterAttribute("alias", Attribute_Config);
+ RegisterAttribute("hostgroups", Attribute_Config);
+}
- if (GetProperty("alias", &value))
+String Host::GetAlias(void) const
+{
+ String value;
+ if (GetAttribute("alias", &value))
return value;
-
- return GetName();
+ else
+ return GetName();
}
-bool Host::Exists(const string& name)
+bool Host::Exists(const String& name)
{
return (DynamicObject::GetObject("Host", name));
}
-Host::Ptr Host::GetByName(const string& name)
+Host::Ptr Host::GetByName(const String& name)
{
DynamicObject::Ptr configObject = DynamicObject::GetObject("Host", name);
Dictionary::Ptr Host::GetGroups(void) const
{
Dictionary::Ptr value;
- GetProperty("hostgroups", &value);
+ GetAttribute("hostgroups", &value);
return value;
}
-set<string> Host::GetParents(void)
+set<String> Host::GetParents(void)
{
- set<string> parents;
+ set<String> parents;
Dictionary::Ptr dependencies;
-
- if (GetProperty("dependencies", &dependencies)) {
+ GetAttribute("dependencies", &dependencies);
+ if (dependencies) {
dependencies = Service::ResolveDependencies(GetSelf(), dependencies);
- Variant dependency;
+ Value dependency;
BOOST_FOREACH(tie(tuples::ignore, dependency), dependencies) {
Service::Ptr service = Service::GetByName(dependency);
- string parent = service->GetHost()->GetName();
+ String parent = service->GetHost()->GetName();
/* ignore ourselves */
if (parent == GetName())
Dictionary::Ptr Host::GetMacros(void) const
{
Dictionary::Ptr value;
- GetProperty("macros", &value);
+ GetAttribute("macros", &value);
return value;
}
bool Host::IsReachable(void)
{
Dictionary::Ptr dependencies;
- if (GetProperty("dependencies", &dependencies)) {
+ GetAttribute("dependencies", &dependencies);
+ if (dependencies) {
dependencies = Service::ResolveDependencies(GetSelf(), dependencies);
- Variant dependency;
+ Value dependency;
BOOST_FOREACH(tie(tuples::ignore, dependency), dependencies) {
Service::Ptr service = Service::GetByName(dependency);
bool Host::IsUp(void)
{
Dictionary::Ptr hostchecks;
- if (GetProperty("hostchecks", &hostchecks)) {
+ GetAttribute("hostchecks", &hostchecks);
+ if (hostchecks) {
hostchecks = Service::ResolveDependencies(GetSelf(), hostchecks);
- Variant hostcheck;
+ Value hostcheck;
BOOST_FOREACH(tie(tuples::ignore, hostcheck), hostchecks) {
Service::Ptr service = Service::GetByName(hostcheck);
typedef shared_ptr<Host> Ptr;
typedef weak_ptr<Host> WeakPtr;
- Host(const Dictionary::Ptr& properties)
- : DynamicObject(properties)
- { }
+ Host(const Dictionary::Ptr& properties);
- static bool Exists(const string& name);
- static Host::Ptr GetByName(const string& name);
+ static bool Exists(const String& name);
+ static Host::Ptr GetByName(const String& name);
- string GetAlias(void) const;
+ String GetAlias(void) const;
Dictionary::Ptr GetGroups(void) const;
- set<string> GetParents(void);
+ set<String> GetParents(void);
Dictionary::Ptr GetMacros(void) const;
bool IsReachable(void);
REGISTER_CLASS(HostGroup);
-string HostGroup::GetAlias(void) const
+String HostGroup::GetAlias(void) const
{
- string value;
+ String value;
+ GetAttribute("alias", &value);
- if (GetProperty("alias", &value))
+ if (!value.IsEmpty())
return value;
-
- return GetName();
+ else
+ return GetName();
}
-string HostGroup::GetNotesUrl(void) const
+String HostGroup::GetNotesUrl(void) const
{
- string value;
- GetProperty("notes_url", &value);
+ String value;
+ GetAttribute("notes_url", &value);
return value;
}
-string HostGroup::GetActionUrl(void) const
+String HostGroup::GetActionUrl(void) const
{
- string value;
- GetProperty("action_url", &value);
+ String value;
+ GetAttribute("action_url", &value);
return value;
}
-bool HostGroup::Exists(const string& name)
+bool HostGroup::Exists(const String& name)
{
return (DynamicObject::GetObject("HostGroup", name));
}
-HostGroup::Ptr HostGroup::GetByName(const string& name)
+HostGroup::Ptr HostGroup::GetByName(const String& name)
{
DynamicObject::Ptr configObject = DynamicObject::GetObject("HostGroup", name);
: DynamicObject(properties)
{ }
- static bool Exists(const string& name);
- static HostGroup::Ptr GetByName(const string& name);
+ static bool Exists(const String& name);
+ static HostGroup::Ptr GetByName(const String& name);
- string GetAlias(void) const;
- string GetNotesUrl(void) const;
- string GetActionUrl(void) const;
+ String GetAlias(void) const;
+ String GetNotesUrl(void) const;
+ String GetActionUrl(void) const;
};
}
using namespace icinga;
-string MacroProcessor::ResolveMacros(const string& str, const vector<Dictionary::Ptr>& macroDicts)
+String MacroProcessor::ResolveMacros(const String& str, const vector<Dictionary::Ptr>& macroDicts)
{
- string::size_type offset, pos_first, pos_second;
+ size_t offset, pos_first, pos_second;
offset = 0;
- string result = str;
- while ((pos_first = result.find_first_of('$', offset)) != string::npos) {
- pos_second = result.find_first_of('$', pos_first + 1);
+ String result = str;
+ while ((pos_first = result.FindFirstOf("$", offset)) != String::NPos) {
+ pos_second = result.FindFirstOf("$", pos_first + 1);
- if (pos_second == string::npos)
- throw_exception(runtime_error("Closing $ not found in macro format string."));
+ if (pos_second == String::NPos)
+ throw_exception(runtime_error("Closing $ not found in macro format String."));
- string name = result.substr(pos_first + 1, pos_second - pos_first - 1);
- string value;
+ String name = result.SubStr(pos_first + 1, pos_second - pos_first - 1);
+ String value;
bool resolved = false;
BOOST_FOREACH(const Dictionary::Ptr& macroDict, macroDicts) {
- if (macroDict && macroDict->Get(name, &value)) {
- resolved = true;
- break;
- }
+ if (!macroDict || !macroDict->Contains(name))
+ continue;
+
+ String value = macroDict->Get(name);
+ result.Replace(pos_first, pos_second - pos_first + 1, value);
+ offset = pos_first + value.GetLength();
+
+ resolved = true;
+ break;
}
if (!resolved)
throw_exception(runtime_error("Macro '" + name + "' is not defined."));
-
- result.replace(pos_first, pos_second - pos_first + 1, value);
-
- offset = pos_first + value.size();
}
return result;
class I2_CIB_API MacroProcessor
{
public:
- static string ResolveMacros(const string& str, const vector<Dictionary::Ptr>& macroDicts);
+ static String ResolveMacros(const String& str, const vector<Dictionary::Ptr>& macroDicts);
};
}
: m_Task(task), m_Process(process)
{ }
-void NagiosCheckTask::ScriptFunc(const ScriptTask::Ptr& task, const vector<Variant>& arguments)
+void NagiosCheckTask::ScriptFunc(const ScriptTask::Ptr& task, const vector<Value>& arguments)
{
if (arguments.size() < 1)
throw_exception(invalid_argument("Missing argument: Service must be specified."));
- Variant vservice = arguments[0];
+ Value vservice = arguments[0];
if (!vservice.IsObjectType<DynamicObject>())
throw_exception(invalid_argument("Argument must be a config object."));
Service::Ptr service = static_cast<Service::Ptr>(vservice);
- string checkCommand = service->GetCheckCommand();
+ String checkCommand = service->GetCheckCommand();
vector<Dictionary::Ptr> macroDicts;
macroDicts.push_back(service->GetMacros());
macroDicts.push_back(service->GetHost()->GetMacros());
macroDicts.push_back(IcingaApplication::GetInstance()->GetMacros());
- string command = MacroProcessor::ResolveMacros(checkCommand, macroDicts);
+ String command = MacroProcessor::ResolveMacros(checkCommand, macroDicts);
Process::Ptr process = boost::make_shared<Process>(command);
NagiosCheckTask ct(task, process);
- ct.m_Result.SetScheduleStart(Utility::GetTime());
+ ct.m_Result = boost::make_shared<Dictionary>();
+ ct.m_Result->Set("schedule_start", Utility::GetTime());
process->Start(boost::bind(&NagiosCheckTask::ProcessFinishedHandler, ct));
}
return;
}
- ct.m_Result.SetExecutionStart(pr.ExecutionStart);
- ct.m_Result.SetExecutionEnd(pr.ExecutionEnd);
+ ct.m_Result->Set("execution_start", pr.ExecutionStart);
+ ct.m_Result->Set("execution_end", pr.ExecutionEnd);
- string output = pr.Output;
- boost::algorithm::trim(output);
+ String output = pr.Output;
+ output.Trim();
ProcessCheckOutput(ct.m_Result, output);
ServiceState state;
break;
}
- ct.m_Result.SetState(state);
+ ct.m_Result->Set("state", state);
- ct.m_Result.SetScheduleEnd(Utility::GetTime());
+ ct.m_Result->Set("schedule_end", Utility::GetTime());
- ct.m_Task->FinishResult(ct.m_Result.GetDictionary());
+ ct.m_Task->FinishResult(ct.m_Result);
}
-void NagiosCheckTask::ProcessCheckOutput(CheckResult& result, const string& output)
+void NagiosCheckTask::ProcessCheckOutput(const Dictionary::Ptr& result, String& output)
{
- string text;
- string perfdata;
+ String text;
+ String perfdata;
- vector<string> lines;
- boost::algorithm::split(lines, output, is_any_of("\r\n"));
+ vector<String> lines = output.Split(is_any_of("\r\n"));
- BOOST_FOREACH (const string& line, lines) {
- string::size_type delim = line.find('|');
+ BOOST_FOREACH (const String& line, lines) {
+ size_t delim = line.FindFirstOf("|");
- if (!text.empty())
- text.append("\n");
+ if (!text.IsEmpty())
+ text += "\n";
- if (delim != string::npos) {
- text.append(line, 0, delim);
+ if (delim != String::NPos) {
+ text += line.SubStr(0, delim);
- if (!perfdata.empty())
- perfdata.append(" ");
+ if (!perfdata.IsEmpty())
+ perfdata += " ";
- perfdata.append(line, delim + 1, line.size());
+ perfdata += line.SubStr(delim + 1, line.GetLength());
} else {
- text.append(line);
+ text += line;
}
}
- result.SetOutput(text);
- result.SetPerformanceDataRaw(perfdata);
+ result->Set("output", text);
+ result->Set("performance_data_raw", perfdata);
}
void NagiosCheckTask::Register(void)
static void Register(void);
private:
- static void ScriptFunc(const ScriptTask::Ptr& task, const vector<Variant>& arguments);
+ static void ScriptFunc(const ScriptTask::Ptr& task, const vector<Value>& arguments);
static void ProcessFinishedHandler(NagiosCheckTask ct);
- static void ProcessCheckOutput(CheckResult& result, const string& output);
+ static void ProcessCheckOutput(const Dictionary::Ptr& result, String& output);
NagiosCheckTask(const ScriptTask::Ptr& task, const Process::Ptr& process);
ScriptTask::Ptr m_Task;
Process::Ptr m_Process;
- CheckResult m_Result;
+ Dictionary::Ptr m_Result;
};
}
using namespace icinga;
-void NullCheckTask::ScriptFunc(const ScriptTask::Ptr& task, const vector<Variant>& arguments)
+void NullCheckTask::ScriptFunc(const ScriptTask::Ptr& task, const vector<Value>& arguments)
{
if (arguments.size() < 1)
throw_exception(invalid_argument("Missing argument: Service must be specified."));
double now = Utility::GetTime();
- CheckResult cr;
- cr.SetScheduleStart(now);
- cr.SetScheduleEnd(now);
- cr.SetExecutionStart(now);
- cr.SetExecutionEnd(now);
- cr.SetState(StateUnknown);
+ Dictionary::Ptr cr = boost::make_shared<Dictionary>();
+ cr->Set("schedule_start", now);
+ cr->Set("schedule_end", now);
+ cr->Set("execution_start", now);
+ cr->Set("execution_end", now);
+ cr->Set("state", StateUnknown);
- task->FinishResult(cr.GetDictionary());
+ task->FinishResult(cr);
}
void NullCheckTask::Register(void)
static void Register(void);
private:
- static void ScriptFunc(const ScriptTask::Ptr& task, const vector<Variant>& arguments);
+ static void ScriptFunc(const ScriptTask::Ptr& task, const vector<Value>& arguments);
};
}
boost::signal<void (const Service::Ptr&, const CheckResultMessage&)> Service::OnCheckResultReceived;
-string Service::GetAlias(void) const
-{
- string value;
-
- if (GetProperty("alias", &value))
+Service::Service(const Dictionary::Ptr& serializedObject)
+ : DynamicObject(serializedObject)
+{
+ RegisterAttribute("alias", Attribute_Config);
+ RegisterAttribute("host_name", Attribute_Config);
+ RegisterAttribute("macros", Attribute_Config);
+ RegisterAttribute("check_command", Attribute_Config);
+ RegisterAttribute("max_check_attempts", Attribute_Config);
+ RegisterAttribute("check_interval", Attribute_Config);
+ RegisterAttribute("retry_interval", Attribute_Config);
+ RegisterAttribute("dependencies", Attribute_Config);
+ RegisterAttribute("servicegroups", Attribute_Config);
+ RegisterAttribute("checkers", Attribute_Config);
+
+ RegisterAttribute("scheduling_offset", Attribute_Transient);
+ RegisterAttribute("next_check", Attribute_Replicated);
+ RegisterAttribute("checker", Attribute_Replicated);
+ RegisterAttribute("check_attempt", Attribute_Replicated);
+ RegisterAttribute("state", Attribute_Replicated);
+ RegisterAttribute("state_type", Attribute_Replicated);
+ RegisterAttribute("last_result", Attribute_Replicated);
+ RegisterAttribute("last_state_change", Attribute_Replicated);
+ RegisterAttribute("last_hard_state_change", Attribute_Replicated);
+}
+
+String Service::GetAlias(void) const
+{
+ String value;
+
+ if (GetAttribute("alias", &value))
return value;
return GetName();
}
-bool Service::Exists(const string& name)
+bool Service::Exists(const String& name)
{
return (DynamicObject::GetObject("Service", name));
}
-Service::Ptr Service::GetByName(const string& name)
+Service::Ptr Service::GetByName(const String& name)
{
DynamicObject::Ptr configObject = DynamicObject::GetObject("Service", name);
Host::Ptr Service::GetHost(void) const
{
- string hostname;
- if (!GetProperty("host_name", &hostname))
+ String hostname;
+ if (!GetAttribute("host_name", &hostname))
throw_exception(runtime_error("Service object is missing the 'host_name' property."));
return Host::GetByName(hostname);
Dictionary::Ptr Service::GetMacros(void) const
{
Dictionary::Ptr macros;
- GetProperty("macros", ¯os);
+ GetAttribute("macros", ¯os);
return macros;
}
-string Service::GetCheckCommand(void) const
+String Service::GetCheckCommand(void) const
{
- string value;
- GetProperty("check_command", &value);
+ String value;
+ GetAttribute("check_command", &value);
return value;
}
long Service::GetMaxCheckAttempts(void) const
{
long value = 3;
- GetProperty("max_check_attempts", &value);
+ GetAttribute("max_check_attempts", &value);
return value;
}
long Service::GetCheckInterval(void) const
{
long value = 300;
- GetProperty("check_interval", &value);
+ GetAttribute("check_interval", &value);
if (value < 15)
value = 15;
long Service::GetRetryInterval(void) const
{
long value;
- if (!GetProperty("retry_interval", &value))
+ if (!GetAttribute("retry_interval", &value))
value = GetCheckInterval() / 5;
return value;
Dictionary::Ptr Service::GetDependencies(void) const
{
Dictionary::Ptr value;
- GetProperty("dependencies", &value);
+ GetAttribute("dependencies", &value);
return value;
}
if (!dependencies)
return;
- Variant dependency;
+ Value dependency;
BOOST_FOREACH(tie(tuples::ignore, dependency), dependencies) {
if (result->Contains(dependency))
continue;
Dictionary::Ptr Service::GetGroups(void) const
{
Dictionary::Ptr value;
- GetProperty("servicegroups", &value);
+ GetAttribute("servicegroups", &value);
return value;
}
Dictionary::Ptr Service::GetCheckers(void) const
{
Dictionary::Ptr value;
- GetProperty("checkers", &value);
+ GetAttribute("checkers", &value);
return value;
}
Dictionary::Ptr dependencies = boost::make_shared<Dictionary>();
GetDependenciesRecursive(dependencies);
- Variant dependency;
+ Value dependency;
BOOST_FOREACH(tie(tuples::ignore, dependency), dependencies) {
Service::Ptr service = Service::GetByName(dependency);
continue;
/* ignore pending services */
- if (!service->HasLastCheckResult())
+ if (!service->GetLastCheckResult())
continue;
/* ignore soft states */
void Service::SetSchedulingOffset(long offset)
{
- SetTag("scheduling_offset", offset);
+ SetAttribute("scheduling_offset", offset);
}
long Service::GetSchedulingOffset(void)
{
long value;
- if (!GetTag("scheduling_offset", &value)) {
+ if (!GetAttribute("scheduling_offset", &value)) {
value = rand();
SetSchedulingOffset(value);
}
void Service::SetNextCheck(double nextCheck)
{
- SetTag("next_check", nextCheck);
+ SetAttribute("next_check", nextCheck);
}
double Service::GetNextCheck(void)
{
double value;
- if (!GetTag("next_check", &value)) {
+ if (!GetAttribute("next_check", &value)) {
UpdateNextCheck();
- return GetNextCheck();
+
+ if (!GetAttribute("next_check", &value))
+ throw_exception(runtime_error("Failed to schedule next check."));
}
return value;
}
SetNextCheck(now - adj + interval);
}
-void Service::SetChecker(const string& checker)
+void Service::SetChecker(const String& checker)
{
- SetTag("checker", checker);
+ SetAttribute("checker", checker);
}
-string Service::GetChecker(void) const
+String Service::GetChecker(void) const
{
- string value;
- GetTag("checker", &value);
+ String value;
+ GetAttribute("checker", &value);
return value;
}
void Service::SetCurrentCheckAttempt(long attempt)
{
- SetTag("check_attempt", attempt);
+ SetAttribute("check_attempt", attempt);
}
long Service::GetCurrentCheckAttempt(void) const
{
long value = 1;
- GetTag("check_attempt", &value);
+ GetAttribute("check_attempt", &value);
return value;
}
void Service::SetState(ServiceState state)
{
- SetTag("state", static_cast<long>(state));
+ SetAttribute("state", static_cast<long>(state));
}
ServiceState Service::GetState(void) const
{
long value = StateUnknown;
- GetTag("state", &value);
+ GetAttribute("state", &value);
return static_cast<ServiceState>(value);
}
void Service::SetStateType(ServiceStateType type)
{
- SetTag("state_type", static_cast<long>(type));
+ SetAttribute("state_type", static_cast<long>(type));
}
ServiceStateType Service::GetStateType(void) const
{
long value = StateTypeHard;
- GetTag("state_type", &value);
+ GetAttribute("state_type", &value);
return static_cast<ServiceStateType>(value);
}
-void Service::SetLastCheckResult(const CheckResult& result)
-{
- SetTag("last_result", result.GetDictionary());
-}
-
-bool Service::HasLastCheckResult(void) const
+void Service::SetLastCheckResult(const Dictionary::Ptr& result)
{
- Dictionary::Ptr value;
- return GetTag("last_result", &value) && value;
+ SetAttribute("last_result", result);
}
-CheckResult Service::GetLastCheckResult(void) const
+Dictionary::Ptr Service::GetLastCheckResult(void) const
{
Dictionary::Ptr value;
- if (!GetTag("last_result", &value))
- throw_exception(invalid_argument("Service has no last check result."));
- return CheckResult(value);
+ GetAttribute("last_result", &value);
+ return value;
}
void Service::SetLastStateChange(double ts)
{
- SetTag("last_state_change", static_cast<long>(ts));
+ SetAttribute("last_state_change", static_cast<long>(ts));
}
double Service::GetLastStateChange(void) const
{
long value;
- if (!GetTag("last_state_change", &value))
+ if (!GetAttribute("last_state_change", &value))
value = IcingaApplication::GetInstance()->GetStartTime();
return value;
}
void Service::SetLastHardStateChange(double ts)
{
- SetTag("last_hard_state_change", ts);
+ SetAttribute("last_hard_state_change", ts);
}
double Service::GetLastHardStateChange(void) const
{
double value;
- if (!GetTag("last_hard_state_change", &value))
+ if (!GetAttribute("last_hard_state_change", &value))
value = IcingaApplication::GetInstance()->GetStartTime();
return value;
}
-void Service::ApplyCheckResult(const CheckResult& cr)
+void Service::ApplyCheckResult(const Dictionary::Ptr& cr)
{
ServiceState old_state = GetState();
ServiceStateType old_stateType = GetStateType();
long attempt = GetCurrentCheckAttempt();
- if (cr.GetState() == StateOK) {
+ if (cr->Get("state") == StateOK) {
if (GetState() == StateOK)
SetStateType(StateTypeHard);
}
SetCurrentCheckAttempt(attempt);
- SetState(cr.GetState());
+
+ int state = cr->Get("state");
+ SetState(static_cast<ServiceState>(state));
SetLastCheckResult(cr);
if (old_stateType != GetStateType())
SetLastHardStateChange(now);
}
-
- UpdateNextCheck();
}
-ServiceState Service::StateFromString(const string& state)
+ServiceState Service::StateFromString(const String& state)
{
/* TODO: make this thread-safe */
- static map<string, ServiceState> stateLookup;
+ static map<String, ServiceState> stateLookup;
if (stateLookup.empty()) {
stateLookup["ok"] = StateOK;
stateLookup["unknown"] = StateUnknown;
}
- map<string, ServiceState>::iterator it;
+ map<String, ServiceState>::iterator it;
it = stateLookup.find(state);
if (it == stateLookup.end())
return it->second;
}
-string Service::StateToString(ServiceState state)
+String Service::StateToString(ServiceState state)
{
switch (state) {
case StateOK:
}
}
-ServiceStateType Service::StateTypeFromString(const string& type)
+ServiceStateType Service::StateTypeFromString(const String& type)
{
if (type == "soft")
return StateTypeSoft;
return StateTypeHard;
}
-string Service::StateTypeToString(ServiceStateType type)
+String Service::StateTypeToString(ServiceStateType type)
{
if (type == StateTypeSoft)
return "soft";
return "hard";
}
-bool Service::IsAllowedChecker(const string& checker) const
+bool Service::IsAllowedChecker(const String& checker) const
{
Dictionary::Ptr checkers = GetCheckers();
if (!checkers)
return true;
- Variant pattern;
+ Value pattern;
BOOST_FOREACH(tie(tuples::ignore, pattern), checkers) {
if (Utility::Match(pattern, checker))
return true;
Dictionary::Ptr Service::ResolveDependencies(const Host::Ptr& host, const Dictionary::Ptr& dependencies)
{
Dictionary::Ptr services;
- host->GetProperty("services", &services);
+ host->GetAttribute("services", &services);
Dictionary::Ptr result = boost::make_shared<Dictionary>();
- Variant dependency;
+ Value dependency;
BOOST_FOREACH(tie(tuples::ignore, dependency), dependencies) {
- string name;
+ String name;
if (services && services->Contains(dependency))
- name = host->GetName() + "-" + static_cast<string>(dependency);
+ name = host->GetName() + "-" + static_cast<String>(dependency);
else
- name = static_cast<string>(dependency);
+ name = static_cast<String>(dependency);
result->Set(name, name);
}
StateTypeHard
};
-class CheckResult;
class CheckResultMessage;
class ServiceStatusMessage;
typedef shared_ptr<Service> Ptr;
typedef weak_ptr<Service> WeakPtr;
- Service(const Dictionary::Ptr& properties)
- : DynamicObject(properties)
- { }
+ Service(const Dictionary::Ptr& properties);
- static bool Exists(const string& name);
- static Service::Ptr GetByName(const string& name);
+ static bool Exists(const String& name);
+ static Service::Ptr GetByName(const String& name);
- string GetAlias(void) const;
+ String GetAlias(void) const;
Host::Ptr GetHost(void) const;
Dictionary::Ptr GetMacros(void) const;
- string GetCheckCommand(void) const;
+ String GetCheckCommand(void) const;
long GetMaxCheckAttempts(void) const;
long GetCheckInterval(void) const;
long GetRetryInterval(void) const;
double GetNextCheck(void);
void UpdateNextCheck(void);
- void SetChecker(const string& checker);
- string GetChecker(void) const;
+ void SetChecker(const String& checker);
+ String GetChecker(void) const;
- bool IsAllowedChecker(const string& checker) const;
+ bool IsAllowedChecker(const String& checker) const;
void SetCurrentCheckAttempt(long attempt);
long GetCurrentCheckAttempt(void) const;
void SetStateType(ServiceStateType type);
ServiceStateType GetStateType(void) const;
- bool HasLastCheckResult(void) const;
- void SetLastCheckResult(const CheckResult& result);
- CheckResult GetLastCheckResult(void) const;
+ void SetLastCheckResult(const Dictionary::Ptr& result);
+ Dictionary::Ptr GetLastCheckResult(void) const;
void SetLastStateChange(double ts);
double GetLastStateChange(void) const;
void SetLastHardStateChange(double ts);
double GetLastHardStateChange(void) const;
- void ApplyCheckResult(const CheckResult& cr);
+ void ApplyCheckResult(const Dictionary::Ptr& cr);
- static ServiceState StateFromString(const string& state);
- static string StateToString(ServiceState state);
+ static ServiceState StateFromString(const String& state);
+ static String StateToString(ServiceState state);
- static ServiceStateType StateTypeFromString(const string& state);
- static string StateTypeToString(ServiceStateType state);
+ static ServiceStateType StateTypeFromString(const String& state);
+ static String StateTypeToString(ServiceStateType state);
static Dictionary::Ptr ResolveDependencies(const Host::Ptr& host, const Dictionary::Ptr& dependencies);
REGISTER_CLASS(ServiceGroup);
-string ServiceGroup::GetAlias(void) const
+String ServiceGroup::GetAlias(void) const
{
- string value;
+ String value;
+ GetAttribute("alias", &value);
- if (GetProperty("alias", &value))
+ if (!value.IsEmpty())
return value;
-
- return GetName();
+ else
+ return GetName();
}
-string ServiceGroup::GetNotesUrl(void) const
+String ServiceGroup::GetNotesUrl(void) const
{
- string value;
- GetProperty("notes_url", &value);
+ String value;
+ GetAttribute("notes_url", &value);
return value;
}
-string ServiceGroup::GetActionUrl(void) const
+String ServiceGroup::GetActionUrl(void) const
{
- string value;
- GetProperty("action_url", &value);
+ String value;
+ GetAttribute("action_url", &value);
return value;
}
-bool ServiceGroup::Exists(const string& name)
+bool ServiceGroup::Exists(const String& name)
{
return (DynamicObject::GetObject("ServiceGroup", name));
}
-ServiceGroup::Ptr ServiceGroup::GetByName(const string& name)
+ServiceGroup::Ptr ServiceGroup::GetByName(const String& name)
{
DynamicObject::Ptr configObject = DynamicObject::GetObject("ServiceGroup", name);
: DynamicObject(properties)
{ }
- static bool Exists(const string& name);
- static ServiceGroup::Ptr GetByName(const string& name);
+ static bool Exists(const String& name);
+ static ServiceGroup::Ptr GetByName(const String& name);
- string GetAlias(void) const;
- string GetNotesUrl(void) const;
- string GetActionUrl(void) const;
+ String GetAlias(void) const;
+ String GetNotesUrl(void) const;
+ String GetActionUrl(void) const;
};
}
m_PendingServices.insert(service);
- vector<Variant> arguments;
+ vector<Value> arguments;
arguments.push_back(service);
ScriptTask::Ptr task;
task = service->InvokeMethod("check", arguments, boost::bind(&CheckerComponent::CheckCompletedHandler, this, service, _1));
assert(task); /* TODO: gracefully handle missing methods */
- service->SetTag("current_task", task);
+ service->SetAttribute("current_task", task);
tasks++;
}
void CheckerComponent::CheckCompletedHandler(const Service::Ptr& service, const ScriptTask::Ptr& task)
{
- service->RemoveTag("current_task");
+ service->ClearAttribute("current_task");
try {
- Variant vresult = task->GetResult();
+ Value vresult = task->GetResult();
if (vresult.IsObjectType<Dictionary>()) {
- CheckResult result = CheckResult(static_cast<Dictionary::Ptr>(vresult));
+ Dictionary::Ptr result = vresult;
+
+ service->ApplyCheckResult(result);
RequestMessage rm;
- rm.SetMethod("checker::CheckResult");
+ rm.SetMethod("checker::ServiceStateChange");
+ /* TODO: add _old_ state to message */
CheckResultMessage params;
params.SetService(service->GetName());
- params.SetCheckResult(result);
rm.SetParams(params);
Logger::Write(LogWarning, "checker", msgbuf.str());
}
- /* figure out when the next check is for this service; the local
- * cibsync component should've already done this as part of processing
- * the CheckResult message, but lets do it again to be sure */
+ /* figure out when the next check is for this service; the call to
+ * ApplyCheckResult() should've already done this but lets do it again
+ * just in case there was no check result. */
service->UpdateNextCheck();
+ assert(service->GetNextCheck() > Utility::GetTime());
+
/* remove the service from the list of pending services; if it's not in the
* list this was a manual (i.e. forced) check and we must not re-add the
* service to the services list because it's already there. */
if (!request.GetParams(¶ms))
return;
- string service;
+ String service;
if (!params.Get("service", &service))
return;
m_Endpoint->RegisterTopicHandler("config::FetchObjects",
boost::bind(&CIBSyncComponent::FetchObjectsHandler, this, _2));
- DynamicObject::OnCommitted.connect(boost::bind(&CIBSyncComponent::LocalObjectCommittedHandler, this, _1));
- DynamicObject::OnRemoved.connect(boost::bind(&CIBSyncComponent::LocalObjectRemovedHandler, this, _1));
+ DynamicObject::OnRegistered.connect(boost::bind(&CIBSyncComponent::LocalObjectRegisteredHandler, this, _1));
+ DynamicObject::OnUnregistered.connect(boost::bind(&CIBSyncComponent::LocalObjectUnregisteredHandler, this, _1));
+ DynamicObject::OnTransactionClosing.connect(boost::bind(&CIBSyncComponent::TransactionClosingHandler, this, _1));
- m_Endpoint->RegisterPublication("config::ObjectCommitted");
+ m_Endpoint->RegisterPublication("config::ObjectUpdate");
m_Endpoint->RegisterPublication("config::ObjectRemoved");
EndpointManager::GetInstance()->OnNewEndpoint.connect(boost::bind(&CIBSyncComponent::NewEndpointHandler, this, _2));
m_Endpoint->RegisterPublication("config::FetchObjects");
- m_Endpoint->RegisterTopicHandler("config::ObjectCommitted",
- boost::bind(&CIBSyncComponent::RemoteObjectCommittedHandler, this, _2, _3));
+ m_Endpoint->RegisterTopicHandler("config::ObjectUpdate",
+ boost::bind(&CIBSyncComponent::RemoteObjectUpdateHandler, this, _2, _3));
m_Endpoint->RegisterTopicHandler("config::ObjectRemoved",
boost::bind(&CIBSyncComponent::RemoteObjectRemovedHandler, this, _3));
if (!request.GetParams(¶ms))
return;
- string svcname;
+ String svcname;
if (!params.GetService(&svcname))
return;
Service::Ptr service = Service::GetByName(svcname);
- CheckResult cr;
- if (!params.GetCheckResult(&cr))
- return;
+ //CheckResult cr;
+ //if (!params.GetCheckResult(&cr))
+ // return;
- Service::OnCheckResultReceived(service, params);
- service->ApplyCheckResult(cr);
+ //Service::OnCheckResultReceived(service, params);
+ //service->ApplyCheckResult(cr);
time_t now = Utility::GetTime();
CIB::UpdateTaskStatistics(now, 1);
EndpointManager::GetInstance()->SendUnicastMessage(m_Endpoint, endpoint, request);
}
-RequestMessage CIBSyncComponent::MakeObjectMessage(const DynamicObject::Ptr& object, string method, bool includeProperties)
+RequestMessage CIBSyncComponent::MakeObjectMessage(const DynamicObject::Ptr& object, const String& method, double sinceTx, bool includeProperties)
{
RequestMessage msg;
msg.SetMethod(method);
params.Set("type", object->GetType());
if (includeProperties)
- params.Set("properties", object->GetProperties());
+ params.Set("update", object->BuildUpdate(sinceTx, Attribute_Replicated | Attribute_Config));
return msg;
}
if (!ShouldReplicateObject(object))
continue;
- RequestMessage request = MakeObjectMessage(object, "config::ObjectCommitted", true);
+ RequestMessage request = MakeObjectMessage(object, "config::ObjectUpdate", 0, true);
EndpointManager::GetInstance()->SendUnicastMessage(m_Endpoint, sender, request);
}
}
}
-void CIBSyncComponent::LocalObjectCommittedHandler(const DynamicObject::Ptr& object)
+void CIBSyncComponent::LocalObjectRegisteredHandler(const DynamicObject::Ptr& object)
{
/* don't send messages when we're currently processing a remote update */
if (m_SyncingConfig)
return;
EndpointManager::GetInstance()->SendMulticastMessage(m_Endpoint,
- MakeObjectMessage(object, "config::ObjectCommitted", true));
+ MakeObjectMessage(object, "config::ObjectCommitted", 0, true));
}
-void CIBSyncComponent::LocalObjectRemovedHandler(const DynamicObject::Ptr& object)
+void CIBSyncComponent::LocalObjectUnregisteredHandler(const DynamicObject::Ptr& object)
{
/* don't send messages when we're currently processing a remote update */
if (m_SyncingConfig)
return;
EndpointManager::GetInstance()->SendMulticastMessage(m_Endpoint,
- MakeObjectMessage(object, "config::ObjectRemoved", false));
+ MakeObjectMessage(object, "config::ObjectRemoved", 0, false));
+}
+
+void CIBSyncComponent::TransactionClosingHandler(const set<DynamicObject::Ptr>& modifiedObjects)
+{
+ stringstream msgbuf;
+ msgbuf << "Sending " << modifiedObjects.size() << " replication updates.";
+ Logger::Write(LogInformation, "cibsync", msgbuf.str());
+
+ BOOST_FOREACH(const DynamicObject::Ptr& object, modifiedObjects) {
+ if (!ShouldReplicateObject(object))
+ continue;
+
+ RequestMessage request = MakeObjectMessage(object, "config::ObjectUpdate", DynamicObject::GetCurrentTx(), true);
+
+ EndpointManager::GetInstance()->SendMulticastMessage(m_Endpoint, request);
+ }
}
-void CIBSyncComponent::RemoteObjectCommittedHandler(const Endpoint::Ptr& sender, const RequestMessage& request)
+void CIBSyncComponent::RemoteObjectUpdateHandler(const Endpoint::Ptr& sender, const RequestMessage& request)
{
MessagePart params;
if (!request.GetParams(¶ms))
return;
- string name;
+ String name;
if (!params.Get("name", &name))
return;
- string type;
+ String type;
if (!params.Get("type", &type))
return;
- MessagePart properties;
- if (!params.Get("properties", &properties))
+ Dictionary::Ptr update;
+ if (!params.Get("update", &update))
return;
DynamicObject::Ptr object = DynamicObject::GetObject(type, name);
if (!object) {
- object = boost::make_shared<DynamicObject>(properties.GetDictionary());
+ object = DynamicObject::Create(type, update);
if (object->GetSource() == EndpointManager::GetInstance()->GetIdentity()) {
/* the peer sent us an object that was originally created by us -
- * however if was deleted locally so we have to tell the peer to destroy
+ * however it was deleted locally so we have to tell the peer to destroy
* its copy of the object. */
EndpointManager::GetInstance()->SendMulticastMessage(m_Endpoint,
- MakeObjectMessage(object, "config::ObjectRemoved", false));
+ MakeObjectMessage(object, "config::ObjectRemoved", 0, false));
return;
}
} else {
- DynamicObject::Ptr remoteObject = boost::make_shared<DynamicObject>(properties.GetDictionary());
+ if (object->IsLocal())
+ throw_exception(invalid_argument("Replicated remote object is marked as local."));
- if (object->GetCommitTimestamp() >= remoteObject->GetCommitTimestamp())
- return;
-
- object->SetProperties(properties.GetDictionary());
- }
+ if (object->GetSource().IsEmpty())
+ object->SetSource(sender->GetIdentity());
- if (object->IsLocal())
- throw_exception(invalid_argument("Replicated remote object is marked as local."));
-
- if (object->GetSource().empty())
- object->SetSource(sender->GetIdentity());
-
- try {
- /* TODO: only ignore updates for _this_ object rather than all objects
- * this might be relevant if the commit handler for this object
- * creates other objects. */
- m_SyncingConfig = true;
- object->Commit();
- m_SyncingConfig = false;
- } catch (...) {
- m_SyncingConfig = false;
- throw;
+ object->ApplyUpdate(update, true);
}
}
if (!request.GetParams(¶ms))
return;
- string name;
+ String name;
if (!params.Get("name", &name))
return;
- string type;
+ String type;
if (!params.Get("type", &type))
return;
void NewEndpointHandler(const Endpoint::Ptr& endpoint);
void SessionEstablishedHandler(const Endpoint::Ptr& endpoint);
- void LocalObjectCommittedHandler(const DynamicObject::Ptr& object);
- void LocalObjectRemovedHandler(const DynamicObject::Ptr& object);
+ void LocalObjectRegisteredHandler(const DynamicObject::Ptr& object);
+ void LocalObjectUnregisteredHandler(const DynamicObject::Ptr& object);
+ void TransactionClosingHandler(const set<DynamicObject::Ptr>& modifiedObjects);
void FetchObjectsHandler(const Endpoint::Ptr& sender);
- void RemoteObjectCommittedHandler(const Endpoint::Ptr& sender, const RequestMessage& request);
+ void RemoteObjectUpdateHandler(const Endpoint::Ptr& sender, const RequestMessage& request);
void RemoteObjectRemovedHandler(const RequestMessage& request);
static RequestMessage MakeObjectMessage(const DynamicObject::Ptr& object,
- string method, bool includeProperties);
+ const String& method, double sinceTx, bool includeProperties);
static bool ShouldReplicateObject(const DynamicObject::Ptr& object);
};
<< "\t" << "active_checks_enabled" << "\t" << 1 << "\n"
<< "\t" << "passive_checks_enabled" << "\t" << 1 << "\n";
- set<string> parents = host->GetParents();
+ set<String> parents = host->GetParents();
if (!parents.empty()) {
fp << "\t" << "parents" << "\t";
void CompatComponent::DumpServiceStatus(ofstream& fp, const Service::Ptr& service)
{
- string output;
- string perfdata;
+ String output;
+ String perfdata;
double schedule_start = -1, schedule_end = -1;
double execution_start = -1, execution_end = -1;
- if (service->HasLastCheckResult()) {
- CheckResult cr = service->GetLastCheckResult();
- output = cr.GetOutput();
- schedule_start = cr.GetScheduleStart();
- schedule_end = cr.GetScheduleEnd();
- execution_start = cr.GetExecutionStart();
- execution_end = cr.GetExecutionEnd();
- perfdata = cr.GetPerformanceDataRaw();
+
+ Dictionary::Ptr cr = service->GetLastCheckResult();
+ if (cr) {
+ output = cr->Get("output");
+ schedule_start = cr->Get("schedule_start");
+ schedule_end = cr->Get("schedule_end");
+ execution_start = cr->Get("execution_start");
+ execution_end = cr->Get("execution_end");
+ perfdata = cr->Get("performance_data_raw");
}
double execution_time = (execution_end - execution_start);
if (!service->IsReachable()) {
state = StateCritical;
- string text = "One or more parent services are unavailable.";
+ String text = "One or more parent services are unavailable.";
- if (output.empty())
+ if (output.IsEmpty())
output = text;
else
output = text + " (" + output + ")";
<< "\t" << "service_description=" << service->GetAlias() << "\n"
<< "\t" << "check_interval=" << service->GetCheckInterval() / 60.0 << "\n"
<< "\t" << "retry_interval=" << service->GetRetryInterval() / 60.0 << "\n"
- << "\t" << "has_been_checked=" << (service->HasLastCheckResult() ? 1 : 0) << "\n"
+ << "\t" << "has_been_checked=" << (service->GetLastCheckResult() ? 1 : 0) << "\n"
<< "\t" << "should_be_scheduled=1" << "\n"
<< "\t" << "check_execution_time=" << execution_time << "\n"
<< "\t" << "check_latency=" << latency << "\n"
<< "# This file is auto-generated. Do not modify this file." << "\n"
<< "\n";
- map<string, vector<string> > hostgroups;
+ map<String, vector<String> > hostgroups;
DynamicObject::Ptr object;
BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Host")) {
dict = host->GetGroups();
if (dict) {
- Variant hostgroup;
+ Value hostgroup;
BOOST_FOREACH(tie(tuples::ignore, hostgroup), dict) {
hostgroups[hostgroup].push_back(host->GetName());
}
DumpHostObject(objectfp, host);
}
- pair<string, vector<string > > hgt;
+ pair<String, vector<String > > hgt;
BOOST_FOREACH(hgt, hostgroups) {
- const string& name = hgt.first;
- const vector<string>& hosts = hgt.second;
+ const String& name = hgt.first;
+ const vector<String>& hosts = hgt.second;
objectfp << "define hostgroup {" << "\n"
<< "\t" << "hostgroup_name" << "\t" << name << "\n";
<< "}" << "\n";
}
- map<string, vector<Service::Ptr> > servicegroups;
+ map<String, vector<Service::Ptr> > servicegroups;
BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Service")) {
Service::Ptr service = static_pointer_cast<Service>(object);
dict = service->GetGroups();
if (dict) {
- Variant servicegroup;
+ Value servicegroup;
BOOST_FOREACH(tie(tuples::ignore, servicegroup), dict) {
servicegroups[servicegroup].push_back(service);
}
DumpServiceObject(objectfp, service);
}
- pair<string, vector<Service::Ptr> > sgt;
+ pair<String, vector<Service::Ptr> > sgt;
BOOST_FOREACH(sgt, servicegroups) {
- const string& name = sgt.first;
+ const String& name = sgt.first;
const vector<Service::Ptr>& services = sgt.second;
objectfp << "define servicegroup {" << "\n"
objectfp << "\t" << "members" << "\t";
- vector<string> sglist;
+ vector<String> sglist;
vector<Service::Ptr>::iterator vt;
BOOST_FOREACH(const Service::Ptr& service, services) {
return;
Dictionary::Ptr oldServices;
- host->GetTag("convenience-services", &oldServices);
+ host->GetAttribute("convenience_services", &oldServices);
Dictionary::Ptr newServices;
newServices = boost::make_shared<Dictionary>();
Dictionary::Ptr serviceDescs;
- host->GetProperty("services", &serviceDescs);
+ host->GetAttribute("services", &serviceDescs);
if (serviceDescs) {
- string svcname;
- Variant svcdesc;
+ String svcname;
+ Value svcdesc;
BOOST_FOREACH(tie(svcname, svcdesc), serviceDescs) {
stringstream namebuf;
namebuf << item->GetName() << "-" << svcname;
- string name = namebuf.str();
+ String name = namebuf.str();
ConfigItemBuilder::Ptr builder = boost::make_shared<ConfigItemBuilder>(item->GetDebugInfo());
builder->SetType("service");
} else if (svcdesc.IsObjectType<Dictionary>()) {
Dictionary::Ptr service = svcdesc;
- string parent;
+ String parent;
if (!service->Get("service", &parent))
parent = svcname;
}
}
- host->SetTag("convenience-services", newServices);
+ host->SetAttribute("convenience_services", newServices);
}
void ConvenienceComponent::HostRemovedHandler(const ConfigItem::Ptr& item)
return;
Dictionary::Ptr services;
- host->GetTag("convenience-services", &services);
+ host->GetAttribute("convenience_services", &services);
if (!services)
return;
void DelegationComponent::Start(void)
{
- DynamicObject::OnCommitted.connect(boost::bind(&DelegationComponent::ServiceCommittedHandler, this, _1));
- DynamicObject::OnRemoved.connect(boost::bind(&DelegationComponent::ServiceRemovedHandler, this, _1));
+ DynamicObject::OnRegistered.connect(boost::bind(&DelegationComponent::ServiceCommittedHandler, this, _1));
+ DynamicObject::OnUnregistered.connect(boost::bind(&DelegationComponent::ServiceRemovedHandler, this, _1));
m_DelegationTimer = boost::make_shared<Timer>();
m_DelegationTimer->SetInterval(30);
if (!service)
return;
- string checker = service->GetChecker();
+ String checker = service->GetChecker();
- if (!checker.empty()) {
+ if (!checker.IsEmpty()) {
/* object was updated, clear its checker to make sure it's re-delegated by the delegation timer */
service->SetChecker("");
if (!service)
return;
- string checker = service->GetChecker();
+ String checker = service->GetChecker();
- if (!checker.empty()) {
+ if (!checker.IsEmpty()) {
/* TODO: figure out a better way to clear individual services */
Endpoint::Ptr endpoint = EndpointManager::GetInstance()->GetEndpointByIdentity(checker);
services.push_back(service);
- string checker = service->GetChecker();
- if (checker.empty())
+ String checker = service->GetChecker();
+ if (checker.IsEmpty())
continue;
Endpoint::Ptr endpoint = EndpointManager::GetInstance()->GetEndpointByIdentity(checker);
/* re-assign services */
BOOST_FOREACH(const Service::Ptr& service, services) {
- string checker = service->GetChecker();
+ String checker = service->GetChecker();
Endpoint::Ptr oldEndpoint;
- if (!checker.empty())
+ if (!checker.IsEmpty())
oldEndpoint = EndpointManager::GetInstance()->GetEndpointByIdentity(checker);
vector<Endpoint::Ptr> candidates = GetCheckerCandidates(service);
continue;
/* clear the service's current checker */
- if (!checker.empty()) {
+ if (!checker.IsEmpty()) {
need_clear = true;
service->SetChecker("");
break;
}
- assert(candidates.size() == 0 || !service->GetChecker().empty());
+ assert(candidates.size() == 0 || !service->GetChecker().IsEmpty());
}
Endpoint::Ptr endpoint;
}
BOOST_FOREACH(const Service::Ptr& service, services) {
- string checker = service->GetChecker();
+ String checker = service->GetChecker();
Endpoint::Ptr endpoint = EndpointManager::GetInstance()->GetEndpointByIdentity(checker);
if (!endpoint)
using namespace icinga;
-/**
- * Returns the name of the component.
- *
- * @returns The name.
- */
-string DemoComponent::GetName(void) const
-{
- return "demo";
-}
-
/**
* Starts the component.
*/
class DemoComponent : public IComponent
{
public:
- virtual string GetName(void) const;
virtual void Start(void);
virtual void Stop(void);
/* accept discovery::Welcome messages from any endpoint */
endpoint->RegisterPublication("discovery::Welcome");
- string identity = endpoint->GetIdentity();
+ String identity = endpoint->GetIdentity();
if (identity == EndpointManager::GetInstance()->GetIdentity()) {
Logger::Write(LogWarning, "discovery", "Detected loop-back connection - Disconnecting endpoint.");
// the broker knows about our message types
SendDiscoveryMessage("discovery::RegisterComponent", EndpointManager::GetInstance()->GetIdentity(), endpoint);
- map<string, ComponentDiscoveryInfo::Ptr>::iterator ic;
+ map<String, ComponentDiscoveryInfo::Ptr>::iterator ic;
// we assume the other component _always_ wants
// discovery::NewComponent messages from us
// register published/subscribed topics for this endpoint
ComponentDiscoveryInfo::Ptr info = ic->second;
- BOOST_FOREACH(string publication, info->Publications) {
+ BOOST_FOREACH(String publication, info->Publications) {
endpoint->RegisterPublication(publication);
}
- BOOST_FOREACH(string subscription, info->Subscriptions) {
+ BOOST_FOREACH(String subscription, info->Subscriptions) {
endpoint->RegisterSubscription(subscription);
}
* @param info Pointer to the information object.
* @returns true if the info object was successfully retrieved, false otherwise.
*/
-bool DiscoveryComponent::GetComponentDiscoveryInfo(string component, ComponentDiscoveryInfo::Ptr *info) const
+bool DiscoveryComponent::GetComponentDiscoveryInfo(String component, ComponentDiscoveryInfo::Ptr *info) const
{
if (component == EndpointManager::GetInstance()->GetIdentity()) {
/* Build fake discovery info for ourselves */
return true;
}
- map<string, ComponentDiscoveryInfo::Ptr>::const_iterator i;
+ map<String, ComponentDiscoveryInfo::Ptr>::const_iterator i;
i = m_Components.find(component);
* @param identity The identity of the component for which a message should be sent.
* @param recipient The recipient of the message. A multicast message is sent if this parameter is empty.
*/
-void DiscoveryComponent::SendDiscoveryMessage(const string& method, const string& identity, const Endpoint::Ptr& recipient)
+void DiscoveryComponent::SendDiscoveryMessage(const String& method, const String& identity, const Endpoint::Ptr& recipient)
{
RequestMessage request;
request.SetMethod(method);
if (!GetComponentDiscoveryInfo(identity, &info))
return;
- if (!info->Node.empty() && !info->Service.empty()) {
+ if (!info->Node.IsEmpty() && !info->Service.IsEmpty()) {
params.SetNode(info->Node);
params.SetService(info->Service);
}
- set<string>::iterator i;
+ set<String>::iterator i;
Dictionary::Ptr subscriptions = boost::make_shared<Dictionary>();
- BOOST_FOREACH(string subscription, info->Subscriptions) {
+ BOOST_FOREACH(String subscription, info->Subscriptions) {
subscriptions->Add(subscription);
}
params.SetSubscriptions(subscriptions);
Dictionary::Ptr publications = boost::make_shared<Dictionary>();
- BOOST_FOREACH(string publication, info->Publications) {
+ BOOST_FOREACH(String publication, info->Publications) {
publications->Add(publication);
}
EndpointManager::GetInstance()->SendMulticastMessage(m_Endpoint, request);
}
-bool DiscoveryComponent::HasMessagePermission(const Dictionary::Ptr& roles, const string& messageType, const string& message)
+bool DiscoveryComponent::HasMessagePermission(const Dictionary::Ptr& roles, const String& messageType, const String& message)
{
if (!roles)
return false;
- DynamicObject::Ptr role;
- BOOST_FOREACH(tie(tuples::ignore, role), DynamicObject::GetObjects("Role")) {
+ Value roleName;
+ BOOST_FOREACH(tie(tuples::ignore, roleName), roles) {
+ DynamicObject::Ptr role = DynamicObject::GetObject("Role", roleName);
Dictionary::Ptr permissions;
- if (!role->GetProperty(messageType, &permissions))
+ if (!role->GetAttribute(messageType, &permissions))
continue;
- Variant permission;
+ Value permission;
BOOST_FOREACH(tie(tuples::ignore, permission), permissions) {
if (Utility::Match(permission, message))
return true;
* @param message The discovery message.
* @param trusted Whether the message comes from a trusted source (i.e. a broker).
*/
-void DiscoveryComponent::ProcessDiscoveryMessage(const string& identity, const DiscoveryMessage& message, bool trusted)
+void DiscoveryComponent::ProcessDiscoveryMessage(const String& identity, const DiscoveryMessage& message, bool trusted)
{
/* ignore discovery messages that are about ourselves */
if (identity == EndpointManager::GetInstance()->GetIdentity())
info->LastSeen = Utility::GetTime();
- string node;
- if (message.GetNode(&node) && !node.empty())
+ String node;
+ if (message.GetNode(&node) && !node.IsEmpty())
info->Node = node;
- string service;
- if (message.GetService(&service) && !service.empty())
+ String service;
+ if (message.GetService(&service) && !service.IsEmpty())
info->Service = service;
DynamicObject::Ptr endpointConfig = DynamicObject::GetObject("endpoint", identity);
Dictionary::Ptr roles;
if (endpointConfig)
- endpointConfig->GetProperty("roles", &roles);
+ endpointConfig->GetAttribute("roles", &roles);
Endpoint::Ptr endpoint = EndpointManager::GetInstance()->GetEndpointByIdentity(identity);
Dictionary::Ptr publications;
if (message.GetPublications(&publications)) {
- Variant publication;
+ Value publication;
BOOST_FOREACH(tie(tuples::ignore, publication), publications) {
if (trusted || HasMessagePermission(roles, "publications", publication)) {
info->Publications.insert(publication);
Dictionary::Ptr subscriptions;
if (message.GetSubscriptions(&subscriptions)) {
- Variant subscription;
+ Value subscription;
BOOST_FOREACH(tie(tuples::ignore, subscription), subscriptions) {
if (trusted || HasMessagePermission(roles, "subscriptions", subscription)) {
info->Subscriptions.insert(subscription);
}
}
- map<string, ComponentDiscoveryInfo::Ptr>::iterator i;
+ map<String, ComponentDiscoveryInfo::Ptr>::iterator i;
i = m_Components.find(identity);
DiscoveryMessage message;
request.GetParams(&message);
- string identity;
+ String identity;
if (!message.GetIdentity(&identity))
return;
if (endpointManager->GetEndpointByIdentity(object->GetName()))
continue;
- string node, service;
- if (object->GetProperty("node", &node) && object->GetProperty("service", &service)) {
+ String node, service;
+ if (object->GetAttribute("node", &node) && object->GetAttribute("service", &service)) {
/* reconnect to this endpoint */
endpointManager->AddConnection(node, service);
}
}
- map<string, ComponentDiscoveryInfo::Ptr>::iterator curr, i;
+ map<String, ComponentDiscoveryInfo::Ptr>::iterator curr, i;
for (i = m_Components.begin(); i != m_Components.end(); ) {
- const string& identity = i->first;
+ const String& identity = i->first;
const ComponentDiscoveryInfo::Ptr& info = i->second;
curr = i;
/* TODO: figure out whether we actually want to connect to this component */
/* try and reconnect to this component */
try {
- if (!info->Node.empty() && !info->Service.empty())
+ if (!info->Node.IsEmpty() && !info->Service.IsEmpty())
endpointManager->AddConnection(info->Node, info->Service);
} catch (const exception& ex) {
stringstream msgbuf;
typedef shared_ptr<ComponentDiscoveryInfo> Ptr;
typedef weak_ptr<ComponentDiscoveryInfo> WeakPtr;
- string Node;
- string Service;
+ String Node;
+ String Service;
- set<string> Subscriptions;
- set<string> Publications;
+ set<String> Subscriptions;
+ set<String> Publications;
double LastSeen;
};
private:
VirtualEndpoint::Ptr m_Endpoint;
- map<string, ComponentDiscoveryInfo::Ptr> m_Components;
+ map<String, ComponentDiscoveryInfo::Ptr> m_Components;
Timer::Ptr m_DiscoveryTimer;
void NewEndpointHandler(const Endpoint::Ptr& endpoint);
void WelcomeMessageHandler(const Endpoint::Ptr& sender, const RequestMessage& request);
- void SendDiscoveryMessage(const string& method, const string& identity, const Endpoint::Ptr& recipient);
- void ProcessDiscoveryMessage(const string& identity, const DiscoveryMessage& message, bool trusted);
+ void SendDiscoveryMessage(const String& method, const String& identity, const Endpoint::Ptr& recipient);
+ void ProcessDiscoveryMessage(const String& identity, const DiscoveryMessage& message, bool trusted);
- bool GetComponentDiscoveryInfo(string component, ComponentDiscoveryInfo::Ptr *info) const;
+ bool GetComponentDiscoveryInfo(String component, ComponentDiscoveryInfo::Ptr *info) const;
void CheckExistingEndpoint(const Endpoint::Ptr& self, const Endpoint::Ptr& other);
void DiscoveryEndpointHandler(const Endpoint::Ptr& endpoint, const ComponentDiscoveryInfo::Ptr& info) const;
void FinishDiscoverySetup(const Endpoint::Ptr& endpoint);
- bool HasMessagePermission(const Dictionary::Ptr& roles, const string& messageType, const string& message);
+ bool HasMessagePermission(const Dictionary::Ptr& roles, const String& messageType, const String& message);
static const int RegistrationTTL = 300;
};
: MessagePart(message)
{ }
-bool DiscoveryMessage::GetIdentity(string *value) const
+bool DiscoveryMessage::GetIdentity(String *value) const
{
return Get("identity", value);
}
-void DiscoveryMessage::SetIdentity(const string& value)
+void DiscoveryMessage::SetIdentity(const String& value)
{
Set("identity", value);
}
-bool DiscoveryMessage::GetNode(string *value) const
+bool DiscoveryMessage::GetNode(String *value) const
{
return Get("node", value);
}
-void DiscoveryMessage::SetNode(const string& value)
+void DiscoveryMessage::SetNode(const String& value)
{
Set("node", value);
}
-bool DiscoveryMessage::GetService(string *value) const
+bool DiscoveryMessage::GetService(String *value) const
{
return Get("service", value);
}
-void DiscoveryMessage::SetService(const string& value)
+void DiscoveryMessage::SetService(const String& value)
{
Set("service", value);
}
DiscoveryMessage(void);
DiscoveryMessage(const MessagePart& message);
- bool GetIdentity(string *value) const;
- void SetIdentity(const string& value);
+ bool GetIdentity(String *value) const;
+ void SetIdentity(const String& value);
- bool GetNode(string *value) const;
- void SetNode(const string& value);
+ bool GetNode(String *value) const;
+ void SetNode(const String& value);
- bool GetService(string *value) const;
- void SetService(const string& value);
+ bool GetService(String *value) const;
+ void SetService(const String& value);
bool GetSubscriptions(Dictionary::Ptr *value) const;
void SetSubscriptions(const Dictionary::Ptr& value);
char *text;
double num;
- icinga::Variant *variant;
+ icinga::Value *variant;
icinga::ExpressionOperator op;
/* Line 1806 of yacc.c */
#line 166 "config_parser.yy"
{
- (yyval.variant) = new Variant(m_ExpressionLists.top());
+ (yyval.variant) = new Value(m_ExpressionLists.top());
m_ExpressionLists.pop();
}
break;
/* Line 1806 of yacc.c */
#line 222 "config_parser.yy"
{
- (yyval.variant) = new Variant((yyvsp[(1) - (1)].text));
+ (yyval.variant) = new Value((yyvsp[(1) - (1)].text));
free((yyvsp[(1) - (1)].text));
}
break;
/* Line 1806 of yacc.c */
#line 227 "config_parser.yy"
{
- (yyval.variant) = new Variant((yyvsp[(1) - (1)].num));
+ (yyval.variant) = new Value((yyvsp[(1) - (1)].num));
}
break;
/* Line 1806 of yacc.c */
#line 231 "config_parser.yy"
{
- (yyval.variant) = new Variant();
+ (yyval.variant) = new Value();
}
break;
char *text;
double num;
- icinga::Variant *variant;
+ icinga::Value *variant;
icinga::ExpressionOperator op;
%union {
char *text;
double num;
- icinga::Variant *variant;
+ icinga::Value *variant;
icinga::ExpressionOperator op;
}
expressions
'}'
{
- $$ = new Variant(m_ExpressionLists.top());
+ $$ = new Value(m_ExpressionLists.top());
m_ExpressionLists.pop();
}
;
simplevalue: T_STRING
{
- $$ = new Variant($1);
+ $$ = new Value($1);
free($1);
}
| T_NUMBER
{
- $$ = new Variant($1);
+ $$ = new Value($1);
}
| T_NULL
{
- $$ = new Variant();
+ $$ = new Value();
}
;
using namespace icinga;
-ConfigCompiler::ConfigCompiler(const string& path, istream *input, HandleIncludeFunc includeHandler)
+ConfigCompiler::ConfigCompiler(const String& path, istream *input, HandleIncludeFunc includeHandler)
: m_Path(path), m_Input(input), m_HandleInclude(includeHandler)
{
InitializeScanner();
return m_Result;
}
-string ConfigCompiler::GetPath(void) const
+String ConfigCompiler::GetPath(void) const
{
return m_Path;
}
-void ConfigCompiler::HandleInclude(const string& include)
+void ConfigCompiler::HandleInclude(const String& include)
{
- string path = Utility::DirName(GetPath()) + "/" + include;
+ String path = Utility::DirName(GetPath()) + "/" + include;
vector<ConfigItem::Ptr> items = m_HandleInclude(path);
std::copy(items.begin(), items.end(), back_inserter(m_Result));
}
-vector<ConfigItem::Ptr> ConfigCompiler::CompileStream(const string& path, istream *stream)
+vector<ConfigItem::Ptr> ConfigCompiler::CompileStream(const String& path, istream *stream)
{
ConfigCompiler ctx(path, stream);
ctx.Compile();
return ctx.GetResult();
}
-vector<ConfigItem::Ptr> ConfigCompiler::CompileFile(const string& path)
+vector<ConfigItem::Ptr> ConfigCompiler::CompileFile(const String& path)
{
ifstream stream;
- stream.open(path.c_str(), ifstream::in);
+ stream.open(path.CStr(), ifstream::in);
if (!stream)
throw_exception(invalid_argument("Could not open config file: " + path));
return CompileStream(path, &stream);
}
-vector<ConfigItem::Ptr> ConfigCompiler::CompileText(const string& path, const string& text)
+vector<ConfigItem::Ptr> ConfigCompiler::CompileText(const String& path, const String& text)
{
stringstream stream(text);
return CompileStream(path, &stream);
}
-vector<ConfigItem::Ptr> ConfigCompiler::HandleFileInclude(const string& include)
+vector<ConfigItem::Ptr> ConfigCompiler::HandleFileInclude(const String& include)
{
/* TODO: implement wildcard includes */
return CompileFile(include);
class I2_DYN_API ConfigCompiler
{
public:
- typedef function<vector<ConfigItem::Ptr> (const string& include)> HandleIncludeFunc;
+ typedef function<vector<ConfigItem::Ptr> (const String& include)> HandleIncludeFunc;
- ConfigCompiler(const string& path, istream *input = &cin,
+ ConfigCompiler(const String& path, istream *input = &cin,
HandleIncludeFunc includeHandler = &ConfigCompiler::HandleFileInclude);
virtual ~ConfigCompiler(void);
void Compile(void);
- static vector<ConfigItem::Ptr> CompileStream(const string& path, istream *stream);
- static vector<ConfigItem::Ptr> CompileFile(const string& path);
- static vector<ConfigItem::Ptr> CompileText(const string& path, const string& text);
+ static vector<ConfigItem::Ptr> CompileStream(const String& path, istream *stream);
+ static vector<ConfigItem::Ptr> CompileFile(const String& path);
+ static vector<ConfigItem::Ptr> CompileText(const String& path, const String& text);
- static vector<ConfigItem::Ptr> HandleFileInclude(const string& include);
+ static vector<ConfigItem::Ptr> HandleFileInclude(const String& include);
vector<ConfigItem::Ptr> GetResult(void) const;
- string GetPath(void) const;
+ String GetPath(void) const;
/* internally used methods */
- void HandleInclude(const string& include);
+ void HandleInclude(const String& include);
void AddObject(const ConfigItem::Ptr& object);
size_t ReadInput(char *buffer, size_t max_bytes);
void *GetScanner(void) const;
private:
- string m_Path;
+ String m_Path;
istream *m_Input;
HandleIncludeFunc m_HandleInclude;
boost::signal<void (const ConfigItem::Ptr&)> ConfigItem::OnCommitted;
boost::signal<void (const ConfigItem::Ptr&)> ConfigItem::OnRemoved;
-ConfigItem::ConfigItem(const string& type, const string& name,
- const ExpressionList::Ptr& exprl, const vector<string>& parents,
+ConfigItem::ConfigItem(const String& type, const String& name,
+ const ExpressionList::Ptr& exprl, const vector<String>& parents,
const DebugInfo& debuginfo)
: m_Type(type), m_Name(name), m_ExpressionList(exprl),
m_Parents(parents), m_DebugInfo(debuginfo)
{
}
-string ConfigItem::GetType(void) const
+String ConfigItem::GetType(void) const
{
return m_Type;
}
-string ConfigItem::GetName(void) const
+String ConfigItem::GetName(void) const
{
return m_Name;
}
return m_ExpressionList;
}
-vector<string> ConfigItem::GetParents(void) const
+vector<String> ConfigItem::GetParents(void) const
{
return m_Parents;
}
-void ConfigItem::CalculateProperties(Dictionary::Ptr dictionary) const
+void ConfigItem::CalculateProperties(const Dictionary::Ptr& dictionary) const
{
- BOOST_FOREACH(const string& name, m_Parents) {
+ BOOST_FOREACH(const String& name, m_Parents) {
ConfigItem::Ptr parent = ConfigItem::GetObject(GetType(), name);
if (!parent) {
Dictionary::Ptr properties = boost::make_shared<Dictionary>();
CalculateProperties(properties);
+ /* Create a fake update in the format that
+ * DynamicObject::ApplyUpdate expects. */
+ Dictionary::Ptr attrs = boost::make_shared<Dictionary>();
+
+ String key;
+ Value data;
+ BOOST_FOREACH(tie(key, data), properties) {
+ Dictionary::Ptr attr = boost::make_shared<Dictionary>();
+ attr->Set("data", data);
+ attr->Set("type", Attribute_Config);
+ attr->Set("tx", DynamicObject::GetCurrentTx());
+ attrs->Set(key, attr);
+ }
+
+ Dictionary::Ptr update = boost::make_shared<Dictionary>();
+ update->Set("attrs", attrs);
+ update->Set("configTx", DynamicObject::GetCurrentTx());
+
if (!dobj)
dobj = DynamicObject::GetObject(GetType(), GetName());
if (!dobj)
- dobj = DynamicObject::Create(GetType(), properties);
+ dobj = DynamicObject::Create(GetType(), update);
else
- dobj->SetProperties(properties);
+ dobj->ApplyUpdate(update);
m_DynamicObject = dobj;
if (dobj->IsAbstract())
dobj->Unregister();
else
- dobj->Commit();
+ dobj->Register();
/* TODO: Figure out whether there are any child objects which inherit
* from this config item and Commit() them as well */
return m_DynamicObject.lock();
}
-ConfigItem::Ptr ConfigItem::GetObject(const string& type, const string& name)
+ConfigItem::Ptr ConfigItem::GetObject(const String& type, const String& name)
{
ConfigItem::ItemMap::iterator it;
it = m_Items.find(make_pair(type, name));
typedef shared_ptr<ConfigItem> Ptr;
typedef weak_ptr<ConfigItem> WeakPtr;
- ConfigItem(const string& type, const string& name,
- const ExpressionList::Ptr& exprl, const vector<string>& parents,
+ ConfigItem(const String& type, const String& name,
+ const ExpressionList::Ptr& exprl, const vector<String>& parents,
const DebugInfo& debuginfo);
- string GetType(void) const;
- string GetName(void) const;
+ String GetType(void) const;
+ String GetName(void) const;
- vector<string> GetParents(void) const;
+ vector<String> GetParents(void) const;
ExpressionList::Ptr GetExpressionList(void) const;
- void CalculateProperties(Dictionary::Ptr dictionary) const;
-
DynamicObject::Ptr Commit(void);
void Unregister(void);
DebugInfo GetDebugInfo(void) const;
- static ConfigItem::Ptr GetObject(const string& type, const string& name);
+ static ConfigItem::Ptr GetObject(const String& type, const String& name);
static boost::signal<void (const ConfigItem::Ptr&)> OnCommitted;
static boost::signal<void (const ConfigItem::Ptr&)> OnRemoved;
private:
- string m_Type;
- string m_Name;
+ void CalculateProperties(const Dictionary::Ptr& dictionary) const;
+
+ String m_Type;
+ String m_Name;
ExpressionList::Ptr m_ExpressionList;
- vector<string> m_Parents;
+ vector<String> m_Parents;
DebugInfo m_DebugInfo;
DynamicObject::WeakPtr m_DynamicObject;
- typedef map<pair<string, string>, ConfigItem::Ptr> ItemMap;
+ typedef map<pair<String, String>, ConfigItem::Ptr> ItemMap;
static ItemMap m_Items;
};
m_DebugInfo = debugInfo;
}
-void ConfigItemBuilder::SetType(const string& type)
+void ConfigItemBuilder::SetType(const String& type)
{
m_Type = type;
}
-void ConfigItemBuilder::SetName(const string& name)
+void ConfigItemBuilder::SetName(const String& name)
{
m_Name = name;
}
m_Abstract = abstract;
}
-void ConfigItemBuilder::AddParent(const string& parent)
+void ConfigItemBuilder::AddParent(const String& parent)
{
m_Parents.push_back(parent);
}
m_ExpressionList->AddExpression(expr);
}
-void ConfigItemBuilder::AddExpression(const string& key, ExpressionOperator op, const Variant& value)
+void ConfigItemBuilder::AddExpression(const String& key, ExpressionOperator op, const Value& value)
{
Expression expr(key, op, value, m_DebugInfo);
AddExpression(expr);
ConfigItem::Ptr ConfigItemBuilder::Compile(void)
{
- assert(!m_Type.empty());
- assert(!m_Name.empty());
+ assert(!m_Type.IsEmpty());
+ assert(!m_Name.IsEmpty());
ExpressionList::Ptr exprl = boost::make_shared<ExpressionList>();
ConfigItemBuilder(void);
ConfigItemBuilder(const DebugInfo& debugInfo);
- void SetType(const string& type);
- void SetName(const string& name);
+ void SetType(const String& type);
+ void SetName(const String& name);
void SetLocal(bool local);
void SetAbstract(bool abstract);
- void AddParent(const string& parent);
+ void AddParent(const String& parent);
void AddExpression(const Expression& expr);
- void AddExpression(const string& key, ExpressionOperator op, const Variant& value);
+ void AddExpression(const String& key, ExpressionOperator op, const Value& value);
void AddExpressionList(const ExpressionList::Ptr& exprl);
ConfigItem::Ptr Compile(void);
private:
- string m_Type;
- string m_Name;
+ String m_Type;
+ String m_Name;
bool m_Local;
bool m_Abstract;
- vector<string> m_Parents;
+ vector<String> m_Parents;
ExpressionList::Ptr m_ExpressionList;
DebugInfo m_DebugInfo;
};
struct DebugInfo
{
- string Path;
+ String Path;
union
{
using namespace icinga;
-Expression::Expression(const string& key, ExpressionOperator op, const Variant& value, const DebugInfo& debuginfo)
+Expression::Expression(const String& key, ExpressionOperator op, const Value& value, const DebugInfo& debuginfo)
: m_Key(key), m_Operator(op), m_Value(value), m_DebugInfo(debuginfo)
{
}
void Expression::Execute(const Dictionary::Ptr& dictionary) const
{
- Variant oldValue, newValue;
+ Value oldValue, newValue;
ExpressionList::Ptr valueExprl;
Dictionary::Ptr valueDict;
break;
case OperatorPlus:
- dictionary->Get(m_Key, &oldValue);
+ oldValue = dictionary->Get(m_Key);
if (oldValue.IsObjectType<Dictionary>())
dict = oldValue;
if (valueExprl) {
valueExprl->Execute(dict);
} else if (valueDict) {
- string key;
- Variant value;
+ String key;
+ Value value;
BOOST_FOREACH(tie(key, value), valueDict) {
dict->Set(key, value);
}
struct I2_DYN_API Expression
{
public:
- Expression(const string& key, ExpressionOperator op, const Variant& value, const DebugInfo& debuginfo);
+ Expression(const String& key, ExpressionOperator op, const Value& value, const DebugInfo& debuginfo);
void Execute(const Dictionary::Ptr& dictionary) const;
private:
- string m_Key;
+ String m_Key;
ExpressionOperator m_Operator;
- Variant m_Value;
+ Value m_Value;
DebugInfo m_DebugInfo;
};
local object Application "icinga" {
-/* cert = "icinga-c1.pem",
+ cert = "icinga-c1.pem",
ca = "ca.crt",
node = "192.168.2.235",
- service = 7777*/
+ service = 7777
}
-/*local object Component "discovery" {
+local object Component "discovery" {
-}*/
+}
local object Component "checker" {
}
-/*local object Endpoint "icinga-c2" {
+local object Component "compat" {
+
+}
+
+local object Endpoint "icinga-c2" {
roles = { "all" }
}
local object Role "all" {
publications = { "*" },
subscriptions = { "*" }
-}*/
+}
object Host "localhost" {
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "icinga-app", "icinga-app\icinga-app.vcxproj", "{BE412865-FEBA-4259-AD41-58950D1F5432}"
ProjectSection(ProjectDependencies) = postProject
+ {2BD1C70C-43DB-4F44-B66B-67CF5C7044AA} = {2BD1C70C-43DB-4F44-B66B-67CF5C7044AA}
{EAD41628-BB96-4F99-9070-8A9676801295} = {EAD41628-BB96-4F99-9070-8A9676801295}
{2E6C1133-730F-4875-A72C-B455B1DD4C5C} = {2E6C1133-730F-4875-A72C-B455B1DD4C5C}
{17C93245-8C20-4316-9573-1AE41D918C10} = {17C93245-8C20-4316-9573-1AE41D918C10}
+ {704DDD8E-9E6D-4C22-80BD-6DE10F3A5E1C} = {704DDD8E-9E6D-4C22-80BD-6DE10F3A5E1C}
+ {D02A349B-BAF7-41FB-86FF-B05BA05FE578} = {D02A349B-BAF7-41FB-86FF-B05BA05FE578}
{38CE81CC-2660-4EF0-A936-4A337591DA3E} = {38CE81CC-2660-4EF0-A936-4A337591DA3E}
{C1FC77E1-04A4-481B-A78B-2F7AF489C2F8} = {C1FC77E1-04A4-481B-A78B-2F7AF489C2F8}
EndProjectSection
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
- {2E6C1133-730F-4875-A72C-B455B1DD4C5C} = {4A1773FD-DDED-4952-8700-C898E890554A}
{EAD41628-BB96-4F99-9070-8A9676801295} = {4A1773FD-DDED-4952-8700-C898E890554A}
{38CE81CC-2660-4EF0-A936-4A337591DA3E} = {4A1773FD-DDED-4952-8700-C898E890554A}
{17C93245-8C20-4316-9573-1AE41D918C10} = {4A1773FD-DDED-4952-8700-C898E890554A}
{704DDD8E-9E6D-4C22-80BD-6DE10F3A5E1C} = {4A1773FD-DDED-4952-8700-C898E890554A}
{2BD1C70C-43DB-4F44-B66B-67CF5C7044AA} = {4A1773FD-DDED-4952-8700-C898E890554A}
{D02A349B-BAF7-41FB-86FF-B05BA05FE578} = {4A1773FD-DDED-4952-8700-C898E890554A}
+ {2E6C1133-730F-4875-A72C-B455B1DD4C5C} = {4A1773FD-DDED-4952-8700-C898E890554A}
EndGlobalSection
EndGlobal
*
* @param topic The name of the topic.
*/
-void Endpoint::RegisterSubscription(string topic)
+void Endpoint::RegisterSubscription(String topic)
{
m_Subscriptions.insert(topic);
}
*
* @param topic The name of the topic.
*/
-void Endpoint::UnregisterSubscription(string topic)
+void Endpoint::UnregisterSubscription(String topic)
{
m_Subscriptions.erase(topic);
}
* @param topic The name of the topic.
* @returns true if the endpoint is subscribed to the topic, false otherwise.
*/
-bool Endpoint::HasSubscription(string topic) const
+bool Endpoint::HasSubscription(String topic) const
{
return (m_Subscriptions.find(topic) != m_Subscriptions.end());
}
*
* @param topic The name of the topic.
*/
-void Endpoint::RegisterPublication(string topic)
+void Endpoint::RegisterPublication(String topic)
{
m_Publications.insert(topic);
}
*
* @param topic The name of the topic.
*/
-void Endpoint::UnregisterPublication(string topic)
+void Endpoint::UnregisterPublication(String topic)
{
m_Publications.erase(topic);
}
* @param topic The name of the topic.
* @returns true if the endpoint is publishing this topic, false otherwise.
*/
-bool Endpoint::HasPublication(string topic) const
+bool Endpoint::HasPublication(String topic) const
{
return (m_Publications.find(topic) != m_Publications.end());
}
typedef shared_ptr<Endpoint> Ptr;
typedef weak_ptr<Endpoint> WeakPtr;
- typedef set<string>::const_iterator ConstTopicIterator;
+ typedef set<String>::const_iterator ConstTopicIterator;
Endpoint(void)
: m_ReceivedWelcome(false), m_SentWelcome(false)
{ }
- virtual string GetIdentity(void) const = 0;
- virtual string GetAddress(void) const = 0;
+ virtual String GetIdentity(void) const = 0;
+ virtual String GetAddress(void) const = 0;
void SetReceivedWelcome(bool value);
bool HasReceivedWelcome(void) const;
shared_ptr<EndpointManager> GetEndpointManager(void) const;
void SetEndpointManager(weak_ptr<EndpointManager> manager);
- void RegisterSubscription(string topic);
- void UnregisterSubscription(string topic);
- bool HasSubscription(string topic) const;
+ void RegisterSubscription(String topic);
+ void UnregisterSubscription(String topic);
+ bool HasSubscription(String topic) const;
- void RegisterPublication(string topic);
- void UnregisterPublication(string topic);
- bool HasPublication(string topic) const;
+ void RegisterPublication(String topic);
+ void UnregisterPublication(String topic);
+ bool HasPublication(String topic) const;
virtual bool IsLocal(void) const = 0;
virtual bool IsConnected(void) const = 0;
boost::signal<void (const Endpoint::Ptr&)> OnSessionEstablished;
private:
- set<string> m_Subscriptions; /**< The topics this endpoint is
+ set<String> m_Subscriptions; /**< The topics this endpoint is
subscribed to. */
- set<string> m_Publications; /**< The topics this endpoint is
+ set<String> m_Publications; /**< The topics this endpoint is
publishing. */
bool m_ReceivedWelcome; /**< Have we received a welcome message
from this endpoint? */
*
* @param identity The new identity.
*/
-void EndpointManager::SetIdentity(const string& identity)
+void EndpointManager::SetIdentity(const String& identity)
{
m_Identity = identity;
}
*
* @returns The identity.
*/
-string EndpointManager::GetIdentity(void) const
+String EndpointManager::GetIdentity(void) const
{
return m_Identity;
}
*
* @param service The port to listen on.
*/
-void EndpointManager::AddListener(const string& service)
+void EndpointManager::AddListener(const String& service)
{
if (!GetSSLContext())
throw_exception(logic_error("SSL context is required for AddListener()"));
* @param node The remote host.
* @param service The remote port.
*/
-void EndpointManager::AddConnection(const string& node, const string& service)
+void EndpointManager::AddConnection(const String& node, const String& service)
{
stringstream s;
s << "Adding new endpoint: [" << node << "]:" << service;
UnregisterEndpoint(endpoint);
- string identity = endpoint->GetIdentity();
+ String identity = endpoint->GetIdentity();
- if (!identity.empty()) {
+ if (!identity.IsEmpty()) {
m_Endpoints[identity] = endpoint;
OnNewEndpoint(GetSelf(), endpoint);
} else {
remove(m_PendingEndpoints.begin(), m_PendingEndpoints.end(), endpoint),
m_PendingEndpoints.end());
- string identity = endpoint->GetIdentity();
- if (!identity.empty())
+ String identity = endpoint->GetIdentity();
+ if (!identity.IsEmpty())
m_Endpoints.erase(identity);
}
void EndpointManager::SendAnycastMessage(const Endpoint::Ptr& sender,
const RequestMessage& message)
{
- string method;
+ String method;
if (!message.GetMethod(&method))
throw_exception(invalid_argument("Message is missing the 'method' property."));
void EndpointManager::SendMulticastMessage(const Endpoint::Ptr& sender,
const RequestMessage& message)
{
- string id;
+ String id;
if (message.GetID(&id))
throw_exception(invalid_argument("Multicast requests must not have an ID."));
- string method;
+ String method;
if (!message.GetMethod(&method))
throw_exception(invalid_argument("Message is missing the 'method' property."));
*/
void EndpointManager::ForEachEndpoint(function<void (const EndpointManager::Ptr&, const Endpoint::Ptr&)> callback)
{
- map<string, Endpoint::Ptr>::iterator prev, i;
+ map<String, Endpoint::Ptr>::iterator prev, i;
for (i = m_Endpoints.begin(); i != m_Endpoints.end(); ) {
prev = i;
i++;
*
* @param identity The identity of the endpoint.
*/
-Endpoint::Ptr EndpointManager::GetEndpointByIdentity(const string& identity) const
+Endpoint::Ptr EndpointManager::GetEndpointByIdentity(const String& identity) const
{
- map<string, Endpoint::Ptr>::const_iterator i;
+ map<String, Endpoint::Ptr>::const_iterator i;
i = m_Endpoints.find(identity);
if (i != m_Endpoints.end())
return i->second;
stringstream idstream;
idstream << m_NextMessageID;
- string id = idstream.str();
+ String id = idstream.str();
message.SetID(id);
PendingRequest pr;
SendUnicastMessage(sender, recipient, message);
}
-bool EndpointManager::RequestTimeoutLessComparer(const pair<string, PendingRequest>& a,
- const pair<string, PendingRequest>& b)
+bool EndpointManager::RequestTimeoutLessComparer(const pair<String, PendingRequest>& a,
+ const pair<String, PendingRequest>& b)
{
return a.second.Timeout < b.second.Timeout;
}
void EndpointManager::RequestTimerHandler(void)
{
- map<string, PendingRequest>::iterator it;
+ map<String, PendingRequest>::iterator it;
for (it = m_Requests.begin(); it != m_Requests.end(); it++) {
if (it->second.HasTimedOut()) {
it->second.Callback(GetSelf(), Endpoint::Ptr(), it->second.Request, ResponseMessage(), true);
void EndpointManager::ProcessResponseMessage(const Endpoint::Ptr& sender, const ResponseMessage& message)
{
- string id;
+ String id;
if (!message.GetID(&id))
throw_exception(invalid_argument("Response message must have a message ID."));
- map<string, PendingRequest>::iterator it;
+ map<String, PendingRequest>::iterator it;
it = m_Requests.find(id);
if (it == m_Requests.end())
typedef shared_ptr<EndpointManager> Ptr;
typedef weak_ptr<EndpointManager> WeakPtr;
- typedef map<string, Endpoint::Ptr>::iterator Iterator;
+ typedef map<String, Endpoint::Ptr>::iterator Iterator;
EndpointManager(void);
static EndpointManager::Ptr GetInstance(void);
- void SetIdentity(const string& identity);
- string GetIdentity(void) const;
+ void SetIdentity(const String& identity);
+ String GetIdentity(void) const;
void SetSSLContext(const shared_ptr<SSL_CTX>& sslContext);
shared_ptr<SSL_CTX> GetSSLContext(void) const;
- void AddListener(const string& service);
- void AddConnection(const string& node, const string& service);
+ void AddListener(const String& service);
+ void AddConnection(const String& node, const String& service);
void RegisterEndpoint(const Endpoint::Ptr& endpoint);
void UnregisterEndpoint(const Endpoint::Ptr& endpoint);
Iterator Begin(void);
Iterator End(void);
- Endpoint::Ptr GetEndpointByIdentity(const string& identity) const;
+ Endpoint::Ptr GetEndpointByIdentity(const String& identity) const;
boost::signal<void (const EndpointManager::Ptr&, const Endpoint::Ptr&)> OnNewEndpoint;
private:
- string m_Identity;
+ String m_Identity;
shared_ptr<SSL_CTX> m_SSLContext;
vector<JsonRpcServer::Ptr> m_Servers;
vector<Endpoint::Ptr> m_PendingEndpoints;
- map<string, Endpoint::Ptr> m_Endpoints;
+ map<String, Endpoint::Ptr> m_Endpoints;
/**
* Information about a pending API request.
};
long m_NextMessageID;
- map<string, PendingRequest> m_Requests;
+ map<String, PendingRequest> m_Requests;
Timer::Ptr m_RequestTimer;
void RegisterServer(const JsonRpcServer::Ptr& server);
void UnregisterServer(const JsonRpcServer::Ptr& server);
- static bool RequestTimeoutLessComparer(const pair<string, PendingRequest>& a, const pair<string, PendingRequest>& b);
+ static bool RequestTimeoutLessComparer(const pair<String, PendingRequest>& a, const pair<String, PendingRequest>& b);
void RequestTimerHandler(void);
void NewClientHandler(const TcpClient::Ptr& client);
using namespace icinga;
-const string IcingaApplication::DefaultPidPath = "icinga.pid";
+const String IcingaApplication::DefaultPidPath = "icinga.pid";
IcingaApplication::IcingaApplication(void)
: m_PidPath(DefaultPidPath)
* @param args Command-line arguments.
* @returns An exit status.
*/
-int IcingaApplication::Main(const vector<string>& args)
+int IcingaApplication::Main(const vector<String>& args)
{
/* create console logger */
ConfigItemBuilder::Ptr consoleLogConfig = boost::make_shared<ConfigItemBuilder>();
/* periodically dump the program state */
m_RetentionTimer = boost::make_shared<Timer>();
- m_RetentionTimer->SetInterval(60);
+ m_RetentionTimer->SetInterval(10);
m_RetentionTimer->OnTimerExpired.connect(boost::bind(&IcingaApplication::DumpProgramState, this));
m_RetentionTimer->Start();
bool daemonize = false;
bool parseOpts = true;
- string configFile;
+ String configFile;
/* TODO: clean up this mess; for now it will just have to do */
- vector<string>::const_iterator it;
+ vector<String>::const_iterator it;
for (it = args.begin() + 1 ; it != args.end(); it++) {
- string arg = *it;
+ String arg = *it;
/* ignore empty arguments */
- if (arg.empty())
+ if (arg.IsEmpty())
continue;
if (arg == "--") {
throw_exception(invalid_argument("Trailing command line arguments after config filename."));
}
- if (configFile.empty())
+ if (configFile.IsEmpty())
throw_exception(invalid_argument("No config file was specified on the command line."));
- string componentDirectory = Utility::DirName(GetExePath()) + "/../lib/icinga2";
+ String componentDirectory = Utility::DirName(GetExePath()) + "/../lib/icinga2";
Component::AddSearchDir(componentDirectory);
/* load cibsync config component */
convenienceComponentConfig->SetType("Component");
convenienceComponentConfig->SetName("convenience");
convenienceComponentConfig->SetLocal(true);
- convenienceComponentConfig->Compile()->Commit();
+ //convenienceComponentConfig->Compile()->Commit();
/* load config file */
vector<ConfigItem::Ptr> configItems = ConfigCompiler::CompileFile(configFile);
if (!icingaConfig->IsLocal())
throw_exception(runtime_error("'icinga' application object must be 'local'."));
- icingaConfig->GetProperty("cert", &m_CertificateFile);
- icingaConfig->GetProperty("ca", &m_CAFile);
- icingaConfig->GetProperty("node", &m_Node);
- icingaConfig->GetProperty("service", &m_Service);
- icingaConfig->GetProperty("pidpath", &m_PidPath);
- icingaConfig->GetProperty("macros", &m_Macros);
+ icingaConfig->GetAttribute("cert", &m_CertificateFile);
+ icingaConfig->GetAttribute("ca", &m_CAFile);
+ icingaConfig->GetAttribute("node", &m_Node);
+ icingaConfig->GetAttribute("service", &m_Service);
+ icingaConfig->GetAttribute("pidpath", &m_PidPath);
+ icingaConfig->GetAttribute("macros", &m_Macros);
- string logpath;
- if (icingaConfig->GetProperty("logpath", &logpath)) {
+ String logpath;
+ icingaConfig->GetAttribute("logpath", &logpath);
+ if (!logpath.IsEmpty()) {
ConfigItemBuilder::Ptr fileLogConfig = boost::make_shared<ConfigItemBuilder>();
fileLogConfig->SetType("Logger");
fileLogConfig->SetName("main");
UpdatePidFile(GetPidPath());
- if (!GetCertificateFile().empty() && !GetCAFile().empty()) {
+ if (!GetCertificateFile().IsEmpty() && !GetCAFile().IsEmpty()) {
/* set up SSL context */
shared_ptr<X509> cert = Utility::GetX509Certificate(GetCertificateFile());
- string identity = Utility::GetCertificateCN(cert);
+ String identity = Utility::GetCertificateCN(cert);
Logger::Write(LogInformation, "icinga", "My identity: " + identity);
EndpointManager::GetInstance()->SetIdentity(identity);
}
/* create the primary RPC listener */
- string service = GetService();
- if (!service.empty())
+ String service = GetService();
+ if (!service.IsEmpty())
EndpointManager::GetInstance()->AddListener(service);
if (daemonize) {
return static_pointer_cast<IcingaApplication>(Application::GetInstance());
}
-string IcingaApplication::GetCertificateFile(void) const
+String IcingaApplication::GetCertificateFile(void) const
{
return m_CertificateFile;
}
-string IcingaApplication::GetCAFile(void) const
+String IcingaApplication::GetCAFile(void) const
{
return m_CAFile;
}
-string IcingaApplication::GetNode(void) const
+String IcingaApplication::GetNode(void) const
{
return m_Node;
}
-string IcingaApplication::GetService(void) const
+String IcingaApplication::GetService(void) const
{
return m_Service;
}
-string IcingaApplication::GetPidPath(void) const
+String IcingaApplication::GetPidPath(void) const
{
return m_PidPath;
}
IcingaApplication(void);
- int Main(const vector<string>& args);
+ int Main(const vector<String>& args);
static IcingaApplication::Ptr GetInstance(void);
- string GetCertificateFile(void) const;
- string GetCAFile(void) const;
- string GetNode(void) const;
- string GetService(void) const;
- string GetPidPath(void) const;
+ String GetCertificateFile(void) const;
+ String GetCAFile(void) const;
+ String GetNode(void) const;
+ String GetService(void) const;
+ String GetPidPath(void) const;
Dictionary::Ptr GetMacros(void) const;
time_t GetStartTime(void) const;
- static const string DefaultPidPath;
+ static const String DefaultPidPath;
private:
- string m_CertificateFile;
- string m_CAFile;
- string m_Node;
- string m_Service;
- string m_PidPath;
+ String m_CertificateFile;
+ String m_CAFile;
+ String m_Node;
+ String m_Service;
+ String m_PidPath;
Dictionary::Ptr m_Macros;
time_t m_StartTime;
using namespace icinga;
-string JsonRpcEndpoint::GetIdentity(void) const
+String JsonRpcEndpoint::GetIdentity(void) const
{
return m_Identity;
}
-string JsonRpcEndpoint::GetAddress(void) const
+String JsonRpcEndpoint::GetAddress(void) const
{
if (!m_Client)
return "<disconnected endpoint>";
return m_Client;
}
-void JsonRpcEndpoint::Connect(string node, string service, shared_ptr<SSL_CTX> sslContext)
+void JsonRpcEndpoint::Connect(String node, String service, shared_ptr<SSL_CTX> sslContext)
{
JsonRpcClient::Ptr client = boost::make_shared<JsonRpcClient>(RoleOutbound, sslContext);
SetClient(client);
RequestMessage request = message;
- string method;
+ String method;
if (!request.GetMethod(&method))
return;
if (!HasPublication(method))
return;
- string id;
+ String id;
if (request.GetID(&id))
GetEndpointManager()->SendAnycastMessage(sender, request);
else
void JsonRpcEndpoint::ClientConnectedHandler(void)
{
- string identity = Utility::GetCertificateCN(m_Client->GetPeerCertificate());
+ String identity = Utility::GetCertificateCN(m_Client->GetPeerCertificate());
- if (GetIdentity().empty() && !identity.empty()) {
+ if (GetIdentity().IsEmpty() && !identity.IsEmpty()) {
m_Identity = identity;
GetEndpointManager()->RegisterEndpoint(GetSelf());
}
typedef shared_ptr<JsonRpcEndpoint> Ptr;
typedef weak_ptr<JsonRpcEndpoint> WeakPtr;
- void Connect(string node, string service,
+ void Connect(String node, String service,
shared_ptr<SSL_CTX> sslContext);
JsonRpcClient::Ptr GetClient(void);
void SetClient(JsonRpcClient::Ptr client);
- virtual string GetIdentity(void) const;
- virtual string GetAddress(void) const;
+ virtual String GetIdentity(void) const;
+ virtual String GetAddress(void) const;
virtual bool IsLocal(void) const;
virtual bool IsConnected(void) const;
virtual void Stop(void);
private:
- string m_Identity; /**< The identity of this endpoint. */
+ String m_Identity; /**< The identity of this endpoint. */
shared_ptr<SSL_CTX> m_SSLContext;
- string m_Address;
+ String m_Address;
JsonRpcClient::Ptr m_Client;
- void SetAddress(string address);
+ void SetAddress(String address);
void NewMessageHandler(const MessagePart& message);
void ClientClosedHandler(void);
using namespace icinga;
-string VirtualEndpoint::GetIdentity(void) const
+String VirtualEndpoint::GetIdentity(void) const
{
return "__" + GetAddress();
}
-string VirtualEndpoint::GetAddress(void) const
+String VirtualEndpoint::GetAddress(void) const
{
char address[50];
sprintf(address, "virtual:%p", (void *)this);
return true;
}
-void VirtualEndpoint::RegisterTopicHandler(string topic, function<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> callback)
+void VirtualEndpoint::RegisterTopicHandler(String topic, function<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> callback)
{
- map<string, shared_ptr<boost::signal<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> > >::iterator it;
+ map<String, shared_ptr<boost::signal<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> > >::iterator it;
it = m_TopicHandlers.find(topic);
shared_ptr<boost::signal<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> > sig;
RegisterSubscription(topic);
}
-void VirtualEndpoint::UnregisterTopicHandler(string topic, function<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> callback)
+void VirtualEndpoint::UnregisterTopicHandler(String topic, function<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> callback)
{
// TODO: implement
//m_TopicHandlers[method] -= callback;
void VirtualEndpoint::ProcessRequest(Endpoint::Ptr sender, const RequestMessage& request)
{
- string method;
+ String method;
if (!request.GetMethod(&method))
return;
- map<string, shared_ptr<boost::signal<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> > >::iterator it;
+ map<String, shared_ptr<boost::signal<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> > >::iterator it;
it = m_TopicHandlers.find(method);
if (it == m_TopicHandlers.end())
typedef shared_ptr<VirtualEndpoint> Ptr;
typedef weak_ptr<VirtualEndpoint> WeakPtr;
- void RegisterTopicHandler(string topic, function<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> callback);
- void UnregisterTopicHandler(string topic, function<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> callback);
+ void RegisterTopicHandler(String topic, function<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> callback);
+ void UnregisterTopicHandler(String topic, function<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> callback);
- virtual string GetIdentity(void) const;
- virtual string GetAddress(void) const;
+ virtual String GetIdentity(void) const;
+ virtual String GetAddress(void) const;
virtual bool IsLocal(void) const;
virtual bool IsConnected(void) const;
virtual void Stop(void);
private:
- map< string, shared_ptr<boost::signal<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> > > m_TopicHandlers;
+ map< String, shared_ptr<boost::signal<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> > > m_TopicHandlers;
};
}
*/
void JsonRpcClient::SendMessage(const MessagePart& message)
{
- Variant value = message.GetDictionary();
- Netstring::WriteStringToIOQueue(this, value.Serialize());
+ Value value = message.GetDictionary();
+ NetString::WriteStringToIOQueue(this, value.Serialize());
}
/**
*/
void JsonRpcClient::DataAvailableHandler(void)
{
- string jsonString;
+ String jsonString;
- while (Netstring::ReadStringFromIOQueue(this, &jsonString)) {
+ while (NetString::ReadStringFromIOQueue(this, &jsonString)) {
try {
- Variant value = Variant::Deserialize(jsonString);
+ Value value = Value::Deserialize(jsonString);
if (!value.IsObjectType<Dictionary>())
throw_exception(invalid_argument("JSON-RPC message must be a dictionary."));
OnNewMessage(GetSelf(), MessagePart(value));
} catch (const exception& ex) {
- Logger::Write(LogCritical, "jsonrpc", "Exception while processing message from JSON-RPC client: " + string(ex.what()));
+ Logger::Write(LogCritical, "jsonrpc", "Exception while processing message from JSON-RPC client: " + String(ex.what()));
}
}
}
* @param[out] The value.
* @returns true if the value was retrieved, false otherwise.
*/
-bool MessagePart::Get(string key, MessagePart *value) const
+bool MessagePart::Get(String key, MessagePart *value) const
{
- Dictionary::Ptr dictionary;
- if (!GetDictionary()->Get(key, &dictionary))
+ Value v;
+ v = GetDictionary()->Get(key);
+
+ if (!v.IsObjectType<Dictionary>())
return false;
+ Dictionary::Ptr dictionary = v;
+
*value = MessagePart(dictionary);
return true;
}
* @param key The name of the property.
* @param value The value.
*/
-void MessagePart::Set(string key, const MessagePart& value)
+void MessagePart::Set(String key, const MessagePart& value)
{
GetDictionary()->Set(key, value.GetDictionary());
}
* @param key The name of the element.
* @returns true if the message contains the element, false otherwise.
*/
-bool MessagePart::Contains(const string& key) const
+bool MessagePart::Contains(const String& key) const
{
return GetDictionary()->Contains(key);
}
* @returns true if the value was retrieved, false otherwise.
*/
template<typename T>
- bool Get(string key, T *value) const
+ bool Get(String key, T *value) const
{
- return GetDictionary()->Get(key, value);
+ Value v =GetDictionary()->Get(key);
+
+ if (v.IsEmpty())
+ return false;
+
+ *value = static_cast<T>(v);
+ return true;
}
/**
* @param value The value.
*/
template<typename T>
- void Set(string key, const T& value)
+ void Set(String key, const T& value)
{
GetDictionary()->Set(key, value);
}
- bool Get(string key, MessagePart *value) const;
- void Set(string key, const MessagePart& value);
+ bool Get(String key, MessagePart *value) const;
+ void Set(String key, const MessagePart& value);
/**
* Adds an item to the message using an automatically generated property name.
void Add(const MessagePart& value);
- bool Contains(const string& key) const;
+ bool Contains(const String& key) const;
Dictionary::Iterator Begin(void);
Dictionary::Iterator End(void);
* @param[out] value The value.
* @returns true if the value was retrieved, false otherwise.
*/
- inline bool GetVersion(string *value) const
+ inline bool GetVersion(String *value) const
{
return Get("jsonrpc", value);
}
*
* @param value The version.
*/
- inline void SetVersion(const string& value)
+ inline void SetVersion(const String& value)
{
Set("jsonrpc", value);
}
* @param[out] value The method.
* @returns true if the value was retrieved, false otherwise.
*/
- inline bool GetMethod(string *value) const
+ inline bool GetMethod(String *value) const
{
return Get("method", value);
}
*
* @param value The method.
*/
- inline void SetMethod(const string& value)
+ inline void SetMethod(const String& value)
{
Set("method", value);
}
* @param[out] value The ID.
* @return true if the value was retrieved, false otherwise.
*/
- inline bool GetID(string *value) const
+ inline bool GetID(String *value) const
{
return Get("id", value);
}
*
* @param value The ID.
*/
- inline void SetID(const string& value)
+ inline void SetID(const String& value)
{
Set("id", value);
}
* @param[out] value The value.
* @returns true if the value was retrieved, false otherwise.
*/
- inline bool GetVersion(string *value) const
+ inline bool GetVersion(String *value) const
{
return Get("jsonrpc", value);
}
*
* @param value The version.
*/
- inline void SetVersion(const string& value)
+ inline void SetVersion(const String& value)
{
Set("jsonrpc", value);
}
* @param[out] value The error message.
* @returns true if the value was retrieved, false otherwise.
*/
- bool GetError(string *value) const
+ bool GetError(String *value) const
{
return Get("error", value);
}
*
* @param value The error message.
*/
- void SetError(const string& value)
+ void SetError(const String& value)
{
Set("error", value);
}
* @param[out] value The ID.
* @return true if the value was retrieved, false otherwise.
*/
- bool GetID(string *value) const
+ bool GetID(String *value) const
{
return Get("id", value);
}
*
* @param value The ID.
*/
- void SetID(const string& value)
+ void SetID(const String& value)
{
Set("id", value);
}
if (str)
{
if (fabs(floor(d)-d)<=DBL_EPSILON) sprintf(str,"%.0f",d);
- else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%.16e",d);
- else sprintf(str,"%f",d);
+ else sprintf(str,"%.*e",(int)log10(d) + 6,d);
}
}
return str;