Skip to content

Commit aa64f23

Browse files
committed
Remove MaxBackends variable in favor of GetMaxBackends() function.
Previously, it was really easy to write code that accessed MaxBackends before we'd actually initialized it, especially when coding up an extension. To make this less error-prune, introduce a new function GetMaxBackends() which should be used to obtain the correct value. This will ERROR if called too early. Demote the global variable to a file-level static, so that nobody can peak at it directly. Nathan Bossart. Idea by Andres Freund. Review by Greg Sabino Mullane, by Michael Paquier (who had doubts about the approach), and by me. Discussion: http://postgr.es/m/20210802224204.bckcikl45uezv5e4@alap3.anarazel.de
1 parent 2da8961 commit aa64f23

File tree

19 files changed

+218
-133
lines changed

19 files changed

+218
-133
lines changed

src/backend/access/nbtree/nbtutils.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2072,7 +2072,7 @@ BTreeShmemSize(void)
20722072
Size size;
20732073

20742074
size = offsetof(BTVacInfo, vacuums);
2075-
size = add_size(size, mul_size(MaxBackends, sizeof(BTOneVacInfo)));
2075+
size = add_size(size, mul_size(GetMaxBackends(), sizeof(BTOneVacInfo)));
20762076
return size;
20772077
}
20782078

@@ -2101,7 +2101,7 @@ BTreeShmemInit(void)
21012101
btvacinfo->cycle_ctr = (BTCycleId) time(NULL);
21022102

21032103
btvacinfo->num_vacuums = 0;
2104-
btvacinfo->max_vacuums = MaxBackends;
2104+
btvacinfo->max_vacuums = GetMaxBackends();
21052105
}
21062106
else
21072107
Assert(found);

src/backend/access/transam/multixact.c

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -282,12 +282,11 @@ typedef struct MultiXactStateData
282282
} MultiXactStateData;
283283

284284
/*
285-
* Last element of OldestMemberMXactId and OldestVisibleMXactId arrays.
286-
* Valid elements are (1..MaxOldestSlot); element 0 is never used.
285+
* Pointers to the state data in shared memory
286+
*
287+
* The index of the last element of the OldestMemberMXactId and
288+
* OldestVisibleMXacId arrays can be obtained with GetMaxOldestSlot().
287289
*/
288-
#define MaxOldestSlot (MaxBackends + max_prepared_xacts)
289-
290-
/* Pointers to the state data in shared memory */
291290
static MultiXactStateData *MultiXactState;
292291
static MultiXactId *OldestMemberMXactId;
293292
static MultiXactId *OldestVisibleMXactId;
@@ -342,6 +341,7 @@ static void MultiXactIdSetOldestVisible(void);
342341
static void RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset,
343342
int nmembers, MultiXactMember *members);
344343
static MultiXactId GetNewMultiXactId(int nmembers, MultiXactOffset *offset);
344+
static inline int GetMaxOldestSlot(void);
345345

346346
/* MultiXact cache management */
347347
static int mxactMemberComparator(const void *arg1, const void *arg2);
@@ -662,6 +662,17 @@ MultiXactIdSetOldestMember(void)
662662
}
663663
}
664664

