63 #define SlruFileName(ctl, path, seg) \
64 snprintf(path, MAXPGPATH, "%s/%04X", (ctl)->Dir, seg)
72 #define MAX_WRITEALL_BUFFERS 16
88 #define INIT_SLRUFILETAG(a,xx_handler,xx_segno) \
90 memset(&(a), 0, sizeof(FileTag)), \
91 (a).handler = (xx_handler), \
92 (a).segno = (xx_segno) \
114 #define SlruRecentlyUsed(shared, slotno) \
116 int new_lru_count = (shared)->cur_lru_count; \
117 if (new_lru_count != (shared)->page_lru_count[slotno]) { \
118 (shared)->cur_lru_count = ++new_lru_count; \
119 (shared)->page_lru_count[slotno] = new_lru_count; \
148 int segpage,
void *
data);
162 sz +=
MAXALIGN(nslots *
sizeof(
char *));
164 sz +=
MAXALIGN(nslots *
sizeof(
bool));
165 sz +=
MAXALIGN(nslots *
sizeof(
int));
166 sz +=
MAXALIGN(nslots *
sizeof(
int));
189 LWLock *ctllock,
const char *subdir,
int tranche_id,
221 ptr = (
char *) shared;
224 offset +=
MAXALIGN(nslots *
sizeof(
char *));
228 offset +=
MAXALIGN(nslots *
sizeof(
bool));
230 offset +=
MAXALIGN(nslots *
sizeof(
int));
232 offset +=
MAXALIGN(nslots *
sizeof(
int));
245 for (slotno = 0; slotno < nslots; slotno++)
505 for (slotno = 0; slotno < shared->
num_slots; slotno++)
631 int offset = rpageno * BLCKSZ;
655 if ((
endpos = lseek(
fd, 0, SEEK_END)) < 0)
662 result =
endpos >= (off_t) (offset + BLCKSZ);
690 off_t offset = rpageno * BLCKSZ;
714 (
errmsg(
"file \"%s\" doesn't exist, reading as zeroes",
762 off_t offset = rpageno * BLCKSZ;
793 if (max_lsn < this_lsn)
936 int offset = rpageno * BLCKSZ;
946 errmsg(
"could not access status of transaction %u", xid),
947 errdetail(
"Could not open file \"%s\": %m.", path)));
952 errmsg(
"could not access status of transaction %u", xid),
953 errdetail(
"Could not seek in file \"%s\" to offset %d: %m.",
960 errmsg(
"could not access status of transaction %u", xid),
961 errdetail(
"Could not read from file \"%s\" at offset %d: %m.",
965 (
errmsg(
"could not access status of transaction %u", xid),
966 errdetail(
"Could not read from file \"%s\" at offset %d: read too few bytes.", path, offset)));
972 errmsg(
"could not access status of transaction %u", xid),
973 errdetail(
"Could not write to file \"%s\" at offset %d: %m.",
977 (
errmsg(
"could not access status of transaction %u", xid),
978 errdetail(
"Could not write to file \"%s\" at offset %d: wrote too few bytes.",
984 errmsg(
"could not access status of transaction %u", xid),
985 errdetail(
"Could not fsync file \"%s\": %m.",
991 errmsg(
"could not access status of transaction %u", xid),
992 errdetail(
"Could not close file \"%s\": %m.",
997 elog(
ERROR,
"unrecognized SimpleLru error cause: %d",
1026 int bestvalidslot = 0;
1027 int best_valid_delta = -1;
1028 int best_valid_page_number = 0;
1029 int bestinvalidslot = 0;
1030 int best_invalid_delta = -1;
1031 int best_invalid_page_number = 0;
1034 for (slotno = 0; slotno < shared->
num_slots; slotno++)
1069 for (slotno = 0; slotno < shared->
num_slots; slotno++)
1072 int this_page_number;
1094 if (this_delta > best_valid_delta ||
1095 (this_delta == best_valid_delta &&
1097 best_valid_page_number)))
1099 bestvalidslot = slotno;
1100 best_valid_delta = this_delta;
1101 best_valid_page_number = this_page_number;
1106 if (this_delta > best_invalid_delta ||
1107 (this_delta == best_invalid_delta &&
1109 best_invalid_page_number)))
1111 bestinvalidslot = slotno;
1112 best_invalid_delta = this_delta;
1113 best_invalid_page_number = this_page_number;
1125 if (best_valid_delta < 0)
1135 return bestvalidslot;
1176 for (slotno = 0; slotno < shared->
num_slots; slotno++)
1185 Assert(allow_redirtied ||
1253 (
errmsg(
"could not truncate directory \"%s\": apparent wraparound",
1258 for (slotno = 0; slotno < shared->
num_slots; slotno++)
1338 for (slotno = 0; slotno < shared->
num_slots; slotno++)
1346 if (pagesegno !=
segno)
1402 #ifdef USE_ASSERT_CHECKING
1404 SlruPagePrecedesTestOffset(
SlruCtl ctl,
int per_page,
uint32 offset)
1419 lhs = per_page + offset;
1420 rhs = lhs + (1U << 31);
1436 || (1U << 31) % per_page != 0);
1438 || (1U << 31) % per_page != 0);
1449 newestXact = newestPage * per_page + offset;
1450 Assert(newestXact / per_page == newestPage);
1451 oldestXact = newestXact + 1;
1452 oldestXact -= 1U << 31;
1453 oldestPage = oldestXact / per_page;
1465 newestXact = newestPage * per_page + offset;
1466 Assert(newestXact / per_page == newestPage);
1467 oldestXact = newestXact + 1;
1468 oldestXact -= 1U << 31;
1469 oldestPage = oldestXact / per_page;
1489 SlruPagePrecedesTestOffset(ctl, per_page, 0);
1490 SlruPagePrecedesTestOffset(ctl, per_page, per_page / 2);
1491 SlruPagePrecedesTestOffset(ctl, per_page, per_page - 1);
1503 int cutoffPage = *(
int *)
data;
1518 int cutoffPage = *(
int *)
data;
1556 bool retval =
false;
1563 while ((clde =
ReadDir(cldir, ctl->
Dir)) != NULL)
1569 if ((
len == 4 ||
len == 5 ||
len == 6) &&
1570 strspn(clde->
d_name,
"0123456789ABCDEF") ==
len)
1572 segno = (int) strtol(clde->
d_name, NULL, 16);
1575 elog(
DEBUG2,
"SlruScanDirectory invoking callback on %s/%s",
#define MemSet(start, val, len)
elog(ERROR, "%s: %s", p2, msg)
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)
Assert(fmt[strlen(fmt) - 1] !='\n')
bool LWLockAcquire(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)
#define SlruFileName(ctl, path, seg)
static bool SlruPhysicalReadPage(SlruCtl ctl, int pageno, int slotno)
#define INIT_SLRUFILETAG(a, xx_handler, xx_segno)
void SimpleLruWritePage(SlruCtl ctl, int slotno)
void SimpleLruWriteAll(SlruCtl ctl, bool allow_redirtied)
bool SlruScanDirCbReportPresence(SlruCtl ctl, char *filename, int segpage, void *data)
#define SlruRecentlyUsed(shared, slotno)
static void SlruInternalDeleteSegment(SlruCtl ctl, int segno)
struct SlruWriteAllData SlruWriteAllData
static void SimpleLruZeroLSNs(SlruCtl ctl, int slotno)
static SlruErrorCause slru_errcause
static bool SlruPhysicalWritePage(SlruCtl ctl, int pageno, int slotno, SlruWriteAll fdata)
bool SlruScanDirCbDeleteAll(SlruCtl ctl, char *filename, int segpage, void *data)
#define MAX_WRITEALL_BUFFERS
static void SlruReportIOError(SlruCtl ctl, int pageno, TransactionId xid)
void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns, LWLock *ctllock, const char *subdir, int tranche_id, SyncRequestHandler sync_handler)
static void SimpleLruWaitIO(SlruCtl ctl, int slotno)
void SimpleLruTruncate(SlruCtl ctl, int cutoffPage)
static void SlruInternalWritePage(SlruCtl ctl, int slotno, SlruWriteAll fdata)
bool SlruScanDirectory(SlruCtl ctl, SlruScanCallback callback, void *data)
static bool SlruScanDirCbDeleteCutoff(SlruCtl ctl, char *filename, int segpage, void *data)
int SlruSyncFileTag(SlruCtl ctl, const FileTag *ftag, char *path)
int SimpleLruZeroPage(SlruCtl ctl, int pageno)
void SlruDeleteSegment(SlruCtl ctl, int segno)
int SimpleLruReadPage_ReadOnly(SlruCtl ctl, int pageno, TransactionId xid)
struct SlruWriteAllData * SlruWriteAll
static int SlruSelectLRUPage(SlruCtl ctl, int pageno)
bool SimpleLruDoesPhysicalPageExist(SlruCtl ctl, int pageno)
int SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok, TransactionId xid)
Size SimpleLruShmemSize(int nslots, int nlsns)
static bool SlruMayDeleteSegment(SlruCtl ctl, int segpage, int cutoffPage)
SlruSharedData * SlruShared
#define SlruPagePrecedesUnitTests(ctl, per_page)
bool(* SlruScanCallback)(SlruCtl ctl, char *filename, int segpage, void *data)
#define SLRU_PAGES_PER_SEGMENT
@ SLRU_PAGE_WRITE_IN_PROGRESS
@ SLRU_PAGE_READ_IN_PROGRESS
SyncRequestHandler sync_handler
bool(* PagePrecedes)(int, int)
SlruPageStatus * page_status
LWLockPadded * buffer_locks
int fd[MAX_WRITEALL_BUFFERS]
int 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)