diff -cpr HEAD/doc/src/sgml/config.sgml LDC_v4/doc/src/sgml/config.sgml
*** HEAD/doc/src/sgml/config.sgml Tue Apr 17 03:29:50 2007
--- LDC_v4/doc/src/sgml/config.sgml Thu Apr 19 11:32:50 2007
*************** SET ENABLE_SEQSCAN TO OFF;
*** 1565,1570 ****
--- 1565,1619 ----
+
+ checkpoint_write_percent (floating point)
+
+ checkpoint_write_percent> configuration parameter
+
+
+
+ To spread works in checkpoints, each checkpoint spends the specified
+ time and delays to write out all dirty buffers in the shared buffer
+ pool. The default value is 50.0 (50% of checkpoint_timeout>).
+ This parameter can only be set in the postgresql.conf>
+ file or on the server command line.
+
+
+
+
+
+ checkpoint_nap_percent (floating point)
+
+ checkpoint_nap_percent> configuration parameter
+
+
+
+ Specifies the delay between writing out all dirty buffers and flushing
+ all modified files. Make the kernel's disk writer to flush dirty buffers
+ during this time in order to reduce works in the next flushing phase.
+ The default value is 10.0 (10% of checkpoint_timeout>).
+ This parameter can only be set in the postgresql.conf>
+ file or on the server command line.
+
+
+
+
+
+ checkpoint_sync_percent (floating point)
+
+ checkpoint_sync_percent> configuration parameter
+
+
+
+ To spread works in checkpoints, each checkpoint spends the specified
+ time and delays to flush all modified files.
+ The default value is 20.0 (20% of checkpoint_timeout>).
+ This parameter can only be set in the postgresql.conf>
+ file or on the server command line.
+
+
+
+
checkpoint_warning (integer)
diff -cpr HEAD/src/backend/access/transam/xlog.c LDC_v4/src/backend/access/transam/xlog.c
*** HEAD/src/backend/access/transam/xlog.c Wed Apr 4 01:34:35 2007
--- LDC_v4/src/backend/access/transam/xlog.c Thu Apr 19 11:32:50 2007
*************** static void readRecoveryCommandFile(void
*** 399,405 ****
static void exitArchiveRecovery(TimeLineID endTLI,
uint32 endLogId, uint32 endLogSeg);
static bool recoveryStopsHere(XLogRecord *record, bool *includeThis);
! static void CheckPointGuts(XLogRecPtr checkPointRedo);
static bool XLogCheckBuffer(XLogRecData *rdata, bool doPageWrites,
XLogRecPtr *lsn, BkpBlock *bkpb);
--- 399,405 ----
static void exitArchiveRecovery(TimeLineID endTLI,
uint32 endLogId, uint32 endLogSeg);
static bool recoveryStopsHere(XLogRecord *record, bool *includeThis);
! static void CheckPointGuts(XLogRecPtr checkPointRedo, bool immediate);
static bool XLogCheckBuffer(XLogRecData *rdata, bool doPageWrites,
XLogRecPtr *lsn, BkpBlock *bkpb);
*************** GetRedoRecPtr(void)
*** 5274,5279 ****
--- 5274,5296 ----
}
/*
+ * GetInsertRecPtr -- Returns the current insert position.
+ */
+ XLogRecPtr
+ GetInsertRecPtr(void)
+ {
+ volatile XLogCtlData *xlogctl = XLogCtl;
+ XLogCtlInsert *Insert = &XLogCtl->Insert;
+ XLogRecPtr recptr;
+
+ SpinLockAcquire(&xlogctl->info_lck);
+ INSERT_RECPTR(recptr, Insert, Insert->curridx);
+ SpinLockRelease(&xlogctl->info_lck);
+
+ return recptr;
+ }
+
+ /*
* Get the time of the last xlog segment switch
*/
time_t
*************** CreateCheckPoint(bool shutdown, bool for
*** 5546,5552 ****
*/
END_CRIT_SECTION();
! CheckPointGuts(checkPoint.redo);
START_CRIT_SECTION();
--- 5563,5569 ----
*/
END_CRIT_SECTION();
! CheckPointGuts(checkPoint.redo, force);
START_CRIT_SECTION();
*************** CreateCheckPoint(bool shutdown, bool for
*** 5652,5663 ****
* recovery restartpoints.
*/
static void
! CheckPointGuts(XLogRecPtr checkPointRedo)
{
CheckPointCLOG();
CheckPointSUBTRANS();
CheckPointMultiXact();
! FlushBufferPool(); /* performs all required fsyncs */
/* We deliberately delay 2PC checkpointing as long as possible */
CheckPointTwoPhase(checkPointRedo);
}
--- 5669,5680 ----
* recovery restartpoints.
*/
static void
! CheckPointGuts(XLogRecPtr checkPointRedo, bool immediate)
{
CheckPointCLOG();
CheckPointSUBTRANS();
CheckPointMultiXact();
! FlushBufferPool(immediate); /* performs all required fsyncs */
/* We deliberately delay 2PC checkpointing as long as possible */
CheckPointTwoPhase(checkPointRedo);
}
*************** RecoveryRestartPoint(const CheckPoint *c
*** 5706,5712 ****
/*
* OK, force data out to disk
*/
! CheckPointGuts(checkPoint->redo);
/*
* Update pg_control so that any subsequent crash will restart from this
--- 5723,5729 ----
/*
* OK, force data out to disk
*/
! CheckPointGuts(checkPoint->redo, true);
/*
* Update pg_control so that any subsequent crash will restart from this
diff -cpr HEAD/src/backend/commands/dbcommands.c LDC_v4/src/backend/commands/dbcommands.c
*** HEAD/src/backend/commands/dbcommands.c Fri Apr 13 00:04:35 2007
--- LDC_v4/src/backend/commands/dbcommands.c Thu Apr 19 11:32:50 2007
*************** createdb(const CreatedbStmt *stmt)
*** 400,406 ****
* up-to-date for the copy. (We really only need to flush buffers for the
* source database, but bufmgr.c provides no API for that.)
*/
! BufferSync();
/*
* Once we start copying subdirectories, we need to be able to clean 'em
--- 400,406 ----
* up-to-date for the copy. (We really only need to flush buffers for the
* source database, but bufmgr.c provides no API for that.)
*/
! BufferSync(true);
/*
* Once we start copying subdirectories, we need to be able to clean 'em
*************** dbase_redo(XLogRecPtr lsn, XLogRecord *r
*** 1417,1423 ****
* up-to-date for the copy. (We really only need to flush buffers for
* the source database, but bufmgr.c provides no API for that.)
*/
! BufferSync();
/*
* Copy this subdirectory to the new location
--- 1417,1423 ----
* up-to-date for the copy. (We really only need to flush buffers for
* the source database, but bufmgr.c provides no API for that.)
*/
! BufferSync(true);
/*
* Copy this subdirectory to the new location
diff -cpr HEAD/src/backend/postmaster/bgwriter.c LDC_v4/src/backend/postmaster/bgwriter.c
*** HEAD/src/backend/postmaster/bgwriter.c Sat Mar 31 03:34:55 2007
--- LDC_v4/src/backend/postmaster/bgwriter.c Thu Apr 19 12:52:06 2007
***************
*** 44,49 ****
--- 44,50 ----
#include "postgres.h"
#include
+ #include
#include
#include
*************** typedef struct
*** 117,122 ****
--- 118,124 ----
sig_atomic_t ckpt_failed; /* advances when checkpoint fails */
sig_atomic_t ckpt_time_warn; /* warn if too soon since last ckpt? */
+ sig_atomic_t ckpt_force; /* any waiter for the checkpoint? */
int num_requests; /* current # of requests */
int max_requests; /* allocated array size */
*************** PgStat_MsgBgWriter BgWriterStats;
*** 138,143 ****
--- 140,148 ----
int BgWriterDelay = 200;
int CheckPointTimeout = 300;
int CheckPointWarning = 30;
+ double checkpoint_write_percent = 50.0;
+ double checkpoint_nap_percent = 10.0;
+ double checkpoint_sync_percent = 20.0;
/*
* Flags set by interrupt handlers for later service in the main loop.
*************** static bool am_bg_writer = false;
*** 153,162 ****
--- 158,175 ----
static bool ckpt_active = false;
+ static time_t ckpt_start_time;
+ static XLogRecPtr ckpt_start_recptr;
+ static double ckpt_progress_at_sync_start;
+
static time_t last_checkpoint_time;
static time_t last_xlog_switch_time;
+ static void CheckArchiveTimeout(void);
+ static void BgWriterNap(long msec);
+ static bool NextCheckpointRequested(void);
+ static double GetCheckpointProgress(void);
static void bg_quickdie(SIGNAL_ARGS);
static void BgSigHupHandler(SIGNAL_ARGS);
static void ReqCheckpointHandler(SIGNAL_ARGS);
*************** BackgroundWriterMain(void)
*** 343,349 ****
bool force_checkpoint = false;
time_t now;
int elapsed_secs;
- long udelay;
/*
* Emergency bailout if postmaster has died. This is to avoid the
--- 356,361 ----
*************** BackgroundWriterMain(void)
*** 362,374 ****
got_SIGHUP = false;
ProcessConfigFile(PGC_SIGHUP);
}
- if (checkpoint_requested)
- {
- checkpoint_requested = false;
- do_checkpoint = true;
- force_checkpoint = true;
- BgWriterStats.m_requested_checkpoints++;
- }
if (shutdown_requested)
{
/*
--- 374,379 ----
*************** BackgroundWriterMain(void)
*** 389,399 ****
*/
now = time(NULL);
elapsed_secs = now - last_checkpoint_time;
! if (elapsed_secs >= CheckPointTimeout)
{
do_checkpoint = true;
! if (!force_checkpoint)
! BgWriterStats.m_timed_checkpoints++;
}
/*
--- 394,410 ----
*/
now = time(NULL);
elapsed_secs = now - last_checkpoint_time;
! if (checkpoint_requested)
! {
! checkpoint_requested = false;
! force_checkpoint = BgWriterShmem->ckpt_force;
! do_checkpoint = true;
! BgWriterStats.m_requested_checkpoints++;
! }
! else if (elapsed_secs >= CheckPointTimeout)
{
do_checkpoint = true;
! BgWriterStats.m_timed_checkpoints++;
}
/*
*************** BackgroundWriterMain(void)
*** 416,428 ****
--- 427,444 ----
elapsed_secs),
errhint("Consider increasing the configuration parameter \"checkpoint_segments\".")));
BgWriterShmem->ckpt_time_warn = false;
+ BgWriterShmem->ckpt_force = false;
/*
* Indicate checkpoint start to any waiting backends.
*/
ckpt_active = true;
+ elog(DEBUG1, "CHECKPOINT: start");
BgWriterShmem->ckpt_started++;
+ ckpt_start_time = now;
+ ckpt_start_recptr = GetInsertRecPtr();
+ ckpt_progress_at_sync_start = 0;
CreateCheckPoint(false, force_checkpoint);
/*
*************** BackgroundWriterMain(void)
*** 435,440 ****
--- 451,457 ----
* Indicate checkpoint completion to any waiting backends.
*/
BgWriterShmem->ckpt_done = BgWriterShmem->ckpt_started;
+ elog(DEBUG1, "CHECKPOINT: end");
ckpt_active = false;
/*
*************** BackgroundWriterMain(void)
*** 451,458 ****
* Check for archive_timeout, if so, switch xlog files. First we do a
* quick check using possibly-stale local state.
*/
! if (XLogArchiveTimeout > 0 &&
! (int) (now - last_xlog_switch_time) >= XLogArchiveTimeout)
{
/*
* Update local state ... note that last_xlog_switch_time is the
--- 468,495 ----
* Check for archive_timeout, if so, switch xlog files. First we do a
* quick check using possibly-stale local state.
*/
! CheckArchiveTimeout();
!
! /* Nap for the configured time. */
! BgWriterNap(0);
! }
! }
!
! /*
! * CheckArchiveTimeout -- check for archive_timeout
! */
! static void
! CheckArchiveTimeout(void)
! {
! time_t now;
!
! if (XLogArchiveTimeout <= 0)
! return;
!
! now = time(NULL);
! if ((int) (now - last_xlog_switch_time) < XLogArchiveTimeout)
! return;
!
{
/*
* Update local state ... note that last_xlog_switch_time is the
*************** BackgroundWriterMain(void)
*** 462,471 ****
last_xlog_switch_time = Max(last_xlog_switch_time, last_time);
- /* if we did a checkpoint, 'now' might be stale too */
- if (do_checkpoint)
- now = time(NULL);
-
/* Now we can do the real check */
if ((int) (now - last_xlog_switch_time) >= XLogArchiveTimeout)
{
--- 499,504 ----
*************** BackgroundWriterMain(void)
*** 490,495 ****
--- 523,540 ----
last_xlog_switch_time = now;
}
}
+ }
+
+ /*
+ * BgWriterNap -- short nap in bgwriter
+ *
+ * Nap for the shorter time of the configured time or the mdelay unless
+ * it is zero. Return the actual nap time in msec.
+ */
+ static void
+ BgWriterNap(long mdelay)
+ {
+ long udelay;
/*
* Send off activity statistics to the stats collector
*************** BackgroundWriterMain(void)
*** 515,520 ****
--- 560,569 ----
else
udelay = 10000000L; /* Ten seconds */
+ /* Clamp the delay to the upper bound. */
+ if (mdelay > 0)
+ udelay = Min(udelay, mdelay * 1000L);
+
while (udelay > 999999L)
{
if (got_SIGHUP || checkpoint_requested || shutdown_requested)
*************** BackgroundWriterMain(void)
*** 526,534 ****
--- 575,727 ----
if (!(got_SIGHUP || checkpoint_requested || shutdown_requested))
pg_usleep(udelay);
+ }
+
+ /*
+ * CheckpointWriteDelay -- periodical sleep in checkpoint write phase
+ */
+ void
+ CheckpointWriteDelay(double progress)
+ {
+ if (!ckpt_active || checkpoint_write_percent <= 0)
+ return;
+
+ elog(DEBUG1, "CheckpointWriteDelay: progress=%.3f", progress);
+
+ if (!NextCheckpointRequested() &&
+ progress * checkpoint_write_percent > GetCheckpointProgress())
+ {
+ AbsorbFsyncRequests();
+ BgLruBufferSync();
+ BgWriterNap(0);
}
}
+ /*
+ * CheckpointNapDelay -- sleep between checkpoint write and sync phases
+ */
+ void
+ CheckpointNapDelay(bool immediate)
+ {
+ if (!ckpt_active)
+ return;
+
+ if (!immediate)
+ {
+ double ckpt_progress_at_nap_start = GetCheckpointProgress();
+ double remain;
+
+ elog(DEBUG1, "CheckpointNapDelay: %f%%", checkpoint_nap_percent);
+
+ while (!NextCheckpointRequested() &&
+ (remain = ckpt_progress_at_nap_start + checkpoint_nap_percent
+ - GetCheckpointProgress()) > 0)
+ {
+ long msec = (long) (CheckPointTimeout * 1000.0 * remain / 100.0);
+
+ AbsorbFsyncRequests();
+ BgLruBufferSync();
+ BgWriterNap(msec);
+ }
+ }
+
+ ckpt_progress_at_sync_start = GetCheckpointProgress();
+ }
+
+ /*
+ * CheckpointSyncDelay -- periodical sleep in checkpoint sync phase
+ */
+ void
+ CheckpointSyncDelay(double progress)
+ {
+ double remain;
+
+ if (!ckpt_active || checkpoint_sync_percent <= 0)
+ return;
+
+ elog(DEBUG1, "CheckpointSyncDelay: progress=%.3f", progress);
+
+ while (!NextCheckpointRequested() &&
+ (remain = ckpt_progress_at_sync_start + progress *
+ checkpoint_sync_percent - GetCheckpointProgress()) > 0)
+ {
+ long msec = (long) (CheckPointTimeout * 1000.0 * remain / 100.0);
+
+ AbsorbFsyncRequests();
+ BgLruBufferSync();
+ BgWriterNap(msec);
+ }
+ }
+
+ /*
+ * NextCheckpointRequested -- true iff the next checkpoint is requested
+ *
+ * Do also check any signals received recently.
+ */
+ static bool
+ NextCheckpointRequested(void)
+ {
+ if (!am_bg_writer || !ckpt_active)
+ return true;
+
+ /* Don't sleep this checkpoint if next checkpoint is requested. */
+ if (checkpoint_requested || shutdown_requested ||
+ (time(NULL) - ckpt_start_time >= CheckPointTimeout))
+ {
+ elog(DEBUG1, "NextCheckpointRequested");
+ checkpoint_requested = true;
+ return true;
+ }
+
+ /* Process reload signals. */
+ if (got_SIGHUP)
+ {
+ got_SIGHUP = false;
+ ProcessConfigFile(PGC_SIGHUP);
+ }
+
+ /* Check for archive_timeout and nap for the configured time. */
+ CheckArchiveTimeout();
+
+ return false;
+ }
+
+ /*
+ * GetCheckpointProgress -- progress of the current checkpoint in range 0-100%
+ */
+ static double
+ GetCheckpointProgress(void)
+ {
+ struct timeval now;
+ XLogRecPtr recptr;
+ double progress_in_time,
+ progress_in_xlog;
+ double percent;
+
+ Assert(ckpt_active);
+
+ /* coordinate the progress with checkpoint_timeout */
+ gettimeofday(&now, NULL);
+ progress_in_time = ((double) (now.tv_sec - ckpt_start_time) +
+ now.tv_usec / 1000000.0) / CheckPointTimeout;
+
+ /* coordinate the progress with checkpoint_segments */
+ recptr = GetInsertRecPtr();
+ progress_in_xlog =
+ ((double) (recptr.xlogid - ckpt_start_recptr.xlogid) * XLogSegsPerFile +
+ (double) (recptr.xrecoff - ckpt_start_recptr.xrecoff) / XLogSegSize) /
+ CheckPointSegments;
+
+ percent = 100.0 * Max(progress_in_time, progress_in_xlog);
+ if (percent > 100.0)
+ percent = 100.0;
+
+ elog(DEBUG2, "GetCheckpointProgress : time=%.3f, xlog=%.3f",
+ progress_in_time, progress_in_xlog);
+
+ return percent;
+ }
+
/* --------------------------------
* signal handler routines
*************** RequestCheckpoint(bool waitforit, bool w
*** 668,673 ****
--- 861,868 ----
/* Set warning request flag if appropriate */
if (warnontime)
bgs->ckpt_time_warn = true;
+ if (waitforit)
+ bgs->ckpt_force = true;
/*
* Send signal to request checkpoint. When waitforit is false, we
diff -cpr HEAD/src/backend/storage/buffer/bufmgr.c LDC_v4/src/backend/storage/buffer/bufmgr.c
*** HEAD/src/backend/storage/buffer/bufmgr.c Sat Mar 31 03:34:55 2007
--- LDC_v4/src/backend/storage/buffer/bufmgr.c Thu Apr 19 11:32:50 2007
*************** UnpinBuffer(volatile BufferDesc *buf, bo
*** 947,957 ****
* This is called at checkpoint time to write out all dirty shared buffers.
*/
void
! BufferSync(void)
{
int buf_id;
int num_to_scan;
int absorb_counter;
/*
* Find out where to start the circular scan.
--- 947,960 ----
* This is called at checkpoint time to write out all dirty shared buffers.
*/
void
! BufferSync(bool immediate)
{
int buf_id;
int num_to_scan;
+ int num_written;
int absorb_counter;
+ int writes_per_nap = (bgwriter_all_maxpages > 0 ?
+ bgwriter_all_maxpages : WRITES_PER_ABSORB);
/*
* Find out where to start the circular scan.
*************** BufferSync(void)
*** 965,970 ****
--- 968,974 ----
* Loop over all buffers.
*/
num_to_scan = NBuffers;
+ num_written = 0;
absorb_counter = WRITES_PER_ABSORB;
while (num_to_scan-- > 0)
{
*************** BufferSync(void)
*** 972,977 ****
--- 976,988 ----
{
BgWriterStats.m_buf_written_checkpoints++;
+ if (!immediate && ++num_written >= writes_per_nap)
+ {
+ num_written = 0;
+ CheckpointWriteDelay(
+ (double) (NBuffers - num_to_scan) / NBuffers);
+ }
+
/*
* If in bgwriter, absorb pending fsync requests after each
* WRITES_PER_ABSORB write operations, to prevent overflow of the
*************** void
*** 998,1004 ****
BgBufferSync(void)
{
static int buf_id1 = 0;
- int buf_id2;
int num_to_scan;
int num_written;
--- 1009,1014 ----
*************** BgBufferSync(void)
*** 1044,1049 ****
--- 1054,1072 ----
BgWriterStats.m_buf_written_all += num_written;
}
+ BgLruBufferSync();
+ }
+
+ /*
+ * BgLruBufferSync -- Write out some lru dirty buffers in the pool.
+ */
+ void
+ BgLruBufferSync(void)
+ {
+ int buf_id2;
+ int num_to_scan;
+ int num_written;
+
/*
* This loop considers only unpinned buffers close to the clock sweep
* point.
*************** PrintBufferLeakWarning(Buffer buffer)
*** 1286,1295 ****
* flushed.
*/
void
! FlushBufferPool(void)
{
! BufferSync();
! smgrsync();
}
--- 1309,1324 ----
* flushed.
*/
void
! FlushBufferPool(bool immediate)
{
! elog(DEBUG1, "CHECKPOINT: write phase");
! BufferSync(immediate || checkpoint_write_percent <= 0);
!
! elog(DEBUG1, "CHECKPOINT: nap phase");
! CheckpointNapDelay(immediate || checkpoint_nap_percent <= 0);
!
! elog(DEBUG1, "CHECKPOINT: sync phase");
! smgrsync(immediate || checkpoint_sync_percent <= 0);
}
diff -cpr HEAD/src/backend/storage/smgr/md.c LDC_v4/src/backend/storage/smgr/md.c
*** HEAD/src/backend/storage/smgr/md.c Fri Apr 13 02:10:55 2007
--- LDC_v4/src/backend/storage/smgr/md.c Thu Apr 19 12:28:18 2007
*************** mdimmedsync(SMgrRelation reln)
*** 863,875 ****
* mdsync() -- Sync previous writes to stable storage.
*/
void
! mdsync(void)
{
static bool mdsync_in_progress = false;
HASH_SEQ_STATUS hstat;
PendingOperationEntry *entry;
int absorb_counter;
/*
* This is only called during checkpoints, and checkpoints should only
--- 863,877 ----
* mdsync() -- Sync previous writes to stable storage.
*/
void
! mdsync(bool immediate)
{
static bool mdsync_in_progress = false;
HASH_SEQ_STATUS hstat;
PendingOperationEntry *entry;
int absorb_counter;
+ double progress = 0; /* progress in bytes */
+ double total = 0; /* total filesize to fsync in bytes */
/*
* This is only called during checkpoints, and checkpoints should only
*************** mdsync(void)
*** 910,922 ****
* From a performance point of view it doesn't matter anyway, as this
* path will never be taken in a system that's functioning normally.
*/
! if (mdsync_in_progress)
{
/* prior try failed, so update any stale cycle_ctr values */
hash_seq_init(&hstat, pendingOpsTable);
while ((entry = (PendingOperationEntry *) hash_seq_search(&hstat)) != NULL)
{
! entry->cycle_ctr = mdsync_cycle_ctr;
}
}
--- 912,940 ----
* From a performance point of view it doesn't matter anyway, as this
* path will never be taken in a system that's functioning normally.
*/
! if (mdsync_in_progress || (enableFsync && !immediate))
{
/* prior try failed, so update any stale cycle_ctr values */
hash_seq_init(&hstat, pendingOpsTable);
while ((entry = (PendingOperationEntry *) hash_seq_search(&hstat)) != NULL)
{
! if (mdsync_in_progress)
! entry->cycle_ctr = mdsync_cycle_ctr;
! else if (enableFsync && !immediate && !entry->canceled)
! {
! SMgrRelation reln;
! MdfdVec *seg;
! long len;
!
! /* Sum up lengths of the files on non-immediate case. */
! reln = smgropen(entry->tag.rnode);
! seg = _mdfd_getseg(reln,
! entry->tag.segno * ((BlockNumber) RELSEG_SIZE),
! true, EXTENSION_RETURN_NULL);
! if (seg != NULL &&
! (len = FileSeek(seg->mdfd_vfd, 0, SEEK_END)) >= 0)
! total += len;
! }
}
}
*************** mdsync(void)
*** 931,936 ****
--- 949,956 ----
hash_seq_init(&hstat, pendingOpsTable);
while ((entry = (PendingOperationEntry *) hash_seq_search(&hstat)) != NULL)
{
+ long seglen = -1;
+
/*
* If the entry is new then don't process it this time. Note that
* "continue" bypasses the hash-remove call at the bottom of the loop.
*************** mdsync(void)
*** 1010,1016 ****
--- 1030,1039 ----
false, EXTENSION_RETURN_NULL);
if (seg != NULL &&
FileSync(seg->mdfd_vfd) >= 0)
+ {
+ seglen = FileSeek(seg->mdfd_vfd, 0, SEEK_END);
break; /* success; break out of retry loop */
+ }
/*
* XXX is there any point in allowing more than one retry?
*************** mdsync(void)
*** 1054,1059 ****
--- 1077,1091 ----
if (hash_search(pendingOpsTable, &entry->tag,
HASH_REMOVE, NULL) == NULL)
elog(ERROR, "pendingOpsTable corrupted");
+
+ /*
+ * Nap some seconds according to the file size.
+ */
+ if (seglen > 0 && total > 0)
+ {
+ progress += seglen;
+ CheckpointSyncDelay(progress / total);
+ }
} /* end loop over hashtable entries */
/* Flag successful completion of mdsync */
diff -cpr HEAD/src/backend/storage/smgr/smgr.c LDC_v4/src/backend/storage/smgr/smgr.c
*** HEAD/src/backend/storage/smgr/smgr.c Sat Jan 6 07:19:39 2007
--- LDC_v4/src/backend/storage/smgr/smgr.c Thu Apr 19 11:32:50 2007
***************
*** 21,26 ****
--- 21,27 ----
#include "access/xlogutils.h"
#include "commands/tablespace.h"
#include "pgstat.h"
+ #include "postmaster/bgwriter.h"
#include "storage/bufmgr.h"
#include "storage/freespace.h"
#include "storage/ipc.h"
*************** typedef struct f_smgr
*** 57,63 ****
void (*smgr_immedsync) (SMgrRelation reln);
void (*smgr_commit) (void); /* may be NULL */
void (*smgr_abort) (void); /* may be NULL */
! void (*smgr_sync) (void); /* may be NULL */
} f_smgr;
--- 58,64 ----
void (*smgr_immedsync) (SMgrRelation reln);
void (*smgr_commit) (void); /* may be NULL */
void (*smgr_abort) (void); /* may be NULL */
! void (*smgr_sync) (bool immediate); /* may be NULL */
} f_smgr;
*************** smgrabort(void)
*** 781,794 ****
* smgrsync() -- Sync files to disk at checkpoint time.
*/
void
! smgrsync(void)
{
int i;
for (i = 0; i < NSmgr; i++)
{
if (smgrsw[i].smgr_sync)
! (*(smgrsw[i].smgr_sync)) ();
}
}
--- 782,795 ----
* smgrsync() -- Sync files to disk at checkpoint time.
*/
void
! smgrsync(bool immediate)
{
int i;
for (i = 0; i < NSmgr; i++)
{
if (smgrsw[i].smgr_sync)
! (*(smgrsw[i].smgr_sync))(immediate);
}
}
diff -cpr HEAD/src/backend/utils/misc/guc.c LDC_v4/src/backend/utils/misc/guc.c
*** HEAD/src/backend/utils/misc/guc.c Tue Apr 17 03:29:55 2007
--- LDC_v4/src/backend/utils/misc/guc.c Thu Apr 19 11:32:50 2007
*************** static struct config_real ConfigureNames
*** 1821,1826 ****
--- 1821,1853 ----
0.1, 0.0, 100.0, NULL, NULL
},
+ {
+ {"checkpoint_write_percent", PGC_SIGHUP, WAL_CHECKPOINTS,
+ gettext_noop("Sets the duration percentage of write phase in checkpoints."),
+ NULL
+ },
+ &checkpoint_write_percent,
+ 50.0, 0.0, 100.0, NULL, NULL
+ },
+
+ {
+ {"checkpoint_nap_percent", PGC_SIGHUP, WAL_CHECKPOINTS,
+ gettext_noop("Sets the duration percentage between write and sync phases in checkpoints."),
+ NULL
+ },
+ &checkpoint_nap_percent,
+ 10.0, 0.0, 100.0, NULL, NULL
+ },
+
+ {
+ {"checkpoint_sync_percent", PGC_SIGHUP, WAL_CHECKPOINTS,
+ gettext_noop("Sets the duration percentage of sync phase in checkpoints."),
+ NULL
+ },
+ &checkpoint_sync_percent,
+ 20.0, 0.0, 100.0, NULL, NULL
+ },
+
/* End-of-list marker */
{
{NULL, 0, 0, NULL, NULL}, NULL, 0.0, 0.0, 0.0, NULL, NULL
diff -cpr HEAD/src/backend/utils/misc/postgresql.conf.sample LDC_v4/src/backend/utils/misc/postgresql.conf.sample
*** HEAD/src/backend/utils/misc/postgresql.conf.sample Tue Apr 17 03:29:55 2007
--- LDC_v4/src/backend/utils/misc/postgresql.conf.sample Thu Apr 19 11:32:50 2007
***************
*** 168,173 ****
--- 168,176 ----
#checkpoint_segments = 3 # in logfile segments, min 1, 16MB each
#checkpoint_timeout = 5min # range 30s-1h
+ #checkpoint_write_percent = 50.0 # duration percentage in write phase
+ #checkpoint_nap_percent = 10.0 # duration percentage between write and sync phases
+ #checkpoint_sync_percent = 20.0 # duration percentage in sync phase
#checkpoint_warning = 30s # 0 is off
# - Archiving -
diff -cpr HEAD/src/include/access/xlog.h LDC_v4/src/include/access/xlog.h
*** HEAD/src/include/access/xlog.h Sat Jan 6 07:19:51 2007
--- LDC_v4/src/include/access/xlog.h Thu Apr 19 11:32:50 2007
*************** extern void InitXLOGAccess(void);
*** 165,170 ****
--- 165,171 ----
extern void CreateCheckPoint(bool shutdown, bool force);
extern void XLogPutNextOid(Oid nextOid);
extern XLogRecPtr GetRedoRecPtr(void);
+ extern XLogRecPtr GetInsertRecPtr(void);
extern void GetNextXidAndEpoch(TransactionId *xid, uint32 *epoch);
#endif /* XLOG_H */
diff -cpr HEAD/src/include/postmaster/bgwriter.h LDC_v4/src/include/postmaster/bgwriter.h
*** HEAD/src/include/postmaster/bgwriter.h Sat Jan 6 07:19:57 2007
--- LDC_v4/src/include/postmaster/bgwriter.h Thu Apr 19 11:32:50 2007
***************
*** 20,29 ****
--- 20,35 ----
extern int BgWriterDelay;
extern int CheckPointTimeout;
extern int CheckPointWarning;
+ extern double checkpoint_write_percent;
+ extern double checkpoint_nap_percent;
+ extern double checkpoint_sync_percent;
extern void BackgroundWriterMain(void);
extern void RequestCheckpoint(bool waitforit, bool warnontime);
+ extern void CheckpointWriteDelay(double progress);
+ extern void CheckpointNapDelay(bool immediate);
+ extern void CheckpointSyncDelay(double progress);
extern bool ForwardFsyncRequest(RelFileNode rnode, BlockNumber segno);
extern void AbsorbFsyncRequests(void);
diff -cpr HEAD/src/include/storage/bufmgr.h LDC_v4/src/include/storage/bufmgr.h
*** HEAD/src/include/storage/bufmgr.h Sat Jan 6 07:19:57 2007
--- LDC_v4/src/include/storage/bufmgr.h Thu Apr 19 11:32:50 2007
*************** extern char *ShowBufferUsage(void);
*** 125,131 ****
extern void ResetBufferUsage(void);
extern void AtEOXact_Buffers(bool isCommit);
extern void PrintBufferLeakWarning(Buffer buffer);
! extern void FlushBufferPool(void);
extern BlockNumber BufferGetBlockNumber(Buffer buffer);
extern BlockNumber RelationGetNumberOfBlocks(Relation relation);
extern void RelationTruncate(Relation rel, BlockNumber nblocks);
--- 125,131 ----
extern void ResetBufferUsage(void);
extern void AtEOXact_Buffers(bool isCommit);
extern void PrintBufferLeakWarning(Buffer buffer);
! extern void FlushBufferPool(bool immediate);
extern BlockNumber BufferGetBlockNumber(Buffer buffer);
extern BlockNumber RelationGetNumberOfBlocks(Relation relation);
extern void RelationTruncate(Relation rel, BlockNumber nblocks);
*************** extern void LockBufferForCleanup(Buffer
*** 150,157 ****
extern void AbortBufferIO(void);
extern void BufmgrCommit(void);
! extern void BufferSync(void);
extern void BgBufferSync(void);
extern void AtProcExit_LocalBuffers(void);
--- 150,158 ----
extern void AbortBufferIO(void);
extern void BufmgrCommit(void);
! extern void BufferSync(bool immediate);
extern void BgBufferSync(void);
+ extern void BgLruBufferSync(void);
extern void AtProcExit_LocalBuffers(void);
diff -cpr HEAD/src/include/storage/smgr.h LDC_v4/src/include/storage/smgr.h
*** HEAD/src/include/storage/smgr.h Thu Jan 18 01:25:01 2007
--- LDC_v4/src/include/storage/smgr.h Thu Apr 19 11:32:50 2007
*************** extern void AtSubAbort_smgr(void);
*** 82,88 ****
extern void PostPrepare_smgr(void);
extern void smgrcommit(void);
extern void smgrabort(void);
! extern void smgrsync(void);
extern void smgr_redo(XLogRecPtr lsn, XLogRecord *record);
extern void smgr_desc(StringInfo buf, uint8 xl_info, char *rec);
--- 82,88 ----
extern void PostPrepare_smgr(void);
extern void smgrcommit(void);
extern void smgrabort(void);
! extern void smgrsync(bool immediate);
extern void smgr_redo(XLogRecPtr lsn, XLogRecord *record);
extern void smgr_desc(StringInfo buf, uint8 xl_info, char *rec);
*************** extern void mdwrite(SMgrRelation reln, B
*** 103,109 ****
extern BlockNumber mdnblocks(SMgrRelation reln);
extern void mdtruncate(SMgrRelation reln, BlockNumber nblocks, bool isTemp);
extern void mdimmedsync(SMgrRelation reln);
! extern void mdsync(void);
extern void RememberFsyncRequest(RelFileNode rnode, BlockNumber segno);
extern void ForgetRelationFsyncRequests(RelFileNode rnode);
--- 103,109 ----
extern BlockNumber mdnblocks(SMgrRelation reln);
extern void mdtruncate(SMgrRelation reln, BlockNumber nblocks, bool isTemp);
extern void mdimmedsync(SMgrRelation reln);
! extern void mdsync(bool immediate);
extern void RememberFsyncRequest(RelFileNode rnode, BlockNumber segno);
extern void ForgetRelationFsyncRequests(RelFileNode rnode);