From cdbeaedb114216847c6c5f92df8dd285cf116d17 Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Date: Fri, 9 Nov 2018 15:48:49 +0900
Subject: [PATCH 6/7] Split out backend status monitor part from pgstat

A large file, pgstat.c, contained two major facilities, backend status
monitor and database usage monitor. Split out the former part from the
file and name the module "bestatus". The names of individual functions
are left alone except for some conficts.
---
 contrib/pg_prewarm/autoprewarm.c                   |    2 +-
 contrib/pg_stat_statements/pg_stat_statements.c    |    1 +
 contrib/postgres_fdw/connection.c                  |    2 +-
 src/backend/Makefile                               |    2 +-
 src/backend/access/heap/rewriteheap.c              |    4 +-
 src/backend/access/nbtree/nbtree.c                 |    2 +-
 src/backend/access/nbtree/nbtsort.c                |    2 +-
 src/backend/access/transam/clog.c                  |    2 +-
 src/backend/access/transam/parallel.c              |    2 +-
 src/backend/access/transam/slru.c                  |    2 +-
 src/backend/access/transam/timeline.c              |    2 +-
 src/backend/access/transam/twophase.c              |    1 +
 src/backend/access/transam/xact.c                  |    1 +
 src/backend/access/transam/xlog.c                  |    1 +
 src/backend/access/transam/xlogfuncs.c             |    2 +-
 src/backend/access/transam/xlogutils.c             |    2 +-
 src/backend/bootstrap/bootstrap.c                  |    8 +-
 src/backend/commands/vacuumlazy.c                  |    1 +
 src/backend/executor/execParallel.c                |    2 +-
 src/backend/executor/nodeBitmapHeapscan.c          |    1 +
 src/backend/executor/nodeGather.c                  |    2 +-
 src/backend/executor/nodeHash.c                    |    2 +-
 src/backend/executor/nodeHashjoin.c                |    2 +-
 src/backend/libpq/be-secure-openssl.c              |    2 +-
 src/backend/libpq/be-secure.c                      |    2 +-
 src/backend/libpq/pqmq.c                           |    2 +-
 src/backend/postmaster/Makefile                    |    2 +-
 src/backend/postmaster/autovacuum.c                |    1 +
 src/backend/postmaster/bgworker.c                  |    2 +-
 src/backend/postmaster/bgwriter.c                  |    1 +
 src/backend/postmaster/checkpointer.c              |    1 +
 src/backend/postmaster/pgarch.c                    |    1 +
 src/backend/postmaster/postmaster.c                |    1 +
 src/backend/postmaster/syslogger.c                 |    2 +-
 src/backend/postmaster/walwriter.c                 |    2 +-
 src/backend/replication/basebackup.c               |    2 +-
 .../libpqwalreceiver/libpqwalreceiver.c            |    2 +-
 src/backend/replication/logical/launcher.c         |    2 +-
 src/backend/replication/logical/origin.c           |    3 +-
 src/backend/replication/logical/reorderbuffer.c    |    2 +-
 src/backend/replication/logical/snapbuild.c        |    2 +-
 src/backend/replication/logical/tablesync.c        |    6 +-
 src/backend/replication/logical/worker.c           |   11 +-
 src/backend/replication/slot.c                     |    2 +-
 src/backend/replication/syncrep.c                  |    2 +-
 src/backend/replication/walreceiver.c              |    2 +-
 src/backend/replication/walsender.c                |    2 +-
 src/backend/statmon/Makefile                       |   17 +
 src/backend/statmon/bestatus.c                     | 1756 ++++++++++++++++++++
 src/backend/{postmaster => statmon}/pgstat.c       | 1727 +------------------
 src/backend/storage/buffer/bufmgr.c                |    1 +
 src/backend/storage/file/buffile.c                 |    2 +-
 src/backend/storage/file/copydir.c                 |    2 +-
 src/backend/storage/file/fd.c                      |    1 +
 src/backend/storage/ipc/dsm_impl.c                 |    2 +-
 src/backend/storage/ipc/latch.c                    |    2 +-
 src/backend/storage/ipc/procarray.c                |    2 +-
 src/backend/storage/ipc/shm_mq.c                   |    2 +-
 src/backend/storage/ipc/standby.c                  |    2 +-
 src/backend/storage/lmgr/deadlock.c                |    1 +
 src/backend/storage/lmgr/lwlock.c                  |    2 +-
 src/backend/storage/lmgr/predicate.c               |    2 +-
 src/backend/storage/lmgr/proc.c                    |    2 +-
 src/backend/storage/smgr/md.c                      |    2 +-
 src/backend/tcop/postgres.c                        |    1 +
 src/backend/utils/adt/misc.c                       |    2 +-
 src/backend/utils/adt/pgstatfuncs.c                |    1 +
 src/backend/utils/cache/relmapper.c                |    2 +-
 src/backend/utils/init/miscinit.c                  |    2 +-
 src/backend/utils/init/postinit.c                  |    4 +
 src/backend/utils/misc/guc.c                       |    1 +
 src/include/bestatus.h                             |  544 ++++++
 src/include/pgstat.h                               |  514 +-----
 73 files changed, 2441 insertions(+), 2260 deletions(-)
 create mode 100644 src/backend/statmon/Makefile
 create mode 100644 src/backend/statmon/bestatus.c
 rename src/backend/{postmaster => statmon}/pgstat.c (70%)
 create mode 100644 src/include/bestatus.h

diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c
index 03bf90ce2d..41be8c6c65 100644
--- a/contrib/pg_prewarm/autoprewarm.c
+++ b/contrib/pg_prewarm/autoprewarm.c
@@ -30,10 +30,10 @@
 
 #include "access/heapam.h"
 #include "access/xact.h"
+#include "bestatus.h"
 #include "catalog/pg_class.h"
 #include "catalog/pg_type.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "postmaster/bgworker.h"
 #include "storage/buf_internals.h"
 #include "storage/dsm.h"
diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c
index ec2fa9881c..3a35798cfb 100644
--- a/contrib/pg_stat_statements/pg_stat_statements.c
+++ b/contrib/pg_stat_statements/pg_stat_statements.c
@@ -62,6 +62,7 @@
 #include <unistd.h>
 
 #include "access/hash.h"
+#include "bestatus.h"
 #include "catalog/pg_authid.h"
 #include "executor/instrument.h"
 #include "funcapi.h"
diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c
index fe4893a8e0..e2b250fde4 100644
--- a/contrib/postgres_fdw/connection.c
+++ b/contrib/postgres_fdw/connection.c
@@ -15,11 +15,11 @@
 #include "postgres_fdw.h"
 
 #include "access/htup_details.h"
+#include "bestatus.h"
 #include "catalog/pg_user_mapping.h"
 #include "access/xact.h"
 #include "mb/pg_wchar.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "storage/latch.h"
 #include "utils/hsearch.h"
 #include "utils/inval.h"
diff --git a/src/backend/Makefile b/src/backend/Makefile
index 3a58bf6685..9921dca7f9 100644
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -20,7 +20,7 @@ include $(top_builddir)/src/Makefile.global
 SUBDIRS = access bootstrap catalog parser commands executor foreign lib libpq \
 	main nodes optimizer partitioning port postmaster \
 	regex replication rewrite \
-	statistics storage tcop tsearch utils $(top_builddir)/src/timezone \
+	statistics statmon storage tcop tsearch utils $(top_builddir)/src/timezone \
 	jit
 
 include $(srcdir)/common.mk
diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c
index c5db75afa1..30890f11ea 100644
--- a/src/backend/access/heap/rewriteheap.c
+++ b/src/backend/access/heap/rewriteheap.c
@@ -115,12 +115,12 @@
 #include "access/xact.h"
 #include "access/xloginsert.h"
 
+#include "bestatus.h"
+
 #include "catalog/catalog.h"
 
 #include "lib/ilist.h"
 
-#include "pgstat.h"
-
 #include "replication/logical.h"
 #include "replication/slot.h"
 
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index e8725fbbe1..6679dbc3a5 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -22,10 +22,10 @@
 #include "access/nbtxlog.h"
 #include "access/relscan.h"
 #include "access/xlog.h"
+#include "bestatus.h"
 #include "commands/vacuum.h"
 #include "miscadmin.h"
 #include "nodes/execnodes.h"
-#include "pgstat.h"
 #include "postmaster/autovacuum.h"
 #include "storage/condition_variable.h"
 #include "storage/indexfsm.h"
diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c
index 16f5755777..14d183b0da 100644
--- a/src/backend/access/nbtree/nbtsort.c
+++ b/src/backend/access/nbtree/nbtsort.c
@@ -63,9 +63,9 @@
 #include "access/xact.h"
 #include "access/xlog.h"
 #include "access/xloginsert.h"
+#include "bestatus.h"
 #include "catalog/index.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "storage/smgr.h"
 #include "tcop/tcopprot.h"		/* pgrminclude ignore */
 #include "utils/rel.h"
diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c
index 8b7ff5b0c2..9971bfe4f2 100644
--- a/src/backend/access/transam/clog.c
+++ b/src/backend/access/transam/clog.c
@@ -38,8 +38,8 @@
 #include "access/xlog.h"
 #include "access/xloginsert.h"
 #include "access/xlogutils.h"
+#include "bestatus.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "pg_trace.h"
 #include "storage/proc.h"
 
diff --git a/src/backend/access/transam/parallel.c b/src/backend/access/transam/parallel.c
index 84197192ec..7e5c84bd5f 100644
--- a/src/backend/access/transam/parallel.c
+++ b/src/backend/access/transam/parallel.c
@@ -19,6 +19,7 @@
 #include "access/session.h"
 #include "access/xact.h"
 #include "access/xlog.h"
+#include "bestatus.h"
 #include "catalog/pg_enum.h"
 #include "catalog/index.h"
 #include "catalog/namespace.h"
@@ -29,7 +30,6 @@
 #include "libpq/pqmq.h"
 #include "miscadmin.h"
 #include "optimizer/planmain.h"
-#include "pgstat.h"
 #include "storage/ipc.h"
 #include "storage/sinval.h"
 #include "storage/spin.h"
diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c
index 1132eef038..90a6f14899 100644
--- a/src/backend/access/transam/slru.c
+++ b/src/backend/access/transam/slru.c
@@ -54,7 +54,7 @@
 #include "access/slru.h"
 #include "access/transam.h"
 #include "access/xlog.h"
-#include "pgstat.h"
+#include "bestatus.h"
 #include "storage/fd.h"
 #include "storage/shmem.h"
 #include "miscadmin.h"
diff --git a/src/backend/access/transam/timeline.c b/src/backend/access/transam/timeline.c
index 61d36050c3..ba78461ff0 100644
--- a/src/backend/access/transam/timeline.c
+++ b/src/backend/access/transam/timeline.c
@@ -38,7 +38,7 @@
 #include "access/xlog.h"
 #include "access/xlog_internal.h"
 #include "access/xlogdefs.h"
-#include "pgstat.h"
+#include "bestatus.h"
 #include "storage/fd.h"
 
 /*
diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index 3942734e5a..e2c1be7422 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -87,6 +87,7 @@
 #include "access/xloginsert.h"
 #include "access/xlogutils.h"
 #include "access/xlogreader.h"
+#include "bestatus.h"
 #include "catalog/pg_type.h"
 #include "catalog/storage.h"
 #include "funcapi.h"
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index a979d7e07b..84c51c6ac8 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -30,6 +30,7 @@
 #include "access/xlog.h"
 #include "access/xloginsert.h"
 #include "access/xlogutils.h"
+#include "bestatus.h"
 #include "catalog/namespace.h"
 #include "catalog/pg_enum.h"
 #include "catalog/storage.h"
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index e52ae54821..018a3737dc 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -36,6 +36,7 @@
 #include "access/xloginsert.h"
 #include "access/xlogreader.h"
 #include "access/xlogutils.h"
+#include "bestatus.h"
 #include "catalog/catversion.h"
 #include "catalog/pg_control.h"
 #include "catalog/pg_database.h"
diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c
index a31adcca5e..b72da3f45f 100644
--- a/src/backend/access/transam/xlogfuncs.c
+++ b/src/backend/access/transam/xlogfuncs.c
@@ -23,9 +23,9 @@
 #include "access/xlog_internal.h"
 #include "access/xlogutils.h"
 #include "catalog/pg_type.h"
+#include "bestatus.h"
 #include "funcapi.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "replication/walreceiver.h"
 #include "storage/smgr.h"
 #include "utils/builtins.h"
diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 4ecdc9220f..b739f650d6 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -23,8 +23,8 @@
 #include "access/xlog.h"
 #include "access/xlog_internal.h"
 #include "access/xlogutils.h"
+#include "bestatus.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "storage/smgr.h"
 #include "utils/guc.h"
 #include "utils/hsearch.h"
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index dab0addd8b..0782cf11b9 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -20,6 +20,7 @@
 #include "access/htup_details.h"
 #include "access/xact.h"
 #include "access/xlog_internal.h"
+#include "bestatus.h"
 #include "bootstrap/bootstrap.h"
 #include "catalog/index.h"
 #include "catalog/pg_collation.h"
@@ -327,9 +328,6 @@ AuxiliaryProcessMain(int argc, char *argv[])
 			case BgWriterProcess:
 				statmsg = pgstat_get_backend_desc(B_BG_WRITER);
 				break;
-			case ArchiverProcess:
-				statmsg = pgstat_get_backend_desc(B_ARCHIVER);
-				break;
 			case CheckpointerProcess:
 				statmsg = pgstat_get_backend_desc(B_CHECKPOINTER);
 				break;
@@ -339,6 +337,9 @@ AuxiliaryProcessMain(int argc, char *argv[])
 			case WalReceiverProcess:
 				statmsg = pgstat_get_backend_desc(B_WAL_RECEIVER);
 				break;
+			case ArchiverProcess:
+				statmsg = pgstat_get_backend_desc(B_ARCHIVER);
+				break;
 			default:
 				statmsg = "??? process";
 				break;
@@ -415,6 +416,7 @@ AuxiliaryProcessMain(int argc, char *argv[])
 		CreateAuxProcessResourceOwner();
 
 		/* Initialize backend status information */
+		pgstat_bearray_initialize();
 		pgstat_initialize();
 		pgstat_bestart();
 
diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c
index 8996d366e9..dff87c1d84 100644
--- a/src/backend/commands/vacuumlazy.c
+++ b/src/backend/commands/vacuumlazy.c
@@ -44,6 +44,7 @@
 #include "access/transam.h"
 #include "access/visibilitymap.h"
 #include "access/xlog.h"
+#include "bestatus.h"
 #include "catalog/storage.h"
 #include "commands/dbcommands.h"
 #include "commands/progress.h"
diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c
index 13ef232d39..a99ea3dbfe 100644
--- a/src/backend/executor/execParallel.c
+++ b/src/backend/executor/execParallel.c
@@ -48,7 +48,7 @@
 #include "utils/lsyscache.h"
 #include "utils/memutils.h"
 #include "utils/snapmgr.h"
-#include "pgstat.h"
+#include "bestatus.h"
 
 /*
  * Magic numbers for parallel executor communication.  We use constants
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c153d74f41..f163daf408 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -40,6 +40,7 @@
 #include "access/relscan.h"
 #include "access/transam.h"
 #include "access/visibilitymap.h"
+#include "bestatus.h"
 #include "executor/execdebug.h"
 #include "executor/nodeBitmapHeapscan.h"
 #include "miscadmin.h"
diff --git a/src/backend/executor/nodeGather.c b/src/backend/executor/nodeGather.c
index afddb0a039..072a9cee23 100644
--- a/src/backend/executor/nodeGather.c
+++ b/src/backend/executor/nodeGather.c
@@ -32,6 +32,7 @@
 
 #include "access/relscan.h"
 #include "access/xact.h"
+#include "bestatus.h"
 #include "executor/execdebug.h"
 #include "executor/execParallel.h"
 #include "executor/nodeGather.h"
@@ -39,7 +40,6 @@
 #include "executor/tqueue.h"
 #include "miscadmin.h"
 #include "optimizer/planmain.h"
-#include "pgstat.h"
 #include "utils/memutils.h"
 #include "utils/rel.h"
 
diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c
index a9f812d66b..9545fb0994 100644
--- a/src/backend/executor/nodeHash.c
+++ b/src/backend/executor/nodeHash.c
@@ -28,6 +28,7 @@
 
 #include "access/htup_details.h"
 #include "access/parallel.h"
+#include "bestatus.h"
 #include "catalog/pg_statistic.h"
 #include "commands/tablespace.h"
 #include "executor/execdebug.h"
@@ -35,7 +36,6 @@
 #include "executor/nodeHash.h"
 #include "executor/nodeHashjoin.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "port/atomics.h"
 #include "utils/dynahash.h"
 #include "utils/memutils.h"
diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c
index 08a8bb3426..7b6f75805a 100644
--- a/src/backend/executor/nodeHashjoin.c
+++ b/src/backend/executor/nodeHashjoin.c
@@ -108,12 +108,12 @@
 
 #include "access/htup_details.h"
 #include "access/parallel.h"
+#include "bestatus.h"
 #include "executor/executor.h"
 #include "executor/hashjoin.h"
 #include "executor/nodeHash.h"
 #include "executor/nodeHashjoin.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "utils/memutils.h"
 #include "utils/sharedtuplestore.h"
 
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 6a576572bb..5a304c7405 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -36,9 +36,9 @@
 #include <openssl/ec.h>
 #endif
 
+#include "bestatus.h"
 #include "libpq/libpq.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "storage/fd.h"
 #include "storage/latch.h"
 #include "tcop/tcopprot.h"
diff --git a/src/backend/libpq/be-secure.c b/src/backend/libpq/be-secure.c
index 4eb21fe89d..517b22a694 100644
--- a/src/backend/libpq/be-secure.c
+++ b/src/backend/libpq/be-secure.c
@@ -29,9 +29,9 @@
 #include <arpa/inet.h>
 #endif
 
+#include "bestatus.h"
 #include "libpq/libpq.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "tcop/tcopprot.h"
 #include "utils/memutils.h"
 #include "storage/ipc.h"
diff --git a/src/backend/libpq/pqmq.c b/src/backend/libpq/pqmq.c
index 6eaed5bf0c..5906682fbf 100644
--- a/src/backend/libpq/pqmq.c
+++ b/src/backend/libpq/pqmq.c
@@ -13,11 +13,11 @@
 
 #include "postgres.h"
 
+#include "bestatus.h"
 #include "libpq/libpq.h"
 #include "libpq/pqformat.h"
 #include "libpq/pqmq.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "tcop/tcopprot.h"
 #include "utils/builtins.h"
 
diff --git a/src/backend/postmaster/Makefile b/src/backend/postmaster/Makefile
index 71c23211b2..311e63017d 100644
--- a/src/backend/postmaster/Makefile
+++ b/src/backend/postmaster/Makefile
@@ -13,6 +13,6 @@ top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
 OBJS = autovacuum.o bgworker.o bgwriter.o checkpointer.o fork_process.o \
-	pgarch.o pgstat.o postmaster.o startup.o syslogger.o walwriter.o
+	pgarch.o postmaster.o startup.o syslogger.o walwriter.o
 
 include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 10e707e9a1..ce2b441c37 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -71,6 +71,7 @@
 #include "access/reloptions.h"
 #include "access/transam.h"
 #include "access/xact.h"
+#include "bestatus.h"
 #include "catalog/dependency.h"
 #include "catalog/namespace.h"
 #include "catalog/pg_database.h"
diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c
index d2b695e146..01eaa187ff 100644
--- a/src/backend/postmaster/bgworker.c
+++ b/src/backend/postmaster/bgworker.c
@@ -16,8 +16,8 @@
 
 #include "libpq/pqsignal.h"
 #include "access/parallel.h"
+#include "bestatus.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "port/atomics.h"
 #include "postmaster/bgworker_internals.h"
 #include "postmaster/postmaster.h"
diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c
index a4b1079e60..aea6a15b74 100644
--- a/src/backend/postmaster/bgwriter.c
+++ b/src/backend/postmaster/bgwriter.c
@@ -40,6 +40,7 @@
 
 #include "access/xlog.h"
 #include "access/xlog_internal.h"
+#include "bestatus.h"
 #include "libpq/pqsignal.h"
 #include "miscadmin.h"
 #include "pgstat.h"
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index 9235390bc6..2968d356ed 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -43,6 +43,7 @@
 
 #include "access/xlog.h"
 #include "access/xlog_internal.h"
+#include "bestatus.h"
 #include "libpq/pqsignal.h"
 #include "miscadmin.h"
 #include "pgstat.h"
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index 7d4e528096..deec58b057 100644
--- a/src/backend/postmaster/pgarch.c
+++ b/src/backend/postmaster/pgarch.c
@@ -34,6 +34,7 @@
 
 #include "access/xlog.h"
 #include "access/xlog_internal.h"
+#include "bestatus.h"
 #include "libpq/pqsignal.h"
 #include "miscadmin.h"
 #include "pgstat.h"
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 559aeedb6e..1719bb8d31 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -95,6 +95,7 @@
 
 #include "access/transam.h"
 #include "access/xlog.h"
+#include "bestatus.h"
 #include "bootstrap/bootstrap.h"
 #include "catalog/pg_control.h"
 #include "common/file_perm.h"
diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c
index 29bdcec895..d23987b20e 100644
--- a/src/backend/postmaster/syslogger.c
+++ b/src/backend/postmaster/syslogger.c
@@ -31,11 +31,11 @@
 #include <sys/stat.h>
 #include <sys/time.h>
 
+#include "bestatus.h"
 #include "lib/stringinfo.h"
 #include "libpq/pqsignal.h"
 #include "miscadmin.h"
 #include "nodes/pg_list.h"
-#include "pgstat.h"
 #include "pgtime.h"
 #include "postmaster/fork_process.h"
 #include "postmaster/postmaster.h"
diff --git a/src/backend/postmaster/walwriter.c b/src/backend/postmaster/walwriter.c
index fb66bceeed..09021b54c4 100644
--- a/src/backend/postmaster/walwriter.c
+++ b/src/backend/postmaster/walwriter.c
@@ -45,9 +45,9 @@
 #include <unistd.h>
 
 #include "access/xlog.h"
+#include "bestatus.h"
 #include "libpq/pqsignal.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "postmaster/walwriter.h"
 #include "storage/bufmgr.h"
 #include "storage/condition_variable.h"
diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c
index 20cf33354a..1ce0809361 100644
--- a/src/backend/replication/basebackup.c
+++ b/src/backend/replication/basebackup.c
@@ -17,6 +17,7 @@
 #include <time.h>
 
 #include "access/xlog_internal.h"	/* for pg_start/stop_backup */
+#include "bestatus.h"
 #include "catalog/pg_type.h"
 #include "common/file_perm.h"
 #include "lib/stringinfo.h"
@@ -25,7 +26,6 @@
 #include "miscadmin.h"
 #include "nodes/pg_list.h"
 #include "pgtar.h"
-#include "pgstat.h"
 #include "port.h"
 #include "postmaster/syslogger.h"
 #include "replication/basebackup.h"
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 1e1695ef4f..b992473fd4 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -22,11 +22,11 @@
 #include "libpq-fe.h"
 #include "pqexpbuffer.h"
 #include "access/xlog.h"
+#include "bestatus.h"
 #include "catalog/pg_type.h"
 #include "funcapi.h"
 #include "mb/pg_wchar.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "replication/walreceiver.h"
 #include "utils/builtins.h"
 #include "utils/memutils.h"
diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c
index ada16adb67..bf7ac927f7 100644
--- a/src/backend/replication/logical/launcher.c
+++ b/src/backend/replication/logical/launcher.c
@@ -19,7 +19,7 @@
 
 #include "funcapi.h"
 #include "miscadmin.h"
-#include "pgstat.h"
+#include "bestatus.h"
 
 #include "access/heapam.h"
 #include "access/htup.h"
diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c
index bf97dcdee4..a60ef0a9f1 100644
--- a/src/backend/replication/logical/origin.c
+++ b/src/backend/replication/logical/origin.c
@@ -77,13 +77,12 @@
 #include "access/heapam.h"
 #include "access/htup_details.h"
 #include "access/xact.h"
-
+#include "bestatus.h"
 #include "catalog/indexing.h"
 #include "nodes/execnodes.h"
 
 #include "replication/origin.h"
 #include "replication/logical.h"
-#include "pgstat.h"
 #include "storage/fd.h"
 #include "storage/ipc.h"
 #include "storage/lmgr.h"
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index bed63c768e..7af1e6b6b1 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -61,10 +61,10 @@
 #include "access/tuptoaster.h"
 #include "access/xact.h"
 #include "access/xlog_internal.h"
+#include "bestatus.h"
 #include "catalog/catalog.h"
 #include "lib/binaryheap.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "replication/logical.h"
 #include "replication/reorderbuffer.h"
 #include "replication/slot.h"
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index a6cd6c67d1..846e1e7267 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -126,7 +126,7 @@
 #include "access/transam.h"
 #include "access/xact.h"
 
-#include "pgstat.h"
+#include "bestatus.h"
 
 #include "replication/logical.h"
 #include "replication/reorderbuffer.h"
diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c
index 862582da23..670552593f 100644
--- a/src/backend/replication/logical/tablesync.c
+++ b/src/backend/replication/logical/tablesync.c
@@ -86,25 +86,27 @@
 #include "postgres.h"
 
 #include "miscadmin.h"
-#include "pgstat.h"
 
 #include "access/xact.h"
 
+#include "bestatus.h"
+
 #include "catalog/pg_subscription_rel.h"
 #include "catalog/pg_type.h"
 
 #include "commands/copy.h"
 
 #include "parser/parse_relation.h"
+#include "pgstat.h"
 
 #include "replication/logicallauncher.h"
 #include "replication/logicalrelation.h"
 #include "replication/walreceiver.h"
 #include "replication/worker_internal.h"
 
-#include "utils/snapmgr.h"
 #include "storage/ipc.h"
 
+#include "utils/snapmgr.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
 #include "utils/memutils.h"
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 087850d089..3dc686f0df 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -23,13 +23,11 @@
 
 #include "postgres.h"
 
-#include "miscadmin.h"
-#include "pgstat.h"
-#include "funcapi.h"
-
 #include "access/xact.h"
 #include "access/xlog_internal.h"
 
+#include "bestatus.h"
+
 #include "catalog/catalog.h"
 #include "catalog/namespace.h"
 #include "catalog/pg_subscription.h"
