/****************************************************************************** * * * Function: process_deleted_records * * * * Purpose: * * * * Parameters: * * * * Return value: * * * * Author: Alexander Vladishev * * * * Comments: * * * ******************************************************************************/ static void process_deleted_records(int nodeid, char *data, int sender_nodetype) { const char *__function_name = "process_deleted_records"; char *r, *lf; const ZBX_TABLE *table = NULL; zbx_uint64_t recid, *ids = NULL; int ids_alloc = 0, ids_num = 0; char *sql = NULL; size_t sql_alloc = 4 * ZBX_KIBIBYTE, sql_offset = 0; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); sql = zbx_malloc(sql, sql_alloc); DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset); for (r = data; '\0' != *r;) { if (NULL != (lf = strchr(r, '\n'))) *lf = '\0'; zbx_get_next_field((const char **)&r, &buf, &buf_alloc, ZBX_DM_DELIMITER); if (NULL == table || 0 != strcmp(table->table, buf)) { make_delete_sql(&sql, &sql_alloc, &sql_offset, table, ids, &ids_num); if (NULL == (table = DBget_table(buf))) { zabbix_log(LOG_LEVEL_DEBUG, "%s(): cannot find table [%s]", __function_name, buf); goto next; } } zbx_get_next_field((const char **)&r, &buf, &buf_alloc, ZBX_DM_DELIMITER); ZBX_STR2UINT64(recid, buf); if ('2' == *r) /* NODE_CONFIGLOG_OP_DELETE */ uint64_array_add(&ids, &ids_alloc, &ids_num, recid, 64); next: if (lf != NULL) { *lf++ = '\n'; r = lf; } else break; } make_delete_sql(&sql, &sql_alloc, &sql_offset, table, ids, &ids_num); DBend_multiple_update(&sql, &sql_alloc, &sql_offset); if (sql_offset > 16) /* In ORACLE always present begin..end; */ DBexecute("%s", sql); zbx_free(sql); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: get_values * * * * Purpose: retrieve values of metrics from monitored hosts * * * * Parameters: * * * * Return value: * * * * Author: Alexei Vladishev * * * * Comments: always SUCCEED * * * ******************************************************************************/ static int get_values(unsigned char poller_type) { const char *__function_name = "get_values"; DC_ITEM items[MAX_REACHABLE_ITEMS]; AGENT_RESULT agent; zbx_uint64_t *ids = NULL, *snmpids = NULL, *ipmiids = NULL; int ids_alloc = 0, snmpids_alloc = 0, ipmiids_alloc = 0, ids_num = 0, snmpids_num = 0, ipmiids_num = 0, i, now, num, res; static char *key = NULL, *ipmi_ip = NULL, *params = NULL, *username = NULL, *publickey = NULL, *privatekey = NULL, *password = NULL, *snmp_community = NULL, *snmp_oid = NULL, *snmpv3_securityname = NULL, *snmpv3_authpassphrase = NULL, *snmpv3_privpassphrase = NULL; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); num = DCconfig_get_poller_items(poller_type, items, ZBX_POLLER_TYPE_UNREACHABLE != poller_type ? MAX_REACHABLE_ITEMS : MAX_UNREACHABLE_ITEMS); for (i = 0; i < num; i++) { zbx_free(key); key = strdup(items[i].key_orig); substitute_simple_macros(NULL, NULL, NULL, &items[i], NULL, &key, MACRO_TYPE_ITEM_KEY, NULL, 0); items[i].key = key; switch (items[i].type) { case ITEM_TYPE_SNMPv3: zbx_free(snmpv3_securityname); zbx_free(snmpv3_authpassphrase); zbx_free(snmpv3_privpassphrase); snmpv3_securityname = strdup(items[i].snmpv3_securityname_orig); snmpv3_authpassphrase = strdup(items[i].snmpv3_authpassphrase_orig); snmpv3_privpassphrase = strdup(items[i].snmpv3_privpassphrase_orig); substitute_simple_macros(NULL, NULL, NULL, &items[i], NULL, &snmpv3_securityname, MACRO_TYPE_ITEM_FIELD, NULL, 0); substitute_simple_macros(NULL, NULL, NULL, &items[i], NULL, &snmpv3_authpassphrase, MACRO_TYPE_ITEM_FIELD, NULL, 0); substitute_simple_macros(NULL, NULL, NULL, &items[i], NULL, &snmpv3_privpassphrase, MACRO_TYPE_ITEM_FIELD, NULL, 0); items[i].snmpv3_securityname = snmpv3_securityname; items[i].snmpv3_authpassphrase = snmpv3_authpassphrase; items[i].snmpv3_privpassphrase = snmpv3_privpassphrase; case ITEM_TYPE_SNMPv1: case ITEM_TYPE_SNMPv2c: zbx_free(snmp_community); zbx_free(snmp_oid); snmp_community = strdup(items[i].snmp_community_orig); snmp_oid = strdup(items[i].snmp_oid_orig); substitute_simple_macros(NULL, NULL, NULL, &items[i], NULL, &snmp_community, MACRO_TYPE_ITEM_FIELD, NULL, 0); substitute_simple_macros(NULL, NULL, NULL, &items[i], NULL, &snmp_oid, MACRO_TYPE_ITEM_FIELD, NULL, 0); items[i].snmp_community = snmp_community; items[i].snmp_oid = snmp_oid; break; case ITEM_TYPE_IPMI: zbx_free(ipmi_ip); ipmi_ip = strdup(items[i].host.ipmi_ip_orig); substitute_simple_macros(NULL, NULL, NULL, &items[i], NULL, &ipmi_ip, MACRO_TYPE_HOST_IPMI_IP, NULL, 0); items[i].host.ipmi_ip = ipmi_ip; break; case ITEM_TYPE_DB_MONITOR: zbx_free(params); params = strdup(items[i].params_orig); substitute_simple_macros(NULL, NULL, NULL, &items[i], NULL, ¶ms, MACRO_TYPE_ITEM_FIELD, NULL, 0); items[i].params = params; break; case ITEM_TYPE_SSH: zbx_free(username); zbx_free(publickey); zbx_free(privatekey); zbx_free(password); zbx_free(params); username = strdup(items[i].username_orig); publickey = strdup(items[i].publickey_orig); privatekey = strdup(items[i].privatekey_orig); password = strdup(items[i].password_orig); params = strdup(items[i].params_orig); substitute_simple_macros(NULL, NULL, NULL, &items[i], NULL, &username, MACRO_TYPE_ITEM_FIELD, NULL, 0); substitute_simple_macros(NULL, NULL, NULL, &items[i], NULL, &publickey, MACRO_TYPE_ITEM_FIELD, NULL, 0); substitute_simple_macros(NULL, NULL, NULL, &items[i], NULL, &privatekey, MACRO_TYPE_ITEM_FIELD, NULL, 0); substitute_simple_macros(NULL, NULL, NULL, &items[i], NULL, &password, MACRO_TYPE_ITEM_FIELD, NULL, 0); substitute_simple_macros(NULL, NULL, NULL, &items[i], NULL, ¶ms, MACRO_TYPE_ITEM_FIELD, NULL, 0); items[i].username = username; items[i].publickey = publickey; items[i].privatekey = privatekey; items[i].password = password; items[i].params = params; break; case ITEM_TYPE_TELNET: zbx_free(username); zbx_free(password); zbx_free(params); username = strdup(items[i].username_orig); password = strdup(items[i].password_orig); params = strdup(items[i].params_orig); substitute_simple_macros(NULL, NULL, NULL, &items[i], NULL, &username, MACRO_TYPE_ITEM_FIELD, NULL, 0); substitute_simple_macros(NULL, NULL, NULL, &items[i], NULL, &password, MACRO_TYPE_ITEM_FIELD, NULL, 0); substitute_simple_macros(NULL, NULL, NULL, &items[i], NULL, ¶ms, MACRO_TYPE_ITEM_FIELD, NULL, 0); items[i].username = username; items[i].password = password; items[i].params = params; break; } /* Skip unreachable hosts but do not break the loop. */ switch (items[i].type) { case ITEM_TYPE_ZABBIX: if (SUCCEED == uint64_array_exists(ids, ids_num, items[i].host.hostid)) { DCrequeue_unreachable_item(items[i].itemid); zabbix_log(LOG_LEVEL_DEBUG, "Zabbix Host " ZBX_FS_UI64 " is unreachable. Skipping [%s]", items[i].host.hostid, items[i].key_orig); continue; } break; case ITEM_TYPE_SNMPv1: case ITEM_TYPE_SNMPv2c: case ITEM_TYPE_SNMPv3: if (SUCCEED == uint64_array_exists(snmpids, snmpids_num, items[i].host.hostid)) { DCrequeue_unreachable_item(items[i].itemid); zabbix_log(LOG_LEVEL_DEBUG, "SNMP Host " ZBX_FS_UI64 " is unreachable. Skipping [%s]", items[i].host.hostid, items[i].key_orig); continue; } break; case ITEM_TYPE_IPMI: if (SUCCEED == uint64_array_exists(ipmiids, ipmiids_num, items[i].host.hostid)) { DCrequeue_unreachable_item(items[i].itemid); zabbix_log(LOG_LEVEL_DEBUG, "IPMI Host " ZBX_FS_UI64 " is unreachable. Skipping [%s]", items[i].host.hostid, items[i].key_orig); continue; } break; default: /* nothing to do */; } init_result(&agent); res = get_value(&items[i], &agent); now = time(NULL); if (res == SUCCEED) { activate_host(&items[i], now); dc_add_history(items[i].itemid, items[i].value_type, &agent, now, ITEM_STATUS_ACTIVE, NULL, 0, NULL, 0, 0, 0, 0); DCrequeue_reachable_item(items[i].itemid, ITEM_STATUS_ACTIVE, now); } else if (res == NOTSUPPORTED || res == AGENT_ERROR) { activate_host(&items[i], now); dc_add_history(items[i].itemid, items[i].value_type, NULL, now, ITEM_STATUS_NOTSUPPORTED, agent.msg, 0, NULL, 0, 0, 0, 0); DCrequeue_reachable_item(items[i].itemid, ITEM_STATUS_NOTSUPPORTED, now); } else if (res == NETWORK_ERROR) { deactivate_host(&items[i], now, agent.msg); switch (items[i].type) { case ITEM_TYPE_ZABBIX: uint64_array_add(&ids, &ids_alloc, &ids_num, items[i].host.hostid, 1); break; case ITEM_TYPE_SNMPv1: case ITEM_TYPE_SNMPv2c: case ITEM_TYPE_SNMPv3: uint64_array_add(&snmpids, &snmpids_alloc, &snmpids_num, items[i].host.hostid, 1); break; case ITEM_TYPE_IPMI: uint64_array_add(&ipmiids, &ipmiids_alloc, &ipmiids_num, items[i].host.hostid, 1); break; default: /* nothing to do */; } DCrequeue_unreachable_item(items[i].itemid); } else { zbx_error("unknown response code returned: %d", res); assert(0); } free_result(&agent); } zbx_free(key); zbx_free(ipmi_ip); zbx_free(params); zbx_free(username); zbx_free(publickey); zbx_free(privatekey); zbx_free(password); zbx_free(snmp_community); zbx_free(snmp_oid); zbx_free(snmpv3_securityname); zbx_free(snmpv3_authpassphrase); zbx_free(snmpv3_privpassphrase); zbx_free(ids); zbx_free(snmpids); zbx_free(ipmiids); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); return num; }
static void update_maintenance_hosts(zbx_host_maintenance_t *hm, int hm_count, int now) { typedef struct { zbx_uint64_t hostid; int maintenance_from; void *next; } maintenance_t; const char *__function_name = "update_maintenance_hosts"; int i; zbx_uint64_t *ids = NULL, hostid; int ids_alloc = 0, ids_num = 0; DB_RESULT result; DB_ROW row; char *sql = NULL; size_t sql_alloc = ZBX_KIBIBYTE, sql_offset; maintenance_t *maintenances = NULL, *m; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); sql = zbx_malloc(sql, sql_alloc); DBbegin(); for (i = 0; i < hm_count; i++) { if (SUCCEED == uint64_array_exists(ids, ids_num, hm[i].hostid)) continue; if (hm[i].host_maintenanceid != hm[i].maintenanceid || HOST_MAINTENANCE_STATUS_ON != hm[i].host_maintenance_status || hm[i].host_maintenance_type != hm[i].maintenance_type || 0 == hm[i].host_maintenance_from) { zabbix_log(LOG_LEVEL_WARNING, "putting host [%s] into maintenance (with%s data collection)", hm[i].host, MAINTENANCE_TYPE_NORMAL == hm[i].maintenance_type ? "" : "out"); sql_offset = 0; zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update hosts" " set maintenanceid=" ZBX_FS_UI64 "," "maintenance_status=%d," "maintenance_type=%d", hm[i].maintenanceid, HOST_MAINTENANCE_STATUS_ON, hm[i].maintenance_type); if (0 == hm[i].host_maintenance_from) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, ",maintenance_from=%d", hm[i].maintenance_from); } zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " where hostid=" ZBX_FS_UI64, hm[i].hostid); DBexecute("%s", sql); DCconfig_set_maintenance(&hm[i].hostid, 1, HOST_MAINTENANCE_STATUS_ON, hm[i].maintenance_type, hm[i].maintenance_from); } uint64_array_add(&ids, &ids_alloc, &ids_num, hm[i].hostid, 4); } sql_offset = 0; zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select hostid,host,maintenance_type,maintenance_from" " from hosts" " where status=%d" " and flags<>%d" " and maintenance_status=%d", HOST_STATUS_MONITORED, ZBX_FLAG_DISCOVERY_PROTOTYPE, HOST_MAINTENANCE_STATUS_ON); if (NULL != ids && 0 != ids_num) { zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and not"); DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", ids, ids_num); } result = DBselect("%s", sql); ids_num = 0; while (NULL != (row = DBfetch(result))) { zabbix_log(LOG_LEVEL_WARNING, "taking host [%s] out of maintenance", row[1]); ZBX_STR2UINT64(hostid, row[0]); uint64_array_add(&ids, &ids_alloc, &ids_num, hostid, 4); if (MAINTENANCE_TYPE_NORMAL != atoi(row[2])) continue; m = zbx_malloc(NULL, sizeof(maintenance_t)); m->hostid = hostid; m->maintenance_from = atoi(row[3]); m->next = maintenances; maintenances = m; } DBfree_result(result); sql_offset = 0; zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update hosts" " set maintenanceid=null," "maintenance_status=%d," "maintenance_type=0," "maintenance_from=0" " where", HOST_MAINTENANCE_STATUS_OFF); if (NULL != ids && 0 != ids_num) { DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", ids, ids_num); DBexecute("%s", sql); DCconfig_set_maintenance(ids, ids_num, HOST_MAINTENANCE_STATUS_OFF, 0, 0); } DBcommit(); zbx_free(sql); zbx_free(ids); for (m = maintenances; NULL != m; m = m->next) generate_events(m->hostid, m->maintenance_from, now); for (m = maintenances; NULL != m; m = maintenances) { maintenances = m->next; zbx_free(m); } zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: DCflush_nextchecks * * * * Purpose: add item nextcheck to the array * * * * Parameters: * * * * Return value: * * * * Author: Alexander Vladishev, Dmitry Borovikov * * * * Comments: * * * ******************************************************************************/ void DCflush_nextchecks() { const char *__function_name = "DCflush_nextchecks"; int i, sql_offset = 0, sql_allocated = 4096; char *sql = NULL; DB_RESULT result; DB_ROW row; zbx_uint64_t triggerid; zbx_uint64_t itemid; zbx_uint64_t events_maxid = 0; char *error_msg_esc = NULL; char *sql_select = NULL; int sql_select_offset = 0, sql_select_allocated = 512; /* a crutch for the function `DBadd_condition_alloc' */ zbx_uint64_t *ids = NULL; int ids_allocated = 0, ids_num = 0; zbx_uint64_t *triggerids = NULL; int triggerids_allocated = 0, triggerids_num = 0; struct event_objectid_clock *events = NULL; int events_num = 0, events_allocated = 32; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (nextcheck_num == 0) return; sql = zbx_malloc(sql, sql_allocated); DBbegin(); #ifdef HAVE_ORACLE zbx_snprintf_alloc(&sql, &sql_allocated, &sql_offset, 8, "begin\n"); #endif /* dealing with items */ for (i = 0; i < nextcheck_num; i++) { if (NULL == nextchecks[i].error_msg) continue; uint64_array_add(&ids, &ids_allocated, &ids_num, nextchecks[i].itemid, 64); error_msg_esc = DBdyn_escape_string_len(nextchecks[i].error_msg, ITEM_ERROR_LEN); zbx_snprintf_alloc(&sql, &sql_allocated, &sql_offset, 128 + strlen(error_msg_esc), "update items set status=%d,lastclock=%d,error='%s' where itemid=" ZBX_FS_UI64 ";\n", ITEM_STATUS_NOTSUPPORTED, (int)nextchecks[i].now, error_msg_esc, nextchecks[i].itemid); zbx_free(error_msg_esc); DBexecute_overflowed_sql(&sql, &sql_allocated, &sql_offset); } /* dealing with notsupported items */ if (ids_num > 0) { sql_select = zbx_malloc(sql_select, sql_select_allocated); events = zbx_malloc(events, events_allocated * sizeof(struct event_objectid_clock)); /* preparing triggers */ zbx_snprintf_alloc(&sql_select, &sql_select_allocated, &sql_select_offset, 256, "select t.triggerid,i.itemid" " from triggers t,functions f,items i" " where t.triggerid=f.triggerid" " and f.itemid=i.itemid" " and t.status in (%d)" " and t.value not in (%d)" " and", TRIGGER_STATUS_ENABLED, TRIGGER_VALUE_UNKNOWN); DBadd_condition_alloc(&sql_select, &sql_select_allocated, &sql_select_offset, "i.itemid", ids, ids_num); result = DBselect("%s", sql_select); zbx_free(sql_select); /* processing triggers */ while (NULL != (row = DBfetch(result))) { ZBX_STR2UINT64(triggerid, row[0]); ZBX_STR2UINT64(itemid, row[1]); /* do not generate multiple unknown events for a trigger */ if (SUCCEED == uint64_array_exists(triggerids, triggerids_num, triggerid)) continue; uint64_array_add(&triggerids, &triggerids_allocated, &triggerids_num, triggerid, 64); /* index `i' will surely contain necessary itemid */ i = get_nearestindex(nextchecks, sizeof(ZBX_DC_NEXTCHECK), nextcheck_num, itemid); if (i == nextcheck_num || nextchecks[i].itemid != itemid) { THIS_SHOULD_NEVER_HAPPEN; continue; } error_msg_esc = DBdyn_escape_string_len(nextchecks[i].error_msg, TRIGGER_ERROR_LEN); zbx_snprintf_alloc(&sql, &sql_allocated, &sql_offset, 128 + strlen(error_msg_esc), "update triggers set value=%d,lastchange=%d,error='%s' where triggerid=" ZBX_FS_UI64";\n", TRIGGER_VALUE_UNKNOWN, nextchecks[i].now, error_msg_esc, triggerid); zbx_free(error_msg_esc); if (events_num == events_allocated) { events_allocated += 32; events = zbx_realloc(events, events_allocated * sizeof(struct event_objectid_clock)); } events[events_num].objectid = triggerid; events[events_num].clock = nextchecks[i].now; events_num++; DBexecute_overflowed_sql(&sql, &sql_allocated, &sql_offset); } DBfree_result(result); /* dealing with events */ for (i = 0; i < events_num; i++) { events_maxid = DBget_maxid("events"); zbx_snprintf_alloc(&sql, &sql_allocated, &sql_offset, 256, "insert into events (eventid,source,object,objectid,clock,value) " "values (" ZBX_FS_UI64 ",%d,%d," ZBX_FS_UI64 ",%d,%d);\n", events_maxid, EVENT_SOURCE_TRIGGERS, EVENT_OBJECT_TRIGGER, events[i].objectid, events[i].clock, TRIGGER_VALUE_UNKNOWN); DBexecute_overflowed_sql(&sql, &sql_allocated, &sql_offset); } zbx_free(events); } #ifdef HAVE_ORACLE zbx_snprintf_alloc(&sql, &sql_allocated, &sql_offset, 8, "end;\n"); #endif if (sql_offset > 16) /* In ORACLE always present begin..end; */ DBexecute("%s", sql); zbx_free(sql); zbx_free(ids); zbx_free(triggerids); DCrelease_nextchecks(); DBcommit(); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: aggregate_get_items * * * * Purpose: get array of items specified by key for selected groups * * * * Parameters: ids - result, list of items * * groups - list of comma-separated host groups * * itemkey - item key to aggregate * * * ******************************************************************************/ static void aggregate_get_items(zbx_uint64_t **ids, int *ids_alloc, int *ids_num, const char *groups, const char *itemkey) { 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; sql = zbx_malloc(sql, sql_alloc); esc = DBdyn_escape_string(itemkey); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select i.itemid" " from items i,hosts_groups hg,hosts h,groups g" " where hg.groupid=g.groupid" " and i.hostid=h.hostid" " and hg.hostid=h.hostid" " 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]); uint64_array_add(ids, ids_alloc, ids_num, itemid, 64); } DBfree_result(result); }
/****************************************************************************** * * * Function: housekeeping_process_log * * * * Purpose: process table 'housekeeper' and remove data if required * * * * Parameters: * * * * Return value: SUCCEED - information removed successfully * * FAIL - otherwise * * * * Author: Alexei Vladishev, Dmitry Borovikov * * * * Comments: sqlite3 does not use CONFIG_MAX_HOUSEKEEPER_DELETE, deletes all * * * ******************************************************************************/ static int housekeeping_process_log() { const char *__function_name = "housekeeping_process_log"; DB_HOUSEKEEPER housekeeper; DB_RESULT result; DB_ROW row; long deleted; char *sql = NULL; int sql_alloc = 512, sql_offset = 0; zbx_uint64_t *ids = NULL; int ids_alloc = 0, ids_num = 0; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); /* 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) { deleted = DBexecute( "delete from %s" " where %s=" ZBX_FS_UI64, housekeeper.tablename, housekeeper.field, housekeeper.value); } else { #ifdef HAVE_ORACLE deleted = 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_POSTGRESQL) deleted = DBexecute( "delete from %s" " where %s=" ZBX_FS_UI64 " and oid in (select oid from %s" " where %s=" ZBX_FS_UI64 " limit %d)", housekeeper.tablename, housekeeper.field, housekeeper.value, housekeeper.tablename, housekeeper.field, housekeeper.value, CONFIG_MAX_HOUSEKEEPER_DELETE); #elif defined(HAVE_MYSQL) deleted = DBexecute( "delete from %s" " where %s=" ZBX_FS_UI64 " limit %d", housekeeper.tablename, housekeeper.field, housekeeper.value, CONFIG_MAX_HOUSEKEEPER_DELETE); #else /* HAVE_SQLITE3 */ deleted = 0; #endif } if (0 == deleted || 0 == CONFIG_MAX_HOUSEKEEPER_DELETE || CONFIG_MAX_HOUSEKEEPER_DELETE > deleted) uint64_array_add(&ids, &ids_alloc, &ids_num, housekeeper.housekeeperid, 64); if (deleted > 0) { zabbix_log( LOG_LEVEL_DEBUG, "Deleted [%ld] records from table [%s]", deleted, housekeeper.tablename); } } DBfree_result(result); if (NULL != ids) { sql = zbx_malloc(sql, sql_alloc * sizeof(char)); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, 32, "delete from housekeeper where"); DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "housekeeperid", ids, ids_num); DBexecute("%s", sql); zbx_free(sql); zbx_free(ids); } return SUCCEED; }