diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/access/transam/xlogfuncs.c | 31 | ||||
-rw-r--r-- | src/backend/access/transam/xlogwait.c | 33 | ||||
-rw-r--r-- | src/include/access/xlogwait.h | 13 | ||||
-rw-r--r-- | src/tools/pgindent/typedefs.list | 1 |
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 |