@ -692,16 +692,17 @@ TEST_F(DBFlushTest, MemPurgeBasic) {
options . allow_concurrent_memtable_write = true ;
// Enforce size of a single MemTable to 64MB (64MB = 67108864 bytes).
options . write_buffer_size = 64 < < 20 ;
options . write_buffer_size = 1 < < 20 ;
// Activate the MemPurge prototype.
options . experimental_allow_mempurge = true ;
ASSERT_OK ( TryReopen ( options ) ) ;
uint32_t mempurge_count = 0 ;
uint32_t flush _count = 0 ;
uint32_t sst _count = 0 ;
ROCKSDB_NAMESPACE : : SyncPoint : : GetInstance ( ) - > SetCallBack (
" DBImpl::MemPurge " , [ & ] ( void * /*arg*/ ) { mempurge_count + + ; } ) ;
" DBImpl::FlushJob:MemPurgeSuccessful " ,
[ & ] ( void * /*arg*/ ) { mempurge_count + + ; } ) ;
ROCKSDB_NAMESPACE : : SyncPoint : : GetInstance ( ) - > SetCallBack (
" DBImpl::FlushJob:Flush " , [ & ] ( void * /*arg*/ ) { flush _count+ + ; } ) ;
" DBImpl::FlushJob:SSTFileCreated " , [ & ] ( void * /*arg*/ ) { sst _count+ + ; } ) ;
ROCKSDB_NAMESPACE : : SyncPoint : : GetInstance ( ) - > EnableProcessing ( ) ;
std : : string KEY1 = " IamKey1 " ;
@ -709,62 +710,120 @@ TEST_F(DBFlushTest, MemPurgeBasic) {
std : : string KEY3 = " IamKey3 " ;
std : : string KEY4 = " IamKey4 " ;
std : : string KEY5 = " IamKey5 " ;
std : : string VALUE1 = " IamValue1 " ;
std : : string VALUE2 = " IamValue2 " ;
std : : string KEY6 = " IamKey6 " ;
std : : string KEY7 = " IamKey7 " ;
std : : string KEY8 = " IamKey8 " ;
std : : string KEY9 = " IamKey9 " ;
std : : string RNDKEY1 , RNDKEY2 , RNDKEY3 ;
const std : : string NOT_FOUND = " NOT_FOUND " ;
// Check simple operations (put-delete).
ASSERT_OK ( Put ( KEY1 , VALUE1 ) ) ;
ASSERT_OK ( Put ( KEY2 , VALUE2 ) ) ;
ASSERT_OK ( Delete ( KEY1 ) ) ;
ASSERT_OK ( Put ( KEY2 , VALUE1 ) ) ;
ASSERT_OK ( Put ( KEY1 , VALUE2 ) ) ;
ASSERT_OK ( Flush ( ) ) ;
ASSERT_EQ ( Get ( KEY1 ) , VALUE2 ) ;
ASSERT_EQ ( Get ( KEY2 ) , VALUE1 ) ;
ASSERT_OK ( Delete ( KEY1 ) ) ;
ASSERT_EQ ( Get ( KEY1 ) , NOT_FOUND ) ;
ASSERT_OK ( Flush ( ) ) ;
ASSERT_EQ ( Get ( KEY1 ) , NOT_FOUND ) ;
// Heavy overwrite workload,
// more than would fit in maximum allowed memtables.
Random rnd ( 719 ) ;
const size_t NUM_REPEAT = 100000 ;
const size_t RAND_VALUES_LENGTH = 512 ;
std : : string p_v1 , p_v2 , p_v3 , p_v4 , p_v5 ;
// Insertion of of K-V pairs, multiple times.
// Also insert DeleteRange
for ( size_t i = 0 ; i < NUM_REPEAT ; i + + ) {
// Create value strings of arbitrary length RAND_VALUES_LENGTH bytes.
const size_t NUM_REPEAT = 100 ;
const size_t RAND_KEYS_LENGTH = 57 ;
const size_t RAND_VALUES_LENGTH = 10240 ;
std : : string p_v1 , p_v2 , p_v3 , p_v4 , p_v5 , p_v6 , p_v7 , p_v8 , p_v9 , p_rv1 ,
p_rv2 , p_rv3 ;
// Insert a very first set of keys that will be
// mempurged at least once.
p_v1 = rnd . RandomString ( RAND_VALUES_LENGTH ) ;
p_v2 = rnd . RandomString ( RAND_VALUES_LENGTH ) ;
p_v3 = rnd . RandomString ( RAND_VALUES_LENGTH ) ;
p_v4 = rnd . RandomString ( RAND_VALUES_LENGTH ) ;
p_v5 = rnd . RandomString ( RAND_VALUES_LENGTH ) ;
ASSERT_OK ( Put ( KEY1 , p_v1 ) ) ;
ASSERT_OK ( Put ( KEY2 , p_v2 ) ) ;
ASSERT_OK ( Put ( KEY3 , p_v3 ) ) ;
ASSERT_OK ( Put ( KEY4 , p_v4 ) ) ;
ASSERT_EQ ( Get ( KEY1 ) , p_v1 ) ;
ASSERT_EQ ( Get ( KEY2 ) , p_v2 ) ;
ASSERT_EQ ( Get ( KEY3 ) , p_v3 ) ;
ASSERT_EQ ( Get ( KEY4 ) , p_v4 ) ;
// Insertion of of K-V pairs, multiple times (overwrites).
for ( size_t i = 0 ; i < NUM_REPEAT ; i + + ) {
// Create value strings of arbitrary length RAND_VALUES_LENGTH bytes.
p_v5 = rnd . RandomString ( RAND_VALUES_LENGTH ) ;
p_v6 = rnd . RandomString ( RAND_VALUES_LENGTH ) ;
p_v7 = rnd . RandomString ( RAND_VALUES_LENGTH ) ;
p_v8 = rnd . RandomString ( RAND_VALUES_LENGTH ) ;
p_v9 = rnd . RandomString ( RAND_VALUES_LENGTH ) ;
ASSERT_OK ( Put ( KEY5 , p_v5 ) ) ;
ASSERT_OK ( Put ( KEY6 , p_v6 ) ) ;
ASSERT_OK ( Put ( KEY7 , p_v7 ) ) ;
ASSERT_OK ( Put ( KEY8 , p_v8 ) ) ;
ASSERT_OK ( Put ( KEY9 , p_v9 ) ) ;
ASSERT_EQ ( Get ( KEY1 ) , p_v1 ) ;
ASSERT_EQ ( Get ( KEY2 ) , p_v2 ) ;
ASSERT_EQ ( Get ( KEY3 ) , p_v3 ) ;
ASSERT_EQ ( Get ( KEY4 ) , p_v4 ) ;
ASSERT_EQ ( Get ( KEY5 ) , p_v5 ) ;
ASSERT_EQ ( Get ( KEY6 ) , p_v6 ) ;
ASSERT_EQ ( Get ( KEY7 ) , p_v7 ) ;
ASSERT_EQ ( Get ( KEY8 ) , p_v8 ) ;
ASSERT_EQ ( Get ( KEY9 ) , p_v9 ) ;
}
// Check that there was at least one mempurge
const uint32_t EXPECTED_MIN_MEMPURGE_COUNT = 1 ;
// Check that there was no flush to storage.
const uint32_t EXPECTED_FLUSH_COUNT = 0 ;
// Check that there was no SST files created during flush .
const uint32_t EXPECTED_SST _COUNT = 0 ;
EXPECT_GE ( mempurge_count , EXPECTED_MIN_MEMPURGE_COUNT ) ;
EXPECT_EQ ( flush_count , EXPECTED_FLUSH_COUNT ) ;
EXPECT_EQ ( sst_count , EXPECTED_SST_COUNT ) ;
const uint32_t mempurge_count_record = mempurge_count ;
// Insertion of of K-V pairs, no overwrites.
for ( size_t i = 0 ; i < NUM_REPEAT ; i + + ) {
// Create value strings of arbitrary length RAND_VALUES_LENGTH bytes.
RNDKEY1 = rnd . RandomString ( RAND_KEYS_LENGTH ) ;
RNDKEY2 = rnd . RandomString ( RAND_KEYS_LENGTH ) ;
RNDKEY3 = rnd . RandomString ( RAND_KEYS_LENGTH ) ;
p_rv1 = rnd . RandomString ( RAND_VALUES_LENGTH ) ;
p_rv2 = rnd . RandomString ( RAND_VALUES_LENGTH ) ;
p_rv3 = rnd . RandomString ( RAND_VALUES_LENGTH ) ;
ASSERT_OK ( Put ( RNDKEY1 , p_rv1 ) ) ;
ASSERT_OK ( Put ( RNDKEY2 , p_rv2 ) ) ;
ASSERT_OK ( Put ( RNDKEY3 , p_rv3 ) ) ;
ASSERT_EQ ( Get ( KEY1 ) , p_v1 ) ;
ASSERT_EQ ( Get ( KEY2 ) , p_v2 ) ;
ASSERT_EQ ( Get ( KEY3 ) , p_v3 ) ;
ASSERT_EQ ( Get ( KEY4 ) , p_v4 ) ;
ASSERT_EQ ( Get ( KEY5 ) , p_v5 ) ;
ASSERT_EQ ( Get ( KEY6 ) , p_v6 ) ;
ASSERT_EQ ( Get ( KEY7 ) , p_v7 ) ;
ASSERT_EQ ( Get ( KEY8 ) , p_v8 ) ;
ASSERT_EQ ( Get ( KEY9 ) , p_v9 ) ;
ASSERT_EQ ( Get ( RNDKEY1 ) , p_rv1 ) ;
ASSERT_EQ ( Get ( RNDKEY2 ) , p_rv2 ) ;
ASSERT_EQ ( Get ( RNDKEY3 ) , p_rv3 ) ;
}
// Assert that at least one flush to storage has been performed
ASSERT_GT ( sst_count , EXPECTED_SST_COUNT ) ;
// (which will consequently increase the number of mempurges recorded too).
ASSERT_EQ ( mempurge_count , mempurge_count_record ) ;
// Assert that there is no data corruption, even with
// a flush to storage.
ASSERT_EQ ( Get ( KEY1 ) , p_v1 ) ;
ASSERT_EQ ( Get ( KEY2 ) , p_v2 ) ;
ASSERT_EQ ( Get ( KEY3 ) , p_v3 ) ;
ASSERT_EQ ( Get ( KEY4 ) , p_v4 ) ;
ASSERT_EQ ( Get ( KEY5 ) , p_v5 ) ;
ASSERT_EQ ( Get ( KEY6 ) , p_v6 ) ;
ASSERT_EQ ( Get ( KEY7 ) , p_v7 ) ;
ASSERT_EQ ( Get ( KEY8 ) , p_v8 ) ;
ASSERT_EQ ( Get ( KEY9 ) , p_v9 ) ;
ASSERT_EQ ( Get ( RNDKEY1 ) , p_rv1 ) ;
ASSERT_EQ ( Get ( RNDKEY2 ) , p_rv2 ) ;
ASSERT_EQ ( Get ( RNDKEY3 ) , p_rv3 ) ;
Close ( ) ;
}
@ -780,17 +839,18 @@ TEST_F(DBFlushTest, MemPurgeDeleteAndDeleteRange) {
options . allow_concurrent_memtable_write = true ;
// Enforce size of a single MemTable to 64MB (64MB = 67108864 bytes).
options . write_buffer_size = 64 < < 20 ;
options . write_buffer_size = 1 < < 20 ;
// Activate the MemPurge prototype.
options . experimental_allow_mempurge = true ;
ASSERT_OK ( TryReopen ( options ) ) ;
uint32_t mempurge_count = 0 ;
uint32_t flush _count = 0 ;
uint32_t sst _count = 0 ;
ROCKSDB_NAMESPACE : : SyncPoint : : GetInstance ( ) - > SetCallBack (
" DBImpl::MemPurge " , [ & ] ( void * /*arg*/ ) { mempurge_count + + ; } ) ;
" DBImpl::FlushJob:MemPurgeSuccessful " ,
[ & ] ( void * /*arg*/ ) { mempurge_count + + ; } ) ;
ROCKSDB_NAMESPACE : : SyncPoint : : GetInstance ( ) - > SetCallBack (
" DBImpl::FlushJob:Flush " , [ & ] ( void * /*arg*/ ) { flush _count+ + ; } ) ;
" DBImpl::FlushJob:SSTFileCreated " , [ & ] ( void * /*arg*/ ) { sst _count+ + ; } ) ;
ROCKSDB_NAMESPACE : : SyncPoint : : GetInstance ( ) - > EnableProcessing ( ) ;
std : : string KEY1 = " ThisIsKey1 " ;
@ -801,9 +861,9 @@ TEST_F(DBFlushTest, MemPurgeDeleteAndDeleteRange) {
const std : : string NOT_FOUND = " NOT_FOUND " ;
Random rnd ( 117 ) ;
const size_t NUM_REPEAT = 2 00;
const size_t RAND_VALUES_LENGTH = 5 12;
bool atLeastOneFlush = false ;
const size_t NUM_REPEAT = 1 00;
const size_t RAND_VALUES_LENGTH = 10 240 ;
std : : string key , value , p_v1 , p_v2 , p_v3 , p_v3b , p_v4 , p_v5 ;
int count = 0 ;
const int EXPECTED_COUNT_FORLOOP = 3 ;
@ -813,6 +873,7 @@ TEST_F(DBFlushTest, MemPurgeDeleteAndDeleteRange) {
ropt . pin_data = true ;
ropt . total_order_seek = true ;
Iterator * iter = nullptr ;
// Insertion of of K-V pairs, multiple times.
// Also insert DeleteRange
for ( size_t i = 0 ; i < NUM_REPEAT ; i + + ) {
@ -836,12 +897,6 @@ TEST_F(DBFlushTest, MemPurgeDeleteAndDeleteRange) {
KEY3 ) ) ;
ASSERT_OK ( Delete ( KEY1 ) ) ;
// Flush (MemPurge) with a probability of 50%.
if ( rnd . OneIn ( 2 ) ) {
ASSERT_OK ( Flush ( ) ) ;
atLeastOneFlush = true ;
}
ASSERT_EQ ( Get ( KEY1 ) , NOT_FOUND ) ;
ASSERT_EQ ( Get ( KEY2 ) , NOT_FOUND ) ;
ASSERT_EQ ( Get ( KEY3 ) , p_v3b ) ;
@ -875,19 +930,11 @@ TEST_F(DBFlushTest, MemPurgeDeleteAndDeleteRange) {
// Check that there was at least one mempurge
const uint32_t EXPECTED_MIN_MEMPURGE_COUNT = 1 ;
// Check that there was no flush to storage .
const uint32_t EXPECTED_FLUSH _COUNT = 0 ;
// Check that there was no SST files created during flush .
const uint32_t EXPECTED_SST _COUNT = 0 ;
if ( atLeastOneFlush ) {
EXPECT_GE ( mempurge_count , EXPECTED_MIN_MEMPURGE_COUNT ) ;
} else {
// Note that there isn't enough values added to
// automatically trigger a flush/MemPurge in the background.
// Therefore we can make the assumption that if we never
// called "Flush()", no mempurge happened.
EXPECT_EQ ( mempurge_count , EXPECTED_FLUSH_COUNT ) ;
}
EXPECT_EQ ( flush_count , EXPECTED_FLUSH_COUNT ) ;
EXPECT_EQ ( sst_count , EXPECTED_SST_COUNT ) ;
// Additional test for the iterator+memPurge.
ASSERT_OK ( Put ( KEY2 , p_v2 ) ) ;
@ -911,6 +958,7 @@ TEST_F(DBFlushTest, MemPurgeDeleteAndDeleteRange) {
ASSERT_EQ ( value , NOT_FOUND ) ;
count + + ;
}
// Expected count here is 4: KEY2, KEY3, KEY4, KEY5.
ASSERT_EQ ( count , EXPECTED_COUNT_END ) ;
if ( iter ) delete iter ;
@ -974,6 +1022,10 @@ TEST_F(DBFlushTest, MemPurgeAndCompactionFilter) {
std : : string KEY3 = " ThisIsKey3 " ;
std : : string KEY4 = " ThisIsKey4 " ;
std : : string KEY5 = " ThisIsKey5 " ;
std : : string KEY6 = " ThisIsKey6 " ;
std : : string KEY7 = " ThisIsKey7 " ;
std : : string KEY8 = " ThisIsKey8 " ;
std : : string KEY9 = " ThisIsKey9 " ;
const std : : string NOT_FOUND = " NOT_FOUND " ;
options . statistics = CreateDBStatistics ( ) ;
@ -990,20 +1042,25 @@ TEST_F(DBFlushTest, MemPurgeAndCompactionFilter) {
std : : make_shared < ConditionalUpdateFilterFactory > ( KEY4 ) ;
// Enforce size of a single MemTable to 64MB (64MB = 67108864 bytes).
options . write_buffer_size = 64 < < 20 ;
options . write_buffer_size = 1 < < 20 ;
// Activate the MemPurge prototype.
options . experimental_allow_mempurge = true ;
ASSERT_OK ( TryReopen ( options ) ) ;
uint32_t mempurge_count = 0 ;
uint32_t sst_count = 0 ;
ROCKSDB_NAMESPACE : : SyncPoint : : GetInstance ( ) - > SetCallBack (
" DBImpl::FlushJob:MemPurgeSuccessful " ,
[ & ] ( void * /*arg*/ ) { mempurge_count + + ; } ) ;
ROCKSDB_NAMESPACE : : SyncPoint : : GetInstance ( ) - > SetCallBack (
" DBImpl::FlushJob:SSTFileCreated " , [ & ] ( void * /*arg*/ ) { sst_count + + ; } ) ;
ROCKSDB_NAMESPACE : : SyncPoint : : GetInstance ( ) - > EnableProcessing ( ) ;
Random rnd ( 53 ) ;
const size_t NUM_REPEAT = 25 ;
const size_t RAND_VALUES_LENGTH = 128 ;
std : : string p_v1 , p_v2 , p_v3 , p_v4 , p_v5 ;
const size_t NUM_REPEAT = 1000 ;
const size_t RAND_VALUES_LENGTH = 10240 ;
std : : string p_v1 , p_v2 , p_v3 , p_v4 , p_v5 , p_v6 , p_v7 , p_v8 , p_v9 ;
// Insertion of of K-V pairs, multiple times.
// Also insert DeleteRange
for ( size_t i = 0 ; i < NUM_REPEAT ; i + + ) {
// Create value strings of arbitrary length RAND_VALUES_LENGTH bytes.
p_v1 = rnd . RandomString ( RAND_VALUES_LENGTH ) ;
p_v2 = rnd . RandomString ( RAND_VALUES_LENGTH ) ;
p_v3 = rnd . RandomString ( RAND_VALUES_LENGTH ) ;
@ -1014,10 +1071,31 @@ TEST_F(DBFlushTest, MemPurgeAndCompactionFilter) {
ASSERT_OK ( Put ( KEY3 , p_v3 ) ) ;
ASSERT_OK ( Put ( KEY4 , p_v4 ) ) ;
ASSERT_OK ( Put ( KEY5 , p_v5 ) ) ;
ASSERT_OK ( Delete ( KEY1 ) ) ;
ASSERT_OK ( Flush ( ) ) ;
// Insertion of of K-V pairs, multiple times.
for ( size_t i = 0 ; i < NUM_REPEAT ; i + + ) {
// Create value strings of arbitrary
// length RAND_VALUES_LENGTH bytes.
p_v6 = rnd . RandomString ( RAND_VALUES_LENGTH ) ;
p_v7 = rnd . RandomString ( RAND_VALUES_LENGTH ) ;
p_v8 = rnd . RandomString ( RAND_VALUES_LENGTH ) ;
p_v9 = rnd . RandomString ( RAND_VALUES_LENGTH ) ;
ASSERT_OK ( Put ( KEY6 , p_v6 ) ) ;
ASSERT_OK ( Put ( KEY7 , p_v7 ) ) ;
ASSERT_OK ( Put ( KEY8 , p_v8 ) ) ;
ASSERT_OK ( Put ( KEY9 , p_v9 ) ) ;
ASSERT_OK ( Delete ( KEY7 ) ) ;
}
// Check that there was at least one mempurge
const uint32_t EXPECTED_MIN_MEMPURGE_COUNT = 1 ;
// Check that there was no SST files created during flush.
const uint32_t EXPECTED_SST_COUNT = 0 ;
EXPECT_GE ( mempurge_count , EXPECTED_MIN_MEMPURGE_COUNT ) ;
EXPECT_EQ ( sst_count , EXPECTED_SST_COUNT ) ;
// Verify that the ConditionalUpdateCompactionFilter
// updated the values of KEY2 and KEY3, and not KEY4 and KEY5.
@ -1027,7 +1105,6 @@ TEST_F(DBFlushTest, MemPurgeAndCompactionFilter) {
ASSERT_EQ ( Get ( KEY4 ) , p_v4 ) ;
ASSERT_EQ ( Get ( KEY5 ) , p_v5 ) ;
}
}
TEST_P ( DBFlushDirectIOTest , DirectIO ) {
Options options ;