665+
/*
666+
* Retrieve the index of the last element of the OldestMemberMXactId and
667+
* OldestVisibleMXactId arrays. Valid elements are (1..MaxOldestSlot); element
668+
* 0 is never used.
669+
*/
670+
static inline int
671+
GetMaxOldestSlot(void)
672+
{
673+
return GetMaxBackends() + max_prepared_xacts;
674+
}
675+
665676
/*
666677
* MultiXactIdSetOldestVisible
667678
* Save the oldest MultiXactId this transaction considers possibly live.
@@ -684,6 +695,7 @@ MultiXactIdSetOldestVisible(void)
684695
if (!MultiXactIdIsValid(OldestVisibleMXactId[MyBackendId]))
685696
{
686697
MultiXactId oldestMXact;
698+
int maxOldestSlot = GetMaxOldestSlot();
687699
int i;
688700

689701
LWLockAcquire(MultiXactGenLock, LW_EXCLUSIVE);
@@ -697,7 +709,7 @@ MultiXactIdSetOldestVisible(void)
697709
if (oldestMXact < FirstMultiXactId)
698710
oldestMXact = FirstMultiXactId;
699711

700-
for (i = 1; i <= MaxOldestSlot; i++)
712+
for (i = 1; i <= maxOldestSlot; i++)
701713
{
702714
MultiXactId thisoldest = OldestMemberMXactId[i];
703715

@@ -1831,7 +1843,7 @@ MultiXactShmemSize(void)
18311843
/* We need 2*MaxOldestSlot + 1 perBackendXactIds[] entries */
18321844
#define SHARED_MULTIXACT_STATE_SIZE \
18331845
add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \
1834-
mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot))
1846+
mul_size(sizeof(MultiXactId) * 2, GetMaxOldestSlot()))
18351847

18361848
size = SHARED_MULTIXACT_STATE_SIZE;
18371849
size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTOFFSET_BUFFERS, 0));
@@ -1882,7 +1894,7 @@ MultiXactShmemInit(void)
18821894
* since we only use indexes 1..MaxOldestSlot in each array.
18831895
*/
18841896
OldestMemberMXactId = MultiXactState->perBackendXactIds;
1885-
OldestVisibleMXactId = OldestMemberMXactId + MaxOldestSlot;
1897+
OldestVisibleMXactId = OldestMemberMXactId + GetMaxOldestSlot();
18861898
}
18871899

18881900
/*
@@ -2507,6 +2519,7 @@ GetOldestMultiXactId(void)
25072519
{
25082520
MultiXactId oldestMXact;
25092521
MultiXactId nextMXact;
2522+
int maxOldestSlot = GetMaxOldestSlot();
25102523
int i;
25112524

25122525
/*
@@ -2525,7 +2538,7 @@ GetOldestMultiXactId(void)
25252538
nextMXact = FirstMultiXactId;
25262539

25272540
oldestMXact = nextMXact;
2528-
for (i = 1; i <= MaxOldestSlot; i++)
2541+
for (i = 1; i <= maxOldestSlot; i++)
25292542
{
25302543
MultiXactId thisoldest;
25312544

src/backend/access/transam/twophase.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ TwoPhaseShmemInit(void)
260260
{
261261
GlobalTransaction gxacts;
262262
int i;
263+
int max_backends = GetMaxBackends();
263264

264265
Assert(!found);
265266
TwoPhaseState->freeGXacts = NULL;
@@ -293,7 +294,7 @@ TwoPhaseShmemInit(void)
293294
* prepared transaction. Currently multixact.c uses that
294295
* technique.
295296
*/
296-
gxacts[i].dummyBackendId = MaxBackends + 1 + i;
297+
gxacts[i].dummyBackendId = max_backends + 1 + i;
297298
}
298299
}
299300
else

src/backend/commands/async.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ AsyncShmemSize(void)
518518
Size size;
519519

520520
/* This had better match AsyncShmemInit */
521-
size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus));
521+
size = mul_size(GetMaxBackends() + 1, sizeof(QueueBackendStatus));
522522
size = add_size(size, offsetof(AsyncQueueControl, backend));
523523

524524
size = add_size(size, SimpleLruShmemSize(NUM_NOTIFY_BUFFERS, 0));
@@ -534,14 +534,15 @@ AsyncShmemInit(void)
534534
{
535535
bool found;
536536
Size size;
537+
int max_backends = GetMaxBackends();
537538

538539
/*
539540
* Create or attach to the AsyncQueueControl structure.
540541
*
541542
* The used entries in the backend[] array run from 1 to MaxBackends; the
542543
* zero'th entry is unused but must be allocated.
543544
*/
544-
size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus));
545+
size = mul_size(max_backends + 1, sizeof(QueueBackendStatus));
545546
size = add_size(size, offsetof(AsyncQueueControl, backend));
546547