@@ -41,17 +39,20 @@
 #include "executor/executor.h"
 #include "executor/nodeModifyTable.h"
 
+#include "funcapi.h"
+
 #include "libpq/pqformat.h"
 #include "libpq/pqsignal.h"
 
 #include "mb/pg_wchar.h"
+#include "miscadmin.h"
 
 #include "nodes/makefuncs.h"
 
 #include "optimizer/planner.h"
 
 #include "parser/parse_relation.h"
-
+#include "pgstat.h"
 #include "postmaster/bgworker.h"
 #include "postmaster/postmaster.h"
 #include "postmaster/walwriter.h"
diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c
index 1f2e7139a7..1620313c55 100644
--- a/src/backend/replication/slot.c
+++ b/src/backend/replication/slot.c
@@ -41,9 +41,9 @@
 
 #include "access/transam.h"
 #include "access/xlog_internal.h"
+#include "bestatus.h"
 #include "common/string.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "replication/slot.h"
 #include "storage/fd.h"
 #include "storage/proc.h"
diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c
index af5ad5fe66..957aea0a7d 100644
--- a/src/backend/replication/syncrep.c
+++ b/src/backend/replication/syncrep.c
@@ -75,8 +75,8 @@
 #include <unistd.h>
 
 #include "access/xact.h"
+#include "bestatus.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "replication/syncrep.h"
 #include "replication/walsender.h"
 #include "replication/walsender_private.h"
diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c
index 6f4b3538ac..0d65ed8f2a 100644
--- a/src/backend/replication/walreceiver.c
+++ b/src/backend/replication/walreceiver.c
@@ -50,6 +50,7 @@
 #include "access/timeline.h"
 #include "access/transam.h"
 #include "access/xlog_internal.h"
+#include "bestatus.h"
 #include "catalog/pg_authid.h"
 #include "catalog/pg_type.h"
 #include "common/ip.h"
@@ -57,7 +58,6 @@
 #include "libpq/pqformat.h"
 #include "libpq/pqsignal.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "replication/walreceiver.h"
 #include "replication/walsender.h"
 #include "storage/ipc.h"
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 2683385ca6..bfe18c860b 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -56,6 +56,7 @@
 #include "access/xlog_internal.h"
 #include "access/xlogutils.h"
 
+#include "bestatus.h"
 #include "catalog/pg_authid.h"
 #include "catalog/pg_type.h"
 #include "commands/dbcommands.h"
@@ -65,7 +66,6 @@
 #include "libpq/pqformat.h"
 #include "miscadmin.h"
 #include "nodes/replnodes.h"
-#include "pgstat.h"
 #include "replication/basebackup.h"
 #include "replication/decode.h"
 #include "replication/logical.h"
