Exemplo n.º 1
0
/******************************************************************************
 *                                                                            *
 * Function: process_pinger_hosts                                             *
 *                                                                            *
 * Purpose:                                                                   *
 *                                                                            *
 * Parameters:                                                                *
 *                                                                            *
 * Return value:                                                              *
 *                                                                            *
 * Author: Alexander Vladishev                                                *
 *                                                                            *
 * Comments:                                                                  *
 *                                                                            *
 ******************************************************************************/
static void	process_pinger_hosts(icmpitem_t *items, int items_count)
{
	const char		*__function_name = "process_pinger_hosts";
	int			i, first_index = 0, ping_result;
	char			error[ITEM_ERROR_LEN_MAX];
	static ZBX_FPING_HOST	*hosts = NULL;
	static int		hosts_alloc = 4;
	int			hosts_count = 0;
	zbx_timespec_t		ts;

	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);

	if (NULL == hosts)
		hosts = zbx_malloc(hosts, sizeof(ZBX_FPING_HOST) * hosts_alloc);

	for (i = 0; i < items_count; i++)
	{
		add_pinger_host(&hosts, &hosts_alloc, &hosts_count, items[i].addr);

		if (i == items_count - 1 || items[i].count != items[i + 1].count || items[i].interval != items[i + 1].interval ||
				items[i].size != items[i + 1].size || items[i].timeout != items[i + 1].timeout)
		{
			zbx_setproctitle("%s #%d [pinging hosts]", get_process_type_string(process_type), process_num);

			zbx_timespec(&ts);

			ping_result = do_ping(hosts, hosts_count,
						items[i].count, items[i].interval, items[i].size, items[i].timeout,
						error, sizeof(error));

			process_values(items, first_index, i + 1, hosts, hosts_count, &ts, ping_result, error);

			hosts_count = 0;
			first_index = i + 1;
		}
	}

	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
}
Exemplo n.º 2
0
void	main_housekeeper_loop()
{
	int	now, d_history_and_trends, d_cleanup, d_events, d_alerts, d_sessions;

	for (;;)
	{
		zabbix_log(LOG_LEVEL_WARNING, "executing housekeeper");
		now = time(NULL);

		zbx_setproctitle("%s [connecting to the database]", get_process_type_string(process_type));

		DBconnect(ZBX_DB_CONNECT_NORMAL);

		zbx_setproctitle("%s [removing old history and trends]", get_process_type_string(process_type));
		d_history_and_trends = housekeeping_history_and_trends(now);

		zbx_setproctitle("%s [removing deleted items data]", get_process_type_string(process_type));
		d_cleanup = housekeeping_cleanup();

		zbx_setproctitle("%s [removing old events]", get_process_type_string(process_type));
		d_events = housekeeping_events(now);

		zbx_setproctitle("%s [removing old alerts]", get_process_type_string(process_type));
		d_alerts = housekeeping_alerts(now);

		zbx_setproctitle("%s [removing old sessions]", get_process_type_string(process_type));
		d_sessions = housekeeping_sessions(now);

		zabbix_log(LOG_LEVEL_WARNING, "housekeeper deleted: %d records from history and trends,"
				" %d records of deleted items, %d events, %d alerts, %d sessions",
				d_history_and_trends, d_cleanup, d_events, d_alerts, d_sessions);

		DBclose();

		zbx_sleep_loop(CONFIG_HOUSEKEEPING_FREQUENCY * SEC_PER_HOUR);
	}
}
Exemplo n.º 3
0
/******************************************************************************
 *                                                                            *
 * Function: user1_signal_handler                                             *
 *                                                                            *
 * Purpose: handle user signal SIGUSR1                                        *
 *                                                                            *
 ******************************************************************************/
static void	user1_signal_handler(int sig, siginfo_t *siginfo, void *context)
{
#ifdef HAVE_SIGQUEUE
	int		flags, process_num, found = 0, i;
	union sigval	s;
	unsigned char	process_type;
#endif
	SIG_CHECK_PARAMS(sig, siginfo, context);

	zabbix_log(LOG_LEVEL_DEBUG, "Got signal [signal:%d(%s),sender_pid:%d,sender_uid:%d,value_int:%d(0x%08x)].",
			sig, get_signal_name(sig),
			SIG_CHECKED_FIELD(siginfo, si_pid),
			SIG_CHECKED_FIELD(siginfo, si_uid),
			SIG_CHECKED_FIELD(siginfo, si_value.ZBX_SIVAL_INT),
			SIG_CHECKED_FIELD(siginfo, si_value.ZBX_SIVAL_INT));
#ifdef HAVE_SIGQUEUE
	flags = SIG_CHECKED_FIELD(siginfo, si_value.ZBX_SIVAL_INT);

	if (!SIG_PARENT_PROCESS)
	{
		common_sigusr_handler(flags);
	}
	else if (NULL == threads)
	{
		zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal: shutdown in progress");
	}
	else if (ZBX_RTC_CONFIG_CACHE_RELOAD == ZBX_RTC_GET_MSG(flags))
	{
		extern unsigned char	daemon_type;

		if (0 != (daemon_type & ZBX_DAEMON_TYPE_PROXY_PASSIVE))
		{
			zabbix_log(LOG_LEVEL_WARNING, "forced reloading of the configuration cache"
					" cannot be performed for a passive proxy");
			return;
		}

		for (i = 0; i < threads_num; i++)
		{
			if (FAIL == get_process_info_by_thread(i + 1, &process_type, &process_num))
				continue;

			if (ZBX_PROCESS_TYPE_CONFSYNCER == process_type)
				break;
		}

		if (i != threads_num)
		{
			s.ZBX_SIVAL_INT = flags;

			if (-1 != sigqueue(threads[i], SIGUSR1, s))
				zabbix_log(LOG_LEVEL_DEBUG, "the signal was redirected to the configuration syncer");
			else
				zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal: %s", zbx_strerror(errno));
		}
		else
			zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal to configuration syncer: process not found");
	}
	else if (ZBX_RTC_LOG_LEVEL_INCREASE == ZBX_RTC_GET_MSG(flags) ||
			ZBX_RTC_LOG_LEVEL_DECREASE == ZBX_RTC_GET_MSG(flags))
	{
		s.ZBX_SIVAL_INT = flags;

		if ((ZBX_RTC_LOG_SCOPE_FLAG | ZBX_RTC_LOG_SCOPE_PID) == ZBX_RTC_GET_SCOPE(flags))
		{
			for (i = 0; i < threads_num; i++)
			{
				if (0 != ZBX_RTC_GET_DATA(flags) && threads[i] != ZBX_RTC_GET_DATA(flags))
					continue;

				found = 1;

				if (-1 != sigqueue(threads[i], SIGUSR1, s))
				{
					zabbix_log(LOG_LEVEL_DEBUG, "the signal was redirected to process pid:%d",
							threads[i]);
				}
				else
					zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal: %s", zbx_strerror(errno));
			}

			if (0 != ZBX_RTC_GET_DATA(flags) && 0 == found)
			{
				zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal: process pid:%d is not a Zabbix child"
						" process", ZBX_RTC_GET_DATA(flags));
			}
		}
		else
		{
			for (i = 0; i < threads_num; i++)
			{
				if (FAIL == get_process_info_by_thread(i + 1, &process_type, &process_num))
					break;

				if (ZBX_RTC_GET_SCOPE(flags) != process_type)
				{
					/* check if we have already checked processes of target type */
					if (1 == found)
						break;

					continue;
				}

				if (0 != ZBX_RTC_GET_DATA(flags) && ZBX_RTC_GET_DATA(flags) != process_num)
					continue;

				found = 1;

				if (-1 != sigqueue(threads[i], SIGUSR1, s))
				{
					zabbix_log(LOG_LEVEL_DEBUG, "the signal was redirected to \"%s\" process"
							" pid:%d", get_process_type_string(process_type), threads[i]);
				}
				else
					zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal: %s", zbx_strerror(errno));
			}

			if (0 == found)
			{
				if (0 == ZBX_RTC_GET_DATA(flags))
				{
					zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal:"
							" \"%s\" process does not exist",
							get_process_type_string(ZBX_RTC_GET_SCOPE(flags)));
				}
				else
				{
					zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal:"
							" \"%s #%d\" process does not exist",
							get_process_type_string(ZBX_RTC_GET_SCOPE(flags)),
							ZBX_RTC_GET_DATA(flags));
				}
			}
		}
	}
