示例#1
0
static ham_status_t
_remote_cursor_overwrite(ham_cursor_t *cursor, 
            ham_record_t *record, ham_u32_t flags)
{
    ham_status_t st;
    ham_db_t *db=cursor_get_db(cursor);
    ham_env_t *env=db_get_env(db);
    proto_wrapper_t *request, *reply;
    
    request=proto_init_cursor_overwrite_request(
                        cursor_get_remote_handle(cursor), record, flags);

    st=_perform_request(env, env_get_curl(env), request, &reply);
    proto_delete(request);
    if (st) {
        if (reply)
            proto_delete(reply);
        return (st);
    }

    ham_assert(reply!=0, (""));
    ham_assert(proto_has_cursor_overwrite_reply(reply)!=0, (""));

    st=proto_cursor_overwrite_reply_get_status(reply);

    proto_delete(reply);

    return (st);
}
示例#2
0
static ham_status_t
_remote_cursor_close(ham_cursor_t *cursor)
{
    ham_status_t st;
    ham_env_t *env=db_get_env(cursor_get_db(cursor));
    proto_wrapper_t *request, *reply;
    
    request=proto_init_cursor_close_request(cursor_get_remote_handle(cursor));

    st=_perform_request(env, env_get_curl(env), request, &reply);
    proto_delete(request);
    if (st) {
        if (reply)
            proto_delete(reply);
        return (st);
    }

    ham_assert(reply!=0, (""));
    ham_assert(proto_has_cursor_close_reply(reply)!=0, (""));

    st=proto_cursor_close_reply_get_status(reply);

    proto_delete(reply);

    return (st);
}
示例#3
0
static ham_status_t 
_remote_fun_open(ham_env_t *env, const char *filename, ham_u32_t flags, 
        const ham_parameter_t *param)
{
    ham_status_t st;
    proto_wrapper_t *request, *reply;
    CURL *handle=curl_easy_init();

    request=proto_init_connect_request(filename);

    st=_perform_request(env, handle, request, &reply);
    proto_delete(request);
    if (st) {
        curl_easy_cleanup(handle);
        if (reply)
            proto_delete(reply);
        return (st);
    }

    ham_assert(reply!=0, (""));
    ham_assert(proto_has_connect_reply(reply), (""));

    st=proto_connect_reply_get_status(reply);
    if (st==0) {
        env_set_curl(env, handle);
        env_set_rt_flags(env, 
                env_get_rt_flags(env)
                    |proto_connect_reply_get_env_flags(reply));
    }

    proto_delete(reply);

    return (st);
}
示例#4
0
static ham_status_t
_remote_cursor_move(ham_cursor_t *cursor, ham_key_t *key, 
                ham_record_t *record, ham_u32_t flags)
{
    ham_status_t st;
    ham_db_t *db=cursor_get_db(cursor);
    ham_env_t *env=db_get_env(db);
    proto_wrapper_t *request, *reply;
    
    request=proto_init_cursor_move_request(cursor_get_remote_handle(cursor), 
                        key, record, flags);

    st=_perform_request(env, env_get_curl(env), request, &reply);
    proto_delete(request);
    if (st) {
        if (reply)
            proto_delete(reply);
        return (st);
    }

    ham_assert(reply!=0, (""));
    ham_assert(proto_has_cursor_move_reply(reply)!=0, (""));

    st=proto_cursor_move_reply_get_status(reply);
    if (st) 
        goto bail;

    /* modify key/record, but make sure that USER_ALLOC is respected! */
    if (proto_cursor_move_reply_has_key(reply)) {
        ham_assert(key, (""));
        key->_flags=proto_cursor_move_reply_get_key_intflags(reply);
        key->size=proto_cursor_move_reply_get_key_size(reply);
        if (!(key->flags&HAM_KEY_USER_ALLOC)) {
            st=db_resize_key_allocdata(db, key->size);
            if (st)
                goto bail;
            key->data=db_get_key_allocdata(db);
        }
        memcpy(key->data, proto_cursor_move_reply_get_key_data(reply),
                key->size);
    }

    /* same for the record */
    if (proto_cursor_move_reply_has_record(reply)) {
        ham_assert(record, (""));
        record->size=proto_cursor_move_reply_get_record_size(reply);
        if (!(record->flags&HAM_RECORD_USER_ALLOC)) {
            st=db_resize_record_allocdata(db, record->size);
            if (st)
                goto bail;
            record->data=db_get_record_allocdata(db);
        }
        memcpy(record->data, proto_cursor_move_reply_get_record_data(reply),
                record->size);
    }

bail:
    proto_delete(reply);
    return (st);
}
示例#5
0
static ham_status_t
_remote_fun_txn_abort(ham_env_t *env, ham_txn_t *txn, ham_u32_t flags)
{
    ham_status_t st;
    proto_wrapper_t *request, *reply;

    request=proto_init_txn_abort_request(txn_get_remote_handle(txn), flags);
    
    st=_perform_request(env, env_get_curl(env), request, &reply);
    proto_delete(request);
    if (st) {
        if (reply)
            proto_delete(reply);
        return (st);
    }

    ham_assert(reply!=0, (""));
    ham_assert(proto_has_txn_abort_reply(reply), (""));

    st=proto_txn_abort_reply_get_status(reply);

    if (st==0) {
        memset(txn, 0, sizeof(*txn));
        allocator_free(env_get_allocator(env), txn);

        /* remove the link between env and txn */
    	env_set_txn(env, 0);
    }

    proto_delete(reply);

    return (st);
}
示例#6
0
static ham_status_t
_remote_fun_env_flush(ham_env_t *env, ham_u32_t flags)
{
    ham_status_t st;
    proto_wrapper_t *request, *reply;

    request=proto_init_env_flush_request(flags);

    st=_perform_request(env, env_get_curl(env), request, &reply);
    proto_delete(request);
    if (st) {
        if (reply)
            proto_delete(reply);
        return (st);
    }

    ham_assert(reply!=0, (""));
    ham_assert(proto_has_env_flush_reply(reply), (""));

    st=proto_env_flush_reply_get_status(reply);

    proto_delete(reply);

    return (st);
}
示例#7
0
static ham_status_t
_remote_fun_check_integrity(ham_db_t *db, ham_txn_t *txn)
{
    ham_status_t st;
    ham_env_t *env=db_get_env(db);
    proto_wrapper_t *request, *reply;
    
    request=proto_init_check_integrity_request(db_get_remote_handle(db), 
                        txn ? txn_get_remote_handle(txn) : 0);

    st=_perform_request(env, env_get_curl(env), request, &reply);
    proto_delete(request);
    if (st) {
        if (reply)
            proto_delete(reply);
        return (st);
    }

    ham_assert(reply!=0, (""));
    ham_assert(proto_has_check_integrity_reply(reply), (""));
    st=proto_check_integrity_reply_get_status(reply);

    proto_delete(reply);

    return (st);
}
示例#8
0
static ham_status_t
_remote_fun_get_key_count(ham_db_t *db, ham_txn_t *txn, ham_u32_t flags,
            ham_offset_t *keycount)
{
    ham_status_t st;
    ham_env_t *env=db_get_env(db);
    proto_wrapper_t *request, *reply;
    
    request=proto_init_db_get_key_count_request(db_get_remote_handle(db), 
                        txn ? txn_get_remote_handle(txn) : 0, flags);

    st=_perform_request(env, env_get_curl(env), request, &reply);
    proto_delete(request);
    if (st) {
        if (reply)
            proto_delete(reply);
        return (st);
    }

    ham_assert(reply!=0, (""));
    ham_assert(proto_has_db_get_key_count_reply(reply), (""));

    st=proto_db_get_key_count_reply_get_status(reply);
    if (!st)
        *keycount=proto_db_get_key_count_reply_get_key_count(reply);

    proto_delete(reply);

    return (st);
}
示例#9
0
文件: blob.c 项目: bawerd/hamsterdb
ham_status_t 
blob_duplicate_get(ham_env_t *env, ham_offset_t table_id,
        ham_size_t position, dupe_entry_t *entry)
{
	ham_status_t st;
    dupe_table_t *table;
    ham_page_t *page=0;

    st = __get_duplicate_table(&table, &page, env, table_id);
	ham_assert(st ? table == NULL : 1, (0));
	ham_assert(st ? page == NULL : 1, (0));
    if (!table)
		return st ? st : HAM_INTERNAL_ERROR;

    if (position>=dupe_table_get_count(table)) 
	{
        if (!(env_get_rt_flags(env)&HAM_IN_MEMORY_DB))
            if (!page)
                allocator_free(env_get_allocator(env), table);
        return HAM_KEY_NOT_FOUND;
    }
    memcpy(entry, dupe_table_get_entry(table, position), sizeof(*entry));

    if (!(env_get_rt_flags(env)&HAM_IN_MEMORY_DB))
	{
        if (!page)
            allocator_free(env_get_allocator(env), table);
	}
    return (0);
}
示例#10
0
ham_status_t
txn_add_page(ham_txn_t *txn, ham_page_t *page, ham_bool_t ignore_if_inserted)
{
    /*
     * don't re-insert, if 'ignore_if_inserted' is true
     */
    if (ignore_if_inserted && txn_get_page(txn, page_get_self(page)))
        return (0);

#ifdef HAM_DEBUG
    /*
     * check if the page is already in the transaction's pagelist - 
     * that would be a bug
     */
    ham_assert(txn_get_page(txn, page_get_self(page))==0, 
            ("page 0x%llx is already in the txn", page_get_self(page)));
#endif

    /*
     * not found? add the page
     */
    page_add_ref(page);

    ham_assert(!page_is_in_list(txn_get_pagelist(txn), page, PAGE_LIST_TXN), (0));
    txn_set_pagelist(txn, page_list_insert(txn_get_pagelist(txn), 
            PAGE_LIST_TXN, page));

    return (HAM_SUCCESS);
}
示例#11
0
文件: blob.c 项目: bawerd/hamsterdb
ham_status_t
blob_get_datasize(ham_db_t *db, ham_offset_t blobid, ham_offset_t *size)
{
    ham_status_t st;
    ham_page_t *page;
    blob_t hdr;

    /*
     * in-memory-database: the blobid is actually a pointer to the memory
     * buffer, in which the blob is stored
     */
    if (env_get_rt_flags(db_get_env(db))&HAM_IN_MEMORY_DB) {
        blob_t *hdr=(blob_t *)U64_TO_PTR(blobid);
        *size=blob_get_size(hdr);
        return (0);
    }

    ham_assert(blobid%DB_CHUNKSIZE==0, ("blobid is %llu", blobid));

    /* read the blob header */
    st=__read_chunk(db_get_env(db), 0, &page, blobid, 
                    (ham_u8_t *)&hdr, sizeof(hdr));
    if (st)
        return (st);

    ham_assert(blob_get_alloc_size(&hdr)%DB_CHUNKSIZE==0, (0));
    if (blob_get_self(&hdr)!=blobid)
        return (HAM_BLOB_NOT_FOUND);

    *size=blob_get_size(&hdr);
    return (0);
}
示例#12
0
static ham_status_t
_remote_fun_find(ham_db_t *db, ham_txn_t *txn, ham_key_t *key,
            ham_record_t *record, ham_u32_t flags)
{
    ham_status_t st;
    ham_env_t *env=db_get_env(db);
    proto_wrapper_t *request, *reply;

    request=proto_init_db_find_request(db_get_remote_handle(db), 
                        txn ? txn_get_remote_handle(txn) : 0, 
                        key, record, flags);

    st=_perform_request(env, env_get_curl(env), request, &reply);
    proto_delete(request);
    if (st) {
        if (reply)
            proto_delete(reply);
        return (st);
    }

    ham_assert(reply!=0, (""));
    ham_assert(proto_has_db_find_reply(reply)!=0, (""));

    st=proto_db_find_reply_get_status(reply);
    if (st==0) {
        /* approx. matching: need to copy the _flags and the key data! */
        if (proto_db_find_reply_has_key(reply)) {
            ham_assert(key, (""));
            key->_flags=proto_db_find_reply_get_key_intflags(reply);
            key->size=proto_db_find_reply_get_key_size(reply);
            if (!(key->flags&HAM_KEY_USER_ALLOC)) {
                st=db_resize_key_allocdata(db, key->size);
                if (st)
                    goto bail;
                key->data=db_get_key_allocdata(db);
            }
            memcpy(key->data, proto_db_find_reply_get_key_data(reply),
                    key->size);
        }
        if (proto_db_find_reply_has_record(reply)) {
            record->size=proto_db_find_reply_get_record_size(reply);
            if (!(record->flags&HAM_RECORD_USER_ALLOC)) {
                st=db_resize_record_allocdata(db, record->size);
                if (st)
                    goto bail;
                record->data=db_get_record_allocdata(db);
            }
            memcpy(record->data, proto_db_find_reply_get_record_data(reply),
                    record->size);
        }
    }

bail:
    proto_delete(reply);

    return (st);
}
void 
btree_erase_get_hints(erase_hints_t *hints, ham_db_t *db, ham_key_t *key)
{
    ham_runtime_statistics_dbdata_t *dbdata = db_get_db_perf_data(db);

    ham_assert(hints->key_is_out_of_bounds == HAM_FALSE, (0));
    ham_assert(hints->try_fast_track == HAM_FALSE, (0));

    ham_assert(!(key->_flags & KEY_IS_EXTENDED), (0));
    key->_flags &= ~KEY_IS_EXTENDED;

    /* forget about deleting a key when it's out of bounds */
    if (dbdata->lower_bound_set)
    {
        if (dbdata->lower_bound_index == 1)
        {
            /*
            impossible index: this is a marker to signal the table 
            is completely empty
            */
            hints->key_is_out_of_bounds = HAM_TRUE;
            hints->try_fast_track = HAM_TRUE;
        }
        else
        {
            int cmp;
            
            ham_assert(dbdata->lower_bound_index == 0, (0));
            ham_assert(dbdata->lower_bound.data == NULL ?
                dbdata->lower_bound.size == 0 : 
                dbdata->lower_bound.size > 0, (0));
            ham_assert(dbdata->lower_bound_page_address != 0, (0));
            cmp = db_compare_keys(db, key, &dbdata->lower_bound);

            if (cmp < 0)
            {
                hints->key_is_out_of_bounds = HAM_TRUE;
                hints->try_fast_track = HAM_TRUE;
            }
        }
    }

    if (dbdata->upper_bound_set)
    {
        int cmp;
        
        ham_assert(dbdata->upper_bound_index >= 0, (0));
        ham_assert(dbdata->upper_bound.data == NULL ?
            dbdata->upper_bound.size == 0 : 
            dbdata->upper_bound.size > 0, (0));
        ham_assert(dbdata->upper_bound_page_address != 0, (0));
        cmp = db_compare_keys(db, key, &dbdata->upper_bound);

        if (cmp > 0)
        {
            hints->key_is_out_of_bounds = HAM_TRUE;
            hints->try_fast_track = HAM_TRUE;
        }
    }
}
示例#14
0
ham_status_t
txn_free_page(ham_txn_t *txn, ham_page_t *page)
{
    ham_assert(!(page_get_npers_flags(page)&PAGE_NPERS_DELETE_PENDING), (0));
    ham_assert(page_get_cursors(page)==0, (0));

    page_set_npers_flags(page,
            page_get_npers_flags(page)|PAGE_NPERS_DELETE_PENDING);

    return (HAM_SUCCESS);
}
示例#15
0
/**                                                                    
 * Remove all extended keys for the given @a page from the            
 * extended key cache.                                                
 */                                                                    
static ham_status_t
my_fun_free_page_extkeys(ham_btree_t *be, ham_page_t *page, ham_u32_t flags)
{
    ham_db_t *db=be_get_db(be);
    
    ham_assert(page_get_owner(page) == db, (0));
    
    ham_assert(0 == (flags & ~DB_MOVE_TO_FREELIST), (0));

    /*
     * if this page has a header, and it's either a B-Tree root page or 
     * a B-Tree index page: remove all extended keys from the cache, 
     * and/or free their blobs
     */
    if (page_get_pers(page) 
            && (!(page_get_npers_flags(page)&PAGE_NPERS_NO_HEADER))
            && (page_get_type(page)==PAGE_TYPE_B_ROOT 
                || page_get_type(page)==PAGE_TYPE_B_INDEX)) 
    {
        ham_size_t i;
        ham_offset_t blobid;
        int_key_t *bte;
        btree_node_t *node=ham_page_get_btree_node(page);
        extkey_cache_t *c;

        ham_assert(db, ("Must be set as page owner when this is a Btree page"));
        ham_assert(db=page_get_owner(page), (""));
        c=db_get_extkey_cache(db);

        for (i=0; i<btree_node_get_count(node); i++) 
        {
            bte=btree_node_get_key(db, node, i);
            if (key_get_flags(bte)&KEY_IS_EXTENDED) 
            {
                blobid=key_get_extended_rid(db, bte);
                if (env_get_rt_flags(db_get_env(db))&HAM_IN_MEMORY_DB) 
                {
                    /* delete the blobid to prevent that it's freed twice */
                    *(ham_offset_t *)(key_get_key(bte)+
                        (db_get_keysize(db)-sizeof(ham_offset_t)))=0;
                }
                //(void)key_erase_record(db, bte, 0, BLOB_FREE_ALL_DUPES);
                if (c)
                    (void)extkey_cache_remove(c, blobid);
            }
        }
    }

    return (HAM_SUCCESS);
}
ham_status_t
stats_fill_ham_statistics_t(ham_env_t *env, ham_db_t *db, ham_statistics_t *dst)
{
    ham_status_t st;
    ham_bool_t collect_globdata;
    ham_bool_t collect_dbdata;

    ham_assert(dst, (0));

    /* copy the user-specified selectors before we zero the whole darn thing */
    collect_globdata = (!dst->dont_collect_global_stats && env);
    collect_dbdata = (!dst->dont_collect_db_stats && db);

    /* now zero the entire structure to begin with */
    memset(dst, 0, sizeof(*dst));

    /* then see if we can / should collect env/global and db-specific stats in there */
    if (collect_globdata)
    {
        ham_runtime_statistics_globdata_t *globalstats;

        ham_assert(env, (0));
        globalstats = env_get_global_perf_data(env);
        ham_assert(globalstats, (0));

        dst->global_stats = *globalstats;
    }
    if (collect_dbdata)
    {
        ham_runtime_statistics_dbdata_t *dbdata;

        ham_assert(db, (0));
        dbdata = db_get_db_perf_data(db);
        ham_assert(dbdata, (0));

        dst->db_stats = *dbdata;
    }

    dst->dont_collect_freelist_stats = !0;

    /* now the tougher part: see if we should report the freelist statistics */
    st = stats_fill_freel_statistics_t(env, dst);

    /* and finally mark which sections have actually been fetched */
    dst->dont_collect_global_stats = !collect_globdata;
    dst->dont_collect_db_stats = !collect_dbdata;
    
    return st;
}
/*
 * when the last hit leaf node is split or shrunk, blow it away for all operations!
 *
 * Also blow away a page when a transaction aborts which has modified this page. We'd rather
 * reconstruct our critical statistics then carry the wrong bounds, etc. around.
 *
 * This is done to prevent the hinter from hinting/pointing at an (by now)
 * INVALID btree node later on!
 */
void 
stats_page_is_nuked(ham_db_t *db, struct ham_page_t *page, ham_bool_t split)
{
    ham_runtime_statistics_dbdata_t *dbdata = db_get_db_perf_data(db);
    ham_env_t *env = db_get_env(db);
    int i;

    for (i = 0; i <= 2; i++)
    {
        ham_runtime_statistics_opdbdata_t *opstats = db_get_op_perf_data(db, i);

        ham_assert(i == HAM_OPERATION_STATS_FIND
                    || i == HAM_OPERATION_STATS_INSERT
                    || i == HAM_OPERATION_STATS_ERASE, (0));

        if (opstats->btree_last_page_addr == page_get_self(page))
        {
            opstats->btree_last_page_addr = 0;
            opstats->btree_last_page_sq_hits = 0;
        }
    }

    if (dbdata->lower_bound_page_address == page_get_self(page))
    {
        if (dbdata->lower_bound.data)
        {
            ham_assert(env_get_allocator(env) != 0, (0));
            allocator_free(env_get_allocator(env), dbdata->lower_bound.data);
        }
        memset(&dbdata->lower_bound, 0, sizeof(dbdata->lower_bound));
        dbdata->lower_bound_index = 0;
        dbdata->lower_bound_page_address = 0;
        dbdata->lower_bound_set = HAM_FALSE;
    }

	if (dbdata->upper_bound_page_address == page_get_self(page))
    {
        if (dbdata->upper_bound.data)
        {
            ham_assert(env_get_allocator(env) != 0, (0));
            allocator_free(env_get_allocator(env), dbdata->upper_bound.data);
        }
        memset(&dbdata->upper_bound, 0, sizeof(dbdata->upper_bound));
        dbdata->upper_bound_index = 0;
        dbdata->upper_bound_page_address = 0;
        dbdata->upper_bound_set = HAM_FALSE;
    }
}
void 
stats_update(int op, ham_db_t *db, ham_page_t *page, ham_size_t cost, ham_bool_t try_fast_track)
{
    ham_runtime_statistics_dbdata_t *dbstats = db_get_db_perf_data(db);
    ham_runtime_statistics_opdbdata_t *opstats = db_get_op_perf_data(db, op);

    ham_assert(op == HAM_OPERATION_STATS_FIND
                || op == HAM_OPERATION_STATS_INSERT
                || op == HAM_OPERATION_STATS_ERASE, (0));
    ham_assert(page, (0));

    /*
     * Again, cost is the fastest riser, so we check that one against a high water mark
     * to decide whether to rescale or not
     */
    if (dbstats->rescale_tracker >= HAM_STATISTICS_HIGH_WATER_MARK - cost)
    {
        rescale_db_stats(dbstats);
    }
    dbstats->rescale_tracker += cost;

    opstats->btree_count++;
    //opstats->btree_fail_count++;
    opstats->btree_cost += cost;
    //opstats->btree_fail_cost += cost;

    /*
     * when we got a hint, account for it's success/failure
     */
    if (try_fast_track)
    {
        if (opstats->btree_last_page_addr != page_get_self(page))
        {
            opstats->btree_hinting_fail_count++;
        }
        opstats->btree_hinting_count++;
    }
    
    if (opstats->btree_last_page_addr
        && opstats->btree_last_page_addr == page_get_self(page))
    {
        opstats->btree_last_page_sq_hits++;
    }
    else
    {
        opstats->btree_last_page_addr = page_get_self(page);
    }
}
示例#19
0
static ham_status_t
_remote_cursor_find(ham_cursor_t *cursor, ham_key_t *key, 
                ham_record_t *record, ham_u32_t flags)
{
    ham_status_t st;
    ham_db_t *db=cursor_get_db(cursor);
    ham_env_t *env=db_get_env(db);
    proto_wrapper_t *request, *reply;

    request=proto_init_cursor_find_request(cursor_get_remote_handle(cursor), 
                        key, record, flags);
    
    st=_perform_request(env, env_get_curl(env), request, &reply);
    proto_delete(request);
    if (st) {
        if (reply)
            proto_delete(reply);
        return (st);
    }

    ham_assert(reply!=0, (""));
    ham_assert(proto_has_cursor_find_reply(reply)!=0, (""));

    st=proto_cursor_find_reply_get_status(reply);
    if (st) 
        goto bail;

    /* approx. matching: need to copy the _flags! */
    if (proto_cursor_find_reply_has_key(reply)) {
        key->_flags=proto_cursor_find_reply_get_key_intflags(reply);
    }
    if (proto_cursor_find_reply_has_record(reply)) {
        ham_assert(record, (""));
        record->size=proto_cursor_find_reply_get_record_size(reply);
        if (!(record->flags&HAM_RECORD_USER_ALLOC)) {
            st=db_resize_record_allocdata(db, record->size);
            if (st)
                goto bail;
            record->data=db_get_record_allocdata(db);
        }
        memcpy(record->data, proto_cursor_find_reply_get_record_data(reply),
                record->size);
    }

bail:
    proto_delete(reply);
    return (st);
}
ham_status_t
extkey_cache_purge(extkey_cache_t *cache)
{
    ham_size_t i;
    extkey_t *e, *n;
    ham_env_t *env;
	
	ham_assert(extkey_cache_get_db(cache), (0));
	env = db_get_env(extkey_cache_get_db(cache));

    /*
     * delete all entries which are "too old" (were not 
     * used in the last EXTKEY_MAX_AGE transactions)
     */
    for (i=0; i<extkey_cache_get_bucketsize(cache); i++) {
        extkey_t *p=0;
        e=extkey_cache_get_bucket(cache, i);
        while (e) {
            n=extkey_get_next(e);
            if (env_get_txn_id(env)-extkey_get_txn_id(e)>EXTKEY_MAX_AGE) {
                /* deleted the head element of the list? */
                if (!p)
                    extkey_cache_set_bucket(cache, i, n);
                else
                    extkey_set_next(p, n);
                allocator_free(env_get_allocator(env), e);
            }
            else
                p=e;
            e=n;
        }
    }

    return (0);
}
void
extkey_cache_destroy(extkey_cache_t *cache)
{
    ham_size_t i;
    extkey_t *e, *n;
    ham_db_t *db=extkey_cache_get_db(cache);
	ham_env_t *env = db_get_env(db);

    /*
     * make sure that all entries are empty
     */
    for (i=0; i<extkey_cache_get_bucketsize(cache); i++) {
        e=extkey_cache_get_bucket(cache, i);
        while (e) {
#if HAM_DEBUG
            /*
             * make sure that the extkey-cache is empty - only for in-memory
             * databases and DEBUG builds.
             */
            if (env_get_rt_flags(env)&HAM_IN_MEMORY_DB)
                ham_assert(!"extkey-cache is not empty!", (0));
#endif
            n=extkey_get_next(e);
            allocator_free(env_get_allocator(env), e);
            e=n;
        }
    }

    allocator_free(env_get_allocator(env), cache);
}
ham_status_t
extkey_cache_insert(extkey_cache_t *cache, ham_offset_t blobid, 
            ham_size_t size, const ham_u8_t *data)
{
    ham_size_t h=my_calc_hash(cache, blobid);
    extkey_t *e;
    ham_db_t *db=extkey_cache_get_db(cache);
	ham_env_t *env = db_get_env(db);

    /*
     * DEBUG build: make sure that the item is not inserted twice!
     */
#ifdef HAM_DEBUG
    e=extkey_cache_get_bucket(cache, h);
    while (e) {
        ham_assert(extkey_get_blobid(e)!=blobid, (0));
        e=extkey_get_next(e);
    }
#endif

    e=(extkey_t *)allocator_alloc(env_get_allocator(env), SIZEOF_EXTKEY_T+size);
    if (!e)
        return HAM_OUT_OF_MEMORY;
    extkey_set_blobid(e, blobid);
    extkey_set_txn_id(e, env_get_txn_id(env));
    extkey_set_next(e, extkey_cache_get_bucket(cache, h));
    extkey_set_size(e, size);
    memcpy(extkey_get_data(e), data, size);

    extkey_cache_set_bucket(cache, h, e);
    extkey_cache_set_usedsize(cache, extkey_cache_get_usedsize(cache)+size);

    return (0);
}
示例#23
0
ham_page_t *
cache_get_page(ham_cache_t *cache, ham_offset_t address, ham_u32_t flags)
{
    ham_page_t *page;
    ham_size_t hash=__calc_hash(cache, address);

    page=cache_get_bucket(cache, hash);
    while (page) {
        if (page_get_self(page)==address)
            break;
        page=page_get_next(page, PAGE_LIST_BUCKET);
    }

    if (page && flags != CACHE_NOREMOVE) {
        if (page_is_in_list(cache_get_totallist(cache), page, PAGE_LIST_CACHED))
        {
            cache_set_totallist(cache, 
                page_list_remove(cache_get_totallist(cache), 
                PAGE_LIST_CACHED, page));
        }
        ham_assert(page_is_in_list(cache_get_bucket(cache, hash), page, 
                PAGE_LIST_BUCKET), (0));
        cache_set_bucket(cache, hash,
            page_list_remove(cache_get_bucket(cache, 
            hash), PAGE_LIST_BUCKET, page));

        cache_set_cur_elements(cache, 
            cache_get_cur_elements(cache)-1);
    }

    return (page);
}
void
stats_trash_dbdata(ham_db_t *db, ham_runtime_statistics_dbdata_t *dbdata)
{
    ham_env_t *env = db_get_env(db);

    /* trash the upper/lower bound keys, when set: */
    if (dbdata->upper_bound.data) {
        ham_assert(env_get_allocator(env) != 0, (0));
        allocator_free(env_get_allocator(env), dbdata->upper_bound.data);
    }
    if (dbdata->lower_bound.data) {
        ham_assert(env_get_allocator(env) != 0, (0));
        allocator_free(env_get_allocator(env), dbdata->lower_bound.data);
    }
    memset(dbdata, 0, sizeof(*dbdata));
}
void 
stats_update_fail(int op, ham_db_t *db, ham_size_t cost, ham_bool_t try_fast_track)
{
    //ham_runtime_statistics_globdata_t *globalstats = db_get_global_perf_data(db);
    ham_runtime_statistics_dbdata_t *dbstats = db_get_db_perf_data(db);
    ham_runtime_statistics_opdbdata_t *opstats = db_get_op_perf_data(db, op);

    ham_assert(op == HAM_OPERATION_STATS_FIND
                || op == HAM_OPERATION_STATS_INSERT
                || op == HAM_OPERATION_STATS_ERASE, (0));

    /*
     * Again, cost is the fastest riser, so we check that one against a high water mark
     * to decide whether to rescale or not
     */
    if (dbstats->rescale_tracker >= HAM_STATISTICS_HIGH_WATER_MARK - cost) {
        rescale_db_stats(dbstats);
    }
    dbstats->rescale_tracker += cost;

    opstats->btree_count++;
    opstats->btree_fail_count++;
    opstats->btree_cost += cost;
    opstats->btree_fail_cost += cost;
    
    //opstats->btree_last_page_addr = 0; -- keep page from previous match around!
    opstats->btree_last_page_sq_hits = 0; /* reset */

    if (try_fast_track)
    {
        opstats->btree_hinting_fail_count++;
        opstats->btree_hinting_count++;
    }
}
示例#26
0
/**                                                                    
Close (and free) all cursors related to this database table.        

 @note This is a B+-tree 'backend' method.
*/                                                                    
static ham_status_t 
my_fun_close_cursors(ham_btree_t *be, ham_u32_t flags)
{
    ham_db_t *db=be_get_db(be);

    ham_assert(db, (0));
    return (btree_close_cursors(db, flags));
}
示例#27
0
static ham_status_t
_remote_fun_txn_begin(ham_env_t *env, ham_db_t *db, 
                ham_txn_t **txn, ham_u32_t flags)
{
    ham_status_t st;
    proto_wrapper_t *request, *reply;
    
    request=proto_init_txn_begin_request(db_get_remote_handle(db), flags);

    st=_perform_request(env, env_get_curl(env), request, &reply);
    proto_delete(request);
    if (st) {
        if (reply)
            proto_delete(reply);
        return (st);
    }

    ham_assert(reply!=0, (""));
    ham_assert(proto_has_txn_begin_reply(reply), (""));

    st=proto_txn_begin_reply_get_status(reply);
    if (st) {
        proto_delete(reply);
        return (st);
    }

    *txn=(ham_txn_t *)allocator_alloc(env_get_allocator(env), 
                            sizeof(ham_txn_t));
    if (!(*txn))
        return (HAM_OUT_OF_MEMORY);

    st=txn_begin(*txn, env, flags);
    if (st) {
        allocator_free(env_get_allocator(env), *txn);
        *txn=0;
    }
    else {
        txn_set_remote_handle(*txn, 
                    proto_txn_begin_reply_get_txn_handle(reply));
    }

    proto_delete(reply);

    return (st);
}
示例#28
0
ham_status_t 
cache_put_page(ham_cache_t *cache, ham_page_t *page)
{
    ham_size_t hash=__calc_hash(cache, page_get_self(page));
    ham_bool_t new_page = HAM_TRUE;

    ham_assert(page_get_pers(page), (""));

    if (page_is_in_list(cache_get_totallist(cache), page, PAGE_LIST_CACHED)) {
        cache_set_totallist(cache, 
                page_list_remove(cache_get_totallist(cache), 
                PAGE_LIST_CACHED, page));

        new_page = HAM_FALSE;

        cache_set_cur_elements(cache, 
                cache_get_cur_elements(cache)-1);
    }
    ham_assert(!page_is_in_list(cache_get_totallist(cache), page, 
                PAGE_LIST_CACHED), (0));
    cache_set_totallist(cache, 
            page_list_insert(cache_get_totallist(cache), 
            PAGE_LIST_CACHED, page));

    cache_set_cur_elements(cache, 
            cache_get_cur_elements(cache)+1);

    /*
     * insert it in the cache bucket
     * !!!
     * to avoid inserting the page twice, we first remove it from the 
     * bucket
     */
    if (page_is_in_list(cache_get_bucket(cache, hash), page, PAGE_LIST_BUCKET))
    {
        cache_set_bucket(cache, hash, page_list_remove(cache_get_bucket(cache, 
                    hash), PAGE_LIST_BUCKET, page));
    }
    ham_assert(!page_is_in_list(cache_get_bucket(cache, hash), page, 
                PAGE_LIST_BUCKET), (0));
    cache_get_bucket(cache, hash)=page_list_insert(cache_get_bucket(cache, 
                hash), PAGE_LIST_BUCKET, page);

    return (0);
}
示例#29
0
static ham_status_t
_remote_cursor_insert(ham_cursor_t *cursor, ham_key_t *key,
            ham_record_t *record, ham_u32_t flags)
{
    ham_status_t st;
    ham_db_t *db=cursor_get_db(cursor);
    ham_env_t *env=db_get_env(db);
    proto_wrapper_t *request, *reply;
    ham_bool_t send_key=HAM_TRUE;

    /* recno: do not send the key */
    if (db_get_rt_flags(db)&HAM_RECORD_NUMBER)
        send_key=HAM_FALSE;
    
    request=proto_init_cursor_insert_request(cursor_get_remote_handle(cursor), 
                        send_key ? key : 0, record, flags);

    st=_perform_request(env, env_get_curl(env), request, &reply);
    proto_delete(request);
    if (st) {
        if (reply)
            proto_delete(reply);
        return (st);
    }

    ham_assert(reply!=0, (""));
    ham_assert(proto_has_cursor_insert_reply(reply)!=0, (""));

    st=proto_cursor_insert_reply_get_status(reply);

    /* recno: the key was modified! */
    if (st==0 && proto_cursor_insert_reply_has_key(reply)) {
        if (proto_cursor_insert_reply_get_key_size(reply)
                ==sizeof(ham_offset_t)) {
            ham_assert(key->data!=0, (""));
            ham_assert(key->size==sizeof(ham_offset_t), (""));
            memcpy(key->data, proto_cursor_insert_reply_get_key_data(reply),
                    sizeof(ham_offset_t));
        }
    }

    proto_delete(reply);

    return (st);
}
示例#30
0
文件: blob.c 项目: bawerd/hamsterdb
ham_status_t
blob_free(ham_env_t *env, ham_db_t *db, ham_offset_t blobid, ham_u32_t flags)
{
    ham_status_t st;
    blob_t hdr;

    /*
     * in-memory-database: the blobid is actually a pointer to the memory
     * buffer, in which the blob is stored
     */
    if (env_get_rt_flags(env)&HAM_IN_MEMORY_DB) {
        allocator_free(env_get_allocator(env), (void *)U64_TO_PTR(blobid));
        return (0);
    }

    ham_assert(blobid%DB_CHUNKSIZE==0, (0));

    /*
     * fetch the blob header 
     */
    st=__read_chunk(env, 0, 0, blobid, (ham_u8_t *)&hdr, sizeof(hdr));
    if (st)
        return (st);

    ham_assert(blob_get_alloc_size(&hdr)%DB_CHUNKSIZE==0, (0));

    /*
     * sanity check
     */
    ham_assert(blob_get_self(&hdr)==blobid, 
            ("invalid blobid %llu != %llu", blob_get_self(&hdr), blobid));
    if (blob_get_self(&hdr)!=blobid)
        return (HAM_BLOB_NOT_FOUND);

    /*
     * move the blob to the freelist
     */
    st = freel_mark_free(env, db, blobid, 
            (ham_size_t)blob_get_alloc_size(&hdr), HAM_FALSE);
	ham_assert(!st, ("unexpected error, at least not covered in the old code"));

    return st;
}