schema-related information (like schema version, DB syntax, etc.) moved from "config...
[public/netxms.git] / src / server / core / hk.cpp
CommitLineData
5039dede
AK
1/*
2** NetXMS - Network Management System
3** Copyright (C) 2003, 2004, 2005 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** $module: hk.cpp
20**
21**/
22
23#include "nxcore.h"
24
25
26//
27// Static data
28//
29
30static DB_HANDLE m_hdb;
31
32
33//
34// Remove deleted objects which are no longer referenced
35//
36
37static void CleanDeletedObjects(void)
38{
39 DB_RESULT hResult;
40
41 hResult = DBSelect(m_hdb, "SELECT object_id FROM deleted_objects");
42 if (hResult != NULL)
43 {
44 DB_ASYNC_RESULT hAsyncResult;
45 char szQuery[256];
46 int i, iNumRows;
47 DWORD dwObjectId;
48
49 iNumRows = DBGetNumRows(hResult);
50 for(i = 0; i < iNumRows; i++)
51 {
52 dwObjectId = DBGetFieldULong(hResult, i, 0);
53
54 // Check if there are references to this object in event log
55 sprintf(szQuery, "SELECT event_source FROM event_log WHERE event_source=%d", dwObjectId);
56 hAsyncResult = DBAsyncSelect(m_hdb, szQuery);
57 if (hAsyncResult != NULL)
58 {
59 if (!DBFetch(hAsyncResult))
60 {
61 // No records with that source ID, so we can purge this object
62 sprintf(szQuery, "DELETE FROM deleted_objects WHERE object_id=%d", dwObjectId);
63 QueueSQLRequest(szQuery);
64 DbgPrintf(4, "*HK* Deleted object with id %d was purged", dwObjectId);
65 }
66 DBFreeAsyncResult(m_hdb, hAsyncResult);
67 }
68 }
69 DBFreeResult(hResult);
70 }
71}
72
73
74//
75// Delete empty subnets
76//
77
78static void DeleteEmptySubnets(void)
79{
80 DWORD i;
81
82 RWLockReadLock(g_rwlockIdIndex, INFINITE);
83
84 // Walk through subnets and delete empty ones
85 for(i = 0; i < g_dwIdIndexSize; i++)
86 if (((NetObj *)g_pIndexById[i].pObject)->Type() == OBJECT_SUBNET)
87 {
88 if (((NetObj *)g_pIndexById[i].pObject)->IsEmpty())
89 {
90 PostEvent(EVENT_SUBNET_DELETED, ((NetObj *)g_pIndexById[i].pObject)->Id(), NULL);
91 ((NetObj *)g_pIndexById[i].pObject)->Delete(TRUE);
92 }
93 }
94
95 RWLockUnlock(g_rwlockIdIndex);
96}
97
98
99//
100// Maintenance tasks specific to PostgreSQL
101//
102
103static void PGSQLMaintenance(void)
104{
105 if (!ConfigReadInt("DisableVacuum", 0))
106 DBQuery(m_hdb, "VACUUM ANALYZE");
107}
108
109
110//
111// Housekeeper thread
112//
113
114THREAD_RESULT THREAD_CALL HouseKeeper(void *pArg)
115{
116 time_t currTime;
117 char szQuery[256];
118 DWORD i, dwRetentionTime, dwInterval;
119
120 // Establish separate connection to database if needed
121 if (g_dwFlags & AF_ENABLE_MULTIPLE_DB_CONN)
122 {
123 m_hdb = DBConnect();
124 if (m_hdb == NULL)
125 {
126 nxlog_write(MSG_DB_CONNFAIL, EVENTLOG_ERROR_TYPE, NULL);
127 m_hdb = g_hCoreDB; // Switch to main DB connection
128 }
129 }
130 else
131 {
132 m_hdb = g_hCoreDB;
133 }
134
135 // Load configuration
136 dwInterval = ConfigReadULong("HouseKeepingInterval", 3600);
137
138 // Housekeeping loop
139 while(!ShutdownInProgress())
140 {
141 currTime = time(NULL);
142 if (SleepAndCheckForShutdown(dwInterval - (DWORD)(currTime % dwInterval)))
143 break; // Shutdown has arrived
144
145 // Remove outdated event log records
146 dwRetentionTime = ConfigReadULong("EventLogRetentionTime", 90);
147 if (dwRetentionTime > 0)
148 {
149 dwRetentionTime *= 86400; // Convert days to seconds
150 sprintf(szQuery, "DELETE FROM event_log WHERE event_timestamp<%ld", currTime - dwRetentionTime);
151 DBQuery(m_hdb, szQuery);
152 }
153
154 // Remove outdated syslog records
155 dwRetentionTime = ConfigReadULong("SyslogRetentionTime", 90);
156 if (dwRetentionTime > 0)
157 {
158 dwRetentionTime *= 86400; // Convert days to seconds
159 sprintf(szQuery, "DELETE FROM syslog WHERE msg_timestamp<%ld", currTime - dwRetentionTime);
160 DBQuery(m_hdb, szQuery);
161 }
162
163 // Remove outdated audit log records
164 dwRetentionTime = ConfigReadULong("AuditLogRetentionTime", 90);
165 if (dwRetentionTime > 0)
166 {
167 dwRetentionTime *= 86400; // Convert days to seconds
168 sprintf(szQuery, "DELETE FROM audit_log WHERE timestamp<%ld", currTime - dwRetentionTime);
169 DBQuery(m_hdb, szQuery);
170 }
171
172 // Delete empty subnets if needed
173 if (g_dwFlags & AF_DELETE_EMPTY_SUBNETS)
174 DeleteEmptySubnets();
175
176 // Remove deleted objects which are no longer referenced
177 CleanDeletedObjects();
178
179 // Remove expired DCI data
180 RWLockReadLock(g_rwlockNodeIndex, INFINITE);
181 for(i = 0; i < g_dwNodeAddrIndexSize; i++)
182 ((Node *)g_pNodeIndexByAddr[i].pObject)->CleanDCIData();
183 RWLockUnlock(g_rwlockNodeIndex);
184
185 // Run DB-specific maintenance tasks
28f5b9a4 186 if (g_nDBSyntax == DB_SYNTAX_PGSQL)
5039dede
AK
187 PGSQLMaintenance();
188 }
189
190 // Disconnect from database if using separate connection
191 if (m_hdb != g_hCoreDB)
192 {
193 DBDisconnect(m_hdb);
194 }
195 DbgPrintf(1, "Housekeeper thread terminated");
196 return THREAD_OK;
197}