diff --git a/src/backend/statmon/Makefile b/src/backend/statmon/Makefile
new file mode 100644
index 0000000000..64a04878e3
--- /dev/null
+++ b/src/backend/statmon/Makefile
@@ -0,0 +1,17 @@
+#-------------------------------------------------------------------------
+#
+# Makefile--
+#    Makefile for src/backend/statmon
+#
+# IDENTIFICATION
+#    src/backend/statmon/Makefile
+#
+#-------------------------------------------------------------------------
+
+subdir = src/backend/statmon
+top_builddir = ../../..
+include $(top_builddir)/src/Makefile.global
+
+OBJS = pgstat.o bestatus.o
+
+include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/statmon/bestatus.c b/src/backend/statmon/bestatus.c
new file mode 100644
index 0000000000..1ea4f80a58
--- /dev/null
+++ b/src/backend/statmon/bestatus.c
@@ -0,0 +1,1756 @@
+/* ----------
+ * bestatus.c
+ *
+ *	Backend status monitor
+ *
+ *	Status data is stored in shared memory. Every backends updates and read it
+ *	individually.
+ *
+ *	Copyright (c) 2001-2018, PostgreSQL Global Development Group
+ *
+ *	src/backend/statmon/bestatus.c
+ * ----------
+ */
+#include "postgres.h"
+
+#include "bestatus.h"
+
+#include "access/xact.h"
+#include "libpq/libpq.h"
+#include "miscadmin.h"
+#include "postmaster/autovacuum.h"
+#include "replication/walsender.h"
+#include "storage/ipc.h"
+#include "storage/lmgr.h"
+#include "storage/sinvaladt.h"
+#include "utils/ascii.h"
+#include "utils/guc.h"
+#include "utils/memutils.h"
+#include "utils/probes.h"
+
+
+/* Status for backends including auxiliary */
+static LocalPgBackendStatus *localBackendStatusTable = NULL;
+
+/* Total number of backends including auxiliary */
+static int	localNumBackends = 0;
+
+/* ----------
+ * Total number of backends including auxiliary
+ *
+ * We reserve a slot for each possible BackendId, plus one for each
+ * possible auxiliary process type.  (This scheme assumes there is not
+ * more than one of any auxiliary process type at a time.) MaxBackends
+ * includes autovacuum workers and background workers as well.
+ * ----------
+ */
+#define NumBackendStatSlots (MaxBackends + NUM_AUXPROCTYPES)
+
+
+/* ----------
+ * GUC parameters
+ * ----------
+ */
+bool		pgstat_track_activities = false;
+int			pgstat_track_activity_query_size = 1024;
+
+static MemoryContext pgBeStatLocalContext = NULL;
+
+/* ------------------------------------------------------------
+ * Functions for management of the shared-memory PgBackendStatus array
+ * ------------------------------------------------------------
+ */
+
+static PgBackendStatus *BackendStatusArray = NULL;
+static PgBackendStatus *MyBEEntry = NULL;
+static char *BackendAppnameBuffer = NULL;
+static char *BackendClientHostnameBuffer = NULL;
+static char *BackendActivityBuffer = NULL;
+static Size BackendActivityBufferSize = 0;
+#ifdef USE_SSL
+static PgBackendSSLStatus *BackendSslStatusBuffer = NULL;
+#endif
+
+static const char *pgstat_get_wait_activity(WaitEventActivity w);
+static const char *pgstat_get_wait_client(WaitEventClient w);
+static const char *pgstat_get_wait_ipc(WaitEventIPC w);
+static const char *pgstat_get_wait_timeout(WaitEventTimeout w);
+static const char *pgstat_get_wait_io(WaitEventIO w);
+static void pgstat_setup_memcxt(void);
+static void pgstat_beshutdown_hook(int code, Datum arg);
+/*
+ * Report shared-memory space needed by CreateSharedBackendStatus.
+ */
+Size
+BackendStatusShmemSize(void)
+{
+	Size		size;
+
+	/* BackendStatusArray: */
+	size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots);
+	/* BackendAppnameBuffer: */
+	size = add_size(size,
+					mul_size(NAMEDATALEN, NumBackendStatSlots));
+	/* BackendClientHostnameBuffer: */
+	size = add_size(size,
+					mul_size(NAMEDATALEN, NumBackendStatSlots));
+	/* BackendActivityBuffer: */
+	size = add_size(size,
+					mul_size(pgstat_track_activity_query_size, NumBackendStatSlots));
+#ifdef USE_SSL
+	/* BackendSslStatusBuffer: */
+	size = add_size(size,
+					mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots));
+#endif
+	return size;
+}
+
+/*
+ * Initialize the shared status array and several string buffers
+ * during postmaster startup.
+ */
+void
+CreateSharedBackendStatus(void)
+{
+	Size		size;
+	bool		found;
+	int			i;
+	char	   *buffer;
+
+	/* Create or attach to the shared array */
+	size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots);
+	BackendStatusArray = (PgBackendStatus *)
+		ShmemInitStruct("Backend Status Array", size, &found);
+
+	if (!found)
+	{
+		/*
+		 * We're the first - initialize.
+		 */
+		MemSet(BackendStatusArray, 0, size);
+	}
+
+	/* Create or attach to the shared appname buffer */
+	size = mul_size(NAMEDATALEN, NumBackendStatSlots);
+	BackendAppnameBuffer = (char *)
+		ShmemInitStruct("Backend Application Name Buffer", size, &found);
+
+	if (!found)
+	{
+		MemSet(BackendAppnameBuffer, 0, size);
+
+		/* Initialize st_appname pointers. */
+		buffer = BackendAppnameBuffer;
+		for (i = 0; i < NumBackendStatSlots; i++)
+		{
+			BackendStatusArray[i].st_appname = buffer;
+			buffer += NAMEDATALEN;
+		}
+	}
+
+	/* Create or attach to the shared client hostname buffer */
+	size = mul_size(NAMEDATALEN, NumBackendStatSlots);
+	BackendClientHostnameBuffer = (char *)
+		ShmemInitStruct("Backend Client Host Name Buffer", size, &found);
+
+	if (!found)
+	{
+		MemSet(BackendClientHostnameBuffer, 0, size);
+
+		/* Initialize st_clienthostname pointers. */
+		buffer = BackendClientHostnameBuffer;
+		for (i = 0; i < NumBackendStatSlots; i++)
+		{
+			BackendStatusArray[i].st_clienthostname = buffer;
+			buffer += NAMEDATALEN;
+		}
+	}
+
+	/* Create or attach to the shared activity buffer */
+	BackendActivityBufferSize = mul_size(pgstat_track_activity_query_size,
+										 NumBackendStatSlots);
+	BackendActivityBuffer = (char *)
+		ShmemInitStruct("Backend Activity Buffer",
+						BackendActivityBufferSize,
+						&found);
+
+	if (!found)
+	{
+		MemSet(BackendActivityBuffer, 0, BackendActivityBufferSize);
+
+		/* Initialize st_activity pointers. */
+		buffer = BackendActivityBuffer;
+		for (i = 0; i < NumBackendStatSlots; i++)
+		{
+			BackendStatusArray[i].st_activity_raw = buffer;
+			buffer += pgstat_track_activity_query_size;
+		}
+	}
+
+#ifdef USE_SSL
+	/* Create or attach to the shared SSL status buffer */
+	size = mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots);
+	BackendSslStatusBuffer = (PgBackendSSLStatus *)
+		ShmemInitStruct("Backend SSL Status Buffer", size, &found);
+
+	if (!found)
+	{
+		PgBackendSSLStatus *ptr;
+
+		MemSet(BackendSslStatusBuffer, 0, size);
+
+		/* Initialize st_sslstatus pointers. */
+		ptr = BackendSslStatusBuffer;
+		for (i = 0; i < NumBackendStatSlots; i++)
+		{
+			BackendStatusArray[i].st_sslstatus = ptr;
+			ptr++;
+		}
+	}
+#endif
+}
+
+/* ----------
+ * pgstat_bearray_initialize() -
+ *
+ *	Initialize pgstats state, and set up our on-proc-exit hook.
+ *	Called from InitPostgres and AuxiliaryProcessMain. For auxiliary process,
+ *	MyBackendId is invalid. Otherwise, MyBackendId must be set,
+ *	but we must not have started any transaction yet (since the
+ *	exit hook must run after the last transaction exit).
+ *	NOTE: MyDatabaseId isn't set yet; so the shutdown hook has to be careful.
+ * ----------
+ */
+void
+pgstat_bearray_initialize(void)
+{
+	/* Initialize MyBEEntry */
+	if (MyBackendId != InvalidBackendId)
+	{
+		Assert(MyBackendId >= 1 && MyBackendId <= MaxBackends);
+		MyBEEntry = &BackendStatusArray[MyBackendId - 1];
+	}
+	else
+	{
+		/* Must be an auxiliary process */
+		Assert(MyAuxProcType != NotAnAuxProcess);
+
+		/*
+		 * Assign the MyBEEntry for an auxiliary process.  Since it doesn't
+		 * have a BackendId, the slot is statically allocated based on the
+		 * auxiliary process type (MyAuxProcType).  Backends use slots indexed
+		 * in the range from 1 to MaxBackends (inclusive), so we use
+		 * MaxBackends + AuxBackendType + 1 as the index of the slot for an
+		 * auxiliary process.
+		 */
+		MyBEEntry = &BackendStatusArray[MaxBackends + MyAuxProcType];
+	}
+
+	/* Set up a process-exit hook to clean up */
+	before_shmem_exit(pgstat_beshutdown_hook, 0);
+}
+
+/*
+ * 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.
+ *
+ * Lastly, clear out our entry in the PgBackendStatus array.
+ */
+static void
+pgstat_beshutdown_hook(int code, Datum arg)
+{
+	volatile PgBackendStatus *beentry = MyBEEntry;
+
+	/*
+	 * Clear my status entry, following the protocol of bumping st_changecount
+	 * before and after.  We use a volatile pointer here to ensure the
+	 * compiler doesn't try to get cute.
+	 */
+	pgstat_increment_changecount_before(beentry);
+
+	beentry->st_procpid = 0;	/* mark invalid */
+
+	pgstat_increment_changecount_after(beentry);
+}
+
+
+/* ----------
+ * pgstat_bestart() -
+ *
+ *	Initialize this backend's entry in the PgBackendStatus array.
+ *	Called from InitPostgres.
+ *
+ *	Apart from auxiliary processes, MyBackendId, MyDatabaseId,
+ *	session userid, and application_name must be set for a
+ *	backend (hence, this cannot be combined with pgstat_initialize).
+ * ----------
+ */
+void
+pgstat_bestart(void)
+{
+	SockAddr	clientaddr;
+	volatile PgBackendStatus *beentry;
+
+	/*
+	 * To minimize the time spent modifying the PgBackendStatus entry, fetch
+	 * all the needed data first.
+	 */
+
+	/*
+	 * We may not have a MyProcPort (eg, if this is the autovacuum process).
+	 * If so, use all-zeroes client address, which is dealt with specially in
+	 * pg_stat_get_backend_client_addr and pg_stat_get_backend_client_port.
+	 */
+	if (MyProcPort)
+		memcpy(&clientaddr, &MyProcPort->raddr, sizeof(clientaddr));
+	else
+		MemSet(&clientaddr, 0, sizeof(clientaddr));
+
+	/*
+	 * Initialize my status entry, following the protocol of bumping
+	 * st_changecount before and after; and make sure it's even afterwards. We
+	 * use a volatile pointer here to ensure the compiler doesn't try to get
+	 * cute.
+	 */
+	beentry = MyBEEntry;
+
+	/* pgstats state must be initialized from pgstat_initialize() */
+	Assert(beentry != NULL);
+
+	if (MyBackendId != InvalidBackendId)
+	{
+		if (IsAutoVacuumLauncherProcess())
+		{
+			/* Autovacuum Launcher */
+			beentry->st_backendType = B_AUTOVAC_LAUNCHER;
+		}
+		else if (IsAutoVacuumWorkerProcess())
+		{
+			/* Autovacuum Worker */
+			beentry->st_backendType = B_AUTOVAC_WORKER;
+		}
+		else if (am_walsender)
+		{
+			/* Wal sender */
+			beentry->st_backendType = B_WAL_SENDER;
+		}
+		else if (IsBackgroundWorker)
+		{
+			/* bgworker */
+			beentry->st_backendType = B_BG_WORKER;
+		}
+		else
+		{
+			/* client-backend */
+			beentry->st_backendType = B_BACKEND;
+		}
+	}
+	else
+	{
+		/* Must be an auxiliary process */
+		Assert(MyAuxProcType != NotAnAuxProcess);
+		switch (MyAuxProcType)
+		{
+			case StartupProcess:
+				beentry->st_backendType = B_STARTUP;
+				break;
+			case BgWriterProcess:
+				beentry->st_backendType = B_BG_WRITER;
+				break;
+			case CheckpointerProcess:
+				beentry->st_backendType = B_CHECKPOINTER;
+				break;
+			case WalWriterProcess:
+				beentry->st_backendType = B_WAL_WRITER;
+				break;
+			case WalReceiverProcess:
+				beentry->st_backendType = B_WAL_RECEIVER;
+				break;
+			case ArchiverProcess:
+				beentry->st_backendType = B_ARCHIVER;
+				break;
+			default:
+				elog(FATAL, "unrecognized process type: %d",
+					 (int) MyAuxProcType);
+				proc_exit(1);
+		}
+	}
+
+	do
+	{
+		pgstat_increment_changecount_before(beentry);
+	} while ((beentry->st_changecount & 1) == 0);
+
+	beentry->st_procpid = MyProcPid;
+	beentry->st_proc_start_timestamp = MyStartTimestamp;
+	beentry->st_activity_start_timestamp = 0;
+	beentry->st_state_start_timestamp = 0;
+	beentry->st_xact_start_timestamp = 0;
+	beentry->st_databaseid = MyDatabaseId;
+
+	/* We have userid for client-backends, wal-sender and bgworker processes */
+	if (beentry->st_backendType == B_BACKEND
+		|| beentry->st_backendType == B_WAL_SENDER
+		|| beentry->st_backendType == B_BG_WORKER)
+		beentry->st_userid = GetSessionUserId();
+	else
+		beentry->st_userid = InvalidOid;
+
+	beentry->st_clientaddr = clientaddr;
+	if (MyProcPort && MyProcPort->remote_hostname)
+		strlcpy(beentry->st_clienthostname, MyProcPort->remote_hostname,
+				NAMEDATALEN);
+	else
+		beentry->st_clienthostname[0] = '\0';
+#ifdef USE_SSL
+	if (MyProcPort && MyProcPort->ssl != NULL)
+	{
+		beentry->st_ssl = true;
+		beentry->st_sslstatus->ssl_bits = be_tls_get_cipher_bits(MyProcPort);
+		beentry->st_sslstatus->ssl_compression = be_tls_get_compression(MyProcPort);
+		strlcpy(beentry->st_sslstatus->ssl_version, be_tls_get_version(MyProcPort), NAMEDATALEN);
+		strlcpy(beentry->st_sslstatus->ssl_cipher, be_tls_get_cipher(MyProcPort), NAMEDATALEN);
+		be_tls_get_peerdn_name(MyProcPort, beentry->st_sslstatus->ssl_clientdn, NAMEDATALEN);
+	}
+	else
+	{
+		beentry->st_ssl = false;
+	}
+#else
+	beentry->st_ssl = false;
+#endif
+	beentry->st_state = STATE_UNDEFINED;
+	beentry->st_appname[0] = '\0';
+	beentry->st_activity_raw[0] = '\0';
+	/* Also make sure the last byte in each string area is always 0 */
+	beentry->st_clienthostname[NAMEDATALEN - 1] = '\0';
+	beentry->st_appname[NAMEDATALEN - 1] = '\0';
+	beentry->st_activity_raw[pgstat_track_activity_query_size - 1] = '\0';
+	beentry->st_progress_command = PROGRESS_COMMAND_INVALID;
+	beentry->st_progress_command_target = InvalidOid;
+
+	/*
+	 * we don't zero st_progress_param here to save cycles; nobody should
+	 * examine it until st_progress_command has been set to something other
+	 * than PROGRESS_COMMAND_INVALID
+	 */
+
+	pgstat_increment_changecount_after(beentry);
+
+	/* Update app name to current GUC setting */
+	if (application_name)
+		pgstat_report_appname(application_name);
+}
+
+/* ----------
+ * pgstat_read_current_status() -
+ *
+ *	Copy the current contents of the PgBackendStatus array to local memory,
+ *	if not already done in this transaction.
+ * ----------
+ */
+static void
+pgstat_read_current_status(void)
+{
+	volatile PgBackendStatus *beentry;
+	LocalPgBackendStatus *localtable;
+	LocalPgBackendStatus *localentry;
+	char	   *localappname,
+			   *localclienthostname,
+			   *localactivity;
+#ifdef USE_SSL
+	PgBackendSSLStatus *localsslstatus;
+#endif
+	int			i;
+
+	Assert(IsUnderPostmaster);
+
+	if (localBackendStatusTable)
+		return;					/* already done */
+
+	pgstat_setup_memcxt();
+
+	localtable = (LocalPgBackendStatus *)
+		MemoryContextAlloc(pgBeStatLocalContext,
+						   sizeof(LocalPgBackendStatus) * NumBackendStatSlots);
+	localappname = (char *)
+		MemoryContextAlloc(pgBeStatLocalContext,
+						   NAMEDATALEN * NumBackendStatSlots);
+	localclienthostname = (char *)
+		MemoryContextAlloc(pgBeStatLocalContext,
+						   NAMEDATALEN * NumBackendStatSlots);
+	localactivity = (char *)
+		MemoryContextAlloc(pgBeStatLocalContext,
+						   pgstat_track_activity_query_size * NumBackendStatSlots);
+#ifdef USE_SSL
+	localsslstatus = (PgBackendSSLStatus *)
+		MemoryContextAlloc(pgBeStatLocalContext,
+						   sizeof(PgBackendSSLStatus) * NumBackendStatSlots);
+#endif
+
+	localNumBackends = 0;
+
+	beentry = BackendStatusArray;
+	localentry = localtable;
+	for (i = 1; i <= NumBackendStatSlots; i++)
+	{
+		/*
+		 * Follow the protocol of retrying if st_changecount changes while we
+		 * copy the entry, or if it's odd.  (The check for odd is needed to
+		 * cover the case where we are able to completely copy the entry while
+		 * the source backend is between increment steps.)	We use a volatile
+		 * pointer here to ensure the compiler doesn't try to get cute.
+		 */
+		for (;;)
+		{
+			int			before_changecount;
+			int			after_changecount;
+
+			pgstat_save_changecount_before(beentry, before_changecount);
+
+			localentry->backendStatus.st_procpid = beentry->st_procpid;
+			if (localentry->backendStatus.st_procpid > 0)
+			{
+				memcpy(&localentry->backendStatus, (char *) beentry, sizeof(PgBackendStatus));
+
+				/*
+				 * strcpy is safe even if the string is modified concurrently,
+				 * because there's always a \0 at the end of the buffer.
+				 */
+				strcpy(localappname, (char *) beentry->st_appname);
+				localentry->backendStatus.st_appname = localappname;
+				strcpy(localclienthostname, (char *) beentry->st_clienthostname);
+				localentry->backendStatus.st_clienthostname = localclienthostname;
+				strcpy(localactivity, (char *) beentry->st_activity_raw);
+				localentry->backendStatus.st_activity_raw = localactivity;
+				localentry->backendStatus.st_ssl = beentry->st_ssl;
+#ifdef USE_SSL
+				if (beentry->st_ssl)
+				{
+					memcpy(localsslstatus, beentry->st_sslstatus, sizeof(PgBackendSSLStatus));
+					localentry->backendStatus.st_sslstatus = localsslstatus;
+				}
+#endif
+			}
+
+			pgstat_save_changecount_after(beentry, after_changecount);
+			if (before_changecount == after_changecount &&
+				(before_changecount & 1) == 0)
+				break;
+
+			/* Make sure we can break out of loop if stuck... */
+			CHECK_FOR_INTERRUPTS();
+		}
+
+		beentry++;
+		/* Only valid entries get included into the local array */
+		if (localentry->backendStatus.st_procpid > 0)
+		{
+			BackendIdGetTransactionIds(i,
+									   &localentry->backend_xid,
+									   &localentry->backend_xmin);
+
+			localentry++;
+			localappname += NAMEDATALEN;
+			localclienthostname += NAMEDATALEN;
+			localactivity += pgstat_track_activity_query_size;
+#ifdef USE_SSL
+			localsslstatus++;
+#endif
+			localNumBackends++;
+		}
+	}
+
+	/* Set the pointer only after completion of a valid table */
+	localBackendStatusTable = localtable;
+}
+
+
+/* ----------
+ * pgstat_fetch_stat_beentry() -
+ *
+ *	Support function for the SQL-callable pgstat* functions. Returns
+ *	our local copy of the current-activity entry for one backend.
+ *
+ *	NB: caller is responsible for a check if the user is permitted to see
+ *	this info (especially the querystring).
+ * ----------
+ */
+PgBackendStatus *
+pgstat_fetch_stat_beentry(int beid)
+{
+	pgstat_read_current_status();
+
+	if (beid < 1 || beid > localNumBackends)
+		return NULL;
+
+	return &localBackendStatusTable[beid - 1].backendStatus;
+}
+
+
+/* ----------
+ * pgstat_fetch_stat_local_beentry() -
+ *
+ *	Like pgstat_fetch_stat_beentry() but with locally computed additions (like
+ *	xid and xmin values of the backend)
+ *
+ *	NB: caller is responsible for a check if the user is permitted to see
+ *	this info (especially the querystring).
+ * ----------
+ */
+LocalPgBackendStatus *
+pgstat_fetch_stat_local_beentry(int beid)
+{
+	pgstat_read_current_status();
+
+	if (beid < 1 || beid > localNumBackends)
+		return NULL;
+
+	return &localBackendStatusTable[beid - 1];
+}
+
+
+/* ----------
+ * pgstat_fetch_stat_numbackends() -
+ *
+ *	Support function for the SQL-callable pgstat* functions. Returns
+ *	the maximum current backend id.
+ * ----------
+ */
+int
+pgstat_fetch_stat_numbackends(void)
+{
+	pgstat_read_current_status();
+
+	return localNumBackends;
+}
+
+/* ----------
+ * pgstat_get_wait_event_type() -
+ *
+ *	Return a string representing the current wait event type, backend is
+ *	waiting on.
+ */
+const char *
+pgstat_get_wait_event_type(uint32 wait_event_info)
+{
+	uint32		classId;
+	const char *event_type;
+
+	/* report process as not waiting. */
+	if (wait_event_info == 0)
+		return NULL;
+
+	classId = wait_event_info & 0xFF000000;
+
+	switch (classId)
+	{
+		case PG_WAIT_LWLOCK:
+			event_type = "LWLock";
+			break;
+		case PG_WAIT_LOCK:
+			event_type = "Lock";
+			break;
+		case PG_WAIT_BUFFER_PIN:
+			event_type = "BufferPin";
+			break;
+		case PG_WAIT_ACTIVITY:
+			event_type = "Activity";
+			break;
+		case PG_WAIT_CLIENT:
+			event_type = "Client";
+			break;
+		case PG_WAIT_EXTENSION:
+			event_type = "Extension";
+			break;
+		case PG_WAIT_IPC:
+			event_type = "IPC";
+			break;
+		case PG_WAIT_TIMEOUT:
+			event_type = "Timeout";
+			break;
+		case PG_WAIT_IO:
+			event_type = "IO";
+			break;
+		default:
+			event_type = "???";
+			break;
+	}
+
+	return event_type;
+}
+
+/* ----------
+ * pgstat_get_wait_event() -
+ *
+ *	Return a string representing the current wait event, backend is
+ *	waiting on.
+ */
+const char *
+pgstat_get_wait_event(uint32 wait_event_info)
+{
+	uint32		classId;
+	uint16		eventId;
+	const char *event_name;
+
+	/* report process as not waiting. */
+	if (wait_event_info == 0)
+		return NULL;
+
+	classId = wait_event_info & 0xFF000000;
+	eventId = wait_event_info & 0x0000FFFF;
+
+	switch (classId)
+	{
+		case PG_WAIT_LWLOCK:
+			event_name = GetLWLockIdentifier(classId, eventId);
+			break;
+		case PG_WAIT_LOCK:
+			event_name = GetLockNameFromTagType(eventId);
+			break;
+		case PG_WAIT_BUFFER_PIN:
+			event_name = "BufferPin";
+			break;
+		case PG_WAIT_ACTIVITY:
+			{
+				WaitEventActivity w = (WaitEventActivity) wait_event_info;
+
+				event_name = pgstat_get_wait_activity(w);
+				break;
+			}
+		case PG_WAIT_CLIENT:
+			{
+				WaitEventClient w = (WaitEventClient) wait_event_info;
+
+				event_name = pgstat_get_wait_client(w);
+				break;
+			}
+		case PG_WAIT_EXTENSION:
+			event_name = "Extension";
+			break;
+		case PG_WAIT_IPC:
+			{
+				WaitEventIPC w = (WaitEventIPC) wait_event_info;
+
+				event_name = pgstat_get_wait_ipc(w);
+				break;
+			}
+		case PG_WAIT_TIMEOUT:
+			{
+				WaitEventTimeout w = (WaitEventTimeout) wait_event_info;
+
+				event_name = pgstat_get_wait_timeout(w);
+				break;
+			}
+		case PG_WAIT_IO:
+			{
+				WaitEventIO w = (WaitEventIO) wait_event_info;
+
+				event_name = pgstat_get_wait_io(w);
+				break;
+			}
+		default:
+			event_name = "unknown wait event";
+			break;
+	}
+
+	return event_name;
+}
+
+/* ----------
+ * pgstat_get_wait_activity() -
+ *
+ * Convert WaitEventActivity to string.
+ * ----------
+ */
+static const char *
+pgstat_get_wait_activity(WaitEventActivity w)
+{
+	const char *event_name = "unknown wait event";
+
+	switch (w)
+	{
+		case WAIT_EVENT_ARCHIVER_MAIN:
+			event_name = "ArchiverMain";
+			break;
+		case WAIT_EVENT_AUTOVACUUM_MAIN:
+			event_name = "AutoVacuumMain";
+			break;
+		case WAIT_EVENT_BGWRITER_HIBERNATE:
+			event_name = "BgWriterHibernate";
+			break;
+		case WAIT_EVENT_BGWRITER_MAIN:
+			event_name = "BgWriterMain";
+			break;
+		case WAIT_EVENT_CHECKPOINTER_MAIN:
+			event_name = "CheckpointerMain";
+			break;
+		case WAIT_EVENT_LOGICAL_APPLY_MAIN:
+			event_name = "LogicalApplyMain";
+			break;
+		case WAIT_EVENT_LOGICAL_LAUNCHER_MAIN:
+			event_name = "LogicalLauncherMain";
+			break;
+		case WAIT_EVENT_RECOVERY_WAL_ALL:
+			event_name = "RecoveryWalAll";
+			break;
+		case WAIT_EVENT_RECOVERY_WAL_STREAM:
+			event_name = "RecoveryWalStream";
+			break;
+		case WAIT_EVENT_SYSLOGGER_MAIN:
+			event_name = "SysLoggerMain";
+			break;
+		case WAIT_EVENT_WAL_RECEIVER_MAIN:
+			event_name = "WalReceiverMain";
+			break;
+		case WAIT_EVENT_WAL_SENDER_MAIN:
+			event_name = "WalSenderMain";
+			break;
+		case WAIT_EVENT_WAL_WRITER_MAIN:
+			event_name = "WalWriterMain";
+			break;
+			/* no default case, so that compiler will warn */
+	}
+
+	return event_name;
+}
+
+/* ----------
+ * pgstat_get_wait_client() -
+ *
+ * Convert WaitEventClient to string.
+ * ----------
+ */
+static const char *
+pgstat_get_wait_client(WaitEventClient w)
+{
+	const char *event_name = "unknown wait event";
+
+	switch (w)
+	{
+		case WAIT_EVENT_CLIENT_READ:
+			event_name = "ClientRead";
+			break;
+		case WAIT_EVENT_CLIENT_WRITE:
+			event_name = "ClientWrite";
+			break;
+		case WAIT_EVENT_LIBPQWALRECEIVER_CONNECT:
+			event_name = "LibPQWalReceiverConnect";
+			break;
+		case WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE:
+			event_name = "LibPQWalReceiverReceive";
+			break;
+		case WAIT_EVENT_SSL_OPEN_SERVER:
+			event_name = "SSLOpenServer";
+			break;
+		case WAIT_EVENT_WAL_RECEIVER_WAIT_START:
+			event_name = "WalReceiverWaitStart";
+			break;
+		case WAIT_EVENT_WAL_SENDER_WAIT_WAL:
+			event_name = "WalSenderWaitForWAL";
+			break;
+		case WAIT_EVENT_WAL_SENDER_WRITE_DATA:
+			event_name = "WalSenderWriteData";
+			break;
+			/* no default case, so that compiler will warn */
+	}
+
+	return event_name;
+}
+
+/* ----------
+ * pgstat_get_wait_ipc() -
+ *
+ * Convert WaitEventIPC to string.
+ * ----------
+ */
+static const char *
+pgstat_get_wait_ipc(WaitEventIPC w)
+{
+	const char *event_name = "unknown wait event";
+
+	switch (w)
+	{
+		case WAIT_EVENT_BGWORKER_SHUTDOWN:
+			event_name = "BgWorkerShutdown";
+			break;
+		case WAIT_EVENT_BGWORKER_STARTUP:
+			event_name = "BgWorkerStartup";
+			break;
+		case WAIT_EVENT_BTREE_PAGE:
+			event_name = "BtreePage";
+			break;
+		case WAIT_EVENT_CLOG_GROUP_UPDATE:
+			event_name = "ClogGroupUpdate";
+			break;
+		case WAIT_EVENT_EXECUTE_GATHER:
+			event_name = "ExecuteGather";
+			break;
+		case WAIT_EVENT_HASH_BATCH_ALLOCATING:
+			event_name = "Hash/Batch/Allocating";
+			break;
+		case WAIT_EVENT_HASH_BATCH_ELECTING:
+			event_name = "Hash/Batch/Electing";
+			break;
+		case WAIT_EVENT_HASH_BATCH_LOADING:
+			event_name = "Hash/Batch/Loading";
+			break;
+		case WAIT_EVENT_HASH_BUILD_ALLOCATING:
+			event_name = "Hash/Build/Allocating";
+			break;
+		case WAIT_EVENT_HASH_BUILD_ELECTING:
+			event_name = "Hash/Build/Electing";
+			break;
+		case WAIT_EVENT_HASH_BUILD_HASHING_INNER:
+			event_name = "Hash/Build/HashingInner";
+			break;
+		case WAIT_EVENT_HASH_BUILD_HASHING_OUTER:
+			event_name = "Hash/Build/HashingOuter";
+			break;
+		case WAIT_EVENT_HASH_GROW_BATCHES_ALLOCATING:
+			event_name = "Hash/GrowBatches/Allocating";
+			break;
+		case WAIT_EVENT_HASH_GROW_BATCHES_DECIDING:
+			event_name = "Hash/GrowBatches/Deciding";
+			break;
+		case WAIT_EVENT_HASH_GROW_BATCHES_ELECTING:
+			event_name = "Hash/GrowBatches/Electing";
+			break;
+		case WAIT_EVENT_HASH_GROW_BATCHES_FINISHING:
+			event_name = "Hash/GrowBatches/Finishing";
+			break;
+		case WAIT_EVENT_HASH_GROW_BATCHES_REPARTITIONING:
+			event_name = "Hash/GrowBatches/Repartitioning";
+			break;
+		case WAIT_EVENT_HASH_GROW_BUCKETS_ALLOCATING:
+			event_name = "Hash/GrowBuckets/Allocating";
+			break;
+		case WAIT_EVENT_HASH_GROW_BUCKETS_ELECTING:
+			event_name = "Hash/GrowBuckets/Electing";
+			break;
+		case WAIT_EVENT_HASH_GROW_BUCKETS_REINSERTING:
+			event_name = "Hash/GrowBuckets/Reinserting";
+			break;
+		case WAIT_EVENT_LOGICAL_SYNC_DATA:
+			event_name = "LogicalSyncData";
+			break;
+		case WAIT_EVENT_LOGICAL_SYNC_STATE_CHANGE:
+			event_name = "LogicalSyncStateChange";
+			break;
+		case WAIT_EVENT_MQ_INTERNAL:
+			event_name = "MessageQueueInternal";
+			break;
+		case WAIT_EVENT_MQ_PUT_MESSAGE:
+			event_name = "MessageQueuePutMessage";
+			break;
+		case WAIT_EVENT_MQ_RECEIVE:
+			event_name = "MessageQueueReceive";
+			break;
+		case WAIT_EVENT_MQ_SEND:
+			event_name = "MessageQueueSend";
+			break;
+		case WAIT_EVENT_PARALLEL_BITMAP_SCAN:
+			event_name = "ParallelBitmapScan";
+			break;
+		case WAIT_EVENT_PARALLEL_CREATE_INDEX_SCAN:
+			event_name = "ParallelCreateIndexScan";
+			break;
+		case WAIT_EVENT_PARALLEL_FINISH:
+			event_name = "ParallelFinish";
+			break;
+		case WAIT_EVENT_PROCARRAY_GROUP_UPDATE:
+			event_name = "ProcArrayGroupUpdate";
+			break;
+		case WAIT_EVENT_PROMOTE:
+			event_name = "Promote";
+			break;
+		case WAIT_EVENT_REPLICATION_ORIGIN_DROP:
+			event_name = "ReplicationOriginDrop";
+			break;
+		case WAIT_EVENT_REPLICATION_SLOT_DROP:
+			event_name = "ReplicationSlotDrop";
+			break;
+		case WAIT_EVENT_SAFE_SNAPSHOT:
+			event_name = "SafeSnapshot";
+			break;
+		case WAIT_EVENT_SYNC_REP:
+			event_name = "SyncRep";
+			break;
+			/* no default case, so that compiler will warn */
+	}
+
+	return event_name;
+}
+
+/* ----------
+ * pgstat_get_wait_timeout() -
+ *
+ * Convert WaitEventTimeout to string.
+ * ----------
+ */
+static const char *
+pgstat_get_wait_timeout(WaitEventTimeout w)
+{
+	const char *event_name = "unknown wait event";
+
+	switch (w)
+	{
+		case WAIT_EVENT_BASE_BACKUP_THROTTLE:
+			event_name = "BaseBackupThrottle";
+			break;
+		case WAIT_EVENT_PG_SLEEP:
+			event_name = "PgSleep";
+			break;
+		case WAIT_EVENT_RECOVERY_APPLY_DELAY:
+			event_name = "RecoveryApplyDelay";
+			break;
+			/* no default case, so that compiler will warn */
+	}
+
+	return event_name;
+}
+
+/* ----------
+ * pgstat_get_wait_io() -
+ *
+ * Convert WaitEventIO to string.
+ * ----------
+ */
+static const char *
+pgstat_get_wait_io(WaitEventIO w)
+{
+	const char *event_name = "unknown wait event";
+
+	switch (w)
+	{
+		case WAIT_EVENT_BUFFILE_READ:
+			event_name = "BufFileRead";
+			break;
+		case WAIT_EVENT_BUFFILE_WRITE:
+			event_name = "BufFileWrite";
+			break;
+		case WAIT_EVENT_CONTROL_FILE_READ:
+			event_name = "ControlFileRead";
+			break;
+		case WAIT_EVENT_CONTROL_FILE_SYNC:
+			event_name = "ControlFileSync";
+			break;
+		case WAIT_EVENT_CONTROL_FILE_SYNC_UPDATE:
+			event_name = "ControlFileSyncUpdate";
+			break;
+		case WAIT_EVENT_CONTROL_FILE_WRITE:
+			event_name = "ControlFileWrite";
+			break;
+		case WAIT_EVENT_CONTROL_FILE_WRITE_UPDATE:
+			event_name = "ControlFileWriteUpdate";
+			break;
+		case WAIT_EVENT_COPY_FILE_READ:
+			event_name = "CopyFileRead";
+			break;
+		case WAIT_EVENT_COPY_FILE_WRITE:
+			event_name = "CopyFileWrite";
+			break;
+		case WAIT_EVENT_DATA_FILE_EXTEND:
+			event_name = "DataFileExtend";
+			break;
+		case WAIT_EVENT_DATA_FILE_FLUSH:
+			event_name = "DataFileFlush";
+			break;
+		case WAIT_EVENT_DATA_FILE_IMMEDIATE_SYNC:
+			event_name = "DataFileImmediateSync";
+			break;
+		case WAIT_EVENT_DATA_FILE_PREFETCH:
+			event_name = "DataFilePrefetch";
+			break;
+		case WAIT_EVENT_DATA_FILE_READ:
+			event_name = "DataFileRead";
+			break;
+		case WAIT_EVENT_DATA_FILE_SYNC:
+			event_name = "DataFileSync";
+			break;
+		case WAIT_EVENT_DATA_FILE_TRUNCATE:
+			event_name = "DataFileTruncate";
+			break;
+		case WAIT_EVENT_DATA_FILE_WRITE:
+			event_name = "DataFileWrite";
+			break;
+		case WAIT_EVENT_DSM_FILL_ZERO_WRITE:
+			event_name = "DSMFillZeroWrite";
+			break;
+		case WAIT_EVENT_LOCK_FILE_ADDTODATADIR_READ:
+			event_name = "LockFileAddToDataDirRead";
+			break;
+		case WAIT_EVENT_LOCK_FILE_ADDTODATADIR_SYNC:
+			event_name = "LockFileAddToDataDirSync";
+			break;
+		case WAIT_EVENT_LOCK_FILE_ADDTODATADIR_WRITE:
+			event_name = "LockFileAddToDataDirWrite";
+			break;
+		case WAIT_EVENT_LOCK_FILE_CREATE_READ:
+			event_name = "LockFileCreateRead";
+			break;
+		case WAIT_EVENT_LOCK_FILE_CREATE_SYNC:
+			event_name = "LockFileCreateSync";
+			break;
+		case WAIT_EVENT_LOCK_FILE_CREATE_WRITE:
+			event_name = "LockFileCreateWRITE";
+			break;
+		case WAIT_EVENT_LOCK_FILE_RECHECKDATADIR_READ:
+			event_name = "LockFileReCheckDataDirRead";
+			break;
+		case WAIT_EVENT_LOGICAL_REWRITE_CHECKPOINT_SYNC:
+			event_name = "LogicalRewriteCheckpointSync";
+			break;
+		case WAIT_EVENT_LOGICAL_REWRITE_MAPPING_SYNC:
+			event_name = "LogicalRewriteMappingSync";
+			break;
+		case WAIT_EVENT_LOGICAL_REWRITE_MAPPING_WRITE:
+			event_name = "LogicalRewriteMappingWrite";
+			break;
+		case WAIT_EVENT_LOGICAL_REWRITE_SYNC:
+			event_name = "LogicalRewriteSync";
+			break;
+		case WAIT_EVENT_LOGICAL_REWRITE_TRUNCATE:
+			event_name = "LogicalRewriteTruncate";
+			break;
+		case WAIT_EVENT_LOGICAL_REWRITE_WRITE:
+			event_name = "LogicalRewriteWrite";
+			break;
+		case WAIT_EVENT_RELATION_MAP_READ:
+			event_name = "RelationMapRead";
+			break;
+		case WAIT_EVENT_RELATION_MAP_SYNC:
+			event_name = "RelationMapSync";
+			break;
+		case WAIT_EVENT_RELATION_MAP_WRITE:
+			event_name = "RelationMapWrite";
+			break;
+		case WAIT_EVENT_REORDER_BUFFER_READ:
+			event_name = "ReorderBufferRead";
+			break;
+		case WAIT_EVENT_REORDER_BUFFER_WRITE:
+			event_name = "ReorderBufferWrite";
+			break;
+		case WAIT_EVENT_REORDER_LOGICAL_MAPPING_READ:
+			event_name = "ReorderLogicalMappingRead";
+			break;
+		case WAIT_EVENT_REPLICATION_SLOT_READ:
+			event_name = "ReplicationSlotRead";
+			break;
+		case WAIT_EVENT_REPLICATION_SLOT_RESTORE_SYNC:
+			event_name = "ReplicationSlotRestoreSync";
+			break;
+		case WAIT_EVENT_REPLICATION_SLOT_SYNC:
+			event_name = "ReplicationSlotSync";
+			break;
+		case WAIT_EVENT_REPLICATION_SLOT_WRITE:
+			event_name = "ReplicationSlotWrite";
+			break;
+		case WAIT_EVENT_SLRU_FLUSH_SYNC:
+			event_name = "SLRUFlushSync";
+			break;
+		case WAIT_EVENT_SLRU_READ:
+			event_name = "SLRURead";
+			break;
+		case WAIT_EVENT_SLRU_SYNC:
+			event_name = "SLRUSync";
+			break;
+		case WAIT_EVENT_SLRU_WRITE:
+			event_name = "SLRUWrite";
+			break;
+		case WAIT_EVENT_SNAPBUILD_READ:
+			event_name = "SnapbuildRead";
+			break;
+		case WAIT_EVENT_SNAPBUILD_SYNC:
+			event_name = "SnapbuildSync";
+			break;
+		case WAIT_EVENT_SNAPBUILD_WRITE:
+			event_name = "SnapbuildWrite";
+			break;
+		case WAIT_EVENT_TIMELINE_HISTORY_FILE_SYNC:
+			event_name = "TimelineHistoryFileSync";
+			break;
+		case WAIT_EVENT_TIMELINE_HISTORY_FILE_WRITE:
+			event_name = "TimelineHistoryFileWrite";
+			break;
+		case WAIT_EVENT_TIMELINE_HISTORY_READ:
+			event_name = "TimelineHistoryRead";
+			break;
+		case WAIT_EVENT_TIMELINE_HISTORY_SYNC:
+			event_name = "TimelineHistorySync";
+			break;
+		case WAIT_EVENT_TIMELINE_HISTORY_WRITE:
+			event_name = "TimelineHistoryWrite";
+			break;
+		case WAIT_EVENT_TWOPHASE_FILE_READ:
+			event_name = "TwophaseFileRead";
+			break;
+		case WAIT_EVENT_TWOPHASE_FILE_SYNC:
+			event_name = "TwophaseFileSync";
+			break;
+		case WAIT_EVENT_TWOPHASE_FILE_WRITE:
+			event_name = "TwophaseFileWrite";
+			break;
+		case WAIT_EVENT_WALSENDER_TIMELINE_HISTORY_READ:
+			event_name = "WALSenderTimelineHistoryRead";
+			break;
+		case WAIT_EVENT_WAL_BOOTSTRAP_SYNC:
+			event_name = "WALBootstrapSync";
+			break;
+		case WAIT_EVENT_WAL_BOOTSTRAP_WRITE:
+			event_name = "WALBootstrapWrite";
+			break;
+		case WAIT_EVENT_WAL_COPY_READ:
+			event_name = "WALCopyRead";
+			break;
+		case WAIT_EVENT_WAL_COPY_SYNC:
+			event_name = "WALCopySync";
+			break;
+		case WAIT_EVENT_WAL_COPY_WRITE:
+			event_name = "WALCopyWrite";
+			break;
+		case WAIT_EVENT_WAL_INIT_SYNC:
+			event_name = "WALInitSync";
+			break;
+		case WAIT_EVENT_WAL_INIT_WRITE:
+			event_name = "WALInitWrite";
+			break;
+		case WAIT_EVENT_WAL_READ:
+			event_name = "WALRead";
+			break;
+		case WAIT_EVENT_WAL_SYNC:
+			event_name = "WALSync";
+			break;
+		case WAIT_EVENT_WAL_SYNC_METHOD_ASSIGN:
+			event_name = "WALSyncMethodAssign";
+			break;
+		case WAIT_EVENT_WAL_WRITE:
+			event_name = "WALWrite";
+			break;
+
+			/* no default case, so that compiler will warn */
+	}
+
+	return event_name;
+}
+
+
+/* ----------
+ * pgstat_get_backend_current_activity() -
+ *
+ *	Return a string representing the current activity of the backend with
+ *	the specified PID.  This looks directly at the BackendStatusArray,
+ *	and so will provide current information regardless of the age of our
+ *	transaction's snapshot of the status array.
+ *
+ *	It is the caller's responsibility to invoke this only for backends whose
+ *	state is expected to remain stable while the result is in use.  The
+ *	only current use is in deadlock reporting, where we can expect that
+ *	the target backend is blocked on a lock.  (There are corner cases
+ *	where the target's wait could get aborted while we are looking at it,
+ *	but the very worst consequence is to return a pointer to a string
+ *	that's been changed, so we won't worry too much.)
+ *
+ *	Note: return strings for special cases match pg_stat_get_backend_activity.
+ * ----------
+ */
+const char *
+pgstat_get_backend_current_activity(int pid, bool checkUser)
+{
+	PgBackendStatus *beentry;
+	int			i;
+
+	beentry = BackendStatusArray;
+	for (i = 1; i <= MaxBackends; i++)
+	{
+		/*
+		 * Although we expect the target backend's entry to be stable, that
+		 * doesn't imply that anyone else's is.  To avoid identifying the
+		 * wrong backend, while we check for a match to the desired PID we
+		 * must follow the protocol of retrying if st_changecount changes
+		 * while we examine the entry, or if it's odd.  (This might be
+		 * unnecessary, since fetching or storing an int is almost certainly
+		 * atomic, but let's play it safe.)  We use a volatile pointer here to
+		 * ensure the compiler doesn't try to get cute.
+		 */
+		volatile PgBackendStatus *vbeentry = beentry;
+		bool		found;
+
+		for (;;)
+		{
+			int			before_changecount;
+			int			after_changecount;
+
+			pgstat_save_changecount_before(vbeentry, before_changecount);
+
+			found = (vbeentry->st_procpid == pid);
+
+			pgstat_save_changecount_after(vbeentry, after_changecount);
+
+			if (before_changecount == after_changecount &&
+				(before_changecount & 1) == 0)
+				break;
+
+			/* Make sure we can break out of loop if stuck... */
+			CHECK_FOR_INTERRUPTS();
+		}
+
+		if (found)
+		{
+			/* Now it is safe to use the non-volatile pointer */
+			if (checkUser && !superuser() && beentry->st_userid != GetUserId())
+				return "<insufficient privilege>";
+			else if (*(beentry->st_activity_raw) == '\0')
+				return "<command string not enabled>";
+			else
+			{
+				/* this'll leak a bit of memory, but that seems acceptable */
+				return pgstat_clip_activity(beentry->st_activity_raw);
+			}
+		}
+
+		beentry++;
+	}
+
+	/* If we get here, caller is in error ... */
+	return "<backend information not available>";
+}
+
+/* ----------
+ * pgstat_get_crashed_backend_activity() -
+ *
+ *	Return a string representing the current activity of the backend with
+ *	the specified PID.  Like the function above, but reads shared memory with
+ *	the expectation that it may be corrupt.  On success, copy the string
+ *	into the "buffer" argument and return that pointer.  On failure,
+ *	return NULL.
+ *
+ *	This function is only intended to be used by the postmaster to report the
+ *	query that crashed a backend.  In particular, no attempt is made to
+ *	follow the correct concurrency protocol when accessing the
+ *	BackendStatusArray.  But that's OK, in the worst case we'll return a
+ *	corrupted message.  We also must take care not to trip on ereport(ERROR).
+ * ----------
+ */
+const char *
+pgstat_get_crashed_backend_activity(int pid, char *buffer, int buflen)
+{
+	volatile PgBackendStatus *beentry;
+	int			i;
+
+	beentry = BackendStatusArray;
+
+	/*
+	 * We probably shouldn't get here before shared memory has been set up,
+	 * but be safe.
+	 */
+	if (beentry == NULL || BackendActivityBuffer == NULL)
+		return NULL;
+
+	for (i = 1; i <= MaxBackends; i++)
+	{
+		if (beentry->st_procpid == pid)
+		{
+			/* Read pointer just once, so it can't change after validation */
+			const char *activity = beentry->st_activity_raw;
+			const char *activity_last;
+
+			/*
+			 * We mustn't access activity string before we verify that it
+			 * falls within the BackendActivityBuffer. To make sure that the
+			 * entire string including its ending is contained within the
+			 * buffer, subtract one activity length from the buffer size.
+			 */
+			activity_last = BackendActivityBuffer + BackendActivityBufferSize
+				- pgstat_track_activity_query_size;
+
+			if (activity < BackendActivityBuffer ||
+				activity > activity_last)
+				return NULL;
+
+			/* If no string available, no point in a report */
+			if (activity[0] == '\0')
+				return NULL;
+
+			/*
+			 * Copy only ASCII-safe characters so we don't run into encoding
+			 * problems when reporting the message; and be sure not to run off
+			 * the end of memory.  As only ASCII characters are reported, it
+			 * doesn't seem necessary to perform multibyte aware clipping.
+			 */
+			ascii_safe_strlcpy(buffer, activity,
+							   Min(buflen, pgstat_track_activity_query_size));
+
+			return buffer;
+		}
+
+		beentry++;
+	}
+
+	/* PID not found */
+	return NULL;
+}
+
+const char *
+pgstat_get_backend_desc(BackendType backendType)
+{
+	const char *backendDesc = "unknown process type";
+
+	switch (backendType)
+	{
+		case B_AUTOVAC_LAUNCHER:
+			backendDesc = "autovacuum launcher";
+			break;
+		case B_AUTOVAC_WORKER:
+			backendDesc = "autovacuum worker";
+			break;
+		case B_BACKEND:
+			backendDesc = "client backend";
+			break;
+		case B_BG_WORKER:
+			backendDesc = "background worker";
+			break;
+		case B_BG_WRITER:
+			backendDesc = "background writer";
+			break;
+		case B_CHECKPOINTER:
+			backendDesc = "checkpointer";
+			break;
+		case B_STARTUP:
+			backendDesc = "startup";
+			break;
+		case B_WAL_RECEIVER:
+			backendDesc = "walreceiver";
+			break;
+		case B_WAL_SENDER:
+			backendDesc = "walsender";
+			break;
+		case B_WAL_WRITER:
+			backendDesc = "walwriter";
+			break;
+		case B_ARCHIVER:
+			backendDesc = "archiver";
+			break;
+	}
+
+	return backendDesc;
+}
+
+/* ----------
+ * pgstat_report_appname() -
+ *
+ *	Called to update our application name.
+ * ----------
+ */
+void
+pgstat_report_appname(const char *appname)
+{
+	volatile PgBackendStatus *beentry = MyBEEntry;
+	int			len;
+
+	if (!beentry)
+		return;
+
+	/* This should be unnecessary if GUC did its job, but be safe */
+	len = pg_mbcliplen(appname, strlen(appname), NAMEDATALEN - 1);
+
+	/*
+	 * Update my status entry, following the protocol of bumping
+	 * st_changecount before and after.  We use a volatile pointer here to
+	 * ensure the compiler doesn't try to get cute.
+	 */
+	pgstat_increment_changecount_before(beentry);
+
+	memcpy((char *) beentry->st_appname, appname, len);
+	beentry->st_appname[len] = '\0';
+
+	pgstat_increment_changecount_after(beentry);
+}
+
+/*
+ * Report current transaction start timestamp as the specified value.
+ * Zero means there is no active transaction.
+ */
+void
+pgstat_report_xact_timestamp(TimestampTz tstamp)
+{
+	volatile PgBackendStatus *beentry = MyBEEntry;
+
+	if (!pgstat_track_activities || !beentry)
+		return;
+
+	/*
+	 * Update my status entry, following the protocol of bumping
+	 * st_changecount before and after.  We use a volatile pointer here to
+	 * ensure the compiler doesn't try to get cute.
+	 */
+	pgstat_increment_changecount_before(beentry);
+	beentry->st_xact_start_timestamp = tstamp;
+	pgstat_increment_changecount_after(beentry);
+}
+
+/* ----------
+ * pgstat_setup_memcxt() -
+ *
+ *	Create pgBeStatLocalContext, if not already done.
+ * ----------
+ */
+static void
+pgstat_setup_memcxt(void)
+{
+	if (!pgBeStatLocalContext)
+		pgBeStatLocalContext = AllocSetContextCreate(TopMemoryContext,
+													 "Backend status snapshot",
+													 ALLOCSET_SMALL_SIZES);
+}
+
+/* ----------
+ * 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_bestatus_clear_snapshot(void)
+{
+	/* Release memory, if any was allocated */
+	if (pgBeStatLocalContext)
+		MemoryContextDelete(pgBeStatLocalContext);
+
+	/* Reset variables */
+	pgBeStatLocalContext = NULL;
+	localBackendStatusTable = NULL;
+	localNumBackends = 0;
+}
+
+
+
+/* ----------
+ * pgstat_report_activity() -
+ *
+ *	Called from tcop/postgres.c to report what the backend is actually doing
+ *	(but note cmd_str can be NULL for certain cases).
+ *
+ * All updates of the status entry follow the protocol of bumping
+ * st_changecount before and after.  We use a volatile pointer here to
+ * ensure the compiler doesn't try to get cute.
+ * ----------
+ */
+void
+pgstat_report_activity(BackendState state, const char *cmd_str)
+{
+	volatile PgBackendStatus *beentry = MyBEEntry;
+	TimestampTz start_timestamp;
+	TimestampTz current_timestamp;
+	int			len = 0;
+
+	TRACE_POSTGRESQL_STATEMENT_STATUS(cmd_str);
+
+	if (!beentry)
+		return;
+
+	if (!pgstat_track_activities)
+	{
+		if (beentry->st_state != STATE_DISABLED)
+		{
+			volatile PGPROC *proc = MyProc;
+
+			/*
+			 * track_activities is disabled, but we last reported a
+			 * non-disabled state.  As our final update, change the state and
+			 * clear fields we will not be updating anymore.
+			 */
+			pgstat_increment_changecount_before(beentry);
+			beentry->st_state = STATE_DISABLED;
+			beentry->st_state_start_timestamp = 0;
+			beentry->st_activity_raw[0] = '\0';
+			beentry->st_activity_start_timestamp = 0;
+			/* st_xact_start_timestamp and wait_event_info are also disabled */
+			beentry->st_xact_start_timestamp = 0;
+			proc->wait_event_info = 0;
+			pgstat_increment_changecount_after(beentry);
+		}
+		return;
+	}
+
+	/*
+	 * To minimize the time spent modifying the entry, fetch all the needed
+	 * data first.
+	 */
+	start_timestamp = GetCurrentStatementStartTimestamp();
+	if (cmd_str != NULL)
+	{
+		/*
+		 * Compute length of to-be-stored string unaware of multi-byte
+		 * characters. For speed reasons that'll get corrected on read, rather
+		 * than computed every write.
+		 */
+		len = Min(strlen(cmd_str), pgstat_track_activity_query_size - 1);
+	}
+	current_timestamp = GetCurrentTimestamp();
+
+	/*
+	 * Now update the status entry
+	 */
+	pgstat_increment_changecount_before(beentry);
+
+	beentry->st_state = state;
+	beentry->st_state_start_timestamp = current_timestamp;
+
+	if (cmd_str != NULL)
+	{
+		memcpy((char *) beentry->st_activity_raw, cmd_str, len);
+		beentry->st_activity_raw[len] = '\0';
+		beentry->st_activity_start_timestamp = start_timestamp;
+	}
+
+	pgstat_increment_changecount_after(beentry);
+}
+
+/*-----------
+ * pgstat_progress_start_command() -
+ *
+ * Set st_progress_command (and st_progress_command_target) in own backend
+ * entry.  Also, zero-initialize st_progress_param array.
+ *-----------
+ */
+void
+pgstat_progress_start_command(ProgressCommandType cmdtype, Oid relid)
+{
+	volatile PgBackendStatus *beentry = MyBEEntry;
+
+	if (!beentry || !pgstat_track_activities)
+		return;
+
+	pgstat_increment_changecount_before(beentry);
+	beentry->st_progress_command = cmdtype;
+	beentry->st_progress_command_target = relid;
+	MemSet(&beentry->st_progress_param, 0, sizeof(beentry->st_progress_param));
+	pgstat_increment_changecount_after(beentry);
+}
+
+/*-----------
+ * pgstat_progress_update_param() -
+ *
+ * Update index'th member in st_progress_param[] of own backend entry.
+ *-----------
+ */
+void
+pgstat_progress_update_param(int index, int64 val)
+{
+	volatile PgBackendStatus *beentry = MyBEEntry;
+
+	Assert(index >= 0 && index < PGSTAT_NUM_PROGRESS_PARAM);
+
+	if (!beentry || !pgstat_track_activities)
+		return;
+
+	pgstat_increment_changecount_before(beentry);
+	beentry->st_progress_param[index] = val;
+	pgstat_increment_changecount_after(beentry);
+}
+
+/*-----------
+ * pgstat_progress_update_multi_param() -
+ *
+ * Update multiple members in st_progress_param[] of own backend entry.
+ * This is atomic; readers won't see intermediate states.
+ *-----------
+ */
+void
+pgstat_progress_update_multi_param(int nparam, const int *index,
+								   const int64 *val)
+{
+	volatile PgBackendStatus *beentry = MyBEEntry;
+	int			i;
+
+	if (!beentry || !pgstat_track_activities || nparam == 0)
+		return;
+
+	pgstat_increment_changecount_before(beentry);
+
+	for (i = 0; i < nparam; ++i)
+	{
+		Assert(index[i] >= 0 && index[i] < PGSTAT_NUM_PROGRESS_PARAM);
+
+		beentry->st_progress_param[index[i]] = val[i];
+	}
+
+	pgstat_increment_changecount_after(beentry);
+}
+
+/*-----------
+ * pgstat_progress_end_command() -
+ *
+ * Reset st_progress_command (and st_progress_command_target) in own backend
+ * entry.  This signals the end of the command.
+ *-----------
+ */
+void
+pgstat_progress_end_command(void)
+{
+	volatile PgBackendStatus *beentry = MyBEEntry;
+
+	if (!beentry)
+		return;
+	if (!pgstat_track_activities
+		&& beentry->st_progress_command == PROGRESS_COMMAND_INVALID)
+		return;
+
+	pgstat_increment_changecount_before(beentry);
+	beentry->st_progress_command = PROGRESS_COMMAND_INVALID;
+	beentry->st_progress_command_target = InvalidOid;
+	pgstat_increment_changecount_after(beentry);
+}
+
+
+/*
+ * Convert a potentially unsafely truncated activity string (see
+ * PgBackendStatus.st_activity_raw's documentation) into a correctly truncated
+ * one.
+ *
+ * The returned string is allocated in the caller's memory context and may be
+ * freed.
+ */
+char *
+pgstat_clip_activity(const char *raw_activity)
+{
+	char	   *activity;
+	int			rawlen;
+	int			cliplen;
+
+	/*
+	 * Some callers, like pgstat_get_backend_current_activity(), do not
+	 * guarantee that the buffer isn't concurrently modified. We try to take
+	 * care that the buffer is always terminated by a NUL byte regardless, but
+	 * let's still be paranoid about the string's length. In those cases the
+	 * underlying buffer is guaranteed to be pgstat_track_activity_query_size
+	 * large.
+	 */
+	activity = pnstrdup(raw_activity, pgstat_track_activity_query_size - 1);
+
+	/* now double-guaranteed to be NUL terminated */
+	rawlen = strlen(activity);
+
+	/*
+	 * All supported server-encodings make it possible to determine the length
+	 * of a multi-byte character from its first byte (this is not the case for
+	 * client encodings, see GB18030). As st_activity is always stored using
+	 * server encoding, this allows us to perform multi-byte aware truncation,
+	 * even if the string earlier was truncated in the middle of a multi-byte
+	 * character.
+	 */
+	cliplen = pg_mbcliplen(activity, rawlen,
+						   pgstat_track_activity_query_size - 1);
+
+	activity[cliplen] = '\0';
+
+	return activity;
+}
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/statmon/pgstat.c
similarity index 70%
rename from src/backend/postmaster/pgstat.c
rename to src/backend/statmon/pgstat.c
index 2d3f7cb898..4a1101c2b0 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/statmon/pgstat.c
@@ -8,7 +8,7 @@
  *
  *	Copyright (c) 2001-2018, PostgreSQL Global Development Group
  *
