Commit a465c2a2 authored by Rich Prohaska's avatar Rich Prohaska Committed by Yoni Fogel
Browse files

#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
parent 9b1ff91d
Loading
Loading
Loading
Loading
+24 −21
Original line number Diff line number Diff line
@@ -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);
        }
        r = lt_free_contents(tree, selfwrite);
        if (r != 0) 
            return lt_panic(tree, r);
+4 −3
Original line number Diff line number Diff line
@@ -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;
+4 −4
Original line number Diff line number Diff line
@@ -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;
+4 −2
Original line number Diff line number Diff line
@@ -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;
+4 −3
Original line number Diff line number Diff line
@@ -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;
Loading