TODO: machine-readable pg_controldata

Started by Dilip kumarabout 12 years ago1 messages
#1Dilip kumar
dilip.kumar@huawei.com
1 attachment(s)

Below attached patch is implementing following todo item..
machine-readable pg_controldata?
/messages/by-id/4B901D73.8030003@agliodbs.com
Possible approaches:

1. Implement as backend function and provide a view to user.

- But In this approach user can only get this information when server is running.

2. Extend pg_controldata tool to provide value of an individual attribute.

A first draft version of the patch is attached in the mail, implemented using approach 2.

Description of the patch:

1. Below is the list of the option which are exposed by pg_controldata (all checkpoint, redo and backup related options are exposed).
I think we don't need to expose options for other parameters, because they will not be useful for using independently. (user can simply print all values same as old behavior)

-v, --catalog-version catalog version
-l, --latest-chcekpoint-loc Latest checkpoint location
-L, --prev-chcekpoint-loc Prior checkpoint location
-r, --latest-checkpoint-redoloc Latest checkpoint's REDO location
-t, --latest-checkpoint-timeline Latest checkpoint's TimeLineID
-T, --latest-checkpoint-prevtimeline Latest checkpoint's PrevTimeLineID
-c, --latest-checkpoint-time Time of latest checkpoint
-x, --latest-checkpoint-nextxid Latest checkpoint's NextXID
-o, --latest-checkpoint-nextoid Latest Latest checkpoint's NextOID
-X, --latest-checkpoint-nextmulti-xactid Latest checkpoint's NextMultiXactId
-O, --latest-checkpoint-nextmulti-offset Latest checkpoint's NextMultiOffset
-q, --latest-checkpoint-oldestxid Latest checkpoint's oldestXID
-a, --latest-checkpoint-oldest-activexid Latest checkpoint's oldestActiveXID
-m, --latest-checkpoint-oldest-multixid Latest checkpoint's oldestMultiXid
-e, --min-recovery-endloc Minimum recovery ending location
-E, --min-recovery-endloc-timeline Min recovery ending loc's timeline
-b, --backup-start-location Backup start location
-B, --backup-end-location Backup end location

2. If user provide individual option, then direct value of that parameter will be printed (as shown in below example), parameter name is not printed as output so that user need not to parse the output.

./pg_controldata --latest-checkpoint-time -- run with latest-checkpoint-time option
Tue 07 Jan 2014 05:22:42 PM IST --output is direct value

3. This feature can save parsing effort for user where user need to get the value of individual parameter

i.e Time of latest checkpoint for Standby lag monitoring.

Please provide your suggestion...

Regards,
Dilip

Attachments:

controldata_v1.patchapplication/octet-stream; name=controldata_v1.patchDownload
*** 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 "getopt_long.h"
  
  
  static void
***************
*** 35,44 **** usage(const char *progname)
  	printf(_("Usage:\n"));
  	printf(_("  %s [OPTION] [DATADIR]\n"), progname);
  	printf(_("\nOptions:\n"));
! 	printf(_("  -V, --version  output version information, then exit\n"));
! 	printf(_("  -?, --help     show this help, then exit\n"));
  	printf(_("\nIf no data directory (DATADIR) is specified, "
  			 "the environment variable PGDATA\nis used.\n\n"));
  	printf(_("Report bugs to <pgsql-bugs@postgresql.org>.\n"));
  }
  
--- 36,68 ----
  	printf(_("Usage:\n"));
  	printf(_("  %s [OPTION] [DATADIR]\n"), progname);
  	printf(_("\nOptions:\n"));
