Exemplo n.º 1
0
/******************************************************************************
 *                                                                            *
 * 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;
}
Exemplo n.º 2
0
/******************************************************************************
 *                                                                            *
 * 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;
}
Exemplo n.º 3
0
/******************************************************************************
 *                                                                            *
 * 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;
	}
Exemplo n.º 4
0
/******************************************************************************
 *                                                                            *
 * 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);
}
Exemplo n.º 5
0
/******************************************************************************
 *                                                                            *
 * 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);
}
Exemplo n.º 6
0
/******************************************************************************
 *                                                                            *
 * 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;
}