@ -9,6 +9,7 @@
# include <functional>
# include "db/db_iter.h"
# include "db/db_test_util.h"
# include "port/port.h"
# include "port/stack_trace.h"
@ -2157,6 +2158,141 @@ TEST_F(DBIteratorTest, SkipStatistics) {
ASSERT_EQ ( skip_count , TestGetTickerCount ( options , NUMBER_ITER_SKIP ) ) ;
}
TEST_F ( DBIteratorTest , ReadCallback ) {
class TestReadCallback : public ReadCallback {
public :
explicit TestReadCallback ( SequenceNumber last_visible_seq )
: last_visible_seq_ ( last_visible_seq ) { }
bool IsCommitted ( SequenceNumber seq ) override {
return seq < = last_visible_seq_ ;
}
private :
SequenceNumber last_visible_seq_ ;
} ;
ASSERT_OK ( Put ( " foo " , " v1 " ) ) ;
ASSERT_OK ( Put ( " foo " , " v2 " ) ) ;
ASSERT_OK ( Put ( " foo " , " v3 " ) ) ;
ASSERT_OK ( Put ( " a " , " va " ) ) ;
ASSERT_OK ( Put ( " z " , " vz " ) ) ;
SequenceNumber seq1 = db_ - > GetLatestSequenceNumber ( ) ;
TestReadCallback callback1 ( seq1 ) ;
ASSERT_OK ( Put ( " foo " , " v4 " ) ) ;
ASSERT_OK ( Put ( " foo " , " v5 " ) ) ;
ASSERT_OK ( Put ( " bar " , " v7 " ) ) ;
SequenceNumber seq2 = db_ - > GetLatestSequenceNumber ( ) ;
auto * cfd =
reinterpret_cast < ColumnFamilyHandleImpl * > ( db_ - > DefaultColumnFamily ( ) )
- > cfd ( ) ;
// The iterator are suppose to see data before seq1.
Iterator * iter =
dbfull ( ) - > NewIteratorImpl ( ReadOptions ( ) , cfd , seq2 , & callback1 ) ;
// Seek
// The latest value of "foo" before seq1 is "v3"
iter - > Seek ( " foo " ) ;
ASSERT_TRUE ( iter - > Valid ( ) ) ;
ASSERT_OK ( iter - > status ( ) ) ;
ASSERT_EQ ( " foo " , iter - > key ( ) ) ;
ASSERT_EQ ( " v3 " , iter - > value ( ) ) ;
// "bar" is not visible to the iterator. It will move on to the next key
// "foo".
iter - > Seek ( " bar " ) ;
ASSERT_TRUE ( iter - > Valid ( ) ) ;
ASSERT_OK ( iter - > status ( ) ) ;
ASSERT_EQ ( " foo " , iter - > key ( ) ) ;
ASSERT_EQ ( " v3 " , iter - > value ( ) ) ;
// Next
// Seek to "a"
iter - > Seek ( " a " ) ;
ASSERT_TRUE ( iter - > Valid ( ) ) ;
ASSERT_OK ( iter - > status ( ) ) ;
ASSERT_EQ ( " va " , iter - > value ( ) ) ;
// "bar" is not visible to the iterator. It will move on to the next key
// "foo".
iter - > Next ( ) ;
ASSERT_TRUE ( iter - > Valid ( ) ) ;
ASSERT_OK ( iter - > status ( ) ) ;
ASSERT_EQ ( " foo " , iter - > key ( ) ) ;
ASSERT_EQ ( " v3 " , iter - > value ( ) ) ;
// Prev
// Seek to "z"
iter - > Seek ( " z " ) ;
ASSERT_TRUE ( iter - > Valid ( ) ) ;
ASSERT_OK ( iter - > status ( ) ) ;
ASSERT_EQ ( " vz " , iter - > value ( ) ) ;
// The previous key is "foo", which is visible to the iterator.
iter - > Prev ( ) ;
ASSERT_TRUE ( iter - > Valid ( ) ) ;
ASSERT_OK ( iter - > status ( ) ) ;
ASSERT_EQ ( " foo " , iter - > key ( ) ) ;
ASSERT_EQ ( " v3 " , iter - > value ( ) ) ;
// "bar" is not visible to the iterator. It will move on to the next key "a".
iter - > Prev ( ) ; // skipping "bar"
ASSERT_TRUE ( iter - > Valid ( ) ) ;
ASSERT_OK ( iter - > status ( ) ) ;
ASSERT_EQ ( " a " , iter - > key ( ) ) ;
ASSERT_EQ ( " va " , iter - > value ( ) ) ;
// SeekForPrev
// The previous key is "foo", which is visible to the iterator.
iter - > SeekForPrev ( " y " ) ;
ASSERT_TRUE ( iter - > Valid ( ) ) ;
ASSERT_OK ( iter - > status ( ) ) ;
ASSERT_EQ ( " foo " , iter - > key ( ) ) ;
ASSERT_EQ ( " v3 " , iter - > value ( ) ) ;
// "bar" is not visible to the iterator. It will move on to the next key "a".
iter - > SeekForPrev ( " bar " ) ;
ASSERT_TRUE ( iter - > Valid ( ) ) ;
ASSERT_OK ( iter - > status ( ) ) ;
ASSERT_EQ ( " a " , iter - > key ( ) ) ;
ASSERT_EQ ( " va " , iter - > value ( ) ) ;
delete iter ;
// Prev beyond max_sequential_skip_in_iterations
uint64_t num_versions =
CurrentOptions ( ) . max_sequential_skip_in_iterations + 10 ;
for ( uint64_t i = 0 ; i < num_versions ; i + + ) {
ASSERT_OK ( Put ( " bar " , ToString ( i ) ) ) ;
}
SequenceNumber seq3 = db_ - > GetLatestSequenceNumber ( ) ;
TestReadCallback callback2 ( seq3 ) ;
ASSERT_OK ( Put ( " bar " , " v8 " ) ) ;
SequenceNumber seq4 = db_ - > GetLatestSequenceNumber ( ) ;
// The iterator is suppose to see data before seq3.
iter = dbfull ( ) - > NewIteratorImpl ( ReadOptions ( ) , cfd , seq4 , & callback2 ) ;
// Seek to "z", which is visible.
iter - > Seek ( " z " ) ;
ASSERT_TRUE ( iter - > Valid ( ) ) ;
ASSERT_OK ( iter - > status ( ) ) ;
ASSERT_EQ ( " vz " , iter - > value ( ) ) ;
// Previous key is "foo" and the last value "v5" is visible.
iter - > Prev ( ) ;
ASSERT_TRUE ( iter - > Valid ( ) ) ;
ASSERT_OK ( iter - > status ( ) ) ;
ASSERT_EQ ( " foo " , iter - > key ( ) ) ;
ASSERT_EQ ( " v5 " , iter - > value ( ) ) ;
// Since the number of values of "bar" is more than
// max_sequential_skip_in_iterations, Prev() will ultimately fallback to
// seek in forward direction. Here we test the fallback seek is correct.
// The last visible value should be (num_versions - 1), as "v8" is not
// visible.
iter - > Prev ( ) ;
ASSERT_TRUE ( iter - > Valid ( ) ) ;
ASSERT_OK ( iter - > status ( ) ) ;
ASSERT_EQ ( " bar " , iter - > key ( ) ) ;
ASSERT_EQ ( ToString ( num_versions - 1 ) , iter - > value ( ) ) ;
delete iter ;
}
} // namespace rocksdb
int main ( int argc , char * * argv ) {