diff --git a/src/backend/access/gin/gindatapage.c b/src/backend/access/gin/gindatapage.c index 272a9ca7c09db884e6fd2a7ff38d9d578bfb8e03..5b7c49654c65d95626b2edd84d8b673810165bd5 100644 --- a/src/backend/access/gin/gindatapage.c +++ b/src/backend/access/gin/gindatapage.c @@ -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" diff --git a/src/backend/access/gin/gininsert.c b/src/backend/access/gin/gininsert.c index b27cae3aab2d342935fbb8ba80f3ddbb2d04a478..2fbd1bf5e47d1037da7ca3d7a9e05d870c6bc32d 100644 --- a/src/backend/access/gin/gininsert.c +++ b/src/backend/access/gin/gininsert.c @@ -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" diff --git a/src/backend/access/gin/ginxlog.c b/src/backend/access/gin/ginxlog.c index 7f93ce6526fecea4c01833b86b93bfc6d0226453..ffabf4e259425039d4b647796e1bb48950079fca 100644 --- a/src/backend/access/gin/ginxlog.c +++ b/src/backend/access/gin/ginxlog.c @@ -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) diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c index e6f06c29e51de05dc488ed263e050f43bc2bcd0b..f4eb246c91a74bd0a32d533bd94bc3ede596878d 100644 --- a/src/backend/access/gist/gist.c +++ b/src/backend/access/gist/gist.c @@ -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" diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 21e76d6a2a91edc2fcc836ff2bd4d3f42dc997ad..d731f988b804d5f0f8c9c32b86b4d8c0a2d12859 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -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; diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index 89a98270798e14b95cfe8a8b8efc239030954791..117b18e59051cc4b7b45a78532c6c00910ba4680 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -18,7 +18,6 @@ */ #include "postgres.h" -#include "access/heapam_xlog.h" #include "access/nbtree.h" #include "access/relscan.h" #include "catalog/index.h" diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c index 048b215118642837c76e8cc2d06b1b6cb6ebc52e..e8a89d24ae5abbf732d6b320c12b0d1c64b35c7f 100644 --- a/src/backend/access/nbtree/nbtsort.c +++ b/src/backend/access/nbtree/nbtsort.c @@ -66,7 +66,6 @@ #include "postgres.h" -#include "access/heapam_xlog.h" #include "access/nbtree.h" #include "miscadmin.h" #include "storage/smgr.h" diff --git a/src/backend/access/rmgrdesc/heapdesc.c b/src/backend/access/rmgrdesc/heapdesc.c index 7df18fa2d2cf4a7ea57324a046e42ea19b9f1248..24b6f92bd55c24341ec6c621a1edf76d4d67b90c 100644 --- a/src/backend/access/rmgrdesc/heapdesc.c +++ b/src/backend/access/rmgrdesc/heapdesc.c @@ -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; diff --git a/src/backend/access/spgist/spginsert.c b/src/backend/access/spgist/spginsert.c index a4408f03bd365d4784858d5df6a6524a0f8a543a..7c104f49cc8855c000a9a84aaf8e3f996099e039 100644 --- a/src/backend/access/spgist/spginsert.c +++ b/src/backend/access/spgist/spginsert.c @@ -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" diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index fe184bde3b97338aca07af94fdf91313ea52ec1b..34f2fc0e21b774b6f6c8b27ea139262e9cb9c77d 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -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. diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 5dc4d18b6a5a63b26244fe27e4c0a649306f830e..158c594a848b088e6113b3e5483f6158c370a92c 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -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" diff --git a/src/backend/replication/logical/decode.c b/src/backend/replication/logical/decode.c index 8f8732afdce28099d28c5a3a2cafe79fb8c8a96b..9f1b20e04abc77496c5a0f6b265209fb2ff74303 100644 --- a/src/backend/replication/logical/decode.c +++ b/src/backend/replication/logical/decode.c @@ -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: /* diff --git a/src/include/access/heapam_xlog.h b/src/include/access/heapam_xlog.h index e964ecce46117633a923d3aed128e77fb5902ebc..254434773ed9c59c1fdb7e0c808232e04d387532 100644 --- a/src/include/access/heapam_xlog.h +++ b/src/include/access/heapam_xlog.h @@ -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 */ diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h index 85f9cb7cab2c4489d47cc23e5199de68465d3c0c..7d6db4989364bddee42a510161d8055b64f6717f 100644 --- a/src/include/access/xlog.h +++ b/src/include/access/xlog.h @@ -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); diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h index 8c8de387e024069e37950dd079375b89f0ebf41f..954114f0d54aad6b79ea20bfa93c0851ae22dca2 100644 --- a/src/include/access/xlog_internal.h +++ b/src/include/access/xlog_internal.h @@ -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 {