diff options
Diffstat (limited to 'src/backend/access/transam/xlogutils.c')
-rw-r--r-- | src/backend/access/transam/xlogutils.c | 212 |
1 files changed, 15 insertions, 197 deletions
diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c index f6ca2b95e51..cb4563ed731 100644 --- a/src/backend/access/transam/xlogutils.c +++ b/src/backend/access/transam/xlogutils.c @@ -19,7 +19,6 @@ #include <unistd.h> -#include "access/timeline.h" #include "access/xlog.h" #include "access/xlog_internal.h" #include "access/xlogutils.h" @@ -660,7 +659,6 @@ XLogRead(char *buf, TimeLineID tli, XLogRecPtr startptr, Size count) /* state maintained across calls */ static int sendFile = -1; static XLogSegNo sendSegNo = 0; - static TimeLineID sendTLI = 0; static uint32 sendOff = 0; p = buf; @@ -676,8 +674,7 @@ XLogRead(char *buf, TimeLineID tli, XLogRecPtr startptr, Size count) startoff = recptr % XLogSegSize; /* Do we need to switch to a different xlog segment? */ - if (sendFile < 0 || !XLByteInSeg(recptr, sendSegNo) || - sendTLI != tli) + if (sendFile < 0 || !XLByteInSeg(recptr, sendSegNo)) { char path[MAXPGPATH]; @@ -704,7 +701,6 @@ XLogRead(char *buf, TimeLineID tli, XLogRecPtr startptr, Size count) path))); } sendOff = 0; - sendTLI = tli; } /* Need to seek in the file? */ @@ -753,147 +749,6 @@ XLogRead(char *buf, TimeLineID tli, XLogRecPtr startptr, Size count) } /* - * Determine XLogReaderState->currTLI and ->currTLIValidUntil; - * XLogReaderState->EndRecPtr, ->currRecPtr and ThisTimeLineID affect the - * decision. This may later be used to determine which xlog segment file to - * open, etc. - * - * We switch to an xlog segment from the new timeline eagerly when on a - * historical timeline, as soon as we reach the start of the xlog segment - * containing the timeline switch. The server copied the segment to the new - * timeline so all the data up to the switch point is the same, but there's no - * guarantee the old segment will still exist. It may have been deleted or - * renamed with a .partial suffix so we can't necessarily keep reading from - * the old TLI even though tliSwitchPoint says it's OK. - * - * Because of this, callers MAY NOT assume that currTLI is the timeline that - * will be in a page's xlp_tli; the page may begin on an older timeline or we - * might be reading from historical timeline data on a segment that's been - * copied to a new timeline. - */ -static void -XLogReadDetermineTimeline(XLogReaderState *state) -{ - /* Read the history on first time through */ - if (state->timelineHistory == NIL) - state->timelineHistory = readTimeLineHistory(ThisTimeLineID); - - /* - * Are we reading the record immediately following the one we read last - * time? If not, then don't use the cached timeline info. - */ - if (state->currRecPtr != state->EndRecPtr) - { - state->currTLI = 0; - state->currTLIValidUntil = InvalidXLogRecPtr; - } - - /* - * Are we reading a timeline that used to be the latest one, but became - * historical? This can happen in a replica that gets promoted, and in a - * cascading replica whose upstream gets promoted. In either case, - * re-read the timeline history data. We cannot read past the timeline - * switch point, because either the records in the old timeline might be - * invalid, or worse, they may valid but *different* from the ones we - * should be reading. - */ - if (state->currTLIValidUntil == InvalidXLogRecPtr && - state->currTLI != ThisTimeLineID && - state->currTLI != 0) - { - /* re-read timeline history */ - list_free_deep(state->timelineHistory); - state->timelineHistory = readTimeLineHistory(ThisTimeLineID); - - elog(DEBUG2, "timeline %u became historical during decoding", - state->currTLI); - - /* then invalidate the cached timeline info */ - state->currTLI = 0; - state->currTLIValidUntil = InvalidXLogRecPtr; - } - - /* - * Are we reading a record immediately following a timeline switch? If - * so, we must follow the switch too. - */ - if (state->currRecPtr == state->EndRecPtr && - state->currTLI != 0 && - state->currTLIValidUntil != InvalidXLogRecPtr && - state->currRecPtr >= state->currTLIValidUntil) - { - elog(DEBUG2, - "requested record %X/%X is on segment containing end of timeline %u valid until %X/%X, switching to next timeline", - (uint32) (state->currRecPtr >> 32), - (uint32) state->currRecPtr, - state->currTLI, - (uint32) (state->currTLIValidUntil >> 32), - (uint32) (state->currTLIValidUntil)); - - /* invalidate TLI info so we look up the next TLI */ - state->currTLI = 0; - state->currTLIValidUntil = InvalidXLogRecPtr; - } - - if (state->currTLI == 0) - { - /* - * Something changed; work out what timeline this record is on. We - * might read it from the segment on this TLI or, if the segment is - * also contained by newer timelines, the copy from a newer TLI. - */ - state->currTLI = tliOfPointInHistory(state->currRecPtr, - state->timelineHistory); - - /* - * Look for the most recent timeline that's on the same xlog segment - * as this record, since that's the only one we can assume is still - * readable. - */ - while (state->currTLI != ThisTimeLineID && - state->currTLIValidUntil == InvalidXLogRecPtr) - { - XLogRecPtr tliSwitch; - TimeLineID nextTLI; - - CHECK_FOR_INTERRUPTS(); - - tliSwitch = tliSwitchPoint(state->currTLI, state->timelineHistory, - &nextTLI); - - /* round ValidUntil down to start of seg containing the switch */ - state->currTLIValidUntil = - ((tliSwitch / XLogSegSize) * XLogSegSize); - - if (state->currRecPtr >= state->currTLIValidUntil) - { - /* - * The new currTLI ends on this WAL segment so check the next - * TLI to see if it's the last one on the segment. - * - * If that's the current TLI we'll stop searching. - */ - state->currTLI = nextTLI; - state->currTLIValidUntil = InvalidXLogRecPtr; - } - } - - /* - * We're now either reading from the first xlog segment in the current - * server's timeline or the most recent historical timeline that - * exists on the target segment. - */ - elog(DEBUG2, "XLog read ptr %X/%X is on segment with TLI %u valid until %X/%X, server current TLI is %u", - (uint32) (state->currRecPtr >> 32), - (uint32) state->currRecPtr, - state->currTLI, - (uint32) (state->currTLIValidUntil >> 32), - (uint32) (state->currTLIValidUntil), - ThisTimeLineID); - } -} - -/* * read_page callback for reading local xlog files * * Public because it would likely be very helpful for someone writing another @@ -914,65 +769,28 @@ read_local_xlog_page(XLogReaderState *state, XLogRecPtr targetPagePtr, int count; loc = targetPagePtr + reqLen; - - /* Make sure enough xlog is available... */ while (1) { /* - * Check which timeline to get the record from. - * - * We have to do it each time through the loop because if we're in - * recovery as a cascading standby, the current timeline might've - * become historical. + * TODO: we're going to have to do something more intelligent about + * timelines on standbys. Use readTimeLineHistory() and + * tliOfPointInHistory() to get the proper LSN? For now we'll catch + * that case earlier, but the code and TODO is left in here for when + * that changes. */ - XLogReadDetermineTimeline(state); - - if (state->currTLI == ThisTimeLineID) + if (!RecoveryInProgress()) { - /* - * We're reading from the current timeline so we might have to - * wait for the desired record to be generated (or, for a standby, - * received & replayed) - */ - if (!RecoveryInProgress()) - { - *pageTLI = ThisTimeLineID; - read_upto = GetFlushRecPtr(); - } - else - read_upto = GetXLogReplayRecPtr(pageTLI); - - if (loc <= read_upto) - break; - - CHECK_FOR_INTERRUPTS(); - pg_usleep(1000L); + *pageTLI = ThisTimeLineID; + read_upto = GetFlushRecPtr(); } else - { - /* - * We're on a historical timeline, so limit reading to the switch - * point where we moved to the next timeline. - * - * We don't need to GetFlushRecPtr or GetXLogReplayRecPtr. We know - * about the new timeline, so we must've received past the end of - * it. - */ - read_upto = state->currTLIValidUntil; - - /* - * Setting pageTLI to our wanted record's TLI is slightly wrong; - * the page might begin on an older timeline if it contains a - * timeline switch, since its xlog segment will have been copied - * from the prior timeline. This is pretty harmless though, as - * nothing cares so long as the timeline doesn't go backwards. We - * should read the page header instead; FIXME someday. - */ - *pageTLI = state->currTLI; - - /* No need to wait on a historical timeline */ + read_upto = GetXLogReplayRecPtr(pageTLI); + + if (loc <= read_upto) break; - } + + CHECK_FOR_INTERRUPTS(); + pg_usleep(1000L); } if (targetPagePtr + XLOG_BLCKSZ <= read_upto) |