/****************************************************************************** * * * 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: 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_sync * * * * Purpose: process configuration changes received from a node * * * * Parameters: * * * * Return value: SUCCEED - processed successfully * * FAIL - an error occurred * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ int node_sync(char *data, int *sender_nodeid, int *nodeid) { const char *r; char *lf; int datalen, res = SUCCEED; unsigned char sender_nodetype; datalen = strlen(data); zabbix_log(LOG_LEVEL_DEBUG, "In node_sync() len:%d", datalen); tmp = zbx_malloc(tmp, tmp_alloc); if (NULL != (lf = strchr(data, '\n'))) *lf = '\0'; r = data; zbx_get_next_field(&r, &tmp, &tmp_alloc, ZBX_DM_DELIMITER); /* Data */ zbx_get_next_field(&r, &tmp, &tmp_alloc, ZBX_DM_DELIMITER); *sender_nodeid = atoi(tmp); sender_nodetype = (*sender_nodeid == CONFIG_MASTER_NODEID) ? ZBX_NODE_MASTER : ZBX_NODE_SLAVE; zbx_get_next_field(&r, &tmp, &tmp_alloc, ZBX_DM_DELIMITER); *nodeid = atoi(tmp); if (0 != *sender_nodeid && 0 != *nodeid) { if (CONFIG_MASTER_NODEID != *sender_nodeid && FAIL == is_direct_slave_node(*sender_nodeid)) { zabbix_log(LOG_LEVEL_ERR, "NODE %d: Received configuration changes from unknown node %d", CONFIG_NODEID, *sender_nodeid); res = FAIL; goto quit; } if (CONFIG_MASTER_NODEID != *sender_nodeid && CONFIG_NODEID == *nodeid) { zabbix_log(LOG_LEVEL_ERR, "NODE %d: Received configuration changes for this node from a non-master node %d", CONFIG_NODEID, *sender_nodeid); res = FAIL; goto quit; } if (CONFIG_NODEID != *nodeid && FAIL == is_slave_node(CONFIG_NODEID, *nodeid)) { zabbix_log(LOG_LEVEL_ERR, "NODE %d: Received configuration changes for unknown node %d", CONFIG_NODEID, *nodeid); res = FAIL; goto quit; } zabbix_log(LOG_LEVEL_WARNING, "NODE %d: Received configuration changes from %s node %d for node %d datalen %d", CONFIG_NODEID, zbx_nodetype_string(sender_nodetype), *sender_nodeid, *nodeid, datalen); DBexecute("delete from node_cksum where nodeid=%d and cksumtype=%d", *nodeid, NODE_CKSUM_TYPE_NEW); if (lf != NULL) { *lf++ = '\n'; data = lf; buf = zbx_malloc(buf, buf_alloc); process_updated_records(*nodeid, data); process_deleted_records(*nodeid, data); process_checksum(*nodeid, data, sender_nodetype); zbx_free(buf); } } quit: zbx_free(tmp); return res; }