93 if (
ctl->long_segment_names)
114 (
unsigned int) segno);
124#define MAX_WRITEALL_BUFFERS 16
143#define SLRU_BANK_BITSHIFT 4
144#define SLRU_BANK_SIZE (1 << SLRU_BANK_BITSHIFT)
149#define SlotGetBankNumber(slotno) ((slotno) >> SLRU_BANK_BITSHIFT)
157#define INIT_SLRUFILETAG(a,xx_handler,xx_segno) \
159 memset(&(a), 0, sizeof(FileTag)), \
160 (a).handler = (xx_handler), \
161 (a).segno = (xx_segno) \
209 sz +=
MAXALIGN(nslots *
sizeof(
char *));
211 sz +=
MAXALIGN(nslots *
sizeof(
bool));
213 sz +=
MAXALIGN(nslots *
sizeof(
int));
216 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;
609 int bankno = pageno %
ctl->nbanks;
617 for (
int slotno = bankstart; slotno < bankend; slotno++)
750 int offset = rpageno * BLCKSZ;
774 if ((
endpos = lseek(
fd, 0, SEEK_END)) < 0)
781 result =
endpos >= (off_t) (offset + BLCKSZ);
809 off_t offset = rpageno * BLCKSZ;
833 (
errmsg(
"file \"%s\" doesn't exist, reading as zeroes",
881 off_t offset = rpageno * BLCKSZ;
911 if (max_lsn < this_lsn)
1052 int offset = rpageno * BLCKSZ;
1062 errmsg(
"could not access status of transaction %u", xid),
1063 errdetail(
"Could not open file \"%s\": %m.", path)));
1068 errmsg(
"could not access status of transaction %u", xid),
1069 errdetail(
"Could not seek in file \"%s\" to offset %d: %m.",
1076 errmsg(
"could not access status of transaction %u", xid),
1077 errdetail(
"Could not read from file \"%s\" at offset %d: %m.",
1081 (
errmsg(
"could not access status of transaction %u", xid),
1082 errdetail(
"Could not read from file \"%s\" at offset %d: read too few bytes.", path, offset)));
1088 errmsg(
"could not access status of transaction %u", xid),
1089 errdetail(
"Could not write to file \"%s\" at offset %d: %m.",
1093 (
errmsg(
"could not access status of transaction %u", xid),
1094 errdetail(
"Could not write to file \"%s\" at offset %d: wrote too few bytes.",
1100 errmsg(
"could not access status of transaction %u", xid),
1101 errdetail(
"Could not fsync file \"%s\": %m.",
1107 errmsg(
"could not access status of transaction %u", xid),
1108 errdetail(
"Could not close file \"%s\": %m.",
1113 elog(
ERROR,
"unrecognized SimpleLru error cause: %d",
1177 int bestvalidslot = 0;
1178 int best_valid_delta = -1;
1179 int64 best_valid_page_number = 0;
1180 int bestinvalidslot = 0;
1181 int best_invalid_delta = -1;
1182 int64 best_invalid_page_number = 0;
1183 int bankno = pageno %
ctl->nbanks;
1190 for (
int slotno = bankstart; slotno < bankend; slotno++)
1225 for (
int slotno = bankstart; slotno < bankend; slotno++)
1228 int64 this_page_number;
1253 if (this_page_number ==
1259 if (this_delta > best_valid_delta ||
1260 (this_delta == best_valid_delta &&
1261 ctl->PagePrecedes(this_page_number,
1262 best_valid_page_number)))
1264 bestvalidslot = slotno;
1265 best_valid_delta = this_delta;
1266 best_valid_page_number = this_page_number;
1271 if (this_delta > best_invalid_delta ||
1272 (this_delta == best_invalid_delta &&
1273 ctl->PagePrecedes(this_page_number,
1274 best_invalid_page_number)))
1276 bestinvalidslot = slotno;
1277 best_invalid_delta = this_delta;
1278 best_invalid_page_number = this_page_number;
1290 if (best_valid_delta < 0)
1300 return bestvalidslot;
1340 for (
int slotno = 0; slotno < shared->
num_slots; slotno++)
1348 if (curbank != prevbank)
1366 Assert(allow_redirtied ||
1434 (
errmsg(
"could not truncate directory \"%s\": apparent wraparound",
1441 for (
int slotno = 0; slotno < shared->
num_slots; slotno++)
1449 if (curbank != prevbank)
1536 for (
int slotno = 0; slotno < shared->
num_slots; slotno++)
1545 if (curbank != prevbank)
1557 if (pagesegno !=
segno)
1609 return (
ctl->PagePrecedes(segpage, cutoffPage) &&
1610 ctl->PagePrecedes(seg_last_page, cutoffPage));
1613#ifdef USE_ASSERT_CHECKING
1630 lhs = per_page + offset;
1631 rhs = lhs + (1U << 31);
1640 Assert(!
ctl->PagePrecedes(lhs / per_page, lhs / per_page));
1641 Assert(!
ctl->PagePrecedes(lhs / per_page, rhs / per_page));
1642 Assert(!
ctl->PagePrecedes(rhs / per_page, lhs / per_page));
1643 Assert(!
ctl->PagePrecedes((lhs - per_page) / per_page, rhs / per_page));
1644 Assert(
ctl->PagePrecedes(rhs / per_page, (lhs - 3 * per_page) / per_page));
1645 Assert(
ctl->PagePrecedes(rhs / per_page, (lhs - 2 * per_page) / per_page));
1646 Assert(
ctl->PagePrecedes(rhs / per_page, (lhs - 1 * per_page) / per_page)
1647 || (1U << 31) % per_page != 0);
1648 Assert(
ctl->PagePrecedes((lhs + 1 * per_page) / per_page, rhs / per_page)
1649 || (1U << 31) % per_page != 0);
1650 Assert(
ctl->PagePrecedes((lhs + 2 * per_page) / per_page, rhs / per_page));
1651 Assert(
ctl->PagePrecedes((lhs + 3 * per_page) / per_page, rhs / per_page));
1652 Assert(!
ctl->PagePrecedes(rhs / per_page, (lhs + per_page) / per_page));
1660 newestXact = newestPage * per_page + offset;
1661 Assert(newestXact / per_page == newestPage);
1662 oldestXact = newestXact + 1;
1663 oldestXact -= 1U << 31;
1664 oldestPage = oldestXact / per_page;
1676 newestXact = newestPage * per_page + offset;
1677 Assert(newestXact / per_page == newestPage);
1678 oldestXact = newestXact + 1;
1679 oldestXact -= 1U << 31;
1680 oldestPage = oldestXact / per_page;
1700 SlruPagePrecedesTestOffset(
ctl, per_page, 0);
1701 SlruPagePrecedesTestOffset(
ctl, per_page, per_page / 2);
1702 SlruPagePrecedesTestOffset(
ctl, per_page, per_page - 1);
1760 if (
ctl->long_segment_names)
1772 return (
len == 4 ||
len == 5 ||
len == 6);
1793 bool retval =
false;
1800 while ((clde =
ReadDir(cldir,
ctl->Dir)) != NULL)
1807 strspn(clde->
d_name,
"0123456789ABCDEF") ==
len)
1809 segno = strtoi64(clde->
d_name, NULL, 16);
1812 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 Assert(condition)
#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
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)