schema-related information (like schema version, DB syntax, etc.) moved from "config...
[public/netxms.git] / src / server / tools / nxdbmgr / check.cpp
CommitLineData
5039dede
AK
1/*
2** nxdbmgr - NetXMS database manager
3** Copyright (C) 2004, 2005, 2006, 2007, 2008 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: 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;
33static int m_iStageFixes;
34static TCHAR *m_pszStageMsg = NULL;
35
36
37//
38// Start stage
39//
40
41static void StartStage(const TCHAR *pszMsg)
42{
43 if (pszMsg != NULL)
44 {
45 safe_free(m_pszStageMsg);
46 m_pszStageMsg = _tcsdup(pszMsg);
47 }
48#ifdef _WIN32
49 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0F);
50 _puttc(_T('*'), stdout);
51 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x07);
52 _tprintf(_T(" %-68s"), m_pszStageMsg, stdout);
53#else
54 _tprintf(_T("* %-68s"), m_pszStageMsg, stdout);
55 fflush(stdout);
56#endif
57 m_iStageErrors = m_iNumErrors;
58 m_iStageFixes = m_iNumFixes;
59}
60
61
62//
63// End stage
64//
65
66static void EndStage(void)
67{
68 static const TCHAR *pszStatus[] = { _T("PASSED"), _T("FIXED "), _T("ERROR ") };
69 static int nColor[] = { 0x0A, 0x0E, 0x0C };
70 int nCode, nErrors;
71
72 nErrors = m_iNumErrors - m_iStageErrors;
73 if (nErrors > 0)
74 {
75 nCode = (m_iNumFixes - m_iStageFixes == nErrors) ? 1 : 2;
76 StartStage(NULL); // redisplay stage message
77 }
78 else
79 {
80 nCode = 0;
81 }
82#ifdef _WIN32
83 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0F);
84 _puttc(_T('['), stdout);
85 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), nColor[nCode]);
86 _tprintf(_T("%s"), pszStatus[nCode]);
87 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0F);
88 _puttc(_T(']'), stdout);
89 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x07);
90 _tprintf("\n");
91#else
92 _tprintf(_T(" [%s]\n"), pszStatus[nCode]);
93#endif
94}
95
96
97//
98// Get object name from object_properties table
99//
100
101static TCHAR *GetObjectName(DWORD dwId, TCHAR *pszBuffer)
102{
103 TCHAR szQuery[256];
104 DB_RESULT hResult;
105
106 _stprintf(szQuery, _T("SELECT name FROM object_properties WHERE object_id=%d"), dwId);
107 hResult = SQLSelect(szQuery);
108 if (hResult != NULL)
109 {
110 if (DBGetNumRows(hResult) > 0)
111 {
112 DBGetField(hResult, 0, 0, pszBuffer, MAX_OBJECT_NAME);
113 }
114 else
115 {
116 _tcscpy(pszBuffer, _T("<unknown>"));
117 }
118 }
119 else
120 {
121 _tcscpy(pszBuffer, _T("<unknown>"));
122 }
123 return pszBuffer;
124}
125
126
127//
128// Check node objects
129//
130
131static void CheckNodes(void)
132{
133 DB_RESULT hResult, hResult2;
134 DWORD i, dwNumObjects, dwId;
135 TCHAR szQuery[1024], szName[MAX_OBJECT_NAME];
136 BOOL bResult, bIsDeleted;
137
138 StartStage(_T("Checking node objects..."));
139 hResult = SQLSelect(_T("SELECT id,primary_ip FROM nodes"));
140 if (hResult != NULL)
141 {
142 dwNumObjects = DBGetNumRows(hResult);
143 for(i = 0; i < dwNumObjects; i++)
144 {
145 dwId = DBGetFieldULong(hResult, i, 0);
146
147 // Check appropriate record in object_properties table
148 _sntprintf(szQuery, 256, _T("SELECT name,is_deleted FROM object_properties WHERE object_id=%d"), dwId);
149 hResult2 = SQLSelect(szQuery);
150 if (hResult2 != NULL)
151 {
152 if (DBGetNumRows(hResult2) == 0)
153 {
154 m_iNumErrors++;
155 _tprintf(_T("\rMissing node object %d properties. Create? (Y/N) "), dwId);
156 if (GetYesNo())
157 {
158 _sntprintf(szQuery, 1024,
159 _T("INSERT INTO object_properties (object_id,name,"
160 "status,is_deleted,image_id,inherit_access_rights,"
161 "last_modified,status_calc_alg,status_prop_alg,"
162 "status_fixed_val,status_shift,status_translation,"
163 "status_single_threshold,status_thresholds) VALUES "
164 "(%d,'lost_node_%d',5,0,0,1,0,0,0,0,0,0,0,'00000000')"),
165 dwId, dwId);
166 if (SQLQuery(szQuery))
167 m_iNumFixes++;
168 }
169 }
170 else
171 {
172 DBGetField(hResult2, 0, 0, szName, MAX_OBJECT_NAME);
173 bIsDeleted = DBGetFieldLong(hResult2, 0, 1) ? TRUE : FALSE;
174 }
175 DBFreeResult(hResult2);
176 }
177
178 if (!bIsDeleted)
179 {
180 _sntprintf(szQuery, 1024, _T("SELECT subnet_id FROM nsmap WHERE node_id=%d"), dwId);
181 hResult2 = SQLSelect(szQuery);
182 if (hResult2 != NULL)
183 {
184 if ((DBGetNumRows(hResult2) == 0) && (DBGetFieldIPAddr(hResult, i, 1) != 0))
185 {
186 m_iNumErrors++;
187 _tprintf(_T("\rUnlinked node object %d (\"%s\"). Delete? (Y/N) "),
188 dwId, szName);
189 if (GetYesNo())
190 {
191 _sntprintf(szQuery, 1024, _T("DELETE FROM nodes WHERE id=%d"), dwId);
192 bResult = SQLQuery(szQuery);
193 _sntprintf(szQuery, 1024, _T("DELETE FROM acl WHERE object_id=%d"), dwId);
194 bResult = bResult && SQLQuery(szQuery);
195 _sntprintf(szQuery, 1024, _T("DELETE FROM object_properties WHERE object_id=%d"), dwId);
196 if (SQLQuery(szQuery) && bResult)
197 m_iNumFixes++;
198 }
199 }
200 DBFreeResult(hResult2);
201 }
202 }
203 }
204 DBFreeResult(hResult);
205 }
206 EndStage();
207}
208
209
210//
211// Check if node exists
212//
213
214static BOOL IsNodeExist(DWORD dwId)
215{
216 TCHAR szQuery[256];
217 DB_RESULT hResult;
218 BOOL bRet = FALSE;
219
220 _sntprintf(szQuery, 256, _T("SELECT id FROM nodes WHERE id=%d"), dwId);
221 hResult = SQLSelect(szQuery);
222 if (hResult != NULL)
223 {
224 bRet = (DBGetNumRows(hResult) > 0);
225 DBFreeResult(hResult);
226 }
227 return bRet;
228}
229
230
231//
232// Check node component objects
233//
234
235static void CheckComponents(const TCHAR *pszDisplayName, const TCHAR *pszTable)
236{
237 DB_RESULT hResult, hResult2;
238 DWORD i, dwNumObjects, dwId;
239 TCHAR szQuery[1024], szName[MAX_OBJECT_NAME];
240 BOOL bIsDeleted;
241
242 _stprintf(szQuery, _T("Checking %s objects..."), pszDisplayName);
243 StartStage(szQuery);
244
245 _stprintf(szQuery, _T("SELECT id,node_id FROM %s"), pszTable);
246 hResult = SQLSelect(szQuery);
247 if (hResult != NULL)
248 {
249 dwNumObjects = DBGetNumRows(hResult);
250 for(i = 0; i < dwNumObjects; i++)
251 {
252 dwId = DBGetFieldULong(hResult, i, 0);
253
254 // Check appropriate record in object_properties table
255 _sntprintf(szQuery, 256, _T("SELECT name,is_deleted FROM object_properties WHERE object_id=%d"), dwId);
256 hResult2 = SQLSelect(szQuery);
257 if (hResult2 != NULL)
258 {
259 if (DBGetNumRows(hResult2) == 0)
260 {
261 m_iNumErrors++;
262 _tprintf(_T("\rMissing %s object %d properties. Create? (Y/N) "),
263 pszDisplayName, dwId);
264 if (GetYesNo())
265 {
266 _sntprintf(szQuery, 1024,
267 _T("INSERT INTO object_properties (object_id,name,"
268 "status,is_deleted,image_id,inherit_access_rights,"
269 "last_modified,status_calc_alg,status_prop_alg,"
270 "status_fixed_val,status_shift,status_translation,"
271 "status_single_threshold,status_thresholds) VALUES "
272 "(%d,'lost_%s_%d',5,0,0,1,0,0,0,0,0,0,0,'00000000')"),
273 dwId, pszDisplayName, dwId);
274 if (SQLQuery(szQuery))
275 m_iNumFixes++;
276 szName[0] = 0;
277 }
278 }
279 else
280 {
281 DBGetField(hResult2, 0, 0, szName, MAX_OBJECT_NAME);
282 bIsDeleted = DBGetFieldLong(hResult2, 0, 1) ? TRUE : FALSE;
283 }
284 DBFreeResult(hResult2);
285 }
286 else
287 {
288 szName[0] = 0;
289 }
290
291 // Check if referred node exists
292 _sntprintf(szQuery, 256, _T("SELECT name FROM object_properties WHERE object_id=%d AND is_deleted=0"),
293 DBGetFieldULong(hResult, i, 1));
294 hResult2 = SQLSelect(szQuery);
295 if (hResult2 != NULL)
296 {
297 if (DBGetNumRows(hResult2) == 0)
298 {
299 m_iNumErrors++;
300 dwId = DBGetFieldULong(hResult, i, 0);
301 _tprintf(_T("\rUnlinked %s object %d (\"%s\"). Delete? (Y/N) "),
302 pszDisplayName, dwId, szName);
303 if (GetYesNo())
304 {
305 _sntprintf(szQuery, 256, _T("DELETE FROM %s WHERE id=%d"), pszTable, dwId);
306 if (SQLQuery(szQuery))
307 {
308 _sntprintf(szQuery, 256, _T("DELETE FROM object_properties WHERE object_id=%d"), dwId);
309 SQLQuery(szQuery);
310 m_iNumFixes++;
311 }
312 }
313 }
314 DBFreeResult(hResult2);
315 }
316 }
317 DBFreeResult(hResult);
318 }
319 EndStage();
320}
321
322
323//
324// Check common object properties
325//
326
327static void CheckObjectProperties(void)
328{
329 DB_RESULT hResult;
330 TCHAR szQuery[1024];
331 DWORD i, dwNumRows, dwObjectId;
332
333 StartStage(_T("Checking object properties..."));
334 hResult = SQLSelect(_T("SELECT object_id,name,last_modified FROM object_properties"));
335 if (hResult != NULL)
336 {
337 dwNumRows = DBGetNumRows(hResult);
338 for(i = 0; i < dwNumRows; i++)
339 {
340 dwObjectId = DBGetFieldULong(hResult, i, 0);
341
342 // Check last change time
343 if (DBGetFieldULong(hResult, i, 2) == 0)
344 {
345 m_iNumErrors++;
346 _tprintf(_T("\rObject %d [%s] has invalid timestamp. Correct? (Y/N) "),
347 dwObjectId, DBGetField(hResult, i, 1, szQuery, 1024));
348 if (GetYesNo())
349 {
350 _sntprintf(szQuery, 1024, _T("UPDATE object_properties SET last_modified=%ld WHERE object_id=%d"),
351 time(NULL), dwObjectId);
352 if (SQLQuery(szQuery))
353 m_iNumFixes++;
354 }
355 }
356 }
357 DBFreeResult(hResult);
358 }
359 EndStage();
360}
361
362
363//
364// Check cluster objects
365//
366
367static void CheckClusters(void)
368{
369 DB_RESULT hResult;
370 TCHAR szQuery[256], szName[MAX_OBJECT_NAME];
371 DWORD i, dwNumRows, dwObjectId, dwId;
372
373 StartStage(_T("Checking cluster objects..."));
374 hResult = SQLSelect(_T("SELECT cluster_id,node_id FROM cluster_members"));
375 if (hResult != NULL)
376 {
377 dwNumRows = DBGetNumRows(hResult);
378 for(i = 0; i < dwNumRows; i++)
379 {
380 dwObjectId = DBGetFieldULong(hResult, i, 1);
381 if (!IsNodeExist(dwObjectId))
382 {
383 m_iNumErrors++;
384 dwId = DBGetFieldULong(hResult, i, 0);
385 _tprintf(_T("\rCluster object %s [%d] refers to non-existing node %d. Dereference? (Y/N) "),
386 GetObjectName(dwId, szName), dwId, dwObjectId);
387 if (GetYesNo())
388 {
389 _sntprintf(szQuery, 256, _T("DELETE FROM cluster_members WHERE cluster_id=%d AND node_id=%d"),dwId, dwObjectId);
390 if (SQLQuery(szQuery))
391 {
392 m_iNumFixes++;
393 }
394 }
395 }
396 }
397 DBFreeResult(hResult);
398 }
399 EndStage();
400}
401
402
403//
404// Returns TRUE if SELECT returns non-empty set
405//
406
407static BOOL CheckResultSet(TCHAR *pszQuery)
408{
409 DB_RESULT hResult;
410 BOOL bResult = FALSE;
411
412 hResult = SQLSelect(pszQuery);
413 if (hResult != NULL)
414 {
415 bResult = (DBGetNumRows(hResult) > 0);
416 DBFreeResult(hResult);
417 }
418 return bResult;
419}
420
421
422//
423// Check event processing policy
424//
425
426static void CheckEPP(void)
427{
428 DB_RESULT hResult;
429 TCHAR szQuery[1024];
430 int i, iNumRows;
431 DWORD dwId;
432
433 StartStage(_T("Checking event processing policy..."));
434
435 // Check source object ID's
436 hResult = SQLSelect(_T("SELECT object_id FROM policy_source_list"));
437 if (hResult != NULL)
438 {
439 iNumRows = DBGetNumRows(hResult);
440 for(i = 0; i < iNumRows; i++)
441 {
442 dwId = DBGetFieldULong(hResult, i, 0);
443 _stprintf(szQuery, _T("SELECT object_id FROM object_properties WHERE object_id=%d"), dwId);
444 if (!CheckResultSet(szQuery))
445 {
446 m_iNumErrors++;
447 _tprintf(_T("\rInvalid object ID %d used. Correct? (Y/N) "), dwId);
448 if (GetYesNo())
449 {
450 _stprintf(szQuery, _T("DELETE FROM policy_source_list WHERE object_id=%d"), dwId);
451 if (SQLQuery(szQuery))
452 m_iNumFixes++;
453 }
454 }
455 }
456 DBFreeResult(hResult);
457 }
458
459 // Check event ID's
460 hResult = SQLSelect(_T("SELECT event_code FROM policy_event_list"));
461 if (hResult != NULL)
462 {
463 iNumRows = DBGetNumRows(hResult);
464 for(i = 0; i < iNumRows; i++)
465 {
466 dwId = DBGetFieldULong(hResult, i, 0);
467 if (dwId & GROUP_FLAG)
468 _stprintf(szQuery, _T("SELECT id FROM event_groups WHERE id=%d"), dwId);
469 else
470 _stprintf(szQuery, _T("SELECT event_code FROM event_cfg WHERE event_code=%d"), dwId);
471 if (!CheckResultSet(szQuery))
472 {
473 m_iNumErrors++;
474 _tprintf(_T("\rInvalid event%s ID 0x%08X used. Correct? (Y/N) "),
475 (dwId & GROUP_FLAG) ? _T(" group") : _T(""), dwId);
476 if (GetYesNo())
477 {
478 _stprintf(szQuery, _T("DELETE FROM policy_event_list WHERE event_code=%d"), dwId);
479 if (SQLQuery(szQuery))
480 m_iNumFixes++;
481 }
482 }
483 }
484 DBFreeResult(hResult);
485 }
486
487 // Check action ID's
488 hResult = SQLSelect(_T("SELECT action_id FROM policy_action_list"));
489 if (hResult != NULL)
490 {
491 iNumRows = DBGetNumRows(hResult);
492 for(i = 0; i < iNumRows; i++)
493 {
494 dwId = DBGetFieldULong(hResult, i, 0);
495 _stprintf(szQuery, _T("SELECT action_id FROM actions WHERE action_id=%d"), dwId);
496 if (!CheckResultSet(szQuery))
497 {
498 m_iNumErrors++;
499 _tprintf(_T("\rInvalid action ID %d used. Correct? (Y/N) "), dwId);
500 if (GetYesNo())
501 {
502 _stprintf(szQuery, _T("DELETE FROM policy_action_list WHERE action_id=%d"), dwId);
503 if (SQLQuery(szQuery))
504 m_iNumFixes++;
505 }
506 }
507 }
508 DBFreeResult(hResult);
509 }
510
511 EndStage();
512}
513
514
515//
516// Create idata_xx table
517//
518
519static BOOL CreateIDataTable(DWORD nodeId)
520{
521 char szQuery[256], szQueryTemplate[256];
522 DWORD i;
523
524 ConfigReadStr("IDataTableCreationCommand", szQueryTemplate, 255, "");
525 sprintf(szQuery, szQueryTemplate, nodeId);
526 if (!SQLQuery(szQuery))
527 return FALSE;
528
529 for(i = 0; i < 10; i++)
530 {
531 sprintf(szQuery, "IDataIndexCreationCommand_%d", i);
532 ConfigReadStr(szQuery, szQueryTemplate, 255, "");
533 if (szQueryTemplate[0] != 0)
534 {
535 sprintf(szQuery, szQueryTemplate, nodeId, nodeId);
536 if (!SQLQuery(szQuery))
537 return FALSE;
538 }
539 }
540
541 return TRUE;
542}
543
544
545//
546// Check collected data
547//
548
549static void CheckIData(void)
550{
551 int i, nodeCount;
552 time_t now;
553 DWORD nodeId;
554 TCHAR query[1024];
555 DB_RESULT hResultNodes, hResult;
556
557 StartStage(_T("Checking collected data..."));
558
559 now = time(NULL);
560 hResultNodes = SQLSelect(_T("SELECT id FROM nodes"));
561 if (hResultNodes != NULL)
562 {
563 nodeCount = DBGetNumRows(hResultNodes);
564 for(i = 0; i < nodeCount; i++)
565 {
566 nodeId = DBGetFieldULong(hResultNodes, i, 0);
567 _sntprintf(query, 1024, _T("SELECT count(*) FROM idata_%d WHERE idata_timestamp>%d"), nodeId, now);
568// hResult = DBSelect(g_hCoreDB, query);
569 hResult = SQLSelect(query);
570 if (hResult != NULL)
571 {
572 if (DBGetFieldLong(hResult, 0, 0) > 0)
573 {
574 m_iNumErrors++;
575 _tprintf(_T("\rFound collected data for node [%d] with timestamp in the future. Correct? (Y/N) "), nodeId);
576 if (GetYesNo())
577 {
578 _sntprintf(query, 1024, _T("DELETE FROM idata_%d WHERE idata_timestamp>%d"), nodeId, now);
579 if (SQLQuery(query))
580 m_iNumFixes++;
581 }
582 }
583 DBFreeResult(hResult);
584 }
585 else
586 {
587/* m_iNumErrors++;
588 _tprintf(_T("\rData collection table for node [%d] not found. Correct? (Y/N) "), nodeId);
589 if (GetYesNo())
590 {
591 if (CreateIDataTable(nodeId))
592 m_iNumFixes++;
593 }*/
594 }
595 }
596 DBFreeResult(hResultNodes);
597 }
598
599 _sntprintf(query, 1024, _T("SELECT count(*) FROM raw_dci_values WHERE last_poll_time>%d"), now);
600 hResult = SQLSelect(query);
601 if (hResult != NULL)
602 {
603 if (DBGetFieldLong(hResult, 0, 0) > 0)
604 {
605 m_iNumErrors++;
606 _tprintf(_T("\rFound DCIs with last poll timestamp in the future. Correct? (Y/N) "));
607 if (GetYesNo())
608 {
609 _sntprintf(query, 1024, _T("UPDATE raw_dci_values SET last_poll_time=%d WHERE last_poll_time>%d"), now, now);
610 if (SQLQuery(query))
611 m_iNumFixes++;
612 }
613 }
614 DBFreeResult(hResult);
615 }
616
617 EndStage();
618}
619
620
621//
622// Check template to node mapping
623//
624
625static void CheckTemplateNodeMapping(void)
626{
627 DB_RESULT hResult;
628 TCHAR name[256], query[256];
629 DWORD i, dwNumRows, dwTemplateId, dwNodeId;
630
631 StartStage(_T("Checking template to node mapping..."));
632 hResult = SQLSelect(_T("SELECT template_id,node_id FROM dct_node_map ORDER BY template_id"));
633 if (hResult != NULL)
634 {
635 dwNumRows = DBGetNumRows(hResult);
636 for(i = 0; i < dwNumRows; i++)
637 {
638 dwTemplateId = DBGetFieldULong(hResult, i, 0);
639 dwNodeId = DBGetFieldULong(hResult, i, 1);
640
641 // Check node existence
642 if (!IsNodeExist(dwNodeId))
643 {
644 m_iNumErrors++;
645 GetObjectName(dwTemplateId, name);
646 _tprintf(_T("\rTemplate %d [%s] mapped to non-existent node %d. Correct? (Y/N) "),
647 dwTemplateId, name, dwNodeId);
648 if (GetYesNo())
649 {
650 _sntprintf(query, 256, _T("DELETE FROM dct_node_map WHERE template_id=%d AND node_id=%d"),
651 dwTemplateId, dwNodeId);
652 if (SQLQuery(query))
653 m_iNumFixes++;
654 }
655 }
656 }
657 DBFreeResult(hResult);
658 }
659 EndStage();
660}
661
662
663//
664// Check database for errors
665//
666
667void CheckDatabase(void)
668{
669 DB_RESULT hResult;
670 LONG iVersion = 0;
671 BOOL bCompleted = FALSE;
672
673 _tprintf(_T("Checking database:\n"));
674
675 // Get database format version
28f5b9a4 676 iVersion = DBGetSchemaVersion(g_hCoreDB);
5039dede
AK
677 if (iVersion < DB_FORMAT_VERSION)
678 {
679 _tprintf(_T("Your database has format version %d, this tool is compiled for version %d.\nUse \"upgrade\" command to upgrade your database first.\n"),
680 iVersion, DB_FORMAT_VERSION);
681 }
682 else if (iVersion > DB_FORMAT_VERSION)
683 {
684 _tprintf(_T("Your database has format version %d, this tool is compiled for version %d.\n"
685 "You need to upgrade your server before using this database.\n"),
686 iVersion, DB_FORMAT_VERSION);
687
688 }
689 else
690 {
691 TCHAR szLockStatus[MAX_DB_STRING], szLockInfo[MAX_DB_STRING];
692 BOOL bLocked;
693
694 // Check if database is locked
695 hResult = DBSelect(g_hCoreDB, _T("SELECT var_value FROM config WHERE var_name='DBLockStatus'"));
696 if (hResult != NULL)
697 {
698 if (DBGetNumRows(hResult) > 0)
699 {
700 DBGetField(hResult, 0, 0, szLockStatus, MAX_DB_STRING);
701 DecodeSQLString(szLockStatus);
702 bLocked = _tcscmp(szLockStatus, _T("UNLOCKED"));
703 }
704 DBFreeResult(hResult);
705
706 if (bLocked)
707 {
708 hResult = DBSelect(g_hCoreDB, _T("SELECT var_value FROM config WHERE var_name='DBLockInfo'"));
709 if (hResult != NULL)
710 {
711 if (DBGetNumRows(hResult) > 0)
712 {
713 DBGetField(hResult, 0, 0, szLockInfo, MAX_DB_STRING);
714 DecodeSQLString(szLockInfo);
715 }
716 DBFreeResult(hResult);
717 }
718 }
719 }
720
721 if (bLocked)
722 {
723 _tprintf(_T("Database is locked by server %s [%s]\n"
724 "Do you wish to force database unlock? (Y/N) "),
725 szLockStatus, szLockInfo);
726 if (GetYesNo())
727 {
728 if (SQLQuery(_T("UPDATE config SET var_value='UNLOCKED' where var_name='DBLockStatus'")))
729 {
730 bLocked = FALSE;
731 _tprintf(_T("Database lock removed\n"));
732 }
733 }
734 }
735
736 if (!bLocked)
737 {
738 DBBegin(g_hCoreDB);
739
740 CheckNodes();
741 CheckComponents(_T("interface"), _T("interfaces"));
742 CheckComponents(_T("network service"), _T("network_services"));
743 CheckClusters();
744 CheckTemplateNodeMapping();
745 CheckObjectProperties();
746 CheckEPP();
747 CheckIData();
748
749 if (m_iNumErrors == 0)
750 {
751 _tprintf(_T("Database doesn't contain any errors\n"));
752 DBCommit(g_hCoreDB);
753 }
754 else
755 {
756 _tprintf(_T("%d errors was found, %d errors was corrected\n"), m_iNumErrors, m_iNumFixes);
757 if (m_iNumFixes == m_iNumErrors)
758 _tprintf(_T("All errors in database was fixed\n"));
759 else
760 _tprintf(_T("Database still contain errors\n"));
761 if (m_iNumFixes > 0)
762 {
763 _tprintf(_T("Commit changes (Y/N) "));
764 if (GetYesNo())
765 {
766 _tprintf(_T("Committing changes...\n"));
767 if (DBCommit(g_hCoreDB))
768 _tprintf(_T("Changes was successfully committed to database\n"));
769 }
770 else
771 {
772 _tprintf(_T("Rolling back changes...\n"));
773 if (DBRollback(g_hCoreDB))
774 _tprintf(_T("All changes made to database was cancelled\n"));
775 }
776 }
777 else
778 {
779 DBRollback(g_hCoreDB);
780 }
781 }
782 bCompleted = TRUE;
783 }
784 }
785
786 _tprintf(_T("Database check %s\n"), bCompleted ? _T("completed") : _T("aborted"));
787}