Beispiel #1
0
static bool
remove_low_priority_tokens(varray *tokens)
{
    int i, j, to_remove[100], total_to_remove = 0;
    varray *item;
    vtoken *t;

    for (i = 0; i < varray_length (tokens); i++)
    {
        item = varray_get (tokens, i);
        if (varray_length (item) == 1)
            continue;

        for (j = 0; j < varray_length (item); j++)
        {
            t = varray_get (item, j);
            if (t->priority <= VARNAM_TOKEN_PRIORITY_LOW) {
                to_remove[total_to_remove++] = j;
            }
        }

        for (j = 0; j < total_to_remove; j++)
        {
            varray_remove_at (item, to_remove[j] - j);
        }
        total_to_remove = 0;

        if (get_total_possible_patterns (tokens) <= MAXIMUM_PATTERNS_TO_LEARN) {
            return true;
        }
    }

    return false;
}
Beispiel #2
0
static varray*
get_next_array(varray *tokens)
{
    varray *item, *candidate = NULL;
    int i;
    bool same_priority = true;
    vtoken *last, *lowest = NULL;

    for (i = 0; i < varray_length (tokens); i++)
    {
        item = varray_get (tokens, i);

        if (varray_length (item) == 1)
            continue;

        last = varray_get (item, varray_length (item) - 1);
        if (lowest == NULL || last->priority < lowest->priority) {
            lowest = last;
            candidate = item;
        }

        if (last->priority != lowest->priority) {
            same_priority = false;
        }
    }

    if (same_priority)
    {
        candidate = get_largest_array (tokens);
        if (varray_length (candidate) == 1)
            return NULL;
    }

    return candidate;
}
Beispiel #3
0
static void AddEdit(MatchContext *ctx,int op,int off,int len)
{
	DiffEdit *e;

	if(len==0 || ctx->DiffEditArray==NULL) 
	{
		return;
	}               
	/* Add an edit to the SES(or
	* coalesce if the op is the same)
	*/
	e=(DiffEdit *)varray_get(ctx->DiffEditArray,ctx->DiffEditArrayIndex);
	if(e->op==op)
	{
		e->len += len;
	}else if(e)
	{
		if(e->op)
		{
			ctx->DiffEditArrayIndex++;
			e=(DiffEdit *)varray_get(ctx->DiffEditArray,ctx->DiffEditArrayIndex);
		}
		if(e)
		{
			e->op=op;
			e->off=off;
			e->len=len;
		}
	}
}
Beispiel #4
0
static void
apply_acceptance_condition(varray *tokens)
{
    int i, j, to_remove[100], total_to_remove = 0, state, empty_arrays[100], empty_arrays_index = 0;
    varray *item;
    vtoken *t;

    for (i = 0; i < varray_length (tokens); i++)
    {
        if (i == 0)
            state = VARNAM_TOKEN_ACCEPT_IF_STARTS_WITH;
        else if ((i + 1) == varray_length (tokens))
            state = VARNAM_TOKEN_ACCEPT_IF_ENDS_WITH;
        else
            state = VARNAM_TOKEN_ACCEPT_IF_IN_BETWEEN;

        item = varray_get (tokens, i);
        for (j = 0; j < varray_length (item); j++)
        {
            t = varray_get (item, j);
            switch (t->type)
            {
                case VARNAM_TOKEN_VIRAMA:
                case VARNAM_TOKEN_VISARGA:
                case VARNAM_TOKEN_ANUSVARA:
                case VARNAM_TOKEN_NON_JOINER:
                case VARNAM_TOKEN_NUMBER:
                    to_remove[total_to_remove++] = j;
                    break;
                default:
                    if (varray_length (item) != 1 && t->accept_condition != VARNAM_TOKEN_ACCEPT_ALL && t->accept_condition != state) {
                        to_remove[total_to_remove++] = j;
                    }
                    break;
            }
        }

        for (j = 0; j < total_to_remove; j++)
        {
            /* to_remove[j] - j is required to calculate the new index as deleting each item changes index */
            varray_remove_at (item, to_remove[j] - j);
        }

        if (varray_length (item) == 0) {
            /* This happens when all the items in this list is VIRAMA, VISARGA etc */
            empty_arrays[empty_arrays_index++] = i;
        }

        total_to_remove = 0;
    }

    for (i = 0; i < empty_arrays_index; i++)
    {
        varray_remove_at (tokens, empty_arrays[i] - i);
    }
}
Beispiel #5
0
static bool
can_learn_from_tokens (varnam *handle, varray *tokens, const char *word)
{
    bool all_vowels = true, unknown_tokens = false;
    int i, j, repeating_tokens = 0, last_token_id = 0;
    vtoken *t, *unknown_token;
    varray *array;

    if (varray_length (tokens) < 2) {
        set_last_error (handle, "Nothing to learn from '%s'", word);
        return false;
    }

    for (i = 0; i < varray_length (tokens); i++)
    {
        array = varray_get (tokens, i);
        for (j = 0; j < varray_length (array); j++)
        {
            t = varray_get (array, j);

            if (t->type != VARNAM_TOKEN_VOWEL) all_vowels = false;

            if (t->type == VARNAM_TOKEN_OTHER) {
                unknown_tokens = true;
                unknown_token = t;
                goto done;
            }

            if (last_token_id == t->id) {
                ++repeating_tokens;
            }
            else {
                repeating_tokens = 0;
                last_token_id = t->id;
            }
        }
    }

done:
    if (all_vowels) {
        set_last_error (handle, "Word contains only vowels. Nothing to learn from '%s'", word);
        return false;
    }
    else if (unknown_tokens) {
        set_last_error (handle, "Can't process '%s'. One or more characters in '%s' are not known", unknown_token->pattern, word);
        return false;
    }
    else if (repeating_tokens >= 3) {
        set_last_error (handle, "'%s' looks incorrect. Not learning anything", word);
        return false;
    }

    return true;
}
Beispiel #6
0
struct eval *
eval_new(symlook_fn symlook, void *context)
{
	struct eval *eval;
	struct tok *em;

	if ((eval = malloc(sizeof *eval)) == NULL) {
		PMNO(errno);
		return NULL;
	}

	memset(eval, 0, sizeof *eval);
	if ((eval->toks = varray_new(sizeof(struct tok), NULL)) == NULL ||
			(eval->opstk = stack_new(4096, NULL)) == NULL ||
			(eval->stk = stack_new(4096, NULL)) == NULL ||
			(em = varray_get(eval->toks, eval->toki++)) == NULL) {
		AMSG("");
		eval_del(eval);
		return NULL;
	}
	eval->context = context;
	eval->symlook = symlook;
	em->type = TOK_TYPE_EMPTY;
	stack_push(eval->opstk, em);

	return eval;
}
Beispiel #7
0
void*
varray_get_last_item(varray *array)
{
    assert (array);

    return varray_get (array, array->index);
}
Beispiel #8
0
static int
next_tok(struct eval *eval, const tchar *src, const tchar *slim, struct tok **tok)
{
	tchar buf[255];
	int ret, i;

	*tok = varray_get(eval->toks, eval->toki++);
	if ((ret = next(src, slim, buf, buf + 255)) > 0) { 
		for (i = TOK_TYPE_BITOR; i < TOK_TYPE_VALUE; i++) {
			if (*buf == ops[i]) {
				break;
			}
		}
		(*tok)->type = i;
		if (i == TOK_TYPE_VALUE) {
			if (istdigit(*buf)) {
				(*tok)->val = tcstoul((const char *)buf, NULL, 0);
			} else {
				if (eval->symlook(buf, &(*tok)->val, eval->context) == -1) {
					T1PMNF(errno = ENOENT, buf);
					return -1;
				}
			}
		}
	} else {
		(*tok)->type = TOK_TYPE_EMPTY;
	}

	return ret;
}
Beispiel #9
0
void model_draw(struct Model *model, float *mMat, float *vMat, float *pMat)
{
    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);

    mat4 t_matrix;
    mat4_identity(t_matrix);
    mat4_mult(mMat, t_matrix, t_matrix);
    mat4_mult(vMat, t_matrix, t_matrix);
    mat4_mult(pMat, t_matrix, t_matrix);
    //mat4_transpose(t_matrix);

    int i;
    for(i = 0; i < varray_length(&model->features); i++)
    {
        static int FALSE = 0;
        const ModelFeature *feature = varray_get(&model->features, i);
        glbProgramTexture(glbdrawmodel, GLB_FRAGMENT_SHADER, 0, feature->color);
        glbProgramUniformMatrix(glbdrawmodel, GLB_VERTEX_SHADER, 0, 
                sizeof(int), true, &FALSE);
        glbProgramUniformMatrix(glbdrawmodel, GLB_VERTEX_SHADER, 1, 
                sizeof(float[16]), true, t_matrix);
        glbProgramDrawIndexed(glbdrawmodel, feature->mesh->vbuffer, feature->mesh->ibuffer);

    }
}
Beispiel #10
0
static int _v(MatchContext *ctx,int k,int r)
{
	int j;

	j=k <= 0 ? -k * 4+r : k * 4 +(r - 2);

	return *((int *)varray_get(ctx->buf,j));
}
void _varray_dump(varray_t* v)
{
    int i;
    for (i = 0; i < varray_length(v); i++)
    {
        printf("'%s', ", (char*)varray_get(v, i));
    }
    printf("\n");
}
Beispiel #12
0
static void _setv(MatchContext *ctx,int k,int r,int val)
{
	int j;
	int *i;
                /* Pack -N to N into 0 to N * 2
                 */
	j=k <= 0 ? -k * 4+r : k * 4 +(r - 2);

	i=(int *)varray_get(ctx->buf,j);
	*i=val;
}
Beispiel #13
0
int
AdtInit(int verbose, struct cfg *cfg, char *args[])
{
	char buf[0xFFFF];
	struct allocator *suba;
	struct stack s;
	struct linkedlist l;
	struct varray va;

	if ((suba = suba_init(buf, 0xFFFF, 1, 0)) == NULL ||
			stack_init(&s, 0, suba) == -1 ||
			linkedlist_init(&l, 0, suba) == -1 ||
			varray_init(&va, sizeof(int), suba) == -1) {
		AMSG("");
		return -1;
	}

	linkedlist_add(&l, "two");
	stack_push(&s, "two");
	linkedlist_add(&l, "three");
	stack_push(&s, "one");
	varray_get(&va, 444);
	stack_push(&s, "three");
	varray_get(&va, 4);
	varray_get(&va, 44);
	linkedlist_add(&l, "one");

	if (varray_deinit(&va) != 0 ||
			linkedlist_deinit(&l, NULL, NULL) != 0 ||
			stack_deinit(&s, NULL, NULL) != 0) {
		AMSG("");
		return -1;
	}

	tcase_printf(verbose, "done ");

	cfg = NULL;
	args[0] = NULL;
    return 0;
}
Beispiel #14
0
bool
varray_exists (varray *array, void *item, bool (*equals)(void *left, void *right))
{
    int i;

    for (i = 0; i < varray_length (array); i++)
    {
        if (equals(varray_get (array, i), item))
            return true;
    }

    return false;
}
END_TEST

