PostgreSQL Source Code  git master
pg_backup_custom.c File Reference
#include "postgres_fe.h"
#include "common/file_utils.h"
#include "compress_io.h"
#include "parallel.h"
#include "pg_backup_utils.h"
Include dependency graph for pg_backup_custom.c:

Go to the source code of this file.

Data Structures

struct  lclContext
 
struct  lclTocEntry
 

Functions

static void _ArchiveEntry (ArchiveHandle *AH, TocEntry *te)
 
static void _StartData (ArchiveHandle *AH, TocEntry *te)
 
static void _WriteData (ArchiveHandle *AH, const void *data, size_t dLen)
 
static void _EndData (ArchiveHandle *AH, TocEntry *te)
 
static int _WriteByte (ArchiveHandle *AH, const int i)
 
static int _ReadByte (ArchiveHandle *)
 
static void _WriteBuf (ArchiveHandle *AH, const void *buf, size_t len)
 
static void _ReadBuf (ArchiveHandle *AH, void *buf, size_t len)
 
static void _CloseArchive (ArchiveHandle *AH)
 
static void _ReopenArchive (ArchiveHandle *AH)
 
static void _PrintTocData (ArchiveHandle *AH, TocEntry *te)
 
static void _WriteExtraToc (ArchiveHandle *AH, TocEntry *te)
 
static void _ReadExtraToc (ArchiveHandle *AH, TocEntry *te)
 
static void _PrintExtraToc (ArchiveHandle *AH, TocEntry *te)
 
static void _PrintData (ArchiveHandle *AH)
 
static void _skipData (ArchiveHandle *AH)
 
static void _skipBlobs (ArchiveHandle *AH)
 
static void _StartBlobs (ArchiveHandle *AH, TocEntry *te)
 
static void _StartBlob (ArchiveHandle *AH, TocEntry *te, Oid oid)
 
static void _EndBlob (ArchiveHandle *AH, TocEntry *te, Oid oid)
 
static void _EndBlobs (ArchiveHandle *AH, TocEntry *te)
 
static void _LoadBlobs (ArchiveHandle *AH, bool drop)
 
static void _PrepParallelRestore (ArchiveHandle *AH)
 
static void _Clone (ArchiveHandle *AH)
 
static void _DeClone (ArchiveHandle *AH)
 
static int _WorkerJobRestoreCustom (ArchiveHandle *AH, TocEntry *te)
 
static void _readBlockHeader (ArchiveHandle *AH, int *type, int *id)
 
static pgoff_t _getFilePos (ArchiveHandle *AH, lclContext *ctx)
 
static void _CustomWriteFunc (ArchiveHandle *AH, const char *buf, size_t len)
 
static size_t _CustomReadFunc (ArchiveHandle *AH, char **buf, size_t *buflen)
 
void InitArchiveFmt_Custom (ArchiveHandle *AH)
 

Function Documentation

◆ _ArchiveEntry()

static void _ArchiveEntry ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 203 of file pg_backup_custom.c.

References _tocEntry::dataDumper, lclTocEntry::dataState, _tocEntry::formatData, K_OFFSET_NO_DATA, K_OFFSET_POS_NOT_SET, and pg_malloc0().

Referenced by InitArchiveFmt_Custom().

204 {
205  lclTocEntry *ctx;
206 
207  ctx = (lclTocEntry *) pg_malloc0(sizeof(lclTocEntry));
208  if (te->dataDumper)
210  else
212 
213  te->formatData = (void *) ctx;
214 }
DataDumperPtr dataDumper
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
#define K_OFFSET_NO_DATA
#define K_OFFSET_POS_NOT_SET

◆ _Clone()

static void _Clone ( ArchiveHandle AH)
static

Definition at line 879 of file pg_backup_custom.c.

References lclContext::cs, fatal, _archiveHandle::formatData, and pg_malloc().

Referenced by InitArchiveFmt_Custom().

880 {
881  lclContext *ctx = (lclContext *) AH->formatData;
882 
883  /*
884  * Each thread must have private lclContext working state.
885  */
886  AH->formatData = (lclContext *) pg_malloc(sizeof(lclContext));
887  memcpy(AH->formatData, ctx, sizeof(lclContext));
888  ctx = (lclContext *) AH->formatData;
889 
890  /* sanity check, shouldn't happen */
891  if (ctx->cs != NULL)
892  fatal("compressor active");
893 
894  /*
895  * We intentionally do not clone TOC-entry-local state: it's useful to
896  * share knowledge about where the data blocks are across threads.
897  * _PrintTocData has to be careful about the order of operations on that
898  * state, though.
899  *
900  * Note: we do not make a local lo_buf because we expect at most one BLOBS
901  * entry per archive, so no parallelism is possible.
902  */
903 }
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
CompressorState * cs
#define fatal(...)

◆ _CloseArchive()

static void _CloseArchive ( ArchiveHandle AH)
static

Definition at line 738 of file pg_backup_custom.c.

References archModeWrite, _archiveHandle::dosync, fatal, _archiveHandle::FH, _archiveHandle::formatData, fseeko, _archiveHandle::fSpec, fsync_fname(), ftello, lclContext::hasSeek, _archiveHandle::mode, pgoff_t, WriteDataChunks(), WriteHead(), and WriteToc().

Referenced by InitArchiveFmt_Custom().

739 {
740  lclContext *ctx = (lclContext *) AH->formatData;
741  pgoff_t tpos;
742 
743  if (AH->mode == archModeWrite)
744  {
745  WriteHead(AH);
746  /* Remember TOC's seek position for use below */
747  tpos = ftello(AH->FH);
748  if (tpos < 0 && ctx->hasSeek)
749  fatal("could not determine seek position in archive file: %m");
750  WriteToc(AH);
751  WriteDataChunks(AH, NULL);
752 
753  /*
754  * If possible, re-write the TOC in order to update the data offset
755  * information. This is not essential, as pg_restore can cope in most
756  * cases without it; but it can make pg_restore significantly faster
757  * in some situations (especially parallel restore).
758  */
759  if (ctx->hasSeek &&
760  fseeko(AH->FH, tpos, SEEK_SET) == 0)
761  WriteToc(AH);
762  }
763 
764  if (fclose(AH->FH) != 0)
765  fatal("could not close archive file: %m");
766 
767  /* Sync the output file if one is defined */
768  if (AH->dosync && AH->mode == archModeWrite && AH->fSpec)
769  (void) fsync_fname(AH->fSpec, false);
770 
771  AH->FH = NULL;
772 }
void WriteDataChunks(ArchiveHandle *AH, ParallelState *pstate)
void fsync_fname(const char *fname, bool isdir)
Definition: fd.c:632
void WriteToc(ArchiveHandle *AH)
#define pgoff_t
Definition: win32_port.h:194
#define ftello(stream)
Definition: win32_port.h:204
#define fseeko(stream, offset, origin)
Definition: win32_port.h:201
#define fatal(...)
void WriteHead(ArchiveHandle *AH)

◆ _CustomReadFunc()

static size_t _CustomReadFunc ( ArchiveHandle AH,
char **  buf,
size_t *  buflen 
)
static

Definition at line 1004 of file pg_backup_custom.c.

References _ReadBuf(), free, pg_malloc(), and ReadInt().

Referenced by _PrintData().

1005 {
1006  size_t blkLen;
1007 
1008  /* Read length */
1009  blkLen = ReadInt(AH);
1010  if (blkLen == 0)
1011  return 0;
1012 
1013  /* If the caller's buffer is not large enough, allocate a bigger one */
1014  if (blkLen > *buflen)
1015  {
1016  free(*buf);
1017  *buf = (char *) pg_malloc(blkLen);
1018  *buflen = blkLen;
1019  }
1020 
1021  /* exits app on read errors */
1022  _ReadBuf(AH, *buf, blkLen);
1023 
1024  return blkLen;
1025 }
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
static void _ReadBuf(ArchiveHandle *AH, void *buf, size_t len)
int ReadInt(ArchiveHandle *AH)
static char * buf
Definition: pg_test_fsync.c:67
#define free(a)
Definition: header.h:65

◆ _CustomWriteFunc()

static void _CustomWriteFunc ( ArchiveHandle AH,
const char *  buf,
size_t  len 
)
static

Definition at line 989 of file pg_backup_custom.c.

References _WriteBuf(), and WriteInt().

Referenced by _StartBlob(), and _StartData().

990 {
991  /* never write 0-byte blocks (this should not happen) */
992  if (len > 0)
993  {
994  WriteInt(AH, len);
995  _WriteBuf(AH, buf, len);
996  }
997 }
static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len)
static char * buf
Definition: pg_test_fsync.c:67
size_t WriteInt(ArchiveHandle *AH, int i)

◆ _DeClone()

static void _DeClone ( ArchiveHandle AH)
static

Definition at line 906 of file pg_backup_custom.c.

References _archiveHandle::formatData, and free.

Referenced by InitArchiveFmt_Custom().

907 {
908  lclContext *ctx = (lclContext *) AH->formatData;
909 
910  free(ctx);
911 }
#define free(a)
Definition: header.h:65

◆ _EndBlob()

static void _EndBlob ( ArchiveHandle AH,
TocEntry te,
Oid  oid 
)
static

Definition at line 389 of file pg_backup_custom.c.

References lclContext::cs, EndCompressor(), _archiveHandle::formatData, and WriteInt().

Referenced by InitArchiveFmt_Custom().

390 {
391  lclContext *ctx = (lclContext *) AH->formatData;
392 
393  EndCompressor(AH, ctx->cs);
394  /* Send the end marker */
395  WriteInt(AH, 0);
396 }
CompressorState * cs
size_t WriteInt(ArchiveHandle *AH, int i)
void EndCompressor(ArchiveHandle *AH, CompressorState *cs)
Definition: compress_io.c:201

◆ _EndBlobs()

static void _EndBlobs ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 404 of file pg_backup_custom.c.

References WriteInt().

Referenced by InitArchiveFmt_Custom().

405 {
406  /* Write out a fake zero OID to mark end-of-blobs. */
407  WriteInt(AH, 0);
408 }
size_t WriteInt(ArchiveHandle *AH, int i)

◆ _EndData()

static void _EndData ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 331 of file pg_backup_custom.c.

References lclContext::cs, EndCompressor(), _archiveHandle::formatData, and WriteInt().

Referenced by InitArchiveFmt_Custom().

332 {
333  lclContext *ctx = (lclContext *) AH->formatData;
334 
335  EndCompressor(AH, ctx->cs);
336  /* Send the end marker */
337  WriteInt(AH, 0);
338 }
CompressorState * cs
size_t WriteInt(ArchiveHandle *AH, int i)
void EndCompressor(ArchiveHandle *AH, CompressorState *cs)
Definition: compress_io.c:201

◆ _getFilePos()

static pgoff_t _getFilePos ( ArchiveHandle AH,
lclContext ctx 
)
static

Definition at line 937 of file pg_backup_custom.c.

References fatal, _archiveHandle::FH, ftello, lclContext::hasSeek, and pgoff_t.

Referenced by _PrintTocData(), _StartBlobs(), _StartData(), and InitArchiveFmt_Custom().

938 {
939  pgoff_t pos;
940 
941  pos = ftello(AH->FH);
942  if (pos < 0)
943  {
944  /* Not expected if we found we can seek. */
945  if (ctx->hasSeek)
946  fatal("could not determine seek position in archive file: %m");
947  }
948  return pos;
949 }
#define pgoff_t
Definition: win32_port.h:194
#define ftello(stream)
Definition: win32_port.h:204
#define fatal(...)

◆ _LoadBlobs()

static void _LoadBlobs ( ArchiveHandle AH,
bool  drop 
)
static

Definition at line 573 of file pg_backup_custom.c.

References _PrintData(), EndRestoreBlob(), EndRestoreBlobs(), ReadInt(), StartRestoreBlob(), and StartRestoreBlobs().

Referenced by _PrintTocData().

574 {
575  Oid oid;
576 
577  StartRestoreBlobs(AH);
578 
579  oid = ReadInt(AH);
580  while (oid != 0)
581  {
582  StartRestoreBlob(AH, oid, drop);
583  _PrintData(AH);
584  EndRestoreBlob(AH, oid);
585  oid = ReadInt(AH);
586  }
587 
588  EndRestoreBlobs(AH);
589 }
int ReadInt(ArchiveHandle *AH)
unsigned int Oid
Definition: postgres_ext.h:31
void StartRestoreBlobs(ArchiveHandle *AH)
static void _PrintData(ArchiveHandle *AH)
void StartRestoreBlob(ArchiveHandle *AH, Oid oid, bool drop)
void EndRestoreBlobs(ArchiveHandle *AH)
void EndRestoreBlob(ArchiveHandle *AH, Oid oid)

◆ _PrepParallelRestore()

static void _PrepParallelRestore ( ArchiveHandle AH)
static

Definition at line 827 of file pg_backup_custom.c.

References lclTocEntry::dataPos, lclTocEntry::dataState, endpos, fatal, _archiveHandle::FH, _archiveHandle::formatData, fseeko, ftello, lclContext::hasSeek, K_OFFSET_POS_SET, _tocEntry::next, pgoff_t, and _archiveHandle::toc.

Referenced by InitArchiveFmt_Custom().

828 {
829  lclContext *ctx = (lclContext *) AH->formatData;
830  TocEntry *prev_te = NULL;
831  lclTocEntry *prev_tctx = NULL;
832  TocEntry *te;
833 
834  /*
835  * Knowing that the data items were dumped out in TOC order, we can
836  * reconstruct the length of each item as the delta to the start offset of
837  * the next data item.
838  */
839  for (te = AH->toc->next; te != AH->toc; te = te->next)
840  {
841  lclTocEntry *tctx = (lclTocEntry *) te->formatData;
842 
843  /*
844  * Ignore entries without a known data offset; if we were unable to
845  * seek to rewrite the TOC when creating the archive, this'll be all
846  * of them, and we'll end up with no size estimates.
847  */
848  if (tctx->dataState != K_OFFSET_POS_SET)
849  continue;
850 
851  /* Compute previous data item's length */
852  if (prev_te)
853  {
854  if (tctx->dataPos > prev_tctx->dataPos)
855  prev_te->dataLength = tctx->dataPos - prev_tctx->dataPos;
856  }
857 
858  prev_te = te;
859  prev_tctx = tctx;
860  }
861 
862  /* If OK to seek, we can determine the length of the last item */
863  if (prev_te && ctx->hasSeek)
864  {
865  pgoff_t endpos;
866 
867  if (fseeko(AH->FH, 0, SEEK_END) != 0)
868  fatal("error during file seek: %m");
869  endpos = ftello(AH->FH);
870  if (endpos > prev_tctx->dataPos)
871  prev_te->dataLength = endpos - prev_tctx->dataPos;
872  }
873 }
struct _tocEntry * next
#define pgoff_t
Definition: win32_port.h:194
#define ftello(stream)
Definition: win32_port.h:204
static XLogRecPtr endpos
Definition: pg_receivewal.c:46
struct _tocEntry * toc
#define fseeko(stream, offset, origin)
Definition: win32_port.h:201
#define fatal(...)
#define K_OFFSET_POS_SET

◆ _PrintData()

static void _PrintData ( ArchiveHandle AH)
static

Definition at line 567 of file pg_backup_custom.c.

References _CustomReadFunc(), _archiveHandle::compression, and ReadDataFromArchive().

Referenced by _LoadBlobs(), and _PrintTocData().

568 {
570 }
void ReadDataFromArchive(ArchiveHandle *AH, int compression, ReadFunc readF)
Definition: compress_io.c:157
static size_t _CustomReadFunc(ArchiveHandle *AH, char **buf, size_t *buflen)

◆ _PrintExtraToc()

static void _PrintExtraToc ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 269 of file pg_backup_custom.c.

References ahprintf(), lclTocEntry::dataPos, _tocEntry::formatData, INT64_FORMAT, _archiveHandle::public, and Archive::verbose.

Referenced by InitArchiveFmt_Custom().

270 {
271  lclTocEntry *ctx = (lclTocEntry *) te->formatData;
272 
273  if (AH->public.verbose)
274  ahprintf(AH, "-- Data Pos: " INT64_FORMAT "\n",
275  (int64) ctx->dataPos);
276 }
int ahprintf(ArchiveHandle *AH, const char *fmt,...)
int verbose
Definition: pg_backup.h:185
#define INT64_FORMAT
Definition: c.h:416

◆ _PrintTocData()

static void _PrintTocData ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 414 of file pg_backup_custom.c.

