Il 05/01/14 13:52, Magnus Hagander ha scritto:
> Yes, that's what I'm talking about. And just increment it by 1.
Done. I am attaching version 2 of the patch, which now implements only
one function (pg_stat_get_archiver()) and adds:

* failed attempts
* WAL of the last failed attempt
* time of the last failed attempt

Thanks for your inputs.

Ciao,
Gabriele

-- 
 Gabriele Bartolini - 2ndQuadrant Italia
 PostgreSQL Training, Services and Support
 gabriele.bartol...@2ndquadrant.it | www.2ndQuadrant.it

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 4ec6981..0094c19 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -270,6 +270,14 @@ 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
@@ -648,6 +656,64 @@ 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 successfully archived WAL file</entry>
+     </row>
+     <row>
+      <entry><structfield>last_archived_wal_time</></entry>
+      <entry><type>timestamp with time zone</type></entry>
+      <entry>Time of the last successful archival 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 +1679,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 575a40f..5ea8c87 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 2bb572e..60f957c 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,15 @@ pgarch_archiveXlog(char *xlog)
                snprintf(activitymsg, sizeof(activitymsg), "failed on %s", 
xlog);
                set_ps_display(activitymsg, false);
 
+               /*
+                * Send off activity statistics to the stats collector.
+                */
+               ArchiverStats.m_type = 'F';
+               strncpy(ArchiverStats.m_xlog,
+                       xlog, sizeof(ArchiverStats.m_xlog));
+               ArchiverStats.m_timestamp = GetCurrentTimestamp();
+               pgstat_send_archiver();
+
                return false;
        }
        ereport(DEBUG1,
@@ -755,4 +766,12 @@ pgarch_archiveDone(char *xlog)
                                (errcode_for_file_access(),
                                 errmsg("could not rename file \"%s\" to 
\"%s\": %m",
                                                rlogready, rlogdone)));
+       /*
+        * Send off activity statistics to the stats collector.
+        */
+       ArchiverStats.m_type = 'A';
+       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 4bfa62e..c039ae2 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,7 +1271,9 @@ 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,
@@ -2321,6 +2337,23 @@ pgstat_fetch_stat_numbackends(void)
 
 /*
  * ---------
+ * pgstat_fetch_archiver() -
+ *
+ *     Support function for the SQL-callable pgstat* functions. Returns
+ *     a pointer to the archiver statistics struct.
+ * ---------
+ */
+PgStat_ArchiverStats *
+pgstat_fetch_archiver(void)
+{
+       backend_read_statsfile();
+
+       return &archiverStats;
+}
+
+
+/*
+ * ---------
  * pgstat_fetch_global() -
  *
  *     Support function for the SQL-callable pgstat* functions. Returns
@@ -3034,6 +3067,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
@@ -3276,6 +3342,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;
@@ -3546,6 +3616,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.
@@ -3561,6 +3632,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);
@@ -3826,16 +3903,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
@@ -3873,7 +3952,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;
        }
 
@@ -4167,6 +4256,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;
@@ -4209,6 +4299,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;
 
@@ -4736,6 +4838,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
@@ -4867,6 +4975,34 @@ 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)
+{
+       switch(msg->m_type)
+       {
+               case 'A':
+                       /* 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;
+                       break;
+               case 'F':
+                       /* 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;
+                       break;
+       }
+}
+
+/* ----------
  * pgstat_recv_bgwriter() -
  *
  *     Process a BGWRITER message.
diff --git a/src/backend/utils/adt/pgstatfuncs.c 
b/src/backend/utils/adt/pgstatfuncs.c
index 2957fc7..d938264 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,94 @@ pg_stat_reset_single_function_counters(PG_FUNCTION_ARGS)
 
        PG_RETURN_VOID();
 }
+
+Datum
+pg_stat_get_archiver(PG_FUNCTION_ARGS)
+{
+       FuncCallContext *funcctx;
+
+       if (SRF_IS_FIRSTCALL())
+       {
+               MemoryContext oldcontext;
+               TupleDesc       tupdesc;
+
+               funcctx = SRF_FIRSTCALL_INIT();
+
+               oldcontext = 
MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
+
+               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);
+
+               funcctx->tuple_desc = BlessTupleDesc(tupdesc);
+
+               funcctx->max_calls = 1;
+
+               MemoryContextSwitchTo(oldcontext);
+       }
+
+       /* stuff done on every call of the function */
+       funcctx = SRF_PERCALL_SETUP();
+
+       if (funcctx->call_cntr < funcctx->max_calls)
+       {
+               Datum           values[7];
+               bool            nulls[7];
+               HeapTuple       tuple;
+               PgStat_ArchiverStats *archiver_stats;
+
+               MemSet(values, 0, sizeof(values));
+               MemSet(nulls, 0, sizeof(nulls));
+
+               /* Get statistics about the archiver process */
+               archiver_stats = pgstat_fetch_archiver();
+
+               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);
+
+               tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
+
+               SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
+       }
+       else
+       {
+               /* nothing left */
+               SRF_RETURN_DONE(funcctx);
+       }
+}
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 05d7ba5..313ef80 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -2700,6 +2700,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 b79a0eb..14a666a 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -18,6 +18,7 @@
 #include "utils/hsearch.h"
 #include "utils/relcache.h"
 
+#define MAX_XFN_CHARS  40
 
 /* Values for track_functions GUC variable --- order is significant! */
 typedef enum TrackFunctionsLevel
@@ -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;
 
@@ -355,6 +358,19 @@ typedef struct PgStat_MsgAnalyze
 
 
 /* ----------
+ * PgStat_MsgArchiver                  Sent by the archiver to update 
statistics.
+ * ----------
+ */
+typedef struct PgStat_MsgArchiver
+{
+       PgStat_MsgHdr m_hdr;
+
+       char m_type; /* A = archival, F = failure */
+       char m_xlog[MAX_XFN_CHARS +1];
+       TimestampTz m_timestamp;
+} PgStat_MsgArchiver;
+
+/* ----------
  * PgStat_MsgBgWriter                  Sent by the bgwriter to update 
statistics.
  * ----------
  */
@@ -501,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;
@@ -517,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
@@ -611,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[MAX_XFN_CHARS +1]; /* file name of the last 
archived WAL */
+       TimestampTz last_archived_wal_timestamp;        /* time of last 
successful archival */
+       PgStat_Counter failed_attempts;
+       char last_failed_wal[MAX_XFN_CHARS +1]; /* file name of the last failed 
WAL */
+       TimestampTz last_failed_wal_timestamp;  /* time of last failed attempt 
of archival */
+       TimestampTz stat_reset_timestamp;
+} PgStat_ArchiverStats;
+
+/*
  * Global statistics kept in the stats collector
  */
 typedef struct PgStat_GlobalStats
@@ -731,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;
@@ -862,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);
 
 /* ----------
@@ -874,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_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 (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to