OSDN Git Service

Fix corner-case bug in tracking of latest removed WAL segment during
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Mon, 1 Nov 2010 07:56:45 +0000 (09:56 +0200)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Mon, 1 Nov 2010 08:05:15 +0000 (10:05 +0200)
streaming replication. We used log/seg 0/0 to indicate that no WAL segments
have been removed since startup, but 0/0 is a valid value for the very first
WAL segment after initdb. To make that disambiguous, store
(latest removed WAL segment + 1) in the global variable.

Per report from Matt Chesler, also reproduced by Greg Smith.

src/backend/access/transam/xlog.c
src/backend/replication/walsender.c

index 6f1fedd..97dced1 100644 (file)
@@ -364,7 +364,7 @@ typedef struct XLogCtlData
        uint32          ckptXidEpoch;   /* nextXID & epoch of latest checkpoint */
        TransactionId ckptXid;
        XLogRecPtr      asyncXactLSN; /* LSN of newest async commit/abort */
-       uint32          lastRemovedLog; /* latest removed/recycled XLOG segment */
+       uint32          lastRemovedLog; /* latest removed/recycled XLOG segment + 1 */
        uint32          lastRemovedSeg;
 
        /* Protected by WALWriteLock: */
@@ -3218,8 +3218,10 @@ PreallocXlogFiles(XLogRecPtr endptr)
 }
 
 /*
- * Get the log/seg of the latest removed or recycled WAL segment.
- * Returns 0 if no WAL segments have been removed since startup.
+ * Get the log/seg of the first WAL segment that has not been removed or
+ * recycled. In other words, the log/seg of the last removed/recycled WAL
+ * segment + 1.
+ * Returns 0/0 if no WAL segments have been removed since startup.
  */
 void
 XLogGetLastRemoved(uint32 *log, uint32 *seg)
@@ -3247,6 +3249,7 @@ UpdateLastRemovedPtr(char *filename)
                                seg;
 
        XLogFromFileName(filename, &tli, &log, &seg);
+       NextLogSeg(log, seg);
 
        SpinLockAcquire(&xlogctl->info_lck);
        if (log > xlogctl->lastRemovedLog ||
index d2b9e5c..3dc794c 100644 (file)
@@ -654,7 +654,7 @@ XLogRead(char *buf, XLogRecPtr recptr, Size nbytes)
        XLogGetLastRemoved(&lastRemovedLog, &lastRemovedSeg);
        XLByteToSeg(startRecPtr, log, seg);
        if (log < lastRemovedLog ||
-               (log == lastRemovedLog && seg <= lastRemovedSeg))
+               (log == lastRemovedLog && seg < lastRemovedSeg))
        {
                char            filename[MAXFNAMELEN];