static void make_delete_sql(char **sql, size_t *sql_alloc, size_t *sql_offset, const ZBX_TABLE *table, zbx_uint64_t *ids, int *ids_num) { if (NULL == table) return; if (0 == *ids_num) return; zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "delete from %s where", table->table); DBadd_condition_alloc(sql, sql_alloc, sql_offset, table->recid, ids, *ids_num); zbx_strcpy_alloc(sql, sql_alloc, sql_offset, ";\n"); DBexecute_overflowed_sql(sql, sql_alloc, sql_offset); *ids_num = 0; }
/****************************************************************************** * * * Function: save_template_lld_rules * * * * Purpose: saves template lld rule item conditions to the target host in * * database * * * * Parameters: items - [IN] the template items * * rules - [IN] the ldd rule mapping * * new_conditions - [IN] the number of new item conditions to * * be inserted * * * ******************************************************************************/ static void save_template_lld_rules(zbx_vector_ptr_t *items, zbx_vector_ptr_t *rules, int new_conditions) { char *macro_esc, *value_esc; int i, j, index; zbx_db_insert_t db_insert; zbx_lld_rule_map_t *rule; zbx_lld_rule_condition_t *condition; char *sql = NULL; size_t sql_alloc = 0, sql_offset = 0; zbx_vector_uint64_t item_conditionids; if (0 == rules->values_num) return; zbx_vector_uint64_create(&item_conditionids); if (0 != new_conditions) { zbx_db_insert_prepare(&db_insert, "item_condition", "item_conditionid", "itemid", "operator", "macro", "value", NULL); /* insert lld rule conditions for new items */ for (i = 0; i < items->values_num; i++) { zbx_template_item_t *item = items->values[i]; if (NULL == item->key) continue; if (0 == (ZBX_FLAG_DISCOVERY_RULE & item->flags)) continue; index = zbx_vector_ptr_bsearch(rules, &item->templateid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC); if (FAIL == index) { THIS_SHOULD_NEVER_HAPPEN; continue; } rule = rules->values[index]; for (j = 0; j < rule->conditions.values_num; j++) { condition = rule->conditions.values[j]; zbx_db_insert_add_values(&db_insert, rule->conditionid++, item->itemid, (int)condition->operator, condition->macro, condition->value); } } } DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset); /* update lld rule conditions for existing items */ for (i = 0; i < rules->values_num; i++) { rule = rules->values[i]; /* skip lld rules of new items */ if (0 == rule->itemid) continue; index = MIN(rule->conditions.values_num, rule->conditionids.values_num); /* update intersecting rule conditions */ for (j = 0; j < index; j++) { condition = rule->conditions.values[j]; macro_esc = DBdyn_escape_string(condition->macro); value_esc = DBdyn_escape_string(condition->value); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update item_condition" " set operator=%d,macro='%s',value='%s'" " where item_conditionid=" ZBX_FS_UI64 ";\n", (int)condition->operator, macro_esc, value_esc, rule->conditionids.values[j]); DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset); zbx_free(value_esc); zbx_free(macro_esc); } /* delete removed rule conditions */ for (j = index; j < rule->conditionids.values_num; j++) zbx_vector_uint64_append(&item_conditionids, rule->conditionids.values[j]); /* insert new rule conditions */ for (j = index; j < rule->conditions.values_num; j++) { condition = rule->conditions.values[j]; zbx_db_insert_add_values(&db_insert, rule->conditionid++, rule->itemid, (int)condition->operator, condition->macro, condition->value); } } /* delete removed item conditions */ if (0 != item_conditionids.values_num) { zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from item_condition where"); DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "item_conditionid", item_conditionids.values, item_conditionids.values_num); zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n"); } DBend_multiple_update(&sql, &sql_alloc, &sql_offset); if (16 < sql_offset) DBexecute("%s", sql); if (0 != new_conditions) { zbx_db_insert_execute(&db_insert); zbx_db_insert_clean(&db_insert); } zbx_free(sql); zbx_vector_uint64_destroy(&item_conditionids); }
/****************************************************************************** * * * 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: 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, 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*64+32], *ck; char *exsql = NULL; int exsql_alloc = 65536, exsql_offset = 0, 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(); #ifdef HAVE_ORACLE zbx_snprintf_alloc(&exsql, &exsql_alloc, &exsql_offset, 8, "begin\n"); #endif c[0] = synked == SUCCEED ? '1' : ' '; /* for new and updated records */ c[1] = synked == SUCCEED ? '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'; } /* Find updated records */ result = DBselect("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 " /* Find 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 " /* Find 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", nodeid, NODE_CKSUM_TYPE_NEW, NODE_CKSUM_TYPE_OLD, sql[0], NODE_CKSUM_TYPE_OLD, nodeid, NODE_CKSUM_TYPE_NEW, sql[0], NODE_CKSUM_TYPE_NEW, nodeid, NODE_CKSUM_TYPE_OLD, sql[1]); while (NULL != (row = DBfetch(result))) { /* Found table */ if (NULL == (table = DBget_table(row[0]))) { zabbix_log(LOG_LEVEL_WARNING, "Cannot find table [%s]", row[0]); continue; } if (FAIL == DBis_null(row[4])) zbx_strlcpy(sync, row[4], sizeof(sync)); else memset(sync, ' ', sizeof(sync)); s = sync; ck = cksum; *ck = '\0'; /* Special (simpler) processing for operation DELETE */ if (SUCCEED == DBis_null(row[3])) { if (synked == SUCCEED) { if (synked_nodetype == ZBX_NODE_SLAVE) s[0] = c[1]; else if (synked_nodetype == ZBX_NODE_MASTER) s[1] = 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, 256, "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] = DBis_null(row[2]) == SUCCEED ? NULL : row[2]; r[1] = row[3]; f = 0; do { while ((table->fields[f].flags & ZBX_SYNC) == 0) f++; 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 (r[0] == NULL || r[1] == NULL || strcmp(r[0], r[1]) != 0) { if (synked_nodetype == ZBX_NODE_SLAVE) { s[0] = c[0]; s[1] = ' '; } else if (synked_nodetype == ZBX_NODE_MASTER) { s[0] = ' '; s[1] = c[0]; } } else { if (synked == SUCCEED) { if (synked_nodetype == ZBX_NODE_SLAVE) s[0] = c[0]; else if (synked_nodetype == ZBX_NODE_MASTER) s[1] = 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, 2560, "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); #ifdef HAVE_ORACLE zbx_snprintf_alloc(&exsql, &exsql_alloc, &exsql_offset, 8, "end;\n"); #endif 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: process_deleted_records * * * * Purpose: * * * * Parameters: * * * * Return value: * * * * Author: Alexander Vladishev * * * * Comments: * * * ******************************************************************************/ static void process_deleted_records(int nodeid, char *data) { const char *__function_name = "process_deleted_records"; typedef struct { const ZBX_TABLE *table; zbx_vector_uint64_t recids; void *next; } zbx_records_t; char *r, *lf; zbx_uint64_t recid; char *sql = NULL; size_t sql_alloc = 4 * ZBX_KIBIBYTE, sql_offset = 0; zbx_records_t *first = NULL, *rec; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); 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); /* table name */ if (NULL == first || 0 != strcmp(first->table->table, buf)) { rec = zbx_malloc(NULL, sizeof(zbx_records_t)); if (NULL == (rec->table = DBget_table(buf))) { zabbix_log(LOG_LEVEL_DEBUG, "%s(): cannot find table [%s]", __function_name, buf); zbx_free(rec); goto next; } zbx_vector_uint64_create(&rec->recids); rec->next = first; first = rec; } zbx_get_next_field((const char **)&r, &buf, &buf_alloc, ZBX_DM_DELIMITER); /* record id */ ZBX_STR2UINT64(recid, buf); zbx_get_next_field((const char **)&r, &buf, &buf_alloc, ZBX_DM_DELIMITER); /* operation type */ if ('2' == *buf) /* deleted record */ zbx_vector_uint64_append(&rec->recids, recid); next: if (lf != NULL) { *lf++ = '\n'; r = lf; } else break; } sql = zbx_malloc(sql, sql_alloc); DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset); for (rec = first; NULL != rec; rec = rec->next) { if (0 == rec->recids.values_num) continue; zbx_vector_uint64_sort(&rec->recids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "delete from %s where", rec->table->table); DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, rec->table->recid, rec->recids.values, rec->recids.values_num); zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n"); DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset); } DBend_multiple_update(&sql, &sql_alloc, &sql_offset); if (sql_offset > 16) /* in ORACLE always present begin..end; */ DBexecute("%s", sql); zbx_free(sql); while (NULL != first) { rec = first; first = rec->next; zbx_vector_uint64_destroy(&rec->recids); zbx_free(rec); } zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
static void update_triggers_status_to_unknown(zbx_uint64_t hostid, zbx_item_type_t type, int now, char *reason) { const char *__function_name = "update_triggers_status_to_unknown"; DB_RESULT result; DB_ROW row; DB_TRIGGER_UPDATE *tr = NULL, *tr_last; int tr_alloc = 0, tr_num = 0; char *sql = NULL; int sql_alloc = 16 * ZBX_KIBIBYTE, sql_offset = 0; char failed_type_buf[8]; zabbix_log(LOG_LEVEL_DEBUG, "In %s() hostid:" ZBX_FS_UI64, __function_name, hostid); sql = zbx_malloc(sql, sql_alloc); #ifdef HAVE_ORACLE zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, 7, "begin\n"); #endif /* determine failed item type */ switch (type) { case ITEM_TYPE_ZABBIX: zbx_snprintf(failed_type_buf, sizeof(failed_type_buf), "%d", ITEM_TYPE_ZABBIX); break; case ITEM_TYPE_SNMPv1: case ITEM_TYPE_SNMPv2c: case ITEM_TYPE_SNMPv3: zbx_snprintf(failed_type_buf, sizeof(failed_type_buf), "%d,%d,%d", ITEM_TYPE_SNMPv1, ITEM_TYPE_SNMPv2c, ITEM_TYPE_SNMPv3); break; case ITEM_TYPE_IPMI: zbx_snprintf(failed_type_buf, sizeof(failed_type_buf), "%d", ITEM_TYPE_IPMI); break; default: /* we should never end up here */ assert(0); } /****************************************************************************** * Set trigger status to UNKNOWN if all are true: * * - trigger's item status ACTIVE * * - trigger's item type same as failed one * * - trigger does not reference time-based functions- trigger status ENABLED * * - trigger's host same as failed one * * - trigger's host status MONITORED * * - trigger does not reference "active" item * * * * An item is considered "active" if all are true: * * - item status ACTIVE * * - item's host status MONITORED * * - item's trigger references time-based functions * * OR * * item is of different type AND it's host is AVAILABLE * ******************************************************************************/ result = DBselect( "select distinct t.triggerid,t.type,t.value,t.error" " from items i,functions f,triggers t,hosts h" " where i.itemid=f.itemid" " and f.triggerid=t.triggerid" " and i.hostid=h.hostid" " and i.status=%d" " and not i.key_ like '%s'" " and i.type in (%s)" " and f.function not in (" ZBX_SQL_TIME_FUNCTIONS ")" " and t.status=%d" " and h.hostid=" ZBX_FS_UI64 " and h.status=%d" " and not exists (" "select 1" " from functions f2,items i2,hosts h2" " where f2.triggerid=f.triggerid" " and f2.itemid=i2.itemid" " and i2.hostid=h2.hostid" " and (" "f2.function in (" ZBX_SQL_TIME_FUNCTIONS ")" " or (" "i2.type not in (%s)" " and (" "i2.type not in (%d,%d,%d,%d,%d)" " or (i2.type in (%d) and h2.available=%d)" " or (i2.type in (%d,%d,%d) and h2.snmp_available=%d)" " or (i2.type in (%d) and h2.ipmi_available=%d)" ")" ")" ")" " and i2.status=%d" " and not i2.key_ like '%s'" " and h2.status=%d" ")" " order by t.triggerid", ITEM_STATUS_ACTIVE, SERVER_STATUS_KEY, failed_type_buf, TRIGGER_STATUS_ENABLED, hostid, HOST_STATUS_MONITORED, failed_type_buf, ITEM_TYPE_ZABBIX, ITEM_TYPE_SNMPv1, ITEM_TYPE_SNMPv2c, ITEM_TYPE_SNMPv3, ITEM_TYPE_IPMI, ITEM_TYPE_ZABBIX, HOST_AVAILABLE_TRUE, ITEM_TYPE_SNMPv1, ITEM_TYPE_SNMPv2c, ITEM_TYPE_SNMPv3, HOST_AVAILABLE_TRUE, ITEM_TYPE_IPMI, HOST_AVAILABLE_TRUE, ITEM_STATUS_ACTIVE, SERVER_STATUS_KEY, HOST_STATUS_MONITORED); while (NULL != (row = DBfetch(result))) { if (tr_num == tr_alloc) { tr_alloc += 64; tr = zbx_realloc(tr, tr_alloc * sizeof(DB_TRIGGER_UPDATE)); } tr_last = &tr[tr_num++]; ZBX_STR2UINT64(tr_last->triggerid, row[0]); tr_last->type = (unsigned char)atoi(row[1]); tr_last->value = atoi(row[2]); tr_last->new_value = TRIGGER_VALUE_UNKNOWN; tr_last->error = row[3]; tr_last->lastchange = now; if (SUCCEED == DBget_trigger_update_sql(&sql, &sql_alloc, &sql_offset, tr_last->triggerid, tr_last->type, tr_last->value, tr_last->error, tr_last->new_value, reason, tr_last->lastchange, &tr_last->add_event)) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, 3, ";\n"); } DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset); } DBfree_result(result); #ifdef HAVE_ORACLE zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, 6, "end;\n"); #endif if (sql_offset > 16) /* In ORACLE always present begin..end; */ DBexecute("%s", sql); zbx_free(sql); if (0 != tr_num) { for (tr_last = &tr[0]; 0 != tr_num; tr_num--, tr_last++) { if (1 != tr_last->add_event) continue; process_event(0, EVENT_SOURCE_TRIGGERS, EVENT_OBJECT_TRIGGER, tr_last->triggerid, tr_last->lastchange, tr_last->new_value, 0, 0); } } zbx_free(tr); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: db_update_event_suppress_data * * * * Purpose: create/update event suppress data to reflect latest maintenance * * changes in cache * * * * Parameters: suppressed_num - [OUT] the number of suppressed events * * * ******************************************************************************/ static void db_update_event_suppress_data(int *suppressed_num) { zbx_vector_ptr_t event_queries, event_data; *suppressed_num = 0; zbx_vector_ptr_create(&event_queries); zbx_vector_ptr_create(&event_data); db_get_query_events(&event_queries, &event_data); if (0 != event_queries.values_num) { zbx_db_insert_t db_insert; char *sql = NULL; size_t sql_alloc = 0, sql_offset = 0; int i, j, k; zbx_event_suppress_query_t *query; zbx_event_suppress_data_t *data; zbx_vector_uint64_pair_t del_event_maintenances; zbx_vector_uint64_t maintenanceids; zbx_uint64_pair_t pair; zbx_vector_uint64_create(&maintenanceids); zbx_vector_uint64_pair_create(&del_event_maintenances); db_get_query_functions(&event_queries); db_get_query_tags(&event_queries); zbx_dc_get_running_maintenanceids(&maintenanceids); DBbegin(); if (0 != maintenanceids.values_num && SUCCEED == zbx_db_lock_maintenanceids(&maintenanceids)) zbx_dc_get_event_maintenances(&event_queries, &maintenanceids); zbx_db_insert_prepare(&db_insert, "event_suppress", "event_suppressid", "eventid", "maintenanceid", "suppress_until", NULL); DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset); for (i = 0; i < event_queries.values_num; i++) { query = (zbx_event_suppress_query_t *)event_queries.values[i]; zbx_vector_uint64_pair_sort(&query->maintenances, ZBX_DEFAULT_UINT64_COMPARE_FUNC); k = 0; if (FAIL != (j = zbx_vector_ptr_bsearch(&event_data, &query->eventid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC))) { data = (zbx_event_suppress_data_t *)event_data.values[j]; zbx_vector_uint64_pair_sort(&data->maintenances, ZBX_DEFAULT_UINT64_COMPARE_FUNC); j = 0; while (j < data->maintenances.values_num && k < query->maintenances.values_num) { if (data->maintenances.values[j].first < query->maintenances.values[k].first) { pair.first = query->eventid; pair.second = data->maintenances.values[j].first; zbx_vector_uint64_pair_append(&del_event_maintenances, pair); j++; continue; } if (data->maintenances.values[j].first > query->maintenances.values[k].first) { if (0 == query->r_eventid) { zbx_db_insert_add_values(&db_insert, __UINT64_C(0), query->eventid, query->maintenances.values[k].first, (int)query->maintenances.values[k].second); (*suppressed_num)++; } k++; continue; } if (data->maintenances.values[j].second != query->maintenances.values[k].second) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update event_suppress" " set suppress_until=%d" " where eventid=" ZBX_FS_UI64 " and maintenanceid=" ZBX_FS_UI64 ";\n", (int)query->maintenances.values[k].second, query->eventid, query->maintenances.values[k].first); if (FAIL == DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset)) goto cleanup; } j++; k++; } for (;j < data->maintenances.values_num; j++) { pair.first = query->eventid; pair.second = data->maintenances.values[j].first; zbx_vector_uint64_pair_append(&del_event_maintenances, pair); } } if (0 == query->r_eventid) { for (;k < query->maintenances.values_num; k++) { zbx_db_insert_add_values(&db_insert, __UINT64_C(0), query->eventid, query->maintenances.values[k].first, (int)query->maintenances.values[k].second); (*suppressed_num)++; } } } for (i = 0; i < del_event_maintenances.values_num; i++) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "delete from event_suppress" " where eventid=" ZBX_FS_UI64 " and maintenanceid=" ZBX_FS_UI64 ";\n", del_event_maintenances.values[i].first, del_event_maintenances.values[i].second); if (FAIL == DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset)) goto cleanup; } DBend_multiple_update(&sql, &sql_alloc, &sql_offset); if (16 < sql_offset) { if (ZBX_DB_OK > DBexecute("%s", sql)) goto cleanup; } zbx_db_insert_autoincrement(&db_insert, "event_suppressid"); zbx_db_insert_execute(&db_insert); cleanup: DBcommit(); zbx_db_insert_clean(&db_insert); zbx_free(sql); zbx_vector_uint64_pair_destroy(&del_event_maintenances); zbx_vector_uint64_destroy(&maintenanceids); } zbx_vector_ptr_clear_ext(&event_data, (zbx_clean_func_t)event_suppress_data_free); zbx_vector_ptr_destroy(&event_data); zbx_vector_ptr_clear_ext(&event_queries, (zbx_clean_func_t)zbx_event_suppress_query_free); zbx_vector_ptr_destroy(&event_queries); }
/****************************************************************************** * * * Function: db_update_host_maintenances * * * * Purpose: update host maintenance properties in database * * * ******************************************************************************/ static void db_update_host_maintenances(const zbx_vector_ptr_t *updates) { int i; const zbx_host_maintenance_diff_t *diff; char *sql = NULL; size_t sql_alloc = 0, sql_offset = 0; DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset); for (i = 0; i < updates->values_num; i++) { char delim = ' '; diff = (const zbx_host_maintenance_diff_t *)updates->values[i]; zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update hosts set"); if (0 != (diff->flags & ZBX_FLAG_HOST_MAINTENANCE_UPDATE_MAINTENANCEID)) { if (0 != diff->maintenanceid) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%cmaintenanceid=" ZBX_FS_UI64, delim, diff->maintenanceid); } else { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%cmaintenanceid=null", delim); } delim = ','; } if (0 != (diff->flags & ZBX_FLAG_HOST_MAINTENANCE_UPDATE_MAINTENANCE_TYPE)) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%cmaintenance_type=%u", delim, diff->maintenance_type); delim = ','; } if (0 != (diff->flags & ZBX_FLAG_HOST_MAINTENANCE_UPDATE_MAINTENANCE_STATUS)) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%cmaintenance_status=%u", delim, diff->maintenance_status); delim = ','; } if (0 != (diff->flags & ZBX_FLAG_HOST_MAINTENANCE_UPDATE_MAINTENANCE_FROM)) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%cmaintenance_from=%d", delim, diff->maintenance_from); } zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " where hostid=" ZBX_FS_UI64 ";\n", diff->hostid); if (SUCCEED != DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset)) break; if (SUCCEED == ZBX_CHECK_LOG_LEVEL(LOG_LEVEL_DEBUG)) log_host_maintenance_update(diff); } DBend_multiple_update(&sql, &sql_alloc, &sql_offset); if (16 < sql_offset) DBexecute("%s", sql); zbx_free(sql); }
/****************************************************************************** * * * 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); }