Commit cfeca621 authored by Jan Wieck's avatar Jan Wieck

Background writer process

This first part of the background writer does no syncing at all.
It's only purpose is to keep the LRU heads clean so that regular
backends seldom to never have to call write().

Jan
parent 5032f830
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.166 2003/09/02 19:04:12 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.167 2003/11/19 15:55:07 wieck Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -428,8 +428,20 @@ BootstrapMain(int argc, char *argv[]) ...@@ -428,8 +428,20 @@ BootstrapMain(int argc, char *argv[])
BaseInit(); BaseInit();
/* needed to get LWLocks */
if (IsUnderPostmaster) if (IsUnderPostmaster)
InitDummyProcess(); /* needed to get LWLocks */ {
switch (xlogop)
{
case BS_XLOG_BGWRITER:
InitDummyProcess(DUMMY_PROC_BGWRITER);
break;
default:
InitDummyProcess(DUMMY_PROC_DEFAULT);
break;
}
}
/* /*
* XLOG operations * XLOG operations
...@@ -453,6 +465,11 @@ BootstrapMain(int argc, char *argv[]) ...@@ -453,6 +465,11 @@ BootstrapMain(int argc, char *argv[])
* postmaster */ * postmaster */
proc_exit(0); /* done */ proc_exit(0); /* done */
case BS_XLOG_BGWRITER:
CreateDummyCaches();
BufferBackgroundWriter();
proc_exit(0); /* done */
case BS_XLOG_STARTUP: case BS_XLOG_STARTUP:
StartupXLOG(); StartupXLOG();
LoadFreeSpaceMap(); LoadFreeSpaceMap();
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.221 2003/11/12 21:15:48 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.222 2003/11/19 15:55:07 wieck Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
...@@ -1043,7 +1043,7 @@ setRelhasindex(Oid relid, bool hasindex, bool isprimary, Oid reltoastidxid) ...@@ -1043,7 +1043,7 @@ setRelhasindex(Oid relid, bool hasindex, bool isprimary, Oid reltoastidxid)
/* Send out shared cache inval if necessary */ /* Send out shared cache inval if necessary */
if (!IsBootstrapProcessingMode()) if (!IsBootstrapProcessingMode())
CacheInvalidateHeapTuple(pg_class, tuple); CacheInvalidateHeapTuple(pg_class, tuple);
BufferSync(); BufferSync(-1, -1);
} }
else if (dirty) else if (dirty)
{ {
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.126 2003/11/12 21:15:50 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.127 2003/11/19 15:55:07 wieck Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -317,7 +317,7 @@ createdb(const CreatedbStmt *stmt) ...@@ -317,7 +317,7 @@ createdb(const CreatedbStmt *stmt)
* up-to-date for the copy. (We really only need to flush buffers for * up-to-date for the copy. (We really only need to flush buffers for
* the source database...) * the source database...)
*/ */
BufferSync(); BufferSync(-1, -1);
/* /*
* Close virtual file descriptors so the kernel has more available for * Close virtual file descriptors so the kernel has more available for
...@@ -454,7 +454,7 @@ createdb(const CreatedbStmt *stmt) ...@@ -454,7 +454,7 @@ createdb(const CreatedbStmt *stmt)
* will see the new database in pg_database right away. (They'll see * will see the new database in pg_database right away. (They'll see
* an uncommitted tuple, but they don't care; see GetRawDatabaseInfo.) * an uncommitted tuple, but they don't care; see GetRawDatabaseInfo.)
*/ */
BufferSync(); BufferSync(-1, -1);
} }
...@@ -591,7 +591,7 @@ dropdb(const char *dbname) ...@@ -591,7 +591,7 @@ dropdb(const char *dbname)
* (They'll see an uncommitted deletion, but they don't care; see * (They'll see an uncommitted deletion, but they don't care; see
* GetRawDatabaseInfo.) * GetRawDatabaseInfo.)
*/ */
BufferSync(); BufferSync(-1, -1);
} }
...@@ -688,7 +688,7 @@ RenameDatabase(const char *oldname, const char *newname) ...@@ -688,7 +688,7 @@ RenameDatabase(const char *oldname, const char *newname)
* see an uncommitted tuple, but they don't care; see * see an uncommitted tuple, but they don't care; see
* GetRawDatabaseInfo.) * GetRawDatabaseInfo.)
*/ */
BufferSync(); BufferSync(-1, -1);
} }
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.348 2003/11/11 01:09:42 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.349 2003/11/19 15:55:07 wieck Exp $
* *
* NOTES * NOTES
* *
...@@ -104,6 +104,7 @@ ...@@ -104,6 +104,7 @@
#include "storage/pg_shmem.h" #include "storage/pg_shmem.h"
#include "storage/pmsignal.h" #include "storage/pmsignal.h"
#include "storage/proc.h" #include "storage/proc.h"
#include "storage/bufmgr.h"
#include "access/xlog.h" #include "access/xlog.h"
#include "tcop/tcopprot.h" #include "tcop/tcopprot.h"
#include "utils/guc.h" #include "utils/guc.h"
...@@ -224,7 +225,8 @@ char *preload_libraries_string = NULL; ...@@ -224,7 +225,8 @@ char *preload_libraries_string = NULL;
/* Startup/shutdown state */ /* Startup/shutdown state */
static pid_t StartupPID = 0, static pid_t StartupPID = 0,
ShutdownPID = 0, ShutdownPID = 0,
CheckPointPID = 0; CheckPointPID = 0,
BgWriterPID = 0;
static time_t checkpointed = 0; static time_t checkpointed = 0;
#define NoShutdown 0 #define NoShutdown 0
...@@ -298,6 +300,7 @@ __attribute__((format(printf, 1, 2))); ...@@ -298,6 +300,7 @@ __attribute__((format(printf, 1, 2)));
#define StartupDataBase() SSDataBase(BS_XLOG_STARTUP) #define StartupDataBase() SSDataBase(BS_XLOG_STARTUP)
#define CheckPointDataBase() SSDataBase(BS_XLOG_CHECKPOINT) #define CheckPointDataBase() SSDataBase(BS_XLOG_CHECKPOINT)
#define StartBackgroundWriter() SSDataBase(BS_XLOG_BGWRITER)
#define ShutdownDataBase() SSDataBase(BS_XLOG_SHUTDOWN) #define ShutdownDataBase() SSDataBase(BS_XLOG_SHUTDOWN)
...@@ -1055,6 +1058,17 @@ ServerLoop(void) ...@@ -1055,6 +1058,17 @@ ServerLoop(void)
} }
} }
/*
* If no background writer process is running and we should
* do background writing, start one. It doesn't matter if
* this fails, we'll just try again later.
*/
if (BgWriterPID == 0 && BgWriterPercent > 0 &&
Shutdown == NoShutdown && !FatalError && random_seed != 0)
{
BgWriterPID = StartBackgroundWriter();
}
/* /*
* Wait for something to happen. * Wait for something to happen.
*/ */
...@@ -1478,6 +1492,13 @@ processCancelRequest(Port *port, void *pkt) ...@@ -1478,6 +1492,13 @@ processCancelRequest(Port *port, void *pkt)
backendPID))); backendPID)));
return; return;
} }
else if (backendPID == BgWriterPID)
{
ereport(DEBUG2,
(errmsg_internal("ignoring cancel request for bgwriter process %d",
backendPID)));
return;
}
else if (ExecBackend) else if (ExecBackend)
AttachSharedMemoryAndSemaphores(); AttachSharedMemoryAndSemaphores();
...@@ -1660,6 +1681,13 @@ SIGHUP_handler(SIGNAL_ARGS) ...@@ -1660,6 +1681,13 @@ SIGHUP_handler(SIGNAL_ARGS)
SignalChildren(SIGHUP); SignalChildren(SIGHUP);
load_hba(); load_hba();
load_ident(); load_ident();
/*
* Tell the background writer to terminate so that we
* will start a new one with a possibly changed config
*/
if (BgWriterPID != 0)
kill(BgWriterPID, SIGTERM);
} }
PG_SETMASK(&UnBlockSig); PG_SETMASK(&UnBlockSig);
...@@ -1692,6 +1720,8 @@ pmdie(SIGNAL_ARGS) ...@@ -1692,6 +1720,8 @@ pmdie(SIGNAL_ARGS)
* *
* Wait for children to end their work and ShutdownDataBase. * Wait for children to end their work and ShutdownDataBase.
*/ */
if (BgWriterPID != 0)
kill(BgWriterPID, SIGTERM);
if (Shutdown >= SmartShutdown) if (Shutdown >= SmartShutdown)
break; break;
Shutdown = SmartShutdown; Shutdown = SmartShutdown;
...@@ -1724,6 +1754,8 @@ pmdie(SIGNAL_ARGS) ...@@ -1724,6 +1754,8 @@ pmdie(SIGNAL_ARGS)
* abort all children with SIGTERM (rollback active transactions * abort all children with SIGTERM (rollback active transactions
* and exit) and ShutdownDataBase when they are gone. * and exit) and ShutdownDataBase when they are gone.
*/ */
if (BgWriterPID != 0)
kill(BgWriterPID, SIGTERM);
if (Shutdown >= FastShutdown) if (Shutdown >= FastShutdown)
break; break;
ereport(LOG, ereport(LOG,
...@@ -1770,6 +1802,8 @@ pmdie(SIGNAL_ARGS) ...@@ -1770,6 +1802,8 @@ pmdie(SIGNAL_ARGS)
* abort all children with SIGQUIT and exit without attempt to * abort all children with SIGQUIT and exit without attempt to
* properly shutdown data base system. * properly shutdown data base system.
*/ */
if (BgWriterPID != 0)
kill(BgWriterPID, SIGQUIT);
ereport(LOG, ereport(LOG,
(errmsg("received immediate shutdown request"))); (errmsg("received immediate shutdown request")));
if (ShutdownPID > 0) if (ShutdownPID > 0)
...@@ -1877,6 +1911,12 @@ reaper(SIGNAL_ARGS) ...@@ -1877,6 +1911,12 @@ reaper(SIGNAL_ARGS)
CheckPointPID = 0; CheckPointPID = 0;
checkpointed = time(NULL); checkpointed = time(NULL);
if (BgWriterPID == 0 && BgWriterPercent > 0 &&
Shutdown == NoShutdown && !FatalError && random_seed != 0)
{
BgWriterPID = StartBackgroundWriter();
}
/* /*
* Go to shutdown mode if a shutdown request was pending. * Go to shutdown mode if a shutdown request was pending.
*/ */
...@@ -1983,6 +2023,8 @@ CleanupProc(int pid, ...@@ -1983,6 +2023,8 @@ CleanupProc(int pid,
GetSavedRedoRecPtr(); GetSavedRedoRecPtr();
} }
} }
else if (pid == BgWriterPID)
BgWriterPID = 0;
else else
pgstat_beterm(pid); pgstat_beterm(pid);
...@@ -1996,6 +2038,7 @@ CleanupProc(int pid, ...@@ -1996,6 +2038,7 @@ CleanupProc(int pid,
{ {
LogChildExit(LOG, LogChildExit(LOG,
(pid == CheckPointPID) ? gettext("checkpoint process") : (pid == CheckPointPID) ? gettext("checkpoint process") :
(pid == BgWriterPID) ? gettext("bgwriter process") :
gettext("server process"), gettext("server process"),
pid, exitstatus); pid, exitstatus);
ereport(LOG, ereport(LOG,
...@@ -2044,6 +2087,10 @@ CleanupProc(int pid, ...@@ -2044,6 +2087,10 @@ CleanupProc(int pid,
CheckPointPID = 0; CheckPointPID = 0;
checkpointed = 0; checkpointed = 0;
} }
else if (pid == BgWriterPID)
{
BgWriterPID = 0;
}
else else
{ {
/* /*
...@@ -2754,6 +2801,8 @@ CountChildren(void) ...@@ -2754,6 +2801,8 @@ CountChildren(void)
} }
if (CheckPointPID != 0) if (CheckPointPID != 0)
cnt--; cnt--;
if (BgWriterPID != 0)
cnt--;
return cnt; return cnt;
} }
...@@ -2827,6 +2876,9 @@ SSDataBase(int xlop) ...@@ -2827,6 +2876,9 @@ SSDataBase(int xlop)
case BS_XLOG_CHECKPOINT: case BS_XLOG_CHECKPOINT:
statmsg = "checkpoint subprocess"; statmsg = "checkpoint subprocess";
break; break;
case BS_XLOG_BGWRITER:
statmsg = "bgwriter subprocess";
break;
case BS_XLOG_SHUTDOWN: case BS_XLOG_SHUTDOWN:
statmsg = "shutdown subprocess"; statmsg = "shutdown subprocess";
break; break;
...@@ -2883,6 +2935,10 @@ SSDataBase(int xlop) ...@@ -2883,6 +2935,10 @@ SSDataBase(int xlop)
ereport(LOG, ereport(LOG,
(errmsg("could not fork checkpoint process: %m"))); (errmsg("could not fork checkpoint process: %m")));
break; break;
case BS_XLOG_BGWRITER:
ereport(LOG,
(errmsg("could not fork bgwriter process: %m")));
break;
case BS_XLOG_SHUTDOWN: case BS_XLOG_SHUTDOWN:
ereport(LOG, ereport(LOG,
(errmsg("could not fork shutdown process: %m"))); (errmsg("could not fork shutdown process: %m")));
...@@ -2895,19 +2951,22 @@ SSDataBase(int xlop) ...@@ -2895,19 +2951,22 @@ SSDataBase(int xlop)
/* /*
* fork failure is fatal during startup/shutdown, but there's no * fork failure is fatal during startup/shutdown, but there's no
* need to choke if a routine checkpoint fails. * need to choke if a routine checkpoint or starting a background
* writer fails.
*/ */
if (xlop == BS_XLOG_CHECKPOINT) if (xlop == BS_XLOG_CHECKPOINT)
return 0; return 0;
if (xlop == BS_XLOG_BGWRITER)
return 0;
ExitPostmaster(1); ExitPostmaster(1);
} }
/* /*
* The startup and shutdown processes are not considered normal * The startup and shutdown processes are not considered normal
* backends, but the checkpoint process is. Checkpoint must be added * backends, but the checkpoint and bgwriter processes are.
* to the list of backends. * They must be added to the list of backends.
*/ */
if (xlop == BS_XLOG_CHECKPOINT) if (xlop == BS_XLOG_CHECKPOINT || xlop == BS_XLOG_BGWRITER)
{ {
if (!(bn = (Backend *) malloc(sizeof(Backend)))) if (!(bn = (Backend *) malloc(sizeof(Backend))))
{ {
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.144 2003/11/13 14:57:15 wieck Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.145 2003/11/19 15:55:07 wieck Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include <sys/file.h> #include <sys/file.h>
#include <math.h> #include <math.h>
#include <signal.h> #include <signal.h>
#include <unistd.h>
#include "lib/stringinfo.h" #include "lib/stringinfo.h"
#include "miscadmin.h" #include "miscadmin.h"
...@@ -63,6 +64,9 @@ ...@@ -63,6 +64,9 @@
/* GUC variable */ /* GUC variable */
bool zero_damaged_pages = false; bool zero_damaged_pages = false;
int BgWriterDelay = 200;
int BgWriterPercent = 1;
int BgWriterMaxpages = 100;
static void WaitIO(BufferDesc *buf); static void WaitIO(BufferDesc *buf);
static void StartBufferIO(BufferDesc *buf, bool forInput); static void StartBufferIO(BufferDesc *buf, bool forInput);
...@@ -679,10 +683,11 @@ ReleaseAndReadBuffer(Buffer buffer, ...@@ -679,10 +683,11 @@ ReleaseAndReadBuffer(Buffer buffer,
/* /*
* BufferSync -- Write all dirty buffers in the pool. * BufferSync -- Write all dirty buffers in the pool.
* *
* This is called at checkpoint time and writes out all dirty shared buffers. * This is called at checkpoint time and writes out all dirty shared buffers,
* and by the background writer process to write out some of the dirty blocks.
*/ */
void int
BufferSync(void) BufferSync(int percent, int maxpages)
{ {
int i; int i;
BufferDesc *bufHdr; BufferDesc *bufHdr;
...@@ -703,12 +708,24 @@ BufferSync(void) ...@@ -703,12 +708,24 @@ BufferSync(void)
* have to wait until the next checkpoint. * have to wait until the next checkpoint.
*/ */
buffer_dirty = (int *)palloc(NBuffers * sizeof(int)); buffer_dirty = (int *)palloc(NBuffers * sizeof(int));
num_buffer_dirty = 0;
LWLockAcquire(BufMgrLock, LW_EXCLUSIVE); LWLockAcquire(BufMgrLock, LW_EXCLUSIVE);
num_buffer_dirty = StrategyDirtyBufferList(buffer_dirty, NBuffers); num_buffer_dirty = StrategyDirtyBufferList(buffer_dirty, NBuffers);
LWLockRelease(BufMgrLock); LWLockRelease(BufMgrLock);
/*
* If called by the background writer, we are usually asked to
* only write out some percentage of dirty buffers now, to prevent
* the IO storm at checkpoint time.
*/
if (percent > 0 && num_buffer_dirty > 10)
{
Assert(percent <= 100);
num_buffer_dirty = (num_buffer_dirty * percent) / 100;
if (maxpages > 0 && num_buffer_dirty > maxpages)
num_buffer_dirty = maxpages;
}
for (i = 0; i < num_buffer_dirty; i++) for (i = 0; i < num_buffer_dirty; i++)
{ {
Buffer buffer; Buffer buffer;
...@@ -854,6 +871,8 @@ BufferSync(void) ...@@ -854,6 +871,8 @@ BufferSync(void)
/* Pop the error context stack */ /* Pop the error context stack */
error_context_stack = errcontext.previous; error_context_stack = errcontext.previous;
return num_buffer_dirty;
} }
/* /*
...@@ -984,10 +1003,56 @@ AtEOXact_Buffers(bool isCommit) ...@@ -984,10 +1003,56 @@ AtEOXact_Buffers(bool isCommit)
void void
FlushBufferPool(void) FlushBufferPool(void)
{ {
BufferSync(); BufferSync(-1, -1);
smgrsync(); smgrsync();
} }
/*
* 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, i;
/*
* 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 galantly. If
* it wasn't meant that way, the postmaster will reincarnate us.
*/
if (InterruptPending)
return;
/*
* Nap for the configured time or sleep for 10 seconds if
* there was nothing to do at all.
*/
if (n > 0)
{
PG_DELAY(BgWriterDelay);
}
else
sleep(10);
}
}
/* /*
* Do whatever is needed to prepare for commit at the bufmgr and smgr levels * Do whatever is needed to prepare for commit at the bufmgr and smgr levels
*/ */
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/freelist.c,v 1.35 2003/11/16 16:41:00 wieck Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/buffer/freelist.c,v 1.36 2003/11/19 15:55:07 wieck Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -190,8 +190,28 @@ StrategyBufferLookup(BufferTag *tagPtr, bool recheck) ...@@ -190,8 +190,28 @@ StrategyBufferLookup(BufferTag *tagPtr, bool recheck)
if (StrategyControl->stat_report + DebugSharedBuffers < now) if (StrategyControl->stat_report + DebugSharedBuffers < now)
{ {
long all_hit, b1_hit, t1_hit, t2_hit, b2_hit; long all_hit, b1_hit, t1_hit, t2_hit, b2_hit;
int id, t1_clean, t2_clean;
ErrorContextCallback *errcxtold; ErrorContextCallback *errcxtold;
id = StrategyControl->listHead[STRAT_LIST_T1];
t1_clean = 0;
while (id >= 0)
{
if (BufferDescriptors[StrategyCDB[id].buf_id].flags & BM_DIRTY)
break;
t1_clean++;
id = StrategyCDB[id].next;
}
id = StrategyControl->listHead[STRAT_LIST_T2];
t2_clean = 0;
while (id >= 0)
{
if (BufferDescriptors[StrategyCDB[id].buf_id].flags & BM_DIRTY)
break;
t2_clean++;
id = StrategyCDB[id].next;
}
if (StrategyControl->num_lookup == 0) if (StrategyControl->num_lookup == 0)
{ {
all_hit = b1_hit = t1_hit = t2_hit = b2_hit = 0; all_hit = b1_hit = t1_hit = t2_hit = b2_hit = 0;
...@@ -215,6 +235,8 @@ StrategyBufferLookup(BufferTag *tagPtr, bool recheck) ...@@ -215,6 +235,8 @@ StrategyBufferLookup(BufferTag *tagPtr, bool recheck)
T1_TARGET, B1_LENGTH, T1_LENGTH, T2_LENGTH, B2_LENGTH); T1_TARGET, B1_LENGTH, T1_LENGTH, T2_LENGTH, B2_LENGTH);
elog(DEBUG1, "ARC total =%4ld%% B1hit=%4ld%% T1hit=%4ld%% T2hit=%4ld%% B2hit=%4ld%%", elog(DEBUG1, "ARC total =%4ld%% B1hit=%4ld%% T1hit=%4ld%% T2hit=%4ld%% B2hit=%4ld%%",
all_hit, b1_hit, t1_hit, t2_hit, b2_hit); all_hit, b1_hit, t1_hit, t2_hit, b2_hit);
elog(DEBUG1, "ARC clean buffers at LRU T1= %5d T2= %5d",
t1_clean, t2_clean);
error_context_stack = errcxtold; error_context_stack = errcxtold;
StrategyControl->num_lookup = 0; StrategyControl->num_lookup = 0;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.136 2003/10/16 20:59:35 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.137 2003/11/19 15:55:07 wieck Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -71,6 +71,7 @@ static slock_t *ProcStructLock = NULL; ...@@ -71,6 +71,7 @@ static slock_t *ProcStructLock = NULL;
static PROC_HDR *ProcGlobal = NULL; static PROC_HDR *ProcGlobal = NULL;
static PGPROC *DummyProc = NULL; static PGPROC *DummyProc = NULL;
static int dummy_proc_type = -1;
static bool waitingForLock = false; static bool waitingForLock = false;
static bool waitingForSignal = false; static bool waitingForSignal = false;
...@@ -163,14 +164,17 @@ InitProcGlobal(int maxBackends) ...@@ -163,14 +164,17 @@ InitProcGlobal(int maxBackends)
* processes, too. This does not get linked into the freeProcs * processes, too. This does not get linked into the freeProcs
* list. * list.
*/ */
DummyProc = (PGPROC *) ShmemAlloc(sizeof(PGPROC)); DummyProc = (PGPROC *) ShmemAlloc(sizeof(PGPROC) * NUM_DUMMY_PROCS);
if (!DummyProc) if (!DummyProc)
ereport(FATAL, ereport(FATAL,
(errcode(ERRCODE_OUT_OF_MEMORY), (errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of shared memory"))); errmsg("out of shared memory")));
MemSet(DummyProc, 0, sizeof(PGPROC)); MemSet(DummyProc, 0, sizeof(PGPROC) * NUM_DUMMY_PROCS);
DummyProc->pid = 0; /* marks DummyProc as not in use */ for (i = 0; i < NUM_DUMMY_PROCS; i++)
PGSemaphoreCreate(&DummyProc->sem); {
DummyProc[i].pid = 0; /* marks DummyProc as not in use */
PGSemaphoreCreate(&(DummyProc[i].sem));
}
/* Create ProcStructLock spinlock, too */ /* Create ProcStructLock spinlock, too */
ProcStructLock = (slock_t *) ShmemAlloc(sizeof(slock_t)); ProcStructLock = (slock_t *) ShmemAlloc(sizeof(slock_t));
...@@ -270,8 +274,10 @@ InitProcess(void) ...@@ -270,8 +274,10 @@ InitProcess(void)
* sema that are assigned are the extra ones created during InitProcGlobal. * sema that are assigned are the extra ones created during InitProcGlobal.
*/ */
void void
InitDummyProcess(void) InitDummyProcess(int proctype)
{ {
PGPROC *dummyproc;
/* /*
* ProcGlobal should be set by a previous call to InitProcGlobal (we * ProcGlobal should be set by a previous call to InitProcGlobal (we
* inherit this by fork() from the postmaster). * inherit this by fork() from the postmaster).
...@@ -282,12 +288,17 @@ InitDummyProcess(void) ...@@ -282,12 +288,17 @@ InitDummyProcess(void)
if (MyProc != NULL) if (MyProc != NULL)
elog(ERROR, "you already exist"); elog(ERROR, "you already exist");
Assert(dummy_proc_type < 0);
dummy_proc_type = proctype;
dummyproc = &DummyProc[proctype];
/* /*
* DummyProc should not presently be in use by anyone else * dummyproc should not presently be in use by anyone else
*/ */
if (DummyProc->pid != 0) if (dummyproc->pid != 0)
elog(FATAL, "DummyProc is in use by PID %d", DummyProc->pid); elog(FATAL, "DummyProc[%d] is in use by PID %d",
MyProc = DummyProc; proctype, dummyproc->pid);
MyProc = dummyproc;
/* /*
* Initialize all fields of MyProc, except MyProc->sem which was set * Initialize all fields of MyProc, except MyProc->sem which was set
...@@ -310,7 +321,7 @@ InitDummyProcess(void) ...@@ -310,7 +321,7 @@ InitDummyProcess(void)
/* /*
* Arrange to clean up at process exit. * Arrange to clean up at process exit.
*/ */
on_shmem_exit(DummyProcKill, 0); on_shmem_exit(DummyProcKill, proctype);
/* /*
* We might be reusing a semaphore that belonged to a failed process. * We might be reusing a semaphore that belonged to a failed process.
...@@ -446,7 +457,13 @@ ProcKill(void) ...@@ -446,7 +457,13 @@ ProcKill(void)
static void static void
DummyProcKill(void) DummyProcKill(void)
{ {
Assert(MyProc != NULL && MyProc == DummyProc); PGPROC *dummyproc;
Assert(dummy_proc_type >= 0 && dummy_proc_type < NUM_DUMMY_PROCS);
dummyproc = &DummyProc[dummy_proc_type];
Assert(MyProc != NULL && MyProc == dummyproc);
/* Release any LW locks I am holding */ /* Release any LW locks I am holding */
LWLockReleaseAll(); LWLockReleaseAll();
...@@ -463,6 +480,8 @@ DummyProcKill(void) ...@@ -463,6 +480,8 @@ DummyProcKill(void)
/* PGPROC struct isn't mine anymore */ /* PGPROC struct isn't mine anymore */
MyProc = NULL; MyProc = NULL;
dummy_proc_type = -1;
} }
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>. * Written by Peter Eisentraut <peter_e@gmx.net>.
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.170 2003/11/16 16:41:01 wieck Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.171 2003/11/19 15:55:08 wieck Exp $
* *
*-------------------------------------------------------------------- *--------------------------------------------------------------------
*/ */
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include "optimizer/prep.h" #include "optimizer/prep.h"
#include "parser/parse_expr.h" #include "parser/parse_expr.h"
#include "parser/parse_relation.h" #include "parser/parse_relation.h"
#include "storage/bufmgr.h"
#include "storage/fd.h" #include "storage/fd.h"
#include "storage/freespace.h" #include "storage/freespace.h"
#include "storage/lock.h" #include "storage/lock.h"
...@@ -1200,6 +1201,33 @@ static struct config_int ConfigureNamesInt[] = ...@@ -1200,6 +1201,33 @@ static struct config_int ConfigureNamesInt[] =
0, 0, 600, NULL, NULL 0, 0, 600, NULL, NULL
}, },
{
{"bgwriter_delay", PGC_SIGHUP, RESOURCES,
gettext_noop("Background writer sleep time between rounds in milliseconds"),
NULL
},
&BgWriterDelay,
200, 10, 5000, NULL, NULL
},
{
{"bgwriter_percent", PGC_SIGHUP, RESOURCES,
gettext_noop("Background writer percentage of dirty buffers to flush per round"),
NULL
},
&BgWriterPercent,
1, 0, 100, NULL, NULL
},
{
{"bgwriter_maxpages", PGC_SIGHUP, RESOURCES,
gettext_noop("Background writer maximum number of pages to flush per round"),
NULL
},
&BgWriterMaxpages,
100, 1, 1000, NULL, NULL
},
/* End-of-list marker */ /* End-of-list marker */
{ {
{NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL {NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL
......
...@@ -60,6 +60,11 @@ ...@@ -60,6 +60,11 @@
#vacuum_mem = 8192 # min 1024, size in KB #vacuum_mem = 8192 # min 1024, size in KB
#debug_shared_buffers = 0 # 0-600 seconds #debug_shared_buffers = 0 # 0-600 seconds
# - Background writer -
#bgwriter_delay = 200 # 10-5000 milliseconds
#bgwriter_percent = 1 # 0-100% of dirty buffers
#bgwriter_maxpages = 100 # 1-1000 buffers max at once
# - Free Space Map - # - Free Space Map -
#max_fsm_pages = 20000 # min max_fsm_relations*16, 6 bytes each #max_fsm_pages = 20000 # min max_fsm_relations*16, 6 bytes each
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: bootstrap.h,v 1.31 2003/08/04 02:40:10 momjian Exp $ * $Id: bootstrap.h,v 1.32 2003/11/19 15:55:08 wieck Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -59,6 +59,7 @@ extern void Int_yyerror(const char *str); ...@@ -59,6 +59,7 @@ extern void Int_yyerror(const char *str);
#define BS_XLOG_BOOTSTRAP 1 #define BS_XLOG_BOOTSTRAP 1
#define BS_XLOG_STARTUP 2 #define BS_XLOG_STARTUP 2
#define BS_XLOG_CHECKPOINT 3 #define BS_XLOG_CHECKPOINT 3
#define BS_XLOG_SHUTDOWN 4 #define BS_XLOG_BGWRITER 4
#define BS_XLOG_SHUTDOWN 5
#endif /* BOOTSTRAP_H */ #endif /* BOOTSTRAP_H */
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: bufmgr.h,v 1.70 2003/08/10 19:48:08 tgl Exp $ * $Id: bufmgr.h,v 1.71 2003/11/19 15:55:08 wieck Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -28,6 +28,11 @@ extern DLLIMPORT int NBuffers; ...@@ -28,6 +28,11 @@ extern DLLIMPORT int NBuffers;
/* in bufmgr.c */ /* in bufmgr.c */
extern bool zero_damaged_pages; extern bool zero_damaged_pages;
extern int BgWriterDelay;
extern int BgWriterPercent;
extern int BgWriterMaxpages;
/* in buf_init.c */ /* in buf_init.c */
extern DLLIMPORT Block *BufferBlockPointers; extern DLLIMPORT Block *BufferBlockPointers;
extern long *PrivateRefCount; extern long *PrivateRefCount;
...@@ -186,7 +191,10 @@ extern void LockBufferForCleanup(Buffer buffer); ...@@ -186,7 +191,10 @@ extern void LockBufferForCleanup(Buffer buffer);
extern void AbortBufferIO(void); extern void AbortBufferIO(void);
extern void BufmgrCommit(void); extern void BufmgrCommit(void);
extern void BufferSync(void); extern int BufferSync(int percent, int maxpages);
extern void BufferBackgroundWriter(void);
extern const char *BgWriterAssignSyncMethod(const char *method,
bool doid, bool interactive);
extern void InitLocalBuffer(void); extern void InitLocalBuffer(void);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: proc.h,v 1.64 2003/08/04 02:40:15 momjian Exp $ * $Id: proc.h,v 1.65 2003/11/19 15:55:08 wieck Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -86,6 +86,11 @@ typedef struct PROC_HDR ...@@ -86,6 +86,11 @@ typedef struct PROC_HDR
} PROC_HDR; } PROC_HDR;
#define DUMMY_PROC_DEFAULT 0
#define DUMMY_PROC_BGWRITER 1
#define NUM_DUMMY_PROCS 2
/* configurable options */ /* configurable options */
extern int DeadlockTimeout; extern int DeadlockTimeout;
extern int StatementTimeout; extern int StatementTimeout;
...@@ -97,7 +102,7 @@ extern int StatementTimeout; ...@@ -97,7 +102,7 @@ extern int StatementTimeout;
extern int ProcGlobalSemas(int maxBackends); extern int ProcGlobalSemas(int maxBackends);
extern void InitProcGlobal(int maxBackends); extern void InitProcGlobal(int maxBackends);
extern void InitProcess(void); extern void InitProcess(void);
extern void InitDummyProcess(void); extern void InitDummyProcess(int proctype);
extern void ProcReleaseLocks(bool isCommit); extern void ProcReleaseLocks(bool isCommit);
extern void ProcQueueInit(PROC_QUEUE *queue); extern void ProcQueueInit(PROC_QUEUE *queue);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment