@ -4224,7 +4224,6 @@ Status VersionSet::ProcessManifestWrites(
if ( ! io_s . ok ( ) ) {
s = io_s ;
}
TEST_SYNC_POINT ( " VersionSet::ProcessManifestWrites:AfterNewManifest " ) ;
}
if ( s . ok ( ) ) {
@ -5716,6 +5715,9 @@ Status ReactiveVersionSet::Recover(
static_cast_with_check < LogReporter > ( manifest_reporter - > get ( ) ) - > status =
manifest_reader_status - > get ( ) ;
Status s = MaybeSwitchManifest ( manifest_reporter - > get ( ) , manifest_reader ) ;
if ( ! s . ok ( ) ) {
return s ;
}
log : : Reader * reader = manifest_reader - > get ( ) ;
assert ( reader ) ;
@ -5757,43 +5759,62 @@ Status ReactiveVersionSet::MaybeSwitchManifest(
std : : unique_ptr < log : : FragmentBufferedReader > * manifest_reader ) {
assert ( manifest_reader ! = nullptr ) ;
Status s ;
do {
std : : string manifest_path ;
s = GetCurrentManifestPath ( dbname_ , fs_ . get ( ) , & manifest_path ,
& manifest_file_number_ ) ;
std : : unique_ptr < FSSequentialFile > manifest_file ;
if ( s . ok ( ) ) {
if ( nullptr = = manifest_reader - > get ( ) | |
manifest_reader - > get ( ) - > file ( ) - > file_name ( ) ! = manifest_path ) {
TEST_SYNC_POINT (
" ReactiveVersionSet::MaybeSwitchManifest: "
" AfterGetCurrentManifestPath:0 " ) ;
TEST_SYNC_POINT (
" ReactiveVersionSet::MaybeSwitchManifest: "
" AfterGetCurrentManifestPath:1 " ) ;
s = fs_ - > NewSequentialFile ( manifest_path ,
fs_ - > OptimizeForManifestRead ( file_options_ ) ,
& manifest_file , nullptr ) ;
} else {
// No need to switch manifest.
break ;
}
}
std : : unique_ptr < SequentialFileReader > manifest_file_reader ;
if ( s . ok ( ) ) {
manifest_file_reader . reset ( new SequentialFileReader (
std : : move ( manifest_file ) , manifest_path ,
db_options_ - > log_readahead_size , io_tracer_ ) ) ;
manifest_reader - > reset ( new log : : FragmentBufferedReader (
nullptr , std : : move ( manifest_file_reader ) , reporter ,
true /* checksum */ , 0 /* log_number */ ) ) ;
ROCKS_LOG_INFO ( db_options_ - > info_log , " Switched to new manifest: %s \n " ,
manifest_path . c_str ( ) ) ;
if ( manifest_tailer_ ) {
manifest_tailer_ - > PrepareToReadNewManifest ( ) ;
}
}
} while ( s . IsPathNotFound ( ) ) ;
std : : string manifest_path ;
s = GetCurrentManifestPath ( dbname_ , fs_ . get ( ) , & manifest_path ,
& manifest_file_number_ ) ;
if ( ! s . ok ( ) ) {
return s ;
}
std : : unique_ptr < FSSequentialFile > manifest_file ;
if ( manifest_reader - > get ( ) ! = nullptr & &
manifest_reader - > get ( ) - > file ( ) - > file_name ( ) = = manifest_path ) {
// CURRENT points to the same MANIFEST as before, no need to switch
// MANIFEST.
return s ;
}
assert ( nullptr = = manifest_reader - > get ( ) | |
manifest_reader - > get ( ) - > file ( ) - > file_name ( ) ! = manifest_path ) ;
s = fs_ - > FileExists ( manifest_path , IOOptions ( ) , nullptr ) ;
if ( s . IsNotFound ( ) ) {
return Status : : TryAgain (
" The primary may have switched to a new MANIFEST and deleted the old "
" one. " ) ;
} else if ( ! s . ok ( ) ) {
return s ;
}
TEST_SYNC_POINT (
" ReactiveVersionSet::MaybeSwitchManifest: "
" AfterGetCurrentManifestPath:0 " ) ;
TEST_SYNC_POINT (
" ReactiveVersionSet::MaybeSwitchManifest: "
" AfterGetCurrentManifestPath:1 " ) ;
// The primary can also delete the MANIFEST while the secondary is reading
// it. This is OK on POSIX. For other file systems, maybe create a hard link
// to MANIFEST. The hard link should be cleaned up later by the secondary.
s = fs_ - > NewSequentialFile ( manifest_path ,
fs_ - > OptimizeForManifestRead ( file_options_ ) ,
& manifest_file , nullptr ) ;
std : : unique_ptr < SequentialFileReader > manifest_file_reader ;
if ( s . ok ( ) ) {
manifest_file_reader . reset (
new SequentialFileReader ( std : : move ( manifest_file ) , manifest_path ,
db_options_ - > log_readahead_size , io_tracer_ ) ) ;
manifest_reader - > reset ( new log : : FragmentBufferedReader (
nullptr , std : : move ( manifest_file_reader ) , reporter , true /* checksum */ ,
0 /* log_number */ ) ) ;
ROCKS_LOG_INFO ( db_options_ - > info_log , " Switched to new manifest: %s \n " ,
manifest_path . c_str ( ) ) ;
if ( manifest_tailer_ ) {
manifest_tailer_ - > PrepareToReadNewManifest ( ) ;
}
} else if ( s . IsPathNotFound ( ) ) {
// This can happen if the primary switches to a new MANIFEST after the
// secondary reads the CURRENT file but before the secondary actually tries
// to open the MANIFEST.
s = Status : : TryAgain (
" The primary may have switched to a new MANIFEST and deleted the old "
" one. " ) ;
}
return s ;
}