Add DBState to pg_control_system function

Started by Bharath Rupireddyalmost 4 years ago2 messages
#1Bharath Rupireddy
bharath.rupireddyforpostgres@gmail.com
1 attachment(s)

Hi,

I think emitting DBState (staring up, shut down, shut down in
recovery, shutting down, in crash recovery, in archive recovery, in
production) via the pg_control_system function would help know the
database state, especially during PITR/archive recovery. During
archive recovery, the server can open up for read-only connections
even before the archive recovery finishes. Having, pg_control_system
emit database state would help the users/service layers know it and so
they can take some actions based on it.

Attaching a patch herewith.

Thoughts?

Regards,
Bharath Rupireddy.

Attachments:

v1-0001-Add-DBState-to-pg_control_system-function.patchapplication/octet-stream; name=v1-0001-Add-DBState-to-pg_control_system-function.patchDownload
From b23f134363d33040249ca3c09b3d5de23aae5792 Mon Sep 17 00:00:00 2001
From: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>
Date: Tue, 1 Feb 2022 04:16:52 +0000
Subject: [PATCH v1] Add DBState to pg_control_system function

Add DBState as a column to the pg_control_system function which
would help know the database state, especially during PITR/archive
recovery. During archive recovery, the server can open up for
read-only connections even before the archive recovery finishes.
Having, pg_control_system emit database state would help the
users/service layers know it and so they can take some actions
based on it.
---
 doc/src/sgml/func.sgml                  |  5 +++++
 src/backend/utils/misc/pg_controldata.c | 11 +++++++---
 src/bin/pg_controldata/pg_controldata.c | 26 +----------------------
 src/common/controldata_utils.c          | 28 +++++++++++++++++++++++++
 src/include/catalog/pg_proc.dat         |  6 +++---
 src/include/common/controldata_utils.h  |  1 +
 6 files changed, 46 insertions(+), 31 deletions(-)

diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 8754f2f89b..0d2bd44f49 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -25166,6 +25166,11 @@ SELECT collation for ('foo' COLLATE "de_DE");
        <entry><type>timestamp with time zone</type></entry>
       </row>
 
+      <row>
+       <entry><structfield>database_cluster_state</structfield></entry>
+       <entry><type>text</type></entry>
+      </row>
+
      </tbody>
     </tgroup>
    </table>
diff --git a/src/backend/utils/misc/pg_controldata.c b/src/backend/utils/misc/pg_controldata.c
index 781f8b8758..09bda4b9d6 100644
--- a/src/backend/utils/misc/pg_controldata.c
+++ b/src/backend/utils/misc/pg_controldata.c
@@ -31,8 +31,8 @@
 Datum
 pg_control_system(PG_FUNCTION_ARGS)
 {
-	Datum		values[4];
-	bool		nulls[4];
+	Datum		values[5];
+	bool		nulls[5];
 	TupleDesc	tupdesc;
 	HeapTuple	htup;
 	ControlFileData *ControlFile;
@@ -42,7 +42,7 @@ pg_control_system(PG_FUNCTION_ARGS)
 	 * Construct a tuple descriptor for the result row.  This must match this
 	 * function's pg_proc entry!
 	 */
-	tupdesc = CreateTemplateTupleDesc(4);
+	tupdesc = CreateTemplateTupleDesc(5);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "pg_control_version",
 					   INT4OID, -1, 0);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "catalog_version_no",
@@ -51,6 +51,8 @@ pg_control_system(PG_FUNCTION_ARGS)
 					   INT8OID, -1, 0);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 4, "pg_control_last_modified",
 					   TIMESTAMPTZOID, -1, 0);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 5, "database_cluster_state",
+					   TEXTOID, -1, 0);
 	tupdesc = BlessTupleDesc(tupdesc);
 
 	/* read the control file */
@@ -71,6 +73,9 @@ pg_control_system(PG_FUNCTION_ARGS)
 	values[3] = TimestampTzGetDatum(time_t_to_timestamptz(ControlFile->time));
 	nulls[3] = false;
 
+	values[4] = CStringGetTextDatum(get_dbstate(ControlFile->state));
+	nulls[4] = false;
+
 	htup = heap_form_tuple(tupdesc, values, nulls);
 
 	PG_RETURN_DATUM(HeapTupleGetDatum(htup));
diff --git a/src/bin/pg_controldata/pg_controldata.c b/src/bin/pg_controldata/pg_controldata.c
index f911f98d94..1d20843391 100644
--- a/src/bin/pg_controldata/pg_controldata.c
+++ b/src/bin/pg_controldata/pg_controldata.c
@@ -45,30 +45,6 @@ usage(const char *progname)
 	printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
 }
 
