PostgreSQL Source Code  git master
slru.h File Reference
#include "access/xlogdefs.h"
#include "storage/lwlock.h"
Include dependency graph for slru.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  SlruSharedData
 
struct  SlruCtlData
 

Macros

#define SLRU_PAGES_PER_SEGMENT   32
 

Typedefs

typedef struct SlruSharedData SlruSharedData
 
typedef SlruSharedDataSlruShared
 
typedef struct SlruCtlData SlruCtlData
 
typedef SlruCtlDataSlruCtl
 
typedef bool(* SlruScanCallback) (SlruCtl ctl, char *filename, int segpage, void *data)
 

Enumerations

enum  SlruPageStatus { SLRU_PAGE_EMPTY, SLRU_PAGE_READ_IN_PROGRESS, SLRU_PAGE_VALID, SLRU_PAGE_WRITE_IN_PROGRESS }
 

Functions

Size SimpleLruShmemSize (int nslots, int nlsns)
 
void SimpleLruInit (SlruCtl ctl, const char *name, int nslots, int nlsns, LWLock *ctllock, const char *subdir, int tranche_id)
 
int SimpleLruZeroPage (SlruCtl ctl, int pageno)
 
int SimpleLruReadPage (SlruCtl ctl, int pageno, bool write_ok, TransactionId xid)
 
int SimpleLruReadPage_ReadOnly (SlruCtl ctl, int pageno, TransactionId xid)
 
void SimpleLruWritePage (SlruCtl ctl, int slotno)
 
void SimpleLruFlush (SlruCtl ctl, bool allow_redirtied)
 
void SimpleLruTruncate (SlruCtl ctl, int cutoffPage)
 
bool SimpleLruDoesPhysicalPageExist (SlruCtl ctl, int pageno)
 
bool SlruScanDirectory (SlruCtl ctl, SlruScanCallback callback, void *data)
 
void SlruDeleteSegment (SlruCtl ctl, int segno)
 
bool SlruScanDirCbReportPresence (SlruCtl ctl, char *filename, int segpage, void *data)
 
bool SlruScanDirCbDeleteAll (SlruCtl ctl, char *filename, int segpage, void *data)
 

Macro Definition Documentation

◆ SLRU_PAGES_PER_SEGMENT

Typedef Documentation

◆ SlruCtl

typedef SlruCtlData* SlruCtl

Definition at line 133 of file slru.h.

◆ SlruCtlData

typedef struct SlruCtlData SlruCtlData

◆ SlruScanCallback

typedef bool(* SlruScanCallback) (SlruCtl ctl, char *filename, int segpage, void *data)

Definition at line 149 of file slru.h.

◆ SlruShared

Definition at line 103 of file slru.h.

◆ SlruSharedData

Enumeration Type Documentation

◆ SlruPageStatus

Enumerator
SLRU_PAGE_EMPTY 
SLRU_PAGE_READ_IN_PROGRESS 
SLRU_PAGE_VALID 
SLRU_PAGE_WRITE_IN_PROGRESS 

Definition at line 41 of file slru.h.

42 {
43  SLRU_PAGE_EMPTY, /* buffer is not in use */
44  SLRU_PAGE_READ_IN_PROGRESS, /* page is being read in */
45  SLRU_PAGE_VALID, /* page is valid and not being written */
46  SLRU_PAGE_WRITE_IN_PROGRESS /* page is being written out */
SlruPageStatus
Definition: slru.h:41

Function Documentation

◆ SimpleLruDoesPhysicalPageExist()

bool SimpleLruDoesPhysicalPageExist ( SlruCtl  ctl,
int  pageno 
)

Definition at line 609 of file slru.c.

References CloseTransientFile(), endpos, SlruFlushData::fd, MAXPGPATH, OpenTransientFile(), PG_BINARY, pgstat_count_slru_page_exists(), SlruFlushData::segno, SlruCtlData::shared, SLRU_CLOSE_FAILED, slru_errcause, slru_errno, SLRU_OPEN_FAILED, SLRU_PAGES_PER_SEGMENT, SLRU_SEEK_FAILED, SlruSharedData::slru_stats_idx, SlruFileName, and SlruReportIOError().

Referenced by ActivateCommitTs(), find_multixact_start(), and MaybeExtendOffsetSlru().

610 {
611  int segno = pageno / SLRU_PAGES_PER_SEGMENT;
612  int rpageno = pageno % SLRU_PAGES_PER_SEGMENT;
613  int offset = rpageno * BLCKSZ;
614  char path[MAXPGPATH];
615  int fd;
616  bool result;
617  off_t endpos;
618 
619  /* update the stats counter of checked pages */
621 
622  SlruFileName(ctl, path, segno);
623 
624  fd = OpenTransientFile(path, O_RDONLY | PG_BINARY);
625  if (fd < 0)
626  {
627  /* expected: file doesn't exist */
628  if (errno == ENOENT)
629  return false;
630 
631  /* report error normally */
633  slru_errno = errno;
634  SlruReportIOError(ctl, pageno, 0);
635  }
636 
637  if ((endpos = lseek(fd, 0, SEEK_END)) < 0)
638  {
640  slru_errno = errno;
641  SlruReportIOError(ctl, pageno, 0);
642  }
643 
644  result = endpos >= (off_t) (offset + BLCKSZ);
645 
646  if (CloseTransientFile(fd) != 0)
647  {
649  slru_errno = errno;
650  return false;
651  }
652 
653  return result;
654 }
static SlruErrorCause slru_errcause
Definition: slru.c:122
static int fd(const char *x, int i)
Definition: preproc-init.c:105
static void SlruReportIOError(SlruCtl ctl, int pageno, TransactionId xid)
Definition: slru.c:923
#define PG_BINARY
Definition: c.h:1234
int OpenTransientFile(const char *fileName, int fileFlags)
Definition: fd.c:2370
#define MAXPGPATH
static XLogRecPtr endpos
Definition: pg_receivewal.c:46
int CloseTransientFile(int fd)
Definition: fd.c:2547
void pgstat_count_slru_page_exists(int slru_idx)
Definition: pgstat.c:6755
#define SlruFileName(ctl, path, seg)
Definition: slru.c:62
int slru_stats_idx
Definition: slru.h:100
static int slru_errno
Definition: slru.c:123
SlruShared shared
Definition: slru.h:111
#define SLRU_PAGES_PER_SEGMENT
Definition: slru.h:33

◆ SimpleLruFlush()

void SimpleLruFlush ( SlruCtl  ctl,
bool  allow_redirtied 
)

Definition at line 1145 of file slru.c.

References Assert, CloseTransientFile(), SlruSharedData::ControlLock, SlruCtlData::do_fsync, SlruFlushData::fd, i, InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), SlruFlushData::num_files, SlruSharedData::num_slots, SlruSharedData::page_dirty, SlruSharedData::page_status, pg_fsync(), pgstat_count_slru_flush(), pgstat_report_wait_end(), pgstat_report_wait_start(), SlruFlushData::segno, SlruCtlData::shared, SLRU_CLOSE_FAILED, slru_errcause, slru_errno, SLRU_FSYNC_FAILED, SLRU_PAGE_EMPTY, SLRU_PAGE_VALID, SLRU_PAGES_PER_SEGMENT, SlruSharedData::slru_stats_idx, SlruInternalWritePage(), SlruReportIOError(), and WAIT_EVENT_SLRU_FLUSH_SYNC.