References _getFilePos(), _LoadBlobs(), _PrintData(), _readBlockHeader(), _skipBlobs(), _skipData(), BLK_BLOBS, BLK_DATA, lclTocEntry::dataPos, lclTocEntry::dataState, _restoreOptions::dropSchema, _tocEntry::dumpId, fatal, _archiveHandle::FH, _archiveHandle::formatData, _tocEntry::formatData, fseeko, getTocEntryByDumpId(), lclContext::hasSeek, K_OFFSET_NO_DATA, K_OFFSET_POS_NOT_SET, K_OFFSET_POS_SET, lclContext::lastFilePos, pg_log_warning, pgoff_t, _archiveHandle::public, and Archive::ropt.

Referenced by InitArchiveFmt_Custom().

415 {
416  lclContext *ctx = (lclContext *) AH->formatData;
417  lclTocEntry *tctx = (lclTocEntry *) te->formatData;
418  int blkType;
419  int id;
420 
421  if (tctx->dataState == K_OFFSET_NO_DATA)
422  return;
423 
424  if (!ctx->hasSeek || tctx->dataState == K_OFFSET_POS_NOT_SET)
425  {
426  /*
427  * We cannot seek directly to the desired block. Instead, skip over
428  * block headers until we find the one we want. Remember the
429  * positions of skipped-over blocks, so that if we later decide we
430  * need to read one, we'll be able to seek to it.
431  *
432  * When our input file is seekable, we can do the search starting from
433  * the point after the last data block we scanned in previous
434  * iterations of this function.
435  */
436  if (ctx->hasSeek)
437  {
438  if (fseeko(AH->FH, ctx->lastFilePos, SEEK_SET) != 0)
439  fatal("error during file seek: %m");
440  }
441 
442  for (;;)
443  {
444  pgoff_t thisBlkPos = _getFilePos(AH, ctx);
445 
446  _readBlockHeader(AH, &blkType, &id);
447 
448  if (blkType == EOF || id == te->dumpId)
449  break;
450 
451  /* Remember the block position, if we got one */
452  if (thisBlkPos >= 0)
453  {
454  TocEntry *otherte = getTocEntryByDumpId(AH, id);
455 
456  if (otherte && otherte->formatData)
457  {
458  lclTocEntry *othertctx = (lclTocEntry *) otherte->formatData;
459 
460  /*
461  * Note: on Windows, multiple threads might access/update
462  * the same lclTocEntry concurrently, but that should be
463  * safe as long as we update dataPos before dataState.
464  * Ideally, we'd use pg_write_barrier() to enforce that,
465  * but the needed infrastructure doesn't exist in frontend
466  * code. But Windows only runs on machines with strong
467  * store ordering, so it should be okay for now.
468  */
469  if (othertctx->dataState == K_OFFSET_POS_NOT_SET)
470  {
471  othertctx->dataPos = thisBlkPos;
472  othertctx->dataState = K_OFFSET_POS_SET;
473  }
474  else if (othertctx->dataPos != thisBlkPos ||
475  othertctx->dataState != K_OFFSET_POS_SET)
476  {
477  /* sanity check */
478  pg_log_warning("data block %d has wrong seek position",
479  id);
480  }
481  }
482  }
483 
484  switch (blkType)
485  {
486  case BLK_DATA:
487  _skipData(AH);
488  break;
489 
490  case BLK_BLOBS:
491  _skipBlobs(AH);
492  break;
493 
494  default: /* Always have a default */
495  fatal("unrecognized data block type (%d) while searching archive",
496  blkType);
497  break;
498  }
499  }
500  }
501  else
502  {
503  /* We can just seek to the place we need to be. */
504  if (fseeko(AH->FH, tctx->dataPos, SEEK_SET) != 0)
505  fatal("error during file seek: %m");
506 
507  _readBlockHeader(AH, &blkType, &id);
508  }
509 
510  /*
511  * If we reached EOF without finding the block we want, then either it
512  * doesn't exist, or it does but we lack the ability to seek back to it.
513  */
514  if (blkType == EOF)
515  {
516  if (!ctx->hasSeek)
517  fatal("could not find block ID %d in archive -- "
518  "possibly due to out-of-order restore request, "
519  "which cannot be handled due to non-seekable input file",
520  te->dumpId);
521  else
522  fatal("could not find block ID %d in archive -- "
523  "possibly corrupt archive",
524  te->dumpId);
525  }
526 
527  /* Are we sane? */
528  if (id != te->dumpId)
529  fatal("found unexpected block ID (%d) when reading data -- expected %d",
530  id, te->dumpId);
531 
532  switch (blkType)
533  {
534  case BLK_DATA:
535  _PrintData(AH);
536  break;
537 
538  case BLK_BLOBS:
539  _LoadBlobs(AH, AH->public.ropt->dropSchema);
540  break;
541 
542  default: /* Always have a default */
543  fatal("unrecognized data block type %d while restoring archive",
544  blkType);
545  break;
546  }
547 
548  /*
549  * If our input file is seekable but lacks data offsets, update our
550  * knowledge of where to start future searches from. (Note that we did
551  * not update the current TE's dataState/dataPos. We could have, but
552  * there is no point since it will not be visited again.)
553  */
554  if (ctx->hasSeek && tctx->dataState == K_OFFSET_POS_NOT_SET)
555  {
556  pgoff_t curPos = _getFilePos(AH, ctx);
557 
558  if (curPos > ctx->lastFilePos)
559  ctx->lastFilePos = curPos;
560  }
561 }
static void _readBlockHeader(ArchiveHandle *AH, int *type, int *id)
#define BLK_DATA
RestoreOptions * ropt
Definition: pg_backup.h:183
#define BLK_BLOBS
static void _skipBlobs(ArchiveHandle *AH)
static void _PrintData(ArchiveHandle *AH)
#define pgoff_t
Definition: win32_port.h:194
TocEntry * getTocEntryByDumpId(ArchiveHandle *AH, DumpId id)
static void _LoadBlobs(ArchiveHandle *AH, bool drop)
#define K_OFFSET_NO_DATA
static void _skipData(ArchiveHandle *AH)
#define fseeko(stream, offset, origin)
Definition: win32_port.h:201
static pgoff_t _getFilePos(ArchiveHandle *AH, lclContext *ctx)
#define fatal(...)
#define K_OFFSET_POS_SET
pgoff_t lastFilePos
#define pg_log_warning(...)
Definition: pgfnames.c:24
#define K_OFFSET_POS_NOT_SET