#endif
}
Exemplo n.º 4
0
/******************************************************************************
 *                                                                            *
 * Function: main_alerter_loop                                                *
 *                                                                            *
 * Purpose: periodically check table alerts and send notifications if needed  *
 *                                                                            *
 * Parameters:                                                                *
 *                                                                            *
 * Return value:                                                              *
 *                                                                            *
 * Author: Alexei Vladishev                                                   *
 *                                                                            *
 * Comments: never returns                                                    *
 *                                                                            *
 ******************************************************************************/
void	main_alerter_loop()
{
	char			error[MAX_STRING_LEN], *error_esc;
	int			res, now;
	DB_RESULT		result;
	DB_ROW			row;
	DB_ALERT		alert;
	DB_MEDIATYPE		mediatype;

	set_child_signal_handler();

	zbx_setproctitle("%s [connecting to the database]", get_process_type_string(process_type));

	DBconnect(ZBX_DB_CONNECT_NORMAL);

	for (;;)
	{
		zbx_setproctitle("%s [sending alerts]", get_process_type_string(process_type));

		now = time(NULL);

		result = DBselect("select a.alertid,a.mediatypeid,a.sendto,a.subject,a.message,a.status,mt.mediatypeid"
				",mt.type,mt.description,mt.smtp_server,mt.smtp_helo,mt.smtp_email,mt.exec_path"
				",mt.gsm_modem,mt.username,mt.passwd,a.retries from alerts a,media_type mt"
				" where a.status=%d and a.mediatypeid=mt.mediatypeid and a.alerttype=%d" DB_NODE
				" order by a.clock",
				ALERT_STATUS_NOT_SENT,
				ALERT_TYPE_MESSAGE,
				DBnode_local("mt.mediatypeid"));

		while (NULL != (row = DBfetch(result)))
		{
			ZBX_STR2UINT64(alert.alertid, row[0]);
			alert.mediatypeid	= atoi(row[1]);
			alert.sendto		= row[2];
			alert.subject		= row[3];
			alert.message		= row[4];
			alert.status		= atoi(row[5]);

			ZBX_STR2UINT64(mediatype.mediatypeid, row[6]);
			mediatype.type		= atoi(row[7]);
			mediatype.description	= row[8];
			mediatype.smtp_server	= row[9];
			mediatype.smtp_helo	= row[10];
			mediatype.smtp_email	= row[11];
			mediatype.exec_path	= row[12];
			mediatype.gsm_modem	= row[13];
			mediatype.username	= row[14];
			mediatype.passwd	= row[15];

			alert.retries		= atoi(row[16]);

			*error = '\0';
			res = execute_action(&alert, &mediatype, error, sizeof(error));

			if (res == SUCCEED)
			{
				zabbix_log(LOG_LEVEL_DEBUG, "Alert ID [" ZBX_FS_UI64 "] was sent successfully",
					alert.alertid);
				DBexecute("update alerts set status=%d,error='' where alertid=" ZBX_FS_UI64,
					ALERT_STATUS_SENT,
					alert.alertid);
			}
			else
			{
				zabbix_log(LOG_LEVEL_DEBUG, "Error sending alert ID [" ZBX_FS_UI64 "]",
					alert.alertid);
				zabbix_syslog("Error sending alert ID [" ZBX_FS_UI64 "]",
					alert.alertid);

				error_esc = DBdyn_escape_string_len(error, ALERT_ERROR_LEN);

				alert.retries++;
				if (alert.retries < ALERT_MAX_RETRIES)
				{
					DBexecute("update alerts set retries=%d,error='%s' where alertid=" ZBX_FS_UI64,
						alert.retries,
						error_esc,
						alert.alertid);
				}
				else
				{
					DBexecute("update alerts set status=%d,retries=%d,error='%s' where alertid=" ZBX_FS_UI64,
						ALERT_STATUS_FAILED,
						alert.retries,
						error_esc,
						alert.alertid);
				}

				zbx_free(error_esc);
			}

		}
		DBfree_result(result);

		zbx_sleep_loop(CONFIG_SENDER_FREQUENCY);
	}
}
Exemplo n.º 5
0
ZBX_THREAD_ENTRY(housekeeper_thread, args)
{
	int	records, start, sleeptime;
	double	sec, time_slept;
	char	sleeptext[25];

	process_type = ((zbx_thread_args_t *)args)->process_type;
	server_num = ((zbx_thread_args_t *)args)->server_num;
	process_num = ((zbx_thread_args_t *)args)->process_num;

	zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_daemon_type_string(daemon_type),
			server_num, get_process_type_string(process_type), process_num);

	if (0 == CONFIG_HOUSEKEEPING_FREQUENCY)
	{
		zbx_setproctitle("%s [waiting for user command]", get_process_type_string(process_type));
		zbx_snprintf(sleeptext, sizeof(sleeptext), "waiting for user command");
	}
	else
	{
		sleeptime = HOUSEKEEPER_STARTUP_DELAY * SEC_PER_MIN;
		zbx_setproctitle("%s [startup idle for %d minutes]", get_process_type_string(process_type),
				HOUSEKEEPER_STARTUP_DELAY);
		zbx_snprintf(sleeptext, sizeof(sleeptext), "idle for %d hour(s)", CONFIG_HOUSEKEEPING_FREQUENCY);
	}

	zbx_set_sigusr_handler(zbx_housekeeper_sigusr_handler);

	for (;;)
	{
		sec = zbx_time();

		if (0 == CONFIG_HOUSEKEEPING_FREQUENCY)
			zbx_sleep_forever();
		else
			zbx_sleep_loop(sleeptime);

		time_slept = zbx_time() - sec;

		hk_period = get_housekeeper_period(time_slept);

		start = time(NULL);

		zabbix_log(LOG_LEVEL_WARNING, "executing housekeeper");

		zbx_setproctitle("%s [connecting to the database]", get_process_type_string(process_type));

		DBconnect(ZBX_DB_CONNECT_NORMAL);

		zbx_setproctitle("%s [removing old history]", get_process_type_string(process_type));

		sec = zbx_time();
		records = housekeeping_history(start);
		sec = zbx_time() - sec;

		DBclose();

		zabbix_log(LOG_LEVEL_WARNING, "%s [deleted %d records in " ZBX_FS_DBL " sec, %s]",
				get_process_type_string(process_type), records, sec, sleeptext);

		zbx_setproctitle("%s [deleted %d records in " ZBX_FS_DBL " sec, %s]",
				get_process_type_string(process_type), records, sec, sleeptext);

		if (0 != CONFIG_HOUSEKEEPING_FREQUENCY)
			sleeptime = CONFIG_HOUSEKEEPING_FREQUENCY * SEC_PER_HOUR;
	}
}
Exemplo n.º 6
0
/******************************************************************************
 *                                                                            *
 * Function: main_dbsyncer_loop                                               *
 *                                                                            *
 * Purpose: periodically synchronises data in memory cache with database      *
 *                                                                            *
 * Author: Alexei Vladishev                                                   *
 *                                                                            *
 * Comments: never returns                                                    *
 *                                                                            *
 ******************************************************************************/
