Skip to content

Commit a9419a4

Browse files
committed
Refactor SLRU download interface between Postgres and the neon extension
Move the responsibility of writing the SLRU segment contents to the neon extension. The neon extension hook now downloads the file and places it to the correct path, and returns a true/false to the caller to indicate if the file existed. On successful download, the caller retries opening the file.
1 parent 2155cb1 commit a9419a4

File tree

4 files changed

+54
-92
lines changed

4 files changed

+54
-92
lines changed

src/backend/access/transam/slru.c

Lines changed: 49 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -619,23 +619,25 @@ SimpleLruWritePage(SlruCtl ctl, int slotno)
619619

620620

621621
/*
622-
* NEON: we do not want to include large pg_xact/multixact files in basebackup and prefer
623-
* to download them on demand to reduce startup time.
624-
* If SLRU segment is not found, we try to download it from page server
622+
* NEON: we do not want to include large pg_xact/multixact files in the
623+
* basebackup and prefer to download them on demand to reduce startup time.
624+
*
625+
* If SLRU segment is not found, we try to download it from the pageserver.
626+
*
627+
* Returns:
628+
* true if the file was successfully downloaded
629+
* false if the file was not found in pageserver
630+
* ereports if some other error happened
625631
*/
626-
static int
627-
SimpleLruDownloadSegment(SlruCtl ctl, int pageno, char const* path)
632+
static bool
633+
SimpleLruDownloadSegment(SlruCtl ctl, int pageno, char const *path)
628634
{
629-
int segno;
630-
int fd = -1;
631-
int n_blocks;
632-
char* buffer;
633-
635+
int segno;
634636
static SMgrRelationData dummy_smgr_rel = {0};
635637

636638
/* If page is greater than latest written page, then do not try to download segment from server */
637639
if (ctl->PagePrecedes(ctl->shared->latest_page_number, pageno))
638-
return -1;
640+
return false;
639641

640642
if (!dummy_smgr_rel.smgr)
641643
{
@@ -644,45 +646,7 @@ SimpleLruDownloadSegment(SlruCtl ctl, int pageno, char const* path)
644646
}
645647
segno = pageno / SLRU_PAGES_PER_SEGMENT;
646648

647-
if (neon_use_communicator_worker) {
648-
buffer = NULL;
649-
} else {
650-
buffer = palloc(BLCKSZ * SLRU_PAGES_PER_SEGMENT);
651-
}
652-
653-
n_blocks = smgr_read_slru_segment(&dummy_smgr_rel, path, segno, buffer);
654-
if (n_blocks > 0)
655-
{
656-
fd = OpenTransientFile(path, O_RDWR | O_CREAT | PG_BINARY);
657-
if (fd < 0)
658-
{
659-
slru_errcause = SLRU_OPEN_FAILED;
660-
slru_errno = errno;
661-
pfree(buffer);
662-
return -1;
663-
}
664-
665-
if (!neon_use_communicator_worker) {
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-
}
684-
pfree(buffer);
685-
return fd;
649+
return smgr_read_slru_segment(&dummy_smgr_rel, path, segno);
686650
}
687651

688652
/*
@@ -701,29 +665,34 @@ SimpleLruDoesPhysicalPageExist(SlruCtl ctl, int pageno)
701665
int fd;
702666
bool result;
703667
off_t endpos;
668+
bool attempted_download = false;
704669

705670
/* update the stats counter of checked pages */
706671
pgstat_count_slru_page_exists(ctl->shared->slru_stats_idx);
707672

708673
SlruFileName(ctl, path, segno);
709674

675+
retry_after_download:
710676
fd = OpenTransientFile(path, O_RDONLY | PG_BINARY);
711677
if (fd < 0)
712678
{
713-
/* expected: file doesn't exist */
714-
if (errno == ENOENT)
679+
if (errno == ENOENT && !attempted_download)
715680
{
716-
fd = SimpleLruDownloadSegment(ctl, pageno, path);
717-
if (fd < 0)
718-
return false;
719-
}
720-
else
721-
{
722-
/* report error normally */
723-
slru_errcause = SLRU_OPEN_FAILED;
724-
slru_errno = errno;
725-
SlruReportIOError(ctl, pageno, 0);
681+
/* Try to download the file from the pageserver */
682+
attempted_download = true;
683+
if (SimpleLruDownloadSegment(ctl, pageno, path))
684+
goto retry_after_download;
685+
errno = ENOENT;
726686
}
687+
688+
/* expected: file doesn't exist */
689+
if (errno == ENOENT)
690+
return false;
691+
692+
/* report error normally */
693+
slru_errcause = SLRU_OPEN_FAILED;
694+
slru_errno = errno;
695+
SlruReportIOError(ctl, pageno, 0);
727696
}
728697

729698
if ((endpos = lseek(fd, 0, SEEK_END)) < 0)
@@ -764,6 +733,7 @@ SlruPhysicalReadPage(SlruCtl ctl, int pageno, int slotno)
764733
off_t offset = rpageno * BLCKSZ;
765734
char path[MAXPGPATH];
766735
int fd;
736+
bool attempted_download = false;
767737

768738
SlruFileName(ctl, path, segno);
769739

@@ -774,33 +744,31 @@ SlruPhysicalReadPage(SlruCtl ctl, int pageno, int slotno)
774744
* SlruPhysicalWritePage). Hence, if we are InRecovery, allow the case
775745
* where the file doesn't exist, and return zeroes instead.
776746
*/
747+
retry_after_download:
777748
fd = OpenTransientFile(path, O_RDONLY | PG_BINARY);
778749
if (fd < 0)
779750
{
780-
if (errno != ENOENT)
751+
if (errno == ENOENT && !attempted_download)
752+
{
753+
/* Try to download the file from the pageserver */
754+
attempted_download = true;
755+
if (SimpleLruDownloadSegment(ctl, pageno, path))
756+
goto retry_after_download;
757+
errno = ENOENT;
758+
}
759+
760+
if (errno != ENOENT || !InRecovery)
781761
{
782762
slru_errcause = SLRU_OPEN_FAILED;
783763
slru_errno = errno;
784764
return false;
785765
}
786-
fd = SimpleLruDownloadSegment(ctl, pageno, path);
787-
if (fd < 0)
788-
{
789-
if (!InRecovery)
790-
{
791-
slru_errcause = SLRU_OPEN_FAILED;
792-
slru_errno = errno;
793-
return false;
794-
}
795-
else
796-
{
797-
ereport(LOG,
798-
(errmsg("file \"%s\" doesn't exist, reading as zeroes",
799-
path)));
800-
MemSet(shared->page_buffer[slotno], 0, BLCKSZ);
801-
return true;
802-
}
803-
}
766+
767+
ereport(LOG,
768+
(errmsg("file \"%s\" doesn't exist, reading as zeroes",
769+
path)));
770+
MemSet(shared->page_buffer[slotno], 0, BLCKSZ);
771+
return true;
804772
}
805773