547548
asyncQueueControl = (AsyncQueueControl *)
@@ -556,7 +557,7 @@ AsyncShmemInit(void)
556557
QUEUE_FIRST_LISTENER = InvalidBackendId;
557558
asyncQueueControl->lastQueueFillWarn = 0;
558559
/* zero'th entry won't be used, but let's initialize it anyway */
559-
for (int i = 0; i <= MaxBackends; i++)
560+
for (int i = 0; i <= max_backends; i++)
560561
{
561562
QUEUE_BACKEND_PID(i) = InvalidPid;
562563
QUEUE_BACKEND_DBOID(i) = InvalidOid;
@@ -1641,8 +1642,8 @@ SignalBackends(void)
16411642
* XXX in principle these pallocs could fail, which would be bad. Maybe
16421643
* preallocate the arrays? They're not that large, though.
16431644
*/
1644-
pids = (int32 *) palloc(MaxBackends * sizeof(int32));
1645-
ids = (BackendId *) palloc(MaxBackends * sizeof(BackendId));
1645+
pids = (int32 *) palloc(GetMaxBackends() * sizeof(int32));
1646+
ids = (BackendId *) palloc(GetMaxBackends() * sizeof(BackendId));
16461647
count = 0;
16471648

16481649
LWLockAcquire(NotifyQueueLock, LW_EXCLUSIVE);

src/backend/libpq/pqcomm.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ StreamServerPort(int family, const char *hostName, unsigned short portNumber,
349349
struct addrinfo hint;
350350
int listen_index = 0;
351351
int added = 0;
352+
int max_backends = GetMaxBackends();
352353

353354
#ifdef HAVE_UNIX_SOCKETS
354355
char unixSocketPath[MAXPGPATH];
@@ -571,7 +572,7 @@ StreamServerPort(int family, const char *hostName, unsigned short portNumber,
571572
* intended to provide a clamp on the request on platforms where an
572573
* overly large request provokes a kernel error (are there any?).
573574
*/
574-
maxconn = MaxBackends * 2;
575+
maxconn = max_backends * 2;
575576
if (maxconn > PG_SOMAXCONN)
576577
maxconn = PG_SOMAXCONN;
577578

src/backend/postmaster/auxprocess.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ AuxiliaryProcessMain(AuxProcType auxtype)
116116
* This will need rethinking if we ever want more than one of a particular
117117
* auxiliary process type.
118118
*/
119-
ProcSignalInit(MaxBackends + MyAuxProcType + 1);
119+
ProcSignalInit(GetMaxBackends() + MyAuxProcType + 1);
120120

121121
/*
122122
* Auxiliary processes don't run transactions, but they may need a

src/backend/postmaster/postmaster.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6260,7 +6260,7 @@ save_backend_variables(BackendParameters *param, Port *port,
62606260
param->query_id_enabled = query_id_enabled;
62616261
param->max_safe_fds = max_safe_fds;
62626262

6263-
param->MaxBackends = MaxBackends;
6263+
param->MaxBackends = GetMaxBackends();
62646264

62656265
#ifdef WIN32
62666266
param->PostmasterHandle = PostmasterHandle;
@@ -6494,7 +6494,7 @@ restore_backend_variables(BackendParameters *param, Port *port)
64946494
query_id_enabled = param->query_id_enabled;
64956495
max_safe_fds = param->max_safe_fds;
64966496

6497-
MaxBackends = param->MaxBackends;
6497+
SetMaxBackends(param->MaxBackends);
64986498

64996499
#ifdef WIN32
65006500
PostmasterHandle = param->PostmasterHandle;

src/backend/storage/ipc/dsm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ dsm_postmaster_startup(PGShmemHeader *shim)
166166

167167
/* Determine size for new control segment. */
168168
maxitems = PG_DYNSHMEM_FIXED_SLOTS
169-
+ PG_DYNSHMEM_SLOTS_PER_BACKEND * MaxBackends;
169+
+ PG_DYNSHMEM_SLOTS_PER_BACKEND * GetMaxBackends();
170170
elog(DEBUG2, "dynamic shared memory system will support %u segments",
171171
maxitems);
172172
segsize = dsm_control_bytes_needed(maxitems);

src/backend/storage/ipc/procarray.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ typedef struct ProcArrayStruct
9797
/* oldest catalog xmin of any replication slot */
9898
TransactionId replication_slot_catalog_xmin;
9999

100-
/* indexes into allProcs[], has PROCARRAY_MAXPROCS entries */
100+
/* indexes into allProcs[], has ProcArrayMaxProcs entries */
101101
int pgprocnos[FLEXIBLE_ARRAY_MEMBER];
102102
} ProcArrayStruct;
103103

@@ -355,6 +355,17 @@ static void MaintainLatestCompletedXidRecovery(TransactionId latestXid);
355355
static inline FullTransactionId FullXidRelativeTo(FullTransactionId rel,
356356
TransactionId xid);
357357
static void GlobalVisUpdateApply(ComputeXidHorizonsResult *horizons);
358+
static inline int GetProcArrayMaxProcs(void);
359+
360+
361+
/*
362+
* Retrieve the number of slots in the ProcArray structure.
363+
*/
364+
static inline int
365+
GetProcArrayMaxProcs(void)
366+
{
367+
return GetMaxBackends() + max_prepared_xacts;
368+
}
358369

359370
/*
360371
* Report shared-memory space needed by CreateSharedProcArray.
@@ -365,10 +376,8 @@ ProcArrayShmemSize(void)
365376
Size size;
366377

367378
/* Size of the ProcArray structure itself */
368-
#define PROCARRAY_MAXPROCS (MaxBackends + max_prepared_xacts)
369-
370379
size = offsetof(ProcArrayStruct, pgprocnos);
371-
size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS));
380+
size = add_size(size, mul_size(sizeof(int), GetProcArrayMaxProcs()));
372381