◆ _readBlockHeader()

static void _readBlockHeader ( ArchiveHandle AH,
int *  type,
int *  id 
)
static

Definition at line 957 of file pg_backup_custom.c.

References BLK_DATA, _archiveHandle::FH, K_VERS_1_3, ReadInt(), and _archiveHandle::version.

Referenced by _PrintTocData().

958 {
959  int byt;
960 
961  /*
962  * Note: if we are at EOF with a pre-1.3 input file, we'll fatal() inside
963  * ReadInt rather than returning EOF. It doesn't seem worth jumping
964  * through hoops to deal with that case better, because no such files are
965  * likely to exist in the wild: only some 7.1 development versions of
966  * pg_dump ever generated such files.
967  */
968  if (AH->version < K_VERS_1_3)
969  *type = BLK_DATA;
970  else
971  {
972  byt = getc(AH->FH);
973  *type = byt;
974  if (byt == EOF)
975  {
976  *id = 0; /* don't return an uninitialized value */
977  return;
978  }
979  }
980 
981  *id = ReadInt(AH);
982 }
#define BLK_DATA
int ReadInt(ArchiveHandle *AH)
#define K_VERS_1_3

◆ _ReadBuf()

static void _ReadBuf ( ArchiveHandle AH,
void *  buf,
size_t  len 
)
static

Definition at line 716 of file pg_backup_custom.c.

References _archiveHandle::FH, and READ_ERROR_EXIT.

Referenced by _CustomReadFunc(), and InitArchiveFmt_Custom().

717 {
718  if (fread(buf, 1, len, AH->FH) != len)
719  READ_ERROR_EXIT(AH->FH);
720 }
static char * buf
Definition: pg_test_fsync.c:67
#define READ_ERROR_EXIT(fd)

◆ _ReadByte()

static int _ReadByte ( ArchiveHandle AH)
static

Definition at line 684 of file pg_backup_custom.c.

References _archiveHandle::FH, and READ_ERROR_EXIT.

Referenced by InitArchiveFmt_Custom().

685 {
686  int res;
687 
688  res = getc(AH->FH);
689  if (res == EOF)
690  READ_ERROR_EXIT(AH->FH);
691  return res;
692 }
#define READ_ERROR_EXIT(fd)

◆ _ReadExtraToc()

static void _ReadExtraToc ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 242 of file pg_backup_custom.c.

References lclTocEntry::dataPos, lclTocEntry::dataState, _tocEntry::formatData, K_VERS_1_7, pg_malloc0(), ReadInt(), ReadOffset(), and _archiveHandle::version.

Referenced by InitArchiveFmt_Custom().

243 {
244  lclTocEntry *ctx = (lclTocEntry *) te->formatData;
245 
246  if (ctx == NULL)
247  {
248  ctx = (lclTocEntry *) pg_malloc0(sizeof(lclTocEntry));
249  te->formatData = (void *) ctx;
250  }
251 
252  ctx->dataState = ReadOffset(AH, &(ctx->dataPos));
253 
254  /*
255  * Prior to V1.7 (pg7.3), we dumped the data size as an int now we don't
256  * dump it at all.
257  */
258  if (AH->version < K_VERS_1_7)
259  ReadInt(AH);
260 }
int ReadInt(ArchiveHandle *AH)
#define K_VERS_1_7
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
int ReadOffset(ArchiveHandle *AH, pgoff_t *o)

◆ _ReopenArchive()

static void _ReopenArchive ( ArchiveHandle AH)
static

Definition at line 782 of file pg_backup_custom.c.

References archModeWrite, fatal, _archiveHandle::FH, _archiveHandle::formatData, fseeko, _archiveHandle::fSpec, ftello, lclContext::hasSeek, _archiveHandle::mode, PG_BINARY_R, and pgoff_t.

Referenced by InitArchiveFmt_Custom().

783 {
784  lclContext *ctx = (lclContext *) AH->formatData;
785  pgoff_t tpos;
786 
787  if (AH->mode == archModeWrite)
788  fatal("can only reopen input archives");
789 
790  /*
791  * These two cases are user-facing errors since they represent unsupported
792  * (but not invalid) use-cases. Word the error messages appropriately.
793  */
794  if (AH->fSpec == NULL || strcmp(AH->fSpec, "") == 0)
795  fatal("parallel restore from standard input is not supported");
796  if (!ctx->hasSeek)
797  fatal("parallel restore from non-seekable file is not supported");
798 
799  tpos = ftello(AH->FH);
800  if (tpos < 0)
801  fatal("could not determine seek position in archive file: %m");
802 
803 #ifndef WIN32
804  if (fclose(AH->FH) != 0)
805  fatal("could not close archive file: %m");
806 #endif
807 
808  AH->FH = fopen(AH->fSpec, PG_BINARY_R);
809  if (!AH->FH)
810  fatal("could not open input file \"%s\": %m", AH->fSpec);
811 
812  if (fseeko(AH->FH, tpos, SEEK_SET) != 0)
813  fatal("could not set seek position in archive file: %m");
814 }
#define PG_BINARY_R
Definition: c.h:1242
#define pgoff_t
Definition: win32_port.h:194
#define ftello(stream)
Definition: win32_port.h:204
#define fseeko(stream, offset, origin)
Definition: win32_port.h:201
#define fatal(...)

