1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-25 12:03:53 +03:00

Replace BackendIds with 0-based ProcNumbers

Now that BackendId was just another index into the proc array, it was
redundant with the 0-based proc numbers used in other places. Replace
all usage of backend IDs with proc numbers.

The only place where the term "backend id" remains is in a few pgstat
functions that expose backend IDs at the SQL level. Those IDs are now
in fact 0-based ProcNumbers too, but the documentation still calls
them "backend ids". That term still seems appropriate to describe what
the numbers are, so I let it be.

One user-visible effect is that pg_temp_0 is now a valid temp schema
name, for backend with ProcNumber 0.

Reviewed-by: Andres Freund
Discussion: https://www.postgresql.org/message-id/8171f1aa-496f-46a6-afc3-c46fe7a9b407@iki.fi
This commit is contained in:
Heikki Linnakangas
2024-03-03 19:38:22 +02:00
parent ab355e3a88
commit 024c521117
71 changed files with 571 additions and 579 deletions

View File

@@ -1,41 +0,0 @@
/*-------------------------------------------------------------------------
*
* backendid.h
* POSTGRES backend id communication definitions
*
*
* Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/storage/backendid.h
*
*-------------------------------------------------------------------------
*/
#ifndef BACKENDID_H
#define BACKENDID_H
/*
* BackendId uniquely identifies an active backend or auxiliary process. It's
* assigned at backend startup after authentication. Note that a backend ID
* can be reused for a different backend immediately after a backend exits.
*
* Backend IDs are assigned starting from 1. For historical reasons, BackendId
* 0 is unused, but InvalidBackendId is defined as -1.
*/
typedef int BackendId;
#define InvalidBackendId (-1)
extern PGDLLIMPORT BackendId MyBackendId; /* backend id of this backend */
/* backend id of our parallel session leader, or InvalidBackendId if none */
extern PGDLLIMPORT BackendId ParallelLeaderBackendId;
/*
* The BackendId to use for our session's temp relations is normally our own,
* but parallel workers should use their leader's ID.
*/
#define BackendIdForTempRelations() \
(ParallelLeaderBackendId == InvalidBackendId ? MyBackendId : ParallelLeaderBackendId)
#endif /* BACKENDID_H */

View File