Referenced by CheckPointCLOG(), CheckPointCommitTs(), CheckPointMultiXact(), CheckPointPredicate(), CheckPointSUBTRANS(), find_multixact_start(), ShutdownCLOG(), ShutdownCommitTs(), ShutdownMultiXact(), and ShutdownSUBTRANS().

1146 {
1147  SlruShared shared = ctl->shared;
1148  SlruFlushData fdata;
1149  int slotno;
1150  int pageno = 0;
1151  int i;
1152  bool ok;
1153 
1154  /* update the stats counter of flushes */
1156 
1157  /*
1158  * Find and write dirty pages
1159  */
1160  fdata.num_files = 0;
1161 
1163 
1164  for (slotno = 0; slotno < shared->num_slots; slotno++)
1165  {
1166  SlruInternalWritePage(ctl, slotno, &fdata);
1167 
1168  /*
1169  * In some places (e.g. checkpoints), we cannot assert that the slot
1170  * is clean now, since another process might have re-dirtied it
1171  * already. That's okay.
1172  */
1173  Assert(allow_redirtied ||
1174  shared->page_status[slotno] == SLRU_PAGE_EMPTY ||
1175  (shared->page_status[slotno] == SLRU_PAGE_VALID &&
1176  !shared->page_dirty[slotno]));
1177  }
1178 
1179  LWLockRelease(shared->ControlLock);
1180 
1181  /*
1182  * Now fsync and close any files that were open
1183  */
1184  ok = true;
1185  for (i = 0; i < fdata.num_files; i++)
1186  {
1188  if (ctl->do_fsync && pg_fsync(fdata.fd[i]) != 0)
1189  {
1191  slru_errno = errno;
1192  pageno = fdata.segno[i] * SLRU_PAGES_PER_SEGMENT;
1193  ok = false;
1194  }
1196 
1197  if (CloseTransientFile(fdata.fd[i]) != 0)
1198  {
1200  slru_errno = errno;
1201  pageno = fdata.segno[i] * SLRU_PAGES_PER_SEGMENT;
1202  ok = false;
1203  }
1204  }
1205  if (!ok)
1207 }
LWLock * ControlLock
Definition: slru.h:54
static void SlruInternalWritePage(SlruCtl ctl, int slotno, SlruFlush fdata)
Definition: slru.c:526
static SlruErrorCause slru_errcause
Definition: slru.c:122
int segno[MAX_FLUSH_BUFFERS]
Definition: slru.c:78
void pgstat_count_slru_flush(int slru_idx)
Definition: pgstat.c:6773
static void SlruReportIOError(SlruCtl ctl, int pageno, TransactionId xid)
Definition: slru.c:923
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
SlruPageStatus * page_status
Definition: slru.h:64
#define InvalidTransactionId
Definition: transam.h:31
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1380
bool do_fsync
Definition: slru.h:117
int CloseTransientFile(int fd)
Definition: fd.c:2547
int num_files
Definition: slru.c:76
#define Assert(condition)
Definition: c.h:738
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1356
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
int slru_stats_idx
Definition: slru.h:100
int num_slots
Definition: slru.h:57
static int slru_errno
Definition: slru.c:123
bool * page_dirty
Definition: slru.h:65
int i
SlruShared shared
Definition: slru.h:111
int pg_fsync(int fd)
Definition: fd.c:343
#define SLRU_PAGES_PER_SEGMENT
Definition: slru.h:33
int fd[MAX_FLUSH_BUFFERS]
Definition: slru.c:77

