int main(int argc, char **argv) { const Pvoid_t params = read_parameters(); test_param(params, "test1", "1,2,3"); test_param(params, "one two three", "dim\ndam\n"); test_param(params, "dummy", "value"); msg("All parameters ok!"); const char DVAL[] = "dkey"; p_entry *dkey = dxmalloc(sizeof(p_entry) + sizeof(DVAL)); dkey->len = sizeof(DVAL) - 1; memcpy(dkey->data, DVAL, dkey->len); int i = 0; p_entry *key = NULL; p_entry *val = NULL; while (read_kv(&key, &val)){ msg("Got key <%s> val <%s>", key->data, val->data); if (!key->len) key = dkey; write_num_prefix(3); write_kv(key, val); write_kv(key, val); write_kv(key, val); ++i; } msg("%d key-value pairs read ok", i); return 0; }
static int get_key_value(char* key, char *value) { char kpath[64] = {0}; sprintf(kpath, KV_STORE, key); if (access(KV_STORE_PATH, F_OK) == -1) { mkdir(KV_STORE_PATH, 0777); } return read_kv(kpath, value); }
static couchstore_error_t modify_node(couchfile_modify_request *rq, node_pointer *nptr, int start, int end, couchfile_modify_result *dst) { char *nodebuf = NULL; // FYI, nodebuf is a malloced block, not in the arena int bufpos = 1; int nodebuflen = 0; int errcode = 0; couchfile_modify_result *local_result = NULL; if (start == end) { return 0; } if (nptr) { if ((nodebuflen = pread_compressed(rq->db, nptr->pointer, (char **) &nodebuf)) < 0) { error_pass(COUCHSTORE_ERROR_READ); } } local_result = make_modres(dst->arena, rq); error_unless(local_result, COUCHSTORE_ERROR_ALLOC_FAIL); if (nptr == NULL || nodebuf[0] == 1) { //KV Node local_result->node_type = KV_NODE; while (bufpos < nodebuflen) { sized_buf cmp_key, val_buf; bufpos += read_kv(nodebuf + bufpos, &cmp_key, &val_buf); int advance = 0; while (!advance && start < end) { advance = 1; int cmp_val = rq->cmp.compare(&cmp_key, rq->actions[start].key); if (cmp_val < 0) { //Key less than action key mr_push_item(&cmp_key, &val_buf, local_result); } else if (cmp_val > 0) { //Key greater than action key switch (rq->actions[start].type) { case ACTION_INSERT: local_result->modified = 1; mr_push_item(rq->actions[start].key, rq->actions[start].value.data, local_result); break; case ACTION_REMOVE: local_result->modified = 1; break; case ACTION_FETCH: if (rq->fetch_callback) { //not found (*rq->fetch_callback)(rq, rq->actions[start].key, NULL, rq->actions[start].value.arg); } } start++; //Do next action on same item in the node, as our action was //not >= it. advance = 0; } else if (cmp_val == 0) { //Node key is equal to action key switch (rq->actions[start].type) { case ACTION_INSERT: local_result->modified = 1; mr_push_item(rq->actions[start].key, rq->actions[start].value.data, local_result); break; case ACTION_REMOVE: local_result->modified = 1; break; case ACTION_FETCH: if (rq->fetch_callback) { (*rq->fetch_callback)(rq, rq->actions[start].key, &val_buf, rq->actions[start].value.arg); } //Do next action on same item in the node, as our action was a fetch //and there may be an equivalent insert or remove //following. advance = 0; } start++; } } if (start == end && !advance) { //If we've exhausted actions then just keep this key mr_push_item(&cmp_key, &val_buf, local_result); } } while (start < end) { //We're at the end of a leaf node. switch (rq->actions[start].type) { case ACTION_INSERT: local_result->modified = 1; mr_push_item(rq->actions[start].key, rq->actions[start].value.data, local_result); break; case ACTION_REMOVE: local_result->modified = 1; break; case ACTION_FETCH: if (rq->fetch_callback) { //not found (*rq->fetch_callback)(rq, rq->actions[start].key, NULL, rq->actions[start].value.arg); } break; } start++; } } else if (nodebuf[0] == 0) { //KP Node local_result->node_type = KP_NODE; while (bufpos < nodebuflen && start < end) { sized_buf cmp_key, val_buf; bufpos += read_kv(nodebuf + bufpos, &cmp_key, &val_buf); int cmp_val = rq->cmp.compare(&cmp_key, rq->actions[start].key); if (bufpos == nodebuflen) { //We're at the last item in the kpnode, must apply all our //actions here. node_pointer *desc = read_pointer(dst->arena, &cmp_key, val_buf.buf); if (!desc) { errcode = COUCHSTORE_ERROR_ALLOC_FAIL; goto cleanup; } errcode = modify_node(rq, desc, start, end, local_result); if (errcode != COUCHSTORE_SUCCESS) { goto cleanup; } break; } if (cmp_val < 0) { //Key in node item less than action item and not at end //position, so just add it and continue. node_pointer *add = read_pointer(dst->arena, &cmp_key, val_buf.buf); if (!add) { errcode = COUCHSTORE_ERROR_ALLOC_FAIL; goto cleanup; } errcode = mr_push_pointerinfo(add, local_result); if (errcode != COUCHSTORE_SUCCESS) { goto cleanup; } } else if (cmp_val >= 0) { //Found a key in the node greater than the one in the current //action. Descend into the pointed node with as many actions as //are less than the key here. int range_end = start; while (range_end < end && rq->cmp.compare(rq->actions[range_end].key, &cmp_key) <= 0) { range_end++; } node_pointer *desc = read_pointer(dst->arena, &cmp_key, val_buf.buf); if (!desc) { errcode = COUCHSTORE_ERROR_ALLOC_FAIL; goto cleanup; } errcode = modify_node(rq, desc, start, range_end, local_result); start = range_end; if (errcode != COUCHSTORE_SUCCESS) { goto cleanup; } } } while (bufpos < nodebuflen) { sized_buf cmp_key, val_buf; bufpos += read_kv(nodebuf + bufpos, &cmp_key, &val_buf); node_pointer *add = read_pointer(dst->arena, &cmp_key, val_buf.buf); if (!add) { errcode = COUCHSTORE_ERROR_ALLOC_FAIL; goto cleanup; } errcode = mr_push_pointerinfo(add, local_result); if (errcode != COUCHSTORE_SUCCESS) { goto cleanup; } } } else { errcode = COUCHSTORE_ERROR_CORRUPT; goto cleanup; } //If we've done modifications, write out the last leaf node. error_pass(flush_mr(local_result)); if (!local_result->modified && nptr != NULL) { //If we didn't do anything, give back the pointer to the original mr_push_pointerinfo(nptr, dst); } else { //Otherwise, give back the pointers to the nodes we've created. dst->modified = 1; error_pass(mr_move_pointers(local_result, dst)); } cleanup: if (nodebuf) { free(nodebuf); } return errcode; }
static couchstore_error_t btree_lookup_inner(couchfile_lookup_request *rq, uint64_t diskpos, int current, int end) { int bufpos = 1, nodebuflen = 0; if (current == end) { return 0; } couchstore_error_t errcode = COUCHSTORE_SUCCESS; char *nodebuf = NULL; nodebuflen = pread_compressed(rq->file, diskpos, &nodebuf); error_unless(nodebuflen >= 0, nodebuflen); // if negative, it's an error code if (nodebuf[0] == 0) { //KP Node while (bufpos < nodebuflen && current < end) { sized_buf cmp_key, val_buf; bufpos += read_kv(nodebuf + bufpos, &cmp_key, &val_buf); if (rq->cmp.compare(&cmp_key, rq->keys[current]) >= 0) { if (rq->fold) { rq->in_fold = 1; } uint64_t pointer = 0; int last_item = current; //Descend into the pointed to node. //with all keys < item key. do { last_item++; } while (last_item < end && rq->cmp.compare(&cmp_key, rq->keys[last_item]) >= 0); const raw_node_pointer *raw = (const raw_node_pointer*)val_buf.buf; if(rq->node_callback) { uint64_t subtreeSize = decode_raw48(raw->subtreesize); sized_buf reduce_value = {val_buf.buf + sizeof(raw_node_pointer), decode_raw16(raw->reduce_value_size)}; error_pass(rq->node_callback(rq, subtreeSize, &reduce_value)); } pointer = decode_raw48(raw->pointer); error_pass(btree_lookup_inner(rq, pointer, current, last_item)); if (!rq->in_fold) { current = last_item; } if(rq->node_callback) { error_pass(rq->node_callback(rq, 0, NULL)); } } } } else if (nodebuf[0] == 1) { //KV Node while (bufpos < nodebuflen && current < end) { sized_buf cmp_key, val_buf; bufpos += read_kv(nodebuf + bufpos, &cmp_key, &val_buf); int cmp_val = rq->cmp.compare(&cmp_key, rq->keys[current]); if (cmp_val >= 0 && rq->fold && !rq->in_fold) { rq->in_fold = 1; } else if (rq->in_fold && (current + 1) < end && (rq->cmp.compare(&cmp_key, rq->keys[current + 1])) > 0) { //We've hit a key past the end of our range. rq->in_fold = 0; rq->fold = 0; current = end; } if (cmp_val == 0 || (cmp_val > 0 && rq->in_fold)) { //Found error_pass(rq->fetch_callback(rq, &cmp_key, &val_buf)); if (!rq->in_fold) { current++; } } } } //Any remaining items are not found. while (current < end && !rq->fold) { error_pass(rq->fetch_callback(rq, rq->keys[current], NULL)); current++; } cleanup: free(nodebuf); return errcode; }