93 if (
ctl->long_segment_names)
113 (
unsigned int) segno);
123#define MAX_WRITEALL_BUFFERS 16
142#define SLRU_BANK_BITSHIFT 4
143#define SLRU_BANK_SIZE (1 << SLRU_BANK_BITSHIFT)
148#define SlotGetBankNumber(slotno) ((slotno) >> SLRU_BANK_BITSHIFT)
156#define INIT_SLRUFILETAG(a,xx_handler,xx_segno) \
158 memset(&(a), 0, sizeof(FileTag)), \
159 (a).handler = (xx_handler), \
160 (a).segno = (xx_segno) \
208 sz +=
MAXALIGN(nslots *
sizeof(
char *));
210 sz +=
MAXALIGN(nslots *
sizeof(
bool));
212 sz +=
MAXALIGN(nslots *
sizeof(
int));
215 sz +=
MAXALIGN(nbanks *
sizeof(
int));
253 const char *subdir,
int buffer_tranche_id,
int bank_tranche_id,
283 ptr = (
char *) shared;
286 offset +=
MAXALIGN(nslots *
sizeof(
char *));
290 offset +=
MAXALIGN(nslots *
sizeof(
bool));
294 offset +=
MAXALIGN(nslots *
sizeof(
int));
302 offset +=
MAXALIGN(nbanks *
sizeof(
int));
311 for (
int slotno = 0; slotno < nslots; slotno++)
324 for (
int bankno = 0; bankno < nbanks; bankno++)
343 ctl->shared = shared;
344 ctl->sync_handler = sync_handler;
345 ctl->long_segment_names = long_segment_names;
346 ctl->nbanks = nbanks;
457 Assert(!
ctl->shared->page_dirty[slotno]);
634 int bankno = pageno %
ctl->nbanks;
642 for (
int slotno = bankstart; slotno < bankend; slotno++)
775 int offset = rpageno * BLCKSZ;
799 if ((
endpos = lseek(
fd, 0, SEEK_END)) < 0)
806 result =
endpos >= (off_t) (offset + BLCKSZ);
834 off_t offset = rpageno * BLCKSZ;
858 (
errmsg(
"file \"%s\" doesn't exist, reading as zeroes",
906 off_t offset = rpageno * BLCKSZ;
936 if (max_lsn < this_lsn)
1077 int offset = rpageno * BLCKSZ;
1087 errmsg(
"could not access status of transaction %u", xid),
1088 errdetail(
"Could not open file \"%s\": %m.", path)));
1093 errmsg(
"could not access status of transaction %u", xid),
1094 errdetail(
"Could not seek in file \"%s\" to offset %d: %m.",
1101 errmsg(
"could not access status of transaction %u", xid),
1102 errdetail(
"Could not read from file \"%s\" at offset %d: %m.",
1106 (
errmsg(
"could not access status of transaction %u", xid),
1107 errdetail(
"Could not read from file \"%s\" at offset %d: read too few bytes.", path, offset)));
1113 errmsg(
"could not access status of transaction %u", xid),
1114 errdetail(
"Could not write to file \"%s\" at offset %d: %m.",
1118 (
errmsg(
"could not access status of transaction %u", xid),
1119 errdetail(
"Could not write to file \"%s\" at offset %d: wrote too few bytes.",
1125 errmsg(
"could not access status of transaction %u", xid),
1126 errdetail(
"Could not fsync file \"%s\": %m.",
1132 errmsg(
"could not access status of transaction %u", xid),
1133 errdetail(
"Could not close file \"%s\": %m.",
1138 elog(
ERROR,
"unrecognized SimpleLru error cause: %d",
1202 int bestvalidslot = 0;
1203 int best_valid_delta = -1;
1204 int64 best_valid_page_number = 0;
1205 int bestinvalidslot = 0;
1206 int best_invalid_delta = -1;
1207 int64 best_invalid_page_number = 0;
1208 int bankno = pageno %
ctl->nbanks;
1215 for (
int slotno = bankstart; slotno < bankend; slotno++)
1250 for (
int slotno = bankstart; slotno < bankend; slotno++)
1253 int64 this_page_number;
1278 if (this_page_number ==
1284 if (this_delta > best_valid_delta ||
1285 (this_delta == best_valid_delta &&
1286 ctl->PagePrecedes(this_page_number,
1287 best_valid_page_number)))
1289 bestvalidslot = slotno;
1290 best_valid_delta = this_delta;
1291 best_valid_page_number = this_page_number;
1296 if (this_delta > best_invalid_delta ||
1297 (this_delta == best_invalid_delta &&
1298 ctl->PagePrecedes(this_page_number,
1299 best_invalid_page_number)))
1301 bestinvalidslot = slotno;
1302 best_invalid_delta = this_delta;
1303 best_invalid_page_number = this_page_number;
1315 if (best_valid_delta < 0)
1325 return bestvalidslot;
1365 for (
int slotno = 0; slotno < shared->
num_slots; slotno++)
1373 if (curbank != prevbank)
1391 Assert(allow_redirtied ||
1459 (
errmsg(
"could not truncate directory \"%s\": apparent wraparound",
1466 for (
int slotno = 0; slotno < shared->
num_slots; slotno++)
1474 if (curbank != prevbank)
1561 for (
int slotno = 0; slotno < shared->
num_slots; slotno++)
1570 if (curbank != prevbank)
1582 if (pagesegno !=
segno)
1634 return (
ctl->PagePrecedes(segpage, cutoffPage) &&
1635 ctl->PagePrecedes(seg_last_page, cutoffPage));
1638#ifdef USE_ASSERT_CHECKING
1655 lhs = per_page + offset;
1656 rhs = lhs + (1U << 31);
1665 Assert(!
ctl->PagePrecedes(lhs / per_page, lhs / per_page));
1666 Assert(!
ctl->PagePrecedes(lhs / per_page, rhs / per_page));
1667 Assert(!
ctl->PagePrecedes(rhs / per_page, lhs / per_page));
1668 Assert(!
ctl->PagePrecedes((lhs - per_page) / per_page, rhs / per_page));
1669 Assert(
ctl->PagePrecedes(rhs / per_page, (lhs - 3 * per_page) / per_page));
1670 Assert(
ctl->PagePrecedes(rhs / per_page, (lhs - 2 * per_page) / per_page));
1671 Assert(
ctl->PagePrecedes(rhs / per_page, (lhs - 1 * per_page) / per_page)
1672 || (1U << 31) % per_page != 0);
1673 Assert(
ctl->PagePrecedes((lhs + 1 * per_page) / per_page, rhs / per_page)
1674 || (1U << 31) % per_page != 0);
1675 Assert(
ctl->PagePrecedes((lhs + 2 * per_page) / per_page, rhs / per_page));
1676 Assert(
ctl->PagePrecedes((lhs + 3 * per_page) / per_page, rhs / per_page));
1677 Assert(!
ctl->PagePrecedes(rhs / per_page, (lhs + per_page) / per_page));
1685 newestXact = newestPage * per_page + offset;
1686 Assert(newestXact / per_page == newestPage);
1687 oldestXact = newestXact + 1;
1688 oldestXact -= 1U << 31;
1689 oldestPage = oldestXact / per_page;
1701 newestXact = newestPage * per_page + offset;
1702 Assert(newestXact / per_page == newestPage);
1703 oldestXact = newestXact + 1;
1704 oldestXact -= 1U << 31;
1705 oldestPage = oldestXact / per_page;
1725 SlruPagePrecedesTestOffset(
ctl, per_page, 0);
1726 SlruPagePrecedesTestOffset(
ctl, per_page, per_page / 2);
1727 SlruPagePrecedesTestOffset(
ctl, per_page, per_page - 1);
1785 if (
ctl->long_segment_names)
1797 return (
len == 4 ||
len == 5 ||
len == 6);
1818 bool retval =
false;
1825 while ((clde =
ReadDir(cldir,
ctl->Dir)) != NULL)
1832 strspn(clde->
d_name,
"0123456789ABCDEF") ==
len)
1834 segno = strtoi64(clde->
d_name, NULL, 16);
1837 elog(
DEBUG2,
"SlruScanDirectory invoking callback on %s/%s",
static void pg_atomic_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
static void pg_atomic_init_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
static uint64 pg_atomic_read_u64(volatile pg_atomic_uint64 *ptr)
#define MemSet(start, val, len)
int errmsg_internal(const char *fmt,...)
int errcode_for_file_access(void)
int errdetail(const char *fmt,...)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
int CloseTransientFile(int fd)
void fsync_fname(const char *fname, bool isdir)
int data_sync_elevel(int elevel)
DIR * AllocateDir(const char *dirname)
struct dirent * ReadDir(DIR *dir, const char *dirname)
int OpenTransientFile(const char *fileName, int fileFlags)
#define GUC_check_errdetail
Assert(PointerIsAligned(start, uint64))
bool LWLockHeldByMe(LWLock *lock)
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
bool LWLockHeldByMeInMode(LWLock *lock, LWLockMode mode)
void LWLockRelease(LWLock *lock)
void LWLockInitialize(LWLock *lock, int tranche_id)
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
#define START_CRIT_SECTION()
#define END_CRIT_SECTION()
void pgstat_count_slru_blocks_zeroed(int slru_idx)
void pgstat_count_slru_blocks_hit(int slru_idx)
void pgstat_count_slru_truncate(int slru_idx)
void pgstat_count_slru_blocks_read(int slru_idx)
void pgstat_count_slru_blocks_written(int slru_idx)
void pgstat_count_slru_flush(int slru_idx)
void pgstat_count_slru_blocks_exists(int slru_idx)
PgStat_CheckpointerStats PendingCheckpointerStats
int pgstat_get_slru_index(const char *name)
size_t strlcpy(char *dst, const char *src, size_t siz)
static int fd(const char *x, int i)
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns, const char *subdir, int buffer_tranche_id, int bank_tranche_id, SyncRequestHandler sync_handler, bool long_segment_names)
static int SlruFileName(SlruCtl ctl, char *path, int64 segno)
static bool SlruPhysicalReadPage(SlruCtl ctl, int64 pageno, int slotno)
int SimpleLruReadPage_ReadOnly(SlruCtl ctl, int64 pageno, TransactionId xid)
#define INIT_SLRUFILETAG(a, xx_handler, xx_segno)
void SimpleLruWritePage(SlruCtl ctl, int slotno)
void SimpleLruWriteAll(SlruCtl ctl, bool allow_redirtied)
static bool SlruMayDeleteSegment(SlruCtl ctl, int64 segpage, int64 cutoffPage)
static void SlruReportIOError(SlruCtl ctl, int64 pageno, TransactionId xid)
struct SlruWriteAllData SlruWriteAllData
static void SimpleLruZeroLSNs(SlruCtl ctl, int slotno)
int SimpleLruAutotuneBuffers(int divisor, int max)
static bool SlruPhysicalWritePage(SlruCtl ctl, int64 pageno, int slotno, SlruWriteAll fdata)
static bool SlruCorrectSegmentFilenameLength(SlruCtl ctl, size_t len)
static SlruErrorCause slru_errcause
#define MAX_WRITEALL_BUFFERS
static void SimpleLruWaitIO(SlruCtl ctl, int slotno)
bool SimpleLruDoesPhysicalPageExist(SlruCtl ctl, int64 pageno)
void SlruDeleteSegment(SlruCtl ctl, int64 segno)
static void SlruInternalWritePage(SlruCtl ctl, int slotno, SlruWriteAll fdata)
bool SlruScanDirectory(SlruCtl ctl, SlruScanCallback callback, void *data)
bool SlruScanDirCbDeleteAll(SlruCtl ctl, char *filename, int64 segpage, void *data)
int SimpleLruReadPage(SlruCtl ctl, int64 pageno, bool write_ok, TransactionId xid)
int SlruSyncFileTag(SlruCtl ctl, const FileTag *ftag, char *path)
static int SlruSelectLRUPage(SlruCtl ctl, int64 pageno)
#define SlotGetBankNumber(slotno)
int SimpleLruZeroPage(SlruCtl ctl, int64 pageno)
void SimpleLruZeroAndWritePage(SlruCtl ctl, int64 pageno)
void SimpleLruTruncate(SlruCtl ctl, int64 cutoffPage)
static void SlruInternalDeleteSegment(SlruCtl ctl, int64 segno)
struct SlruWriteAllData * SlruWriteAll
Size SimpleLruShmemSize(int nslots, int nlsns)
bool SlruScanDirCbReportPresence(SlruCtl ctl, char *filename, int64 segpage, void *data)
static bool SlruScanDirCbDeleteCutoff(SlruCtl ctl, char *filename, int64 segpage, void *data)
static void SlruRecentlyUsed(SlruShared shared, int slotno)
bool check_slru_buffers(const char *name, int *newval)
static LWLock * SimpleLruGetBankLock(SlruCtl ctl, int64 pageno)
SlruSharedData * SlruShared
#define SlruPagePrecedesUnitTests(ctl, per_page)
bool(* SlruScanCallback)(SlruCtl ctl, char *filename, int64 segpage, void *data)
#define SLRU_PAGES_PER_SEGMENT
#define SLRU_MAX_ALLOWED_BUFFERS
@ SLRU_PAGE_WRITE_IN_PROGRESS
@ SLRU_PAGE_READ_IN_PROGRESS
PgStat_Counter slru_written
LWLockPadded * bank_locks
pg_atomic_uint64 latest_page_number
SlruPageStatus * page_status
LWLockPadded * buffer_locks
int fd[MAX_WRITEALL_BUFFERS]
int64 segno[MAX_WRITEALL_BUFFERS]
bool RegisterSyncRequest(const FileTag *ftag, SyncRequestType type, bool retryOnError)
static void callback(struct sockaddr *addr, struct sockaddr *mask, void *unused)
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
#define InvalidTransactionId
static void pgstat_report_wait_start(uint32 wait_event_info)
static void pgstat_report_wait_end(void)
CheckpointStatsData CheckpointStats
void XLogFlush(XLogRecPtr record)
#define XLogRecPtrIsInvalid(r)