373382
/*
374383
* During Hot Standby processing we have a data structure called
@@ -384,7 +393,7 @@ ProcArrayShmemSize(void)
384393
* shared memory is being set up.
385394
*/
386395
#define TOTAL_MAX_CACHED_SUBXIDS \
387-
((PGPROC_MAX_CACHED_SUBXIDS + 1) * PROCARRAY_MAXPROCS)
396+
((PGPROC_MAX_CACHED_SUBXIDS + 1) * GetProcArrayMaxProcs())
388397

389398
if (EnableHotStandby)
390399
{
@@ -411,7 +420,7 @@ CreateSharedProcArray(void)
411420
ShmemInitStruct("Proc Array",
412421
add_size(offsetof(ProcArrayStruct, pgprocnos),
413422
mul_size(sizeof(int),
414-
PROCARRAY_MAXPROCS)),
423+
GetProcArrayMaxProcs())),
415424
&found);
416425

417426
if (!found)
@@ -420,7 +429,7 @@ CreateSharedProcArray(void)
420429
* We're the first - initialize.
421430
*/
422431
procArray->numProcs = 0;
423-
procArray->maxProcs = PROCARRAY_MAXPROCS;
432+
procArray->maxProcs = GetProcArrayMaxProcs();
424433
procArray->maxKnownAssignedXids = TOTAL_MAX_CACHED_SUBXIDS;
425434
procArray->numKnownAssignedXids = 0;
426435
procArray->tailKnownAssignedXids = 0;
@@ -4623,7 +4632,7 @@ KnownAssignedXidsCompress(bool force)
46234632
*/
46244633
int nelements = head - tail;
46254634

4626-
if (nelements < 4 * PROCARRAY_MAXPROCS ||
4635+
if (nelements < 4 * GetProcArrayMaxProcs() ||
46274636
nelements < 2 * pArray->numKnownAssignedXids)
46284637
return;
46294638
}

0 commit comments

Comments
 (0)