! 	printf(_("  -V, --version  output version information\n"));
! 	printf(_("  -?, --help     show this help\n"));
! 	printf(_("  -v, --catalog-version                      catalog version \n"));
! 	printf(_("  -l, --latest-chcekpoint-loc                Latest checkpoint location\n"));
! 	printf(_("  -L, --prev-chcekpoint-loc                  Prior checkpoint location\n"));
! 	printf(_("  -r, --latest-checkpoint-redoloc            Latest checkpoint's REDO location\n"));
! 	printf(_("  -t, --latest-checkpoint-timeline           Latest checkpoint's TimeLineID\n"));
! 	printf(_("  -T, --latest-checkpoint-prevtimeline       Latest checkpoint's PrevTimeLineID\n"));
! 	printf(_("  -c, --latest-checkpoint-time               Time of latest checkpoint\n"));
! 	printf(_("  -x, --latest-checkpoint-nextxid            Latest checkpoint's NextXID \n"));
! 	printf(_("  -o, --latest-checkpoint-nextoid            Latest Latest checkpoint's NextOID \n"));
! 	printf(_("  -X, --latest-checkpoint-nextmulti-xactid   Latest checkpoint's NextMultiXactId   \n"));
! 	printf(_("  -O, --latest-checkpoint-nextmulti-offset   Latest checkpoint's NextMultiOffset \n"));
! 	printf(_("  -q, --latest-checkpoint-oldestxid          Latest checkpoint's oldestXID \n"));
! 	printf(_("  -a, --latest-checkpoint-oldest-activexid   Latest checkpoint's oldestActiveXID \n"));
! 	printf(_("  -m, --latest-checkpoint-oldest-multixid    Latest checkpoint's oldestMultiXid \n"));
! 	printf(_("  -e, --min-recovery-endloc                  Minimum recovery ending location \n"));
! 	printf(_("  -E, --min-recovery-endloc-timeline         Min recovery ending loc's timeline \n"));
! 	printf(_("  -b, --backup-start-location                Backup start location \n"));
! 	printf(_("  -B, --backup-end-location                  Backup end location \n"));
! 
  	printf(_("\nIf no data directory (DATADIR) is specified, "
  			 "the environment variable PGDATA\nis used.\n\n"));
+ 	printf(_("\nMax one option is supported at a time, if no option specified "
+ 	  		 "then all information\nwill be printed\n\n"));
+ 	printf(_("\nIf invalid control option is given then it will be ignored, "
+ 			"and all information\nwill be printed\n\n"));
  	printf(_("Report bugs to <pgsql-bugs@postgresql.org>.\n"));
  }
  
***************
*** 90,96 **** main(int argc, char *argv[])
  	ControlFileData ControlFile;
  	int			fd;
  	char		ControlFilePath[MAXPGPATH];
! 	char	   *DataDir;
  	pg_crc32	crc;
  	time_t		time_tmp;
  	char		pgctime_str[128];
--- 114,120 ----
  	ControlFileData ControlFile;
  	int			fd;
  	char		ControlFilePath[MAXPGPATH];
! 	char	   *DataDir = NULL;
  	pg_crc32	crc;
  	time_t		time_tmp;
  	char		pgctime_str[128];
***************
*** 100,105 **** main(int argc, char *argv[])
--- 124,153 ----
  	const char *progname;
  	XLogSegNo	segno;
  	char		xlogfilename[MAXFNAMELEN];
+ 	int			optindex;
+ 	int			c;
+ 
+ 	static struct option long_options[] = {
+ 		{"catalog-version", no_argument, NULL, 'v'},
+ 		{"latest-chcekpoint-loc", no_argument, NULL, 'l'},
+ 		{"prev-chcekpoint-loc", no_argument, NULL, 'L'},
+ 		{"latest-checkpoint-redoloc", no_argument, NULL, 'r'},
+ 		{"latest-checkpoint-timeline", no_argument, NULL, 't'},
+ 		{"latest-checkpoint-prevtimeline", no_argument, NULL, 'T'},
+ 		{"latest-checkpoint-time", no_argument, NULL, 'c'},
+ 		{"latest-checkpoint-nextxid", no_argument, NULL, 'x'},
+ 		{"latest-checkpoint-nextoid", no_argument, NULL, 'o'},
+ 		{"latest-checkpoint-nextmulti-xactid", no_argument, NULL, 'X'},
+ 		{"latest-checkpoint-nextmulti-offset", no_argument, NULL, 'O'},
+ 		{"latest-checkpoint-oldestxid", no_argument, NULL, 'q'},
+ 		{"latest-checkpoint-oldest-activexid", no_argument, NULL, 'a'},
+ 		{"latest-checkpoint-oldest-multixid", no_argument, NULL, 'm'},
+ 		{"min-recovery-endloc", no_argument, NULL, 'e'},
+ 		{"min-recovery-endloc-timeline", no_argument, NULL, 'E'},
+ 		{"backup-start-location", no_argument, NULL, 'b'},
+ 		{"backup-end-location", no_argument, NULL, 'B'},
+ 		{NULL, 0, NULL, 0}
+ 	};
  
  	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_controldata"));
  
***************
*** 119,128 **** main(int argc, char *argv[])
  		}
  	}
  
! 	if (argc > 1)
! 		DataDir = argv[1];
! 	else
  		DataDir = getenv("PGDATA");
  	if (DataDir == NULL)
  	{
  		fprintf(stderr, _("%s: no data directory specified\n"), progname);
--- 167,191 ----
  		}
  	}
  