◆ SimpleLruInit()

void SimpleLruInit ( SlruCtl  ctl,
const char *  name,
int  nslots,
int  nlsns,
LWLock ctllock,
const char *  subdir,
int  tranche_id 
)

Definition at line 175 of file slru.c.

References Assert, SlruSharedData::buffer_locks, BUFFERALIGN, SlruSharedData::ControlLock, SlruSharedData::cur_lru_count, SlruCtlData::Dir, SlruCtlData::do_fsync, SlruSharedData::group_lsn, IsUnderPostmaster, LWLockPadded::lock, SlruSharedData::lsn_groups_per_page, LWLockInitialize(), MAXALIGN, SlruSharedData::num_slots, SlruSharedData::page_buffer, SlruSharedData::page_dirty, SlruSharedData::page_lru_count, SlruSharedData::page_number, SlruSharedData::page_status, pgstat_slru_index(), SlruCtlData::shared, ShmemInitStruct(), SimpleLruShmemSize(), SLRU_PAGE_EMPTY, SlruSharedData::slru_stats_idx, and StrNCpy.

Referenced by AsyncShmemInit(), CLOGShmemInit(), CommitTsShmemInit(), MultiXactShmemInit(), SerialInit(), and SUBTRANSShmemInit().

177 {
178  SlruShared shared;
179  bool found;
180 
181  shared = (SlruShared) ShmemInitStruct(name,
182  SimpleLruShmemSize(nslots, nlsns),
183  &found);
184 
185  if (!IsUnderPostmaster)
186  {
187  /* Initialize locks and shared memory area */
188  char *ptr;
189  Size offset;
190  int slotno;
191 
192  Assert(!found);
193 
194  memset(shared, 0, sizeof(SlruSharedData));
195 
196  shared->ControlLock = ctllock;
197 
198  shared->num_slots = nslots;
199  shared->lsn_groups_per_page = nlsns;
200 
201  shared->cur_lru_count = 0;
202 
203  /* shared->latest_page_number will be set later */
204 
206 
207  ptr = (char *) shared;
208  offset = MAXALIGN(sizeof(SlruSharedData));
209  shared->page_buffer = (char **) (ptr + offset);
210  offset += MAXALIGN(nslots * sizeof(char *));
211  shared->page_status = (SlruPageStatus *) (ptr + offset);
212  offset += MAXALIGN(nslots * sizeof(SlruPageStatus));
213  shared->page_dirty = (bool *) (ptr + offset);
214  offset += MAXALIGN(nslots * sizeof(bool));
215  shared->page_number = (int *) (ptr + offset);
216  offset += MAXALIGN(nslots * sizeof(int));
217  shared->page_lru_count = (int *) (ptr + offset);
218  offset += MAXALIGN(nslots * sizeof(int));
219 
220  /* Initialize LWLocks */
221  shared->buffer_locks = (LWLockPadded *) (ptr + offset);
222  offset += MAXALIGN(nslots * sizeof(LWLockPadded));
223 
224  if (nlsns > 0)
225  {
226  shared->group_lsn = (XLogRecPtr *) (ptr + offset);
227  offset += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr));
228  }
229 
230  ptr += BUFFERALIGN(offset);
231  for (slotno = 0; slotno < nslots; slotno++)
232  {
233  LWLockInitialize(&shared->buffer_locks[slotno].lock,
234  tranche_id);
235 
236  shared->page_buffer[slotno] = ptr;
237  shared->page_status[slotno] = SLRU_PAGE_EMPTY;
238  shared->page_dirty[slotno] = false;
239  shared->page_lru_count[slotno] = 0;
240  ptr += BLCKSZ;
241  }
242 
243  /* Should fit to estimated shmem size */
244  Assert(ptr - (char *) shared <= SimpleLruShmemSize(nslots, nlsns));
245  }
246  else
247  Assert(found);
248 
249  /*
250  * Initialize the unshared control struct, including directory path. We
251  * assume caller set PagePrecedes.
252  */
253  ctl->shared = shared;
254  ctl->do_fsync = true; /* default behavior */
255  StrNCpy(ctl->Dir, subdir, sizeof(ctl->Dir));
256 }
LWLock * ControlLock
Definition: slru.h:54
int * page_number
Definition: slru.h:66
SlruPageStatus
Definition: slru.h:41
char ** page_buffer
Definition: slru.h:63
int cur_lru_count
Definition: slru.h:90
int lsn_groups_per_page
Definition: slru.h:79
Size SimpleLruShmemSize(int nslots, int nlsns)
Definition: slru.c:144
int pgstat_slru_index(const char *name)
Definition: pgstat.c:6688
SlruPageStatus * page_status
Definition: slru.h:64
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:392
bool IsUnderPostmaster
Definition: globals.c:109
LWLockPadded * buffer_locks
Definition: slru.h:68
XLogRecPtr * group_lsn
Definition: slru.h:78
bool do_fsync
Definition: slru.h:117
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition: lwlock.c:745
SlruSharedData * SlruShared
Definition: slru.h:103
char Dir[64]
Definition: slru.h:130
LWLock lock
Definition: lwlock.h:79
int * page_lru_count
Definition: slru.h:67
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:738
#define StrNCpy(dst, src, len)
Definition: c.h:944
size_t Size
Definition: c.h:466
#define MAXALIGN(LEN)
Definition: c.h:691
int slru_stats_idx
Definition: slru.h:100
int num_slots
Definition: slru.h:57
const char * name
Definition: encode.c:555
bool * page_dirty
Definition: slru.h:65
SlruShared shared
Definition: slru.h:111
#define BUFFERALIGN(LEN)
Definition: c.h:693

