diff --git a/components/ido_mysql/mysqldbconnection.cpp b/components/ido_mysql/mysqldbconnection.cpp index 9c842495a..2e79ec0c2 100644 --- a/components/ido_mysql/mysqldbconnection.cpp +++ b/components/ido_mysql/mysqldbconnection.cpp @@ -22,6 +22,7 @@ #include "base/convert.h" #include "base/utility.h" #include "ido/dbtype.h" +#include "ido/dbvalue.h" #include "ido_mysql/mysqldbconnection.h" #include #include @@ -136,9 +137,9 @@ void MysqlDbConnection::ReconnectTimerHandler(void) Query("UPDATE icinga_objects SET is_active = 0"); - std::ostringstream qbuf; - qbuf << "SELECT object_id, objecttype_id, name1, name2 FROM icinga_objects WHERE instance_id = " << static_cast(m_InstanceID); - rows = Query(qbuf.str()); + std::ostringstream q1buf; + q1buf << "SELECT object_id, objecttype_id, name1, name2 FROM icinga_objects WHERE instance_id = " << static_cast(m_InstanceID); + rows = Query(q1buf.str()); ObjectLock olock(rows); BOOST_FOREACH(const Dictionary::Ptr& row, rows) { @@ -151,6 +152,11 @@ void MysqlDbConnection::ReconnectTimerHandler(void) SetReference(dbobj, DbReference(row->Get("object_id"))); } + // TODO: Use a timer, move to libido + std::ostringstream q2buf; + q2buf << "REPLACE INTO icinga_programstatus (instance_id, status_update_time) VALUES (" << static_cast(m_InstanceID) << ", NOW())"; + Query(q2buf.str()); + Query("BEGIN"); } @@ -276,9 +282,12 @@ void MysqlDbConnection::DeactivateObject(const DbObject::Ptr& dbobj) SetReference(dbobj, DbReference()); } -bool MysqlDbConnection::FieldToString(const String& key, const Value& value, Value *result) +bool MysqlDbConnection::FieldToEscapedString(const String& key, const Value& value, Value *result) { - *result = value; + if (key == "instance_id") { + *result = static_cast(m_InstanceID); + return true; + } if (value.IsObjectType()) { DbObject::Ptr dbobjcol = DbObject::GetOrCreateByObject(value); @@ -300,16 +309,27 @@ bool MysqlDbConnection::FieldToString(const String& key, const Value& value, Val } *result = static_cast(dbrefcol); + } else if (DbValue::IsTimestamp(value)) { + double ts = DbValue::ExtractValue(value); + std::ostringstream msgbuf; + msgbuf << "FROM_UNIXTIME(" << ts << ")"; + *result = Value(msgbuf.str()); + } else if (DbValue::IsTimestampNow(value)) { + *result = "NOW()"; + } else { + *result = "'" + Escape(DbValue::ExtractValue(value)) + "'"; } - if (key == "instance_id") - *result = static_cast(m_InstanceID); - return true; } void MysqlDbConnection::ExecuteQuery(const DbQuery& query) { + boost::mutex::scoped_lock lock(m_ConnectionMutex); + + if (!m_Connected) + return; + std::ostringstream qbuf; switch (query.Type) { @@ -336,7 +356,7 @@ void MysqlDbConnection::ExecuteQuery(const DbQuery& query) Value value; bool first = true; BOOST_FOREACH(boost::tie(key, value), query.Fields) { - if (!FieldToString(key, value, &value)) + if (!FieldToEscapedString(key, value, &value)) return; if (query.Type == DbQueryInsert) { @@ -346,12 +366,12 @@ void MysqlDbConnection::ExecuteQuery(const DbQuery& query) } cols += key; - values += "'" + Convert::ToString(value) + "'"; + values += Convert::ToString(value); } else { if (!first) qbuf << ", "; - qbuf << " " << key << " = '" << Escape(value) << "'"; + qbuf << " " << key << " = " << value; } if (first) @@ -371,7 +391,7 @@ void MysqlDbConnection::ExecuteQuery(const DbQuery& query) Value value; bool first = true; BOOST_FOREACH(boost::tie(key, value), query.WhereCriteria) { - if (!FieldToString(Empty, value, &value)) + if (!FieldToEscapedString(Empty, value, &value)) return; if (!first) @@ -384,6 +404,5 @@ void MysqlDbConnection::ExecuteQuery(const DbQuery& query) } } - boost::mutex::scoped_lock lock(m_ConnectionMutex); Query(qbuf.str()); } diff --git a/components/ido_mysql/mysqldbconnection.h b/components/ido_mysql/mysqldbconnection.h index bc3b2b018..6384ffb48 100644 --- a/components/ido_mysql/mysqldbconnection.h +++ b/components/ido_mysql/mysqldbconnection.h @@ -73,7 +73,7 @@ private: String Escape(const String& s); Dictionary::Ptr FetchRow(MYSQL_RES *result); - bool FieldToString(const String& key, const Value& value, Value *result); + bool FieldToEscapedString(const String& key, const Value& value, Value *result); void TxTimerHandler(void); void ReconnectTimerHandler(void); diff --git a/lib/ido/Makefile.am b/lib/ido/Makefile.am index 51d27cbfc..0867fa246 100644 --- a/lib/ido/Makefile.am +++ b/lib/ido/Makefile.am @@ -20,6 +20,8 @@ libido_la_SOURCES = \ dbreference.h \ dbtype.cpp \ dbtype.h \ + dbvalue.cpp \ + dbvalue.h \ hostdbobject.cpp \ hostdbobject.h \ ido-type.cpp \ diff --git a/lib/ido/dbobject.cpp b/lib/ido/dbobject.cpp index 9da69bc50..4d1e9920c 100644 --- a/lib/ido/dbobject.cpp +++ b/lib/ido/dbobject.cpp @@ -88,6 +88,7 @@ void DbObject::SendConfigUpdate(void) query2.Fields->Set(GetType()->GetTable() + "_object_id", GetObject()); query2.Fields->Set("instance_id", 0); /* DbConnection class fills in real ID */ + query2.Fields->Set("config_type", 1); OnQuery(query2); } diff --git a/lib/ido/dbquery.cpp b/lib/ido/dbquery.cpp new file mode 100644 index 000000000..6e9dee8dc --- /dev/null +++ b/lib/ido/dbquery.cpp @@ -0,0 +1,22 @@ +/****************************************************************************** + * 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/dbquery.h" + +using namespace icinga; diff --git a/lib/ido/dbquery.h b/lib/ido/dbquery.h new file mode 100644 index 000000000..223dcc50e --- /dev/null +++ b/lib/ido/dbquery.h @@ -0,0 +1,45 @@ +/****************************************************************************** + * 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 DBQUERY_H +#define DBQUERY_H + +#include "base/dictionary.h" + +namespace icinga +{ + +enum DbQueryType +{ + DbQueryInsert, + DbQueryUpdate, + DbQueryDelete +}; + +struct DbQuery +{ + DbQueryType Type; + String Table; + Dictionary::Ptr Fields; + Dictionary::Ptr WhereCriteria; +}; + +} + +#endif /* DBQUERY_H */ diff --git a/lib/ido/dbvalue.cpp b/lib/ido/dbvalue.cpp new file mode 100644 index 000000000..6a6034a52 --- /dev/null +++ b/lib/ido/dbvalue.cpp @@ -0,0 +1,81 @@ +/****************************************************************************** + * 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/dbvalue.h" + +using namespace icinga; + +DbValue::DbValue(DbValueType type, const Value& value) + : m_Type(type), m_Value(value) +{ } + +Value DbValue::FromTimestamp(const Value& ts) +{ + if (ts.IsEmpty() || ts == 0) + return Empty; + + return boost::make_shared(DbValueTimestamp, ts); +} + +Value DbValue::FromTimestampNow(void) +{ + return boost::make_shared(DbValueTimestampNow, Empty); +} + +Value DbValue::FromValue(const Value& value) +{ + return value; +} + +bool DbValue::IsTimestamp(const Value& value) +{ + if (!value.IsObjectType()) + return false; + + DbValue::Ptr dbv = value; + return dbv->GetType() == DbValueTimestamp; +} + +bool DbValue::IsTimestampNow(const Value& value) +{ + if (!value.IsObjectType()) + return false; + + DbValue::Ptr dbv = value; + return dbv->GetType() == DbValueTimestampNow; +} + +Value DbValue::ExtractValue(const Value& value) +{ + if (!value.IsObjectType()) + return value; + + DbValue::Ptr dbv = value; + return dbv->GetValue(); +} + +DbValueType DbValue::GetType(void) const +{ + return m_Type; +} + +Value DbValue::GetValue(void) const +{ + return m_Value; +} diff --git a/lib/ido/dbvalue.h b/lib/ido/dbvalue.h new file mode 100644 index 000000000..526fbc0a7 --- /dev/null +++ b/lib/ido/dbvalue.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * 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 DBVALUE_H +#define DBVALUE_H + +#include "base/object.h" +#include "base/value.h" +#include + +namespace icinga +{ + +enum DbValueType +{ + DbValueTimestamp, + DbValueTimestampNow, +}; + +/** + * A database value. + * + * @ingroup ido + */ +struct DbValue : public Object +{ +public: + DECLARE_PTR_TYPEDEFS(DbValue); + + static Value FromTimestamp(const Value& ts); + static Value FromTimestampNow(void); + static Value FromValue(const Value& value); + + static bool IsTimestamp(const Value& value); + static bool IsTimestampNow(const Value& value); + static Value ExtractValue(const Value& value); + + DbValueType GetType(void) const; + Value GetValue(void) const; + +protected: + DbValue(DbValueType type, const Value& value); + +private: + DbValueType m_Type; + Value m_Value; + + friend boost::shared_ptr boost::make_shared<>(const icinga::DbValueType&, const double&); + friend boost::shared_ptr boost::make_shared<>(const icinga::DbValueType&, const icinga::Value&); +}; + +} + +#endif /* DBVALUE_H */ diff --git a/lib/ido/hostdbobject.cpp b/lib/ido/hostdbobject.cpp index f8b14bf34..7b2f17a8c 100644 --- a/lib/ido/hostdbobject.cpp +++ b/lib/ido/hostdbobject.cpp @@ -19,6 +19,7 @@ #include "ido/hostdbobject.h" #include "ido/dbtype.h" +#include "ido/dbvalue.h" #include "icinga/host.h" #include "icinga/service.h" #include "icinga/checkcommand.h" @@ -133,14 +134,14 @@ Dictionary::Ptr HostDbObject::GetStatusFields(void) const fields->Set("output", attrs->Get("plugin_output")); fields->Set("long_output", attrs->Get("long_plugin_output")); fields->Set("perfdata", attrs->Get("performance_data")); - fields->Set("last_check", attrs->Get("last_check")); - fields->Set("next_check", attrs->Get("next_check")); + fields->Set("last_check", DbValue::FromTimestamp(attrs->Get("last_check"))); + fields->Set("next_check", DbValue::FromTimestamp(attrs->Get("next_check"))); fields->Set("current_check_attempt", attrs->Get("current_attempt")); fields->Set("max_check_attempts", attrs->Get("max_attempts")); - fields->Set("last_state_change", attrs->Get("last_state_change")); - fields->Set("last_hard_state_change", attrs->Get("last_hard_state_change")); - fields->Set("last_time_up", attrs->Get("last_time_up")); - fields->Set("last_time_down", attrs->Get("last_time_down")); + fields->Set("last_state_change", DbValue::FromTimestamp(attrs->Get("last_state_change"))); + fields->Set("last_hard_state_change", DbValue::FromTimestamp(attrs->Get("last_hard_state_change"))); + fields->Set("last_time_up", DbValue::FromTimestamp(attrs->Get("last_time_up"))); + fields->Set("last_time_down", DbValue::FromTimestamp(attrs->Get("last_time_down"))); fields->Set("last_time_unreachable", attrs->Get("last_time_unreachable")); //fields->Set("last_update", attrs->Get("last_update")); fields->Set("notifications_enabled", attrs->Get("notifications_enabled")); @@ -153,8 +154,8 @@ Dictionary::Ptr HostDbObject::GetStatusFields(void) const fields->Set("acknowledgement_type", attrs->Get("acknowledgement_type")); //fields->Set("acknowledgement_end_time", attrs->Get("acknowledgement_end_time")); fields->Set("scheduled_downtime_depth", attrs->Get("scheduled_downtime_depth")); - fields->Set("last_notification", attrs->Get("last_notification")); - fields->Set("next_notification", attrs->Get("next_notification")); + fields->Set("last_notification", DbValue::FromTimestamp(attrs->Get("last_notification"))); + fields->Set("next_notification", DbValue::FromTimestamp(attrs->Get("next_notification"))); fields->Set("current_notification_number", attrs->Get("current_notification_number")); diff --git a/lib/ido/servicedbobject.cpp b/lib/ido/servicedbobject.cpp index 364b888c0..7d61bd9a6 100644 --- a/lib/ido/servicedbobject.cpp +++ b/lib/ido/servicedbobject.cpp @@ -19,6 +19,7 @@ #include "ido/servicedbobject.h" #include "ido/dbtype.h" +#include "ido/dbvalue.h" #include "base/objectlock.h" #include "icinga/service.h" #include "icinga/checkcommand.h" @@ -37,6 +38,12 @@ Dictionary::Ptr ServiceDbObject::GetConfigFields(void) const Dictionary::Ptr fields = boost::make_shared(); Service::Ptr service = static_pointer_cast(GetObject()); + Host::Ptr host = service->GetHost(); + + if (!host) + return Dictionary::Ptr(); + + fields->Set("host_object_id", host); fields->Set("display_name", service->GetDisplayName()); fields->Set("check_command_object_id", service->GetCheckCommand()); fields->Set("check_command_args", Empty); @@ -45,8 +52,8 @@ Dictionary::Ptr ServiceDbObject::GetConfigFields(void) const 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("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); @@ -111,16 +118,16 @@ Dictionary::Ptr ServiceDbObject::GetStatusFields(void) const fields->Set("output", attrs->Get("plugin_output")); fields->Set("long_output", attrs->Get("long_plugin_output")); fields->Set("perfdata", attrs->Get("performance_data")); - fields->Set("last_check", attrs->Get("last_check")); - fields->Set("next_check", attrs->Get("next_check")); + fields->Set("last_check", DbValue::FromTimestamp(attrs->Get("last_check"))); + fields->Set("next_check", DbValue::FromTimestamp(attrs->Get("next_check"))); fields->Set("current_check_attempt", attrs->Get("current_attempt")); fields->Set("max_check_attempts", attrs->Get("max_attempts")); - fields->Set("last_state_change", attrs->Get("last_state_change")); - fields->Set("last_hard_state_change", attrs->Get("last_hard_state_change")); - fields->Set("last_time_ok", attrs->Get("last_time_ok")); - fields->Set("last_time_warning", attrs->Get("last_time_warn")); - fields->Set("last_time_critical", attrs->Get("last_time_critical")); - fields->Set("last_time_unknown", attrs->Get("last_time_unknown")); + fields->Set("last_state_change", DbValue::FromTimestamp(attrs->Get("last_state_change"))); + fields->Set("last_hard_state_change", DbValue::FromTimestamp(attrs->Get("last_hard_state_change"))); + fields->Set("last_time_ok", DbValue::FromTimestamp(attrs->Get("last_time_ok"))); + fields->Set("last_time_warning", DbValue::FromTimestamp(attrs->Get("last_time_warn"))); + fields->Set("last_time_critical", DbValue::FromTimestamp(attrs->Get("last_time_critical"))); + fields->Set("last_time_unknown", DbValue::FromTimestamp(attrs->Get("last_time_unknown"))); //fields->Set("last_update", attrs->Get("last_update")); fields->Set("notifications_enabled", attrs->Get("notifications_enabled")); fields->Set("active_checks_enabled", attrs->Get("active_checks_enabled")); @@ -132,8 +139,8 @@ Dictionary::Ptr ServiceDbObject::GetStatusFields(void) const fields->Set("acknowledgement_type", attrs->Get("acknowledgement_type")); //fields->Set("acknowledgement_end_time", attrs->Get("acknowledgement_end_time")); fields->Set("scheduled_downtime_depth", attrs->Get("scheduled_downtime_depth")); - fields->Set("last_notification", attrs->Get("last_notification")); - fields->Set("next_notification", attrs->Get("next_notification")); + fields->Set("last_notification", DbValue::FromTimestamp(attrs->Get("last_notification"))); + fields->Set("next_notification", DbValue::FromTimestamp(attrs->Get("next_notification"))); fields->Set("current_notification_number", attrs->Get("current_notification_number"));