PostgreSQL Source Code  git master
heapam_visibility.c File Reference
#include "postgres.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "access/multixact.h"
#include "access/subtrans.h"
#include "access/tableam.h"
#include "access/transam.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "storage/bufmgr.h"
#include "storage/procarray.h"
#include "utils/builtins.h"
#include "utils/combocid.h"
#include "utils/snapmgr.h"
Include dependency graph for heapam_visibility.c:

Go to the source code of this file.

Functions

static void SetHintBits (HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
 
void HeapTupleSetHintBits (HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
 
static bool HeapTupleSatisfiesSelf (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
static bool HeapTupleSatisfiesAny (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
static bool HeapTupleSatisfiesToast (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
TM_Result HeapTupleSatisfiesUpdate (HeapTuple htup, CommandId curcid, Buffer buffer)
 
static bool HeapTupleSatisfiesDirty (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
static bool HeapTupleSatisfiesMVCC (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
HTSV_Result HeapTupleSatisfiesVacuum (HeapTuple htup, TransactionId OldestXmin, Buffer buffer)
 
static bool HeapTupleSatisfiesNonVacuumable (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
bool HeapTupleIsSurelyDead (HeapTuple htup, TransactionId OldestXmin)
 
bool HeapTupleHeaderIsOnlyLocked (HeapTupleHeader tuple)
 
static bool TransactionIdInArray (TransactionId xid, TransactionId *xip, Size num)
 
static bool HeapTupleSatisfiesHistoricMVCC (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
bool HeapTupleSatisfiesVisibility (HeapTuple tup, Snapshot snapshot, Buffer buffer)
 

Function Documentation

◆ HeapTupleHeaderIsOnlyLocked()

bool HeapTupleHeaderIsOnlyLocked ( HeapTupleHeader  tuple)

Definition at line 1475 of file heapam_visibility.c.

References Assert, HEAP_XMAX_INVALID, HEAP_XMAX_IS_MULTI, HEAP_XMAX_LOCK_ONLY, HeapTupleGetUpdateXid(), HeapTupleHeaderGetRawXmax, HeapTupleHeaderData::t_infomask, TransactionIdDidCommit(), TransactionIdIsCurrentTransactionId(), TransactionIdIsInProgress(), and TransactionIdIsValid.

Referenced by heap_delete(), heap_get_latest_tid(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), HeapTupleSatisfiesVacuum(), and rewrite_heap_tuple().

1476 {
1477  TransactionId xmax;
1478 
1479  /* if there's no valid Xmax, then there's obviously no update either */
1480  if (tuple->t_infomask & HEAP_XMAX_INVALID)
1481  return true;
1482 
1483  if (tuple->t_infomask & HEAP_XMAX_LOCK_ONLY)
1484  return true;
1485 
1486  /* invalid xmax means no update */
1488  return true;
1489 
1490  /*
1491  * if HEAP_XMAX_LOCK_ONLY is not set and not a multi, then this must
1492  * necessarily have been updated
1493  */
1494  if (!(tuple->t_infomask & HEAP_XMAX_IS_MULTI))
1495  return false;
1496 
1497  /* ... but if it's a multi, then perhaps the updating Xid aborted. */
1498  xmax = HeapTupleGetUpdateXid(tuple);
1499 
1500  /* not LOCKED_ONLY, so it has to have an xmax */
1502 
1504  return false;
1505  if (TransactionIdIsInProgress(xmax))
1506  return false;
1507  if (TransactionIdDidCommit(xmax))
1508  return false;
1509 
1510  /*
1511  * not current, not in progress, not committed -- must have aborted or
1512  * crashed
1513  */
1514  return true;
1515 }
#define HEAP_XMAX_LOCK_ONLY
Definition: htup_details.h:196
uint32 TransactionId
Definition: c.h:514
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:853
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:987
TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple)
Definition: heapam.c:6532
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:375
#define HEAP_XMAX_INVALID
Definition: htup_details.h:207
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:208
#define Assert(condition)
Definition: c.h:739
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ HeapTupleIsSurelyDead()

bool HeapTupleIsSurelyDead ( HeapTuple  htup,
TransactionId  OldestXmin 
)

Definition at line 1421 of file heapam_visibility.c.

References Assert, HEAP_XMAX_COMMITTED, HEAP_XMAX_INVALID, HEAP_XMAX_IS_LOCKED_ONLY, HEAP_XMAX_IS_MULTI, HeapTupleHeaderGetRawXmax, HeapTupleHeaderXminCommitted, HeapTupleHeaderXminInvalid, InvalidOid, ItemPointerIsValid, HeapTupleData::t_data, HeapTupleHeaderData::t_infomask, HeapTupleData::t_self, HeapTupleData::t_tableOid, TransactionIdPrecedes(), and true.

Referenced by heap_hot_search_buffer().

1422 {
1423  HeapTupleHeader tuple = htup->t_data;
1424 
1425  Assert(ItemPointerIsValid(&htup->t_self));
1426  Assert(htup->t_tableOid != InvalidOid);
1427 
1428  /*
1429  * If the inserting transaction is marked invalid, then it aborted, and
1430  * the tuple is definitely dead. If it's marked neither committed nor
1431  * invalid, then we assume it's still alive (since the presumption is that
1432  * all relevant hint bits were just set moments ago).
1433  */
1434  if (!HeapTupleHeaderXminCommitted(tuple))
1435  return HeapTupleHeaderXminInvalid(tuple) ? true : false;
1436 
1437  /*
1438  * If the inserting transaction committed, but any deleting transaction
1439  * aborted, the tuple is still alive.
1440  */
1441  if (tuple->t_infomask & HEAP_XMAX_INVALID)
1442  return false;
1443 
1444  /*
1445  * If the XMAX is just a lock, the tuple is still alive.
1446  */
1448  return false;
1449 
1450  /*
1451  * If the Xmax is a MultiXact, it might be dead or alive, but we cannot
1452  * know without checking pg_multixact.
1453  */
1454  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1455  return false;
1456 
1457  /* If deleter isn't known to have committed, assume it's still running. */
1458  if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
1459  return false;
1460 
1461  /* Deleter committed, so tuple is dead if the XID is old enough. */
1463 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:82
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:329
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:206
HeapTupleHeader t_data
Definition: htup.h:68
#define true
Definition: c.h:313
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:375
#define HEAP_XMAX_INVALID
Definition: htup_details.h:207
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:324
static TransactionId OldestXmin
Definition: vacuumlazy.c:145
Oid t_tableOid
Definition: htup.h:66
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:230
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:208
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:739

◆ HeapTupleSatisfiesAny()

static bool HeapTupleSatisfiesAny ( HeapTuple  htup,
Snapshot  snapshot,
Buffer  buffer 
)
static

Definition at line 339 of file heapam_visibility.c.

Referenced by HeapTupleSatisfiesVisibility().

340 {
341  return true;
342 }

◆ HeapTupleSatisfiesDirty()

static bool HeapTupleSatisfiesDirty ( HeapTuple  htup,
Snapshot  snapshot,
Buffer  buffer 
)
static

Definition at line 745 of file heapam_visibility.c.

References Assert, HEAP_MOVED_IN, HEAP_MOVED_OFF, HEAP_XMAX_COMMITTED, HEAP_XMAX_INVALID, HEAP_XMAX_IS_LOCKED_ONLY, HEAP_XMAX_IS_MULTI, HEAP_XMIN_COMMITTED, HEAP_XMIN_INVALID, HeapTupleGetUpdateXid(), HeapTupleHeaderGetRawXmax, HeapTupleHeaderGetRawXmin, HeapTupleHeaderGetSpeculativeToken, HeapTupleHeaderGetXvac, HeapTupleHeaderIsSpeculative, HeapTupleHeaderXminCommitted, HeapTupleHeaderXminInvalid, InvalidOid, InvalidTransactionId, ItemPointerIsValid, SetHintBits(), SnapshotData::speculativeToken, HeapTupleData::t_data, HeapTupleHeaderData::t_infomask, HeapTupleData::t_self, HeapTupleData::t_tableOid, TransactionIdDidCommit(), TransactionIdIsCurrentTransactionId(), TransactionIdIsInProgress(), TransactionIdIsValid, SnapshotData::xmax, and SnapshotData::xmin.

Referenced by HeapTupleSatisfiesVisibility().

747 {
748  HeapTupleHeader tuple = htup->t_data;
749 
751  Assert(htup->t_tableOid != InvalidOid);
752 
753  snapshot->xmin = snapshot->xmax = InvalidTransactionId;
754  snapshot->speculativeToken = 0;
755 
756  if (!HeapTupleHeaderXminCommitted(tuple))
757  {
758  if (HeapTupleHeaderXminInvalid(tuple))
759  return false;
760 
761  /* Used by pre-9.0 binary upgrades */
762  if (tuple->t_infomask & HEAP_MOVED_OFF)
763  {
765 
767  return false;
768  if (!TransactionIdIsInProgress(xvac))
769  {
770  if (TransactionIdDidCommit(xvac))
771  {
772  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
774  return false;
775  }
776  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
778  }
779  }
780  /* Used by pre-9.0 binary upgrades */
781  else if (tuple->t_infomask & HEAP_MOVED_IN)
782  {
784 
786  {
787  if (TransactionIdIsInProgress(xvac))
788  return false;
789  if (TransactionIdDidCommit(xvac))
790  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
792  else
793  {
794  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
796  return false;
797  }
798  }
799  }
801  {
802  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
803  return true;
804 
805  if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)) /* not deleter */
806  return true;
807 
808  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
809  {
810  TransactionId xmax;
811 
812  xmax = HeapTupleGetUpdateXid(tuple);
813 
814  /* not LOCKED_ONLY, so it has to have an xmax */
816 
817  /* updating subtransaction must have aborted */
819  return true;
820  else
821  return false;
822  }
823 
825  {
826  /* deleting subtransaction must have aborted */
827  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
829  return true;
830  }
831 
832  return false;
833  }
835  {
836  /*
837  * Return the speculative token to caller. Caller can worry about
838  * xmax, since it requires a conclusively locked row version, and
839  * a concurrent update to this tuple is a conflict of its
840  * purposes.
841  */
842  if (HeapTupleHeaderIsSpeculative(tuple))
843  {
844  snapshot->speculativeToken =
846 
847  Assert(snapshot->speculativeToken != 0);
848  }
849 
850  snapshot->xmin = HeapTupleHeaderGetRawXmin(tuple);
851  /* XXX shouldn't we fall through to look at xmax? */
852  return true; /* in insertion by other */
853  }
855  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
857  else
858  {
859  /* it must have aborted or crashed */
860  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
862  return false;
863  }
864  }
865 
866  /* by here, the inserting transaction has committed */
867 
868  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
869  return true;
870 
871  if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
872  {
874  return true;
875  return false; /* updated by other */
876  }
877 
878  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
879  {
880  TransactionId xmax;
881 
883  return true;
884 
885  xmax = HeapTupleGetUpdateXid(tuple);
886 
887  /* not LOCKED_ONLY, so it has to have an xmax */
889 
891  return false;
892  if (TransactionIdIsInProgress(xmax))
893  {
894  snapshot->xmax = xmax;
895  return true;
896  }
897  if (TransactionIdDidCommit(xmax))
898  return false;
899  /* it must have aborted or crashed */
900  return true;
901  }
902 
904  {
906  return true;
907  return false;
908  }
909 
911  {
913  snapshot->xmax = HeapTupleHeaderGetRawXmax(tuple);
914  return true;
915  }
916 
918  {
919  /* it must have aborted or crashed */
920  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
922  return true;
923  }
924 
925  /* xmax transaction committed */
926 
928  {
929  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
931  return true;
932  }
933 
934  SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
936  return false; /* updated by other */
937 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:82
#define HeapTupleHeaderGetSpeculativeToken(tup)
Definition: htup_details.h:434
uint32 TransactionId
Definition: c.h:514
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:853
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:987
TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple)
Definition: heapam.c:6532
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
#define HeapTupleHeaderIsSpeculative(tup)
Definition: htup_details.h:429
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:329
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:206
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:68
#define HEAP_XMIN_INVALID
Definition: htup_details.h:204
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:375
#define HEAP_XMAX_INVALID
Definition: htup_details.h:207
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:324
#define InvalidTransactionId
Definition: transam.h:31
#define HeapTupleHeaderGetXvac(tup)
Definition: htup_details.h:415
Oid t_tableOid
Definition: htup.h:66
TransactionId xmax
Definition: snapshot.h:158
TransactionId xmin
Definition: snapshot.h:157
#define HEAP_MOVED_IN
Definition: htup_details.h:213
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:230
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:208
#define HEAP_XMIN_COMMITTED
Definition: htup_details.h:203
#define InvalidOid
Definition: postgres_ext.h:36
uint32 speculativeToken
Definition: snapshot.h:193
#define HEAP_MOVED_OFF
Definition: htup_details.h:210
#define Assert(condition)
Definition: c.h:739
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:308
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ HeapTupleSatisfiesHistoricMVCC()

static bool HeapTupleSatisfiesHistoricMVCC ( HeapTuple  htup,
Snapshot  snapshot,
Buffer  buffer 
)
static

Definition at line 1542 of file heapam_visibility.c.

References Assert, SnapshotData::curcid, elog, ERROR, HEAP_XMAX_COMMITTED, HEAP_XMAX_INVALID, HEAP_XMAX_IS_LOCKED_ONLY, HEAP_XMAX_IS_MULTI, HeapTupleGetUpdateXid(), HeapTupleHeaderGetRawCommandId, HeapTupleHeaderGetRawXmax, HeapTupleHeaderGetXmin, HeapTupleHeaderXminCommitted, HeapTupleHeaderXminInvalid, HistoricSnapshotGetTupleCids(), InvalidCommandId, InvalidOid, ItemPointerIsValid, ResolveCminCmaxDuringDecoding(), SnapshotData::subxcnt, SnapshotData::subxip, HeapTupleData::t_data, HeapTupleHeaderData::t_infomask, HeapTupleData::t_self, HeapTupleData::t_tableOid, TransactionIdDidCommit(), TransactionIdFollowsOrEquals(), TransactionIdInArray(), TransactionIdPrecedes(), SnapshotData::xcnt, SnapshotData::xip, SnapshotData::xmax, and SnapshotData::xmin.

Referenced by HeapTupleSatisfiesVisibility().

1544 {
1545  HeapTupleHeader tuple = htup->t_data;
1546  TransactionId xmin = HeapTupleHeaderGetXmin(tuple);
1548 
1549  Assert(ItemPointerIsValid(&htup->t_self));
1550  Assert(htup->t_tableOid != InvalidOid);
1551 
1552  /* inserting transaction aborted */
1553  if (HeapTupleHeaderXminInvalid(tuple))
1554  {
1556  return false;
1557  }
1558  /* check if it's one of our txids, toplevel is also in there */
1559  else if (TransactionIdInArray(xmin, snapshot->subxip, snapshot->subxcnt))
1560  {
1561  bool resolved;
1563  CommandId cmax = InvalidCommandId;
1564 
1565  /*
1566  * another transaction might have (tried to) delete this tuple or
1567  * cmin/cmax was stored in a combocid. So we need to lookup the actual
1568  * values externally.
1569  */
1571  htup, buffer,
1572  &cmin, &cmax);
1573 
1574  if (!resolved)
1575  elog(ERROR, "could not resolve cmin/cmax of catalog tuple");
1576 
1577  Assert(cmin != InvalidCommandId);
1578 
1579  if (cmin >= snapshot->curcid)
1580  return false; /* inserted after scan started */
1581  /* fall through */
1582  }
1583  /* committed before our xmin horizon. Do a normal visibility check. */
1584  else if (TransactionIdPrecedes(xmin, snapshot->xmin))
1585  {
1587  !TransactionIdDidCommit(xmin)));
1588 
1589  /* check for hint bit first, consult clog afterwards */
1590  if (!HeapTupleHeaderXminCommitted(tuple) &&
1591  !TransactionIdDidCommit(xmin))
1592  return false;
1593  /* fall through */
1594  }
1595  /* beyond our xmax horizon, i.e. invisible */
1596  else if (TransactionIdFollowsOrEquals(xmin, snapshot->xmax))
1597  {
1598  return false;
1599  }
1600  /* check if it's a committed transaction in [xmin, xmax) */
1601  else if (TransactionIdInArray(xmin, snapshot->xip, snapshot->xcnt))
1602  {
1603  /* fall through */
1604  }
1605 
1606  /*
1607  * none of the above, i.e. between [xmin, xmax) but hasn't committed. I.e.
1608  * invisible.
1609  */
1610  else
1611  {
1612  return false;
1613  }
1614 
1615  /* at this point we know xmin is visible, go on to check xmax */
1616 
1617  /* xid invalid or aborted */
1618  if (tuple->t_infomask & HEAP_XMAX_INVALID)
1619  return true;
1620  /* locked tuples are always visible */
1621  else if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
1622  return true;
1623 
1624  /*
1625  * We can see multis here if we're looking at user tables or if somebody
1626  * SELECT ... FOR SHARE/UPDATE a system table.
1627  */
1628  else if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1629  {
1630  xmax = HeapTupleGetUpdateXid(tuple);
1631  }
1632 
1633  /* check if it's one of our txids, toplevel is also in there */
1634  if (TransactionIdInArray(xmax, snapshot->subxip, snapshot->subxcnt))
1635  {
1636  bool resolved;
1637  CommandId cmin;
1639 
1640  /* Lookup actual cmin/cmax values */
1642  htup, buffer,
1643  &cmin, &cmax);
1644 
1645  if (!resolved)
1646  elog(ERROR, "could not resolve combocid to cmax");
1647 
1648  Assert(cmax != InvalidCommandId);
1649 
1650  if (cmax >= snapshot->curcid)
1651  return true; /* deleted after scan started */
1652  else
1653  return false; /* deleted before scan started */
1654  }
1655  /* below xmin horizon, normal transaction state is valid */
1656  else if (TransactionIdPrecedes(xmax, snapshot->xmin))
1657  {
1658  Assert(!(tuple->t_infomask & HEAP_XMAX_COMMITTED &&
1659  !TransactionIdDidCommit(xmax)));
1660 
1661  /* check hint bit first */
1662  if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
1663  return false;
1664 
1665  /* check clog */
1666  return !TransactionIdDidCommit(xmax);
1667  }
1668  /* above xmax horizon, we cannot possibly see the deleting transaction */
1669  else if (TransactionIdFollowsOrEquals(xmax, snapshot->xmax))
1670  return true;
1671  /* xmax is between [xmin, xmax), check known committed array */
1672  else if (TransactionIdInArray(xmax, snapshot->xip, snapshot->xcnt))
1673  return false;
1674  /* xmax is between [xmin, xmax), but known not to have committed yet */
1675  else
1676  return true;
1677 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:82
uint32 CommandId
Definition: c.h:528
uint32 TransactionId
Definition: c.h:514
TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple)
Definition: heapam.c:6532
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:349
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:329
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:206
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:68
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:375
#define ERROR
Definition: elog.h:43
#define HEAP_XMAX_INVALID
Definition: htup_details.h:207
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:324
Oid t_tableOid
Definition: htup.h:66
TransactionId xmax
Definition: snapshot.h:158
TransactionId xmin
Definition: snapshot.h:157
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
TransactionId * xip
Definition: snapshot.h:168
#define InvalidCommandId
Definition: c.h:531
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:230
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:208
#define InvalidOid
Definition: postgres_ext.h:36
CommandId curcid
Definition: snapshot.h:187
#define Assert(condition)
Definition: c.h:739
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:313
static bool TransactionIdInArray(TransactionId xid, TransactionId *xip, Size num)
#define HeapTupleHeaderGetRawCommandId(tup)
Definition: htup_details.h:391
HTAB * HistoricSnapshotGetTupleCids(void)
Definition: snapmgr.c:2064
uint32 xcnt
Definition: snapshot.h:169
#define elog(elevel,...)
Definition: elog.h:228
TransactionId * subxip
Definition: snapshot.h:180
int32 subxcnt
Definition: snapshot.h:181
bool ResolveCminCmaxDuringDecoding(HTAB *tuplecid_data, Snapshot snapshot, HeapTuple htup, Buffer buffer, CommandId *cmin, CommandId *cmax)

◆ HeapTupleSatisfiesMVCC()

static bool HeapTupleSatisfiesMVCC ( HeapTuple  htup,
Snapshot  snapshot,
Buffer  buffer 
)
static

Definition at line 962 of file heapam_visibility.c.

References Assert, SnapshotData::curcid, HEAP_MOVED_IN, HEAP_MOVED_OFF, HEAP_XMAX_COMMITTED, HEAP_XMAX_INVALID, HEAP_XMAX_IS_LOCKED_ONLY, HEAP_XMAX_IS_MULTI, HEAP_XMIN_COMMITTED, HEAP_XMIN_INVALID, HeapTupleGetUpdateXid(), HeapTupleHeaderGetCmax(), HeapTupleHeaderGetCmin(), HeapTupleHeaderGetRawXmax, HeapTupleHeaderGetRawXmin, HeapTupleHeaderGetXvac, HeapTupleHeaderXminCommitted, HeapTupleHeaderXminFrozen, HeapTupleHeaderXminInvalid, InvalidOid, InvalidTransactionId, ItemPointerIsValid, SetHintBits(), HeapTupleData::t_data, HeapTupleHeaderData::t_infomask, HeapTupleData::t_self, HeapTupleData::t_tableOid, TransactionIdDidCommit(), TransactionIdIsCurrentTransactionId(), TransactionIdIsValid, and XidInMVCCSnapshot().

Referenced by HeapTupleSatisfiesVisibility().

964 {
965  HeapTupleHeader tuple = htup->t_data;
966 
968  Assert(htup->t_tableOid != InvalidOid);
969 
970  if (!HeapTupleHeaderXminCommitted(tuple))
971  {
972  if (HeapTupleHeaderXminInvalid(tuple))
973  return false;
974 
975  /* Used by pre-9.0 binary upgrades */
976  if (tuple->t_infomask & HEAP_MOVED_OFF)
977  {
979 
981  return false;
982  if (!XidInMVCCSnapshot(xvac, snapshot))
983  {
984  if (TransactionIdDidCommit(xvac))
985  {
986  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
988  return false;
989  }
990  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
992  }
993  }
994  /* Used by pre-9.0 binary upgrades */
995  else if (tuple->t_infomask & HEAP_MOVED_IN)
996  {
998 
1000  {
1001  if (XidInMVCCSnapshot(xvac, snapshot))
1002  return false;
1003  if (TransactionIdDidCommit(xvac))
1004  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
1006  else
1007  {
1008  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
1010  return false;
1011  }
1012  }
1013  }
1015  {
1016  if (HeapTupleHeaderGetCmin(tuple) >= snapshot->curcid)
1017  return false; /* inserted after scan started */
1018 
1019  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
1020  return true;
1021 
1022  if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)) /* not deleter */
1023  return true;
1024 
1025  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1026  {
1027  TransactionId xmax;
1028 
1029  xmax = HeapTupleGetUpdateXid(tuple);
1030 
1031  /* not LOCKED_ONLY, so it has to have an xmax */
1033 
1034  /* updating subtransaction must have aborted */
1036  return true;
1037  else if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
1038  return true; /* updated after scan started */
1039  else
1040  return false; /* updated before scan started */
1041  }
1042 
1044  {
1045  /* deleting subtransaction must have aborted */
1046  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
1048  return true;
1049  }
1050 
1051  if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
1052  return true; /* deleted after scan started */
1053  else
1054  return false; /* deleted before scan started */
1055  }
1056  else if (XidInMVCCSnapshot(HeapTupleHeaderGetRawXmin(tuple), snapshot))
1057  return false;
1059  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
1060  HeapTupleHeaderGetRawXmin(tuple));
1061  else
1062  {
1063  /* it must have aborted or crashed */
1064  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
1066  return false;
1067  }
1068  }
1069  else
1070  {
1071  /* xmin is committed, but maybe not according to our snapshot */
1072  if (!HeapTupleHeaderXminFrozen(tuple) &&
1073  XidInMVCCSnapshot(HeapTupleHeaderGetRawXmin(tuple), snapshot))
1074  return false; /* treat as still in progress */
1075  }
1076 
1077  /* by here, the inserting transaction has committed */
1078 
1079  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
1080  return true;
1081 
1083  return true;
1084 
1085  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1086  {
1087  TransactionId xmax;
1088 
1089  /* already checked above */
1091 
1092  xmax = HeapTupleGetUpdateXid(tuple);
1093 
1094  /* not LOCKED_ONLY, so it has to have an xmax */
1096 
1098  {
1099  if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
1100  return true; /* deleted after scan started */
1101  else
1102  return false; /* deleted before scan started */
1103  }
1104  if (XidInMVCCSnapshot(xmax, snapshot))
1105  return true;
1106  if (TransactionIdDidCommit(xmax))
1107  return false; /* updating transaction committed */
1108  /* it must have aborted or crashed */
1109  return true;
1110  }
1111 
1112  if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
1113  {
1115  {
1116  if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
1117  return true; /* deleted after scan started */
1118  else
1119  return false; /* deleted before scan started */
1120  }
1121 
1122  if (XidInMVCCSnapshot(HeapTupleHeaderGetRawXmax(tuple), snapshot))
1123  return true;
1124 
1126  {
1127  /* it must have aborted or crashed */
1128  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
1130  return true;
1131  }
1132 
1133  /* xmax transaction committed */
1134  SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
1135  HeapTupleHeaderGetRawXmax(tuple));
1136  }
1137  else
1138  {
1139  /* xmax is committed, but maybe not according to our snapshot */
1140  if (XidInMVCCSnapshot(HeapTupleHeaderGetRawXmax(tuple), snapshot))
1141  return true; /* treat as still in progress */
1142  }
1143 
1144  /* xmax transaction committed */
1145 
1146  return false;
1147 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:82
bool XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot)
Definition: snapmgr.c:2241
uint32 TransactionId
Definition: c.h:514
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:853
TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple)
Definition: heapam.c:6532
CommandId HeapTupleHeaderGetCmin(HeapTupleHeader tup)
Definition: combocid.c:104
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:329
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:206
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:68
#define HEAP_XMIN_INVALID
Definition: htup_details.h:204
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:375
#define HEAP_XMAX_INVALID
Definition: htup_details.h:207
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:324
#define InvalidTransactionId
Definition: transam.h:31
#define HeapTupleHeaderGetXvac(tup)
Definition: htup_details.h:415
Oid t_tableOid
Definition: htup.h:66
#define HEAP_MOVED_IN
Definition: htup_details.h:213
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:230
#define HeapTupleHeaderXminFrozen(tup)
Definition: htup_details.h:335
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:208
#define HEAP_XMIN_COMMITTED
Definition: htup_details.h:203
#define InvalidOid
Definition: postgres_ext.h:36
CommandId curcid
Definition: snapshot.h:187
#define HEAP_MOVED_OFF
Definition: htup_details.h:210
#define Assert(condition)
Definition: c.h:739
CommandId HeapTupleHeaderGetCmax(HeapTupleHeader tup)
Definition: combocid.c:118
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:308
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ HeapTupleSatisfiesNonVacuumable()

static bool HeapTupleSatisfiesNonVacuumable ( HeapTuple  htup,
Snapshot  snapshot,
Buffer  buffer 
)
static

Definition at line 1399 of file heapam_visibility.c.

References HEAPTUPLE_DEAD, HeapTupleSatisfiesVacuum(), and SnapshotData::xmin.

Referenced by HeapTupleSatisfiesVisibility().

1401 {
1402  return HeapTupleSatisfiesVacuum(htup, snapshot->xmin, buffer)
1403  != HEAPTUPLE_DEAD;
1404 }
TransactionId xmin
Definition: snapshot.h:157
HTSV_Result HeapTupleSatisfiesVacuum(HeapTuple htup, TransactionId OldestXmin, Buffer buffer)

◆ HeapTupleSatisfiesSelf()

static bool HeapTupleSatisfiesSelf ( HeapTuple  htup,
Snapshot  snapshot,
Buffer  buffer 
)
static

Definition at line 169 of file heapam_visibility.c.

References Assert, HEAP_MOVED_IN, HEAP_MOVED_OFF, HEAP_XMAX_COMMITTED, HEAP_XMAX_INVALID, HEAP_XMAX_IS_LOCKED_ONLY, HEAP_XMAX_IS_MULTI, HEAP_XMIN_COMMITTED, HEAP_XMIN_INVALID, HeapTupleGetUpdateXid(), HeapTupleHeaderGetRawXmax, HeapTupleHeaderGetRawXmin, HeapTupleHeaderGetXvac, HeapTupleHeaderXminCommitted, HeapTupleHeaderXminInvalid, InvalidOid, InvalidTransactionId, ItemPointerIsValid, SetHintBits(), HeapTupleData::t_data, HeapTupleHeaderData::t_infomask, HeapTupleData::t_self, HeapTupleData::t_tableOid, TransactionIdDidCommit(), TransactionIdIsCurrentTransactionId(), TransactionIdIsInProgress(), and TransactionIdIsValid.

Referenced by HeapTupleSatisfiesVisibility().

170 {
171  HeapTupleHeader tuple = htup->t_data;
172 
174  Assert(htup->t_tableOid != InvalidOid);
175 
176  if (!HeapTupleHeaderXminCommitted(tuple))
177  {
178  if (HeapTupleHeaderXminInvalid(tuple))
179  return false;
180 
181  /* Used by pre-9.0 binary upgrades */
182  if (tuple->t_infomask & HEAP_MOVED_OFF)
183  {
185 
187  return false;
188  if (!TransactionIdIsInProgress(xvac))
189  {
190  if (TransactionIdDidCommit(xvac))
191  {
192  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
194  return false;
195  }
196  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
198  }
199  }
200  /* Used by pre-9.0 binary upgrades */
201  else if (tuple->t_infomask & HEAP_MOVED_IN)
202  {
204 
206  {
207  if (TransactionIdIsInProgress(xvac))
208  return false;
209  if (TransactionIdDidCommit(xvac))
210  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
212  else
213  {
214  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
216  return false;
217  }
218  }
219  }
221  {
222  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
223  return true;
224 
225  if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)) /* not deleter */
226  return true;
227 
228  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
229  {
230  TransactionId xmax;
231 
232  xmax = HeapTupleGetUpdateXid(tuple);
233 
234  /* not LOCKED_ONLY, so it has to have an xmax */
236 
237  /* updating subtransaction must have aborted */
239  return true;
240  else
241  return false;
242  }
243 
245  {
246  /* deleting subtransaction must have aborted */
247  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
249  return true;
250  }
251 
252  return false;
253  }
255  return false;
257  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
259  else
260  {
261  /* it must have aborted or crashed */
262  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
264  return false;
265  }
266  }
267 
268  /* by here, the inserting transaction has committed */
269 
270  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
271  return true;
272 
273  if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
274  {
276  return true;
277  return false; /* updated by other */
278  }
279 
280  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
281  {
282  TransactionId xmax;
283 
285  return true;
286 
287  xmax = HeapTupleGetUpdateXid(tuple);
288 
289  /* not LOCKED_ONLY, so it has to have an xmax */
291 
293  return false;
294  if (TransactionIdIsInProgress(xmax))
295  return true;
296  if (TransactionIdDidCommit(xmax))
297  return false;
298  /* it must have aborted or crashed */
299  return true;
300  }
301 
303  {
305  return true;
306  return false;
307  }
308 
310  return true;
311 
313  {
314  /* it must have aborted or crashed */
315  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
317  return true;
318  }
319 
320  /* xmax transaction committed */
321 
323  {
324  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
326  return true;
327  }
328 
329  SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
331  return false;
332 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:82
uint32 TransactionId
Definition: c.h:514
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:853
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:987
TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple)
Definition: heapam.c:6532
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:329
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:206
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:68
#define HEAP_XMIN_INVALID
Definition: htup_details.h:204
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:375
#define HEAP_XMAX_INVALID
Definition: htup_details.h:207
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:324
#define InvalidTransactionId
Definition: transam.h:31
#define HeapTupleHeaderGetXvac(tup)
Definition: htup_details.h:415
Oid t_tableOid
Definition: htup.h:66
#define HEAP_MOVED_IN
Definition: htup_details.h:213
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:230
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:208
#define HEAP_XMIN_COMMITTED
Definition: htup_details.h:203
#define InvalidOid
Definition: postgres_ext.h:36
#define HEAP_MOVED_OFF
Definition: htup_details.h:210
#define Assert(condition)
Definition: c.h:739
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:308
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ HeapTupleSatisfiesToast()

