Beispiel #1
0
/*
 * bc_close() is not thread safe, should stop other threads before call it.
 * */
void bc_close(Bitcask *bc)
{
    int i=0;
    pthread_mutex_lock(&bc->write_lock);
    bc_flush(bc, 0, 0);
    
    if (NULL != bc->curr_tree) {
        uint32_t curr;
        ht_get_hash(bc->curr_tree, "@", &curr);
        if (curr > 0) {
            char name[255], buf[255];
            sprintf(name, HINT_FILE, bc->curr);
            sprintf(buf, "%s/%s", mgr_alloc(bc->mgr, name), name);
            build_hint(bc->curr_tree, buf);
        }else{
            ht_destroy(bc->curr_tree);
        }
        bc->curr_tree = NULL;
    }
    bc->curr = 0;
    ht_destroy(bc->tree);
    mgr_destroy(bc->mgr);
    free(bc->write_buffer);
    free(bc);
}
Beispiel #2
0
void hs_flush(HStore *store, int limit, int period)
{
    if (!store) return;
    if (store->before > 0) return;
    int i;
    for (i=0; i<store->count; i++){
        bc_flush(store->bitcasks[i], limit, period);
    }
}
Beispiel #3
0
/*
 * bc_close() is not thread safe, should stop other threads before call it.
 * */
void bc_close(Bitcask *bc)
{
    char datapath[255], hintpath[255];

    if (bc->optimize_flag > 0)
    {
        bc->optimize_flag = 2;
        while (bc->optimize_flag > 0)
        {
            sleep(1);
        }
    }

    pthread_mutex_lock(&bc->write_lock);

    bc_flush(bc, 0, 0);

    if (NULL != bc->curr_tree)
    {
        if (bc->curr_bytes > 0)
        {
            build_hint(bc->curr_tree, new_path(hintpath, bc->mgr, HINT_FILE, bc->curr));
        }
        else
        {
            ht_destroy(bc->curr_tree);
        }
        bc->curr_tree = NULL;
    }

    if (bc->curr_bytes == 0) bc->curr --;
    if (bc->curr - bc->last_snapshot >= SAVE_HTREE_LIMIT)
    {
        if (ht_save(bc->tree, new_path(datapath, bc->mgr, HTREE_FILE, bc->curr)) == 0)
        {
            mgr_unlink(gen_path(datapath, mgr_base(bc->mgr), HTREE_FILE, bc->last_snapshot));
        }
        else
        {
            fprintf(stderr, "save HTree to %s failed\n", datapath);
        }
    }
    ht_destroy(bc->tree);

    mgr_destroy(bc->mgr);
    free(bc->write_buffer);
    free(bc);
}
Beispiel #4
0
bool bc_set(Bitcask *bc, const char* key, char* value, int vlen, int flag, int version)
{
    if (version < 0 && vlen > 0 || vlen > MAX_RECORD_SIZE)
    {
        fprintf(stderr, "invalid set cmd \n");
        return false;
    }

    bool suc = false;
    pthread_mutex_lock(&bc->write_lock);

    int oldv = 0, ver = version;
    Item *it = ht_get(bc->tree, key);
    if (it != NULL)
    {
        oldv = it->ver;
    }

    if (version == 0 && oldv > 0)  // replace
    {
        ver = oldv + 1;
    }
    else if (version == 0 && oldv <= 0)    // add
    {
        ver = -oldv + 1;
    }
    else if (version < 0 && oldv <= 0)     // delete, not exist
    {
        goto SET_FAIL;
    }
    else if (version == -1)     // delete
    {
        ver = - abs(oldv) - 1;
    }
    else if (abs(version) <= abs(oldv))     // sync
    {
        goto SET_FAIL;
    }
    else     // sync
    {
        ver = version;
    }

    uint16_t hash = gen_hash(value, vlen);
    if (ver < 0) hash = 0;

    if (NULL != it && hash == it->hash)
    {
        DataRecord *r = bc_get(bc, key);
        if (r != NULL && r->flag == flag && vlen  == r->vsz
                && memcmp(value, r->value, vlen) == 0)
        {
            if (version != 0)
            {
                // update version
                if (it->pos & 0xff == bc->curr)
                {
                    ht_add(bc->curr_tree, key, it->pos, it->hash, ver);
                }
                ht_add(bc->tree, key, it->pos, it->hash, ver);
            }
            suc = true;
            free_record(r);
            goto SET_FAIL;
        }
        if (r != NULL) free_record(r);
    }

    int klen = strlen(key);
    DataRecord *r = (DataRecord*)malloc(sizeof(DataRecord) + klen);
    r->ksz = klen;
    memcpy(r->key, key, klen);
    r->vsz = vlen;
    r->value = value;
    r->free_value = false;
    r->flag = flag;
    r->version = ver;
    r->tstamp = time(NULL);

    int rlen;
    char *rbuf = encode_record(r, &rlen);
    if (rbuf == NULL || (rlen & 0xff) != 0)
    {
        fprintf(stderr, "encode_record() failed with %d\n", rlen);
        if (rbuf != NULL) free(rbuf);
        goto SET_FAIL;
    }

    pthread_mutex_lock(&bc->buffer_lock);
    // record maybe larger than buffer
    if (bc->wbuf_curr_pos + rlen > bc->wbuf_size)
    {
        pthread_mutex_unlock(&bc->buffer_lock);
        bc_flush(bc, 0, 0);
        pthread_mutex_lock(&bc->buffer_lock);

        while (rlen > bc->wbuf_size)
        {
            bc->wbuf_size *= 2;
            free(bc->write_buffer);
            bc->write_buffer = (char*)malloc(bc->wbuf_size);
        }
        if (bc->wbuf_start_pos + bc->wbuf_size > MAX_BUCKET_SIZE)
        {
            bc_rotate(bc);
        }
    }
    memcpy(bc->write_buffer + bc->wbuf_curr_pos, rbuf, rlen);
    int pos = (bc->wbuf_start_pos + bc->wbuf_curr_pos) | bc->curr;
    bc->wbuf_curr_pos += rlen;
    pthread_mutex_unlock(&bc->buffer_lock);

    ht_add(bc->curr_tree, key, pos, hash, ver);
    ht_add(bc->tree, key, pos, hash, ver);
    suc = true;
    free(rbuf);
    free_record(r);

SET_FAIL:
    pthread_mutex_unlock(&bc->write_lock);
    if (it != NULL) free(it);
    return suc;
}