START_TEST(test_sort)
{
    srand(12345);
    int i, j;
    uint64_t t1, t2, tt;
    tt = 0;
    int num_repeats = 10;
    int max_size = 20000;
    for(i = 0; i < num_repeats; i++)
    {
        varray_t* v = varray_new();
        int size = _random64() % max_size;
        for(j = 0; j < size; j++)
        {
            varray_add(v, _new_int64(_random64()));
        }

        t1 = gettimeusec();
        varray_sort(v, _cmp_int64);
        t2 = gettimeusec();
        tt += t2 - t1;

        for(j = 0; j < varray_length(v) - 1; j++)
        {
            fail_unless(_cmp_int64( varray_get(v, j), varray_get(v, j+1) ) <= 0, "array not sorted correctly");
        }
        
        for(j = varray_length(v) - 1; j >= 0; j--)
        {
            free( varray_get(v, j) );
            varray_remove(v, j);
        }
        varray_free(v);
    }

    if (verbose) { printf("sort loop: %f /sec (%d repeats, %d array size)\n", (1000000*(double)num_repeats)/tt, num_repeats, max_size/2); }
}
Beispiel #16
0
void
varray_copy(varray *source, varray *destination)
{
    int i;
    void *item;

    if (source == NULL) return;
    if (destination == NULL) return;

    for (i = 0; i < varray_length (source); i++) {
        item = varray_get (source, i);
        varray_push (destination, item);
    }
}
Beispiel #17
0
static int
get_total_possible_patterns(varray *tokens)
{
    int total = 1, i = 0;
    varray *item;

    for (i = 0; i < varray_length (tokens); i++)
    {
        item = varray_get (tokens, i);
        total *= varray_length (item);
    }

    return total;
}
Beispiel #18
0
END_TEST

START_TEST (indic_digit_rendering)
{
    int rc;
    vword* word;
    varray *words;

    rc = varnam_transliterate (varnam_instance, "01", &words);
    assert_success (rc);
    ck_assert_int_eq (varray_length (words), 1);
    word = varray_get (words, 0);
    ck_assert_str_eq (word->text, "01");

    rc = varnam_config (varnam_instance, VARNAM_CONFIG_USE_INDIC_DIGITS, 1);
    assert_success (rc);

    rc = varnam_transliterate (varnam_instance, "01", &words);
    assert_success (rc);
    ck_assert_int_eq (varray_length (words), 1);
    word = varray_get (words, 0);
    ck_assert_str_eq (word->text, "०१");
}
// expects a NULL-terminated string array
int _varray_cmp_to_string_array(varray_t* v, const char** strs)
{
    int i = 0;
    int result = 0;
    while (strs[i] != NULL)
    {
        char* e = (char*)varray_get(v, i);
        if (e == NULL) { result = -2; continue; }
        if (result == 0) { result = strcmp(e, strs[i]); }
        i++;
    }
    if (varray_length(v) != i) { result = -3; }
    return result;
}
Beispiel #20
0
END_TEST

START_TEST (dependent_vowel_rendering)
{
    int rc;
    vword* word;
    varray *words;

    rc = varnam_transliterate(varnam_instance, "aaa", &words);
    assert_success (rc);
    ck_assert_int_eq (varray_length(words), 1);

    word = varray_get(words, 0);
    ck_assert_str_eq (word->text, "aa-value1a-value2");
}
Beispiel #21
0
END_TEST

START_TEST (cancellation_character_should_force_independent_vowel_form)
{
    int rc;
    vword* word;
    varray *words;

    rc = varnam_transliterate(varnam_instance, "aa_a", &words);
    assert_success (rc);
    ck_assert_int_eq (varray_length(words), 1);

    word = varray_get(words, 0);
    ck_assert_str_eq (word->text, "aa-value1a-value1");
}
Beispiel #22
0
static varray*
get_largest_array(varray *tokens)
{
    int i;
    varray *item = NULL, *largest = NULL;

    for (i = 0; i < varray_length (tokens); i++)
    {
        item = varray_get (tokens, i);
        if (largest == NULL || varray_length (item) > varray_length (largest)) {
            largest = item;
        }
    }

    return largest;
}
Beispiel #23
0
static
void _vroute_srvc_space_inspect(struct vroute_srvc_space* space, vroute_srvc_space_inspect_t cb, void* cookie, vnonce* nonce, uint32_t insp_id)
{
    struct varray* services = NULL;
    int i = 0;
    int j = 0;

    vassert(space);
    vassert(insp_id);

    for (i = 0; i < NBUCKETS; i++) {
        services = &space->bucket[i].srvcs;
        for (j = 0; j < varray_size(services); j++) {
            cb((struct vservice*)varray_get(services, j), cookie, nonce, insp_id);
        }
    }
    return ;
}
Beispiel #24
0
int GetStringSimilarity(const char *a,const char *b)
{
	int n,m,d;
	int sn,i;
	struct varray ses;

	varray_init(&ses,sizeof(DiffEdit),NULL);
	n=strlen(a);
	m=strlen(b);
	if ((d=DiffArray(
		a,0,n,
		b,0,m,
		NULL,0,&ses,&sn,NULL)) == -1) 
	{
		return 0;
	}

	int match_len=0;
	int unmatch_len=0;
	for (i=0; i < sn; i++) {
		DiffEdit *e=(DiffEdit *)varray_get(&ses,i);
		switch (e->op)
		{
			case DIFF_MATCH:
				//fwrite(a + e->off,1,e->len,stdout);
				match_len+=e->len*2;
				break;
			case DIFF_INSERT:
				unmatch_len+=e->len;
				break;
			case DIFF_DELETE:
				unmatch_len+=e->len;
				break;
		}
	}
	if(match_len+unmatch_len==0)
	{
		return 100;
	}
	return (match_len*100)/(match_len+unmatch_len);
}
Beispiel #25
0
void
ensure_word_list_contains(varray *words, const char *word)
{
    int i = 0, found = 0;
    vword *w;
    strbuf *error;

    for (i = 0; i < varray_length (words); i++) {
        w = varray_get (words, i);
        if (strcmp (w->text, word) == 0) {
            found = 1;
            break;
        }
    }

    if (!found) {
        error = strbuf_init (50);
        strbuf_addf (error, "Expected word list to contain '%s'", word);
        ck_abort_msg (strbuf_to_s (error));
    }
}
Beispiel #26
0
END_TEST

START_TEST (confidence_should_get_updated_for_existing_words)
{
    int rc;
    varray* words;
    vword* word;
    const char *word_to_learn = "കഖ";

    rc = varnam_learn (varnam_instance, word_to_learn);
    assert_success (rc);
    rc = varnam_learn (varnam_instance, word_to_learn);
    assert_success (rc);

    rc = varnam_transliterate (varnam_instance, "kagha", &words);
    assert_success (rc);
    ck_assert_int_eq (varray_length (words), 2);

    word = varray_get (words, 0);
    ck_assert_int_eq (word->confidence, 2);
}
Beispiel #27
0
void
varray_free(varray *array, void (*destructor)(void*))
{
    int i;
    void *item;

    if (array == NULL)
        return;

    if (destructor != NULL)
    {
        for(i = 0; i < varray_length(array); i++)
        {
            item = varray_get (array, i);
            if (item != NULL) destructor(item);
        }
    }

    if (array->memory != NULL)
        free(array->memory);
    free(array);
}
Beispiel #28
0
/*
 * the routine to dump all service nodes in service routing table
 *
 * @space:
 */
static
void _vroute_srvc_space_dump(struct vroute_srvc_space* space, vdump_t dcb)
{
    struct varray* services = NULL;
    int titled = 0;
    int i = 0;
    int j = 0;

    vassert(space);

    for (i = 0; i < NBUCKETS; i++) {
        services = &space->bucket[i].srvcs;
        for (j = 0; j < varray_size(services); j++) {
            if (!titled) {
                dcb("-> list of services in service routing space:");
                titled = 1;
            }
            vservice_dump((struct vservice*)varray_get(services, j), dcb);
        }
    }
    return;
}
Beispiel #29
0
/*
 * the routine to pack a @ping query and send it.
 * @route:
 * @conn:
 */
static
int _vroute_dht_ping(struct vroute* route, vnodeConn* conn)
{
    struct vroute_recr_space* recr_space = &route->recr_space;
    void* buf = NULL;
    vtoken token;
    int ret = 0;

    vassert(route);
    vassert(conn);
    retS((!(route->props & PROP_PING))); //ping disabled.

    buf = vdht_buf_alloc();
    retE((!buf));

    vtoken_make(&token);
    ret = route->enc_ops->ping(&token, &route->myid, buf, vdht_buf_len());
    ret1E((ret < 0), vdht_buf_free(buf));
    {
        struct vmsg_usr msg = {
            .addr  = to_vsockaddr_from_sin(&conn->remote),
            .spec  = to_vsockaddr_from_sin(&conn->local),
            .msgId = VMSG_DHT,
            .data  = buf,
            .len   = ret
        };
        ret = route->msger->ops->push(route->msger, &msg);
        ret1E((ret < 0), vdht_buf_free(buf));
    }
    route->ops->inspect(route, &token, VROUTE_INSP_SND_PING);

    // make a record according to the query, which will be used to
    // check invality of response msg.
    recr_space->ops->make(recr_space, &token);
    vlogD("send @ping");
    return 0;
}


/*
 * the routine to pack and send a response to @ping query back to source node
 * where the ping query was from.
 * @route:
 * @conn:
 * @token:
 * @info :
 */
static
int _vroute_dht_ping_rsp(struct vroute* route, vnodeConn* conn, vtoken* token, vnodeInfo* nodei)
{
    void* buf = NULL;
    int ret = 0;

    vassert(route);
    vassert(conn);
    vassert(token);
    vassert(nodei);
    retS((!(route->props & PROP_PING_R)));

    buf = vdht_buf_alloc();
    retE((!buf));

    ret = route->enc_ops->ping_rsp(token, &route->myid, nodei, buf, vdht_buf_len());
    ret1E((ret < 0), vdht_buf_free(buf));
    {
        struct vmsg_usr msg = {
            .addr  = to_vsockaddr_from_sin(&conn->remote),
            .spec  = to_vsockaddr_from_sin(&conn->local),
            .msgId = VMSG_DHT,
            .data  = buf,
            .len   = ret
        };
        ret = route->msger->ops->push(route->msger, &msg);
        ret1E((ret < 0), vdht_buf_free(buf));
    }
    vlogD("send @ping_rsp");
    return 0;
}

/*
 * the routine to pack and send @find_node query to specific node to get infos
 * of a given node.
 * @route:
 * @conn:
 * @target
 */
static
int _vroute_dht_find_node(struct vroute* route, vnodeConn* conn, vnodeId* targetId)
{
    struct vroute_recr_space* recr_space = &route->recr_space;
    void* buf = NULL;
    vtoken token;
    int ret = 0;

    vassert(route);
    vassert(conn);
    vassert(targetId);
    retS((!(route->props & PROP_FIND_NODE)));

    buf = vdht_buf_alloc();
    retE((!buf));

    vtoken_make(&token);
    ret = route->enc_ops->find_node(&token, &route->myid, targetId, buf, vdht_buf_len());
    ret1E((ret < 0), vdht_buf_free(buf));
    {
        struct vmsg_usr msg = {
            .addr  = to_vsockaddr_from_sin(&conn->remote),
            .spec  = to_vsockaddr_from_sin(&conn->local),
            .msgId = VMSG_DHT,
            .data  = buf,
            .len   = ret
        };
        ret = route->msger->ops->push(route->msger, &msg);
        ret1E((ret < 0), vdht_buf_free(buf));
    }
    route->ops->inspect(route, &token, VROUTE_INSP_SND_FIND_NODE);
    recr_space->ops->make(recr_space, &token);
    vlogD("send @find_node");
    return 0;
}

/*
 * the routine to pack and send a response to @find_node query.
 * @route:
 * @conn:
 * @token:
 * @info:
 */
static
int _vroute_dht_find_node_rsp(struct vroute* route, vnodeConn* conn, vtoken* token, vnodeInfo* nodei)
{
    void* buf = NULL;
    int ret = 0;

    vassert(route);
    vassert(conn);
    vassert(token);
    vassert(nodei);
    retS((!(route->props & PROP_FIND_NODE_R)));

    buf = vdht_buf_alloc();
    retE((!buf));

    ret = route->enc_ops->find_node_rsp(token, &route->myid, nodei, buf, vdht_buf_len());
    ret1E((ret < 0), vdht_buf_free(buf));
    {
        struct vmsg_usr msg = {
            .addr  = to_vsockaddr_from_sin(&conn->remote),
            .spec  = to_vsockaddr_from_sin(&conn->local),
            .msgId = VMSG_DHT,
            .data  = buf,
            .len   = ret
        };
        ret = route->msger->ops->push(route->msger, &msg);
        ret1E((ret < 0), vdht_buf_free(buf));
    }
    vlogD("send @find_node_rsp");
    return 0;
}

/*
 * the routine to pack and send a @find_closest_nodes query( closest to @targetId).
 * @route:
 * @conn:
 * @targetId:
 */
static
int _vroute_dht_find_closest_nodes(struct vroute* route, vnodeConn* conn, vnodeId* targetId)
{
    struct vroute_recr_space* recr_space = &route->recr_space;
    void* buf = NULL;
    vtoken token;
    int ret = 0;

    vassert(route);
    vassert(conn);
    vassert(targetId);
    retS((!(route->props & PROP_FIND_CLOSEST_NODES)));

    buf = vdht_buf_alloc();
    retE((!buf));

    vtoken_make(&token);
    ret = route->enc_ops->find_closest_nodes(&token, &route->myid, targetId, buf, vdht_buf_len());
    ret1E((ret < 0), vdht_buf_free(buf));
    {
        struct vmsg_usr msg = {
            .addr  = to_vsockaddr_from_sin(&conn->remote),
            .spec  = to_vsockaddr_from_sin(&conn->local),
            .msgId = VMSG_DHT,
            .data  = buf,
            .len   = ret
        };
        ret = route->msger->ops->push(route->msger, &msg);
        ret1E((ret < 0), vdht_buf_free(buf));
    }
    route->ops->inspect(route, &token, VROUTE_INSP_SND_FIND_CLOSEST_NODES);
    recr_space->ops->make(recr_space, &token);
    vlogD("send @find_closest_nodes");
    return 0;
}

/*
 * the routine to pack and send back a response to @find_closest_nodes query.
 * @route:
 * @conn:
 * @token:
 * @closest: array of closest nodes (closest to given id);
 */
static
int _vroute_dht_find_closest_nodes_rsp(struct vroute* route, vnodeConn* conn, vtoken* token, struct varray* closest)
{
    void* buf = NULL;
    int ret = 0;

    vassert(route);
    vassert(conn);
    vassert(token);
    vassert(closest);
    retS((!(route->props & PROP_FIND_CLOSEST_NODES_R)));

    buf = vdht_buf_alloc();
    retE((!buf));

    ret = route->enc_ops->find_closest_nodes_rsp(token, &route->myid, closest, buf, vdht_buf_len());
    ret1E((ret < 0), vdht_buf_free(buf));
    {
        struct vmsg_usr msg = {
            .addr  = to_vsockaddr_from_sin(&conn->remote),
            .spec  = to_vsockaddr_from_sin(&conn->local),
            .msgId = VMSG_DHT,
            .data  = buf,
            .len   = ret
        };
        ret = route->msger->ops->push(route->msger, &msg);
        ret1E((ret < 0), vdht_buf_free(buf));
    }
    vlogD("send @find_closest_nodes_rsp");
    return 0;
}

/*
 * the routine to pack and send a @reflex_addr query.
 * @route:
 * @conn:
 */
static
int _vroute_dht_reflex(struct vroute* route, vnodeConn* conn)
{
    struct vroute_recr_space* recr_space = &route->recr_space;
    void* buf = NULL;
    vtoken token;
    int ret = 0;

    vassert(route);
    vassert(conn);

    buf = vdht_buf_alloc();
    retE((!buf));

    vtoken_make(&token);
    ret = route->enc_ops->reflex(&token, &route->myid, buf, vdht_buf_len());
    ret1E((ret < 0), vdht_buf_free(buf));
    {
        struct vmsg_usr msg = {
            .addr  = to_vsockaddr_from_sin(&conn->remote),
            .spec  = to_vsockaddr_from_sin(&conn->local),
            .msgId = VMSG_DHT,
            .data  = buf,
            .len   = ret
        };
        ret = route->msger->ops->push(route->msger, &msg);
        ret1E((ret < 0), vdht_buf_free(buf));
    }
    route->ops->inspect(route, &token, VROUTE_INSP_SND_REFLEX);
    recr_space->ops->make(recr_space, &token);
    vlogD("send @reflex");
    return 0;
}

/*
 * the routine to pack and send back a response to @reflex_addr query.
 * @route:
 * @conn:
 * @token:
 * @reflexive_addr:
 */
static
int _vroute_dht_reflex_rsp(struct vroute* route, vnodeConn* conn, vtoken* token, struct sockaddr_in* reflexive_addr)
{
    void* buf = NULL;
    int ret = 0;

    vassert(route);
    vassert(conn);
    vassert(token);
    vassert(reflexive_addr);

    buf = vdht_buf_alloc();
    retE((!buf));

    ret = route->enc_ops->reflex_rsp(token, &route->myid, reflexive_addr, buf, vdht_buf_len());
    ret1E((ret < 0), vdht_buf_free(buf));
    {
        struct vmsg_usr msg = {
            .addr  = to_vsockaddr_from_sin(&conn->remote),
            .spec  = to_vsockaddr_from_sin(&conn->local),
            .msgId = VMSG_DHT,
            .data  = buf,
            .len   = ret
        };
        ret = route->msger->ops->push(route->msger, &msg);
        ret1E((ret < 0), vdht_buf_free(buf));
    }
    vlogD("send @reflex_rsp");
    return 0;
}

/*
 * the routine to pack and send a @probe_connectivity query
 * @route:
 * @conn:
 * @targetId:
 */
static
int _vroute_dht_probe(struct vroute* route, vnodeConn* conn, vnodeId* targetId)
{
    struct vroute_recr_space* recr_space = &route->recr_space;
    void* buf = NULL;
    vtoken token;
    int ret = 0;

    vassert(route);
    vassert(conn);
    vassert(targetId);

    buf = vdht_buf_alloc();
    retE((!buf));

    vtoken_make(&token);
    ret = route->enc_ops->probe(&token, &route->myid, targetId, buf, vdht_buf_len());
    ret1E((ret < 0), vdht_buf_free(buf));
    {
        struct vmsg_usr msg = {
            .addr  = to_vsockaddr_from_sin(&conn->remote),
            .spec  = to_vsockaddr_from_sin(&conn->local),
            .msgId = VMSG_DHT,
            .data  = buf,
            .len   = ret
        };
        ret = route->msger->ops->push(route->msger, &msg);
        ret1E((ret < 0), vdht_buf_free(buf));
    }
    route->ops->inspect(route, &token, VROUTE_INSP_SND_PROBE);
    recr_space->ops->make(recr_space, &token);
    vlogD("send @probe");
    return 0;
}

/*
 * the routine to pack and send back a response to @probe_connectivity query.
 * @route:
 * @conn:
 * @token:
 */
static
int _vroute_dht_probe_rsp(struct vroute* route, vnodeConn* conn, vtoken* token)
{
    void* buf = NULL;
    int ret = 0;

    vassert(route);
    vassert(conn);
    vassert(token);

    buf = vdht_buf_alloc();
    retE((!buf));

    ret = route->enc_ops->probe_rsp(token, &route->myid, buf, vdht_buf_len());
    ret1E((ret < 0), vdht_buf_free(buf));
    {
        struct vmsg_usr msg = {
            .addr  = to_vsockaddr_from_sin(&conn->remote),
            .spec  = to_vsockaddr_from_sin(&conn->local),
            .msgId = VMSG_DHT,
            .data  = buf,
            .len   = ret
        };
        ret = route->msger->ops->push(route->msger, &msg);
        ret1E((ret < 0), vdht_buf_free(buf));
    }
    vlogD("send @probe_rsp");
    return 0;
}

/*
 * the routine to pack and send @post_service indication.
 * @route:
 * @conn:
 * @srvc:
 */
static
int _vroute_dht_post_service(struct vroute* route, vnodeConn* conn, vsrvcInfo* srvci)
{
    void* buf = NULL;
    vtoken token;
    int ret = 0;

    vassert(route);
    vassert(conn);
    vassert(srvci);
    retS((!(route->props & PROP_POST_SERVICE)));

    buf = vdht_buf_alloc();
    retE((!buf));

    vtoken_make(&token);
    ret = route->enc_ops->post_service(&token, &route->myid, srvci, buf, vdht_buf_len());
    ret1E((ret < 0), vdht_buf_free(buf));
    {
        struct vmsg_usr msg = {
            .addr  = to_vsockaddr_from_sin(&conn->remote),
            .spec  = to_vsockaddr_from_sin(&conn->local),
            .msgId = VMSG_DHT,
            .data  = buf,
            .len   = ret
        };
        ret = route->msger->ops->push(route->msger, &msg);
        ret1E((ret < 0), vdht_buf_free(buf));
    }
    vlogD("send @post_service");
    return 0;
}

/*
 * the routine to pack and send a @find_service query.
 * @route:
 * @conn:
 * @srvcId:
 */
static
int _vroute_dht_find_service(struct vroute* route, vnodeConn* conn, vsrvcHash* hash)
{
    struct vroute_recr_space* recr_space = &route->recr_space;
    void* buf = NULL;
    vtoken token;
    int ret = 0;

    vassert(route);
    vassert(conn);
    vassert(hash);
    retS((!(route->props & PROP_FIND_SERVICE)));

    buf = vdht_buf_alloc();
    retE((!buf));

    vtoken_make(&token);
    ret = route->enc_ops->find_service(&token, &route->myid, hash, buf, vdht_buf_len());
    ret1E((ret < 0), vdht_buf_free(buf));
    {
        struct vmsg_usr msg = {
            .addr  = to_vsockaddr_from_sin(&conn->remote),
            .spec  = to_vsockaddr_from_sin(&conn->local),
            .msgId = VMSG_DHT,
            .data  = buf,
            .len   = ret
        };
        ret = route->msger->ops->push(route->msger, &msg);
        ret1E((ret < 0), vdht_buf_free(buf));
    }

    route->ops->inspect(route, &token, VROUTE_INSP_SND_FIND_SERVICE);
    recr_space->ops->make(recr_space, &token);
    vlogD("send @find_service");
    return 0;
}

/*
 * the routine to pack and send a response to @find_service query.
 * @route:
 * @conn:
 * @token:
 * @srvcs:
 */
static
int _vroute_dht_find_service_rsp(struct vroute* route, vnodeConn* conn, vtoken* token, vsrvcInfo* srvc)
{
    void* buf = NULL;
    int ret = 0;

    vassert(route);
    vassert(conn);
    vassert(token);
    vassert(srvc);
    retS((!(route->props & PROP_FIND_SERVICE_R)));

    buf = vdht_buf_alloc();
    retE((!buf));

    ret = route->enc_ops->find_service_rsp(token, &route->myid, srvc, buf, vdht_buf_len());
    ret1E((ret < 0), vdht_buf_free(buf));
    {
        struct vmsg_usr msg = {
            .addr  = to_vsockaddr_from_sin(&conn->remote),
            .spec  = to_vsockaddr_from_sin(&conn->local),
            .msgId = VMSG_DHT,
            .data  = buf,
            .len   = ret
        };
        ret = route->msger->ops->push(route->msger, &msg);
        ret1E((ret < 0), vdht_buf_free(buf));
    }
    vlogD("send @find_service_rsp");
    return 0;
}

static
struct vroute_dht_ops route_dht_ops = {
    .ping                   = _vroute_dht_ping,
    .ping_rsp               = _vroute_dht_ping_rsp,
    .find_node              = _vroute_dht_find_node,
    .find_node_rsp          = _vroute_dht_find_node_rsp,
    .find_closest_nodes     = _vroute_dht_find_closest_nodes,
    .find_closest_nodes_rsp = _vroute_dht_find_closest_nodes_rsp,
    .reflex                 = _vroute_dht_reflex,
    .reflex_rsp             = _vroute_dht_reflex_rsp,
    .probe                  = _vroute_dht_probe,
    .probe_rsp              = _vroute_dht_probe_rsp,
    .post_service           = _vroute_dht_post_service,
    .find_service           = _vroute_dht_find_service,
    .find_service_rsp       = _vroute_dht_find_service_rsp
};

static
void _aux_vnodeInfo_free(void* item, void* cookie)
{
    vnodeInfo_relax* nodei = (vnodeInfo_relax*)item;
    vassert(nodei);

    vnodeInfo_relax_free(nodei);
    return ;
}

/* the routine to call when receiving a @ping query.
 *
 * @route:
 * @conn:
 * @ctxt:  dht decoder context.
 */
static
int _vroute_cb_ping(struct vroute* route, vnodeConn* conn, void* ctxt)
{
    struct vroute_node_space* node_space = &route->node_space;
    vnodeInfo_relax nodei_relax;
    vnodeInfo* nodei = (vnodeInfo*)&nodei_relax;
    vnodeId fromId;
    vtoken  token;
    int ret = 0;

    vassert(route);
    vassert(conn);
    vassert(ctxt);

    ret =route->dec_ops->ping(ctxt, &token, &fromId);
    retE((ret < 0));

    vnodeInfo_relax_init(&nodei_relax, &fromId, vnodeVer_unknown(), 0);
    vnodeInfo_add_addr(&nodei, &conn->remote);
    ret = node_space->ops->add_node(node_space, nodei, 1);
    retE((ret < 0));

    route->ops->inspect(route, &token, VROUTE_INSP_RCV_PING);
    ret = route->dht_ops->ping_rsp(route, conn, &token, (vnodeInfo*)&route->node->nodei);
    retE((ret < 0));
    return 0;
}

/*
 * the routine to call when receving a response to @ping query.
 *
 * @route:
 * @conn:
 * @ctxt:
 */
static
int _vroute_cb_ping_rsp(struct vroute* route, vnodeConn* conn, void* ctxt)
{
    struct vroute_node_space* node_space = &route->node_space;
    struct vroute_recr_space* recr_space = &route->recr_space;
    vnodeInfo_relax nodei;
    vtoken  token;
    int ret = 0;

    ret = route->dec_ops->ping_rsp(ctxt, &token, (vnodeInfo*)&nodei);
    retE((ret < 0));
    retE((!recr_space->ops->check(recr_space, &token))); // skip vicious response.

    ret = node_space->ops->add_node(node_space, (vnodeInfo*)&nodei, 1);
    retE((ret < 0));
    route->ops->inspect(route, &token, VROUTE_INSP_RCV_PING_RSP);
    return 0;
}

/*
 * the routine to call when receiving a @find_node query.
 *
 * @route:
 * @conn:
 * @ctxt:
 */
static
int _vroute_cb_find_node(struct vroute* route, vnodeConn* conn, void* ctxt)
{
    struct vroute_node_space* node_space = &route->node_space;
    vnodeInfo_relax nodei;
    struct varray closest;
    vnodeId targetId;
    vnodeId fromId;
    vtoken token;
    int ret = 0;

    vassert(route);
    vassert(conn);
    vassert(ctxt);

    ret = route->dec_ops->find_node(ctxt, &token, &fromId, &targetId);
    retE((ret < 0));
    ret = node_space->ops->get_node(node_space, &targetId, (vnodeInfo*)&nodei);
    retE((ret < 0));
    if (ret == 1) { //means found
        ret = route->dht_ops->find_node_rsp(route, conn, &token, (vnodeInfo*)&nodei);
        retE((ret < 0));
        return 0;
    }

    // otherwise, send @find_closest_nodes_rsp response instead.
    varray_init(&closest, MAX_CAPC);
    ret = node_space->ops->get_neighbors(node_space, &targetId, &closest, MAX_CAPC);
    ret1E((ret < 0), varray_deinit(&closest));
    if (ret == 0) { //means no closest nodes.
        varray_deinit(&closest);
        return 0;
    }
    ret = route->dht_ops->find_closest_nodes_rsp(route, conn, &token, &closest);
    varray_zero(&closest, _aux_vnodeInfo_free, NULL);
    varray_deinit(&closest);
    retE((ret < 0));
    return 0;
}

/*
 * the routine to call when receiving a response to @find_node query.
 *
 * @route:
 * @conn:
 * @ctxt:
 */
static
int _vroute_cb_find_node_rsp(struct vroute* route, vnodeConn* conn, void* ctxt)
{
    struct vroute_node_space* node_space = &route->node_space;
    struct vroute_recr_space* recr_space = &route->recr_space;
    vnodeInfo_relax nodei;
    vnodeId fromId;
    vtoken  token;
    int ret = 0;

    vassert(route);
    vassert(conn);
    vassert(ctxt);

    ret = route->dec_ops->find_node_rsp(ctxt, &token, &fromId, (vnodeInfo*)&nodei);
    retE((ret < 0));
    retE((!recr_space->ops->check(recr_space, &token)));

    ret = node_space->ops->add_node(node_space, (vnodeInfo*)&nodei, 0);
    retE((ret < 0));

    route->ops->inspect(route, &token, VROUTE_INSP_RCV_FIND_NODE_RSP);
    return 0;
}

/*
 * the routine to call when receiving a @find_closest_nodes query.
 *
 * @route:
 * @conn:
 * @ctxt:
 */
static
int _vroute_cb_find_closest_nodes(struct vroute* route, vnodeConn* conn, void* ctxt)
{
    struct vroute_node_space* node_space = &route->node_space;
    struct varray closest;
    vnodeId targetId;
    vnodeId fromId;
    vtoken  token;
    int ret = 0;

    vassert(route);
    vassert(conn);
    vassert(ctxt);

    ret = route->dec_ops->find_closest_nodes(ctxt, &token, &fromId, &targetId);
    retE((ret < 0));

    varray_init(&closest, MAX_CAPC);
    ret = node_space->ops->get_neighbors(node_space, &targetId, &closest, MAX_CAPC);
    ret1E((ret < 0), varray_deinit(&closest));
    if (ret == 0) {
        varray_deinit(&closest);
        return 0; // not response if no closest nodes found.
    }

    ret = route->dht_ops->find_closest_nodes_rsp(route, conn, &token, &closest);
    varray_zero(&closest, _aux_vnodeInfo_free, NULL);
    varray_deinit(&closest);
    retE((ret < 0));
    return 0;
}

/*
 * the routine to call when receiving a response to @find_closest_nodes
 *
 * @route:
 * @conn:
 * @ctxt:
 */
