Commit 3b200ebe authored by Zardosht Kasheff's avatar Zardosht Kasheff

refs Tokutek/mongo#886, change get_last_key to use a callback instead of...

refs Tokutek/mongo#886, change get_last_key to use a callback instead of copying data, so that we don't have
mongo code freeing data that fractal tree allocated.
parent d8b9fb11
...@@ -551,7 +551,7 @@ static void print_db_struct (void) { ...@@ -551,7 +551,7 @@ static void print_db_struct (void) {
"int (*get_fractal_tree_info64)(DB*,uint64_t*,uint64_t*,uint64_t*,uint64_t*)", "int (*get_fractal_tree_info64)(DB*,uint64_t*,uint64_t*,uint64_t*,uint64_t*)",
"int (*iterate_fractal_tree_block_map)(DB*,int(*)(uint64_t,int64_t,int64_t,int64_t,int64_t,void*),void*)", "int (*iterate_fractal_tree_block_map)(DB*,int(*)(uint64_t,int64_t,int64_t,int64_t,int64_t,void*),void*)",
"const char *(*get_dname)(DB *db)", "const char *(*get_dname)(DB *db)",
"int (*get_last_key)(DB *db, DBT*, uint32_t)", "int (*get_last_key)(DB *db, YDB_CALLBACK_FUNCTION func, void* extra)",
NULL}; NULL};
sort_and_dump_fields("db", true, extra); sort_and_dump_fields("db", true, extra);
} }
......
...@@ -173,34 +173,25 @@ static void cleanup_env_and_db(DB_ENV * env, DB * db) ...@@ -173,34 +173,25 @@ static void cleanup_env_and_db(DB_ENV * env, DB * db)
r = env->close(env, 0); { int chk_r = r; CKERR(chk_r); } r = env->close(env, 0); { int chk_r = r; CKERR(chk_r); }
} }
static void check_dbt_matches(DB *db, int expect_r, int key, DBT *kdbt) { static int get_last_key_cb(const DBT *key, const DBT *value, void *extra) {
int r = db->get_last_key(db, kdbt, 0); if (key->data) {
CKERR2(r, expect_r); invariant(value == NULL);
int expected_key = *(int*)extra;
if (r==0) { int found_key = *(int*)key->data;
invariant(kdbt->size == sizeof(int)); invariant(expected_key == (int)ntohl(found_key));
int found_key = *(int*)kdbt->data;
invariant(key == (int)ntohl(found_key));
} }
return 0;
} }
static void check_last_key_matches(DB *db, int expect_r, int key) { static void check_dbt_matches(DB *db, int expect_r, int key) {
DBT kdbt; int r = db->get_last_key(db, get_last_key_cb, &key);
CKERR2(r, expect_r);
dbt_init(&kdbt, nullptr, 0); }
check_dbt_matches(db, expect_r, key, &kdbt);
dbt_init_malloc(&kdbt);
check_dbt_matches(db, expect_r, key, &kdbt);
if (kdbt.data) {
toku_free(kdbt.data);
}
dbt_init_realloc(&kdbt); static void check_last_key_matches(DB *db, int expect_r, int key) {
check_dbt_matches(db, expect_r, key, &kdbt); check_dbt_matches(db, expect_r, key);
if (kdbt.data) { check_dbt_matches(db, expect_r, key);
toku_free(kdbt.data); check_dbt_matches(db, expect_r, key);
}
} }
static void do_test(size_t ct_size, int num_keys) static void do_test(size_t ct_size, int num_keys)
......
...@@ -945,30 +945,32 @@ locked_db_optimize(DB *db) { ...@@ -945,30 +945,32 @@ locked_db_optimize(DB *db) {
struct last_key_extra { struct last_key_extra {
DBT * const key_dbt; YDB_CALLBACK_FUNCTION func;
DB * db; void* extra;
}; };
static int static int
db_get_last_key_callback(ITEMLEN keylen, bytevec key, ITEMLEN vallen UU(), bytevec val UU(), void *extra, bool lock_only) { db_get_last_key_callback(ITEMLEN keylen, bytevec key, ITEMLEN vallen UU(), bytevec val UU(), void *extra, bool lock_only) {
if (!lock_only) { if (!lock_only) {
DBT keydbt;
toku_fill_dbt(&keydbt, key, keylen);
struct last_key_extra * CAST_FROM_VOIDP(info, extra); struct last_key_extra * CAST_FROM_VOIDP(info, extra);
toku_dbt_set(keylen, key, info->key_dbt, &info->db->i->skey); info->func(&keydbt, NULL, info->extra);
} }
return 0; return 0;
} }
static int static int
toku_db_get_last_key(DB * db, DB_TXN *txn, DBT * key, uint32_t flags UU()) { toku_db_get_last_key(DB * db, DB_TXN *txn, YDB_CALLBACK_FUNCTION func, void* extra) {
int r; int r;
LE_CURSOR cursor = nullptr; LE_CURSOR cursor = nullptr;
struct last_key_extra extra = { .key_dbt = key, .db = db }; struct last_key_extra last_extra = { .func = func, .extra = extra };
r = toku_le_cursor_create(&cursor, db->i->ft_handle, db_txn_struct_i(txn)->tokutxn); r = toku_le_cursor_create(&cursor, db->i->ft_handle, db_txn_struct_i(txn)->tokutxn);
if (r != 0) { goto cleanup; } if (r != 0) { goto cleanup; }
// Goes in reverse order. First key returned is last in dictionary. // Goes in reverse order. First key returned is last in dictionary.
r = toku_le_cursor_next(cursor, db_get_last_key_callback, &extra); r = toku_le_cursor_next(cursor, db_get_last_key_callback, &last_extra);
if (r != 0) { goto cleanup; } if (r != 0) { goto cleanup; }
cleanup: cleanup:
...@@ -979,14 +981,14 @@ toku_db_get_last_key(DB * db, DB_TXN *txn, DBT * key, uint32_t flags UU()) { ...@@ -979,14 +981,14 @@ toku_db_get_last_key(DB * db, DB_TXN *txn, DBT * key, uint32_t flags UU()) {
} }
static int static int
autotxn_db_get_last_key(DB* db, DBT* key, uint32_t flags) { autotxn_db_get_last_key(DB* db, YDB_CALLBACK_FUNCTION func, void* extra) {
bool changed; int r; bool changed; int r;
DB_TXN *txn = nullptr; DB_TXN *txn = nullptr;
// Cursors inside require transactions, but this is _not_ a transactional function. // Cursors inside require transactions, but this is _not_ a transactional function.
// Create transaction in a wrapper and then later close it. // Create transaction in a wrapper and then later close it.
r = toku_db_construct_autotxn(db, &txn, &changed, false); r = toku_db_construct_autotxn(db, &txn, &changed, false);
if (r!=0) return r; if (r!=0) return r;
r = toku_db_get_last_key(db, txn, key, flags); r = toku_db_get_last_key(db, txn, func, extra);
return toku_db_destruct_autotxn(txn, r, changed); return toku_db_destruct_autotxn(txn, r, changed);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment