ssi-predlock-snapshot-2.patch
application/octet-stream
Filename: ssi-predlock-snapshot-2.patch
Type: application/octet-stream
Part: 0
Message:
Re: SSI work for 9.1
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: context
| File | + | − |
|---|---|---|
| src/backend/access/heap/heapam.c | 10 | 0 |
| src/backend/access/index/indexam.c | 8 | 0 |
| src/backend/access/nbtree/nbtsearch.c | 7 | 0 |
| src/backend/executor/nodeSeqscan.c | 2 | 0 |
| src/backend/storage/lmgr/predicate.c | 22 | 5 |
| src/include/storage/predicate.h | 5 | 0 |
*** a/src/backend/access/heap/heapam.c
--- b/src/backend/access/heap/heapam.c
***************
*** 274,280 **** heapgetpage(HeapScanDesc scan, BlockNumber page)
else
valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
! CheckForSerializableConflictOut(valid, scan->rs_rd, &loctup, buffer);
if (valid)
scan->rs_vistuples[ntup++] = lineoff;
--- 274,280 ----
else
valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
! CheckForSerializableConflictOut(valid, scan->rs_rd, &loctup, buffer, snapshot);
if (valid)
scan->rs_vistuples[ntup++] = lineoff;
***************
*** 469,475 **** heapgettup(HeapScanDesc scan,
snapshot,
scan->rs_cbuf);
! CheckForSerializableConflictOut(valid, scan->rs_rd, tuple, scan->rs_cbuf);
if (valid && key != NULL)
HeapKeyTest(tuple, RelationGetDescr(scan->rs_rd),
--- 469,475 ----
snapshot,
scan->rs_cbuf);
! CheckForSerializableConflictOut(valid, scan->rs_rd, tuple, scan->rs_cbuf, snapshot);
if (valid && key != NULL)
HeapKeyTest(tuple, RelationGetDescr(scan->rs_rd),
***************
*** 478,484 **** heapgettup(HeapScanDesc scan,
if (valid)
{
if (!scan->rs_relpredicatelocked)
! PredicateLockTuple(scan->rs_rd, tuple);
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
return;
}
--- 478,484 ----
if (valid)
{
if (!scan->rs_relpredicatelocked)
! PredicateLockTuple(scan->rs_rd, tuple, snapshot);
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
return;
}
***************
*** 747,753 **** heapgettup_pagemode(HeapScanDesc scan,
if (valid)
{
if (!scan->rs_relpredicatelocked)
! PredicateLockTuple(scan->rs_rd, tuple);
scan->rs_cindex = lineindex;
return;
}
--- 747,753 ----
if (valid)
{
if (!scan->rs_relpredicatelocked)
! PredicateLockTuple(scan->rs_rd, tuple, scan->rs_snapshot);
scan->rs_cindex = lineindex;
return;
}
***************
*** 755,761 **** heapgettup_pagemode(HeapScanDesc scan,
else
{
if (!scan->rs_relpredicatelocked)
! PredicateLockTuple(scan->rs_rd, tuple);
scan->rs_cindex = lineindex;
return;
}
--- 755,761 ----
else
{
if (!scan->rs_relpredicatelocked)
! PredicateLockTuple(scan->rs_rd, tuple, scan->rs_snapshot);
scan->rs_cindex = lineindex;
return;
}
***************
*** 1470,1478 **** heap_fetch(Relation relation,
valid = HeapTupleSatisfiesVisibility(tuple, snapshot, buffer);
if (valid)
! PredicateLockTuple(relation, tuple);
! CheckForSerializableConflictOut(valid, relation, tuple, buffer);
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
--- 1470,1478 ----
valid = HeapTupleSatisfiesVisibility(tuple, snapshot, buffer);
if (valid)
! PredicateLockTuple(relation, tuple, snapshot);
! CheckForSerializableConflictOut(valid, relation, tuple, buffer, snapshot);
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
***************
*** 1588,1598 **** heap_hot_search_buffer(ItemPointer tid, Relation relation, Buffer buffer,
/* If it's visible per the snapshot, we must return it */
valid = HeapTupleSatisfiesVisibility(&heapTuple, snapshot, buffer);
! CheckForSerializableConflictOut(valid, relation, &heapTuple, buffer);
if (valid)
{
ItemPointerSetOffsetNumber(tid, offnum);
! PredicateLockTuple(relation, &heapTuple);
if (all_dead)
*all_dead = false;
return true;
--- 1588,1598 ----
/* If it's visible per the snapshot, we must return it */
valid = HeapTupleSatisfiesVisibility(&heapTuple, snapshot, buffer);
! CheckForSerializableConflictOut(valid, relation, &heapTuple, buffer, snapshot);
if (valid)
{
ItemPointerSetOffsetNumber(tid, offnum);
! PredicateLockTuple(relation, &heapTuple, snapshot);
if (all_dead)
*all_dead = false;
return true;
***************
*** 1750,1756 **** heap_get_latest_tid(Relation relation,
* result candidate.
*/
valid = HeapTupleSatisfiesVisibility(&tp, snapshot, buffer);
! CheckForSerializableConflictOut(valid, relation, &tp, buffer);
if (valid)
*tid = ctid;
--- 1750,1756 ----
* result candidate.
*/
valid = HeapTupleSatisfiesVisibility(&tp, snapshot, buffer);
! CheckForSerializableConflictOut(valid, relation, &tp, buffer, snapshot);
if (valid)
*tid = ctid;
*** a/src/backend/access/index/indexam.c
--- b/src/backend/access/index/indexam.c
***************
*** 126,132 **** do { \
} while(0)
static IndexScanDesc index_beginscan_internal(Relation indexRelation,
! int nkeys, int norderbys);
/* ----------------------------------------------------------------
--- 126,132 ----
} while(0)
static IndexScanDesc index_beginscan_internal(Relation indexRelation,
! int nkeys, int norderbys, const Snapshot snapshot);
/* ----------------------------------------------------------------
***************
*** 234,240 **** index_beginscan(Relation heapRelation,
{
IndexScanDesc scan;
! scan = index_beginscan_internal(indexRelation, nkeys, norderbys);
/*
* Save additional parameters into the scandesc. Everything else was set
--- 234,240 ----
{
IndexScanDesc scan;
! scan = index_beginscan_internal(indexRelation, nkeys, norderbys, snapshot);
/*
* Save additional parameters into the scandesc. Everything else was set
***************
*** 259,265 **** index_beginscan_bitmap(Relation indexRelation,
{
IndexScanDesc scan;
! scan = index_beginscan_internal(indexRelation, nkeys, 0);
/*
* Save additional parameters into the scandesc. Everything else was set
--- 259,265 ----
{
IndexScanDesc scan;
! scan = index_beginscan_internal(indexRelation, nkeys, 0, snapshot);
/*
* Save additional parameters into the scandesc. Everything else was set
***************
*** 275,281 **** index_beginscan_bitmap(Relation indexRelation,
*/
static IndexScanDesc
index_beginscan_internal(Relation indexRelation,
! int nkeys, int norderbys)
{
IndexScanDesc scan;
FmgrInfo *procedure;
--- 275,281 ----
*/
static IndexScanDesc
index_beginscan_internal(Relation indexRelation,
! int nkeys, int norderbys, const Snapshot snapshot)
{
IndexScanDesc scan;
FmgrInfo *procedure;
***************
*** 284,290 **** index_beginscan_internal(Relation indexRelation,
GET_REL_PROCEDURE(ambeginscan);
if (!(indexRelation->rd_am->ampredlocks))
! PredicateLockRelation(indexRelation);
/*
* We hold a reference count to the relcache entry throughout the scan.
--- 284,290 ----
GET_REL_PROCEDURE(ambeginscan);
if (!(indexRelation->rd_am->ampredlocks))
! PredicateLockRelation(indexRelation, snapshot);
/*
* We hold a reference count to the relcache entry throughout the scan.
***************
*** 602,608 **** index_getnext(IndexScanDesc scan, ScanDirection direction)
scan->xs_cbuf);
CheckForSerializableConflictOut(valid, scan->heapRelation,
! heapTuple, scan->xs_cbuf);
if (valid)
{
--- 602,609 ----
scan->xs_cbuf);
CheckForSerializableConflictOut(valid, scan->heapRelation,
! heapTuple, scan->xs_cbuf,
! scan->xs_snapshot);
if (valid)
{
***************
*** 624,630 **** index_getnext(IndexScanDesc scan, ScanDirection direction)
else
scan->xs_next_hot = InvalidOffsetNumber;
! PredicateLockTuple(scan->heapRelation, heapTuple);
LockBuffer(scan->xs_cbuf, BUFFER_LOCK_UNLOCK);
--- 625,631 ----
else
scan->xs_next_hot = InvalidOffsetNumber;
! PredicateLockTuple(scan->heapRelation, heapTuple, scan->xs_snapshot);
LockBuffer(scan->xs_cbuf, BUFFER_LOCK_UNLOCK);
*** a/src/backend/access/nbtree/nbtsearch.c
--- b/src/backend/access/nbtree/nbtsearch.c
***************
*** 65,71 **** _bt_search(Relation rel, int keysz, ScanKey scankey, bool nextkey,
/* If index is empty and access = BT_READ, no root page is created. */
if (!BufferIsValid(*bufP))
{
! PredicateLockRelation(rel); /* Nothing finer to lock exists. */
return (BTStack) NULL;
}
--- 65,71 ----
/* If index is empty and access = BT_READ, no root page is created. */
if (!BufferIsValid(*bufP))
{
! PredicateLockRelation(rel, NULL); /* Nothing finer to lock exists. */
return (BTStack) NULL;
}
***************
*** 94,100 **** _bt_search(Relation rel, int keysz, ScanKey scankey, bool nextkey,
if (P_ISLEAF(opaque))
{
if (access == BT_READ)
! PredicateLockPage(rel, BufferGetBlockNumber(*bufP));
break;
}
--- 94,100 ----
if (P_ISLEAF(opaque))
{
if (access == BT_READ)
! PredicateLockPage(rel, BufferGetBlockNumber(*bufP), NULL);
break;
}
***************
*** 1153,1159 **** _bt_steppage(IndexScanDesc scan, ScanDirection dir)
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
if (!P_IGNORE(opaque))
{
! PredicateLockPage(rel, blkno);
/* see if there are any matches on this page */
/* note that this will clear moreRight if we can stop */
if (_bt_readpage(scan, dir, P_FIRSTDATAKEY(opaque)))
--- 1153,1159 ----
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
if (!P_IGNORE(opaque))
{
! PredicateLockPage(rel, blkno, scan->xs_snapshot);
/* see if there are any matches on this page */
/* note that this will clear moreRight if we can stop */
if (_bt_readpage(scan, dir, P_FIRSTDATAKEY(opaque)))
***************
*** 1201,1207 **** _bt_steppage(IndexScanDesc scan, ScanDirection dir)
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
if (!P_IGNORE(opaque))
{
! PredicateLockPage(rel, BufferGetBlockNumber(so->currPos.buf));
/* see if there are any matches on this page */
/* note that this will clear moreLeft if we can stop */
if (_bt_readpage(scan, dir, PageGetMaxOffsetNumber(page)))
--- 1201,1207 ----
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
if (!P_IGNORE(opaque))
{
! PredicateLockPage(rel, BufferGetBlockNumber(so->currPos.buf), scan->xs_snapshot);
/* see if there are any matches on this page */
/* note that this will clear moreLeft if we can stop */
if (_bt_readpage(scan, dir, PageGetMaxOffsetNumber(page)))
***************
*** 1365,1371 **** _bt_get_endpoint(Relation rel, uint32 level, bool rightmost)
if (!BufferIsValid(buf))
{
/* empty index... */
! PredicateLockRelation(rel); /* Nothing finer to lock exists. */
return InvalidBuffer;
}
--- 1365,1371 ----
if (!BufferIsValid(buf))
{
/* empty index... */
! PredicateLockRelation(rel, NULL); /* Nothing finer to lock exists. */
return InvalidBuffer;
}
***************
*** 1445,1456 **** _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
if (!BufferIsValid(buf))
{
/* empty index... */
! PredicateLockRelation(rel); /* Nothing finer to lock exists. */
so->currPos.buf = InvalidBuffer;
return false;
}
! PredicateLockPage(rel, BufferGetBlockNumber(buf));
page = BufferGetPage(buf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
Assert(P_ISLEAF(opaque));
--- 1445,1456 ----
if (!BufferIsValid(buf))
{
/* empty index... */
! PredicateLockRelation(rel, scan->xs_snapshot); /* Nothing finer to lock exists. */
so->currPos.buf = InvalidBuffer;
return false;
}
! PredicateLockPage(rel, BufferGetBlockNumber(buf), scan->xs_snapshot);
page = BufferGetPage(buf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
Assert(P_ISLEAF(opaque));
*** a/src/backend/executor/nodeSeqscan.c
--- b/src/backend/executor/nodeSeqscan.c
***************
*** 113,119 **** SeqRecheck(SeqScanState *node, TupleTableSlot *slot)
TupleTableSlot *
ExecSeqScan(SeqScanState *node)
{
! PredicateLockRelation(node->ss_currentRelation);
node->ss_currentScanDesc->rs_relpredicatelocked = true;
return ExecScan((ScanState *) node,
(ExecScanAccessMtd) SeqNext,
--- 113,120 ----
TupleTableSlot *
ExecSeqScan(SeqScanState *node)
{
! PredicateLockRelation(node->ss_currentRelation,
! node->ss_currentScanDesc->rs_snapshot);
node->ss_currentScanDesc->rs_relpredicatelocked = true;
return ExecScan((ScanState *) node,
(ExecScanAccessMtd) SeqNext,
*** a/src/backend/storage/lmgr/predicate.c
--- b/src/backend/storage/lmgr/predicate.c
***************
*** 148,156 ****
* predicate lock maintenance
* RegisterSerializableTransaction(Snapshot snapshot)
* RegisterPredicateLockingXid(void)
! * PredicateLockRelation(Relation relation)
! * PredicateLockPage(Relation relation, BlockNumber blkno)
! * PredicateLockTuple(Relation relation, HeapTuple tuple)
* PredicateLockPageSplit(Relation relation, BlockNumber oldblkno,
* BlockNumber newblkno);
* PredicateLockPageCombine(Relation relation, BlockNumber oldblkno,
--- 148,158 ----
* predicate lock maintenance
* RegisterSerializableTransaction(Snapshot snapshot)
* RegisterPredicateLockingXid(void)
! * PredicateLockRelation(Relation relation, Snapshot snapshot)
! * PredicateLockPage(Relation relation, BlockNumber blkno,
! * Snapshot snapshot)
! * PredicateLockTuple(Relation relation, HeapTuple tuple,
! * Snapshot snapshot)
* PredicateLockPageSplit(Relation relation, BlockNumber oldblkno,
* BlockNumber newblkno);
* PredicateLockPageCombine(Relation relation, BlockNumber oldblkno,
***************
*** 160,166 ****
*
* conflict detection (may also trigger rollback)
* CheckForSerializableConflictOut(bool visible, Relation relation,
! * HeapTupleData *tup, Buffer buffer)
* CheckForSerializableConflictIn(Relation relation, HeapTupleData *tup,
* Buffer buffer)
* CheckTableForSerializableConflictIn(Relation relation)
--- 162,169 ----
*
* conflict detection (may also trigger rollback)
* CheckForSerializableConflictOut(bool visible, Relation relation,
! * HeapTupleData *tup, Buffer buffer,
! * Snapshot snapshot)
* CheckForSerializableConflictIn(Relation relation, HeapTupleData *tup,
* Buffer buffer)
* CheckTableForSerializableConflictIn(Relation relation)
***************
*** 271,279 ****
* the current transaction, this is the test to see if we should do a quick
* return.
*/
! #define SkipSerialization(relation) \
((!IsolationIsSerializable()) \
|| ((MySerializableXact == InvalidSerializableXact)) \
|| ReleasePredicateLocksIfROSafe() \
|| SkipPredicateLocksForRelation(relation))
--- 274,283 ----
* the current transaction, this is the test to see if we should do a quick
* return.
*/
! #define SkipSerialization(relation, snapshot) \
((!IsolationIsSerializable()) \
|| ((MySerializableXact == InvalidSerializableXact)) \
+ || ((snapshot) != NULL && !IsMVCCSnapshot(snapshot)) \
|| ReleasePredicateLocksIfROSafe() \
|| SkipPredicateLocksForRelation(relation))
***************
*** 2201,2211 **** PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
* Clear any finer-grained predicate locks this session has on the relation.
*/
void
! PredicateLockRelation(const Relation relation)
{
PREDICATELOCKTARGETTAG tag;
! if (SkipSerialization(relation))
return;
SET_PREDICATELOCKTARGETTAG_RELATION(tag,
--- 2205,2215 ----
* Clear any finer-grained predicate locks this session has on the relation.
*/
void
! PredicateLockRelation(const Relation relation, const Snapshot snapshot)
{
PREDICATELOCKTARGETTAG tag;
! if (SkipSerialization(relation, snapshot))
return;
SET_PREDICATELOCKTARGETTAG_RELATION(tag,
***************
*** 2224,2234 **** PredicateLockRelation(const Relation relation)
* Clear any finer-grained predicate locks this session has on the relation.
*/
void
! PredicateLockPage(const Relation relation, const BlockNumber blkno)
{
PREDICATELOCKTARGETTAG tag;
! if (SkipSerialization(relation))
return;
SET_PREDICATELOCKTARGETTAG_PAGE(tag,
--- 2228,2239 ----
* Clear any finer-grained predicate locks this session has on the relation.
*/
void
! PredicateLockPage(const Relation relation, const BlockNumber blkno,
! const Snapshot snapshot)
{
PREDICATELOCKTARGETTAG tag;
! if (SkipSerialization(relation, snapshot))
return;
SET_PREDICATELOCKTARGETTAG_PAGE(tag,
***************
*** 2246,2258 **** PredicateLockPage(const Relation relation, const BlockNumber blkno)
* Skip if this is a temporary table.
*/
void
! PredicateLockTuple(const Relation relation, const HeapTuple tuple)
{
PREDICATELOCKTARGETTAG tag;
ItemPointer tid;
TransactionId targetxmin;
! if (SkipSerialization(relation))
return;
/*
--- 2251,2264 ----
* Skip if this is a temporary table.
*/
void
! PredicateLockTuple(const Relation relation, const HeapTuple tuple,
! const Snapshot snapshot)
{
PREDICATELOCKTARGETTAG tag;
ItemPointer tid;
TransactionId targetxmin;
! if (SkipSerialization(relation, snapshot))
return;
/*
***************
*** 3613,3619 **** XidIsConcurrent(TransactionId xid)
*/
void
CheckForSerializableConflictOut(const bool visible, const Relation relation,
! const HeapTuple tuple, const Buffer buffer)
{
TransactionId xid;
SERIALIZABLEXIDTAG sxidtag;
--- 3619,3626 ----
*/
void
CheckForSerializableConflictOut(const bool visible, const Relation relation,
! const HeapTuple tuple, const Buffer buffer,
! const Snapshot snapshot)
{
TransactionId xid;
SERIALIZABLEXIDTAG sxidtag;
***************
*** 3621,3627 **** CheckForSerializableConflictOut(const bool visible, const Relation relation,
SERIALIZABLEXACT *sxact;
HTSV_Result htsvResult;
! if (SkipSerialization(relation))
return;
if (SxactIsMarkedForDeath(MySerializableXact))
--- 3628,3634 ----
SERIALIZABLEXACT *sxact;
HTSV_Result htsvResult;
! if (SkipSerialization(relation, snapshot))
return;
if (SxactIsMarkedForDeath(MySerializableXact))
***************
*** 3998,4004 **** CheckForSerializableConflictIn(const Relation relation, const HeapTuple tuple,
{
PREDICATELOCKTARGETTAG targettag;
! if (SkipSerialization(relation))
return;
if (SxactIsMarkedForDeath(MySerializableXact))
--- 4005,4011 ----
{
PREDICATELOCKTARGETTAG targettag;
! if (SkipSerialization(relation, (Snapshot) NULL))
return;
if (SxactIsMarkedForDeath(MySerializableXact))
***************
*** 4090,4096 **** CheckTableForSerializableConflictIn(const Relation relation)
if (!TransactionIdIsValid(PredXact->SxactGlobalXmin))
return;
! if (SkipSerialization(relation))
return;
Assert(relation->rd_index == NULL); /* not an index relation */
--- 4097,4103 ----
if (!TransactionIdIsValid(PredXact->SxactGlobalXmin))
return;
! if (SkipSerialization(relation, (Snapshot) NULL))
return;
Assert(relation->rd_index == NULL); /* not an index relation */
*** a/src/include/storage/predicate.h
--- b/src/include/storage/predicate.h
***************
*** 44,59 **** extern bool PageIsPredicateLocked(const Relation relation, const BlockNumber blk
/* predicate lock maintenance */
extern Snapshot RegisterSerializableTransaction(Snapshot snapshot);
extern void RegisterPredicateLockingXid(const TransactionId xid);
! extern void PredicateLockRelation(const Relation relation);
! extern void PredicateLockPage(const Relation relation, const BlockNumber blkno);
! extern void PredicateLockTuple(const Relation relation, const HeapTuple tuple);
extern void PredicateLockPageSplit(const Relation relation, const BlockNumber oldblkno, const BlockNumber newblkno);
extern void PredicateLockPageCombine(const Relation relation, const BlockNumber oldblkno, const BlockNumber newblkno);
extern void TransferPredicateLocksToHeapRelation(const Relation relation);
extern void ReleasePredicateLocks(const bool isCommit);
/* conflict detection (may also trigger rollback) */
! extern void CheckForSerializableConflictOut(const bool valid, const Relation relation, const HeapTuple tuple, const Buffer buffer);
extern void CheckForSerializableConflictIn(const Relation relation, const HeapTuple tuple, const Buffer buffer);
extern void CheckTableForSerializableConflictIn(const Relation relation);
--- 44,60 ----
/* predicate lock maintenance */
extern Snapshot RegisterSerializableTransaction(Snapshot snapshot);
extern void RegisterPredicateLockingXid(const TransactionId xid);
! extern void PredicateLockRelation(const Relation relation, const Snapshot snapshot);
! extern void PredicateLockPage(const Relation relation, const BlockNumber blkno, const Snapshot snapshot);
! extern void PredicateLockTuple(const Relation relation, const HeapTuple tuple, const Snapshot snapshot);
extern void PredicateLockPageSplit(const Relation relation, const BlockNumber oldblkno, const BlockNumber newblkno);
extern void PredicateLockPageCombine(const Relation relation, const BlockNumber oldblkno, const BlockNumber newblkno);
extern void TransferPredicateLocksToHeapRelation(const Relation relation);
extern void ReleasePredicateLocks(const bool isCommit);
/* conflict detection (may also trigger rollback) */
! extern void CheckForSerializableConflictOut(const bool valid, const Relation relation, const HeapTuple tuple,
! const Buffer buffer, const Snapshot snapshot);
extern void CheckForSerializableConflictIn(const Relation relation, const HeapTuple tuple, const Buffer buffer);
extern void CheckTableForSerializableConflictIn(const Relation relation);