2013-01-16 20:12:53 +01:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* xlogreader.h
|
|
|
|
* Definitions for the generic XLog reading facility
|
|
|
|
*
|
2014-01-07 22:05:30 +01:00
|
|
|
* Portions Copyright (c) 2013-2014, PostgreSQL Global Development Group
|
2013-01-16 20:12:53 +01:00
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
|
|
|
* src/include/access/xlogreader.h
|
|
|
|
*
|
|
|
|
* NOTES
|
|
|
|
* See the definition of the XLogReaderState struct for instructions on
|
|
|
|
* how to use the XLogReader infrastructure.
|
|
|
|
*
|
|
|
|
* The basic idea is to allocate an XLogReaderState via
|
|
|
|
* XLogReaderAllocate(), and call XLogReadRecord() until it returns NULL.
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#ifndef XLOGREADER_H
|
|
|
|
#define XLOGREADER_H
|
|
|
|
|
|
|
|
#include "access/xlog_internal.h"
|
|
|
|
|
|
|
|
typedef struct XLogReaderState XLogReaderState;
|
|
|
|
|
|
|
|
/* Function type definition for the read_page callback */
|
|
|
|
typedef int (*XLogPageReadCB) (XLogReaderState *xlogreader,
|
|
|
|
XLogRecPtr targetPagePtr,
|
|
|
|
int reqLen,
|
Use the right timeline when beginning to stream from master.
The xlogreader refactoring broke the logic to decide which timeline to start
streaming from. XLogPageRead() uses the timeline history to check which
timeline the requested WAL position falls into. However, after the
refactoring, XLogPageRead() is always first called with the first page in
the segment, to verify the segment header, and only then with the actual WAL
position we're interested in. That first read of the segment's header made
XLogPageRead() to always start streaming from the old timeline containing
the segment header, not the timeline containing the actual record, if there
was a timeline switch within the segment.
I thought I fixed this yesterday, but that fix was too narrow and only fixed
this for the corner-case that the timeline switch happened in the first page
of the segment. To fix this more robustly, pass explicitly the position of
the record we're actually interested in to XLogPageRead, and use that to
decide which timeline to read from, rather than deduce it from the page and
offset.
Per report from Fujii Masao.
2013-01-18 10:41:36 +01:00
|
|
|
XLogRecPtr targetRecPtr,
|
2013-01-16 20:12:53 +01:00
|
|
|
char *readBuf,
|
|
|
|
TimeLineID *pageTLI);
|
|
|
|
|
|
|
|
struct XLogReaderState
|
|
|
|
{
|
|
|
|
/* ----------------------------------------
|
|
|
|
* Public parameters
|
|
|
|
* ----------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Data input callback (mandatory).
|
|
|
|
*
|
|
|
|
* This callback shall read at least reqLen valid bytes of the xlog page
|
|
|
|
* starting at targetPagePtr, and store them in readBuf. The callback
|
|
|
|
* shall return the number of bytes read (never more than XLOG_BLCKSZ), or
|
|
|
|
* -1 on failure. The callback shall sleep, if necessary, to wait for the
|
|
|
|
* requested bytes to become available. The callback will not be invoked
|
|
|
|
* again for the same page unless more than the returned number of bytes
|
Use the right timeline when beginning to stream from master.
The xlogreader refactoring broke the logic to decide which timeline to start
streaming from. XLogPageRead() uses the timeline history to check which
timeline the requested WAL position falls into. However, after the
refactoring, XLogPageRead() is always first called with the first page in
the segment, to verify the segment header, and only then with the actual WAL
position we're interested in. That first read of the segment's header made
XLogPageRead() to always start streaming from the old timeline containing
the segment header, not the timeline containing the actual record, if there
was a timeline switch within the segment.
I thought I fixed this yesterday, but that fix was too narrow and only fixed
this for the corner-case that the timeline switch happened in the first page
of the segment. To fix this more robustly, pass explicitly the position of
the record we're actually interested in to XLogPageRead, and use that to
decide which timeline to read from, rather than deduce it from the page and
offset.
Per report from Fujii Masao.
2013-01-18 10:41:36 +01:00
|
|
|
* are needed.
|
2013-01-16 20:12:53 +01:00
|
|
|
*
|
Use the right timeline when beginning to stream from master.
The xlogreader refactoring broke the logic to decide which timeline to start
streaming from. XLogPageRead() uses the timeline history to check which
timeline the requested WAL position falls into. However, after the
refactoring, XLogPageRead() is always first called with the first page in
the segment, to verify the segment header, and only then with the actual WAL
position we're interested in. That first read of the segment's header made
XLogPageRead() to always start streaming from the old timeline containing
the segment header, not the timeline containing the actual record, if there
was a timeline switch within the segment.
I thought I fixed this yesterday, but that fix was too narrow and only fixed
this for the corner-case that the timeline switch happened in the first page
of the segment. To fix this more robustly, pass explicitly the position of
the record we're actually interested in to XLogPageRead, and use that to
decide which timeline to read from, rather than deduce it from the page and
offset.
Per report from Fujii Masao.
2013-01-18 10:41:36 +01:00
|
|
|
* targetRecPtr is the position of the WAL record we're reading. Usually
|
|
|
|
* it is equal to targetPagePtr + reqLen, but sometimes xlogreader needs
|
|
|
|
* to read and verify the page or segment header, before it reads the
|
|
|
|
* actual WAL record it's interested in. In that case, targetRecPtr can
|
|
|
|
* be used to determine which timeline to read the page from.
|
|
|
|
*
|
|
|
|
* The callback shall set *pageTLI to the TLI of the file the page was
|
|
|
|
* read from. It is currently used only for error reporting purposes, to
|
|
|
|
* reconstruct the name of the WAL file where an error occurred.
|
2013-01-16 20:12:53 +01:00
|
|
|
*/
|
|
|
|
XLogPageReadCB read_page;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* System identifier of the xlog files we're about to read. Set to zero
|
|
|
|
* (the default value) if unknown or unimportant.
|
|
|
|
*/
|
|
|
|
uint64 system_identifier;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Opaque data for callbacks to use. Not used by XLogReader.
|
|
|
|
*/
|
|
|
|
void *private_data;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Start and end point of last record read. EndRecPtr is also used as the
|
|
|
|
* position to read next, if XLogReadRecord receives an invalid recptr.
|
|
|
|
*/
|
|
|
|
XLogRecPtr ReadRecPtr; /* start of last record read */
|
|
|
|
XLogRecPtr EndRecPtr; /* end+1 of last record read */
|
|
|
|
|
|
|
|
/* ----------------------------------------
|
|
|
|
* private/internal state
|
|
|
|
* ----------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Buffer for currently read page (XLOG_BLCKSZ bytes) */
|
|
|
|
char *readBuf;
|
|
|
|
|
|
|
|
/* last read segment, segment offset, read length, TLI */
|
|
|
|
XLogSegNo readSegNo;
|
|
|
|
uint32 readOff;
|
|
|
|
uint32 readLen;
|
|
|
|
TimeLineID readPageTLI;
|
|
|
|
|
|
|
|
/* beginning of last page read, and its TLI */
|
|
|
|
XLogRecPtr latestPagePtr;
|
|
|
|
TimeLineID latestPageTLI;
|
|
|
|
|
Use the right timeline when beginning to stream from master.
The xlogreader refactoring broke the logic to decide which timeline to start
streaming from. XLogPageRead() uses the timeline history to check which
timeline the requested WAL position falls into. However, after the
refactoring, XLogPageRead() is always first called with the first page in
the segment, to verify the segment header, and only then with the actual WAL
position we're interested in. That first read of the segment's header made
XLogPageRead() to always start streaming from the old timeline containing
the segment header, not the timeline containing the actual record, if there
was a timeline switch within the segment.
I thought I fixed this yesterday, but that fix was too narrow and only fixed
this for the corner-case that the timeline switch happened in the first page
of the segment. To fix this more robustly, pass explicitly the position of
the record we're actually interested in to XLogPageRead, and use that to
decide which timeline to read from, rather than deduce it from the page and
offset.
Per report from Fujii Masao.
2013-01-18 10:41:36 +01:00
|
|
|
/* beginning of the WAL record being read. */
|
|
|
|
XLogRecPtr currRecPtr;
|
|
|
|
|
2013-01-16 20:12:53 +01:00
|
|
|
/* Buffer for current ReadRecord result (expandable) */
|
|
|
|
char *readRecordBuf;
|
|
|
|
uint32 readRecordBufSize;
|
|
|
|
|
|
|
|
/* Buffer to hold error message */
|
|
|
|
char *errormsg_buf;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Get a new XLogReader */
|
|
|
|
extern XLogReaderState *XLogReaderAllocate(XLogPageReadCB pagereadfunc,
|
|
|
|
void *private_data);
|
|
|
|
|
|
|
|
/* Free an XLogReader */
|
|
|
|
extern void XLogReaderFree(XLogReaderState *state);
|
|
|
|
|
|
|
|
/* Read the next XLog record. Returns NULL on end-of-WAL or failure */
|
|
|
|
extern struct XLogRecord *XLogReadRecord(XLogReaderState *state,
|
|
|
|
XLogRecPtr recptr, char **errormsg);
|
|
|
|
|
|
|
|
#ifdef FRONTEND
|
|
|
|
extern XLogRecPtr XLogFindNextRecord(XLogReaderState *state, XLogRecPtr RecPtr);
|
|
|
|
#endif /* FRONTEND */
|
|
|
|
|
|
|
|
#endif /* XLOGREADER_H */
|