806774
errno = 0;

src/backend/storage/smgr/smgr.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -547,10 +547,10 @@ smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
547547
* of partial segment, it can be smaller. Zero value means that segment doesn't exist.
548548
* From Postgres point of view empty segment is the same as absent segment.
549549
*/
550-
int
551-
smgr_read_slru_segment(SMgrRelation reln, const char* path, int segno, void* buffer)
550+
bool
551+
smgr_read_slru_segment(SMgrRelation reln, const char* path, int segno)
552552
{
553-
return (*reln->smgr).smgr_read_slru_segment ? (*reln->smgr).smgr_read_slru_segment(reln, path, segno, buffer) : 0;
553+
return (*reln->smgr).smgr_read_slru_segment ? (*reln->smgr).smgr_read_slru_segment(reln, path, segno) : false;
554554
}
555555

556556

src/include/miscadmin.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -169,12 +169,6 @@ extern PGDLLIMPORT bool IsPostmasterEnvironment;
169169
extern PGDLLIMPORT bool IsUnderPostmaster;
170170
extern PGDLLIMPORT bool IsBackgroundWorker;
171171
extern PGDLLIMPORT bool IsBinaryUpgrade;
172-
/* Whether the communicator worker is used or not. Defined here so that
173-
* it is also accessible from the main postgres code easily without
174-
* having to look up the value using strings and chain of other
175-
* functions.
176-
*/
177-
extern PGDLLIMPORT bool neon_use_communicator_worker;
178172

179173
extern PGDLLIMPORT bool ExitOnAnyError;
180174

src/include/storage/smgr.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ typedef struct f_smgr
129129
void (*smgr_finish_unlogged_build_phase_1) (SMgrRelation reln);
130130
void (*smgr_end_unlogged_build) (SMgrRelation reln);
131131

132-
int (*smgr_read_slru_segment) (SMgrRelation reln, const char *path, int segno, void* buffer);
132+
bool (*smgr_read_slru_segment) (SMgrRelation reln, const char *path, int segno);
133133
} f_smgr;
134134

135135
typedef void (*smgr_init_hook_type) (void);
@@ -184,6 +184,6 @@ extern void smgr_start_unlogged_build(SMgrRelation reln);
184184
extern void smgr_finish_unlogged_build_phase_1(SMgrRelation reln);
185185
extern void smgr_end_unlogged_build(SMgrRelation reln);
186186

187-
extern int smgr_read_slru_segment(SMgrRelation reln, const char *path, int segno, void* buffer);
187+
extern bool smgr_read_slru_segment(SMgrRelation reln, const char *path, int segno);
188188

189189
#endif /* SMGR_H */

0 commit comments

Comments
 (0)