@ -186,6 +186,9 @@ class BackupEngineImpl : public BackupEngine {
inline std : : string GetPrivateDirRel ( ) const {
inline std : : string GetPrivateDirRel ( ) const {
return " private " ;
return " private " ;
}
}
inline std : : string GetSharedChecksumDirRel ( ) const {
return " shared_checksum " ;
}
inline std : : string GetPrivateFileRel ( BackupID backup_id ,
inline std : : string GetPrivateFileRel ( BackupID backup_id ,
bool tmp = false ,
bool tmp = false ,
const std : : string & file = " " ) const {
const std : : string & file = " " ) const {
@ -198,6 +201,27 @@ class BackupEngineImpl : public BackupEngine {
assert ( file . size ( ) = = 0 | | file [ 0 ] ! = ' / ' ) ;
assert ( file . size ( ) = = 0 | | file [ 0 ] ! = ' / ' ) ;
return " shared/ " + file + ( tmp ? " .tmp " : " " ) ;
return " shared/ " + file + ( tmp ? " .tmp " : " " ) ;
}
}
inline std : : string GetSharedFileWithChecksumRel ( const std : : string & file = " " ,
bool tmp = false ) const {
assert ( file . size ( ) = = 0 | | file [ 0 ] ! = ' / ' ) ;
return GetSharedChecksumDirRel ( ) + " / " + file + ( tmp ? " .tmp " : " " ) ;
}
inline std : : string GetSharedFileWithChecksum ( const std : : string & file ,
const uint32_t checksum_value ,
const uint64_t file_size ) const {
assert ( file . size ( ) = = 0 | | file [ 0 ] ! = ' / ' ) ;
std : : string file_copy = file ;
return file_copy . insert ( file_copy . find_last_of ( ' . ' ) ,
" _ " + std : : to_string ( checksum_value )
+ " _ " + std : : to_string ( file_size ) ) ;
}
inline std : : string GetFileFromChecksumFile ( const std : : string & file ) const {
assert ( file . size ( ) = = 0 | | file [ 0 ] ! = ' / ' ) ;
std : : string file_copy = file ;
size_t first_underscore = file_copy . find_first_of ( ' _ ' ) ;
return file_copy . erase ( first_underscore ,
file_copy . find_last_of ( ' . ' ) - first_underscore ) ;
}
inline std : : string GetLatestBackupFile ( bool tmp = false ) const {
inline std : : string GetLatestBackupFile ( bool tmp = false ) const {
return GetAbsolutePath ( std : : string ( " LATEST_BACKUP " ) + ( tmp ? " .tmp " : " " ) ) ;
return GetAbsolutePath ( std : : string ( " LATEST_BACKUP " ) + ( tmp ? " .tmp " : " " ) ) ;
}
}
@ -227,7 +251,8 @@ class BackupEngineImpl : public BackupEngine {
const std : : string & src_dir ,
const std : : string & src_dir ,
const std : : string & src_fname , // starts with "/"
const std : : string & src_fname , // starts with "/"
RateLimiter * rate_limiter ,
RateLimiter * rate_limiter ,
uint64_t size_limit = 0 ) ;
uint64_t size_limit = 0 ,
bool shared_checksum = false ) ;
Status CalculateChecksum ( const std : : string & src ,
Status CalculateChecksum ( const std : : string & src ,
Env * src_env ,
Env * src_env ,
@ -286,10 +311,17 @@ BackupEngineImpl::BackupEngineImpl(Env* db_env,
backup_env_ - > CreateDirIfMissing ( GetAbsolutePath ( ) ) ;
backup_env_ - > CreateDirIfMissing ( GetAbsolutePath ( ) ) ;
backup_env_ - > NewDirectory ( GetAbsolutePath ( ) , & backup_directory_ ) ;
backup_env_ - > NewDirectory ( GetAbsolutePath ( ) , & backup_directory_ ) ;
if ( options_ . share_table_files ) {
if ( options_ . share_table_files ) {
if ( options_ . share_files_with_checksum ) {
backup_env_ - > CreateDirIfMissing ( GetAbsolutePath (
GetSharedFileWithChecksumRel ( ) ) ) ;
backup_env_ - > NewDirectory ( GetAbsolutePath (
GetSharedFileWithChecksumRel ( ) ) , & shared_directory_ ) ;
} else {
backup_env_ - > CreateDirIfMissing ( GetAbsolutePath ( GetSharedFileRel ( ) ) ) ;
backup_env_ - > CreateDirIfMissing ( GetAbsolutePath ( GetSharedFileRel ( ) ) ) ;
backup_env_ - > NewDirectory ( GetAbsolutePath ( GetSharedFileRel ( ) ) ,
backup_env_ - > NewDirectory ( GetAbsolutePath ( GetSharedFileRel ( ) ) ,
& shared_directory_ ) ;
& shared_directory_ ) ;
}
}
}
backup_env_ - > CreateDirIfMissing ( GetAbsolutePath ( GetPrivateDirRel ( ) ) ) ;
backup_env_ - > CreateDirIfMissing ( GetAbsolutePath ( GetPrivateDirRel ( ) ) ) ;
backup_env_ - > NewDirectory ( GetAbsolutePath ( GetPrivateDirRel ( ) ) ,
backup_env_ - > NewDirectory ( GetAbsolutePath ( GetPrivateDirRel ( ) ) ,
& private_directory_ ) ;
& private_directory_ ) ;
@ -436,7 +468,7 @@ Status BackupEngineImpl::CreateNewBackup(DB* db, bool flush_before_backup) {
type = = kCurrentFile ) ;
type = = kCurrentFile ) ;
// rules:
// rules:
// * if it's kTableFile, tha n it's shared
// * if it's kTableFile, the n it's shared
// * if it's kDescriptorFile, limit the size to manifest_file_size
// * if it's kDescriptorFile, limit the size to manifest_file_size
s = BackupFile ( new_backup_id ,
s = BackupFile ( new_backup_id ,
& new_backup ,
& new_backup ,
@ -444,7 +476,8 @@ Status BackupEngineImpl::CreateNewBackup(DB* db, bool flush_before_backup) {
db - > GetName ( ) , /* src_dir */
db - > GetName ( ) , /* src_dir */
live_files [ i ] , /* src_fname */
live_files [ i ] , /* src_fname */
rate_limiter . get ( ) ,
rate_limiter . get ( ) ,
( type = = kDescriptorFile ) ? manifest_file_size : 0 ) ;
( type = = kDescriptorFile ) ? manifest_file_size : 0 ,
options_ . share_files_with_checksum & & type = = kTableFile ) ;
}
}
// copy WAL files
// copy WAL files
@ -614,10 +647,17 @@ Status BackupEngineImpl::RestoreDBFromBackup(
std : : string dst ;
std : : string dst ;
// 1. extract the filename
// 1. extract the filename
size_t slash = file . find_last_of ( ' / ' ) ;
size_t slash = file . find_last_of ( ' / ' ) ;
// file will either be shared/<file> or private/<number>/<file>
// file will either be shared/<file>, shared_checksum/<file_crc32_size>
// or private/<number>/<file>
assert ( slash ! = std : : string : : npos ) ;
assert ( slash ! = std : : string : : npos ) ;
dst = file . substr ( slash + 1 ) ;
dst = file . substr ( slash + 1 ) ;
// if the file was in shared_checksum, extract the real file name
// in this case the file is <number>_<checksum>_<size>.<type>
if ( file . substr ( 0 , slash ) = = GetSharedChecksumDirRel ( ) ) {
dst = GetFileFromChecksumFile ( dst ) ;
}
// 2. find the filetype
// 2. find the filetype
uint64_t number ;
uint64_t number ;
FileType type ;
FileType type ;
@ -785,12 +825,33 @@ Status BackupEngineImpl::BackupFile(BackupID backup_id, BackupMeta* backup,
bool shared , const std : : string & src_dir ,
bool shared , const std : : string & src_dir ,
const std : : string & src_fname ,
const std : : string & src_fname ,
RateLimiter * rate_limiter ,
RateLimiter * rate_limiter ,
uint64_t size_limit ) {
uint64_t size_limit ,
bool shared_checksum ) {
assert ( src_fname . size ( ) > 0 & & src_fname [ 0 ] = = ' / ' ) ;
assert ( src_fname . size ( ) > 0 & & src_fname [ 0 ] = = ' / ' ) ;
std : : string dst_relative = src_fname . substr ( 1 ) ;
std : : string dst_relative = src_fname . substr ( 1 ) ;
std : : string dst_relative_tmp ;
std : : string dst_relative_tmp ;
if ( shared ) {
Status s ;
uint64_t size ;
uint32_t checksum_value = 0 ;
if ( shared & & shared_checksum ) {
// add checksum and file length to the file name
s = CalculateChecksum ( src_dir + src_fname ,
db_env_ ,
size_limit ,
& checksum_value ) ;
if ( s . ok ( ) ) {
s = db_env_ - > GetFileSize ( src_dir + src_fname , & size ) ;
}
if ( ! s . ok ( ) ) {
return s ;
}
dst_relative = GetSharedFileWithChecksum ( dst_relative , checksum_value ,
size ) ;
dst_relative_tmp = GetSharedFileWithChecksumRel ( dst_relative , true ) ;
dst_relative = GetSharedFileWithChecksumRel ( dst_relative , false ) ;
} else if ( shared ) {
dst_relative_tmp = GetSharedFileRel ( dst_relative , true ) ;
dst_relative_tmp = GetSharedFileRel ( dst_relative , true ) ;
dst_relative = GetSharedFileRel ( dst_relative , false ) ;
dst_relative = GetSharedFileRel ( dst_relative , false ) ;
} else {
} else {
@ -799,13 +860,15 @@ Status BackupEngineImpl::BackupFile(BackupID backup_id, BackupMeta* backup,
}
}
std : : string dst_path = GetAbsolutePath ( dst_relative ) ;
std : : string dst_path = GetAbsolutePath ( dst_relative ) ;
std : : string dst_path_tmp = GetAbsolutePath ( dst_relative_tmp ) ;
std : : string dst_path_tmp = GetAbsolutePath ( dst_relative_tmp ) ;
Status s ;
uint64_t size ;
// if it's shared, we also need to check if it exists -- if it does,
// if it's shared, we also need to check if it exists -- if it does,
// no need to copy it again
// no need to copy it again
uint32_t checksum_value = 0 ;
if ( shared & & backup_env_ - > FileExists ( dst_path ) ) {
if ( shared & & backup_env_ - > FileExists ( dst_path ) ) {
if ( shared_checksum ) {
Log ( options_ . info_log ,
" %s already present, with checksum %u and size % " PRIu64 ,
src_fname . c_str ( ) , checksum_value , size ) ;
} else {
backup_env_ - > GetFileSize ( dst_path , & size ) ; // Ignore error
backup_env_ - > GetFileSize ( dst_path , & size ) ; // Ignore error
Log ( options_ . info_log , " %s already present, calculate checksum " ,
Log ( options_ . info_log , " %s already present, calculate checksum " ,
src_fname . c_str ( ) ) ;
src_fname . c_str ( ) ) ;
@ -813,6 +876,7 @@ Status BackupEngineImpl::BackupFile(BackupID backup_id, BackupMeta* backup,
db_env_ ,
db_env_ ,
size_limit ,
size_limit ,
& checksum_value ) ;
& checksum_value ) ;
}
} else {
} else {
Log ( options_ . info_log , " Copying %s " , src_fname . c_str ( ) ) ;
Log ( options_ . info_log , " Copying %s " , src_fname . c_str ( ) ) ;
s = CopyFile ( src_dir + src_fname ,
s = CopyFile ( src_dir + src_fname ,