PageRenderTime 43ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/src/bin/pg_dump/pg_backup_custom.c

https://bitbucket.org/mhellegers/pghaikuport
C | 916 lines | 525 code | 120 blank | 271 comment | 95 complexity | c090cd9e5cbc7342a26e6519ec5c447f MD5 | raw file
Possible License(s): AGPL-3.0
  1. /*-------------------------------------------------------------------------
  2. *
  3. * pg_backup_custom.c
  4. *
  5. * Implements the custom output format.
  6. *
  7. * The comments with the routined 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 "compress_io.h"
  27. #include "dumputils.h"
  28. #include "dumpmem.h"
  29. /*--------
  30. * Routines in the format interface
  31. *--------
  32. */
  33. static void _ArchiveEntry(ArchiveHandle *AH, TocEntry *te);
  34. static void _StartData(ArchiveHandle *AH, TocEntry *te);
  35. static size_t _WriteData(ArchiveHandle *AH, const void *data, size_t dLen);
  36. static void _EndData(ArchiveHandle *AH, TocEntry *te);
  37. static int _WriteByte(ArchiveHandle *AH, const int i);
  38. static int _ReadByte(ArchiveHandle *);
  39. static size_t _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len);
  40. static size_t _ReadBuf(ArchiveHandle *AH, void *buf, size_t len);
  41. static void _CloseArchive(ArchiveHandle *AH);
  42. static void _ReopenArchive(ArchiveHandle *AH);
  43. static void _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);
  44. static void _WriteExtraToc(ArchiveHandle *AH, TocEntry *te);
  45. static void _ReadExtraToc(ArchiveHandle *AH, TocEntry *te);
  46. static void _PrintExtraToc(ArchiveHandle *AH, TocEntry *te);
  47. static void _PrintData(ArchiveHandle *AH);
  48. static void _skipData(ArchiveHandle *AH);
  49. static void _skipBlobs(ArchiveHandle *AH);
  50. static void _StartBlobs(ArchiveHandle *AH, TocEntry *te);
  51. static void _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid);
  52. static void _EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid);
  53. static void _EndBlobs(ArchiveHandle *AH, TocEntry *te);
  54. static void _LoadBlobs(ArchiveHandle *AH, bool drop);
  55. static void _Clone(ArchiveHandle *AH);
  56. static void _DeClone(ArchiveHandle *AH);
  57. typedef struct
  58. {
  59. CompressorState *cs;
  60. int hasSeek;
  61. pgoff_t filePos;
  62. pgoff_t dataStart;
  63. } lclContext;
  64. typedef struct
  65. {
  66. int dataState;
  67. pgoff_t dataPos;
  68. } lclTocEntry;
  69. /*------
  70. * Static declarations
  71. *------
  72. */
  73. static void _readBlockHeader(ArchiveHandle *AH, int *type, int *id);
  74. static pgoff_t _getFilePos(ArchiveHandle *AH, lclContext *ctx);
  75. static size_t _CustomWriteFunc(ArchiveHandle *AH, const char *buf, size_t len);
  76. static size_t _CustomReadFunc(ArchiveHandle *AH, char **buf, size_t *buflen);
  77. /* translator: this is a module name */
  78. static const char *modulename = gettext_noop("custom archiver");
  79. /*
  80. * Init routine required by ALL formats. This is a global routine
  81. * and should be declared in pg_backup_archiver.h
  82. *
  83. * It's task is to create any extra archive context (using AH->formatData),
  84. * and to initialize the supported function pointers.
  85. *
  86. * It should also prepare whatever it's input source is for reading/writing,
  87. * and in the case of a read mode connection, it should load the Header & TOC.
  88. */
  89. void
  90. InitArchiveFmt_Custom(ArchiveHandle *AH)
  91. {
  92. lclContext *ctx;
  93. /* Assuming static functions, this can be copied for each format. */
  94. AH->ArchiveEntryPtr = _ArchiveEntry;
  95. AH->StartDataPtr = _StartData;
  96. AH->WriteDataPtr = _WriteData;
  97. AH->EndDataPtr = _EndData;
  98. AH->WriteBytePtr = _WriteByte;
  99. AH->ReadBytePtr = _ReadByte;
  100. AH->WriteBufPtr = _WriteBuf;
  101. AH->ReadBufPtr = _ReadBuf;
  102. AH->ClosePtr = _CloseArchive;
  103. AH->ReopenPtr = _ReopenArchive;
  104. AH->PrintTocDataPtr = _PrintTocData;
  105. AH->ReadExtraTocPtr = _ReadExtraToc;
  106. AH->WriteExtraTocPtr = _WriteExtraToc;
  107. AH->PrintExtraTocPtr = _PrintExtraToc;
  108. AH->StartBlobsPtr = _StartBlobs;
  109. AH->StartBlobPtr = _StartBlob;
  110. AH->EndBlobPtr = _EndBlob;
  111. AH->EndBlobsPtr = _EndBlobs;
  112. AH->ClonePtr = _Clone;
  113. AH->DeClonePtr = _DeClone;
  114. /* Set up a private area. */
  115. ctx = (lclContext *) pg_malloc0(sizeof(lclContext));
  116. AH->formatData = (void *) ctx;
  117. /* Initialize LO buffering */
  118. AH->lo_buf_size = LOBBUFSIZE;
  119. AH->lo_buf = (void *) pg_malloc(LOBBUFSIZE);
  120. ctx->filePos = 0;
  121. /*
  122. * Now open the file
  123. */
  124. if (AH->mode == archModeWrite)
  125. {
  126. if (AH->fSpec && strcmp(AH->fSpec, "") != 0)
  127. {
  128. AH->FH = fopen(AH->fSpec, PG_BINARY_W);
  129. if (!AH->FH)
  130. exit_horribly(modulename, "could not open output file \"%s\": %s\n",
  131. AH->fSpec, strerror(errno));
  132. }
  133. else
  134. {
  135. AH->FH = stdout;
  136. if (!AH->FH)
  137. exit_horribly(modulename, "could not open output file: %s\n",
  138. strerror(errno));
  139. }
  140. ctx->hasSeek = checkSeek(AH->FH);
  141. }
  142. else
  143. {
  144. if (AH->fSpec && strcmp(AH->fSpec, "") != 0)
  145. {
  146. AH->FH = fopen(AH->fSpec, PG_BINARY_R);
  147. if (!AH->FH)
  148. exit_horribly(modulename, "could not open input file \"%s\": %s\n",
  149. AH->fSpec, strerror(errno));
  150. }
  151. else
  152. {
  153. AH->FH = stdin;
  154. if (!AH->FH)
  155. exit_horribly(modulename, "could not open input file: %s\n",
  156. strerror(errno));
  157. }
  158. ctx->hasSeek = checkSeek(AH->FH);
  159. ReadHead(AH);
  160. ReadToc(AH);
  161. ctx->dataStart = _getFilePos(AH, ctx);
  162. }
  163. }
  164. /*
  165. * Called by the Archiver when the dumper creates a new TOC entry.
  166. *
  167. * Optional.
  168. *
  169. * Set up extrac format-related TOC data.
  170. */
  171. static void
  172. _ArchiveEntry(ArchiveHandle *AH, TocEntry *te)
  173. {
  174. lclTocEntry *ctx;
  175. ctx = (lclTocEntry *) pg_malloc0(sizeof(lclTocEntry));
  176. if (te->dataDumper)
  177. ctx->dataState = K_OFFSET_POS_NOT_SET;
  178. else
  179. ctx->dataState = K_OFFSET_NO_DATA;
  180. te->formatData = (void *) ctx;
  181. }
  182. /*
  183. * Called by the Archiver to save any extra format-related TOC entry
  184. * data.
  185. *
  186. * Optional.
  187. *
  188. * Use the Archiver routines to write data - they are non-endian, and
  189. * maintain other important file information.
  190. */
  191. static void
  192. _WriteExtraToc(ArchiveHandle *AH, TocEntry *te)
  193. {
  194. lclTocEntry *ctx = (lclTocEntry *) te->formatData;
  195. WriteOffset(AH, ctx->dataPos, ctx->dataState);
  196. }
  197. /*
  198. * Called by the Archiver to read any extra format-related TOC data.
  199. *
  200. * Optional.
  201. *
  202. * Needs to match the order defined in _WriteExtraToc, and should also
  203. * use the Archiver input routines.
  204. */
  205. static void
  206. _ReadExtraToc(ArchiveHandle *AH, TocEntry *te)
  207. {
  208. lclTocEntry *ctx = (lclTocEntry *) te->formatData;
  209. if (ctx == NULL)
  210. {
  211. ctx = (lclTocEntry *) pg_malloc0(sizeof(lclTocEntry));
  212. te->formatData = (void *) ctx;
  213. }
  214. ctx->dataState = ReadOffset(AH, &(ctx->dataPos));
  215. /*
  216. * Prior to V1.7 (pg7.3), we dumped the data size as an int now we don't
  217. * dump it at all.
  218. */
  219. if (AH->version < K_VERS_1_7)
  220. ReadInt(AH);
  221. }
  222. /*
  223. * Called by the Archiver when restoring an archive to output a comment
  224. * that includes useful information about the TOC entry.
  225. *
  226. * Optional.
  227. *
  228. */
  229. static void
  230. _PrintExtraToc(ArchiveHandle *AH, TocEntry *te)
  231. {
  232. lclTocEntry *ctx = (lclTocEntry *) te->formatData;
  233. if (AH->public.verbose)
  234. ahprintf(AH, "-- Data Pos: " INT64_FORMAT "\n",
  235. (int64) ctx->dataPos);
  236. }
  237. /*
  238. * Called by the archiver when saving TABLE DATA (not schema). This routine
  239. * should save whatever format-specific information is needed to read
  240. * the archive back.
  241. *
  242. * It is called just prior to the dumper's 'DataDumper' routine being called.
  243. *
  244. * Optional, but strongly recommended.
  245. *
  246. */
  247. static void
  248. _StartData(ArchiveHandle *AH, TocEntry *te)
  249. {
  250. lclContext *ctx = (lclContext *) AH->formatData;
  251. lclTocEntry *tctx = (lclTocEntry *) te->formatData;
  252. tctx->dataPos = _getFilePos(AH, ctx);
  253. tctx->dataState = K_OFFSET_POS_SET;
  254. _WriteByte(AH, BLK_DATA); /* Block type */
  255. WriteInt(AH, te->dumpId); /* For sanity check */
  256. ctx->cs = AllocateCompressor(AH->compression, _CustomWriteFunc);
  257. }
  258. /*
  259. * Called by archiver when dumper calls WriteData. This routine is
  260. * called for both BLOB and TABLE data; it is the responsibility of
  261. * the format to manage each kind of data using StartBlob/StartData.
  262. *
  263. * It should only be called from within a DataDumper routine.
  264. *
  265. * Mandatory.
  266. */
  267. static size_t
  268. _WriteData(ArchiveHandle *AH, const void *data, size_t dLen)
  269. {
  270. lclContext *ctx = (lclContext *) AH->formatData;
  271. CompressorState *cs = ctx->cs;
  272. if (dLen == 0)
  273. return 0;
  274. return WriteDataToArchive(AH, cs, data, dLen);
  275. }
  276. /*
  277. * Called by the archiver when a dumper's 'DataDumper' routine has
  278. * finished.
  279. *
  280. * Optional.
  281. *
  282. */
  283. static void
  284. _EndData(ArchiveHandle *AH, TocEntry *te)
  285. {
  286. lclContext *ctx = (lclContext *) AH->formatData;
  287. EndCompressor(AH, ctx->cs);
  288. /* Send the end marker */
  289. WriteInt(AH, 0);
  290. }
  291. /*
  292. * Called by the archiver when starting to save all BLOB DATA (not schema).
  293. * This routine should save whatever format-specific information is needed
  294. * to read the BLOBs back into memory.
  295. *
  296. * It is called just prior to the dumper's DataDumper routine.
  297. *
  298. * Optional, but strongly recommended.
  299. */
  300. static void
  301. _StartBlobs(ArchiveHandle *AH, TocEntry *te)
  302. {
  303. lclContext *ctx = (lclContext *) AH->formatData;
  304. lclTocEntry *tctx = (lclTocEntry *) te->formatData;
  305. tctx->dataPos = _getFilePos(AH, ctx);
  306. tctx->dataState = K_OFFSET_POS_SET;
  307. _WriteByte(AH, BLK_BLOBS); /* Block type */
  308. WriteInt(AH, te->dumpId); /* For sanity check */
  309. }
  310. /*
  311. * Called by the archiver when the dumper calls StartBlob.
  312. *
  313. * Mandatory.
  314. *
  315. * Must save the passed OID for retrieval at restore-time.
  316. */
  317. static void
  318. _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid)
  319. {
  320. lclContext *ctx = (lclContext *) AH->formatData;
  321. if (oid == 0)
  322. exit_horribly(modulename, "invalid OID for large object\n");
  323. WriteInt(AH, oid);
  324. ctx->cs = AllocateCompressor(AH->compression, _CustomWriteFunc);
  325. }
  326. /*
  327. * Called by the archiver when the dumper calls EndBlob.
  328. *
  329. * Optional.
  330. */
  331. static void
  332. _EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid)
  333. {
  334. lclContext *ctx = (lclContext *) AH->formatData;
  335. EndCompressor(AH, ctx->cs);
  336. /* Send the end marker */
  337. WriteInt(AH, 0);
  338. }
  339. /*
  340. * Called by the archiver when finishing saving all BLOB DATA.
  341. *
  342. * Optional.
  343. */
  344. static void
  345. _EndBlobs(ArchiveHandle *AH, TocEntry *te)
  346. {
  347. /* Write out a fake zero OID to mark end-of-blobs. */
  348. WriteInt(AH, 0);
  349. }
  350. /*
  351. * Print data for a given TOC entry
  352. */
  353. static void
  354. _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
  355. {
  356. lclContext *ctx = (lclContext *) AH->formatData;
  357. lclTocEntry *tctx = (lclTocEntry *) te->formatData;
  358. int blkType;
  359. int id;
  360. if (tctx->dataState == K_OFFSET_NO_DATA)
  361. return;
  362. if (!ctx->hasSeek || tctx->dataState == K_OFFSET_POS_NOT_SET)
  363. {
  364. /*
  365. * We cannot seek directly to the desired block. Instead, skip over
  366. * block headers until we find the one we want. This could fail if we
  367. * are asked to restore items out-of-order.
  368. */
  369. _readBlockHeader(AH, &blkType, &id);
  370. while (blkType != EOF && id != te->dumpId)
  371. {
  372. switch (blkType)
  373. {
  374. case BLK_DATA:
  375. _skipData(AH);
  376. break;
  377. case BLK_BLOBS:
  378. _skipBlobs(AH);
  379. break;
  380. default: /* Always have a default */
  381. exit_horribly(modulename,
  382. "unrecognized data block type (%d) while searching archive\n",
  383. blkType);
  384. break;
  385. }
  386. _readBlockHeader(AH, &blkType, &id);
  387. }
  388. }
  389. else
  390. {
  391. /* We can just seek to the place we need to be. */
  392. if (fseeko(AH->FH, tctx->dataPos, SEEK_SET) != 0)
  393. exit_horribly(modulename, "error during file seek: %s\n",
  394. strerror(errno));
  395. _readBlockHeader(AH, &blkType, &id);
  396. }
  397. /* Produce suitable failure message if we fell off end of file */
  398. if (blkType == EOF)
  399. {
  400. if (tctx->dataState == K_OFFSET_POS_NOT_SET)
  401. exit_horribly(modulename, "could not find block ID %d in archive -- "
  402. "possibly due to out-of-order restore request, "
  403. "which cannot be handled due to lack of data offsets in archive\n",
  404. te->dumpId);
  405. else if (!ctx->hasSeek)
  406. exit_horribly(modulename, "could not find block ID %d in archive -- "
  407. "possibly due to out-of-order restore request, "
  408. "which cannot be handled due to non-seekable input file\n",
  409. te->dumpId);
  410. else /* huh, the dataPos led us to EOF? */
  411. exit_horribly(modulename, "could not find block ID %d in archive -- "
  412. "possibly corrupt archive\n",
  413. te->dumpId);
  414. }
  415. /* Are we sane? */
  416. if (id != te->dumpId)
  417. exit_horribly(modulename, "found unexpected block ID (%d) when reading data -- expected %d\n",
  418. id, te->dumpId);
  419. switch (blkType)
  420. {
  421. case BLK_DATA:
  422. _PrintData(AH);
  423. break;
  424. case BLK_BLOBS:
  425. _LoadBlobs(AH, ropt->dropSchema);
  426. break;
  427. default: /* Always have a default */
  428. exit_horribly(modulename, "unrecognized data block type %d while restoring archive\n",
  429. blkType);
  430. break;
  431. }
  432. }
  433. /*
  434. * Print data from current file position.
  435. */
  436. static void
  437. _PrintData(ArchiveHandle *AH)
  438. {
  439. ReadDataFromArchive(AH, AH->compression, _CustomReadFunc);
  440. }
  441. static void
  442. _LoadBlobs(ArchiveHandle *AH, bool drop)
  443. {
  444. Oid oid;
  445. StartRestoreBlobs(AH);
  446. oid = ReadInt(AH);
  447. while (oid != 0)
  448. {
  449. StartRestoreBlob(AH, oid, drop);
  450. _PrintData(AH);
  451. EndRestoreBlob(AH, oid);
  452. oid = ReadInt(AH);
  453. }
  454. EndRestoreBlobs(AH);
  455. }
  456. /*
  457. * Skip the BLOBs from the current file position.
  458. * BLOBS are written sequentially as data blocks (see below).
  459. * Each BLOB is preceded by it's original OID.
  460. * A zero OID indicated the end of the BLOBS
  461. */
  462. static void
  463. _skipBlobs(ArchiveHandle *AH)
  464. {
  465. Oid oid;
  466. oid = ReadInt(AH);
  467. while (oid != 0)
  468. {
  469. _skipData(AH);
  470. oid = ReadInt(AH);
  471. }
  472. }
  473. /*
  474. * Skip data from current file position.
  475. * Data blocks are formatted as an integer length, followed by data.
  476. * A zero length denoted the end of the block.
  477. */
  478. static void
  479. _skipData(ArchiveHandle *AH)
  480. {
  481. lclContext *ctx = (lclContext *) AH->formatData;
  482. size_t blkLen;
  483. char *buf = NULL;
  484. int buflen = 0;
  485. size_t cnt;
  486. blkLen = ReadInt(AH);
  487. while (blkLen != 0)
  488. {
  489. if (blkLen > buflen)
  490. {
  491. if (buf)
  492. free(buf);
  493. buf = (char *) pg_malloc(blkLen);
  494. buflen = blkLen;
  495. }
  496. cnt = fread(buf, 1, blkLen, AH->FH);
  497. if (cnt != blkLen)
  498. {
  499. if (feof(AH->FH))
  500. exit_horribly(modulename,
  501. "could not read from input file: end of file\n");
  502. else
  503. exit_horribly(modulename,
  504. "could not read from input file: %s\n", strerror(errno));
  505. }
  506. ctx->filePos += blkLen;
  507. blkLen = ReadInt(AH);
  508. }
  509. if (buf)
  510. free(buf);
  511. }
  512. /*
  513. * Write a byte of data to the archive.
  514. *
  515. * Mandatory.
  516. *
  517. * Called by the archiver to do integer & byte output to the archive.
  518. */
  519. static int
  520. _WriteByte(ArchiveHandle *AH, const int i)
  521. {
  522. lclContext *ctx = (lclContext *) AH->formatData;
  523. int res;
  524. res = fputc(i, AH->FH);
  525. if (res != EOF)
  526. ctx->filePos += 1;
  527. else
  528. exit_horribly(modulename, "could not write byte: %s\n", strerror(errno));
  529. return res;
  530. }
  531. /*
  532. * Read a byte of data from the archive.
  533. *
  534. * Mandatory
  535. *
  536. * Called by the archiver to read bytes & integers from the archive.
  537. * EOF should be treated as a fatal error.
  538. */
  539. static int
  540. _ReadByte(ArchiveHandle *AH)
  541. {
  542. lclContext *ctx = (lclContext *) AH->formatData;
  543. int res;
  544. res = getc(AH->FH);
  545. if (res == EOF)
  546. exit_horribly(modulename, "unexpected end of file\n");
  547. ctx->filePos += 1;
  548. return res;
  549. }
  550. /*
  551. * Write a buffer of data to the archive.
  552. *
  553. * Mandatory.
  554. *
  555. * Called by the archiver to write a block of bytes to the archive.
  556. */
  557. static size_t
  558. _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len)
  559. {
  560. lclContext *ctx = (lclContext *) AH->formatData;
  561. size_t res;
  562. res = fwrite(buf, 1, len, AH->FH);
  563. if (res != len)
  564. exit_horribly(modulename,
  565. "could not write to output file: %s\n", strerror(errno));
  566. ctx->filePos += res;
  567. return res;
  568. }
  569. /*
  570. * Read a block of bytes from the archive.
  571. *
  572. * Mandatory.
  573. *
  574. * Called by the archiver to read a block of bytes from the archive
  575. */
  576. static size_t
  577. _ReadBuf(ArchiveHandle *AH, void *buf, size_t len)
  578. {
  579. lclContext *ctx = (lclContext *) AH->formatData;
  580. size_t res;
  581. res = fread(buf, 1, len, AH->FH);
  582. ctx->filePos += res;
  583. return res;
  584. }
  585. /*
  586. * Close the archive.
  587. *
  588. * Mandatory.
  589. *
  590. * When writing the archive, this is the routine that actually starts
  591. * the process of saving it to files. No data should be written prior
  592. * to this point, since the user could sort the TOC after creating it.
  593. *
  594. * If an archive is to be written, this toutine must call:
  595. * WriteHead to save the archive header
  596. * WriteToc to save the TOC entries
  597. * WriteDataChunks to save all DATA & BLOBs.
  598. *
  599. */
  600. static void
  601. _CloseArchive(ArchiveHandle *AH)
  602. {
  603. lclContext *ctx = (lclContext *) AH->formatData;
  604. pgoff_t tpos;
  605. if (AH->mode == archModeWrite)
  606. {
  607. WriteHead(AH);
  608. tpos = ftello(AH->FH);
  609. WriteToc(AH);
  610. ctx->dataStart = _getFilePos(AH, ctx);
  611. WriteDataChunks(AH);
  612. /*
  613. * If possible, re-write the TOC in order to update the data offset
  614. * information. This is not essential, as pg_restore can cope in most
  615. * cases without it; but it can make pg_restore significantly faster
  616. * in some situations (especially parallel restore).
  617. */
  618. if (ctx->hasSeek &&
  619. fseeko(AH->FH, tpos, SEEK_SET) == 0)
  620. WriteToc(AH);
  621. }
  622. if (fclose(AH->FH) != 0)
  623. exit_horribly(modulename, "could not close archive file: %s\n", strerror(errno));
  624. AH->FH = NULL;
  625. }
  626. /*
  627. * Reopen the archive's file handle.
  628. *
  629. * We close the original file handle, except on Windows. (The difference
  630. * is because on Windows, this is used within a multithreading context,
  631. * and we don't want a thread closing the parent file handle.)
  632. */
  633. static void
  634. _ReopenArchive(ArchiveHandle *AH)
  635. {
  636. lclContext *ctx = (lclContext *) AH->formatData;
  637. pgoff_t tpos;
  638. if (AH->mode == archModeWrite)
  639. exit_horribly(modulename, "can only reopen input archives\n");
  640. /*
  641. * These two cases are user-facing errors since they represent unsupported
  642. * (but not invalid) use-cases. Word the error messages appropriately.
  643. */
  644. if (AH->fSpec == NULL || strcmp(AH->fSpec, "") == 0)
  645. exit_horribly(modulename, "parallel restore from standard input is not supported\n");
  646. if (!ctx->hasSeek)
  647. exit_horribly(modulename, "parallel restore from non-seekable file is not supported\n");
  648. errno = 0;
  649. tpos = ftello(AH->FH);
  650. if (errno)
  651. exit_horribly(modulename, "could not determine seek position in archive file: %s\n",
  652. strerror(errno));
  653. #ifndef WIN32
  654. if (fclose(AH->FH) != 0)
  655. exit_horribly(modulename, "could not close archive file: %s\n",
  656. strerror(errno));
  657. #endif
  658. AH->FH = fopen(AH->fSpec, PG_BINARY_R);
  659. if (!AH->FH)
  660. exit_horribly(modulename, "could not open input file \"%s\": %s\n",
  661. AH->fSpec, strerror(errno));
  662. if (fseeko(AH->FH, tpos, SEEK_SET) != 0)
  663. exit_horribly(modulename, "could not set seek position in archive file: %s\n",
  664. strerror(errno));
  665. }
  666. /*
  667. * Clone format-specific fields during parallel restoration.
  668. */
  669. static void
  670. _Clone(ArchiveHandle *AH)
  671. {
  672. lclContext *ctx = (lclContext *) AH->formatData;
  673. AH->formatData = (lclContext *) pg_malloc(sizeof(lclContext));
  674. memcpy(AH->formatData, ctx, sizeof(lclContext));
  675. ctx = (lclContext *) AH->formatData;
  676. /* sanity check, shouldn't happen */
  677. if (ctx->cs != NULL)
  678. exit_horribly(modulename, "compressor active\n");
  679. /*
  680. * Note: we do not make a local lo_buf because we expect at most one BLOBS
  681. * entry per archive, so no parallelism is possible. Likewise,
  682. * TOC-entry-local state isn't an issue because any one TOC entry is
  683. * touched by just one worker child.
  684. */
  685. }
  686. static void
  687. _DeClone(ArchiveHandle *AH)
  688. {
  689. lclContext *ctx = (lclContext *) AH->formatData;
  690. free(ctx);
  691. }
  692. /*--------------------------------------------------
  693. * END OF FORMAT CALLBACKS
  694. *--------------------------------------------------
  695. */
  696. /*
  697. * Get the current position in the archive file.
  698. */
  699. static pgoff_t
  700. _getFilePos(ArchiveHandle *AH, lclContext *ctx)
  701. {
  702. pgoff_t pos;
  703. if (ctx->hasSeek)
  704. {
  705. pos = ftello(AH->FH);
  706. if (pos != ctx->filePos)
  707. {
  708. write_msg(modulename, "WARNING: ftell mismatch with expected position -- ftell used\n");
  709. /*
  710. * Prior to 1.7 (pg7.3) we relied on the internally maintained
  711. * pointer. Now we rely on ftello() always, unless the file has
  712. * been found to not support it.
  713. */
  714. }
  715. }
  716. else
  717. pos = ctx->filePos;
  718. return pos;
  719. }
  720. /*
  721. * Read a data block header. The format changed in V1.3, so we
  722. * centralize the code here for simplicity. Returns *type = EOF
  723. * if at EOF.
  724. */
  725. static void
  726. _readBlockHeader(ArchiveHandle *AH, int *type, int *id)
  727. {
  728. lclContext *ctx = (lclContext *) AH->formatData;
  729. int byt;
  730. /*
  731. * Note: if we are at EOF with a pre-1.3 input file, we'll exit_horribly
  732. * inside ReadInt rather than returning EOF. It doesn't seem worth
  733. * jumping through hoops to deal with that case better, because no such
  734. * files are likely to exist in the wild: only some 7.1 development
  735. * versions of pg_dump ever generated such files.
  736. */
  737. if (AH->version < K_VERS_1_3)
  738. *type = BLK_DATA;
  739. else
  740. {
  741. byt = getc(AH->FH);
  742. *type = byt;
  743. if (byt == EOF)
  744. {
  745. *id = 0; /* don't return an uninitialized value */
  746. return;
  747. }
  748. ctx->filePos += 1;
  749. }
  750. *id = ReadInt(AH);
  751. }
  752. /*
  753. * Callback function for WriteDataToArchive. Writes one block of (compressed)
  754. * data to the archive.
  755. */
  756. static size_t
  757. _CustomWriteFunc(ArchiveHandle *AH, const char *buf, size_t len)
  758. {
  759. /* never write 0-byte blocks (this should not happen) */
  760. if (len == 0)
  761. return 0;
  762. WriteInt(AH, len);
  763. return _WriteBuf(AH, buf, len);
  764. }
  765. /*
  766. * Callback function for ReadDataFromArchive. To keep things simple, we
  767. * always read one compressed block at a time.
  768. */
  769. static size_t
  770. _CustomReadFunc(ArchiveHandle *AH, char **buf, size_t *buflen)
  771. {
  772. size_t blkLen;
  773. size_t cnt;
  774. /* Read length */
  775. blkLen = ReadInt(AH);
  776. if (blkLen == 0)
  777. return 0;
  778. /* If the caller's buffer is not large enough, allocate a bigger one */
  779. if (blkLen > *buflen)
  780. {
  781. free(*buf);
  782. *buf = (char *) pg_malloc(blkLen);
  783. *buflen = blkLen;
  784. }
  785. cnt = _ReadBuf(AH, *buf, blkLen);
  786. if (cnt != blkLen)
  787. {
  788. if (feof(AH->FH))
  789. exit_horribly(modulename,
  790. "could not read from input file: end of file\n");
  791. else
  792. exit_horribly(modulename,
  793. "could not read from input file: %s\n", strerror(errno));
  794. }
  795. return cnt;
  796. }