Skip to content

Commit 4feaaa0

Browse files
author
Konstantin Knizhnik
committed
On demand downloading of SLRU segments
1 parent 03358bb commit 4feaaa0

File tree

4 files changed

+118
-13
lines changed

4 files changed

+118
-13
lines changed

src/backend/access/transam/slru.c

+99-13
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
#include "pgstat.h"
5959
#include "storage/fd.h"
6060
#include "storage/shmem.h"
61+
#include "storage/smgr.h"
6162

6263
#define SlruFileName(ctl, path, seg) \
6364
snprintf(path, MAXPGPATH, "%s/%04X", (ctl)->Dir, seg)
@@ -266,6 +267,15 @@ SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns,
266267
ctl->shared = shared;
267268
ctl->sync_handler = sync_handler;
268269
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;
269279
}
270280

271281
/*
@@ -616,6 +626,64 @@ SimpleLruWritePage(SlruCtl ctl, int slotno)
616626
SlruInternalWritePage(ctl, slotno, NULL);
617627
}
618628

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+
619687
/*
620688
* Return whether the given page exists on disk.
621689
*
@@ -643,12 +711,18 @@ SimpleLruDoesPhysicalPageExist(SlruCtl ctl, int pageno)
643711
{
644712
/* expected: file doesn't exist */
645713
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+
}
652726
}
653727

654728
if ((endpos = lseek(fd, 0, SEEK_END)) < 0)
@@ -702,18 +776,30 @@ SlruPhysicalReadPage(SlruCtl ctl, int pageno, int slotno)
702776
fd = OpenTransientFile(path, O_RDONLY | PG_BINARY);
703777
if (fd < 0)
704778
{
705-
if (errno != ENOENT || !InRecovery)
779+
if (errno != ENOENT)
706780
{
707781
slru_errcause = SLRU_OPEN_FAILED;
708782
slru_errno = errno;
709783
return false;
710784
}
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+
}
717803
}
718804

719805
errno = 0;

src/backend/storage/smgr/smgr.c

+7
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,13 @@ smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
538538
buffer, skipFsync);
539539
}
540540

541+
int
542+
smgr_read_slru_segment(SMgrRelation reln, SlruKind kind, int segno, void* buffer)
543+
{
544+
return (*reln->smgr).smgr_read_slru_segment && (*reln->smgr).smgr_read_slru_segment(reln, kind, segno, buffer);
545+
}
546+
547+
541548

542549
/*
543550
* smgrwriteback() -- Trigger kernel writeback for the supplied range of

src/include/access/slru.h

+2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "access/xlogdefs.h"
1717
#include "storage/lwlock.h"
1818
#include "storage/sync.h"
19+
#include "storage/smgr.h"
1920

2021

2122
/*
@@ -134,6 +135,7 @@ typedef struct SlruCtlData
134135
* it's always the same, it doesn't need to be in shared memory.
135136
*/
136137
char Dir[64];
138+
SlruKind kind;
137139
} SlruCtlData;
138140

139141
typedef SlruCtlData *SlruCtl;

src/include/storage/smgr.h

+10
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,12 @@ typedef SMgrRelationData *SMgrRelation;
8888
#define SmgrIsTemp(smgr) \
8989
RelFileNodeBackendIsTemp((smgr)->smgr_rnode)
9090

91+
typedef enum {
92+
SLRU_CLOG,
93+
SLRU_MULTIXACT_MEMBERS,
94+
SLRU_MULTIXACT_OFFSETS,
95+
SLRU_OTHER
96+
} SlruKind;
9197

9298
/*
9399
* This struct of function pointers defines the API between smgr.c and
@@ -129,6 +135,8 @@ typedef struct f_smgr
129135
void (*smgr_start_unlogged_build) (SMgrRelation reln);
130136
void (*smgr_finish_unlogged_build_phase_1) (SMgrRelation reln);
131137
void (*smgr_end_unlogged_build) (SMgrRelation reln);
138+
139+
int (*smgr_read_slru_segment) (SMgrRelation reln, SlruKind kind, int segno, void* buffer);
132140
} f_smgr;
133141

134142
typedef void (*smgr_init_hook_type) (void);
@@ -180,4 +188,6 @@ extern void smgr_start_unlogged_build(SMgrRelation reln);
180188
extern void smgr_finish_unlogged_build_phase_1(SMgrRelation reln);
181189
extern void smgr_end_unlogged_build(SMgrRelation reln);
182190

191+
extern int smgr_read_slru_segment(SMgrRelation reln, SlruKind kind, int segno, void* buffer);
192+
183193
#endif /* SMGR_H */

0 commit comments

Comments
 (0)