@ -43,13 +43,10 @@ INSTANTIATE_TEST_CASE_P(
DBAsBaseDB , TransactionTest ,
DBAsBaseDB , TransactionTest ,
: : testing : : Values ( std : : make_tuple ( false , false , WRITE_COMMITTED ) ,
: : testing : : Values ( std : : make_tuple ( false , false , WRITE_COMMITTED ) ,
std : : make_tuple ( false , true , WRITE_COMMITTED ) ,
std : : make_tuple ( false , true , WRITE_COMMITTED ) ,
std : : make_tuple ( false , false , WRITE_PREPARED ) ,
std : : make_tuple ( false , true , WRITE_PREPARED ) ) ) ;
std : : make_tuple ( false , true , WRITE_PREPARED ) ) ) ;
INSTANTIATE_TEST_CASE_P (
INSTANTIATE_TEST_CASE_P (
StackableDBAsBaseDB , TransactionTest ,
StackableDBAsBaseDB , TransactionTest ,
: : testing : : Values ( std : : make_tuple ( true , false , WRITE_COMMITTED ) ,
: : testing : : Values ( std : : make_tuple ( true , true , WRITE_COMMITTED ) ,
std : : make_tuple ( true , true , WRITE_COMMITTED ) ,
std : : make_tuple ( true , false , WRITE_PREPARED ) ,
std : : make_tuple ( true , true , WRITE_PREPARED ) ) ) ;
std : : make_tuple ( true , true , WRITE_PREPARED ) ) ) ;
INSTANTIATE_TEST_CASE_P (
INSTANTIATE_TEST_CASE_P (
MySQLStyleTransactionTest , MySQLStyleTransactionTest ,
MySQLStyleTransactionTest , MySQLStyleTransactionTest ,
@ -707,112 +704,131 @@ TEST_P(TransactionTest, CommitTimeBatchFailTest) {
}
}
TEST_P ( TransactionTest , SimpleTwoPhaseTransactionTest ) {
TEST_P ( TransactionTest , SimpleTwoPhaseTransactionTest ) {
WriteOptions write_options ;
for ( bool cwb4recovery : { true , false } ) {
ReadOptions read_options ;
ReOpen ( ) ;
WriteOptions write_options ;
ReadOptions read_options ;
TransactionOptions txn_options ;
TransactionOptions txn_options ;
txn_options . use_only_the_last_commit_time_batch_for_recovery = cwb4recovery ;
string value ;
string value ;
Status s ;
Status s ;
DBImpl * db_impl = reinterpret_cast < DBImpl * > ( db - > GetRootDB ( ) ) ;
DBImpl * db_impl = reinterpret_cast < DBImpl * > ( db - > GetRootDB ( ) ) ;
Transaction * txn = db - > BeginTransaction ( write_options , txn_options ) ;
Transaction * txn = db - > BeginTransaction ( write_options , txn_options ) ;
s = txn - > SetName ( " xid " ) ;
s = txn - > SetName ( " xid " ) ;
ASSERT_OK ( s ) ;
ASSERT_OK ( s ) ;
ASSERT_EQ ( db - > GetTransactionByName ( " xid " ) , txn ) ;
ASSERT_EQ ( db - > GetTransactionByName ( " xid " ) , txn ) ;
// transaction put
// transaction put
s = txn - > Put ( Slice ( " foo " ) , Slice ( " bar " ) ) ;
s = txn - > Put ( Slice ( " foo " ) , Slice ( " bar " ) ) ;
ASSERT_OK ( s ) ;
ASSERT_OK ( s ) ;
ASSERT_EQ ( 1 , txn - > GetNumPuts ( ) ) ;
ASSERT_EQ ( 1 , txn - > GetNumPuts ( ) ) ;
// regular db put
// regular db put
s = db - > Put ( write_options , Slice ( " foo2 " ) , Slice ( " bar2 " ) ) ;
s = db - > Put ( write_options , Slice ( " foo2 " ) , Slice ( " bar2 " ) ) ;
ASSERT_OK ( s ) ;
ASSERT_OK ( s ) ;
ASSERT_EQ ( 1 , txn - > GetNumPuts ( ) ) ;
ASSERT_EQ ( 1 , txn - > GetNumPuts ( ) ) ;
// regular db read
// regular db read
db - > Get ( read_options , " foo2 " , & value ) ;
db - > Get ( read_options , " foo2 " , & value ) ;
ASSERT_EQ ( value , " bar2 " ) ;
ASSERT_EQ ( value , " bar2 " ) ;
// commit time put
// commit time put
txn - > GetCommitTimeWriteBatch ( ) - > Put ( Slice ( " gtid " ) , Slice ( " dogs " ) ) ;
txn - > GetCommitTimeWriteBatch ( ) - > Put ( Slice ( " gtid " ) , Slice ( " dogs " ) ) ;
txn - > GetCommitTimeWriteBatch ( ) - > Put ( Slice ( " gtid2 " ) , Slice ( " cats " ) ) ;
txn - > GetCommitTimeWriteBatch ( ) - > Put ( Slice ( " gtid2 " ) , Slice ( " cats " ) ) ;
// nothing has been prepped yet
// nothing has been prepped yet
ASSERT_EQ ( db_impl - > TEST_FindMinLogContainingOutstandingPrep ( ) , 0 ) ;
ASSERT_EQ ( db_impl - > TEST_FindMinLogContainingOutstandingPrep ( ) , 0 ) ;
s = txn - > Prepare ( ) ;
s = txn - > Prepare ( ) ;
ASSERT_OK ( s ) ;
ASSERT_OK ( s ) ;
// data not im mem yet
// data not im mem yet
s = db - > Get ( read_options , Slice ( " foo " ) , & value ) ;
s = db - > Get ( read_options , Slice ( " foo " ) , & value ) ;
ASSERT_TRUE ( s . IsNotFound ( ) ) ;
ASSERT_TRUE ( s . IsNotFound ( ) ) ;
s = db - > Get ( read_options , Slice ( " gtid " ) , & value ) ;
s = db - > Get ( read_options , Slice ( " gtid " ) , & value ) ;
ASSERT_TRUE ( s . IsNotFound ( ) ) ;
ASSERT_TRUE ( s . IsNotFound ( ) ) ;
// find trans in list of prepared transactions
// find trans in list of prepared transactions
std : : vector < Transaction * > prepared_trans ;
std : : vector < Transaction * > prepared_trans ;
db - > GetAllPreparedTransactions ( & prepared_trans ) ;
db - > GetAllPreparedTransactions ( & prepared_trans ) ;
ASSERT_EQ ( prepared_trans . size ( ) , 1 ) ;
ASSERT_EQ ( prepared_trans . size ( ) , 1 ) ;
ASSERT_EQ ( prepared_trans . front ( ) - > GetName ( ) , " xid " ) ;
ASSERT_EQ ( prepared_trans . front ( ) - > GetName ( ) , " xid " ) ;
auto log_containing_prep =
auto log_containing_prep =
db_impl - > TEST_FindMinLogContainingOutstandingPrep ( ) ;
db_impl - > TEST_FindMinLogContainingOutstandingPrep ( ) ;
ASSERT_GT ( log_containing_prep , 0 ) ;
ASSERT_GT ( log_containing_prep , 0 ) ;
// make commit
// make commit
s = txn - > Commit ( ) ;
s = txn - > Commit ( ) ;
ASSERT_OK ( s ) ;
ASSERT_OK ( s ) ;
// value is now available
// value is now available
s = db - > Get ( read_options , " foo " , & value ) ;
s = db - > Get ( read_options , " foo " , & value ) ;
ASSERT_OK ( s ) ;
ASSERT_OK ( s ) ;
ASSERT_EQ ( value , " bar " ) ;
ASSERT_EQ ( value , " bar " ) ;
s = db - > Get ( read_options , " gtid " , & value ) ;
if ( ! cwb4recovery ) {
ASSERT_OK ( s ) ;
s = db - > Get ( read_options , " gtid " , & value ) ;
ASSERT_EQ ( value , " dogs " ) ;
ASSERT_OK ( s ) ;
ASSERT_EQ ( value , " dogs " ) ;
s = db - > Get ( read_options , " gtid2 " , & value ) ;
s = db - > Get ( read_options , " gtid2 " , & value ) ;
ASSERT_OK ( s ) ;
ASSERT_OK ( s ) ;
ASSERT_EQ ( value , " cats " ) ;
ASSERT_EQ ( value , " cats " ) ;
}
// we already committed
// we already committed
s = txn - > Commit ( ) ;
s = txn - > Commit ( ) ;
ASSERT_EQ ( s , Status : : InvalidArgument ( ) ) ;
ASSERT_EQ ( s , Status : : InvalidArgument ( ) ) ;
// no longer is prpared results
// no longer is prpared results
db - > GetAllPreparedTransactions ( & prepared_trans ) ;
db - > GetAllPreparedTransactions ( & prepared_trans ) ;
ASSERT_EQ ( prepared_trans . size ( ) , 0 ) ;
ASSERT_EQ ( prepared_trans . size ( ) , 0 ) ;
ASSERT_EQ ( db - > GetTransactionByName ( " xid " ) , nullptr ) ;
ASSERT_EQ ( db - > GetTransactionByName ( " xid " ) , nullptr ) ;
// heap should not care about prepared section anymore
// heap should not care about prepared section anymore
ASSERT_EQ ( db_impl - > TEST_FindMinLogContainingOutstandingPrep ( ) , 0 ) ;
ASSERT_EQ ( db_impl - > TEST_FindMinLogContainingOutstandingPrep ( ) , 0 ) ;
switch ( txn_db_options . write_policy ) {
switch ( txn_db_options . write_policy ) {
case WRITE_COMMITTED :
case WRITE_COMMITTED :
// but now our memtable should be referencing the prep section
// but now our memtable should be referencing the prep section
ASSERT_EQ ( log_containing_prep ,
ASSERT_EQ ( log_containing_prep ,
db_impl - > TEST_FindMinPrepLogReferencedByMemTable ( ) ) ;
db_impl - > TEST_FindMinPrepLogReferencedByMemTable ( ) ) ;
break ;
break ;
case WRITE_PREPARED :
case WRITE_PREPARED :
case WRITE_UNPREPARED :
case WRITE_UNPREPARED :
// In these modes memtable do not ref the prep sections
// In these modes memtable do not ref the prep sections
ASSERT_EQ ( 0 , db_impl - > TEST_FindMinPrepLogReferencedByMemTable ( ) ) ;
ASSERT_EQ ( 0 , db_impl - > TEST_FindMinPrepLogReferencedByMemTable ( ) ) ;
break ;
break ;
default :
default :
assert ( false ) ;
assert ( false ) ;
}
}
db_impl - > TEST_FlushMemTable ( true ) ;
db_impl - > TEST_FlushMemTable ( true ) ;
// after memtable flush we can now relese the log
// after memtable flush we can now relese the log
ASSERT_EQ ( 0 , db_impl - > TEST_FindMinPrepLogReferencedByMemTable ( ) ) ;
ASSERT_EQ ( 0 , db_impl - > TEST_FindMinPrepLogReferencedByMemTable ( ) ) ;
delete txn ;
delete txn ;
if ( cwb4recovery ) {
// kill and reopen to trigger recovery
s = ReOpenNoDelete ( ) ;
ASSERT_OK ( s ) ;
s = db - > Get ( read_options , " gtid " , & value ) ;
ASSERT_OK ( s ) ;
ASSERT_EQ ( value , " dogs " ) ;
s = db - > Get ( read_options , " gtid2 " , & value ) ;
ASSERT_OK ( s ) ;
ASSERT_EQ ( value , " cats " ) ;
}
}
}
}
TEST_P ( TransactionTest , TwoPhaseNameTest ) {
TEST_P ( TransactionTest , TwoPhaseNameTest ) {
@ -873,44 +889,67 @@ TEST_P(TransactionTest, TwoPhaseNameTest) {
}
}
TEST_P ( TransactionTest , TwoPhaseEmptyWriteTest ) {
TEST_P ( TransactionTest , TwoPhaseEmptyWriteTest ) {
Status s ;
for ( bool cwb4recovery : { true , false } ) {
std : : string value ;
for ( bool test_with_empty_wal : { true , false } ) {
if ( ! cwb4recovery & & test_with_empty_wal ) {
WriteOptions write_options ;
continue ;
ReadOptions read_options ;
}
TransactionOptions txn_options ;
ReOpen ( ) ;
Transaction * txn1 = db - > BeginTransaction ( write_options , txn_options ) ;
Status s ;
ASSERT_TRUE ( txn1 ) ;
std : : string value ;
Transaction * txn2 = db - > BeginTransaction ( write_options , txn_options ) ;
ASSERT_TRUE ( txn2 ) ;
WriteOptions write_options ;
ReadOptions read_options ;
s = txn1 - > SetName ( " joe " ) ;
TransactionOptions txn_options ;
ASSERT_OK ( s ) ;
txn_options . use_only_the_last_commit_time_batch_for_recovery =
cwb4recovery ;
s = txn2 - > SetName ( " bob " ) ;
Transaction * txn1 = db - > BeginTransaction ( write_options , txn_options ) ;
ASSERT_OK ( s ) ;
ASSERT_TRUE ( txn1 ) ;
Transaction * txn2 = db - > BeginTransaction ( write_options , txn_options ) ;
ASSERT_TRUE ( txn2 ) ;
s = txn1 - > SetName ( " joe " ) ;
ASSERT_OK ( s ) ;
s = txn1 - > Prepare ( ) ;
s = txn2 - > SetName ( " bob " ) ;
ASSERT_OK ( s ) ;
ASSERT_OK ( s ) ;
s = txn1 - > Commit ( ) ;
s = txn1 - > Prepare ( ) ;
ASSERT_OK ( s ) ;
ASSERT_OK ( s ) ;
delete txn1 ;
s = txn1 - > Commit ( ) ;
ASSERT_OK ( s ) ;
txn2 - > GetCommitTimeWriteBatch ( ) - > Put ( Slice ( " foo " ) , Slice ( " bar " ) ) ;
delete txn1 ;
s = txn2 - > Prepare ( ) ;
txn2 - > GetCommitTimeWriteBatch ( ) - > Put ( Slice ( " foo " ) , Slice ( " bar " ) ) ;
ASSERT_OK ( s ) ;
s = txn2 - > Commit ( ) ;
s = txn2 - > Prepare ( ) ;
ASSERT_OK ( s ) ;
ASSERT_OK ( s ) ;
s = db - > Get ( read_options , " foo " , & value ) ;
s = txn2 - > Commit ( ) ;
ASSERT_OK ( s ) ;
ASSERT_OK ( s ) ;
ASSERT_EQ ( value , " bar " ) ;
delete txn2 ;
delete txn2 ;
if ( ! cwb4recovery ) {
s = db - > Get ( read_options , " foo " , & value ) ;
ASSERT_OK ( s ) ;
ASSERT_EQ ( value , " bar " ) ;
} else {
if ( test_with_empty_wal ) {
DBImpl * db_impl = reinterpret_cast < DBImpl * > ( db - > GetRootDB ( ) ) ;
db_impl - > TEST_FlushMemTable ( true ) ;
}
db - > FlushWAL ( true ) ;
// kill and reopen to trigger recovery
s = ReOpenNoDelete ( ) ;
ASSERT_OK ( s ) ;
s = db - > Get ( read_options , " foo " , & value ) ;
ASSERT_OK ( s ) ;
ASSERT_EQ ( value , " bar " ) ;
}
}
}
}
}
TEST_P ( TransactionTest , TwoPhaseExpirationTest ) {
TEST_P ( TransactionTest , TwoPhaseExpirationTest ) {