Пример #1
0
void
server_deinit(struct array *server)
{
    uint32_t i, nserver;

    for (i = 0, nserver = array_n(server); i < nserver; i++) {
        struct server *s;

        s = array_pop(server);
        ASSERT(TAILQ_EMPTY(&s->s_conn_q) && s->ns_conn_q == 0);
    }
    array_deinit(server);
}
Пример #2
0
void
ffi_replicaset_deinit(struct replicaset *rs)
{
    int i;

    for (i = 0; i < NC_MAXTAGNUM; i++) {
        uint32_t n = array_n(&rs->tagged_servers[i]);
        while (n--) {
            array_pop(&rs->tagged_servers[i]);
        }
    }
    rs->master = NULL;
}
Пример #3
0
void
dnode_peer_deinit(struct array *nodes)
{
	uint32_t i, nnode;

	for (i = 0, nnode = array_n(nodes); i < nnode; i++) {
		struct server *s;

		s = array_pop(nodes);
		ASSERT(TAILQ_EMPTY(&s->s_conn_q) && s->ns_conn_q == 0);
	}
	array_deinit(nodes);
}
Пример #4
0
/*
 * Returns the entry that has been removed, if any.
 */
Array_item *BX_remove_from_array (Array *array, char *name)
{
	int count, location = 0;

	if (array->max)
	{
		find_array_item(array, name, &count, &location);
		if (count >= 0)
			return NULL;

		return array_pop(array, location);
	}
	return NULL;	/* Cant delete whats not there */
}
Пример #5
0
Array_item *remove_from_array (Array *array, char *name)
{
	int count, location = 0;

	if (array->max)
	{
		find_array_item(array, name, &count, &location);
		if (count >= 0)
			return (void *) 0 ;

		return array_pop(array, location);
	}
	return (void *) 0 ;	 
}
Пример #6
0
static void
stats_server_unmap(struct array *stats_server)
{
    uint32_t i, nserver;

    nserver = array_n(stats_server);

    for (i = 0; i < nserver; i++) {
        struct stats_server *sts = array_pop(stats_server);
        stats_metric_deinit(&sts->metric);
    }
    array_deinit(stats_server);

    log_debug(LOG_VVVERB, "unmap %"PRIu32" stats servers", nserver);
}
Пример #7
0
void
conf_destroy(struct conf *cf)
{
    while (array_n(&cf->arg) != 0) {
        conf_pop_scalar(cf);
    }
    array_deinit(&cf->arg);

    while (array_n(&cf->pool) != 0) {
        conf_pool_deinit(array_pop(&cf->pool));
    }
    array_deinit(&cf->pool);

    nc_free(cf);
}
Пример #8
0
static void
conf_pool_deinit(struct conf_pool *cp)
{
    string_deinit(&cp->name);

    string_deinit(&cp->listen.pname);
    string_deinit(&cp->listen.name);

    if (cp->redis_auth.len > 0) {
        string_deinit(&cp->redis_auth);
    }

    while (array_n(&cp->groups) != 0) {
        string_deinit(array_pop(&cp->groups));
    }
    array_deinit(&cp->groups);

    while (array_n(&cp->sentinels) != 0) {
        conf_server_deinit(array_pop(&cp->sentinels));
    }
    array_deinit(&cp->sentinels);

    log_debug(LOG_VVERB, "deinit conf pool %p", cp);
}
Пример #9
0
static void
conf_pool_deinit(struct conf_pool *cp)
{
    string_deinit(&cp->name);

    string_deinit(&cp->listen.pname);
    string_deinit(&cp->listen.name);

    while (array_n(&cp->server) != 0) {
        conf_server_deinit(array_pop(&cp->server));
    }
    array_deinit(&cp->server);

    log_debug(LOG_VVERB, "deinit conf pool %p", cp);
}
Пример #10
0
static void
stats_pool_unmap(struct array *stats_pool)
{
    uint32_t i, npool;

    npool = array_n(stats_pool);

    for (i = 0; i < npool; i++) {
        struct stats_pool *stp = array_pop(stats_pool);
        stats_metric_deinit(&stp->metric);
        stats_server_unmap(&stp->server);
    }
    array_deinit(stats_pool);

    log_debug(LOG_VVVERB, "unmap %"PRIu32" stats pool", npool);
}
Пример #11
0
void test_push_pop() {
    int i;

    for (i = 0; i < 100; i++) {
        int *element = array_new(array);
        *element = i * 333;
        array_push(array, element);
    }
    mu_assert(array->max == 151, "Wrong max size");

    for (i = 99; i >= 0; i--) {
        int *value = array_pop(array);

        mu_assert(value != NULL, "Shouldn't get NULL");
        mu_assert(*value == i * 333, "Wrong value");
        free(value);
    }
}
Пример #12
0
void
stats_pool_copy_deinit(struct stats_pool *stp, struct hash_table **sit)
{
    uint32_t nserver;
    uint32_t i;
    struct stats_server *sts;

    stats_metric_deinit(&stp->metric);
    string_deinit(&stp->name);

    nserver = array_n(&stp->server);
    for (i = 0;i < nserver;i++) {
        sts = array_pop(&stp->server);
        string_deinit(&stp->name);

        stats_metric_deinit(&sts->metric);
    }
    array_deinit(&stp->server);

    assoc_destroy_table(*sit);
    (*sit) = NULL;
}
Пример #13
0
void	*hmap_delete(t_hmap *map, void *key)
{
	t_uint		hash;
	void		*data;
	t_array		*contents;
	int			i;
	t_node_h	nh;

	contents = hmap_find_contents(map, key, 0, &hash);
	hash = 0;
	if (!contents)
		return (NULL);
	if ((i = hmap_get_node(map, hash, contents, key)) == -1)
		return (NULL);
	nh.node = array_get(contents, i);
	data = nh.node->data;
	free(nh.node);
	nh.ending = array_pop(contents);
	if (nh.ending != nh.node)
		array_set(contents, i, nh.ending);
	return (data);
}
Пример #14
0
static void test_array(void **state)
{
	int ret = 0;
	array_t(int) arr;
	array_init(arr);

	/* Basic access */
	assert_int_equal(arr.len, 0);
	assert_int_equal(array_push(arr, 5), 0);
	assert_int_equal(arr.at[0], 5);
	assert_int_equal(array_tail(arr), 5);
	array_clear(arr);

	/* Reserve capacity and fill. */
	assert_true(array_reserve(arr, 5) >= 0);
	for (unsigned i = 0; i < 100; ++i) {
		ret = array_push(arr, i);
		assert_true(ret >= 0);
	}

	/* Make sure reservation holds. */
	assert_true(array_reserve(arr, 5) >= 0);

	/* Delete elements. */
	array_del(arr, 0);
	while (arr.len > 0) {
		array_pop(arr);
	}

	/* Overfill. */
	for (unsigned i = 0; i < 4096; ++i) {
		ret = array_push(arr, i);
		assert_true(ret >= 0);
	}

	array_clear(arr);
}
Пример #15
0
static void conf_pool_deinit(conf_pool *cp)
{
    sds *str;

    if(cp == NULL){
        return;
    }

    cp->type = CONF_UNSET_GROUP;

    if(cp->servers != NULL){
        while(array_n(cp->servers) > 0){
            str = array_pop(cp->servers);
            sdsfree(*str);
        }

        array_destroy(cp->servers);
        cp->servers = CONF_UNSET_PTR;
    }
    
    cp->hash = CONF_UNSET_HASH;
    cp->distribution = CONF_UNSET_DIST;

    if(cp->hash_tag != NULL){
        sdsfree(cp->hash_tag);
        cp->hash_tag = CONF_UNSET_PTR;
    }

    if(cp->redis_auth != NULL){
        sdsfree(cp->redis_auth);
        cp->redis_auth = CONF_UNSET_PTR;
    }
    
    cp->redis_db = CONF_UNSET_NUM;
    cp->timeout = CONF_UNSET_NUM;
    cp->backlog = CONF_UNSET_NUM;
}
Пример #16
0
int main() {
	array_t a;
	char **p;

	array_init(&a, sizeof(char *));

	p = (char **)array_push(&a);
	*p = "aaaa";
	p = (char **)array_push(&a);
	*p = "bbbb";
	p = (char **)array_push(&a);
	*p = "cccc";
	p = (char **)array_push(&a);
	*p = "dddd";
	p = (char **)array_push(&a);

	while ((p = array_pop(&a)) != NULL) {
		printf("popped: %s\n", *p);
	}

	array_destroy(&a);

	return 0;
}
Пример #17
0
static unsigned int* _random_thread_allocate( void )
{
	unsigned int* buffer;

	mutex_lock( _random_mutex );

	//Grab a free state buffer or allocate if none available
	if( !array_size( _random_available_state ) )
	{
		buffer = _random_allocate_buffer();
		array_push( _random_available_state, buffer );
	}
	else
	{
		buffer = _random_available_state[ array_size( _random_available_state ) - 1 ];
		array_pop( _random_available_state );
	}

	mutex_unlock( _random_mutex );
	
	set_thread_state( buffer );

	return buffer;
}
Пример #18
0
void
server_pool_deinit(struct array *server_pool)
{
	uint32_t i, npool;

	for (i = 0, npool = array_n(server_pool); i < npool; i++) {
		struct server_pool *sp;

		sp = array_pop(server_pool);
		ASSERT(sp->p_conn == NULL);
		ASSERT(TAILQ_EMPTY(&sp->c_conn_q) && sp->dn_conn_q == 0);

		server_deinit(&sp->server);

		sp->nlive_server = 0;

		log_debug(LOG_DEBUG, "deinit pool %"PRIu32" '%.*s'", sp->idx,
				sp->name.len, sp->name.data);
	}

	array_deinit(server_pool);

	log_debug(LOG_DEBUG, "deinit %"PRIu32" pools", npool);
}
Пример #19
0
static int check_response(redis_node *rnode, struct msg *r)
{
    int ret;
    rmtContext *ctx = rnode->ctx;
    struct msg *resp, *msg = NULL;
    check_data *chdata;
    check_unit *cunit;
    char extra_err[50];
    struct array args;
    sds *arg;
    struct array *bulks1 = NULL, *bulks2 = NULL;
    sds *bulk1, *bulk2;

    if (r == NULL) {
        return RMT_ERROR;
    }

    extra_err[0] = '\0';

    resp = r->peer;
    r->peer = NULL;
    array_init(&args, 3, sizeof(sds));

    ASSERT(r->request && r->sent);
    ASSERT(resp != NULL && resp->request == 0);

    cunit = (check_unit *)r->ptr;
    chdata = cunit->cdata->data;

    if(resp->type == MSG_RSP_REDIS_ERROR){
        log_warn("Response from node[%s] for %s is error",
            rnode->addr, msg_type_string(r->type));
        goto error;
    }

    if (cunit->state == CHECK_UNIT_STATE_GET_KEY) {
        ASSERT(cunit->key == NULL);
        ASSERT(cunit->key_type == -1);
        ASSERT(cunit->result1 == NULL && cunit->result2 == NULL);
        ASSERT(cunit->srnode == rnode);

        if (resp->type != MSG_RSP_REDIS_BULK) {
            log_error("ERROR: the response type for command 'randomkey' from node[%s] is error: %s", 
                rnode->addr, msg_type_string(resp->type));
            goto error;
        }

        if (msg_cmp_str(resp, (const uint8_t*)REDIS_REPLY_BULK_NULL, 
            rmt_strlen(REDIS_REPLY_BULK_NULL)) == 0) {
            /* source group may have no keys, stop it */
            cunit->cdata->keys_count --;
            goto done;
        }

        cunit->key = redis_msg_response_get_bulk_string(resp);
        if (cunit->key == NULL) {
            log_error("ERROR: get bulk string from response of node[%s] failed, "
                "bulk_len: %"PRIu32", bulk_start: %p", 
                rnode->addr, resp->bulk_len, resp->bulk_start);
            goto error;
        }

        if (ctx->filter != NULL && !stringmatchlen(ctx->filter, sdslen(ctx->filter), 
            cunit->key, sdslen(cunit->key), 0)) {
            goto done;
        }

        ASSERT(sdslen(cunit->key) == resp->bulk_len);

        msg = msg_get(r->mb, 1, REDIS_DATA_TYPE_CMD);
        if (msg == NULL) {
            log_error("ERROR: out of memory.");
            goto error;
        }

        arg = array_push(&args);
        *arg = sdsnew("type");
        arg = array_push(&args);
        *arg = sdsdup(cunit->key);
        ret = redis_msg_append_command_full_safe(msg, &args);
        if (ret != RMT_OK) {
            log_error("ERROR: msg append multi bulk len failed.");
            goto error;
        }
        while (array_n(&args) > 0) {
            arg = array_pop(&args);
            sdsfree(*arg);
        }
        
        msg->ptr = cunit;
        msg->resp_check = check_response;

        ret = prepare_send_msg(rnode, msg, rnode);
        if (ret != RMT_OK) {
            log_error("ERROR: prepare send msg node[%s] failed.", rnode->addr);
            goto error;
        }

        cunit->state = CHECK_UNIT_STATE_GET_TYPE;
        goto next_step;
    }

    if (cunit->state == CHECK_UNIT_STATE_GET_TYPE) {
        ASSERT(cunit->key != NULL);
        ASSERT(cunit->key_type == -1);
        ASSERT(cunit->result1 == NULL && cunit->result2 == NULL);
        ASSERT(cunit->srnode == rnode);
        
        if (resp->type != MSG_RSP_REDIS_STATUS) {
            log_error("ERROR: the response type for command 'type' from node[%s] is error: %s", 
                rnode->addr, msg_type_string(resp->type));
            goto error;
        }

        if (msg_cmp_str(resp, (const uint8_t*)REDIS_REPLY_STATUS_NONE, 
            rmt_strlen(REDIS_REPLY_STATUS_NONE)) == 0) {
            /* This key doesn't exit, may be expired or evicted */
            goto done;
        }

        msg = msg_get(r->mb, 1, REDIS_DATA_TYPE_CMD);
        if (msg == NULL) {
            log_error("ERROR: out of memory.");
            goto error;
        }

        if (msg_cmp_str(resp, (const uint8_t*)REDIS_REPLY_STATUS_STRING, 
            rmt_strlen(REDIS_REPLY_STATUS_STRING)) == 0) {
            cunit->key_type = REDIS_STRING;

            arg = array_push(&args);
            *arg = sdsnew("get");
            arg = array_push(&args);
            *arg = sdsdup(cunit->key);
            ret = redis_msg_append_command_full_safe(msg, &args);
            if (ret != RMT_OK) {
                log_error("ERROR: msg append multi bulk len failed.");
                goto error;
            }
            while (array_n(&args) > 0) {
                arg = array_pop(&args);
                sdsfree(*arg);
            }
        } else if (msg_cmp_str(resp, (const uint8_t*)REDIS_REPLY_STATUS_LIST, 
            rmt_strlen(REDIS_REPLY_STATUS_LIST)) == 0) {
            cunit->key_type = REDIS_LIST;

            arg = array_push(&args);
            *arg = sdsnew("lrange");
            arg = array_push(&args);
            *arg = sdsdup(cunit->key);
            arg = array_push(&args);
            *arg = sdsnew("0");
            arg = array_push(&args);
            *arg = sdsnew("-1");
            ret = redis_msg_append_command_full_safe(msg, &args);
            if (ret != RMT_OK) {
                log_error("ERROR: msg append multi bulk len failed.");
                goto error;
            }
            while (array_n(&args) > 0) {
                arg = array_pop(&args);
                sdsfree(*arg);
            }
        } else if (msg_cmp_str(resp, (const uint8_t*)REDIS_REPLY_STATUS_SET, 
            rmt_strlen(REDIS_REPLY_STATUS_SET)) == 0) {
            cunit->key_type = REDIS_SET;

            arg = array_push(&args);
            *arg = sdsnew("smembers");
            arg = array_push(&args);
            *arg = sdsdup(cunit->key);
            ret = redis_msg_append_command_full_safe(msg, &args);
            if (ret != RMT_OK) {
                log_error("ERROR: msg append multi bulk len failed.");
                goto error;
            }
            while (array_n(&args) > 0) {
                arg = array_pop(&args);
                sdsfree(*arg);
            }
        } else if (msg_cmp_str(resp, (const uint8_t*)REDIS_REPLY_STATUS_ZSET, 
            rmt_strlen(REDIS_REPLY_STATUS_ZSET)) == 0) {
            cunit->key_type = REDIS_ZSET;

            arg = array_push(&args);
            *arg = sdsnew("zrange");
            arg = array_push(&args);
            *arg = sdsdup(cunit->key);
            arg = array_push(&args);
            *arg = sdsnew("0");
            arg = array_push(&args);
            *arg = sdsnew("-1");
            ret = redis_msg_append_command_full_safe(msg, &args);
            if (ret != RMT_OK) {
                log_error("ERROR: msg append multi bulk len failed.");
                goto error;
            }
            while (array_n(&args) > 0) {
                arg = array_pop(&args);
                sdsfree(*arg);
            }
        } else if (msg_cmp_str(resp, (const uint8_t*)REDIS_REPLY_STATUS_HASH, 
            rmt_strlen(REDIS_REPLY_STATUS_HASH)) == 0) {
            cunit->key_type = REDIS_HASH;

            arg = array_push(&args);
            *arg = sdsnew("hgetall");
            arg = array_push(&args);
            *arg = sdsdup(cunit->key);
            ret = redis_msg_append_command_full_safe(msg, &args);
            if (ret != RMT_OK) {
                log_error("ERROR: msg append multi bulk len failed.");
                goto error;
            }
            while (array_n(&args) > 0) {
                arg = array_pop(&args);
                sdsfree(*arg);
            }
        } else {
            log_error("ERROR: response key type from node[%s] is error: ",
                rnode->addr);
            goto error;
        }

        msg->ptr = cunit;
        msg->resp_check = check_response;
        
        ret = send_msg_to_all(cunit, msg);
        if (ret != RMT_OK) {
            log_error("ERROR: send msg to source and target group failed.");
            goto error;
        }

        cunit->state = CHECK_UNIT_STATE_GET_VALUE;
        goto next_step;
    }

    if (cunit->state == CHECK_UNIT_STATE_GET_VALUE) {
        ASSERT(cunit->key != NULL);
        ASSERT(cunit->key_type >= 0);
        ASSERT(cunit->result1 == NULL || cunit->result2 == NULL);
        
        if (cunit->key_type == REDIS_STRING) {
            if (resp->type != MSG_RSP_REDIS_BULK) {
                log_error("ERROR: the response type for %s from node[%s] is error: %s", 
                    rnode->addr, msg_type_string(r->type), msg_type_string(resp->type));
                goto error;
            }
        } else if (cunit->key_type == REDIS_LIST) {

        } else if (cunit->key_type == REDIS_SET) {
            
        } else if (cunit->key_type == REDIS_ZSET) {
            
        } else if (cunit->key_type == REDIS_HASH) {
            
        } else {
            NOT_REACHED();
        }

        if (cunit->result1 == NULL) {
            cunit->result1 = resp;
            resp = NULL;
        } else if (cunit->result2 == NULL) {
            cunit->result2 = resp;
            resp = NULL;
        } else {
            NOT_REACHED();
        }
    
        if (cunit->result1 != NULL && cunit->result2 != NULL) {
            if (cunit->key_type == REDIS_SET) {
                uint32_t j;

                bulks1 = get_multi_bulk_array_from_mbuf_list(cunit->result1->data);
                bulks2 = get_multi_bulk_array_from_mbuf_list(cunit->result2->data);
                if (bulks1 == NULL || bulks2 == NULL) {
                    log_error("ERROR: get multi bulk array from mbufs failed");
                    goto error;
                }

                if (array_n(bulks1) != array_n(bulks2)) {
                    chdata->err_inconsistent_value_keys_count ++;
                    rmt_safe_snprintf(extra_err, 50, ", value is inconsistent\0");
                    goto error;
                }
                
                array_sort(bulks1, string_binary_cmp);
                array_sort(bulks2, string_binary_cmp);

                for (j = 0; j < array_n(bulks1); j ++) {
                    bulk1 = array_get(bulks1, j);
                    bulk2 = array_get(bulks2, j);
                    if (string_binary_cmp(bulk1, bulk2) != 0) {
                        chdata->err_inconsistent_value_keys_count ++;
                        rmt_safe_snprintf(extra_err, 50, ", value is inconsistent\0");
                        goto error;
                    }
                }
            } else if (cunit->key_type == REDIS_HASH) {
                struct array *hash_datas1, *hash_datas2;
                uint32_t hash_len;
                uint32_t j;
                struct hash_data *hd1, *hd2;

                hash_datas1 = hash_datas2 = NULL;
            
                bulks1 = get_multi_bulk_array_from_mbuf_list(cunit->result1->data);
                bulks2 = get_multi_bulk_array_from_mbuf_list(cunit->result2->data);
                if (bulks1 == NULL || bulks2 == NULL) {
                    log_error("ERROR: get multi bulk array from mbufs failed");
                    goto error;
                }

                if (array_n(bulks1)%2 != 0 || array_n(bulks2)%2 != 0) {
                    log_error("ERROR: bad hash value");
                    goto error;
                }

                if (array_n(bulks1) != array_n(bulks2)) {
                    chdata->err_inconsistent_value_keys_count ++;
                    rmt_safe_snprintf(extra_err, 50, ", value is inconsistent\0");
                    goto error;
                }

                hash_len = array_n(bulks1)/2;
                hash_datas1 = array_create(hash_len, sizeof(struct hash_data));
                hash_datas2 = array_create(hash_len, sizeof(struct hash_data));

                for (j = 0; j < hash_len; j ++) {
                    hd1 = array_push(hash_datas1);
                    hd2 = array_push(hash_datas2);

                    bulk1 = array_pop(bulks1);
                    bulk2 = array_pop(bulks1);
                    hd1->field = *bulk1;
                    hd1->value = *bulk2;

                    bulk1 = array_pop(bulks2);
                    bulk2 = array_pop(bulks2);
                    hd2->field = *bulk1;
                    hd2->value = *bulk2;
                }

                array_sort(hash_datas1, hash_data_field_cmp);
                array_sort(hash_datas2, hash_data_field_cmp);

                for (j = 0; j < array_n(bulks1); j ++) {
                    hd1 = array_get(hash_datas1, j);
                    hd2 = array_get(hash_datas2, j);
                    if (string_binary_cmp(hd1->field, hd2->field) != 0) {
                        chdata->err_inconsistent_value_keys_count ++;
                        rmt_safe_snprintf(extra_err, 50, ", value is inconsistent\0");
                        if (hash_datas1 != NULL) {
                            while (array_n(hash_datas1) > 0) {
                                hd1 = array_pop(hash_datas1);
                                sdsfree(hd1->field);
                                sdsfree(hd1->value);
                            }
                            array_destroy(hash_datas1);
                            hash_datas1 = NULL;
                        }
                        if (hash_datas2 != NULL) {
                            while (array_n(hash_datas2) > 0) {
                                hd2 = array_pop(hash_datas2);
                                sdsfree(hd2->field);
                                sdsfree(hd2->value);
                            }
                            array_destroy(hash_datas2);
                            hash_datas2 = NULL;
                        }
                        goto error;
                    }
                    if (string_binary_cmp(hd1->value, hd2->value) != 0) {
                        chdata->err_inconsistent_value_keys_count ++;
                        rmt_safe_snprintf(extra_err, 50, ", value is inconsistent\0");
                        if (hash_datas1 != NULL) {
                            while (array_n(hash_datas1) > 0) {
                                hd1 = array_pop(hash_datas1);
                                sdsfree(hd1->field);
                                sdsfree(hd1->value);
                            }
                            array_destroy(hash_datas1);
                            hash_datas1 = NULL;
                        }
                        if (hash_datas2 != NULL) {
                            while (array_n(hash_datas2) > 0) {
                                hd2 = array_pop(hash_datas2);
                                sdsfree(hd2->field);
                                sdsfree(hd2->value);
                            }
                            array_destroy(hash_datas2);
                            hash_datas2 = NULL;
                        }
                        goto error;
                    }
                }

                if (hash_datas1 != NULL) {
                    while (array_n(hash_datas1) > 0) {
                        hd1 = array_pop(hash_datas1);
                        sdsfree(hd1->field);
                        sdsfree(hd1->value);
                    }
                    array_destroy(hash_datas1);
                    hash_datas1 = NULL;
                }
                if (hash_datas2 != NULL) {
                    while (array_n(hash_datas2) > 0) {
                        hd2 = array_pop(hash_datas2);
                        sdsfree(hd2->field);
                        sdsfree(hd2->value);
                    }
                    array_destroy(hash_datas2);
                    hash_datas2 = NULL;
                }
            } else if (msg_data_compare(cunit->result1, cunit->result2) != 0) {
                chdata->err_inconsistent_value_keys_count ++;
                rmt_safe_snprintf(extra_err, 50, ", value is inconsistent\0");
                goto error;
            }

            msg_put(cunit->result1);
            msg_free(cunit->result1);
            cunit->result1 = NULL;
            msg_put(cunit->result2);
            msg_free(cunit->result2);
            cunit->result2 = NULL;

            if (bulks1 != NULL) {
                while (array_n(bulks1) > 0) {
                    bulk1 = array_pop(bulks1);
                    sdsfree(*bulk1);
                }
                array_destroy(bulks1);
                bulks1 = NULL;
            }
            if (bulks2 != NULL) {
                while (array_n(bulks2) > 0) {
                    bulk2 = array_pop(bulks2);
                    sdsfree(*bulk2);
                }
                array_destroy(bulks2);
                bulks2 = NULL;
            }

            msg = msg_get(r->mb, 1, REDIS_DATA_TYPE_CMD);
            if (msg == NULL) {
                log_error("ERROR: out of memory.");
                goto error;
            }

            arg = array_push(&args);
            *arg = sdsnew("ttl");
            arg = array_push(&args);
            *arg = sdsdup(cunit->key);
            ret = redis_msg_append_command_full_safe(msg, &args);
            if (ret != RMT_OK) {
                log_error("ERROR: msg append multi bulk len failed.");
                goto error;
            }
            while (array_n(&args) > 0) {
                arg = array_pop(&args);
                sdsfree(*arg);
            }
            
            msg->ptr = cunit;
            msg->resp_check = check_response;
            
            ret = send_msg_to_all(cunit, msg);
            if (ret != RMT_OK) {
                log_error("ERROR: send msg to source and target group failed.");
                goto error;
            }
            cunit->state = CHECK_UNIT_STATE_GET_EXPIRE;
        }

        goto next_step;
    }

    if (cunit->state == CHECK_UNIT_STATE_GET_EXPIRE) {
        ASSERT(cunit->key != NULL);
        ASSERT(cunit->key_type >= 0);
        ASSERT(cunit->result1 == NULL || cunit->result2 == NULL);

        if (resp->type != MSG_RSP_REDIS_INTEGER) {
            log_error("ERROR: the response type for command 'ttl' from node[%s] is error: %s", 
                rnode->addr, msg_type_string(resp->type));
            goto error;
        }

        if (cunit->result1 == NULL) {
            cunit->result1 = resp;
            resp = NULL;
        } else if (cunit->result2 == NULL) {
            cunit->result2 = resp;
            resp = NULL;
        } else {
            NOT_REACHED();
        }

        if (cunit->result1 != NULL && cunit->result2 != NULL) {
            if (msg_data_compare(cunit->result1, cunit->result2) != 0) { 
                int mistake = (int)cunit->result1->integer - (int)cunit->result2->integer;
                ASSERT(mistake != 0);

                if (abs(mistake) > TTL_MISTAKE_CAN_BE_ACCEPT) {
                    chdata->err_inconsistent_expire_keys_count ++;
                    rmt_safe_snprintf(extra_err, 50, 
                        ", remaining time are %"PRIu32" and %"PRIu32"\0", 
                        cunit->result1->integer, cunit->result2->integer);
                    goto error;
                }
            }

            /* OK, this key is consistent between source group and target group */
            goto done;
        }

        goto next_step;
    }

done:

    check_unit_destroy(cunit);

next_step:
    
    msg_put(r);
    msg_free(r);
    if (resp != NULL) {
        msg_put(resp);
        msg_free(resp);
    }

    array_deinit(&args);
    
    return RMT_OK;

error:

    chdata->err_check_keys_count ++;

    if (cunit->key != NULL) {        
        log_error("ERROR: key checked failed: %s%s. key(len:%zu, type:%s): %.*s",  
            get_check_error(cunit), extra_err, 
            sdslen(cunit->key), get_redis_type_string(cunit->key_type),
            sdslen(cunit->key), cunit->key);
    } else {
        log_error("ERROR: key checked failed: %s%s.", 
            get_check_error(cunit), extra_err);
    }
    MSG_DUMP(r, LOG_ERR, 1);
    msg_put(r);
    msg_free(r);
    if (resp != NULL) {
        MSG_DUMP(resp, LOG_ERR, 1);
        msg_put(resp);
        msg_free(resp);
    }

    if (msg != NULL) {
        msg_put(msg);
        msg_free(msg);
    }

    check_unit_destroy(cunit);
    
    while (array_n(&args) > 0) {
        arg = array_pop(&args);
        sdsfree(*arg);
    }
    array_deinit(&args);

    if (bulks1 != NULL) {
        while (array_n(bulks1) > 0) {
            bulk1 = array_pop(bulks1);
            sdsfree(*bulk1);
        }
        array_destroy(bulks1);
        bulks1 = NULL;
    }
    if (bulks2 != NULL) {
        while (array_n(bulks2) > 0) {
            bulk2 = array_pop(bulks2);
            sdsfree(*bulk2);
        }
        array_destroy(bulks2);
        bulks2 = NULL;
    }
    
    return RMT_OK;
}
Пример #20
0
char *
conf_add_server(struct conf *cf, struct command *cmd, void *conf)
{
    rstatus_t status;
    struct array *a;
    struct string *value;
    struct conf_server *field;
    uint8_t *p, *q, *start;
    uint8_t *name, *port, *weight;
    uint32_t k, namelen, portlen, weightlen;

    p = conf;
    a = (struct array *)(p + cmd->offset);

    field = array_push(a);
    if (field == NULL) {
        return CONF_ERROR;
    }

    conf_server_init(field);

    value = array_top(&cf->arg);

    status = string_duplicate(&field->pname, value);
    if (status != NC_OK) {
        array_pop(a);
        return CONF_ERROR;
    }

    /* parse "hostname:port:weight" from the end */
    p = value->data + value->len - 1;
    start = value->data;
    name = NULL;
    namelen = 0;
    weight = NULL;
    weightlen = 0;
    port = NULL;
    portlen = 0;

    for (k = 0; k < 2; k++) {
        q = nc_strrchr(p, start, ':');
        if (q == NULL) {
            break;
        }

        switch (k) {
        case 0:
            weight = q + 1;
            weightlen = (uint32_t)(p - weight + 1);
            break;

        case 1:
            port = q + 1;
            portlen = (uint32_t)(p - port + 1);
            break;

        default:
            NOT_REACHED();
        }

        p = q - 1;
    }

    if (k != 2) {
        return "has an invalid \"hostname:port:weight\" format string";
    }

    name = start;
    namelen = (uint32_t)(p - start + 1);

    field->weight = nc_atoi(weight, weightlen);
    if (field->weight < 0) {
        return "has an invalid weight in \"hostname:port:weight\" format string";
    }

    field->port = nc_atoi(port, portlen);
    if (field->port < 0 || !nc_valid_port(field->port)) {
        return "has an invalid port in \"hostname:port:weight\" format string";
    }

    status = string_copy(&field->name, name, namelen);
    if (status != NC_OK) {
        return CONF_ERROR;
    }

    status = nc_resolve(&field->name, field->port, &field->info);
    if (status != NC_OK) {
        return CONF_ERROR;
    }

    field->valid = 1;

    return CONF_OK;
}
Пример #21
0
char *
conf_add_server(struct conf *cf, struct command *cmd, void *conf)
{
    rstatus_t status;
    struct array *a;
    struct string *value;
    struct conf_server *field;
    uint8_t *p, *q, *start;
    uint8_t *pname, *addr, *port, *weight, *name;
    uint32_t k, pnamelen, addrlen, portlen, weightlen, namelen;
    struct string address;
    char delim[] = " ::";

    string_init(&address);
    p = conf;
    a = (struct array *)(p + cmd->offset);

    field = array_push(a);
    if (field == NULL) {
        return CONF_ERROR;
    }

    conf_server_init(field);

    value = array_top(&cf->arg);

    /* parse "hostname:port:weight [name]" from the end */
    p = value->data + value->len - 1;
    start = value->data;
    addr = NULL;
    addrlen = 0;
    weight = NULL;
    weightlen = 0;
    port = NULL;
    portlen = 0;
    name = NULL;
    namelen = 0;

    for (k = 0; k < sizeof(delim); k++) {
        q = nc_strrchr(p, start, delim[k]);
        if (q == NULL) {
            if (k == 0) {
                /*
                 * name in "hostname:port:weight [name]" format string is
                 * optional
                 */
                continue;
            }
            break;
        }

        switch (k) {
        case 0:
            name = q + 1;
            namelen = (uint32_t)(p - name + 1);
            break;

        case 1:
            weight = q + 1;
            weightlen = (uint32_t)(p - weight + 1);
            break;

        case 2:
            port = q + 1;
            portlen = (uint32_t)(p - port + 1);
            break;

        default:
            NOT_REACHED();
        }

        p = q - 1;
    }

    if (k != 3) {
        return "has an invalid \"hostname:port:weight [name]\" format string";
    }

    pname = value->data;
    pnamelen = namelen > 0 ? value->len - (namelen + 1) : value->len;
    status = string_copy(&field->pname, pname, pnamelen);
    if (status != NC_OK) {
        array_pop(a);
        return CONF_ERROR;
    }

    addr = start;
    addrlen = (uint32_t)(p - start + 1);

    field->weight = nc_atoi(weight, weightlen);
    if (field->weight < 0) {
        return "has an invalid weight in \"hostname:port:weight [name]\" format string";
    }

    field->port = nc_atoi(port, portlen);
    if (field->port < 0 || !nc_valid_port(field->port)) {
        return "has an invalid port in \"hostname:port:weight [name]\" format string";
    }

    if (name == NULL) {
        /*
         * To maintain backward compatibility with libmemcached, we don't
         * include the port as the part of the input string to the consistent
         * hashing algorithm, when it is equal to 11211.
         */
        if (field->port == CONF_DEFAULT_KETAMA_PORT) {
            name = addr;
            namelen = addrlen;
        } else {
            name = addr;
            namelen = addrlen + 1 + portlen;
        }
    }

    status = string_copy(&field->name, name, namelen);
    if (status != NC_OK) {
        return CONF_ERROR;
    }

    status = string_copy(&address, addr, addrlen);
    if (status != NC_OK) {
        return CONF_ERROR;
    }

    status = nc_resolve(&address, field->port, &field->info);
    if (status != NC_OK) {
        string_deinit(&address);
        return CONF_ERROR;
    }

    string_deinit(&address);
    field->valid = 1;

    return CONF_OK;
}
Пример #22
0
static data_config *configparser_pop(config_t *ctx) {
  data_config *old = ctx->current;
  ctx->current = (data_config *) array_pop(ctx->configs_stack);
  return old;
}
Пример #23
0
int main(int argc, char *argv[])
{
	struct array a;
	struct array_iterator ai;
	int i;
	int *t, *t_arr;
	
	while ((i = getopt(argc, argv, "vi:")) != -1) {
		switch (i) {
		    case 'v':
			++verbose;
			break;
		    case 'i':
			MAX_ITEMS = atoi(optarg);
			break;
		    default:
			fprintf(stderr, "bad option\n");
			exit(1);
		}
	}
	
	assert(t_arr = malloc(MAX_ITEMS * sizeof(int)));
	array_init(&a, 100);
	
	verbose_print(1, "start\n");
	for (i = 0; i < MAX_ITEMS; i++) {
		t = t_arr + i;
		*t = i;
		assert(array_put(&a, t) == i);
	}
	for (i = 0; i < MAX_ITEMS; i += 2) {
		t = t_arr + i;
		assert(array_remove(&a, t) == t);
	}
	for (i = 1; i < MAX_ITEMS; i += 2) {
		t = t_arr + i;
		assert(array_pop(&a) == t);
	}
	for (i = 0; i < MAX_ITEMS; i += 2) {
		t = t_arr + i;
		assert(array_put_at(&a, i, t) == NULL);
	}
	for (i = 1; i < MAX_ITEMS; i += 2) {
		t = t_arr + i;
		assert(array_put(&a, t) == i);
	}
	for (i = 0; i < MAX_ITEMS; i += 2) {
		t = t_arr + i;
		assert(array_remove_at(&a, i) == t);
	}
	array_iter_set(&ai, &a);
	i = 1;
	while ((t = array_iter_get(&ai))) {
		assert(*t == i);
		i += 2;
		verbose_print(2, "%d ", *t);
	}
	array_iter_end(&ai);
	printf("\n");
	
	array_free(&a);
	
	return 0;
}
Пример #24
0
char *
conf_add_server(struct conf *cf, struct command *cmd, void *conf)
{
    rstatus_t status;
    struct array *a;
    struct string *value;
    struct conf_server *field;
    uint8_t *p, *q, *start;
    uint8_t *pname, *addr, *port, *weight, *name;
    uint32_t k, delimlen, pnamelen, addrlen, portlen, weightlen, namelen;
    char delim[] = " ::";

    p = conf;
    a = (struct array *)(p + cmd->offset);

    field = array_push(a);
    if (field == NULL) {
        return CONF_ERROR;
    }

    conf_server_init(field);

    value = array_top(&cf->arg);

    /* parse "hostname:port:weight [name]" or "/path/unix_socket:weight [name]" from the end */
    p = value->data + value->len - 1;
    start = value->data;
    addr = NULL;
    addrlen = 0;
    weight = NULL;
    weightlen = 0;
    port = NULL;
    portlen = 0;
    name = NULL;
    namelen = 0;

    delimlen = value->data[0] == '/' ? 2 : 3;

    for (k = 0; k < sizeof(delim); k++) {
        q = nc_strrchr(p, start, delim[k]);
        if (q == NULL) {
            if (k == 0) {
                /*
                 * name in "hostname:port:weight [name]" format string is
                 * optional
                 */
                continue;
            }
            break;
        }

        switch (k) {
        case 0:
            name = q + 1;
            namelen = (uint32_t)(p - name + 1);
            break;

        case 1:
            weight = q + 1;
            weightlen = (uint32_t)(p - weight + 1);
            break;

        case 2:
            port = q + 1;
            portlen = (uint32_t)(p - port + 1);
            break;

        default:
            NOT_REACHED();
        }

        p = q - 1;
    }

    if (k != delimlen) {
        return "has an invalid \"hostname:port:weight [name]\"or \"/path/unix_socket:weight [name]\" format string";
    }

    pname = value->data;
    pnamelen = namelen > 0 ? value->len - (namelen + 1) : value->len;
    status = string_copy(&field->pname, pname, pnamelen);
    if (status != NC_OK) {
        array_pop(a);
        return CONF_ERROR;
    }

    addr = start;
    addrlen = (uint32_t)(p - start + 1);

    field->weight = nc_atoi(weight, weightlen);
    if (field->weight < 0) {
        return "has an invalid weight in \"hostname:port:weight [name]\" format string";
    } else if (field->weight == 0) {
        return "has a zero weight in \"hostname:port:weight [name]\" format string";
    }

    if (value->data[0] != '/') {
        field->port = nc_atoi(port, portlen);
        if (field->port < 0 || !nc_valid_port(field->port)) {
            return "has an invalid port in \"hostname:port:weight [name]\" format string";
        }
    }

    if (name == NULL) {
        /*
         * To maintain backward compatibility with libmemcached, we don't
         * include the port as the part of the input string to the consistent
         * hashing algorithm, when it is equal to 11211.
         */
        if (field->port == CONF_DEFAULT_KETAMA_PORT) {
            name = addr;
            namelen = addrlen;
        } else {
            name = addr;
            namelen = addrlen + 1 + portlen;
        }
    }

    status = string_copy(&field->name, name, namelen);
    if (status != NC_OK) {
        return CONF_ERROR;
    }

    status = string_copy(&field->addrstr, (uint8_t *)addr, addrlen);
    if (status != NC_OK) {
        return CONF_ERROR;
    }

    /*
     * The address resolution of the backend server hostname is lazy.
     * The resolution occurs when a new connection to the server is
     * created, which could either be the first time or every time
     * the server gets re-added to the pool after an auto ejection
     */

    field->valid = 1;

    return CONF_OK;
}