Commit becb7c5b authored by Yoni Fogel's avatar Yoni Fogel

Addresses #479

Implementation of range tree wrapper for red black tree.

git-svn-id: file:///svn/tokudb@2706 c7de825b-a66e-492c-adef-691d508d4ae1
parent c4a1dd67
......@@ -83,11 +83,11 @@ static inline DBT* toku__recreate_DBT(DBT* dbt, void* payload, u_int32_t length)
return dbt;
}
static inline int toku__lt_txn_cmp(DB_TXN* a, DB_TXN* b) {
static inline int toku__lt_txn_cmp(const DB_TXN* a, const DB_TXN* b) {
return a < b ? -1 : (a != b);
}
int toku__lt_point_cmp(toku_point* x, toku_point* y) {
int toku__lt_point_cmp(const toku_point* x, const toku_point* y) {
int partial_result;
DBT point_1;
DBT point_2;
......
......@@ -82,8 +82,8 @@ static inline BOOL toku__rt_exact(toku_range_tree* tree,
}
int toku_rt_create(toku_range_tree** ptree,
int (*end_cmp)(toku_point*,toku_point*),
int (*data_cmp)(DB_TXN*,DB_TXN*),
int (*end_cmp)(const toku_point*,const toku_point*),
int (*data_cmp)(const DB_TXN*,const DB_TXN*),
BOOL allow_overlaps,
void* (*user_malloc) (size_t),
void (*user_free) (void*),
......
......@@ -16,14 +16,15 @@
#include <errno.h>
#include <assert.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <tokuredblack.h>
struct __toku_range_tree_local {
//Logarithmic non-overlapping version only fields:
toku_rbt* rbt;
struct toku_rbt_tree* rbt;
};
#include <rangetree-internal.h>
#include <tokuredblack.h>
/*
Redblack tree.
......@@ -34,224 +35,295 @@ lookup (type) returns:
'insertpointer' (to be used in finger_insert)
Finger usefulness:
1- Insert
O(lg N) CMPs We do a lookup(<=) (out elementpointer, out found, out insertpointer)
If found
If overlaps (found.right >= query.left) return error
Do a finger_successor(elementpointer) (out found2)
(0+1) CMPs if (found2 and overlaps (found2.left <= query.right) return error
else
Do a lookup(First) (out found2)
if (found2 and overlaps (found2.left <= query.right) return error
(0) CMPs Do a finger_insert(data, insertpointer)
2- Delete
O(lg N) CMPs We do a lookup (==). (out found, out elementpointer)
If !found return error.
(== already checks for left end point)
Data cmp is free (pointer)
(0+1) CMPs if (found.right != to_insert.data || found.data != to_delete.data), return error.
(0) CMPs Do a finger_delete(element_pointer)
3- Predecessor:
O(lg N) CMPs Do a lookup(<) (out found, out elementpointer)
If !found return "not found"
(0+1) CMPs If overlaps (found.right >= query)
(0) CMPs do a finger_predecessor(elementpointer) (out found2)
If found2 return found2.
else return "not found"
else return found.
4- Successor:
O(lg N) CMPs Do a lookup (>) (out found)
If found, return found.
return "not found."
5- FindOverlaps
O(lg N+1) CMPs Do a lookup (<=) (out found, out elementpointer)
If found
(0+1) CMPs if overlap (if found.right >= query.left)
Increaes buffer
add found to buffer
(0) CMPs do a finger_successor(elementpointer) (out found, out elementpointer)
else
do a lookup (FIRST) (out found, out elementpointer)
O(min(k,K))CMPs while (found && found.left <= query.right
Increaes buffer
add found to buffer
(0) CMPs do a finger_successor(elementpointer) (out found, out elementpointer)
*/
static inline BOOL toku__rt_overlap(toku_range_tree* tree,
toku_range* a, toku_range* b) {
assert(tree);
assert(a);
assert(b);
//a->left <= b->right && b->left <= a->right
return (tree->end_cmp(a->left, b->right) <= 0 &&
tree->end_cmp(b->left, a->right) <= 0);
}
static inline BOOL toku__rt_exact(toku_range_tree* tree,
toku_range* a, toku_range* b) {
assert(tree);
assert(a);
assert(b);
return (tree->end_cmp (a->left, b->left) == 0 &&
tree->end_cmp (a->right, b->right) == 0 &&
tree->data_cmp(a->data, b->data) == 0);
}
//FIRST PASS
int toku_rt_create(toku_range_tree** ptree,
int (*end_cmp)(toku_point*,toku_point*),
int (*data_cmp)(DB_TXN*,DB_TXN*),
int (*end_cmp)(const toku_point*,const toku_point*),
int (*data_cmp)(const DB_TXN*,const DB_TXN*),
BOOL allow_overlaps,
void* (*user_malloc) (size_t),
void (*user_free) (void*),
void* (*user_realloc)(void*, size_t)) {
int r;
toku_range_tree* tmptree;
int r = ENOSYS;
toku_range_tree* temptree = NULL;
if (allow_overlaps) return ENOSYS;
r = toku_rt_super_create(ptree, &tmptree, end_cmp, data_cmp, allow_overlaps,
if (allow_overlaps) return EINVAL;
r = toku_rt_super_create(ptree, &temptree, end_cmp, data_cmp, allow_overlaps,
user_malloc, user_free, user_realloc);
if (0) {
died1:
user_free(temptree);
return r;
}
if (r!=0) return r;
if (r!=0) { goto cleanup; }
//Any local initializers go here.
tmptree->rbt = toku_rbt_init(void);
if (!tmptree->rbt) { r = errno; goto died1; }
*ptree = tmptree;
r = toku_rbt_init(end_cmp, &temptree->i.rbt, user_malloc, user_free, user_realloc);
if (r!=0) { goto cleanup; }
return 0;
*ptree = temptree;
r = 0;
cleanup:
if (r!=0) {
if (temptree) user_free(temptree);
}
return r;
}
//FIRST PASS
int toku_rt_close(toku_range_tree* tree) {
if (!tree) return EINVAL;
toku_rbt_destroy(tree->rbt);
if (!tree) { return EINVAL; }
toku_rbt_destroy(tree->i.rbt);
tree->free(tree);
return 0;
}
/*
5- FindOverlaps
O(lg N+1) CMPs Do a lookup (<=) (out found, out elementpointer)
If found
(0+1) CMPs if overlap (if found.right >= query.left)
Increaes buffer
add found to buffer
(0) CMPs do a finger_successor(elementpointer) (out found, out elementpointer)
else
do a lookup (FIRST) (out found, out elementpointer)
O(min(k,K))CMPs while (found && found.left <= query.right
Increaes buffer
add found to buffer
(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,
toku_range** buf, u_int32_t* buflen, u_int32_t* numfound) {
/* TODO: RED BLACK TREE does not support partial scan.
*/
if (!tree || !query || !buf || !buflen || !numfound) return EINVAL;
if (query->data != NULL) return EINVAL;
if (*buflen == 0) return EINVAL;
int r = ENOSYS;
if (!tree || !query || !buf || !buflen || !numfound ||
query->data != NULL || *buflen == 0) {
r = EINVAL; goto cleanup;
}
assert(!tree->allow_overlaps);
u_int32_t temp_numfound = 0;
int r;
u_int32_t i;
for (i = 0; i < tree->numelements; i++) {
if (toku__rt_overlap(tree, query, &tree->ranges[i])) {
struct toku_rbt_node* ignore_insert = NULL;
struct toku_rbt_node* succ_finger = NULL;
toku_range* data = NULL;
u_int32_t temp_numfound = 0;
/* k = 0 means return ALL. (infinity) */
if (k == 0) { k = UINT32_MAX; }
r = toku_rbt_lookup(RB_LULTEQ, query, tree->i.rbt, &ignore_insert, &succ_finger, &data);
if (r!=0) { goto cleanup; }
if (data != NULL) {
if (tree->end_cmp(data->right, query->left) >= 0) {
r = toku__rt_increase_buffer(tree, buf, buflen, temp_numfound + 1);
if (r != 0) return r;
(*buf)[temp_numfound++] = tree->ranges[i];
//k == 0 means limit of infinity, this is not a bug.
if (temp_numfound == k) break;
if (r!=0) { goto cleanup; }
(*buf)[temp_numfound++] = *data;
}
if (temp_numfound < k) {
r = toku_rbt_finger_successor(&succ_finger, &data);
if (r!=0) { goto cleanup; }
}
}
else {
r = toku_rbt_lookup(RB_LUFIRST, query, tree->i.rbt, &ignore_insert, &succ_finger, &data);
if (r!=0) { goto cleanup; }
}
while (temp_numfound < k && data != NULL) {
if (tree->end_cmp(data->left, query->right) > 0) { break; }
r = toku__rt_increase_buffer(tree, buf, buflen, temp_numfound + 1);
if (r!=0) { goto cleanup; }
(*buf)[temp_numfound++] = *data;
r = toku_rbt_finger_successor(&succ_finger, &data);
if (r!=0) { goto cleanup; }
}
*numfound = temp_numfound;
return 0;
r = 0;
cleanup:
return r;
}
/*
1- Insert
O(lg N) CMPs We do a lookup(<=) (out elementpointer, out found, out insertpointer)
If found
If overlaps (found.right >= query.left) return error
Do a finger_successor(elementpointer) (out found2)
(0+1) CMPs if (found2 and overlaps (found2.left <= query.right) return error
else
Do a lookup(First) (out found2)
if (found2 and overlaps (found2.left <= query.right) return error
(0) CMPs Do a finger_insert(data, insertpointer)
*/
int toku_rt_insert(toku_range_tree* tree, toku_range* range) {
/* TODO: */
if (!tree || !range) return EINVAL;
int r = ENOSYS;
if (!tree || !range) { r = EINVAL; goto cleanup; }
assert(!tree->allow_overlaps);
u_int32_t i;
int r;
struct toku_rbt_node* insert_finger = NULL;
struct toku_rbt_node* ignore_insert = NULL;
struct toku_rbt_node* succ_finger = NULL;
toku_range* data = NULL;
//EDOM cases
if (tree->allow_overlaps) {
for (i = 0; i < tree->numelements; i++) {
if (toku__rt_exact (tree, range, &tree->ranges[i])) return EDOM;
r = toku_rbt_lookup(RB_LULTEQ, range, tree->i.rbt, &insert_finger, &succ_finger, &data);
if (r!=0) { goto cleanup; }
if (data != NULL) {
if (tree->end_cmp(data->right, range->left) >= 0) {
r = EDOM; goto cleanup;
}
r = toku_rbt_finger_successor(&succ_finger, &data);
if (r!=0) { goto cleanup; }
}
else {
for (i = 0; i < tree->numelements; i++) {
if (toku__rt_overlap(tree, range, &tree->ranges[i])) return EDOM;
}
r = toku_rbt_lookup(RB_LUFIRST, range, tree->i.rbt, &ignore_insert, &succ_finger, &data);
if (r!=0) { goto cleanup; }
}
r = toku__rt_increase_capacity(tree, tree->numelements + 1);
if (r != 0) return r;
tree->ranges[tree->numelements++] = *range;
return 0;
if (data != NULL && tree->end_cmp(data->left, range->right) <= 0) {
r = EDOM; goto cleanup;
}
r = toku_rbt_finger_insert(range, tree->i.rbt, insert_finger);
if (r!=0) { goto cleanup; }
r = 0;
tree->numelements++;
cleanup:
return r;
}
/*
2- Delete
O(lg N) CMPs We do a lookup (==). (out found, out elementpointer)
If !found return error.
(== already checks for left end point)
Data cmp is free (pointer)
(0+1) CMPs if (found.right != to_insert.right || found.data != to_delete.data), return error.
(0) CMPs Do a finger_delete(element_pointer)
*/
int toku_rt_delete(toku_range_tree* tree, toku_range* range) {
/* TODO: */
if (!tree || !range) return EINVAL;
u_int32_t i;
int r = ENOSYS;
if (!tree || !range) { r = EINVAL; goto cleanup; }
assert(!tree->allow_overlaps);
for (i = 0;
i < tree->numelements &&
!toku__rt_exact(tree, range, &(tree->ranges[i]));
i++) {}
//EDOM case: Not Found
if (i == tree->numelements) return EDOM;
if (i < tree->numelements - 1) {
tree->ranges[i] = tree->ranges[tree->numelements - 1];
struct toku_rbt_node* ignore_insert = NULL;
struct toku_rbt_node* delete_finger = NULL;
toku_range* data = NULL;
r = toku_rbt_lookup(RB_LUEQUAL, range, tree->i.rbt,
&ignore_insert, &delete_finger, &data);
if (r!=0) { goto cleanup; }
if (!data ||
tree->data_cmp(data->data, range->data) != 0 ||
tree->end_cmp(data->right, range->right) != 0) {
r = EDOM; goto cleanup;
}
toku__rt_decrease_capacity(tree, --tree->numelements);
return 0;
r = toku_rbt_finger_delete(delete_finger, tree->i.rbt);
if (r!=0) { goto cleanup; }
r = 0;
tree->numelements--;
cleanup:
return r;
}
/*
3- Predecessor:
O(lg N) CMPs Do a lookup(<) (out found, out elementpointer)
If !found return "not found"
(0+1) CMPs If overlaps (found.right >= query)
(0) CMPs do a finger_predecessor(elementpointer) (out found2)
If found2 return found2.
else return "not found"
else return found.
*/
int toku_rt_predecessor (toku_range_tree* tree, toku_point* point,
toku_range* pred, BOOL* wasfound) {
/* TODO: */
if (!tree || !point || !pred || !wasfound) return EINVAL;
if (tree->allow_overlaps) return EINVAL;
toku_range* best = NULL;
u_int32_t i;
for (i = 0; i < tree->numelements; i++) {
if (toku__rt_p_cmp(tree, point, &tree->ranges[i]) > 0 &&
(!best || tree->end_cmp(best->left, tree->ranges[i].left) < 0)) {
best = &tree->ranges[i];
}
int r = ENOSYS;
if (!tree || !point || !pred || !wasfound || tree->allow_overlaps) {
r = EINVAL; goto cleanup;
}
*wasfound = best != NULL;
if (best) *pred = *best;
return 0;
}
struct toku_rbt_node* ignore_insert = NULL;
struct toku_rbt_node* pred_finger = NULL;
toku_range* data = NULL;
toku_range range;
range.left = point;
range.right = point;
range.data = NULL;
r = toku_rbt_lookup(RB_LULESS, &range, tree->i.rbt, &ignore_insert, &pred_finger, &data);
if (r!=0) { goto cleanup; }
if (!data) {
*wasfound = FALSE;
r = 0;
goto cleanup;
}
if (tree->end_cmp(data->right, point) < 0) {
*wasfound = TRUE;
*pred = *data;
r = 0;
goto cleanup;
}
r = toku_rbt_finger_predecessor(&pred_finger, &data);
if (r!=0) { goto cleanup; }
if (!data) {
*wasfound = FALSE;
r = 0;
goto cleanup;
}
*wasfound = TRUE;
*pred = *data;
r = 0;
cleanup:
return r;
}
/*
4- Successor:
O(lg N) CMPs Do a lookup (>) (out found)
If found, return found.
return "not found."
*/
int toku_rt_successor (toku_range_tree* tree, toku_point* point,
toku_range* succ, BOOL* wasfound) {
/* TODO: */
if (!tree || !point || !succ || !wasfound) return EINVAL;
if (tree->allow_overlaps) return EINVAL;
toku_range* best = NULL;
u_int32_t i;
for (i = 0; i < tree->numelements; i++) {
if (toku__rt_p_cmp(tree, point, &tree->ranges[i]) < 0 &&
(!best || tree->end_cmp(best->left, tree->ranges[i].left) > 0)) {
best = &tree->ranges[i];
}
int r = ENOSYS;
if (!tree || !point || !succ || !wasfound || tree->allow_overlaps) {
r = EINVAL; goto cleanup;
}
*wasfound = best != NULL;
if (best) *succ = *best;
return 0;
struct toku_rbt_node* ignore_insert = NULL;
struct toku_rbt_node* succ_finger = NULL;
toku_range* data = NULL;
toku_range range;
range.left = point;
range.right = point;
range.data = NULL;
r = toku_rbt_lookup(RB_LUGREAT, &range, tree->i.rbt, &ignore_insert, &succ_finger, &data);
if (r!=0) { goto cleanup; }
if (!data) {
*wasfound = FALSE;
r = 0;
goto cleanup;
}
*wasfound = TRUE;
*succ = *data;
r = 0;
cleanup:
return r;
}
int toku_rt_get_allow_overlaps(toku_range_tree* tree, BOOL* allowed) {
if (!tree || !allowed) return EINVAL;
if (!tree || !allowed) return EINVAL;
assert(!tree->allow_overlaps);
*allowed = tree->allow_overlaps;
return 0;
}
int toku_rt_get_size(toku_range_tree* tree, u_int32_t* size) {
/* TODO: */
if (!tree || !size) return EINVAL;
if (!tree || !size) return EINVAL;
*size = tree->numelements;
return 0;
}
......@@ -20,10 +20,10 @@ struct __toku_range_tree {
//Shared fields:
/** A comparison function, as in bsearch(3), to compare the end-points of
a range. It is assumed to be commutative. */
int (*end_cmp)(toku_point*,toku_point*);
int (*end_cmp)(const toku_point*,const toku_point*);
/** A comparison function, as in bsearch(3), to compare the data associated
with a range */
int (*data_cmp)(DB_TXN*,DB_TXN*);
int (*data_cmp)(const DB_TXN*,const DB_TXN*);
/** Whether this tree allows ranges to overlap */
BOOL allow_overlaps;
/** The number of ranges in the range tree */
......@@ -69,8 +69,8 @@ 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,
toku_range_tree** ptree,
int (*end_cmp)(toku_point*,toku_point*),
int (*data_cmp)(DB_TXN*,DB_TXN*),
int (*end_cmp)(const toku_point*,const toku_point*),
int (*data_cmp)(const DB_TXN*,const DB_TXN*),
BOOL allow_overlaps,
void* (*user_malloc) (size_t),
void (*user_free) (void*),
......
......@@ -79,12 +79,13 @@ int toku_rt_get_allow_overlaps(toku_range_tree* tree, BOOL* allowed);
\return
- 0: Success.
- EINVAL: If any pointer argument is NULL.
- ENOSYS: If allow_overlaps = TRUE and the implementation does
- EINVAL: If allow_overlaps = TRUE and the implementation does
not support overlaps.
- Other exit codes may be forwarded from underlying system calls. */
int toku_rt_create(toku_range_tree** ptree,
int (*end_cmp)(toku_point*,toku_point*),
int (*data_cmp)(DB_TXN*,DB_TXN*), BOOL allow_overlaps,
int (*end_cmp)(const toku_point*,const toku_point*),
int (*data_cmp)(const DB_TXN*,const DB_TXN*),
BOOL allow_overlaps,
void* (*user_malloc) (size_t),
void (*user_free) (void*),
void* (*user_realloc)(void*, size_t));
......
......@@ -28,7 +28,7 @@ LIN_TESTS = $(patsubst %.c,%.lin,$(SRCS))
ALL_TESTS = $(LIN_TESTS) $(LOG_TESTS) $(TLOG_TESTS)
RUN_LOG_TESTS = $(patsubst %.log,%.logrun,$(LOG_TESTS))
RUN_TLOG_TESTS = $(patsubst %.log,%.logrun,$(TLOG_TESTS))
RUN_TLOG_TESTS = $(patsubst %.tlog,%.tlogrun,$(TLOG_TESTS))
RUN_LIN_TESTS = $(patsubst %.lin,%.linrun,$(LIN_TESTS))
RUN_ALL_TESTS = $(RUN_LIN_TESTS) $(RUN_TLOG_TESTS) $(RUN_LOG_TESTS)
......@@ -85,7 +85,7 @@ endif
$(MAYBEATSIGN) $(VGRIND) ./$< $(VERBVERBOSE)
LINEAR_BINS = ../linear.o
TLOG_BINS = ../log_nooverlap.o
TLOG_BINS = ../log_nooverlap.o ../tokuredblack.o
LOG_BINS = ../log.o
HEADERS=../rangetree.h ../rangetree-internal.h test.h
......
......@@ -40,22 +40,22 @@ static inline uint32_t myrandom (void) {
}
int dummy_cmp(toku_point *a __attribute__((__unused__)),
toku_point *b __attribute__((__unused__))) {
int dummy_cmp(const toku_point *a __attribute__((__unused__)),
const toku_point *b __attribute__((__unused__))) {
return 0;
}
int ptr_cmp(DB_TXN* a, DB_TXN* b) {
int ptr_cmp(const DB_TXN* a, const DB_TXN* b) {
return a < b ? -1 : (a != b); /* \marginpar{!?} */
}
int int_cmp(toku_point* a, toku_point*b) {
int int_cmp(const toku_point* a, const toku_point*b) {
int x = *(int*)a;
int y = *(int*)b;
return x -y;
}
int char_cmp(DB_TXN *a, DB_TXN *b) {
int char_cmp(const DB_TXN *a, const DB_TXN *b) {
int x = *(char*)a;
int y = *(char*)b;
return x -y;
......
......@@ -88,7 +88,7 @@ static void toku_rbt__delete_fix(struct toku_rbt_node **, struct toku_rbt_node *
* Returns a pointer to the top of the tree.
*/
int toku_rbt_init (
int (*cmp)(const toku_range*, const toku_range*),
int (*cmp)(const toku_point*, const toku_point*),
struct toku_rbt_tree** ptree,
void* (*user_malloc) (size_t),
void (*user_free) (void*),
......@@ -108,7 +108,8 @@ int toku_rbt_init (
/* Key is initialized since the toku_rbt__null is static. */
}
if (!ptree) { r = EINVAL; goto cleanup; }
if (!cmp || !ptree || !user_malloc || !user_free || !user_realloc) {
r = EINVAL; goto cleanup; }
temptree=(struct toku_rbt_tree *) user_malloc(sizeof(struct toku_rbt_tree));
if (!temptree) { r = ENOMEM; goto cleanup; }
......@@ -153,7 +154,7 @@ int toku_rbt_lookup(
struct toku_rbt_tree* rbinfo,
struct toku_rbt_node** pinsert_finger,
struct toku_rbt_node** pelement_finger,
const toku_range** pdata
toku_range** pdata
)
{
int r = ENOSYS;
......@@ -193,7 +194,7 @@ toku_rbt__traverse(int insert, const toku_range *key, struct toku_rbt_tree *rbin
{
y=x;
/* printf("key=%s, RB_GET(x, key)=%s\n", key, RB_GET(x, key)); */
cmp=rbinfo->rb_cmp(key, RB_GET(x, key));
cmp=rbinfo->rb_cmp(key->left, x->key.left);
if (cmp<0)
x=x->left;
......@@ -211,8 +212,8 @@ toku_rbt__traverse(int insert, const toku_range *key, struct toku_rbt_tree *rbin
static struct toku_rbt_node* toku_rbt__insert(
const toku_range* key,
struct toku_rbt_tree* rbinfo,
struct toku_rbt_node* parent
struct toku_rbt_tree* rbinfo,
struct toku_rbt_node* parent
) {
struct toku_rbt_node* x;
struct toku_rbt_node* y = parent;
......@@ -239,7 +240,7 @@ static struct toku_rbt_node* toku_rbt__insert(
}
else
{
cmp=rbinfo->rb_cmp(RB_GET(z, key), RB_GET(y, key));
cmp=rbinfo->rb_cmp(z->key.left, y->key.left);
if (cmp<0)
y->left=z;
else
......@@ -375,7 +376,7 @@ toku_rbt__lookup(int mode, const toku_range *key, struct toku_rbt_tree *rbinfo,
{
y=x;
/* printf("key=%s, RB_GET(x, key)=%s\n", key, RB_GET(x, key)); */
cmp=rbinfo->rb_cmp(key, RB_GET(x, key));
cmp=rbinfo->rb_cmp(key->left, x->key.left);
if (cmp<0)
......@@ -602,41 +603,42 @@ toku_rbt__predecessor(const struct toku_rbt_node *x)
return(y);
}
int toku_rbt_finger_predecessor(const struct toku_rbt_node** pfinger,
const toku_range** ppred_data) {
int toku_rbt_finger_predecessor(struct toku_rbt_node** pfinger,
toku_range** ppred_data) {
int r = ENOSYS;
if (!pfinger || !*pfinger ||
*pfinger == RBNULL || !ppred_data) { r = EINVAL; goto cleanup; }
*pfinger = toku_rbt__predecessor(*pfinger);
*ppred_data = ((*pfinger==RBNULL) ? NULL : RB_GET((*pfinger), key));
*ppred_data = (toku_range*)
((*pfinger==RBNULL) ? NULL : RB_GET((*pfinger), key));
r = 0;
cleanup:
return r;
}
int toku_rbt_finger_succecessor(const struct toku_rbt_node** pfinger,
const toku_range** psucc_data) {
int toku_rbt_finger_successor(struct toku_rbt_node** pfinger,
toku_range** psucc_data) {
int r = ENOSYS;
if (!pfinger || !*pfinger ||
*pfinger == RBNULL || !psucc_data) { r = EINVAL; goto cleanup; }
*pfinger = toku_rbt__successor(*pfinger);
*psucc_data = ((*pfinger==RBNULL) ? NULL : RB_GET((*pfinger), key));
*psucc_data = (toku_range*)
((*pfinger==RBNULL) ? NULL : RB_GET((*pfinger), key));
r = 0;
cleanup:
return r;
}
const toku_range* toku_rbt_finger_insert(
int toku_rbt_finger_insert(
const toku_range* key,
struct toku_rbt_tree* rbinfo,
struct toku_rbt_node* parent
struct toku_rbt_tree* rbinfo,
struct toku_rbt_node* parent
) {
struct toku_rbt_node* x;
if (!parent) return NULL;
x = toku_rbt__insert(key, rbinfo, parent);
return ((x==RBNULL) ? NULL : RB_GET(x, key));
if (!key || !rbinfo || !parent) return EINVAL;
toku_rbt__insert(key, rbinfo, parent);
return 0;
}
/* Delete the node z, and free up the space
......
......@@ -21,7 +21,6 @@
#define TOKU_REDBLACK_H
#include <rangetree.h>
#define toku_range toku_range
#define RB_INLINE
/* Modes for rblookup */
......@@ -44,7 +43,7 @@ const struct toku_rbt_node *nextp;
};
struct toku_rbt_tree {
int (*rb_cmp)(const toku_range*, const toku_range*);
int (*rb_cmp)(const toku_point*, const toku_point*);
struct toku_rbt_node *rb_root;
void* (*rb_malloc) (size_t);
void (*rb_free) (void*);
......@@ -52,33 +51,34 @@ struct toku_rbt_tree {
};
int toku_rbt_init (
int (*cmp)(const toku_range*, const toku_range*),
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_range* key,
struct toku_rbt_tree* rbinfo,
struct toku_rbt_node** pinsert_finger,
struct toku_rbt_node** pelement_finger,
const toku_range** pdata
toku_range** pdata
);
const toku_range* toku_rbt_finger_insert(
int toku_rbt_finger_insert(
const toku_range* key,
struct toku_rbt_tree* rbinfo,
struct toku_rbt_node* parent
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(const struct toku_rbt_node** pfinger, const toku_range** ppred_data);
int toku_rbt_finger_predecessor(struct toku_rbt_node** pfinger, toku_range** ppred_data);
int toku_rbt_finger_successor(const struct toku_rbt_node** pfinger, const toku_range** psucc_data);
int toku_rbt_finger_successor(struct toku_rbt_node** pfinger, toku_range** psucc_data);
void toku_rbt_destroy(struct toku_rbt_tree *);
......
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