Commit | Line | Data |
---|---|---|
2589cc10 | 1 | /* |
5039dede | 2 | ** nxdbmgr - NetXMS database manager |
56c41b56 | 3 | ** Copyright (C) 2004-2016 Victor Kirhenshtein |
5039dede AK |
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: check.cpp | |
20 | ** | |
21 | **/ | |
22 | ||
23 | #include "nxdbmgr.h" | |
24 | ||
25 | ||
26 | // | |
27 | // Static data | |
28 | // | |
29 | ||
30 | static int m_iNumErrors = 0; | |
31 | static int m_iNumFixes = 0; | |
32 | static int m_iStageErrors; | |
33 | static int m_iStageFixes; | |
34 | static TCHAR *m_pszStageMsg = NULL; | |
35 | ||
16a0cd88 VK |
36 | /** |
37 | * Start stage | |
38 | */ | |
5039dede AK |
39 | static void StartStage(const TCHAR *pszMsg) |
40 | { | |
41 | if (pszMsg != NULL) | |
42 | { | |
43 | safe_free(m_pszStageMsg); | |
44 | m_pszStageMsg = _tcsdup(pszMsg); | |
45 | } | |
84ee0f9c | 46 | WriteToTerminalEx(_T("\x1b[1m*\x1b[0m %-67s"), m_pszStageMsg); |
f669df41 | 47 | #ifndef _WIN32 |
5039dede AK |
48 | fflush(stdout); |
49 | #endif | |
50 | m_iStageErrors = m_iNumErrors; | |
51 | m_iStageFixes = m_iNumFixes; | |
52 | } | |
53 | ||
16a0cd88 VK |
54 | /** |
55 | * End stage | |
56 | */ | |
f669df41 | 57 | static void EndStage() |
5039dede AK |
58 | { |
59 | static const TCHAR *pszStatus[] = { _T("PASSED"), _T("FIXED "), _T("ERROR ") }; | |
f669df41 | 60 | static int nColor[] = { 32, 33, 31 }; |
5039dede AK |
61 | int nCode, nErrors; |
62 | ||
63 | nErrors = m_iNumErrors - m_iStageErrors; | |
64 | if (nErrors > 0) | |
65 | { | |
66 | nCode = (m_iNumFixes - m_iStageFixes == nErrors) ? 1 : 2; | |
67 | StartStage(NULL); // redisplay stage message | |
68 | } | |
69 | else | |
70 | { | |
71 | nCode = 0; | |
72 | } | |
2ac6ce86 | 73 | WriteToTerminalEx(_T(" \x1b[37;1m[\x1b[%d;1m%s\x1b[37;1m]\x1b[0m\n"), nColor[nCode], pszStatus[nCode]); |
5039dede AK |
74 | } |
75 | ||
16a0cd88 VK |
76 | /** |
77 | * Get object name from object_properties table | |
78 | */ | |
5039dede AK |
79 | static TCHAR *GetObjectName(DWORD dwId, TCHAR *pszBuffer) |
80 | { | |
81 | TCHAR szQuery[256]; | |
82 | DB_RESULT hResult; | |
83 | ||
08b214c6 | 84 | _sntprintf(szQuery, 256, _T("SELECT name FROM object_properties WHERE object_id=%d"), dwId); |
5039dede AK |
85 | hResult = SQLSelect(szQuery); |
86 | if (hResult != NULL) | |
87 | { | |
88 | if (DBGetNumRows(hResult) > 0) | |
89 | { | |
90 | DBGetField(hResult, 0, 0, pszBuffer, MAX_OBJECT_NAME); | |
91 | } | |
92 | else | |
93 | { | |
94 | _tcscpy(pszBuffer, _T("<unknown>")); | |
95 | } | |
96 | } | |
97 | else | |
98 | { | |
99 | _tcscpy(pszBuffer, _T("<unknown>")); | |
100 | } | |
101 | return pszBuffer; | |
102 | } | |
103 | ||
305c5d65 VK |
104 | /** |
105 | * Check that given node is inside at least one container or cluster | |
106 | */ | |
a6c1f07f | 107 | static bool NodeInContainer(DWORD id) |
4262c0dc VK |
108 | { |
109 | TCHAR query[256]; | |
110 | DB_RESULT hResult; | |
a6c1f07f | 111 | bool result = false; |
4262c0dc VK |
112 | |
113 | _sntprintf(query, 256, _T("SELECT container_id FROM container_members WHERE object_id=%d"), id); | |
114 | hResult = SQLSelect(query); | |
115 | if (hResult != NULL) | |
116 | { | |
117 | result = (DBGetNumRows(hResult) > 0); | |
118 | DBFreeResult(hResult); | |
119 | } | |
a6c1f07f VK |
120 | |
121 | if (!result) | |
122 | { | |
123 | _sntprintf(query, 256, _T("SELECT cluster_id FROM cluster_members WHERE node_id=%d"), id); | |
124 | hResult = SQLSelect(query); | |
125 | if (hResult != NULL) | |
126 | { | |
127 | result = (DBGetNumRows(hResult) > 0); | |
128 | DBFreeResult(hResult); | |
129 | } | |
130 | } | |
131 | ||
4262c0dc VK |
132 | return result; |
133 | } | |
134 | ||
305c5d65 VK |
135 | /** |
136 | * Find subnet for unlinked node | |
137 | */ | |
4262c0dc VK |
138 | static BOOL FindSubnetForNode(DWORD id, const TCHAR *name) |
139 | { | |
140 | DB_RESULT hResult, hResult2; | |
141 | TCHAR query[256], buffer[32]; | |
142 | int i, count; | |
4262c0dc VK |
143 | BOOL success = FALSE; |
144 | ||
145 | // Read list of interfaces of given node | |
c30c0c0f | 146 | _sntprintf(query, 256, _T("SELECT l.ip_addr,l.ip_netmask FROM interfaces i INNER JOIN interface_address_list l ON l.iface_id = i.id WHERE node_id=%d"), id); |
4262c0dc VK |
147 | hResult = SQLSelect(query); |
148 | if (hResult != NULL) | |
149 | { | |
150 | count = DBGetNumRows(hResult); | |
151 | for(i = 0; i < count; i++) | |
152 | { | |
c30c0c0f VK |
153 | InetAddress addr = DBGetFieldInetAddr(hResult, i, 0); |
154 | addr.setMaskBits(DBGetFieldLong(hResult, i, 1)); | |
155 | InetAddress subnet = addr.getSubnetAddress(); | |
2589cc10 | 156 | |
c30c0c0f | 157 | _sntprintf(query, 256, _T("SELECT id FROM subnets WHERE ip_addr='%s'"), subnet.toString(buffer)); |
4262c0dc VK |
158 | hResult2 = SQLSelect(query); |
159 | if (hResult2 != NULL) | |
160 | { | |
161 | if (DBGetNumRows(hResult2) > 0) | |
162 | { | |
c30c0c0f | 163 | UINT32 subnetId = DBGetFieldULong(hResult2, 0, 0); |
4262c0dc | 164 | m_iNumErrors++; |
c30c0c0f | 165 | if (GetYesNo(_T("\rUnlinked node object %d (\"%s\") can be linked to subnet %d (%s). Link?"), id, name, subnetId, buffer)) |
4262c0dc | 166 | { |
c30c0c0f | 167 | _sntprintf(query, 256, _T("INSERT INTO nsmap (subnet_id,node_id) VALUES (%d,%d)"), subnetId, id); |
4262c0dc VK |
168 | if (SQLQuery(query)) |
169 | { | |
170 | success = TRUE; | |
171 | m_iNumFixes++; | |
172 | break; | |
173 | } | |
174 | else | |
175 | { | |
176 | // Node remains unlinked, so error count will be | |
177 | // incremented again by node deletion code or next iteration | |
178 | m_iNumErrors--; | |
179 | } | |
180 | } | |
181 | else | |
182 | { | |
183 | // Node remains unlinked, so error count will be | |
184 | // incremented again by node deletion code | |
185 | m_iNumErrors--; | |
186 | } | |
187 | } | |
188 | DBFreeResult(hResult2); | |
189 | } | |
190 | } | |
191 | DBFreeResult(hResult); | |
192 | } | |
193 | return success; | |
194 | } | |
195 | ||
7777b139 VK |
196 | /** |
197 | * Check zone objects | |
198 | */ | |
0d9b58ef VK |
199 | static void CheckZones() |
200 | { | |
201 | DB_RESULT hResult, hResult2; | |
202 | DWORD i, dwNumObjects, dwId; | |
7c2b8394 | 203 | TCHAR szQuery[1024]; |
0d9b58ef VK |
204 | |
205 | StartStage(_T("Checking zone objects...")); | |
206 | hResult = SQLSelect(_T("SELECT id FROM zones")); | |
207 | if (hResult != NULL) | |
208 | { | |
209 | dwNumObjects = DBGetNumRows(hResult); | |
210 | for(i = 0; i < dwNumObjects; i++) | |
211 | { | |
212 | dwId = DBGetFieldULong(hResult, i, 0); | |
213 | ||
214 | // Check appropriate record in object_properties table | |
215 | _sntprintf(szQuery, 256, _T("SELECT name,is_deleted FROM object_properties WHERE object_id=%d"), (int)dwId); | |
216 | hResult2 = SQLSelect(szQuery); | |
217 | if (hResult2 != NULL) | |
218 | { | |
219 | if ((DBGetNumRows(hResult2) == 0) && (dwId != 4)) // Properties for built-in zone can be missing | |
220 | { | |
221 | m_iNumErrors++; | |
222 | if (GetYesNo(_T("\rMissing zone object %d properties. Create?"), dwId)) | |
223 | { | |
224 | uuid_t guid; | |
225 | TCHAR guidText[128]; | |
226 | ||
999945fa | 227 | _uuid_generate(guid); |
2589cc10 | 228 | _sntprintf(szQuery, 1024, |
0d9b58ef VK |
229 | _T("INSERT INTO object_properties (object_id,guid,name,") |
230 | _T("status,is_deleted,is_system,inherit_access_rights,") | |
231 | _T("last_modified,status_calc_alg,status_prop_alg,") | |
232 | _T("status_fixed_val,status_shift,status_translation,") | |
233 | _T("status_single_threshold,status_thresholds,location_type,") | |
56c41b56 | 234 | _T("latitude,longitude,image,maint_mode,maint_event_id) VALUES ") |
0d9b58ef | 235 | _T("(%d,'%s','lost_zone_%d',5,0,0,1,") TIME_T_FMT _T(",0,0,0,0,0,0,'00000000',0,") |
56c41b56 | 236 | _T("'0.000000','0.000000','00000000-0000-0000-0000-000000000000','0',0)"), |
999945fa | 237 | (int)dwId, _uuid_to_string(guid, guidText), (int)dwId, TIME_T_FCAST(time(NULL))); |
0d9b58ef VK |
238 | if (SQLQuery(szQuery)) |
239 | m_iNumFixes++; | |
240 | } | |
241 | } | |
0d9b58ef VK |
242 | DBFreeResult(hResult2); |
243 | } | |
244 | } | |
245 | DBFreeResult(hResult); | |
246 | } | |
247 | EndStage(); | |
248 | } | |
249 | ||
305c5d65 VK |
250 | /** |
251 | * Check node objects | |
252 | */ | |
035a4d73 | 253 | static void CheckNodes() |
5039dede AK |
254 | { |
255 | DB_RESULT hResult, hResult2; | |
256 | DWORD i, dwNumObjects, dwId; | |
257 | TCHAR szQuery[1024], szName[MAX_OBJECT_NAME]; | |
7833a69f | 258 | BOOL bResult, bIsDeleted = FALSE; |
5039dede AK |
259 | |
260 | StartStage(_T("Checking node objects...")); | |
261 | hResult = SQLSelect(_T("SELECT id,primary_ip FROM nodes")); | |
262 | if (hResult != NULL) | |
263 | { | |
264 | dwNumObjects = DBGetNumRows(hResult); | |
265 | for(i = 0; i < dwNumObjects; i++) | |
266 | { | |
267 | dwId = DBGetFieldULong(hResult, i, 0); | |
268 | ||
269 | // Check appropriate record in object_properties table | |
270 | _sntprintf(szQuery, 256, _T("SELECT name,is_deleted FROM object_properties WHERE object_id=%d"), dwId); | |
271 | hResult2 = SQLSelect(szQuery); | |
272 | if (hResult2 != NULL) | |
273 | { | |
274 | if (DBGetNumRows(hResult2) == 0) | |
275 | { | |
276 | m_iNumErrors++; | |
a4743a0f | 277 | if (GetYesNo(_T("\rMissing node object %d properties. Create?"), dwId)) |
5039dede | 278 | { |
478d4ff4 | 279 | uuid_t guid; |
0d9b58ef | 280 | TCHAR guidText[128]; |
478d4ff4 | 281 | |
999945fa | 282 | _uuid_generate(guid); |
2589cc10 | 283 | _sntprintf(szQuery, 1024, |
478d4ff4 VK |
284 | _T("INSERT INTO object_properties (object_id,guid,name,") |
285 | _T("status,is_deleted,is_system,inherit_access_rights,") | |
08b214c6 VK |
286 | _T("last_modified,status_calc_alg,status_prop_alg,") |
287 | _T("status_fixed_val,status_shift,status_translation,") | |
478d4ff4 | 288 | _T("status_single_threshold,status_thresholds,location_type,") |
56c41b56 VK |
289 | _T("latitude,longitude,location_accuracy,location_timestamp,") |
290 | _T("image,submap_id,maint_mode,maint_event_id) VALUES ") | |
0d9b58ef | 291 | _T("(%d,'%s','lost_node_%d',5,0,0,1,") TIME_T_FMT _T(",0,0,0,0,0,0,'00000000',0,") |
56c41b56 | 292 | _T("'0.000000','0.000000',0,0,'00000000-0000-0000-0000-000000000000',0,'0',0)"), |
999945fa | 293 | (int)dwId, _uuid_to_string(guid, guidText), (int)dwId, TIME_T_FCAST(time(NULL))); |
5039dede AK |
294 | if (SQLQuery(szQuery)) |
295 | m_iNumFixes++; | |
296 | } | |
297 | } | |
298 | else | |
299 | { | |
300 | DBGetField(hResult2, 0, 0, szName, MAX_OBJECT_NAME); | |
301 | bIsDeleted = DBGetFieldLong(hResult2, 0, 1) ? TRUE : FALSE; | |
302 | } | |
303 | DBFreeResult(hResult2); | |
304 | } | |
305 | ||
306 | if (!bIsDeleted) | |
307 | { | |
308 | _sntprintf(szQuery, 1024, _T("SELECT subnet_id FROM nsmap WHERE node_id=%d"), dwId); | |
309 | hResult2 = SQLSelect(szQuery); | |
310 | if (hResult2 != NULL) | |
311 | { | |
4262c0dc | 312 | if ((DBGetNumRows(hResult2) == 0) && (!NodeInContainer(dwId))) |
5039dede | 313 | { |
4262c0dc VK |
314 | if ((DBGetFieldIPAddr(hResult, i, 1) == 0) || (!FindSubnetForNode(dwId, szName))) |
315 | { | |
316 | m_iNumErrors++; | |
5e5461a9 | 317 | if (GetYesNo(_T("\rUnlinked node object %d (\"%s\"). Delete it?"), dwId, szName)) |
4262c0dc VK |
318 | { |
319 | _sntprintf(szQuery, 1024, _T("DELETE FROM nodes WHERE id=%d"), dwId); | |
320 | bResult = SQLQuery(szQuery); | |
321 | _sntprintf(szQuery, 1024, _T("DELETE FROM acl WHERE object_id=%d"), dwId); | |
322 | bResult = bResult && SQLQuery(szQuery); | |
323 | _sntprintf(szQuery, 1024, _T("DELETE FROM object_properties WHERE object_id=%d"), dwId); | |
324 | if (SQLQuery(szQuery) && bResult) | |
325 | m_iNumFixes++; | |
326 | } | |
327 | } | |
5039dede AK |
328 | } |
329 | DBFreeResult(hResult2); | |
330 | } | |
331 | } | |
332 | } | |
333 | DBFreeResult(hResult); | |
334 | } | |
335 | EndStage(); | |
336 | } | |
337 | ||
305c5d65 VK |
338 | /** |
339 | * Check node component objects | |
340 | */ | |
5039dede AK |
341 | static void CheckComponents(const TCHAR *pszDisplayName, const TCHAR *pszTable) |
342 | { | |
343 | DB_RESULT hResult, hResult2; | |
344 | DWORD i, dwNumObjects, dwId; | |
345 | TCHAR szQuery[1024], szName[MAX_OBJECT_NAME]; | |
5039dede | 346 | |
08b214c6 | 347 | _sntprintf(szQuery, 1024, _T("Checking %s objects..."), pszDisplayName); |
5039dede AK |
348 | StartStage(szQuery); |
349 | ||
08b214c6 | 350 | _sntprintf(szQuery, 1024, _T("SELECT id,node_id FROM %s"), pszTable); |
5039dede AK |
351 | hResult = SQLSelect(szQuery); |
352 | if (hResult != NULL) | |
353 | { | |
354 | dwNumObjects = DBGetNumRows(hResult); | |
355 | for(i = 0; i < dwNumObjects; i++) | |
356 | { | |
357 | dwId = DBGetFieldULong(hResult, i, 0); | |
358 | ||
359 | // Check appropriate record in object_properties table | |
08b214c6 | 360 | _sntprintf(szQuery, 1024, _T("SELECT name,is_deleted FROM object_properties WHERE object_id=%d"), dwId); |
5039dede AK |
361 | hResult2 = SQLSelect(szQuery); |
362 | if (hResult2 != NULL) | |
363 | { | |
364 | if (DBGetNumRows(hResult2) == 0) | |
365 | { | |
366 | m_iNumErrors++; | |
a4743a0f | 367 | if (GetYesNo(_T("\rMissing %s object %d properties. Create?"), pszDisplayName, dwId)) |
5039dede | 368 | { |
478d4ff4 | 369 | uuid_t guid; |
0d9b58ef | 370 | TCHAR guidText[128]; |
478d4ff4 | 371 | |
999945fa | 372 | _uuid_generate(guid); |
2589cc10 | 373 | _sntprintf(szQuery, 1024, |
478d4ff4 VK |
374 | _T("INSERT INTO object_properties (object_id,guid,name,") |
375 | _T("status,is_deleted,is_system,inherit_access_rights,") | |
08b214c6 VK |
376 | _T("last_modified,status_calc_alg,status_prop_alg,") |
377 | _T("status_fixed_val,status_shift,status_translation,") | |
478d4ff4 | 378 | _T("status_single_threshold,status_thresholds,location_type,") |
56c41b56 | 379 | _T("latitude,longitude,image,maint_mode,maint_event_id) VALUES ") |
0d9b58ef | 380 | _T("(%d,'%s','lost_%s_%d',5,0,0,1,") TIME_T_FMT _T(",0,0,0,0,0,0,'00000000',0,") |
56c41b56 | 381 | _T("'0.000000','0.000000','00000000-0000-0000-0000-000000000000','0',0)"), |
999945fa | 382 | (int)dwId, _uuid_to_string(guid, guidText), pszDisplayName, (int)dwId, TIME_T_FCAST(time(NULL))); |
5039dede AK |
383 | if (SQLQuery(szQuery)) |
384 | m_iNumFixes++; | |
385 | szName[0] = 0; | |
386 | } | |
387 | } | |
388 | else | |
389 | { | |
390 | DBGetField(hResult2, 0, 0, szName, MAX_OBJECT_NAME); | |
5039dede AK |
391 | } |
392 | DBFreeResult(hResult2); | |
393 | } | |
394 | else | |
395 | { | |
396 | szName[0] = 0; | |
397 | } | |
398 | ||
399 | // Check if referred node exists | |
400 | _sntprintf(szQuery, 256, _T("SELECT name FROM object_properties WHERE object_id=%d AND is_deleted=0"), | |
401 | DBGetFieldULong(hResult, i, 1)); | |
402 | hResult2 = SQLSelect(szQuery); | |
403 | if (hResult2 != NULL) | |
404 | { | |
405 | if (DBGetNumRows(hResult2) == 0) | |
406 | { | |
407 | m_iNumErrors++; | |
408 | dwId = DBGetFieldULong(hResult, i, 0); | |
5e5461a9 | 409 | if (GetYesNo(_T("\rUnlinked %s object %d (\"%s\"). Delete it?"), pszDisplayName, dwId, szName)) |
5039dede AK |
410 | { |
411 | _sntprintf(szQuery, 256, _T("DELETE FROM %s WHERE id=%d"), pszTable, dwId); | |
412 | if (SQLQuery(szQuery)) | |
413 | { | |
414 | _sntprintf(szQuery, 256, _T("DELETE FROM object_properties WHERE object_id=%d"), dwId); | |
415 | SQLQuery(szQuery); | |
416 | m_iNumFixes++; | |
417 | } | |
418 | } | |
419 | } | |
420 | DBFreeResult(hResult2); | |
421 | } | |
422 | } | |
423 | DBFreeResult(hResult); | |
424 | } | |
425 | EndStage(); | |
426 | } | |
427 | ||
305c5d65 VK |
428 | /** |
429 | * Check common object properties | |
430 | */ | |
0d9b58ef | 431 | static void CheckObjectProperties() |
5039dede AK |
432 | { |
433 | DB_RESULT hResult; | |
434 | TCHAR szQuery[1024]; | |
435 | DWORD i, dwNumRows, dwObjectId; | |
436 | ||
437 | StartStage(_T("Checking object properties...")); | |
438 | hResult = SQLSelect(_T("SELECT object_id,name,last_modified FROM object_properties")); | |
439 | if (hResult != NULL) | |
440 | { | |
441 | dwNumRows = DBGetNumRows(hResult); | |
442 | for(i = 0; i < dwNumRows; i++) | |
443 | { | |
444 | dwObjectId = DBGetFieldULong(hResult, i, 0); | |
445 | ||
446 | // Check last change time | |
447 | if (DBGetFieldULong(hResult, i, 2) == 0) | |
448 | { | |
449 | m_iNumErrors++; | |
5e5461a9 | 450 | if (GetYesNo(_T("\rObject %d [%s] has invalid timestamp. Fix it?"), |
a4743a0f | 451 | dwObjectId, DBGetField(hResult, i, 1, szQuery, 1024))) |
5039dede | 452 | { |
0d9b58ef VK |
453 | _sntprintf(szQuery, 1024, _T("UPDATE object_properties SET last_modified=") TIME_T_FMT _T(" WHERE object_id=%d"), |
454 | TIME_T_FCAST(time(NULL)), (int)dwObjectId); | |
5039dede AK |
455 | if (SQLQuery(szQuery)) |
456 | m_iNumFixes++; | |
457 | } | |
458 | } | |
459 | } | |
460 | DBFreeResult(hResult); | |
461 | } | |
462 | EndStage(); | |
463 | } | |
464 | ||
305c5d65 VK |
465 | /** |
466 | * Check cluster objects | |
467 | */ | |
0d9b58ef | 468 | static void CheckClusters() |
5039dede AK |
469 | { |
470 | DB_RESULT hResult; | |
471 | TCHAR szQuery[256], szName[MAX_OBJECT_NAME]; | |
472 | DWORD i, dwNumRows, dwObjectId, dwId; | |
473 | ||
474 | StartStage(_T("Checking cluster objects...")); | |
475 | hResult = SQLSelect(_T("SELECT cluster_id,node_id FROM cluster_members")); | |
476 | if (hResult != NULL) | |
477 | { | |
478 | dwNumRows = DBGetNumRows(hResult); | |
479 | for(i = 0; i < dwNumRows; i++) | |
480 | { | |
481 | dwObjectId = DBGetFieldULong(hResult, i, 1); | |
06b83321 | 482 | if (!IsDatabaseRecordExist(_T("nodes"), _T("id"), dwObjectId)) |
5039dede AK |
483 | { |
484 | m_iNumErrors++; | |
485 | dwId = DBGetFieldULong(hResult, i, 0); | |
a4743a0f VK |
486 | if (GetYesNo(_T("\rCluster object %s [%d] refers to non-existing node %d. Dereference?"), |
487 | GetObjectName(dwId, szName), dwId, dwObjectId)) | |
5039dede AK |
488 | { |
489 | _sntprintf(szQuery, 256, _T("DELETE FROM cluster_members WHERE cluster_id=%d AND node_id=%d"),dwId, dwObjectId); | |
490 | if (SQLQuery(szQuery)) | |
491 | { | |
492 | m_iNumFixes++; | |
493 | } | |
494 | } | |
495 | } | |
496 | } | |
497 | DBFreeResult(hResult); | |
498 | } | |
499 | EndStage(); | |
500 | } | |
501 | ||
305c5d65 VK |
502 | /** |
503 | * Returns TRUE if SELECT returns non-empty set | |
504 | */ | |
5039dede AK |
505 | static BOOL CheckResultSet(TCHAR *pszQuery) |
506 | { | |
507 | DB_RESULT hResult; | |
508 | BOOL bResult = FALSE; | |
509 | ||
510 | hResult = SQLSelect(pszQuery); | |
511 | if (hResult != NULL) | |
512 | { | |
513 | bResult = (DBGetNumRows(hResult) > 0); | |
514 | DBFreeResult(hResult); | |
515 | } | |
516 | return bResult; | |
517 | } | |
518 | ||
305c5d65 VK |
519 | /** |
520 | * Check event processing policy | |
521 | */ | |
0d9b58ef | 522 | static void CheckEPP() |
5039dede AK |
523 | { |
524 | DB_RESULT hResult; | |
525 | TCHAR szQuery[1024]; | |
526 | int i, iNumRows; | |
527 | DWORD dwId; | |
528 | ||
529 | StartStage(_T("Checking event processing policy...")); | |
2589cc10 | 530 | |
5039dede AK |
531 | // Check source object ID's |
532 | hResult = SQLSelect(_T("SELECT object_id FROM policy_source_list")); | |
533 | if (hResult != NULL) | |
534 | { | |
535 | iNumRows = DBGetNumRows(hResult); | |
536 | for(i = 0; i < iNumRows; i++) | |
537 | { | |
538 | dwId = DBGetFieldULong(hResult, i, 0); | |
08b214c6 | 539 | _sntprintf(szQuery, 1024, _T("SELECT object_id FROM object_properties WHERE object_id=%d"), dwId); |
5039dede AK |
540 | if (!CheckResultSet(szQuery)) |
541 | { | |
542 | m_iNumErrors++; | |
5e5461a9 | 543 | if (GetYesNo(_T("\rInvalid object ID %d used in policy. Delete it from policy?"), dwId)) |
5039dede | 544 | { |
08b214c6 | 545 | _sntprintf(szQuery, 1024, _T("DELETE FROM policy_source_list WHERE object_id=%d"), dwId); |
5039dede AK |
546 | if (SQLQuery(szQuery)) |
547 | m_iNumFixes++; | |
548 | } | |
549 | } | |
550 | } | |
551 | DBFreeResult(hResult); | |
552 | } | |
553 | ||
554 | // Check event ID's | |
555 | hResult = SQLSelect(_T("SELECT event_code FROM policy_event_list")); | |
556 | if (hResult != NULL) | |
557 | { | |
558 | iNumRows = DBGetNumRows(hResult); | |
559 | for(i = 0; i < iNumRows; i++) | |
560 | { | |
561 | dwId = DBGetFieldULong(hResult, i, 0); | |
562 | if (dwId & GROUP_FLAG) | |
08b214c6 | 563 | _sntprintf(szQuery, 1024, _T("SELECT id FROM event_groups WHERE id=%d"), dwId); |
5039dede | 564 | else |
08b214c6 | 565 | _sntprintf(szQuery, 1024, _T("SELECT event_code FROM event_cfg WHERE event_code=%d"), dwId); |
5039dede AK |
566 | if (!CheckResultSet(szQuery)) |
567 | { | |
568 | m_iNumErrors++; | |
5e5461a9 | 569 | if (GetYesNo(_T("\rInvalid event%s ID 0x%08X referenced in policy. Delete this reference?"), (dwId & GROUP_FLAG) ? _T(" group") : _T(""), dwId)) |
5039dede | 570 | { |
08b214c6 | 571 | _sntprintf(szQuery, 1024, _T("DELETE FROM policy_event_list WHERE event_code=%d"), dwId); |
5039dede AK |
572 | if (SQLQuery(szQuery)) |
573 | m_iNumFixes++; | |
574 | } | |
575 | } | |
576 | } | |
577 | DBFreeResult(hResult); | |
578 | } | |
579 | ||
580 | // Check action ID's | |
581 | hResult = SQLSelect(_T("SELECT action_id FROM policy_action_list")); | |
582 | if (hResult != NULL) | |
583 | { | |
584 | iNumRows = DBGetNumRows(hResult); | |
585 | for(i = 0; i < iNumRows; i++) | |
586 | { | |
587 | dwId = DBGetFieldULong(hResult, i, 0); | |
08b214c6 | 588 | _sntprintf(szQuery, 1024, _T("SELECT action_id FROM actions WHERE action_id=%d"), dwId); |
5039dede AK |
589 | if (!CheckResultSet(szQuery)) |
590 | { | |
591 | m_iNumErrors++; | |
5e5461a9 | 592 | if (GetYesNo(_T("\rInvalid action ID %d referenced in policy. Delete this reference?"), dwId)) |
5039dede | 593 | { |
08b214c6 | 594 | _sntprintf(szQuery, 1024, _T("DELETE FROM policy_action_list WHERE action_id=%d"), dwId); |
5039dede AK |
595 | if (SQLQuery(szQuery)) |
596 | m_iNumFixes++; | |
597 | } | |
598 | } | |
599 | } | |
600 | DBFreeResult(hResult); | |
601 | } | |
602 | ||
603 | EndStage(); | |
604 | } | |
605 | ||
85ae39bc VK |
606 | /** |
607 | * Create idata_xx table | |
608 | */ | |
609 | BOOL CreateIDataTable(DWORD nodeId) | |
5039dede | 610 | { |
08b214c6 | 611 | TCHAR szQuery[256], szQueryTemplate[256]; |
5039dede AK |
612 | DWORD i; |
613 | ||
85ae39bc | 614 | MetaDataReadStr(_T("IDataTableCreationCommand"), szQueryTemplate, 255, _T("")); |
08b214c6 | 615 | _sntprintf(szQuery, 256, szQueryTemplate, nodeId); |
5039dede AK |
616 | if (!SQLQuery(szQuery)) |
617 | return FALSE; | |
618 | ||
619 | for(i = 0; i < 10; i++) | |
620 | { | |
08b214c6 | 621 | _sntprintf(szQuery, 256, _T("IDataIndexCreationCommand_%d"), i); |
85ae39bc | 622 | MetaDataReadStr(szQuery, szQueryTemplate, 255, _T("")); |
5039dede AK |
623 | if (szQueryTemplate[0] != 0) |
624 | { | |
08b214c6 | 625 | _sntprintf(szQuery, 256, szQueryTemplate, nodeId, nodeId); |
5039dede AK |
626 | if (!SQLQuery(szQuery)) |
627 | return FALSE; | |
628 | } | |
629 | } | |
630 | ||
631 | return TRUE; | |
632 | } | |
633 | ||
85ae39bc | 634 | /** |
22aaa779 | 635 | * Create tdata_xx table - pre V281 version |
85ae39bc | 636 | */ |
22aaa779 | 637 | BOOL CreateTDataTable_preV281(DWORD nodeId) |
85ae39bc VK |
638 | { |
639 | TCHAR szQuery[256], szQueryTemplate[256]; | |
640 | DWORD i; | |
5039dede | 641 | |
85ae39bc VK |
642 | MetaDataReadStr(_T("TDataTableCreationCommand"), szQueryTemplate, 255, _T("")); |
643 | _sntprintf(szQuery, 256, szQueryTemplate, nodeId); | |
644 | if (!SQLQuery(szQuery)) | |
645 | return FALSE; | |
5039dede | 646 | |
85ae39bc VK |
647 | for(i = 0; i < 10; i++) |
648 | { | |
649 | _sntprintf(szQuery, 256, _T("TDataIndexCreationCommand_%d"), i); | |
650 | MetaDataReadStr(szQuery, szQueryTemplate, 255, _T("")); | |
651 | if (szQueryTemplate[0] != 0) | |
652 | { | |
653 | _sntprintf(szQuery, 256, szQueryTemplate, nodeId, nodeId); | |
654 | if (!SQLQuery(szQuery)) | |
655 | return FALSE; | |
656 | } | |
657 | } | |
658 | ||
659 | return TRUE; | |
660 | } | |
661 | ||
22aaa779 | 662 | /** |
63604cda | 663 | * Create tdata_xx table |
22aaa779 | 664 | */ |
63604cda | 665 | BOOL CreateTDataTable(DWORD nodeId) |
22aaa779 VK |
666 | { |
667 | TCHAR szQuery[256], szQueryTemplate[256]; | |
668 | DWORD i; | |
669 | ||
670 | for(i = 0; i < 10; i++) | |
671 | { | |
672 | _sntprintf(szQuery, 256, _T("TDataTableCreationCommand_%d"), i); | |
673 | MetaDataReadStr(szQuery, szQueryTemplate, 255, _T("")); | |
674 | if (szQueryTemplate[0] != 0) | |
675 | { | |
1d4f7890 | 676 | _sntprintf(szQuery, 256, szQueryTemplate, nodeId, nodeId); |
22aaa779 VK |
677 | if (!SQLQuery(szQuery)) |
678 | return FALSE; | |
679 | } | |
680 | } | |
681 | ||
682 | for(i = 0; i < 10; i++) | |
683 | { | |
684 | _sntprintf(szQuery, 256, _T("TDataIndexCreationCommand_%d"), i); | |
685 | MetaDataReadStr(szQuery, szQueryTemplate, 255, _T("")); | |
686 | if (szQueryTemplate[0] != 0) | |
687 | { | |
688 | _sntprintf(szQuery, 256, szQueryTemplate, nodeId, nodeId); | |
689 | if (!SQLQuery(szQuery)) | |
690 | return FALSE; | |
691 | } | |
692 | } | |
693 | ||
694 | return TRUE; | |
695 | } | |
696 | ||
85ae39bc VK |
697 | /** |
698 | * Check collected data | |
699 | */ | |
0d9b58ef | 700 | static void CheckIData() |
5039dede AK |
701 | { |
702 | int i, nodeCount; | |
703 | time_t now; | |
704 | DWORD nodeId; | |
705 | TCHAR query[1024]; | |
706 | DB_RESULT hResultNodes, hResult; | |
707 | ||
708 | StartStage(_T("Checking collected data...")); | |
2589cc10 | 709 | |
5039dede AK |
710 | now = time(NULL); |
711 | hResultNodes = SQLSelect(_T("SELECT id FROM nodes")); | |
712 | if (hResultNodes != NULL) | |
713 | { | |
714 | nodeCount = DBGetNumRows(hResultNodes); | |
715 | for(i = 0; i < nodeCount; i++) | |
716 | { | |
717 | nodeId = DBGetFieldULong(hResultNodes, i, 0); | |
376e15e8 | 718 | _sntprintf(query, 1024, _T("SELECT count(*) FROM idata_%d WHERE idata_timestamp>") TIME_T_FMT, nodeId, TIME_T_FCAST(now)); |
5039dede AK |
719 | hResult = SQLSelect(query); |
720 | if (hResult != NULL) | |
721 | { | |
722 | if (DBGetFieldLong(hResult, 0, 0) > 0) | |
723 | { | |
724 | m_iNumErrors++; | |
5e5461a9 | 725 | if (GetYesNo(_T("\rFound collected data for node [%d] with timestamp in the future. Delete them?"), nodeId)) |
5039dede | 726 | { |
376e15e8 | 727 | _sntprintf(query, 1024, _T("DELETE FROM idata_%d WHERE idata_timestamp>") TIME_T_FMT, nodeId, TIME_T_FCAST(now)); |
5039dede AK |
728 | if (SQLQuery(query)) |
729 | m_iNumFixes++; | |
730 | } | |
731 | } | |
732 | DBFreeResult(hResult); | |
733 | } | |
5039dede AK |
734 | } |
735 | DBFreeResult(hResultNodes); | |
736 | } | |
737 | ||
376e15e8 | 738 | _sntprintf(query, 1024, _T("SELECT count(*) FROM raw_dci_values WHERE last_poll_time>") TIME_T_FMT, TIME_T_FCAST(now)); |
5039dede AK |
739 | hResult = SQLSelect(query); |
740 | if (hResult != NULL) | |
741 | { | |
742 | if (DBGetFieldLong(hResult, 0, 0) > 0) | |
743 | { | |
744 | m_iNumErrors++; | |
5e5461a9 | 745 | if (GetYesNo(_T("\rFound DCIs with last poll timestamp in the future. Fix it?"))) |
5039dede | 746 | { |
376e15e8 | 747 | _sntprintf(query, 1024, _T("UPDATE raw_dci_values SET last_poll_time=") TIME_T_FMT _T(" WHERE last_poll_time>") TIME_T_FMT, TIME_T_FCAST(now), TIME_T_FCAST(now)); |
5039dede AK |
748 | if (SQLQuery(query)) |
749 | m_iNumFixes++; | |
750 | } | |
751 | } | |
752 | DBFreeResult(hResult); | |
753 | } | |
754 | ||
755 | EndStage(); | |
756 | } | |
757 | ||
daf3c104 VK |
758 | /** |
759 | * Check if given data table exist | |
760 | */ | |
63604cda | 761 | BOOL IsDataTableExist(const TCHAR *format, DWORD id) |
daf3c104 VK |
762 | { |
763 | TCHAR table[256]; | |
764 | _sntprintf(table, 256, format, id); | |
fdf1ed50 VK |
765 | int rc = DBIsTableExist(g_hCoreDB, table); |
766 | if (rc == DBIsTableExist_Failure) | |
767 | { | |
768 | _tprintf(_T("WARNING: call to DBIsTableExist(\"%s\") failed\n"), table); | |
769 | } | |
770 | return rc != DBIsTableExist_NotFound; | |
daf3c104 VK |
771 | } |
772 | ||
773 | /** | |
774 | * Check data tables for given o bject class | |
775 | */ | |
776 | static void CheckDataTablesForClass(const TCHAR *className, const TCHAR *classDescr) | |
777 | { | |
778 | TCHAR query[1024]; | |
779 | _sntprintf(query, 256, _T("SELECT id FROM %s"), className); | |
780 | DB_RESULT hResult = SQLSelect(query); | |
781 | if (hResult != NULL) | |
782 | { | |
783 | int count = DBGetNumRows(hResult); | |
784 | for(int i = 0; i < count; i++) | |
785 | { | |
786 | DWORD id = DBGetFieldULong(hResult, i, 0); | |
787 | ||
788 | // IDATA | |
789 | if (!IsDataTableExist(_T("idata_%d"), id)) | |
790 | { | |
791 | m_iNumErrors++; | |
792 | if (GetYesNo(_T("\rData collection table (IDATA) for %s [%d] not found. Create? (Y/N) "), classDescr, id)) | |
793 | { | |
794 | if (CreateIDataTable(id)) | |
795 | m_iNumFixes++; | |
796 | } | |
797 | } | |
798 | ||
799 | // TDATA | |
63604cda | 800 | if (IsDataTableExist(_T("tdata_%d"), id)) |
daf3c104 VK |
801 | { |
802 | m_iNumErrors++; | |
803 | if (GetYesNo(_T("\rData collection table (TDATA) for %s [%d] not found. Create? (Y/N) "), classDescr, id)) | |
804 | { | |
63604cda | 805 | if (CreateTDataTable(id)) |
daf3c104 VK |
806 | m_iNumFixes++; |
807 | } | |
808 | } | |
809 | } | |
810 | DBFreeResult(hResult); | |
811 | } | |
812 | } | |
813 | ||
814 | /** | |
815 | * Check data tables | |
816 | */ | |
817 | static void CheckDataTables() | |
818 | { | |
819 | StartStage(_T("Checking data tables...")); | |
820 | ||
821 | CheckDataTablesForClass(_T("nodes"), _T("node")); | |
822 | CheckDataTablesForClass(_T("clusters"), _T("cluster")); | |
823 | CheckDataTablesForClass(_T("mobile_devices"), _T("mobile device")); | |
6cedcfc3 | 824 | CheckDataTablesForClass(_T("access_points"), _T("access point")); |
63604cda | 825 | CheckDataTablesForClass(_T("chassis"), _T("chassis")); |
daf3c104 VK |
826 | |
827 | EndStage(); | |
828 | } | |
829 | ||
85ae39bc VK |
830 | /** |
831 | * Check template to node mapping | |
832 | */ | |
0d9b58ef | 833 | static void CheckTemplateNodeMapping() |
5039dede AK |
834 | { |
835 | DB_RESULT hResult; | |
836 | TCHAR name[256], query[256]; | |
837 | DWORD i, dwNumRows, dwTemplateId, dwNodeId; | |
838 | ||
839 | StartStage(_T("Checking template to node mapping...")); | |
840 | hResult = SQLSelect(_T("SELECT template_id,node_id FROM dct_node_map ORDER BY template_id")); | |
841 | if (hResult != NULL) | |
842 | { | |
843 | dwNumRows = DBGetNumRows(hResult); | |
844 | for(i = 0; i < dwNumRows; i++) | |
845 | { | |
846 | dwTemplateId = DBGetFieldULong(hResult, i, 0); | |
847 | dwNodeId = DBGetFieldULong(hResult, i, 1); | |
848 | ||
849 | // Check node existence | |
06b83321 VK |
850 | if (!IsDatabaseRecordExist(_T("nodes"), _T("id"), dwNodeId) && |
851 | !IsDatabaseRecordExist(_T("clusters"), _T("id"), dwNodeId) && | |
852 | !IsDatabaseRecordExist(_T("mobile_devices"), _T("id"), dwNodeId)) | |
5039dede AK |
853 | { |
854 | m_iNumErrors++; | |
855 | GetObjectName(dwTemplateId, name); | |
5e5461a9 | 856 | if (GetYesNo(_T("\rTemplate %d [%s] mapped to non-existent node %d. Delete this mapping?"), dwTemplateId, name, dwNodeId)) |
5039dede AK |
857 | { |
858 | _sntprintf(query, 256, _T("DELETE FROM dct_node_map WHERE template_id=%d AND node_id=%d"), | |
859 | dwTemplateId, dwNodeId); | |
860 | if (SQLQuery(query)) | |
861 | m_iNumFixes++; | |
862 | } | |
863 | } | |
864 | } | |
865 | DBFreeResult(hResult); | |
866 | } | |
867 | EndStage(); | |
868 | } | |
869 | ||
16a0cd88 VK |
870 | /** |
871 | * Check network map links | |
872 | */ | |
873 | static void CheckMapLinks() | |
874 | { | |
875 | StartStage(_T("Checking network map links...")); | |
876 | ||
877 | for(int pass = 1; pass <= 2; pass++) | |
878 | { | |
879 | TCHAR query[1024]; | |
880 | _sntprintf(query, 1024, | |
881 | _T("SELECT network_map_links.map_id,network_map_links.element1,network_map_links.element2 ") | |
882 | _T("FROM network_map_links ") | |
883 | _T("LEFT OUTER JOIN network_map_elements ON ") | |
884 | _T(" network_map_links.map_id = network_map_elements.map_id AND ") | |
885 | _T(" network_map_links.element%d = network_map_elements.element_id ") | |
886 | _T("WHERE network_map_elements.element_id IS NULL"), pass); | |
887 | ||
888 | DB_RESULT hResult = SQLSelect(query); | |
889 | if (hResult != NULL) | |
890 | { | |
891 | int count = DBGetNumRows(hResult); | |
892 | for(int i = 0; i < count; i++) | |
893 | { | |
894 | m_iNumErrors++; | |
895 | DWORD mapId = DBGetFieldULong(hResult, i, 0); | |
896 | TCHAR name[MAX_OBJECT_NAME]; | |
897 | GetObjectName(mapId, name); | |
898 | if (GetYesNo(_T("\rInvalid link on network map %s [%d]. Delete?"), name, mapId)) | |
899 | { | |
900 | _sntprintf(query, 256, _T("DELETE FROM network_map_links WHERE map_id=%d AND element1=%d AND element2=%d"), | |
901 | mapId, DBGetFieldLong(hResult, i, 1), DBGetFieldLong(hResult, i, 2)); | |
902 | if (SQLQuery(query)) | |
903 | m_iNumFixes++; | |
904 | } | |
905 | } | |
906 | DBFreeResult(hResult); | |
907 | } | |
908 | } | |
909 | EndStage(); | |
910 | } | |
911 | ||
96e87c92 VK |
912 | /** |
913 | * Check database for errors | |
914 | */ | |
0d9b58ef | 915 | void CheckDatabase() |
5039dede AK |
916 | { |
917 | DB_RESULT hResult; | |
918 | LONG iVersion = 0; | |
919 | BOOL bCompleted = FALSE; | |
920 | ||
daf3c104 VK |
921 | if (g_checkDataTablesOnly) |
922 | _tprintf(_T("Checking database (data tables only):\n")); | |
923 | else | |
924 | _tprintf(_T("Checking database (%s collected data):\n"), g_checkData ? _T("including") : _T("excluding")); | |
5039dede AK |
925 | |
926 | // Get database format version | |
28f5b9a4 | 927 | iVersion = DBGetSchemaVersion(g_hCoreDB); |
daf3c104 | 928 | if ((iVersion < DB_FORMAT_VERSION) && !g_checkDataTablesOnly) |
5039dede AK |
929 | { |
930 | _tprintf(_T("Your database has format version %d, this tool is compiled for version %d.\nUse \"upgrade\" command to upgrade your database first.\n"), | |
931 | iVersion, DB_FORMAT_VERSION); | |
932 | } | |
933 | else if (iVersion > DB_FORMAT_VERSION) | |
934 | { | |
08b214c6 VK |
935 | _tprintf(_T("Your database has format version %d, this tool is compiled for version %d.\n") |
936 | _T("You need to upgrade your server before using this database.\n"), | |
5039dede AK |
937 | iVersion, DB_FORMAT_VERSION); |
938 | ||
939 | } | |
940 | else | |
941 | { | |
bf7f9d94 | 942 | TCHAR szLockStatus[MAX_DB_STRING], szLockInfo[MAX_DB_STRING]; |
0d6a7062 | 943 | BOOL bLocked = FALSE; |
5039dede AK |
944 | |
945 | // Check if database is locked | |
946 | hResult = DBSelect(g_hCoreDB, _T("SELECT var_value FROM config WHERE var_name='DBLockStatus'")); | |
947 | if (hResult != NULL) | |
948 | { | |
949 | if (DBGetNumRows(hResult) > 0) | |
950 | { | |
bf7f9d94 | 951 | DBGetField(hResult, 0, 0, szLockStatus, MAX_DB_STRING); |
5039dede AK |
952 | DecodeSQLString(szLockStatus); |
953 | bLocked = _tcscmp(szLockStatus, _T("UNLOCKED")); | |
954 | } | |
955 | DBFreeResult(hResult); | |
956 | ||
957 | if (bLocked) | |
958 | { | |
959 | hResult = DBSelect(g_hCoreDB, _T("SELECT var_value FROM config WHERE var_name='DBLockInfo'")); | |
960 | if (hResult != NULL) | |
961 | { | |
962 | if (DBGetNumRows(hResult) > 0) | |
963 | { | |
bf7f9d94 | 964 | DBGetField(hResult, 0, 0, szLockInfo, MAX_DB_STRING); |
5039dede AK |
965 | DecodeSQLString(szLockInfo); |
966 | } | |
967 | DBFreeResult(hResult); | |
968 | } | |
969 | } | |
5039dede | 970 | |
96e87c92 VK |
971 | if (bLocked) |
972 | { | |
973 | if (GetYesNo(_T("Database is locked by server %s [%s]\nDo you wish to force database unlock?"), szLockStatus, szLockInfo)) | |
974 | { | |
975 | if (SQLQuery(_T("UPDATE config SET var_value='UNLOCKED' where var_name='DBLockStatus'"))) | |
976 | { | |
977 | bLocked = FALSE; | |
978 | _tprintf(_T("Database lock removed\n")); | |
979 | } | |
980 | } | |
981 | } | |
5039dede | 982 | |
96e87c92 VK |
983 | if (!bLocked) |
984 | { | |
985 | DBBegin(g_hCoreDB); | |
986 | ||
daf3c104 VK |
987 | if (g_checkDataTablesOnly) |
988 | { | |
989 | CheckDataTables(); | |
990 | } | |
991 | else | |
992 | { | |
993 | CheckZones(); | |
994 | CheckNodes(); | |
995 | CheckComponents(_T("interface"), _T("interfaces")); | |
996 | CheckComponents(_T("network service"), _T("network_services")); | |
997 | CheckClusters(); | |
998 | CheckTemplateNodeMapping(); | |
999 | CheckObjectProperties(); | |
1000 | CheckEPP(); | |
1001 | CheckMapLinks(); | |
1002 | CheckDataTables(); | |
1003 | if (g_checkData) | |
1004 | CheckIData(); | |
1005 | } | |
96e87c92 VK |
1006 | |
1007 | if (m_iNumErrors == 0) | |
1008 | { | |
1009 | _tprintf(_T("Database doesn't contain any errors\n")); | |
1010 | DBCommit(g_hCoreDB); | |
1011 | } | |
1012 | else | |
1013 | { | |
1014 | _tprintf(_T("%d errors was found, %d errors was corrected\n"), m_iNumErrors, m_iNumFixes); | |
1015 | if (m_iNumFixes == m_iNumErrors) | |
1016 | _tprintf(_T("All errors in database was fixed\n")); | |
1017 | else | |
1018 | _tprintf(_T("Database still contain errors\n")); | |
1019 | if (m_iNumFixes > 0) | |
1020 | { | |
1021 | if (GetYesNo(_T("Commit changes?"))) | |
1022 | { | |
1023 | _tprintf(_T("Committing changes...\n")); | |
1024 | if (DBCommit(g_hCoreDB)) | |
1025 | _tprintf(_T("Changes was successfully committed to database\n")); | |
1026 | } | |
1027 | else | |
1028 | { | |
1029 | _tprintf(_T("Rolling back changes...\n")); | |
1030 | if (DBRollback(g_hCoreDB)) | |
1031 | _tprintf(_T("All changes made to database was cancelled\n")); | |
1032 | } | |
1033 | } | |
1034 | else | |
1035 | { | |
1036 | DBRollback(g_hCoreDB); | |
1037 | } | |
1038 | } | |
1039 | bCompleted = TRUE; | |
1040 | } | |
5039dede | 1041 | } |
96e87c92 VK |
1042 | else |
1043 | { | |
1044 | _tprintf(_T("Unable to get database lock status\n")); | |
1045 | } | |
5039dede AK |
1046 | } |
1047 | ||
1048 | _tprintf(_T("Database check %s\n"), bCompleted ? _T("completed") : _T("aborted")); | |
1049 | } |