Exemplo n.º 1
0
size_t encode_root(void *buf, node_pointer *node)
{
    if (!node) {
        return 0;
    }
    if (buf) {
        raw_btree_root *root = buf;
        root->pointer = encode_raw48(node->pointer);
        root->subtreesize = encode_raw48(node->subtreesize);
        memcpy(root + 1, node->reduce_value.buf, node->reduce_value.size);
    }
    return sizeof(raw_btree_root) + node->reduce_value.size;
}
Exemplo n.º 2
0
static size_t assemble_id_index_value(DocInfo *docinfo, char *dst)
{
    char* const start = dst;
    raw_id_index_value *raw = (raw_id_index_value*)dst;
    raw->db_seq = encode_raw48(docinfo->db_seq);
    raw->size = encode_raw32((uint32_t)docinfo->size);
    raw->bp = encode_raw48(docinfo->bp | (docinfo->deleted ? 1LL<<47 : 0));
    raw->content_meta = encode_raw08(docinfo->content_meta);
    raw->rev_seq = encode_raw48(docinfo->rev_seq);
    dst += sizeof(*raw);

    memcpy(dst, docinfo->rev_meta.buf, docinfo->rev_meta.size);
    dst += docinfo->rev_meta.size;
    return dst - start;
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
0
static void idfetch_update_cb(couchfile_modify_request *rq,
                              sized_buf *k, sized_buf *v, void *arg)
{
    (void)k;
    (void)rq;
    //v contains a seq we need to remove ( {Seq,_,_,_,_} )
    uint64_t oldseq;
    sized_buf *delbuf = NULL;
    index_update_ctx *ctx = (index_update_ctx *) arg;

    if (v == NULL) { //Doc not found
        return;
    }

    const raw_id_index_value *raw = (raw_id_index_value*) v->buf;
    oldseq = decode_raw48(raw->db_seq);

    delbuf = (sized_buf *) fatbuf_get(ctx->deltermbuf, sizeof(sized_buf));
    delbuf->buf = (char *) fatbuf_get(ctx->deltermbuf, 6);
    delbuf->size = 6;
    memset(delbuf->buf, 0, 6);
    *(raw_48*)delbuf->buf = encode_raw48(oldseq);

    ctx->seqacts[ctx->actpos].type = ACTION_REMOVE;
    ctx->seqacts[ctx->actpos].value.data = NULL;
    ctx->seqacts[ctx->actpos].key = delbuf;

    ctx->actpos++;
}
Exemplo n.º 5
0
LIBCOUCHSTORE_API
couchstore_error_t couchstore_docinfos_by_sequence(Db *db,
        const uint64_t sequence[],
        unsigned numDocs,
        couchstore_docinfos_options options,
        couchstore_changes_callback_fn callback,
        void *ctx)
{
    // Create the array of keys:
    sized_buf *keylist = malloc(numDocs * sizeof(sized_buf));
    raw_by_seq_key *keyvalues = malloc(numDocs * sizeof(raw_by_seq_key));
    couchstore_error_t errcode;
    error_unless(keylist && keyvalues, COUCHSTORE_ERROR_ALLOC_FAIL);
    unsigned i;
    for (i = 0; i< numDocs; ++i) {
        keyvalues[i].sequence = encode_raw48(sequence[i]);
        keylist[i].buf = (void*) &keyvalues[i];
        keylist[i].size = sizeof(keyvalues[i]);
    }

    error_pass(iterate_docinfos(db, keylist, numDocs,
                                db->header.by_seq_root, seq_ptr_cmp, seq_cmp,
                                callback,
                                (options & RANGES) != 0,
                                ctx));
cleanup:
    free(keylist);
    free(keyvalues);
    return errcode;
}
Exemplo n.º 6
0
static void enc_uint48(uint64_t u, char **buf)
{
    raw_48 r;
    encode_raw48(u, &r);
    memcpy(*buf, &r, 6);
    *buf += 6;
}
Exemplo n.º 7
0
static void test_raw_48(uint64_t value, const uint8_t expected[8])
{
    union {
        raw_48 raw;
        uint8_t bytes[8];
    } data;
    memset(&data, 0, sizeof(data));
    data.raw = encode_raw48(value);
    assert(memcmp(data.bytes, expected, 8) == 0);
    assert(decode_raw48(data.raw) == value);
}
Exemplo n.º 8
0
static couchstore_error_t add_doc_to_update_list(Db *db,
                                                 const Doc *doc,
                                                 const DocInfo *info,
                                                 fatbuf *fb,
                                                 sized_buf *seqterm,
                                                 sized_buf *idterm,
                                                 sized_buf *seqval,
                                                 sized_buf *idval,
                                                 uint64_t seq,
                                                 couchstore_save_options options)
{
    couchstore_error_t errcode = COUCHSTORE_SUCCESS;
    DocInfo updated = *info;
    updated.db_seq = seq;

    seqterm->buf = (char *) fatbuf_get(fb, 6);
    seqterm->size = 6;
    error_unless(seqterm->buf, COUCHSTORE_ERROR_ALLOC_FAIL);
    *(raw_48*)seqterm->buf = encode_raw48(seq);

    if (doc) {
        size_t disk_size;

        // Don't compress a doc unless the meta flag is set
        if (!(info->content_meta & COUCH_DOC_IS_COMPRESSED)) {
            options &= ~COMPRESS_DOC_BODIES;
        }
        errcode = write_doc(db, doc, &updated.bp, &disk_size, options);

        if (errcode != COUCHSTORE_SUCCESS) {
            return errcode;
        }
        updated.size = disk_size;
    } else {
        updated.deleted = 1;
        updated.bp = 0;
        updated.size = 0;
    }

    *idterm = updated.id;

    seqval->buf = (char *) fatbuf_get(fb, (44 + updated.id.size + updated.rev_meta.size));
    error_unless(seqval->buf, COUCHSTORE_ERROR_ALLOC_FAIL);
    seqval->size = assemble_seq_index_value(&updated, seqval->buf);

    idval->buf = (char *) fatbuf_get(fb, (44 + 10 + updated.rev_meta.size));
    error_unless(idval->buf, COUCHSTORE_ERROR_ALLOC_FAIL);
    idval->size = assemble_id_index_value(&updated, idval->buf);

    //We use 37 + id.size + 2 * rev_meta.size bytes
cleanup:
    return errcode;
}
Exemplo n.º 9
0
LIBCOUCHSTORE_API
couchstore_error_t couchstore_walk_seq_tree(Db *db,
        uint64_t startSequence,
        couchstore_docinfos_options options,
        couchstore_walk_tree_callback_fn callback,
        void *ctx)
{
    raw_48 start_termbuf = encode_raw48(startSequence);
    sized_buf start_term = {(char*)&start_termbuf, 6};

    return couchstore_walk_tree(db, 0, db->header.by_seq_root, &start_term,
                                options, seq_cmp, callback, ctx);
}
Exemplo n.º 10
0
static couchstore_error_t write_header(Db *db)
{
    sized_buf writebuf;
    size_t seqrootsize = 0, idrootsize = 0, localrootsize = 0;
    if (db->header.by_seq_root) {
        seqrootsize = ROOT_BASE_SIZE + db->header.by_seq_root->reduce_value.size;
    }
    if (db->header.by_id_root) {
        idrootsize = ROOT_BASE_SIZE + db->header.by_id_root->reduce_value.size;
    }
    if (db->header.local_docs_root) {
        localrootsize = ROOT_BASE_SIZE + db->header.local_docs_root->reduce_value.size;
    }
    writebuf.size = sizeof(raw_file_header) + seqrootsize + idrootsize + localrootsize;
    writebuf.buf = (char *) calloc(1, writebuf.size);
    raw_file_header* header = (raw_file_header*)writebuf.buf;
    header->version = encode_raw08(COUCH_DISK_VERSION);
    header->update_seq = encode_raw48(db->header.update_seq);
    header->purge_seq = encode_raw48(db->header.purge_seq);
    header->purge_ptr = encode_raw48(db->header.purge_ptr);
    header->seqrootsize = encode_raw16((uint16_t)seqrootsize);
    header->idrootsize = encode_raw16((uint16_t)idrootsize);
    header->localrootsize = encode_raw16((uint16_t)localrootsize);
    uint8_t *root = (uint8_t*)(header + 1);
    encode_root(root, db->header.by_seq_root);
    root += seqrootsize;
    encode_root(root, db->header.by_id_root);
    root += idrootsize;
    encode_root(root, db->header.local_docs_root);
    cs_off_t pos;
    couchstore_error_t errcode = db_write_header(&db->file, &writebuf, &pos);
    if (errcode == COUCHSTORE_SUCCESS) {
        db->header.position = pos;
    }
    free(writebuf.buf);
    return errcode;
}
Exemplo n.º 11
0
LIBCOUCHSTORE_API
couchstore_error_t couchstore_changes_since(Db *db,
        uint64_t since,
        couchstore_docinfos_options options,
        couchstore_changes_callback_fn callback,
        void *ctx)
{
    char since_termbuf[6];
    sized_buf since_term;
    sized_buf *keylist = &since_term;
    lookup_context cbctx = {db, options, callback, ctx, 0, 0, NULL};
    couchfile_lookup_request rq;
    sized_buf cmptmp;
    couchstore_error_t errcode;

    if (db->header.by_seq_root == NULL) {
        return COUCHSTORE_SUCCESS;
    }

    since_term.buf = since_termbuf;
    since_term.size = 6;
    *(raw_48*)since_term.buf = encode_raw48(since);

    rq.cmp.compare = seq_cmp;
    rq.cmp.arg = &cmptmp;
    rq.file = &db->file;
    rq.num_keys = 1;
    rq.keys = &keylist;
    rq.callback_ctx = &cbctx;
    rq.fetch_callback = lookup_callback;
    rq.node_callback = NULL;
    rq.fold = 1;

    errcode = btree_lookup(&rq, db->header.by_seq_root->pointer);
    return errcode;
}