* transaction. If compatible, return true with the buffer exclusive-locked,
* and the caller must release that by calling
* heap_inplace_update_and_unlock(), calling heap_inplace_unlock(), or raising
- * an error. Otherwise, return false after blocking transactions, if any,
- * have ended.
+ * an error. Otherwise, call release_callback(arg), wait for blocking
+ * transactions to end, and return false.
*
* Since this is intended for system catalogs and SERIALIZABLE doesn't cover
* DDL, this doesn't guarantee any particular predicate locking.
*/
bool
heap_inplace_lock(Relation relation,
- HeapTuple oldtup_ptr, Buffer buffer)
+ HeapTuple oldtup_ptr, Buffer buffer,
+ void (*release_callback) (void *), void *arg)
{
HeapTupleData oldtup = *oldtup_ptr; /* minimize diff vs. heap_update() */
TM_Result result;
lockmode, NULL))
{
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+ release_callback(arg);
ret = false;
MultiXactIdWait((MultiXactId) xwait, mxact_status, infomask,
relation, &oldtup.t_self, XLTW_Update,
else
{
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+ release_callback(arg);
ret = false;
XactLockTableWait(xwait, relation, &oldtup.t_self,
XLTW_Update);
if (!ret)
{
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+ release_callback(arg);
}
}
int retries = 0;
SysScanDesc scan;
HeapTuple oldtup;
+ BufferHeapTupleTableSlot *bslot;
/*
* For now, we don't allow parallel updates. Unlike a regular update,
Assert(IsInplaceUpdateRelation(relation) || !IsSystemRelation(relation));
/* Loop for an exclusive-locked buffer of a non-updated tuple. */
- for (;;)
+ do
{
TupleTableSlot *slot;
- BufferHeapTupleTableSlot *bslot;
CHECK_FOR_INTERRUPTS();
slot = scan->slot;
Assert(TTS_IS_BUFFERTUPLE(slot));
bslot = (BufferHeapTupleTableSlot *) slot;
- if (heap_inplace_lock(scan->heap_rel,
- bslot->base.tuple, bslot->buffer))
- break;
- systable_endscan(scan);
- };
+ } while (!heap_inplace_lock(scan->heap_rel,
+ bslot->base.tuple, bslot->buffer,
+ (void (*) (void *)) systable_endscan, scan));
*oldtupcopy = heap_copytuple(oldtup);
*state = scan;
Buffer *buffer, struct TM_FailureData *tmfd);
extern bool heap_inplace_lock(Relation relation,
- HeapTuple oldtup_ptr, Buffer buffer);
+ HeapTuple oldtup_ptr, Buffer buffer,
+ void (*release_callback) (void *), void *arg);
extern void heap_inplace_update_and_unlock(Relation relation,
HeapTuple oldtup, HeapTuple tuple,
Buffer buffer);