1 /*-------------------------------------------------------------------------
3 * pg_backup_directory.c
5 * A directory format dump is a directory, which contains a "toc.dat" file
6 * for the TOC, and a separate file for each data entry, named "<oid>.dat".
7 * Large objects are stored in separate files named "blob_<oid>.dat",
8 * and there's a plain-text TOC file for each BLOBS TOC entry named
9 * "blobs_<dumpID>.toc" (or just "blobs.toc" in archive versions before 16).
11 * If compression is used, each data file is individually compressed and the
12 * ".gz" suffix is added to the filenames. The TOC files are never
13 * compressed by pg_dump, however they are accepted with the .gz suffix too,
14 * in case the user has manually compressed them with 'gzip'.
16 * NOTE: This format is identical to the files written in the tar file in
17 * the 'tar' format, except that we don't write the restore.sql file (TODO),
18 * and the tar format doesn't support compression. Please keep the formats in
22 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
23 * Portions Copyright (c) 1994, Regents of the University of California
24 * Portions Copyright (c) 2000, Philip Warner
26 * Rights are granted to use this software in any way so long
27 * as this notice is not removed.
29 * The author is not responsible for loss or damages that may
30 * result from its use.
33 * src/bin/pg_dump/pg_backup_directory.c
35 *-------------------------------------------------------------------------
37 #include "postgres_fe.h"
42 #include "common/file_utils.h"
43 #include "compress_io.h"
45 #include "pg_backup_utils.h"
50 * Our archive location. This is basically what the user specified as his
51 * backup file but of course here it is a directory.
55 CompressFileHandle
*dataFH
; /* currently open data file */
56 CompressFileHandle
*LOsTocFH
; /* file handle for blobs_NNN.toc */
57 ParallelState
*pstate
; /* for parallel backup / restore */
62 char *filename
; /* filename excluding the directory (basename) */
65 /* prototypes for private functions */
66 static void _ArchiveEntry(ArchiveHandle
*AH
, TocEntry
*te
);
67 static void _StartData(ArchiveHandle
*AH
, TocEntry
*te
);
68 static void _EndData(ArchiveHandle
*AH
, TocEntry
*te
);
69 static void _WriteData(ArchiveHandle
*AH
, const void *data
, size_t dLen
);
70 static int _WriteByte(ArchiveHandle
*AH
, const int i
);
71 static int _ReadByte(ArchiveHandle
*AH
);
72 static void _WriteBuf(ArchiveHandle
*AH
, const void *buf
, size_t len
);
73 static void _ReadBuf(ArchiveHandle
*AH
, void *buf
, size_t len
);
74 static void _CloseArchive(ArchiveHandle
*AH
);
75 static void _ReopenArchive(ArchiveHandle
*AH
);
76 static void _PrintTocData(ArchiveHandle
*AH
, TocEntry
*te
);
78 static void _WriteExtraToc(ArchiveHandle
*AH
, TocEntry
*te
);
79 static void _ReadExtraToc(ArchiveHandle
*AH
, TocEntry
*te
);
80 static void _PrintExtraToc(ArchiveHandle
*AH
, TocEntry
*te
);
82 static void _StartLOs(ArchiveHandle
*AH
, TocEntry
*te
);
83 static void _StartLO(ArchiveHandle
*AH
, TocEntry
*te
, Oid oid
);
84 static void _EndLO(ArchiveHandle
*AH
, TocEntry
*te
, Oid oid
);
85 static void _EndLOs(ArchiveHandle
*AH
, TocEntry
*te
);
86 static void _LoadLOs(ArchiveHandle
*AH
, TocEntry
*te
);
88 static void _PrepParallelRestore(ArchiveHandle
*AH
);
89 static void _Clone(ArchiveHandle
*AH
);
90 static void _DeClone(ArchiveHandle
*AH
);
92 static int _WorkerJobRestoreDirectory(ArchiveHandle
*AH
, TocEntry
*te
);
93 static int _WorkerJobDumpDirectory(ArchiveHandle
*AH
, TocEntry
*te
);
95 static void setFilePath(ArchiveHandle
*AH
, char *buf
,
96 const char *relativeFilename
);
99 * Init routine required by ALL formats. This is a global routine
100 * and should be declared in pg_backup_archiver.h
102 * Its task is to create any extra archive context (using AH->formatData),
103 * and to initialize the supported function pointers.
105 * It should also prepare whatever its input source is for reading/writing,
106 * and in the case of a read mode connection, it should load the Header & TOC.
109 InitArchiveFmt_Directory(ArchiveHandle
*AH
)
113 /* Assuming static functions, this can be copied for each format. */
114 AH
->ArchiveEntryPtr
= _ArchiveEntry
;
115 AH
->StartDataPtr
= _StartData
;
116 AH
->WriteDataPtr
= _WriteData
;
117 AH
->EndDataPtr
= _EndData
;
118 AH
->WriteBytePtr
= _WriteByte
;
119 AH
->ReadBytePtr
= _ReadByte
;
120 AH
->WriteBufPtr
= _WriteBuf
;
121 AH
->ReadBufPtr
= _ReadBuf
;
122 AH
->ClosePtr
= _CloseArchive
;
123 AH
->ReopenPtr
= _ReopenArchive
;
124 AH
->PrintTocDataPtr
= _PrintTocData
;
125 AH
->ReadExtraTocPtr
= _ReadExtraToc
;
126 AH
->WriteExtraTocPtr
= _WriteExtraToc
;
127 AH
->PrintExtraTocPtr
= _PrintExtraToc
;
129 AH
->StartLOsPtr
= _StartLOs
;
130 AH
->StartLOPtr
= _StartLO
;
131 AH
->EndLOPtr
= _EndLO
;
132 AH
->EndLOsPtr
= _EndLOs
;
134 AH
->PrepParallelRestorePtr
= _PrepParallelRestore
;
135 AH
->ClonePtr
= _Clone
;
136 AH
->DeClonePtr
= _DeClone
;
138 AH
->WorkerJobRestorePtr
= _WorkerJobRestoreDirectory
;
139 AH
->WorkerJobDumpPtr
= _WorkerJobDumpDirectory
;
141 /* Set up our private context */
142 ctx
= (lclContext
*) pg_malloc0(sizeof(lclContext
));
143 AH
->formatData
= ctx
;
146 ctx
->LOsTocFH
= NULL
;
149 * Now open the TOC file
152 if (!AH
->fSpec
|| strcmp(AH
->fSpec
, "") == 0)
153 pg_fatal("no output directory specified");
155 ctx
->directory
= AH
->fSpec
;
157 if (AH
->mode
== archModeWrite
)
160 bool is_empty
= false;
162 /* we accept an empty existing directory */
163 if (stat(ctx
->directory
, &st
) == 0 && S_ISDIR(st
.st_mode
))
165 DIR *dir
= opendir(ctx
->directory
);
172 while (errno
= 0, (d
= readdir(dir
)))
174 if (strcmp(d
->d_name
, ".") != 0 && strcmp(d
->d_name
, "..") != 0)
182 pg_fatal("could not read directory \"%s\": %m",
186 pg_fatal("could not close directory \"%s\": %m",
191 if (!is_empty
&& mkdir(ctx
->directory
, 0700) < 0)
192 pg_fatal("could not create directory \"%s\": %m",
197 char fname
[MAXPGPATH
];
198 CompressFileHandle
*tocFH
;
200 setFilePath(AH
, fname
, "toc.dat");
202 tocFH
= InitDiscoverCompressFileHandle(fname
, PG_BINARY_R
);
204 pg_fatal("could not open input file \"%s\": %m", fname
);
209 * The TOC of a directory format dump shares the format code of the
212 AH
->format
= archTar
;
214 AH
->format
= archDirectory
;
217 /* Nothing else in the file, so close it again... */
218 if (!EndCompressFileHandle(tocFH
))
219 pg_fatal("could not close TOC file: %m");
225 * Called by the Archiver when the dumper creates a new TOC entry.
227 * We determine the filename for this entry.
230 _ArchiveEntry(ArchiveHandle
*AH
, TocEntry
*te
)
235 tctx
= (lclTocEntry
*) pg_malloc0(sizeof(lclTocEntry
));
236 if (strcmp(te
->desc
, "BLOBS") == 0)
238 snprintf(fn
, MAXPGPATH
, "blobs_%d.toc", te
->dumpId
);
239 tctx
->filename
= pg_strdup(fn
);
241 else if (te
->dataDumper
)
243 snprintf(fn
, MAXPGPATH
, "%d.dat", te
->dumpId
);
244 tctx
->filename
= pg_strdup(fn
);
247 tctx
->filename
= NULL
;
249 te
->formatData
= tctx
;
253 * Called by the Archiver to save any extra format-related TOC entry
256 * Use the Archiver routines to write data - they are non-endian, and
257 * maintain other important file information.
260 _WriteExtraToc(ArchiveHandle
*AH
, TocEntry
*te
)
262 lclTocEntry
*tctx
= (lclTocEntry
*) te
->formatData
;
265 * A dumpable object has set tctx->filename, any other object has not.
266 * (see _ArchiveEntry).
269 WriteStr(AH
, tctx
->filename
);
275 * Called by the Archiver to read any extra format-related TOC data.
277 * Needs to match the order defined in _WriteExtraToc, and should also
278 * use the Archiver input routines.
281 _ReadExtraToc(ArchiveHandle
*AH
, TocEntry
*te
)
283 lclTocEntry
*tctx
= (lclTocEntry
*) te
->formatData
;
287 tctx
= (lclTocEntry
*) pg_malloc0(sizeof(lclTocEntry
));
288 te
->formatData
= tctx
;
291 tctx
->filename
= ReadStr(AH
);
292 if (strlen(tctx
->filename
) == 0)
294 free(tctx
->filename
);
295 tctx
->filename
= NULL
;
300 * Called by the Archiver when restoring an archive to output a comment
301 * that includes useful information about the TOC entry.
304 _PrintExtraToc(ArchiveHandle
*AH
, TocEntry
*te
)
306 lclTocEntry
*tctx
= (lclTocEntry
*) te
->formatData
;
308 if (AH
->public.verbose
&& tctx
->filename
)
309 ahprintf(AH
, "-- File: %s\n", tctx
->filename
);
313 * Called by the archiver when saving TABLE DATA (not schema). This routine
314 * should save whatever format-specific information is needed to read
317 * It is called just prior to the dumper's 'DataDumper' routine being called.
319 * We create the data file for writing.
322 _StartData(ArchiveHandle
*AH
, TocEntry
*te
)
324 lclTocEntry
*tctx
= (lclTocEntry
*) te
->formatData
;
325 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
326 char fname
[MAXPGPATH
];
328 setFilePath(AH
, fname
, tctx
->filename
);
330 ctx
->dataFH
= InitCompressFileHandle(AH
->compression_spec
);
332 if (!ctx
->dataFH
->open_write_func(fname
, PG_BINARY_W
, ctx
->dataFH
))
333 pg_fatal("could not open output file \"%s\": %m", fname
);
337 * Called by archiver when dumper calls WriteData. This routine is
338 * called for both LO and table data; it is the responsibility of
339 * the format to manage each kind of data using StartLO/StartData.
341 * It should only be called from within a DataDumper routine.
343 * We write the data to the open data file.
346 _WriteData(ArchiveHandle
*AH
, const void *data
, size_t dLen
)
348 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
349 CompressFileHandle
*CFH
= ctx
->dataFH
;
352 if (dLen
> 0 && !CFH
->write_func(data
, dLen
, CFH
))
354 /* if write didn't set errno, assume problem is no disk space */
357 pg_fatal("could not write to output file: %s",
358 CFH
->get_error_func(CFH
));
363 * Called by the archiver when a dumper's 'DataDumper' routine has
366 * We close the data file.
369 _EndData(ArchiveHandle
*AH
, TocEntry
*te
)
371 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
374 if (!EndCompressFileHandle(ctx
->dataFH
))
375 pg_fatal("could not close data file: %m");
381 * Print data for a given file (can be a LO as well)
384 _PrintFileData(ArchiveHandle
*AH
, char *filename
)
389 CompressFileHandle
*CFH
;
394 CFH
= InitDiscoverCompressFileHandle(filename
, PG_BINARY_R
);
396 pg_fatal("could not open input file \"%s\": %m", filename
);
398 buflen
= DEFAULT_IO_BUFFER_SIZE
;
399 buf
= pg_malloc(buflen
);
401 while (CFH
->read_func(buf
, buflen
, &cnt
, CFH
) && cnt
> 0)
403 ahwrite(buf
, 1, cnt
, AH
);
407 if (!EndCompressFileHandle(CFH
))
408 pg_fatal("could not close data file \"%s\": %m", filename
);
412 * Print data for a given TOC entry
415 _PrintTocData(ArchiveHandle
*AH
, TocEntry
*te
)
417 lclTocEntry
*tctx
= (lclTocEntry
*) te
->formatData
;
422 if (strcmp(te
->desc
, "BLOBS") == 0)
426 char fname
[MAXPGPATH
];
428 setFilePath(AH
, fname
, tctx
->filename
);
429 _PrintFileData(AH
, fname
);
434 _LoadLOs(ArchiveHandle
*AH
, TocEntry
*te
)
437 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
438 lclTocEntry
*tctx
= (lclTocEntry
*) te
->formatData
;
439 CompressFileHandle
*CFH
;
440 char tocfname
[MAXPGPATH
];
441 char line
[MAXPGPATH
];
446 * Note: before archive v16, there was always only one BLOBS TOC entry,
447 * now there can be multiple. We don't need to worry what version we are
448 * reading though, because tctx->filename should be correct either way.
450 setFilePath(AH
, tocfname
, tctx
->filename
);
452 CFH
= ctx
->LOsTocFH
= InitDiscoverCompressFileHandle(tocfname
, PG_BINARY_R
);
454 if (ctx
->LOsTocFH
== NULL
)
455 pg_fatal("could not open large object TOC file \"%s\" for input: %m",
458 /* Read the LOs TOC file line-by-line, and process each LO */
459 while ((CFH
->gets_func(line
, MAXPGPATH
, CFH
)) != NULL
)
461 char lofname
[MAXPGPATH
+ 1];
462 char path
[MAXPGPATH
];
464 /* Can't overflow because line and lofname are the same length */
465 if (sscanf(line
, "%u %" CppAsString2(MAXPGPATH
) "s\n", &oid
, lofname
) != 2)
466 pg_fatal("invalid line in large object TOC file \"%s\": \"%s\"",
469 StartRestoreLO(AH
, oid
, AH
->public.ropt
->dropSchema
);
470 snprintf(path
, MAXPGPATH
, "%s/%s", ctx
->directory
, lofname
);
471 _PrintFileData(AH
, path
);
472 EndRestoreLO(AH
, oid
);
474 if (!CFH
->eof_func(CFH
))
475 pg_fatal("error reading large object TOC file \"%s\"",
478 if (!EndCompressFileHandle(ctx
->LOsTocFH
))
479 pg_fatal("could not close large object TOC file \"%s\": %m",
482 ctx
->LOsTocFH
= NULL
;
489 * Write a byte of data to the archive.
490 * Called by the archiver to do integer & byte output to the archive.
491 * These routines are only used to read & write the headers & TOC.
494 _WriteByte(ArchiveHandle
*AH
, const int i
)
496 unsigned char c
= (unsigned char) i
;
497 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
498 CompressFileHandle
*CFH
= ctx
->dataFH
;
501 if (!CFH
->write_func(&c
, 1, CFH
))
503 /* if write didn't set errno, assume problem is no disk space */
506 pg_fatal("could not write to output file: %s",
507 CFH
->get_error_func(CFH
));
514 * Read a byte of data from the archive.
515 * Called by the archiver to read bytes & integers from the archive.
516 * These routines are only used to read & write headers & TOC.
517 * EOF should be treated as a fatal error.
520 _ReadByte(ArchiveHandle
*AH
)
522 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
523 CompressFileHandle
*CFH
= ctx
->dataFH
;
525 return CFH
->getc_func(CFH
);
529 * Write a buffer of data to the archive.
530 * Called by the archiver to write a block of bytes to the TOC or a data file.
533 _WriteBuf(ArchiveHandle
*AH
, const void *buf
, size_t len
)
535 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
536 CompressFileHandle
*CFH
= ctx
->dataFH
;
539 if (!CFH
->write_func(buf
, len
, CFH
))
541 /* if write didn't set errno, assume problem is no disk space */
544 pg_fatal("could not write to output file: %s",
545 CFH
->get_error_func(CFH
));
550 * Read a block of bytes from the archive.
552 * Called by the archiver to read a block of bytes from the archive
555 _ReadBuf(ArchiveHandle
*AH
, void *buf
, size_t len
)
557 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
558 CompressFileHandle
*CFH
= ctx
->dataFH
;
561 * If there was an I/O error, we already exited in readF(), so here we
562 * exit on short reads.
564 if (!CFH
->read_func(buf
, len
, NULL
, CFH
))
565 pg_fatal("could not read from input file: end of file");
571 * When writing the archive, this is the routine that actually starts
572 * the process of saving it to files. No data should be written prior
573 * to this point, since the user could sort the TOC after creating it.
575 * If an archive is to be written, this routine must call:
576 * WriteHead to save the archive header
577 * WriteToc to save the TOC entries
578 * WriteDataChunks to save all data & LOs.
581 _CloseArchive(ArchiveHandle
*AH
)
583 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
585 if (AH
->mode
== archModeWrite
)
587 CompressFileHandle
*tocFH
;
588 pg_compress_specification compression_spec
= {0};
589 char fname
[MAXPGPATH
];
591 setFilePath(AH
, fname
, "toc.dat");
593 /* this will actually fork the processes for a parallel backup */
594 ctx
->pstate
= ParallelBackupStart(AH
);
596 /* The TOC is always created uncompressed */
597 compression_spec
.algorithm
= PG_COMPRESSION_NONE
;
598 tocFH
= InitCompressFileHandle(compression_spec
);
599 if (!tocFH
->open_write_func(fname
, PG_BINARY_W
, tocFH
))
600 pg_fatal("could not open output file \"%s\": %m", fname
);
604 * Write 'tar' in the format field of the toc.dat file. The directory
605 * is compatible with 'tar', so there's no point having a different
606 * format code for it.
608 AH
->format
= archTar
;
610 AH
->format
= archDirectory
;
612 if (!EndCompressFileHandle(tocFH
))
613 pg_fatal("could not close TOC file: %m");
614 WriteDataChunks(AH
, ctx
->pstate
);
616 ParallelBackupEnd(AH
, ctx
->pstate
);
619 * In directory mode, there is no need to sync all the entries
620 * individually. Just recurse once through all the files generated.
623 sync_dir_recurse(ctx
->directory
, AH
->sync_method
);
629 * Reopen the archive's file handle.
632 _ReopenArchive(ArchiveHandle
*AH
)
635 * Our TOC is in memory, our data files are opened by each child anyway as
636 * they are separate. We support reopening the archive by just doing
646 * Called by the archiver when starting to save BLOB DATA (not schema).
647 * It is called just prior to the dumper's DataDumper routine.
649 * We open the large object TOC file here, so that we can append a line to
653 _StartLOs(ArchiveHandle
*AH
, TocEntry
*te
)
655 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
656 lclTocEntry
*tctx
= (lclTocEntry
*) te
->formatData
;
657 pg_compress_specification compression_spec
= {0};
658 char fname
[MAXPGPATH
];
660 setFilePath(AH
, fname
, tctx
->filename
);
662 /* The LO TOC file is never compressed */
663 compression_spec
.algorithm
= PG_COMPRESSION_NONE
;
664 ctx
->LOsTocFH
= InitCompressFileHandle(compression_spec
);
665 if (!ctx
->LOsTocFH
->open_write_func(fname
, "ab", ctx
->LOsTocFH
))
666 pg_fatal("could not open output file \"%s\": %m", fname
);
670 * Called by the archiver when we're about to start dumping a LO.
672 * We create a file to write the LO to.
675 _StartLO(ArchiveHandle
*AH
, TocEntry
*te
, Oid oid
)
677 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
678 char fname
[MAXPGPATH
];
680 snprintf(fname
, MAXPGPATH
, "%s/blob_%u.dat", ctx
->directory
, oid
);
682 ctx
->dataFH
= InitCompressFileHandle(AH
->compression_spec
);
683 if (!ctx
->dataFH
->open_write_func(fname
, PG_BINARY_W
, ctx
->dataFH
))
684 pg_fatal("could not open output file \"%s\": %m", fname
);
688 * Called by the archiver when the dumper is finished writing a LO.
690 * We close the LO file and write an entry to the LO TOC file for it.
693 _EndLO(ArchiveHandle
*AH
, TocEntry
*te
, Oid oid
)
695 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
696 CompressFileHandle
*CFH
= ctx
->LOsTocFH
;
700 /* Close the BLOB data file itself */
701 if (!EndCompressFileHandle(ctx
->dataFH
))
702 pg_fatal("could not close LO data file: %m");
705 /* register the LO in blobs_NNN.toc */
706 len
= snprintf(buf
, sizeof(buf
), "%u blob_%u.dat\n", oid
, oid
);
707 if (!CFH
->write_func(buf
, len
, CFH
))
709 /* if write didn't set errno, assume problem is no disk space */
712 pg_fatal("could not write to LOs TOC file: %s",
713 CFH
->get_error_func(CFH
));
718 * Called by the archiver when finishing saving BLOB DATA.
720 * We close the LOs TOC file.
723 _EndLOs(ArchiveHandle
*AH
, TocEntry
*te
)
725 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
727 if (!EndCompressFileHandle(ctx
->LOsTocFH
))
728 pg_fatal("could not close LOs TOC file: %m");
729 ctx
->LOsTocFH
= NULL
;
733 * Gets a relative file name and prepends the output directory, writing the
734 * result to buf. The caller needs to make sure that buf is MAXPGPATH bytes
735 * big. Can't use a static char[MAXPGPATH] inside the function because we run
736 * multithreaded on Windows.
739 setFilePath(ArchiveHandle
*AH
, char *buf
, const char *relativeFilename
)
741 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
744 dname
= ctx
->directory
;
746 if (strlen(dname
) + 1 + strlen(relativeFilename
) + 1 > MAXPGPATH
)
747 pg_fatal("file name too long: \"%s\"", dname
);
751 strcat(buf
, relativeFilename
);
755 * Prepare for parallel restore.
757 * The main thing that needs to happen here is to fill in TABLE DATA and BLOBS
758 * TOC entries' dataLength fields with appropriate values to guide the
759 * ordering of restore jobs. The source of said data is format-dependent,
760 * as is the exact meaning of the values.
762 * A format module might also choose to do other setup here.
765 _PrepParallelRestore(ArchiveHandle
*AH
)
769 for (te
= AH
->toc
->next
; te
!= AH
->toc
; te
= te
->next
)
771 lclTocEntry
*tctx
= (lclTocEntry
*) te
->formatData
;
772 char fname
[MAXPGPATH
];
776 * A dumpable object has set tctx->filename, any other object has not.
777 * (see _ArchiveEntry).
779 if (tctx
->filename
== NULL
)
782 /* We may ignore items not due to be restored */
783 if ((te
->reqs
& REQ_DATA
) == 0)
787 * Stat the file and, if successful, put its size in dataLength. When
788 * using compression, the physical file size might not be a very good
789 * guide to the amount of work involved in restoring the file, but we
790 * only need an approximate indicator of that.
792 setFilePath(AH
, fname
, tctx
->filename
);
794 if (stat(fname
, &st
) == 0)
795 te
->dataLength
= st
.st_size
;
796 else if (AH
->compression_spec
.algorithm
!= PG_COMPRESSION_NONE
)
798 if (AH
->compression_spec
.algorithm
== PG_COMPRESSION_GZIP
)
799 strlcat(fname
, ".gz", sizeof(fname
));
800 else if (AH
->compression_spec
.algorithm
== PG_COMPRESSION_LZ4
)
801 strlcat(fname
, ".lz4", sizeof(fname
));
802 else if (AH
->compression_spec
.algorithm
== PG_COMPRESSION_ZSTD
)
803 strlcat(fname
, ".zst", sizeof(fname
));
805 if (stat(fname
, &st
) == 0)
806 te
->dataLength
= st
.st_size
;
810 * If this is a BLOBS entry, what we stat'd was blobs_NNN.toc, which
811 * most likely is a lot smaller than the actual blob data. We don't
812 * have a cheap way to estimate how much smaller, but fortunately it
813 * doesn't matter too much as long as we get the LOs processed
814 * reasonably early. Arbitrarily scale up by a factor of 1K.
816 if (strcmp(te
->desc
, "BLOBS") == 0)
817 te
->dataLength
*= 1024;
822 * Clone format-specific fields during parallel restoration.
825 _Clone(ArchiveHandle
*AH
)
827 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
829 AH
->formatData
= (lclContext
*) pg_malloc(sizeof(lclContext
));
830 memcpy(AH
->formatData
, ctx
, sizeof(lclContext
));
831 ctx
= (lclContext
*) AH
->formatData
;
834 * TOC-entry-local state isn't an issue because any one TOC entry is
835 * touched by just one worker child.
839 * We also don't copy the ParallelState pointer (pstate), only the leader
840 * process ever writes to it.
845 _DeClone(ArchiveHandle
*AH
)
847 lclContext
*ctx
= (lclContext
*) AH
->formatData
;
853 * This function is executed in the child of a parallel backup for a
854 * directory-format archive and dumps the actual data for one TOC entry.
857 _WorkerJobDumpDirectory(ArchiveHandle
*AH
, TocEntry
*te
)
860 * This function returns void. We either fail and die horribly or
861 * succeed... A failure will be detected by the parent when the child dies
864 WriteDataChunksForTocEntry(AH
, te
);
870 * This function is executed in the child of a parallel restore from a
871 * directory-format archive and restores the actual data for one TOC entry.
874 _WorkerJobRestoreDirectory(ArchiveHandle
*AH
, TocEntry
*te
)
876 return parallel_restore(AH
, te
);