Пример #1
0
static couchstore_error_t write_doc(Db *db, const Doc *doc, uint64_t *bp,
                                    size_t* disk_size, couchstore_save_options writeopts)
{
    couchstore_error_t errcode;
    if (writeopts & COMPRESS_DOC_BODIES) {
        errcode = db_write_buf_compressed(db, &doc->data, (off_t *) bp, disk_size);
    } else {
        errcode = db_write_buf(db, &doc->data, (off_t *) bp, disk_size);
    }

    return errcode;
}
Пример #2
0
//Write a node using enough items from the values list to create a node
//with uncompressed size of at least mr_quota
static couchstore_error_t flush_mr_partial(couchfile_modify_result *res, size_t mr_quota)
{
    char *dst;
    int errcode = COUCHSTORE_SUCCESS;
    int itmcount = 0;
    char *nodebuf = NULL;
    sized_buf writebuf;
    char reducebuf[30];
    size_t reducesize = 0;
    uint64_t subtreesize = 0;
    off_t diskpos;
    size_t disk_size;
    sized_buf final_key = {NULL, 0};

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

    // nodebuf/writebuf is very short-lived and can be large, so use regular malloc heap for it:
    nodebuf = malloc(res->node_len + 1);
    if (!nodebuf) {
        return COUCHSTORE_ERROR_ALLOC_FAIL;
    }

    writebuf.buf = nodebuf;

    dst = nodebuf;
    *(dst++) = (char) res->node_type;

    nodelist *i = res->values->next;
    //We don't care that we've reached mr_quota if we haven't written out
    //at least two items and we're not writing a leaf node.
    while (i != NULL && (mr_quota > 0 || (itmcount < 2 && res->node_type == KP_NODE))) {
        dst = write_kv(dst, i->key, i->data);
        if (i->pointer) {
            subtreesize += i->pointer->subtreesize;
        }
        mr_quota -= i->key.size + i->data.size + 5;
        final_key = i->key;
        i = i->next;
        res->count--;
        itmcount++;
    }

    writebuf.size = dst - nodebuf;

    errcode = db_write_buf_compressed(res->rq->db, &writebuf, &diskpos, &disk_size);
    free(nodebuf);  // here endeth the nodebuf.
    if (errcode != COUCHSTORE_SUCCESS) {
        return errcode;
    }

    if (res->node_type == KV_NODE && res->rq->reduce) {
        res->rq->reduce(reducebuf, &reducesize, res->values->next, itmcount);
    }

    if (res->node_type == KP_NODE && res->rq->rereduce) {
        res->rq->rereduce(reducebuf, &reducesize, res->values->next, itmcount);
    }

    node_pointer *ptr = (node_pointer *) arena_alloc(res->arena, sizeof(node_pointer) + final_key.size + reducesize);
    if (!ptr) {
        return COUCHSTORE_ERROR_ALLOC_FAIL;
    }

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

    ptr->key.size = final_key.size;
    ptr->reduce_value.size = reducesize;

    memcpy(ptr->key.buf, final_key.buf, final_key.size);
    memcpy(ptr->reduce_value.buf, reducebuf, reducesize);

    ptr->subtreesize = subtreesize + disk_size;
    ptr->pointer = diskpos;

    nodelist *pel = encode_pointer(res->arena, ptr);
    if (!pel) {
        return COUCHSTORE_ERROR_ALLOC_FAIL;
    }

    res->pointers_end->next = pel;
    res->pointers_end = pel;

    res->node_len -= (writebuf.size - 1);

    res->values->next = i;
    if(i == NULL) {
        res->values_end = res->values;
    }

    return COUCHSTORE_SUCCESS;
}
Пример #3
0
/* Write a node using enough items from the values list to create a node
 * with uncompressed size of at least mr_quota */
