@ -14,6 +14,7 @@
# include "table/block.h"
# include "table/block.h"
# include "table/block_builder.h"
# include "table/block_builder.h"
# include "table/format.h"
# include "table/format.h"
# include "util/ldb_cmd.h"
# include "util/random.h"
# include "util/random.h"
# include "util/testharness.h"
# include "util/testharness.h"
# include "util/testutil.h"
# include "util/testutil.h"
@ -22,10 +23,16 @@ namespace leveldb {
class SstFileReader {
class SstFileReader {
public :
public :
explicit SstFileReader ( std : : string file_name ,
explicit SstFileReader ( const std : : string & file_name ,
bool verify_checksum = false ,
bool verify_checksum ,
bool output_hex = false ) ;
bool output_hex ) ;
Status ReadSequential ( bool print_kv , uint64_t read_num = - 1 ) ;
Status ReadSequential ( bool print_kv ,
uint64_t read_num ,
bool has_from ,
const std : : string & from_key ,
bool has_to ,
const std : : string & to_key ) ;
uint64_t GetReadNumber ( ) { return read_num_ ; }
uint64_t GetReadNumber ( ) { return read_num_ ; }
@ -37,17 +44,25 @@ private:
EnvOptions soptions_ ;
EnvOptions soptions_ ;
} ;
} ;
SstFileReader : : SstFileReader ( std : : string file_path ,
SstFileReader : : SstFileReader ( const std : : string & file_path ,
bool verify_checksum ,
bool verify_checksum ,
bool output_hex )
bool output_hex )
: file_name_ ( file_path ) , read_num_ ( 0 ) , verify_checksum_ ( verify_checksum ) ,
: file_name_ ( file_path ) , read_num_ ( 0 ) , verify_checksum_ ( verify_checksum ) ,
output_hex_ ( output_hex ) {
output_hex_ ( output_hex ) {
std : : cout < < " Process " < < file_path < < " \n " ;
}
}
Status SstFileReader : : ReadSequential ( bool print_kv , uint64_t read_num )
Status SstFileReader : : ReadSequential ( bool print_kv ,
uint64_t read_num ,
bool has_from ,
const std : : string & from_key ,
bool has_to ,
const std : : string & to_key )
{
{
unique_ptr < Table > table ;
unique_ptr < Table > table ;
InternalKeyComparator internal_comparator_ ( BytewiseComparator ( ) ) ;
Options table_options ;
Options table_options ;
table_options . comparator = & internal_comparator_ ;
unique_ptr < RandomAccessFile > file ;
unique_ptr < RandomAccessFile > file ;
Status s = table_options . env - > NewRandomAccessFile ( file_name_ , & file ,
Status s = table_options . env - > NewRandomAccessFile ( file_name_ , & file ,
soptions_ ) ;
soptions_ ) ;
@ -63,17 +78,38 @@ Status SstFileReader::ReadSequential(bool print_kv, uint64_t read_num)
Iterator * iter = table - > NewIterator ( ReadOptions ( verify_checksum_ , false ) ) ;
Iterator * iter = table - > NewIterator ( ReadOptions ( verify_checksum_ , false ) ) ;
uint64_t i = 0 ;
uint64_t i = 0 ;
for ( iter - > SeekToFirst ( ) ; iter - > Valid ( ) ; iter - > Next ( ) ) {
if ( has_from ) {
InternalKey ikey ( from_key , kMaxSequenceNumber , kValueTypeForSeek ) ;
iter - > Seek ( ikey . Encode ( ) ) ;
} else {
iter - > SeekToFirst ( ) ;
}
for ( ; iter - > Valid ( ) ; iter - > Next ( ) ) {
Slice key = iter - > key ( ) ;
Slice key = iter - > key ( ) ;
Slice value = iter - > value ( ) ;
Slice value = iter - > value ( ) ;
+ + i ;
+ + i ;
if ( read_num > 0 & & i > read_num )
if ( read_num > 0 & & i > read_num )
break ;
break ;
ParsedInternalKey ikey ;
if ( ! ParseInternalKey ( key , & ikey ) ) {
std : : cerr < < " Internal Key [ "
< < key . ToString ( true /* in hex*/ )
< < " ] parse error! \n " ;
continue ;
}
// If end marker was specified, we stop before it
if ( has_to & & BytewiseComparator ( ) - > Compare ( ikey . user_key , to_key ) > = 0 ) {
break ;
}
if ( print_kv ) {
if ( print_kv ) {
fprintf ( stdout , " %s ==> %s \n " ,
std : : cout < < ikey . DebugString ( output_hex_ )
key . ToString ( output_hex_ ) . c_str ( ) ,
< < " => "
value . ToString ( output_hex_ ) . c_str ( ) ) ;
< < value . ToString ( output_hex_ ) < < " \n " ;
}
}
}
}
read_num_ + = i ;
read_num_ + = i ;
@ -90,9 +126,29 @@ static void print_help() {
" sst_dump [--command=check|scan] [--verify_checksum] "
" sst_dump [--command=check|scan] [--verify_checksum] "
" --file=data_dir_OR_sst_file "
" --file=data_dir_OR_sst_file "
" [--output_hex] "
" [--output_hex] "
" [--input_key_hex] "
" [--from=<user_key>] "
" [--to=<user_key>] "
" [--read_num=NUM] \n " ) ;
" [--read_num=NUM] \n " ) ;
}
}
string HexToString ( const string & str ) {
string parsed ;
if ( str [ 0 ] ! = ' 0 ' | | str [ 1 ] ! = ' x ' ) {
fprintf ( stderr , " Invalid hex input %s. Must start with 0x \n " ,
str . c_str ( ) ) ;
throw " Invalid hex input " ;
}
for ( unsigned int i = 2 ; i < str . length ( ) ; ) {
int c ;
sscanf ( str . c_str ( ) + i , " %2X " , & c ) ;
parsed . push_back ( c ) ;
i + = 2 ;
}
return parsed ;
}
int main ( int argc , char * * argv ) {
int main ( int argc , char * * argv ) {
const char * dir_or_file = nullptr ;
const char * dir_or_file = nullptr ;
@ -103,24 +159,47 @@ int main(int argc, char** argv) {
uint64_t n ;
uint64_t n ;
bool verify_checksum = false ;
bool verify_checksum = false ;
bool output_hex = false ;
bool output_hex = false ;
bool input_key_hex = false ;
bool has_from = false ;
bool has_to = false ;
std : : string from_key ;
std : : string to_key ;
for ( int i = 1 ; i < argc ; i + + )
for ( int i = 1 ; i < argc ; i + + )
{
{
if ( strncmp ( argv [ i ] , " --file= " , 7 ) = = 0 ) {
if ( strncmp ( argv [ i ] , " --file= " , 7 ) = = 0 ) {
dir_or_file = argv [ i ] + 7 ;
dir_or_file = argv [ i ] + 7 ;
} else if ( strcmp ( argv [ i ] , " --output_hex " ) = = 0 ) {
} else if ( strcmp ( argv [ i ] , " --output_hex " ) = = 0 ) {
output_hex = true ;
output_hex = true ;
} else if ( strcmp ( argv [ i ] , " --input_key_hex " ) = = 0 ) {
input_key_hex = true ;
} else if ( sscanf ( argv [ i ] , " --read_num=%ld%c " , & n , & junk ) = = 1 ) {
} else if ( sscanf ( argv [ i ] , " --read_num=%ld%c " , & n , & junk ) = = 1 ) {
read_num = n ;
read_num = n ;
} else if ( strcmp ( argv [ i ] , " --verify_checksum " ) = = 0 ) {
} else if ( strcmp ( argv [ i ] , " --verify_checksum " ) = = 0 ) {
verify_checksum = true ;
verify_checksum = true ;
} else if ( strncmp ( argv [ i ] , " --command= " , 10 ) = = 0 ) {
} else if ( strncmp ( argv [ i ] , " --command= " , 10 ) = = 0 ) {
command = argv [ i ] + 10 ;
command = argv [ i ] + 10 ;
} else if ( strncmp ( argv [ i ] , " --from= " , 7 ) = = 0 ) {
from_key = argv [ i ] + 7 ;
has_from = true ;
} else if ( strncmp ( argv [ i ] , " --to= " , 5 ) = = 0 ) {
to_key = argv [ i ] + 5 ;
has_to = true ;
} else {
} else {
print_help ( ) ;
print_help ( ) ;
exit ( 1 ) ;
exit ( 1 ) ;
}
}
}
}
if ( input_key_hex ) {
if ( has_from ) {
from_key = HexToString ( from_key ) ;
}
if ( has_to ) {
to_key = HexToString ( to_key ) ;
}
}
if ( dir_or_file = = nullptr ) {
if ( dir_or_file = = nullptr ) {
print_help ( ) ;
print_help ( ) ;
exit ( 1 ) ;
exit ( 1 ) ;
@ -136,6 +215,9 @@ int main(int argc, char** argv) {
dir = false ;
dir = false ;
}
}
std : : cout < < " from [ " < < leveldb : : Slice ( from_key ) . ToString ( true )
< < " ] to [ " < < leveldb : : Slice ( to_key ) . ToString ( true ) < < " ] \n " ;
uint64_t total_read = 0 ;
uint64_t total_read = 0 ;
for ( size_t i = 0 ; i < filenames . size ( ) ; i + + ) {
for ( size_t i = 0 ; i < filenames . size ( ) ; i + + ) {
std : : string filename = filenames . at ( i ) ;
std : : string filename = filenames . at ( i ) ;
@ -145,7 +227,7 @@ int main(int argc, char** argv) {
continue ;
continue ;
}
}
if ( dir ) {
if ( dir ) {
filename = std : : string ( dir_or_file ) + " // " + filename ;
filename = std : : string ( dir_or_file ) + " / " + filename ;
}
}
leveldb : : SstFileReader reader ( filename , verify_checksum ,
leveldb : : SstFileReader reader ( filename , verify_checksum ,
output_hex ) ;
output_hex ) ;
@ -153,7 +235,9 @@ int main(int argc, char** argv) {
// scan all files in give file path.
// scan all files in give file path.
if ( command = = " " | | command = = " scan " | | command = = " check " ) {
if ( command = = " " | | command = = " scan " | | command = = " check " ) {
st = reader . ReadSequential ( command ! = " check " ,
st = reader . ReadSequential ( command ! = " check " ,
read_num > 0 ? ( read_num - total_read ) : read_num ) ;
read_num > 0 ? ( read_num - total_read ) :
read_num ,
has_from , from_key , has_to , to_key ) ;
if ( ! st . ok ( ) ) {
if ( ! st . ok ( ) ) {
fprintf ( stderr , " %s: %s \n " , filename . c_str ( ) ,
fprintf ( stderr , " %s: %s \n " , filename . c_str ( ) ,
st . ToString ( ) . c_str ( ) ) ;
st . ToString ( ) . c_str ( ) ) ;