-
-static const char *
-dbState(DBState state)
-{
-	switch (state)
-	{
-		case DB_STARTUP:
-			return _("starting up");
-		case DB_SHUTDOWNED:
-			return _("shut down");
-		case DB_SHUTDOWNED_IN_RECOVERY:
-			return _("shut down in recovery");
-		case DB_SHUTDOWNING:
-			return _("shutting down");
-		case DB_IN_CRASH_RECOVERY:
-			return _("in crash recovery");
-		case DB_IN_ARCHIVE_RECOVERY:
-			return _("in archive recovery");
-		case DB_IN_PRODUCTION:
-			return _("in production");
-	}
-	return _("unrecognized status code");
-}
-
 static const char *
 wal_level_str(WalLevel wal_level)
 {
@@ -232,7 +208,7 @@ main(int argc, char *argv[])
 	printf(_("Database system identifier:           %llu\n"),
 		   (unsigned long long) ControlFile->system_identifier);
 	printf(_("Database cluster state:               %s\n"),
-		   dbState(ControlFile->state));
+		   get_dbstate(ControlFile->state));
 	printf(_("pg_control last modified:             %s\n"),
 		   pgctime_str);
 	printf(_("Latest checkpoint location:           %X/%X\n"),
diff --git a/src/common/controldata_utils.c b/src/common/controldata_utils.c
index 348f046a44..b51b693965 100644
--- a/src/common/controldata_utils.c
+++ b/src/common/controldata_utils.c
@@ -265,3 +265,31 @@ update_controlfile(const char *DataDir,
 #endif
 	}
 }
+
+/*
+ * get_dbstate()
+ *
+ * Get the database cluster state.
+ */
+const char *
+get_dbstate(DBState state)
+{
+	switch (state)
+	{
+		case DB_STARTUP:
+			return _("starting up");
+		case DB_SHUTDOWNED:
+			return _("shut down");
+		case DB_SHUTDOWNED_IN_RECOVERY:
+			return _("shut down in recovery");
+		case DB_SHUTDOWNING:
+			return _("shutting down");
+		case DB_IN_CRASH_RECOVERY:
+			return _("in crash recovery");
+		case DB_IN_ARCHIVE_RECOVERY:
+			return _("in archive recovery");
+		case DB_IN_PRODUCTION:
+			return _("in production");
+	}
+	return _("unrecognized status code");
+}
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 7024dbe10a..159421ce0e 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -11561,9 +11561,9 @@
 { oid => '3441',
   descr => 'pg_controldata general state information as a function',
   proname => 'pg_control_system', provolatile => 'v', prorettype => 'record',
-  proargtypes => '', proallargtypes => '{int4,int4,int8,timestamptz}',
-  proargmodes => '{o,o,o,o}',
-  proargnames => '{pg_control_version,catalog_version_no,system_identifier,pg_control_last_modified}',
+  proargtypes => '', proallargtypes => '{int4,int4,int8,timestamptz,text}',
+  proargmodes => '{o,o,o,o,o}',
+  proargnames => '{pg_control_version,catalog_version_no,system_identifier,pg_control_last_modified,database_cluster_state}',
   prosrc => 'pg_control_system' },
 
 { oid => '3442',
diff --git a/src/include/common/controldata_utils.h b/src/include/common/controldata_utils.h
index b1dab7547c..1ac0147724 100644
--- a/src/include/common/controldata_utils.h
+++ b/src/include/common/controldata_utils.h
@@ -15,5 +15,6 @@
 extern ControlFileData *get_controlfile(const char *DataDir, bool *crc_ok_p);
 extern void update_controlfile(const char *DataDir,
 							   ControlFileData *ControlFile, bool do_sync);
+extern const char *get_dbstate(DBState state);
 
 #endif							/* COMMON_CONTROLDATA_UTILS_H */
-- 
2.25.1

#2Fujii Masao
masao.fujii@oss.nttdata.com
In reply to: Bharath Rupireddy (#1)
Re: Add DBState to pg_control_system function

On 2022/02/01 13:22, Bharath Rupireddy wrote:

Hi,

I think emitting DBState (staring up, shut down, shut down in
recovery, shutting down, in crash recovery, in archive recovery, in
production) via the pg_control_system function would help know the
database state, especially during PITR/archive recovery. During
archive recovery, the server can open up for read-only connections
even before the archive recovery finishes. Having, pg_control_system
emit database state would help the users/service layers know it and so
they can take some actions based on it.

Attaching a patch herewith.

Thoughts?

This information seems not so helpful because only "in production" and "archive recovery" can be reported during normal running and recovery, respectively. No? In the state other than them, we cannot connect to the server and execute pg_control_system().

Regards,

--
Fujii Masao
Advanced Computing Technology Center
Research and Development Headquarters
NTT DATA CORPORATION