78 if (
ctl->long_segment_names)
87 Assert(segno >= 0 && segno <= INT64CONST(0xFFFFFFFFFFFFFFF));
97 Assert(segno >= 0 && segno <= INT64CONST(0xFFFFFF));
99 (
unsigned int) segno);
109 #define MAX_WRITEALL_BUFFERS 16
128 #define SLRU_BANK_BITSHIFT 4
129 #define SLRU_BANK_SIZE (1 << SLRU_BANK_BITSHIFT)
134 #define SlotGetBankNumber(slotno) ((slotno) >> SLRU_BANK_BITSHIFT)
142 #define INIT_SLRUFILETAG(a,xx_handler,xx_segno) \
144 memset(&(a), 0, sizeof(FileTag)), \
145 (a).handler = (xx_handler), \
146 (a).segno = (xx_segno) \
174 int64 segpage,
void *
data);
194 sz +=
MAXALIGN(nslots *
sizeof(
char *));
196 sz +=
MAXALIGN(nslots *
sizeof(
bool));
197 sz +=
MAXALIGN(nslots *
sizeof(int64));
198 sz +=
MAXALIGN(nslots *
sizeof(
int));
201 sz +=
MAXALIGN(nbanks *
sizeof(
int));
239 const char *subdir,
int buffer_tranche_id,
int bank_tranche_id,
269 ptr = (
char *) shared;
272 offset +=
MAXALIGN(nslots *
sizeof(
char *));
276 offset +=
MAXALIGN(nslots *
sizeof(
bool));
278 offset +=
MAXALIGN(nslots *
sizeof(int64));
280 offset +=
MAXALIGN(nslots *
sizeof(
int));
288 offset +=
MAXALIGN(nbanks *
sizeof(
int));
297 for (
int slotno = 0; slotno < nslots; slotno++)
310 for (
int bankno = 0; bankno < nbanks; bankno++)
329 ctl->shared = shared;
330 ctl->sync_handler = sync_handler;
331 ctl->long_segment_names = long_segment_names;
595 int bankno = pageno &
ctl->bank_mask;
603 for (
int slotno = bankstart; slotno < bankend; slotno++)
733 int offset = rpageno * BLCKSZ;
757 if ((
endpos = lseek(
fd, 0, SEEK_END)) < 0)
764 result =
endpos >= (off_t) (offset + BLCKSZ);
792 off_t offset = rpageno * BLCKSZ;
816 (
errmsg(
"file \"%s\" doesn't exist, reading as zeroes",
864 off_t offset = rpageno * BLCKSZ;
894 if (max_lsn < this_lsn)
1035 int offset = rpageno * BLCKSZ;
1045 errmsg(
"could not access status of transaction %u", xid),
1046 errdetail(
"Could not open file \"%s\": %m.", path)));
1051 errmsg(
"could not access status of transaction %u", xid),
1052 errdetail(
"Could not seek in file \"%s\" to offset %d: %m.",
1059 errmsg(
"could not access status of transaction %u", xid),
1060 errdetail(
"Could not read from file \"%s\" at offset %d: %m.",
1064 (
errmsg(
"could not access status of transaction %u", xid),
1065 errdetail(
"Could not read from file \"%s\" at offset %d: read too few bytes.", path, offset)));
1071 errmsg(
"could not access status of transaction %u", xid),
1072 errdetail(
"Could not write to file \"%s\" at offset %d: %m.",
1076 (
errmsg(
"could not access status of transaction %u", xid),
1077 errdetail(
"Could not write to file \"%s\" at offset %d: wrote too few bytes.",
1083 errmsg(
"could not access status of transaction %u", xid),
1084 errdetail(
"Could not fsync file \"%s\": %m.",
1090 errmsg(
"could not access status of transaction %u", xid),
1091 errdetail(
"Could not close file \"%s\": %m.",
1096 elog(
ERROR,
"unrecognized SimpleLru error cause: %d",
1160 int bestvalidslot = 0;
1161 int best_valid_delta = -1;
1162 int64 best_valid_page_number = 0;
1163 int bestinvalidslot = 0;
1164 int best_invalid_delta = -1;
1165 int64 best_invalid_page_number = 0;
1166 int bankno = pageno &
ctl->bank_mask;
1173 for (
int slotno = 0; slotno < shared->
num_slots; slotno++)
1208 for (
int slotno = bankstart; slotno < bankend; slotno++)
1211 int64 this_page_number;
1236 if (this_page_number ==
1242 if (this_delta > best_valid_delta ||
1243 (this_delta == best_valid_delta &&
1244 ctl->PagePrecedes(this_page_number,
1245 best_valid_page_number)))
1247 bestvalidslot = slotno;
1248 best_valid_delta = this_delta;
1249 best_valid_page_number = this_page_number;
1254 if (this_delta > best_invalid_delta ||
1255 (this_delta == best_invalid_delta &&
1256 ctl->PagePrecedes(this_page_number,
1257 best_invalid_page_number)))
1259 bestinvalidslot = slotno;
1260 best_invalid_delta = this_delta;
1261 best_invalid_page_number = this_page_number;
1273 if (best_valid_delta < 0)
1283 return bestvalidslot;
1323 for (
int slotno = 0; slotno < shared->
num_slots; slotno++)
1331 if (curbank != prevbank)
1349 Assert(allow_redirtied ||
1417 (
errmsg(
"could not truncate directory \"%s\": apparent wraparound",
1424 for (
int slotno = 0; slotno < shared->
num_slots; slotno++)
1432 if (curbank != prevbank)
1519 for (
int slotno = 0; slotno < shared->
num_slots; slotno++)
1528 if (curbank != prevbank)
1540 if (pagesegno !=
segno)
1592 return (
ctl->PagePrecedes(segpage, cutoffPage) &&
1593 ctl->PagePrecedes(seg_last_page, cutoffPage));
1596 #ifdef USE_ASSERT_CHECKING
1613 lhs = per_page + offset;
1614 rhs = lhs + (1U << 31);
1623 Assert(!
ctl->PagePrecedes(lhs / per_page, lhs / per_page));
1624 Assert(!
ctl->PagePrecedes(lhs / per_page, rhs / per_page));
1625 Assert(!
ctl->PagePrecedes(rhs / per_page, lhs / per_page));
1626 Assert(!
ctl->PagePrecedes((lhs - per_page) / per_page, rhs / per_page));
1627 Assert(
ctl->PagePrecedes(rhs / per_page, (lhs - 3 * per_page) / per_page));
1628 Assert(
ctl->PagePrecedes(rhs / per_page, (lhs - 2 * per_page) / per_page));
1629 Assert(
ctl->PagePrecedes(rhs / per_page, (lhs - 1 * per_page) / per_page)
1630 || (1U << 31) % per_page != 0);
1631 Assert(
ctl->PagePrecedes((lhs + 1 * per_page) / per_page, rhs / per_page)
1632 || (1U << 31) % per_page != 0);
1633 Assert(
ctl->PagePrecedes((lhs + 2 * per_page) / per_page, rhs / per_page));
1634 Assert(
ctl->PagePrecedes((lhs + 3 * per_page) / per_page, rhs / per_page));
1635 Assert(!
ctl->PagePrecedes(rhs / per_page, (lhs + per_page) / per_page));
1643 newestXact = newestPage * per_page + offset;
1644 Assert(newestXact / per_page == newestPage);
1645 oldestXact = newestXact + 1;
1646 oldestXact -= 1U << 31;
1647 oldestPage = oldestXact / 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;
1683 SlruPagePrecedesTestOffset(
ctl, per_page, 0);
1684 SlruPagePrecedesTestOffset(
ctl, per_page, per_page / 2);
1685 SlruPagePrecedesTestOffset(
ctl, per_page, per_page - 1);
1698 int64 cutoffPage = *(int64 *)
data;
1714 int64 cutoffPage = *(int64 *)
data;
1743 if (
ctl->long_segment_names)
1755 return (
len == 4 ||
len == 5 ||
len == 6);
1776 bool retval =
false;
1783 while ((clde =
ReadDir(cldir,
ctl->Dir)) != NULL)
1790 strspn(clde->
d_name,
"0123456789ABCDEF") ==
len)
1795 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)