#################################################################################################################################### # BACKUP COMMON MODULE #################################################################################################################################### package pgBackRest::Backup::Common; use strict; use warnings FATAL => qw(all); use Carp qw(confess); use Exporter qw(import); our @EXPORT = qw(); use File::Basename; use pgBackRest::Common::Log; use pgBackRest::Common::String; use pgBackRest::Common::Wait; use pgBackRest::Config::Config; use pgBackRest::Protocol::Storage::Helper; use pgBackRest::Storage::Helper; use pgBackRest::Manifest; #################################################################################################################################### # Latest backup link constant #################################################################################################################################### use constant LINK_LATEST => 'latest'; push @EXPORT, qw(LINK_LATEST); #################################################################################################################################### # backupRegExpGet # # Generate a regexp depending on the backups that need to be found. #################################################################################################################################### sub backupRegExpGet { # Assign function parameters, defaults, and log debug info my ( $strOperation, $bFull, $bDifferential, $bIncremental, $bAnchor ) = logDebugParam ( __PACKAGE__ . '::backupRegExpGet', \@_, {name => 'bFull', default => false}, {name => 'bDifferential', default => false}, {name => 'bIncremental', default => false}, {name => 'bAnchor', default => true} ); # One of the types must be selected if (!($bFull || $bDifferential || $bIncremental)) { confess &log(ASSERT, 'at least one backup type must be selected'); } # Standard regexp to match date and time formattting my $strDateTimeRegExp = "[0-9]{8}\\-[0-9]{6}"; # Start the expression with the anchor if requested, date/time regexp and full backup indicator my $strRegExp = ($bAnchor ? '^' : '') . $strDateTimeRegExp . 'F'; # Add the diff and/or incr expressions if requested if ($bDifferential || $bIncremental) { # If full requested then diff/incr is optional if ($bFull) { $strRegExp .= "(\\_"; } # Else diff/incr is required else { $strRegExp .= "\\_"; } # Append date/time regexp for diff/incr $strRegExp .= $strDateTimeRegExp; # Filter on both diff/incr if ($bDifferential && $bIncremental) { $strRegExp .= '(D|I)'; } # Else just diff elsif ($bDifferential) { $strRegExp .= 'D'; } # Else just incr else { $strRegExp .= 'I'; } # If full requested then diff/incr is optional if ($bFull) { $strRegExp .= '){0,1}'; } } # Append the end anchor if requested $strRegExp .= $bAnchor ? "\$" : ''; # Return from function and log return values if any return logDebugReturn ( $strOperation, {name => 'strRegExp', value => $strRegExp} ); } push @EXPORT, qw(backupRegExpGet); #################################################################################################################################### # backupLabelFormat # # Format the label for a backup. #################################################################################################################################### sub backupLabelFormat { # Assign function parameters, defaults, and log debug info my ( $strOperation, $strType, $strBackupLabelLast, $lTimestampStart ) = logDebugParam ( __PACKAGE__ . '::backupLabelFormat', \@_, {name => 'strType', trace => true}, {name => 'strBackupLabelLast', required => false, trace => true}, {name => 'lTimestampTart', trace => true} ); # Full backup label my $strBackupLabel; if ($strType eq CFGOPTVAL_BACKUP_TYPE_FULL) { # Last backup label must not be defined if (defined($strBackupLabelLast)) { confess &log(ASSERT, "strBackupLabelLast must not be defined when strType = '${strType}'"); } # Format the timestamp and add the full indicator $strBackupLabel = timestampFileFormat(undef, $lTimestampStart) . 'F'; } # Else diff or incr label else { # Last backup label must be defined if (!defined($strBackupLabelLast)) { confess &log(ASSERT, "strBackupLabelLast must be defined when strType = '${strType}'"); } # Get the full backup portion of the last backup label $strBackupLabel = substr($strBackupLabelLast, 0, 16); # Format the timestamp $strBackupLabel .= '_' . timestampFileFormat(undef, $lTimestampStart); # Add the diff indicator if ($strType eq CFGOPTVAL_BACKUP_TYPE_DIFF) { $strBackupLabel .= 'D'; } # Else incr indicator else { $strBackupLabel .= 'I'; } } # Return from function and log return values if any return logDebugReturn ( $strOperation, {name => 'strBackupLabel', value => $strBackupLabel, trace => true} ); } push @EXPORT, qw(backupLabelFormat); #################################################################################################################################### # backupLabel # # Get unique backup label. #################################################################################################################################### sub backupLabel { # Assign function parameters, defaults, and log debug info my ( $strOperation, $oStorageRepo, $strType, $strBackupLabelLast, $lTimestampStart ) = logDebugParam ( __PACKAGE__ . '::backupLabelFormat', \@_, {name => 'oStorageRepo', trace => true}, {name => 'strType', trace => true}, {name => 'strBackupLabelLast', required => false, trace => true}, {name => 'lTimestampStart', trace => true} ); # Create backup label my $strBackupLabel = backupLabelFormat($strType, $strBackupLabelLast, $lTimestampStart); # Make sure that the timestamp has not already been used by a prior backup. This is unlikely for online backups since there is # already a wait after the manifest is built but it's still possible if the remote and local systems don't have synchronized # clocks. In practice this is most useful for making offline testing faster since it allows the wait after manifest build to # be skipped by dealing with any backup label collisions here. if ($oStorageRepo->list( STORAGE_REPO_BACKUP, {strExpression => ($strType eq CFGOPTVAL_BACKUP_TYPE_FULL ? '^' : '_') . timestampFileFormat(undef, $lTimestampStart) . ($strType eq CFGOPTVAL_BACKUP_TYPE_FULL ? 'F' : '(D|I)$')}) || $oStorageRepo->list( STORAGE_REPO_BACKUP . qw{/} . PATH_BACKUP_HISTORY . '/' . timestampFormat('%4d', $lTimestampStart), {strExpression => ($strType eq CFGOPTVAL_BACKUP_TYPE_FULL ? '^' : '_') . timestampFileFormat(undef, $lTimestampStart) . ($strType eq CFGOPTVAL_BACKUP_TYPE_FULL ? 'F' : '(D|I)\.manifest\.' . COMPRESS_EXT . qw{$}), bIgnoreMissing => true})) { waitRemainder(); $strBackupLabel = backupLabelFormat($strType, $strBackupLabelLast, time()); } # Return from function and log return values if any return logDebugReturn ( $strOperation, {name => 'strBackupLabel', value => $strBackupLabel, trace => true} ); } push @EXPORT, qw(backupLabel); 1;