@@ -221,6 +221,7 @@ static int localNumBackends = 0;
221221 * Contains statistics that are not collected per database
222222 * or per table.
223223 */
224+ static PgStat_ArchiverStats archiverStats ;
224225static PgStat_GlobalStats globalStats ;
225226
226227/* Write request info for each database */
@@ -292,6 +293,7 @@ static void pgstat_recv_resetsinglecounter(PgStat_MsgResetsinglecounter *msg, in
292293static void pgstat_recv_autovac (PgStat_MsgAutovacStart * msg , int len );
293294static void pgstat_recv_vacuum (PgStat_MsgVacuum * msg , int len );
294295static void pgstat_recv_analyze (PgStat_MsgAnalyze * msg , int len );
296+ static void pgstat_recv_archiver (PgStat_MsgArchiver * msg , int len );
295297static void pgstat_recv_bgwriter (PgStat_MsgBgWriter * msg , int len );
296298static void pgstat_recv_funcstat (PgStat_MsgFuncstat * msg , int len );
297299static void pgstat_recv_funcpurge (PgStat_MsgFuncpurge * msg , int len );
@@ -1257,13 +1259,15 @@ pgstat_reset_shared_counters(const char *target)
12571259 (errcode (ERRCODE_INSUFFICIENT_PRIVILEGE ),
12581260 errmsg ("must be superuser to reset statistics counters" )));
12591261
1260- if (strcmp (target , "bgwriter" ) == 0 )
1262+ if (strcmp (target , "archiver" ) == 0 )
1263+ msg .m_resettarget = RESET_ARCHIVER ;
1264+ else if (strcmp (target , "bgwriter" ) == 0 )
12611265 msg .m_resettarget = RESET_BGWRITER ;
12621266 else
12631267 ereport (ERROR ,
12641268 (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
12651269 errmsg ("unrecognized reset target: \"%s\"" , target ),
1266- errhint ("Target must be \"bgwriter\"." )));
1270+ errhint ("Target must be \"archiver\" or \" bgwriter\"." )));
12671271
12681272 pgstat_setheader (& msg .m_hdr , PGSTAT_MTYPE_RESETSHAREDCOUNTER );
12691273 pgstat_send (& msg , sizeof (msg ));
@@ -2321,6 +2325,23 @@ pgstat_fetch_stat_numbackends(void)
23212325 return localNumBackends ;
23222326}
23232327
2328+ /*
2329+ * ---------
2330+ * pgstat_fetch_stat_archiver() -
2331+ *
2332+ * Support function for the SQL-callable pgstat* functions. Returns
2333+ * a pointer to the archiver statistics struct.
2334+ * ---------
2335+ */
2336+ PgStat_ArchiverStats *
2337+ pgstat_fetch_stat_archiver (void )
2338+ {
2339+ backend_read_statsfile ();
2340+
2341+ return & archiverStats ;
2342+ }
2343+
2344+
23242345/*
23252346 * ---------
23262347 * pgstat_fetch_global() -
@@ -3035,6 +3056,28 @@ pgstat_send(void *msg, int len)
30353056#endif
30363057}
30373058
3059+ /* ----------
3060+ * pgstat_send_archiver() -
3061+ *
3062+ * Tell the collector about the WAL file that we successfully
3063+ * archived or failed to archive.
3064+ * ----------
3065+ */
3066+ void
3067+ pgstat_send_archiver (const char * xlog , bool failed )
3068+ {
3069+ PgStat_MsgArchiver msg ;
3070+
3071+ /*
3072+ * Prepare and send the message
3073+ */
3074+ pgstat_setheader (& msg .m_hdr , PGSTAT_MTYPE_ARCHIVER );
3075+ msg .m_failed = failed ;
3076+ strncpy (msg .m_xlog , xlog , sizeof (msg .m_xlog ));
3077+ msg .m_timestamp = GetCurrentTimestamp ();
3078+ pgstat_send (& msg , sizeof (msg ));
3079+ }
3080+
30383081/* ----------
30393082 * pgstat_send_bgwriter() -
30403083 *
@@ -3278,6 +3321,10 @@ PgstatCollectorMain(int argc, char *argv[])
32783321 pgstat_recv_analyze ((PgStat_MsgAnalyze * ) & msg , len );
32793322 break ;
32803323
3324+ case PGSTAT_MTYPE_ARCHIVER :
3325+ pgstat_recv_archiver ((PgStat_MsgArchiver * ) & msg , len );
3326+ break ;
3327+
32813328 case PGSTAT_MTYPE_BGWRITER :
32823329 pgstat_recv_bgwriter ((PgStat_MsgBgWriter * ) & msg , len );
32833330 break ;
@@ -3562,6 +3609,12 @@ pgstat_write_statsfiles(bool permanent, bool allDbs)
35623609 rc = fwrite (& globalStats , sizeof (globalStats ), 1 , fpout );
35633610 (void ) rc ; /* we'll check for error with ferror */
35643611
3612+ /*
3613+ * Write archiver stats struct
3614+ */
3615+ rc = fwrite (& archiverStats , sizeof (archiverStats ), 1 , fpout );
3616+ (void ) rc ; /* we'll check for error with ferror */
3617+
35653618 /*
35663619 * Walk through the database table.
35673620 */
@@ -3828,16 +3881,18 @@ pgstat_read_statsfiles(Oid onlydb, bool permanent, bool deep)
38283881 HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT );
38293882
38303883 /*
3831- * Clear out global statistics so they start from zero in case we can't
3832- * load an existing statsfile.
3884+ * Clear out global and archiver statistics so they start from zero
3885+ * in case we can't load an existing statsfile.
38333886 */
38343887 memset (& globalStats , 0 , sizeof (globalStats ));
3888+ memset (& archiverStats , 0 , sizeof (archiverStats ));
38353889
38363890 /*
38373891 * Set the current timestamp (will be kept only in case we can't load an
38383892 * existing statsfile).
38393893 */
38403894 globalStats .stat_reset_timestamp = GetCurrentTimestamp ();
3895+ archiverStats .stat_reset_timestamp = globalStats .stat_reset_timestamp ;
38413896
38423897 /*
38433898 * Try to open the stats file. If it doesn't exist, the backends simply
@@ -3879,6 +3934,16 @@ pgstat_read_statsfiles(Oid onlydb, bool permanent, bool deep)
38793934 goto done ;
38803935 }
38813936
3937+ /*
3938+ * Read archiver stats struct
3939+ */
3940+ if (fread (& archiverStats , 1 , sizeof (archiverStats ), fpin ) != sizeof (archiverStats ))
3941+ {
3942+ ereport (pgStatRunningInCollector ? LOG : WARNING ,
3943+ (errmsg ("corrupted statistics file \"%s\"" , statfile )));
3944+ goto done ;
3945+ }
3946+
38823947 /*
38833948 * We found an existing collector stats file. Read it and put all the
38843949 * hashtable entries into place.
@@ -4159,7 +4224,7 @@ pgstat_read_db_statsfile(Oid databaseid, HTAB *tabhash, HTAB *funchash,
41594224 * stats_timestamp value.
41604225 *
41614226 * - if there's no db stat entry (e.g. for a new or inactive database),
4162- * there's no stat_timestamp value, but also nothing to write so we return
4227+ * there's no stats_timestamp value, but also nothing to write so we return
41634228 * the timestamp of the global statfile.
41644229 * ----------
41654230 */
@@ -4169,6 +4234,7 @@ pgstat_read_db_statsfile_timestamp(Oid databaseid, bool permanent,
41694234{
41704235 PgStat_StatDBEntry dbentry ;
41714236 PgStat_GlobalStats myGlobalStats ;
4237+ PgStat_ArchiverStats myArchiverStats ;
41724238 FILE * fpin ;
41734239 int32 format_id ;
41744240 const char * statfile = permanent ? PGSTAT_STAT_PERMANENT_FILENAME : pgstat_stat_filename ;
@@ -4211,6 +4277,18 @@ pgstat_read_db_statsfile_timestamp(Oid databaseid, bool permanent,
42114277 return false;
42124278 }
42134279
4280+ /*
4281+ * Read archiver stats struct
4282+ */
4283+ if (fread (& myArchiverStats , 1 , sizeof (myArchiverStats ),
4284+ fpin ) != sizeof (myArchiverStats ))
4285+ {
4286+ ereport (pgStatRunningInCollector ? LOG : WARNING ,
4287+ (errmsg ("corrupted statistics file \"%s\"" , statfile )));
4288+ FreeFile (fpin );
4289+ return false;
4290+ }
4291+
42144292 /* By default, we're going to return the timestamp of the global file. */
42154293 * ts = myGlobalStats .stats_timestamp ;
42164294
@@ -4738,6 +4816,12 @@ pgstat_recv_resetsharedcounter(PgStat_MsgResetsharedcounter *msg, int len)
47384816 memset (& globalStats , 0 , sizeof (globalStats ));
47394817 globalStats .stat_reset_timestamp = GetCurrentTimestamp ();
47404818 }
4819+ else if (msg -> m_resettarget == RESET_ARCHIVER )
4820+ {
4821+ /* Reset the archiver statistics for the cluster. */
4822+ memset (& archiverStats , 0 , sizeof (archiverStats ));
4823+ archiverStats .stat_reset_timestamp = GetCurrentTimestamp ();
4824+ }
47414825
47424826 /*
47434827 * Presumably the sender of this message validated the target, don't
@@ -4867,6 +4951,33 @@ pgstat_recv_analyze(PgStat_MsgAnalyze *msg, int len)
48674951}
48684952
48694953
4954+ /* ----------
4955+ * pgstat_recv_archiver() -
4956+ *
4957+ * Process a ARCHIVER message.
4958+ * ----------
4959+ */
4960+ static void
4961+ pgstat_recv_archiver (PgStat_MsgArchiver * msg , int len )
4962+ {
4963+ if (msg -> m_failed )
4964+ {
4965+ /* Failed archival attempt */
4966+ ++ archiverStats .failed_count ;
4967+ memcpy (archiverStats .last_failed_wal , msg -> m_xlog ,
4968+ sizeof (archiverStats .last_failed_wal ));
4969+ archiverStats .last_failed_timestamp = msg -> m_timestamp ;
4970+ }
4971+ else
4972+ {
4973+ /* Successful archival operation */
4974+ ++ archiverStats .archived_count ;
4975+ memcpy (archiverStats .last_archived_wal , msg -> m_xlog ,
4976+ sizeof (archiverStats .last_archived_wal ));
4977+ archiverStats .last_archived_timestamp = msg -> m_timestamp ;
4978+ }
4979+ }
4980+
48704981/* ----------
48714982 * pgstat_recv_bgwriter() -
48724983 *
0 commit comments