Per stage confirmation in database manager during database check
[public/netxms.git] / src / server / tools / nxdbmgr / check.cpp
CommitLineData
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
30static int m_iNumErrors = 0;
31static int m_iNumFixes = 0;
32static int m_iStageErrors;
04ca2b83 33static int s_stageErrorsUpdate;
5039dede
AK
34static int m_iStageFixes;
35static TCHAR *m_pszStageMsg = NULL;
04ca2b83
VK
36static int s_stageWorkTotal = 0;
37static int s_stageWorkDone = 0;
5039dede 38
16a0cd88
VK
39/**
40 * Start stage
41 */
04ca2b83 42static void StartStage(const TCHAR *pszMsg, int workTotal = 1)
5039dede
AK
43{
44 if (pszMsg != NULL)
45 {
04ca2b83 46 free(m_pszStageMsg);
5039dede 47 m_pszStageMsg = _tcsdup(pszMsg);
04ca2b83
VK
48 m_iStageErrors = m_iNumErrors;
49 s_stageErrorsUpdate = m_iNumErrors;
50 m_iStageFixes = m_iNumFixes;
51 s_stageWorkTotal = workTotal;
52 s_stageWorkDone = 0;
ec46698b 53 ResetBulkYesNo();
5039dede 54 }
2dc48d7e 55 WriteToTerminalEx(_T("\x1b[1m*\x1b[0m %-67s \x1b[37;1m[\x1b[0m 0%% \x1b[37;1m]\x1b[0m\b\b\b"), m_pszStageMsg);
04ca2b83
VK
56#ifndef _WIN32
57 fflush(stdout);
58#endif
59 SetOperationInProgress(true);
60}
61
62/**
63 * Set total work for stage
64 */
65static void SetStageWorkTotal(int workTotal)
66{
67 s_stageWorkTotal = workTotal;
68 if (s_stageWorkDone > s_stageWorkTotal)
69 s_stageWorkDone = s_stageWorkTotal;
70}
71
72/**
73 * Update stage progress
74 */
75static void UpdateStageProgress(int installment)
76{
77 if (m_iNumErrors - s_stageErrorsUpdate > 0)
78 {
79 StartStage(NULL); // redisplay stage message
80 s_stageErrorsUpdate = m_iNumErrors;
81 }
82
83 s_stageWorkDone += installment;
84 if (s_stageWorkDone > s_stageWorkTotal)
85 s_stageWorkDone = s_stageWorkTotal;
86 WriteToTerminalEx(_T("\b\b\b%3d"), s_stageWorkDone * 100 / s_stageWorkTotal);
f669df41 87#ifndef _WIN32
5039dede
AK
88 fflush(stdout);
89#endif
5039dede
AK
90}
91
16a0cd88
VK
92/**
93 * End stage
94 */
f669df41 95static void EndStage()
5039dede
AK
96{
97 static const TCHAR *pszStatus[] = { _T("PASSED"), _T("FIXED "), _T("ERROR ") };
f669df41 98 static int nColor[] = { 32, 33, 31 };
5039dede
AK
99 int nCode, nErrors;
100
101 nErrors = m_iNumErrors - m_iStageErrors;
102 if (nErrors > 0)
103 {
104 nCode = (m_iNumFixes - m_iStageFixes == nErrors) ? 1 : 2;
04ca2b83
VK
105 if (m_iNumErrors - s_stageErrorsUpdate > 0)
106 StartStage(NULL); // redisplay stage message
5039dede
AK
107 }
108 else
109 {
110 nCode = 0;
111 }
04ca2b83
VK
112 WriteToTerminalEx(_T("\b\b\b\b\b\x1b[37;1m[\x1b[%d;1m%s\x1b[37;1m]\x1b[0m\n"), nColor[nCode], pszStatus[nCode]);
113 SetOperationInProgress(false);
ec46698b 114 ResetBulkYesNo();
5039dede
AK
115}
116
16a0cd88
VK
117/**
118 * Get object name from object_properties table
119 */
5039dede
AK
120static TCHAR *GetObjectName(DWORD dwId, TCHAR *pszBuffer)
121{
122 TCHAR szQuery[256];
123 DB_RESULT hResult;
124
08b214c6 125 _sntprintf(szQuery, 256, _T("SELECT name FROM object_properties WHERE object_id=%d"), dwId);
5039dede
AK
126 hResult = SQLSelect(szQuery);
127 if (hResult != NULL)
128 {
129 if (DBGetNumRows(hResult) > 0)
130 {
131 DBGetField(hResult, 0, 0, pszBuffer, MAX_OBJECT_NAME);
132 }
133 else
134 {
135 _tcscpy(pszBuffer, _T("<unknown>"));
136 }
137 }
138 else
139 {
140 _tcscpy(pszBuffer, _T("<unknown>"));
141 }
142 return pszBuffer;
143}
144
305c5d65
VK
145/**
146 * Check that given node is inside at least one container or cluster
147 */
a6c1f07f 148static bool NodeInContainer(DWORD id)
4262c0dc
VK
149{
150 TCHAR query[256];
151 DB_RESULT hResult;
a6c1f07f 152 bool result = false;
4262c0dc
VK
153
154 _sntprintf(query, 256, _T("SELECT container_id FROM container_members WHERE object_id=%d"), id);
155 hResult = SQLSelect(query);
156 if (hResult != NULL)
157 {
158 result = (DBGetNumRows(hResult) > 0);
159 DBFreeResult(hResult);
160 }
a6c1f07f
VK
161
162 if (!result)
163 {
164 _sntprintf(query, 256, _T("SELECT cluster_id FROM cluster_members WHERE node_id=%d"), id);
165 hResult = SQLSelect(query);
166 if (hResult != NULL)
167 {
168 result = (DBGetNumRows(hResult) > 0);
169 DBFreeResult(hResult);
170 }
171 }
172
4262c0dc
VK
173 return result;
174}
175
305c5d65
VK
176/**
177 * Find subnet for unlinked node
178 */
4262c0dc
VK
179static BOOL FindSubnetForNode(DWORD id, const TCHAR *name)
180{
181 DB_RESULT hResult, hResult2;
182 TCHAR query[256], buffer[32];
183 int i, count;
4262c0dc
VK
184 BOOL success = FALSE;
185
186 // Read list of interfaces of given node
c30c0c0f 187 _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
188 hResult = SQLSelect(query);
189 if (hResult != NULL)
190 {
191 count = DBGetNumRows(hResult);
192 for(i = 0; i < count; i++)
193 {
c30c0c0f
VK
194 InetAddress addr = DBGetFieldInetAddr(hResult, i, 0);
195 addr.setMaskBits(DBGetFieldLong(hResult, i, 1));
196 InetAddress subnet = addr.getSubnetAddress();
2589cc10 197
c30c0c0f 198 _sntprintf(query, 256, _T("SELECT id FROM subnets WHERE ip_addr='%s'"), subnet.toString(buffer));
4262c0dc
VK
199 hResult2 = SQLSelect(query);
200 if (hResult2 != NULL)
201 {
202 if (DBGetNumRows(hResult2) > 0)
203 {
c30c0c0f 204 UINT32 subnetId = DBGetFieldULong(hResult2, 0, 0);
4262c0dc 205 m_iNumErrors++;
ec46698b 206 if (GetYesNoEx(_T("Unlinked node object %d (\"%s\") can be linked to subnet %d (%s). Link?"), id, name, subnetId, buffer))
4262c0dc 207 {
c30c0c0f 208 _sntprintf(query, 256, _T("INSERT INTO nsmap (subnet_id,node_id) VALUES (%d,%d)"), subnetId, id);
4262c0dc
VK
209 if (SQLQuery(query))
210 {
211 success = TRUE;
212 m_iNumFixes++;
213 break;
214 }
215 else
216 {
217 // Node remains unlinked, so error count will be
218 // incremented again by node deletion code or next iteration
219 m_iNumErrors--;
220 }
221 }
222 else
223 {
224 // Node remains unlinked, so error count will be
225 // incremented again by node deletion code
226 m_iNumErrors--;
227 }
228 }
229 DBFreeResult(hResult2);
230 }
231 }
232 DBFreeResult(hResult);
233 }
234 return success;
235}
236
7777b139 237/**
ec46698b 238 * Check missing object properties
7777b139 239 */
ec46698b 240static void CheckMissingObjectProperties(const TCHAR *table, const TCHAR *className, UINT32 builtinObjectId)
0d9b58ef 241{
ec46698b
VK
242 TCHAR query[1024];
243 _sntprintf(query, 1024, _T("SELECT o.id FROM %s o LEFT OUTER JOIN object_properties p ON p.object_id = o.id WHERE p.name IS NULL"), table);
244 DB_RESULT hResult = SQLSelect(query);
245 if (hResult == NULL)
246 return;
0d9b58ef 247
ec46698b
VK
248 int count = DBGetNumRows(hResult);
249 for(int i = 0; i < count; i++)
0d9b58ef 250 {
ec46698b
VK
251 UINT32 id = DBGetFieldULong(hResult, i, 0);
252 if (id == builtinObjectId)
253 continue;
254 m_iNumErrors++;
255 if (GetYesNoEx(_T("Missing %s object %d properties. Create?"), className, id))
0d9b58ef 256 {
ec46698b
VK
257 uuid_t guid;
258 _uuid_generate(guid);
259
260 TCHAR guidText[128];
261 _sntprintf(query, 1024,
262 _T("INSERT INTO object_properties (object_id,guid,name,")
263 _T("status,is_deleted,is_system,inherit_access_rights,")
264 _T("last_modified,status_calc_alg,status_prop_alg,")
265 _T("status_fixed_val,status_shift,status_translation,")
266 _T("status_single_threshold,status_thresholds,location_type,")
267 _T("latitude,longitude,location_accuracy,location_timestamp,image,submap_id,maint_mode,maint_event_id) VALUES ")
268 _T("(%d,'%s','lost_%s_%d',5,0,0,1,") TIME_T_FMT _T(",0,0,0,0,0,0,'00000000',0,")
269 _T("'0.000000','0.000000',0,0,'00000000-0000-0000-0000-000000000000',0,'0',0)"),
270 (int)id, _uuid_to_string(guid, guidText), className, (int)id, TIME_T_FCAST(time(NULL)));
271 if (SQLQuery(query))
272 m_iNumFixes++;
0d9b58ef 273 }
0d9b58ef 274 }
ec46698b
VK
275 DBFreeResult(hResult);
276}
277
278/**
279 * Check zone objects
280 */
281static void CheckZones()
282{
283 StartStage(_T("Checking zone object properties"));
284 CheckMissingObjectProperties(_T("zones"), _T("zone"), 4);
0d9b58ef
VK
285 EndStage();
286}
287
305c5d65
VK
288/**
289 * Check node objects
290 */
035a4d73 291static void CheckNodes()
5039dede 292{
ec46698b
VK
293 StartStage(_T("Checking node object properties"));
294 CheckMissingObjectProperties(_T("nodes"), _T("node"), 0);
295 EndStage();
5039dede 296
ec46698b
VK
297 StartStage(_T("Checking node to subnet bindings"));
298 DB_RESULT hResult = SQLSelect(_T("SELECT n.id,p.name FROM nodes n INNER JOIN object_properties p ON p.object_id = n.id WHERE p.is_deleted=0"));
299 int count = DBGetNumRows(hResult);
300 SetStageWorkTotal(count);
301 for(int i = 0; i < count; i++)
5039dede 302 {
ec46698b 303 UINT32 nodeId = DBGetFieldULong(hResult, i, 0);
5039dede 304
ec46698b
VK
305 TCHAR query[1024];
306 _sntprintf(query, 1024, _T("SELECT subnet_id FROM nsmap WHERE node_id=%d"), nodeId);
307 DB_RESULT hResult2 = SQLSelect(query);
308 if (hResult2 != NULL)
309 {
310 if ((DBGetNumRows(hResult2) == 0) && (!NodeInContainer(nodeId)))
5039dede 311 {
ec46698b
VK
312 TCHAR nodeName[MAX_OBJECT_NAME];
313 DBGetField(hResult, i, 1, nodeName, MAX_OBJECT_NAME);
314 if ((DBGetFieldIPAddr(hResult, i, 1) == 0) || (!FindSubnetForNode(nodeId, nodeName)))
5039dede
AK
315 {
316 m_iNumErrors++;
ec46698b 317 if (GetYesNoEx(_T("Unlinked node object %d (\"%s\"). Delete it?"), nodeId, nodeName))
5039dede 318 {
ec46698b
VK
319 _sntprintf(query, 1024, _T("DELETE FROM nodes WHERE id=%d"), nodeId);
320 bool success = SQLQuery(query);
321 _sntprintf(query, 1024, _T("DELETE FROM acl WHERE object_id=%d"), nodeId);
322 success = success && SQLQuery(query);
323 _sntprintf(query, 1024, _T("DELETE FROM object_properties WHERE object_id=%d"), nodeId);
324 if (success && SQLQuery(query))
5039dede
AK
325 m_iNumFixes++;
326 }
327 }
5039dede 328 }
ec46698b 329 DBFreeResult(hResult2);
5039dede 330 }
ec46698b 331 UpdateStageProgress(1);
5039dede 332 }
ec46698b 333 DBFreeResult(hResult);
5039dede
AK
334 EndStage();
335}
336
305c5d65
VK
337/**
338 * Check node component objects
339 */
5039dede
AK
340static void CheckComponents(const TCHAR *pszDisplayName, const TCHAR *pszTable)
341{
ec46698b
VK
342 TCHAR stageName[256];
343 _sntprintf(stageName, 256, _T("Checking %s object properties"), pszDisplayName);
344 StartStage(stageName);
345 CheckMissingObjectProperties(pszTable, pszDisplayName, 0);
346 EndStage();
5039dede 347
ec46698b
VK
348 _sntprintf(stageName, 256, _T("Checking %s bindings"), pszDisplayName);
349 StartStage(stageName);
5039dede 350
ec46698b
VK
351 TCHAR query[256];
352 _sntprintf(query, 1024, _T("SELECT id,node_id FROM %s"), pszTable);
353 DB_RESULT hResult = SQLSelect(query);
5039dede
AK
354 if (hResult != NULL)
355 {
ec46698b
VK
356 int count = DBGetNumRows(hResult);
357 SetStageWorkTotal(count);
358 for(int i = 0; i < count; i++)
5039dede 359 {
ec46698b 360 UINT32 objectId = DBGetFieldULong(hResult, i, 0);
5039dede
AK
361
362 // Check if referred node exists
ec46698b 363 _sntprintf(query, 256, _T("SELECT name FROM object_properties WHERE object_id=%d AND is_deleted=0"),
5039dede 364 DBGetFieldULong(hResult, i, 1));
ec46698b 365 DB_RESULT hResult2 = SQLSelect(query);
5039dede
AK
366 if (hResult2 != NULL)
367 {
368 if (DBGetNumRows(hResult2) == 0)
369 {
370 m_iNumErrors++;
ec46698b
VK
371 TCHAR objectName[MAX_OBJECT_NAME];
372 if (GetYesNoEx(_T("Unlinked %s object %d (\"%s\"). Delete it?"), pszDisplayName, objectId, GetObjectName(objectId, objectName)))
5039dede 373 {
ec46698b
VK
374 _sntprintf(query, 256, _T("DELETE FROM %s WHERE id=%d"), pszTable, objectId);
375 if (SQLQuery(query))
5039dede 376 {
ec46698b
VK
377 _sntprintf(query, 256, _T("DELETE FROM object_properties WHERE object_id=%d"), objectId);
378 SQLQuery(query);
5039dede
AK
379 m_iNumFixes++;
380 }
381 }
382 }
383 DBFreeResult(hResult2);
384 }
385 }
386 DBFreeResult(hResult);
387 }
388 EndStage();
389}
390
305c5d65
VK
391/**
392 * Check common object properties
393 */
0d9b58ef 394static void CheckObjectProperties()
5039dede
AK
395{
396 DB_RESULT hResult;
397 TCHAR szQuery[1024];
398 DWORD i, dwNumRows, dwObjectId;
399
05e63846 400 StartStage(_T("Checking object properties"));
5039dede
AK
401 hResult = SQLSelect(_T("SELECT object_id,name,last_modified FROM object_properties"));
402 if (hResult != NULL)
403 {
404 dwNumRows = DBGetNumRows(hResult);
405 for(i = 0; i < dwNumRows; i++)
406 {
407 dwObjectId = DBGetFieldULong(hResult, i, 0);
408
409 // Check last change time
410 if (DBGetFieldULong(hResult, i, 2) == 0)
411 {
412 m_iNumErrors++;
ec46698b 413 if (GetYesNoEx(_T("Object %d [%s] has invalid timestamp. Fix it?"),
a4743a0f 414 dwObjectId, DBGetField(hResult, i, 1, szQuery, 1024)))
5039dede 415 {
0d9b58ef
VK
416 _sntprintf(szQuery, 1024, _T("UPDATE object_properties SET last_modified=") TIME_T_FMT _T(" WHERE object_id=%d"),
417 TIME_T_FCAST(time(NULL)), (int)dwObjectId);
5039dede
AK
418 if (SQLQuery(szQuery))
419 m_iNumFixes++;
420 }
421 }
422 }
423 DBFreeResult(hResult);
424 }
425 EndStage();
426}
427
ec46698b
VK
428/**
429 * Check container membership
430 */
3a9dfc75
EJ
431static void CheckContainerMembership()
432{
05e63846 433 StartStage(_T("Checking container membership"));
3a9dfc75
EJ
434 DB_RESULT containerList = SQLSelect(_T("SELECT object_id,container_id FROM container_members"));
435 DB_RESULT objectList = SQLSelect(_T("SELECT object_id FROM object_properties"));
436 if (containerList != NULL && objectList != NULL)
437 {
9f541446
VK
438 int numContainers = DBGetNumRows(containerList);
439 int numObjects = DBGetNumRows(objectList);
3a9dfc75
EJ
440 bool match = false;
441 TCHAR szQuery[1024];
442
7e39b214 443 SetStageWorkTotal(numContainers);
3a9dfc75
EJ
444 for(int i = 0; i < numContainers; i++)
445 {
446 for(int n = 0; n < numObjects; n++)
447 {
448 if (DBGetFieldULong(containerList, i, 0) == DBGetFieldULong(objectList, n, 0))
449 {
450 match = true;
451 break;
452 }
453 }
454 if (!match)
455 {
456 m_iNumErrors++;
ec46698b 457 if (GetYesNoEx(_T("Container %d contains non-existing child %d. Fix it?"),
3a9dfc75
EJ
458 DBGetFieldULong(containerList, i, 1), DBGetFieldULong(containerList, i, 0)))
459 {
460 _sntprintf(szQuery, 1024, _T("DELETE FROM container_members WHERE object_id=%d AND container_id=%d"),
461 DBGetFieldULong(containerList, i, 0), DBGetFieldULong(containerList, i, 1));
462 if (SQLQuery(szQuery))
463 m_iNumFixes++;
464 }
465 }
466 match = false;
7e39b214 467 UpdateStageProgress(1);
3a9dfc75
EJ
468 }
469 DBFreeResult(containerList);
470 DBFreeResult(objectList);
471 }
472 EndStage();
473}
474
305c5d65
VK
475/**
476 * Check cluster objects
477 */
0d9b58ef 478static void CheckClusters()
5039dede 479{
ec46698b
VK
480 StartStage(_T("Checking cluster object properties"));
481 CheckMissingObjectProperties(_T("clusters"), _T("cluster"), 0);
482 EndStage();
5039dede 483
ec46698b
VK
484 StartStage(_T("Checking cluster member nodes"));
485 DB_RESULT hResult = SQLSelect(_T("SELECT cluster_id,node_id FROM cluster_members"));
5039dede
AK
486 if (hResult != NULL)
487 {
ec46698b
VK
488 int count = DBGetNumRows(hResult);
489 SetStageWorkTotal(count);
490 for(int i = 0; i < count; i++)
5039dede 491 {
ec46698b
VK
492 UINT32 nodeId = DBGetFieldULong(hResult, i, 1);
493 if (!IsDatabaseRecordExist(_T("nodes"), _T("id"), nodeId))
5039dede
AK
494 {
495 m_iNumErrors++;
ec46698b
VK
496 UINT32 clusterId = DBGetFieldULong(hResult, i, 0);
497 TCHAR name[MAX_OBJECT_NAME];
498 if (GetYesNoEx(_T("Cluster object %s [%d] refers to non-existing node %d. Dereference?"),
499 GetObjectName(clusterId, name), clusterId, nodeId))
5039dede 500 {
ec46698b
VK
501 TCHAR query[256];
502 _sntprintf(query, 256, _T("DELETE FROM cluster_members WHERE cluster_id=%d AND node_id=%d"), clusterId, nodeId);
503 if (SQLQuery(query))
5039dede
AK
504 {
505 m_iNumFixes++;
506 }
507 }
508 }
ec46698b 509 UpdateStageProgress(1);
5039dede
AK
510 }
511 DBFreeResult(hResult);
512 }
513 EndStage();
514}
515
305c5d65
VK
516/**
517 * Returns TRUE if SELECT returns non-empty set
518 */
5039dede
AK
519static BOOL CheckResultSet(TCHAR *pszQuery)
520{
521 DB_RESULT hResult;
522 BOOL bResult = FALSE;
523
524 hResult = SQLSelect(pszQuery);
525 if (hResult != NULL)
526 {
527 bResult = (DBGetNumRows(hResult) > 0);
528 DBFreeResult(hResult);
529 }
530 return bResult;
531}
532
305c5d65
VK
533/**
534 * Check event processing policy
535 */
0d9b58ef 536static void CheckEPP()
5039dede
AK
537{
538 DB_RESULT hResult;
539 TCHAR szQuery[1024];
540 int i, iNumRows;
541 DWORD dwId;
542
05e63846 543 StartStage(_T("Checking event processing policy"));
2589cc10 544
5039dede
AK
545 // Check source object ID's
546 hResult = SQLSelect(_T("SELECT object_id FROM policy_source_list"));
547 if (hResult != NULL)
548 {
549 iNumRows = DBGetNumRows(hResult);
550 for(i = 0; i < iNumRows; i++)
551 {
552 dwId = DBGetFieldULong(hResult, i, 0);
08b214c6 553 _sntprintf(szQuery, 1024, _T("SELECT object_id FROM object_properties WHERE object_id=%d"), dwId);
5039dede
AK
554 if (!CheckResultSet(szQuery))
555 {
556 m_iNumErrors++;
ec46698b 557 if (GetYesNoEx(_T("Invalid object ID %d used in policy. Delete it from policy?"), dwId))
5039dede 558 {
08b214c6 559 _sntprintf(szQuery, 1024, _T("DELETE FROM policy_source_list WHERE object_id=%d"), dwId);
5039dede
AK
560 if (SQLQuery(szQuery))
561 m_iNumFixes++;
562 }
563 }
564 }
565 DBFreeResult(hResult);
566 }
567
568 // Check event ID's
ec46698b 569 ResetBulkYesNo();
5039dede
AK
570 hResult = SQLSelect(_T("SELECT event_code FROM policy_event_list"));
571 if (hResult != NULL)
572 {
573 iNumRows = DBGetNumRows(hResult);
574 for(i = 0; i < iNumRows; i++)
575 {
576 dwId = DBGetFieldULong(hResult, i, 0);
577 if (dwId & GROUP_FLAG)
08b214c6 578 _sntprintf(szQuery, 1024, _T("SELECT id FROM event_groups WHERE id=%d"), dwId);
5039dede 579 else
08b214c6 580 _sntprintf(szQuery, 1024, _T("SELECT event_code FROM event_cfg WHERE event_code=%d"), dwId);
5039dede
AK
581 if (!CheckResultSet(szQuery))
582 {
583 m_iNumErrors++;
ec46698b 584 if (GetYesNoEx(_T("Invalid event%s ID 0x%08X referenced in policy. Delete this reference?"), (dwId & GROUP_FLAG) ? _T(" group") : _T(""), dwId))
5039dede 585 {
08b214c6 586 _sntprintf(szQuery, 1024, _T("DELETE FROM policy_event_list WHERE event_code=%d"), dwId);
5039dede
AK
587 if (SQLQuery(szQuery))
588 m_iNumFixes++;
589 }
590 }
591 }
592 DBFreeResult(hResult);
593 }
594
595 // Check action ID's
ec46698b 596 ResetBulkYesNo();
5039dede
AK
597 hResult = SQLSelect(_T("SELECT action_id FROM policy_action_list"));
598 if (hResult != NULL)
599 {
600 iNumRows = DBGetNumRows(hResult);
601 for(i = 0; i < iNumRows; i++)
602 {
603 dwId = DBGetFieldULong(hResult, i, 0);
08b214c6 604 _sntprintf(szQuery, 1024, _T("SELECT action_id FROM actions WHERE action_id=%d"), dwId);
5039dede
AK
605 if (!CheckResultSet(szQuery))
606 {
607 m_iNumErrors++;
ec46698b 608 if (GetYesNoEx(_T("Invalid action ID %d referenced in policy. Delete this reference?"), dwId))
5039dede 609 {
08b214c6 610 _sntprintf(szQuery, 1024, _T("DELETE FROM policy_action_list WHERE action_id=%d"), dwId);
5039dede
AK
611 if (SQLQuery(szQuery))
612 m_iNumFixes++;
613 }
614 }
615 }
616 DBFreeResult(hResult);
617 }
618
619 EndStage();
620}
621
04ca2b83
VK
622/**
623 * Check data tables for given object class
624 */
625static void CollectObjectIdentifiers(const TCHAR *className, IntegerArray<UINT32> *list)
626{
627 TCHAR query[1024];
628 _sntprintf(query, 256, _T("SELECT id FROM %s"), className);
629 DB_RESULT hResult = SQLSelect(query);
630 if (hResult != NULL)
631 {
632 int count = DBGetNumRows(hResult);
633 for(int i = 0; i < count; i++)
634 {
635 list->add(DBGetFieldULong(hResult, i, 0));
636 }
637 DBFreeResult(hResult);
638 }
639}
640
641/**
642 * Get all data collection targets
643 */
e1d49d6e 644IntegerArray<UINT32> *GetDataCollectionTargets()
04ca2b83
VK
645{
646 IntegerArray<UINT32> *list = new IntegerArray<UINT32>(128, 128);
647 CollectObjectIdentifiers(_T("nodes"), list);
648 CollectObjectIdentifiers(_T("clusters"), list);
649 CollectObjectIdentifiers(_T("mobile_devices"), list);
650 CollectObjectIdentifiers(_T("access_points"), list);
651 CollectObjectIdentifiers(_T("chassis"), list);
652 CollectObjectIdentifiers(_T("sensors"), list);
653 return list;
654}
655
85ae39bc
VK
656/**
657 * Create idata_xx table
658 */
659BOOL CreateIDataTable(DWORD nodeId)
5039dede 660{
08b214c6 661 TCHAR szQuery[256], szQueryTemplate[256];
5039dede
AK
662 DWORD i;
663
85ae39bc 664 MetaDataReadStr(_T("IDataTableCreationCommand"), szQueryTemplate, 255, _T(""));
08b214c6 665 _sntprintf(szQuery, 256, szQueryTemplate, nodeId);
5039dede
AK
666 if (!SQLQuery(szQuery))
667 return FALSE;
668
669 for(i = 0; i < 10; i++)
670 {
08b214c6 671 _sntprintf(szQuery, 256, _T("IDataIndexCreationCommand_%d"), i);
85ae39bc 672 MetaDataReadStr(szQuery, szQueryTemplate, 255, _T(""));
5039dede
AK
673 if (szQueryTemplate[0] != 0)
674 {
08b214c6 675 _sntprintf(szQuery, 256, szQueryTemplate, nodeId, nodeId);
5039dede
AK
676 if (!SQLQuery(szQuery))
677 return FALSE;
678 }
679 }
680
681 return TRUE;
682}
683
85ae39bc 684/**
22aaa779 685 * Create tdata_xx table - pre V281 version
85ae39bc 686 */
22aaa779 687BOOL CreateTDataTable_preV281(DWORD nodeId)
85ae39bc
VK
688{
689 TCHAR szQuery[256], szQueryTemplate[256];
690 DWORD i;
5039dede 691
85ae39bc
VK
692 MetaDataReadStr(_T("TDataTableCreationCommand"), szQueryTemplate, 255, _T(""));
693 _sntprintf(szQuery, 256, szQueryTemplate, nodeId);
694 if (!SQLQuery(szQuery))
695 return FALSE;
5039dede 696
85ae39bc
VK
697 for(i = 0; i < 10; i++)
698 {
699 _sntprintf(szQuery, 256, _T("TDataIndexCreationCommand_%d"), i);
700 MetaDataReadStr(szQuery, szQueryTemplate, 255, _T(""));
701 if (szQueryTemplate[0] != 0)
702 {
703 _sntprintf(szQuery, 256, szQueryTemplate, nodeId, nodeId);
704 if (!SQLQuery(szQuery))
705 return FALSE;
706 }
707 }
708
709 return TRUE;
710}
711
22aaa779 712/**
63604cda 713 * Create tdata_xx table
22aaa779 714 */
63604cda 715BOOL CreateTDataTable(DWORD nodeId)
22aaa779
VK
716{
717 TCHAR szQuery[256], szQueryTemplate[256];
718 DWORD i;
719
720 for(i = 0; i < 10; i++)
721 {
722 _sntprintf(szQuery, 256, _T("TDataTableCreationCommand_%d"), i);
723 MetaDataReadStr(szQuery, szQueryTemplate, 255, _T(""));
724 if (szQueryTemplate[0] != 0)
725 {
1d4f7890 726 _sntprintf(szQuery, 256, szQueryTemplate, nodeId, nodeId);
22aaa779
VK
727 if (!SQLQuery(szQuery))
728 return FALSE;
729 }
730 }
731
732 for(i = 0; i < 10; i++)
733 {
734 _sntprintf(szQuery, 256, _T("TDataIndexCreationCommand_%d"), i);
735 MetaDataReadStr(szQuery, szQueryTemplate, 255, _T(""));
736 if (szQueryTemplate[0] != 0)
737 {
738 _sntprintf(szQuery, 256, szQueryTemplate, nodeId, nodeId);
739 if (!SQLQuery(szQuery))
740 return FALSE;
741 }
742 }
743
744 return TRUE;
745}
746
85ae39bc 747/**
04ca2b83 748 * Check if DCI exists
85ae39bc 749 */
04ca2b83 750static bool IsDciExists(UINT32 dciId, UINT32 nodeId, bool isTable)
5039dede 751{
04ca2b83
VK
752 TCHAR query[256];
753 if (nodeId != 0)
754 _sntprintf(query, 256, _T("SELECT count(*) FROM %s WHERE item_id=%d AND node_id=%d"), isTable ? _T("dc_tables") : _T("items"), dciId, nodeId);
755 else
756 _sntprintf(query, 256, _T("SELECT count(*) FROM %s WHERE item_id=%d"), isTable ? _T("dc_tables") : _T("items"), dciId);
757 DB_RESULT hResult = SQLSelect(query);
758 if (hResult == NULL)
759 return false;
5039dede 760
04ca2b83
VK
761 int count = DBGetFieldLong(hResult, 0, 0);
762 DBFreeResult(hResult);
9c56e492 763 return count != 0;
04ca2b83
VK
764}
765
766/**
767 * Check collected data
768 */
769static void CheckCollectedData(bool isTable)
770{
05e63846 771 StartStage(isTable ? _T("Checking table DCI history records") : _T("Checking DCI history records"));
2589cc10 772
04ca2b83
VK
773 time_t now = time(NULL);
774 IntegerArray<UINT32> *targets = GetDataCollectionTargets();
775 SetStageWorkTotal(targets->size());
776 for(int i = 0; i < targets->size(); i++)
5039dede 777 {
04ca2b83
VK
778 UINT32 objectId = targets->get(i);
779 TCHAR query[1024];
780 _sntprintf(query, 1024, _T("SELECT count(*) FROM %s_%d WHERE %s_timestamp>") TIME_T_FMT,
781 isTable ? _T("tdata") : _T("idata"), objectId, isTable ? _T("tdata") : _T("idata"), TIME_T_FCAST(now));
782 DB_RESULT hResult = SQLSelect(query);
783 if (hResult != NULL)
784 {
785 if (DBGetFieldLong(hResult, 0, 0) > 0)
786 {
787 m_iNumErrors++;
ec46698b 788 if (GetYesNoEx(_T("Found collected data for node [%d] with timestamp in the future. Delete invalid records?"), objectId))
04ca2b83
VK
789 {
790 _sntprintf(query, 1024, _T("DELETE FROM %s_%d WHERE %s_timestamp>") TIME_T_FMT,
791 isTable ? _T("tdata") : _T("idata"), objectId, isTable ? _T("tdata") : _T("idata"), TIME_T_FCAST(now));
792 if (SQLQuery(query))
793 m_iNumFixes++;
794 }
795 }
796 DBFreeResult(hResult);
797 }
ec46698b
VK
798 }
799
800 ResetBulkYesNo();
5039dede 801
ec46698b
VK
802 for(int i = 0; i < targets->size(); i++)
803 {
804 UINT32 objectId = targets->get(i);
805 TCHAR query[1024];
04ca2b83 806 _sntprintf(query, 1024, _T("SELECT distinct(item_id) FROM %s_%d"), isTable ? _T("tdata") : _T("idata"), objectId);
ec46698b 807 DB_RESULT hResult = SQLSelect(query);
04ca2b83
VK
808 if (hResult != NULL)
809 {
810 int count = DBGetNumRows(hResult);
811 for(int i = 0; i < count; i++)
812 {
813 UINT32 id = DBGetFieldLong(hResult, i, 0);
814 if (!IsDciExists(id, objectId, isTable))
815 {
816 m_iNumErrors++;
ec46698b 817 if (GetYesNoEx(_T("Found collected data for non-existing DCI [%d] on node [%d]. Delete invalid records?"), id, objectId))
04ca2b83
VK
818 {
819 _sntprintf(query, 1024, _T("DELETE FROM %s_%d WHERE item_id=%d"), isTable ? _T("tdata") : _T("idata"), objectId, id);
820 if (SQLQuery(query))
821 m_iNumFixes++;
822 }
823 }
824 }
825 DBFreeResult(hResult);
826 }
827
828 UpdateStageProgress(1);
829 }
830 delete targets;
5039dede
AK
831
832 EndStage();
833}
834
04ca2b83
VK
835/**
836 * Check raw DCI values
837 */
838static void CheckRawDciValues()
839{
05e63846 840 StartStage(_T("Checking raw DCI values table"));
04ca2b83
VK
841
842 time_t now = time(NULL);
843
844 DB_RESULT hResult = SQLSelect(_T("SELECT item_id FROM raw_dci_values"));
845 if (hResult != NULL)
846 {
847 int count = DBGetNumRows(hResult);
848 SetStageWorkTotal(count + 1);
849 for(int i = 0; i < count; i++)
850 {
851 UINT32 id = DBGetFieldLong(hResult, i, 0);
852 if (!IsDciExists(id, 0, false))
853 {
854 m_iNumErrors++;
ec46698b 855 if (GetYesNoEx(_T("Found raw value record for non-existing DCI [%d]. Delete it?"), id))
04ca2b83
VK
856 {
857 TCHAR query[256];
858 _sntprintf(query, 256, _T("DELETE FROM raw_dci_values WHERE item_id=%d"), id);
859 if (SQLQuery(query))
860 m_iNumFixes++;
861 }
862 }
863 UpdateStageProgress(1);
864 }
865 DBFreeResult(hResult);
866 }
867
ec46698b 868 ResetBulkYesNo();
04ca2b83
VK
869 TCHAR query[1024];
870 _sntprintf(query, 1024, _T("SELECT count(*) FROM raw_dci_values WHERE last_poll_time>") TIME_T_FMT, TIME_T_FCAST(now));
871 hResult = SQLSelect(query);
872 if (hResult != NULL)
873 {
874 if (DBGetFieldLong(hResult, 0, 0) > 0)
875 {
876 m_iNumErrors++;
ec46698b 877 if (GetYesNoEx(_T("Found DCIs with last poll timestamp in the future. Fix it?")))
04ca2b83
VK
878 {
879 _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));
880 if (SQLQuery(query))
881 m_iNumFixes++;
882 }
883 }
884 DBFreeResult(hResult);
885 }
886 UpdateStageProgress(1);
887
888 EndStage();
889}
890
05e63846
VK
891/**
892 * Check thresholds
893 */
894static void CheckThresholds()
895{
896 StartStage(_T("Checking DCI thresholds"));
897
898 DB_RESULT hResult = SQLSelect(_T("SELECT threshold_id,item_id FROM thresholds"));
899 if (hResult != NULL)
900 {
901 int count = DBGetNumRows(hResult);
902 SetStageWorkTotal(count);
903 for(int i = 0; i < count; i++)
904 {
905 UINT32 dciId = DBGetFieldULong(hResult, i, 1);
906 if (!IsDciExists(dciId, 0, false))
907 {
908 m_iNumErrors++;
ec46698b 909 if (GetYesNoEx(_T("Found threshold configuration for non-existing DCI [%d]. Delete?"), dciId))
05e63846
VK
910 {
911 TCHAR query[256];
912 _sntprintf(query, 256, _T("DELETE FROM thresholds WHERE threshold_id=%d AND item_id=%d"), DBGetFieldLong(hResult, i, 0), dciId);
913 if (SQLQuery(query))
914 m_iNumFixes++;
915 }
916 }
917 UpdateStageProgress(1);
918 }
919 DBFreeResult(hResult);
920 }
921
922 EndStage();
923}
924
925/**
926 * Check thresholds
927 */
928static void CheckTableThresholds()
929{
930 StartStage(_T("Checking table DCI thresholds"));
931
932 DB_RESULT hResult = SQLSelect(_T("SELECT id,table_id FROM dct_thresholds"));
933 if (hResult != NULL)
934 {
935 int count = DBGetNumRows(hResult);
936 SetStageWorkTotal(count);
937 for(int i = 0; i < count; i++)
938 {
939 UINT32 dciId = DBGetFieldULong(hResult, i, 1);
940 if (!IsDciExists(dciId, 0, true))
941 {
942 m_iNumErrors++;
ec46698b 943 if (GetYesNoEx(_T("Found threshold configuration for non-existing table DCI [%d]. Delete?"), dciId))
05e63846
VK
944 {
945 UINT32 id = DBGetFieldLong(hResult, i, 0);
946
947 TCHAR query[256];
948 _sntprintf(query, 256, _T("DELETE FROM dct_threshold_instances WHERE threshold_id=%d"), id);
949 if (SQLQuery(query))
950 {
951 _sntprintf(query, 256, _T("DELETE FROM dct_threshold_conditions WHERE threshold_id=%d"), id);
952 if (SQLQuery(query))
953 {
954 _sntprintf(query, 256, _T("DELETE FROM dct_thresholds WHERE id=%d"), id);
955 if (SQLQuery(query))
956 m_iNumFixes++;
957 }
958 }
959 }
960 }
961 UpdateStageProgress(1);
962 }
963 DBFreeResult(hResult);
964 }
965
966 EndStage();
967}
968
daf3c104
VK
969/**
970 * Check if given data table exist
971 */
b29e5407 972bool IsDataTableExist(const TCHAR *format, UINT32 id)
daf3c104
VK
973{
974 TCHAR table[256];
975 _sntprintf(table, 256, format, id);
fdf1ed50
VK
976 int rc = DBIsTableExist(g_hCoreDB, table);
977 if (rc == DBIsTableExist_Failure)
978 {
979 _tprintf(_T("WARNING: call to DBIsTableExist(\"%s\") failed\n"), table);
980 }
981 return rc != DBIsTableExist_NotFound;
daf3c104
VK
982}
983
984/**
7e39b214 985 * Check data tables
daf3c104 986 */
7e39b214 987static void CheckDataTables()
daf3c104 988{
7e39b214
VK
989 StartStage(_T("Checking data tables"));
990
991 IntegerArray<UINT32> *targets = GetDataCollectionTargets();
992 SetStageWorkTotal(targets->size());
993 for(int i = 0; i < targets->size(); i++)
daf3c104 994 {
7e39b214 995 UINT32 objectId = targets->get(i);
daf3c104 996
7e39b214
VK
997 // IDATA
998 if (!IsDataTableExist(_T("idata_%d"), objectId))
999 {
1000 m_iNumErrors++;
daf3c104 1001
7e39b214
VK
1002 TCHAR objectName[MAX_OBJECT_NAME];
1003 GetObjectName(objectId, objectName);
ec46698b 1004 if (GetYesNoEx(_T("Data collection table (IDATA) for object %s [%d] not found. Create? (Y/N) "), objectName, objectId))
7e39b214
VK
1005 {
1006 if (CreateIDataTable(objectId))
1007 m_iNumFixes++;
1008 }
daf3c104 1009 }
daf3c104 1010
7e39b214
VK
1011 // TDATA
1012 if (!IsDataTableExist(_T("tdata_%d"), objectId))
1013 {
1014 m_iNumErrors++;
daf3c104 1015
7e39b214
VK
1016 TCHAR objectName[MAX_OBJECT_NAME];
1017 GetObjectName(objectId, objectName);
ec46698b 1018 if (GetYesNoEx(_T("Data collection table (TDATA) for %s [%d] not found. Create? (Y/N) "), objectName, objectId))
7e39b214
VK
1019 {
1020 if (CreateTDataTable(objectId))
1021 m_iNumFixes++;
1022 }
1023 }
1024
1025 UpdateStageProgress(1);
1026 }
daf3c104 1027
7e39b214 1028 delete targets;
daf3c104
VK
1029 EndStage();
1030}
1031
85ae39bc
VK
1032/**
1033 * Check template to node mapping
1034 */
0d9b58ef 1035static void CheckTemplateNodeMapping()
5039dede
AK
1036{
1037 DB_RESULT hResult;
1038 TCHAR name[256], query[256];
1039 DWORD i, dwNumRows, dwTemplateId, dwNodeId;
1040
05e63846 1041 StartStage(_T("Checking template to node mapping"));
5039dede
AK
1042 hResult = SQLSelect(_T("SELECT template_id,node_id FROM dct_node_map ORDER BY template_id"));
1043 if (hResult != NULL)
1044 {
1045 dwNumRows = DBGetNumRows(hResult);
04ca2b83 1046 SetStageWorkTotal(dwNumRows);
5039dede
AK
1047 for(i = 0; i < dwNumRows; i++)
1048 {
1049 dwTemplateId = DBGetFieldULong(hResult, i, 0);
1050 dwNodeId = DBGetFieldULong(hResult, i, 1);
1051
1052 // Check node existence
06b83321
VK
1053 if (!IsDatabaseRecordExist(_T("nodes"), _T("id"), dwNodeId) &&
1054 !IsDatabaseRecordExist(_T("clusters"), _T("id"), dwNodeId) &&
1055 !IsDatabaseRecordExist(_T("mobile_devices"), _T("id"), dwNodeId))
5039dede
AK
1056 {
1057 m_iNumErrors++;
1058 GetObjectName(dwTemplateId, name);
ec46698b 1059 if (GetYesNoEx(_T("Template %d [%s] mapped to non-existent node %d. Delete this mapping?"), dwTemplateId, name, dwNodeId))
5039dede
AK
1060 {
1061 _sntprintf(query, 256, _T("DELETE FROM dct_node_map WHERE template_id=%d AND node_id=%d"),
1062 dwTemplateId, dwNodeId);
1063 if (SQLQuery(query))
1064 m_iNumFixes++;
1065 }
1066 }
04ca2b83 1067 UpdateStageProgress(1);
5039dede
AK
1068 }
1069 DBFreeResult(hResult);
1070 }
1071 EndStage();
1072}
1073
16a0cd88
VK
1074/**
1075 * Check network map links
1076 */
1077static void CheckMapLinks()
1078{
05e63846 1079 StartStage(_T("Checking network map links"));
16a0cd88
VK
1080
1081 for(int pass = 1; pass <= 2; pass++)
1082 {
1083 TCHAR query[1024];
1084 _sntprintf(query, 1024,
1085 _T("SELECT network_map_links.map_id,network_map_links.element1,network_map_links.element2 ")
1086 _T("FROM network_map_links ")
1087 _T("LEFT OUTER JOIN network_map_elements ON ")
1088 _T(" network_map_links.map_id = network_map_elements.map_id AND ")
1089 _T(" network_map_links.element%d = network_map_elements.element_id ")
1090 _T("WHERE network_map_elements.element_id IS NULL"), pass);
1091
1092 DB_RESULT hResult = SQLSelect(query);
1093 if (hResult != NULL)
1094 {
1095 int count = DBGetNumRows(hResult);
1096 for(int i = 0; i < count; i++)
1097 {
1098 m_iNumErrors++;
1099 DWORD mapId = DBGetFieldULong(hResult, i, 0);
1100 TCHAR name[MAX_OBJECT_NAME];
1101 GetObjectName(mapId, name);
ec46698b 1102 if (GetYesNoEx(_T("Invalid link on network map %s [%d]. Delete?"), name, mapId))
16a0cd88
VK
1103 {
1104 _sntprintf(query, 256, _T("DELETE FROM network_map_links WHERE map_id=%d AND element1=%d AND element2=%d"),
1105 mapId, DBGetFieldLong(hResult, i, 1), DBGetFieldLong(hResult, i, 2));
1106 if (SQLQuery(query))
1107 m_iNumFixes++;
1108 }
1109 }
1110 DBFreeResult(hResult);
1111 }
1112 }
1113 EndStage();
1114}
1115
96e87c92
VK
1116/**
1117 * Check database for errors
1118 */
0d9b58ef 1119void CheckDatabase()
5039dede 1120{
daf3c104
VK
1121 if (g_checkDataTablesOnly)
1122 _tprintf(_T("Checking database (data tables only):\n"));
1123 else
1124 _tprintf(_T("Checking database (%s collected data):\n"), g_checkData ? _T("including") : _T("excluding"));
5039dede
AK
1125
1126 // Get database format version
da4b354a
VK
1127 INT32 major, minor;
1128 if (!DBGetSchemaVersion(g_hCoreDB, &major, &minor))
5039dede 1129 {
da4b354a
VK
1130 _tprintf(_T("Unable to determine database schema version\n"));
1131 _tprintf(_T("Database check aborted\n"));
1132 return;
5039dede 1133 }
da4b354a 1134 if ((major > DB_SCHEMA_VERSION_MAJOR) || ((major == DB_SCHEMA_VERSION_MAJOR) && (minor > DB_SCHEMA_VERSION_MINOR)))
5039dede 1135 {
da4b354a
VK
1136 _tprintf(_T("Your database has format version %d.%d, this tool is compiled for version %d.%d.\n")
1137 _T("You need to upgrade your server before using this database.\n"),
1138 major, minor, DB_SCHEMA_VERSION_MAJOR, DB_SCHEMA_VERSION_MINOR);
1139 _tprintf(_T("Database check aborted\n"));
1140 return;
5039dede 1141 }
da4b354a 1142 if ((major < DB_SCHEMA_VERSION_MAJOR) || ((major == DB_SCHEMA_VERSION_MAJOR) && (minor < DB_SCHEMA_VERSION_MINOR)))
5039dede 1143 {
da4b354a
VK
1144 _tprintf(_T("Your database has format version %d.%d, this tool is compiled for version %d.%d.\nUse \"upgrade\" command to upgrade your database first.\n"),
1145 major, minor, DB_SCHEMA_VERSION_MAJOR, DB_SCHEMA_VERSION_MINOR);
1146 _tprintf(_T("Database check aborted\n"));
1147 return;
1148 }
5039dede 1149
da4b354a
VK
1150 TCHAR szLockStatus[MAX_DB_STRING], szLockInfo[MAX_DB_STRING];
1151 BOOL bLocked = FALSE;
1152 BOOL bCompleted = FALSE;
1153
1154 // Check if database is locked
1155 DB_RESULT hResult = DBSelect(g_hCoreDB, _T("SELECT var_value FROM config WHERE var_name='DBLockStatus'"));
1156 if (hResult != NULL)
1157 {
1158 if (DBGetNumRows(hResult) > 0)
5039dede 1159 {
da4b354a
VK
1160 DBGetField(hResult, 0, 0, szLockStatus, MAX_DB_STRING);
1161 DecodeSQLString(szLockStatus);
1162 bLocked = _tcscmp(szLockStatus, _T("UNLOCKED"));
1163 }
1164 DBFreeResult(hResult);
1165
1166 if (bLocked)
1167 {
1168 hResult = DBSelect(g_hCoreDB, _T("SELECT var_value FROM config WHERE var_name='DBLockInfo'"));
1169 if (hResult != NULL)
5039dede 1170 {
da4b354a
VK
1171 if (DBGetNumRows(hResult) > 0)
1172 {
1173 DBGetField(hResult, 0, 0, szLockInfo, MAX_DB_STRING);
1174 DecodeSQLString(szLockInfo);
1175 }
1176 DBFreeResult(hResult);
5039dede 1177 }
da4b354a 1178 }
5039dede 1179
da4b354a
VK
1180 if (bLocked)
1181 {
1182 if (GetYesNo(_T("Database is locked by server %s [%s]\nDo you wish to force database unlock?"), szLockStatus, szLockInfo))
5039dede 1183 {
da4b354a 1184 if (SQLQuery(_T("UPDATE config SET var_value='UNLOCKED' where var_name='DBLockStatus'")))
5039dede 1185 {
da4b354a
VK
1186 bLocked = FALSE;
1187 _tprintf(_T("Database lock removed\n"));
5039dede
AK
1188 }
1189 }
da4b354a 1190 }
5039dede 1191
da4b354a
VK
1192 if (!bLocked)
1193 {
1194 DBBegin(g_hCoreDB);
5039dede 1195
da4b354a
VK
1196 if (g_checkDataTablesOnly)
1197 {
1198 CheckDataTables();
1199 }
1200 else
1201 {
1202 CheckZones();
1203 CheckNodes();
1204 CheckComponents(_T("interface"), _T("interfaces"));
1205 CheckComponents(_T("network service"), _T("network_services"));
1206 CheckClusters();
1207 CheckTemplateNodeMapping();
1208 CheckObjectProperties();
1209 CheckContainerMembership();
1210 CheckEPP();
1211 CheckMapLinks();
1212 CheckDataTables();
1213 CheckRawDciValues();
1214 CheckThresholds();
1215 CheckTableThresholds();
1216 if (g_checkData)
1217 {
1218 CheckCollectedData(false);
1219 CheckCollectedData(true);
1220 }
1221 }
96e87c92 1222
da4b354a
VK
1223 if (m_iNumErrors == 0)
1224 {
1225 _tprintf(_T("Database doesn't contain any errors\n"));
1226 DBCommit(g_hCoreDB);
1227 }
1228 else
1229 {
1230 _tprintf(_T("%d errors was found, %d errors was corrected\n"), m_iNumErrors, m_iNumFixes);
1231 if (m_iNumFixes == m_iNumErrors)
1232 _tprintf(_T("All errors in database was fixed\n"));
1233 else
1234 _tprintf(_T("Database still contain errors\n"));
1235 if (m_iNumFixes > 0)
daf3c104 1236 {
da4b354a
VK
1237 if (GetYesNo(_T("Commit changes?")))
1238 {
1239 _tprintf(_T("Committing changes...\n"));
1240 if (DBCommit(g_hCoreDB))
1241 _tprintf(_T("Changes was successfully committed to database\n"));
1242 }
1243 else
1244 {
1245 _tprintf(_T("Rolling back changes...\n"));
1246 if (DBRollback(g_hCoreDB))
1247 _tprintf(_T("All changes made to database was cancelled\n"));
1248 }
daf3c104
VK
1249 }
1250 else
1251 {
da4b354a 1252 DBRollback(g_hCoreDB);
daf3c104 1253 }
da4b354a
VK
1254 }
1255 bCompleted = TRUE;
5039dede 1256 }
da4b354a
VK
1257 }
1258 else
1259 {
1260 _tprintf(_T("Unable to get database lock status\n"));
5039dede
AK
1261 }
1262
1263 _tprintf(_T("Database check %s\n"), bCompleted ? _T("completed") : _T("aborted"));
1264}