- *	src/backend/postmaster/pgstat.c
+ *	src/backend/statmon/pgstat.c
  * ----------
  */
 #include "postgres.h"
@@ -21,19 +21,14 @@
 #include "access/htup_details.h"
 #include "access/twophase_rmgr.h"
 #include "access/xact.h"
+#include "bestatus.h"
 #include "catalog/pg_database.h"
 #include "catalog/pg_proc.h"
-#include "libpq/libpq.h"
 #include "miscadmin.h"
-#include "pg_trace.h"
 #include "postmaster/autovacuum.h"
-#include "replication/walsender.h"
 #include "storage/ipc.h"
 #include "storage/lmgr.h"
 #include "storage/procsignal.h"
-#include "storage/sinvaladt.h"
-#include "utils/ascii.h"
-#include "utils/guc.h"
 #include "utils/memutils.h"
 #include "utils/snapmgr.h"
 
@@ -68,26 +63,12 @@ typedef enum
 	PGSTAT_ENTRY_LOCK_FAILED
 } pg_stat_table_result_status;
 
-/* ----------
- * Total number of backends including auxiliary
- *
- * We reserve a slot for each possible BackendId, plus one for each
- * possible auxiliary process type.  (This scheme assumes there is not
- * more than one of any auxiliary process type at a time.) MaxBackends
- * includes autovacuum workers and background workers as well.
- * ----------
- */
-#define NumBackendStatSlots (MaxBackends + NUM_AUXPROCTYPES)
-
-
 /* ----------
  * GUC parameters
  * ----------
  */
-bool		pgstat_track_activities = false;
 bool		pgstat_track_counts = false;
 int			pgstat_track_functions = TRACK_FUNC_OFF;
-int			pgstat_track_activity_query_size = 1024;
 
 /* Shared stats bootstrap infomation */
 typedef struct StatsShmemStruct {
@@ -125,6 +106,8 @@ static bool pgstat_pending_recoveryconflict = false;
 static bool pgstat_pending_deadlock = false;
 static bool pgstat_pending_tempfile = false;
 
+static MemoryContext pgStatLocalContext = NULL;
+
 /* dshash parameter for each type of table */
 static const dshash_parameters dsh_dbparams = {
 	sizeof(Oid),
@@ -236,15 +219,8 @@ typedef struct
 /*
  * Info about current "snapshot" of stats file
  */
-static MemoryContext pgStatLocalContext = NULL;
 static HTAB *pgStatDBHash = NULL;
 
-/* Status for backends including auxiliary */
-static LocalPgBackendStatus *localBackendStatusTable = NULL;
-
-/* Total number of backends including auxiliary */
-static int	localNumBackends = 0;
-
 /*
  * Cluster wide statistics.
  * Contains statistics that are not collected per database or per table.
@@ -280,7 +256,6 @@ static void pgstat_read_db_statsfile(Oid databaseid, dshash_table *tabhash, dsha
 /* functions used in backends */
 static bool backend_snapshot_global_stats(void);
 static PgStat_StatFuncEntry *backend_get_func_etnry(PgStat_StatDBEntry *dbent, Oid funcid, bool oneshot);
-static void pgstat_read_current_status(void);
 
 static void pgstat_postmaster_shutdown(int code, Datum arg);
 static void pgstat_apply_pending_tabstats(bool shared, bool force,
@@ -307,12 +282,6 @@ static PgStat_TableStatus *get_tabstat_entry(Oid rel_id, bool isshared);
 
 static void pgstat_setup_memcxt(void);
 
-static const char *pgstat_get_wait_activity(WaitEventActivity w);
-static const char *pgstat_get_wait_client(WaitEventClient w);
-static const char *pgstat_get_wait_ipc(WaitEventIPC w);
-static const char *pgstat_get_wait_timeout(WaitEventTimeout w);
-static const char *pgstat_get_wait_io(WaitEventIO w);
-
 static bool pgstat_update_tabentry(dshash_table *tabhash,
 								   PgStat_TableStatus *stat, bool nowait);
 static void pgstat_update_dbentry(PgStat_StatDBEntry *dbentry,
@@ -323,6 +292,14 @@ static void pgstat_update_dbentry(PgStat_StatDBEntry *dbentry,
  * ------------------------------------------------------------
  */
 
+
+void
+pgstat_initialize(void)
+{
+	/* Set up a process-exit hook to clean up */
+	before_shmem_exit(pgstat_beshutdown_hook, 0);
+}
+
 /*
  * subroutine for pgstat_reset_all
  */
@@ -484,7 +461,7 @@ pgstat_update_stat(bool force)
 		 */
 		TimestampDifference(last_report, now, &secs, &usecs);
 		elapsed = secs * 1000 + usecs /1000;
-		
+
 		if(elapsed < PGSTAT_STAT_MIN_INTERVAL)
 		{
 			/* we know we have some statistics */
@@ -740,7 +717,7 @@ pgstat_apply_tabstat(pgstat_apply_tabstat_context *cxt,
 			pgStatBlockReadTime = 0;
 			pgStatBlockWriteTime = 0;
 		}
-		
+
 		cxt->tabhash =
 			dshash_attach(area, &dsh_tblparams, cxt->dbentry->tables, 0);
 	}
@@ -800,7 +777,7 @@ pgstat_merge_tabentry(PgStat_TableStatus *deststat,
 		dest->t_blocks_hit += src->t_blocks_hit;
 	}
 }
-		
+
 /*
  * pgstat_update_funcstats: subroutine for pgstat_update_stat
  *
@@ -920,7 +897,7 @@ pgstat_update_funcstats(bool force, PgStat_StatDBEntry *dbentry)
 				hash_search(pgStatPendingFunctions,
 							(void *) &(pendent->functionid), HASH_REMOVE, NULL);
 			}
-		}	
+		}
 
 		/* destroy the hsah if no entry remains */
 		if (hash_get_num_entries(pgStatPendingFunctions) == 0)
@@ -1058,7 +1035,7 @@ pgstat_vacuum_stat(void)
 	dbentry = pgstat_get_db_entry(MyDatabaseId, PGSTAT_FETCH_EXCLUSIVE, NULL);
 	if (!dbentry)
 		return;
-	
+
 	/*
 	 * Similarly to above, make a list of all known relations in this DB.
 	 */
@@ -2611,66 +2588,6 @@ pgstat_fetch_stat_funcentry(Oid func_id)
 	return funcentry;
 }
 
-
-/* ----------
- * pgstat_fetch_stat_beentry() -
- *
- *	Support function for the SQL-callable pgstat* functions. Returns
- *	our local copy of the current-activity entry for one backend.
- *
- *	NB: caller is responsible for a check if the user is permitted to see
- *	this info (especially the querystring).
- * ----------
- */
-PgBackendStatus *
-pgstat_fetch_stat_beentry(int beid)
-{
-	pgstat_read_current_status();
-
-	if (beid < 1 || beid > localNumBackends)
-		return NULL;
-
-	return &localBackendStatusTable[beid - 1].backendStatus;
-}
-
-
-/* ----------
- * pgstat_fetch_stat_local_beentry() -
- *
- *	Like pgstat_fetch_stat_beentry() but with locally computed additions (like
- *	xid and xmin values of the backend)
- *
- *	NB: caller is responsible for a check if the user is permitted to see
- *	this info (especially the querystring).
- * ----------
- */
-LocalPgBackendStatus *
-pgstat_fetch_stat_local_beentry(int beid)
-{
-	pgstat_read_current_status();
-
-	if (beid < 1 || beid > localNumBackends)
-		return NULL;
-
-	return &localBackendStatusTable[beid - 1];
-}
-
-
-/* ----------
- * pgstat_fetch_stat_numbackends() -
- *
- *	Support function for the SQL-callable pgstat* functions. Returns
- *	the maximum current backend id.
- * ----------
- */
-int
-pgstat_fetch_stat_numbackends(void)
-{
-	pgstat_read_current_status();
-
-	return localNumBackends;
-}
-
 /*
  * ---------
  * pgstat_fetch_stat_archiver() -
@@ -2708,364 +2625,6 @@ pgstat_fetch_global(void)
 	return snapshot_globalStats;
 }
 
-
-/* ------------------------------------------------------------
- * Functions for management of the shared-memory PgBackendStatus array
- * ------------------------------------------------------------
- */
-
-static PgBackendStatus *BackendStatusArray = NULL;
-static PgBackendStatus *MyBEEntry = NULL;
-static char *BackendAppnameBuffer = NULL;
-static char *BackendClientHostnameBuffer = NULL;
-static char *BackendActivityBuffer = NULL;
-static Size BackendActivityBufferSize = 0;
-#ifdef USE_SSL
-static PgBackendSSLStatus *BackendSslStatusBuffer = NULL;
-#endif
-
-
-/*
- * Report shared-memory space needed by CreateSharedBackendStatus.
- */
-Size
-BackendStatusShmemSize(void)
-{
-	Size		size;
-
-	/* BackendStatusArray: */
-	size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots);
-	/* BackendAppnameBuffer: */
-	size = add_size(size,
-					mul_size(NAMEDATALEN, NumBackendStatSlots));
-	/* BackendClientHostnameBuffer: */
-	size = add_size(size,
-					mul_size(NAMEDATALEN, NumBackendStatSlots));
-	/* BackendActivityBuffer: */
-	size = add_size(size,
-					mul_size(pgstat_track_activity_query_size, NumBackendStatSlots));
-#ifdef USE_SSL
-	/* BackendSslStatusBuffer: */
-	size = add_size(size,
-					mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots));
-#endif
-	return size;
-}
-
-/*
- * Initialize the shared status array and several string buffers
- * during postmaster startup.
- */
-void
-CreateSharedBackendStatus(void)
-{
-	Size		size;
-	bool		found;
-	int			i;
-	char	   *buffer;
-
-	/* Create or attach to the shared array */
-	size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots);
-	BackendStatusArray = (PgBackendStatus *)
-		ShmemInitStruct("Backend Status Array", size, &found);
-
-	if (!found)
-	{
-		/*
-		 * We're the first - initialize.
-		 */
-		MemSet(BackendStatusArray, 0, size);
-	}
-
-	/* Create or attach to the shared appname buffer */
-	size = mul_size(NAMEDATALEN, NumBackendStatSlots);
-	BackendAppnameBuffer = (char *)
-		ShmemInitStruct("Backend Application Name Buffer", size, &found);
-
-	if (!found)
-	{
-		MemSet(BackendAppnameBuffer, 0, size);
-
-		/* Initialize st_appname pointers. */
-		buffer = BackendAppnameBuffer;
-		for (i = 0; i < NumBackendStatSlots; i++)
-		{
-			BackendStatusArray[i].st_appname = buffer;
-			buffer += NAMEDATALEN;
-		}
-	}
-
-	/* Create or attach to the shared client hostname buffer */
-	size = mul_size(NAMEDATALEN, NumBackendStatSlots);
-	BackendClientHostnameBuffer = (char *)
-		ShmemInitStruct("Backend Client Host Name Buffer", size, &found);
-
-	if (!found)
-	{
-		MemSet(BackendClientHostnameBuffer, 0, size);
-
-		/* Initialize st_clienthostname pointers. */
-		buffer = BackendClientHostnameBuffer;
-		for (i = 0; i < NumBackendStatSlots; i++)
-		{
-			BackendStatusArray[i].st_clienthostname = buffer;
-			buffer += NAMEDATALEN;
-		}
-	}
-
-	/* Create or attach to the shared activity buffer */
-	BackendActivityBufferSize = mul_size(pgstat_track_activity_query_size,
-										 NumBackendStatSlots);
-	BackendActivityBuffer = (char *)
-		ShmemInitStruct("Backend Activity Buffer",
-						BackendActivityBufferSize,
-						&found);
-
-	if (!found)
-	{
-		MemSet(BackendActivityBuffer, 0, BackendActivityBufferSize);
-
-		/* Initialize st_activity pointers. */
-		buffer = BackendActivityBuffer;
-		for (i = 0; i < NumBackendStatSlots; i++)
-		{
-			BackendStatusArray[i].st_activity_raw = buffer;
-			buffer += pgstat_track_activity_query_size;
-		}
-	}
-
-#ifdef USE_SSL
-	/* Create or attach to the shared SSL status buffer */
-	size = mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots);
-	BackendSslStatusBuffer = (PgBackendSSLStatus *)
-		ShmemInitStruct("Backend SSL Status Buffer", size, &found);
-
-	if (!found)
-	{
-		PgBackendSSLStatus *ptr;
-
-		MemSet(BackendSslStatusBuffer, 0, size);
-
-		/* Initialize st_sslstatus pointers. */
-		ptr = BackendSslStatusBuffer;
-		for (i = 0; i < NumBackendStatSlots; i++)
-		{
-			BackendStatusArray[i].st_sslstatus = ptr;
-			ptr++;
-		}
-	}
-#endif
-}
-
-
-/* ----------
- * pgstat_initialize() -
- *
- *	Initialize pgstats state, and set up our on-proc-exit hook.
- *	Called from InitPostgres and AuxiliaryProcessMain. For auxiliary process,
- *	MyBackendId is invalid. Otherwise, MyBackendId must be set,
- *	but we must not have started any transaction yet (since the
- *	exit hook must run after the last transaction exit).
- *	NOTE: MyDatabaseId isn't set yet; so the shutdown hook has to be careful.
- * ----------
- */
-void
-pgstat_initialize(void)
-{
-	/* Initialize MyBEEntry */
-	if (MyBackendId != InvalidBackendId)
-	{
-		Assert(MyBackendId >= 1 && MyBackendId <= MaxBackends);
-		MyBEEntry = &BackendStatusArray[MyBackendId - 1];
-	}
-	else
-	{
-		/* Must be an auxiliary process */
-		Assert(MyAuxProcType != NotAnAuxProcess);
-
-		/*
-		 * Assign the MyBEEntry for an auxiliary process.  Since it doesn't
-		 * have a BackendId, the slot is statically allocated based on the
-		 * auxiliary process type (MyAuxProcType).  Backends use slots indexed
-		 * in the range from 1 to MaxBackends (inclusive), so we use
-		 * MaxBackends + AuxBackendType + 1 as the index of the slot for an
-		 * auxiliary process.
-		 */
-		MyBEEntry = &BackendStatusArray[MaxBackends + MyAuxProcType];
-	}
-
-	/* Set up a process-exit hook to clean up */
-	before_shmem_exit(pgstat_beshutdown_hook, 0);
-}
-
-/* ----------
- * pgstat_bestart() -
- *
- *	Initialize this backend's entry in the PgBackendStatus array.
- *	Called from InitPostgres.
- *
- *	Apart from auxiliary processes, MyBackendId, MyDatabaseId,
- *	session userid, and application_name must be set for a
- *	backend (hence, this cannot be combined with pgstat_initialize).
- * ----------
- */
-void
-pgstat_bestart(void)
-{
-	SockAddr	clientaddr;
-	volatile PgBackendStatus *beentry;
-
-	/*
-	 * To minimize the time spent modifying the PgBackendStatus entry, fetch
-	 * all the needed data first.
-	 */
-
-	/*
-	 * We may not have a MyProcPort (eg, if this is the autovacuum process).
-	 * If so, use all-zeroes client address, which is dealt with specially in
-	 * pg_stat_get_backend_client_addr and pg_stat_get_backend_client_port.
-	 */
-	if (MyProcPort)
-		memcpy(&clientaddr, &MyProcPort->raddr, sizeof(clientaddr));
-	else
-		MemSet(&clientaddr, 0, sizeof(clientaddr));
-
-	/*
-	 * Initialize my status entry, following the protocol of bumping
-	 * st_changecount before and after; and make sure it's even afterwards. We
-	 * use a volatile pointer here to ensure the compiler doesn't try to get
-	 * cute.
-	 */
-	beentry = MyBEEntry;
-
-	/* pgstats state must be initialized from pgstat_initialize() */
-	Assert(beentry != NULL);
-
-	if (MyBackendId != InvalidBackendId)
-	{
-		if (IsAutoVacuumLauncherProcess())
-		{
-			/* Autovacuum Launcher */
-			beentry->st_backendType = B_AUTOVAC_LAUNCHER;
-		}
-		else if (IsAutoVacuumWorkerProcess())
-		{
-			/* Autovacuum Worker */
-			beentry->st_backendType = B_AUTOVAC_WORKER;
-		}
-		else if (am_walsender)
-		{
-			/* Wal sender */
-			beentry->st_backendType = B_WAL_SENDER;
-		}
-		else if (IsBackgroundWorker)
-		{
-			/* bgworker */
-			beentry->st_backendType = B_BG_WORKER;
-		}
-		else
-		{
-			/* client-backend */
-			beentry->st_backendType = B_BACKEND;
-		}
-	}
-	else
-	{
-		/* Must be an auxiliary process */
-		Assert(MyAuxProcType != NotAnAuxProcess);
-		switch (MyAuxProcType)
-		{
-			case StartupProcess:
-				beentry->st_backendType = B_STARTUP;
-				break;
-			case BgWriterProcess:
-				beentry->st_backendType = B_BG_WRITER;
-				break;
-			case ArchiverProcess:
-				beentry->st_backendType = B_ARCHIVER;
-				break;
-			case CheckpointerProcess:
-				beentry->st_backendType = B_CHECKPOINTER;
-				break;
-			case WalWriterProcess:
-				beentry->st_backendType = B_WAL_WRITER;
-				break;
-			case WalReceiverProcess:
-				beentry->st_backendType = B_WAL_RECEIVER;
-				break;
-			default:
-				elog(FATAL, "unrecognized process type: %d",
-					 (int) MyAuxProcType);
-				proc_exit(1);
-		}
-	}
-
-	do
-	{
-		pgstat_increment_changecount_before(beentry);
-	} while ((beentry->st_changecount & 1) == 0);
-
-	beentry->st_procpid = MyProcPid;
-	beentry->st_proc_start_timestamp = MyStartTimestamp;
-	beentry->st_activity_start_timestamp = 0;
-	beentry->st_state_start_timestamp = 0;
-	beentry->st_xact_start_timestamp = 0;
-	beentry->st_databaseid = MyDatabaseId;
-
-	/* We have userid for client-backends, wal-sender and bgworker processes */
-	if (beentry->st_backendType == B_BACKEND
-		|| beentry->st_backendType == B_WAL_SENDER
-		|| beentry->st_backendType == B_BG_WORKER)
-		beentry->st_userid = GetSessionUserId();
-	else
-		beentry->st_userid = InvalidOid;
-
-	beentry->st_clientaddr = clientaddr;
-	if (MyProcPort && MyProcPort->remote_hostname)
-		strlcpy(beentry->st_clienthostname, MyProcPort->remote_hostname,
-				NAMEDATALEN);
-	else
-		beentry->st_clienthostname[0] = '\0';
-#ifdef USE_SSL
-	if (MyProcPort && MyProcPort->ssl != NULL)
-	{
-		beentry->st_ssl = true;
-		beentry->st_sslstatus->ssl_bits = be_tls_get_cipher_bits(MyProcPort);
-		beentry->st_sslstatus->ssl_compression = be_tls_get_compression(MyProcPort);
-		strlcpy(beentry->st_sslstatus->ssl_version, be_tls_get_version(MyProcPort), NAMEDATALEN);
-		strlcpy(beentry->st_sslstatus->ssl_cipher, be_tls_get_cipher(MyProcPort), NAMEDATALEN);
-		be_tls_get_peerdn_name(MyProcPort, beentry->st_sslstatus->ssl_clientdn, NAMEDATALEN);
-	}
-	else
-	{
-		beentry->st_ssl = false;
-	}
-#else
-	beentry->st_ssl = false;
-#endif
-	beentry->st_state = STATE_UNDEFINED;
-	beentry->st_appname[0] = '\0';
-	beentry->st_activity_raw[0] = '\0';
-	/* Also make sure the last byte in each string area is always 0 */
-	beentry->st_clienthostname[NAMEDATALEN - 1] = '\0';
-	beentry->st_appname[NAMEDATALEN - 1] = '\0';
-	beentry->st_activity_raw[pgstat_track_activity_query_size - 1] = '\0';
-	beentry->st_progress_command = PROGRESS_COMMAND_INVALID;
-	beentry->st_progress_command_target = InvalidOid;
-
-	/*
-	 * we don't zero st_progress_param here to save cycles; nobody should
-	 * examine it until st_progress_command has been set to something other
-	 * than PROGRESS_COMMAND_INVALID
-	 */
-
-	pgstat_increment_changecount_after(beentry);
-
-	/* Update app name to current GUC setting */
-	if (application_name)
-		pgstat_report_appname(application_name);
-}
-
 /*
  * Shut down a single backend's statistics reporting at process exit.
  *
@@ -3078,8 +2637,6 @@ pgstat_bestart(void)
 static void
 pgstat_beshutdown_hook(int code, Datum arg)
 {
-	volatile PgBackendStatus *beentry = MyBEEntry;
-
 	/*
 	 * 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
@@ -3088,1188 +2645,9 @@ pgstat_beshutdown_hook(int code, Datum arg)
 	 */
 	if (OidIsValid(MyDatabaseId))
 		pgstat_update_stat(true);
