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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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; } } }
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); }
/** * 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); } }
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); }
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++; } }
/** 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)); }
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); }
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); }
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); }
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; }