PostgreSQL Source Code git master
Data Structures | Typedefs | Functions | Variables
storage.c File Reference
#include "postgres.h"
#include "access/visibilitymap.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "access/xloginsert.h"
#include "access/xlogutils.h"
#include "catalog/storage.h"
#include "catalog/storage_xlog.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "storage/bulk_write.h"
#include "storage/freespace.h"
#include "storage/proc.h"
#include "storage/smgr.h"
#include "utils/hsearch.h"
#include "utils/memutils.h"
#include "utils/rel.h"
Include dependency graph for storage.c:

Go to the source code of this file.

Data Structures

struct   PendingRelDelete
 
struct   PendingRelSync
 

Typedefs

 
typedef struct PendingRelSync  PendingRelSync
 

Functions

static void  AddPendingSync (const RelFileLocator *rlocator)
 
SMgrRelation  RelationCreateStorage (RelFileLocator rlocator, char relpersistence, bool register_delete)
 
void  log_smgrcreate (const RelFileLocator *rlocator, ForkNumber forkNum)
 
 
void  RelationPreserveStorage (RelFileLocator rlocator, bool atCommit)
 
void  RelationTruncate (Relation rel, BlockNumber nblocks)
 
 
void  RelationCopyStorage (SMgrRelation src, SMgrRelation dst, ForkNumber forkNum, char relpersistence)
 
 
 
void  SerializePendingSyncs (Size maxSize, char *startAddress)
 
void  RestorePendingSyncs (char *startAddress)
 
void  smgrDoPendingDeletes (bool isCommit)
 
void  smgrDoPendingSyncs (bool isCommit, bool isParallelWorker)
 
int  smgrGetPendingDeletes (bool forCommit, RelFileLocator **ptr)
 
void  PostPrepare_smgr (void)
 
void  AtSubCommit_smgr (void)
 
void  AtSubAbort_smgr (void)
 
void  smgr_redo (XLogReaderState *record)
 

Variables

int  wal_skip_threshold = 2048
 
static PendingRelDeletependingDeletes = NULL
 
static HTABpendingSyncHash = NULL
 

Typedef Documentation

PendingRelDelete

PendingRelSync

Function Documentation

AddPendingSync()

static void AddPendingSync ( const RelFileLocatorrlocator )
static

Definition at line 86 of file storage.c.

87{
88 PendingRelSync *pending;
89 bool found;
90
91 /* create the hash if not yet */
92 if (!pendingSyncHash)
93 {
95
96 ctl.keysize = sizeof(RelFileLocator);
97 ctl.entrysize = sizeof(PendingRelSync);
99 pendingSyncHash = hash_create("pending sync hash", 16, &ctl,
101 }
102
103 pending = hash_search(pendingSyncHash, rlocator, HASH_ENTER, &found);
104 Assert(!found);
105 pending->is_truncated = false;
106}
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:952
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:358
Assert(PointerIsAligned(start, uint64))
@ HASH_ENTER
Definition: hsearch.h:114
#define HASH_CONTEXT
Definition: hsearch.h:102
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_BLOBS
Definition: hsearch.h:97
MemoryContext TopTransactionContext
Definition: mcxt.c:171
tree ctl
Definition: radixtree.h:1838
struct RelFileLocator RelFileLocator
static HTAB * pendingSyncHash
Definition: storage.c:78
struct PendingRelSync PendingRelSync
Definition: hsearch.h:66
bool is_truncated
Definition: storage.c:74

References Assert(), ctl, HASH_BLOBS, HASH_CONTEXT, hash_create(), HASH_ELEM, HASH_ENTER, hash_search(), PendingRelSync::is_truncated, pendingSyncHash, and TopTransactionContext.

Referenced by RelationCreateStorage(), and RestorePendingSyncs().

AtSubAbort_smgr()

void AtSubAbort_smgr ( void  )

Definition at line 975 of file storage.c.

976{
978}
void smgrDoPendingDeletes(bool isCommit)
Definition: storage.c:673

References smgrDoPendingDeletes().

Referenced by AbortSubTransaction().

AtSubCommit_smgr()

void AtSubCommit_smgr ( void  )

Definition at line 955 of file storage.c.

956{
957 int nestLevel = GetCurrentTransactionNestLevel();
958 PendingRelDelete *pending;
959
960 for (pending = pendingDeletes; pending != NULL; pending = pending->next)
961 {
962 if (pending->nestLevel >= nestLevel)
963 pending->nestLevel = nestLevel - 1;
964 }
965}
static PendingRelDelete * pendingDeletes
Definition: storage.c:77
int nestLevel
Definition: storage.c:67
struct PendingRelDelete * next
Definition: storage.c:68
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:929

References GetCurrentTransactionNestLevel(), PendingRelDelete::nestLevel, PendingRelDelete::next, and pendingDeletes.

Referenced by CommitSubTransaction().

EstimatePendingSyncsSpace()

Size EstimatePendingSyncsSpace ( void  )

Definition at line 587 of file storage.c.

588{
589 int64 entries;
590
592 return mul_size(1 + entries, sizeof(RelFileLocator));
593}
int64_t int64
Definition: c.h:535
int64 hash_get_num_entries(HTAB *hashp)
Definition: dynahash.c:1336
Size mul_size(Size s1, Size s2)
Definition: shmem.c:510

References hash_get_num_entries(), mul_size(), and pendingSyncHash.

Referenced by InitializeParallelDSM().

log_smgrcreate()

void log_smgrcreate ( const RelFileLocatorrlocator,
ForkNumber  forkNum 
)

Definition at line 187 of file storage.c.

188{
189 xl_smgr_create xlrec;
190
191 /*
192 * Make an XLOG entry reporting the file creation.
193 */
194 xlrec.rlocator = *rlocator;
195 xlrec.forkNum = forkNum;
196
198 XLogRegisterData(&xlrec, sizeof(xlrec));
200}
#define XLOG_SMGR_CREATE
Definition: storage_xlog.h:30
ForkNumber forkNum
Definition: storage_xlog.h:36
RelFileLocator rlocator
Definition: storage_xlog.h:35
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:474
void XLogRegisterData(const void *data, uint32 len)
Definition: xloginsert.c:364
void XLogBeginInsert(void)
Definition: xloginsert.c:149
#define XLR_SPECIAL_REL_UPDATE
Definition: xlogrecord.h:82

References xl_smgr_create::forkNum, xl_smgr_create::rlocator, XLOG_SMGR_CREATE, XLogBeginInsert(), XLogInsert(), XLogRegisterData(), and XLR_SPECIAL_REL_UPDATE.

Referenced by CreateAndCopyRelationData(), fill_seq_with_data(), heapam_relation_copy_data(), heapam_relation_set_new_filelocator(), index_build(), index_copy_data(), and RelationCreateStorage().

PostPrepare_smgr()

void PostPrepare_smgr ( void  )

Definition at line 934 of file storage.c.

935{
936 PendingRelDelete *pending;
938
939 for (pending = pendingDeletes; pending != NULL; pending = next)
940 {
941 next = pending->next;
943 /* must explicitly free the list entry */
944 pfree(pending);
945 }
946}
static int32 next
Definition: blutils.c:224
void pfree(void *pointer)
Definition: mcxt.c:1594

References next, PendingRelDelete::next, pendingDeletes, and pfree().

Referenced by PrepareTransaction().

RelationCopyStorage()

void RelationCopyStorage ( SMgrRelation  src,
SMgrRelation  dst,
ForkNumber  forkNum,
char  relpersistence 
)

Definition at line 478 of file storage.c.

480{
481 bool use_wal;
482 bool copying_initfork;
483 BlockNumber nblocks;
484 BlockNumber blkno;
485 BulkWriteState *bulkstate;
486
487 /*
488 * The init fork for an unlogged relation in many respects has to be
489 * treated the same as normal relation, changes need to be WAL logged and
490 * it needs to be synced to disk.
491 */
492 copying_initfork = relpersistence == RELPERSISTENCE_UNLOGGED &&
493 forkNum == INIT_FORKNUM;
494
495 /*
496 * We need to log the copied data in WAL iff WAL archiving/streaming is
497 * enabled AND it's a permanent relation. This gives the same answer as
498 * "RelationNeedsWAL(rel) || copying_initfork", because we know the
499 * current operation created new relation storage.
500 */
501 use_wal = XLogIsNeeded() &&
502 (relpersistence == RELPERSISTENCE_PERMANENT || copying_initfork);
503
504 bulkstate = smgr_bulk_start_smgr(dst, forkNum, use_wal);
505
506 nblocks = smgrnblocks(src, forkNum);
507
508 for (blkno = 0; blkno < nblocks; blkno++)
509 {
511 int piv_flags;
512 bool checksum_failure;
513 bool verified;
514
515 /* If we got a cancel signal during the copy of the data, quit */
517
518 buf = smgr_bulk_get_buf(bulkstate);
519 smgrread(src, forkNum, blkno, (Page) buf);
520
521 piv_flags = PIV_LOG_WARNING;
523 piv_flags |= PIV_IGNORE_CHECKSUM_FAILURE;
524 verified = PageIsVerified((Page) buf, blkno, piv_flags,
527 {
529
532 }
533
534 if (!verified)
535 {
536 /*
537 * For paranoia's sake, capture the file path before invoking the
538 * ereport machinery. This guards against the possibility of a
539 * relcache flush caused by, e.g., an errcontext callback.
540 * (errcontext callbacks shouldn't be risking any such thing, but
541 * people have been known to forget that rule.)
542 */
545 forkNum);
546
549 errmsg("invalid page in block %u of relation \"%s\"",
550 blkno, relpath.str)));
551 }
552
553 /*
554 * Queue the page for WAL-logging and writing out. Unfortunately we
555 * don't know what kind of a page this is, so we have to log the full
556 * page including any unused space.
557 */
558 smgr_bulk_write(bulkstate, blkno, buf, false);
559 }
560 smgr_bulk_finish(bulkstate);
561}
uint32 BlockNumber
Definition: block.h:31
bool ignore_checksum_failure
Definition: bufpage.c:27
bool PageIsVerified(PageData *page, BlockNumber blkno, int flags, bool *checksum_failure_p)
Definition: bufpage.c:94
#define PIV_LOG_WARNING
Definition: bufpage.h:468
PageData * Page
Definition: bufpage.h:82
#define PIV_IGNORE_CHECKSUM_FAILURE
Definition: bufpage.h:470
void smgr_bulk_write(BulkWriteState *bulkstate, BlockNumber blocknum, BulkWriteBuffer buf, bool page_std)
Definition: bulk_write.c:323
BulkWriteBuffer smgr_bulk_get_buf(BulkWriteState *bulkstate)
Definition: bulk_write.c:347
BulkWriteState * smgr_bulk_start_smgr(SMgrRelation smgr, ForkNumber forknum, bool use_wal)
Definition: bulk_write.c:100
void smgr_bulk_finish(BulkWriteState *bulkstate)
Definition: bulk_write.c:130
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:150
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
static bool checksum_failure
Definition: pg_basebackup.c:137
#define ERRCODE_DATA_CORRUPTED
Definition: pg_basebackup.c:42
static char * buf
Definition: pg_test_fsync.c:72
void pgstat_prepare_report_checksum_failure(Oid dboid)
void pgstat_report_checksum_failures_in_db(Oid dboid, int failurecount)
@ INIT_FORKNUM
Definition: relpath.h:61
#define relpath(rlocator, forknum)
Definition: relpath.h:150
#define relpathbackend(rlocator, backend, forknum)
Definition: relpath.h:141
BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:819
static void smgrread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, void *buffer)
Definition: smgr.h:124
RelFileLocator locator
Definition: relfilelocator.h:75
RelFileLocatorBackend smgr_rlocator
Definition: smgr.h:38
#define XLogIsNeeded()
Definition: xlog.h:109

References RelFileLocatorBackend::backend, buf, CHECK_FOR_INTERRUPTS, checksum_failure, RelFileLocator::dbOid, ereport, errcode(), ERRCODE_DATA_CORRUPTED, errmsg(), ERROR, ignore_checksum_failure, INIT_FORKNUM, RelFileLocatorBackend::locator, PageIsVerified(), pgstat_prepare_report_checksum_failure(), pgstat_report_checksum_failures_in_db(), PIV_IGNORE_CHECKSUM_FAILURE, PIV_LOG_WARNING, relpath, relpathbackend, smgr_bulk_finish(), smgr_bulk_get_buf(), smgr_bulk_start_smgr(), smgr_bulk_write(), SMgrRelationData::smgr_rlocator, smgrnblocks(), smgrread(), and XLogIsNeeded.

Referenced by heapam_relation_copy_data(), and index_copy_data().

RelationCreateStorage()

SMgrRelation RelationCreateStorage ( RelFileLocator  rlocator,
char  relpersistence,
bool  register_delete 
)

Definition at line 122 of file storage.c.

124{
125 SMgrRelation srel;
126 ProcNumber procNumber;
127 bool needs_wal;
128
129 Assert(!IsInParallelMode()); /* couldn't update pendingSyncHash */
130
131 switch (relpersistence)
132 {
133 case RELPERSISTENCE_TEMP:
134 procNumber = ProcNumberForTempRelations();
135 needs_wal = false;
136 break;
137 case RELPERSISTENCE_UNLOGGED:
138 procNumber = INVALID_PROC_NUMBER;
139 needs_wal = false;
140 break;
141 case RELPERSISTENCE_PERMANENT:
142 procNumber = INVALID_PROC_NUMBER;
143 needs_wal = true;
144 break;
145 default:
146 elog(ERROR, "invalid relpersistence: %c", relpersistence);
147 return NULL; /* placate compiler */
148 }
149
150 srel = smgropen(rlocator, procNumber);
151 smgrcreate(srel, MAIN_FORKNUM, false);
152
153 if (needs_wal)
155
156 /*
157 * Add the relation to the list of stuff to delete at abort, if we are
158 * asked to do so.
159 */
160 if (register_delete)
161 {
162 PendingRelDelete *pending;
163
164 pending = (PendingRelDelete *)
166 pending->rlocator = rlocator;
167 pending->procNumber = procNumber;
168 pending->atCommit = false; /* delete if abort */
170 pending->next = pendingDeletes;
171 pendingDeletes = pending;
172 }
173
174 if (relpersistence == RELPERSISTENCE_PERMANENT && !XLogIsNeeded())
175 {
176 Assert(procNumber == INVALID_PROC_NUMBER);
177 AddPendingSync(&rlocator);
178 }
179
180 return srel;
181}
#define elog(elevel,...)
Definition: elog.h:226
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1229
MemoryContext TopMemoryContext
Definition: mcxt.c:166
#define INVALID_PROC_NUMBER
Definition: procnumber.h:26
int ProcNumber
Definition: procnumber.h:24
#define ProcNumberForTempRelations()
Definition: procnumber.h:53
@ MAIN_FORKNUM
Definition: relpath.h:58
SMgrRelation smgropen(RelFileLocator rlocator, ProcNumber backend)
Definition: smgr.c:240
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
Definition: smgr.c:481
static void AddPendingSync(const RelFileLocator *rlocator)
Definition: storage.c:86
void log_smgrcreate(const RelFileLocator *rlocator, ForkNumber forkNum)
Definition: storage.c:187
ProcNumber procNumber
Definition: storage.c:65
bool atCommit
Definition: storage.c:66
RelFileLocator rlocator
Definition: storage.c:64
bool IsInParallelMode(void)
Definition: xact.c:1089

References AddPendingSync(), Assert(), PendingRelDelete::atCommit, elog, ERROR, GetCurrentTransactionNestLevel(), INVALID_PROC_NUMBER, IsInParallelMode(), RelFileLocatorBackend::locator, log_smgrcreate(), MAIN_FORKNUM, MemoryContextAlloc(), PendingRelDelete::nestLevel, PendingRelDelete::next, pendingDeletes, PendingRelDelete::procNumber, ProcNumberForTempRelations, PendingRelDelete::rlocator, SMgrRelationData::smgr_rlocator, smgrcreate(), smgropen(), TopMemoryContext, and XLogIsNeeded.

Referenced by CreateAndCopyRelationData(), heap_create(), heapam_relation_copy_data(), heapam_relation_set_new_filelocator(), index_copy_data(), and RelationSetNewRelfilenumber().

RelationDropStorage()

void RelationDropStorage ( Relation  rel )

Definition at line 207 of file storage.c.

208{
209 PendingRelDelete *pending;
210
211 /* Add the relation to the list of stuff to delete at commit */
212 pending = (PendingRelDelete *)
214 pending->rlocator = rel->rd_locator;
215 pending->procNumber = rel->rd_backend;
216 pending->atCommit = true; /* delete if commit */
218 pending->next = pendingDeletes;
219 pendingDeletes = pending;
220
221 /*
222 * NOTE: if the relation was created in this transaction, it will now be
223 * present in the pending-delete list twice, once with atCommit true and
224 * once with atCommit false. Hence, it will be physically deleted at end
225 * of xact in either case (and the other entry will be ignored by
226 * smgrDoPendingDeletes, so no error will occur). We could instead remove
227 * the existing list entry and delete the physical file immediately, but
228 * for now I'll keep the logic simple.
229 */
230
232}
static void RelationCloseSmgr(Relation relation)
Definition: rel.h:591
ProcNumber rd_backend
Definition: rel.h:60
RelFileLocator rd_locator
Definition: rel.h:57

References PendingRelDelete::atCommit, GetCurrentTransactionNestLevel(), MemoryContextAlloc(), PendingRelDelete::nestLevel, PendingRelDelete::next, pendingDeletes, PendingRelDelete::procNumber, RelationData::rd_backend, RelationData::rd_locator, RelationCloseSmgr(), PendingRelDelete::rlocator, and TopMemoryContext.

Referenced by heap_drop_with_catalog(), heapam_relation_copy_data(), index_copy_data(), index_drop(), reindex_index(), and RelationSetNewRelfilenumber().

RelationPreserveStorage()

void RelationPreserveStorage ( RelFileLocator  rlocator,
bool  atCommit 
)

Definition at line 252 of file storage.c.

253{
254 PendingRelDelete *pending;
255 PendingRelDelete *prev;
257
258 prev = NULL;
259 for (pending = pendingDeletes; pending != NULL; pending = next)
260 {
261 next = pending->next;
262 if (RelFileLocatorEquals(rlocator, pending->rlocator)
263 && pending->atCommit == atCommit)
264 {
265 /* unlink and delete list entry */
266 if (prev)
267 prev->next = next;
268 else
270 pfree(pending);
271 /* prev does not change */
272 }
273 else
274 {
275 /* unrelated entry, don't touch it */
276 prev = pending;
277 }
278 }
279}
#define RelFileLocatorEquals(locator1, locator2)
Definition: relfilelocator.h:89

