@@ -221,6 +221,7 @@ static int localNumBackends = 0;
221
221
* Contains statistics that are not collected per database
222
222
* or per table.
223
223
*/
224
+ static PgStat_ArchiverStats archiverStats ;
224
225
static PgStat_GlobalStats globalStats ;
225
226
226
227
/* Write request info for each database */
@@ -292,6 +293,7 @@ static void pgstat_recv_resetsinglecounter(PgStat_MsgResetsinglecounter *msg, in
292
293
static void pgstat_recv_autovac (PgStat_MsgAutovacStart * msg , int len );
293
294
static void pgstat_recv_vacuum (PgStat_MsgVacuum * msg , int len );
294
295
static void pgstat_recv_analyze (PgStat_MsgAnalyze * msg , int len );
296
+ static void pgstat_recv_archiver (PgStat_MsgArchiver * msg , int len );
295
297
static void pgstat_recv_bgwriter (PgStat_MsgBgWriter * msg , int len );
296
298
static void pgstat_recv_funcstat (PgStat_MsgFuncstat * msg , int len );
297
299
static void pgstat_recv_funcpurge (PgStat_MsgFuncpurge * msg , int len );
@@ -1257,13 +1259,15 @@ pgstat_reset_shared_counters(const char *target)
1257
1259
(errcode (ERRCODE_INSUFFICIENT_PRIVILEGE ),
1258
1260
errmsg ("must be superuser to reset statistics counters" )));
1259
1261
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 )
1261
1265
msg .m_resettarget = RESET_BGWRITER ;
1262
1266
else
1263
1267
ereport (ERROR ,
1264
1268
(errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
1265
1269
errmsg ("unrecognized reset target: \"%s\"" , target ),
1266
- errhint ("Target must be \"bgwriter\"." )));
1270
+ errhint ("Target must be \"archiver\" or \" bgwriter\"." )));
1267
1271
1268
1272
pgstat_setheader (& msg .m_hdr , PGSTAT_MTYPE_RESETSHAREDCOUNTER );
1269
1273
pgstat_send (& msg , sizeof (msg ));
@@ -2321,6 +2325,23 @@ pgstat_fetch_stat_numbackends(void)
2321
2325
return localNumBackends ;
2322
2326
}
2323
2327
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
+
2324
2345
/*
2325
2346
* ---------
2326
2347
* pgstat_fetch_global() -
@@ -3035,6 +3056,28 @@ pgstat_send(void *msg, int len)
3035
3056
#endif
3036
3057
}
3037
3058
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
+
3038
3081
/* ----------
3039
3082
* pgstat_send_bgwriter() -
3040
3083
*
@@ -3278,6 +3321,10 @@ PgstatCollectorMain(int argc, char *argv[])
3278
3321
pgstat_recv_analyze ((PgStat_MsgAnalyze * ) & msg , len );
3279
3322
break ;
3280
3323
3324
+ case PGSTAT_MTYPE_ARCHIVER :
3325
+ pgstat_recv_archiver ((PgStat_MsgArchiver * ) & msg , len );
3326
+ break ;
3327
+
3281
3328
case PGSTAT_MTYPE_BGWRITER :
3282
3329
pgstat_recv_bgwriter ((PgStat_MsgBgWriter * ) & msg , len );
3283
3330
break ;
@@ -3562,6 +3609,12 @@ pgstat_write_statsfiles(bool permanent, bool allDbs)
3562
3609
rc = fwrite (& globalStats , sizeof (globalStats ), 1 , fpout );
3563
3610
(void ) rc ; /* we'll check for error with ferror */
3564
3611
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
+
3565
3618
/*
3566
3619
* Walk through the database table.
3567
3620
*/
@@ -3828,16 +3881,18 @@ pgstat_read_statsfiles(Oid onlydb, bool permanent, bool deep)
3828
3881
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT );
3829
3882
3830
3883
/*
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.
3833
3886
*/
3834
3887
memset (& globalStats , 0 , sizeof (globalStats ));
3888
+ memset (& archiverStats , 0 , sizeof (archiverStats ));
3835
3889
3836
3890
/*
3837
3891
* Set the current timestamp (will be kept only in case we can't load an
3838
3892
* existing statsfile).
3839
3893
*/
3840
3894
globalStats .stat_reset_timestamp = GetCurrentTimestamp ();
3895
+ archiverStats .stat_reset_timestamp = globalStats .stat_reset_timestamp ;
3841
3896
3842
3897
/*
3843
3898
* 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)
3879
3934
goto done ;
3880
3935
}
3881
3936
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
+
3882
3947
/*
3883
3948
* We found an existing collector stats file. Read it and put all the
3884
3949
* hashtable entries into place.
@@ -4159,7 +4224,7 @@ pgstat_read_db_statsfile(Oid databaseid, HTAB *tabhash, HTAB *funchash,
4159
4224
* stats_timestamp value.
4160
4225
*
4161
4226
* - 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
4163
4228
* the timestamp of the global statfile.
4164
4229
* ----------
4165
4230
*/
@@ -4169,6 +4234,7 @@ pgstat_read_db_statsfile_timestamp(Oid databaseid, bool permanent,
4169
4234
{
4170
4235
PgStat_StatDBEntry dbentry ;
4171
4236
PgStat_GlobalStats myGlobalStats ;
4237
+ PgStat_ArchiverStats myArchiverStats ;
4172
4238
FILE * fpin ;
4173
4239
int32 format_id ;
4174
4240
const char * statfile = permanent ? PGSTAT_STAT_PERMANENT_FILENAME : pgstat_stat_filename ;
@@ -4211,6 +4277,18 @@ pgstat_read_db_statsfile_timestamp(Oid databaseid, bool permanent,
4211
4277
return false;
4212
4278
}
4213
4279
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
+
4214
4292
/* By default, we're going to return the timestamp of the global file. */
4215
4293
* ts = myGlobalStats .stats_timestamp ;
4216
4294
@@ -4738,6 +4816,12 @@ pgstat_recv_resetsharedcounter(PgStat_MsgResetsharedcounter *msg, int len)
4738
4816
memset (& globalStats , 0 , sizeof (globalStats ));
4739
4817
globalStats .stat_reset_timestamp = GetCurrentTimestamp ();
4740
4818
}
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
+ }
4741
4825
4742
4826
/*
4743
4827
* Presumably the sender of this message validated the target, don't
@@ -4867,6 +4951,33 @@ pgstat_recv_analyze(PgStat_MsgAnalyze *msg, int len)
4867
4951
}
4868
4952
4869
4953
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
+
4870
4981
/* ----------
4871
4982
* pgstat_recv_bgwriter() -
4872
4983
*
0 commit comments