diff --git a/contrib/pg_archivecleanup/pg_archivecleanup.c b/contrib/pg_archivecleanup/pg_archivecleanup.c
index e97a11c..fb01da9 100644
--- a/contrib/pg_archivecleanup/pg_archivecleanup.c
+++ b/contrib/pg_archivecleanup/pg_archivecleanup.c
@@ -255,7 +255,7 @@ usage(void)
printf(" -x EXT clean up files if they have this extension\n");
printf(" -?, --help show this help, then exit\n");
printf("\n"
- "For use as archive_cleanup_command in recovery.conf when standby_mode = on:\n"
+ "For use as archive_cleanup_command in postgresql.conf when standby_mode = on:\n"
" archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVELOCATION %%r'\n"
"e.g.\n"
" archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n");
diff --git a/contrib/pg_standby/pg_standby.c b/contrib/pg_standby/pg_standby.c
index 659bd50..115c25e 100644
--- a/contrib/pg_standby/pg_standby.c
+++ b/contrib/pg_standby/pg_standby.c
@@ -531,7 +531,7 @@ usage(void)
printf(" -w MAXWAITTIME max seconds to wait for a file (0=no limit) (default=0)\n");
printf(" -?, --help show this help, then exit\n");
printf("\n"
- "Main intended use as restore_command in recovery.conf:\n"
+ "Main intended use as restore_command in postgresql.conf:\n"
" restore_command = 'pg_standby [OPTION]... ARCHIVELOCATION %%f %%p %%r'\n"
"e.g.\n"
" restore_command = 'pg_standby /mnt/server/archiverdir %%f %%p %%r'\n");
diff --git a/doc/src/sgml/backup.sgml b/doc/src/sgml/backup.sgml
index c4215be..e57d521 100644
--- a/doc/src/sgml/backup.sgml
+++ b/doc/src/sgml/backup.sgml
@@ -1002,8 +1002,16 @@ SELECT pg_stop_backup();
- Create a recovery command file recovery.conf> in the cluster
- data directory (see ). You might
+ Set up recovery parameters in postgresql.conf> (see
+ and
+ ). You can also
+ use the same parameters in recovery.conf>.
+
+
+
+
+ Create a recovery command file recovery.conf>
+ in the cluster data directory. You might
also want to temporarily modify pg_hba.conf> to prevent
ordinary users from connecting until you are sure the recovery was successful.
@@ -1031,12 +1039,11 @@ SELECT pg_stop_backup();
- The key part of all this is to set up a recovery configuration file that
- describes how you want to recover and how far the recovery should
- run. You can use recovery.conf.sample> (normally
- located in the installation's share/> directory) as a
- prototype. The one thing that you absolutely must specify in
- recovery.conf> is the restore_command>,
+ The key part of all this is to set up recovery parameters that
+ specify how you want to recover and how far the recovery should
+ run. The one thing that you absolutely must specify in
+ postgresql.conf> or recovery.conf> to
+ recover from the backup is the restore_command>,
which tells PostgreSQL> how to retrieve archived
WAL file segments. Like the archive_command>, this is
a shell command string. It can contain %f>, which is
@@ -1090,8 +1097,8 @@ restore_command = 'cp /mnt/server/archivedir/%f %p'
If you want to recover to some previous point in time (say, right before
the junior DBA dropped your main transaction table), just specify the
- required stopping point in recovery.conf>. You can specify
- the stop point, known as the recovery target>, either by
+ required stopping point in postgresql.conf> or recovery.conf>.
+ You can specify the stop point, known as the recovery target>, either by
date/time, named restore point or by completion of a specific transaction
ID. As of this writing only the date/time and named restore point options
are very usable, since there are no tools to help you identify with any
@@ -1187,9 +1194,11 @@ restore_command = 'cp /mnt/server/archivedir/%f %p'
The default behavior of recovery is to recover along the same timeline
that was current when the base backup was taken. If you wish to recover
into some child timeline (that is, you want to return to some state that
- was itself generated after a recovery attempt), you need to specify the
- target timeline ID in recovery.conf>. You cannot recover into
- timelines that branched off earlier than the base backup.
+ was itself generated after a recovery attempt), you need to set
+ to the
+ target timeline ID in postgresql.conf> or recovery.conf>.
+ You cannot recover into timelines that branched off earlier than the
+ base backup.
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index b7df8ce..3b26bb7 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2161,6 +2161,278 @@ include 'filename'
+
+ Archive Recovery
+
+
+
+ restore_command (string)
+
+ restore_command> configuration parameter
+
+
+
+ The shell command to execute to retrieve an archived segment of
+ the WAL file series. This parameter is required for archive recovery,
+ but optional for streaming replication.
+ Any %f> in the string is
+ replaced by the name of the file to retrieve from the archive,
+ and any %p> is replaced by the copy destination path name
+ on the server.
+ (The path name is relative to the current working directory,
+ i.e., the cluster's data directory.)
+ Any %r> is replaced by the name of the file containing the
+ last valid restart point. That is the earliest file that must be kept
+ to allow a restore to be restartable, so this information can be used
+ to truncate the archive to just the minimum required to support
+ restarting from the current restore. %r> is typically only
+ used by warm-standby configurations
+ (see ).
+ Write %%> to embed an actual %> character.
+
+
+ It is important for the command to return a zero exit status
+ only if it succeeds. The command will> be asked for file
+ names that are not present in the archive; it must return nonzero
+ when so asked. Examples:
+
+restore_command = 'cp /mnt/server/archivedir/%f "%p"'
+restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
+
+
+
+ This parameter can only be set in the postgresql.conf>
+ file or on the server command line. It only has effect during archive
+ recovery or in standby mode.
+
+
+
+
+
+ archive_cleanup_command (string)
+
+ archive_cleanup_command> configuration parameter
+
+
+
+ The shell command that will be executed at every restartpoint.
+ The purpose of archive_cleanup_command> is to
+ provide a mechanism for cleaning up old archived WAL files that
+ are no longer needed by the standby server.
+ Any %r> is replaced by the name of the file containing the
+ last valid restart point.
+ That is the earliest file that must be kept> to allow a
+ restore to be restartable, and so all files earlier than %r>
+ may be safely removed.
+ This information can be used to truncate the archive to just the
+ minimum required to support restart from the current restore.
+ The module
+ is often used in archive_cleanup_command> for
+ single-standby configurations, for example:
+archive_cleanup_command = 'pg_archivecleanup /mnt/server/archivedir %r'
+ Note however that if multiple standby servers are restoring from the
+ same archive directory, you will need to ensure that you do not delete
+ WAL files until they are no longer needed by any of the servers.
+ archive_cleanup_command> would typically be used in a
+ warm-standby configuration (see ).
+ Write %%> to embed an actual %> character in the
+ command.
+
+
+ If the command returns a non-zero exit status then a WARNING log
+ message will be written.
+
+
+ This parameter can only be set in the postgresql.conf>
+ file or on the server command line. It only has effect during archive
+ recovery or in standby mode.
+
+
+
+
+
+ recovery_end_command (string)
+
+ recovery_end_command> configuration parameter
+
+
+
+ The shell command that will be executed once only
+ at the end of recovery. This parameter is optional. The purpose of the
+ recovery_end_command> is to provide a mechanism for cleanup
+ following replication or recovery.
+ Any %r> is replaced by the name of the file containing the
+ last valid restart point, like in archive_cleanup_command>.
+
+
+ If the command returns a non-zero exit status then a WARNING log
+ message will be written and the database will proceed to start up
+ anyway. An exception is that if the command was terminated by a
+ signal, the database will not proceed with startup.
+
+
+ This parameter can only be set in the postgresql.conf>
+ file or on the server command line. It only has effect during archive
+ recovery or in standby mode.
+
+
+
+
+
+
+
+ Recovery Target
+
+
+
+ recovery_target_name (string)
+
+ recovery_target_name> configuration parameter
+
+
+
+ Specifies the named restore point, created with
+ pg_create_restore_point()> to which recovery will proceed.
+ At most one of recovery_target_name>,
+ recovery_target_time> or
+ recovery_target_xid> can be specified. The default
+ value is an empty string, which will recover to the end of the WAL log.
+
+
+ This parameter can only be set in the postgresql.conf>
+ file or on the server command line. It only has effect during archive
+ recovery or in standby mode.
+
+
+
+
+
+ recovery_target_time (string)
+
+ recovery_target_time> configuration parameter
+
+
+
+ Specifies the time stamp up to which recovery will proceed.
+ This parameter must be specified in the date/time format
+ (see for details).
+ At most one of recovery_target_time>,
+ recovery_target_name> or
+ recovery_target_xid> can be specified.
+ The default value is an empty string, which will recover to
+ the end of the WAL log. The precise stopping point is also
+ influenced by recovery_target_inclusive>.
+
+
+ This parameter can only be set in the postgresql.conf>
+ file or on the server command line. It only has effect during archive
+ recovery or in standby mode.
+
+
+
+
+
+ recovery_target_xid (string)
+
+ recovery_target_xid> configuration parameter
+
+
+
+ Specifies the transaction ID up to which recovery will proceed.
+ Keep in mind that while transaction IDs are assigned sequentially
+ at transaction start, transactions can complete in a different
+ numeric order. The transactions that will be recovered are
+ those that committed before (and optionally including)
+ the specified one. At most one of recovery_target_xid>,
+ recovery_target_name> or
+ recovery_target_time> can be specified.
+ The default value is an empty string, which will recover to the end of
+ the WAL log. The precise stopping point is also influenced by
+ recovery_target_inclusive>.
+
+
+ This parameter can only be set in the postgresql.conf>
+ file or on the server command line. It only has effect during archive
+ recovery or in standby mode.
+
+
+
+
+
+ recovery_target_inclusive (boolean)
+
+ recovery_target_inclusive> configuration parameter
+
+
+
+ Specifies whether we stop just after the specified recovery target
+ (on>), or just before the recovery target (off>).
+ Applies to both recovery_target_time>
+ and recovery_target_xid>, whichever one is
+ specified for this recovery. This indicates whether transactions
+ having exactly the target commit time or ID, respectively, will
+ be included in the recovery. Default is on>.
+
+
+ This parameter can only be set in the postgresql.conf>
+ file or on the server command line. It only has effect during archive
+ recovery or in standby mode.
+
+
+
+
+
+ recovery_target_timeline (string)
+
+ recovery_target_timeline> configuration parameter
+
+
+
+ Specifies recovering into a particular timeline. The default value is
+ an empty string, which will recover along the same timeline that was
+ current when the base backup was taken. Setting this to
+ latest> recovers to the latest timeline found in the archive,
+ which is useful in a standby server. Other than that you only need to
+ set this parameter in complex re-recovery situations, where you need
+ to return to a state that itself was reached after a point-in-time
+ recovery. See for discussion.
+
+
+ This parameter can only be set at server start. It only has effect
+ during archive recovery or in standby mode.
+
+
+
+
+
+ pause_at_recovery_target (boolean)
+
+ pause_at_recovery_target> configuration parameter
+
+
+
+ Specifies whether recovery should pause when the recovery target
+ is reached. The default is on>.
+ This is intended to allow queries to be executed against the
+ database to check if this recovery target is the most desirable
+ point for recovery. The paused state can be resumed by using
+ pg_xlog_replay_resume()> (See
+ ), which then
+ causes recovery to end. If this recovery target is not the
+ desired stopping point, then shutdown the server, change the
+ recovery target settings to a later target and restart to
+ continue recovery.
+
+
+ This parameter can only be set in the postgresql.conf>
+ file or on the server command line. It only has effect during archive
+ recovery or in standby mode if recovery target is set.
+
+
+
+
+
+
@@ -2380,6 +2652,93 @@ include 'filename'
+
+ standby_mode (boolean)
+
+ standby_mode> configuration parameter
+
+
+
+ Specifies whether to start the PostgreSQL> server as
+ a standby when recovery trigger file recovery.trigger> exists.
+ The default value is off>.
+ If this parameter is on>, the server will not
+ stop recovery when the end of archived WAL is reached,
+ but will keep trying to continue recovery by fetching new WAL segments
+ using restore_command> and/or by connecting to
+ the primary server as specified by the primary_conninfo>
+ setting.
+
+
+ This parameter can only be set at server start. It only has effect
+ if recovery trigger file recovery.trigger> exists.
+
+
+
+
+
+ primary_conninfo (string)
+
+ primary_conninfo> configuration parameter
+
+
+
+ Specifies a connection string to be used for the standby server
+ to connect with the primary. This string is in the format
+ accepted by the libpq PQconnectdb function,
+ described in . If any option is
+ unspecified in this string, then the corresponding environment
+ variable (see ) is checked. If the
+ environment variable is not set either, then defaults are used.
+ If this parameter is an empty string (the default), no attempt is
+ made to connect to the master.
+
+
+ The connection string should specify the host name (or address)
+ of the primary server, as well as the port number if it is not
+ the same as the standby server's default.
+ Also specify a user name corresponding to a role that has the
+ REPLICATION> and LOGIN> privileges on the
+ primary (see
+ ).
+ A password needs to be provided too, if the primary demands password
+ authentication. It can be provided in the
+ primary_conninfo string, or in a separate
+ ~/.pgpass> file on the standby server (use
+ replication> as the database name).
+ Do not specify a database name in the
+ primary_conninfo string.
+
+
+ This parameter can only be set in the postgresql.conf>
+ file or on the server command line. It only has effect in standby mode.
+
+
+ If this parameter is changed while replication is in progress,
+ the standby terminates replication, and then tries to restart
+ replication with new setting.
+
+
+
+
+
+ trigger_file (string)
+
+ trigger_file> configuration parameter
+
+
+
+ Specifies a trigger file whose presence ends recovery in the
+ standby. Even if this value is not set, you can still promote
+ the standby using pg_ctl promote>.
+
+
+ This parameter can only be set in the postgresql.conf>
+ file or on the server command line. It only has effect in standby mode.
+
+
+
+
hot_standby (boolean)
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 35c7f75..48cfe9e 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -14670,7 +14670,7 @@ postgres=# select pg_start_backup('label_goes_here');
pg_create_restore_point> creates a named transaction log
record that can be used as recovery target, and returns the corresponding
transaction log location. The given name can then be used with
- to specify the point up to which
+ to specify the point up to which
recovery will proceed. Avoid creating multiple restore points with the
same name, since recovery will stop at the first one whose name matches
the recovery target.
diff --git a/doc/src/sgml/high-availability.sgml b/doc/src/sgml/high-availability.sgml
index c8f6fa8..21e1ee0 100644
--- a/doc/src/sgml/high-availability.sgml
+++ b/doc/src/sgml/high-availability.sgml
@@ -591,7 +591,7 @@ protocol to make nodes agree on a serializable transactional order.
In standby mode, the server continuously applies WAL received from the
master server. The standby server can read WAL from a WAL archive
- (see ) or directly from the master
+ (see ) or directly from the master
over a TCP connection (streaming replication). The standby server will
also attempt to restore any WAL found in the standby cluster's
pg_xlog> directory. That typically happens after a server
@@ -658,13 +658,14 @@ protocol to make nodes agree on a serializable transactional order.
To set up the standby server, restore the base backup taken from primary
server (see ). Create a recovery
- command file recovery.conf> in the standby's cluster data
- directory, and turn on standby_mode>. Set
+ command file recovery.done> in the standby's cluster data
+ directory. Turn on standby_mode> and set
restore_command> to a simple command to copy files from
the WAL archive. If you plan to have multiple standby servers for high
availability purposes, set recovery_target_timeline> to
latest>, to make the standby server follow the timeline change
- that occurs at failover to another standby.
+ that occurs at failover to another standby. Parameters can be set up
+ in either postgresql.conf> or recovery.conf>.
@@ -695,7 +696,7 @@ protocol to make nodes agree on a serializable transactional order.
If you're using a WAL archive, its size can be minimized using the parameter to remove files that are no
+ linkend="guc-archive-cleanup-command"> parameter to remove files that are no
longer required by the standby server.
The pg_archivecleanup> utility is designed specifically to
be used with archive_cleanup_command> in typical single-standby
@@ -706,7 +707,7 @@ protocol to make nodes agree on a serializable transactional order.
- A simple example of a recovery.conf> is:
+ A simple example of standby settings is:
standby_mode = 'on'
primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass'
@@ -763,8 +764,8 @@ archive_cleanup_command = 'pg_archivecleanup /path/to/archive %r'
To use streaming replication, set up a file-based log-shipping standby
server as described in . The step that
turns a file-based log-shipping standby into streaming replication
- standby is setting primary_conninfo> setting in the
- recovery.conf> file to point to the primary server. Set
+ standby is setting primary_conninfo> to
+ point to the primary server. Set
and authentication options
(see pg_hba.conf>) on the primary so that the standby server
can connect to the replication> pseudo-database on the primary
@@ -824,15 +825,14 @@ host replication foo 192.168.1.100/32 md5
The host name and port number of the primary, connection user name,
- and password are specified in the recovery.conf> file.
+ and password are specified in primary_conninfo>.
The password can also be set in the ~/.pgpass> file on the
standby (specify replication> in the database>
field).
For example, if the primary is running on host IP 192.168.1.50>,
port 5432, the account name for replication is
foo>, and the password is foopass>, the administrator
- can add the following line to the recovery.conf> file on the
- standby:
+ can set primary_conninfo> on the standby like this:
# The standby connects to the primary that is running on host 192.168.1.50
@@ -1212,8 +1212,8 @@ primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass'
To trigger failover of a log-shipping standby server,
run pg_ctl promote> or create a trigger
- file with the file name and path specified by the trigger_file>
- setting in recovery.conf>. If you're planning to use
+ file with the file name and path specified by the trigger_file>.
+ If you're planning to use
pg_ctl promote> to fail over, trigger_file> is
not required. If you're setting up the reporting servers that are
only used to offload read-only queries from the primary, not for high
@@ -1258,8 +1258,7 @@ primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass'
The magic that makes the two loosely coupled servers work together is
simply a restore_command> used on the standby that,
when asked for the next WAL file, waits for it to become available from
- the primary. The restore_command> is specified in the
- recovery.conf> file on the standby server. Normal recovery
+ the primary. Normal recovery
processing would request a file from the WAL archive, reporting failure
if the file was unavailable. For standby processing it is normal for
the next WAL file to be unavailable, so the standby must wait for
@@ -1347,9 +1346,10 @@ if (!triggered)
Begin recovery on the standby server from the local WAL
- archive, using a recovery.conf> that specifies a
+ archive, create a recovery.conf> file, then specify a
restore_command> that waits as described
- previously (see ).
+ previously (see ) in either
+ postgresql.conf> or recovery.conf>.
diff --git a/doc/src/sgml/pgarchivecleanup.sgml b/doc/src/sgml/pgarchivecleanup.sgml
index 932914b..2984da4 100644
--- a/doc/src/sgml/pgarchivecleanup.sgml
+++ b/doc/src/sgml/pgarchivecleanup.sgml
@@ -38,8 +38,8 @@
To configure a standby
- server to use pg_archivecleanup>, put this into its
- recovery.conf configuration file:
+ server to use pg_archivecleanup>, specify
+ like this:
archive_cleanup_command = 'pg_archivecleanup archivelocation> %r'
@@ -47,7 +47,7 @@ archive_cleanup_command = 'pg_archivecleanup archivelocation> %r'
files should be removed.
- When used within , all WAL files
+ When used within archive_cleanup_command>, all WAL files
logically preceding the value of the %r> argument will be removed
from archivelocation>. This minimizes the number of files
that need to be retained, while preserving crash-restart capability. Use of
diff --git a/doc/src/sgml/pgstandby.sgml b/doc/src/sgml/pgstandby.sgml
index ca2b5c0..15097ca 100644
--- a/doc/src/sgml/pgstandby.sgml
+++ b/doc/src/sgml/pgstandby.sgml
@@ -46,8 +46,8 @@
To configure a standby
- server to use pg_standby>, put this into its
- recovery.conf configuration file:
+ server to use pg_standby>, specify
+ like this:
restore_command = 'pg_standby archiveDir> %f %p %r'
diff --git a/doc/src/sgml/recovery-config.sgml b/doc/src/sgml/recovery-config.sgml
index 7e39c0d..52b75b7 100644
--- a/doc/src/sgml/recovery-config.sgml
+++ b/doc/src/sgml/recovery-config.sgml
@@ -42,34 +42,8 @@
- The shell command to execute to retrieve an archived segment of
- the WAL file series. This parameter is required for archive recovery,
- but optional for streaming replication.
- Any %f> in the string is
- replaced by the name of the file to retrieve from the archive,
- and any %p> is replaced by the copy destination path name
- on the server.
- (The path name is relative to the current working directory,
- i.e., the cluster's data directory.)
- Any %r> is replaced by the name of the file containing the
- last valid restart point. That is the earliest file that must be kept
- to allow a restore to be restartable, so this information can be used
- to truncate the archive to just the minimum required to support
- restarting from the current restore. %r> is typically only
- used by warm-standby configurations
- (see ).
- Write %%> to embed an actual %> character.
-
-
-
- It is important for the command to return a zero exit status
- only if it succeeds. The command will> be asked for file
- names that are not present in the archive; it must return nonzero
- when so asked. Examples:
-
-restore_command = 'cp /mnt/server/archivedir/%f "%p"'
-restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
-
+ Refer to for detailed
+ description.
@@ -81,33 +55,8 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
- This optional parameter specifies a shell command that will be executed
- at every restartpoint. The purpose of
- archive_cleanup_command> is to provide a mechanism for
- cleaning up old archived WAL files that are no longer needed by the
- standby server.
- Any %r> is replaced by the name of the file containing the
- last valid restart point.
- That is the earliest file that must be kept> to allow a
- restore to be restartable, and so all files earlier than %r>
- may be safely removed.
- This information can be used to truncate the archive to just the
- minimum required to support restart from the current restore.
- The module
- is often used in archive_cleanup_command> for
- single-standby configurations, for example:
-archive_cleanup_command = 'pg_archivecleanup /mnt/server/archivedir %r'
- Note however that if multiple standby servers are restoring from the
- same archive directory, you will need to ensure that you do not delete
- WAL files until they are no longer needed by any of the servers.
- archive_cleanup_command> would typically be used in a
- warm-standby configuration (see ).
- Write %%> to embed an actual %> character in the
- command.
-
-
- If the command returns a non-zero exit status then a WARNING log
- message will be written.
+ Refer to for detailed
+ description.
@@ -119,18 +68,8 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
- This parameter specifies a shell command that will be executed once only
- at the end of recovery. This parameter is optional. The purpose of the
- recovery_end_command> is to provide a mechanism for cleanup
- following replication or recovery.
- Any %r> is replaced by the name of the file containing the
- last valid restart point, like in .
-
-
- If the command returns a non-zero exit status then a WARNING log
- message will be written and the database will proceed to start up
- anyway. An exception is that if the command was terminated by a
- signal, the database will not proceed with startup.
+ Refer to for detailed
+ description.
@@ -153,12 +92,8 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
- This parameter specifies the named restore point, created with
- pg_create_restore_point()> to which recovery will proceed.
- At most one of recovery_target_name>,
- or
- can be specified. The default is to
- recover to the end of the WAL log.
+ Refer to for detailed
+ description.
@@ -172,14 +107,8 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
- This parameter specifies the time stamp up to which recovery
- will proceed.
- At most one of recovery_target_time>,
- or
- can be specified.
- The default is to recover to the end of the WAL log.
- The precise stopping point is also influenced by
- .
+ Refer to for detailed
+ description.
@@ -191,18 +120,7 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
- This parameter specifies the transaction ID up to which recovery
- will proceed. Keep in mind
- that while transaction IDs are assigned sequentially at transaction
- start, transactions can complete in a different numeric order.
- The transactions that will be recovered are those that committed
- before (and optionally including) the specified one.
- At most one of recovery_target_xid>,
- or
- can be specified.
- The default is to recover to the end of the WAL log.
- The precise stopping point is also influenced by
- .
+ Refer to for detailed description.
@@ -217,14 +135,8 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
- Specifies whether we stop just after the specified recovery target
- (true), or just before the recovery target
- (false).
- Applies to both
- and , whichever one is
- specified for this recovery. This indicates whether transactions
- having exactly the target commit time or ID, respectively, will
- be included in the recovery. Default is true>.
+ Refer to for detailed
+ description.
@@ -239,14 +151,7 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
- Specifies recovering into a particular timeline. The default is
- to recover along the same timeline that was current when the
- base backup was taken. Setting this to latest> recovers
- to the latest timeline found in the archive, which is useful in
- a standby server. Other than that you only need to set this parameter
- in complex re-recovery situations, where you need to return to
- a state that itself was reached after a point-in-time recovery.
- See for discussion.
+ Refer to for more details.
@@ -261,21 +166,7 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
- Specifies whether recovery should pause when the recovery target
- is reached. The default is true.
- This is intended to allow queries to be executed against the
- database to check if this recovery target is the most desirable
- point for recovery. The paused state can be resumed by using
- pg_xlog_replay_resume()> (See
- ), which then
- causes recovery to end. If this recovery target is not the
- desired stopping point, then shutdown the server, change the
- recovery target settings to a later target and restart to
- continue recovery.
-
-
- This setting has no effect if is not
- enabled, or if no recovery target is set.
+ Refer to for more details.
@@ -295,13 +186,7 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
- Specifies whether to start the PostgreSQL> server as
- a standby. If this parameter is on>, the server will
- not stop recovery when the end of archived WAL is reached, but
- will keep trying to continue recovery by fetching new WAL segments
- using restore_command>
- and/or by connecting to the primary server as specified by the
- primary_conninfo> setting.
+ Refer to for more details.
@@ -312,32 +197,7 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
- Specifies a connection string to be used for the standby server
- to connect with the primary. This string is in the format
- accepted by the libpq PQconnectdb function,
- described in . If any option is
- unspecified in this string, then the corresponding environment
- variable (see ) is checked. If the
- environment variable is not set either, then
- defaults are used.
-
-
- The connection string should specify the host name (or address)
- of the primary server, as well as the port number if it is not
- the same as the standby server's default.
- Also specify a user name corresponding to a suitably-privileged role
- on the primary (see
- ).
- A password needs to be provided too, if the primary demands password
- authentication. It can be provided in the
- primary_conninfo string, or in a separate
- ~/.pgpass> file on the standby server (use
- replication> as the database name).
- Do not specify a database name in the
- primary_conninfo string.
-
-
- This setting has no effect if standby_mode> is off>.
+ Refer to for more details.
@@ -348,10 +208,7 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
- Specifies a trigger file whose presence ends recovery in the
- standby. Even if this value is not set, you can still promote
- the standby using pg_ctl promote>.
- This setting has no effect if standby_mode> is off>.
+ Refer to for more details.
diff --git a/doc/src/sgml/release-9.1.sgml b/doc/src/sgml/release-9.1.sgml
index 1143fdf..36546bb 100644
--- a/doc/src/sgml/release-9.1.sgml
+++ b/doc/src/sgml/release-9.1.sgml
@@ -3957,7 +3957,7 @@
Add recovery.conf> setting pause_at_recovery_target>
+ linkend="guc-pause-at-recovery-target">pause_at_recovery_target>
to pause recovery at target (Simon Riggs)
@@ -3977,7 +3977,7 @@
These named restore points can be specified as recovery
targets using the new recovery.conf> setting
- recovery_target_name>.
+ recovery_target_name>.
@@ -4009,8 +4009,7 @@
- Allow recovery.conf>
+ Allow recovery.conf>
to use the same quoting behavior as postgresql.conf>
(Dimitri Fontaine)
diff --git a/doc/src/sgml/release.sgml b/doc/src/sgml/release.sgml
index 2515329..de7f68d 100644
--- a/doc/src/sgml/release.sgml
+++ b/doc/src/sgml/release.sgml
@@ -5,7 +5,7 @@ Typical markup:
&<> use & escapes
PostgreSQL
-postgresql.conf, pg_hba.conf,
+postgresql.conf, pg_hba.conf
recovery.conf
[A-Z][A-Z_ ]+[A-Z_] , ,
[A-Za-z_][A-Za-z0-9_]+()
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index cf2f6e7..3671862 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -82,6 +82,20 @@ int sync_method = DEFAULT_SYNC_METHOD;
int wal_level = WAL_LEVEL_MINIMAL;
int CommitDelay = 0; /* precommit delay in microseconds */
int CommitSiblings = 5; /* # concurrent xacts needed to sleep */
+char *restore_command = NULL;
+char *archive_cleanup_command = NULL;
+char *recovery_end_command = NULL;
+bool standby_mode = false;
+char *primary_conninfo = NULL;
+char *trigger_file = NULL;
+RecoveryTargetType recovery_target = RECOVERY_TARGET_UNSET;
+TransactionId recovery_target_xid = InvalidTransactionId;
+TimestampTz recovery_target_time = 0;
+char *recovery_target_name = NULL;
+bool recovery_target_inclusive = true;
+bool pause_at_recovery_target = true;
+char *recovery_target_timeline_string = NULL;
+TimeLineID recovery_target_timeline = 0;
#ifdef WAL_DEBUG
bool XLOG_DEBUG = false;
@@ -194,23 +208,8 @@ bool InArchiveRecovery = false;
/* Was the last xlog file restored from archive, or local? */
static bool restoredFromArchive = false;
-/* options taken from recovery.conf for archive recovery */
-char *recoveryRestoreCommand = NULL;
-static char *recoveryEndCommand = NULL;
-static char *archiveCleanupCommand = NULL;
-static RecoveryTargetType recoveryTarget = RECOVERY_TARGET_UNSET;
-static bool recoveryTargetInclusive = true;
-static bool recoveryPauseAtTarget = true;
-static TransactionId recoveryTargetXid;
-static TimestampTz recoveryTargetTime;
-static char *recoveryTargetName;
-
-/* options taken from recovery.conf for XLOG streaming */
-bool StandbyMode = false;
-static char *PrimaryConnInfo = NULL;
-static char *TriggerFile = NULL;
-
/* if recoveryStopsHere returns true, it saves actual stop xid/time/name here */
+static RecoveryTargetType recoveryStopTarget;
static TransactionId recoveryStopXid;
static TimestampTz recoveryStopTime;
static char recoveryStopName[MAXFNAMELEN];
@@ -407,12 +406,6 @@ typedef struct XLogCtlData
TimeLineID ThisTimeLineID;
/*
- * archiveCleanupCommand is read from recovery.conf but needs to be in
- * shared memory so that the checkpointer process can access it.
- */
- char archiveCleanupCommand[MAXPGPATH];
-
- /*
* SharedRecoveryInProgress indicates if we're still in crash or archive
* recovery. Protected by info_lck.
*/
@@ -3222,7 +3215,7 @@ ReadRecord(XLogReaderState *xlogreader, XLogRecPtr RecPtr, int emode,
/*
* We only end up here without a message when XLogPageRead() failed
* - in that case we already logged something.
- * In StandbyMode that only happens if we have been triggered, so
+ * In standby_mode that only happens if we have been triggered, so
* we shouldn't loop anymore in that case.
*/
if (errormsg)
@@ -3257,7 +3250,7 @@ ReadRecord(XLogReaderState *xlogreader, XLogRecPtr RecPtr, int emode,
record = NULL;
continue;
}
- } while (StandbyMode && record == NULL && !CheckForStandbyTrigger());
+ } while (standby_mode && record == NULL && !CheckForStandbyTrigger());
return record;
}
@@ -4006,21 +3999,18 @@ str_time(pg_time_t tnow)
}
/*
- * See if there is a recovery command file (recovery.conf), and if so
- * read in parameters for archive recovery and XLOG streaming.
- *
- * The file is parsed using the main configuration parser.
+ * Check to see if there is a recovery trigger file (recovery.trigger).
+ * If so, validate recovery parameters and determine recovery target timeline.
*/
static void
readRecoveryCommandFile(void)
{
- FILE *fd;
- TimeLineID rtli = 0;
- bool rtliGiven = false;
+ FILE *fd;
ConfigVariable *item,
- *head = NULL,
- *tail = NULL;
+ *head = NULL,
+ *tail = NULL;
+ /* Check the presence of recovery command file */
fd = AllocateFile(RECOVERY_COMMAND_FILE, "r");
if (fd == NULL)
{
@@ -4040,72 +4030,63 @@ readRecoveryCommandFile(void)
FreeFile(fd);
+ /*
+ * Parse each item in recovery command file and set the related GUC
+ * parameters in consequence. Priority is given to recovery command
+ * file if parameters are already set in postgresql.conf.
+ */
for (item = head; item; item = item->next)
{
if (strcmp(item->name, "restore_command") == 0)
{
- recoveryRestoreCommand = pstrdup(item->value);
+ SetConfigOption("restore_command",
+ pstrdup(item->value), PGC_POSTMASTER, PGC_S_OVERRIDE);
ereport(DEBUG2,
(errmsg_internal("restore_command = '%s'",
- recoveryRestoreCommand)));
+ restore_command)));
}
else if (strcmp(item->name, "recovery_end_command") == 0)
{
- recoveryEndCommand = pstrdup(item->value);
+ SetConfigOption("recovery_end_command",
+ pstrdup(item->value), PGC_POSTMASTER, PGC_S_OVERRIDE);
ereport(DEBUG2,
(errmsg_internal("recovery_end_command = '%s'",
- recoveryEndCommand)));
+ recovery_end_command)));
}
else if (strcmp(item->name, "archive_cleanup_command") == 0)
{
- archiveCleanupCommand = pstrdup(item->value);
+ SetConfigOption("archive_cleanup_command",
+ pstrdup(item->value), PGC_POSTMASTER, PGC_S_OVERRIDE);
ereport(DEBUG2,
(errmsg_internal("archive_cleanup_command = '%s'",
- archiveCleanupCommand)));
+ archive_cleanup_command)));
}
else if (strcmp(item->name, "pause_at_recovery_target") == 0)
{
- if (!parse_bool(item->value, &recoveryPauseAtTarget))
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("parameter \"%s\" requires a Boolean value", "pause_at_recovery_target")));
+ SetConfigOption("pause_at_recovery_target",
+ pstrdup(item->value), PGC_POSTMASTER, PGC_S_OVERRIDE);
ereport(DEBUG2,
(errmsg_internal("pause_at_recovery_target = '%s'",
- item->value)));
+ pause_at_recovery_target ? "true" : "false")));
}
else if (strcmp(item->name, "recovery_target_timeline") == 0)
{
- rtliGiven = true;
- if (strcmp(item->value, "latest") == 0)
- rtli = 0;
- else
- {
- errno = 0;
- rtli = (TimeLineID) strtoul(item->value, NULL, 0);
- if (errno == EINVAL || errno == ERANGE)
- ereport(FATAL,
- (errmsg("recovery_target_timeline is not a valid number: \"%s\"",
- item->value)));
- }
- if (rtli)
+ SetConfigOption("recovery_target_timeline",
+ pstrdup(item->value), PGC_POSTMASTER, PGC_S_OVERRIDE);
+ if (strcmp(recovery_target_timeline_string, "") != 0)
ereport(DEBUG2,
- (errmsg_internal("recovery_target_timeline = %u", rtli)));
- else
- ereport(DEBUG2,
- (errmsg_internal("recovery_target_timeline = latest")));
+ (errmsg_internal("recovery_target_timeline = %u",
+ recovery_target_timeline)));
+ ereport(DEBUG2,
+ (errmsg_internal("recovery_target_timeline = latest")));
}
else if (strcmp(item->name, "recovery_target_xid") == 0)
{
- errno = 0;
- recoveryTargetXid = (TransactionId) strtoul(item->value, NULL, 0);
- if (errno == EINVAL || errno == ERANGE)
- ereport(FATAL,
- (errmsg("recovery_target_xid is not a valid number: \"%s\"",
- item->value)));
+ SetConfigOption("recovery_target_xid",
+ pstrdup(item->value), PGC_POSTMASTER, PGC_S_OVERRIDE);
ereport(DEBUG2,
(errmsg_internal("recovery_target_xid = %u",
- recoveryTargetXid)));
- recoveryTarget = RECOVERY_TARGET_XID;
+ recovery_target_xid)));
}
else if (strcmp(item->name, "recovery_target_time") == 0)
{
@@ -4113,22 +4094,15 @@ readRecoveryCommandFile(void)
* if recovery_target_xid or recovery_target_name specified, then
* this overrides recovery_target_time
*/
- if (recoveryTarget == RECOVERY_TARGET_XID ||
- recoveryTarget == RECOVERY_TARGET_NAME)
+ if (recovery_target == RECOVERY_TARGET_XID ||
+ recovery_target == RECOVERY_TARGET_NAME)
continue;
- recoveryTarget = RECOVERY_TARGET_TIME;
- /*
- * Convert the time string given by the user to TimestampTz form.
- */
- recoveryTargetTime =
- DatumGetTimestampTz(DirectFunctionCall3(timestamptz_in,
- CStringGetDatum(item->value),
- ObjectIdGetDatum(InvalidOid),
- Int32GetDatum(-1)));
+ SetConfigOption("recovery_target_time",
+ pstrdup(item->value), PGC_POSTMASTER, PGC_S_OVERRIDE);
ereport(DEBUG2,
(errmsg_internal("recovery_target_time = '%s'",
- timestamptz_to_str(recoveryTargetTime))));
+ timestamptz_to_str(recovery_target_time))));
}
else if (strcmp(item->name, "recovery_target_name") == 0)
{
@@ -4136,58 +4110,45 @@ readRecoveryCommandFile(void)
* if recovery_target_xid specified, then this overrides
* recovery_target_name
*/
- if (recoveryTarget == RECOVERY_TARGET_XID)
+ if (recovery_target == RECOVERY_TARGET_XID)
continue;
- recoveryTarget = RECOVERY_TARGET_NAME;
-
- recoveryTargetName = pstrdup(item->value);
- if (strlen(recoveryTargetName) >= MAXFNAMELEN)
- ereport(FATAL,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("recovery_target_name is too long (maximum %d characters)",
- MAXFNAMELEN - 1)));
+ SetConfigOption("recovery_target_name",
+ pstrdup(item->value), PGC_POSTMASTER, PGC_S_OVERRIDE);
ereport(DEBUG2,
(errmsg_internal("recovery_target_name = '%s'",
- recoveryTargetName)));
+ recovery_target_name)));
}
else if (strcmp(item->name, "recovery_target_inclusive") == 0)
{
- /*
- * does nothing if a recovery_target is not also set
- */
- if (!parse_bool(item->value, &recoveryTargetInclusive))
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("parameter \"%s\" requires a Boolean value",
- "recovery_target_inclusive")));
+ SetConfigOption("recovery_target_inclusive",
+ pstrdup(item->value), PGC_POSTMASTER, PGC_S_OVERRIDE);
ereport(DEBUG2,
(errmsg_internal("recovery_target_inclusive = %s",
- item->value)));
+ recovery_target_inclusive ? "true" : "false")));
}
else if (strcmp(item->name, "standby_mode") == 0)
{
- if (!parse_bool(item->value, &StandbyMode))
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("parameter \"%s\" requires a Boolean value",
- "standby_mode")));
+ SetConfigOption("standby_mode",
+ pstrdup(item->value), PGC_POSTMASTER, PGC_S_OVERRIDE);
ereport(DEBUG2,
(errmsg_internal("standby_mode = '%s'", item->value)));
}
else if (strcmp(item->name, "primary_conninfo") == 0)
{
- PrimaryConnInfo = pstrdup(item->value);
+ SetConfigOption("primary_conninfo",
+ pstrdup(item->value), PGC_POSTMASTER, PGC_S_OVERRIDE);
ereport(DEBUG2,
(errmsg_internal("primary_conninfo = '%s'",
- PrimaryConnInfo)));
+ primary_conninfo)));
}
else if (strcmp(item->name, "trigger_file") == 0)
{
- TriggerFile = pstrdup(item->value);
+ SetConfigOption("trigger_file",
+ pstrdup(item->value), PGC_POSTMASTER, PGC_S_OVERRIDE);
ereport(DEBUG2,
(errmsg_internal("trigger_file = '%s'",
- TriggerFile)));
+ trigger_file)));
}
else
ereport(FATAL,
@@ -4195,23 +4156,20 @@ readRecoveryCommandFile(void)
item->name)));
}
- /*
- * Check for compulsory parameters
- */
- if (StandbyMode)
+ /* Check for compulsory parameters */
+ if (standby_mode)
{
- if (PrimaryConnInfo == NULL && recoveryRestoreCommand == NULL)
+ if (!restore_command[0] && !primary_conninfo[0])
ereport(WARNING,
- (errmsg("recovery command file \"%s\" specified neither primary_conninfo nor restore_command",
- RECOVERY_COMMAND_FILE),
+ (errmsg("Neither primary_conninfo nor restore_command specified"),
errhint("The database server will regularly poll the pg_xlog subdirectory to check for files placed there.")));
}
else
{
- if (recoveryRestoreCommand == NULL)
+ if (!restore_command[0])
ereport(FATAL,
- (errmsg("recovery command file \"%s\" must specify restore_command when standby mode is not enabled",
- RECOVERY_COMMAND_FILE)));
+ (errmsg("restore_command must be specified when "
+ "standby_mode is not enabled")));
}
/* Enable fetching from archive recovery area */
@@ -4223,16 +4181,17 @@ readRecoveryCommandFile(void)
* command and set InArchiveRecovery, because we need to fetch timeline
* history files from the archive.
*/
- if (rtliGiven)
+ if (strcmp(recovery_target_timeline_string, "") != 0)
{
- if (rtli)
+ if (recovery_target_timeline)
{
/* Timeline 1 does not have a history file, all else should */
- if (rtli != 1 && !existsTimeLineHistory(rtli))
+ if (recovery_target_timeline != 1 &&
+ !existsTimeLineHistory(recovery_target_timeline))
ereport(FATAL,
(errmsg("recovery target timeline %u does not exist",
- rtli)));
- recoveryTargetTLI = rtli;
+ recovery_target_timeline)));
+ recoveryTargetTLI = recovery_target_timeline;
recoveryTargetIsLatest = false;
}
else
@@ -4385,7 +4344,7 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
return false;
/* Do we have a PITR target at all? */
- if (recoveryTarget == RECOVERY_TARGET_UNSET)
+ if (recovery_target == RECOVERY_TARGET_UNSET)
{
/*
* Save timestamp of latest transaction commit/abort if this is a
@@ -4396,7 +4355,7 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
return false;
}
- if (recoveryTarget == RECOVERY_TARGET_XID)
+ if (recovery_target == RECOVERY_TARGET_XID)
{
/*
* There can be only one transaction end record with this exact
@@ -4407,17 +4366,17 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
* they complete. A higher numbered xid will complete before you about
* 50% of the time...
*/
- stopsHere = (record->xl_xid == recoveryTargetXid);
+ stopsHere = (record->xl_xid == recovery_target_xid);
if (stopsHere)
- *includeThis = recoveryTargetInclusive;
+ *includeThis = recovery_target_inclusive;
}
- else if (recoveryTarget == RECOVERY_TARGET_NAME)
+ else if (recovery_target == RECOVERY_TARGET_NAME)
{
/*
* There can be many restore points that share the same name, so we
* stop at the first one
*/
- stopsHere = (strcmp(recordRPName, recoveryTargetName) == 0);
+ stopsHere = (strcmp(recordRPName, recovery_target_name) == 0);
/*
* Ignore recoveryTargetInclusive because this is not a transaction
@@ -4432,16 +4391,17 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
* we stop after the last one, if we are inclusive, or stop at the
* first one if we are exclusive
*/
- if (recoveryTargetInclusive)
- stopsHere = (recordXtime > recoveryTargetTime);
+ if (recovery_target_inclusive)
+ stopsHere = (recordXtime > recovery_target_time);
else
- stopsHere = (recordXtime >= recoveryTargetTime);
+ stopsHere = (recordXtime >= recovery_target_time);
if (stopsHere)
*includeThis = false;
}
if (stopsHere)
{
+ recoveryStopTarget = recovery_target;
recoveryStopXid = record->xl_xid;
recoveryStopTime = recordXtime;
recoveryStopAfter = *includeThis;
@@ -4789,36 +4749,28 @@ StartupXLOG(void)
recoveryTargetTLI = ControlFile->checkPointCopy.ThisTimeLineID;
/*
- * Check for recovery control file, and if so set up state for offline
- * recovery
+ * Check for recovery trigger file, and if so set up state for offline
+ * recovery.
*/
readRecoveryCommandFile();
- /*
- * Save archive_cleanup_command in shared memory so that other processes
- * can see it.
- */
- strncpy(XLogCtl->archiveCleanupCommand,
- archiveCleanupCommand ? archiveCleanupCommand : "",
- sizeof(XLogCtl->archiveCleanupCommand));
-
if (InArchiveRecovery)
{
- if (StandbyMode)
+ if (standby_mode)
ereport(LOG,
(errmsg("entering standby mode")));
- else if (recoveryTarget == RECOVERY_TARGET_XID)
+ else if (recovery_target == RECOVERY_TARGET_XID)
ereport(LOG,
(errmsg("starting point-in-time recovery to XID %u",
- recoveryTargetXid)));
- else if (recoveryTarget == RECOVERY_TARGET_TIME)
+ recovery_target_xid)));
+ else if (recovery_target == RECOVERY_TARGET_TIME)
ereport(LOG,
(errmsg("starting point-in-time recovery to %s",
- timestamptz_to_str(recoveryTargetTime))));
- else if (recoveryTarget == RECOVERY_TARGET_NAME)
+ timestamptz_to_str(recovery_target_time))));
+ else if (recovery_target == RECOVERY_TARGET_NAME)
ereport(LOG,
(errmsg("starting point-in-time recovery to \"%s\"",
- recoveryTargetName)));
+ recovery_target_name)));
else
ereport(LOG,
(errmsg("starting archive recovery")));
@@ -4828,7 +4780,7 @@ StartupXLOG(void)
* Take ownership of the wakeup latch if we're going to sleep during
* recovery.
*/
- if (StandbyMode)
+ if (standby_mode)
OwnLatch(&XLogCtl->recoveryWakeupLatch);
/* Set up XLOG reader facility */
@@ -4897,7 +4849,7 @@ StartupXLOG(void)
(errmsg("checkpoint record is at %X/%X",
(uint32) (checkPointLoc >> 32), (uint32) checkPointLoc)));
}
- else if (StandbyMode)
+ else if (standby_mode)
{
/*
* The last valid checkpoint record required for a streaming
@@ -5030,7 +4982,7 @@ StartupXLOG(void)
/*
* Check whether we need to force recovery from WAL. If it appears to
- * have been a clean shutdown and we did not have a recovery.conf file,
+ * have been a clean shutdown and we did not have a recovery.trigger file,
* then assume no recovery needed.
*/
if (checkPoint.redo < RecPtr)
@@ -5044,7 +4996,7 @@ StartupXLOG(void)
InRecovery = true;
else if (InArchiveRecovery)
{
- /* force recovery due to presence of recovery.conf */
+ /* force recovery due to presence of recovery.trigger */
InRecovery = true;
}
@@ -5357,7 +5309,7 @@ StartupXLOG(void)
*/
if (recoveryStopsHere(record, &recoveryApply))
{
- if (recoveryPauseAtTarget)
+ if (pause_at_recovery_target)
{
SetRecoveryPause(true);
recoveryPausesHere();
@@ -5507,7 +5459,7 @@ StartupXLOG(void)
* We don't need the latch anymore. It's not strictly necessary to disown
* it, but let's do it for the sake of tidiness.
*/
- if (StandbyMode)
+ if (standby_mode)
DisownLatch(&XLogCtl->recoveryWakeupLatch);
/*
@@ -5515,7 +5467,7 @@ StartupXLOG(void)
* recovery to force fetching the files (which would be required at end of
* recovery, e.g., timeline history file) from archive or pg_xlog.
*/
- StandbyMode = false;
+ SetConfigOption("standby_mode", "false", PGC_POSTMASTER, PGC_S_OVERRIDE);
/*
* Re-fetch the last valid or last applied record, so we can identify the
@@ -5594,17 +5546,17 @@ StartupXLOG(void)
* Create a comment for the history file to explain why and where
* timeline changed.
*/
- if (recoveryTarget == RECOVERY_TARGET_XID)
+ if (recovery_target == RECOVERY_TARGET_XID)
snprintf(reason, sizeof(reason),
"%s transaction %u",
recoveryStopAfter ? "after" : "before",
recoveryStopXid);
- else if (recoveryTarget == RECOVERY_TARGET_TIME)
+ else if (recovery_target == RECOVERY_TARGET_TIME)
snprintf(reason, sizeof(reason),
"%s %s\n",
recoveryStopAfter ? "after" : "before",
timestamptz_to_str(recoveryStopTime));
- else if (recoveryTarget == RECOVERY_TARGET_NAME)
+ else if (recovery_target == RECOVERY_TARGET_NAME)
snprintf(reason, sizeof(reason),
"at restore point \"%s\"",
recoveryStopName);
@@ -5738,8 +5690,8 @@ StartupXLOG(void)
/*
* And finally, execute the recovery_end_command, if any.
*/
- if (recoveryEndCommand)
- ExecuteRecoveryCommand(recoveryEndCommand,
+ if (recovery_end_command[0])
+ ExecuteRecoveryCommand(recovery_end_command,
"recovery_end_command",
true);
}
@@ -6592,7 +6544,7 @@ CreateCheckPoint(int flags)
XLogRecPtr curInsert;
INSERT_RECPTR(curInsert, Insert, Insert->curridx);
- if (curInsert == ControlFile->checkPoint +
+ if (curInsert == ControlFile->checkPoint +
MAXALIGN(SizeOfXLogRecord + sizeof(CheckPoint)) &&
ControlFile->checkPoint == ControlFile->checkPointCopy.redo)
{
@@ -7169,8 +7121,8 @@ CreateRestartPoint(int flags)
/*
* Finally, execute archive_cleanup_command, if any.
*/
- if (XLogCtl->archiveCleanupCommand[0])
- ExecuteRecoveryCommand(XLogCtl->archiveCleanupCommand,
+ if (archive_cleanup_command[0])
+ ExecuteRecoveryCommand(archive_cleanup_command,
"archive_cleanup_command",
false);
@@ -8886,7 +8838,7 @@ XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen,
* Request a restartpoint if we've replayed too much xlog since the
* last one.
*/
- if (StandbyMode && bgwriterLaunched)
+ if (standby_mode && bgwriterLaunched)
{
if (XLogCheckpointNeeded(readSegNo))
{
@@ -8909,7 +8861,7 @@ retry:
(readSource == XLOG_FROM_STREAM &&
receivedUpto < targetPagePtr + reqLen))
{
- if (StandbyMode)
+ if (standby_mode)
{
if (!WaitForWALToBecomeAvailable(targetPagePtr + reqLen,
private->randAccess,
@@ -8998,7 +8950,7 @@ next_record_is_invalid:
readSource = 0;
/* In standby-mode, keep trying */
- if (StandbyMode)
+ if (standby_mode)
goto retry;
else
return -1;
@@ -9105,7 +9057,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
* that when we later jump backwards to start redo at
* RedoStartLSN, we will have the logs streamed already.
*/
- if (PrimaryConnInfo)
+ if (primary_conninfo[0])
{
XLogRecPtr ptr;
TimeLineID tli;
@@ -9126,7 +9078,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
tli, curFileTLI);
}
curFileTLI = tli;
- RequestXLogStreaming(curFileTLI, ptr, PrimaryConnInfo);
+ RequestXLogStreaming(curFileTLI, ptr);
}
/*
* Move to XLOG_FROM_STREAM state in either case. We'll get
@@ -9412,14 +9364,14 @@ CheckForStandbyTrigger(void)
return true;
}
- if (TriggerFile == NULL)
+ if (!trigger_file[0])
return false;
- if (stat(TriggerFile, &stat_buf) == 0)
+ if (stat(trigger_file, &stat_buf) == 0)
{
ereport(LOG,
- (errmsg("trigger file found: %s", TriggerFile)));
- unlink(TriggerFile);
+ (errmsg("trigger file found: %s", trigger_file)));
+ unlink(trigger_file);
triggered = true;
return true;
}
diff --git a/src/backend/access/transam/xlogarchive.c b/src/backend/access/transam/xlogarchive.c
index 52922da..20275c8 100644
--- a/src/backend/access/transam/xlogarchive.c
+++ b/src/backend/access/transam/xlogarchive.c
@@ -67,7 +67,7 @@ RestoreArchivedFile(char *path, const char *xlogfname,
TimeLineID restartTli;
/* In standby mode, restore_command might not be supplied */
- if (recoveryRestoreCommand == NULL)
+ if (restore_command == NULL)
goto not_available;
/*
@@ -150,7 +150,7 @@ RestoreArchivedFile(char *path, const char *xlogfname,
endp = xlogRestoreCmd + MAXPGPATH - 1;
*endp = '\0';
- for (sp = recoveryRestoreCommand; *sp; sp++)
+ for (sp = restore_command; *sp; sp++)
{
if (*sp == '%')
{
@@ -236,7 +236,7 @@ RestoreArchivedFile(char *path, const char *xlogfname,
* incorrectly conclude we've reached the end of WAL and we're
* done recovering ...
*/
- if (StandbyMode && stat_buf.st_size < expectedSize)
+ if (standby_mode && stat_buf.st_size < expectedSize)
elevel = DEBUG1;
else
elevel = FATAL;
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index c02101f..9babd74 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -9,7 +9,7 @@
* dependent objects can be associated with it. An extension is created by
* populating the pg_extension catalog from a "control" file.
* The extension control file is parsed with the same parser we use for
- * postgresql.conf and recovery.conf. An extension also has an installation
+ * postgresql.conf. An extension also has an installation
* script file, containing SQL commands to create the extension's objects.
*
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c
index 7359297..325f6de 100644
--- a/src/backend/replication/walreceiver.c
+++ b/src/backend/replication/walreceiver.c
@@ -185,7 +185,6 @@ DisableWalRcvImmediateExit(void)
void
WalReceiverMain(void)
{
- char conninfo[MAXCONNINFO];
XLogRecPtr startpoint;
TimeLineID startpointTLI;
TimeLineID primaryTLI;
@@ -239,7 +238,6 @@ WalReceiverMain(void)
walrcv->walRcvState = WALRCV_STREAMING;
/* Fetch information required to start streaming */
- strlcpy(conninfo, (char *) walrcv->conninfo, MAXCONNINFO);
startpoint = walrcv->receiveStart;
startpointTLI = walrcv->receiveStartTLI;
@@ -306,7 +304,7 @@ WalReceiverMain(void)
/* Establish the connection to the primary for XLOG streaming */
EnableWalRcvImmediateExit();
- walrcv_connect(conninfo);
+ walrcv_connect(primary_conninfo);
DisableWalRcvImmediateExit();
first_stream = true;
@@ -404,8 +402,21 @@ WalReceiverMain(void)
if (got_SIGHUP)
{
+ char *conninfo = pstrdup(primary_conninfo);
+
got_SIGHUP = false;
ProcessConfigFile(PGC_SIGHUP);
+
+ /*
+ * If primary_conninfo has been changed while walreceiver is running,
+ * shut down walreceiver so that new walreceiver is started and
+ * it initiates replication with new primary_conninfo.
+ */
+ if (strcmp(conninfo, primary_conninfo) != 0)
+ ereport(FATAL,
+ (errcode(ERRCODE_ADMIN_SHUTDOWN),
+ errmsg("terminating walreceiver process because primary_conninfo was changed")));
+ pfree(conninfo);
}
/* Wait a while for data to arrive */
diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c
index d414808..d6a5e06 100644
--- a/src/backend/replication/walreceiverfuncs.c
+++ b/src/backend/replication/walreceiverfuncs.c
@@ -219,11 +219,10 @@ ShutdownWalRcv(void)
/*
* Request postmaster to start walreceiver.
*
- * recptr indicates the position where streaming should begin, and conninfo
- * is a libpq connection string to use.
+ * recptr indicates the position where streaming should begin.
*/
void
-RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo)
+RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr)
{
/* use volatile pointer to prevent code rearrangement */
volatile WalRcvData *walrcv = WalRcv;
@@ -245,11 +244,6 @@ RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo)
Assert(walrcv->walRcvState == WALRCV_STOPPED ||
walrcv->walRcvState == WALRCV_WAITING);
- if (conninfo != NULL)
- strlcpy((char *) walrcv->conninfo, conninfo, MAXCONNINFO);
- else
- walrcv->conninfo[0] = '\0';
-
if (walrcv->walRcvState == WALRCV_STOPPED)
{
launch = true;
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 6128694..f49b8fe 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -30,6 +30,7 @@
#include "access/transam.h"
#include "access/twophase.h"
#include "access/xact.h"
+#include "access/xlog_internal.h"
#include "catalog/namespace.h"
#include "commands/async.h"
#include "commands/prepare.h"
@@ -196,6 +197,14 @@ static bool check_application_name(char **newval, void **extra, GucSource source
static void assign_application_name(const char *newval, void *extra);
static const char *show_unix_socket_permissions(void);
static const char *show_log_file_mode(void);
+static bool check_recovery_target_xid(char **newval, void **extra, GucSource source);
+static void assign_recovery_target_xid(const char *newval, void *extra);
+static bool check_recovery_target_name(char **newval, void **extra, GucSource source);
+static void assign_recovery_target_name(const char *newval, void *extra);
+static bool check_recovery_target_time(char **newval, void **extra, GucSource source);
+static void assign_recovery_target_time(const char *newval, void *extra);
+static bool check_recovery_target_timeline(char **newval, void **extra, GucSource source);
+static void assign_recovery_target_timeline(const char *newval, void *extra);
static char *config_enum_get_options(struct config_enum * record,
const char *prefix, const char *suffix,
@@ -468,6 +477,8 @@ static int wal_block_size;
static int wal_segment_size;
static bool integer_datetimes;
static int effective_io_concurrency;
+static char *recovery_target_xid_string;
+static char *recovery_target_time_string;
/* should be static, but commands/variable.c needs to get at this */
char *role_string;
@@ -547,6 +558,10 @@ const char *const config_group_names[] =
gettext_noop("Write-Ahead Log / Checkpoints"),
/* WAL_ARCHIVING */
gettext_noop("Write-Ahead Log / Archiving"),
+ /* WAL_ARCHIVE_RECOVERY */
+ gettext_noop("Write-Ahead Log / Archive Recovery"),
+ /* WAL_RECOVERY_TARGET */
+ gettext_noop("Write-Ahead Log / Recovery Target"),
/* REPLICATION */
gettext_noop("Replication"),
/* REPLICATION_SENDING */
@@ -1375,6 +1390,36 @@ static struct config_bool ConfigureNamesBool[] =
},
{
+ {"recovery_target_inclusive", PGC_SIGHUP, WAL_RECOVERY_TARGET,
+ gettext_noop("Sets whether to include or exclude transaction with recovery target."),
+ NULL
+ },
+ &recovery_target_inclusive,
+ true,
+ NULL, NULL, NULL
+ },
+
+ {
+ {"pause_at_recovery_target", PGC_SIGHUP, WAL_RECOVERY_TARGET,
+ gettext_noop("Sets whether recovery should pause when the recovery target is reached."),
+ NULL
+ },
+ &pause_at_recovery_target,
+ true,
+ NULL, NULL, NULL
+ },
+
+ {
+ {"standby_mode", PGC_POSTMASTER, REPLICATION_STANDBY,
+ gettext_noop("Sets whether to start the server as a standby."),
+ NULL
+ },
+ &standby_mode,
+ false,
+ NULL, NULL, NULL
+ },
+
+ {
{"hot_standby", PGC_POSTMASTER, REPLICATION_STANDBY,
gettext_noop("Allows connections and queries during recovery."),
NULL
@@ -2543,6 +2588,97 @@ static struct config_string ConfigureNamesString[] =
},
{
+ {"restore_command", PGC_SIGHUP, WAL_ARCHIVE_RECOVERY,
+ gettext_noop("Sets the shell command that will retrieve an archived WAL file."),
+ NULL
+ },
+ &restore_command,
+ "",
+ NULL, NULL, NULL
+ },
+
+ {
+ {"archive_cleanup_command", PGC_SIGHUP, WAL_ARCHIVE_RECOVERY,
+ gettext_noop("Sets the shell command that will be executed at every restartpoint."),
+ NULL
+ },
+ &archive_cleanup_command,
+ "",
+ NULL, NULL, NULL
+ },
+
+ {
+ {"recovery_end_command", PGC_SIGHUP, WAL_ARCHIVE_RECOVERY,
+ gettext_noop("Sets the shell command that will be executed once only at the end of recovery."),
+ NULL
+ },
+ &recovery_end_command,
+ "",
+ NULL, NULL, NULL
+ },
+
+ {
+ {"recovery_target_xid", PGC_SIGHUP, WAL_RECOVERY_TARGET,
+ gettext_noop("Sets the transaction ID up to which recovery will proceed."),
+ NULL
+ },
+ &recovery_target_xid_string,
+ "",
+ check_recovery_target_xid, assign_recovery_target_xid, NULL
+ },
+
+ {
+ {"recovery_target_name", PGC_SIGHUP, WAL_RECOVERY_TARGET,
+ gettext_noop("Sets the named restore point."),
+ NULL
+ },
+ &recovery_target_name,
+ "",
+ check_recovery_target_name, assign_recovery_target_name, NULL
+ },
+
+ {
+ {"recovery_target_time", PGC_SIGHUP, WAL_RECOVERY_TARGET,
+ gettext_noop("Sets the time stamp up to which recovery will proceed."),
+ NULL
+ },
+ &recovery_target_time_string,
+ "",
+ check_recovery_target_time, assign_recovery_target_time, NULL
+ },
+
+ {
+ {"recovery_target_timeline", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
+ gettext_noop("Sets recoverying into a particular timeline."),
+ NULL
+ },
+ &recovery_target_timeline_string,
+ "",
+ check_recovery_target_timeline, assign_recovery_target_timeline, NULL
+ },
+
+ {
+ {"primary_conninfo", PGC_SIGHUP, REPLICATION_STANDBY,
+ gettext_noop("Sets the connection string to be used to connect with the primary."),
+ NULL,
+ GUC_SUPERUSER_ONLY
+ },
+ &primary_conninfo,
+ "",
+ NULL, NULL, NULL
+ },
+
+ {
+ {"trigger_file", PGC_SIGHUP, REPLICATION_STANDBY,
+ gettext_noop("Sets the trigger file whose presence ends recovery in the standby."),
+ NULL
+ },
+ &trigger_file,
+ "",
+ NULL, NULL, NULL
+ },
+
+ {
{"client_encoding", PGC_USERSET, CLIENT_CONN_LOCALE,
gettext_noop("Sets the client's character set encoding."),
NULL,
@@ -8760,4 +8896,158 @@ show_log_file_mode(void)
return buf;
}
+static bool
+check_recovery_target_xid(char **newval, void **extra, GucSource source)
+{
+ TransactionId xid;
+ TransactionId *myextra;
+
+ if (strcmp(*newval, "") == 0)
+ xid = InvalidTransactionId;
+ else
+ {
+ errno = 0;
+ xid = (TransactionId) strtoul(*newval, NULL, 0);
+ if (errno == EINVAL || errno == ERANGE)
+ {
+ GUC_check_errdetail("recovery_target_xid is not a valid number: \"%s\"",
+ *newval);
+ return false;
+ }
+ }
+
+ myextra = (TransactionId *) guc_malloc(ERROR, sizeof(TransactionId));
+ *myextra = xid;
+ *extra = (void *) myextra;
+
+ return true;
+}
+
+static void
+assign_recovery_target_xid(const char *newval, void *extra)
+{
+ recovery_target_xid = *((TransactionId *) extra);
+
+ if (recovery_target_xid != InvalidTransactionId)
+ recovery_target = RECOVERY_TARGET_XID;
+ else if (recovery_target_name[0])
+ recovery_target = RECOVERY_TARGET_NAME;
+ else if (recovery_target_time != 0)
+ recovery_target = RECOVERY_TARGET_TIME;
+ else
+ recovery_target = RECOVERY_TARGET_UNSET;
+}
+
+static bool
+check_recovery_target_name(char **newval, void **extra, GucSource source)
+{
+ if (strlen(*newval) >= MAXFNAMELEN)
+ {
+ GUC_check_errdetail("\"recovery_target_name\" is too long (maximum %d characters)",
+ MAXFNAMELEN - 1);
+ return false;
+ }
+ return true;
+}
+
+static void
+assign_recovery_target_name(const char *newval, void *extra)
+{
+ if (recovery_target_xid != InvalidTransactionId)
+ recovery_target = RECOVERY_TARGET_XID;
+ else if (newval[0])
+ recovery_target = RECOVERY_TARGET_NAME;
+ else if (recovery_target_time != 0)
+ recovery_target = RECOVERY_TARGET_TIME;
+ else
+ recovery_target = RECOVERY_TARGET_UNSET;
+}
+
+static bool
+check_recovery_target_time(char **newval, void **extra, GucSource source)
+{
+ TimestampTz time;
+ TimestampTz *myextra;
+ MemoryContext oldcontext = CurrentMemoryContext;
+
+ PG_TRY();
+ {
+ time = (strcmp(*newval, "") == 0) ?
+ 0 :
+ DatumGetTimestampTz(DirectFunctionCall3(timestamptz_in,
+ CStringGetDatum(*newval),
+ ObjectIdGetDatum(InvalidOid),
+ Int32GetDatum(-1)));
+ }
+ PG_CATCH();
+ {
+ ErrorData *edata;
+
+ /* Save error info */
+ MemoryContextSwitchTo(oldcontext);
+ edata = CopyErrorData();
+ FlushErrorState();
+
+ /* Pass the error message */
+ GUC_check_errdetail("%s", edata->message);
+ FreeErrorData(edata);
+ return false;
+ }
+ PG_END_TRY();
+
+ myextra = (TimestampTz *) guc_malloc(ERROR, sizeof(TimestampTz));
+ *myextra = time;
+ *extra = (void *) myextra;
+
+ return true;
+}
+
+static void
+assign_recovery_target_time(const char *newval, void *extra)
+{
+ recovery_target_time = *((TimestampTz *) extra);
+
+ if (recovery_target_xid != InvalidTransactionId)
+ recovery_target = RECOVERY_TARGET_XID;
+ else if (recovery_target_name[0])
+ recovery_target = RECOVERY_TARGET_NAME;
+ else if (recovery_target_time != 0)
+ recovery_target = RECOVERY_TARGET_TIME;
+ else
+ recovery_target = RECOVERY_TARGET_UNSET;
+}
+
+static bool
+check_recovery_target_timeline(char **newval, void **extra, GucSource source)
+{
+ TimeLineID tli = 0;
+ TimeLineID *myextra;
+
+ if (strcmp(*newval, "") == 0 || strcmp(*newval, "latest") == 0)
+ tli = 0;
+ else
+ {
+ errno = 0;
+ tli = (TimeLineID) strtoul(*newval, NULL, 0);
+ if (errno == EINVAL || errno == ERANGE)
+ {
+ GUC_check_errdetail("recovery_target_timeline is not a valid number: \"%s\"",
+ *newval);
+ return false;
+ }
+ }
+
+ myextra = (TimeLineID *) guc_malloc(ERROR, sizeof(TimeLineID));
+ *myextra = tli;
+ *extra = (void *) myextra;
+
+ return true;
+}
+
+static void
+assign_recovery_target_timeline(const char *newval, void *extra)
+{
+ recovery_target_timeline = *((TimeLineID *) extra);
+}
+
#include "guc-file.c"
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 62aea2f..52a4e71 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -198,6 +198,23 @@
#archive_timeout = 0 # force a logfile segment switch after this
# number of seconds; 0 disables
+# - Archive Recovery -
+#restore_command = '' # command to use to restore an archived logfile segment
+ # placeholders: %p = path of file to restore
+ # %f = file name only
+ # e.g. 'cp /mnt/server/archivedir/%f %p'
+#archive_cleanup_command = '' # command to execute at every restartpoint
+#recovery_end_command = '' # command to execute at completion of recovery
+
+# - Recovery Target -
+#recovery_target_xid = ''
+#recovery_target_name = '' # e.g. 'daily backup 2011-01-26'
+#recovery_target_time = '' # e.g. '2004-07-14 22:39:00 EST'
+#recovery_target_timeline = '' # timeline ID or 'latest'
+ # (change requires restart)
+#recovery_target_inclusive = on
+#pause_at_recovery_target = on # Pause recovery once target is reached
+
#------------------------------------------------------------------------------
# REPLICATION
@@ -240,6 +257,11 @@
#wal_receiver_timeout = 60s # time that receiver waits for
# communication from master
# in milliseconds; 0 disables
+#standby_mode = off # "on" starts the server as a standby
+ # (change requires restart)
+#primary_conninfo = '' # connection string to connect to the master
+ # e.g. 'host=localhost port=5432'
+#trigger_file = '' # trigger file to promote the standby
#------------------------------------------------------------------------------
diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c
index e412d71..3a02481 100644
--- a/src/bin/pg_ctl/pg_ctl.c
+++ b/src/bin/pg_ctl/pg_ctl.c
@@ -928,7 +928,7 @@ do_stop(void)
/*
* If backup_label exists, an online backup is running. Warn the user
* that smart shutdown will wait for it to finish. However, if
- * recovery.conf is also present, we're recovering from an online
+ * recovery.trigger is also present, we're recovering from an online
* backup instead of performing one.
*/
if (shutdown_mode == SMART_MODE &&
@@ -1016,7 +1016,7 @@ do_restart(void)
/*
* If backup_label exists, an online backup is running. Warn the user
* that smart shutdown will wait for it to finish. However, if
- * recovery.conf is also present, we're recovering from an online
+ * recovery.trigger is also present, we're recovering from an online
* backup instead of performing one.
*/
if (shutdown_mode == SMART_MODE &&
@@ -1127,7 +1127,7 @@ do_promote(void)
exit(1);
}
- /* If recovery.conf doesn't exist, the server is not in standby mode */
+ /* If recovery.trigger doesn't exist, the server is not in standby mode */
if (stat(recovery_file, &statbuf) != 0)
{
write_stderr(_("%s: cannot promote server; "
@@ -2270,7 +2270,7 @@ main(int argc, char **argv)
snprintf(postopts_file, MAXPGPATH, "%s/postmaster.opts", pg_data);
snprintf(pid_file, MAXPGPATH, "%s/postmaster.pid", pg_data);
snprintf(backup_file, MAXPGPATH, "%s/backup_label", pg_data);
- snprintf(recovery_file, MAXPGPATH, "%s/recovery.conf", pg_data);
+ snprintf(recovery_file, MAXPGPATH, "%s/recovery.trigger", pg_data);
snprintf(promote_file, MAXPGPATH, "%s/promote", pg_data);
}
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 72e3242..c831345 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -190,6 +190,20 @@ extern char *XLogArchiveCommand;
extern bool EnableHotStandby;
extern bool fullPageWrites;
extern bool log_checkpoints;
+extern char *restore_command;
+extern char *archive_cleanup_command;
+extern char *recovery_end_command;
+extern bool standby_mode;
+extern char *primary_conninfo;
+extern char *trigger_file;
+extern RecoveryTargetType recovery_target;
+extern TransactionId recovery_target_xid;
+extern TimestampTz recovery_target_time;
+extern char *recovery_target_name;
+extern bool recovery_target_inclusive;
+extern bool pause_at_recovery_target;
+extern char *recovery_target_timeline_string;
+extern TimeLineID recovery_target_timeline;
/* WAL levels */
typedef enum WalLevel
diff --git a/src/include/replication/walreceiver.h b/src/include/replication/walreceiver.h
index 72878f8..d51d86f 100644
--- a/src/include/replication/walreceiver.h
+++ b/src/include/replication/walreceiver.h
@@ -149,7 +149,7 @@ extern void WalRcvShmemInit(void);
extern void ShutdownWalRcv(void);
extern bool WalRcvStreaming(void);
extern bool WalRcvRunning(void);
-extern void RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo);
+extern void RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr);
extern XLogRecPtr GetWalRcvWriteRecPtr(XLogRecPtr *latestChunkStart, TimeLineID *receiveTLI);
extern int GetReplicationApplyDelay(void);
extern int GetReplicationTransferLatency(void);
diff --git a/src/include/utils/guc_tables.h b/src/include/utils/guc_tables.h
index 7360ce3..a2d3281 100644
--- a/src/include/utils/guc_tables.h
+++ b/src/include/utils/guc_tables.h
@@ -68,6 +68,8 @@ enum config_group
WAL_SETTINGS,
WAL_CHECKPOINTS,
WAL_ARCHIVING,
+ WAL_ARCHIVE_RECOVERY,
+ WAL_RECOVERY_TARGET,
REPLICATION,
REPLICATION_SENDING,
REPLICATION_MASTER,