123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375 |
- /*-------------------------------------------------------------------------
- *
- * transam.h
- * postgres transaction access method support code
- *
- *
- * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * src/include/access/transam.h
- *
- *-------------------------------------------------------------------------
- */
- #ifndef TRANSAM_H
- #define TRANSAM_H
- #include "access/xlogdefs.h"
- /* ----------------
- * Special transaction ID values
- *
- * BootstrapTransactionId is the XID for "bootstrap" operations, and
- * FrozenTransactionId is used for very old tuples. Both should
- * always be considered valid.
- *
- * FirstNormalTransactionId is the first "normal" transaction id.
- * Note: if you need to change it, you must change pg_class.h as well.
- * ----------------
- */
- #define InvalidTransactionId ((TransactionId) 0)
- #define BootstrapTransactionId ((TransactionId) 1)
- #define FrozenTransactionId ((TransactionId) 2)
- #define FirstNormalTransactionId ((TransactionId) 3)
- #define MaxTransactionId ((TransactionId) 0xFFFFFFFF)
- /* ----------------
- * transaction ID manipulation macros
- * ----------------
- */
- #define TransactionIdIsValid(xid) ((xid) != InvalidTransactionId)
- #define TransactionIdIsNormal(xid) ((xid) >= FirstNormalTransactionId)
- #define TransactionIdEquals(id1, id2) ((id1) == (id2))
- #define TransactionIdStore(xid, dest) (*(dest) = (xid))
- #define StoreInvalidTransactionId(dest) (*(dest) = InvalidTransactionId)
- #define EpochFromFullTransactionId(x) ((uint32) ((x).value >> 32))
- #define XidFromFullTransactionId(x) ((uint32) (x).value)
- #define U64FromFullTransactionId(x) ((x).value)
- #define FullTransactionIdEquals(a, b) ((a).value == (b).value)
- #define FullTransactionIdPrecedes(a, b) ((a).value < (b).value)
- #define FullTransactionIdPrecedesOrEquals(a, b) ((a).value <= (b).value)
- #define FullTransactionIdFollows(a, b) ((a).value > (b).value)
- #define FullTransactionIdFollowsOrEquals(a, b) ((a).value >= (b).value)
- #define FullTransactionIdIsValid(x) TransactionIdIsValid(XidFromFullTransactionId(x))
- #define InvalidFullTransactionId FullTransactionIdFromEpochAndXid(0, InvalidTransactionId)
- #define FirstNormalFullTransactionId FullTransactionIdFromEpochAndXid(0, FirstNormalTransactionId)
- #define FullTransactionIdIsNormal(x) FullTransactionIdFollowsOrEquals(x, FirstNormalFullTransactionId)
- /*
- * A 64 bit value that contains an epoch and a TransactionId. This is
- * wrapped in a struct to prevent implicit conversion to/from TransactionId.
- * Not all values represent valid normal XIDs.
- */
- typedef struct FullTransactionId
- {
- uint64 value;
- } FullTransactionId;
- static inline FullTransactionId
- FullTransactionIdFromEpochAndXid(uint32 epoch, TransactionId xid)
- {
- FullTransactionId result;
- result.value = ((uint64) epoch) << 32 | xid;
- return result;
- }
- static inline FullTransactionId
- FullTransactionIdFromU64(uint64 value)
- {
- FullTransactionId result;
- result.value = value;
- return result;
- }
- /* advance a transaction ID variable, handling wraparound correctly */
- #define TransactionIdAdvance(dest) \
- do { \
- (dest)++; \
- if ((dest) < FirstNormalTransactionId) \
- (dest) = FirstNormalTransactionId; \
- } while(0)
- /*
- * Retreat a FullTransactionId variable, stepping over xids that would appear
- * to be special only when viewed as 32bit XIDs.
- */
- static inline void
- FullTransactionIdRetreat(FullTransactionId *dest)
- {
- dest->value--;
- /*
- * In contrast to 32bit XIDs don't step over the "actual" special xids.
- * For 64bit xids these can't be reached as part of a wraparound as they
- * can in the 32bit case.
- */
- if (FullTransactionIdPrecedes(*dest, FirstNormalFullTransactionId))
- return;
- /*
- * But we do need to step over XIDs that'd appear special only for 32bit
- * XIDs.
- */
- while (XidFromFullTransactionId(*dest) < FirstNormalTransactionId)
- dest->value--;
- }
- /*
- * Advance a FullTransactionId variable, stepping over xids that would appear
- * to be special only when viewed as 32bit XIDs.
- */
- static inline void
- FullTransactionIdAdvance(FullTransactionId *dest)
- {
- dest->value++;
- /* see FullTransactionIdAdvance() */
- if (FullTransactionIdPrecedes(*dest, FirstNormalFullTransactionId))
- return;
- while (XidFromFullTransactionId(*dest) < FirstNormalTransactionId)
- dest->value++;
- }
- /* back up a transaction ID variable, handling wraparound correctly */
- #define TransactionIdRetreat(dest) \
- do { \
- (dest)--; \
- } while ((dest) < FirstNormalTransactionId)
- /* compare two XIDs already known to be normal; this is a macro for speed */
- #define NormalTransactionIdPrecedes(id1, id2) \
- (AssertMacro(TransactionIdIsNormal(id1) && TransactionIdIsNormal(id2)), \
- (int32) ((id1) - (id2)) < 0)
- /* compare two XIDs already known to be normal; this is a macro for speed */
- #define NormalTransactionIdFollows(id1, id2) \
- (AssertMacro(TransactionIdIsNormal(id1) && TransactionIdIsNormal(id2)), \
- (int32) ((id1) - (id2)) > 0)
- /* ----------
- * Object ID (OID) zero is InvalidOid.
- *
- * OIDs 1-9999 are reserved for manual assignment (see .dat files in
- * src/include/catalog/). Of these, 8000-9999 are reserved for
- * development purposes (such as in-progress patches and forks);
- * they should not appear in released versions.
- *
- * OIDs 10000-11999 are reserved for assignment by genbki.pl, for use
- * when the .dat files in src/include/catalog/ do not specify an OID
- * for a catalog entry that requires one. Note that genbki.pl assigns
- * these OIDs independently in each catalog, so they're not guaranteed
- * to be globally unique. Furthermore, the bootstrap backend and
- * initdb's post-bootstrap processing can also assign OIDs in this range.
- * The normal OID-generation logic takes care of any OID conflicts that
- * might arise from that.
- *
- * OIDs 12000-16383 are reserved for unpinned objects created by initdb's
- * post-bootstrap processing. initdb forces the OID generator up to
- * 12000 as soon as it's made the pinned objects it's responsible for.
- *
- * OIDs beginning at 16384 are assigned from the OID generator
- * during normal multiuser operation. (We force the generator up to
- * 16384 as soon as we are in normal operation.)
- *
- * The choices of 8000, 10000 and 12000 are completely arbitrary, and can be
- * moved if we run low on OIDs in any category. Changing the macros below,
- * and updating relevant documentation (see bki.sgml and RELEASE_CHANGES),
- * should be sufficient to do this. Moving the 16384 boundary between
- * initdb-assigned OIDs and user-defined objects would be substantially
- * more painful, however, since some user-defined OIDs will appear in
- * on-disk data; such a change would probably break pg_upgrade.
- *
- * NOTE: if the OID generator wraps around, we skip over OIDs 0-16383
- * and resume with 16384. This minimizes the odds of OID conflict, by not
- * reassigning OIDs that might have been assigned during initdb. Critically,
- * it also ensures that no user-created object will be considered pinned.
- * ----------
- */
- #define FirstGenbkiObjectId 10000
- #define FirstUnpinnedObjectId 12000
- #define FirstNormalObjectId 16384
- /*
- * VariableCache is a data structure in shared memory that is used to track
- * OID and XID assignment state. For largely historical reasons, there is
- * just one struct with different fields that are protected by different
- * LWLocks.
- *
- * Note: xidWrapLimit and oldestXidDB are not "active" values, but are
- * used just to generate useful messages when xidWarnLimit or xidStopLimit
- * are exceeded.
- */
- typedef struct VariableCacheData
- {
- /*
- * These fields are protected by OidGenLock.
- */
- Oid nextOid; /* next OID to assign */
- uint32 oidCount; /* OIDs available before must do XLOG work */
- /*
- * These fields are protected by XidGenLock.
- */
- FullTransactionId nextXid; /* next XID to assign */
- TransactionId oldestXid; /* cluster-wide minimum datfrozenxid */
- TransactionId xidVacLimit; /* start forcing autovacuums here */
- TransactionId xidWarnLimit; /* start complaining here */
- TransactionId xidStopLimit; /* refuse to advance nextXid beyond here */
- TransactionId xidWrapLimit; /* where the world ends */
- Oid oldestXidDB; /* database with minimum datfrozenxid */
- /*
- * These fields are protected by CommitTsLock
- */
- TransactionId oldestCommitTsXid;
- TransactionId newestCommitTsXid;
- /*
- * These fields are protected by ProcArrayLock.
- */
- FullTransactionId latestCompletedXid; /* newest full XID that has
- * committed or aborted */
- /*
- * Number of top-level transactions with xids (i.e. which may have
- * modified the database) that completed in some form since the start of
- * the server. This currently is solely used to check whether
- * GetSnapshotData() needs to recompute the contents of the snapshot, or
- * not. There are likely other users of this. Always above 1.
- */
- uint64 xactCompletionCount;
- /*
- * These fields are protected by XactTruncationLock
- */
- TransactionId oldestClogXid; /* oldest it's safe to look up in clog */
- } VariableCacheData;
- typedef VariableCacheData *VariableCache;
- /* ----------------
- * extern declarations
- * ----------------
- */
- /* in transam/xact.c */
- extern bool TransactionStartedDuringRecovery(void);
- /* in transam/varsup.c */
- extern PGDLLIMPORT VariableCache ShmemVariableCache;
- /*
- * prototypes for functions in transam/transam.c
- */
- extern bool TransactionIdDidCommit(TransactionId transactionId);
- extern bool TransactionIdDidAbort(TransactionId transactionId);
- extern void TransactionIdCommitTree(TransactionId xid, int nxids, TransactionId *xids);
- extern void TransactionIdAsyncCommitTree(TransactionId xid, int nxids, TransactionId *xids, XLogRecPtr lsn);
- extern void TransactionIdAbortTree(TransactionId xid, int nxids, TransactionId *xids);
- extern bool TransactionIdPrecedes(TransactionId id1, TransactionId id2);
- extern bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2);
- extern bool TransactionIdFollows(TransactionId id1, TransactionId id2);
- extern bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2);
- extern TransactionId TransactionIdLatest(TransactionId mainxid,
- int nxids, const TransactionId *xids);
- extern XLogRecPtr TransactionIdGetCommitLSN(TransactionId xid);
- /* in transam/varsup.c */
- extern FullTransactionId GetNewTransactionId(bool isSubXact);
- extern void AdvanceNextFullTransactionIdPastXid(TransactionId xid);
- extern FullTransactionId ReadNextFullTransactionId(void);
- extern void SetTransactionIdLimit(TransactionId oldest_datfrozenxid,
- Oid oldest_datoid);
- extern void AdvanceOldestClogXid(TransactionId oldest_datfrozenxid);
- extern bool ForceTransactionIdLimitUpdate(void);
- extern Oid GetNewObjectId(void);
- extern void StopGeneratingPinnedObjectIds(void);
- #ifdef USE_ASSERT_CHECKING
- extern void AssertTransactionIdInAllowableRange(TransactionId xid);
- #else
- #define AssertTransactionIdInAllowableRange(xid) ((void)true)
- #endif
- /*
- * Some frontend programs include this header. For compilers that emit static
- * inline functions even when they're unused, that leads to unsatisfied
- * external references; hence hide them with #ifndef FRONTEND.
- */
- #ifndef FRONTEND
- /*
- * For callers that just need the XID part of the next transaction ID.
- */
- static inline TransactionId
- ReadNextTransactionId(void)
- {
- return XidFromFullTransactionId(ReadNextFullTransactionId());
- }
- /* return transaction ID backed up by amount, handling wraparound correctly */
- static inline TransactionId
- TransactionIdRetreatedBy(TransactionId xid, uint32 amount)
- {
- xid -= amount;
- while (xid < FirstNormalTransactionId)
- xid--;
- return xid;
- }
- /* return the older of the two IDs */
- static inline TransactionId
- TransactionIdOlder(TransactionId a, TransactionId b)
- {
- if (!TransactionIdIsValid(a))
- return b;
- if (!TransactionIdIsValid(b))
- return a;
- if (TransactionIdPrecedes(a, b))
- return a;
- return b;
- }
- /* return the older of the two IDs, assuming they're both normal */
- static inline TransactionId
- NormalTransactionIdOlder(TransactionId a, TransactionId b)
- {
- Assert(TransactionIdIsNormal(a));
- Assert(TransactionIdIsNormal(b));
- if (NormalTransactionIdPrecedes(a, b))
- return a;
- return b;
- }
- /* return the newer of the two IDs */
- static inline FullTransactionId
- FullTransactionIdNewer(FullTransactionId a, FullTransactionId b)
- {
- if (!FullTransactionIdIsValid(a))
- return b;
- if (!FullTransactionIdIsValid(b))
- return a;
- if (FullTransactionIdFollows(a, b))
- return a;
- return b;
- }
- #endif /* FRONTEND */
- #endif /* TRANSAM_H */
|