Allow external recovery_config_directory

If required, recovery.conf can now be located outside of the data directory.
Server needs read/write permissions on this directory.
This commit is contained in:
Simon Riggs 2013-03-27 11:45:42 +00:00
parent f7f210b5c4
commit bc5334d867
7 changed files with 75 additions and 7 deletions

View File

@ -330,6 +330,23 @@ include 'filename'
</listitem>
</varlistentry>
<variablelist>
<varlistentry id="guc-recovery-config-directory" xreflabel="recovery_config_directory">
<term><varname>recovery_config_directory</varname> (<type>string</type>)</term>
<indexterm>
<primary><varname>recovery_config_directory</> configuration parameter</primary>
</indexterm>
<listitem>
<para>
Specifies the directory to use for the recovery.conf file. Note
the server requires read and write permission on this directory
because the file will be renamed to recovery.done at the end of
recovery.
This parameter can only be set at server start.
</para>
</listitem>
</varlistentry>
<varlistentry id="guc-config-file" xreflabel="config_file">
<term><varname>config_file</varname> (<type>string</type>)</term>
<indexterm>

View File

@ -62,6 +62,7 @@
extern bool bootstrap_data_checksums;
char recoveryConfPath[MAXPGPATH];
/* File path names (all relative to $PGDATA) */
#define RECOVERY_COMMAND_FILE "recovery.conf"
#define RECOVERY_COMMAND_DONE "recovery.done"
@ -4163,7 +4164,8 @@ readRecoveryCommandFile(void)
*head = NULL,
*tail = NULL;
fd = AllocateFile(RECOVERY_COMMAND_FILE, "r");
snprintf(recoveryConfPath, MAXPGPATH, "%s/%s", RecoveryConfDir, RECOVERY_COMMAND_FILE);
fd = AllocateFile(recoveryConfPath, "r");
if (fd == NULL)
{
if (errno == ENOENT)
@ -4171,7 +4173,7 @@ readRecoveryCommandFile(void)
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not open recovery command file \"%s\": %m",
RECOVERY_COMMAND_FILE)));
recoveryConfPath)));
}
/*
@ -4345,7 +4347,7 @@ readRecoveryCommandFile(void)
if (PrimaryConnInfo == NULL && recoveryRestoreCommand == NULL)
ereport(WARNING,
(errmsg("recovery command file \"%s\" specified neither primary_conninfo nor restore_command",
RECOVERY_COMMAND_FILE),
recoveryConfPath),
errhint("The database server will regularly poll the pg_xlog subdirectory to check for files placed there.")));
}
else
@ -4353,7 +4355,7 @@ readRecoveryCommandFile(void)
if (recoveryRestoreCommand == NULL)
ereport(FATAL,
(errmsg("recovery command file \"%s\" must specify restore_command when standby mode is not enabled",
RECOVERY_COMMAND_FILE)));
recoveryConfPath)));
}
/* Enable fetching from archive recovery area */
@ -4395,6 +4397,7 @@ static void
exitArchiveRecovery(TimeLineID endTLI, XLogSegNo endLogSegNo)
{
char recoveryPath[MAXPGPATH];
char recoveryDonePath[MAXPGPATH];
char xlogpath[MAXPGPATH];
/*
@ -4459,12 +4462,13 @@ exitArchiveRecovery(TimeLineID endTLI, XLogSegNo endLogSegNo)
* Rename the config file out of the way, so that we don't accidentally
* re-enter archive recovery mode in a subsequent crash.
*/
unlink(RECOVERY_COMMAND_DONE);
if (rename(RECOVERY_COMMAND_FILE, RECOVERY_COMMAND_DONE) != 0)
snprintf(recoveryDonePath, MAXPGPATH, "%s/%s", RecoveryConfDir, RECOVERY_COMMAND_DONE);
unlink(recoveryDonePath);
if (rename(recoveryConfPath, recoveryDonePath) != 0)
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not rename file \"%s\" to \"%s\": %m",
RECOVERY_COMMAND_FILE, RECOVERY_COMMAND_DONE)));
recoveryConfPath, recoveryDonePath)));
ereport(LOG,
(errmsg("archive recovery complete")));

View File

@ -46,6 +46,7 @@ int MyPMChildSlot;
* explicitly.
*/
char *DataDir = NULL;
char *RecoveryConfDir = NULL;
char OutputFileName[MAXPGPATH]; /* debugging output file */

View File

@ -99,6 +99,25 @@ SetDataDir(const char *dir)
DataDir = new;
}
/*
* Set recovery config directory, but make sure it's an absolute path. Use this,
* never set RecoveryConfDir directly.
*/
void
SetRecoveryConfDir(const char *dir)
{
char *new;
AssertArg(dir);
/* If presented path is relative, convert to absolute */
new = make_absolute_path(dir);
if (RecoveryConfDir)
free(RecoveryConfDir);
RecoveryConfDir = new;
}
/*
* Change working directory to DataDir. Most of the postmaster and backend
* code assumes that we are in DataDir so it can use relative paths to access

View File

@ -424,6 +424,7 @@ int temp_file_limit = -1;
int num_temp_buffers = 1024;
char *data_directory;
char *recovery_config_directory;
char *ConfigFileName;
char *HbaFileName;
char *IdentFileName;
@ -2960,6 +2961,17 @@ static struct config_string ConfigureNamesString[] =
NULL, NULL, NULL
},
{
{"recovery_config_directory", PGC_POSTMASTER, FILE_LOCATIONS,
gettext_noop("Sets the server's recovery configuration directory."),
NULL,
GUC_SUPERUSER_ONLY
},
&recovery_config_directory,
NULL,
NULL, NULL, NULL
},
{
{"config_file", PGC_POSTMASTER, FILE_LOCATIONS,
gettext_noop("Sets the server's main configuration file."),
@ -4181,6 +4193,18 @@ SelectConfigFiles(const char *userDoption, const char *progname)
*/
SetConfigOption("data_directory", DataDir, PGC_POSTMASTER, PGC_S_OVERRIDE);
/*
* If the recovery_config_directory GUC variable has been set, use that,
* otherwise use DataDir.
*
* Note: SetRecoveryConfDir will copy and absolute-ize its argument,
* so we don't have to.
*/
if (recovery_config_directory)
SetRecoveryConfDir(recovery_config_directory);
else
SetRecoveryConfDir(DataDir);
/*
* If timezone_abbreviations wasn't set in the configuration file, install
* the default value. We do it this way because we can't safely install a

View File

@ -137,6 +137,7 @@ extern bool IsBinaryUpgrade;
extern bool ExitOnAnyError;
extern PGDLLIMPORT char *DataDir;
extern PGDLLIMPORT char *RecoveryConfDir;
extern PGDLLIMPORT int NBuffers;
extern int MaxBackends;
@ -301,6 +302,7 @@ extern Oid GetCurrentRoleId(void);
extern void SetCurrentRoleId(Oid roleid, bool is_superuser);
extern void SetDataDir(const char *dir);
extern void SetRecoveryConfDir(const char *dir);
extern void ChangeToDataDir(void);
extern char *make_absolute_path(const char *path);

View File

@ -220,6 +220,7 @@ extern int temp_file_limit;
extern int num_temp_buffers;
extern char *data_directory;
extern char *recovery_config_directory;
extern char *ConfigFileName;
extern char *HbaFileName;
extern char *IdentFileName;