-
-	/*
-	 * Clear my status entry, following the protocol of bumping st_changecount
-	 * before and after.  We use a volatile pointer here to ensure the
-	 * compiler doesn't try to get cute.
-	 */
-	pgstat_increment_changecount_before(beentry);
-
-	beentry->st_procpid = 0;	/* mark invalid */
-
-	pgstat_increment_changecount_after(beentry);
 }
 
 
-/* ----------
- * pgstat_report_activity() -
- *
- *	Called from tcop/postgres.c to report what the backend is actually doing
- *	(but note cmd_str can be NULL for certain cases).
- *
- * All updates of the status entry follow the protocol of bumping
- * st_changecount before and after.  We use a volatile pointer here to
- * ensure the compiler doesn't try to get cute.
- * ----------
- */
-void
-pgstat_report_activity(BackendState state, const char *cmd_str)
-{
-	volatile PgBackendStatus *beentry = MyBEEntry;
-	TimestampTz start_timestamp;
-	TimestampTz current_timestamp;
-	int			len = 0;
-
-	TRACE_POSTGRESQL_STATEMENT_STATUS(cmd_str);
-
-	if (!beentry)
-		return;
-
-	if (!pgstat_track_activities)
-	{
-		if (beentry->st_state != STATE_DISABLED)
-		{
-			volatile PGPROC *proc = MyProc;
-
-			/*
-			 * track_activities is disabled, but we last reported a
-			 * non-disabled state.  As our final update, change the state and
-			 * clear fields we will not be updating anymore.
-			 */
-			pgstat_increment_changecount_before(beentry);
-			beentry->st_state = STATE_DISABLED;
-			beentry->st_state_start_timestamp = 0;
-			beentry->st_activity_raw[0] = '\0';
-			beentry->st_activity_start_timestamp = 0;
-			/* st_xact_start_timestamp and wait_event_info are also disabled */
-			beentry->st_xact_start_timestamp = 0;
-			proc->wait_event_info = 0;
-			pgstat_increment_changecount_after(beentry);
-		}
-		return;
-	}
-
-	/*
-	 * To minimize the time spent modifying the entry, fetch all the needed
-	 * data first.
-	 */
-	start_timestamp = GetCurrentStatementStartTimestamp();
-	if (cmd_str != NULL)
-	{
-		/*
-		 * Compute length of to-be-stored string unaware of multi-byte
-		 * characters. For speed reasons that'll get corrected on read, rather
-		 * than computed every write.
-		 */
-		len = Min(strlen(cmd_str), pgstat_track_activity_query_size - 1);
-	}
-	current_timestamp = GetCurrentTimestamp();
-
-	/*
-	 * Now update the status entry
-	 */
-	pgstat_increment_changecount_before(beentry);
-
-	beentry->st_state = state;
-	beentry->st_state_start_timestamp = current_timestamp;
-
-	if (cmd_str != NULL)
-	{
-		memcpy((char *) beentry->st_activity_raw, cmd_str, len);
-		beentry->st_activity_raw[len] = '\0';
-		beentry->st_activity_start_timestamp = start_timestamp;
-	}
-
-	pgstat_increment_changecount_after(beentry);
-}
-
-/*-----------
- * pgstat_progress_start_command() -
- *
- * Set st_progress_command (and st_progress_command_target) in own backend
- * entry.  Also, zero-initialize st_progress_param array.
- *-----------
- */
-void
-pgstat_progress_start_command(ProgressCommandType cmdtype, Oid relid)
-{
-	volatile PgBackendStatus *beentry = MyBEEntry;
-
-	if (!beentry || !pgstat_track_activities)
-		return;
-
-	pgstat_increment_changecount_before(beentry);
-	beentry->st_progress_command = cmdtype;
-	beentry->st_progress_command_target = relid;
-	MemSet(&beentry->st_progress_param, 0, sizeof(beentry->st_progress_param));
-	pgstat_increment_changecount_after(beentry);
-}
-
-/*-----------
- * pgstat_progress_update_param() -
- *
- * Update index'th member in st_progress_param[] of own backend entry.
- *-----------
- */
-void
-pgstat_progress_update_param(int index, int64 val)
-{
-	volatile PgBackendStatus *beentry = MyBEEntry;
-
-	Assert(index >= 0 && index < PGSTAT_NUM_PROGRESS_PARAM);
-
-	if (!beentry || !pgstat_track_activities)
-		return;
-
-	pgstat_increment_changecount_before(beentry);
-	beentry->st_progress_param[index] = val;
-	pgstat_increment_changecount_after(beentry);
-}
-
-/*-----------
- * pgstat_progress_update_multi_param() -
- *
- * Update multiple members in st_progress_param[] of own backend entry.
- * This is atomic; readers won't see intermediate states.
- *-----------
- */
-void
-pgstat_progress_update_multi_param(int nparam, const int *index,
-								   const int64 *val)
-{
-	volatile PgBackendStatus *beentry = MyBEEntry;
-	int			i;
-
-	if (!beentry || !pgstat_track_activities || nparam == 0)
-		return;
-
-	pgstat_increment_changecount_before(beentry);
-
-	for (i = 0; i < nparam; ++i)
-	{
-		Assert(index[i] >= 0 && index[i] < PGSTAT_NUM_PROGRESS_PARAM);
-
-		beentry->st_progress_param[index[i]] = val[i];
-	}
-
-	pgstat_increment_changecount_after(beentry);
-}
-
-/*-----------
- * pgstat_progress_end_command() -
- *
- * Reset st_progress_command (and st_progress_command_target) in own backend
- * entry.  This signals the end of the command.
- *-----------
- */
-void
-pgstat_progress_end_command(void)
-{
-	volatile PgBackendStatus *beentry = MyBEEntry;
-
-	if (!beentry)
-		return;
-	if (!pgstat_track_activities
-		&& beentry->st_progress_command == PROGRESS_COMMAND_INVALID)
-		return;
-
-	pgstat_increment_changecount_before(beentry);
-	beentry->st_progress_command = PROGRESS_COMMAND_INVALID;
-	beentry->st_progress_command_target = InvalidOid;
-	pgstat_increment_changecount_after(beentry);
-}
-
-/* ----------
- * pgstat_report_appname() -
- *
- *	Called to update our application name.
- * ----------
- */
-void
-pgstat_report_appname(const char *appname)
-{
-	volatile PgBackendStatus *beentry = MyBEEntry;
-	int			len;
-
-	if (!beentry)
-		return;
-
-	/* This should be unnecessary if GUC did its job, but be safe */
-	len = pg_mbcliplen(appname, strlen(appname), NAMEDATALEN - 1);
-
-	/*
-	 * Update my status entry, following the protocol of bumping
-	 * st_changecount before and after.  We use a volatile pointer here to
-	 * ensure the compiler doesn't try to get cute.
-	 */
-	pgstat_increment_changecount_before(beentry);
-
-	memcpy((char *) beentry->st_appname, appname, len);
-	beentry->st_appname[len] = '\0';
-
-	pgstat_increment_changecount_after(beentry);
-}
-
-/*
- * Report current transaction start timestamp as the specified value.
- * Zero means there is no active transaction.
- */
-void
-pgstat_report_xact_timestamp(TimestampTz tstamp)
-{
-	volatile PgBackendStatus *beentry = MyBEEntry;
-
-	if (!pgstat_track_activities || !beentry)
-		return;
-
-	/*
-	 * Update my status entry, following the protocol of bumping
-	 * st_changecount before and after.  We use a volatile pointer here to
-	 * ensure the compiler doesn't try to get cute.
-	 */
-	pgstat_increment_changecount_before(beentry);
-	beentry->st_xact_start_timestamp = tstamp;
-	pgstat_increment_changecount_after(beentry);
-}
-
-/* ----------
- * pgstat_read_current_status() -
- *
- *	Copy the current contents of the PgBackendStatus array to local memory,
- *	if not already done in this transaction.
- * ----------
- */
-static void
-pgstat_read_current_status(void)
-{
-	volatile PgBackendStatus *beentry;
-	LocalPgBackendStatus *localtable;
-	LocalPgBackendStatus *localentry;
-	char	   *localappname,
-			   *localclienthostname,
-			   *localactivity;
-#ifdef USE_SSL
-	PgBackendSSLStatus *localsslstatus;
-#endif
-	int			i;
-
-	Assert(IsUnderPostmaster);
-
-	if (localBackendStatusTable)
-		return;					/* already done */
-
-	pgstat_setup_memcxt();
-
-	localtable = (LocalPgBackendStatus *)
-		MemoryContextAlloc(pgStatLocalContext,
-						   sizeof(LocalPgBackendStatus) * NumBackendStatSlots);
-	localappname = (char *)
-		MemoryContextAlloc(pgStatLocalContext,
-						   NAMEDATALEN * NumBackendStatSlots);
-	localclienthostname = (char *)
-		MemoryContextAlloc(pgStatLocalContext,
-						   NAMEDATALEN * NumBackendStatSlots);
-	localactivity = (char *)
-		MemoryContextAlloc(pgStatLocalContext,
-						   pgstat_track_activity_query_size * NumBackendStatSlots);
-#ifdef USE_SSL
-	localsslstatus = (PgBackendSSLStatus *)
-		MemoryContextAlloc(pgStatLocalContext,
-						   sizeof(PgBackendSSLStatus) * NumBackendStatSlots);
-#endif
-
-	localNumBackends = 0;
-
-	beentry = BackendStatusArray;
-	localentry = localtable;
-	for (i = 1; i <= NumBackendStatSlots; i++)
-	{
-		/*
-		 * Follow the protocol of retrying if st_changecount changes while we
-		 * copy the entry, or if it's odd.  (The check for odd is needed to
-		 * cover the case where we are able to completely copy the entry while
-		 * the source backend is between increment steps.)	We use a volatile
-		 * pointer here to ensure the compiler doesn't try to get cute.
-		 */
-		for (;;)
-		{
-			int			before_changecount;
-			int			after_changecount;
-
-			pgstat_save_changecount_before(beentry, before_changecount);
-
-			localentry->backendStatus.st_procpid = beentry->st_procpid;
-			if (localentry->backendStatus.st_procpid > 0)
-			{
-				memcpy(&localentry->backendStatus, (char *) beentry, sizeof(PgBackendStatus));
-
-				/*
-				 * strcpy is safe even if the string is modified concurrently,
-				 * because there's always a \0 at the end of the buffer.
-				 */
-				strcpy(localappname, (char *) beentry->st_appname);
-				localentry->backendStatus.st_appname = localappname;
-				strcpy(localclienthostname, (char *) beentry->st_clienthostname);
-				localentry->backendStatus.st_clienthostname = localclienthostname;
-				strcpy(localactivity, (char *) beentry->st_activity_raw);
-				localentry->backendStatus.st_activity_raw = localactivity;
-				localentry->backendStatus.st_ssl = beentry->st_ssl;
-#ifdef USE_SSL
-				if (beentry->st_ssl)
-				{
-					memcpy(localsslstatus, beentry->st_sslstatus, sizeof(PgBackendSSLStatus));
-					localentry->backendStatus.st_sslstatus = localsslstatus;
-				}
-#endif
-			}
-
-			pgstat_save_changecount_after(beentry, after_changecount);
-			if (before_changecount == after_changecount &&
-				(before_changecount & 1) == 0)
-				break;
-
-			/* Make sure we can break out of loop if stuck... */
-			CHECK_FOR_INTERRUPTS();
-		}
-
-		beentry++;
-		/* Only valid entries get included into the local array */
-		if (localentry->backendStatus.st_procpid > 0)
-		{
-			BackendIdGetTransactionIds(i,
-									   &localentry->backend_xid,
-									   &localentry->backend_xmin);
-
-			localentry++;
-			localappname += NAMEDATALEN;
-			localclienthostname += NAMEDATALEN;
-			localactivity += pgstat_track_activity_query_size;
-#ifdef USE_SSL
-			localsslstatus++;
-#endif
-			localNumBackends++;
-		}
-	}
-
-	/* Set the pointer only after completion of a valid table */
-	localBackendStatusTable = localtable;
-}
-
-/* ----------
- * pgstat_get_wait_event_type() -
- *
- *	Return a string representing the current wait event type, backend is
- *	waiting on.
- */
-const char *
-pgstat_get_wait_event_type(uint32 wait_event_info)
-{
-	uint32		classId;
-	const char *event_type;
-
-	/* report process as not waiting. */
-	if (wait_event_info == 0)
-		return NULL;
-
-	classId = wait_event_info & 0xFF000000;
-
-	switch (classId)
-	{
-		case PG_WAIT_LWLOCK:
-			event_type = "LWLock";
-			break;
-		case PG_WAIT_LOCK:
-			event_type = "Lock";
-			break;
-		case PG_WAIT_BUFFER_PIN:
-			event_type = "BufferPin";
-			break;
-		case PG_WAIT_ACTIVITY:
-			event_type = "Activity";
-			break;
-		case PG_WAIT_CLIENT:
-			event_type = "Client";
-			break;
-		case PG_WAIT_EXTENSION:
-			event_type = "Extension";
-			break;
-		case PG_WAIT_IPC:
-			event_type = "IPC";
-			break;
-		case PG_WAIT_TIMEOUT:
-			event_type = "Timeout";
-			break;
-		case PG_WAIT_IO:
-			event_type = "IO";
-			break;
-		default:
-			event_type = "???";
-			break;
-	}
-
-	return event_type;
-}
-
-/* ----------
- * pgstat_get_wait_event() -
- *
- *	Return a string representing the current wait event, backend is
- *	waiting on.
- */
-const char *
-pgstat_get_wait_event(uint32 wait_event_info)
-{
-	uint32		classId;
-	uint16		eventId;
-	const char *event_name;
-
-	/* report process as not waiting. */
-	if (wait_event_info == 0)
-		return NULL;
-
-	classId = wait_event_info & 0xFF000000;
-	eventId = wait_event_info & 0x0000FFFF;
-
-	switch (classId)
-	{
-		case PG_WAIT_LWLOCK:
-			event_name = GetLWLockIdentifier(classId, eventId);
-			break;
-		case PG_WAIT_LOCK:
-			event_name = GetLockNameFromTagType(eventId);
-			break;
-		case PG_WAIT_BUFFER_PIN:
-			event_name = "BufferPin";
-			break;
-		case PG_WAIT_ACTIVITY:
-			{
-				WaitEventActivity w = (WaitEventActivity) wait_event_info;
-
-				event_name = pgstat_get_wait_activity(w);
-				break;
-			}
-		case PG_WAIT_CLIENT:
-			{
-				WaitEventClient w = (WaitEventClient) wait_event_info;
-
-				event_name = pgstat_get_wait_client(w);
-				break;
-			}
-		case PG_WAIT_EXTENSION:
-			event_name = "Extension";
-			break;
-		case PG_WAIT_IPC:
-			{
-				WaitEventIPC w = (WaitEventIPC) wait_event_info;
-
-				event_name = pgstat_get_wait_ipc(w);
-				break;
-			}
-		case PG_WAIT_TIMEOUT:
-			{
-				WaitEventTimeout w = (WaitEventTimeout) wait_event_info;
-
-				event_name = pgstat_get_wait_timeout(w);
-				break;
-			}
-		case PG_WAIT_IO:
-			{
-				WaitEventIO w = (WaitEventIO) wait_event_info;
-
-				event_name = pgstat_get_wait_io(w);
-				break;
-			}
-		default:
-			event_name = "unknown wait event";
-			break;
-	}
-
-	return event_name;
-}
-
-/* ----------
- * pgstat_get_wait_activity() -
- *
- * Convert WaitEventActivity to string.
- * ----------
- */
-static const char *
-pgstat_get_wait_activity(WaitEventActivity w)
-{
-	const char *event_name = "unknown wait event";
-
-	switch (w)
-	{
-		case WAIT_EVENT_ARCHIVER_MAIN:
-			event_name = "ArchiverMain";
-			break;
-		case WAIT_EVENT_AUTOVACUUM_MAIN:
-			event_name = "AutoVacuumMain";
-			break;
-		case WAIT_EVENT_BGWRITER_HIBERNATE:
-			event_name = "BgWriterHibernate";
-			break;
-		case WAIT_EVENT_BGWRITER_MAIN:
-			event_name = "BgWriterMain";
-			break;
-		case WAIT_EVENT_CHECKPOINTER_MAIN:
-			event_name = "CheckpointerMain";
-			break;
-		case WAIT_EVENT_LOGICAL_APPLY_MAIN:
-			event_name = "LogicalApplyMain";
-			break;
-		case WAIT_EVENT_LOGICAL_LAUNCHER_MAIN:
-			event_name = "LogicalLauncherMain";
-			break;
-		case WAIT_EVENT_PGSTAT_MAIN:
-			event_name = "PgStatMain";
-			break;
-		case WAIT_EVENT_RECOVERY_WAL_ALL:
-			event_name = "RecoveryWalAll";
-			break;
-		case WAIT_EVENT_RECOVERY_WAL_STREAM:
-			event_name = "RecoveryWalStream";
-			break;
-		case WAIT_EVENT_SYSLOGGER_MAIN:
-			event_name = "SysLoggerMain";
-			break;
-		case WAIT_EVENT_WAL_RECEIVER_MAIN:
-			event_name = "WalReceiverMain";
-			break;
-		case WAIT_EVENT_WAL_SENDER_MAIN:
-			event_name = "WalSenderMain";
-			break;
-		case WAIT_EVENT_WAL_WRITER_MAIN:
-			event_name = "WalWriterMain";
-			break;
-			/* no default case, so that compiler will warn */
-	}
-
-	return event_name;
-}
-
-/* ----------
- * pgstat_get_wait_client() -
- *
- * Convert WaitEventClient to string.
- * ----------
- */
-static const char *
-pgstat_get_wait_client(WaitEventClient w)
-{
-	const char *event_name = "unknown wait event";
-
-	switch (w)
-	{
-		case WAIT_EVENT_CLIENT_READ:
-			event_name = "ClientRead";
-			break;
-		case WAIT_EVENT_CLIENT_WRITE:
-			event_name = "ClientWrite";
-			break;
-		case WAIT_EVENT_LIBPQWALRECEIVER_CONNECT:
-			event_name = "LibPQWalReceiverConnect";
-			break;
-		case WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE:
-			event_name = "LibPQWalReceiverReceive";
-			break;
-		case WAIT_EVENT_SSL_OPEN_SERVER:
-			event_name = "SSLOpenServer";
-			break;
-		case WAIT_EVENT_WAL_RECEIVER_WAIT_START:
-			event_name = "WalReceiverWaitStart";
-			break;
-		case WAIT_EVENT_WAL_SENDER_WAIT_WAL:
-			event_name = "WalSenderWaitForWAL";
-			break;
-		case WAIT_EVENT_WAL_SENDER_WRITE_DATA:
-			event_name = "WalSenderWriteData";
-			break;
-			/* no default case, so that compiler will warn */
-	}
-
-	return event_name;
-}
-
-/* ----------
- * pgstat_get_wait_ipc() -
- *
- * Convert WaitEventIPC to string.
- * ----------
- */
-static const char *
-pgstat_get_wait_ipc(WaitEventIPC w)
-{
-	const char *event_name = "unknown wait event";
-
-	switch (w)
-	{
-		case WAIT_EVENT_BGWORKER_SHUTDOWN:
-			event_name = "BgWorkerShutdown";
-			break;
-		case WAIT_EVENT_BGWORKER_STARTUP:
-			event_name = "BgWorkerStartup";
-			break;
-		case WAIT_EVENT_BTREE_PAGE:
-			event_name = "BtreePage";
-			break;
-		case WAIT_EVENT_CLOG_GROUP_UPDATE:
-			event_name = "ClogGroupUpdate";
-			break;
-		case WAIT_EVENT_EXECUTE_GATHER:
-			event_name = "ExecuteGather";
-			break;
-		case WAIT_EVENT_HASH_BATCH_ALLOCATING:
-			event_name = "Hash/Batch/Allocating";
-			break;
-		case WAIT_EVENT_HASH_BATCH_ELECTING:
-			event_name = "Hash/Batch/Electing";
-			break;
-		case WAIT_EVENT_HASH_BATCH_LOADING:
-			event_name = "Hash/Batch/Loading";
-			break;
-		case WAIT_EVENT_HASH_BUILD_ALLOCATING:
-			event_name = "Hash/Build/Allocating";
-			break;
-		case WAIT_EVENT_HASH_BUILD_ELECTING:
-			event_name = "Hash/Build/Electing";
-			break;
-		case WAIT_EVENT_HASH_BUILD_HASHING_INNER:
-			event_name = "Hash/Build/HashingInner";
-			break;
-		case WAIT_EVENT_HASH_BUILD_HASHING_OUTER:
-			event_name = "Hash/Build/HashingOuter";
-			break;
-		case WAIT_EVENT_HASH_GROW_BATCHES_ALLOCATING:
-			event_name = "Hash/GrowBatches/Allocating";
-			break;
-		case WAIT_EVENT_HASH_GROW_BATCHES_DECIDING:
-			event_name = "Hash/GrowBatches/Deciding";
-			break;
-		case WAIT_EVENT_HASH_GROW_BATCHES_ELECTING:
-			event_name = "Hash/GrowBatches/Electing";
-			break;
-		case WAIT_EVENT_HASH_GROW_BATCHES_FINISHING:
-			event_name = "Hash/GrowBatches/Finishing";
-			break;
-		case WAIT_EVENT_HASH_GROW_BATCHES_REPARTITIONING:
-			event_name = "Hash/GrowBatches/Repartitioning";
-			break;
-		case WAIT_EVENT_HASH_GROW_BUCKETS_ALLOCATING:
-			event_name = "Hash/GrowBuckets/Allocating";
-			break;
-		case WAIT_EVENT_HASH_GROW_BUCKETS_ELECTING:
-			event_name = "Hash/GrowBuckets/Electing";
-			break;
-		case WAIT_EVENT_HASH_GROW_BUCKETS_REINSERTING:
-			event_name = "Hash/GrowBuckets/Reinserting";
-			break;
-		case WAIT_EVENT_LOGICAL_SYNC_DATA:
-			event_name = "LogicalSyncData";
-			break;
-		case WAIT_EVENT_LOGICAL_SYNC_STATE_CHANGE:
-			event_name = "LogicalSyncStateChange";
-			break;
-		case WAIT_EVENT_MQ_INTERNAL:
-			event_name = "MessageQueueInternal";
-			break;
-		case WAIT_EVENT_MQ_PUT_MESSAGE:
-			event_name = "MessageQueuePutMessage";
-			break;
-		case WAIT_EVENT_MQ_RECEIVE:
-			event_name = "MessageQueueReceive";
-			break;
-		case WAIT_EVENT_MQ_SEND:
-			event_name = "MessageQueueSend";
-			break;
-		case WAIT_EVENT_PARALLEL_BITMAP_SCAN:
-			event_name = "ParallelBitmapScan";
-			break;
-		case WAIT_EVENT_PARALLEL_CREATE_INDEX_SCAN:
-			event_name = "ParallelCreateIndexScan";
-			break;
-		case WAIT_EVENT_PARALLEL_FINISH:
-			event_name = "ParallelFinish";
-			break;
-		case WAIT_EVENT_PROCARRAY_GROUP_UPDATE:
-			event_name = "ProcArrayGroupUpdate";
-			break;
-		case WAIT_EVENT_PROMOTE:
-			event_name = "Promote";
-			break;
-		case WAIT_EVENT_REPLICATION_ORIGIN_DROP:
-			event_name = "ReplicationOriginDrop";
-			break;
-		case WAIT_EVENT_REPLICATION_SLOT_DROP:
-			event_name = "ReplicationSlotDrop";
-			break;
-		case WAIT_EVENT_SAFE_SNAPSHOT:
-			event_name = "SafeSnapshot";
-			break;
-		case WAIT_EVENT_SYNC_REP:
-			event_name = "SyncRep";
-			break;
-			/* no default case, so that compiler will warn */
-	}
-
-	return event_name;
-}
-
-/* ----------
- * pgstat_get_wait_timeout() -
- *
- * Convert WaitEventTimeout to string.
- * ----------
- */
-static const char *
-pgstat_get_wait_timeout(WaitEventTimeout w)
-{
-	const char *event_name = "unknown wait event";
-
-	switch (w)
-	{
-		case WAIT_EVENT_BASE_BACKUP_THROTTLE:
-			event_name = "BaseBackupThrottle";
-			break;
-		case WAIT_EVENT_PG_SLEEP:
-			event_name = "PgSleep";
-			break;
-		case WAIT_EVENT_RECOVERY_APPLY_DELAY:
-			event_name = "RecoveryApplyDelay";
-			break;
-			/* no default case, so that compiler will warn */
-	}
-
-	return event_name;
-}
-
-/* ----------
- * pgstat_get_wait_io() -
- *
- * Convert WaitEventIO to string.
- * ----------
- */
-static const char *
-pgstat_get_wait_io(WaitEventIO w)
-{
-	const char *event_name = "unknown wait event";
-
-	switch (w)
-	{
-		case WAIT_EVENT_BUFFILE_READ:
-			event_name = "BufFileRead";
-			break;
-		case WAIT_EVENT_BUFFILE_WRITE:
-			event_name = "BufFileWrite";
-			break;
-		case WAIT_EVENT_CONTROL_FILE_READ:
-			event_name = "ControlFileRead";
-			break;
-		case WAIT_EVENT_CONTROL_FILE_SYNC:
-			event_name = "ControlFileSync";
-			break;
-		case WAIT_EVENT_CONTROL_FILE_SYNC_UPDATE:
-			event_name = "ControlFileSyncUpdate";
-			break;
-		case WAIT_EVENT_CONTROL_FILE_WRITE:
-			event_name = "ControlFileWrite";
-			break;
-		case WAIT_EVENT_CONTROL_FILE_WRITE_UPDATE:
-			event_name = "ControlFileWriteUpdate";
-			break;
-		case WAIT_EVENT_COPY_FILE_READ:
-			event_name = "CopyFileRead";
-			break;
-		case WAIT_EVENT_COPY_FILE_WRITE:
-			event_name = "CopyFileWrite";
-			break;
-		case WAIT_EVENT_DATA_FILE_EXTEND:
-			event_name = "DataFileExtend";
-			break;
-		case WAIT_EVENT_DATA_FILE_FLUSH:
-			event_name = "DataFileFlush";
-			break;
-		case WAIT_EVENT_DATA_FILE_IMMEDIATE_SYNC:
-			event_name = "DataFileImmediateSync";
-			break;
-		case WAIT_EVENT_DATA_FILE_PREFETCH:
-			event_name = "DataFilePrefetch";
-			break;
-		case WAIT_EVENT_DATA_FILE_READ:
-			event_name = "DataFileRead";
-			break;
-		case WAIT_EVENT_DATA_FILE_SYNC:
-			event_name = "DataFileSync";
-			break;
-		case WAIT_EVENT_DATA_FILE_TRUNCATE:
-			event_name = "DataFileTruncate";
-			break;
-		case WAIT_EVENT_DATA_FILE_WRITE:
-			event_name = "DataFileWrite";
-			break;
-		case WAIT_EVENT_DSM_FILL_ZERO_WRITE:
-			event_name = "DSMFillZeroWrite";
-			break;
-		case WAIT_EVENT_LOCK_FILE_ADDTODATADIR_READ:
-			event_name = "LockFileAddToDataDirRead";
-			break;
-		case WAIT_EVENT_LOCK_FILE_ADDTODATADIR_SYNC:
-			event_name = "LockFileAddToDataDirSync";
-			break;
-		case WAIT_EVENT_LOCK_FILE_ADDTODATADIR_WRITE:
-			event_name = "LockFileAddToDataDirWrite";
-			break;
-		case WAIT_EVENT_LOCK_FILE_CREATE_READ:
-			event_name = "LockFileCreateRead";
-			break;
-		case WAIT_EVENT_LOCK_FILE_CREATE_SYNC:
-			event_name = "LockFileCreateSync";
-			break;
-		case WAIT_EVENT_LOCK_FILE_CREATE_WRITE:
-			event_name = "LockFileCreateWRITE";
-			break;
-		case WAIT_EVENT_LOCK_FILE_RECHECKDATADIR_READ:
-			event_name = "LockFileReCheckDataDirRead";
-			break;
-		case WAIT_EVENT_LOGICAL_REWRITE_CHECKPOINT_SYNC:
-			event_name = "LogicalRewriteCheckpointSync";
-			break;
-		case WAIT_EVENT_LOGICAL_REWRITE_MAPPING_SYNC:
-			event_name = "LogicalRewriteMappingSync";
-			break;
-		case WAIT_EVENT_LOGICAL_REWRITE_MAPPING_WRITE:
-			event_name = "LogicalRewriteMappingWrite";
-			break;
-		case WAIT_EVENT_LOGICAL_REWRITE_SYNC:
-			event_name = "LogicalRewriteSync";
-			break;
-		case WAIT_EVENT_LOGICAL_REWRITE_TRUNCATE:
-			event_name = "LogicalRewriteTruncate";
-			break;
-		case WAIT_EVENT_LOGICAL_REWRITE_WRITE:
-			event_name = "LogicalRewriteWrite";
-			break;
-		case WAIT_EVENT_RELATION_MAP_READ:
-			event_name = "RelationMapRead";
-			break;
-		case WAIT_EVENT_RELATION_MAP_SYNC:
-			event_name = "RelationMapSync";
-			break;
-		case WAIT_EVENT_RELATION_MAP_WRITE:
-			event_name = "RelationMapWrite";
-			break;
-		case WAIT_EVENT_REORDER_BUFFER_READ:
-			event_name = "ReorderBufferRead";
-			break;
-		case WAIT_EVENT_REORDER_BUFFER_WRITE:
-			event_name = "ReorderBufferWrite";
-			break;
-		case WAIT_EVENT_REORDER_LOGICAL_MAPPING_READ:
-			event_name = "ReorderLogicalMappingRead";
-			break;
-		case WAIT_EVENT_REPLICATION_SLOT_READ:
-			event_name = "ReplicationSlotRead";
-			break;
-		case WAIT_EVENT_REPLICATION_SLOT_RESTORE_SYNC:
-			event_name = "ReplicationSlotRestoreSync";
-			break;
-		case WAIT_EVENT_REPLICATION_SLOT_SYNC:
-			event_name = "ReplicationSlotSync";
-			break;
-		case WAIT_EVENT_REPLICATION_SLOT_WRITE:
-			event_name = "ReplicationSlotWrite";
-			break;
-		case WAIT_EVENT_SLRU_FLUSH_SYNC:
-			event_name = "SLRUFlushSync";
-			break;
-		case WAIT_EVENT_SLRU_READ:
-			event_name = "SLRURead";
-			break;
-		case WAIT_EVENT_SLRU_SYNC:
-			event_name = "SLRUSync";
-			break;
-		case WAIT_EVENT_SLRU_WRITE:
-			event_name = "SLRUWrite";
-			break;
-		case WAIT_EVENT_SNAPBUILD_READ:
-			event_name = "SnapbuildRead";
-			break;
-		case WAIT_EVENT_SNAPBUILD_SYNC:
-			event_name = "SnapbuildSync";
-			break;
-		case WAIT_EVENT_SNAPBUILD_WRITE:
-			event_name = "SnapbuildWrite";
-			break;
-		case WAIT_EVENT_TIMELINE_HISTORY_FILE_SYNC:
-			event_name = "TimelineHistoryFileSync";
-			break;
-		case WAIT_EVENT_TIMELINE_HISTORY_FILE_WRITE:
-			event_name = "TimelineHistoryFileWrite";
-			break;
-		case WAIT_EVENT_TIMELINE_HISTORY_READ:
-			event_name = "TimelineHistoryRead";
-			break;
-		case WAIT_EVENT_TIMELINE_HISTORY_SYNC:
-			event_name = "TimelineHistorySync";
-			break;
-		case WAIT_EVENT_TIMELINE_HISTORY_WRITE:
-			event_name = "TimelineHistoryWrite";
-			break;
-		case WAIT_EVENT_TWOPHASE_FILE_READ:
-			event_name = "TwophaseFileRead";
-			break;
-		case WAIT_EVENT_TWOPHASE_FILE_SYNC:
-			event_name = "TwophaseFileSync";
-			break;
-		case WAIT_EVENT_TWOPHASE_FILE_WRITE:
-			event_name = "TwophaseFileWrite";
-			break;
-		case WAIT_EVENT_WALSENDER_TIMELINE_HISTORY_READ:
-			event_name = "WALSenderTimelineHistoryRead";
-			break;
-		case WAIT_EVENT_WAL_BOOTSTRAP_SYNC:
-			event_name = "WALBootstrapSync";
-			break;
-		case WAIT_EVENT_WAL_BOOTSTRAP_WRITE:
-			event_name = "WALBootstrapWrite";
-			break;
-		case WAIT_EVENT_WAL_COPY_READ:
-			event_name = "WALCopyRead";
-			break;
-		case WAIT_EVENT_WAL_COPY_SYNC:
-			event_name = "WALCopySync";
-			break;
-		case WAIT_EVENT_WAL_COPY_WRITE:
-			event_name = "WALCopyWrite";
-			break;
-		case WAIT_EVENT_WAL_INIT_SYNC:
-			event_name = "WALInitSync";
-			break;
-		case WAIT_EVENT_WAL_INIT_WRITE:
-			event_name = "WALInitWrite";
-			break;
-		case WAIT_EVENT_WAL_READ:
-			event_name = "WALRead";
-			break;
-		case WAIT_EVENT_WAL_SYNC:
-			event_name = "WALSync";
-			break;
-		case WAIT_EVENT_WAL_SYNC_METHOD_ASSIGN:
-			event_name = "WALSyncMethodAssign";
-			break;
-		case WAIT_EVENT_WAL_WRITE:
-			event_name = "WALWrite";
-			break;
-
-			/* no default case, so that compiler will warn */
-	}
-
-	return event_name;
-}
-
-
-/* ----------
- * pgstat_get_backend_current_activity() -
- *
- *	Return a string representing the current activity of the backend with
- *	the specified PID.  This looks directly at the BackendStatusArray,
- *	and so will provide current information regardless of the age of our
- *	transaction's snapshot of the status array.
- *
- *	It is the caller's responsibility to invoke this only for backends whose
- *	state is expected to remain stable while the result is in use.  The
- *	only current use is in deadlock reporting, where we can expect that
- *	the target backend is blocked on a lock.  (There are corner cases
- *	where the target's wait could get aborted while we are looking at it,
- *	but the very worst consequence is to return a pointer to a string
- *	that's been changed, so we won't worry too much.)
- *
- *	Note: return strings for special cases match pg_stat_get_backend_activity.
- * ----------
- */
-const char *
-pgstat_get_backend_current_activity(int pid, bool checkUser)
-{
-	PgBackendStatus *beentry;
-	int			i;
-
-	beentry = BackendStatusArray;
-	for (i = 1; i <= MaxBackends; i++)
-	{
-		/*
-		 * Although we expect the target backend's entry to be stable, that
-		 * doesn't imply that anyone else's is.  To avoid identifying the
-		 * wrong backend, while we check for a match to the desired PID we
-		 * must follow the protocol of retrying if st_changecount changes
-		 * while we examine the entry, or if it's odd.  (This might be
-		 * unnecessary, since fetching or storing an int is almost certainly
-		 * atomic, but let's play it safe.)  We use a volatile pointer here to
-		 * ensure the compiler doesn't try to get cute.
-		 */
-		volatile PgBackendStatus *vbeentry = beentry;
-		bool		found;
-
-		for (;;)
-		{
-			int			before_changecount;
-			int			after_changecount;
-
-			pgstat_save_changecount_before(vbeentry, before_changecount);
-
-			found = (vbeentry->st_procpid == pid);
-
-			pgstat_save_changecount_after(vbeentry, after_changecount);
-
-			if (before_changecount == after_changecount &&
-				(before_changecount & 1) == 0)
-				break;
-
-			/* Make sure we can break out of loop if stuck... */
-			CHECK_FOR_INTERRUPTS();
-		}
-
-		if (found)
-		{
-			/* Now it is safe to use the non-volatile pointer */
-			if (checkUser && !superuser() && beentry->st_userid != GetUserId())
-				return "<insufficient privilege>";
-			else if (*(beentry->st_activity_raw) == '\0')
-				return "<command string not enabled>";
-			else
-			{
-				/* this'll leak a bit of memory, but that seems acceptable */
-				return pgstat_clip_activity(beentry->st_activity_raw);
-			}
-		}
-
-		beentry++;
-	}
-
-	/* If we get here, caller is in error ... */
-	return "<backend information not available>";
-}
-
-/* ----------
- * pgstat_get_crashed_backend_activity() -
- *
- *	Return a string representing the current activity of the backend with
- *	the specified PID.  Like the function above, but reads shared memory with
- *	the expectation that it may be corrupt.  On success, copy the string
- *	into the "buffer" argument and return that pointer.  On failure,
- *	return NULL.
- *
- *	This function is only intended to be used by the postmaster to report the
- *	query that crashed a backend.  In particular, no attempt is made to
- *	follow the correct concurrency protocol when accessing the
- *	BackendStatusArray.  But that's OK, in the worst case we'll return a
- *	corrupted message.  We also must take care not to trip on ereport(ERROR).
- * ----------
- */
-const char *
-pgstat_get_crashed_backend_activity(int pid, char *buffer, int buflen)
-{
-	volatile PgBackendStatus *beentry;
-	int			i;
-
-	beentry = BackendStatusArray;
-
-	/*
-	 * We probably shouldn't get here before shared memory has been set up,
-	 * but be safe.
-	 */
-	if (beentry == NULL || BackendActivityBuffer == NULL)
-		return NULL;
-
-	for (i = 1; i <= MaxBackends; i++)
-	{
-		if (beentry->st_procpid == pid)
-		{
-			/* Read pointer just once, so it can't change after validation */
-			const char *activity = beentry->st_activity_raw;
-			const char *activity_last;
-
-			/*
-			 * We mustn't access activity string before we verify that it
-			 * falls within the BackendActivityBuffer. To make sure that the
-			 * entire string including its ending is contained within the
-			 * buffer, subtract one activity length from the buffer size.
-			 */
-			activity_last = BackendActivityBuffer + BackendActivityBufferSize
-				- pgstat_track_activity_query_size;
-
-			if (activity < BackendActivityBuffer ||
-				activity > activity_last)
-				return NULL;
-
-			/* If no string available, no point in a report */
-			if (activity[0] == '\0')
-				return NULL;
-
-			/*
-			 * Copy only ASCII-safe characters so we don't run into encoding
-			 * problems when reporting the message; and be sure not to run off
-			 * the end of memory.  As only ASCII characters are reported, it
-			 * doesn't seem necessary to perform multibyte aware clipping.
-			 */
-			ascii_safe_strlcpy(buffer, activity,
-							   Min(buflen, pgstat_track_activity_query_size));
-
-			return buffer;
-		}
-
-		beentry++;
-	}
-
-	/* PID not found */
-	return NULL;
-}
-
-const char *
-pgstat_get_backend_desc(BackendType backendType)
-{
-	const char *backendDesc = "unknown process type";
-
-	switch (backendType)
-	{
-		case B_AUTOVAC_LAUNCHER:
-			backendDesc = "autovacuum launcher";
-			break;
-		case B_AUTOVAC_WORKER:
-			backendDesc = "autovacuum worker";
-			break;
-		case B_BACKEND:
-			backendDesc = "client backend";
-			break;
-		case B_BG_WORKER:
-			backendDesc = "background worker";
-			break;
-		case B_BG_WRITER:
-			backendDesc = "background writer";
-			break;
-		case B_ARCHIVER:
-			backendDesc = "archiver";
-			break;
-		case B_CHECKPOINTER:
-			backendDesc = "checkpointer";
-			break;
-		case B_STARTUP:
-			backendDesc = "startup";
-			break;
-		case B_WAL_RECEIVER:
-			backendDesc = "walreceiver";
-			break;
-		case B_WAL_SENDER:
-			backendDesc = "walsender";
-			break;
-		case B_WAL_WRITER:
-			backendDesc = "walwriter";
-			break;
-	}
-
-	return backendDesc;
-}
-
 /* ------------------------------------------------------------
  * Local support functions follow
  * ------------------------------------------------------------
@@ -5412,22 +3790,6 @@ backend_get_func_etnry(PgStat_StatDBEntry *dbent, Oid funcid, bool oneshot)
 							  funcid);
 }
 
-/* ----------
- * 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);
-}
-
-
 /* ----------
  * pgstat_clear_snapshot() -
  *
@@ -5443,6 +3805,8 @@ pgstat_clear_snapshot(void)
 {
 	int param = 0;	/* only the address is significant */
 
