]> granicus.if.org Git - postgresql/commitdiff
Background writer process
authorJan Wieck <JanWieck@Yahoo.com>
Wed, 19 Nov 2003 15:55:08 +0000 (15:55 +0000)
committerJan Wieck <JanWieck@Yahoo.com>
Wed, 19 Nov 2003 15:55:08 +0000 (15:55 +0000)
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

12 files changed:
src/backend/bootstrap/bootstrap.c
src/backend/catalog/index.c
src/backend/commands/dbcommands.c
src/backend/postmaster/postmaster.c
src/backend/storage/buffer/bufmgr.c
src/backend/storage/buffer/freelist.c
src/backend/storage/lmgr/proc.c
src/backend/utils/misc/guc.c
src/backend/utils/misc/postgresql.conf.sample
src/include/bootstrap/bootstrap.h
src/include/storage/bufmgr.h
src/include/storage/proc.h

index cfd8a553582451edba1c44f1dc68a2a978ab4814..bb67feab71fc3716d6e2e8d89de2c0a9f858901e 100644 (file)
@@ -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();
index 72f76b01b06d2e18e7e81fed3aee12932d3bd716..3d6c71e4e89fe6f356c11fd1eea8ba39a6c3d5af 100644 (file)
@@ -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)
        {
index 320f1fc0deddf1f54d01980786250bf0ac9f0f9d..9abdb9555c67d546ce866300b21c6c5a0d4b9a62 100644 (file)
@@ -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);
 }
 
 
index 01c3a363c8f6d553d8a55b6a4b643c97023b4cc6..52c91fa97d903bcd33175ea4e90c141c868dd879 100644 (file)
@@ -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
  *
 #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)
 
 
@@ -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.
                 */
@@ -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))))
                {
index cbb23b664c6df445bce198070f0a334eafa0bc53..aab99caa9d6ecbf269418e558fe46328b1a80386 100644 (file)
@@ -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
  */
index 12d67b1342461ef593bc374d1d3892626dbfd722..84bcb1554d1957fd5d6db299a52bf46bb830698e 100644 (file)
@@ -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;
index 6ffac1d43cf29fb0b2c9b710aaa0401222b4d39d..cea8ffe4c76e42797863999c73486aca63530bc7 100644 (file)
@@ -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;
 }
 
 
index bd8db1bb85b964ae115c12e7fb9ffcb71337a31d..25aef118e3547600568732543271a98727e35a92 100644 (file)
@@ -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
index 64e94edab965e0a7034f786a4be536e1278ecee8..e4305d98596c86eb6d6f9d0902cad5022460b45e 100644 (file)
 #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
index e444aeef43cb89afcf48d0aadc758dd8bdbf0278..0367522da3a3a490d04e293030fd703b80c9ae01 100644 (file)
@@ -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 */
index bfbf64e207f5dc9b0f0eaca8edf9cd0f97acd9c9..df0708f9092eef4d5b7ba681c51543498cf4ad89 100644 (file)
@@ -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);
 
index 3cad0c5b63c2f298a4de8be45d6e50189e8b9dd4..235ed751b4139ca656e1638b6b151142966e8637 100644 (file)
@@ -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);