From 572012427d202c4e2a8c66b64a1bca544a5987d8 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Sat, 3 Apr 2021 21:30:01 -0700
Subject: [PATCH v60 08/17] pgstat: Introduce pgstat_relation_should_count().

---
 src/include/pgstat.h                 | 22 +++++++----
 src/include/utils/rel.h              |  1 +
 src/backend/access/common/relation.c |  4 +-
 src/backend/catalog/index.c          |  2 +-
 src/backend/postmaster/pgstat.c      | 59 +++++++++++++++++-----------
 5 files changed, 53 insertions(+), 35 deletions(-)

diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 291e5ab1698..a34bb328e60 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -1030,43 +1030,49 @@ extern void pgstat_initialize(void);
 extern PgStat_TableStatus *find_tabstat_entry(Oid rel_id);
 extern PgStat_BackendFunctionEntry *find_funcstat_entry(Oid func_id);
 
-extern void pgstat_initstats(Relation rel);
+extern void pgstat_relation_init(Relation rel);
+extern void pgstat_relation_assoc(Relation rel);
+
+#define pgstat_relation_should_count(rel)                           \
+	(likely((rel)->pgstat_info != NULL) ? true :                    \
+	 ((rel)->pgstat_enabled ? pgstat_relation_assoc(rel), true : false))
+
 
 /* nontransactional event counts are simple enough to inline */
 
 #define pgstat_count_heap_scan(rel)									\
 	do {															\
-		if ((rel)->pgstat_info != NULL)								\
+		if (pgstat_relation_should_count(rel))						\
 			(rel)->pgstat_info->t_counts.t_numscans++;				\
 	} while (0)
 #define pgstat_count_heap_getnext(rel)								\
 	do {															\
-		if ((rel)->pgstat_info != NULL)								\
+		if (pgstat_relation_should_count(rel))						\
 			(rel)->pgstat_info->t_counts.t_tuples_returned++;		\
 	} while (0)
 #define pgstat_count_heap_fetch(rel)								\
 	do {															\
-		if ((rel)->pgstat_info != NULL)								\
+		if (pgstat_relation_should_count(rel))						\
 			(rel)->pgstat_info->t_counts.t_tuples_fetched++;		\
 	} while (0)
 #define pgstat_count_index_scan(rel)								\
 	do {															\
-		if ((rel)->pgstat_info != NULL)								\
+		if (pgstat_relation_should_count(rel))						\
 			(rel)->pgstat_info->t_counts.t_numscans++;				\
 	} while (0)
 #define pgstat_count_index_tuples(rel, n)							\
 	do {															\
-		if ((rel)->pgstat_info != NULL)								\
+		if (pgstat_relation_should_count(rel))						\
 			(rel)->pgstat_info->t_counts.t_tuples_returned += (n);	\
 	} while (0)
 #define pgstat_count_buffer_read(rel)								\
 	do {															\
-		if ((rel)->pgstat_info != NULL)								\
+		if (pgstat_relation_should_count(rel))						\
 			(rel)->pgstat_info->t_counts.t_blocks_fetched++;		\
 	} while (0)
 #define pgstat_count_buffer_hit(rel)								\
 	do {															\
-		if ((rel)->pgstat_info != NULL)								\
+		if (pgstat_relation_should_count(rel))						\
 			(rel)->pgstat_info->t_counts.t_blocks_hit++;			\
 	} while (0)
 #define pgstat_count_buffer_read_time(n)							\
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index 9a3a03e5207..e032612d39f 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -234,6 +234,7 @@ typedef struct RelationData
 	Oid			rd_toastoid;	/* Real TOAST table's OID, or InvalidOid */
 
 	/* use "struct" here to avoid needing to include pgstat.h: */
+	bool		pgstat_enabled;
 	struct PgStat_TableStatus *pgstat_info; /* statistics collection area */
 } RelationData;
 
diff --git a/src/backend/access/common/relation.c b/src/backend/access/common/relation.c
index 632d13c1eaf..3721bad1daf 100644
--- a/src/backend/access/common/relation.c
+++ b/src/backend/access/common/relation.c
@@ -73,7 +73,7 @@ relation_open(Oid relationId, LOCKMODE lockmode)
 	if (RelationUsesLocalBuffers(r))
 		MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPNAMESPACE;
 
-	pgstat_initstats(r);
+	pgstat_relation_init(r);
 
 	return r;
 }
@@ -123,7 +123,7 @@ try_relation_open(Oid relationId, LOCKMODE lockmode)
 	if (RelationUsesLocalBuffers(r))
 		MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPNAMESPACE;
 
-	pgstat_initstats(r);
+	pgstat_relation_init(r);
 
 	return r;
 }
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index a628b3281ce..7c5c2093328 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -1877,7 +1877,7 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
 		tabentry = pgstat_fetch_stat_tabentry(oldIndexId);
 		if (tabentry)
 		{
-			if (newClassRel->pgstat_info)
+			if (pgstat_relation_should_count(newClassRel))
 			{
 				newClassRel->pgstat_info->t_counts.t_numscans = tabentry->numscans;
 				newClassRel->pgstat_info->t_counts.t_tuples_returned = tabentry->tuples_returned;
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index bf93d0cd55e..6c4ba9932de 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -183,7 +183,7 @@ static bool pgStatRunningInCollector = false;
  * for the life of the backend.  Also, we zero out the t_id fields of the
  * contained PgStat_TableStatus structs whenever they are not actively in use.
  * This allows relcache pgstat_info pointers to be treated as long-lived data,
- * avoiding repeated searches in pgstat_initstats() when a relation is
+ * avoiding repeated searches in pgstat_relation_assoc() when a relation is
  * repeatedly opened during a transaction.
  */
 #define TABSTAT_QUANTUM		100 /* we alloc this many at a time */
@@ -1617,7 +1617,7 @@ pgstat_report_analyze(Relation rel,
 	 * collector ends up with the right numbers if we abort instead of
 	 * committing.)
 	 */
-	if (rel->pgstat_info != NULL)
+	if (pgstat_relation_should_count(rel))
 	{
 		PgStat_TableXactStatus *trans;
 
@@ -1943,7 +1943,7 @@ pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu, bool finalize)
 
 
 /* ----------
- * pgstat_initstats() -
+ * pgstat_relation_init() -
  *
  *	Initialize a relcache entry to count access statistics.
  *	Called whenever a relation is opened.
@@ -1955,7 +1955,7 @@ pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu, bool finalize)
  * ----------
  */
 void
-pgstat_initstats(Relation rel)
+pgstat_relation_init(Relation rel)
 {
 	Oid			rel_id = rel->rd_id;
 	char		relkind = rel->rd_rel->relkind;
@@ -1963,6 +1963,7 @@ pgstat_initstats(Relation rel)
 	/* We only count stats for things that have storage */
 	if (!RELKIND_HAS_STORAGE(relkind))
 	{
+		rel->pgstat_enabled = false;
 		rel->pgstat_info = NULL;
 		return;
 	}
@@ -1970,6 +1971,7 @@ pgstat_initstats(Relation rel)
 	if (pgStatSock == PGINVALID_SOCKET || !pgstat_track_counts)
 	{
 		/* We're not counting at all */
+		rel->pgstat_enabled = false;
 		rel->pgstat_info = NULL;
 		return;
 	}
@@ -1978,11 +1980,22 @@ pgstat_initstats(Relation rel)
 	 * If we already set up this relation in the current transaction, nothing
 	 * to do.
 	 */
-	if (rel->pgstat_info != NULL &&
+	if (rel->pgstat_info &&
 		rel->pgstat_info->t_id == rel_id)
 		return;
 
-	/* Else find or make the PgStat_TableStatus entry, and update link */
+	rel->pgstat_enabled = true;
+}
+
+void
+pgstat_relation_assoc(Relation rel)
+{
+	Oid			rel_id = rel->rd_id;
+
+	Assert(rel->pgstat_enabled);
+	Assert(rel->pgstat_info == NULL);
+
+	/* find or make the PgStat_TableStatus entry, and update link */
 	rel->pgstat_info = get_tabstat_entry(rel_id, rel->rd_rel->relisshared);
 }
 
@@ -2149,13 +2162,12 @@ add_tabstat_xact_level(PgStat_TableStatus *pgstat_info, int nest_level)
 void
 pgstat_count_heap_insert(Relation rel, PgStat_Counter n)
 {
-	PgStat_TableStatus *pgstat_info = rel->pgstat_info;
-
-	if (pgstat_info != NULL)
+	if (pgstat_relation_should_count(rel))
 	{
-		/* We have to log the effect at the proper transactional level */
+		PgStat_TableStatus *pgstat_info = rel->pgstat_info;
 		int			nest_level = GetCurrentTransactionNestLevel();
 
+		/* We have to log the effect at the proper transactional level */
 		if (pgstat_info->trans == NULL ||
 			pgstat_info->trans->nest_level != nest_level)
 			add_tabstat_xact_level(pgstat_info, nest_level);
@@ -2170,13 +2182,12 @@ pgstat_count_heap_insert(Relation rel, PgStat_Counter n)
 void
 pgstat_count_heap_update(Relation rel, bool hot)
 {
-	PgStat_TableStatus *pgstat_info = rel->pgstat_info;
-
-	if (pgstat_info != NULL)
+	if (pgstat_relation_should_count(rel))
 	{
-		/* We have to log the effect at the proper transactional level */
+		PgStat_TableStatus *pgstat_info = rel->pgstat_info;
 		int			nest_level = GetCurrentTransactionNestLevel();
 
+		/* We have to log the effect at the proper transactional level */
 		if (pgstat_info->trans == NULL ||
 			pgstat_info->trans->nest_level != nest_level)
 			add_tabstat_xact_level(pgstat_info, nest_level);
@@ -2195,13 +2206,12 @@ pgstat_count_heap_update(Relation rel, bool hot)
 void
 pgstat_count_heap_delete(Relation rel)
 {
-	PgStat_TableStatus *pgstat_info = rel->pgstat_info;
-
-	if (pgstat_info != NULL)
+	if (pgstat_relation_should_count(rel))
 	{
-		/* We have to log the effect at the proper transactional level */
+		PgStat_TableStatus *pgstat_info = rel->pgstat_info;
 		int			nest_level = GetCurrentTransactionNestLevel();
 
+		/* We have to log the effect at the proper transactional level */
 		if (pgstat_info->trans == NULL ||
 			pgstat_info->trans->nest_level != nest_level)
 			add_tabstat_xact_level(pgstat_info, nest_level);
@@ -2253,13 +2263,12 @@ pgstat_truncdrop_restore_counters(PgStat_TableXactStatus *trans)
 void
 pgstat_count_truncate(Relation rel)
 {
-	PgStat_TableStatus *pgstat_info = rel->pgstat_info;
-
-	if (pgstat_info != NULL)
+	if (pgstat_relation_should_count(rel))
 	{
-		/* We have to log the effect at the proper transactional level */
+		PgStat_TableStatus *pgstat_info = rel->pgstat_info;
 		int			nest_level = GetCurrentTransactionNestLevel();
 
+		/* We have to log the effect at the proper transactional level */
 		if (pgstat_info->trans == NULL ||
 			pgstat_info->trans->nest_level != nest_level)
 			add_tabstat_xact_level(pgstat_info, nest_level);
@@ -2282,10 +2291,12 @@ pgstat_count_truncate(Relation rel)
 void
 pgstat_update_heap_dead_tuples(Relation rel, int delta)
 {
-	PgStat_TableStatus *pgstat_info = rel->pgstat_info;
+	if (pgstat_relation_should_count(rel))
+	{
+		PgStat_TableStatus *pgstat_info = rel->pgstat_info;
 
-	if (pgstat_info != NULL)
 		pgstat_info->t_counts.t_delta_dead_tuples -= delta;
+	}
 }
 
 /*
-- 
2.31.0.121.g9198c13e34