static
int _vroute_cb_find_closest_nodes_rsp(struct vroute* route, vnodeConn* conn, void* ctxt)
{
    struct vroute_recr_space* recr_space = &route->recr_space;
    struct vroute_node_space* node_space = &route->node_space;
    struct varray closest;
    vnodeId fromId;
    vtoken  token;
    int ret = 0;
    int i = 0;

    vassert(route);
    vassert(conn);
    vassert(ctxt);

    varray_init(&closest, MAX_CAPC);
    ret = route->dec_ops->find_closest_nodes_rsp(ctxt, &token, &fromId, &closest);
    ret1E((ret < 0), varray_deinit(&closest));
    if (!recr_space->ops->check(recr_space, &token)) {
        varray_zero(&closest, _aux_vnodeInfo_free, NULL);
        varray_deinit(&closest);
        return -1;
    }

    for (i = 0; i < varray_size(&closest); i++) {
        node_space->ops->add_node(node_space, (vnodeInfo*)varray_get(&closest, i), 0);
    }
    varray_zero(&closest, _aux_vnodeInfo_free, NULL);
    varray_deinit(&closest);

    route->ops->inspect(route, &token, VROUTE_INSP_RCV_FIND_CLOSEST_NODES_RSP);
    return 0;
}

/*
 * the routine to call when receiving a @reflex query.
 * @route:
 * @conn:
 * @ctxt:
 */
static
int _vroute_cb_reflex(struct vroute* route, vnodeConn* conn, void* ctxt)
{
    vnodeId fromId;
    vtoken  token;
    int ret = 0;

    vassert(route);
    vassert(conn);
    vassert(ctxt);

    ret = route->dec_ops->reflex(ctxt, &token, &fromId);
    retE((ret < 0));

    ret = route->dht_ops->reflex_rsp(route, conn, &token, &conn->remote);
    retE((ret < 0));
    return 0;
}

/*
 * the routine to call when receiving a response to @reflex
 * @route:
 * @conn:
 * @ctxt:
 */
static
int _vroute_cb_reflex_rsp(struct vroute* route, vnodeConn* conn, void* ctxt)
{
    struct vroute_recr_space* recr_space = &route->recr_space;
    struct vnode* node = route->node;
    struct sockaddr_in reflexive_addr;
    vnodeId fromId;
    vtoken  token;
    int ret = 0;

    vassert(route);
    vassert(conn);
    vassert(ctxt);

    ret = route->dec_ops->reflex_rsp(ctxt, &token, &fromId, &reflexive_addr);
    retE((ret < 0));
    retE((!recr_space->ops->check(recr_space, &token)));

    ret = node->ops->reflex_addr(node, &conn->local, &reflexive_addr);
    retE((ret < 0));
    route->ops->inspect(route, &token, VROUTE_INSP_RCV_REFLEX_RSP);
    return 0;
}

/*
 * the routine to call when receiving a @probe query.
 * @route:
 * @conn:
 * @ctxt:
 */
static
int _vroute_cb_probe(struct vroute* route, vnodeConn* conn, void* ctxt)
{
    vnodeId targetId;
    vnodeId fromId;
    vtoken  token;
    int ret = 0;

    vassert(route);
    vassert(conn);
    vassert(ctxt);

    ret = route->dec_ops->probe(ctxt, &token, &fromId, &targetId);
    retE((ret < 0));
    retE((!vtoken_equal(&targetId, &route->myid)));

    ret = route->dht_ops->probe_rsp(route, conn, &token);
    retE((ret < 0));
    return 0;
}

/*
 * the routine to call when receiving a response to @probe query.
 * @route:
 * @conn:
 * @ctxt:
 */
static
int _vroute_cb_probe_rsp(struct vroute* route, vnodeConn* conn, void* ctxt)
{
    struct vroute_recr_space* recr_space = &route->recr_space;
    struct vroute_node_space* node_space = &route->node_space;
    vnodeId fromId;
    vtoken  token;
    int ret = 0;

    vassert(route);
    vassert(conn);
    vassert(ctxt);

    ret = route->dec_ops->probe_rsp(ctxt, &token, &fromId);
    retE((ret < 0));
    retE((!recr_space->ops->check(recr_space, &token)));

    ret = node_space->ops->adjust_connectivity(node_space, &fromId, conn);
    retE((ret < 0));
    route->ops->inspect(route, &token, VROUTE_INSP_RCV_PROBE_RSP);
    return 0;
}

/*
 * the routine to call when receiving a @post_service indication.
 *
 * @route:
 * @conn:
 * @ctxt:
 */
static
int _vroute_cb_post_service(struct vroute* route, vnodeConn* conn, void* ctxt)
{
    struct vroute_srvc_space* srvc_space = &route->srvc_space;
    vsrvcInfo_relax srvci;
    vnodeId fromId;
    vtoken  token;
    int ret = 0;

    vassert(route);
    vassert(conn);
    vassert(ctxt);

    ret = route->dec_ops->post_service(ctxt, &token, &fromId, (vsrvcInfo*)&srvci);
    retE((ret < 0));
    ret = srvc_space->ops->add_service(srvc_space, (vsrvcInfo*)&srvci);
    retE((ret < 0));
    route->ops->inspect(route, &token, VROUTE_INSP_RCV_POST_SERVICE);
    return 0;
}

/*
 * the routine to call when receiving a @find_service query.
 *
 * @route:
 * @conn:
 * @ctxt:
 */
static
int _vroute_cb_find_service(struct vroute* route, vnodeConn* conn, void* ctxt)
{
    struct vroute_srvc_space* srvc_space = &route->srvc_space;
    vsrvcInfo_relax srvci;
    vsrvcHash srvcHash;
    vnodeId fromId;
    vtoken token;
    int ret = 0;

    vassert(route);
    vassert(conn);
    vassert(ctxt);

    memset(&srvci, 0, sizeof(srvci));
    srvci.capc = VSRVCINFO_MAX_ADDRS;

    ret = route->dec_ops->find_service(ctxt, &token, &fromId, &srvcHash);
    retE((ret < 0));
    ret = srvc_space->ops->get_service(srvc_space, &srvcHash, (vsrvcInfo*)&srvci);
    retE((ret < 0));
    retS((ret == 0));
    ret = route->dht_ops->find_service_rsp(route, conn, &token, (vsrvcInfo*)&srvci);
    retE((ret < 0));
    return 0;
}

/*
 * the routine to call when receiving a response to @find_service.
 *
 * @route:
 * @conn:
 * @ctxt:
 */
