From 84b211ad56506ea1b9517a71ec3fb4010936e4da Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@otacoo.com>
Date: Tue, 23 Aug 2016 16:28:05 +0900
Subject: [PATCH 2/2] Introduce error callback when parsing recovery.conf

At the moment an error occurs when recovery.conf is parsed, generate
a context message related to the parameter used, as follows:
CONTEXT:  line 11 of configuration file "recovery.conf", parameter foo

This is useful to understand from where a parsing failure is coming in
recovery.conf, particularly for parameters like recovery_target_time and
recovery_target_lsn that do not have recovery-specific error messages.
---
 src/backend/access/transam/xlog.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 4bb4485..4496f26 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -4935,6 +4935,20 @@ str_time(pg_time_t tnow)
 }
 
 /*
+ * error context callback for parsing of recovery.conf
+ *
+ * The argument for the error context must be of type ConfigVariable.
+ */
+static void
+readRecoveryErrorCallback(void *arg)
+{
+	ConfigVariable   *item = (ConfigVariable *) arg;
+
+	errcontext("line %d of configuration file \"%s\", parameter \"%s\"",
+			   item->sourceline, item->filename, item->name);
+}
+
+/*
  * See if there is a recovery command file (recovery.conf), and if so
  * read in parameters for archive recovery and XLOG streaming.
  *
@@ -4950,6 +4964,7 @@ readRecoveryCommandFile(void)
 			   *head = NULL,
 			   *tail = NULL;
 	bool		recoveryTargetActionSet = false;
+	ErrorContextCallback errcallback;
 
 
 	fd = AllocateFile(RECOVERY_COMMAND_FILE, "r");
@@ -4971,8 +4986,15 @@ readRecoveryCommandFile(void)
 
 	FreeFile(fd);
 
+	/* set up callback to identify file parsing information on failure */
+	errcallback.callback = readRecoveryErrorCallback;
+	errcallback.previous = error_context_stack;
+	error_context_stack = &errcallback;
+
 	for (item = head; item; item = item->next)
 	{
+		errcallback.arg = (void *) item;
+
 		if (strcmp(item->name, "restore_command") == 0)
 		{
 			recoveryRestoreCommand = pstrdup(item->value);
@@ -5179,6 +5201,9 @@ readRecoveryCommandFile(void)
 							item->name)));
 	}
 
+	/* Done, clean up */
+	error_context_stack = errcallback.previous;
+
 	/*
 	 * Check for compulsory parameters
 	 */
-- 
2.9.3

