Commit cca6a235 authored by John Esmet's avatar John Esmet

FT-273 Use a comparator in the locktree instead of a

descriptor/ft_compare_func pair
parent 5ec7bdee
......@@ -115,6 +115,24 @@ namespace toku {
_builtin = _cmp == &toku_builtin_compare_fun;
}
// inherit the attributes of another comparator, but keep our own
// copy of fake_db that is owned separately from the one given.
void inherit(const comparator &cmp) {
invariant_notnull(_fake_db);
invariant_notnull(cmp._cmp);
invariant_notnull(cmp._fake_db);
_cmp = cmp._cmp;
_fake_db->cmp_descriptor = cmp._fake_db->cmp_descriptor;
_builtin = cmp._builtin;
}
// like inherit, but doesn't require that the this comparator
// was already created
void create_from(const comparator &cmp) {
XCALLOC(_fake_db);
inherit(cmp);
}
void destroy() {
toku_free(_fake_db);
}
......@@ -127,10 +145,6 @@ namespace toku {
return _cmp;
}
void set_descriptor(DESCRIPTOR desc) {
_fake_db->cmp_descriptor = desc;
}
bool valid() const {
return _cmp != nullptr;
}
......
......@@ -3255,8 +3255,9 @@ void toku_ft_set_update(FT_HANDLE ft_handle, ft_update_func update_fun) {
ft_handle->options.update_fun = update_fun;
}
ft_compare_func toku_ft_get_bt_compare (FT_HANDLE ft_handle) {
return ft_handle->options.compare_fun;
const toku::comparator &toku_ft_get_comparator(FT_HANDLE ft_handle) {
invariant_notnull(ft_handle->ft);
return ft_handle->ft->cmp;
}
static void
......
......@@ -125,8 +125,8 @@ void toku_ft_handle_get_compression_method(FT_HANDLE, enum toku_compression_meth
void toku_ft_handle_set_fanout(FT_HANDLE, unsigned int fanout);
void toku_ft_handle_get_fanout(FT_HANDLE, unsigned int *fanout);
void toku_ft_set_bt_compare(FT_HANDLE, ft_compare_func);
ft_compare_func toku_ft_get_bt_compare (FT_HANDLE ft_h);
void toku_ft_set_bt_compare(FT_HANDLE ft_handle, ft_compare_func cmp_func);
const toku::comparator &toku_ft_get_comparator(FT_HANDLE ft_handle);
void toku_ft_set_redirect_callback(FT_HANDLE ft_h, on_redirect_callback redir_cb, void* extra);
......
......@@ -116,11 +116,23 @@ static void test_desc(void) {
invariant(c == MAGIC);
// set desc to d2, make sure it gets used
cmp.set_descriptor(&d2);
toku::comparator cmp2;
cmp2.create(magic_compare, &d2);
cmp.inherit(cmp2);
expected_desc = &d2;
c = cmp(&dbt_a, &dbt_b);
invariant(c == MAGIC);
// go back to using d1, but using the create_from API
toku::comparator cmp3, cmp4;
cmp3.create(magic_compare, &d1); // cmp3 has d1
cmp4.create_from(cmp3); // cmp4 should get d1 from cmp3
expected_desc = &d1;
c = cmp3(&dbt_a, &dbt_b);
invariant(c == MAGIC);
c = cmp4(&dbt_a, &dbt_b);
invariant(c == MAGIC);
cmp.destroy();
}
......
......@@ -116,12 +116,11 @@ namespace toku {
// but does nothing based on the value of the reference count - it is
// up to the user of the locktree to destroy it when it sees fit.
void locktree::create(locktree_manager *mgr, DICTIONARY_ID dict_id,
DESCRIPTOR desc, ft_compare_func cmp) {
void locktree::create(locktree_manager *mgr, DICTIONARY_ID dict_id, const comparator &cmp) {
m_mgr = mgr;
m_dict_id = dict_id;
m_cmp.create(cmp, desc);
m_cmp.create_from(cmp);
m_reference_count = 1;
m_userdata = nullptr;
......@@ -791,8 +790,8 @@ struct lt_lock_request_info *locktree::get_lock_request_info(void) {
return &m_lock_request_info;
}
void locktree::set_descriptor(DESCRIPTOR desc) {
m_cmp.set_descriptor(desc);
void locktree::set_comparator(const comparator &cmp) {
m_cmp.inherit(cmp);
}
locktree_manager *locktree::get_manager(void) const {
......
......@@ -183,10 +183,10 @@ namespace toku {
// effect: Get a locktree from the manager. If a locktree exists with the given
// dict_id, it is referenced and then returned. If one did not exist, it
// is created. It will use the given descriptor and comparison function
// for comparing keys, and the on_create callback passed to locktree_manager::create()
// will be called with the given extra parameter.
locktree *get_lt(DICTIONARY_ID dict_id, DESCRIPTOR desc, ft_compare_func cmp, void *on_create_extra);
// is created. It will use the comparator for comparing keys. The on_create
// callback (passed to locktree_manager::create()) will be called with the
// given extra parameter.
locktree *get_lt(DICTIONARY_ID dict_id, const comparator &cmp, void *on_create_extra);
void reference_lt(locktree *lt);
......@@ -307,8 +307,7 @@ namespace toku {
// A locktree represents the set of row locks owned by all transactions
// over an open dictionary. Read and write ranges are represented as
// a left and right key which are compared with the given descriptor
// and comparison fn.
// a left and right key which are compared with the given comparator
//
// Locktrees are not created and destroyed by the user. Instead, they are
// referenced and released using the locktree manager.
......@@ -324,8 +323,7 @@ namespace toku {
class locktree {
public:
// effect: Creates a locktree
void create(locktree_manager *mgr, DICTIONARY_ID dict_id,
DESCRIPTOR desc, ft_compare_func cmp);
void create(locktree_manager *mgr, DICTIONARY_ID dict_id, const comparator &cmp);
void destroy(void);
......@@ -371,7 +369,7 @@ namespace toku {
locktree_manager *get_manager(void) const;
void set_descriptor(DESCRIPTOR desc);
void set_comparator(const comparator &cmp);
int compare(const locktree *lt) const;
......@@ -389,15 +387,13 @@ namespace toku {
DICTIONARY_ID m_dict_id;
uint32_t m_reference_count;
// use a comparator object that encapsulates an ft compare
// function and a descriptor in a fake db. this way we can
// pass it around for easy key comparisons.
// Since the memory referenced by this comparator is not owned by the
// locktree, the user must guarantee it will outlive the locktree.
//
// since this comparator will store a pointer to a descriptor,
// the user of the locktree needs to make sure that the descriptor
// is valid for as long as the locktree. this is currently
// implemented by opening an ft_handle for this locktree and
// storing it as userdata below.
// The ydb API accomplishes this by opening an ft_handle in the on_create
// callback, which will keep the underlying FT (and its descriptor) in memory
// for as long as the handle is open. The ft_handle is stored opaquely in the
// userdata pointer below. see locktree_manager::get_lt w/ on_create_extra
comparator m_cmp;
concurrent_tree *m_rangetree;
......
......@@ -183,8 +183,8 @@ void locktree_manager::locktree_map_remove(locktree *lt) {
invariant_zero(r);
}
locktree *locktree_manager::get_lt(DICTIONARY_ID dict_id, DESCRIPTOR desc,
ft_compare_func cmp, void *on_create_extra) {
locktree *locktree_manager::get_lt(DICTIONARY_ID dict_id,
const comparator &cmp, void *on_create_extra) {
// hold the mutex around searching and maybe
// inserting into the locktree map
......@@ -193,7 +193,7 @@ locktree *locktree_manager::get_lt(DICTIONARY_ID dict_id, DESCRIPTOR desc,
locktree *lt = locktree_map_find(dict_id);
if (lt == nullptr) {
XCALLOC(lt);
lt->create(this, dict_id, desc, cmp);
lt->create(this, dict_id, cmp);
// new locktree created - call the on_create callback
// and put it in the locktree map
......
......@@ -120,7 +120,7 @@ void lock_request_unit_test::test_wait_time_callback(void) {
locktree lt;
DICTIONARY_ID dict_id = { 1 };
lt.create(nullptr, dict_id, nullptr, compare_dbts);
lt.create(nullptr, dict_id, dbt_comparator);
TXNID txnid_a = 1001;
lock_request request_a;
......
......@@ -117,7 +117,7 @@ void lock_request_unit_test::test_wait_time_callback(void) {
locktree lt;
DICTIONARY_ID dict_id = { 1 };
lt.create(nullptr, dict_id, nullptr, compare_dbts);
lt.create(nullptr, dict_id, dbt_comparator);
TXNID txnid_a = 1001;
lock_request request_a;
......
......@@ -102,7 +102,7 @@ void lock_request_unit_test::test_start_deadlock(void) {
const uint64_t lock_wait_time = 10;
DICTIONARY_ID dict_id = { 1 };
lt.create(nullptr, dict_id, nullptr, compare_dbts);
lt.create(nullptr, dict_id, dbt_comparator);
TXNID txnid_a = 1001;
TXNID txnid_b = 2001;
......
......@@ -101,7 +101,7 @@ void lock_request_unit_test::test_start_pending(void) {
lock_request request;
DICTIONARY_ID dict_id = { 1 };
lt.create(nullptr, dict_id, nullptr, compare_dbts);
lt.create(nullptr, dict_id, dbt_comparator);
TXNID txnid_a = 1001;
TXNID txnid_b = 2001;
......
......@@ -101,7 +101,7 @@ void lock_request_unit_test::test_wait_time_callback(void) {
locktree lt;
DICTIONARY_ID dict_id = { 1 };
lt.create(nullptr, dict_id, nullptr, compare_dbts);
lt.create(nullptr, dict_id, dbt_comparator);
TXNID txnid_a = 1001;
lock_request request_a;
......
......@@ -108,7 +108,7 @@ void locktree_unit_test::test_conflicts(void) {
locktree lt;
DICTIONARY_ID dict_id = { 1 };
lt.create(nullptr, dict_id, nullptr, compare_dbts);
lt.create(nullptr, dict_id, dbt_comparator);
int r;
TXNID txnid_a = 1001;
......
......@@ -98,7 +98,7 @@ void locktree_unit_test::test_create_destroy(void) {
locktree lt;
DICTIONARY_ID dict_id = { 1 };
lt.create(nullptr, dict_id, nullptr, compare_dbts);
lt.create(nullptr, dict_id, dbt_comparator);
lt_lock_request_info *info = lt.get_lock_request_info();
invariant_notnull(info);
......
......@@ -247,11 +247,11 @@ int main(int argc, const char *argv[]) {
locktree *big_lt[n_big];
for (int i = 0; i < n_big; i++) {
dict_id = { next_dict_id }; next_dict_id++;
big_lt[i] = mgr.get_lt(dict_id, nullptr, compare_dbts, nullptr);
big_lt[i] = mgr.get_lt(dict_id, dbt_comparator, nullptr);
}
dict_id = { next_dict_id }; next_dict_id++;
locktree *small_lt = mgr.get_lt(dict_id, nullptr, compare_dbts, nullptr);
locktree *small_lt = mgr.get_lt(dict_id, dbt_comparator, nullptr);
// create the worker threads
struct big_arg big_arg = { &mgr, big_lt, n_big, 1000 };
......
......@@ -210,13 +210,10 @@ int main(int argc, const char *argv[]) {
mgr.set_max_lock_memory(max_lock_memory);
// create lock trees
DESCRIPTOR desc[n_lt];
DICTIONARY_ID dict_id[n_lt];
locktree *lt[n_big];
for (int i = 0; i < n_lt; i++) {
desc[i] = nullptr;
dict_id[i] = { (uint64_t)i };
lt[i] = mgr.get_lt(dict_id[i], desc[i], compare_dbts, nullptr);
DICTIONARY_ID dict_id = { .dictid = (uint64_t) i };
lt[i] = mgr.get_lt(dict_id, dbt_comparator, nullptr);
assert(lt[i]);
}
......
......@@ -210,13 +210,10 @@ int main(int argc, const char *argv[]) {
mgr.set_max_lock_memory(max_lock_memory);
// create lock trees
DESCRIPTOR desc[n_lt];
DICTIONARY_ID dict_id[n_lt];
locktree *lt[n_big];
for (int i = 0; i < n_lt; i++) {
desc[i] = nullptr;
dict_id[i] = { (uint64_t)i };
lt[i] = mgr.get_lt(dict_id[i], desc[i], compare_dbts, nullptr);
DICTIONARY_ID dict_id = { .dictid = (uint64_t)i };
lt[i] = mgr.get_lt(dict_id, dbt_comparator, nullptr);
assert(lt[i]);
}
......
......@@ -167,9 +167,8 @@ int main(int argc, const char *argv[]) {
const TXNID txn_b = 100;
// create lock trees
DESCRIPTOR desc = nullptr;
DICTIONARY_ID dict_id = { 1 };
locktree *lt = mgr.get_lt(dict_id, desc, compare_dbts, nullptr);
DICTIONARY_ID dict_id = { .dictid = 1 };
locktree *lt = mgr.get_lt(dict_id, dbt_comparator, nullptr);
int64_t last_i = -1;
for (int64_t i = 0; ; i++) {
......
......@@ -228,13 +228,11 @@ int main(int argc, const char *argv[]) {
mgr.set_max_lock_memory(max_lock_memory);
// create lock trees
DESCRIPTOR desc_0 = nullptr;
DICTIONARY_ID dict_id_0 = { 1 };
locktree *lt_0 = mgr.get_lt(dict_id_0, desc_0, compare_dbts, nullptr);
DICTIONARY_ID dict_id_0 = { .dictid = 1 };
locktree *lt_0 = mgr.get_lt(dict_id_0, dbt_comparator, nullptr);
DESCRIPTOR desc_1 = nullptr;
DICTIONARY_ID dict_id_1 = { 2 };
locktree *lt_1 = mgr.get_lt(dict_id_1, desc_1, compare_dbts, nullptr);
DICTIONARY_ID dict_id_1 = { .dictid = 2 };
locktree *lt_1 = mgr.get_lt(dict_id_1, dbt_comparator, nullptr);
// create the worker threads
struct arg big_arg = { &mgr, lt_0, 1000 };
......
......@@ -98,7 +98,7 @@ void locktree_unit_test::test_infinity(void) {
locktree lt;
DICTIONARY_ID dict_id = { 1 };
lt.create(nullptr, dict_id, nullptr, compare_dbts);
lt.create(nullptr, dict_id, dbt_comparator);
int r;
TXNID txnid_a = 1001;
......
......@@ -109,7 +109,9 @@ static int my_compare_dbts(DB *db, const DBT *a, const DBT *b) {
void locktree_unit_test::test_misc(void) {
locktree lt;
DICTIONARY_ID dict_id = { 1 };
lt.create(nullptr, dict_id, nullptr, my_compare_dbts);
toku::comparator my_dbt_comparator;
my_dbt_comparator.create(my_compare_dbts, nullptr);
lt.create(nullptr, dict_id, my_dbt_comparator);
invariant(lt.get_userdata() == nullptr);
int userdata;
......@@ -124,19 +126,27 @@ void locktree_unit_test::test_misc(void) {
expected_a = &dbt_a;
expected_b = &dbt_b;
toku::comparator cmp_d1, cmp_d2;
cmp_d1.create(my_compare_dbts, &d1);
cmp_d2.create(my_compare_dbts, &d2);
// make sure the comparator object has the correct
// descriptor when we set the locktree's descriptor
lt.set_descriptor(&d1);
lt.set_comparator(cmp_d1);
expected_descriptor = &d1;
r = lt.m_cmp(&dbt_a, &dbt_b);
invariant(r == expected_comparison_magic);
lt.set_descriptor(&d2);
lt.set_comparator(cmp_d2);
expected_descriptor = &d2;
r = lt.m_cmp(&dbt_a, &dbt_b);
invariant(r == expected_comparison_magic);
lt.release_reference();
lt.destroy();
cmp_d1.destroy();
cmp_d2.destroy();
my_dbt_comparator.destroy();
}
} /* namespace toku */
......
......@@ -101,7 +101,7 @@ void locktree_unit_test::test_overlapping_relock(void) {
locktree lt;
DICTIONARY_ID dict_id = { 1 };
lt.create(nullptr, dict_id, nullptr, compare_dbts);
lt.create(nullptr, dict_id, dbt_comparator);
const DBT *zero = get_dbt(0);
const DBT *one = get_dbt(1);
......
......@@ -98,8 +98,8 @@ void locktree_unit_test::test_simple_lock(void) {
locktree_manager mgr;
mgr.create(nullptr, nullptr, nullptr, nullptr);
DICTIONARY_ID dict_id = { 1 };
locktree *lt = mgr.get_lt(dict_id, nullptr, compare_dbts, nullptr);
DICTIONARY_ID dict_id = { .dictid = 1 };
locktree *lt = mgr.get_lt(dict_id, dbt_comparator, nullptr);
int r;
TXNID txnid_a = 1001;
......
......@@ -101,7 +101,7 @@ void locktree_unit_test::test_single_txnid_optimization(void) {
locktree lt;
DICTIONARY_ID dict_id = { 1 };
lt.create(nullptr, dict_id, nullptr, compare_dbts);
lt.create(nullptr, dict_id, dbt_comparator);
const DBT *zero = get_dbt(0);
const DBT *one = get_dbt(1);
......
......@@ -107,9 +107,15 @@ static void destroy_cb(locktree *lt) {
(*k) = false;
}
static int my_cmp(DB *UU(db), const DBT *UU(a), const DBT *UU(b)) {
return 0;
}
void manager_unit_test::test_reference_release_lt(void) {
locktree_manager mgr;
mgr.create(create_cb, destroy_cb, nullptr, nullptr);
toku::comparator my_comparator;
my_comparator.create(my_cmp, nullptr);
DICTIONARY_ID a = { 0 };
DICTIONARY_ID b = { 1 };
......@@ -117,18 +123,12 @@ void manager_unit_test::test_reference_release_lt(void) {
bool aok = false;
bool bok = false;
bool cok = false;
int d = 5;
DESCRIPTOR_S desc_s;
desc_s.dbt.data = &d;
desc_s.dbt.size = desc_s.dbt.ulen = sizeof(d);
desc_s.dbt.flags = DB_DBT_USERMEM;
locktree *alt = mgr.get_lt(a, &desc_s, nullptr, &aok);
locktree *alt = mgr.get_lt(a, my_comparator, &aok);
invariant_notnull(alt);
locktree *blt = mgr.get_lt(b, &desc_s, nullptr, &bok);
locktree *blt = mgr.get_lt(b, my_comparator, &bok);
invariant_notnull(alt);
locktree *clt = mgr.get_lt(c, &desc_s, nullptr, &cok);
locktree *clt = mgr.get_lt(c, my_comparator, &cok);
invariant_notnull(alt);
// three distinct locktrees should have been returned
......@@ -152,9 +152,9 @@ void manager_unit_test::test_reference_release_lt(void) {
// get another handle on a and b, they shoudl be the same
// as the original alt and blt
locktree *blt2 = mgr.get_lt(b, &desc_s, nullptr, &bok);
locktree *blt2 = mgr.get_lt(b, my_comparator, &bok);
invariant(blt2 == blt);
locktree *alt2 = mgr.get_lt(a, &desc_s, nullptr, &aok);
locktree *alt2 = mgr.get_lt(a, my_comparator, &aok);
invariant(alt2 == alt);
// remove one ref from everything. c should die. a and b are ok.
......@@ -171,6 +171,7 @@ void manager_unit_test::test_reference_release_lt(void) {
invariant(!aok);
invariant(!bok);
my_comparator.destroy();
mgr.destroy();
}
......
......@@ -120,9 +120,8 @@ void manager_unit_test::test_status(void) {
assert_status(&status, "LTM_WAIT_COUNT", 0);
assert_status(&status, "LTM_TIMEOUT_COUNT", 0);
DESCRIPTOR desc = nullptr;
DICTIONARY_ID dict_id = { 1 };
locktree *lt = mgr.get_lt(dict_id, desc, compare_dbts, nullptr);
DICTIONARY_ID dict_id = { .dictid = 1 };
locktree *lt = mgr.get_lt(dict_id, dbt_comparator, nullptr);
int r;
TXNID txnid_a = 1001;
TXNID txnid_b = 2001;
......
......@@ -91,71 +91,85 @@ PATENT RIGHTS GRANT:
#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
#include <ft/ybt.h>
#include <limits.h>
#include "ft/comparator.h"
#include "ft/ybt.h"
namespace toku {
__attribute__((__unused__))
static DBT min_dbt(void) {
static int64_t min = INT_MIN;
DBT dbt;
toku_fill_dbt(&dbt, &min, sizeof(int64_t));
dbt.flags = DB_DBT_USERMEM;
return dbt;
}
__attribute__((__unused__))
static DBT max_dbt(void) {
static int64_t max = INT_MAX;
DBT dbt;
toku_fill_dbt(&dbt, &max, sizeof(int64_t));
dbt.flags = DB_DBT_USERMEM;
return dbt;
}
__attribute__((__unused__))
static const DBT *get_dbt(int64_t key) {
static const int NUM_DBTS = 1000;
static bool initialized;
static int64_t static_ints[NUM_DBTS];
static DBT static_dbts[NUM_DBTS];
invariant(key < NUM_DBTS);
if (!initialized) {
for (int i = 0; i < NUM_DBTS; i++) {
static_ints[i] = i;
toku_fill_dbt(&static_dbts[i],
&static_ints[i],
sizeof(int64_t));
static_dbts[i].flags = DB_DBT_USERMEM;
__attribute__((__unused__))
static DBT min_dbt(void) {
static int64_t min = INT_MIN;
DBT dbt;
toku_fill_dbt(&dbt, &min, sizeof(int64_t));
dbt.flags = DB_DBT_USERMEM;
return dbt;
}
__attribute__((__unused__))
static DBT max_dbt(void) {
static int64_t max = INT_MAX;
DBT dbt;
toku_fill_dbt(&dbt, &max, sizeof(int64_t));
dbt.flags = DB_DBT_USERMEM;
return dbt;
}
__attribute__((__unused__))
static const DBT *get_dbt(int64_t key) {
static const int NUM_DBTS = 1000;
static bool initialized;
static int64_t static_ints[NUM_DBTS];
static DBT static_dbts[NUM_DBTS];
invariant(key < NUM_DBTS);
if (!initialized) {
for (int i = 0; i < NUM_DBTS; i++) {
static_ints[i] = i;
toku_fill_dbt(&static_dbts[i],
&static_ints[i],
sizeof(int64_t));
static_dbts[i].flags = DB_DBT_USERMEM;
}
initialized = true;
}
initialized = true;
invariant(key < NUM_DBTS);
return &static_dbts[key];
}
invariant(key < NUM_DBTS);
return &static_dbts[key];
}
__attribute__((__unused__))
static int compare_dbts(DB *db, const DBT *key1, const DBT *key2) {
(void) db;
// this emulates what a "infinity-aware" comparator object does
if (toku_dbt_is_infinite(key1) || toku_dbt_is_infinite(key2)) {
return toku_dbt_infinite_compare(key1, key2);
} else {
invariant(key1->size == sizeof(int64_t));
invariant(key2->size == sizeof(int64_t));
int64_t a = *(int64_t*) key1->data;
int64_t b = *(int64_t*) key2->data;
if (a < b) {
return -1;
} else if (a == b) {
return 0;
__attribute__((__unused__))
static int compare_dbts(DB *db, const DBT *key1, const DBT *key2) {
(void) db;
// this emulates what a "infinity-aware" comparator object does
if (toku_dbt_is_infinite(key1) || toku_dbt_is_infinite(key2)) {
return toku_dbt_infinite_compare(key1, key2);
} else {
return 1;
invariant(key1->size == sizeof(int64_t));
invariant(key2->size == sizeof(int64_t));
int64_t a = *(int64_t*) key1->data;
int64_t b = *(int64_t*) key2->data;
if (a < b) {
return -1;
} else if (a == b) {
return 0;
} else {
return 1;
}
}
}
}
__attribute__((__unused__)) comparator dbt_comparator;
__attribute__((__constructor__))
static void construct_dbt_comparator(void) {
dbt_comparator.create(compare_dbts, nullptr);
}
__attribute__((__destructor__))
static void destruct_dbt_comparator(void) {
dbt_comparator.destroy();
}
} /* namespace toku */
......@@ -233,32 +233,25 @@ toku_indexer_unlock(DB_INDEXER* indexer) {
// after grabbing the indexer lock
bool
toku_indexer_may_insert(DB_INDEXER* indexer, const DBT* key) {
bool retval = false;
bool may_insert = false;
toku_mutex_lock(&indexer->i->indexer_estimate_lock);
// if we have no position estimate, we can't tell, so return false
if (indexer->i->position_estimate.data == NULL) {
retval = false;
}
else {
FT_HANDLE ft_handle = indexer->i->src_db->i->ft_handle;
ft_compare_func keycompare = toku_ft_get_bt_compare(ft_handle);
int r = keycompare(
indexer->i->src_db,
&indexer->i->position_estimate,
key
);
if (indexer->i->position_estimate.data == nullptr) {
may_insert = false;
} else {
DB *db = indexer->i->src_db;
const toku::comparator &cmp = toku_ft_get_comparator(db->i->ft_handle);
int c = cmp(&indexer->i->position_estimate, key);
// if key > position_estimate, then we know the indexer cursor
// is past key, and we can safely say that associated values of
// key must be inserted into the indexer's db
if (r < 0) {
retval = true;
}
else {
retval = false;
}
may_insert = c < 0;
}
toku_mutex_unlock(&indexer->i->indexer_estimate_lock);
return retval;
return may_insert;
}
void
......
......@@ -96,6 +96,7 @@ PATENT RIGHTS GRANT:
#include <ft/cachetable.h>
#include <ft/cursor.h>
#include <ft/comparator.h>
#include <ft/fttypes.h>
#include <ft/logger.h>
#include <ft/txn.h>
......
......@@ -390,10 +390,12 @@ toku_db_open(DB * db, DB_TXN * txn, const char *fname, const char *dbname, DBTYP
// locktree's descriptor pointer if necessary
static void
db_set_descriptors(DB *db, FT_HANDLE ft_handle) {
const toku::comparator &cmp = toku_ft_get_comparator(ft_handle);
db->descriptor = toku_ft_get_descriptor(ft_handle);
db->cmp_descriptor = toku_ft_get_cmp_descriptor(ft_handle);
invariant(db->cmp_descriptor == cmp.get_descriptor());
if (db->i->lt) {
db->i->lt->set_descriptor(db->cmp_descriptor);
db->i->lt->set_comparator(cmp);
}
}
......@@ -476,7 +478,7 @@ toku_db_open_iname(DB * db, DB_TXN * txn, const char *iname_in_env, uint32_t fla
db->dbenv->i->cachetable,
txn ? db_txn_struct_i(txn)->tokutxn : nullptr);
if (r != 0) {
goto error_cleanup;
goto out;
}
// if the dictionary was opened as a blackhole, mark the
......@@ -497,26 +499,27 @@ toku_db_open_iname(DB * db, DB_TXN * txn, const char *iname_in_env, uint32_t fla
.txn = txn,
.ft_handle = db->i->ft_handle,
};
db->i->lt = db->dbenv->i->ltm.get_lt(
db->i->dict_id,
db->cmp_descriptor,
toku_ft_get_bt_compare(db->i->ft_handle),
&on_create_extra);
db->i->lt = db->dbenv->i->ltm.get_lt(db->i->dict_id,
toku_ft_get_comparator(db->i->ft_handle),
&on_create_extra);
if (db->i->lt == nullptr) {
r = errno;
if (r == 0)
if (r == 0) {
r = EINVAL;
goto error_cleanup;
}
goto out;
}
}
return 0;
r = 0;
error_cleanup:
db->i->dict_id = DICTIONARY_ID_NONE;
db->i->opened = 0;
if (db->i->lt) {
db->dbenv->i->ltm.release_lt(db->i->lt);
db->i->lt = NULL;
out:
if (r != 0) {
db->i->dict_id = DICTIONARY_ID_NONE;
db->i->opened = 0;
if (db->i->lt) {
db->dbenv->i->ltm.release_lt(db->i->lt);
db->i->lt = nullptr;
}
}
return r;
}
......
......@@ -127,9 +127,8 @@ static inline int db_opened(DB *db) {
return db->i->opened != 0;
}
static inline ft_compare_func
toku_db_get_compare_fun(DB* db) {
return toku_ft_get_bt_compare(db->i->ft_handle);
static inline const toku::comparator &toku_db_get_comparator(DB *db) {
return toku_ft_get_comparator(db->i->ft_handle);
}
int toku_db_pre_acquire_fileops_lock(DB *db, DB_TXN *txn);
......
......@@ -951,8 +951,8 @@ env_update_multiple(DB_ENV *env, DB *src_db, DB_TXN *txn,
} else if (idx_old == old_keys.size) {
cmp = +1;
} else {
ft_compare_func cmpfun = toku_db_get_compare_fun(db);
cmp = cmpfun(db, curr_old_key, curr_new_key);
const toku::comparator &cmpfn = toku_db_get_comparator(db);
cmp = cmpfn(curr_old_key, curr_new_key);
}
bool do_del = false;
......
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