On Thu, Jan 9, 2014 at 6:36 AM, Gabriele Bartolini
<[email protected]> wrote:
> Il 08/01/14 18:42, Simon Riggs ha scritto:
>> Not sure I see why it needs to be an SRF. It only returns one row.
> Attached is version 4, which removes management of SRF stages.
I have been looking at v4 a bit more, and found a couple of small things:
- a warning in pgstatfuncs.c
- some typos and format fixing in the sgml docs
- some corrections in a couple of comments
- Fixed an error message related to pg_stat_reset_shared referring
only to bgwriter and not the new option archiver. Here is how the new
message looks:
=# select pg_stat_reset_shared('popo');
ERROR: 22023: unrecognized reset target: "popo"
HINT: Target must be "bgwriter" or "archiver"
A new version is attached containing those fixes. I played also with
the patch and pgbench, simulating some archive failures and successes
while running pgbench and the reports given by pg_stat_archiver were
correct, so I am marking this patch as "Ready for committer".
Regards,
--
Michael
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 4ec6981..eb5131f 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -270,11 +270,19 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re
</row>
<row>
+ <entry><structname>pg_stat_archiver</><indexterm><primary>pg_stat_archiver</primary></indexterm></entry>
+ <entry>One row only, showing statistics about the
+ WAL archiver process's activity. See
+ <xref linkend="pg-stat-archiver-view"> for details.
+ </entry>
+ </row>
+
+ <row>
<entry><structname>pg_stat_bgwriter</><indexterm><primary>pg_stat_bgwriter</primary></indexterm></entry>
<entry>One row only, showing statistics about the
background writer process's activity. See
<xref linkend="pg-stat-bgwriter-view"> for details.
- </entry>
+ </entry>
</row>
<row>
@@ -648,6 +656,63 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re
</para>
</note>
+ <table id="pg-stat-archiver-view" xreflabel="pg_stat_archiver">
+ <title><structname>pg_stat_archiver</structname> View</title>
+
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>Column</entry>
+ <entry>Type</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry><structfield>archived_wals</></entry>
+ <entry><type>bigint</type></entry>
+ <entry>Number of WAL files that have been successfully archived</entry>
+ </row>
+ <row>
+ <entry><structfield>last_archived_wal</></entry>
+ <entry><type>text</type></entry>
+ <entry>Name of the last WAL file successfully archived</entry>
+ </row>
+ <row>
+ <entry><structfield>last_archived_wal_time</></entry>
+ <entry><type>timestamp with time zone</type></entry>
+ <entry>Time of the last successful archive operation</entry>
+ </row>
+ <row>
+ <entry><structfield>failed_attempts</></entry>
+ <entry><type>bigint</type></entry>
+ <entry>Number of failed attempts for archiving WAL files</entry>
+ </row>
+ <row>
+ <entry><structfield>last_failed_wal</></entry>
+ <entry><type>text</type></entry>
+ <entry>Name of the WAL file of the last failed archival operation</entry>
+ </row>
+ <row>
+ <entry><structfield>last_failed_wal_time</></entry>
+ <entry><type>timestamp with time zone</type></entry>
+ <entry>Time of the last failed archival operation</entry>
+ </row>
+ <row>
+ <entry><structfield>stats_reset</></entry>
+ <entry><type>timestamp with time zone</type></entry>
+ <entry>Time at which these statistics were last reset</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>
+ The <structname>pg_stat_archiver</structname> view will always have a
+ single row, containing data about the archiver process of the cluster.
+ </para>
+
<table id="pg-stat-bgwriter-view" xreflabel="pg_stat_bgwriter">
<title><structname>pg_stat_bgwriter</structname> View</title>
@@ -1613,6 +1678,8 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re
argument (requires superuser privileges).
Calling <literal>pg_stat_reset_shared('bgwriter')</> will zero all the
counters shown in the <structname>pg_stat_bgwriter</> view.
+ Calling <literal>pg_stat_reset_shared('archiver')</> will zero all the
+ counters shown in the <structname>pg_stat_archiver</> view.
</entry>
</row>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 043d118..c8a89fc 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -672,6 +672,17 @@ CREATE VIEW pg_stat_xact_user_functions AS
WHERE P.prolang != 12 -- fast check to eliminate built-in functions
AND pg_stat_get_xact_function_calls(P.oid) IS NOT NULL;
+CREATE VIEW pg_stat_archiver AS
+ SELECT
+ s.archived_wals,
+ s.last_archived_wal,
+ s.last_archived_wal_time,
+ s.failed_attempts,
+ s.last_failed_wal,
+ s.last_failed_wal_time,
+ s.stats_reset
+ FROM pg_stat_get_archiver() s;
+
CREATE VIEW pg_stat_bgwriter AS
SELECT
pg_stat_get_bgwriter_timed_checkpoints() AS checkpoints_timed,
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index 2fd7a01..69f8600 100644
--- a/src/backend/postmaster/pgarch.c
+++ b/src/backend/postmaster/pgarch.c
@@ -36,6 +36,7 @@
#include "access/xlog_internal.h"
#include "libpq/pqsignal.h"
#include "miscadmin.h"
+#include "pgstat.h"
#include "postmaster/fork_process.h"
#include "postmaster/pgarch.h"
#include "postmaster/postmaster.h"
@@ -46,6 +47,7 @@
#include "storage/pmsignal.h"
#include "utils/guc.h"
#include "utils/ps_status.h"
+#include "utils/timestamp.h"
/* ----------
@@ -647,6 +649,13 @@ pgarch_archiveXlog(char *xlog)
snprintf(activitymsg, sizeof(activitymsg), "failed on %s", xlog);
set_ps_display(activitymsg, false);
+ /* Send archiver statistics to the stats collector */
+ ArchiverStats.m_failed = true;
+ strncpy(ArchiverStats.m_xlog,
+ xlog, sizeof(ArchiverStats.m_xlog));
+ ArchiverStats.m_timestamp = GetCurrentTimestamp();
+ pgstat_send_archiver();
+
return false;
}
ereport(DEBUG1,
@@ -755,4 +764,10 @@ pgarch_archiveDone(char *xlog)
(errcode_for_file_access(),
errmsg("could not rename file \"%s\" to \"%s\": %m",
rlogready, rlogdone)));
+ /* Send archiver statistics to the stats collector */
+ ArchiverStats.m_failed = false;
+ strncpy(ArchiverStats.m_xlog,
+ xlog, sizeof(ArchiverStats.m_xlog));
+ ArchiverStats.m_timestamp = GetCurrentTimestamp();
+ pgstat_send_archiver();
}
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index 1c3b481..8aa5127 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -123,6 +123,13 @@ char *pgstat_stat_filename = NULL;
char *pgstat_stat_tmpname = NULL;
/*
+ * Archiver global statistics counters (unused in other processes).
+ * Stored directly in a stats message structure so it can be sent
+ * without needing to copy things around. We assume this inits to zeroes.
+ */
+PgStat_MsgArchiver ArchiverStats;
+
+/*
* BgWriter global statistics counters (unused in other processes).
* Stored directly in a stats message structure so it can be sent
* without needing to copy things around. We assume this inits to zeroes.
@@ -217,6 +224,12 @@ static PgBackendStatus *localBackendStatusTable = NULL;
static int localNumBackends = 0;
/*
+ * Archiver statistics, kept in the stats collector.
+ * Contains statistics regarding the archiving process.
+ */
+static PgStat_ArchiverStats archiverStats;
+
+/*
* Cluster wide statistics, kept in the stats collector.
* Contains statistics that are not collected per database
* or per table.
@@ -292,6 +305,7 @@ static void pgstat_recv_resetsinglecounter(PgStat_MsgResetsinglecounter *msg, in
static void pgstat_recv_autovac(PgStat_MsgAutovacStart *msg, int len);
static void pgstat_recv_vacuum(PgStat_MsgVacuum *msg, int len);
static void pgstat_recv_analyze(PgStat_MsgAnalyze *msg, int len);
+static void pgstat_recv_archiver(PgStat_MsgArchiver *msg, int len);
static void pgstat_recv_bgwriter(PgStat_MsgBgWriter *msg, int len);
static void pgstat_recv_funcstat(PgStat_MsgFuncstat *msg, int len);
static void pgstat_recv_funcpurge(PgStat_MsgFuncpurge *msg, int len);
@@ -1257,13 +1271,15 @@ pgstat_reset_shared_counters(const char *target)
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to reset statistics counters")));
- if (strcmp(target, "bgwriter") == 0)
+ if (strcmp(target, "archiver") == 0)
+ msg.m_resettarget = RESET_ARCHIVER;
+ else if (strcmp(target, "bgwriter") == 0)
msg.m_resettarget = RESET_BGWRITER;
else
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("unrecognized reset target: \"%s\"", target),
- errhint("Target must be \"bgwriter\".")));
+ errhint("Target must be \"bgwriter\" or \"archiver\".")));
pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_RESETSHAREDCOUNTER);
pgstat_send(&msg, sizeof(msg));
@@ -2323,6 +2339,23 @@ pgstat_fetch_stat_numbackends(void)
/*
* ---------
+ * pgstat_fetch_stat_archiver() -
+ *
+ * Support function for the SQL-callable pgstat* functions. Returns
+ * a pointer to the archiver statistics struct.
+ * ---------
+ */
+PgStat_ArchiverStats *
+pgstat_fetch_stat_archiver(void)
+{
+ backend_read_statsfile();
+
+ return &archiverStats;
+}
+
+
+/*
+ * ---------
* pgstat_fetch_global() -
*
* Support function for the SQL-callable pgstat* functions. Returns
@@ -3036,6 +3069,39 @@ pgstat_send(void *msg, int len)
}
/* ----------
+ * pgstat_send_archiver() -
+ *
+ * Send archiver statistics to the collector
+ * ----------
+ */
+void
+pgstat_send_archiver(void)
+{
+ /* We assume this initializes to zeroes */
+ static const PgStat_MsgArchiver all_zeroes;
+
+ /*
+ * This function can be called even if nothing at all has happened. In
+ * this case, avoid sending a completely empty message to the stats
+ * collector.
+ */
+ if (memcmp(&ArchiverStats, &all_zeroes, sizeof(PgStat_MsgArchiver)) == 0)
+ return;
+
+ /*
+ * Prepare and send the message
+ */
+ pgstat_setheader(&ArchiverStats.m_hdr, PGSTAT_MTYPE_ARCHIVER);
+ pgstat_send(&ArchiverStats, sizeof(ArchiverStats));
+
+ /*
+ * Clear out the statistics buffer, so it can be re-used.
+ */
+ MemSet(&ArchiverStats, 0, sizeof(ArchiverStats));
+}
+
+
+/* ----------
* pgstat_send_bgwriter() -
*
* Send bgwriter statistics to the collector
@@ -3278,6 +3344,10 @@ PgstatCollectorMain(int argc, char *argv[])
pgstat_recv_analyze((PgStat_MsgAnalyze *) &msg, len);
break;
+ case PGSTAT_MTYPE_ARCHIVER:
+ pgstat_recv_archiver((PgStat_MsgArchiver *) &msg, len);
+ break;
+
case PGSTAT_MTYPE_BGWRITER:
pgstat_recv_bgwriter((PgStat_MsgBgWriter *) &msg, len);
break;
@@ -3548,6 +3618,7 @@ pgstat_write_statsfiles(bool permanent, bool allDbs)
* Set the timestamp of the stats file.
*/
globalStats.stats_timestamp = GetCurrentTimestamp();
+ archiverStats.stats_timestamp = globalStats.stats_timestamp;
/*
* Write the file header --- currently just a format ID.
@@ -3563,6 +3634,12 @@ pgstat_write_statsfiles(bool permanent, bool allDbs)
(void) rc; /* we'll check for error with ferror */
/*
+ * Write archiver stats struct
+ */
+ rc = fwrite(&archiverStats, sizeof(archiverStats), 1, fpout);
+ (void) rc; /* we'll check for error with ferror */
+
+ /*
* Walk through the database table.
*/
hash_seq_init(&hstat, pgStatDBHash);
@@ -3828,16 +3905,18 @@ pgstat_read_statsfiles(Oid onlydb, bool permanent, bool deep)
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
/*
- * Clear out global statistics so they start from zero in case we can't
- * load an existing statsfile.
+ * Clear out global and archiver statistics so they start from zero
+ * in case we can't load an existing statsfile.
*/
memset(&globalStats, 0, sizeof(globalStats));
+ memset(&archiverStats, 0, sizeof(archiverStats));
/*
* Set the current timestamp (will be kept only in case we can't load an
* existing statsfile).
*/
globalStats.stat_reset_timestamp = GetCurrentTimestamp();
+ archiverStats.stat_reset_timestamp = globalStats.stat_reset_timestamp;
/*
* Try to open the stats file. If it doesn't exist, the backends simply
@@ -3875,7 +3954,17 @@ pgstat_read_statsfiles(Oid onlydb, bool permanent, bool deep)
if (fread(&globalStats, 1, sizeof(globalStats), fpin) != sizeof(globalStats))
{
ereport(pgStatRunningInCollector ? LOG : WARNING,
- (errmsg("corrupted statistics file \"%s\"", statfile)));
+ (errmsg("corrupted statistics file (global) \"%s\"", statfile)));
+ goto done;
+ }
+
+ /*
+ * Read archiver stats struct
+ */
+ if (fread(&archiverStats, 1, sizeof(archiverStats), fpin) != sizeof(archiverStats))
+ {
+ ereport(pgStatRunningInCollector ? LOG : WARNING,
+ (errmsg("corrupted statistics file (archiver) \"%s\"", statfile)));
goto done;
}
@@ -4169,6 +4258,7 @@ pgstat_read_db_statsfile_timestamp(Oid databaseid, bool permanent,
{
PgStat_StatDBEntry dbentry;
PgStat_GlobalStats myGlobalStats;
+ PgStat_ArchiverStats myArchiverStats;
FILE *fpin;
int32 format_id;
const char *statfile = permanent ? PGSTAT_STAT_PERMANENT_FILENAME : pgstat_stat_filename;
@@ -4211,6 +4301,18 @@ pgstat_read_db_statsfile_timestamp(Oid databaseid, bool permanent,
return false;
}
+ /*
+ * Read archiver stats struct
+ */
+ if (fread(&myArchiverStats, 1, sizeof(myArchiverStats),
+ fpin) != sizeof(myArchiverStats))
+ {
+ ereport(pgStatRunningInCollector ? LOG : WARNING,
+ (errmsg("corrupted statistics file \"%s\"", statfile)));
+ FreeFile(fpin);
+ return false;
+ }
+
/* By default, we're going to return the timestamp of the global file. */
*ts = myGlobalStats.stats_timestamp;
@@ -4738,6 +4840,12 @@ pgstat_recv_resetsharedcounter(PgStat_MsgResetsharedcounter *msg, int len)
memset(&globalStats, 0, sizeof(globalStats));
globalStats.stat_reset_timestamp = GetCurrentTimestamp();
}
+ else if (msg->m_resettarget == RESET_ARCHIVER)
+ {
+ /* Reset the archiver statistics for the cluster. */
+ memset(&archiverStats, 0, sizeof(archiverStats));
+ archiverStats.stat_reset_timestamp = GetCurrentTimestamp();
+ }
/*
* Presumably the sender of this message validated the target, don't
@@ -4868,6 +4976,33 @@ pgstat_recv_analyze(PgStat_MsgAnalyze *msg, int len)
/* ----------
+ * pgstat_recv_archiver() -
+ *
+ * Process a ARCHIVER message.
+ * ----------
+ */
+static void
+pgstat_recv_archiver(PgStat_MsgArchiver *msg, int len)
+{
+ if (msg->m_failed)
+ {
+ /* Failed archival attempt */
+ ++archiverStats.failed_attempts;
+ memcpy(archiverStats.last_failed_wal, msg->m_xlog,
+ sizeof(archiverStats.last_failed_wal));
+ archiverStats.last_failed_wal_timestamp = msg->m_timestamp;
+ }
+ else
+ {
+ /* Successful archival operation */
+ ++archiverStats.archived_wals;
+ memcpy(archiverStats.last_archived_wal, msg->m_xlog,
+ sizeof(archiverStats.last_archived_wal));
+ archiverStats.last_archived_wal_timestamp = msg->m_timestamp;
+ }
+}
+
+/* ----------
* pgstat_recv_bgwriter() -
*
* Process a BGWRITER message.
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 2b8f5ee..0e5cd09 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -87,6 +87,8 @@ extern Datum pg_stat_get_db_temp_bytes(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_db_blk_read_time(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_db_blk_write_time(PG_FUNCTION_ARGS);
+extern Datum pg_stat_get_archiver(PG_FUNCTION_ARGS);
+
extern Datum pg_stat_get_bgwriter_timed_checkpoints(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_bgwriter_requested_checkpoints(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_checkpoint_write_time(PG_FUNCTION_ARGS);
@@ -1712,3 +1714,70 @@ pg_stat_reset_single_function_counters(PG_FUNCTION_ARGS)
PG_RETURN_VOID();
}
+
+Datum
+pg_stat_get_archiver(PG_FUNCTION_ARGS)
+{
+ TupleDesc tupdesc;
+ Datum values[7];
+ bool nulls[7];
+ PgStat_ArchiverStats *archiver_stats;
+
+ /* Initialise values and NULL flags arrays */
+ MemSet(values, 0, sizeof(values));
+ MemSet(nulls, 0, sizeof(nulls));
+
+ /* Initialise attributes information in the tuple descriptor */
+ tupdesc = CreateTemplateTupleDesc(7, false);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 1, "archived_wals",
+ INT8OID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 2, "last_archived_wal",
+ TEXTOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 3, "last_archived_wal_time",
+ TIMESTAMPTZOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 4, "failed_attempts",
+ INT8OID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 5, "last_failed_wal",
+ TEXTOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 6, "last_failed_wal_time",
+ TIMESTAMPTZOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 7, "stats_reset",
+ TIMESTAMPTZOID, -1, 0);
+
+ BlessTupleDesc(tupdesc);
+
+ /* Get statistics about the archiver process */
+ archiver_stats = pgstat_fetch_stat_archiver();
+
+ /* Fill values and NULLs */
+ values[0] = Int64GetDatum(archiver_stats->archived_wals);
+ if (archiver_stats->last_archived_wal == 0)
+ nulls[1] = true;
+ else
+ values[1] = CStringGetTextDatum(archiver_stats->last_archived_wal);
+
+ if (archiver_stats->last_archived_wal_timestamp == 0)
+ nulls[2] = true;
+ else
+ values[2] = TimestampTzGetDatum(archiver_stats->last_archived_wal_timestamp);
+
+ values[3] = Int64GetDatum(archiver_stats->failed_attempts);
+ if (archiver_stats->last_failed_wal == 0)
+ nulls[4] = true;
+ else
+ values[4] = CStringGetTextDatum(archiver_stats->last_failed_wal);
+
+ if (archiver_stats->last_failed_wal_timestamp == 0)
+ nulls[5] = true;
+ else
+ values[5] = TimestampTzGetDatum(archiver_stats->last_failed_wal_timestamp);
+
+ if (archiver_stats->stat_reset_timestamp == 0)
+ nulls[6] = true;
+ else
+ values[6] = TimestampTzGetDatum(archiver_stats->stat_reset_timestamp);
+
+ /* Returns the record as Datum */
+ PG_RETURN_DATUM(HeapTupleGetDatum(
+ heap_form_tuple(tupdesc, values, nulls)));
+}
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index ad9774c..e81ef2e 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -2702,6 +2702,8 @@ DATA(insert OID = 2844 ( pg_stat_get_db_blk_read_time PGNSP PGUID 12 1 0 0 0 f
DESCR("statistics: block read time, in msec");
DATA(insert OID = 2845 ( pg_stat_get_db_blk_write_time PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 701 "26" _null_ _null_ _null_ _null_ pg_stat_get_db_blk_write_time _null_ _null_ _null_ ));
DESCR("statistics: block write time, in msec");
+DATA(insert OID = 3195 ( pg_stat_get_archiver PGNSP PGUID 12 1 0 0 0 f f f f f f s 0 0 2249 "" "{20,25,1184,20,25,1184,1184}" "{o,o,o,o,o,o,o}" "{archived_wals,last_archived_wal,last_archived_wal_time,failed_attempts,last_failed_wal,last_failed_wal_time,stats_reset}" _null_ pg_stat_get_archiver _null_ _null_ _null_ ));
+DESCR("statistics: information about WAL archiver");
DATA(insert OID = 2769 ( pg_stat_get_bgwriter_timed_checkpoints PGNSP PGUID 12 1 0 0 0 f f f f t f s 0 0 20 "" _null_ _null_ _null_ _null_ pg_stat_get_bgwriter_timed_checkpoints _null_ _null_ _null_ ));
DESCR("statistics: number of timed checkpoints started by the bgwriter");
DATA(insert OID = 2770 ( pg_stat_get_bgwriter_requested_checkpoints PGNSP PGUID 12 1 0 0 0 f f f f t f s 0 0 20 "" _null_ _null_ _null_ _null_ pg_stat_get_bgwriter_requested_checkpoints _null_ _null_ _null_ ));
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 0b458e5..d07abd2 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -17,6 +17,7 @@
#include "portability/instr_time.h"
#include "utils/hsearch.h"
#include "utils/relcache.h"
+#include "access/xlog_internal.h"
/* Values for track_functions GUC variable --- order is significant! */
@@ -44,6 +45,7 @@ typedef enum StatMsgType
PGSTAT_MTYPE_AUTOVAC_START,
PGSTAT_MTYPE_VACUUM,
PGSTAT_MTYPE_ANALYZE,
+ PGSTAT_MTYPE_ARCHIVER,
PGSTAT_MTYPE_BGWRITER,
PGSTAT_MTYPE_FUNCSTAT,
PGSTAT_MTYPE_FUNCPURGE,
@@ -102,6 +104,7 @@ typedef struct PgStat_TableCounts
/* Possible targets for resetting cluster-wide shared values */
typedef enum PgStat_Shared_Reset_Target
{
+ RESET_ARCHIVER,
RESET_BGWRITER
} PgStat_Shared_Reset_Target;
@@ -356,6 +359,18 @@ typedef struct PgStat_MsgAnalyze
/* ----------
+ * PgStat_MsgArchiver Sent by the archiver to update statistics.
+ * ----------
+ */
+typedef struct PgStat_MsgArchiver
+{
+ PgStat_MsgHdr m_hdr;
+ bool m_failed; /* Failed attempt */
+ char m_xlog[MAXFNAMELEN];
+ TimestampTz m_timestamp;
+} PgStat_MsgArchiver;
+
+/* ----------
* PgStat_MsgBgWriter Sent by the bgwriter to update statistics.
* ----------
*/
@@ -502,6 +517,7 @@ typedef union PgStat_Msg
PgStat_MsgAutovacStart msg_autovacuum;
PgStat_MsgVacuum msg_vacuum;
PgStat_MsgAnalyze msg_analyze;
+ PgStat_MsgArchiver msg_archiver;
PgStat_MsgBgWriter msg_bgwriter;
PgStat_MsgFuncstat msg_funcstat;
PgStat_MsgFuncpurge msg_funcpurge;
@@ -518,7 +534,7 @@ typedef union PgStat_Msg
* ------------------------------------------------------------
*/
-#define PGSTAT_FILE_FORMAT_ID 0x01A5BC9B
+#define PGSTAT_FILE_FORMAT_ID 0x01A5BC9C
/* ----------
* PgStat_StatDBEntry The collector's data per database
@@ -612,6 +628,21 @@ typedef struct PgStat_StatFuncEntry
/*
+ * Archiver statistics kept in the stats collector
+ */
+typedef struct PgStat_ArchiverStats
+{
+ TimestampTz stats_timestamp; /* time of stats file update */
+ PgStat_Counter archived_wals;
+ char last_archived_wal[MAXFNAMELEN]; /* last WAL file archived */
+ TimestampTz last_archived_wal_timestamp; /* last archival success */
+ PgStat_Counter failed_attempts;
+ char last_failed_wal[MAXFNAMELEN]; /* last WAL file involved in failure */
+ TimestampTz last_failed_wal_timestamp; /* last archival failure */
+ TimestampTz stat_reset_timestamp;
+} PgStat_ArchiverStats;
+
+/*
* Global statistics kept in the stats collector
*/
typedef struct PgStat_GlobalStats
@@ -732,6 +763,11 @@ extern char *pgstat_stat_tmpname;
extern char *pgstat_stat_filename;
/*
+ * Archiver statistics counters are updated directly by pgarch
+ */
+extern PgStat_MsgArchiver ArchiverStats;
+
+/*
* BgWriter statistics counters are updated directly by bgwriter and bufmgr
*/
extern PgStat_MsgBgWriter BgWriterStats;
@@ -863,6 +899,7 @@ extern void pgstat_twophase_postcommit(TransactionId xid, uint16 info,
extern void pgstat_twophase_postabort(TransactionId xid, uint16 info,
void *recdata, uint32 len);
+extern void pgstat_send_archiver(void);
extern void pgstat_send_bgwriter(void);
/* ----------
@@ -875,6 +912,7 @@ extern PgStat_StatTabEntry *pgstat_fetch_stat_tabentry(Oid relid);
extern PgBackendStatus *pgstat_fetch_stat_beentry(int beid);
extern PgStat_StatFuncEntry *pgstat_fetch_stat_funcentry(Oid funcid);
extern int pgstat_fetch_stat_numbackends(void);
+extern PgStat_ArchiverStats *pgstat_fetch_stat_archiver(void);
extern PgStat_GlobalStats *pgstat_fetch_global(void);
#endif /* PGSTAT_H */
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 9f089e3..bffcb30 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1640,6 +1640,14 @@ pg_stat_all_tables| SELECT c.oid AS relid,
LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace)))
WHERE (c.relkind = ANY (ARRAY['r'::"char", 't'::"char", 'm'::"char"]))
GROUP BY c.oid, n.nspname, c.relname;
+pg_stat_archiver| SELECT s.archived_wals,
+ s.last_archived_wal,
+ s.last_archived_wal_time,
+ s.failed_attempts,
+ s.last_failed_wal,
+ s.last_failed_wal_time,
+ s.stats_reset
+ FROM pg_stat_get_archiver() s(archived_wals, last_archived_wal, last_archived_wal_time, failed_attempts, last_failed_wal, last_failed_wal_time, stats_reset);
pg_stat_bgwriter| SELECT pg_stat_get_bgwriter_timed_checkpoints() AS checkpoints_timed,
pg_stat_get_bgwriter_requested_checkpoints() AS checkpoints_req,
pg_stat_get_checkpoint_write_time() AS checkpoint_write_time,
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers