90 #include "utils/fmgrprotos.h"
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)
295 #define MaxOldestSlot (MaxBackends + max_prepared_xacts)
328 #define MAX_CACHE_ENTRIES 256
332 #ifdef MULTIXACT_DEBUG
333 #define debug_elog2(a,b) elog(a,b)
334 #define debug_elog3(a,b,c) elog(a,b,c)
335 #define debug_elog4(a,b,c,d) elog(a,b,c,d)
336 #define debug_elog5(a,b,c,d,e) elog(a,b,c,d,e)
337 #define debug_elog6(a,b,c,d,e,f) elog(a,b,c,d,e,f)
339 #define debug_elog2(a,b)
340 #define debug_elog3(a,b,c)
341 #define debug_elog4(a,b,c,d)
342 #define debug_elog5(a,b,c,d,e)
343 #define debug_elog6(a,b,c,d,e,f)
412 members[0].
xid = xid1;
413 members[0].
status = status1;
414 members[1].
xid = xid2;
415 members[1].
status = status2;
494 for (
i = 0;
i < nmembers;
i++)
497 (members[
i].status == status))
522 for (
i = 0,
j = 0;
i < nmembers;
i++)
533 newMembers[
j].
xid = xid;
534 newMembers[
j++].
status = status;
584 for (
i = 0;
i < nmembers;
i++)
599 for (
i = 0;
i < nmembers;
i++)
712 oldestMXact = thisoldest;
802 bool has_update =
false;
804 for (
i = 0;
i < nmembers;
i++)
809 elog(
ERROR,
"new multixact has more than one updating member: %s",
913 for (
i = 0;
i < nmembers;
i++, offset++)
929 if (pageno != prev_pageno)
937 if (lock != prevlock)
939 if (prevlock != NULL)
946 prev_pageno = pageno;
952 *memberptr = members[
i].
xid;
957 flagsval = *flagsptr;
959 flagsval |= (members[
i].
status << bshift);
960 *flagsptr = flagsval;
965 if (prevlock != NULL)
994 elog(
ERROR,
"cannot assign MultiXactIds during recovery");
1049 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1050 errmsg(
"database is not accepting commands that assign new MultiXactIds to avoid wraparound data loss in database \"%s\"",
1052 errhint(
"Execute a database-wide VACUUM in that database.\n"
1053 "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
1056 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1057 errmsg(
"database is not accepting commands that assign new MultiXactIds to avoid wraparound data loss in database with OID %u",
1059 errhint(
"Execute a database-wide VACUUM in that database.\n"
1060 "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
1078 (
errmsg_plural(
"database \"%s\" must be vacuumed before %u more MultiXactId is used",
1079 "database \"%s\" must be vacuumed before %u more MultiXactIds are used",
1080 multiWrapLimit - result,
1082 multiWrapLimit - result),
1083 errhint(
"Execute a database-wide VACUUM in that database.\n"
1084 "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
1087 (
errmsg_plural(
"database with OID %u must be vacuumed before %u more MultiXactId is used",
1088 "database with OID %u must be vacuumed before %u more MultiXactIds are used",
1089 multiWrapLimit - result,
1091 multiWrapLimit - result),
1092 errhint(
"Execute a database-wide VACUUM in that database.\n"
1093 "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
1112 if (nextOffset == 0)
1118 *offset = nextOffset;
1138 #define OFFSET_WARN_SEGMENTS 20
1147 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1148 errmsg(
"multixact \"members\" limit exceeded"),
1149 errdetail_plural(
"This command would create a multixact with %u members, but the remaining space is only enough for %u member.",
1150 "This command would create a multixact with %u members, but the remaining space is only enough for %u members.",
1154 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.",
1184 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1185 errmsg_plural(
"database with OID %u must be vacuumed before %d more multixact member is used",
1186 "database with OID %u must be vacuumed before %d more multixact members are used",
1190 errhint(
"Execute a database-wide VACUUM in that database with reduced vacuum_multixact_freeze_min_age and vacuum_multixact_freeze_table_age settings.")));
1253 bool from_pgupgrade,
bool isLockOnly)
1329 (
errcode(ERRCODE_INTERNAL_ERROR),
1330 errmsg(
"MultiXactId %u does no longer exist -- apparent wraparound",
1335 (
errcode(ERRCODE_INTERNAL_ERROR),
1336 errmsg(
"MultiXactId %u has not been created yet -- apparent wraparound",
1393 tmpMXact = multi + 1;
1395 if (nextMXact == tmpMXact)
1398 length = nextOffset - offset;
1408 prev_pageno = pageno;
1413 if (pageno != prev_pageno)
1423 if (newlock != lock)
1434 nextMXOffset = *offptr;
1436 if (nextMXOffset == 0)
1443 WAIT_EVENT_MULTIXACT_CREATION);
1448 length = nextMXOffset - offset;
1464 for (
int i = 0;
i < length;
i++, offset++)
1475 if (pageno != prev_pageno)
1485 if (newlock != lock)
1494 prev_pageno = pageno;
1511 ptr[truelength].
xid = *xactptr;
1545 if (member1.
xid > member2.
xid)
1547 if (member1.
xid < member2.
xid)
1596 return entry->
multi;
1624 if (entry->
multi == multi)
1672 "MultiXact cache context",
1681 entry->
multi = multi;
1714 return "fornokeyupd";
1722 elog(
ERROR,
"unrecognized multixact status %d", status);
1730 static char *
str = NULL;
1742 for (
i = 1;
i < nmembers;
i++)
1903 #define SHARED_MULTIXACT_STATE_SIZE \
1904 add_size(offsetof(MultiXactStateData, perBackendXactIds), \
1905 mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot))
2208 MemSet(xidptr, 0, BLCKSZ - memberoff);
2247 "MultiXact: checkpoint is nextMulti %u, nextOffset %u, oldestMulti %u in DB %u",
2248 *nextMulti, *nextMultiOffset, *oldestMulti, *oldestMultiDB);
2257 TRACE_POSTGRESQL_MULTIXACT_CHECKPOINT_START(
true);
2267 TRACE_POSTGRESQL_MULTIXACT_CHECKPOINT_DONE(
true);
2283 nextMulti, nextMultiOffset);
2321 bool needs_offset_vacuum;
2340 multiStopLimit = multiWrapLimit - 3000000;
2354 multiWarnLimit = multiWrapLimit - 40000000;
2383 (
errmsg_internal(
"MultiXactId wrap limit is %u, limited by database with OID %u",
2384 multiWrapLimit, oldest_datoid)));
2415 char *oldest_datname;
2429 oldest_datname = NULL;
2433 (
errmsg_plural(
"database \"%s\" must be vacuumed before %u more MultiXactId is used",
2434 "database \"%s\" must be vacuumed before %u more MultiXactIds are used",
2435 multiWrapLimit - curMulti,
2437 multiWrapLimit - curMulti),
2438 errhint(
"To avoid MultiXactId assignment failures, execute a database-wide VACUUM in that database.\n"
2439 "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
2442 (
errmsg_plural(
"database with OID %u must be vacuumed before %u more MultiXactId is used",
2443 "database with OID %u must be vacuumed before %u more MultiXactIds are used",
2444 multiWrapLimit - curMulti,
2446 multiWrapLimit - curMulti),
2447 errhint(
"To avoid MultiXactId assignment failures, execute a database-wide VACUUM in that database.\n"
2448 "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
2544 while (nmembers > 0)
2555 if (flagsoff == 0 && flagsbit == 0)
2632 oldestMXact = nextMXact;
2640 oldestMXact = thisoldest;
2644 oldestMXact = thisoldest;
2671 bool oldestOffsetKnown =
false;
2672 bool prevOldestOffsetKnown;
2700 if (oldestMultiXactId == nextMXact)
2706 oldestOffset = nextOffset;
2707 oldestOffsetKnown =
true;
2720 if (oldestOffsetKnown)
2726 (
errmsg(
"MultiXact member wraparound protections are disabled because oldest checkpointed MultiXact %u does not exist on disk",
2727 oldestMultiXactId)));
2737 if (oldestOffsetKnown)
2740 offsetStopLimit = oldestOffset - (oldestOffset %
2746 if (!prevOldestOffsetKnown && !is_startup)
2748 (
errmsg(
"MultiXact member wraparound protections are now enabled")));
2751 (
errmsg_internal(
"MultiXact member stop limit is now %u based on MultiXact %u",
2752 offsetStopLimit, oldestMultiXactId)));
2754 else if (prevOldestOffsetKnown)
2762 oldestOffset = prevOldestOffset;
2763 oldestOffsetKnown =
true;
2764 offsetStopLimit = prevOffsetStopLimit;
2777 return !oldestOffsetKnown ||
2800 finish =
start + distance;
2823 if (
start < boundary)
2824 return finish >= boundary || finish <
start;
2826 return finish >= boundary && finish <
start;
2883 bool oldestOffsetKnown;
2893 if (!oldestOffsetKnown)
2896 *members = nextOffset - oldestOffset;
2897 *multixacts = nextMultiXactId - oldestMultiXactId;
2933 uint32 victim_multixacts;
2951 victim_multixacts = multixacts * fraction;
2954 if (victim_multixacts > multixacts)
2956 return multixacts - victim_multixacts;
2997 int segment = startsegment;
3003 while (segment != endsegment)
3005 elog(
DEBUG2,
"truncating multixact members segment %x", segment);
3009 if (segment == maxsegment)
3123 if (oldestMulti == nextMulti)
3126 oldestOffset = nextOffset;
3131 (
errmsg(
"oldest MultiXact %u not found, earliest MultiXact %u, skipping truncation",
3132 oldestMulti, earliest)));
3141 if (newOldestMulti == nextMulti)
3144 newOldestOffset = nextOffset;
3149 (
errmsg(
"cannot truncate up to MultiXact %u because it does not exist on disk, skipping truncation",
3155 elog(
DEBUG1,
"performing multixact truncation: "
3156 "offsets [%u, %u), offsets segments [%x, %x), "
3157 "members [%u, %u), members segments [%x, %x)",
3158 oldestMulti, newOldestMulti,
3161 oldestOffset, newOldestOffset,
3184 oldestMulti, newOldestMulti,
3185 oldestOffset, newOldestOffset);
3415 elog(
DEBUG1,
"replaying multixact truncation: "
3416 "offsets [%u, %u), offsets segments [%x, %x), "
3417 "members [%u, %u), members segments [%x, %x)",
3449 elog(
PANIC,
"multixact_redo: unknown op code %u", info);
3467 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3468 errmsg(
"invalid MultiXactId: %u", mxid)));
3478 multi =
palloc(
sizeof(mxact));
3485 elog(
ERROR,
"return type must be a row type");
3496 while (multi->iter < multi->nmembers)
static void pg_atomic_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
int autovacuum_multixact_freeze_max_age
static Datum values[MAXATTR]
#define Assert(condition)
TransactionId MultiXactId
#define FLEXIBLE_ARRAY_MEMBER
#define MemSet(start, val, len)
bool ConditionVariableCancelSleep(void)
void ConditionVariableBroadcast(ConditionVariable *cv)
void ConditionVariableInit(ConditionVariable *cv)
void ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info)
char * get_database_name(Oid dbid)
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
int errmsg_internal(const char *fmt,...)
int errdetail_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
AttInMetadata * TupleDescGetAttInMetadata(TupleDesc tupdesc)
#define PG_GETARG_TRANSACTIONID(n)
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
#define SRF_IS_FIRSTCALL()
#define SRF_PERCALL_SETUP()
#define SRF_RETURN_NEXT(_funcctx, _result)
#define SRF_FIRSTCALL_INIT()
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
#define SRF_RETURN_DONE(_funcctx)
Datum difference(PG_FUNCTION_ARGS)
int multixact_offset_buffers
int multixact_member_buffers
#define dclist_container(type, membername, ptr)
static dlist_node * dclist_tail_node(dclist_head *head)
static uint32 dclist_count(const dclist_head *head)
static void dclist_move_head(dclist_head *head, dlist_node *node)
static void dclist_delete_from(dclist_head *head, dlist_node *node)
#define DCLIST_STATIC_INIT(name)
static void dclist_push_head(dclist_head *head, dlist_node *node)
static void dclist_init(dclist_head *head)
#define dclist_foreach(iter, lhead)
if(TABLE==NULL||TABLE_index==NULL)
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
void LWLockRelease(LWLock *lock)
@ LWTRANCHE_MULTIXACTOFFSET_SLRU
@ LWTRANCHE_MULTIXACTMEMBER_SLRU
@ LWTRANCHE_MULTIXACTMEMBER_BUFFER
@ LWTRANCHE_MULTIXACTOFFSET_BUFFER
MemoryContext TopTransactionContext
void pfree(void *pointer)
MemoryContext TopMemoryContext
void * MemoryContextAlloc(MemoryContext context, Size size)
char * MemoryContextStrdup(MemoryContext context, const char *string)
#define AllocSetContextCreate
#define ALLOCSET_SMALL_SIZES
#define START_CRIT_SECTION()
#define CHECK_FOR_INTERRUPTS()
#define END_CRIT_SECTION()
#define MXOffsetToMemberPage(xid)
static void WriteMTruncateXlogRec(Oid oldestMultiDB, MultiXactId startTruncOff, MultiXactId endTruncOff, MultiXactOffset startTruncMemb, MultiXactOffset endTruncMemb)
static SlruCtlData MultiXactOffsetCtlData
void MultiXactShmemInit(void)
#define MULTIXACT_MEMBER_SAFE_THRESHOLD
static bool MultiXactMemberPagePrecedes(int64 page1, int64 page2)
static MultiXactId GetNewMultiXactId(int nmembers, MultiXactOffset *offset)
static int mXactCacheGetById(MultiXactId multi, MultiXactMember **members)
MultiXactId MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status)
static int ZeroMultiXactMemberPage(int64 pageno, bool writeXlog)
#define MXACT_MEMBER_BITS_PER_XACT
static void ExtendMultiXactMember(MultiXactOffset offset, int nmembers)
void ReadMultiXactIdRange(MultiXactId *oldest, MultiXactId *next)
static void PerformOffsetsTruncation(MultiXactId oldestMulti, MultiXactId newOldestMulti)
#define MXACT_MEMBER_XACT_BITMASK
#define MultiXactIdToOffsetEntry(xid)
bool MultiXactIdPrecedes(MultiXactId multi1, MultiXactId multi2)
void multixact_redo(XLogReaderState *record)
#define MULTIXACT_OFFSETS_PER_PAGE
#define debug_elog5(a, b, c, d, e)
static void MultiXactIdSetOldestVisible(void)
int multixactoffsetssyncfiletag(const FileTag *ftag, char *path)
void multixact_twophase_postcommit(TransactionId xid, uint16 info, void *recdata, uint32 len)
static bool find_multixact_start(MultiXactId multi, MultiXactOffset *result)
void MultiXactSetNextMXact(MultiXactId nextMulti, MultiXactOffset nextMultiOffset)
void multixact_twophase_recover(TransactionId xid, uint16 info, void *recdata, uint32 len)
#define MultiXactMemberCtl
static bool SlruScanDirCbFindEarliest(SlruCtl ctl, char *filename, int64 segpage, void *data)
void AtPrepare_MultiXact(void)
static bool MultiXactOffsetWouldWrap(MultiXactOffset boundary, MultiXactOffset start, uint32 distance)
bool MultiXactIdPrecedesOrEquals(MultiXactId multi1, MultiXactId multi2)
#define MXOffsetToFlagsBitShift(xid)
void MultiXactAdvanceOldest(MultiXactId oldestMulti, Oid oldestMultiDB)
static void mXactCachePut(MultiXactId multi, int nmembers, MultiXactMember *members)
#define MXOffsetToFlagsOffset(xid)
static void MaybeExtendOffsetSlru(void)
bool MultiXactIdIsRunning(MultiXactId multi, bool isLockOnly)
void MultiXactIdSetOldestMember(void)
static void PerformMembersTruncation(MultiXactOffset oldestOffset, MultiXactOffset newOldestOffset)
static MemoryContext MXactContext
#define SHARED_MULTIXACT_STATE_SIZE
static MultiXactId * OldestVisibleMXactId
struct mxtruncinfo mxtruncinfo
static int mxactMemberComparator(const void *arg1, const void *arg2)
struct MultiXactStateData MultiXactStateData
static void ExtendMultiXactOffset(MultiXactId multi)
void PostPrepare_MultiXact(TransactionId xid)
Size MultiXactShmemSize(void)
#define MultiXactOffsetCtl
void multixact_twophase_postabort(TransactionId xid, uint16 info, void *recdata, uint32 len)
#define PreviousMultiXactId(xid)
void MultiXactGetCheckptMulti(bool is_shutdown, MultiXactId *nextMulti, MultiXactOffset *nextMultiOffset, MultiXactId *oldestMulti, Oid *oldestMultiDB)
static void WriteMZeroPageXlogRec(int64 pageno, uint8 info)
void SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid, bool is_startup)
static void RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset, int nmembers, MultiXactMember *members)
int multixactmemberssyncfiletag(const FileTag *ftag, char *path)
#define MAX_CACHE_ENTRIES
#define MXOffsetToMemberOffset(xid)
MultiXactId GetOldestMultiXactId(void)
void CheckPointMultiXact(void)
MultiXactId MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members)
static bool ReadMultiXactCounts(uint32 *multixacts, MultiXactOffset *members)
struct mXactCacheEnt mXactCacheEnt
static MultiXactId mXactCacheGetBySet(int nmembers, MultiXactMember *members)
static dclist_head MXactCache
#define MXOffsetToMemberSegment(xid)
char * mxid_to_string(MultiXactId multi, int nmembers, MultiXactMember *members)
#define debug_elog3(a, b, c)
#define debug_elog4(a, b, c, d)
static bool MultiXactOffsetPagePrecedes(int64 page1, int64 page2)
static bool SetOffsetVacuumLimit(bool is_startup)
int MultiXactMemberFreezeThreshold(void)
void MultiXactAdvanceNextMXact(MultiXactId minMulti, MultiXactOffset minMultiOffset)
static MultiXactId * OldestMemberMXactId
#define MAX_MEMBERS_IN_LAST_MEMBERS_PAGE
static MultiXactStateData * MultiXactState
static int ZeroMultiXactOffsetPage(int64 pageno, bool writeXlog)
static char * mxstatus_to_string(MultiXactStatus status)
#define OFFSET_WARN_SEGMENTS
Datum pg_get_multixact_members(PG_FUNCTION_ARGS)
MultiXactId ReadNextMultiXactId(void)
void BootStrapMultiXact(void)
#define debug_elog6(a, b, c, d, e, f)
#define MULTIXACT_MEMBERS_PER_PAGE
MultiXactId MultiXactIdCreate(TransactionId xid1, MultiXactStatus status1, TransactionId xid2, MultiXactStatus status2)
void TruncateMultiXact(MultiXactId newOldestMulti, Oid newOldestMultiDB)
#define MULTIXACT_MEMBER_DANGER_THRESHOLD
bool check_multixact_offset_buffers(int *newval, void **extra, GucSource source)
static bool MultiXactOffsetPrecedes(MultiXactOffset offset1, MultiXactOffset offset2)
#define MultiXactIdToOffsetSegment(xid)
bool check_multixact_member_buffers(int *newval, void **extra, GucSource source)
void AtEOXact_MultiXact(void)
#define MultiXactIdToOffsetPage(xid)
static SlruCtlData MultiXactMemberCtlData
#define debug_elog2(a, b)
void StartupMultiXact(void)
int GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members, bool from_pgupgrade, bool isLockOnly)
#define MultiXactIdIsValid(multi)
#define XLOG_MULTIXACT_ZERO_MEM_PAGE
#define XLOG_MULTIXACT_ZERO_OFF_PAGE
@ MultiXactStatusForShare
@ MultiXactStatusForNoKeyUpdate
@ MultiXactStatusNoKeyUpdate
@ MultiXactStatusForUpdate
@ MultiXactStatusForKeyShare
#define ISUPDATE_from_mxstatus(status)
#define InvalidMultiXactId
#define XLOG_MULTIXACT_TRUNCATE_ID
#define SizeOfMultiXactCreate
#define SizeOfMultiXactTruncate
#define XLOG_MULTIXACT_CREATE_ID
#define MaxMultiXactOffset
struct MultiXactMember MultiXactMember
static rewind_source * source
void SendPostmasterSignal(PMSignalReason reason)
@ PMSIGNAL_START_AUTOVAC_LAUNCHER
#define qsort(a, b, c, d)
#define DELAY_CHKPT_START
bool TransactionIdIsInProgress(TransactionId xid)
char * psprintf(const char *fmt,...)
MemoryContextSwitchTo(old_ctx)
Size add_size(Size s1, Size s2)
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
static pg_noinline void Size size
void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns, const char *subdir, int buffer_tranche_id, int bank_tranche_id, SyncRequestHandler sync_handler, bool long_segment_names)
int SimpleLruReadPage_ReadOnly(SlruCtl ctl, int64 pageno, TransactionId xid)
void SimpleLruWritePage(SlruCtl ctl, int slotno)
void SimpleLruWriteAll(SlruCtl ctl, bool allow_redirtied)
bool SimpleLruDoesPhysicalPageExist(SlruCtl ctl, int64 pageno)
void SlruDeleteSegment(SlruCtl ctl, int64 segno)
bool SlruScanDirectory(SlruCtl ctl, SlruScanCallback callback, void *data)
int SimpleLruReadPage(SlruCtl ctl, int64 pageno, bool write_ok, TransactionId xid)
int SlruSyncFileTag(SlruCtl ctl, const FileTag *ftag, char *path)
int SimpleLruZeroPage(SlruCtl ctl, int64 pageno)
void SimpleLruTruncate(SlruCtl ctl, int64 cutoffPage)
Size SimpleLruShmemSize(int nslots, int nlsns)
bool check_slru_buffers(const char *name, int *newval)
static LWLock * SimpleLruGetBankLock(SlruCtl ctl, int64 pageno)
#define SlruPagePrecedesUnitTests(ctl, per_page)
#define SLRU_PAGES_PER_SEGMENT
void appendStringInfo(StringInfo str, const char *fmt,...)
void appendStringInfoChar(StringInfo str, char ch)
void initStringInfo(StringInfo str)
AttInMetadata * attinmeta
MemoryContext multi_call_memory_ctx
MultiXactId multiWrapLimit
MultiXactId multiStopLimit
MultiXactId multiWarnLimit
MultiXactId multiVacLimit
MultiXactOffset offsetStopLimit
MultiXactOffset nextOffset
MultiXactId oldestMultiXactId
MultiXactId perBackendXactIds[FLEXIBLE_ARRAY_MEMBER]
MultiXactOffset oldestOffset
ConditionVariable nextoff_cv
MultiXactMember members[FLEXIBLE_ARRAY_MEMBER]
int64 earliestExistingPage
MultiXactMember members[FLEXIBLE_ARRAY_MEMBER]
MultiXactOffset startTruncMemb
MultiXactOffset endTruncMemb
MultiXactId startTruncOff
@ SYNC_HANDLER_MULTIXACT_MEMBER
@ SYNC_HANDLER_MULTIXACT_OFFSET
bool TransactionIdDidCommit(TransactionId transactionId)
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
#define TransactionIdEquals(id1, id2)
#define TransactionIdIsValid(xid)
void RegisterTwoPhaseRecord(TwoPhaseRmgrId rmid, uint16 info, const void *data, uint32 len)
ProcNumber TwoPhaseGetDummyProcNumber(TransactionId xid, bool lock_held)
#define TWOPHASE_RM_MULTIXACT_ID
void AdvanceNextFullTransactionIdPastXid(TransactionId xid)
bool IsTransactionState(void)
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
bool RecoveryInProgress(void)
void XLogFlush(XLogRecPtr record)
void XLogRegisterData(char *data, uint32 len)
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
void XLogBeginInsert(void)
#define XLogRecGetInfo(decoder)
#define XLogRecGetData(decoder)
#define XLogRecGetXid(decoder)
#define XLogRecHasAnyBlockRefs(decoder)