void	main_dbsyncer_loop()
{
	int	sleeptime, last_sleeptime = -1, num;
	double	sec;
	int	retry_up = 0, retry_dn = 0;

	zabbix_log(LOG_LEVEL_DEBUG, "In main_dbsyncer_loop() process_num:%d", process_num);

	zbx_setproctitle("%s [connecting to the database]", get_process_type_string(process_type));

	DBconnect(ZBX_DB_CONNECT_NORMAL);

	for (;;)
	{
		zbx_setproctitle("%s [syncing history]", get_process_type_string(process_type));

		zabbix_log(LOG_LEVEL_DEBUG, "Syncing ...");

		sec = zbx_time();
		num = DCsync_history(ZBX_SYNC_PARTIAL);
		sec = zbx_time() - sec;

		zabbix_log(LOG_LEVEL_DEBUG, "%s #%d spent " ZBX_FS_DBL " seconds while processing %d items",
				get_process_type_string(process_type), process_num, sec, num);

		if (-1 == last_sleeptime)
		{
			sleeptime = num ? ZBX_SYNC_MAX / num : CONFIG_HISTSYNCER_FREQUENCY;
		}
		else
		{
			sleeptime = last_sleeptime;
			if (ZBX_SYNC_MAX < num)
			{
				retry_up = 0;
				retry_dn++;
			}
			else if (ZBX_SYNC_MAX / 2 > num)
			{
				retry_up++;
				retry_dn = 0;
			}
			else
				retry_up = retry_dn = 0;

			if (2 < retry_dn)
			{
				sleeptime--;
				retry_dn = 0;
			}

			if (2 < retry_up)
			{
				sleeptime++;
				retry_up = 0;
			}
		}

		if (0 > sleeptime)
			sleeptime = 0;
		else if (CONFIG_HISTSYNCER_FREQUENCY < sleeptime)
			sleeptime = CONFIG_HISTSYNCER_FREQUENCY;

		last_sleeptime = sleeptime;

		zbx_sleep_loop(sleeptime);
	}
}
Exemplo n.º 7
0
/******************************************************************************
 *                                                                            *
 * Function: main_timer_loop                                                  *
 *                                                                            *
 * Purpose: periodically updates time-related triggers                        *
 *                                                                            *
 * Parameters:                                                                *
 *                                                                            *
 * Return value:                                                              *
 *                                                                            *
 * Author: Alexei Vladishev                                                   *
 *                                                                            *
 * Comments: does update once per 30 seconds (hardcoded)                      *
 *                                                                            *
 ******************************************************************************/
void	main_timer_loop(void)
{
	int	now, nextcheck, sleeptime = -1,
		triggers_count = 0, events_count = 0, hm_count = 0,
		old_triggers_count = 0, old_events_count = 0, old_hm_count = 0,
		tr_count, ev_count;

	double	sec = 0.0, sec_maint = 0.0,
		total_sec = 0.0, total_sec_maint = 0.0,
		old_total_sec = 0.0, old_total_sec_maint = 0.0;

	time_t	last_stat_time;

#define STAT_INTERVAL	5	/* if a process is busy and does not sleep then update status not faster than */
				/* once in STAT_INTERVAL seconds */

	zbx_setproctitle("%s #%d [connecting to the database]", get_process_type_string(process_type), process_num);
	last_stat_time = time(NULL);

	DBconnect(ZBX_DB_CONNECT_NORMAL);

	for (;;)
	{
		now = time(NULL);
		nextcheck = now + TIMER_DELAY - (now % TIMER_DELAY);
		sleeptime = nextcheck - now;

		if (0 != sleeptime || STAT_INTERVAL <= time(NULL) - last_stat_time)
		{
			if (0 == sleeptime)
			{
				if (1 != process_num)
				{
					zbx_setproctitle("%s #%d [processed %d triggers, %d events in " ZBX_FS_DBL
							" sec, processing time functions]",
							get_process_type_string(process_type), process_num,
							triggers_count, events_count, total_sec);
				}
				else
				{
					zbx_setproctitle("%s #1 [processed %d triggers, %d events in " ZBX_FS_DBL
							" sec, %d maint.periods in " ZBX_FS_DBL " sec, processing time "
							"functions]",
							get_process_type_string(process_type),
							triggers_count, events_count, total_sec, hm_count,
							total_sec_maint);
				}
			}
			else
			{
				if (1 != process_num)
				{
					zbx_setproctitle("%s #%d [processed %d triggers, %d events in " ZBX_FS_DBL
							" sec, idle %d sec]",
							get_process_type_string(process_type), process_num,
							triggers_count, events_count, total_sec, sleeptime);
				}
				else
				{
					zbx_setproctitle("%s #1 [processed %d triggers, %d events in " ZBX_FS_DBL
							" sec, %d maint.periods in " ZBX_FS_DBL " sec, idle %d sec]",
							get_process_type_string(process_type),
							triggers_count, events_count, total_sec, hm_count,
							total_sec_maint, sleeptime);
					old_hm_count = hm_count;
					old_total_sec_maint = total_sec_maint;
				}
				old_triggers_count = triggers_count;
				old_events_count = events_count;
				old_total_sec = total_sec;
			}

			triggers_count = 0;
			events_count = 0;
			hm_count = 0;
			total_sec = 0.0;
			total_sec_maint = 0.0;
			last_stat_time = time(NULL);
		}

		zbx_sleep_loop(sleeptime);

		if (0 != sleeptime)
		{
			if (1 != process_num)
			{
				zbx_setproctitle("%s #%d [processed %d triggers, %d events in " ZBX_FS_DBL
						" sec, processing time functions]",
						get_process_type_string(process_type), process_num,
						old_triggers_count, old_events_count, old_total_sec);
			}
			else
			{
				zbx_setproctitle("%s #1 [processed %d triggers, %d events in " ZBX_FS_DBL
						" sec, %d maint.periods in " ZBX_FS_DBL " sec, processing time "
						"functions]",
						get_process_type_string(process_type),
						old_triggers_count, old_events_count, old_total_sec, old_hm_count,
						old_total_sec_maint);
			}
		}

		sec = zbx_time();
		tr_count = 0;
		ev_count = 0;
		process_time_functions(&tr_count, &ev_count);
		triggers_count += tr_count;
		events_count += ev_count;
		total_sec += zbx_time() - sec;

		/* only the "timer #1" process evaluates the maintenance periods */
		if (1 != process_num)
			continue;

		/* we process maintenance at every 00 sec */
		/* process time functions can take long time */
		if (0 == nextcheck % SEC_PER_MIN || nextcheck + SEC_PER_MIN - (nextcheck % SEC_PER_MIN) <= time(NULL))
		{
			zbx_setproctitle("%s #1 [processed %d triggers, %d events in " ZBX_FS_DBL
					" sec, %d maint.periods in " ZBX_FS_DBL " sec, processing maintenance periods]",
					get_process_type_string(process_type),
					triggers_count, events_count, total_sec, old_hm_count,
					old_total_sec_maint);

			sec_maint = zbx_time();
			hm_count += process_maintenance();
			total_sec_maint += zbx_time() - sec_maint;
		}
	}

#undef STAT_INTERVAL
}
Exemplo n.º 8
0
/******************************************************************************
 *                                                                            *
 * Function: main_alerter_loop                                                *
 *                                                                            *
 * Purpose: periodically check table alerts and send notifications if needed  *
 *                                                                            *
 * Author: Alexei Vladishev                                                   *
 *                                                                            *
 ******************************************************************************/
