pgstat: reorder pgstat.[ch] contents.
authorAndres Freund <andres@anarazel.de>
Mon, 21 Mar 2022 23:16:42 +0000 (16:16 -0700)
committerAndres Freund <andres@anarazel.de>
Mon, 21 Mar 2022 23:21:00 +0000 (16:21 -0700)
Now that 13619598f10 has split pgstat up into multiple files it isn't quite as
hard to come up with a sensible order for pgstat.[ch]. Inconsistent naming
makes it still not quite right looking, but that's work for another commit.

Author: Andres Freund <andres@anarazel.de>
Discussion: https://postgr.es/m/20220303021600.hs34ghqcw6zcokdh@alap3.anarazel.de

src/backend/postmaster/pgstat.c
src/include/pgstat.h

index e781cac7bf7d2a497325dcac5d739c4be67057ba..1e7adc27b9d3fa3d60551e9455bcca6f6911c4b8 100644 (file)
 #include "utils/snapmgr.h"
 #include "utils/timestamp.h"
 
+
 /* ----------
  * Timer definitions.
  * ----------
  */
+
 #define PGSTAT_RETRY_DELAY     10  /* How long to wait between checks for a
                                     * new file; in milliseconds. */
 
 #define PGSTAT_MIN_RCVBUF      (100 * 1024)
 
 
+/* ----------
+ * Local function forward declarations
+ * ----------
+ */
+
+#ifdef EXEC_BACKEND
+static pid_t pgstat_forkexec(void);
+#endif
+
+NON_EXEC_STATIC void PgstatCollectorMain(int argc, char *argv[]) pg_attribute_noreturn();
+
+static PgStat_StatDBEntry *pgstat_get_db_entry(Oid databaseid, bool create);
+static PgStat_StatTabEntry *pgstat_get_tab_entry(PgStat_StatDBEntry *dbentry,
+                                                Oid tableoid, bool create);
+static PgStat_StatSubEntry *pgstat_get_subscription_entry(Oid subid, bool create);
+static void pgstat_reset_subscription(PgStat_StatSubEntry *subentry, TimestampTz ts);
+static void pgstat_write_statsfiles(bool permanent, bool allDbs);
+static void pgstat_write_db_statsfile(PgStat_StatDBEntry *dbentry, bool permanent);
+static HTAB *pgstat_read_statsfiles(Oid onlydb, bool permanent, bool deep);
+static void pgstat_read_db_statsfile(Oid databaseid, HTAB *tabhash, HTAB *funchash,
+                                    bool permanent);
+static void backend_read_statsfile(void);
+
+static bool pgstat_write_statsfile_needed(void);
+static bool pgstat_db_requested(Oid databaseid);
+
+static PgStat_StatReplSlotEntry *pgstat_get_replslot_entry(NameData name, bool create_it);
+static void pgstat_reset_replslot(PgStat_StatReplSlotEntry *slotstats, TimestampTz ts);
+
+static HTAB *pgstat_collect_oids(Oid catalogid, AttrNumber anum_oid);
+
+static void pgstat_setup_memcxt(void);
+
+static void pgstat_recv_inquiry(PgStat_MsgInquiry *msg, int len);
+static void pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len);
+static void pgstat_recv_tabpurge(PgStat_MsgTabpurge *msg, int len);
+static void pgstat_recv_dropdb(PgStat_MsgDropdb *msg, int len);
+static void pgstat_recv_resetcounter(PgStat_MsgResetcounter *msg, int len);
+static void pgstat_recv_resetsharedcounter(PgStat_MsgResetsharedcounter *msg, int len);
+static void pgstat_recv_resetsinglecounter(PgStat_MsgResetsinglecounter *msg, int len);
+static void pgstat_recv_resetslrucounter(PgStat_MsgResetslrucounter *msg, int len);
+static void pgstat_recv_resetreplslotcounter(PgStat_MsgResetreplslotcounter *msg, int len);
+static void pgstat_recv_resetsubcounter(PgStat_MsgResetsubcounter *msg, int len);
+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_checkpointer(PgStat_MsgCheckpointer *msg, int len);
+static void pgstat_recv_wal(PgStat_MsgWal *msg, int len);
+static void pgstat_recv_slru(PgStat_MsgSLRU *msg, int len);
+static void pgstat_recv_funcstat(PgStat_MsgFuncstat *msg, int len);
+static void pgstat_recv_funcpurge(PgStat_MsgFuncpurge *msg, int len);
+static void pgstat_recv_recoveryconflict(PgStat_MsgRecoveryConflict *msg, int len);
+static void pgstat_recv_deadlock(PgStat_MsgDeadlock *msg, int len);
+static void pgstat_recv_checksum_failure(PgStat_MsgChecksumFailure *msg, int len);
+static void pgstat_recv_connect(PgStat_MsgConnect *msg, int len);
+static void pgstat_recv_disconnect(PgStat_MsgDisconnect *msg, int len);
+static void pgstat_recv_replslot(PgStat_MsgReplSlot *msg, int len);
+static void pgstat_recv_tempfile(PgStat_MsgTempFile *msg, int len);
+static void pgstat_recv_subscription_drop(PgStat_MsgSubscriptionDrop *msg, int len);
+static void pgstat_recv_subscription_error(PgStat_MsgSubscriptionError *msg, int len);
+
+
 /* ----------
  * GUC parameters
  * ----------
  */
+
 bool       pgstat_track_counts = false;
 
+
 /* ----------
  * Built from GUC parameter
  * ----------
  */
+
 char      *pgstat_stat_directory = NULL;
 char      *pgstat_stat_filename = NULL;
 char      *pgstat_stat_tmpname = NULL;
 
+
 /* ----------
  * state shared with pgstat_*.c
  * ----------
@@ -116,6 +186,7 @@ char       *pgstat_stat_tmpname = NULL;
 
 pgsocket   pgStatSock = PGINVALID_SOCKET;
 
+
 /* ----------
  * Local data
  * ----------
@@ -164,69 +235,6 @@ static bool pgstat_is_shutdown = false;
 #endif
 
 
-/* ----------
- * Local function forward declarations
- * ----------
- */
-#ifdef EXEC_BACKEND
-static pid_t pgstat_forkexec(void);
-#endif
-
-NON_EXEC_STATIC void PgstatCollectorMain(int argc, char *argv[]) pg_attribute_noreturn();
-
-static PgStat_StatDBEntry *pgstat_get_db_entry(Oid databaseid, bool create);
-static PgStat_StatTabEntry *pgstat_get_tab_entry(PgStat_StatDBEntry *dbentry,
-                                                Oid tableoid, bool create);
-static PgStat_StatSubEntry *pgstat_get_subscription_entry(Oid subid, bool create);
-static void pgstat_reset_subscription(PgStat_StatSubEntry *subentry, TimestampTz ts);
-static void pgstat_write_statsfiles(bool permanent, bool allDbs);
-static void pgstat_write_db_statsfile(PgStat_StatDBEntry *dbentry, bool permanent);
-static HTAB *pgstat_read_statsfiles(Oid onlydb, bool permanent, bool deep);
-static void pgstat_read_db_statsfile(Oid databaseid, HTAB *tabhash, HTAB *funchash,
-                                    bool permanent);
-static void backend_read_statsfile(void);
-
-static bool pgstat_write_statsfile_needed(void);
-static bool pgstat_db_requested(Oid databaseid);
-
-static PgStat_StatReplSlotEntry *pgstat_get_replslot_entry(NameData name, bool create_it);
-static void pgstat_reset_replslot(PgStat_StatReplSlotEntry *slotstats, TimestampTz ts);
-
-static HTAB *pgstat_collect_oids(Oid catalogid, AttrNumber anum_oid);
-
-static void pgstat_setup_memcxt(void);
-
-
-static void pgstat_recv_inquiry(PgStat_MsgInquiry *msg, int len);
-static void pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len);
-static void pgstat_recv_tabpurge(PgStat_MsgTabpurge *msg, int len);
-static void pgstat_recv_dropdb(PgStat_MsgDropdb *msg, int len);
-static void pgstat_recv_resetcounter(PgStat_MsgResetcounter *msg, int len);
-static void pgstat_recv_resetsharedcounter(PgStat_MsgResetsharedcounter *msg, int len);
-static void pgstat_recv_resetsinglecounter(PgStat_MsgResetsinglecounter *msg, int len);
-static void pgstat_recv_resetslrucounter(PgStat_MsgResetslrucounter *msg, int len);
-static void pgstat_recv_resetreplslotcounter(PgStat_MsgResetreplslotcounter *msg, int len);
-static void pgstat_recv_resetsubcounter(PgStat_MsgResetsubcounter *msg, int len);
-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_checkpointer(PgStat_MsgCheckpointer *msg, int len);
-static void pgstat_recv_wal(PgStat_MsgWal *msg, int len);
-static void pgstat_recv_slru(PgStat_MsgSLRU *msg, int len);
-static void pgstat_recv_funcstat(PgStat_MsgFuncstat *msg, int len);
-static void pgstat_recv_funcpurge(PgStat_MsgFuncpurge *msg, int len);
-static void pgstat_recv_recoveryconflict(PgStat_MsgRecoveryConflict *msg, int len);
-static void pgstat_recv_deadlock(PgStat_MsgDeadlock *msg, int len);
-static void pgstat_recv_checksum_failure(PgStat_MsgChecksumFailure *msg, int len);
-static void pgstat_recv_connect(PgStat_MsgConnect *msg, int len);
-static void pgstat_recv_disconnect(PgStat_MsgDisconnect *msg, int len);
-static void pgstat_recv_replslot(PgStat_MsgReplSlot *msg, int len);
-static void pgstat_recv_tempfile(PgStat_MsgTempFile *msg, int len);
-static void pgstat_recv_subscription_drop(PgStat_MsgSubscriptionDrop *msg, int len);
-static void pgstat_recv_subscription_error(PgStat_MsgSubscriptionError *msg, int len);
-
 /* ------------------------------------------------------------
  * Public functions called from postmaster follow
  * ------------------------------------------------------------
@@ -687,11 +695,230 @@ allow_immediate_pgstat_restart(void)
    last_pgstat_start_time = 0;
 }
 
+
 /* ------------------------------------------------------------
- * Public functions used by backends follow
- *------------------------------------------------------------
+ * Backend initialization / shutdown functions
+ * ------------------------------------------------------------
+ */
+
+/*
+ * Shut down a single backend's statistics reporting at process exit.
+ *
+ * Flush any remaining statistics counts out to the collector.
+ * Without this, operations triggered during backend exit (such as
+ * temp table deletions) won't be counted.
  */
+static void
+pgstat_shutdown_hook(int code, Datum arg)
+{
+   Assert(!pgstat_is_shutdown);
 
+   /*
+    * If we got as far as discovering our own database ID, we can report what
+    * we did to the collector.  Otherwise, we'd be sending an invalid
+    * database ID, so forget it.  (This means that accesses to pg_database
+    * during failed backend starts might never get counted.)
+    */
+   if (OidIsValid(MyDatabaseId))
+       pgstat_report_stat(true);
+
+#ifdef USE_ASSERT_CHECKING
+   pgstat_is_shutdown = true;
+#endif
+}
+
+/* ----------
+ * pgstat_initialize() -
+ *
+ * Initialize pgstats state, and set up our on-proc-exit hook. Called from
+ * BaseInit().
+ *
+ * NOTE: MyDatabaseId isn't set yet; so the shutdown hook has to be careful.
+ * ----------
+ */
+void
+pgstat_initialize(void)
+{
+   Assert(!pgstat_is_initialized);
+
+   pgstat_wal_initialize();
+
+   /* Set up a process-exit hook to clean up */
+   before_shmem_exit(pgstat_shutdown_hook, 0);
+
+#ifdef USE_ASSERT_CHECKING
+   pgstat_is_initialized = true;
+#endif
+}
+
+
+/* ------------------------------------------------------------
+ * Transaction integration
+ * ------------------------------------------------------------
+ */
+
+/* ----------
+ * AtEOXact_PgStat
+ *
+ * Called from access/transam/xact.c at top-level transaction commit/abort.
+ * ----------
+ */
+void
+AtEOXact_PgStat(bool isCommit, bool parallel)
+{
+   PgStat_SubXactStatus *xact_state;
+
+   AtEOXact_PgStat_Database(isCommit, parallel);
+
+   /* handle transactional stats information */
+   xact_state = pgStatXactStack;
+   if (xact_state != NULL)
+   {
+       Assert(xact_state->nest_level == 1);
+       Assert(xact_state->prev == NULL);
+
+       AtEOXact_PgStat_Relations(xact_state, isCommit);
+   }
+   pgStatXactStack = NULL;
+
+   /* Make sure any stats snapshot is thrown away */
+   pgstat_clear_snapshot();
+}
+
+/* ----------
+ * AtEOSubXact_PgStat
+ *
+ * Called from access/transam/xact.c at subtransaction commit/abort.
+ * ----------
+ */
+void
+AtEOSubXact_PgStat(bool isCommit, int nestDepth)
+{
+   PgStat_SubXactStatus *xact_state;
+
+   /* merge the sub-transaction's transactional stats into the parent */
+   xact_state = pgStatXactStack;
+   if (xact_state != NULL &&
+       xact_state->nest_level >= nestDepth)
+   {
+       /* delink xact_state from stack immediately to simplify reuse case */
+       pgStatXactStack = xact_state->prev;
+
+       AtEOSubXact_PgStat_Relations(xact_state, isCommit, nestDepth);
+
+       pfree(xact_state);
+   }
+}
+
+/*
+ * AtPrepare_PgStat
+ *     Save the transactional stats state at 2PC transaction prepare.
+ */
+void
+AtPrepare_PgStat(void)
+{
+   PgStat_SubXactStatus *xact_state;
+
+   xact_state = pgStatXactStack;
+   if (xact_state != NULL)
+   {
+       Assert(xact_state->nest_level == 1);
+       Assert(xact_state->prev == NULL);
+
+       AtPrepare_PgStat_Relations(xact_state);
+   }
+}
+
+/*
+ * PostPrepare_PgStat
+ *     Clean up after successful PREPARE.
+ *
+ * Note: AtEOXact_PgStat is not called during PREPARE.
+ */
+void
+PostPrepare_PgStat(void)
+{
+   PgStat_SubXactStatus *xact_state;
+
+   /*
+    * We don't bother to free any of the transactional state, since it's all
+    * in TopTransactionContext and will go away anyway.
+    */
+   xact_state = pgStatXactStack;
+   if (xact_state != NULL)
+   {
+       Assert(xact_state->nest_level == 1);
+       Assert(xact_state->prev == NULL);
+
+       PostPrepare_PgStat_Relations(xact_state);
+   }
+   pgStatXactStack = NULL;
+
+   /* Make sure any stats snapshot is thrown away */
+   pgstat_clear_snapshot();
+}
+
+/* ----------
+ * pgstat_clear_snapshot() -
+ *
+ * Discard any data collected in the current transaction.  Any subsequent
+ * request will cause new snapshots to be read.
+ *
+ * This is also invoked during transaction commit or abort to discard
+ * the no-longer-wanted snapshot.
+ * ----------
+ */
+void
+pgstat_clear_snapshot(void)
+{
+   pgstat_assert_is_up();
+
+   /* Release memory, if any was allocated */
+   if (pgStatLocalContext)
+       MemoryContextDelete(pgStatLocalContext);
+
+   /* Reset variables */
+   pgStatLocalContext = NULL;
+   pgStatDBHash = NULL;
+   replSlotStatHash = NULL;
+   subscriptionStatHash = NULL;
+
+   /*
+    * Historically the backend_status.c facilities lived in this file, and
+    * were reset with the same function. For now keep it that way, and
+    * forward the reset request.
+    */
+   pgstat_clear_backend_activity_snapshot();
+}
+
+/*
+ * Ensure (sub)transaction stack entry for the given nest_level exists, adding
+ * it if needed.
+ */
+PgStat_SubXactStatus *
+pgstat_xact_stack_level_get(int nest_level)
+{
+   PgStat_SubXactStatus *xact_state;
+
+   xact_state = pgStatXactStack;
+   if (xact_state == NULL || xact_state->nest_level != nest_level)
+   {
+       xact_state = (PgStat_SubXactStatus *)
+           MemoryContextAlloc(TopTransactionContext,
+                              sizeof(PgStat_SubXactStatus));
+       xact_state->nest_level = nest_level;
+       xact_state->prev = pgStatXactStack;
+       xact_state->first = NULL;
+       pgStatXactStack = xact_state;
+   }
+   return xact_state;
+}
+
+
+/* ------------------------------------------------------------
+ * Public functions used by backends follow
+ * ------------------------------------------------------------
+ */
 
 /* ----------
  * pgstat_report_stat() -
@@ -974,7 +1201,6 @@ pgstat_vacuum_stat(void)
    }
 }
 
-
 /* ----------
  * pgstat_collect_oids() -
  *
@@ -1140,130 +1366,6 @@ pgstat_send_inquiry(TimestampTz clock_time, TimestampTz cutoff_time, Oid databas
    pgstat_send(&msg, sizeof(msg));
 }
 
-/*
- * Ensure (sub)transaction stack entry for the given nest_level exists, adding
- * it if needed.
- */
-PgStat_SubXactStatus *
-pgstat_xact_stack_level_get(int nest_level)
-{
-   PgStat_SubXactStatus *xact_state;
-
-   xact_state = pgStatXactStack;
-   if (xact_state == NULL || xact_state->nest_level != nest_level)
-   {
-       xact_state = (PgStat_SubXactStatus *)
-           MemoryContextAlloc(TopTransactionContext,
-                              sizeof(PgStat_SubXactStatus));
-       xact_state->nest_level = nest_level;
-       xact_state->prev = pgStatXactStack;
-       xact_state->first = NULL;
-       pgStatXactStack = xact_state;
-   }
-   return xact_state;
-}
-
-/* ----------
- * AtEOXact_PgStat
- *
- * Called from access/transam/xact.c at top-level transaction commit/abort.
- * ----------
- */
-void
-AtEOXact_PgStat(bool isCommit, bool parallel)
-{
-   PgStat_SubXactStatus *xact_state;
-
-   AtEOXact_PgStat_Database(isCommit, parallel);
-
-   /* handle transactional stats information */
-   xact_state = pgStatXactStack;
-   if (xact_state != NULL)
-   {
-       Assert(xact_state->nest_level == 1);
-       Assert(xact_state->prev == NULL);
-
-       AtEOXact_PgStat_Relations(xact_state, isCommit);
-   }
-   pgStatXactStack = NULL;
-
-   /* Make sure any stats snapshot is thrown away */
-   pgstat_clear_snapshot();
-}
-
-/* ----------
- * AtEOSubXact_PgStat
- *
- * Called from access/transam/xact.c at subtransaction commit/abort.
- * ----------
- */
-void
-AtEOSubXact_PgStat(bool isCommit, int nestDepth)
-{
-   PgStat_SubXactStatus *xact_state;
-
-   /* merge the sub-transaction's transactional stats into the parent */
-   xact_state = pgStatXactStack;
-   if (xact_state != NULL &&
-       xact_state->nest_level >= nestDepth)
-   {
-       /* delink xact_state from stack immediately to simplify reuse case */
-       pgStatXactStack = xact_state->prev;
-
-       AtEOSubXact_PgStat_Relations(xact_state, isCommit, nestDepth);
-
-       pfree(xact_state);
-   }
-}
-
-/*
- * AtPrepare_PgStat
- *     Save the transactional stats state at 2PC transaction prepare.
- */
-void
-AtPrepare_PgStat(void)
-{
-   PgStat_SubXactStatus *xact_state;
-
-   xact_state = pgStatXactStack;
-   if (xact_state != NULL)
-   {
-       Assert(xact_state->nest_level == 1);
-       Assert(xact_state->prev == NULL);
-
-       AtPrepare_PgStat_Relations(xact_state);
-   }
-}
-
-/*
- * PostPrepare_PgStat
- *     Clean up after successful PREPARE.
- *
- * Note: AtEOXact_PgStat is not called during PREPARE.
- */
-void
-PostPrepare_PgStat(void)
-{
-   PgStat_SubXactStatus *xact_state;
-
-   /*
-    * We don't bother to free any of the transactional state, since it's all
-    * in TopTransactionContext and will go away anyway.
-    */
-   xact_state = pgStatXactStack;
-   if (xact_state != NULL)
-   {
-       Assert(xact_state->nest_level == 1);
-       Assert(xact_state->prev == NULL);
-
-       PostPrepare_PgStat_Relations(xact_state);
-   }
-   pgStatXactStack = NULL;
-
-   /* Make sure any stats snapshot is thrown away */
-   pgstat_clear_snapshot();
-}
-
 /* ----------
  * pgstat_fetch_stat_dbentry() -
  *
@@ -1282,15 +1384,30 @@ pgstat_fetch_stat_dbentry(Oid dbid)
     */
    backend_read_statsfile();
 
-   /*
-    * Lookup the requested database; return NULL if not found
-    */
-   return (PgStat_StatDBEntry *) hash_search(pgStatDBHash,
-                                             (void *) &dbid,
-                                             HASH_FIND, NULL);
+   /*
+    * Lookup the requested database; return NULL if not found
+    */
+   return (PgStat_StatDBEntry *) hash_search(pgStatDBHash,
+                                             (void *) &dbid,
+                                             HASH_FIND, NULL);
+}
+
+/*
+ * ---------
+ * pgstat_fetch_global() -
+ *
+ * Support function for the SQL-callable pgstat* functions. Returns
+ * a pointer to the global statistics struct.
+ * ---------
+ */
+PgStat_GlobalStats *
+pgstat_fetch_global(void)
+{
+   backend_read_statsfile();
+
+   return &globalStats;
 }
 
-
 /* ----------
  * pgstat_fetch_stat_tabentry() -
  *
@@ -1425,22 +1542,6 @@ pgstat_fetch_stat_checkpointer(void)
    return &globalStats.checkpointer;
 }
 
-/*
- * ---------
- * pgstat_fetch_global() -
- *
- * Support function for the SQL-callable pgstat* functions. Returns
- * a pointer to the global statistics struct.
- * ---------
- */
-PgStat_GlobalStats *
-pgstat_fetch_global(void)
-{
-   backend_read_statsfile();
-
-   return &globalStats;
-}
-
 /*
  * ---------
  * pgstat_fetch_stat_wal() -
@@ -1506,61 +1607,39 @@ pgstat_fetch_stat_subscription(Oid subid)
    return pgstat_get_subscription_entry(subid, false);
 }
 
-/*
- * Shut down a single backend's statistics reporting at process exit.
- *
- * Flush any remaining statistics counts out to the collector.
- * Without this, operations triggered during backend exit (such as
- * temp table deletions) won't be counted.
- */
-static void
-pgstat_shutdown_hook(int code, Datum arg)
-{
-   Assert(!pgstat_is_shutdown);
-
-   /*
-    * If we got as far as discovering our own database ID, we can report what
-    * we did to the collector.  Otherwise, we'd be sending an invalid
-    * database ID, so forget it.  (This means that accesses to pg_database
-    * during failed backend starts might never get counted.)
-    */
-   if (OidIsValid(MyDatabaseId))
-       pgstat_report_stat(true);
 
-#ifdef USE_ASSERT_CHECKING
-   pgstat_is_shutdown = true;
-#endif
-}
+/* ------------------------------------------------------------
+ * Helper / infrastructure functions
+ * ------------------------------------------------------------
+ */
 
 /* ----------
- * pgstat_initialize() -
- *
- * Initialize pgstats state, and set up our on-proc-exit hook. Called from
- * BaseInit().
+ * pgstat_setup_memcxt() -
  *
- * NOTE: MyDatabaseId isn't set yet; so the shutdown hook has to be careful.
+ * Create pgStatLocalContext, if not already done.
  * ----------
  */
-void
-pgstat_initialize(void)
+static void
+pgstat_setup_memcxt(void)
 {
-   Assert(!pgstat_is_initialized);
-
-   pgstat_wal_initialize();
-
-   /* Set up a process-exit hook to clean up */
-   before_shmem_exit(pgstat_shutdown_hook, 0);
-
-#ifdef USE_ASSERT_CHECKING
-   pgstat_is_initialized = true;
-#endif
+   if (!pgStatLocalContext)
+       pgStatLocalContext = AllocSetContextCreate(TopMemoryContext,
+                                                  "Statistics snapshot",
+                                                  ALLOCSET_SMALL_SIZES);
 }
 
-/* ------------------------------------------------------------
- * Local support functions follow
- * ------------------------------------------------------------
+/*
+ * Stats should only be reported after pgstat_initialize() and before
+ * pgstat_shutdown(). This check is put in a few central places to catch
+ * violations of this rule more easily.
  */
-
+#ifdef USE_ASSERT_CHECKING
+void
+pgstat_assert_is_up(void)
+{
+   Assert(pgstat_is_initialized && !pgstat_is_shutdown);
+}
+#endif
 
 /* ----------
  * pgstat_setheader() -
@@ -2003,7 +2082,6 @@ pgstat_get_db_entry(Oid databaseid, bool create)
    return result;
 }
 
-
 /*
  * Lookup the hash table entry for the specified table. If no hash
  * table entry exists, initialize it, if the create parameter is true.
@@ -2053,6 +2131,151 @@ pgstat_get_tab_entry(PgStat_StatDBEntry *dbentry, Oid tableoid, bool create)
    return result;
 }
 
+/* ----------
+ * pgstat_replslot_entry
+ *
+ * Return the entry of replication slot stats with the given name. Return
+ * NULL if not found and the caller didn't request to create it.
+ *
+ * create tells whether to create the new slot entry if it is not found.
+ * ----------
+ */
+static PgStat_StatReplSlotEntry *
+pgstat_get_replslot_entry(NameData name, bool create)
+{
+   PgStat_StatReplSlotEntry *slotent;
+   bool        found;
+
+   if (replSlotStatHash == NULL)
+   {
+       HASHCTL     hash_ctl;
+
+       /*
+        * Quick return NULL if the hash table is empty and the caller didn't
+        * request to create the entry.
+        */
+       if (!create)
+           return NULL;
+
+       hash_ctl.keysize = sizeof(NameData);
+       hash_ctl.entrysize = sizeof(PgStat_StatReplSlotEntry);
+       replSlotStatHash = hash_create("Replication slots hash",
+                                      PGSTAT_REPLSLOT_HASH_SIZE,
+                                      &hash_ctl,
+                                      HASH_ELEM | HASH_BLOBS);
+   }
+
+   slotent = (PgStat_StatReplSlotEntry *) hash_search(replSlotStatHash,
+                                                      (void *) &name,
+                                                      create ? HASH_ENTER : HASH_FIND,
+                                                      &found);
+
+   if (!slotent)
+   {
+       /* not found */
+       Assert(!create && !found);
+       return NULL;
+   }
+
+   /* initialize the entry */
+   if (create && !found)
+   {
+       namestrcpy(&(slotent->slotname), NameStr(name));
+       pgstat_reset_replslot(slotent, 0);
+   }
+
+   return slotent;
+}
+
+/* ----------
+ * pgstat_reset_replslot
+ *
+ * Reset the given replication slot stats.
+ * ----------
+ */
+static void
+pgstat_reset_replslot(PgStat_StatReplSlotEntry *slotent, TimestampTz ts)
+{
+   /* reset only counters. Don't clear slot name */
+   slotent->spill_txns = 0;
+   slotent->spill_count = 0;
+   slotent->spill_bytes = 0;
+   slotent->stream_txns = 0;
+   slotent->stream_count = 0;
+   slotent->stream_bytes = 0;
+   slotent->total_txns = 0;
+   slotent->total_bytes = 0;
+   slotent->stat_reset_timestamp = ts;
+}
+
+/* ----------
+ * pgstat_get_subscription_entry
+ *
+ * Return the subscription statistics entry with the given subscription OID.
+ * If no subscription entry exists, initialize it, if the create parameter is
+ * true.  Else, return NULL.
+ * ----------
+ */
+static PgStat_StatSubEntry *
+pgstat_get_subscription_entry(Oid subid, bool create)
+{
+   PgStat_StatSubEntry *subentry;
+   bool        found;
+   HASHACTION  action = (create ? HASH_ENTER : HASH_FIND);
+
+   if (subscriptionStatHash == NULL)
+   {
+       HASHCTL     hash_ctl;
+
+       /*
+        * Quick return NULL if the hash table is empty and the caller didn't
+        * request to create the entry.
+        */
+       if (!create)
+           return NULL;
+
+       hash_ctl.keysize = sizeof(Oid);
+       hash_ctl.entrysize = sizeof(PgStat_StatSubEntry);
+       subscriptionStatHash = hash_create("Subscription hash",
+                                          PGSTAT_SUBSCRIPTION_HASH_SIZE,
+                                          &hash_ctl,
+                                          HASH_ELEM | HASH_BLOBS);
+   }
+
+   subentry = (PgStat_StatSubEntry *) hash_search(subscriptionStatHash,
+                                                  (void *) &subid,
+                                                  action, &found);
+
+   if (!create && !found)
+       return NULL;
+
+   /* If not found, initialize the new one */
+   if (!found)
+       pgstat_reset_subscription(subentry, 0);
+
+   return subentry;
+}
+
+/* ----------
+ * pgstat_reset_subscription
+ *
+ * Reset the given subscription stats.
+ * ----------
+ */
+static void
+pgstat_reset_subscription(PgStat_StatSubEntry *subentry, TimestampTz ts)
+{
+   subentry->apply_error_count = 0;
+   subentry->sync_error_count = 0;
+   subentry->stat_reset_timestamp = ts;
+}
+
+
+/* ------------------------------------------------------------
+ * reading and writing of on-disk stats file
+ * ------------------------------------------------------------
+ */
+
 /* ----------
  * pgstat_write_statsfiles() -
  *     Write the global statistics file, as well as requested DB files.
@@ -3195,76 +3418,59 @@ backend_read_statsfile(void)
     * is sufficient.  Regular backends want a deep read for just the tables
     * they can see (MyDatabaseId + shared catalogs).
     */
-   if (IsAutoVacuumLauncherProcess())
-       pgStatDBHash = pgstat_read_statsfiles(InvalidOid, false, false);
-   else
-       pgStatDBHash = pgstat_read_statsfiles(MyDatabaseId, false, true);
-}
-
-
-/* ----------
- * pgstat_setup_memcxt() -
- *
- * Create pgStatLocalContext, if not already done.
- * ----------
- */
-static void
-pgstat_setup_memcxt(void)
-{
-   if (!pgStatLocalContext)
-       pgStatLocalContext = AllocSetContextCreate(TopMemoryContext,
-                                                  "Statistics snapshot",
-                                                  ALLOCSET_SMALL_SIZES);
+   if (IsAutoVacuumLauncherProcess())
+       pgStatDBHash = pgstat_read_statsfiles(InvalidOid, false, false);
+   else
+       pgStatDBHash = pgstat_read_statsfiles(MyDatabaseId, false, true);
 }
 
-/*
- * Stats should only be reported after pgstat_initialize() and before
- * pgstat_shutdown(). This check is put in a few central places to catch
- * violations of this rule more easily.
+/* ----------
+ * pgstat_write_statsfile_needed() -
+ *
+ * Do we need to write out any stats files?
+ * ----------
  */
-#ifdef USE_ASSERT_CHECKING
-void
-pgstat_assert_is_up(void)
+static bool
+pgstat_write_statsfile_needed(void)
 {
-   Assert(pgstat_is_initialized && !pgstat_is_shutdown);
-}
-#endif
+   if (pending_write_requests != NIL)
+       return true;
 
+   /* Everything was written recently */
+   return false;
+}
 
 /* ----------
- * pgstat_clear_snapshot() -
- *
- * Discard any data collected in the current transaction.  Any subsequent
- * request will cause new snapshots to be read.
+ * pgstat_db_requested() -
  *
- * This is also invoked during transaction commit or abort to discard
- * the no-longer-wanted snapshot.
+ * Checks whether stats for a particular DB need to be written to a file.
  * ----------
  */
-void
-pgstat_clear_snapshot(void)
+static bool
+pgstat_db_requested(Oid databaseid)
 {
-   pgstat_assert_is_up();
-
-   /* Release memory, if any was allocated */
-   if (pgStatLocalContext)
-       MemoryContextDelete(pgStatLocalContext);
-
-   /* Reset variables */
-   pgStatLocalContext = NULL;
-   pgStatDBHash = NULL;
-   replSlotStatHash = NULL;
-   subscriptionStatHash = NULL;
-
    /*
-    * Historically the backend_status.c facilities lived in this file, and
-    * were reset with the same function. For now keep it that way, and
-    * forward the reset request.
+    * If any requests are outstanding at all, we should write the stats for
+    * shared catalogs (the "database" with OID 0).  This ensures that
+    * backends will see up-to-date stats for shared catalogs, even though
+    * they send inquiry messages mentioning only their own DB.
     */
-   pgstat_clear_backend_activity_snapshot();
+   if (databaseid == InvalidOid && pending_write_requests != NIL)
+       return true;
+
+   /* Search to see if there's an open request to write this database. */
+   if (list_member_oid(pending_write_requests, databaseid))
+       return true;
+
+   return false;
 }
 
 
+/* ------------------------------------------------------------
+ * stats collector message processing functions
+ * ------------------------------------------------------------
+ */
+
 /* ----------
  * pgstat_recv_inquiry() -
  *
@@ -3357,7 +3563,6 @@ pgstat_recv_inquiry(PgStat_MsgInquiry *msg, int len)
                                         msg->databaseid);
 }
 
-
 /* ----------
  * pgstat_recv_tabstat() -
  *
@@ -3475,7 +3680,6 @@ pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len)
    }
 }
 
-
 /* ----------
  * pgstat_recv_tabpurge() -
  *
@@ -3508,7 +3712,6 @@ pgstat_recv_tabpurge(PgStat_MsgTabpurge *msg, int len)
    }
 }
 
-
 /* ----------
  * pgstat_recv_dropdb() -
  *
@@ -3551,7 +3754,6 @@ pgstat_recv_dropdb(PgStat_MsgDropdb *msg, int len)
    }
 }
 
-
 /* ----------
  * pgstat_recv_resetcounter() -
  *
@@ -3772,7 +3974,6 @@ pgstat_recv_resetsubcounter(PgStat_MsgResetsubcounter *msg, int len)
    }
 }
 
-
 /* ----------
  * pgstat_recv_autovac() -
  *
@@ -3880,7 +4081,6 @@ pgstat_recv_analyze(PgStat_MsgAnalyze *msg, int len)
    }
 }
 
-
 /* ----------
  * pgstat_recv_archiver() -
  *
@@ -4282,183 +4482,3 @@ pgstat_recv_subscription_error(PgStat_MsgSubscriptionError *msg, int len)
    else
        subentry->sync_error_count++;
 }
-
-/* ----------
- * pgstat_write_statsfile_needed() -
- *
- * Do we need to write out any stats files?
- * ----------
- */
-static bool
-pgstat_write_statsfile_needed(void)
-{
-   if (pending_write_requests != NIL)
-       return true;
-
-   /* Everything was written recently */
-   return false;
-}
-
-/* ----------
- * pgstat_db_requested() -
- *
- * Checks whether stats for a particular DB need to be written to a file.
- * ----------
- */
-static bool
-pgstat_db_requested(Oid databaseid)
-{
-   /*
-    * If any requests are outstanding at all, we should write the stats for
-    * shared catalogs (the "database" with OID 0).  This ensures that
-    * backends will see up-to-date stats for shared catalogs, even though
-    * they send inquiry messages mentioning only their own DB.
-    */
-   if (databaseid == InvalidOid && pending_write_requests != NIL)
-       return true;
-
-   /* Search to see if there's an open request to write this database. */
-   if (list_member_oid(pending_write_requests, databaseid))
-       return true;
-
-   return false;
-}
-
-/* ----------
- * pgstat_replslot_entry
- *
- * Return the entry of replication slot stats with the given name. Return
- * NULL if not found and the caller didn't request to create it.
- *
- * create tells whether to create the new slot entry if it is not found.
- * ----------
- */
-static PgStat_StatReplSlotEntry *
-pgstat_get_replslot_entry(NameData name, bool create)
-{
-   PgStat_StatReplSlotEntry *slotent;
-   bool        found;
-
-   if (replSlotStatHash == NULL)
-   {
-       HASHCTL     hash_ctl;
-
-       /*
-        * Quick return NULL if the hash table is empty and the caller didn't
-        * request to create the entry.
-        */
-       if (!create)
-           return NULL;
-
-       hash_ctl.keysize = sizeof(NameData);
-       hash_ctl.entrysize = sizeof(PgStat_StatReplSlotEntry);
-       replSlotStatHash = hash_create("Replication slots hash",
-                                      PGSTAT_REPLSLOT_HASH_SIZE,
-                                      &hash_ctl,
-                                      HASH_ELEM | HASH_BLOBS);
-   }
-
-   slotent = (PgStat_StatReplSlotEntry *) hash_search(replSlotStatHash,
-                                                      (void *) &name,
-                                                      create ? HASH_ENTER : HASH_FIND,
-                                                      &found);
-
-   if (!slotent)
-   {
-       /* not found */
-       Assert(!create && !found);
-       return NULL;
-   }
-
-   /* initialize the entry */
-   if (create && !found)
-   {
-       namestrcpy(&(slotent->slotname), NameStr(name));
-       pgstat_reset_replslot(slotent, 0);
-   }
-
-   return slotent;
-}
-
-/* ----------
- * pgstat_reset_replslot
- *
- * Reset the given replication slot stats.
- * ----------
- */
-static void
-pgstat_reset_replslot(PgStat_StatReplSlotEntry *slotent, TimestampTz ts)
-{
-   /* reset only counters. Don't clear slot name */
-   slotent->spill_txns = 0;
-   slotent->spill_count = 0;
-   slotent->spill_bytes = 0;
-   slotent->stream_txns = 0;
-   slotent->stream_count = 0;
-   slotent->stream_bytes = 0;
-   slotent->total_txns = 0;
-   slotent->total_bytes = 0;
-   slotent->stat_reset_timestamp = ts;
-}
-
-/* ----------
- * pgstat_get_subscription_entry
- *
- * Return the subscription statistics entry with the given subscription OID.
- * If no subscription entry exists, initialize it, if the create parameter is
- * true.  Else, return NULL.
- * ----------
- */
-static PgStat_StatSubEntry *
-pgstat_get_subscription_entry(Oid subid, bool create)
-{
-   PgStat_StatSubEntry *subentry;
-   bool        found;
-   HASHACTION  action = (create ? HASH_ENTER : HASH_FIND);
-
-   if (subscriptionStatHash == NULL)
-   {
-       HASHCTL     hash_ctl;
-
-       /*
-        * Quick return NULL if the hash table is empty and the caller didn't
-        * request to create the entry.
-        */
-       if (!create)
-           return NULL;
-
-       hash_ctl.keysize = sizeof(Oid);
-       hash_ctl.entrysize = sizeof(PgStat_StatSubEntry);
-       subscriptionStatHash = hash_create("Subscription hash",
-                                          PGSTAT_SUBSCRIPTION_HASH_SIZE,
-                                          &hash_ctl,
-                                          HASH_ELEM | HASH_BLOBS);
-   }
-
-   subentry = (PgStat_StatSubEntry *) hash_search(subscriptionStatHash,
-                                                  (void *) &subid,
-                                                  action, &found);
-
-   if (!create && !found)
-       return NULL;
-
-   /* If not found, initialize the new one */
-   if (!found)
-       pgstat_reset_subscription(subentry, 0);
-
-   return subentry;
-}
-
-/* ----------
- * pgstat_reset_subscription
- *
- * Reset the given subscription stats.
- * ----------
- */
-static void
-pgstat_reset_subscription(PgStat_StatSubEntry *subentry, TimestampTz ts)
-{
-   subentry->apply_error_count = 0;
-   subentry->sync_error_count = 0;
-   subentry->stat_reset_timestamp = ts;
-}
index cfb00ba65a5dfb2505b84c51662f0ea9cdd89176..534d595ca08435316bdc23d6af74706e78e9437c 100644 (file)
@@ -33,6 +33,7 @@
 /* Default directory to store temporary statistics data in */
 #define PG_STAT_TMP_DIR        "pg_stat_tmp"
 
