localbuf: Introduce FlushLocalBuffer()
authorAndres Freund <[email protected]>
Sat, 15 Mar 2025 16:30:07 +0000 (12:30 -0400)
committerAndres Freund <[email protected]>
Sun, 16 Mar 2025 02:07:48 +0000 (22:07 -0400)
Previously we had two paths implementing writing out temporary table
buffers. For shared buffers, the logic for that is centralized in
FlushBuffer(). Introduce FlushLocalBuffer() to do the same for local buffers.

Besides being a nice cleanup on its own, it also makes an upcoming change
slightly easier.

Reviewed-by: Melanie Plageman <[email protected]>
Discussion: https://postgr.es/m/CAAKRu_b9anbWzEs5AAF9WCvcEVmgz-1AkHSQ-CLLy-p7WHzvFw@mail.gmail.com

src/backend/storage/buffer/bufmgr.c
src/backend/storage/buffer/localbuf.c
src/include/storage/buf_internals.h

index a716074467f8decd1cb7bdeda34aa185b15107dd..f3c27d7e77adaf289861e02396bb58752824eee8 100644 (file)
@@ -4453,7 +4453,6 @@ FlushRelationBuffers(Relation rel)
        for (i = 0; i < NLocBuffer; i++)
        {
            uint32      buf_state;
-           instr_time  io_start;
 
            bufHdr = GetLocalBufferDescriptor(i);
            if (BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator) &&
@@ -4461,9 +4460,6 @@ FlushRelationBuffers(Relation rel)
                 (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY))
            {
                ErrorContextCallback errcallback;
-               Page        localpage;
-
-               localpage = (char *) LocalBufHdrGetBlock(bufHdr);
 
                /* Setup error traceback support for ereport() */
                errcallback.callback = local_buffer_write_error_callback;
@@ -4471,23 +4467,7 @@ FlushRelationBuffers(Relation rel)
                errcallback.previous = error_context_stack;
                error_context_stack = &errcallback;
 
-               PageSetChecksumInplace(localpage, bufHdr->tag.blockNum);
-
-               io_start = pgstat_prepare_io_time(track_io_timing);
-
-               smgrwrite(srel,
-                         BufTagGetForkNum(&bufHdr->tag),
-                         bufHdr->tag.blockNum,
-                         localpage,
-                         false);
-
-               pgstat_count_io_op_time(IOOBJECT_TEMP_RELATION,
-                                       IOCONTEXT_NORMAL, IOOP_WRITE,
-                                       io_start, 1, BLCKSZ);
-
-               TerminateLocalBufferIO(bufHdr, true, 0);
-
-               pgBufferUsage.local_blks_written++;
+               FlushLocalBuffer(bufHdr, srel);
 
                /* Pop the error context stack */
                error_context_stack = errcallback.previous;
index 86b1c4c7c680adcba4f8f66bd627ac83770af5ce..8efde05c0a5fb6cc88f30ac558532ef00b44d86f 100644 (file)
@@ -174,6 +174,41 @@ LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum,
    return bufHdr;
 }
 
+/*
+ * Like FlushBuffer(), just for local buffers.
+ */
+void
+FlushLocalBuffer(BufferDesc *bufHdr, SMgrRelation reln)
+{
+   instr_time  io_start;
+   Page        localpage = (char *) LocalBufHdrGetBlock(bufHdr);
+
+   /* Find smgr relation for buffer */
+   if (reln == NULL)
+       reln = smgropen(BufTagGetRelFileLocator(&bufHdr->tag),
+                       MyProcNumber);
+
+   PageSetChecksumInplace(localpage, bufHdr->tag.blockNum);
+
+   io_start = pgstat_prepare_io_time(track_io_timing);
+
+   /* And write... */
+   smgrwrite(reln,
+             BufTagGetForkNum(&bufHdr->tag),
+             bufHdr->tag.blockNum,
+             localpage,
+             false);
+
+   /* Temporary table I/O does not use Buffer Access Strategies */
+   pgstat_count_io_op_time(IOOBJECT_TEMP_RELATION, IOCONTEXT_NORMAL,
+                           IOOP_WRITE, io_start, 1, BLCKSZ);
+
+   /* Mark not-dirty */
+   TerminateLocalBufferIO(bufHdr, true, 0);
+
+   pgBufferUsage.local_blks_written++;
+}
+
 static Buffer
 GetLocalVictimBuffer(void)
 {
@@ -234,34 +269,7 @@ GetLocalVictimBuffer(void)
     * the case, write it out before reusing it!
     */
    if (pg_atomic_read_u32(&bufHdr->state) & BM_DIRTY)
-   {
-       instr_time  io_start;
-       SMgrRelation oreln;
-       Page        localpage = (char *) LocalBufHdrGetBlock(bufHdr);
-
-       /* Find smgr relation for buffer */
-       oreln = smgropen(BufTagGetRelFileLocator(&bufHdr->tag), MyProcNumber);
-
-       PageSetChecksumInplace(localpage, bufHdr->tag.blockNum);
-
-       io_start = pgstat_prepare_io_time(track_io_timing);
-
-       /* And write... */
-       smgrwrite(oreln,
-                 BufTagGetForkNum(&bufHdr->tag),
-                 bufHdr->tag.blockNum,
-                 localpage,
-                 false);
-
-       /* Temporary table I/O does not use Buffer Access Strategies */
-       pgstat_count_io_op_time(IOOBJECT_TEMP_RELATION, IOCONTEXT_NORMAL,
-                               IOOP_WRITE, io_start, 1, BLCKSZ);
-
-       /* Mark not-dirty now in case we error out below */
-       TerminateLocalBufferIO(bufHdr, true, 0);
-
-       pgBufferUsage.local_blks_written++;
-   }
+       FlushLocalBuffer(bufHdr, NULL);
 
    /*
     * Remove the victim buffer from the hashtable and mark as invalid.
index 4611a60d3e0ed7577243bc834e3ace2eab5192c6..90bc7e0db7be25318d5726a93e7a882328bd5e81 100644 (file)
@@ -473,6 +473,7 @@ extern BlockNumber ExtendBufferedRelLocal(BufferManagerRelation bmr,
 extern void MarkLocalBufferDirty(Buffer buffer);
 extern void TerminateLocalBufferIO(BufferDesc *bufHdr, bool clear_dirty,
                                   uint32 set_flag_bits);
+extern void FlushLocalBuffer(BufferDesc *bufHdr, SMgrRelation reln);
 extern void DropRelationLocalBuffers(RelFileLocator rlocator,
                                     ForkNumber forkNum,
                                     BlockNumber firstDelBlock);