From: Robert Haas Date: Thu, 6 Jun 2013 14:14:46 +0000 (-0400) Subject: Backport log_newpage_buffer. X-Git-Tag: REL9_2_5~84 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4c641d994e19676ef2fec574d52d2156ffc2b3ce;p=postgresql Backport log_newpage_buffer. Andres' fix for XLOG_HEAP2_VISIBLE on unitialized pages requires this. --- diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 860fd2039b..a4ab9b4e07 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -4504,10 +4504,9 @@ log_heap_update(Relation reln, Buffer oldbuf, ItemPointerData from, * Perform XLogInsert of a HEAP_NEWPAGE record to WAL. Caller is responsible * for writing the page to disk after calling this routine. * - * Note: all current callers build pages in private memory and write them - * directly to smgr, rather than using bufmgr. Therefore there is no need - * to pass a buffer ID to XLogInsert, nor to perform MarkBufferDirty within - * the critical section. + * 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. * * Note: the NEWPAGE log record is used for both heaps and indexes, so do * not do anything that assumes we are touching a heap. @@ -4554,6 +4553,53 @@ log_newpage(RelFileNode *rnode, ForkNumber forkNum, BlockNumber blkno, 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. + * + * Note: the NEWPAGE log record is used for both heaps and indexes, so do + * not do anything that assumes we are touching a heap. + */ +XLogRecPtr +log_newpage_buffer(Buffer buffer) +{ + xl_heap_newpage xlrec; + XLogRecPtr recptr; + XLogRecData rdata[2]; + Page page = BufferGetPage(buffer); + + /* We should be in a critical section. */ + Assert(CritSectionCount > 0); + + BufferGetTag(buffer, &xlrec.node, &xlrec.forknum, &xlrec.blkno); + + rdata[0].data = (char *) &xlrec; + rdata[0].len = SizeOfHeapNewpage; + rdata[0].buffer = InvalidBuffer; + rdata[0].next = &(rdata[1]); + + rdata[1].data = page; + rdata[1].len = BLCKSZ; + rdata[1].buffer = InvalidBuffer; + rdata[1].next = NULL; + + recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_NEWPAGE, rdata); + + /* + * The page may be uninitialized. If so, we can't set the LSN and TLI + * because that would corrupt the page. + */ + if (!PageIsNew(page)) + { + PageSetLSN(page, recptr); + PageSetTLI(page, ThisTimeLineID); + } + + return recptr; +} + /* * Handles CLEANUP_INFO */ diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index 026a19fa74..660a854b0e 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -144,6 +144,7 @@ extern XLogRecPtr log_heap_visible(RelFileNode rnode, BlockNumber block, Buffer vm_buffer, TransactionId cutoff_xid); extern XLogRecPtr log_newpage(RelFileNode *rnode, ForkNumber forkNum, BlockNumber blk, Page page); +extern XLogRecPtr log_newpage_buffer(Buffer buffer); /* in heap/pruneheap.c */ extern void heap_page_prune_opt(Relation relation, Buffer buffer,