+	pgstat_bestatus_clear_snapshot();
+
 	/* Release memory, if any was allocated */
 	if (pgStatLocalContext)
 		MemoryContextDelete(pgStatLocalContext);
@@ -5450,8 +3814,6 @@ pgstat_clear_snapshot(void)
 	/* Reset variables */
 	pgStatLocalContext = NULL;
 	pgStatDBHash = NULL;
-	localBackendStatusTable = NULL;
-	localNumBackends = 0;
 
 	/*
 	 * the parameter inform the function that it is not called from
@@ -5557,47 +3919,18 @@ pgstat_update_dbentry(PgStat_StatDBEntry *dbentry, PgStat_TableStatus *stat)
 	dbentry->n_blocks_hit += stat->t_counts.t_blocks_hit;
 }
 
-
-/*
- * Convert a potentially unsafely truncated activity string (see
- * PgBackendStatus.st_activity_raw's documentation) into a correctly truncated
- * one.
+/* ----------
+ * pgstat_setup_memcxt() -
  *
- * The returned string is allocated in the caller's memory context and may be
- * freed.
+ *	Create pgStatLocalContext, if not already done.
+ * ----------
  */
-char *
-pgstat_clip_activity(const char *raw_activity)
+static void
+pgstat_setup_memcxt(void)
 {
-	char	   *activity;
-	int			rawlen;
-	int			cliplen;
-
-	/*
-	 * Some callers, like pgstat_get_backend_current_activity(), do not
-	 * guarantee that the buffer isn't concurrently modified. We try to take
-	 * care that the buffer is always terminated by a NUL byte regardless, but
-	 * let's still be paranoid about the string's length. In those cases the
-	 * underlying buffer is guaranteed to be pgstat_track_activity_query_size
-	 * large.
-	 */
-	activity = pnstrdup(raw_activity, pgstat_track_activity_query_size - 1);
-
-	/* now double-guaranteed to be NUL terminated */
-	rawlen = strlen(activity);
-
-	/*
-	 * All supported server-encodings make it possible to determine the length
-	 * of a multi-byte character from its first byte (this is not the case for
-	 * client encodings, see GB18030). As st_activity is always stored using
-	 * server encoding, this allows us to perform multi-byte aware truncation,
-	 * even if the string earlier was truncated in the middle of a multi-byte
-	 * character.
-	 */
-	cliplen = pg_mbcliplen(activity, rawlen,
-						   pgstat_track_activity_query_size - 1);
-
-	activity[cliplen] = '\0';
-
-	return activity;
+	if (!pgStatLocalContext)
+		pgStatLocalContext = AllocSetContextCreate(TopMemoryContext,
+												   "Statistics snapshot",
+												   ALLOCSET_SMALL_SIZES);
 }
+
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index e794a81c4c..d92c7c935d 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -34,6 +34,7 @@
 #include <unistd.h>
 
 #include "access/xlog.h"
+#include "bestatus.h"
 #include "catalog/catalog.h"
 #include "catalog/storage.h"
 #include "executor/instrument.h"
diff --git a/src/backend/storage/file/buffile.c b/src/backend/storage/file/buffile.c
index dd687dfe71..34ef69d8d0 100644
--- a/src/backend/storage/file/buffile.c
+++ b/src/backend/storage/file/buffile.c
@@ -41,9 +41,9 @@
 
 #include "postgres.h"
 
+#include "bestatus.h"
 #include "executor/instrument.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "storage/fd.h"
 #include "storage/buffile.h"
 #include "storage/buf_internals.h"
diff --git a/src/backend/storage/file/copydir.c b/src/backend/storage/file/copydir.c
index 4a0d23b11e..4054ac5108 100644
--- a/src/backend/storage/file/copydir.c
+++ b/src/backend/storage/file/copydir.c
@@ -22,10 +22,10 @@
 #include <unistd.h>
 #include <sys/stat.h>
 
+#include "bestatus.h"
 #include "storage/copydir.h"
 #include "storage/fd.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 
 /*
  * copydir: copy a directory
diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index 2d75773ef0..4342fb3e39 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -82,6 +82,7 @@
 #include "miscadmin.h"
 #include "access/xact.h"
 #include "access/xlog.h"
+#include "bestatus.h"
 #include "catalog/pg_tablespace.h"
 #include "common/file_perm.h"
 #include "pgstat.h"
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index 0ff1f5be91..a3465f57ae 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -61,8 +61,8 @@
 #ifdef HAVE_SYS_SHM_H
 #include <sys/shm.h>
 #endif
+#include "bestatus.h"
 #include "common/file_perm.h"
-#include "pgstat.h"
 
 #include "portability/mem.h"
 #include "storage/dsm_impl.h"
diff --git a/src/backend/storage/ipc/latch.c b/src/backend/storage/ipc/latch.c
index c129446f9c..51c6fff11c 100644
--- a/src/backend/storage/ipc/latch.c
+++ b/src/backend/storage/ipc/latch.c
@@ -43,8 +43,8 @@
 #include <poll.h>
 #endif
 
+#include "bestatus.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "port/atomics.h"
 #include "portability/instr_time.h"
 #include "postmaster/postmaster.h"
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index dc7e875680..293d15661a 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -51,9 +51,9 @@
 #include "access/twophase.h"
 #include "access/xact.h"
 #include "access/xlog.h"
+#include "bestatus.h"
 #include "catalog/catalog.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "storage/proc.h"
 #include "storage/procarray.h"
 #include "storage/spin.h"
diff --git a/src/backend/storage/ipc/shm_mq.c b/src/backend/storage/ipc/shm_mq.c
index fde71afd47..a0a5582aac 100644
--- a/src/backend/storage/ipc/shm_mq.c
+++ b/src/backend/storage/ipc/shm_mq.c
@@ -18,8 +18,8 @@
 
 #include "postgres.h"
 
+#include "bestatus.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "postmaster/bgworker.h"
 #include "storage/procsignal.h"
 #include "storage/shm_mq.h"
diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c
index c9bb3e987d..0a9181cd9d 100644
--- a/src/backend/storage/ipc/standby.c
+++ b/src/backend/storage/ipc/standby.c
@@ -21,8 +21,8 @@
 #include "access/xact.h"
 #include "access/xlog.h"
 #include "access/xloginsert.h"
+#include "bestatus.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "storage/bufmgr.h"
 #include "storage/lmgr.h"
 #include "storage/proc.h"
diff --git a/src/backend/storage/lmgr/deadlock.c b/src/backend/storage/lmgr/deadlock.c
index aeaf1f3ab4..22a42b9977 100644
--- a/src/backend/storage/lmgr/deadlock.c
+++ b/src/backend/storage/lmgr/deadlock.c
@@ -25,6 +25,7 @@
  */
 #include "postgres.h"
 
