Commit 3bafeecf authored by Yoni Fogel's avatar Yoni Fogel

Closes #567

Merge all of ticket 567 into trunk

git-svn-id: file:///svn/tokudb@3134 c7de825b-a66e-492c-adef-691d508d4ae1
parent 57004ac0
...@@ -2,19 +2,25 @@ ...@@ -2,19 +2,25 @@
// FNV Hash: From an idea sent by Glenn Fowler and Phong Vo to the IEEE POSIX 1003.2 committee. Landon Curt Noll improved it. // FNV Hash: From an idea sent by Glenn Fowler and Phong Vo to the IEEE POSIX 1003.2 committee. Landon Curt Noll improved it.
// See: http://isthe.com/chongo/tech/comp/fnv/ // See: http://isthe.com/chongo/tech/comp/fnv/
static inline unsigned int hash_key (const unsigned char *key, unsigned long keylen) { static inline u_int32_t hash_key_extend(u_int32_t initial_hash,
unsigned long i; const unsigned char *key,
unsigned int hash=0; size_t keylen) {
size_t i;
u_int32_t hash = initial_hash;
for (i=0; i<keylen; i++, key++) { for (i=0; i<keylen; i++, key++) {
hash *= 16777619; hash *= 16777619;
// GCC 4.1.2 -O2 and -O3 translates the following shifts back into the multiply shown on the line above here. // GCC 4.1.2 -O2 and -O3 translates the following shifts back into the multiply shown on the line above here.
// So much for optimizing this multiplication... // So much for optimizing this multiplication...
//hash += (hash<<1) + (hash<<4) + (hash<<7) + (hash<<8) + (hash<<24); //hash += (hash<<1) + (hash<<4) + (hash<<7) + (hash<<8) + (hash<<24);
hash ^= *key; hash ^= *key;
} }
return hash; return hash;
} }
static inline u_int32_t hash_key(const unsigned char *key, size_t keylen) {
return hash_key_extend(0, key, keylen);
}
#if 0 #if 0
static unsigned int hash_key (const char *key, ITEMLEN keylen) { static unsigned int hash_key (const char *key, ITEMLEN keylen) {
/* From Sedgewick. There are probably better hash functions. */ /* From Sedgewick. There are probably better hash functions. */
......
...@@ -51,7 +51,7 @@ ydb.o: ../include/db.h ../newbrt/cachetable.h ../newbrt/brt.h ../newbrt/log.c ...@@ -51,7 +51,7 @@ ydb.o: ../include/db.h ../newbrt/cachetable.h ../newbrt/brt.h ../newbrt/log.c
DBBINS = ydb.o errors.o elocks.o ../newbrt/brt.o ../newbrt/brt-serialize.o ../newbrt/brt-verify.o ../newbrt/cachetable.o ../newbrt/fifo.o ../newbrt/key.o ../newbrt/memory.o ../newbrt/mempool.o ../newbrt/pma.o ../newbrt/ybt.o ../newbrt/primes.o ../newbrt/log.o ../newbrt/fingerprint.o ../newbrt/log_code.o ../newbrt/roll.o ../newbrt/toku_assert.o ../newbrt/recover.o DBBINS = ydb.o errors.o elocks.o ../newbrt/brt.o ../newbrt/brt-serialize.o ../newbrt/brt-verify.o ../newbrt/cachetable.o ../newbrt/fifo.o ../newbrt/key.o ../newbrt/memory.o ../newbrt/mempool.o ../newbrt/pma.o ../newbrt/ybt.o ../newbrt/primes.o ../newbrt/log.o ../newbrt/fingerprint.o ../newbrt/log_code.o ../newbrt/roll.o ../newbrt/toku_assert.o ../newbrt/recover.o
RANGETREE_BINS = range_tree/rangetree.o range_tree/tokuredblack.o RANGETREE_BINS = range_tree/rangetree.o range_tree/tokuredblack.o
LOCKTREE_BINS = lock_tree/locktree.o lock_tree/rth.o lock_tree/lth.o $(RANGETREE_BINS) LOCKTREE_BINS = lock_tree/locktree.o lock_tree/rth.o lock_tree/lth.o lock_tree/idlth.o lock_tree/db_id.o $(RANGETREE_BINS)
$(LIBRARY): $(DBBINS) $(LOCKTREE_BINS) $(LIBRARY): $(DBBINS) $(LOCKTREE_BINS)
......
...@@ -31,7 +31,7 @@ LT_TLOG = $(LT_NOOVERLAP) ...@@ -31,7 +31,7 @@ LT_TLOG = $(LT_NOOVERLAP)
LT_LOG = $(LT_OVERLAP) LT_LOG = $(LT_OVERLAP)
LT_BINS=$(LT_OVERLAP) $(LT_NOOVERLAP) locktree.o LT_BINS=$(LT_OVERLAP) $(LT_NOOVERLAP) locktree.o
BINS=rth.o lth.o BINS=rth.o lth.o idlth.o db_id.o
.PHONY: install logformat range_tree .PHONY: install logformat range_tree
install: range_tree $(BINS) $(LT_BINS) install: range_tree $(BINS) $(LT_BINS)
...@@ -45,8 +45,6 @@ clean: ...@@ -45,8 +45,6 @@ clean:
rm -rf *.gcno *.gcda *.gcov rm -rf *.gcno *.gcda *.gcov
cd tests && make clean cd tests && make clean
BINS = locktree.o rth.o lth.o
locktree.o: $(LT_TLOG) locktree.o: $(LT_TLOG)
cp $< $@ cp $< $@
......
/* -*- mode: C; c-basic-offset: 4 -*- */
#ident "Copyright (c) 2007-8 Tokutek Inc. All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
#include <errno.h>
#include <assert.h>
#include <string.h>
#include <limits.h>
#include <memory.h>
#include <hashfun.h>
#include "db_id.h"
BOOL toku_db_id_equals(const toku_db_id* a, const toku_db_id* b) {
assert(a && b);
return a == b ||
(a->saved_hash == b->saved_hash &&
!strcmp(a->absolute_path, b->absolute_path) &&
!strcmp(a->sub_database_name, b->sub_database_name));
}
void toku_db_id_add_ref(toku_db_id* db_id) {
assert(db_id);
assert(db_id->ref_count > 0);
db_id->ref_count++;
}
static void toku_db_id_close(toku_db_id* db_id) {
toku_free(db_id->absolute_path);
toku_free(db_id->sub_database_name);
toku_free(db_id);
}
void toku_db_id_remove_ref(toku_db_id* db_id) {
assert(db_id);
assert(db_id->ref_count > 0);
db_id->ref_count--;
if (db_id->ref_count > 0) { return; }
toku_db_id_close(db_id);
}
int toku_db_id_create(toku_db_id** pdbid, const char* path,
const char* sub_database_name) {
int r = ENOSYS;
assert(sub_database_name);
toku_db_id* db_id = NULL;
db_id = (toku_db_id *)toku_malloc(sizeof(*db_id));
if (!db_id) { r = ENOMEM; goto cleanup; }
memset(db_id, 0, sizeof(*db_id));
db_id->absolute_path = (char *)toku_malloc((PATH_MAX + 1) * sizeof(char));
if (!db_id->absolute_path) { r = ENOMEM; goto cleanup; }
/* TODO: BUG! Buffer overflow if the path > PATH_MAX. */
if (realpath(path, db_id->absolute_path) == NULL) {
r = errno;
goto cleanup;
}
char* tmp = (char*)toku_realloc(db_id->absolute_path,
(strlen(db_id->absolute_path) + 1) * sizeof(char));
if (!tmp) { r = ENOMEM; goto cleanup; }
db_id->absolute_path = tmp;
db_id->sub_database_name = toku_strdup(sub_database_name);
if (!db_id->sub_database_name) { r = ENOMEM; goto cleanup; }
db_id->saved_hash = hash_key((unsigned char*)db_id->absolute_path,
strlen(db_id->absolute_path));
db_id->saved_hash = hash_key_extend(db_id->saved_hash,
(unsigned char*)db_id->sub_database_name,
strlen(db_id->sub_database_name));
db_id->ref_count = 1;
*pdbid = db_id;
r = 0;
cleanup:
if (r != 0) {
if (db_id != NULL) {
if (db_id->absolute_path) { toku_free(db_id->absolute_path); }
if (db_id->sub_database_name) { toku_free(db_id->sub_database_name); }
toku_free(db_id);
}
}
return r;
}
/* -*- mode: C; c-basic-offset: 4 -*- */
#ident "Copyright (c) 2007-8 Tokutek Inc. All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
#include <brttypes.h>
#if !defined(TOKU_DB_ID_H)
#define TOKU_DB_ID_H
typedef struct __toku_db_id {
char* absolute_path;
char* sub_database_name;
u_int32_t saved_hash;
u_int32_t ref_count;
} toku_db_id;
/* db_id methods */
int toku_db_id_create(toku_db_id** pdbid, const char* path,
const char* sub_database_name);
BOOL toku_db_id_equals(const toku_db_id* a, const toku_db_id* b);
void toku_db_id_add_ref(toku_db_id* db_id);
void toku_db_id_remove_ref(toku_db_id* db_id);
#endif /* #if !defined(TOKU_DB_ID_H) */
/* -*- mode: C; c-basic-offset: 4 -*- */
#ident "Copyright (c) 2007-8 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."
/**
\file hash_idlth.h
\brief Hash idlth
*/
#include <idlth.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
/* TODO: investigate whether we can remove the user_memory functions */
/* TODO: reallocate the hash idlth if it grows too big. Perhaps, use toku_get_prime in newbrt/primes.c */
const u_int32_t __toku_idlth_init_size = 521;
static inline u_int32_t toku__idlth_hash(toku_idlth* idlth, toku_db_id* key) {
size_t tmp = key->saved_hash;
return tmp % idlth->num_buckets;
}
static inline void toku__invalidate_scan(toku_idlth* idlth) {
idlth->iter_is_valid = FALSE;
}
int toku_idlth_create(toku_idlth** pidlth,
void* (*user_malloc) (size_t),
void (*user_free) (void*),
void* (*user_realloc)(void*, size_t)) {
int r = ENOSYS;
assert(pidlth && user_malloc && user_free && user_realloc);
toku_idlth* tmp = NULL;
tmp = (toku_idlth*)user_malloc(sizeof(*tmp));
if (!tmp) { r = ENOMEM; goto cleanup; }
memset(tmp, 0, sizeof(*tmp));
tmp->malloc = user_malloc;
tmp->free = user_free;
tmp->realloc = user_realloc;
tmp->num_buckets = __toku_idlth_init_size;
tmp->buckets = (toku_idlth_elt*)
tmp->malloc(tmp->num_buckets * sizeof(*tmp->buckets));
if (!tmp->buckets) { r = ENOMEM; goto cleanup; }
memset(tmp->buckets, 0, tmp->num_buckets * sizeof(*tmp->buckets));
toku__invalidate_scan(tmp);
tmp->iter_head.next_in_iteration = &tmp->iter_head;
tmp->iter_head.prev_in_iteration = &tmp->iter_head;
*pidlth = tmp;
r = 0;
cleanup:
if (r != 0) {
if (tmp) {
if (tmp->buckets) { user_free(tmp->buckets); }
user_free(tmp);
}
}
return r;
}
toku_lt_map* toku_idlth_find(toku_idlth* idlth, toku_db_id* key) {
assert(idlth);
u_int32_t index = toku__idlth_hash(idlth, key);
toku_idlth_elt* head = &idlth->buckets[index];
toku_idlth_elt* current = head->next_in_bucket;
while (current) {
if (toku_db_id_equals(current->value.db_id, key)) { break; }
current = current->next_in_bucket;
}
return current ? &current->value : NULL;
}
void toku_idlth_start_scan(toku_idlth* idlth) {
assert(idlth);
idlth->iter_curr = &idlth->iter_head;
idlth->iter_is_valid = TRUE;
}
static inline toku_idlth_elt* toku__idlth_next(toku_idlth* idlth) {
assert(idlth);
assert(idlth->iter_is_valid);
idlth->iter_curr = idlth->iter_curr->next_in_iteration;
idlth->iter_is_valid = idlth->iter_curr != &idlth->iter_head;
return idlth->iter_curr;
}
toku_lt_map* toku_idlth_next(toku_idlth* idlth) {
assert(idlth);
toku_idlth_elt* next = toku__idlth_next(idlth);
return idlth->iter_curr != &idlth->iter_head ? &next->value : NULL;
}
/* Element MUST exist. */
void toku_idlth_delete(toku_idlth* idlth, toku_db_id* key) {
assert(idlth);
toku__invalidate_scan(idlth);
/* Must have elements. */
assert(idlth->num_keys);
u_int32_t index = toku__idlth_hash(idlth, key);
toku_idlth_elt* head = &idlth->buckets[index];
toku_idlth_elt* prev = head;
toku_idlth_elt* current = prev->next_in_bucket;
while (current != NULL) {
if (toku_db_id_equals(current->value.db_id, key)) { break; }
prev = current;
current = current->next_in_bucket;
}
/* Must be found. */
assert(current);
current->prev_in_iteration->next_in_iteration = current->next_in_iteration;
current->next_in_iteration->prev_in_iteration = current->prev_in_iteration;
prev->next_in_bucket = current->next_in_bucket;
toku_db_id_remove_ref(current->value.db_id);
idlth->free(current);
idlth->num_keys--;
return;
}
/* Will allow you to insert it over and over. You need to keep track. */
int toku_idlth_insert(toku_idlth* idlth, toku_db_id* key) {
int r = ENOSYS;
assert(idlth);
toku__invalidate_scan(idlth);
u_int32_t index = toku__idlth_hash(idlth, key);
/* Allocate a new one. */
toku_idlth_elt* element = (toku_idlth_elt*)idlth->malloc(sizeof(*element));
if (!element) { r = ENOMEM; goto cleanup; }
memset(element, 0, sizeof(*element));
element->value.db_id = key;
toku_db_id_add_ref(element->value.db_id);
element->next_in_iteration = idlth->iter_head.next_in_iteration;
element->prev_in_iteration = &idlth->iter_head;
element->next_in_iteration->prev_in_iteration = element;
element->prev_in_iteration->next_in_iteration = element;
element->next_in_bucket = idlth->buckets[index].next_in_bucket;
idlth->buckets[index].next_in_bucket = element;
idlth->num_keys++;
r = 0;
cleanup:
return r;
}
static inline void toku__idlth_clear(toku_idlth* idlth, BOOL clean) {
assert(idlth);
toku_idlth_elt* element;
toku_idlth_elt* head = &idlth->iter_head;
toku_idlth_elt* next = NULL;
toku_idlth_start_scan(idlth);
next = toku__idlth_next(idlth);
while (next != head) {
element = next;
next = toku__idlth_next(idlth);
toku_db_id_remove_ref(element->value.db_id);
idlth->free(element);
}
/* If clean is true, then we want to restore it to 'just created' status.
If we are closing the tree, we don't need to do that restoration. */
if (!clean) { return; }
memset(idlth->buckets, 0, idlth->num_buckets * sizeof(*idlth->buckets));
toku__invalidate_scan(idlth);
idlth->iter_head.next_in_iteration = &idlth->iter_head;
idlth->iter_head.prev_in_iteration = &idlth->iter_head;
idlth->num_keys = 0;
}
void toku_idlth_clear(toku_idlth* idlth) {
toku__idlth_clear(idlth, TRUE);
}
void toku_idlth_close(toku_idlth* idlth) {
assert(idlth);
toku__idlth_clear(idlth, FALSE);
idlth->free(idlth->buckets);
idlth->free(idlth);
}
BOOL toku_idlth_is_empty(toku_idlth* idlth) {
assert(idlth);
/* Verify consistency. */
assert((idlth->num_keys == 0) ==
(idlth->iter_head.next_in_iteration == &idlth->iter_head));
assert((idlth->num_keys == 0) ==
(idlth->iter_head.prev_in_iteration == &idlth->iter_head));
return idlth->num_keys == 0;
}
/* -*- mode: C; c-basic-offset: 4 -*- */
#ident "Copyright (c) 2007-8 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."
#if !defined(TOKU_IDLTH_H)
#define TOKU_IDLTH_H
/**
\file hash_table.h
\brief Hash table
*/
//Defines BOOL data type.
#include <db.h>
#include <brttypes.h>
#include <rangetree.h>
#include <db_id.h>
#if !defined(TOKU_LOCKTREE_DEFINE)
#define TOKU_LOCKTREE_DEFINE
typedef struct __toku_lock_tree toku_lock_tree;
#endif
typedef struct __toku_lt_map toku_lt_map;
struct __toku_lt_map {
toku_db_id* db_id;
toku_lock_tree* tree;
};
typedef struct __toku_idlth_elt toku_idlth_elt;
struct __toku_idlth_elt {
toku_lt_map value;
toku_idlth_elt* next_in_bucket;
toku_idlth_elt* next_in_iteration;
toku_idlth_elt* prev_in_iteration;
};
typedef struct __toku_idlth toku_idlth;
struct __toku_idlth {
toku_idlth_elt* buckets;
u_int32_t num_buckets;
u_int32_t num_keys;
toku_idlth_elt iter_head;
toku_idlth_elt* iter_curr;
BOOL iter_is_valid;
/** The user malloc function */
void* (*malloc) (size_t);
/** The user free function */
void (*free) (void*);
/** The user realloc function */
void* (*realloc)(void*, size_t);
};
int toku_idlth_create(toku_idlth** ptable,
void* (*user_malloc) (size_t),
void (*user_free) (void*),
void* (*user_realloc)(void*, size_t));
toku_lt_map* toku_idlth_find (toku_idlth* table, toku_db_id* key);
void toku_idlth_start_scan (toku_idlth* table);
toku_lt_map* toku_idlth_next (toku_idlth* table);
void toku_idlth_delete (toku_idlth* table, toku_db_id* key);
void toku_idlth_close (toku_idlth* table);
int toku_idlth_insert (toku_idlth* table, toku_db_id* key);
void toku_idlth_clear (toku_idlth* idlth);
BOOL toku_idlth_is_empty (toku_idlth* idlth);
#endif
This diff is collapsed.
This diff is collapsed.
...@@ -15,9 +15,9 @@ ...@@ -15,9 +15,9 @@
#include <string.h> #include <string.h>
/* TODO: reallocate the hash lth if it grows too big. Perhaps, use toku_get_prime in newbrt/primes.c */ /* TODO: reallocate the hash lth if it grows too big. Perhaps, use toku_get_prime in newbrt/primes.c */
const uint32 __toku_lth_init_size = 521; const u_int32_t __toku_lth_init_size = 521;
static inline uint32 toku__lth_hash(toku_lth* lth, toku_lock_tree* key) { static inline u_int32_t toku__lth_hash(toku_lth* lth, toku_lock_tree* key) {
size_t tmp = (size_t)key; size_t tmp = (size_t)key;
return tmp % lth->num_buckets; return tmp % lth->num_buckets;
} }
...@@ -64,7 +64,7 @@ int toku_lth_create(toku_lth** plth, ...@@ -64,7 +64,7 @@ int toku_lth_create(toku_lth** plth,
toku_lock_tree* toku_lth_find(toku_lth* lth, toku_lock_tree* key) { toku_lock_tree* toku_lth_find(toku_lth* lth, toku_lock_tree* key) {
assert(lth && key); assert(lth && key);
uint32 index = toku__lth_hash(lth, key); u_int32_t index = toku__lth_hash(lth, key);
toku_lth_elt* head = &lth->buckets[index]; toku_lth_elt* head = &lth->buckets[index];
toku_lth_elt* current = head->next_in_bucket; toku_lth_elt* current = head->next_in_bucket;
while (current) { while (current) {
...@@ -103,7 +103,7 @@ void toku_lth_delete(toku_lth* lth, toku_lock_tree* key) { ...@@ -103,7 +103,7 @@ void toku_lth_delete(toku_lth* lth, toku_lock_tree* key) {
/* Must have elements. */ /* Must have elements. */
assert(lth->num_keys); assert(lth->num_keys);
uint32 index = toku__lth_hash(lth, key); u_int32_t index = toku__lth_hash(lth, key);
toku_lth_elt* head = &lth->buckets[index]; toku_lth_elt* head = &lth->buckets[index];
toku_lth_elt* prev = head; toku_lth_elt* prev = head;
toku_lth_elt* current = prev->next_in_bucket; toku_lth_elt* current = prev->next_in_bucket;
...@@ -129,7 +129,7 @@ int toku_lth_insert(toku_lth* lth, toku_lock_tree* key) { ...@@ -129,7 +129,7 @@ int toku_lth_insert(toku_lth* lth, toku_lock_tree* key) {
assert(lth && key); assert(lth && key);
toku__invalidate_scan(lth); toku__invalidate_scan(lth);
uint32 index = toku__lth_hash(lth, key); u_int32_t index = toku__lth_hash(lth, key);
/* Allocate a new one. */ /* Allocate a new one. */
toku_lth_elt* element = (toku_lth_elt*)lth->malloc(sizeof(*element)); toku_lth_elt* element = (toku_lth_elt*)lth->malloc(sizeof(*element));
......
...@@ -15,9 +15,9 @@ ...@@ -15,9 +15,9 @@
#include <string.h> #include <string.h>
/* TODO: reallocate the hash rth if it grows too big. Perhaps, use toku_get_prime in newbrt/primes.c */ /* TODO: reallocate the hash rth if it grows too big. Perhaps, use toku_get_prime in newbrt/primes.c */
const uint32 __toku_rth_init_size = 521; const u_int32_t __toku_rth_init_size = 521;
static inline uint32 toku__rth_hash(toku_rth* rth, DB_TXN* key) { static inline u_int32_t toku__rth_hash(toku_rth* rth, TXNID key) {
size_t tmp = (size_t)key; size_t tmp = (size_t)key;
return tmp % rth->num_buckets; return tmp % rth->num_buckets;
} }
...@@ -47,7 +47,7 @@ int toku_rth_create(toku_rth** prth, ...@@ -47,7 +47,7 @@ int toku_rth_create(toku_rth** prth,
memset(tmp->buckets, 0, tmp->num_buckets * sizeof(*tmp->buckets)); memset(tmp->buckets, 0, tmp->num_buckets * sizeof(*tmp->buckets));
toku__invalidate_scan(tmp); toku__invalidate_scan(tmp);
tmp->iter_head.next_in_iteration = &tmp->iter_head; tmp->iter_head.next_in_iteration = &tmp->iter_head;
tmp->iter_head.prev_in_iteration = &tmp->iter_head; tmp->iter_head.prev_in_iteration = &tmp->iter_head;
*prth = tmp; *prth = tmp;
r = 0; r = 0;
...@@ -61,10 +61,10 @@ int toku_rth_create(toku_rth** prth, ...@@ -61,10 +61,10 @@ int toku_rth_create(toku_rth** prth,
return r; return r;
} }
toku_rt_forest* toku_rth_find(toku_rth* rth, DB_TXN* key) { toku_rt_forest* toku_rth_find(toku_rth* rth, TXNID key) {
assert(rth && key); assert(rth);
uint32 index = toku__rth_hash(rth, key); u_int32_t index = toku__rth_hash(rth, key);
toku_rth_elt* head = &rth->buckets[index]; toku_rth_elt* head = &rth->buckets[index];
toku_rth_elt* current = head->next_in_bucket; toku_rth_elt* current = head->next_in_bucket;
while (current) { while (current) {
...@@ -96,14 +96,14 @@ toku_rt_forest* toku_rth_next(toku_rth* rth) { ...@@ -96,14 +96,14 @@ toku_rt_forest* toku_rth_next(toku_rth* rth) {
} }
/* Element MUST exist. */ /* Element MUST exist. */
void toku_rth_delete(toku_rth* rth, DB_TXN* key) { void toku_rth_delete(toku_rth* rth, TXNID key) {
assert(rth && key); assert(rth);
toku__invalidate_scan(rth); toku__invalidate_scan(rth);
/* Must have elements. */ /* Must have elements. */
assert(rth->num_keys); assert(rth->num_keys);
uint32 index = toku__rth_hash(rth, key); u_int32_t index = toku__rth_hash(rth, key);
toku_rth_elt* head = &rth->buckets[index]; toku_rth_elt* head = &rth->buckets[index];
toku_rth_elt* prev = head; toku_rth_elt* prev = head;
toku_rth_elt* current = prev->next_in_bucket; toku_rth_elt* current = prev->next_in_bucket;
...@@ -124,12 +124,12 @@ void toku_rth_delete(toku_rth* rth, DB_TXN* key) { ...@@ -124,12 +124,12 @@ void toku_rth_delete(toku_rth* rth, DB_TXN* key) {
} }
/* Will allow you to insert it over and over. You need to keep track. */ /* Will allow you to insert it over and over. You need to keep track. */
int toku_rth_insert(toku_rth* rth, DB_TXN* key) { int toku_rth_insert(toku_rth* rth, TXNID key) {
int r = ENOSYS; int r = ENOSYS;
assert(rth && key); assert(rth);
toku__invalidate_scan(rth); toku__invalidate_scan(rth);
uint32 index = toku__rth_hash(rth, key); u_int32_t index = toku__rth_hash(rth, key);
/* Allocate a new one. */ /* Allocate a new one. */
toku_rth_elt* element = (toku_rth_elt*)rth->malloc(sizeof(*element)); toku_rth_elt* element = (toku_rth_elt*)rth->malloc(sizeof(*element));
...@@ -150,12 +150,12 @@ int toku_rth_insert(toku_rth* rth, DB_TXN* key) { ...@@ -150,12 +150,12 @@ int toku_rth_insert(toku_rth* rth, DB_TXN* key) {
return r; return r;
} }
void toku_rth_close(toku_rth* rth) { static inline void toku__rth_clear(toku_rth* rth, BOOL clean) {
assert(rth); assert(rth);
toku_rth_elt* element; toku_rth_elt* element;
toku_rth_elt* head = &rth->iter_head; toku_rth_elt* head = &rth->iter_head;
toku_rth_elt* next = NULL; toku_rth_elt* next = NULL;
toku_rth_start_scan(rth); toku_rth_start_scan(rth);
next = toku__rth_next(rth); next = toku__rth_next(rth);
while (next != head) { while (next != head) {
...@@ -163,7 +163,34 @@ void toku_rth_close(toku_rth* rth) { ...@@ -163,7 +163,34 @@ void toku_rth_close(toku_rth* rth) {
next = toku__rth_next(rth); next = toku__rth_next(rth);
rth->free(element); rth->free(element);
} }
/* If clean is true, then we want to restore it to 'just created' status.
If we are closing the tree, we don't need to do that restoration. */
if (!clean) { return; }
memset(rth->buckets, 0, rth->num_buckets * sizeof(*rth->buckets));
toku__invalidate_scan(rth);
rth->iter_head.next_in_iteration = &rth->iter_head;
rth->iter_head.prev_in_iteration = &rth->iter_head;
rth->num_keys = 0;
}
void toku_rth_clear(toku_rth* rth) {
toku__rth_clear(rth, TRUE);
}
void toku_rth_close(toku_rth* rth) {
assert(rth);
toku__rth_clear(rth, FALSE);
rth->free(rth->buckets); rth->free(rth->buckets);
rth->free(rth); rth->free(rth);
} }
BOOL toku_rth_is_empty(toku_rth* rth) {
assert(rth);
/* Verify consistency. */
assert((rth->num_keys == 0) ==
(rth->iter_head.next_in_iteration == &rth->iter_head));
assert((rth->num_keys == 0) ==
(rth->iter_head.prev_in_iteration == &rth->iter_head));
return rth->num_keys == 0;
}
...@@ -16,11 +16,9 @@ ...@@ -16,11 +16,9 @@
#include <brttypes.h> #include <brttypes.h>
#include <rangetree.h> #include <rangetree.h>
typedef u_int32_t uint32;
typedef struct __toku_rt_forest toku_rt_forest; typedef struct __toku_rt_forest toku_rt_forest;
struct __toku_rt_forest { struct __toku_rt_forest {
DB_TXN* hash_key; TXNID hash_key;
toku_range_tree* self_read; toku_range_tree* self_read;
toku_range_tree* self_write; toku_range_tree* self_write;
}; };
...@@ -36,8 +34,8 @@ struct __toku_rth_elt { ...@@ -36,8 +34,8 @@ struct __toku_rth_elt {
typedef struct __toku_rth toku_rth; typedef struct __toku_rth toku_rth;
struct __toku_rth { struct __toku_rth {
toku_rth_elt* buckets; toku_rth_elt* buckets;
uint32 num_buckets; u_int32_t num_buckets;
uint32 num_keys; u_int32_t num_keys;
toku_rth_elt iter_head; toku_rth_elt iter_head;
toku_rth_elt* iter_curr; toku_rth_elt* iter_curr;
BOOL iter_is_valid; BOOL iter_is_valid;
...@@ -54,15 +52,20 @@ int toku_rth_create(toku_rth** ptable, ...@@ -54,15 +52,20 @@ int toku_rth_create(toku_rth** ptable,
void (*user_free) (void*), void (*user_free) (void*),
void* (*user_realloc)(void*, size_t)); void* (*user_realloc)(void*, size_t));
toku_rt_forest* toku_rth_find (toku_rth* table, DB_TXN* key); toku_rt_forest* toku_rth_find (toku_rth* table, TXNID key);
void toku_rth_start_scan (toku_rth* table); void toku_rth_start_scan (toku_rth* table);
toku_rt_forest* toku_rth_next (toku_rth* table); toku_rt_forest* toku_rth_next (toku_rth* table);
void toku_rth_delete (toku_rth* table, DB_TXN* key); void toku_rth_delete (toku_rth* table, TXNID key);
void toku_rth_close (toku_rth* table); void toku_rth_close (toku_rth* table);
int toku_rth_insert (toku_rth* table, DB_TXN* key); int toku_rth_insert (toku_rth* table, TXNID key);
void toku_rth_clear (toku_rth* rth);
BOOL toku_rth_is_empty (toku_rth* rth);
#endif #endif
...@@ -107,7 +107,7 @@ RT_TLINEAR_BINS = ../../range_tree/linear.o ...@@ -107,7 +107,7 @@ RT_TLINEAR_BINS = ../../range_tree/linear.o
RT_TLOG_BINS = ../../range_tree/log_nooverlap.o ../../range_tree/tokuredblack.o RT_TLOG_BINS = ../../range_tree/log_nooverlap.o ../../range_tree/tokuredblack.o
RT_LOG_BINS = ../../range_tree/log.o RT_LOG_BINS = ../../range_tree/log.o
LT_BINS = ../lth.o ../rth.o LT_BINS = ../lth.o ../rth.o ../idlth.o ../db_id.o
LT_OVERLAP = ../locktree_global_readset.o LT_OVERLAP = ../locktree_global_readset.o
LT_NOOVERLAP = ../locktree_no_global_readset.o LT_NOOVERLAP = ../locktree_no_global_readset.o
LT_LINEAR = $(LT_OVERLAP) $(LT_BINS) $(RT_LINEAR_BINS) LT_LINEAR = $(LT_OVERLAP) $(LT_BINS) $(RT_LINEAR_BINS)
......
...@@ -8,7 +8,10 @@ ...@@ -8,7 +8,10 @@
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
int verbose=0; int verbose=0;
#include <db_id.h>
#include <lth.h> #include <lth.h>
#include <sys/types.h>
#include <sys/stat.h>
BOOL want_panic = FALSE; BOOL want_panic = FALSE;
...@@ -46,6 +49,17 @@ int dbcmp (DB *db __attribute__((__unused__)), const DBT *a, const DBT*b) { ...@@ -46,6 +49,17 @@ int dbcmp (DB *db __attribute__((__unused__)), const DBT *a, const DBT*b) {
return toku_keycompare(a->data, a->size, b->data, b->size); return toku_keycompare(a->data, a->size, b->data, b->size);
} }
toku_dbt_cmp compare_fun = dbcmp;
toku_dbt_cmp dup_compare = dbcmp;
toku_dbt_cmp get_compare_fun_from_db(__attribute__((unused)) DB* db) {
return compare_fun;
}
toku_dbt_cmp get_dup_compare_from_db(__attribute__((unused)) DB* db) {
return dup_compare;
}
BOOL panicked = FALSE; BOOL panicked = FALSE;
int dbpanic(DB* db, int r) { int dbpanic(DB* db, int r) {
...@@ -134,3 +148,10 @@ void* fail_malloc(size_t size) { ...@@ -134,3 +148,10 @@ void* fail_malloc(size_t size) {
} }
return malloc(size); return malloc(size);
} }
char *toku_strdup (const char *s) {
size_t len = strlen(s) + 1;
void * r = toku_malloc(len);
memcpy(r, s, len);
return r;
}
...@@ -4,16 +4,18 @@ int main() { ...@@ -4,16 +4,18 @@ int main() {
int r; int r;
toku_lock_tree* lt = NULL; toku_lock_tree* lt = NULL;
toku_ltm* mgr = NULL; toku_ltm* mgr = NULL;
DB* db = (DB*)1;
u_int32_t max_locks = 1000; u_int32_t max_locks = 1000;
BOOL duplicates; BOOL duplicates;
r = toku_ltm_create(&mgr, max_locks, toku_malloc, toku_free, toku_realloc); r = toku_ltm_create(&mgr, max_locks, dbpanic,
get_compare_fun_from_db, get_dup_compare_from_db,
toku_malloc, toku_free, toku_realloc);
CKERR(r); CKERR(r);
for (duplicates = 0; duplicates < 2; duplicates++) { for (duplicates = 0; duplicates < 2; duplicates++) {
r = toku_lt_create(&lt, db, duplicates, dbpanic, mgr, r = toku_lt_create(&lt, duplicates, dbpanic, mgr,
dbcmp, dbcmp, toku_malloc, toku_free, toku_realloc); get_compare_fun_from_db, get_dup_compare_from_db,
toku_malloc, toku_free, toku_realloc);
CKERR(r); CKERR(r);
assert(lt); assert(lt);
r = toku_lt_close(lt); r = toku_lt_close(lt);
......
...@@ -2,14 +2,14 @@ ...@@ -2,14 +2,14 @@
#include "test.h" #include "test.h"
toku_range_tree* toku__lt_ifexist_selfwrite(toku_lock_tree* tree, DB_TXN* txn); toku_range_tree* toku__lt_ifexist_selfwrite(toku_lock_tree* tree, TXNID txn);
toku_range_tree* toku__lt_ifexist_selfread(toku_lock_tree* tree, DB_TXN* txn); toku_range_tree* toku__lt_ifexist_selfread(toku_lock_tree* tree, TXNID txn);
int r; int r;
toku_lock_tree* lt = NULL; toku_lock_tree* lt = NULL;
toku_ltm* ltm = NULL; toku_ltm* ltm = NULL;
DB* db = (DB*)1; DB* db = (DB*)1;
DB_TXN* txn = (DB_TXN*)1; TXNID txn = (TXNID)1;
u_int32_t max_locks = 1000; u_int32_t max_locks = 1000;
BOOL duplicates = FALSE; BOOL duplicates = FALSE;
int nums[100]; int nums[100];
...@@ -24,7 +24,7 @@ DBT* data_left [2] ; ...@@ -24,7 +24,7 @@ DBT* data_left [2] ;
DBT* data_right[2] ; DBT* data_right[2] ;
toku_point qleft, qright; toku_point qleft, qright;
toku_range query; toku_interval query;
toku_range* buf; toku_range* buf;
unsigned buflen; unsigned buflen;
unsigned numfound; unsigned numfound;
...@@ -48,10 +48,13 @@ void init_query(BOOL dups) { ...@@ -48,10 +48,13 @@ void init_query(BOOL dups) {
void setup_tree(BOOL dups) { void setup_tree(BOOL dups) {
assert(!lt && !ltm); assert(!lt && !ltm);
r = toku_ltm_create(&ltm, max_locks, toku_malloc, toku_free, toku_realloc); r = toku_ltm_create(&ltm, max_locks, dbpanic,
get_compare_fun_from_db, get_dup_compare_from_db,
toku_malloc, toku_free, toku_realloc);
CKERR(r); CKERR(r);
assert(ltm); assert(ltm);
r = toku_lt_create(&lt, db, dups, dbpanic, ltm, dbcmp, dbcmp, r = toku_lt_create(&lt, dups, dbpanic, ltm,
get_compare_fun_from_db, get_dup_compare_from_db,
toku_malloc, toku_free, toku_realloc); toku_malloc, toku_free, toku_realloc);
CKERR(r); CKERR(r);
assert(lt); assert(lt);
...@@ -104,8 +107,8 @@ void lt_insert(BOOL dups, int key_l, int data_l, int key_r, int data_r) { ...@@ -104,8 +107,8 @@ void lt_insert(BOOL dups, int key_l, int data_l, int key_r, int data_r) {
assert(key_right && !data_right); assert(key_right && !data_right);
} }
r = toku_lt_acquire_range_read_lock(lt, txn, key_left, data_left, r = toku_lt_acquire_range_read_lock(lt, db, txn, key_left, data_left,
key_right, data_right); key_right, data_right);
CKERR(r); CKERR(r);
} }
...@@ -125,11 +128,25 @@ void setup_payload_len(void** payload, u_int32_t* len, int val) { ...@@ -125,11 +128,25 @@ void setup_payload_len(void** payload, u_int32_t* len, int val) {
} }
} }
void temporarily_fake_comparison_functions(void) {
assert(!lt->db && !lt->compare_fun && !lt->dup_compare);
lt->db = db;
lt->compare_fun = get_compare_fun_from_db(db);
lt->dup_compare = get_dup_compare_from_db(db);
}
void stop_fake_comparison_functions(void) {
assert(lt->db && lt->compare_fun && lt->dup_compare);
lt->db = NULL;
lt->compare_fun = NULL;
lt->dup_compare = NULL;
}
void lt_find(BOOL dups, toku_range_tree* rt, void lt_find(BOOL dups, toku_range_tree* rt,
unsigned k, int key_l, int data_l, unsigned k, int key_l, int data_l,
int key_r, int data_r, int key_r, int data_r,
DB_TXN* find_txn) { TXNID find_txn) {
temporarily_fake_comparison_functions();
r = toku_rt_find(rt, &query, 0, &buf, &buflen, &numfound); r = toku_rt_find(rt, &query, 0, &buf, &buflen, &numfound);
CKERR(r); CKERR(r);
assert(numfound==k); assert(numfound==k);
...@@ -149,11 +166,13 @@ void lt_find(BOOL dups, toku_range_tree* rt, ...@@ -149,11 +166,13 @@ void lt_find(BOOL dups, toku_range_tree* rt,
} }
unsigned i; unsigned i;
for (i = 0; i < numfound; i++) { for (i = 0; i < numfound; i++) {
if (toku__lt_point_cmp(buf[i].left, &left ) == 0 && if (toku__lt_point_cmp(buf[i].ends.left, &left ) == 0 &&
toku__lt_point_cmp(buf[i].right, &right) == 0 && toku__lt_point_cmp(buf[i].ends.right, &right) == 0 &&
buf[i].data == find_txn) return; buf[i].data == find_txn) { goto cleanup; }
} }
assert(FALSE); //Crash since we didn't find it. assert(FALSE); //Crash since we didn't find it.
cleanup:
stop_fake_comparison_functions();
} }
...@@ -181,13 +200,13 @@ void insert_1(BOOL dups, int key_l, int key_r, int data_l, int data_r, ...@@ -181,13 +200,13 @@ void insert_1(BOOL dups, int key_l, int key_r, int data_l, int data_r,
setup_tree(dups); setup_tree(dups);
r = toku_lt_acquire_range_read_lock(lt, txn, key_left, data_left, r = toku_lt_acquire_range_read_lock(lt, db, txn, key_left, data_left,
key_right, data_right); key_right, data_right);
CKERR(r); CKERR(r);
close_tree(); close_tree();
setup_tree(dups); setup_tree(dups);
r = toku_lt_acquire_read_lock(lt, txn, key_left, data_left); r = toku_lt_acquire_read_lock(lt, db, txn, key_left, data_left);
CKERR(r); CKERR(r);
close_tree(); close_tree();
} }
...@@ -220,8 +239,8 @@ void insert_2_noclose(BOOL dups, int key_l[2], int key_r[2], ...@@ -220,8 +239,8 @@ void insert_2_noclose(BOOL dups, int key_l[2], int key_r[2],
if (kl[i]) key_left[i] = (DBT*)kl[i]; if (kl[i]) key_left[i] = (DBT*)kl[i];
if (kr[i]) key_right[i] = (DBT*)kr[i]; if (kr[i]) key_right[i] = (DBT*)kr[i];
r = toku_lt_acquire_range_read_lock(lt, txn, key_left[i], data_left[i], r = toku_lt_acquire_range_read_lock(lt, db, txn, key_left[i], data_left[i],
key_right[i], data_right[i]); key_right[i], data_right[i]);
CKERR(r); CKERR(r);
} }
...@@ -263,7 +282,6 @@ void runtest(BOOL dups) { ...@@ -263,7 +282,6 @@ void runtest(BOOL dups) {
lt_insert(dups, lt_insert(dups,
dups ? 3 : 4, 4, dups ? 3 : 4, 4,
dups ? 3 : 5, 5); dups ? 3 : 5, 5);
rt = toku__lt_ifexist_selfread(lt, txn); rt = toku__lt_ifexist_selfread(lt, txn);
assert(rt); assert(rt);
......
...@@ -8,6 +8,7 @@ int main(int argc, const char *argv[]) { ...@@ -8,6 +8,7 @@ int main(int argc, const char *argv[]) {
int r; int r;
parse_args(argc, argv); parse_args(argc, argv);
/* ********************************************************************** */
rth = NULL; rth = NULL;
for (failon = 1; failon <= 2; failon++) { for (failon = 1; failon <= 2; failon++) {
...@@ -22,6 +23,8 @@ int main(int argc, const char *argv[]) { ...@@ -22,6 +23,8 @@ int main(int argc, const char *argv[]) {
toku_rth_close(rth); toku_rth_close(rth);
rth = NULL; rth = NULL;
/* ********************************************************************** */
size_t i; size_t i;
size_t iterations = 512 << 2; size_t iterations = 512 << 2;
...@@ -29,41 +32,44 @@ int main(int argc, const char *argv[]) { ...@@ -29,41 +32,44 @@ int main(int argc, const char *argv[]) {
CKERR(r); CKERR(r);
assert(rth); assert(rth);
for (i = 1; i < iterations; i++) { for (i = 1; i < iterations; i++) {
r = toku_rth_insert(rth, (DB_TXN*)i); r = toku_rth_insert(rth, (TXNID)i);
CKERR(r); CKERR(r);
} }
toku_rt_forest* f; toku_rt_forest* f;
for (i = 1; i < iterations; i++) { for (i = 1; i < iterations; i++) {
f = toku_rth_find(rth, (DB_TXN*)i); f = toku_rth_find(rth, (TXNID)i);
assert(f); assert(f);
} }
f = toku_rth_find(rth, (DB_TXN*)i); f = toku_rth_find(rth, (TXNID)i);
assert(!f); assert(!f);
for (i = iterations - 1; i >= 1; i--) { for (i = iterations - 1; i >= 1; i--) {
toku_rth_delete(rth, (DB_TXN*)i); toku_rth_delete(rth, (TXNID)i);
} }
toku_rth_close(rth); toku_rth_close(rth);
rth = NULL; rth = NULL;
/* ********************************************************************** */
r = toku_rth_create(&rth, toku_malloc, toku_free, toku_realloc); r = toku_rth_create(&rth, toku_malloc, toku_free, toku_realloc);
CKERR(r); CKERR(r);
assert(rth); assert(rth);
for (i = 1; i < iterations; i++) { for (i = 1; i < iterations; i++) {
r = toku_rth_insert(rth, (DB_TXN*)i); r = toku_rth_insert(rth, (TXNID)i);
CKERR(r); CKERR(r);
} }
for (i = 1; i < iterations; i++) { for (i = 1; i < iterations; i++) {
toku_rth_delete(rth, (DB_TXN*)i); toku_rth_delete(rth, (TXNID)i);
} }
toku_rth_close(rth); toku_rth_close(rth);
rth = NULL; rth = NULL;
/* ********************************************************************** */
r = toku_rth_create(&rth, toku_malloc, toku_free, toku_realloc); r = toku_rth_create(&rth, toku_malloc, toku_free, toku_realloc);
CKERR(r); CKERR(r);
assert(rth); assert(rth);
for (i = iterations - 1; i >= 1; i--) { for (i = iterations - 1; i >= 1; i--) {
r = toku_rth_insert(rth, (DB_TXN*)i); r = toku_rth_insert(rth, (TXNID)i);
CKERR(r); CKERR(r);
} }
toku_rth_close(rth); toku_rth_close(rth);
...@@ -74,9 +80,23 @@ int main(int argc, const char *argv[]) { ...@@ -74,9 +80,23 @@ int main(int argc, const char *argv[]) {
r = toku_rth_create(&rth, fail_malloc, toku_free, toku_realloc); r = toku_rth_create(&rth, fail_malloc, toku_free, toku_realloc);
CKERR(r); CKERR(r);
assert(rth); assert(rth);
r = toku_rth_insert(rth, (DB_TXN*)1); r = toku_rth_insert(rth, (TXNID)1);
CKERR2(r, ENOMEM); CKERR2(r, ENOMEM);
toku_rth_close(rth); toku_rth_close(rth);
rth = NULL; rth = NULL;
/* ********************************************************************** */
r = toku_rth_create(&rth, toku_malloc, toku_free, toku_realloc);
CKERR(r);
assert(rth);
for (i = iterations - 1; i >= 1; i--) {
r = toku_rth_insert(rth, (TXNID)i);
CKERR(r);
}
toku_rth_clear(rth);
assert(toku_rth_is_empty(rth));
rth = NULL;
return 0; return 0;
} }
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
#include "test.h" #include "test.h"
toku_range_tree* toku__lt_ifexist_selfwrite(toku_lock_tree* tree, DB_TXN* txn); toku_range_tree* toku__lt_ifexist_selfwrite(toku_lock_tree* tree, TXNID txn);
toku_range_tree* toku__lt_ifexist_selfread(toku_lock_tree* tree, DB_TXN* txn); toku_range_tree* toku__lt_ifexist_selfread(toku_lock_tree* tree, TXNID txn);
int r; int r;
toku_lock_tree* lt = NULL; toku_lock_tree* lt = NULL;
...@@ -17,13 +17,13 @@ DBT _key_left[2]; ...@@ -17,13 +17,13 @@ DBT _key_left[2];
DBT _key_right[2]; DBT _key_right[2];
DBT _data_left[2]; DBT _data_left[2];
DBT _data_right[2]; DBT _data_right[2];
DBT* key_left[2] ; DBT* key_left[2];
DBT* key_right[2] ; DBT* key_right[2];
DBT* data_left [2] ; DBT* data_left [2];
DBT* data_right[2] ; DBT* data_right[2];
toku_point qleft, qright; toku_point qleft, qright;
toku_range query; toku_interval query;
toku_range* buf; toku_range* buf;
unsigned buflen; unsigned buflen;
unsigned numfound; unsigned numfound;
...@@ -47,10 +47,13 @@ void init_query(BOOL dups) { ...@@ -47,10 +47,13 @@ void init_query(BOOL dups) {
void setup_tree(BOOL dups) { void setup_tree(BOOL dups) {
assert(!lt && !ltm); assert(!lt && !ltm);
r = toku_ltm_create(&ltm, max_locks, toku_malloc, toku_free, toku_realloc); r = toku_ltm_create(&ltm, max_locks, dbpanic,
get_compare_fun_from_db, get_dup_compare_from_db,
toku_malloc, toku_free, toku_realloc);
CKERR(r); CKERR(r);
assert(ltm); assert(ltm);
r = toku_lt_create(&lt, db, dups, dbpanic, ltm, dbcmp, dbcmp, r = toku_lt_create(&lt, dups, dbpanic, ltm,
get_compare_fun_from_db, get_dup_compare_from_db,
toku_malloc, toku_free, toku_realloc); toku_malloc, toku_free, toku_realloc);
CKERR(r); CKERR(r);
assert(lt); assert(lt);
...@@ -104,13 +107,14 @@ void lt_insert(BOOL dups, int r_expect, char txn, int key_l, int data_l, ...@@ -104,13 +107,14 @@ void lt_insert(BOOL dups, int r_expect, char txn, int key_l, int data_l,
assert(!read_flag || (key_right && !data_right)); assert(!read_flag || (key_right && !data_right));
} }
DB_TXN* local_txn = (DB_TXN*) (size_t) txn; TXNID local_txn = (TXNID) (size_t) txn;
if (read_flag) if (read_flag)
r = toku_lt_acquire_range_read_lock(lt, local_txn, key_left, data_left, r = toku_lt_acquire_range_read_lock(lt, db, local_txn,
key_left, data_left,
key_right, data_right); key_right, data_right);
else else
r = toku_lt_acquire_write_lock(lt, local_txn, key_left, data_left); r = toku_lt_acquire_write_lock(lt, db, local_txn, key_left, data_left);
CKERR2(r, r_expect); CKERR2(r, r_expect);
} }
...@@ -149,7 +153,7 @@ void lt_find(BOOL dups, toku_range_tree* rt, ...@@ -149,7 +153,7 @@ void lt_find(BOOL dups, toku_range_tree* rt,
CKERR(r); CKERR(r);
assert(numfound==k); assert(numfound==k);
DB_TXN* find_txn = (DB_TXN *) (size_t) char_txn; TXNID find_txn = (TXNID) (size_t) char_txn;
toku_point left, right; toku_point left, right;
init_point(&left, lt); init_point(&left, lt);
...@@ -166,8 +170,8 @@ void lt_find(BOOL dups, toku_range_tree* rt, ...@@ -166,8 +170,8 @@ void lt_find(BOOL dups, toku_range_tree* rt,
} }
unsigned i; unsigned i;
for (i = 0; i < numfound; i++) { for (i = 0; i < numfound; i++) {
if (toku__lt_point_cmp(buf[i].left, &left ) == 0 && if (toku__lt_point_cmp(buf[i].ends.left, &left ) == 0 &&
toku__lt_point_cmp(buf[i].right, &right) == 0 && toku__lt_point_cmp(buf[i].ends.right, &right) == 0 &&
buf[i].data == find_txn) return; buf[i].data == find_txn) return;
} }
assert(FALSE); //Crash since we didn't find it. assert(FALSE); //Crash since we didn't find it.
...@@ -175,7 +179,7 @@ void lt_find(BOOL dups, toku_range_tree* rt, ...@@ -175,7 +179,7 @@ void lt_find(BOOL dups, toku_range_tree* rt,
void lt_unlock(char ctxn) { void lt_unlock(char ctxn) {
int r; int r;
r = toku_lt_unlock(lt, (DB_TXN *) (size_t) ctxn); r = toku_lt_unlock(lt, (TXNID) (size_t) ctxn);
CKERR(r); CKERR(r);
} }
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
#include "test.h" #include "test.h"
toku_range_tree* toku__lt_ifexist_selfwrite(toku_lock_tree* tree, DB_TXN* txn); toku_range_tree* toku__lt_ifexist_selfwrite(toku_lock_tree* tree, TXNID txn);
toku_range_tree* toku__lt_ifexist_selfread(toku_lock_tree* tree, DB_TXN* txn); toku_range_tree* toku__lt_ifexist_selfread(toku_lock_tree* tree, TXNID txn);
int r; int r;
toku_lock_tree* lt = NULL; toku_lock_tree* lt = NULL;
...@@ -23,7 +23,7 @@ DBT* data_left [2] ; ...@@ -23,7 +23,7 @@ DBT* data_left [2] ;
DBT* data_right[2] ; DBT* data_right[2] ;
toku_point qleft, qright; toku_point qleft, qright;
toku_range query; toku_interval query;
toku_range* buf; toku_range* buf;
unsigned buflen; unsigned buflen;
unsigned numfound; unsigned numfound;
...@@ -47,10 +47,13 @@ void init_query(BOOL dups) { ...@@ -47,10 +47,13 @@ void init_query(BOOL dups) {
void setup_tree(BOOL dups) { void setup_tree(BOOL dups) {
assert(!lt && !ltm); assert(!lt && !ltm);
r = toku_ltm_create(&ltm, max_locks, toku_malloc, toku_free, toku_realloc); r = toku_ltm_create(&ltm, max_locks, dbpanic,
get_compare_fun_from_db, get_dup_compare_from_db,
toku_malloc, toku_free, toku_realloc);
CKERR(r); CKERR(r);
assert(ltm); assert(ltm);
r = toku_lt_create(&lt, db, dups, dbpanic, ltm, intcmp, intcmp, r = toku_lt_create(&lt, dups, dbpanic, ltm,
get_compare_fun_from_db, get_dup_compare_from_db,
toku_malloc, toku_free, toku_realloc); toku_malloc, toku_free, toku_realloc);
CKERR(r); CKERR(r);
assert(lt); assert(lt);
...@@ -104,13 +107,14 @@ void lt_insert(BOOL dups, int r_expect, char txn, int key_l, int data_l, ...@@ -104,13 +107,14 @@ void lt_insert(BOOL dups, int r_expect, char txn, int key_l, int data_l,
assert(!read_flag || (key_right && !data_right)); assert(!read_flag || (key_right && !data_right));
} }
DB_TXN* local_txn = (DB_TXN*) (size_t) txn; TXNID local_txn = (TXNID) (size_t) txn;
if (read_flag) if (read_flag)
r = toku_lt_acquire_range_read_lock(lt, local_txn, key_left, data_left, r = toku_lt_acquire_range_read_lock(lt, db, local_txn,
key_left, data_left,
key_right, data_right); key_right, data_right);
else else
r = toku_lt_acquire_write_lock(lt, local_txn, key_left, data_left); r = toku_lt_acquire_write_lock(lt, db, local_txn, key_left, data_left);
CKERR2(r, r_expect); CKERR2(r, r_expect);
} }
...@@ -140,16 +144,30 @@ void setup_payload_len(void** payload, u_int32_t* len, int val) { ...@@ -140,16 +144,30 @@ void setup_payload_len(void** payload, u_int32_t* len, int val) {
} }
} }
void temporarily_fake_comparison_functions(void) {
assert(!lt->db && !lt->compare_fun && !lt->dup_compare);
lt->db = db;
lt->compare_fun = get_compare_fun_from_db(db);
lt->dup_compare = get_dup_compare_from_db(db);
}
void stop_fake_comparison_functions(void) {
assert(lt->db && lt->compare_fun && lt->dup_compare);
lt->db = NULL;
lt->compare_fun = NULL;
lt->dup_compare = NULL;
}
void lt_find(BOOL dups, toku_range_tree* rt, void lt_find(BOOL dups, toku_range_tree* rt,
unsigned k, int key_l, int data_l, unsigned k, int key_l, int data_l,
int key_r, int data_r, int key_r, int data_r,
char char_txn) { char char_txn) {
temporarily_fake_comparison_functions();
r = toku_rt_find(rt, &query, 0, &buf, &buflen, &numfound); r = toku_rt_find(rt, &query, 0, &buf, &buflen, &numfound);
CKERR(r); CKERR(r);
assert(numfound==k); assert(numfound==k);
DB_TXN* find_txn = (DB_TXN *) (size_t) char_txn; TXNID find_txn = (TXNID) (size_t) char_txn;
toku_point left, right; toku_point left, right;
init_point(&left, lt); init_point(&left, lt);
...@@ -166,16 +184,18 @@ void lt_find(BOOL dups, toku_range_tree* rt, ...@@ -166,16 +184,18 @@ void lt_find(BOOL dups, toku_range_tree* rt,
} }
unsigned i; unsigned i;
for (i = 0; i < numfound; i++) { for (i = 0; i < numfound; i++) {
if (toku__lt_point_cmp(buf[i].left, &left ) == 0 && if (toku__lt_point_cmp(buf[i].ends.left, &left ) == 0 &&
toku__lt_point_cmp(buf[i].right, &right) == 0 && toku__lt_point_cmp(buf[i].ends.right, &right) == 0 &&
buf[i].data == find_txn) return; buf[i].data == find_txn) { goto cleanup; }
} }
assert(FALSE); //Crash since we didn't find it. assert(FALSE); //Crash since we didn't find it.
cleanup:
stop_fake_comparison_functions();
} }
void lt_unlock(char ctxn) { void lt_unlock(char ctxn) {
int r; int r;
r = toku_lt_unlock(lt, (DB_TXN *) (size_t) ctxn); r = toku_lt_unlock(lt, (TXNID) (size_t) ctxn);
CKERR(r); CKERR(r);
} }
...@@ -507,6 +527,8 @@ void init_test(void) { ...@@ -507,6 +527,8 @@ void init_test(void) {
buflen = 64; buflen = 64;
buf = (toku_range*) toku_malloc(buflen*sizeof(toku_range)); buf = (toku_range*) toku_malloc(buflen*sizeof(toku_range));
compare_fun = intcmp;
dup_compare = intcmp;
} }
......
...@@ -7,40 +7,86 @@ toku_range_tree* toku__lt_ifexist_selfwrite(toku_lock_tree* tree, DB_TXN* txn); ...@@ -7,40 +7,86 @@ toku_range_tree* toku__lt_ifexist_selfwrite(toku_lock_tree* tree, DB_TXN* txn);
toku_range_tree* toku__lt_ifexist_selfread(toku_lock_tree* tree, DB_TXN* txn); toku_range_tree* toku__lt_ifexist_selfread(toku_lock_tree* tree, DB_TXN* txn);
int r; int r;
toku_lock_tree* lt = NULL; toku_lock_tree* lt [10] = {0};
toku_ltm* ltm = NULL; toku_ltm* ltm = NULL;
DB* db = (DB*)1; DB* db = (DB*)1;
u_int32_t max_locks = 10; u_int32_t max_locks = 10;
BOOL duplicates = FALSE; BOOL duplicates = FALSE;
int nums[10000]; int nums[10000];
void setup_tree(BOOL dups) { void setup_ltm(void) {
assert(!lt && !ltm); assert(!ltm);
r = toku_ltm_create(&ltm, max_locks, toku_malloc, toku_free, toku_realloc); r = toku_ltm_create(&ltm, max_locks, dbpanic,
get_compare_fun_from_db, get_dup_compare_from_db,
toku_malloc, toku_free, toku_realloc);
CKERR(r); CKERR(r);
assert(ltm); assert(ltm);
r = toku_lt_create(&lt, db, dups, dbpanic, ltm, intcmp, intcmp, }
toku_malloc, toku_free, toku_realloc);
void setup_tree(BOOL dups, size_t index, toku_db_id* db_id) {
assert(!lt[index] && ltm);
r = toku_ltm_get_lt(ltm, &lt[index], dups, db_id);
CKERR(r); CKERR(r);
assert(lt); assert(lt[index]);
} }
void close_ltm(void) { void close_ltm(void) {
assert(lt && ltm); assert(ltm);
r = toku_ltm_close(ltm); r = toku_ltm_close(ltm);
CKERR(r); CKERR(r);
lt = NULL; u_int32_t i = 0;
for (i = 0; i < sizeof(lt)/sizeof(*lt); i++) { lt[i] = NULL; }
ltm = NULL; ltm = NULL;
} }
void run_test(BOOL dups) { void run_test(BOOL dups) {
setup_tree(dups); toku_db_id* db_id = NULL;
close_ltm(); r = toku_db_id_create(&db_id, DIR, "subdb");
CKERR(r);
assert(db_id);
toku_db_id* db_id2 = NULL;
r = toku_db_id_create(&db_id2, DIR, "subdb2");
CKERR(r);
assert(db_id);
toku_db_id* db_id3 = NULL;
r = toku_db_id_create(&db_id3, DIR, "subdb");
CKERR(r);
assert(db_id);
setup_ltm();
setup_tree(dups, 0, db_id);
setup_tree(dups, 1, db_id);
assert(lt[0] == lt[1]);
setup_tree(dups, 2, db_id2);
assert(lt[0] != lt[2]);
setup_tree(dups, 3, db_id3);
assert(lt[0] == lt[3]);
toku_ltm_invalidate_lt(ltm, db_id);
setup_tree(dups, 4, db_id);
assert(lt[0] != lt[4]);
setup_tree(dups, 5, db_id);
assert(lt[0] != lt[5]);
assert(lt[4] == lt[5]);
close_ltm();
toku_db_id_remove_ref(db_id);
toku_db_id_remove_ref(db_id2);
toku_db_id_remove_ref(db_id3);
} }
int main(int argc, const char *argv[]) { int main(int argc, const char *argv[]) {
parse_args(argc, argv); parse_args(argc, argv);
compare_fun = intcmp;
dup_compare = intcmp;
system("rm -rf " DIR);
mkdir(DIR, 0777);
run_test(FALSE); run_test(FALSE);
run_test(TRUE); run_test(TRUE);
......
/* Test for a memory leak from just closing the lock tree manager (should close
all lock trees. */
#include "test.h"
toku_range_tree* toku__lt_ifexist_selfwrite(toku_lock_tree* tree, DB_TXN* txn);
toku_range_tree* toku__lt_ifexist_selfread(toku_lock_tree* tree, DB_TXN* txn);
void initial_setup(void);
static int r;
static u_int32_t lt_refs[100];
static toku_lock_tree* lts [100];
static toku_ltm* ltm = NULL;
static toku_db_id* db_ids[100];
static char subdb [100][5];
static u_int32_t max_locks = 10;
int nums[10000];
void setup_ltm(void) {
assert(!ltm);
r = toku_ltm_create(&ltm, max_locks, dbpanic,
get_compare_fun_from_db, get_dup_compare_from_db,
toku_malloc, toku_free, toku_realloc);
CKERR(r);
assert(ltm);
}
void db_open_tree(BOOL dups, size_t index, size_t db_id_index) {
assert((lt_refs[index] == 0 && !lts[index]) ||
(lt_refs[index] > 0 && lts[index]));
assert(ltm);
lt_refs[index]++;
r = toku_ltm_get_lt(ltm, &lts[index], dups, db_ids[db_id_index]);
CKERR(r);
assert(lts[index]);
}
void db_close_tree(size_t index) {
assert(lts[index] && ltm && lt_refs[index] > 0);
r = toku_lt_remove_ref(lts[index]); CKERR(r);
lt_refs[index]--;
if (lt_refs[index] == 0) { lts[index] = NULL; }
}
void txn_open_tree(size_t index) {
assert(lts[index] && ltm && lt_refs[index] > 0);
toku_lt_add_ref(lts[index]);
lt_refs[index]++;
}
void txn_close_tree(size_t index) {
assert(lts[index] && ltm && lt_refs[index] > 0);
r = toku_lt_remove_ref(lts[index]); CKERR(r);
lt_refs[index]--;
if (lt_refs[index] == 0) { lts[index] = NULL; }
}
void close_ltm(void) {
assert(ltm);
r = toku_ltm_close(ltm);
CKERR(r);
initial_setup();
ltm = NULL;
}
void run_test(BOOL dups) {
setup_ltm();
//Start:
/* ********************************************************************** */
//Open and close.
db_open_tree(dups, 0, 0);
db_close_tree(0);
/* ********************************************************************** */
//Open with db and transaction, db closes first.
db_open_tree(dups, 0, 0);
txn_open_tree(0);
db_close_tree(0);
txn_close_tree(0);
/* ********************************************************************** */
//Open with db and transaction, txn closes first.
db_open_tree(dups, 0, 0);
txn_open_tree(0);
txn_close_tree(0);
db_close_tree(0);
/* ********************************************************************** */
//Open with multiple db handles.
db_open_tree(dups, 0, 0);
db_open_tree(dups, 0, 0);
db_close_tree(0);
db_close_tree(0);
/* ********************************************************************** */
//Open with multiple db handles and txns.
db_open_tree(dups, 0, 0);
txn_open_tree(0);
db_open_tree(dups, 0, 0);
db_close_tree(0);
db_close_tree(0);
txn_close_tree(0);
/* ********************************************************************** */
//Open with multiple db handles and txns.
db_open_tree(dups, 0, 0);
db_open_tree(dups, 0, 0);
txn_open_tree(0);
db_close_tree(0);
db_close_tree(0);
txn_close_tree(0);
/* ********************************************************************** */
//End:
close_ltm();
}
void initial_setup(void) {
u_int32_t i;
ltm = NULL;
assert(sizeof(db_ids) / sizeof(db_ids[0]) == sizeof(lts) / sizeof(lts[0]));
assert(sizeof(subdb) / sizeof(subdb[0]) == sizeof(lts) / sizeof(lts[0]));
for (i = 0; i < sizeof(lts) / sizeof(lts[0]); i++) {
lts[i] = NULL;
sprintf(subdb[i], "%05x", i);
if (!db_ids[i]) toku_db_id_create(&db_ids[i], DIR, subdb[i]);
assert(db_ids[i]);
lt_refs[i] = 0;
}
}
int main(int argc, const char *argv[]) {
parse_args(argc, argv);
compare_fun = intcmp;
dup_compare = intcmp;
system("rm -rf " DIR);
mkdir(DIR, 0777);
initial_setup();
run_test(FALSE);
run_test(TRUE);
return 0;
}
...@@ -70,7 +70,7 @@ static inline int toku__rt_increase_capacity(toku_range_tree* tree, ...@@ -70,7 +70,7 @@ static inline int toku__rt_increase_capacity(toku_range_tree* tree,
} }
static inline BOOL toku__rt_overlap(toku_range_tree* tree, static inline BOOL toku__rt_overlap(toku_range_tree* tree,
toku_range* a, toku_range* b) { toku_interval* a, toku_interval* b) {
assert(tree); assert(tree);
assert(a); assert(a);
assert(b); assert(b);
...@@ -85,14 +85,14 @@ static inline BOOL toku__rt_exact(toku_range_tree* tree, ...@@ -85,14 +85,14 @@ static inline BOOL toku__rt_exact(toku_range_tree* tree,
assert(a); assert(a);
assert(b); assert(b);
return (tree->end_cmp (a->left, b->left) == 0 && return (tree->end_cmp (a->ends.left, b->ends.left) == 0 &&
tree->end_cmp (a->right, b->right) == 0 && tree->end_cmp (a->ends.right, b->ends.right) == 0 &&
tree->data_cmp(a->data, b->data) == 0); tree->data_cmp(a->data, b->data) == 0);
} }
int toku_rt_create(toku_range_tree** ptree, int toku_rt_create(toku_range_tree** ptree,
int (*end_cmp)(const toku_point*,const toku_point*), int (*end_cmp)(const toku_point*,const toku_point*),
int (*data_cmp)(const DB_TXN*,const DB_TXN*), int (*data_cmp)(const TXNID,const TXNID),
BOOL allow_overlaps, BOOL allow_overlaps,
void* (*user_malloc) (size_t), void* (*user_malloc) (size_t),
void (*user_free) (void*), void (*user_free) (void*),
...@@ -122,6 +122,13 @@ int toku_rt_create(toku_range_tree** ptree, ...@@ -122,6 +122,13 @@ int toku_rt_create(toku_range_tree** ptree,
return 0; return 0;
} }
void toku_rt_clear(toku_range_tree* tree) {
assert(tree);
toku__rt_decrease_capacity(tree, 0);
toku_rt_invalidate_iteration(tree);
tree->numelements = 0;
}
int toku_rt_close(toku_range_tree* tree) { int toku_rt_close(toku_range_tree* tree) {
if (!tree) return EINVAL; if (!tree) return EINVAL;
tree->free(tree->i.ranges); tree->free(tree->i.ranges);
...@@ -129,10 +136,9 @@ int toku_rt_close(toku_range_tree* tree) { ...@@ -129,10 +136,9 @@ int toku_rt_close(toku_range_tree* tree) {
return 0; return 0;
} }
int toku_rt_find(toku_range_tree* tree, toku_range* query, u_int32_t k, int toku_rt_find(toku_range_tree* tree, toku_interval* query, u_int32_t k,
toku_range** buf, u_int32_t* buflen, u_int32_t* numfound) { toku_range** buf, u_int32_t* buflen, u_int32_t* numfound) {
if (!tree || !query || !buf || !buflen || !numfound) return EINVAL; if (!tree || !query || !buf || !buflen || !numfound) return EINVAL;
if (query->data != NULL) return EINVAL;
if (*buflen == 0) return EINVAL; if (*buflen == 0) return EINVAL;
u_int32_t temp_numfound = 0; u_int32_t temp_numfound = 0;
...@@ -140,7 +146,7 @@ int toku_rt_find(toku_range_tree* tree, toku_range* query, u_int32_t k, ...@@ -140,7 +146,7 @@ int toku_rt_find(toku_range_tree* tree, toku_range* query, u_int32_t k,
u_int32_t i; u_int32_t i;
for (i = 0; i < tree->numelements; i++) { for (i = 0; i < tree->numelements; i++) {
if (toku__rt_overlap(tree, query, &tree->i.ranges[i])) { if (toku__rt_overlap(tree, query, &tree->i.ranges[i].ends)) {
r = toku__rt_increase_buffer(tree, buf, buflen, temp_numfound + 1); r = toku__rt_increase_buffer(tree, buf, buflen, temp_numfound + 1);
if (r != 0) return r; if (r != 0) return r;
(*buf)[temp_numfound++] = tree->i.ranges[i]; (*buf)[temp_numfound++] = tree->i.ranges[i];
...@@ -166,7 +172,7 @@ int toku_rt_insert(toku_range_tree* tree, toku_range* range) { ...@@ -166,7 +172,7 @@ int toku_rt_insert(toku_range_tree* tree, toku_range* range) {
} }
else { else {
for (i = 0; i < tree->numelements; i++) { for (i = 0; i < tree->numelements; i++) {
if (toku__rt_overlap(tree, range, &tree->i.ranges[i])) return EDOM; if (toku__rt_overlap(tree, &range->ends, &tree->i.ranges[i].ends)) return EDOM;
} }
} }
r = toku__rt_increase_capacity(tree, tree->numelements + 1); r = toku__rt_increase_capacity(tree, tree->numelements + 1);
...@@ -202,8 +208,8 @@ int toku_rt_predecessor (toku_range_tree* tree, toku_point* point, ...@@ -202,8 +208,8 @@ int toku_rt_predecessor (toku_range_tree* tree, toku_point* point,
u_int32_t i; u_int32_t i;
for (i = 0; i < tree->numelements; i++) { for (i = 0; i < tree->numelements; i++) {
if (toku__rt_p_cmp(tree, point, &tree->i.ranges[i]) > 0 && if (toku__rt_p_cmp(tree, point, &tree->i.ranges[i].ends) > 0 &&
(!best || tree->end_cmp(best->left, tree->i.ranges[i].left) < 0)) { (!best || tree->end_cmp(best->ends.left, tree->i.ranges[i].ends.left) < 0)) {
best = &tree->i.ranges[i]; best = &tree->i.ranges[i];
} }
} }
...@@ -220,8 +226,8 @@ int toku_rt_successor (toku_range_tree* tree, toku_point* point, ...@@ -220,8 +226,8 @@ int toku_rt_successor (toku_range_tree* tree, toku_point* point,
u_int32_t i; u_int32_t i;
for (i = 0; i < tree->numelements; i++) { for (i = 0; i < tree->numelements; i++) {
if (toku__rt_p_cmp(tree, point, &tree->i.ranges[i]) < 0 && if (toku__rt_p_cmp(tree, point, &tree->i.ranges[i].ends) < 0 &&
(!best || tree->end_cmp(best->left, tree->i.ranges[i].left) > 0)) { (!best || tree->end_cmp(best->ends.left, tree->i.ranges[i].ends.left) > 0)) {
best = &tree->i.ranges[i]; best = &tree->i.ranges[i];
} }
} }
......
...@@ -61,7 +61,7 @@ static inline void toku_rt_invalidate_iteration(toku_range_tree* tree) { ...@@ -61,7 +61,7 @@ static inline void toku_rt_invalidate_iteration(toku_range_tree* tree) {
//FIRST PASS //FIRST PASS
int toku_rt_create(toku_range_tree** ptree, int toku_rt_create(toku_range_tree** ptree,
int (*end_cmp)(const toku_point*,const toku_point*), int (*end_cmp)(const toku_point*,const toku_point*),
int (*data_cmp)(const DB_TXN*,const DB_TXN*), int (*data_cmp)(const TXNID,const TXNID),
BOOL allow_overlaps, BOOL allow_overlaps,
void* (*user_malloc) (size_t), void* (*user_malloc) (size_t),
void (*user_free) (void*), void (*user_free) (void*),
...@@ -100,6 +100,13 @@ int toku_rt_close(toku_range_tree* tree) { ...@@ -100,6 +100,13 @@ int toku_rt_close(toku_range_tree* tree) {
return 0; return 0;
} }
void toku_rt_clear(toku_range_tree* tree) {
assert(tree);
toku_rbt_clear(tree->i.rbt);
toku_rt_invalidate_iteration(tree);
tree->numelements = 0;
}
/* /*
5- FindOverlaps 5- FindOverlaps
O(lg N+1) CMPs Do a lookup (<=) (out found, out elementpointer) O(lg N+1) CMPs Do a lookup (<=) (out found, out elementpointer)
...@@ -115,12 +122,11 @@ int toku_rt_close(toku_range_tree* tree) { ...@@ -115,12 +122,11 @@ int toku_rt_close(toku_range_tree* tree) {
add found to buffer add found to buffer
(0) CMPs do a finger_successor(elementpointer) (out found, out elementpointer) (0) CMPs do a finger_successor(elementpointer) (out found, out elementpointer)
*/ */
int toku_rt_find(toku_range_tree* tree, toku_range* query, u_int32_t k, int toku_rt_find(toku_range_tree* tree, toku_interval* query, u_int32_t k,
toku_range** buf, u_int32_t* buflen, u_int32_t* numfound) { toku_range** buf, u_int32_t* buflen, u_int32_t* numfound) {
int r = ENOSYS; int r = ENOSYS;
if (!tree || !query || !buf || !buflen || !numfound || if (!tree || !query || !buf || !buflen || !numfound || *buflen == 0) {
query->data != NULL || *buflen == 0) {
r = EINVAL; goto cleanup; r = EINVAL; goto cleanup;
} }
assert(!tree->allow_overlaps); assert(!tree->allow_overlaps);
...@@ -136,7 +142,7 @@ int toku_rt_find(toku_range_tree* tree, toku_range* query, u_int32_t k, ...@@ -136,7 +142,7 @@ int toku_rt_find(toku_range_tree* tree, toku_range* query, u_int32_t k,
r = toku_rbt_lookup(RB_LULTEQ, query, tree->i.rbt, &ignore_insert, &succ_finger, &data); r = toku_rbt_lookup(RB_LULTEQ, query, tree->i.rbt, &ignore_insert, &succ_finger, &data);
if (r!=0) { goto cleanup; } if (r!=0) { goto cleanup; }
if (data != NULL) { if (data != NULL) {
if (tree->end_cmp(data->right, query->left) >= 0) { if (tree->end_cmp(data->ends.right, query->left) >= 0) {
r = toku__rt_increase_buffer(tree, buf, buflen, temp_numfound + 1); r = toku__rt_increase_buffer(tree, buf, buflen, temp_numfound + 1);
if (r!=0) { goto cleanup; } if (r!=0) { goto cleanup; }
(*buf)[temp_numfound++] = *data; (*buf)[temp_numfound++] = *data;
...@@ -152,7 +158,7 @@ int toku_rt_find(toku_range_tree* tree, toku_range* query, u_int32_t k, ...@@ -152,7 +158,7 @@ int toku_rt_find(toku_range_tree* tree, toku_range* query, u_int32_t k,
} }
while (temp_numfound < k && data != NULL) { while (temp_numfound < k && data != NULL) {
if (tree->end_cmp(data->left, query->right) > 0) { break; } if (tree->end_cmp(data->ends.left, query->right) > 0) { break; }
r = toku__rt_increase_buffer(tree, buf, buflen, temp_numfound + 1); r = toku__rt_increase_buffer(tree, buf, buflen, temp_numfound + 1);
if (r!=0) { goto cleanup; } if (r!=0) { goto cleanup; }
(*buf)[temp_numfound++] = *data; (*buf)[temp_numfound++] = *data;
...@@ -188,10 +194,10 @@ int toku_rt_insert(toku_range_tree* tree, toku_range* range) { ...@@ -188,10 +194,10 @@ int toku_rt_insert(toku_range_tree* tree, toku_range* range) {
struct toku_rbt_node* succ_finger = NULL; struct toku_rbt_node* succ_finger = NULL;
toku_range* data = NULL; toku_range* data = NULL;
r = toku_rbt_lookup(RB_LULTEQ, range, tree->i.rbt, &insert_finger, &succ_finger, &data); r = toku_rbt_lookup(RB_LULTEQ, &range->ends, tree->i.rbt, &insert_finger, &succ_finger, &data);
if (r!=0) { goto cleanup; } if (r!=0) { goto cleanup; }
if (data != NULL) { if (data != NULL) {
if (tree->end_cmp(data->right, range->left) >= 0) { if (tree->end_cmp(data->ends.right, range->ends.left) >= 0) {
r = EDOM; goto cleanup; r = EDOM; goto cleanup;
} }
r = toku_rbt_finger_successor(&succ_finger, &data); r = toku_rbt_finger_successor(&succ_finger, &data);
...@@ -201,7 +207,7 @@ int toku_rt_insert(toku_range_tree* tree, toku_range* range) { ...@@ -201,7 +207,7 @@ int toku_rt_insert(toku_range_tree* tree, toku_range* range) {
r = toku_rbt_lookup(RB_LUFIRST, NULL, tree->i.rbt, &ignore_insert, &succ_finger, &data); r = toku_rbt_lookup(RB_LUFIRST, NULL, tree->i.rbt, &ignore_insert, &succ_finger, &data);
if (r!=0) { goto cleanup; } if (r!=0) { goto cleanup; }
} }
if (data != NULL && tree->end_cmp(data->left, range->right) <= 0) { if (data != NULL && tree->end_cmp(data->ends.left, range->ends.right) <= 0) {
r = EDOM; goto cleanup; r = EDOM; goto cleanup;
} }
r = toku_rbt_finger_insert(range, tree->i.rbt, insert_finger); r = toku_rbt_finger_insert(range, tree->i.rbt, insert_finger);
...@@ -237,12 +243,12 @@ int toku_rt_delete(toku_range_tree* tree, toku_range* range) { ...@@ -237,12 +243,12 @@ int toku_rt_delete(toku_range_tree* tree, toku_range* range) {
struct toku_rbt_node* delete_finger = NULL; struct toku_rbt_node* delete_finger = NULL;
toku_range* data = NULL; toku_range* data = NULL;
r = toku_rbt_lookup(RB_LUEQUAL, range, tree->i.rbt, r = toku_rbt_lookup(RB_LUEQUAL, &range->ends, tree->i.rbt,
&ignore_insert, &delete_finger, &data); &ignore_insert, &delete_finger, &data);
if (r!=0) { goto cleanup; } if (r!=0) { goto cleanup; }
if (!data || if (!data ||
tree->data_cmp(data->data, range->data) != 0 || tree->data_cmp(data->data, range->data) != 0 ||
tree->end_cmp(data->right, range->right) != 0) { tree->end_cmp(data->ends.right, range->ends.right) != 0) {
r = EDOM; goto cleanup; r = EDOM; goto cleanup;
} }
...@@ -279,12 +285,11 @@ int toku_rt_predecessor (toku_range_tree* tree, toku_point* point, ...@@ -279,12 +285,11 @@ int toku_rt_predecessor (toku_range_tree* tree, toku_point* point,
struct toku_rbt_node* ignore_insert = NULL; struct toku_rbt_node* ignore_insert = NULL;
struct toku_rbt_node* pred_finger = NULL; struct toku_rbt_node* pred_finger = NULL;
toku_range* data = NULL; toku_range* data = NULL;
toku_range range; toku_interval query;
range.left = point; query.left = point;
range.right = point; query.right = point;
range.data = NULL;
r = toku_rbt_lookup(RB_LULESS, &range, tree->i.rbt, &ignore_insert, &pred_finger, &data); r = toku_rbt_lookup(RB_LULESS, &query, tree->i.rbt, &ignore_insert, &pred_finger, &data);
if (r!=0) { goto cleanup; } if (r!=0) { goto cleanup; }
if (!data) { if (!data) {
...@@ -292,7 +297,7 @@ int toku_rt_predecessor (toku_range_tree* tree, toku_point* point, ...@@ -292,7 +297,7 @@ int toku_rt_predecessor (toku_range_tree* tree, toku_point* point,
r = 0; r = 0;
goto cleanup; goto cleanup;
} }
if (tree->end_cmp(data->right, point) < 0) { if (tree->end_cmp(data->ends.right, point) < 0) {
*wasfound = TRUE; *wasfound = TRUE;
*pred = *data; *pred = *data;
r = 0; r = 0;
...@@ -329,12 +334,11 @@ int toku_rt_successor (toku_range_tree* tree, toku_point* point, ...@@ -329,12 +334,11 @@ int toku_rt_successor (toku_range_tree* tree, toku_point* point,
struct toku_rbt_node* ignore_insert = NULL; struct toku_rbt_node* ignore_insert = NULL;
struct toku_rbt_node* succ_finger = NULL; struct toku_rbt_node* succ_finger = NULL;
toku_range* data = NULL; toku_range* data = NULL;
toku_range range; toku_interval query;
range.left = point; query.left = point;
range.right = point; query.right = point;
range.data = NULL;
r = toku_rbt_lookup(RB_LUGREAT, &range, tree->i.rbt, &ignore_insert, &succ_finger, &data); r = toku_rbt_lookup(RB_LUGREAT, &query, tree->i.rbt, &ignore_insert, &succ_finger, &data);
if (r!=0) { goto cleanup; } if (r!=0) { goto cleanup; }
if (!data) { if (!data) {
......
/* -*- mode: C; c-basic-offset: 4 -*- */ /* -*- mode: C; c-basic-offset: 4 -*- */
#ident "Copyright (c) 2007-8 Tokutek Inc. All rights reserved." #ident "Copyright (c) 2007-8 Tokutek Inc. All rights reserved."
...@@ -23,7 +24,7 @@ struct __toku_range_tree { ...@@ -23,7 +24,7 @@ struct __toku_range_tree {
int (*end_cmp)(const toku_point*,const toku_point*); int (*end_cmp)(const toku_point*,const toku_point*);
/** A comparison function, as in bsearch(3), to compare the data associated /** A comparison function, as in bsearch(3), to compare the data associated
with a range */ with a range */
int (*data_cmp)(const DB_TXN*,const DB_TXN*); int (*data_cmp)(const TXNID,const TXNID);
/** Whether this tree allows ranges to overlap */ /** Whether this tree allows ranges to overlap */
BOOL allow_overlaps; BOOL allow_overlaps;
/** The number of ranges in the range tree */ /** The number of ranges in the range tree */
...@@ -45,9 +46,9 @@ struct __toku_range_tree { ...@@ -45,9 +46,9 @@ struct __toku_range_tree {
* > 0: Point strictly greater than the range. * > 0: Point strictly greater than the range.
*/ */
static inline int toku__rt_p_cmp(toku_range_tree* tree, static inline int toku__rt_p_cmp(toku_range_tree* tree,
toku_point* point, toku_range* range) { toku_point* point, toku_interval* interval) {
if (tree->end_cmp(point, range->left) < 0) return -1; if (tree->end_cmp(point, interval->left) < 0) return -1;
if (tree->end_cmp(point, range->right) > 0) return 1; if (tree->end_cmp(point, interval->right) > 0) return 1;
return 0; return 0;
} }
...@@ -70,7 +71,7 @@ static inline int toku__rt_increase_buffer(toku_range_tree* tree, toku_range** b ...@@ -70,7 +71,7 @@ static inline int toku__rt_increase_buffer(toku_range_tree* tree, toku_range** b
static inline int toku_rt_super_create(toku_range_tree** upperptree, static inline int toku_rt_super_create(toku_range_tree** upperptree,
toku_range_tree** ptree, toku_range_tree** ptree,
int (*end_cmp)(const toku_point*,const toku_point*), int (*end_cmp)(const toku_point*,const toku_point*),
int (*data_cmp)(const DB_TXN*,const DB_TXN*), int (*data_cmp)(const TXNID,const TXNID),
BOOL allow_overlaps, BOOL allow_overlaps,
void* (*user_malloc) (size_t), void* (*user_malloc) (size_t),
void (*user_free) (void*), void (*user_free) (void*),
......
...@@ -34,9 +34,12 @@ typedef struct __toku_point toku_point; ...@@ -34,9 +34,12 @@ typedef struct __toku_point toku_point;
typedef struct { typedef struct {
toku_point* left; /**< Left end-point */ toku_point* left; /**< Left end-point */
toku_point* right; /**< Right end-point */ toku_point* right; /**< Right end-point */
DB_TXN* data; /**< Data associated with the range */ } toku_interval;
} toku_range;
typedef struct {
toku_interval ends;
TXNID data; /**< Data associated with the range */
} toku_range;
/** Export the internal representation to a sensible name */ /** Export the internal representation to a sensible name */
/* These lines will remain. */ /* These lines will remain. */
...@@ -84,7 +87,7 @@ int toku_rt_get_allow_overlaps(toku_range_tree* tree, BOOL* allowed); ...@@ -84,7 +87,7 @@ int toku_rt_get_allow_overlaps(toku_range_tree* tree, BOOL* allowed);
- Other exit codes may be forwarded from underlying system calls. */ - Other exit codes may be forwarded from underlying system calls. */
int toku_rt_create(toku_range_tree** ptree, int toku_rt_create(toku_range_tree** ptree,
int (*end_cmp)(const toku_point*,const toku_point*), int (*end_cmp)(const toku_point*,const toku_point*),
int (*data_cmp)(const DB_TXN*,const DB_TXN*), int (*data_cmp)(const TXNID,const TXNID),
BOOL allow_overlaps, BOOL allow_overlaps,
void* (*user_malloc) (size_t), void* (*user_malloc) (size_t),
void (*user_free) (void*), void (*user_free) (void*),
...@@ -101,6 +104,13 @@ int toku_rt_create(toku_range_tree** ptree, ...@@ -101,6 +104,13 @@ int toku_rt_create(toku_range_tree** ptree,
*/ */
int toku_rt_close(toku_range_tree* tree); int toku_rt_close(toku_range_tree* tree);
/**
Deletes all elements of a range tree.
\param tree The range tree to clear.
*/
void toku_rt_clear(toku_range_tree* tree);
/** /**
Finds ranges in the range tree that overlap a query range. Finds ranges in the range tree that overlap a query range.
...@@ -133,7 +143,7 @@ int toku_rt_close(toku_range_tree* tree); ...@@ -133,7 +143,7 @@ int toku_rt_close(toku_range_tree* tree);
parameter to specify whether more elements exist in the tree that overlap parameter to specify whether more elements exist in the tree that overlap
(in excess of the requested limit of k). (in excess of the requested limit of k).
*/ */
int toku_rt_find(toku_range_tree* tree,toku_range* query, u_int32_t k, int toku_rt_find(toku_range_tree* tree,toku_interval* query, u_int32_t k,
toku_range** buf, u_int32_t* buflen, u_int32_t* numfound); toku_range** buf, u_int32_t* buflen, u_int32_t* numfound);
......
...@@ -45,7 +45,7 @@ int dummy_cmp(const toku_point *a __attribute__((__unused__)), ...@@ -45,7 +45,7 @@ int dummy_cmp(const toku_point *a __attribute__((__unused__)),
return 0; return 0;
} }
int ptr_cmp(const DB_TXN* a, const DB_TXN* b) { int TXNID_cmp(const TXNID a, const TXNID b) {
return a < b ? -1 : (a != b); /* \marginpar{!?} */ return a < b ? -1 : (a != b); /* \marginpar{!?} */
} }
...@@ -55,9 +55,9 @@ int int_cmp(const toku_point* a, const toku_point*b) { ...@@ -55,9 +55,9 @@ int int_cmp(const toku_point* a, const toku_point*b) {
return x -y; return x -y;
} }
int char_cmp(const DB_TXN *a, const DB_TXN *b) { int char_cmp(const TXNID a, const TXNID b) {
int x = *(char*)a; int x = (char)a;
int y = *(char*)b; int y = (char)b;
return x -y; return x -y;
} }
...@@ -83,3 +83,14 @@ void* fail_malloc(size_t size) { ...@@ -83,3 +83,14 @@ void* fail_malloc(size_t size) {
} }
return malloc(size); return malloc(size);
} }
void verify_all_overlap(toku_interval* query, toku_range* list, unsigned listlen) {
unsigned i;
for (i = 0; i < listlen; i++) {
/* Range A and B overlap iff A.left <= B.right && B.left <= A.right */
assert(int_cmp(query->left, list[i].ends.right) <= 0 &&
int_cmp(list[i].ends.left, query->right) <= 0);
}
}
...@@ -10,10 +10,10 @@ int main(int argc, const char *argv[]) { ...@@ -10,10 +10,10 @@ int main(int argc, const char *argv[]) {
parse_args(argc, argv); parse_args(argc, argv);
/* Create tests */ /* Create tests */
r = toku_rt_create(NULL, int_cmp, ptr_cmp, FALSE, malloc, free, realloc); r = toku_rt_create(NULL, int_cmp, TXNID_cmp, FALSE, malloc, free, realloc);
CKERR2(r, EINVAL); CKERR2(r, EINVAL);
r = toku_rt_create(&tree, NULL, ptr_cmp, FALSE, malloc, free, realloc); r = toku_rt_create(&tree, NULL, TXNID_cmp, FALSE, malloc, free, realloc);
CKERR2(r, EINVAL); CKERR2(r, EINVAL);
assert(tree == NULL); assert(tree == NULL);
...@@ -21,13 +21,13 @@ int main(int argc, const char *argv[]) { ...@@ -21,13 +21,13 @@ int main(int argc, const char *argv[]) {
r = toku_rt_create(&tree, int_cmp, NULL, FALSE, malloc, free, realloc); r = toku_rt_create(&tree, int_cmp, NULL, FALSE, malloc, free, realloc);
CKERR2(r, EINVAL); CKERR2(r, EINVAL);
r = toku_rt_create(&tree, int_cmp, ptr_cmp, FALSE, NULL, free, realloc); r = toku_rt_create(&tree, int_cmp, TXNID_cmp, FALSE, NULL, free, realloc);
CKERR2(r, EINVAL); CKERR2(r, EINVAL);
r = toku_rt_create(&tree, int_cmp, ptr_cmp, FALSE, malloc, NULL, realloc); r = toku_rt_create(&tree, int_cmp, TXNID_cmp, FALSE, malloc, NULL, realloc);
CKERR2(r, EINVAL); CKERR2(r, EINVAL);
r = toku_rt_create(&tree, int_cmp, ptr_cmp, FALSE, malloc, free, NULL); r = toku_rt_create(&tree, int_cmp, TXNID_cmp, FALSE, malloc, free, NULL);
CKERR2(r, EINVAL); CKERR2(r, EINVAL);
assert(tree == NULL); assert(tree == NULL);
...@@ -40,7 +40,7 @@ int main(int argc, const char *argv[]) { ...@@ -40,7 +40,7 @@ int main(int argc, const char *argv[]) {
r = toku_rt_insert(NULL, &range); r = toku_rt_insert(NULL, &range);
CKERR2(r, EINVAL); CKERR2(r, EINVAL);
r = toku_rt_create(&tree, int_cmp, ptr_cmp, FALSE, malloc, free, realloc); r = toku_rt_create(&tree, int_cmp, TXNID_cmp, FALSE, malloc, free, realloc);
CKERR(r); CKERR(r);
assert(tree != NULL); assert(tree != NULL);
...@@ -53,7 +53,7 @@ int main(int argc, const char *argv[]) { ...@@ -53,7 +53,7 @@ int main(int argc, const char *argv[]) {
r = toku_rt_delete(NULL, &range); r = toku_rt_delete(NULL, &range);
CKERR2(r, EINVAL); CKERR2(r, EINVAL);
r = toku_rt_create(&tree, int_cmp, ptr_cmp, FALSE, malloc, free, realloc); r = toku_rt_create(&tree, int_cmp, TXNID_cmp, FALSE, malloc, free, realloc);
CKERR(r); CKERR(r);
assert(tree != NULL); assert(tree != NULL);
...@@ -66,38 +66,33 @@ int main(int argc, const char *argv[]) { ...@@ -66,38 +66,33 @@ int main(int argc, const char *argv[]) {
unsigned found; unsigned found;
int stuff[3] = {0,1,2}; int stuff[3] = {0,1,2};
range.left = (toku_point*)&stuff[0]; range.ends.left = (toku_point*)&stuff[0];
range.right = (toku_point*)&stuff[1]; range.ends.right = (toku_point*)&stuff[1];
range.data = NULL; range.data = 0;
r = toku_rt_create(&tree, int_cmp, ptr_cmp, FALSE, malloc, free, realloc); r = toku_rt_create(&tree, int_cmp, TXNID_cmp, FALSE, malloc, free, realloc);
CKERR(r); CKERR(r);
assert(tree != NULL); assert(tree != NULL);
r = toku_rt_find(NULL, &range, 2, &buf, &bufsize, &found); r = toku_rt_find(NULL, &range.ends, 2, &buf, &bufsize, &found);
CKERR2(r, EINVAL); CKERR2(r, EINVAL);
r = toku_rt_find(tree, NULL, 2, &buf, &bufsize, &found); r = toku_rt_find(tree, NULL, 2, &buf, &bufsize, &found);
CKERR2(r, EINVAL); CKERR2(r, EINVAL);
range.data = (DB_TXN*)&stuff[2]; r = toku_rt_find(tree, &range.ends, 2, NULL, &bufsize, &found);
r = toku_rt_find(tree, &range, 2, &buf, &bufsize, &found);
CKERR2(r, EINVAL); CKERR2(r, EINVAL);
range.data = NULL;
r = toku_rt_find(tree, &range, 2, NULL, &bufsize, &found); r = toku_rt_find(tree, &range.ends, 2, &buf, NULL, &found);
CKERR2(r, EINVAL);
r = toku_rt_find(tree, &range, 2, &buf, NULL, &found);
CKERR2(r, EINVAL); CKERR2(r, EINVAL);
unsigned oldbufsize = bufsize; unsigned oldbufsize = bufsize;
bufsize = 0; bufsize = 0;
r = toku_rt_find(tree, &range, 2, &buf, &bufsize, &found); r = toku_rt_find(tree, &range.ends, 2, &buf, &bufsize, &found);
CKERR2(r, EINVAL); CKERR2(r, EINVAL);
bufsize = oldbufsize; bufsize = oldbufsize;
r = toku_rt_find(tree, &range, 2, &buf, &bufsize, NULL); r = toku_rt_find(tree, &range.ends, 2, &buf, &bufsize, NULL);
CKERR2(r, EINVAL); CKERR2(r, EINVAL);
r = toku_rt_close(tree); CKERR(r); r = toku_rt_close(tree); CKERR(r);
...@@ -105,7 +100,7 @@ int main(int argc, const char *argv[]) { ...@@ -105,7 +100,7 @@ int main(int argc, const char *argv[]) {
/* Predecessor tests */ /* Predecessor tests */
toku_point* foo = (toku_point*)&stuff[0]; toku_point* foo = (toku_point*)&stuff[0];
BOOL wasfound; BOOL wasfound;
r = toku_rt_create(&tree, int_cmp, ptr_cmp, FALSE, malloc, free, realloc); r = toku_rt_create(&tree, int_cmp, TXNID_cmp, FALSE, malloc, free, realloc);
CKERR(r); CKERR(r);
assert(tree != NULL); assert(tree != NULL);
...@@ -124,7 +119,7 @@ int main(int argc, const char *argv[]) { ...@@ -124,7 +119,7 @@ int main(int argc, const char *argv[]) {
r = toku_rt_close(tree); CKERR(r); r = toku_rt_close(tree); CKERR(r);
#ifndef TOKU_RT_NOOVERLAPS #ifndef TOKU_RT_NOOVERLAPS
r = toku_rt_create(&tree, int_cmp, ptr_cmp, TRUE, malloc, free, realloc); r = toku_rt_create(&tree, int_cmp, TXNID_cmp, TRUE, malloc, free, realloc);
CKERR(r); CKERR(r);
assert(tree != NULL); assert(tree != NULL);
...@@ -138,7 +133,7 @@ int main(int argc, const char *argv[]) { ...@@ -138,7 +133,7 @@ int main(int argc, const char *argv[]) {
/* Successor tests */ /* Successor tests */
r = toku_rt_create(&tree, int_cmp, ptr_cmp, FALSE, malloc, free, realloc); r = toku_rt_create(&tree, int_cmp, TXNID_cmp, FALSE, malloc, free, realloc);
CKERR(r); CKERR(r);
assert(tree != NULL); assert(tree != NULL);
...@@ -157,7 +152,7 @@ int main(int argc, const char *argv[]) { ...@@ -157,7 +152,7 @@ int main(int argc, const char *argv[]) {
r = toku_rt_close(tree); CKERR(r); r = toku_rt_close(tree); CKERR(r);
#ifndef TOKU_RT_NOOVERLAPS #ifndef TOKU_RT_NOOVERLAPS
r = toku_rt_create(&tree, int_cmp, ptr_cmp, TRUE, malloc, free, realloc); r = toku_rt_create(&tree, int_cmp, TXNID_cmp, TRUE, malloc, free, realloc);
CKERR(r); CKERR(r);
assert(tree != NULL); assert(tree != NULL);
...@@ -174,7 +169,7 @@ int main(int argc, const char *argv[]) { ...@@ -174,7 +169,7 @@ int main(int argc, const char *argv[]) {
r = toku_rt_get_allow_overlaps(NULL, &allowed); r = toku_rt_get_allow_overlaps(NULL, &allowed);
CKERR2(r, EINVAL); CKERR2(r, EINVAL);
r = toku_rt_create(&tree, int_cmp, ptr_cmp, FALSE, malloc, free, realloc); r = toku_rt_create(&tree, int_cmp, TXNID_cmp, FALSE, malloc, free, realloc);
CKERR(r); CKERR(r);
assert(tree != NULL); assert(tree != NULL);
......
...@@ -25,80 +25,80 @@ int main(int argc, const char *argv[]) { ...@@ -25,80 +25,80 @@ int main(int argc, const char *argv[]) {
CKERR(r); CKERR(r);
/* Verify we can insert a trivial range and lose it. */ /* Verify we can insert a trivial range and lose it. */
range.left = (toku_point*)&nums[1]; range.ends.left = (toku_point*)&nums[1];
range.right = (toku_point*)&nums[1]; range.ends.right = (toku_point*)&nums[1];
range.data = (DB_TXN*)&letters[0]; range.data = (TXNID)letters[0];
r = toku_rt_insert(tree, &range); CKERR(r); r = toku_rt_insert(tree, &range); CKERR(r);
u_int32_t num_in_range; u_int32_t num_in_range;
r = toku_rt_get_size(tree, &num_in_range); CKERR(r); r = toku_rt_get_size(tree, &num_in_range); CKERR(r);
assert(num_in_range == 1); assert(num_in_range == 1);
r = toku_rt_delete(tree, &range); CKERR(r); r = toku_rt_delete(tree, &range); CKERR(r);
range.left = (toku_point*)&nums[1]; range.ends.left = (toku_point*)&nums[1];
range.right = (toku_point*)&nums[5]; range.ends.right = (toku_point*)&nums[5];
range.data = (DB_TXN*)&letters[0]; range.data = (TXNID)letters[0];
r = toku_rt_insert(tree, &range); CKERR(r); r = toku_rt_insert(tree, &range); CKERR(r);
/* Try and fail to insert exact same thing. */ /* Try and fail to insert exact same thing. */
r = toku_rt_insert(tree, &range); CKERR2(r,EDOM); r = toku_rt_insert(tree, &range); CKERR2(r,EDOM);
/* Try and succeed to insert (and delete) similar yet different things */ /* Try and succeed to insert (and delete) similar yet different things */
range.right = (toku_point*)&nums[6]; range.ends.right = (toku_point*)&nums[6];
r = toku_rt_insert(tree, &range); CKERR(r); r = toku_rt_insert(tree, &range); CKERR(r);
r = toku_rt_delete(tree, &range); CKERR(r); r = toku_rt_delete(tree, &range); CKERR(r);
range.right = (toku_point*)&nums[5]; range.ends.right = (toku_point*)&nums[5];
range.data = (DB_TXN*)&letters[1]; range.data = (TXNID)letters[1];
r = toku_rt_insert(tree, &range); CKERR(r); r = toku_rt_insert(tree, &range); CKERR(r);
r = toku_rt_delete(tree, &range); CKERR(r); r = toku_rt_delete(tree, &range); CKERR(r);
range.data = (DB_TXN*)&letters[0]; range.data = (TXNID)letters[0];
range.left = (toku_point*)&nums[2]; range.ends.left = (toku_point*)&nums[2];
range.right = (toku_point*)&nums[6]; range.ends.right = (toku_point*)&nums[6];
range.data = (DB_TXN*)&letters[0]; range.data = (TXNID)letters[0];
r = toku_rt_insert(tree, &range); CKERR(r); r = toku_rt_insert(tree, &range); CKERR(r);
range.left = (toku_point*)&nums[3]; range.ends.left = (toku_point*)&nums[3];
range.right = (toku_point*)&nums[7]; range.ends.right = (toku_point*)&nums[7];
range.data = (DB_TXN*)&letters[0]; range.data = (TXNID)letters[0];
r = toku_rt_insert(tree, &range); CKERR(r); r = toku_rt_insert(tree, &range); CKERR(r);
range.left = (toku_point*)&nums[2]; range.ends.left = (toku_point*)&nums[2];
range.right = (toku_point*)&nums[6]; range.ends.right = (toku_point*)&nums[6];
range.data = (DB_TXN*)&letters[1]; range.data = (TXNID)letters[1];
r = toku_rt_insert(tree, &range); CKERR(r); r = toku_rt_insert(tree, &range); CKERR(r);
range.left = (toku_point*)&nums[2]; range.ends.left = (toku_point*)&nums[2];
range.right = (toku_point*)&nums[6]; range.ends.right = (toku_point*)&nums[6];
range.data = (DB_TXN*)&letters[0]; range.data = (TXNID)letters[0];
r = toku_rt_delete(tree, &range); CKERR(r); r = toku_rt_delete(tree, &range); CKERR(r);
/* Try to delete again, make sure it fails. (Not there anymore) */ /* Try to delete again, make sure it fails. (Not there anymore) */
r = toku_rt_delete(tree, &range); CKERR2(r,EDOM); r = toku_rt_delete(tree, &range); CKERR2(r,EDOM);
range.left = (toku_point*)&nums[2]; range.ends.left = (toku_point*)&nums[2];
range.right = (toku_point*)&nums[6]; range.ends.right = (toku_point*)&nums[6];
range.data = (DB_TXN*)&letters[0]; range.data = (TXNID)letters[0];
r = toku_rt_insert(tree, &range); CKERR(r); r = toku_rt_insert(tree, &range); CKERR(r);
range.left = (toku_point*)&nums[2]; range.ends.left = (toku_point*)&nums[2];
range.right = (toku_point*)&nums[6]; range.ends.right = (toku_point*)&nums[6];
range.data = (DB_TXN*)&letters[1]; range.data = (TXNID)letters[1];
r = toku_rt_delete(tree, &range); CKERR(r); r = toku_rt_delete(tree, &range); CKERR(r);
/* Clean up. */ /* Clean up. */
range.left = (toku_point*)&nums[1]; range.ends.left = (toku_point*)&nums[1];
range.right = (toku_point*)&nums[5]; range.ends.right = (toku_point*)&nums[5];
range.data = (DB_TXN*)&letters[0]; range.data = (TXNID)letters[0];
r = toku_rt_delete(tree, &range); CKERR(r); r = toku_rt_delete(tree, &range); CKERR(r);
range.left = (toku_point*)&nums[2]; range.ends.left = (toku_point*)&nums[2];
range.right = (toku_point*)&nums[6]; range.ends.right = (toku_point*)&nums[6];
range.data = (DB_TXN*)&letters[0]; range.data = (TXNID)letters[0];
r = toku_rt_delete(tree, &range); CKERR(r); r = toku_rt_delete(tree, &range); CKERR(r);
range.left = (toku_point*)&nums[3]; range.ends.left = (toku_point*)&nums[3];
range.right = (toku_point*)&nums[7]; range.ends.right = (toku_point*)&nums[7];
range.data = (DB_TXN*)&letters[0]; range.data = (TXNID)letters[0];
r = toku_rt_delete(tree, &range); CKERR(r); r = toku_rt_delete(tree, &range); CKERR(r);
/* Done */ /* Done */
...@@ -116,60 +116,60 @@ int main(int argc, const char *argv[]) { ...@@ -116,60 +116,60 @@ int main(int argc, const char *argv[]) {
CKERR(r); CKERR(r);
/* Verify we can insert a trivial range and lose it. */ /* Verify we can insert a trivial range and lose it. */
range.left = (toku_point*)&nums[1]; range.ends.left = (toku_point*)&nums[1];
range.right = (toku_point*)&nums[1]; range.ends.right = (toku_point*)&nums[1];
range.data = (DB_TXN*)&letters[0]; range.data = (TXNID)letters[0];
r = toku_rt_insert(tree, &range); CKERR(r); r = toku_rt_insert(tree, &range); CKERR(r);
r = toku_rt_delete(tree, &range); CKERR(r); r = toku_rt_delete(tree, &range); CKERR(r);
range.left = (toku_point*)&nums[1]; range.ends.left = (toku_point*)&nums[1];
range.right = (toku_point*)&nums[3]; range.ends.right = (toku_point*)&nums[3];
range.data = (DB_TXN*)&letters[0]; range.data = (TXNID)letters[0];
r = toku_rt_insert(tree, &range); CKERR(r); r = toku_rt_insert(tree, &range); CKERR(r);
/* Try and fail to insert exact same thing. */ /* Try and fail to insert exact same thing. */
r = toku_rt_insert(tree, &range); CKERR2(r,EDOM); r = toku_rt_insert(tree, &range); CKERR2(r,EDOM);
/* Try (and fail) to insert an overlapping range in a nooverlap tree. */ /* Try (and fail) to insert an overlapping range in a nooverlap tree. */
range.left = (toku_point*)&nums[0]; range.ends.left = (toku_point*)&nums[0];
range.right = (toku_point*)&nums[4]; range.ends.right = (toku_point*)&nums[4];
range.data = (DB_TXN*)&letters[0]; range.data = (TXNID)letters[0];
r = toku_rt_insert(tree, &range); CKERR2(r,EDOM); r = toku_rt_insert(tree, &range); CKERR2(r,EDOM);
/* Try (and fail) to insert an overlapping range (different data) in a /* Try (and fail) to insert an overlapping range (different data) in a
nooverlap tree. */ nooverlap tree. */
range.left = (toku_point*)&nums[0]; range.ends.left = (toku_point*)&nums[0];
range.right = (toku_point*)&nums[4]; range.ends.right = (toku_point*)&nums[4];
range.data = (DB_TXN*)&letters[1]; range.data = (TXNID)letters[1];
r = toku_rt_insert(tree, &range); CKERR2(r,EDOM); r = toku_rt_insert(tree, &range); CKERR2(r,EDOM);
range.left = (toku_point*)&nums[4]; range.ends.left = (toku_point*)&nums[4];
range.right = (toku_point*)&nums[6]; range.ends.right = (toku_point*)&nums[6];
range.data = (DB_TXN*)&letters[1]; range.data = (TXNID)letters[1];
r = toku_rt_insert(tree, &range); CKERR(r); r = toku_rt_insert(tree, &range); CKERR(r);
range.left = (toku_point*)&nums[4]; range.ends.left = (toku_point*)&nums[4];
range.right = (toku_point*)&nums[6]; range.ends.right = (toku_point*)&nums[6];
range.data = (DB_TXN*)&letters[1]; range.data = (TXNID)letters[1];
r = toku_rt_delete(tree, &range); CKERR(r); r = toku_rt_delete(tree, &range); CKERR(r);
/* Try to delete again, make sure it fails. (Not there anymore) */ /* Try to delete again, make sure it fails. (Not there anymore) */
r = toku_rt_delete(tree, &range); CKERR2(r,EDOM); r = toku_rt_delete(tree, &range); CKERR2(r,EDOM);
range.left = (toku_point*)&nums[4]; range.ends.left = (toku_point*)&nums[4];
range.right = (toku_point*)&nums[6]; range.ends.right = (toku_point*)&nums[6];
range.data = (DB_TXN*)&letters[1]; range.data = (TXNID)letters[1];
r = toku_rt_insert(tree, &range); CKERR(r); r = toku_rt_insert(tree, &range); CKERR(r);
range.left = (toku_point*)&nums[1]; range.ends.left = (toku_point*)&nums[1];
range.right = (toku_point*)&nums[3]; range.ends.right = (toku_point*)&nums[3];
range.data = (DB_TXN*)&letters[0]; range.data = (TXNID)letters[0];
r = toku_rt_delete(tree, &range); CKERR(r); r = toku_rt_delete(tree, &range); CKERR(r);
/* Clean up. */ /* Clean up. */
range.left = (toku_point*)&nums[4]; range.ends.left = (toku_point*)&nums[4];
range.right = (toku_point*)&nums[6]; range.ends.right = (toku_point*)&nums[6];
range.data = (DB_TXN*)&letters[1]; range.data = (TXNID)letters[1];
r = toku_rt_delete(tree, &range); CKERR(r); r = toku_rt_delete(tree, &range); CKERR(r);
/* Done */ /* Done */
......
...@@ -35,18 +35,18 @@ void RunTest (BOOL f_overlaps_allowed) { ...@@ -35,18 +35,18 @@ void RunTest (BOOL f_overlaps_allowed) {
/* Insert lots of ranges */ /* Insert lots of ranges */
for (i = 0; i < 512; i++) { for (i = 0; i < 512; i++) {
j = i + i; j = i + i;
range.left = (toku_point*)&nums[j]; range.ends.left = (toku_point*)&nums[j];
range.right = (toku_point*)&nums[j+1]; range.ends.right = (toku_point*)&nums[j+1];
range.data = (DB_TXN*)&letters[0]; range.data = (TXNID)letters[0];
r = toku_rt_insert(tree, &range); CKERR(r); r = toku_rt_insert(tree, &range); CKERR(r);
} }
/* Decrease lots of ranges */ /* Decrease lots of ranges */
for (i = 0; i < 512; i++) { for (i = 0; i < 512; i++) {
j = i + i; j = i + i;
range.left = (toku_point*)&nums[j]; range.ends.left = (toku_point*)&nums[j];
range.right = (toku_point*)&nums[j+1]; range.ends.right = (toku_point*)&nums[j+1];
range.data = (DB_TXN*)&letters[0]; range.data = (TXNID)letters[0];
r = toku_rt_delete(tree, &range); CKERR(r); r = toku_rt_delete(tree, &range); CKERR(r);
} }
......
...@@ -27,9 +27,9 @@ void run_test (BOOL overlap_allowed) { ...@@ -27,9 +27,9 @@ void run_test (BOOL overlap_allowed) {
); );
CKERR(r); CKERR(r);
range.left = (toku_point*)&nums[1]; range.ends.left = (toku_point*)&nums[1];
range.right = (toku_point*)&nums[5]; range.ends.right = (toku_point*)&nums[5];
range.data = (DB_TXN*)&letters[0]; range.data = (TXNID)letters[0];
r = toku_rt_insert(tree, &range); CKERR(r); r = toku_rt_insert(tree, &range); CKERR(r);
r = toku_rt_close(tree); CKERR(r); r = toku_rt_close(tree); CKERR(r);
......
This diff is collapsed.
...@@ -2,16 +2,6 @@ ...@@ -2,16 +2,6 @@
#include "test.h" #include "test.h"
void verify_all_overlap(toku_range* query, toku_range* list, unsigned listlen) {
unsigned i;
for (i = 0; i < listlen; i++) {
/* Range A and B overlap iff A.left <= B.right && B.left <= A.right */
assert(int_cmp(query->left, list[i].right) <= 0 &&
int_cmp(list[i].left, query->right) <= 0);
}
}
int nums[200]; int nums[200];
char letters[2] = {'A','B'}; char letters[2] = {'A','B'};
...@@ -19,11 +9,16 @@ toku_range_tree *tree; ...@@ -19,11 +9,16 @@ toku_range_tree *tree;
toku_range* buf; toku_range* buf;
unsigned buflen; unsigned buflen;
toku_range* init_range(toku_range* range, int left, int right, int data) { toku_interval* init_query(toku_interval* range, int left, int right) {
range->left = (toku_point*)&nums[left]; range->left = (toku_point*)&nums[left];
range->right = (toku_point*)&nums[right]; range->right = (toku_point*)&nums[right];
if (data < 0) range->data = NULL; return range;
else range->data = (DB_TXN*)&letters[data]; }
toku_range* init_range(toku_range* range, int left, int right, int data) {
init_query(&range->ends, left, right);
if (data < 0) range->data = 0;
else range->data = (TXNID)letters[data];
return range; return range;
} }
...@@ -43,7 +38,7 @@ void close_tree(void) { ...@@ -43,7 +38,7 @@ void close_tree(void) {
r = toku_rt_close(tree); CKERR(r); r = toku_rt_close(tree); CKERR(r);
} }
void runsearch(int rexpect, toku_range* query, toku_range* expect) { void runsearch(int rexpect, toku_interval* query, toku_range* expect) {
int r; int r;
unsigned found; unsigned found;
r = toku_rt_find(tree, query, 0, &buf, &buflen, &found); r = toku_rt_find(tree, query, 0, &buf, &buflen, &found);
...@@ -51,8 +46,8 @@ void runsearch(int rexpect, toku_range* query, toku_range* expect) { ...@@ -51,8 +46,8 @@ void runsearch(int rexpect, toku_range* query, toku_range* expect) {
if (rexpect != 0) return; if (rexpect != 0) return;
assert(found == 1); assert(found == 1);
assert(int_cmp(buf[0].left, expect->left) == 0 && assert(int_cmp(buf[0].ends.left, expect->ends.left) == 0 &&
int_cmp(buf[0].right, expect->right) == 0 && int_cmp(buf[0].ends.right, expect->ends.right) == 0 &&
char_cmp(buf[0].data, expect->data) == 0); char_cmp(buf[0].data, expect->data) == 0);
} }
...@@ -62,7 +57,7 @@ void runinsert(int rexpect, toku_range* toinsert) { ...@@ -62,7 +57,7 @@ void runinsert(int rexpect, toku_range* toinsert) {
CKERR2(r, rexpect); CKERR2(r, rexpect);
} }
void runlimitsearch(toku_range* query, unsigned limit, unsigned findexpect) { void runlimitsearch(toku_interval* query, unsigned limit, unsigned findexpect) {
int r; int r;
unsigned found; unsigned found;
r=toku_rt_find(tree, query, limit, &buf, &buflen, &found); CKERR(r); r=toku_rt_find(tree, query, limit, &buf, &buflen, &found); CKERR(r);
...@@ -72,7 +67,7 @@ void runlimitsearch(toku_range* query, unsigned limit, unsigned findexpect) { ...@@ -72,7 +67,7 @@ void runlimitsearch(toku_range* query, unsigned limit, unsigned findexpect) {
} }
void tests(BOOL allow_overlaps) { void tests(BOOL allow_overlaps) {
toku_range query; toku_interval query;
toku_range insert; toku_range insert;
/* /*
Limited/Unlimited Queries Limited/Unlimited Queries
...@@ -88,30 +83,30 @@ void tests(BOOL allow_overlaps) { ...@@ -88,30 +83,30 @@ void tests(BOOL allow_overlaps) {
runinsert(0, init_range(&insert, 6, 7, 0)); runinsert(0, init_range(&insert, 6, 7, 0));
runinsert(0, init_range(&insert, 8, 9, 0)); runinsert(0, init_range(&insert, 8, 9, 0));
runlimitsearch(init_range(&query, 2, 7, -1), 0, 3); runlimitsearch(init_query(&query, 2, 7), 0, 3);
runlimitsearch(init_range(&query, 2, 7, -1), 1, 1); runlimitsearch(init_query(&query, 2, 7), 1, 1);
runlimitsearch(init_range(&query, 2, 7, -1), 2, 2); runlimitsearch(init_query(&query, 2, 7), 2, 2);
runlimitsearch(init_range(&query, 2, 7, -1), 3, 3); runlimitsearch(init_query(&query, 2, 7), 3, 3);
runlimitsearch(init_range(&query, 2, 7, -1), 4, 3); runlimitsearch(init_query(&query, 2, 7), 4, 3);
close_tree(); close_tree();
/* Tree is empty (return none) */ /* Tree is empty (return none) */
setup_tree(allow_overlaps, FALSE, 0, 0, 0); setup_tree(allow_overlaps, FALSE, 0, 0, 0);
runlimitsearch(init_range(&query, 0, 0, -1), 0, 0); runlimitsearch(init_query(&query, 0, 0), 0, 0);
close_tree(); close_tree();
/* Tree contains only elements to the left. */ /* Tree contains only elements to the left. */
setup_tree(allow_overlaps, FALSE, 0, 0, 0); setup_tree(allow_overlaps, FALSE, 0, 0, 0);
runinsert(0, init_range(&insert, 1, 2, 0)); runinsert(0, init_range(&insert, 1, 2, 0));
runinsert(0, init_range(&insert, 3, 4, 0)); runinsert(0, init_range(&insert, 3, 4, 0));
runlimitsearch(init_range(&query, 8, 30, -1), 0, 0); runlimitsearch(init_query(&query, 8, 30), 0, 0);
close_tree(); close_tree();
/* Tree contains only elements to the right. */ /* Tree contains only elements to the right. */
setup_tree(allow_overlaps, FALSE, 0, 0, 0); setup_tree(allow_overlaps, FALSE, 0, 0, 0);
runinsert(0, init_range(&insert, 10, 20, 0)); runinsert(0, init_range(&insert, 10, 20, 0));
runinsert(0, init_range(&insert, 30, 40, 0)); runinsert(0, init_range(&insert, 30, 40, 0));
runlimitsearch(init_range(&query, 5, 7, -1), 0, 0); runlimitsearch(init_query(&query, 5, 7), 0, 0);
close_tree(); close_tree();
/* Tree contains only elements to the left and to the right. */ /* Tree contains only elements to the left and to the right. */
...@@ -120,7 +115,7 @@ void tests(BOOL allow_overlaps) { ...@@ -120,7 +115,7 @@ void tests(BOOL allow_overlaps) {
runinsert(0, init_range(&insert, 30, 40, 0)); runinsert(0, init_range(&insert, 30, 40, 0));
runinsert(0, init_range(&insert, 70, 80, 0)); runinsert(0, init_range(&insert, 70, 80, 0));
runinsert(0, init_range(&insert, 90, 100, 0)); runinsert(0, init_range(&insert, 90, 100, 0));
runlimitsearch(init_range(&query, 60, 65, -1), 0, 0); runlimitsearch(init_query(&query, 60, 65), 0, 0);
close_tree(); close_tree();
/* Tree contains overlaps and elements to the left. */ /* Tree contains overlaps and elements to the left. */
...@@ -129,7 +124,7 @@ void tests(BOOL allow_overlaps) { ...@@ -129,7 +124,7 @@ void tests(BOOL allow_overlaps) {
runinsert(0, init_range(&insert, 30, 40, 0)); runinsert(0, init_range(&insert, 30, 40, 0));
runinsert(0, init_range(&insert, 60, 80, 0)); runinsert(0, init_range(&insert, 60, 80, 0));
runinsert(0, init_range(&insert, 90, 100, 0)); runinsert(0, init_range(&insert, 90, 100, 0));
runlimitsearch(init_range(&query, 70, 95, -1), 0, 2); runlimitsearch(init_query(&query, 70, 95), 0, 2);
close_tree(); close_tree();
/* Tree contains overlaps and elements to the right. */ /* Tree contains overlaps and elements to the right. */
...@@ -138,7 +133,7 @@ void tests(BOOL allow_overlaps) { ...@@ -138,7 +133,7 @@ void tests(BOOL allow_overlaps) {
runinsert(0, init_range(&insert, 130, 140, 0)); runinsert(0, init_range(&insert, 130, 140, 0));
runinsert(0, init_range(&insert, 60, 80, 0)); runinsert(0, init_range(&insert, 60, 80, 0));
runinsert(0, init_range(&insert, 90, 100, 0)); runinsert(0, init_range(&insert, 90, 100, 0));
runlimitsearch(init_range(&query, 70, 95, -1), 0, 2); runlimitsearch(init_query(&query, 70, 95), 0, 2);
close_tree(); close_tree();
/* Tree contains overlaps and elements to the left and to the right. */ /* Tree contains overlaps and elements to the left and to the right. */
...@@ -149,7 +144,7 @@ void tests(BOOL allow_overlaps) { ...@@ -149,7 +144,7 @@ void tests(BOOL allow_overlaps) {
runinsert(0, init_range(&insert, 130, 140, 0)); runinsert(0, init_range(&insert, 130, 140, 0));
runinsert(0, init_range(&insert, 60, 80, 0)); runinsert(0, init_range(&insert, 60, 80, 0));
runinsert(0, init_range(&insert, 90, 100, 0)); runinsert(0, init_range(&insert, 90, 100, 0));
runlimitsearch(init_range(&query, 70, 95, -1), 0, 2); runlimitsearch(init_query(&query, 70, 95), 0, 2);
close_tree(); close_tree();
} }
......
...@@ -2,16 +2,6 @@ ...@@ -2,16 +2,6 @@
#include "test.h" #include "test.h"
void verify_all_overlap(toku_range* query, toku_range* list, unsigned listlen) {
unsigned i;
for (i = 0; i < listlen; i++) {
/* Range A and B overlap iff A.left <= B.right && B.left <= A.right */
assert(int_cmp(query->left, list[i].right) <= 0 &&
int_cmp(list[i].left, query->right) <= 0);
}
}
int nums[8] = {0,1,2,3,4,5,6,7}; int nums[8] = {0,1,2,3,4,5,6,7};
char letters[2] = {'A','B'}; char letters[2] = {'A','B'};
...@@ -19,11 +9,16 @@ toku_range_tree *tree; ...@@ -19,11 +9,16 @@ toku_range_tree *tree;
toku_range* buf; toku_range* buf;
unsigned buflen; unsigned buflen;
toku_range* init_range(toku_range* range, int left, int right, int data) { toku_interval* init_query(toku_interval* range, int left, int right) {
range->left = (toku_point*)&nums[left]; range->left = (toku_point*)&nums[left];
range->right = (toku_point*)&nums[right]; range->right = (toku_point*)&nums[right];
if (data < 0) range->data = NULL; return range;
else range->data = (DB_TXN*)&letters[data]; }
toku_range* init_range(toku_range* range, int left, int right, int data) {
init_query(&range->ends, left, right);
if (data < 0) range->data = 0;
else range->data = (TXNID)letters[data];
return range; return range;
} }
...@@ -40,7 +35,7 @@ void close_tree(void) { ...@@ -40,7 +35,7 @@ void close_tree(void) {
r = toku_rt_close(tree); CKERR(r); r = toku_rt_close(tree); CKERR(r);
} }
void runsearch(int rexpect, toku_range* query, toku_range* expect) { void runsearch(int rexpect, toku_interval* query, toku_range* expect) {
int r; int r;
unsigned found; unsigned found;
r = toku_rt_find(tree, query, 0, &buf, &buflen, &found); r = toku_rt_find(tree, query, 0, &buf, &buflen, &found);
...@@ -48,8 +43,8 @@ void runsearch(int rexpect, toku_range* query, toku_range* expect) { ...@@ -48,8 +43,8 @@ void runsearch(int rexpect, toku_range* query, toku_range* expect) {
if (rexpect != 0) return; if (rexpect != 0) return;
assert(found == 1); assert(found == 1);
assert(int_cmp(buf[0].left, expect->left) == 0 && assert(int_cmp(buf[0].ends.left, expect->ends.left) == 0 &&
int_cmp(buf[0].right, expect->right) == 0 && int_cmp(buf[0].ends.right, expect->ends.right) == 0 &&
char_cmp(buf[0].data, expect->data) == 0); char_cmp(buf[0].data, expect->data) == 0);
} }
...@@ -71,7 +66,7 @@ void verify_overlap(BOOL allow_overlaps) { ...@@ -71,7 +66,7 @@ void verify_overlap(BOOL allow_overlaps) {
void tests(BOOL allow_overlaps) { void tests(BOOL allow_overlaps) {
toku_range expect; toku_range expect;
toku_range query; toku_interval query;
toku_range toinsert; toku_range toinsert;
/* /*
...@@ -88,12 +83,12 @@ void tests(BOOL allow_overlaps) { ...@@ -88,12 +83,12 @@ void tests(BOOL allow_overlaps) {
is set appropriately. */ is set appropriately. */
setup_tree(allow_overlaps, 0, 1, 0); setup_tree(allow_overlaps, 0, 1, 0);
verify_overlap(allow_overlaps); verify_overlap(allow_overlaps);
runsearch(0, init_range(&query, 1, 2, -1), init_range(&expect, 0, 1, 0)); runsearch(0, init_query(&query, 1, 2), init_range(&expect, 0, 1, 0));
close_tree(); close_tree();
/* Tree: {|1-2|}, query of |0-1| returns |1-2| */ /* Tree: {|1-2|}, query of |0-1| returns |1-2| */
setup_tree(allow_overlaps, 1, 2, 0); setup_tree(allow_overlaps, 1, 2, 0);
runsearch(0, init_range(&query, 0, 1, -1), init_range(&expect, 1, 2, 0)); runsearch(0, init_query(&query, 0, 1), init_range(&expect, 1, 2, 0));
close_tree(); close_tree();
/* Tree: {|1-2|}, insert of of |0-1| success == allow_overlaps */ /* Tree: {|1-2|}, insert of of |0-1| success == allow_overlaps */
...@@ -117,12 +112,12 @@ void tests(BOOL allow_overlaps) { ...@@ -117,12 +112,12 @@ void tests(BOOL allow_overlaps) {
/* Tree: {|0-3|}, query of |1-2| returns |0-3| */ /* Tree: {|0-3|}, query of |1-2| returns |0-3| */
setup_tree(allow_overlaps, 0, 3, 0); setup_tree(allow_overlaps, 0, 3, 0);
runsearch(0, init_range(&query, 1, 2, -1), init_range(&expect, 0, 3, 0)); runsearch(0, init_query(&query, 1, 2), init_range(&expect, 0, 3, 0));
close_tree(); close_tree();
/* Tree: {|1-2|}, query of |0-3| returns |1-2| */ /* Tree: {|1-2|}, query of |0-3| returns |1-2| */
setup_tree(allow_overlaps, 1, 2, 0); setup_tree(allow_overlaps, 1, 2, 0);
runsearch(0, init_range(&query, 0, 3, -1), init_range(&expect, 1, 2, 0)); runsearch(0, init_query(&query, 0, 3), init_range(&expect, 1, 2, 0));
close_tree(); close_tree();
/* Tree: {|1-2|}, insert of of |0-3| success == allow_overlaps */ /* Tree: {|1-2|}, insert of of |0-3| success == allow_overlaps */
...@@ -144,7 +139,7 @@ void tests(BOOL allow_overlaps) { ...@@ -144,7 +139,7 @@ void tests(BOOL allow_overlaps) {
/* Tree: {|0-3|}, query of |0-3| returns |0-3| */ /* Tree: {|0-3|}, query of |0-3| returns |0-3| */
setup_tree(allow_overlaps, 0, 3, 0); setup_tree(allow_overlaps, 0, 3, 0);
runsearch(0, init_range(&query, 0, 3, -1), init_range(&expect, 0, 3, 0)); runsearch(0, init_query(&query, 0, 3), init_range(&expect, 0, 3, 0));
close_tree(); close_tree();
/* Tree: {(|0-3|,0)}, insert of of (|0-3|,1) success == allow_overlaps */ /* Tree: {(|0-3|,0)}, insert of of (|0-3|,1) success == allow_overlaps */
......
...@@ -2,16 +2,6 @@ ...@@ -2,16 +2,6 @@
#include "test.h" #include "test.h"
void verify_all_overlap(toku_range* query, toku_range* list, unsigned listlen) {
unsigned i;
for (i = 0; i < listlen; i++) {
/* Range A and B overlap iff A.left <= B.right && B.left <= A.right */
assert(int_cmp(query->left, list[i].right) <= 0 &&
int_cmp(list[i].left, query->right) <= 0);
}
}
int nums[64 << 3]; int nums[64 << 3];
const size_t numlen = sizeof(nums) / sizeof(nums[0]); const size_t numlen = sizeof(nums) / sizeof(nums[0]);
char letters[2] = {'A','B'}; char letters[2] = {'A','B'};
...@@ -20,12 +10,16 @@ toku_range_tree *tree; ...@@ -20,12 +10,16 @@ toku_range_tree *tree;
toku_range* buf; toku_range* buf;
unsigned buflen; unsigned buflen;
toku_range* init_range(toku_range* range, unsigned left, unsigned right, toku_interval* init_query(toku_interval* range, unsigned left, unsigned right) {
int data) {
range->left = (toku_point*)&nums[left]; range->left = (toku_point*)&nums[left];
range->right = (toku_point*)&nums[right]; range->right = (toku_point*)&nums[right];
if (data < 0) range->data = NULL; return range;
else range->data = (DB_TXN*)&letters[data]; }
toku_range* init_range(toku_range* range, unsigned left, unsigned right, int data) {
init_query(&range->ends, left, right);
if (data < 0) range->data = 0;
else range->data = (TXNID)letters[data];
return range; return range;
} }
...@@ -46,7 +40,7 @@ void close_tree(void) { ...@@ -46,7 +40,7 @@ void close_tree(void) {
r = toku_rt_close(tree); CKERR(r); r = toku_rt_close(tree); CKERR(r);
} }
void runsearch(int rexpect, toku_range* query, toku_range* expect) { void runsearch(int rexpect, toku_interval* query, toku_range* expect) {
int r; int r;
unsigned found; unsigned found;
r = toku_rt_find(tree, query, 0, &buf, &buflen, &found); r = toku_rt_find(tree, query, 0, &buf, &buflen, &found);
...@@ -54,8 +48,8 @@ void runsearch(int rexpect, toku_range* query, toku_range* expect) { ...@@ -54,8 +48,8 @@ void runsearch(int rexpect, toku_range* query, toku_range* expect) {
if (rexpect != 0) return; if (rexpect != 0) return;
assert(found == 1); assert(found == 1);
assert(int_cmp(buf[0].left, expect->left) == 0 && assert(int_cmp(buf[0].ends.left, expect->ends.left) == 0 &&
int_cmp(buf[0].right, expect->right) == 0 && int_cmp(buf[0].ends.right, expect->ends.right) == 0 &&
char_cmp(buf[0].data, expect->data) == 0); char_cmp(buf[0].data, expect->data) == 0);
} }
...@@ -71,7 +65,7 @@ void rundelete(int rexpect, toku_range* todelete) { ...@@ -71,7 +65,7 @@ void rundelete(int rexpect, toku_range* todelete) {
CKERR2(r, rexpect); CKERR2(r, rexpect);
} }
void runlimitsearch(toku_range* query, unsigned limit, unsigned findexpect) { void runlimitsearch(toku_interval* query, unsigned limit, unsigned findexpect) {
int r; int r;
unsigned found; unsigned found;
r=toku_rt_find(tree, query, limit, &buf, &buflen, &found); CKERR(r); r=toku_rt_find(tree, query, limit, &buf, &buflen, &found); CKERR(r);
......
#include "test.h" #include "test.h"
void verify_all_overlap(toku_range* query, toku_range* list, unsigned listlen) {
unsigned i;
for (i = 0; i < listlen; i++) {
/* Range A and B overlap iff A.left <= B.right && B.left <= A.right */
assert(int_cmp(query->left, list[i].right) <= 0 &&
int_cmp(list[i].left, query->right) <= 0);
}
}
int nums[200]; int nums[200];
char letters[2] = {'A','B'}; char letters[2] = {'A','B'};
...@@ -17,11 +7,16 @@ toku_range_tree *tree; ...@@ -17,11 +7,16 @@ toku_range_tree *tree;
toku_range* buf; toku_range* buf;
unsigned buflen; unsigned buflen;
toku_range* init_range(toku_range* range, int left, int right, int data) { toku_interval* init_query(toku_interval* range, int left, int right) {
range->left = (toku_point*)&nums[left]; range->left = (toku_point*)&nums[left];
range->right = (toku_point*)&nums[right]; range->right = (toku_point*)&nums[right];
if (data < 0) range->data = NULL; return range;
else range->data = (DB_TXN*)&letters[data]; }
toku_range* init_range(toku_range* range, int left, int right, int data) {
init_query(&range->ends, left, right);
if (data < 0) range->data = 0;
else range->data = (TXNID)letters[data];
return range; return range;
} }
...@@ -46,7 +41,7 @@ void close_tree(void) { ...@@ -46,7 +41,7 @@ void close_tree(void) {
r = toku_rt_close(tree); CKERR(r); r = toku_rt_close(tree); CKERR(r);
} }
void runsearch(int rexpect, toku_range* query, toku_range* expect) { void runsearch(int rexpect, toku_interval* query, toku_range* expect) {
int r; int r;
unsigned found; unsigned found;
r = toku_rt_find(tree, query, 0, &buf, &buflen, &found); r = toku_rt_find(tree, query, 0, &buf, &buflen, &found);
...@@ -54,8 +49,8 @@ void runsearch(int rexpect, toku_range* query, toku_range* expect) { ...@@ -54,8 +49,8 @@ void runsearch(int rexpect, toku_range* query, toku_range* expect) {
if (rexpect != 0) return; if (rexpect != 0) return;
assert(found == 1); assert(found == 1);
assert(int_cmp(buf[0].left, expect->left) == 0 && assert(int_cmp(buf[0].ends.left, expect->ends.left) == 0 &&
int_cmp(buf[0].right, expect->right) == 0 && int_cmp(buf[0].ends.right, expect->ends.right) == 0 &&
char_cmp(buf[0].data, expect->data) == 0); char_cmp(buf[0].data, expect->data) == 0);
} }
...@@ -65,7 +60,7 @@ void runinsert(int rexpect, toku_range* toinsert) { ...@@ -65,7 +60,7 @@ void runinsert(int rexpect, toku_range* toinsert) {
CKERR2(r, rexpect); CKERR2(r, rexpect);
} }
void runlimitsearch(toku_range* query, unsigned limit, unsigned findexpect) { void runlimitsearch(toku_interval* query, unsigned limit, unsigned findexpect) {
int r; int r;
unsigned found; unsigned found;
r=toku_rt_find(tree, query, limit, &buf, &buflen, &found); CKERR(r); r=toku_rt_find(tree, query, limit, &buf, &buflen, &found); CKERR(r);
...@@ -75,7 +70,7 @@ void runlimitsearch(toku_range* query, unsigned limit, unsigned findexpect) { ...@@ -75,7 +70,7 @@ void runlimitsearch(toku_range* query, unsigned limit, unsigned findexpect) {
} }
typedef enum {PRED=0, SUCC=1} predsucc; typedef enum {PRED=0, SUCC=1} predsucc;
void runtest(predsucc testtype, void* query, BOOL findexpect, void runtest(predsucc testtype, toku_point* query, BOOL findexpect,
unsigned left, unsigned right, unsigned data) { unsigned left, unsigned right, unsigned data) {
int r; int r;
BOOL found; BOOL found;
...@@ -94,9 +89,9 @@ void runtest(predsucc testtype, void* query, BOOL findexpect, ...@@ -94,9 +89,9 @@ void runtest(predsucc testtype, void* query, BOOL findexpect,
CKERR(r); CKERR(r);
assert(found == findexpect); assert(found == findexpect);
if (findexpect) { if (findexpect) {
assert(int_cmp(out.left, (toku_point*)&nums[left]) == 0); assert(int_cmp(out.ends.left, (toku_point*)&nums[left]) == 0);
assert(int_cmp(out.right, (toku_point*)&nums[right]) == 0); assert(int_cmp(out.ends.right, (toku_point*)&nums[right]) == 0);
assert(char_cmp(out.data, (DB_TXN*)&letters[data]) == 0); assert(char_cmp(out.data, (TXNID)letters[data]) == 0);
} }
} }
......
...@@ -57,7 +57,7 @@ static struct toku_rbt_node* toku_rbt__insert( ...@@ -57,7 +57,7 @@ static struct toku_rbt_node* toku_rbt__insert(
struct toku_rbt_node* parent struct toku_rbt_node* parent
); );
static struct toku_rbt_node *toku_rbt__lookup(int, const toku_range * , struct toku_rbt_tree *, struct toku_rbt_node**); static struct toku_rbt_node *toku_rbt__lookup(int, const toku_interval * , struct toku_rbt_tree *, struct toku_rbt_node**);
static void toku_rbt__destroy(struct toku_rbt_tree *rbinfo, struct toku_rbt_node *); static void toku_rbt__destroy(struct toku_rbt_tree *rbinfo, struct toku_rbt_node *);
...@@ -126,15 +126,14 @@ int toku_rbt_init ( ...@@ -126,15 +126,14 @@ int toku_rbt_init (
return r; return r;
} }
void void toku_rbt_clear(struct toku_rbt_tree *rbinfo) {
toku_rbt_destroy(struct toku_rbt_tree *rbinfo) assert(rbinfo);
{ if (rbinfo->rb_root!=RBNULL) { toku_rbt__destroy(rbinfo, rbinfo->rb_root); }
if (rbinfo==NULL) rbinfo->rb_root = RBNULL;
return; }
if (rbinfo->rb_root!=RBNULL) void toku_rbt_destroy(struct toku_rbt_tree *rbinfo) {
toku_rbt__destroy(rbinfo, rbinfo->rb_root); toku_rbt_clear(rbinfo);
rbinfo->rb_free(rbinfo); rbinfo->rb_free(rbinfo);
} }
...@@ -150,7 +149,7 @@ int toku_rbt_finger_delete(struct toku_rbt_node* node, struct toku_rbt_tree *rbi ...@@ -150,7 +149,7 @@ int toku_rbt_finger_delete(struct toku_rbt_node* node, struct toku_rbt_tree *rbi
int toku_rbt_lookup( int toku_rbt_lookup(
int mode, int mode,
const toku_range* key, const toku_interval* key,
struct toku_rbt_tree* rbinfo, struct toku_rbt_tree* rbinfo,
struct toku_rbt_node** pinsert_finger, struct toku_rbt_node** pinsert_finger,
struct toku_rbt_node** pelement_finger, struct toku_rbt_node** pelement_finger,
...@@ -194,7 +193,7 @@ toku_rbt__traverse(int insert, const toku_range *key, struct toku_rbt_tree *rbin ...@@ -194,7 +193,7 @@ toku_rbt__traverse(int insert, const toku_range *key, struct toku_rbt_tree *rbin
{ {
y=x; y=x;
/* printf("key=%s, RB_GET(x, key)=%s\n", key, RB_GET(x, key)); */ /* printf("key=%s, RB_GET(x, key)=%s\n", key, RB_GET(x, key)); */
cmp=rbinfo->rb_cmp(key->left, x->key.left); cmp=rbinfo->rb_cmp(key->ends.left, x->key.ends.left);
if (cmp<0) if (cmp<0)
x=x->left; x=x->left;
...@@ -240,7 +239,7 @@ static struct toku_rbt_node* toku_rbt__insert( ...@@ -240,7 +239,7 @@ static struct toku_rbt_node* toku_rbt__insert(
} }
else else
{ {
cmp=rbinfo->rb_cmp(z->key.left, y->key.left); cmp=rbinfo->rb_cmp(z->key.ends.left, y->key.ends.left);
if (cmp<0) if (cmp<0)
y->left=z; y->left=z;
else else
...@@ -339,7 +338,7 @@ static struct toku_rbt_node* toku_rbt__insert( ...@@ -339,7 +338,7 @@ static struct toku_rbt_node* toku_rbt__insert(
/* Search for a key according to mode (see redblack.h) /* Search for a key according to mode (see redblack.h)
*/ */
static struct toku_rbt_node * static struct toku_rbt_node *
toku_rbt__lookup(int mode, const toku_range *key, struct toku_rbt_tree *rbinfo, struct toku_rbt_node** pinsert_finger) toku_rbt__lookup(int mode, const toku_interval *key, struct toku_rbt_tree *rbinfo, struct toku_rbt_node** pinsert_finger)
{ {
struct toku_rbt_node *x,*y; struct toku_rbt_node *x,*y;
int cmp = 0; int cmp = 0;
...@@ -376,7 +375,7 @@ toku_rbt__lookup(int mode, const toku_range *key, struct toku_rbt_tree *rbinfo, ...@@ -376,7 +375,7 @@ toku_rbt__lookup(int mode, const toku_range *key, struct toku_rbt_tree *rbinfo,
{ {
y=x; y=x;
/* printf("key=%s, RB_GET(x, key)=%s\n", key, RB_GET(x, key)); */ /* printf("key=%s, RB_GET(x, key)=%s\n", key, RB_GET(x, key)); */
cmp=rbinfo->rb_cmp(key->left, x->key.left); cmp=rbinfo->rb_cmp(key->left, x->key.ends.left);
if (cmp<0) if (cmp<0)
......
...@@ -61,7 +61,7 @@ int toku_rbt_init ( ...@@ -61,7 +61,7 @@ int toku_rbt_init (
/* Sets *pdata to NULL if not found. (unless error) */ /* Sets *pdata to NULL if not found. (unless error) */
int toku_rbt_lookup( int toku_rbt_lookup(
int mode, int mode,
const toku_range* key, const toku_interval* key,
struct toku_rbt_tree* rbinfo, struct toku_rbt_tree* rbinfo,
struct toku_rbt_node** pinsert_finger, struct toku_rbt_node** pinsert_finger,
struct toku_rbt_node** pelement_finger, struct toku_rbt_node** pelement_finger,
...@@ -82,6 +82,8 @@ int toku_rbt_finger_successor(struct toku_rbt_node** pfinger, toku_range** psucc ...@@ -82,6 +82,8 @@ int toku_rbt_finger_successor(struct toku_rbt_node** pfinger, toku_range** psucc
void toku_rbt_destroy(struct toku_rbt_tree *); void toku_rbt_destroy(struct toku_rbt_tree *);
void toku_rbt_clear(struct toku_rbt_tree *);
enum nodecolour { BLACK, RED }; enum nodecolour { BLACK, RED };
struct toku_rbt_node struct toku_rbt_node
......
...@@ -8,6 +8,9 @@ ...@@ -8,6 +8,9 @@
#include "../newbrt/brt.h" #include "../newbrt/brt.h"
#include "../newbrt/list.h" #include "../newbrt/list.h"
#include "./lock_tree/locktree.h" #include "./lock_tree/locktree.h"
#include "./lock_tree/db_id.h"
#include "./lock_tree/idlth.h"
#include <limits.h>
struct db_header { struct db_header {
int n_databases; // Or there can be >=1 named databases. This is the count. int n_databases; // Or there can be >=1 named databases. This is the count.
...@@ -34,6 +37,7 @@ struct __toku_db_internal { ...@@ -34,6 +37,7 @@ struct __toku_db_internal {
int(*associate_callback)(DB*, const DBT*, const DBT*, DBT*); // For secondary, the callback function for associate. NULL if not secondary int(*associate_callback)(DB*, const DBT*, const DBT*, DBT*); // For secondary, the callback function for associate. NULL if not secondary
int associate_is_immutable; // If this DB is a secondary then this field indicates that the index never changes due to updates. int associate_is_immutable; // If this DB is a secondary then this field indicates that the index never changes due to updates.
struct __toku_lock_tree* lt; struct __toku_lock_tree* lt;
toku_db_id* db_id;
}; };
#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 #if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1
......
This diff is collapsed.
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