Update for new pg_control format.
authorTom Lane
Tue, 13 Mar 2001 01:17:40 +0000 (01:17 +0000)
committerTom Lane
Tue, 13 Mar 2001 01:17:40 +0000 (01:17 +0000)
contrib/pg_controldata/Makefile
contrib/pg_controldata/README.pg_controldata
contrib/pg_controldata/pg_controldata.c

index 77a1880dd1b6592491600966be2d03405ac9d5be..f9ffe40080c58c319c9af1d4e8fc4d2730e34dd3 100644 (file)
@@ -1,20 +1,21 @@
 #
-# $Header: /cvsroot/pgsql/contrib/pg_controldata/Attic/Makefile,v 1.2 2001/02/25 15:57:45 petere Exp $
+# $Header: /cvsroot/pgsql/contrib/pg_controldata/Attic/Makefile,v 1.3 2001/03/13 01:17:40 tgl Exp $
 #
 
 subdir = contrib/pg_controldata
 top_builddir = ../..
 include $(top_builddir)/src/Makefile.global
 
-override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS)
-
-OBJS   = pg_controldata.o
+OBJS   = pg_controldata.o pg_crc.o
 
 all: pg_controldata
 
 pg_controldata: $(OBJS)
    $(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) $(LIBS) -o $@
 
+pg_crc.c: $(top_builddir)/src/backend/utils/hash/pg_crc.c
+   rm -f $@ && $(LN_S) $< .
+
 install: all installdirs
    $(INSTALL_PROGRAM) pg_controldata$(X)   $(bindir)
    $(INSTALL_DATA) README.pg_controldata   $(docdir)/contrib
@@ -26,7 +27,7 @@ uninstall:
    rm -f $(bindir)/pg_controldata$(X) $(docdir)/contrib/README.pg_controldata
 
 clean distclean maintainer-clean:
-   rm -f pg_controldata$(X) $(OBJS)
+   rm -f pg_controldata$(X) $(OBJS) pg_crc.c
 
 depend dep:
    $(CC) -MM -MG $(CFLAGS) *.c > depend
index e1c4192cfea90f01f627b9a63dfbbe4d5775edea..85ca0e1467a7a81373f3669549a2a2242703de0e 100644 (file)
@@ -2,18 +2,31 @@ I had a need to read such things as the backend locale and the catalog
 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                 
index 9cd148f6f4863e2ff29f4fdc971ab8c0499da5aa..dc666c1fcf29d12952e4a8bc95eef6dc79378523 100644 (file)
@@ -1,87 +1,54 @@
-/* pg_controldata
+/*
+ * pg_controldata
  *
  * reads the data from $PGDATA/global/pg_control
  *
  * copyright (c) Oliver Elphick , 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 
-#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 
+#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 ) {
@@ -91,33 +58,77 @@ int main() {
 
    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);
 }
-