◆ SimpleLruReadPage()

int SimpleLruReadPage ( SlruCtl  ctl,
int  pageno,
bool  write_ok,
TransactionId  xid 
)

Definition at line 382 of file slru.c.

References Assert, SlruSharedData::buffer_locks, SlruSharedData::ControlLock, LWLockPadded::lock, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), SlruSharedData::page_dirty, SlruSharedData::page_number, SlruSharedData::page_status, pgstat_count_slru_page_hit(), pgstat_count_slru_page_read(), SlruCtlData::shared, SimpleLruWaitIO(), SimpleLruZeroLSNs(), SLRU_PAGE_EMPTY, SLRU_PAGE_READ_IN_PROGRESS, SLRU_PAGE_VALID, SLRU_PAGE_WRITE_IN_PROGRESS, SlruSharedData::slru_stats_idx, SlruPhysicalReadPage(), SlruRecentlyUsed, SlruReportIOError(), and SlruSelectLRUPage().

Referenced by asyncQueueAddEntries(), GetMultiXactIdMembers(), RecordNewMultiXact(), SerialAdd(), SetXidCommitTsInPage(), SimpleLruReadPage_ReadOnly(), SubTransSetParent(), TransactionIdSetPageStatusInternal(), TrimCLOG(), and TrimMultiXact().

384 {
385  SlruShared shared = ctl->shared;
386 
387  /* Outer loop handles restart if we must wait for someone else's I/O */
388  for (;;)
389  {
390  int slotno;
391  bool ok;
392 
393  /* See if page already is in memory; if not, pick victim slot */
394  slotno = SlruSelectLRUPage(ctl, pageno);
395 
396  /* Did we find the page in memory? */
397  if (shared->page_number[slotno] == pageno &&
398  shared->page_status[slotno] != SLRU_PAGE_EMPTY)
399  {
400  /*
401  * If page is still being read in, we must wait for I/O. Likewise
402  * if the page is being written and the caller said that's not OK.
403  */
404  if (shared->page_status[slotno] == SLRU_PAGE_READ_IN_PROGRESS ||
405  (shared->page_status[slotno] == SLRU_PAGE_WRITE_IN_PROGRESS &&
406  !write_ok))
407  {
408  SimpleLruWaitIO(ctl, slotno);
409  /* Now we must recheck state from the top */
410  continue;
411  }
412  /* Otherwise, it's ready to use */
413  SlruRecentlyUsed(shared, slotno);
414 
415  /* update the stats counter of pages found in the SLRU */
417 
418  return slotno;
419  }
420 
421  /* We found no match; assert we selected a freeable slot */
422  Assert(shared->page_status[slotno] == SLRU_PAGE_EMPTY ||
423  (shared->page_status[slotno] == SLRU_PAGE_VALID &&
424  !shared->page_dirty[slotno]));
425 
426  /* Mark the slot read-busy */
427  shared->page_number[slotno] = pageno;
428  shared->page_status[slotno] = SLRU_PAGE_READ_IN_PROGRESS;
429  shared->page_dirty[slotno] = false;
430 
431  /* Acquire per-buffer lock (cannot deadlock, see notes at top) */
432  LWLockAcquire(&shared->buffer_locks[slotno].lock, LW_EXCLUSIVE);
433 
434  /* Release control lock while doing I/O */
435  LWLockRelease(shared->ControlLock);
436 
437  /* Do the read */
438  ok = SlruPhysicalReadPage(ctl, pageno, slotno);
439 
440  /* Set the LSNs for this newly read-in page to zero */
441  SimpleLruZeroLSNs(ctl, slotno);
442 
443  /* Re-acquire control lock and update page state */
445 
446  Assert(shared->page_number[slotno] == pageno &&
447  shared->page_status[slotno] == SLRU_PAGE_READ_IN_PROGRESS &&
448  !shared->page_dirty[slotno]);
449 
450  shared->page_status[slotno] = ok ? SLRU_PAGE_VALID : SLRU_PAGE_EMPTY;
451 
452  LWLockRelease(&shared->buffer_locks[slotno].lock);
453 
454  /* Now it's okay to ereport if we failed */
455  if (!ok)
456  SlruReportIOError(ctl, pageno, xid);
457 
458  SlruRecentlyUsed(shared, slotno);
459 
460  /* update the stats counter of pages not found in SLRU */
462 
463  return slotno;
464  }
465 }
LWLock * ControlLock
Definition: slru.h:54
int * page_number
Definition: slru.h:66
static void SimpleLruZeroLSNs(SlruCtl ctl, int slotno)
Definition: slru.c:311
static void SlruReportIOError(SlruCtl ctl, int pageno, TransactionId xid)
Definition: slru.c:923
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
SlruPageStatus * page_status
Definition: slru.h:64
LWLockPadded * buffer_locks
Definition: slru.h:68
void pgstat_count_slru_page_read(int slru_idx)
Definition: pgstat.c:6761
static void SimpleLruWaitIO(SlruCtl ctl, int slotno)
Definition: slru.c:328
LWLock lock
Definition: lwlock.h:79
static bool SlruPhysicalReadPage(SlruCtl ctl, int pageno, int slotno)
Definition: slru.c:667
#define Assert(condition)
Definition: c.h:738
void pgstat_count_slru_page_hit(int slru_idx)
Definition: pgstat.c:6749
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
int slru_stats_idx
Definition: slru.h:100
static int SlruSelectLRUPage(SlruCtl ctl, int pageno)
Definition: slru.c:1008
bool * page_dirty
Definition: slru.h:65
SlruShared shared
Definition: slru.h:111
#define SlruRecentlyUsed(shared, slotno)
Definition: slru.c:102

