Zabbix Unofficial GitWeb - Updated every 4 hours from svn://svn.zabbix.com
The objective of this repository is to provide an easy way to view/search Zabbix source-code
.......PS. [ZBX-4980] fixed trapper process crash/hang on decoding big base64 encoded...
[zabbix1.8/.git] / src / zabbix_server / housekeeper / housekeeper.c
1 /*
2 ** ZABBIX
3 ** Copyright (C) 2000-2005 SIA Zabbix
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
20 #include "common.h"
21 #include "db.h"
22 #include "log.h"
23 #include "daemon.h"
24 #include "zbxself.h"
25 #include "zbxalgo.h"
26
27 #include "housekeeper.h"
28
29 extern unsigned char    process_type;
30
31 /******************************************************************************
32  *                                                                            *
33  * Function: housekeeping_cleanup                                             *
34  *                                                                            *
35  * Purpose: remove deleted items data                                         *
36  *                                                                            *
37  * Return value: number of rows deleted                                       *
38  *                                                                            *
39  * Author: Alexei Vladishev, Dmitry Borovikov                                 *
40  *                                                                            *
41  * Comments: sqlite3 does not use CONFIG_MAX_HOUSEKEEPER_DELETE, deletes all  *
42  *                                                                            *
43  ******************************************************************************/
44 static int      housekeeping_cleanup()
45 {
46         const char              *__function_name = "housekeeping_cleanup";
47         DB_HOUSEKEEPER          housekeeper;
48         DB_RESULT               result;
49         DB_ROW                  row;
50         int                     d, deleted = 0;
51         zbx_vector_uint64_t     housekeeperids;
52
53         zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
54
55         zbx_vector_uint64_create(&housekeeperids);
56
57         /* order by tablename to effectively use DB cache */
58         result = DBselect(
59                         "select housekeeperid,tablename,field,value"
60                         " from housekeeper"
61                         " order by tablename");
62
63         while (NULL != (row = DBfetch(result)))
64         {
65                 ZBX_STR2UINT64(housekeeper.housekeeperid, row[0]);
66                 housekeeper.tablename = row[1];
67                 housekeeper.field = row[2];
68                 ZBX_STR2UINT64(housekeeper.value, row[3]);
69
70                 if (0 == CONFIG_MAX_HOUSEKEEPER_DELETE)
71                 {
72                         d = DBexecute(
73                                         "delete from %s"
74                                         " where %s=" ZBX_FS_UI64,
75                                         housekeeper.tablename,
76                                         housekeeper.field,
77                                         housekeeper.value);
78                 }
79                 else
80                 {
81 #if defined(HAVE_IBM_DB2) || defined(HAVE_ORACLE)
82                         d = DBexecute(
83                                         "delete from %s"
84                                         " where %s=" ZBX_FS_UI64
85                                                 " and rownum<=%d",
86                                         housekeeper.tablename,
87                                         housekeeper.field,
88                                         housekeeper.value,
89                                         CONFIG_MAX_HOUSEKEEPER_DELETE);
90 #elif defined(HAVE_MYSQL)
91                         d = DBexecute(
92                                         "delete from %s"
93                                         " where %s=" ZBX_FS_UI64 " limit %d",
94                                         housekeeper.tablename,
95                                         housekeeper.field,
96                                         housekeeper.value,
97                                         CONFIG_MAX_HOUSEKEEPER_DELETE);
98 #elif defined(HAVE_POSTGRESQL)
99                         extern int      ZBX_PG_SVERSION;
100
101                         /* PostgreSQL array constructors are available since version 7.4 */
102                         if (70400 > ZBX_PG_SVERSION)
103                         {
104                                 d = DBexecute(
105                                                 "delete from %s"
106                                                 " where %s=" ZBX_FS_UI64
107                                                         " and clock in (select clock from %s"
108                                                                 " where %s=" ZBX_FS_UI64 " limit %d)",
109                                                 housekeeper.tablename,
110                                                 housekeeper.field,
111                                                 housekeeper.value,
112                                                 housekeeper.tablename,
113                                                 housekeeper.field,
114                                                 housekeeper.value,
115                                                 CONFIG_MAX_HOUSEKEEPER_DELETE);
116                         }
117                         else
118                         {
119                                 d = DBexecute(
120                                                 "delete from %s"
121                                                 " where ctid = any(array(select ctid from %s"
122                                                         " where %s=" ZBX_FS_UI64 " limit %d))",
123                                                 housekeeper.tablename,
124                                                 housekeeper.tablename,
125                                                 housekeeper.field,
126                                                 housekeeper.value,
127                                                 CONFIG_MAX_HOUSEKEEPER_DELETE);
128                         }
129 #elif defined(HAVE_SQLITE3)
130                         d = 0;
131 #endif
132                 }
133
134                 if (0 == d || 0 == CONFIG_MAX_HOUSEKEEPER_DELETE || CONFIG_MAX_HOUSEKEEPER_DELETE > d)
135                         zbx_vector_uint64_append(&housekeeperids, housekeeper.housekeeperid);
136
137                 deleted += d;
138         }
139         DBfree_result(result);
140
141         if (0 != housekeeperids.values_num)
142         {
143                 char    *sql = NULL;
144                 int     sql_alloc = 512, sql_offset = 0;
145
146                 sql = zbx_malloc(sql, sql_alloc);
147
148                 zbx_vector_uint64_sort(&housekeeperids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
149
150                 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, 32, "delete from housekeeper where");
151                 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "housekeeperid",
152                                 housekeeperids.values, housekeeperids.values_num);
153
154                 DBexecute("%s", sql);
155
156                 zbx_free(sql);
157         }
158
159         zbx_vector_uint64_destroy(&housekeeperids);
160
161         zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __function_name, deleted);
162
163         return deleted;
164 }
165
166 static int      housekeeping_sessions(int now)
167 {
168         const char      *__function_name = "housekeeping_sessions";
169         int             deleted;
170
171         zabbix_log(LOG_LEVEL_DEBUG, "In %s() now:%d", __function_name, now);
172
173         deleted = DBexecute("delete from sessions where lastaccess<%d", now - SEC_PER_YEAR);
174
175         zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __function_name, deleted);
176
177         return deleted;
178 }
179
180 static int      housekeeping_alerts(int now)
181 {
182         const char      *__function_name = "housekeeping_alerts";
183         int             alert_history;
184         DB_RESULT       result;
185         DB_ROW          row;
186         int             deleted = 0;
187
188         zabbix_log(LOG_LEVEL_DEBUG, "In %s() now:%d", __function_name, now);
189
190         result = DBselect("select alert_history from config");
191
192         if (NULL == (row = DBfetch(result)) || SUCCEED == DBis_null(row[0]))
193         {
194                 zabbix_log(LOG_LEVEL_ERR, "no records in table 'config'");
195         }
196         else
197         {
198                 alert_history = atoi(row[0]);
199
200                 deleted = DBexecute("delete from alerts where clock<%d", now - alert_history * SEC_PER_DAY);
201         }
202         DBfree_result(result);
203
204         zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __function_name, deleted);
205
206         return deleted;
207 }
208
209 static int      housekeeping_events(int now)
210 {
211         const char      *__function_name = "housekeeping_events";
212         int             event_history, deleted = 0;
213         DB_RESULT       result;
214         DB_RESULT       result2;
215         DB_ROW          row1;
216         DB_ROW          row2;
217         zbx_uint64_t    eventid;
218
219         zabbix_log(LOG_LEVEL_DEBUG, "In %s() now:%d", __function_name, now);
220
221         result = DBselect("select event_history from config");
222
223         if (NULL == (row1 = DBfetch(result)) || SUCCEED == DBis_null(row1[0]))
224         {
225                 zabbix_log(LOG_LEVEL_ERR, "no records in table 'config'");
226         }
227         else
228         {
229                 event_history = atoi(row1[0]);
230
231                 result2 = DBselect("select eventid from events where clock<%d", now - event_history * SEC_PER_DAY);
232
233                 while (NULL != (row2 = DBfetch(result2)))
234                 {
235                         ZBX_STR2UINT64(eventid, row2[0]);
236
237                         DBexecute("delete from acknowledges where eventid=" ZBX_FS_UI64, eventid);
238                         deleted += DBexecute("delete from events where eventid=" ZBX_FS_UI64, eventid);
239                 }
240                 DBfree_result(result2);
241         }
242         DBfree_result(result);
243
244         zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __function_name, deleted);
245
246         return deleted;
247 }
248
249 /******************************************************************************
250  *                                                                            *
251  * Function: delete_history                                                   *
252  *                                                                            *
253  * Purpose: remove outdated information from historical table                 *
254  *                                                                            *
255  * Parameters: now - current timestamp                                        *
256  *                                                                            *
257  * Return value: number of rows deleted                                       *
258  *                                                                            *
259  * Author: Alexei Vladishev                                                   *
260  *                                                                            *
261  * Comments:                                                                  *
262  *                                                                            *
263  ******************************************************************************/
264 static int      delete_history(const char *table, zbx_uint64_t itemid, int keep_history, int now)
265 {
266         const char      *__function_name = "delete_history";
267         DB_RESULT       result;
268         DB_ROW          row;
269         int             min_clock, deleted;
270
271         zabbix_log(LOG_LEVEL_DEBUG, "In %s() table:'%s' itemid:" ZBX_FS_UI64 " keep_history:%d now:%d",
272                 __function_name, table, itemid, keep_history, now);
273
274         result = DBselect("select min(clock) from %s where itemid=" ZBX_FS_UI64, table, itemid);
275
276         if (NULL == (row = DBfetch(result)) || SUCCEED == DBis_null(row[0]))
277         {
278                 DBfree_result(result);
279                 return 0;
280         }
281
282         min_clock = atoi(row[0]);
283         min_clock = MIN(now - keep_history * SEC_PER_DAY, min_clock + 4 * CONFIG_HOUSEKEEPING_FREQUENCY * SEC_PER_HOUR);
284         DBfree_result(result);
285
286         deleted = DBexecute("delete from %s where itemid=" ZBX_FS_UI64 " and clock<%d", table, itemid, min_clock);
287
288         zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __function_name, deleted);
289
290         return deleted;
291 }
292
293 /******************************************************************************
294  *                                                                            *
295  * Function: housekeeping_history_and_trends                                  *
296  *                                                                            *
297  * Purpose: remove outdated information from history and trends               *
298  *                                                                            *
299  * Parameters: now - current timestamp                                        *
300  *                                                                            *
301  * Return value: number of rows deleted                                       *
302  *                                                                            *
303  * Author: Alexei Vladishev                                                   *
304  *                                                                            *
305  * Comments:                                                                  *
306  *                                                                            *
307  ******************************************************************************/
308 static int      housekeeping_history_and_trends(int now)
309 {
310         const char      *__function_name = "housekeeping_history_and_trends";
311         zbx_uint64_t    itemid;
312         DB_RESULT       result;
313         DB_ROW          row;
314         int             history, trends, deleted = 0;
315
316         zabbix_log(LOG_LEVEL_DEBUG, "In %s() now:%d", __function_name, now);
317
318         result = DBselect(
319                         "select i.itemid,i.history,i.trends from items i,hosts h"
320                         " where i.hostid=h.hostid"
321                                 " and h.status in (%d,%d)",
322                         HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED);
323
324         while (NULL != (row = DBfetch(result)))
325         {
326                 ZBX_STR2UINT64(itemid, row[0]);
327                 history = atoi(row[1]);
328                 trends = atoi(row[2]);
329
330                 deleted += delete_history("history", itemid, history, now);
331                 deleted += delete_history("history_uint", itemid, history, now);
332                 deleted += delete_history("history_str", itemid, history, now);
333                 deleted += delete_history("history_text", itemid, history, now);
334                 deleted += delete_history("history_log", itemid, history, now);
335                 deleted += delete_history("trends", itemid, trends, now);
336                 deleted += delete_history("trends_uint", itemid, trends, now);
337         }
338         DBfree_result(result);
339
340         zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __function_name, deleted);
341
342         return deleted;
343 }
344
345 void    main_housekeeper_loop()
346 {
347         int     now, d_history_and_trends, d_cleanup, d_events, d_alerts, d_sessions;
348
349         for (;;)
350         {
351                 zabbix_log(LOG_LEVEL_WARNING, "executing housekeeper");
352                 now = time(NULL);
353
354                 zbx_setproctitle("%s [connecting to the database]", get_process_type_string(process_type));
355
356                 DBconnect(ZBX_DB_CONNECT_NORMAL);
357
358                 zbx_setproctitle("%s [removing old history and trends]", get_process_type_string(process_type));
359                 d_history_and_trends = housekeeping_history_and_trends(now);
360
361                 zbx_setproctitle("%s [removing deleted items data]", get_process_type_string(process_type));
362                 d_cleanup = housekeeping_cleanup(now);
363
364                 zbx_setproctitle("%s [removing old events]", get_process_type_string(process_type));
365                 d_events = housekeeping_events(now);
366
367                 zbx_setproctitle("%s [removing old alerts]", get_process_type_string(process_type));
368                 d_alerts = housekeeping_alerts(now);
369
370                 zbx_setproctitle("%s [removing old sessions]", get_process_type_string(process_type));
371                 d_sessions = housekeeping_sessions(now);
372
373                 zabbix_log(LOG_LEVEL_WARNING, "housekeeper deleted: %d records from history and trends,"
374                                 " %d records of deleted items, %d events, %d alerts, %d sessions",
375                                 d_history_and_trends, d_cleanup, d_events, d_alerts, d_sessions);
376
377                 DBclose();
378
379                 zbx_sleep_loop(CONFIG_HOUSEKEEPING_FREQUENCY * SEC_PER_HOUR);
380         }
381 }