2017-05-26 04:48:44 +08:00
/*
* RYWIterator . h
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013 - 2018 Apple Inc . and the FoundationDB project authors
2018-02-22 02:25:11 +08:00
*
2017-05-26 04:48:44 +08:00
* Licensed under the Apache License , Version 2.0 ( the " License " ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
2018-02-22 02:25:11 +08:00
*
2017-05-26 04:48:44 +08:00
* http : //www.apache.org/licenses/LICENSE-2.0
2018-02-22 02:25:11 +08:00
*
2017-05-26 04:48:44 +08:00
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an " AS IS " BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
*/
# ifndef FDBCLIENT_RYWITERATOR_H
# define FDBCLIENT_RYWITERATOR_H
# pragma once
2018-10-20 01:30:13 +08:00
# include "fdbclient/SnapshotCache.h"
# include "fdbclient/WriteMap.h"
2017-05-26 04:48:44 +08:00
class RYWIterator {
public :
RYWIterator ( SnapshotCache * snapshotCache , WriteMap * writeMap ) : cache ( snapshotCache ) , writes ( writeMap ) , begin_key_cmp ( 0 ) , end_key_cmp ( 0 ) { }
enum SEGMENT_TYPE { UNKNOWN_RANGE , EMPTY_RANGE , KV } ;
static const SEGMENT_TYPE typeMap [ 12 ] ;
2020-06-18 05:45:38 +08:00
SEGMENT_TYPE type ( ) const ;
2017-05-26 04:48:44 +08:00
2020-06-18 05:45:38 +08:00
bool is_kv ( ) const ;
bool is_unknown_range ( ) const ;
bool is_empty_range ( ) const ;
bool is_unreadable ( ) const ;
bool is_dependent ( ) const ;
2017-05-26 04:48:44 +08:00
ExtStringRef beginKey ( ) ;
ExtStringRef endKey ( ) ;
2019-01-31 17:23:32 +08:00
const KeyValueRef * kv ( Arena & arena ) ;
2017-05-26 04:48:44 +08:00
RYWIterator & operator + + ( ) ;
RYWIterator & operator - - ( ) ;
bool operator = = ( const RYWIterator & r ) const ;
void skip ( KeyRef key ) ;
void skipContiguous ( KeyRef key ) ;
void skipContiguousBack ( KeyRef key ) ;
WriteMap : : iterator & extractWriteMapIterator ( ) ;
// Really this should return an iterator by value, but for performance it's convenient to actually grab the internal one. Consider copying the return value if performance isn't critical.
// If you modify the returned iterator, it invalidates this iterator until the next call to skip()
void dbg ( ) ;
private :
int begin_key_cmp ; // -1 if cache.beginKey() < writes.beginKey(), 0 if ==, +1 if >
int end_key_cmp ; //
SnapshotCache : : iterator cache ;
WriteMap : : iterator writes ;
KeyValueRef temp ;
void updateCmp ( ) ;
} ;
class RandomTestImpl {
public :
static ValueRef getRandomValue ( Arena & arena ) {
2019-05-11 05:01:52 +08:00
return ValueRef ( arena , std : : string ( deterministicRandom ( ) - > randomInt ( 0 , 1000 ) , ' x ' ) ) ;
2017-05-26 04:48:44 +08:00
}
static ValueRef getRandomVersionstampValue ( Arena & arena ) {
2019-05-11 05:01:52 +08:00
int len = deterministicRandom ( ) - > randomInt ( 10 , 98 ) ;
2018-02-16 13:35:00 +08:00
std : : string value = std : : string ( len , ' x ' ) ;
2019-05-11 05:01:52 +08:00
int32_t pos = deterministicRandom ( ) - > randomInt ( 0 , len - 9 ) ;
if ( deterministicRandom ( ) - > random01 ( ) < 0.01 ) {
2018-02-16 13:35:00 +08:00
pos = value . size ( ) - 10 ;
}
2018-02-24 10:17:53 +08:00
pos = littleEndian32 ( pos ) ;
value + = std : : string ( ( const char * ) & pos , sizeof ( int32_t ) ) ;
2018-02-16 13:35:00 +08:00
return ValueRef ( arena , value ) ;
}
2017-05-26 04:48:44 +08:00
static ValueRef getRandomVersionstampKey ( Arena & arena ) {
2019-05-11 05:01:52 +08:00
int idx = deterministicRandom ( ) - > randomInt ( 0 , 100 ) ;
2017-05-26 04:48:44 +08:00
std : : string key = format ( " %010d " , idx / 3 ) ;
if ( idx % 3 > = 1 )
key + = ' \x00 ' ;
if ( idx % 3 > = 2 )
key + = ' \x00 ' ;
2019-05-11 05:01:52 +08:00
int32_t pos = key . size ( ) - deterministicRandom ( ) - > randomInt ( 0 , 3 ) ;
if ( deterministicRandom ( ) - > random01 ( ) < 0.01 ) {
2017-05-26 04:48:44 +08:00
pos = 0 ;
}
key = key . substr ( 0 , pos ) ;
key + = " XXXXXXXXYY " ;
2019-05-11 05:01:52 +08:00
key + = std : : string ( deterministicRandom ( ) - > randomInt ( 0 , 3 ) , ' z ' ) ;
2018-03-22 09:58:19 +08:00
pos = littleEndian32 ( pos ) ;
key + = std : : string ( ( const char * ) & pos , sizeof ( int32_t ) ) ;
2017-05-26 04:48:44 +08:00
return ValueRef ( arena , key ) ;
}
static KeyRef getRandomKey ( Arena & arena ) {
2019-05-11 05:01:52 +08:00
return getKeyForIndex ( arena , deterministicRandom ( ) - > randomInt ( 0 , 100 ) ) ;
2017-05-26 04:48:44 +08:00
}
static KeyRef getKeyForIndex ( Arena & arena , int idx ) {
std : : string key = format ( " %010d " , idx / 3 ) ;
if ( idx % 3 > = 1 )
key + = ' \x00 ' ;
if ( idx % 3 > = 2 )
key + = ' \x00 ' ;
return KeyRef ( arena , key ) ;
}
static KeyRangeRef getRandomRange ( Arena & arena ) {
2019-05-11 05:01:52 +08:00
int startLocation = deterministicRandom ( ) - > randomInt ( 0 , 100 ) ;
int endLocation = startLocation + deterministicRandom ( ) - > randomInt ( 1 , 1 + 100 - startLocation ) ;
2017-05-26 04:48:44 +08:00
return KeyRangeRef ( getKeyForIndex ( arena , startLocation ) , getKeyForIndex ( arena , endLocation ) ) ;
}
static KeySelectorRef getRandomKeySelector ( Arena & arena ) {
2019-05-11 05:01:52 +08:00
return KeySelectorRef ( getRandomKey ( arena ) , deterministicRandom ( ) - > random01 ( ) < 0.5 , deterministicRandom ( ) - > randomInt ( - 10 , 10 ) ) ;
2017-05-26 04:48:44 +08:00
}
} ;
void testESR ( ) ;
void testSnapshotCache ( ) ;
2018-02-16 13:35:00 +08:00
# endif