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));
252 const char *subdir,
int buffer_tranche_id,
int bank_tranche_id,
282 ptr = (
char *) shared;
285 offset +=
MAXALIGN(nslots *
sizeof(
char *));
289 offset +=
MAXALIGN(nslots *
sizeof(
bool));
293 offset +=
MAXALIGN(nslots *
sizeof(
int));
301 offset +=
MAXALIGN(nbanks *
sizeof(
int));
310 for (
int slotno = 0; slotno < nslots; slotno++)
323 for (
int bankno = 0; bankno < nbanks; bankno++)
342 ctl->shared = shared;
343 ctl->sync_handler = sync_handler;
344 ctl->long_segment_names = long_segment_names;
345 ctl->nbanks = nbanks;
608 int bankno = pageno %
ctl->nbanks;
616 for (
int slotno = bankstart; slotno < bankend; slotno++)
749 int offset = rpageno * BLCKSZ;
773 if ((
endpos = lseek(
fd, 0, SEEK_END)) < 0)
780 result =
endpos >= (off_t) (offset + BLCKSZ);
808 off_t offset = rpageno * BLCKSZ;
832 (
errmsg(
"file \"%s\" doesn't exist, reading as zeroes",
880 off_t offset = rpageno * BLCKSZ;
910 if (max_lsn < this_lsn)
1051 int offset = rpageno * BLCKSZ;
1061 errmsg(
"could not access status of transaction %u", xid),
1062 errdetail(
"Could not open file \"%s\": %m.", path)));
1067 errmsg(
"could not access status of transaction %u", xid),
1068 errdetail(
"Could not seek in file \"%s\" to offset %d: %m.",
1075 errmsg(
"could not access status of transaction %u", xid),
1076 errdetail(
"Could not read from file \"%s\" at offset %d: %m.",
1080 (
errmsg(
"could not access status of transaction %u", xid),
1081 errdetail(
"Could not read from file \"%s\" at offset %d: read too few bytes.", path, offset)));
1087 errmsg(
"could not access status of transaction %u", xid),
1088 errdetail(
"Could not write to file \"%s\" at offset %d: %m.",
1092 (
errmsg(
"could not access status of transaction %u", xid),
1093 errdetail(
"Could not write to file \"%s\" at offset %d: wrote too few bytes.",
1099 errmsg(
"could not access status of transaction %u", xid),
1100 errdetail(
"Could not fsync file \"%s\": %m.",
1106 errmsg(
"could not access status of transaction %u", xid),
1107 errdetail(
"Could not close file \"%s\": %m.",
1112 elog(
ERROR,
"unrecognized SimpleLru error cause: %d",
1176 int bestvalidslot = 0;
1177 int best_valid_delta = -1;
1178 int64 best_valid_page_number = 0;
1179 int bestinvalidslot = 0;
1180 int best_invalid_delta = -1;
1181 int64 best_invalid_page_number = 0;
1182 int bankno = pageno %
ctl->nbanks;
1189 for (
int slotno = bankstart; slotno < bankend; slotno++)
1224 for (
int slotno = bankstart; slotno < bankend; slotno++)
1227 int64 this_page_number;
1252 if (this_page_number ==
1258 if (this_delta > best_valid_delta ||
1259 (this_delta == best_valid_delta &&
1260 ctl->PagePrecedes(this_page_number,
1261 best_valid_page_number)))
1263 bestvalidslot = slotno;
1264 best_valid_delta = this_delta;
1265 best_valid_page_number = this_page_number;
1270 if (this_delta > best_invalid_delta ||
1271 (this_delta == best_invalid_delta &&
1272 ctl->PagePrecedes(this_page_number,
1273 best_invalid_page_number)))
1275 bestinvalidslot = slotno;
1276 best_invalid_delta = this_delta;
1277 best_invalid_page_number = this_page_number;
1289 if (best_valid_delta < 0)
1299 return bestvalidslot;
1339 for (
int slotno = 0; slotno < shared->
num_slots; slotno++)
1347 if (curbank != prevbank)
1365 Assert(allow_redirtied ||
1433 (
errmsg(
"could not truncate directory \"%s\": apparent wraparound",
1440 for (
int slotno = 0; slotno < shared->
num_slots; slotno++)
1448 if (curbank != prevbank)
1535 for (
int slotno = 0; slotno < shared->
num_slots; slotno++)
1544 if (curbank != prevbank)
1556 if (pagesegno !=
segno)
1608 return (
ctl->PagePrecedes(segpage, cutoffPage) &&
1609 ctl->PagePrecedes(seg_last_page, cutoffPage));
1612#ifdef USE_ASSERT_CHECKING
1629 lhs = per_page + offset;
1630 rhs = lhs + (1U << 31);
1639 Assert(!
ctl->PagePrecedes(lhs / per_page, lhs / per_page));
1640 Assert(!
ctl->PagePrecedes(lhs / per_page, rhs / per_page));
1641 Assert(!
ctl->PagePrecedes(rhs / per_page, lhs / per_page));
1642 Assert(!
ctl->PagePrecedes((lhs - per_page) / per_page, rhs / per_page));
1643 Assert(
ctl->PagePrecedes(rhs / per_page, (lhs - 3 * per_page) / per_page));
1644 Assert(
ctl->PagePrecedes(rhs / per_page, (lhs - 2 * per_page) / per_page));
1645 Assert(
ctl->PagePrecedes(rhs / per_page, (lhs - 1 * per_page) / per_page)
1646 || (1U << 31) % per_page != 0);
1647 Assert(
ctl->PagePrecedes((lhs + 1 * per_page) / per_page, rhs / per_page)
1648 || (1U << 31) % per_page != 0);
1649 Assert(
ctl->PagePrecedes((lhs + 2 * per_page) / per_page, rhs / per_page));
1650 Assert(
ctl->PagePrecedes((lhs + 3 * per_page) / per_page, rhs / per_page));
1651 Assert(!
ctl->PagePrecedes(rhs / per_page, (lhs + per_page) / per_page));
1659 newestXact = newestPage * per_page + offset;
1660 Assert(newestXact / per_page == newestPage);
1661 oldestXact = newestXact + 1;
1662 oldestXact -= 1U << 31;
1663 oldestPage = oldestXact / per_page;
1675 newestXact = newestPage * per_page + offset;
1676 Assert(newestXact / per_page == newestPage);
1677 oldestXact = newestXact + 1;
1678 oldestXact -= 1U << 31;
1679 oldestPage = oldestXact / per_page;
1699 SlruPagePrecedesTestOffset(
ctl, per_page, 0);
1700 SlruPagePrecedesTestOffset(
ctl, per_page, per_page / 2);
1701 SlruPagePrecedesTestOffset(
ctl, per_page, per_page - 1);
1759 if (
ctl->long_segment_names)
1771 return (
len == 4 ||
len == 5 ||
len == 6);
1792 bool retval =
false;
1799 while ((clde =
ReadDir(cldir,
ctl->Dir)) != NULL)
1806 strspn(clde->
d_name,
"0123456789ABCDEF") ==
len)
1808 segno = strtoi64(clde->
d_name, NULL, 16);
1811 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()
PgStat_CheckpointerStats PendingCheckpointerStats
void pgstat_count_slru_page_exists(int slru_idx)
void pgstat_count_slru_page_read(int slru_idx)
int pgstat_get_slru_index(const char *name)
void pgstat_count_slru_page_hit(int slru_idx)
void pgstat_count_slru_page_zeroed(int slru_idx)
void pgstat_count_slru_truncate(int slru_idx)
void pgstat_count_slru_page_written(int slru_idx)
void pgstat_count_slru_flush(int slru_idx)
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 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)