/****************************************************************************** * * * Function: send_history_last_id * * * * Purpose: send list of last historical tables IDs * * * * Parameters: sock - opened socket of node-node connection * * record * * * * Return value: SUCCEED - sent successfully * * FAIL - an error occurred * * * * Author: Alexander Vladishev * * * * Comments: * * * ******************************************************************************/ int send_history_last_id(zbx_sock_t *sock, const char *data) { DB_RESULT result; DB_ROW row; const char *r; const ZBX_TABLE *table; size_t buffer_offset; int sender_nodeid = (-1), nodeid = (-1), res; zabbix_log(LOG_LEVEL_DEBUG, "In send_history_last_id()"); buffer_alloc = 320; buffer = zbx_malloc(buffer, buffer_alloc); r = data; if (NULL == r) goto error; zbx_get_next_field(&r, &buffer, &buffer_alloc, ZBX_DM_DELIMITER); /* constant 'ZBX_GET_HISTORY_LAST_ID' */ if (NULL == r) goto error; zbx_get_next_field(&r, &buffer, &buffer_alloc, ZBX_DM_DELIMITER); /* sender_nodeid */ sender_nodeid = atoi(buffer); if (NULL == r) goto error; if (FAIL == is_direct_slave_node(sender_nodeid)) { zabbix_log(LOG_LEVEL_ERR, "NODE %d: Received data from node %d that is not a direct slave node [%s]", CONFIG_NODEID, sender_nodeid, data); goto fail; } zbx_get_next_field(&r, &buffer, &buffer_alloc, '\n'); /* nodeid */ nodeid = atoi(buffer); if (NULL == r) goto error; if (FAIL == is_slave_node(CONFIG_NODEID, nodeid)) { zabbix_log(LOG_LEVEL_ERR, "NODE %d: Received data for unknown slave node %d [%s]", CONFIG_NODEID, nodeid, data); goto fail; } zbx_get_next_field(&r, &buffer, &buffer_alloc, ZBX_DM_DELIMITER); /* table name */ if (NULL == (table = DBget_table(buffer))) goto error; if (0 == (table->flags & ZBX_HISTORY)) goto error; if (NULL == r) goto error; zbx_get_next_field(&r, &buffer, &buffer_alloc, ZBX_DM_DELIMITER); /* field name */ if (0 != strcmp(buffer, table->recid)) goto error; buffer_offset= 0; zbx_snprintf_alloc(&buffer, &buffer_alloc, &buffer_offset, "select max(%s)" " from %s" " where 1=1" DB_NODE, table->recid, table->table, DBnode(table->recid, nodeid)); buffer_offset= 0; result = DBselect("%s", buffer); if (NULL != (row = DBfetch(result))) zbx_strcpy_alloc(&buffer, &buffer_alloc, &buffer_offset, SUCCEED == DBis_null(row[0]) ? "0" : row[0]); DBfree_result(result); if (buffer_offset == 0) goto error; alarm(CONFIG_TIMEOUT); res = send_data_to_node(sender_nodeid, sock, buffer); alarm(0); zbx_free(buffer); return res; error: zabbix_log(LOG_LEVEL_ERR, "NODE %d: Received invalid record from node %d for node %d [%s]", CONFIG_NODEID, sender_nodeid, nodeid, data); fail: buffer_offset= 0; zbx_strcpy_alloc(&buffer, &buffer_alloc, &buffer_offset, "FAIL"); alarm(CONFIG_TIMEOUT); res = send_data_to_node(sender_nodeid, sock, buffer); alarm(0); zbx_free(buffer); return FAIL; }
/****************************************************************************** * * * Function: node_history * * * * Purpose: process new history received from a slave node * * * * Parameters: * * * * Return value: SUCCEED - processed successfully * * FAIL - an error occurred * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ int node_history(char *data, size_t datalen) { const char *r; char *newline = NULL; char *pos; int sender_nodeid = 0, nodeid = 0, firstline = 1, events = 0, history = 0, acknowledges = 0; const ZBX_TABLE *table_sync = NULL, *table = NULL; int res = SUCCEED; char *sql1 = NULL, *sql2 = NULL, *sql3 = NULL; size_t sql1_alloc, sql2_alloc, sql3_alloc; size_t sql1_offset, sql2_offset, sql3_offset; zbx_vector_uint64_t ack_eventids; assert(data); zabbix_log(LOG_LEVEL_DEBUG, "In node_history()"); buffer_alloc = 4 * ZBX_KIBIBYTE; sql1_alloc = 32 * ZBX_KIBIBYTE; sql2_alloc = 32 * ZBX_KIBIBYTE; sql3_alloc = 32 * ZBX_KIBIBYTE; tmp_alloc = 4 * ZBX_KIBIBYTE; buffer = zbx_malloc(buffer, buffer_alloc); sql1 = zbx_malloc(sql1, sql1_alloc); sql2 = zbx_malloc(sql2, sql2_alloc); sql3 = zbx_malloc(sql3, sql3_alloc); tmp = zbx_malloc(tmp, tmp_alloc); zbx_vector_uint64_create(&ack_eventids); DBbegin(); for (r = data; *r != '\0' && res == SUCCEED;) { if (NULL != (newline = strchr(r, '\n'))) *newline = '\0'; if (1 == firstline) { zbx_get_next_field(&r, &buffer, &buffer_alloc, ZBX_DM_DELIMITER); /* constant 'History' */ zbx_get_next_field(&r, &buffer, &buffer_alloc, ZBX_DM_DELIMITER); /* sender_nodeid */ sender_nodeid=atoi(buffer); zbx_get_next_field(&r, &buffer, &buffer_alloc, ZBX_DM_DELIMITER); /* nodeid */ nodeid=atoi(buffer); zbx_get_next_field(&r, &buffer, &buffer_alloc, ZBX_DM_DELIMITER); /* tablename */ if (FAIL == is_direct_slave_node(sender_nodeid)) { zabbix_log(LOG_LEVEL_ERR, "NODE %d: Received data from node %d" " that is not a direct slave node", CONFIG_NODEID, sender_nodeid); res = FAIL; } if (FAIL == is_slave_node(CONFIG_NODEID, nodeid)) { zabbix_log(LOG_LEVEL_ERR, "NODE %d: Received history for unknown slave node %d", CONFIG_NODEID, nodeid); res = FAIL; } table = DBget_table(buffer); if (NULL != table && 0 == (table->flags & (ZBX_HISTORY | ZBX_HISTORY_SYNC))) table = NULL; if (NULL != table && 0 != (table->flags & ZBX_HISTORY_SYNC)) { table_sync = table; if (NULL != (pos = strstr(buffer, "_sync"))) { *pos = '\0'; table = DBget_table(buffer); } } if (NULL == table) { zabbix_log(LOG_LEVEL_ERR, "NODE %d: Invalid received data: unknown tablename \"%s\"", CONFIG_NODEID, buffer); res = FAIL; } else { if (0 == strcmp(table->table, "events")) events = 1; if (0 == strncmp(table->table, "history", 7)) history = 1; if (0 == strcmp(table->table, "acknowledges")) acknowledges = 1; } if (NULL != newline) { zabbix_log(LOG_LEVEL_WARNING, "NODE %d: Received %s from node %d for node %d datalen " ZBX_FS_SIZE_T, CONFIG_NODEID, buffer, sender_nodeid, nodeid, (zbx_fs_size_t)datalen); } firstline = 0; sql1_offset = 0; sql2_offset = 0; sql3_offset = 0; } else if (NULL != table) { if (events) { res = process_record_event(sender_nodeid, nodeid, table, r); } else { res = process_record(&sql1, &sql1_alloc, &sql1_offset, sender_nodeid, nodeid, table, r, newline ? 0 : 1, acknowledges, &ack_eventids); if (SUCCEED == res && 0 != history) { res = process_items(&sql2, &sql2_alloc, &sql2_offset, sender_nodeid, nodeid, table, r, newline ? 0 : 1); } if (SUCCEED == res && NULL != table_sync && 0 != CONFIG_MASTER_NODEID) { res = process_record(&sql3, &sql3_alloc, &sql3_offset, sender_nodeid, nodeid, table_sync, r, newline ? 0 : 1, 0, NULL); } } } if (newline != NULL) { *newline = '\n'; r = newline + 1; } else break; } if (SUCCEED == res) DBcommit(); else DBrollback(); zbx_vector_uint64_destroy(&ack_eventids); zbx_free(tmp); zbx_free(sql1); zbx_free(sql2); zbx_free(sql3); zbx_free(buffer); return res; }
/****************************************************************************** * * * Function: process_updated_records * * * * Purpose: * * * * Parameters: * * * * Return value: * * * * Author: Alexander Vladishev * * * * Comments: * * * ******************************************************************************/ static void process_updated_records(int nodeid, char *data, int sender_nodetype) { const char *__function_name = "process_updated_records"; char *r, *lf, *value_esc; int op, dnum; const ZBX_TABLE *table = NULL; const ZBX_FIELD *field = NULL; zbx_uint64_t recid; char *dsql = NULL, *isql = NULL, *ifld = NULL, *ival = NULL, *usql = NULL, *ufld = NULL; size_t dsql_alloc = 4 * ZBX_KIBIBYTE, dsql_offset = 0, dtmp_offset = 0, isql_alloc = 4 * ZBX_KIBIBYTE, isql_offset = 0, ifld_alloc = 4 * ZBX_KIBIBYTE, ifld_offset = 0, ival_alloc = 4 * ZBX_KIBIBYTE, ival_offset = 0, usql_alloc = 4 * ZBX_KIBIBYTE, usql_offset = 0, ufld_alloc = 4 * ZBX_KIBIBYTE, ufld_offset = 0; DB_RESULT result; DB_ROW row; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); dsql = zbx_malloc(dsql, dsql_alloc); isql = zbx_malloc(isql, isql_alloc); ifld = zbx_malloc(ifld, ifld_alloc); ival = zbx_malloc(ival, ival_alloc); usql = zbx_malloc(usql, usql_alloc); ufld = zbx_malloc(ufld, ufld_alloc); #ifdef HAVE_ORACLE DBbegin_multiple_update(&dsql, &dsql_alloc, &dsql_offset); DBbegin_multiple_update(&isql, &isql_alloc, &isql_offset); DBbegin_multiple_update(&usql, &usql_alloc, &usql_offset); #endif for (r = data; '\0' != *r;) { if (NULL != (lf = strchr(r, '\n'))) *lf = '\0'; /* table name */ zbx_get_next_field((const char **)&r, &buf, &buf_alloc, ZBX_DM_DELIMITER); if (NULL == table || 0 != strcmp(table->table, buf)) { if (NULL == (table = DBget_table(buf))) { zabbix_log(LOG_LEVEL_DEBUG, "%s(): cannot find table [%s]", __function_name, buf); goto next; } } /* record id */ zbx_get_next_field((const char **)&r, &buf, &buf_alloc, ZBX_DM_DELIMITER); ZBX_STR2UINT64(recid, buf); if (NULL == r) { zabbix_log(LOG_LEVEL_DEBUG, "%s(): invalid record", __function_name); goto next; } if ('0' == *r) /* NODE_CONFIGLOG_OP_UPDATE */ { result = DBselect("select 0 from %s where %s=" ZBX_FS_UI64, table->table, table->recid, recid); if (NULL == (row = DBfetch(result))) op = NODE_CONFIGLOG_OP_ADD; else op = NODE_CONFIGLOG_OP_UPDATE; DBfree_result(result); zbx_get_next_field((const char **)&r, &buf, &buf_alloc, ZBX_DM_DELIMITER); ifld_offset = 0; ival_offset = 0; ufld_offset = 0; dtmp_offset = dsql_offset; dnum = 0; if (op == NODE_CONFIGLOG_OP_ADD && NULL != table->uniq) { zbx_snprintf_alloc(&dsql, &dsql_alloc, &dsql_offset, "delete from %s where ", table->table); } while (NULL != r) { /* field name */ zbx_get_next_field((const char **)&r, &buf, &buf_alloc, ZBX_DM_DELIMITER); if (NULL == (field = DBget_field(table, buf))) { zabbix_log(LOG_LEVEL_DEBUG, "%s(): cannot find field [%s.%s]", __function_name, table->table, buf); goto next; } if (NODE_CONFIGLOG_OP_UPDATE == op) zbx_snprintf_alloc(&ufld, &ufld_alloc, &ufld_offset, "%s=", buf); else /* NODE_CONFIGLOG_OP_ADD */ zbx_snprintf_alloc(&ifld, &ifld_alloc, &ifld_offset, "%s,", buf); /* value type (ignored) */ zbx_get_next_field((const char **)&r, &buf, &buf_alloc, ZBX_DM_DELIMITER); zbx_get_next_field((const char **)&r, &buf, &buf_alloc, ZBX_DM_DELIMITER); if (0 == strcmp(buf, "NULL")) { if (NODE_CONFIGLOG_OP_UPDATE == op) zbx_strcpy_alloc(&ufld, &ufld_alloc, &ufld_offset, "NULL,"); else /* NODE_CONFIGLOG_OP_ADD */ zbx_strcpy_alloc(&ival, &ival_alloc, &ival_offset, "NULL,"); continue; } switch (field->type) { case ZBX_TYPE_ID: /* if the field relates the same table * for example: host.proxy_hostid relates with host.hostid */ if (NODE_CONFIGLOG_OP_ADD == op && NULL != field->fk_table && 0 == strcmp(table->table, field->fk_table)) { zbx_snprintf_alloc(&ufld, &ufld_alloc, &ufld_offset, "%s=%s,", field->name, buf); zbx_strcpy_alloc(&ival, &ival_alloc, &ival_offset, "NULL,"); break; } case ZBX_TYPE_INT: case ZBX_TYPE_UINT: case ZBX_TYPE_FLOAT: if (NODE_CONFIGLOG_OP_UPDATE == op) zbx_snprintf_alloc(&ufld, &ufld_alloc, &ufld_offset, "%s,", buf); else /* NODE_CONFIGLOG_OP_ADD */ { zbx_snprintf_alloc(&ival, &ival_alloc, &ival_offset, "%s,", buf); if (NULL != table->uniq && SUCCEED == str_in_list(table->uniq, field->name, ',')) { zbx_snprintf_alloc(&dsql, &dsql_alloc, &dsql_offset, "%s=%s and ", field->name, buf); dnum++; } } break; case ZBX_TYPE_BLOB: if ('\0' == *buf) { if (NODE_CONFIGLOG_OP_UPDATE == op) zbx_strcpy_alloc(&ufld, &ufld_alloc, &ufld_offset, "'',"); else /* NODE_CONFIGLOG_OP_ADD */ zbx_strcpy_alloc(&ival, &ival_alloc, &ival_offset, "'',"); } else { #if defined(HAVE_POSTGRESQL) size_t len; len = zbx_hex2binary(buf); zbx_pg_escape_bytea((u_char *)buf, len, &tmp, &tmp_alloc); if (NODE_CONFIGLOG_OP_UPDATE == op) zbx_snprintf_alloc(&ufld, &ufld_alloc, &ufld_offset, "'%s',", tmp); else /* NODE_CONFIGLOG_OP_ADD */ zbx_snprintf_alloc(&ival, &ival_alloc, &ival_offset, "'%s',", tmp); #else if (NODE_CONFIGLOG_OP_UPDATE == op) zbx_snprintf_alloc(&ufld, &ufld_alloc, &ufld_offset, "0x%s,", buf); else /* NODE_CONFIGLOG_OP_ADD */ zbx_snprintf_alloc(&ival, &ival_alloc, &ival_offset, "0x%s,", buf); #endif } break; default: /* ZBX_TYPE_TEXT, ZBX_TYPE_CHAR */ zbx_hex2binary(buf); value_esc = DBdyn_escape_string(buf); if (NODE_CONFIGLOG_OP_UPDATE == op) zbx_snprintf_alloc(&ufld, &ufld_alloc, &ufld_offset, "'%s',", value_esc); else /* NODE_CONFIGLOG_OP_ADD */ { zbx_snprintf_alloc(&ival, &ival_alloc, &ival_offset, "'%s',", value_esc); if (NULL != table->uniq && SUCCEED == str_in_list(table->uniq, field->name, ',')) { zbx_snprintf_alloc(&dsql, &dsql_alloc, &dsql_offset, "%s='%s' and ", field->name, value_esc); dnum++; } } zbx_free(value_esc) } } if (dsql_offset != dtmp_offset) { if (dnum != num_param(table->uniq)) { zabbix_log(LOG_LEVEL_DEBUG, "%s(): missing required fields [%s][%s]", __function_name, table->table, table->uniq); dsql_offset = dtmp_offset; goto next; } dsql_offset -= 5; zbx_strcpy_alloc(&dsql, &dsql_alloc, &dsql_offset, ";\n"); } if (0 != ifld_offset) { ifld[--ifld_offset] = '\0'; ival[--ival_offset] = '\0'; zbx_snprintf_alloc(&isql, &isql_alloc, &isql_offset, "insert into %s (%s,%s) values (" ZBX_FS_UI64 ",%s);\n", table->table, table->recid, ifld, recid, ival); } if (0 != ufld_offset) { ufld[--ufld_offset] = '\0'; zbx_snprintf_alloc(&usql, &usql_alloc, &usql_offset, "update %s set %s where %s=" ZBX_FS_UI64 ";\n", table->table, ufld, table->recid, recid); } if (dsql_offset > ZBX_MAX_SQL_SIZE || isql_offset > ZBX_MAX_SQL_SIZE || usql_offset > ZBX_MAX_SQL_SIZE) { DBend_multiple_update(&dsql, &dsql_alloc, &dsql_offset); DBend_multiple_update(&isql, &isql_alloc, &isql_offset); DBend_multiple_update(&usql, &usql_alloc, &usql_offset); if (dsql_offset > 16) DBexecute("%s", dsql); if (isql_offset > 16) DBexecute("%s", isql); if (usql_offset > 16) DBexecute("%s", usql); dsql_offset = 0; isql_offset = 0; usql_offset = 0; #ifdef HAVE_ORACLE DBbegin_multiple_update(&dsql, &dsql_alloc, &dsql_offset); DBbegin_multiple_update(&isql, &isql_alloc, &isql_offset); DBbegin_multiple_update(&usql, &usql_alloc, &usql_offset); #endif } } next: if (lf != NULL) { *lf++ = '\n'; r = lf; } else break; }
/****************************************************************************** * * * Function: process_checksum * * * * Author: Alexander Vladishev * * * ******************************************************************************/ static void process_checksum(int nodeid, char *data, unsigned char sender_nodetype) { const char *__function_name = "process_checksum"; char *r, *lf; size_t tmp_offset; const ZBX_TABLE *table = NULL; zbx_uint64_t recid; 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 == table || 0 != strcmp(table->table, buf)) { 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); /* record id */ ZBX_STR2UINT64(recid, buf); zbx_get_next_field((const char **)&r, &buf, &buf_alloc, ZBX_DM_DELIMITER); /* operation type */ if ('0' == *buf) /* NODE_CONFIGLOG_OP_UPDATE */ { *tmp = '\0'; tmp_offset = 0; while (NULL != r) { /* field name */ zbx_get_next_field((const char **)&r, &buf, &buf_alloc, ZBX_DM_DELIMITER); if (0 != tmp_offset) zbx_chrcpy_alloc(&tmp, &tmp_alloc, &tmp_offset, ','); zbx_strcpy_alloc(&tmp, &tmp_alloc, &tmp_offset, buf); /* field type */ zbx_get_next_field((const char **)&r, &buf, &buf_alloc, ZBX_DM_DELIMITER); /* value */ zbx_get_next_field((const char **)&r, &buf, &buf_alloc, ZBX_DM_DELIMITER); } if (SUCCEED == calculate_checksums(nodeid, table->table, recid)) update_checksums(nodeid, sender_nodetype, SUCCEED, table->table, recid, tmp); } next: if (NULL != lf) { *lf++ = '\n'; r = lf; } else break; } zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * 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); }
/****************************************************************************** * * * Function: change_nodeid * * * * Purpose: convert database data to new node ID * * * * Parameters: old_id - old id, new_id - new node id * * * * Return value: SUCCEED - converted successfully * * FAIL - an error occurred * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ int change_nodeid(int old_id, int new_id) { struct conv_t { const char *rel; int type; }; struct special_conv_t { const char *table_name, *field_name, *type_field_name; struct conv_t convs[32]; }; struct special_conv_t special_convs[]= { {"sysmaps_elements", "elementid", "elementtype", { {"hosts", SYSMAP_ELEMENT_TYPE_HOST}, {"sysmaps", SYSMAP_ELEMENT_TYPE_MAP}, {"triggers", SYSMAP_ELEMENT_TYPE_TRIGGER}, {"groups", SYSMAP_ELEMENT_TYPE_HOST_GROUP}, {"images", SYSMAP_ELEMENT_TYPE_IMAGE}, {NULL} } }, {"events", "objectid", "object", { {"triggers", EVENT_OBJECT_TRIGGER}, {"dhosts", EVENT_OBJECT_DHOST}, {"dservices", EVENT_OBJECT_DSERVICE}, {NULL} } }, {"operations", "objectid", "object", { {"users", OPERATION_OBJECT_USER}, {"usrgrp", OPERATION_OBJECT_GROUP}, {NULL} } }, {"ids", "nextid", NULL, { {NULL} } }, {"node_cksum", "recordid", NULL, { {NULL} } }, {"screens_items", "resourceid", "resourcetype", { {"graphs", SCREEN_RESOURCE_GRAPH}, {"items", SCREEN_RESOURCE_SIMPLE_GRAPH}, {"sysmaps", SCREEN_RESOURCE_MAP}, {"items", SCREEN_RESOURCE_PLAIN_TEXT}, {"groups", SCREEN_RESOURCE_HOSTS_INFO}, {"screens", SCREEN_RESOURCE_SCREEN}, {"groups", SCREEN_RESOURCE_TRIGGERS_OVERVIEW}, {"groups", SCREEN_RESOURCE_DATA_OVERVIEW}, {"groups", SCREEN_RESOURCE_HOSTGROUP_TRIGGERS}, {"hosts", SCREEN_RESOURCE_HOST_TRIGGERS}, {NULL} } }, {"auditlog", "resourceid", "resourcetype", { {"users", AUDIT_RESOURCE_USER}, /* {"", AUDIT_RESOURCE_ZABBIX},*/ {"config", AUDIT_RESOURCE_ZABBIX_CONFIG}, {"media_type", AUDIT_RESOURCE_MEDIA_TYPE}, {"hosts", AUDIT_RESOURCE_HOST}, {"actions", AUDIT_RESOURCE_ACTION}, {"graphs", AUDIT_RESOURCE_GRAPH}, {"graphs_items", AUDIT_RESOURCE_GRAPH_ELEMENT}, /* {"", AUDIT_RESOURCE_ESCALATION}, {"", AUDIT_RESOURCE_ESCALATION_RULE}, {"", AUDIT_RESOURCE_AUTOREGISTRATION},*/ {"usrgrp", AUDIT_RESOURCE_USER_GROUP}, {"applications", AUDIT_RESOURCE_APPLICATION}, {"triggers", AUDIT_RESOURCE_TRIGGER}, {"groups", AUDIT_RESOURCE_HOST_GROUP}, {"items", AUDIT_RESOURCE_ITEM}, {"images", AUDIT_RESOURCE_IMAGE}, {"valuemaps", AUDIT_RESOURCE_VALUE_MAP}, {"services", AUDIT_RESOURCE_IT_SERVICE}, {"sysmaps", AUDIT_RESOURCE_MAP}, {"screens", AUDIT_RESOURCE_SCREEN}, /* {"nodes", AUDIT_RESOURCE_NODE},*/ /* {"", AUDIT_RESOURCE_SCENARIO},*/ {"drules", AUDIT_RESOURCE_DISCOVERY_RULE}, {"slideshows", AUDIT_RESOURCE_SLIDESHOW}, {"scripts", AUDIT_RESOURCE_SCRIPT}, /* {"", AUDIT_RESOURCE_PROXY},*/ {"maintenances", AUDIT_RESOURCE_MAINTENANCE}, {"regexps", AUDIT_RESOURCE_REGEXP}, {NULL} } }, {NULL} }; struct conv_t condition_convs[]= { {"groups", CONDITION_TYPE_HOST_GROUP}, {"hosts", CONDITION_TYPE_HOST}, {"hosts", CONDITION_TYPE_HOST_TEMPLATE}, {"hosts", CONDITION_TYPE_PROXY}, {"triggers", CONDITION_TYPE_TRIGGER}, {"dchecks", CONDITION_TYPE_DCHECK}, {"drules", CONDITION_TYPE_DRULE}, {NULL}, }; int i, j, s, t; zbx_uint64_t prefix; const ZBX_TABLE *r_table; if(old_id!=0) { printf("Conversion from non-zero node id is not supported.\n"); return FAIL; } if(new_id>999 || new_id<0) { printf("Node ID must be in range of 0-999.\n"); return FAIL; } zabbix_set_log_level(LOG_LEVEL_WARNING); DBconnect(ZBX_DB_CONNECT_EXIT); DBbegin(); printf("Converting tables "); fflush(stdout); for (i = 0; NULL != tables[i].table; i++) { printf("."); fflush(stdout); for (j = 0; NULL != tables[i].fields[j].name; j++) { for (s = 0; NULL != special_convs[s].table_name; s++) if (0 == strcmp(special_convs[s].table_name, tables[i].table) && 0 == strcmp(special_convs[s].field_name, tables[i].fields[j].name)) break; if (NULL != special_convs[s].table_name) { for (t = 0; NULL != special_convs[s].convs[t].rel; t++) { convert_special_field(old_id, new_id, special_convs[s].table_name, special_convs[s].field_name, special_convs[s].type_field_name, special_convs[s].convs[t].rel, special_convs[s].convs[t].type); } continue; } if (tables[i].fields[j].type == ZBX_TYPE_ID) { if (0 == strcmp(tables[i].fields[j].name, tables[i].recid)) /* primary key */ { prefix = (zbx_uint64_t)__UINT64_C(100000000000000)*(zbx_uint64_t)new_id; if (tables[i].flags & ZBX_SYNC) prefix += (zbx_uint64_t)__UINT64_C(100000000000)*(zbx_uint64_t)new_id; } else if (NULL != tables[i].fields[j].rel) /* relations */ { if (NULL == (r_table = DBget_table(tables[i].fields[j].rel))) { printf("%s.%s FAILED\n", tables[i].table, tables[i].fields[j].name); fflush(stdout); continue; } 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; } else if (0 == strcmp("profiles", tables[i].table)) /* special processing for table 'profiles' */ { convert_profiles(old_id, new_id, tables[i].fields[j].name); continue; } else { printf("%s.%s FAILED\n", tables[i].table, tables[i].fields[j].name); fflush(stdout); continue; } DBexecute("update %s set %s=%s+" ZBX_FS_UI64 " where %s>0", tables[i].table, tables[i].fields[j].name, tables[i].fields[j].name, prefix, tables[i].fields[j].name); } } } /* Special processing for trigger expressions */ convert_triggers_expression(old_id, new_id); /* Special processing for condition values */ for (i = 0; NULL != condition_convs[i].rel; i++) convert_condition_values(old_id, new_id, condition_convs[i].rel, condition_convs[i].type); DBexecute("insert into nodes (nodeid,name,ip,nodetype) values (%d,'Local node','127.0.0.1',1)", new_id); DBcommit(); DBclose(); printf(" done.\nConversion completed.\n"); return SUCCEED; }