@ -88,9 +88,10 @@ class BackupEngineImpl : public BackupEngine {
BackupEngineImpl ( Env * db_env , const BackupableDBOptions & options ,
bool read_only = false ) ;
~ BackupEngineImpl ( ) ;
Status CreateNewBackup ( DB * db , bool flush_before_backup = false ,
std : : function < void ( ) > progress_callback = [ ] ( ) {
} ) override ;
Status CreateNewBackupWithMetadata ( DB * db , const std : : string & app_metadata ,
bool flush_before_backup = false ,
std : : function < void ( ) > progress_callback =
[ ] ( ) { } ) override ;
Status PurgeOldBackups ( uint32_t num_backups_to_keep ) override ;
Status DeleteBackup ( BackupID backup_id ) override ;
void StopBackup ( ) override {
@ -166,6 +167,12 @@ class BackupEngineImpl : public BackupEngine {
return sequence_number_ ;
}
const std : : string & GetAppMetadata ( ) const { return app_metadata_ ; }
void SetAppMetadata ( const std : : string & app_metadata ) {
app_metadata_ = app_metadata ;
}
Status AddFile ( std : : shared_ptr < FileInfo > file_info ) ;
Status Delete ( bool delete_meta = true ) ;
@ -212,6 +219,7 @@ class BackupEngineImpl : public BackupEngine {
// by clients
uint64_t sequence_number_ ;
uint64_t size_ ;
std : : string app_metadata_ ;
std : : string const meta_filename_ ;
// files with relative paths (without "/" prefix!!)
std : : vector < std : : shared_ptr < FileInfo > > files_ ;
@ -464,6 +472,7 @@ class BackupEngineImpl : public BackupEngine {
size_t copy_file_buffer_size_ ;
bool read_only_ ;
BackupStatistics backup_statistics_ ;
static const size_t kMaxAppMetaSize = 1024 * 1024 ; // 1MB
} ;
Status BackupEngine : : Open ( Env * env , const BackupableDBOptions & options ,
@ -641,10 +650,14 @@ Status BackupEngineImpl::Initialize() {
return Status : : OK ( ) ;
}
Status BackupEngineImpl : : CreateNewBackup (
DB * db , bool flush_before_backup , std : : function < void ( ) > progress_callback ) {
Status BackupEngineImpl : : CreateNewBackupWithMetadata (
DB * db , const std : : string & app_metadata , bool flush_before_backup ,
std : : function < void ( ) > progress_callback ) {
assert ( initialized_ ) ;
assert ( ! read_only_ ) ;
if ( app_metadata . size ( ) > kMaxAppMetaSize ) {
return Status : : InvalidArgument ( " App metadata too large " ) ;
}
Status s ;
std : : vector < std : : string > live_files ;
VectorLogPtr live_wal_files ;
@ -678,6 +691,7 @@ Status BackupEngineImpl::CreateNewBackup(
auto & new_backup = ret . first - > second ;
new_backup - > RecordTimestamp ( ) ;
new_backup - > SetSequenceNumber ( sequence_number ) ;
new_backup - > SetAppMetadata ( app_metadata ) ;
auto start_backup = backup_env_ - > NowMicros ( ) ;
@ -957,10 +971,9 @@ void BackupEngineImpl::GetBackupInfo(std::vector<BackupInfo>* backup_info) {
backup_info - > reserve ( backups_ . size ( ) ) ;
for ( auto & backup : backups_ ) {
if ( ! backup . second - > Empty ( ) ) {
backup_info - > push_back ( BackupInfo (
backup . first , backup . second - > GetTimestamp ( ) ,
backup . second - > GetSize ( ) ,
backup . second - > GetNumberFiles ( ) ) ) ;
backup_info - > push_back ( BackupInfo (
backup . first , backup . second - > GetTimestamp ( ) , backup . second - > GetSize ( ) ,
backup . second - > GetNumberFiles ( ) , backup . second - > GetAppMetadata ( ) ) ) ;
}
}
}
@ -1562,9 +1575,12 @@ Status BackupEngineImpl::BackupMeta::Delete(bool delete_meta) {
return s ;
}
Slice kMetaDataPrefix ( " metadata " ) ;
// each backup meta file is of the format:
// <timestamp>
// <seq number>
// <metadata(literal string)> <metadata> (optional)
// <number of files>
// <file1> <crc32(literal string)> <crc32_value>
// <file2> <crc32(literal string)> <crc32_value>
@ -1597,6 +1613,18 @@ Status BackupEngineImpl::BackupMeta::LoadFromFile(
data . remove_prefix ( next - data . data ( ) + 1 ) ; // +1 for '\n'
sequence_number_ = strtoull ( data . data ( ) , & next , 10 ) ;
data . remove_prefix ( next - data . data ( ) + 1 ) ; // +1 for '\n'
if ( data . starts_with ( kMetaDataPrefix ) ) {
// app metadata present
data . remove_prefix ( kMetaDataPrefix . size ( ) ) ;
Slice hex_encoded_metadata = GetSliceUntil ( & data , ' \n ' ) ;
bool decode_success = hex_encoded_metadata . DecodeHex ( & app_metadata_ ) ;
if ( ! decode_success ) {
return Status : : Corruption (
" Failed to decode stored hex encoded app metadata " ) ;
}
}
num_files = static_cast < uint32_t > ( strtoul ( data . data ( ) , & next , 10 ) ) ;
data . remove_prefix ( next - data . data ( ) + 1 ) ; // +1 for '\n'
@ -1678,6 +1706,20 @@ Status BackupEngineImpl::BackupMeta::StoreToFile(bool sync) {
len + = snprintf ( buf . get ( ) , buf_size , " % " PRId64 " \n " , timestamp_ ) ;
len + = snprintf ( buf . get ( ) + len , buf_size - len , " % " PRIu64 " \n " ,
sequence_number_ ) ;
if ( ! app_metadata_ . empty ( ) ) {
std : : string hex_encoded_metadata =
Slice ( app_metadata_ ) . ToString ( /* hex */ true ) ;
if ( hex_encoded_metadata . size ( ) + kMetaDataPrefix . size ( ) + 1 >
( size_t ) ( buf_size - len ) ) {
return Status : : Corruption ( " Buffer too small to fit backup metadata " ) ;
}
memcpy ( buf . get ( ) + len , kMetaDataPrefix . data ( ) , kMetaDataPrefix . size ( ) ) ;
len + = kMetaDataPrefix . size ( ) ;
memcpy ( buf . get ( ) + len , hex_encoded_metadata . data ( ) ,
hex_encoded_metadata . size ( ) ) ;
len + = hex_encoded_metadata . size ( ) ;
buf [ len + + ] = ' \n ' ;
}
len + = snprintf ( buf . get ( ) + len , buf_size - len , " % " ROCKSDB_PRIszt " \n " ,
files_ . size ( ) ) ;
for ( const auto & file : files_ ) {