1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2024-12-14 10:13:05 +02:00
pgbackrest/lib/pgBackRest/ArchiveInfo.pm

214 lines
8.4 KiB
Perl

####################################################################################################################################
# ARCHIVE INFO MODULE
#
# The archive.info file is created when archiving begins. It is located under the stanza directory. The file contains information
# regarding the stanza database version, database WAL segment system id and other information to ensure that archiving is being
# performed on the proper database.
####################################################################################################################################
package pgBackRest::ArchiveInfo;
use parent 'pgBackRest::Common::Ini';
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use Exporter qw(import);
use File::Basename qw(dirname basename);
use File::stat;
use lib dirname($0);
use pgBackRest::Common::Exception;
use pgBackRest::Common::Ini;
use pgBackRest::Common::Log;
use pgBackRest::BackupInfo;
use pgBackRest::Config::Config;
use pgBackRest::File;
use pgBackRest::Manifest;
####################################################################################################################################
# Operation constants
####################################################################################################################################
use constant OP_ARCHIVE_INFO => 'ArchiveInfo';
use constant OP_ARCHIVE_INFO_ARCHIVE_ID => OP_ARCHIVE_INFO . "->archiveId";
use constant OP_ARCHIVE_INFO_CHECK => OP_ARCHIVE_INFO . "->check";
use constant OP_ARCHIVE_INFO_NEW => OP_ARCHIVE_INFO . "->new";
####################################################################################################################################
# File/path constants
####################################################################################################################################
use constant ARCHIVE_INFO_FILE => 'archive.info';
our @EXPORT = qw(ARCHIVE_INFO_FILE);
####################################################################################################################################
# Backup info Constants
####################################################################################################################################
use constant INFO_ARCHIVE_SECTION_DB => INFO_BACKUP_SECTION_DB;
push @EXPORT, qw(INFO_ARCHIVE_SECTION_DB);
use constant INFO_ARCHIVE_SECTION_DB_HISTORY => INFO_BACKUP_SECTION_DB_HISTORY;
push @EXPORT, qw(INFO_ARCHIVE_SECTION_DB);
use constant INFO_ARCHIVE_KEY_DB_VERSION => MANIFEST_KEY_DB_VERSION;
push @EXPORT, qw(INFO_ARCHIVE_KEY_DB_VERSION);
use constant INFO_ARCHIVE_KEY_DB_ID => INFO_BACKUP_KEY_HISTORY_ID;
push @EXPORT, qw(INFO_ARCHIVE_KEY_DB_ID);
use constant INFO_ARCHIVE_KEY_DB_SYSTEM_ID => MANIFEST_KEY_SYSTEM_ID;
push @EXPORT, qw(INFO_ARCHIVE_KEY_DB_SYSTEM_ID);
####################################################################################################################################
# CONSTRUCTOR
####################################################################################################################################
sub new
{
my $class = shift; # Class name
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$strArchiveClusterPath, # Backup cluster path
$bRequired # Is archive info required?
) =
logDebugParam
(
OP_ARCHIVE_INFO_NEW, \@_,
{name => 'strArchiveClusterPath'},
{name => 'bRequired', default => false}
);
# Build the archive info path/file name
my $strArchiveInfoFile = "${strArchiveClusterPath}/" . ARCHIVE_INFO_FILE;
my $bExists = -e $strArchiveInfoFile ? true : false;
if (!$bExists && $bRequired)
{
confess &log(ERROR, ARCHIVE_INFO_FILE . " does not exist but is required to get WAL segments\n" .
"HINT: is archive_command configured in postgresql.conf?\n" .
"HINT: use --no-archive-check to disable archive checks during backup if you have an alternate archiving" .
" scheme.", ERROR_FILE_MISSING);
}
# Init object and store variables
my $self = $class->SUPER::new($strArchiveInfoFile, $bExists);
$self->{bExists} = $bExists;
$self->{strArchiveClusterPath} = $strArchiveClusterPath;
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'self', value => $self}
);
}
####################################################################################################################################
# check
#
# Check archive info file and make sure it is compatible with the current version of the database for the stanza. If the file does
# not exist it will be created with the values passed.
####################################################################################################################################
sub check
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$strDbVersion,
$ullDbSysId
) =
logDebugParam
(
OP_ARCHIVE_INFO_CHECK, \@_,
{name => 'strDbVersion'},
{name => 'ullDbSysId'}
);
my $bSave = false;
if ($self->test(INFO_ARCHIVE_SECTION_DB))
{
my $strError = undef;
if (!$self->test(INFO_ARCHIVE_SECTION_DB, INFO_ARCHIVE_KEY_DB_VERSION, undef, $strDbVersion))
{
$strError = "WAL segment version ${strDbVersion} does not match archive version " .
$self->get(INFO_ARCHIVE_SECTION_DB, INFO_ARCHIVE_KEY_DB_VERSION);
}
if (!$self->test(INFO_ARCHIVE_SECTION_DB, INFO_ARCHIVE_KEY_DB_SYSTEM_ID, undef, $ullDbSysId))
{
$strError = (defined($strError) ? ($strError . "\n") : "") .
"WAL segment system-id ${ullDbSysId} does not match archive system-id " .
$self->get(INFO_ARCHIVE_SECTION_DB, INFO_ARCHIVE_KEY_DB_SYSTEM_ID);
}
if (defined($strError))
{
confess &log(ERROR, "${strError}\nHINT: are you archiving to the correct stanza?", ERROR_ARCHIVE_MISMATCH);
}
}
# Else create the info file from the parameters passed which are usually derived from the current WAL segment
else
{
my $iDbId = 1;
# Fill db section
$self->numericSet(INFO_ARCHIVE_SECTION_DB, INFO_ARCHIVE_KEY_DB_SYSTEM_ID, undef, $ullDbSysId);
$self->set(INFO_ARCHIVE_SECTION_DB, INFO_ARCHIVE_KEY_DB_VERSION, undef, $strDbVersion);
$self->numericSet(INFO_ARCHIVE_SECTION_DB, INFO_ARCHIVE_KEY_DB_ID, undef, $iDbId);
# Fill db history
$self->numericSet(INFO_ARCHIVE_SECTION_DB_HISTORY, $iDbId, INFO_ARCHIVE_KEY_DB_ID, $ullDbSysId);
$self->set(INFO_ARCHIVE_SECTION_DB_HISTORY, $iDbId, INFO_ARCHIVE_KEY_DB_VERSION, $strDbVersion);
$bSave = true;
}
# Save if changes have been made
if ($bSave)
{
$self->save();
}
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'strArchiveId', value => $self->archiveId()}
);
}
####################################################################################################################################
# archiveId
#
# Get the archive id which is a combination of the DB version and the db-id setting (e.g. 9.4-1)
####################################################################################################################################
sub archiveId
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation
) =
logDebugParam
(
OP_ARCHIVE_INFO_ARCHIVE_ID
);
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'strArchiveId', value => $self->get(INFO_ARCHIVE_SECTION_DB, INFO_ARCHIVE_KEY_DB_VERSION) . "-" .
$self->get(INFO_ARCHIVE_SECTION_DB, INFO_ARCHIVE_KEY_DB_ID)}
);
}
1;