changed log file format
[public/netxms.git] / src / server / core / hk.cpp
CommitLineData
1ea2769b 1/*
5039dede 2** NetXMS - Network Management System
a191c634 3** Copyright (C) 2003-2017 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**
a65c1819 19** File: hk.cpp
5039dede
AK
20**
21**/
22
23#include "nxcore.h"
24
1e42f2e8
VK
25#define DEBUG_TAG _T("housekeeper")
26
171c2fd6 27/**
0dd7953d
VK
28 * Delete empty subnets from given list
29 */
30static void DeleteEmptySubnetsFromList(ObjectArray<NetObj> *subnets)
31{
32 for(int i = 0; i < subnets->size(); i++)
33 {
34 NetObj *object = subnets->get(i);
1e42f2e8 35 nxlog_debug_tag(DEBUG_TAG, 7, _T("DeleteEmptySubnets: checking subnet %s [%d] (refs: %d refs, children: %d, parents: %d)"),
0dd7953d
VK
36 object->getName(), object->getId(), object->getRefCount(), object->getChildCount(), object->getParentCount());
37 if (object->isEmpty())
38 {
1e42f2e8 39 nxlog_debug_tag(DEBUG_TAG, 5, _T("DeleteEmptySubnets: delete subnet %s [%d] (refs: %d, children: %d, parents: %d)"),
0dd7953d
VK
40 object->getName(), object->getId(), object->getRefCount(), object->getChildCount(), object->getParentCount());
41 object->deleteObject();
42 }
43 object->decRefCount();
44 }
45}
46
47/**
171c2fd6
VK
48 * Delete empty subnets
49 */
465b3f2d 50static void DeleteEmptySubnets()
5039dede 51{
0dd7953d
VK
52 if (IsZoningEnabled())
53 {
a191c634 54 ObjectArray<NetObj> *zones = g_idxZoneByUIN.getObjects(true);
0dd7953d
VK
55 for(int i = 0; i < zones->size(); i++)
56 {
57 Zone *zone = (Zone *)zones->get(i);
58 ObjectArray<NetObj> *subnets = zone->getSubnets(true);
59 DeleteEmptySubnetsFromList(subnets);
60 delete subnets;
61 zone->decRefCount();
62 }
63 delete zones;
64 }
65 else
66 {
67 ObjectArray<NetObj> *subnets = g_idxSubnetByAddr.getObjects(true);
68 DeleteEmptySubnetsFromList(subnets);
69 delete subnets;
70 }
5039dede
AK
71}
72
171c2fd6 73/**
171c2fd6
VK
74 * Delete notes for alarm
75 */
967893bb 76void DeleteAlarmNotes(DB_HANDLE hdb, UINT32 alarmId)
1add6d73
VK
77{
78 DB_STATEMENT hStmt = DBPrepare(hdb, _T("DELETE FROM alarm_notes WHERE alarm_id=?"));
79 if (hStmt == NULL)
80 return;
81
82 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, alarmId);
83 DBExecute(hStmt);
84 DBFreeStatement(hStmt);
85}
86
171c2fd6 87/**
22ee6d97
VK
88 * Delete realted events for alarm
89 */
967893bb 90void DeleteAlarmEvents(DB_HANDLE hdb, UINT32 alarmId)
22ee6d97
VK
91{
92 DB_STATEMENT hStmt = DBPrepare(hdb, _T("DELETE FROM alarm_events WHERE alarm_id=?"));
93 if (hStmt == NULL)
94 return;
95
96 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, alarmId);
97 DBExecute(hStmt);
98 DBFreeStatement(hStmt);
99}
100
101/**
171c2fd6
VK
102 * Remove outdated alarm records
103 */
1add6d73
VK
104static void CleanAlarmHistory(DB_HANDLE hdb)
105{
967893bb 106 UINT32 retentionTime = ConfigReadULong(_T("AlarmHistoryRetentionTime"), 180);
1add6d73
VK
107 if (retentionTime == 0)
108 return;
109
1e42f2e8 110 nxlog_debug_tag(DEBUG_TAG, 2, _T("Clearing alarm log (retention time %d days)"), retentionTime);
1add6d73
VK
111 retentionTime *= 86400; // Convert days to seconds
112 time_t ts = time(NULL) - (time_t)retentionTime;
113
0367f999 114 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT alarm_id FROM alarms WHERE alarm_state=3 AND last_change_time<?"));
1add6d73
VK
115 if (hStmt != NULL)
116 {
967893bb 117 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, (UINT32)ts);
1add6d73
VK
118 DB_RESULT hResult = DBSelectPrepared(hStmt);
119 if (hResult != NULL)
120 {
121 int count = DBGetNumRows(hResult);
122 for(int i = 0; i < count; i++)
22ee6d97 123 {
967893bb 124 UINT32 alarmId = DBGetFieldULong(hResult, i, 0);
22ee6d97
VK
125 DeleteAlarmNotes(hdb, alarmId);
126 DeleteAlarmEvents(hdb, alarmId);
127 }
1add6d73
VK
128 DBFreeResult(hResult);
129 }
130 DBFreeStatement(hStmt);
131 }
132
0367f999 133 hStmt = DBPrepare(hdb, _T("DELETE FROM alarms WHERE alarm_state=3 AND last_change_time<?"));
1add6d73
VK
134 if (hStmt != NULL)
135 {
967893bb 136 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, (UINT32)ts);
1add6d73
VK
137 DBExecute(hStmt);
138 DBFreeStatement(hStmt);
139 }
140}
141
171c2fd6
VK
142/**
143 * Callback for cleaning expired DCI data on node
144 */
6aba3998
VK
145static void CleanDciData(NetObj *object, void *data)
146{
5f648670 147 ((DataCollectionTarget *)object)->cleanDCIData((DB_HANDLE)data);
6aba3998
VK
148}
149
171c2fd6 150/**
a64c346b
VK
151 * Housekeeper wakeup condition
152 */
153static CONDITION s_wakeupCondition = INVALID_CONDITION_HANDLE;
154
155/**
156 * Housekeeper shutdown flag
157 */
158static bool s_shutdown = false;
159
160/**
171c2fd6
VK
161 * Housekeeper thread
162 */
a64c346b 163static THREAD_RESULT THREAD_CALL HouseKeeper(void *pArg)
5039dede 164{
930a2a62
VK
165 ThreadSetName("Housekeeper");
166
b06ae508
VK
167 // Read housekeeping configuration
168 int hour;
169 int minute;
170
171 TCHAR buffer[64];
172 ConfigReadStr(_T("HousekeeperStartTime"), buffer, 64, _T("02:00"));
173 TCHAR *p = _tcschr(buffer, _T(':'));
174 if (p != NULL)
175 {
176 *p = 0;
177 p++;
178 minute = _tcstol(p, NULL, 10);
179 if ((minute < 0) || (minute > 59))
180 {
1e42f2e8 181 nxlog_debug_tag(DEBUG_TAG, 2, _T("Invalid minute value %s"), p);
b06ae508
VK
182 minute = 0;
183 }
184 }
185 else
186 {
187 minute = 0;
188 }
189 hour = _tcstol(buffer, NULL, 10);
190 if ((hour < 0) || (hour > 23))
191 {
1e42f2e8 192 nxlog_debug_tag(DEBUG_TAG, 2, _T("Invalid hour value %s"), buffer);
b06ae508
VK
193 hour = 0;
194 }
1e42f2e8 195 nxlog_debug_tag(DEBUG_TAG, 2, _T("Wakeup time is %02d:%02d"), hour, minute);
5039dede 196
b06ae508 197 int sleepTime = GetSleepTime(hour, minute, 0);
1e42f2e8 198 nxlog_debug_tag(DEBUG_TAG, 2, _T("Sleeping for %d seconds"), sleepTime);
5039dede 199
a64c346b 200 while(!s_shutdown)
5039dede 201 {
a64c346b
VK
202 ConditionWait(s_wakeupCondition, sleepTime * 1000);
203 if (s_shutdown)
204 break;
205
1e42f2e8 206 nxlog_debug_tag(DEBUG_TAG, 2, _T("Wakeup"));
465b3f2d 207
1ea2769b 208 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
1add6d73 209 CleanAlarmHistory(hdb);
ff392ecf 210
b06ae508
VK
211 time_t currTime = time(NULL);
212
c9a9601c 213 // Remove outdated event log records
b06ae508 214 UINT32 dwRetentionTime = ConfigReadULong(_T("EventLogRetentionTime"), 90);
c9a9601c 215 if (dwRetentionTime > 0)
f68d9eac 216 {
1e42f2e8 217 nxlog_debug_tag(DEBUG_TAG, 2, _T("Clearing event log (retention time %d days)"), dwRetentionTime);
c9a9601c 218 dwRetentionTime *= 86400; // Convert days to seconds
b06ae508
VK
219 TCHAR query[256];
220 _sntprintf(query, sizeof(query) / sizeof(TCHAR), _T("DELETE FROM event_log WHERE event_timestamp<%ld"), (long)(currTime - dwRetentionTime));
221 DBQuery(hdb, query);
f68d9eac 222 }
5039dede 223
c9a9601c
VK
224 // Remove outdated syslog records
225 dwRetentionTime = ConfigReadULong(_T("SyslogRetentionTime"), 90);
226 if (dwRetentionTime > 0)
227 {
1e42f2e8 228 nxlog_debug_tag(DEBUG_TAG, 2, _T("Clearing syslog (retention time %d days)"), dwRetentionTime);
c9a9601c 229 dwRetentionTime *= 86400; // Convert days to seconds
b06ae508
VK
230 TCHAR query[256];
231 _sntprintf(query, sizeof(query) / sizeof(TCHAR), _T("DELETE FROM syslog WHERE msg_timestamp<%ld"), (long)(currTime - dwRetentionTime));
232 DBQuery(hdb, query);
c9a9601c
VK
233 }
234
235 // Remove outdated audit log records
236 dwRetentionTime = ConfigReadULong(_T("AuditLogRetentionTime"), 90);
237 if (dwRetentionTime > 0)
238 {
1e42f2e8 239 nxlog_debug_tag(DEBUG_TAG, 2, _T("Clearing audit log (retention time %d days)"), dwRetentionTime);
c9a9601c 240 dwRetentionTime *= 86400; // Convert days to seconds
b06ae508
VK
241 TCHAR query[256];
242 _sntprintf(query, sizeof(query) / sizeof(TCHAR), _T("DELETE FROM audit_log WHERE timestamp<%ld"), (long)(currTime - dwRetentionTime));
243 DBQuery(hdb, query);
c9a9601c
VK
244 }
245
0f75f8fc
VK
246 // Remove outdated SNMP trap log records
247 dwRetentionTime = ConfigReadULong(_T("SNMPTrapLogRetentionTime"), 90);
248 if (dwRetentionTime > 0)
249 {
1e42f2e8 250 nxlog_debug_tag(DEBUG_TAG, 2, _T("Clearing SNMP trap log (retention time %d days)"), dwRetentionTime);
0f75f8fc 251 dwRetentionTime *= 86400; // Convert days to seconds
b06ae508
VK
252 TCHAR query[256];
253 _sntprintf(query, sizeof(query) / sizeof(TCHAR), _T("DELETE FROM snmp_trap_log WHERE trap_timestamp<%ld"), (long)(currTime - dwRetentionTime));
254 DBQuery(hdb, query);
0f75f8fc
VK
255 }
256
c9a9601c 257 // Delete empty subnets if needed
c8076b19 258 if (g_flags & AF_DELETE_EMPTY_SUBNETS)
c9a9601c
VK
259 DeleteEmptySubnets();
260
c9a9601c 261 // Remove expired DCI data
1e42f2e8 262 nxlog_debug_tag(DEBUG_TAG, 2, _T("Clearing collected DCI data"));
5f648670
VK
263 g_idxNodeById.forEach(CleanDciData, hdb);
264 g_idxClusterById.forEach(CleanDciData, hdb);
265 g_idxMobileDeviceById.forEach(CleanDciData, hdb);
ce9e00cc 266 g_idxSensorById.forEach(CleanDciData, hdb);
c9a9601c 267
465b3f2d 268 DBConnectionPoolReleaseConnection(hdb);
69bb7f47 269
1ea2769b 270 // Call hooks in loaded modules
271 for(UINT32 i = 0; i < g_dwNumModules; i++)
272 {
1fcc93ce 273 if (g_pModuleList[i].pfHousekeeperHook != NULL)
1ea2769b 274 {
1e42f2e8 275 nxlog_debug_tag(DEBUG_TAG, 3, _T("Housekeeper: calling hook in module %s"), g_pModuleList[i].szName);
1ea2769b 276 g_pModuleList[i].pfHousekeeperHook();
277 }
278 }
279
69bb7f47 280 SaveCurrentFreeId();
b06ae508
VK
281
282 ThreadSleep(1); // to prevent multiple executions if processing took less then 1 second
283 sleepTime = GetSleepTime(hour, minute, 0);
1e42f2e8 284 nxlog_debug_tag(DEBUG_TAG, 2, _T("Sleeping for %d seconds"), sleepTime);
5039dede 285 }
465b3f2d 286
1e42f2e8 287 nxlog_debug_tag(DEBUG_TAG, 1, _T("Housekeeper thread terminated"));
5039dede
AK
288 return THREAD_OK;
289}
a64c346b
VK
290
291/**
292 * Housekeeper thread handle
293 */
294static THREAD s_thread = INVALID_THREAD_HANDLE;
295
296/**
297 * Start housekeeper
298 */
299void StartHouseKeeper()
300{
301 s_wakeupCondition = ConditionCreate(FALSE);
302 s_thread = ThreadCreateEx(HouseKeeper, 0, NULL);
303}
304
305/**
306 * Stop housekeeper
307 */
308void StopHouseKeeper()
309{
310 s_shutdown = true;
311 ConditionSet(s_wakeupCondition);
312 ThreadJoin(s_thread);
313 ConditionDestroy(s_wakeupCondition);
314}
315
316/**
317 * Run housekeeper
318 */
319void RunHouseKeeper()
320{
321 ConditionSet(s_wakeupCondition);
322}