LCOV - differential code coverage report
Current view: top level - src/bin/pg_dump - pg_backup_custom.c (source / functions) Coverage Total Hit UBC GBC CBC
Current: c70b6db34ffeab48beef1fb4ce61bcad3772b8dd vs 06473f5a344df8c9594ead90a609b86f6724cff8 Lines: 61.1 % 332 203 129 8 195
Current Date: 2025-09-06 07:49:51 +0900 Functions: 77.4 % 31 24 7 24
Baseline: lcov-20250906-005545-baseline Branches: 36.4 % 176 64 112 7 57
Baseline Date: 2025-09-05 08:21:35 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(30,360] days: 100.0 % 4 4 4
(360..) days: 60.7 % 328 199 129 8 191
Function coverage date bins:
(360..) days: 77.4 % 31 24 7 24
Branch coverage date bins:
(30,360] days: 66.7 % 6 4 2 4
(360..) days: 35.3 % 170 60 110 7 53

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * pg_backup_custom.c
                                  4                 :                :  *
                                  5                 :                :  *  Implements the custom output format.
                                  6                 :                :  *
                                  7                 :                :  *  The comments with the routines in this code are a good place to
                                  8                 :                :  *  understand how to write a new format.
                                  9                 :                :  *
                                 10                 :                :  *  See the headers to pg_restore for more details.
                                 11                 :                :  *
                                 12                 :                :  * Copyright (c) 2000, Philip Warner
                                 13                 :                :  *      Rights are granted to use this software in any way so long
                                 14                 :                :  *      as this notice is not removed.
                                 15                 :                :  *
                                 16                 :                :  *  The author is not responsible for loss or damages that may
                                 17                 :                :  *  and any liability will be limited to the time taken to fix any
                                 18                 :                :  *  related bug.
                                 19                 :                :  *
                                 20                 :                :  *
                                 21                 :                :  * IDENTIFICATION
                                 22                 :                :  *      src/bin/pg_dump/pg_backup_custom.c
                                 23                 :                :  *
                                 24                 :                :  *-------------------------------------------------------------------------
                                 25                 :                :  */
                                 26                 :                : #include "postgres_fe.h"
                                 27                 :                : 
                                 28                 :                : #include "common/file_utils.h"
                                 29                 :                : #include "compress_io.h"
                                 30                 :                : #include "pg_backup_utils.h"
                                 31                 :                : 
                                 32                 :                : /*--------
                                 33                 :                :  * Routines in the format interface
                                 34                 :                :  *--------
                                 35                 :                :  */
                                 36                 :                : 
                                 37                 :                : static void _ArchiveEntry(ArchiveHandle *AH, TocEntry *te);
                                 38                 :                : static void _StartData(ArchiveHandle *AH, TocEntry *te);
                                 39                 :                : static void _WriteData(ArchiveHandle *AH, const void *data, size_t dLen);
                                 40                 :                : static void _EndData(ArchiveHandle *AH, TocEntry *te);
                                 41                 :                : static int  _WriteByte(ArchiveHandle *AH, const int i);
                                 42                 :                : static int  _ReadByte(ArchiveHandle *AH);
                                 43                 :                : static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len);
                                 44                 :                : static void _ReadBuf(ArchiveHandle *AH, void *buf, size_t len);
                                 45                 :                : static void _CloseArchive(ArchiveHandle *AH);
                                 46                 :                : static void _ReopenArchive(ArchiveHandle *AH);
                                 47                 :                : static void _PrintTocData(ArchiveHandle *AH, TocEntry *te);
                                 48                 :                : static void _WriteExtraToc(ArchiveHandle *AH, TocEntry *te);
                                 49                 :                : static void _ReadExtraToc(ArchiveHandle *AH, TocEntry *te);
                                 50                 :                : static void _PrintExtraToc(ArchiveHandle *AH, TocEntry *te);
                                 51                 :                : 
                                 52                 :                : static void _PrintData(ArchiveHandle *AH);
                                 53                 :                : static void _skipData(ArchiveHandle *AH);
                                 54                 :                : static void _skipLOs(ArchiveHandle *AH);
                                 55                 :                : 
                                 56                 :                : static void _StartLOs(ArchiveHandle *AH, TocEntry *te);
                                 57                 :                : static void _StartLO(ArchiveHandle *AH, TocEntry *te, Oid oid);
                                 58                 :                : static void _EndLO(ArchiveHandle *AH, TocEntry *te, Oid oid);
                                 59                 :                : static void _EndLOs(ArchiveHandle *AH, TocEntry *te);
                                 60                 :                : static void _LoadLOs(ArchiveHandle *AH, bool drop);
                                 61                 :                : 
                                 62                 :                : static void _PrepParallelRestore(ArchiveHandle *AH);
                                 63                 :                : static void _Clone(ArchiveHandle *AH);
                                 64                 :                : static void _DeClone(ArchiveHandle *AH);
                                 65                 :                : 
                                 66                 :                : static int  _WorkerJobRestoreCustom(ArchiveHandle *AH, TocEntry *te);
                                 67                 :                : 
                                 68                 :                : typedef struct
                                 69                 :                : {
                                 70                 :                :     CompressorState *cs;
                                 71                 :                :     int         hasSeek;
                                 72                 :                :     /* lastFilePos is used only when reading, and may be invalid if !hasSeek */
                                 73                 :                :     pgoff_t     lastFilePos;    /* position after last data block we've read */
                                 74                 :                : } lclContext;
                                 75                 :                : 
                                 76                 :                : typedef struct
                                 77                 :                : {
                                 78                 :                :     int         dataState;
                                 79                 :                :     pgoff_t     dataPos;        /* valid only if dataState=K_OFFSET_POS_SET */
                                 80                 :                : } lclTocEntry;
                                 81                 :                : 
                                 82                 :                : 
                                 83                 :                : /*------
                                 84                 :                :  * Static declarations
                                 85                 :                :  *------
                                 86                 :                :  */
                                 87                 :                : static void _readBlockHeader(ArchiveHandle *AH, int *type, int *id);
                                 88                 :                : static pgoff_t _getFilePos(ArchiveHandle *AH, lclContext *ctx);
                                 89                 :                : 
                                 90                 :                : static void _CustomWriteFunc(ArchiveHandle *AH, const char *buf, size_t len);
                                 91                 :                : static size_t _CustomReadFunc(ArchiveHandle *AH, char **buf, size_t *buflen);
                                 92                 :                : 
                                 93                 :                : 
                                 94                 :                : /*
                                 95                 :                :  *  Init routine required by ALL formats. This is a global routine
                                 96                 :                :  *  and should be declared in pg_backup_archiver.h
                                 97                 :                :  *
                                 98                 :                :  *  It's task is to create any extra archive context (using AH->formatData),
                                 99                 :                :  *  and to initialize the supported function pointers.
                                100                 :                :  *
                                101                 :                :  *  It should also prepare whatever its input source is for reading/writing,
                                102                 :                :  *  and in the case of a read mode connection, it should load the Header & TOC.
                                103                 :                :  */
                                104                 :                : void
 8934 bruce@momjian.us          105                 :CBC          86 : InitArchiveFmt_Custom(ArchiveHandle *AH)
                                106                 :                : {
                                107                 :                :     lclContext *ctx;
                                108                 :                : 
                                109                 :                :     /* Assuming static functions, this can be copied for each format. */
                                110                 :             86 :     AH->ArchiveEntryPtr = _ArchiveEntry;
                                111                 :             86 :     AH->StartDataPtr = _StartData;
                                112                 :             86 :     AH->WriteDataPtr = _WriteData;
                                113                 :             86 :     AH->EndDataPtr = _EndData;
                                114                 :             86 :     AH->WriteBytePtr = _WriteByte;
                                115                 :             86 :     AH->ReadBytePtr = _ReadByte;
                                116                 :             86 :     AH->WriteBufPtr = _WriteBuf;
                                117                 :             86 :     AH->ReadBufPtr = _ReadBuf;
                                118                 :             86 :     AH->ClosePtr = _CloseArchive;
 6060 andrew@dunslane.net       119                 :             86 :     AH->ReopenPtr = _ReopenArchive;
 8934 bruce@momjian.us          120                 :             86 :     AH->PrintTocDataPtr = _PrintTocData;
                                121                 :             86 :     AH->ReadExtraTocPtr = _ReadExtraToc;
                                122                 :             86 :     AH->WriteExtraTocPtr = _WriteExtraToc;
                                123                 :             86 :     AH->PrintExtraTocPtr = _PrintExtraToc;
                                124                 :                : 
 1006 peter@eisentraut.org      125                 :             86 :     AH->StartLOsPtr = _StartLOs;
                                126                 :             86 :     AH->StartLOPtr = _StartLO;
                                127                 :             86 :     AH->EndLOPtr = _EndLO;
                                128                 :             86 :     AH->EndLOsPtr = _EndLOs;
                                129                 :                : 
 2549 tgl@sss.pgh.pa.us         130                 :             86 :     AH->PrepParallelRestorePtr = _PrepParallelRestore;
 5931 bruce@momjian.us          131                 :             86 :     AH->ClonePtr = _Clone;
                                132                 :             86 :     AH->DeClonePtr = _DeClone;
                                133                 :                : 
                                134                 :                :     /* no parallel dump in the custom archive, only parallel restore */
 4549 andrew@dunslane.net       135                 :             86 :     AH->WorkerJobDumpPtr = NULL;
                                136                 :             86 :     AH->WorkerJobRestorePtr = _WorkerJobRestoreCustom;
                                137                 :                : 
                                138                 :                :     /* Set up a private area. */
 4722 tgl@sss.pgh.pa.us         139                 :             86 :     ctx = (lclContext *) pg_malloc0(sizeof(lclContext));
  282 peter@eisentraut.org      140                 :             86 :     AH->formatData = ctx;
                                141                 :                : 
                                142                 :                :     /*
                                143                 :                :      * Now open the file
                                144                 :                :      */
 8934 bruce@momjian.us          145         [ +  + ]:             86 :     if (AH->mode == archModeWrite)
                                146                 :                :     {
                                147   [ +  -  +  - ]:             42 :         if (AH->fSpec && strcmp(AH->fSpec, "") != 0)
                                148                 :                :         {
 9178 pjw@rhyme.com.au          149                 :             42 :             AH->FH = fopen(AH->fSpec, PG_BINARY_W);
 6523 tgl@sss.pgh.pa.us         150         [ -  + ]:             42 :             if (!AH->FH)
 1247 tgl@sss.pgh.pa.us         151                 :UBC           0 :                 pg_fatal("could not open output file \"%s\": %m", AH->fSpec);
                                152                 :                :         }
                                153                 :                :         else
                                154                 :                :         {
 9178 pjw@rhyme.com.au          155                 :              0 :             AH->FH = stdout;
 6523 tgl@sss.pgh.pa.us         156         [ #  # ]:              0 :             if (!AH->FH)
 1247                           157                 :              0 :                 pg_fatal("could not open output file: %m");
                                158                 :                :         }
                                159                 :                : 
 8352 bruce@momjian.us          160                 :CBC          42 :         ctx->hasSeek = checkSeek(AH->FH);
                                161                 :                :     }
                                162                 :                :     else
                                163                 :                :     {
 8934                           164   [ +  -  +  - ]:             44 :         if (AH->fSpec && strcmp(AH->fSpec, "") != 0)
                                165                 :                :         {
 9178 pjw@rhyme.com.au          166                 :             44 :             AH->FH = fopen(AH->fSpec, PG_BINARY_R);
 6523 tgl@sss.pgh.pa.us         167         [ -  + ]:             44 :             if (!AH->FH)
 1247 tgl@sss.pgh.pa.us         168                 :UBC           0 :                 pg_fatal("could not open input file \"%s\": %m", AH->fSpec);
                                169                 :                :         }
                                170                 :                :         else
                                171                 :                :         {
 9178 pjw@rhyme.com.au          172                 :              0 :             AH->FH = stdin;
 6523 tgl@sss.pgh.pa.us         173         [ #  # ]:              0 :             if (!AH->FH)
 1247                           174                 :              0 :                 pg_fatal("could not open input file: %m");
                                175                 :                :         }
                                176                 :                : 
 8352 bruce@momjian.us          177                 :CBC          44 :         ctx->hasSeek = checkSeek(AH->FH);
                                178                 :                : 
 9178 pjw@rhyme.com.au          179                 :             44 :         ReadHead(AH);
                                180                 :             44 :         ReadToc(AH);
                                181                 :                : 
                                182                 :                :         /*
                                183                 :                :          * Remember location of first data block (i.e., the point after TOC)
                                184                 :                :          * in case we have to search for desired data blocks.
                                185                 :                :          */
 1877 tgl@sss.pgh.pa.us         186                 :             44 :         ctx->lastFilePos = _getFilePos(AH, ctx);
                                187                 :                :     }
 9178 pjw@rhyme.com.au          188                 :             86 : }
                                189                 :                : 
                                190                 :                : /*
                                191                 :                :  * Called by the Archiver when the dumper creates a new TOC entry.
                                192                 :                :  *
                                193                 :                :  * Optional.
                                194                 :                :  *
                                195                 :                :  * Set up extract format-related TOC data.
                                196                 :                : */
                                197                 :                : static void
 8934 bruce@momjian.us          198                 :           5461 : _ArchiveEntry(ArchiveHandle *AH, TocEntry *te)
                                199                 :                : {
                                200                 :                :     lclTocEntry *ctx;
                                201                 :                : 
 4722 tgl@sss.pgh.pa.us         202                 :           5461 :     ctx = (lclTocEntry *) pg_malloc0(sizeof(lclTocEntry));
 8934 bruce@momjian.us          203         [ +  + ]:           5461 :     if (te->dataDumper)
 8355                           204                 :            248 :         ctx->dataState = K_OFFSET_POS_NOT_SET;
                                205                 :                :     else
                                206                 :           5213 :         ctx->dataState = K_OFFSET_NO_DATA;
                                207                 :                : 
  282 peter@eisentraut.org      208                 :           5461 :     te->formatData = ctx;
 9178 pjw@rhyme.com.au          209                 :           5461 : }
                                210                 :                : 
                                211                 :                : /*
                                212                 :                :  * Called by the Archiver to save any extra format-related TOC entry
                                213                 :                :  * data.
                                214                 :                :  *
                                215                 :                :  * Optional.
                                216                 :                :  *
                                217                 :                :  * Use the Archiver routines to write data - they are non-endian, and
                                218                 :                :  * maintain other important file information.
                                219                 :                :  */
                                220                 :                : static void
 8934 bruce@momjian.us          221                 :           7062 : _WriteExtraToc(ArchiveHandle *AH, TocEntry *te)
                                222                 :                : {
                                223                 :           7062 :     lclTocEntry *ctx = (lclTocEntry *) te->formatData;
                                224                 :                : 
 8355                           225                 :           7062 :     WriteOffset(AH, ctx->dataPos, ctx->dataState);
 9178 pjw@rhyme.com.au          226                 :           7062 : }
                                227                 :                : 
                                228                 :                : /*
                                229                 :                :  * Called by the Archiver to read any extra format-related TOC data.
                                230                 :                :  *
                                231                 :                :  * Optional.
                                232                 :                :  *
                                233                 :                :  * Needs to match the order defined in _WriteExtraToc, and should also
                                234                 :                :  * use the Archiver input routines.
                                235                 :                :  */
                                236                 :                : static void
 8934 bruce@momjian.us          237                 :           7020 : _ReadExtraToc(ArchiveHandle *AH, TocEntry *te)
                                238                 :                : {
                                239                 :           7020 :     lclTocEntry *ctx = (lclTocEntry *) te->formatData;
                                240                 :                : 
                                241         [ +  - ]:           7020 :     if (ctx == NULL)
                                242                 :                :     {
 4722 tgl@sss.pgh.pa.us         243                 :           7020 :         ctx = (lclTocEntry *) pg_malloc0(sizeof(lclTocEntry));
  282 peter@eisentraut.org      244                 :           7020 :         te->formatData = ctx;
                                245                 :                :     }
                                246                 :                : 
 8069 bruce@momjian.us          247                 :           7020 :     ctx->dataState = ReadOffset(AH, &(ctx->dataPos));
                                248                 :                : 
                                249                 :                :     /*
                                250                 :                :      * Prior to V1.7 (pg7.3), we dumped the data size as an int now we don't
                                251                 :                :      * dump it at all.
                                252                 :                :      */
 8355                           253         [ -  + ]:           7020 :     if (AH->version < K_VERS_1_7)
 5262 peter_e@gmx.net           254                 :UBC           0 :         ReadInt(AH);
 9178 pjw@rhyme.com.au          255                 :CBC        7020 : }
                                256                 :                : 
                                257                 :                : /*
                                258                 :                :  * Called by the Archiver when restoring an archive to output a comment
                                259                 :                :  * that includes useful information about the TOC entry.
                                260                 :                :  *
                                261                 :                :  * Optional.
                                262                 :                :  */
                                263                 :                : static void
 8934 bruce@momjian.us          264                 :           1889 : _PrintExtraToc(ArchiveHandle *AH, TocEntry *te)
                                265                 :                : {
                                266                 :           1889 :     lclTocEntry *ctx = (lclTocEntry *) te->formatData;
                                267                 :                : 
 7857 tgl@sss.pgh.pa.us         268         [ +  + ]:           1889 :     if (AH->public.verbose)
                                269                 :            331 :         ahprintf(AH, "-- Data Pos: " INT64_FORMAT "\n",
                                270                 :            331 :                  (int64) ctx->dataPos);
 9178 pjw@rhyme.com.au          271                 :           1889 : }
                                272                 :                : 
                                273                 :                : /*
                                274                 :                :  * Called by the archiver when saving TABLE DATA (not schema). This routine
                                275                 :                :  * should save whatever format-specific information is needed to read
                                276                 :                :  * the archive back.
                                277                 :                :  *
                                278                 :                :  * It is called just prior to the dumper's 'DataDumper' routine being called.
                                279                 :                :  *
                                280                 :                :  * Optional, but strongly recommended.
                                281                 :                :  *
                                282                 :                :  */
                                283                 :                : static void
 8934 bruce@momjian.us          284                 :            237 : _StartData(ArchiveHandle *AH, TocEntry *te)
                                285                 :                : {
                                286                 :            237 :     lclContext *ctx = (lclContext *) AH->formatData;
                                287                 :            237 :     lclTocEntry *tctx = (lclTocEntry *) te->formatData;
                                288                 :                : 
                                289                 :            237 :     tctx->dataPos = _getFilePos(AH, ctx);
 1877 tgl@sss.pgh.pa.us         290         [ +  - ]:            237 :     if (tctx->dataPos >= 0)
                                291                 :            237 :         tctx->dataState = K_OFFSET_POS_SET;
                                292                 :                : 
 8934 bruce@momjian.us          293                 :            237 :     _WriteByte(AH, BLK_DATA);   /* Block type */
 7945 tgl@sss.pgh.pa.us         294                 :            237 :     WriteInt(AH, te->dumpId);    /* For sanity check */
                                295                 :                : 
  926 tomas.vondra@postgre      296                 :            237 :     ctx->cs = AllocateCompressor(AH->compression_spec,
                                297                 :                :                                  NULL,
                                298                 :                :                                  _CustomWriteFunc);
 9178 pjw@rhyme.com.au          299                 :            237 : }
                                300                 :                : 
                                301                 :                : /*
                                302                 :                :  * Called by archiver when dumper calls WriteData. This routine is
                                303                 :                :  * called for both LO and table data; it is the responsibility of
                                304                 :                :  * the format to manage each kind of data using StartLO/StartData.
                                305                 :                :  *
                                306                 :                :  * It should only be called from within a DataDumper routine.
                                307                 :                :  *
                                308                 :                :  * Mandatory.
                                309                 :                :  */
                                310                 :                : static void
 8418 peter_e@gmx.net           311                 :            780 : _WriteData(ArchiveHandle *AH, const void *data, size_t dLen)
                                312                 :                : {
 8934 bruce@momjian.us          313                 :            780 :     lclContext *ctx = (lclContext *) AH->formatData;
 5263                           314                 :            780 :     CompressorState *cs = ctx->cs;
                                315                 :                : 
 4142                           316         [ +  + ]:            780 :     if (dLen > 0)
                                317                 :                :         /* writeData() internally throws write errors */
  926 tomas.vondra@postgre      318                 :            772 :         cs->writeData(AH, cs, data, dLen);
 9178 pjw@rhyme.com.au          319                 :            780 : }
                                320                 :                : 
                                321                 :                : /*
                                322                 :                :  * Called by the archiver when a dumper's 'DataDumper' routine has
                                323                 :                :  * finished.
                                324                 :                :  *
                                325                 :                :  * Mandatory.
                                326                 :                :  */
                                327                 :                : static void
 8934 bruce@momjian.us          328                 :            237 : _EndData(ArchiveHandle *AH, TocEntry *te)
                                329                 :                : {
 5392 heikki.linnakangas@i      330                 :            237 :     lclContext *ctx = (lclContext *) AH->formatData;
                                331                 :                : 
                                332                 :            237 :     EndCompressor(AH, ctx->cs);
  926 tomas.vondra@postgre      333                 :            237 :     ctx->cs = NULL;
                                334                 :                : 
                                335                 :                :     /* Send the end marker */
 5392 heikki.linnakangas@i      336                 :            237 :     WriteInt(AH, 0);
 9178 pjw@rhyme.com.au          337                 :            237 : }
                                338                 :                : 
                                339                 :                : /*
                                340                 :                :  * Called by the archiver when starting to save BLOB DATA (not schema).
                                341                 :                :  * This routine should save whatever format-specific information is needed
                                342                 :                :  * to read the LOs back into memory.
                                343                 :                :  *
                                344                 :                :  * It is called just prior to the dumper's DataDumper routine.
                                345                 :                :  *
                                346                 :                :  * Optional, but strongly recommended.
                                347                 :                :  */
                                348                 :                : static void
 1006 peter@eisentraut.org      349                 :              8 : _StartLOs(ArchiveHandle *AH, TocEntry *te)
                                350                 :                : {
 8934 bruce@momjian.us          351                 :              8 :     lclContext *ctx = (lclContext *) AH->formatData;
                                352                 :              8 :     lclTocEntry *tctx = (lclTocEntry *) te->formatData;
                                353                 :                : 
                                354                 :              8 :     tctx->dataPos = _getFilePos(AH, ctx);
 1877 tgl@sss.pgh.pa.us         355         [ +  - ]:              8 :     if (tctx->dataPos >= 0)
                                356                 :              8 :         tctx->dataState = K_OFFSET_POS_SET;
                                357                 :                : 
 8934 bruce@momjian.us          358                 :              8 :     _WriteByte(AH, BLK_BLOBS);  /* Block type */
 7945 tgl@sss.pgh.pa.us         359                 :              8 :     WriteInt(AH, te->dumpId);    /* For sanity check */
 9178 pjw@rhyme.com.au          360                 :              8 : }
                                361                 :                : 
                                362                 :                : /*
                                363                 :                :  * Called by the archiver when the dumper calls StartLO.
                                364                 :                :  *
                                365                 :                :  * Mandatory.
                                366                 :                :  *
                                367                 :                :  * Must save the passed OID for retrieval at restore-time.
                                368                 :                :  */
                                369                 :                : static void
 1006 peter@eisentraut.org      370                 :              8 : _StartLO(ArchiveHandle *AH, TocEntry *te, Oid oid)
                                371                 :                : {
 5392 heikki.linnakangas@i      372                 :              8 :     lclContext *ctx = (lclContext *) AH->formatData;
                                373                 :                : 
 8934 bruce@momjian.us          374         [ -  + ]:              8 :     if (oid == 0)
 1247 tgl@sss.pgh.pa.us         375                 :UBC           0 :         pg_fatal("invalid OID for large object");
                                376                 :                : 
 8934 bruce@momjian.us          377                 :CBC           8 :     WriteInt(AH, oid);
                                378                 :                : 
  926 tomas.vondra@postgre      379                 :              8 :     ctx->cs = AllocateCompressor(AH->compression_spec,
                                380                 :                :                                  NULL,
                                381                 :                :                                  _CustomWriteFunc);
 9178 pjw@rhyme.com.au          382                 :              8 : }
                                383                 :                : 
                                384                 :                : /*
                                385                 :                :  * Called by the archiver when the dumper calls EndLO.
                                386                 :                :  *
                                387                 :                :  * Optional.
                                388                 :                :  */
                                389                 :                : static void
 1006 peter@eisentraut.org      390                 :              8 : _EndLO(ArchiveHandle *AH, TocEntry *te, Oid oid)
                                391                 :                : {
 5392 heikki.linnakangas@i      392                 :              8 :     lclContext *ctx = (lclContext *) AH->formatData;
                                393                 :                : 
                                394                 :              8 :     EndCompressor(AH, ctx->cs);
                                395                 :                :     /* Send the end marker */
                                396                 :              8 :     WriteInt(AH, 0);
 9178 pjw@rhyme.com.au          397                 :              8 : }
                                398                 :                : 
                                399                 :                : /*
                                400                 :                :  * Called by the archiver when finishing saving BLOB DATA.
                                401                 :                :  *
                                402                 :                :  * Optional.
                                403                 :                :  */
                                404                 :                : static void
 1006 peter@eisentraut.org      405                 :              8 : _EndLOs(ArchiveHandle *AH, TocEntry *te)
                                406                 :                : {
                                407                 :                :     /* Write out a fake zero OID to mark end-of-LOs. */
 8934 bruce@momjian.us          408                 :              8 :     WriteInt(AH, 0);
 9178 pjw@rhyme.com.au          409                 :              8 : }
                                410                 :                : 
                                411                 :                : /*
                                412                 :                :  * Print data for a given TOC entry
                                413                 :                :  */
                                414                 :                : static void
 3524 tgl@sss.pgh.pa.us         415                 :            226 : _PrintTocData(ArchiveHandle *AH, TocEntry *te)
                                416                 :                : {
 8934 bruce@momjian.us          417                 :            226 :     lclContext *ctx = (lclContext *) AH->formatData;
                                418                 :            226 :     lclTocEntry *tctx = (lclTocEntry *) te->formatData;
                                419                 :                :     int         blkType;
                                420                 :                :     int         id;
                                421                 :                : 
 8355                           422         [ -  + ]:            226 :     if (tctx->dataState == K_OFFSET_NO_DATA)
 9178 pjw@rhyme.com.au          423                 :UBC           0 :         return;
                                424                 :                : 
 8355 bruce@momjian.us          425   [ +  -  +  + ]:CBC         226 :     if (!ctx->hasSeek || tctx->dataState == K_OFFSET_POS_NOT_SET)
                                426                 :                :     {
                                427                 :                :         /*
                                428                 :                :          * We cannot seek directly to the desired block.  Instead, skip over
                                429                 :                :          * block headers until we find the one we want.  Remember the
                                430                 :                :          * positions of skipped-over blocks, so that if we later decide we
                                431                 :                :          * need to read one, we'll be able to seek to it.
                                432                 :                :          *
                                433                 :                :          * When our input file is seekable, we can do the search starting from
                                434                 :                :          * the point after the last data block we scanned in previous
                                435                 :                :          * iterations of this function.
                                436                 :                :          */
 1877 tgl@sss.pgh.pa.us         437         [ -  + ]:GBC          58 :         if (ctx->hasSeek)
                                438                 :                :         {
                                439         [ +  - ]:             58 :             if (fseeko(AH->FH, ctx->lastFilePos, SEEK_SET) != 0)
 1247 tgl@sss.pgh.pa.us         440                 :UBC           0 :                 pg_fatal("error during file seek: %m");
                                441                 :                :         }
                                442                 :                : 
                                443                 :                :         for (;;)
 8934 bruce@momjian.us          444                 :              0 :         {
 1877 tgl@sss.pgh.pa.us         445                 :GBC          58 :             pgoff_t     thisBlkPos = _getFilePos(AH, ctx);
                                446                 :                : 
                                447                 :             58 :             _readBlockHeader(AH, &blkType, &id);
                                448                 :                : 
                                449   [ +  -  -  + ]:             58 :             if (blkType == EOF || id == te->dumpId)
                                450                 :                :                 break;
                                451                 :                : 
                                452                 :                :             /* Remember the block position, if we got one */
 1877 tgl@sss.pgh.pa.us         453         [ #  # ]:UBC           0 :             if (thisBlkPos >= 0)
                                454                 :                :             {
                                455                 :              0 :                 TocEntry   *otherte = getTocEntryByDumpId(AH, id);
                                456                 :                : 
                                457   [ #  #  #  # ]:              0 :                 if (otherte && otherte->formatData)
                                458                 :                :                 {
                                459                 :              0 :                     lclTocEntry *othertctx = (lclTocEntry *) otherte->formatData;
                                460                 :                : 
                                461                 :                :                     /*
                                462                 :                :                      * Note: on Windows, multiple threads might access/update
                                463                 :                :                      * the same lclTocEntry concurrently, but that should be
                                464                 :                :                      * safe as long as we update dataPos before dataState.
                                465                 :                :                      * Ideally, we'd use pg_write_barrier() to enforce that,
                                466                 :                :                      * but the needed infrastructure doesn't exist in frontend
                                467                 :                :                      * code.  But Windows only runs on machines with strong
                                468                 :                :                      * store ordering, so it should be okay for now.
                                469                 :                :                      */
                                470         [ #  # ]:              0 :                     if (othertctx->dataState == K_OFFSET_POS_NOT_SET)
                                471                 :                :                     {
                                472                 :              0 :                         othertctx->dataPos = thisBlkPos;
                                473                 :              0 :                         othertctx->dataState = K_OFFSET_POS_SET;
                                474                 :                :                     }
                                475         [ #  # ]:              0 :                     else if (othertctx->dataPos != thisBlkPos ||
                                476         [ #  # ]:              0 :                              othertctx->dataState != K_OFFSET_POS_SET)
                                477                 :                :                     {
                                478                 :                :                         /* sanity check */
                                479                 :              0 :                         pg_log_warning("data block %d has wrong seek position",
                                480                 :                :                                        id);
                                481                 :                :                     }
                                482                 :                :                 }
                                483                 :                :             }
                                484                 :                : 
 8934 bruce@momjian.us          485      [ #  #  # ]:              0 :             switch (blkType)
                                486                 :                :             {
                                487                 :              0 :                 case BLK_DATA:
                                488                 :              0 :                     _skipData(AH);
                                489                 :              0 :                     break;
                                490                 :                : 
                                491                 :              0 :                 case BLK_BLOBS:
 1006 peter@eisentraut.org      492                 :              0 :                     _skipLOs(AH);
 8934 bruce@momjian.us          493                 :              0 :                     break;
                                494                 :                : 
                                495                 :              0 :                 default:        /* Always have a default */
 1247 tgl@sss.pgh.pa.us         496                 :              0 :                     pg_fatal("unrecognized data block type (%d) while searching archive",
                                497                 :                :                              blkType);
                                498                 :                :                     break;
                                499                 :                :             }
                                500                 :                :         }
                                501                 :                :     }
                                502                 :                :     else
                                503                 :                :     {
                                504                 :                :         /* We can just seek to the place we need to be. */
 8418 peter_e@gmx.net           505         [ -  + ]:CBC         168 :         if (fseeko(AH->FH, tctx->dataPos, SEEK_SET) != 0)
 1247 tgl@sss.pgh.pa.us         506                 :UBC           0 :             pg_fatal("error during file seek: %m");
                                507                 :                : 
 9178 pjw@rhyme.com.au          508                 :CBC         168 :         _readBlockHeader(AH, &blkType, &id);
                                509                 :                :     }
                                510                 :                : 
                                511                 :                :     /*
                                512                 :                :      * If we reached EOF without finding the block we want, then either it
                                513                 :                :      * doesn't exist, or it does but we lack the ability to seek back to it.
                                514                 :                :      */
 5550 tgl@sss.pgh.pa.us         515         [ -  + ]:            226 :     if (blkType == EOF)
                                516                 :                :     {
 1877 tgl@sss.pgh.pa.us         517         [ #  # ]:UBC           0 :         if (!ctx->hasSeek)
 1247                           518                 :              0 :             pg_fatal("could not find block ID %d in archive -- "
                                519                 :                :                      "possibly due to out-of-order restore request, "
                                520                 :                :                      "which cannot be handled due to non-seekable input file",
                                521                 :                :                      te->dumpId);
                                522                 :                :         else
                                523                 :              0 :             pg_fatal("could not find block ID %d in archive -- "
                                524                 :                :                      "possibly corrupt archive",
                                525                 :                :                      te->dumpId);
                                526                 :                :     }
                                527                 :                : 
                                528                 :                :     /* Are we sane? */
 7945 tgl@sss.pgh.pa.us         529         [ -  + ]:CBC         226 :     if (id != te->dumpId)
 1247 tgl@sss.pgh.pa.us         530                 :UBC           0 :         pg_fatal("found unexpected block ID (%d) when reading data -- expected %d",
                                531                 :                :                  id, te->dumpId);
                                532                 :                : 
 8934 bruce@momjian.us          533      [ +  +  - ]:CBC         226 :     switch (blkType)
                                534                 :                :     {
 9178 pjw@rhyme.com.au          535                 :            218 :         case BLK_DATA:
                                536                 :            218 :             _PrintData(AH);
                                537                 :            218 :             break;
                                538                 :                : 
                                539                 :              8 :         case BLK_BLOBS:
 1006 peter@eisentraut.org      540                 :              8 :             _LoadLOs(AH, AH->public.ropt->dropSchema);
 9178 pjw@rhyme.com.au          541                 :              8 :             break;
                                542                 :                : 
 8934 bruce@momjian.us          543                 :UBC           0 :         default:                /* Always have a default */
 1247 tgl@sss.pgh.pa.us         544                 :              0 :             pg_fatal("unrecognized data block type %d while restoring archive",
                                545                 :                :                      blkType);
                                546                 :                :             break;
                                547                 :                :     }
                                548                 :                : 
                                549                 :                :     /*
                                550                 :                :      * If our input file is seekable but lacks data offsets, update our
                                551                 :                :      * knowledge of where to start future searches from.  (Note that we did
                                552                 :                :      * not update the current TE's dataState/dataPos.  We could have, but
                                553                 :                :      * there is no point since it will not be visited again.)
                                554                 :                :      */
 1877 tgl@sss.pgh.pa.us         555   [ +  -  +  + ]:CBC         226 :     if (ctx->hasSeek && tctx->dataState == K_OFFSET_POS_NOT_SET)
                                556                 :                :     {
 1877 tgl@sss.pgh.pa.us         557                 :GBC          58 :         pgoff_t     curPos = _getFilePos(AH, ctx);
                                558                 :                : 
                                559         [ +  - ]:             58 :         if (curPos > ctx->lastFilePos)
                                560                 :             58 :             ctx->lastFilePos = curPos;
                                561                 :                :     }
                                562                 :                : }
                                563                 :                : 
                                564                 :                : /*
                                565                 :                :  * Print data from current file position.
                                566                 :                : */
                                567                 :                : static void
 8934 bruce@momjian.us          568                 :CBC         226 : _PrintData(ArchiveHandle *AH)
                                569                 :                : {
                                570                 :                :     CompressorState *cs;
                                571                 :                : 
  926 tomas.vondra@postgre      572                 :            226 :     cs = AllocateCompressor(AH->compression_spec,
                                573                 :                :                             _CustomReadFunc, NULL);
                                574                 :            226 :     cs->readData(AH, cs);
                                575                 :            226 :     EndCompressor(AH, cs);
 9178 pjw@rhyme.com.au          576                 :            226 : }
                                577                 :                : 
                                578                 :                : static void
 1006 peter@eisentraut.org      579                 :              8 : _LoadLOs(ArchiveHandle *AH, bool drop)
                                580                 :                : {
                                581                 :                :     Oid         oid;
                                582                 :                : 
                                583                 :              8 :     StartRestoreLOs(AH);
                                584                 :                : 
 8934 bruce@momjian.us          585                 :              8 :     oid = ReadInt(AH);
                                586         [ +  + ]:             16 :     while (oid != 0)
                                587                 :                :     {
 1006 peter@eisentraut.org      588                 :              8 :         StartRestoreLO(AH, oid, drop);
 9178 pjw@rhyme.com.au          589                 :              8 :         _PrintData(AH);
 1006 peter@eisentraut.org      590                 :              8 :         EndRestoreLO(AH, oid);
 9178 pjw@rhyme.com.au          591                 :              8 :         oid = ReadInt(AH);
                                592                 :                :     }
                                593                 :                : 
 1006 peter@eisentraut.org      594                 :              8 :     EndRestoreLOs(AH);
 9178 pjw@rhyme.com.au          595                 :              8 : }
                                596                 :                : 
                                597                 :                : /*
                                598                 :                :  * Skip the LOs from the current file position.
                                599                 :                :  * LOs are written sequentially as data blocks (see below).
                                600                 :                :  * Each LO is preceded by its original OID.
                                601                 :                :  * A zero OID indicates the end of the LOs.
                                602                 :                :  */
                                603                 :                : static void
 1006 peter@eisentraut.org      604                 :UBC           0 : _skipLOs(ArchiveHandle *AH)
                                605                 :                : {
                                606                 :                :     Oid         oid;
                                607                 :                : 
 8934 bruce@momjian.us          608                 :              0 :     oid = ReadInt(AH);
                                609         [ #  # ]:              0 :     while (oid != 0)
                                610                 :                :     {
 9076 pjw@rhyme.com.au          611                 :              0 :         _skipData(AH);
                                612                 :              0 :         oid = ReadInt(AH);
                                613                 :                :     }
 9178                           614                 :              0 : }
                                615                 :                : 
                                616                 :                : /*
                                617                 :                :  * Skip data from current file position.
                                618                 :                :  * Data blocks are formatted as an integer length, followed by data.
                                619                 :                :  * A zero length indicates the end of the block.
                                620                 :                : */
                                621                 :                : static void
 8934 bruce@momjian.us          622                 :              0 : _skipData(ArchiveHandle *AH)
                                623                 :                : {
 1877 tgl@sss.pgh.pa.us         624                 :              0 :     lclContext *ctx = (lclContext *) AH->formatData;
                                625                 :                :     size_t      blkLen;
 5392 heikki.linnakangas@i      626                 :              0 :     char       *buf = NULL;
                                627                 :              0 :     int         buflen = 0;
                                628                 :                : 
 9178 pjw@rhyme.com.au          629                 :              0 :     blkLen = ReadInt(AH);
 8934 bruce@momjian.us          630         [ #  # ]:              0 :     while (blkLen != 0)
                                631                 :                :     {
 1877 tgl@sss.pgh.pa.us         632         [ #  # ]:              0 :         if (ctx->hasSeek)
                                633                 :                :         {
                                634         [ #  # ]:              0 :             if (fseeko(AH->FH, blkLen, SEEK_CUR) != 0)
 1247                           635                 :              0 :                 pg_fatal("error during file seek: %m");
                                636                 :                :         }
                                637                 :                :         else
                                638                 :                :         {
 1877                           639         [ #  # ]:              0 :             if (blkLen > buflen)
                                640                 :                :             {
 1178 peter@eisentraut.org      641                 :              0 :                 free(buf);
 1877 tgl@sss.pgh.pa.us         642                 :              0 :                 buf = (char *) pg_malloc(blkLen);
                                643                 :              0 :                 buflen = blkLen;
                                644                 :                :             }
 1827                           645         [ #  # ]:              0 :             if (fread(buf, 1, blkLen, AH->FH) != blkLen)
                                646                 :                :             {
 1877                           647         [ #  # ]:              0 :                 if (feof(AH->FH))
 1247                           648                 :              0 :                     pg_fatal("could not read from input file: end of file");
                                649                 :                :                 else
                                650                 :              0 :                     pg_fatal("could not read from input file: %m");
                                651                 :                :             }
                                652                 :                :         }
                                653                 :                : 
 8934 bruce@momjian.us          654                 :              0 :         blkLen = ReadInt(AH);
                                655                 :                :     }
                                656                 :                : 
 1178 peter@eisentraut.org      657                 :              0 :     free(buf);
 9178 pjw@rhyme.com.au          658                 :              0 : }
                                659                 :                : 
                                660                 :                : /*
                                661                 :                :  * Write a byte of data to the archive.
                                662                 :                :  *
                                663                 :                :  * Mandatory.
                                664                 :                :  *
                                665                 :                :  * Called by the archiver to do integer & byte output to the archive.
                                666                 :                :  */
                                667                 :                : static int
 8934 bruce@momjian.us          668                 :CBC      725067 : _WriteByte(ArchiveHandle *AH, const int i)
                                669                 :                : {
 1827 tgl@sss.pgh.pa.us         670         [ -  + ]:         725067 :     if (fputc(i, AH->FH) == EOF)
 4142 bruce@momjian.us          671                 :UBC           0 :         WRITE_ERROR_EXIT;
                                672                 :                : 
 4142 bruce@momjian.us          673                 :CBC      725067 :     return 1;
                                674                 :                : }
                                675                 :                : 
                                676                 :                : /*
                                677                 :                :  * Read a byte of data from the archive.
                                678                 :                :  *
                                679                 :                :  * Mandatory
                                680                 :                :  *
                                681                 :                :  * Called by the archiver to read bytes & integers from the archive.
                                682                 :                :  * EOF should be treated as a fatal error.
                                683                 :                :  */
                                684                 :                : static int
 8934                           685                 :         722023 : _ReadByte(ArchiveHandle *AH)
                                686                 :                : {
                                687                 :                :     int         res;
                                688                 :                : 
 6606 tgl@sss.pgh.pa.us         689                 :         722023 :     res = getc(AH->FH);
                                690         [ -  + ]:         722023 :     if (res == EOF)
 4142 bruce@momjian.us          691         [ #  # ]:UBC           0 :         READ_ERROR_EXIT(AH->FH);
 8934 bruce@momjian.us          692                 :CBC      722023 :     return res;
                                693                 :                : }
                                694                 :                : 
                                695                 :                : /*
                                696                 :                :  * Write a buffer of data to the archive.
                                697                 :                :  *
                                698                 :                :  * Mandatory.
                                699                 :                :  *
                                700                 :                :  * Called by the archiver to write a block of bytes to the archive.
                                701                 :                :  */
                                702                 :                : static void
 8418 peter_e@gmx.net           703                 :          71283 : _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len)
                                704                 :                : {
 4142 bruce@momjian.us          705         [ -  + ]:          71283 :     if (fwrite(buf, 1, len, AH->FH) != len)
 4142 bruce@momjian.us          706                 :UBC           0 :         WRITE_ERROR_EXIT;
 9178 pjw@rhyme.com.au          707                 :CBC       71283 : }
                                708                 :                : 
                                709                 :                : /*
                                710                 :                :  * Read a block of bytes from the archive.
                                711                 :                :  *
                                712                 :                :  * Mandatory.
                                713                 :                :  *
                                714                 :                :  * Called by the archiver to read a block of bytes from the archive
                                715                 :                :  */
                                716                 :                : static void
 8418 peter_e@gmx.net           717                 :          71289 : _ReadBuf(ArchiveHandle *AH, void *buf, size_t len)
                                718                 :                : {
 4142 bruce@momjian.us          719         [ -  + ]:          71289 :     if (fread(buf, 1, len, AH->FH) != len)
 4142 bruce@momjian.us          720         [ #  # ]:UBC           0 :         READ_ERROR_EXIT(AH->FH);
 9178 pjw@rhyme.com.au          721                 :CBC       71289 : }
                                722                 :                : 
                                723                 :                : /*
                                724                 :                :  * Close the archive.
                                725                 :                :  *
                                726                 :                :  * Mandatory.
                                727                 :                :  *
                                728                 :                :  * When writing the archive, this is the routine that actually starts
                                729                 :                :  * the process of saving it to files. No data should be written prior
                                730                 :                :  * to this point, since the user could sort the TOC after creating it.
                                731                 :                :  *
                                732                 :                :  * If an archive is to be written, this routine must call:
                                733                 :                :  *      WriteHead           to save the archive header
                                734                 :                :  *      WriteToc            to save the TOC entries
                                735                 :                :  *      WriteDataChunks     to save all data & LOs.
                                736                 :                :  *
                                737                 :                :  */
                                738                 :                : static void
 3524 tgl@sss.pgh.pa.us         739                 :             86 : _CloseArchive(ArchiveHandle *AH)
                                740                 :                : {
 8934 bruce@momjian.us          741                 :             86 :     lclContext *ctx = (lclContext *) AH->formatData;
                                742                 :                :     pgoff_t     tpos;
                                743                 :                : 
                                744         [ +  + ]:             86 :     if (AH->mode == archModeWrite)
                                745                 :                :     {
 9178 pjw@rhyme.com.au          746                 :             42 :         WriteHead(AH);
                                747                 :                :         /* Remember TOC's seek position for use below */
 8418 peter_e@gmx.net           748                 :             42 :         tpos = ftello(AH->FH);
 4142 tgl@sss.pgh.pa.us         749   [ -  +  -  - ]:             42 :         if (tpos < 0 && ctx->hasSeek)
 1247 tgl@sss.pgh.pa.us         750                 :UBC           0 :             pg_fatal("could not determine seek position in archive file: %m");
 9178 pjw@rhyme.com.au          751                 :CBC          42 :         WriteToc(AH);
 3524 tgl@sss.pgh.pa.us         752                 :             42 :         WriteDataChunks(AH, NULL);
                                753                 :                : 
                                754                 :                :         /*
                                755                 :                :          * If possible, re-write the TOC in order to update the data offset
                                756                 :                :          * information.  This is not essential, as pg_restore can cope in most
                                757                 :                :          * cases without it; but it can make pg_restore significantly faster
                                758                 :                :          * in some situations (especially parallel restore).  We can skip this
                                759                 :                :          * step if we're not dumping any data; there are no offsets to update
                                760                 :                :          * in that case.
                                761                 :                :          */
  155 nathan@postgresql.or      762   [ +  -  +  +  :             49 :         if (ctx->hasSeek && AH->public.dopt->dumpData &&
                                              +  - ]
 6060 andrew@dunslane.net       763                 :              7 :             fseeko(AH->FH, tpos, SEEK_SET) == 0)
 9178 pjw@rhyme.com.au          764                 :              7 :             WriteToc(AH);
                                765                 :                :     }
                                766                 :                : 
 8934 bruce@momjian.us          767         [ -  + ]:             86 :     if (fclose(AH->FH) != 0)
 1247 tgl@sss.pgh.pa.us         768                 :UBC           0 :         pg_fatal("could not close archive file: %m");
                                769                 :                : 
                                770                 :                :     /* Sync the output file if one is defined */
 3090 andrew@dunslane.net       771   [ +  +  +  +  :CBC          86 :     if (AH->dosync && AH->mode == archModeWrite && AH->fSpec)
                                              +  - ]
 2350 peter@eisentraut.org      772                 :              6 :         (void) fsync_fname(AH->fSpec, false);
                                773                 :                : 
 8934 bruce@momjian.us          774                 :             86 :     AH->FH = NULL;
 9178 pjw@rhyme.com.au          775                 :             86 : }
                                776                 :                : 
                                777                 :                : /*
                                778                 :                :  * Reopen the archive's file handle.
                                779                 :                :  *
                                780                 :                :  * We close the original file handle, except on Windows.  (The difference
                                781                 :                :  * is because on Windows, this is used within a multithreading context,
                                782                 :                :  * and we don't want a thread closing the parent file handle.)
                                783                 :                :  */
                                784                 :                : static void
 6060 andrew@dunslane.net       785                 :UBC           0 : _ReopenArchive(ArchiveHandle *AH)
                                786                 :                : {
                                787                 :              0 :     lclContext *ctx = (lclContext *) AH->formatData;
                                788                 :                :     pgoff_t     tpos;
                                789                 :                : 
                                790         [ #  # ]:              0 :     if (AH->mode == archModeWrite)
 1247 tgl@sss.pgh.pa.us         791                 :              0 :         pg_fatal("can only reopen input archives");
                                792                 :                : 
                                793                 :                :     /*
                                794                 :                :      * These two cases are user-facing errors since they represent unsupported
                                795                 :                :      * (but not invalid) use-cases.  Word the error messages appropriately.
                                796                 :                :      */
 6060 andrew@dunslane.net       797   [ #  #  #  # ]:              0 :     if (AH->fSpec == NULL || strcmp(AH->fSpec, "") == 0)
 1247 tgl@sss.pgh.pa.us         798                 :              0 :         pg_fatal("parallel restore from standard input is not supported");
 6060 andrew@dunslane.net       799         [ #  # ]:              0 :     if (!ctx->hasSeek)
 1247 tgl@sss.pgh.pa.us         800                 :              0 :         pg_fatal("parallel restore from non-seekable file is not supported");
                                801                 :                : 
 6060 andrew@dunslane.net       802                 :              0 :     tpos = ftello(AH->FH);
 4227 sfrost@snowman.net        803         [ #  # ]:              0 :     if (tpos < 0)
 1247 tgl@sss.pgh.pa.us         804                 :              0 :         pg_fatal("could not determine seek position in archive file: %m");
                                805                 :                : 
                                806                 :                : #ifndef WIN32
 6060 andrew@dunslane.net       807         [ #  # ]:              0 :     if (fclose(AH->FH) != 0)
 1247 tgl@sss.pgh.pa.us         808                 :              0 :         pg_fatal("could not close archive file: %m");
                                809                 :                : #endif
                                810                 :                : 
 6060 andrew@dunslane.net       811                 :              0 :     AH->FH = fopen(AH->fSpec, PG_BINARY_R);
                                812         [ #  # ]:              0 :     if (!AH->FH)
 1247 tgl@sss.pgh.pa.us         813                 :              0 :         pg_fatal("could not open input file \"%s\": %m", AH->fSpec);
                                814                 :                : 
 6060 andrew@dunslane.net       815         [ #  # ]:              0 :     if (fseeko(AH->FH, tpos, SEEK_SET) != 0)
 1247 tgl@sss.pgh.pa.us         816                 :              0 :         pg_fatal("could not set seek position in archive file: %m");
 6060 andrew@dunslane.net       817                 :              0 : }
                                818                 :                : 
                                819                 :                : /*
                                820                 :                :  * Prepare for parallel restore.
                                821                 :                :  *
                                822                 :                :  * The main thing that needs to happen here is to fill in TABLE DATA and BLOBS
                                823                 :                :  * TOC entries' dataLength fields with appropriate values to guide the
                                824                 :                :  * ordering of restore jobs.  The source of said data is format-dependent,
                                825                 :                :  * as is the exact meaning of the values.
                                826                 :                :  *
                                827                 :                :  * A format module might also choose to do other setup here.
                                828                 :                :  */
                                829                 :                : static void
 2549 tgl@sss.pgh.pa.us         830                 :              0 : _PrepParallelRestore(ArchiveHandle *AH)
                                831                 :                : {
                                832                 :              0 :     lclContext *ctx = (lclContext *) AH->formatData;
                                833                 :              0 :     TocEntry   *prev_te = NULL;
                                834                 :              0 :     lclTocEntry *prev_tctx = NULL;
                                835                 :                :     TocEntry   *te;
                                836                 :                : 
                                837                 :                :     /*
                                838                 :                :      * Knowing that the data items were dumped out in TOC order, we can
                                839                 :                :      * reconstruct the length of each item as the delta to the start offset of
                                840                 :                :      * the next data item.
                                841                 :                :      */
                                842         [ #  # ]:              0 :     for (te = AH->toc->next; te != AH->toc; te = te->next)
                                843                 :                :     {
                                844                 :              0 :         lclTocEntry *tctx = (lclTocEntry *) te->formatData;
                                845                 :                : 
                                846                 :                :         /*
                                847                 :                :          * Ignore entries without a known data offset; if we were unable to
                                848                 :                :          * seek to rewrite the TOC when creating the archive, this'll be all
                                849                 :                :          * of them, and we'll end up with no size estimates.
                                850                 :                :          */
                                851         [ #  # ]:              0 :         if (tctx->dataState != K_OFFSET_POS_SET)
                                852                 :              0 :             continue;
                                853                 :                : 
                                854                 :                :         /* Compute previous data item's length */
                                855         [ #  # ]:              0 :         if (prev_te)
                                856                 :                :         {
                                857         [ #  # ]:              0 :             if (tctx->dataPos > prev_tctx->dataPos)
                                858                 :              0 :                 prev_te->dataLength = tctx->dataPos - prev_tctx->dataPos;
                                859                 :                :         }
                                860                 :                : 
                                861                 :              0 :         prev_te = te;
                                862                 :              0 :         prev_tctx = tctx;
                                863                 :                :     }
                                864                 :                : 
                                865                 :                :     /* If OK to seek, we can determine the length of the last item */
                                866   [ #  #  #  # ]:              0 :     if (prev_te && ctx->hasSeek)
                                867                 :                :     {
                                868                 :                :         pgoff_t     endpos;
                                869                 :                : 
                                870         [ #  # ]:              0 :         if (fseeko(AH->FH, 0, SEEK_END) != 0)
 1247                           871                 :              0 :             pg_fatal("error during file seek: %m");
 2549                           872                 :              0 :         endpos = ftello(AH->FH);
                                873         [ #  # ]:              0 :         if (endpos > prev_tctx->dataPos)
                                874                 :              0 :             prev_te->dataLength = endpos - prev_tctx->dataPos;
                                875                 :                :     }
                                876                 :              0 : }
                                877                 :                : 
                                878                 :                : /*
                                879                 :                :  * Clone format-specific fields during parallel restoration.
                                880                 :                :  */
                                881                 :                : static void
 5391 heikki.linnakangas@i      882                 :              0 : _Clone(ArchiveHandle *AH)
                                883                 :                : {
                                884                 :              0 :     lclContext *ctx = (lclContext *) AH->formatData;
                                885                 :                : 
                                886                 :                :     /*
                                887                 :                :      * Each thread must have private lclContext working state.
                                888                 :                :      */
 5034 bruce@momjian.us          889                 :              0 :     AH->formatData = (lclContext *) pg_malloc(sizeof(lclContext));
 5391 heikki.linnakangas@i      890                 :              0 :     memcpy(AH->formatData, ctx, sizeof(lclContext));
                                891                 :              0 :     ctx = (lclContext *) AH->formatData;
                                892                 :                : 
                                893                 :                :     /* sanity check, shouldn't happen */
                                894         [ #  # ]:              0 :     if (ctx->cs != NULL)
 1247 tgl@sss.pgh.pa.us         895                 :              0 :         pg_fatal("compressor active");
                                896                 :                : 
                                897                 :                :     /*
                                898                 :                :      * We intentionally do not clone TOC-entry-local state: it's useful to
                                899                 :                :      * share knowledge about where the data blocks are across threads.
                                900                 :                :      * _PrintTocData has to be careful about the order of operations on that
                                901                 :                :      * state, though.
                                902                 :                :      */
 5391 heikki.linnakangas@i      903                 :              0 : }
                                904                 :                : 
                                905                 :                : static void
                                906                 :              0 : _DeClone(ArchiveHandle *AH)
                                907                 :                : {
                                908                 :              0 :     lclContext *ctx = (lclContext *) AH->formatData;
                                909                 :                : 
                                910                 :              0 :     free(ctx);
                                911                 :              0 : }
                                912                 :                : 
                                913                 :                : /*
                                914                 :                :  * This function is executed in the child of a parallel restore from a
                                915                 :                :  * custom-format archive and restores the actual data for one TOC entry.
                                916                 :                :  */
                                917                 :                : static int
 3266 tgl@sss.pgh.pa.us         918                 :              0 : _WorkerJobRestoreCustom(ArchiveHandle *AH, TocEntry *te)
                                919                 :                : {
                                920                 :              0 :     return parallel_restore(AH, te);
                                921                 :                : }
                                922                 :                : 
                                923                 :                : /*--------------------------------------------------
                                924                 :                :  * END OF FORMAT CALLBACKS
                                925                 :                :  *--------------------------------------------------
                                926                 :                :  */
                                927                 :                : 
                                928                 :                : /*
                                929                 :                :  * Get the current position in the archive file.
                                930                 :                :  *
                                931                 :                :  * With a non-seekable archive file, we may not be able to obtain the
                                932                 :                :  * file position.  If so, just return -1.  It's not too important in
                                933                 :                :  * that case because we won't be able to rewrite the TOC to fill in
                                934                 :                :  * data block offsets anyway.
                                935                 :                :  */
                                936                 :                : static pgoff_t
 8934 bruce@momjian.us          937                 :CBC         405 : _getFilePos(ArchiveHandle *AH, lclContext *ctx)
                                938                 :                : {
                                939                 :                :     pgoff_t     pos;
                                940                 :                : 
 1877 tgl@sss.pgh.pa.us         941                 :            405 :     pos = ftello(AH->FH);
                                942         [ -  + ]:            405 :     if (pos < 0)
                                943                 :                :     {
                                944                 :                :         /* Not expected if we found we can seek. */
 1877 tgl@sss.pgh.pa.us         945         [ #  # ]:UBC           0 :         if (ctx->hasSeek)
 1247                           946                 :              0 :             pg_fatal("could not determine seek position in archive file: %m");
                                947                 :                :     }
 8934 bruce@momjian.us          948                 :CBC         405 :     return pos;
                                949                 :                : }
                                950                 :                : 
                                951                 :                : /*
                                952                 :                :  * Read a data block header. The format changed in V1.3, so we
                                953                 :                :  * centralize the code here for simplicity.  Returns *type = EOF
                                954                 :                :  * if at EOF.
                                955                 :                :  */
                                956                 :                : static void
                                957                 :            226 : _readBlockHeader(ArchiveHandle *AH, int *type, int *id)
                                958                 :                : {
                                959                 :                :     int         byt;
                                960                 :                : 
                                961                 :                :     /*
                                962                 :                :      * Note: if we are at EOF with a pre-1.3 input file, we'll pg_fatal()
                                963                 :                :      * inside ReadInt rather than returning EOF.  It doesn't seem worth
                                964                 :                :      * jumping through hoops to deal with that case better, because no such
                                965                 :                :      * files are likely to exist in the wild: only some 7.1 development
                                966                 :                :      * versions of pg_dump ever generated such files.
                                967                 :                :      */
                                968         [ -  + ]:            226 :     if (AH->version < K_VERS_1_3)
 9178 pjw@rhyme.com.au          969                 :UBC           0 :         *type = BLK_DATA;
                                970                 :                :     else
                                971                 :                :     {
 5550 tgl@sss.pgh.pa.us         972                 :CBC         226 :         byt = getc(AH->FH);
                                973                 :            226 :         *type = byt;
                                974         [ -  + ]:            226 :         if (byt == EOF)
                                975                 :                :         {
 5550 tgl@sss.pgh.pa.us         976                 :UBC           0 :             *id = 0;            /* don't return an uninitialized value */
                                977                 :              0 :             return;
                                978                 :                :         }
                                979                 :                :     }
                                980                 :                : 
 8934 bruce@momjian.us          981                 :CBC         226 :     *id = ReadInt(AH);
                                982                 :                : }
                                983                 :                : 
                                984                 :                : /*
                                985                 :                :  * Callback function for writeData. Writes one block of (compressed)
                                986                 :                :  * data to the archive.
                                987                 :                :  */
                                988                 :                : static void
 5392 heikki.linnakangas@i      989                 :            459 : _CustomWriteFunc(ArchiveHandle *AH, const char *buf, size_t len)
                                990                 :                : {
                                991                 :                :     /* never write 0-byte blocks (this should not happen) */
 4142 bruce@momjian.us          992         [ +  + ]:            459 :     if (len > 0)
                                993                 :                :     {
                                994                 :            287 :         WriteInt(AH, len);
                                995                 :            287 :         _WriteBuf(AH, buf, len);
                                996                 :                :     }
 9178 pjw@rhyme.com.au          997                 :            459 : }
                                998                 :                : 
                                999                 :                : /*
                               1000                 :                :  * Callback function for readData. To keep things simple, we
                               1001                 :                :  * always read one compressed block at a time.
                               1002                 :                :  */
                               1003                 :                : static size_t
 5392 heikki.linnakangas@i     1004                 :            494 : _CustomReadFunc(ArchiveHandle *AH, char **buf, size_t *buflen)
                               1005                 :                : {
                               1006                 :                :     size_t      blkLen;
                               1007                 :                : 
                               1008                 :                :     /* Read length */
                               1009                 :            494 :     blkLen = ReadInt(AH);
                               1010         [ +  + ]:            494 :     if (blkLen == 0)
                               1011                 :            226 :         return 0;
                               1012                 :                : 
                               1013                 :                :     /* If the caller's buffer is not large enough, allocate a bigger one */
                               1014         [ +  + ]:            268 :     if (blkLen > *buflen)
                               1015                 :                :     {
                               1016                 :              1 :         free(*buf);
 5034 bruce@momjian.us         1017                 :              1 :         *buf = (char *) pg_malloc(blkLen);
 5392 heikki.linnakangas@i     1018                 :              1 :         *buflen = blkLen;
                               1019                 :                :     }
                               1020                 :                : 
                               1021                 :                :     /* exits app on read errors */
 4142 bruce@momjian.us         1022                 :            268 :     _ReadBuf(AH, *buf, blkLen);
                               1023                 :                : 
                               1024                 :            268 :     return blkLen;
                               1025                 :                : }
        

Generated by: LCOV version 2.4-beta