Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 15732b3

Browse files
committed
Add WaitForLockers in lmgr, refactoring index.c code
This is in support of a future REINDEX CONCURRENTLY feature. Michael Paquier
1 parent dddc91d commit 15732b3

File tree

4 files changed

+81
-50
lines changed

4 files changed

+81
-50
lines changed

src/backend/catalog/index.c

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1323,7 +1323,6 @@ index_drop(Oid indexId, bool concurrent)
13231323
indexrelid;
13241324
LOCKTAG heaplocktag;
13251325
LOCKMODE lockmode;
1326-
VirtualTransactionId *old_lockholders;
13271326

13281327
/*
13291328
* To drop an index safely, we must grab exclusive lock on its parent
@@ -1445,30 +1444,17 @@ index_drop(Oid indexId, bool concurrent)
14451444

14461445
/*
14471446
* Now we must wait until no running transaction could be using the
1448-
* index for a query. To do this, inquire which xacts currently would
1449-
* conflict with AccessExclusiveLock on the table -- ie, which ones
1450-
* have a lock of any kind on the table. Then wait for each of these
1451-
* xacts to commit or abort. Note we do not need to worry about xacts
1452-
* that open the table for reading after this point; they will see the
1447+
* index for a query. Note we do not need to worry about xacts that
1448+
* open the table for reading after this point; they will see the
14531449
* index as invalid when they open the relation.
14541450
*
14551451
* Note: the reason we use actual lock acquisition here, rather than
14561452
* just checking the ProcArray and sleeping, is that deadlock is
14571453
* possible if one of the transactions in question is blocked trying
14581454
* to acquire an exclusive lock on our table. The lock code will
14591455
* detect deadlock and error out properly.
1460-
*
1461-
* Note: GetLockConflicts() never reports our own xid, hence we need
1462-
* not check for that. Also, prepared xacts are not reported, which
1463-
* is fine since they certainly aren't going to do anything more.
14641456
*/
1465-
old_lockholders = GetLockConflicts(&heaplocktag, AccessExclusiveLock);
1466-
1467-
while (VirtualTransactionIdIsValid(*old_lockholders))
1468-
{
1469-
VirtualXactLock(*old_lockholders, true);
1470-
old_lockholders++;
1471-
}
1457+
WaitForLockers(heaplocktag, AccessExclusiveLock);
14721458

14731459
/*
14741460
* No more predicate locks will be acquired on this index, and we're
@@ -1510,15 +1496,9 @@ index_drop(Oid indexId, bool concurrent)
15101496

15111497
/*
15121498
* Wait till every transaction that saw the old index state has
1513-
* finished. The logic here is the same as above.
1499+
* finished.
15141500
*/
1515-
old_lockholders = GetLockConflicts(&heaplocktag, AccessExclusiveLock);
1516-
1517-
while (VirtualTransactionIdIsValid(*old_lockholders))
1518-
{
1519-
VirtualXactLock(*old_lockholders, true);
1520-
old_lockholders++;
1521-
}
1501+
WaitForLockers(heaplocktag, AccessExclusiveLock);
15221502

15231503
/*
15241504
* Re-open relations to allow us to complete our actions.

src/backend/commands/indexcmds.c

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,6 @@ DefineIndex(IndexStmt *stmt,
321321
IndexInfo *indexInfo;
322322
int numberOfAttributes;
323323
TransactionId limitXmin;
324-
VirtualTransactionId *old_lockholders;
325324
VirtualTransactionId *old_snapshots;
326325
int n_old_snapshots;
327326
LockRelId heaprelid;
@@ -652,30 +651,17 @@ DefineIndex(IndexStmt *stmt,
652651
* for an overview of how this works)
653652
*
654653
* Now we must wait until no running transaction could have the table open
655-
* with the old list of indexes. To do this, inquire which xacts
656-
* currently would conflict with ShareLock on the table -- ie, which ones
657-
* have a lock that permits writing the table. Then wait for each of
658-
* these xacts to commit or abort. Note we do not need to worry about
659-
* xacts that open the table for writing after this point; they will see
660-
* the new index when they open it.
654+
* with the old list of indexes. Note we do not need to worry about xacts
655+
* that open the table for writing after this point; they will see the new
656+
* index when they open it.
661657
*
662658
* Note: the reason we use actual lock acquisition here, rather than just
663659
* checking the ProcArray and sleeping, is that deadlock is possible if
664660
* one of the transactions in question is blocked trying to acquire an
665661
* exclusive lock on our table. The lock code will detect deadlock and
666662
* error out properly.
667-
*
668-
* Note: GetLockConflicts() never reports our own xid, hence we need not
669-
* check for that. Also, prepared xacts are not reported, which is fine
670-
* since they certainly aren't going to do anything more.
671663
*/
672-
old_lockholders = GetLockConflicts(&heaplocktag, ShareLock);
673-
674-
while (VirtualTransactionIdIsValid(*old_lockholders))
675-
{
676-
VirtualXactLock(*old_lockholders, true);
677-
old_lockholders++;
678-
}
664+
WaitForLockers(heaplocktag, ShareLock);
679665

