On 18/11/14 12:57, Simon Riggs wrote:
On 31 October 2014 15:18, Petr Jelinek <p...@2ndquadrant.com> wrote:

Attached is the v2 of the patch with the review comments addressed (see
below).
...
Done, there is now action_at_recovery_target which can be set to either
pause, continue or shutdown, defaulting to pause (which is same as old
behavior of pause_at_recovery_target defaulting to true).

One comment only: I think the actions should be called: pause, promote
and shutdown, since "continue" leads immediately to promotion of the
server.

I'm good with this patch otherwise. Barring objections I will commit tomorrow.


OK, promote works for me as well, I attached patch that changes continue to promote so you don't have to find and replace everything yourself. The changed doc wording probably needs to be checked.

--
 Petr Jelinek                  http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services
diff --git a/doc/src/sgml/recovery-config.sgml b/doc/src/sgml/recovery-config.sgml
index 0f1ff34..fe42394 100644
--- a/doc/src/sgml/recovery-config.sgml
+++ b/doc/src/sgml/recovery-config.sgml
@@ -289,12 +289,39 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"'  # Windows
       </term>
       <listitem>
        <para>
-        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
-        <function>pg_xlog_replay_resume()</> (See
+        Alias for action_at_recovery_target, <literal>true</> is same as
+        action_at_recovery_target = <literal>pause</> and <literal>false</>
+        is same as action_at_recovery_target = <literal>promote</>.
+       </para>
+       <para>
+        This setting has no effect if <xref linkend="guc-hot-standby"> is not
+        enabled, or if no recovery target is set.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     </variablelist>
+
+     <varlistentry id="action-at-recovery-target"
+                   xreflabel="action_at_recovery_target">
+      <term><varname>action_at_recovery_target</varname> (<type>enum</type>)
+      <indexterm>
+        <primary><varname>action_at_recovery_target</> recovery parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Specifies what action should PostgreSQL do once the recovery target is
+        reached. The default is <literal>pause</>, which means recovery will
+        be paused. <literal>promote</> means recovery process will finish and
+        the server will start to accept connections.
+        Finally <literal>shutdown</> will stop the PostgreSQL instance at
+        recovery target.
+       </para>
+        The intended use of <literal>pause</> setting is 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 <function>pg_xlog_replay_resume()</> (See
         <xref linkend="functions-recovery-control-table">), which then
         causes recovery to end. If this recovery target is not the
         desired stopping point, then shutdown the server, change the
@@ -302,6 +329,20 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"'  # Windows
         continue recovery.
        </para>
        <para>
+        The <literal>shutdown</> setting is useful to have instance ready at
+        exact replay point desired.
+        The instance will still be able to replay more WAL records (and in fact
+        will have to replay WAL records since last checkpoint upon next time it is
+        started).
+       </para>
+       <para>
+        Note that because <filename>recovery.conf</> will not be renamed when
+        <varname>action_at_recovery_target</> is set to <literal>shutdown</>,
+        any subsequent start will end with immediate shutdown unless the
+        configuration is changed or the <filename>recovery.conf</> is removed
+        manually.
+       </para>
+       <para>
         This setting has no effect if <xref linkend="guc-hot-standby"> is not
         enabled, or if no recovery target is set.
        </para>
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 3c9aeae..974e6c1 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -227,7 +227,7 @@ static char *recoveryEndCommand = NULL;
 static char *archiveCleanupCommand = NULL;
 static RecoveryTargetType recoveryTarget = RECOVERY_TARGET_UNSET;
 static bool recoveryTargetInclusive = true;
-static bool recoveryPauseAtTarget = true;
+static RecoveryTargetAction actionAtRecoveryTarget = RECOVERY_TARGET_ACTION_PAUSE;
 static TransactionId recoveryTargetXid;
 static TimestampTz recoveryTargetTime;
 static char *recoveryTargetName;
@@ -5068,6 +5068,9 @@ readRecoveryCommandFile(void)
 	ConfigVariable *item,
 			   *head = NULL,
 			   *tail = NULL;
+	bool		recoveryPauseAtTargetSet = false;
+	bool		actionAtRecoveryTargetSet = false;
+
 
 	fd = AllocateFile(RECOVERY_COMMAND_FILE, "r");
 	if (fd == NULL)
@@ -5113,13 +5116,43 @@ readRecoveryCommandFile(void)
 		}
 		else if (strcmp(item->name, "pause_at_recovery_target") == 0)
 		{
+			bool recoveryPauseAtTarget;
+
 			if (!parse_bool(item->value, &recoveryPauseAtTarget))
 				ereport(ERROR,
 						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 						 errmsg("parameter \"%s\" requires a Boolean value", "pause_at_recovery_target")));
+
 			ereport(DEBUG2,
 					(errmsg_internal("pause_at_recovery_target = '%s'",
 									 item->value)));
+
+			actionAtRecoveryTarget = recoveryPauseAtTarget ?
+									 RECOVERY_TARGET_ACTION_PAUSE :
+									 RECOVERY_TARGET_ACTION_PROMOTE;
+
+			recoveryPauseAtTargetSet = true;
+		}
+		else if (strcmp(item->name, "action_at_recovery_target") == 0)
+		{
+			if (strcmp(item->value, "pause") == 0)
+				actionAtRecoveryTarget = RECOVERY_TARGET_ACTION_PAUSE;
+			else if (strcmp(item->value, "promote") == 0)
+				actionAtRecoveryTarget = RECOVERY_TARGET_ACTION_PROMOTE;
+			else if (strcmp(item->value, "shutdown") == 0)
+				actionAtRecoveryTarget = RECOVERY_TARGET_ACTION_SHUTDOWN;
+			else
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+						 errmsg("invalid value for recovery parameter \"%s\"",
+								"action_at_recovery_target"),
+						 errhint("The allowed values are \"pause\", \"promote\" and \"shutdown\".")));
+
+			ereport(DEBUG2,
+					(errmsg_internal("action_at_recovery_target = '%s'",
+									 item->value)));
+
+			actionAtRecoveryTargetSet = true;
 		}
 		else if (strcmp(item->name, "recovery_target_timeline") == 0)
 		{
@@ -5284,6 +5317,18 @@ readRecoveryCommandFile(void)
 							RECOVERY_COMMAND_FILE)));
 	}
 
+	/*
+	 * Check for mutually exclusive parameters
+	 */
+	if (recoveryPauseAtTargetSet && actionAtRecoveryTargetSet)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("cannot set both \"%s\" and \"%s\" recovery parameters",
+						"pause_at_recovery_target",
+						"action_at_recovery_target"),
+				 errhint("The \"pause_at_recovery_target\" is deprecated.")));
+
+
 	/* Enable fetching from archive recovery area */
 	ArchiveRecoveryRequested = true;
 
@@ -6832,7 +6877,8 @@ StartupXLOG(void)
 			 * end of main redo apply loop
 			 */
 
-			if (recoveryPauseAtTarget && reachedStopPoint)
+			if (actionAtRecoveryTarget == RECOVERY_TARGET_ACTION_PAUSE &&
+				reachedStopPoint)
 			{
 				SetRecoveryPause(true);
 				recoveryPausesHere();
@@ -6853,6 +6899,25 @@ StartupXLOG(void)
 				ereport(LOG,
 					 (errmsg("last completed transaction was at log time %s",
 							 timestamptz_to_str(xtime))));
+
+			/*
+			 * Shutdown here when requested. We need to exit this early because
+			 * we want to be able to continue the WAL replay when started
+			 * the next time.
+			 */
+			if (actionAtRecoveryTarget == RECOVERY_TARGET_ACTION_SHUTDOWN &&
+				reachedStopPoint)
+			{
+				ereport(LOG, (errmsg("shutting down at recovery target")));
+				/*
+				 * Note that we exit with status 2 instead of 0 here to force
+				 * postmaster shutdown the whole instance. This produces one
+				 * unnecessary log line, but we don't have better way to
+				 * shutdown postmaster from within single backend.
+				 */
+				proc_exit(2);
+			}
+
 			InRedo = false;
 		}
 		else
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 0ae110f..7e48138 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -179,6 +179,16 @@ typedef enum
 	RECOVERY_TARGET_IMMEDIATE
 } RecoveryTargetType;
 
+/*
+ * Recovery target action.
+ */
+typedef enum
+{
+	RECOVERY_TARGET_ACTION_PAUSE,
+	RECOVERY_TARGET_ACTION_PROMOTE,
+	RECOVERY_TARGET_ACTION_SHUTDOWN,
+} RecoveryTargetAction;
+
 extern XLogRecPtr XactLastRecEnd;
 
 extern bool reachedConsistency;
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to