63 elog(
PANIC,
"failed to add tuple to page");
142 bool need_to_pin_buffer1;
143 bool need_to_pin_buffer2;
144 bool released_locks =
false;
154 Buffer *tmpvmbuf = vmbuffer1;
158 vmbuffer1 = vmbuffer2;
162 vmbuffer2 = tmpvmbuf;
177 if (!need_to_pin_buffer1 && !need_to_pin_buffer2)
181 released_locks =
true;
187 if (need_to_pin_buffer1)
189 if (need_to_pin_buffer2)
204 || (need_to_pin_buffer1 && need_to_pin_buffer2))
208 return released_locks;
237 int num_pages,
bool use_fsm,
bool *did_unlock)
239#define MAX_BUFFERS_TO_EXTEND_BY 64
251 if (bistate == NULL && !use_fsm)
267 extend_by_pages = num_pages;
281 extend_by_pages += extend_by_pages * waitcount;
318 if (num_pages > 1 && bistate == NULL)
319 not_in_fsm_pages = 1;
321 not_in_fsm_pages = num_pages;
345 buffer = victim_buffers[0];
346 last_block = first_block + (extend_by_pages - 1);
357 elog(
ERROR,
"page %u of relation \"%s\" should be empty but is not",
369 if (use_fsm && not_in_fsm_pages < extend_by_pages)
382 for (
uint32 i = 1;
i < extend_by_pages;
i++)
391 if (use_fsm &&
i >= not_in_fsm_pages)
400 if (use_fsm && not_in_fsm_pages < extend_by_pages)
402 BlockNumber first_fsm_block = first_block + not_in_fsm_pages;
413 if (extend_by_pages > 1)
431#undef MAX_BUFFERS_TO_EXTEND_BY
509 Size nearlyEmptyFreeSpace,
515 bool unlockedTargetBuffer;
532 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
533 errmsg(
"row is too big: size %zu, maximum size %zu",
548 if (
len + saveFreeSpace > nearlyEmptyFreeSpace)
549 targetFreeSpace =
Max(
len, nearlyEmptyFreeSpace);
551 targetFreeSpace =
len + saveFreeSpace;
595 targetBlock = nblocks - 1;
630 else if (otherBlock == targetBlock)
633 buffer = otherBuffer;
638 else if (otherBlock < targetBlock)
679 targetBlock, otherBlock, vmbuffer,
701 if (targetFreeSpace <= pageFreeSpace)
717 else if (otherBlock != targetBlock)
766 &unlockedTargetBuffer);
782 if (!unlockedTargetBuffer)
784 unlockedTargetBuffer =
true;
797 recheckVmPins =
false;
798 if (unlockedTargetBuffer)
804 recheckVmPins =
true;
821 Assert(otherBuffer != buffer);
822 Assert(targetBlock > otherBlock);
826 unlockedTargetBuffer =
true;
831 recheckVmPins =
true;
845 otherBlock, targetBlock, vmbuffer_other,
847 unlockedTargetBuffer =
true;
858 if (
len > pageFreeSpace)
860 if (unlockedTargetBuffer)
#define InvalidBlockNumber
static bool BlockNumberIsValid(BlockNumber blockNumber)
void IncrBufferRefCount(Buffer buffer)
BlockNumber BufferGetBlockNumber(Buffer buffer)
BlockNumber ExtendBufferedRelBy(BufferManagerRelation bmr, ForkNumber fork, BufferAccessStrategy strategy, uint32 flags, uint32 extend_by, Buffer *buffers, uint32 *extended_by)
bool ConditionalLockBuffer(Buffer buffer)
void ReleaseBuffer(Buffer buffer)
void UnlockReleaseBuffer(Buffer buffer)
void MarkBufferDirty(Buffer buffer)
void LockBuffer(Buffer buffer, int mode)
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
#define BUFFER_LOCK_UNLOCK
#define RelationGetNumberOfBlocks(reln)
static Page BufferGetPage(Buffer buffer)
static Size BufferGetPageSize(Buffer buffer)
#define BUFFER_LOCK_EXCLUSIVE
@ RBM_ZERO_AND_CLEANUP_LOCK
static bool BufferIsValid(Buffer bufnum)
Size PageGetHeapFreeSpace(const PageData *page)
void PageInit(Page page, Size pageSize, Size specialSize)
static bool PageIsAllVisible(const PageData *page)
static void * PageGetItem(const PageData *page, const ItemIdData *itemId)
static bool PageIsNew(const PageData *page)
#define SizeOfPageHeaderData
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
static OffsetNumber PageGetMaxOffsetNumber(const PageData *page)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
void FreeSpaceMapVacuumRange(Relation rel, BlockNumber start, BlockNumber end)
BlockNumber RecordAndGetPageWithFreeSpace(Relation rel, BlockNumber oldPage, Size oldSpaceAvail, Size spaceNeeded)
void RecordPageWithFreeSpace(Relation rel, BlockNumber heapBlk, Size spaceAvail)
BlockNumber GetPageWithFreeSpace(Relation rel, Size spaceNeeded)
Assert(PointerIsAligned(start, uint64))
#define HEAP_INSERT_SKIP_FSM
#define HEAP_INSERT_FROZEN
void RelationPutHeapTuple(Relation relation, Buffer buffer, HeapTuple tuple, bool token)
static Buffer RelationAddBlocks(Relation relation, BulkInsertState bistate, int num_pages, bool use_fsm, bool *did_unlock)
static bool GetVisibilityMapPins(Relation relation, Buffer buffer1, Buffer buffer2, BlockNumber block1, BlockNumber block2, Buffer *vmbuffer1, Buffer *vmbuffer2)
#define MAX_BUFFERS_TO_EXTEND_BY
Buffer RelationGetBufferForTuple(Relation relation, Size len, Buffer otherBuffer, int options, BulkInsertState bistate, Buffer *vmbuffer, Buffer *vmbuffer_other, int num_pages)
static Buffer ReadBufferBI(Relation relation, BlockNumber targetBlock, ReadBufferMode mode, BulkInsertState bistate)
HeapTupleHeaderData * HeapTupleHeader
#define HEAP_XMAX_IS_MULTI
#define HEAP_XMAX_COMMITTED
static bool HeapTupleHeaderIsSpeculative(const HeapTupleHeaderData *tup)
#define MaxHeapTuplesPerPage
struct ItemIdData ItemIdData
static void ItemPointerSet(ItemPointerData *pointer, BlockNumber blockNumber, OffsetNumber offNum)
int RelationExtensionLockWaiterCount(Relation relation)
#define InvalidOffsetNumber
static PgChecksumMode mode
#define RELATION_IS_LOCAL(relation)
#define RelationGetTargetPageFreeSpace(relation, defaultff)
#define RelationGetRelationName(relation)
#define RelationGetTargetBlock(relation)
#define RelationSetTargetBlock(relation, targblock)
#define HEAP_DEFAULT_FILLFACTOR
BufferAccessStrategy strategy
uint32 already_extended_by
bool visibilitymap_pin_ok(BlockNumber heapBlk, Buffer vmbuf)
void visibilitymap_pin(Relation rel, BlockNumber heapBlk, Buffer *vmbuf)
static StringInfoData tmpbuf