PostgreSQL Source Code  git master
bulk_write.h File Reference
#include "storage/smgr.h"
#include "utils/rel.h"
Include dependency graph for bulk_write.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef struct BulkWriteState BulkWriteState
 
typedef PGIOAlignedBlockBulkWriteBuffer
 

Functions

BulkWriteStatesmgr_bulk_start_rel (Relation rel, ForkNumber forknum)
 
BulkWriteStatesmgr_bulk_start_smgr (struct SMgrRelationData *smgr, ForkNumber forknum, bool use_wal)
 
BulkWriteBuffer smgr_bulk_get_buf (BulkWriteState *bulkstate)
 
void smgr_bulk_write (BulkWriteState *bulkstate, BlockNumber blocknum, BulkWriteBuffer buf, bool page_std)
 
void smgr_bulk_finish (BulkWriteState *bulkstate)
 

Typedef Documentation

◆ BulkWriteBuffer

Definition at line 28 of file bulk_write.h.

◆ BulkWriteState

Definition at line 1 of file bulk_write.h.

Function Documentation

◆ smgr_bulk_finish()

void smgr_bulk_finish ( BulkWriteState bulkstate)

Definition at line 130 of file bulk_write.c.

131 {
132  /* WAL-log and flush any remaining pages */
133  smgr_bulk_flush(bulkstate);
134 
135  /*
136  * Fsync the relation, or register it for the next checkpoint, if
137  * necessary.
138  */
139  if (SmgrIsTemp(bulkstate->smgr))
140  {
141  /* Temporary relations don't need to be fsync'd, ever */
142  }
143  else if (!bulkstate->use_wal)
144  {
145  /*----------
146  * This is either an unlogged relation, or a permanent relation but we
147  * skipped WAL-logging because wal_level=minimal:
148  *
149  * A) Unlogged relation
150  *
151  * Unlogged relations will go away on crash, but they need to be
152  * fsync'd on a clean shutdown. It's sufficient to call
153  * smgrregistersync(), that ensures that the checkpointer will
154  * flush it at the shutdown checkpoint. (It will flush it on the
155  * next online checkpoint too, which is not strictly necessary.)
156  *
157  * Note that the init-fork of an unlogged relation is not
158  * considered unlogged for our purposes. It's treated like a
159  * regular permanent relation. The callers will pass use_wal=true
160  * for the init fork.
161  *
162  * B) Permanent relation, WAL-logging skipped because wal_level=minimal
163  *
164  * This is a new relation, and we didn't WAL-log the pages as we
165  * wrote, but they need to be fsync'd before commit.
166  *
167  * We don't need to do that here, however. The fsync() is done at
168  * commit, by smgrDoPendingSyncs() (*).
169  *
170  * (*) smgrDoPendingSyncs() might decide to WAL-log the whole
171  * relation at commit instead of fsyncing it, if the relation was
172  * very small, but it's smgrDoPendingSyncs() responsibility in any
173  * case.
174  *
175  * We cannot distinguish the two here, so conservatively assume it's
176  * an unlogged relation. A permanent relation with wal_level=minimal
177  * would require no actions, see above.
178  */
179  smgrregistersync(bulkstate->smgr, bulkstate->forknum);
180  }
181  else
182  {
183  /*
184  * Permanent relation, WAL-logged normally.
185  *
186  * We already WAL-logged all the pages, so they will be replayed from
187  * WAL on crash. However, when we wrote out the pages, we passed
188  * skipFsync=true to avoid the overhead of registering all the writes
189  * with the checkpointer. Register the whole relation now.
190  *
191  * There is one hole in that idea: If a checkpoint occurred while we
192  * were writing the pages, it already missed fsyncing the pages we had
193  * written before the checkpoint started. A crash later on would
194  * replay the WAL starting from the checkpoint, therefore it wouldn't
195  * replay our earlier WAL records. So if a checkpoint started after
196  * the bulk write, fsync the files now.
197  */
198 
199  /*
200  * Prevent a checkpoint from starting between the GetRedoRecPtr() and
201  * smgrregistersync() calls.
202  */
205 
206  if (bulkstate->start_RedoRecPtr != GetRedoRecPtr())
207  {
208  /*
209  * A checkpoint occurred and it didn't know about our writes, so
210  * fsync() the relation ourselves.
211  */
213  smgrimmedsync(bulkstate->smgr, bulkstate->forknum);
214  elog(DEBUG1, "flushed relation because a checkpoint occurred concurrently");
215  }
216  else
217  {
218  smgrregistersync(bulkstate->smgr, bulkstate->forknum);
220  }
221  }
222 }
static void smgr_bulk_flush(BulkWriteState *bulkstate)
Definition: bulk_write.c:242
#define Assert(condition)
Definition: c.h:812
#define DEBUG1
Definition: elog.h:30
#define elog(elevel,...)
Definition: elog.h:225
#define DELAY_CHKPT_START
Definition: proc.h:119
void smgrimmedsync(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:811
void smgrregistersync(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:779
#define SmgrIsTemp(smgr)
Definition: smgr.h:73
PGPROC * MyProc
Definition: proc.c:66
SMgrRelation smgr
Definition: bulk_write.c:64
XLogRecPtr start_RedoRecPtr
Definition: bulk_write.c:76
ForkNumber forknum
Definition: bulk_write.c:65
int delayChkptFlags
Definition: proc.h:240
XLogRecPtr GetRedoRecPtr(void)
Definition: xlog.c:6437

References Assert, DEBUG1, DELAY_CHKPT_START, PGPROC::delayChkptFlags, elog, BulkWriteState::forknum, GetRedoRecPtr(), MyProc, BulkWriteState::smgr, smgr_bulk_flush(), smgrimmedsync(), SmgrIsTemp, smgrregistersync(), BulkWriteState::start_RedoRecPtr, and BulkWriteState::use_wal.

Referenced by _bt_load(), btbuildempty(), end_heap_rewrite(), gist_indexsortbuild(), RelationCopyStorage(), and spgbuildempty().

◆ smgr_bulk_get_buf()

BulkWriteBuffer smgr_bulk_get_buf ( BulkWriteState bulkstate)

Definition at line 347 of file bulk_write.c.

348 {
349  return MemoryContextAllocAligned(bulkstate->memcxt, BLCKSZ, PG_IO_ALIGN_SIZE, 0);
350 }
void * MemoryContextAllocAligned(MemoryContext context, Size size, Size alignto, int flags)
Definition: mcxt.c:1409
#define PG_IO_ALIGN_SIZE
MemoryContext memcxt
Definition: bulk_write.c:78

References BulkWriteState::memcxt, MemoryContextAllocAligned(), and PG_IO_ALIGN_SIZE.

Referenced by _bt_blnewpage(), _bt_uppershutdown(), btbuildempty(), gist_indexsortbuild(), gist_indexsortbuild_levelstate_flush(), raw_heap_insert(), RelationCopyStorage(), and spgbuildempty().

◆ smgr_bulk_start_rel()

BulkWriteState* smgr_bulk_start_rel ( Relation  rel,
ForkNumber  forknum 
)

Definition at line 87 of file bulk_write.c.

88 {
90  forknum,
91  RelationNeedsWAL(rel) || forknum == INIT_FORKNUM);
92 }
BulkWriteState * smgr_bulk_start_smgr(SMgrRelation smgr, ForkNumber forknum, bool use_wal)
Definition: bulk_write.c:100
static SMgrRelation RelationGetSmgr(Relation rel)
Definition: rel.h:567
#define RelationNeedsWAL(relation)
Definition: rel.h:628
@ INIT_FORKNUM
Definition: relpath.h:61

References INIT_FORKNUM, RelationGetSmgr(), RelationNeedsWAL, and smgr_bulk_start_smgr().

Referenced by _bt_load(), begin_heap_rewrite(), btbuildempty(), gist_indexsortbuild(), and spgbuildempty().

◆ smgr_bulk_start_smgr()

BulkWriteState* smgr_bulk_start_smgr ( struct SMgrRelationData smgr,
ForkNumber  forknum,
bool  use_wal 
)

◆ smgr_bulk_write()

void smgr_bulk_write ( BulkWriteState bulkstate,
BlockNumber  blocknum,
BulkWriteBuffer  buf,
bool  page_std 
)

Definition at line 323 of file bulk_write.c.

324 {
325  PendingWrite *w;
326 
327  w = &bulkstate->pending_writes[bulkstate->npending++];
328  w->buf = buf;
329  w->blkno = blocknum;
330  w->page_std = page_std;
331 
332  if (bulkstate->npending == MAX_PENDING_WRITES)
333  smgr_bulk_flush(bulkstate);
334 }
#define MAX_PENDING_WRITES
Definition: bulk_write.c:47
static char * buf
Definition: pg_test_fsync.c:72
PendingWrite pending_writes[MAX_PENDING_WRITES]
Definition: bulk_write.c:70
BulkWriteBuffer buf
Definition: bulk_write.c:53
BlockNumber blkno
Definition: bulk_write.c:54
bool page_std
Definition: bulk_write.c:55

References PendingWrite::blkno, PendingWrite::buf, buf, MAX_PENDING_WRITES, BulkWriteState::npending, PendingWrite::page_std, BulkWriteState::pending_writes, and smgr_bulk_flush().

Referenced by _bt_blwritepage(), btbuildempty(), end_heap_rewrite(), gist_indexsortbuild(), gist_indexsortbuild_levelstate_flush(), raw_heap_insert(), RelationCopyStorage(), and spgbuildempty().