Commit b2fc97a4 authored by Yoni Fogel's avatar Yoni Fogel

Addresses #350

Bugfix with releasing locks/unlocking a transaction.

DBC->c_get (DB_SET)
and DB->put (DB_YESOVERWRITE) now perform locking
Secondary dbs not included (behavior unknown).

Several tests added for c_get (DB_SET) and DB->put(DB_YESOVERWRITE).

Lock tree only created if INIT_TXN is enabled during env creation.


git-svn-id: file:///svn/tokudb@2191 c7de825b-a66e-492c-adef-691d508d4ae1
parent c1de576b
......@@ -570,7 +570,7 @@ static int __toku_lt_free_points(toku_lock_tree* tree, toku_range* to_insert,
u_int32_t i;
for (i = 0; i < numfound; i++) {
if (rt != NULL) {
r = toku_rt_delete(rt, to_insert);
r = toku_rt_delete(rt, &tree->buf[i]);
if (r!=0) return __toku_lt_panic(tree, r);
}
/*
......@@ -1207,6 +1207,8 @@ int toku_lt_unlock(toku_lock_tree* tree, DB_TXN* txn) {
ranges += toku_rt_get_size(selfwrite);
r = __toku_lt_border_delete(tree, selfwrite);
if (r!=0) return __toku_lt_panic(tree, r);
r = __toku_lt_free_contents(tree, selfwrite, NULL);
if (r!=0) return __toku_lt_panic(tree, r);
}
if (selfread || selfwrite) toku_rth_delete(tree->rth, txn);
......
......@@ -363,6 +363,7 @@ int toku_lt_acquire_range_write_lock(toku_lock_tree* tree, DB_TXN* txn,
* Returns:
* 0: Success.
* EINVAL: If (tree == NULL || txn == NULL).
* EINVAL: If panicking.
* *** Note that txn == NULL is not supported at this time.
*/
int toku_lt_unlock(toku_lock_tree* tree, DB_TXN* txn);
......
......@@ -42,7 +42,7 @@ endif
LIBNAME=libdb.$(LIBEXT)
# GCOV_FLAGS = -fprofile-arcs -ftest-coverage
CFLAGS += -Wall -Werror $(OPTFLAGS) -g $(GCOV_FLAGS)
CFLAGS += -Wall -Werror $(OPTFLAGS) -g3 -ggdb3 $(GCOV_FLAGS)
TDB_CPPFLAGS = -I../../include
......
......@@ -3,6 +3,7 @@
#include <stdint.h>
#include <stdio.h>
#include <db.h>
#include "../../newbrt/brttypes.h"
#ifndef DB_YESOVERWRITE
#define DB_YESOVERWRITE 0
......@@ -15,6 +16,7 @@ int verbose=0;
#define CKERR(r) ({ if (r!=0) fprintf(stderr, "%s:%d error %d %s\n", __FILE__, __LINE__, r, db_strerror(r)); assert(r==0); })
#define CKERR2(r,r2) ({ if (r!=r2) fprintf(stderr, "%s:%d error %d %s, expected %d\n", __FILE__, __LINE__, r, db_strerror(r), r2); assert(r==r2); })
#define CKERR2s(r,r2,r3) ({ if (r!=r2 && r!=r3) fprintf(stderr, "%s:%d error %d %s, expected %d or %d\n", __FILE__, __LINE__, r, db_strerror(r), r2,r3); assert(r==r2||r==r3); })
void parse_args (int argc, const char *argv[]) {
const char *argv0=argv[0];
......
/* -*- mode: C; c-basic-offset: 4 -*- */
#ident "Copyright (c) 2007 Tokutek Inc. All rights reserved."
#include <string.h>
#include <db.h>
#include <assert.h>
#include <errno.h>
#include <sys/stat.h>
#include "test.h"
// DIR is defined in the Makefile
int dbtcmp(DBT *dbt1, DBT *dbt2) {
int r;
r = dbt1->size - dbt2->size; if (r) return r;
return memcmp(dbt1->data, dbt2->data, dbt1->size);
}
DB *db;
DB_TXN* txns[(int)256];
DB_ENV* dbenv;
DBC* cursors[(int)256];
void put(BOOL success, char txn, int _key, int _data) {
assert(txns[(int)txn]);
int r;
DBT key;
DBT data;
r = db->put(db, txns[(int)txn],
dbt_init(&key, &_key, sizeof(int)),
dbt_init(&data, &_data, sizeof(int)),
DB_YESOVERWRITE);
if (success) CKERR(r);
else CKERR2s(r, DB_LOCK_DEADLOCK, DB_LOCK_NOTGRANTED);
}
void cget(BOOL success, BOOL find, char txn, int _key, int _data) {
assert(txns[(int)txn] && cursors[(int)txn]);
int r;
DBT key;
DBT data;
r = cursors[(int)txn]->c_get(cursors[(int)txn],
dbt_init(&key, &_key, sizeof(int)),
dbt_init(&data, &_data, sizeof(int)),
DB_SET);
if (success) {
if (find) CKERR(r);
else CKERR2(r, DB_NOTFOUND);
}
else CKERR2s(r, DB_LOCK_DEADLOCK, DB_LOCK_NOTGRANTED);
}
void init_txn(char name) {
int r;
assert(!txns[(int)name]);
r = dbenv->txn_begin(dbenv, NULL, &txns[(int)name], DB_TXN_NOWAIT);
CKERR(r);
assert(txns[(int)name]);
}
void init_dbc(char name) {
int r;
assert(!cursors[(int)name] && txns[(int)name]);
r = db->cursor(db, txns[(int)name], &cursors[(int)name], 0);
CKERR(r);
assert(cursors[(int)name]);
}
void commit_txn(char name) {
int r;
assert(txns[(int)name] && !cursors[(int)name]);
r = txns[(int)name]->commit(txns[(int)name], 0);
CKERR(r);
txns[(int)name] = NULL;
}
void abort_txn(char name) {
int r;
assert(txns[(int)name] && !cursors[(int)name]);
r = txns[(int)name]->abort(txns[(int)name]);
CKERR(r);
txns[(int)name] = NULL;
}
void close_dbc(char name) {
int r;
assert(cursors[(int)name]);
r = cursors[(int)name]->c_close(cursors[(int)name]);
CKERR(r);
cursors[(int)name] = NULL;
}
void early_commit(char name) {
assert(cursors[(int)name] && txns[(int)name]);
close_dbc(name);
commit_txn(name);
}
void early_abort(char name) {
assert(cursors[(int)name] && txns[(int)name]);
close_dbc(name);
abort_txn(name);
}
void setup_dbs(u_int32_t dup_flags) {
int r;
system("rm -rf " DIR);
mkdir(DIR, 0777);
dbenv = NULL;
db = NULL;
/* Open/create primary */
r = db_env_create(&dbenv, 0);
CKERR(r);
r = dbenv->open(dbenv, DIR, DB_CREATE | DB_PRIVATE | DB_INIT_MPOOL | DB_INIT_TXN, 0600);
CKERR(r);
r = db_create(&db, dbenv, 0);
CKERR(r);
if (dup_flags) {
r = db->set_flags(db, dup_flags);
CKERR(r);
}
r = db->open(db, NULL, "foobar.db", NULL, DB_BTREE, DB_CREATE, 0600);
CKERR(r);
char a;
for (a = 'a'; a <= 'z'; a++) {
init_txn(a);
init_dbc(a);
}
}
void close_dbs(void) {
char a;
for (a = 'a'; a <= 'z'; a++) {
if (cursors[(int)a]) close_dbc(a);
if (txns[(int)a]) commit_txn(a);
}
int r;
r = db->close(db, 0);
CKERR(r);
db = NULL;
r = dbenv->close(dbenv, 0);
CKERR(r);
dbenv = NULL;
}
void test(u_int32_t dup_flags) {
/* ********************************************************************** */
setup_dbs(dup_flags);
close_dbs();
/* ********************************************************************** */
setup_dbs(dup_flags);
cget(TRUE, FALSE, 'a', 1, 1);
close_dbs();
/* ********************************************************************** */
setup_dbs(dup_flags);
put(TRUE, 'a', 1, 1);
close_dbs();
/* ********************************************************************** */
setup_dbs(dup_flags);
cget(TRUE, FALSE, 'a', 1, 1);
cget(TRUE, FALSE, 'a', 2, 1);
close_dbs();
/* ********************************************************************** */
setup_dbs(dup_flags);
cget(TRUE, FALSE, 'a', 1, 1);
cget(TRUE, FALSE, 'a', 1, 1);
close_dbs();
/* ********************************************************************** */
setup_dbs(dup_flags);
cget(TRUE, FALSE, 'a', 1, 1);
cget(TRUE, FALSE, 'b', 2, 1);
close_dbs();
/* ********************************************************************** */
setup_dbs(dup_flags);
cget(TRUE, FALSE, 'a', 1, 1);
cget(TRUE, FALSE, 'b', 1, 1);
close_dbs();
/* ********************************************************************** */
setup_dbs(dup_flags);
cget(TRUE, FALSE, 'a', 1, 1);
cget(TRUE, FALSE, 'b', 1, 1);
put(FALSE, 'a', 1, 1);
early_commit('b');
put(TRUE, 'a', 1, 1);
cget(TRUE, TRUE, 'a', 1, 1);
cget(TRUE, FALSE, 'a', 2, 1);
cget(FALSE, TRUE, 'c', 1, 1);
early_commit('a');
cget(TRUE, TRUE, 'c', 1, 1);
close_dbs();
/* ********************************************************************** */
setup_dbs(dup_flags);
cget(TRUE, FALSE, 'a', 1, 1);
cget(TRUE, FALSE, 'b', 1, 1);
put(FALSE, 'a', 1, 1);
early_commit('b');
put(TRUE, 'a', 1, 1);
cget(TRUE, TRUE, 'a', 1, 1);
cget(TRUE, FALSE, 'a', 2, 1);
cget(FALSE, TRUE, 'c', 1, 1);
early_abort('a');
cget(TRUE, FALSE, 'c', 1, 1);
close_dbs();
/* ********************************************************************** */
}
int main() {
test(0);
test(DB_DUP | DB_DUPSORT);
return 0;
}
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