◆ SimpleLruReadPage_ReadOnly()

int SimpleLruReadPage_ReadOnly ( SlruCtl  ctl,
int  pageno,
TransactionId  xid 
)

Definition at line 482 of file slru.c.

References SlruSharedData::ControlLock, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), SlruSharedData::num_slots, SlruSharedData::page_number, SlruSharedData::page_status, pgstat_count_slru_page_hit(), SlruCtlData::shared, SimpleLruReadPage(), SLRU_PAGE_EMPTY, SLRU_PAGE_READ_IN_PROGRESS, SlruSharedData::slru_stats_idx, and SlruRecentlyUsed.

Referenced by asyncQueueReadAllNotifications(), find_multixact_start(), SerialGetMinConflictCommitSeqNo(), SubTransGetParent(), TransactionIdGetCommitTsData(), and TransactionIdGetStatus().

483 {
484  SlruShared shared = ctl->shared;
485  int slotno;
486 
487  /* Try to find the page while holding only shared lock */
489 
490  /* See if page is already in a buffer */
491  for (slotno = 0; slotno < shared->num_slots; slotno++)
492  {
493  if (shared->page_number[slotno] == pageno &&
494  shared->page_status[slotno] != SLRU_PAGE_EMPTY &&
495  shared->page_status[slotno] != SLRU_PAGE_READ_IN_PROGRESS)
496  {
497  /* See comments for SlruRecentlyUsed macro */
498  SlruRecentlyUsed(shared, slotno);
499 
500  /* update the stats counter of pages found in the SLRU */
502 
503  return slotno;
504  }
505  }
506 
507  /* No luck, so switch to normal exclusive lock and do regular read */
508  LWLockRelease(shared->ControlLock);
510 
511  return SimpleLruReadPage(ctl, pageno, true, xid);
512 }
LWLock * ControlLock
Definition: slru.h:54
int * page_number
Definition: slru.h:66
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
SlruPageStatus * page_status
Definition: slru.h:64
int SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok, TransactionId xid)
Definition: slru.c:382
void pgstat_count_slru_page_hit(int slru_idx)
Definition: pgstat.c:6749
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
int slru_stats_idx
Definition: slru.h:100
int num_slots
Definition: slru.h:57
SlruShared shared
Definition: slru.h:111
#define SlruRecentlyUsed(shared, slotno)
Definition: slru.c:102

◆ SimpleLruShmemSize()

Size SimpleLruShmemSize ( int  nslots,
int  nlsns 
)

Definition at line 144 of file slru.c.

References BUFFERALIGN, and MAXALIGN.

Referenced by AsyncShmemSize(), CLOGShmemSize(), CommitTsShmemSize(), MultiXactShmemSize(), PredicateLockShmemSize(), SimpleLruInit(), and SUBTRANSShmemSize().

145 {
146  Size sz;
147 
148  /* we assume nslots isn't so large as to risk overflow */
149  sz = MAXALIGN(sizeof(SlruSharedData));
150  sz += MAXALIGN(nslots * sizeof(char *)); /* page_buffer[] */
151  sz += MAXALIGN(nslots * sizeof(SlruPageStatus)); /* page_status[] */
152  sz += MAXALIGN(nslots * sizeof(bool)); /* page_dirty[] */
153  sz += MAXALIGN(nslots * sizeof(int)); /* page_number[] */
154  sz += MAXALIGN(nslots * sizeof(int)); /* page_lru_count[] */
155  sz += MAXALIGN(nslots * sizeof(LWLockPadded)); /* buffer_locks[] */
156 
157  if (nlsns > 0)
158  sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */
159 
160  return BUFFERALIGN(sz) + BLCKSZ * nslots;
161 }
SlruPageStatus
Definition: slru.h:41
uint64 XLogRecPtr
Definition: xlogdefs.h:21
size_t Size
Definition: c.h:466
#define MAXALIGN(LEN)
Definition: c.h:691
#define BUFFERALIGN(LEN)
Definition: c.h:693

◆ SimpleLruTruncate()

void SimpleLruTruncate ( SlruCtl  ctl,
int  cutoffPage 
)

Definition at line 1213 of file slru.c.