680666
/*
681667
* At this moment we are sure that there are no transactions with the
@@ -739,13 +725,7 @@ DefineIndex(IndexStmt *stmt,
739725
* We once again wait until no transaction can have the table open with
740726
* the index marked as read-only for updates.
741727
*/
742-
old_lockholders = GetLockConflicts(&heaplocktag, ShareLock);
743-
744-
while (VirtualTransactionIdIsValid(*old_lockholders))
745-
{
746-
VirtualXactLock(*old_lockholders, true);
747-
old_lockholders++;
748-
}
728+
WaitForLockers(heaplocktag, ShareLock);
749729

750730
/*
751731
* Now take the "reference snapshot" that will be used by validate_index()

src/backend/storage/lmgr/lmgr.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,73 @@ ConditionalXactLockTableWait(TransactionId xid)
533533
return true;
534534
}
535535

536+
/*
537+
* WaitForLockersMultiple
538+
* Wait until no transaction holds locks that conflict with the given
539+
* locktags at the given lockmode.
540+
*
541+
* To do this, obtain the current list of lockers, and wait on their VXIDs
542+
* until they are finished.
543+
*
544+
* Note we don't try to acquire the locks on the given locktags, only the VXIDs
545+
* of its lock holders; if somebody grabs a conflicting lock on the objects
546+
* after we obtained our initial list of lockers, we will not wait for them.
547+
*/
548+
void
549+
WaitForLockersMultiple(List *locktags, LOCKMODE lockmode)
550+
{
551+
List *holders = NIL;
552+
ListCell *lc;
553+
554+
/* Done if no locks to wait for */
555+
if (list_length(locktags) == 0)
556+
return;
557+
558+
/* Collect the transactions we need to wait on */
559+
foreach(lc, locktags)
560+
{
561+
LOCKTAG *locktag = lfirst(lc);
562+
563+
holders = lappend(holders, GetLockConflicts(locktag, lockmode));
564+
}
565+
566+
/*
567+
* Note: GetLockConflicts() never reports our own xid, hence we need not
568+
* check for that. Also, prepared xacts are not reported, which is fine
569+
* since they certainly aren't going to do anything anymore.
570+
*/
571+
572+
/* Finally wait for each such transaction to complete */
573+
foreach(lc, holders)
574+
{
575+
VirtualTransactionId *lockholders = lfirst(lc);
576+
577+
while (VirtualTransactionIdIsValid(*lockholders))
578+
{
579+
VirtualXactLock(*lockholders, true);
580+
lockholders++;
581+
}
582+
}
583+
584+
list_free_deep(holders);
585+
}
586+
587+
/*
588+
* WaitForLockers
589+
*
590+
* Same as WaitForLockersMultiple, for a single lock tag.
591+
*/
592+
void
593+
WaitForLockers(LOCKTAG heaplocktag, LOCKMODE lockmode)
594+
{
595+
List *l;
596+
597+
l = list_make1(&heaplocktag);
598+
WaitForLockersMultiple(l, lockmode);
599+
list_free(l);
600+
}
601+
602+
536603
/*
537604
* LockDatabaseObject
538605
*

src/include/storage/lmgr.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ extern void XactLockTableDelete(TransactionId xid);
5757
extern void XactLockTableWait(TransactionId xid);
5858
extern bool ConditionalXactLockTableWait(TransactionId xid);
5959

60+
/* Lock VXIDs, specified by conflicting locktags */
61+
extern void WaitForLockers(LOCKTAG heaplocktag, LOCKMODE lockmode);
62+
extern void WaitForLockersMultiple(List *locktags, LOCKMODE lockmode);
63+
6064
/* Lock a general object (other than a relation) of the current database */
6165
extern void LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid,
6266
LOCKMODE lockmode);

0 commit comments

Comments
 (0)