mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-01-18 04:58:51 +02:00
The check command is implemented entirely in C.
Note that building the manifest on each host has been temporarily removed. This feature will likely be brought back as a non-default option (after the manifest code has been fully migrated to C) since it can be fairly expensive.
This commit is contained in:
parent
ecae5e34e5
commit
a1c13a50dd
@ -15,6 +15,14 @@
|
||||
<release date="XXXX-XX-XX" version="2.19dev" title="UNDER DEVELOPMENT">
|
||||
<release-doc-list>
|
||||
<release-improvement-list>
|
||||
<release-item>
|
||||
<release-item-contributor-list>
|
||||
<release-item-contributor id="cynthia.shang"/>
|
||||
</release-item-contributor-list>
|
||||
|
||||
<p>The <cmd>check</cmd> command is implemented entirely in C.</p>
|
||||
</release-item>
|
||||
|
||||
<release-item>
|
||||
<release-item-contributor-list>
|
||||
<release-item-contributor id="cynthia.shang"/>
|
||||
|
@ -2786,7 +2786,7 @@
|
||||
|
||||
<execute user="postgres" output="y">
|
||||
<exe-cmd>{[project-exe]} {[dash]}-stanza={[postgres-cluster-demo]} {[dash]}-log-level-console=info check</exe-cmd>
|
||||
<exe-highlight>because no primary was found</exe-highlight>
|
||||
<exe-highlight>because this is a standby</exe-highlight>
|
||||
</execute>
|
||||
</execute-list>
|
||||
</section>
|
||||
|
@ -1,235 +0,0 @@
|
||||
####################################################################################################################################
|
||||
# CHECK MODULE
|
||||
####################################################################################################################################
|
||||
package pgBackRest::Check::Check;
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => qw(all);
|
||||
use Carp qw(confess);
|
||||
use English '-no_match_vars';
|
||||
|
||||
use pgBackRest::Archive::Common;
|
||||
use pgBackRest::Archive::Get::File;
|
||||
use pgBackRest::Backup::Info;
|
||||
use pgBackRest::Common::Exception;
|
||||
use pgBackRest::Common::Log;
|
||||
use pgBackRest::Common::Wait;
|
||||
use pgBackRest::Config::Config;
|
||||
use pgBackRest::Db;
|
||||
use pgBackRest::Manifest;
|
||||
use pgBackRest::Protocol::Helper;
|
||||
use pgBackRest::Protocol::Storage::Helper;
|
||||
|
||||
####################################################################################################################################
|
||||
# constructor
|
||||
####################################################################################################################################
|
||||
sub new
|
||||
{
|
||||
my $class = shift; # Class name
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my ($strOperation) = logDebugParam(__PACKAGE__ . '->new');
|
||||
|
||||
# Create the class hash
|
||||
my $self = {};
|
||||
bless $self, $class;
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'self', value => $self}
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# process
|
||||
#
|
||||
# Validates the database configuration and checks that the archive logs can be read by backup. This will alert the user to any
|
||||
# misconfiguration, particularly of archiving, that would result in the inability of a backup to complete (e.g waiting at the end
|
||||
# until it times out because it could not find the WAL file).
|
||||
####################################################################################################################################
|
||||
sub process
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my $strOperation = logDebugParam(__PACKAGE__ . '->process');
|
||||
|
||||
# Initialize the local variables
|
||||
my $iArchiveTimeout = cfgOption(CFGOPT_ARCHIVE_TIMEOUT);
|
||||
|
||||
my $iResult = 0;
|
||||
my $strResultMessage = undef;
|
||||
|
||||
my $strArchiveId = undef;
|
||||
my $strArchiveFile = undef;
|
||||
my $strWalSegment = undef;
|
||||
|
||||
# Get the master database object to test to see if the manifest can be built
|
||||
my ($oDb) = dbMasterGet();
|
||||
|
||||
# Get the database version to pass to the manifest constructor and the system-id in the event of a failure
|
||||
my ($strDbVersion, $iControlVersion, $iCatalogVersion, $ullDbSysId) = $oDb->info();
|
||||
|
||||
# Turn off console logging to control when to display the error
|
||||
logLevelSet(undef, OFF);
|
||||
|
||||
# Loop through all defined databases and attempt to build a manifest
|
||||
for (my $iRemoteIdx = 1; $iRemoteIdx <= cfgOptionIndexTotal(CFGOPT_PG_HOST); $iRemoteIdx++)
|
||||
{
|
||||
# Make sure a db is defined for this index
|
||||
if (cfgOptionTest(cfgOptionIdFromIndex(CFGOPT_PG_PATH, $iRemoteIdx)) ||
|
||||
cfgOptionTest(cfgOptionIdFromIndex(CFGOPT_PG_HOST, $iRemoteIdx)))
|
||||
{
|
||||
eval
|
||||
{
|
||||
# Passing file location dev/null so that the save will fail if it is ever attempted. Pass a miscellaneous value for
|
||||
# encryption key since the file will not be saved.
|
||||
my $oBackupManifest = new pgBackRest::Manifest("/dev/null/manifest.chk",
|
||||
{bLoad => false, strDbVersion => $strDbVersion, iDbCatalogVersion => $iCatalogVersion,
|
||||
strCipherPass => 'x', strCipherPassSub => 'x'});
|
||||
|
||||
# Set required settings not set during manifest instantiation
|
||||
$oBackupManifest->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_ID, undef, 1);
|
||||
$oBackupManifest->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CONTROL, undef, $iControlVersion);
|
||||
$oBackupManifest->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_SYSTEM_ID, undef, $ullDbSysId);
|
||||
|
||||
$oBackupManifest->build(
|
||||
storageDb({iRemoteIdx => $iRemoteIdx}), cfgOption(cfgOptionIdFromIndex(CFGOPT_PG_PATH, $iRemoteIdx)), undef,
|
||||
cfgOptionValid(CFGOPT_ONLINE) && cfgOption(CFGOPT_ONLINE), false, $oDb->tablespaceMapGet());
|
||||
|
||||
return true;
|
||||
}
|
||||
or do
|
||||
{
|
||||
# Capture error information
|
||||
$strResultMessage = "Database: ${strDbVersion} ${ullDbSysId} " . exceptionMessage($EVAL_ERROR) .
|
||||
(($iResult != 0) ? "\n[$iResult] : $strResultMessage" : "");
|
||||
$iResult = exceptionCode($EVAL_ERROR);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
# Reset the console logging
|
||||
logLevelSet(undef, cfgOption(CFGOPT_LOG_LEVEL_CONSOLE));
|
||||
|
||||
# If the manifest builds are ok, then proceed with the other checks
|
||||
if ($iResult == 0)
|
||||
{
|
||||
# Reinitialize the database object in order to check the configured replicas. This will throw an error if at least one is not
|
||||
# able to be connected to and warnings for any that cannot be properly connected to.
|
||||
($oDb) = dbObjectGet();
|
||||
|
||||
# Validate the database configuration
|
||||
$oDb->configValidate();
|
||||
|
||||
# Turn off console logging to control when to display the error
|
||||
logLevelSet(undef, OFF);
|
||||
|
||||
# Check backup.info - if the archive check fails below (e.g --no-archive-check set) then at least know backup.info succeeded
|
||||
eval
|
||||
{
|
||||
# Check that the backup info file is written and is valid for the current database of the stanza
|
||||
$self->backupInfoCheck();
|
||||
return true;
|
||||
}
|
||||
# If there is an unhandled error then confess
|
||||
or do
|
||||
{
|
||||
# Capture error information
|
||||
$iResult = exceptionCode($EVAL_ERROR);
|
||||
$strResultMessage = exceptionMessage($EVAL_ERROR);
|
||||
};
|
||||
|
||||
# Check archive.info
|
||||
if ($iResult == 0)
|
||||
{
|
||||
eval
|
||||
{
|
||||
# Check that the archive info file is written and is valid for the current database of the stanza
|
||||
($strArchiveId) = archiveGetCheck();
|
||||
return true;
|
||||
}
|
||||
or do
|
||||
{
|
||||
# Capture error information
|
||||
$iResult = exceptionCode($EVAL_ERROR);
|
||||
$strResultMessage = exceptionMessage($EVAL_ERROR);
|
||||
};
|
||||
}
|
||||
|
||||
# Reset the console logging
|
||||
logLevelSet(undef, cfgOption(CFGOPT_LOG_LEVEL_CONSOLE));
|
||||
}
|
||||
|
||||
# Log the captured error
|
||||
if ($iResult != 0)
|
||||
{
|
||||
&log(ERROR, $strResultMessage, $iResult);
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'iResult', value => $iResult, trace => true}
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# backupInfoCheck
|
||||
#
|
||||
# Check the backup.info file, if it exists, to confirm the DB version, system-id, control and catalog numbers match the database.
|
||||
####################################################################################################################################
|
||||
sub backupInfoCheck
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$strDbVersion,
|
||||
$iControlVersion,
|
||||
$iCatalogVersion,
|
||||
$ullDbSysId,
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
__PACKAGE__ . '->backupInfoCheck', \@_,
|
||||
{name => 'strDbVersion', required => false},
|
||||
{name => 'iControlVersion', required => false},
|
||||
{name => 'iCatalogVersion', required => false},
|
||||
{name => 'ullDbSysId', required => false}
|
||||
);
|
||||
|
||||
# If the db info are not passed, then we need to retrieve the database information
|
||||
my $iDbHistoryId;
|
||||
|
||||
if (!defined($strDbVersion) || !defined($iControlVersion) || !defined($iCatalogVersion) || !defined($ullDbSysId))
|
||||
{
|
||||
# get DB info for comparison
|
||||
($strDbVersion, $iControlVersion, $iCatalogVersion, $ullDbSysId) = dbMasterGet()->info();
|
||||
}
|
||||
|
||||
if (!isRepoLocal())
|
||||
{
|
||||
$iDbHistoryId = protocolGet(CFGOPTVAL_REMOTE_TYPE_BACKUP)->cmdExecute(
|
||||
OP_CHECK_BACKUP_INFO_CHECK, [$strDbVersion, $iControlVersion, $iCatalogVersion, $ullDbSysId]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$iDbHistoryId = (new pgBackRest::Backup::Info(storageRepo()->pathGet(STORAGE_REPO_BACKUP)))->check(
|
||||
$strDbVersion, $iControlVersion, $iCatalogVersion, $ullDbSysId);
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'iDbHistoryId', value => $iDbHistoryId, trace => true}
|
||||
);
|
||||
}
|
||||
|
||||
1;
|
@ -106,17 +106,6 @@ sub main
|
||||
$oRemote->process(
|
||||
cfgOption(CFGOPT_LOCK_PATH), cfgOption(CFGOPT_COMMAND), cfgOption(CFGOPT_STANZA, false), cfgOption(CFGOPT_PROCESS));
|
||||
}
|
||||
|
||||
# Process check command
|
||||
# --------------------------------------------------------------------------------------------------------------------------
|
||||
elsif (cfgCommandTest(CFGCMD_CHECK))
|
||||
{
|
||||
# Load module dynamically
|
||||
require pgBackRest::Check::Check;
|
||||
pgBackRest::Check::Check->import();
|
||||
|
||||
$iResult = new pgBackRest::Check::Check()->process();
|
||||
}
|
||||
else
|
||||
{
|
||||
# Check that the repo path exists
|
||||
|
@ -26,10 +26,6 @@ use constant OP_BACKUP_FILE => 'backupF
|
||||
use constant OP_ARCHIVE_GET_CHECK => 'archiveCheck';
|
||||
push @EXPORT, qw(OP_ARCHIVE_GET_CHECK);
|
||||
|
||||
# Check Module
|
||||
use constant OP_CHECK_BACKUP_INFO_CHECK => 'backupInfoCheck';
|
||||
push @EXPORT, qw(OP_CHECK_BACKUP_INFO_CHECK);
|
||||
|
||||
# Db Module
|
||||
use constant OP_DB_CONNECT => 'dbConnect';
|
||||
push @EXPORT, qw(OP_DB_CONNECT);
|
||||
|
@ -15,7 +15,6 @@ use pgBackRest::Common::Log;
|
||||
use pgBackRest::Common::Io::Buffered;
|
||||
use pgBackRest::Common::Wait;
|
||||
use pgBackRest::Archive::Get::File;
|
||||
use pgBackRest::Check::Check;
|
||||
use pgBackRest::Config::Config;
|
||||
use pgBackRest::Db;
|
||||
use pgBackRest::Protocol::Command::Minion;
|
||||
@ -68,7 +67,6 @@ sub init
|
||||
# Create objects
|
||||
my $oStorage = cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_DB) ? storageDb() : storageRepo();
|
||||
|
||||
my $oCheck = cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_BACKUP) ? new pgBackRest::Check::Check() : undef;
|
||||
my $oDb = cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_DB) ? new pgBackRest::Db() : undef;
|
||||
|
||||
# Create anonymous subs for each command
|
||||
@ -77,9 +75,6 @@ sub init
|
||||
# ArchiveGet commands
|
||||
&OP_ARCHIVE_GET_CHECK => sub {archiveGetCheck(@{shift()})},
|
||||
|
||||
# Check commands
|
||||
&OP_CHECK_BACKUP_INFO_CHECK => sub {$oCheck->backupInfoCheck(@{shift()})},
|
||||
|
||||
# Db commands
|
||||
&OP_DB_CONNECT => sub {$oDb->connect()},
|
||||
&OP_DB_EXECUTE_SQL => sub {$oDb->executeSql(@{shift()})},
|
||||
|
@ -246,10 +246,10 @@ command/backup/pageChecksum.o: command/backup/pageChecksum.c build.auto.h comman
|
||||
command/backup/protocol.o: command/backup/protocol.c build.auto.h command/backup/file.h command/backup/protocol.h common/assert.h common/crypto/common.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/io.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h protocol/server.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c command/backup/protocol.c -o command/backup/protocol.o
|
||||
|
||||
command/check/check.o: command/check/check.c build.auto.h command/archive/common.h command/check/check.h common/assert.h common/crypto/common.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h db/db.h db/helper.h info/info.h info/infoArchive.h info/infoPg.h postgres/client.h protocol/client.h protocol/command.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h
|
||||
command/check/check.o: command/check/check.c build.auto.h command/archive/common.h command/check/check.h command/check/common.h common/assert.h common/crypto/common.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h db/db.h db/helper.h info/info.h info/infoArchive.h info/infoPg.h postgres/client.h postgres/interface.h protocol/client.h protocol/command.h protocol/helper.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c command/check/check.c -o command/check/check.o
|
||||
|
||||
command/check/common.o: command/check/common.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h db/db.h db/helper.h postgres/client.h postgres/interface.h protocol/client.h protocol/command.h storage/info.h storage/read.h storage/storage.h storage/write.h
|
||||
command/check/common.o: command/check/common.c build.auto.h command/backup/common.h command/check/common.h common/assert.h common/crypto/common.h common/crypto/hash.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h db/db.h db/helper.h info/info.h info/infoArchive.h info/infoBackup.h info/infoPg.h info/manifest.h postgres/client.h postgres/interface.h protocol/client.h protocol/command.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h version.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c command/check/common.c -o command/check/common.o
|
||||
|
||||
command/command.o: command/command.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/http/client.h common/io/http/header.h common/io/http/query.h common/io/read.h common/io/tls/client.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h version.h
|
||||
@ -291,13 +291,13 @@ command/restore/restore.o: command/restore/restore.c build.auto.h command/backup
|
||||
command/stanza/common.o: command/stanza/common.c build.auto.h command/check/common.h common/assert.h common/crypto/common.h common/debug.h common/encode.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h db/db.h db/helper.h info/info.h info/infoPg.h postgres/client.h postgres/interface.h postgres/version.h protocol/client.h protocol/command.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c command/stanza/common.c -o command/stanza/common.o
|
||||
|
||||
command/stanza/create.o: command/stanza/create.c build.auto.h command/backup/common.h command/control/common.h command/stanza/common.h command/stanza/create.h common/assert.h common/crypto/common.h common/crypto/hash.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h info/info.h info/infoArchive.h info/infoBackup.h info/infoPg.h info/manifest.h postgres/interface.h postgres/version.h protocol/client.h protocol/command.h protocol/helper.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h
|
||||
command/stanza/create.o: command/stanza/create.c build.auto.h command/backup/common.h command/check/common.h command/control/common.h command/stanza/common.h command/stanza/create.h common/assert.h common/crypto/common.h common/crypto/hash.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h db/db.h info/info.h info/infoArchive.h info/infoBackup.h info/infoPg.h info/manifest.h postgres/client.h postgres/interface.h postgres/version.h protocol/client.h protocol/command.h protocol/helper.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c command/stanza/create.c -o command/stanza/create.o
|
||||
|
||||
command/stanza/delete.o: command/stanza/delete.c build.auto.h command/backup/common.h command/control/common.h command/stanza/delete.h common/assert.h common/crypto/common.h common/crypto/hash.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h info/info.h info/infoArchive.h info/infoBackup.h info/infoPg.h info/manifest.h postgres/interface.h protocol/client.h protocol/command.h protocol/helper.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c command/stanza/delete.c -o command/stanza/delete.o
|
||||
|
||||
command/stanza/upgrade.o: command/stanza/upgrade.c build.auto.h command/backup/common.h command/control/common.h command/stanza/common.h command/stanza/upgrade.h common/assert.h common/crypto/common.h common/crypto/hash.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h info/info.h info/infoArchive.h info/infoBackup.h info/infoPg.h info/manifest.h postgres/interface.h postgres/version.h protocol/client.h protocol/command.h protocol/helper.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h
|
||||
command/stanza/upgrade.o: command/stanza/upgrade.c build.auto.h command/backup/common.h command/check/common.h command/control/common.h command/stanza/common.h command/stanza/upgrade.h common/assert.h common/crypto/common.h common/crypto/hash.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h db/db.h info/info.h info/infoArchive.h info/infoBackup.h info/infoPg.h info/manifest.h postgres/client.h postgres/interface.h postgres/version.h protocol/client.h protocol/command.h protocol/helper.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c command/stanza/upgrade.c -o command/stanza/upgrade.o
|
||||
|
||||
command/storage/list.o: command/storage/list.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/handleWrite.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/json.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h
|
||||
|
@ -5,14 +5,157 @@ Check Command
|
||||
|
||||
#include "command/archive/common.h"
|
||||
#include "command/check/check.h"
|
||||
#include "command/check/common.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/log.h"
|
||||
#include "common/memContext.h"
|
||||
#include "config/config.h"
|
||||
#include "db/helper.h"
|
||||
#include "info/infoArchive.h"
|
||||
#include "postgres/interface.h"
|
||||
#include "protocol/helper.h"
|
||||
#include "storage/helper.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Helper functions (to assist with testing)
|
||||
***********************************************************************************************************************************/
|
||||
static unsigned int
|
||||
checkManifest(void)
|
||||
{
|
||||
FUNCTION_LOG_VOID(logLevelTrace);
|
||||
|
||||
// Return the actual number of pg* defined
|
||||
unsigned int result = 0;
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
// Loop through all defined databases and attempt to build a manifest
|
||||
for (unsigned int pgIdx = 0; pgIdx < cfgOptionIndexTotal(cfgOptPgPath); pgIdx++)
|
||||
{
|
||||
if (cfgOptionTest(cfgOptPgHost + pgIdx) || cfgOptionTest(cfgOptPgPath + pgIdx))
|
||||
{
|
||||
result++;
|
||||
// ??? Placeholder for manifest build
|
||||
storageListNP(storagePgId(pgIdx + 1), varStr(cfgOption(cfgOptPgPath + pgIdx)));
|
||||
}
|
||||
}
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_LOG_RETURN(UINT, result);
|
||||
}
|
||||
|
||||
static void
|
||||
checkStandby(const DbGetResult dbGroup, unsigned int pgPathDefinedTotal)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(DB_GET_RESULT, dbGroup);
|
||||
FUNCTION_LOG_PARAM(UINT, pgPathDefinedTotal);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
// If a standby is defined, check the configuration
|
||||
if (dbGroup.standby != NULL)
|
||||
{
|
||||
// If primary was not found
|
||||
if (dbGroup.primary == NULL)
|
||||
{
|
||||
// If the repo is local or more than one pg-path is found then a master should have been found so error
|
||||
if (repoIsLocal() || pgPathDefinedTotal > 1)
|
||||
{
|
||||
THROW(
|
||||
ConfigError,
|
||||
"primary database not found\n"
|
||||
"HINT: check indexed pg-path/pg-host configurations");
|
||||
}
|
||||
}
|
||||
|
||||
// Validate the standby database config
|
||||
PgControl pgControl = pgControlFromFile(storagePgId(dbGroup.standbyId));
|
||||
|
||||
// Check the user configured path and version against the database
|
||||
checkDbConfig(pgControl.version, dbGroup.standbyId, dbGroup.standby, true);
|
||||
|
||||
// Get the repo storage in case it is remote and encryption settings need to be pulled down (performed here for testing)
|
||||
storageRepo();
|
||||
|
||||
// Check that the backup and archive info files exist and are valid for the current database of the stanza
|
||||
checkStanzaInfoPg(
|
||||
storageRepo(), pgControl.version, pgControl.systemId, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
|
||||
LOG_INFO("switch wal not performed because this is a standby");
|
||||
|
||||
// Free the standby connection
|
||||
dbFree(dbGroup.standby);
|
||||
}
|
||||
// If backup from standby is true then warn when a standby not found
|
||||
else if (cfgOptionBool(cfgOptBackupStandby))
|
||||
{
|
||||
LOG_WARN("option '%s' is enabled but standby is not properly configured", cfgOptionName(cfgOptBackupStandby));
|
||||
}
|
||||
|
||||
FUNCTION_LOG_RETURN_VOID();
|
||||
}
|
||||
|
||||
static void
|
||||
checkPrimary(const DbGetResult dbGroup)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(DB_GET_RESULT, dbGroup);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
// If a primary is defined, check the configuration and perform a WAL switch and make sure the WAL is archived
|
||||
if (dbGroup.primary != NULL)
|
||||
{
|
||||
// Validate the primary database config
|
||||
PgControl pgControl = pgControlFromFile(storagePgId(dbGroup.primaryId));
|
||||
|
||||
// Check the user configured path and version against the database
|
||||
checkDbConfig(pgControl.version, dbGroup.primaryId, dbGroup.primary, false);
|
||||
|
||||
// Get the repo storage in case it is remote and encryption settings need to be pulled down (performed here for testing)
|
||||
storageRepo();
|
||||
|
||||
// Check that the backup and archive info files exist and are valid for the current database of the stanza
|
||||
checkStanzaInfoPg(
|
||||
storageRepo(), pgControl.version, pgControl.systemId, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
|
||||
// Attempt to load the archive info file and retrieve the archiveId
|
||||
InfoArchive *archiveInfo = infoArchiveLoadFile(
|
||||
storageRepo(), INFO_ARCHIVE_PATH_FILE_STR, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
const String *archiveId = infoArchiveId(archiveInfo);
|
||||
|
||||
// Perform a WAL switch
|
||||
const String *walSegment = dbWalSwitch(dbGroup.primary);
|
||||
dbFree(dbGroup.primary);
|
||||
|
||||
// Wait for the WAL to appear in the repo
|
||||
TimeMSec archiveTimeout = (TimeMSec)(cfgOptionDbl(cfgOptArchiveTimeout) * MSEC_PER_SEC);
|
||||
const String *walSegmentFile = walSegmentFind(storageRepo(), archiveId, walSegment, archiveTimeout);
|
||||
|
||||
if (walSegmentFile != NULL)
|
||||
{
|
||||
LOG_INFO(
|
||||
"WAL segment %s successfully archived to '%s'", strPtr(walSegment),
|
||||
strPtr(storagePath(storageRepo(), strNewFmt(STORAGE_REPO_ARCHIVE "/%s/%s", strPtr(archiveId),
|
||||
strPtr(walSegmentFile)))));
|
||||
}
|
||||
else
|
||||
{
|
||||
THROW_FMT(
|
||||
ArchiveTimeoutError,
|
||||
"WAL segment %s was not archived before the %" PRIu64 "ms timeout\n"
|
||||
"HINT: check the archive_command to ensure that all options are correct (especially --stanza).\n"
|
||||
"HINT: check the PostgreSQL server log for errors.",
|
||||
strPtr(walSegment), archiveTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
FUNCTION_LOG_RETURN_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Perform standard checks
|
||||
***********************************************************************************************************************************/
|
||||
@ -23,53 +166,15 @@ cmdCheck(void)
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
// Get the repo storage in case it is remote and encryption settings need to be pulled down
|
||||
storageRepo();
|
||||
|
||||
// Attempt to load the archive info file
|
||||
InfoArchive *archiveInfo = infoArchiveLoadFile(
|
||||
storageRepo(), INFO_ARCHIVE_PATH_FILE_STR, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
const String *archiveId = infoArchiveId(archiveInfo);
|
||||
|
||||
// Get the primary/standby connections (standby is only required if backup from standby is enabled)
|
||||
DbGetResult dbGroup = dbGet(false, false);
|
||||
|
||||
// Free the standby connection immediately since we don't need it for anything
|
||||
dbFree(dbGroup.standby);
|
||||
|
||||
// Perform a WAL switch and make sure the WAL is archived if a primary was found
|
||||
if (dbGroup.primary != NULL)
|
||||
{
|
||||
// Perform WAL switch
|
||||
const String *walSegment = dbWalSwitch(dbGroup.primary);
|
||||
dbFree(dbGroup.primary);
|
||||
|
||||
// Wait for the WAL to appear in the repo
|
||||
TimeMSec archiveTimeout = (TimeMSec)(cfgOptionDbl(cfgOptArchiveTimeout) * MSEC_PER_SEC);
|
||||
const String *walSegmentFile = walSegmentFind(storageRepo(), archiveId, walSegment, archiveTimeout);
|
||||
|
||||
if (walSegmentFile != NULL)
|
||||
{
|
||||
LOG_INFO(
|
||||
"WAL segment %s successfully archived to '%s'", strPtr(walSegment),
|
||||
strPtr(
|
||||
storagePath(
|
||||
storageRepo(), strNewFmt(STORAGE_REPO_ARCHIVE "/%s/%s", strPtr(archiveId), strPtr(walSegmentFile)))));
|
||||
}
|
||||
else
|
||||
{
|
||||
THROW_FMT(
|
||||
ArchiveTimeoutError,
|
||||
"WAL segment %s was not archived before the %" PRIu64 "ms timeout\n"
|
||||
"HINT: check the archive_command to ensure that all options are correct (especially --stanza).\n"
|
||||
"HINT: check the PostgreSQL server log for errors.",
|
||||
strPtr(walSegment), archiveTimeout);
|
||||
}
|
||||
}
|
||||
else
|
||||
LOG_INFO("switch wal not performed because no primary was found");
|
||||
if (dbGroup.standby == NULL && dbGroup.primary == NULL)
|
||||
THROW(ConfigError, "no database found\nHINT: check indexed pg-path/pg-host configurations");
|
||||
|
||||
unsigned int pgPathDefinedTotal = checkManifest();
|
||||
checkStandby(dbGroup, pgPathDefinedTotal);
|
||||
checkPrimary(dbGroup);
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
|
@ -3,39 +3,167 @@ Check Common Handler
|
||||
***********************************************************************************************************************************/
|
||||
#include "build.auto.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "command/check/common.h"
|
||||
#include "common/debug.h"
|
||||
#include "config/config.h"
|
||||
#include "db/db.h"
|
||||
#include "db/helper.h"
|
||||
#include "info/infoArchive.h"
|
||||
#include "info/infoBackup.h"
|
||||
#include "postgres/interface.h"
|
||||
#include "storage/helper.h"
|
||||
#include "version.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Helper function
|
||||
***********************************************************************************************************************************/
|
||||
static bool
|
||||
checkArchiveCommand(const String *archiveCommand)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, archiveCommand);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
bool result = archiveCommand != NULL;
|
||||
|
||||
if (result && strstr(strPtr(archiveCommand), PROJECT_BIN) == NULL)
|
||||
result = false;
|
||||
|
||||
if (!result)
|
||||
{
|
||||
THROW_FMT(
|
||||
ArchiveCommandInvalidError, "archive_command '%s' must contain %s", (archiveCommand != NULL ? strPtr(archiveCommand)
|
||||
: "[null]"), PROJECT_BIN);
|
||||
}
|
||||
|
||||
FUNCTION_TEST_RETURN(result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Check the database path and version are configured correctly
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
checkDbConfig(const unsigned int pgVersion, const unsigned int dbIdx, const unsigned int dbVersion, const String *dbPath)
|
||||
checkDbConfig(const unsigned int pgVersion, const unsigned int dbIdx, const Db *dbObject, bool isStandby)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(UINT, pgVersion);
|
||||
FUNCTION_TEST_PARAM(UINT, dbIdx);
|
||||
FUNCTION_TEST_PARAM(UINT, dbVersion);
|
||||
FUNCTION_TEST_PARAM(STRING, dbPath);
|
||||
FUNCTION_TEST_PARAM(DB, dbObject);
|
||||
FUNCTION_TEST_PARAM(BOOL, isStandby);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(dbIdx > 0);
|
||||
ASSERT(dbPath != NULL);
|
||||
ASSERT(dbObject != NULL);
|
||||
|
||||
unsigned int pgPath = cfgOptPgPath + (dbIdx - 1);
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
unsigned int dbVersion = dbPgVersion(dbObject);
|
||||
const String *dbPath = dbPgDataPath(dbObject);
|
||||
unsigned int pgPath = cfgOptPgPath + (dbIdx - 1);
|
||||
|
||||
// Error if the version from the control file and the configured pg-path do not match the values obtained from the database
|
||||
if (pgVersion != dbVersion || strCmp(cfgOptionStr(pgPath), dbPath) != 0)
|
||||
// Error if the version from the control file and the configured pg-path do not match the values obtained from the database
|
||||
if (pgVersion != dbVersion || strCmp(cfgOptionStr(pgPath), dbPath) != 0)
|
||||
{
|
||||
THROW_FMT(
|
||||
DbMismatchError, "version '%s' and path '%s' queried from cluster do not match version '%s' and '%s' read from '%s/"
|
||||
PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL "'\nHINT: the %s and %s settings likely reference different clusters.",
|
||||
strPtr(pgVersionToStr(dbVersion)), strPtr(dbPath), strPtr(pgVersionToStr(pgVersion)), strPtr(cfgOptionStr(pgPath)),
|
||||
strPtr(cfgOptionStr(pgPath)), cfgOptionName(pgPath), cfgOptionName(cfgOptPgPort + (dbIdx - 1)));
|
||||
}
|
||||
|
||||
// Check archive configuration if option is valid for the command and set
|
||||
if (!isStandby && cfgOptionValid(cfgOptArchiveCheck) && cfgOptionBool(cfgOptArchiveCheck))
|
||||
{
|
||||
// Error if archive_mode = off since pg_start_backup () will fail
|
||||
if (strCmpZ(dbArchiveMode(dbObject), "off") == 0)
|
||||
{
|
||||
THROW(ArchiveDisabledError, "archive_mode must be enabled");
|
||||
}
|
||||
|
||||
// Error if archive_mode = always (support has not been added yet)
|
||||
if (strCmpZ(dbArchiveMode(dbObject), "always") == 0)
|
||||
{
|
||||
THROW(FeatureNotSupportedError, "archive_mode=always not supported");
|
||||
}
|
||||
|
||||
// Check if archive_command is set and is valid
|
||||
checkArchiveCommand(dbArchiveCommand(dbObject));
|
||||
}
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_TEST_RETURN_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Validate the archive and backup info files
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
checkStanzaInfo(const InfoPgData *archiveInfo, const InfoPgData *backupInfo)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM_P(INFO_PG_DATA, archiveInfo);
|
||||
FUNCTION_TEST_PARAM_P(INFO_PG_DATA, backupInfo);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(archiveInfo != NULL);
|
||||
ASSERT(backupInfo != NULL);
|
||||
|
||||
// Error if there is a mismatch between the archive and backup info files
|
||||
if (archiveInfo->id != backupInfo->id || archiveInfo->systemId != backupInfo->systemId ||
|
||||
archiveInfo->version != backupInfo->version)
|
||||
{
|
||||
THROW_FMT(
|
||||
DbMismatchError, "version '%s' and path '%s' queried from cluster do not match version '%s' and '%s' read from '%s/"
|
||||
PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL "'\nHINT: the %s and %s settings likely reference different clusters.",
|
||||
strPtr(pgVersionToStr(dbVersion)), strPtr(dbPath), strPtr(pgVersionToStr(pgVersion)), strPtr(cfgOptionStr(pgPath)),
|
||||
strPtr(cfgOptionStr(pgPath)), cfgOptionName(pgPath), cfgOptionName(cfgOptPgPort + (dbIdx - 1)));
|
||||
FileInvalidError, "backup info file and archive info file do not match\n"
|
||||
"archive: id = %u, version = %s, system-id = %" PRIu64 "\n"
|
||||
"backup : id = %u, version = %s, system-id = %" PRIu64 "\n"
|
||||
"HINT: this may be a symptom of repository corruption!",
|
||||
archiveInfo->id, strPtr(pgVersionToStr(archiveInfo->version)), archiveInfo->systemId, backupInfo->id,
|
||||
strPtr(pgVersionToStr(backupInfo->version)), backupInfo->systemId);
|
||||
}
|
||||
|
||||
FUNCTION_TEST_RETURN_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Load and validate the database data of the info files against each other and the current database
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
checkStanzaInfoPg(
|
||||
const Storage *storage, const unsigned int pgVersion, const uint64_t pgSystemId, CipherType cipherType,
|
||||
const String *cipherPass)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_LOG_PARAM(STORAGE, storage);
|
||||
FUNCTION_LOG_PARAM(UINT, pgVersion);
|
||||
FUNCTION_LOG_PARAM(UINT64, pgSystemId);
|
||||
FUNCTION_LOG_PARAM(ENUM, cipherType);
|
||||
FUNCTION_TEST_PARAM(STRING, cipherPass);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(storage != NULL);
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
// Check that the backup and archive info files exist
|
||||
InfoArchive *infoArchive = infoArchiveLoadFile(storage, INFO_ARCHIVE_PATH_FILE_STR, cipherType, cipherPass);
|
||||
InfoPgData archiveInfoPg = infoPgData(infoArchivePg(infoArchive), infoPgDataCurrentId(infoArchivePg(infoArchive)));
|
||||
InfoBackup *infoBackup = infoBackupLoadFile(storage, INFO_BACKUP_PATH_FILE_STR, cipherType, cipherPass);
|
||||
InfoPgData backupInfoPg = infoPgData(infoBackupPg(infoBackup), infoPgDataCurrentId(infoBackupPg(infoBackup)));
|
||||
|
||||
// Check that the info files pg data match each other
|
||||
checkStanzaInfo(&archiveInfoPg, &backupInfoPg);
|
||||
|
||||
// Check that the version and system id match the current database
|
||||
if (pgVersion != archiveInfoPg.version || pgSystemId != archiveInfoPg.systemId)
|
||||
{
|
||||
THROW(FileInvalidError, "backup and archive info files exist but do not match the database\n"
|
||||
"HINT: is this the correct stanza?\n"
|
||||
"HINT: did an error occur during stanza-upgrade?");
|
||||
}
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_TEST_RETURN_VOID();
|
||||
}
|
||||
|
@ -5,10 +5,16 @@ Check Command Common
|
||||
#define COMMAND_CHECK_COMMON_H
|
||||
|
||||
#include "common/type/string.h"
|
||||
#include "db/db.h"
|
||||
#include "info/infoPg.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Functions
|
||||
***********************************************************************************************************************************/
|
||||
void checkDbConfig(const unsigned int pgVersion, const unsigned int dbIdx, const unsigned int dbVersion, const String *dbPath);
|
||||
void checkDbConfig(const unsigned int pgVersion, const unsigned int dbIdx, const Db *dbObject, bool isStandby);
|
||||
void checkStanzaInfo(const InfoPgData *archiveInfo, const InfoPgData *backupInfo);
|
||||
void checkStanzaInfoPg(
|
||||
const Storage *storage, const unsigned int pgVersion, const uint64_t pgSystemId, CipherType cipherType,
|
||||
const String *cipherPass);
|
||||
|
||||
#endif
|
||||
|
@ -38,36 +38,6 @@ cipherPassGen(CipherType cipherType)
|
||||
FUNCTION_TEST_RETURN(result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Validate the archive and backup info files
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
infoValidate(const InfoPgData *archiveInfo, const InfoPgData *backupInfo)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM_P(INFO_PG_DATA, archiveInfo);
|
||||
FUNCTION_TEST_PARAM_P(INFO_PG_DATA, backupInfo);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(archiveInfo != NULL);
|
||||
ASSERT(backupInfo != NULL);
|
||||
|
||||
// Error if there is a mismatch between the archive and backup info files
|
||||
if (archiveInfo->id != backupInfo->id || archiveInfo->systemId != backupInfo->systemId ||
|
||||
archiveInfo->version != backupInfo->version)
|
||||
{
|
||||
THROW_FMT(
|
||||
FileInvalidError, "backup info file and archive info file do not match\n"
|
||||
"archive: id = %u, version = %s, system-id = %" PRIu64 "\n"
|
||||
"backup : id = %u, version = %s, system-id = %" PRIu64 "\n"
|
||||
"HINT: this may be a symptom of repository corruption!",
|
||||
archiveInfo->id, strPtr(pgVersionToStr(archiveInfo->version)), archiveInfo->systemId, backupInfo->id,
|
||||
strPtr(pgVersionToStr(backupInfo->version)), backupInfo->systemId);
|
||||
}
|
||||
|
||||
FUNCTION_TEST_RETURN_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Validate and return database information
|
||||
***********************************************************************************************************************************/
|
||||
@ -89,7 +59,7 @@ pgValidate(void)
|
||||
result = pgControlFromFile(storagePgId(dbObject.primaryId));
|
||||
|
||||
// Check the user configured path and version against the database
|
||||
checkDbConfig(result.version, dbObject.primaryId, dbPgVersion(dbObject.primary), dbPgDataPath(dbObject.primary));
|
||||
checkDbConfig(result.version, dbObject.primaryId, dbObject.primary, false);
|
||||
}
|
||||
// If the database is not online, assume that pg1 is the master
|
||||
else
|
||||
|
@ -11,7 +11,6 @@ Stanza Commands Handler
|
||||
Functions
|
||||
***********************************************************************************************************************************/
|
||||
String *cipherPassGen(CipherType cipherType);
|
||||
void infoValidate(const InfoPgData *archiveInfo, const InfoPgData *backupInfo);
|
||||
PgControl pgValidate(void);
|
||||
|
||||
#endif
|
||||
|
@ -7,6 +7,7 @@ Stanza Create Command
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "command/check/common.h"
|
||||
#include "command/control/common.h"
|
||||
#include "command/stanza/common.h"
|
||||
#include "command/stanza/create.h"
|
||||
@ -74,6 +75,7 @@ cmdStanzaCreate(void)
|
||||
|
||||
// Create and save archive info
|
||||
infoArchive = infoArchiveNew(pgControl.version, pgControl.systemId, cipherPassSub);
|
||||
|
||||
infoArchiveSaveFile(
|
||||
infoArchive, storageRepoWriteStanza, INFO_ARCHIVE_PATH_FILE_STR, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
@ -83,6 +85,7 @@ cmdStanzaCreate(void)
|
||||
|
||||
// Create and save backup info
|
||||
infoBackup = infoBackupNew(pgControl.version, pgControl.systemId, cipherPassSub);
|
||||
|
||||
infoBackupSaveFile(
|
||||
infoBackup, storageRepoWriteStanza, INFO_BACKUP_PATH_FILE_STR, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
@ -90,59 +93,41 @@ cmdStanzaCreate(void)
|
||||
// Else if at least one archive and one backup info file exists, then ensure both are valid
|
||||
else if ((archiveInfoFileExists || archiveInfoFileCopyExists) && (backupInfoFileExists || backupInfoFileCopyExists))
|
||||
{
|
||||
infoArchive = infoArchiveLoadFile(
|
||||
storageRepoReadStanza, INFO_ARCHIVE_PATH_FILE_STR, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
// Error if there is a mismatch between the archive and backup info files or the database version/system Id matches
|
||||
// current database
|
||||
checkStanzaInfoPg(
|
||||
storageRepoReadStanza, pgControl.version, pgControl.systemId, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
InfoPgData archiveInfo = infoPgData(infoArchivePg(infoArchive), infoPgDataCurrentId(infoArchivePg(infoArchive)));
|
||||
|
||||
infoBackup = infoBackupLoadFile(
|
||||
storageRepoReadStanza, INFO_BACKUP_PATH_FILE_STR, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
InfoPgData backupInfo = infoPgData(infoBackupPg(infoBackup), infoPgDataCurrentId(infoBackupPg(infoBackup)));
|
||||
// The files are valid - upgrade
|
||||
const String *sourceFile = NULL;
|
||||
const String *destinationFile = NULL;
|
||||
|
||||
// Error if there is a mismatch between the archive and backup info files
|
||||
infoValidate(&archiveInfo, &backupInfo);
|
||||
|
||||
// The archive and backup info files match so check if the versions or system ids match the current database,
|
||||
// if not, then an upgrade may be necessary
|
||||
if (pgControl.version != archiveInfo.version || pgControl.systemId != archiveInfo.systemId)
|
||||
// If the existing files are valid, then, if a file is missing, copy the existing one to the missing one to ensure
|
||||
// there is both a .info and .info.copy
|
||||
if (!archiveInfoFileExists || !archiveInfoFileCopyExists)
|
||||
{
|
||||
THROW(FileInvalidError, "backup and archive info files already exist but do not match the database\n"
|
||||
"HINT: is this the correct stanza?\n"
|
||||
"HINT: did an error occur during stanza-upgrade?");
|
||||
sourceFile = archiveInfoFileExists ? INFO_ARCHIVE_PATH_FILE_STR : INFO_ARCHIVE_PATH_FILE_COPY_STR;
|
||||
destinationFile = !archiveInfoFileExists ? INFO_ARCHIVE_PATH_FILE_STR : INFO_ARCHIVE_PATH_FILE_COPY_STR;
|
||||
|
||||
storageCopyNP(
|
||||
storageNewReadNP(storageRepoReadStanza, sourceFile),
|
||||
storageNewWriteNP(storageRepoWriteStanza, destinationFile));
|
||||
}
|
||||
// Else the files are valid
|
||||
else
|
||||
|
||||
if (!backupInfoFileExists || !backupInfoFileCopyExists)
|
||||
{
|
||||
const String *sourceFile = NULL;
|
||||
const String *destinationFile = NULL;
|
||||
sourceFile = backupInfoFileExists ? INFO_BACKUP_PATH_FILE_STR : INFO_BACKUP_PATH_FILE_COPY_STR;
|
||||
destinationFile = !backupInfoFileExists ? INFO_BACKUP_PATH_FILE_STR : INFO_BACKUP_PATH_FILE_COPY_STR;
|
||||
|
||||
// If the existing files are valid, then, if a file is missing, copy the existing one to the missing one to ensure
|
||||
// there is both a .info and .info.copy
|
||||
if (!archiveInfoFileExists || !archiveInfoFileCopyExists)
|
||||
{
|
||||
sourceFile = archiveInfoFileExists ? INFO_ARCHIVE_PATH_FILE_STR : INFO_ARCHIVE_PATH_FILE_COPY_STR;
|
||||
destinationFile = !archiveInfoFileExists ? INFO_ARCHIVE_PATH_FILE_STR : INFO_ARCHIVE_PATH_FILE_COPY_STR;
|
||||
|
||||
storageCopyNP(
|
||||
storageNewReadNP(storageRepoReadStanza, sourceFile),
|
||||
storageNewWriteNP(storageRepoWriteStanza, destinationFile));
|
||||
}
|
||||
|
||||
if (!backupInfoFileExists || !backupInfoFileCopyExists)
|
||||
{
|
||||
sourceFile = backupInfoFileExists ? INFO_BACKUP_PATH_FILE_STR : INFO_BACKUP_PATH_FILE_COPY_STR;
|
||||
destinationFile = !backupInfoFileExists ? INFO_BACKUP_PATH_FILE_STR : INFO_BACKUP_PATH_FILE_COPY_STR;
|
||||
|
||||
storageCopyNP(
|
||||
storageNewReadNP(storageRepoReadStanza, sourceFile),
|
||||
storageNewWriteNP(storageRepoWriteStanza, destinationFile));
|
||||
}
|
||||
|
||||
// If no files copied, then the stanza was already valid
|
||||
if (sourceFile == NULL)
|
||||
LOG_INFO("stanza '%s' already exists and is valid", strPtr(cfgOptionStr(cfgOptStanza)));
|
||||
storageCopyNP(
|
||||
storageNewReadNP(storageRepoReadStanza, sourceFile),
|
||||
storageNewWriteNP(storageRepoWriteStanza, destinationFile));
|
||||
}
|
||||
|
||||
// If no files copied, then the stanza was already valid
|
||||
if (sourceFile == NULL)
|
||||
LOG_INFO("stanza '%s' already exists and is valid", strPtr(cfgOptionStr(cfgOptStanza)));
|
||||
}
|
||||
// Else if both .info and corresponding .copy file are missing for one but not the other, then error
|
||||
else
|
||||
|
@ -7,6 +7,7 @@ Stanza Update Command
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "command/check/common.h"
|
||||
#include "command/control/common.h"
|
||||
#include "command/stanza/common.h"
|
||||
#include "command/stanza/upgrade.h"
|
||||
@ -74,7 +75,7 @@ cmdStanzaUpgrade(void)
|
||||
// needed to be updated)
|
||||
backupInfo = infoPgData(infoBackupPg(infoBackup), infoPgDataCurrentId(infoBackupPg(infoBackup)));
|
||||
archiveInfo = infoPgData(infoArchivePg(infoArchive), infoPgDataCurrentId(infoArchivePg(infoArchive)));
|
||||
infoValidate(&archiveInfo, &backupInfo);
|
||||
checkStanzaInfo(&archiveInfo, &backupInfo);
|
||||
|
||||
// Save archive info
|
||||
if (infoArchiveUpgrade)
|
||||
|
42
src/db/db.c
42
src/db/db.c
@ -26,6 +26,8 @@ struct Db
|
||||
|
||||
unsigned int pgVersion; // Version as reported by the database
|
||||
const String *pgDataPath; // Data directory reported by the database
|
||||
const String *archiveMode; // The archive_mode reported by the database
|
||||
const String *archiveCommand; // The archive_command reported by the database
|
||||
};
|
||||
|
||||
OBJECT_DEFINE_MOVE(DB);
|
||||
@ -203,17 +205,21 @@ dbOpen(Db *this)
|
||||
this,
|
||||
STRDEF(
|
||||
"select (select setting from pg_catalog.pg_settings where name = 'server_version_num')::int4,"
|
||||
" (select setting from pg_catalog.pg_settings where name = 'data_directory')::text"));
|
||||
" (select setting from pg_catalog.pg_settings where name = 'data_directory')::text,"
|
||||
" (select setting from pg_catalog.pg_settings where name = 'archive_mode')::text,"
|
||||
" (select setting from pg_catalog.pg_settings where name = 'archive_command')::text"));
|
||||
|
||||
// Strip the minor version off since we don't need it. In the future it might be a good idea to warn users when they are
|
||||
// running an old minor version.
|
||||
this->pgVersion = varUIntForce(varLstGet(row, 0)) / 100 * 100;
|
||||
|
||||
// Store the data directory that PostgreSQL is running in. This can be compared to the configured pgBackRest directory when
|
||||
// validating the configuration.
|
||||
// Store the data directory that PostgreSQL is running in, the archive mode, and archive command. These can be compared to
|
||||
// the configured pgBackRest directory, and archive settings checked for validity, when validating the configuration.
|
||||
MEM_CONTEXT_BEGIN(this->memContext)
|
||||
{
|
||||
this->pgDataPath = strDup(varStr(varLstGet(row, 1)));
|
||||
this->archiveMode = strDup(varStr(varLstGet(row, 2)));
|
||||
this->archiveCommand = strDup(varStr(varLstGet(row, 3)));
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
|
||||
@ -313,6 +319,36 @@ dbPgVersion(const Db *this)
|
||||
FUNCTION_TEST_RETURN(this->pgVersion);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Get pg version loaded from the server_version_num GUC
|
||||
***********************************************************************************************************************************/
|
||||
const String *
|
||||
dbArchiveMode(const Db *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(DB, this);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
|
||||
FUNCTION_TEST_RETURN(this->archiveMode);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Get pg version loaded from the server_version_num GUC
|
||||
***********************************************************************************************************************************/
|
||||
const String *
|
||||
dbArchiveCommand(const Db *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(DB, this);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
|
||||
FUNCTION_TEST_RETURN(this->archiveCommand);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Render as string for logging
|
||||
***********************************************************************************************************************************/
|
||||
|
@ -38,6 +38,8 @@ Getters
|
||||
***********************************************************************************************************************************/
|
||||
const String *dbPgDataPath(const Db *this);
|
||||
unsigned int dbPgVersion(const Db *this);
|
||||
const String *dbArchiveMode(const Db *this);
|
||||
const String *dbArchiveCommand(const Db *this);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Destructor
|
||||
|
@ -133,8 +133,6 @@ main(int argListSize, const char *argList[])
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
case cfgCmdCheck:
|
||||
{
|
||||
// Functionality is currently split between Perl and C
|
||||
perlExec();
|
||||
cmdCheck();
|
||||
break;
|
||||
}
|
||||
|
@ -3192,204 +3192,6 @@ static const EmbeddedModule embeddedModule[] =
|
||||
"\n"
|
||||
"1;\n"
|
||||
},
|
||||
{
|
||||
.name = "pgBackRest/Check/Check.pm",
|
||||
.data =
|
||||
"\n\n\n"
|
||||
"package pgBackRest::Check::Check;\n"
|
||||
"\n"
|
||||
"use strict;\n"
|
||||
"use warnings FATAL => qw(all);\n"
|
||||
"use Carp qw(confess);\n"
|
||||
"use English '-no_match_vars';\n"
|
||||
"\n"
|
||||
"use pgBackRest::Archive::Common;\n"
|
||||
"use pgBackRest::Archive::Get::File;\n"
|
||||
"use pgBackRest::Backup::Info;\n"
|
||||
"use pgBackRest::Common::Exception;\n"
|
||||
"use pgBackRest::Common::Log;\n"
|
||||
"use pgBackRest::Common::Wait;\n"
|
||||
"use pgBackRest::Config::Config;\n"
|
||||
"use pgBackRest::Db;\n"
|
||||
"use pgBackRest::Manifest;\n"
|
||||
"use pgBackRest::Protocol::Helper;\n"
|
||||
"use pgBackRest::Protocol::Storage::Helper;\n"
|
||||
"\n\n\n\n"
|
||||
"sub new\n"
|
||||
"{\n"
|
||||
"my $class = shift;\n"
|
||||
"\n\n"
|
||||
"my ($strOperation) = logDebugParam(__PACKAGE__ . '->new');\n"
|
||||
"\n\n"
|
||||
"my $self = {};\n"
|
||||
"bless $self, $class;\n"
|
||||
"\n\n"
|
||||
"return logDebugReturn\n"
|
||||
"(\n"
|
||||
"$strOperation,\n"
|
||||
"{name => 'self', value => $self}\n"
|
||||
");\n"
|
||||
"}\n"
|
||||
"\n\n\n\n\n\n\n\n"
|
||||
"sub process\n"
|
||||
"{\n"
|
||||
"my $self = shift;\n"
|
||||
"\n\n"
|
||||
"my $strOperation = logDebugParam(__PACKAGE__ . '->process');\n"
|
||||
"\n\n"
|
||||
"my $iArchiveTimeout = cfgOption(CFGOPT_ARCHIVE_TIMEOUT);\n"
|
||||
"\n"
|
||||
"my $iResult = 0;\n"
|
||||
"my $strResultMessage = undef;\n"
|
||||
"\n"
|
||||
"my $strArchiveId = undef;\n"
|
||||
"my $strArchiveFile = undef;\n"
|
||||
"my $strWalSegment = undef;\n"
|
||||
"\n\n"
|
||||
"my ($oDb) = dbMasterGet();\n"
|
||||
"\n\n"
|
||||
"my ($strDbVersion, $iControlVersion, $iCatalogVersion, $ullDbSysId) = $oDb->info();\n"
|
||||
"\n\n"
|
||||
"logLevelSet(undef, OFF);\n"
|
||||
"\n\n"
|
||||
"for (my $iRemoteIdx = 1; $iRemoteIdx <= cfgOptionIndexTotal(CFGOPT_PG_HOST); $iRemoteIdx++)\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"if (cfgOptionTest(cfgOptionIdFromIndex(CFGOPT_PG_PATH, $iRemoteIdx)) ||\n"
|
||||
"cfgOptionTest(cfgOptionIdFromIndex(CFGOPT_PG_HOST, $iRemoteIdx)))\n"
|
||||
"{\n"
|
||||
"eval\n"
|
||||
"{\n"
|
||||
"\n\n"
|
||||
"my $oBackupManifest = new pgBackRest::Manifest(\"/dev/null/manifest.chk\",\n"
|
||||
"{bLoad => false, strDbVersion => $strDbVersion, iDbCatalogVersion => $iCatalogVersion,\n"
|
||||
"strCipherPass => 'x', strCipherPassSub => 'x'});\n"
|
||||
"\n\n"
|
||||
"$oBackupManifest->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_ID, undef, 1);\n"
|
||||
"$oBackupManifest->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CONTROL, undef, $iControlVersion);\n"
|
||||
"$oBackupManifest->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_SYSTEM_ID, undef, $ullDbSysId);\n"
|
||||
"\n"
|
||||
"$oBackupManifest->build(\n"
|
||||
"storageDb({iRemoteIdx => $iRemoteIdx}), cfgOption(cfgOptionIdFromIndex(CFGOPT_PG_PATH, $iRemoteIdx)), undef,\n"
|
||||
"cfgOptionValid(CFGOPT_ONLINE) && cfgOption(CFGOPT_ONLINE), false, $oDb->tablespaceMapGet());\n"
|
||||
"\n"
|
||||
"return true;\n"
|
||||
"}\n"
|
||||
"or do\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"$strResultMessage = \"Database: ${strDbVersion} ${ullDbSysId} \" . exceptionMessage($EVAL_ERROR) .\n"
|
||||
"(($iResult != 0) ? \"\\n[$iResult] : $strResultMessage\" : \"\");\n"
|
||||
"$iResult = exceptionCode($EVAL_ERROR);\n"
|
||||
"};\n"
|
||||
"}\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
"logLevelSet(undef, cfgOption(CFGOPT_LOG_LEVEL_CONSOLE));\n"
|
||||
"\n\n"
|
||||
"if ($iResult == 0)\n"
|
||||
"{\n"
|
||||
"\n\n"
|
||||
"($oDb) = dbObjectGet();\n"
|
||||
"\n\n"
|
||||
"$oDb->configValidate();\n"
|
||||
"\n\n"
|
||||
"logLevelSet(undef, OFF);\n"
|
||||
"\n\n"
|
||||
"eval\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"$self->backupInfoCheck();\n"
|
||||
"return true;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"or do\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"$iResult = exceptionCode($EVAL_ERROR);\n"
|
||||
"$strResultMessage = exceptionMessage($EVAL_ERROR);\n"
|
||||
"};\n"
|
||||
"\n\n"
|
||||
"if ($iResult == 0)\n"
|
||||
"{\n"
|
||||
"eval\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"($strArchiveId) = archiveGetCheck();\n"
|
||||
"return true;\n"
|
||||
"}\n"
|
||||
"or do\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"$iResult = exceptionCode($EVAL_ERROR);\n"
|
||||
"$strResultMessage = exceptionMessage($EVAL_ERROR);\n"
|
||||
"};\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
"logLevelSet(undef, cfgOption(CFGOPT_LOG_LEVEL_CONSOLE));\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
"if ($iResult != 0)\n"
|
||||
"{\n"
|
||||
"&log(ERROR, $strResultMessage, $iResult);\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
"return logDebugReturn\n"
|
||||
"(\n"
|
||||
"$strOperation,\n"
|
||||
"{name => 'iResult', value => $iResult, trace => true}\n"
|
||||
");\n"
|
||||
"}\n"
|
||||
"\n\n\n\n\n\n"
|
||||
"sub backupInfoCheck\n"
|
||||
"{\n"
|
||||
"my $self = shift;\n"
|
||||
"\n\n"
|
||||
"my\n"
|
||||
"(\n"
|
||||
"$strOperation,\n"
|
||||
"$strDbVersion,\n"
|
||||
"$iControlVersion,\n"
|
||||
"$iCatalogVersion,\n"
|
||||
"$ullDbSysId,\n"
|
||||
") =\n"
|
||||
"logDebugParam\n"
|
||||
"(\n"
|
||||
"__PACKAGE__ . '->backupInfoCheck', \\@_,\n"
|
||||
"{name => 'strDbVersion', required => false},\n"
|
||||
"{name => 'iControlVersion', required => false},\n"
|
||||
"{name => 'iCatalogVersion', required => false},\n"
|
||||
"{name => 'ullDbSysId', required => false}\n"
|
||||
");\n"
|
||||
"\n\n"
|
||||
"my $iDbHistoryId;\n"
|
||||
"\n"
|
||||
"if (!defined($strDbVersion) || !defined($iControlVersion) || !defined($iCatalogVersion) || !defined($ullDbSysId))\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"($strDbVersion, $iControlVersion, $iCatalogVersion, $ullDbSysId) = dbMasterGet()->info();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"if (!isRepoLocal())\n"
|
||||
"{\n"
|
||||
"$iDbHistoryId = protocolGet(CFGOPTVAL_REMOTE_TYPE_BACKUP)->cmdExecute(\n"
|
||||
"OP_CHECK_BACKUP_INFO_CHECK, [$strDbVersion, $iControlVersion, $iCatalogVersion, $ullDbSysId]);\n"
|
||||
"}\n"
|
||||
"else\n"
|
||||
"{\n"
|
||||
"$iDbHistoryId = (new pgBackRest::Backup::Info(storageRepo()->pathGet(STORAGE_REPO_BACKUP)))->check(\n"
|
||||
"$strDbVersion, $iControlVersion, $iCatalogVersion, $ullDbSysId);\n"
|
||||
"}\n"
|
||||
"\n\n"
|
||||
"return logDebugReturn\n"
|
||||
"(\n"
|
||||
"$strOperation,\n"
|
||||
"{name => 'iDbHistoryId', value => $iDbHistoryId, trace => true}\n"
|
||||
");\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"1;\n"
|
||||
},
|
||||
{
|
||||
.name = "pgBackRest/Common/Cipher.pm",
|
||||
.data =
|
||||
@ -8279,15 +8081,6 @@ static const EmbeddedModule embeddedModule[] =
|
||||
"$oRemote->process(\n"
|
||||
"cfgOption(CFGOPT_LOCK_PATH), cfgOption(CFGOPT_COMMAND), cfgOption(CFGOPT_STANZA, false), cfgOption(CFGOPT_PROCESS));\n"
|
||||
"}\n"
|
||||
"\n\n\n"
|
||||
"elsif (cfgCommandTest(CFGCMD_CHECK))\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"require pgBackRest::Check::Check;\n"
|
||||
"pgBackRest::Check::Check->import();\n"
|
||||
"\n"
|
||||
"$iResult = new pgBackRest::Check::Check()->process();\n"
|
||||
"}\n"
|
||||
"else\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
@ -10342,9 +10135,6 @@ static const EmbeddedModule embeddedModule[] =
|
||||
"use constant OP_ARCHIVE_GET_CHECK => 'archiveCheck';\n"
|
||||
"push @EXPORT, qw(OP_ARCHIVE_GET_CHECK);\n"
|
||||
"\n\n"
|
||||
"use constant OP_CHECK_BACKUP_INFO_CHECK => 'backupInfoCheck';\n"
|
||||
"push @EXPORT, qw(OP_CHECK_BACKUP_INFO_CHECK);\n"
|
||||
"\n\n"
|
||||
"use constant OP_DB_CONNECT => 'dbConnect';\n"
|
||||
"push @EXPORT, qw(OP_DB_CONNECT);\n"
|
||||
"use constant OP_DB_EXECUTE_SQL => 'dbExecSql';\n"
|
||||
@ -11439,7 +11229,6 @@ static const EmbeddedModule embeddedModule[] =
|
||||
"use pgBackRest::Common::Io::Buffered;\n"
|
||||
"use pgBackRest::Common::Wait;\n"
|
||||
"use pgBackRest::Archive::Get::File;\n"
|
||||
"use pgBackRest::Check::Check;\n"
|
||||
"use pgBackRest::Config::Config;\n"
|
||||
"use pgBackRest::Db;\n"
|
||||
"use pgBackRest::Protocol::Command::Minion;\n"
|
||||
@ -11481,7 +11270,6 @@ static const EmbeddedModule embeddedModule[] =
|
||||
"\n\n"
|
||||
"my $oStorage = cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_DB) ? storageDb() : storageRepo();\n"
|
||||
"\n"
|
||||
"my $oCheck = cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_BACKUP) ? new pgBackRest::Check::Check() : undef;\n"
|
||||
"my $oDb = cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_DB) ? new pgBackRest::Db() : undef;\n"
|
||||
"\n\n"
|
||||
"my $hCommandMap =\n"
|
||||
@ -11489,8 +11277,6 @@ static const EmbeddedModule embeddedModule[] =
|
||||
"\n"
|
||||
"&OP_ARCHIVE_GET_CHECK => sub {archiveGetCheck(@{shift()})},\n"
|
||||
"\n\n"
|
||||
"&OP_CHECK_BACKUP_INFO_CHECK => sub {$oCheck->backupInfoCheck(@{shift()})},\n"
|
||||
"\n\n"
|
||||
"&OP_DB_CONNECT => sub {$oDb->connect()},\n"
|
||||
"&OP_DB_EXECUTE_SQL => sub {$oDb->executeSql(@{shift()})},\n"
|
||||
"&OP_DB_INFO => sub {$oDb->info(@{shift()})},\n"
|
||||
|
@ -640,7 +640,8 @@ unit:
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: check
|
||||
total: 2
|
||||
total: 4
|
||||
containerReq: true
|
||||
|
||||
coverage:
|
||||
command/check/common: full
|
||||
|
@ -111,7 +111,7 @@ stanza-create db - fail on database mismatch and warn force option deprecated (d
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --force --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --no-online --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
P00 WARN: option --force is no longer supported
|
||||
P00 ERROR: [028]: backup and archive info files already exist but do not match the database
|
||||
P00 ERROR: [028]: backup and archive info files exist but do not match the database
|
||||
HINT: is this the correct stanza?
|
||||
HINT: did an error occur during stanza-upgrade?
|
||||
P00 INFO: stanza-create command end: aborted with exception [028]
|
||||
|
@ -129,7 +129,7 @@ stanza-create db - fail on database mismatch and warn force option deprecated (b
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: stanza-create command begin [BACKREST-VERSION]: --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/backup/pgbackrest.conf --db-timeout=45 --force --lock-path=[TEST_PATH]/backup/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/backup/log --log-subprocess --no-log-timestamp --no-online --pg1-host=db-master --pg1-host-cmd=[BACKREST-BIN] --pg1-host-config=[TEST_PATH]/db-master/pgbackrest.conf --pg1-host-user=[USER-1] --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-cipher-pass=<redacted> --repo1-cipher-type=aes-256-cbc --repo1-path=/ --repo1-s3-bucket=pgbackrest-dev --repo1-s3-endpoint=s3.amazonaws.com --repo1-s3-key=<redacted> --repo1-s3-key-secret=<redacted> --repo1-s3-region=us-east-1 --no-repo1-s3-verify-tls --repo1-type=s3 --stanza=db
|
||||
P00 WARN: option --force is no longer supported
|
||||
P00 ERROR: [028]: backup and archive info files already exist but do not match the database
|
||||
P00 ERROR: [028]: backup and archive info files exist but do not match the database
|
||||
HINT: is this the correct stanza?
|
||||
HINT: did an error occur during stanza-upgrade?
|
||||
P00 DETAIL: tls statistics:[TLS-STATISTICS]
|
||||
|
@ -45,10 +45,6 @@ check db - fail on backup info mismatch (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --archive-timeout=5 --stanza=db check
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
check db - confirm master manifest->build executed (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --archive-timeout=5 --stanza=db check
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
check db - verify success after backup (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --archive-timeout=5 --stanza=db check
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -153,10 +153,6 @@ repo1-host-config=[TEST_PATH]/db-master/pgbackrest.conf
|
||||
repo1-host-user=[USER-1]
|
||||
spool-path=[TEST_PATH]/db-standby/spool
|
||||
|
||||
check db - confirm standby manifest->build executed (db-standby host)
|
||||
> [CONTAINER-EXEC] db-standby [BACKREST-BIN] --config=[TEST_PATH]/db-standby/pgbackrest.conf --archive-timeout=5 --stanza=db check
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
check db - verify check command on standby (db-standby host)
|
||||
> [CONTAINER-EXEC] db-standby [BACKREST-BIN] --config=[TEST_PATH]/db-standby/pgbackrest.conf --stanza=db check
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -157,10 +157,6 @@ spool-path=[TEST_PATH]/db-standby/spool
|
||||
archive-copy=y
|
||||
start-fast=y
|
||||
|
||||
check db - confirm standby manifest->build executed (db-standby host)
|
||||
> [CONTAINER-EXEC] db-standby [BACKREST-BIN] --config=[TEST_PATH]/db-standby/pgbackrest.conf --archive-timeout=5 --stanza=db check
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
incr backup - update during backup (db-standby host)
|
||||
> [CONTAINER-EXEC] db-standby [BACKREST-BIN] --config=[TEST_PATH]/db-standby/pgbackrest.conf --stop-auto --buffer-size=32768 --delta --stanza=db backup --test --test-delay=1 --test-point=manifest-build=y
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -69,10 +69,6 @@ check db - fail on backup info mismatch (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --archive-timeout=5 --stanza=db check
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
check db - confirm master manifest->build executed (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --archive-timeout=5 --stanza=db check
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
check db - verify success after backup (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --archive-timeout=5 --stanza=db check
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -215,10 +215,6 @@ repo1-path=[TEST_PATH]/backup/repo
|
||||
archive-copy=y
|
||||
start-fast=y
|
||||
|
||||
check db - confirm standby manifest->build executed (db-standby host)
|
||||
> [CONTAINER-EXEC] db-standby [BACKREST-BIN] --config=[TEST_PATH]/db-standby/pgbackrest.conf --archive-timeout=5 --stanza=db check
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
check db - verify check command on standby (db-standby host)
|
||||
> [CONTAINER-EXEC] db-standby [BACKREST-BIN] --config=[TEST_PATH]/db-standby/pgbackrest.conf --stanza=db check
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -69,10 +69,6 @@ check db - fail on backup info mismatch (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --archive-timeout=5 --stanza=db check
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
check db - confirm master manifest->build executed (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --archive-timeout=5 --stanza=db check
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
check db - verify success after backup (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --archive-timeout=5 --stanza=db check
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -228,14 +228,15 @@ sub run
|
||||
# load the archive info file and munge it for testing by breaking the database version
|
||||
$oHostBackup->infoMunge(
|
||||
storageRepo()->pathGet(STORAGE_REPO_ARCHIVE . qw{/} . ARCHIVE_INFO_FILE),
|
||||
{&INFO_ARCHIVE_SECTION_DB => {&INFO_ARCHIVE_KEY_DB_VERSION => '8.0'}});
|
||||
{&INFO_ARCHIVE_SECTION_DB => {&INFO_ARCHIVE_KEY_DB_VERSION => '8.0'},
|
||||
&INFO_ARCHIVE_SECTION_DB_HISTORY => {1 => {&INFO_ARCHIVE_KEY_DB_VERSION => '8.0'}}});
|
||||
|
||||
$oHostDbMaster->check($strComment, {iTimeout => 0.1, iExpectedExitStatus => ERROR_ARCHIVE_MISMATCH});
|
||||
$oHostDbMaster->check($strComment, {iTimeout => 0.1, iExpectedExitStatus => ERROR_FILE_INVALID});
|
||||
|
||||
# If running the remote tests then also need to run check locally
|
||||
if ($bHostBackup)
|
||||
{
|
||||
$oHostBackup->check($strComment, {iTimeout => 0.1, iExpectedExitStatus => ERROR_ARCHIVE_MISMATCH});
|
||||
$oHostBackup->check($strComment, {iTimeout => 0.1, iExpectedExitStatus => ERROR_FILE_INVALID});
|
||||
}
|
||||
|
||||
# Restore the file to its original condition
|
||||
@ -264,29 +265,32 @@ sub run
|
||||
$oHostBackup->infoMunge(
|
||||
storageRepo()->pathGet(STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO),
|
||||
{&INFO_BACKUP_SECTION_DB =>
|
||||
{&INFO_BACKUP_KEY_DB_VERSION => '8.0', &INFO_BACKUP_KEY_SYSTEM_ID => 6999999999999999999}});
|
||||
{&INFO_BACKUP_KEY_DB_VERSION => '8.0', &INFO_BACKUP_KEY_SYSTEM_ID => 6999999999999999999},
|
||||
&INFO_BACKUP_SECTION_DB_HISTORY =>
|
||||
{1 => {&INFO_BACKUP_KEY_DB_VERSION => '8.0', &INFO_BACKUP_KEY_SYSTEM_ID => 6999999999999999999}}});
|
||||
|
||||
# Run the test
|
||||
$oHostDbMaster->check($strComment, {iTimeout => 5, iExpectedExitStatus => ERROR_BACKUP_MISMATCH});
|
||||
$oHostDbMaster->check($strComment, {iTimeout => 5, iExpectedExitStatus => ERROR_FILE_INVALID});
|
||||
|
||||
# If running the remote tests then also need to run check locally
|
||||
if ($bHostBackup)
|
||||
{
|
||||
$oHostBackup->check($strComment, {iTimeout => 5, iExpectedExitStatus => ERROR_BACKUP_MISMATCH});
|
||||
$oHostBackup->check($strComment, {iTimeout => 5, iExpectedExitStatus => ERROR_FILE_INVALID});
|
||||
}
|
||||
|
||||
# Restore the file to its original condition
|
||||
$oHostBackup->infoRestore(storageRepo()->pathGet(STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO));
|
||||
|
||||
# ??? Removed temporarily until manifest build can be brought back into the check command
|
||||
# Create a directory in pg_data location that is only readable by root to ensure manifest->build is called by check
|
||||
my $strDir = $oHostDbMaster->dbBasePath() . '/rootreaddir';
|
||||
executeTest('sudo mkdir ' . $strDir);
|
||||
executeTest("sudo chown root:root ${strDir}");
|
||||
executeTest("sudo chmod 400 ${strDir}");
|
||||
|
||||
$strComment = 'confirm master manifest->build executed';
|
||||
$oHostDbMaster->check($strComment, {iTimeout => 5, iExpectedExitStatus => ERROR_PATH_OPEN});
|
||||
executeTest("sudo rmdir ${strDir}");
|
||||
# my $strDir = $oHostDbMaster->dbBasePath() . '/rootreaddir';
|
||||
# executeTest('sudo mkdir ' . $strDir);
|
||||
# executeTest("sudo chown root:root ${strDir}");
|
||||
# executeTest("sudo chmod 400 ${strDir}");
|
||||
#
|
||||
# $strComment = 'confirm master manifest->build executed';
|
||||
# $oHostDbMaster->check($strComment, {iTimeout => 5, iExpectedExitStatus => ERROR_PATH_OPEN});
|
||||
# executeTest("sudo rmdir ${strDir}");
|
||||
|
||||
# Providing a sufficient archive-timeout, verify that the check command runs successfully now with valid
|
||||
# archive.info and backup.info files
|
||||
@ -491,27 +495,28 @@ sub run
|
||||
$strFullBackup = $strStandbyBackup;
|
||||
}
|
||||
|
||||
# Create a directory in pg_data location that is only readable by root to ensure manifest->build is called by check
|
||||
my $strDir = $oHostDbStandby->dbBasePath() . '/rootreaddir';
|
||||
executeTest('sudo mkdir ' . $strDir);
|
||||
executeTest("sudo chown root:root ${strDir}");
|
||||
executeTest("sudo chmod 400 ${strDir}");
|
||||
|
||||
my $strComment = 'confirm standby manifest->build executed';
|
||||
|
||||
# If there is an invalid host, the final error returned from check will be the inability to resolve the name which is
|
||||
# an open error instead of a read error
|
||||
if (!$oHostDbStandby->bogusHost())
|
||||
{
|
||||
$oHostDbStandby->check($strComment, {iTimeout => 5, iExpectedExitStatus => ERROR_PATH_OPEN});
|
||||
}
|
||||
else
|
||||
{
|
||||
$oHostDbStandby->check($strComment, {iTimeout => 5, iExpectedExitStatus => ERROR_FILE_READ});
|
||||
}
|
||||
|
||||
# Remove the directory in pg_data location that is only readable by root
|
||||
executeTest("sudo rmdir ${strDir}");
|
||||
# ??? Removed temporarily until manifest build can be brought back into the check command
|
||||
# # Create a directory in pg_data location that is only readable by root to ensure manifest->build is called by check
|
||||
# my $strDir = $oHostDbStandby->dbBasePath() . '/rootreaddir';
|
||||
# executeTest('sudo mkdir ' . $strDir);
|
||||
# executeTest("sudo chown root:root ${strDir}");
|
||||
# executeTest("sudo chmod 400 ${strDir}");
|
||||
#
|
||||
# my $strComment = 'confirm standby manifest->build executed';
|
||||
#
|
||||
# # If there is an invalid host, the final error returned from check will be the inability to resolve the name which is
|
||||
# # an open error instead of a read error
|
||||
# if (!$oHostDbStandby->bogusHost())
|
||||
# {
|
||||
# $oHostDbStandby->check($strComment, {iTimeout => 5, iExpectedExitStatus => ERROR_PATH_OPEN});
|
||||
# }
|
||||
# else
|
||||
# {
|
||||
# $oHostDbStandby->check($strComment, {iTimeout => 5, iExpectedExitStatus => ERROR_FILE_READ});
|
||||
# }
|
||||
#
|
||||
# # Remove the directory in pg_data location that is only readable by root
|
||||
# executeTest("sudo rmdir ${strDir}");
|
||||
|
||||
# Confirm the check command runs without error on a standby (when a bogus host is not configured)
|
||||
if (!$oHostDbStandby->bogusHost())
|
||||
|
@ -54,21 +54,29 @@ Macros for defining groups of functions that implement various queries and comma
|
||||
{.session = sessionParam, .function = HRNPQ_CLEAR}, \
|
||||
{.session = sessionParam, .function = HRNPQ_GETRESULT, .resultNull = true}
|
||||
|
||||
#define HRNPQ_MACRO_VALIDATE_QUERY(sessionParam, versionParam, pgPathParam) \
|
||||
#define HRNPQ_MACRO_VALIDATE_QUERY(sessionParam, versionParam, pgPathParam, archiveMode, archiveCommand) \
|
||||
{.session = sessionParam, .function = HRNPQ_SENDQUERY, .param = \
|
||||
"[\"select (select setting from pg_catalog.pg_settings where name = 'server_version_num')::int4," \
|
||||
" (select setting from pg_catalog.pg_settings where name = 'data_directory')::text\"]", \
|
||||
" (select setting from pg_catalog.pg_settings where name = 'data_directory')::text," \
|
||||
" (select setting from pg_catalog.pg_settings where name = 'archive_mode')::text," \
|
||||
" (select setting from pg_catalog.pg_settings where name = 'archive_command')::text\"]", \
|
||||
.resultInt = 1}, \
|
||||
{.session = sessionParam, .function = HRNPQ_CONSUMEINPUT}, \
|
||||
{.session = sessionParam, .function = HRNPQ_ISBUSY}, \
|
||||
{.session = sessionParam, .function = HRNPQ_GETRESULT}, \
|
||||
{.session = sessionParam, .function = HRNPQ_RESULTSTATUS, .resultInt = PGRES_TUPLES_OK}, \
|
||||
{.session = sessionParam, .function = HRNPQ_NTUPLES, .resultInt = 1}, \
|
||||
{.session = sessionParam, .function = HRNPQ_NFIELDS, .resultInt = 2}, \
|
||||
{.session = sessionParam, .function = HRNPQ_NFIELDS, .resultInt = 4}, \
|
||||
{.session = sessionParam, .function = HRNPQ_FTYPE, .param = "[0]", .resultInt = HRNPQ_TYPE_INT}, \
|
||||
{.session = sessionParam, .function = HRNPQ_FTYPE, .param = "[1]", .resultInt = HRNPQ_TYPE_TEXT}, \
|
||||
{.session = sessionParam, .function = HRNPQ_FTYPE, .param = "[2]", .resultInt = HRNPQ_TYPE_TEXT}, \
|
||||
{.session = sessionParam, .function = HRNPQ_FTYPE, .param = "[3]", .resultInt = HRNPQ_TYPE_TEXT}, \
|
||||
{.session = sessionParam, .function = HRNPQ_GETVALUE, .param = "[0,0]", .resultZ = STRINGIFY(versionParam)}, \
|
||||
{.session = sessionParam, .function = HRNPQ_GETVALUE, .param = "[0,1]", .resultZ = pgPathParam}, \
|
||||
{.session = sessionParam, .function = HRNPQ_GETVALUE, .param = "[0,2]", .resultZ = archiveMode == NULL ? "on" \
|
||||
: archiveMode}, \
|
||||
{.session = sessionParam, .function = HRNPQ_GETVALUE, .param = "[0,3]", .resultZ = archiveCommand == NULL ? PROJECT_BIN \
|
||||
: archiveCommand}, \
|
||||
{.session = sessionParam, .function = HRNPQ_CLEAR}, \
|
||||
{.session = sessionParam, .function = HRNPQ_GETRESULT, .resultNull = true}
|
||||
|
||||
@ -135,15 +143,15 @@ Macros for defining groups of functions that implement various queries and comma
|
||||
/***********************************************************************************************************************************
|
||||
Macros to simplify dbOpen() for specific database versions
|
||||
***********************************************************************************************************************************/
|
||||
#define HRNPQ_MACRO_OPEN_84(sessionParam, connectParam, pgPathParam) \
|
||||
#define HRNPQ_MACRO_OPEN_84(sessionParam, connectParam, pgPathParam, archiveMode, archiveCommand) \
|
||||
HRNPQ_MACRO_OPEN(sessionParam, connectParam), \
|
||||
HRNPQ_MACRO_SET_SEARCH_PATH(sessionParam), \
|
||||
HRNPQ_MACRO_VALIDATE_QUERY(sessionParam, PG_VERSION_84, pgPathParam)
|
||||
HRNPQ_MACRO_VALIDATE_QUERY(sessionParam, PG_VERSION_84, pgPathParam, archiveMode, archiveCommand)
|
||||
|
||||
#define HRNPQ_MACRO_OPEN_92(sessionParam, connectParam, pgPathParam, standbyParam) \
|
||||
#define HRNPQ_MACRO_OPEN_92(sessionParam, connectParam, pgPathParam, standbyParam, archiveMode, archiveCommand) \
|
||||
HRNPQ_MACRO_OPEN(sessionParam, connectParam), \
|
||||
HRNPQ_MACRO_SET_SEARCH_PATH(sessionParam), \
|
||||
HRNPQ_MACRO_VALIDATE_QUERY(sessionParam, PG_VERSION_92, pgPathParam), \
|
||||
HRNPQ_MACRO_VALIDATE_QUERY(sessionParam, PG_VERSION_92, pgPathParam, archiveMode, archiveCommand), \
|
||||
HRNPQ_MACRO_SET_APPLICATION_NAME(sessionParam), \
|
||||
HRNPQ_MACRO_IS_STANDBY_QUERY(sessionParam, standbyParam)
|
||||
|
||||
|
@ -3,11 +3,15 @@ Test Check Command
|
||||
***********************************************************************************************************************************/
|
||||
#include "postgres/version.h"
|
||||
#include "storage/helper.h"
|
||||
#include "storage/posix/storage.h"
|
||||
#include "storage/storage.intern.h"
|
||||
|
||||
#include "command/stanza/create.h"
|
||||
#include "common/harnessConfig.h"
|
||||
#include "common/harnessInfo.h"
|
||||
#include "common/harnessPq.h"
|
||||
#include "info/infoArchive.h"
|
||||
#include "info/infoBackup.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Test Run
|
||||
@ -17,19 +21,173 @@ testRun(void)
|
||||
{
|
||||
FUNCTION_HARNESS_VOID();
|
||||
|
||||
String *pg1Path = strNewFmt("%s/pg1", testPath());
|
||||
Storage *storageTest = storagePosixNew(
|
||||
strNew(testPath()), STORAGE_MODE_FILE_DEFAULT, STORAGE_MODE_PATH_DEFAULT, true, NULL);
|
||||
|
||||
String *pg1 = strNew("pg1");
|
||||
String *pg1Path = strNewFmt("%s/%s", testPath(), strPtr(pg1));
|
||||
String *pg1PathOpt = strNewFmt("--pg1-path=%s", strPtr(pg1Path));
|
||||
String *pg8 = strNew("pg8");
|
||||
String *pg8Path = strNewFmt("%s/%s", testPath(), strPtr(pg8));
|
||||
String *pg8PathOpt = strNewFmt("--pg8-path=%s", strPtr(pg8Path));
|
||||
String *stanza = strNew("test1");
|
||||
String *stanzaOpt = strNewFmt("--stanza=%s", strPtr(stanza));
|
||||
StringList *argList = strLstNew();
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("cmdCheck()"))
|
||||
{
|
||||
StringList *argList = strLstNew();
|
||||
strLstAddZ(argList, "--stanza=test1");
|
||||
// Load Parameters
|
||||
argList = strLstNew();
|
||||
strLstAdd(argList, stanzaOpt);
|
||||
strLstAdd(argList, pg1PathOpt);
|
||||
strLstAdd(argList, strNewFmt("--repo1-path=%s/repo", testPath()));
|
||||
strLstAddZ(argList, "--archive-timeout=.5");
|
||||
harnessCfgLoad(cfgCmdCheck, argList);
|
||||
|
||||
// Set up harness to expect a failure to connect to the database
|
||||
harnessPqScriptSet((HarnessPq [])
|
||||
{
|
||||
{.function = HRNPQ_CONNECTDB, .param = "[\"dbname='postgres' port=5432\"]"},
|
||||
{.function = HRNPQ_STATUS, .resultInt = CONNECTION_BAD},
|
||||
{.function = HRNPQ_ERRORMESSAGE, .resultZ = "error"},
|
||||
{.function = HRNPQ_FINISH},
|
||||
{.function = NULL}
|
||||
});
|
||||
|
||||
TEST_ERROR_FMT(cmdCheck(), ConfigError, "no database found\nHINT: check indexed pg-path/pg-host configurations");
|
||||
harnessLogResult(
|
||||
"P00 WARN: unable to check pg-1: [DbConnectError] unable to connect to 'dbname='postgres' port=5432': error");
|
||||
|
||||
// Standby only, repo local
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
harnessPqScriptSet((HarnessPq [])
|
||||
{
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", strPtr(pg1Path), true, NULL, NULL),
|
||||
HRNPQ_MACRO_CLOSE(1),
|
||||
HRNPQ_MACRO_DONE()
|
||||
});
|
||||
|
||||
TEST_ERROR(cmdCheck(), ConfigError, "primary database not found\nHINT: check indexed pg-path/pg-host configurations");
|
||||
|
||||
// Standby only, repo remote but more than one pg-path configured
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
argList = strLstNew();
|
||||
strLstAdd(argList, stanzaOpt);
|
||||
strLstAdd(argList, pg1PathOpt);
|
||||
strLstAddZ(argList, "--pg8-path=/path/to/standby2");
|
||||
strLstAddZ(argList, "--pg8-port=5433");
|
||||
strLstAddZ(argList, "--repo1-host=repo.domain.com");
|
||||
strLstAddZ(argList, "--archive-timeout=.5");
|
||||
harnessCfgLoad(cfgCmdCheck, argList);
|
||||
|
||||
// Two standbys found but no primary
|
||||
harnessPqScriptSet((HarnessPq [])
|
||||
{
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", "/pgdata", true, NULL, NULL),
|
||||
HRNPQ_MACRO_OPEN_92(8, "dbname='postgres' port=5433", "/pgdata", true, NULL, NULL),
|
||||
|
||||
HRNPQ_MACRO_CLOSE(8),
|
||||
HRNPQ_MACRO_CLOSE(1),
|
||||
|
||||
HRNPQ_MACRO_DONE()
|
||||
});
|
||||
|
||||
TEST_ERROR(cmdCheck(), ConfigError, "primary database not found\nHINT: check indexed pg-path/pg-host configurations");
|
||||
|
||||
// Standby only, repo remote but only one pg-path configured
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
argList = strLstNew();
|
||||
strLstAdd(argList, stanzaOpt);
|
||||
strLstAdd(argList, pg1PathOpt);
|
||||
strLstAddZ(argList, "--repo1-host=repo.domain.com");
|
||||
strLstAddZ(argList, "--archive-timeout=.5");
|
||||
harnessCfgLoad(cfgCmdCheck, argList);
|
||||
|
||||
harnessPqScriptSet((HarnessPq [])
|
||||
{
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", "/pgdata", true, NULL, NULL),
|
||||
HRNPQ_MACRO_CLOSE(1),
|
||||
HRNPQ_MACRO_DONE()
|
||||
});
|
||||
|
||||
// Only confirming we get passed the check for isRepoLocal || more than one pg-path configured
|
||||
TEST_ERROR_FMT(
|
||||
cmdCheck(), FileMissingError, "unable to open missing file '%s/global/pg_control' for read", strPtr(pg1Path));
|
||||
|
||||
// backup-standby set without standby
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
argList = strLstNew();
|
||||
strLstAdd(argList, stanzaOpt);
|
||||
strLstAdd(argList, pg1PathOpt);
|
||||
strLstAdd(argList, strNewFmt("--repo1-path=%s/repo", testPath()));
|
||||
strLstAddZ(argList, "--archive-timeout=.5");
|
||||
strLstAddZ(argList, "--backup-standby");
|
||||
harnessCfgLoad(cfgCmdCheck, argList);
|
||||
|
||||
// Primary database connection ok
|
||||
harnessPqScriptSet((HarnessPq [])
|
||||
{
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", strPtr(pg1Path), false, NULL, NULL),
|
||||
HRNPQ_MACRO_CLOSE(1),
|
||||
HRNPQ_MACRO_DONE()
|
||||
});
|
||||
|
||||
TEST_ERROR_FMT(
|
||||
cmdCheck(), FileMissingError, "unable to open missing file '%s' for read",
|
||||
strPtr(strNewFmt("%s/" PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL, strPtr(pg1Path))));
|
||||
harnessLogResult(
|
||||
strPtr(strNewFmt("P00 WARN: option '%s' is enabled but standby is not properly configured",
|
||||
cfgOptionName(cfgOptBackupStandby))));
|
||||
|
||||
// Standby and primary database
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
// Create pg_control for standby
|
||||
storagePutNP(
|
||||
storageNewWriteNP(storageTest, strNewFmt("%s/" PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL, strPtr(pg1))),
|
||||
pgControlTestToBuffer((PgControl){.version = PG_VERSION_92, .systemId = 6569239123849665679}));
|
||||
|
||||
argList = strLstNew();
|
||||
strLstAdd(argList, stanzaOpt);
|
||||
strLstAdd(argList, pg1PathOpt);
|
||||
strLstAdd(argList, strNewFmt("--repo1-path=%s/repo", testPath()));
|
||||
strLstAddZ(argList, "--archive-timeout=.5");
|
||||
strLstAdd(argList, pg8PathOpt);
|
||||
strLstAddZ(argList, "--pg8-port=5433");
|
||||
harnessCfgLoad(cfgCmdCheck, argList);
|
||||
|
||||
// Standby database path doesn't match pg_control
|
||||
harnessPqScriptSet((HarnessPq [])
|
||||
{
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", testPath(), true, NULL, NULL),
|
||||
HRNPQ_MACRO_OPEN_92(8, "dbname='postgres' port=5433", strPtr(pg8Path), false, NULL, NULL),
|
||||
|
||||
HRNPQ_MACRO_CLOSE(8),
|
||||
HRNPQ_MACRO_CLOSE(1),
|
||||
|
||||
HRNPQ_MACRO_DONE()
|
||||
});
|
||||
|
||||
TEST_ERROR_FMT(
|
||||
cmdCheck(), DbMismatchError, "version '%s' and path '%s' queried from cluster do not match version '%s' and '%s'"
|
||||
" read from '%s/" PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL "'\n"
|
||||
"HINT: the pg1-path and pg1-port settings likely reference different clusters.",
|
||||
strPtr(pgVersionToStr(PG_VERSION_92)), testPath(), strPtr(pgVersionToStr(PG_VERSION_92)), strPtr(pg1Path),
|
||||
strPtr(pg1Path));
|
||||
|
||||
// Standby - Stanza has not yet been created
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
harnessPqScriptSet((HarnessPq [])
|
||||
{
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", strPtr(pg1Path), true, NULL, NULL),
|
||||
HRNPQ_MACRO_OPEN_92(8, "dbname='postgres' port=5433", strPtr(pg8Path), false, NULL, NULL),
|
||||
|
||||
HRNPQ_MACRO_CLOSE(8),
|
||||
HRNPQ_MACRO_CLOSE(1),
|
||||
|
||||
HRNPQ_MACRO_DONE()
|
||||
});
|
||||
|
||||
TEST_ERROR_FMT(
|
||||
cmdCheck(), FileMissingError,
|
||||
"unable to load info file '%s/repo/archive/test1/archive.info' or '%s/repo/archive/test1/archive.info.copy':\n"
|
||||
@ -42,7 +200,14 @@ testRun(void)
|
||||
testPath(), testPath(), strPtr(strNewFmt("%s/repo/archive/test1/archive.info", testPath())),
|
||||
strPtr(strNewFmt("%s/repo/archive/test1/archive.info.copy", testPath())));
|
||||
|
||||
// Create archive.info file
|
||||
// Standby - Stanza created
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
// Create pg_control for primary
|
||||
storagePutNP(
|
||||
storageNewWriteNP(storageTest, strNewFmt("%s/" PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL, strPtr(pg8))),
|
||||
pgControlTestToBuffer((PgControl){.version = PG_VERSION_92, .systemId = 6569239123849665679}));
|
||||
|
||||
// Create info files
|
||||
storagePutNP(
|
||||
storageNewWriteNP(storageRepoWrite(), INFO_ARCHIVE_PATH_FILE_STR),
|
||||
harnessInfoChecksum(
|
||||
@ -55,12 +220,49 @@ testRun(void)
|
||||
"[db:history]\n"
|
||||
"1={\"db-id\":6569239123849665679,\"db-version\":\"9.2\"}\n")));
|
||||
|
||||
storagePutNP(
|
||||
storageNewWriteNP(storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR),
|
||||
harnessInfoChecksum(
|
||||
strNew(
|
||||
"[db]\n"
|
||||
"db-catalog-version=201608131\n"
|
||||
"db-control-version=920\n"
|
||||
"db-id=1\n"
|
||||
"db-system-id=6569239123849665679\n"
|
||||
"db-version=\"9.2\"\n"
|
||||
"\n"
|
||||
"[db:history]\n"
|
||||
"1={\"db-catalog-version\":201608131,\"db-control-version\":920,\"db-system-id\":6569239123849665679,"
|
||||
"\"db-version\":\"9.2\"}\n")));
|
||||
|
||||
harnessPqScriptSet((HarnessPq [])
|
||||
{
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", strPtr(pg1Path), true, NULL, NULL),
|
||||
HRNPQ_MACRO_OPEN_92(8, "dbname='postgres' port=5433", strPtr(pg8Path), false, "off", NULL),
|
||||
|
||||
HRNPQ_MACRO_CLOSE(1),
|
||||
HRNPQ_MACRO_CLOSE(8),
|
||||
|
||||
HRNPQ_MACRO_DONE()
|
||||
});
|
||||
|
||||
// Error on primary but standby check ok
|
||||
TEST_ERROR_FMT(cmdCheck(), ArchiveDisabledError, "archive_mode must be enabled");
|
||||
harnessLogResult("P00 INFO: switch wal not performed because this is a standby");
|
||||
|
||||
// Single primary
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
argList = strLstNew();
|
||||
strLstAdd(argList, stanzaOpt);
|
||||
strLstAdd(argList, pg1PathOpt);
|
||||
strLstAdd(argList, strNewFmt("--repo1-path=%s/repo", testPath()));
|
||||
strLstAddZ(argList, "--archive-timeout=.5");
|
||||
harnessCfgLoad(cfgCmdCheck, argList);
|
||||
|
||||
// Error when WAL segment not found
|
||||
harnessPqScriptSet((HarnessPq [])
|
||||
{
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", strPtr(pg1Path), false),
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", strPtr(pg1Path), false, NULL, NULL),
|
||||
HRNPQ_MACRO_CREATE_RESTORE_POINT(1, "1/1"),
|
||||
HRNPQ_MACRO_WAL_SWITCH(1, "xlog", "000000010000000100000001"),
|
||||
HRNPQ_MACRO_CLOSE(1),
|
||||
@ -81,7 +283,7 @@ testRun(void)
|
||||
// WAL segment is found
|
||||
harnessPqScriptSet((HarnessPq [])
|
||||
{
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", strPtr(pg1Path), false),
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", strPtr(pg1Path), false, NULL, NULL),
|
||||
HRNPQ_MACRO_CREATE_RESTORE_POINT(1, "1/1"),
|
||||
HRNPQ_MACRO_WAL_SWITCH(1, "xlog", "000000010000000100000001"),
|
||||
HRNPQ_MACRO_CLOSE(1),
|
||||
@ -94,7 +296,7 @@ testRun(void)
|
||||
strNew(STORAGE_REPO_ARCHIVE "/9.2-1/000000010000000100000001-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")),
|
||||
buffer);
|
||||
|
||||
TEST_RESULT_VOID(cmdCheck(), "check");
|
||||
TEST_RESULT_VOID(cmdCheck(), "check primary, WAL archived");
|
||||
harnessLogResult(
|
||||
strPtr(
|
||||
strNewFmt(
|
||||
@ -102,55 +304,228 @@ testRun(void)
|
||||
"0000000100000001/000000010000000100000001-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'",
|
||||
testPath())));
|
||||
|
||||
// Single standby
|
||||
// Primary == NULL (for test coverage)
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
DbGetResult dbGroup = {0};
|
||||
TEST_RESULT_VOID(checkPrimary(dbGroup), "primary == NULL");
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("checkManifest()"))
|
||||
{
|
||||
argList = strLstNew();
|
||||
strLstAddZ(argList, "--stanza=test1");
|
||||
strLstAdd(argList, stanzaOpt);
|
||||
strLstAdd(argList, pg1PathOpt);
|
||||
strLstAdd(argList, strNewFmt("--repo1-path=%s/repo", testPath()));
|
||||
strLstAddZ(argList, "--archive-timeout=.5");
|
||||
strLstAddZ(argList, "--pg5-host=localhost");
|
||||
strLstAddZ(argList, "--pg5-path=/path/to/pg5");
|
||||
strLstAdd(argList, strNewFmt("--pg5-host-user=%s", testUser()));
|
||||
harnessCfgLoad(cfgCmdCheck, argList);
|
||||
|
||||
// Set script
|
||||
// Placeholder test for manifest
|
||||
TEST_ERROR(
|
||||
checkManifest(), UnknownError,
|
||||
"remote-0 process on 'localhost' terminated unexpectedly [127]: bash: pgbackrest: command not found");
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("checkDbConfig(), checkArchiveCommand()"))
|
||||
{
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_ERROR_FMT(
|
||||
checkArchiveCommand(NULL), ArchiveCommandInvalidError, "archive_command '[null]' must contain " PROJECT_BIN);
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_ERROR_FMT(
|
||||
checkArchiveCommand(strNew("")), ArchiveCommandInvalidError, "archive_command '' must contain " PROJECT_BIN);
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_ERROR_FMT(
|
||||
checkArchiveCommand(strNew("backrest")), ArchiveCommandInvalidError, "archive_command 'backrest' must contain "
|
||||
PROJECT_BIN);
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_RESULT_BOOL(checkArchiveCommand(strNew("pgbackrest --stanza=demo archive-push %p")), true, "archive_command valid");
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
argList = strLstNew();
|
||||
strLstAdd(argList, stanzaOpt);
|
||||
strLstAdd(argList, pg1PathOpt);
|
||||
strLstAdd(argList, pg8PathOpt);
|
||||
strLstAddZ(argList, "--pg8-port=5433");
|
||||
strLstAdd(argList, strNewFmt("--repo1-path=%s/repo", testPath()));
|
||||
harnessCfgLoad(cfgCmdCheck, argList);
|
||||
|
||||
DbGetResult db = {0};
|
||||
|
||||
harnessPqScriptSet((HarnessPq [])
|
||||
{
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", strPtr(pg1Path), true),
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", strPtr(pg1Path), false, NULL, NULL),
|
||||
HRNPQ_MACRO_OPEN_92(8, "dbname='postgres' port=5433", "/badpath", true, NULL, NULL),
|
||||
|
||||
HRNPQ_MACRO_CLOSE(1),
|
||||
HRNPQ_MACRO_CLOSE(8),
|
||||
HRNPQ_MACRO_DONE()
|
||||
});
|
||||
|
||||
TEST_ASSIGN(db, dbGet(false, false), "get primary and standby");
|
||||
|
||||
TEST_RESULT_VOID(checkDbConfig(PG_VERSION_92, db.primaryId, db.primary, false), "valid db config");
|
||||
|
||||
// Version mismatch
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_ERROR_FMT(
|
||||
checkDbConfig(PG_VERSION_94, db.primaryId, db.primary, false), DbMismatchError,
|
||||
"version '%s' and path '%s' queried from cluster do not match version '%s' and '%s' read from '%s/"
|
||||
PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL "'\n"
|
||||
"HINT: the pg1-path and pg1-port settings likely reference different clusters.",
|
||||
strPtr(pgVersionToStr(PG_VERSION_92)), strPtr(pg1Path), strPtr(pgVersionToStr(PG_VERSION_94)), strPtr(pg1Path),
|
||||
strPtr(pg1Path));
|
||||
|
||||
// Path mismatch
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_ERROR_FMT(
|
||||
checkDbConfig(PG_VERSION_92, db.standbyId, db.standby, true), DbMismatchError,
|
||||
"version '%s' and path '%s' queried from cluster do not match version '%s' and '%s' read from '%s/"
|
||||
PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL "'\n"
|
||||
"HINT: the pg8-path and pg8-port settings likely reference different clusters.",
|
||||
strPtr(pgVersionToStr(PG_VERSION_92)), strPtr(dbPgDataPath(db.standby)), strPtr(pgVersionToStr(PG_VERSION_92)),
|
||||
strPtr(pg8Path), strPtr(pg8Path));
|
||||
|
||||
// archive-check=false
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
strLstAddZ(argList, "--no-archive-check");
|
||||
harnessCfgLoad(cfgCmdCheck, argList);
|
||||
|
||||
TEST_RESULT_VOID(checkDbConfig(PG_VERSION_92, db.primaryId, db.primary, false), "valid db config --no-archive-check");
|
||||
|
||||
// archive-check not valid for command
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
argList = strLstNew();
|
||||
strLstAdd(argList, stanzaOpt);
|
||||
strLstAdd(argList, pg1PathOpt);
|
||||
strLstAdd(argList, pg8PathOpt);
|
||||
strLstAddZ(argList, "--pg8-port=5433");
|
||||
strLstAdd(argList, strNewFmt("--repo1-path=%s/repo", testPath()));
|
||||
harnessCfgLoad(cfgCmdStanzaCreate, argList);
|
||||
|
||||
TEST_RESULT_VOID(
|
||||
checkDbConfig(PG_VERSION_92, db.primaryId, db.primary, false), "valid db config, archive-check not valid for command");
|
||||
|
||||
TEST_RESULT_VOID(dbFree(db.primary), "free primary");
|
||||
TEST_RESULT_VOID(dbFree(db.standby), "free standby");
|
||||
|
||||
// archive_mode=always not supported
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
argList = strLstNew();
|
||||
strLstAdd(argList, stanzaOpt);
|
||||
strLstAdd(argList, pg1PathOpt);
|
||||
strLstAdd(argList, strNewFmt("--repo1-path=%s/repo", testPath()));
|
||||
harnessCfgLoad(cfgCmdCheck, argList);
|
||||
|
||||
harnessPqScriptSet((HarnessPq [])
|
||||
{
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", strPtr(pg1Path), false, "always", NULL),
|
||||
HRNPQ_MACRO_CLOSE(1),
|
||||
HRNPQ_MACRO_DONE()
|
||||
});
|
||||
|
||||
TEST_RESULT_VOID(cmdCheck(), "check");
|
||||
harnessLogResult("P00 INFO: switch wal not performed because no primary was found");
|
||||
TEST_ASSIGN(db, dbGet(true, true), "get primary");
|
||||
TEST_ERROR_FMT(
|
||||
checkDbConfig(PG_VERSION_92, db.primaryId, db.primary, false), FeatureNotSupportedError,
|
||||
"archive_mode=always not supported");
|
||||
|
||||
TEST_RESULT_VOID(dbFree(db.primary), "free primary");
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("checkDbConfig()"))
|
||||
if (testBegin("checkStanzaInfo(), checkStanzaInfoPg()"))
|
||||
{
|
||||
StringList *argList = strLstNew();
|
||||
strLstAddZ(argList, "--stanza=test1");
|
||||
strLstAdd(argList, pg1PathOpt);
|
||||
InfoArchive *archiveInfo = infoArchiveNew(PG_VERSION_96, 6569239123849665679, NULL);
|
||||
InfoPgData archivePg = infoPgData(infoArchivePg(archiveInfo), infoPgDataCurrentId(infoArchivePg(archiveInfo)));
|
||||
|
||||
InfoBackup *backupInfo = infoBackupNew(PG_VERSION_96, 6569239123849665679, NULL);
|
||||
InfoPgData backupPg = infoPgData(infoBackupPg(backupInfo), infoPgDataCurrentId(infoBackupPg(backupInfo)));
|
||||
|
||||
TEST_RESULT_VOID(checkStanzaInfo(&archivePg, &backupPg), "stanza info files match");
|
||||
|
||||
// Create a corrupted backup file - system id
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
backupInfo = infoBackupNew(PG_VERSION_96, 6569239123849665999, NULL);
|
||||
backupPg = infoPgData(infoBackupPg(backupInfo), infoPgDataCurrentId(infoBackupPg(backupInfo)));
|
||||
|
||||
TEST_ERROR_FMT(
|
||||
checkStanzaInfo(&archivePg, &backupPg), FileInvalidError, "backup info file and archive info file do not match\n"
|
||||
"archive: id = 1, version = 9.6, system-id = 6569239123849665679\n"
|
||||
"backup : id = 1, version = 9.6, system-id = 6569239123849665999\n"
|
||||
"HINT: this may be a symptom of repository corruption!");
|
||||
|
||||
// Create a corrupted backup file - system id and version
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
backupInfo = infoBackupNew(PG_VERSION_95, 6569239123849665999, NULL);
|
||||
backupPg = infoPgData(infoBackupPg(backupInfo), infoPgDataCurrentId(infoBackupPg(backupInfo)));
|
||||
|
||||
TEST_ERROR_FMT(
|
||||
checkStanzaInfo(&archivePg, &backupPg), FileInvalidError, "backup info file and archive info file do not match\n"
|
||||
"archive: id = 1, version = 9.6, system-id = 6569239123849665679\n"
|
||||
"backup : id = 1, version = 9.5, system-id = 6569239123849665999\n"
|
||||
"HINT: this may be a symptom of repository corruption!");
|
||||
|
||||
// Create a corrupted backup file - version
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
backupInfo = infoBackupNew(PG_VERSION_95, 6569239123849665679, NULL);
|
||||
backupPg = infoPgData(infoBackupPg(backupInfo), infoPgDataCurrentId(infoBackupPg(backupInfo)));
|
||||
|
||||
TEST_ERROR_FMT(
|
||||
checkStanzaInfo(&archivePg, &backupPg), FileInvalidError, "backup info file and archive info file do not match\n"
|
||||
"archive: id = 1, version = 9.6, system-id = 6569239123849665679\n"
|
||||
"backup : id = 1, version = 9.5, system-id = 6569239123849665679\n"
|
||||
"HINT: this may be a symptom of repository corruption!");
|
||||
|
||||
// Create a corrupted backup file - db id
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
infoBackupPgSet(backupInfo, PG_VERSION_96, 6569239123849665679);
|
||||
backupPg = infoPgData(infoBackupPg(backupInfo), infoPgDataCurrentId(infoBackupPg(backupInfo)));
|
||||
|
||||
TEST_ERROR_FMT(
|
||||
checkStanzaInfo(&archivePg, &backupPg), FileInvalidError, "backup info file and archive info file do not match\n"
|
||||
"archive: id = 1, version = 9.6, system-id = 6569239123849665679\n"
|
||||
"backup : id = 2, version = 9.6, system-id = 6569239123849665679\n"
|
||||
"HINT: this may be a symptom of repository corruption!");
|
||||
|
||||
// checkStanzaInfoPg
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
argList = strLstNew();
|
||||
strLstAddZ(argList, "--no-online");
|
||||
strLstAdd(argList, stanzaOpt);
|
||||
strLstAdd(argList, strNewFmt("--pg1-path=%s/%s", testPath(), strPtr(stanza)));
|
||||
strLstAdd(argList, strNewFmt("--repo1-path=%s/repo", testPath()));
|
||||
harnessCfgLoad(cfgCmdCheck, argList);
|
||||
strLstAddZ(argList, "--repo1-cipher-type=aes-256-cbc");
|
||||
setenv("PGBACKREST_REPO1_CIPHER_PASS", "12345678", true);
|
||||
harnessCfgLoad(cfgCmdStanzaCreate, argList);
|
||||
|
||||
TEST_RESULT_VOID(checkDbConfig(PG_VERSION_92, 1, PG_VERSION_92, pg1Path), "valid db config");
|
||||
// Create pg_control
|
||||
storagePutNP(
|
||||
storageNewWriteNP(storageTest, strNewFmt("%s/" PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL, strPtr(stanza))),
|
||||
pgControlTestToBuffer((PgControl){.version = PG_VERSION_96, .systemId = 6569239123849665679}));
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
// Create info files
|
||||
TEST_RESULT_VOID(cmdStanzaCreate(), "stanza create - encryption");
|
||||
|
||||
// Version mismatch
|
||||
TEST_ERROR_FMT(
|
||||
checkDbConfig(PG_VERSION_92, 1, PG_VERSION_94, pg1Path),
|
||||
DbMismatchError, "version '%s' and path '%s' queried from cluster do not match version '%s' and '%s'"
|
||||
" read from '%s/" PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL "'\n"
|
||||
"HINT: the pg1-path and pg1-port settings likely reference different clusters.",
|
||||
strPtr(pgVersionToStr(PG_VERSION_94)), strPtr(pg1Path), strPtr(pgVersionToStr(PG_VERSION_92)), strPtr(pg1Path),
|
||||
strPtr(pg1Path));
|
||||
checkStanzaInfoPg(storageRepo(), PG_VERSION_94, 6569239123849665679, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass)), FileInvalidError,
|
||||
"backup and archive info files exist but do not match the database\n"
|
||||
"HINT: is this the correct stanza?\n"
|
||||
"HINT: did an error occur during stanza-upgrade?");
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
// SystemId mismatch
|
||||
TEST_ERROR_FMT(
|
||||
checkDbConfig(PG_VERSION_92, 1, PG_VERSION_92, strNew("bogus/path")),
|
||||
DbMismatchError, "version '%s' and path '%s' queried from cluster do not match version '%s' and '%s'"
|
||||
" read from '%s/" PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL "'\n"
|
||||
"HINT: the pg1-path and pg1-port settings likely reference different clusters.",
|
||||
strPtr(pgVersionToStr(PG_VERSION_92)), "bogus/path", strPtr(pgVersionToStr(PG_VERSION_92)), strPtr(pg1Path),
|
||||
strPtr(pg1Path));
|
||||
checkStanzaInfoPg(storageRepo(), PG_VERSION_96, 6569239123849665699, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass)), FileInvalidError,
|
||||
"backup and archive info files exist but do not match the database\n"
|
||||
"HINT: is this the correct stanza?\n"
|
||||
"HINT: did an error occur during stanza-upgrade?");
|
||||
}
|
||||
|
||||
FUNCTION_HARNESS_RESULT_VOID();
|
||||
|
@ -34,7 +34,7 @@ testRun(void)
|
||||
strLstAdd(argListBase, strNewFmt("--repo1-path=%s/repo", testPath()));
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("cmdStanzaCreate(), infoValidate()"))
|
||||
if (testBegin("cmdStanzaCreate(), checkStanzaInfo()"))
|
||||
{
|
||||
// Load Parameters
|
||||
StringList *argList = strLstDup(argListBase);
|
||||
@ -231,7 +231,7 @@ testRun(void)
|
||||
cmdStanzaCreate(), FileMissingError, "archive.info exists but backup.info is missing\n"
|
||||
"HINT: this may be a symptom of repository corruption!");
|
||||
|
||||
// infoValidate()
|
||||
// checkStanzaInfo() - already checked in checkTest so just a sanity check here
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// Create a corrupted backup file - db id
|
||||
contentBackup = strNew
|
||||
@ -250,7 +250,7 @@ testRun(void)
|
||||
TEST_RESULT_VOID(
|
||||
storagePutNP(
|
||||
storageNewWriteNP(storageTest, backupInfoFileName), harnessInfoChecksum(contentBackup)),
|
||||
"put back info to file - bad db-id");
|
||||
"put backup info to file - bad db-id");
|
||||
|
||||
TEST_ERROR_FMT(
|
||||
cmdStanzaCreate(), FileInvalidError, "backup info file and archive info file do not match\n"
|
||||
@ -258,57 +258,12 @@ testRun(void)
|
||||
"backup : id = 2, version = 9.6, system-id = 6569239123849665679\n"
|
||||
"HINT: this may be a symptom of repository corruption!");
|
||||
|
||||
// Create a corrupted backup file - system id
|
||||
contentBackup = strNew
|
||||
(
|
||||
"[db]\n"
|
||||
"db-catalog-version=201608131\n"
|
||||
"db-control-version=960\n"
|
||||
"db-id=1\n"
|
||||
"db-system-id=6569239123849665999\n"
|
||||
"db-version=\"9.6\"\n"
|
||||
"\n"
|
||||
"[db:history]\n"
|
||||
"1={\"db-catalog-version\":201608131,\"db-control-version\":960,\"db-system-id\":6569239123849665999,"
|
||||
"\"db-version\":\"9.6\"}\n"
|
||||
);
|
||||
TEST_RESULT_VOID(
|
||||
storagePutNP(
|
||||
storageNewWriteNP(storageTest, backupInfoFileName), harnessInfoChecksum(contentBackup)),
|
||||
"put back info to file - bad system-id");
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// Copy files may or may not exist - remove
|
||||
storageRemoveNP(storageTest, strNewFmt("%s" INFO_COPY_EXT, strPtr(archiveInfoFileName)));
|
||||
storageRemoveNP(storageTest, strNewFmt("%s" INFO_COPY_EXT, strPtr(backupInfoFileName)));
|
||||
|
||||
TEST_ERROR_FMT(
|
||||
cmdStanzaCreate(), FileInvalidError, "backup info file and archive info file do not match\n"
|
||||
"archive: id = 1, version = 9.6, system-id = 6569239123849665679\n"
|
||||
"backup : id = 1, version = 9.6, system-id = 6569239123849665999\n"
|
||||
"HINT: this may be a symptom of repository corruption!");
|
||||
|
||||
// Create a corrupted backup file - system id and version
|
||||
contentBackup = strNew
|
||||
(
|
||||
"[db]\n"
|
||||
"db-catalog-version=201608131\n"
|
||||
"db-control-version=960\n"
|
||||
"db-id=1\n"
|
||||
"db-system-id=6569239123849665999\n"
|
||||
"db-version=\"9.5\"\n"
|
||||
"\n"
|
||||
"[db:history]\n"
|
||||
"1={\"db-catalog-version\":201608131,\"db-control-version\":960,\"db-system-id\":6569239123849665999,"
|
||||
"\"db-version\":\"9.5\"}\n"
|
||||
);
|
||||
TEST_RESULT_VOID(
|
||||
storagePutNP(
|
||||
storageNewWriteNP(storageTest, backupInfoFileName), harnessInfoChecksum(contentBackup)),
|
||||
"put back info to file - bad system-id and version");
|
||||
|
||||
TEST_ERROR_FMT(
|
||||
cmdStanzaCreate(), FileInvalidError, "backup info file and archive info file do not match\n"
|
||||
"archive: id = 1, version = 9.6, system-id = 6569239123849665679\n"
|
||||
"backup : id = 1, version = 9.5, system-id = 6569239123849665999\n"
|
||||
"HINT: this may be a symptom of repository corruption!");
|
||||
|
||||
// Create a corrupted backup file - version
|
||||
// Create an archive.info file and backup.info files that match but do not match the current database version
|
||||
contentBackup = strNew
|
||||
(
|
||||
"[db]\n"
|
||||
@ -325,20 +280,8 @@ testRun(void)
|
||||
TEST_RESULT_VOID(
|
||||
storagePutNP(
|
||||
storageNewWriteNP(storageTest, backupInfoFileName), harnessInfoChecksum(contentBackup)),
|
||||
"put back info to file - bad version");
|
||||
"put backup info to file");
|
||||
|
||||
TEST_ERROR_FMT(
|
||||
cmdStanzaCreate(), FileInvalidError, "backup info file and archive info file do not match\n"
|
||||
"archive: id = 1, version = 9.6, system-id = 6569239123849665679\n"
|
||||
"backup : id = 1, version = 9.5, system-id = 6569239123849665679\n"
|
||||
"HINT: this may be a symptom of repository corruption!");
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// Copy files may or may not exist - remove
|
||||
storageRemoveNP(storageTest, strNewFmt("%s" INFO_COPY_EXT, strPtr(archiveInfoFileName)));
|
||||
storageRemoveNP(storageTest, strNewFmt("%s" INFO_COPY_EXT, strPtr(backupInfoFileName)));
|
||||
|
||||
// Create an archive.info file that matches the backup.info file but does not match the current database version
|
||||
contentArchive = strNew
|
||||
(
|
||||
"[db]\n"
|
||||
@ -355,7 +298,7 @@ testRun(void)
|
||||
"put archive info file");
|
||||
|
||||
TEST_ERROR_FMT(
|
||||
cmdStanzaCreate(), FileInvalidError, "backup and archive info files already exist but do not match the database\n"
|
||||
cmdStanzaCreate(), FileInvalidError, "backup and archive info files exist but do not match the database\n"
|
||||
"HINT: is this the correct stanza?\n"
|
||||
"HINT: did an error occur during stanza-upgrade?");
|
||||
|
||||
@ -391,10 +334,10 @@ testRun(void)
|
||||
TEST_RESULT_VOID(
|
||||
storagePutNP(
|
||||
storageNewWriteNP(storageTest, backupInfoFileName), harnessInfoChecksum(contentBackup)),
|
||||
"put back info to file");
|
||||
"put backup info to file");
|
||||
|
||||
TEST_ERROR_FMT(
|
||||
cmdStanzaCreate(), FileInvalidError, "backup and archive info files already exist but do not match the database\n"
|
||||
cmdStanzaCreate(), FileInvalidError, "backup and archive info files exist but do not match the database\n"
|
||||
"HINT: is this the correct stanza?\n"
|
||||
"HINT: did an error occur during stanza-upgrade?");
|
||||
|
||||
@ -449,7 +392,7 @@ testRun(void)
|
||||
|
||||
harnessPqScriptSet((HarnessPq [])
|
||||
{
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", strPtr(pg1Path), false),
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", strPtr(pg1Path), false, NULL, NULL),
|
||||
HRNPQ_MACRO_CLOSE(1),
|
||||
HRNPQ_MACRO_DONE()
|
||||
});
|
||||
@ -460,7 +403,7 @@ testRun(void)
|
||||
|
||||
harnessPqScriptSet((HarnessPq [])
|
||||
{
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", strPtr(pg1Path), false),
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", strPtr(pg1Path), false, NULL, NULL),
|
||||
HRNPQ_MACRO_CLOSE(1),
|
||||
HRNPQ_MACRO_DONE()
|
||||
});
|
||||
@ -477,7 +420,7 @@ testRun(void)
|
||||
|
||||
harnessPqScriptSet((HarnessPq [])
|
||||
{
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", strPtr(pg1Path), false),
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", strPtr(pg1Path), false, NULL, NULL),
|
||||
HRNPQ_MACRO_CLOSE(1),
|
||||
HRNPQ_MACRO_DONE()
|
||||
});
|
||||
@ -498,7 +441,7 @@ testRun(void)
|
||||
|
||||
harnessPqScriptSet((HarnessPq [])
|
||||
{
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", strPtr(strNewFmt("%s/pg2", testPath())), false),
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", strPtr(strNewFmt("%s/pg2", testPath())), false, NULL, NULL),
|
||||
HRNPQ_MACRO_CLOSE(1),
|
||||
HRNPQ_MACRO_DONE()
|
||||
});
|
||||
@ -532,8 +475,8 @@ testRun(void)
|
||||
|
||||
harnessPqScriptSet((HarnessPq [])
|
||||
{
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", testPath(), true),
|
||||
HRNPQ_MACRO_OPEN_92(2, "dbname='postgres' port=5434", strPtr(pg1Path), false),
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", testPath(), true, NULL, NULL),
|
||||
HRNPQ_MACRO_OPEN_92(2, "dbname='postgres' port=5434", strPtr(pg1Path), false, NULL, NULL),
|
||||
HRNPQ_MACRO_CLOSE(2),
|
||||
HRNPQ_MACRO_CLOSE(1),
|
||||
HRNPQ_MACRO_DONE()
|
||||
|
@ -43,12 +43,12 @@ testRun(void)
|
||||
{
|
||||
HRNPQ_MACRO_OPEN(1, "dbname='postgres' port=5432"),
|
||||
HRNPQ_MACRO_SET_SEARCH_PATH(1),
|
||||
HRNPQ_MACRO_VALIDATE_QUERY(1, PG_VERSION_84, "/pgdata"),
|
||||
HRNPQ_MACRO_VALIDATE_QUERY(1, PG_VERSION_84, "/pgdata", NULL, NULL),
|
||||
HRNPQ_MACRO_CLOSE(1),
|
||||
|
||||
HRNPQ_MACRO_OPEN(1, "dbname='postgres' port=5432"),
|
||||
HRNPQ_MACRO_SET_SEARCH_PATH(1),
|
||||
HRNPQ_MACRO_VALIDATE_QUERY(1, PG_VERSION_84, "/pgdata"),
|
||||
HRNPQ_MACRO_VALIDATE_QUERY(1, PG_VERSION_84, "/pgdata", NULL, NULL),
|
||||
HRNPQ_MACRO_WAL_SWITCH(1, "xlog", "000000030000000200000003"),
|
||||
HRNPQ_MACRO_CLOSE(1),
|
||||
|
||||
@ -128,7 +128,7 @@ testRun(void)
|
||||
{
|
||||
HRNPQ_MACRO_OPEN(1, "dbname='postgres' port=5432"),
|
||||
HRNPQ_MACRO_SET_SEARCH_PATH(1),
|
||||
HRNPQ_MACRO_VALIDATE_QUERY(1, PG_VERSION_94, "/pgdata"),
|
||||
HRNPQ_MACRO_VALIDATE_QUERY(1, PG_VERSION_94, "/pgdata", NULL, NULL),
|
||||
HRNPQ_MACRO_SET_APPLICATION_NAME(1),
|
||||
HRNPQ_MACRO_IS_STANDBY_QUERY(1, true),
|
||||
HRNPQ_MACRO_CLOSE(1),
|
||||
@ -141,7 +141,7 @@ testRun(void)
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
harnessPqScriptSet((HarnessPq [])
|
||||
{
|
||||
HRNPQ_MACRO_OPEN_84(1, "dbname='postgres' port=5432", "/pgdata"),
|
||||
HRNPQ_MACRO_OPEN_84(1, "dbname='postgres' port=5432", "/pgdata", NULL, NULL),
|
||||
HRNPQ_MACRO_CLOSE(1),
|
||||
HRNPQ_MACRO_DONE()
|
||||
});
|
||||
@ -169,8 +169,8 @@ testRun(void)
|
||||
|
||||
harnessPqScriptSet((HarnessPq [])
|
||||
{
|
||||
HRNPQ_MACRO_OPEN_84(1, "dbname='postgres' port=5432", "/pgdata"),
|
||||
HRNPQ_MACRO_OPEN_84(8, "dbname='postgres' port=5433", "/pgdata"),
|
||||
HRNPQ_MACRO_OPEN_84(1, "dbname='postgres' port=5432", "/pgdata", NULL, NULL),
|
||||
HRNPQ_MACRO_OPEN_84(8, "dbname='postgres' port=5433", "/pgdata", NULL, NULL),
|
||||
|
||||
HRNPQ_MACRO_CLOSE(1),
|
||||
HRNPQ_MACRO_CLOSE(8),
|
||||
@ -184,8 +184,8 @@ testRun(void)
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
harnessPqScriptSet((HarnessPq [])
|
||||
{
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", "/pgdata", true),
|
||||
HRNPQ_MACRO_OPEN_92(8, "dbname='postgres' port=5433", "/pgdata", true),
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", "/pgdata", true, NULL, NULL),
|
||||
HRNPQ_MACRO_OPEN_92(8, "dbname='postgres' port=5433", "/pgdata", true, NULL, NULL),
|
||||
|
||||
HRNPQ_MACRO_CLOSE(8),
|
||||
HRNPQ_MACRO_CLOSE(1),
|
||||
@ -199,8 +199,8 @@ testRun(void)
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
harnessPqScriptSet((HarnessPq [])
|
||||
{
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", "/pgdata", true),
|
||||
HRNPQ_MACRO_OPEN_92(8, "dbname='postgres' port=5433", "/pgdata", true),
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", "/pgdata", true, NULL, NULL),
|
||||
HRNPQ_MACRO_OPEN_92(8, "dbname='postgres' port=5433", "/pgdata", true, NULL, NULL),
|
||||
|
||||
HRNPQ_MACRO_CLOSE(8),
|
||||
HRNPQ_MACRO_CLOSE(1),
|
||||
@ -234,7 +234,7 @@ testRun(void)
|
||||
|
||||
harnessPqScriptSet((HarnessPq [])
|
||||
{
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", "/pgdata", true),
|
||||
HRNPQ_MACRO_OPEN_92(1, "dbname='postgres' port=5432", "/pgdata", true, NULL, NULL),
|
||||
|
||||
// pg-4 error
|
||||
{.session = 4, .function = HRNPQ_CONNECTDB, .param = "[\"dbname='postgres' port=5433\"]"},
|
||||
@ -242,7 +242,7 @@ testRun(void)
|
||||
{.session = 4, .function = HRNPQ_ERRORMESSAGE, .resultZ = "error"},
|
||||
{.session = 4, .function = HRNPQ_FINISH},
|
||||
|
||||
HRNPQ_MACRO_OPEN_92(8, "dbname='postgres' port=5434", "/pgdata", false),
|
||||
HRNPQ_MACRO_OPEN_92(8, "dbname='postgres' port=5434", "/pgdata", false, NULL, NULL),
|
||||
|
||||
HRNPQ_MACRO_CREATE_RESTORE_POINT(8, "2/3"),
|
||||
HRNPQ_MACRO_WAL_SWITCH(8, "xlog", "000000010000000200000003"),
|
||||
@ -261,6 +261,8 @@ testRun(void)
|
||||
|
||||
TEST_RESULT_INT(result.primaryId, 8, " check primary id");
|
||||
TEST_RESULT_BOOL(result.primary != NULL, true, " check primary");
|
||||
TEST_RESULT_STR(strPtr(dbArchiveMode(result.primary)), "on", " dbArchiveMode");
|
||||
TEST_RESULT_STR(strPtr(dbArchiveCommand(result.primary)), PROJECT_BIN, " dbArchiveCommand");
|
||||
TEST_RESULT_STR(strPtr(dbWalSwitch(result.primary)), "000000010000000200000003", " wal switch");
|
||||
TEST_RESULT_INT(result.standbyId, 1, " check standby id");
|
||||
TEST_RESULT_BOOL(result.standby != NULL, true, " check standby");
|
||||
|
Loading…
Reference in New Issue
Block a user