⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pg_resetxlog.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * pg_resetxlog.c *	  A utility to "zero out" the xlog when it's corrupt beyond recovery. *	  Can also rebuild pg_control if needed. * * The theory of operation is fairly simple: *	  1. Read the existing pg_control (which will include the last *		 checkpoint record).  If it is an old format then update to *		 current format. *	  2. If pg_control is corrupt, attempt to intuit reasonable values, *		 by scanning the old xlog if necessary. *	  3. Modify pg_control to reflect a "shutdown" state with a checkpoint *		 record at the start of xlog. *	  4. Flush the existing xlog files and write a new segment with *		 just a checkpoint record in it.  The new segment is positioned *		 just past the end of the old xlog, so that existing LSNs in *		 data pages will appear to be "in the past". * This is all pretty straightforward except for the intuition part of * step 2 ... * * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * $PostgreSQL: pgsql/src/bin/pg_resetxlog/pg_resetxlog.c,v 1.38 2005/10/15 02:49:40 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include <dirent.h>#include <fcntl.h>#include <locale.h>#include <sys/stat.h>#include <sys/time.h>#include <time.h>#include <unistd.h>#ifdef HAVE_GETOPT_H#include <getopt.h>#endif#include "access/multixact.h"#include "access/xlog.h"#include "access/xlog_internal.h"#include "catalog/catversion.h"#include "catalog/pg_control.h"extern int	optind;extern char *optarg;static ControlFileData ControlFile;		/* pg_control values */static uint32 newXlogId,			newXlogSeg;			/* ID/Segment of new XLOG segment */static bool guessed = false;	/* T if we had to guess at any values */static const char *progname;static bool ReadControlFile(void);static void GuessControlValues(void);static void PrintControlValues(bool guessed);static void RewriteControlFile(void);static void KillExistingXLOG(void);static void WriteEmptyXLOG(void);static void usage(void);intmain(int argc, char *argv[]){	int			c;	bool		force = false;	bool		noupdate = false;	TransactionId set_xid = 0;	Oid			set_oid = 0;	MultiXactId set_mxid = 0;	MultiXactOffset set_mxoff = -1;	uint32		minXlogTli = 0,				minXlogId = 0,				minXlogSeg = 0;	char	   *endptr;	char	   *endptr2;	char	   *endptr3;	char	   *DataDir;	int			fd;	char		path[MAXPGPATH];	set_pglocale_pgservice(argv[0], "pg_resetxlog");	progname = get_progname(argv[0]);	if (argc > 1)	{		if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)		{			usage();			exit(0);		}		if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)		{			puts("pg_resetxlog (PostgreSQL) " PG_VERSION);			exit(0);		}	}	while ((c = getopt(argc, argv, "fl:m:no:O:x:")) != -1)	{		switch (c)		{			case 'f':				force = true;				break;			case 'n':				noupdate = true;				break;			case 'x':				set_xid = strtoul(optarg, &endptr, 0);				if (endptr == optarg || *endptr != '\0')				{					fprintf(stderr, _("%s: invalid argument for option -x\n"), progname);					fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);					exit(1);				}				if (set_xid == 0)				{					fprintf(stderr, _("%s: transaction ID (-x) must not be 0\n"), progname);					exit(1);				}				break;			case 'o':				set_oid = strtoul(optarg, &endptr, 0);				if (endptr == optarg || *endptr != '\0')				{					fprintf(stderr, _("%s: invalid argument for option -o\n"), progname);					fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);					exit(1);				}				if (set_oid == 0)				{					fprintf(stderr, _("%s: OID (-o) must not be 0\n"), progname);					exit(1);				}				break;			case 'm':				set_mxid = strtoul(optarg, &endptr, 0);				if (endptr == optarg || *endptr != '\0')				{					fprintf(stderr, _("%s: invalid argument for option -m\n"), progname);					fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);					exit(1);				}				if (set_mxid == 0)				{					fprintf(stderr, _("%s: multitransaction ID (-m) must not be 0\n"), progname);					exit(1);				}				break;			case 'O':				set_mxoff = strtoul(optarg, &endptr, 0);				if (endptr == optarg || *endptr != '\0')				{					fprintf(stderr, _("%s: invalid argument for option -O\n"), progname);					fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);					exit(1);				}				if (set_mxoff == -1)				{					fprintf(stderr, _("%s: multitransaction offset (-O) must not be -1\n"), progname);					exit(1);				}				break;			case 'l':				minXlogTli = strtoul(optarg, &endptr, 0);				if (endptr == optarg || *endptr != ',')				{					fprintf(stderr, _("%s: invalid argument for option -l\n"), progname);					fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);					exit(1);				}				minXlogId = strtoul(endptr + 1, &endptr2, 0);				if (endptr2 == endptr + 1 || *endptr2 != ',')				{					fprintf(stderr, _("%s: invalid argument for option -l\n"), progname);					fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);					exit(1);				}				minXlogSeg = strtoul(endptr2 + 1, &endptr3, 0);				if (endptr3 == endptr2 + 1 || *endptr3 != '\0')				{					fprintf(stderr, _("%s: invalid argument for option -l\n"), progname);					fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);					exit(1);				}				break;			default:				fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);				exit(1);		}	}	if (optind == argc)	{		fprintf(stderr, _("%s: no data directory specified\n"), progname);		fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);		exit(1);	}	/*	 * Don't allow pg_resetxlog to be run as root, to avoid overwriting the	 * ownership of files in the data directory. We need only check for root	 * -- any other user won't have sufficient permissions to modify files in	 * the data directory.	 */#ifndef WIN32#ifndef __BEOS__				/* no root check on BeOS */	if (geteuid() == 0)	{		fprintf(stderr, _("%s: cannot be executed by \"root\"\n"),				progname);		fprintf(stderr, _("You must run %s as the PostgreSQL superuser.\n"),				progname);		exit(1);	}#endif#endif	DataDir = argv[optind];	if (chdir(DataDir) < 0)	{		fprintf(stderr, _("%s: could not change directory to \"%s\": %s\n"),				progname, DataDir, strerror(errno));		exit(1);	}	/*	 * Check for a postmaster lock file --- if there is one, refuse to	 * proceed, on grounds we might be interfering with a live installation.	 */	snprintf(path, MAXPGPATH, "%s/postmaster.pid", DataDir);	if ((fd = open(path, O_RDONLY)) < 0)	{		if (errno != ENOENT)		{			fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"), progname, path, strerror(errno));			exit(1);		}	}	else	{		fprintf(stderr, _("%s: lock file \"%s\" exists\n"						  "Is a server running?  If not, delete the lock file and try again.\n"),				progname, path);		exit(1);	}	/*	 * Attempt to read the existing pg_control file	 */	if (!ReadControlFile())		GuessControlValues();	/*	 * Adjust fields if required by switches.  (Do this now so that printout,	 * if any, includes these values.)	 */	if (set_xid != 0)		ControlFile.checkPointCopy.nextXid = set_xid;	if (set_oid != 0)		ControlFile.checkPointCopy.nextOid = set_oid;	if (set_mxid != 0)		ControlFile.checkPointCopy.nextMulti = set_mxid;	if (set_mxoff != -1)		ControlFile.checkPointCopy.nextMultiOffset = set_mxoff;	if (minXlogTli > ControlFile.checkPointCopy.ThisTimeLineID)		ControlFile.checkPointCopy.ThisTimeLineID = minXlogTli;	if (minXlogId > ControlFile.logId ||		(minXlogId == ControlFile.logId &&		 minXlogSeg > ControlFile.logSeg))	{		ControlFile.logId = minXlogId;		ControlFile.logSeg = minXlogSeg;	}	/*	 * If we had to guess anything, and -f was not given, just print the	 * guessed values and exit.  Also print if -n is given.	 */	if ((guessed && !force) || noupdate)	{		PrintControlValues(guessed);		if (!noupdate)		{			printf(_("\nIf these values seem acceptable, use -f to force reset.\n"));			exit(1);		}		else			exit(0);	}	/*	 * Don't reset from a dirty pg_control without -f, either.	 */	if (ControlFile.state != DB_SHUTDOWNED && !force)	{		printf(_("The database server was not shut down cleanly.\n"				 "Resetting the transaction log may cause data to be lost.\n"				 "If you want to proceed anyway, use -f to force reset.\n"));		exit(1);	}	/*	 * Else, do the dirty deed.	 */	RewriteControlFile();	KillExistingXLOG();	WriteEmptyXLOG();	printf(_("Transaction log reset\n"));	return 0;}/* * Try to read the existing pg_control file. * * This routine is also responsible for updating old pg_control versions * to the current format.  (Currently we don't do anything of the sort.) */static boolReadControlFile(void){	int			fd;	int			len;	char	   *buffer;	pg_crc32	crc;	if ((fd = open(XLOG_CONTROL_FILE, O_RDONLY)) < 0)	{		/*		 * If pg_control is not there at all, or we can't read it, the odds		 * are we've been handed a bad DataDir path, so give up. User can do		 * "touch pg_control" to force us to proceed.		 */		fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),				progname, XLOG_CONTROL_FILE, strerror(errno));		if (errno == ENOENT)			fprintf(stderr, _("If you are sure the data directory path is correct, execute\n"							  "  touch %s\n"							  "and try again.\n"),					XLOG_CONTROL_FILE);		exit(1);	}	/* Use malloc to ensure we have a maxaligned buffer */	buffer = (char *) malloc(BLCKSZ);	len = read(fd, buffer, BLCKSZ);	if (len < 0)	{		fprintf(stderr, _("%s: could not read file \"%s\": %s\n"),				progname, XLOG_CONTROL_FILE, strerror(errno));		exit(1);	}	close(fd);	if (len >= sizeof(ControlFileData) &&	  ((ControlFileData *) buffer)->pg_control_version == PG_CONTROL_VERSION)	{		/* Check the CRC. */		INIT_CRC32(crc);		COMP_CRC32(crc,				   buffer,				   offsetof(ControlFileData, crc));		FIN_CRC32(crc);		if (EQ_CRC32(crc, ((ControlFileData *) buffer)->crc))		{			/* Valid data... */			memcpy(&ControlFile, buffer, sizeof(ControlFile));			return true;		}		fprintf(stderr, _("%s: pg_control exists but has invalid CRC; proceed with caution\n"),				progname);		/* We will use the data anyway, but treat it as guessed. */		memcpy(&ControlFile, buffer, sizeof(ControlFile));		guessed = true;		return true;	}	/* Looks like it's a mess. */	fprintf(stderr, _("%s: pg_control exists but is broken or unknown version; ignoring it\n"),

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -