diff options
Diffstat (limited to 'src/backend/postmaster')
-rw-r--r-- | src/backend/postmaster/pgarch.c | 21 | ||||
-rw-r--r-- | src/backend/postmaster/pgstat.c | 121 |
2 files changed, 124 insertions, 18 deletions
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c index 2fd7a012df0..cf2ce46516b 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" @@ -58,19 +59,6 @@ #define PGARCH_RESTART_INTERVAL 10 /* How often to attempt to restart a * failed archiver; in seconds. */ -/* ---------- - * Archiver control info. - * - * We expect that archivable files within pg_xlog will have names between - * MIN_XFN_CHARS and MAX_XFN_CHARS in length, consisting only of characters - * appearing in VALID_XFN_CHARS. The status files in archive_status have - * corresponding names with ".ready" or ".done" appended. - * ---------- - */ -#define MIN_XFN_CHARS 16 -#define MAX_XFN_CHARS 40 -#define VALID_XFN_CHARS "0123456789ABCDEF.history.backup" - #define NUM_ARCHIVE_RETRIES 3 @@ -496,10 +484,17 @@ pgarch_ArchiverCopyLoop(void) { /* successful */ pgarch_archiveDone(xlog); + + /* Tell the collector about the WAL file that we successfully archived */ + pgstat_send_archiver(xlog, false); + break; /* out of inner retry loop */ } else { + /* Tell the collector about the WAL file that we failed to archive */ + pgstat_send_archiver(xlog, true); + if (++failures >= NUM_ARCHIVE_RETRIES) { ereport(WARNING, diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index 1c3b481015d..305d1269124 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -221,6 +221,7 @@ static int localNumBackends = 0; * Contains statistics that are not collected per database * or per table. */ +static PgStat_ArchiverStats archiverStats; static PgStat_GlobalStats globalStats; /* Write request info for each database */ @@ -292,6 +293,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 +1259,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 \"archiver\" or \"bgwriter\"."))); pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_RESETSHAREDCOUNTER); pgstat_send(&msg, sizeof(msg)); @@ -2323,6 +2327,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 +3057,28 @@ pgstat_send(void *msg, int len) } /* ---------- + * pgstat_send_archiver() - + * + * Tell the collector about the WAL file that we successfully + * archived or failed to archive. + * ---------- + */ +void +pgstat_send_archiver(const char *xlog, bool failed) +{ + PgStat_MsgArchiver msg; + + /* + * Prepare and send the message + */ + pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_ARCHIVER); + msg.m_failed = failed; + strncpy(msg.m_xlog, xlog, sizeof(msg.m_xlog)); + msg.m_timestamp = GetCurrentTimestamp(); + pgstat_send(&msg, sizeof(msg)); +} + +/* ---------- * pgstat_send_bgwriter() - * * Send bgwriter statistics to the collector @@ -3278,6 +3321,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; @@ -3563,6 +3610,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 +3881,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 @@ -3880,6 +3935,16 @@ pgstat_read_statsfiles(Oid onlydb, bool permanent, bool deep) } /* + * Read archiver stats struct + */ + if (fread(&archiverStats, 1, sizeof(archiverStats), fpin) != sizeof(archiverStats)) + { + ereport(pgStatRunningInCollector ? LOG : WARNING, + (errmsg("corrupted statistics file \"%s\"", statfile))); + goto done; + } + + /* * We found an existing collector stats file. Read it and put all the * hashtable entries into place. */ @@ -4159,7 +4224,7 @@ done: * stats_timestamp value. * * - if there's no db stat entry (e.g. for a new or inactive database), - * there's no stat_timestamp value, but also nothing to write so we return + * there's no stats_timestamp value, but also nothing to write so we return * the timestamp of the global statfile. * ---------- */ @@ -4169,6 +4234,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 +4277,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 +4816,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 +4952,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_count; + memcpy(archiverStats.last_failed_wal, msg->m_xlog, + sizeof(archiverStats.last_failed_wal)); + archiverStats.last_failed_timestamp = msg->m_timestamp; + } + else + { + /* Successful archival operation */ + ++archiverStats.archived_count; + memcpy(archiverStats.last_archived_wal, msg->m_xlog, + sizeof(archiverStats.last_archived_wal)); + archiverStats.last_archived_timestamp = msg->m_timestamp; + } +} + +/* ---------- * pgstat_recv_bgwriter() - * * Process a BGWRITER message. |