mirror of
https://github.com/MariaDB/server.git
synced 2025-01-22 14:54:20 +01:00
Addresses #1125 refs [t:1125] Add two tests for nested transactions at ydb layer.
Shuffled around some constants at the newbrt layer, extracted tokuconst.h git-svn-id: file:///svn/toku/tokudb@13670 c7de825b-a66e-492c-adef-691d508d4ae1
This commit is contained in:
parent
c64a572566
commit
3e9fcd103b
4 changed files with 277 additions and 34 deletions
16
newbrt/tokuconst.h
Normal file
16
newbrt/tokuconst.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
/* -*- mode: C; c-basic-offset: 4 -*- */
|
||||
#ident "Copyright (c) 2009 Tokutek Inc. All rights reserved."
|
||||
|
||||
#ifndef TOKUCONST_H
|
||||
#define TOKUCONST_H
|
||||
/* The number of transaction ids stored in the xids structure is
|
||||
* represented by an 8-bit value. The value 255 is reserved.
|
||||
* The constant MAX_NESTED_TRANSACTIONS is one less because
|
||||
* one slot in the packed leaf entry is used for the implicit
|
||||
* root transaction (id 0).
|
||||
*/
|
||||
enum {MAX_NESTED_TRANSACTIONS = 253};
|
||||
enum {MAX_TRANSACTION_RECORDS = MAX_NESTED_TRANSACTIONS + 1};
|
||||
|
||||
#endif
|
||||
|
|
@ -19,16 +19,7 @@
|
|||
|
||||
#include "rbuf.h"
|
||||
#include "wbuf.h"
|
||||
/* The number of transaction ids stored in the xids structure is
|
||||
* represented by an 8-bit value. The value 255 is reserved.
|
||||
* The constant MAX_NESTED_TRANSACTIONS is one less because
|
||||
* one slot in the packed leaf entry is used for the implicit
|
||||
* root transaction (id 0).
|
||||
*/
|
||||
enum {MAX_NESTED_TRANSACTIONS = 253};
|
||||
enum {MAX_TRANSACTION_RECORDS = MAX_NESTED_TRANSACTIONS + 1};
|
||||
|
||||
|
||||
#include "tokuconst.h"
|
||||
//Retrieve an XIDS representing the root transaction.
|
||||
XIDS xids_get_root_xids(void);
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* -*- mode: C; c-basic-offset: 4 -*- */
|
||||
|
||||
#ident "Copyright (c) 200o Tokutek Inc. All rights reserved."
|
||||
#ident "Copyright (c) 2009 Tokutek Inc. All rights reserved."
|
||||
#include "test.h"
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
@ -9,10 +8,8 @@
|
|||
#include <memory.h>
|
||||
#include <sys/stat.h>
|
||||
#include <db.h>
|
||||
// #include "xids.h"
|
||||
|
||||
// fix later (maybe pass in desired depth as a param?)
|
||||
#define MAX_NEST 250
|
||||
#include "tokuconst.h"
|
||||
#define MAX_NEST MAX_NESTED_TRANSACTIONS
|
||||
|
||||
|
||||
/*********************
|
||||
|
@ -26,7 +23,7 @@
|
|||
* - insert, query
|
||||
*
|
||||
* for i = 1 to MAX
|
||||
* - txnid = txns[MAX - i]
|
||||
* - txnid = txns[MAX - i - 1]
|
||||
* - commit or abort(txnid), query
|
||||
*
|
||||
*/
|
||||
|
@ -51,6 +48,8 @@ setup_db (void) {
|
|||
r = env->txn_begin(env, 0, &txn, 0); CKERR(r);
|
||||
|
||||
r = db_create(&db, env, 0); CKERR(r);
|
||||
r = db->set_bt_compare(db, int_dbt_cmp); CKERR(r);
|
||||
r = db->set_dup_compare(db, int_dbt_cmp); CKERR(r);
|
||||
r = db->open(db, txn, "test.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
|
||||
r = txn->commit(txn, 0); CKERR(r);
|
||||
}
|
||||
|
@ -64,42 +63,71 @@ close_db (void) {
|
|||
r=env->close(env, 0); CKERR(r);
|
||||
}
|
||||
|
||||
int
|
||||
static void
|
||||
test_txn_nesting (int depth) {
|
||||
int r;
|
||||
if (verbose) { fprintf(stderr, "%s (%s):%d [depth = %d]\n", __FILE__, __FUNCTION__, __LINE__, depth); fflush(stderr); }
|
||||
|
||||
DBT key, val;
|
||||
DBT key, val, observed_val;
|
||||
dbt_init(&observed_val, NULL, 0);
|
||||
int i;
|
||||
|
||||
DB_TXN * txns[depth];
|
||||
DB_TXN * parent = NULL;
|
||||
|
||||
int vals[depth];
|
||||
|
||||
int mykey = 42;
|
||||
dbt_init(&key, &mykey, sizeof mykey);
|
||||
|
||||
|
||||
for (i = 0; i < depth; i++){
|
||||
int r;
|
||||
DB_TXN * this_txn;
|
||||
|
||||
|
||||
if (verbose)
|
||||
printf("Begin txn at level %d\n", i);
|
||||
dbt_init(&key, &i, sizeof i);
|
||||
dbt_init(&val, &i, sizeof i);
|
||||
vals[i] = i;
|
||||
dbt_init(&val, &vals[i], sizeof i);
|
||||
r = env->txn_begin(env, parent, &this_txn, 0); CKERR(r);
|
||||
txns[i] = this_txn;
|
||||
parent = this_txn; // will be parent in next iteration
|
||||
r = db->put(db, this_txn, &key, &val, 0); CKERR(r);
|
||||
r = db->put(db, this_txn, &key, &val, DB_YESOVERWRITE); CKERR(r);
|
||||
|
||||
r = db->get(db, this_txn, &key, &observed_val, 0); CKERR(r);
|
||||
assert(int_dbt_cmp(db, &val, &observed_val) == 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < depth; i++) {
|
||||
int r;
|
||||
DB_TXN * this_txn;
|
||||
int which_val = depth-1;
|
||||
for (i = depth-1; i >= 0; i--) {
|
||||
//Query, verify the correct value is stored.
|
||||
//Close (abort/commit) innermost transaction
|
||||
|
||||
if (verbose)
|
||||
printf("Commit txn at level %d\n", i);
|
||||
this_txn = txns[depth - i - 1];
|
||||
r = this_txn->commit(this_txn, DB_TXN_NOSYNC); CKERR(r);
|
||||
if (verbose)
|
||||
printf("Commit txn at level %d\n", i);
|
||||
|
||||
dbt_init(&observed_val, NULL, 0);
|
||||
r = db->get(db, txns[i], &key, &observed_val, 0); CKERR(r);
|
||||
dbt_init(&val, &vals[which_val], sizeof i);
|
||||
assert(int_dbt_cmp(db, &val, &observed_val) == 0);
|
||||
|
||||
if (i % 2) {
|
||||
r = txns[i]->commit(txns[i], DB_TXN_NOSYNC); CKERR(r);
|
||||
//which_val does not change (it gets promoted)
|
||||
}
|
||||
else {
|
||||
r = txns[i]->abort(txns[i]); CKERR(r);
|
||||
which_val = i - 1;
|
||||
}
|
||||
txns[i] = NULL;
|
||||
}
|
||||
//Query, verify the correct value is stored.
|
||||
r = db->get(db, NULL, &key, &observed_val, 0);
|
||||
if (which_val == -1) CKERR2(r, DB_NOTFOUND);
|
||||
else {
|
||||
CKERR(r);
|
||||
dbt_init(&val, &vals[which_val], sizeof i);
|
||||
assert(int_dbt_cmp(db, &val, &observed_val) == 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
208
src/tests/test_txn_nested2.c
Normal file
208
src/tests/test_txn_nested2.c
Normal file
|
@ -0,0 +1,208 @@
|
|||
/* -*- mode: C; c-basic-offset: 4 -*- */
|
||||
#ident "Copyright (c) 2009 Tokutek Inc. All rights reserved."
|
||||
#include "test.h"
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <memory.h>
|
||||
#include <sys/stat.h>
|
||||
#include <db.h>
|
||||
#include "tokuconst.h"
|
||||
#define MAX_NEST MAX_TRANSACTION_RECORDS
|
||||
#define MAX_SIZE MAX_TRANSACTION_RECORDS
|
||||
|
||||
u_int8_t valbufs[MAX_NEST][MAX_SIZE];
|
||||
DBT vals [MAX_NEST];
|
||||
u_int8_t keybuf [MAX_SIZE];
|
||||
DBT key;
|
||||
DB_TXN *txns [MAX_NEST];
|
||||
DB_TXN *txn_query;
|
||||
int which_expected;
|
||||
|
||||
static void
|
||||
fillrandom(u_int8_t buf[MAX_SIZE], u_int32_t length) {
|
||||
assert(length < MAX_SIZE);
|
||||
u_int32_t i;
|
||||
for (i = 0; i < length; i++) {
|
||||
buf[i] = random() & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
initialize_values (void) {
|
||||
int nest_level;
|
||||
for (nest_level = 0; nest_level < MAX_NEST; nest_level++) {
|
||||
fillrandom(valbufs[nest_level], nest_level);
|
||||
dbt_init(&vals[nest_level], &valbufs[nest_level][0], nest_level);
|
||||
}
|
||||
u_int32_t len = random() % MAX_SIZE;
|
||||
fillrandom(keybuf, len);
|
||||
dbt_init(&vals[nest_level], &keybuf[0], len);
|
||||
}
|
||||
|
||||
|
||||
/*********************
|
||||
*
|
||||
* Purpose of this test is to verify nested transactions (support right number of possible values)
|
||||
for test = 1 to MAX
|
||||
create empty db
|
||||
for nesting_level = 1 to MAX
|
||||
- begin txn
|
||||
- insert a value/len unique to this txn
|
||||
- query
|
||||
abort txn (MAX-test) (test-th innermost) // for test=1 don't abort anything
|
||||
commit txn 1 (outermost) // for test = MAX don't commit anything
|
||||
query // only query that really matters
|
||||
*/
|
||||
|
||||
static DB *db;
|
||||
static DB_ENV *env;
|
||||
|
||||
static void
|
||||
setup_db (void) {
|
||||
system("rm -rf " ENVDIR);
|
||||
toku_os_mkdir(ENVDIR, S_IRWXU+S_IRWXG+S_IRWXO);
|
||||
|
||||
int r;
|
||||
r = db_env_create(&env, 0); CKERR(r);
|
||||
r = env->set_data_dir(env, ENVDIR);
|
||||
r = env->set_lg_dir(env, ENVDIR);
|
||||
r = env->open(env, 0, DB_INIT_MPOOL | DB_INIT_LOG | DB_INIT_LOCK | DB_INIT_TXN | DB_PRIVATE | DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO);
|
||||
CKERR(r);
|
||||
|
||||
{
|
||||
DB_TXN *txn = 0;
|
||||
r = env->txn_begin(env, 0, &txn, 0); CKERR(r);
|
||||
|
||||
r = db_create(&db, env, 0); CKERR(r);
|
||||
r = db->open(db, txn, "test.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r);
|
||||
r = txn->commit(txn, 0); CKERR(r);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
close_db (void) {
|
||||
int r;
|
||||
r = txn_query->commit(txn_query, 0);
|
||||
CKERR(r);
|
||||
r=db->close(db, 0); CKERR(r);
|
||||
r=env->close(env, 0); CKERR(r);
|
||||
}
|
||||
|
||||
static void
|
||||
verify_val(void) {
|
||||
int r;
|
||||
DBT observed_val;
|
||||
dbt_init(&observed_val, NULL, 0);
|
||||
r = db->get(db, txn_query, &key, &observed_val, 0);
|
||||
if (which_expected==-1)
|
||||
CKERR2(r, DB_NOTFOUND);
|
||||
else {
|
||||
CKERR(r);
|
||||
assert(observed_val.size == vals[which_expected].size);
|
||||
assert(memcmp(observed_val.data, vals[which_expected].data, vals[which_expected].size) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
initialize_db(void) {
|
||||
int r;
|
||||
r = env->txn_begin(env, NULL, &txn_query, DB_READ_UNCOMMITTED);
|
||||
CKERR(r);
|
||||
which_expected = -1;
|
||||
verify_val();
|
||||
//Put in a 'committed value'
|
||||
r = db->put(db, NULL, &key, &vals[0], DB_YESOVERWRITE);
|
||||
CKERR(r);
|
||||
txns[0] = NULL;
|
||||
|
||||
int i;
|
||||
which_expected = 0;
|
||||
for (i = 1; i < MAX_NEST; i++) {
|
||||
r = env->txn_begin(env, txns[i-1], &txns[i], 0);
|
||||
CKERR(r);
|
||||
verify_val();
|
||||
r = db->put(db, txns[i], &key, &vals[i], DB_YESOVERWRITE);
|
||||
CKERR(r);
|
||||
which_expected = i;
|
||||
verify_val();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_txn_nested_shortcut (int abort_at_depth) {
|
||||
int r;
|
||||
if (verbose) { fprintf(stderr, "%s (%s):%d [abortdepth = %d]\n", __FILE__, __FUNCTION__, __LINE__, abort_at_depth); fflush(stderr); }
|
||||
|
||||
setup_db();
|
||||
initialize_db();
|
||||
|
||||
which_expected = MAX_NEST-1;
|
||||
verify_val();
|
||||
|
||||
assert(abort_at_depth > 0); //Cannot abort 'committed' txn.
|
||||
assert(abort_at_depth <= MAX_NEST); //must be in range
|
||||
if (abort_at_depth < MAX_NEST) {
|
||||
//MAX_NEST means no abort
|
||||
DB_TXN *abort_txn = txns[abort_at_depth];
|
||||
r = abort_txn->abort(abort_txn);
|
||||
CKERR(r);
|
||||
which_expected = abort_at_depth - 1;
|
||||
verify_val();
|
||||
}
|
||||
if (abort_at_depth > 1) {
|
||||
//abort_at_depth 1 means abort the whole thing (nothing left to commit)
|
||||
DB_TXN *commit_txn = txns[1];
|
||||
r = commit_txn->commit(commit_txn, DB_TXN_NOSYNC);
|
||||
CKERR(r);
|
||||
verify_val();
|
||||
}
|
||||
close_db();
|
||||
}
|
||||
|
||||
static void
|
||||
test_txn_nested_slow (int abort_at_depth) {
|
||||
int r;
|
||||
if (verbose) { fprintf(stderr, "%s (%s):%d [abortdepth = %d]\n", __FILE__, __FUNCTION__, __LINE__, abort_at_depth); fflush(stderr); }
|
||||
|
||||
setup_db();
|
||||
initialize_db();
|
||||
|
||||
which_expected = MAX_NEST-1;
|
||||
verify_val();
|
||||
|
||||
assert(abort_at_depth > 0); //Cannot abort 'committed' txn.
|
||||
assert(abort_at_depth <= MAX_NEST); //must be in range
|
||||
//MAX_NEST means no abort
|
||||
int nest;
|
||||
for (nest = MAX_NEST - 1; nest >= abort_at_depth; nest--) {
|
||||
DB_TXN *abort_txn = txns[nest];
|
||||
r = abort_txn->abort(abort_txn);
|
||||
CKERR(r);
|
||||
which_expected = nest - 1;
|
||||
verify_val();
|
||||
}
|
||||
//which_expected does not change anymore
|
||||
for (nest = abort_at_depth-1; nest > 0; nest--) {
|
||||
DB_TXN *commit_txn = txns[nest];
|
||||
r = commit_txn->commit(commit_txn, DB_TXN_NOSYNC);
|
||||
CKERR(r);
|
||||
verify_val();
|
||||
}
|
||||
close_db();
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
test_main(int argc, char *argv[]) {
|
||||
parse_args(argc, argv);
|
||||
initialize_values();
|
||||
int i;
|
||||
for (i = 1; i <= MAX_NEST; i++) {
|
||||
test_txn_nested_shortcut(i);
|
||||
test_txn_nested_slow(i);
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Reference in a new issue