static
int _vroute_cb_find_service_rsp(struct vroute* route, vnodeConn* conn, void* ctxt)
{
    struct vroute_srvc_probe_helper* probe_helper = &route->probe_helper;
    struct vroute_srvc_space* srvc_space = &route->srvc_space;
    struct vroute_recr_space* recr_space = &route->recr_space;
    struct vroute_node_space* node_space = &route->node_space;
    vsrvcInfo_relax srvci;
    vnodeId fromId;
    vtoken token;
    int ret = 0;

    vassert(route);
    vassert(ctxt);
    vassert(conn);

    ret = route->dec_ops->find_service_rsp(ctxt, &token, &fromId, (vsrvcInfo*)&srvci);
    retE((ret < 0));
    retE((!recr_space->ops->check(recr_space, &token)));

    ret = srvc_space->ops->add_service(srvc_space, (vsrvcInfo*)&srvci);
    retE((ret < 0));

    //try to add info of node hosting that service.
    ret = node_space->ops->probe_node(node_space, &srvci.hostid);
    retE((ret < 0));
    route->ops->inspect(route, &token, VROUTE_INSP_RCV_FIND_SERVICE_RSP);
    probe_helper->ops->invoke(probe_helper, &srvci.hash, (vsrvcInfo*)&srvci);
    return 0;
}

static
vroute_dht_cb_t route_cb_ops[] = {
    _vroute_cb_ping,
    _vroute_cb_ping_rsp,
    _vroute_cb_find_node,
    _vroute_cb_find_node_rsp,
    _vroute_cb_find_closest_nodes,
    _vroute_cb_find_closest_nodes_rsp,
    _vroute_cb_reflex,
    _vroute_cb_reflex_rsp,
    _vroute_cb_probe,
    _vroute_cb_probe_rsp,
    _vroute_cb_post_service,
    _vroute_cb_find_service,
    _vroute_cb_find_service_rsp,
    NULL
};

static
int _aux_route_msg_cb(void* cookie, struct vmsg_usr* mu)
{
    struct vroute* route = (struct vroute*)cookie;
    vnodeConn conn;
    void* ctxt = NULL;
    int   ret  = 0;

    vassert(route);
    vassert(mu);

    ret = route->dec_ops->dec_begin(mu->data, mu->len, &ctxt);
    retE((ret >= VDHT_UNKNOWN));
    retE((ret < 0));
    vlogD("received @%s", vdht_get_desc(ret));

    vnodeConn_set(&conn, to_sockaddr_sin(mu->spec), to_sockaddr_sin(mu->addr));
    vlock_enter(&route->lock);
    ret = route->cb_ops[ret](route, &conn, ctxt);
    vlock_leave(&route->lock);
    route->dec_ops->dec_done(ctxt);
    retE((ret < 0));
    return 0;
}

static
int _aux_route_load_proto_caps(struct vconfig* cfg, uint32_t* props)
{
    struct varray* tuple = NULL;
    int i = 0;

    vassert(cfg);
    vassert(props);

    tuple = cfg->ops->get_tuple_val(cfg, "dht.protocol");
    if (!tuple) {
        *props |= PROP_PING;
        *props |= PROP_PING_R;
        return 0;
    }
    for (i = 0; i < varray_size(tuple); i++) {
        struct vcfg_item* item = NULL;
        int dht_id = -1;

        item = (struct vcfg_item*)varray_get(tuple, i);
        retE((item->type != CFG_STR));
        dht_id = vdht_get_dhtId_by_desc(item->val.s);
        retE((dht_id < 0));
        retE((dht_id >= VDHT_UNKNOWN));

        *props |= (1 << dht_id);
    }
    return 0;
}

int vroute_init(struct vroute* route, struct vconfig* cfg, struct vhost* host, vnodeId* myid)
{
    vassert(route);
    vassert(host);
    vassert(myid);

    vtoken_copy(&route->myid, myid);
    _aux_route_load_proto_caps(cfg, &route->props);

    vlock_init(&route->lock);
    vroute_node_space_init(&route->node_space, route, cfg, myid);
    vroute_srvc_space_init(&route->srvc_space, cfg);
    vroute_recr_space_init(&route->recr_space);
    vroute_srvc_probe_helper_init(&route->probe_helper);

    route->ops     = &route_ops;
    route->dht_ops = &route_dht_ops;
    route->cb_ops  = route_cb_ops;
    route->enc_ops = &dht_enc_ops;
    route->dec_ops = &dht_dec_ops;

    route->cfg   = cfg;
    route->msger = &host->msger;
    route->node  = &host->node;

    route->insp_cb = NULL;
    route->insp_cookie = NULL;

    route->msger->ops->add_cb(route->msger, route, _aux_route_msg_cb, VMSG_DHT);
    return 0;
}

void vroute_deinit(struct vroute* route)
{
    vassert(route);

    vroute_srvc_probe_helper_deinit (&route->probe_helper);
    vroute_recr_space_deinit(&route->recr_space);
    vroute_node_space_deinit(&route->node_space);
    vroute_srvc_space_deinit(&route->srvc_space);
    vlock_deinit(&route->lock);
    return ;
}
Beispiel #30
0
int
varnam_learn_from_file(varnam *handle,
                       const char *filepath,
                       vlearn_status *status,
                       void (*callback)(varnam *handle, const char *word, int status_code, void *object),
                       void *object)
{
    int rc;
    FILE *infile;
    char line_buffer[10000];
    strbuf *word;
    varray *word_parts;
    int confidence;
    int parts;

    infile = fopen(filepath, "r");
    if (!infile) {
        set_last_error (handle, "Couldn't open file '%s' for reading.\n", filepath);
        return VARNAM_ERROR;
    }

    if (status != NULL)
    {
        status->total_words = 0;
        status->failed = 0;
    }

    rc = vwt_optimize_for_huge_transaction(handle);
    if (rc) {
        fclose (infile);
        return rc;
    }

    /* Learning from file will be mostly new words. Optimizing for that */
    v_->_config_mostly_learning_new_words = 1;

    varnam_log (handle, "Starting to learn from %s", filepath);
    rc = vwt_start_changes (handle);
    if (rc) {
        vwt_turn_off_optimization_for_huge_transaction(handle);
        fclose (infile);
        return rc;
    }

    while (fgets(line_buffer, sizeof(line_buffer), infile))
    {
        reset_pool (handle);

        word = get_pooled_string (handle);
        strbuf_add (word, trimwhitespace (line_buffer));
        word_parts = strbuf_split (word, handle, ' ');
        parts = varray_length (word_parts);
        if (parts > 0 && parts <= 2)
        {
            confidence = 1;
            if (parts == 2) {
                word = varray_get (word_parts, 1);
                confidence = atoi (strbuf_to_s (word));
            }

            word = varray_get (word_parts, 0);
            rc = varnam_learn_internal (handle, strbuf_to_s (word), confidence);
            if (rc) {
                if (status != NULL) status->failed++;
            }
        }
        else {
            rc = VARNAM_ERROR;
            if (status != NULL) status->failed++;
        }

        if (status   != NULL) status->total_words++;
        if (callback != NULL) callback (handle, strbuf_to_s (word), rc, object);
    }

    varnam_log (handle, "Writing changes to disk");
    rc = vwt_end_changes (handle);
    if (rc) {
        varnam_log (handle, "Writing changes to disk failed");
    }

    varnam_log (handle, "Ensuring file integrity");
    rc = vwt_turn_off_optimization_for_huge_transaction(handle);
    if (rc) {
        varnam_log (handle, "Failed to check file integrity");
    }

    varnam_log (handle, "Compacting file");
    rc = vwt_compact_file (handle);
    if (rc) return rc;

    fclose (infile);
    return rc;
}