static couchstore_error_t flush_spatial_partial(couchfile_modify_result *res,
                                                size_t mr_quota)
{
    char *dst;
    couchstore_error_t errcode = COUCHSTORE_SUCCESS;
    int itmcount = 0;
    char *nodebuf = NULL;
    sized_buf writebuf;
    char reducebuf[MAX_REDUCTION_SIZE];
    size_t reducesize = 0;
    uint64_t subtreesize = 0;
    cs_off_t diskpos;
    size_t disk_size;
    nodelist *i, *pel;
    node_pointer *ptr;

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

    /* nodebuf/writebuf is very short-lived and can be large, so use regular
     * malloc heap for it: */
    nodebuf = (char *) cb_malloc(res->node_len + 1);
    if (nodebuf == NULL) {
        return COUCHSTORE_ERROR_ALLOC_FAIL;
    }

    writebuf.buf = nodebuf;

    dst = nodebuf;
    *(dst++) = (char) res->node_type;

    i = res->values->next;
    /* We don't care that we've reached mr_quota if we haven't written out
     * at least two items and we're not writing a leaf node. */
    while (i != NULL &&
           (mr_quota > 0 || (itmcount < 2 && res->node_type == KP_NODE))) {
        dst = (char *) write_kv(dst, i->key, i->data);
        if (i->pointer) {
            subtreesize += i->pointer->subtreesize;
        }
        mr_quota -= i->key.size + i->data.size + sizeof(raw_kv_length);
        i = i->next;
        res->count--;
        itmcount++;
    }

    writebuf.size = dst - nodebuf;

    errcode = (couchstore_error_t) db_write_buf_compressed(
        res->rq->file, &writebuf, &diskpos, &disk_size);
    cb_free(nodebuf);  /* here endeth the nodebuf. */
    if (errcode != COUCHSTORE_SUCCESS) {
        return errcode;
    }

    /* Store the enclosing MBB in the reducebuf */
    if (res->node_type == KV_NODE && res->rq->reduce) {
        errcode = res->rq->reduce(
            reducebuf, &reducesize, res->values->next, itmcount,
            res->rq->user_reduce_ctx);
        if (errcode != COUCHSTORE_SUCCESS) {
            return errcode;
        }
        cb_assert(reducesize <= sizeof(reducebuf));
    }

    if (res->node_type == KP_NODE && res->rq->rereduce) {
        errcode = res->rq->rereduce(
            reducebuf, &reducesize, res->values->next, itmcount,
            res->rq->user_reduce_ctx);
        if (errcode != COUCHSTORE_SUCCESS) {
            return errcode;
        }
        cb_assert(reducesize <= sizeof(reducebuf));
    }

    /* `reducesize` one time for the key, one time for the actual reduce */
    ptr = (node_pointer *) arena_alloc(
        res->arena, sizeof(node_pointer) + 2 * reducesize);
    if (ptr == NULL) {
        return COUCHSTORE_ERROR_ALLOC_FAIL;
    }

    ptr->key.buf = ((char *)ptr) + sizeof(node_pointer);
    ptr->reduce_value.buf = ((char *)ptr) + sizeof(node_pointer) + reducesize;

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

    /* Store the enclosing MBB that was calculate in the reduce function
     * as the key. The reduce also stores it as it is the "Original MBB"
     * used in the RR*-tree algorithm */
    memcpy(ptr->key.buf, reducebuf, reducesize);
    memcpy(ptr->reduce_value.buf, reducebuf, reducesize);

    ptr->subtreesize = subtreesize + disk_size;
    ptr->pointer = diskpos;

    pel = encode_pointer(res->arena, ptr);
    if (pel == NULL) {
        return COUCHSTORE_ERROR_ALLOC_FAIL;
    }

    res->pointers_end->next = pel;
    res->pointers_end = pel;

    res->node_len -= (writebuf.size - 1);

    res->values->next = i;
    if(i == NULL) {
        res->values_end = res->values;
    }

    return COUCHSTORE_SUCCESS;
}