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); }
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; }
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; }
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; }
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); }
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); }
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); }
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; }
//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; }
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; }