Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit b779ea8

Browse files
committed
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.
1 parent e351593 commit b779ea8

File tree

1 file changed

+52
-14
lines changed

1 file changed

+52
-14
lines changed

src/bin/pg_dump/pg_backup_custom.c

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
*
2020
*
2121
* IDENTIFICATION
22-
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_custom.c,v 1.44 2009/08/24 14:15:09 alvherre Exp $
22+
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_custom.c,v 1.45 2010/06/27 19:07:24 tgl Exp $
2323
*
2424
*-------------------------------------------------------------------------
2525
*/
@@ -438,26 +438,24 @@ static void
438438
_PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
439439
{
440440
lclContext *ctx = (lclContext *) AH->formatData;
441-
int id;
442441
lclTocEntry *tctx = (lclTocEntry *) te->formatData;
443442
int blkType;
443+
int id;
444444

445445
if (tctx->dataState == K_OFFSET_NO_DATA)
446446
return;
447447

448448
if (!ctx->hasSeek || tctx->dataState == K_OFFSET_POS_NOT_SET)
449449
{
450-
/* Skip over unnecessary blocks until we get the one we want. */
451-
450+
/*
451+
* We cannot seek directly to the desired block. Instead, skip
452+
* over block headers until we find the one we want. This could
453+
* fail if we are asked to restore items out-of-order.
454+
*/
452455
_readBlockHeader(AH, &blkType, &id);
453456

454-
while (id != te->dumpId)
457+
while (blkType != EOF && id != te->dumpId)
455458
{
456-
if ((TocIDRequired(AH, id, ropt) & REQ_DATA) != 0)
457-
die_horribly(AH, modulename,
458-
"dumping a specific TOC data block out of order is not supported"
459-
" without ID on this input stream (fseek required)\n");
460-
461459
switch (blkType)
462460
{
463461
case BLK_DATA:
@@ -479,13 +477,33 @@ _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
479477
}
480478
else
481479
{
482-
/* Grab it */
480+
/* We can just seek to the place we need to be. */
483481
if (fseeko(AH->FH, tctx->dataPos, SEEK_SET) != 0)
484-
die_horribly(AH, modulename, "error during file seek: %s\n", strerror(errno));
482+
die_horribly(AH, modulename, "error during file seek: %s\n",
483+
strerror(errno));
485484

486485
_readBlockHeader(AH, &blkType, &id);
487486
}
488487

488+
/* Produce suitable failure message if we fell off end of file */
489+
if (blkType == EOF)
490+
{
491+
if (tctx->dataState == K_OFFSET_POS_NOT_SET)
492+
die_horribly(AH, modulename, "could not find block ID %d in archive -- "
493+
"possibly due to out-of-order restore request, "
494+
"which cannot be handled due to lack of data offsets in archive\n",
495+
te->dumpId);
496+
else if (!ctx->hasSeek)
497+
die_horribly(AH, modulename, "could not find block ID %d in archive -- "
498+
"possibly due to out-of-order restore request, "
499+
"which cannot be handled due to non-seekable input file\n",
500+
te->dumpId);
501+
else /* huh, the dataPos led us to EOF? */
502+
die_horribly(AH, modulename, "could not find block ID %d in archive -- "
503+
"possibly corrupt archive\n",
504+
te->dumpId);
505+
}
506+
489507
/* Are we sane? */
490508
if (id != te->dumpId)
491509
die_horribly(AH, modulename, "found unexpected block ID (%d) when reading data -- expected %d\n",
@@ -907,15 +925,35 @@ _getFilePos(ArchiveHandle *AH, lclContext *ctx)
907925

908926
/*
909927
* Read a data block header. The format changed in V1.3, so we
910-
* put the code here for simplicity.
928+
* centralize the code here for simplicity. Returns *type = EOF
929+
* if at EOF.
911930
*/
912931
static void
913932
_readBlockHeader(ArchiveHandle *AH, int *type, int *id)
914933
{
934+
lclContext *ctx = (lclContext *) AH->formatData;
935+
int byt;
936+
937+
/*
938+
* Note: if we are at EOF with a pre-1.3 input file, we'll die_horribly
939+
* inside ReadInt rather than returning EOF. It doesn't seem worth
940+
* jumping through hoops to deal with that case better, because no such
941+
* files are likely to exist in the wild: only some 7.1 development
942+
* versions of pg_dump ever generated such files.
943+
*/
915944
if (AH->version < K_VERS_1_3)
916945
*type = BLK_DATA;
917946
else
918-
*type = _ReadByte(AH);
947+
{
948+
byt = getc(AH->FH);
949+
*type = byt;
950+
if (byt == EOF)
951+
{
952+
*id = 0; /* don't return an uninitialized value */
953+
return;
954+
}
955+
ctx->filePos += 1;
956+
}
919957

920958
*id = ReadInt(AH);
921959
}

0 commit comments

Comments
 (0)