+
 /* Values for track_functions GUC variable --- order is significant! */
 typedef enum TrackFunctionsLevel
 {
@@ -52,48 +53,74 @@ typedef enum SessionEndType
 } SessionEndType;
 
 /* ----------
- * The types of backend -> collector messages
+ * The data type used for counters.
  * ----------
  */
-typedef enum StatMsgType
+typedef int64 PgStat_Counter;
+
+/* Possible targets for resetting cluster-wide shared values */
+typedef enum PgStat_Shared_Reset_Target
 {
-   PGSTAT_MTYPE_DUMMY,
-   PGSTAT_MTYPE_INQUIRY,
-   PGSTAT_MTYPE_TABSTAT,
-   PGSTAT_MTYPE_TABPURGE,
-   PGSTAT_MTYPE_DROPDB,
-   PGSTAT_MTYPE_RESETCOUNTER,
-   PGSTAT_MTYPE_RESETSHAREDCOUNTER,
-   PGSTAT_MTYPE_RESETSINGLECOUNTER,
-   PGSTAT_MTYPE_RESETSLRUCOUNTER,
-   PGSTAT_MTYPE_RESETREPLSLOTCOUNTER,
-   PGSTAT_MTYPE_RESETSUBCOUNTER,
-   PGSTAT_MTYPE_AUTOVAC_START,
-   PGSTAT_MTYPE_VACUUM,
-   PGSTAT_MTYPE_ANALYZE,
-   PGSTAT_MTYPE_ARCHIVER,
-   PGSTAT_MTYPE_BGWRITER,
-   PGSTAT_MTYPE_CHECKPOINTER,
-   PGSTAT_MTYPE_WAL,
-   PGSTAT_MTYPE_SLRU,
-   PGSTAT_MTYPE_FUNCSTAT,
-   PGSTAT_MTYPE_FUNCPURGE,
-   PGSTAT_MTYPE_RECOVERYCONFLICT,
-   PGSTAT_MTYPE_TEMPFILE,
-   PGSTAT_MTYPE_DEADLOCK,
-   PGSTAT_MTYPE_CHECKSUMFAILURE,
-   PGSTAT_MTYPE_REPLSLOT,
-   PGSTAT_MTYPE_CONNECT,
-   PGSTAT_MTYPE_DISCONNECT,
-   PGSTAT_MTYPE_SUBSCRIPTIONDROP,
-   PGSTAT_MTYPE_SUBSCRIPTIONERROR,
-} StatMsgType;
+   RESET_ARCHIVER,
+   RESET_BGWRITER,
+   RESET_WAL
+} PgStat_Shared_Reset_Target;
+
+/* Possible object types for resetting single counters */
+typedef enum PgStat_Single_Reset_Type
+{
+   RESET_TABLE,
+   RESET_FUNCTION
+} PgStat_Single_Reset_Type;
+
+
+/* ------------------------------------------------------------
+ * Structures kept in backend local memory while accumulating counts
+ * ------------------------------------------------------------
+ */
 
 /* ----------
- * The data type used for counters.
+ * PgStat_FunctionCounts   The actual per-function counts kept by a backend
+ *
+ * This struct should contain only actual event counters, because we memcmp
+ * it against zeroes to detect whether there are any counts to transmit.
+ *
+ * Note that the time counters are in instr_time format here.  We convert to
+ * microseconds in PgStat_Counter format when transmitting to the collector.
  * ----------
  */
-typedef int64 PgStat_Counter;
+typedef struct PgStat_FunctionCounts
+{
+   PgStat_Counter f_numcalls;
+   instr_time  f_total_time;
+   instr_time  f_self_time;
+} PgStat_FunctionCounts;
+
+/* ----------
+ * PgStat_BackendFunctionEntry Entry in backend's per-function hash table
+ * ----------
+ */
+typedef struct PgStat_BackendFunctionEntry
+{
+   Oid         f_id;
+   PgStat_FunctionCounts f_counts;
+} PgStat_BackendFunctionEntry;
+
+/*
+ * Working state needed to accumulate per-function-call timing statistics.
+ */
+typedef struct PgStat_FunctionCallUsage
+{
+   /* Link to function's hashtable entry (must still be there at exit!) */
+   /* NULL means we are not tracking the current function call */
+   PgStat_FunctionCounts *fs;
+   /* Total time previously charged to function, as of function start */
+   instr_time  save_f_total_time;
+   /* Backend-wide total time as of function start */
+   instr_time  save_total;
+   /* system clock as of function start */
+   instr_time  f_start;
+} PgStat_FunctionCallUsage;
 
 /* ----------
  * PgStat_TableCounts          The actual per-table counts kept by a backend
@@ -137,27 +164,6 @@ typedef struct PgStat_TableCounts
    PgStat_Counter t_blocks_hit;
 } PgStat_TableCounts;
 
-/* Possible targets for resetting cluster-wide shared values */
-typedef enum PgStat_Shared_Reset_Target
-{
-   RESET_ARCHIVER,
-   RESET_BGWRITER,
-   RESET_WAL
-} PgStat_Shared_Reset_Target;
-
-/* Possible object types for resetting single counters */
-typedef enum PgStat_Single_Reset_Type
-{
-   RESET_TABLE,
-   RESET_FUNCTION
-} PgStat_Single_Reset_Type;
-
-/* ------------------------------------------------------------
- * Structures kept in backend local memory while accumulating counts
- * ------------------------------------------------------------
- */
-
-
 /* ----------
  * PgStat_TableStatus          Per-table status within a backend
  *
@@ -210,6 +216,43 @@ typedef struct PgStat_TableXactStatus
  * ------------------------------------------------------------
  */
 
+/* ----------
+ * The types of backend -> collector messages
+ * ----------
+ */
+typedef enum StatMsgType
+{
+   PGSTAT_MTYPE_DUMMY,
+   PGSTAT_MTYPE_INQUIRY,
+   PGSTAT_MTYPE_TABSTAT,
+   PGSTAT_MTYPE_TABPURGE,
+   PGSTAT_MTYPE_DROPDB,
+   PGSTAT_MTYPE_RESETCOUNTER,
+   PGSTAT_MTYPE_RESETSHAREDCOUNTER,
+   PGSTAT_MTYPE_RESETSINGLECOUNTER,
+   PGSTAT_MTYPE_RESETSLRUCOUNTER,
+   PGSTAT_MTYPE_RESETREPLSLOTCOUNTER,
+   PGSTAT_MTYPE_RESETSUBCOUNTER,
+   PGSTAT_MTYPE_AUTOVAC_START,
+   PGSTAT_MTYPE_VACUUM,
+   PGSTAT_MTYPE_ANALYZE,
+   PGSTAT_MTYPE_ARCHIVER,
+   PGSTAT_MTYPE_BGWRITER,
+   PGSTAT_MTYPE_CHECKPOINTER,
+   PGSTAT_MTYPE_WAL,
+   PGSTAT_MTYPE_SLRU,
+   PGSTAT_MTYPE_FUNCSTAT,
+   PGSTAT_MTYPE_FUNCPURGE,
+   PGSTAT_MTYPE_RECOVERYCONFLICT,
+   PGSTAT_MTYPE_TEMPFILE,
+   PGSTAT_MTYPE_DEADLOCK,
+   PGSTAT_MTYPE_CHECKSUMFAILURE,
+   PGSTAT_MTYPE_REPLSLOT,
+   PGSTAT_MTYPE_CONNECT,
+   PGSTAT_MTYPE_DISCONNECT,
+   PGSTAT_MTYPE_SUBSCRIPTIONDROP,
+   PGSTAT_MTYPE_SUBSCRIPTIONERROR,
+} StatMsgType;
 
 /* ----------
  * PgStat_MsgHdr               The common message header
@@ -241,7 +284,6 @@ typedef struct PgStat_MsgDummy
    PgStat_MsgHdr m_hdr;
 } PgStat_MsgDummy;
 
-
 /* ----------
  * PgStat_MsgInquiry           Sent by a backend to ask the collector
  *                             to write the stats file(s).
@@ -260,7 +302,6 @@ typedef struct PgStat_MsgDummy
  * effect unless that occurs.  We assume clock_time >= cutoff_time, though.
  * ----------
  */
