aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/pg_walinspect/pg_walinspect.c59
-rw-r--r--src/backend/access/transam/xlogutils.c11
-rw-r--r--src/include/access/xlogutils.h6
3 files changed, 50 insertions, 26 deletions
diff --git a/contrib/pg_walinspect/pg_walinspect.c b/contrib/pg_walinspect/pg_walinspect.c
index bf38863ff16..cc33fb65d5c 100644
--- a/contrib/pg_walinspect/pg_walinspect.c
+++ b/contrib/pg_walinspect/pg_walinspect.c
@@ -89,6 +89,7 @@ static XLogReaderState *
InitXLogReaderState(XLogRecPtr lsn, XLogRecPtr *first_record)
{
XLogReaderState *xlogreader;
+ ReadLocalXLogPageNoWaitPrivate *private_data;
/*
* Reading WAL below the first page of the first segments isn't allowed.
@@ -100,11 +101,14 @@ InitXLogReaderState(XLogRecPtr lsn, XLogRecPtr *first_record)
(errmsg("could not read WAL at LSN %X/%X",
LSN_FORMAT_ARGS(lsn))));
+ private_data = (ReadLocalXLogPageNoWaitPrivate *)
+ palloc0(sizeof(ReadLocalXLogPageNoWaitPrivate));
+
xlogreader = XLogReaderAllocate(wal_segment_size, NULL,
XL_ROUTINE(.page_read = &read_local_xlog_page_no_wait,
.segment_open = &wal_segment_open,
.segment_close = &wal_segment_close),
- NULL);
+ private_data);
if (xlogreader == NULL)
ereport(ERROR,
@@ -132,7 +136,8 @@ InitXLogReaderState(XLogRecPtr lsn, XLogRecPtr *first_record)
*
* We guard against ordinary errors trying to read WAL that hasn't been
* written yet by limiting end_lsn to the flushed WAL, but that can also
- * encounter errors if the flush pointer falls in the middle of a record.
+ * encounter errors if the flush pointer falls in the middle of a record. In
+ * that case we'll return NULL.
*/
static XLogRecord *
ReadNextXLogRecord(XLogReaderState *xlogreader, XLogRecPtr first_record)
@@ -144,6 +149,15 @@ ReadNextXLogRecord(XLogReaderState *xlogreader, XLogRecPtr first_record)
if (record == NULL)
{
+ ReadLocalXLogPageNoWaitPrivate *private_data;
+
+ /* return NULL, if end of WAL is reached */
+ private_data = (ReadLocalXLogPageNoWaitPrivate *)
+ xlogreader->private_data;
+
+ if (private_data->end_of_wal)
+ return NULL;
+
if (errormsg)
ereport(ERROR,
(errcode_for_file_access(),
@@ -246,7 +260,11 @@ pg_get_wal_record_info(PG_FUNCTION_ARGS)
xlogreader = InitXLogReaderState(lsn, &first_record);
- (void) ReadNextXLogRecord(xlogreader, first_record);
+ if (!ReadNextXLogRecord(xlogreader, first_record))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("could not read WAL at %X/%X",
+ LSN_FORMAT_ARGS(first_record))));
MemSet(values, 0, sizeof(values));
MemSet(nulls, 0, sizeof(nulls));
@@ -254,6 +272,7 @@ pg_get_wal_record_info(PG_FUNCTION_ARGS)
GetWALRecordInfo(xlogreader, first_record, values, nulls,
PG_GET_WAL_RECORD_INFO_COLS);
+ pfree(xlogreader->private_data);
XLogReaderFree(xlogreader);
tuple = heap_form_tuple(tupdesc, values, nulls);
@@ -327,26 +346,19 @@ GetWALRecordsInfo(FunctionCallInfo fcinfo, XLogRecPtr start_lsn,
MemSet(values, 0, sizeof(values));
MemSet(nulls, 0, sizeof(nulls));
- for (;;)
+ while (ReadNextXLogRecord(xlogreader, first_record) &&
+ xlogreader->EndRecPtr <= end_lsn)
{
- (void) ReadNextXLogRecord(xlogreader, first_record);
-
- if (xlogreader->EndRecPtr <= end_lsn)
- {
- GetWALRecordInfo(xlogreader, xlogreader->currRecPtr, values, nulls,
- PG_GET_WAL_RECORDS_INFO_COLS);
+ GetWALRecordInfo(xlogreader, xlogreader->currRecPtr, values, nulls,
+ PG_GET_WAL_RECORDS_INFO_COLS);
- tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
- values, nulls);
- }
-
- /* if we read up to end_lsn, we're done */
- if (xlogreader->EndRecPtr >= end_lsn)
- break;
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
+ values, nulls);
CHECK_FOR_INTERRUPTS();
}
+ pfree(xlogreader->private_data);
XLogReaderFree(xlogreader);
#undef PG_GET_WAL_RECORDS_INFO_COLS
@@ -555,20 +567,15 @@ GetWalStats(FunctionCallInfo fcinfo, XLogRecPtr start_lsn,
MemSet(&stats, 0, sizeof(stats));
- for (;;)
+ while (ReadNextXLogRecord(xlogreader, first_record) &&
+ xlogreader->EndRecPtr <= end_lsn)
{
- (void) ReadNextXLogRecord(xlogreader, first_record);
-
- if (xlogreader->EndRecPtr <= end_lsn)
- XLogRecStoreStats(&stats, xlogreader);
-
- /* if we read up to end_lsn, we're done */
- if (xlogreader->EndRecPtr >= end_lsn)
- break;
+ XLogRecStoreStats(&stats, xlogreader);
CHECK_FOR_INTERRUPTS();
}
+ pfree(xlogreader->private_data);
XLogReaderFree(xlogreader);
MemSet(values, 0, sizeof(values));
diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 425702641a6..29419c10a88 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -957,7 +957,18 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
/* If asked, let's not wait for future WAL. */
if (!wait_for_wal)
+ {
+ ReadLocalXLogPageNoWaitPrivate *private_data;
+
+ /*
+ * Inform the caller of read_local_xlog_page_no_wait that the
+ * end of WAL has been reached.
+ */
+ private_data = (ReadLocalXLogPageNoWaitPrivate *)
+ state->private_data;
+ private_data->end_of_wal = true;
break;
+ }
CHECK_FOR_INTERRUPTS();
pg_usleep(1000L);
diff --git a/src/include/access/xlogutils.h b/src/include/access/xlogutils.h
index 761625acf44..5fcbbc136f9 100644
--- a/src/include/access/xlogutils.h
+++ b/src/include/access/xlogutils.h
@@ -75,6 +75,12 @@ typedef enum
* need to be replayed) */
} XLogRedoAction;
+/* Private data of the read_local_xlog_page_no_wait callback. */
+typedef struct ReadLocalXLogPageNoWaitPrivate
+{
+ bool end_of_wal; /* true, when end of WAL is reached */
+} ReadLocalXLogPageNoWaitPrivate;
+
extern XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record,
uint8 buffer_id, Buffer *buf);
extern Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id);