93 if (
ctl->long_segment_names)
102 Assert(segno >= 0 && segno <= INT64CONST(0xFFFFFFFFFFFFFFF));
112 Assert(segno >= 0 && segno <= INT64CONST(0xFFFFFF));
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) \
189 int64 segpage,
void *
data);
209 sz +=
MAXALIGN(nslots *
sizeof(
char *));
211 sz +=
MAXALIGN(nslots *
sizeof(
bool));
212 sz +=
MAXALIGN(nslots *
sizeof(int64));
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));
292 offset +=
MAXALIGN(nslots *
sizeof(int64));
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;
609 int bankno = pageno &
ctl->bank_mask;
617 for (
int slotno = bankstart; slotno < bankend; slotno++)
747 int offset = rpageno * BLCKSZ;
771 if ((
endpos = lseek(
fd, 0, SEEK_END)) < 0)
778 result =
endpos >= (off_t) (offset + BLCKSZ);
806 off_t offset = rpageno * BLCKSZ;
830 (
errmsg(
"file \"%s\" doesn't exist, reading as zeroes",
878 off_t offset = rpageno * BLCKSZ;
908 if (max_lsn < this_lsn)
1049 int offset = rpageno * BLCKSZ;
1059 errmsg(
"could not access status of transaction %u", xid),
1060 errdetail(
"Could not open file \"%s\": %m.", path)));
1065 errmsg(
"could not access status of transaction %u", xid),
1066 errdetail(
"Could not seek in file \"%s\" to offset %d: %m.",
1073 errmsg(
"could not access status of transaction %u", xid),
1074 errdetail(
"Could not read from file \"%s\" at offset %d: %m.",
1078 (
errmsg(
"could not access status of transaction %u", xid),
1079 errdetail(
"Could not read from file \"%s\" at offset %d: read too few bytes.", path, offset)));
1085 errmsg(
"could not access status of transaction %u", xid),
1086 errdetail(
"Could not write to file \"%s\" at offset %d: %m.",
1090 (
errmsg(
"could not access status of transaction %u", xid),
1091 errdetail(
"Could not write to file \"%s\" at offset %d: wrote too few bytes.",
1097 errmsg(
"could not access status of transaction %u", xid),
1098 errdetail(
"Could not fsync file \"%s\": %m.",
1104 errmsg(
"could not access status of transaction %u", xid),
1105 errdetail(
"Could not close file \"%s\": %m.",
1110 elog(
ERROR,
"unrecognized SimpleLru error cause: %d",
1174 int bestvalidslot = 0;
1175 int best_valid_delta = -1;
1176 int64 best_valid_page_number = 0;
1177 int bestinvalidslot = 0;
1178 int best_invalid_delta = -1;
1179 int64 best_invalid_page_number = 0;
1180 int bankno = pageno &
ctl->bank_mask;
1187 for (
int slotno = bankstart; slotno < bankend; slotno++)
1222 for (
int slotno = bankstart; slotno < bankend; slotno++)
1225 int64 this_page_number;
1250 if (this_page_number ==
1256 if (this_delta > best_valid_delta ||
1257 (this_delta == best_valid_delta &&
1258 ctl->PagePrecedes(this_page_number,
1259 best_valid_page_number)))
1261 bestvalidslot = slotno;
1262 best_valid_delta = this_delta;
1263 best_valid_page_number = this_page_number;
1268 if (this_delta > best_invalid_delta ||
1269 (this_delta == best_invalid_delta &&
1270 ctl->PagePrecedes(this_page_number,
1271 best_invalid_page_number)))
1273 bestinvalidslot = slotno;
1274 best_invalid_delta = this_delta;
1275 best_invalid_page_number = this_page_number;
1287 if (best_valid_delta < 0)
1297 return bestvalidslot;
1337 for (
int slotno = 0; slotno < shared->
num_slots; slotno++)
1345 if (curbank != prevbank)
1363 Assert(allow_redirtied ||
1431 (
errmsg(
"could not truncate directory \"%s\": apparent wraparound",
1438 for (
int slotno = 0; slotno < shared->
num_slots; slotno++)
1446 if (curbank != prevbank)
1533 for (
int slotno = 0; slotno < shared->
num_slots; slotno++)
1542 if (curbank != prevbank)
1554 if (pagesegno !=
segno)
1606 return (
ctl->PagePrecedes(segpage, cutoffPage) &&
1607 ctl->PagePrecedes(seg_last_page, cutoffPage));
1610 #ifdef USE_ASSERT_CHECKING
1627 lhs = per_page + offset;
1628 rhs = lhs + (1U << 31);
1637 Assert(!
ctl->PagePrecedes(lhs / per_page, lhs / per_page));
1638 Assert(!
ctl->PagePrecedes(lhs / per_page, rhs / per_page));
1639 Assert(!
ctl->PagePrecedes(rhs / per_page, lhs / per_page));
1640 Assert(!
ctl->PagePrecedes((lhs - per_page) / per_page, rhs / per_page));
1641 Assert(
ctl->PagePrecedes(rhs / per_page, (lhs - 3 * per_page) / per_page));
1642 Assert(
ctl->PagePrecedes(rhs / per_page, (lhs - 2 * per_page) / per_page));
1643 Assert(
ctl->PagePrecedes(rhs / per_page, (lhs - 1 * per_page) / per_page)
1644 || (1U << 31) % per_page != 0);
1645 Assert(
ctl->PagePrecedes((lhs + 1 * per_page) / per_page, rhs / per_page)
1646 || (1U << 31) % per_page != 0);
1647 Assert(
ctl->PagePrecedes((lhs + 2 * per_page) / per_page, rhs / per_page));
1648 Assert(
ctl->PagePrecedes((lhs + 3 * per_page) / per_page, rhs / per_page));
1649 Assert(!
ctl->PagePrecedes(rhs / per_page, (lhs + per_page) / per_page));
1657 newestXact = newestPage * per_page + offset;
1658 Assert(newestXact / per_page == newestPage);
1659 oldestXact = newestXact + 1;
1660 oldestXact -= 1U << 31;
1661 oldestPage = oldestXact / per_page;
1673 newestXact = newestPage * per_page + offset;
1674 Assert(newestXact / per_page == newestPage);
1675 oldestXact = newestXact + 1;
1676 oldestXact -= 1U << 31;
1677 oldestPage = oldestXact / per_page;
1697 SlruPagePrecedesTestOffset(
ctl, per_page, 0);
1698 SlruPagePrecedesTestOffset(
ctl, per_page, per_page / 2);
1699 SlruPagePrecedesTestOffset(
ctl, per_page, per_page - 1);
1712 int64 cutoffPage = *(int64 *)
data;
1728 int64 cutoffPage = *(int64 *)
data;
1757 if (
ctl->long_segment_names)
1769 return (
len == 4 ||
len == 5 ||
len == 6);
1790 bool retval =
false;
1797 while ((clde =
ReadDir(cldir,
ctl->Dir)) != NULL)
1804 strspn(clde->
d_name,
"0123456789ABCDEF") ==
len)
1809 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 strtoi64(str, endptr, base)
#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,...)
struct dirent * ReadDir(DIR *dir, const char *dirname)
int CloseTransientFile(int fd)
void fsync_fname(const char *fname, bool isdir)
int data_sync_elevel(int elevel)
int OpenTransientFile(const char *fileName, int fileFlags)
DIR * AllocateDir(const char *dirname)
#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()
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
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)