-
 typedef struct PgStat_MsgInquiry
 {
    PgStat_MsgHdr m_hdr;
@@ -269,7 +310,6 @@ typedef struct PgStat_MsgInquiry
    Oid         databaseid;     /* requested DB (InvalidOid => shared only) */
 } PgStat_MsgInquiry;
 
-
 /* ----------
  * PgStat_TableEntry           Per-table info in a MsgTabstat
  * ----------
@@ -304,7 +344,6 @@ typedef struct PgStat_MsgTabstat
    PgStat_TableEntry m_entry[PGSTAT_NUM_TABENTRIES];
 } PgStat_MsgTabstat;
 
-
 /* ----------
  * PgStat_MsgTabpurge          Sent by the backend to tell the collector
  *                             about dead tables.
@@ -322,7 +361,6 @@ typedef struct PgStat_MsgTabpurge
    Oid         m_tableid[PGSTAT_NUM_TABPURGE];
 } PgStat_MsgTabpurge;
 
-
 /* ----------
  * PgStat_MsgDropdb                Sent by the backend to tell the collector
  *                             about a dropped database
@@ -334,7 +372,6 @@ typedef struct PgStat_MsgDropdb
    Oid         m_databaseid;
 } PgStat_MsgDropdb;
 
-
 /* ----------
  * PgStat_MsgResetcounter      Sent by the backend to tell the collector
  *                             to reset counters
@@ -405,7 +442,6 @@ typedef struct PgStat_MsgResetsubcounter
                                 * stats */
 } PgStat_MsgResetsubcounter;
 
-
 /* ----------
  * PgStat_MsgAutovacStart      Sent by the autovacuum daemon to signal
  *                             that a database is going to be processed
@@ -418,7 +454,6 @@ typedef struct PgStat_MsgAutovacStart
    TimestampTz m_start_time;
 } PgStat_MsgAutovacStart;
 
-
 /* ----------
  * PgStat_MsgVacuum                Sent by the backend or autovacuum daemon
  *                             after VACUUM
@@ -435,7 +470,6 @@ typedef struct PgStat_MsgVacuum
    PgStat_Counter m_dead_tuples;
 } PgStat_MsgVacuum;
 
-
 /* ----------
  * PgStat_MsgAnalyze           Sent by the backend or autovacuum daemon
  *                             after ANALYZE
@@ -453,7 +487,6 @@ typedef struct PgStat_MsgAnalyze
    PgStat_Counter m_dead_tuples;
 } PgStat_MsgAnalyze;
 
-
 /* ----------
  * PgStat_MsgArchiver          Sent by the archiver to update statistics.
  * ----------
@@ -601,33 +634,6 @@ typedef struct PgStat_MsgTempFile
    size_t      m_filesize;
 } PgStat_MsgTempFile;
 
-/* ----------
- * PgStat_FunctionCounts   The actual per-function counts kept by a backend
- *
- * This struct should contain only actual event counters, because we memcmp
- * it against zeroes to detect whether there are any counts to transmit.
- *
- * Note that the time counters are in instr_time format here.  We convert to
- * microseconds in PgStat_Counter format when transmitting to the collector.
- * ----------
- */
-typedef struct PgStat_FunctionCounts
-{
-   PgStat_Counter f_numcalls;
-   instr_time  f_total_time;
-   instr_time  f_self_time;
-} PgStat_FunctionCounts;
-
-/* ----------
- * PgStat_BackendFunctionEntry Entry in backend's per-function hash table
- * ----------
- */
-typedef struct PgStat_BackendFunctionEntry
-{
-   Oid         f_id;
-   PgStat_FunctionCounts f_counts;
-} PgStat_BackendFunctionEntry;
-
 /* ----------
  * PgStat_FunctionEntry            Per-function info in a MsgFuncstat
  * ----------
@@ -770,6 +776,48 @@ typedef union PgStat_Msg
 
 #define PGSTAT_FILE_FORMAT_ID  0x01A5BCA6
 
+/*
+ * Archiver statistics kept in the stats collector
+ */
+typedef struct PgStat_ArchiverStats
+{
+   PgStat_Counter archived_count;  /* archival successes */
+   char        last_archived_wal[MAX_XFN_CHARS + 1];   /* last WAL file
+                                                        * archived */
+   TimestampTz last_archived_timestamp;    /* last archival success time */
+   PgStat_Counter failed_count;    /* failed archival attempts */
+   char        last_failed_wal[MAX_XFN_CHARS + 1]; /* WAL file involved in
+                                                    * last failure */
+   TimestampTz last_failed_timestamp;  /* last archival failure time */
+   TimestampTz stat_reset_timestamp;
+} PgStat_ArchiverStats;
+
+/*
+ * Background writer statistics kept in the stats collector
+ */
+typedef struct PgStat_BgWriterStats
+{
+   PgStat_Counter buf_written_clean;
+   PgStat_Counter maxwritten_clean;
+   PgStat_Counter buf_alloc;
+   TimestampTz stat_reset_timestamp;
+} PgStat_BgWriterStats;
+
+/*
+ * Checkpointer statistics kept in the stats collector
+ */
+typedef struct PgStat_CheckpointerStats
+{
+   TimestampTz stats_timestamp;    /* time of stats file update */
+   PgStat_Counter timed_checkpoints;
+   PgStat_Counter requested_checkpoints;
+   PgStat_Counter checkpoint_write_time;   /* times in milliseconds */
+   PgStat_Counter checkpoint_sync_time;
+   PgStat_Counter buf_written_checkpoints;
+   PgStat_Counter buf_written_backend;
+   PgStat_Counter buf_fsync_backend;
+} PgStat_CheckpointerStats;
+
 /* ----------
  * PgStat_StatDBEntry          The collector's data per database
  * ----------
@@ -818,100 +866,19 @@ typedef struct PgStat_StatDBEntry
    HTAB       *functions;
 } PgStat_StatDBEntry;
 
-
 /* ----------
- * PgStat_StatTabEntry         The collector's data per table (or index)
+ * PgStat_StatFuncEntry            The collector's data per function
  * ----------
  */
-typedef struct PgStat_StatTabEntry
+typedef struct PgStat_StatFuncEntry
 {
-   Oid         tableid;
-
-   PgStat_Counter numscans;
+   Oid         functionid;
 
-   PgStat_Counter tuples_returned;
-   PgStat_Counter tuples_fetched;
+   PgStat_Counter f_numcalls;
 
-   PgStat_Counter tuples_inserted;
-   PgStat_Counter tuples_updated;
-   PgStat_Counter tuples_deleted;
-   PgStat_Counter tuples_hot_updated;
-
-   PgStat_Counter n_live_tuples;
-   PgStat_Counter n_dead_tuples;
-   PgStat_Counter changes_since_analyze;
-   PgStat_Counter inserts_since_vacuum;
-
-   PgStat_Counter blocks_fetched;
-   PgStat_Counter blocks_hit;
-
-   TimestampTz vacuum_timestamp;   /* user initiated vacuum */
-   PgStat_Counter vacuum_count;
-   TimestampTz autovac_vacuum_timestamp;   /* autovacuum initiated */
-   PgStat_Counter autovac_vacuum_count;
-   TimestampTz analyze_timestamp;  /* user initiated */
-   PgStat_Counter analyze_count;
-   TimestampTz autovac_analyze_timestamp;  /* autovacuum initiated */
-   PgStat_Counter autovac_analyze_count;
-} PgStat_StatTabEntry;
-
-
-/* ----------
- * PgStat_StatFuncEntry            The collector's data per function
- * ----------
- */
-typedef struct PgStat_StatFuncEntry
-{
-   Oid         functionid;
-
-   PgStat_Counter f_numcalls;
-
-   PgStat_Counter f_total_time;    /* times in microseconds */
-   PgStat_Counter f_self_time;
-} PgStat_StatFuncEntry;
-
-
-/*
- * Archiver statistics kept in the stats collector
- */
-typedef struct PgStat_ArchiverStats
-{
-   PgStat_Counter archived_count;  /* archival successes */
-   char        last_archived_wal[MAX_XFN_CHARS + 1];   /* last WAL file
-                                                        * archived */
-   TimestampTz last_archived_timestamp;    /* last archival success time */
-   PgStat_Counter failed_count;    /* failed archival attempts */
-   char        last_failed_wal[MAX_XFN_CHARS + 1]; /* WAL file involved in
-                                                    * last failure */
-   TimestampTz last_failed_timestamp;  /* last archival failure time */
-   TimestampTz stat_reset_timestamp;
-} PgStat_ArchiverStats;
-
-/*
- * Background writer statistics kept in the stats collector
- */
-typedef struct PgStat_BgWriterStats
-{
-   PgStat_Counter buf_written_clean;
-   PgStat_Counter maxwritten_clean;
-   PgStat_Counter buf_alloc;
-   TimestampTz stat_reset_timestamp;
-} PgStat_BgWriterStats;
-
-/*
- * Checkpointer statistics kept in the stats collector
- */
-typedef struct PgStat_CheckpointerStats
-{
-   TimestampTz stats_timestamp;    /* time of stats file update */
-   PgStat_Counter timed_checkpoints;
-   PgStat_Counter requested_checkpoints;
-   PgStat_Counter checkpoint_write_time;   /* times in milliseconds */
-   PgStat_Counter checkpoint_sync_time;
-   PgStat_Counter buf_written_checkpoints;
-   PgStat_Counter buf_written_backend;
-   PgStat_Counter buf_fsync_backend;
-} PgStat_CheckpointerStats;
+   PgStat_Counter f_total_time;    /* times in microseconds */
+   PgStat_Counter f_self_time;
+} PgStat_StatFuncEntry;
 
 /*
  * Global statistics kept in the stats collector
@@ -925,20 +892,21 @@ typedef struct PgStat_GlobalStats
 } PgStat_GlobalStats;
 
 /*
- * WAL statistics kept in the stats collector
+ * Replication slot statistics kept in the stats collector
  */
