summaryrefslogtreecommitdiffstats
path: root/src/zabbix_server/escalator
diff options
context:
space:
mode:
authorsasha <sasha@97f52cf1-0a1b-0410-bd0e-c28be96e8082>2008-05-27 08:24:17 +0000
committersasha <sasha@97f52cf1-0a1b-0410-bd0e-c28be96e8082>2008-05-27 08:24:17 +0000
commitc0bfb062b8ac422278fbd5b299ecbef51203011b (patch)
tree0d21b48a18b42a9fafeb19236cff97f50436bc3a /src/zabbix_server/escalator
parent1528814bf6b442cc01211b9f0b3f2adaadf970f4 (diff)
downloadzabbix-c0bfb062b8ac422278fbd5b299ecbef51203011b.tar.gz
zabbix-c0bfb062b8ac422278fbd5b299ecbef51203011b.tar.xz
zabbix-c0bfb062b8ac422278fbd5b299ecbef51203011b.zip
- [DEV-173] added support of notification escalations on server side
git-svn-id: svn://svn.zabbix.com/trunk@5725 97f52cf1-0a1b-0410-bd0e-c28be96e8082
Diffstat (limited to 'src/zabbix_server/escalator')
-rw-r--r--src/zabbix_server/escalator/Makefile.am5
-rw-r--r--src/zabbix_server/escalator/escalator.c679
-rw-r--r--src/zabbix_server/escalator/escalator.h27
3 files changed, 711 insertions, 0 deletions
diff --git a/src/zabbix_server/escalator/Makefile.am b/src/zabbix_server/escalator/Makefile.am
new file mode 100644
index 00000000..27204d6b
--- /dev/null
+++ b/src/zabbix_server/escalator/Makefile.am
@@ -0,0 +1,5 @@
+## Process this file with automake to produce Makefile.in
+
+noinst_LIBRARIES = libzbxescalator.a
+
+libzbxescalator_a_SOURCES = escalator.c escalator.h
diff --git a/src/zabbix_server/escalator/escalator.c b/src/zabbix_server/escalator/escalator.c
new file mode 100644
index 00000000..81b730d9
--- /dev/null
+++ b/src/zabbix_server/escalator/escalator.c
@@ -0,0 +1,679 @@
+/*
+** ZABBIX
+** Copyright (C) 2000-2005 SIA Zabbix
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**/
+
+#include "common.h"
+#include "db.h"
+#include "log.h"
+#include "zlog.h"
+#include "daemon.h"
+#include "zbxserver.h"
+
+#include "escalator.h"
+#include "../operations.h"
+#include "../events.h"
+#include "../actions.h"
+
+#define CONFIG_ESCALATOR_FREQUENCY 5
+
+#define ZBX_USER_MSG struct zxb_user_msg_t
+ZBX_USER_MSG
+{
+ zbx_uint64_t userid;
+ char *subject;
+ char *message;
+ void *next;
+};
+
+static void add_user_msg(DB_OPERATION *operation, ZBX_USER_MSG **user_msg, char *subject, char *message)
+{
+ DB_RESULT result;
+ DB_ROW row;
+ ZBX_USER_MSG *p;
+ zbx_uint64_t userid;
+
+ switch (operation->object) {
+ case OPERATION_OBJECT_USER:
+ case OPERATION_OBJECT_GROUP:
+ /* user group disabled ? */
+ result = DBselect("select ug.userid from users_groups ug,usrgrp g"
+ " WHERE ug.%s=" ZBX_FS_UI64 " AND g.usrgrpid=ug.usrgrpid AND g.users_status=%d",
+ operation->object == OPERATION_OBJECT_USER ? "userid" : "usrgrpid",
+ operation->objectid,
+ GROUP_STATUS_ACTIVE);
+
+ while (NULL != (row = DBfetch(result))) {
+ userid = zbx_atoui64(row[0]);
+
+ p = *user_msg;
+ while (NULL != p) {
+ if (p->userid == userid && 0 == strcmp(p->subject, subject)
+ && 0 == strcmp(p->message, message))
+ break;
+
+ p = p->next;
+ }
+
+ if (NULL == p) {
+ p = zbx_malloc(p, sizeof(ZBX_USER_MSG));
+
+ p->userid = userid;
+ p->subject = strdup(subject);
+ p->message = strdup(message);
+ p->next = *user_msg;
+
+ *user_msg = p;
+
+ }
+ }
+
+ DBfree_result(result);
+ break;
+ default:
+ zabbix_log(LOG_LEVEL_WARNING, "Unknown object type [%d] for operationid [" ZBX_FS_UI64 "]",
+ operation->object,
+ operation->operationid);
+ zabbix_syslog("Unknown object type [%d] for operationid [" ZBX_FS_UI64 "]",
+ operation->object,
+ operation->operationid);
+ break;
+ }
+}
+
+static void add_command_alert(DB_ESCALATION *escalation, DB_EVENT *event, DB_ACTION *action, char *command)
+{
+ zbx_uint64_t alertid;
+ int now;
+ char *command_esc = NULL;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In add_command_alert()");
+/* zabbix_log(LOG_LEVEL_DEBUG,"----- COMMAND\n\tcommand: %s", command);*/
+
+ alertid = DBget_maxid("alerts", "alertid");
+ now = time(NULL);
+ command_esc = DBdyn_escape_string(command);
+
+ DBexecute("insert into alerts (alertid,actionid,eventid,clock,message,status,alerttype,esc_step)"
+ " values (" ZBX_FS_UI64 "," ZBX_FS_UI64 "," ZBX_FS_UI64 ",%d,'%s',%d,%d,%d)",
+ alertid,
+ action->actionid,
+ event->eventid,
+ now,
+ command_esc,
+ ALERT_STATUS_NOT_SENT,
+ ALERT_TYPE_COMMAND,
+ escalation->esc_step);
+
+ op_run_commands(command);
+
+ zbx_free(command_esc);
+}
+
+static void add_message_alert(DB_ESCALATION *escalation, DB_EVENT *event, DB_ACTION *action, zbx_uint64_t userid, char *subject, char *message)
+{
+ DB_RESULT result;
+ DB_ROW row;
+ zbx_uint64_t alertid, mediatypeid;
+ int now, severity, medias = 0;
+ char *sendto_esc = NULL;
+ char *subject_esc = NULL;
+ char *message_esc = NULL;
+ char *error_esc = NULL;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In add_message_alert()");
+/* zabbix_log(LOG_LEVEL_DEBUG,"MESSAGE\n\tuserid : " ZBX_FS_UI64 "\n\tsubject: %s\n\tmessage: %s", userid, subject, message);*/
+
+ now = time(NULL);
+ subject_esc = DBdyn_escape_string(subject);
+ message_esc = DBdyn_escape_string(message);
+
+ result = DBselect("select mediatypeid,sendto,severity,period from media"
+ " where active=%d and userid=" ZBX_FS_UI64,
+ MEDIA_STATUS_ACTIVE,
+ userid);
+
+ while (NULL != (row = DBfetch(result))) {
+ medias = 1;
+
+ mediatypeid = zbx_atoui64(row[0]);
+ severity = atoi(row[2]);
+
+ zabbix_log( LOG_LEVEL_DEBUG, "Trigger severity [%d] Media severity [%d] Period [%s]",
+ event->trigger_priority,
+ severity,
+ row[3]);
+
+ if (((1 << event->trigger_priority) & severity) == 0) {
+ zabbix_log( LOG_LEVEL_DEBUG, "Won't send message (severity)");
+ continue;
+ }
+
+ if (check_time_period(row[3], (time_t)NULL) == 0) {
+ zabbix_log( LOG_LEVEL_DEBUG, "Won't send message (period)");
+ continue;
+ }
+
+ alertid = DBget_maxid("alerts", "alertid");
+ sendto_esc = DBdyn_escape_string(row[1]);
+
+ DBexecute("insert into alerts (alertid,actionid,eventid,userid,clock"
+ ",mediatypeid,sendto,subject,message,status,alerttype,esc_step)"
+ " values (" ZBX_FS_UI64 "," ZBX_FS_UI64 "," ZBX_FS_UI64 "," ZBX_FS_UI64 ",%d"
+ "," ZBX_FS_UI64 ",'%s','%s','%s',%d,%d,%d)",
+ alertid,
+ action->actionid,
+ event->eventid,
+ userid,
+ now,
+ mediatypeid,
+ sendto_esc,
+ subject_esc,
+ message_esc,
+ ALERT_STATUS_NOT_SENT,
+ ALERT_TYPE_MESSAGE,
+ escalation->esc_step);
+
+ zbx_free(sendto_esc);
+ }
+
+ DBfree_result(result);
+
+ if (0 == medias) {
+ alertid = DBget_maxid("alerts", "alertid");
+ error_esc = DBdyn_escape_string("No media defined");
+
+ DBexecute("insert into alerts (alertid,actionid,eventid,userid,clock"
+ ",subject,message,status,alerttype,error,esc_step)"
+ " values (" ZBX_FS_UI64 "," ZBX_FS_UI64 "," ZBX_FS_UI64 "," ZBX_FS_UI64 ",%d"
+ ",'%s','%s',%d,%d,'%s',%d)",
+ alertid,
+ action->actionid,
+ event->eventid,
+ userid,
+ now,
+ subject_esc,
+ message_esc,
+ ALERT_STATUS_FAILED,
+ ALERT_TYPE_MESSAGE,
+ error_esc,
+ escalation->esc_step);
+
+ zbx_free(error_esc);
+ }
+
+ zbx_free(subject_esc);
+ zbx_free(message_esc);
+}
+
+/******************************************************************************
+ * *
+ * Function: check_operation_conditions *
+ * *
+ * Purpose: *
+ * *
+ * Parameters: event - event to check *
+ * actionid - action ID for matching *
+ * *
+ * Return value: SUCCEED - matches, FAIL - otherwise *
+ * *
+ * Author: Alexei Vladishev *
+ * *
+ * Comments: *
+ * *
+ ******************************************************************************/
+static int check_operation_conditions(DB_EVENT *event, DB_OPERATION *operation)
+{
+ DB_RESULT result;
+ DB_ROW row;
+ DB_CONDITION condition;
+
+ /* SUCCEED required for ACTION_EVAL_TYPE_AND_OR */
+ int ret = SUCCEED;
+ int old_type = -1;
+ int cond;
+ int num = 0;
+ int exit = 0;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In check_opeartion_conditions (operationid:" ZBX_FS_UI64 ")",
+ operation->operationid);
+
+ result = DBselect("select conditiontype,operator,value from opconditions where operationid=" ZBX_FS_UI64 " order by conditiontype",
+ operation->operationid);
+
+ while (NULL != (row = DBfetch(result)) && (0 == exit)) {
+ num++;
+
+ memset(&condition, 0, sizeof(condition));
+ condition.conditiontype = atoi(row[0]);
+ condition.operator = atoi(row[1]);
+ condition.value = row[2];
+
+ switch (operation->evaltype) {
+ case ACTION_EVAL_TYPE_AND_OR:
+ if (old_type == condition.conditiontype) { /* OR conditions */
+ if (SUCCEED == check_action_condition(event, &condition))
+ ret = SUCCEED;
+ } else { /* AND conditions */
+ /* Break if PREVIOUS AND condition is FALSE */
+ if (ret == FAIL)
+ exit = 1;
+ else if (FAIL == check_action_condition(event, &condition))
+ ret = FAIL;
+ }
+
+ old_type = condition.conditiontype;
+ break;
+ case ACTION_EVAL_TYPE_AND:
+ cond = check_action_condition(event, &condition);
+ /* Break if any of AND conditions is FALSE */
+ if(cond == FAIL) {
+ ret = FAIL;
+ exit = 1;
+ } else
+ ret = SUCCEED;
+ break;
+ case ACTION_EVAL_TYPE_OR:
+ cond = check_action_condition(event, &condition);
+ /* Break if any of OR conditions is TRUE */
+ if (cond == SUCCEED) {
+ ret = SUCCEED;
+ exit = 1;
+ } else
+ ret = FAIL;
+ break;
+ default:
+ ret = FAIL;
+ exit = 1;
+ break;
+
+ }
+
+ }
+ DBfree_result(result);
+
+ zabbix_log(LOG_LEVEL_DEBUG, "End check_opeartion_conditions():%s",
+ FAIL == ret ? "FALSE" : "TRUE");
+
+ return ret;
+}
+
+static void execute_operations(DB_ESCALATION *escalation, DB_EVENT *event, DB_ACTION *action)
+{
+ DB_RESULT result;
+ DB_ROW row;
+ DB_OPERATION operation;
+ int esc_period = 0, operations = 0;
+ ZBX_USER_MSG *user_msg = NULL, *p;
+ char *shortdata, *longdata;
+
+ if (0 == action->esc_period)
+ result = DBselect("select operationid,operationtype,object,objectid,default_msg,shortdata,longdata"
+ ",esc_period,evaltype from operations where actionid=" ZBX_FS_UI64,
+ action->actionid);
+ else {
+ escalation->esc_step++;
+
+ result = DBselect("select operationid,operationtype,object,objectid,default_msg,shortdata,longdata"
+ ",esc_period,evaltype from operations where actionid=" ZBX_FS_UI64
+ " and esc_step_from<=%d and (esc_step_to=0 or esc_step_to>=%d)",
+ action->actionid,
+ escalation->esc_step,
+ escalation->esc_step);
+ }
+
+ while (NULL != (row = DBfetch(result))) {
+ memset(&operation, 0, sizeof(operation));
+ operation.operationid = zbx_atoui64(row[0]);
+ operation.actionid = action->actionid;
+ operation.operationtype = atoi(row[1]);
+ operation.object = atoi(row[2]);
+ operation.objectid = zbx_atoui64(row[3]);
+ operation.default_msg = atoi(row[4]);
+ operation.shortdata = strdup(row[5]);
+ operation.longdata = strdup(row[6]);
+ operation.esc_period = atoi(row[7]);
+ operation.evaltype = atoi(row[8]);
+
+ if (SUCCEED == check_operation_conditions(event, &operation)) {
+ zabbix_log(LOG_LEVEL_DEBUG, "Conditions match our event. Execute operation.");
+
+ substitute_macros(event, action, &operation.shortdata);
+ substitute_macros(event, action, &operation.longdata);
+
+ if (0 == esc_period || esc_period > operation.esc_period)
+ esc_period = operation.esc_period;
+
+ switch (operation.operationtype) {
+ case OPERATION_TYPE_MESSAGE:
+ if (0 == operation.default_msg) {
+ shortdata = operation.shortdata;
+ longdata = operation.longdata;
+ } else {
+ shortdata = action->shortdata;
+ longdata = action->longdata;
+ }
+
+ add_user_msg(&operation, &user_msg, shortdata, longdata);
+ break;
+ case OPERATION_TYPE_COMMAND:
+ add_command_alert(escalation, event, action, operation.longdata);
+ break;
+ default:
+ break;
+ }
+ } else
+ zabbix_log(LOG_LEVEL_DEBUG, "Conditions do not match our event. Do not execute operation.");
+
+ zbx_free(operation.shortdata);
+ zbx_free(operation.longdata);
+
+ operations = 1;
+ }
+
+ DBfree_result(result);
+
+ while (NULL != user_msg) {
+ p = user_msg;
+ user_msg = user_msg->next;
+
+ add_message_alert(escalation, event, action, p->userid, p->subject, p->message);
+
+ zbx_free(p->subject);
+ zbx_free(p->message);
+ zbx_free(p);
+ }
+
+ if (0 == action->esc_period)
+ escalation->status = ESCALATION_STATUS_COMPLETED;
+ else {
+ if (0 == operations) {
+ result = DBselect("select operationid from operations where actionid=" ZBX_FS_UI64 " and esc_step_from>%d",
+ action->actionid,
+ escalation->esc_step);
+
+ if (NULL != (row = DBfetch(result)) && SUCCEED != DBis_null(row[0]))
+ operations = 1;
+
+ DBfree_result(result);
+ }
+
+ if (1 == operations) {
+ esc_period = (0 != esc_period) ? esc_period : action->esc_period;
+ escalation->nextcheck = time(NULL) + esc_period;
+ } else
+ escalation->status = ESCALATION_STATUS_COMPLETED;
+ }
+}
+
+static void process_recovery_msg(DB_ESCALATION *escalation, DB_EVENT *event, DB_ACTION *action)
+{
+ DB_RESULT result;
+ DB_ROW row;
+ zbx_uint64_t userid;
+
+ if (1 == action->recovery_msg) {
+ result = DBselect("select distinct userid from alerts where actionid=" ZBX_FS_UI64 " and eventid=" ZBX_FS_UI64,
+ action->actionid,
+ event->eventid);
+
+ while (NULL != (row = DBfetch(result))) {
+ userid = zbx_atoui64(row[0]);
+
+ add_message_alert(escalation, event, action, userid, action->shortdata, action->longdata);
+ }
+
+ DBfree_result(result);
+ } else {
+ zabbix_log(LOG_LEVEL_DEBUG, "Escalation stopped: recovery message not defined",
+ escalation->actionid);
+ DBremove_escalation(escalation->escalationid);
+ }
+
+ escalation->status = ESCALATION_STATUS_COMPLETED;
+}
+
+static void execute_escalation(DB_ESCALATION *escalation, DB_EVENT *event)
+{
+ DB_RESULT result;
+ DB_ROW row;
+ DB_ACTION action;
+
+ switch (escalation->status) {
+ case ESCALATION_STATUS_ACTIVE:
+ result = DBselect("select actionid,eventsource,esc_period,shortdata,longdata"
+ " from actions where actionid=" ZBX_FS_UI64,
+ escalation->actionid);
+ break;
+ case ESCALATION_STATUS_RECOVERY:
+ result = DBselect("select actionid,eventsource,esc_period,r_shortdata,r_longdata,recovery_msg"
+ " from actions where actionid=" ZBX_FS_UI64,
+ escalation->actionid);
+ break;
+ default:
+ /* Never reached */
+ return;
+ }
+
+ if (NULL != (row = DBfetch(result))) {
+ memset(&action, 0, sizeof(action));
+ action.actionid = zbx_atoui64(row[0]);
+ action.eventsource = atoi(row[1]);
+ action.esc_period = atoi(row[2]);
+ action.shortdata = strdup(row[3]);
+ action.longdata = strdup(row[4]);
+ action.recovery_msg = atoi(row[5]);
+
+ substitute_macros(event, &action, &action.shortdata);
+ substitute_macros(event, &action, &action.longdata);
+
+ switch (escalation->status) {
+ case ESCALATION_STATUS_ACTIVE:
+ execute_operations(escalation, event, &action);
+ break;
+ case ESCALATION_STATUS_RECOVERY:
+ process_recovery_msg(escalation, event, &action);
+ break;
+ default:
+ break;
+ }
+
+ zbx_free(action.shortdata);
+ zbx_free(action.longdata);
+ } else {
+ zabbix_log(LOG_LEVEL_DEBUG, "Escalation canceled: action [" ZBX_FS_UI64 "] not found",
+ escalation->actionid);
+ DBremove_escalation(escalation->escalationid);
+ }
+
+ DBfree_result(result);
+}
+
+static void process_escalations(int now)
+{
+ DB_RESULT result;
+ DB_ROW row;
+ DB_ESCALATION escalation;
+ DB_EVENT event;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In process_escalations()");
+
+ result = DBselect("select e.escalationid,e.actionid,e.esc_step,e.status,ev.eventid"
+ ",ev.source,ev.object,ev.objectid,ev.clock,ev.value,ev.acknowledged"
+ " from escalations e,events ev where e.eventid=ev.eventid"
+ " and e.status in (%d,%d) and e.nextcheck<=%d" DB_NODE,
+ ESCALATION_STATUS_ACTIVE,
+ ESCALATION_STATUS_RECOVERY,
+ now,
+ DBnode_local("escalationid"));
+
+ while (NULL != (row = DBfetch(result))) {
+ memset(&escalation, 0, sizeof(escalation));
+ escalation.escalationid = zbx_atoui64(row[0]);
+ escalation.actionid = zbx_atoui64(row[1]);
+ escalation.esc_step = atoi(row[2]);
+ escalation.status = atoi(row[3]);
+ escalation.nextcheck = 0;
+
+ memset(&event, 0, sizeof(event));
+ event.eventid = zbx_atoui64(row[4]);
+ event.source = atoi(row[5]);
+ event.object = atoi(row[6]);
+ event.objectid = zbx_atoui64(row[7]);
+ event.clock = atoi(row[8]);
+ event.value = atoi(row[9]);
+ event.acknowledged = atoi(row[10]);
+
+ add_trigger_info(&event);
+
+ DBbegin();
+
+ execute_escalation(&escalation, &event);
+
+ if (escalation.status == ESCALATION_STATUS_COMPLETED)
+ DBremove_escalation(escalation.escalationid);
+ else
+ DBexecute("update escalations set esc_step=%d,nextcheck=%d where escalationid=" ZBX_FS_UI64,
+ escalation.esc_step,
+ escalation.nextcheck,
+ escalation.escalationid);
+
+ DBcommit();
+ }
+
+ DBfree_result(result);
+}
+
+/******************************************************************************
+ * *
+ * Function: get_minnextcheck *
+ * *
+ * Purpose: calculate when we have to process earliest escalations *
+ * *
+ * Parameters: now - current timestamp *
+ * *
+ * Return value: timestamp of earliest check or -1 if not found *
+ * *
+ * Author: Aleksander Vladishev *
+ * *
+ * Comments: *
+ * *
+ ******************************************************************************/
+static int get_minnextcheck()
+{
+ DB_RESULT result;
+ DB_ROW row;
+ int res;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In get_minnextcheck()");
+
+ result = DBselect("select count(*),min(nextcheck) from escalations where status in (%d,%d)" DB_NODE,
+ ESCALATION_STATUS_ACTIVE,
+ ESCALATION_STATUS_RECOVERY,
+ DBnode_local("escalationid"));
+
+ if (NULL == (row = DBfetch(result)) || DBis_null(row[0]) == SUCCEED || DBis_null(row[1]) == SUCCEED)
+ {
+ zabbix_log(LOG_LEVEL_DEBUG, "No items to update for minnextcheck.");
+ res = FAIL;
+ }
+ else
+ {
+ if (atoi(row[0]) == 0)
+ {
+ res = FAIL;
+ }
+ else
+ {
+ res = atoi(row[1]);
+ }
+ }
+ DBfree_result(result);
+
+ return res;
+}
+
+/******************************************************************************
+ * *
+ * Function: main_escalator_loop *
+ * *
+ * Purpose: periodically check table escalations and generate alerts *
+ * *
+ * Parameters: *
+ * *
+ * Return value: *
+ * *
+ * Author: Aleksander Vladishev *
+ * *
+ * Comments: never returns *
+ * *
+ ******************************************************************************/
+int main_escalator_loop()
+{
+ int now, nextcheck, sleeptime;
+ double sec;
+ struct sigaction phan;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In main_escalator_loop()");
+
+ phan.sa_handler = child_signal_handler;
+ sigemptyset(&phan.sa_mask);
+ phan.sa_flags = 0;
+ sigaction(SIGALRM, &phan, NULL);
+
+ zbx_setproctitle("escalator [connecting to the database]");
+
+ DBconnect(ZBX_DB_CONNECT_NORMAL);
+
+ for (;;) {
+ now = time(NULL);
+ sec = zbx_time();
+
+ zbx_setproctitle("escalator [processing escalations]");
+
+ process_escalations(now);
+
+ sec = zbx_time() - sec;
+
+ nextcheck = get_minnextcheck();
+
+ if (FAIL == nextcheck)
+ sleeptime = CONFIG_ESCALATOR_FREQUENCY;
+ else {
+ sleeptime = nextcheck - time(NULL);
+ if (sleeptime < 0)
+ sleeptime = 0;
+ else if (sleeptime > CONFIG_ESCALATOR_FREQUENCY)
+ sleeptime = CONFIG_ESCALATOR_FREQUENCY;
+ }
+
+ zabbix_log(LOG_LEVEL_DEBUG, "Escalator spent " ZBX_FS_DBL " seconds while processing escalation items."
+ " Nextcheck after %d sec.",
+ sec,
+ sleeptime);
+
+ if (sleeptime > 0) {
+ zbx_setproctitle("escalator [sleeping for %d seconds]",
+ sleeptime);
+
+ sleep(sleeptime);
+ }
+ }
+
+ /* Never reached */
+ DBclose();
+}
diff --git a/src/zabbix_server/escalator/escalator.h b/src/zabbix_server/escalator/escalator.h
new file mode 100644
index 00000000..aeb70d4c
--- /dev/null
+++ b/src/zabbix_server/escalator/escalator.h
@@ -0,0 +1,27 @@
+/*
+** ZABBIX
+** Copyright (C) 2000-2005 SIA Zabbix
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**/
+
+#ifndef ZABBIX_ESCALATOR_H
+#define ZABBIX_ESCALATOR_H
+
+#include "db.h"
+
+int main_escalator_loop();
+
+#endif