Пример #1
0
couchstore_error_t spatial_push_item(sized_buf *k,
                                     sized_buf *v,
                                     couchfile_modify_result *dst)
{
    nodelist *itm = NULL;
    if(dst->arena_transient != NULL)
    {
        itm = make_nodelist(dst->arena_transient, 0);
    } else {
        cb_assert(dst->arena != NULL);
        itm = make_nodelist(dst->arena, 0);
    }
    if (itm == NULL) {
        return COUCHSTORE_ERROR_ALLOC_FAIL;
    }
    itm->data = *v;
    itm->key = *k;
    itm->pointer = NULL;
    dst->values_end->next = itm;
    dst->values_end = itm;
    /* Encoded size (see flush_spatial) */
    dst->node_len += k->size + v->size + sizeof(raw_kv_length);
    dst->count++;
    return maybe_flush_spatial(dst);
}
Пример #2
0
static couchfile_modify_result *make_modres(arena* a, couchfile_modify_request *rq)
{
    couchfile_modify_result *res = arena_alloc(a, sizeof(couchfile_modify_result));
    if (!res) {
        return NULL;
    }
    res->arena = a;
    res->arena_transient = NULL;
    res->values = make_nodelist(a, 0);
    if (!res->values) {
        return NULL;
    }
    res->values_end = res->values;
    res->pointers = make_nodelist(a, 0);
    if (!res->pointers) {
        return NULL;
    }
    res->pointers_end = res->pointers;
    res->node_len = 0;
    res->count = 0;
    res->modified = 0;
    res->error_state = 0;
    res->rq = rq;
    return res;
}
Пример #3
0
couchfile_modify_result *make_modres(couchfile_modify_request *rq) {
    couchfile_modify_result *res = malloc(sizeof(couchfile_modify_result));
    res->values = make_nodelist();
    res->values_end = res->values;
    res->pointers = make_nodelist();
    res->pointers_end = res->pointers;
    res->node_len = 0;
    res->count = 0;
    res->modified = 0;
    res->error_state = 0;
    res->rq = rq;
    return res;
}
Пример #4
0
int mr_push_kv_range(char* buf, int pos, int bound, int end, couchfile_modify_result *dst)
{
    int current = 0;
    int term_begin_pos;
    ei_decode_list_header(buf, &pos, NULL);
    int errcode = 0;
    while(current < end && errcode == 0)
    {
        term_begin_pos = pos;
        ei_skip_term(buf, &pos);
        if(current >= bound)
        { //Parse KV pair into a leaf_value
            couchfile_leaf_value *lv = malloc(sizeof(couchfile_leaf_value));

            lv->term.buf = buf+term_begin_pos;
            lv->term.size = pos-term_begin_pos;

            nodelist* n = make_nodelist();
            dst->values_end->next = n;
            dst->values_end = n;
            n->value.leaf = lv;

            dst->node_len += lv->term.size;
            dst->count++;
            errcode = maybe_flush(dst);
        }
        current++;
    }
    return errcode;
}
Пример #5
0
int mr_push_action(couchfile_modify_action *act, couchfile_modify_result *dst)
{
    //For ACTION_INSERT
    couchfile_leaf_value* lv = malloc(sizeof(couchfile_leaf_value) +
           act->key->size + act->value->size + 2);
    //Allocate space for {K,V} term
    lv->term.buf = ((char*)lv) + sizeof(couchfile_leaf_value);
    lv->term.size = (act->key->size + act->value->size + 2);
    //tuple of arity 2
    lv->term.buf[0] = 104;
    lv->term.buf[1] = 2;
    //copy terms from the action
    memcpy(lv->term.buf + 2, act->key->buf, act->key->size);
    memcpy(lv->term.buf + 2 + act->key->size,
            act->value->buf, act->value->size);

    nodelist* n = make_nodelist();
    dst->values_end->next = n;
    dst->values_end = n;
    n->value.leaf = lv;

    dst->node_len += lv->term.size;
    dst->count++;
    return maybe_flush(dst);
}
Пример #6
0
int mr_push_pointerinfo(couchfile_pointer_info* ptr, couchfile_modify_result* dst)
{
    nodelist* pel = make_nodelist();
    pel->value.pointer = ptr;
    dst->values_end->next = pel;
    dst->values_end = pel;

    //max len of {key,{pointer, reduce_value, subtreesize}}
    dst->node_len += ptr->key.size + ptr->reduce_value.size + 24;
    dst->count++;
    return maybe_flush(dst);
}
Пример #7
0
couchstore_error_t mr_push_item(sized_buf *k, sized_buf *v, couchfile_modify_result *dst)
{
    nodelist *itm = NULL;
    if(dst->arena_transient != NULL)
    {
        itm = make_nodelist(dst->arena_transient, 0);
    } else {
        itm = make_nodelist(dst->arena, 0);
    }
    if (!itm) {
        return COUCHSTORE_ERROR_ALLOC_FAIL;
    }
    itm->key = *k;
    itm->data = *v;
    itm->pointer = NULL;
    dst->values_end->next = itm;
    dst->values_end = itm;
    //Encoded size (see flush_mr)
    dst->node_len += k->size + v->size + 5;
    dst->count++;
    return maybe_flush(dst);
}
Пример #8
0
static nodelist *encode_pointer(arena* a, node_pointer *ptr)
{
    nodelist *pel = make_nodelist(a, sizeof(raw_node_pointer) + ptr->reduce_value.size);
    if (!pel) {
        return NULL;
    }
    raw_node_pointer *raw = (raw_node_pointer*)pel->data.buf;
    raw->pointer = encode_raw48(ptr->pointer);
    raw->subtreesize = encode_raw48(ptr->subtreesize);
    raw->reduce_value_size = encode_raw16((uint16_t)ptr->reduce_value.size);
    memcpy(raw + 1, ptr->reduce_value.buf, ptr->reduce_value.size);
    pel->pointer = ptr;
    pel->key = ptr->key;
    return pel;
}
Пример #9
0
//Write the current contents of the values list to disk as a node
//and add the resulting pointer to the pointers list.
int flush_mr(couchfile_modify_result *res)
{
    int nbufpos = 0;
    long long subtreesize = 0;
    eterm_buf reduce_value;
    //default reduce value []
    reduce_value.buf = "\x6A"; //NIL_EXT
    reduce_value.size = 1;
    int reduced = 0;
    int errcode = 0;

    if(res->values_end == res->values || !res->modified)
    {
        //Empty
        return 0;
    }

    res->node_len += 19; //tuple header and node type tuple, list header and tail
    nif_writerq *wrq = nif_writerq_alloc(res->node_len);
    char *nodebuf = wrq->buf;

    //External term header; tuple header arity 2;
    ei_encode_version(nodebuf, &nbufpos);
    ei_encode_tuple_header(nodebuf, &nbufpos, 2);
    switch(res->node_type)
    {
        case KV_NODE:
            ei_encode_atom_len(nodebuf, &nbufpos, "kv_node", 7);
            if(res->rq->reduce)
            {
                (*res->rq->reduce)(&reduce_value, res->values->next, res->count);
                reduced = 1;
            }
        break;
        case KP_NODE:
            ei_encode_atom_len(nodebuf, &nbufpos, "kp_node", 7);
            if(res->rq->rereduce)
            {
                (*res->rq->rereduce)(&reduce_value, res->values->next, res->count);
                reduced = 1;
            }
        break;
    }

    ei_encode_list_header(nodebuf, &nbufpos, res->count);

    nodelist* i = res->values->next;

    eterm_buf last_key;
    while(i != NULL)
    {
        if(res->node_type == KV_NODE) //writing value in a kv_node
        {
            append_buf(nodebuf, &nbufpos, i->value.leaf->term.buf, i->value.leaf->term.size);
            if(i->next == NULL)
            {
                int pos = 0;
                term_to_buf(&last_key, i->value.leaf->term.buf+2, &pos);
            }
        }
        else if (res->node_type == KP_NODE) //writing value in a kp_node
        {
            if(wait_pointer(res->rq, i->value.pointer) < 0)
            {
                errcode = ERROR_WRITER_DEAD;
                goto cleanup;
            }
            subtreesize += i->value.pointer->subtreesize;
            ei_encode_tuple_header(nodebuf, &nbufpos, 2); //tuple arity 2
            append_buf(nodebuf, &nbufpos, i->value.pointer->key.buf, i->value.pointer->key.size);
            ei_encode_tuple_header(nodebuf, &nbufpos, 3); //tuple arity 3
            //pointer
            // v- between 2 and 10 bytes (ERL_SMALL_INTEGER_EXT to ERL_SMALL_BIG_EXT/8)
            ei_encode_ulonglong(nodebuf, &nbufpos, i->value.pointer->pointer);
            //reduce_value
            append_buf(nodebuf, &nbufpos, i->value.pointer->reduce_value.buf,
                    i->value.pointer->reduce_value.size);
            //subtreesize
            // v- between 2 and 10 bytes (ERL_SMALL_INTEGER_EXT to ERL_SMALL_BIG_EXT/8)
            ei_encode_ulonglong(nodebuf, &nbufpos, i->value.pointer->subtreesize);
            if(i->next == NULL)
            {
                last_key = i->value.pointer->key;
            }
        }
        i = i->next;
    }

    //NIL_EXT (list tail)
    ei_encode_empty_list(nodebuf, &nbufpos);

    couchfile_pointer_info* ptr = malloc(sizeof(couchfile_pointer_info) +
            last_key.size + reduce_value.size);

    ptr->pointer = 0;

    nif_write(res->rq, ptr, wrq, nbufpos);

    ptr->key.buf = ((char*)ptr) + sizeof(couchfile_pointer_info);
    ptr->reduce_value.buf = ((char*)ptr) + sizeof(couchfile_pointer_info) + last_key.size;

    ptr->key.size = last_key.size;
    ptr->reduce_value.size = reduce_value.size;

    memcpy(ptr->key.buf, last_key.buf, last_key.size);
    memcpy(ptr->reduce_value.buf, reduce_value.buf, reduce_value.size);

    ptr->subtreesize = subtreesize;

    nodelist* pel = make_nodelist();
    pel->value.pointer = ptr;
    res->pointers_end->next = pel;
    res->pointers_end = pel;

    res->node_len = 0;
    res->count = 0;

    res->values_end = res->values;
    free_nodelist(res->values->next);
    res->values->next = NULL;
cleanup:

    if(errcode < 0)
    {
        enif_release_resource(wrq);
    }

    if(reduced)
    {
        free(reduce_value.buf);
    }
    return errcode;
}
Пример #10
0
evaluator_context *make_evaluator(const document_model *model, const jsonpath *path)
{
    evaluator_debug("creating evaluator context");
    evaluator_context *context = (evaluator_context *)calloc(1, sizeof(evaluator_context));
    if(NULL == context)
    {
        evaluator_debug("uh oh! out of memory, can't allocate the evaluator context");
        return NULL;
    }
    if(NULL == model)
    {
        evaluator_debug("model is null");
        errno = EINVAL;
        context->code = ERR_MODEL_IS_NULL;
        return context;
    }
    if(NULL == path)
    {
        evaluator_debug("path is null");
        errno = EINVAL;
        context->code = ERR_PATH_IS_NULL;
        return context;
    }
    if(NULL == model_document(model, 0))
    {
        evaluator_debug("document is null");
        errno = EINVAL;
        context->code = ERR_NO_DOCUMENT_IN_MODEL;
        return context;
    }
    if(NULL == model_document_root(model, 0))
    {
        evaluator_debug("document root is null");
        errno = EINVAL;
        context->code = ERR_NO_ROOT_IN_DOCUMENT;
        return context;
    }
    if(ABSOLUTE_PATH != path_kind(path))
    {
        evaluator_debug("path is not absolute");
        errno = EINVAL;
        context->code = ERR_PATH_IS_NOT_ABSOLUTE;
        return context;
    }
    if(0 == path_length(path))
    {
        evaluator_debug("path is empty");
        errno = EINVAL;
        context->code = ERR_PATH_IS_EMPTY;
        return context;
    }

    nodelist *list = make_nodelist();
    if(NULL == list)
    {
        evaluator_debug("uh oh! out of memory, can't allocate the result nodelist");
        context->code = ERR_EVALUATOR_OUT_OF_MEMORY;
        return context;
    }
    context->list = list;
    context->model = model;
    context->path = path;

    return context;
}