diff --git a/components/Makefile.am b/components/Makefile.am index b49409e38..092faf4a9 100644 --- a/components/Makefile.am +++ b/components/Makefile.am @@ -6,7 +6,6 @@ SUBDIRS = \ compat \ delegation \ demo \ - ido_log \ ido_mysql \ livestatus \ notification \ diff --git a/components/ido_log/.gitignore b/components/ido_log/.gitignore deleted file mode 100644 index f7032c2ff..000000000 --- a/components/ido_log/.gitignore +++ /dev/null @@ -1 +0,0 @@ -ido_log-type.cpp diff --git a/components/ido_log/Makefile.am b/components/ido_log/Makefile.am deleted file mode 100644 index 6cb07b291..000000000 --- a/components/ido_log/Makefile.am +++ /dev/null @@ -1,38 +0,0 @@ -## Process this file with automake to produce Makefile.in - -pkglib_LTLIBRARIES = \ - libido_log.la - -EXTRA_DIST = \ - ido_log-type.conf - -.conf.cpp: $(top_builddir)/tools/mkembedconfig/mkembedconfig.c - $(top_builddir)/tools/mkembedconfig/mkembedconfig $< $@ - -libido_log_la_SOURCES = \ - ido_log-type.cpp \ - logdbconnection.cpp \ - logdbconnection.h - -libido_log_la_CPPFLAGS = \ - $(LTDLINCL) \ - $(BOOST_CPPFLAGS) \ - -I${top_srcdir}/lib \ - -I${top_srcdir}/components - -libido_log_la_LDFLAGS = \ - $(BOOST_LDFLAGS) \ - -module \ - -no-undefined \ - @RELEASE_INFO@ \ - @VERSION_INFO@ - -libido_log_la_LIBADD = \ - $(BOOST_SIGNALS_LIB) \ - $(BOOST_THREAD_LIB) \ - $(BOOST_SYSTEM_LIB) \ - ${top_builddir}/lib/base/libbase.la \ - ${top_builddir}/lib/config/libconfig.la \ - ${top_builddir}/lib/remoting/libremoting.la \ - ${top_builddir}/lib/icinga/libicinga.la \ - ${top_builddir}/lib/ido/libido.la diff --git a/components/ido_log/ido_log-type.conf b/components/ido_log/ido_log-type.conf deleted file mode 100644 index a983b7743..000000000 --- a/components/ido_log/ido_log-type.conf +++ /dev/null @@ -1,28 +0,0 @@ -/****************************************************************************** - * 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. * - ******************************************************************************/ - -type MysqlDbConnection { - %attribute string "host", - %attribute number "port", - - %attribute string "user", - %attribute string "password", - - %attribute string "database", -} diff --git a/components/ido_log/ido_log.vcxproj b/components/ido_log/ido_log.vcxproj deleted file mode 100644 index fcf55e5d2..000000000 --- a/components/ido_log/ido_log.vcxproj +++ /dev/null @@ -1,193 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {2E6C1133-730F-4875-A72C-B455B1DD4C5C} - Win32Proj - demo - - - - DynamicLibrary - true - MultiByte - - - DynamicLibrary - true - MultiByte - - - DynamicLibrary - false - true - MultiByte - - - DynamicLibrary - false - true - MultiByte - - - - - - - - - - - - - - - - - - - true - $(SolutionDir)\lib;$(SolutionDir)\components;$(IncludePath) - $(SolutionDir)$(Platform)\$(Configuration)\;$(LibraryPath) - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - - - true - $(SolutionDir)\lib;$(SolutionDir)\components;$(IncludePath) - $(SolutionDir)$(Platform)\$(Configuration)\;$(LibraryPath) - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - - - false - $(SolutionDir)\lib;$(SolutionDir)\components;$(IncludePath) - $(SolutionDir)$(Platform)\$(Configuration)\;$(LibraryPath) - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - - - false - $(SolutionDir)\lib;$(SolutionDir)\components;$(IncludePath) - $(SolutionDir)$(Platform)\$(Configuration)\;$(LibraryPath) - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - - - - Disabled - _DEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - false - true - NotUsing - - - Windows - true - base.lib;config.lib;remoting.lib;icinga.lib;%(AdditionalDependencies) - - - - - Disabled - _DEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;_WINDOWS;%(PreprocessorDefinitions) - Level3 - false - true - NotUsing - - - Windows - true - base.lib;config.lib;remoting.lib;icinga.lib;%(AdditionalDependencies) - - - - - MaxSpeed - true - true - NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - false - true - NotUsing - - - Windows - true - true - true - base.lib;config.lib;remoting.lib;icinga.lib;%(AdditionalDependencies) - - - - - MaxSpeed - true - true - NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - Level3 - false - true - NotUsing - - - Windows - true - true - true - base.lib;config.lib;remoting.lib;icinga.lib;%(AdditionalDependencies) - - - - - - - - - - - - - Document - "$(SolutionDir)$(Platform)\$(Configuration)\mkembedconfig.exe" "%(Identity)" "%(Filename).cpp" - Preparing config fragment for embedding - "$(SolutionDir)$(Platform)\$(Configuration)\mkembedconfig.exe" "%(Identity)" "%(Filename).cpp" - Preparing config fragment for embedding - "$(SolutionDir)$(Platform)\$(Configuration)\mkembedconfig.exe" "%(Identity)" "%(Filename).cpp" - Preparing config fragment for embedding - "$(SolutionDir)$(Platform)\$(Configuration)\mkembedconfig.exe" "%(Identity)" "%(Filename).cpp" - Preparing config fragment for embedding - %(Filename).cpp;%(Outputs) - %(Filename).cpp;%(Outputs) - %(Filename).cpp;%(Outputs) - %(Filename).cpp;%(Outputs) - $(SolutionDir)\tools\mkembedconfig\mkembedconfig.c - $(SolutionDir)\tools\mkembedconfig\mkembedconfig.c - $(SolutionDir)\tools\mkembedconfig\mkembedconfig.c - $(SolutionDir)\tools\mkembedconfig\mkembedconfig.c - - - - - - \ No newline at end of file diff --git a/components/ido_log/ido_log.vcxproj.filters b/components/ido_log/ido_log.vcxproj.filters deleted file mode 100644 index 922435a52..000000000 --- a/components/ido_log/ido_log.vcxproj.filters +++ /dev/null @@ -1,32 +0,0 @@ - - - - - Headerdateien - - - Headerdateien - - - - - {11a495bf-a705-4766-b3d3-9b5db266a6ef} - - - {1fb6337f-a17f-46ea-9316-2d800a94b53d} - - - - - Quelldateien - - - Quelldateien - - - - - Quelldateien - - - \ No newline at end of file diff --git a/components/ido_log/logdbconnection.cpp b/components/ido_log/logdbconnection.cpp deleted file mode 100644 index 654be4801..000000000 --- a/components/ido_log/logdbconnection.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/****************************************************************************** - * 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 "ido_log/logdbconnection.h" -#include "base/logger_fwd.h" - -using namespace icinga; - -REGISTER_TYPE(LogDbConnection); - -LogDbConnection::LogDbConnection(const Dictionary::Ptr& serializedUpdate) - : DbConnection(serializedUpdate) -{ - /* We're already "connected" to our database... Let's do this. */ - UpdateAllObjects(); -} - -void LogDbConnection::UpdateObject(const DbObject::Ptr& dbobj, DbUpdateType kind) -{ - Log(LogInformation, "ido_log", "Object '" + dbobj->GetObject()->GetName() + "' was updated."); -} diff --git a/components/ido_log/logdbconnection.h b/components/ido_log/logdbconnection.h deleted file mode 100644 index 290a8b347..000000000 --- a/components/ido_log/logdbconnection.h +++ /dev/null @@ -1,47 +0,0 @@ -/****************************************************************************** - * 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. * - ******************************************************************************/ - -#ifndef LOGDBCONNECTION_H -#define LOGDBCONNECTION_H - -#include "base/dynamictype.h" -#include "ido/dbconnection.h" - -namespace icinga -{ - -/** - * A MySQL database connection. - * - * @ingroup ido - */ -class LogDbConnection : public DbConnection -{ -public: - typedef shared_ptr Ptr; - typedef weak_ptr WeakPtr; - - LogDbConnection(const Dictionary::Ptr& serializedUpdate); - - virtual void UpdateObject(const DbObject::Ptr& dbobj, DbUpdateType kind); -}; - -} - -#endif /* LOGDBCONNECTION_H */ diff --git a/components/ido_mysql/mysqldbconnection.cpp b/components/ido_mysql/mysqldbconnection.cpp index 24037b554..0a52b25da 100644 --- a/components/ido_mysql/mysqldbconnection.cpp +++ b/components/ido_mysql/mysqldbconnection.cpp @@ -58,6 +58,11 @@ MysqlDbConnection::MysqlDbConnection(const Dictionary::Ptr& serializedUpdate) void MysqlDbConnection::Stop(void) { boost::mutex::scoped_lock lock(m_ConnectionMutex); + + if (!m_Connected) + return; + + Query("COMMIT"); mysql_close(&m_Connection); } @@ -220,9 +225,8 @@ Dictionary::Ptr MysqlDbConnection::FetchRow(MYSQL_RES *result) for (field = mysql_fetch_field(result), i = 0; field; field = mysql_fetch_field(result), i++) { Value value; - if (field) { + if (field) value = String(row[i], row[i] + lengths[i]); - } dict->Set(field->name, value); } @@ -230,85 +234,147 @@ Dictionary::Ptr MysqlDbConnection::FetchRow(MYSQL_RES *result) return dict; } -void MysqlDbConnection::UpdateObject(const DbObject::Ptr& dbobj, DbUpdateType kind) { +void MysqlDbConnection::ActivateObject(const DbObject::Ptr& dbobj) +{ boost::mutex::scoped_lock lock(m_ConnectionMutex); + DbReference dbref = GetReference(dbobj); + std::ostringstream qbuf; - /* Check if we can handle updates right now */ - if (!m_Connected) - return; + if (!dbref.IsValid()) { + qbuf << "INSERT INTO icinga_objects (instance_id, objecttype_id, name1, name2, is_active) VALUES (" + << static_cast(m_InstanceID) << ", " << dbobj->GetType()->GetTypeID() << ", " + << "'" << Escape(dbobj->GetName1()) << "', '" << Escape(dbobj->GetName2()) << "', 1)"; + Query(qbuf.str()); + SetReference(dbobj, GetInsertID()); + } else { + qbuf << "UPDATE icinga_objects SET is_active = 1 WHERE object_id = " << static_cast(dbref); + Query(qbuf.str()); + } +} + +void MysqlDbConnection::DeactivateObject(const DbObject::Ptr& dbobj) +{ + boost::mutex::scoped_lock lock(m_ConnectionMutex); DbReference dbref = GetReference(dbobj); - if (kind == DbObjectRemoved) { - if (!dbref.IsValid()) - return; + if (!dbref.IsValid()) + return; - std::ostringstream qbuf; - qbuf << "DELETE FROM icinga_" << dbobj->GetType()->GetTable() << "s WHERE id = " << static_cast(dbref); - Log(LogWarning, "ido_mysql", "Query: " + qbuf.str()); - } + std::ostringstream qbuf; + qbuf << "UPDATE icinga_objects SET is_active = 0 WHERE object_id = " << static_cast(dbref); + Query(qbuf.str()); - if (kind == DbObjectCreated) { - std::ostringstream q1buf; + SetReference(dbobj, DbReference()); +} - if (!dbref.IsValid()) { - q1buf << "INSERT INTO icinga_objects (instance_id, objecttype_id, name1, name2, is_active) VALUES (" - << static_cast(m_InstanceID) << ", " << dbobj->GetType()->GetTypeID() << ", " - << "'" << Escape(dbobj->GetName1()) << "', '" << Escape(dbobj->GetName2()) << "', 1)"; - Query(q1buf.str()); - dbref = GetInsertID(); - } else if (kind == DbObjectCreated) { - q1buf << "UPDATE icinga_objects SET is_active = 1 WHERE object_id = " << static_cast(dbref); - Query(q1buf.str()); +bool MysqlDbConnection::FieldToString(const String& key, const Value& value, Value *result) +{ + *result = value; + + if (value.IsObjectType()) { + DbObject::Ptr dbobjcol = DbObject::GetOrCreateByObject(value); + + if (!dbobjcol) { + *result = 0; + return true; } - Dictionary::Ptr fields = dbobj->GetFields(); + DbReference dbrefcol = GetReference(dbobjcol); - if (!fields) - return; + if (!dbrefcol.IsValid()) { + ActivateObject(dbobjcol); + dbrefcol = GetReference(dbobjcol); + + if (!dbrefcol.IsValid()) + return false; + } + + *result = static_cast(dbrefcol); + } + + if (key == "instance_id") + *result = static_cast(m_InstanceID); + + return true; +} + +void MysqlDbConnection::ExecuteQuery(const DbQuery& query) +{ + std::ostringstream qbuf; + + switch (query.Type) { + case DbQueryInsert: + qbuf << "INSERT INTO " << query.Table; + break; + case DbQueryUpdate: + qbuf << "UPDATE " << query.Table << "SET"; + break; + case DbQueryDelete: + qbuf << "DELETE FROM " << query.Table; + break; + default: + ASSERT(!"Invalid query type."); + } + + if (query.Type == DbQueryInsert || query.Type == DbQueryUpdate) { String cols; String values; - ObjectLock olock(fields); + ObjectLock olock(query.Fields); String key; Value value; - BOOST_FOREACH(boost::tie(key, value), fields) { - if (value.IsObjectType()) { - DbObject::Ptr dbobjcol = DbObject::GetOrCreateByObject(value); + bool first = true; + BOOST_FOREACH(boost::tie(key, value), query.Fields) { + if (!FieldToString(key, value, &value)) + return; - if (!dbobjcol) - return; - - DbReference dbrefcol = GetReference(dbobjcol); - - if (!dbrefcol.IsValid()) { - UpdateObject(dbobjcol, DbObjectCreated); - - dbrefcol = GetReference(dbobjcol); - - if (!dbrefcol.IsValid()) - return; + if (query.Type == DbQueryInsert) { + if (!first) { + cols += ", "; + values += ", "; } - value = static_cast(dbrefcol); + cols += key; + values += "'" + Convert::ToString(value) + "'"; + } else { + if (!first) + qbuf << ", "; + + qbuf << " " << key << " = '" << Escape(value) << "'"; } - cols += ", " + key; - values += ", '" + Convert::ToString(value) + "'"; + if (first) + first = false; } - std::ostringstream q2buf; - q2buf << "DELETE FROM icinga_" << dbobj->GetType()->GetTable() << "s WHERE " << dbobj->GetType()->GetTable() << "_object_id = " << static_cast(dbref); - Query(q2buf.str()); - - std::ostringstream q3buf; - q3buf << "INSERT INTO icinga_" << dbobj->GetType()->GetTable() - << "s (instance_id, " << dbobj->GetType()->GetTable() << "_object_id" << cols << ") VALUES (" - << static_cast(m_InstanceID) << ", " << static_cast(dbref) << values << ")"; - Query(q3buf.str()); + if (query.Type == DbQueryInsert) + qbuf << " (" << cols << ") VALUES (" << values << ")"; } - // TODO: Object and status updates + if (query.WhereCriteria) { + qbuf << " WHERE "; + + ObjectLock olock(query.WhereCriteria); + + String key; + Value value; + bool first = true; + BOOST_FOREACH(boost::tie(key, value), query.WhereCriteria) { + if (!FieldToString(Empty, value, &value)) + return; + + if (!first) + qbuf << " AND "; + + qbuf << key << " = '" << Escape(value) << "'"; + + if (first) + first = false; + } + } + + Query(qbuf.str()); } diff --git a/components/ido_mysql/mysqldbconnection.h b/components/ido_mysql/mysqldbconnection.h index 224b00f48..bc3b2b018 100644 --- a/components/ido_mysql/mysqldbconnection.h +++ b/components/ido_mysql/mysqldbconnection.h @@ -43,7 +43,12 @@ public: MysqlDbConnection(const Dictionary::Ptr& serializedUpdate); virtual void Stop(void); - virtual void UpdateObject(const DbObject::Ptr& dbobj, DbUpdateType kind); + //virtual void UpdateObject(const DbObject::Ptr& dbobj, DbUpdateType kind); + +protected: + virtual void ActivateObject(const DbObject::Ptr& dbobj); + virtual void DeactivateObject(const DbObject::Ptr& dbobj); + virtual void ExecuteQuery(const DbQuery& query); private: Attribute m_Host; @@ -68,6 +73,8 @@ private: String Escape(const String& s); Dictionary::Ptr FetchRow(MYSQL_RES *result); + bool FieldToString(const String& key, const Value& value, Value *result); + void TxTimerHandler(void); void ReconnectTimerHandler(void); }; diff --git a/configure.ac b/configure.ac index 3c74b61a1..af54c31dc 100644 --- a/configure.ac +++ b/configure.ac @@ -123,7 +123,6 @@ components/checker/Makefile components/compat/Makefile components/delegation/Makefile components/demo/Makefile -components/ido_log/Makefile components/ido_mysql/Makefile components/livestatus/Makefile components/notification/Makefile diff --git a/lib/ido/Makefile.am b/lib/ido/Makefile.am index 211dc4d0f..51d27cbfc 100644 --- a/lib/ido/Makefile.am +++ b/lib/ido/Makefile.am @@ -14,6 +14,8 @@ libido_la_SOURCES = \ dbconnection.h \ dbobject.cpp \ dbobject.h \ + dbquery.cpp \ + dbquery.h \ dbreference.cpp \ dbreference.h \ dbtype.cpp \ diff --git a/lib/ido/dbconnection.cpp b/lib/ido/dbconnection.cpp index 1a155f91b..bd22ed258 100644 --- a/lib/ido/dbconnection.cpp +++ b/lib/ido/dbconnection.cpp @@ -29,7 +29,9 @@ DbConnection::DbConnection(const Dictionary::Ptr& serializedUpdate) void DbConnection::Start(void) { - DbObject::OnObjectUpdated.connect(boost::bind(&DbConnection::InternalUpdateObject, this, _1, _2)); + DbObject::OnRegistered.connect(boost::bind(&DbConnection::ActivateObject, this, _1)); + DbObject::OnUnregistered.connect(boost::bind(&DbConnection::DeactivateObject, this, _1)); + DbObject::OnQuery.connect(boost::bind(&DbConnection::ExecuteQuery, this, _1)); } void DbConnection::SetReference(const DbObject::Ptr& dbobj, const DbReference& dbref) @@ -52,19 +54,11 @@ DbReference DbConnection::GetReference(const DbObject::Ptr& dbobj) const return it->second; } -void DbConnection::UpdateObject(const DbObject::Ptr&, DbUpdateType) +void DbConnection::ExecuteQuery(const DbQuery&) { /* Default handler does nothing. */ } -void DbConnection::InternalUpdateObject(const DbObject::Ptr& dbobj, DbUpdateType kind) -{ - UpdateObject(dbobj, kind); - - if (kind == DbObjectRemoved) - SetReference(dbobj, DbReference()); -} - void DbConnection::UpdateAllObjects(void) { DynamicType::Ptr type; @@ -72,8 +66,11 @@ void DbConnection::UpdateAllObjects(void) BOOST_FOREACH(const DynamicObject::Ptr& object, dt->GetObjects()) { DbObject::Ptr dbobj = DbObject::GetOrCreateByObject(object); - if (dbobj) - UpdateObject(dbobj, DbObjectCreated); + if (dbobj) { + ActivateObject(dbobj); + dbobj->SendConfigUpdate(); + dbobj->SendStatusUpdate(); + } } } } diff --git a/lib/ido/dbconnection.h b/lib/ido/dbconnection.h index 804527f52..8e6e377bd 100644 --- a/lib/ido/dbconnection.h +++ b/lib/ido/dbconnection.h @@ -22,6 +22,7 @@ #include "base/dynamicobject.h" #include "ido/dbobject.h" +#include "ido/dbquery.h" namespace icinga { @@ -44,13 +45,13 @@ public: protected: virtual void Start(void); - virtual void UpdateObject(const DbObject::Ptr& dbobj, DbUpdateType kind) = 0; + virtual void ExecuteQuery(const DbQuery& query) = 0; + virtual void ActivateObject(const DbObject::Ptr& dbobj) = 0; + virtual void DeactivateObject(const DbObject::Ptr& dbobj) = 0; void UpdateAllObjects(void); private: - void InternalUpdateObject(const DbObject::Ptr& dbobj, DbUpdateType kind); - std::map m_References; }; diff --git a/lib/ido/dbobject.cpp b/lib/ido/dbobject.cpp index 419aee5f3..6fb073058 100644 --- a/lib/ido/dbobject.cpp +++ b/lib/ido/dbobject.cpp @@ -26,7 +26,9 @@ using namespace icinga; -boost::signals2::signal DbObject::OnObjectUpdated; +boost::signals2::signal DbObject::OnRegistered; +boost::signals2::signal DbObject::OnUnregistered; +boost::signals2::signal DbObject::OnQuery; DbObject::DbObject(const shared_ptr& type, const String& name1, const String& name2) : m_Name1(name1), m_Name2(name2), m_Type(type) @@ -36,8 +38,8 @@ void DbObject::StaticInitialize(void) { DynamicObject::OnRegistered.connect(boost::bind(&DbObject::ObjectRegisteredHandler, _1)); DynamicObject::OnUnregistered.connect(boost::bind(&DbObject::ObjectUnregisteredHandler, _1)); - DynamicObject::OnTransactionClosing.connect(boost::bind(&DbObject::TransactionClosingHandler, _1, _2)); - DynamicObject::OnFlushObject.connect(boost::bind(&DbObject::FlushObjectHandler, _1, _2)); +// DynamicObject::OnTransactionClosing.connect(boost::bind(&DbObject::TransactionClosingHandler, _1, _2)); +// DynamicObject::OnFlushObject.connect(boost::bind(&DbObject::FlushObjectHandler, _1, _2)); } void DbObject::SetObject(const DynamicObject::Ptr& object) @@ -65,9 +67,51 @@ DbType::Ptr DbObject::GetType(void) const return m_Type; } -void DbObject::SendUpdate(DbUpdateType kind) +void DbObject::SendConfigUpdate(void) { - OnObjectUpdated(GetSelf(), kind); + DbQuery query1; + query1.Table = "icinga_" + GetType()->GetTable() + "s"; + query1.Type = DbQueryDelete; + query1.WhereCriteria = boost::make_shared(); + query1.WhereCriteria->Set(GetType()->GetTable() + "_object_id", GetObject()); + OnQuery(query1); + + DbQuery query2; + query2.Table = "icinga_" + GetType()->GetTable() + "s"; + query2.Type = DbQueryInsert; + + query2.Fields = GetConfigFields(); + + if (!query2.Fields) + return; + + query2.Fields->Set(GetType()->GetTable() + "_object_id", GetObject()); + query2.Fields->Set("instance_id", 0); /* DbConnection class fills in real ID */ + OnQuery(query2); +} + +void DbObject::SendStatusUpdate(void) +{ + DbQuery query1; + query1.Table = "icinga_" + GetType()->GetTable() + "status"; + query1.Type = DbQueryDelete; + query1.WhereCriteria = boost::make_shared(); + query1.WhereCriteria->Set(GetType()->GetTable() + "_object_id", GetObject()); + OnQuery(query1); + + DbQuery query2; + query2.Table = "icinga_" + GetType()->GetTable() + "status"; + query2.Type = DbQueryInsert; + + query2.Fields = GetStatusFields(); + + if (!query2.Fields) + return; + + query2.Fields->Set(GetType()->GetTable() + "_object_id", GetObject()); + query2.Fields->Set("instance_id", 0); /* DbConnection class fills in real ID */ + query2.Fields->Set("status_update_time", Utility::FormatDateTime("%Y-%m-%d %H:%M:%S", Utility::GetTime())); + OnQuery(query2); } DbObject::Ptr DbObject::GetOrCreateByObject(const DynamicObject::Ptr& object) @@ -117,7 +161,10 @@ void DbObject::ObjectRegisteredHandler(const DynamicObject::Ptr& object) if (!dbobj) return; - dbobj->SendUpdate(DbObjectCreated); + OnRegistered(dbobj); + + dbobj->SendConfigUpdate(); + dbobj->SendStatusUpdate(); } void DbObject::ObjectUnregisteredHandler(const DynamicObject::Ptr& object) @@ -127,7 +174,8 @@ void DbObject::ObjectUnregisteredHandler(const DynamicObject::Ptr& object) if (!dbobj) return; - dbobj->SendUpdate(DbObjectRemoved); + OnUnregistered(dbobj); + //dbobj->SendUpdate(DbObjectRemoved); { ObjectLock olock(object); @@ -135,24 +183,24 @@ void DbObject::ObjectUnregisteredHandler(const DynamicObject::Ptr& object) } } -void DbObject::TransactionClosingHandler(double tx, const std::set& modifiedObjects) -{ - BOOST_FOREACH(const DynamicObject::WeakPtr& wobject, modifiedObjects) { - DynamicObject::Ptr object = wobject.lock(); - - if (!object) - continue; - - FlushObjectHandler(tx, object); - } -} - -void DbObject::FlushObjectHandler(double tx, const DynamicObject::Ptr& object) -{ - DbObject::Ptr dbobj = GetOrCreateByObject(object); - - if (!dbobj) - return; - - dbobj->SendUpdate(); -} +//void DbObject::TransactionClosingHandler(double tx, const std::set& modifiedObjects) +//{ +// BOOST_FOREACH(const DynamicObject::WeakPtr& wobject, modifiedObjects) { +// DynamicObject::Ptr object = wobject.lock(); +// +// if (!object) +// continue; +// +// FlushObjectHandler(tx, object); +// } +//} +// +//void DbObject::FlushObjectHandler(double tx, const DynamicObject::Ptr& object) +//{ +// DbObject::Ptr dbobj = GetOrCreateByObject(object); +// +// if (!dbobj) +// return; +// +// dbobj->SendUpdate(); +//} diff --git a/lib/ido/dbobject.h b/lib/ido/dbobject.h index d3738febe..c2a124622 100644 --- a/lib/ido/dbobject.h +++ b/lib/ido/dbobject.h @@ -20,17 +20,17 @@ #ifndef DBOBJECT_H #define DBOBJECT_H -#include "dbreference.h" +#include "ido/dbreference.h" +#include "ido/dbquery.h" #include "base/dynamicobject.h" #include namespace icinga { -enum DbUpdateType +enum DbObjectUpdateType { DbObjectCreated, - DbObjectUpdated, DbObjectRemoved }; @@ -53,13 +53,17 @@ public: String GetName2(void) const; boost::shared_ptr GetType(void) const; - virtual Dictionary::Ptr GetFields(void) const = 0; + virtual Dictionary::Ptr GetConfigFields(void) const = 0; + virtual Dictionary::Ptr GetStatusFields(void) const = 0; static DbObject::Ptr GetOrCreateByObject(const DynamicObject::Ptr& object); - static boost::signals2::signal OnObjectUpdated; + static boost::signals2::signal OnRegistered; + static boost::signals2::signal OnUnregistered; + static boost::signals2::signal OnQuery; - void SendUpdate(DbUpdateType kind = DbObjectUpdated); + void SendConfigUpdate(void); + void SendStatusUpdate(void); protected: DbObject(const boost::shared_ptr& type, const String& name1, const String& name2); @@ -76,8 +80,8 @@ private: static void ObjectRegisteredHandler(const DynamicObject::Ptr& object); static void ObjectUnregisteredHandler(const DynamicObject::Ptr& object); - static void TransactionClosingHandler(double tx, const std::set& modifiedObjects); - static void FlushObjectHandler(double tx, const DynamicObject::Ptr& object); + //static void TransactionClosingHandler(double tx, const std::set& modifiedObjects); + //static void FlushObjectHandler(double tx, const DynamicObject::Ptr& object); friend class DbType; }; diff --git a/lib/ido/dbtype.h b/lib/ido/dbtype.h index ebf0bd3bd..005d06f08 100644 --- a/lib/ido/dbtype.h +++ b/lib/ido/dbtype.h @@ -32,7 +32,7 @@ namespace icinga * * @ingroup ido */ -struct DbType : public Object +class DbType : public Object { public: DECLARE_PTR_TYPEDEFS(DbType); diff --git a/lib/ido/hostdbobject.cpp b/lib/ido/hostdbobject.cpp index d51329ee6..160653d2f 100644 --- a/lib/ido/hostdbobject.cpp +++ b/lib/ido/hostdbobject.cpp @@ -20,6 +20,9 @@ #include "ido/hostdbobject.h" #include "ido/dbtype.h" #include "icinga/host.h" +#include "icinga/service.h" +#include "icinga/checkcommand.h" +#include using namespace icinga; @@ -29,12 +32,189 @@ HostDbObject::HostDbObject(const String& name1, const String& name2) : DbObject(DbType::GetByName("Host"), name1, name2) { } -Dictionary::Ptr HostDbObject::GetFields(void) const +Dictionary::Ptr HostDbObject::GetConfigFields(void) const { Dictionary::Ptr fields = boost::make_shared(); Host::Ptr host = static_pointer_cast(GetObject()); + Service::Ptr service = host->GetHostCheckService(); + + if (!service) + return Empty; + + fields->Set("alias", host->GetName()); fields->Set("display_name", host->GetDisplayName()); + fields->Set("check_command_object_id", service->GetCheckCommand()); + fields->Set("check_command_args", Empty); + fields->Set("check_interval", service->GetCheckInterval() / 60); + fields->Set("retry_interval", service->GetRetryInterval() / 60); + fields->Set("max_check_attempts", service->GetMaxCheckAttempts()); + + fields->Set("address", Empty); + fields->Set("address6", Empty); + fields->Set("eventhandler_command_object_id", Empty); + fields->Set("eventhandler_command_args", Empty); + fields->Set("notification_timeperiod_object_id", Empty); + fields->Set("check_timeperiod_object_id", Empty); + fields->Set("failure_prediction_options", Empty); + fields->Set("first_notification_delay", Empty); + fields->Set("notification_interval", Empty); + fields->Set("notify_on_down", Empty); + fields->Set("notify_on_unreachable", Empty); + fields->Set("notify_on_recovery", Empty); + fields->Set("notify_on_flapping", Empty); + fields->Set("notify_on_downtime", Empty); + fields->Set("stalk_on_up", Empty); + fields->Set("stalk_on_down", Empty); + fields->Set("stalk_on_unreachable", Empty); + fields->Set("flap_detection_enabled", Empty); + fields->Set("flap_detection_on_up", Empty); + fields->Set("flap_detection_on_down", Empty); + fields->Set("flap_detection_on_unreachable", Empty); + fields->Set("low_flap_threshold", Empty); + fields->Set("high_flap_threshold", Empty); + fields->Set("process_performance_data", Empty); + fields->Set("freshness_checks_enabled", Empty); + fields->Set("freshness_threshold", Empty); + fields->Set("passive_checks_enabled", Empty); + fields->Set("event_handler_enabled", Empty); + fields->Set("active_checks_enabled", Empty); + fields->Set("retain_status_information", 1); + fields->Set("retain_nonstatus_information", 1); + fields->Set("notifications_enabled", 1); + fields->Set("obsess_over_host", 0); + fields->Set("failure_prediction_enabled", 0); + fields->Set("notes", Empty); + fields->Set("notes_url", Empty); + fields->Set("action_url", Empty); + fields->Set("icon_image", Empty); + fields->Set("icon_image_alt", Empty); + fields->Set("vrml_image", Empty); + fields->Set("statusmap_image", Empty); + fields->Set("have_2d_coords", Empty); + fields->Set("x_2d", Empty); + fields->Set("y_2d", Empty); + fields->Set("have_3d_coords", Empty); + fields->Set("x_3d", Empty); + fields->Set("y_3d", Empty); + fields->Set("z_3d", Empty); + + return fields; +} + +Dictionary::Ptr HostDbObject::GetStatusFields(void) const +{ + Dictionary::Ptr fields = boost::make_shared(); + Host::Ptr host = static_pointer_cast(GetObject()); + Service::Ptr service = host->GetHostCheckService(); + + if (!service) + return Empty; + + String raw_output; + String output; + String long_output; + String perfdata; + double schedule_end = -1; + + String check_period_str; + TimePeriod::Ptr check_period = service->GetCheckPeriod(); + if (check_period) + check_period_str = check_period->GetName(); + else + check_period_str = "24x7"; + + Dictionary::Ptr cr = service->GetLastCheckResult(); + + if (cr) { + raw_output = cr->Get("output"); + size_t line_end = raw_output.Find("\n"); + + output = raw_output.SubStr(0, line_end); + + if (line_end > 0 && line_end != String::NPos) + long_output = raw_output.SubStr(line_end+1, raw_output.GetLength()); + + boost::algorithm::replace_all(output, "\n", "\\n"); + + schedule_end = cr->Get("schedule_end"); + + perfdata = cr->Get("performance_data_raw"); + boost::algorithm::replace_all(perfdata, "\n", "\\n"); + } + + int state = service->GetState(); + + if (state > StateUnknown) + state = StateUnknown; + +// if (type == CompatTypeHost) { + if (state == StateOK || state == StateWarning) + state = 0; /* UP */ + else + state = 1; /* DOWN */ + + if (!host->IsReachable()) + state = 2; /* UNREACHABLE */ +// } + + double last_notification = 0; + double next_notification = 0; + int notification_number = 0; + BOOST_FOREACH(const Notification::Ptr& notification, service->GetNotifications()) { + if (notification->GetLastNotification() > last_notification) + last_notification = notification->GetLastNotification(); + + if (notification->GetNextNotification() < next_notification) + next_notification = notification->GetNextNotification(); + + if (notification->GetNotificationNumber() > notification_number) + notification_number = notification->GetNotificationNumber(); + } + fields->Set("output", output); + fields->Set("long_output", long_output); + fields->Set("perfdata", perfdata); + fields->Set("current_state", state); + fields->Set("has_been_checked", (service->GetLastCheckResult() ? 1 : 0)); + fields->Set("should_be_scheduled", 1); + fields->Set("current_check_attempt", service->GetCurrentCheckAttempt()); + fields->Set("max_check_attempts", service->GetMaxCheckAttempts()); + fields->Set("last_check", schedule_end); + fields->Set("next_check", service->GetNextCheck()); + fields->Set("check_type", Empty); + fields->Set("last_state_change", Empty); + fields->Set("last_hard_state_change", Empty); + fields->Set("last_hard_state", Empty); + fields->Set("last_time_up", Empty); + fields->Set("last_time_down", Empty); + fields->Set("last_time_unreachable", Empty); + fields->Set("state_type", Empty); + fields->Set("last_notification", Empty); + fields->Set("next_notification", Empty); + fields->Set("no_more_notifications", Empty); + fields->Set("notifications_enabled", Empty); + fields->Set("problem_has_been_acknowledged", Empty); + fields->Set("acknowledgement_type", Empty); + fields->Set("current_notification_number", Empty); + fields->Set("passive_checks_enabled", Empty); + fields->Set("active_checks_enabled", Empty); + fields->Set("event_handler_enabled", Empty); + fields->Set("flap_detection_enabled", Empty); + fields->Set("is_flapping", Empty); + fields->Set("percent_state_change", Empty); + fields->Set("latency", Empty); + fields->Set("execution_time", Empty); + fields->Set("scheduled_downtime_depth", Empty); + fields->Set("failure_prediction_enabled", Empty); + fields->Set("process_performance_data", Empty); + fields->Set("obsess_over_host", Empty); + fields->Set("modified_host_attributes", Empty); + fields->Set("event_handler", Empty); + fields->Set("check_command", Empty); + fields->Set("normal_check_interval", Empty); + fields->Set("retry_check_interval", Empty); + fields->Set("check_timeperiod_object_id", Empty); + return fields; } diff --git a/lib/ido/hostdbobject.h b/lib/ido/hostdbobject.h index ac9b41fbc..0a58aec1e 100644 --- a/lib/ido/hostdbobject.h +++ b/lib/ido/hostdbobject.h @@ -38,7 +38,8 @@ public: HostDbObject(const String& name1, const String& name2); - virtual Dictionary::Ptr GetFields(void) const; + virtual Dictionary::Ptr GetConfigFields(void) const; + virtual Dictionary::Ptr GetStatusFields(void) const; }; } diff --git a/lib/ido/servicedbobject.cpp b/lib/ido/servicedbobject.cpp index 2d9651f99..c8ed7945b 100644 --- a/lib/ido/servicedbobject.cpp +++ b/lib/ido/servicedbobject.cpp @@ -20,6 +20,7 @@ #include "ido/servicedbobject.h" #include "ido/dbtype.h" #include "icinga/service.h" +#include "icinga/checkcommand.h" using namespace icinga; @@ -29,12 +30,111 @@ ServiceDbObject::ServiceDbObject(const String& name1, const String& name2) : DbObject(DbType::GetByName("Service"), name1, name2) { } -Dictionary::Ptr ServiceDbObject::GetFields(void) const +Dictionary::Ptr ServiceDbObject::GetConfigFields(void) const { Dictionary::Ptr fields = boost::make_shared(); Service::Ptr service = static_pointer_cast(GetObject()); fields->Set("display_name", service->GetDisplayName()); + fields->Set("check_command_object_id", service->GetCheckCommand()); + fields->Set("check_command_args", Empty); + fields->Set("eventhandler_command_object_id", Empty); + fields->Set("eventhandler_command_args", Empty); + fields->Set("notification_timeperiod_object_id", Empty); + fields->Set("check_timeperiod_object_id", Empty); + fields->Set("failure_prediction_options", Empty); + fields->Set("check_interval", service->GetCheckInterval() * 60); + fields->Set("retry_interval", service->GetRetryInterval() * 60); + fields->Set("max_check_attempts", service->GetMaxCheckAttempts()); + fields->Set("first_notification_delay", Empty); + fields->Set("notification_interval", Empty); + fields->Set("notify_on_warning", Empty); + fields->Set("notify_on_unknown", Empty); + fields->Set("notify_on_critical", Empty); + fields->Set("notify_on_recovery", Empty); + fields->Set("notify_on_flapping", Empty); + fields->Set("notify_on_downtime", Empty); + fields->Set("stalk_on_ok", 0); + fields->Set("stalk_on_warning", 0); + fields->Set("stalk_on_unknown", 0); + fields->Set("stalk_on_critical", 0); + fields->Set("is_volatile", Empty); + fields->Set("flap_detection_enabled", Empty); + fields->Set("flap_detection_on_ok", Empty); + fields->Set("flap_detection_on_warning", Empty); + fields->Set("flap_detection_on_unknown", Empty); + fields->Set("flap_detection_on_critical", Empty); + fields->Set("low_flap_threshold", Empty); + fields->Set("high_flap_threshold", Empty); + fields->Set("process_performance_data", Empty); + fields->Set("freshness_checks_enabled", Empty); + fields->Set("freshness_threshold", Empty); + fields->Set("passive_checks_enabled", Empty); + fields->Set("event_handler_enabled", Empty); + fields->Set("active_checks_enabled", Empty); + fields->Set("retain_status_information", Empty); + fields->Set("retain_nonstatus_information", Empty); + fields->Set("notifications_enabled", Empty); + fields->Set("obsess_over_service", Empty); + fields->Set("failure_prediction_enabled", Empty); + fields->Set("notes", Empty); + fields->Set("notes_url", Empty); + fields->Set("action_url", Empty); + fields->Set("icon_image", Empty); + fields->Set("icon_image_alt", Empty); return fields; } + +Dictionary::Ptr ServiceDbObject::GetStatusFields(void) const +{ + Dictionary::Ptr fields = boost::make_shared(); + Service::Ptr service = static_pointer_cast(GetObject()); + + fields->Set("output", Empty); + fields->Set("long_output", Empty); + fields->Set("perfdata", Empty); + fields->Set("current_state", Empty); + fields->Set("has_been_checked", Empty); + fields->Set("should_be_scheduled", Empty); + fields->Set("current_check_attempt", Empty); + fields->Set("max_check_attempts", Empty); + fields->Set("last_check", Empty); + fields->Set("next_check", Empty); + fields->Set("check_type", Empty); + fields->Set("last_state_change", Empty); + fields->Set("last_hard_state_change", Empty); + fields->Set("last_hard_state", Empty); + fields->Set("last_time_ok", Empty); + fields->Set("last_time_warning", Empty); + fields->Set("last_time_unknown", Empty); + fields->Set("last_time_critical", Empty); + fields->Set("state_type", Empty); + fields->Set("last_notification", Empty); + fields->Set("next_notification", Empty); + fields->Set("no_more_notifications", Empty); + fields->Set("notifications_enabled", Empty); + fields->Set("problem_has_been_acknowledged", Empty); + fields->Set("acknowledgement_type", Empty); + fields->Set("current_notification_number", Empty); + fields->Set("passive_checks_enabled", Empty); + fields->Set("active_checks_enabled", Empty); + fields->Set("event_handler_enabled", Empty); + fields->Set("flap_detection_enabled", Empty); + fields->Set("is_flapping", Empty); + fields->Set("percent_state_change", Empty); + fields->Set("latency", Empty); + fields->Set("execution_time", Empty); + fields->Set("scheduled_downtime_depth", Empty); + fields->Set("failure_prediction_enabled", Empty); + fields->Set("process_performance_data", Empty); + fields->Set("obsess_over_service", Empty); + fields->Set("modified_service_attributes", Empty); + fields->Set("event_handler", Empty); + fields->Set("check_command", Empty); + fields->Set("normal_check_interval", Empty); + fields->Set("retry_check_interval", Empty); + fields->Set("check_timeperiod_object_id", Empty); + + return fields; +} \ No newline at end of file diff --git a/lib/ido/servicedbobject.h b/lib/ido/servicedbobject.h index 1dff03c9d..d6b060888 100644 --- a/lib/ido/servicedbobject.h +++ b/lib/ido/servicedbobject.h @@ -38,7 +38,8 @@ public: ServiceDbObject(const String& name1, const String& name2); - virtual Dictionary::Ptr GetFields(void) const; + virtual Dictionary::Ptr GetConfigFields(void) const; + virtual Dictionary::Ptr GetStatusFields(void) const; }; }