mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-21 08:29:39 +08:00
Fix pg_restore so parallel restore doesn't fail when the input file doesn't
contain data offsets (which it won't, if pg_dump thought its output wasn't seekable). To do that, remove an unnecessarily aggressive error check, and instead fail if we get to the end of the archive without finding the desired data item. Also improve the error message to be more specific about the cause of the problem. Per discussion of recent report from Igor Neyman. Back-patch to 8.4 where parallel restore was introduced.
This commit is contained in:
parent
e351593922
commit
b779ea8a9a
@ -19,7 +19,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_custom.c,v 1.44 2009/08/24 14:15:09 alvherre Exp $
|
||||
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_custom.c,v 1.45 2010/06/27 19:07:24 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -438,26 +438,24 @@ static void
|
||||
_PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
|
||||
{
|
||||
lclContext *ctx = (lclContext *) AH->formatData;
|
||||
int id;
|
||||
lclTocEntry *tctx = (lclTocEntry *) te->formatData;
|
||||
int blkType;
|
||||
int id;
|
||||
|
||||
if (tctx->dataState == K_OFFSET_NO_DATA)
|
||||
return;
|
||||
|
||||
if (!ctx->hasSeek || tctx->dataState == K_OFFSET_POS_NOT_SET)
|
||||
{
|
||||
/* Skip over unnecessary blocks until we get the one we want. */
|
||||
|
||||
/*
|
||||
* We cannot seek directly to the desired block. Instead, skip
|
||||
* over block headers until we find the one we want. This could
|
||||
* fail if we are asked to restore items out-of-order.
|
||||
*/
|
||||
_readBlockHeader(AH, &blkType, &id);
|
||||
|
||||
while (id != te->dumpId)
|
||||
while (blkType != EOF && id != te->dumpId)
|
||||
{
|
||||
if ((TocIDRequired(AH, id, ropt) & REQ_DATA) != 0)
|
||||
die_horribly(AH, modulename,
|
||||
"dumping a specific TOC data block out of order is not supported"
|
||||
" without ID on this input stream (fseek required)\n");
|
||||
|
||||
switch (blkType)
|
||||
{
|
||||
case BLK_DATA:
|
||||
@ -479,13 +477,33 @@ _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Grab it */
|
||||
/* We can just seek to the place we need to be. */
|
||||
if (fseeko(AH->FH, tctx->dataPos, SEEK_SET) != 0)
|
||||
die_horribly(AH, modulename, "error during file seek: %s\n", strerror(errno));
|
||||
die_horribly(AH, modulename, "error during file seek: %s\n",
|
||||
strerror(errno));
|
||||
|
||||
_readBlockHeader(AH, &blkType, &id);
|
||||
}
|
||||
|
||||
/* Produce suitable failure message if we fell off end of file */
|
||||
if (blkType == EOF)
|
||||
{
|
||||
if (tctx->dataState == K_OFFSET_POS_NOT_SET)
|
||||
die_horribly(AH, modulename, "could not find block ID %d in archive -- "
|
||||
"possibly due to out-of-order restore request, "
|
||||
"which cannot be handled due to lack of data offsets in archive\n",
|
||||
te->dumpId);
|
||||
else if (!ctx->hasSeek)
|
||||
die_horribly(AH, modulename, "could not find block ID %d in archive -- "
|
||||
"possibly due to out-of-order restore request, "
|
||||
"which cannot be handled due to non-seekable input file\n",
|
||||
te->dumpId);
|
||||
else /* huh, the dataPos led us to EOF? */
|
||||
die_horribly(AH, modulename, "could not find block ID %d in archive -- "
|
||||
"possibly corrupt archive\n",
|
||||
te->dumpId);
|
||||
}
|
||||
|
||||
/* Are we sane? */
|
||||
if (id != te->dumpId)
|
||||
die_horribly(AH, modulename, "found unexpected block ID (%d) when reading data -- expected %d\n",
|
||||
@ -907,15 +925,35 @@ _getFilePos(ArchiveHandle *AH, lclContext *ctx)
|
||||
|
||||
/*
|
||||
* Read a data block header. The format changed in V1.3, so we
|
||||
* put the code here for simplicity.
|
||||
* centralize the code here for simplicity. Returns *type = EOF
|
||||
* if at EOF.
|
||||
*/
|
||||
static void
|
||||
_readBlockHeader(ArchiveHandle *AH, int *type, int *id)
|
||||
{
|
||||
lclContext *ctx = (lclContext *) AH->formatData;
|
||||
int byt;
|
||||
|
||||
/*
|
||||
* Note: if we are at EOF with a pre-1.3 input file, we'll die_horribly
|
||||
* inside ReadInt rather than returning EOF. It doesn't seem worth
|
||||
* jumping through hoops to deal with that case better, because no such
|
||||
* files are likely to exist in the wild: only some 7.1 development
|
||||
* versions of pg_dump ever generated such files.
|
||||
*/
|
||||
if (AH->version < K_VERS_1_3)
|
||||
*type = BLK_DATA;
|
||||
else
|
||||
*type = _ReadByte(AH);
|
||||
{
|
||||
byt = getc(AH->FH);
|
||||
*type = byt;
|
||||
if (byt == EOF)
|
||||
{
|
||||
*id = 0; /* don't return an uninitialized value */
|
||||
return;
|
||||
}
|
||||
ctx->filePos += 1;
|
||||
}
|
||||
|
||||
*id = ReadInt(AH);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user