Commit c4cd97d6 authored by Vincenzo Liberatore's avatar Vincenzo Liberatore

Addresses #378

Separates out error handling and ephemeral locking. 
However, it fails a few tests.

git-svn-id: file:///svn/tokudb@2295 c7de825b-a66e-492c-adef-691d508d4ae1
parent 5a0df7b3
......@@ -43,7 +43,7 @@ clean:
ydb.o: ../include/db.h ../newbrt/cachetable.h ../newbrt/brt.h ../newbrt/log.c
DBBINS = ydb.o ../newbrt/brt.o ../newbrt/brt-serialize.o ../newbrt/brt-verify.o ../newbrt/cachetable.o ../newbrt/fifo.o ../newbrt/key.o ../newbrt/memory.o ../newbrt/mempool.o ../newbrt/pma.o ../newbrt/ybt.o ../newbrt/primes.o ../newbrt/log.o ../newbrt/fingerprint.o ../newbrt/log_code.o ../newbrt/roll.o ../newbrt/toku_assert.o
DBBINS = ydb.o errors.o elocks.o ../newbrt/brt.o ../newbrt/brt-serialize.o ../newbrt/brt-verify.o ../newbrt/cachetable.o ../newbrt/fifo.o ../newbrt/key.o ../newbrt/memory.o ../newbrt/mempool.o ../newbrt/pma.o ../newbrt/ybt.o ../newbrt/primes.o ../newbrt/log.o ../newbrt/fingerprint.o ../newbrt/log_code.o ../newbrt/roll.o ../newbrt/toku_assert.o
RANGETREE_BINS = range_tree/linear.o
LOCKTREE_BINS = lock_tree/locktree.o lock_tree/rth.o lock_tree/lth.o $(RANGETREE_BINS)
......
......@@ -4,6 +4,7 @@
#include <stdio.h>
#include <db.h>
#include "../../newbrt/brttypes.h"
#include <assert.h>
#ifndef DB_YESOVERWRITE
#define DB_YESOVERWRITE 0
......
......@@ -57,7 +57,33 @@ void cget(BOOL success, BOOL find, char txn, int _key, int _data,
assert(*(int *)key.data == _key_expect);
assert(*(int *)data.data == _data_expect);
}
else CKERR2(r, DB_NOTFOUND);
else CKERR2s(r, DB_NOTFOUND, DB_KEYEMPTY);
}
else CKERR2s(r, DB_LOCK_DEADLOCK, DB_LOCK_NOTGRANTED);
}
void cdel(BOOL success, BOOL find, char txn) {
int r;
r = cursors[(int)txn]->c_del(cursors[(int)txn], 0);
if (success) {
if (find) CKERR(r);
else CKERR2(r, DB_KEYEMPTY);
}
else CKERR2s(r, DB_LOCK_DEADLOCK, DB_LOCK_NOTGRANTED);
}
void dbdel(BOOL success, BOOL find, char txn, int _key) {
int r;
DBT key;
/* If DB_DELETE_ANY changes to 0, then find is meaningful and
has to be fixed in test_dbdel*/
r = db->del(db, txns[(int)txn], dbt_init(&key,&_key, sizeof(int)),
DB_DELETE_ANY);
if (success) {
if (find) CKERR(r);
else CKERR2( r, DB_NOTFOUND);
}
else CKERR2s(r, DB_LOCK_DEADLOCK, DB_LOCK_NOTGRANTED);
}
......@@ -418,10 +444,9 @@ void test_next(u_int32_t dup_flags, u_int32_t next_type) {
put(FALSE, 'b', -1, 1);
cget(FALSE, TRUE, 'a', 0, 0, 4, 1, next_type);
early_commit('b');
/* We need to keep going from here
cget(TRUE, TRUE, 'a', 2, 1, 2, 1, DB_GET_BOTH);
cget(TRUE, TRUE, 'a', 0, 0, 4, 1, next_type);
cget(TRUE, TRUE, 'a', 0, 0, 5, 1, next_type);
*/
close_dbs();
/* ****************************************** */
setup_dbs(dup_flags);
......@@ -437,6 +462,137 @@ void test_next(u_int32_t dup_flags, u_int32_t next_type) {
close_dbs();
}
void test_prev(u_int32_t dup_flags, u_int32_t next_type) {
/* ********************************************************************** */
setup_dbs(dup_flags);
put(TRUE, 'a', -2, -1);
put(TRUE, 'a', -5, -1);
cget(TRUE, TRUE, 'a', 0, 0, -2, -1, next_type);
put(FALSE, 'b', -2, -1);
put(TRUE, 'b', -4, -1);
put(FALSE, 'b', 1, -1);
cget(FALSE, TRUE, 'a', 0, 0, -4, -1, next_type);
early_commit('b');
cget(TRUE, TRUE, 'a', -2, -1, -2, -1, DB_GET_BOTH);
cget(TRUE, TRUE, 'a', 0, 0, -4, -1, next_type);
cget(TRUE, TRUE, 'a', 0, 0, -5, -1, next_type);
close_dbs();
/* ****************************************** */
setup_dbs(dup_flags);
put(TRUE, 'a', -1, -1);
put(TRUE, 'a', -3, -1);
put(TRUE, 'a', -6, -1);
cget(TRUE, TRUE, 'a', 0, 0, -1, -1, next_type);
cget(TRUE, TRUE, 'a', 0, 0, -3, -1, next_type);
put(FALSE, 'b', -2, -1);
put(TRUE, 'b', -4, -1);
put(TRUE, 'b', -7, -1);
put(FALSE, 'b', 1, -1);
close_dbs();
}
void test_nextdup(u_int32_t dup_flags, u_int32_t next_type, int i) {
/* ****************************************** */
if (dup_flags == 0) return;
setup_dbs(dup_flags);
put(TRUE, 'c', i*1, i*1);
early_commit('c');
cget(TRUE, TRUE, 'a', i*1, i*1, i*1, i*1, DB_GET_BOTH);
cget(TRUE, FALSE, 'a', 0, 0, i*1, i*1, next_type);
put(TRUE, 'b', i*2, i*1);
put(FALSE, 'b', i*1, i*1);
put(FALSE, 'b', i*1, i*2);
put(TRUE, 'b', i*1, 0);
close_dbs();
/* ****************************************** */
setup_dbs(dup_flags);
put(TRUE, 'c', i*1, i*1);
put(TRUE, 'c', i*1, i*3);
early_commit('c');
cget(TRUE, TRUE, 'a', i*1, i*1, i*1, i*1, DB_GET_BOTH);
cget(TRUE, TRUE, 'a', 0, 0, i*1, i*3, next_type);
put(TRUE, 'b', i*2, i*1);
put(TRUE, 'b', i*1, i*4);
put(FALSE, 'b', i*1, i*1);
put(FALSE, 'b', i*1, i*2);
put(FALSE, 'b', i*1, i*3);
put(TRUE, 'b', i*1, 0);
close_dbs();
}
void test_cdel(u_int32_t dup_flags) {
/* ********************************************************************** */
setup_dbs(dup_flags);
put(TRUE, 'c', 1, 1);
early_commit('c');
cget(TRUE, TRUE, 'a', 1, 1, 1, 1, DB_GET_BOTH);
cdel(TRUE, TRUE, 'a');
cget(FALSE, TRUE, 'b', 1, 1, 1, 1, DB_GET_BOTH);
cget(dup_flags != 0, FALSE, 'b', 1, 2, 1, 2, DB_GET_BOTH);
cget(dup_flags != 0, FALSE, 'b', 1, 0, 1, 0, DB_GET_BOTH);
cget(TRUE, FALSE, 'b', 0, 0, 0, 0, DB_GET_BOTH);
cget(TRUE, FALSE, 'b', 2, 10, 2, 10, DB_GET_BOTH);
close_dbs();
/* ********************************************************************** */
setup_dbs(dup_flags);
put(TRUE, 'c', 1, 1);
early_commit('c');
cget(TRUE, TRUE, 'a', 1, 1, 1, 1, DB_GET_BOTH);
cget(TRUE, TRUE, 'b', 1, 1, 1, 1, DB_GET_BOTH);
cdel(FALSE, TRUE, 'a');
close_dbs();
}
void test_dbdel(u_int32_t dup_flags) {
if (dup_flags != 0) {
if (verbose) printf("Pinhead! Can't dbdel now with duplicates!\n");
return;
}
/* If DB_DELETE_ANY changes to 0, then find is meaningful and
has to be fixed in test_dbdel*/
/* ********************************************************************** */
setup_dbs(dup_flags);
put(TRUE, 'c', 1, 1);
early_commit('c');
dbdel(TRUE, TRUE, 'a', 1);
cget(FALSE, TRUE, 'b', 1, 1, 1, 1, DB_GET_BOTH);
cget(FALSE, TRUE, 'b', 1, 4, 1, 4, DB_GET_BOTH);
cget(FALSE, TRUE, 'b', 1, 0, 1, 4, DB_GET_BOTH);
cget(TRUE, FALSE, 'b', 0, 0, 0, 0, DB_GET_BOTH);
cget(TRUE, FALSE, 'b', 2, 10, 2, 10, DB_GET_BOTH);
close_dbs();
/* ********************************************************************** */
setup_dbs(dup_flags);
dbdel(TRUE, TRUE, 'a', 1);
cget(FALSE, TRUE, 'b', 1, 1, 1, 1, DB_GET_BOTH);
cget(FALSE, TRUE, 'b', 1, 4, 1, 4, DB_GET_BOTH);
cget(FALSE, TRUE, 'b', 1, 0, 1, 4, DB_GET_BOTH);
cget(TRUE, FALSE, 'b', 0, 0, 0, 0, DB_GET_BOTH);
cget(TRUE, FALSE, 'b', 2, 10, 2, 10, DB_GET_BOTH);
close_dbs();
/* ********************************************************************** */
setup_dbs(dup_flags);
put(TRUE, 'c', 1, 1);
early_commit('c');
cget(TRUE, TRUE, 'b', 1, 1, 1, 1, DB_GET_BOTH);
dbdel(FALSE, TRUE, 'a', 1);
dbdel(TRUE, TRUE, 'a', 2);
dbdel(TRUE, TRUE, 'a', 0);
close_dbs();
}
void test_current(u_int32_t dup_flags) {
/* ********************************************************************** */
setup_dbs(dup_flags);
put(TRUE, 'a', 1, 1);
early_commit('a');
cget(TRUE, TRUE, 'b', 1, 1, 1, 1, DB_GET_BOTH);
cget(TRUE, TRUE, 'b', 1, 1, 1, 1, DB_CURRENT);
cdel(TRUE, TRUE, 'b');
cget(TRUE, FALSE, 'b', 1, 1, 1, 1, DB_CURRENT);
close_dbs();
}
void test(u_int32_t dup_flags) {
/* ********************************************************************** */
setup_dbs(dup_flags);
......@@ -467,6 +623,20 @@ void test(u_int32_t dup_flags) {
/* ********************************************************************** */
test_next(dup_flags, DB_NEXT);
test_next(dup_flags, DB_NEXT_NODUP);
/* ********************************************************************** */
test_prev(dup_flags, DB_PREV);
test_prev(dup_flags, DB_PREV_NODUP);
/* ********************************************************************** */
test_nextdup(dup_flags, DB_NEXT_DUP, 1);
#ifdef DB_PREV_DUP
test_nextdup(dup_flags, DB_PREV_DUP, -1);
#endif
/* ********************************************************************** */
test_cdel(dup_flags);
/* ********************************************************************** */
test_dbdel(dup_flags);
/* ********************************************************************** */
test_current(dup_flags);
}
......
......@@ -10,28 +10,37 @@
#include <sys/stat.h>
#include "test.h"
int main (int argc, char *argv[]) {
void test_autotxn(u_int32_t env_flags, u_int32_t db_flags) {
DB_ENV *env;
DB *db;
int r;
system("rm -rf " DIR);
mkdir(DIR, 0777);
r = db_env_create (&env, 0); assert(r==0);
r = env->open(env, DIR, DB_CREATE | DB_PRIVATE | DB_INIT_MPOOL | DB_INIT_LOG | DB_INIT_TXN | DB_INIT_LOCK, 0777); CKERR(r);
r = db_env_create (&env, 0); CKERR(r);
r = env->set_flags(env, env_flags, 1); CKERR(r);
r = env->open(env, DIR,
DB_CREATE | DB_PRIVATE | DB_INIT_MPOOL |
DB_INIT_LOG | DB_INIT_TXN | DB_INIT_LOCK, 0777); CKERR(r);
r = db_create(&db, env, 0);
CKERR(r);
db->set_errfile(db, stderr);
{
DB_TXN *x;
DB_TXN *x = NULL;
#ifdef USE_BDB
r = env->txn_begin(env, 0, &x, 0); assert(r==0);
r = db->open(db, x, "numbers.db", 0, DB_BTREE, DB_CREATE, 0);
assert(r==0);
#endif
r = db->open(db, x, "numbers.db", 0, DB_BTREE, DB_CREATE | db_flags, 0);
CKERR(r);
#ifdef USE_BDB
r = x->commit(x, 0); assert(r==0);
#endif
}
DB_TXN *x1, *x2;
r = env->txn_begin(env, 0, &x1, 0); assert(r==0);
r = env->txn_begin(env, 0, &x2, DB_TXN_NOWAIT); assert(r==0);
DB_TXN *x1, *x2 = NULL;
r = env->txn_begin(env, 0, &x1, DB_TXN_NOWAIT); CKERR(r);
#ifdef USE_BDB
r = env->txn_begin(env, 0, &x2, DB_TXN_NOWAIT); CKERR(r);
#endif
DBT k1,k2,v1,v2;
memset(&k1, 0, sizeof(DBT));
memset(&k2, 0, sizeof(DBT));
......@@ -43,9 +52,18 @@ int main (int argc, char *argv[]) {
v1.size = 6;
r = db->put(db, x1, &k1, &v1, 0); CKERR(r);
r = db->get(db, x2, &k2, &v2, 0); assert(r==DB_LOCK_DEADLOCK || r==DB_LOCK_NOTGRANTED);
r = x1->commit(x1, 0); assert(r==0);
r = x1->commit(x1, 0); CKERR(r);
#ifdef USE_BDB
r = x2->commit(x2, 0); assert(r==0);
r = db->close(db, 0); assert(r==0);
#endif
r = db->close(db, 0); CKERR(r);
r = env->close(env, 0); assert(r==0);
}
int main (int argc, char *argv[]) {
test_autotxn(DB_AUTO_COMMIT, DB_AUTO_COMMIT);
test_autotxn(0, DB_AUTO_COMMIT);
test_autotxn(DB_AUTO_COMMIT, 0);
test_autotxn(0, 0);
return 0;
}
......@@ -77,4 +77,46 @@ struct __toku_dbc_internal {
DB_TXN *txn;
};
/* *********************************************************
Ephemeral locking
********************************************************* */
void toku_ydb_lock();
void toku_ydb_unlock();
/* *********************************************************
Error handling
********************************************************* */
/* Exception handling */
/** Raise a C-like exception: currently returns an status code */
#define RAISE_EXCEPTION(status) {return status;}
/** Raise a C-like conditional exception: currently returns an status code
if condition is true */
#define RAISE_COND_EXCEPTION(cond, status) {if (cond) return status;}
/** Propagate the exception to the caller: if the status is non-zero,
returns it to the caller */
#define PROPAGATE_EXCEPTION(status) ({if (status != 0) return status;})
/** Handle a panicked environment: return EINVAL if the env is panicked */
#define HANDLE_PANICKED_ENV(env) \
RAISE_COND_EXCEPTION(toku_env_is_panicked(env), EINVAL)
/** Handle a panicked database: return EINVAL if the database env is panicked */
#define HANDLE_PANICKED_DB(db) HANDLE_PANICKED_ENV(db->dbenv)
/* */
int toku_ydb_do_error (const DB_ENV *, int, const char *, ...);
/* Location specific debug print-outs */
void toku_ydb_barf();
void toku_ydb_notef(const char *, ...);
/* Environment related errors */
int toku_env_is_panicked(DB_ENV *dbenv);
void toku_locked_env_err(const DB_ENV * env, int error, const char *fmt, ...);
#endif
This diff is collapsed.
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