@ -419,6 +419,10 @@ DEFINE_int32(acquire_snapshot_one_in, 0,
" If non-zero, then acquires a snapshot once every N operations on "
" If non-zero, then acquires a snapshot once every N operations on "
" average. " ) ;
" average. " ) ;
DEFINE_bool ( compare_full_db_state_snapshot , false ,
" If set we compare state of entire db (in one of the threads) with "
" each snapshot. " ) ;
DEFINE_uint64 ( snapshot_hold_ops , 0 ,
DEFINE_uint64 ( snapshot_hold_ops , 0 ,
" If non-zero, then releases snapshots N operations after they're "
" If non-zero, then releases snapshots N operations after they're "
" acquired. " ) ;
" acquired. " ) ;
@ -651,6 +655,18 @@ static std::string Key(int64_t val) {
return big_endian_key ;
return big_endian_key ;
}
}
static bool GetIntVal ( std : : string big_endian_key , uint64_t * key_p ) {
unsigned int size_key = sizeof ( * key_p ) ;
assert ( big_endian_key . size ( ) = = size_key ) ;
std : : string little_endian_key ;
little_endian_key . resize ( size_key ) ;
for ( size_t i = 0 ; i < size_key ; + + i ) {
little_endian_key [ i ] = big_endian_key [ size_key - 1 - i ] ;
}
Slice little_endian_slice = Slice ( little_endian_key ) ;
return GetFixed64 ( & little_endian_slice , key_p ) ;
}
static std : : string StringToHex ( const std : : string & str ) {
static std : : string StringToHex ( const std : : string & str ) {
std : : string result = " 0x " ;
std : : string result = " 0x " ;
result . append ( Slice ( str ) . ToString ( true ) ) ;
result . append ( Slice ( str ) . ToString ( true ) ) ;
@ -1207,6 +1223,8 @@ struct ThreadState {
Status status ;
Status status ;
// The value of the Get
// The value of the Get
std : : string value ;
std : : string value ;
// optional state of all keys in the db
std : : vector < bool > * key_vec ;
} ;
} ;
std : : queue < std : : pair < uint64_t , SnapshotState > > snapshot_queue ;
std : : queue < std : : pair < uint64_t , SnapshotState > > snapshot_queue ;
@ -1713,6 +1731,21 @@ class StressTest {
" ) " ) ;
" ) " ) ;
}
}
}
}
if ( snap_state . key_vec ! = nullptr ) {
std : : unique_ptr < Iterator > iterator ( db - > NewIterator ( ropt ) ) ;
std : : unique_ptr < std : : vector < bool > > tmp_bitvec ( new std : : vector < bool > ( FLAGS_max_key ) ) ;
for ( iterator - > SeekToFirst ( ) ; iterator - > Valid ( ) ; iterator - > Next ( ) ) {
uint64_t key_val ;
if ( GetIntVal ( iterator - > key ( ) . ToString ( ) , & key_val ) ) {
( * tmp_bitvec . get ( ) ) [ key_val ] = true ;
}
}
if ( ! std : : equal ( snap_state . key_vec - > begin ( ) ,
snap_state . key_vec - > end ( ) ,
tmp_bitvec . get ( ) - > begin ( ) ) ) {
return Status : : Corruption ( " Found inconsistent keys at this snapshot " ) ;
}
}
return Status : : OK ( ) ;
return Status : : OK ( ) ;
}
}
@ -1796,6 +1829,7 @@ class StressTest {
while ( ! thread - > snapshot_queue . empty ( ) ) {
while ( ! thread - > snapshot_queue . empty ( ) ) {
db_ - > ReleaseSnapshot (
db_ - > ReleaseSnapshot (
thread - > snapshot_queue . front ( ) . second . snapshot ) ;
thread - > snapshot_queue . front ( ) . second . snapshot ) ;
delete thread - > snapshot_queue . front ( ) . second . key_vec ;
thread - > snapshot_queue . pop ( ) ;
thread - > snapshot_queue . pop ( ) ;
}
}
thread - > shared - > IncVotedReopen ( ) ;
thread - > shared - > IncVotedReopen ( ) ;
@ -1970,9 +2004,23 @@ class StressTest {
// will later read the same key before releasing the snapshot and verify
// will later read the same key before releasing the snapshot and verify
// that the results are the same.
// that the results are the same.
auto status_at = db_ - > Get ( ropt , column_family , key , & value_at ) ;
auto status_at = db_ - > Get ( ropt , column_family , key , & value_at ) ;
std : : vector < bool > * key_vec = nullptr ;
if ( FLAGS_compare_full_db_state_snapshot & &
( thread - > tid = = 0 ) ) {
key_vec = new std : : vector < bool > ( FLAGS_max_key ) ;
std : : unique_ptr < Iterator > iterator ( db_ - > NewIterator ( ropt ) ) ;
for ( iterator - > SeekToFirst ( ) ; iterator - > Valid ( ) ; iterator - > Next ( ) ) {
uint64_t key_val ;
if ( GetIntVal ( iterator - > key ( ) . ToString ( ) , & key_val ) ) {
( * key_vec ) [ key_val ] = true ;
}
}
}
ThreadState : : SnapshotState snap_state = {
ThreadState : : SnapshotState snap_state = {
snapshot , rand_column_family , column_family - > GetName ( ) ,
snapshot , rand_column_family , column_family - > GetName ( ) ,
keystr , status_at , value_at } ;
keystr , status_at , value_at , key_vec } ;
thread - > snapshot_queue . emplace (
thread - > snapshot_queue . emplace (
std : : min ( FLAGS_ops_per_thread - 1 , i + FLAGS_snapshot_hold_ops ) ,
std : : min ( FLAGS_ops_per_thread - 1 , i + FLAGS_snapshot_hold_ops ) ,
snap_state ) ;
snap_state ) ;
@ -1990,6 +2038,7 @@ class StressTest {
VerificationAbort ( shared , " Snapshot gave inconsistent state " , s ) ;
VerificationAbort ( shared , " Snapshot gave inconsistent state " , s ) ;
}
}
db_ - > ReleaseSnapshot ( snap_state . snapshot ) ;
db_ - > ReleaseSnapshot ( snap_state . snapshot ) ;
delete snap_state . key_vec ;
thread - > snapshot_queue . pop ( ) ;
thread - > snapshot_queue . pop ( ) ;
}
}