static bool HeapTupleSatisfiesToast ( HeapTuple  htup,
Snapshot  snapshot,
Buffer  buffer 
)
static

Definition at line 361 of file heapam_visibility.c.

References Assert, HEAP_MOVED_IN, HEAP_MOVED_OFF, HEAP_XMIN_COMMITTED, HEAP_XMIN_INVALID, HeapTupleHeaderGetXmin, HeapTupleHeaderGetXvac, HeapTupleHeaderXminCommitted, HeapTupleHeaderXminInvalid, InvalidOid, InvalidTransactionId, ItemPointerIsValid, SetHintBits(), HeapTupleData::t_data, HeapTupleHeaderData::t_infomask, HeapTupleData::t_self, HeapTupleData::t_tableOid, TransactionIdDidCommit(), TransactionIdIsCurrentTransactionId(), TransactionIdIsInProgress(), and TransactionIdIsValid.

Referenced by HeapTupleSatisfiesVisibility().

363 {
364  HeapTupleHeader tuple = htup->t_data;
365 
367  Assert(htup->t_tableOid != InvalidOid);
368 
369  if (!HeapTupleHeaderXminCommitted(tuple))
370  {
371  if (HeapTupleHeaderXminInvalid(tuple))
372  return false;
373 
374  /* Used by pre-9.0 binary upgrades */
375  if (tuple->t_infomask & HEAP_MOVED_OFF)
376  {
378 
380  return false;
381  if (!TransactionIdIsInProgress(xvac))
382  {
383  if (TransactionIdDidCommit(xvac))
384  {
385  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
387  return false;
388  }
389  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
391  }
392  }
393  /* Used by pre-9.0 binary upgrades */
394  else if (tuple->t_infomask & HEAP_MOVED_IN)
395  {
397 
399  {
400  if (TransactionIdIsInProgress(xvac))
401  return false;
402  if (TransactionIdDidCommit(xvac))
403  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
405  else
406  {
407  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
409  return false;
410  }
411  }
412  }
413 
414  /*
415  * An invalid Xmin can be left behind by a speculative insertion that
416  * is canceled by super-deleting the tuple. This also applies to
417  * TOAST tuples created during speculative insertion.
418  */
420  return false;
421  }
422 
423  /* otherwise assume the tuple is valid for TOAST. */
424  return true;
425 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:82
uint32 TransactionId
Definition: c.h:514
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:853
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:987
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:329
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:68
#define HEAP_XMIN_INVALID
Definition: htup_details.h:204
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:324
#define InvalidTransactionId
Definition: transam.h:31
#define HeapTupleHeaderGetXvac(tup)
Definition: htup_details.h:415
Oid t_tableOid
Definition: htup.h:66
#define HEAP_MOVED_IN
Definition: htup_details.h:213
#define HEAP_XMIN_COMMITTED
Definition: htup_details.h:203
#define InvalidOid
Definition: postgres_ext.h:36
#define HEAP_MOVED_OFF
Definition: htup_details.h:210
#define Assert(condition)
Definition: c.h:739
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:313
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ HeapTupleSatisfiesUpdate()

TM_Result HeapTupleSatisfiesUpdate ( HeapTuple  htup,
CommandId  curcid,
Buffer  buffer 
)

Definition at line 457 of file heapam_visibility.c.

References Assert, HEAP_LOCKED_UPGRADED, HEAP_MOVED_IN, HEAP_MOVED_OFF, HEAP_XMAX_COMMITTED, HEAP_XMAX_INVALID, HEAP_XMAX_IS_LOCKED_ONLY, HEAP_XMAX_IS_MULTI, HEAP_XMIN_COMMITTED, HEAP_XMIN_INVALID, HeapTupleGetUpdateXid(), HeapTupleHeaderGetCmax(), HeapTupleHeaderGetCmin(), HeapTupleHeaderGetRawXmax, HeapTupleHeaderGetRawXmin, HeapTupleHeaderGetXvac, HeapTupleHeaderIndicatesMovedPartitions, HeapTupleHeaderXminCommitted, HeapTupleHeaderXminInvalid, InvalidOid, InvalidTransactionId, ItemPointerEquals(), ItemPointerIsValid, MultiXactIdIsRunning(), SetHintBits(), HeapTupleHeaderData::t_ctid, HeapTupleData::t_data, HeapTupleHeaderData::t_infomask, HeapTupleData::t_self, HeapTupleData::t_tableOid, TM_BeingModified, TM_Deleted, TM_Invisible, TM_Ok, TM_SelfModified, TM_Updated, TransactionIdDidCommit(), TransactionIdIsCurrentTransactionId(), TransactionIdIsInProgress(), and TransactionIdIsValid.

Referenced by heap_delete(), heap_lock_tuple(), heap_update(), and pgrowlocks().

459 {
460  HeapTupleHeader tuple = htup->t_data;
461 
463  Assert(htup->t_tableOid != InvalidOid);
464 
465  if (!HeapTupleHeaderXminCommitted(tuple))
466  {
467  if (HeapTupleHeaderXminInvalid(tuple))
468  return TM_Invisible;
469 
470  /* Used by pre-9.0 binary upgrades */
471  if (tuple->t_infomask & HEAP_MOVED_OFF)
472  {
474 
476  return TM_Invisible;
477  if (!TransactionIdIsInProgress(xvac))
478  {
479  if (TransactionIdDidCommit(xvac))
480  {
481  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
483  return TM_Invisible;
484  }
485  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
487  }
488  }
489  /* Used by pre-9.0 binary upgrades */
490  else if (tuple->t_infomask & HEAP_MOVED_IN)
491  {
493 
495  {
496  if (TransactionIdIsInProgress(xvac))
497  return TM_Invisible;
498  if (TransactionIdDidCommit(xvac))
499  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
501  else
502  {
503  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
505  return TM_Invisible;
506  }
507  }
508  }
510  {
511  if (HeapTupleHeaderGetCmin(tuple) >= curcid)
512  return TM_Invisible; /* inserted after scan started */
513 
514  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
515  return TM_Ok;
516 
518  {
519  TransactionId xmax;
520 
521  xmax = HeapTupleHeaderGetRawXmax(tuple);
522 
523  /*
524  * Careful here: even though this tuple was created by our own
525  * transaction, it might be locked by other transactions, if
526  * the original version was key-share locked when we updated
527  * it.
528  */
529 
530  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
531  {
532  if (MultiXactIdIsRunning(xmax, true))
533  return TM_BeingModified;
534  else
535  return TM_Ok;
536  }
537 
538  /*
539  * If the locker is gone, then there is nothing of interest
540  * left in this Xmax; otherwise, report the tuple as
541  * locked/updated.
542  */
543  if (!TransactionIdIsInProgress(xmax))
544  return TM_Ok;
545  return TM_BeingModified;
546  }
547 
548  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
549  {
550  TransactionId xmax;
551 
552  xmax = HeapTupleGetUpdateXid(tuple);
553 
554  /* not LOCKED_ONLY, so it has to have an xmax */
556 
557  /* deleting subtransaction must have aborted */
559  {
561  false))
562  return TM_BeingModified;
563  return TM_Ok;
564  }
565  else
566  {
567  if (HeapTupleHeaderGetCmax(tuple) >= curcid)
568  return TM_SelfModified; /* updated after scan started */
569  else
570  return TM_Invisible; /* updated before scan started */
571  }
572  }
573 
575  {
576  /* deleting subtransaction must have aborted */
577  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
579  return TM_Ok;
580  }
581 
582  if (HeapTupleHeaderGetCmax(tuple) >= curcid)
583  return TM_SelfModified; /* updated after scan started */
584  else
585  return TM_Invisible; /* updated before scan started */
586  }
588  return TM_Invisible;
590  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
592  else
593  {
594  /* it must have aborted or crashed */
595  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
597  return TM_Invisible;
598  }
599  }
600 
601  /* by here, the inserting transaction has committed */
602 
603  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
604  return TM_Ok;
605 
606  if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
607  {
609  return TM_Ok;
610  if (!ItemPointerEquals(&htup->t_self, &tuple->t_ctid) ||
612  return TM_Updated; /* updated by other */
613  else
614  return TM_Deleted; /* deleted by other */
615  }
616 
617  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
618  {
619  TransactionId xmax;
620 
621  if (HEAP_LOCKED_UPGRADED(tuple->t_infomask))
622  return TM_Ok;
623 
625  {
627  return TM_BeingModified;
628 
630  return TM_Ok;
631  }
632 
633  xmax = HeapTupleGetUpdateXid(tuple);
634  if (!TransactionIdIsValid(xmax))
635  {
637  return TM_BeingModified;
638  }
639 
640  /* not LOCKED_ONLY, so it has to have an xmax */
642 
644  {
645  if (HeapTupleHeaderGetCmax(tuple) >= curcid)
646  return TM_SelfModified; /* updated after scan started */
647  else
648  return TM_Invisible; /* updated before scan started */
649  }
650 
652  return TM_BeingModified;
653 
654  if (TransactionIdDidCommit(xmax))
655  {
656  if (!ItemPointerEquals(&htup->t_self, &tuple->t_ctid) ||
658  return TM_Updated;
659  else
660  return TM_Deleted;
661  }
662 
663  /*
664  * By here, the update in the Xmax is either aborted or crashed, but
665  * what about the other members?
666  */
667 
669  {
670  /*
671  * There's no member, even just a locker, alive anymore, so we can
672  * mark the Xmax as invalid.
673  */
674  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
676  return TM_Ok;
677  }
678  else
679  {
680  /* There are lockers running */
681  return TM_BeingModified;
682  }
683  }
684 
686  {
688  return TM_BeingModified;
689  if (HeapTupleHeaderGetCmax(tuple) >= curcid)
690  return TM_SelfModified; /* updated after scan started */
691  else
692  return TM_Invisible; /* updated before scan started */
693  }
694 
696  return TM_BeingModified;
697 
699  {
700  /* it must have aborted or crashed */
701  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
703  return TM_Ok;
704  }
705 
706  /* xmax transaction committed */
707 
709  {
710  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
712  return TM_Ok;
713  }
714 
715  SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
717  if (!ItemPointerEquals(&htup->t_self, &tuple->t_ctid) ||
719  return TM_Updated; /* updated by other */
720  else
721  return TM_Deleted; /* deleted by other */
722 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:82
uint32 TransactionId
Definition: c.h:514
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:853
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:987
TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple)
Definition: heapam.c:6532
CommandId HeapTupleHeaderGetCmin(HeapTupleHeader tup)
Definition: combocid.c:104
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
#define HEAP_LOCKED_UPGRADED(infomask)
Definition: htup_details.h:252
#define HeapTupleHeaderIndicatesMovedPartitions(tup)
Definition: htup_details.h:445
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:329
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:206
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:68
#define HEAP_XMIN_INVALID
Definition: htup_details.h:204
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:375
#define HEAP_XMAX_INVALID
Definition: htup_details.h:207
ItemPointerData t_ctid
Definition: htup_details.h:160
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:324
#define InvalidTransactionId
Definition: transam.h:31
#define HeapTupleHeaderGetXvac(tup)
Definition: htup_details.h:415
Oid t_tableOid
Definition: htup.h:66
#define HEAP_MOVED_IN
Definition: htup_details.h:213
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:230
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:208
#define HEAP_XMIN_COMMITTED
Definition: htup_details.h:203
#define InvalidOid
Definition: postgres_ext.h:36
#define HEAP_MOVED_OFF
Definition: htup_details.h:210
#define Assert(condition)
Definition: c.h:739
CommandId HeapTupleHeaderGetCmax(HeapTupleHeader tup)
Definition: combocid.c:118
Definition: tableam.h:74
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:308
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
Definition: itemptr.c:29
#define TransactionIdIsValid(xid)
Definition: transam.h:41
bool MultiXactIdIsRunning(MultiXactId multi, bool isLockOnly)
Definition: multixact.c:551

◆ HeapTupleSatisfiesVacuum()

HTSV_Result HeapTupleSatisfiesVacuum ( HeapTuple  htup,
TransactionId  OldestXmin,
Buffer  buffer 
)

Definition at line 1163 of file heapam_visibility.c.

References Assert, HEAP_LOCKED_UPGRADED, HEAP_MOVED_IN, HEAP_MOVED_OFF, HEAP_XMAX_COMMITTED, HEAP_XMAX_INVALID, HEAP_XMAX_IS_LOCKED_ONLY, HEAP_XMAX_IS_MULTI, HEAP_XMIN_COMMITTED, HEAP_XMIN_INVALID, HEAPTUPLE_DEAD, HEAPTUPLE_DELETE_IN_PROGRESS, HEAPTUPLE_INSERT_IN_PROGRESS, HEAPTUPLE_LIVE, HEAPTUPLE_RECENTLY_DEAD, HeapTupleGetUpdateXid(), HeapTupleHeaderGetRawXmax, HeapTupleHeaderGetRawXmin, HeapTupleHeaderGetUpdateXid, HeapTupleHeaderGetXvac, HeapTupleHeaderIsOnlyLocked(), HeapTupleHeaderXminCommitted, HeapTupleHeaderXminInvalid, InvalidOid, InvalidTransactionId, ItemPointerIsValid, MultiXactIdIsRunning(), SetHintBits(), HeapTupleData::t_data, HeapTupleHeaderData::t_infomask, HeapTupleData::t_self, HeapTupleData::t_tableOid, TransactionIdDidCommit(), TransactionIdIsCurrentTransactionId(), TransactionIdIsInProgress(), TransactionIdIsValid, and TransactionIdPrecedes().

Referenced by CheckForSerializableConflictOut(), heap_page_is_all_visible(), heap_prune_chain(), heapam_index_build_range_scan(), heapam_relation_copy_for_cluster(), heapam_scan_analyze_next_tuple(), HeapTupleSatisfiesNonVacuumable(), lazy_scan_heap(), statapprox_heap(), and tuple_all_visible().

1165 {
1166  HeapTupleHeader tuple = htup->t_data;
1167 
1168  Assert(ItemPointerIsValid(&htup->t_self));
1169  Assert(htup->t_tableOid != InvalidOid);
1170 
1171  /*
1172  * Has inserting transaction committed?
1173  *
1174  * If the inserting transaction aborted, then the tuple was never visible
1175  * to any other transaction, so we can delete it immediately.
1176  */
1177  if (!HeapTupleHeaderXminCommitted(tuple))
1178  {
1179  if (HeapTupleHeaderXminInvalid(tuple))
1180  return HEAPTUPLE_DEAD;
1181  /* Used by pre-9.0 binary upgrades */
1182  else if (tuple->t_infomask & HEAP_MOVED_OFF)
1183  {
1184  TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
1185 
1188  if (TransactionIdIsInProgress(xvac))
1190  if (TransactionIdDidCommit(xvac))
1191  {
1192  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
1194  return HEAPTUPLE_DEAD;
1195  }
1196  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
1198  }
1199  /* Used by pre-9.0 binary upgrades */
1200  else if (tuple->t_infomask & HEAP_MOVED_IN)
1201  {
1202  TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
1203 
1206  if (TransactionIdIsInProgress(xvac))
1208  if (TransactionIdDidCommit(xvac))
1209  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
1211  else
1212  {
1213  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
1215  return HEAPTUPLE_DEAD;
1216  }
1217  }
1219  {
1220  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
1222  /* only locked? run infomask-only check first, for performance */
1223  if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask) ||
1226  /* inserted and then deleted by same xact */
1229  /* deleting subtransaction must have aborted */
1231  }
1233  {
1234  /*
1235  * It'd be possible to discern between INSERT/DELETE in progress
1236  * here by looking at xmax - but that doesn't seem beneficial for
1237  * the majority of callers and even detrimental for some. We'd
1238  * rather have callers look at/wait for xmin than xmax. It's
1239  * always correct to return INSERT_IN_PROGRESS because that's
1240  * what's happening from the view of other backends.
1241  */
1243  }
1245  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
1246  HeapTupleHeaderGetRawXmin(tuple));
1247  else
1248  {
1249  /*
1250  * Not in Progress, Not Committed, so either Aborted or crashed
1251  */
1252  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
1254  return HEAPTUPLE_DEAD;
1255  }
1256 
1257  /*
1258  * At this point the xmin is known committed, but we might not have
1259  * been able to set the hint bit yet; so we can no longer Assert that
1260  * it's set.
1261  */
1262  }
1263 
1264  /*
1265  * Okay, the inserter committed, so it was good at some point. Now what
1266  * about the deleting transaction?
1267  */
1268  if (tuple->t_infomask & HEAP_XMAX_INVALID)
1269  return HEAPTUPLE_LIVE;
1270 
1272  {
1273  /*
1274  * "Deleting" xact really only locked it, so the tuple is live in any
1275  * case. However, we should make sure that either XMAX_COMMITTED or
1276  * XMAX_INVALID gets set once the xact is gone, to reduce the costs of
1277  * examining the tuple for future xacts.
1278  */
1279  if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
1280  {
1281  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1282  {
1283  /*
1284  * If it's a pre-pg_upgrade tuple, the multixact cannot
1285  * possibly be running; otherwise have to check.
1286  */
1287  if (!HEAP_LOCKED_UPGRADED(tuple->t_infomask) &&
1289  true))
1290  return HEAPTUPLE_LIVE;
1292  }
1293  else
1294  {
1296  return HEAPTUPLE_LIVE;
1297  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
1299  }
1300  }
1301 
1302  /*
1303  * We don't really care whether xmax did commit, abort or crash. We
1304  * know that xmax did lock the tuple, but it did not and will never
1305  * actually update it.
1306  */
1307 
1308  return HEAPTUPLE_LIVE;
1309  }
1310 
1311  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1312  {
1313  TransactionId xmax = HeapTupleGetUpdateXid(tuple);
1314 
1315  /* already checked above */
1317 
1318  /* not LOCKED_ONLY, so it has to have an xmax */
1320 
1321  if (TransactionIdIsInProgress(xmax))
1323  else if (TransactionIdDidCommit(xmax))
1324  {
1325  /*
1326  * The multixact might still be running due to lockers. If the
1327  * updater is below the xid horizon, we have to return DEAD
1328  * regardless -- otherwise we could end up with a tuple where the
1329  * updater has to be removed due to the horizon, but is not pruned
1330  * away. It's not a problem to prune that tuple, because any
1331  * remaining lockers will also be present in newer tuple versions.
1332  */
1333  if (!TransactionIdPrecedes(xmax, OldestXmin))
1334  return HEAPTUPLE_RECENTLY_DEAD;
1335 
1336  return HEAPTUPLE_DEAD;
1337  }
1338  else if (!MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple), false))
1339  {
1340  /*
1341  * Not in Progress, Not Committed, so either Aborted or crashed.
1342  * Mark the Xmax as invalid.
1343  */
1345  }
1346 
1347  return HEAPTUPLE_LIVE;
1348  }
1349 
1350  if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
1351  {
1355  SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
1356  HeapTupleHeaderGetRawXmax(tuple));
1357  else
1358  {
1359  /*
1360  * Not in Progress, Not Committed, so either Aborted or crashed
1361  */
1362  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
1364  return HEAPTUPLE_LIVE;
1365  }
1366 
1367  /*
1368  * At this point the xmax is known committed, but we might not have
1369  * been able to set the hint bit yet; so we can no longer Assert that
1370  * it's set.
1371  */
1372  }
1373 
1374  /*
1375  * Deleter committed, but perhaps it was recent enough that some open
1376  * transactions could still see the tuple.
1377  */
1379  return HEAPTUPLE_RECENTLY_DEAD;
1380 
1381  /* Otherwise, it's dead and removable */
1382  return HEAPTUPLE_DEAD;
1383 }
#define HeapTupleHeaderGetUpdateXid(tup)
Definition: htup_details.h:365
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:82
uint32 TransactionId
Definition: c.h:514
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:853
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:987
TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple)
Definition: heapam.c:6532
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
bool HeapTupleHeaderIsOnlyLocked(HeapTupleHeader tuple)
#define HEAP_LOCKED_UPGRADED(infomask)
Definition: htup_details.h:252
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:329
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:206
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:68
#define HEAP_XMIN_INVALID
Definition: htup_details.h:204
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:375
#define HEAP_XMAX_INVALID
Definition: htup_details.h:207
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:324
#define InvalidTransactionId
Definition: transam.h:31
#define HeapTupleHeaderGetXvac(tup)
Definition: htup_details.h:415
static TransactionId OldestXmin
Definition: vacuumlazy.c:145
Oid t_tableOid
Definition: htup.h:66
#define HEAP_MOVED_IN
Definition: htup_details.h:213
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:230
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:208
#define HEAP_XMIN_COMMITTED
Definition: htup_details.h:203
#define InvalidOid
Definition: postgres_ext.h:36
#define HEAP_MOVED_OFF
Definition: htup_details.h:210
#define Assert(condition)
Definition: c.h:739
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:308
#define TransactionIdIsValid(xid)
Definition: transam.h:41
bool MultiXactIdIsRunning(MultiXactId multi, bool isLockOnly)
Definition: multixact.c:551

