On Mon, 27 Aug 2018 21:05:33 +0900
Yugo Nagata <nag...@sraoss.co.jp> wrote:

> On Mon, 27 Aug 2018 13:34:12 +0200
> Michael Banck <michael.ba...@credativ.de> wrote:
> 
> > Hi,
> > 
> > On Mon, Aug 27, 2018 at 07:53:36PM +0900, Yugo Nagata wrote:
> > > On Fri, 24 Aug 2018 18:01:09 +0200
> > > Peter Eisentraut <peter.eisentr...@2ndquadrant.com> wrote:
> > > > I'm curious about this option:
> > > > 
> > > >   -r RELFILENODE         check only relation with specified relfilenode
> > > > 
> > > > but there is no facility to specify a database.
> > > > 
> > > > Also, referring to the relfilenode of a mapped relation seems a bit
> > > > inaccurate.
> > > > 
> > > > Maybe reframing this in terms of the file name of the file you want
> > > > checked would be better?
> > > 
> > > If we specified 1234 to -r option, pg_verify_shceksums checks not only 
> > > 1234
> > > but also 1234_vm, 1234_fsm, and 1234.1, 1234.2, ... and so on, so I think
> > > it makes senses to allow to specify a relfilenode instead of a file name.
> > > 
> > > I think it is reasonable to add a option to specify a database, although
> > > I don't know which character is good because both -d and -D are already 
> > > used....
> > 
> > Maybe the -d (debug) option should be revisited as well. Mentioning
> > every scanned block generates a huge amount of output which might be
> > useful during development but does not seem very useful for a stable
> > release. AFAICT there is no other debug output for now.
> > 
> > So it could be renamed to -v (verbose) and only mention each scanned
> > file, e.g. (errors/checksum mismatches are still reported of course).
> > 
> > Then -d could (in the future, I guess that is too late for v11) be used
> > for -d/--dbname (or make that only a long option, if the above does not
> > work).
> 
> I realized after sending the previous post that we can not specify a database
> by name because pg_verify_checksum is run in offline and this can not get the
> OID from the database name.  Also, there are global and pg_tblspc directories
> not only base/<database OID>. So, it seems to me good to specify a directories
> to scan which is under PGDATA. We would be able to use -d ( or --directory ?)
> for this purpose.

Attached is a patch to allow pg_verity_checksums to specify a database
to scan.  This is usefule for users who want to verify checksums of relations
in a specific database. We can specify a database by OID using -d or --dboid 
option.
Also, when -g or --global-only is used only shared relations are scaned.

Regards,
-- 
Yugo Nagata <nag...@sraoss.co.jp>
>From 99135eec747b0f115b8fbdbf092c85808a70da85 Mon Sep 17 00:00:00 2001
From: Yugo Nagata <nag...@sraoss.co.jp>
Date: Thu, 30 Aug 2018 18:48:00 +0900
Subject: [PATCH] Allow pg_verify_checksums to specify a database to scan

---
 doc/src/sgml/ref/pg_verify_checksums.sgml     | 20 +++++++++++
 .../pg_verify_checksums/pg_verify_checksums.c | 35 ++++++++++++++++---
 2 files changed, 51 insertions(+), 4 deletions(-)

diff --git a/doc/src/sgml/ref/pg_verify_checksums.sgml b/doc/src/sgml/ref/pg_verify_checksums.sgml
index 3a3433b1c8..782cf35ca0 100644
--- a/doc/src/sgml/ref/pg_verify_checksums.sgml
+++ b/doc/src/sgml/ref/pg_verify_checksums.sgml
@@ -70,6 +70,26 @@ PostgreSQL documentation
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term><option>-d <replaceable>oid</replaceable></option></term>
+      <term><option>--dboid=<replaceable>oid</replaceable></option></term>
+      <listitem>
+       <para>
+        Only validate checksums in the relations in the database with specified OID.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>-g</option></term>
+      <term><option>--globel-only</option></term>
+      <listitem>
+       <para>
+        Only validate checksums in the relations in the shared database.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term><option>-r <replaceable>relfilenode</replaceable></option></term>
       <listitem>
diff --git a/src/bin/pg_verify_checksums/pg_verify_checksums.c b/src/bin/pg_verify_checksums/pg_verify_checksums.c
index 1eb3bed2b9..0b9c03ac30 100644
--- a/src/bin/pg_verify_checksums/pg_verify_checksums.c
+++ b/src/bin/pg_verify_checksums/pg_verify_checksums.c
@@ -31,6 +31,8 @@ static int64 badblocks = 0;
 static ControlFileData *ControlFile;
 
 static char *only_relfilenode = NULL;
+static char *only_dboid = NULL;
+static bool only_global = false;
 static bool verbose = false;
 
 static const char *progname;
@@ -44,6 +46,8 @@ usage()
 	printf(_("\nOptions:\n"));
 	printf(_(" [-D, --pgdata=]DATADIR  data directory\n"));
 	printf(_("  -v, --verbose          output verbose messages, list all checked files\n"));
+	printf(_("  -d, --dboid=OID        check only relations in database with specified OID\n"));
+	printf(_("  -g, --global-only      check only shared relations\n"));
 	printf(_("  -r RELFILENODE         check only relation with specified relfilenode\n"));
 	printf(_("  -V, --version          output version information, then exit\n"));
 	printf(_("  -?, --help             show this help, then exit\n"));
@@ -198,7 +202,13 @@ scan_directory(char *basedir, char *subdir)
 #else
 		else if (S_ISDIR(st.st_mode) || pgwin32_is_junction(fn))
 #endif
+		{
+			if (atoi(de->d_name) != 0 && strcmp(subdir, "pg_tblspc") &&
+				only_dboid && strcmp(only_dboid, de->d_name) != 0)
+				continue;
+
 			scan_directory(path, de->d_name);
+		}
 	}
 	closedir(dir);
 }
@@ -208,6 +218,8 @@ main(int argc, char *argv[])
 {
 	static struct option long_options[] = {
 		{"pgdata", required_argument, NULL, 'D'},
+		{"dboid", required_argument, NULL, 'd'},
+		{"global-only", no_argument, NULL, 'g'},
 		{"verbose", no_argument, NULL, 'v'},
 		{NULL, 0, NULL, 0}
 	};
@@ -235,7 +247,7 @@ main(int argc, char *argv[])
 		}
 	}
 
-	while ((c = getopt_long(argc, argv, "D:r:v", long_options, &option_index)) != -1)
+	while ((c = getopt_long(argc, argv, "D:r:d:gv", long_options, &option_index)) != -1)
 	{
 		switch (c)
 		{
@@ -253,6 +265,17 @@ main(int argc, char *argv[])
 				}
 				only_relfilenode = pstrdup(optarg);
 				break;
+			case 'd':
+				if (atoi(optarg) <= 0)
+				{
+					fprintf(stderr, _("%s: invalid database oid specification, must be numeric: %s\n"), progname, optarg);
+					exit(1);
+				}
+				only_dboid = pstrdup(optarg);
+				break;
+			case 'g':
+				only_global = true;
+				break;
 			default:
 				fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
 				exit(1);
@@ -307,9 +330,13 @@ main(int argc, char *argv[])
 	}
 
 	/* Scan all files */
-	scan_directory(DataDir, "global");
-	scan_directory(DataDir, "base");
-	scan_directory(DataDir, "pg_tblspc");
+	if (!only_dboid)
+		scan_directory(DataDir, "global");
+	if (!only_global)
+	{
+		scan_directory(DataDir, "base");
+		scan_directory(DataDir, "pg_tblspc");
+	}
 
 	printf(_("Checksum scan completed\n"));
 	printf(_("Data checksum version: %d\n"), ControlFile->data_checksum_version);
-- 
2.17.1

Reply via email to