Move log_newpage and log_newpage_buffer to xlog.c.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Thu, 31 Jul 2014 13:48:43 +0000 (16:48 +0300)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Thu, 31 Jul 2014 13:48:55 +0000 (16:48 +0300)
log_newpage is used by many indexams, in addition to heap, but for
historical reasons it's always been part of the heapam rmgr. Starting with
9.3, we have another WAL record type for logging an image of a page,
XLOG_FPI. Simplify things by moving log_newpage and log_newpage_buffer to
xlog.c, and switch to using the XLOG_FPI record type.

Bump the WAL version number because the code to replay the old HEAP_NEWPAGE
records is removed.

15 files changed:
src/backend/access/gin/gindatapage.c
src/backend/access/gin/gininsert.c
src/backend/access/gin/ginxlog.c
src/backend/access/gist/gist.c
src/backend/access/heap/heapam.c
src/backend/access/nbtree/nbtree.c
src/backend/access/nbtree/nbtsort.c
src/backend/access/rmgrdesc/heapdesc.c
src/backend/access/spgist/spginsert.c
src/backend/access/transam/xlog.c
src/backend/commands/tablecmds.c
src/backend/replication/logical/decode.c
src/include/access/heapam_xlog.h
src/include/access/xlog.h
src/include/access/xlog_internal.h

index 272a9ca7c09db884e6fd2a7ff38d9d578bfb8e03..5b7c49654c65d95626b2edd84d8b673810165bd5 100644 (file)
@@ -15,7 +15,6 @@
 #include "postgres.h"
 
 #include "access/gin_private.h"
-#include "access/heapam_xlog.h"
 #include "lib/ilist.h"
 #include "miscadmin.h"
 #include "utils/memutils.h"
index b27cae3aab2d342935fbb8ba80f3ddbb2d04a478..2fbd1bf5e47d1037da7ca3d7a9e05d870c6bc32d 100644 (file)
@@ -15,7 +15,6 @@
 #include "postgres.h"
 
 #include "access/gin_private.h"
-#include "access/heapam_xlog.h"
 #include "catalog/index.h"
 #include "miscadmin.h"
 #include "storage/bufmgr.h"
index 7f93ce6526fecea4c01833b86b93bfc6d0226453..ffabf4e259425039d4b647796e1bb48950079fca 100644 (file)
@@ -558,7 +558,8 @@ ginRedoSplit(XLogRecPtr lsn, XLogRecord *record)
 }
 
 /*
- * This is functionally the same as heap_xlog_newpage.
+ * VACUUM_PAGE record contains simply a full image of the page, similar to
+ * a XLOG_FPI record.
  */
 static void
 ginRedoVacuumPage(XLogRecPtr lsn, XLogRecord *record)
index e6f06c29e51de05dc488ed263e050f43bc2bcd0b..f4eb246c91a74bd0a32d533bd94bc3ede596878d 100644 (file)
@@ -16,7 +16,6 @@
 
 #include "access/genam.h"
 #include "access/gist_private.h"
-#include "access/heapam_xlog.h"
 #include "catalog/index.h"
 #include "catalog/pg_collation.h"
 #include "miscadmin.h"
index 21e76d6a2a91edc2fcc836ff2bd4d3f42dc997ad..d731f988b804d5f0f8c9c32b86b4d8c0a2d12859 100644 (file)
@@ -6921,133 +6921,6 @@ log_heap_update(Relation reln, Buffer oldbuf,
        return recptr;
 }
 
-/*
- * Perform XLogInsert of a HEAP_NEWPAGE record to WAL. Caller is responsible
- * for writing the page to disk after calling this routine.
- *
- * Note: If you're using this function, you should be building pages in private
- * memory and writing them directly to smgr.  If you're using buffers, call
- * log_newpage_buffer instead.
- *
- * If the page follows the standard page layout, with a PageHeader and unused
- * space between pd_lower and pd_upper, set 'page_std' to TRUE. That allows
- * the unused space to be left out from the WAL record, making it smaller.
- */
-XLogRecPtr
-log_newpage(RelFileNode *rnode, ForkNumber forkNum, BlockNumber blkno,
-                       Page page, bool page_std)
-{
-       xl_heap_newpage xlrec;
-       XLogRecPtr      recptr;
-       XLogRecData rdata[3];
-
-       /*
-        * Note: the NEWPAGE log record is used for both heaps and indexes, so do
-        * not do anything that assumes we are touching a heap.
-        */
-
-       /* NO ELOG(ERROR) from here till newpage op is logged */
-       START_CRIT_SECTION();
-
-       xlrec.node = *rnode;
-       xlrec.forknum = forkNum;
-       xlrec.blkno = blkno;
-
-       if (page_std)
-       {
-               /* Assume we can omit data between pd_lower and pd_upper */
-               uint16          lower = ((PageHeader) page)->pd_lower;
-               uint16          upper = ((PageHeader) page)->pd_upper;
-
-               if (lower >= SizeOfPageHeaderData &&
-                       upper > lower &&
-                       upper <= BLCKSZ)
-               {
-                       xlrec.hole_offset = lower;
-                       xlrec.hole_length = upper - lower;
-               }
-               else
-               {
-                       /* No "hole" to compress out */
-                       xlrec.hole_offset = 0;
-                       xlrec.hole_length = 0;
-               }
-       }
-       else
-       {
-               /* Not a standard page header, don't try to eliminate "hole" */
-               xlrec.hole_offset = 0;
-               xlrec.hole_length = 0;
-       }
-
-       rdata[0].data = (char *) &xlrec;
-       rdata[0].len = SizeOfHeapNewpage;
-       rdata[0].buffer = InvalidBuffer;
-       rdata[0].next = &(rdata[1]);
-
-       if (xlrec.hole_length == 0)
-       {
-               rdata[1].data = (char *) page;
-               rdata[1].len = BLCKSZ;
-               rdata[1].buffer = InvalidBuffer;
-               rdata[1].next = NULL;
-       }
-       else
-       {
-               /* must skip the hole */
-               rdata[1].data = (char *) page;
-               rdata[1].len = xlrec.hole_offset;
-               rdata[1].buffer = InvalidBuffer;
-               rdata[1].next = &rdata[2];
-
-               rdata[2].data = (char *) page + (xlrec.hole_offset + xlrec.hole_length);
-               rdata[2].len = BLCKSZ - (xlrec.hole_offset + xlrec.hole_length);
-               rdata[2].buffer = InvalidBuffer;
-               rdata[2].next = NULL;
-       }
-
-       recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_NEWPAGE, rdata);
-
-       /*
-        * The page may be uninitialized. If so, we can't set the LSN because that
-        * would corrupt the page.
-        */
-       if (!PageIsNew(page))
-       {
-               PageSetLSN(page, recptr);
-       }
-
-       END_CRIT_SECTION();
-
-       return recptr;
-}
-
-/*
- * Perform XLogInsert of a HEAP_NEWPAGE record to WAL.
- *
- * Caller should initialize the buffer and mark it dirty before calling this
- * function.  This function will set the page LSN and TLI.
- *
- * If the page follows the standard page layout, with a PageHeader and unused
- * space between pd_lower and pd_upper, set 'page_std' to TRUE. That allows
- * the unused space to be left out from the WAL record, making it smaller.
- */
-XLogRecPtr
-log_newpage_buffer(Buffer buffer, bool page_std)
-{
-       Page            page = BufferGetPage(buffer);
-       RelFileNode rnode;
-       ForkNumber      forkNum;
-       BlockNumber blkno;
-
-       /* Shared buffers should be modified in a critical section. */
-       Assert(CritSectionCount > 0);
-
-       BufferGetTag(buffer, &rnode, &forkNum, &blkno);
-
-       return log_newpage(&rnode, forkNum, blkno, page, page_std);
-}
-
 /*
  * Perform XLogInsert of a XLOG_HEAP2_NEW_CID record
  *
@@ -7515,56 +7388,6 @@ heap_xlog_freeze_page(XLogRecPtr lsn, XLogRecord *record)
        UnlockReleaseBuffer(buffer);
 }
 
-static void
-heap_xlog_newpage(XLogRecPtr lsn, XLogRecord *record)
-{
-       xl_heap_newpage *xlrec = (xl_heap_newpage *) XLogRecGetData(record);
-       char       *blk = ((char *) xlrec) + sizeof(xl_heap_newpage);
-       Buffer          buffer;
-       Page            page;
-
-       /* Backup blocks are not used in newpage records */
-       Assert(!(record->xl_info & XLR_BKP_BLOCK_MASK));
-
-       Assert(record->xl_len == SizeOfHeapNewpage + BLCKSZ - xlrec->hole_length);
-
-       /*
-        * Note: the NEWPAGE log record is used for both heaps and indexes, so do
-        * not do anything that assumes we are touching a heap.
-        */
-       buffer = XLogReadBufferExtended(xlrec->node, xlrec->forknum, xlrec->blkno,
-                                                                       RBM_ZERO);
-       Assert(BufferIsValid(buffer));
-       LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
-       page = (Page) BufferGetPage(buffer);
-
-       if (xlrec->hole_length == 0)
-       {
-               memcpy((char *) page, blk, BLCKSZ);
-       }
-       else
-       {
-               memcpy((char *) page, blk, xlrec->hole_offset);
-               /* must zero-fill the hole */
-               MemSet((char *) page + xlrec->hole_offset, 0, xlrec->hole_length);
-               memcpy((char *) page + (xlrec->hole_offset + xlrec->hole_length),
-                          blk + xlrec->hole_offset,
-                          BLCKSZ - (xlrec->hole_offset + xlrec->hole_length));
-       }
-
-       /*
-        * The page may be uninitialized. If so, we can't set the LSN because that
-        * would corrupt the page.
-        */
-       if (!PageIsNew(page))
-       {
-               PageSetLSN(page, lsn);
-       }
-
-       MarkBufferDirty(buffer);
-       UnlockReleaseBuffer(buffer);
-}
-
 /*
  * Given an "infobits" field from an XLog record, set the correct bits in the
  * given infomask and infomask2 for the tuple touched by the record.
@@ -8421,9 +8244,6 @@ heap_redo(XLogRecPtr lsn, XLogRecord *record)
                case XLOG_HEAP_HOT_UPDATE:
                        heap_xlog_update(lsn, record, true);
                        break;
-               case XLOG_HEAP_NEWPAGE:
-                       heap_xlog_newpage(lsn, record);
-                       break;
                case XLOG_HEAP_LOCK:
                        heap_xlog_lock(lsn, record);
                        break;
index 89a98270798e14b95cfe8a8b8efc239030954791..117b18e59051cc4b7b45a78532c6c00910ba4680 100644 (file)
@@ -18,7 +18,6 @@
  */
 #include "postgres.h"
 
