Commit 902b8bb9 authored by Yoni Fogel's avatar Yoni Fogel

Closes #477

created two versions of the lock tree, distinguished by -DTOKU_RT_NOOVERLAPS
modified rth iterator to provide hash key

git-svn-id: file:///svn/tokudb@2588 c7de825b-a66e-492c-adef-691d508d4ae1
parent 25cb6d4b
......@@ -386,21 +386,21 @@ inline static int __toku_lt_meets(toku_lock_tree* tree, toku_range* query,
/*
Determines whether 'query' meets 'rt' at txn2 not equal to txn.
This function supports overlapping trees with heterogenous transactions,
but queries must be a single point.
This function supports all range trees, but queries must be a single point.
Uses the standard definition of 'query' meets 'tree' at 'data' from the
design document.
*/
inline static int __toku_lt_meets_peer(toku_lock_tree* tree, toku_range* query,
toku_range_tree* rt, DB_TXN* self, BOOL* met) {
toku_range_tree* rt, BOOL is_homogenous,
DB_TXN* self, BOOL* met) {
assert(tree && query && rt && self && met);
assert(query->left == query->right);
const u_int32_t query_size = 2;
toku_range buffer[query_size];
u_int32_t buflen = query_size;
const u_int32_t query_size = is_homogenous ? 1 : 2;
toku_range buffer[2];
u_int32_t buflen = query_size;
toku_range* buf = &buffer[0];
u_int32_t numfound;
u_int32_t numfound;
int r;
r = toku_rt_find(rt, query, query_size, &buf, &buflen, &numfound);
......@@ -621,8 +621,10 @@ inline static int __toku_consolidate(toku_lock_tree* tree,
BOOL alloc_right = TRUE;
toku_range_tree* selfread;
assert(tree && to_insert && txn);
#if !defined(TOKU_RT_NOOVERLAPS)
toku_range_tree* mainread = tree->mainread;
assert(mainread);
#endif
/* Find the self read tree */
r = __toku_lt_selfread(tree, txn, &selfread);
if (r!=0) return r;
......@@ -651,8 +653,10 @@ inline static int __toku_consolidate(toku_lock_tree* tree,
/* ... and mainread.
Growth direction: if we had no overlaps, the next line
should be commented out */
#if !defined(TOKU_RT_NOOVERLAPS)
r = __toku_lt_delete_overlapping_ranges(tree, mainread, numfound);
if (r!=0) return __toku_lt_panic(tree, r);
#endif
/* Free all the points from ranges in tree->buf[0]..tree->buf[numfound-1] */
__toku_lt_free_points(tree, to_insert, numfound, NULL);
/* We don't necessarily need to panic after here unless numfound > 0
......@@ -660,13 +664,16 @@ inline static int __toku_consolidate(toku_lock_tree* tree,
/* Insert extreme range into selfread. */
/* VL */
r = toku_rt_insert(selfread, to_insert);
#if !defined(TOKU_RT_NOOVERLAPS)
int r2;
if (0) { died2: r2 = toku_rt_delete(selfread, to_insert);
if (r2!=0) return __toku_lt_panic(tree, r2); goto died1; }
#endif
if (r!=0) {
/* If we deleted/merged anything, this is a panic situation. */
if (numfound) return __toku_lt_panic(tree, TOKU_LT_INCONSISTENT);
goto died1; }
#if !defined(TOKU_RT_NOOVERLAPS)
/* Insert extreme range into mainread. */
assert(tree->mainread);
r = toku_rt_insert(tree->mainread, to_insert);
......@@ -674,6 +681,7 @@ inline static int __toku_consolidate(toku_lock_tree* tree,
/* If we deleted/merged anything, this is a panic situation. */
if (numfound) return __toku_lt_panic(tree, TOKU_LT_INCONSISTENT);
goto died2; }
#endif
__toku_lt_range_incr(tree, numfound);
return 0;
}
......@@ -944,11 +952,15 @@ int toku_lt_create(toku_lock_tree** ptree, DB* db, BOOL duplicates,
tmp_tree->malloc = user_malloc;
tmp_tree->free = user_free;
tmp_tree->realloc = user_realloc;
#if defined(TOKU_RT_NOOVERLAPS)
if (0) { died2: goto died1; }
#else
r = toku_rt_create(&tmp_tree->mainread,
__toku_lt_point_cmp, __toku_lt_txn_cmp, TRUE,
user_malloc, user_free, user_realloc);
if (0) { died2: toku_rt_close(tmp_tree->mainread); goto died1; }
if (r!=0) goto died1;
#endif
r = toku_rt_create(&tmp_tree->borderwrite,
__toku_lt_point_cmp, __toku_lt_txn_cmp, FALSE,
user_malloc, user_free, user_realloc);
......@@ -969,8 +981,10 @@ int toku_lt_close(toku_lock_tree* tree) {
if (!tree) return EINVAL;
int r;
int r2 = 0;
#if !defined(TOKU_RT_NOOVERLAPS)
r = toku_rt_close(tree->mainread);
if (r!=0) r2 = r;
#endif
r = toku_rt_close(tree->borderwrite);
if (!r2 && r!=0) r2 = r;
......@@ -1043,13 +1057,39 @@ int toku_lt_acquire_range_read_lock(toku_lock_tree* tree, DB_TXN* txn,
return __toku_consolidate(tree, &query, &to_insert, txn);
}
static int __toku_lt_write_point_conflicts_reads(toku_lock_tree* tree,
DB_TXN* txn, toku_range* query) {
int r = 0;
BOOL met = FALSE;
#if defined(TOKU_RT_NOOVERLAPS)
toku_rth_start_scan(tree->rth);
toku_rt_forest* forest;
while ((forest = toku_rth_next(tree->rth)) != NULL) {
if (forest->self_read != NULL && forest->hash_key != txn) {
r = __toku_lt_meets_peer(tree, query, forest->self_read, TRUE, txn,
&met);
if (r!=0) goto cleanup;
if (met) { r = DB_LOCK_DEADLOCK; goto cleanup; }
}
}
#else
toku_range_tree* mainread = tree->mainread; assert(mainread);
r = __toku_lt_meets_peer(tree, query, mainread, FALSE, txn, &met);
if (r!=0) goto cleanup;
if (met) { r = DB_LOCK_DEADLOCK; goto cleanup; }
#endif
r = 0;
cleanup:
return r;
}
int toku_lt_acquire_write_lock(toku_lock_tree* tree, DB_TXN* txn,
const DBT* key, const DBT* data) {
int r;
toku_point endpoint;
toku_range query;
BOOL dominated;
toku_range_tree* mainread;
r = __toku_lt_preprocess(tree, txn, key, &data,
key, &data,
......@@ -1061,11 +1101,8 @@ int toku_lt_acquire_write_lock(toku_lock_tree* tree, DB_TXN* txn,
__toku_lt_ifexist_selfwrite(tree, txn), &dominated);
if (r || dominated) return r;
/* else if K meets mainread at 'txn2' then return failure */
BOOL met;
mainread = tree->mainread; assert(mainread);
r = __toku_lt_meets_peer(tree, &query, mainread, txn, &met);
if (r!=0) return r;
if (met) return DB_LOCK_DEADLOCK;
r = __toku_lt_write_point_conflicts_reads(tree, txn, &query);
if (r!=0) return r;
/*
else if 'K' meets borderwrite at 'peer' ('peer'!='txn') &&
'K' meets selfwrite('peer') then return failure.
......
......@@ -55,7 +55,7 @@ toku_rt_forest* toku_rth_find(toku_rth* table, DB_TXN* key) {
uint32 index = __toku_rth_hash(table, key);
toku_rth_elt* element = table->table[index];
while (element && element->key != key) element = element->next;
while (element && element->value.hash_key != key) element = element->next;
return element ? &element->value : NULL;
}
......@@ -102,7 +102,7 @@ void toku_rth_delete(toku_rth* table, DB_TXN* key) {
/* Elements of the right hash must exist. */
assert(element);
/* Case where it is the first element. */
if (element->key == key) {
if (element->value.hash_key == key) {
table->table[index] = element->next;
table->free(element);
table->num_keys--;
......@@ -114,7 +114,7 @@ void toku_rth_delete(toku_rth* table, DB_TXN* key) {
assert(element);
prev = element;
element = element->next;
} while (element->key != key);
} while (element->value.hash_key != key);
/* Must be found. */
assert(element);
prev->next = element->next;
......@@ -134,7 +134,7 @@ int toku_rth_insert(toku_rth* table, DB_TXN* key) {
toku_rth_elt* element = (toku_rth_elt*)table->malloc(sizeof(*element));
if (!element) return errno;
memset(element, 0, sizeof(*element));
element->key = key;
element->value.hash_key = key;
element->next = table->table[index];
table->table[index] = element;
table->num_keys++;
......
......@@ -20,13 +20,13 @@ typedef u_int32_t uint32;
typedef struct __toku_rt_forest toku_rt_forest;
struct __toku_rt_forest {
DB_TXN* hash_key;
toku_range_tree* self_read;
toku_range_tree* self_write;
};
typedef struct __toku_rth_elt toku_rth_elt;
struct __toku_rth_elt {
DB_TXN* key;
toku_rt_forest value;
toku_rth_elt* next;
};
......
......@@ -44,17 +44,24 @@ default: check
all: make_libs $(ALL_TESTS)
#check: check.lin check.tlog check.log
check: check.lin #check.tlog check.log
@ echo ok
check: check.lin check.tlin #check.tlog check.log
@ echo $@ ok
tests.lin: make_libs $(LIN_TESTS)
@ echo $@ ok
check.lin: make_libs $(RUN_LIN_TESTS)
@ echo $@ ok
tests.tlin: make_libs $(TLIN_TESTS)
@ echo $@ ok
check.tlin: make_libs $(RUN_TLIN_TESTS)
@ echo $@ ok
tests.tlog: make_libs $(TLOG_TESTS)
@ echo $@ ok
check.tlog: make_libs $(RUN_TLOG_TESTS)
@ echo $@ ok
tests.log: make_libs $(LOG_TESTS)
@ echo $@ ok
check.log: make_libs $(RUN_LOG_TESTS)
@ echo $@ ok
# Need these rule so that Make knows about all the file names
.PHONY: %.linrun %.tlinrun %.tlogrun %.logrun %.run
......@@ -102,17 +109,17 @@ LT_BINS = ../lth.o ../rth.o
LT_OVERLAP = ../locktree_global_readset.o
LT_NOOVERLAP = ../locktree_no_global_readset.o
LT_LINEAR = $(LT_OVERLAP) $(LT_BINS) $(RT_LINEAR_BINS)
LT_TLINEAR = $(LT_NOOVERLAP) $(LT_BINS) $(RT_TLINEAR_BINS) -DTOKU_RT_NOOVERLAPS
LT_TLOG = $(LT_NOOVERLAP) $(LT_BINS) $(RT_TLOG_BINS) -DTOKU_RT_NOOVERLAPS
LT_TLINEAR = $(LT_NOOVERLAP) $(LT_BINS) $(RT_TLINEAR_BINS)
LT_TLOG = $(LT_NOOVERLAP) $(LT_BINS) $(RT_TLOG_BINS)
LT_LOG = $(LT_OVERLAP) $(LT_BINS) $(RT_LOG_BINS)
%.lin: %.c ../locktree.h test.h
%.lin: %.c ../locktree.h test.h $(LT_LINEAR)
cc -DDIR=\"dir.$<.lin\" $(CPPFLAGS) $(CFLAGS) $< -o $@ $(LT_LINEAR)
%.tlin: %.c ../locktree.h test.h
cc -DDIR=\"dir.$<.tlin\" $(CPPFLAGS) $(CFLAGS) $< -o $@ $(LT_TLINEAR)
%.tlog: %.c ../locktree.h test.h
cc -DDIR=\"dir.$<.tlog\" $(CPPFLAGS) $(CFLAGS) $< -o $@ $(LT_TLOG)
%.log: %.c ../locktree.h test.h
%.tlin: %.c ../locktree.h test.h $(LT_TLINEAR)
cc -DDIR=\"dir.$<.tlin\" $(CPPFLAGS) $(CFLAGS) $< -o $@ $(LT_TLINEAR) -DTOKU_RT_NOOVERLAPS
%.tlog: %.c ../locktree.h test.h $(LT_TLOG)
cc -DDIR=\"dir.$<.tlog\" $(CPPFLAGS) $(CFLAGS) $< -o $@ $(LT_TLOG) -DTOKU_RT_NOOVERLAPS
%.log: %.c ../locktree.h test.h $(LT_LOG)
cc -DDIR=\"dir.$<.log\" $(CPPFLAGS) $(CFLAGS) $< -o $@ $(LT_LOG)
.PHONY: make_libs
......
......@@ -37,15 +37,20 @@ default: check
all: make_libs $(ALL_TESTS)
#check: check.lin check.tlog check.log
check: check.lin #check.tlog check.log
@ echo ok
@ echo $@ ok
tests.lin: make_libs $(LIN_TESTS)
@ echo $@ ok
check.lin: make_libs $(RUN_LIN_TESTS)
@ echo $@ ok
tests.tlog: make_libs $(TLOG_TESTS)
@ echo $@ ok
check.tlog: make_libs $(RUN_TLOG_TESTS)
@ echo $@ ok
tests.log: make_libs $(LOG_TESTS)
@ echo $@ ok
check.log: make_libs $(RUN_LOG_TESTS)
@ echo $@ ok
# Need these rule so that Make knows about all the file names
.PHONY: %.linrun %.logrun %.run %.tlogrun
......@@ -83,11 +88,11 @@ LINEAR_BINS = ../linear.o
TLOG_BINS = ../log_nooverlap.o
LOG_BINS = ../log.o
%.lin: %.c ../rangetree.h test.h
%.lin: %.c ../rangetree.h test.h $(LINEAR_BINS)
cc -DDIR=\"dir.$<.lin\" $(CFLAGS) $(CPPFLAGS) $< -o $@ $(LINEAR_BINS)
%.tlog: %.c ../rangetree.h test.h
%.tlog: %.c ../rangetree.h test.h $(TLOG_BINS)
cc -DDIR=\"dir.$<.log\" $(CFLAGS) $(CPPFLAGS) $< -o $@ $(TLOG_BINS)
%.log: %.c ../rangetree.h test.h
%.log: %.c ../rangetree.h test.h $(LOG_BINS)
cc -DDIR=\"dir.$<.log\" $(CFLAGS) $(CPPFLAGS) $< -o $@ $(LOG_BINS)
.PHONY: make_libs
......
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