1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-10 17:42:29 +03:00

Separate out bgwriter code into a logically separate module, rather

than being random pieces of other files.  Give bgwriter responsibility
for all checkpoint activity (other than a post-recovery checkpoint);
so this child process absorbs the functionality of the former transient
checkpoint and shutdown subprocesses.  While at it, create an actual
include file for postmaster.c, which for some reason never had its own
file before.
This commit is contained in:
Tom Lane
2004-05-29 22:48:23 +00:00
parent d531fd2cdc
commit 076a055acf
28 changed files with 1133 additions and 902 deletions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.165 2004/05/08 19:09:25 tgl Exp $
* $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.166 2004/05/29 22:48:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -60,10 +60,6 @@ bool zero_damaged_pages = false;
bool ShowPinTrace = false;
#endif
int BgWriterDelay = 200;
int BgWriterPercent = 1;
int BgWriterMaxpages = 100;
long NDirectFileRead; /* some I/O's are direct file access.
* bypass bufmgr */
long NDirectFileWrite; /* e.g., I/O in psort and hashjoin. */
@@ -862,72 +858,6 @@ FlushBufferPool(void)
}
/*
* BufferBackgroundWriter
*
* Periodically flushes dirty blocks from the buffer pool to keep
* the LRU list clean, preventing regular backends from writing.
*/
void
BufferBackgroundWriter(void)
{
if (BgWriterPercent == 0)
return;
/*
* Loop forever
*/
for (;;)
{
int n;
long udelay;
/*
* Call BufferSync() with instructions to keep just the
* LRU heads clean.
*/
n = BufferSync(BgWriterPercent, BgWriterMaxpages);
/*
* Whatever signal is sent to us, let's just die gallantly. If
* it wasn't meant that way, the postmaster will reincarnate us.
*/
if (InterruptPending)
return;
/*
* Whenever we have nothing to do, close all smgr files. This
* is so we won't hang onto smgr references to deleted files
* indefinitely. XXX this is a bogus, temporary solution. 'Twould
* be much better to do this once per checkpoint, but the bgwriter
* doesn't yet know anything about checkpoints.
*/
if (n == 0)
smgrcloseall();
/*
* Nap for the configured time or sleep for 10 seconds if
* there was nothing to do at all.
*
* On some platforms, signals won't interrupt the sleep. To ensure
* we respond reasonably promptly when the postmaster signals us,
* break down the sleep into 1-second increments, and check for
* interrupts after each nap.
*/
udelay = ((n > 0) ? BgWriterDelay : 10000) * 1000L;
while (udelay > 1000000L)
{
pg_usleep(1000000L);
udelay -= 1000000L;
if (InterruptPending)
return;
}
pg_usleep(udelay);
if (InterruptPending)
return;
}
}
/*
* Do whatever is needed to prepare for commit at the bufmgr and smgr levels
*/

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.67 2004/05/28 05:13:03 tgl Exp $
* $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.68 2004/05/29 22:48:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -18,6 +18,7 @@
#include "miscadmin.h"
#include "access/clog.h"
#include "access/xlog.h"
#include "postmaster/bgwriter.h"
#include "storage/bufmgr.h"
#include "storage/freespace.h"
#include "storage/ipc.h"
@@ -72,6 +73,7 @@ CreateSharedMemoryAndSemaphores(bool makePrivate,
size += LWLockShmemSize();
size += SInvalShmemSize(maxBackends);
size += FreeSpaceShmemSize();
size += BgWriterShmemSize();
#ifdef EXEC_BACKEND
size += ShmemBackendArraySize();
#endif
@@ -155,9 +157,10 @@ CreateSharedMemoryAndSemaphores(bool makePrivate,
InitFreeSpaceMap();
/*
* Set up child-to-postmaster signaling mechanism
* Set up interprocess signaling mechanisms
*/
PMSignalInit();
BgWriterShmemInit();
#ifdef EXEC_BACKEND
/*

View File

@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/ipc/pmsignal.c,v 1.13 2004/02/08 22:28:56 neilc Exp $
* $PostgreSQL: pgsql/src/backend/storage/ipc/pmsignal.c,v 1.14 2004/05/29 22:48:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -83,3 +83,41 @@ CheckPostmasterSignal(PMSignalReason reason)
}
return false;
}
/*
* PostmasterIsAlive - check whether postmaster process is still alive
*
* amDirectChild should be passed as "true" by code that knows it is
* executing in a direct child process of the postmaster; pass "false"
* if an indirect child or not sure. The "true" case uses a faster and
* more reliable test, so use it when possible.
*/
bool
PostmasterIsAlive(bool amDirectChild)
{
#ifndef WIN32
if (amDirectChild)
{
/*
* If the postmaster is alive, we'll still be its child. If it's
* died, we'll be reassigned as a child of the init process.
*/
return (getppid() == PostmasterPid);
}
else
{
/*
* Use kill() to see if the postmaster is still alive. This can
* sometimes give a false positive result, since the postmaster's PID
* may get recycled, but it is good enough for existing uses by
* indirect children.
*/
return (kill(PostmasterPid, 0) == 0);
}
#else /* WIN32 */
/*
* XXX needs to be implemented by somebody
*/
return true;
#endif /* WIN32 */
}

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.147 2004/02/18 16:25:12 momjian Exp $
* $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.148 2004/05/29 22:48:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -68,10 +68,9 @@ PGPROC *MyProc = NULL;
*/
NON_EXEC_STATIC slock_t *ProcStructLock = NULL;
/* Pointers to shared-memory structures */
static PROC_HDR *ProcGlobal = NULL;
static PGPROC *DummyProc = NULL;
static int dummy_proc_type = -1;
static PGPROC *DummyProcs = NULL;
static bool waitingForLock = false;
static bool waitingForSignal = false;
@@ -130,17 +129,16 @@ InitProcGlobal(int maxBackends)
/*
* Create or attach to the PGPROC structures for dummy (checkpoint)
* processes, too. This does not get linked into the freeProcs
* list.
* processes, too. These do not get linked into the freeProcs list.
*/
DummyProc = (PGPROC *)
ShmemInitStruct("DummyProc",sizeof(PGPROC) * NUM_DUMMY_PROCS, &foundDummy);
DummyProcs = (PGPROC *)
ShmemInitStruct("DummyProcs", sizeof(PGPROC) * NUM_DUMMY_PROCS,
&foundDummy);
if (foundProcGlobal || foundDummy)
{
/* both should be present or neither */
Assert(foundProcGlobal && foundDummy);
return;
}
else
{
@@ -170,11 +168,11 @@ InitProcGlobal(int maxBackends)
ProcGlobal->freeProcs = MAKE_OFFSET(proc);
}
MemSet(DummyProc, 0, sizeof(PGPROC) * NUM_DUMMY_PROCS);
MemSet(DummyProcs, 0, sizeof(PGPROC) * NUM_DUMMY_PROCS);
for (i = 0; i < NUM_DUMMY_PROCS; i++)
{
DummyProc[i].pid = 0; /* marks DummyProc as not in use */
PGSemaphoreCreate(&(DummyProc[i].sem));
DummyProcs[i].pid = 0; /* marks dummy proc as not in use */
PGSemaphoreCreate(&(DummyProcs[i].sem));
}
/* Create ProcStructLock spinlock, too */
@@ -249,7 +247,6 @@ InitProcess(void)
MyProc->waitHolder = NULL;
SHMQueueInit(&(MyProc->procHolders));
/*
* Arrange to clean up at backend exit.
*/
@@ -274,6 +271,9 @@ InitProcess(void)
* This is called by checkpoint processes so that they will have a MyProc
* value that's real enough to let them wait for LWLocks. The PGPROC and
* sema that are assigned are the extra ones created during InitProcGlobal.
*
* Dummy processes are presently not expected to wait for real (lockmgr)
* locks, nor to participate in sinval messaging.
*/
void
InitDummyProcess(int proctype)
@@ -284,29 +284,29 @@ InitDummyProcess(int proctype)
* ProcGlobal should be set by a previous call to InitProcGlobal (we
* inherit this by fork() from the postmaster).
*/
if (ProcGlobal == NULL || DummyProc == NULL)
if (ProcGlobal == NULL || DummyProcs == NULL)
elog(PANIC, "proc header uninitialized");
if (MyProc != NULL)
elog(ERROR, "you already exist");
Assert(dummy_proc_type < 0);
dummy_proc_type = proctype;
dummyproc = &DummyProc[proctype];
Assert(proctype >= 0 && proctype < NUM_DUMMY_PROCS);
dummyproc = &DummyProcs[proctype];
/*
* dummyproc should not presently be in use by anyone else
*/
if (dummyproc->pid != 0)
elog(FATAL, "DummyProc[%d] is in use by PID %d",
proctype, dummyproc->pid);
proctype, dummyproc->pid);
MyProc = dummyproc;
/*
* Initialize all fields of MyProc, except MyProc->sem which was set
* up by InitProcGlobal.
*/
MyProc->pid = MyProcPid; /* marks DummyProc as in use by me */
MyProc->pid = MyProcPid; /* marks dummy proc as in use by me */
SHMQueueElemInit(&(MyProc->links));
MyProc->errType = STATUS_OK;
MyProc->xid = InvalidTransactionId;
@@ -323,7 +323,7 @@ InitDummyProcess(int proctype)
/*
* Arrange to clean up at process exit.
*/
on_shmem_exit(DummyProcKill, proctype);
on_shmem_exit(DummyProcKill, Int32GetDatum(proctype));
/*
* We might be reusing a semaphore that belonged to a failed process.
@@ -459,13 +459,14 @@ ProcKill(int code, Datum arg)
static void
DummyProcKill(int code, Datum arg)
{
int proctype = DatumGetInt32(arg);
PGPROC *dummyproc;
Assert(dummy_proc_type >= 0 && dummy_proc_type < NUM_DUMMY_PROCS);
Assert(proctype >= 0 && proctype < NUM_DUMMY_PROCS);
dummyproc = &DummyProc[dummy_proc_type];
dummyproc = &DummyProcs[proctype];
Assert(MyProc != NULL && MyProc == dummyproc);
Assert(MyProc == dummyproc);
/* Release any LW locks I am holding */
LWLockReleaseAll();
@@ -477,13 +478,11 @@ DummyProcKill(int code, Datum arg)
/* I can't be on regular lock queues, so needn't check */
/* Mark DummyProc no longer in use */
/* Mark dummy proc no longer in use */
MyProc->pid = 0;
/* PGPROC struct isn't mine anymore */
MyProc = NULL;
dummy_proc_type = -1;
}