-typedef struct PgStat_WalStats
+typedef struct PgStat_StatReplSlotEntry
 {
-   PgStat_Counter wal_records;
-   PgStat_Counter wal_fpi;
-   uint64      wal_bytes;
-   PgStat_Counter wal_buffers_full;
-   PgStat_Counter wal_write;
-   PgStat_Counter wal_sync;
-   PgStat_Counter wal_write_time;
-   PgStat_Counter wal_sync_time;
+   NameData    slotname;
+   PgStat_Counter spill_txns;
+   PgStat_Counter spill_count;
+   PgStat_Counter spill_bytes;
+   PgStat_Counter stream_txns;
+   PgStat_Counter stream_count;
+   PgStat_Counter stream_bytes;
+   PgStat_Counter total_txns;
+   PgStat_Counter total_bytes;
    TimestampTz stat_reset_timestamp;
-} PgStat_WalStats;
+} PgStat_StatReplSlotEntry;
 
 /*
  * SLRU statistics kept in the stats collector
@@ -955,23 +923,6 @@ typedef struct PgStat_SLRUStats
    TimestampTz stat_reset_timestamp;
 } PgStat_SLRUStats;
 
-/*
- * Replication slot statistics kept in the stats collector
- */
-typedef struct PgStat_StatReplSlotEntry
-{
-   NameData    slotname;
-   PgStat_Counter spill_txns;
-   PgStat_Counter spill_count;
-   PgStat_Counter spill_bytes;
-   PgStat_Counter stream_txns;
-   PgStat_Counter stream_count;
-   PgStat_Counter stream_bytes;
-   PgStat_Counter total_txns;
-   PgStat_Counter total_bytes;
-   TimestampTz stat_reset_timestamp;
-} PgStat_StatReplSlotEntry;
-
 /*
  * Subscription statistics kept in the stats collector.
  */
@@ -984,126 +935,174 @@ typedef struct PgStat_StatSubEntry
    TimestampTz stat_reset_timestamp;
 } PgStat_StatSubEntry;
 
-/*
- * Working state needed to accumulate per-function-call timing statistics.
+/* ----------
+ * PgStat_StatTabEntry         The collector's data per table (or index)
+ * ----------
  */
-typedef struct PgStat_FunctionCallUsage
+typedef struct PgStat_StatTabEntry
 {
-   /* Link to function's hashtable entry (must still be there at exit!) */
-   /* NULL means we are not tracking the current function call */
-   PgStat_FunctionCounts *fs;
-   /* Total time previously charged to function, as of function start */
-   instr_time  save_f_total_time;
-   /* Backend-wide total time as of function start */
-   instr_time  save_total;
-   /* system clock as of function start */
-   instr_time  f_start;
-} PgStat_FunctionCallUsage;
+   Oid         tableid;
 
+   PgStat_Counter numscans;
 
-/* ----------
- * GUC parameters
- * ----------
- */
-extern PGDLLIMPORT bool pgstat_track_counts;
-extern PGDLLIMPORT int pgstat_track_functions;
-extern char *pgstat_stat_directory;
-extern char *pgstat_stat_tmpname;
-extern char *pgstat_stat_filename;
+   PgStat_Counter tuples_returned;
+   PgStat_Counter tuples_fetched;
 
-/*
- * BgWriter statistics counters are updated directly by bgwriter and bufmgr
- */
-extern PgStat_MsgBgWriter PendingBgWriterStats;
+   PgStat_Counter tuples_inserted;
+   PgStat_Counter tuples_updated;
+   PgStat_Counter tuples_deleted;
+   PgStat_Counter tuples_hot_updated;
 
-/*
- * Checkpointer statistics counters are updated directly by checkpointer and
- * bufmgr.
- */
-extern PgStat_MsgCheckpointer PendingCheckpointerStats;
+   PgStat_Counter n_live_tuples;
+   PgStat_Counter n_dead_tuples;
+   PgStat_Counter changes_since_analyze;
+   PgStat_Counter inserts_since_vacuum;
 
-/*
- * WAL statistics counter is updated by backends and background processes
- */
-extern PgStat_MsgWal WalStats;
+   PgStat_Counter blocks_fetched;
+   PgStat_Counter blocks_hit;
 
-/*
- * Updated by pgstat_count_buffer_*_time macros
- */
-extern PgStat_Counter pgStatBlockReadTime;
-extern PgStat_Counter pgStatBlockWriteTime;
+   TimestampTz vacuum_timestamp;   /* user initiated vacuum */
+   PgStat_Counter vacuum_count;
+   TimestampTz autovac_vacuum_timestamp;   /* autovacuum initiated */
+   PgStat_Counter autovac_vacuum_count;
+   TimestampTz analyze_timestamp;  /* user initiated */
+   PgStat_Counter analyze_count;
+   TimestampTz autovac_analyze_timestamp;  /* autovacuum initiated */
+   PgStat_Counter autovac_analyze_count;
+} PgStat_StatTabEntry;
 
 /*
- * Updated by pgstat_count_conn_*_time macros, called by
- * pgstat_report_activity().
+ * WAL statistics kept in the stats collector
  */
-extern PgStat_Counter pgStatActiveTime;
-extern PgStat_Counter pgStatTransactionIdleTime;
+typedef struct PgStat_WalStats
+{
+   PgStat_Counter wal_records;
+   PgStat_Counter wal_fpi;
+   uint64      wal_bytes;
+   PgStat_Counter wal_buffers_full;
+   PgStat_Counter wal_write;
+   PgStat_Counter wal_sync;
+   PgStat_Counter wal_write_time;
+   PgStat_Counter wal_sync_time;
+   TimestampTz stat_reset_timestamp;
+} PgStat_WalStats;
 
 
 /*
- * Updated by the traffic cop and in errfinish()
+ * Functions in pgstat.c
  */
-extern SessionEndType pgStatSessionEndCause;
 
-/* ----------
- * Functions called from postmaster
- * ----------
- */
+/* functions called from postmaster */
 extern void pgstat_init(void);
-extern int pgstat_start(void);
 extern void pgstat_reset_all(void);
+extern int pgstat_start(void);
 extern void allow_immediate_pgstat_restart(void);
 
 #ifdef EXEC_BACKEND
 extern void PgstatCollectorMain(int argc, char *argv[]) pg_attribute_noreturn();
 #endif
 
+/* Functions for backend initialization */
+extern void pgstat_initialize(void);
 
-/* ----------
- * Functions called from backends
- * ----------
- */
-extern void pgstat_ping(void);
+/* transactional integration */
+extern void AtEOXact_PgStat(bool isCommit, bool parallel);
+extern void AtEOSubXact_PgStat(bool isCommit, int nestDepth);
+extern void AtPrepare_PgStat(void);
+extern void PostPrepare_PgStat(void);
+extern void pgstat_clear_snapshot(void);
 
+/* Functions called from backends */
 extern void pgstat_report_stat(bool force);
 extern void pgstat_vacuum_stat(void);
-extern void pgstat_drop_database(Oid databaseid);
+extern void pgstat_ping(void);
 
-extern void pgstat_clear_snapshot(void);
 extern void pgstat_reset_counters(void);
-extern void pgstat_reset_shared_counters(const char *);
 extern void pgstat_reset_single_counter(Oid objectid, PgStat_Single_Reset_Type type);
-extern void pgstat_reset_slru_counter(const char *);
-extern void pgstat_reset_replslot_counter(const char *name);
-extern void pgstat_reset_subscription_counter(Oid subid);
+extern void pgstat_reset_shared_counters(const char *);
 
