On 12/23/2015 04:37 PM, Michael Paquier wrote: > On Thu, Dec 24, 2015 at 2:08 AM, Joe Conway <[email protected]> wrote: >> 2) Change the pg_controldata to be a bunch of separate functions as >> suggested by Josh Berkus rather than one SRF. > > This looks like a plan, thanks!
As discussed, a completely revamped and split off pg_controldata patch.
Below are the details for those interested.
Comments please.
Joe
===============
What this patch does:
---------------
1) Change NextXID output format from "%u/%u" to "%u:%u"
(see recent hackers thread)
2) Refactor bin/pg_controldata (there should be no visible change to
pg_controldata output)
3) Adds new functions, more or less in line with previous discussions:
* pg_checkpoint_state()
* pg_controldata_state()
* pg_recovery_state()
* pg_init_state()
===============
Missing (TODO once agreement on the above is reached):
---------------
a) documentation
b) catversion bump
c) regression tests
===============
New function detail and sample output:
---------------
postgres=# \x
Expanded display is on.
postgres=# \df pg_*_state
List of functions
-[ RECORD 1 ]-------+----------------------------------------------
Schema | pg_catalog
Name | pg_checkpoint_state
Result data type | record
Argument data types | OUT checkpoint_location pg_lsn,
| OUT prior_location pg_lsn,
| OUT redo_location pg_lsn,
| OUT redo_wal_file text,
| OUT timeline_id integer,
| OUT prev_timeline_id integer,
| OUT full_page_writes boolean,
| OUT next_xid text,
| OUT next_oid oid,
| OUT next_multixact_id xid,
| OUT next_multi_offset xid,
| OUT oldest_xid xid,
| OUT oldest_xid_dbid oid,
| OUT oldest_active_xid xid,
| OUT oldest_multi_xid xid,
| OUT oldest_multi_dbid oid,
| OUT oldest_commit_ts_xid xid,
| OUT newest_commit_ts_xid xid,
| OUT checkpoint_time timestamp with time zone
Type | normal
-[ RECORD 2 ]-------+----------------------------------------------
Schema | pg_catalog
Name | pg_controldata_state
Result data type | record
Argument data types | OUT pg_control_version integer,
| OUT catalog_version_no integer,
| OUT system_identifier bigint,
| OUT pg_control_last_modified
| timestamp with time zone
Type | normal
-[ RECORD 3 ]-------+----------------------------------------------
Schema | pg_catalog
Name | pg_init_state
Result data type | record
Argument data types | OUT max_data_alignment integer,
| OUT database_block_size integer,
| OUT blocks_per_segment integer,
| OUT wal_block_size integer,
| OUT bytes_per_wal_segment integer,
| OUT max_identifier_length integer,
| OUT max_index_columns integer,
| OUT max_toast_chunk_size integer,
| OUT large_object_chunk_size integer,
| OUT bigint_timestamps boolean,
| OUT float4_pass_by_value boolean,
| OUT float8_pass_by_value boolean,
| OUT data_page_checksum_version integer
Type | normal
-[ RECORD 4 ]-------+----------------------------------------------
Schema | pg_catalog
Name | pg_recovery_state
Result data type | record
Argument data types | OUT min_recovery_end_location pg_lsn,
| OUT min_recovery_end_timeline integer,
| OUT backup_start_location pg_lsn,
| OUT backup_end_location pg_lsn,
| OUT end_of_backup_record_required boolean
Type | normal
postgres=# select * from pg_controldata_state();
-[ RECORD 1 ]------------+-----------------------
pg_control_version | 942
catalog_version_no | 201511071
system_identifier | 6233852631805477166
pg_control_last_modified | 2015-12-29 15:32:09-08
postgres=# select * from pg_checkpoint_state();
-[ RECORD 1 ]--------+-------------------------
checkpoint_location | 0/14E8C38
prior_location | 0/14D6340
redo_location | 0/14E8C38
redo_wal_file | 000000010000000000000001
timeline_id | 1
prev_timeline_id | 1
full_page_writes | t
next_xid | 0:574
next_oid | 12407
next_multixact_id | 1
next_multi_offset | 0
oldest_xid | 565
oldest_xid_dbid | 1
oldest_active_xid | 0
oldest_multi_xid | 1
oldest_multi_dbid | 1
oldest_commit_ts_xid | 0
newest_commit_ts_xid | 0
checkpoint_time | 2015-12-29 15:32:02-08
postgres=# select * from pg_recovery_state();
-[ RECORD 1 ]-----------------+----
min_recovery_end_location | 0/0
min_recovery_end_timeline | 0
backup_start_location | 0/0
backup_end_location | 0/0
end_of_backup_record_required | f
postgres=# select * from pg_init_state();
-[ RECORD 1 ]--------------+---------
max_data_alignment | 8
database_block_size | 8192
blocks_per_segment | 131072
wal_block_size | 8192
bytes_per_wal_segment | 16777216
max_identifier_length | 64
max_index_columns | 32
max_toast_chunk_size | 1996
large_object_chunk_size | 2048
bigint_timestamps | t
float4_pass_by_value | t
float8_pass_by_value | t
data_page_checksum_version | 0
--
Crunchy Data - http://crunchydata.com
PostgreSQL Support for Secure Enterprises
Consulting, Training, & Open Source Development
diff --git a/src/backend/utils/misc/Makefile b/src/backend/utils/misc/Makefile
index 7889101..80b139e 100644
*** a/src/backend/utils/misc/Makefile
--- b/src/backend/utils/misc/Makefile
*************** include $(top_builddir)/src/Makefile.glo
*** 14,21 ****
override CPPFLAGS := -I. -I$(srcdir) $(CPPFLAGS)
! OBJS = guc.o help_config.o pg_rusage.o ps_status.o rls.o \
! sampling.o superuser.o timeout.o tzparser.o
# This location might depend on the installation directories. Therefore
# we can't subsitute it into pg_config.h.
--- 14,21 ----
override CPPFLAGS := -I. -I$(srcdir) $(CPPFLAGS)
! OBJS = guc.o help_config.o pg_controldata.o pg_rusage.o \
! ps_status.o rls.o sampling.o superuser.o timeout.o tzparser.o
# This location might depend on the installation directories. Therefore
# we can't subsitute it into pg_config.h.
diff --git a/src/backend/utils/misc/pg_controldata.c b/src/backend/utils/misc/pg_controldata.c
index ...fd00ec7 .
*** a/src/backend/utils/misc/pg_controldata.c
--- b/src/backend/utils/misc/pg_controldata.c
***************
*** 0 ****
--- 1,358 ----
+ /*-------------------------------------------------------------------------
+ *
+ * pg_controldata.c
+ * Expose select pg_controldata output, except via SQL functions
+ *
+ * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/backend/utils/misc/pg_controldata.c
+ *
+ */
+
+ #include "postgres.h"
+
+ #include "funcapi.h"
+ #include "miscadmin.h"
+ #include "access/htup_details.h"
+ #include "access/xlog_internal.h"
+ #include "catalog/pg_control.h"
+ #include "catalog/pg_type.h"
+ #include "common/controldata_utils.h"
+ #include "utils/builtins.h"
+ #include "utils/pg_lsn.h"
+ #include "utils/timestamp.h"
+
+ extern controldata *ControlData;
+
+ Datum
+ pg_controldata_state(PG_FUNCTION_ARGS)
+ {
+ Datum values[4];
+ bool nulls[4];
+ TupleDesc tupdesc;
+ HeapTuple htup;
+ ControlFileData *ControlFile;
+
+ /*
+ * Construct a tuple descriptor for the result row. This must match this
+ * function's pg_proc entry!
+ */
+ tupdesc = CreateTemplateTupleDesc(4, false);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 1, "pg_control_version",
+ INT4OID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 2, "catalog_version_no",
+ INT4OID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 3, "system_identifier",
+ INT8OID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 4, "pg_control_last_modified",
+ TIMESTAMPTZOID, -1, 0);
+ tupdesc = BlessTupleDesc(tupdesc);
+
+ /* read the control file */
+ ControlFile = get_controlfile(DataDir, NULL);
+
+ if (ControlFile->pg_control_version % 65536 == 0 &&
+ ControlFile->pg_control_version / 65536 != 0)
+ elog(ERROR, _("byte ordering mismatch"));
+
+ values[0] = Int32GetDatum(ControlFile->pg_control_version);
+ nulls[0] = false;
+
+ values[1] = Int32GetDatum(ControlFile->catalog_version_no);
+ nulls[1] = false;
+
+ values[2] = Int64GetDatum(ControlFile->system_identifier);
+ nulls[2] = false;
+
+ values[3] = TimestampTzGetDatum(time_t_to_timestamptz(ControlFile->time));
+ nulls[3] = false;
+
+ htup = heap_form_tuple(tupdesc, values, nulls);
+
+ PG_RETURN_DATUM(HeapTupleGetDatum(htup));
+ }
+
+ Datum
+ pg_checkpoint_state(PG_FUNCTION_ARGS)
+ {
+ Datum values[19];
+ bool nulls[19];
+ TupleDesc tupdesc;
+ HeapTuple htup;
+ ControlFileData *ControlFile;
+ XLogSegNo segno;
+ char xlogfilename[MAXFNAMELEN];
+
+ /*
+ * Construct a tuple descriptor for the result row. This must match this
+ * function's pg_proc entry!
+ */
+ tupdesc = CreateTemplateTupleDesc(19, false);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 1, "checkpoint_location",
+ LSNOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 2, "prior_location",
+ LSNOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 3, "redo_location",
+ LSNOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 4, "redo_wal_file",
+ TEXTOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 5, "timeline_id",
+ INT4OID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 6, "prev_timeline_id",
+ INT4OID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 7, "full_page_writes",
+ BOOLOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 8, "next_xid",
+ TEXTOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 9, "next_oid",
+ OIDOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 10, "next_multixact_id",
+ XIDOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 11, "next_multi_offset",
+ XIDOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 12, "oldest_xid",
+ XIDOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 13, "oldest_xid_dbid",
+ OIDOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 14, "oldest_active_xid",
+ XIDOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 15, "oldest_multi_xid",
+ XIDOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 16, "oldest_multi_dbid",
+ OIDOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 17, "oldest_commit_ts_xid",
+ XIDOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 18, "newest_commit_ts_xid",
+ XIDOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 19, "checkpoint_time",
+ TIMESTAMPTZOID, -1, 0);
+ tupdesc = BlessTupleDesc(tupdesc);
+
+ /* Read the control file. */
+ ControlFile = get_controlfile(DataDir, NULL);
+
+ /* Make sure it is valid. */
+ if (ControlFile->pg_control_version % 65536 == 0 &&
+ ControlFile->pg_control_version / 65536 != 0)
+ elog(ERROR, _("byte ordering mismatch"));
+
+ /*
+ * Calculate name of the WAL file containing the latest checkpoint's REDO
+ * start point.
+ */
+ XLByteToSeg(ControlFile->checkPointCopy.redo, segno);
+ XLogFileName(xlogfilename, ControlFile->checkPointCopy.ThisTimeLineID, segno);
+
+ /* Populate the values and null arrays */
+ values[0] = LSNGetDatum(ControlFile->checkPoint);
+ nulls[0] = false;
+
+ values[1] = LSNGetDatum(ControlFile->prevCheckPoint);
+ nulls[1] = false;
+
+ values[2] = LSNGetDatum(ControlFile->checkPointCopy.redo);
+ nulls[2] = false;
+
+ values[3] = CStringGetTextDatum(xlogfilename);
+ nulls[3] = false;
+
+ values[4] = Int32GetDatum(ControlFile->checkPointCopy.ThisTimeLineID);
+ nulls[4] = false;
+
+ values[5] = Int32GetDatum(ControlFile->checkPointCopy.PrevTimeLineID);
+ nulls[5] = false;
+
+ values[6] = BoolGetDatum(ControlFile->checkPointCopy.fullPageWrites);
+ nulls[6] = false;
+
+ values[7] = CStringGetTextDatum(psprintf("%u:%u",
+ ControlFile->checkPointCopy.nextXidEpoch,
+ ControlFile->checkPointCopy.nextXid));
+ nulls[7] = false;
+
+ values[8] = ObjectIdGetDatum(ControlFile->checkPointCopy.nextOid);
+ nulls[8] = false;
+
+ values[9] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMulti);
+ nulls[9] = false;
+
+ values[10] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMultiOffset);
+ nulls[10] = false;
+
+ values[11] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestXid);
+ nulls[11] = false;
+
+ values[12] = ObjectIdGetDatum(ControlFile->checkPointCopy.oldestXidDB);
+ nulls[12] = false;
+
+ values[13] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestActiveXid);
+ nulls[13] = false;
+
+ values[14] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestMulti);
+ nulls[14] = false;
+
+ values[15] = ObjectIdGetDatum(ControlFile->checkPointCopy.oldestMultiDB);
+ nulls[15] = false;
+
+ values[16] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestCommitTsXid);
+ nulls[16] = false;
+
+ values[17] = TransactionIdGetDatum(ControlFile->checkPointCopy.newestCommitTsXid);
+ nulls[17] = false;
+
+ values[18] = TimestampTzGetDatum(
+ time_t_to_timestamptz(ControlFile->checkPointCopy.time));
+ nulls[18] = false;
+
+ htup = heap_form_tuple(tupdesc, values, nulls);
+
+ PG_RETURN_DATUM(HeapTupleGetDatum(htup));
+ }
+
+ Datum
+ pg_recovery_state(PG_FUNCTION_ARGS)
+ {
+ Datum values[5];
+ bool nulls[5];
+ TupleDesc tupdesc;
+ HeapTuple htup;
+ ControlFileData *ControlFile;
+
+ /*
+ * Construct a tuple descriptor for the result row. This must match this
+ * function's pg_proc entry!
+ */
+ tupdesc = CreateTemplateTupleDesc(5, false);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 1, "min_recovery_end_location",
+ LSNOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 2, "min_recovery_end_timeline",
+ INT4OID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 3, "backup_start_location",
+ LSNOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 4, "backup_end_location",
+ LSNOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 5, "end_of_backup_record_required",
+ BOOLOID, -1, 0);
+ tupdesc = BlessTupleDesc(tupdesc);
+
+ /* read the control file */
+ ControlFile = get_controlfile(DataDir, NULL);
+
+ if (ControlFile->pg_control_version % 65536 == 0 &&
+ ControlFile->pg_control_version / 65536 != 0)
+ elog(ERROR, _("byte ordering mismatch"));
+
+ values[0] = LSNGetDatum(ControlFile->minRecoveryPoint);
+ nulls[0] = false;
+
+ values[1] = Int32GetDatum(ControlFile->minRecoveryPointTLI);
+ nulls[1] = false;
+
+ values[2] = LSNGetDatum(ControlFile->backupStartPoint);
+ nulls[2] = false;
+
+ values[3] = LSNGetDatum(ControlFile->backupEndPoint);
+ nulls[3] = false;
+
+ values[4] = BoolGetDatum(ControlFile->backupEndRequired);
+ nulls[4] = false;
+
+ htup = heap_form_tuple(tupdesc, values, nulls);
+
+ PG_RETURN_DATUM(HeapTupleGetDatum(htup));
+ }
+
+ Datum
+ pg_init_state(PG_FUNCTION_ARGS)
+ {
+ Datum values[13];
+ bool nulls[13];
+ TupleDesc tupdesc;
+ HeapTuple htup;
+ ControlFileData *ControlFile;
+
+ /*
+ * Construct a tuple descriptor for the result row. This must match this
+ * function's pg_proc entry!
+ */
+ tupdesc = CreateTemplateTupleDesc(13, false);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 1, "max_data_alignment",
+ INT4OID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 2, "database_block_size",
+ INT4OID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 3, "blocks_per_segment",
+ INT4OID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 4, "wal_block_size",
+ INT4OID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 5, "bytes_per_wal_segment",
+ INT4OID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 6, "max_identifier_length",
+ INT4OID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 7, "max_index_columns",
+ INT4OID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 8, "max_toast_chunk_size",
+ INT4OID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 9, "large_object_chunk_size",
+ INT4OID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 10, "bigint_timestamps",
+ BOOLOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 11, "float4_pass_by_value",
+ BOOLOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 12, "float8_pass_by_value",
+ BOOLOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 13, "data_page_checksum_version",
+ INT4OID, -1, 0);
+ tupdesc = BlessTupleDesc(tupdesc);
+
+ /* read the control file */
+ ControlFile = get_controlfile(DataDir, NULL);
+
+ if (ControlFile->pg_control_version % 65536 == 0 &&
+ ControlFile->pg_control_version / 65536 != 0)
+ elog(ERROR, _("byte ordering mismatch"));
+
+ values[0] = Int32GetDatum(ControlFile->maxAlign);
+ nulls[0] = false;
+
+ values[1] = Int32GetDatum(ControlFile->blcksz);
+ nulls[1] = false;
+
+ values[2] = Int32GetDatum(ControlFile->relseg_size);
+ nulls[2] = false;
+
+ values[3] = Int32GetDatum(ControlFile->xlog_blcksz);
+ nulls[3] = false;
+
+ values[4] = Int32GetDatum(ControlFile->xlog_seg_size);
+ nulls[4] = false;
+
+ values[5] = Int32GetDatum(ControlFile->nameDataLen);
+ nulls[5] = false;
+
+ values[6] = Int32GetDatum(ControlFile->indexMaxKeys);
+ nulls[6] = false;
+
+ values[7] = Int32GetDatum(ControlFile->toast_max_chunk_size);
+ nulls[7] = false;
+
+ values[8] = Int32GetDatum(ControlFile->loblksize);
+ nulls[8] = false;
+
+ values[9] = BoolGetDatum(ControlFile->enableIntTimes);
+ nulls[9] = false;
+
+ values[10] = BoolGetDatum(ControlFile->float4ByVal);
+ nulls[10] = false;
+
+ values[11] = BoolGetDatum(ControlFile->float8ByVal);
+ nulls[11] = false;
+
+ values[12] = Int32GetDatum(ControlFile->data_checksum_version);
+ nulls[12] = 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 e7e072f..75ed71b 100644
*** a/src/bin/pg_controldata/pg_controldata.c
--- b/src/bin/pg_controldata/pg_controldata.c
***************
*** 26,31 ****
--- 26,32 ----
#include "access/xlog.h"
#include "access/xlog_internal.h"
#include "catalog/pg_control.h"
+ #include "common/controldata_utils.h"
#include "pg_getopt.h"
*************** usage(const char *progname)
*** 45,108 ****
}
! 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)
! {
! switch (wal_level)
! {
! case WAL_LEVEL_MINIMAL:
! return "minimal";
! case WAL_LEVEL_ARCHIVE:
! return "archive";
! case WAL_LEVEL_HOT_STANDBY:
! return "hot_standby";
! case WAL_LEVEL_LOGICAL:
! return "logical";
! }
! return _("unrecognized wal_level");
! }
!
!
int
main(int argc, char *argv[])
{
! ControlFileData ControlFile;
! int fd;
! char ControlFilePath[MAXPGPATH];
! char *DataDir = NULL;
! pg_crc32c crc;
! time_t time_tmp;
! char pgctime_str[128];
! char ckpttime_str[128];
! char sysident_str[32];
! const char *strftime_fmt = "%c";
! const char *progname;
! XLogSegNo segno;
! char xlogfilename[MAXFNAMELEN];
! int c;
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_controldata"));
--- 46,62 ----
}
! #define CONTROLDATANAME_LEN 39
! #define CONTROLDATANAME_FMT "%-39s%s\n"
int
main(int argc, char *argv[])
{
! char *DataDir = NULL;
! controldata *ControlData;
! size_t ControlData_len;
! char ControlDataName[CONTROLDATANAME_LEN + 1];
! const char *progname;
! int c, i;
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_controldata"));
*************** main(int argc, char *argv[])
*** 161,338 ****
exit(1);
}
! snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);
!
! if ((fd = open(ControlFilePath, O_RDONLY | PG_BINARY, 0)) == -1)
! {
! fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
! progname, ControlFilePath, strerror(errno));
! exit(2);
! }
!
! if (read(fd, &ControlFile, sizeof(ControlFileData)) != sizeof(ControlFileData))
{
! fprintf(stderr, _("%s: could not read file \"%s\": %s\n"),
! progname, ControlFilePath, strerror(errno));
! exit(2);
}
- close(fd);
-
- /* Check the CRC. */
- INIT_CRC32C(crc);
- COMP_CRC32C(crc,
- (char *) &ControlFile,
- offsetof(ControlFileData, crc));
- FIN_CRC32C(crc);
-
- if (!EQ_CRC32C(crc, ControlFile.crc))
- printf(_("WARNING: Calculated CRC checksum does not match value stored in file.\n"
- "Either the file is corrupt, or it has a different layout than this program\n"
- "is expecting. The results below are untrustworthy.\n\n"));
-
- /*
- * This slightly-chintzy coding will work as long as the control file
- * timestamps are within the range of time_t; that should be the case in
- * all foreseeable circumstances, so we don't bother importing the
- * backend's timezone library into pg_controldata.
- *
- * Use variable for format to suppress overly-anal-retentive gcc warning
- * about %c
- */
- time_tmp = (time_t) ControlFile.time;
- strftime(pgctime_str, sizeof(pgctime_str), strftime_fmt,
- localtime(&time_tmp));
- time_tmp = (time_t) ControlFile.checkPointCopy.time;
- strftime(ckpttime_str, sizeof(ckpttime_str), strftime_fmt,
- localtime(&time_tmp));
-
- /*
- * Calculate name of the WAL file containing the latest checkpoint's REDO
- * start point.
- */
- XLByteToSeg(ControlFile.checkPointCopy.redo, segno);
- XLogFileName(xlogfilename, ControlFile.checkPointCopy.ThisTimeLineID, segno);
-
- /*
- * Format system_identifier separately to keep platform-dependent format
- * code out of the translatable message string.
- */
- snprintf(sysident_str, sizeof(sysident_str), UINT64_FORMAT,
- ControlFile.system_identifier);
- printf(_("pg_control version number: %u\n"),
- ControlFile.pg_control_version);
- if (ControlFile.pg_control_version % 65536 == 0 && ControlFile.pg_control_version / 65536 != 0)
- printf(_("WARNING: possible byte ordering mismatch\n"
- "The byte ordering used to store the pg_control file might not match the one\n"
- "used by this program. In that case the results below would be incorrect, and\n"
- "the PostgreSQL installation would be incompatible with this data directory.\n"));
- printf(_("Catalog version number: %u\n"),
- ControlFile.catalog_version_no);
- printf(_("Database system identifier: %s\n"),
- sysident_str);
- printf(_("Database cluster state: %s\n"),
- dbState(ControlFile.state));
- printf(_("pg_control last modified: %s\n"),
- pgctime_str);
- printf(_("Latest checkpoint location: %X/%X\n"),
- (uint32) (ControlFile.checkPoint >> 32),
- (uint32) ControlFile.checkPoint);
- printf(_("Prior checkpoint location: %X/%X\n"),
- (uint32) (ControlFile.prevCheckPoint >> 32),
- (uint32) ControlFile.prevCheckPoint);
- printf(_("Latest checkpoint's REDO location: %X/%X\n"),
- (uint32) (ControlFile.checkPointCopy.redo >> 32),
- (uint32) ControlFile.checkPointCopy.redo);
- printf(_("Latest checkpoint's REDO WAL file: %s\n"),
- xlogfilename);
- printf(_("Latest checkpoint's TimeLineID: %u\n"),
- ControlFile.checkPointCopy.ThisTimeLineID);
- printf(_("Latest checkpoint's PrevTimeLineID: %u\n"),
- ControlFile.checkPointCopy.PrevTimeLineID);
- printf(_("Latest checkpoint's full_page_writes: %s\n"),
- ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off"));
- printf(_("Latest checkpoint's NextXID: %u/%u\n"),
- ControlFile.checkPointCopy.nextXidEpoch,
- ControlFile.checkPointCopy.nextXid);
- printf(_("Latest checkpoint's NextOID: %u\n"),
- ControlFile.checkPointCopy.nextOid);
- printf(_("Latest checkpoint's NextMultiXactId: %u\n"),
- ControlFile.checkPointCopy.nextMulti);
- printf(_("Latest checkpoint's NextMultiOffset: %u\n"),
- ControlFile.checkPointCopy.nextMultiOffset);
- printf(_("Latest checkpoint's oldestXID: %u\n"),
- ControlFile.checkPointCopy.oldestXid);
- printf(_("Latest checkpoint's oldestXID's DB: %u\n"),
- ControlFile.checkPointCopy.oldestXidDB);
- printf(_("Latest checkpoint's oldestActiveXID: %u\n"),
- ControlFile.checkPointCopy.oldestActiveXid);
- printf(_("Latest checkpoint's oldestMultiXid: %u\n"),
- ControlFile.checkPointCopy.oldestMulti);
- printf(_("Latest checkpoint's oldestMulti's DB: %u\n"),
- ControlFile.checkPointCopy.oldestMultiDB);
- printf(_("Latest checkpoint's oldestCommitTsXid:%u\n"),
- ControlFile.checkPointCopy.oldestCommitTsXid);
- printf(_("Latest checkpoint's newestCommitTsXid:%u\n"),
- ControlFile.checkPointCopy.newestCommitTsXid);
- printf(_("Time of latest checkpoint: %s\n"),
- ckpttime_str);
- printf(_("Fake LSN counter for unlogged rels: %X/%X\n"),
- (uint32) (ControlFile.unloggedLSN >> 32),
- (uint32) ControlFile.unloggedLSN);
- printf(_("Minimum recovery ending location: %X/%X\n"),
- (uint32) (ControlFile.minRecoveryPoint >> 32),
- (uint32) ControlFile.minRecoveryPoint);
- printf(_("Min recovery ending loc's timeline: %u\n"),
- ControlFile.minRecoveryPointTLI);
- printf(_("Backup start location: %X/%X\n"),
- (uint32) (ControlFile.backupStartPoint >> 32),
- (uint32) ControlFile.backupStartPoint);
- printf(_("Backup end location: %X/%X\n"),
- (uint32) (ControlFile.backupEndPoint >> 32),
- (uint32) ControlFile.backupEndPoint);
- printf(_("End-of-backup record required: %s\n"),
- ControlFile.backupEndRequired ? _("yes") : _("no"));
- printf(_("wal_level setting: %s\n"),
- wal_level_str(ControlFile.wal_level));
- printf(_("wal_log_hints setting: %s\n"),
- ControlFile.wal_log_hints ? _("on") : _("off"));
- printf(_("max_connections setting: %d\n"),
- ControlFile.MaxConnections);
- printf(_("max_worker_processes setting: %d\n"),
- ControlFile.max_worker_processes);
- printf(_("max_prepared_xacts setting: %d\n"),
- ControlFile.max_prepared_xacts);
- printf(_("max_locks_per_xact setting: %d\n"),
- ControlFile.max_locks_per_xact);
- printf(_("track_commit_timestamp setting: %s\n"),
- ControlFile.track_commit_timestamp ? _("on") : _("off"));
- printf(_("Maximum data alignment: %u\n"),
- ControlFile.maxAlign);
- /* we don't print floatFormat since can't say much useful about it */
- printf(_("Database block size: %u\n"),
- ControlFile.blcksz);
- printf(_("Blocks per segment of large relation: %u\n"),
- ControlFile.relseg_size);
- printf(_("WAL block size: %u\n"),
- ControlFile.xlog_blcksz);
- printf(_("Bytes per WAL segment: %u\n"),
- ControlFile.xlog_seg_size);
- printf(_("Maximum length of identifiers: %u\n"),
- ControlFile.nameDataLen);
- printf(_("Maximum columns in an index: %u\n"),
- ControlFile.indexMaxKeys);
- printf(_("Maximum size of a TOAST chunk: %u\n"),
- ControlFile.toast_max_chunk_size);
- printf(_("Size of a large-object chunk: %u\n"),
- ControlFile.loblksize);
- printf(_("Date/time type storage: %s\n"),
- (ControlFile.enableIntTimes ? _("64-bit integers") : _("floating-point numbers")));
- printf(_("Float4 argument passing: %s\n"),
- (ControlFile.float4ByVal ? _("by value") : _("by reference")));
- printf(_("Float8 argument passing: %s\n"),
- (ControlFile.float8ByVal ? _("by value") : _("by reference")));
- printf(_("Data page checksum version: %u\n"),
- ControlFile.data_checksum_version);
return 0;
}
--- 115,128 ----
exit(1);
}
! ControlData = get_controldata(DataDir, progname, &ControlData_len);
! for (i = 0; i < ControlData_len; i++)
{
! memset(ControlDataName, ' ', CONTROLDATANAME_LEN);
! snprintf (ControlDataName, CONTROLDATANAME_LEN,
! "%s:", ControlData[i].name);
! printf(CONTROLDATANAME_FMT, ControlDataName, ControlData[i].setting);
}
return 0;
}
diff --git a/src/bin/pg_resetxlog/pg_resetxlog.c b/src/bin/pg_resetxlog/pg_resetxlog.c
index f675c92..642ec54 100644
*** a/src/bin/pg_resetxlog/pg_resetxlog.c
--- b/src/bin/pg_resetxlog/pg_resetxlog.c
*************** PrintControlValues(bool guessed)
*** 646,652 ****
ControlFile.checkPointCopy.ThisTimeLineID);
printf(_("Latest checkpoint's full_page_writes: %s\n"),
ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off"));
! printf(_("Latest checkpoint's NextXID: %u/%u\n"),
ControlFile.checkPointCopy.nextXidEpoch,
ControlFile.checkPointCopy.nextXid);
printf(_("Latest checkpoint's NextOID: %u\n"),
--- 646,652 ----
ControlFile.checkPointCopy.ThisTimeLineID);
printf(_("Latest checkpoint's full_page_writes: %s\n"),
ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off"));
! printf(_("Latest checkpoint's NextXID: %u:%u\n"),
ControlFile.checkPointCopy.nextXidEpoch,
ControlFile.checkPointCopy.nextXid);
printf(_("Latest checkpoint's NextOID: %u\n"),
diff --git a/src/common/Makefile b/src/common/Makefile
index c47445e..5d04a6b 100644
*** a/src/common/Makefile
--- b/src/common/Makefile
*************** include $(top_builddir)/src/Makefile.glo
*** 23,30 ****
override CPPFLAGS := -DFRONTEND $(CPPFLAGS)
LIBS += $(PTHREAD_LIBS)
! OBJS_COMMON = exec.o pg_lzcompress.o pgfnames.o psprintf.o relpath.o \
! rmtree.o string.o username.o wait_error.o
OBJS_FRONTEND = $(OBJS_COMMON) fe_memutils.o restricted_token.o
--- 23,30 ----
override CPPFLAGS := -DFRONTEND $(CPPFLAGS)
LIBS += $(PTHREAD_LIBS)
! OBJS_COMMON = controldata_utils.o exec.o pg_lzcompress.o pgfnames.o \
! psprintf.o relpath.o rmtree.o string.o username.o wait_error.o
OBJS_FRONTEND = $(OBJS_COMMON) fe_memutils.o restricted_token.o
diff --git a/src/common/controldata_utils.c b/src/common/controldata_utils.c
index ...f7b12c8 .
*** a/src/common/controldata_utils.c
--- b/src/common/controldata_utils.c
***************
*** 0 ****
--- 1,378 ----
+ /*-------------------------------------------------------------------------
+ *
+ * controldata_utils.c
+ * Common code for pg_controldata output
+ *
+ *
+ * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/common/controldata_utils.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+ #include "postgres.h"
+
+ #include <unistd.h>
+ #include <time.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>
+
+ #include "miscadmin.h"
+ #include "access/xlog.h"
+ #include "access/xlog_internal.h"
+ #include "catalog/pg_control.h"
+ #include "catalog/pg_type.h"
+ #include "common/controldata_utils.h"
+ #include "port/pg_crc32c.h"
+ #include "utils/builtins.h"
+
+ #ifndef FRONTEND
+ /* NOTE: caller must provide gettext call around str */
+ #define log_error(str, param1, param2) \
+ elog(ERROR, str, param1, param2)
+ #else
+ #define log_error(str, param1, param2) \
+ do { \
+ char *buf = psprintf("%%s: %s", str); \
+ fprintf(stderr, buf, progname, param1, param2); \
+ exit(2); \
+ } while (0)
+ #endif
+
+ static const char *dbState(DBState state);
+ static const char *wal_level_str(WalLevel wal_level);
+
+ static const char *const ControlDataNames[] =
+ {
+ gettext_noop("pg_control version number"),
+ gettext_noop("Catalog version number"),
+ gettext_noop("Database system identifier"),
+ gettext_noop("Database cluster state"),
+ gettext_noop("pg_control last modified"),
+ gettext_noop("Latest checkpoint location"),
+ gettext_noop("Prior checkpoint location"),
+ gettext_noop("Latest checkpoint's REDO location"),
+ gettext_noop("Latest checkpoint's REDO WAL file"),
+ gettext_noop("Latest checkpoint's TimeLineID"),
+ gettext_noop("Latest checkpoint's PrevTimeLineID"),
+ gettext_noop("Latest checkpoint's full_page_writes"),
+ gettext_noop("Latest checkpoint's NextXID"),
+ gettext_noop("Latest checkpoint's NextOID"),
+ gettext_noop("Latest checkpoint's NextMultiXactId"),
+ gettext_noop("Latest checkpoint's NextMultiOffset"),
+ gettext_noop("Latest checkpoint's oldestXID"),
+ gettext_noop("Latest checkpoint's oldestXID's DB"),
+ gettext_noop("Latest checkpoint's oldestActiveXID"),
+ gettext_noop("Latest checkpoint's oldestMultiXid"),
+ gettext_noop("Latest checkpoint's oldestMulti's DB"),
+ gettext_noop("Latest checkpoint's oldestCommitTsXid"),
+ gettext_noop("Latest checkpoint's newestCommitTsXid"),
+ gettext_noop("Time of latest checkpoint"),
+ gettext_noop("Fake LSN counter for unlogged rels"),
+ gettext_noop("Minimum recovery ending location"),
+ gettext_noop("Min recovery ending loc's timeline"),
+ gettext_noop("Backup start location"),
+ gettext_noop("Backup end location"),
+ gettext_noop("End-of-backup record required"),
+ gettext_noop("wal_level setting"),
+ gettext_noop("wal_log_hints setting"),
+ gettext_noop("max_connections setting"),
+ gettext_noop("max_worker_processes setting"),
+ gettext_noop("max_prepared_xacts setting"),
+ gettext_noop("max_locks_per_xact setting"),
+ gettext_noop("track_commit_timestamp setting"),
+ gettext_noop("Maximum data alignment"),
+ gettext_noop("Database block size"),
+ gettext_noop("Blocks per segment of large relation"),
+ gettext_noop("WAL block size"),
+ gettext_noop("Bytes per WAL segment"),
+ gettext_noop("Maximum length of identifiers"),
+ gettext_noop("Maximum columns in an index"),
+ gettext_noop("Maximum size of a TOAST chunk"),
+ gettext_noop("Size of a large-object chunk"),
+ gettext_noop("Date/time type storage"),
+ gettext_noop("Float4 argument passing"),
+ gettext_noop("Float8 argument passing"),
+ gettext_noop("Data page checksum version"),
+ NULL
+ };
+
+ static size_t
+ ControlDataNames_len(void)
+ {
+ size_t i = 0;
+
+ while (ControlDataNames[i])
+ i++;
+
+ return i;
+ }
+
+
+ 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)
+ {
+ switch (wal_level)
+ {
+ case WAL_LEVEL_MINIMAL:
+ return "minimal";
+ case WAL_LEVEL_ARCHIVE:
+ return "archive";
+ case WAL_LEVEL_HOT_STANDBY:
+ return "hot_standby";
+ case WAL_LEVEL_LOGICAL:
+ return "logical";
+ }
+ return _("unrecognized wal_level");
+ }
+
+
+ ControlFileData *
+ get_controlfile(char *DataDir, const char *progname)
+ {
+ ControlFileData *ControlFile;
+ int fd;
+ char ControlFilePath[MAXPGPATH];
+ pg_crc32c crc;
+
+ ControlFile = palloc(sizeof(ControlFileData));
+ snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);
+
+ if ((fd = open(ControlFilePath, O_RDONLY | PG_BINARY, 0)) == -1)
+ log_error(_("could not open file \"%s\" for reading: %s"),
+ ControlFilePath, strerror(errno));
+
+ if (read(fd, ControlFile, sizeof(ControlFileData)) != sizeof(ControlFileData))
+ log_error(_("could not read file \"%s\": %s"),
+ ControlFilePath, strerror(errno));
+
+ close(fd);
+
+ /* Check the CRC. */
+ INIT_CRC32C(crc);
+ COMP_CRC32C(crc,
+ (char *) ControlFile,
+ offsetof(ControlFileData, crc));
+ FIN_CRC32C(crc);
+
+ if (!EQ_CRC32C(crc, ControlFile->crc))
+ #ifndef FRONTEND
+ elog(ERROR, _("calculated CRC checksum does not match value stored in file"));
+ #else
+ printf(_("WARNING: Calculated CRC checksum does not match value stored in file.\n"
+ "Either the file is corrupt, or it has a different layout than this program\n"
+ "is expecting. The results below are untrustworthy.\n\n"));
+ #endif
+
+ return ControlFile;
+ }
+
+ controldata *
+ get_controldata(char *DataDir, const char *progname,
+ size_t *controldata_len)
+ {
+ ControlFileData *ControlFile;
+ controldata *ControlData;
+ time_t time_tmp;
+ char pgctime_str[128];
+ char ckpttime_str[128];
+ char sysident_str[32];
+ const char *strftime_fmt = "%c";
+ XLogSegNo segno;
+ char xlogfilename[MAXFNAMELEN];
+ int i;
+ int idx = 0;
+
+ *controldata_len = ControlDataNames_len();
+ ControlData = palloc(*controldata_len * sizeof(controldata));
+
+ /*
+ * initialize controldata names
+ *
+ * These better be in sync with the settings manually
+ * defined below.
+ */
+ for (i = 0; i < *controldata_len; i++)
+ ControlData[i].name = pstrdup(_(ControlDataNames[i]));
+
+ /* get a copy of the control file */
+ ControlFile = get_controlfile(DataDir, progname);
+
+ /*
+ * This slightly-chintzy coding will work as long as the control file
+ * timestamps are within the range of time_t; that should be the case in
+ * all foreseeable circumstances, so we don't bother importing the
+ * backend's timezone library.
+ *
+ * Use variable for format to suppress overly-anal-retentive gcc warning
+ * about %c
+ */
+ time_tmp = (time_t) ControlFile->time;
+ strftime(pgctime_str, sizeof(pgctime_str), strftime_fmt,
+ localtime(&time_tmp));
+ time_tmp = (time_t) ControlFile->checkPointCopy.time;
+ strftime(ckpttime_str, sizeof(ckpttime_str), strftime_fmt,
+ localtime(&time_tmp));
+
+ /*
+ * Calculate name of the WAL file containing the latest checkpoint's REDO
+ * start point.
+ */
+ XLByteToSeg(ControlFile->checkPointCopy.redo, segno);
+ XLogFileName(xlogfilename, ControlFile->checkPointCopy.ThisTimeLineID, segno);
+
+ /*
+ * Format system_identifier separately to keep platform-dependent format
+ * code out of the translatable message string.
+ */
+ snprintf(sysident_str, sizeof(sysident_str), UINT64_FORMAT,
+ ControlFile->system_identifier);
+
+ if (ControlFile->pg_control_version % 65536 == 0 &&
+ ControlFile->pg_control_version / 65536 != 0)
+ #ifndef FRONTEND
+ elog(ERROR, _("byte ordering mismatch"));
+ #else
+ printf(_("WARNING: possible byte ordering mismatch\n"
+ "The byte ordering used to store the pg_control file might not match the one\n"
+ "used by this program. In that case the results below would be incorrect, and\n"
+ "the PostgreSQL installation would be incompatible with this data directory.\n"));
+ #endif
+
+ ControlData[idx++].setting = psprintf("%u",
+ ControlFile->pg_control_version);
+ ControlData[idx++].setting = psprintf("%u",
+ ControlFile->catalog_version_no);
+ ControlData[idx++].setting = psprintf("%s",
+ sysident_str);
+ ControlData[idx++].setting = psprintf("%s",
+ dbState(ControlFile->state));
+ ControlData[idx++].setting = psprintf("%s",
+ pgctime_str);
+ ControlData[idx++].setting = psprintf("%X/%X",
+ (uint32) (ControlFile->checkPoint >> 32),
+ (uint32) ControlFile->checkPoint);
+ ControlData[idx++].setting = psprintf("%X/%X",
+ (uint32) (ControlFile->prevCheckPoint >> 32),
+ (uint32) ControlFile->prevCheckPoint);
+ ControlData[idx++].setting = psprintf("%X/%X",
+ (uint32) (ControlFile->checkPointCopy.redo >> 32),
+ (uint32) ControlFile->checkPointCopy.redo);
+ ControlData[idx++].setting = psprintf("%s", xlogfilename);
+ ControlData[idx++].setting = psprintf("%u",
+ ControlFile->checkPointCopy.ThisTimeLineID);
+ ControlData[idx++].setting = psprintf("%u",
+ ControlFile->checkPointCopy.PrevTimeLineID);
+ ControlData[idx++].setting = psprintf("%s",
+ ControlFile->checkPointCopy.fullPageWrites ? _("on") : _("off"));
+ ControlData[idx++].setting = psprintf("%u:%u",
+ ControlFile->checkPointCopy.nextXidEpoch,
+ ControlFile->checkPointCopy.nextXid);
+ ControlData[idx++].setting = psprintf("%u",
+ ControlFile->checkPointCopy.nextOid);
+ ControlData[idx++].setting = psprintf("%u",
+ ControlFile->checkPointCopy.nextMulti);
+ ControlData[idx++].setting = psprintf("%u",
+ ControlFile->checkPointCopy.nextMultiOffset);
+ ControlData[idx++].setting = psprintf("%u",
+ ControlFile->checkPointCopy.oldestXid);
+ ControlData[idx++].setting = psprintf("%u",
+ ControlFile->checkPointCopy.oldestXidDB);
+ ControlData[idx++].setting = psprintf("%u",
+ ControlFile->checkPointCopy.oldestActiveXid);
+ ControlData[idx++].setting = psprintf("%u",
+ ControlFile->checkPointCopy.oldestMulti);
+ ControlData[idx++].setting = psprintf("%u",
+ ControlFile->checkPointCopy.oldestMultiDB);
+ ControlData[idx++].setting = psprintf("%u",
+ ControlFile->checkPointCopy.oldestCommitTsXid);
+ ControlData[idx++].setting = psprintf("%u",
+ ControlFile->checkPointCopy.newestCommitTsXid);
+ ControlData[idx++].setting = psprintf("%s", ckpttime_str);
+ ControlData[idx++].setting = psprintf("%X/%X",
+ (uint32) (ControlFile->unloggedLSN >> 32),
+ (uint32) ControlFile->unloggedLSN);
+ ControlData[idx++].setting = psprintf("%X/%X",
+ (uint32) (ControlFile->minRecoveryPoint >> 32),
+ (uint32) ControlFile->minRecoveryPoint);
+ ControlData[idx++].setting = psprintf("%u",
+ ControlFile->minRecoveryPointTLI);
+ ControlData[idx++].setting = psprintf("%X/%X",
+ (uint32) (ControlFile->backupStartPoint >> 32),
+ (uint32) ControlFile->backupStartPoint);
+ ControlData[idx++].setting = psprintf("%X/%X",
+ (uint32) (ControlFile->backupEndPoint >> 32),
+ (uint32) ControlFile->backupEndPoint);
+ ControlData[idx++].setting = psprintf("%s",
+ ControlFile->backupEndRequired ? _("yes") : _("no"));
+ ControlData[idx++].setting = psprintf("%s",
+ wal_level_str(ControlFile->wal_level));
+ ControlData[idx++].setting = psprintf("%s",
+ ControlFile->wal_log_hints ? _("on") : _("off"));
+ ControlData[idx++].setting = psprintf("%d",
+ ControlFile->MaxConnections);
+ ControlData[idx++].setting = psprintf("%d",
+ ControlFile->max_worker_processes);
+ ControlData[idx++].setting = psprintf("%d",
+ ControlFile->max_prepared_xacts);
+ ControlData[idx++].setting = psprintf("%d",
+ ControlFile->max_locks_per_xact);
+ ControlData[idx++].setting = psprintf("%s",
+ ControlFile->track_commit_timestamp ? _("on") : _("off"));
+ ControlData[idx++].setting = psprintf("%u",
+ ControlFile->maxAlign);
+ ControlData[idx++].setting = psprintf("%u",
+ ControlFile->blcksz);
+ ControlData[idx++].setting = psprintf("%u",
+ ControlFile->relseg_size);
+ ControlData[idx++].setting = psprintf("%u",
+ ControlFile->xlog_blcksz);
+ ControlData[idx++].setting = psprintf("%u",
+ ControlFile->xlog_seg_size);
+ ControlData[idx++].setting = psprintf("%u",
+ ControlFile->nameDataLen);
+ ControlData[idx++].setting = psprintf("%u",
+ ControlFile->indexMaxKeys);
+ ControlData[idx++].setting = psprintf("%u",
+ ControlFile->toast_max_chunk_size);
+ ControlData[idx++].setting = psprintf("%u",
+ ControlFile->loblksize);
+ ControlData[idx++].setting = psprintf("%s",
+ (ControlFile->enableIntTimes ?
+ _("64-bit integers") : _("floating-point numbers")));
+ ControlData[idx++].setting = psprintf("%s",
+ (ControlFile->float4ByVal ? _("by value") : _("by reference")));
+ ControlData[idx++].setting = psprintf("%s",
+ (ControlFile->float8ByVal ? _("by value") : _("by reference")));
+ ControlData[idx++].setting = psprintf("%u",
+ ControlFile->data_checksum_version);
+
+ return ControlData;
+ }
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index d8640db..6923136 100644
*** a/src/include/catalog/pg_proc.h
--- b/src/include/catalog/pg_proc.h
*************** DESCR("get an individual replication ori
*** 5337,5342 ****
--- 5337,5355 ----
DATA(insert OID = 6014 ( pg_show_replication_origin_status PGNSP PGUID 12 1 100 0 0 f f f f f t v r 0 0 2249 "" "{26,25,3220,3220}" "{o,o,o,o}" "{local_id, external_id, remote_lsn, local_lsn}" _null_ _null_ pg_show_replication_origin_status _null_ _null_ _null_ ));
DESCR("get progress for all replication origins");
+ /* pg_controldata related functions */
+ DATA(insert OID = 3331 ( pg_controldata_state PGNSP PGUID 12 1 0 0 0 f f f f t f v s 0 0 2249 "" "{23,23,20,1184}" "{o,o,o,o}" "{pg_control_version,catalog_version_no,system_identifier,pg_control_last_modified}" _null_ _null_ pg_controldata_state _null_ _null_ _null_ ));
+ DESCR("pg_controldata general state information as a function");
+
+ DATA(insert OID = 3332 ( pg_checkpoint_state PGNSP PGUID 12 1 0 0 0 f f f f t f v s 0 0 2249 "" "{3220,3220,3220,25,23,23,16,25,26,28,28,28,26,28,28,26,28,28,1184}" "{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{checkpoint_location,prior_location,redo_location,redo_wal_file,timeline_id,prev_timeline_id,full_page_writes,next_xid,next_oid,next_multixact_id,next_multi_offset,oldest_xid,oldest_xid_dbid,oldest_active_xid,oldest_multi_xid,oldest_multi_dbid,oldest_commit_ts_xid,newest_commit_ts_xid,checkpoint_time}" _null_ _null_ pg_checkpoint_state _null_ _null_ _null_ ));
+ DESCR("pg_controldata checkpoint state information as a function");
+
+ DATA(insert OID = 3333 ( pg_recovery_state PGNSP PGUID 12 1 0 0 0 f f f f t f v s 0 0 2249 "" "{3220,23,3220,3220,16}" "{o,o,o,o,o}" "{min_recovery_end_location,min_recovery_end_timeline,backup_start_location,backup_end_location,end_of_backup_record_required}" _null_ _null_ pg_recovery_state _null_ _null_ _null_ ));
+ DESCR("pg_controldata recovery state information as a function");
+
+ DATA(insert OID = 3334 ( pg_init_state PGNSP PGUID 12 1 0 0 0 f f f f t f v s 0 0 2249 "" "{23,23,23,23,23,23,23,23,23,16,16,16,23}" "{o,o,o,o,o,o,o,o,o,o,o,o,o}" "{max_data_alignment,database_block_size,blocks_per_segment,wal_block_size,bytes_per_wal_segment,max_identifier_length,max_index_columns,max_toast_chunk_size,large_object_chunk_size,bigint_timestamps,float4_pass_by_value,float8_pass_by_value,data_page_checksum_version}" _null_ _null_ pg_init_state _null_ _null_ _null_ ));
+ DESCR("pg_controldata init state information as a function");
+
/*
* Symbolic values for provolatile column: these indicate whether the result
* of a function is dependent *only* on the values of its explicit arguments,
diff --git a/src/include/common/controldata_utils.h b/src/include/common/controldata_utils.h
index ...70989ef .
*** a/src/include/common/controldata_utils.h
--- b/src/include/common/controldata_utils.h
***************
*** 0 ****
--- 1,23 ----
+ /*
+ * controldata_utils.h
+ * Common code for pg_controldata output
+ *
+ * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/controldata_utils.h
+ */
+ #ifndef COMMON_CONTROLDATA_UTILS_H
+ #define COMMON_CONTROLDATA_UTILS_H
+
+ typedef struct controldata
+ {
+ char *name;
+ char *setting;
+ } controldata;
+
+ extern ControlFileData *get_controlfile(char *DataDir, const char *progname);
+ extern controldata *get_controldata(char *DataDir, const char *progname,
+ size_t *controldata_len);
+
+ #endif /* COMMON_CONTROLDATA_UTILS_H */
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index e610bf3..f977279 100644
*** a/src/include/utils/builtins.h
--- b/src/include/utils/builtins.h
*************** extern Datum set_config_by_name(PG_FUNCT
*** 1123,1128 ****
--- 1123,1134 ----
extern Datum show_all_settings(PG_FUNCTION_ARGS);
extern Datum show_all_file_settings(PG_FUNCTION_ARGS);
+ /* pg_controldata.c */
+ extern Datum pg_controldata_state(PG_FUNCTION_ARGS);
+ extern Datum pg_checkpoint_state(PG_FUNCTION_ARGS);
+ extern Datum pg_recovery_state(PG_FUNCTION_ARGS);
+ extern Datum pg_init_state(PG_FUNCTION_ARGS);
+
/* rls.c */
extern Datum row_security_active(PG_FUNCTION_ARGS);
extern Datum row_security_active_name(PG_FUNCTION_ARGS);
signature.asc
Description: OpenPGP digital signature
