1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
2 
3 #ifndef DBCONNECTION_H
4 #define DBCONNECTION_H
5 
6 #include "db_ido/i2-db_ido.hpp"
7 #include "db_ido/dbconnection-ti.hpp"
8 #include "db_ido/dbobject.hpp"
9 #include "db_ido/dbquery.hpp"
10 #include "base/timer.hpp"
11 #include "base/ringbuffer.hpp"
12 #include <boost/thread/once.hpp>
13 #include <mutex>
14 
15 namespace icinga
16 {
17 
18 /**
19  * A database connection.
20  *
21  * @ingroup db_ido
22  */
23 class DbConnection : public ObjectImpl<DbConnection>
24 {
25 public:
26 	DECLARE_OBJECT(DbConnection);
27 
28 	static void InitializeDbTimer();
29 
30 	virtual const char * GetLatestSchemaVersion() const noexcept = 0;
31 	virtual const char * GetCompatSchemaVersion() const noexcept = 0;
32 
33 	void SetConfigHash(const DbObject::Ptr& dbobj, const String& hash);
34 	void SetConfigHash(const DbType::Ptr& type, const DbReference& objid, const String& hash);
35 	String GetConfigHash(const DbObject::Ptr& dbobj) const;
36 	String GetConfigHash(const DbType::Ptr& type, const DbReference& objid) const;
37 
38 	void SetObjectID(const DbObject::Ptr& dbobj, const DbReference& dbref);
39 	DbReference GetObjectID(const DbObject::Ptr& dbobj) const;
40 
41 	void SetInsertID(const DbObject::Ptr& dbobj, const DbReference& dbref);
42 	void SetInsertID(const DbType::Ptr& type, const DbReference& objid, const DbReference& dbref);
43 	DbReference GetInsertID(const DbObject::Ptr& dbobj) const;
44 	DbReference GetInsertID(const DbType::Ptr& type, const DbReference& objid) const;
45 
46 	void SetObjectActive(const DbObject::Ptr& dbobj, bool active);
47 	bool GetObjectActive(const DbObject::Ptr& dbobj) const;
48 
49 	void ClearIDCache();
50 
51 	void SetConfigUpdate(const DbObject::Ptr& dbobj, bool hasupdate);
52 	bool GetConfigUpdate(const DbObject::Ptr& dbobj) const;
53 
54 	void SetStatusUpdate(const DbObject::Ptr& dbobj, bool hasupdate);
55 	bool GetStatusUpdate(const DbObject::Ptr& dbobj) const;
56 
57 	int GetQueryCount(RingBuffer::SizeType span);
58 	virtual int GetPendingQueryCount() const = 0;
59 
60 	void ValidateFailoverTimeout(const Lazy<double>& lvalue, const ValidationUtils& utils) final;
61 	void ValidateCategories(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils) final;
62 
63 protected:
64 	void OnConfigLoaded() override;
65 	void Start(bool runtimeCreated) override;
66 	void Stop(bool runtimeRemoved) override;
67 	void Resume() override;
68 	void Pause() override;
69 
70 	virtual void ExecuteQuery(const DbQuery& query) = 0;
71 	virtual void ExecuteMultipleQueries(const std::vector<DbQuery>&) = 0;
72 	virtual void ActivateObject(const DbObject::Ptr& dbobj) = 0;
73 	virtual void DeactivateObject(const DbObject::Ptr& dbobj) = 0;
74 
75 	virtual void CleanUpExecuteQuery(const String& table, const String& time_column, double max_age);
76 	virtual void FillIDCache(const DbType::Ptr& type) = 0;
77 	virtual void NewTransaction() = 0;
78 	virtual void Disconnect() = 0;
79 
80 	void UpdateObject(const ConfigObject::Ptr& object);
81 	void UpdateAllObjects();
82 
83 	void PrepareDatabase();
84 
85 	void IncreaseQueryCount();
86 
87 	bool IsIDCacheValid() const;
88 	void SetIDCacheValid(bool valid);
89 
90 	void EnableActiveChangedHandler();
91 
92 	static void UpdateProgramStatus();
93 
94 	static int GetSessionToken();
95 
96 	void IncreasePendingQueries(int count);
97 	void DecreasePendingQueries(int count);
98 
99 	WorkQueue m_QueryQueue{10000000, 1, LogNotice};
100 
101 private:
102 	bool m_IDCacheValid{false};
103 	std::map<std::pair<DbType::Ptr, DbReference>, String> m_ConfigHashes;
104 	std::map<DbObject::Ptr, DbReference> m_ObjectIDs;
105 	std::map<std::pair<DbType::Ptr, DbReference>, DbReference> m_InsertIDs;
106 	std::set<DbObject::Ptr> m_ActiveObjects;
107 	std::set<DbObject::Ptr> m_ConfigUpdates;
108 	std::set<DbObject::Ptr> m_StatusUpdates;
109 	Timer::Ptr m_CleanUpTimer;
110 	Timer::Ptr m_LogStatsTimer;
111 
112 	double m_LogStatsTimeout;
113 
114 	void CleanUpHandler();
115 	void LogStatsHandler();
116 
117 	static Timer::Ptr m_ProgramStatusTimer;
118 	static boost::once_flag m_OnceFlag;
119 
120 	static void InsertRuntimeVariable(const String& key, const Value& value);
121 
122 	mutable std::mutex m_StatsMutex;
123 	RingBuffer m_QueryStats{15 * 60};
124 	bool m_ActiveChangedHandler{false};
125 
126 	RingBuffer m_InputQueries{10};
127 	RingBuffer m_OutputQueries{10};
128 	Atomic<uint_fast64_t> m_PendingQueries{0};
129 };
130 
131 struct database_error : virtual std::exception, virtual boost::exception { };
132 
133 struct errinfo_database_query_;
134 typedef boost::error_info<struct errinfo_database_query_, std::string> errinfo_database_query;
135 
136 }
137 
138 #endif /* DBCONNECTION_H */
139