aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/transam/xlogfuncs.c31
-rw-r--r--src/backend/access/transam/xlogwait.c33
-rw-r--r--src/include/access/xlogwait.h13
-rw-r--r--src/tools/pgindent/typedefs.list1
4 files changed, 54 insertions, 24 deletions
diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c
index cbf84ef7d8f..ddca78d3717 100644
--- a/src/backend/access/transam/xlogfuncs.c
+++ b/src/backend/access/transam/xlogfuncs.c
@@ -759,6 +759,7 @@ pg_wal_replay_wait(PG_FUNCTION_ARGS)
{
XLogRecPtr target_lsn = PG_GETARG_LSN(0);
int64 timeout = PG_GETARG_INT64(1);
+ WaitLSNResult result;
if (timeout < 0)
ereport(ERROR,
@@ -799,7 +800,35 @@ pg_wal_replay_wait(PG_FUNCTION_ARGS)
*/
Assert(MyProc->xmin == InvalidTransactionId);
- (void) WaitForLSNReplay(target_lsn, timeout);
+ result = WaitForLSNReplay(target_lsn, timeout);
+
+ /*
+ * Process the result of WaitForLSNReplay(). Throw appropriate error if
+ * needed.
+ */
+ switch (result)
+ {
+ case WAIT_LSN_RESULT_SUCCESS:
+ /* Nothing to do on success */
+ break;
+
+ case WAIT_LSN_RESULT_TIMEOUT:
+ ereport(ERROR,
+ (errcode(ERRCODE_QUERY_CANCELED),
+ errmsg("timed out while waiting for target LSN %X/%X to be replayed; current replay LSN %X/%X",
+ LSN_FORMAT_ARGS(target_lsn),
+ LSN_FORMAT_ARGS(GetXLogReplayRecPtr(NULL)))));
+ break;
+
+ case WAIT_LSN_RESULT_NOT_IN_RECOVERY:
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("recovery is not in progress"),
+ errdetail("Recovery ended before replaying target LSN %X/%X; last replay LSN %X/%X.",
+ LSN_FORMAT_ARGS(target_lsn),
+ LSN_FORMAT_ARGS(GetXLogReplayRecPtr(NULL)))));
+ break;
+ }
PG_RETURN_VOID();
}
diff --git a/src/backend/access/transam/xlogwait.c b/src/backend/access/transam/xlogwait.c
index 353b7854dc8..58fb10aa5a8 100644
--- a/src/backend/access/transam/xlogwait.c
+++ b/src/backend/access/transam/xlogwait.c
@@ -217,7 +217,7 @@ WaitLSNCleanup(void)
* Wait using MyLatch till the given LSN is replayed, the postmaster dies or
* timeout happens.
*/
-void
+WaitLSNResult
WaitForLSNReplay(XLogRecPtr targetLSN, int64 timeout)
{
XLogRecPtr currentLSN;
@@ -240,17 +240,14 @@ WaitForLSNReplay(XLogRecPtr targetLSN, int64 timeout)
* check the last replay LSN before reporting an error.
*/
if (targetLSN <= GetXLogReplayRecPtr(NULL))
- return;
- ereport(ERROR,
- (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- errmsg("recovery is not in progress"),
- errhint("Waiting for LSN can only be executed during recovery.")));
+ return WAIT_LSN_RESULT_SUCCESS;
+ return WAIT_LSN_RESULT_NOT_IN_RECOVERY;
}
else
{
/* If target LSN is already replayed, exit immediately */
if (targetLSN <= GetXLogReplayRecPtr(NULL))
- return;
+ return WAIT_LSN_RESULT_SUCCESS;
}
if (timeout > 0)
@@ -276,17 +273,13 @@ WaitForLSNReplay(XLogRecPtr targetLSN, int64 timeout)
{
/*
* Recovery was ended, but recheck if target LSN was already
- * replayed.
+ * replayed. See the comment regarding deleteLSNWaiter() below.
*/
+ deleteLSNWaiter();
currentLSN = GetXLogReplayRecPtr(NULL);
if (targetLSN <= currentLSN)
- return;
- ereport(ERROR,
- (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- errmsg("recovery is not in progress"),
- errdetail("Recovery ended before replaying target LSN %X/%X; last replay LSN %X/%X.",
- LSN_FORMAT_ARGS(targetLSN),
- LSN_FORMAT_ARGS(currentLSN))));
+ return WAIT_LSN_RESULT_SUCCESS;
+ return WAIT_LSN_RESULT_NOT_IN_RECOVERY;
}
else
{
@@ -338,11 +331,7 @@ WaitForLSNReplay(XLogRecPtr targetLSN, int64 timeout)
* If we didn't reach the target LSN, we must be exited by timeout.
*/
if (targetLSN > currentLSN)
- {
- ereport(ERROR,
- (errcode(ERRCODE_QUERY_CANCELED),
- errmsg("timed out while waiting for target LSN %X/%X to be replayed; current replay LSN %X/%X",
- LSN_FORMAT_ARGS(targetLSN),
- LSN_FORMAT_ARGS(currentLSN))));
- }
+ return WAIT_LSN_RESULT_TIMEOUT;
+
+ return WAIT_LSN_RESULT_SUCCESS;
}
diff --git a/src/include/access/xlogwait.h b/src/include/access/xlogwait.h
index 31e208cb7ad..eb2260aa2ec 100644
--- a/src/include/access/xlogwait.h
+++ b/src/include/access/xlogwait.h
@@ -70,12 +70,23 @@ typedef struct WaitLSNState
WaitLSNProcInfo procInfos[FLEXIBLE_ARRAY_MEMBER];
} WaitLSNState;
+/*
+ * Result statuses for WaitForLSNReplay().
+ */
+typedef enum
+{
+ WAIT_LSN_RESULT_SUCCESS, /* Target LSN is reached */
+ WAIT_LSN_RESULT_TIMEOUT, /* Timeout occurred */
+ WAIT_LSN_RESULT_NOT_IN_RECOVERY, /* Recovery ended before or during our
+ * wait */
+} WaitLSNResult;
+
extern PGDLLIMPORT WaitLSNState *waitLSNState;
extern Size WaitLSNShmemSize(void);
extern void WaitLSNShmemInit(void);
extern void WaitLSNSetLatches(XLogRecPtr currentLSN);
extern void WaitLSNCleanup(void);
-extern void WaitForLSNReplay(XLogRecPtr targetLSN, int64 timeout);
+extern WaitLSNResult WaitForLSNReplay(XLogRecPtr targetLSN, int64 timeout);
#endif /* XLOG_WAIT_H */
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 4b8139c4b47..110089695e1 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -3126,6 +3126,7 @@ WaitEventIPC
WaitEventSet
WaitEventTimeout
WaitLSNProcInfo
+WaitLSNResult
WaitLSNState
WaitPMResult
WalCloseMethod