-extern void pgstat_report_connect(Oid dboid);
-extern void pgstat_report_autovac(Oid dboid);
-extern void pgstat_report_vacuum(Oid tableoid, bool shared,
-                                PgStat_Counter livetuples, PgStat_Counter deadtuples);
-extern void pgstat_report_analyze(Relation rel,
-                                 PgStat_Counter livetuples, PgStat_Counter deadtuples,
-                                 bool resetcounter);
+/* stats accessors */
+extern PgStat_ArchiverStats *pgstat_fetch_stat_archiver(void);
+extern PgStat_BgWriterStats *pgstat_fetch_stat_bgwriter(void);
+extern PgStat_CheckpointerStats *pgstat_fetch_stat_checkpointer(void);
+extern PgStat_StatDBEntry *pgstat_fetch_stat_dbentry(Oid dbid);
+extern PgStat_StatFuncEntry *pgstat_fetch_stat_funcentry(Oid funcid);
+extern PgStat_GlobalStats *pgstat_fetch_global(void);
+extern PgStat_StatReplSlotEntry *pgstat_fetch_replslot(NameData slotname);
+extern PgStat_StatSubEntry *pgstat_fetch_stat_subscription(Oid subid);
+extern PgStat_SLRUStats *pgstat_fetch_slru(void);
+extern PgStat_StatTabEntry *pgstat_fetch_stat_tabentry(Oid relid);
+extern PgStat_WalStats *pgstat_fetch_stat_wal(void);
+
+
+/*
+ * Functions in pgstat_archiver.c
+ */
+
+extern void pgstat_send_archiver(const char *xlog, bool failed);
+
+
+/*
+ * Functions in pgstat_bgwriter.c
+ */
+
+extern void pgstat_send_bgwriter(void);
+
+
+/*
+ * Functions in pgstat_checkpointer.c
+ */
+
+extern void pgstat_send_checkpointer(void);
+
+
+/*
+ * Functions in pgstat_database.c
+ */
 
+extern void pgstat_drop_database(Oid databaseid);
 extern void pgstat_report_recovery_conflict(int reason);
 extern void pgstat_report_deadlock(void);
 extern void pgstat_report_checksum_failures_in_db(Oid dboid, int failurecount);
 extern void pgstat_report_checksum_failure(void);
-extern void pgstat_report_replslot(const PgStat_StatReplSlotEntry *repSlotStat);
-extern void pgstat_report_replslot_create(const char *slotname);
-extern void pgstat_report_replslot_drop(const char *slotname);
-extern void pgstat_report_subscription_error(Oid subid, bool is_apply_error);
-extern void pgstat_report_subscription_drop(Oid subid);
+extern void pgstat_report_connect(Oid dboid);
 
-extern void pgstat_initialize(void);
+#define pgstat_count_buffer_read_time(n)                           \
+   (pgStatBlockReadTime += (n))
+#define pgstat_count_buffer_write_time(n)                          \
+   (pgStatBlockWriteTime += (n))
+#define pgstat_count_conn_active_time(n)                           \
+   (pgStatActiveTime += (n))
+#define pgstat_count_conn_txn_idle_time(n)                         \
+   (pgStatTransactionIdleTime += (n))
 
 
-extern PgStat_TableStatus *find_tabstat_entry(Oid rel_id);
+/*
+ * Functions in pgstat_function.c
+ */
+
+struct FunctionCallInfoBaseData;
+extern void pgstat_init_function_usage(struct FunctionCallInfoBaseData *fcinfo,
+                                      PgStat_FunctionCallUsage *fcu);
+extern void pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu,
+                                     bool finalize);
+
 extern PgStat_BackendFunctionEntry *find_funcstat_entry(Oid func_id);
 
+
+/*
+ * Functions in pgstat_relation.c
+ */
+
 extern void pgstat_relation_init(Relation rel);
 
+extern void pgstat_report_autovac(Oid dboid);
+extern void pgstat_report_vacuum(Oid tableoid, bool shared,
+                                PgStat_Counter livetuples, PgStat_Counter deadtuples);
+extern void pgstat_report_analyze(Relation rel,
+                                 PgStat_Counter livetuples, PgStat_Counter deadtuples,
+                                 bool resetcounter);
+
 #define pgstat_relation_should_count(rel)                           \
    (likely((rel)->pgstat_info != NULL))
 
@@ -1144,14 +1143,6 @@ extern void pgstat_relation_init(Relation rel);
        if (pgstat_relation_should_count(rel))                      \
            (rel)->pgstat_info->t_counts.t_blocks_hit++;            \
    } while (0)
-#define pgstat_count_buffer_read_time(n)                           \
-   (pgStatBlockReadTime += (n))
-#define pgstat_count_buffer_write_time(n)                          \
-   (pgStatBlockWriteTime += (n))
-#define pgstat_count_conn_active_time(n)                           \
-   (pgStatActiveTime += (n))
-#define pgstat_count_conn_txn_idle_time(n)                         \
-   (pgStatTransactionIdleTime += (n))
 
 extern void pgstat_count_heap_insert(Relation rel, PgStat_Counter n);
 extern void pgstat_count_heap_update(Relation rel, bool hot);
@@ -1159,45 +1150,29 @@ extern void pgstat_count_heap_delete(Relation rel);
 extern void pgstat_count_truncate(Relation rel);
 extern void pgstat_update_heap_dead_tuples(Relation rel, int delta);
 
-struct FunctionCallInfoBaseData;
-extern void pgstat_init_function_usage(struct FunctionCallInfoBaseData *fcinfo,
-                                      PgStat_FunctionCallUsage *fcu);
-extern void pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu,
-                                     bool finalize);
-
-extern void AtEOXact_PgStat(bool isCommit, bool parallel);
-extern void AtEOSubXact_PgStat(bool isCommit, int nestDepth);
-
-extern void AtPrepare_PgStat(void);
-extern void PostPrepare_PgStat(void);
-
 extern void pgstat_twophase_postcommit(TransactionId xid, uint16 info,
                                       void *recdata, uint32 len);
 extern void pgstat_twophase_postabort(TransactionId xid, uint16 info,
                                      void *recdata, uint32 len);
 
-extern void pgstat_send_archiver(const char *xlog, bool failed);
-extern void pgstat_send_bgwriter(void);
-extern void pgstat_send_checkpointer(void);
-extern void pgstat_send_wal(bool force);
+extern PgStat_TableStatus *find_tabstat_entry(Oid rel_id);
 
-/* ----------
- * Support functions for the SQL-callable functions to
- * generate the pgstat* views.
- * ----------
+
+/*
+ * Functions in pgstat_replslot.c
  */
-extern PgStat_StatDBEntry *pgstat_fetch_stat_dbentry(Oid dbid);
-extern PgStat_StatTabEntry *pgstat_fetch_stat_tabentry(Oid relid);
-extern PgStat_StatFuncEntry *pgstat_fetch_stat_funcentry(Oid funcid);
-extern PgStat_StatSubEntry *pgstat_fetch_stat_subscription(Oid subid);
-extern PgStat_ArchiverStats *pgstat_fetch_stat_archiver(void);
-extern PgStat_BgWriterStats *pgstat_fetch_stat_bgwriter(void);
-extern PgStat_CheckpointerStats *pgstat_fetch_stat_checkpointer(void);
-extern PgStat_GlobalStats *pgstat_fetch_global(void);
-extern PgStat_WalStats *pgstat_fetch_stat_wal(void);
-extern PgStat_SLRUStats *pgstat_fetch_slru(void);
-extern PgStat_StatReplSlotEntry *pgstat_fetch_replslot(NameData slotname);
 
+extern void pgstat_reset_replslot_counter(const char *name);
+extern void pgstat_report_replslot(const PgStat_StatReplSlotEntry *repSlotStat);
+extern void pgstat_report_replslot_create(const char *slotname);
+extern void pgstat_report_replslot_drop(const char *slotname);
+
+
+/*
+ * Functions in pgstat_slru.c
+ */
+
+extern void pgstat_reset_slru_counter(const char *);
 extern void pgstat_count_slru_page_zeroed(int slru_idx);
 extern void pgstat_count_slru_page_hit(int slru_idx);
 extern void pgstat_count_slru_page_read(int slru_idx);
@@ -1208,4 +1183,79 @@ extern void pgstat_count_slru_truncate(int slru_idx);
 extern const char *pgstat_slru_name(int slru_idx);
 extern int pgstat_slru_index(const char *name);
 
+
+/*
+ * Functions in pgstat_subscription.c
+ */
+
+extern void pgstat_reset_subscription_counter(Oid subid);
+extern void pgstat_report_subscription_error(Oid subid, bool is_apply_error);
+extern void pgstat_report_subscription_drop(Oid subid);
+
+
+/*
+ * Functions in pgstat_wal.c
+ */
+
+extern void pgstat_send_wal(bool force);
+
+
+/*
+ * Variables in pgstat.c
+ */
+
+/* GUC parameters */
+extern PGDLLIMPORT bool pgstat_track_counts;
+extern PGDLLIMPORT int pgstat_track_functions;
+extern char *pgstat_stat_directory;
+extern char *pgstat_stat_tmpname;
+extern char *pgstat_stat_filename;
+
+
+/*
+ * Variables in pgstat_bgwriter.c
+ */
+
+/* updated directly by bgwriter and bufmgr */
+extern PgStat_MsgBgWriter PendingBgWriterStats;
+
+
+/*
+ * Variables in pgstat_checkpointer.c
+ */
+
+/*
+ * Checkpointer statistics counters are updated directly by checkpointer and
+ * bufmgr.
+ */
+extern PgStat_MsgCheckpointer PendingCheckpointerStats;
+
+
+/*
+ * Variables in pgstat_database.c
+ */
+
+/* Updated by pgstat_count_buffer_*_time macros */
+extern PgStat_Counter pgStatBlockReadTime;
+extern PgStat_Counter pgStatBlockWriteTime;
+
+/*
+ * Updated by pgstat_count_conn_*_time macros, called by
+ * pgstat_report_activity().
+ */
+extern PgStat_Counter pgStatActiveTime;
+extern PgStat_Counter pgStatTransactionIdleTime;
+
+/* updated by the traffic cop and in errfinish() */
+extern SessionEndType pgStatSessionEndCause;
+
+
+/*
+ * Variables in pgstat_wal.c
+ */
+
+/* updated directly by backends and background processes */
+extern PgStat_MsgWal WalStats;
+
+
 #endif                         /* PGSTAT_H */