Background writer process - Mailing list pgsql-hackers

From Jan Wieck
Subject Background writer process
Date
Msg-id 3FB3F923.4000006@Yahoo.com
Whole thread Raw
Responses Re: Background writer process  (Kurt Roeckx <Q@ping.be>)
Re: Background writer process  (Shridhar Daithankar <shridhar_daithankar@myrealbox.com>)
List pgsql-hackers
The attached diff is another attempt for distributing the write IO.

It is a separate background process much like the checkpointer. It's
purpose is to keep the number of dirty blocks in the buffer cache at a
reasonable level and try that the buffers returned by the strategy for
replacement are allways clean. This current shot does it this way:

     - get a list of all dirty blocks in strategy replacement order
     - flush n percent of that list or a maximum of m buffers
       (whatever is smaller)
     - issue a sync()
     - sleep for x milliseconds

If there is nothing to do, it will sleep for 10 seconds before checking
again at all. It acquires a checkpoint lock during the flush, so it will
yield for a real checkpoint.

For sure the sync() needs to be replaced by the discussed fsync() of
recently written files. And I think the algorithm how much and how often
to flush can be significantly improved. But after all, this does not
change the real checkpointing at all, and the general framework having a
separate process is what we probably want.


Jan

--
#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me.                                  #
#================================================== JanWieck@Yahoo.com #
Index: src/backend/bootstrap/bootstrap.c
===================================================================
RCS file: /home/pgsql/CvsRoot/pgsql-server/src/backend/bootstrap/bootstrap.c,v
retrieving revision 1.166
diff -c -r1.166 bootstrap.c
*** src/backend/bootstrap/bootstrap.c    2003/09/02 19:04:12    1.166
--- src/backend/bootstrap/bootstrap.c    2003/11/13 18:39:51
***************
*** 428,435 ****

      BaseInit();

      if (IsUnderPostmaster)
!         InitDummyProcess();        /* needed to get LWLocks */

      /*
       * XLOG operations
--- 428,447 ----

      BaseInit();

+     /* needed to get LWLocks */
      if (IsUnderPostmaster)
!     {
!         switch (xlogop)
!         {
!             case BS_XLOG_BGWRITER:
!                 InitDummyProcess(DUMMY_PROC_BGWRITER);
!                 break;
!
!             default:
!                 InitDummyProcess(DUMMY_PROC_DEFAULT);
!                 break;
!         }
!     }

      /*
       * XLOG operations
***************
*** 451,456 ****
--- 463,473 ----
              CreateCheckPoint(false, false);
              SetSavedRedoRecPtr();        /* pass redo ptr back to
                                           * postmaster */
+             proc_exit(0);        /* done */
+
+         case BS_XLOG_BGWRITER:
+             CreateDummyCaches();
+             BufferBackgroundWriter();
              proc_exit(0);        /* done */

          case BS_XLOG_STARTUP:
Index: src/backend/catalog/index.c
===================================================================
RCS file: /home/pgsql/CvsRoot/pgsql-server/src/backend/catalog/index.c,v
retrieving revision 1.221
diff -c -r1.221 index.c
*** src/backend/catalog/index.c    2003/11/12 21:15:48    1.221
--- src/backend/catalog/index.c    2003/11/13 16:19:07
***************
*** 1043,1049 ****
          /* Send out shared cache inval if necessary */
          if (!IsBootstrapProcessingMode())
              CacheInvalidateHeapTuple(pg_class, tuple);
!         BufferSync();
      }
      else if (dirty)
      {
--- 1043,1049 ----
          /* Send out shared cache inval if necessary */
          if (!IsBootstrapProcessingMode())
              CacheInvalidateHeapTuple(pg_class, tuple);
!         BufferSync(-1, -1);
      }
      else if (dirty)
      {
Index: src/backend/commands/dbcommands.c
===================================================================
RCS file: /home/pgsql/CvsRoot/pgsql-server/src/backend/commands/dbcommands.c,v
retrieving revision 1.126
diff -c -r1.126 dbcommands.c
*** src/backend/commands/dbcommands.c    2003/11/12 21:15:50    1.126
--- src/backend/commands/dbcommands.c    2003/11/13 16:19:07
***************
*** 317,323 ****
       * up-to-date for the copy.  (We really only need to flush buffers for
       * the source database...)
       */
!     BufferSync();

      /*
       * Close virtual file descriptors so the kernel has more available for
--- 317,323 ----
       * up-to-date for the copy.  (We really only need to flush buffers for
       * the source database...)
       */
!     BufferSync(-1, -1);

      /*
       * Close virtual file descriptors so the kernel has more available for
***************
*** 454,460 ****
       * will see the new database in pg_database right away.  (They'll see
       * an uncommitted tuple, but they don't care; see GetRawDatabaseInfo.)
       */
!     BufferSync();
  }


--- 454,460 ----
       * will see the new database in pg_database right away.  (They'll see
       * an uncommitted tuple, but they don't care; see GetRawDatabaseInfo.)
       */
!     BufferSync(-1, -1);
  }


***************
*** 591,597 ****
       * (They'll see an uncommitted deletion, but they don't care; see
       * GetRawDatabaseInfo.)
       */
!     BufferSync();
  }


--- 591,597 ----
       * (They'll see an uncommitted deletion, but they don't care; see
       * GetRawDatabaseInfo.)
       */
!     BufferSync(-1, -1);
  }


***************
*** 688,694 ****
       * see an uncommitted tuple, but they don't care; see
       * GetRawDatabaseInfo.)
       */
!     BufferSync();
  }


--- 688,694 ----
       * see an uncommitted tuple, but they don't care; see
       * GetRawDatabaseInfo.)
       */
!     BufferSync(-1, -1);
  }


Index: src/backend/postmaster/postmaster.c
===================================================================
RCS file: /home/pgsql/CvsRoot/pgsql-server/src/backend/postmaster/postmaster.c,v
retrieving revision 1.348
diff -c -r1.348 postmaster.c
*** src/backend/postmaster/postmaster.c    2003/11/11 01:09:42    1.348
--- src/backend/postmaster/postmaster.c    2003/11/13 19:39:58
***************
*** 205,210 ****
--- 205,213 ----
  int            CheckPointTimeout = 300;
  int            CheckPointWarning = 30;
  time_t        LastSignalledCheckpoint = 0;
+ int            BgWriterDelay = 500;
+ int            BgWriterPercent = 0;
+ int            BgWriterMaxpages = 100;

  bool        log_hostname;        /* for ps display */
  bool        LogSourcePort;
***************
*** 224,230 ****
  /* Startup/shutdown state */
  static pid_t StartupPID = 0,
              ShutdownPID = 0,
!             CheckPointPID = 0;
  static time_t checkpointed = 0;

  #define            NoShutdown        0
--- 227,234 ----
  /* Startup/shutdown state */
  static pid_t StartupPID = 0,
              ShutdownPID = 0,
!             CheckPointPID = 0,
!             BgWriterPID = 0;
  static time_t checkpointed = 0;

  #define            NoShutdown        0
***************
*** 298,303 ****
--- 302,308 ----

  #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,1061 ****
--- 1061,1077 ----
          }

          /*
+          * 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,1483 ****
--- 1494,1506 ----
                                   backendPID)));
          return;
      }
+     else if (backendPID == BgWriterPID)
+     {
+         ereport(DEBUG2,
+                 (errmsg_internal("ignoring cancel request for bgwriter process %d",
+                                  backendPID)));
+         return;
+     }
      else if (ExecBackend)
          AttachSharedMemoryAndSemaphores();

***************
*** 1660,1665 ****
--- 1683,1695 ----
          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,1697 ****
--- 1722,1729 ----
               *
               * Wait for children to end their work and ShutdownDataBase.
               */
+             if (BgWriterPID != 0)
+                 kill(BgWriterPID, SIGTERM);
              if (Shutdown >= SmartShutdown)
                  break;
              Shutdown = SmartShutdown;
***************
*** 1724,1729 ****
--- 1756,1763 ----
               * 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,1775 ****
--- 1804,1811 ----
               * 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,1882 ****
--- 1913,1924 ----
              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,1988 ****
--- 2025,2032 ----
                  GetSavedRedoRecPtr();
              }
          }
+         else if (pid == BgWriterPID)
+             BgWriterPID = 0;
          else
              pgstat_beterm(pid);

***************
*** 1996,2001 ****
--- 2040,2046 ----
      {
          LogChildExit(LOG,
                   (pid == CheckPointPID) ? gettext("checkpoint process") :
+                  (pid == BgWriterPID) ? gettext("bgwriter process") :
                       gettext("server process"),
                       pid, exitstatus);
          ereport(LOG,
***************
*** 2044,2049 ****
--- 2089,2098 ----
          CheckPointPID = 0;
          checkpointed = 0;
      }
+     else if (pid == BgWriterPID)
+     {
+         BgWriterPID = 0;
+     }
      else
      {
          /*
***************
*** 2754,2759 ****
--- 2803,2810 ----
      }
      if (CheckPointPID != 0)
          cnt--;
+     if (BgWriterPID != 0)
+         cnt--;
      return cnt;
  }

***************
*** 2827,2832 ****
--- 2878,2886 ----
              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,2888 ****
--- 2937,2946 ----
                  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,2913 ****

          /*
           * fork failure is fatal during startup/shutdown, but there's no
!          * need to choke if a routine checkpoint fails.
           */
          if (xlop == BS_XLOG_CHECKPOINT)
              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.
       */
!     if (xlop == BS_XLOG_CHECKPOINT)
      {
          if (!(bn = (Backend *) malloc(sizeof(Backend))))
          {
--- 2953,2974 ----

          /*
           * fork failure is fatal during startup/shutdown, but there's no
!          * 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 and bgwriter processes are.
!      * They must be added to the list of backends.
       */
!     if (xlop == BS_XLOG_CHECKPOINT || xlop == BS_XLOG_BGWRITER)
      {
          if (!(bn = (Backend *) malloc(sizeof(Backend))))
          {
Index: src/backend/storage/buffer/bufmgr.c
===================================================================
RCS file: /home/pgsql/CvsRoot/pgsql-server/src/backend/storage/buffer/bufmgr.c,v
retrieving revision 1.144
diff -c -r1.144 bufmgr.c
*** src/backend/storage/buffer/bufmgr.c    2003/11/13 14:57:15    1.144
--- src/backend/storage/buffer/bufmgr.c    2003/11/13 18:41:48
***************
*** 44,49 ****
--- 44,50 ----
  #include <sys/file.h>
  #include <math.h>
  #include <signal.h>
+ #include <unistd.h>

  #include "lib/stringinfo.h"
  #include "miscadmin.h"
***************
*** 679,688 ****
  /*
   * BufferSync -- Write all dirty buffers in the pool.
   *
!  * This is called at checkpoint time and writes out all dirty shared buffers.
   */
! void
! BufferSync(void)
  {
      int            i;
      BufferDesc *bufHdr;
--- 680,690 ----
  /*
   * BufferSync -- Write all dirty buffers in the pool.
   *
!  * 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.
   */
! int
! BufferSync(int percent, int maxpages)
  {
      int            i;
      BufferDesc *bufHdr;
***************
*** 703,714 ****
       * 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);

      for (i = 0; i < num_buffer_dirty; i++)
      {
          Buffer        buffer;
--- 705,728 ----
       * have to wait until the next checkpoint.
       */
      buffer_dirty = (int *)palloc(NBuffers * sizeof(int));
!
      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,859 ****
--- 868,875 ----

      /* Pop the error context stack */
      error_context_stack = errcontext.previous;
+
+     return num_buffer_dirty;
  }

  /*
***************
*** 984,991 ****
  void
  FlushBufferPool(void)
  {
!     BufferSync();
      smgrsync();
  }

  /*
--- 1000,1064 ----
  void
  FlushBufferPool(void)
  {
!     BufferSync(-1, -1);
      smgrsync();
+ }
+
+ void
+ BufferBackgroundWriter(void)
+ {
+     if (BgWriterPercent == 0)
+         return;
+
+     for (;;)
+     {
+         int n;
+
+         /*
+          * Acquire a CheckpointLock to suspend background writing
+          * while a real checkpoint is going on.
+          */
+         while (!LWLockConditionalAcquire(CheckpointLock, LW_EXCLUSIVE))
+         {
+             if (InterruptPending)
+                 return;
+             sleep(1);
+         }
+
+         /*
+          * Call BufferSync() with instructions to keep just the
+          * LRU heads clean.
+          */
+         n = BufferSync(BgWriterPercent, BgWriterMaxpages);
+
+         /*
+          * Release the CheckpointLock
+          */
+         LWLockRelease(CheckpointLock);
+
+         /*
+          * 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;
+
+         /*
+          * If there was nothing to flush, sleep for 10 seconds. If there
+          * was, pg_fsync() recently written files and nap.
+          */
+         if (n > 0)
+         {
+             /*
+              * TODO: This sync must be replaced with calls to
+              *       pg_fdatasync() for recently written files.
+              */
+             sync();
+             PG_DELAY(BgWriterDelay);
+         }
+         else
+             sleep(10);
+     }
  }

  /*
Index: src/backend/storage/buffer/freelist.c
===================================================================
RCS file: /home/pgsql/CvsRoot/pgsql-server/src/backend/storage/buffer/freelist.c,v
retrieving revision 1.34
diff -c -r1.34 freelist.c
*** src/backend/storage/buffer/freelist.c    2003/11/13 14:57:15    1.34
--- src/backend/storage/buffer/freelist.c    2003/11/13 19:45:32
***************
*** 190,197 ****
--- 190,217 ----
          if (StrategyControl->stat_report + BufferStrategyStatInterval < 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,220 ****
--- 235,242 ----
                      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: src/backend/storage/lmgr/proc.c
===================================================================
RCS file: /home/pgsql/CvsRoot/pgsql-server/src/backend/storage/lmgr/proc.c,v
retrieving revision 1.136
diff -c -r1.136 proc.c
*** src/backend/storage/lmgr/proc.c    2003/10/16 20:59:35    1.136
--- src/backend/storage/lmgr/proc.c    2003/11/13 18:03:24
***************
*** 71,76 ****
--- 71,77 ----
  static PROC_HDR *ProcGlobal = NULL;

  static PGPROC *DummyProc = NULL;
+ static int    dummy_proc_type = -1;

  static bool waitingForLock = false;
  static bool waitingForSignal = false;
***************
*** 163,176 ****
           * processes, too.    This does not get linked into the freeProcs
           * list.
           */
!         DummyProc = (PGPROC *) ShmemAlloc(sizeof(PGPROC));
          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);

          /* Create ProcStructLock spinlock, too */
          ProcStructLock = (slock_t *) ShmemAlloc(sizeof(slock_t));
--- 164,180 ----
           * processes, too.    This does not get linked into the freeProcs
           * list.
           */
!         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) * 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,277 ****
   * sema that are assigned are the extra ones created during InitProcGlobal.
   */
  void
! InitDummyProcess(void)
  {
      /*
       * ProcGlobal should be set by a previous call to InitProcGlobal (we
       * inherit this by fork() from the postmaster).
--- 274,283 ----
   * sema that are assigned are the extra ones created during InitProcGlobal.
   */
  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,293 ****
      if (MyProc != NULL)
          elog(ERROR, "you already exist");

      /*
!      * 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;

      /*
       * Initialize all fields of MyProc, except MyProc->sem which was set
--- 288,304 ----
      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
       */
!     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,316 ****
      /*
       * Arrange to clean up at process exit.
       */
!     on_shmem_exit(DummyProcKill, 0);

      /*
       * We might be reusing a semaphore that belonged to a failed process.
--- 321,327 ----
      /*
       * Arrange to clean up at process exit.
       */
!     on_shmem_exit(DummyProcKill, proctype);

      /*
       * We might be reusing a semaphore that belonged to a failed process.
***************
*** 446,453 ****
  static void
  DummyProcKill(void)
  {
!     Assert(MyProc != NULL && MyProc == DummyProc);

      /* Release any LW locks I am holding */
      LWLockReleaseAll();

--- 457,470 ----
  static void
  DummyProcKill(void)
  {
!     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,468 ****
--- 480,487 ----

      /* PGPROC struct isn't mine anymore */
      MyProc = NULL;
+
+     dummy_proc_type = -1;
  }


Index: src/backend/utils/misc/guc.c
===================================================================
RCS file: /home/pgsql/CvsRoot/pgsql-server/src/backend/utils/misc/guc.c,v
retrieving revision 1.169
diff -c -r1.169 guc.c
*** src/backend/utils/misc/guc.c    2003/11/13 14:57:15    1.169
--- src/backend/utils/misc/guc.c    2003/11/13 19:40:10
***************
*** 74,79 ****
--- 74,82 ----
  extern int    CommitSiblings;
  extern char *preload_libraries_string;
  extern int    BufferStrategyStatInterval;
+ extern int    BgWriterDelay;
+ extern int    BgWriterPercent;
+ extern int    BgWriterMaxpages;

  #ifdef HAVE_SYSLOG
  extern char *Syslog_facility;
***************
*** 1198,1203 ****
--- 1201,1233 ----
          },
          &BufferStrategyStatInterval,
          0, 0, 600, NULL, NULL
+     },
+
+     {
+         {"bgwriter_delay", PGC_SIGHUP, RESOURCES,
+             gettext_noop("Background writer sleep time between rounds in milliseconds"),
+             NULL
+         },
+         &BgWriterDelay,
+         500, 10, 5000, NULL, NULL
+     },
+
+     {
+         {"bgwriter_percent", PGC_SIGHUP, RESOURCES,
+             gettext_noop("Background writer percentage of dirty buffers to flush per round"),
+             NULL
+         },
+         &BgWriterPercent,
+         0, 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 */
Index: src/backend/utils/misc/postgresql.conf.sample
===================================================================
RCS file: /home/pgsql/CvsRoot/pgsql-server/src/backend/utils/misc/postgresql.conf.sample,v
retrieving revision 1.95
diff -c -r1.95 postgresql.conf.sample
*** src/backend/utils/misc/postgresql.conf.sample    2003/11/13 14:57:15    1.95
--- src/backend/utils/misc/postgresql.conf.sample    2003/11/13 21:20:03
***************
*** 60,65 ****
--- 60,70 ----
  #vacuum_mem = 8192        # min 1024, size in KB
  #buffer_strategy_status_interval = 0    # 0-600 seconds

+ # - Background writer -
+ #bgwriter_delay = 500        # 10-5000 milliseconds
+ #bgwriter_percent = 0        # 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: src/include/bootstrap/bootstrap.h
===================================================================
RCS file: /home/pgsql/CvsRoot/pgsql-server/src/include/bootstrap/bootstrap.h,v
retrieving revision 1.31
diff -c -r1.31 bootstrap.h
*** src/include/bootstrap/bootstrap.h    2003/08/04 02:40:10    1.31
--- src/include/bootstrap/bootstrap.h    2003/11/13 16:19:07
***************
*** 59,64 ****
  #define BS_XLOG_BOOTSTRAP    1
  #define BS_XLOG_STARTUP        2
  #define BS_XLOG_CHECKPOINT    3
! #define BS_XLOG_SHUTDOWN    4

  #endif   /* BOOTSTRAP_H */
--- 59,65 ----
  #define BS_XLOG_BOOTSTRAP    1
  #define BS_XLOG_STARTUP        2
  #define BS_XLOG_CHECKPOINT    3
! #define BS_XLOG_BGWRITER    4
! #define BS_XLOG_SHUTDOWN    5

  #endif   /* BOOTSTRAP_H */
Index: src/include/storage/bufmgr.h
===================================================================
RCS file: /home/pgsql/CvsRoot/pgsql-server/src/include/storage/bufmgr.h,v
retrieving revision 1.70
diff -c -r1.70 bufmgr.h
*** src/include/storage/bufmgr.h    2003/08/10 19:48:08    1.70
--- src/include/storage/bufmgr.h    2003/11/13 17:12:15
***************
*** 37,42 ****
--- 37,47 ----
  extern DLLIMPORT Block *LocalBufferBlockPointers;
  extern long *LocalRefCount;

+ /* in postmaster.c ... they don't belong here */
+ extern int    BgWriterDelay;
+ extern int    BgWriterPercent;
+ extern int    BgWriterMaxpages;
+
  /* special pageno for bget */
  #define P_NEW    InvalidBlockNumber        /* grow the file to get a new page */

***************
*** 186,192 ****
  extern void AbortBufferIO(void);

  extern void BufmgrCommit(void);
! extern void BufferSync(void);

  extern void InitLocalBuffer(void);

--- 191,198 ----
  extern void AbortBufferIO(void);

  extern void BufmgrCommit(void);
! extern int    BufferSync(int percent, int maxpages);
! extern void BufferBackgroundWriter(void);

  extern void InitLocalBuffer(void);

Index: src/include/storage/proc.h
===================================================================
RCS file: /home/pgsql/CvsRoot/pgsql-server/src/include/storage/proc.h,v
retrieving revision 1.64
diff -c -r1.64 proc.h
*** src/include/storage/proc.h    2003/08/04 02:40:15    1.64
--- src/include/storage/proc.h    2003/11/13 17:55:02
***************
*** 86,91 ****
--- 86,96 ----
  } 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,103 ****
  extern int    ProcGlobalSemas(int maxBackends);
  extern void InitProcGlobal(int maxBackends);
  extern void InitProcess(void);
! extern void InitDummyProcess(void);
  extern void ProcReleaseLocks(bool isCommit);

  extern void ProcQueueInit(PROC_QUEUE *queue);
--- 102,108 ----
  extern int    ProcGlobalSemas(int maxBackends);
  extern void InitProcGlobal(int maxBackends);
  extern void InitProcess(void);
! extern void InitDummyProcess(int proctype);
  extern void ProcReleaseLocks(bool isCommit);

  extern void ProcQueueInit(PROC_QUEUE *queue);

pgsql-hackers by date:

Previous
From: James Robinson
Date:
Subject: Re: [GENERAL] Proposal for a cascaded master-slave replication system
Next
From: Rod Taylor
Date:
Subject: Re: ALTER TABLE modifications