ZBX_THREAD_ENTRY(alerter_thread, args)
{
	char		error[MAX_STRING_LEN], *error_esc;
	int		res, alerts_success, alerts_fail;
	double		sec;
	DB_RESULT	result;
	DB_ROW		row;
	DB_ALERT	alert;
	DB_MEDIATYPE	mediatype;

	process_type = ((zbx_thread_args_t *)args)->process_type;
	server_num = ((zbx_thread_args_t *)args)->server_num;
	process_num = ((zbx_thread_args_t *)args)->process_num;

	zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_daemon_type_string(daemon_type),
			server_num, get_process_type_string(process_type), process_num);

	zbx_setproctitle("%s [connecting to the database]", get_process_type_string(process_type));

	DBconnect(ZBX_DB_CONNECT_NORMAL);

	for (;;)
	{
		zbx_setproctitle("%s [sending alerts]", get_process_type_string(process_type));

		sec = zbx_time();

		alerts_success = alerts_fail = 0;

		result = DBselect(
				"select a.alertid,a.mediatypeid,a.sendto,a.subject,a.message,a.status,mt.mediatypeid,"
					"mt.type,mt.description,mt.smtp_server,mt.smtp_helo,mt.smtp_email,mt.exec_path,"
					"mt.gsm_modem,mt.username,mt.passwd,mt.smtp_port,mt.smtp_security,"
					"mt.smtp_verify_peer,mt.smtp_verify_host,mt.smtp_authentication,a.retries"
				" from alerts a,media_type mt"
				" where a.mediatypeid=mt.mediatypeid"
					" and a.status=%d"
					" and a.alerttype=%d"
				" order by a.alertid",
				ALERT_STATUS_NOT_SENT,
				ALERT_TYPE_MESSAGE);

		while (NULL != (row = DBfetch(result)))
		{
			ZBX_STR2UINT64(alert.alertid, row[0]);
			ZBX_STR2UINT64(alert.mediatypeid, row[1]);
			alert.sendto = row[2];
			alert.subject = row[3];
			alert.message = row[4];
			alert.status = atoi(row[5]);

			ZBX_STR2UINT64(mediatype.mediatypeid, row[6]);
			mediatype.type = atoi(row[7]);
			mediatype.description = row[8];
			mediatype.smtp_server = row[9];
			mediatype.smtp_helo = row[10];
			mediatype.smtp_email = row[11];
			mediatype.exec_path = row[12];
			mediatype.gsm_modem = row[13];
			mediatype.username = row[14];
			mediatype.passwd = row[15];
			mediatype.smtp_port = (unsigned short)atoi(row[16]);
			ZBX_STR2UCHAR(mediatype.smtp_security, row[17]);
			ZBX_STR2UCHAR(mediatype.smtp_verify_peer, row[18]);
			ZBX_STR2UCHAR(mediatype.smtp_verify_host, row[19]);
			ZBX_STR2UCHAR(mediatype.smtp_authentication, row[20]);

			alert.retries = atoi(row[21]);

			*error = '\0';
			res = execute_action(&alert, &mediatype, error, sizeof(error));

			if (SUCCEED == res)
			{
				zabbix_log(LOG_LEVEL_DEBUG, "alert ID [" ZBX_FS_UI64 "] was sent successfully",
						alert.alertid);
				DBexecute("update alerts set status=%d,error='' where alertid=" ZBX_FS_UI64,
						ALERT_STATUS_SENT, alert.alertid);
				alerts_success++;
			}
			else
			{
				zabbix_log(LOG_LEVEL_DEBUG, "error sending alert ID [" ZBX_FS_UI64 "]", alert.alertid);

				error_esc = DBdyn_escape_string_len(error, ALERT_ERROR_LEN);

				alert.retries++;

				if (ALERT_MAX_RETRIES > alert.retries)
				{
					DBexecute("update alerts set retries=%d,error='%s' where alertid=" ZBX_FS_UI64,
							alert.retries, error_esc, alert.alertid);
				}
				else
				{
					DBexecute("update alerts set status=%d,retries=%d,error='%s' where alertid=" ZBX_FS_UI64,
							ALERT_STATUS_FAILED, alert.retries, error_esc, alert.alertid);
				}

				zbx_free(error_esc);

				alerts_fail++;
			}

		}
		DBfree_result(result);

		sec = zbx_time() - sec;

		zbx_setproctitle("%s [sent alerts: %d success, %d fail in " ZBX_FS_DBL " sec, idle %d sec]",
				get_process_type_string(process_type), alerts_success, alerts_fail, sec,
				CONFIG_SENDER_FREQUENCY);

		zbx_sleep_loop(CONFIG_SENDER_FREQUENCY);
	}
}
Exemplo n.º 9
0
/******************************************************************************
 *                                                                            *
 * Function: get_value_internal                                               *
 *                                                                            *
 * Purpose: retrieve data from Zabbix server (internally supported items)     *
 *                                                                            *
 * Parameters: item - item we are interested in                               *
 *                                                                            *
 * Return value: SUCCEED - data successfully retrieved and stored in result   *
 *               NOTSUPPORTED - requested item is not supported               *
 *                                                                            *
 * Author: Alexei Vladishev                                                   *
 *                                                                            *
 ******************************************************************************/
int	get_value_internal(DC_ITEM *item, AGENT_RESULT *result)
{
    int		nparams;
    char		params[MAX_STRING_LEN], *error = NULL;
    char		tmp[MAX_STRING_LEN], tmp1[HOST_HOST_LEN_MAX];

    init_result(result);

    if (0 != strncmp(item->key, "zabbix[", 7))
        goto notsupported;

    if (2 != parse_command(item->key, NULL, 0, params, sizeof(params)))
        goto notsupported;

    if (0 != get_param(params, 1, tmp, sizeof(tmp)))
        goto notsupported;

    nparams = num_param(params);

    if (0 == strcmp(tmp, "triggers"))			/* zabbix["triggers"] */
    {
        if (1 != nparams)
            goto notsupported;

        SET_UI64_RESULT(result, DBget_row_count("triggers"));
    }
    else if (0 == strcmp(tmp, "items"))			/* zabbix["items"] */
    {
        if (1 != nparams)
            goto notsupported;

        SET_UI64_RESULT(result, DBget_row_count("items"));
    }
    else if (0 == strcmp(tmp, "items_unsupported"))		/* zabbix["items_unsupported"] */
    {
        if (1 != nparams)
            goto notsupported;

        SET_UI64_RESULT(result, DBget_items_unsupported_count());
    }
    else if (0 == strcmp(tmp, "history") ||			/* zabbix["history"] */
             0 == strcmp(tmp, "history_log") ||	/* zabbix["history_log"] */
             0 == strcmp(tmp, "history_str") ||	/* zabbix["history_str"] */
             0 == strcmp(tmp, "history_text") ||	/* zabbix["history_text"] */
             0 == strcmp(tmp, "history_uint"))	/* zabbix["history_uint"] */
    {
        if (1 != nparams)
            goto notsupported;

        SET_UI64_RESULT(result, DBget_row_count(tmp));
    }
    else if (0 == strcmp(tmp, "trends") ||			/* zabbix["trends"] */
             0 == strcmp(tmp, "trends_uint"))	/* zabbix["trends_uint"] */
    {
        if (1 != nparams)
            goto notsupported;

        SET_UI64_RESULT(result, DBget_row_count(tmp));
    }
    else if (0 == strcmp(tmp, "queue"))			/* zabbix["queue",<from>,<to>] */
    {
        unsigned int	from = 6, to = (unsigned int)-1;

        if (3 < nparams)
        {
            error = zbx_strdup(error, "Invalid number of parameters");
            goto notsupported;
        }

        if (2 <= nparams)
        {
            if (0 != get_param(params, 2, tmp, sizeof(tmp)))
                goto notsupported;

            if ('\0' != *tmp && FAIL == is_uint_suffix(tmp, &from))
            {
                error = zbx_strdup(error, "Invalid second parameter");
                goto notsupported;
            }
        }

        if (3 <= nparams)
        {
            if (0 != get_param(params, 3, tmp, sizeof(tmp)))
                goto notsupported;

            if ('\0' != *tmp && FAIL == is_uint_suffix(tmp, &to))
            {
                error = zbx_strdup(error, "Invalid third parameter");
                goto notsupported;
            }
        }

        if ((unsigned int)-1 != to && from > to)
        {
            error = zbx_strdup(error, "Parameters represent an invalid interval");
            goto notsupported;
        }

        SET_UI64_RESULT(result, DBget_queue_count((int)from, (int)to));
    }
    else if (0 == strcmp(tmp, "requiredperformance"))	/* zabbix["requiredperformance"] */
    {
        if (1 != nparams)
            goto notsupported;

        SET_DBL_RESULT(result, DBget_requiredperformance());
    }
    else if (0 == strcmp(tmp, "uptime"))			/* zabbix["uptime"] */
    {
        if (1 != nparams)
            goto notsupported;

        SET_UI64_RESULT(result, time(NULL) - CONFIG_SERVER_STARTUP_TIME);
    }
    else if (0 == strcmp(tmp, "boottime"))			/* zabbix["boottime"] */
    {
        if (1 != nparams)
            goto notsupported;

        SET_UI64_RESULT(result, CONFIG_SERVER_STARTUP_TIME);
    }
    else if (0 == strcmp(tmp, "host"))			/* zabbix["host",<type>,"available"] */
    {
        if (3 != nparams)
            goto notsupported;

        if (0 != get_param(params, 3, tmp, sizeof(tmp)) || 0 != strcmp(tmp, "available"))
            goto notsupported;

        if (0 != get_param(params, 2, tmp, sizeof(tmp)))
            goto notsupported;

        if (0 == strcmp(tmp, "agent"))
            SET_UI64_RESULT(result, item->host.available);
        else if (0 == strcmp(tmp, "snmp"))
            SET_UI64_RESULT(result, item->host.snmp_available);
        else if (0 == strcmp(tmp, "ipmi"))
            SET_UI64_RESULT(result, item->host.ipmi_available);
        else if (0 == strcmp(tmp, "jmx"))
            SET_UI64_RESULT(result, item->host.jmx_available);
        else
            goto notsupported;

        result->ui64 = 2 - result->ui64;
    }
    else if (0 == strcmp(tmp, "proxy"))			/* zabbix["proxy",<hostname>,"lastaccess"] */
    {
        int	lastaccess;

        if (3 != nparams)
            goto notsupported;

        if (0 != get_param(params, 2, tmp1, sizeof(tmp1)))
            goto notsupported;

        if (0 != get_param(params, 3, tmp, sizeof(tmp)) || 0 != strcmp(tmp, "lastaccess"))
            goto notsupported;

        if (FAIL == DBget_proxy_lastaccess(tmp1, &lastaccess, &error))
            goto notsupported;

        SET_UI64_RESULT(result, lastaccess);
    }
    else if (0 == strcmp(tmp, "java"))			/* zabbix["java",...] */
    {
        int	res;

        alarm(CONFIG_TIMEOUT);
        res = get_value_java(ZBX_JAVA_GATEWAY_REQUEST_INTERNAL, item, result);
        alarm(0);

        if (SUCCEED != res)
            goto notsupported;
    }
    else if (0 == strcmp(tmp, "process"))			/* zabbix["process",<type>,<mode>,<state>] */
    {
        unsigned char	process_type;
        int		process_forks;
        double		value;

        if (4 < nparams)
        {
            error = zbx_strdup(error, "Invalid number of parameters");
            goto notsupported;
        }

        if (0 != get_param(params, 2, tmp, sizeof(tmp)))
        {
            error = zbx_strdup(error, "Required second parameter missing");
            goto notsupported;
        }

        for (process_type = 0; process_type < ZBX_PROCESS_TYPE_COUNT; process_type++)
            if (0 == strcmp(tmp, get_process_type_string(process_type)))
                break;

        if (ZBX_PROCESS_TYPE_COUNT == process_type)
        {
            error = zbx_strdup(error, "Invalid second parameter");
            goto notsupported;
        }

        process_forks = get_process_type_forks(process_type);

        if (0 != get_param(params, 3, tmp, sizeof(tmp)))
            *tmp = '\0';

        if (0 == strcmp(tmp, "count"))
        {
            if (3 < nparams)
            {
                error = zbx_strdup(error, "Invalid number of parameters");
                goto notsupported;
            }

            SET_UI64_RESULT(result, process_forks);
        }
        else
        {
            unsigned char	aggr_func, state;
            unsigned short	process_num = 0;

            if ('\0' == *tmp || 0 == strcmp(tmp, "avg"))
                aggr_func = ZBX_AGGR_FUNC_AVG;
            else if (0 == strcmp(tmp, "max"))
                aggr_func = ZBX_AGGR_FUNC_MAX;
            else if (0 == strcmp(tmp, "min"))
                aggr_func = ZBX_AGGR_FUNC_MIN;
            else if (SUCCEED == is_ushort(tmp, &process_num) && 0 < process_num)
                aggr_func = ZBX_AGGR_FUNC_ONE;
            else
            {
                error = zbx_strdup(error, "Invalid third parameter");
                goto notsupported;
            }

            if (0 == process_forks)
            {
                error = zbx_dsprintf(error, "No \"%s\" processes started",
                                     get_process_type_string(process_type));
                goto notsupported;
            }
            else if (process_num > process_forks)
            {
                error = zbx_dsprintf(error, "\"%s\" #%d is not started",
                                     get_process_type_string(process_type), process_num);
                goto notsupported;
            }

            if (0 != get_param(params, 4, tmp, sizeof(tmp)))
                *tmp = '\0';

            if ('\0' == *tmp || 0 == strcmp(tmp, "busy"))
                state = ZBX_PROCESS_STATE_BUSY;
            else if (0 == strcmp(tmp, "idle"))
                state = ZBX_PROCESS_STATE_IDLE;
            else
            {
                error = zbx_strdup(error, "Invalid fourth parameter");
                goto notsupported;
            }

            get_selfmon_stats(process_type, aggr_func, process_num, state, &value);

            SET_DBL_RESULT(result, value);
        }
    }
    else if (0 == strcmp(tmp, "wcache"))			/* zabbix[wcache,<cache>,<mode>] */
    {
        if (3 < nparams)
            goto notsupported;

        if (0 != get_param(params, 2, tmp, sizeof(tmp)))
            goto notsupported;

        if (0 != get_param(params, 3, tmp1, sizeof(tmp1)))
            *tmp1 = '\0';

        if (0 == strcmp(tmp, "values"))
        {
            if ('\0' == *tmp1 || 0 == strcmp(tmp1, "all"))
                SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_COUNTER));
            else if (0 == strcmp(tmp1, "float"))
                SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_FLOAT_COUNTER));
            else if (0 == strcmp(tmp1, "uint"))
                SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_UINT_COUNTER));
            else if (0 == strcmp(tmp1, "str"))
                SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_STR_COUNTER));
            else if (0 == strcmp(tmp1, "log"))
                SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_LOG_COUNTER));
            else if (0 == strcmp(tmp1, "text"))
                SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_TEXT_COUNTER));
            else if (0 == strcmp(tmp1, "not supported"))
                SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_NOTSUPPORTED_COUNTER));
            else
                goto notsupported;
        }
        else if (0 == strcmp(tmp, "history"))
        {
            if ('\0' == *tmp1 || 0 == strcmp(tmp1, "pfree"))
                SET_DBL_RESULT(result, *(double *)DCget_stats(ZBX_STATS_HISTORY_PFREE));
            else if (0 == strcmp(tmp1, "total"))
                SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_TOTAL));
            else if (0 == strcmp(tmp1, "used"))
                SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_USED));
            else if (0 == strcmp(tmp1, "free"))
                SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_FREE));
            else
                goto notsupported;
        }
        else if (0 == strcmp(tmp, "trend"))
        {
            if ('\0' == *tmp1 || 0 == strcmp(tmp1, "pfree"))
                SET_DBL_RESULT(result, *(double *)DCget_stats(ZBX_STATS_TREND_PFREE));
            else if (0 == strcmp(tmp1, "total"))
                SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_TREND_TOTAL));
            else if (0 == strcmp(tmp1, "used"))
                SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_TREND_USED));
            else if (0 == strcmp(tmp1, "free"))
                SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_TREND_FREE));
            else
                goto notsupported;
        }
        else if (0 == strcmp(tmp, "text"))
        {
            if ('\0' == *tmp1 || 0 == strcmp(tmp1, "pfree"))
                SET_DBL_RESULT(result, *(double *)DCget_stats(ZBX_STATS_TEXT_PFREE));
            else if (0 == strcmp(tmp1, "total"))
                SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_TEXT_TOTAL));
            else if (0 == strcmp(tmp1, "used"))
                SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_TEXT_USED));
            else if (0 == strcmp(tmp1, "free"))
                SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_TEXT_FREE));
            else
                goto notsupported;
        }
        else
            goto notsupported;
    }
    else if (0 == strcmp(tmp, "rcache"))			/* zabbix[rcache,<cache>,<mode>] */
    {
        if (3 < nparams)
            goto notsupported;

        if (0 != get_param(params, 2, tmp, sizeof(tmp)))
            goto notsupported;

        if (0 != get_param(params, 3, tmp1, sizeof(tmp1)))
            *tmp1 = '\0';

        if (0 == strcmp(tmp, "buffer"))
        {
            if ('\0' == *tmp1 || 0 == strcmp(tmp1, "pfree"))
                SET_DBL_RESULT(result, *(double *)DCconfig_get_stats(ZBX_CONFSTATS_BUFFER_PFREE));
            else if (0 == strcmp(tmp1, "total"))
                SET_UI64_RESULT(result, *(zbx_uint64_t *)DCconfig_get_stats(ZBX_CONFSTATS_BUFFER_TOTAL));
            else if (0 == strcmp(tmp1, "used"))
                SET_UI64_RESULT(result, *(zbx_uint64_t *)DCconfig_get_stats(ZBX_CONFSTATS_BUFFER_USED));
            else if (0 == strcmp(tmp1, "free"))
                SET_UI64_RESULT(result, *(zbx_uint64_t *)DCconfig_get_stats(ZBX_CONFSTATS_BUFFER_FREE));
            else
                goto notsupported;
        }
        else
            goto notsupported;
    }
    else
        goto notsupported;

    return SUCCEED;
notsupported:
    if (!ISSET_MSG(result))
    {
        if (NULL == error)
            error = zbx_strdup(error, "Internal check is not supported");

        SET_MSG_RESULT(result, error);
    }

    return NOTSUPPORTED;
}
Exemplo n.º 10
0
ZBX_THREAD_ENTRY(listener_thread, args)
{
#if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
	char		*msg = NULL;
#endif
	int		ret;
	zbx_socket_t	s;

	assert(args);
	assert(((zbx_thread_args_t *)args)->args);

	process_type = ((zbx_thread_args_t *)args)->process_type;
	server_num = ((zbx_thread_args_t *)args)->server_num;
	process_num = ((zbx_thread_args_t *)args)->process_num;

	zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type),
			server_num, get_process_type_string(process_type), process_num);

	memcpy(&s, (zbx_socket_t *)((zbx_thread_args_t *)args)->args, sizeof(zbx_socket_t));

	zbx_free(args);

#if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
	zbx_tls_init_child();
#endif
	while (ZBX_IS_RUNNING())
	{
		zbx_setproctitle("listener #%d [waiting for connection]", process_num);
		ret = zbx_tcp_accept(&s, configured_tls_accept_modes);
		zbx_update_env(zbx_time());

		if (SUCCEED == ret)
		{
			zbx_setproctitle("listener #%d [processing request]", process_num);

			if ('\0' != *CONFIG_HOSTS_ALLOWED &&
					SUCCEED == (ret = zbx_tcp_check_allowed_peers(&s, CONFIG_HOSTS_ALLOWED)))
			{
#if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
				if (ZBX_TCP_SEC_TLS_CERT != s.connection_type ||
						SUCCEED == (ret = zbx_check_server_issuer_subject(&s, &msg)))
#endif
				{
					process_listener(&s);
				}
			}

			zbx_tcp_unaccept(&s);
		}

		if (SUCCEED == ret || EINTR == zbx_socket_last_error())
			continue;

#if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
		if (NULL != msg)
		{
			zabbix_log(LOG_LEVEL_WARNING, "failed to accept an incoming connection: %s", msg);
			zbx_free(msg);
		}
		else
#endif
		{
			zabbix_log(LOG_LEVEL_WARNING, "failed to accept an incoming connection: %s",
					zbx_socket_strerror());
		}

		if (ZBX_IS_RUNNING())
			zbx_sleep(1);
	}

#ifdef _WINDOWS
	ZBX_DO_EXIT();

	zbx_thread_exit(EXIT_SUCCESS);
#endif
}
Exemplo n.º 11
0
/******************************************************************************
 *                                                                            *
 * Function: timer_thread                                                     *
 *                                                                            *
 * Purpose: periodically processes maintenance                                *
 *                                                                            *
 ******************************************************************************/
ZBX_THREAD_ENTRY(timer_thread, args)
{
	double		sec = 0.0;
	int		maintenance_time = 0, update_time = 0, idle = 1, events_num, hosts_num, update;
	char		*info = NULL;
	size_t		info_alloc = 0, info_offset = 0;

	process_type = ((zbx_thread_args_t *)args)->process_type;
	server_num = ((zbx_thread_args_t *)args)->server_num;
	process_num = ((zbx_thread_args_t *)args)->process_num;

	zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type),
			server_num, get_process_type_string(process_type), process_num);

	zbx_setproctitle("%s #%d [connecting to the database]", get_process_type_string(process_type), process_num);
	zbx_strcpy_alloc(&info, &info_alloc, &info_offset, "started");

	DBconnect(ZBX_DB_CONNECT_NORMAL);

	for (;;)
	{
		sec = zbx_time();
		zbx_update_env(sec);

		if (1 == process_num)
		{
			/* start update process only when all timers have finished their updates */
			if (sec - maintenance_time >= ZBX_TIMER_DELAY && FAIL == zbx_dc_maintenance_check_update_flags())
			{
				zbx_setproctitle("%s #%d [%s, processing maintenances]",
						get_process_type_string(process_type), process_num, info);

				update = zbx_dc_update_maintenances();

				/* force maintenance updates at server startup */
				if (0 == maintenance_time)
					update = SUCCEED;

				/* update hosts if there are modified (stopped, started, changed) maintenances */
				if (SUCCEED == update)
					hosts_num = update_host_maintenances();
				else
					hosts_num = 0;

				db_remove_expired_event_suppress_data((int)sec);

				if (SUCCEED == update)
				{
					zbx_dc_maintenance_set_update_flags();
					db_update_event_suppress_data(&events_num);
					zbx_dc_maintenance_reset_update_flag(process_num);
				}
				else
					events_num = 0;

				info_offset = 0;
				zbx_snprintf_alloc(&info, &info_alloc, &info_offset,
						"updated %d hosts, suppressed %d events in " ZBX_FS_DBL " sec",
						hosts_num, events_num, zbx_time() - sec);

				update_time = (int)sec;
			}
		}
		else if (SUCCEED == zbx_dc_maintenance_check_update_flag(process_num))
		{
			zbx_setproctitle("%s #%d [%s, processing maintenances]", get_process_type_string(process_type),
					process_num, info);

			db_update_event_suppress_data(&events_num);

			info_offset = 0;
			zbx_snprintf_alloc(&info, &info_alloc, &info_offset, "suppressed %d events in " ZBX_FS_DBL
					" sec", events_num, zbx_time() - sec);

			update_time = (int)sec;
			zbx_dc_maintenance_reset_update_flag(process_num);
		}

		if (maintenance_time != update_time)
		{
			maintenance_time = (int)sec;

			if (0 > (idle = ZBX_TIMER_DELAY - (zbx_time() - sec)))
				idle = 0;

			zbx_setproctitle("%s #%d [%s, idle %d sec]",
					get_process_type_string(process_type), process_num, info, idle);
		}

		if (0 != idle)
			zbx_sleep_loop(1);

		idle = 1;
	}

}
Exemplo n.º 12
0
ZBX_THREAD_ENTRY(proxypoller_thread, args)
{
	int	nextcheck, sleeptime = -1, processed = 0, old_processed = 0;
	double	sec, total_sec = 0.0, old_total_sec = 0.0;
	time_t	last_stat_time;

	process_type = ((zbx_thread_args_t *)args)->process_type;
	server_num = ((zbx_thread_args_t *)args)->server_num;
	process_num = ((zbx_thread_args_t *)args)->process_num;

	zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_daemon_type_string(daemon_type),
			server_num, get_process_type_string(process_type), process_num);

#define STAT_INTERVAL	5	/* if a process is busy and does not sleep then update status not faster than */
				/* once in STAT_INTERVAL seconds */

	zbx_setproctitle("%s #%d [connecting to the database]", get_process_type_string(process_type), process_num);
	last_stat_time = time(NULL);

	DBconnect(ZBX_DB_CONNECT_NORMAL);

	for (;;)
	{
		if (0 != sleeptime)
		{
			zbx_setproctitle("%s #%d [exchanged data with %d proxies in " ZBX_FS_DBL " sec,"
					" exchanging data]", get_process_type_string(process_type), process_num,
					old_processed, old_total_sec);
		}

		sec = zbx_time();
		processed += process_proxy();
		total_sec += zbx_time() - sec;

		nextcheck = DCconfig_get_proxypoller_nextcheck();
		sleeptime = calculate_sleeptime(nextcheck, POLLER_DELAY);

		if (0 != sleeptime || STAT_INTERVAL <= time(NULL) - last_stat_time)
		{
			if (0 == sleeptime)
			{
				zbx_setproctitle("%s #%d [exchanged data with %d proxies in " ZBX_FS_DBL " sec,"
						" exchanging data]", get_process_type_string(process_type), process_num,
						processed, total_sec);
			}
			else
			{
				zbx_setproctitle("%s #%d [exchanged data with %d proxies in " ZBX_FS_DBL " sec,"
						" idle %d sec]", get_process_type_string(process_type), process_num,
						processed, total_sec, sleeptime);
				old_processed = processed;
				old_total_sec = total_sec;
			}
			processed = 0;
			total_sec = 0.0;
			last_stat_time = time(NULL);
		}

		zbx_sleep_loop(sleeptime);
	}
#undef STAT_INTERVAL
}