◆ HeapTupleSatisfiesVisibility()

bool HeapTupleSatisfiesVisibility ( HeapTuple  tup,
Snapshot  snapshot,
Buffer  buffer 
)

Definition at line 1690 of file heapam_visibility.c.

References HeapTupleSatisfiesAny(), HeapTupleSatisfiesDirty(), HeapTupleSatisfiesHistoricMVCC(), HeapTupleSatisfiesMVCC(), HeapTupleSatisfiesNonVacuumable(), HeapTupleSatisfiesSelf(), HeapTupleSatisfiesToast(), SNAPSHOT_ANY, SNAPSHOT_DIRTY, SNAPSHOT_HISTORIC_MVCC, SNAPSHOT_MVCC, SNAPSHOT_NON_VACUUMABLE, SNAPSHOT_SELF, SNAPSHOT_TOAST, and SnapshotData::snapshot_type.

Referenced by heap_delete(), heap_fetch(), heap_get_latest_tid(), heap_hot_search_buffer(), heap_update(), heapam_scan_bitmap_next_block(), heapam_tuple_satisfies_snapshot(), heapgetpage(), heapgettup(), pgstat_heap(), and SampleHeapTupleVisible().

1691 {
1692  switch (snapshot->snapshot_type)
1693  {
1694  case SNAPSHOT_MVCC:
1695  return HeapTupleSatisfiesMVCC(tup, snapshot, buffer);
1696  break;
1697  case SNAPSHOT_SELF:
1698  return HeapTupleSatisfiesSelf(tup, snapshot, buffer);
1699  break;
1700  case SNAPSHOT_ANY:
1701  return HeapTupleSatisfiesAny(tup, snapshot, buffer);
1702  break;
1703  case SNAPSHOT_TOAST:
1704  return HeapTupleSatisfiesToast(tup, snapshot, buffer);
1705  break;
1706  case SNAPSHOT_DIRTY:
1707  return HeapTupleSatisfiesDirty(tup, snapshot, buffer);
1708  break;
1710  return HeapTupleSatisfiesHistoricMVCC(tup, snapshot, buffer);
1711  break;
1713  return HeapTupleSatisfiesNonVacuumable(tup, snapshot, buffer);
1714  break;
1715  }
1716 
1717  return false; /* keep compiler quiet */
1718 }
static bool HeapTupleSatisfiesHistoricMVCC(HeapTuple htup, Snapshot snapshot, Buffer buffer)
static bool HeapTupleSatisfiesDirty(HeapTuple htup, Snapshot snapshot, Buffer buffer)
static bool HeapTupleSatisfiesSelf(HeapTuple htup, Snapshot snapshot, Buffer buffer)
SnapshotType snapshot_type
Definition: snapshot.h:144
static bool HeapTupleSatisfiesToast(HeapTuple htup, Snapshot snapshot, Buffer buffer)
static bool HeapTupleSatisfiesAny(HeapTuple htup, Snapshot snapshot, Buffer buffer)
static bool HeapTupleSatisfiesMVCC(HeapTuple htup, Snapshot snapshot, Buffer buffer)
static bool HeapTupleSatisfiesNonVacuumable(HeapTuple htup, Snapshot snapshot, Buffer buffer)