References SlruSharedData::ControlLock, SlruCtlData::Dir, ereport, errmsg(), SlruSharedData::latest_page_number, LOG, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), SlruSharedData::num_slots, SlruSharedData::page_dirty, SlruSharedData::page_number, SlruSharedData::page_status, SlruCtlData::PagePrecedes, pgstat_count_slru_truncate(), SlruCtlData::shared, SimpleLruWaitIO(), SLRU_PAGE_EMPTY, SLRU_PAGE_VALID, SLRU_PAGES_PER_SEGMENT, SlruSharedData::slru_stats_idx, SlruInternalWritePage(), SlruScanDirCbDeleteCutoff(), and SlruScanDirectory().

Referenced by asyncQueueAdvanceTail(), CheckPointPredicate(), clog_redo(), commit_ts_redo(), PerformOffsetsTruncation(), TruncateCLOG(), TruncateCommitTs(), and TruncateSUBTRANS().

1214 {
1215  SlruShared shared = ctl->shared;
1216  int slotno;
1217 
1218  /* update the stats counter of truncates */
1220 
1221  /*
1222  * The cutoff point is the start of the segment containing cutoffPage.
1223  */
1224  cutoffPage -= cutoffPage % SLRU_PAGES_PER_SEGMENT;
1225 
1226  /*
1227  * Scan shared memory and remove any pages preceding the cutoff page, to
1228  * ensure we won't rewrite them later. (Since this is normally called in
1229  * or just after a checkpoint, any dirty pages should have been flushed
1230  * already ... we're just being extra careful here.)
1231  */
1233 
1234 restart:;
1235 
1236  /*
1237  * While we are holding the lock, make an important safety check: the
1238  * planned cutoff point must be <= the current endpoint page. Otherwise we
1239  * have already wrapped around, and proceeding with the truncation would
1240  * risk removing the current segment.
1241  */
1242  if (ctl->PagePrecedes(shared->latest_page_number, cutoffPage))
1243  {
1244  LWLockRelease(shared->ControlLock);
1245  ereport(LOG,
1246  (errmsg("could not truncate directory \"%s\": apparent wraparound",
1247  ctl->Dir)));
1248  return;
1249  }
1250 
1251  for (slotno = 0; slotno < shared->num_slots; slotno++)
1252  {
1253  if (shared->page_status[slotno] == SLRU_PAGE_EMPTY)
1254  continue;
1255  if (!ctl->PagePrecedes(shared->page_number[slotno], cutoffPage))
1256  continue;
1257 
1258  /*
1259  * If page is clean, just change state to EMPTY (expected case).
1260  */
1261  if (shared->page_status[slotno] == SLRU_PAGE_VALID &&
1262  !shared->page_dirty[slotno])
1263  {
1264  shared->page_status[slotno] = SLRU_PAGE_EMPTY;
1265  continue;
1266  }
1267 
1268  /*
1269  * Hmm, we have (or may have) I/O operations acting on the page, so
1270  * we've got to wait for them to finish and then start again. This is
1271  * the same logic as in SlruSelectLRUPage. (XXX if page is dirty,
1272  * wouldn't it be OK to just discard it without writing it? For now,
1273  * keep the logic the same as it was.)
1274  */
1275  if (shared->page_status[slotno] == SLRU_PAGE_VALID)
1276  SlruInternalWritePage(ctl, slotno, NULL);
1277  else
1278  SimpleLruWaitIO(ctl, slotno);
1279  goto restart;
1280  }
1281 
1282  LWLockRelease(shared->ControlLock);
1283 
1284  /* Now we can remove the old segment(s) */
1285  (void) SlruScanDirectory(ctl, SlruScanDirCbDeleteCutoff, &cutoffPage);
1286 }
LWLock * ControlLock
Definition: slru.h:54
int * page_number
Definition: slru.h:66
static void SlruInternalWritePage(SlruCtl ctl, int slotno, SlruFlush fdata)
Definition: slru.c:526
int latest_page_number
Definition: slru.h:97
#define LOG
Definition: elog.h:26
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
SlruPageStatus * page_status
Definition: slru.h:64
static void SimpleLruWaitIO(SlruCtl ctl, int slotno)
Definition: slru.c:328
static bool SlruScanDirCbDeleteCutoff(SlruCtl ctl, char *filename, int segpage, void *data)
Definition: slru.c:1386
char Dir[64]
Definition: slru.h:130
void pgstat_count_slru_truncate(int slru_idx)
Definition: pgstat.c:6779
#define ereport(elevel,...)
Definition: elog.h:144
bool SlruScanDirectory(SlruCtl ctl, SlruScanCallback callback, void *data)
Definition: slru.c:1424
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
int slru_stats_idx
Definition: slru.h:100
int num_slots
Definition: slru.h:57
int errmsg(const char *fmt,...)
Definition: elog.c:824
bool * page_dirty
Definition: slru.h:65
SlruShared shared
Definition: slru.h:111
bool(* PagePrecedes)(int, int)
Definition: slru.h:124
#define SLRU_PAGES_PER_SEGMENT
Definition: slru.h:33

◆ SimpleLruWritePage()

void SimpleLruWritePage ( SlruCtl  ctl,
int  slotno 
)

Definition at line 597 of file slru.c.

