Implement support for timestamps.

This commit is contained in:
Gunnar Beutner 2013-07-23 11:02:47 +02:00
parent e894d24939
commit 3a552403eb
10 changed files with 282 additions and 34 deletions

View File

@ -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 <boost/tuple/tuple.hpp>
#include <boost/smart_ptr/make_shared.hpp>
@ -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<long>(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<long>(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<long>(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<long>(m_InstanceID);
return true;
}
if (value.IsObjectType<DynamicObject>()) {
DbObject::Ptr dbobjcol = DbObject::GetOrCreateByObject(value);
@ -300,16 +309,27 @@ bool MysqlDbConnection::FieldToString(const String& key, const Value& value, Val
}
*result = static_cast<long>(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<long>(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());
}

View File

@ -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);

View File

@ -20,6 +20,8 @@ libido_la_SOURCES = \
dbreference.h \
dbtype.cpp \
dbtype.h \
dbvalue.cpp \
dbvalue.h \
hostdbobject.cpp \
hostdbobject.h \
ido-type.cpp \

View File

@ -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);
}

22
lib/ido/dbquery.cpp Normal file
View File

@ -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;

45
lib/ido/dbquery.h Normal file
View File

@ -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 */

81
lib/ido/dbvalue.cpp Normal file
View File

@ -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<DbValue>(DbValueTimestamp, ts);
}
Value DbValue::FromTimestampNow(void)
{
return boost::make_shared<DbValue>(DbValueTimestampNow, Empty);
}
Value DbValue::FromValue(const Value& value)
{
return value;
}
bool DbValue::IsTimestamp(const Value& value)
{
if (!value.IsObjectType<DbValue>())
return false;
DbValue::Ptr dbv = value;
return dbv->GetType() == DbValueTimestamp;
}
bool DbValue::IsTimestampNow(const Value& value)
{
if (!value.IsObjectType<DbValue>())
return false;
DbValue::Ptr dbv = value;
return dbv->GetType() == DbValueTimestampNow;
}
Value DbValue::ExtractValue(const Value& value)
{
if (!value.IsObjectType<DbValue>())
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;
}

70
lib/ido/dbvalue.h Normal file
View File

@ -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 <boost/smart_ptr/make_shared.hpp>
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<DbValue> boost::make_shared<>(const icinga::DbValueType&, const double&);
friend boost::shared_ptr<DbValue> boost::make_shared<>(const icinga::DbValueType&, const icinga::Value&);
};
}
#endif /* DBVALUE_H */

View File

@ -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"));

View File

@ -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<Dictionary>();
Service::Ptr service = static_pointer_cast<Service>(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"));