aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/bootstrap/bootstrap.c21
-rw-r--r--src/backend/catalog/index.c4
-rw-r--r--src/backend/commands/dbcommands.c10
-rw-r--r--src/backend/postmaster/postmaster.c71
-rw-r--r--src/backend/storage/buffer/bufmgr.c79
-rw-r--r--src/backend/storage/buffer/freelist.c24
-rw-r--r--src/backend/storage/lmgr/proc.c43
-rw-r--r--src/backend/utils/misc/guc.c30
-rw-r--r--src/backend/utils/misc/postgresql.conf.sample5
-rw-r--r--src/include/bootstrap/bootstrap.h5
-rw-r--r--src/include/storage/bufmgr.h12
-rw-r--r--src/include/storage/proc.h9
12 files changed, 271 insertions, 42 deletions
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index cfd8a553582..bb67feab71f 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* 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[])
BaseInit();
+ /* needed to get LWLocks */
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
@@ -453,6 +465,11 @@ BootstrapMain(int argc, char *argv[])
* postmaster */
proc_exit(0); /* done */
+ case BS_XLOG_BGWRITER:
+ CreateDummyCaches();
+ BufferBackgroundWriter();
+ proc_exit(0); /* done */
+
case BS_XLOG_STARTUP:
StartupXLOG();
LoadFreeSpaceMap();
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 72f76b01b06..3d6c71e4e89 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -8,7 +8,7 @@
*
*
* 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
@@ -1043,7 +1043,7 @@ setRelhasindex(Oid relid, bool hasindex, bool isprimary, Oid reltoastidxid)
/* Send out shared cache inval if necessary */
if (!IsBootstrapProcessingMode())
CacheInvalidateHeapTuple(pg_class, tuple);
- BufferSync();
+ BufferSync(-1, -1);
}
else if (dirty)
{
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 320f1fc0ded..9abdb9555c6 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -9,7 +9,7 @@
*
*
* 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)
* up-to-date for the copy. (We really only need to flush buffers for
* the source database...)
*/
- BufferSync();
+ BufferSync(-1, -1);
/*
* Close virtual file descriptors so the kernel has more available for
@@ -454,7 +454,7 @@ createdb(const CreatedbStmt *stmt)
* will see the new database in pg_database right away. (They'll see
* an uncommitted tuple, but they don't care; see GetRawDatabaseInfo.)
*/
- BufferSync();
+ BufferSync(-1, -1);
}
@@ -591,7 +591,7 @@ dropdb(const char *dbname)
* (They'll see an uncommitted deletion, but they don't care; see
* GetRawDatabaseInfo.)
*/
- BufferSync();
+ BufferSync(-1, -1);
}
@@ -688,7 +688,7 @@ RenameDatabase(const char *oldname, const char *newname)
* see an uncommitted tuple, but they don't care; see
* GetRawDatabaseInfo.)
*/
- BufferSync();
+ BufferSync(-1, -1);
}
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 01c3a363c8f..52c91fa97d9 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -37,7 +37,7 @@
*
*
* 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
*
@@ -104,6 +104,7 @@
#include "storage/pg_shmem.h"
#include "storage/pmsignal.h"
#include "storage/proc.h"
+#include "storage/bufmgr.h"
#include "access/xlog.h"
#include "tcop/tcopprot.h"
#include "utils/guc.h"
@@ -224,7 +225,8 @@ char *preload_libraries_string = NULL;
/* Startup/shutdown state */
static pid_t StartupPID = 0,
ShutdownPID = 0,
- CheckPointPID = 0;
+ CheckPointPID = 0,
+ BgWriterPID = 0;
static time_t checkpointed = 0;
#define NoShutdown 0
@@ -298,6 +300,7 @@ __attribute__((format(printf, 1, 2)));
#define StartupDataBase() SSDataBase(BS_XLOG_STARTUP)
#define CheckPointDataBase() SSDataBase(BS_XLOG_CHECKPOINT)
+#define StartBackgroundWriter() SSDataBase(BS_XLOG_BGWRITER)
#define ShutdownDataBase() SSDataBase(BS_XLOG_SHUTDOWN)
@@ -1056,6 +1059,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.
*/
memcpy((char *) &rmask, (char *) &readmask, sizeof(fd_set));
@@ -1478,6 +1492,13 @@ processCancelRequest(Port *port, void *pkt)
backendPID)));
return;
}
+ else if (backendPID == BgWriterPID)
+ {
+ ereport(DEBUG2,
+ (errmsg_internal("ignoring cancel request for bgwriter process %d",
+ backendPID)));
+ return;
+ }
else if (ExecBackend)
AttachSharedMemoryAndSemaphores();
@@ -1660,6 +1681,13 @@ SIGHUP_handler(SIGNAL_ARGS)
SignalChildren(SIGHUP);
load_hba();
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);
@@ -1692,6 +1720,8 @@ pmdie(SIGNAL_ARGS)
*
* Wait for children to end their work and ShutdownDataBase.
*/
+ if (BgWriterPID != 0)
+ kill(BgWriterPID, SIGTERM);
if (Shutdown >= SmartShutdown)
break;
Shutdown = SmartShutdown;
@@ -1724,6 +1754,8 @@ pmdie(SIGNAL_ARGS)
* abort all children with SIGTERM (rollback active transactions
* and exit) and ShutdownDataBase when they are gone.
*/
+ if (BgWriterPID != 0)
+ kill(BgWriterPID, SIGTERM);
if (Shutdown >= FastShutdown)
break;
ereport(LOG,
@@ -1770,6 +1802,8 @@ pmdie(SIGNAL_ARGS)
* abort all children with SIGQUIT and exit without attempt to
* properly shutdown data base system.
*/
+ if (BgWriterPID != 0)
+ kill(BgWriterPID, SIGQUIT);
ereport(LOG,
(errmsg("received immediate shutdown request")));
if (ShutdownPID > 0)
@@ -1877,6 +1911,12 @@ reaper(SIGNAL_ARGS)
CheckPointPID = 0;
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.
*/
@@ -1983,6 +2023,8 @@ CleanupProc(int pid,
GetSavedRedoRecPtr();
}
}
+ else if (pid == BgWriterPID)
+ BgWriterPID = 0;
else
pgstat_beterm(pid);
@@ -1996,6 +2038,7 @@ CleanupProc(int pid,
{
LogChildExit(LOG,
(pid == CheckPointPID) ? gettext("checkpoint process") :
+ (pid == BgWriterPID) ? gettext("bgwriter process") :
gettext("server process"),
pid, exitstatus);
ereport(LOG,
@@ -2044,6 +2087,10 @@ CleanupProc(int pid,
CheckPointPID = 0;
checkpointed = 0;
}
+ else if (pid == BgWriterPID)
+ {
+ BgWriterPID = 0;
+ }
else
{
/*
@@ -2754,6 +2801,8 @@ CountChildren(void)
}
if (CheckPointPID != 0)
cnt--;
+ if (BgWriterPID != 0)
+ cnt--;
return cnt;
}
@@ -2827,6 +2876,9 @@ SSDataBase(int xlop)
case BS_XLOG_CHECKPOINT:
statmsg = "checkpoint subprocess";
break;
+ case BS_XLOG_BGWRITER:
+ statmsg = "bgwriter subprocess";
+ break;
case BS_XLOG_SHUTDOWN:
statmsg = "shutdown subprocess";
break;
@@ -2883,6 +2935,10 @@ SSDataBase(int xlop)
ereport(LOG,
(errmsg("could not fork checkpoint process: %m")));
break;
+ case BS_XLOG_BGWRITER:
+ ereport(LOG,
+ (errmsg("could not fork bgwriter process: %m")));
+ break;
case BS_XLOG_SHUTDOWN:
ereport(LOG,
(errmsg("could not fork shutdown process: %m")));
@@ -2895,19 +2951,22 @@ SSDataBase(int xlop)
/*
* 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)
return 0;
+ if (xlop == BS_XLOG_BGWRITER)
+ return 0;
ExitPostmaster(1);
}
/*
* The startup and shutdown processes are not considered normal
- * backends, but the checkpoint process is. Checkpoint must be added
- * to the list of backends.
+ * backends, but the checkpoint and bgwriter processes are.
+ * 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))))
{
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index cbb23b664c6..aab99caa9d6 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -8,7 +8,7 @@
*
*
* 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 @@
#include <sys/file.h>
#include <math.h>
#include <signal.h>
+#include <unistd.h>
#include "lib/stringinfo.h"
#include "miscadmin.h"
@@ -63,6 +64,9 @@
/* GUC variable */
bool zero_damaged_pages = false;
+int BgWriterDelay = 200;
+int BgWriterPercent = 1;
+int BgWriterMaxpages = 100;
static void WaitIO(BufferDesc *buf);
static void StartBufferIO(BufferDesc *buf, bool forInput);
@@ -679,10 +683,11 @@ ReleaseAndReadBuffer(Buffer buffer,
/*
* 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
-BufferSync(void)
+int
+BufferSync(int percent, int maxpages)
{
int i;
BufferDesc *bufHdr;
@@ -703,12 +708,24 @@ BufferSync(void)
* have to wait until the next checkpoint.
*/
buffer_dirty = (int *)palloc(NBuffers * sizeof(int));
- num_buffer_dirty = 0;
-
+
LWLockAcquire(BufMgrLock, LW_EXCLUSIVE);
num_buffer_dirty = StrategyDirtyBufferList(buffer_dirty, NBuffers);
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++)
{
Buffer buffer;
@@ -854,6 +871,8 @@ BufferSync(void)
/* Pop the error context stack */
error_context_stack = errcontext.previous;
+
+ return num_buffer_dirty;
}
/*
@@ -984,10 +1003,56 @@ AtEOXact_Buffers(bool isCommit)
void
FlushBufferPool(void)
{
- BufferSync();
+ BufferSync(-1, -1);
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
*/
diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c
index 12d67b13424..84bcb1554d1 100644
--- a/src/backend/storage/buffer/freelist.c
+++ b/src/backend/storage/buffer/freelist.c
@@ -8,7 +8,7 @@
*
*
* 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)
if (StrategyControl->stat_report + DebugSharedBuffers < now)
{
long all_hit, b1_hit, t1_hit, t2_hit, b2_hit;
+ int id, t1_clean, t2_clean;
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)
{
all_hit = b1_hit = t1_hit = t2_hit = b2_hit = 0;
@@ -215,6 +235,8 @@ StrategyBufferLookup(BufferTag *tagPtr, bool recheck)
T1_TARGET, B1_LENGTH, T1_LENGTH, T2_LENGTH, B2_LENGTH);
elog(DEBUG1, "ARC total =%4ld%% B1hit=%4ld%% T1hit=%4ld%% T2hit=%4ld%% B2hit=%4ld%%",
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;
StrategyControl->num_lookup = 0;
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 6ffac1d43cf..cea8ffe4c76 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -8,7 +8,7 @@
*
*
* 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;
static PROC_HDR *ProcGlobal = NULL;
static PGPROC *DummyProc = NULL;
+static int dummy_proc_type = -1;
static bool waitingForLock = false;
static bool waitingForSignal = false;
@@ -163,14 +164,17 @@ InitProcGlobal(int maxBackends)
* processes, too. This does not get linked into the freeProcs
* list.
*/
- DummyProc = (PGPROC *) ShmemAlloc(sizeof(PGPROC));
+ DummyProc = (PGPROC *) ShmemAlloc(sizeof(PGPROC) * NUM_DUMMY_PROCS);
if (!DummyProc)
ereport(FATAL,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of shared memory")));
- MemSet(DummyProc, 0, sizeof(PGPROC));
- DummyProc->pid = 0; /* marks DummyProc as not in use */
- PGSemaphoreCreate(&DummyProc->sem);
+ MemSet(DummyProc, 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));
+ }
/* Create ProcStructLock spinlock, too */
ProcStructLock = (slock_t *) ShmemAlloc(sizeof(slock_t));
@@ -270,8 +274,10 @@ InitProcess(void)
* sema that are assigned are the extra ones created during InitProcGlobal.
*/
void
-InitDummyProcess(void)
+InitDummyProcess(int proctype)
{
+ PGPROC *dummyproc;
+
/*
* ProcGlobal should be set by a previous call to InitProcGlobal (we
* inherit this by fork() from the postmaster).
@@ -282,12 +288,17 @@ InitDummyProcess(void)
if (MyProc != NULL)
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)
- elog(FATAL, "DummyProc is in use by PID %d", DummyProc->pid);
- MyProc = DummyProc;
+ if (dummyproc->pid != 0)
+ elog(FATAL, "DummyProc[%d] is in use by PID %d",
+ proctype, dummyproc->pid);
+ MyProc = dummyproc;
/*
* Initialize all fields of MyProc, except MyProc->sem which was set
@@ -310,7 +321,7 @@ InitDummyProcess(void)
/*
* 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.
@@ -446,7 +457,13 @@ ProcKill(void)
static 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 */
LWLockReleaseAll();
@@ -463,6 +480,8 @@ DummyProcKill(void)
/* PGPROC struct isn't mine anymore */
MyProc = NULL;
+
+ dummy_proc_type = -1;
}
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index bd8db1bb85b..25aef118e35 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* 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 @@
#include "optimizer/prep.h"
#include "parser/parse_expr.h"
#include "parser/parse_relation.h"
+#include "storage/bufmgr.h"
#include "storage/fd.h"
#include "storage/freespace.h"
#include "storage/lock.h"
@@ -1200,6 +1201,33 @@ static struct config_int ConfigureNamesInt[] =
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 */
{
{NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 64e94edab96..e4305d98596 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -60,6 +60,11 @@
#vacuum_mem = 8192 # min 1024, size in KB
#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 -
#max_fsm_pages = 20000 # min max_fsm_relations*16, 6 bytes each
diff --git a/src/include/bootstrap/bootstrap.h b/src/include/bootstrap/bootstrap.h
index e444aeef43c..0367522da3a 100644
--- a/src/include/bootstrap/bootstrap.h
+++ b/src/include/bootstrap/bootstrap.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* 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);
#define BS_XLOG_BOOTSTRAP 1
#define BS_XLOG_STARTUP 2
#define BS_XLOG_CHECKPOINT 3
-#define BS_XLOG_SHUTDOWN 4
+#define BS_XLOG_BGWRITER 4
+#define BS_XLOG_SHUTDOWN 5
#endif /* BOOTSTRAP_H */
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index bfbf64e207f..df0708f9092 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* 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;
/* in bufmgr.c */
extern bool zero_damaged_pages;
+extern int BgWriterDelay;
+extern int BgWriterPercent;
+extern int BgWriterMaxpages;
+
+
/* in buf_init.c */
extern DLLIMPORT Block *BufferBlockPointers;
extern long *PrivateRefCount;
@@ -186,7 +191,10 @@ extern void LockBufferForCleanup(Buffer buffer);
extern void AbortBufferIO(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);
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index 3cad0c5b63c..235ed751b41 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* 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
} PROC_HDR;
+#define DUMMY_PROC_DEFAULT 0
+#define DUMMY_PROC_BGWRITER 1
+#define NUM_DUMMY_PROCS 2
+
+
/* configurable options */
extern int DeadlockTimeout;
extern int StatementTimeout;
@@ -97,7 +102,7 @@ extern int StatementTimeout;
extern int ProcGlobalSemas(int maxBackends);
extern void InitProcGlobal(int maxBackends);
extern void InitProcess(void);
-extern void InitDummyProcess(void);
+extern void InitDummyProcess(int proctype);
extern void ProcReleaseLocks(bool isCommit);
extern void ProcQueueInit(PROC_QUEUE *queue);