diff -ru postgresql-8.3.1-orig/src/backend/postmaster/bgwriter.c postgresql-8.3.1/src/backend/postmaster/bgwriter.c --- postgresql-8.3.1-orig/src/backend/postmaster/bgwriter.c 2008-01-01 14:45:51.000000000 -0500 +++ postgresql-8.3.1/src/backend/postmaster/bgwriter.c 2008-04-03 17:29:21.705604181 -0400 @@ -123,6 +123,8 @@ slock_t ckpt_lck; /* protects all the ckpt_* fields */ int ckpt_started; /* advances when checkpoint starts */ + time_t last_ckpt_start_time; /* set to "now" when skpt_started is advanced */ + time_t last_ckpt_done_time; /* set to "now" when skpt_started is advanced */ int ckpt_done; /* advances when checkpoint done */ int ckpt_failed; /* advances when checkpoint fails */ @@ -309,11 +311,15 @@ { /* use volatile pointer to prevent code rearrangement */ volatile BgWriterShmemStruct *bgs = BgWriterShmem; + TimestampTz endtime; + endtime = time_t_to_timestamptz(time(NULL)); SpinLockAcquire(&bgs->ckpt_lck); bgs->ckpt_failed++; bgs->ckpt_done = bgs->ckpt_started; + bgs->last_ckpt_done_time = endtime; SpinLockRelease(&bgs->ckpt_lck); + BgWriterStats.m_last_checkpoint_done = endtime; ckpt_active = false; } @@ -363,6 +369,7 @@ int flags = 0; time_t now; int elapsed_secs; + TimestampTz endtime; /* * Emergency bailout if postmaster has died. This is to avoid the @@ -425,6 +432,7 @@ { /* use volatile pointer to prevent code rearrangement */ volatile BgWriterShmemStruct *bgs = BgWriterShmem; + TimestampTz starttime = time_t_to_timestamptz(now); /* * Atomically fetch the request flags to figure out what kind of a @@ -435,7 +443,9 @@ flags |= bgs->ckpt_flags; bgs->ckpt_flags = 0; bgs->ckpt_started++; + bgs->last_ckpt_start_time = starttime; SpinLockRelease(&bgs->ckpt_lck); + BgWriterStats.m_last_checkpoint_start = starttime; /* * We will warn if (a) too soon since last checkpoint (whatever @@ -472,10 +482,14 @@ /* * Indicate checkpoint completion to any waiting backends. + * Set the endtime to now to hand to the stats writer. */ + endtime = time_t_to_timestamptz(time(NULL)); SpinLockAcquire(&bgs->ckpt_lck); bgs->ckpt_done = bgs->ckpt_started; + bgs->last_ckpt_done_time = endtime; SpinLockRelease(&bgs->ckpt_lck); + BgWriterStats.m_last_checkpoint_done = endtime; ckpt_active = false; diff -ru postgresql-8.3.1-orig/src/backend/postmaster/pgstat.c postgresql-8.3.1/src/backend/postmaster/pgstat.c --- postgresql-8.3.1-orig/src/backend/postmaster/pgstat.c 2008-01-01 14:45:51.000000000 -0500 +++ postgresql-8.3.1/src/backend/postmaster/pgstat.c 2008-04-03 17:30:07.211460576 -0400 @@ -3169,4 +3171,6 @@ globalStats.maxwritten_clean += msg->m_maxwritten_clean; globalStats.buf_written_backend += msg->m_buf_written_backend; globalStats.buf_alloc += msg->m_buf_alloc; + globalStats.last_checkpoint_start = msg->m_last_checkpoint_start; + globalStats.last_checkpoint_done = msg->m_last_checkpoint_done; } diff -ru postgresql-8.3.1-orig/src/backend/utils/adt/pgstatfuncs.c postgresql-8.3.1/src/backend/utils/adt/pgstatfuncs.c --- postgresql-8.3.1-orig/src/backend/utils/adt/pgstatfuncs.c 2008-01-01 14:45:52.000000000 -0500 +++ postgresql-8.3.1/src/backend/utils/adt/pgstatfuncs.c 2008-04-03 16:48:51.715709622 -0400 @@ -786,6 +786,30 @@ } Datum +pg_stat_get_bgwriter_last_checkpoint_start(PG_FUNCTION_ARGS) +{ + TimestampTz result; + + result = pgstat_fetch_global()->last_checkpoint_start; + if(result == 0) + PG_RETURN_NULL(); + + PG_RETURN_TIMESTAMPTZ(result); +} + +Datum +pg_stat_get_bgwriter_last_checkpoint_done(PG_FUNCTION_ARGS) +{ + TimestampTz result; + + result = pgstat_fetch_global()->last_checkpoint_done; + if(result == 0) + PG_RETURN_NULL(); + + PG_RETURN_TIMESTAMPTZ(result); +} + +Datum pg_stat_get_bgwriter_timed_checkpoints(PG_FUNCTION_ARGS) { PG_RETURN_INT64(pgstat_fetch_global()->timed_checkpoints); diff -ru postgresql-8.3.1-orig/src/include/catalog/pg_proc.h postgresql-8.3.1/src/include/catalog/pg_proc.h --- postgresql-8.3.1-orig/src/include/catalog/pg_proc.h 2008-01-01 14:45:57.000000000 -0500 +++ postgresql-8.3.1/src/include/catalog/pg_proc.h 2008-04-03 17:47:26.314929683 -0400 @@ -4392,6 +4392,10 @@ DESCR("I/O"); DATA(insert OID = 3774 ( regdictionarysend PGNSP PGUID 12 1 0 f f t f i 1 17 "3769" _null_ _null_ _null_ regdictionarysend - _null_ _null_ )); DESCR("I/O"); +DATA(insert OID = 3775 ( pg_stat_get_bgwriter_last_checkpoint_start PGNSP PGUID 12 1 0 f f t f s 0 1184 "" _null_ _null_ _null_ pg_stat_get_bgwriter_last_checkpoint_start - _null_ _null_ )); +DESCR("statistics: timestamp when the most recent checkpoint was initiated"); +DATA(insert OID = 3776 ( pg_stat_get_bgwriter_last_checkpoint_done PGNSP PGUID 12 1 0 f f t f s 0 1184 "" _null_ _null_ _null_ pg_stat_get_bgwriter_last_checkpoint_done - _null_ _null_ )); +DESCR("statistics: timestamp when the most recent checkpoint was completed"); /* txid */ DATA(insert OID = 2939 ( txid_snapshot_in PGNSP PGUID 12 1 0 f f t f i 1 2970 "2275" _null_ _null_ _null_ txid_snapshot_in - _null_ _null_ )); diff -ru postgresql-8.3.1-orig/src/include/pgstat.h postgresql-8.3.1/src/include/pgstat.h --- postgresql-8.3.1-orig/src/include/pgstat.h 2008-01-01 14:45:56.000000000 -0500 +++ postgresql-8.3.1/src/include/pgstat.h 2008-04-03 17:28:37.288895715 -0400 @@ -296,6 +296,8 @@ PgStat_Counter m_maxwritten_clean; PgStat_Counter m_buf_written_backend; PgStat_Counter m_buf_alloc; + TimestampTz m_last_checkpoint_start; + TimestampTz m_last_checkpoint_done; } PgStat_MsgBgWriter; @@ -398,6 +400,8 @@ PgStat_Counter maxwritten_clean; PgStat_Counter buf_written_backend; PgStat_Counter buf_alloc; + TimestampTz last_checkpoint_start; + TimestampTz last_checkpoint_done; } PgStat_GlobalStats;