References SlruInternalWritePage().

Referenced by ActivateCommitTs(), BootStrapCLOG(), BootStrapMultiXact(), BootStrapSUBTRANS(), clog_redo(), commit_ts_redo(), MaybeExtendOffsetSlru(), and multixact_redo().

598 {
599  SlruInternalWritePage(ctl, slotno, NULL);
600 }
static void SlruInternalWritePage(SlruCtl ctl, int slotno, SlruFlush fdata)
Definition: slru.c:526

◆ SimpleLruZeroPage()

int SimpleLruZeroPage ( SlruCtl  ctl,
int  pageno 
)

Definition at line 267 of file slru.c.

References Assert, SlruSharedData::latest_page_number, MemSet, SlruSharedData::page_buffer, SlruSharedData::page_dirty, SlruSharedData::page_number, SlruSharedData::page_status, pgstat_count_slru_page_zeroed(), SlruCtlData::shared, SimpleLruZeroLSNs(), SLRU_PAGE_EMPTY, SLRU_PAGE_VALID, SlruSharedData::slru_stats_idx, SlruRecentlyUsed, and SlruSelectLRUPage().

Referenced by asyncQueueAddEntries(), SerialAdd(), ZeroCLOGPage(), ZeroCommitTsPage(), ZeroMultiXactMemberPage(), ZeroMultiXactOffsetPage(), and ZeroSUBTRANSPage().

268 {
269  SlruShared shared = ctl->shared;
270  int slotno;
271 
272  /* Find a suitable buffer slot for the page */
273  slotno = SlruSelectLRUPage(ctl, pageno);
274  Assert(shared->page_status[slotno] == SLRU_PAGE_EMPTY ||
275  (shared->page_status[slotno] == SLRU_PAGE_VALID &&
276  !shared->page_dirty[slotno]) ||
277  shared->page_number[slotno] == pageno);
278 
279  /* Mark the slot as containing this page */
280  shared->page_number[slotno] = pageno;
281  shared->page_status[slotno] = SLRU_PAGE_VALID;
282  shared->page_dirty[slotno] = true;
283  SlruRecentlyUsed(shared, slotno);
284 
285  /* Set the buffer to zeroes */
286  MemSet(shared->page_buffer[slotno], 0, BLCKSZ);
287 
288  /* Set the LSNs for this new page to zero */
289  SimpleLruZeroLSNs(ctl, slotno);
290 
291  /* Assume this page is now the latest active page */
292  shared->latest_page_number = pageno;
293 
294  /* update the stats counter of zeroed pages */
296 
297  return slotno;
298 }
int * page_number
Definition: slru.h:66
int latest_page_number
Definition: slru.h:97
char ** page_buffer
Definition: slru.h:63
#define MemSet(start, val, len)
Definition: c.h:971
static void SimpleLruZeroLSNs(SlruCtl ctl, int slotno)
Definition: slru.c:311
SlruPageStatus * page_status
Definition: slru.h:64
void pgstat_count_slru_page_zeroed(int slru_idx)
Definition: pgstat.c:6743
#define Assert(condition)
Definition: c.h:738
int slru_stats_idx
Definition: slru.h:100
static int SlruSelectLRUPage(SlruCtl ctl, int pageno)
Definition: slru.c:1008
bool * page_dirty
Definition: slru.h:65
SlruShared shared
Definition: slru.h:111
#define SlruRecentlyUsed(shared, slotno)
Definition: slru.c:102

◆ SlruDeleteSegment()

void SlruDeleteSegment ( SlruCtl  ctl,
int  segno 
)

Definition at line 1309 of file slru.c.

