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