41 #define GIN_PAGE_FREESIZE \ 42 ( BLCKSZ - MAXALIGN(SizeOfPageHeaderData) - MAXALIGN(sizeof(GinPageOpaqueData)) ) 78 for (i = 0; i < ntuples; i++)
82 memcpy(ptr, tuples[i], this_size);
89 elog(
ERROR,
"failed to add item to index page in \"%s\"",
160 for (i = 0; i < ntuples; i++)
179 prevBuffer = curBuffer;
204 ntuples - startTuple,
228 bool separateList =
false;
229 bool needCleanup =
false;
376 for (i = 0; i < collector->
ntuples; i++)
382 elog(
ERROR,
"failed to add item to index page in \"%s\"",
385 memcpy(ptr, collector->
tuples[i], tupsize);
488 &nentries, &categories);
495 elog(
ERROR,
"too many entries for GIN index");
500 if (collector->
tuples == NULL)
526 for (i = 0; i < nentries; i++)
530 itup =
GinFormTuple(ginstate, attnum, entries[i], categories[i],
532 itup->
t_tid = *ht_ctid;
554 blknoToDelete = metadata->
head;
560 int64 nDeletedHeapTuples = 0;
568 freespace[data.
ndeleted] = blknoToDelete;
594 metadata->
head = blknoToDelete;
646 for (i = 0; i < data.ndeleted; i++)
658 for (i = 0; fill_fsm && i < data.
ndeleted; i++)
661 }
while (blknoToDelete != newHead);
731 heapptr = itup->
t_tid;
735 curattnum == attrnum))
745 heapptr = itup->
t_tid;
775 bool fill_fsm,
bool forceCleanup,
790 bool cleanupFinish =
false;
791 bool fsm_vac =
false;
841 blknoFinish = metadata->
tail;
846 blkno = metadata->
head;
857 "GIN insert cleanup temporary context",
881 if (blkno == blknoFinish && full_clean ==
false)
882 cleanupFinish =
true;
922 &attnum, &key, &category, &nlist)) != NULL)
952 &attnum, &key, &category, &nlist)) != NULL)
968 shiftList(index, metabuffer, blkno, fill_fsm, stats);
1013 if (fsm_vac && fill_fsm)
1034 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1035 errmsg(
"recovery is in progress"),
1036 errhint(
"GIN pending list cannot be cleaned up during recovery.")));
1039 if (indexRel->
rd_rel->relkind != RELKIND_INDEX ||
1040 indexRel->
rd_rel->relam != GIN_AM_OID)
1042 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
1043 errmsg(
"\"%s\" is not a GIN index",
1053 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1054 errmsg(
"cannot access temporary indexes of other sessions")));
1061 memset(&stats, 0,
sizeof(stats));
#define GinPageHasFullRow(page)
#define ItemPointerIsValid(pointer)
void XLogRegisterBufData(uint8 block_id, char *data, int len)
Buffer GinNewBuffer(Relation index)
void MemoryContextDelete(MemoryContext context)
#define AllocSetContextCreate
#define PageIsEmpty(page)
void ginHeapTupleFastInsert(GinState *ginstate, GinTupleCollector *collector)
int errhint(const char *fmt,...)
#define PG_RETURN_INT64(x)
void MarkBufferDirty(Buffer buffer)
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
#define END_CRIT_SECTION()
static MemoryContext opCtx
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
static void addDatum(KeyArray *keys, Datum datum, GinNullCategory category)
#define GIN_NDELETE_AT_ONCE
#define START_CRIT_SECTION()
int errcode(int sqlerrcode)
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
void MemoryContextReset(MemoryContext context)
void ReleaseBuffer(Buffer buffer)
#define GinPageGetOpaque(page)
#define GIN_METAPAGE_BLKNO
static int32 writeListPage(Relation index, Buffer buffer, IndexTuple *tuples, int32 ntuples, BlockNumber rightlink)
bool RecoveryInProgress(void)
#define PageGetMaxOffsetNumber(page)
static void makeSublist(Relation index, IndexTuple *tuples, int32 ntuples, GinMetaPageData *res)
#define XLOG_GIN_INSERT_LISTPAGE
static void initKeyArray(KeyArray *keys, int32 maxvalues)
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
void ginEntryInsert(GinState *ginstate, OffsetNumber attnum, Datum key, GinNullCategory category, ItemPointerData *items, uint32 nitem, GinStatsData *buildStats)
void UnlockReleaseBuffer(Buffer buffer)
signed char GinNullCategory
#define XLOG_GIN_UPDATE_META_PAGE
#define ALLOCSET_DEFAULT_SIZES
void LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
OffsetNumber gintuple_get_attrnum(GinState *ginstate, IndexTuple tuple)
#define FirstOffsetNumber
IndexTupleData * IndexTuple
void initGinState(GinState *state, Relation index)
#define GinGetPendingListCleanupSize(relation)
static uint32 pg_nextpower2_32(uint32 num)
#define RelationGetRelationName(relation)
struct ItemIdData ItemIdData
MemoryContext CurrentMemoryContext
Datum gintuple_get_key(GinState *ginstate, IndexTuple tuple, GinNullCategory *category)
BlockNumber pages_deleted
#define BufferGetPage(buffer)
bool IsAutoVacuumWorkerProcess(void)
#define GinPageSetFullRow(page)
#define PageGetItemId(page, offsetNumber)
void XLogRegisterData(char *data, int len)
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
static void processPendingPage(BuildAccumulator *accum, KeyArray *ka, Page page, OffsetNumber startoff)
#define GinPageIsDeleted(page)
void ginInsertBAEntries(BuildAccumulator *accum, ItemPointer heapptr, OffsetNumber attnum, Datum *entries, GinNullCategory *categories, int32 nentries)
void LockBuffer(Buffer buffer, int mode)
void CheckForSerializableConflictIn(Relation relation, ItemPointer tid, BlockNumber blkno)
#define InvalidOffsetNumber
#define ereport(elevel,...)
void ginInsertCleanup(GinState *ginstate, bool full_clean, bool fill_fsm, bool forceCleanup, IndexBulkDeleteResult *stats)
PageHeaderData * PageHeader
#define Assert(condition)
static void shiftList(Relation index, Buffer metabuffer, BlockNumber newHead, bool fill_fsm, IndexBulkDeleteResult *stats)
IndexTuple GinFormTuple(GinState *ginstate, OffsetNumber attnum, Datum key, GinNullCategory category, Pointer data, Size dataSize, int nipd, bool errorTooBig)
#define RELATION_IS_OTHER_TEMP(relation)
void IndexFreeSpaceMapVacuum(Relation rel)
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
#define OffsetNumberNext(offsetNumber)
#define InvalidBlockNumber
void XLogEnsureRecordSpace(int max_block_id, int ndatas)
void GinInitBuffer(Buffer b, uint32 f)
ItemPointerData * ginGetBAEntry(BuildAccumulator *accum, OffsetNumber *attnum, Datum *key, GinNullCategory *category, uint32 *n)
#define RelationNeedsWAL(relation)
void UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
void * repalloc(void *pointer, Size size)
void index_close(Relation relation, LOCKMODE lockmode)
Size PageGetExactFreeSpace(Page page)
bool ConditionalLockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
void ginBeginBAScan(BuildAccumulator *accum)
Datum gin_clean_pending_list(PG_FUNCTION_ARGS)
BlockNumber BufferGetBlockNumber(Buffer buffer)
#define ItemPointerSetInvalid(pointer)
int errmsg(const char *fmt,...)
void ginHeapTupleFastCollect(GinState *ginstate, GinTupleCollector *collector, OffsetNumber attnum, Datum value, bool isNull, ItemPointer ht_ctid)
#define GIN_PAGE_FREESIZE
GinNullCategory * categories
#define GinPageGetMeta(p)
int gin_pending_list_limit
void vacuum_delay_point(void)
void XLogBeginInsert(void)
void RecordFreeIndexPage(Relation rel, BlockNumber freeBlock)
#define PageSetLSN(page, lsn)
Relation index_open(Oid relationId, LOCKMODE lockmode)
Datum * ginExtractEntries(GinState *ginstate, OffsetNumber attnum, Datum value, bool isNull, int32 *nentries, GinNullCategory **categories)
#define PageGetItem(page, itemId)
#define IndexTupleSize(itup)
void ginInitBA(BuildAccumulator *accum)
BlockNumber nPendingPages
#define XLOG_GIN_DELETE_LISTPAGE