Re: [v9.3] Extra Daemons (Re: elegant and effective way for running jobs inside a database) - Mailing list pgsql-hackers

From Alvaro Herrera
Subject Re: [v9.3] Extra Daemons (Re: elegant and effective way for running jobs inside a database)
Date
Msg-id 1348674577-sup-3506@alvh.no-ip.org
Whole thread Raw
In response to [v9.3] Extra Daemons (Re: elegant and effective way for running jobs inside a database)  (Kohei KaiGai <kaigai@kaigai.gr.jp>)
Responses Re: [v9.3] Extra Daemons (Re: elegant and effective way for running jobs inside a database)
List pgsql-hackers
Excerpts from Kohei KaiGai's message of mié abr 25 06:40:23 -0300 2012:

> I tried to implement a patch according to the idea. It allows extensions
> to register an entry point of the self-managed daemon processes,
> then postmaster start and stop them according to the normal manner.

Here's my attempt at this.  This is loosely based on your code, as well
as parts of what Simon sent me privately.

One thing *not* implemented in this patch is EXEC_BACKEND support.  I
haven't looked at that at all, but it looks rather involved to
implement.  If we agree that what I propose here is a reasonable
interface I will start looking at that.

I ported your auth_counter to my framework.  It works in the sense that
it runs, but I observed that it always report zeroes.  I didn't debug
that.

Please let me know your thoughts.  Some ideas below.  (I thought about
putting the text below as src/backend/postmaster/README.bgworker).


A background worker is a secondary process that takes advantage of postmaster
to start, stop, and receive signals during operation (e.g. for recovery
restart and similar conditions).  It may optionally connect to a particular
database, like a regular backend; or it might "connect" to no database in
particular, giving it access to shared catalogs, similar to autovacuum
launcher.  It may also request attachment to shared memory, which allows it to
acquire lwlocks, etc.

An extension or loadable module can request a bgworker to be loaded by calling
RegisterBackgroundWorker.  This receives a function pointer to run when the
bgworker is started; a point in time at which to start it; a pointer to some
opaque data; and SIGHUP and SIGTERM handlers.

RegisterBackgroundWorker can be called multiple times by the same loadable
module; this can be used, for example, to have one worker to connect to each
database.

Once running, a worker can establish a database connection by calling
BackgroundWorkerInitializeConnection.  This receives a database name to
connect to (NULL for a shared-catalog-only connection), and a username (NULL
to mean bootstrap superuser).

Registration flags
------------------

The following flags currently exist:

BGWORKER_SHMEM_ACCESS --- this determines that the worker will have access to
shared memory; in particular it'll be able to acquire lwlocks.  It will also
be killed in case of child crash, etc.

BGWORKER_BACKEND_DATABASE_CONNECTION --- this allows a worker to request a
database connection.  This also determines stop time on postmaster shutdown,
etc.  If this flag is passed, BGWORKER_SHMEM_ACCESS must also be passed.
If a worker with such a flag dies with an exit code other than 0/1, it will
cause HandleChildCrash to be called, just like a backend that dies.

XXX --- do we need more flags?

XXX --- the signal timing bits depending on flags are not yet set in stone.

Postmaster behavior
-------------------

Each RegisterBackgroundWorker(BGWORKER_SHMEM_ACCESS) call increases the number
of PGPROC elements required.  Such bgworkers can only be registered during
shared_preload_libraries; this is a useful limitation because it means the
total number of PGPROC entries needed can be determined at postmaster start
time, and thus we do not need a new GUC to control the max number of workers
(Whether we want such a limit for other reasons, such as protecting against
broken modules that register thousands of workers, is TBD).  XXX not
implemented is the capability that workers that do *not* request shared memory
access can be registered when postmaster is running.  It's not clear that this
is really useful.

There are three states in the postmaster state machine upon entering which
bgworkers can be started.  1. PM_INIT (postmaster start); 2. PM_HOT_STANDBY
(consistent state reached); 3. PM_RUN (recovery finished).  Workers specify
their start time during registration.  A worker cannot request database
connection if the start time is PM_INIT.

XXX It is unclear whether we need to allow for shutdown timing tweaks.

Postmaster coding
-----------------

Postmaster keeps track of background workers in BackgroundWorkerList.  Each
list element is a RegisteredBgWorker; this list, and each element, are allocated at
postmaster start time (during RegisterBackgroundWorker) and never destroyed.
Each element has a pointer to a BackgroundWorker element, plus a PID (zero if
the worker is not running), a PMChildSlot, a cancel_key, and possibly a
pointer to a Backend entry (which is also present in the BackendList).

This arrangement makes it easy to
1. find workers that need to be started
2. find workers that need to be signalled in various conditions
3. execute cancel signals (even though the cancel key is presumably hard to
find)

Note that since the Backend entry for a worker is in BackendList, it's
important to search the bgworkers list (CleanupBackgroundWorker) before the
backends list (CleanupBackend) during signalling.


--
Álvaro Herrera                http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services


Attachment

pgsql-hackers by date:

Previous
From: Dimitri Fontaine
Date:
Subject: Re: Oid registry
Next
From: Jeff Janes
Date:
Subject: Re: autovacuum stress-testing our system