|
58 | 58 | #include "pgstat.h"
|
59 | 59 | #include "storage/fd.h"
|
60 | 60 | #include "storage/shmem.h"
|
| 61 | +#include "storage/smgr.h" |
61 | 62 |
|
62 | 63 | #define SlruFileName(ctl, path, seg) \
|
63 | 64 | snprintf(path, MAXPGPATH, "%s/%04X", (ctl)->Dir, seg)
|
@@ -266,6 +267,15 @@ SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns,
|
266 | 267 | ctl->shared = shared;
|
267 | 268 | ctl->sync_handler = sync_handler;
|
268 | 269 | strlcpy(ctl->Dir, subdir, sizeof(ctl->Dir));
|
| 270 | + |
| 271 | + if (strcmp(subdir, "pg_xact") == 0) |
| 272 | + ctl->kind = SLRU_CLOG; |
| 273 | + else if (strcmp(subdir, "pg_multixact/members") == 0) |
| 274 | + ctl->kind = SLRU_MULTIXACT_MEMBERS; |
| 275 | + else if (strcmp(subdir, "pg_multixact/offsets") == 0) |
| 276 | + ctl->kind = SLRU_MULTIXACT_OFFSETS; |
| 277 | + else |
| 278 | + ctl->kind = SLRU_OTHER; |
269 | 279 | }
|
270 | 280 |
|
271 | 281 | /*
|
@@ -616,6 +626,64 @@ SimpleLruWritePage(SlruCtl ctl, int slotno)
|
616 | 626 | SlruInternalWritePage(ctl, slotno, NULL);
|
617 | 627 | }
|
618 | 628 |
|
| 629 | + |
| 630 | +static int |
| 631 | +SimpleLruDownloadSegment(SlruCtl ctl, int pageno, char const* path) |
| 632 | +{ |
| 633 | + int segno; |
| 634 | + int fd = -1; |
| 635 | + int n_blocks; |
| 636 | + char* buffer; |
| 637 | + |
| 638 | + static SMgrRelationData dummy_smgr_rel = {0}; |
| 639 | + |
| 640 | + if (ctl->kind == SLRU_OTHER) /* Only CLOG/multixact can be downloaded from page server */ |
| 641 | + return -1; |
| 642 | + |
| 643 | + /* If page is beyond latest written page, then do not try to download segment from server */ |
| 644 | + if (pageno < ctl->shared->latest_page_number) |
| 645 | + return -1; |
| 646 | + |
| 647 | + if (!dummy_smgr_rel.smgr) |
| 648 | + { |
| 649 | + RelFileNode rnode = {0}; |
| 650 | + dummy_smgr_rel.smgr = smgr(InvalidBackendId, rnode); |
| 651 | + } |
| 652 | + segno = pageno / SLRU_PAGES_PER_SEGMENT; |
| 653 | + |
| 654 | + buffer = palloc(BLCKSZ * SLRU_PAGES_PER_SEGMENT); |
| 655 | + n_blocks = smgr_read_slru_segment(&dummy_smgr_rel, ctl->kind, segno, buffer); |
| 656 | + if (n_blocks > 0) |
| 657 | + { |
| 658 | + fd = OpenTransientFile(path, O_RDWR | O_CREAT | PG_BINARY); |
| 659 | + if (fd < 0) |
| 660 | + { |
| 661 | + slru_errcause = SLRU_OPEN_FAILED; |
| 662 | + slru_errno = errno; |
| 663 | + pfree(buffer); |
| 664 | + return -1; |
| 665 | + } |
| 666 | + errno = 0; |
| 667 | + pgstat_report_wait_start(WAIT_EVENT_SLRU_WRITE); |
| 668 | + if (pg_pwrite(fd, buffer, n_blocks*BLCKSZ, 0) != n_blocks*BLCKSZ) |
| 669 | + { |
| 670 | + pgstat_report_wait_end(); |
| 671 | + /* if write didn't set errno, assume problem is no disk space */ |
| 672 | + if (errno == 0) |
| 673 | + errno = ENOSPC; |
| 674 | + slru_errcause = SLRU_WRITE_FAILED; |
| 675 | + slru_errno = errno; |
| 676 | + |
| 677 | + CloseTransientFile(fd); |
| 678 | + pfree(buffer); |
| 679 | + return -1; |
| 680 | + } |
| 681 | + pgstat_report_wait_end(); |
| 682 | + } |
| 683 | + pfree(buffer); |
| 684 | + return fd; |
| 685 | +} |
| 686 | + |
619 | 687 | /*
|
620 | 688 | * Return whether the given page exists on disk.
|
621 | 689 | *
|
@@ -643,12 +711,18 @@ SimpleLruDoesPhysicalPageExist(SlruCtl ctl, int pageno)
|
643 | 711 | {
|
644 | 712 | /* expected: file doesn't exist */
|
645 | 713 | if (errno == ENOENT)
|
646 |
| - return false; |
647 |
| - |
648 |
| - /* report error normally */ |
649 |
| - slru_errcause = SLRU_OPEN_FAILED; |
650 |
| - slru_errno = errno; |
651 |
| - SlruReportIOError(ctl, pageno, 0); |
| 714 | + { |
| 715 | + fd = SimpleLruDownloadSegment(ctl, pageno, path); |
| 716 | + if (fd < 0) |
| 717 | + return false; |
| 718 | + } |
| 719 | + else |
| 720 | + { |
| 721 | + /* report error normally */ |
| 722 | + slru_errcause = SLRU_OPEN_FAILED; |
| 723 | + slru_errno = errno; |
| 724 | + SlruReportIOError(ctl, pageno, 0); |
| 725 | + } |
652 | 726 | }
|
653 | 727 |
|
654 | 728 | if ((endpos = lseek(fd, 0, SEEK_END)) < 0)
|
@@ -702,18 +776,30 @@ SlruPhysicalReadPage(SlruCtl ctl, int pageno, int slotno)
|
702 | 776 | fd = OpenTransientFile(path, O_RDONLY | PG_BINARY);
|
703 | 777 | if (fd < 0)
|
704 | 778 | {
|
705 |
| - if (errno != ENOENT || !InRecovery) |
| 779 | + if (errno != ENOENT) |
706 | 780 | {
|
707 | 781 | slru_errcause = SLRU_OPEN_FAILED;
|
708 | 782 | slru_errno = errno;
|
709 | 783 | return false;
|
710 | 784 | }
|
711 |
| - |
712 |
| - ereport(LOG, |
713 |
| - (errmsg("file \"%s\" doesn't exist, reading as zeroes", |
714 |
| - path))); |
715 |
| - MemSet(shared->page_buffer[slotno], 0, BLCKSZ); |
716 |
| - return true; |
| 785 | + fd = SimpleLruDownloadSegment(ctl, pageno, path); |
| 786 | + if (fd < 0) |
| 787 | + { |
| 788 | + if (!InRecovery) |
| 789 | + { |
| 790 | + slru_errcause = SLRU_OPEN_FAILED; |
| 791 | + slru_errno = errno; |
| 792 | + return false; |
| 793 | + } |
| 794 | + else |
| 795 | + { |
| 796 | + ereport(LOG, |
| 797 | + (errmsg("file \"%s\" doesn't exist, reading as zeroes", |
| 798 | + path))); |
| 799 | + MemSet(shared->page_buffer[slotno], 0, BLCKSZ); |
| 800 | + return true; |
| 801 | + } |
| 802 | + } |
717 | 803 | }
|
718 | 804 |
|
719 | 805 | errno = 0;
|
|
0 commit comments