-#include "access/heapam_xlog.h"
 #include "access/nbtree.h"
 #include "access/relscan.h"
 #include "catalog/index.h"
index 048b215118642837c76e8cc2d06b1b6cb6ebc52e..e8a89d24ae5abbf732d6b320c12b0d1c64b35c7f 100644 (file)
@@ -66,7 +66,6 @@
 
 #include "postgres.h"
 
-#include "access/heapam_xlog.h"
 #include "access/nbtree.h"
 #include "miscadmin.h"
 #include "storage/smgr.h"
index 7df18fa2d2cf4a7ea57324a046e42ea19b9f1248..24b6f92bd55c24341ec6c621a1edf76d4d67b90c 100644 (file)
@@ -98,15 +98,6 @@ heap_desc(StringInfo buf, XLogRecord *record)
                                                 ItemPointerGetOffsetNumber(&(xlrec->newtid)),
                                                 xlrec->new_xmax);
        }
-       else if (info == XLOG_HEAP_NEWPAGE)
-       {
-               xl_heap_newpage *xlrec = (xl_heap_newpage *) rec;
-
-               appendStringInfo(buf, "newpage: rel %u/%u/%u; fork %u, blk %u",
-                                                xlrec->node.spcNode, xlrec->node.dbNode,
-                                                xlrec->node.relNode, xlrec->forknum,
-                                                xlrec->blkno);
-       }
        else if (info == XLOG_HEAP_LOCK)
        {
                xl_heap_lock *xlrec = (xl_heap_lock *) rec;
index a4408f03bd365d4784858d5df6a6524a0f8a543a..7c104f49cc8855c000a9a84aaf8e3f996099e039 100644 (file)
@@ -17,7 +17,6 @@
 #include "postgres.h"
 
 #include "access/genam.h"
-#include "access/heapam_xlog.h"
 #include "access/spgist_private.h"
 #include "catalog/index.h"
 #include "miscadmin.h"
index fe184bde3b97338aca07af94fdf91313ea52ec1b..34f2fc0e21b774b6f6c8b27ea139262e9cb9c77d 100644 (file)
@@ -4084,7 +4084,14 @@ RestoreBackupBlockContents(XLogRecPtr lsn, BkpBlock bkpb, char *blk,
         * reset it here since it will be set before being written.
         */
 
-       PageSetLSN(page, lsn);
+       /*
+        * The page may be uninitialized. If so, we can't set the LSN because that
+        * would corrupt the page.
+        */
+       if (!PageIsNew(page))
+       {
+               PageSetLSN(page, lsn);
+       }
        MarkBufferDirty(buffer);
 
        if (!keep_buffer)
@@ -8988,6 +8995,128 @@ XLogSaveBufferForHint(Buffer buffer, bool buffer_std)
        return recptr;
 }
 
+/*
+ * Write a WAL record containing a full image of a page. Caller is responsible
+ * for writing the page to disk after calling this routine.
+ *
+ * Note: If you're using this function, you should be building pages in private
+ * memory and writing them directly to smgr.  If you're using buffers, call
+ * log_newpage_buffer instead.
+ *
+ * If the page follows the standard page layout, with a PageHeader and unused
+ * space between pd_lower and pd_upper, set 'page_std' to TRUE. That allows
+ * the unused space to be left out from the WAL record, making it smaller.
+ */
+XLogRecPtr
+log_newpage(RelFileNode *rnode, ForkNumber forkNum, BlockNumber blkno,
+                       Page page, bool page_std)
+{
+       BkpBlock        bkpb;
+       XLogRecPtr      recptr;
+       XLogRecData rdata[3];
+
+       /* NO ELOG(ERROR) from here till newpage op is logged */
+       START_CRIT_SECTION();
+
+       bkpb.node = *rnode;
+       bkpb.fork = forkNum;
+       bkpb.block = blkno;
+
+       if (page_std)
+       {
+               /* Assume we can omit data between pd_lower and pd_upper */
+               uint16          lower = ((PageHeader) page)->pd_lower;
+               uint16          upper = ((PageHeader) page)->pd_upper;
+
+               if (lower >= SizeOfPageHeaderData &&
+                       upper > lower &&
+                       upper <= BLCKSZ)
+               {
+                       bkpb.hole_offset = lower;
+                       bkpb.hole_length = upper - lower;
+               }
+               else
+               {
+                       /* No "hole" to compress out */
+                       bkpb.hole_offset = 0;
+                       bkpb.hole_length = 0;
+               }
+       }
+       else
+       {
+               /* Not a standard page header, don't try to eliminate "hole" */
+               bkpb.hole_offset = 0;
+               bkpb.hole_length = 0;
+       }
+
+       rdata[0].data = (char *) &bkpb;
+       rdata[0].len = sizeof(BkpBlock);
+       rdata[0].buffer = InvalidBuffer;
+       rdata[0].next = &(rdata[1]);
+
+       if (bkpb.hole_length == 0)
+       {
+               rdata[1].data = (char *) page;
+               rdata[1].len = BLCKSZ;
+               rdata[1].buffer = InvalidBuffer;
+               rdata[1].next = NULL;
+       }
+       else
+       {
+               /* must skip the hole */
+               rdata[1].data = (char *) page;
+               rdata[1].len = bkpb.hole_offset;
+               rdata[1].buffer = InvalidBuffer;
+               rdata[1].next = &rdata[2];
+
+               rdata[2].data = (char *) page + (bkpb.hole_offset + bkpb.hole_length);
+               rdata[2].len = BLCKSZ - (bkpb.hole_offset + bkpb.hole_length);
+               rdata[2].buffer = InvalidBuffer;
+               rdata[2].next = NULL;
+       }
+
+       recptr = XLogInsert(RM_XLOG_ID, XLOG_FPI, rdata);
+
+       /*
+        * The page may be uninitialized. If so, we can't set the LSN because that
+        * would corrupt the page.
+        */
+       if (!PageIsNew(page))
+       {
+               PageSetLSN(page, recptr);
+       }
+
+       END_CRIT_SECTION();
+
+       return recptr;
+}
+
+/*
+ * Write a WAL record containing a full image of a page.
+ *
+ * Caller should initialize the buffer and mark it dirty before calling this
+ * function.  This function will set the page LSN.
+ *
+ * If the page follows the standard page layout, with a PageHeader and unused
+ * space between pd_lower and pd_upper, set 'page_std' to TRUE. That allows
+ * the unused space to be left out from the WAL record, making it smaller.
+ */
+XLogRecPtr
+log_newpage_buffer(Buffer buffer, bool page_std)
+{
+       Page            page = BufferGetPage(buffer);
+       RelFileNode rnode;
+       ForkNumber      forkNum;
+       BlockNumber blkno;
+
+       /* Shared buffers should be modified in a critical section. */
+       Assert(CritSectionCount > 0);
+
+       BufferGetTag(buffer, &rnode, &forkNum, &blkno);
+
+       return log_newpage(&rnode, forkNum, blkno, page, page_std);
+}
+
 /*
  * Check if any of the GUC parameters that are critical for hot standby
  * have changed, and update the value in pg_control file if necessary.
index 5dc4d18b6a5a63b26244fe27e4c0a649306f830e..158c594a848b088e6113b3e5483f6158c370a92c 100644 (file)
@@ -16,7 +16,6 @@
 
 #include "access/genam.h"
 #include "access/heapam.h"
-#include "access/heapam_xlog.h"
 #include "access/multixact.h"
 #include "access/reloptions.h"
 #include "access/relscan.h"
index 8f8732afdce28099d28c5a3a2cafe79fb8c8a96b..9f1b20e04abc77496c5a0f6b265209fb2ff74303 100644 (file)
@@ -435,14 +435,6 @@ DecodeHeapOp(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
                                DecodeDelete(ctx, buf);
                        break;
 
-               case XLOG_HEAP_NEWPAGE:
-
-                       /*
-                        * This is only used in places like indexams and CLUSTER which
-                        * don't contain changes relevant for logical replication.
-                        */
-                       break;
-
                case XLOG_HEAP_INPLACE:
 
                        /*
index e964ecce46117633a923d3aed128e77fb5902ebc..254434773ed9c59c1fdb7e0c808232e04d387532 100644 (file)
@@ -32,7 +32,7 @@
 #define XLOG_HEAP_UPDATE               0x20
 /* 0x030 is free, was XLOG_HEAP_MOVE */
 #define XLOG_HEAP_HOT_UPDATE   0x40
-#define XLOG_HEAP_NEWPAGE              0x50
+/* 0x050 is free, was XLOG_HEAP_NEWPAGE */
 #define XLOG_HEAP_LOCK                 0x60
 #define XLOG_HEAP_INPLACE              0x70
 
@@ -239,20 +239,6 @@ typedef struct xl_heap_cleanup_info
 
 #define SizeOfHeapCleanupInfo (sizeof(xl_heap_cleanup_info))
 
-/* This is for replacing a page's contents in toto */
-/* NB: this is used for indexes as well as heaps */
-typedef struct xl_heap_newpage
-{
-       RelFileNode node;
-       ForkNumber      forknum;
-       BlockNumber blkno;                      /* location of new page */
-       uint16          hole_offset;    /* number of bytes before "hole" */
-       uint16          hole_length;    /* number of bytes in "hole" */
-       /* entire page contents (minus the hole) follow at end of record */
-} xl_heap_newpage;
-
-#define SizeOfHeapNewpage      (offsetof(xl_heap_newpage, hole_length) + sizeof(uint16))
-
 /* flags for infobits_set */
 #define XLHL_XMAX_IS_MULTI             0x01
 #define XLHL_XMAX_LOCK_ONLY            0x02
@@ -393,8 +379,5 @@ extern void heap_execute_freeze_tuple(HeapTupleHeader tuple,
                                                  xl_heap_freeze_tuple *xlrec_tp);
 extern XLogRecPtr log_heap_visible(RelFileNode rnode, Buffer heap_buffer,
                                 Buffer vm_buffer, TransactionId cutoff_xid);
-extern XLogRecPtr log_newpage(RelFileNode *rnode, ForkNumber forkNum,
-                       BlockNumber blk, Page page, bool page_std);
-extern XLogRecPtr log_newpage_buffer(Buffer buffer, bool page_std);
 
 #endif   /* HEAPAM_XLOG_H */
index 85f9cb7cab2c4489d47cc23e5199de68465d3c0c..7d6db4989364bddee42a510161d8055b64f6717f 100644 (file)
@@ -15,7 +15,9 @@
 #include "access/xlogdefs.h"
 #include "datatype/timestamp.h"
 #include "lib/stringinfo.h"
+#include "storage/block.h"
 #include "storage/buf.h"
+#include "storage/relfilenode.h"
 #include "utils/pg_crc.h"
 
 /*
@@ -286,6 +288,9 @@ extern bool XLogNeedsFlush(XLogRecPtr RecPtr);
 extern int     XLogFileInit(XLogSegNo segno, bool *use_existent, bool use_lock);
 extern int     XLogFileOpen(XLogSegNo segno);
 
+extern XLogRecPtr log_newpage(RelFileNode *rnode, ForkNumber forkNum,
+                       BlockNumber blk, char *page, bool page_std);
+extern XLogRecPtr log_newpage_buffer(Buffer buffer, bool page_std);
 extern XLogRecPtr XLogSaveBufferForHint(Buffer buffer, bool buffer_std);
 
 extern void CheckXLogRemoved(XLogSegNo segno, TimeLineID tli);
index 8c8de387e024069e37950dd079375b89f0ebf41f..954114f0d54aad6b79ea20bfa93c0851ae22dca2 100644 (file)
@@ -55,7 +55,7 @@ typedef struct BkpBlock
 /*
  * Each page of XLOG file has a header like this:
  */
-#define XLOG_PAGE_MAGIC 0xD07E /* can be used as WAL version indicator */
+#define XLOG_PAGE_MAGIC 0xD07F /* can be used as WAL version indicator */
 
 typedef struct XLogPageHeaderData
 {