mirror of
https://github.com/MariaDB/server.git
synced 2025-12-03 05:41:09 +03:00
Closes #567
Merge all of ticket 567 into trunk git-svn-id: file:///svn/tokudb@3134 c7de825b-a66e-492c-adef-691d508d4ae1
This commit is contained in:
@@ -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
|
|||||||
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)
|
|||||||
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:
|
|||||||
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 $< $@
|
||||||
|
|
||||||
|
|||||||
87
src/lock_tree/db_id.c
Normal file
87
src/lock_tree/db_id.c
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/* -*- 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;
|
||||||
|
}
|
||||||
28
src/lock_tree/db_id.h
Normal file
28
src/lock_tree/db_id.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/* -*- 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) */
|
||||||
201
src/lock_tree/idlth.c
Normal file
201
src/lock_tree/idlth.c
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
/* -*- 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 ? ¤t->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;
|
||||||
|
}
|
||||||
76
src/lock_tree/idlth.h
Normal file
76
src/lock_tree/idlth.h
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
/* -*- 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
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -24,6 +24,7 @@
|
|||||||
#include <rangetree.h>
|
#include <rangetree.h>
|
||||||
#include <lth.h>
|
#include <lth.h>
|
||||||
#include <rth.h>
|
#include <rth.h>
|
||||||
|
#include <idlth.h>
|
||||||
|
|
||||||
/** Errors returned by lock trees */
|
/** Errors returned by lock trees */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -31,6 +32,8 @@ typedef enum {
|
|||||||
state */
|
state */
|
||||||
} TOKU_LT_ERROR;
|
} TOKU_LT_ERROR;
|
||||||
|
|
||||||
|
typedef int (*toku_dbt_cmp)(DB*,const DBT*,const DBT*);
|
||||||
|
|
||||||
/** Convert error codes into a human-readable error message */
|
/** Convert error codes into a human-readable error message */
|
||||||
char* toku_lt_strerror(TOKU_LT_ERROR r /**< Error code */)
|
char* toku_lt_strerror(TOKU_LT_ERROR r /**< Error code */)
|
||||||
__attribute__((const,pure));
|
__attribute__((const,pure));
|
||||||
@@ -58,7 +61,20 @@ struct __toku_lock_tree {
|
|||||||
BOOL settings_final;
|
BOOL settings_final;
|
||||||
toku_range_tree* mainread; /**< See design document */
|
toku_range_tree* mainread; /**< See design document */
|
||||||
toku_range_tree* borderwrite; /**< See design document */
|
toku_range_tree* borderwrite; /**< See design document */
|
||||||
toku_rth* rth;
|
toku_rth* rth; /**< Stores local(read|write)set tables */
|
||||||
|
/**
|
||||||
|
Stores a list of transactions to unlock when it is safe.
|
||||||
|
When we get a PUT or a GET, the comparison function is valid
|
||||||
|
and we can delete locks held in txns_to_unlock, even if txns_still_locked
|
||||||
|
is nonempty.
|
||||||
|
*/
|
||||||
|
toku_rth* txns_to_unlock;
|
||||||
|
/** Stores a list of transactions that hold locks. txns_still_locked = rth - txns_to_unlock
|
||||||
|
rth != txns_still_locked + txns_to_unlock, we may get an unlock call for a txn that has
|
||||||
|
no locks in rth.
|
||||||
|
When txns_still_locked becomes empty, we can throw away the contents of the lock tree
|
||||||
|
quickly. */
|
||||||
|
toku_rth* txns_still_locked;
|
||||||
/** A temporary area where we store the results of various find on
|
/** A temporary area where we store the results of various find on
|
||||||
the range trees that this lock tree owns
|
the range trees that this lock tree owns
|
||||||
|
|
||||||
@@ -81,10 +97,10 @@ struct __toku_lock_tree {
|
|||||||
BOOL lock_escalation_allowed;
|
BOOL lock_escalation_allowed;
|
||||||
/** Lock tree manager */
|
/** Lock tree manager */
|
||||||
toku_ltm* mgr;
|
toku_ltm* mgr;
|
||||||
/** The callback function to let a transaction add a new lock tree. */
|
/** Function to retrieve the key compare function from the database. */
|
||||||
int (*lock_add_callback)(DB_TXN*, toku_lock_tree*);
|
toku_dbt_cmp (*get_compare_fun_from_db)(DB*);
|
||||||
/** The callback function to let a transaction forget a lock tree. */
|
/** Function to retrieve the data compare function from the database. */
|
||||||
void (*lock_remove_callback)(DB_TXN*, toku_lock_tree*);
|
toku_dbt_cmp (*get_dup_compare_from_db)(DB*);
|
||||||
/** The key compare function */
|
/** The key compare function */
|
||||||
int (*compare_fun)(DB*,const DBT*,const DBT*);
|
int (*compare_fun)(DB*,const DBT*,const DBT*);
|
||||||
/** The data compare function */
|
/** The data compare function */
|
||||||
@@ -97,6 +113,14 @@ struct __toku_lock_tree {
|
|||||||
void (*free) (void*);
|
void (*free) (void*);
|
||||||
/** The user realloc function */
|
/** The user realloc function */
|
||||||
void* (*realloc)(void*, size_t);
|
void* (*realloc)(void*, size_t);
|
||||||
|
/** The maximum number of locks allowed for this lock tree. */
|
||||||
|
u_int32_t max_locks;
|
||||||
|
/** The current number of locks for this lock tree. */
|
||||||
|
u_int32_t curr_locks;
|
||||||
|
/** The number of references held by DB instances and transactions to this lock tree*/
|
||||||
|
u_int32_t ref_count;
|
||||||
|
/** db_id associated with the lock tree */
|
||||||
|
toku_db_id* db_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct __toku_ltm {
|
struct __toku_ltm {
|
||||||
@@ -104,8 +128,21 @@ struct __toku_ltm {
|
|||||||
u_int32_t max_locks;
|
u_int32_t max_locks;
|
||||||
/** The current number of locks for the environment. */
|
/** The current number of locks for the environment. */
|
||||||
u_int32_t curr_locks;
|
u_int32_t curr_locks;
|
||||||
|
/** The maximum number of locks allowed for the environment. */
|
||||||
|
u_int32_t max_locks_per_db;
|
||||||
/** The list of lock trees it manages. */
|
/** The list of lock trees it manages. */
|
||||||
toku_lth* lth;
|
toku_lth* lth;
|
||||||
|
/** List of lock-tree DB mappings. Upon a request for a lock tree given
|
||||||
|
a DB, if an object for that DB exists in this list, then the lock tree
|
||||||
|
is retrieved from this list, otherwise, a new lock tree is created
|
||||||
|
and the new mapping of DB and Lock tree is stored here */
|
||||||
|
toku_idlth* idlth;
|
||||||
|
/** Function to retrieve the key compare function from the database. */
|
||||||
|
toku_dbt_cmp (*get_compare_fun_from_db)(DB*);
|
||||||
|
/** Function to retrieve the data compare function from the database. */
|
||||||
|
toku_dbt_cmp (*get_dup_compare_from_db)(DB*);
|
||||||
|
/** The panic function */
|
||||||
|
int (*panic)(DB*, int);
|
||||||
/** The user malloc function */
|
/** The user malloc function */
|
||||||
void* (*malloc) (size_t);
|
void* (*malloc) (size_t);
|
||||||
/** The user free function */
|
/** The user free function */
|
||||||
@@ -147,11 +184,9 @@ typedef struct __toku_point toku_point;
|
|||||||
Create a lock tree. Should be called only inside DB->open.
|
Create a lock tree. Should be called only inside DB->open.
|
||||||
|
|
||||||
\param ptree We set *ptree to the newly allocated tree.
|
\param ptree We set *ptree to the newly allocated tree.
|
||||||
\param db This is the db that the lock tree will be performing
|
|
||||||
locking for.
|
|
||||||
\param duplicates Whether the db supports duplicates.
|
\param duplicates Whether the db supports duplicates.
|
||||||
\param compare_fun The key compare function.
|
\param get_compare_fun_from_db Accessor for the key compare function.
|
||||||
\param dup_compare The data compare function.
|
\param get_dup_compare_from_db Accessor for the data compare function.
|
||||||
\param panic The function to cause the db to panic.
|
\param panic The function to cause the db to panic.
|
||||||
i.e., godzilla_rampage()
|
i.e., godzilla_rampage()
|
||||||
\param payload_capacity The maximum amount of memory to use for dbt payloads.
|
\param payload_capacity The maximum amount of memory to use for dbt payloads.
|
||||||
@@ -172,26 +207,22 @@ typedef struct __toku_point toku_point;
|
|||||||
If this library is ever exported to users, we will use error datas
|
If this library is ever exported to users, we will use error datas
|
||||||
instead.
|
instead.
|
||||||
*/
|
*/
|
||||||
int toku_lt_create(toku_lock_tree** ptree, DB* db, BOOL duplicates,
|
int toku_lt_create(toku_lock_tree** ptree, BOOL duplicates,
|
||||||
int (*panic)(DB*, int),
|
int (*panic)(DB*, int),
|
||||||
toku_ltm* mgr,
|
toku_ltm* mgr,
|
||||||
int (*compare_fun)(DB*,const DBT*,const DBT*),
|
toku_dbt_cmp (*get_compare_fun_from_db)(DB*),
|
||||||
int (*dup_compare)(DB*,const DBT*,const DBT*),
|
toku_dbt_cmp (*get_dup_compare_from_db)(DB*),
|
||||||
void* (*user_malloc) (size_t),
|
void* (*user_malloc) (size_t),
|
||||||
void (*user_free) (void*),
|
void (*user_free) (void*),
|
||||||
void* (*user_realloc)(void*, size_t));
|
void* (*user_realloc)(void*, size_t));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Set whether duplicates are allowed.
|
Gets a lock tree for a given DB with id db_id
|
||||||
This can be called after create, but NOT after any locks or unlocks have
|
|
||||||
occurred.
|
|
||||||
|
|
||||||
\return
|
|
||||||
- 0 on success.
|
|
||||||
- EINVAL if tree is NULL
|
|
||||||
- EDOM if it is too late to change.
|
|
||||||
*/
|
*/
|
||||||
int toku_lt_set_dups(toku_lock_tree* tree, BOOL duplicates);
|
int toku_ltm_get_lt(toku_ltm* mgr, toku_lock_tree** ptree,
|
||||||
|
BOOL duplicates, toku_db_id* db_id);
|
||||||
|
|
||||||
|
void toku_ltm_invalidate_lt(toku_ltm* mgr, toku_db_id* db_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Closes and frees a lock tree.
|
Closes and frees a lock tree.
|
||||||
@@ -234,14 +265,14 @@ int toku_lt_close(toku_lock_tree* tree);
|
|||||||
(tree->db is dupsort && data == NULL) or
|
(tree->db is dupsort && data == NULL) or
|
||||||
(tree->db is dupsort && key != data &&
|
(tree->db is dupsort && key != data &&
|
||||||
(key == toku_lt_infinity ||
|
(key == toku_lt_infinity ||
|
||||||
(toku_lock_tree* tree, DB_TXN* txn, const DBT* key, const DBT* data);
|
(toku_lock_tree* tree, TXNID txn, const DBT* key, const DBT* data);
|
||||||
If this library is ever exported to users, we will use EINVAL instead.
|
If this library is ever exported to users, we will use EINVAL instead.
|
||||||
|
|
||||||
In BDB, txn can actually be NULL (mixed operations with transactions and
|
In BDB, txn can actually be NULL (mixed operations with transactions and
|
||||||
no transactions). This can cause conflicts, nobody was able (so far)
|
no transactions). This can cause conflicts, nobody was able (so far)
|
||||||
to verify that MySQL does or does not use this.
|
to verify that MySQL does or does not use this.
|
||||||
*/
|
*/
|
||||||
int toku_lt_acquire_read_lock(toku_lock_tree* tree, DB_TXN* txn,
|
int toku_lt_acquire_read_lock(toku_lock_tree* tree, DB* db, TXNID txn,
|
||||||
const DBT* key, const DBT* data);
|
const DBT* key, const DBT* data);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -288,7 +319,7 @@ int toku_lt_acquire_read_lock(toku_lock_tree* tree, DB_TXN* txn,
|
|||||||
no transactions). This can cause conflicts, nobody was able (so far)
|
no transactions). This can cause conflicts, nobody was able (so far)
|
||||||
to verify that MySQL does or does not use this.
|
to verify that MySQL does or does not use this.
|
||||||
*/
|
*/
|
||||||
int toku_lt_acquire_range_read_lock(toku_lock_tree* tree, DB_TXN* txn,
|
int toku_lt_acquire_range_read_lock(toku_lock_tree* tree, DB* db, TXNID txn,
|
||||||
const DBT* key_left, const DBT* data_left,
|
const DBT* key_left, const DBT* data_left,
|
||||||
const DBT* key_right, const DBT* data_right);
|
const DBT* key_right, const DBT* data_right);
|
||||||
|
|
||||||
@@ -321,7 +352,7 @@ int toku_lt_acquire_range_read_lock(toku_lock_tree* tree, DB_TXN* txn,
|
|||||||
If the lock tree needs to hold onto the key or data, it will make copies
|
If the lock tree needs to hold onto the key or data, it will make copies
|
||||||
to its local memory.
|
to its local memory.
|
||||||
*/
|
*/
|
||||||
int toku_lt_acquire_write_lock(toku_lock_tree* tree, DB_TXN* txn,
|
int toku_lt_acquire_write_lock(toku_lock_tree* tree, DB* db, TXNID txn,
|
||||||
const DBT* key, const DBT* data);
|
const DBT* key, const DBT* data);
|
||||||
|
|
||||||
//In BDB, txn can actually be NULL (mixed operations with transactions and no transactions).
|
//In BDB, txn can actually be NULL (mixed operations with transactions and no transactions).
|
||||||
@@ -373,7 +404,7 @@ int toku_lt_acquire_write_lock(toku_lock_tree* tree, DB_TXN* txn,
|
|||||||
* to its local memory.
|
* to its local memory.
|
||||||
* *** Note that txn == NULL is not supported at this time.
|
* *** Note that txn == NULL is not supported at this time.
|
||||||
*/
|
*/
|
||||||
int toku_lt_acquire_range_write_lock(toku_lock_tree* tree, DB_TXN* txn,
|
int toku_lt_acquire_range_write_lock(toku_lock_tree* tree, DB* db, TXNID txn,
|
||||||
const DBT* key_left, const DBT* data_left,
|
const DBT* key_left, const DBT* data_left,
|
||||||
const DBT* key_right, const DBT* data_right);
|
const DBT* key_right, const DBT* data_right);
|
||||||
|
|
||||||
@@ -393,43 +424,7 @@ int toku_lt_acquire_range_write_lock(toku_lock_tree* tree, DB_TXN* txn,
|
|||||||
- EINVAL If (tree == NULL || txn == NULL).
|
- EINVAL If (tree == NULL || txn == NULL).
|
||||||
- EINVAL If panicking.
|
- EINVAL If panicking.
|
||||||
*/
|
*/
|
||||||
int toku_lt_unlock(toku_lock_tree* tree, DB_TXN* txn);
|
int toku_lt_unlock(toku_lock_tree* tree, TXNID txn);
|
||||||
|
|
||||||
/**
|
|
||||||
Set a add_callback function to run after parameter checking but before
|
|
||||||
any locks.
|
|
||||||
This can be called after create, but NOT after any locks or unlocks have
|
|
||||||
occurred.
|
|
||||||
|
|
||||||
\param tree The tree on whick to set the add_callback function
|
|
||||||
\param add_callback The add_callback function
|
|
||||||
|
|
||||||
\return
|
|
||||||
- 0 on success.
|
|
||||||
- EINVAL if tree is NULL
|
|
||||||
- EDOM if it is too late to change.
|
|
||||||
*/
|
|
||||||
int toku_lt_set_txn_add_lt_callback(toku_lock_tree* tree,
|
|
||||||
int (*add_callback)(DB_TXN*, toku_lock_tree*));
|
|
||||||
|
|
||||||
/**
|
|
||||||
Set a remove_callback function to run after parameter checking but before
|
|
||||||
any locks.
|
|
||||||
This can be called after create, but NOT after any locks or unlocks have
|
|
||||||
occurred.
|
|
||||||
|
|
||||||
\param tree The tree on whick to set the remove_callback function
|
|
||||||
\param remove_callback The remove_callback function
|
|
||||||
|
|
||||||
\return
|
|
||||||
- 0 on success.
|
|
||||||
- EINVAL if tree is NULL
|
|
||||||
- EDOM if it is too late to change.
|
|
||||||
*/
|
|
||||||
int toku_lt_set_txn_remove_lt_callback(toku_lock_tree* tree,
|
|
||||||
void (*remove_callback)(DB_TXN*, toku_lock_tree*));
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Lock tree manager functions begin here */
|
/* Lock tree manager functions begin here */
|
||||||
/**
|
/**
|
||||||
@@ -447,10 +442,13 @@ int toku_lt_set_txn_remove_lt_callback(toku_lock_tree* tree,
|
|||||||
- May return other errors due to system calls.
|
- May return other errors due to system calls.
|
||||||
*/
|
*/
|
||||||
int toku_ltm_create(toku_ltm** pmgr,
|
int toku_ltm_create(toku_ltm** pmgr,
|
||||||
u_int32_t max_locks,
|
u_int32_t max_locks,
|
||||||
void* (*user_malloc) (size_t),
|
int (*panic)(DB*, int),
|
||||||
void (*user_free) (void*),
|
toku_dbt_cmp (*get_compare_fun_from_db)(DB*),
|
||||||
void* (*user_realloc)(void*, size_t));
|
toku_dbt_cmp (*get_dup_compare_from_db)(DB*),
|
||||||
|
void* (*user_malloc) (size_t),
|
||||||
|
void (*user_free) (void*),
|
||||||
|
void* (*user_realloc)(void*, size_t));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Closes and frees a lock tree manager..
|
Closes and frees a lock tree manager..
|
||||||
@@ -478,6 +476,22 @@ int toku_ltm_close(toku_ltm* mgr);
|
|||||||
*/
|
*/
|
||||||
int toku_ltm_set_max_locks(toku_ltm* mgr, u_int32_t max_locks);
|
int toku_ltm_set_max_locks(toku_ltm* mgr, u_int32_t max_locks);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets the maximum number of locks for each lock tree.
|
||||||
|
This is a temporary function until we can complete ticket #596.
|
||||||
|
This will be used instead of toku_ltm_set_max_locks.
|
||||||
|
|
||||||
|
\param mgr The lock tree manager to which to set max_locks.
|
||||||
|
\param max_locks The new maximum number of locks.
|
||||||
|
|
||||||
|
\return
|
||||||
|
- 0 on success.
|
||||||
|
- EINVAL if tree is NULL or max_locks is 0
|
||||||
|
- EDOM if max_locks is less than the number of locks held by any lock tree
|
||||||
|
held by the manager
|
||||||
|
*/
|
||||||
|
int toku_ltm_set_max_locks_per_db(toku_ltm* mgr, u_int32_t max_locks);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Sets the maximum number of locks on the lock tree manager.
|
Sets the maximum number of locks on the lock tree manager.
|
||||||
|
|
||||||
@@ -490,5 +504,10 @@ int toku_ltm_set_max_locks(toku_ltm* mgr, u_int32_t max_locks);
|
|||||||
*/
|
*/
|
||||||
int toku_ltm_get_max_locks(toku_ltm* mgr, u_int32_t* max_locks);
|
int toku_ltm_get_max_locks(toku_ltm* mgr, u_int32_t* max_locks);
|
||||||
|
|
||||||
|
int toku_ltm_get_max_locks_per_db(toku_ltm* mgr, u_int32_t* max_locks);
|
||||||
|
|
||||||
|
void toku_lt_add_ref(toku_lock_tree* tree);
|
||||||
|
|
||||||
|
int toku_lt_remove_ref(toku_lock_tree* tree);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -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 @@ cleanup:
|
|||||||
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 = <h->buckets[index];
|
toku_lth_elt* head = <h->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) {
|
|||||||
/* 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 = <h->buckets[index];
|
toku_lth_elt* head = <h->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) {
|
|||||||
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 @@
|
|||||||
#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;
|
||||||
}
|
}
|
||||||
@@ -61,10 +61,10 @@ cleanup:
|
|||||||
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) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 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) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 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 @@ cleanup:
|
|||||||
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) {
|
|||||||
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 @@
|
|||||||
#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 {
|
|||||||
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,
|
|||||||
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
|
|||||||
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 @@
|
|||||||
#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) {
|
|||||||
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) {
|
|||||||
}
|
}
|
||||||
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() {
|
|||||||
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(<, db, duplicates, dbpanic, mgr,
|
r = toku_lt_create(<, 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);
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ DBT* data;
|
|||||||
u_int32_t max_locks = 1000;
|
u_int32_t max_locks = 1000;
|
||||||
toku_ltm* ltm = NULL;
|
toku_ltm* ltm = NULL;
|
||||||
|
|
||||||
static void do_range_test(int (*acquire)(toku_lock_tree*, DB_TXN*,
|
static void do_range_test(int (*acquire)(toku_lock_tree*, DB*, TXNID,
|
||||||
const DBT*, const DBT*,
|
const DBT*, const DBT*,
|
||||||
const DBT*, const DBT*)) {
|
const DBT*, const DBT*)) {
|
||||||
int r;
|
int r;
|
||||||
toku_lock_tree* lt = NULL;
|
toku_lock_tree* lt = NULL;
|
||||||
DB* db = (DB*)1;
|
DB* db = (DB*)1;
|
||||||
DB_TXN* txn = (DB_TXN*)1; // Fake.
|
TXNID txn = (TXNID)1; // Fake.
|
||||||
BOOL duplicates = FALSE;
|
BOOL duplicates = FALSE;
|
||||||
DBT _key_l = _key;
|
DBT _key_l = _key;
|
||||||
DBT _key_r = _key;
|
DBT _key_r = _key;
|
||||||
@@ -40,63 +40,61 @@ static void do_range_test(int (*acquire)(toku_lock_tree*, DB_TXN*,
|
|||||||
reverse_data_l = &_data_l;
|
reverse_data_l = &_data_l;
|
||||||
reverse_data_r = &_data_r;
|
reverse_data_r = &_data_r;
|
||||||
}
|
}
|
||||||
r = toku_lt_create(<, db, duplicates, dbpanic, ltm,
|
r = toku_lt_create(<, duplicates, dbpanic, ltm,
|
||||||
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);
|
||||||
|
|
||||||
if (acquire == toku_lt_acquire_range_write_lock) {
|
if (acquire == toku_lt_acquire_range_write_lock) {
|
||||||
r = acquire(lt, txn, key_l, data_l,
|
r = acquire(lt, db, txn, key_l, data_l,
|
||||||
key_r, data_r);
|
key_r, data_r);
|
||||||
CKERR2(r, ENOSYS);
|
CKERR2(r, ENOSYS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
r = acquire(NULL, txn, key_l, data_l,
|
r = acquire(NULL, db, txn, key_l, data_l,
|
||||||
key_r, data_r);
|
key_r, data_r);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
r = acquire(lt, NULL, key_l, data_l,
|
r = acquire(lt, db, txn, NULL, data_l,
|
||||||
key_r, data_r);
|
|
||||||
CKERR2(r, EINVAL);
|
|
||||||
r = acquire(lt, txn, NULL, data_l,
|
|
||||||
key_r, data_r);
|
key_r, data_r);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
if (duplicates) {
|
if (duplicates) {
|
||||||
r = acquire(lt, txn, key_l, reverse_data_l,
|
r = acquire(lt, db, txn, key_l, reverse_data_l,
|
||||||
key_r, data_r);
|
key_r, data_r);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
r = acquire(lt, txn, key_l, data_l,
|
r = acquire(lt, db, txn, key_l, data_l,
|
||||||
key_r, reverse_data_r);
|
key_r, reverse_data_r);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
}
|
}
|
||||||
r = acquire(lt, txn, key_l, data_l,
|
r = acquire(lt, db, txn, key_l, data_l,
|
||||||
NULL, data_r);
|
NULL, data_r);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
|
|
||||||
/* Infinite tests. */
|
/* Infinite tests. */
|
||||||
if (duplicates) {
|
if (duplicates) {
|
||||||
r = acquire(lt, txn, toku_lt_infinity, data_l,
|
r = acquire(lt, db, txn, toku_lt_infinity, data_l,
|
||||||
key_r, data_r);
|
key_r, data_r);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
r = acquire(lt, txn, toku_lt_neg_infinity, data_l,
|
r = acquire(lt, db, txn, toku_lt_neg_infinity, data_l,
|
||||||
key_r, data_r);
|
key_r, data_r);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
r = acquire(lt, txn, key_l, data_l,
|
r = acquire(lt, db, txn, key_l, data_l,
|
||||||
toku_lt_infinity, data_r);
|
toku_lt_infinity, data_r);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
r = acquire(lt, txn, key_l, data_l,
|
r = acquire(lt, db, txn, key_l, data_l,
|
||||||
toku_lt_neg_infinity, data_r);
|
toku_lt_neg_infinity, data_r);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
r = acquire(lt, txn, toku_lt_infinity, toku_lt_neg_infinity,
|
r = acquire(lt, db, txn, toku_lt_infinity, toku_lt_neg_infinity,
|
||||||
key_r, data_r);
|
key_r, data_r);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
r = acquire(lt, txn, toku_lt_neg_infinity, toku_lt_infinity,
|
r = acquire(lt, db, txn, toku_lt_neg_infinity, toku_lt_infinity,
|
||||||
key_r, data_r);
|
key_r, data_r);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
r = acquire(lt, txn, key_l, data_l,
|
r = acquire(lt, db, txn, key_l, data_l,
|
||||||
toku_lt_infinity, toku_lt_neg_infinity);
|
toku_lt_infinity, toku_lt_neg_infinity);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
r = acquire(lt, txn, key_l, data_l,
|
r = acquire(lt, db, txn, key_l, data_l,
|
||||||
toku_lt_neg_infinity, toku_lt_infinity);
|
toku_lt_neg_infinity, toku_lt_infinity);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
}
|
}
|
||||||
@@ -105,13 +103,13 @@ static void do_range_test(int (*acquire)(toku_lock_tree*, DB_TXN*,
|
|||||||
const DBT* inf = toku_lt_infinity;
|
const DBT* inf = toku_lt_infinity;
|
||||||
const DBT* d_ninf = duplicates ? toku_lt_neg_infinity : NULL;
|
const DBT* d_ninf = duplicates ? toku_lt_neg_infinity : NULL;
|
||||||
const DBT* ninf = toku_lt_neg_infinity;
|
const DBT* ninf = toku_lt_neg_infinity;
|
||||||
r = acquire(lt, txn, inf, d_inf,
|
r = acquire(lt, db, txn, inf, d_inf,
|
||||||
key_r, data_r);
|
key_r, data_r);
|
||||||
CKERR2(r, EDOM);
|
CKERR2(r, EDOM);
|
||||||
r = acquire(lt, txn, key_l, data_l,
|
r = acquire(lt, db, txn, key_l, data_l,
|
||||||
ninf, d_ninf);
|
ninf, d_ninf);
|
||||||
CKERR2(r, EDOM);
|
CKERR2(r, EDOM);
|
||||||
r = acquire(lt, txn, inf, d_inf,
|
r = acquire(lt, db, txn, inf, d_inf,
|
||||||
ninf, d_ninf);
|
ninf, d_ninf);
|
||||||
CKERR2(r, EDOM);
|
CKERR2(r, EDOM);
|
||||||
|
|
||||||
@@ -123,12 +121,12 @@ static void do_range_test(int (*acquire)(toku_lock_tree*, DB_TXN*,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_point_test(int (*acquire)(toku_lock_tree*, DB_TXN*,
|
static void do_point_test(int (*acquire)(toku_lock_tree*, DB*, TXNID,
|
||||||
const DBT*, const DBT*)) {
|
const DBT*, const DBT*)) {
|
||||||
int r;
|
int r;
|
||||||
toku_lock_tree* lt = NULL;
|
toku_lock_tree* lt = NULL;
|
||||||
DB* db = (DB*)1;
|
TXNID txn = (TXNID)1; // Fake.
|
||||||
DB_TXN* txn = (DB_TXN*)1; // Fake.
|
DB* db = (DB*)0x1;
|
||||||
BOOL duplicates = FALSE;
|
BOOL duplicates = FALSE;
|
||||||
|
|
||||||
lt = NULL;
|
lt = NULL;
|
||||||
@@ -145,40 +143,35 @@ static void do_point_test(int (*acquire)(toku_lock_tree*, DB_TXN*,
|
|||||||
reverse_data = &_data;
|
reverse_data = &_data;
|
||||||
data = NULL;
|
data = NULL;
|
||||||
}
|
}
|
||||||
r = toku_lt_create(<, db, duplicates, dbpanic, ltm,
|
r = toku_lt_create(<, duplicates, dbpanic, ltm,
|
||||||
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_unlock(NULL, (DB_TXN*)1);
|
r = toku_lt_unlock(NULL, (TXNID)1);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
|
|
||||||
r = toku_lt_unlock(lt, NULL);
|
r = acquire(NULL, db, txn, key, data);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
|
|
||||||
r = acquire(NULL, txn, key, data);
|
r = acquire(lt, db, txn, NULL, data);
|
||||||
CKERR2(r, EINVAL);
|
|
||||||
|
|
||||||
r = acquire(lt, NULL, key, data);
|
|
||||||
CKERR2(r, EINVAL);
|
|
||||||
|
|
||||||
r = acquire(lt, txn, NULL, data);
|
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
|
|
||||||
if (duplicates) {
|
if (duplicates) {
|
||||||
r = acquire(lt, txn, key, reverse_data);
|
r = acquire(lt, db, txn, key, reverse_data);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Infinite tests. */
|
/* Infinite tests. */
|
||||||
if (duplicates) {
|
if (duplicates) {
|
||||||
r = acquire(lt, txn, toku_lt_infinity, data);
|
r = acquire(lt, db, txn, toku_lt_infinity, data);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
r = acquire(lt, txn, toku_lt_neg_infinity, data);
|
r = acquire(lt, db, txn, toku_lt_neg_infinity, data);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
r = acquire(lt, txn, toku_lt_infinity, toku_lt_neg_infinity);
|
r = acquire(lt, db, txn, toku_lt_infinity, toku_lt_neg_infinity);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
r = acquire(lt, txn, toku_lt_neg_infinity, toku_lt_infinity);
|
r = acquire(lt, db, txn, toku_lt_neg_infinity, toku_lt_infinity);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,27 +188,38 @@ int main(int argc, const char *argv[]) {
|
|||||||
|
|
||||||
int r;
|
int r;
|
||||||
toku_lock_tree* lt = NULL;
|
toku_lock_tree* lt = NULL;
|
||||||
DB* db = (DB*)1;
|
|
||||||
BOOL duplicates = FALSE;
|
BOOL duplicates = FALSE;
|
||||||
|
|
||||||
r = toku_ltm_create(NULL, max_locks, toku_malloc, toku_free, toku_realloc);
|
r = toku_ltm_create(NULL, max_locks, dbpanic,
|
||||||
|
get_compare_fun_from_db, get_dup_compare_from_db,
|
||||||
|
toku_malloc, toku_free, toku_realloc);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
assert(ltm == NULL);
|
assert(ltm == NULL);
|
||||||
r = toku_ltm_create(<m, 0, toku_malloc, toku_free, toku_realloc);
|
r = toku_ltm_create(<m, 0, dbpanic,
|
||||||
|
get_compare_fun_from_db, get_dup_compare_from_db,
|
||||||
|
toku_malloc, toku_free, toku_realloc);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
assert(ltm == NULL);
|
assert(ltm == NULL);
|
||||||
r = toku_ltm_create(<m, max_locks, NULL, toku_free, toku_realloc);
|
r = toku_ltm_create(<m, max_locks, dbpanic,
|
||||||
|
get_compare_fun_from_db, get_dup_compare_from_db,
|
||||||
|
NULL, toku_free, toku_realloc);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
assert(ltm == NULL);
|
assert(ltm == NULL);
|
||||||
r = toku_ltm_create(<m, max_locks, toku_malloc, NULL, toku_realloc);
|
r = toku_ltm_create(<m, max_locks, dbpanic,
|
||||||
|
get_compare_fun_from_db, get_dup_compare_from_db,
|
||||||
|
toku_malloc, NULL, toku_realloc);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
assert(ltm == NULL);
|
assert(ltm == NULL);
|
||||||
r = toku_ltm_create(<m, max_locks, toku_malloc, toku_free, NULL);
|
r = toku_ltm_create(<m, max_locks, dbpanic,
|
||||||
|
get_compare_fun_from_db, get_dup_compare_from_db,
|
||||||
|
toku_malloc, toku_free, NULL);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
assert(ltm == NULL);
|
assert(ltm == NULL);
|
||||||
|
|
||||||
/* Actually create it. */
|
/* Actually create it. */
|
||||||
r = toku_ltm_create(<m, max_locks, toku_malloc, toku_free, toku_realloc);
|
r = toku_ltm_create(<m, 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);
|
||||||
|
|
||||||
@@ -239,37 +243,41 @@ int main(int argc, const char *argv[]) {
|
|||||||
|
|
||||||
/* create tests. */
|
/* create tests. */
|
||||||
for (duplicates = 0; duplicates < 2; duplicates++) {
|
for (duplicates = 0; duplicates < 2; duplicates++) {
|
||||||
r = toku_lt_create(NULL, db, duplicates, dbpanic, ltm,
|
r = toku_lt_create(NULL, duplicates, dbpanic, ltm,
|
||||||
dbcmp, dbcmp, toku_malloc, toku_free, toku_realloc);
|
get_compare_fun_from_db, get_dup_compare_from_db,
|
||||||
|
toku_malloc, toku_free, toku_realloc);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
|
|
||||||
r = toku_lt_create(<, NULL, duplicates, dbpanic, ltm,
|
r = toku_lt_create(<, duplicates, NULL, ltm,
|
||||||
dbcmp, dbcmp, toku_malloc, toku_free, toku_realloc);
|
get_compare_fun_from_db, get_dup_compare_from_db,
|
||||||
|
toku_malloc, toku_free, toku_realloc);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
|
|
||||||
r = toku_lt_create(<, db, duplicates, NULL, ltm,
|
r = toku_lt_create(<, duplicates, dbpanic, NULL,
|
||||||
dbcmp, dbcmp, toku_malloc, toku_free, toku_realloc);
|
get_compare_fun_from_db, get_dup_compare_from_db,
|
||||||
|
toku_malloc, toku_free, toku_realloc);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
|
|
||||||
r = toku_lt_create(<, db, duplicates, dbpanic, NULL,
|
r = toku_lt_create(<, duplicates, dbpanic, ltm,
|
||||||
dbcmp, dbcmp, toku_malloc, toku_free, toku_realloc);
|
NULL, get_dup_compare_from_db,
|
||||||
|
toku_malloc, toku_free, toku_realloc);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
|
|
||||||
r = toku_lt_create(<, db, duplicates, dbpanic, ltm,
|
r = toku_lt_create(<, duplicates, dbpanic, ltm,
|
||||||
NULL, dbcmp, toku_malloc, toku_free, toku_realloc);
|
get_compare_fun_from_db, NULL,
|
||||||
|
toku_malloc, toku_free, toku_realloc);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
|
r = toku_lt_create(<, duplicates, dbpanic, ltm,
|
||||||
r = toku_lt_create(<, db, duplicates, dbpanic, ltm,
|
get_compare_fun_from_db, get_dup_compare_from_db,
|
||||||
dbcmp, NULL, toku_malloc, toku_free, toku_realloc);
|
NULL, toku_free, toku_realloc);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
r = toku_lt_create(<, db, duplicates, dbpanic, ltm,
|
r = toku_lt_create(<, duplicates, dbpanic, ltm,
|
||||||
dbcmp, dbcmp, NULL, toku_free, toku_realloc);
|
get_compare_fun_from_db, get_dup_compare_from_db,
|
||||||
|
toku_malloc, NULL, toku_realloc);
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
r = toku_lt_create(<, db, duplicates, dbpanic, ltm,
|
r = toku_lt_create(<, duplicates, dbpanic, ltm,
|
||||||
dbcmp, dbcmp, toku_malloc, NULL, toku_realloc);
|
get_compare_fun_from_db, get_dup_compare_from_db,
|
||||||
CKERR2(r, EINVAL);
|
toku_malloc, toku_free, NULL);
|
||||||
r = toku_lt_create(<, db, duplicates, dbpanic, ltm,
|
|
||||||
dbcmp, dbcmp, toku_malloc, toku_free, NULL);
|
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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] ;
|
|||||||
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) {
|
|||||||
|
|
||||||
void setup_tree(BOOL dups) {
|
void setup_tree(BOOL dups) {
|
||||||
assert(!lt && !ltm);
|
assert(!lt && !ltm);
|
||||||
r = toku_ltm_create(<m, max_locks, toku_malloc, toku_free, toku_realloc);
|
r = toku_ltm_create(<m, 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(<, db, dups, dbpanic, ltm, dbcmp, dbcmp,
|
r = toku_lt_create(<, 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) {
|
|||||||
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) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
|||||||
}
|
}
|
||||||
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,
|
|||||||
|
|
||||||
|
|
||||||
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],
|
|||||||
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) {
|
|||||||
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[]) {
|
|||||||
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[]) {
|
|||||||
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[]) {
|
|||||||
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[]) {
|
|||||||
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 @@
|
|||||||
|
|
||||||
#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];
|
|||||||
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) {
|
|||||||
|
|
||||||
void setup_tree(BOOL dups) {
|
void setup_tree(BOOL dups) {
|
||||||
assert(!lt && !ltm);
|
assert(!lt && !ltm);
|
||||||
r = toku_ltm_create(<m, max_locks, toku_malloc, toku_free, toku_realloc);
|
r = toku_ltm_create(<m, 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(<, db, dups, dbpanic, ltm, dbcmp, dbcmp,
|
r = toku_lt_create(<, 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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
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,
|
|||||||
|
|
||||||
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 @@
|
|||||||
|
|
||||||
#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] ;
|
|||||||
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) {
|
|||||||
|
|
||||||
void setup_tree(BOOL dups) {
|
void setup_tree(BOOL dups) {
|
||||||
assert(!lt && !ltm);
|
assert(!lt && !ltm);
|
||||||
r = toku_ltm_create(<m, max_locks, toku_malloc, toku_free, toku_realloc);
|
r = toku_ltm_create(<m, 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(<, db, dups, dbpanic, ltm, intcmp, intcmp,
|
r = toku_lt_create(<, 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,
|
|||||||
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) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
|||||||
}
|
}
|
||||||
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) {
|
|||||||
|
|
||||||
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);
|
|||||||
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(<m, max_locks, toku_malloc, toku_free, toku_realloc);
|
r = toku_ltm_create(<m, 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(<, db, dups, dbpanic, ltm, intcmp, intcmp,
|
|
||||||
toku_malloc, toku_free, toku_realloc);
|
|
||||||
CKERR(r);
|
|
||||||
assert(lt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setup_tree(BOOL dups, size_t index, toku_db_id* db_id) {
|
||||||
|
assert(!lt[index] && ltm);
|
||||||
|
r = toku_ltm_get_lt(ltm, <[index], dups, db_id);
|
||||||
|
CKERR(r);
|
||||||
|
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;
|
||||||
|
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();
|
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);
|
||||||
|
|||||||
145
src/lock_tree/tests/test_00080_lt_refcount.c
Normal file
145
src/lock_tree/tests/test_00080_lt_refcount.c
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
/* 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(<m, 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, <s[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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
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) {
|
|||||||
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,
|
|||||||
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) {
|
|||||||
}
|
}
|
||||||
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,
|
|||||||
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,
|
|||||||
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) {
|
|||||||
//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) {
|
|||||||
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) {
|
|||||||
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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
|||||||
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) {
|
|||||||
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) {
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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) {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
/* -*- 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 {
|
|||||||
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 {
|
|||||||
* > 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
|
|||||||
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;
|
|||||||
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);
|
|||||||
- 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,
|
|||||||
*/
|
*/
|
||||||
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);
|
|||||||
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__)),
|
|||||||
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) {
|
|||||||
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) {
|
|||||||
}
|
}
|
||||||
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[]) {
|
|||||||
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[]) {
|
|||||||
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[]) {
|
|||||||
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[]) {
|
|||||||
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[]) {
|
|||||||
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);
|
|
||||||
range.data = NULL;
|
|
||||||
|
|
||||||
r = toku_rt_find(tree, &range, 2, NULL, &bufsize, &found);
|
|
||||||
CKERR2(r, EINVAL);
|
CKERR2(r, EINVAL);
|
||||||
|
|
||||||
r = toku_rt_find(tree, &range, 2, &buf, NULL, &found);
|
r = toku_rt_find(tree, &range.ends, 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[]) {
|
|||||||
/* 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[]) {
|
|||||||
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[]) {
|
|||||||
|
|
||||||
|
|
||||||
/* 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[]) {
|
|||||||
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[]) {
|
|||||||
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[]) {
|
|||||||
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[]) {
|
|||||||
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) {
|
|||||||
/* 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) {
|
|||||||
);
|
);
|
||||||
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);
|
||||||
|
|||||||
@@ -2,22 +2,12 @@
|
|||||||
|
|
||||||
#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 main(int argc, const char *argv[]) {
|
int main(int argc, const char *argv[]) {
|
||||||
int r;
|
int r;
|
||||||
toku_range_tree *tree = NULL;
|
toku_range_tree *tree = NULL;
|
||||||
toku_range range;
|
toku_range range;
|
||||||
toku_range find_range;
|
toku_interval find_range;
|
||||||
toku_range find_all_range;
|
toku_interval find_all_range;
|
||||||
int nums[1000];
|
int nums[1000];
|
||||||
char letters[2] = {'A','B'};
|
char letters[2] = {'A','B'};
|
||||||
unsigned found;
|
unsigned found;
|
||||||
@@ -34,11 +24,9 @@ int main(int argc, const char *argv[]) {
|
|||||||
|
|
||||||
find_range.left = (toku_point*)&nums[4];
|
find_range.left = (toku_point*)&nums[4];
|
||||||
find_range.right = (toku_point*)&nums[4];
|
find_range.right = (toku_point*)&nums[4];
|
||||||
find_range.data = NULL;
|
|
||||||
|
|
||||||
find_all_range.left = (toku_point*)&nums[0];
|
find_all_range.left = (toku_point*)&nums[0];
|
||||||
find_all_range.right = (toku_point*)&nums[sizeof(nums)/sizeof(nums[0]) - 1];
|
find_all_range.right = (toku_point*)&nums[sizeof(nums)/sizeof(nums[0]) - 1];
|
||||||
find_all_range.data = NULL;
|
|
||||||
|
|
||||||
#ifndef TOKU_RT_NOOVERLAPS
|
#ifndef TOKU_RT_NOOVERLAPS
|
||||||
bufsize = 2;
|
bufsize = 2;
|
||||||
@@ -59,9 +47,9 @@ int main(int argc, const char *argv[]) {
|
|||||||
assert(found == 0);
|
assert(found == 0);
|
||||||
assert(bufsize == 2);
|
assert(bufsize == 2);
|
||||||
|
|
||||||
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_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
||||||
@@ -69,9 +57,9 @@ int main(int argc, const char *argv[]) {
|
|||||||
assert(bufsize == 2);
|
assert(bufsize == 2);
|
||||||
verify_all_overlap(&find_range, buf, found);
|
verify_all_overlap(&find_range, buf, found);
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
||||||
@@ -79,9 +67,9 @@ int main(int argc, const char *argv[]) {
|
|||||||
assert(bufsize == 2);
|
assert(bufsize == 2);
|
||||||
verify_all_overlap(&find_range, buf, found);
|
verify_all_overlap(&find_range, buf, found);
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
/* Now that we find 3, we are testing that realloc works. */
|
/* Now that we find 3, we are testing that realloc works. */
|
||||||
@@ -90,9 +78,9 @@ int main(int argc, const char *argv[]) {
|
|||||||
assert(bufsize >= 3);
|
assert(bufsize >= 3);
|
||||||
verify_all_overlap(&find_range, buf, found);
|
verify_all_overlap(&find_range, buf, found);
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
||||||
@@ -101,9 +89,9 @@ int main(int argc, const char *argv[]) {
|
|||||||
verify_all_overlap(&find_range, buf, found);
|
verify_all_overlap(&find_range, buf, found);
|
||||||
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
||||||
@@ -113,14 +101,14 @@ int main(int argc, const char *argv[]) {
|
|||||||
|
|
||||||
/* Verify the right one is still there, and the wrong one is not there. */
|
/* Verify the right one is still there, and the wrong one is not there. */
|
||||||
for (i = 0; i < found; i++) {
|
for (i = 0; i < found; i++) {
|
||||||
assert(*(int*)buf[i].left != 2 ||
|
assert(*(int*)buf[i].ends.left != 2 ||
|
||||||
*(int*)buf[i].right != 6 ||
|
*(int*)buf[i].ends.right != 6 ||
|
||||||
*(char*)buf[i].data == letters[1]);
|
(char)buf[i].data == letters[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
||||||
@@ -128,9 +116,9 @@ int main(int argc, const char *argv[]) {
|
|||||||
assert(bufsize >= 4);
|
assert(bufsize >= 4);
|
||||||
verify_all_overlap(&find_range, buf, found);
|
verify_all_overlap(&find_range, buf, found);
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
||||||
@@ -140,15 +128,15 @@ int main(int argc, const char *argv[]) {
|
|||||||
|
|
||||||
/* Verify the right one is still there, and the wrong one is not there. */
|
/* Verify the right one is still there, and the wrong one is not there. */
|
||||||
for (i = 0; i < found; i++) {
|
for (i = 0; i < found; i++) {
|
||||||
assert(*(int*)buf[i].left != 2 ||
|
assert(*(int*)buf[i].ends.left != 2 ||
|
||||||
*(int*)buf[i].right != 6 ||
|
*(int*)buf[i].ends.right != 6 ||
|
||||||
*(char*)buf[i].data == letters[0]);
|
(char)buf[i].data == letters[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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);
|
||||||
|
|
||||||
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
||||||
@@ -156,9 +144,9 @@ int main(int argc, const char *argv[]) {
|
|||||||
assert(bufsize >= 4);
|
assert(bufsize >= 4);
|
||||||
verify_all_overlap(&find_range, buf, found);
|
verify_all_overlap(&find_range, buf, found);
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
||||||
@@ -167,13 +155,13 @@ int main(int argc, const char *argv[]) {
|
|||||||
verify_all_overlap(&find_range, buf, found);
|
verify_all_overlap(&find_range, buf, found);
|
||||||
|
|
||||||
/* Verify the right one is still there, and the wrong one is not there. */
|
/* Verify the right one is still there, and the wrong one is not there. */
|
||||||
assert(*(int*)buf[0].left == 3 &&
|
assert(*(int*)buf[0].ends.left == 3 &&
|
||||||
*(int*)buf[0].right == 7 &&
|
*(int*)buf[0].ends.right == 7 &&
|
||||||
*(char*)buf[0].data == letters[0]);
|
(char)buf[0].data == letters[0]);
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
||||||
@@ -201,7 +189,6 @@ int main(int argc, const char *argv[]) {
|
|||||||
*/
|
*/
|
||||||
find_range.left = (toku_point*)&nums[3];
|
find_range.left = (toku_point*)&nums[3];
|
||||||
find_range.right = (toku_point*)&nums[4];
|
find_range.right = (toku_point*)&nums[4];
|
||||||
find_range.data = NULL;
|
|
||||||
|
|
||||||
r = toku_rt_create(&tree, int_cmp, char_cmp, FALSE, malloc, free, realloc);
|
r = toku_rt_create(&tree, int_cmp, char_cmp, FALSE, malloc, free, realloc);
|
||||||
CKERR(r);
|
CKERR(r);
|
||||||
@@ -211,9 +198,9 @@ int main(int argc, const char *argv[]) {
|
|||||||
assert(bufsize >= 2);
|
assert(bufsize >= 2);
|
||||||
verify_all_overlap(&find_range, buf, found);
|
verify_all_overlap(&find_range, buf, found);
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
||||||
@@ -221,9 +208,9 @@ int main(int argc, const char *argv[]) {
|
|||||||
assert(bufsize >= 2);
|
assert(bufsize >= 2);
|
||||||
verify_all_overlap(&find_range, buf, found);
|
verify_all_overlap(&find_range, buf, found);
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
||||||
@@ -235,9 +222,9 @@ int main(int argc, const char *argv[]) {
|
|||||||
const uint32_t start_loop = 100;
|
const uint32_t start_loop = 100;
|
||||||
const uint32_t end_loop = 200;
|
const uint32_t end_loop = 200;
|
||||||
for (i = start_loop; i < end_loop; i += 4) {
|
for (i = start_loop; i < end_loop; i += 4) {
|
||||||
range.left = (toku_point*)&nums[i];
|
range.ends.left = (toku_point*)&nums[i];
|
||||||
range.right = (toku_point*)&nums[i+2];
|
range.ends.right = (toku_point*)&nums[i+2];
|
||||||
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);
|
||||||
inserted++;
|
inserted++;
|
||||||
|
|
||||||
@@ -246,17 +233,17 @@ int main(int argc, const char *argv[]) {
|
|||||||
assert(bufsize >= inserted);
|
assert(bufsize >= inserted);
|
||||||
}
|
}
|
||||||
for (i = start_loop; i < end_loop; i += 4) {
|
for (i = start_loop; i < end_loop; i += 4) {
|
||||||
range.left = (toku_point*)&nums[i];
|
range.ends.left = (toku_point*)&nums[i];
|
||||||
range.right = (toku_point*)&nums[i+2];
|
range.ends.right = (toku_point*)&nums[i+2];
|
||||||
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[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);
|
||||||
|
|
||||||
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
||||||
@@ -265,13 +252,13 @@ int main(int argc, const char *argv[]) {
|
|||||||
verify_all_overlap(&find_range, buf, found);
|
verify_all_overlap(&find_range, buf, found);
|
||||||
|
|
||||||
/* Verify the right one is still there, and the wrong one is not there. */
|
/* Verify the right one is still there, and the wrong one is not there. */
|
||||||
assert(*(int*)buf[0].left == 1 &&
|
assert(*(int*)buf[0].ends.left == 1 &&
|
||||||
*(int*)buf[0].right == 3 &&
|
*(int*)buf[0].ends.right == 3 &&
|
||||||
*(char*)buf[0].data == letters[0]);
|
(char)buf[0].data == letters[0]);
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
||||||
@@ -279,9 +266,9 @@ int main(int argc, const char *argv[]) {
|
|||||||
assert(bufsize >= inserted);
|
assert(bufsize >= inserted);
|
||||||
verify_all_overlap(&find_range, buf, found);
|
verify_all_overlap(&find_range, buf, found);
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
||||||
@@ -290,14 +277,14 @@ int main(int argc, const char *argv[]) {
|
|||||||
verify_all_overlap(&find_range, buf, found);
|
verify_all_overlap(&find_range, buf, found);
|
||||||
|
|
||||||
/* Verify the right one is still there, and the wrong one is not there. */
|
/* Verify the right one is still there, and the wrong one is not there. */
|
||||||
assert(*(int*)buf[0].left == 4 &&
|
assert(*(int*)buf[0].ends.left == 4 &&
|
||||||
*(int*)buf[0].right == 6 &&
|
*(int*)buf[0].ends.right == 6 &&
|
||||||
*(char*)buf[0].data == letters[1]);
|
(char)buf[0].data == letters[1]);
|
||||||
|
|
||||||
/* 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);
|
||||||
|
|
||||||
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
r = toku_rt_find(tree, &find_range, 4, &buf, &bufsize, &found); CKERR(r);
|
||||||
|
|||||||
@@ -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;
|
|||||||
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) {
|
|||||||
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) {
|
|||||||
|
|
||||||
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) {
|
|||||||
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) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
|||||||
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) {
|
|||||||
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) {
|
|||||||
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) {
|
|||||||
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) {
|
|||||||
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 @@
|
|||||||
|
|
||||||
#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;
|
|||||||
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) {
|
|||||||
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) {
|
|||||||
|
|
||||||
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) {
|
|||||||
|
|
||||||
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) {
|
|||||||
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) {
|
|||||||
|
|
||||||
/* 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) {
|
|||||||
|
|
||||||
/* 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 @@
|
|||||||
|
|
||||||
#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;
|
|||||||
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) {
|
|||||||
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) {
|
|||||||
|
|
||||||
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) {
|
|||||||
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);
|
||||||
|
|||||||
@@ -1,15 +1,5 @@
|
|||||||
#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;
|
|||||||
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) {
|
|||||||
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) {
|
|||||||
|
|
||||||
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) {
|
|||||||
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) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
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(
|
|||||||
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 @@ cleanup:
|
|||||||
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)
|
|
||||||
toku_rbt__destroy(rbinfo, rbinfo->rb_root);
|
|
||||||
|
|
||||||
|
void toku_rbt_destroy(struct toku_rbt_tree *rbinfo) {
|
||||||
|
toku_rbt_clear(rbinfo);
|
||||||
rbinfo->rb_free(rbinfo);
|
rbinfo->rb_free(rbinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,7 +149,7 @@ cleanup:
|
|||||||
|
|
||||||
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
|
|||||||
{
|
{
|
||||||
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(
|
|||||||
}
|
}
|
||||||
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(
|
|||||||
/* 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,
|
|||||||
{
|
{
|
||||||
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 (
|
|||||||
/* 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
|
|||||||
|
|
||||||
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 @@
|
|||||||
#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 {
|
|||||||
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
|
||||||
|
|||||||
239
src/ydb.c
239
src/ydb.c
@@ -29,7 +29,6 @@ const char *toku_copyright_string = "Copyright (c) 2007, 2008 Tokutek Inc. All
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
||||||
|
|
||||||
/** The default maximum number of persistent locks in a lock tree */
|
/** The default maximum number of persistent locks in a lock tree */
|
||||||
const u_int32_t __toku_env_default_max_locks = 1000;
|
const u_int32_t __toku_env_default_max_locks = 1000;
|
||||||
|
|
||||||
@@ -541,7 +540,7 @@ static int toku_env_set_lk_max_locks(DB_ENV *dbenv, u_int32_t max) {
|
|||||||
int r = ENOSYS;
|
int r = ENOSYS;
|
||||||
HANDLE_PANICKED_ENV(dbenv);
|
HANDLE_PANICKED_ENV(dbenv);
|
||||||
if (env_opened(dbenv)) { return EINVAL; }
|
if (env_opened(dbenv)) { return EINVAL; }
|
||||||
r = toku_ltm_set_max_locks(dbenv->i->ltm, max);
|
r = toku_ltm_set_max_locks_per_db(dbenv->i->ltm, max);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -557,7 +556,7 @@ static int locked_env_set_lk_max(DB_ENV * env, u_int32_t lk_max) {
|
|||||||
|
|
||||||
static int toku_env_get_lk_max_locks(DB_ENV *dbenv, u_int32_t *lk_maxp) {
|
static int toku_env_get_lk_max_locks(DB_ENV *dbenv, u_int32_t *lk_maxp) {
|
||||||
HANDLE_PANICKED_ENV(dbenv);
|
HANDLE_PANICKED_ENV(dbenv);
|
||||||
return toku_ltm_get_max_locks(dbenv->i->ltm, lk_maxp);
|
return toku_ltm_get_max_locks_per_db(dbenv->i->ltm, lk_maxp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int locked_env_set_lk_max_locks(DB_ENV *dbenv, u_int32_t max) {
|
static int locked_env_set_lk_max_locks(DB_ENV *dbenv, u_int32_t max) {
|
||||||
@@ -679,6 +678,12 @@ static int locked_env_txn_stat(DB_ENV * env, DB_TXN_STAT ** statp, u_int32_t fla
|
|||||||
|
|
||||||
static int locked_txn_begin(DB_ENV * env, DB_TXN * stxn, DB_TXN ** txn, u_int32_t flags);
|
static int locked_txn_begin(DB_ENV * env, DB_TXN * stxn, DB_TXN ** txn, u_int32_t flags);
|
||||||
|
|
||||||
|
static int toku_db_lt_panic(DB* db, int r);
|
||||||
|
|
||||||
|
static toku_dbt_cmp toku_db_get_compare_fun(DB* db);
|
||||||
|
|
||||||
|
static toku_dbt_cmp toku_db_get_dup_compare(DB* db);
|
||||||
|
|
||||||
static int toku_env_create(DB_ENV ** envp, u_int32_t flags) {
|
static int toku_env_create(DB_ENV ** envp, u_int32_t flags) {
|
||||||
int r = ENOSYS;
|
int r = ENOSYS;
|
||||||
DB_ENV* result = NULL;
|
DB_ENV* result = NULL;
|
||||||
@@ -728,7 +733,9 @@ static int toku_env_create(DB_ENV ** envp, u_int32_t flags) {
|
|||||||
result->i->errfile = 0;
|
result->i->errfile = 0;
|
||||||
|
|
||||||
r = toku_ltm_create(&result->i->ltm, __toku_env_default_max_locks,
|
r = toku_ltm_create(&result->i->ltm, __toku_env_default_max_locks,
|
||||||
toku_malloc, toku_free, toku_realloc);
|
toku_db_lt_panic,
|
||||||
|
toku_db_get_compare_fun, toku_db_get_dup_compare,
|
||||||
|
toku_malloc, toku_free, toku_realloc);
|
||||||
if (r!=0) { goto cleanup; }
|
if (r!=0) { goto cleanup; }
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -763,19 +770,25 @@ static int toku_txn_release_locks(DB_TXN* txn) {
|
|||||||
assert(txn);
|
assert(txn);
|
||||||
toku_lth* lth = txn->i->lth;
|
toku_lth* lth = txn->i->lth;
|
||||||
|
|
||||||
int r = 0;
|
int r = ENOSYS;
|
||||||
|
int first_error = 0;
|
||||||
if (lth) {
|
if (lth) {
|
||||||
toku_lth_start_scan(lth);
|
toku_lth_start_scan(lth);
|
||||||
toku_lock_tree* next = toku_lth_next(lth);
|
toku_lock_tree* next = toku_lth_next(lth);
|
||||||
int r2;
|
|
||||||
while (next) {
|
while (next) {
|
||||||
r2 = toku_lt_unlock(next, txn);
|
r = toku_lt_unlock(next, toku_txn_get_txnid(txn->i->tokutxn));
|
||||||
if (r2!=0 && !r) r = r2;
|
if (!first_error && r!=0) { first_error = r; }
|
||||||
|
if (r == 0) {
|
||||||
|
r = toku_lt_remove_ref(next);
|
||||||
|
if (!first_error && r!=0) { first_error = r; }
|
||||||
|
}
|
||||||
next = toku_lth_next(lth);
|
next = toku_lth_next(lth);
|
||||||
}
|
}
|
||||||
toku_lth_close(lth);
|
toku_lth_close(lth);
|
||||||
txn->i->lth = NULL;
|
txn->i->lth = NULL;
|
||||||
}
|
}
|
||||||
|
r = first_error;
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -786,6 +799,7 @@ static int toku_txn_commit(DB_TXN * txn, u_int32_t flags) {
|
|||||||
int nosync = (flags & DB_TXN_NOSYNC)!=0;
|
int nosync = (flags & DB_TXN_NOSYNC)!=0;
|
||||||
flags &= ~DB_TXN_NOSYNC;
|
flags &= ~DB_TXN_NOSYNC;
|
||||||
if (flags!=0) {
|
if (flags!=0) {
|
||||||
|
//TODO: Release locks perhaps?
|
||||||
if (txn->i) {
|
if (txn->i) {
|
||||||
if (txn->i->tokutxn)
|
if (txn->i->tokutxn)
|
||||||
toku_free(txn->i->tokutxn);
|
toku_free(txn->i->tokutxn);
|
||||||
@@ -794,8 +808,8 @@ static int toku_txn_commit(DB_TXN * txn, u_int32_t flags) {
|
|||||||
toku_free(txn);
|
toku_free(txn);
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
int r2 = toku_txn_release_locks(txn);
|
||||||
int r = toku_logger_commit(txn->i->tokutxn, nosync); // frees the tokutxn
|
int r = toku_logger_commit(txn->i->tokutxn, nosync); // frees the tokutxn
|
||||||
int r2 = toku_txn_release_locks(txn); // release the locks after the commit (otherwise, what if we abort)
|
|
||||||
// the toxutxn is freed, and we must free the rest. */
|
// the toxutxn is freed, and we must free the rest. */
|
||||||
if (txn->i)
|
if (txn->i)
|
||||||
toku_free(txn->i);
|
toku_free(txn->i);
|
||||||
@@ -812,12 +826,12 @@ static u_int32_t toku_txn_id(DB_TXN * txn) {
|
|||||||
|
|
||||||
static int toku_txn_abort(DB_TXN * txn) {
|
static int toku_txn_abort(DB_TXN * txn) {
|
||||||
HANDLE_PANICKED_ENV(txn->mgrp);
|
HANDLE_PANICKED_ENV(txn->mgrp);
|
||||||
|
int r2 = toku_txn_release_locks(txn);
|
||||||
int r = toku_logger_abort(txn->i->tokutxn);
|
int r = toku_logger_abort(txn->i->tokutxn);
|
||||||
|
|
||||||
toku_txn_release_locks(txn);
|
|
||||||
toku_free(txn->i);
|
toku_free(txn->i);
|
||||||
toku_free(txn);
|
toku_free(txn);
|
||||||
return r;
|
return r ? r : r2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int toku_txn_begin(DB_ENV *env, DB_TXN * stxn, DB_TXN ** txn, u_int32_t flags);
|
static int toku_txn_begin(DB_ENV *env, DB_TXN * stxn, DB_TXN ** txn, u_int32_t flags);
|
||||||
@@ -953,26 +967,27 @@ static int toku_db_associate (DB *primary, DB_TXN *txn, DB *secondary,
|
|||||||
|
|
||||||
static int toku_db_close(DB * db, u_int32_t flags) {
|
static int toku_db_close(DB * db, u_int32_t flags) {
|
||||||
if (db->i->primary==0) {
|
if (db->i->primary==0) {
|
||||||
// It is a primary. Unlink all the secondaries. */
|
// It is a primary. Unlink all the secondaries. */
|
||||||
while (!list_empty(&db->i->associated)) {
|
while (!list_empty(&db->i->associated)) {
|
||||||
assert(list_struct(list_head(&db->i->associated),
|
assert(list_struct(list_head(&db->i->associated),
|
||||||
struct __toku_db_internal,
|
struct __toku_db_internal, associated)->primary==db);
|
||||||
associated)->primary==db);
|
list_remove(list_head(&db->i->associated));
|
||||||
list_remove(list_head(&db->i->associated));
|
}
|
||||||
}
|
}
|
||||||
} else {
|
else {
|
||||||
// It is a secondary. Remove it from the list, (which it must be in .*/
|
// It is a secondary. Remove it from the list, (which it must be in .*/
|
||||||
if (!list_empty(&db->i->associated)) {
|
if (!list_empty(&db->i->associated)) {
|
||||||
list_remove(&db->i->associated);
|
list_remove(&db->i->associated);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
flags=flags;
|
flags=flags;
|
||||||
int r = toku_close_brt(db->i->brt);
|
int r = toku_close_brt(db->i->brt);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return r;
|
return r;
|
||||||
|
if (db->i->db_id) { toku_db_id_remove_ref(db->i->db_id); }
|
||||||
if (db->i->lt) {
|
if (db->i->lt) {
|
||||||
r = toku_lt_close(db->i->lt);
|
r = toku_lt_remove_ref(db->i->lt);
|
||||||
if (r!=0) return r;
|
if (r!=0) { return r; }
|
||||||
}
|
}
|
||||||
// printf("%s:%d %d=__toku_db_close(%p)\n", __FILE__, __LINE__, r, db);
|
// printf("%s:%d %d=__toku_db_close(%p)\n", __FILE__, __LINE__, r, db);
|
||||||
// Even if panicked, let's close as much as we can.
|
// Even if panicked, let's close as much as we can.
|
||||||
@@ -1077,9 +1092,12 @@ static inline int toku_uninitialized_swap(DBC* c, DBT* key, DBT* data,
|
|||||||
*/
|
*/
|
||||||
static inline DB_TXN* toku_txn_ancestor(DB_TXN* txn) {
|
static inline DB_TXN* toku_txn_ancestor(DB_TXN* txn) {
|
||||||
while (txn && txn->i->parent) txn = txn->i->parent;
|
while (txn && txn->i->parent) txn = txn->i->parent;
|
||||||
|
|
||||||
return txn;
|
return txn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int toku_txn_add_lt(DB_TXN* txn, toku_lock_tree* lt);
|
||||||
|
|
||||||
static int toku_c_get_pre_lock(DBC* c, DBT* key, DBT* data, u_int32_t* flag,
|
static int toku_c_get_pre_lock(DBC* c, DBT* key, DBT* data, u_int32_t* flag,
|
||||||
DBT* saved_key, DBT* saved_data) {
|
DBT* saved_key, DBT* saved_data) {
|
||||||
assert(saved_key && saved_data && flag);
|
assert(saved_key && saved_data && flag);
|
||||||
@@ -1093,6 +1111,8 @@ static int toku_c_get_pre_lock(DBC* c, DBT* key, DBT* data, u_int32_t* flag,
|
|||||||
unsigned int brtflags;
|
unsigned int brtflags;
|
||||||
toku_brt_get_flags(db->i->brt, &brtflags);
|
toku_brt_get_flags(db->i->brt, &brtflags);
|
||||||
BOOL duplicates = (brtflags & TOKU_DB_DUPSORT) != 0;
|
BOOL duplicates = (brtflags & TOKU_DB_DUPSORT) != 0;
|
||||||
|
DB_TXN* txn_anc = NULL;
|
||||||
|
TXNID id_anc = 0;
|
||||||
|
|
||||||
int r = 0;
|
int r = 0;
|
||||||
switch (get_flag) {
|
switch (get_flag) {
|
||||||
@@ -1105,8 +1125,11 @@ static int toku_c_get_pre_lock(DBC* c, DBT* key, DBT* data, u_int32_t* flag,
|
|||||||
}
|
}
|
||||||
case (DB_GET_BOTH): {
|
case (DB_GET_BOTH): {
|
||||||
get_both:
|
get_both:
|
||||||
r = toku_lt_acquire_read_lock(db->i->lt, toku_txn_ancestor(txn),
|
txn_anc = toku_txn_ancestor(txn);
|
||||||
key, data);
|
r = toku_txn_add_lt(txn_anc, db->i->lt);
|
||||||
|
if (r!=0) return r;
|
||||||
|
id_anc = toku_txn_get_txnid(txn_anc->i->tokutxn);
|
||||||
|
r = toku_lt_acquire_read_lock(db->i->lt, db, id_anc, key, data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (DB_SET_RANGE): {
|
case (DB_SET_RANGE): {
|
||||||
@@ -1256,10 +1279,15 @@ static int toku_c_get_post_lock(DBC* c, DBT* key, DBT* data, u_int32_t flag,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (lock) r = toku_lt_acquire_range_read_lock(db->i->lt,
|
if (lock) {
|
||||||
toku_txn_ancestor(txn),
|
DB_TXN* txn_anc = toku_txn_ancestor(txn);
|
||||||
key_l, data_l,
|
r = toku_txn_add_lt(txn_anc, db->i->lt);
|
||||||
key_r, data_r);
|
if (r!=0) { goto cleanup; }
|
||||||
|
TXNID id_anc = toku_txn_get_txnid(txn_anc->i->tokutxn);
|
||||||
|
r = toku_lt_acquire_range_read_lock(db->i->lt, db, id_anc,
|
||||||
|
key_l, data_l,
|
||||||
|
key_r, data_r);
|
||||||
|
}
|
||||||
cleanup:
|
cleanup:
|
||||||
if (saved_key->data) toku_free(saved_key->data);
|
if (saved_key->data) toku_free(saved_key->data);
|
||||||
if (saved_data->data) toku_free(saved_data->data);
|
if (saved_data->data) toku_free(saved_data->data);
|
||||||
@@ -1293,7 +1321,11 @@ static int toku_c_del_noassociate(DBC * c, u_int32_t flags) {
|
|||||||
DBT saved_data;
|
DBT saved_data;
|
||||||
r = toku_c_get_current_unconditional(c, &saved_key, &saved_data);
|
r = toku_c_get_current_unconditional(c, &saved_key, &saved_data);
|
||||||
if (r!=0) return r;
|
if (r!=0) return r;
|
||||||
r = toku_lt_acquire_write_lock(db->i->lt, toku_txn_ancestor(c->i->txn),
|
DB_TXN* txn_anc = toku_txn_ancestor(c->i->txn);
|
||||||
|
r = toku_txn_add_lt(txn_anc, db->i->lt);
|
||||||
|
if (r!=0) { return r; }
|
||||||
|
TXNID id_anc = toku_txn_get_txnid(txn_anc->i->tokutxn);
|
||||||
|
r = toku_lt_acquire_write_lock(db->i->lt, db, id_anc,
|
||||||
&saved_key, &saved_data);
|
&saved_key, &saved_data);
|
||||||
if (saved_key.data) toku_free(saved_key.data);
|
if (saved_key.data) toku_free(saved_key.data);
|
||||||
if (saved_data.data) toku_free(saved_data.data);
|
if (saved_data.data) toku_free(saved_data.data);
|
||||||
@@ -1516,7 +1548,11 @@ static int toku_db_del_noassociate(DB * db, DB_TXN * txn, DBT * key, u_int32_t f
|
|||||||
}
|
}
|
||||||
//Do the actual deleting.
|
//Do the actual deleting.
|
||||||
if (db->i->lt) {
|
if (db->i->lt) {
|
||||||
r = toku_lt_acquire_range_write_lock(db->i->lt, toku_txn_ancestor(txn),
|
DB_TXN* txn_anc = toku_txn_ancestor(txn);
|
||||||
|
r = toku_txn_add_lt(txn_anc, db->i->lt);
|
||||||
|
if (r!=0) { return r; }
|
||||||
|
TXNID id_anc = toku_txn_get_txnid(txn_anc->i->tokutxn);
|
||||||
|
r = toku_lt_acquire_range_write_lock(db->i->lt, db, id_anc,
|
||||||
key, toku_lt_neg_infinity,
|
key, toku_lt_neg_infinity,
|
||||||
key, toku_lt_infinity);
|
key, toku_lt_infinity);
|
||||||
if (r!=0) return r;
|
if (r!=0) return r;
|
||||||
@@ -1646,10 +1682,14 @@ static int toku_c_put(DBC *dbc, DBT *key, DBT *data, u_int32_t flags) {
|
|||||||
//Remove old pair.
|
//Remove old pair.
|
||||||
if (db->i->lt) {
|
if (db->i->lt) {
|
||||||
/* Acquire all write locks before */
|
/* Acquire all write locks before */
|
||||||
r = toku_lt_acquire_write_lock(db->i->lt, toku_txn_ancestor(txn),
|
DB_TXN* txn_anc = toku_txn_ancestor(txn);
|
||||||
|
r = toku_txn_add_lt(txn_anc, db->i->lt);
|
||||||
|
if (r!=0) { return r; }
|
||||||
|
TXNID id_anc = toku_txn_get_txnid(txn_anc->i->tokutxn);
|
||||||
|
r = toku_lt_acquire_write_lock(db->i->lt, db, id_anc,
|
||||||
&key_local, &data_local);
|
&key_local, &data_local);
|
||||||
if (r!=0) goto cleanup;
|
if (r!=0) goto cleanup;
|
||||||
r = toku_lt_acquire_write_lock(db->i->lt, toku_txn_ancestor(txn),
|
r = toku_lt_acquire_write_lock(db->i->lt, db, id_anc,
|
||||||
&key_local, data);
|
&key_local, data);
|
||||||
if (r!=0) goto cleanup;
|
if (r!=0) goto cleanup;
|
||||||
}
|
}
|
||||||
@@ -1954,6 +1994,7 @@ static int toku_db_lt_panic(DB* db, int r) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int toku_txn_add_lt(DB_TXN* txn, toku_lock_tree* lt) {
|
static int toku_txn_add_lt(DB_TXN* txn, toku_lock_tree* lt) {
|
||||||
|
int r = ENOSYS;
|
||||||
assert(txn && lt);
|
assert(txn && lt);
|
||||||
toku_lth* lth = txn->i->lth;
|
toku_lth* lth = txn->i->lth;
|
||||||
assert(lth);
|
assert(lth);
|
||||||
@@ -1961,22 +2002,24 @@ static int toku_txn_add_lt(DB_TXN* txn, toku_lock_tree* lt) {
|
|||||||
toku_lock_tree* find = toku_lth_find(lth, lt);
|
toku_lock_tree* find = toku_lth_find(lth, lt);
|
||||||
if (find) {
|
if (find) {
|
||||||
assert(find == lt);
|
assert(find == lt);
|
||||||
return 0;
|
r = 0;
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
int r = toku_lth_insert(lth, lt);
|
r = toku_lth_insert(lth, lt);
|
||||||
|
if (r != 0) { goto cleanup; }
|
||||||
|
|
||||||
|
toku_lt_add_ref(lt);
|
||||||
|
r = 0;
|
||||||
|
cleanup:
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void toku_txn_remove_lt(DB_TXN* txn, toku_lock_tree* lt) {
|
static toku_dbt_cmp toku_db_get_compare_fun(DB* db) {
|
||||||
assert(txn && lt);
|
return db->i->brt->compare_fun;
|
||||||
toku_lth* lth = txn->i->lth;
|
}
|
||||||
assert(lth);
|
|
||||||
|
|
||||||
toku_lock_tree* find = toku_lth_find(lth, lt);
|
static toku_dbt_cmp toku_db_get_dup_compare(DB* db) {
|
||||||
if (find) {
|
return db->i->brt->dup_compare;
|
||||||
assert(find == lt);
|
|
||||||
toku_lth_delete(lth, lt);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int toku_db_open(DB * db, DB_TXN * txn, const char *fname, const char *dbname, DBTYPE dbtype, u_int32_t flags, int mode) {
|
static int toku_db_open(DB * db, DB_TXN * txn, const char *fname, const char *dbname, DBTYPE dbtype, u_int32_t flags, int mode) {
|
||||||
@@ -2044,20 +2087,6 @@ static int toku_db_open(DB * db, DB_TXN * txn, const char *fname, const char *db
|
|||||||
db->i->open_flags = flags;
|
db->i->open_flags = flags;
|
||||||
db->i->open_mode = mode;
|
db->i->open_mode = mode;
|
||||||
|
|
||||||
if (need_locktree) {
|
|
||||||
r = toku_lt_create(&db->i->lt, db, FALSE,
|
|
||||||
toku_db_lt_panic, db->dbenv->i->ltm,
|
|
||||||
db->i->brt->compare_fun, db->i->brt->dup_compare,
|
|
||||||
toku_malloc, toku_free, toku_realloc);
|
|
||||||
if (r!=0) goto error_cleanup;
|
|
||||||
r = toku_lt_set_txn_add_lt_callback(db->i->lt, toku_txn_add_lt);
|
|
||||||
if (r!=0) fprintf(stderr, "%s:%d r=%d (%s)\n", __FILE__, __LINE__, r, strerror(r));
|
|
||||||
assert(r==0);
|
|
||||||
r = toku_lt_set_txn_remove_lt_callback(db->i->lt, toku_txn_remove_lt);
|
|
||||||
assert(r==0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
r = toku_brt_open(db->i->brt, db->i->full_fname, fname, dbname,
|
r = toku_brt_open(db->i->brt, db->i->full_fname, fname, dbname,
|
||||||
is_db_create, is_db_excl, is_db_unknown,
|
is_db_create, is_db_excl, is_db_unknown,
|
||||||
@@ -2067,20 +2096,26 @@ static int toku_db_open(DB * db, DB_TXN * txn, const char *fname, const char *db
|
|||||||
if (r != 0)
|
if (r != 0)
|
||||||
goto error_cleanup;
|
goto error_cleanup;
|
||||||
|
|
||||||
if (db->i->lt) {
|
if (need_locktree) {
|
||||||
unsigned int brtflags;
|
unsigned int brtflags;
|
||||||
BOOL dups;
|
BOOL dups;
|
||||||
/* Whether we have dups is only known starting now. */
|
|
||||||
toku_brt_get_flags(db->i->brt, &brtflags);
|
toku_brt_get_flags(db->i->brt, &brtflags);
|
||||||
dups = (brtflags & TOKU_DB_DUPSORT || brtflags & TOKU_DB_DUP);
|
dups = (brtflags & TOKU_DB_DUPSORT || brtflags & TOKU_DB_DUP);
|
||||||
r = toku_lt_set_dups(db->i->lt, dups);
|
|
||||||
/* toku_lt_set_dups cannot return an error here. */
|
r = toku_db_id_create(&db->i->db_id, db->i->full_fname,
|
||||||
assert(r==0);
|
db->i->database_name);
|
||||||
|
if (r!=0) { goto error_cleanup; }
|
||||||
|
r = toku_ltm_get_lt(db->dbenv->i->ltm, &db->i->lt, dups, db->i->db_id);
|
||||||
|
if (r!=0) { goto error_cleanup; }
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_cleanup:
|
error_cleanup:
|
||||||
|
if (db->i->db_id) {
|
||||||
|
toku_db_id_remove_ref(db->i->db_id);
|
||||||
|
db->i->db_id = NULL;
|
||||||
|
}
|
||||||
if (db->i->database_name) {
|
if (db->i->database_name) {
|
||||||
toku_free(db->i->database_name);
|
toku_free(db->i->database_name);
|
||||||
db->i->database_name = NULL;
|
db->i->database_name = NULL;
|
||||||
@@ -2090,7 +2125,7 @@ error_cleanup:
|
|||||||
db->i->full_fname = NULL;
|
db->i->full_fname = NULL;
|
||||||
}
|
}
|
||||||
if (db->i->lt) {
|
if (db->i->lt) {
|
||||||
toku_lt_close(db->i->lt);
|
toku_lt_remove_ref(db->i->lt);
|
||||||
db->i->lt = NULL;
|
db->i->lt = NULL;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
@@ -2142,8 +2177,11 @@ static int toku_db_put_noassociate(DB * db, DB_TXN * txn, DBT * key, DBT * data,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (db->i->lt) {
|
if (db->i->lt) {
|
||||||
r = toku_lt_acquire_write_lock(db->i->lt, toku_txn_ancestor(txn),
|
DB_TXN* txn_anc = toku_txn_ancestor(txn);
|
||||||
key, data);
|
r = toku_txn_add_lt(txn_anc, db->i->lt);
|
||||||
|
if (r!=0) { return r; }
|
||||||
|
TXNID id_anc = toku_txn_get_txnid(txn_anc->i->tokutxn);
|
||||||
|
r = toku_lt_acquire_write_lock(db->i->lt, db, id_anc, key, data);
|
||||||
if (r!=0) return r;
|
if (r!=0) return r;
|
||||||
}
|
}
|
||||||
r = toku_brt_insert(db->i->brt, key, data, txn ? txn->i->tokutxn : 0);
|
r = toku_brt_insert(db->i->brt, key, data, txn ? txn->i->tokutxn : 0);
|
||||||
@@ -2194,33 +2232,63 @@ static int toku_db_put(DB * db, DB_TXN * txn, DBT * key, DBT * data, u_int32_t f
|
|||||||
|
|
||||||
static int toku_db_remove(DB * db, const char *fname, const char *dbname, u_int32_t flags) {
|
static int toku_db_remove(DB * db, const char *fname, const char *dbname, u_int32_t flags) {
|
||||||
HANDLE_PANICKED_DB(db);
|
HANDLE_PANICKED_DB(db);
|
||||||
int r;
|
int r = ENOSYS;
|
||||||
int r2;
|
int r2 = 0;
|
||||||
char *full_name;
|
toku_db_id* db_id = NULL;
|
||||||
|
BOOL need_close = TRUE;
|
||||||
|
char* full_name = NULL;
|
||||||
|
toku_ltm* ltm = NULL;
|
||||||
|
|
||||||
//TODO: Verify DB* db not yet opened
|
//TODO: Verify DB* db not yet opened
|
||||||
|
//TODO: Verify db file not in use. (all dbs in the file must be unused)
|
||||||
|
r = toku_db_open(db, NULL, fname, dbname, DB_BTREE, 0, 0777);
|
||||||
|
if (r!=0) { goto cleanup; }
|
||||||
|
if (db->i->lt) {
|
||||||
|
/* Lock tree exists, therefore:
|
||||||
|
* Non-private environment (since we are using transactions)
|
||||||
|
* Environment will exist after db->close */
|
||||||
|
if (db->i->db_id) {
|
||||||
|
/* 'copy' the db_id */
|
||||||
|
db_id = db->i->db_id;
|
||||||
|
toku_db_id_add_ref(db_id);
|
||||||
|
}
|
||||||
|
if (db->dbenv->i->ltm) { ltm = db->dbenv->i->ltm; }
|
||||||
|
}
|
||||||
|
|
||||||
if (dbname) {
|
if (dbname) {
|
||||||
//TODO: Verify the target db is not open
|
//TODO: Verify the target db is not open
|
||||||
//TODO: Use master database (instead of manual edit) when implemented.
|
//TODO: Use master database (instead of manual edit) when implemented.
|
||||||
|
|
||||||
if ((r = toku_db_open(db, NULL, fname, dbname, DB_BTREE, 0, 0777)) != 0) goto cleanup;
|
|
||||||
r = toku_brt_remove_subdb(db->i->brt, dbname, flags);
|
r = toku_brt_remove_subdb(db->i->brt, dbname, flags);
|
||||||
|
if (r!=0) { goto cleanup; }
|
||||||
|
}
|
||||||
|
r = toku_db_close(db, 0);
|
||||||
|
need_close = FALSE;
|
||||||
|
if (r!=0) { goto cleanup; }
|
||||||
|
if (!dbname) {
|
||||||
|
r = find_db_file(db->dbenv, fname, &full_name);
|
||||||
|
if (r!=0) { goto cleanup; }
|
||||||
|
assert(full_name);
|
||||||
|
if (unlink(full_name) != 0) { r = errno; goto cleanup; }
|
||||||
|
}
|
||||||
|
if (ltm && db_id) { toku_ltm_invalidate_lt(ltm, db_id); }
|
||||||
|
|
||||||
|
r = 0;
|
||||||
cleanup:
|
cleanup:
|
||||||
r2 = toku_db_close(db, 0);
|
if (need_close) { r2 = toku_db_close(db, 0); }
|
||||||
return r ? r : r2;
|
if (full_name) { toku_free(full_name); }
|
||||||
}
|
if (db_id) { toku_db_id_remove_ref(db_id); }
|
||||||
//TODO: Verify db file not in use. (all dbs in the file must be unused)
|
|
||||||
r = find_db_file(db->dbenv, fname, &full_name);
|
|
||||||
if (r!=0) return r;
|
|
||||||
assert(full_name);
|
|
||||||
r2 = toku_db_close(db, 0);
|
|
||||||
if (r == 0 && r2 == 0) {
|
|
||||||
if (unlink(full_name) != 0) r = errno;
|
|
||||||
}
|
|
||||||
toku_free(full_name);
|
|
||||||
return r ? r : r2;
|
return r ? r : r2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: Either
|
||||||
|
-find a way for the DB_ID to survive this rename (i.e. be
|
||||||
|
the same before and after
|
||||||
|
or
|
||||||
|
-Go through all DB_IDs in the ltm, and rename them so we
|
||||||
|
have the correct unique ids.
|
||||||
|
TODO: Verify the DB file is not in use (either a single db file or
|
||||||
|
a file with multi-databases).
|
||||||
|
*/
|
||||||
static int toku_db_rename(DB * db, const char *namea, const char *nameb, const char *namec, u_int32_t flags) {
|
static int toku_db_rename(DB * db, const char *namea, const char *nameb, const char *namec, u_int32_t flags) {
|
||||||
HANDLE_PANICKED_DB(db);
|
HANDLE_PANICKED_DB(db);
|
||||||
if (flags!=0) return EINVAL;
|
if (flags!=0) return EINVAL;
|
||||||
@@ -2578,3 +2646,4 @@ const char *db_version(int *major, int *minor, int *patch) {
|
|||||||
int db_env_set_func_fsync (int (*fsync_function)(int)) {
|
int db_env_set_func_fsync (int (*fsync_function)(int)) {
|
||||||
return toku_set_func_fsync(fsync_function);
|
return toku_set_func_fsync(fsync_function);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user