! 	if (argc > 2)
! 	{
! 		c = getopt_long(argc, argv, "abBceElLmoOqrtTvxX", long_options, &optindex);
! 		DataDir = argv[2];
! 	}
! 	else if (argc == 2)
! 	{
! 		c = getopt_long(argc, argv, "abBceElLmoOqrtTvxX", long_options, &optindex);
! 		if (c == -1)
! 		{
! 			DataDir = argv[1];
! 		}
! 	}
! 
! 	if (!DataDir)
! 	{
  		DataDir = getenv("PGDATA");
+ 	}
+ 
  	if (DataDir == NULL)
  	{
  		fprintf(stderr, _("%s: no data directory specified\n"), progname);
***************
*** 189,194 **** main(int argc, char *argv[])
--- 252,364 ----
  	snprintf(sysident_str, sizeof(sysident_str), UINT64_FORMAT,
  			 ControlFile.system_identifier);
  
+ 	switch (c)
+ 	{
+ 		case 'v':
+ 			printf(("%u\n"),
+ 		   			ControlFile.catalog_version_no);
+ 			return 0;
+ 
+ 		case 'l':
+ 			printf("%X/%X\n",
+ 				   (uint32) (ControlFile.checkPoint >> 32),
+ 				   (uint32) ControlFile.checkPoint);
+ 			return 0;
+ 
+ 		case 'L':
+ 			printf("%X/%X\n",
+ 				   (uint32) (ControlFile.prevCheckPoint >> 32),
+ 				   (uint32) ControlFile.prevCheckPoint);
+ 			return 0;
+ 
+ 		case 'r':
+ 			printf("%X/%X\n",
+ 				   (uint32) (ControlFile.checkPointCopy.redo >> 32),
+ 				   (uint32) ControlFile.checkPointCopy.redo);
+ 			return 0;
+ 
+ 		case 't':
+ 			printf("%u\n",
+ 				   ControlFile.checkPointCopy.ThisTimeLineID);
+ 			return 0;
+ 
+ 		case 'T':
+ 
+ 			printf("%u\n",
+ 				   ControlFile.checkPointCopy.PrevTimeLineID);
+ 			return 0;
+ 
+ 		case 'c':
+ 			printf("%s\n", ckpttime_str);
+ 			return 0;
+ 
+ 		case 'x':
+ 			printf("%u/%u\n",
+ 				   ControlFile.checkPointCopy.nextXidEpoch,
+ 				   ControlFile.checkPointCopy.nextXid);
+ 			return 0;
+ 
+ 		case 'o':
+ 			printf("%u\n",
+ 				   ControlFile.checkPointCopy.nextOid);
+ 			return 0;
+ 
+ 		case 'X':
+ 			printf("%u\n",
+ 				   ControlFile.checkPointCopy.nextMulti);
+ 
+ 			return 0;
+ 
+ 		case 'O':
+ 			printf("%u\n",
+ 				   ControlFile.checkPointCopy.nextMultiOffset);
+ 
+ 			return 0;
+ 
+ 		case 'q':
+ 			printf("%u\n",
+ 				   ControlFile.checkPointCopy.oldestXid);
+ 
+ 			return 0;
+ 
+ 		case 'a':
+ 			printf("%u\n",
+ 				   ControlFile.checkPointCopy.oldestActiveXid);
+ 
+ 			return 0;
+ 
+ 		case 'm':
+ 			printf("%u\n",
+ 				   ControlFile.checkPointCopy.oldestMulti);
+ 
+ 			return 0;
+ 
+ 		case 'e':
+ 			printf("%X/%X\n",
+ 				   (uint32) (ControlFile.minRecoveryPoint >> 32),
+ 				   (uint32) ControlFile.minRecoveryPoint);
+ 
+ 			return 0;
+ 
+ 		case 'E':
+ 			printf("%u\n", ControlFile.minRecoveryPointTLI);
+ 			return 0;
+ 
+ 		case 'b':
+ 			printf("%X/%X\n",
+ 				   (uint32) (ControlFile.backupStartPoint >> 32),
+ 				   (uint32) ControlFile.backupStartPoint);
+ 
+ 			return 0;
+ 
+ 		case 'B':
+ 			printf("%X/%X\n",
+ 				   (uint32) (ControlFile.backupEndPoint >> 32),
+ 				   (uint32) ControlFile.backupEndPoint);
+ 
+ 			return 0;
+ 	}
+ 
  	printf(_("pg_control version number:            %u\n"),
  		   ControlFile.pg_control_version);
  	if (ControlFile.pg_control_version % 65536 == 0 && ControlFile.pg_control_version / 65536 != 0)