@ -399,7 +399,7 @@ IOStatus Directories::SetDirectories(FileSystem* fs, const std::string& dbname,
Status DBImpl : : Recover (
const std : : vector < ColumnFamilyDescriptor > & column_families , bool read_only ,
bool error_if_wal_file_exists , bool error_if_data_exists_in_wals ,
uint64_t * recovered_seq ) {
uint64_t * recovered_seq , RecoveryContext * recovery_ctx ) {
mutex_ . AssertHeld ( ) ;
bool is_new_db = false ;
@ -524,9 +524,9 @@ Status DBImpl::Recover(
return s ;
}
}
s = SetDBId ( read_only ) ;
s = SetDBId ( read_only , recovery_ctx ) ;
if ( s . ok ( ) & & ! read_only ) {
s = DeleteUnreferencedSstFiles ( ) ;
s = DeleteUnreferencedSstFiles ( recovery_ctx ) ;
}
if ( immutable_db_options_ . paranoid_checks & & s . ok ( ) ) {
@ -541,10 +541,6 @@ Status DBImpl::Recover(
}
}
}
// DB mutex is already held
if ( s . ok ( ) & & immutable_db_options_ . persist_stats_to_disk ) {
s = InitPersistStatsColumnFamily ( ) ;
}
std : : vector < std : : string > files_in_wal_dir ;
if ( s . ok ( ) ) {
@ -610,7 +606,10 @@ Status DBImpl::Recover(
WalNumber max_wal_number =
versions_ - > GetWalSet ( ) . GetWals ( ) . rbegin ( ) - > first ;
edit . DeleteWalsBefore ( max_wal_number + 1 ) ;
s = versions_ - > LogAndApplyToDefaultColumnFamily ( & edit , & mutex_ ) ;
assert ( recovery_ctx ! = nullptr ) ;
assert ( versions_ - > GetColumnFamilySet ( ) ! = nullptr ) ;
recovery_ctx - > UpdateVersionEdits (
versions_ - > GetColumnFamilySet ( ) - > GetDefault ( ) , edit ) ;
}
if ( ! s . ok ( ) ) {
return s ;
@ -646,8 +645,8 @@ Status DBImpl::Recover(
std : : sort ( wals . begin ( ) , wals . end ( ) ) ;
bool corrupted_wal_found = false ;
s = RecoverLogFiles ( wals , & next_sequence , read_only ,
& corrupted_wal_found ) ;
s = RecoverLogFiles ( wals , & next_sequence , read_only , & corrupted_wal_found ,
recovery_ctx ) ;
if ( corrupted_wal_found & & recovered_seq ! = nullptr ) {
* recovered_seq = next_sequence ;
}
@ -826,10 +825,30 @@ Status DBImpl::InitPersistStatsColumnFamily() {
return s ;
}
Status DBImpl : : LogAndApplyForRecovery ( const RecoveryContext & recovery_ctx ) {
mutex_ . AssertHeld ( ) ;
assert ( versions_ - > descriptor_log_ = = nullptr ) ;
Status s = versions_ - > LogAndApply (
recovery_ctx . cfds_ , recovery_ctx . mutable_cf_opts_ ,
recovery_ctx . edit_lists_ , & mutex_ , directories_ . GetDbDir ( ) ) ;
if ( s . ok ( ) & & ! ( recovery_ctx . files_to_delete_ . empty ( ) ) ) {
mutex_ . Unlock ( ) ;
for ( const auto & fname : recovery_ctx . files_to_delete_ ) {
s = env_ - > DeleteFile ( fname ) ;
if ( ! s . ok ( ) ) {
break ;
}
}
mutex_ . Lock ( ) ;
}
return s ;
}
// REQUIRES: wal_numbers are sorted in ascending order
Status DBImpl : : RecoverLogFiles ( const std : : vector < uint64_t > & wal_numbers ,
SequenceNumber * next_sequence , bool read_only ,
bool * corrupted_wal_found ) {
bool * corrupted_wal_found ,
RecoveryContext * recovery_ctx ) {
struct LogReporter : public log : : Reader : : Reporter {
Env * env ;
Logger * info_log ;
@ -1287,44 +1306,36 @@ Status DBImpl::RecoverLogFiles(const std::vector<uint64_t>& wal_numbers,
// VersionSet::next_file_number_ always to be strictly greater than any
// log number
versions_ - > MarkFileNumberUsed ( max_wal_number + 1 ) ;
assert ( recovery_ctx ! = nullptr ) ;
autovector < ColumnFamilyData * > cfds ;
autovector < const MutableCFOptions * > cf_opts ;
autovector < autovector < VersionEdit * > > edit_lists ;
for ( auto * cfd : * versions_ - > GetColumnFamilySet ( ) ) {
cfds . push_back ( cfd ) ;
cf_opts . push_back ( cfd - > GetLatestMutableCFOptions ( ) ) ;
auto iter = version_edits . find ( cfd - > GetID ( ) ) ;
assert ( iter ! = version_edits . end ( ) ) ;
edit_lists . push_back ( { & iter - > second } ) ;
recovery_ctx - > UpdateVersionEdits ( cfd , iter - > second ) ;
}
std : : unique_ptr < VersionEdit > wal_deletion ;
if ( flushed ) {
wal_deletion = std : : make_unique < VersionEdit > ( ) ;
VersionEdit wal_deletion ;
if ( immutable_db_options_ . track_and_verify_wals_in_manifest ) {
wal_deletion - > DeleteWalsBefore ( max_wal_number + 1 ) ;
wal_deletion . DeleteWalsBefore ( max_wal_number + 1 ) ;
}
if ( ! allow_2pc ( ) ) {
// In non-2pc mode, flushing the memtables of the column families
// means we can advance min_log_number_to_keep.
wal_deletion - > SetMinLogNumberToKeep ( max_wal_number + 1 ) ;
wal_deletion . SetMinLogNumberToKeep ( max_wal_number + 1 ) ;
}
edit_lists . back ( ) . push_back ( wal_deletion . get ( ) ) ;
assert ( versions_ - > GetColumnFamilySet ( ) ! = nullptr ) ;
recovery_ctx - > UpdateVersionEdits (
versions_ - > GetColumnFamilySet ( ) - > GetDefault ( ) , wal_deletion ) ;
}
// write MANIFEST with update
status = versions_ - > LogAndApply ( cfds , cf_opts , edit_lists , & mutex_ ,
directories_ . GetDbDir ( ) ,
/*new_descriptor_log=*/ true ) ;
}
}
if ( status . ok ( ) ) {
if ( data_seen & & ! flushed ) {
status = RestoreAliveLogFiles ( wal_numbers ) ;
} else {
// If there's no data in the WAL, or we flushed all the data, still
} else if ( ! wal_numbers . empty ( ) ) { // If there's no data in the WAL, or we
// flushed all the data, still
// truncate the log file. If the process goes into a crash loop before
// the file is deleted, the preallocated space will never get freed.
const bool truncate = ! read_only ;
@ -1720,6 +1731,7 @@ Status DBImpl::Open(const DBOptions& db_options, const std::string& dbname,
}
* dbptr = nullptr ;
assert ( handles ) ;
handles - > clear ( ) ;
size_t max_write_buffer_size = 0 ;
@ -1767,11 +1779,13 @@ Status DBImpl::Open(const DBOptions& db_options, const std::string& dbname,
}
impl - > wal_in_db_path_ = impl - > immutable_db_options_ . IsWalDirSameAsDBPath ( ) ;
RecoveryContext recovery_ctx ;
impl - > mutex_ . Lock ( ) ;
// Handles create_if_missing, error_if_exists
uint64_t recovered_seq ( kMaxSequenceNumber ) ;
s = impl - > Recover ( column_families , false , false , false , & recovered_seq ) ;
s = impl - > Recover ( column_families , false , false , false , & recovered_seq ,
& recovery_ctx ) ;
if ( s . ok ( ) ) {
uint64_t new_log_number = impl - > versions_ - > NewFileNumber ( ) ;
log : : Writer * new_log = nullptr ;
@ -1788,40 +1802,6 @@ Status DBImpl::Open(const DBOptions& db_options, const std::string& dbname,
}
if ( s . ok ( ) ) {
// set column family handles
for ( auto cf : column_families ) {
auto cfd =
impl - > versions_ - > GetColumnFamilySet ( ) - > GetColumnFamily ( cf . name ) ;
if ( cfd ! = nullptr ) {
handles - > push_back (
new ColumnFamilyHandleImpl ( cfd , impl , & impl - > mutex_ ) ) ;
impl - > NewThreadStatusCfInfo ( cfd ) ;
} else {
if ( db_options . create_missing_column_families ) {
// missing column family, create it
ColumnFamilyHandle * handle ;
impl - > mutex_ . Unlock ( ) ;
s = impl - > CreateColumnFamily ( cf . options , cf . name , & handle ) ;
impl - > mutex_ . Lock ( ) ;
if ( s . ok ( ) ) {
handles - > push_back ( handle ) ;
} else {
break ;
}
} else {
s = Status : : InvalidArgument ( " Column family not found " , cf . name ) ;
break ;
}
}
}
}
if ( s . ok ( ) ) {
SuperVersionContext sv_context ( /* create_superversion */ true ) ;
for ( auto cfd : * impl - > versions_ - > GetColumnFamilySet ( ) ) {
impl - > InstallSuperVersionAndScheduleWork (
cfd , & sv_context , * cfd - > GetLatestMutableCFOptions ( ) ) ;
}
sv_context . Clean ( ) ;
if ( impl - > two_write_queues_ ) {
impl - > log_write_mutex_ . Lock ( ) ;
}
@ -1861,6 +1841,53 @@ Status DBImpl::Open(const DBOptions& db_options, const std::string& dbname,
}
}
}
if ( s . ok ( ) ) {
s = impl - > LogAndApplyForRecovery ( recovery_ctx ) ;
}
if ( s . ok ( ) & & impl - > immutable_db_options_ . persist_stats_to_disk ) {
impl - > mutex_ . AssertHeld ( ) ;
s = impl - > InitPersistStatsColumnFamily ( ) ;
}
if ( s . ok ( ) ) {
// set column family handles
for ( auto cf : column_families ) {
auto cfd =
impl - > versions_ - > GetColumnFamilySet ( ) - > GetColumnFamily ( cf . name ) ;
if ( cfd ! = nullptr ) {
handles - > push_back (
new ColumnFamilyHandleImpl ( cfd , impl , & impl - > mutex_ ) ) ;
impl - > NewThreadStatusCfInfo ( cfd ) ;
} else {
if ( db_options . create_missing_column_families ) {
// missing column family, create it
ColumnFamilyHandle * handle = nullptr ;
impl - > mutex_ . Unlock ( ) ;
s = impl - > CreateColumnFamily ( cf . options , cf . name , & handle ) ;
impl - > mutex_ . Lock ( ) ;
if ( s . ok ( ) ) {
handles - > push_back ( handle ) ;
} else {
break ;
}
} else {
s = Status : : InvalidArgument ( " Column family not found " , cf . name ) ;
break ;
}
}
}
}
if ( s . ok ( ) ) {
SuperVersionContext sv_context ( /* create_superversion */ true ) ;
for ( auto cfd : * impl - > versions_ - > GetColumnFamilySet ( ) ) {
impl - > InstallSuperVersionAndScheduleWork (
cfd , & sv_context , * cfd - > GetLatestMutableCFOptions ( ) ) ;
}
sv_context . Clean ( ) ;
}
if ( s . ok ( ) & & impl - > immutable_db_options_ . persist_stats_to_disk ) {
// try to read format version
s = impl - > PersistentStatsProcessFormatVersion ( ) ;