◆ _skipBlobs()

static void _skipBlobs ( ArchiveHandle AH)
static

Definition at line 598 of file pg_backup_custom.c.

References _skipData(), and ReadInt().

Referenced by _PrintTocData().

599 {
600  Oid oid;
601 
602  oid = ReadInt(AH);
603  while (oid != 0)
604  {
605  _skipData(AH);
606  oid = ReadInt(AH);
607  }
608 }
int ReadInt(ArchiveHandle *AH)
unsigned int Oid
Definition: postgres_ext.h:31
static void _skipData(ArchiveHandle *AH)

◆ _skipData()

static void _skipData ( ArchiveHandle AH)
static

Definition at line 616 of file pg_backup_custom.c.

References buf, fatal, _archiveHandle::FH, _archiveHandle::formatData, free, fseeko, lclContext::hasSeek, pg_malloc(), and ReadInt().

Referenced by _PrintTocData(), and _skipBlobs().

617 {
618  lclContext *ctx = (lclContext *) AH->formatData;
619  size_t blkLen;
620  char *buf = NULL;
621  int buflen = 0;
622  size_t cnt;
623 
624  blkLen = ReadInt(AH);
625  while (blkLen != 0)
626  {
627  if (ctx->hasSeek)
628  {
629  if (fseeko(AH->FH, blkLen, SEEK_CUR) != 0)
630  fatal("error during file seek: %m");
631  }
632  else
633  {
634  if (blkLen > buflen)
635  {
636  if (buf)
637  free(buf);
638  buf = (char *) pg_malloc(blkLen);
639  buflen = blkLen;
640  }
641  if ((cnt = fread(buf, 1, blkLen, AH->FH)) != blkLen)
642  {
643  if (feof(AH->FH))
644  fatal("could not read from input file: end of file");
645  else
646  fatal("could not read from input file: %m");
647  }
648  }
649 
650  blkLen = ReadInt(AH);
651  }
652 
653  if (buf)
654  free(buf);
655 }
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
int ReadInt(ArchiveHandle *AH)
static char * buf
Definition: pg_test_fsync.c:67
#define fseeko(stream, offset, origin)
Definition: win32_port.h:201
#define free(a)
Definition: header.h:65
#define fatal(...)

◆ _StartBlob()

static void _StartBlob ( ArchiveHandle AH,
TocEntry te,
Oid  oid 
)
static

Definition at line 371 of file pg_backup_custom.c.

References _CustomWriteFunc(), AllocateCompressor(), _archiveHandle::compression, lclContext::cs, fatal, _archiveHandle::formatData, and WriteInt().

Referenced by InitArchiveFmt_Custom().

372 {
373  lclContext *ctx = (lclContext *) AH->formatData;
374 
375  if (oid == 0)
376  fatal("invalid OID for large object");
377 
378  WriteInt(AH, oid);
379 
381 }
CompressorState * AllocateCompressor(int compression, WriteFunc writeF)
Definition: compress_io.c:124
CompressorState * cs
size_t WriteInt(ArchiveHandle *AH, int i)
#define fatal(...)
static void _CustomWriteFunc(ArchiveHandle *AH, const char *buf, size_t len)

◆ _StartBlobs()

static void _StartBlobs ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 350 of file pg_backup_custom.c.

References _getFilePos(), _WriteByte(), BLK_BLOBS, _tocEntry::dumpId, _archiveHandle::formatData, _tocEntry::formatData, K_OFFSET_POS_SET, and WriteInt().

Referenced by InitArchiveFmt_Custom().

351 {
352  lclContext *ctx = (lclContext *) AH->formatData;
353  lclTocEntry *tctx = (lclTocEntry *) te->formatData;
354 
355  tctx->dataPos = _getFilePos(AH, ctx);
356  if (tctx->dataPos >= 0)
357  tctx->dataState = K_OFFSET_POS_SET;
358 
359  _WriteByte(AH, BLK_BLOBS); /* Block type */
360  WriteInt(AH, te->dumpId); /* For sanity check */
361 }
#define BLK_BLOBS
static pgoff_t _getFilePos(ArchiveHandle *AH, lclContext *ctx)
size_t WriteInt(ArchiveHandle *AH, int i)
#define K_OFFSET_POS_SET
static int _WriteByte(ArchiveHandle *AH, const int i)

◆ _StartData()

static void _StartData ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 289 of file pg_backup_custom.c.

References _CustomWriteFunc(), _getFilePos(), _WriteByte(), AllocateCompressor(), BLK_DATA, _archiveHandle::compression, lclContext::cs, _tocEntry::dumpId, _archiveHandle::formatData, _tocEntry::formatData, K_OFFSET_POS_SET, and WriteInt().

Referenced by InitArchiveFmt_Custom().