@@ -19,9 +19,9 @@
#endif
#include "lib/ilist.h"
#include "storage/backendid.h"
#include "storage/lockdefs.h"
#include "storage/lwlock.h"
#include "storage/procnumber.h"
#include "storage/shmem.h"
#include "utils/timestamp.h"
@@ -42,7 +42,7 @@ extern PGDLLIMPORT bool Debug_deadlocks;
/*
* Top-level transactions are identified by VirtualTransactionIDs comprising
* PGPROC fields backendId and lxid. For recovered prepared transactions, the
* PGPROC fields procNumber and lxid. For recovered prepared transactions, the
* LocalTransactionId is an ordinary XID; LOCKTAG_VIRTUALTRANSACTION never
* refers to that kind. These are guaranteed unique over the short term, but
* will be reused after a database restart or XID wraparound; hence they
@@ -50,7 +50,7 @@ extern PGDLLIMPORT bool Debug_deadlocks;
*
* Note that struct VirtualTransactionId can not be assumed to be atomically
* assignable as a whole. However, type LocalTransactionId is assumed to
* be atomically assignable, and the backend ID doesn't change often enough
* be atomically assignable, and the proc number doesn't change often enough
* to be a problem, so we can fetch or assign the two fields separately.
* We deliberately refrain from using the struct within PGPROC, to prevent
* coding errors from trying to use struct assignment with it; instead use
@@ -58,7 +58,7 @@ extern PGDLLIMPORT bool Debug_deadlocks;
*/
typedef struct
{
BackendId backendId; /* backendId from PGPROC */
ProcNumber procNumber; /* proc number of the PGPROC */
LocalTransactionId localTransactionId; /* lxid from PGPROC */
} VirtualTransactionId;
@@ -67,15 +67,15 @@ typedef struct
#define VirtualTransactionIdIsValid(vxid) \
(LocalTransactionIdIsValid((vxid).localTransactionId))
#define VirtualTransactionIdIsRecoveredPreparedXact(vxid) \
((vxid).backendId == InvalidBackendId)
((vxid).procNumber == INVALID_PROC_NUMBER)
#define VirtualTransactionIdEquals(vxid1, vxid2) \
((vxid1).backendId == (vxid2).backendId && \
((vxid1).procNumber == (vxid2).procNumber && \
(vxid1).localTransactionId == (vxid2).localTransactionId)
#define SetInvalidVirtualTransactionId(vxid) \
((vxid).backendId = InvalidBackendId, \
((vxid).procNumber = INVALID_PROC_NUMBER, \
(vxid).localTransactionId = InvalidLocalTransactionId)
#define GET_VXID_FROM_PGPROC(vxid_dst, proc) \
((vxid_dst).backendId = (proc).vxid.backendId, \
((vxid_dst).procNumber = (proc).vxid.procNumber, \
(vxid_dst).localTransactionId = (proc).vxid.lxid)
/* MAX_LOCKMODES cannot be larger than the # of bits in LOCKMASK */
@@ -233,7 +233,7 @@ typedef struct LOCKTAG
/* ID info for a virtual transaction is its VirtualTransactionId */
#define SET_LOCKTAG_VIRTUALTRANSACTION(locktag,vxid) \
((locktag).locktag_field1 = (vxid).backendId, \
((locktag).locktag_field1 = (vxid).procNumber, \
(locktag).locktag_field2 = (vxid).localTransactionId, \
(locktag).locktag_field3 = 0, \
(locktag).locktag_field4 = 0, \

View File

@@ -21,6 +21,7 @@
#include "storage/lock.h"
#include "storage/pg_sema.h"
#include "storage/proclist_types.h"
#include "storage/procnumber.h"
/*
* Each backend advertises up to PGPROC_MAX_CACHED_SUBXIDS TransactionIds
@@ -84,12 +85,6 @@ struct XidCache
*/
#define FP_LOCK_SLOTS_PER_BACKEND 16
/*
* An invalid pgprocno. Must be larger than the maximum number of PGPROC
* structures we could possibly have. See comments for MAX_BACKENDS.
*/
#define INVALID_PGPROCNO PG_INT32_MAX
/*
* Flags for PGPROC.delayChkptFlags
*
@@ -199,11 +194,11 @@ struct PGPROC
*/
struct
{
BackendId backendId; /* For regular backends, equal to
* GetBackendIdFromPGProc(proc). For prepared
ProcNumber procNumber; /* For regular backends, equal to
* GetNumberFromPGProc(proc). For prepared
* xacts, ID of the original backend that
* processed the transaction. For unused
* PGPROC entries, InvalidBackendID. */
* PGPROC entries, INVALID_PROC_NUMBER. */
LocalTransactionId lxid; /* local id of top-level transaction
* currently * being executed by this
* proc, if running; else
@@ -317,7 +312,19 @@ struct PGPROC
extern PGDLLIMPORT PGPROC *MyProc;
extern PGDLLIMPORT int MyProcNumber; /* same as GetNumberFromPGProc(MyProc) */
/* Proc number of this backend. Equal to GetNumberFromPGProc(MyProc). */
extern PGDLLIMPORT ProcNumber MyProcNumber;
/* Our parallel session leader, or INVALID_PROC_NUMBER if none */
extern PGDLLIMPORT ProcNumber ParallelLeaderProcNumber;
/*
* The proc number to use for our session's temp relations is normally our own,
* but parallel workers should use their leader's ID.
*/
#define ProcNumberForTempRelations() \
(ParallelLeaderProcNumber == INVALID_PROC_NUMBER ? MyProcNumber : ParallelLeaderProcNumber)
/*
* There is one ProcGlobal struct for the whole database cluster.
@@ -422,15 +429,10 @@ extern PGDLLIMPORT PROC_HDR *ProcGlobal;
extern PGDLLIMPORT PGPROC *PreparedXactProcs;
/*
* Accessors for getting PGPROC given a pgprocno or BackendId, and vice versa.
*
* For historical reasons, some code uses 0-based "proc numbers", while other
* code uses 1-based backend IDs.
* Accessors for getting PGPROC given a ProcNumber and vice versa.
*/
#define GetPGProcByNumber(n) (&ProcGlobal->allProcs[(n)])
#define GetNumberFromPGProc(proc) ((proc) - &ProcGlobal->allProcs[0])
#define GetPGProcByBackendId(n) (&ProcGlobal->allProcs[(n) - 1])
#define GetBackendIdFromPGProc(proc) (GetNumberFromPGProc(proc) + 1)
/*
* We set aside some extra PGPROC structures for auxiliary processes,
@@ -477,7 +479,7 @@ extern bool IsWaitingForLock(void);
extern void LockErrorCleanup(void);
extern void ProcWaitForSignal(uint32 wait_event_info);
extern void ProcSendSignal(int pgprocno);
extern void ProcSendSignal(ProcNumber procNumber);
extern PGPROC *AuxiliaryPidGetProc(int pid);

View File

@@ -64,10 +64,10 @@ extern VirtualTransactionId *GetVirtualXIDsDelayingChkpt(int *nvxids, int type);
extern bool HaveVirtualXIDsDelayingChkpt(VirtualTransactionId *vxids,
int nvxids, int type);
extern PGPROC *BackendIdGetProc(int backendID);
extern void BackendIdGetTransactionIds(int backendID, TransactionId *xid,
TransactionId *xmin, int *nsubxid,
bool *overflowed);
extern PGPROC *ProcNumberGetProc(int procNumber);
extern void ProcNumberGetTransactionIds(int procNumber, TransactionId *xid,
TransactionId *xmin, int *nsubxid,
bool *overflowed);
extern PGPROC *BackendPidGetProc(int pid);
extern PGPROC *BackendPidGetProcWithLock(int pid);
extern int BackendXidGetPid(TransactionId xid);

View File

@@ -28,7 +28,7 @@
static inline void
proclist_init(proclist_head *list)
{
list->head = list->tail = INVALID_PGPROCNO;
list->head = list->tail = INVALID_PROC_NUMBER;
}
/*
@@ -37,7 +37,7 @@ proclist_init(proclist_head *list)
static inline bool
proclist_is_empty(const proclist_head *list)
{
return list->head == INVALID_PGPROCNO;
return list->head == INVALID_PROC_NUMBER;
}
/*
@@ -62,20 +62,20 @@ proclist_push_head_offset(proclist_head *list, int procno, size_t node_offset)
Assert(node->next == 0 && node->prev == 0);
if (list->head == INVALID_PGPROCNO)
if (list->head == INVALID_PROC_NUMBER)
{
Assert(list->tail == INVALID_PGPROCNO);
node->next = node->prev = INVALID_PGPROCNO;
Assert(list->tail == INVALID_PROC_NUMBER);
node->next = node->prev = INVALID_PROC_NUMBER;
list->head = list->tail = procno;
}
else
{
Assert(list->tail != INVALID_PGPROCNO);
Assert(list->tail != INVALID_PROC_NUMBER);
Assert(list->head != procno);
Assert(list->tail != procno);
node->next = list->head;
proclist_node_get(node->next, node_offset)->prev = procno;
node->prev = INVALID_PGPROCNO;
node->prev = INVALID_PROC_NUMBER;
list->head = procno;
}
}
@@ -90,20 +90,20 @@ proclist_push_tail_offset(proclist_head *list, int procno, size_t node_offset)
Assert(node->next == 0 && node->prev == 0);
if (list->tail == INVALID_PGPROCNO)
if (list->tail == INVALID_PROC_NUMBER)
{
Assert(list->head == INVALID_PGPROCNO);
node->next = node->prev = INVALID_PGPROCNO;
Assert(list->head == INVALID_PROC_NUMBER);
node->next = node->prev = INVALID_PROC_NUMBER;
list->head = list->tail = procno;
}
else
{
Assert(list->head != INVALID_PGPROCNO);
Assert(list->head != INVALID_PROC_NUMBER);
Assert(list->head != procno);
Assert(list->tail != procno);
node->prev = list->tail;
proclist_node_get(node->prev, node_offset)->next = procno;
node->next = INVALID_PGPROCNO;
node->next = INVALID_PROC_NUMBER;
list->tail = procno;
}
}
@@ -118,7 +118,7 @@ proclist_delete_offset(proclist_head *list, int procno, size_t node_offset)
Assert(node->next != 0 || node->prev != 0);
if (node->prev == INVALID_PGPROCNO)
if (node->prev == INVALID_PROC_NUMBER)
{
Assert(list->head == procno);
list->head = node->next;
@@ -126,7 +126,7 @@ proclist_delete_offset(proclist_head *list, int procno, size_t node_offset)
else
proclist_node_get(node->prev, node_offset)->next = node->next;
if (node->next == INVALID_PGPROCNO)
if (node->next == INVALID_PROC_NUMBER)
{
Assert(list->tail == procno);
list->tail = node->prev;
@@ -160,8 +160,8 @@ proclist_contains_offset(const proclist_head *list, int procno,
* tail, and that seems worth doing, since in practice that should often
* be enough to catch mistakes.
*/
Assert(node->prev != INVALID_PGPROCNO || list->head == procno);
Assert(node->next != INVALID_PGPROCNO || list->tail == procno);
Assert(node->prev != INVALID_PROC_NUMBER || list->head == procno);
Assert(node->next != INVALID_PROC_NUMBER || list->tail == procno);
return true;
}
@@ -207,12 +207,12 @@ proclist_pop_head_node_offset(proclist_head *list, size_t node_offset)
for (AssertVariableIsOfTypeMacro(iter, proclist_mutable_iter), \
AssertVariableIsOfTypeMacro(lhead, proclist_head *), \
(iter).cur = (lhead)->head, \
(iter).next = (iter).cur == INVALID_PGPROCNO ? INVALID_PGPROCNO : \
(iter).next = (iter).cur == INVALID_PROC_NUMBER ? INVALID_PROC_NUMBER : \
proclist_node_get((iter).cur, \
offsetof(PGPROC, link_member))->next; \
(iter).cur != INVALID_PGPROCNO; \
(iter).cur != INVALID_PROC_NUMBER; \
(iter).cur = (iter).next, \
(iter).next = (iter).cur == INVALID_PGPROCNO ? INVALID_PGPROCNO : \
(iter).next = (iter).cur == INVALID_PROC_NUMBER ? INVALID_PROC_NUMBER : \
proclist_node_get((iter).cur, \
offsetof(PGPROC, link_member))->next)

View File

@@ -15,28 +15,30 @@
#ifndef PROCLIST_TYPES_H
#define PROCLIST_TYPES_H
#include "storage/procnumber.h"
/*
* A node in a doubly-linked list of processes. The link fields contain
* the 0-based PGPROC indexes of the next and previous process, or
* INVALID_PGPROCNO in the next-link of the last node and the prev-link
* INVALID_PROC_NUMBER in the next-link of the last node and the prev-link
* of the first node. A node that is currently not in any list
* should have next == prev == 0; this is not a possible state for a node
* that is in a list, because we disallow circularity.
*/
typedef struct proclist_node
{
int next; /* pgprocno of the next PGPROC */
int prev; /* pgprocno of the prev PGPROC */
ProcNumber next; /* pgprocno of the next PGPROC */
ProcNumber prev; /* pgprocno of the prev PGPROC */
} proclist_node;
/*
* Header of a doubly-linked list of PGPROCs, identified by pgprocno.
* An empty list is represented by head == tail == INVALID_PGPROCNO.
* An empty list is represented by head == tail == INVALID_PROC_NUMBER.
*/
typedef struct proclist_head
{
int head; /* pgprocno of the head PGPROC */
int tail; /* pgprocno of the tail PGPROC */
ProcNumber head; /* pgprocno of the head PGPROC */
ProcNumber tail; /* pgprocno of the tail PGPROC */
} proclist_head;
/*
@@ -44,8 +46,8 @@ typedef struct proclist_head
*/
typedef struct proclist_mutable_iter
{
int cur; /* pgprocno of the current PGPROC */
int next; /* pgprocno of the next PGPROC */
ProcNumber cur; /* pgprocno of the current PGPROC */
ProcNumber next; /* pgprocno of the next PGPROC */
} proclist_mutable_iter;
#endif /* PROCLIST_TYPES_H */

View File

@@ -0,0 +1,43 @@
/*-------------------------------------------------------------------------
*
* procnumber.h
* definition of process number
*
*
* Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/storage/procnumber.h
*
*-------------------------------------------------------------------------
*/
#ifndef PROCNUMBER_H
#define PROCNUMBER_H
/*
* ProcNumber uniquely identifies an active backend or auxiliary process.
* It's assigned at backend startup after authentication, when the process
* adds itself to the proc array. It is an index into the proc array,
* starting from 0. Note that a ProcNumber can be reused for a different
* backend immediately after a backend exits.
*/
typedef int ProcNumber;
#define INVALID_PROC_NUMBER (-1)
/*
* Proc number of this backend (same as GetNumberFromPGProc(MyProc))
*/
extern PGDLLIMPORT ProcNumber MyProcNumber;
/* proc number of our parallel session leader, or INVALID_PROC_NUMBER if none */
extern PGDLLIMPORT ProcNumber ParallelLeaderProcNumber;
/*
* The ProcNumber to use for our session's temp relations is normally our own,
* but parallel workers should use their leader's proc number.
*/
#define ProcNumberForTempRelations() \
(ParallelLeaderProcNumber == INVALID_PROC_NUMBER ? MyProcNumber : ParallelLeaderProcNumber)
#endif /* PROCNUMBER_H */

View File

@@ -14,7 +14,7 @@
#ifndef PROCSIGNAL_H
#define PROCSIGNAL_H
#include "storage/backendid.h"
#include "storage/procnumber.h"
/*
@@ -64,7 +64,7 @@ extern void ProcSignalShmemInit(void);
extern void ProcSignalInit(void);
extern int SendProcSignal(pid_t pid, ProcSignalReason reason,
BackendId backendId);
ProcNumber procNumber);
extern uint64 EmitProcSignalBarrier(ProcSignalBarrierType type);
extern void WaitForProcSignalBarrier(uint64 generation);

View File

@@ -15,14 +15,15 @@
#define RELFILELOCATOR_H
#include "common/relpath.h"
#include "storage/backendid.h"
#include "storage/procnumber.h"
/*
* RelFileLocator must provide all that we need to know to physically access
* a relation, with the exception of the backend ID, which can be provided
* separately. Note, however, that a "physical" relation is comprised of
* multiple files on the filesystem, as each fork is stored as a separate
* file, and each fork can be divided into multiple segments. See md.c.
* a relation, with the exception of the backend's proc number, which can be
* provided separately. Note, however, that a "physical" relation is
* comprised of multiple files on the filesystem, as each fork is stored as
* a separate file, and each fork can be divided into multiple segments. See
* md.c.
*
* spcOid identifies the tablespace of the relation. It corresponds to
* pg_tablespace.oid.
@@ -62,28 +63,28 @@ typedef struct RelFileLocator
} RelFileLocator;
/*
* Augmenting a relfilelocator with the backend ID provides all the information
* we need to locate the physical storage. The backend ID is InvalidBackendId
* for regular relations (those accessible to more than one backend), or the
* owning backend's ID for backend-local relations. Backend-local relations
* are always transient and removed in case of a database crash; they are
* never WAL-logged or fsync'd.
* Augmenting a relfilelocator with the backend's proc number provides all the
* information we need to locate the physical storage. 'backend' is
* INVALID_PROC_NUMBER for regular relations (those accessible to more than
* one backend), or the owning backend's proc number for backend-local
* relations. Backend-local relations are always transient and removed in
* case of a database crash; they are never WAL-logged or fsync'd.
*/
typedef struct RelFileLocatorBackend
{
RelFileLocator locator;
BackendId backend;
ProcNumber backend;
} RelFileLocatorBackend;
#define RelFileLocatorBackendIsTemp(rlocator) \
((rlocator).backend != InvalidBackendId)
((rlocator).backend != INVALID_PROC_NUMBER)
/*
* Note: RelFileLocatorEquals and RelFileLocatorBackendEquals compare relNumber
* first since that is most likely to be different in two unequal
* RelFileLocators. It is probably redundant to compare spcOid if the other
* fields are found equal, but do it anyway to be sure. Likewise for checking
* the backend ID in RelFileLocatorBackendEquals.
* the backend number in RelFileLocatorBackendEquals.
*/
#define RelFileLocatorEquals(locator1, locator2) \
((locator1).relNumber == (locator2).relNumber && \

View File

@@ -88,8 +88,8 @@ typedef struct
{
/* note: field layout chosen to pack into 16 bytes */
int8 id; /* type field --- must be first */
int8 backend_hi; /* high bits of backend ID, if temprel */
uint16 backend_lo; /* low bits of backend ID, if temprel */
int8 backend_hi; /* high bits of backend procno, if temprel */
uint16 backend_lo; /* low bits of backend procno, if temprel */
RelFileLocator rlocator; /* spcOid, dbOid, relNumber */
} SharedInvalSmgrMsg;

View File

@@ -74,7 +74,7 @@ typedef SMgrRelationData *SMgrRelation;
RelFileLocatorBackendIsTemp((smgr)->smgr_rlocator)
extern void smgrinit(void);
extern SMgrRelation smgropen(RelFileLocator rlocator, BackendId backend);
extern SMgrRelation smgropen(RelFileLocator rlocator, ProcNumber backend);
extern bool smgrexists(SMgrRelation reln, ForkNumber forknum);
extern void smgrpin(SMgrRelation reln);
extern void smgrunpin(SMgrRelation reln);