version number from the current database, and couldn't find any existing
program to do that.
-The attached utility produces this output:
+The attached utility produces output like this:
-linda:~$ pg_controldata
-Log file id: 0
-Log file segment: 5
-Last modified: Wed Feb 7 19:35:47 2001
+$ pg_controldata
+pg_control version number: 71
+Catalog version number: 200101061
+Database state: IN_PRODUCTION
+pg_control last modified: Sat Mar 10 00:07:55 2001
+Current log file id: 0
+Next log file segment: 9
+Latest checkpoint location: 0/88CAA20
+Prior checkpoint location: 0/70A5D48
+Latest checkpoint's REDO location: 0/88CAA20
+Latest checkpoint's UNDO location: 0/0
+Latest checkpoint's StartUpID: 22
+Latest checkpoint's NextXID: 4711
+Latest checkpoint's NextOID: 444704
+Time of latest checkpoint: Sat Mar 10 00:07:52 2001
Database block size: 8192
Blocks per segment of large relation: 131072
-Catalog version number: 200101061
-LC_COLLATE: en_GB
-LC_CTYPE: en_GB
-Log archive directory:
+LC_COLLATE: C
+LC_CTYPE: C
+
+
+To access the pg_control file, the program must be run as the Postgres user,
+and PGDATA must be set correctly in its environment.
--
Oliver Elphick <olly@lfix.co.uk>
-/* pg_controldata
+/*
+ * pg_controldata
*
* reads the data from $PGDATA/global/pg_control
*
* copyright (c) Oliver Elphick <olly@lfix.co.uk>, 2001;
* licence: BSD
*
-*/
+ * $Header: /cvsroot/pgsql/contrib/pg_controldata/Attic/pg_controldata.c,v 1.2 2001/03/13 01:17:40 tgl Exp $
+ */
+#include "postgres.h"
-#include <stdio.h>
-#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include "catalog/pg_control.h"
-typedef unsigned int uint32;
-
-#include "config.h"
-#include "access/xlogdefs.h"
-
-/*
- * #include "access/xlog.h"
- * #include "c.h"
- */
-
-/* The following definitions are extracted from access/xlog.h and its
- * recursive includes. There is too much initialisation needed if
- * they are included direct. Perhaps someone more knowledgeable can
- * fix that.
- */
-typedef struct crc64
-{
- uint32 crc1;
- uint32 crc2;
-} crc64;
-
-#define LOCALE_NAME_BUFLEN 128
-typedef enum DBState
+static const char *
+dbState(DBState state)
{
- DB_STARTUP = 0,
- DB_SHUTDOWNED,
- DB_SHUTDOWNING,
- DB_IN_RECOVERY,
- DB_IN_PRODUCTION
-} DBState;
+ switch (state)
+ {
+ case DB_STARTUP:
+ return "STARTUP";
+ case DB_SHUTDOWNED:
+ return "SHUTDOWNED";
+ case DB_SHUTDOWNING:
+ return "SHUTDOWNING";
+ case DB_IN_RECOVERY:
+ return "IN_RECOVERY";
+ case DB_IN_PRODUCTION:
+ return "IN_PRODUCTION";
+ }
+ return "unrecognized status code";
+}
-typedef struct ControlFileData
+int
+main()
{
- crc64 crc;
- uint32 logId; /* current log file id */
- uint32 logSeg; /* current log file segment (1-based) */
- struct
- XLogRecPtr checkPoint; /* last check point record ptr */
- time_t time; /* time stamp of last modification */
- DBState state; /* see enum above */
-
- /*
- * this data is used to make sure that configuration of this DB is
- * compatible with the backend executable
- */
- uint32 blcksz; /* block size for this DB */
- uint32 relseg_size; /* blocks per segment of large relation */
- uint32 catalog_version_no; /* internal version number */
- /* active locales --- "C" if compiled without USE_LOCALE: */
- char lc_collate[LOCALE_NAME_BUFLEN];
- char lc_ctype[LOCALE_NAME_BUFLEN];
-
- /*
- * important directory locations
- */
- char archdir[MAXPGPATH]; /* where to move offline log files */
-} ControlFileData;
-
-int main() {
ControlFileData ControlFile;
int fd;
char ControlFilePath[MAXPGPATH];
char *DataDir;
- char tmdt[32];
+ crc64 crc;
+ char pgctime_str[32];
+ char ckpttime_str[32];
DataDir = getenv("PGDATA");
if ( DataDir == NULL ) {
snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);
- if ((fd = open(ControlFilePath, O_RDONLY)) == -1) {
+ if ((fd = open(ControlFilePath, O_RDONLY)) == -1)
+ {
perror("Failed to open $PGDATA/global/pg_control for reading");
exit(2);
}
- read(fd, &ControlFile, sizeof(ControlFileData));
- strftime(tmdt, 32, "%c", localtime(&(ControlFile.time)));
-
- printf("Log file id: %u\n"
- "Log file segment: %u\n"
- "Last modified: %s\n"
- "Database block size: %u\n"
- "Blocks per segment of large relation: %u\n"
- "Catalog version number: %u\n"
- "LC_COLLATE: %s\n"
- "LC_CTYPE: %s\n"
- "Log archive directory: %s\n",
- ControlFile.logId,
- ControlFile.logSeg,
- tmdt,
- ControlFile.blcksz,
- ControlFile.relseg_size,
- ControlFile.catalog_version_no,
- ControlFile.lc_collate,
- ControlFile.lc_ctype,
- ControlFile.archdir);
-
+ if (read(fd, &ControlFile, sizeof(ControlFileData)) != sizeof(ControlFileData))
+ {
+ perror("Failed to read $PGDATA/global/pg_control");
+ exit(2);
+ }
+ close(fd);
+
+ /* Check the CRC. */
+ INIT_CRC64(crc);
+ COMP_CRC64(crc,
+ (char*) &ControlFile + sizeof(crc64),
+ sizeof(ControlFileData) - sizeof(crc64));
+ FIN_CRC64(crc);
+
+ if (!EQ_CRC64(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");
+
+ strftime(pgctime_str, 32, "%c",
+ localtime(&(ControlFile.time)));
+ strftime(ckpttime_str, 32, "%c",
+ localtime(&(ControlFile.checkPointCopy.time)));
+
+ printf("pg_control version number: %u\n"
+ "Catalog version number: %u\n"
+ "Database state: %s\n"
+ "pg_control last modified: %s\n"
+ "Current log file id: %u\n"
+ "Next log file segment: %u\n"
+ "Latest checkpoint location: %X/%X\n"
+ "Prior checkpoint location: %X/%X\n"
+ "Latest checkpoint's REDO location: %X/%X\n"
+ "Latest checkpoint's UNDO location: %X/%X\n"
+ "Latest checkpoint's StartUpID: %u\n"
+ "Latest checkpoint's NextXID: %u\n"
+ "Latest checkpoint's NextOID: %u\n"
+ "Time of latest checkpoint: %s\n"
+ "Database block size: %u\n"
+ "Blocks per segment of large relation: %u\n"
+ "LC_COLLATE: %s\n"
+ "LC_CTYPE: %s\n",
+
+ ControlFile.pg_control_version,
+ ControlFile.catalog_version_no,
+ dbState(ControlFile.state),
+ pgctime_str,
+ ControlFile.logId,
+ ControlFile.logSeg,
+ ControlFile.checkPoint.xlogid,
+ ControlFile.checkPoint.xrecoff,
+ ControlFile.prevCheckPoint.xlogid,
+ ControlFile.prevCheckPoint.xrecoff,
+ ControlFile.checkPointCopy.redo.xlogid,
+ ControlFile.checkPointCopy.redo.xrecoff,
+ ControlFile.checkPointCopy.undo.xlogid,
+ ControlFile.checkPointCopy.undo.xrecoff,
+ ControlFile.checkPointCopy.ThisStartUpID,
+ ControlFile.checkPointCopy.nextXid,
+ ControlFile.checkPointCopy.nextOid,
+ ckpttime_str,
+ ControlFile.blcksz,
+ ControlFile.relseg_size,
+ ControlFile.lc_collate,
+ ControlFile.lc_ctype);
+
return (0);
}
-