Skip to content

Commit e871de0

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 a42351f commit e871de0

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
@@ -620,23 +620,25 @@ SimpleLruWritePage(SlruCtl ctl, int slotno)
620620

621621

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

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

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

648-
if (neon_use_communicator_worker) {
649-
buffer = NULL;
650-
} else {
651-
buffer = palloc(BLCKSZ * SLRU_PAGES_PER_SEGMENT);
652-
}
653-
654-
n_blocks = smgr_read_slru_segment(&dummy_smgr_rel, path, segno, buffer);
655-
if (n_blocks > 0)
656-
{
657-
fd = OpenTransientFile(path, O_RDWR | O_CREAT | PG_BINARY);
658-
if (fd < 0)
659-
{
660-
slru_errcause = SLRU_OPEN_FAILED;
661-
slru_errno = errno;
662-
pfree(buffer);
663-
return -1;
664-
}
665-
666-
if (!neon_use_communicator_worker) {
667-
errno = 0;
668-
pgstat_report_wait_start(WAIT_EVENT_SLRU_WRITE);
669-
if (pg_pwrite(fd, buffer, n_blocks*BLCKSZ, 0) != n_blocks*BLCKSZ)
670-
{
671-
pgstat_report_wait_end();
672-
/* if write didn't set errno, assume problem is no disk space */
673-
if (errno == 0)
674-
errno = ENOSPC;
675-
slru_errcause = SLRU_WRITE_FAILED;
676-
slru_errno = errno;
677-
678-
CloseTransientFile(fd);
679-
pfree(buffer);
680-
return -1;
681-
}
682-
pgstat_report_wait_end();
683-
}
684-
}
685-
pfree(buffer);
686-
return fd;
650+
return smgr_read_slru_segment(&dummy_smgr_rel, path, segno);
687651
}
688652

689653
/*
@@ -702,29 +666,34 @@ SimpleLruDoesPhysicalPageExist(SlruCtl ctl, int pageno)
702666
int fd;
703667
bool result;
704668
off_t endpos;
669+
bool attempted_download = false;
705670

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

709674
SlruFileName(ctl, path, segno);
710675

676+
retry_after_download:
711677
fd = OpenTransientFile(path, O_RDONLY | PG_BINARY);
712678
if (fd < 0)
713679
{
714-
/* expected: file doesn't exist */
715-
if (errno == ENOENT)
680+
if (errno == ENOENT && !attempted_download)
716681
{
717-
fd = SimpleLruDownloadSegment(ctl, pageno, path);
718-
if (fd < 0)
719-
return false;
720-
}
721-
else
722-
{
723-
/* report error normally */
724-
slru_errcause = SLRU_OPEN_FAILED;
725-
slru_errno = errno;
726-
SlruReportIOError(ctl, pageno, 0);
682+
/* Try to download the file from the pageserver */
683+
attempted_download = true;
684+
if (SimpleLruDownloadSegment(ctl, pageno, path))
685+
goto retry_after_download;
686+
errno = ENOENT;
727687
}
688+
689+
/* expected: file doesn't exist */
690+
if (errno == ENOENT)
691+
return false;
692+
693+
/* report error normally */
694+
slru_errcause = SLRU_OPEN_FAILED;
695+
slru_errno = errno;
696+
SlruReportIOError(ctl, pageno, 0);
728697
}
729698

730699
if ((endpos = lseek(fd, 0, SEEK_END)) < 0)
@@ -765,6 +734,7 @@ SlruPhysicalReadPage(SlruCtl ctl, int pageno, int slotno)
765734
off_t offset = rpageno * BLCKSZ;
766735
char path[MAXPGPATH];
767736
int fd;
737+
bool attempted_download = false;
768738

769739
SlruFileName(ctl, path, segno);
770740

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

807775
errno = 0;

src/backend/storage/smgr/smgr.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -784,10 +784,10 @@ smgr_end_unlogged_build(SMgrRelation reln)
784784
* of partial segment, it can be smaller. Zero value means that segment doesn't exist.
785785
* From Postgres point of view empty segment is the same as absent segment.
786786
*/
787-
int
788-
smgr_read_slru_segment(SMgrRelation reln, const char* path, int segno, void* buffer)
787+
bool
788+
smgr_read_slru_segment(SMgrRelation reln, const char* path, int segno)
789789
{
790-
return (*reln->smgr).smgr_read_slru_segment ? (*reln->smgr).smgr_read_slru_segment(reln, path, segno, buffer) : 0;
790+
return (*reln->smgr).smgr_read_slru_segment ? (*reln->smgr).smgr_read_slru_segment(reln, path, segno) : false;
791791
}
792792

793793

src/include/miscadmin.h

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

180174
extern PGDLLIMPORT bool ExitOnAnyError;
181175

src/include/storage/smgr.h

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

134-
int (*smgr_read_slru_segment) (SMgrRelation reln, const char *path, int segno, void* buffer);
134+
bool (*smgr_read_slru_segment) (SMgrRelation reln, const char *path, int segno);
135135
} f_smgr;
136136

137137
typedef void (*smgr_init_hook_type) (void);
@@ -192,6 +192,6 @@ extern void smgr_start_unlogged_build(SMgrRelation reln);
192192
extern void smgr_finish_unlogged_build_phase_1(SMgrRelation reln);
193193
extern void smgr_end_unlogged_build(SMgrRelation reln);
194194

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

197197
#endif /* SMGR_H */

0 commit comments

Comments
 (0)