03e12fcd3586cc7cfc41d01b365e885086a5bd85
[public/netxms.git] / src / agent / core / localdb.cpp
1 /*
2 ** NetXMS multiplatform core agent
3 ** Copyright (C) 2003-2015 Victor Kirhenshtein
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 **
19 ** File: localdb.cpp
20 **
21 **/
22
23 #include "nxagentd.h"
24
25 /**
26 * Database driver
27 */
28 static DB_DRIVER s_driver = NULL;
29
30 /**
31 * Database handle
32 */
33 static DB_HANDLE s_db = NULL;
34
35 /**
36 * Read metadata
37 */
38 TCHAR *ReadMetadata(const TCHAR *attr, TCHAR *buffer)
39 {
40 TCHAR query[256], *value = NULL;
41 _sntprintf(query, 256, _T("SELECT value FROM metadata WHERE attribute='%s'"), attr);
42
43 DB_RESULT hResult = DBSelect(s_db, query);
44 if (hResult != NULL)
45 {
46 value = DBGetField(hResult, 0, 0, buffer, MAX_DB_STRING);
47 DBFreeResult(hResult);
48 }
49 return value;
50 }
51
52 /**
53 * Read integer from metadata
54 */
55 INT32 ReadMetadataAsInt(const TCHAR *attr)
56 {
57 TCHAR buffer[MAX_DB_STRING];
58 if (ReadMetadata(attr, buffer) == NULL)
59 return 0;
60 return _tcstol(buffer, NULL, 0);
61 }
62
63 /**
64 * Set value in metadata
65 */
66 bool WriteMetadata(const TCHAR *name, const TCHAR *value)
67 {
68 String prepValue = DBPrepareString(s_db, value, 255);
69
70 TCHAR query[1024];
71 _sntprintf(query, 1024, _T("UPDATE OR IGNORE metadata SET value=%s WHERE attribute='%s'"), (const TCHAR *)prepValue, name);
72 if (!DBQuery(s_db, query))
73 return false;
74
75 _sntprintf(query, 1024, _T("INSERT OR IGNORE INTO metadata (attribute,value) VALUES ('%s',%s)"), name, (const TCHAR *)prepValue);
76 return DBQuery(s_db, query);
77 }
78
79 /**
80 * Set value in metadata from int
81 */
82 bool WriteMetadata(const TCHAR *name, INT32 value)
83 {
84 TCHAR buffer[64];
85 _sntprintf(buffer, 64, _T("%d"), value);
86 return WriteMetadata(name, buffer);
87 }
88
89 /**
90 * DB init queries
91 */
92 static const TCHAR *s_dbInitQueries[] =
93 {
94 _T("CREATE TABLE agent_policy (")
95 _T(" guid varchar(36) not null,")
96 _T(" type integer not null,")
97 _T(" server_info varchar(64) null,")
98 _T(" server_id number(20) not null,")
99 _T(" version integer not null,")
100 _T(" PRIMARY KEY(guid))"),
101
102 _T("CREATE TABLE dc_config (")
103 _T(" server_id number(20) not null,")
104 _T(" dci_id integer not null,")
105 _T(" type integer not null,")
106 _T(" origin integer not null,")
107 _T(" name varchar(1023) null,")
108 _T(" polling_interval integer not null,")
109 _T(" last_poll integer not null,")
110 _T(" snmp_port integer not null,")
111 _T(" snmp_target_guid varchar(36) not null,")
112 _T(" snmp_raw_type integer not null,")
113 _T(" PRIMARY KEY(server_id,dci_id))"),
114
115 _T("CREATE TABLE dc_queue (")
116 _T(" server_id number(20) not null,")
117 _T(" dci_id integer not null,")
118 _T(" dci_type integer not null,")
119 _T(" dci_origin integer not null,")
120 _T(" snmp_target_guid varchar(36) not null,")
121 _T(" timestamp integer not null,")
122 _T(" value varchar not null,")
123 _T(" status_code integer not null,")
124 _T(" PRIMARY KEY(server_id,dci_id,timestamp))"),
125
126 _T("CREATE TABLE dc_snmp_targets (")
127 _T(" guid varchar(36) not null,")
128 _T(" server_id number(20) not null,")
129 _T(" ip_address varchar(48) not null,")
130 _T(" snmp_version integer not null,")
131 _T(" port integer not null,")
132 _T(" auth_type integer not null,")
133 _T(" enc_type integer not null,")
134 _T(" auth_name varchar(63),")
135 _T(" auth_pass varchar(63),")
136 _T(" enc_pass varchar(63),")
137 _T(" PRIMARY KEY(guid))"),
138
139 _T("CREATE TABLE registry (")
140 _T(" attribute varchar(63) null,")
141 _T(" value varchar null,")
142 _T(" PRIMARY KEY(attribute))"),
143
144 NULL
145 };
146
147 /**
148 * Initialize new database
149 */
150 static bool InitDatabase()
151 {
152 for(int i = 0; s_dbInitQueries[i] != NULL; i++)
153 if (!DBQuery(s_db, s_dbInitQueries[i]))
154 return false;
155 nxlog_debug(1, _T("Empty local database initialized successfully"));
156 return true;
157 }
158
159 /**
160 * Database tables
161 */
162 static const TCHAR *s_dbTables[] = { _T("agent_policy"), _T("dc_config"), _T("dc_queue"), _T("dc_snmp_targets"), _T("registry"), NULL };
163
164 /**
165 * Check database structure
166 */
167 static bool CheckDatabaseStructure()
168 {
169 int version;
170 if (!DBIsTableExist(s_db, _T("metadata")))
171 {
172 DBQuery(s_db, _T("CREATE TABLE metadata (attribute varchar(63), value varchar(255), PRIMARY KEY(attribute))"));
173
174 // assume empty database, create tables
175 if (!InitDatabase())
176 {
177 nxlog_write(MSG_LOCAL_DB_CORRUPTED, NXLOG_ERROR, NULL);
178 return false;
179 }
180
181 TCHAR query[256];
182 _sntprintf(query, 256, _T("INSERT INTO metadata (attribute, value) VALUES ('SchemaVersion', '%d')"), DB_SCHEMA_VERSION);
183 DBQuery(s_db, query);
184
185 version = DB_SCHEMA_VERSION;
186 }
187 else
188 {
189 version = ReadMetadataAsInt(_T("SchemaVersion"));
190 }
191
192 if ((version <= 0) || (version > DB_SCHEMA_VERSION))
193 {
194 nxlog_write(MSG_LOCAL_DB_CORRUPTED, NXLOG_ERROR, NULL);
195 return false;
196 }
197
198 bool success = true;
199 for(int i = 0; s_dbTables[i] != NULL; i++)
200 {
201 if (!DBIsTableExist(s_db, s_dbTables[i]))
202 {
203 nxlog_debug(1, _T("Local database table %s does not exist"), s_dbTables[i]);
204 success = false;
205 }
206 }
207 if (!success)
208 {
209 nxlog_write(MSG_LOCAL_DB_CORRUPTED, NXLOG_ERROR, NULL);
210 return false;
211 }
212
213 return true;
214 }
215
216 /**
217 * Open local agent database
218 */
219 bool OpenLocalDatabase()
220 {
221 s_driver = DBLoadDriver(_T("sqlite.ddr"), _T(""), nxlog_get_debug_level() == 9, NULL, NULL);
222 if (s_driver == NULL)
223 {
224 return false;
225 }
226
227 TCHAR dbFile[MAX_PATH];
228 nx_strncpy(dbFile, g_szDataDirectory, MAX_PATH - 12);
229 if (dbFile[_tcslen(dbFile) - 1] != FS_PATH_SEPARATOR_CHAR)
230 _tcscat(dbFile, FS_PATH_SEPARATOR);
231 _tcscat(dbFile, _T("nxagentd.db"));
232 if (g_dwFlags & AF_SUBAGENT_LOADER)
233 {
234 _tcscat(dbFile, _T("."));
235 _tcscat(dbFile, g_masterAgent);
236 }
237
238 TCHAR errorText[DBDRV_MAX_ERROR_TEXT];
239 s_db = DBConnect(s_driver, NULL, dbFile, NULL, NULL, NULL, errorText);
240 if (s_db == NULL)
241 {
242 nxlog_debug(1, _T("Local database open error: %s"), errorText);
243 g_failFlags = FAIL_OPEN_DATABASE;
244 return false;
245 }
246
247 if (!CheckDatabaseStructure() || !UpgradeDatabase())
248 {
249 g_failFlags = FIAL_UPGRADE_DATABASE;
250 DBDisconnect(s_db);
251 s_db = NULL;
252 return false;
253 }
254
255 if (g_longRunningQueryThreshold != 0)
256 DBSetLongRunningThreshold(g_longRunningQueryThreshold);
257
258 DBQuery(s_db, _T("VACUUM"));
259 DebugPrintf(INVALID_INDEX, 1, _T("Local database opened successfully"));
260 return true;
261 }
262
263 /**
264 * Close local database
265 */
266 void CloseLocalDatabase()
267 {
268 DBDisconnect(s_db);
269 DBUnloadDriver(s_driver);
270 }
271
272 /**
273 * Get database handle
274 */
275 DB_HANDLE GetLocalDatabaseHandle()
276 {
277 return s_db;
278 }