106 prune_xid = ((
PageHeader) page)->pd_prune_xid;
133 minfree =
Max(minfree, BLCKSZ / 10);
216 bool mark_unused_now,
276 for (offnum = maxoff;
286 presult->
htsv[offnum] = -1;
314 if (prstate.
marked[offnum])
328 presult->
htsv, &prstate);
477 Assert(htsv[rootoffnum] != -1);
536 if (prstate->
marked[offnum])
554 chainitems[nchain++] = offnum;
590 chainitems[nchain++] = offnum;
595 tupdead = recent_dead =
false;
636 elog(
ERROR,
"unexpected HeapTupleSatisfiesVacuum result");
653 else if (!recent_dead)
689 for (
i = 1; (
i < nchain) && (chainitems[
i - 1] != latestdead);
i++)
752 prstate->
marked[offnum] =
true;
754 prstate->
marked[rdoffnum] =
true;
765 prstate->
marked[offnum] =
true;
797 prstate->
marked[offnum] =
true;
822 Assert(nredirected > 0 || ndead > 0 || nunused > 0);
825 Assert(!lp_truncate_only || (nredirected == 0 && ndead == 0));
829 for (
int i = 0;
i < nredirected;
i++)
836 #ifdef USE_ASSERT_CHECKING
886 for (
int i = 0;
i < ndead;
i++)
891 #ifdef USE_ASSERT_CHECKING
918 for (
int i = 0;
i < nunused;
i++)
923 #ifdef USE_ASSERT_CHECKING
925 if (lp_truncate_only)
955 if (lp_truncate_only)
990 #ifdef USE_ASSERT_CHECKING
1072 root_offsets[offnum - 1] = offnum;
1109 if (offnum > maxoff)
1125 root_offsets[nextoffnum - 1] = offnum;
1238 for (
int i = 0;
i < ntuples;
i++)
1274 Assert(nplans > 0 && nplans <= ntuples);
1346 freeze_plans.
nplans = nplans;
1352 if (nredirected > 0)
1356 redirect_items.
ntargets = nredirected;
1398 Assert(nredirected == 0 && ndead == 0);
1417 elog(
ERROR,
"unrecognized prune reason: %d", (
int) reason);
BlockNumber BufferGetBlockNumber(Buffer buffer)
void MarkBufferDirty(Buffer buffer)
void LockBuffer(Buffer buffer, int mode)
void MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
bool ConditionalLockBufferForCleanup(Buffer buffer)
#define BUFFER_LOCK_UNLOCK
static Page BufferGetPage(Buffer buffer)
Size PageGetHeapFreeSpace(Page page)
void PageRepairFragmentation(Page page)
void PageTruncateLinePointerArray(Page page)
PageHeaderData * PageHeader
static Item PageGetItem(Page page, ItemId itemId)
static void PageClearFull(Page page)
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
static void PageSetLSN(Page page, XLogRecPtr lsn)
static bool PageIsFull(Page page)
static OffsetNumber PageGetMaxOffsetNumber(Page page)
#define PG_USED_FOR_ASSERTS_ONLY
#define MemSet(start, val, len)
static void PGresult * res
void HeapTupleHeaderAdvanceConflictHorizon(HeapTupleHeader tuple, TransactionId *snapshotConflictHorizon)
@ HEAPTUPLE_RECENTLY_DEAD
@ HEAPTUPLE_INSERT_IN_PROGRESS
@ HEAPTUPLE_DELETE_IN_PROGRESS
static HTSV_Result htsv_get_valid_status(int status)
HTSV_Result HeapTupleSatisfiesVacuumHorizon(HeapTuple htup, Buffer buffer, TransactionId *dead_after)
#define XLHP_HAS_CONFLICT_HORIZON
#define XLHP_HAS_FREEZE_PLANS
#define XLHP_HAS_NOW_UNUSED_ITEMS
#define XLHP_HAS_REDIRECTIONS
#define XLOG_HEAP2_PRUNE_VACUUM_SCAN
#define XLOG_HEAP2_PRUNE_ON_ACCESS
#define XLHP_CLEANUP_LOCK
#define XLHP_HAS_DEAD_ITEMS
#define XLOG_HEAP2_PRUNE_VACUUM_CLEANUP
#define XLHP_IS_CATALOG_REL
HeapTupleHeaderData * HeapTupleHeader
#define HeapTupleHeaderIsHeapOnly(tup)
#define HeapTupleHeaderIndicatesMovedPartitions(tup)
#define HeapTupleHeaderGetXmin(tup)
#define MaxHeapTuplesPerPage
#define HeapTupleHeaderGetUpdateXid(tup)
#define HeapTupleHeaderIsHotUpdated(tup)
#define ItemIdGetLength(itemId)
#define ItemIdSetRedirect(itemId, link)
#define ItemIdIsNormal(itemId)
#define ItemIdGetRedirect(itemId)
#define ItemIdIsDead(itemId)
#define ItemIdSetDead(itemId)
#define ItemIdIsUsed(itemId)
#define ItemIdSetUnused(itemId)
#define ItemIdIsRedirected(itemId)
#define ItemIdHasStorage(itemId)
static void ItemPointerSet(ItemPointerData *pointer, BlockNumber blockNumber, OffsetNumber offNum)
static OffsetNumber ItemPointerGetOffsetNumber(const ItemPointerData *pointer)
static BlockNumber ItemPointerGetBlockNumber(const ItemPointerData *pointer)
Assert(fmt[strlen(fmt) - 1] !='\n')
#define START_CRIT_SECTION()
#define END_CRIT_SECTION()
#define InvalidOffsetNumber
#define OffsetNumberIsValid(offsetNumber)
#define OffsetNumberNext(offsetNumber)
#define FirstOffsetNumber
#define OffsetNumberPrev(offsetNumber)
void pgstat_update_heap_dead_tuples(Relation rel, int delta)
#define qsort(a, b, c, d)
bool GlobalVisTestIsRemovableXid(GlobalVisState *state, TransactionId xid)
GlobalVisState * GlobalVisTestFor(Relation rel)
static void heap_prune_record_redirect(PruneState *prstate, OffsetNumber offnum, OffsetNumber rdoffnum)
void heap_page_prune(Relation relation, Buffer buffer, GlobalVisState *vistest, bool mark_unused_now, PruneResult *presult, PruneReason reason, OffsetNumber *off_loc)
static int heap_prune_chain(Buffer buffer, OffsetNumber rootoffnum, int8 *htsv, PruneState *prstate)
static void heap_prune_record_dead(PruneState *prstate, OffsetNumber offnum)
void heap_get_root_tuples(Page page, OffsetNumber *root_offsets)
void heap_page_prune_opt(Relation relation, Buffer buffer)
static void heap_prune_record_unused(PruneState *prstate, OffsetNumber offnum)
static int heap_log_freeze_plan(HeapTupleFreeze *tuples, int ntuples, xlhp_freeze_plan *plans_out, OffsetNumber *offsets_out)
static void page_verify_redirects(Page page)
static int heap_log_freeze_cmp(const void *arg1, const void *arg2)
void log_heap_prune_and_freeze(Relation relation, Buffer buffer, TransactionId conflict_xid, bool cleanup_lock, PruneReason reason, HeapTupleFreeze *frozen, int nfrozen, OffsetNumber *redirected, int nredirected, OffsetNumber *dead, int ndead, OffsetNumber *unused, int nunused)
static bool heap_log_freeze_eq(xlhp_freeze_plan *plan, HeapTupleFreeze *frz)
static void heap_prune_record_prunable(PruneState *prstate, TransactionId xid)
static void heap_log_freeze_new_plan(xlhp_freeze_plan *plan, HeapTupleFreeze *frz)
static HTSV_Result heap_prune_satisfies_vacuum(PruneState *prstate, HeapTuple tup, Buffer buffer)
void heap_page_prune_execute(Buffer buffer, bool lp_truncate_only, OffsetNumber *redirected, int nredirected, OffsetNumber *nowdead, int ndead, OffsetNumber *nowunused, int nunused)
static void heap_prune_record_dead_or_unused(PruneState *prstate, OffsetNumber offnum)
#define RelationGetRelid(relation)
#define RelationGetTargetPageFreeSpace(relation, defaultff)
#define RelationIsAccessibleInLogicalDecoding(relation)
#define RelationNeedsWAL(relation)
#define HEAP_DEFAULT_FILLFACTOR
int8 htsv[MaxHeapTuplesPerPage+1]
TransactionId new_prune_xid
OffsetNumber nowdead[MaxHeapTuplesPerPage]
bool marked[MaxHeapTuplesPerPage+1]
OffsetNumber nowunused[MaxHeapTuplesPerPage]
OffsetNumber redirected[MaxHeapTuplesPerPage *2]
TransactionId snapshotConflictHorizon
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
#define InvalidTransactionId
#define TransactionIdEquals(id1, id2)
#define TransactionIdIsValid(xid)
#define TransactionIdIsNormal(xid)
bool RecoveryInProgress(void)
void XLogRegisterData(char *data, uint32 len)
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
void XLogRegisterBufData(uint8 block_id, char *data, uint32 len)
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
void XLogBeginInsert(void)