References SlruSharedData::ControlLock, DEBUG2, SlruCtlData::Dir, ereport, errmsg(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MAXPGPATH, SlruSharedData::num_slots, SlruSharedData::page_dirty, SlruSharedData::page_number, SlruSharedData::page_status, SlruCtlData::shared, SimpleLruWaitIO(), SLRU_PAGE_EMPTY, SLRU_PAGE_VALID, SLRU_PAGES_PER_SEGMENT, SlruInternalWritePage(), and snprintf.

Referenced by PerformMembersTruncation().

1310 {
1311  SlruShared shared = ctl->shared;
1312  int slotno;
1313  char path[MAXPGPATH];
1314  bool did_write;
1315 
1316  /* Clean out any possibly existing references to the segment. */
1318 restart:
1319  did_write = false;
1320  for (slotno = 0; slotno < shared->num_slots; slotno++)
1321  {
1322  int pagesegno = shared->page_number[slotno] / SLRU_PAGES_PER_SEGMENT;
1323 
1324  if (shared->page_status[slotno] == SLRU_PAGE_EMPTY)
1325  continue;
1326 
1327  /* not the segment we're looking for */
1328  if (pagesegno != segno)
1329  continue;
1330 
1331  /* If page is clean, just change state to EMPTY (expected case). */
1332  if (shared->page_status[slotno] == SLRU_PAGE_VALID &&
1333  !shared->page_dirty[slotno])
1334  {
1335  shared->page_status[slotno] = SLRU_PAGE_EMPTY;
1336  continue;
1337  }
1338 
1339  /* Same logic as SimpleLruTruncate() */
1340  if (shared->page_status[slotno] == SLRU_PAGE_VALID)
1341  SlruInternalWritePage(ctl, slotno, NULL);
1342  else
1343  SimpleLruWaitIO(ctl, slotno);
1344 
1345  did_write = true;
1346  }
1347 
1348  /*
1349  * Be extra careful and re-check. The IO functions release the control
1350  * lock, so new pages could have been read in.
1351  */
1352  if (did_write)
1353  goto restart;
1354 
1355  snprintf(path, MAXPGPATH, "%s/%04X", ctl->Dir, segno);
1356  ereport(DEBUG2,
1357  (errmsg("removing file \"%s\"", path)));
1358  unlink(path);
1359 
1360  LWLockRelease(shared->ControlLock);
1361 }
LWLock * ControlLock
Definition: slru.h:54
int * page_number
Definition: slru.h:66
static void SlruInternalWritePage(SlruCtl ctl, int slotno, SlruFlush fdata)
Definition: slru.c:526
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
SlruPageStatus * page_status
Definition: slru.h:64
#define MAXPGPATH
#define DEBUG2
Definition: elog.h:24
static void SimpleLruWaitIO(SlruCtl ctl, int slotno)
Definition: slru.c:328
char Dir[64]
Definition: slru.h:130
#define ereport(elevel,...)
Definition: elog.h:144
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
int num_slots
Definition: slru.h:57
int errmsg(const char *fmt,...)
Definition: elog.c:824
bool * page_dirty
Definition: slru.h:65
SlruShared shared
Definition: slru.h:111
#define SLRU_PAGES_PER_SEGMENT
Definition: slru.h:33
#define snprintf
Definition: port.h:193

◆ SlruScanDirCbDeleteAll()

bool SlruScanDirCbDeleteAll ( SlruCtl  ctl,
char *  filename,
int  segpage,
void *  data 
)

Definition at line 1401 of file slru.c.

References SlruInternalDeleteSegment().

Referenced by AsyncShmemInit(), and DeactivateCommitTs().

1402 {
1404 
1405  return false; /* keep going */
1406 }
static void SlruInternalDeleteSegment(SlruCtl ctl, char *filename)
Definition: slru.c:1295
static char * filename
Definition: pg_dumpall.c:90

◆ SlruScanDirCbReportPresence()

bool SlruScanDirCbReportPresence ( SlruCtl  ctl,
char *  filename,
int  segpage,
void *  data 
)

Definition at line 1369 of file slru.c.

References SlruCtlData::PagePrecedes, and SLRU_PAGES_PER_SEGMENT.

Referenced by TruncateCLOG(), and TruncateCommitTs().

1370 {
1371  int cutoffPage = *(int *) data;
1372 
1373  cutoffPage -= cutoffPage % SLRU_PAGES_PER_SEGMENT;
1374 
1375  if (ctl->PagePrecedes(segpage, cutoffPage))
1376  return true; /* found one; don't iterate any more */
1377 
1378  return false; /* keep going */
1379 }
bool(* PagePrecedes)(int, int)
Definition: slru.h:124
#define SLRU_PAGES_PER_SEGMENT
Definition: slru.h:33

◆ SlruScanDirectory()

bool SlruScanDirectory ( SlruCtl  ctl,
SlruScanCallback  callback,
void *  data 
)

Definition at line 1424 of file slru.c.

References AllocateDir(), callback(), dirent::d_name, DEBUG2, SlruCtlData::Dir, elog, FreeDir(), ReadDir(), SlruFlushData::segno, and SLRU_PAGES_PER_SEGMENT.

Referenced by AsyncShmemInit(), DeactivateCommitTs(), SimpleLruTruncate(), TruncateCLOG(), TruncateCommitTs(), and TruncateMultiXact().

1425 {
1426  bool retval = false;
1427  DIR *cldir;
1428  struct dirent *clde;
1429  int segno;
1430  int segpage;
1431 
1432  cldir = AllocateDir(ctl->Dir);
1433  while ((clde = ReadDir(cldir, ctl->Dir)) != NULL)
1434  {
1435  size_t len;
1436 
1437  len = strlen(clde->d_name);
1438 
1439  if ((len == 4 || len == 5 || len == 6) &&
1440  strspn(clde->d_name, "0123456789ABCDEF") == len)
1441  {
1442  segno = (int) strtol(clde->d_name, NULL, 16);
1443  segpage = segno * SLRU_PAGES_PER_SEGMENT;
1444 
1445  elog(DEBUG2, "SlruScanDirectory invoking callback on %s/%s",
1446  ctl->Dir, clde->d_name);
1447  retval = callback(ctl, clde->d_name, segpage, data);
1448  if (retval)
1449  break;
1450  }
1451  }
1452  FreeDir(cldir);
1453 
1454  return retval;
1455 }
Definition: dirent.h:9
Definition: dirent.c:25
static void callback(struct sockaddr *addr, struct sockaddr *mask, void *unused)
Definition: test_ifaddrs.c:48
#define DEBUG2
Definition: elog.h:24
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2581
char Dir[64]
Definition: slru.h:130
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2647
#define elog(elevel,...)
Definition: elog.h:214
char d_name[MAX_PATH]
Definition: dirent.h:14
#define SLRU_PAGES_PER_SEGMENT
Definition: slru.h:33
int FreeDir(DIR *dir)
Definition: fd.c:2699