109 #define MULTIXACT_OFFSETS_PER_PAGE (BLCKSZ / sizeof(MultiXactOffset)) 111 #define MultiXactIdToOffsetPage(xid) \ 112 ((xid) / (MultiXactOffset) MULTIXACT_OFFSETS_PER_PAGE) 113 #define MultiXactIdToOffsetEntry(xid) \ 114 ((xid) % (MultiXactOffset) MULTIXACT_OFFSETS_PER_PAGE) 115 #define MultiXactIdToOffsetSegment(xid) (MultiXactIdToOffsetPage(xid) / SLRU_PAGES_PER_SEGMENT) 130 #define MXACT_MEMBER_BITS_PER_XACT 8 131 #define MXACT_MEMBER_FLAGS_PER_BYTE 1 132 #define MXACT_MEMBER_XACT_BITMASK ((1 << MXACT_MEMBER_BITS_PER_XACT) - 1) 135 #define MULTIXACT_FLAGBYTES_PER_GROUP 4 136 #define MULTIXACT_MEMBERS_PER_MEMBERGROUP \ 137 (MULTIXACT_FLAGBYTES_PER_GROUP * MXACT_MEMBER_FLAGS_PER_BYTE) 139 #define MULTIXACT_MEMBERGROUP_SIZE \ 140 (sizeof(TransactionId) * MULTIXACT_MEMBERS_PER_MEMBERGROUP + MULTIXACT_FLAGBYTES_PER_GROUP) 141 #define MULTIXACT_MEMBERGROUPS_PER_PAGE (BLCKSZ / MULTIXACT_MEMBERGROUP_SIZE) 142 #define MULTIXACT_MEMBERS_PER_PAGE \ 143 (MULTIXACT_MEMBERGROUPS_PER_PAGE * MULTIXACT_MEMBERS_PER_MEMBERGROUP) 155 #define MAX_MEMBERS_IN_LAST_MEMBERS_PAGE \ 156 ((uint32) ((0xFFFFFFFF % MULTIXACT_MEMBERS_PER_PAGE) + 1)) 159 #define MXOffsetToMemberPage(xid) ((xid) / (TransactionId) MULTIXACT_MEMBERS_PER_PAGE) 160 #define MXOffsetToMemberSegment(xid) (MXOffsetToMemberPage(xid) / SLRU_PAGES_PER_SEGMENT) 163 #define MXOffsetToFlagsOffset(xid) \ 164 ((((xid) / (TransactionId) MULTIXACT_MEMBERS_PER_MEMBERGROUP) % \ 165 (TransactionId) MULTIXACT_MEMBERGROUPS_PER_PAGE) * \ 166 (TransactionId) MULTIXACT_MEMBERGROUP_SIZE) 167 #define MXOffsetToFlagsBitShift(xid) \ 168 (((xid) % (TransactionId) MULTIXACT_MEMBERS_PER_MEMBERGROUP) * \ 169 MXACT_MEMBER_BITS_PER_XACT) 172 #define MXOffsetToMemberOffset(xid) \ 173 (MXOffsetToFlagsOffset(xid) + MULTIXACT_FLAGBYTES_PER_GROUP + \ 174 ((xid) % MULTIXACT_MEMBERS_PER_MEMBERGROUP) * sizeof(TransactionId)) 177 #define MULTIXACT_MEMBER_SAFE_THRESHOLD (MaxMultiXactOffset / 2) 178 #define MULTIXACT_MEMBER_DANGER_THRESHOLD \ 179 (MaxMultiXactOffset - MaxMultiXactOffset / 4) 181 #define PreviousMultiXactId(xid) \ 182 ((xid) == FirstMultiXactId ? MaxMultiXactId : (xid) - 1) 190 #define MultiXactOffsetCtl (&MultiXactOffsetCtlData) 191 #define MultiXactMemberCtl (&MultiXactMemberCtlData) 288 #define MaxOldestSlot (MaxBackends + max_prepared_xacts) 321 #define MAX_CACHE_ENTRIES 256 326 #ifdef MULTIXACT_DEBUG 327 #define debug_elog2(a,b) elog(a,b) 328 #define debug_elog3(a,b,c) elog(a,b,c) 329 #define debug_elog4(a,b,c,d) elog(a,b,c,d) 330 #define debug_elog5(a,b,c,d,e) elog(a,b,c,d,e) 331 #define debug_elog6(a,b,c,d,e,f) elog(a,b,c,d,e,f) 333 #define debug_elog2(a,b) 334 #define debug_elog3(a,b,c) 335 #define debug_elog4(a,b,c,d) 336 #define debug_elog5(a,b,c,d,e) 337 #define debug_elog6(a,b,c,d,e,f) 406 members[0].
xid = xid1;
407 members[0].
status = status1;
408 members[1].
xid = xid2;
409 members[1].
status = status2;
488 for (i = 0; i < nmembers; i++)
491 (members[i].status == status))
516 for (i = 0, j = 0; i < nmembers; i++)
522 newMembers[j].
xid = members[
i].
xid;
527 newMembers[j].
xid = xid;
578 for (i = 0; i < nmembers; i++)
593 for (i = 0; i < nmembers; i++)
661 MyBackendId, nextMXact);
706 oldestMXact = thisoldest;
714 MyBackendId, oldestMXact);
796 bool has_update =
false;
798 for (i = 0; i < nmembers; i++)
803 elog(
ERROR,
"new multixact has more than one updating member");
899 for (i = 0; i < nmembers; i++, offset++)
915 if (pageno != prev_pageno)
918 prev_pageno = pageno;
924 *memberptr = members[
i].
xid;
929 flagsval = *flagsptr;
931 flagsval |= (members[
i].
status << bshift);
932 *flagsptr = flagsval;
965 elog(
ERROR,
"cannot assign MultiXactIds during recovery");
1020 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1021 errmsg(
"database is not accepting commands that generate new MultiXactIds to avoid wraparound data loss in database \"%s\"",
1023 errhint(
"Execute a database-wide VACUUM in that database.\n" 1024 "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
1027 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1028 errmsg(
"database is not accepting commands that generate new MultiXactIds to avoid wraparound data loss in database with OID %u",
1030 errhint(
"Execute a database-wide VACUUM in that database.\n" 1031 "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
1049 (
errmsg_plural(
"database \"%s\" must be vacuumed before %u more MultiXactId is used",
1050 "database \"%s\" must be vacuumed before %u more MultiXactIds are used",
1051 multiWrapLimit - result,
1053 multiWrapLimit - result),
1054 errhint(
"Execute a database-wide VACUUM in that database.\n" 1055 "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
1058 (
errmsg_plural(
"database with OID %u must be vacuumed before %u more MultiXactId is used",
1059 "database with OID %u must be vacuumed before %u more MultiXactIds are used",
1060 multiWrapLimit - result,
1062 multiWrapLimit - result),
1063 errhint(
"Execute a database-wide VACUUM in that database.\n" 1064 "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
1083 if (nextOffset == 0)
1109 #define OFFSET_WARN_SEGMENTS 20 1118 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1119 errmsg(
"multixact \"members\" limit exceeded"),
1120 errdetail_plural(
"This command would create a multixact with %u members, but the remaining space is only enough for %u member.",
1121 "This command would create a multixact with %u members, but the remaining space is only enough for %u members.",
1125 errhint(
"Execute a database-wide VACUUM in database with OID %u with reduced vacuum_multixact_freeze_min_age and vacuum_multixact_freeze_table_age settings.",
1155 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1156 errmsg_plural(
"database with OID %u must be vacuumed before %d more multixact member is used",
1157 "database with OID %u must be vacuumed before %d more multixact members are used",
1161 errhint(
"Execute a database-wide VACUUM in that database with reduced vacuum_multixact_freeze_min_age and vacuum_multixact_freeze_table_age settings.")));
1224 bool from_pgupgrade,
bool onlyLock)
1297 (
errcode(ERRCODE_INTERNAL_ERROR),
1298 errmsg(
"MultiXactId %u does no longer exist -- apparent wraparound",
1305 (
errcode(ERRCODE_INTERNAL_ERROR),
1306 errmsg(
"MultiXactId %u has not been created yet -- apparent wraparound",
1359 tmpMXact = multi + 1;
1361 if (nextMXact == tmpMXact)
1364 length = nextOffset - offset;
1374 prev_pageno = pageno;
1379 if (pageno != prev_pageno)
1384 nextMXOffset = *offptr;
1386 if (nextMXOffset == 0)
1395 length = nextMXOffset - offset;
1408 for (i = 0; i < length; i++, offset++)
1419 if (pageno != prev_pageno)
1422 prev_pageno = pageno;
1439 ptr[truelength].
xid = *xactptr;
1469 if (member1.
xid > member2.
xid)
1471 if (member1.
xid < member2.
xid)
1519 return entry->
multi;
1546 if (entry->
multi == multi)
1555 memcpy(ptr, entry->
members, size);
1589 if (MXactContext == NULL)
1594 "MultiXact cache context",
1603 entry->
multi = multi;
1638 return "fornokeyupd";
1646 elog(
ERROR,
"unrecognized multixact status %d", status);
1654 static char *
str = NULL;
1666 for (i = 1; i < nmembers; i++)
1699 MXactContext = NULL;
1766 MXactContext = NULL;
1777 void *recdata,
uint32 len)
1798 void *recdata,
uint32 len)
1813 void *recdata,
uint32 len)
1829 #define SHARED_MULTIXACT_STATE_SIZE \ 1830 add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \ 1831 mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot)) 1852 MultiXactOffsetSLRULock,
"pg_multixact/offsets",
1858 MultiXactMemberSLRULock,
"pg_multixact/members",
2104 MemSet(xidptr, 0, BLCKSZ - memberoff);
2138 *nextMultiOffset = MultiXactState->
nextOffset;
2144 "MultiXact: checkpoint is nextMulti %u, nextOffset %u, oldestMulti %u in DB %u",
2145 *nextMulti, *nextMultiOffset, *oldestMulti, *oldestMultiDB);
2154 TRACE_POSTGRESQL_MULTIXACT_CHECKPOINT_START(
true);
2164 TRACE_POSTGRESQL_MULTIXACT_CHECKPOINT_DONE(
true);
2180 nextMulti, nextMultiOffset);
2183 MultiXactState->
nextOffset = nextMultiOffset;
2218 bool needs_offset_vacuum;
2237 multiStopLimit = multiWrapLimit - 3000000;
2251 multiWarnLimit = multiWrapLimit - 40000000;
2280 (
errmsg_internal(
"MultiXactId wrap limit is %u, limited by database with OID %u",
2281 multiWrapLimit, oldest_datoid)));
2312 char *oldest_datname;
2326 oldest_datname = NULL;
2330 (
errmsg_plural(
"database \"%s\" must be vacuumed before %u more MultiXactId is used",
2331 "database \"%s\" must be vacuumed before %u more MultiXactIds are used",
2332 multiWrapLimit - curMulti,
2334 multiWrapLimit - curMulti),
2335 errhint(
"To avoid a database shutdown, execute a database-wide VACUUM in that database.\n" 2336 "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
2339 (
errmsg_plural(
"database with OID %u must be vacuumed before %u more MultiXactId is used",
2340 "database with OID %u must be vacuumed before %u more MultiXactIds are used",
2341 multiWrapLimit - curMulti,
2343 multiWrapLimit - curMulti),
2344 errhint(
"To avoid a database shutdown, execute a database-wide VACUUM in that database.\n" 2345 "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
2439 while (nmembers > 0)
2450 if (flagsoff == 0 && flagsbit == 0)
2532 oldestMXact = thisoldest;
2536 oldestMXact = thisoldest;
2564 bool prevOldestOffsetKnown;
2592 if (oldestMultiXactId == nextMXact)
2599 oldestOffsetKnown =
true;
2612 if (oldestOffsetKnown)
2618 (
errmsg(
"MultiXact member wraparound protections are disabled because oldest checkpointed MultiXact %u does not exist on disk",
2619 oldestMultiXactId)));
2629 if (oldestOffsetKnown)
2632 offsetStopLimit = oldestOffset - (oldestOffset %
2638 if (!prevOldestOffsetKnown && !is_startup)
2640 (
errmsg(
"MultiXact member wraparound protections are now enabled")));
2643 (
errmsg_internal(
"MultiXact member stop limit is now %u based on MultiXact %u",
2644 offsetStopLimit, oldestMultiXactId)));
2646 else if (prevOldestOffsetKnown)
2654 oldestOffset = prevOldestOffset;
2655 oldestOffsetKnown =
true;
2656 offsetStopLimit = prevOffsetStopLimit;
2669 return !oldestOffsetKnown ||
2692 finish = start + distance;
2715 if (start < boundary)
2716 return finish >= boundary || finish < start;
2718 return finish >= boundary && finish < start;
2780 nextMultiXactId = MultiXactState->
nextMXact;
2785 if (!oldestOffsetKnown)
2829 uint32 victim_multixacts;
2847 victim_multixacts = multixacts * fraction;
2850 if (victim_multixacts > multixacts)
2852 return multixacts - victim_multixacts;
2893 int segment = startsegment;
2899 while (segment != endsegment)
2901 elog(
DEBUG2,
"truncating multixact members segment %x", segment);
2905 if (segment == maxsegment)
3019 if (oldestMulti == nextMulti)
3027 (
errmsg(
"oldest MultiXact %u not found, earliest MultiXact %u, skipping truncation",
3028 oldestMulti, earliest)));
3037 if (newOldestMulti == nextMulti)
3045 (
errmsg(
"cannot truncate up to MultiXact %u because it does not exist on disk, skipping truncation",
3051 elog(
DEBUG1,
"performing multixact truncation: " 3052 "offsets [%u, %u), offsets segments [%x, %x), " 3053 "members [%u, %u), members segments [%x, %x)",
3054 oldestMulti, newOldestMulti,
3057 oldestOffset, newOldestOffset,
3080 oldestMulti, newOldestMulti,
3081 oldestOffset, newOldestOffset);
3291 for (i = 0; i < xlrec->
nmembers; i++)
3307 elog(
DEBUG1,
"replaying multixact truncation: " 3308 "offsets [%u, %u), offsets segments [%x, %x), " 3309 "members [%u, %u), members segments [%x, %x)",
3340 elog(
PANIC,
"multixact_redo: unknown op code %u", info);
3358 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3359 errmsg(
"invalid MultiXactId: %u", mxid)));
3369 multi =
palloc(
sizeof(mxact));
3390 while (multi->iter < multi->nmembers)
3395 values[0] =
psprintf(
"%u", multi->members[multi->iter].xid);
#define MaxMultiXactOffset
Datum pg_get_multixact_members(PG_FUNCTION_ARGS)
static SlruCtlData MultiXactMemberCtlData
#define MULTIXACT_MEMBER_DANGER_THRESHOLD
#define AllocSetContextCreate
void StartupMultiXact(void)
int errhint(const char *fmt,...)
void AtPrepare_MultiXact(void)
MemoryContext TopTransactionContext
#define MXOffsetToFlagsBitShift(xid)
static bool SlruScanDirCbFindEarliest(SlruCtl ctl, char *filename, int segpage, void *data)
#define TransactionIdEquals(id1, id2)
#define debug_elog4(a, b, c, d)
int SlruSyncFileTag(SlruCtl ctl, const FileTag *ftag, char *path)
void AdvanceNextFullTransactionIdPastXid(TransactionId xid)
TupleDesc CreateTemplateTupleDesc(int natts)
static void dlist_push_head(dlist_head *head, dlist_node *node)
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
static MultiXactId * OldestMemberMXactId
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
MultiXactMember members[FLEXIBLE_ARRAY_MEMBER]
static int ZeroMultiXactOffsetPage(int pageno, bool writeXlog)
static dlist_node * dlist_tail_node(dlist_head *head)
MultiXactOffset nextOffset
bool TransactionIdIsInProgress(TransactionId xid)
#define SRF_IS_FIRSTCALL()
MultiXactId perBackendXactIds[FLEXIBLE_ARRAY_MEMBER]
#define MAX_CACHE_ENTRIES
#define dlist_foreach(iter, lhead)
void multixact_redo(XLogReaderState *record)
char * psprintf(const char *fmt,...)
#define ALLOCSET_SMALL_SIZES
void SimpleLruTruncate(SlruCtl ctl, int cutoffPage)
static bool MultiXactOffsetPagePrecedes(int page1, int page2)
#define MULTIXACT_MEMBERS_PER_PAGE
#define END_CRIT_SECTION()
void BootStrapMultiXact(void)
MultiXactId MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
static bool find_multixact_start(MultiXactId multi, MultiXactOffset *result)
#define PreviousMultiXactId(xid)
#define FLEXIBLE_ARRAY_MEMBER
static MultiXactId GetNewMultiXactId(int nmembers, MultiXactOffset *offset)
#define XLOG_MULTIXACT_ZERO_MEM_PAGE
#define START_CRIT_SECTION()
int autovacuum_multixact_freeze_max_age
int errcode(int sqlerrcode)
#define MemSet(start, val, len)
void MultiXactGetCheckptMulti(bool is_shutdown, MultiXactId *nextMulti, MultiXactOffset *nextMultiOffset, MultiXactId *oldestMulti, Oid *oldestMultiDB)
#define MXOffsetToMemberPage(xid)
bool TransactionIdDidCommit(TransactionId transactionId)
static MultiXactId * OldestVisibleMXactId
bool RecoveryInProgress(void)
static void MaybeExtendOffsetSlru(void)
#define MXOffsetToFlagsOffset(xid)
void MultiXactAdvanceNextMXact(MultiXactId minMulti, MultiXactOffset minMultiOffset)
struct mXactCacheEnt mXactCacheEnt
Size SimpleLruShmemSize(int nslots, int nlsns)
#define NUM_MULTIXACTOFFSET_BUFFERS
#define SRF_PERCALL_SETUP()
void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns, LWLock *ctllock, const char *subdir, int tranche_id, SyncRequestHandler sync_handler)
void XLogFlush(XLogRecPtr record)
void RegisterTwoPhaseRecord(TwoPhaseRmgrId rmid, uint16 info, const void *data, uint32 len)
#define SizeOfMultiXactTruncate
#define MultiXactIdToOffsetEntry(xid)
HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
#define MultiXactIdToOffsetPage(xid)
void MultiXactIdSetOldestMember(void)
static MultiXactStateData * MultiXactState
void LWLockRelease(LWLock *lock)
#define SRF_RETURN_NEXT(_funcctx, _result)
MultiXactId oldestMultiXactId
#define SizeOfMultiXactCreate
MultiXactMember members[FLEXIBLE_ARRAY_MEMBER]
void pg_usleep(long microsec)
void multixact_twophase_postabort(TransactionId xid, uint16 info, void *recdata, uint32 len)
#define dlist_container(type, membername, ptr)
void pfree(void *pointer)
static bool MultiXactOffsetWouldWrap(MultiXactOffset boundary, MultiXactOffset start, uint32 distance)
#define XLogRecGetData(decoder)
void appendStringInfo(StringInfo str, const char *fmt,...)
void MultiXactShmemInit(void)
static bool SetOffsetVacuumLimit(bool is_startup)
#define debug_elog6(a, b, c, d, e, f)
#define XLOG_MULTIXACT_CREATE_ID
MultiXactId multiVacLimit
#define MXOffsetToMemberOffset(xid)
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
#define MXACT_MEMBER_XACT_BITMASK
int SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok, TransactionId xid)
static int MXactCacheMembers
char * get_database_name(Oid dbid)
static void WriteMZeroPageXlogRec(int pageno, uint8 info)
#define PG_GETARG_TRANSACTIONID(n)
int multixactoffsetssyncfiletag(const FileTag *ftag, char *path)
#define MultiXactIdToOffsetSegment(xid)
AttInMetadata * attinmeta
static void PerformMembersTruncation(MultiXactOffset oldestOffset, MultiXactOffset newOldestOffset)
void multixact_twophase_postcommit(TransactionId xid, uint16 info, void *recdata, uint32 len)
void SimpleLruWriteAll(SlruCtl ctl, bool allow_redirtied)
MultiXactId multiStopLimit
struct mxtruncinfo mxtruncinfo
#define ISUPDATE_from_mxstatus(status)
static void WriteMTruncateXlogRec(Oid oldestMultiDB, MultiXactId startTruncOff, MultiXactId endTruncOff, MultiXactOffset startTruncMemb, MultiXactOffset endTruncMemb)
#define MultiXactIdIsValid(multi)
bool SimpleLruDoesPhysicalPageExist(SlruCtl ctl, int pageno)
#define debug_elog2(a, b)
void SimpleLruWritePage(SlruCtl ctl, int slotno)
static void dlist_delete(dlist_node *node)
char * mxid_to_string(MultiXactId multi, int nmembers, MultiXactMember *members)
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
#define TWOPHASE_RM_MULTIXACT_ID
#define MULTIXACT_OFFSETS_PER_PAGE
int MultiXactMemberFreezeThreshold(void)
#define AssertArg(condition)
#define XLogRecGetInfo(decoder)
MemoryContext TopMemoryContext
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
MultiXactOffset endTruncMemb
static bool MultiXactMemberPagePrecedes(int page1, int page2)
#define MultiXactOffsetCtl
void appendStringInfoChar(StringInfo str, char ch)
void initStringInfo(StringInfo str)
#define DLIST_STATIC_INIT(name)
MultiXactOffset offsetStopLimit
MultiXactId MultiXactIdCreate(TransactionId xid1, MultiXactStatus status1, TransactionId xid2, MultiXactStatus status2)
void CheckPointMultiXact(void)
void XLogRegisterData(char *data, int len)
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
#define XLogRecGetXid(decoder)
BackendId TwoPhaseGetDummyBackendId(TransactionId xid, bool lock_held)
MultiXactId GetOldestMultiXactId(void)
#define XLOG_MULTIXACT_ZERO_OFF_PAGE
MultiXactOffset oldestOffset
Datum difference(PG_FUNCTION_ARGS)
#define debug_elog3(a, b, c)
Size add_size(Size s1, Size s2)
#define OFFSET_WARN_SEGMENTS
AttInMetadata * TupleDescGetAttInMetadata(TupleDesc tupdesc)
static void ExtendMultiXactOffset(MultiXactId multi)
int SimpleLruReadPage_ReadOnly(SlruCtl ctl, int pageno, TransactionId xid)
#define InvalidMultiXactId
MultiXactOffset startTruncMemb
void SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid, bool is_startup)
static void dlist_init(dlist_head *head)
#define ereport(elevel,...)
static bool ReadMultiXactCounts(uint32 *multixacts, MultiXactOffset *members)
TransactionId MultiXactId
int errmsg_internal(const char *fmt,...)
MultiXactId multiWrapLimit
static SlruCtlData MultiXactOffsetCtlData
#define Assert(condition)
bool SlruScanDirectory(SlruCtl ctl, SlruScanCallback callback, void *data)
static dlist_head MXactCache
static void MultiXactIdSetOldestVisible(void)
#define XLOG_MULTIXACT_TRUNCATE_ID
MemoryContext multi_call_memory_ctx
struct MultiXactMember MultiXactMember
#define MXOffsetToMemberSegment(xid)
int errdetail_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
void AtEOXact_MultiXact(void)
void PostPrepare_MultiXact(TransactionId xid)
MultiXactId startTruncOff
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
bool IsTransactionState(void)
static void mXactCachePut(MultiXactId multi, int nmembers, MultiXactMember *members)
bool MultiXactIdPrecedes(MultiXactId multi1, MultiXactId multi2)
MultiXactId multiWarnLimit
#define HeapTupleGetDatum(tuple)
Size MultiXactShmemSize(void)
void multixact_twophase_recover(TransactionId xid, uint16 info, void *recdata, uint32 len)
static void dlist_move_head(dlist_head *head, dlist_node *node)
#define MXACT_MEMBER_BITS_PER_XACT
static Datum values[MAXATTR]
int errmsg(const char *fmt,...)
char * MemoryContextStrdup(MemoryContext context, const char *string)
static int ZeroMultiXactMemberPage(int pageno, bool writeXlog)
void * MemoryContextAlloc(MemoryContext context, Size size)
static int mXactCacheGetById(MultiXactId multi, MultiXactMember **members)
static int mxactMemberComparator(const void *arg1, const void *arg2)
bool MultiXactIdPrecedesOrEquals(MultiXactId multi1, MultiXactId multi2)
static char * mxstatus_to_string(MultiXactStatus status)
static MemoryContext MXactContext
#define SlruPagePrecedesUnitTests(ctl, per_page)
bool(* PagePrecedes)(int, int)
#define XLogRecHasAnyBlockRefs(decoder)
void SlruDeleteSegment(SlruCtl ctl, int segno)
#define CHECK_FOR_INTERRUPTS()
#define MAX_MEMBERS_IN_LAST_MEMBERS_PAGE
void SendPostmasterSignal(PMSignalReason reason)
int GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members, bool from_pgupgrade, bool onlyLock)
#define SLRU_PAGES_PER_SEGMENT
static void RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset, int nmembers, MultiXactMember *members)
struct MultiXactStateData MultiXactStateData
#define qsort(a, b, c, d)
#define TransactionIdIsValid(xid)
static void PerformOffsetsTruncation(MultiXactId oldestMulti, MultiXactId newOldestMulti)
static void static void status(const char *fmt,...) pg_attribute_printf(1
#define MULTIXACT_MEMBER_SAFE_THRESHOLD
void TruncateMultiXact(MultiXactId newOldestMulti, Oid newOldestMultiDB)
void XLogBeginInsert(void)
#define MultiXactMemberCtl
#define SHARED_MULTIXACT_STATE_SIZE
#define debug_elog5(a, b, c, d, e)
bool MultiXactIdIsRunning(MultiXactId multi, bool isLockOnly)
void ReadMultiXactIdRange(MultiXactId *oldest, MultiXactId *next)
static bool MultiXactOffsetPrecedes(MultiXactOffset offset1, MultiXactOffset offset2)
int SimpleLruZeroPage(SlruCtl ctl, int pageno)
void MultiXactAdvanceOldest(MultiXactId oldestMulti, Oid oldestMultiDB)
static MultiXactId mXactCacheGetBySet(int nmembers, MultiXactMember *members)
static void ExtendMultiXactMember(MultiXactOffset offset, int nmembers)
#define offsetof(type, field)
#define NUM_MULTIXACTMEMBER_BUFFERS
MultiXactId MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status)
#define SRF_RETURN_DONE(_funcctx)
int multixactmemberssyncfiletag(const FileTag *ftag, char *path)
MultiXactId ReadNextMultiXactId(void)
void MultiXactSetNextMXact(MultiXactId nextMulti, MultiXactOffset nextMultiOffset)
#define SRF_FIRSTCALL_INIT()