Commit 72d39612 authored by Yoni Fogel's avatar Yoni Fogel

Addresses #293

Addresses #329
Combined rangetree hashtables and the lock tree.

git-svn-id: file:///svn/tokudb@2044 c7de825b-a66e-492c-adef-691d508d4ae1
parent f3b38bfb
......@@ -45,8 +45,11 @@ clean:
locktree.o: locktree.c locktree.h
gcc $(CFLAGS) $(CPPFLAGS) -c -DTOKU_LINEAR_RANGE_TREE $< -o $@
$(LIBNAME).$(LIBEXT): locktree.o
cc $(CPPFLAGS) $< $(SHARED) -o $@ $(CFLAGS) -lrangetreelinear
rth.o: rth.c rth.h
gcc $(CFLAGS) $(CPPFLAGS) -c -DTOKU_LINEAR_RANGE_TREE $< -o $@
$(LIBNAME).$(LIBEXT): locktree.o rth.o
cc $(CPPFLAGS) $^ $(SHARED) -o $@ $(CFLAGS) -lrangetreelinear
$(LIBNAME).a: locktree.o
$(AR) rv $@ $<
$(LIBNAME).a: locktree.o rth.o
$(AR) rv $@ $^
......@@ -176,42 +176,22 @@ static int __toku_p_makecopy(toku_lock_tree* tree, void** ppoint) {
return 0;
}
/* Provides access to a selfwrite tree for a particular transaction.
Returns NULL if it does not exist yet. */
toku_range_tree* __toku_lt_ifexist_selfwrite(toku_lock_tree* tree,
DB_TXN* txn) {
assert(tree && txn);
//TODO: Implement real version.
return tree->selfwrite;
}
/* Provides access to a selfread tree for a particular transaction.
Returns NULL if it does not exist yet. */
toku_range_tree* __toku_lt_ifexist_selfread(toku_lock_tree* tree, DB_TXN* txn) {
assert(tree && txn);
//TODO: Implement.
return tree->selfread;
toku_rt_forest* forest = toku_rth_find(tree->rth, txn);
return forest ? forest->self_read : NULL;
}
/* Provides access to a selfwrite tree for a particular transaction.
Creates it if it does not exist. */
static int __toku_lt_selfwrite(toku_lock_tree* tree, DB_TXN* txn,
toku_range_tree** pselfwrite) {
int r;
assert(tree && txn && pselfwrite);
//TODO: Remove this, and use multiples per transaction
if (!tree->selfwrite)
{
r = toku_rt_create(&tree->selfwrite,
__toku_lt_point_cmp, __toku_lt_txn_cmp, FALSE,
tree->malloc, tree->free, tree->realloc);
if(r!=0) return r;
}
assert(tree->selfwrite);
*pselfwrite = tree->selfwrite;
return 0;
Returns NULL if it does not exist yet. */
toku_range_tree* __toku_lt_ifexist_selfwrite(toku_lock_tree* tree,
DB_TXN* txn) {
assert(tree && txn);
toku_rt_forest* forest = toku_rth_find(tree->rth, txn);
return forest ? forest->self_write : NULL;
}
/* Provides access to a selfread tree for a particular transaction.
......@@ -221,20 +201,52 @@ static int __toku_lt_selfread(toku_lock_tree* tree, DB_TXN* txn,
int r;
assert(tree && txn && pselfread);
//TODO: Remove this, and use multiples per transaction
if (!tree->selfread)
{
r = toku_rt_create(&tree->selfread,
__toku_lt_point_cmp, __toku_lt_txn_cmp, FALSE,
tree->malloc, tree->free, tree->realloc);
if(r!=0) return r;
toku_rt_forest* forest = toku_rth_find(tree->rth, txn);
if (!forest) {
r = toku_rth_insert(tree->rth, txn);
if (r!=0) return r;
forest = toku_rth_find(tree->rth, txn);
}
assert(forest);
if (!forest->self_read) {
r = toku_rt_create(&forest->self_read,
__toku_lt_point_cmp, __toku_lt_txn_cmp,
FALSE,
tree->malloc, tree->free, tree->realloc);
if (r!=0) return r;
assert(forest->self_read);
}
*pselfread = forest->self_read;
return 0;
}
assert(tree->selfread);
*pselfread = tree->selfread;
/* Provides access to a selfwrite tree for a particular transaction.
Creates it if it does not exist. */
static int __toku_lt_selfwrite(toku_lock_tree* tree, DB_TXN* txn,
toku_range_tree** pselfwrite) {
int r;
assert(tree && txn && pselfwrite);
toku_rt_forest* forest = toku_rth_find(tree->rth, txn);
if (!forest) {
r = toku_rth_insert(tree->rth, txn);
if (r!=0) return r;
forest = toku_rth_find(tree->rth, txn);
}
assert(forest);
if (!forest->self_write) {
r = toku_rt_create(&forest->self_write,
__toku_lt_point_cmp, __toku_lt_txn_cmp,
FALSE,
tree->malloc, tree->free, tree->realloc);
if (r!=0) return r;
assert(forest->self_write);
}
*pselfwrite = forest->self_write;
return 0;
}
/*
This function only supports non-overlapping trees.
Uses the standard definition of dominated from the design document.
......@@ -884,12 +896,13 @@ int toku_lt_create(toku_lock_tree** ptree, DB* db, BOOL duplicates,
user_malloc, user_free, user_realloc);
if (0) { died3: toku_rt_close(tmp_tree->borderwrite); goto died2; }
if (r!=0) goto died2;
r = toku_rth_create(&tmp_tree->rth, user_malloc, user_free, user_realloc);
if (0) { died4: toku_rth_close(tmp_tree->rth); goto died3; }
if (r!=0) goto died3;
tmp_tree->buflen = __toku_default_buflen;
tmp_tree->buf = (toku_range*)
user_malloc(tmp_tree->buflen * sizeof(toku_range));
if (!tmp_tree->buf) { r = errno; goto died3; }
//TODO: Create list of selfreads
//TODO: Create list of selfwrites
if (!tmp_tree->buf) { r = errno; goto died4; }
*ptree = tmp_tree;
return 0;
}
......@@ -902,16 +915,18 @@ int toku_lt_close(toku_lock_tree* tree) {
if (r!=0) r2 = r;
r = toku_rt_close(tree->borderwrite);
if (!r2 && r!=0) r2 = r;
//TODO: Do this to ALLLLLLLL selfread and ALLLLLL selfwrite tables.
/* Free all points referred to in a range tree (and close the tree). */
r = __toku_lt_free_contents(tree,
__toku_lt_ifexist_selfread (tree, (DB_TXN*)1), NULL);
if (!r2 && r!=0) r2 = r;
r= __toku_lt_free_contents( tree,
__toku_lt_ifexist_selfwrite(tree, (DB_TXN*)1), NULL);
if (!r2 && r!=0) r2 = r;
//TODO: After freeing the tree, need to remove it from both lists!!!
// One list probably IN the transaction, and one additional one here.
toku_rth_start_scan(tree->rth);
toku_rt_forest* forest;
while ((forest = toku_rth_next(tree->rth)) != NULL) {
r = __toku_lt_free_contents(tree, forest->self_read, NULL);
if (!r2 && r!=0) r2 = r;
r = __toku_lt_free_contents(tree, forest->self_write, NULL);
if (!r2 && r!=0) r2 = r;
}
toku_rth_close(tree->rth);
tree->free(tree->buf);
tree->free(tree);
return r2;
......
......@@ -47,6 +47,7 @@
#include <db.h>
#include <brttypes.h>
#include <rangetree.h>
#include <rth.h>
/** \brief The lock tree structure */
typedef struct {
......@@ -56,10 +57,7 @@ typedef struct {
BOOL duplicates;
toku_range_tree* mainread; /**< See design document */
toku_range_tree* borderwrite; /**< See design document */
//TODO: Remove this tree and have one per transaction.
toku_range_tree* selfread;
//TODO: Remove this tree and have one per transaction.
toku_range_tree* selfwrite;
toku_rt_hashtable* rth;
/** A temporary area where we store the results of various find on
the range trees that this lock tree owns */
toku_range* buf;
......
......@@ -9,7 +9,13 @@
*/
#include "hash_table.h"
#include "rth.h"
#include <assert.h>
#include <errno.h>
#include <string.h>
/* TODO: reallocate the hash table if it grows too big. Perhaps, use toku_get_prime in newbrt/primes.c */
const uint32 __toku_rth_init_size = 521;
static uint32 __toku_rth_hash(toku_rt_hashtable* table, DB_TXN* key) {
assert(table);
......@@ -41,8 +47,8 @@ int toku_rth_create(toku_rt_hashtable** ptable,
toku_rt_forest* toku_rth_find(toku_rt_hashtable* table, DB_TXN* key) {
assert(table && key);
uint32 index = __toku_rth_hash(table, key);
toku_rt_hash_elt* element = table->table[index];
uint32 index = __toku_rth_hash(table, key);
toku_rth_elt* element = table->table[index];
while (element && element->key != key) element = element->next;
return element ? &element->value : NULL;
}
......@@ -53,8 +59,8 @@ void toku_rth_start_scan(toku_rt_hashtable* table) {
table->finger_ptr = NULL;
}
toku_rt_forest* toku_rth_next(toku_rt_hashtable* table) {
assert(table && value && found);
toku_rth_elt* __toku_rth_next(toku_rt_hashtable* table) {
assert(table);
if (table->finger_ptr) table->finger_ptr = table->finger_ptr->next;
while (!table->finger_ptr && table->finger_index < table->array_size) {
table->finger_ptr = table->table[++table->finger_index];
......@@ -62,13 +68,19 @@ toku_rt_forest* toku_rth_next(toku_rt_hashtable* table) {
return table->finger_ptr;
}
toku_rt_forest* toku_rth_next(toku_rt_hashtable* table) {
assert(table);
toku_rth_elt* next = __toku_rth_next(table);
return next ? &next->value : NULL;
}
int toku_rth_delete(toku_rt_hashtable* table, DB_TXN* key) {
assert(table && key);
/* No elements. */
if (!table->num_keys) return EDOM;
uint32 index = __toku_rth_hash(table, key);
toku_rt_hash_elt* element = table->table[index];
toku_rth_elt* element = table->table[index];
/* No elements of the right hash. */
if (!element) return EDOM;
......@@ -77,7 +89,7 @@ int toku_rth_delete(toku_rt_hashtable* table, DB_TXN* key) {
table->table[index] = element->next;
goto recycle;
}
toku_rt_hash_elt* prev;
toku_rth_elt* prev;
/* Case where it is not the first element. */
do {
prev = element;
......@@ -96,14 +108,14 @@ int toku_rth_delete(toku_rt_hashtable* table, DB_TXN* key) {
}
void toku_rth_close(toku_rt_hashtable* table) {
toku_rt_hash_elt* element;
toku_rt_hash_elt* next = NULL;
toku_rth_elt* element;
toku_rth_elt* next = NULL;
toku_rth_start_scan(table);
next = toku_rth_next(table);
next = __toku_rth_next(table);
while (next) {
element = next;
next = toku_rth_next(table);
next = __toku_rth_next(table);
table->free(element);
}
......@@ -119,27 +131,26 @@ void toku_rth_close(toku_rt_hashtable* table) {
}
/* Will allow you to insert it over and over. You need to keep track. */
int toku_rth_insert(toku_rt_hashtable* table, DB_TXN* key,
toku_rt_forsest* value) {
assert(table && key && value);
int toku_rth_insert(toku_rt_hashtable* table, DB_TXN* key) {
assert(table && key);
uint32 index = __toku_rth_hash(table, key);
toku_rt_hash_elt* next = table->table[index];
/* Recycle */
toku_rt_hash_elt* element;
toku_rth_elt* element;
if (table->free_list) {
element = table->free_list;
table->free_list = table->free_list->next;
element = table->free_list;
table->free_list = table->free_list->next;
}
else {
/* Allocate a new one. */
element = (toku_rt_hash_elt*)table->malloc(sizeof(*element));
element = (toku_rth_elt*)table->malloc(sizeof(*element));
if (!element) return errno;
}
element->next = table->table[index];
table->table[index]->next = element;
memset(&element->value, 0, sizeof(toku_rt_forest));
element->key = key;
element->next = table->table[index];
table->table[index] = element;
table->num_keys++;
return 0;
}
\ No newline at end of file
......@@ -10,33 +10,27 @@
*/
//Defines BOOL data type.
#include <db.h>
#include <brttypes.h>
#include <rangetree.h>
typedef u_int32_t uint32;
/* TODO: reallocate the hash table if it grows too big. Perhaps, use toku_get_prime in newbrt/primes.c */
const uint32 __toku_rth_init_size = 521;
typedef struct __toku_rt_forest toku_rt_forest;
struct __toku_rt_forest {
toku_range_tree* selfread;
toku_range_tree* selfwrite;
toku_range_tree* self_read;
toku_range_tree* self_write;
};
typedef struct __toku_rth_elt toku_rth_elt;
struct __toku_rth_elt {
DB_TXN* key;
toku_range_forest value;
DB_TXN* key;
toku_rt_forest value;
toku_rth_elt* next;
};
typedef struct {
uint32 index;
toku_rth_elt* next;
} toku_rth_finger;
typedef struct __toku_rt_hash_elt toku_rt_hash_elt;
struct toku_rt_hashtable {
typedef struct __toku_rt_hashtable toku_rt_hashtable;
struct __toku_rt_hashtable {
toku_rth_elt** table;
uint32 num_keys;
uint32 array_size;
......@@ -56,8 +50,8 @@ int toku_rth_create(toku_rt_hashtable** ptable,
void (*user_free) (void*),
void* (*user_realloc)(void*, size_t));
void toku_rth_find(toku_rt_hashtable* table, DB_TXN* key, toku_rt_forest* value,
BOOL* found);
toku_rt_forest* toku_rth_find(toku_rt_hashtable* table, DB_TXN* key);
void toku_rth_start_scan(toku_rt_hashtable* table);
toku_rt_forest* toku_rth_next(toku_rt_hashtable* table);
......@@ -66,5 +60,4 @@ int toku_rth_delete(toku_rt_hashtable* table, DB_TXN* key);
void toku_rth_close(toku_rt_hashtable* table);
int toku_rth_insert(toku_rt_hashtable* table, DB_TXN* key,
toku_rt_forsest* value);
int toku_rth_insert(toku_rt_hashtable* table, DB_TXN* key);
......@@ -3,6 +3,8 @@
#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_RANGE_TREE_H)
#define TOKU_RANGE_TREE_H
/**
\file rangetree.h
\brief Range trees: header and comments
......@@ -223,3 +225,4 @@ int toku_rt_predecessor(toku_range_tree* tree, void* point, toku_range* pred,
*/
int toku_rt_successor(toku_range_tree* tree, void* point, toku_range* succ,
BOOL* wasfound);
#endif /* #if !defined(TOKU_RANGE_TREE_H) */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment