@ -17,44 +17,14 @@
# include <vector>
# include "rocksdb/comparator.h"
# include "table/format.h"
# include "table/block_hash_index.h"
# include "table/block_prefix_index.h"
# include "table/format.h"
# include "util/coding.h"
# include "util/logging.h"
# include "db/dbformat.h"
namespace rocksdb {
uint32_t Block : : NumRestarts ( ) const {
assert ( size_ > = 2 * sizeof ( uint32_t ) ) ;
return DecodeFixed32 ( data_ + size_ - sizeof ( uint32_t ) ) ;
}
Block : : Block ( const BlockContents & contents )
: data_ ( contents . data . data ( ) ) ,
size_ ( contents . data . size ( ) ) ,
owned_ ( contents . heap_allocated ) ,
cachable_ ( contents . cachable ) ,
compression_type_ ( contents . compression_type ) {
if ( size_ < sizeof ( uint32_t ) ) {
size_ = 0 ; // Error marker
} else {
restart_offset_ = size_ - ( 1 + NumRestarts ( ) ) * sizeof ( uint32_t ) ;
if ( restart_offset_ > size_ - sizeof ( uint32_t ) ) {
// The size is too small for NumRestarts() and therefore
// restart_offset_ wrapped around.
size_ = 0 ;
}
}
}
Block : : ~ Block ( ) {
if ( owned_ ) {
delete [ ] data_ ;
}
}
// Helper routine: decode the next block entry starting at "p",
// storing the number of shared key bytes, non_shared key bytes,
// and the length of the value in "*shared", "*non_shared", and
@ -85,78 +55,12 @@ static inline const char* DecodeEntry(const char* p, const char* limit,
return p ;
}
class Block : : Iter : public Iterator {
private :
const Comparator * const comparator_ ;
const char * const data_ ; // underlying block contents
uint32_t const restarts_ ; // Offset of restart array (list of fixed32)
uint32_t const num_restarts_ ; // Number of uint32_t entries in restart array
// current_ is offset in data_ of current entry. >= restarts_ if !Valid
uint32_t current_ ;
uint32_t restart_index_ ; // Index of restart block in which current_ falls
IterKey key_ ;
Slice value_ ;
Status status_ ;
BlockHashIndex * hash_index_ ;
BlockPrefixIndex * prefix_index_ ;
inline int Compare ( const Slice & a , const Slice & b ) const {
return comparator_ - > Compare ( a , b ) ;
}
// Return the offset in data_ just past the end of the current entry.
inline uint32_t NextEntryOffset ( ) const {
return ( value_ . data ( ) + value_ . size ( ) ) - data_ ;
}
uint32_t GetRestartPoint ( uint32_t index ) {
assert ( index < num_restarts_ ) ;
return DecodeFixed32 ( data_ + restarts_ + index * sizeof ( uint32_t ) ) ;
}
void SeekToRestartPoint ( uint32_t index ) {
key_ . Clear ( ) ;
restart_index_ = index ;
// current_ will be fixed by ParseNextKey();
// ParseNextKey() starts at the end of value_, so set value_ accordingly
uint32_t offset = GetRestartPoint ( index ) ;
value_ = Slice ( data_ + offset , 0 ) ;
}
public :
Iter ( const Comparator * comparator , const char * data , uint32_t restarts ,
uint32_t num_restarts , BlockHashIndex * hash_index ,
BlockPrefixIndex * prefix_index )
: comparator_ ( comparator ) ,
data_ ( data ) ,
restarts_ ( restarts ) ,
num_restarts_ ( num_restarts ) ,
current_ ( restarts_ ) ,
restart_index_ ( num_restarts_ ) ,
hash_index_ ( hash_index ) ,
prefix_index_ ( prefix_index ) {
assert ( num_restarts_ > 0 ) ;
}
virtual bool Valid ( ) const { return current_ < restarts_ ; }
virtual Status status ( ) const { return status_ ; }
virtual Slice key ( ) const {
assert ( Valid ( ) ) ;
return key_ . GetKey ( ) ;
}
virtual Slice value ( ) const {
assert ( Valid ( ) ) ;
return value_ ;
}
virtual void Next ( ) {
void BlockIter : : Next ( ) {
assert ( Valid ( ) ) ;
ParseNextKey ( ) ;
}
virtual void Prev ( ) {
void BlockIter : : Prev ( ) {
assert ( Valid ( ) ) ;
// Scan backwards to a restart point before current_
@ -177,7 +81,10 @@ class Block::Iter : public Iterator {
} while ( ParseNextKey ( ) & & NextEntryOffset ( ) < original ) ;
}
virtual void Seek ( const Slice & target ) {
void BlockIter : : Seek ( const Slice & target ) {
if ( data_ = = nullptr ) { // Not init yet
return ;
}
uint32_t index = 0 ;
bool ok = false ;
if ( prefix_index_ ) {
@ -199,20 +106,26 @@ class Block::Iter : public Iterator {
}
}
}
virtual void SeekToFirst ( ) {
void BlockIter : : SeekToFirst ( ) {
if ( data_ = = nullptr ) { // Not init yet
return ;
}
SeekToRestartPoint ( 0 ) ;
ParseNextKey ( ) ;
}
virtual void SeekToLast ( ) {
void BlockIter : : SeekToLast ( ) {
if ( data_ = = nullptr ) { // Not init yet
return ;
}
SeekToRestartPoint ( num_restarts_ - 1 ) ;
while ( ParseNextKey ( ) & & NextEntryOffset ( ) < restarts_ ) {
// Keep skipping
}
}
private :
void CorruptionError ( ) {
void BlockIter : : CorruptionError ( ) {
current_ = restarts_ ;
restart_index_ = num_restarts_ ;
status_ = Status : : Corruption ( " bad entry in block " ) ;
@ -220,7 +133,7 @@ class Block::Iter : public Iterator {
value_ . clear ( ) ;
}
bool ParseNextKey ( ) {
bool BlockIter : : ParseNextKey ( ) {
current_ = NextEntryOffset ( ) ;
const char * p = data_ + current_ ;
const char * limit = data_ + restarts_ ; // Restarts come right after data
@ -250,7 +163,7 @@ class Block::Iter : public Iterator {
// Binary search in restart array to find the first restart point
// with a key >= target (TODO: this comment is inaccurate)
bool BinarySeek ( const Slice & target , uint32_t left , uint32_t right ,
bool BlockIter : : BinarySeek ( const Slice & target , uint32_t left , uint32_t right ,
uint32_t * index ) {
assert ( left < = right ) ;
@ -286,7 +199,7 @@ class Block::Iter : public Iterator {
// Compare target key and the block key of the block of `block_index`.
// Return -1 if error.
int CompareBlockKey ( uint32_t block_index , const Slice & target ) {
int BlockIter : : CompareBlockKey ( uint32_t block_index , const Slice & target ) {
uint32_t region_offset = GetRestartPoint ( block_index ) ;
uint32_t shared , non_shared , value_length ;
const char * key_ptr = DecodeEntry ( data_ + region_offset , data_ + restarts_ ,
@ -301,7 +214,7 @@ class Block::Iter : public Iterator {
// Binary search in block_ids to find the first block
// with a key >= target
bool BinaryBlockIndexSeek ( const Slice & target , uint32_t * block_ids ,
bool BlockIter : : BinaryBlockIndexSeek ( const Slice & target , uint32_t * block_ids ,
uint32_t left , uint32_t right ,
uint32_t * index ) {
assert ( left < = right ) ;
@ -351,7 +264,7 @@ class Block::Iter : public Iterator {
}
}
bool HashSeek ( const Slice & target , uint32_t * index ) {
bool BlockIter : : HashSeek ( const Slice & target , uint32_t * index ) {
assert ( hash_index_ ) ;
auto restart_index = hash_index_ - > GetRestartIndex ( target ) ;
if ( restart_index = = nullptr ) {
@ -366,12 +279,11 @@ class Block::Iter : public Iterator {
return BinarySeek ( target , left , right , index ) ;
}
bool PrefixSeek ( const Slice & target , uint32_t * index ) {
bool BlockIter : : PrefixSeek ( const Slice & target , uint32_t * index ) {
assert ( prefix_index_ ) ;
uint32_t * block_ids = nullptr ;
uint32_t num_blocks = prefix_index_ - > GetBlocks ( target , & block_ids ) ;
if ( num_blocks = = 0 ) {
current_ = restarts_ ;
return false ;
@ -379,21 +291,66 @@ class Block::Iter : public Iterator {
return BinaryBlockIndexSeek ( target , block_ids , 0 , num_blocks - 1 , index ) ;
}
}
} ;
Iterator * Block : : NewIterator ( const Comparator * cmp ) {
uint32_t Block : : NumRestarts ( ) const {
assert ( size_ > = 2 * sizeof ( uint32_t ) ) ;
return DecodeFixed32 ( data_ + size_ - sizeof ( uint32_t ) ) ;
}
Block : : Block ( const BlockContents & contents )
: data_ ( contents . data . data ( ) ) ,
size_ ( contents . data . size ( ) ) ,
owned_ ( contents . heap_allocated ) ,
cachable_ ( contents . cachable ) ,
compression_type_ ( contents . compression_type ) {
if ( size_ < sizeof ( uint32_t ) ) {
size_ = 0 ; // Error marker
} else {
restart_offset_ = size_ - ( 1 + NumRestarts ( ) ) * sizeof ( uint32_t ) ;
if ( restart_offset_ > size_ - sizeof ( uint32_t ) ) {
// The size is too small for NumRestarts() and therefore
// restart_offset_ wrapped around.
size_ = 0 ;
}
}
}
Block : : ~ Block ( ) {
if ( owned_ ) {
delete [ ] data_ ;
}
}
Iterator * Block : : NewIterator ( const Comparator * cmp , BlockIter * iter ) {
if ( size_ < 2 * sizeof ( uint32_t ) ) {
if ( iter ! = nullptr ) {
iter - > SetStatus ( Status : : Corruption ( " bad block contents " ) ) ;
return iter ;
} else {
return NewErrorIterator ( Status : : Corruption ( " bad block contents " ) ) ;
}
}
const uint32_t num_restarts = NumRestarts ( ) ;
if ( num_restarts = = 0 ) {
if ( iter ! = nullptr ) {
iter - > SetStatus ( Status : : OK ( ) ) ;
return iter ;
} else {
return NewEmptyIterator ( ) ;
}
} else {
if ( iter ! = nullptr ) {
iter - > Initialize ( cmp , data_ , restart_offset_ , num_restarts ,
hash_index_ . get ( ) , prefix_index_ . get ( ) ) ;
} else {
return new Iter ( cmp , data_ , restart_offset_ , num_restarts ,
iter = new Block Iter( cmp , data_ , restart_offset_ , num_restarts ,
hash_index_ . get ( ) , prefix_index_ . get ( ) ) ;
}
}
return iter ;
}
void Block : : SetBlockHashIndex ( BlockHashIndex * hash_index ) {
hash_index_ . reset ( hash_index ) ;
}