290 {
291  lclContext *ctx = (lclContext *) AH->formatData;
292  lclTocEntry *tctx = (lclTocEntry *) te->formatData;
293 
294  tctx->dataPos = _getFilePos(AH, ctx);
295  if (tctx->dataPos >= 0)
296  tctx->dataState = K_OFFSET_POS_SET;
297 
298  _WriteByte(AH, BLK_DATA); /* Block type */
299  WriteInt(AH, te->dumpId); /* For sanity check */
300 
302 }
#define BLK_DATA
CompressorState * AllocateCompressor(int compression, WriteFunc writeF)
Definition: compress_io.c:124
CompressorState * cs
static pgoff_t _getFilePos(ArchiveHandle *AH, lclContext *ctx)
size_t WriteInt(ArchiveHandle *AH, int i)
#define K_OFFSET_POS_SET
static void _CustomWriteFunc(ArchiveHandle *AH, const char *buf, size_t len)
static int _WriteByte(ArchiveHandle *AH, const int i)

◆ _WorkerJobRestoreCustom()

static int _WorkerJobRestoreCustom ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 918 of file pg_backup_custom.c.

References parallel_restore(), and pgoff_t.

Referenced by InitArchiveFmt_Custom().

919 {
920  return parallel_restore(AH, te);
921 }
int parallel_restore(ArchiveHandle *AH, TocEntry *te)

◆ _WriteBuf()

static void _WriteBuf ( ArchiveHandle AH,
const void *  buf,
size_t  len 
)
static

Definition at line 702 of file pg_backup_custom.c.

References _archiveHandle::FH, and WRITE_ERROR_EXIT.

Referenced by _CustomWriteFunc(), and InitArchiveFmt_Custom().

703 {
704  if (fwrite(buf, 1, len, AH->FH) != len)
706 }
static char * buf
Definition: pg_test_fsync.c:67
#define WRITE_ERROR_EXIT

◆ _WriteByte()

static int _WriteByte ( ArchiveHandle AH,
const int  i 
)
static

Definition at line 665 of file pg_backup_custom.c.

References _archiveHandle::FH, and WRITE_ERROR_EXIT.

Referenced by _StartBlobs(), _StartData(), and InitArchiveFmt_Custom().

666 {
667  int res;
668 
669  if ((res = fputc(i, AH->FH)) == EOF)
671 
672  return 1;
673 }
#define WRITE_ERROR_EXIT
int i

◆ _WriteData()

static void _WriteData ( ArchiveHandle AH,
const void *  data,
size_t  dLen 
)
static

Definition at line 314 of file pg_backup_custom.c.

References lclContext::cs, _archiveHandle::formatData, and WriteDataToArchive().

Referenced by InitArchiveFmt_Custom().

315 {
316  lclContext *ctx = (lclContext *) AH->formatData;
317  CompressorState *cs = ctx->cs;
318 
319  if (dLen > 0)
320  /* WriteDataToArchive() internally throws write errors */
321  WriteDataToArchive(AH, cs, data, dLen);
322 }
void WriteDataToArchive(ArchiveHandle *AH, CompressorState *cs, const void *data, size_t dLen)
Definition: compress_io.c:179
CompressorState * cs

◆ _WriteExtraToc()

static void _WriteExtraToc ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 226 of file pg_backup_custom.c.

References lclTocEntry::dataPos, lclTocEntry::dataState, _tocEntry::formatData, and WriteOffset().

Referenced by InitArchiveFmt_Custom().

227 {
228  lclTocEntry *ctx = (lclTocEntry *) te->formatData;
229 
230  WriteOffset(AH, ctx->dataPos, ctx->dataState);
231 }
size_t WriteOffset(ArchiveHandle *AH, pgoff_t o, int wasSet)

◆ InitArchiveFmt_Custom()

void InitArchiveFmt_Custom ( ArchiveHandle AH)

Definition at line 106 of file pg_backup_custom.c.

References _ArchiveEntry(), _Clone(), _CloseArchive(), _DeClone(), _EndBlob(), _EndBlobs(), _EndData(), _getFilePos(), _PrepParallelRestore(), _PrintExtraToc(), _PrintTocData(), _ReadBuf(), _ReadByte(), _ReadExtraToc(), _ReopenArchive(), _StartBlob(), _StartBlobs(), _StartData(), _WorkerJobRestoreCustom(), _WriteBuf(), _WriteByte(), _WriteData(), _WriteExtraToc(), _archiveHandle::ArchiveEntryPtr, archModeWrite, checkSeek(), _archiveHandle::ClonePtr, _archiveHandle::ClosePtr, _archiveHandle::DeClonePtr, _archiveHandle::EndBlobPtr, _archiveHandle::EndBlobsPtr, _archiveHandle::EndDataPtr, fatal, _archiveHandle::FH, _archiveHandle::formatData, _archiveHandle::fSpec, lclContext::hasSeek, lclContext::lastFilePos, _archiveHandle::lo_buf, _archiveHandle::lo_buf_size, LOBBUFSIZE, _archiveHandle::mode, PG_BINARY_R, PG_BINARY_W, pg_malloc(), pg_malloc0(), _archiveHandle::PrepParallelRestorePtr, _archiveHandle::PrintExtraTocPtr, _archiveHandle::PrintTocDataPtr, _archiveHandle::ReadBufPtr, _archiveHandle::ReadBytePtr, _archiveHandle::ReadExtraTocPtr, ReadHead(), ReadToc(), _archiveHandle::ReopenPtr, _archiveHandle::StartBlobPtr, _archiveHandle::StartBlobsPtr, _archiveHandle::StartDataPtr, generate_unaccent_rules::stdout, _archiveHandle::WorkerJobDumpPtr, _archiveHandle::WorkerJobRestorePtr, _archiveHandle::WriteBufPtr, _archiveHandle::WriteBytePtr, _archiveHandle::WriteDataPtr, and _archiveHandle::WriteExtraTocPtr.

Referenced by _allocAH().

