@ -18,8 +18,8 @@ class BatchedOpsStressTest : public StressTest {
bool IsStateTracked ( ) const override { return false ; }
bool IsStateTracked ( ) const override { return false ; }
// Given a key K and value V, this puts ("0"+K, "0"+V ), ("1"+K, "1"+V ), ...
// Given a key K and value V, this puts ("0"+K, V+ "0"), ("1"+K, V+ "1"), ...,
// ("9"+K, "9"+V ) in DB atomically i.e in a single batch.
// ("9"+K, V+ "9") in DB atomically i.e in a single batch.
// Also refer BatchedOpsStressTest::TestGet
// Also refer BatchedOpsStressTest::TestGet
Status TestPut ( ThreadState * thread , WriteOptions & write_opts ,
Status TestPut ( ThreadState * thread , WriteOptions & write_opts ,
const ReadOptions & /* read_opts */ ,
const ReadOptions & /* read_opts */ ,
@ -29,12 +29,12 @@ class BatchedOpsStressTest : public StressTest {
assert ( ! rand_column_families . empty ( ) ) ;
assert ( ! rand_column_families . empty ( ) ) ;
assert ( ! rand_keys . empty ( ) ) ;
assert ( ! rand_keys . empty ( ) ) ;
const std : : string key_suffix = Key ( rand_keys [ 0 ] ) ;
const std : : string key_body = Key ( rand_keys [ 0 ] ) ;
const uint32_t value_base =
const uint32_t value_base =
thread - > rand . Next ( ) % thread - > shared - > UNKNOWN_SENTINEL ;
thread - > rand . Next ( ) % thread - > shared - > UNKNOWN_SENTINEL ;
const size_t sz = GenerateValue ( value_base , value , sizeof ( value ) ) ;
const size_t sz = GenerateValue ( value_base , value , sizeof ( value ) ) ;
const std : : string value_suffix = Slice ( value , sz ) . ToString ( ) ;
const std : : string value_body = Slice ( value , sz ) . ToString ( ) ;
WriteBatch batch ( 0 /* reserved_bytes */ , 0 /* max_bytes */ ,
WriteBatch batch ( 0 /* reserved_bytes */ , 0 /* max_bytes */ ,
FLAGS_batch_protection_bytes_per_key ,
FLAGS_batch_protection_bytes_per_key ,
@ -44,10 +44,14 @@ class BatchedOpsStressTest : public StressTest {
assert ( cfh ) ;
assert ( cfh ) ;
for ( int i = 9 ; i > = 0 ; - - i ) {
for ( int i = 9 ; i > = 0 ; - - i ) {
const std : : string prefix = std : : to_string ( i ) ;
const std : : string num = std : : to_string ( i ) ;
const std : : string k = prefix + key_suffix ;
// Note: the digit in num is prepended to the key; however, it is appended
const std : : string v = prefix + value_suffix ;
// to the value because we want the "value base" to be encoded uniformly
// at the beginning of the value for all types of stress tests (e.g.
// batched, non-batched, CF consistency).
const std : : string k = num + key_body ;
const std : : string v = value_body + num ;
if ( FLAGS_use_merge ) {
if ( FLAGS_use_merge ) {
batch . Merge ( cfh , k , v ) ;
batch . Merge ( cfh , k , v ) ;
@ -72,7 +76,7 @@ class BatchedOpsStressTest : public StressTest {
return s ;
return s ;
}
}
// Given a key K, this deletes ("0"+K), ("1"+K),... ("9"+K)
// Given a key K, this deletes ("0"+K), ("1"+K), ..., ("9"+K)
// in DB atomically i.e in a single batch. Also refer MultiGet.
// in DB atomically i.e in a single batch. Also refer MultiGet.
Status TestDelete ( ThreadState * thread , WriteOptions & writeoptions ,
Status TestDelete ( ThreadState * thread , WriteOptions & writeoptions ,
const std : : vector < int > & rand_column_families ,
const std : : vector < int > & rand_column_families ,
@ -122,9 +126,9 @@ class BatchedOpsStressTest : public StressTest {
std : : terminate ( ) ;
std : : terminate ( ) ;
}
}
// Given a key K, this gets values for "0"+K, "1"+K,..."9"+K
// Given a key K, this gets values for "0"+K, "1"+K, ..., "9"+K
// in the same snapshot, and verifies that all the values are of the form
// in the same snapshot, and verifies that all the values are of the form
// "0"+V , "1"+V ,..."9"+V .
// V+ "0", V+ "1", ..., V+ "9".
// ASSUMES that BatchedOpsStressTest::TestPut was used to put (K, V) into
// ASSUMES that BatchedOpsStressTest::TestPut was used to put (K, V) into
// the DB.
// the DB.
Status TestGet ( ThreadState * thread , const ReadOptions & readoptions ,
Status TestGet ( ThreadState * thread , const ReadOptions & readoptions ,
@ -156,13 +160,19 @@ class BatchedOpsStressTest : public StressTest {
} else {
} else {
values [ i ] = from_db ;
values [ i ] = from_db ;
char expected_prefix = ( keys [ i ] ) [ 0 ] ;
assert ( ! keys [ i ] . empty ( ) ) ;
char actual_prefix = ( values [ i ] ) [ 0 ] ;
assert ( ! values [ i ] . empty ( ) ) ;
if ( actual_prefix ! = expected_prefix ) {
fprintf ( stderr , " error expected prefix = %c actual = %c \n " ,
const char expected = keys [ i ] . front ( ) ;
expected_prefix , actual_prefix ) ;
const char actual = values [ i ] . back ( ) ;
if ( expected ! = actual ) {
fprintf ( stderr , " get error expected = %c actual = %c \n " , expected ,
actual ) ;
}
}
( values [ i ] ) [ 0 ] = ' ' ; // blank out the differing character
values [ i ] . pop_back ( ) ; // get rid of the differing character
thread - > stats . AddGets ( 1 , 1 ) ;
thread - > stats . AddGets ( 1 , 1 ) ;
}
}
}
}
@ -171,7 +181,7 @@ class BatchedOpsStressTest : public StressTest {
// Now that we retrieved all values, check that they all match
// Now that we retrieved all values, check that they all match
for ( int i = 1 ; i < 10 ; i + + ) {
for ( int i = 1 ; i < 10 ; i + + ) {
if ( values [ i ] ! = values [ 0 ] ) {
if ( values [ i ] ! = values [ 0 ] ) {
fprintf ( stderr , " error : inconsistent values for key %s: %s, %s \n " ,
fprintf ( stderr , " get error: inconsistent values for key %s: %s, %s\n " ,
key . ToString ( true ) . c_str ( ) , StringToHex ( values [ 0 ] ) . c_str ( ) ,
key . ToString ( true ) . c_str ( ) , StringToHex ( values [ 0 ] ) . c_str ( ) ,
StringToHex ( values [ i ] ) . c_str ( ) ) ;
StringToHex ( values [ i ] ) . c_str ( ) ) ;
// we continue after error rather than exiting so that we can
// we continue after error rather than exiting so that we can
@ -214,7 +224,7 @@ class BatchedOpsStressTest : public StressTest {
for ( size_t i = 0 ; i < num_prefixes ; i + + ) {
for ( size_t i = 0 ; i < num_prefixes ; i + + ) {
Status s = statuses [ i ] ;
Status s = statuses [ i ] ;
if ( ! s . ok ( ) & & ! s . IsNotFound ( ) ) {
if ( ! s . ok ( ) & & ! s . IsNotFound ( ) ) {
fprintf ( stderr , " get error: %s \n " , s . ToString ( ) . c_str ( ) ) ;
fprintf ( stderr , " multi get error: %s\n " , s . ToString ( ) . c_str ( ) ) ;
thread - > stats . AddErrors ( 1 ) ;
thread - > stats . AddErrors ( 1 ) ;
ret_status [ rand_key ] = s ;
ret_status [ rand_key ] = s ;
// we continue after error rather than exiting so that we can
// we continue after error rather than exiting so that we can
@ -223,17 +233,19 @@ class BatchedOpsStressTest : public StressTest {
thread - > stats . AddGets ( 1 , 0 ) ;
thread - > stats . AddGets ( 1 , 0 ) ;
ret_status [ rand_key ] = s ;
ret_status [ rand_key ] = s ;
} else {
} else {
char expected_prefix = ( keys [ i ] ) [ 0 ] ;
assert ( ! keys [ i ] . empty ( ) ) ;
char actual_prefix = ( values [ i ] ) [ 0 ] ;
assert ( ! values [ i ] . empty ( ) ) ;
if ( actual_prefix ! = expected_prefix ) {
fprintf ( stderr , " error expected prefix = %c actual = %c \n " ,
const char expected = keys [ i ] [ 0 ] ;
expected_prefix , actual_prefix ) ;
const char actual = values [ i ] [ values [ i ] . size ( ) - 1 ] ;
}
std : : string str ;
if ( expected ! = actual ) {
str . assign ( values [ i ] . data ( ) , values [ i ] . size ( ) ) ;
fprintf ( stderr , " multiget error expected = %c actual = %c \n " ,
values [ i ] . Reset ( ) ;
expected , actual ) ;
str [ 0 ] = ' ' ; // blank out the differing character
}
values [ i ] . PinSelf ( str ) ;
values [ i ] . remove_suffix ( 1 ) ; // get rid of the differing character
thread - > stats . AddGets ( 1 , 1 ) ;
thread - > stats . AddGets ( 1 , 1 ) ;
}
}
}
}
@ -242,7 +254,8 @@ class BatchedOpsStressTest : public StressTest {
// Now that we retrieved all values, check that they all match
// Now that we retrieved all values, check that they all match
for ( size_t i = 1 ; i < num_prefixes ; i + + ) {
for ( size_t i = 1 ; i < num_prefixes ; i + + ) {
if ( values [ i ] ! = values [ 0 ] ) {
if ( values [ i ] ! = values [ 0 ] ) {
fprintf ( stderr , " error : inconsistent values for key %s: %s, %s \n " ,
fprintf ( stderr ,
" multiget error: inconsistent values for key %s: %s, %s \n " ,
StringToHex ( key_str [ i ] ) . c_str ( ) ,
StringToHex ( key_str [ i ] ) . c_str ( ) ,
StringToHex ( values [ 0 ] . ToString ( ) ) . c_str ( ) ,
StringToHex ( values [ 0 ] . ToString ( ) ) . c_str ( ) ,
StringToHex ( values [ i ] . ToString ( ) ) . c_str ( ) ) ;
StringToHex ( values [ i ] . ToString ( ) ) . c_str ( ) ) ;
@ -255,11 +268,11 @@ class BatchedOpsStressTest : public StressTest {
return ret_status ;
return ret_status ;
}
}
// Given a key, this does prefix scans for "0"+P, "1"+P,..."9"+P
// Given a key, this does prefix scans for "0"+P, "1"+P, ..., "9"+P
// in the same snapshot where P is the first FLAGS_prefix_size - 1 bytes
// in the same snapshot where P is the first FLAGS_prefix_size - 1 bytes
// of the key. Each of these 10 scans returns a series of values;
// of the key. Each of these 10 scans returns a series of values;
// each series should be the same length, and it is verified for each
// each series should be the same length, and it is verified for each
// index i that all the i'th values are of the form "0"+V , "1"+V ,..."9"+V .
// index i that all the i'th values are of the form V+ "0", V+ "1", ..., V+ "9".
// ASSUMES that MultiPut was used to put (K, V)
// ASSUMES that MultiPut was used to put (K, V)
Status TestPrefixScan ( ThreadState * thread , const ReadOptions & readoptions ,
Status TestPrefixScan ( ThreadState * thread , const ReadOptions & readoptions ,
const std : : vector < int > & rand_column_families ,
const std : : vector < int > & rand_column_families ,
@ -317,21 +330,24 @@ class BatchedOpsStressTest : public StressTest {
iters [ i ] - > key ( ) . starts_with ( prefix_slices [ i ] ) ) ;
iters [ i ] - > key ( ) . starts_with ( prefix_slices [ i ] ) ) ;
values [ i ] = iters [ i ] - > value ( ) . ToString ( ) ;
values [ i ] = iters [ i ] - > value ( ) . ToString ( ) ;
// make sure the first character of the value is the expected digit
// make sure the last character of the value is the expected digit
const char expected_first = prefixes [ i ] [ 0 ] ;
assert ( ! prefixes [ i ] . empty ( ) ) ;
const char actual_first = values [ i ] [ 0 ] ;
assert ( ! values [ i ] . empty ( ) ) ;
const char expected = prefixes [ i ] . front ( ) ;
const char actual = values [ i ] . back ( ) ;
if ( actual_first ! = expected_first ) {
if ( expected ! = actual ) {
fprintf ( stderr , " error expected first = %c actual = %c \n " ,
fprintf ( stderr , " prefix scan error expected = %c actual = %c\n " ,
expected_first , actual_first ) ;
expected , actual ) ;
}
}
values [ i ] [ 0 ] = ' ' ; // blank out the differing character
values [ i ] . pop_back ( ) ; // get rid of the differing character
// make sure all values are equivalent
// make sure all values are equivalent
if ( values [ i ] ! = values [ 0 ] ) {
if ( values [ i ] ! = values [ 0 ] ) {
fprintf ( stderr ,
fprintf ( stderr ,
" error : % " ROCKSDB_PRIszt
" prefix scan error : %" ROCKSDB_PRIszt
" , inconsistent values for prefix %s: %s, %s \n " ,
" , inconsistent values for prefix %s: %s, %s \n " ,
i , prefix_slices [ i ] . ToString ( /* hex */ true ) . c_str ( ) ,
i , prefix_slices [ i ] . ToString ( /* hex */ true ) . c_str ( ) ,
StringToHex ( values [ 0 ] ) . c_str ( ) ,
StringToHex ( values [ 0 ] ) . c_str ( ) ,
@ -341,16 +357,11 @@ class BatchedOpsStressTest : public StressTest {
}
}
// make sure value() and columns() are consistent
// make sure value() and columns() are consistent
// note: in these tests, value base is stored after a single-digit
// prefix
Slice value_base_slice = iters [ i ] - > value ( ) ;
value_base_slice . remove_prefix ( 1 ) ;
const WideColumns expected_columns = GenerateExpectedWideColumns (
const WideColumns expected_columns = GenerateExpectedWideColumns (
GetValueBase ( value_base_slice ) , iters [ i ] - > value ( ) ) ;
GetValueBase ( iters [ i ] - > value ( ) ) , iters [ i ] - > value ( ) ) ;
if ( iters [ i ] - > columns ( ) ! = expected_columns ) {
if ( iters [ i ] - > columns ( ) ! = expected_columns ) {
fprintf ( stderr ,
fprintf ( stderr ,
" error : % " ROCKSDB_PRIszt
" prefix scan error : % " ROCKSDB_PRIszt
" , value and columns inconsistent for prefix %s: %s \n " ,
" , value and columns inconsistent for prefix %s: %s \n " ,
i , prefix_slices [ i ] . ToString ( /* hex */ true ) . c_str ( ) ,
i , prefix_slices [ i ] . ToString ( /* hex */ true ) . c_str ( ) ,
DebugString ( iters [ i ] - > value ( ) , iters [ i ] - > columns ( ) ,
DebugString ( iters [ i ] - > value ( ) , iters [ i ] - > columns ( ) ,
@ -377,11 +388,6 @@ class BatchedOpsStressTest : public StressTest {
return Status : : OK ( ) ;
return Status : : OK ( ) ;
}
}
Slice GetValueBaseSlice ( Slice slice ) override {
slice . remove_prefix ( 1 ) ;
return slice ;
}
void VerifyDb ( ThreadState * /* thread */ ) const override { }
void VerifyDb ( ThreadState * /* thread */ ) const override { }
void ContinuouslyVerifyDb ( ThreadState * /* thread */ ) const override { }
void ContinuouslyVerifyDb ( ThreadState * /* thread */ ) const override { }