From ed139c85a61e021e4a4b311017dcf4786bd113d2 Mon Sep 17 00:00:00 2001
From: Rich Prohaska <prohaska@tokutek.com>
Date: Wed, 17 Apr 2013 00:00:12 -0400
Subject: [PATCH] #4572 fix the lock tree to handle txn unlocks after db closes
 refs[t:4572]

git-svn-id: file:///svn/toku/tokudb@40356 c7de825b-a66e-492c-adef-691d508d4ae1
---
 src/lock_tree/locktree.c                      | 45 +++++-----
 src/lock_tree/tests/bench_point_write_locks.c |  7 +-
 .../tests/stress_point_write_locks.c          |  8 +-
 src/lock_tree/tests/test_00020_read.c         |  6 +-
 src/lock_tree/tests/test_00040_write.c        |  7 +-
 src/lock_tree/tests/test_borderwrite_merge.c  |  6 +-
 .../tests/test_conflict_read_table_write.c    | 12 +--
 .../tests/test_conflict_read_write.c          | 12 +--
 .../tests/test_conflict_write_read.c          | 10 ++-
 .../tests/test_conflict_write_table_read.c    | 10 ++-
 .../tests/test_conflict_write_write.c         | 10 ++-
 .../tests/test_default_lock_timeout.c         |  6 +-
 .../tests/test_footprint_point_write.c        |  7 +-
 .../tests/test_footprint_range_write.c        |  7 +-
 src/lock_tree/tests/test_global_write_lock.c  |  6 +-
 src/lock_tree/tests/test_lock_timeout.c       |  6 +-
 src/lock_tree/tests/test_ltm_get_status.c     | 84 +------------------
 src/lock_tree/tests/test_read_notgranted.c    |  6 +-
 src/lock_tree/tests/test_read_out_of_locks.c  | 12 +--
 .../tests/test_read_request_blocked.c         | 12 +--
 src/lock_tree/tests/test_simple_deadlock.c    | 14 ++--
 src/lock_tree/tests/test_unlock_after_close.c | 63 ++++++++++++++
 src/lock_tree/tests/test_update_deadlock.c    | 14 ++--
 .../tests/test_update_deadlock_copy_keys.c    | 14 ++--
 .../tests/test_write_conflict_with_threads.c  |  6 +-
 src/lock_tree/tests/test_write_notgranted.c   |  6 +-
 src/lock_tree/tests/test_write_range.c        |  6 +-
 .../tests/test_write_range_conflict_read.c    |  6 +-
 .../tests/test_write_range_conflict_write.c   |  6 +-
 .../tests/test_write_request_blocked.c        | 10 ++-
 src/lock_tree/tests/test_wrw.c                | 12 +--
 31 files changed, 235 insertions(+), 201 deletions(-)
 create mode 100644 src/lock_tree/tests/test_unlock_after_close.c

diff --git a/src/lock_tree/locktree.c b/src/lock_tree/locktree.c
index c4be3d9cf9..3ca9d9b5ea 100644
--- a/src/lock_tree/locktree.c
+++ b/src/lock_tree/locktree.c
@@ -577,8 +577,7 @@ lt_borderwrite_conflict(toku_lock_tree* tree, TXNID self,
                         toku_interval* query,
                         toku_conflict* conflict, TXNID* peer) {
     assert(tree && query && conflict && peer);
-    toku_range_tree* rt = tree->borderwrite;
-    assert(rt);
+    assert(tree->borderwrite);
 
     const uint32_t query_size = 2;
     toku_range   buffer[query_size];
@@ -587,7 +586,7 @@ lt_borderwrite_conflict(toku_lock_tree* tree, TXNID self,
     uint32_t     numfound;
     int          r;
 
-    r = toku_rt_find(rt, query, query_size, &buf, &buflen, &numfound);
+    r = toku_rt_find(tree->borderwrite, query, query_size, &buf, &buflen, &numfound);
     if (r != 0) 
         return r;
     assert(numfound <= query_size);
@@ -1177,13 +1176,12 @@ lt_get_border_in_borderwrite(toku_lock_tree* tree,
                              toku_range* to_insert) {
     assert(tree && pred && succ && found_p && found_s);                                    
     int r;
-    toku_range_tree* rt = tree->borderwrite;
-    if (!rt)  
+    if (!tree->borderwrite)  
         return lt_panic(tree, TOKU_LT_INCONSISTENT);
-    r = toku_rt_predecessor(rt, to_insert->ends.left,  pred, found_p);
+    r = toku_rt_predecessor(tree->borderwrite, to_insert->ends.left,  pred, found_p);
     if (r != 0) 
         return r;
-    r = toku_rt_successor  (rt, to_insert->ends.right, succ, found_s);
+    r = toku_rt_successor  (tree->borderwrite, to_insert->ends.right, succ, found_s);
     if (r != 0) 
         return r;
     return 0;
@@ -1244,14 +1242,14 @@ lt_split_border(toku_lock_tree* tree, toku_range* to_insert,
 static inline int 
 lt_borderwrite_insert(toku_lock_tree* tree, toku_interval* query, toku_range* to_insert) {
     assert(tree && query && to_insert);
+    assert(tree->borderwrite);
+
     int r;
-    toku_range_tree* borderwrite = tree->borderwrite;   
-    assert(borderwrite);
 
     // find all overlapping ranges.  there can be 0 or 1.
     const uint32_t query_size = 1;
     uint32_t numfound;
-    r = toku_rt_find(borderwrite, query, query_size, &tree->bw_buf, &tree->bw_buflen, &numfound);
+    r = toku_rt_find(tree->borderwrite, query, query_size, &tree->bw_buf, &tree->bw_buflen, &numfound);
     if (r != 0) 
         return lt_panic(tree, r);
     assert(numfound <= query_size);
@@ -1270,7 +1268,7 @@ lt_borderwrite_insert(toku_lock_tree* tree, toku_interval* query, toku_range* to
         r = lt_expand_border(tree, to_insert, &pred, &succ, found_p, found_s);
         if (r != 0) 
             return lt_panic(tree, r);
-        r = toku_rt_insert(borderwrite, to_insert);
+        r = toku_rt_insert(tree->borderwrite, to_insert);
         if (r != 0) 
             return lt_panic(tree, r);
     } else {
@@ -1284,10 +1282,10 @@ lt_borderwrite_insert(toku_lock_tree* tree, toku_interval* query, toku_range* to
                     to_insert->ends.left = tree->bw_buf[0].ends.left;
                 if (toku_lt_point_cmp(to_insert->ends.right, tree->bw_buf[0].ends.right) < 0)
                     to_insert->ends.right = tree->bw_buf[0].ends.right;
-                r = toku_rt_delete(borderwrite, &tree->bw_buf[0]);
+                r = toku_rt_delete(tree->borderwrite, &tree->bw_buf[0]);
                 if (r != 0)
                     return lt_panic(tree, r);
-                r = toku_rt_insert(borderwrite, to_insert);
+                r = toku_rt_insert(tree->borderwrite, to_insert);
                 if (r != 0)
                     return lt_panic(tree, r);
             }
@@ -1304,7 +1302,7 @@ lt_borderwrite_insert(toku_lock_tree* tree, toku_interval* query, toku_range* to
             r = lt_split_border(tree, to_insert, &pred, &succ, found_p, found_s);
             if (r != 0) 
                 return lt_panic(tree, r);
-            r = toku_rt_insert(borderwrite, to_insert);
+            r = toku_rt_insert(tree->borderwrite, to_insert);
             if (r != 0) 
                 return lt_panic(tree, r);
         }
@@ -2125,18 +2123,23 @@ lt_unlock_txn(toku_lock_tree* tree, TXNID txn) {
         uint32_t size = toku_rt_get_size(selfwrite);
         ranges += size;
 
-        DB *db = NULL;
+        // get a db from the db's associated with the lock tree and use it to update the borderwrite 
+        // if there are no db's, then assume that the db was closed before all transactions that referenced the
+        // lock tree were retired.  in this case, there is no need to update the border write since 
+        // these transactions may no longer do anything to the db since it is closed, and
+        // we expect to just close the lock tree when all of the open references to it are retired.
         if (toku_omt_size(tree->dbs) > 0) {
             OMTVALUE dbv;
             r = toku_omt_fetch(tree->dbs, 0, &dbv);
             assert_zero(r);
-            db = dbv;
+            DB *db = dbv;
+
+            lt_set_comparison_functions(tree, db);
+            r = lt_border_delete(tree, selfwrite);
+            lt_clear_comparison_functions(tree);
+            if (r != 0) 
+                return lt_panic(tree, r);
         }
-        lt_set_comparison_functions(tree, db);
-        r = lt_border_delete(tree, selfwrite);
-        lt_clear_comparison_functions(tree);
-        if (r != 0) 
-            return lt_panic(tree, r);
         r = lt_free_contents(tree, selfwrite);
         if (r != 0) 
             return lt_panic(tree, r);
diff --git a/src/lock_tree/tests/bench_point_write_locks.c b/src/lock_tree/tests/bench_point_write_locks.c
index 8814b79f4f..db4b109be7 100644
--- a/src/lock_tree/tests/bench_point_write_locks.c
+++ b/src/lock_tree/tests/bench_point_write_locks.c
@@ -41,11 +41,12 @@ int main(int argc, const char *argv[]) {
     r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
     assert(r == 0 && ltm);
 
+    DB *db_a = (DB *) 2;
+
     toku_lock_tree *lt = NULL;
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, db_a, dbcmp);
     assert(r == 0 && lt);
 
-    DB *db_a = (DB *) 2;
     TXNID txn_a = 1;
 
     // acquire the locks on keys 0 .. nrows-1
@@ -58,7 +59,7 @@ int main(int argc, const char *argv[]) {
     r = toku_lt_unlock_txn(lt, txn_a);  assert(r == 0);
 
     // shutdown 
-    r = toku_lt_close(lt); assert(r == 0);
+    toku_lt_remove_db_ref(lt, db_a);
     r = toku_ltm_close(ltm); assert(r == 0);
 
     return 0;
diff --git a/src/lock_tree/tests/stress_point_write_locks.c b/src/lock_tree/tests/stress_point_write_locks.c
index 474e1bc925..7032a5cabc 100644
--- a/src/lock_tree/tests/stress_point_write_locks.c
+++ b/src/lock_tree/tests/stress_point_write_locks.c
@@ -142,12 +142,12 @@ int main(int argc, const char *argv[]) {
     r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
     assert(r == 0 && ltm);
 
+    DB *fake_db = (DB *) 1;
+
     toku_lock_tree *lt = NULL;
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, fake_db, dbcmp);
     assert(r == 0 && lt);
 
-    DB *fake_db = (DB *) 1;
-
     toku_pthread_t tids[nthreads];
     struct test_arg args[nthreads];
     for (uint64_t i = 1; i < nthreads; i++) {
@@ -163,7 +163,7 @@ int main(int argc, const char *argv[]) {
     }
 
     // shutdown 
-    r = toku_lt_close(lt); assert(r == 0);
+    toku_lt_remove_db_ref(lt, fake_db);
     r = toku_ltm_close(ltm); assert(r == 0);
 
     return 0;
diff --git a/src/lock_tree/tests/test_00020_read.c b/src/lock_tree/tests/test_00020_read.c
index 4cc12635b1..4c3d646afe 100644
--- a/src/lock_tree/tests/test_00020_read.c
+++ b/src/lock_tree/tests/test_00020_read.c
@@ -40,12 +40,14 @@ static void init_query(void) {
     query.right = &qright;
 }
 
+static DB *fake_db = (DB *) 1;
+
 static void setup_tree(void) {
     assert(!lt && !ltm);
     r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
     CKERR(r);
     assert(ltm);
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, fake_db, dbcmp);
     CKERR(r);
     assert(lt);
     init_query();
@@ -54,7 +56,7 @@ static void setup_tree(void) {
 static void close_tree(void) {
     r = toku_lt_unlock_txn(lt, txn); CKERR(r);
     assert(lt && ltm);
-    r = toku_lt_close(lt); CKERR(r);
+    toku_lt_remove_db_ref(lt, fake_db);
     r = toku_ltm_close(ltm); CKERR(r);
     lt = NULL;
     ltm = NULL;
diff --git a/src/lock_tree/tests/test_00040_write.c b/src/lock_tree/tests/test_00040_write.c
index 1492de407f..1f878d4016 100644
--- a/src/lock_tree/tests/test_00040_write.c
+++ b/src/lock_tree/tests/test_00040_write.c
@@ -34,12 +34,14 @@ static void init_query(void) {
     query.right = &qright;
 }
 
+static DB *fake_db = (DB *) 1;
+
 static void setup_tree(void) {
     assert(!lt && !ltm);
     r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
     CKERR(r);
     assert(ltm);
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, fake_db, dbcmp);
     CKERR(r);
     assert(lt);
     init_query();
@@ -47,8 +49,7 @@ static void setup_tree(void) {
 
 static void close_tree(void) {
     assert(lt && ltm);
-    r = toku_lt_close(lt);
-        CKERR(r);
+    toku_lt_remove_db_ref(lt, fake_db);
     r = toku_ltm_close(ltm);
         CKERR(r);
     lt = NULL;
diff --git a/src/lock_tree/tests/test_borderwrite_merge.c b/src/lock_tree/tests/test_borderwrite_merge.c
index 180be5487b..d6d4b65d7e 100644
--- a/src/lock_tree/tests/test_borderwrite_merge.c
+++ b/src/lock_tree/tests/test_borderwrite_merge.c
@@ -34,12 +34,14 @@ static void init_query(void) {
     query.right = &qright;
 }
 
+static DB *fake_db = (DB *) 1;
+
 static void setup_tree(void) {
     assert(!lt && !ltm);
     r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
     CKERR(r);
     assert(ltm);
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, fake_db, dbcmp);
     CKERR(r);
     assert(lt);
     init_query();
@@ -47,7 +49,7 @@ static void setup_tree(void) {
 
 static void close_tree(void) {
     assert(lt && ltm);
-    r = toku_lt_close(lt); CKERR(r);
+    toku_lt_remove_db_ref(lt, fake_db);
     r = toku_ltm_close(ltm); CKERR(r);
     lt = NULL;
     ltm = NULL;
diff --git a/src/lock_tree/tests/test_conflict_read_table_write.c b/src/lock_tree/tests/test_conflict_read_table_write.c
index 0434792d54..191f2f44d2 100644
--- a/src/lock_tree/tests/test_conflict_read_table_write.c
+++ b/src/lock_tree/tests/test_conflict_read_table_write.c
@@ -46,8 +46,10 @@ int main(int argc, const char *argv[]) {
     r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
     assert(r == 0 && ltm);
 
+    DB *fake_db = (DB *) 1;
+
     toku_lock_tree *lt = NULL;
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, fake_db, dbcmp);
     assert(r == 0 && lt);
 
     DBT key_l; dbt_init(&key_l, "L", 1);
@@ -55,7 +57,7 @@ int main(int argc, const char *argv[]) {
     txnid_set conflicts; 
 
     const TXNID txn_a = 1;
-    toku_lock_request a_r_t; toku_lock_request_init(&a_r_t, (DB *)1, txn_a, toku_lt_neg_infinity, toku_lt_infinity, LOCK_REQUEST_READ);
+    toku_lock_request a_r_t; toku_lock_request_init(&a_r_t, fake_db, txn_a, toku_lt_neg_infinity, toku_lt_infinity, LOCK_REQUEST_READ);
     r = toku_lock_request_start(&a_r_t, lt, false); assert(r == 0); 
     assert(a_r_t.state == LOCK_REQUEST_COMPLETE && a_r_t.complete_r == 0);
     txnid_set_init(&conflicts);
@@ -66,7 +68,7 @@ int main(int argc, const char *argv[]) {
     toku_lock_request_destroy(&a_r_t);
 
     const TXNID txn_b = 2;
-    toku_lock_request b_r_l; toku_lock_request_init(&b_r_l, (DB *)1, txn_b, &key_l, &key_l, LOCK_REQUEST_READ);
+    toku_lock_request b_r_l; toku_lock_request_init(&b_r_l, fake_db, txn_b, &key_l, &key_l, LOCK_REQUEST_READ);
     r = toku_lock_request_start(&b_r_l, lt, false); assert(r == 0); 
     assert(b_r_l.state == LOCK_REQUEST_COMPLETE && b_r_l.complete_r == 0);
     txnid_set_init(&conflicts);
@@ -77,7 +79,7 @@ int main(int argc, const char *argv[]) {
     toku_lock_request_destroy(&b_r_l);
 
     const TXNID txn_c = 3;
-    toku_lock_request c_w_l; toku_lock_request_init(&c_w_l, (DB *)1, txn_c, &key_l, &key_l, LOCK_REQUEST_WRITE);
+    toku_lock_request c_w_l; toku_lock_request_init(&c_w_l, fake_db, txn_c, &key_l, &key_l, LOCK_REQUEST_WRITE);
     r = toku_lock_request_start(&c_w_l, lt, false); assert(r != 0); 
     assert(c_w_l.state == LOCK_REQUEST_PENDING);
 
@@ -105,7 +107,7 @@ int main(int argc, const char *argv[]) {
     r = toku_lt_unlock_txn(lt, txn_c); assert(r == 0);
 
     // shutdown 
-    r = toku_lt_close(lt); assert(r == 0);
+    toku_lt_remove_db_ref(lt, fake_db);
     r = toku_ltm_close(ltm); assert(r == 0);
 
     return 0;
diff --git a/src/lock_tree/tests/test_conflict_read_write.c b/src/lock_tree/tests/test_conflict_read_write.c
index f773832516..dae6738a31 100644
--- a/src/lock_tree/tests/test_conflict_read_write.c
+++ b/src/lock_tree/tests/test_conflict_read_write.c
@@ -46,8 +46,10 @@ int main(int argc, const char *argv[]) {
     r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
     assert(r == 0 && ltm);
 
+    DB *fake_db = (DB *) 1;
+
     toku_lock_tree *lt = NULL;
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, fake_db, dbcmp);
     assert(r == 0 && lt);
 
     DBT key_l; dbt_init(&key_l, "L", 1);
@@ -55,7 +57,7 @@ int main(int argc, const char *argv[]) {
     txnid_set conflicts; 
 
     const TXNID txn_a = 1;
-    toku_lock_request a_r_l; toku_lock_request_init(&a_r_l, (DB *)1, txn_a, &key_l, &key_l, LOCK_REQUEST_READ);
+    toku_lock_request a_r_l; toku_lock_request_init(&a_r_l, fake_db, txn_a, &key_l, &key_l, LOCK_REQUEST_READ);
     r = toku_lock_request_start(&a_r_l, lt, false); assert(r == 0); 
     assert(a_r_l.state == LOCK_REQUEST_COMPLETE && a_r_l.complete_r == 0);
     txnid_set_init(&conflicts);
@@ -66,7 +68,7 @@ int main(int argc, const char *argv[]) {
     toku_lock_request_destroy(&a_r_l);
 
     const TXNID txn_b = 2;
-    toku_lock_request b_r_l; toku_lock_request_init(&b_r_l, (DB *)1, txn_b, &key_l, &key_l, LOCK_REQUEST_READ);
+    toku_lock_request b_r_l; toku_lock_request_init(&b_r_l, fake_db, txn_b, &key_l, &key_l, LOCK_REQUEST_READ);
     r = toku_lock_request_start(&b_r_l, lt, false); assert(r == 0); 
     assert(b_r_l.state == LOCK_REQUEST_COMPLETE && b_r_l.complete_r == 0
 );
@@ -78,7 +80,7 @@ int main(int argc, const char *argv[]) {
     toku_lock_request_destroy(&b_r_l);
 
     const TXNID txn_c = 3;
-    toku_lock_request c_w_l; toku_lock_request_init(&c_w_l, (DB *)1, txn_c, &key_l, &key_l, LOCK_REQUEST_WRITE);
+    toku_lock_request c_w_l; toku_lock_request_init(&c_w_l, fake_db, txn_c, &key_l, &key_l, LOCK_REQUEST_WRITE);
     r = toku_lock_request_start(&c_w_l, lt, false); assert(r != 0); 
     assert(c_w_l.state == LOCK_REQUEST_PENDING);
 
@@ -106,7 +108,7 @@ int main(int argc, const char *argv[]) {
     r = toku_lt_unlock_txn(lt, txn_c); assert(r == 0);
 
     // shutdown 
-    r = toku_lt_close(lt); assert(r == 0);
+    toku_lt_remove_db_ref(lt, fake_db);
     r = toku_ltm_close(ltm); assert(r == 0);
 
     return 0;
diff --git a/src/lock_tree/tests/test_conflict_write_read.c b/src/lock_tree/tests/test_conflict_write_read.c
index a5b866f578..0dda0186f7 100644
--- a/src/lock_tree/tests/test_conflict_write_read.c
+++ b/src/lock_tree/tests/test_conflict_write_read.c
@@ -36,13 +36,15 @@ int main(int argc, const char *argv[]) {
     r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
     assert(r == 0 && ltm);
 
+    DB *fake_db = (DB *) 1;
+
     toku_lock_tree *lt = NULL;
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, fake_db, dbcmp);
     assert(r == 0 && lt);
 
     const TXNID txn_a = 1;
     DBT key_l; dbt_init(&key_l, "L", 1);
-    toku_lock_request a_w_l; toku_lock_request_init(&a_w_l, (DB *)1, txn_a, &key_l, &key_l, LOCK_REQUEST_WRITE);
+    toku_lock_request a_w_l; toku_lock_request_init(&a_w_l, fake_db, txn_a, &key_l, &key_l, LOCK_REQUEST_WRITE);
     r = toku_lock_request_start(&a_w_l, lt, false); assert(r == 0); 
     assert(a_w_l.state == LOCK_REQUEST_COMPLETE && a_w_l.complete_r == 0);
 
@@ -57,7 +59,7 @@ int main(int argc, const char *argv[]) {
     toku_lock_request_destroy(&a_w_l);
 
     const TXNID txn_b = 2;
-    toku_lock_request b_r_l; toku_lock_request_init(&b_r_l, (DB *)1, txn_b, &key_l, &key_l, LOCK_REQUEST_READ);
+    toku_lock_request b_r_l; toku_lock_request_init(&b_r_l, fake_db, txn_b, &key_l, &key_l, LOCK_REQUEST_READ);
     r = toku_lock_request_start(&b_r_l, lt, false); assert(r != 0); 
     assert(b_r_l.state == LOCK_REQUEST_PENDING);
 
@@ -74,7 +76,7 @@ int main(int argc, const char *argv[]) {
     r = toku_lt_unlock_txn(lt, txn_b); assert(r == 0);
 
     // shutdown 
-    r = toku_lt_close(lt); assert(r == 0);
+    toku_lt_remove_db_ref(lt, fake_db);
     r = toku_ltm_close(ltm); assert(r == 0);
 
     return 0;
diff --git a/src/lock_tree/tests/test_conflict_write_table_read.c b/src/lock_tree/tests/test_conflict_write_table_read.c
index 1a98ab5b37..047b5f2142 100644
--- a/src/lock_tree/tests/test_conflict_write_table_read.c
+++ b/src/lock_tree/tests/test_conflict_write_table_read.c
@@ -36,14 +36,16 @@ int main(int argc, const char *argv[]) {
     r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
     assert(r == 0 && ltm);
 
+    DB *fake_db = (DB *) 1;
+
     toku_lock_tree *lt = NULL;
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, fake_db, dbcmp);
     assert(r == 0 && lt);
 
     DBT key_l; dbt_init(&key_l, "L", 1);
 
     const TXNID txn_a = 1;
-    toku_lock_request a_w_l; toku_lock_request_init(&a_w_l, (DB *)1, txn_a, toku_lt_neg_infinity, toku_lt_infinity, LOCK_REQUEST_WRITE);
+    toku_lock_request a_w_l; toku_lock_request_init(&a_w_l, fake_db, txn_a, toku_lt_neg_infinity, toku_lt_infinity, LOCK_REQUEST_WRITE);
     r = toku_lock_request_start(&a_w_l, lt, false); assert(r == 0); 
     assert(a_w_l.state == LOCK_REQUEST_COMPLETE && a_w_l.complete_r == 0);
 
@@ -58,7 +60,7 @@ int main(int argc, const char *argv[]) {
     toku_lock_request_destroy(&a_w_l);
 
     const TXNID txn_b = 2;
-    toku_lock_request b_r_l; toku_lock_request_init(&b_r_l, (DB *)1, txn_b, &key_l, &key_l, LOCK_REQUEST_READ);
+    toku_lock_request b_r_l; toku_lock_request_init(&b_r_l, fake_db, txn_b, &key_l, &key_l, LOCK_REQUEST_READ);
     r = toku_lock_request_start(&b_r_l, lt, false); assert(r != 0); 
     assert(b_r_l.state == LOCK_REQUEST_PENDING);
 
@@ -74,7 +76,7 @@ int main(int argc, const char *argv[]) {
     r = toku_lt_unlock_txn(lt, txn_b); assert(r == 0);
 
     // shutdown 
-    r = toku_lt_close(lt); assert(r == 0);
+    toku_lt_remove_db_ref(lt, fake_db);
     r = toku_ltm_close(ltm); assert(r == 0);
 
     return 0;
diff --git a/src/lock_tree/tests/test_conflict_write_write.c b/src/lock_tree/tests/test_conflict_write_write.c
index 8d3dfc48db..189724e59e 100644
--- a/src/lock_tree/tests/test_conflict_write_write.c
+++ b/src/lock_tree/tests/test_conflict_write_write.c
@@ -36,14 +36,16 @@ int main(int argc, const char *argv[]) {
     r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
     assert(r == 0 && ltm);
 
+    DB *fake_db = (DB *) 1;
+
     toku_lock_tree *lt = NULL;
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, fake_db, dbcmp);
     assert(r == 0 && lt);
 
     DBT key_l; dbt_init(&key_l, "L", 1);
 
     const TXNID txn_a = 1;
-    toku_lock_request a_w_l; toku_lock_request_init(&a_w_l, (DB *)1, txn_a, &key_l, &key_l, LOCK_REQUEST_WRITE);
+    toku_lock_request a_w_l; toku_lock_request_init(&a_w_l, fake_db, txn_a, &key_l, &key_l, LOCK_REQUEST_WRITE);
     r = toku_lock_request_start(&a_w_l, lt, false); assert(r == 0); 
     assert(a_w_l.state == LOCK_REQUEST_COMPLETE && a_w_l.complete_r == 0);
 
@@ -58,7 +60,7 @@ int main(int argc, const char *argv[]) {
     toku_lock_request_destroy(&a_w_l);
 
     const TXNID txn_b = 2;
-    toku_lock_request b_w_l; toku_lock_request_init(&b_w_l, (DB *)1, txn_b, &key_l, &key_l, LOCK_REQUEST_WRITE);
+    toku_lock_request b_w_l; toku_lock_request_init(&b_w_l, fake_db, txn_b, &key_l, &key_l, LOCK_REQUEST_WRITE);
     r = toku_lock_request_start(&b_w_l, lt, false); assert(r != 0); 
     assert(b_w_l.state == LOCK_REQUEST_PENDING);
 
@@ -74,7 +76,7 @@ int main(int argc, const char *argv[]) {
     r = toku_lt_unlock_txn(lt, txn_a);  assert(r == 0);
 
     // shutdown 
-    r = toku_lt_close(lt); assert(r == 0);
+    toku_lt_remove_db_ref(lt, fake_db);
     r = toku_ltm_close(ltm); assert(r == 0);
 
     return 0;
diff --git a/src/lock_tree/tests/test_default_lock_timeout.c b/src/lock_tree/tests/test_default_lock_timeout.c
index f343ed3d8d..35dd8eee63 100644
--- a/src/lock_tree/tests/test_default_lock_timeout.c
+++ b/src/lock_tree/tests/test_default_lock_timeout.c
@@ -53,8 +53,10 @@ int main(int argc, const char *argv[]) {
     r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
     assert(r == 0 && ltm);
 
+    DB *fake_db = (DB *) 1;
+
     toku_lock_tree *lt = NULL;
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, fake_db, dbcmp);
     assert(r == 0 && lt);
 
     const TXNID txn_a = 1;
@@ -71,7 +73,7 @@ int main(int argc, const char *argv[]) {
     r = toku_lt_unlock_txn(lt, txn_a);  assert(r == 0);
 
     // shutdown 
-    r = toku_lt_close(lt); assert(r == 0);
+    toku_lt_remove_db_ref(lt, fake_db);
     r = toku_ltm_close(ltm); assert(r == 0);
 
     return 0;
diff --git a/src/lock_tree/tests/test_footprint_point_write.c b/src/lock_tree/tests/test_footprint_point_write.c
index ff7a8ebc54..3ae662c98d 100644
--- a/src/lock_tree/tests/test_footprint_point_write.c
+++ b/src/lock_tree/tests/test_footprint_point_write.c
@@ -103,11 +103,12 @@ int main(int argc, const char *argv[]) {
     assert(s.max_lock_memory == max_lock_memory);
     assert(s.curr_lock_memory == 0);
 
+    DB *db_a = (DB *) 2;
+
     toku_lock_tree *lt = NULL;
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, db_a, dbcmp);
     assert(r == 0 && lt);
 
-    DB *db_a = (DB *) 2;
     TXNID txn_a = 1;
 
     // acquire the locks on keys 1 .. nrows
@@ -141,7 +142,7 @@ int main(int argc, const char *argv[]) {
     assert(s.curr_locks == 0);
 
     // shutdown 
-    r = toku_lt_close(lt); assert(r == 0);
+    toku_lt_remove_db_ref(lt, db_a);
     r = toku_ltm_close(ltm); assert(r == 0);
 
     return 0;
diff --git a/src/lock_tree/tests/test_footprint_range_write.c b/src/lock_tree/tests/test_footprint_range_write.c
index 9555c14200..2016b34402 100644
--- a/src/lock_tree/tests/test_footprint_range_write.c
+++ b/src/lock_tree/tests/test_footprint_range_write.c
@@ -105,11 +105,12 @@ int main(int argc, const char *argv[]) {
     assert(s.max_lock_memory == max_lock_memory);
     assert(s.curr_lock_memory == 0);
 
+    DB *db_a = (DB *) 2;
+
     toku_lock_tree *lt = NULL;
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, db_a, dbcmp);
     assert(r == 0 && lt);
 
-    DB *db_a = (DB *) 2;
     TXNID txn_a = 1;
 
     // acquire the locks on keys 1 .. nrows
@@ -145,7 +146,7 @@ int main(int argc, const char *argv[]) {
     assert(s.curr_locks == 0);
 
     // shutdown 
-    r = toku_lt_close(lt); assert(r == 0);
+    toku_lt_remove_db_ref(lt, db_a);
     r = toku_ltm_close(ltm); assert(r == 0);
 
     return 0;
diff --git a/src/lock_tree/tests/test_global_write_lock.c b/src/lock_tree/tests/test_global_write_lock.c
index 38c56be2a2..e0ceb04bb2 100644
--- a/src/lock_tree/tests/test_global_write_lock.c
+++ b/src/lock_tree/tests/test_global_write_lock.c
@@ -34,12 +34,14 @@ static void init_query(void) {
     query.right = &qright;
 }
 
+static DB *fake_db = (DB *) 1;
+
 static void setup_tree(void) {
     assert(!lt && !ltm);
     r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
     CKERR(r);
     assert(ltm);
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, fake_db, dbcmp);
     CKERR(r);
     assert(lt);
     init_query();
@@ -47,7 +49,7 @@ static void setup_tree(void) {
 
 static void close_tree(void) {
     assert(lt && ltm);
-    r = toku_lt_close(lt); CKERR(r);
+    toku_lt_remove_db_ref(lt, fake_db);
     r = toku_ltm_close(ltm); CKERR(r);
     lt = NULL;
     ltm = NULL;
diff --git a/src/lock_tree/tests/test_lock_timeout.c b/src/lock_tree/tests/test_lock_timeout.c
index d4293d8062..4f5ccb81f3 100644
--- a/src/lock_tree/tests/test_lock_timeout.c
+++ b/src/lock_tree/tests/test_lock_timeout.c
@@ -53,8 +53,10 @@ int main(int argc, const char *argv[]) {
     r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
     assert(r == 0 && ltm);
 
+    DB *fake_db = (DB *) 1;
+
     toku_lock_tree *lt = NULL;
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, fake_db, dbcmp);
     assert(r == 0 && lt);
 
     const TXNID txn_a = 1;
@@ -71,7 +73,7 @@ int main(int argc, const char *argv[]) {
     r = toku_lt_unlock_txn(lt, txn_a);  assert(r == 0);
 
     // shutdown 
-    r = toku_lt_close(lt); assert(r == 0);
+    toku_lt_remove_db_ref(lt, fake_db);
     r = toku_ltm_close(ltm); assert(r == 0);
 
     return 0;
diff --git a/src/lock_tree/tests/test_ltm_get_status.c b/src/lock_tree/tests/test_ltm_get_status.c
index 0e7a7c54f9..86d6a55756 100644
--- a/src/lock_tree/tests/test_ltm_get_status.c
+++ b/src/lock_tree/tests/test_ltm_get_status.c
@@ -22,90 +22,8 @@ int main(int argc, const char *argv[]) {
     toku_ltm *ltm = NULL;
     r = toku_ltm_create(&ltm, MAX_LOCKS, MAX_LOCK_MEMORY, dbpanic);
     CKERR(r);
-    do_ltm_status(ltm);
-#if 0
-    r = toku_ltm_set_max_locks(NULL, max_locks);
-        CKERR2(r, EINVAL);
-    r = toku_ltm_set_max_locks(ltm,  0);
-        CKERR2(r, EINVAL);
-    r = toku_ltm_set_max_locks(ltm,  max_locks);
-        CKERR(r);
-
-    uint32_t get_max = 73; //Some random number that isn't 0.
-    r = toku_ltm_get_max_locks(NULL, &get_max);
-        CKERR2(r, EINVAL);
-        assert(get_max == 73);
-    r = toku_ltm_get_max_locks(ltm,  NULL);
-        CKERR2(r, EINVAL);
-        assert(get_max == 73);
-    r = toku_ltm_get_max_locks(ltm,  &get_max);
-        CKERR(r);
-        assert(get_max == max_locks);
-
-    r = toku_ltm_set_max_lock_memory(NULL, max_lock_memory);
-        CKERR2(r, EINVAL);
-    r = toku_ltm_set_max_lock_memory(ltm,  0);
-        CKERR2(r, EINVAL);
-    r = toku_ltm_set_max_lock_memory(ltm,  max_lock_memory);
-        CKERR(r);
-
-    uint64_t get_max_memory = 73; //Some random number that isn't 0.
-    r = toku_ltm_get_max_lock_memory(NULL, &get_max_memory);
-        CKERR2(r, EINVAL);
-        assert(get_max_memory == 73);
-    r = toku_ltm_get_max_lock_memory(ltm,  NULL);
-        CKERR2(r, EINVAL);
-        assert(get_max_memory == 73);
-    r = toku_ltm_get_max_lock_memory(ltm,  &get_max_memory);
-        CKERR(r);
-        assert(get_max_memory == max_lock_memory);
-
-    /* create tests. */
-    {
-        r = toku_lt_create(NULL, dbpanic, ltm,
-                           dbcmp,
-                           toku_malloc, toku_free, toku_realloc);
-        CKERR2(r, EINVAL);
-
-        r = toku_lt_create(&lt,  NULL,    ltm,
-                           dbcmp,
-                           toku_malloc, toku_free, toku_realloc);
-        CKERR2(r, EINVAL);
 
-        r = toku_lt_create(&lt,  dbpanic, NULL,
-                           dbcmp,
-                           toku_malloc, toku_free, toku_realloc);
-        CKERR2(r, EINVAL);
-
-        r = toku_lt_create(&lt,  dbpanic, ltm,
-                           NULL,
-                           toku_malloc, toku_free, toku_realloc);
-        CKERR2(r, EINVAL);
-
-        r = toku_lt_create(&lt,  dbpanic, ltm,
-                           dbcmp,
-                           NULL,        toku_free, toku_realloc);
-        CKERR2(r, EINVAL);
-        r = toku_lt_create(&lt,  dbpanic, ltm,
-                           dbcmp,
-                           toku_malloc, NULL,      toku_realloc);
-        CKERR2(r, EINVAL);
-        r = toku_lt_create(&lt,  dbpanic, ltm,
-                           dbcmp,
-                           toku_malloc, toku_free, NULL);
-        CKERR2(r, EINVAL);
-    }
-
-    /* Close tests. */
-    r = toku_lt_close(NULL);
-    CKERR2(r, EINVAL);
-
-    do_point_test(toku_lt_acquire_read_lock);
-    do_point_test(toku_lt_acquire_write_lock);
-
-    do_range_test(toku_lt_acquire_range_read_lock);
-    do_range_test(toku_lt_acquire_range_write_lock);
-#endif
+    do_ltm_status(ltm);
 
     toku_ltm_close(ltm);
 
diff --git a/src/lock_tree/tests/test_read_notgranted.c b/src/lock_tree/tests/test_read_notgranted.c
index 560298f9b6..9c7c6c90f4 100644
--- a/src/lock_tree/tests/test_read_notgranted.c
+++ b/src/lock_tree/tests/test_read_notgranted.c
@@ -52,8 +52,10 @@ int main(int argc, const char *argv[]) {
     r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
     assert(r == 0 && ltm);
 
+    DB *fake_db = (DB *) 1;
+
     toku_lock_tree *lt = NULL;
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, fake_db, dbcmp);
     assert(r == 0 && lt);
 
     const TXNID txn_a = 1;
@@ -72,7 +74,7 @@ int main(int argc, const char *argv[]) {
     r = toku_lt_unlock_txn(lt, txn_c); assert(r == 0);
 
     // shutdown 
-    r = toku_lt_close(lt); assert(r == 0);
+    toku_lt_remove_db_ref(lt, fake_db);
     r = toku_ltm_close(ltm); assert(r == 0);
 
     return 0;
diff --git a/src/lock_tree/tests/test_read_out_of_locks.c b/src/lock_tree/tests/test_read_out_of_locks.c
index f2b9a4e3bc..3cfd34b224 100644
--- a/src/lock_tree/tests/test_read_out_of_locks.c
+++ b/src/lock_tree/tests/test_read_out_of_locks.c
@@ -41,24 +41,26 @@ int main(int argc, const char *argv[]) {
     r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
     assert(r == 0 && ltm);
 
+    DB *fake_db = (DB *) 1;
+
     toku_lock_tree *lt = NULL;
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, fake_db, dbcmp);
     assert(r == 0 && lt);
 
     const TXNID txn_a = 1;
     DBT key_l; dbt_init(&key_l, "L", 1);
-    toku_lock_request a_w_l; toku_lock_request_init(&a_w_l, (DB *)1, txn_a, &key_l, &key_l, LOCK_REQUEST_WRITE);
+    toku_lock_request a_w_l; toku_lock_request_init(&a_w_l, fake_db, txn_a, &key_l, &key_l, LOCK_REQUEST_WRITE);
     r = toku_lock_request_start(&a_w_l, lt, false); assert(r == 0); 
     assert(a_w_l.state == LOCK_REQUEST_COMPLETE && a_w_l.complete_r == 0);
     toku_lock_request_destroy(&a_w_l);
 
     const TXNID txn_b = 2;
-    toku_lock_request b_w_l; toku_lock_request_init(&b_w_l, (DB *)1, txn_b, &key_l, &key_l, LOCK_REQUEST_READ);
+    toku_lock_request b_w_l; toku_lock_request_init(&b_w_l, fake_db, txn_b, &key_l, &key_l, LOCK_REQUEST_READ);
     r = toku_lock_request_start(&b_w_l, lt, false); assert(r != 0); 
     assert(b_w_l.state == LOCK_REQUEST_PENDING);
 
     const TXNID txn_c = 3;
-    toku_lock_request c_w_l; toku_lock_request_init(&c_w_l, (DB *)1, txn_c, &key_l, &key_l, LOCK_REQUEST_READ);
+    toku_lock_request c_w_l; toku_lock_request_init(&c_w_l, fake_db, txn_c, &key_l, &key_l, LOCK_REQUEST_READ);
     r = toku_lock_request_start(&c_w_l, lt, false); assert(r != 0); 
     assert(c_w_l.state == LOCK_REQUEST_PENDING);
 
@@ -71,7 +73,7 @@ int main(int argc, const char *argv[]) {
     r = toku_lt_unlock_txn(lt, txn_c);  assert(r == 0);
 
     // shutdown 
-    r = toku_lt_close(lt); assert(r == 0);
+    toku_lt_remove_db_ref(lt, fake_db);
     r = toku_ltm_close(ltm); assert(r == 0);
 
     return 0;
diff --git a/src/lock_tree/tests/test_read_request_blocked.c b/src/lock_tree/tests/test_read_request_blocked.c
index 9944aef840..86e42cf68a 100644
--- a/src/lock_tree/tests/test_read_request_blocked.c
+++ b/src/lock_tree/tests/test_read_request_blocked.c
@@ -40,24 +40,26 @@ int main(int argc, const char *argv[]) {
     r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
     assert(r == 0 && ltm);
 
+    DB *fake_db = (DB *) 1;
+
     toku_lock_tree *lt = NULL;
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, fake_db, dbcmp);
     assert(r == 0 && lt);
 
     const TXNID txn_a = 1;
     DBT key_l; dbt_init(&key_l, "L", 1);
-    toku_lock_request a_w_l; toku_lock_request_init(&a_w_l, (DB *)1, txn_a, &key_l, &key_l, LOCK_REQUEST_WRITE);
+    toku_lock_request a_w_l; toku_lock_request_init(&a_w_l, fake_db, txn_a, &key_l, &key_l, LOCK_REQUEST_WRITE);
     r = toku_lock_request_start(&a_w_l, lt, false); assert(r == 0); 
     assert(a_w_l.state == LOCK_REQUEST_COMPLETE && a_w_l.complete_r == 0);
     toku_lock_request_destroy(&a_w_l);
 
     const TXNID txn_b = 2;
-    toku_lock_request b_w_l; toku_lock_request_init(&b_w_l, (DB *)1, txn_b, &key_l, &key_l, LOCK_REQUEST_READ);
+    toku_lock_request b_w_l; toku_lock_request_init(&b_w_l, fake_db, txn_b, &key_l, &key_l, LOCK_REQUEST_READ);
     r = toku_lock_request_start(&b_w_l, lt, false); assert(r != 0); 
     assert(b_w_l.state == LOCK_REQUEST_PENDING);
 
     const TXNID txn_c = 3;
-    toku_lock_request c_w_l; toku_lock_request_init(&c_w_l, (DB *)1, txn_c, &key_l, &key_l, LOCK_REQUEST_READ);
+    toku_lock_request c_w_l; toku_lock_request_init(&c_w_l, fake_db, txn_c, &key_l, &key_l, LOCK_REQUEST_READ);
     r = toku_lock_request_start(&c_w_l, lt, false); assert(r != 0); 
     assert(c_w_l.state == LOCK_REQUEST_PENDING);
 
@@ -70,7 +72,7 @@ int main(int argc, const char *argv[]) {
     r = toku_lt_unlock_txn(lt, txn_c);  assert(r == 0);
 
     // shutdown 
-    r = toku_lt_close(lt); assert(r == 0);
+    toku_lt_remove_db_ref(lt, fake_db);
     r = toku_ltm_close(ltm); assert(r == 0);
 
     return 0;
diff --git a/src/lock_tree/tests/test_simple_deadlock.c b/src/lock_tree/tests/test_simple_deadlock.c
index 7ae907418c..0d848e3192 100644
--- a/src/lock_tree/tests/test_simple_deadlock.c
+++ b/src/lock_tree/tests/test_simple_deadlock.c
@@ -39,29 +39,31 @@ int main(int argc, const char *argv[]) {
     r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
     assert(r == 0 && ltm);
 
+    DB *fake_db = (DB *) 1;
+
     toku_lock_tree *lt = NULL;
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, fake_db, dbcmp);
     assert(r == 0 && lt);
 
     const TXNID txn_a = 1;
     DBT key_l; dbt_init(&key_l, "L", 1);
-    toku_lock_request a_w_l; toku_lock_request_init(&a_w_l, (DB *)1, txn_a, &key_l, &key_l, LOCK_REQUEST_WRITE);
+    toku_lock_request a_w_l; toku_lock_request_init(&a_w_l, fake_db, txn_a, &key_l, &key_l, LOCK_REQUEST_WRITE);
     r = toku_lock_request_start(&a_w_l, lt, false); assert(r == 0); 
     assert(a_w_l.state == LOCK_REQUEST_COMPLETE && a_w_l.complete_r == 0);
     toku_lock_request_destroy(&a_w_l);
 
     const TXNID txn_b = 2;
     DBT key_m; dbt_init(&key_m, "M", 1);
-    toku_lock_request b_w_m; toku_lock_request_init(&b_w_m, (DB *)1, txn_b, &key_m, &key_m, LOCK_REQUEST_WRITE);
+    toku_lock_request b_w_m; toku_lock_request_init(&b_w_m, fake_db, txn_b, &key_m, &key_m, LOCK_REQUEST_WRITE);
     r = toku_lock_request_start(&b_w_m, lt, false); assert(r == 0); 
     assert(b_w_m.state == LOCK_REQUEST_COMPLETE && b_w_m.complete_r == 0);
     toku_lock_request_destroy(&b_w_m);
 
-    toku_lock_request a_w_m; toku_lock_request_init(&a_w_m, (DB *)1, txn_a, &key_m, &key_m, LOCK_REQUEST_WRITE);
+    toku_lock_request a_w_m; toku_lock_request_init(&a_w_m, fake_db, txn_a, &key_m, &key_m, LOCK_REQUEST_WRITE);
     r = toku_lock_request_start(&a_w_m, lt, false); assert(r == DB_LOCK_NOTGRANTED); 
     assert(a_w_m.state == LOCK_REQUEST_PENDING);
 
-    toku_lock_request b_w_l; toku_lock_request_init(&b_w_l, (DB *)1, txn_b, &key_l, &key_l, LOCK_REQUEST_WRITE);
+    toku_lock_request b_w_l; toku_lock_request_init(&b_w_l, fake_db, txn_b, &key_l, &key_l, LOCK_REQUEST_WRITE);
     r = toku_lock_request_start(&b_w_l, lt, false); assert(r == DB_LOCK_DEADLOCK); 
     assert(b_w_l.state == LOCK_REQUEST_COMPLETE && b_w_l.complete_r == DB_LOCK_DEADLOCK);
 
@@ -75,7 +77,7 @@ int main(int argc, const char *argv[]) {
     r = toku_lt_unlock_txn(lt, txn_a);  assert(r == 0);
 
     // shutdown 
-    r = toku_lt_close(lt); assert(r == 0);
+    toku_lt_remove_db_ref(lt, fake_db);
     r = toku_ltm_close(ltm); assert(r == 0);
 
     return 0;
diff --git a/src/lock_tree/tests/test_unlock_after_close.c b/src/lock_tree/tests/test_unlock_after_close.c
new file mode 100644
index 0000000000..a48f5c8751
--- /dev/null
+++ b/src/lock_tree/tests/test_unlock_after_close.c
@@ -0,0 +1,63 @@
+// add a write lock on L for a transaction, remove a reference on the lock tree, then release the locks for the transaction.
+
+#include "test.h"
+
+int main(int argc, const char *argv[]) {
+    int r;
+
+    uint32_t max_locks = 2;
+    uint64_t max_lock_memory = 4096;
+
+    for (int i = 1; i < argc; i++) {
+        if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) {
+            verbose++;
+            continue;
+        }
+        if (strcmp(argv[i], "-q") == 0 || strcmp(argv[i], "--quiet") == 0) {
+            if (verbose > 0) verbose--;
+            continue;
+        }
+        if (strcmp(argv[i], "--max_locks") == 0 && i+1 < argc) {
+            max_locks = atoi(argv[++i]);
+            continue;
+        }
+        if (strcmp(argv[i], "--max_lock_memory") == 0 && i+1 < argc) {
+            max_lock_memory = atoi(argv[++i]);
+            continue;
+        }        
+        assert(0);
+    }
+
+    // setup
+    toku_ltm *ltm = NULL;
+    r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
+    assert(r == 0 && ltm);
+
+    DB *fake_db = (DB *) 1;
+
+    toku_lock_tree *lt = NULL;
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, fake_db, dbcmp);
+    assert(r == 0 && lt);
+
+    // add a lock for a transaction
+    const TXNID txn_a = 1;
+    DBT key_l; dbt_init(&key_l, "L", 1);
+    toku_lock_request a_w_l; toku_lock_request_init(&a_w_l, fake_db, txn_a, &key_l, &key_l, LOCK_REQUEST_WRITE);
+    r = toku_lock_request_start(&a_w_l, lt, false); assert(r == 0); 
+    assert(a_w_l.state == LOCK_REQUEST_COMPLETE && a_w_l.complete_r == 0);
+    toku_lock_request_destroy(&a_w_l);
+    
+    // add a reference to the lock tree for the transaction
+    toku_lt_add_ref(lt);
+
+    // start closing the lock tree
+    toku_lt_remove_db_ref(lt, fake_db);
+
+    // release all locks for the transaction
+    r = toku_lt_unlock_txn(lt, txn_a);  assert(r == 0);
+
+    // shutdown 
+    r = toku_ltm_close(ltm); assert(r == 0);
+
+    return 0;
+}
diff --git a/src/lock_tree/tests/test_update_deadlock.c b/src/lock_tree/tests/test_update_deadlock.c
index a38689e7e9..e129d8d5e9 100644
--- a/src/lock_tree/tests/test_update_deadlock.c
+++ b/src/lock_tree/tests/test_update_deadlock.c
@@ -38,29 +38,31 @@ int main(int argc, const char *argv[]) {
     toku_ltm *ltm = NULL;
     r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
     assert(r == 0 && ltm);
+    
+    DB *fake_db = (DB *) 1;
 
     toku_lock_tree *lt = NULL;
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, fake_db, dbcmp);
     assert(r == 0 && lt);
 
     const TXNID txn_a = 1;
     DBT key_l; dbt_init(&key_l, "L", 1);
-    toku_lock_request a_r_l; toku_lock_request_init(&a_r_l, (DB *)1, txn_a, &key_l, &key_l, LOCK_REQUEST_READ);
+    toku_lock_request a_r_l; toku_lock_request_init(&a_r_l, fake_db, txn_a, &key_l, &key_l, LOCK_REQUEST_READ);
     r = toku_lock_request_start(&a_r_l, lt, false); assert(r == 0); 
     assert(a_r_l.state == LOCK_REQUEST_COMPLETE && a_r_l.complete_r == 0);
     toku_lock_request_destroy(&a_r_l);
 
     const TXNID txn_b = 2;
-    toku_lock_request b_r_l; toku_lock_request_init(&b_r_l, (DB *)1, txn_b, &key_l, &key_l, LOCK_REQUEST_READ);
+    toku_lock_request b_r_l; toku_lock_request_init(&b_r_l, fake_db, txn_b, &key_l, &key_l, LOCK_REQUEST_READ);
     r = toku_lock_request_start(&b_r_l, lt, false); assert(r == 0); 
     assert(b_r_l.state == LOCK_REQUEST_COMPLETE && b_r_l.complete_r == 0);
     toku_lock_request_destroy(&b_r_l);
 
-    toku_lock_request a_w_l; toku_lock_request_init(&a_w_l, (DB *)1, txn_a, &key_l, &key_l, LOCK_REQUEST_WRITE);
+    toku_lock_request a_w_l; toku_lock_request_init(&a_w_l, fake_db, txn_a, &key_l, &key_l, LOCK_REQUEST_WRITE);
     r = toku_lock_request_start(&a_w_l, lt, false); assert(r == DB_LOCK_NOTGRANTED); 
     assert(a_w_l.state == LOCK_REQUEST_PENDING);
 
-    toku_lock_request b_w_l; toku_lock_request_init(&b_w_l, (DB *)1, txn_b, &key_l, &key_l, LOCK_REQUEST_WRITE);
+    toku_lock_request b_w_l; toku_lock_request_init(&b_w_l, fake_db, txn_b, &key_l, &key_l, LOCK_REQUEST_WRITE);
     r = toku_lock_request_start(&b_w_l, lt, false); assert(r == DB_LOCK_DEADLOCK); 
     assert(b_w_l.state == LOCK_REQUEST_COMPLETE && b_w_l.complete_r == DB_LOCK_DEADLOCK);
 
@@ -73,7 +75,7 @@ int main(int argc, const char *argv[]) {
     r = toku_lt_unlock_txn(lt, txn_a);  assert(r == 0);
 
     // shutdown 
-    r = toku_lt_close(lt); assert(r == 0);
+    toku_lt_remove_db_ref(lt, fake_db);
     r = toku_ltm_close(ltm); assert(r == 0);
 
     return 0;
diff --git a/src/lock_tree/tests/test_update_deadlock_copy_keys.c b/src/lock_tree/tests/test_update_deadlock_copy_keys.c
index 6601d56f7e..ea4dc6dc89 100644
--- a/src/lock_tree/tests/test_update_deadlock_copy_keys.c
+++ b/src/lock_tree/tests/test_update_deadlock_copy_keys.c
@@ -39,28 +39,30 @@ int main(int argc, const char *argv[]) {
     r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
     assert(r == 0 && ltm);
 
+    DB *fake_db = (DB *) 1;
+
     toku_lock_tree *lt = NULL;
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, fake_db, dbcmp);
     assert(r == 0 && lt);
 
     const TXNID txn_a = 1;
     DBT key_l; dbt_init(&key_l, "L", 1);
-    toku_lock_request a_r_l; toku_lock_request_init(&a_r_l, (DB *)1, txn_a, &key_l, &key_l, LOCK_REQUEST_READ);
+    toku_lock_request a_r_l; toku_lock_request_init(&a_r_l, fake_db, txn_a, &key_l, &key_l, LOCK_REQUEST_READ);
     r = toku_lock_request_start(&a_r_l, lt, false); assert(r == 0); 
     assert(a_r_l.state == LOCK_REQUEST_COMPLETE && a_r_l.complete_r == 0);
     toku_lock_request_destroy(&a_r_l);
 
     const TXNID txn_b = 2;
-    toku_lock_request b_r_l; toku_lock_request_init(&b_r_l, (DB *)1, txn_b, &key_l, &key_l, LOCK_REQUEST_READ);
+    toku_lock_request b_r_l; toku_lock_request_init(&b_r_l, fake_db, txn_b, &key_l, &key_l, LOCK_REQUEST_READ);
     r = toku_lock_request_start(&b_r_l, lt, true); assert(r == 0); 
     assert(b_r_l.state == LOCK_REQUEST_COMPLETE && b_r_l.complete_r == 0);
     toku_lock_request_destroy(&b_r_l);
 
-    toku_lock_request a_w_l; toku_lock_request_init(&a_w_l, (DB *)1, txn_a, &key_l, &key_l, LOCK_REQUEST_WRITE);
+    toku_lock_request a_w_l; toku_lock_request_init(&a_w_l, fake_db, txn_a, &key_l, &key_l, LOCK_REQUEST_WRITE);
     r = toku_lock_request_start(&a_w_l, lt, true); assert(r == DB_LOCK_NOTGRANTED); 
     assert(a_w_l.state == LOCK_REQUEST_PENDING);
 
-    toku_lock_request b_w_l; toku_lock_request_init(&b_w_l, (DB *)1, txn_b, &key_l, &key_l, LOCK_REQUEST_WRITE);
+    toku_lock_request b_w_l; toku_lock_request_init(&b_w_l, fake_db, txn_b, &key_l, &key_l, LOCK_REQUEST_WRITE);
     r = toku_lock_request_start(&b_w_l, lt, true); assert(r == DB_LOCK_DEADLOCK); 
     assert(b_w_l.state == LOCK_REQUEST_COMPLETE && b_w_l.complete_r == DB_LOCK_DEADLOCK);
 
@@ -73,7 +75,7 @@ int main(int argc, const char *argv[]) {
     r = toku_lt_unlock_txn(lt, txn_a);  assert(r == 0);
 
     // shutdown 
-    r = toku_lt_close(lt); assert(r == 0);
+    toku_lt_remove_db_ref(lt, fake_db);
     r = toku_ltm_close(ltm); assert(r == 0);
 
     return 0;
diff --git a/src/lock_tree/tests/test_write_conflict_with_threads.c b/src/lock_tree/tests/test_write_conflict_with_threads.c
index fd79e0beff..ca04bebcc3 100644
--- a/src/lock_tree/tests/test_write_conflict_with_threads.c
+++ b/src/lock_tree/tests/test_write_conflict_with_threads.c
@@ -68,8 +68,10 @@ int main(int argc, const char *argv[]) {
     r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
     assert(r == 0 && ltm);
 
+    DB *fake_db = (DB *) 1;
+
     toku_lock_tree *lt = NULL;
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, fake_db, dbcmp);
     assert(r == 0 && lt);
 
     const TXNID txn_a = 1;
@@ -94,7 +96,7 @@ int main(int argc, const char *argv[]) {
     }
 
     // shutdown 
-    r = toku_lt_close(lt); assert(r == 0);
+    toku_lt_remove_db_ref(lt, fake_db);
     r = toku_ltm_close(ltm); assert(r == 0);
 
     return 0;
diff --git a/src/lock_tree/tests/test_write_notgranted.c b/src/lock_tree/tests/test_write_notgranted.c
index 167db5959e..53b44d7e37 100644
--- a/src/lock_tree/tests/test_write_notgranted.c
+++ b/src/lock_tree/tests/test_write_notgranted.c
@@ -43,8 +43,10 @@ int main(int argc, const char *argv[]) {
     r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
     assert(r == 0 && ltm);
 
+    DB *fake_db = (DB *) 1;
+
     toku_lock_tree *lt = NULL;
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, fake_db, dbcmp);
     assert(r == 0 && lt);
 
     const TXNID txn_a = 1;
@@ -57,7 +59,7 @@ int main(int argc, const char *argv[]) {
     r = toku_lt_unlock_txn(lt, txn_b);  assert(r == 0);
 
     // shutdown 
-    r = toku_lt_close(lt); assert(r == 0);
+    toku_lt_remove_db_ref(lt, fake_db);
     r = toku_ltm_close(ltm); assert(r == 0);
 
     return 0;
diff --git a/src/lock_tree/tests/test_write_range.c b/src/lock_tree/tests/test_write_range.c
index 8bcfab454f..9be0bf514e 100644
--- a/src/lock_tree/tests/test_write_range.c
+++ b/src/lock_tree/tests/test_write_range.c
@@ -34,12 +34,14 @@ static void init_query(void) {
     query.right = &qright;
 }
 
+static DB *fake_db = (DB *) 1;
+
 static void setup_tree(void) {
     assert(!lt && !ltm);
     r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
     CKERR(r);
     assert(ltm);
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, fake_db, dbcmp);
     CKERR(r);
     assert(lt);
     init_query();
@@ -47,7 +49,7 @@ static void setup_tree(void) {
 
 static void close_tree(void) {
     assert(lt && ltm);
-    r = toku_lt_close(lt); CKERR(r);
+    toku_lt_remove_db_ref(lt, fake_db);
     r = toku_ltm_close(ltm); CKERR(r);
     lt = NULL;
     ltm = NULL;
diff --git a/src/lock_tree/tests/test_write_range_conflict_read.c b/src/lock_tree/tests/test_write_range_conflict_read.c
index def4b49f30..e5b0d8a710 100644
--- a/src/lock_tree/tests/test_write_range_conflict_read.c
+++ b/src/lock_tree/tests/test_write_range_conflict_read.c
@@ -34,12 +34,14 @@ static void init_query(void) {
     query.right = &qright;
 }
 
+static DB *fake_db = (DB *) 1;
+
 static void setup_tree(void) {
     assert(!lt && !ltm);
     r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
     CKERR(r);
     assert(ltm);
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, fake_db, dbcmp);
     CKERR(r);
     assert(lt);
     init_query();
@@ -47,7 +49,7 @@ static void setup_tree(void) {
 
 static void close_tree(void) {
     assert(lt && ltm);
-    r = toku_lt_close(lt); CKERR(r);
+    toku_lt_remove_db_ref(lt, fake_db);
     r = toku_ltm_close(ltm); CKERR(r);
     lt = NULL;
     ltm = NULL;
diff --git a/src/lock_tree/tests/test_write_range_conflict_write.c b/src/lock_tree/tests/test_write_range_conflict_write.c
index 7b58b53373..0e13f86ba0 100644
--- a/src/lock_tree/tests/test_write_range_conflict_write.c
+++ b/src/lock_tree/tests/test_write_range_conflict_write.c
@@ -34,12 +34,14 @@ static void init_query(void) {
     query.right = &qright;
 }
 
+static DB *fake_db = (DB *) 1;
+
 static void setup_tree(void) {
     assert(!lt && !ltm);
     r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
     CKERR(r);
     assert(ltm);
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, fake_db, dbcmp);
     CKERR(r);
     assert(lt);
     init_query();
@@ -47,7 +49,7 @@ static void setup_tree(void) {
 
 static void close_tree(void) {
     assert(lt && ltm);
-    r = toku_lt_close(lt); CKERR(r);
+    toku_lt_remove_db_ref(lt, fake_db);
     r = toku_ltm_close(ltm); CKERR(r);
     lt = NULL;
     ltm = NULL;
diff --git a/src/lock_tree/tests/test_write_request_blocked.c b/src/lock_tree/tests/test_write_request_blocked.c
index 196ff120f9..a780c3f26b 100644
--- a/src/lock_tree/tests/test_write_request_blocked.c
+++ b/src/lock_tree/tests/test_write_request_blocked.c
@@ -37,20 +37,22 @@ int main(int argc, const char *argv[]) {
     r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
     assert(r == 0 && ltm);
 
+    DB *fake_db = (DB *)1;
+
     toku_lock_tree *lt = NULL;
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, fake_db,  dbcmp);
     assert(r == 0 && lt);
 
     const TXNID txn_a = 1;
     const TXNID txn_b = 2;
 
     DBT key_l; dbt_init(&key_l, "L", 1);
-    toku_lock_request a_w_l; toku_lock_request_init(&a_w_l, (DB *)1, txn_a, &key_l, &key_l, LOCK_REQUEST_WRITE);
+    toku_lock_request a_w_l; toku_lock_request_init(&a_w_l, fake_db, txn_a, &key_l, &key_l, LOCK_REQUEST_WRITE);
     r = toku_lock_request_start(&a_w_l, lt, false); assert(r == 0); 
     assert(a_w_l.state == LOCK_REQUEST_COMPLETE && a_w_l.complete_r == 0);
     toku_lock_request_destroy(&a_w_l);
 
-    toku_lock_request b_w_l; toku_lock_request_init(&b_w_l, (DB *)1, txn_b, &key_l, &key_l, LOCK_REQUEST_WRITE);
+    toku_lock_request b_w_l; toku_lock_request_init(&b_w_l, fake_db, txn_b, &key_l, &key_l, LOCK_REQUEST_WRITE);
     r = toku_lock_request_start(&b_w_l, lt, false); assert(r != 0); 
     assert(b_w_l.state == LOCK_REQUEST_PENDING);
 
@@ -60,7 +62,7 @@ int main(int argc, const char *argv[]) {
     r = toku_lt_unlock_txn(lt, txn_b);  assert(r == 0);
 
     // shutdown 
-    r = toku_lt_close(lt); assert(r == 0);
+    toku_lt_remove_db_ref(lt, fake_db);
     r = toku_ltm_close(ltm); assert(r == 0);
 
     return 0;
diff --git a/src/lock_tree/tests/test_wrw.c b/src/lock_tree/tests/test_wrw.c
index b290580596..f68a134414 100644
--- a/src/lock_tree/tests/test_wrw.c
+++ b/src/lock_tree/tests/test_wrw.c
@@ -36,23 +36,25 @@ int main(int argc, const char *argv[]) {
     r = toku_ltm_create(&ltm, max_locks, max_lock_memory, dbpanic);
     assert(r == 0 && ltm);
 
+    DB *fake_db = (DB *) 1;
+
     toku_lock_tree *lt = NULL;
-    r = toku_lt_create(&lt, ltm, dbcmp);
+    r = toku_ltm_get_lt(ltm, &lt, (DICTIONARY_ID){1}, fake_db, dbcmp);
     assert(r == 0 && lt);
 
     const TXNID txn_a = 1;
     DBT key_l; dbt_init(&key_l, "L", 1);
-    toku_lock_request a_w_l; toku_lock_request_init(&a_w_l, (DB *)1, txn_a, &key_l, &key_l, LOCK_REQUEST_WRITE);
+    toku_lock_request a_w_l; toku_lock_request_init(&a_w_l, fake_db, txn_a, &key_l, &key_l, LOCK_REQUEST_WRITE);
     r = toku_lock_request_start(&a_w_l, lt, false); assert(r == 0); 
     assert(a_w_l.state == LOCK_REQUEST_COMPLETE && a_w_l.complete_r == 0);
     toku_lock_request_destroy(&a_w_l);
 
-    toku_lock_request a_r_l; toku_lock_request_init(&a_r_l, (DB *)1, txn_a, &key_l, &key_l, LOCK_REQUEST_READ);
+    toku_lock_request a_r_l; toku_lock_request_init(&a_r_l, fake_db, txn_a, &key_l, &key_l, LOCK_REQUEST_READ);
     r = toku_lock_request_start(&a_r_l, lt, false); assert(r == 0); 
     assert(a_r_l.state == LOCK_REQUEST_COMPLETE && a_r_l.complete_r == 0);
     toku_lock_request_destroy(&a_r_l);
 
-    toku_lock_request a_w_l_2; toku_lock_request_init(&a_w_l_2, (DB *)1, txn_a, &key_l, &key_l, LOCK_REQUEST_WRITE);
+    toku_lock_request a_w_l_2; toku_lock_request_init(&a_w_l_2, fake_db, txn_a, &key_l, &key_l, LOCK_REQUEST_WRITE);
     r = toku_lock_request_start(&a_w_l_2, lt, false); assert(r == 0); 
     assert(a_w_l_2.state == LOCK_REQUEST_COMPLETE && a_w_l_2.complete_r == 0);
     toku_lock_request_destroy(&a_w_l_2);
@@ -60,7 +62,7 @@ int main(int argc, const char *argv[]) {
     r = toku_lt_unlock_txn(lt, txn_a);  assert(r == 0);
 
     // shutdown 
-    r = toku_lt_close(lt); assert(r == 0);
+    toku_lt_remove_db_ref(lt, fake_db);
     r = toku_ltm_close(ltm); assert(r == 0);
 
     return 0;
-- 
2.30.9