+#include "bestatus.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
 #include "pgstat.h"
diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index c46bb8d057..8ddb4c88e0 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -76,8 +76,8 @@
  */
 #include "postgres.h"
 
+#include "bestatus.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "pg_trace.h"
 #include "postmaster/postmaster.h"
 #include "replication/slot.h"
diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c
index e8390311d0..ac352885f3 100644
--- a/src/backend/storage/lmgr/predicate.c
+++ b/src/backend/storage/lmgr/predicate.c
@@ -193,8 +193,8 @@
 #include "access/twophase_rmgr.h"
 #include "access/xact.h"
 #include "access/xlog.h"
+#include "bestatus.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "storage/bufmgr.h"
 #include "storage/predicate.h"
 #include "storage/predicate_internals.h"
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 6f9aaa52fa..0ecaa24b1a 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -38,8 +38,8 @@
 #include "access/transam.h"
 #include "access/twophase.h"
 #include "access/xact.h"
+#include "bestatus.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "postmaster/autovacuum.h"
 #include "replication/slot.h"
 #include "replication/syncrep.h"
diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c
index 86013a5c8b..92b3cd8b55 100644
--- a/src/backend/storage/smgr/md.c
+++ b/src/backend/storage/smgr/md.c
@@ -28,7 +28,7 @@
 #include "miscadmin.h"
 #include "access/xlogutils.h"
 #include "access/xlog.h"
-#include "pgstat.h"
+#include "bestatus.h"
 #include "portability/instr_time.h"
 #include "postmaster/bgwriter.h"
 #include "storage/fd.h"
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index ee4e43331b..f894bac680 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -39,6 +39,7 @@
 #include "access/parallel.h"
 #include "access/printtup.h"
 #include "access/xact.h"
+#include "bestatus.h"
 #include "catalog/pg_type.h"
 #include "commands/async.h"
 #include "commands/prepare.h"
diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c
index 309eb2935c..b229f42622 100644
--- a/src/backend/utils/adt/misc.c
+++ b/src/backend/utils/adt/misc.c
@@ -20,6 +20,7 @@
 #include <unistd.h>
 
 #include "access/sysattr.h"
+#include "bestatus.h"
 #include "catalog/catalog.h"
 #include "catalog/pg_tablespace.h"
 #include "catalog/pg_type.h"
@@ -28,7 +29,6 @@
 #include "common/keywords.h"
 #include "funcapi.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "parser/scansup.h"
 #include "postmaster/syslogger.h"
 #include "rewrite/rewriteHandler.h"
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index eca801eeed..29da24b91d 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -15,6 +15,7 @@
 #include "postgres.h"
 
 #include "access/htup_details.h"
+#include "bestatus.h"
 #include "catalog/pg_authid.h"
 #include "catalog/pg_type.h"
 #include "common/ip.h"
diff --git a/src/backend/utils/cache/relmapper.c b/src/backend/utils/cache/relmapper.c
index 905867dc76..29df1e9773 100644
--- a/src/backend/utils/cache/relmapper.c
+++ b/src/backend/utils/cache/relmapper.c
@@ -46,11 +46,11 @@
 #include "access/xact.h"
 #include "access/xlog.h"
 #include "access/xloginsert.h"
+#include "bestatus.h"
 #include "catalog/catalog.h"
 #include "catalog/pg_tablespace.h"
 #include "catalog/storage.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "storage/fd.h"
 #include "storage/lwlock.h"
 #include "utils/inval.h"
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 238fe1deec..1a25c813f2 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -31,12 +31,12 @@
 #endif
 
 #include "access/htup_details.h"
+#include "bestatus.h"
 #include "catalog/pg_authid.h"
 #include "common/file_perm.h"
 #include "libpq/libpq.h"
 #include "mb/pg_wchar.h"
 #include "miscadmin.h"
-#include "pgstat.h"
 #include "postmaster/autovacuum.h"
 #include "postmaster/postmaster.h"
 #include "storage/fd.h"
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 1e4fa89135..d4774d717f 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -25,6 +25,7 @@
 #include "access/sysattr.h"
 #include "access/xact.h"
 #include "access/xlog.h"
+#include "bestatus.h"
 #include "catalog/catalog.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
@@ -688,7 +689,10 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
 
 	/* Initialize stats collection --- must happen before first xact */
 	if (!bootstrap)
+	{
+		pgstat_bearray_initialize();
 		pgstat_initialize();
+	}
 
 	/*
 	 * Load relcache entries for the shared system catalogs.  This must create
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index cfdffbca2b..45974082b9 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -33,6 +33,7 @@
 #include "access/twophase.h"
 #include "access/xact.h"
 #include "access/xlog_internal.h"
+#include "bestatus.h"
 #include "catalog/namespace.h"
 #include "catalog/pg_authid.h"
 #include "commands/async.h"
diff --git a/src/include/bestatus.h b/src/include/bestatus.h
new file mode 100644
index 0000000000..3b47e9c063
--- /dev/null
+++ b/src/include/bestatus.h
@@ -0,0 +1,544 @@
+/* ----------
+ *	bestatus.h
+ *
+ *	Definitions for the PostgreSQL backend status monitor facility
+ *
+ *	Copyright (c) 2001-2018, PostgreSQL Global Development Group
+ *
+ *	src/include/bestatus.h
+ * ----------
+ */
+#ifndef BESTATUS_H
+#define BESTATUS_H
+
+#include "datatype/timestamp.h"
+#include "libpq/pqcomm.h"
+#include "storage/proc.h"
+
+/* ----------
+ * Backend types
+ * ----------
+ */
+typedef enum BackendType
+{
+	B_AUTOVAC_LAUNCHER,
+	B_AUTOVAC_WORKER,
+	B_BACKEND,
+	B_BG_WORKER,
+	B_BG_WRITER,
+	B_CHECKPOINTER,
+	B_STARTUP,
+	B_WAL_RECEIVER,
+	B_WAL_SENDER,
+	B_WAL_WRITER,
+	B_ARCHIVER
+} BackendType;
+
+
+/* ----------
+ * Backend states
+ * ----------
+ */
+typedef enum BackendState
+{
+	STATE_UNDEFINED,
+	STATE_IDLE,
+	STATE_RUNNING,
+	STATE_IDLEINTRANSACTION,
+	STATE_FASTPATH,
+	STATE_IDLEINTRANSACTION_ABORTED,
+	STATE_DISABLED
+} BackendState;
+
+
+/* ----------
+ * Wait Classes
+ * ----------
+ */
+#define PG_WAIT_LWLOCK				0x01000000U
+#define PG_WAIT_LOCK				0x03000000U
+#define PG_WAIT_BUFFER_PIN			0x04000000U
+#define PG_WAIT_ACTIVITY			0x05000000U
+#define PG_WAIT_CLIENT				0x06000000U
+#define PG_WAIT_EXTENSION			0x07000000U
+#define PG_WAIT_IPC					0x08000000U
+#define PG_WAIT_TIMEOUT				0x09000000U
+#define PG_WAIT_IO					0x0A000000U
+
+/* ----------
+ * Wait Events - Activity
+ *
+ * Use this category when a process is waiting because it has no work to do,
+ * unless the "Client" or "Timeout" category describes the situation better.
+ * Typically, this should only be used for background processes.
+ * ----------
+ */
+typedef enum
+{
+	WAIT_EVENT_ARCHIVER_MAIN = PG_WAIT_ACTIVITY,
+	WAIT_EVENT_AUTOVACUUM_MAIN,
+	WAIT_EVENT_BGWRITER_HIBERNATE,
+	WAIT_EVENT_BGWRITER_MAIN,
+	WAIT_EVENT_CHECKPOINTER_MAIN,
+	WAIT_EVENT_LOGICAL_APPLY_MAIN,
+	WAIT_EVENT_LOGICAL_LAUNCHER_MAIN,
+	WAIT_EVENT_RECOVERY_WAL_ALL,
+	WAIT_EVENT_RECOVERY_WAL_STREAM,
+	WAIT_EVENT_SYSLOGGER_MAIN,
+	WAIT_EVENT_WAL_RECEIVER_MAIN,
+	WAIT_EVENT_WAL_SENDER_MAIN,
+	WAIT_EVENT_WAL_WRITER_MAIN
+} WaitEventActivity;
+
+/* ----------
+ * Wait Events - Client
+ *
+ * Use this category when a process is waiting to send data to or receive data
+ * from the frontend process to which it is connected.  This is never used for
+ * a background process, which has no client connection.
+ * ----------
+ */
+typedef enum
+{
+	WAIT_EVENT_CLIENT_READ = PG_WAIT_CLIENT,
+	WAIT_EVENT_CLIENT_WRITE,
+	WAIT_EVENT_LIBPQWALRECEIVER_CONNECT,
+	WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE,
+	WAIT_EVENT_SSL_OPEN_SERVER,
+	WAIT_EVENT_WAL_RECEIVER_WAIT_START,
+	WAIT_EVENT_WAL_SENDER_WAIT_WAL,
+	WAIT_EVENT_WAL_SENDER_WRITE_DATA
+} WaitEventClient;
+
+/* ----------
+ * Wait Events - IPC
+ *
+ * Use this category when a process cannot complete the work it is doing because
+ * it is waiting for a notification from another process.
+ * ----------
+ */
+typedef enum
+{
+	WAIT_EVENT_BGWORKER_SHUTDOWN = PG_WAIT_IPC,
+	WAIT_EVENT_BGWORKER_STARTUP,
+	WAIT_EVENT_BTREE_PAGE,
+	WAIT_EVENT_CLOG_GROUP_UPDATE,
+	WAIT_EVENT_EXECUTE_GATHER,
+	WAIT_EVENT_HASH_BATCH_ALLOCATING,
+	WAIT_EVENT_HASH_BATCH_ELECTING,
+	WAIT_EVENT_HASH_BATCH_LOADING,
+	WAIT_EVENT_HASH_BUILD_ALLOCATING,
+	WAIT_EVENT_HASH_BUILD_ELECTING,
+	WAIT_EVENT_HASH_BUILD_HASHING_INNER,
+	WAIT_EVENT_HASH_BUILD_HASHING_OUTER,
+	WAIT_EVENT_HASH_GROW_BATCHES_ALLOCATING,
+	WAIT_EVENT_HASH_GROW_BATCHES_DECIDING,
+	WAIT_EVENT_HASH_GROW_BATCHES_ELECTING,
+	WAIT_EVENT_HASH_GROW_BATCHES_FINISHING,
+	WAIT_EVENT_HASH_GROW_BATCHES_REPARTITIONING,
+	WAIT_EVENT_HASH_GROW_BUCKETS_ALLOCATING,
+	WAIT_EVENT_HASH_GROW_BUCKETS_ELECTING,
+	WAIT_EVENT_HASH_GROW_BUCKETS_REINSERTING,
+	WAIT_EVENT_LOGICAL_SYNC_DATA,
+	WAIT_EVENT_LOGICAL_SYNC_STATE_CHANGE,
+	WAIT_EVENT_MQ_INTERNAL,
+	WAIT_EVENT_MQ_PUT_MESSAGE,
+	WAIT_EVENT_MQ_RECEIVE,
+	WAIT_EVENT_MQ_SEND,
+	WAIT_EVENT_PARALLEL_BITMAP_SCAN,
+	WAIT_EVENT_PARALLEL_CREATE_INDEX_SCAN,
+	WAIT_EVENT_PARALLEL_FINISH,
+	WAIT_EVENT_PROCARRAY_GROUP_UPDATE,
+	WAIT_EVENT_PROMOTE,
+	WAIT_EVENT_REPLICATION_ORIGIN_DROP,
+	WAIT_EVENT_REPLICATION_SLOT_DROP,
+	WAIT_EVENT_SAFE_SNAPSHOT,
+	WAIT_EVENT_SYNC_REP
+} WaitEventIPC;
+
+/* ----------
+ * Wait Events - Timeout
+ *
+ * Use this category when a process is waiting for a timeout to expire.
+ * ----------
+ */
+typedef enum
+{
+	WAIT_EVENT_BASE_BACKUP_THROTTLE = PG_WAIT_TIMEOUT,
+	WAIT_EVENT_PG_SLEEP,
+	WAIT_EVENT_RECOVERY_APPLY_DELAY
+} WaitEventTimeout;
+
+/* ----------
+ * Wait Events - IO
+ *
+ * Use this category when a process is waiting for a IO.
+ * ----------
+ */
+typedef enum
+{
+	WAIT_EVENT_BUFFILE_READ = PG_WAIT_IO,
+	WAIT_EVENT_BUFFILE_WRITE,
+	WAIT_EVENT_CONTROL_FILE_READ,
+	WAIT_EVENT_CONTROL_FILE_SYNC,
+	WAIT_EVENT_CONTROL_FILE_SYNC_UPDATE,
+	WAIT_EVENT_CONTROL_FILE_WRITE,
+	WAIT_EVENT_CONTROL_FILE_WRITE_UPDATE,
+	WAIT_EVENT_COPY_FILE_READ,
+	WAIT_EVENT_COPY_FILE_WRITE,
+	WAIT_EVENT_DATA_FILE_EXTEND,
+	WAIT_EVENT_DATA_FILE_FLUSH,
+	WAIT_EVENT_DATA_FILE_IMMEDIATE_SYNC,
+	WAIT_EVENT_DATA_FILE_PREFETCH,
+	WAIT_EVENT_DATA_FILE_READ,
+	WAIT_EVENT_DATA_FILE_SYNC,
+	WAIT_EVENT_DATA_FILE_TRUNCATE,
+	WAIT_EVENT_DATA_FILE_WRITE,
+	WAIT_EVENT_DSM_FILL_ZERO_WRITE,
+	WAIT_EVENT_LOCK_FILE_ADDTODATADIR_READ,
+	WAIT_EVENT_LOCK_FILE_ADDTODATADIR_SYNC,
+	WAIT_EVENT_LOCK_FILE_ADDTODATADIR_WRITE,
+	WAIT_EVENT_LOCK_FILE_CREATE_READ,
+	WAIT_EVENT_LOCK_FILE_CREATE_SYNC,
+	WAIT_EVENT_LOCK_FILE_CREATE_WRITE,
+	WAIT_EVENT_LOCK_FILE_RECHECKDATADIR_READ,
+	WAIT_EVENT_LOGICAL_REWRITE_CHECKPOINT_SYNC,
+	WAIT_EVENT_LOGICAL_REWRITE_MAPPING_SYNC,
+	WAIT_EVENT_LOGICAL_REWRITE_MAPPING_WRITE,
+	WAIT_EVENT_LOGICAL_REWRITE_SYNC,
+	WAIT_EVENT_LOGICAL_REWRITE_TRUNCATE,
+	WAIT_EVENT_LOGICAL_REWRITE_WRITE,
+	WAIT_EVENT_RELATION_MAP_READ,
+	WAIT_EVENT_RELATION_MAP_SYNC,
+	WAIT_EVENT_RELATION_MAP_WRITE,
+	WAIT_EVENT_REORDER_BUFFER_READ,
+	WAIT_EVENT_REORDER_BUFFER_WRITE,
+	WAIT_EVENT_REORDER_LOGICAL_MAPPING_READ,
+	WAIT_EVENT_REPLICATION_SLOT_READ,
+	WAIT_EVENT_REPLICATION_SLOT_RESTORE_SYNC,
+	WAIT_EVENT_REPLICATION_SLOT_SYNC,
+	WAIT_EVENT_REPLICATION_SLOT_WRITE,
+	WAIT_EVENT_SLRU_FLUSH_SYNC,
+	WAIT_EVENT_SLRU_READ,
+	WAIT_EVENT_SLRU_SYNC,
+	WAIT_EVENT_SLRU_WRITE,
+	WAIT_EVENT_SNAPBUILD_READ,
+	WAIT_EVENT_SNAPBUILD_SYNC,
+	WAIT_EVENT_SNAPBUILD_WRITE,
+	WAIT_EVENT_TIMELINE_HISTORY_FILE_SYNC,
+	WAIT_EVENT_TIMELINE_HISTORY_FILE_WRITE,
+	WAIT_EVENT_TIMELINE_HISTORY_READ,
+	WAIT_EVENT_TIMELINE_HISTORY_SYNC,
+	WAIT_EVENT_TIMELINE_HISTORY_WRITE,
+	WAIT_EVENT_TWOPHASE_FILE_READ,
+	WAIT_EVENT_TWOPHASE_FILE_SYNC,
+	WAIT_EVENT_TWOPHASE_FILE_WRITE,
+	WAIT_EVENT_WALSENDER_TIMELINE_HISTORY_READ,
+	WAIT_EVENT_WAL_BOOTSTRAP_SYNC,
+	WAIT_EVENT_WAL_BOOTSTRAP_WRITE,
+	WAIT_EVENT_WAL_COPY_READ,
+	WAIT_EVENT_WAL_COPY_SYNC,
+	WAIT_EVENT_WAL_COPY_WRITE,
+	WAIT_EVENT_WAL_INIT_SYNC,
+	WAIT_EVENT_WAL_INIT_WRITE,
+	WAIT_EVENT_WAL_READ,
+	WAIT_EVENT_WAL_SYNC,
+	WAIT_EVENT_WAL_SYNC_METHOD_ASSIGN,
+	WAIT_EVENT_WAL_WRITE
+} WaitEventIO;
+
+/* ----------
+ * Command type for progress reporting purposes
+ * ----------
+ */
+typedef enum ProgressCommandType
+{
+	PROGRESS_COMMAND_INVALID,
+	PROGRESS_COMMAND_VACUUM
+} ProgressCommandType;
+
+#define PGSTAT_NUM_PROGRESS_PARAM	10
+
+/* ----------
+ * Shared-memory data structures
+ * ----------
+ */
+
+
+/*
+ * PgBackendSSLStatus
+ *
+ * For each backend, we keep the SSL status in a separate struct, that
+ * is only filled in if SSL is enabled.
+ */
+typedef struct PgBackendSSLStatus
+{
+	/* Information about SSL connection */
+	int			ssl_bits;
+	bool		ssl_compression;
+	char		ssl_version[NAMEDATALEN];	/* MUST be null-terminated */
+	char		ssl_cipher[NAMEDATALEN];	/* MUST be null-terminated */
+	char		ssl_clientdn[NAMEDATALEN];	/* MUST be null-terminated */
+} PgBackendSSLStatus;
+
+
+/* ----------
+ * PgBackendStatus
+ *
+ * Each live backend maintains a PgBackendStatus struct in shared memory
+ * showing its current activity.  (The structs are allocated according to
+ * BackendId, but that is not critical.)  Note that the collector process
+ * has no involvement in, or even access to, these structs.
+ *
+ * Each auxiliary process also maintains a PgBackendStatus struct in shared
+ * memory.
+ * ----------
+ */
+typedef struct PgBackendStatus
+{
+	/*
+	 * To avoid locking overhead, we use the following protocol: a backend
+	 * increments st_changecount before modifying its entry, and again after
+	 * finishing a modification.  A would-be reader should note the value of
+	 * st_changecount, copy the entry into private memory, then check
+	 * st_changecount again.  If the value hasn't changed, and if it's even,
+	 * the copy is valid; otherwise start over.  This makes updates cheap
+	 * while reads are potentially expensive, but that's the tradeoff we want.
+	 *
+	 * The above protocol needs the memory barriers to ensure that the
+	 * apparent order of execution is as it desires. Otherwise, for example,
+	 * the CPU might rearrange the code so that st_changecount is incremented
+	 * twice before the modification on a machine with weak memory ordering.
+	 * This surprising result can lead to bugs.
+	 */
+	int			st_changecount;
+
+	/* The entry is valid iff st_procpid > 0, unused if st_procpid == 0 */
+	int			st_procpid;
+
+	/* Type of backends */
+	BackendType st_backendType;
+
+	/* Times when current backend, transaction, and activity started */
+	TimestampTz st_proc_start_timestamp;
+	TimestampTz st_xact_start_timestamp;
+	TimestampTz st_activity_start_timestamp;
+	TimestampTz st_state_start_timestamp;
+
+	/* Database OID, owning user's OID, connection client address */
+	Oid			st_databaseid;
+	Oid			st_userid;
+	SockAddr	st_clientaddr;
+	char	   *st_clienthostname;	/* MUST be null-terminated */
+
+	/* Information about SSL connection */
+	bool		st_ssl;
+	PgBackendSSLStatus *st_sslstatus;
+
+	/* current state */
+	BackendState st_state;
+
+	/* application name; MUST be null-terminated */
+	char	   *st_appname;
+
+	/*
+	 * Current command string; MUST be null-terminated. Note that this string
+	 * possibly is truncated in the middle of a multi-byte character. As
+	 * activity strings are stored more frequently than read, that allows to
+	 * move the cost of correct truncation to the display side. Use
+	 * pgstat_clip_activity() to truncate correctly.
+	 */
+	char	   *st_activity_raw;
+
+	/*
+	 * Command progress reporting.  Any command which wishes can advertise
+	 * that it is running by setting st_progress_command,
+	 * st_progress_command_target, and st_progress_param[].
+	 * st_progress_command_target should be the OID of the relation which the
+	 * command targets (we assume there's just one, as this is meant for
+	 * utility commands), but the meaning of each element in the
+	 * st_progress_param array is command-specific.
+	 */
+	ProgressCommandType st_progress_command;
+	Oid			st_progress_command_target;
+	int64		st_progress_param[PGSTAT_NUM_PROGRESS_PARAM];
+} PgBackendStatus;
+
+/*
+ * Macros to load and store st_changecount with the memory barriers.
+ *
+ * pgstat_increment_changecount_before() and
+ * pgstat_increment_changecount_after() need to be called before and after
+ * PgBackendStatus entries are modified, respectively. This makes sure that
+ * st_changecount is incremented around the modification.
+ *
+ * Also pgstat_save_changecount_before() and pgstat_save_changecount_after()
+ * need to be called before and after PgBackendStatus entries are copied into
+ * private memory, respectively.
+ */
+#define pgstat_increment_changecount_before(beentry)	\
+	do {	\
+		beentry->st_changecount++;	\
+		pg_write_barrier(); \
+	} while (0)
+
+#define pgstat_increment_changecount_after(beentry) \
+	do {	\
+		pg_write_barrier(); \
+		beentry->st_changecount++;	\
+		Assert((beentry->st_changecount & 1) == 0); \
+	} while (0)
+
+#define pgstat_save_changecount_before(beentry, save_changecount)	\
+	do {	\
+		save_changecount = beentry->st_changecount; \
+		pg_read_barrier();	\
+	} while (0)
+
+#define pgstat_save_changecount_after(beentry, save_changecount)	\
+	do {	\
+		pg_read_barrier();	\
+		save_changecount = beentry->st_changecount; \
+	} while (0)
+
+/* ----------
+ * LocalPgBackendStatus
+ *
+ * When we build the backend status array, we use LocalPgBackendStatus to be
+ * able to add new values to the struct when needed without adding new fields
+ * to the shared memory. It contains the backend status as a first member.
+ * ----------
+ */
+typedef struct LocalPgBackendStatus
+{
+	/*
+	 * Local version of the backend status entry.
+	 */
+	PgBackendStatus backendStatus;
+
+	/*
+	 * The xid of the current transaction if available, InvalidTransactionId
+	 * if not.
+	 */
+	TransactionId backend_xid;
+
+	/*
+	 * The xmin of the current session if available, InvalidTransactionId if
+	 * not.
+	 */
+	TransactionId backend_xmin;
+} LocalPgBackendStatus;
+
+/* ----------
+ * GUC parameters
+ * ----------
+ */
+extern bool pgstat_track_activities;
+extern PGDLLIMPORT int pgstat_track_activity_query_size;
+
+/* ----------
+ * Functions called from backends
+ * ----------
+ */
+extern void pgstat_bestatus_clear_snapshot(void);
+extern void pgstat_bearray_initialize(void);
+extern void pgstat_bestart(void);
+
+extern const char *pgstat_get_wait_event(uint32 wait_event_info);
+extern const char *pgstat_get_wait_event_type(uint32 wait_event_info);
+extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
+extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
+									int buflen);
+extern const char *pgstat_get_backend_desc(BackendType backendType);
+
+extern void pgstat_progress_start_command(ProgressCommandType cmdtype,
+							  Oid relid);
+extern void pgstat_progress_update_param(int index, int64 val);
+extern void pgstat_progress_update_multi_param(int nparam, const int *index,
+								   const int64 *val);
+extern void pgstat_progress_end_command(void);
+
+extern char *pgstat_clip_activity(const char *raw_activity);
+
+/* ----------
+ * pgstat_report_wait_start() -
+ *
+ *	Called from places where server process needs to wait.  This is called
+ *	to report wait event information.  The wait information is stored
+ *	as 4-bytes where first byte represents the wait event class (type of
+ *	wait, for different types of wait, refer WaitClass) and the next
+ *	3-bytes represent the actual wait event.  Currently 2-bytes are used
+ *	for wait event which is sufficient for current usage, 1-byte is
+ *	reserved for future usage.
+ *
+ * NB: this *must* be able to survive being called before MyProc has been
+ * initialized.
+ * ----------
+ */
+static inline void
+pgstat_report_wait_start(uint32 wait_event_info)
+{
+	volatile PGPROC *proc = MyProc;
+
+	if (!pgstat_track_activities || !proc)
+		return;
+
+	/*
+	 * Since this is a four-byte field which is always read and written as
+	 * four-bytes, updates are atomic.
+	 */
+	proc->wait_event_info = wait_event_info;
+}
+
+/* ----------
+ * pgstat_report_wait_end() -
+ *
+ *	Called to report end of a wait.
+ *
+ * NB: this *must* be able to survive being called before MyProc has been
+ * initialized.
+ * ----------
+ */
+static inline void
+pgstat_report_wait_end(void)
+{
+	volatile PGPROC *proc = MyProc;
+
+	if (!pgstat_track_activities || !proc)
+		return;
+
+	/*
+	 * Since this is a four-byte field which is always read and written as
+	 * four-bytes, updates are atomic.
+	 */
+	proc->wait_event_info = 0;
+}
+extern PgBackendStatus *pgstat_fetch_stat_beentry(int beid);
+extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
+extern int	pgstat_fetch_stat_numbackends(void);
+
+/* For shared memory allocation/initialize */
+extern Size BackendStatusShmemSize(void);
+extern void CreateSharedBackendStatus(void);
+
+void pgstat_report_xact_timestamp(TimestampTz tstamp);
+void pgstat_bestat_initialize(void);
+
+extern void pgstat_report_activity(BackendState state, const char *cmd_str);
+extern void pgstat_report_appname(const char *appname);
+extern void pgstat_report_xact_timestamp(TimestampTz tstamp);
+extern const char *pgstat_get_wait_event(uint32 wait_event_info);
+extern const char *pgstat_get_wait_event_type(uint32 wait_event_info);
+extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
+extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
+									int buflen);
+extern const char *pgstat_get_backend_desc(BackendType backendType);
+
+extern void pgstat_progress_start_command(ProgressCommandType cmdtype,
+							  Oid relid);
+extern void pgstat_progress_update_param(int index, int64 val);
+extern void pgstat_progress_update_multi_param(int nparam, const int *index,
+								   const int64 *val);
+extern void pgstat_progress_end_command(void);
+
+#endif							/* BESTATUS_H */
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index bd09937457..5583f92902 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -1,7 +1,7 @@
 /* ----------
  *	pgstat.h
  *
- *	Definitions for the PostgreSQL statistics collector daemon.
+ *	Definitions for the PostgreSQL statistics collector facility.
  *
  *	Copyright (c) 2001-2018, PostgreSQL Global Development Group
  *
@@ -14,11 +14,8 @@
 #include "datatype/timestamp.h"
 #include "fmgr.h"
 #include "lib/dshash.h"
-#include "libpq/pqcomm.h"
-#include "port/atomics.h"
 #include "portability/instr_time.h"
 #include "postmaster/pgarch.h"
-#include "storage/proc.h"
 #include "utils/hsearch.h"
 #include "utils/relcache.h"
 
@@ -94,12 +91,11 @@ typedef enum PgStat_Single_Reset_Type
 	RESET_FUNCTION
 } PgStat_Single_Reset_Type;
 
+
 /* ------------------------------------------------------------
  * Structures kept in backend local memory while accumulating counts
  * ------------------------------------------------------------
  */
-
-
 /* ----------
  * PgStat_TableStatus			Per-table status within a backend
  *
@@ -167,10 +163,10 @@ typedef struct PgStat_BgWriter
  * 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.
+ * it against zeroes to detect whether there are any counts to apply.
  *
  * Note that the time counters are in instr_time format here.  We convert to
- * microseconds in PgStat_Counter format when transmitting to the collector.
+ * microseconds in PgStat_Counter format when applying to shared statsitics.
  * ----------
  */
 typedef struct PgStat_FunctionCounts
@@ -203,7 +199,7 @@ typedef struct PgStat_FunctionEntry
 } PgStat_FunctionEntry;
 
 /* ------------------------------------------------------------
- * Statistic collector data structures follow
+ * Statistic collector data structures on file and shared memory follow
  *
  * PGSTAT_FILE_FORMAT_ID should be changed whenever any of these
  * data structures change.
@@ -307,7 +303,7 @@ typedef struct PgStat_StatFuncEntry
 
 
 /*
- * Archiver statistics kept in the stats collector
+ * Archiver statistics kept in the shared stats
  */
 typedef struct PgStat_ArchiverStats
 {
@@ -323,7 +319,7 @@ typedef struct PgStat_ArchiverStats
 } PgStat_ArchiverStats;
 
 /*
- * Global statistics kept in the stats collector
+ * Global statistics kept in the shared stats
  */
 typedef struct PgStat_GlobalStats
 {
@@ -341,422 +337,6 @@ typedef struct PgStat_GlobalStats
 	TimestampTz stat_reset_timestamp;
 } PgStat_GlobalStats;
 
-
-/* ----------
- * Backend types
- * ----------
- */
-typedef enum BackendType
-{
-	B_AUTOVAC_LAUNCHER,
-	B_AUTOVAC_WORKER,
-	B_BACKEND,
-	B_BG_WORKER,
-	B_BG_WRITER,
-	B_ARCHIVER,
-	B_CHECKPOINTER,
-	B_STARTUP,
-	B_WAL_RECEIVER,
-	B_WAL_SENDER,
-	B_WAL_WRITER
-} BackendType;
-
-
-/* ----------
- * Backend states
- * ----------
- */
-typedef enum BackendState
-{
-	STATE_UNDEFINED,
-	STATE_IDLE,
-	STATE_RUNNING,
-	STATE_IDLEINTRANSACTION,
-	STATE_FASTPATH,
-	STATE_IDLEINTRANSACTION_ABORTED,
-	STATE_DISABLED
-} BackendState;
-
-
-/* ----------
- * Wait Classes
- * ----------
- */
-#define PG_WAIT_LWLOCK				0x01000000U
-#define PG_WAIT_LOCK				0x03000000U
-#define PG_WAIT_BUFFER_PIN			0x04000000U
-#define PG_WAIT_ACTIVITY			0x05000000U
-#define PG_WAIT_CLIENT				0x06000000U
-#define PG_WAIT_EXTENSION			0x07000000U
-#define PG_WAIT_IPC					0x08000000U
-#define PG_WAIT_TIMEOUT				0x09000000U
-#define PG_WAIT_IO					0x0A000000U
-
-/* ----------
- * Wait Events - Activity
- *
- * Use this category when a process is waiting because it has no work to do,
- * unless the "Client" or "Timeout" category describes the situation better.
- * Typically, this should only be used for background processes.
- * ----------
- */
-typedef enum
-{
-	WAIT_EVENT_ARCHIVER_MAIN = PG_WAIT_ACTIVITY,
-	WAIT_EVENT_AUTOVACUUM_MAIN,
-	WAIT_EVENT_BGWRITER_HIBERNATE,
-	WAIT_EVENT_BGWRITER_MAIN,
-	WAIT_EVENT_CHECKPOINTER_MAIN,
-	WAIT_EVENT_LOGICAL_APPLY_MAIN,
-	WAIT_EVENT_LOGICAL_LAUNCHER_MAIN,
-	WAIT_EVENT_PGSTAT_MAIN,
-	WAIT_EVENT_RECOVERY_WAL_ALL,
-	WAIT_EVENT_RECOVERY_WAL_STREAM,
-	WAIT_EVENT_SYSLOGGER_MAIN,
-	WAIT_EVENT_WAL_RECEIVER_MAIN,
-	WAIT_EVENT_WAL_SENDER_MAIN,
-	WAIT_EVENT_WAL_WRITER_MAIN
-} WaitEventActivity;
-
-/* ----------
- * Wait Events - Client
- *
- * Use this category when a process is waiting to send data to or receive data
- * from the frontend process to which it is connected.  This is never used for
- * a background process, which has no client connection.
- * ----------
- */
-typedef enum
-{
-	WAIT_EVENT_CLIENT_READ = PG_WAIT_CLIENT,
-	WAIT_EVENT_CLIENT_WRITE,
-	WAIT_EVENT_LIBPQWALRECEIVER_CONNECT,
-	WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE,
-	WAIT_EVENT_SSL_OPEN_SERVER,
-	WAIT_EVENT_WAL_RECEIVER_WAIT_START,
-	WAIT_EVENT_WAL_SENDER_WAIT_WAL,
-	WAIT_EVENT_WAL_SENDER_WRITE_DATA
-} WaitEventClient;
-
-/* ----------
- * Wait Events - IPC
- *
- * Use this category when a process cannot complete the work it is doing because
- * it is waiting for a notification from another process.
- * ----------
- */
-typedef enum
-{
-	WAIT_EVENT_BGWORKER_SHUTDOWN = PG_WAIT_IPC,
-	WAIT_EVENT_BGWORKER_STARTUP,
-	WAIT_EVENT_BTREE_PAGE,
-	WAIT_EVENT_CLOG_GROUP_UPDATE,
-	WAIT_EVENT_EXECUTE_GATHER,
-	WAIT_EVENT_HASH_BATCH_ALLOCATING,
-	WAIT_EVENT_HASH_BATCH_ELECTING,
-	WAIT_EVENT_HASH_BATCH_LOADING,
-	WAIT_EVENT_HASH_BUILD_ALLOCATING,
-	WAIT_EVENT_HASH_BUILD_ELECTING,
-	WAIT_EVENT_HASH_BUILD_HASHING_INNER,
-	WAIT_EVENT_HASH_BUILD_HASHING_OUTER,
-	WAIT_EVENT_HASH_GROW_BATCHES_ALLOCATING,
-	WAIT_EVENT_HASH_GROW_BATCHES_DECIDING,
-	WAIT_EVENT_HASH_GROW_BATCHES_ELECTING,
-	WAIT_EVENT_HASH_GROW_BATCHES_FINISHING,
-	WAIT_EVENT_HASH_GROW_BATCHES_REPARTITIONING,
-	WAIT_EVENT_HASH_GROW_BUCKETS_ALLOCATING,
-	WAIT_EVENT_HASH_GROW_BUCKETS_ELECTING,
-	WAIT_EVENT_HASH_GROW_BUCKETS_REINSERTING,
-	WAIT_EVENT_LOGICAL_SYNC_DATA,
-	WAIT_EVENT_LOGICAL_SYNC_STATE_CHANGE,
-	WAIT_EVENT_MQ_INTERNAL,
-	WAIT_EVENT_MQ_PUT_MESSAGE,
-	WAIT_EVENT_MQ_RECEIVE,
-	WAIT_EVENT_MQ_SEND,
-	WAIT_EVENT_PARALLEL_BITMAP_SCAN,
-	WAIT_EVENT_PARALLEL_CREATE_INDEX_SCAN,
-	WAIT_EVENT_PARALLEL_FINISH,
-	WAIT_EVENT_PROCARRAY_GROUP_UPDATE,
-	WAIT_EVENT_PROMOTE,
-	WAIT_EVENT_REPLICATION_ORIGIN_DROP,
-	WAIT_EVENT_REPLICATION_SLOT_DROP,
-	WAIT_EVENT_SAFE_SNAPSHOT,
-	WAIT_EVENT_SYNC_REP
-} WaitEventIPC;
-
-/* ----------
- * Wait Events - Timeout
- *
- * Use this category when a process is waiting for a timeout to expire.
- * ----------
- */
-typedef enum
-{
-	WAIT_EVENT_BASE_BACKUP_THROTTLE = PG_WAIT_TIMEOUT,
-	WAIT_EVENT_PG_SLEEP,
-	WAIT_EVENT_RECOVERY_APPLY_DELAY
-} WaitEventTimeout;
-
-/* ----------
- * Wait Events - IO
- *
- * Use this category when a process is waiting for a IO.
- * ----------
- */
-typedef enum
-{
-	WAIT_EVENT_BUFFILE_READ = PG_WAIT_IO,
-	WAIT_EVENT_BUFFILE_WRITE,
-	WAIT_EVENT_CONTROL_FILE_READ,
-	WAIT_EVENT_CONTROL_FILE_SYNC,
-	WAIT_EVENT_CONTROL_FILE_SYNC_UPDATE,
-	WAIT_EVENT_CONTROL_FILE_WRITE,
-	WAIT_EVENT_CONTROL_FILE_WRITE_UPDATE,
-	WAIT_EVENT_COPY_FILE_READ,
-	WAIT_EVENT_COPY_FILE_WRITE,
-	WAIT_EVENT_DATA_FILE_EXTEND,
-	WAIT_EVENT_DATA_FILE_FLUSH,
-	WAIT_EVENT_DATA_FILE_IMMEDIATE_SYNC,
-	WAIT_EVENT_DATA_FILE_PREFETCH,
-	WAIT_EVENT_DATA_FILE_READ,
-	WAIT_EVENT_DATA_FILE_SYNC,
-	WAIT_EVENT_DATA_FILE_TRUNCATE,
-	WAIT_EVENT_DATA_FILE_WRITE,
-	WAIT_EVENT_DSM_FILL_ZERO_WRITE,
-	WAIT_EVENT_LOCK_FILE_ADDTODATADIR_READ,
-	WAIT_EVENT_LOCK_FILE_ADDTODATADIR_SYNC,
-	WAIT_EVENT_LOCK_FILE_ADDTODATADIR_WRITE,
-	WAIT_EVENT_LOCK_FILE_CREATE_READ,
-	WAIT_EVENT_LOCK_FILE_CREATE_SYNC,
-	WAIT_EVENT_LOCK_FILE_CREATE_WRITE,
-	WAIT_EVENT_LOCK_FILE_RECHECKDATADIR_READ,
-	WAIT_EVENT_LOGICAL_REWRITE_CHECKPOINT_SYNC,
-	WAIT_EVENT_LOGICAL_REWRITE_MAPPING_SYNC,
-	WAIT_EVENT_LOGICAL_REWRITE_MAPPING_WRITE,
-	WAIT_EVENT_LOGICAL_REWRITE_SYNC,
-	WAIT_EVENT_LOGICAL_REWRITE_TRUNCATE,
-	WAIT_EVENT_LOGICAL_REWRITE_WRITE,
-	WAIT_EVENT_RELATION_MAP_READ,
-	WAIT_EVENT_RELATION_MAP_SYNC,
-	WAIT_EVENT_RELATION_MAP_WRITE,
-	WAIT_EVENT_REORDER_BUFFER_READ,
-	WAIT_EVENT_REORDER_BUFFER_WRITE,
-	WAIT_EVENT_REORDER_LOGICAL_MAPPING_READ,
-	WAIT_EVENT_REPLICATION_SLOT_READ,
-	WAIT_EVENT_REPLICATION_SLOT_RESTORE_SYNC,
-	WAIT_EVENT_REPLICATION_SLOT_SYNC,
-	WAIT_EVENT_REPLICATION_SLOT_WRITE,
-	WAIT_EVENT_SLRU_FLUSH_SYNC,
-	WAIT_EVENT_SLRU_READ,
-	WAIT_EVENT_SLRU_SYNC,
-	WAIT_EVENT_SLRU_WRITE,
-	WAIT_EVENT_SNAPBUILD_READ,
-	WAIT_EVENT_SNAPBUILD_SYNC,
-	WAIT_EVENT_SNAPBUILD_WRITE,
-	WAIT_EVENT_TIMELINE_HISTORY_FILE_SYNC,
-	WAIT_EVENT_TIMELINE_HISTORY_FILE_WRITE,
-	WAIT_EVENT_TIMELINE_HISTORY_READ,
-	WAIT_EVENT_TIMELINE_HISTORY_SYNC,
-	WAIT_EVENT_TIMELINE_HISTORY_WRITE,
-	WAIT_EVENT_TWOPHASE_FILE_READ,
-	WAIT_EVENT_TWOPHASE_FILE_SYNC,
-	WAIT_EVENT_TWOPHASE_FILE_WRITE,
-	WAIT_EVENT_WALSENDER_TIMELINE_HISTORY_READ,
-	WAIT_EVENT_WAL_BOOTSTRAP_SYNC,
-	WAIT_EVENT_WAL_BOOTSTRAP_WRITE,
-	WAIT_EVENT_WAL_COPY_READ,
-	WAIT_EVENT_WAL_COPY_SYNC,
-	WAIT_EVENT_WAL_COPY_WRITE,
-	WAIT_EVENT_WAL_INIT_SYNC,
-	WAIT_EVENT_WAL_INIT_WRITE,
-	WAIT_EVENT_WAL_READ,
-	WAIT_EVENT_WAL_SYNC,
-	WAIT_EVENT_WAL_SYNC_METHOD_ASSIGN,
-	WAIT_EVENT_WAL_WRITE
-} WaitEventIO;
-
-/* ----------
- * Command type for progress reporting purposes
- * ----------
- */
-typedef enum ProgressCommandType
-{
-	PROGRESS_COMMAND_INVALID,
-	PROGRESS_COMMAND_VACUUM
-} ProgressCommandType;
-
-#define PGSTAT_NUM_PROGRESS_PARAM	10
-
-/* ----------
- * Shared-memory data structures
- * ----------
- */
-
-
-/*
- * PgBackendSSLStatus
- *
- * For each backend, we keep the SSL status in a separate struct, that
- * is only filled in if SSL is enabled.
- */
-typedef struct PgBackendSSLStatus
-{
-	/* Information about SSL connection */
-	int			ssl_bits;
-	bool		ssl_compression;
-	char		ssl_version[NAMEDATALEN];	/* MUST be null-terminated */
-	char		ssl_cipher[NAMEDATALEN];	/* MUST be null-terminated */
-	char		ssl_clientdn[NAMEDATALEN];	/* MUST be null-terminated */
-} PgBackendSSLStatus;
-
-
-/* ----------
- * PgBackendStatus
- *
- * Each live backend maintains a PgBackendStatus struct in shared memory
- * showing its current activity.  (The structs are allocated according to
- * BackendId, but that is not critical.)  Note that the collector process
- * has no involvement in, or even access to, these structs.
- *
- * Each auxiliary process also maintains a PgBackendStatus struct in shared
- * memory.
- * ----------
- */
-typedef struct PgBackendStatus
-{
-	/*
-	 * To avoid locking overhead, we use the following protocol: a backend
-	 * increments st_changecount before modifying its entry, and again after
-	 * finishing a modification.  A would-be reader should note the value of
-	 * st_changecount, copy the entry into private memory, then check
-	 * st_changecount again.  If the value hasn't changed, and if it's even,
-	 * the copy is valid; otherwise start over.  This makes updates cheap
-	 * while reads are potentially expensive, but that's the tradeoff we want.
-	 *
-	 * The above protocol needs the memory barriers to ensure that the
-	 * apparent order of execution is as it desires. Otherwise, for example,
-	 * the CPU might rearrange the code so that st_changecount is incremented
-	 * twice before the modification on a machine with weak memory ordering.
-	 * This surprising result can lead to bugs.
-	 */
-	int			st_changecount;
-
-	/* The entry is valid iff st_procpid > 0, unused if st_procpid == 0 */
-	int			st_procpid;
-
-	/* Type of backends */
-	BackendType st_backendType;
-
-	/* Times when current backend, transaction, and activity started */
-	TimestampTz st_proc_start_timestamp;
-	TimestampTz st_xact_start_timestamp;
-	TimestampTz st_activity_start_timestamp;
-	TimestampTz st_state_start_timestamp;
-
-	/* Database OID, owning user's OID, connection client address */
-	Oid			st_databaseid;
-	Oid			st_userid;
-	SockAddr	st_clientaddr;
-	char	   *st_clienthostname;	/* MUST be null-terminated */
-
-	/* Information about SSL connection */
-	bool		st_ssl;
-	PgBackendSSLStatus *st_sslstatus;
-
-	/* current state */
-	BackendState st_state;
-
-	/* application name; MUST be null-terminated */
-	char	   *st_appname;
-
-	/*
-	 * Current command string; MUST be null-terminated. Note that this string
-	 * possibly is truncated in the middle of a multi-byte character. As
-	 * activity strings are stored more frequently than read, that allows to
-	 * move the cost of correct truncation to the display side. Use
-	 * pgstat_clip_activity() to truncate correctly.
-	 */
-	char	   *st_activity_raw;
-
-	/*
-	 * Command progress reporting.  Any command which wishes can advertise
-	 * that it is running by setting st_progress_command,
-	 * st_progress_command_target, and st_progress_param[].
-	 * st_progress_command_target should be the OID of the relation which the
-	 * command targets (we assume there's just one, as this is meant for
-	 * utility commands), but the meaning of each element in the
-	 * st_progress_param array is command-specific.
-	 */
-	ProgressCommandType st_progress_command;
-	Oid			st_progress_command_target;
-	int64		st_progress_param[PGSTAT_NUM_PROGRESS_PARAM];
-} PgBackendStatus;
-
-/*
- * Macros to load and store st_changecount with the memory barriers.
- *
- * pgstat_increment_changecount_before() and
- * pgstat_increment_changecount_after() need to be called before and after
- * PgBackendStatus entries are modified, respectively. This makes sure that
- * st_changecount is incremented around the modification.
- *
- * Also pgstat_save_changecount_before() and pgstat_save_changecount_after()
- * need to be called before and after PgBackendStatus entries are copied into
- * private memory, respectively.
- */
-#define pgstat_increment_changecount_before(beentry)	\
-	do {	\
-		beentry->st_changecount++;	\
-		pg_write_barrier(); \
-	} while (0)
-
-#define pgstat_increment_changecount_after(beentry) \
-	do {	\
-		pg_write_barrier(); \
-		beentry->st_changecount++;	\
-		Assert((beentry->st_changecount & 1) == 0); \
-	} while (0)
-
-#define pgstat_save_changecount_before(beentry, save_changecount)	\
-	do {	\
-		save_changecount = beentry->st_changecount; \
-		pg_read_barrier();	\
-	} while (0)
-
-#define pgstat_save_changecount_after(beentry, save_changecount)	\
-	do {	\
-		pg_read_barrier();	\
-		save_changecount = beentry->st_changecount; \
-	} while (0)
-
-/* ----------
- * LocalPgBackendStatus
- *
- * When we build the backend status array, we use LocalPgBackendStatus to be
- * able to add new values to the struct when needed without adding new fields
- * to the shared memory. It contains the backend status as a first member.
- * ----------
- */
-typedef struct LocalPgBackendStatus
-{
-	/*
-	 * Local version of the backend status entry.
-	 */
-	PgBackendStatus backendStatus;
-
-	/*
-	 * The xid of the current transaction if available, InvalidTransactionId
-	 * if not.
-	 */
-	TransactionId backend_xid;
-
-	/*
-	 * The xmin of the current session if available, InvalidTransactionId if
-	 * not.
-	 */
-	TransactionId backend_xmin;
-} LocalPgBackendStatus;
-
 /*
  * Working state needed to accumulate per-function-call timing statistics.
  */
@@ -778,10 +358,8 @@ typedef struct PgStat_FunctionCallUsage
  * GUC parameters
  * ----------
  */
-extern bool pgstat_track_activities;
 extern bool pgstat_track_counts;
 extern int	pgstat_track_functions;
-extern PGDLLIMPORT int pgstat_track_activity_query_size;
 extern char *pgstat_stat_directory;
 
 /*
@@ -826,26 +404,9 @@ extern void pgstat_report_deadlock(void);
 extern void pgstat_clear_snapshot(void);
 
 extern void pgstat_initialize(void);
+extern void pgstat_bearray_initialize(void);
 extern void pgstat_bestart(void);
 
-extern void pgstat_report_activity(BackendState state, const char *cmd_str);
-extern void pgstat_report_tempfile(size_t filesize);
-extern void pgstat_report_appname(const char *appname);
-extern void pgstat_report_xact_timestamp(TimestampTz tstamp);
-extern const char *pgstat_get_wait_event(uint32 wait_event_info);
-extern const char *pgstat_get_wait_event_type(uint32 wait_event_info);
-extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
-extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
-									int buflen);
-extern const char *pgstat_get_backend_desc(BackendType backendType);
-
-extern void pgstat_progress_start_command(ProgressCommandType cmdtype,
-							  Oid relid);
-extern void pgstat_progress_update_param(int index, int64 val);
-extern void pgstat_progress_update_multi_param(int nparam, const int *index,
-								   const int64 *val);
-extern void pgstat_progress_end_command(void);
-
 extern PgStat_TableStatus *find_tabstat_entry(Oid rel_id);
 extern PgStat_BackendFunctionEntry *find_funcstat_entry(Oid func_id);
 
@@ -856,60 +417,6 @@ extern PgStat_StatDBEntry *backend_get_db_entry(Oid dbid, bool oneshot);
 extern HTAB *backend_snapshot_all_db_entries(void);
 extern PgStat_StatTabEntry *backend_get_tab_entry(PgStat_StatDBEntry *dbent, Oid relid, bool oneshot);
 
-/* ----------
- * pgstat_report_wait_start() -
- *
- *	Called from places where server process needs to wait.  This is called
- *	to report wait event information.  The wait information is stored
- *	as 4-bytes where first byte represents the wait event class (type of
- *	wait, for different types of wait, refer WaitClass) and the next
- *	3-bytes represent the actual wait event.  Currently 2-bytes are used
- *	for wait event which is sufficient for current usage, 1-byte is
- *	reserved for future usage.
- *
- * NB: this *must* be able to survive being called before MyProc has been
- * initialized.
- * ----------
- */
-static inline void
-pgstat_report_wait_start(uint32 wait_event_info)
-{
-	volatile PGPROC *proc = MyProc;
-
-	if (!pgstat_track_activities || !proc)
-		return;
-
-	/*
-	 * Since this is a four-byte field which is always read and written as
-	 * four-bytes, updates are atomic.
-	 */
-	proc->wait_event_info = wait_event_info;
-}
-
-/* ----------
- * pgstat_report_wait_end() -
- *
- *	Called to report end of a wait.
- *
- * NB: this *must* be able to survive being called before MyProc has been
- * initialized.
- * ----------
- */
-static inline void
-pgstat_report_wait_end(void)
-{
-	volatile PGPROC *proc = MyProc;
-
-	if (!pgstat_track_activities || !proc)
-		return;
-
-	/*
-	 * Since this is a four-byte field which is always read and written as
-	 * four-bytes, updates are atomic.
-	 */
-	proc->wait_event_info = 0;
-}
-
 /* nontransactional event counts are simple enough to inline */
 
 #define pgstat_count_heap_scan(rel)									\
@@ -977,6 +484,8 @@ extern void pgstat_twophase_postabort(TransactionId xid, uint16 info,
 extern void pgstat_update_archiver(const char *xlog, bool failed);
 extern void pgstat_update_bgwriter(void);
 
+extern void pgstat_report_tempfile(size_t filesize);
+
 /* ----------
  * Support functions for the SQL-callable functions to
  * generate the pgstat* views.
@@ -984,10 +493,7 @@ extern void pgstat_update_bgwriter(void);
  */
 extern PgStat_StatDBEntry *pgstat_fetch_stat_dbentry(Oid relid, bool oneshot);
 extern PgStat_StatTabEntry *pgstat_fetch_stat_tabentry(Oid relid);
-extern PgBackendStatus *pgstat_fetch_stat_beentry(int beid);
-extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
 extern PgStat_StatFuncEntry *pgstat_fetch_stat_funcentry(Oid funcid);
-extern int	pgstat_fetch_stat_numbackends(void);
 extern PgStat_ArchiverStats *pgstat_fetch_stat_archiver(void);
 extern PgStat_GlobalStats *pgstat_fetch_global(void);
 
-- 
2.16.3

