/****************************************************************************** * * * Function: delete_history * * * * Purpose: remove outdated information from historical table * * * * Parameters: now - current timestamp * * * * Return value: number of rows deleted * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static int delete_history(char *table, zbx_uint64_t itemid, int keep_history, int now) { DB_RESULT result; DB_ROW row; int min_clock; zabbix_log( LOG_LEVEL_DEBUG, "In delete_history(%s," ZBX_FS_UI64 "," ZBX_FS_UI64 ",%d)", table, itemid, keep_history, now); result = DBselect("select min(clock) from %s where itemid=" ZBX_FS_UI64, table, itemid); row=DBfetch(result); if(!row || DBis_null(row[0]) == SUCCEED) { DBfree_result(result); return 0; } min_clock = atoi(row[0]); DBfree_result(result); /* zabbix_log( LOG_LEVEL_DEBUG, "Now %d keep_history %d Itemid " ZBX_FS_UI64 " min %d new min %d", now, keep_history, itemid, min_clock, MIN(now-24*3600*keep_history, min_clock+4*3600*CONFIG_HOUSEKEEPING_FREQUENCY));*/ return DBexecute("delete from %s where itemid=" ZBX_FS_UI64 " and clock<%d", table, itemid, MIN(now-24*3600*keep_history, min_clock+4*3600*CONFIG_HOUSEKEEPING_FREQUENCY) ); }
static int check_data_uniqueness(const char *table_name, const char *field_name) { DB_RESULT result; DB_ROW row; int ret = SUCCEED; if (NULL == (result = DBselect("select %s from %s group by %s having count(*)>1", field_name, table_name, field_name))) { return FAIL; } while (NULL != (row = DBfetch(result))) { zabbix_log(LOG_LEVEL_CRIT, "Duplicate data \"%s\" for field \"%s\" is found in table \"%s\"." " Remove it manually and restart the process.", row[0], field_name, table_name); ret = FAIL; } DBfree_result(result); return ret; }
static int DBpatch_2030024(void) { DB_RESULT result; DB_ROW row; char *value, *macro_esc, *value_esc; int ret = FAIL, rc; /* 1 - ZBX_FLAG_DISCOVERY_RULE*/ if (NULL == (result = DBselect("select itemid,filter from items where filter<>'' and flags=1"))) return FAIL; while (NULL != (row = DBfetch(result))) { if (NULL == (value = strchr(row[1], ':')) || 0 == strcmp(row[1], ":")) continue; *value++ = '\0'; macro_esc = DBdyn_escape_string(row[1]); value_esc = DBdyn_escape_string(value); rc = DBexecute("insert into item_condition" " (item_conditionid,itemid,macro,value)" " values (%s,%s,'%s','%s')", row[0], row[0], macro_esc, value_esc); zbx_free(value_esc); zbx_free(macro_esc); if (ZBX_DB_OK > rc) goto out; } ret = SUCCEED; out: DBfree_result(result); return ret; }
/****************************************************************************** * * * Function: add_discovered_host_group * * * * Purpose: add group to host if not added already * * * * Author: Alexander Vladishev * * * ******************************************************************************/ static void add_discovered_host_group(zbx_uint64_t hostid, zbx_uint64_t groupid) { DB_RESULT result; DB_ROW row; zbx_uint64_t hostgroupid; result = DBselect( "select hostgroupid" " from hosts_groups" " where groupid=" ZBX_FS_UI64 " and hostid=" ZBX_FS_UI64, groupid, hostid); if (NULL == (row = DBfetch(result))) { hostgroupid = DBget_maxid("hosts_groups"); DBexecute("insert into hosts_groups (hostgroupid,hostid,groupid)" " values (" ZBX_FS_UI64 "," ZBX_FS_UI64 "," ZBX_FS_UI64 ")", hostgroupid, hostid, groupid); } DBfree_result(result); }
/****************************************************************************** * * * Function: main_historysender * * * * Purpose: periodically sends historical data to master node * * * * Parameters: * * * * Return value: * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ void main_historysender() { DB_RESULT result; DB_ROW row; int master_nodeid, nodeid; zabbix_log(LOG_LEVEL_DEBUG, "In main_historysender()"); master_nodeid = CONFIG_MASTER_NODEID; if (0 == master_nodeid) return; result = DBselect("select nodeid from nodes"); while ((row = DBfetch(result))) { nodeid = atoi(row[0]); if (SUCCEED == is_master_node(CONFIG_NODEID, nodeid)) continue; process_history_tables(master_nodeid, nodeid); } DBfree_result(result); }
/****************************************************************************** * * * Function: get_next_point_to_node * * * * Purpose: find next point to slave node * * * * Parameters: * * * * Return value: SUCCEED - processed successfully * * FAIL - an error occurred * * * * Author: Alexander Vladishev * * * * Comments: * * * ******************************************************************************/ static int get_next_point_to_node(int current_nodeid, int slave_nodeid, int *nodeid) { DB_RESULT db_result; DB_ROW db_row; int id, res = FAIL; db_result = DBselect("select nodeid from nodes where masterid=%d", current_nodeid); while (NULL != (db_row = DBfetch(db_result))) { id = atoi(db_row[0]); if (id == slave_nodeid || SUCCEED == get_next_point_to_node(id, slave_nodeid, NULL)) { if (NULL != nodeid) *nodeid = id; res = SUCCEED; break; } } DBfree_result(db_result); return res; }
/****************************************************************************** * * * Function: add_host_event * * * * Purpose: generate host UP/DOWN event if required * * * * Parameters: * * * * Return value: * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static void add_host_event(char *ip) { DB_RESULT result; DB_ROW row; DB_EVENT event; int now; int status; zbx_uint64_t dhostid; assert(ip); zabbix_log(LOG_LEVEL_DEBUG, "In add_host_event(ip:%s)", ip); result = DBselect("select status,dhostid from dhosts where ip='%s'", ip); row=DBfetch(result); if(row && DBis_null(row[0])!=SUCCEED) { now = time(NULL); status = atoi(row[0]); ZBX_STR2UINT64(dhostid, row[1]); memset(&event,0,sizeof(DB_EVENT)); event.eventid = 0; event.source = EVENT_SOURCE_DISCOVERY; event.object = EVENT_OBJECT_DHOST; event.objectid = dhostid; event.clock = now; event.value = status; event.acknowledged = 0; process_event(&event); } DBfree_result(result); zabbix_log(LOG_LEVEL_DEBUG, "End add_host_event()"); }
static void DBget_version(int *mandatory, int *optional) { DB_RESULT result; DB_ROW row; *mandatory = -1; *optional = -1; result = DBselect("select mandatory,optional from dbversion"); if (NULL != (row = DBfetch(result))) { *mandatory = atoi(row[0]); *optional = atoi(row[1]); } DBfree_result(result); if (-1 == *mandatory) { zabbix_log(LOG_LEVEL_CRIT, "Cannot get the database version. Exiting ..."); exit(EXIT_FAILURE); } }
/****************************************************************************** * * * Function: * * * * Purpose: * * * * Parameters: * * * * Return value: * * * * Comments: * * * ******************************************************************************/ int ja_host_unlock(const char *host) { int db_ret; char *host_esc; const char *__function_name = "ja_host_unlock"; zabbix_log(LOG_LEVEL_DEBUG, "In %s() host: %s", __function_name, host); DBfree_result(DBselect ("select lock_host_name from ja_host_lock_table where lock_host_name = 'HOST_LOCK_RECORD' for update")); host_esc = DBdyn_escape_string(host); db_ret = DBexecute ("delete from ja_host_lock_table where lock_host_name = '%s'", host_esc); zbx_free(host_esc); if (db_ret < ZBX_DB_OK) return FAIL; else return SUCCEED; }
/****************************************************************************** * * * Function: convert_condition_values * * * * Purpose: special processing for "value" field in "conditions" table * * * * Parameters: old_id - old id, new_id - new node id * * * * Return value: SUCCEED - converted successfully * * FAIL - an error occurred * * * * Author: Aleksandrs Saveljevs * * * * Comments: * * * ******************************************************************************/ static int convert_condition_values(int old_id, int new_id, const char *rel_table_name, int type) { zbx_uint64_t prefix; const ZBX_TABLE *r_table; DB_RESULT result; DB_ROW row; zbx_uint64_t value; if (NULL == (r_table = DBget_table(rel_table_name))) { printf("conditions.value FAILED\n"); return FAIL; } prefix = (zbx_uint64_t)__UINT64_C(100000000000000)*(zbx_uint64_t)new_id; if (r_table->flags & ZBX_SYNC) prefix += (zbx_uint64_t)__UINT64_C(100000000000)*(zbx_uint64_t)new_id; result = DBselect("select conditionid,value" " from conditions" " where conditiontype=%d", type); while (NULL != (row = DBfetch(result))) { ZBX_STR2UINT64(value, row[1]); value += prefix; DBexecute("update conditions" " set value='" ZBX_FS_UI64 "'" " where conditionid=%s", value, row[0]); } DBfree_result(result); return SUCCEED; }
/****************************************************************************** * * * Function: * * * * Purpose: * * * * Parameters: * * * * Return value: * * * * Comments: * * * ******************************************************************************/ int ja_setenv(const zbx_uint64_t inner_job_id) { int ret; DB_RESULT result; DB_ROW row; char *key, *value; const char *__function_name = "ja_setenv"; zabbix_log(LOG_LEVEL_DEBUG, "In %s() inner_job_id: " ZBX_FS_UI64, __function_name, inner_job_id); result = DBselect ("select value_name, before_value from ja_run_value_before_table" " where inner_job_id = " ZBX_FS_UI64, inner_job_id); ret = SUCCEED; while (NULL != (row = DBfetch(result))) { key = row[0]; value = row[1]; zabbix_log(LOG_LEVEL_DEBUG, "In %s() inner_job_id: " ZBX_FS_UI64 ", %s = %s", __function_name, inner_job_id, key, value); if (setenv(key, value, 1) != 0) { ja_log("JAENV300001", 0, NULL, inner_job_id, __function_name, inner_job_id, key, value); ret = FAIL; break; } } DBfree_result(result); return ret; }
/****************************************************************************** * * * Function: init_config * * * * Purpose: init list of medias to send notifications in case if DB is down * * * * Parameters: * * * * Return value: * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static void init_config() { DB_RESULT result; DB_ROW row; zabbix_log(LOG_LEVEL_DEBUG, "In init_config()"); result = DBselect("select 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, m.mediaid,m.userid,m.mediatypeid,m.sendto,m.severity,m.period from media m, users_groups u, config c,media_type mt where m.userid=u.userid and u.usrgrpid=c.alert_usrgrpid and m.mediatypeid=mt.mediatypeid and m.active=%d", MEDIA_STATUS_ACTIVE); while((row=DBfetch(result))) { if(num>=ZBX_MAX_RECIPIENTS) break; memset(&recipients[num].mediatype, 0, sizeof(DB_MEDIATYPE)); memset(&recipients[num].alert, 0, sizeof(DB_ALERT)); ZBX_STR2UINT64(recipients[num].mediatype.mediatypeid,row[0]); recipients[num].mediatype.type=atoi(row[1]); recipients[num].mediatype.description=strdup(row[2]); recipients[num].mediatype.smtp_server=strdup(row[3]); recipients[num].mediatype.smtp_helo=strdup(row[4]); recipients[num].mediatype.smtp_email=strdup(row[5]); recipients[num].mediatype.exec_path=strdup(row[6]); recipients[num].mediatype.gsm_modem=strdup(row[7]); recipients[num].mediatype.username=strdup(row[8]); recipients[num].mediatype.passwd=strdup(row[9]); recipients[num].alert.sendto=strdup(row[13]); recipients[num].alert.subject=strdup("ZABBIX database is down."); recipients[num].alert.message=strdup("ZABBIX database is down."); num++; } DBfree_result(result); }
/****************************************************************************** * * * Function: * * * * Purpose: * * * * Parameters: * * * * Return value: * * * * Comments: * * * ******************************************************************************/ int ja_host_lockinfo(const char *host) { int ret; DB_RESULT result; DB_ROW row; char *host_esc; const char *__function_name = "ja_host_lockinfo"; zabbix_log(LOG_LEVEL_DEBUG, "In %s() host: %s", __function_name, host); ret = FAIL; host_esc = DBdyn_escape_string(host); result = DBselect ("select lock_host_name from ja_host_lock_table where lock_host_name = '%s'", host_esc); row = DBfetch(result); if (row != NULL) ret = SUCCEED; zbx_free(host_esc); DBfree_result(result); return ret; }
/****************************************************************************** * * * Function: convert_triggers_expression * * * * Purpose: convert trigger expressions to new node ID * * * * Parameters: old_id - old id, new_id - new node id * * * * Return value: SUCCEED - converted successfully * * FAIL - an error occurred * * * * Author: Alexander Vladishev * * * * Comments: * * * ******************************************************************************/ static int convert_triggers_expression(int old_id, int new_id) { zbx_uint64_t prefix; const ZBX_TABLE *r_table; DB_RESULT result; DB_ROW row; char new_expression[MAX_STRING_LEN]; char *new_expression_esc; if (NULL == (r_table = DBget_table("functions"))) { printf("triggers.expression FAILED\n"); return FAIL; } prefix = (zbx_uint64_t)__UINT64_C(100000000000000)*(zbx_uint64_t)new_id; if (r_table->flags & ZBX_SYNC) prefix += (zbx_uint64_t)__UINT64_C(100000000000)*(zbx_uint64_t)new_id; result = DBselect("select expression,triggerid from triggers"); while (NULL != (row = DBfetch(result))) { memset(new_expression, 0, sizeof(new_expression)); convert_expression(old_id, new_id, prefix, row[0], new_expression); new_expression_esc = DBdyn_escape_string_len(new_expression, TRIGGER_EXPRESSION_LEN); DBexecute("update triggers set expression='%s' where triggerid=%s", new_expression_esc, row[1]); zbx_free(new_expression_esc); } DBfree_result(result); return SUCCEED; }
/****************************************************************************** * * * Function: housekeeping_history_and_trends * * * * Purpose: remove outdated information from history and trends * * * * Parameters: now - current timestamp * * * * Return value: number of rows deleted * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static int housekeeping_history_and_trends(int now) { const char *__function_name = "housekeeping_history_and_trends"; zbx_uint64_t itemid; DB_RESULT result; DB_ROW row; int history, trends, deleted = 0; zabbix_log(LOG_LEVEL_DEBUG, "In %s() now:%d", __function_name, now); result = DBselect( "select i.itemid,i.history,i.trends from items i,hosts h" " where i.hostid=h.hostid" " and h.status in (%d,%d)", HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED); while (NULL != (row = DBfetch(result))) { ZBX_STR2UINT64(itemid, row[0]); history = atoi(row[1]); trends = atoi(row[2]); deleted += delete_history("history", itemid, history, now); deleted += delete_history("history_uint", itemid, history, now); deleted += delete_history("history_str", itemid, history, now); deleted += delete_history("history_text", itemid, history, now); deleted += delete_history("history_log", itemid, history, now); deleted += delete_history("trends", itemid, trends, now); deleted += delete_history("trends_uint", itemid, trends, now); } DBfree_result(result); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __function_name, deleted); return deleted; }
/****************************************************************************** * * * Function: aggregate_get_items * * * * Purpose: get array of items specified by key for selected groups * * * * Parameters: itemids - [OUT] list of item ids * * groups - [IN] list of comma-separated host groups * * itemkey - [IN] item key to aggregate * * * ******************************************************************************/ static void aggregate_get_items(zbx_vector_uint64_t *itemids, const char *groups, const char *itemkey) { const char *__function_name = "aggregate_get_items"; char *group, *esc; DB_RESULT result; DB_ROW row; zbx_uint64_t itemid; char *sql = NULL; size_t sql_alloc = ZBX_KIBIBYTE, sql_offset = 0; int num, n; zabbix_log(LOG_LEVEL_DEBUG, "In %s() groups:'%s' itemkey:'%s'", __function_name, groups, itemkey); sql = zbx_malloc(sql, sql_alloc); esc = DBdyn_escape_string(itemkey); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select distinct i.itemid" " from items i,hosts h,hosts_groups hg,groups g" " where i.hostid=h.hostid" " and h.hostid=hg.hostid" " and hg.groupid=g.groupid" " and i.key_='%s'" " and i.status=%d" " and h.status=%d", esc, ITEM_STATUS_ACTIVE, HOST_STATUS_MONITORED); zbx_free(esc); num = num_param(groups); zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and g.name in ("); for (n = 1; n <= num; n++) { if (NULL == (group = get_param_dyn(groups, n))) continue; esc = DBdyn_escape_string(group); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "'%s'", esc); if (n != num) zbx_chrcpy_alloc(&sql, &sql_alloc, &sql_offset, ','); zbx_free(esc); zbx_free(group); } zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, ")" DB_NODE, DBnode_local("h.hostid")); result = DBselect("%s", sql); zbx_free(sql); while (NULL != (row = DBfetch(result))) { ZBX_STR2UINT64(itemid, row[0]); zbx_vector_uint64_append(itemids, itemid); } DBfree_result(result); zbx_vector_uint64_sort(itemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: main_alerter_loop * * * * Purpose: periodically check table alerts and send notifications if needed * * * * Parameters: * * * * Return value: * * * * Author: Alexei Vladishev * * * * Comments: never returns * * * ******************************************************************************/ int main_alerter_loop() { char error[MAX_STRING_LEN], *error_esc; int res, now; struct sigaction phan; DB_RESULT result; DB_ROW row; DB_ALERT alert; DB_MEDIATYPE mediatype; /* phan.sa_handler = child_signal_handler;*/ phan.sa_sigaction = child_signal_handler; sigemptyset(&phan.sa_mask); phan.sa_flags = SA_SIGINFO; sigaction(SIGALRM, &phan, NULL); zbx_setproctitle("connecting to the database"); DBconnect(ZBX_DB_CONNECT_NORMAL); for (;;) { 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))) { res = FAIL; 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_setproctitle("sender [sleeping for %d seconds]", CONFIG_SENDER_FREQUENCY); sleep(CONFIG_SENDER_FREQUENCY); } /* Never reached */ DBclose(); }
/****************************************************************************** * * * Function: housekeeping_cleanup * * * * Purpose: remove deleted items data * * * * Return value: number of rows deleted * * * * Author: Alexei Vladishev, Dmitry Borovikov * * * * Comments: sqlite3 does not use CONFIG_MAX_HOUSEKEEPER_DELETE, deletes all * * * ******************************************************************************/ static int housekeeping_cleanup() { const char *__function_name = "housekeeping_cleanup"; DB_HOUSEKEEPER housekeeper; DB_RESULT result; DB_ROW row; int d, deleted = 0; zbx_vector_uint64_t housekeeperids; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); zbx_vector_uint64_create(&housekeeperids); /* order by tablename to effectively use DB cache */ result = DBselect( "select housekeeperid,tablename,field,value" " from housekeeper" " order by tablename"); while (NULL != (row = DBfetch(result))) { ZBX_STR2UINT64(housekeeper.housekeeperid, row[0]); housekeeper.tablename = row[1]; housekeeper.field = row[2]; ZBX_STR2UINT64(housekeeper.value, row[3]); if (0 == CONFIG_MAX_HOUSEKEEPER_DELETE) { d = DBexecute( "delete from %s" " where %s=" ZBX_FS_UI64, housekeeper.tablename, housekeeper.field, housekeeper.value); } else { #if defined(HAVE_IBM_DB2) || defined(HAVE_ORACLE) d = DBexecute( "delete from %s" " where %s=" ZBX_FS_UI64 " and rownum<=%d", housekeeper.tablename, housekeeper.field, housekeeper.value, CONFIG_MAX_HOUSEKEEPER_DELETE); #elif defined(HAVE_MYSQL) d = DBexecute( "delete from %s" " where %s=" ZBX_FS_UI64 " limit %d", housekeeper.tablename, housekeeper.field, housekeeper.value, CONFIG_MAX_HOUSEKEEPER_DELETE); #elif defined(HAVE_POSTGRESQL) d = DBexecute( "delete from %s" " where ctid = any(array(select ctid from %s" " where %s=" ZBX_FS_UI64 " limit %d))", housekeeper.tablename, housekeeper.tablename, housekeeper.field, housekeeper.value, CONFIG_MAX_HOUSEKEEPER_DELETE); #elif defined(HAVE_SQLITE3) d = 0; #endif } if (0 == d || 0 == CONFIG_MAX_HOUSEKEEPER_DELETE || CONFIG_MAX_HOUSEKEEPER_DELETE > d) zbx_vector_uint64_append(&housekeeperids, housekeeper.housekeeperid); deleted += d; } DBfree_result(result); if (0 != housekeeperids.values_num) { char *sql = NULL; size_t sql_alloc = 512, sql_offset = 0; sql = zbx_malloc(sql, sql_alloc); zbx_vector_uint64_sort(&housekeeperids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from housekeeper where"); DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "housekeeperid", housekeeperids.values, housekeeperids.values_num); DBexecute("%s", sql); zbx_free(sql); } zbx_vector_uint64_destroy(&housekeeperids); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __function_name, deleted); return deleted; }
/****************************************************************************** * * * Function: update_checksums * * * * Purpose: overwrite old checksums with new ones * * * * Parameters: * * * * Return value: SUCCESS - calculated successfully * * FAIL - an error occurred * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ int update_checksums(int nodeid, int synked_nodetype, int synked, const char *tablename, const zbx_uint64_t id, const char *fields) { const char *__function_name = "update_checksums"; char *r[2], *d[2], sync[129], *s; char c[2], sql[2][256]; char cksum[32 * 72 + 72], *ck; char *exsql = NULL; size_t exsql_alloc = 64 * ZBX_KIBIBYTE, exsql_offset = 0; int cksumtype; DB_RESULT result; DB_ROW row; int f; const ZBX_TABLE *table; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); exsql = zbx_malloc(exsql, exsql_alloc); DBbegin(); DBbegin_multiple_update(&exsql, &exsql_alloc, &exsql_offset); c[0] = SUCCEED == synked ? '1' : ' '; /* for new and updated records */ c[1] = SUCCEED == synked ? '2' : ' '; /* for deleted records */ if (NULL != tablename) { zbx_snprintf(sql[0], sizeof(sql[0]), " and curr.tablename='%s' and curr.recordid=" ZBX_FS_UI64, tablename, id); zbx_snprintf(sql[1], sizeof(sql[1]), " and prev.tablename='%s' and prev.recordid=" ZBX_FS_UI64, tablename, id); } else { *sql[0] = '\0'; *sql[1] = '\0'; } result = DBselect( /* new records */ "select curr.tablename,curr.recordid,prev.cksum,curr.cksum,NULL" " from node_cksum curr" " left join node_cksum prev" " on prev.nodeid=curr.nodeid" " and prev.tablename=curr.tablename" " and prev.recordid=curr.recordid" " and prev.cksumtype=%d" " where curr.nodeid=%d" " and curr.cksumtype=%d" " and prev.tablename is null%s" " union all " /* updated records */ "select curr.tablename,curr.recordid,prev.cksum,curr.cksum,prev.sync" " from node_cksum curr, node_cksum prev" " where curr.nodeid=%d" " and prev.nodeid=curr.nodeid" " and curr.tablename=prev.tablename" " and curr.recordid=prev.recordid" " and curr.cksumtype=%d" " and prev.cksumtype=%d%s" " union all " /* deleted records */ "select prev.tablename,prev.recordid,prev.cksum,curr.cksum,prev.sync" " from node_cksum prev" " left join node_cksum curr" " on curr.nodeid=prev.nodeid" " and curr.tablename=prev.tablename" " and curr.recordid=prev.recordid" " and curr.cksumtype=%d" " where prev.nodeid=%d" " and prev.cksumtype=%d" " and curr.tablename is null%s", NODE_CKSUM_TYPE_OLD, nodeid, NODE_CKSUM_TYPE_NEW, sql[0], nodeid, NODE_CKSUM_TYPE_NEW, NODE_CKSUM_TYPE_OLD, sql[0], NODE_CKSUM_TYPE_NEW, nodeid, NODE_CKSUM_TYPE_OLD, sql[1]); while (NULL != (row = DBfetch(result))) { if (NULL == (table = DBget_table(row[0]))) { zabbix_log(LOG_LEVEL_WARNING, "cannot find table [%s]", row[0]); continue; } memset(sync, ' ', sizeof(sync)); if (FAIL == DBis_null(row[4])) memcpy(sync, row[4], strlen(row[4])); s = sync; ck = cksum; *ck = '\0'; /* special (simpler) processing for operation DELETE */ if (SUCCEED == DBis_null(row[3])) { if (SUCCEED == synked) s[synked_nodetype] = c[1]; if ((0 == CONFIG_MASTER_NODEID || s[1] == c[1]) && (CONFIG_NODEID == nodeid || s[0] == c[1])) { zbx_snprintf_alloc(&exsql, &exsql_alloc, &exsql_offset, "delete from node_cksum" " where nodeid=%d" " and cksumtype=%d" " and tablename='%s'" " and recordid=%s;\n", nodeid, NODE_CKSUM_TYPE_OLD, row[0], row[1]); DBexecute_overflowed_sql(&exsql, &exsql_alloc, &exsql_offset); continue; } s += 2; } else { r[0] = SUCCEED == DBis_null(row[2]) ? NULL : row[2]; r[1] = row[3]; f = 0; do { while ((table->fields[f].flags & ZBX_SYNC) == 0) f++; /* "host_inventory" table has more than 64 fields */ /* remaining fields are processed as one */ if (128 == s - sync) s -= 2; d[0] = NULL; d[1] = NULL; if (NULL != r[0] && NULL != (d[0] = strchr(r[0], ','))) *d[0] = '\0'; if (NULL != r[1] && NULL != (d[1] = strchr(r[1], ','))) *d[1] = '\0'; if (NULL == tablename || SUCCEED == str_in_list(fields, table->fields[f].name, ',')) { ck += zbx_snprintf(ck, 64, "%s,", NULL != r[1] ? r[1] : r[0]); if (NULL == r[0] || NULL == r[1] || 0 != strcmp(r[0], r[1])) { s[0] = s[1] = ' '; s[synked_nodetype] = c[0]; } else { if (SUCCEED == synked) s[synked_nodetype] = c[0]; } } else ck += zbx_snprintf(ck, 64, "%s,", NULL != r[0] ? r[0] : ""); s += 2; f++; if (d[0] != NULL) { *d[0] = ','; r[0] = d[0] + 1; } else r[0] = NULL; if (d[1] != NULL) { *d[1] = ','; r[1] = d[1] + 1; } else r[1] = NULL; } while (d[0] != NULL || d[1] != NULL); *--ck = '\0'; } *s = '\0'; if (SUCCEED == DBis_null(row[2]) || SUCCEED == DBis_null(row[3]) || 0 != strcmp(row[4], sync) || 0 != strcmp(row[2], row[3])) { cksumtype = (DBis_null(row[2]) == SUCCEED) ? NODE_CKSUM_TYPE_NEW : NODE_CKSUM_TYPE_OLD; zbx_snprintf_alloc(&exsql, &exsql_alloc, &exsql_offset, "update node_cksum" " set cksumtype=%d," "cksum='%s'," "sync='%s'" " where nodeid=%d" " and cksumtype=%d" " and tablename='%s'" " and recordid=%s;\n", NODE_CKSUM_TYPE_OLD, cksum, sync, nodeid, cksumtype, row[0], row[1]); DBexecute_overflowed_sql(&exsql, &exsql_alloc, &exsql_offset); } } DBfree_result(result); DBend_multiple_update(&exsql, &exsql_alloc, &exsql_offset); if (exsql_offset > 16) /* In ORACLE always present begin..end; */ DBexecute("%s", exsql); zbx_free(exsql); DBcommit(); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); return SUCCEED; }
/****************************************************************************** * * * Function: DMcolect_table_data * * * * Purpose: obtain configuration changes to required node * * * * Return value: SUCCESS - processed successfully * * FAIL - an error occurred * * * * Author: Alexander Vladishev * * * * Comments: the changes are collected into data parameter * * * ******************************************************************************/ static void DMcollect_table_data(int nodeid, unsigned char dest_nodetype, const ZBX_TABLE *table, char **data, size_t *data_alloc, size_t *data_offset) { #define ZBX_REC_UPDATED '1' #define ZBX_REC_DELETED '2' const char *__function_name = "DMcolect_table_data"; DB_RESULT result; DB_RESULT result2; DB_ROW row; DB_ROW row2; const char *s; char *hex = NULL, *sql = NULL, sync[128], *curr_cksum, *d_curr_cksum, *prev_cksum, *d_prev_cksum; size_t sql_alloc = 8 * ZBX_KIBIBYTE, sql_offset = 0, hex_alloc = ZBX_KIBIBYTE, rowlen; int f, j; zabbix_log(LOG_LEVEL_DEBUG, "In %s() table:'%s'", __function_name, table->table); hex = zbx_malloc(hex, hex_alloc); sql = zbx_malloc(sql, sql_alloc); result = DBselect( /* new records */ "select curr.recordid,prev.cksum,curr.cksum,curr.sync" " from node_cksum curr" " left join node_cksum prev" " on prev.nodeid=curr.nodeid" " and prev.tablename=curr.tablename" " and prev.recordid=curr.recordid" " and prev.cksumtype=%d" " where curr.nodeid=%d" " and curr.tablename='%s'" " and curr.cksumtype=%d" " and prev.tablename is null" " union all " /* updated records */ "select curr.recordid,prev.cksum,curr.cksum,prev.sync" " from node_cksum curr,node_cksum prev" " where curr.nodeid=prev.nodeid" " and curr.tablename=prev.tablename" " and curr.recordid=prev.recordid" " and curr.nodeid=%d" " and curr.tablename='%s'" " and curr.cksumtype=%d" " and prev.cksumtype=%d" " union all " /* deleted records */ "select prev.recordid,prev.cksum,curr.cksum,prev.sync" " from node_cksum prev" " left join node_cksum curr" " on curr.nodeid=prev.nodeid" " and curr.tablename=prev.tablename" " and curr.recordid=prev.recordid" " and curr.cksumtype=%d" " where prev.nodeid=%d" " and prev.tablename='%s'" " and prev.cksumtype=%d" " and curr.tablename is null", NODE_CKSUM_TYPE_OLD, nodeid, table->table, NODE_CKSUM_TYPE_NEW, nodeid, table->table, NODE_CKSUM_TYPE_NEW, NODE_CKSUM_TYPE_OLD, NODE_CKSUM_TYPE_NEW, nodeid, table->table, NODE_CKSUM_TYPE_OLD); while (NULL != (row = DBfetch(result))) { memset(sync, ' ', sizeof(sync)); memcpy(sync, row[3], strlen(row[3])); s = sync; /* special (simpler) processing for operation DELETE */ if (SUCCEED == DBis_null(row[2])) { if (ZBX_REC_DELETED != s[dest_nodetype]) { zbx_snprintf_alloc(data, data_alloc, data_offset, "\n%s%c%s%c%d", table->table, ZBX_DM_DELIMITER, row[0], ZBX_DM_DELIMITER, NODE_CONFIGLOG_OP_DELETE); } continue; } prev_cksum = (SUCCEED == DBis_null(row[1]) ? NULL : row[1]); curr_cksum = row[2]; f = 0; sql_offset = 0; zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select "); do { while (0 == (table->fields[f].flags & ZBX_SYNC)) f++; d_prev_cksum = NULL; if (NULL != prev_cksum && NULL != (d_prev_cksum = strchr(prev_cksum, ','))) *d_prev_cksum = '\0'; d_curr_cksum = NULL; if (NULL != curr_cksum && NULL != (d_curr_cksum = strchr(curr_cksum, ','))) *d_curr_cksum = '\0'; if (NULL == prev_cksum || NULL == curr_cksum || ZBX_REC_UPDATED != s[dest_nodetype] || 0 != strcmp(prev_cksum, curr_cksum)) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%s,", table->fields[f].name); if (table->fields[f].type == ZBX_TYPE_BLOB) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "length(%s),", table->fields[f].name); } } /* "host_inventory" table has more than 64 fields */ /* remaining fields are processed as one */ if (126 > s - sync) s += 2; f++; if (d_prev_cksum != NULL) { *d_prev_cksum = ','; prev_cksum = d_prev_cksum + 1; } else prev_cksum = NULL; if (d_curr_cksum != NULL) { *d_curr_cksum = ','; curr_cksum = d_curr_cksum + 1; } else curr_cksum = NULL; } while (NULL != d_prev_cksum || NULL != d_curr_cksum); if (sql[sql_offset - 1] != ',') continue; sql_offset--; zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " from %s where %s=%s", table->table, table->recid, row[0]); result2 = DBselect("%s", sql); if (NULL == (row2 = DBfetch(result2))) goto out; zbx_snprintf_alloc(data, data_alloc, data_offset, "\n%s%c%s%c%d", table->table, ZBX_DM_DELIMITER, row[0], ZBX_DM_DELIMITER, NODE_CONFIGLOG_OP_UPDATE); prev_cksum = DBis_null(row[1]) == SUCCEED ? NULL : row[1]; curr_cksum = row[2]; s = sync; f = 0; j = 0; do { while (0 == (table->fields[f].flags & ZBX_SYNC)) f++; d_prev_cksum = NULL; if (NULL != prev_cksum && NULL != (d_prev_cksum = strchr(prev_cksum, ','))) *d_prev_cksum = '\0'; d_curr_cksum = NULL; if (NULL != curr_cksum && NULL != (d_curr_cksum = strchr(curr_cksum, ','))) *d_curr_cksum = '\0'; if (NULL == prev_cksum || NULL == curr_cksum || ZBX_REC_UPDATED != s[dest_nodetype] || 0 != strcmp(prev_cksum, curr_cksum)) { /* fieldname, type */ zbx_snprintf_alloc(data, data_alloc, data_offset, "%c%s%c%d%c", ZBX_DM_DELIMITER, table->fields[f].name, ZBX_DM_DELIMITER, table->fields[f].type, ZBX_DM_DELIMITER); /* value */ if (SUCCEED == DBis_null(row2[j])) { zbx_strcpy_alloc(data, data_alloc, data_offset, "NULL"); } else if (ZBX_TYPE_INT == table->fields[f].type || ZBX_TYPE_UINT == table->fields[f].type || ZBX_TYPE_ID == table->fields[f].type || ZBX_TYPE_FLOAT == table->fields[f].type) { zbx_strcpy_alloc(data, data_alloc, data_offset, row2[j]); } else { if (table->fields[f].type == ZBX_TYPE_BLOB) rowlen = (size_t)atoi(row2[j + 1]); else rowlen = strlen(row2[j]); zbx_binary2hex((u_char *)row2[j], rowlen, &hex, &hex_alloc); zbx_strcpy_alloc(data, data_alloc, data_offset, hex); } if (table->fields[f].type == ZBX_TYPE_BLOB) j += 2; else j++; } /* "host_inventory" table has more than 64 fields */ /* remaining fields are processed as one */ if (126 > s - sync) s += 2; f++; if (d_prev_cksum != NULL) { *d_prev_cksum = ','; prev_cksum = d_prev_cksum + 1; } else prev_cksum = NULL; if (d_curr_cksum != NULL) { *d_curr_cksum = ','; curr_cksum = d_curr_cksum + 1; } else curr_cksum = NULL; } while (NULL != d_prev_cksum || NULL != d_curr_cksum); out: DBfree_result(result2); } DBfree_result(result); zbx_free(hex); zbx_free(sql); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: housekeeping_cleanup * * * * Purpose: remove deleted items data * * * * Return value: number of rows deleted * * * * Author: Alexei Vladishev, Dmitry Borovikov * * * * Comments: sqlite3 does not use CONFIG_MAX_HOUSEKEEPER_DELETE, deletes all * * * ******************************************************************************/ static int housekeeping_cleanup() { const char *__function_name = "housekeeping_cleanup"; DB_HOUSEKEEPER housekeeper; DB_RESULT result; DB_ROW row; int d, deleted = 0; zbx_vector_uint64_t housekeeperids; char *sql = NULL, *table_name_esc; size_t sql_alloc = 0, sql_offset = 0; zbx_hk_cleanup_table_t *table; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); /* first handle the trivial case when history and trend housekeeping is disabled */ if (ZBX_HK_OPTION_DISABLED == hk_config.history_mode && ZBX_HK_OPTION_DISABLED == hk_config.trends_mode) goto out; zbx_vector_uint64_create(&housekeeperids); zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select housekeeperid,tablename,field,value" " from housekeeper" " where tablename in ("); /* assemble list of tables excluded from housekeeping procedure */ for (table = hk_cleanup_tables; NULL != table->name; table++) { if (ZBX_HK_OPTION_ENABLED != *table->poption_mode) continue; table_name_esc = DBdyn_escape_string(table->name); zbx_chrcpy_alloc(&sql, &sql_alloc, &sql_offset, '\''); zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, table_name_esc); zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "',"); zbx_free(table_name_esc); } sql_offset--; /* order by tablename to effectively use DB cache */ zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ") order by tablename"); result = DBselect("%s", sql); while (NULL != (row = DBfetch(result))) { ZBX_STR2UINT64(housekeeper.housekeeperid, row[0]); housekeeper.tablename = row[1]; housekeeper.field = row[2]; ZBX_STR2UINT64(housekeeper.value, row[3]); if (0 == CONFIG_MAX_HOUSEKEEPER_DELETE) { d = DBexecute( "delete from %s" " where %s=" ZBX_FS_UI64, housekeeper.tablename, housekeeper.field, housekeeper.value); } else { #if defined(HAVE_IBM_DB2) || defined(HAVE_ORACLE) d = DBexecute( "delete from %s" " where %s=" ZBX_FS_UI64 " and rownum<=%d", housekeeper.tablename, housekeeper.field, housekeeper.value, CONFIG_MAX_HOUSEKEEPER_DELETE); #elif defined(HAVE_MYSQL) d = DBexecute( "delete from %s" " where %s=" ZBX_FS_UI64 " limit %d", housekeeper.tablename, housekeeper.field, housekeeper.value, CONFIG_MAX_HOUSEKEEPER_DELETE); #elif defined(HAVE_POSTGRESQL) d = DBexecute( "delete from %s" " where ctid = any(array(select ctid from %s" " where %s=" ZBX_FS_UI64 " limit %d))", housekeeper.tablename, housekeeper.tablename, housekeeper.field, housekeeper.value, CONFIG_MAX_HOUSEKEEPER_DELETE); #elif defined(HAVE_SQLITE3) d = 0; #endif } if (ZBX_DB_OK <= d) { if (0 == CONFIG_MAX_HOUSEKEEPER_DELETE || CONFIG_MAX_HOUSEKEEPER_DELETE > d) zbx_vector_uint64_append(&housekeeperids, housekeeper.housekeeperid); deleted += d; } } DBfree_result(result); if (0 != housekeeperids.values_num) { zbx_vector_uint64_sort(&housekeeperids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); sql_offset = 0; zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from housekeeper where"); DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "housekeeperid", housekeeperids.values, housekeeperids.values_num); DBexecute("%s", sql); } zbx_free(sql); zbx_vector_uint64_destroy(&housekeeperids); out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __function_name, deleted); return deleted; }
static void execute_operations(DB_ESCALATION *escalation, DB_EVENT *event, DB_ACTION *action) { const char *__function_name = "execute_operations"; DB_RESULT result; DB_ROW row; DB_OPERATION operation; int esc_period = 0, operations = 0; ZBX_USER_MSG *user_msg = NULL, *p; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (0 == action->esc_period) { result = DBselect( "select o.operationid,o.operationtype,o.esc_period,o.evaltype," "m.operationid,m.default_msg,subject,message,mediatypeid" " from operations o" " left join opmessage m" " on m.operationid=o.operationid" " where o.actionid=" ZBX_FS_UI64 " and o.operationtype in (%d,%d)", action->actionid, OPERATION_TYPE_MESSAGE, OPERATION_TYPE_COMMAND); } else { escalation->esc_step++; result = DBselect( "select o.operationid,o.operationtype,o.esc_period,o.evaltype," "m.operationid,m.default_msg,subject,message,mediatypeid" " from operations o" " left join opmessage m" " on m.operationid=o.operationid" " where o.actionid=" ZBX_FS_UI64 " and o.operationtype in (%d,%d)" " and o.esc_step_from<=%d" " and (o.esc_step_to=0 or o.esc_step_to>=%d)", action->actionid, OPERATION_TYPE_MESSAGE, OPERATION_TYPE_COMMAND, escalation->esc_step, escalation->esc_step); } while (NULL != (row = DBfetch(result))) { memset(&operation, 0, sizeof(operation)); ZBX_STR2UINT64(operation.operationid, row[0]); operation.actionid = action->actionid; operation.operationtype = atoi(row[1]); operation.esc_period = atoi(row[2]); operation.evaltype = (unsigned char)atoi(row[3]); if (SUCCEED == check_operation_conditions(event, operation.operationid, operation.evaltype)) { unsigned char default_msg; char *subject, *message; zbx_uint64_t mediatypeid; zabbix_log(LOG_LEVEL_DEBUG, "Conditions match our event. Execute operation."); if (0 == esc_period || esc_period > operation.esc_period) esc_period = operation.esc_period; switch (operation.operationtype) { case OPERATION_TYPE_MESSAGE: if (SUCCEED == DBis_null(row[4])) break; default_msg = (unsigned char)atoi(row[5]); ZBX_DBROW2UINT64(mediatypeid, row[8]); if (0 == default_msg) { subject = row[6]; message = row[7]; } else { subject = action->shortdata; message = action->longdata; } add_object_msg(operation.operationid, mediatypeid, &user_msg, subject, message, event->source, event->objectid); break; case OPERATION_TYPE_COMMAND: execute_commands(event, action->actionid, operation.operationid, escalation->esc_step); break; } } else zabbix_log(LOG_LEVEL_DEBUG, "Conditions do not match our event. Do not execute operation."); 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->mediatypeid, p->subject, p->message); zbx_free(p->subject); zbx_free(p->message); zbx_free(p); } if (0 == action->esc_period) { escalation->status = (action->recovery_msg == 1) ? ESCALATION_STATUS_SLEEP : 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 = (action->recovery_msg == 1) ? ESCALATION_STATUS_SLEEP : ESCALATION_STATUS_COMPLETED; } zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: get_template_items * * * * Purpose: read template items from database * * * * Parameters: hostid - [IN] host id * * templateids - [IN] array of template IDs * * items - [OUT] the item data * * * * Comments: The itemid and key are set depending on whether the item exists * * for the specified host. * * If item exists itemid will be set to its itemid and key will be * * set to NULL. * * If item does not exist, itemid will be set to 0 and key will be * * set to item key. * * * ******************************************************************************/ static void get_template_items(zbx_uint64_t hostid, const zbx_vector_uint64_t *templateids, zbx_vector_ptr_t *items) { DB_RESULT result; DB_ROW row; char *sql = NULL; size_t sql_alloc = 0, sql_offset = 0, i; unsigned char interface_type; zbx_template_item_t *item; zbx_uint64_t interfaceids[4]; memset(&interfaceids, 0, sizeof(interfaceids)); DBget_interfaces_by_hostid(hostid, interfaceids); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select ti.itemid,ti.name,ti.key_,ti.type,ti.value_type,ti.data_type,ti.delay,ti.delay_flex," "ti.history,ti.trends,ti.status,ti.trapper_hosts,ti.units,ti.multiplier,ti.delta," "ti.formula,ti.logtimefmt,ti.valuemapid,ti.params,ti.ipmi_sensor,ti.snmp_community," "ti.snmp_oid,ti.snmpv3_securityname,ti.snmpv3_securitylevel,ti.snmpv3_authprotocol," "ti.snmpv3_authpassphrase,ti.snmpv3_privprotocol,ti.snmpv3_privpassphrase,ti.authtype," "ti.username,ti.password,ti.publickey,ti.privatekey,ti.flags,ti.description," "ti.inventory_link,ti.lifetime,ti.snmpv3_contextname,hi.itemid,ti.evaltype,ti.port" " from items ti" " left join items hi on hi.key_=ti.key_" " and hi.hostid=" ZBX_FS_UI64 " where", hostid); DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "ti.hostid", templateids->values, templateids->values_num); result = DBselect("%s", sql); while (NULL != (row = DBfetch(result))) { item = zbx_malloc(NULL, sizeof(zbx_template_item_t)); ZBX_STR2UINT64(item->templateid, row[0]); ZBX_STR2UCHAR(item->type, row[3]); ZBX_STR2UCHAR(item->value_type, row[4]); ZBX_STR2UCHAR(item->data_type, row[5]); item->delay = atoi(row[6]); item->history = atoi(row[8]); item->trends = atoi(row[9]); ZBX_STR2UCHAR(item->status, row[10]); ZBX_STR2UCHAR(item->multiplier, row[13]); ZBX_STR2UCHAR(item->delta, row[14]); ZBX_DBROW2UINT64(item->valuemapid, row[17]); ZBX_STR2UCHAR(item->snmpv3_securitylevel, row[23]); ZBX_STR2UCHAR(item->snmpv3_authprotocol, row[24]); ZBX_STR2UCHAR(item->snmpv3_privprotocol, row[26]); ZBX_STR2UCHAR(item->authtype, row[28]); ZBX_STR2UCHAR(item->flags, row[33]); ZBX_STR2UCHAR(item->inventory_link, row[35]); ZBX_STR2UCHAR(item->evaltype, row[39]); switch (interface_type = get_interface_type_by_item_type(item->type)) { case INTERFACE_TYPE_UNKNOWN: item->interfaceid = 0; break; case INTERFACE_TYPE_ANY: for (i = 0; INTERFACE_TYPE_COUNT > i; i++) { if (0 != interfaceids[INTERFACE_TYPE_PRIORITY[i] - 1]) break; } item->interfaceid = interfaceids[INTERFACE_TYPE_PRIORITY[i] - 1]; break; default: item->interfaceid = interfaceids[interface_type - 1]; } item->name = zbx_strdup(NULL, row[1]); item->delay_flex = zbx_strdup(NULL, row[7]); item->trapper_hosts = zbx_strdup(NULL, row[11]); item->units = zbx_strdup(NULL, row[12]); item->formula = zbx_strdup(NULL, row[15]); item->logtimefmt = zbx_strdup(NULL, row[16]); item->params = zbx_strdup(NULL, row[18]); item->ipmi_sensor = zbx_strdup(NULL, row[19]); item->snmp_community = zbx_strdup(NULL, row[20]); item->snmp_oid = zbx_strdup(NULL, row[21]); item->snmpv3_securityname = zbx_strdup(NULL, row[22]); item->snmpv3_authpassphrase = zbx_strdup(NULL, row[25]); item->snmpv3_privpassphrase = zbx_strdup(NULL, row[27]); item->username = zbx_strdup(NULL, row[29]); item->password = zbx_strdup(NULL, row[30]); item->publickey = zbx_strdup(NULL, row[31]); item->privatekey = zbx_strdup(NULL, row[32]); item->description = zbx_strdup(NULL, row[34]); item->lifetime = zbx_strdup(NULL, row[36]); item->snmpv3_contextname = zbx_strdup(NULL, row[37]); item->port = zbx_strdup(NULL, row[40]); if (SUCCEED != DBis_null(row[38])) { item->key = NULL; ZBX_STR2UINT64(item->itemid, row[38]); } else { item->key = zbx_strdup(NULL, row[2]); item->itemid = 0; } zbx_vector_ptr_append(items, item); } DBfree_result(result); zbx_free(sql); zbx_vector_ptr_sort(items, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC); }
/****************************************************************************** * * * Function: save_template_item_applications * * * * Purpose: saves new item applications links in database * * * * Parameters: items - [IN] the template items * * * ******************************************************************************/ void save_template_item_applications(zbx_vector_ptr_t *items) { typedef struct { zbx_uint64_t itemid; zbx_uint64_t applicationid; } zbx_itemapp_t; DB_RESULT result; DB_ROW row; char *sql = NULL; size_t sql_alloc = 0, sql_offset = 0; zbx_vector_uint64_t itemids; zbx_vector_ptr_t itemapps; zbx_itemapp_t *itemapp; int i; zbx_db_insert_t db_insert; zbx_vector_ptr_create(&itemapps); zbx_vector_uint64_create(&itemids); for (i = 0; i < items->values_num; i++) { zbx_template_item_t *item = items->values[i]; zbx_vector_uint64_append(&itemids, item->itemid); } zbx_vector_uint64_sort(&itemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select hi.itemid,ha.applicationid" " from items_applications tia" " join items hi on hi.templateid=tia.itemid" " and"); DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hi.itemid", itemids.values, itemids.values_num); zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " join application_template hat on hat.templateid=tia.applicationid" " join applications ha on ha.applicationid=hat.applicationid" " and ha.hostid=hi.hostid" " left join items_applications hia on hia.applicationid=ha.applicationid" " and hia.itemid=hi.itemid" " where hia.itemappid is null"); result = DBselect("%s", sql); while (NULL != (row = DBfetch(result))) { itemapp = zbx_malloc(NULL, sizeof(zbx_itemapp_t)); ZBX_STR2UINT64(itemapp->itemid, row[0]); ZBX_STR2UINT64(itemapp->applicationid, row[1]); zbx_vector_ptr_append(&itemapps, itemapp); } DBfree_result(result); if (0 == itemapps.values_num) goto out; zbx_db_insert_prepare(&db_insert, "items_applications", "itemappid", "itemid", "applicationid", NULL); for (i = 0; i < itemapps.values_num; i++) { itemapp = itemapps.values[i]; zbx_db_insert_add_values(&db_insert, __UINT64_C(0), itemapp->itemid, itemapp->applicationid); } zbx_db_insert_autoincrement(&db_insert, "itemappid"); zbx_db_insert_execute(&db_insert); zbx_db_insert_clean(&db_insert); out: zbx_free(sql); zbx_vector_uint64_destroy(&itemids); zbx_vector_ptr_clear_ext(&itemapps, zbx_ptr_free); zbx_vector_ptr_destroy(&itemapps); }
/****************************************************************************** * * * Function: get_template_lld_rule_map * * * * Purpose: reads template lld rule conditions and host lld_rule identifiers * * from database * * * * Parameters: items - [IN] the host items including lld rules * * rules - [OUT] the ldd rule mapping * * * ******************************************************************************/ static void get_template_lld_rule_map(const zbx_vector_ptr_t *items, zbx_vector_ptr_t *rules) { zbx_template_item_t *item; zbx_lld_rule_map_t *rule; zbx_lld_rule_condition_t *condition; int i, index; zbx_vector_uint64_t itemids; DB_RESULT result; DB_ROW row; char *sql = NULL; size_t sql_alloc = 0, sql_offset = 0; zbx_uint64_t itemid, item_conditionid; zbx_vector_uint64_create(&itemids); /* prepare discovery rules */ for (i = 0; i < items->values_num; i++) { item = items->values[i]; if (0 == (ZBX_FLAG_DISCOVERY_RULE & item->flags)) continue; rule = zbx_malloc(NULL, sizeof(zbx_lld_rule_map_t)); rule->itemid = item->itemid; rule->templateid = item->templateid; rule->conditionid = 0; zbx_vector_uint64_create(&rule->conditionids); zbx_vector_ptr_create(&rule->conditions); zbx_vector_ptr_append(rules, rule); if (0 != rule->itemid) zbx_vector_uint64_append(&itemids, rule->itemid); zbx_vector_uint64_append(&itemids, rule->templateid); } if (0 != itemids.values_num) { zbx_vector_ptr_sort(rules, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC); zbx_vector_uint64_sort(&itemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select item_conditionid,itemid,operator,macro,value from item_condition where"); DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid", itemids.values, itemids.values_num); result = DBselect("%s", sql); while (NULL != (row = DBfetch(result))) { ZBX_STR2UINT64(itemid, row[1]); index = zbx_vector_ptr_bsearch(rules, &itemid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC); if (FAIL != index) { /* read template lld conditions */ rule = (zbx_lld_rule_map_t *)rules->values[index]; condition = zbx_malloc(NULL, sizeof(zbx_lld_rule_condition_t)); ZBX_STR2UINT64(condition->item_conditionid, row[0]); ZBX_STR2UCHAR(condition->operator, row[2]); condition->macro = zbx_strdup(NULL, row[3]); condition->value = zbx_strdup(NULL, row[4]); zbx_vector_ptr_append(&rule->conditions, condition); } else { /* read host lld conditions identifiers */ for (i = 0; i < rules->values_num; i++) { rule = (zbx_lld_rule_map_t *)rules->values[i]; if (itemid != rule->itemid) continue; ZBX_STR2UINT64(item_conditionid, row[0]); zbx_vector_uint64_append(&rule->conditionids, item_conditionid); break; } if (i == rules->values_num) THIS_SHOULD_NEVER_HAPPEN; } } DBfree_result(result); zbx_free(sql); } zbx_vector_uint64_destroy(&itemids); }
static void execute_commands(DB_EVENT *event, zbx_uint64_t actionid, zbx_uint64_t operationid, int esc_step) { const char *__function_name = "execute_commands"; DB_RESULT result; DB_ROW row; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); result = DBselect( "select distinct h.hostid,h.host,o.type,o.scriptid,o.execute_on,o.port" ",o.authtype,o.username,o.password,o.publickey,o.privatekey,o.command" #ifdef HAVE_OPENIPMI ",h.ipmi_authtype,h.ipmi_privilege,h.ipmi_username,h.ipmi_password" #endif " from opcommand o,opcommand_grp og,hosts_groups hg,hosts h" " where o.operationid=og.operationid" " and og.groupid=hg.groupid" " and hg.hostid=h.hostid" " and o.operationid=" ZBX_FS_UI64 " and h.status=%d" " union " "select distinct h.hostid,h.host,o.type,o.scriptid,o.execute_on,o.port" ",o.authtype,o.username,o.password,o.publickey,o.privatekey,o.command" #ifdef HAVE_OPENIPMI ",h.ipmi_authtype,h.ipmi_privilege,h.ipmi_username,h.ipmi_password" #endif " from opcommand o,opcommand_hst oh,hosts h" " where o.operationid=oh.operationid" " and oh.hostid=h.hostid" " and o.operationid=" ZBX_FS_UI64 " and h.status=%d" " union " "select distinct 0,null,o.type,o.scriptid,o.execute_on,o.port" ",o.authtype,o.username,o.password,o.publickey,o.privatekey,o.command" #ifdef HAVE_OPENIPMI ",0,2,null,null" #endif " from opcommand o,opcommand_hst oh" " where o.operationid=oh.operationid" " and o.operationid=" ZBX_FS_UI64 " and oh.hostid is null", operationid, HOST_STATUS_MONITORED, operationid, HOST_STATUS_MONITORED, operationid); while (NULL != (row = DBfetch(result))) { int rc = SUCCEED; char error[ALERT_ERROR_LEN_MAX]; DC_HOST host; zbx_script_t script; zbx_alert_status_t status; *error = '\0'; memset(&host, 0, sizeof(host)); zbx_script_init(&script); ZBX_STR2UINT64(host.hostid, row[0]); if (0 != host.hostid) { strscpy(host.host, row[1]); #ifdef HAVE_OPENIPMI host.ipmi_authtype = (signed char)atoi(row[12]); host.ipmi_privilege = (unsigned char)atoi(row[13]); strscpy(host.ipmi_username, row[14]); strscpy(host.ipmi_password, row[15]); #endif } else rc = get_dynamic_hostid(event, &host, error, sizeof(error)); script.type = (unsigned char)atoi(row[2]); if (ZBX_SCRIPT_TYPE_GLOBAL_SCRIPT != script.type) { script.command = zbx_strdup(script.command, row[11]); substitute_simple_macros(event, NULL, NULL, NULL, NULL, NULL, &script.command, MACRO_TYPE_MESSAGE, NULL, 0); } if (SUCCEED == rc) { switch (script.type) { case ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT: script.execute_on = (unsigned char)atoi(row[4]); break; case ZBX_SCRIPT_TYPE_SSH: script.authtype = (unsigned char)atoi(row[6]); script.publickey = zbx_strdup(script.publickey, row[9]); script.privatekey = zbx_strdup(script.privatekey, row[10]); /* break; is not missing here */ case ZBX_SCRIPT_TYPE_TELNET: script.port = zbx_strdup(script.port, row[5]); script.username = zbx_strdup(script.username, row[7]); script.password = zbx_strdup(script.password, row[8]); break; case ZBX_SCRIPT_TYPE_GLOBAL_SCRIPT: ZBX_DBROW2UINT64(script.scriptid, row[3]); break; } rc = zbx_execute_script(&host, &script, NULL, error, sizeof(error)); } status = (SUCCEED != rc ? ALERT_STATUS_FAILED : ALERT_STATUS_SENT); add_command_alert(&host, event->eventid, actionid, esc_step, script.command, status, error); zbx_script_clean(&script); } DBfree_result(result); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: save_template_discovery_prototypes * * * * Purpose: saves host item prototypes in database * * * * Parameters: hostid - [IN] the target host * * items - [IN] the template items * * * ******************************************************************************/ void save_template_discovery_prototypes(zbx_uint64_t hostid, zbx_vector_ptr_t *items) { typedef struct { zbx_uint64_t itemid; zbx_uint64_t parent_itemid; } zbx_proto_t; DB_RESULT result; DB_ROW row; char *sql = NULL; size_t sql_alloc = 0, sql_offset = 0; zbx_vector_uint64_t itemids; zbx_vector_ptr_t prototypes; zbx_proto_t *proto; int i; zbx_db_insert_t db_insert; zbx_vector_ptr_create(&prototypes); zbx_vector_uint64_create(&itemids); for (i = 0; i < items->values_num; i++) { zbx_template_item_t *item = items->values[i]; /* process only new prototype items */ if (NULL == item->key || 0 == (ZBX_FLAG_DISCOVERY_PROTOTYPE & item->flags)) continue; zbx_vector_uint64_append(&itemids, item->itemid); } if (0 == itemids.values_num) goto out; zbx_vector_uint64_sort(&itemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select i.itemid,r.itemid" " from items i,item_discovery id,items r" " where i.templateid=id.itemid" " and id.parent_itemid=r.templateid" " and r.hostid=" ZBX_FS_UI64 " and", hostid); DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "i.itemid", itemids.values, itemids.values_num); result = DBselect("%s", sql); while (NULL != (row = DBfetch(result))) { proto = zbx_malloc(NULL, sizeof(zbx_proto_t)); ZBX_STR2UINT64(proto->itemid, row[0]); ZBX_STR2UINT64(proto->parent_itemid, row[1]); zbx_vector_ptr_append(&prototypes, proto); } DBfree_result(result); if (0 == prototypes.values_num) goto out; zbx_db_insert_prepare(&db_insert, "item_discovery", "itemdiscoveryid", "itemid", "parent_itemid", NULL); for (i = 0; i < prototypes.values_num; i++) { proto = prototypes.values[i]; zbx_db_insert_add_values(&db_insert, __UINT64_C(0), proto->itemid, proto->parent_itemid); } zbx_db_insert_autoincrement(&db_insert, "itemdiscoveryid"); zbx_db_insert_execute(&db_insert); zbx_db_insert_clean(&db_insert); out: zbx_free(sql); zbx_vector_uint64_destroy(&itemids); zbx_vector_ptr_clear_ext(&prototypes, zbx_ptr_free); zbx_vector_ptr_destroy(&prototypes); }
static void add_message_alert(DB_ESCALATION *escalation, DB_EVENT *event, DB_ACTION *action, zbx_uint64_t userid, zbx_uint64_t mediatypeid, const char *subject, const char *message) { const char *__function_name = "add_message_alert"; DB_RESULT result; DB_ROW row; zbx_uint64_t alertid; int now, severity, medias = 0; char *subject_dyn, *message_dyn, *sendto_esc, *subject_esc, *message_esc, *error_esc; char error[MAX_STRING_LEN]; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); subject_dyn = zbx_strdup(NULL, subject); message_dyn = zbx_strdup(NULL, message); substitute_simple_macros(event, &userid, NULL, NULL, NULL, NULL, &subject_dyn, MACRO_TYPE_MESSAGE, NULL, 0); substitute_simple_macros(event, &userid, NULL, NULL, NULL, NULL, &message_dyn, MACRO_TYPE_MESSAGE, NULL, 0); now = time(NULL); subject_esc = DBdyn_escape_string_len(subject_dyn, ALERT_SUBJECT_LEN); message_esc = DBdyn_escape_string_len(message_dyn, ALERT_MESSAGE_LEN); zbx_free(subject_dyn); zbx_free(message_dyn); if (0 == mediatypeid) { result = DBselect( "select m.mediatypeid,m.sendto,m.severity,m.period,mt.status" " from media m,media_type mt" " where m.mediatypeid=mt.mediatypeid" " and m.active=%d" " and m.userid=" ZBX_FS_UI64, MEDIA_STATUS_ACTIVE, userid); } else { result = DBselect( "select m.mediatypeid,m.sendto,m.severity,m.period,mt.status" " from media m,media_type mt" " where m.mediatypeid=mt.mediatypeid" " and m.active=%d" " and m.userid=" ZBX_FS_UI64 " and m.mediatypeid=" ZBX_FS_UI64, MEDIA_STATUS_ACTIVE, userid, mediatypeid); } while (NULL != (row = DBfetch(result))) { medias = 1; ZBX_STR2UINT64(mediatypeid, row[0]); severity = atoi(row[2]); zabbix_log(LOG_LEVEL_DEBUG, "Trigger severity [%d] Media severity [%d] Period [%s]", (int)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 (FAIL == check_time_period(row[3], (time_t)NULL)) { zabbix_log(LOG_LEVEL_DEBUG, "Won't send message (period)"); continue; } alertid = DBget_maxid("alerts"); sendto_esc = DBdyn_escape_string_len(row[1], ALERT_SENDTO_LEN); if (MEDIA_TYPE_STATUS_ACTIVE == atoi(row[4])) { 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); } else { error_esc = DBdyn_escape_string("Media type disabled"); DBexecute("insert into alerts (alertid,actionid,eventid,userid,clock" ",mediatypeid,sendto,subject,message,status,alerttype,esc_step,error)" " values (" ZBX_FS_UI64 "," ZBX_FS_UI64 "," ZBX_FS_UI64 "," ZBX_FS_UI64 ",%d" "," ZBX_FS_UI64 ",'%s','%s','%s',%d,%d,%d,'%s')", alertid, action->actionid, event->eventid, userid, now, mediatypeid, sendto_esc, subject_esc, message_esc, ALERT_STATUS_FAILED, ALERT_TYPE_MESSAGE, escalation->esc_step, error_esc); zbx_free(error_esc); } zbx_free(sendto_esc); } DBfree_result(result); if (0 == medias) { zbx_snprintf(error, sizeof(error), "No media defined for user \"%s\"", zbx_user_string(userid)); alertid = DBget_maxid("alerts"); error_esc = DBdyn_escape_string(error); DBexecute("insert into alerts (alertid,actionid,eventid,userid,retries,clock" ",subject,message,status,alerttype,error,esc_step)" " values (" ZBX_FS_UI64 "," ZBX_FS_UI64 "," ZBX_FS_UI64 "," ZBX_FS_UI64 ",%d,%d" ",'%s','%s',%d,%d,'%s',%d)", alertid, action->actionid, event->eventid, userid, ALERT_MAX_RETRIES, 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); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: evaluate_aggregate * * * * Parameters: item - [IN] aggregated item * * grp_func - [IN] one of ZBX_GRP_FUNC_* * * groups - [IN] list of comma-separated host groups * * itemkey - [IN] item key to aggregate * * item_func - [IN] one of ZBX_DB_GET_HIST_* * * param - [IN] item_func parameter (optional) * * * * Return value: SUCCEED - aggregate item evaluated successfully * * FAIL - otherwise * * * ******************************************************************************/ static int evaluate_aggregate(DC_ITEM *item, AGENT_RESULT *res, int grp_func, const char *groups, const char *itemkey, int item_func, const char *param) { const char *__function_name = "evaluate_aggregate"; char *sql = NULL; size_t sql_alloc = 1024, sql_offset = 0; zbx_uint64_t itemid; zbx_vector_uint64_t itemids; DB_RESULT result; DB_ROW row; unsigned char value_type; history_value_t value; int num = 0, ret = FAIL; zabbix_log(LOG_LEVEL_DEBUG, "In %s() grp_func:%d groups:'%s' itemkey:'%s' item_func:%d param:'%s'", __function_name, grp_func, groups, itemkey, item_func, param); memset(&value, 0, sizeof(value)); zbx_vector_uint64_create(&itemids); aggregate_get_items(&itemids, groups, itemkey); if (0 == itemids.values_num) { SET_MSG_RESULT(res, zbx_dsprintf(NULL, "No items for key [%s] in group(s) [%s]", itemkey, groups)); goto clean; } sql = zbx_malloc(sql, sql_alloc); if (ZBX_DB_GET_HIST_VALUE == item_func) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select value_type,lastvalue" " from items" " where lastvalue is not null" " and value_type in (%d,%d)" " and", ITEM_VALUE_TYPE_FLOAT, ITEM_VALUE_TYPE_UINT64); DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid", itemids.values, itemids.values_num); result = DBselect("%s", sql); while (NULL != (row = DBfetch(result))) { value_type = (unsigned char)atoi(row[0]); evaluate_one(item, &value, &num, grp_func, row[1], value_type); } DBfree_result(result); } else { int clock_from; unsigned int period; char **h_value; if (FAIL == is_uint_suffix(param, &period)) { SET_MSG_RESULT(res, zbx_strdup(NULL, "Invalid fourth parameter")); goto clean; } clock_from = time(NULL) - period; zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select itemid,value_type" " from items" " where value_type in (%d,%d)" " and", ITEM_VALUE_TYPE_FLOAT, ITEM_VALUE_TYPE_UINT64); DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid", itemids.values, itemids.values_num); result = DBselect("%s", sql); while (NULL != (row = DBfetch(result))) { ZBX_STR2UINT64(itemid, row[0]); value_type = (unsigned char)atoi(row[1]); h_value = DBget_history(itemid, value_type, item_func, clock_from, 0, NULL, NULL, 0); if (NULL != h_value[0]) evaluate_one(item, &value, &num, grp_func, h_value[0], value_type); DBfree_history(h_value); } DBfree_result(result); } if (0 == num) { SET_MSG_RESULT(res, zbx_dsprintf(NULL, "No values for key \"%s\" in group(s) \"%s\"", itemkey, groups)); goto clean; } if (ZBX_GRP_FUNC_AVG == grp_func) { switch (item->value_type) { case ITEM_VALUE_TYPE_FLOAT: value.dbl = value.dbl / num; break; case ITEM_VALUE_TYPE_UINT64: value.ui64 = value.ui64 / num; break; default: assert(0); } } if (ITEM_VALUE_TYPE_FLOAT == item->value_type) SET_DBL_RESULT(res, value.dbl); else SET_UI64_RESULT(res, value.ui64); ret = SUCCEED; clean: zbx_vector_uint64_destroy(&itemids); zbx_free(sql); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
/****************************************************************************** * * * 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, zbx_uint64_t operationid, unsigned char evaltype) { const char *__function_name = "check_operation_conditions"; DB_RESULT result; DB_ROW row; DB_CONDITION condition; int ret = SUCCEED; /* SUCCEED required for ACTION_EVAL_TYPE_AND_OR */ int cond, old_type = -1, exit = 0; zabbix_log(LOG_LEVEL_DEBUG, "In %s() operationid:" ZBX_FS_UI64, __function_name, operationid); result = DBselect("select conditiontype,operator,value" " from opconditions" " where operationid=" ZBX_FS_UI64 " order by conditiontype", operationid); while (NULL != (row = DBfetch(result)) && 0 == exit) { memset(&condition, 0, sizeof(condition)); condition.conditiontype = atoi(row[0]); condition.operator = atoi(row[1]); condition.value = row[2]; switch (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 of %s():%s", __function_name, zbx_result_string(ret)); return ret; }