References PendingRelDelete::atCommit, next, PendingRelDelete::next, pendingDeletes, pfree(), RelFileLocatorEquals, and PendingRelDelete::rlocator.

Referenced by ATExecAddIndex(), and write_relmap_file().

RelationPreTruncate()

void RelationPreTruncate ( Relation  rel )

Definition at line 450 of file storage.c.

451{
452 PendingRelSync *pending;
453
454 if (!pendingSyncHash)
455 return;
456
458 &(RelationGetSmgr(rel)->smgr_rlocator.locator),
459 HASH_FIND, NULL);
460 if (pending)
461 pending->is_truncated = true;
462}
@ HASH_FIND
Definition: hsearch.h:113
static SMgrRelation RelationGetSmgr(Relation rel)
Definition: rel.h:576

References HASH_FIND, hash_search(), PendingRelSync::is_truncated, pendingSyncHash, and RelationGetSmgr().

Referenced by RelationTruncate().

RelationTruncate()

void RelationTruncate ( Relation  rel,
BlockNumber  nblocks 
)

Definition at line 289 of file storage.c.

290{
291 bool fsm;
292 bool vm;
293 bool need_fsm_vacuum = false;
294 ForkNumber forks[MAX_FORKNUM];
295 BlockNumber old_blocks[MAX_FORKNUM];
296 BlockNumber blocks[MAX_FORKNUM];
297 int nforks = 0;
298 SMgrRelation reln;
299
300 /*
301 * Make sure smgr_targblock etc aren't pointing somewhere past new end.
302 * (Note: don't rely on this reln pointer below this loop.)
303 */
304 reln = RelationGetSmgr(rel);
306 for (int i = 0; i <= MAX_FORKNUM; ++i)
308
309 /* Prepare for truncation of MAIN fork of the relation */
310 forks[nforks] = MAIN_FORKNUM;
311 old_blocks[nforks] = smgrnblocks(reln, MAIN_FORKNUM);
312 blocks[nforks] = nblocks;
313 nforks++;
314
315 /* Prepare for truncation of the FSM if it exists */
317 if (fsm)
318 {
319 blocks[nforks] = FreeSpaceMapPrepareTruncateRel(rel, nblocks);
320 if (BlockNumberIsValid(blocks[nforks]))
321 {
322 forks[nforks] = FSM_FORKNUM;
323 old_blocks[nforks] = smgrnblocks(reln, FSM_FORKNUM);
324 nforks++;
325 need_fsm_vacuum = true;
326 }
327 }
328
329 /* Prepare for truncation of the visibility map too if it exists */
331 if (vm)
332 {
333 blocks[nforks] = visibilitymap_prepare_truncate(rel, nblocks);
334 if (BlockNumberIsValid(blocks[nforks]))
335 {
336 forks[nforks] = VISIBILITYMAP_FORKNUM;
337 old_blocks[nforks] = smgrnblocks(reln, VISIBILITYMAP_FORKNUM);
338 nforks++;
339 }
340 }
341
343
344 /*
345 * The code which follows can interact with concurrent checkpoints in two
346 * separate ways.
347 *
348 * First, the truncation operation might drop buffers that the checkpoint
349 * otherwise would have flushed. If it does, then it's essential that the
350 * files actually get truncated on disk before the checkpoint record is
351 * written. Otherwise, if reply begins from that checkpoint, the
352 * to-be-truncated blocks might still exist on disk but have older
353 * contents than expected, which can cause replay to fail. It's OK for the
354 * blocks to not exist on disk at all, but not for them to have the wrong
355 * contents. For this reason, we need to set DELAY_CHKPT_COMPLETE while
356 * this code executes.
357 *
358 * Second, the call to smgrtruncate() below will in turn call
359 * RegisterSyncRequest(). We need the sync request created by that call to
360 * be processed before the checkpoint completes. CheckPointGuts() will
361 * call ProcessSyncRequests(), but if we register our sync request after
362 * that happens, then the WAL record for the truncation could end up
363 * preceding the checkpoint record, while the actual sync doesn't happen
364 * until the next checkpoint. To prevent that, we need to set
365 * DELAY_CHKPT_START here. That way, if the XLOG_SMGR_TRUNCATE precedes
366 * the redo pointer of a concurrent checkpoint, we're guaranteed that the
367 * corresponding sync request will be processed before the checkpoint
368 * completes.
369 */
372
373 /*
374 * We WAL-log the truncation first and then truncate in a critical
375 * section. Truncation drops buffers, even if dirty, and then truncates
376 * disk files. All of that work needs to complete before the lock is
377 * released, or else old versions of pages on disk that are missing recent
378 * changes would become accessible again. We'll try the whole operation
379 * again in crash recovery if we panic, but even then we can't give up
380 * because we don't want standbys' relation sizes to diverge and break
381 * replay or visibility invariants downstream. The critical section also
382 * suppresses interrupts.
383 *
384 * (See also visibilitymap.c if changing this code.)
385 */
387
388 if (RelationNeedsWAL(rel))
389 {
390 /*
391 * Make an XLOG entry reporting the file truncation.
392 */
393 XLogRecPtr lsn;
394 xl_smgr_truncate xlrec;
395
396 xlrec.blkno = nblocks;
397 xlrec.rlocator = rel->rd_locator;
398 xlrec.flags = SMGR_TRUNCATE_ALL;
399
401 XLogRegisterData(&xlrec, sizeof(xlrec));
402
403 lsn = XLogInsert(RM_SMGR_ID,
405
406 /*
407 * Flush, because otherwise the truncation of the main relation might
408 * hit the disk before the WAL record, and the truncation of the FSM
409 * or visibility map. If we crashed during that window, we'd be left
410 * with a truncated heap, but the FSM or visibility map would still
411 * contain entries for the non-existent heap pages, and standbys would
412 * also never replay the truncation.
413 */
414 XLogFlush(lsn);
415 }
416
417 /*
418 * This will first remove any buffers from the buffer pool that should no
419 * longer exist after truncation is complete, and then truncate the
420 * corresponding files on disk.
421 */
422 smgrtruncate(RelationGetSmgr(rel), forks, nforks, old_blocks, blocks);
423
425
426 /* We've done all the critical work, so checkpoints are OK now. */
428
429 /*
430 * Update upper-level FSM pages to account for the truncation. This is
431 * important because the just-truncated pages were likely marked as
432 * all-free, and would be preferentially selected.
433 *
434 * NB: There's no point in delaying checkpoints until this is done.
435 * Because the FSM is not WAL-logged, we have to be prepared for the
436 * possibility of corruption after a crash anyway.
437 */
438 if (need_fsm_vacuum)
440}
#define InvalidBlockNumber
Definition: block.h:33
static bool BlockNumberIsValid(BlockNumber blockNumber)
Definition: block.h:71
void FreeSpaceMapVacuumRange(Relation rel, BlockNumber start, BlockNumber end)
Definition: freespace.c:377
BlockNumber FreeSpaceMapPrepareTruncateRel(Relation rel, BlockNumber nblocks)
Definition: freespace.c:275
i
int i
Definition: isn.c:77
#define START_CRIT_SECTION()
Definition: miscadmin.h:149
#define END_CRIT_SECTION()
Definition: miscadmin.h:151
#define DELAY_CHKPT_START
Definition: proc.h:135
#define DELAY_CHKPT_COMPLETE
Definition: proc.h:136
#define RelationNeedsWAL(relation)
Definition: rel.h:637
ForkNumber
Definition: relpath.h:56
@ FSM_FORKNUM
Definition: relpath.h:59
@ VISIBILITYMAP_FORKNUM
Definition: relpath.h:60
#define MAX_FORKNUM
Definition: relpath.h:70
void smgrtruncate(SMgrRelation reln, ForkNumber *forknum, int nforks, BlockNumber *old_nblocks, BlockNumber *nblocks)
Definition: smgr.c:875
bool smgrexists(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:462
PGPROC * MyProc
Definition: proc.c:66
void RelationPreTruncate(Relation rel)
Definition: storage.c:450
#define SMGR_TRUNCATE_ALL
Definition: storage_xlog.h:43
#define XLOG_SMGR_TRUNCATE
Definition: storage_xlog.h:31
int delayChkptFlags
Definition: proc.h:257
BlockNumber smgr_targblock
Definition: smgr.h:46
BlockNumber smgr_cached_nblocks[MAX_FORKNUM+1]
Definition: smgr.h:47
RelFileLocator rlocator
Definition: storage_xlog.h:49
BlockNumber blkno
Definition: storage_xlog.h:48
BlockNumber visibilitymap_prepare_truncate(Relation rel, BlockNumber nheapblocks)
Definition: visibilitymap.c:446
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2780
uint64 XLogRecPtr
Definition: xlogdefs.h:21

References Assert(), xl_smgr_truncate::blkno, BlockNumberIsValid(), DELAY_CHKPT_COMPLETE, DELAY_CHKPT_START, PGPROC::delayChkptFlags, END_CRIT_SECTION, xl_smgr_truncate::flags, FreeSpaceMapPrepareTruncateRel(), FreeSpaceMapVacuumRange(), FSM_FORKNUM, i, InvalidBlockNumber, MAIN_FORKNUM, MAX_FORKNUM, MyProc, RelationData::rd_locator, RelationGetSmgr(), RelationNeedsWAL, RelationPreTruncate(), xl_smgr_truncate::rlocator, SMgrRelationData::smgr_cached_nblocks, SMgrRelationData::smgr_targblock, SMGR_TRUNCATE_ALL, smgrexists(), smgrnblocks(), smgrtruncate(), START_CRIT_SECTION, VISIBILITYMAP_FORKNUM, visibilitymap_prepare_truncate(), XLOG_SMGR_TRUNCATE, XLogBeginInsert(), XLogFlush(), XLogInsert(), XLogRegisterData(), and XLR_SPECIAL_REL_UPDATE.

Referenced by heapam_relation_nontransactional_truncate(), lazy_truncate_heap(), RelationTruncateIndexes(), and spgvacuumscan().

RelFileLocatorSkippingWAL()

bool RelFileLocatorSkippingWAL ( RelFileLocator  rlocator )

Definition at line 573 of file storage.c.

574{
575 if (!pendingSyncHash ||
576 hash_search(pendingSyncHash, &rlocator, HASH_FIND, NULL) == NULL)
577 return false;
578
579 return true;
580}

References HASH_FIND, hash_search(), and pendingSyncHash.

Referenced by MarkBufferDirtyHint(), and RelationInitPhysicalAddr().

RestorePendingSyncs()

void RestorePendingSyncs ( char *  startAddress )

Definition at line 651 of file storage.c.

652{
653 RelFileLocator *rlocator;
654
655 Assert(pendingSyncHash == NULL);
656 for (rlocator = (RelFileLocator *) startAddress; rlocator->relNumber != 0;
657 rlocator++)
658 AddPendingSync(rlocator);
659}
RelFileNumber relNumber
Definition: relfilelocator.h:62

References AddPendingSync(), Assert(), pendingSyncHash, and RelFileLocator::relNumber.

Referenced by ParallelWorkerMain().

SerializePendingSyncs()

void SerializePendingSyncs ( Size  maxSize,
char *  startAddress 
)

Definition at line 600 of file storage.c.

601{
602 HTAB *tmphash;
603 HASHCTL ctl;
604 HASH_SEQ_STATUS scan;
605 PendingRelSync *sync;
606 PendingRelDelete *delete;
607 RelFileLocator *src;
608 RelFileLocator *dest = (RelFileLocator *) startAddress;
609
610 if (!pendingSyncHash)
611 goto terminate;
612
613 /* Create temporary hash to collect active relfilelocators */
614 ctl.keysize = sizeof(RelFileLocator);
615 ctl.entrysize = sizeof(RelFileLocator);
617 tmphash = hash_create("tmp relfilelocators",
620
621 /* collect all rlocator from pending syncs */
623 while ((sync = (PendingRelSync *) hash_seq_search(&scan)))
624 (void) hash_search(tmphash, &sync->rlocator, HASH_ENTER, NULL);
625
626 /* remove deleted rnodes */
627 for (delete = pendingDeletes; delete != NULL; delete = delete->next)
628 if (delete->atCommit)
629 (void) hash_search(tmphash, &delete->rlocator,
630 HASH_REMOVE, NULL);
631
632 hash_seq_init(&scan, tmphash);
633 while ((src = (RelFileLocator *) hash_seq_search(&scan)))
634 *dest++ = *src;
635
636 hash_destroy(tmphash);
637
638terminate:
639 MemSet(dest, 0, sizeof(RelFileLocator));
640}
#define MemSet(start, val, len)
Definition: c.h:1019
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:865
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1415
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1380
@ HASH_REMOVE
Definition: hsearch.h:115
MemoryContext CurrentMemoryContext
Definition: mcxt.c:160
Definition: dynahash.c:222
RelFileLocator rlocator
Definition: storage.c:73

References ctl, CurrentMemoryContext, generate_unaccent_rules::dest, HASH_BLOBS, HASH_CONTEXT, hash_create(), hash_destroy(), HASH_ELEM, HASH_ENTER, hash_get_num_entries(), HASH_REMOVE, hash_search(), hash_seq_init(), hash_seq_search(), MemSet, PendingRelDelete::next, pendingDeletes, pendingSyncHash, and PendingRelSync::rlocator.

Referenced by InitializeParallelDSM().

smgr_redo()

void smgr_redo ( XLogReaderStaterecord )

Definition at line 981 of file storage.c.

982{
983 XLogRecPtr lsn = record->EndRecPtr;
984 uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
985
986 /* Backup blocks are not used in smgr records */
988
989 if (info == XLOG_SMGR_CREATE)
990 {
991 xl_smgr_create *xlrec = (xl_smgr_create *) XLogRecGetData(record);
992 SMgrRelation reln;
993
994 reln = smgropen(xlrec->rlocator, INVALID_PROC_NUMBER);
995 smgrcreate(reln, xlrec->forkNum, true);
996 }
997 else if (info == XLOG_SMGR_TRUNCATE)
998 {
1000 SMgrRelation reln;
1001 Relation rel;
1002 ForkNumber forks[MAX_FORKNUM];
1003 BlockNumber blocks[MAX_FORKNUM];
1004 BlockNumber old_blocks[MAX_FORKNUM];
1005 int nforks = 0;
1006 bool need_fsm_vacuum = false;
1007
1008 reln = smgropen(xlrec->rlocator, INVALID_PROC_NUMBER);
1009
1010 /*
1011 * Forcibly create relation if it doesn't exist (which suggests that
1012 * it was dropped somewhere later in the WAL sequence). As in
1013 * XLogReadBufferForRedo, we prefer to recreate the rel and replay the
1014 * log as best we can until the drop is seen.
1015 */
1016 smgrcreate(reln, MAIN_FORKNUM, true);
1017
1018 /*
1019 * Before we perform the truncation, update minimum recovery point to
1020 * cover this WAL record. Once the relation is truncated, there's no
1021 * going back. The buffer manager enforces the WAL-first rule for
1022 * normal updates to relation files, so that the minimum recovery
1023 * point is always updated before the corresponding change in the data
1024 * file is flushed to disk. We have to do the same manually here.
1025 *
1026 * Doing this before the truncation means that if the truncation fails
1027 * for some reason, you cannot start up the system even after restart,
1028 * until you fix the underlying situation so that the truncation will
1029 * succeed. Alternatively, we could update the minimum recovery point
1030 * after truncation, but that would leave a small window where the
1031 * WAL-first rule could be violated.
1032 */
1033 XLogFlush(lsn);
1034
1035 /* Prepare for truncation of MAIN fork */
1036 if ((xlrec->flags & SMGR_TRUNCATE_HEAP) != 0)
1037 {
1038 forks[nforks] = MAIN_FORKNUM;
1039 old_blocks[nforks] = smgrnblocks(reln, MAIN_FORKNUM);
1040 blocks[nforks] = xlrec->blkno;
1041 nforks++;
1042
1043 /* Also tell xlogutils.c about it */
1045 }
1046
1047 /* Prepare for truncation of FSM and VM too */
1048 rel = CreateFakeRelcacheEntry(xlrec->rlocator);
1049
1050 if ((xlrec->flags & SMGR_TRUNCATE_FSM) != 0 &&
1051 smgrexists(reln, FSM_FORKNUM))
1052 {
1053 blocks[nforks] = FreeSpaceMapPrepareTruncateRel(rel, xlrec->blkno);
1054 if (BlockNumberIsValid(blocks[nforks]))
1055 {
1056 forks[nforks] = FSM_FORKNUM;
1057 old_blocks[nforks] = smgrnblocks(reln, FSM_FORKNUM);
1058 nforks++;
1059 need_fsm_vacuum = true;
1060 }
1061 }
1062 if ((xlrec->flags & SMGR_TRUNCATE_VM) != 0 &&
1064 {
1065 blocks[nforks] = visibilitymap_prepare_truncate(rel, xlrec->blkno);
1066 if (BlockNumberIsValid(blocks[nforks]))
1067 {
1068 forks[nforks] = VISIBILITYMAP_FORKNUM;
1069 old_blocks[nforks] = smgrnblocks(reln, VISIBILITYMAP_FORKNUM);
1070 nforks++;
1071 }
1072 }
1073
1074 /* Do the real work to truncate relation forks */
1075 if (nforks > 0)
1076 {
1078 smgrtruncate(reln, forks, nforks, old_blocks, blocks);
1080 }
1081
1082 /*
1083 * Update upper-level FSM pages to account for the truncation. This is
1084 * important because the just-truncated pages were likely marked as
1085 * all-free, and would be preferentially selected.
1086 */
1087 if (need_fsm_vacuum)
1088 FreeSpaceMapVacuumRange(rel, xlrec->blkno,
1090
1092 }
1093 else
1094 elog(PANIC, "smgr_redo: unknown op code %u", info);
1095}
uint8_t uint8
Definition: c.h:536
#define PANIC
Definition: elog.h:42
#define SMGR_TRUNCATE_VM
Definition: storage_xlog.h:41
#define SMGR_TRUNCATE_HEAP
Definition: storage_xlog.h:40
#define SMGR_TRUNCATE_FSM
Definition: storage_xlog.h:42
Definition: rel.h:56
XLogRecPtr EndRecPtr
Definition: xlogreader.h:207
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:410
#define XLogRecGetData(decoder)
Definition: xlogreader.h:415
#define XLogRecHasAnyBlockRefs(decoder)
Definition: xlogreader.h:417
void FreeFakeRelcacheEntry(Relation fakerel)
Definition: xlogutils.c:618
void XLogTruncateRelation(RelFileLocator rlocator, ForkNumber forkNum, BlockNumber nblocks)
Definition: xlogutils.c:660
Relation CreateFakeRelcacheEntry(RelFileLocator rlocator)
Definition: xlogutils.c:571

References Assert(), xl_smgr_truncate::blkno, BlockNumberIsValid(), CreateFakeRelcacheEntry(), elog, END_CRIT_SECTION, XLogReaderState::EndRecPtr, xl_smgr_truncate::flags, xl_smgr_create::forkNum, FreeFakeRelcacheEntry(), FreeSpaceMapPrepareTruncateRel(), FreeSpaceMapVacuumRange(), FSM_FORKNUM, INVALID_PROC_NUMBER, InvalidBlockNumber, MAIN_FORKNUM, MAX_FORKNUM, PANIC, xl_smgr_create::rlocator, xl_smgr_truncate::rlocator, SMGR_TRUNCATE_FSM, SMGR_TRUNCATE_HEAP, SMGR_TRUNCATE_VM, smgrcreate(), smgrexists(), smgrnblocks(), smgropen(), smgrtruncate(), START_CRIT_SECTION, VISIBILITYMAP_FORKNUM, visibilitymap_prepare_truncate(), XLOG_SMGR_CREATE, XLOG_SMGR_TRUNCATE, XLogFlush(), XLogRecGetData, XLogRecGetInfo, XLogRecHasAnyBlockRefs, and XLogTruncateRelation().

smgrDoPendingDeletes()

void smgrDoPendingDeletes ( bool  isCommit )

Definition at line 673 of file storage.c.

674{
675 int nestLevel = GetCurrentTransactionNestLevel();
676 PendingRelDelete *pending;
677 PendingRelDelete *prev;
679 int nrels = 0,
680 maxrels = 0;
681 SMgrRelation *srels = NULL;
682
683 prev = NULL;
684 for (pending = pendingDeletes; pending != NULL; pending = next)
685 {
686 next = pending->next;
687 if (pending->nestLevel < nestLevel)
688 {
689 /* outer-level entries should not be processed yet */
690 prev = pending;
691 }
692 else
693 {
694 /* unlink list entry first, so we don't retry on failure */
695 if (prev)
696 prev->next = next;
697 else
699 /* do deletion if called for */
700 if (pending->atCommit == isCommit)
701 {
702 SMgrRelation srel;
703
704 srel = smgropen(pending->rlocator, pending->procNumber);
705
706 /* allocate the initial array, or extend it, if needed */
707 if (maxrels == 0)
708 {
709 maxrels = 8;
710 srels = palloc(sizeof(SMgrRelation) * maxrels);
711 }
712 else if (maxrels <= nrels)
713 {
714 maxrels *= 2;
715 srels = repalloc(srels, sizeof(SMgrRelation) * maxrels);
716 }
717
718 srels[nrels++] = srel;
719 }
720 /* must explicitly free the list entry */
721 pfree(pending);
722 /* prev does not change */
723 }
724 }
725
726 if (nrels > 0)
727 {
728 smgrdounlinkall(srels, nrels, false);
729
730 for (int i = 0; i < nrels; i++)
731 smgrclose(srels[i]);
732
733 pfree(srels);
734 }
735}
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1610
void * palloc(Size size)
Definition: mcxt.c:1365
void smgrclose(SMgrRelation reln)
Definition: smgr.c:374
void smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
Definition: smgr.c:538

References PendingRelDelete::atCommit, GetCurrentTransactionNestLevel(), i, PendingRelDelete::nestLevel, next, PendingRelDelete::next, palloc(), pendingDeletes, pfree(), PendingRelDelete::procNumber, repalloc(), PendingRelDelete::rlocator, smgrclose(), smgrdounlinkall(), and smgropen().

Referenced by AbortTransaction(), AtSubAbort_smgr(), and CommitTransaction().

smgrDoPendingSyncs()

void smgrDoPendingSyncs ( bool  isCommit,
bool  isParallelWorker 
)

Definition at line 741 of file storage.c.

742{
743 PendingRelDelete *pending;
744 int nrels = 0,
745 maxrels = 0;
746 SMgrRelation *srels = NULL;
747 HASH_SEQ_STATUS scan;
748 PendingRelSync *pendingsync;
749
751
752 if (!pendingSyncHash)
753 return; /* no relation needs sync */
754
755 /* Abort -- just throw away all pending syncs */
756 if (!isCommit)
757 {
758 pendingSyncHash = NULL;
759 return;
760 }
761
763
764 /* Parallel worker -- just throw away all pending syncs */
765 if (isParallelWorker)
766 {
767 pendingSyncHash = NULL;
768 return;
769 }
770
771 /* Skip syncing nodes that smgrDoPendingDeletes() will delete. */
772 for (pending = pendingDeletes; pending != NULL; pending = pending->next)
773 if (pending->atCommit)
774 (void) hash_search(pendingSyncHash, &pending->rlocator,
775 HASH_REMOVE, NULL);
776
778 while ((pendingsync = (PendingRelSync *) hash_seq_search(&scan)))
779 {
780 ForkNumber fork;
781 BlockNumber nblocks[MAX_FORKNUM + 1];
782 uint64 total_blocks = 0;
783 SMgrRelation srel;
784
785 srel = smgropen(pendingsync->rlocator, INVALID_PROC_NUMBER);
786
787 /*
788 * We emit newpage WAL records for smaller relations.
789 *
790 * Small WAL records have a chance to be flushed along with other
791 * backends' WAL records. We emit WAL records instead of syncing for
792 * files that are smaller than a certain threshold, expecting faster
793 * commit. The threshold is defined by the GUC wal_skip_threshold.
794 */
795 if (!pendingsync->is_truncated)
796 {
797 for (fork = 0; fork <= MAX_FORKNUM; fork++)
798 {
799 if (smgrexists(srel, fork))
800 {
801 BlockNumber n = smgrnblocks(srel, fork);
802
803 /* we shouldn't come here for unlogged relations */
804 Assert(fork != INIT_FORKNUM);
805 nblocks[fork] = n;
806 total_blocks += n;
807 }
808 else
809 nblocks[fork] = InvalidBlockNumber;
810 }
811 }
812
813 /*
814 * Sync file or emit WAL records for its contents.
815 *
816 * Although we emit WAL record if the file is small enough, do file
817 * sync regardless of the size if the file has experienced a
818 * truncation. It is because the file would be followed by trailing
819 * garbage blocks after a crash recovery if, while a past longer file
820 * had been flushed out, we omitted syncing-out of the file and
821 * emitted WAL instead. You might think that we could choose WAL if
822 * the current main fork is longer than ever, but there's a case where
823 * main fork is longer than ever but FSM fork gets shorter.
824 */
825 if (pendingsync->is_truncated ||
826 total_blocks >= wal_skip_threshold * (uint64) 1024 / BLCKSZ)
827 {
828 /* allocate the initial array, or extend it, if needed */
829 if (maxrels == 0)
830 {
831 maxrels = 8;
832 srels = palloc(sizeof(SMgrRelation) * maxrels);
833 }
834 else if (maxrels <= nrels)
835 {
836 maxrels *= 2;
837 srels = repalloc(srels, sizeof(SMgrRelation) * maxrels);
838 }
839
840 srels[nrels++] = srel;
841 }
842 else
843 {
844 /* Emit WAL records for all blocks. The file is small enough. */
845 for (fork = 0; fork <= MAX_FORKNUM; fork++)
846 {
847 int n = nblocks[fork];
848 Relation rel;
849
850 if (!BlockNumberIsValid(n))
851 continue;
852
853 /*
854 * Emit WAL for the whole file. Unfortunately we don't know
855 * what kind of a page this is, so we have to log the full
856 * page including any unused space. ReadBufferExtended()
857 * counts some pgstat events; unfortunately, we discard them.
858 */
860 log_newpage_range(rel, fork, 0, n, false);
862 }
863 }
864 }
865
866 pendingSyncHash = NULL;
867
868 if (nrels > 0)
869 {
870 smgrdosyncall(srels, nrels);
871 pfree(srels);
872 }
873}
uint64_t uint64
Definition: c.h:539
#define AssertPendingSyncs_RelationCache()
Definition: relcache.h:143
void smgrdosyncall(SMgrRelation *rels, int nrels)
Definition: smgr.c:498
int wal_skip_threshold
Definition: storage.c:40
void log_newpage_range(Relation rel, ForkNumber forknum, BlockNumber startblk, BlockNumber endblk, bool page_std)
Definition: xloginsert.c:1282

References Assert(), AssertPendingSyncs_RelationCache, PendingRelDelete::atCommit, BlockNumberIsValid(), CreateFakeRelcacheEntry(), FreeFakeRelcacheEntry(), GetCurrentTransactionNestLevel(), HASH_REMOVE, hash_search(), hash_seq_init(), hash_seq_search(), INIT_FORKNUM, INVALID_PROC_NUMBER, InvalidBlockNumber, PendingRelSync::is_truncated, RelFileLocatorBackend::locator, log_newpage_range(), MAX_FORKNUM, PendingRelDelete::next, palloc(), pendingDeletes, pendingSyncHash, pfree(), repalloc(), PendingRelDelete::rlocator, PendingRelSync::rlocator, SMgrRelationData::smgr_rlocator, smgrdosyncall(), smgrexists(), smgrnblocks(), smgropen(), and wal_skip_threshold.

Referenced by AbortTransaction(), CommitTransaction(), and PrepareTransaction().

smgrGetPendingDeletes()

int smgrGetPendingDeletes ( bool  forCommit,
RelFileLocator **  ptr 
)

Definition at line 893 of file storage.c.

894{
895 int nestLevel = GetCurrentTransactionNestLevel();
896 int nrels;
897 RelFileLocator *rptr;
898 PendingRelDelete *pending;
899
900 nrels = 0;
901 for (pending = pendingDeletes; pending != NULL; pending = pending->next)
902 {
903 if (pending->nestLevel >= nestLevel && pending->atCommit == forCommit
904 && pending->procNumber == INVALID_PROC_NUMBER)
905 nrels++;
906 }
907 if (nrels == 0)
908 {
909 *ptr = NULL;
910 return 0;
911 }
912 rptr = (RelFileLocator *) palloc(nrels * sizeof(RelFileLocator));
913 *ptr = rptr;
914 for (pending = pendingDeletes; pending != NULL; pending = pending->next)
915 {
916 if (pending->nestLevel >= nestLevel && pending->atCommit == forCommit
917 && pending->procNumber == INVALID_PROC_NUMBER)
918 {
919 *rptr = pending->rlocator;
920 rptr++;
921 }
922 }
923 return nrels;
924}

References PendingRelDelete::atCommit, GetCurrentTransactionNestLevel(), INVALID_PROC_NUMBER, PendingRelDelete::nestLevel, PendingRelDelete::next, palloc(), pendingDeletes, PendingRelDelete::procNumber, and PendingRelDelete::rlocator.

Referenced by RecordTransactionAbort(), RecordTransactionCommit(), and StartPrepare().

Variable Documentation

pendingDeletes

PendingRelDelete* pendingDeletes = NULL
static

Definition at line 77 of file storage.c.

Referenced by AtSubCommit_smgr(), PostPrepare_smgr(), RelationCreateStorage(), RelationDropStorage(), RelationPreserveStorage(), SerializePendingSyncs(), smgrDoPendingDeletes(), smgrDoPendingSyncs(), and smgrGetPendingDeletes().

pendingSyncHash

HTAB* pendingSyncHash = NULL
static

Definition at line 78 of file storage.c.

Referenced by AddPendingSync(), EstimatePendingSyncsSpace(), RelationPreTruncate(), RelFileLocatorSkippingWAL(), RestorePendingSyncs(), SerializePendingSyncs(), and smgrDoPendingSyncs().

wal_skip_threshold

int wal_skip_threshold = 2048

Definition at line 40 of file storage.c.

Referenced by smgrDoPendingSyncs().

AltStyle によって変換されたページ (->オリジナル) /