1/*-------------------------------------------------------------------------
2 *
3 * lmgr.c
4 * POSTGRES lock manager code
5 *
6 * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/storage/lmgr/lmgr.c
12 *
13 *-------------------------------------------------------------------------
14 */
15
16#include "postgres.h"
17
18#include "access/subtrans.h"
19#include "access/transam.h"
20#include "access/xact.h"
21#include "catalog/catalog.h"
22#include "commands/progress.h"
23#include "miscadmin.h"
24#include "pgstat.h"
25#include "storage/lmgr.h"
26#include "storage/procarray.h"
27#include "storage/sinvaladt.h"
28#include "utils/inval.h"
29
30
31/*
32 * Per-backend counter for generating speculative insertion tokens.
33 *
34 * This may wrap around, but that's OK as it's only used for the short
35 * duration between inserting a tuple and checking that there are no (unique)
36 * constraint violations. It's theoretically possible that a backend sees a
37 * tuple that was speculatively inserted by another backend, but before it has
38 * started waiting on the token, the other backend completes its insertion,
39 * and then performs 2^32 unrelated insertions. And after all that, the
40 * first backend finally calls SpeculativeInsertionLockAcquire(), with the
41 * intention of waiting for the first insertion to complete, but ends up
42 * waiting for the latest unrelated insertion instead. Even then, nothing
43 * particularly bad happens: in the worst case they deadlock, causing one of
44 * the transactions to abort.
45 */
46static uint32 speculativeInsertionToken = 0;
47
48
49/*
50 * Struct to hold context info for transaction lock waits.
51 *
52 * 'oper' is the operation that needs to wait for the other transaction; 'rel'
53 * and 'ctid' specify the address of the tuple being waited for.
54 */
55typedef struct XactLockTableWaitInfo
56{
57 XLTW_Oper oper;
58 Relation rel;
59 ItemPointer ctid;
60} XactLockTableWaitInfo;
61
62static void XactLockTableWaitErrorCb(void *arg);
63
64/*
65 * RelationInitLockInfo
66 * Initializes the lock information in a relation descriptor.
67 *
68 * relcache.c must call this during creation of any reldesc.
69 */
70void
71RelationInitLockInfo(Relation relation)
72{
73 Assert(RelationIsValid(relation));
74 Assert(OidIsValid(RelationGetRelid(relation)));
75
76 relation->rd_lockInfo.lockRelId.relId = RelationGetRelid(relation);
77
78 if (relation->rd_rel->relisshared)
79 relation->rd_lockInfo.lockRelId.dbId = InvalidOid;
80 else
81 relation->rd_lockInfo.lockRelId.dbId = MyDatabaseId;
82}
83
84/*
85 * SetLocktagRelationOid
86 * Set up a locktag for a relation, given only relation OID
87 */
88static inline void
89SetLocktagRelationOid(LOCKTAG *tag, Oid relid)
90{
91 Oid dbid;
92
93 if (IsSharedRelation(relid))
94 dbid = InvalidOid;
95 else
96 dbid = MyDatabaseId;
97
98 SET_LOCKTAG_RELATION(*tag, dbid, relid);
99}
100
101/*
102 * LockRelationOid
103 *
104 * Lock a relation given only its OID. This should generally be used
105 * before attempting to open the relation's relcache entry.
106 */
107void
108LockRelationOid(Oid relid, LOCKMODE lockmode)
109{
110 LOCKTAG tag;
111 LOCALLOCK *locallock;
112 LockAcquireResult res;
113
114 SetLocktagRelationOid(&tag, relid);
115
116 res = LockAcquireExtended(&tag, lockmode, false, false, true, &locallock);
117
118 /*
119 * Now that we have the lock, check for invalidation messages, so that we
120 * will update or flush any stale relcache entry before we try to use it.
121 * RangeVarGetRelid() specifically relies on us for this. We can skip
122 * this in the not-uncommon case that we already had the same type of lock
123 * being requested, since then no one else could have modified the
124 * relcache entry in an undesirable way. (In the case where our own xact
125 * modifies the rel, the relcache update happens via
126 * CommandCounterIncrement, not here.)
127 *
128 * However, in corner cases where code acts on tables (usually catalogs)
129 * recursively, we might get here while still processing invalidation
130 * messages in some outer execution of this function or a sibling. The
131 * "cleared" status of the lock tells us whether we really are done
132 * absorbing relevant inval messages.
133 */
134 if (res != LOCKACQUIRE_ALREADY_CLEAR)
135 {
136 AcceptInvalidationMessages();
137 MarkLockClear(locallock);
138 }
139}
140
141/*
142 * ConditionalLockRelationOid
143 *
144 * As above, but only lock if we can get the lock without blocking.
145 * Returns true iff the lock was acquired.
146 *
147 * NOTE: we do not currently need conditional versions of all the
148 * LockXXX routines in this file, but they could easily be added if needed.
149 */
150bool
151ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode)
152{
153 LOCKTAG tag;
154 LOCALLOCK *locallock;
155 LockAcquireResult res;
156
157 SetLocktagRelationOid(&tag, relid);
158
159 res = LockAcquireExtended(&tag, lockmode, false, true, true, &locallock);
160
161 if (res == LOCKACQUIRE_NOT_AVAIL)
162 return false;
163
164 /*
165 * Now that we have the lock, check for invalidation messages; see notes
166 * in LockRelationOid.
167 */
168 if (res != LOCKACQUIRE_ALREADY_CLEAR)
169 {
170 AcceptInvalidationMessages();
171 MarkLockClear(locallock);
172 }
173
174 return true;
175}
176
177/*
178 * UnlockRelationId
179 *
180 * Unlock, given a LockRelId. This is preferred over UnlockRelationOid
181 * for speed reasons.
182 */
183void
184UnlockRelationId(LockRelId *relid, LOCKMODE lockmode)
185{
186 LOCKTAG tag;
187
188 SET_LOCKTAG_RELATION(tag, relid->dbId, relid->relId);
189
190 LockRelease(&tag, lockmode, false);
191}
192
193/*
194 * UnlockRelationOid
195 *
196 * Unlock, given only a relation Oid. Use UnlockRelationId if you can.
197 */
198void
199UnlockRelationOid(Oid relid, LOCKMODE lockmode)
200{
201 LOCKTAG tag;
202
203 SetLocktagRelationOid(&tag, relid);
204
205 LockRelease(&tag, lockmode, false);
206}
207
208/*
209 * LockRelation
210 *
211 * This is a convenience routine for acquiring an additional lock on an
212 * already-open relation. Never try to do "relation_open(foo, NoLock)"
213 * and then lock with this.
214 */
215void
216LockRelation(Relation relation, LOCKMODE lockmode)
217{
218 LOCKTAG tag;
219 LOCALLOCK *locallock;
220 LockAcquireResult res;
221
222 SET_LOCKTAG_RELATION(tag,
223 relation->rd_lockInfo.lockRelId.dbId,
224 relation->rd_lockInfo.lockRelId.relId);
225
226 res = LockAcquireExtended(&tag, lockmode, false, false, true, &locallock);
227
228 /*
229 * Now that we have the lock, check for invalidation messages; see notes
230 * in LockRelationOid.
231 */
232 if (res != LOCKACQUIRE_ALREADY_CLEAR)
233 {
234 AcceptInvalidationMessages();
235 MarkLockClear(locallock);
236 }
237}
238
239/*
240 * ConditionalLockRelation
241 *
242 * This is a convenience routine for acquiring an additional lock on an
243 * already-open relation. Never try to do "relation_open(foo, NoLock)"
244 * and then lock with this.
245 */
246bool
247ConditionalLockRelation(Relation relation, LOCKMODE lockmode)
248{
249 LOCKTAG tag;
250 LOCALLOCK *locallock;
251 LockAcquireResult res;
252
253 SET_LOCKTAG_RELATION(tag,
254 relation->rd_lockInfo.lockRelId.dbId,
255 relation->rd_lockInfo.lockRelId.relId);
256
257 res = LockAcquireExtended(&tag, lockmode, false, true, true, &locallock);
258
259 if (res == LOCKACQUIRE_NOT_AVAIL)
260 return false;
261
262 /*
263 * Now that we have the lock, check for invalidation messages; see notes
264 * in LockRelationOid.
265 */
266 if (res != LOCKACQUIRE_ALREADY_CLEAR)
267 {
268 AcceptInvalidationMessages();
269 MarkLockClear(locallock);
270 }
271
272 return true;
273}
274
275/*
276 * UnlockRelation
277 *
278 * This is a convenience routine for unlocking a relation without also
279 * closing it.
280 */
281void
282UnlockRelation(Relation relation, LOCKMODE lockmode)
283{
284 LOCKTAG tag;
285
286 SET_LOCKTAG_RELATION(tag,
287 relation->rd_lockInfo.lockRelId.dbId,
288 relation->rd_lockInfo.lockRelId.relId);
289
290 LockRelease(&tag, lockmode, false);
291}
292
293/*
294 * CheckRelationLockedByMe
295 *
296 * Returns true if current transaction holds a lock on 'relation' of mode
297 * 'lockmode'. If 'orstronger' is true, a stronger lockmode is also OK.
298 * ("Stronger" is defined as "numerically higher", which is a bit
299 * semantically dubious but is OK for the purposes we use this for.)
300 */
301bool
302CheckRelationLockedByMe(Relation relation, LOCKMODE lockmode, bool orstronger)
303{
304 LOCKTAG tag;
305
306 SET_LOCKTAG_RELATION(tag,
307 relation->rd_lockInfo.lockRelId.dbId,
308 relation->rd_lockInfo.lockRelId.relId);
309
310 if (LockHeldByMe(&tag, lockmode))
311 return true;
312
313 if (orstronger)
314 {
315 LOCKMODE slockmode;
316
317 for (slockmode = lockmode + 1;
318 slockmode <= MaxLockMode;
319 slockmode++)
320 {
321 if (LockHeldByMe(&tag, slockmode))
322 {
323#ifdef NOT_USED
324 /* Sometimes this might be useful for debugging purposes */
325 elog(WARNING, "lock mode %s substituted for %s on relation %s",
326 GetLockmodeName(tag.locktag_lockmethodid, slockmode),
327 GetLockmodeName(tag.locktag_lockmethodid, lockmode),
328 RelationGetRelationName(relation));
329#endif
330 return true;
331 }
332 }
333 }
334
335 return false;
336}
337
338/*
339 * LockHasWaitersRelation
340 *
341 * This is a function to check whether someone else is waiting for a
342 * lock which we are currently holding.
343 */
344bool
345LockHasWaitersRelation(Relation relation, LOCKMODE lockmode)
346{
347 LOCKTAG tag;
348
349 SET_LOCKTAG_RELATION(tag,
350 relation->rd_lockInfo.lockRelId.dbId,
351 relation->rd_lockInfo.lockRelId.relId);
352
353 return LockHasWaiters(&tag, lockmode, false);
354}
355
356/*
357 * LockRelationIdForSession
358 *
359 * This routine grabs a session-level lock on the target relation. The
360 * session lock persists across transaction boundaries. It will be removed
361 * when UnlockRelationIdForSession() is called, or if an ereport(ERROR) occurs,
362 * or if the backend exits.
363 *
364 * Note that one should also grab a transaction-level lock on the rel
365 * in any transaction that actually uses the rel, to ensure that the
366 * relcache entry is up to date.
367 */
368void
369LockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
370{
371 LOCKTAG tag;
372
373 SET_LOCKTAG_RELATION(tag, relid->dbId, relid->relId);
374
375 (void) LockAcquire(&tag, lockmode, true, false);
376}
377
378/*
379 * UnlockRelationIdForSession
380 */
381void
382UnlockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
383{
384 LOCKTAG tag;
385
386 SET_LOCKTAG_RELATION(tag, relid->dbId, relid->relId);
387
388 LockRelease(&tag, lockmode, true);
389}
390
391/*
392 * LockRelationForExtension
393 *
394 * This lock tag is used to interlock addition of pages to relations.
395 * We need such locking because bufmgr/smgr definition of P_NEW is not
396 * race-condition-proof.
397 *
398 * We assume the caller is already holding some type of regular lock on
399 * the relation, so no AcceptInvalidationMessages call is needed here.
400 */
401void
402LockRelationForExtension(Relation relation, LOCKMODE lockmode)
403{
404 LOCKTAG tag;
405
406 SET_LOCKTAG_RELATION_EXTEND(tag,
407 relation->rd_lockInfo.lockRelId.dbId,
408 relation->rd_lockInfo.lockRelId.relId);
409
410 (void) LockAcquire(&tag, lockmode, false, false);
411}
412
413/*
414 * ConditionalLockRelationForExtension
415 *
416 * As above, but only lock if we can get the lock without blocking.
417 * Returns true iff the lock was acquired.
418 */
419bool
420ConditionalLockRelationForExtension(Relation relation, LOCKMODE lockmode)
421{
422 LOCKTAG tag;
423
424 SET_LOCKTAG_RELATION_EXTEND(tag,
425 relation->rd_lockInfo.lockRelId.dbId,
426 relation->rd_lockInfo.lockRelId.relId);
427
428 return (LockAcquire(&tag, lockmode, false, true) != LOCKACQUIRE_NOT_AVAIL);
429}
430
431/*
432 * RelationExtensionLockWaiterCount
433 *
434 * Count the number of processes waiting for the given relation extension lock.
435 */
436int
437RelationExtensionLockWaiterCount(Relation relation)
438{
439 LOCKTAG tag;
440
441 SET_LOCKTAG_RELATION_EXTEND(tag,
442 relation->rd_lockInfo.lockRelId.dbId,
443 relation->rd_lockInfo.lockRelId.relId);
444
445 return LockWaiterCount(&tag);
446}
447
448/*
449 * UnlockRelationForExtension
450 */
451void
452UnlockRelationForExtension(Relation relation, LOCKMODE lockmode)
453{
454 LOCKTAG tag;
455
456 SET_LOCKTAG_RELATION_EXTEND(tag,
457 relation->rd_lockInfo.lockRelId.dbId,
458 relation->rd_lockInfo.lockRelId.relId);
459
460 LockRelease(&tag, lockmode, false);
461}
462
463/*
464 * LockPage
465 *
466 * Obtain a page-level lock. This is currently used by some index access
467 * methods to lock individual index pages.
468 */
469void
470LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
471{
472 LOCKTAG tag;
473
474 SET_LOCKTAG_PAGE(tag,
475 relation->rd_lockInfo.lockRelId.dbId,
476 relation->rd_lockInfo.lockRelId.relId,
477 blkno);
478
479 (void) LockAcquire(&tag, lockmode, false, false);
480}
481
482/*
483 * ConditionalLockPage
484 *
485 * As above, but only lock if we can get the lock without blocking.
486 * Returns true iff the lock was acquired.
487 */
488bool
489ConditionalLockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
490{
491 LOCKTAG tag;
492
493 SET_LOCKTAG_PAGE(tag,
494 relation->rd_lockInfo.lockRelId.dbId,
495 relation->rd_lockInfo.lockRelId.relId,
496 blkno);
497
498 return (LockAcquire(&tag, lockmode, false, true) != LOCKACQUIRE_NOT_AVAIL);
499}
500
501/*
502 * UnlockPage
503 */
504void
505UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
506{
507 LOCKTAG tag;
508
509 SET_LOCKTAG_PAGE(tag,
510 relation->rd_lockInfo.lockRelId.dbId,
511 relation->rd_lockInfo.lockRelId.relId,
512 blkno);
513
514 LockRelease(&tag, lockmode, false);
515}
516
517/*
518 * LockTuple
519 *
520 * Obtain a tuple-level lock. This is used in a less-than-intuitive fashion
521 * because we can't afford to keep a separate lock in shared memory for every
522 * tuple. See heap_lock_tuple before using this!
523 */
524void
525LockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode)
526{
527 LOCKTAG tag;
528
529 SET_LOCKTAG_TUPLE(tag,
530 relation->rd_lockInfo.lockRelId.dbId,
531 relation->rd_lockInfo.lockRelId.relId,
532 ItemPointerGetBlockNumber(tid),
533 ItemPointerGetOffsetNumber(tid));
534
535 (void) LockAcquire(&tag, lockmode, false, false);
536}
537
538/*
539 * ConditionalLockTuple
540 *
541 * As above, but only lock if we can get the lock without blocking.
542 * Returns true iff the lock was acquired.
543 */
544bool
545ConditionalLockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode)
546{
547 LOCKTAG tag;
548
549 SET_LOCKTAG_TUPLE(tag,
550 relation->rd_lockInfo.lockRelId.dbId,
551 relation->rd_lockInfo.lockRelId.relId,
552 ItemPointerGetBlockNumber(tid),
553 ItemPointerGetOffsetNumber(tid));
554
555 return (LockAcquire(&tag, lockmode, false, true) != LOCKACQUIRE_NOT_AVAIL);
556}
557
558/*
559 * UnlockTuple
560 */
561void
562UnlockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode)
563{
564 LOCKTAG tag;
565
566 SET_LOCKTAG_TUPLE(tag,
567 relation->rd_lockInfo.lockRelId.dbId,
568 relation->rd_lockInfo.lockRelId.relId,
569 ItemPointerGetBlockNumber(tid),
570 ItemPointerGetOffsetNumber(tid));
571
572 LockRelease(&tag, lockmode, false);
573}
574
575/*
576 * XactLockTableInsert
577 *
578 * Insert a lock showing that the given transaction ID is running ---
579 * this is done when an XID is acquired by a transaction or subtransaction.
580 * The lock can then be used to wait for the transaction to finish.
581 */
582void
583XactLockTableInsert(TransactionId xid)
584{
585 LOCKTAG tag;
586
587 SET_LOCKTAG_TRANSACTION(tag, xid);
588
589 (void) LockAcquire(&tag, ExclusiveLock, false, false);
590}
591
592/*
593 * XactLockTableDelete
594 *
595 * Delete the lock showing that the given transaction ID is running.
596 * (This is never used for main transaction IDs; those locks are only
597 * released implicitly at transaction end. But we do use it for subtrans IDs.)
598 */
599void
600XactLockTableDelete(TransactionId xid)
601{
602 LOCKTAG tag;
603
604 SET_LOCKTAG_TRANSACTION(tag, xid);
605
606 LockRelease(&tag, ExclusiveLock, false);
607}
608
609/*
610 * XactLockTableWait
611 *
612 * Wait for the specified transaction to commit or abort. If an operation
613 * is specified, an error context callback is set up. If 'oper' is passed as
614 * None, no error context callback is set up.
615 *
616 * Note that this does the right thing for subtransactions: if we wait on a
617 * subtransaction, we will exit as soon as it aborts or its top parent commits.
618 * It takes some extra work to ensure this, because to save on shared memory
619 * the XID lock of a subtransaction is released when it ends, whether
620 * successfully or unsuccessfully. So we have to check if it's "still running"
621 * and if so wait for its parent.
622 */
623void
624XactLockTableWait(TransactionId xid, Relation rel, ItemPointer ctid,
625 XLTW_Oper oper)
626{
627 LOCKTAG tag;
628 XactLockTableWaitInfo info;
629 ErrorContextCallback callback;
630 bool first = true;
631
632 /*
633 * If an operation is specified, set up our verbose error context
634 * callback.
635 */
636 if (oper != XLTW_None)
637 {
638 Assert(RelationIsValid(rel));
639 Assert(ItemPointerIsValid(ctid));
640
641 info.rel = rel;
642 info.ctid = ctid;
643 info.oper = oper;
644
645 callback.callback = XactLockTableWaitErrorCb;
646 callback.arg = &info;
647 callback.previous = error_context_stack;
648 error_context_stack = &callback;
649 }
650
651 for (;;)
652 {
653 Assert(TransactionIdIsValid(xid));
654 Assert(!TransactionIdEquals(xid, GetTopTransactionIdIfAny()));
655
656 SET_LOCKTAG_TRANSACTION(tag, xid);
657
658 (void) LockAcquire(&tag, ShareLock, false, false);
659
660 LockRelease(&tag, ShareLock, false);
661
662 if (!TransactionIdIsInProgress(xid))
663 break;
664
665 /*
666 * If the Xid belonged to a subtransaction, then the lock would have
667 * gone away as soon as it was finished; for correct tuple visibility,
668 * the right action is to wait on its parent transaction to go away.
669 * But instead of going levels up one by one, we can just wait for the
670 * topmost transaction to finish with the same end result, which also
671 * incurs less locktable traffic.
672 *
673 * Some uses of this function don't involve tuple visibility -- such
674 * as when building snapshots for logical decoding. It is possible to
675 * see a transaction in ProcArray before it registers itself in the
676 * locktable. The topmost transaction in that case is the same xid,
677 * so we try again after a short sleep. (Don't sleep the first time
678 * through, to avoid slowing down the normal case.)
679 */
680 if (!first)
681 pg_usleep(1000L);
682 first = false;
683 xid = SubTransGetTopmostTransaction(xid);
684 }
685
686 if (oper != XLTW_None)
687 error_context_stack = callback.previous;
688}
689
690/*
691 * ConditionalXactLockTableWait
692 *
693 * As above, but only lock if we can get the lock without blocking.
694 * Returns true if the lock was acquired.
695 */
696bool
697ConditionalXactLockTableWait(TransactionId xid)
698{
699 LOCKTAG tag;
700 bool first = true;
701
702 for (;;)
703 {
704 Assert(TransactionIdIsValid(xid));
705 Assert(!TransactionIdEquals(xid, GetTopTransactionIdIfAny()));
706
707 SET_LOCKTAG_TRANSACTION(tag, xid);
708
709 if (LockAcquire(&tag, ShareLock, false, true) == LOCKACQUIRE_NOT_AVAIL)
710 return false;
711
712 LockRelease(&tag, ShareLock, false);
713
714 if (!TransactionIdIsInProgress(xid))
715 break;
716
717 /* See XactLockTableWait about this case */
718 if (!first)
719 pg_usleep(1000L);
720 first = false;
721 xid = SubTransGetTopmostTransaction(xid);
722 }
723
724 return true;
725}
726
727/*
728 * SpeculativeInsertionLockAcquire
729 *
730 * Insert a lock showing that the given transaction ID is inserting a tuple,
731 * but hasn't yet decided whether it's going to keep it. The lock can then be
732 * used to wait for the decision to go ahead with the insertion, or aborting
733 * it.
734 *
735 * The token is used to distinguish multiple insertions by the same
736 * transaction. It is returned to caller.
737 */
738uint32
739SpeculativeInsertionLockAcquire(TransactionId xid)
740{
741 LOCKTAG tag;
742
743 speculativeInsertionToken++;
744
745 /*
746 * Check for wrap-around. Zero means no token is held, so don't use that.
747 */
748 if (speculativeInsertionToken == 0)
749 speculativeInsertionToken = 1;
750
751 SET_LOCKTAG_SPECULATIVE_INSERTION(tag, xid, speculativeInsertionToken);
752
753 (void) LockAcquire(&tag, ExclusiveLock, false, false);
754
755 return speculativeInsertionToken;
756}
757
758/*
759 * SpeculativeInsertionLockRelease
760 *
761 * Delete the lock showing that the given transaction is speculatively
762 * inserting a tuple.
763 */
764void
765SpeculativeInsertionLockRelease(TransactionId xid)
766{
767 LOCKTAG tag;
768
769 SET_LOCKTAG_SPECULATIVE_INSERTION(tag, xid, speculativeInsertionToken);
770
771 LockRelease(&tag, ExclusiveLock, false);
772}
773
774/*
775 * SpeculativeInsertionWait
776 *
777 * Wait for the specified transaction to finish or abort the insertion of a
778 * tuple.
779 */
780void
781SpeculativeInsertionWait(TransactionId xid, uint32 token)
782{
783 LOCKTAG tag;
784
785 SET_LOCKTAG_SPECULATIVE_INSERTION(tag, xid, token);
786
787 Assert(TransactionIdIsValid(xid));
788 Assert(token != 0);
789
790 (void) LockAcquire(&tag, ShareLock, false, false);
791 LockRelease(&tag, ShareLock, false);
792}
793
794/*
795 * XactLockTableWaitErrorContextCb
796 * Error context callback for transaction lock waits.
797 */
798static void
799XactLockTableWaitErrorCb(void *arg)
800{
801 XactLockTableWaitInfo *info = (XactLockTableWaitInfo *) arg;
802
803 /*
804 * We would like to print schema name too, but that would require a
805 * syscache lookup.
806 */
807 if (info->oper != XLTW_None &&
808 ItemPointerIsValid(info->ctid) && RelationIsValid(info->rel))
809 {
810 const char *cxt;
811
812 switch (info->oper)
813 {
814 case XLTW_Update:
815 cxt = gettext_noop("while updating tuple (%u,%u) in relation \"%s\"");
816 break;
817 case XLTW_Delete:
818 cxt = gettext_noop("while deleting tuple (%u,%u) in relation \"%s\"");
819 break;
820 case XLTW_Lock:
821 cxt = gettext_noop("while locking tuple (%u,%u) in relation \"%s\"");
822 break;
823 case XLTW_LockUpdated:
824 cxt = gettext_noop("while locking updated version (%u,%u) of tuple in relation \"%s\"");
825 break;
826 case XLTW_InsertIndex:
827 cxt = gettext_noop("while inserting index tuple (%u,%u) in relation \"%s\"");
828 break;
829 case XLTW_InsertIndexUnique:
830 cxt = gettext_noop("while checking uniqueness of tuple (%u,%u) in relation \"%s\"");
831 break;
832 case XLTW_FetchUpdated:
833 cxt = gettext_noop("while rechecking updated tuple (%u,%u) in relation \"%s\"");
834 break;
835 case XLTW_RecheckExclusionConstr:
836 cxt = gettext_noop("while checking exclusion constraint on tuple (%u,%u) in relation \"%s\"");
837 break;
838
839 default:
840 return;
841 }
842
843 errcontext(cxt,
844 ItemPointerGetBlockNumber(info->ctid),
845 ItemPointerGetOffsetNumber(info->ctid),
846 RelationGetRelationName(info->rel));
847 }
848}
849
850/*
851 * WaitForLockersMultiple
852 * Wait until no transaction holds locks that conflict with the given
853 * locktags at the given lockmode.
854 *
855 * To do this, obtain the current list of lockers, and wait on their VXIDs
856 * until they are finished.
857 *
858 * Note we don't try to acquire the locks on the given locktags, only the VXIDs
859 * of its lock holders; if somebody grabs a conflicting lock on the objects
860 * after we obtained our initial list of lockers, we will not wait for them.
861 */
862void
863WaitForLockersMultiple(List *locktags, LOCKMODE lockmode, bool progress)
864{
865 List *holders = NIL;
866 ListCell *lc;
867 int total = 0;
868 int done = 0;
869
870 /* Done if no locks to wait for */
871 if (list_length(locktags) == 0)
872 return;
873
874 /* Collect the transactions we need to wait on */
875 foreach(lc, locktags)
876 {
877 LOCKTAG *locktag = lfirst(lc);
878 int count;
879
880 holders = lappend(holders,
881 GetLockConflicts(locktag, lockmode,
882 progress ? &count : NULL));
883 if (progress)
884 total += count;
885 }
886
887 if (progress)
888 pgstat_progress_update_param(PROGRESS_WAITFOR_TOTAL, total);
889
890 /*
891 * Note: GetLockConflicts() never reports our own xid, hence we need not
892 * check for that. Also, prepared xacts are not reported, which is fine
893 * since they certainly aren't going to do anything anymore.
894 */
895
896 /* Finally wait for each such transaction to complete */
897 foreach(lc, holders)
898 {
899 VirtualTransactionId *lockholders = lfirst(lc);
900
901 while (VirtualTransactionIdIsValid(*lockholders))
902 {
903 /*
904 * If requested, publish who we're going to wait for. This is not
905 * 100% accurate if they're already gone, but we don't care.
906 */
907 if (progress)
908 {
909 PGPROC *holder = BackendIdGetProc(lockholders->backendId);
910
911 pgstat_progress_update_param(PROGRESS_WAITFOR_CURRENT_PID,
912 holder->pid);
913 }
914 VirtualXactLock(*lockholders, true);
915 lockholders++;
916
917 if (progress)
918 pgstat_progress_update_param(PROGRESS_WAITFOR_DONE, ++done);
919 }
920 }
921 if (progress)
922 {
923 const int index[] = {
924 PROGRESS_WAITFOR_TOTAL,
925 PROGRESS_WAITFOR_DONE,
926 PROGRESS_WAITFOR_CURRENT_PID
927 };
928 const int64 values[] = {
929 0, 0, 0
930 };
931
932 pgstat_progress_update_multi_param(3, index, values);
933 }
934
935 list_free_deep(holders);
936}
937
938/*
939 * WaitForLockers
940 *
941 * Same as WaitForLockersMultiple, for a single lock tag.
942 */
943void
944WaitForLockers(LOCKTAG heaplocktag, LOCKMODE lockmode, bool progress)
945{
946 List *l;
947
948 l = list_make1(&heaplocktag);
949 WaitForLockersMultiple(l, lockmode, progress);
950 list_free(l);
951}
952
953
954/*
955 * LockDatabaseObject
956 *
957 * Obtain a lock on a general object of the current database. Don't use
958 * this for shared objects (such as tablespaces). It's unwise to apply it
959 * to relations, also, since a lock taken this way will NOT conflict with
960 * locks taken via LockRelation and friends.
961 */
962void
963LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid,
964 LOCKMODE lockmode)
965{
966 LOCKTAG tag;
967
968 SET_LOCKTAG_OBJECT(tag,
969 MyDatabaseId,
970 classid,
971 objid,
972 objsubid);
973
974 (void) LockAcquire(&tag, lockmode, false, false);
975
976 /* Make sure syscaches are up-to-date with any changes we waited for */
977 AcceptInvalidationMessages();
978}
979
980/*
981 * UnlockDatabaseObject
982 */
983void
984UnlockDatabaseObject(Oid classid, Oid objid, uint16 objsubid,
985 LOCKMODE lockmode)
986{
987 LOCKTAG tag;
988
989 SET_LOCKTAG_OBJECT(tag,
990 MyDatabaseId,
991 classid,
992 objid,
993 objsubid);
994
995 LockRelease(&tag, lockmode, false);
996}
997
998/*
999 * LockSharedObject
1000 *
1001 * Obtain a lock on a shared-across-databases object.
1002 */
1003void
1004LockSharedObject(Oid classid, Oid objid, uint16 objsubid,
1005 LOCKMODE lockmode)
1006{
1007 LOCKTAG tag;
1008
1009 SET_LOCKTAG_OBJECT(tag,
1010 InvalidOid,
1011 classid,
1012 objid,
1013 objsubid);
1014
1015 (void) LockAcquire(&tag, lockmode, false, false);
1016
1017 /* Make sure syscaches are up-to-date with any changes we waited for */
1018 AcceptInvalidationMessages();
1019}
1020
1021/*
1022 * UnlockSharedObject
1023 */
1024void
1025UnlockSharedObject(Oid classid, Oid objid, uint16 objsubid,
1026 LOCKMODE lockmode)
1027{
1028 LOCKTAG tag;
1029
1030 SET_LOCKTAG_OBJECT(tag,
1031 InvalidOid,
1032 classid,
1033 objid,
1034 objsubid);
1035
1036 LockRelease(&tag, lockmode, false);
1037}
1038
1039/*
1040 * LockSharedObjectForSession
1041 *
1042 * Obtain a session-level lock on a shared-across-databases object.
1043 * See LockRelationIdForSession for notes about session-level locks.
1044 */
1045void
1046LockSharedObjectForSession(Oid classid, Oid objid, uint16 objsubid,
1047 LOCKMODE lockmode)
1048{
1049 LOCKTAG tag;
1050
1051 SET_LOCKTAG_OBJECT(tag,
1052 InvalidOid,
1053 classid,
1054 objid,
1055 objsubid);
1056
1057 (void) LockAcquire(&tag, lockmode, true, false);
1058}
1059
1060/*
1061 * UnlockSharedObjectForSession
1062 */
1063void
1064UnlockSharedObjectForSession(Oid classid, Oid objid, uint16 objsubid,
1065 LOCKMODE lockmode)
1066{
1067 LOCKTAG tag;
1068
1069 SET_LOCKTAG_OBJECT(tag,
1070 InvalidOid,
1071 classid,
1072 objid,
1073 objsubid);
1074
1075 LockRelease(&tag, lockmode, true);
1076}
1077
1078
1079/*
1080 * Append a description of a lockable object to buf.
1081 *
1082 * Ideally we would print names for the numeric values, but that requires
1083 * getting locks on system tables, which might cause problems since this is
1084 * typically used to report deadlock situations.
1085 */
1086void
1087DescribeLockTag(StringInfo buf, const LOCKTAG *tag)
1088{
1089 switch ((LockTagType) tag->locktag_type)
1090 {
1091 case LOCKTAG_RELATION:
1092 appendStringInfo(buf,
1093 _("relation %u of database %u"),
1094 tag->locktag_field2,
1095 tag->locktag_field1);
1096 break;
1097 case LOCKTAG_RELATION_EXTEND:
1098 appendStringInfo(buf,
1099 _("extension of relation %u of database %u"),
1100 tag->locktag_field2,
1101 tag->locktag_field1);
1102 break;
1103 case LOCKTAG_PAGE:
1104 appendStringInfo(buf,
1105 _("page %u of relation %u of database %u"),
1106 tag->locktag_field3,
1107 tag->locktag_field2,
1108 tag->locktag_field1);
1109 break;
1110 case LOCKTAG_TUPLE:
1111 appendStringInfo(buf,
1112 _("tuple (%u,%u) of relation %u of database %u"),
1113 tag->locktag_field3,
1114 tag->locktag_field4,
1115 tag->locktag_field2,
1116 tag->locktag_field1);
1117 break;
1118 case LOCKTAG_TRANSACTION:
1119 appendStringInfo(buf,
1120 _("transaction %u"),
1121 tag->locktag_field1);
1122 break;
1123 case LOCKTAG_VIRTUALTRANSACTION:
1124 appendStringInfo(buf,
1125 _("virtual transaction %d/%u"),
1126 tag->locktag_field1,
1127 tag->locktag_field2);
1128 break;
1129 case LOCKTAG_SPECULATIVE_TOKEN:
1130 appendStringInfo(buf,
1131 _("speculative token %u of transaction %u"),
1132 tag->locktag_field2,
1133 tag->locktag_field1);
1134 break;
1135 case LOCKTAG_OBJECT:
1136 appendStringInfo(buf,
1137 _("object %u of class %u of database %u"),
1138 tag->locktag_field3,
1139 tag->locktag_field2,
1140 tag->locktag_field1);
1141 break;
1142 case LOCKTAG_USERLOCK:
1143 /* reserved for old contrib code, now on pgfoundry */
1144 appendStringInfo(buf,
1145 _("user lock [%u,%u,%u]"),
1146 tag->locktag_field1,
1147 tag->locktag_field2,
1148 tag->locktag_field3);
1149 break;
1150 case LOCKTAG_ADVISORY:
1151 appendStringInfo(buf,
1152 _("advisory lock [%u,%u,%u,%u]"),
1153 tag->locktag_field1,
1154 tag->locktag_field2,
1155 tag->locktag_field3,
1156 tag->locktag_field4);
1157 break;
1158 default:
1159 appendStringInfo(buf,
1160 _("unrecognized locktag type %d"),
1161 (int) tag->locktag_type);
1162 break;
1163 }
1164}
1165
1166/*
1167 * GetLockNameFromTagType
1168 *
1169 * Given locktag type, return the corresponding lock name.
1170 */
1171const char *
1172GetLockNameFromTagType(uint16 locktag_type)
1173{
1174 if (locktag_type > LOCKTAG_LAST_TYPE)
1175 return "???";
1176 return LockTagTypeNames[locktag_type];
1177}
1178