Commit 0cf40db2 authored by Yoni Fogel's avatar Yoni Fogel

Addresses #284

Checkpoint in implementing linear.c

git-svn-id: file:///svn/tokudb@1776 c7de825b-a66e-492c-adef-691d508d4ae1
parent b32ac2cb
# On OSX do:
# make OSX=OSX
LIBNAMELINEAR=librangetreelinear
LIBNAME=librangetree
OPTFLAGS = -O2
OPTFLAGS = #-O2
# GCOV_FLAGS = -fprofile-arcs -ftest-coverage
CFLAGS = -W -Wall -Werror -g -fPIC $(OPTFLAGS) $(GCOV_FLAGS)
CPPFLAGS = -I../../include -I../../newbrt
CPPFLAGS += -D_GNU_SOURCE -D_THREAD_SAFE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE
#CPPFLAGS += -D_GNU_SOURCE -D_THREAD_SAFE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE
ifeq ($(OSX),OSX)
LIBEXT=dylib
......@@ -20,28 +20,32 @@ SHARED=-shared
endif
.PHONY: install logformat
install: $(LIBNAME).$(LIBEXT) $(LIBNAME).a
cp $(LIBNAME).$(LIBEXT) ../../lib/
cp $(LIBNAME).a ../../lib
check: $(LIBNAME).$(LIBEXT)
python tokuglobals.py $(LIBNAME).$(LIBEXT)
strip: $(LIBNAME).$(LIBEXT)
strip $(LIBNAME).$(LIBEXT)
install: $(LIBNAMELINEAR).$(LIBEXT) $(LIBNAMELINEAR).a #$(LIBNAME).$(LIBEXT) $(LIBNAME).a
#cp $(LIBNAME).$(LIBEXT) ../../lib/
#cp $(LIBNAME).a ../../lib
cp $(LIBNAMELINEAR).$(LIBEXT) ../../lib/
cp $(LIBNAMELINEAR).a ../../lib
clean:
rm -rf $(LIBNAMELINEAR).$(LIBEXT) $(LIBNAMELINEAR)
rm -rf $(LIBNAME).$(LIBEXT) $(LIBNAME).a *.o *.gcno *.gcda *.gcov
cd tests;make clean
linear.o: rangetree.h
DBBINS = linear.o
linear.o: linear.c rangetree.h
gcc $(CFLAGS) $(CPPFLAGS) -DTOKU_LINEAR_RANGE_TREE -c $< -o $@
log.o: log.c rangetree.h
gcc $(CFLAGS) $(CPPFLAGS) -DTOKU_LOG_RANGE_TREE -c $< -o $@
$(LIBNAME).$(LIBEXT): log.o
cc $(CPPFLAGS) $< $(SHARED) -o $@ $(CFLAGS) -lz
$(LIBNAME).$(LIBEXT): $(DBBINS)
cc $(CPPFLAGS) $(DBBINS) $(SHARED) -o $@ $(CFLAGS) -lz
$(LIBNAMELINEAR).$(LIBEXT): linear.o
cc $(CPPFLAGS) $< $(SHARED) -o $@ $(CFLAGS) -lz
$(LIBNAME).a: $(DBBINS)
$(AR) rv $@ $(DBBINS)
$(LIBNAME).a: log.o
$(AR) rv $@ $<
libdb.a(ydb.o): ydb.o
$(LIBNAMELINEAR).a: linear.o
$(AR) rv $@ $<
......@@ -11,33 +11,226 @@
//Currently this is a stub implementation just so we can write and compile tests
//before actually implementing the range tree.
#include "rangetree.h"
#include <errno.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#define AA __attribute__((__unused__))
int toku_rt_create(toku_range_tree** a AA,
int (*b)(void*,void*) AA, int (*c)(void*,void*) AA,
BOOL d AA)
{return 0;}
int toku_rt_close(toku_range_tree*a AA)
{return 0;}
const unsigned minlen = 64;
int toku_rt_find(toku_range_tree*b AA, toku_range*c AA, unsigned d AA, toku_range**e AA, unsigned*g AA, unsigned*f AA)
{return 0;}
/*
* Returns:
* 0: Point \in range
* < 0: Point strictly less than the range.
* > 0: Point strictly greater than the range.
*/
static int __toku_rt_p_cmp(toku_range_tree* tree,
void* point, toku_range* range) {
if (tree->end_cmp(point, range->left) < 0) return -1;
if (tree->end_cmp(point, range->right) > 0) return 1;
return 0;
}
static int __toku_rt_decrease_capacity(toku_range_tree* tree, unsigned num AA) {
assert(tree);
//TODO: reclaim capacity.
return 1;
}
static int __toku_rt_increase_capacity(toku_range_tree* tree, unsigned num) {
assert(tree);
if (tree->ranges_len < num) {
unsigned temp_len = tree->ranges_len;
while (temp_len < num) temp_len *= 2;
toku_range* temp_ranges =
realloc(tree->ranges, temp_len * sizeof(toku_range));
if (!temp_ranges) return errno;
tree->ranges = temp_ranges;
tree->ranges_len = temp_len;
}
return 0;
}
static int __toku_increase_buffer(toku_range** buf, unsigned* buflen,
unsigned num) {
assert(buf);
assert(buflen);
if (*buflen < num) {
unsigned temp_len = *buflen;
while (temp_len < num) temp_len *= 2;
toku_range* temp_buf = realloc(*buf, temp_len * sizeof(toku_range));
if (!temp_buf) return errno;
*buf = temp_buf;
*buflen = temp_len;
}
return 0;
}
static 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);
}
BOOL __toku_rt_exact(toku_range_tree* tree,
toku_range* a, toku_range* b) {
assert(tree);
assert(a);
// assert(a->left);
// assert(a->right);
assert(b);
// assert(b->left);
// assert(b->right);
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);
}
int toku_rt_create(toku_range_tree** ptree,
int (*end_cmp)(void*,void*), int (*data_cmp)(void*,void*),
BOOL allow_overlaps) {
int r;
toku_range_tree* temptree;
if (!ptree || !end_cmp || !data_cmp) return EINVAL;
temptree = (toku_range_tree*)malloc(sizeof(toku_range_tree));
if (0) {
died1:
free(temptree);
return r;
}
if (!temptree) return errno;
//Any initializers go here.
memset(temptree, 0, sizeof(*temptree));
temptree->end_cmp = end_cmp;
temptree->data_cmp = data_cmp;
temptree->allow_overlaps = allow_overlaps;
temptree->ranges_len = minlen;
temptree->ranges = (toku_range*)
malloc(temptree->ranges_len * sizeof(toku_range));
if (!temptree->ranges) {
r = errno;
goto died1;
}
*ptree = temptree;
return 0;
}
int toku_rt_close(toku_range_tree* tree) {
if (!tree) return EINVAL;
free(tree->ranges);
free(tree);
return 0;
}
int toku_rt_find(toku_range_tree* tree, toku_range* query, unsigned k,
toku_range** buf, unsigned* buflen, unsigned* numfound) {
if (!tree || !query || !buf || !buflen || !numfound) return EINVAL;
if (query->data != NULL) return EINVAL;
if (*buflen == 0) return EINVAL;
unsigned temp_numfound = 0;
int r;
unsigned i;
for (i = 0; i < tree->numelements; i++) {
if (__toku_rt_overlap(tree, query, &tree->ranges[i])) {
r = __toku_increase_buffer(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;
}
}
*numfound = temp_numfound;
return 0;
}
int toku_rt_insert(toku_range_tree* tree, toku_range* range) {
if (!tree || !range) return EINVAL;
unsigned i;
int r;
//EDOM cases
if (tree->allow_overlaps) {
for (i = 0; i < tree->numelements; i++) {
if (__toku_rt_exact (tree, range, &tree->ranges[i])) return EDOM;
}
}
else {
for (i = 0; i < tree->numelements; i++) {
if (__toku_rt_overlap(tree, range, &tree->ranges[i]) ||
__toku_rt_overlap(tree, &tree->ranges[i], range)) return EDOM;
}
}
r = __toku_rt_increase_capacity(tree, tree->numelements + 1);
if (r != 0) return r;
tree->ranges[++tree->numelements] = *range;
return 0;
}
int toku_rt_delete(toku_range_tree* tree, toku_range* range) {
if (!tree || !range) return EINVAL;
unsigned i;
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) {
//juggle
}
__toku_rt_decrease_capacity(tree, --tree->numelements);
return 0;
}
int toku_rt_predecessor (toku_range_tree* tree, void* point, toku_range* pred,
BOOL* wasfound) {
if (!tree || !point || !pred || !wasfound) return EINVAL;
if (tree->allow_overlaps) return EINVAL;
toku_range* best = NULL;
unsigned 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];
}
}
*wasfound = best != NULL;
pred = best;
return 0;
}
int toku_rt_insert(toku_range_tree*a AA, toku_range*v AA)
{return 0;}
int toku_rt_delete(toku_range_tree*c AA, toku_range*q AA)
{return 0;}
int toku_rt_successor (toku_range_tree* tree, void* point, toku_range* succ,
BOOL* wasfound) {
if (!tree || !point || !succ || !wasfound) return EINVAL;
if (tree->allow_overlaps) return EINVAL;
toku_range* best = NULL;
unsigned i;
int toku_rt_predecessor (toku_range_tree*f AA, void*g AA, toku_range*q AA, BOOL* v AA)
{return 0;}
int toku_rt_successor (toku_range_tree*e AA, void*c AA, toku_range*a AA, BOOL* q AA)
{return 0;}
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];
}
}
*wasfound = best != NULL;
succ = best;
return 0;
}
/*
\marginpar{
static int __toku_lt_infinity;
static int __toku_lt_neg_infinity;
extern void* toku_lt_infinity = &__toku_lt_infinity;
extern void* toku_lt_neg_infinity = &__toku_lt_infinity;}
\marginpar{add more \\marginpar\'s}
*/
......@@ -10,21 +10,35 @@
#include <brttypes.h>
/** Represents a range of data with an extra value. */
/** Represents a range of data with an extra value.
* Parameters are never modified on failure with the exception of
* buf and buflen.
*/
typedef struct {
void* left;
void* right;
void* data;
} toku_range;
/** Structure is not yet defined, this is so we can write and compile tests
before implementation.
Will be defined during implementation,
and will actually be defined in a separate headers (one for linear version
and one for binary search tree based version). */
struct __toku_range_tree_internal {
int dummy;
//Shared fields:
int (*end_cmp)(void*,void*);
int (*data_cmp)(void*,void*);
BOOL allow_overlaps;
unsigned numelements;
#if defined(TOKU_LINEAR_RANGE_TREE)
#if defined(TOKU_LOG_RANGE_TREE)
#error Choose just one range tree type.
#endif
//Linear version only fields:
toku_range* ranges;
unsigned ranges_len;
#elif defined(TOKU_LOG_RANGE_TREE)
#error Not defined yet.
//Log version only fields:
#else
#error Using an undefined RANGE TREE TYPE.
#endif
};
/* These lines will remain. */
......@@ -68,7 +82,7 @@ int toku_rt_close(toku_range_tree* tree);
* k: The maximum number of ranges to return.
* The special value '0' is used to request ALL overlapping
* ranges.
* range: The range to query.
* query: The range to query.
* range.data must be NULL.
* buf: A pointer to the buffer used to return ranges.
* The buffer will be increased using realloc(3) if
......@@ -88,8 +102,11 @@ int toku_rt_close(toku_range_tree* tree);
* If range.data != NULL.
* If buflen == 0.
* Other exit codes may be forwarded from underlying system calls.
* It may be useful in the future to add an extra out parameter to specify
* whether more elements exist in the tree that overlap (in excess of the
* requested limit of k).
*/
int toku_rt_find(toku_range_tree* tree, toku_range* range, unsigned k,
int toku_rt_find(toku_range_tree* tree, toku_range* query, unsigned k,
toku_range** buf, unsigned* buflen, unsigned* numfound);
/**
......
......@@ -10,56 +10,50 @@ ifeq ($(OSX),OSX)
#Note: OSX 10.4 needs DYLD_LIBRARY_PATH. OSX 10.5 claims to support -rpath.
LIBEXT=dylib
VGRIND=
TDB_LOADLIBES = -L../ -lrangetree
SETTOKUENV=export DYLD_LIBRARY_PATH=.. ;
UNSETTOKUENV=unset DYLD_LIBRARY_PATH ;
CPPFLAGS =
SETENV=export DYLD_LIBRARY_PATH=.. ;
else
SETTOKUENV=
UNSETTOKUENV=
LIBEXT=so
TDB_LOADLIBES = -L../ -lrangetree -Wl,-rpath,.. -lpthread
CPPFLAGS = -Wl,-rpath,..
VGRIND=valgrind --quiet --error-exitcode=1 --leak-check=yes
endif
LIBNAME=librt.$(LIBEXT)
# GCOV_FLAGS = -fprofile-arcs -ftest-coverage
CFLAGS = -Wall -Werror $(OPTFLAGS) -g $(GCOV_FLAGS)
TDB_CPPFLAGS = -I../ -I../../../newbrt
CPPFLAGS += -L../ -I../ -I../../../newbrt -lpthread
SRCS = $(wildcard *.c)
TDB_TESTS = $(patsubst %.c,%.tdb,$(SRCS))
BDB_TESTS = $(patsubst %.c,%.bdb,$(SRCS))
LINEAR_TESTS = $(patsubst %.c,%.bdb,$(SRCS))
LOG_TESTS = $(patsubst %.c,%.log,$(SRCS))
LIN_TESTS = $(patsubst %.c,%.lin,$(SRCS))
ALL_TESTS = $(TDB_TESTS) #$(BDB_TESTS)
ALL_TESTS = $(LOG_TESTS) $(LIN_TESTS)
RUN_TDB_TESTS = $(patsubst %.tdb,%.tdbrun,$(TDB_TESTS))
RUN_BDB_TESTS = $(patsubst %.bdb,%.bdbrun,$(BDB_TESTS))
RUN_ALL_TESTS = $(RUN_TDB_TESTS) $(RUN_BDB_TESTS)
RUN_LOG_TESTS = $(patsubst %.log,%.logrun,$(LOG_TESTS))
RUN_LIN_TESTS = $(patsubst %.lin,%.linrun,$(LIN_TESTS))
RUN_ALL_TESTS = $(RUN_LOG_TESTS) $(RUN_LIN_TESTS)
all: make_libs $(ALL_TESTS)
foo:
echo RUN_TDB_TESTS: $(RUN_TDB_TESTS)
echo ALL_TESTS: $(ALL_TESTS)
.PHONY: check check.bdb check.tdb
check: check.bdb check.tdb all.recover test_db_assoc3.tdbrun_wasbad
.PHONY: check check.lin check.log tests.lin tests.log
check: check.lin check.log
@ echo ok
tests.bdb: $(BDB_TESTS)
check.bdb: $(RUN_BDB_TESTS)
tests.tdb: $(TDB_TESTS)
check.tdb: $(RUN_TDB_TESTS)
tests.lin: make_libs $(LIN_TESTS)
check.lin: make_libs $(RUN_LIN_TESTS)
tests.log: make_libs $(LOG_TESTS)
check.log: make_libs $(RUN_LOG_TESTS)
# Need these rule so that Make knows about all the file names
.PHONY: %.bdbrun %.tdbrun %.run
.PHONY: %.linrun %.logrun %.run
$(RUN_ALL_TESTS):
$(ALL_TESTS):
%.run: %.bdbrun %.tdbrun
%.run: %.linrun %.logrun
@ echo ok
ifeq ($(VERBOSE),2)
......@@ -79,94 +73,24 @@ else
endif
# The @ sign makes the make quiet. If there is an error there is enough info to tell what test failed.
%.bdbrun: %.bdb
$(MAYBEATSIGN) $(UNSETTOKUENV) $(VGRIND) $(BDB_SUPPRESSIONS) ./$< $(VERBVERBOSE)
%.tdbrun: %.tdb
$(MAYBEATSIGN) $(SETTOKUENV) $(VGRIND) ./$< $(VERBVERBOSE)
# For a few of the tests bdb is making valgrind unhappy.
FOO_NO_VGRIND = \
db_already_exists \
db_curs2 \
db_dbt_appmalloc \
db_dbt_mem_behavior \
db_dup \
db_env_open_nocreate \
db_env_open_open_close \
db_open_notexist_reopen \
db_remove_subdb \
db_subdb \
dup_delete \
dup_flags \
dup_insert \
dup_search \
kv_limits \
log4 \
rand_insert \
reverse_compare_fun \
# Comment to terminate list so the previous line can end with a slash
NO_VGRIND = \
db_dbt_appmalloc \
db_dbt_mem_behavior \
db_assoc3 \
db_curs2 \
db_delete \
db_env_open_nocreate \
db_env_open_open_close \
db_open_notexist_reopen \
db_remove_subdb \
log4 \
log5 \
# Comment to terminate list so the previous line can end with a slash
$(patsubst %,test_%.bdbrun,$(NO_VGRIND)): VGRIND=
$(patsubst %,test_%.bdbrun,$(NO_VGRIND)): BDB_SUPPRESSIONS=
%.linrun: %.lin
$(MAYBEATSIGN) $(SETENV) $(VGRIND) ./$< $(VERBVERBOSE)
%.logrun: %.log
$(MAYBEATSIGN) $(SETENV) $(VGRIND) ./$< $(VERBVERBOSE)
libs:
cd ..;make
%.bdb: %.c ../rangetree.h test.h
$(UNSETTOKUENV) cc -DDIR=\"dir.$<.bdb\" $(BDB_CPPFLAGS) -DUSE_BDB -DIS_TDB=0 $(CFLAGS) $< $(BDB_LDFLAGS) -lrangetree -o $@
%.tdb: %.c ../rangetree.h test.h
$(SETTOKUENV) cc -DDIR=\"dir.$<.tdb\" -DUSE_TDB -DIS_TDB=1 $(CFLAGS) $(TDB_CPPFLAGS) $(TDB_LOADLIBES) $< -o $@
.PHONY: %.recover
all.recover: test_log2.recover test_log3.recover test_log4.recover test_log5.recover
%.recover: %.tdb
$(MAYBEATSIGN) cd ..;make $(VERBQUIET)
$(MAYBEATSIGN) $(VGRIND) ./$<
$(MAYBEATSIGN) rm -rf dir.$(patsubst %.tdb,%.c.tdb,$<).recover
$(MAYBEATSIGN) mkdir dir.$(patsubst %.tdb,%.c.tdb,$<).recover
$(MAYBEATSIGN) cd dir.$(patsubst %.tdb,%.c.tdb,$<).recover;$(VGRIND) ../../../newbrt/recover ../dir.$(patsubst %.tdb,%.c.tdb,$<)
$(MAYBEATSIGN) diff dir.$(patsubst %.tdb,%.c.tdb,$<) dir.$(patsubst %.tdb,%.c.tdb,$<).recover/foo.db
%.lin: %.c ../rangetree.h test.h
$(SETENV) cc -DDIR=\"dir.$<.lin\" -DTOKU_LINEAR_RANGE_TREE $(CPPFLAGS) $(CFLAGS) $< -lrangetreelinear -o $@
%.log: %.c ../rangetree.h test.h
$(SETENV) cc -DDIR=\"dir.$<.log\" -DTOKU_LOG_RANGE_TREE $(CPPFLAGS) $(CFLAGS) $< -lrangetree -o $@
.PHONY: make_libs
make_libs:
cd ..;make
clean:
rm -f $(ALL_TESTS) *.o *.gcno *.gcda *.gcov
rm -rf dir.*.tdb dir.*.bdb
test_db_curs4.tdb: trace.h
test_db_curs4.bdb: trace.h
test_db_assoc3.tdb test_db_assoc3.bdb: test.h
# This one failed in both BDB and TokuDB, in the same way. It was a program error. Now it works
test_db_assoc3.tdbrun_wasbad: test_db_assoc3.tdb
$(MAYBEATSIGN) ./test_db_assoc3.tdb --seed=1 --count=200
$(MAYBEATSIGN) ./test_db_assoc3.tdb --seed=1 --count=200 --more
$(MAYBEATSIGN) ./test_db_assoc3.tdb --seed=1 --count=200 --more
$(MAYBEATSIGN) ./test_db_assoc3.tdb --seed=1 --count=200 --more
$(MAYBEATSIGN) ./test_db_assoc3.tdb --seed=1 --count=200 --more
$(MAYBEATSIGN) ./test_db_assoc3.tdb --seed=1 --count=200 --more
$(MAYBEATSIGN) ./test_db_assoc3.tdb --seed=1 --count=200 --more
test_db_assoc3.tdbrun: test_db_assoc3.tdb
$(MAYBEATSIGN) $(VGRIND) ./test_db_assoc3.tdb --seed=2 --count=100000 $(VERBVERBOSE)
$(MAYBEATSIGN) $(VGRIND) ./test_db_assoc3.tdb --seed=2 --count=100000 --more $(VERBVERBOSE)
test_db_assoc3.bdbrun: test_db_assoc3.bdb
$(MAYBEATSIGN) $(VGRIND) ./test_db_assoc3.bdb --seed=2 --count=100000 $(VERBVERBOSE)
$(MAYBEATSIGN) $(VGRIND) ./test_db_assoc3.bdb --seed=2 --count=100000 --more $(VERBVERBOSE)
rm -rf dir.*.log dir.*.LIN
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