Commit f32fcb75 authored by Yoni Fogel's avatar Yoni Fogel

Closes #777

omt used to replaced libredblack


git-svn-id: file:///svn/tokudb@3986 c7de825b-a66e-492c-adef-691d508d4ae1
parent 9c26f7c6
......@@ -99,6 +99,7 @@ typedef enum {
#endif
/* TOKUDB specific error codes */
#define TOKUDB_OUT_OF_LOCKS -100000
#define TOKUDB_SUCCEEDED_EARLY -100001
/* in wrap mode, top-level function txn_begin is renamed, but the field isn't renamed, so we have to hack it here.*/
#ifdef _TOKUDB_WRAP_H
#undef txn_begin
......
......@@ -101,6 +101,7 @@ typedef enum {
#endif
/* TOKUDB specific error codes */
#define TOKUDB_OUT_OF_LOCKS -100000
#define TOKUDB_SUCCEEDED_EARLY -100001
/* in wrap mode, top-level function txn_begin is renamed, but the field isn't renamed, so we have to hack it here.*/
#ifdef _TOKUDB_WRAP_H
#undef txn_begin
......
......@@ -101,6 +101,7 @@ typedef enum {
#endif
/* TOKUDB specific error codes */
#define TOKUDB_OUT_OF_LOCKS -100000
#define TOKUDB_SUCCEEDED_EARLY -100001
/* in wrap mode, top-level function txn_begin is renamed, but the field isn't renamed, so we have to hack it here.*/
#ifdef _TOKUDB_WRAP_H
#undef txn_begin
......
......@@ -101,6 +101,7 @@ typedef enum {
#endif
/* TOKUDB specific error codes */
#define TOKUDB_OUT_OF_LOCKS -100000
#define TOKUDB_SUCCEEDED_EARLY -100001
/* in wrap mode, top-level function txn_begin is renamed, but the field isn't renamed, so we have to hack it here.*/
#ifdef _TOKUDB_WRAP_H
#undef txn_begin
......
......@@ -11,9 +11,9 @@ extern "C" {
#define TOKUDB 1
#define DB_VERSION_MAJOR 4
#define DB_VERSION_MINOR 6
#define DB_VERSION_PATCH 21
#define DB_VERSION_PATCH 19
#ifndef _TOKUDB_WRAP_H
#define DB_VERSION_STRING "Tokutek: TokuDB 4.6.21"
#define DB_VERSION_STRING "Tokutek: TokuDB 4.6.19"
#else
#define DB_VERSION_STRING_ydb "Tokutek: TokuDB (wrapped bdb)"
#endif
......@@ -103,6 +103,7 @@ typedef enum {
#endif
/* TOKUDB specific error codes */
#define TOKUDB_OUT_OF_LOCKS -100000
#define TOKUDB_SUCCEEDED_EARLY -100001
/* in wrap mode, top-level function txn_begin is renamed, but the field isn't renamed, so we have to hack it here.*/
#ifdef _TOKUDB_WRAP_H
#undef txn_begin
......
......@@ -31,6 +31,7 @@ void print_db_notices (void) {
enum {
TOKUDB_OUT_OF_LOCKS = -100000,
TOKUDB_SUCCEEDED_EARLY = -100001
};
void print_defines (void) {
......@@ -130,6 +131,7 @@ void print_defines (void) {
/* TOKUDB specific error codes*/
printf("/* TOKUDB specific error codes */\n");
dodefine(TOKUDB_OUT_OF_LOCKS);
dodefine(TOKUDB_SUCCEEDED_EARLY);
}
//#define DECL_LIMIT 100
......
......@@ -101,6 +101,7 @@ typedef enum {
#endif
/* TOKUDB specific error codes */
#define TOKUDB_OUT_OF_LOCKS -100000
#define TOKUDB_SUCCEEDED_EARLY -100001
/* in wrap mode, top-level function txn_begin is renamed, but the field isn't renamed, so we have to hack it here.*/
#ifdef _TOKUDB_WRAP_H
#undef txn_begin
......
......@@ -134,10 +134,10 @@ static inline int maybe_resize_and_rebuild(OMT omt, u_int32_t n, enum build_choi
OMT_NODE new_nodes = NULL;
OMTVALUE *tmp_values = NULL;
int r = ENOSYS;
u_int32_t new_size = 2*n;
u_int32_t new_size = n<=2 ? 4 : 2*n;
if (omt->tmparray_size<n ||
(omt->tmparray_size/4 >= n && n>=2)) {
(omt->tmparray_size/2 >= new_size)) {
/* Malloc and free instead of realloc (saves the memcpy). */
MALLOC_N(new_size, new_tmparray);
if (new_tmparray==NULL) { r = errno; goto cleanup; }
......@@ -147,7 +147,7 @@ static inline int maybe_resize_and_rebuild(OMT omt, u_int32_t n, enum build_choi
* We are increasing the number of elements and there is no free space.
* The array is too large. */
u_int32_t num_nodes = nweight(omt, omt->root);
if ((omt->node_capacity/4 >= n && n>=2) ||
if ((omt->node_capacity/2 >= new_size) ||
(omt->free_idx>=omt->node_capacity && num_nodes<n) ||
(omt->node_capacity<n)) {
if (choice==MAYBE_REBUILD) {
......@@ -173,6 +173,7 @@ static inline int maybe_resize_and_rebuild(OMT omt, u_int32_t n, enum build_choi
omt->nodes = new_nodes;
omt->node_capacity = new_size;
omt->free_idx = 0; /* Allocating from mempool starts over. */
omt->root = NODE_NULL;
if (choice==MAYBE_REBUILD) {
create_from_sorted_array_internal(omt, &omt->root, tmp_values, num_nodes);
}
......@@ -355,18 +356,25 @@ int toku_omt_fetch(OMT V, u_int32_t i, OMTVALUE *v) {
return 0;
}
static inline int iterate_internal(OMT omt, node_idx n_idx, u_int32_t idx,
static inline int iterate_internal(OMT omt, u_int32_t left, u_int32_t right,
node_idx n_idx, u_int32_t idx,
int (*f)(OMTVALUE, u_int32_t, void*), void*v) {
int r;
if (n_idx==NODE_NULL) return 0;
OMT_NODE n = omt->nodes+n_idx;
if ((r=iterate_internal(omt, n->left, idx, f, v))) return r;
if ((r=f(n->value, idx+nweight(omt, n->left), v))) return r;
return iterate_internal(omt, n->right, idx+nweight(omt, n->left)+1, f, v);
u_int32_t idx_root = idx+nweight(omt,n->left);
if (left< idx_root && (r=iterate_internal(omt, left, right, n->left, idx, f, v))) return r;
if (left<=idx_root && idx_root<right && (r=f(n->value, idx_root, v))) return r;
if (idx_root+1<right) return iterate_internal(omt, left, right, n->right, idx_root+1, f, v);
return 0;
}
int toku_omt_iterate(OMT omt, int (*f)(OMTVALUE, u_int32_t, void*), void*v) {
return iterate_internal(omt, omt->root, 0, f, v);
return iterate_internal(omt, 0, nweight(omt, omt->root), omt->root, 0, f, v);
}
int toku_omt_iterate_on_range(OMT omt, u_int32_t left, u_int32_t right, int (*f)(OMTVALUE, u_int32_t, void*), void*v) {
return iterate_internal(omt, left, right, omt->root, 0, f, v);
}
int toku_omt_insert(OMT omt, OMTVALUE value, int(*h)(OMTVALUE, void*v), void *v, u_int32_t *index) {
......@@ -511,3 +519,8 @@ int toku_omt_merge(OMT leftomt, OMT rightomt, OMT *newomtp) {
return r;
}
void toku_omt_clear(OMT omt) {
omt->free_idx = 0;
omt->root = NODE_NULL;
}
......@@ -95,6 +95,23 @@ u_int32_t toku_omt_size(OMT V);
// Requires: V != NULL
// Performance: time=O(1)
int toku_omt_iterate_on_range(OMT omt, u_int32_t left, u_int32_t right, int (*f)(OMTVALUE, u_int32_t, void*), void*v);
// Effect: Iterate over the values of the omt, from left to right, calling f on each value.
// The second argument passed to f is the index of the value.
// The third argument passed to f is v.
// The indices run from 0 (inclusive) to toku_omt_size(omt) (exclusive).
// We will iterate only over [left,right)
//
// Requires: omt != NULL
// left <= right
// Requires: f != NULL
// Returns:
// If f ever returns nonzero, then the iteration stops, and the value returned by f is returned by toku_omt_iterate.
// If f always returns zero, then toku_omt_iterate returns 0.
// Requires: Don't modify omt while running. (E.g., f may not insert or delete values form omt.)
// Performance: time=O(i+\log N) where i is the number of times f is called, and N is the number of elements in omt.
// Rational: Although the functional iterator requires defining another function (as opposed to C++ style iterator), it is much easier to read.
int toku_omt_iterate(OMT omt, int (*f)(OMTVALUE, u_int32_t, void*), void*v);
// Effect: Iterate over the values of the omt, from left to right, calling f on each value.
// The second argument passed to f is the index of the value.
......@@ -260,4 +277,10 @@ int toku_omt_merge(OMT leftomt, OMT rightomt, OMT *newomt);
// On error, nothing is modified.
// Performance: time=O(n) is acceptable, but one can imagine implementations that are O(\log n) worst-case.
void toku_omt_clear(OMT omt);
// Effect: Set the tree to be empty.
// Note: Will not resize the array, since void precludes allowing a malloc.
// Performance: time=O(1)
#endif /* #ifndef OMT_H */
......@@ -926,6 +926,24 @@ static inline void toku__lt_init_full_query(toku_lock_tree* tree, toku_interval*
toku__init_query(query, left, right);
}
typedef struct {
toku_lock_tree* lt;
toku_range_tree* rtdel;
toku_interval* query;
toku_range* store_value;
} free_contents_info;
static int free_contents_helper(toku_range* value, void* extra) {
free_contents_info* info = extra;
int r = ENOSYS;
*info->store_value = *value;
if ((r=toku__lt_free_points(info->lt, info->query, 1, info->rtdel))) {
return toku__lt_panic(info->lt, r);
}
return 0;
}
/*
TODO: Refactor.
toku__lt_free_points should be replaced (or supplanted) with a
......@@ -937,20 +955,20 @@ static inline int toku__lt_free_contents(toku_lock_tree* tree, toku_range_tree*
if (!rt) return 0;
int r;
int r2;
BOOL found = FALSE;
toku_interval query;
toku_point left;
toku_point right;
toku__lt_init_full_query(tree, &query, &left, &right);
toku_rt_start_scan(rt);
while ((r = toku_rt_next(rt, &tree->buf[0], &found)) == 0 && found) {
r = toku__lt_free_points(tree, &query, 1, rtdel);
if (r!=0) return toku__lt_panic(tree, r);
}
r2 = toku_rt_close(rt);
assert(r2 == 0);
free_contents_info info;
info.lt = tree;
info.rtdel = rtdel;
info.query = &query;
info.store_value = &tree->buf[0];
if ((r=toku_rt_iterate(rt, free_contents_helper, &info))) return r;
r = toku_rt_close(rt);
assert(r == 0);
return r;
}
......@@ -1519,8 +1537,29 @@ static int toku__lt_escalate_read_locks_in_interval(toku_lock_tree* tree,
return r;
}
typedef struct {
toku_lock_tree* lt;
toku_range_tree* border;
toku_interval* escalate_interval;
TXNID txn;
} escalate_info;
//TODO: Whenever comparing TXNIDs use the comparison function INSTEAD of just '!= or =='
static int escalate_read_locks_helper(toku_range* border_range, void* extra) {
escalate_info* info = extra;
int r = ENOSYS;
if (!toku__lt_txn_cmp(border_range->data, info->txn)) { r = 0; goto cleanup; }
info->escalate_interval->right = border_range->ends.left;
r = toku__lt_escalate_read_locks_in_interval(info->lt,
info->escalate_interval, info->txn);
if (r!=0) goto cleanup;
info->escalate_interval->left = border_range->ends.right;
r = 0;
cleanup:
return r;
}
//TODO: Whenever comparing TXNIDs use the comparison function INSTEAD of just '!= or =='
static int toku__lt_escalate_read_locks(toku_lock_tree* tree, TXNID txn) {
int r = ENOSYS;
assert(tree);
......@@ -1534,21 +1573,34 @@ static int toku__lt_escalate_read_locks(toku_lock_tree* tree, TXNID txn) {
toku_range_tree* border = tree->borderwrite;
assert(border);
toku_range border_range;
BOOL found;
toku_rt_start_scan(border);
escalate_info info;
info.lt = tree;
info.border = border;
info.escalate_interval = &query;
info.txn = txn;
if ((r = toku_rt_iterate(border, escalate_read_locks_helper, &info))) goto cleanup;
/* Special case for zero entries in border? Just do the 'after'? */
while ((r = toku_rt_next(border, &border_range, &found)) == 0 && found) {
if (!toku__lt_txn_cmp(border_range.data, txn)) { continue; }
query.right = border_range.ends.left;
r = toku__lt_escalate_read_locks_in_interval(tree, &query, txn);
if (r!=0) { goto cleanup; }
query.left = border_range.ends.right;
}
query.right = &infinite;
r = toku__lt_escalate_read_locks_in_interval(tree, &query, txn);
if (r!=0) { goto cleanup; }
goto cleanup;
if (r!=0) goto cleanup;
r = 0;
cleanup:
return r;
}
static int escalate_write_locks_helper(toku_range* border_range, void* extra) {
toku_lock_tree* tree = extra;
int r = ENOSYS;
BOOL trivial;
if ((r = toku__border_escalation_trivial(tree, border_range, &trivial))) goto cleanup;
if (!trivial) { r = 0; goto cleanup; }
/*
* At this point, we determine that escalation is simple,
* Attempt escalation
*/
r = toku__escalate_writes_from_border_range(tree, border_range);
if (r!=0) { r = toku__lt_panic(tree, r); goto cleanup; }
r = 0;
cleanup:
return r;
}
......@@ -1562,25 +1614,9 @@ static int toku__lt_escalate_read_locks(toku_lock_tree* tree, TXNID txn) {
static int toku__lt_escalate_write_locks(toku_lock_tree* tree) {
int r = ENOSYS;
assert(tree);
assert(tree->lock_escalation_allowed);
toku_range_tree* border = tree->borderwrite;
assert(border);
toku_range border_range;
BOOL found = FALSE;
BOOL trivial = FALSE;
assert(tree->borderwrite);
toku_rt_start_scan(border);
while ((r = toku_rt_next(border, &border_range, &found)) == 0 && found) {
r = toku__border_escalation_trivial(tree, &border_range, &trivial);
if (r!=0) { goto cleanup; }
if (!trivial) { continue; }
/*
* At this point, we determine that escalation is simple,
* Attempt escalation
*/
r = toku__escalate_writes_from_border_range(tree, &border_range);
if (r!=0) { r = toku__lt_panic(tree, r); goto cleanup; }
}
if ((r = toku_rt_iterate(tree->borderwrite, escalate_write_locks_helper, tree))) goto cleanup;
r = 0;
cleanup:
return r;
......
......@@ -103,7 +103,7 @@ NEWBRT_BINS = ../../../newbrt/newbrt.o
RT_LINEAR_BINS = ../../range_tree/linear.o
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
RT_LOG_BINS = ../../range_tree/log.o
LT_BINS = ../lth.o ../rth.o ../idlth.o ../db_id.o
......
......@@ -24,7 +24,7 @@ ifneq ($(OSX),)
CFLAGS+=-fno-common
endif
BINS = linear.o log_nooverlap.o tokuredblack.o rangetree.o #log.o
BINS = linear.o log_nooverlap.o rangetree.o #log.o
build: $(BINS)
cd tests;$(MAKE) build
......@@ -50,4 +50,3 @@ log.o: log.c $(HEADERS)
log_nooverlap.o: log_nooverlap.c $(HEADERS)
tokuredblack.o: tokuredblack.c $(HEADERS) tokuredblack.h
......@@ -21,21 +21,12 @@ struct __toku_range_tree_local {
//Linear version only fields:
toku_range* ranges;
u_int32_t ranges_len;
/*
* BOOL that says whether we are allowed to iterate.
*/
BOOL iter_is_valid;
u_int32_t iter_index;
};
#include <rangetree-internal.h>
static const u_int32_t minlen = 64;
static inline void toku_rt_invalidate_iteration(toku_range_tree* tree) {
tree->i.iter_is_valid = FALSE;
}
static inline int toku__rt_decrease_capacity(toku_range_tree* tree,
u_int32_t _num) {
//TODO: SOME ATTRIBUTE TO REMOVE NEVER EXECUTABLE ERROR: assert(tree);
......@@ -135,7 +126,6 @@ int toku_rt_create(toku_range_tree** ptree,
user_malloc(tmptree->i.ranges_len * sizeof(toku_range));
if (!tmptree->i.ranges) { r = errno; goto died1; }
toku_rt_invalidate_iteration(tmptree);
*ptree = tmptree;
return 0;
......@@ -144,7 +134,6 @@ int toku_rt_create(toku_range_tree** ptree,
void toku_rt_clear(toku_range_tree* tree) {
assert(tree);
toku__rt_decrease_capacity(tree, 0);
toku_rt_invalidate_iteration(tree);
tree->numelements = 0;
}
......@@ -207,7 +196,6 @@ int toku_rt_insert(toku_range_tree* tree, toku_range* range) {
tree->i.ranges[move] = tree->i.ranges[move - 1];
}
tree->i.ranges[i] = *range;
toku_rt_invalidate_iteration(tree);
return 0;
}
......@@ -227,7 +215,6 @@ int toku_rt_delete(toku_range_tree* tree, toku_range* range) {
tree->i.ranges[move] = tree->i.ranges[move + 1];
}
toku__rt_decrease_capacity(tree, --tree->numelements);
toku_rt_invalidate_iteration(tree);
return 0;
}
......@@ -279,27 +266,15 @@ int toku_rt_get_size(toku_range_tree* tree, u_int32_t* size) {
return 0;
}
void toku_rt_start_scan (toku_range_tree* range_tree) {
assert(range_tree);
range_tree->i.iter_is_valid = TRUE;
range_tree->i.iter_index = 0;
return;
}
int toku_rt_iterate(toku_range_tree* tree, int (*f)(toku_range*,void*), void* extra) {
u_int32_t index;
int toku_rt_next (toku_range_tree* range_tree, toku_range* out_range, BOOL* elem_found) {
int r = ENOSYS;
if (!range_tree || !out_range || !elem_found) { r = EINVAL; goto cleanup; }
/* Check to see if range tree is in invalid iteration state */
if (!range_tree->i.iter_is_valid) { r = EDOM; goto cleanup; }
*elem_found = range_tree->i.iter_index < range_tree->numelements;
range_tree->i.iter_is_valid = range_tree->i.iter_index < range_tree->numelements;
if (*elem_found) { *out_range = range_tree->i.ranges[range_tree->i.iter_index]; }
range_tree->i.iter_index++;
for (index = 0; index < tree->numelements; index++) {
if ((r = f(&tree->i.ranges[index], extra))) goto cleanup;
}
r = 0;
cleanup:
if (range_tree && r!=0) { toku_rt_invalidate_iteration(range_tree); }
return r;
}
This diff is collapsed.
......@@ -234,8 +234,6 @@ int toku_rt_successor(toku_range_tree* tree, toku_point* point,
*/
int toku_rt_get_size(toku_range_tree* tree, u_int32_t* size);
void toku_rt_start_scan (toku_range_tree* range_tree);
int toku_rt_next (toku_range_tree* range_tree, toku_range* out_range, BOOL* elem_found);
int toku_rt_iterate(toku_range_tree* tree, int (*f)(toku_range*,void*), void* extra);
#endif /* #if !defined(TOKU_RANGE_TREE_H) */
......@@ -15,7 +15,7 @@ OPTFLAGS=-O0
# GCOV_FLAGS = -fprofile-arcs -ftest-coverage
CFLAGS = -W -Wall -Wextra -Werror $(OPTFLAGS) -g3 -ggdb3 $(GCOV_FLAGS)
CFLAGS += -Wbad-function-cast -Wcast-align -Wconversion -Waggregate-return
CFLAGS += -Wmissing-noreturn -Wmissing-format-attribute
CFLAGS += -Wmissing-noreturn -Wmissing-format-attribute -lz
CPPFLAGS += -I../ -I../../../newbrt -I../../../include
......@@ -87,11 +87,14 @@ endif
%.tlogrun: %.tlog
$(MAYBEATSIGN) $(VGRIND) ./$< $(VERBVERBOSE)
LINEAR_BINS = ../linear.o
TLOG_BINS = ../log_nooverlap.o ../tokuredblack.o
LOG_BINS = ../log.o
LINEAR_BINS = ../linear.o ../../../newbrt/newbrt.o
TLOG_BINS = ../log_nooverlap.o ../../../newbrt/newbrt.o
LOG_BINS = ../log.o ../../../newbrt/newbrt.o
HEADERS=../rangetree.h ../rangetree-internal.h test.h
../../../newbrt/newbrt.o:
cd ../../../newbrt && make
%.lin: %.c $(HEADERS) $(LINEAR_BINS)
$(CC) -DDIR=\"dir.$<.lin\" $(CFLAGS) $(CPPFLAGS) $< -o $@ $(LINEAR_BINS)
%.tlog: %.c $(HEADERS) $(TLOG_BINS)
......
......@@ -5,6 +5,7 @@
#include <assert.h>
#include <rangetree.h>
#include <errno.h>
#include "../../../newbrt/memory.h"
int verbose=0;
#define CKERR(r) ({ if (r!=0) fprintf(stderr, "%s:%d error %d %s\n", __FILE__, __LINE__, r, strerror(r)); assert(r==0); })
......@@ -61,18 +62,6 @@ int char_cmp(const TXNID a, const TXNID b) {
return x -y;
}
void* toku_malloc(size_t size) {
return malloc(size);
}
void toku_free(void* p) {
free(p);
}
void* toku_realloc(void *ptr, size_t size) {
return realloc(ptr, size);
}
int mallocced = 0;
int failon = -1;
......
......@@ -33,7 +33,7 @@ int main(int argc, const char *argv[]) {
if (allow_overlaps) continue;
#endif
int i;
for (i = 1; i <= 2; i++) {
for (i = 1; i <= 1; i++) {
mallocced = 0;
failon = i;
r = toku_rt_create(&tree, int_cmp, char_cmp, allow_overlaps,
......
......@@ -64,13 +64,6 @@ void RunTest (BOOL f_overlaps_allowed) {
realloc);
CKERR2(r, ENOMEM);
/* Failure when allocating the tree ranges */
malloc_cnt = 0;
malloc_cntl = 2;
r = toku_rt_create(&tree, int_cmp, char_cmp, f_overlaps_allowed, malloc_fail, free,
realloc);
CKERR2(r, ENOMEM);
}
int main(int argc, const char *argv[]) {
......
This diff is collapsed.
/*
Redblack balanced tree algorithm
Copyright (C) Damian Ivereigh 2000
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See the file COPYING for details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef TOKU_REDBLACK_H
#define TOKU_REDBLACK_H
#include <rangetree.h>
#define RB_INLINE
/* Modes for rblookup */
typedef enum {
RB_NONE = -1, /* None of those below */
RB_LUEQUAL = 0, /* Only exact match */
RB_LUGTEQ = 1, /* Exact match or greater */
RB_LULTEQ = 2, /* Exact match or less */
RB_LULESS = 3, /* Less than key (not equal to) */
RB_LUGREAT = 4, /* Greater than key (not equal to) */
RB_LUNEXT = 5, /* Next key after current */
RB_LUPREV = 6, /* Prev key before current */
RB_LUFIRST = 7, /* First key in index */
RB_LULAST = 8 /* Last key in index */
} toku_rbt_look_mode;
struct toku_rbt_lists {
const struct toku_rbt_node *rootp;
const struct toku_rbt_node *nextp;
};
struct toku_rbt_tree {
int (*rb_cmp)(const toku_point*, const toku_point*);
struct toku_rbt_node *rb_root;
void* (*rb_malloc) (size_t);
void (*rb_free) (void*);
void* (*rb_realloc)(void*, size_t);
};
int toku_rbt_init (
int (*cmp)(const toku_point*, const toku_point*),
struct toku_rbt_tree** ptree,
void* (*user_malloc) (size_t),
void (*user_free) (void*),
void* (*user_realloc)(void*, size_t)
);
/* Sets *pdata to NULL if not found. (unless error) */
int toku_rbt_lookup(
int mode,
const toku_interval* key,
struct toku_rbt_tree* rbinfo,
struct toku_rbt_node** pinsert_finger,
struct toku_rbt_node** pelement_finger,
toku_range** pdata
);
int toku_rbt_finger_insert(
const toku_range* key,
struct toku_rbt_tree* rbinfo,
struct toku_rbt_node* parent
);
int toku_rbt_finger_delete(struct toku_rbt_node* node, struct toku_rbt_tree *rbinfo);
int toku_rbt_finger_predecessor(struct toku_rbt_node** pfinger, toku_range** ppred_data);
int toku_rbt_finger_successor(struct toku_rbt_node** pfinger, toku_range** psucc_data);
void toku_rbt_destroy(struct toku_rbt_tree *);
void toku_rbt_clear(struct toku_rbt_tree *);
enum nodecolour { BLACK, RED };
struct toku_rbt_node
{
struct toku_rbt_node *left; /* Left down */
struct toku_rbt_node *right; /* Right down */
struct toku_rbt_node *up; /* Up */
enum nodecolour colour; /* Node colour */
#ifdef RB_INLINE
toku_range key; /* User's key (and data) */
#define RB_GET(x,y) &x->y
#define RB_SET(x,y,v) x->y = *(v)
#else
const toku_range *key; /* Pointer to user's key (and data) */
#define RB_GET(x,y) x->y
#define RB_SET(x,y,v) x->y = v
#endif /* RB_INLINE */
};
#endif /* TOKU_REDBLACK_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