107 {
108  lclContext *ctx;
109 
110  /* Assuming static functions, this can be copied for each format. */
112  AH->StartDataPtr = _StartData;
113  AH->WriteDataPtr = _WriteData;
114  AH->EndDataPtr = _EndData;
115  AH->WriteBytePtr = _WriteByte;
116  AH->ReadBytePtr = _ReadByte;
117  AH->WriteBufPtr = _WriteBuf;
118  AH->ReadBufPtr = _ReadBuf;
119  AH->ClosePtr = _CloseArchive;
125 
127  AH->StartBlobPtr = _StartBlob;
128  AH->EndBlobPtr = _EndBlob;
129  AH->EndBlobsPtr = _EndBlobs;
130 
132  AH->ClonePtr = _Clone;
133  AH->DeClonePtr = _DeClone;
134 
135  /* no parallel dump in the custom archive, only parallel restore */
136  AH->WorkerJobDumpPtr = NULL;
138 
139  /* Set up a private area. */
140  ctx = (lclContext *) pg_malloc0(sizeof(lclContext));
141  AH->formatData = (void *) ctx;
142 
143  /* Initialize LO buffering */
144  AH->lo_buf_size = LOBBUFSIZE;
145  AH->lo_buf = (void *) pg_malloc(LOBBUFSIZE);
146 
147  /*
148  * Now open the file
149  */
150  if (AH->mode == archModeWrite)
151  {
152  if (AH->fSpec && strcmp(AH->fSpec, "") != 0)
153  {
154  AH->FH = fopen(AH->fSpec, PG_BINARY_W);
155  if (!AH->FH)
156  fatal("could not open output file \"%s\": %m", AH->fSpec);
157  }
158  else
159  {
160  AH->FH = stdout;
161  if (!AH->FH)
162  fatal("could not open output file: %m");
163  }
164 
165  ctx->hasSeek = checkSeek(AH->FH);
166  }
167  else
168  {
169  if (AH->fSpec && strcmp(AH->fSpec, "") != 0)
170  {
171  AH->FH = fopen(AH->fSpec, PG_BINARY_R);
172  if (!AH->FH)
173  fatal("could not open input file \"%s\": %m", AH->fSpec);
174  }
175  else
176  {
177  AH->FH = stdin;
178  if (!AH->FH)
179  fatal("could not open input file: %m");
180  }
181 
182  ctx->hasSeek = checkSeek(AH->FH);
183 
184  ReadHead(AH);
185  ReadToc(AH);
186 
187  /*
188  * Remember location of first data block (i.e., the point after TOC)
189  * in case we have to search for desired data blocks.
190  */
191  ctx->lastFilePos = _getFilePos(AH, ctx);
192  }
193 }
static void _ReopenArchive(ArchiveHandle *AH)
ReopenPtrType ReopenPtr
ReadBufPtrType ReadBufPtr
void ReadToc(ArchiveHandle *AH)
void ReadHead(ArchiveHandle *AH)
DeClonePtrType DeClonePtr
static void _Clone(ArchiveHandle *AH)
static void _StartData(ArchiveHandle *AH, TocEntry *te)
static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len)
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
WriteBufPtrType WriteBufPtr
static void _ReadBuf(ArchiveHandle *AH, void *buf, size_t len)
static void _PrintExtraToc(ArchiveHandle *AH, TocEntry *te)
static void _EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid)
StartBlobPtrType StartBlobPtr
static int _WorkerJobRestoreCustom(ArchiveHandle *AH, TocEntry *te)
EndDataPtrType EndDataPtr
#define PG_BINARY_W
Definition: c.h:1243
static void _PrintTocData(ArchiveHandle *AH, TocEntry *te)
static void _CloseArchive(ArchiveHandle *AH)
StartBlobsPtrType StartBlobsPtr
#define PG_BINARY_R
Definition: c.h:1242
ReadBytePtrType ReadBytePtr
EndBlobPtrType EndBlobPtr
static void _WriteData(ArchiveHandle *AH, const void *data, size_t dLen)
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
static void _StartBlobs(ArchiveHandle *AH, TocEntry *te)
StartDataPtrType StartDataPtr
WriteBytePtrType WriteBytePtr
static void _EndData(ArchiveHandle *AH, TocEntry *te)
static void _ReadExtraToc(ArchiveHandle *AH, TocEntry *te)
static void _PrepParallelRestore(ArchiveHandle *AH)
static int _ReadByte(ArchiveHandle *)
PrintTocDataPtrType PrintTocDataPtr
WriteDataPtrType WriteDataPtr
static pgoff_t _getFilePos(ArchiveHandle *AH, lclContext *ctx)
static void _ArchiveEntry(ArchiveHandle *AH, TocEntry *te)
static void _EndBlobs(ArchiveHandle *AH, TocEntry *te)
PrepParallelRestorePtrType PrepParallelRestorePtr
EndBlobsPtrType EndBlobsPtr
ArchiveEntryPtrType ArchiveEntryPtr
#define fatal(...)
ClonePtrType ClonePtr
WorkerJobRestorePtrType WorkerJobRestorePtr
pgoff_t lastFilePos
static void _DeClone(ArchiveHandle *AH)
bool checkSeek(FILE *fp)
ClosePtrType ClosePtr
PrintExtraTocPtrType PrintExtraTocPtr
static int _WriteByte(ArchiveHandle *AH, const int i)
WriteExtraTocPtrType WriteExtraTocPtr
#define LOBBUFSIZE
ReadExtraTocPtrType ReadExtraTocPtr
static void _WriteExtraToc(ArchiveHandle *AH, TocEntry *te)
static void _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid)
WorkerJobDumpPtrType WorkerJobDumpPtr