summaryrefslogtreecommitdiffstats
path: root/lib/db_ido/dbconnection.hpp
blob: 517a8a40ebcdd4197080737d3b3cf2a8d434fc79 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */

#ifndef DBCONNECTION_H
#define DBCONNECTION_H

#include "db_ido/i2-db_ido.hpp"
#include "db_ido/dbconnection-ti.hpp"
#include "db_ido/dbobject.hpp"
#include "db_ido/dbquery.hpp"
#include "base/timer.hpp"
#include "base/ringbuffer.hpp"
#include <boost/thread/once.hpp>
#include <mutex>

namespace icinga
{

/**
 * A database connection.
 *
 * @ingroup db_ido
 */
class DbConnection : public ObjectImpl<DbConnection>
{
public:
	DECLARE_OBJECT(DbConnection);

	static void InitializeDbTimer();

	virtual const char * GetLatestSchemaVersion() const noexcept = 0;
	virtual const char * GetCompatSchemaVersion() const noexcept = 0;

	void SetConfigHash(const DbObject::Ptr& dbobj, const String& hash);
	void SetConfigHash(const DbType::Ptr& type, const DbReference& objid, const String& hash);
	String GetConfigHash(const DbObject::Ptr& dbobj) const;
	String GetConfigHash(const DbType::Ptr& type, const DbReference& objid) const;

	void SetObjectID(const DbObject::Ptr& dbobj, const DbReference& dbref);
	DbReference GetObjectID(const DbObject::Ptr& dbobj) const;

	void SetInsertID(const DbObject::Ptr& dbobj, const DbReference& dbref);
	void SetInsertID(const DbType::Ptr& type, const DbReference& objid, const DbReference& dbref);
	DbReference GetInsertID(const DbObject::Ptr& dbobj) const;
	DbReference GetInsertID(const DbType::Ptr& type, const DbReference& objid) const;

	void SetObjectActive(const DbObject::Ptr& dbobj, bool active);
	bool GetObjectActive(const DbObject::Ptr& dbobj) const;

	void ClearIDCache();

	void SetConfigUpdate(const DbObject::Ptr& dbobj, bool hasupdate);
	bool GetConfigUpdate(const DbObject::Ptr& dbobj) const;

	void SetStatusUpdate(const DbObject::Ptr& dbobj, bool hasupdate);
	bool GetStatusUpdate(const DbObject::Ptr& dbobj) const;

	int GetQueryCount(RingBuffer::SizeType span);
	virtual int GetPendingQueryCount() const = 0;

	void ValidateFailoverTimeout(const Lazy<double>& lvalue, const ValidationUtils& utils) final;
	void ValidateCategories(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils) final;

protected:
	void OnConfigLoaded() override;
	void Start(bool runtimeCreated) override;
	void Stop(bool runtimeRemoved) override;
	void Resume() override;
	void Pause() override;

	virtual void ExecuteQuery(const DbQuery& query) = 0;
	virtual void ExecuteMultipleQueries(const std::vector<DbQuery>&) = 0;
	virtual void ActivateObject(const DbObject::Ptr& dbobj) = 0;
	virtual void DeactivateObject(const DbObject::Ptr& dbobj) = 0;

	virtual void CleanUpExecuteQuery(const String& table, const String& time_column, double max_age);
	virtual void FillIDCache(const DbType::Ptr& type) = 0;
	virtual void NewTransaction() = 0;
	virtual void Disconnect() = 0;

	void UpdateObject(const ConfigObject::Ptr& object);
	void UpdateAllObjects();

	void PrepareDatabase();

	void IncreaseQueryCount();

	bool IsIDCacheValid() const;
	void SetIDCacheValid(bool valid);

	void EnableActiveChangedHandler();

	static void UpdateProgramStatus();

	static int GetSessionToken();

	void IncreasePendingQueries(int count);
	void DecreasePendingQueries(int count);

	WorkQueue m_QueryQueue{10000000, 1, LogNotice};

private:
	bool m_IDCacheValid{false};
	std::map<std::pair<DbType::Ptr, DbReference>, String> m_ConfigHashes;
	std::map<DbObject::Ptr, DbReference> m_ObjectIDs;
	std::map<std::pair<DbType::Ptr, DbReference>, DbReference> m_InsertIDs;
	std::set<DbObject::Ptr> m_ActiveObjects;
	std::set<DbObject::Ptr> m_ConfigUpdates;
	std::set<DbObject::Ptr> m_StatusUpdates;
	Timer::Ptr m_CleanUpTimer;
	Timer::Ptr m_LogStatsTimer;

	double m_LogStatsTimeout;

	void CleanUpHandler();
	void LogStatsHandler();

	static Timer::Ptr m_ProgramStatusTimer;
	static boost::once_flag m_OnceFlag;

	static void InsertRuntimeVariable(const String& key, const Value& value);

	mutable std::mutex m_StatsMutex;
	RingBuffer m_QueryStats{15 * 60};
	bool m_ActiveChangedHandler{false};

	RingBuffer m_InputQueries{10};
	RingBuffer m_OutputQueries{10};
	Atomic<uint_fast64_t> m_PendingQueries{0};
};

struct database_error : virtual std::exception, virtual boost::exception { };

struct errinfo_database_query_;
typedef boost::error_info<struct errinfo_database_query_, std::string> errinfo_database_query;

}

#endif /* DBCONNECTION_H */