mirror of
https://github.com/postgres/postgres.git
synced 2025-11-22 12:22:45 +03:00
Redefine backend ID to be an index into the proc array
Previously, backend ID was an index into the ProcState array, in the shared cache invalidation manager (sinvaladt.c). The entry in the ProcState array was reserved at backend startup by scanning the array for a free entry, and that was also when the backend got its backend ID. Things become slightly simpler if we redefine backend ID to be the index into the PGPROC array, and directly use it also as an index to the ProcState array. This uses a little more memory, as we reserve a few extra slots in the ProcState array for aux processes that don't need them, but the simplicity is worth it. Aux processes now also have a backend ID. This simplifies the reservation of BackendStatusArray and ProcSignal slots. You can now convert a backend ID into an index into the PGPROC array simply by subtracting 1. We still use 0-based "pgprocnos" in various places, for indexes into the PGPROC array, but the only difference now is that backend IDs start at 1 while pgprocnos start at 0. (The next commmit will get rid of the term "backend ID" altogether and make everything 0-based.) There is still a 'backendId' field in PGPROC, now part of 'vxid' which encapsulates the backend ID and local transaction ID together. It's needed for prepared xacts. For regular backends, the backendId is always equal to pgprocno + 1, but for prepared xact PGPROC entries, it's the ID of the original backend that processed the transaction. Reviewed-by: Andres Freund, Reid Thompson Discussion: https://www.postgresql.org/message-id/8171f1aa-496f-46a6-afc3-c46fe7a9b407@iki.fi
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
#include "port/atomics.h" /* for memory barriers */
|
||||
#include "storage/ipc.h"
|
||||
#include "storage/proc.h" /* for MyProc */
|
||||
#include "storage/procarray.h"
|
||||
#include "storage/sinvaladt.h"
|
||||
#include "utils/ascii.h"
|
||||
#include "utils/backend_status.h"
|
||||
@@ -29,13 +30,12 @@
|
||||
/* ----------
|
||||
* Total number of backends including auxiliary
|
||||
*
|
||||
* We reserve a slot for each possible BackendId, plus one for each
|
||||
* possible auxiliary process type. (This scheme assumes there is not
|
||||
* more than one of any auxiliary process type at a time.) MaxBackends
|
||||
* includes autovacuum workers and background workers as well.
|
||||
* We reserve a slot for each possible PGPROC entry, including aux processes.
|
||||
* (But not including PGPROC entries reserved for prepared xacts; they are not
|
||||
* real processes.)
|
||||
* ----------
|
||||
*/
|
||||
#define NumBackendStatSlots (MaxBackends + NUM_AUXPROCTYPES)
|
||||
#define NumBackendStatSlots (MaxBackends + NUM_AUXILIARY_PROCS)
|
||||
|
||||
|
||||
/* ----------
|
||||
@@ -238,10 +238,9 @@ CreateSharedBackendStatus(void)
|
||||
|
||||
/*
|
||||
* Initialize pgstats backend activity state, and set up our on-proc-exit
|
||||
* hook. Called from InitPostgres and AuxiliaryProcessMain. For auxiliary
|
||||
* process, MyBackendId is invalid. Otherwise, MyBackendId must be set, but we
|
||||
* must not have started any transaction yet (since the exit hook must run
|
||||
* after the last transaction exit).
|
||||
* hook. Called from InitPostgres and AuxiliaryProcessMain. MyBackendId must
|
||||
* be set, but we must not have started any transaction yet (since the exit
|
||||
* hook must run after the last transaction exit).
|
||||
*
|
||||
* NOTE: MyDatabaseId isn't set yet; so the shutdown hook has to be careful.
|
||||
*/
|
||||
@@ -249,26 +248,9 @@ void
|
||||
pgstat_beinit(void)
|
||||
{
|
||||
/* Initialize MyBEEntry */
|
||||
if (MyBackendId != InvalidBackendId)
|
||||
{
|
||||
Assert(MyBackendId >= 1 && MyBackendId <= MaxBackends);
|
||||
MyBEEntry = &BackendStatusArray[MyBackendId - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Must be an auxiliary process */
|
||||
Assert(MyAuxProcType != NotAnAuxProcess);
|
||||
|
||||
/*
|
||||
* Assign the MyBEEntry for an auxiliary process. Since it doesn't
|
||||
* have a BackendId, the slot is statically allocated based on the
|
||||
* auxiliary process type (MyAuxProcType). Backends use slots indexed
|
||||
* in the range from 0 to MaxBackends (exclusive), so we use
|
||||
* MaxBackends + AuxProcType as the index of the slot for an auxiliary
|
||||
* process.
|
||||
*/
|
||||
MyBEEntry = &BackendStatusArray[MaxBackends + MyAuxProcType];
|
||||
}
|
||||
Assert(MyBackendId != InvalidBackendId);
|
||||
Assert(MyBackendId >= 1 && MyBackendId <= NumBackendStatSlots);
|
||||
MyBEEntry = &BackendStatusArray[MyBackendId - 1];
|
||||
|
||||
/* Set up a process-exit hook to clean up */
|
||||
on_shmem_exit(pgstat_beshutdown_hook, 0);
|
||||
@@ -281,12 +263,12 @@ pgstat_beinit(void)
|
||||
* Initialize this backend's entry in the PgBackendStatus array.
|
||||
* Called from InitPostgres.
|
||||
*
|
||||
* Apart from auxiliary processes, MyBackendId, MyDatabaseId,
|
||||
* session userid, and application_name must be set for a
|
||||
* backend (hence, this cannot be combined with pgstat_beinit).
|
||||
* Note also that we must be inside a transaction if this isn't an aux
|
||||
* process, as we may need to do encoding conversion on some strings.
|
||||
* ----------
|
||||
* Apart from auxiliary processes, MyDatabaseId, session userid, and
|
||||
* application_name must already be set (hence, this cannot be combined
|
||||
* with pgstat_beinit). Note also that we must be inside a transaction
|
||||
* if this isn't an aux process, as we may need to do encoding conversion
|
||||
* on some strings.
|
||||
*----------
|
||||
*/
|
||||
void
|
||||
pgstat_bestart(void)
|
||||
|
||||
@@ -353,7 +353,7 @@ pg_lock_status(PG_FUNCTION_ARGS)
|
||||
break;
|
||||
}
|
||||
|
||||
values[10] = VXIDGetDatum(instance->backend, instance->lxid);
|
||||
values[10] = VXIDGetDatum(instance->vxid.backendId, instance->vxid.localTransactionId);
|
||||
if (instance->pid != 0)
|
||||
values[11] = Int32GetDatum(instance->pid);
|
||||
else
|
||||
|
||||
@@ -148,19 +148,11 @@ pg_log_backend_memory_contexts(PG_FUNCTION_ARGS)
|
||||
PGPROC *proc;
|
||||
BackendId backendId = InvalidBackendId;
|
||||
|
||||
proc = BackendPidGetProc(pid);
|
||||
|
||||
/*
|
||||
* See if the process with given pid is a backend or an auxiliary process.
|
||||
*
|
||||
* If the given process is a backend, use its backend id in
|
||||
* SendProcSignal() later to speed up the operation. Otherwise, don't do
|
||||
* that because auxiliary processes (except the startup process) don't
|
||||
* have a valid backend id.
|
||||
*/
|
||||
if (proc != NULL)
|
||||
backendId = proc->backendId;
|
||||
else
|
||||
proc = BackendPidGetProc(pid);
|
||||
if (proc == NULL)
|
||||
proc = AuxiliaryPidGetProc(pid);
|
||||
|
||||
/*
|
||||
@@ -183,6 +175,8 @@ pg_log_backend_memory_contexts(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_BOOL(false);
|
||||
}
|
||||
|
||||
if (proc != NULL)
|
||||
backendId = GetBackendIdFromPGProc(proc);
|
||||
if (SendProcSignal(pid, PROCSIG_LOG_MEMORY_CONTEXT, backendId) < 0)
|
||||
{
|
||||
/* Again, just a warning to allow loops */
|
||||
|
||||
@@ -152,8 +152,8 @@ write_csvlog(ErrorData *edata)
|
||||
|
||||
/* Virtual transaction id */
|
||||
/* keep VXID format in sync with lockfuncs.c */
|
||||
if (MyProc != NULL && MyProc->backendId != InvalidBackendId)
|
||||
appendStringInfo(&buf, "%d/%u", MyProc->backendId, MyProc->lxid);
|
||||
if (MyProc != NULL && MyProc->vxid.backendId != InvalidBackendId)
|
||||
appendStringInfo(&buf, "%d/%u", MyProc->vxid.backendId, MyProc->vxid.lxid);
|
||||
appendStringInfoChar(&buf, ',');
|
||||
|
||||
/* Transaction id */
|
||||
|
||||
@@ -3076,18 +3076,18 @@ log_status_format(StringInfo buf, const char *format, ErrorData *edata)
|
||||
break;
|
||||
case 'v':
|
||||
/* keep VXID format in sync with lockfuncs.c */
|
||||
if (MyProc != NULL && MyProc->backendId != InvalidBackendId)
|
||||
if (MyProc != NULL && MyProc->vxid.backendId != InvalidBackendId)
|
||||
{
|
||||
if (padding != 0)
|
||||
{
|
||||
char strfbuf[128];
|
||||
|
||||
snprintf(strfbuf, sizeof(strfbuf) - 1, "%d/%u",
|
||||
MyProc->backendId, MyProc->lxid);
|
||||
MyProc->vxid.backendId, MyProc->vxid.lxid);
|
||||
appendStringInfo(buf, "%*s", padding, strfbuf);
|
||||
}
|
||||
else
|
||||
appendStringInfo(buf, "%d/%u", MyProc->backendId, MyProc->lxid);
|
||||
appendStringInfo(buf, "%d/%u", MyProc->vxid.backendId, MyProc->vxid.lxid);
|
||||
}
|
||||
else if (padding != 0)
|
||||
appendStringInfoSpaces(buf,
|
||||
|
||||
@@ -197,9 +197,9 @@ write_jsonlog(ErrorData *edata)
|
||||
|
||||
/* Virtual transaction id */
|
||||
/* keep VXID format in sync with lockfuncs.c */
|
||||
if (MyProc != NULL && MyProc->backendId != InvalidBackendId)
|
||||
appendJSONKeyValueFmt(&buf, "vxid", true, "%d/%u", MyProc->backendId,
|
||||
MyProc->lxid);
|
||||
if (MyProc != NULL && MyProc->vxid.backendId != InvalidBackendId)
|
||||
appendJSONKeyValueFmt(&buf, "vxid", true, "%d/%u",
|
||||
MyProc->vxid.backendId, MyProc->vxid.lxid);
|
||||
|
||||
/* Transaction id */
|
||||
appendJSONKeyValueFmt(&buf, "txid", false, "%u",
|
||||
|
||||
@@ -742,18 +742,10 @@ InitPostgres(const char *in_dbname, Oid dboid,
|
||||
/*
|
||||
* Initialize my entry in the shared-invalidation manager's array of
|
||||
* per-backend data.
|
||||
*
|
||||
* Sets up MyBackendId, a unique backend identifier.
|
||||
*/
|
||||
MyBackendId = InvalidBackendId;
|
||||
|
||||
SharedInvalBackendInit(false);
|
||||
|
||||
if (MyBackendId > MaxBackends || MyBackendId <= 0)
|
||||
elog(FATAL, "bad backend ID: %d", MyBackendId);
|
||||
|
||||
/* Now that we have a BackendId, we can participate in ProcSignal */
|
||||
ProcSignalInit(MyBackendId);
|
||||
ProcSignalInit();
|
||||
|
||||
/*
|
||||
* Also set up timeout handlers needed for backend operation. We need
|
||||
|
||||
@@ -1154,7 +1154,8 @@ ExportSnapshot(Snapshot snapshot)
|
||||
* inside the transaction from 1.
|
||||
*/
|
||||
snprintf(path, sizeof(path), SNAPSHOT_EXPORT_DIR "/%08X-%08X-%d",
|
||||
MyProc->backendId, MyProc->lxid, list_length(exportedSnapshots) + 1);
|
||||
MyProc->vxid.backendId, MyProc->vxid.lxid,
|
||||
list_length(exportedSnapshots) + 1);
|
||||
|
||||
/*
|
||||
* Copy the snapshot into TopTransactionContext, add it to the
|
||||
@@ -1181,7 +1182,7 @@ ExportSnapshot(Snapshot snapshot)
|
||||
*/
|
||||
initStringInfo(&buf);
|
||||
|
||||
appendStringInfo(&buf, "vxid:%d/%u\n", MyProc->backendId, MyProc->lxid);
|
||||
appendStringInfo(&buf, "vxid:%d/%u\n", MyProc->vxid.backendId, MyProc->vxid.lxid);
|
||||
appendStringInfo(&buf, "pid:%d\n", MyProcPid);
|
||||
appendStringInfo(&buf, "dbid:%u\n", MyDatabaseId);
|
||||
appendStringInfo(&buf, "iso:%d\n", XactIsoLevel);
|
||||
|
||||
Reference in New Issue
Block a user