You've already forked pgbackrest
mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2026-01-06 08:01:21 +03:00
Add stanza-delete command to cleanup unused stanzas.
Contributed by Cynthia Shang.
This commit is contained in:
committed by
David Steele
parent
526acca5bd
commit
0e9ba98a50
@@ -13,8 +13,11 @@ use English '-no_match_vars';
|
||||
use Exporter qw(import);
|
||||
our @EXPORT = qw();
|
||||
|
||||
use pgBackRest::Backup::Common;
|
||||
use pgBackRest::Common::Cipher;
|
||||
use pgBackRest::Common::Exception;
|
||||
use pgBackRest::Common::Ini;
|
||||
use pgBackRest::Common::Lock;
|
||||
use pgBackRest::Common::Log;
|
||||
use pgBackRest::Config::Config;
|
||||
use pgBackRest::Archive::Info;
|
||||
@@ -22,6 +25,7 @@ use pgBackRest::Backup::Info;
|
||||
use pgBackRest::Db;
|
||||
use pgBackRest::DbVersion;
|
||||
use pgBackRest::InfoCommon;
|
||||
use pgBackRest::Manifest;
|
||||
use pgBackRest::Protocol::Helper;
|
||||
use pgBackRest::Protocol::Storage::Helper;
|
||||
|
||||
@@ -48,9 +52,12 @@ sub new
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my $strOperation = logDebugParam(__PACKAGE__ . '->new');
|
||||
|
||||
# Initialize the database object
|
||||
($self->{oDb}) = dbObjectGet();
|
||||
$self->dbInfoGet();
|
||||
# Initialize the database object if not performing a stanza-delete
|
||||
if (!cfgCommandTest(CFGCMD_STANZA_DELETE))
|
||||
{
|
||||
($self->{oDb}) = dbObjectGet();
|
||||
$self->dbInfoGet();
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
@@ -82,6 +89,11 @@ sub process
|
||||
{
|
||||
$iResult = $self->stanzaUpgrade();
|
||||
}
|
||||
# Process stanza delete
|
||||
elsif (cfgCommandTest(CFGCMD_STANZA_DELETE))
|
||||
{
|
||||
$iResult = $self->stanzaDelete();
|
||||
}
|
||||
# Else error if any other command is found
|
||||
else
|
||||
{
|
||||
@@ -251,6 +263,82 @@ sub stanzaUpgrade
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# stanzaDelete
|
||||
#
|
||||
# Delete a stanza. The stop file must exist and the db must be offline unless --force is used.
|
||||
####################################################################################################################################
|
||||
sub stanzaDelete
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my ($strOperation) = logDebugParam(__PACKAGE__ . '->stanzaDelete');
|
||||
|
||||
my $strStanza = cfgOption(CFGOPT_STANZA);
|
||||
my $oStorageRepo = storageRepo({strStanza => $strStanza});
|
||||
|
||||
# If at least an archive or backup directory exists for the stanza, then continue, else nothing to do
|
||||
if ($oStorageRepo->pathExists(STORAGE_REPO_ARCHIVE) || $oStorageRepo->pathExists(STORAGE_REPO_BACKUP))
|
||||
{
|
||||
# If the stop file does not exist, then error
|
||||
if (!lockStopTest({bStanzaStopRequired => true}))
|
||||
{
|
||||
confess &log(ERROR, "stop file does not exist for stanza '${strStanza}'" .
|
||||
"\nHINT: has the pgbackrest stop command been run on this server?", ERROR_FILE_MISSING);
|
||||
}
|
||||
|
||||
# Get the master database object and index
|
||||
my ($oDbMaster, $iMasterRemoteIdx) = dbObjectGet({bMasterOnly => true});
|
||||
|
||||
# Initialize the master file object and path
|
||||
my $oStorageDbMaster = storageDb({iRemoteIdx => $iMasterRemoteIdx});
|
||||
|
||||
# Check if Postgres is running and if so only continue when forced
|
||||
if ($oStorageDbMaster->exists(DB_FILE_POSTMASTERPID) && !cfgOption(CFGOPT_FORCE))
|
||||
{
|
||||
confess &log(ERROR, DB_FILE_POSTMASTERPID . " exists - looks like the postmaster is running. " .
|
||||
"To delete stanza '${strStanza}', shutdown the postmaster for stanza '${strStanza}' and try again, " .
|
||||
"or use --force.", ERROR_POSTMASTER_RUNNING);
|
||||
}
|
||||
|
||||
# Delete the archive info files
|
||||
$oStorageRepo->remove(STORAGE_REPO_ARCHIVE . '/' . ARCHIVE_INFO_FILE, {bIgnoreMissing => true});
|
||||
$oStorageRepo->remove(STORAGE_REPO_ARCHIVE . '/' . ARCHIVE_INFO_FILE . INI_COPY_EXT, {bIgnoreMissing => true});
|
||||
|
||||
# Delete the backup info files
|
||||
$oStorageRepo->remove(STORAGE_REPO_BACKUP . '/' . FILE_BACKUP_INFO, {bIgnoreMissing => true});
|
||||
$oStorageRepo->remove(STORAGE_REPO_BACKUP . '/' . FILE_BACKUP_INFO . INI_COPY_EXT, {bIgnoreMissing => true});
|
||||
|
||||
# Invalidate the backups by removing the manifest files
|
||||
foreach my $strBackup ($oStorageRepo->list(
|
||||
STORAGE_REPO_BACKUP, {strExpression => backupRegExpGet(true, true, true), strSortOrder => 'reverse',
|
||||
bIgnoreMissing => true}))
|
||||
{
|
||||
$oStorageRepo->remove(STORAGE_REPO_BACKUP . "/${strBackup}/" . FILE_MANIFEST, {bIgnoreMissing => true});
|
||||
$oStorageRepo->remove(STORAGE_REPO_BACKUP . "/${strBackup}/" . FILE_MANIFEST_COPY, {bIgnoreMissing => true});
|
||||
}
|
||||
|
||||
# Recursively remove the stanza archive and backup directories
|
||||
$oStorageRepo->remove(STORAGE_REPO_ARCHIVE, {bRecurse => true, bIgnoreMissing => true});
|
||||
$oStorageRepo->remove(STORAGE_REPO_BACKUP, {bRecurse => true, bIgnoreMissing => true});
|
||||
|
||||
# Remove the stop file so processes can run.
|
||||
lockStart();
|
||||
}
|
||||
else
|
||||
{
|
||||
&log(INFO, "stanza ${strStanza} already deleted");
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'iResult', value => 0, trace => true}
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# parentPathGet
|
||||
#
|
||||
@@ -338,7 +426,7 @@ sub existingFileName
|
||||
####################################################################################################################################
|
||||
# errorForce
|
||||
#
|
||||
# Creates the parent path if it doesn't exist and returns the path.
|
||||
# Determines based on encryption or not and errors when force is required but not set.
|
||||
####################################################################################################################################
|
||||
sub errorForce
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user