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

📄 pg_backup_archiver.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
		newToc->nDeps = 0;	}	newToc->dataDumper = dumpFn;	newToc->dataDumperArg = dumpArg;	newToc->hadDumper = dumpFn ? true : false;	newToc->formatData = NULL;	if (AH->ArchiveEntryPtr !=NULL)		(*AH->ArchiveEntryPtr) (AH, newToc);}/* Public */voidPrintTOCSummary(Archive *AHX, RestoreOptions *ropt){	ArchiveHandle *AH = (ArchiveHandle *) AHX;	TocEntry   *te = AH->toc->next;	OutputContext sav;	char	   *fmtName;	if (ropt->filename)		sav = SetOutput(AH, ropt->filename, 0 /* no compression */ );	ahprintf(AH, ";\n; Archive created at %s", ctime(&AH->createDate));	ahprintf(AH, ";     dbname: %s\n;     TOC Entries: %d\n;     Compression: %d\n",			 AH->archdbname, AH->tocCount, AH->compression);	switch (AH->format)	{		case archFiles:			fmtName = "FILES";			break;		case archCustom:			fmtName = "CUSTOM";			break;		case archTar:			fmtName = "TAR";			break;		default:			fmtName = "UNKNOWN";	}	ahprintf(AH, ";     Dump Version: %d.%d-%d\n", AH->vmaj, AH->vmin, AH->vrev);	ahprintf(AH, ";     Format: %s\n", fmtName);	ahprintf(AH, ";     Integer: %d bytes\n", (int) AH->intSize);	ahprintf(AH, ";     Offset: %d bytes\n", (int) AH->offSize);	if (AH->archiveRemoteVersion)		ahprintf(AH, ";     Dumped from database version: %s\n",				 AH->archiveRemoteVersion);	if (AH->archiveDumpVersion)		ahprintf(AH, ";     Dumped by pg_dump version: %s\n",				 AH->archiveDumpVersion);	ahprintf(AH, ";\n;\n; Selected TOC Entries:\n;\n");	while (te != AH->toc)	{		if (_tocEntryRequired(te, ropt, true) != 0)			ahprintf(AH, "%d; %u %u %s %s %s %s\n", te->dumpId,					 te->catalogId.tableoid, te->catalogId.oid,					 te->desc, te->namespace ? te->namespace : "-",					 te->tag, te->owner);		te = te->next;	}	if (ropt->filename)		ResetOutput(AH, sav);}/*********** * BLOB Archival ***********//* Called by a dumper to signal start of a BLOB */intStartBlob(Archive *AHX, Oid oid){	ArchiveHandle *AH = (ArchiveHandle *) AHX;	if (!AH->StartBlobPtr)		die_horribly(AH, modulename, "large-object output not supported in chosen format\n");	(*AH->StartBlobPtr) (AH, AH->currToc, oid);	return 1;}/* Called by a dumper to signal end of a BLOB */intEndBlob(Archive *AHX, Oid oid){	ArchiveHandle *AH = (ArchiveHandle *) AHX;	if (AH->EndBlobPtr)		(*AH->EndBlobPtr) (AH, AH->currToc, oid);	return 1;}/********** * BLOB Restoration **********//* * Called by a format handler before any blobs are restored */voidStartRestoreBlobs(ArchiveHandle *AH){	if (AH->connection)		StartTransaction(AH);	else		ahprintf(AH, "BEGIN;\n\n");	AH->blobCount = 0;}/* * Called by a format handler after all blobs are restored */voidEndRestoreBlobs(ArchiveHandle *AH){	if (AH->connection)		CommitTransaction(AH);	else		ahprintf(AH, "COMMIT;\n\n");	ahlog(AH, 1, "restored %d large objects\n", AH->blobCount);}/* * Called by a format handler to initiate restoration of a blob */voidStartRestoreBlob(ArchiveHandle *AH, Oid oid){	Oid			loOid;	AH->blobCount++;	/* Initialize the LO Buffer */	AH->lo_buf_used = 0;	ahlog(AH, 2, "restoring large object with OID %u\n", oid);	if (AH->connection)	{		loOid = lo_create(AH->connection, oid);		if (loOid == 0 || loOid != oid)			die_horribly(AH, modulename, "could not create large object %u\n",						 oid);		AH->loFd = lo_open(AH->connection, oid, INV_WRITE);		if (AH->loFd == -1)			die_horribly(AH, modulename, "could not open large object\n");	}	else	{		ahprintf(AH, "SELECT lo_open(lo_create(%u), %d);\n", oid, INV_WRITE);	}	AH->writingBlob = 1;}voidEndRestoreBlob(ArchiveHandle *AH, Oid oid){	if (AH->lo_buf_used > 0)	{		/* Write remaining bytes from the LO buffer */		dump_lo_buf(AH);	}	AH->writingBlob = 0;	if (AH->connection)	{		lo_close(AH->connection, AH->loFd);		AH->loFd = -1;	}	else	{		ahprintf(AH, "SELECT lo_close(0);\n\n");	}}/*********** * Sorting and Reordering ***********/voidSortTocFromFile(Archive *AHX, RestoreOptions *ropt){	ArchiveHandle *AH = (ArchiveHandle *) AHX;	FILE	   *fh;	char		buf[1024];	char	   *cmnt;	char	   *endptr;	DumpId		id;	TocEntry   *te;	TocEntry   *tePrev;	/* Allocate space for the 'wanted' array, and init it */	ropt->idWanted = (bool *) malloc(sizeof(bool) * AH->maxDumpId);	memset(ropt->idWanted, 0, sizeof(bool) * AH->maxDumpId);	ropt->limitToList = true;	/* Set prev entry as head of list */	tePrev = AH->toc;	/* Setup the file */	fh = fopen(ropt->tocFile, PG_BINARY_R);	if (!fh)		die_horribly(AH, modulename, "could not open TOC file\n");	while (fgets(buf, sizeof(buf), fh) != NULL)	{		/* Truncate line at comment, if any */		cmnt = strchr(buf, ';');		if (cmnt != NULL)			cmnt[0] = '\0';		/* Ignore if all blank */		if (strspn(buf, " \t\r") == strlen(buf))			continue;		/* Get an ID, check it's valid and not already seen */		id = strtol(buf, &endptr, 10);		if (endptr == buf || id <= 0 || id > AH->maxDumpId ||			ropt->idWanted[id - 1])		{			write_msg(modulename, "WARNING: line ignored: %s\n", buf);			continue;		}		/* Find TOC entry */		te = getTocEntryByDumpId(AH, id);		if (!te)			die_horribly(AH, modulename, "could not find entry for ID %d\n",						 id);		ropt->idWanted[id - 1] = true;		_moveAfter(AH, tePrev, te);		tePrev = te;	}	if (fclose(fh) != 0)		die_horribly(AH, modulename, "could not close TOC file: %s\n",					 strerror(errno));}/********************** * 'Convenience functions that look like standard IO functions * for writing data when in dump mode. **********************//* Public */intarchputs(const char *s, Archive *AH){	return WriteData(AH, s, strlen(s));}/* Public */intarchprintf(Archive *AH, const char *fmt,...){	char	   *p = NULL;	va_list		ap;	int			bSize = strlen(fmt) + 256;	int			cnt = -1;	/*	 * This is paranoid: deal with the possibility that vsnprintf is willing	 * to ignore trailing null or returns > 0 even if string does not fit. It	 * may be the case that it returns cnt = bufsize	 */	while (cnt < 0 || cnt >= (bSize - 1))	{		if (p != NULL)			free(p);		bSize *= 2;		p = (char *) malloc(bSize);		if (p == NULL)			exit_horribly(AH, modulename, "out of memory\n");		va_start(ap, fmt);		cnt = vsnprintf(p, bSize, fmt, ap);		va_end(ap);	}	WriteData(AH, p, cnt);	free(p);	return cnt;}/******************************* * Stuff below here should be 'private' to the archiver routines *******************************/OutputContextSetOutput(ArchiveHandle *AH, char *filename, int compression){	OutputContext sav;	int			fn;	/* Replace the AH output file handle */	sav.OF = AH->OF;	sav.gzOut = AH->gzOut;	if (filename)		fn = -1;	else if (AH->FH)		fn = fileno(AH->FH);	else if (AH->fSpec)	{		fn = -1;		filename = AH->fSpec;	}	else		fn = fileno(stdout);	/* If compression explicitly requested, use gzopen */#ifdef HAVE_LIBZ	if (compression != 0)	{		char		fmode[10];		/* Don't use PG_BINARY_x since this is zlib */		sprintf(fmode, "wb%d", compression);		if (fn >= 0)			AH->OF = gzdopen(dup(fn), fmode);		else			AH->OF = gzopen(filename, fmode);		AH->gzOut = 1;	}	else#endif	{							/* Use fopen */		if (fn >= 0)			AH->OF = fdopen(dup(fn), PG_BINARY_W);		else			AH->OF = fopen(filename, PG_BINARY_W);		AH->gzOut = 0;	}	if (!AH->OF)		die_horribly(AH, modulename, "could not open output file: %s\n", strerror(errno));	return sav;}voidResetOutput(ArchiveHandle *AH, OutputContext sav){	int			res;	if (AH->gzOut)		res = GZCLOSE(AH->OF);	else		res = fclose(AH->OF);	if (res != 0)		die_horribly(AH, modulename, "could not close output file: %s\n",					 strerror(errno));	AH->gzOut = sav.gzOut;	AH->OF = sav.OF;}/* *	Print formatted text to the output file (usually stdout). */intahprintf(ArchiveHandle *AH, const char *fmt,...){	char	   *p = NULL;	va_list		ap;	int			bSize = strlen(fmt) + 256;		/* Should be enough */	int			cnt = -1;	/*	 * This is paranoid: deal with the possibility that vsnprintf is willing	 * to ignore trailing null	 */	/*	 * or returns > 0 even if string does not fit. It may be the case that it	 * returns cnt = bufsize	 */	while (cnt < 0 || cnt >= (bSize - 1))	{		if (p != NULL)			free(p);		bSize *= 2;		p = (char *) malloc(bSize);		if (p == NULL)			die_horribly(AH, modulename, "out of memory\n");		va_start(ap, fmt);		cnt = vsnprintf(p, bSize, fmt, ap);		va_end(ap);	}	ahwrite(p, 1, cnt, AH);	free(p);	return cnt;}voidahlog(ArchiveHandle *AH, int level, const char *fmt,...){	va_list		ap;	if (AH->debugLevel < level && (!AH->public.verbose || level > 1))		return;	va_start(ap, fmt);	_write_msg(NULL, fmt, ap);	va_end(ap);}/* * Single place for logic which says 'We are restoring to a direct DB connection'. */intRestoringToDB(ArchiveHandle *AH){	return (AH->ropt && AH->ropt->useDB && AH->connection);}/* * Dump the current contents of the LO data buffer while writing a BLOB */static voiddump_lo_buf(ArchiveHandle *AH){	if (AH->connection)	{		size_t		res;		res = lo_write(AH->connection, AH->loFd, AH->lo_buf, AH->lo_buf_used);		ahlog(AH, 5, "wrote %lu bytes of large object data (result = %lu)\n",			  (unsigned long) AH->lo_buf_used, (unsigned long) res);		if (res != AH->lo_buf_used)			die_horribly(AH, modulename,			"could not write to large object (result: %lu, expected: %lu)\n",					   (unsigned long) res, (unsigned long) AH->lo_buf_used);	}	else	{		unsigned char *str;		size_t		len;		str = PQescapeBytea((const unsigned char *) AH->lo_buf,							AH->lo_buf_used, &len);		if (!str)			die_horribly(AH, modulename, "out of memory\n");		/* Hack: turn off writingBlob so ahwrite doesn't recurse to here */		AH->writingBlob = 0;		ahprintf(AH, "SELECT lowrite(0, '%s');\n", str);		AH->writingBlob = 1;		free(str);	}	AH->lo_buf_used = 0;}/* *	Write buffer to the output file (usually stdout). This is user for *	outputting 'restore' scripts etc. It is even possible for an archive *	format to create a custom output routine to 'fake' a restore if it *	wants to generate a script (see TAR output). */intahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH){	size_t		res;	if (AH->writingBlob)	{		size_t		remaining = size * nmemb;		while (AH->lo_buf_used + remaining > AH->lo_buf_size)		{			size_t		avail = AH->lo_buf_size - AH->lo_buf_used;			memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, avail);			ptr = (const void *) ((const char *) ptr + avail);			remaining -= avail;			AH->lo_buf_used += avail;			dump_lo_buf(AH);		}		memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, remaining);		AH->lo_buf_used += remaining;		return size * nmemb;	}	else if (AH->gzOut)	{		res = GZWRITE((void *) ptr, size, nmemb, AH->OF);		if (res != (nmemb * size))			die_horribly(AH, modulename, "could not write to compressed archive\n");		return res;	}	else if (AH->CustomOutPtr)	{		res = AH->CustomOutPtr (AH, ptr, size * nmemb);		if (res != (nmemb * size))			die_horribly(AH, modulename, "could not write to custom output routine\n");		return res;	}	else	{		/*		 * If we're doing a restore, and it's direct to DB, and we're		 * connected then send it to the DB.		 */		if (RestoringToDB(AH))			return ExecuteSqlCommandBuf(AH, (void *) ptr, size * nmemb);		/* Always 1, currently */		else		{			res = fwrite((void *) ptr, size, nmemb, AH->OF);			if (res != nmemb)				die_horribly(AH, modulename, "could not write to output file (%lu != %lu)\n",							 (unsigned long) res, (unsigned long) nmemb);

⌨️ 快捷键说明

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