|
|
@ -13,6 +13,7 @@ |
|
|
|
|
|
|
|
|
|
|
|
namespace rocksdb { |
|
|
|
namespace rocksdb { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// A wrapper class to hold log reader, log reporter, log status.
|
|
|
|
class LogReaderContainer { |
|
|
|
class LogReaderContainer { |
|
|
|
public: |
|
|
|
public: |
|
|
|
LogReaderContainer() |
|
|
|
LogReaderContainer() |
|
|
@ -62,11 +63,19 @@ class LogReaderContainer { |
|
|
|
}; |
|
|
|
}; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// The secondary instance shares access to the storage as the primary.
|
|
|
|
|
|
|
|
// The secondary is able to read and replay changes described in both the
|
|
|
|
|
|
|
|
// MANIFEST and the WAL files without coordination with the primary.
|
|
|
|
|
|
|
|
// The secondary instance can be opened using `DB::OpenAsSecondary`. After
|
|
|
|
|
|
|
|
// that, it can call `DBImplSecondary::TryCatchUpWithPrimary` to make best
|
|
|
|
|
|
|
|
// effort attempts to catch up with the primary.
|
|
|
|
class DBImplSecondary : public DBImpl { |
|
|
|
class DBImplSecondary : public DBImpl { |
|
|
|
public: |
|
|
|
public: |
|
|
|
DBImplSecondary(const DBOptions& options, const std::string& dbname); |
|
|
|
DBImplSecondary(const DBOptions& options, const std::string& dbname); |
|
|
|
~DBImplSecondary() override; |
|
|
|
~DBImplSecondary() override; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Recover by replaying MANIFEST and WAL. Also initialize manifest_reader_
|
|
|
|
|
|
|
|
// and log_readers_ to facilitate future operations.
|
|
|
|
Status Recover(const std::vector<ColumnFamilyDescriptor>& column_families, |
|
|
|
Status Recover(const std::vector<ColumnFamilyDescriptor>& column_families, |
|
|
|
bool read_only, bool error_if_log_file_exist, |
|
|
|
bool read_only, bool error_if_log_file_exist, |
|
|
|
bool error_if_data_exists_in_logs) override; |
|
|
|
bool error_if_data_exists_in_logs) override; |
|
|
@ -182,10 +191,15 @@ class DBImplSecondary : public DBImpl { |
|
|
|
// method can take long time due to all the I/O and CPU costs.
|
|
|
|
// method can take long time due to all the I/O and CPU costs.
|
|
|
|
Status TryCatchUpWithPrimary() override; |
|
|
|
Status TryCatchUpWithPrimary() override; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Try to find log reader using log_number from log_readers_ map, initialize
|
|
|
|
|
|
|
|
// if it doesn't exist
|
|
|
|
Status MaybeInitLogReader(uint64_t log_number, |
|
|
|
Status MaybeInitLogReader(uint64_t log_number, |
|
|
|
log::FragmentBufferedReader** log_reader); |
|
|
|
log::FragmentBufferedReader** log_reader); |
|
|
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
protected: |
|
|
|
|
|
|
|
// ColumnFamilyCollector is a write batch handler which does nothing
|
|
|
|
|
|
|
|
// except recording unique column family IDs
|
|
|
|
class ColumnFamilyCollector : public WriteBatch::Handler { |
|
|
|
class ColumnFamilyCollector : public WriteBatch::Handler { |
|
|
|
std::unordered_set<uint32_t> column_family_ids_; |
|
|
|
std::unordered_set<uint32_t> column_family_ids_; |
|
|
|
|
|
|
|
|
|
|
@ -262,6 +276,8 @@ class DBImplSecondary : public DBImpl { |
|
|
|
std::unordered_set<ColumnFamilyData*>* cfds_changed, |
|
|
|
std::unordered_set<ColumnFamilyData*>* cfds_changed, |
|
|
|
JobContext* job_context); |
|
|
|
JobContext* job_context); |
|
|
|
Status FindNewLogNumbers(std::vector<uint64_t>* logs); |
|
|
|
Status FindNewLogNumbers(std::vector<uint64_t>* logs); |
|
|
|
|
|
|
|
// After manifest recovery, replay WALs and refresh log_readers_ if necessary
|
|
|
|
|
|
|
|
// REQUIRES: log_numbers are sorted in ascending order
|
|
|
|
Status RecoverLogFiles(const std::vector<uint64_t>& log_numbers, |
|
|
|
Status RecoverLogFiles(const std::vector<uint64_t>& log_numbers, |
|
|
|
SequenceNumber* next_sequence, |
|
|
|
SequenceNumber* next_sequence, |
|
|
|
std::unordered_set<ColumnFamilyData*>* cfds_changed, |
|
|
|
std::unordered_set<ColumnFamilyData*>* cfds_changed, |
|
|
|