summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorJoe Conway2016-03-05 19:10:19 +0000
committerJoe Conway2016-03-05 19:10:19 +0000
commitdc7d70ea05deca9dfc6a25043d406b57cc8f6c30 (patch)
tree227bb6a01ec3a15386b29d22d64bc90e92a9b1f9 /src/common
parentd34794f7d5566effd342dd0ebaca3de3b48656f0 (diff)
Expose control file data via SQL accessible functions.
Add four new SQL accessible functions: pg_control_system(), pg_control_checkpoint(), pg_control_recovery(), and pg_control_init() which expose a subset of the control file data. Along the way move the code to read and validate the control file to src/common, where it can be shared by the new backend functions and the original pg_controldata frontend program. Patch by me, significant input, testing, and review by Michael Paquier.
Diffstat (limited to 'src/common')
-rw-r--r--src/common/Makefile4
-rw-r--r--src/common/controldata_utils.c100
2 files changed, 102 insertions, 2 deletions
diff --git a/src/common/Makefile b/src/common/Makefile
index bde4fc25975..f7a4a4d099a 100644
--- a/src/common/Makefile
+++ b/src/common/Makefile
@@ -36,8 +36,8 @@ override CPPFLAGS += -DVAL_LDFLAGS_EX="\"$(LDFLAGS_EX)\""
override CPPFLAGS += -DVAL_LDFLAGS_SL="\"$(LDFLAGS_SL)\""
override CPPFLAGS += -DVAL_LIBS="\"$(LIBS)\""
-OBJS_COMMON = config_info.o exec.o pg_lzcompress.o pgfnames.o psprintf.o \
- relpath.o rmtree.o string.o username.o wait_error.o
+OBJS_COMMON = config_info.o 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
new file mode 100644
index 00000000000..b6d0a128f7f
--- /dev/null
+++ b/src/common/controldata_utils.c
@@ -0,0 +1,100 @@
+/*-------------------------------------------------------------------------
+ *
+ * controldata_utils.c
+ * Common code for control data file output.
+ *
+ *
+ * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/common/controldata_utils.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "catalog/pg_control.h"
+#include "common/controldata_utils.h"
+#include "port/pg_crc32c.h"
+
+#ifndef FRONTEND
+/* NOTE: caller must provide gettext call around the format string */
+#define log_error(...) \
+ elog(ERROR, __VA_ARGS__)
+#else
+#define log_error(...) \
+ do { \
+ char *buf = psprintf(__VA_ARGS__); \
+ fprintf(stderr, "%s: %s\n", progname, buf); \
+ exit(2); \
+ } while (0)
+#endif
+
+/*
+ * get_controlfile(char *DataDir, const char *progname)
+ *
+ * Get controlfile values. The caller is responsible
+ * for pfreeing the result.
+ */
+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
+
+ /* Make sure the control file is valid byte order. */
+ 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
+
+ return ControlFile;
+}