예제 #1
0
파일: bitcask.c 프로젝트: haiger/beansdb
void bc_scan(Bitcask* bc)
{
    const char* path = mgr_base(bc->mgr);
    char dname[20], hname[20], datapath[255], hintpath[255];
    int i=0;
    struct stat st;
    for (i=0; i<MAX_BUCKET_COUNT; i++) {
        sprintf(dname, DATA_FILE, i);
        sprintf(datapath, "%s/%s", path, dname);
        if (stat(datapath, &st) != 0) {
            break;
        }
        bc->bytes += st.st_size;

        sprintf(hname, HINT_FILE, i);
        sprintf(hintpath, "%s/%s", path, hname);
        if (bc->before == 0){
            if (0 == stat(hintpath, &st)){
                scanHintFile(bc->tree, i, hintpath, NULL);
            }else{
                sprintf(hintpath, "%s/%s", mgr_alloc(bc->mgr, hname), hname);
                scanDataFile(bc->tree, i, datapath, hintpath);                
            }
        }else{
            if (0 == stat(hintpath, &st) && 
                (st.st_mtime < bc->before || 0 == stat(datapath, &st) && st.st_mtime < bc->before)){
                scanHintFile(bc->tree, i, hintpath, NULL); 
            }else{
                scanDataFileBefore(bc->tree, i, datapath, bc->before);
            }
        }
    }
    bc->curr = i;
}
예제 #2
0
파일: bitcask.c 프로젝트: haiger/beansdb
/*
 * 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);
}
예제 #3
0
파일: bitcask.c 프로젝트: alexband/beansdb
static inline char *new_path(char *dst, Mgr *mgr, const char *fmt, int i)
{
    char *path = gen_path(dst, mgr_base(mgr), fmt, i);
    if (!file_exists(dst))
    {
        char name[16];
        sprintf(name, fmt, i);
        sprintf(path, "%s/%s",  mgr_alloc(mgr, name), name);
    }
    return path;
}
예제 #4
0
파일: bitcask.c 프로젝트: haiger/beansdb
void bc_optimize(Bitcask *bc, int limit)
{
    int i;
    for (i=0; i < bc->curr; i++) {
        char data[20], hint[20], datapath[255], hintpath[255];
        sprintf(data, DATA_FILE, i);
        sprintf(hint, HINT_FILE, i);
        sprintf(datapath, "%s/%s", mgr_alloc(bc->mgr, data), data);
        sprintf(hintpath, "%s/%s", mgr_alloc(bc->mgr, hint), hint);
        
        uint32_t recoverd = 0;
        HTree *cur_tree = optimizeDataFile(bc->tree, i, datapath, hintpath, limit, &recoverd);
        if (NULL == cur_tree) continue;
        pthread_mutex_lock(&bc->buffer_lock);
        bc->bytes -= recoverd;
        pthread_mutex_unlock(&bc->buffer_lock);

        pthread_mutex_lock(&bc->write_lock);
        ht_visit(cur_tree, update_items, bc->tree);
        pthread_mutex_unlock(&bc->write_lock);

        build_hint(cur_tree, hintpath);
    }
}
예제 #5
0
파일: bitcask.c 프로젝트: haiger/beansdb
void bc_flush(Bitcask *bc, int limit, int flush_period)
{
    if (bc->curr >= MAX_BUCKET_COUNT) {
        fprintf(stderr, "reach max bucket count\n");
        exit(1);
    }
    
    pthread_mutex_lock(&bc->flush_lock);

    time_t now = time(NULL);
    if (bc->wbuf_curr_pos > limit * 1024 || 
        now > bc->last_flush_time + flush_period && bc->wbuf_curr_pos > 0) {
        char name[20], buf[255];
        sprintf(name, DATA_FILE, bc->curr);
        sprintf(buf, "%s/%s", mgr_alloc(bc->mgr, name), name);

        FILE *f = fopen(buf, "ab");
        if (f == NULL) {
            fprintf(stderr, "open file %s for flushing failed.\n", buf);
            exit(1);
        }
        // check file size
        uint64_t last_pos = ftell(f);
        if (last_pos > 0 && last_pos != bc->wbuf_start_pos) {
            fprintf(stderr, "last pos not match: %llu != %d\n", last_pos, bc->wbuf_start_pos);
            exit(1);
        }
      
        pthread_mutex_lock(&bc->buffer_lock);
        int size = bc->wbuf_curr_pos;
        char * tmp = (char*) malloc(size);
        memcpy(tmp, bc->write_buffer, size);
        pthread_mutex_unlock(&bc->buffer_lock);
        
        int n = fwrite(tmp, 1, size, f);
        if (n <= 0) {
            fprintf(stderr, "write failed: return %d\n", n);
            exit(1);
        }
        free(tmp);
        fclose(f);
        bc->last_flush_time = now;

        pthread_mutex_lock(&bc->buffer_lock);
        bc->bytes += n;
        if (n < bc->wbuf_curr_pos) {
            memmove(bc->write_buffer, bc->write_buffer + n, bc->wbuf_curr_pos - n);
        }
        bc->wbuf_start_pos += n;
        bc->wbuf_curr_pos -= n;
        if (bc->wbuf_curr_pos == 0) {
            if (bc->wbuf_size < WRITE_BUFFER_SIZE) {
                bc->wbuf_size *= 2;
                free(bc->write_buffer);
                bc->write_buffer = malloc(bc->wbuf_size);
            } else if (bc->wbuf_size > WRITE_BUFFER_SIZE * 2) {
                bc->wbuf_size = WRITE_BUFFER_SIZE;
                free(bc->write_buffer);
                bc->write_buffer = malloc(bc->wbuf_size);
            }
        }
        
        if (bc->wbuf_start_pos + bc->wbuf_size > MAX_BUCKET_SIZE) {
            // build in new thread
            char hname[20], hintpath[255];
            sprintf(hname, HINT_FILE, bc->curr);
            sprintf(hintpath, "%s/%s", mgr_alloc(bc->mgr, hname), hname);
            struct build_thread_args *args = (struct build_thread_args*)malloc(
                    sizeof(struct build_thread_args));
            args->tree = bc->curr_tree;
            args->path = strdup(hintpath);
            pthread_t build_ptid;
            pthread_create(&build_ptid, NULL, build_thread, args);
            // next bucket
            bc->curr ++;
            bc->curr_tree = ht_new(bc->depth, bc->pos);
            bc->wbuf_start_pos = 0;
        }
        pthread_mutex_unlock(&bc->buffer_lock);
    }
    pthread_mutex_unlock(&bc->flush_lock);
}