Commit ea55d190 authored by Vincenzo Liberatore's avatar Vincenzo Liberatore

Addresses #378

Refactored error handling to work with C++ API.
Modify Makefile to avoid repeating all tests.

git-svn-id: file:///svn/tokudb@2309 c7de825b-a66e-492c-adef-691d508d4ae1
parent 093e960e
...@@ -62,11 +62,11 @@ static void __toku_ydb_error_file(const DB_ENV *env, BOOL use_stderr, ...@@ -62,11 +62,11 @@ static void __toku_ydb_error_file(const DB_ENV *env, BOOL use_stderr,
if the prefix is empty) if the prefix is empty)
\param ap Optional prefix \param ap Optional prefix
*/ */
static void __toku_ydb_error_all_cases(const DB_ENV * env, void toku_ydb_error_all_cases(const DB_ENV * env,
int error, int error,
BOOL include_stderrstring, BOOL include_stderrstring,
BOOL use_stderr_if_nothing_else, BOOL use_stderr_if_nothing_else,
const char *fmt, va_list ap) { const char *fmt, va_list ap) {
/* Construct the error message */ /* Construct the error message */
char buf [4000]; char buf [4000];
int count=0; int count=0;
...@@ -96,7 +96,7 @@ int toku_ydb_do_error (const DB_ENV *dbenv, int error, const char *fmt, ...) { ...@@ -96,7 +96,7 @@ int toku_ydb_do_error (const DB_ENV *dbenv, int error, const char *fmt, ...) {
if (toku_logger_panicked(dbenv->i->logger)) dbenv->i->is_panicked=1; if (toku_logger_panicked(dbenv->i->logger)) dbenv->i->is_panicked=1;
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
__toku_ydb_error_all_cases(dbenv, error, TRUE, FALSE, fmt, ap); toku_ydb_error_all_cases(dbenv, error, TRUE, FALSE, fmt, ap);
va_end(ap); va_end(ap);
return error; return error;
} }
...@@ -114,7 +114,7 @@ void toku_locked_env_err(const DB_ENV * env, int error, const char *fmt, ...) { ...@@ -114,7 +114,7 @@ void toku_locked_env_err(const DB_ENV * env, int error, const char *fmt, ...) {
toku_ydb_lock(); toku_ydb_lock();
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
__toku_ydb_error_all_cases(env, error, TRUE, TRUE, fmt, ap); toku_ydb_error_all_cases(env, error, TRUE, TRUE, fmt, ap);
va_end(ap); va_end(ap);
toku_ydb_unlock(); toku_ydb_unlock();
} }
......
...@@ -13,19 +13,6 @@ ...@@ -13,19 +13,6 @@
#include <ydb-internal.h> #include <ydb-internal.h>
#include <brt-internal.h> #include <brt-internal.h>
/* TODO: Yoni should check that all asserts make sense instead of panic,
and all early returns make sense instead of panic,
and vice versa. */
/* TODO: During integration, create a db panic function to take care of this.
The panic function will go in ydb.c.
We may have to return the panic return code something.
We know the DB will always return EINVAL afterwards, but
what is the INITIAL panic return?
ALSO maybe make ticket, maybe it should be doing DB_RUNRECOVERY after
instead of EINVAL.
*/
/* TODO: During integration, make sure we first verify the NULL CONSISTENCY,
(return EINVAL if necessary) before making lock tree calls. */
inline static int __toku_lt_panic(toku_lock_tree *tree, int r) { inline static int __toku_lt_panic(toku_lock_tree *tree, int r) {
return tree->panic(tree->db, r); return tree->panic(tree->db, r);
} }
......
...@@ -17,7 +17,7 @@ ifneq ($(OSX),) ...@@ -17,7 +17,7 @@ ifneq ($(OSX),)
LIBEXT=dylib LIBEXT=dylib
VGRIND= VGRIND=
BDB_SUPPRESSIONS= BDB_SUPPRESSIONS=
TDB_LOADLIBES = -L../ -ltokudb TDB_LOADLIBES = -L../ -ltokudb
SETTOKUENV=export DYLD_LIBRARY_PATH=.. ; SETTOKUENV=export DYLD_LIBRARY_PATH=.. ;
UNSETTOKUENV=unset DYLD_LIBRARY_PATH ; UNSETTOKUENV=unset DYLD_LIBRARY_PATH ;
else else
...@@ -77,7 +77,7 @@ check.tdb: make_libs $(RUN_TDB_TESTS) ...@@ -77,7 +77,7 @@ check.tdb: make_libs $(RUN_TDB_TESTS)
@ echo ok $@ @ echo ok $@
# Need these rule so that Make knows about all the file names # Need these rule so that Make knows about all the file names
.PHONY: %.bdbrun %.tdbrun %.run .PHONY: %.run
$(RUN_ALL_TESTS): $(RUN_ALL_TESTS):
$(ALL_TESTS): $(ALL_TESTS):
...@@ -106,10 +106,11 @@ endif ...@@ -106,10 +106,11 @@ endif
#%.bdbrun: %.bdb #%.bdbrun: %.bdb
# $(MAYBEATSIGN) $(UNSETTOKUENV) $(VGRIND) $(BDB_SUPPRESSIONS) ./$< $(VERBVERBOSE) # $(MAYBEATSIGN) $(UNSETTOKUENV) $(VGRIND) $(BDB_SUPPRESSIONS) ./$< $(VERBVERBOSE)
# Now thiss: # Now thiss:
%.bdbrun: %.bdb %.bdbrun: %.bdb ../libtokudb.$(LIBEXT)
$(MAYBEATSIGN) $(UNSETTOKUENV) ./$< $(VERBVERBOSE) $(MAYBEATSIGN) $(UNSETTOKUENV) ./$< $(VERBVERBOSE)
%.tdbrun: %.tdb %.tdbrun: %.tdb ../libtokudb.$(LIBEXT)
$(MAYBEATSIGN) $(SETTOKUENV) $(VGRIND) ./$< $(VERBVERBOSE) $(MAYBEATSIGN) $(SETTOKUENV) $(VGRIND) ./$< $(VERBVERBOSE)
@ touch $@
# For BDB, VGRIND isn't happy # For BDB, VGRIND isn't happy
NO_VGRIND = \ NO_VGRIND = \
...@@ -186,10 +187,15 @@ all.recover: test_log2.recover test_log3.recover test_log4.recover test_log5.rec ...@@ -186,10 +187,15 @@ all.recover: test_log2.recover test_log3.recover test_log4.recover test_log5.rec
make_libs: make_libs:
cd ..;make cd ..;make
.PHONY: clean cleanall
clean: clean:
rm -f $(ALL_TESTS) *.o *.gcno *.gcda *.gcov rm -f $(ALL_TESTS) *.o *.gcno *.gcda *.gcov
rm -rf dir.*.tdb dir.*.bdb rm -rf dir.*.tdb dir.*.bdb
cleanall: clean
rm -f *.tdbrun
test_db_curs4.tdb: trace.h test_db_curs4.tdb: trace.h
test_db_curs4.bdb: trace.h test_db_curs4.bdb: trace.h
test_db_assoc3.tdb test_db_assoc3.bdb: test.h test_db_assoc3.tdb test_db_assoc3.bdb: test.h
...@@ -204,10 +210,12 @@ test_db_assoc3.tdbrun_wasbad: test_db_assoc3.tdb ...@@ -204,10 +210,12 @@ test_db_assoc3.tdbrun_wasbad: test_db_assoc3.tdb
$(MAYBEATSIGN) $(SETTOKUENV) ./test_db_assoc3.tdb --seed=1 --count=200 --more $(MAYBEATSIGN) $(SETTOKUENV) ./test_db_assoc3.tdb --seed=1 --count=200 --more
$(MAYBEATSIGN) $(SETTOKUENV) ./test_db_assoc3.tdb --seed=1 --count=200 --more $(MAYBEATSIGN) $(SETTOKUENV) ./test_db_assoc3.tdb --seed=1 --count=200 --more
$(MAYBEATSIGN) $(SETTOKUENV) ./test_db_assoc3.tdb --seed=1 --count=200 --more $(MAYBEATSIGN) $(SETTOKUENV) ./test_db_assoc3.tdb --seed=1 --count=200 --more
@ touch $@
test_db_assoc3.tdbrun: test_db_assoc3.tdb test_db_assoc3.tdbrun: test_db_assoc3.tdb
$(MAYBEATSIGN) $(SETTOKUENV) $(VGRIND) ./test_db_assoc3.tdb --seed=2 --count=100000 $(VERBVERBOSE) $(MAYBEATSIGN) $(SETTOKUENV) $(VGRIND) ./test_db_assoc3.tdb --seed=2 --count=100000 $(VERBVERBOSE)
$(MAYBEATSIGN) $(SETTOKUENV) $(VGRIND) ./test_db_assoc3.tdb --seed=2 --count=100000 --more $(VERBVERBOSE) $(MAYBEATSIGN) $(SETTOKUENV) $(VGRIND) ./test_db_assoc3.tdb --seed=2 --count=100000 --more $(VERBVERBOSE)
@ touch $@
# Give up on VGRIND for bdbrun # Give up on VGRIND for bdbrun
test_db_assoc3.bdbrun: test_db_assoc3.bdb test_db_assoc3.bdbrun: test_db_assoc3.bdb
......
...@@ -109,6 +109,11 @@ void toku_ydb_unlock(); ...@@ -109,6 +109,11 @@ void toku_ydb_unlock();
#define HANDLE_PANICKED_DB(db) HANDLE_PANICKED_ENV(db->dbenv) #define HANDLE_PANICKED_DB(db) HANDLE_PANICKED_ENV(db->dbenv)
/* */ /* */
void toku_ydb_error_all_cases(const DB_ENV * env,
int error,
BOOL include_stderrstring,
BOOL use_stderr_if_nothing_else,
const char *fmt, va_list ap);
int toku_ydb_do_error (const DB_ENV *, int, const char *, ...); int toku_ydb_do_error (const DB_ENV *, int, const char *, ...);
/* Location specific debug print-outs */ /* Location specific debug print-outs */
......
...@@ -910,24 +910,40 @@ static int toku_db_close(DB * db, u_int32_t flags) { ...@@ -910,24 +910,40 @@ static int toku_db_close(DB * db, u_int32_t flags) {
return r; return r;
} }
/* Verify that an element from the secondary database is still consistent
with the primary.
\param secondary Secondary database
\param pkey Primary key
\param data Primary data
\param skey Secondary key to test
\return
*/
static int verify_secondary_key(DB *secondary, DBT *pkey, DBT *data, DBT *skey) { static int verify_secondary_key(DB *secondary, DBT *pkey, DBT *data, DBT *skey) {
int r = 0; int r = 0;
DBT idx; DBT idx;
assert(secondary->i->primary != 0); assert(secondary->i->primary != 0);
memset(&idx, 0, sizeof(idx)); memset(&idx, 0, sizeof(idx));
secondary->i->associate_callback(secondary, pkey, data, &idx); r = secondary->i->associate_callback(secondary, pkey, data, &idx);
if (r==DB_DONOTINDEX) return DB_SECONDARY_BAD; if (r==DB_DONOTINDEX) { r = DB_SECONDARY_BAD; goto clean_up; }
if (r!=0) goto clean_up;
#ifdef DB_DBT_MULTIPLE #ifdef DB_DBT_MULTIPLE
if (idx.flags & DB_DBT_MULTIPLE) { if (idx.flags & DB_DBT_MULTIPLE) {
return EINVAL; // We aren't ready for this r = EINVAL; // We aren't ready for this
goto clean_up;
} }
#endif #endif
if (skey->size != idx.size || memcmp(skey->data, idx.data, idx.size) != 0) r = DB_SECONDARY_BAD; if (secondary->i->brt->compare_fun(secondary, skey, &idx) != 0) {
r = DB_SECONDARY_BAD;
goto clean_up;
}
clean_up:
if (idx.flags & DB_DBT_APPMALLOC) { if (idx.flags & DB_DBT_APPMALLOC) {
toku_free(idx.data); /* This should be free because idx.data is allocated by the user */
free(idx.data);
} }
return r; return r;
} }
//Get the main portion of a cursor flag (excluding the bitwise or'd components). //Get the main portion of a cursor flag (excluding the bitwise or'd components).
...@@ -1299,7 +1315,8 @@ static int toku_c_pget(DBC * c, DBT *key, DBT *pkey, DBT *data, u_int32_t flag) ...@@ -1299,7 +1315,8 @@ static int toku_c_pget(DBC * c, DBT *key, DBT *pkey, DBT *data, u_int32_t flag)
if (r == DB_NOTFOUND) goto delete_silently_and_retry; if (r == DB_NOTFOUND) goto delete_silently_and_retry;
if (r != 0) goto died3; if (r != 0) goto died3;
r = verify_secondary_key(db, pkey, data, key); r = verify_secondary_key(db, pkey, data, key);
if (r != 0) goto delete_silently_and_retry; if (r == DB_SECONDARY_BAD) goto delete_silently_and_retry;
if (r != 0) goto died3;
//Copy everything and return. //Copy everything and return.
assert(r==0); assert(r==0);
...@@ -1435,12 +1452,14 @@ static int do_associated_deletes(DB_TXN *txn, DBT *key, DBT *data, DB *secondary ...@@ -1435,12 +1452,14 @@ static int do_associated_deletes(DB_TXN *txn, DBT *key, DBT *data, DB *secondary
u_int32_t brtflags; u_int32_t brtflags;
DBT idx; DBT idx;
memset(&idx, 0, sizeof(idx)); memset(&idx, 0, sizeof(idx));
int r = secondary->i->associate_callback(secondary, key, data, &idx);
int r2 = 0; int r2 = 0;
if (r==DB_DONOTINDEX) return 0; int r = secondary->i->associate_callback(secondary, key, data, &idx);
if (r==DB_DONOTINDEX) { r = 0; goto clean_up; }
if (r!=0) goto clean_up;
#ifdef DB_DBT_MULTIPLE #ifdef DB_DBT_MULTIPLE
if (idx.flags & DB_DBT_MULTIPLE) { if (idx.flags & DB_DBT_MULTIPLE) {
return EINVAL; // We aren't ready for this r = EINVAL; // We aren't ready for this
goto clean_up;
} }
#endif #endif
toku_brt_get_flags(secondary->i->brt, &brtflags); toku_brt_get_flags(secondary->i->brt, &brtflags);
...@@ -1448,16 +1467,18 @@ static int do_associated_deletes(DB_TXN *txn, DBT *key, DBT *data, DB *secondary ...@@ -1448,16 +1467,18 @@ static int do_associated_deletes(DB_TXN *txn, DBT *key, DBT *data, DB *secondary
//If the secondary has duplicates we need to use cursor deletes. //If the secondary has duplicates we need to use cursor deletes.
DBC *dbc; DBC *dbc;
r = toku_db_cursor(secondary, txn, &dbc, 0); r = toku_db_cursor(secondary, txn, &dbc, 0);
if (r!=0) goto cleanup; if (r!=0) goto cursor_cleanup;
r = toku_c_get_noassociate(dbc, &idx, key, DB_GET_BOTH); r = toku_c_get_noassociate(dbc, &idx, key, DB_GET_BOTH);
if (r!=0) goto cleanup; if (r!=0) goto cursor_cleanup;
r = toku_c_del_noassociate(dbc, 0); r = toku_c_del_noassociate(dbc, 0);
cleanup: cursor_cleanup:
r2 = toku_c_close(dbc); r2 = toku_c_close(dbc);
} else } else
r = toku_db_del_noassociate(secondary, txn, &idx, DB_DELETE_ANY); r = toku_db_del_noassociate(secondary, txn, &idx, DB_DELETE_ANY);
clean_up:
if (idx.flags & DB_DBT_APPMALLOC) { if (idx.flags & DB_DBT_APPMALLOC) {
toku_free(idx.data); /* This should be free because idx.data is allocated by the user */
free(idx.data);
} }
if (r!=0) return r; if (r!=0) return r;
return r2; return r2;
...@@ -2037,15 +2058,18 @@ static int do_associated_inserts (DB_TXN *txn, DBT *key, DBT *data, DB *secondar ...@@ -2037,15 +2058,18 @@ static int do_associated_inserts (DB_TXN *txn, DBT *key, DBT *data, DB *secondar
DBT idx; DBT idx;
memset(&idx, 0, sizeof(idx)); memset(&idx, 0, sizeof(idx));
int r = secondary->i->associate_callback(secondary, key, data, &idx); int r = secondary->i->associate_callback(secondary, key, data, &idx);
if (r==DB_DONOTINDEX) return 0; if (r==DB_DONOTINDEX) { r = 0; goto clean_up; }
if (r != 0) goto clean_up;
#ifdef DB_DBT_MULTIPLE #ifdef DB_DBT_MULTIPLE
if (idx.flags & DB_DBT_MULTIPLE) { if (idx.flags & DB_DBT_MULTIPLE) {
return EINVAL; // We aren't ready for this return EINVAL; // We aren't ready for this
} }
#endif #endif
r = toku_db_put_noassociate(secondary, txn, &idx, key, DB_YESOVERWRITE); r = toku_db_put_noassociate(secondary, txn, &idx, key, DB_YESOVERWRITE);
clean_up:
if (idx.flags & DB_DBT_APPMALLOC) { if (idx.flags & DB_DBT_APPMALLOC) {
toku_free(idx.data); /* This should be free because idx.data is allocated by the user */
free(idx.data);
} }
return r; return r;
} }
......
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