◆ HeapTupleSetHintBits()

void HeapTupleSetHintBits ( HeapTupleHeader  tuple,
Buffer  buffer,
uint16  infomask,
TransactionId  xid 
)

Definition at line 140 of file heapam_visibility.c.

References SetHintBits().

Referenced by UpdateXmaxHintBits().

142 {
143  SetHintBits(tuple, buffer, infomask, xid);
144 }
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)

◆ SetHintBits()

static void SetHintBits ( HeapTupleHeader  tuple,
Buffer  buffer,
uint16  infomask,
TransactionId  xid 
)
inlinestatic

Definition at line 113 of file heapam_visibility.c.

References BufferGetLSNAtomic(), BufferIsPermanent(), MarkBufferDirtyHint(), HeapTupleHeaderData::t_infomask, TransactionIdGetCommitLSN(), TransactionIdIsValid, and XLogNeedsFlush().

Referenced by HeapTupleSatisfiesDirty(), HeapTupleSatisfiesMVCC(), HeapTupleSatisfiesSelf(), HeapTupleSatisfiesToast(), HeapTupleSatisfiesUpdate(), HeapTupleSatisfiesVacuum(), and HeapTupleSetHintBits().

115 {
116  if (TransactionIdIsValid(xid))
117  {
118  /* NB: xid must be known committed here! */
119  XLogRecPtr commitLSN = TransactionIdGetCommitLSN(xid);
120 
121  if (BufferIsPermanent(buffer) && XLogNeedsFlush(commitLSN) &&
122  BufferGetLSNAtomic(buffer) < commitLSN)
123  {
124  /* not flushed and no LSN interlock, so don't set hint */
125  return;
126  }
127  }
128 
129  tuple->t_infomask |= infomask;
130  MarkBufferDirtyHint(buffer, true);
131 }
void MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
Definition: bufmgr.c:3435
bool XLogNeedsFlush(XLogRecPtr record)
Definition: xlog.c:3126
XLogRecPtr BufferGetLSNAtomic(Buffer buffer)
Definition: bufmgr.c:2876
bool BufferIsPermanent(Buffer buffer)
Definition: bufmgr.c:2846
XLogRecPtr TransactionIdGetCommitLSN(TransactionId xid)
Definition: transam.c:402
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ TransactionIdInArray()

static bool TransactionIdInArray ( TransactionId  xid,
TransactionId xip,
Size  num 
)
static

Definition at line 1521 of file heapam_visibility.c.

References xidComparator().

Referenced by HeapTupleSatisfiesHistoricMVCC().

1522 {
1523  return bsearch(&xid, xip, num,
1524  sizeof(TransactionId), xidComparator) != NULL;
1525 }
uint32 TransactionId
Definition: c.h:514
int xidComparator(const void *arg1, const void *arg2)
Definition: xid.c:138