Skip to content

Commit d8e950d

Browse files
committed
Improve and cleanup ProcArrayAdd(), ProcArrayRemove().
941697c changed ProcArrayAdd()/Remove() substantially. As reported by zhanyi, I missed that due to the introduction of the PGPROC->pgxactoff ProcArrayRemove() does not need to search for the position in procArray->pgprocnos anymore - that's pgxactoff. Remove the search loop. The removal of the search loop reduces assertion coverage a bit - but we can easily do better than before by adding assertions to other loops over pgprocnos elements. Also do a bit of cleanup, mostly by reducing line lengths by introducing local helper variables and adding newlines. Author: zhanyi <w@hidva.com> Author: Andres Freund <andres@anarazel.de> Discussion: https://postgr.es/m/tencent_5624AA3B116B3D1C31CA9744@qq.com
1 parent d120e66 commit d8e950d

File tree

1 file changed

+78
-55
lines changed

1 file changed

+78
-55
lines changed

src/backend/storage/ipc/procarray.c

Lines changed: 78 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ ProcArrayAdd(PGPROC *proc)
446446
{
447447
ProcArrayStruct *arrayP = procArray;
448448
int index;
449+
int movecount;
449450

450451
/* See ProcGlobal comment explaining why both locks are held */
451452
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
@@ -474,33 +475,48 @@ ProcArrayAdd(PGPROC *proc)
474475
*/
475476
for (index = 0; index < arrayP->numProcs; index++)
476477
{
477-
/*
478-
* If we are the first PGPROC or if we have found our right position
479-
* in the array, break
480-
*/
481-
if ((arrayP->pgprocnos[index] == -1) || (arrayP->pgprocnos[index] > proc->pgprocno))
478+
int procno PG_USED_FOR_ASSERTS_ONLY = arrayP->pgprocnos[index];
479+
480+
Assert(procno >= 0 && procno < (arrayP->maxProcs + NUM_AUXILIARY_PROCS));
481+
Assert(allProcs[procno].pgxactoff == index);
482+
483+
/* If we have found our right position in the array, break */
484+
if (arrayP->pgprocnos[index] > proc->pgprocno)
482485
break;
483486
}
484487

485-
memmove(&arrayP->pgprocnos[index + 1], &arrayP->pgprocnos[index],
486-
(arrayP->numProcs - index) * sizeof(*arrayP->pgprocnos));
487-
memmove(&ProcGlobal->xids[index + 1], &ProcGlobal->xids[index],
488-
(arrayP->numProcs - index) * sizeof(*ProcGlobal->xids));
489-
memmove(&ProcGlobal->subxidStates[index + 1], &ProcGlobal->subxidStates[index],
490-
(arrayP->numProcs - index) * sizeof(*ProcGlobal->subxidStates));
491-
memmove(&ProcGlobal->statusFlags[index + 1], &ProcGlobal->statusFlags[index],
492-
(arrayP->numProcs - index) * sizeof(*ProcGlobal->statusFlags));
488+
movecount = arrayP->numProcs - index;
489+
memmove(&arrayP->pgprocnos[index + 1],
490+
&arrayP->pgprocnos[index],
491+
movecount * sizeof(*arrayP->pgprocnos));
492+
memmove(&ProcGlobal->xids[index + 1],
493+
&ProcGlobal->xids[index],
494+
movecount * sizeof(*ProcGlobal->xids));
495+
memmove(&ProcGlobal->subxidStates[index + 1],
496+
&ProcGlobal->subxidStates[index],
497+
movecount * sizeof(*ProcGlobal->subxidStates));
498+
memmove(&ProcGlobal->statusFlags[index + 1],
499+
&ProcGlobal->statusFlags[index],
500+
movecount * sizeof(*ProcGlobal->statusFlags));
493501

494502
arrayP->pgprocnos[index] = proc->pgprocno;
503+
proc->pgxactoff = index;
495504
ProcGlobal->xids[index] = proc->xid;
496505
ProcGlobal->subxidStates[index] = proc->subxidStatus;
497506
ProcGlobal->statusFlags[index] = proc->statusFlags;
498507

499508
arrayP->numProcs++;
500509

510+
/* adjust pgxactoff for all following PGPROCs */
511+
index++;
501512
for (; index < arrayP->numProcs; index++)
502513
{
503-
allProcs[arrayP->pgprocnos[index]].pgxactoff = index;
514+
int procno = arrayP->pgprocnos[index];
515+
516+
Assert(procno >= 0 && procno < (arrayP->maxProcs + NUM_AUXILIARY_PROCS));
517+
Assert(allProcs[procno].pgxactoff == index - 1);
518+
519+
allProcs[procno].pgxactoff = index;
504520
}
505521

506522
/*
@@ -525,7 +541,8 @@ void
525541
ProcArrayRemove(PGPROC *proc, TransactionId latestXid)
526542
{
527543
ProcArrayStruct *arrayP = procArray;
528-
int index;
544+
int myoff;
545+
int movecount;
529546

530547
#ifdef XIDCACHE_DEBUG
531548
/* dump stats at backend shutdown, but not prepared-xact end */
@@ -537,69 +554,75 @@ ProcArrayRemove(PGPROC *proc, TransactionId latestXid)
537554
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
538555
LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
539556

540-
Assert(ProcGlobal->allProcs[arrayP->pgprocnos[proc->pgxactoff]].pgxactoff == proc->pgxactoff);
557+
myoff = proc->pgxactoff;
558+
559+
Assert(myoff >= 0 && myoff < arrayP->numProcs);
560+
Assert(ProcGlobal->allProcs[arrayP->pgprocnos[myoff]].pgxactoff == myoff);
541561

542562
if (TransactionIdIsValid(latestXid))
543563
{
544-
Assert(TransactionIdIsValid(ProcGlobal->xids[proc->pgxactoff]));
564+
Assert(TransactionIdIsValid(ProcGlobal->xids[myoff]));
545565

546566
/* Advance global latestCompletedXid while holding the lock */
547567
MaintainLatestCompletedXid(latestXid);
548568

549569
/* Same with xactCompletionCount */
550570
ShmemVariableCache->xactCompletionCount++;
551571

552-
ProcGlobal->xids[proc->pgxactoff] = 0;
553-
ProcGlobal->subxidStates[proc->pgxactoff].overflowed = false;
554-
ProcGlobal->subxidStates[proc->pgxactoff].count = 0;
572+
ProcGlobal->xids[myoff] = InvalidTransactionId;
573+
ProcGlobal->subxidStates[myoff].overflowed = false;
574+
ProcGlobal->subxidStates[myoff].count = 0;
555575
}
556576
else
557577
{
558578
/* Shouldn't be trying to remove a live transaction here */
559-
Assert(!TransactionIdIsValid(ProcGlobal->xids[proc->pgxactoff]));
579+
Assert(!TransactionIdIsValid(ProcGlobal->xids[myoff]));
560580
}
561581

562-
Assert(TransactionIdIsValid(ProcGlobal->xids[proc->pgxactoff] == 0));
563-
Assert(TransactionIdIsValid(ProcGlobal->subxidStates[proc->pgxactoff].count == 0));
564-
Assert(TransactionIdIsValid(ProcGlobal->subxidStates[proc->pgxactoff].overflowed == false));
565-
ProcGlobal->statusFlags[proc->pgxactoff] = 0;
582+
Assert(!TransactionIdIsValid(ProcGlobal->xids[myoff]));
583+
Assert(ProcGlobal->subxidStates[myoff].count == 0);
584+
Assert(ProcGlobal->subxidStates[myoff].overflowed == false);
585+
586+
ProcGlobal->statusFlags[myoff] = 0;
587+
588+
/* Keep the PGPROC array sorted. See notes above */
589+
movecount = arrayP->numProcs - myoff - 1;
590+
memmove(&arrayP->pgprocnos[myoff],
591+
&arrayP->pgprocnos[myoff + 1],
592+
movecount * sizeof(*arrayP->pgprocnos));
593+
memmove(&ProcGlobal->xids[myoff],
594+
&ProcGlobal->xids[myoff + 1],
595+
movecount * sizeof(*ProcGlobal->xids));
596+
memmove(&ProcGlobal->subxidStates[myoff],
597+
&ProcGlobal->subxidStates[myoff + 1],
598+
movecount * sizeof(*ProcGlobal->subxidStates));
599+
memmove(&ProcGlobal->statusFlags[myoff],
600+
&ProcGlobal->statusFlags[myoff + 1],
601+
movecount * sizeof(*ProcGlobal->statusFlags));
602+
603+
arrayP->pgprocnos[arrayP->numProcs - 1] = -1; /* for debugging */
604+
arrayP->numProcs--;
566605

567-
for (index = 0; index < arrayP->numProcs; index++)
606+
/*
607+
* Adjust pgxactoff of following procs for removed PGPROC (note that
608+
* numProcs already has been decremented).
609+
*/
610+
for (int index = myoff; index < arrayP->numProcs; index++)
568611
{
569-
if (arrayP->pgprocnos[index] == proc->pgprocno)
570-
{
571-
/* Keep the PGPROC array sorted. See notes above */
572-
memmove(&arrayP->pgprocnos[index], &arrayP->pgprocnos[index + 1],
573-
(arrayP->numProcs - index - 1) * sizeof(*arrayP->pgprocnos));
574-
memmove(&ProcGlobal->xids[index], &ProcGlobal->xids[index + 1],
575-
(arrayP->numProcs - index - 1) * sizeof(*ProcGlobal->xids));
576-
memmove(&ProcGlobal->subxidStates[index], &ProcGlobal->subxidStates[index + 1],
577-
(arrayP->numProcs - index - 1) * sizeof(*ProcGlobal->subxidStates));
578-
memmove(&ProcGlobal->statusFlags[index], &ProcGlobal->statusFlags[index + 1],
579-
(arrayP->numProcs - index - 1) * sizeof(*ProcGlobal->statusFlags));
580-
581-
arrayP->pgprocnos[arrayP->numProcs - 1] = -1; /* for debugging */
582-
arrayP->numProcs--;
583-
584-
/* adjust for removed PGPROC */
585-
for (; index < arrayP->numProcs; index++)
586-
allProcs[arrayP->pgprocnos[index]].pgxactoff--;
612+
int procno = arrayP->pgprocnos[index];
587613

588-
/*
589-
* Release in reversed acquisition order, to reduce frequency of
590-
* having to wait for XidGenLock while holding ProcArrayLock.
591-
*/
592-
LWLockRelease(XidGenLock);
593-
LWLockRelease(ProcArrayLock);
594-
return;
595-
}
614+
Assert(procno >= 0 && procno < (arrayP->maxProcs + NUM_AUXILIARY_PROCS));
615+
Assert(allProcs[procno].pgxactoff - 1 == index);
616+
617+
allProcs[procno].pgxactoff = index;
596618
}
597619

598-
/* Oops */
620+
/*
621+
* Release in reversed acquisition order, to reduce frequency of having to
622+
* wait for XidGenLock while holding ProcArrayLock.
623+
*/
599624
LWLockRelease(XidGenLock);
600625
LWLockRelease(ProcArrayLock);
601-
602-
elog(LOG, "failed to find proc %p in ProcArray", proc);
603626
}
604627

605628

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy