]> granicus.if.org Git - postgresql/commitdiff
Add new function log_newpage_buffer.
authorRobert Haas <rhaas@postgresql.org>
Thu, 14 Jun 2012 14:11:16 +0000 (10:11 -0400)
committerRobert Haas <rhaas@postgresql.org>
Thu, 14 Jun 2012 14:11:16 +0000 (10:11 -0400)
When I implemented the ginbuildempty() function as part of
implementing unlogged tables, I falsified the note in the header
comment for log_newpage.  Although we could fix that up by changing
the comment, it seems cleaner to add a new function which is
specifically intended to handle this case.  So do that.

src/backend/access/gin/gininsert.c
src/backend/access/heap/heapam.c
src/include/access/heapam.h

index fe06bdcbfab7c03a13407995b39cec8f44a36066..2f95f718e0bf17e3ba9819f4621de6ce19df0041 100644 (file)
@@ -520,20 +520,14 @@ ginbuildempty(PG_FUNCTION_ARGS)
                ReadBufferExtended(index, INIT_FORKNUM, P_NEW, RBM_NORMAL, NULL);
        LockBuffer(RootBuffer, BUFFER_LOCK_EXCLUSIVE);
 
-       /* Initialize both pages, mark them dirty, unlock and release buffer. */
+       /* Initialize and xlog metabuffer and root buffer. */
        START_CRIT_SECTION();
        GinInitMetabuffer(MetaBuffer);
        MarkBufferDirty(MetaBuffer);
+       log_newpage_buffer(MetaBuffer);
        GinInitBuffer(RootBuffer, GIN_LEAF);
        MarkBufferDirty(RootBuffer);
-
-       /* XLOG the new pages */
-       log_newpage(&index->rd_smgr->smgr_rnode.node, INIT_FORKNUM,
-                               BufferGetBlockNumber(MetaBuffer),
-                               BufferGetPage(MetaBuffer));
-       log_newpage(&index->rd_smgr->smgr_rnode.node, INIT_FORKNUM,
-                               BufferGetBlockNumber(RootBuffer),
-                               BufferGetPage(RootBuffer));
+       log_newpage_buffer(RootBuffer);
        END_CRIT_SECTION();
 
        /* Unlock and release the buffers. */
index 9519e73e54c6c6315015a648ef0f958527315c80..f28026be0fb68f0059f1b1778fa80757a32e915d 100644 (file)
@@ -4479,10 +4479,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.
@@ -4529,6 +4528,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
  */
index 026a19fa741e1d4e1c7ab4e7198903d4eec51d92..660a854b0e6439648ccad90c165a8926bc1bf279 100644 (file)
@@ -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,