/* These are always necessary for a bgworker */ #include"miscadmin.h" #include"postmaster/bgworker.h" #include"postmaster/interrupt.h" #include"storage/latch.h"
/* these headers are used by this particular worker's code */ #include"access/xact.h" #include"commands/dbcommands.h" #include"executor/spi.h" #include"fmgr.h" #include"lib/stringinfo.h" #include"pgstat.h" #include"tcop/utility.h" #include"utils/acl.h" #include"utils/builtins.h" #include"utils/snapmgr.h"
/* XXX could we use CREATE SCHEMA IF NOT EXISTS? */
initStringInfo(&buf);
appendStringInfo(&buf, "select count(*) from pg_namespace where nspname = '%s'",
table->schema);
debug_query_string = buf.data;
ret = SPI_execute(buf.data, true, 0); if (ret != SPI_OK_SELECT)
elog(FATAL, "SPI_execute failed: error code %d", ret);
if (SPI_processed != 1)
elog(FATAL, "not a singleton result");
/* fetch database and role OIDs, these are set for a dynamic worker */
p = MyBgworkerEntry->bgw_extra;
memcpy(&dboid, p, sizeof(Oid));
p += sizeof(Oid);
memcpy(&roleoid, p, sizeof(Oid));
p += sizeof(Oid);
memcpy(&flags, p, sizeof(bits32));
/* Establish signal handlers before unblocking signals. */
pqsignal(SIGHUP, SignalHandlerForConfigReload);
pqsignal(SIGTERM, die);
/* We're now ready to receive signals */
BackgroundWorkerUnblockSignals();
/* Connect to our database */ if (OidIsValid(dboid))
BackgroundWorkerInitializeConnectionByOid(dboid, roleoid, flags); else
BackgroundWorkerInitializeConnection(worker_spi_database,
worker_spi_role, flags);
elog(LOG, "%s initialized with %s.%s",
MyBgworkerEntry->bgw_name, table->schema, table->name);
initialize_worker_spi(table);
initStringInfo(&buf);
appendStringInfo(&buf, "WITH deleted AS (DELETE " "FROM %s.%s " "WHERE type = 'delta' RETURNING value), " "total AS (SELECT coalesce(sum(value), 0) as sum " "FROM deleted) " "UPDATE %s.%s " "SET value = %s.value + total.sum " "FROM total WHERE type = 'total' " "RETURNING %s.value",
table->schema, table->name,
table->schema, table->name,
table->name,
table->name);
/* *Mainloop:dothisuntilSIGTERMisreceivedandprocessedby *ProcessInterrupts.
*/ for (;;)
{ int ret;
/* First time, allocate or get the custom wait event */ if (worker_spi_wait_event_main == 0)
worker_spi_wait_event_main = WaitEventExtensionNew("WorkerSpiMain");
/* We can now execute queries via SPI */
ret = SPI_execute(buf.data, false, 0);
if (ret != SPI_OK_UPDATE_RETURNING)
elog(FATAL, "cannot select from table %s.%s: error code %d",
table->schema, table->name, ret);
if (SPI_processed > 0)
{ bool isnull;
int32 val;
val = DatumGetInt32(SPI_getbinval(SPI_tuptable->vals[0],
SPI_tuptable->tupdesc, 1, &isnull)); if (!isnull)
elog(LOG, "%s: count in %s.%s is now %d",
MyBgworkerEntry->bgw_name,
table->schema, table->name, val);
}
/* set up common data for all our workers */
memset(&worker, 0, sizeof(worker));
worker.bgw_flags = BGWORKER_SHMEM_ACCESS |
BGWORKER_BACKEND_DATABASE_CONNECTION;
worker.bgw_start_time = BgWorkerStart_RecoveryFinished;
worker.bgw_restart_time = BGW_NEVER_RESTART;
sprintf(worker.bgw_library_name, "worker_spi");
sprintf(worker.bgw_function_name, "worker_spi_main");
worker.bgw_notify_pid = 0;
/* *Nowfillinworker-specificdata,anddotheactualregistrations. * *bgw_extracanoptionallyincludeadatabaseOID,aroleOIDandaset *offlags.ThisisleftemptyheretofallbacktotherelatedGUCsat *startup(0forthebgworkerflags).
*/ for (int i = 1; i <= worker_spi_total_workers; i++)
{
snprintf(worker.bgw_name, BGW_MAXLEN, "worker_spi worker %d", i);
snprintf(worker.bgw_type, BGW_MAXLEN, "worker_spi");
worker.bgw_main_arg = Int32GetDatum(i);
RegisterBackgroundWorker(&worker);
}
}
/* *DynamicallylaunchanSPIworker.
*/
Datum
worker_spi_launch(PG_FUNCTION_ARGS)
{
int32 i = PG_GETARG_INT32(0);
Oid dboid = PG_GETARG_OID(1);
Oid roleoid = PG_GETARG_OID(2);
BackgroundWorker worker;
BackgroundWorkerHandle *handle;
BgwHandleStatus status;
pid_t pid; char *p;
bits32 flags = 0;
ArrayType *arr = PG_GETARG_ARRAYTYPE_P(3);
Size ndim; int nelems;
Datum *datum_flags;
memset(&worker, 0, sizeof(worker));
worker.bgw_flags = BGWORKER_SHMEM_ACCESS |
BGWORKER_BACKEND_DATABASE_CONNECTION;
worker.bgw_start_time = BgWorkerStart_RecoveryFinished;
worker.bgw_restart_time = BGW_NEVER_RESTART;
sprintf(worker.bgw_library_name, "worker_spi");
sprintf(worker.bgw_function_name, "worker_spi_main");
snprintf(worker.bgw_name, BGW_MAXLEN, "worker_spi dynamic worker %d", i);
snprintf(worker.bgw_type, BGW_MAXLEN, "worker_spi dynamic");
worker.bgw_main_arg = Int32GetDatum(i); /* set bgw_notify_pid so that we can use WaitForBackgroundWorkerStartup */
worker.bgw_notify_pid = MyProcPid;
/* extract flags, if any */
ndim = ARR_NDIM(arr); if (ndim > 1)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("flags array must be one-dimensional")));
if (array_contains_nulls(arr))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("flags array must not contain nulls")));
p = worker.bgw_extra;
memcpy(p, &dboid, sizeof(Oid));
p += sizeof(Oid);
memcpy(p, &roleoid, sizeof(Oid));
p += sizeof(Oid);
memcpy(p, &flags, sizeof(bits32));
if (!RegisterDynamicBackgroundWorker(&worker, &handle))
PG_RETURN_NULL();
status = WaitForBackgroundWorkerStartup(handle, &pid);
if (status == BGWH_STOPPED)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_RESOURCES),
errmsg("could not start background process"),
errhint("More details may be available in the server log."))); if (status == BGWH_POSTMASTER_DIED)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_RESOURCES),
errmsg("cannot start background processes without postmaster"),
errhint("Kill all remaining database processes and restart the database.")));
Assert(status == BGWH_STARTED);
PG_RETURN_INT32(pid);
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-08-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.