PostgreSQL Source Code  git master
slru.h File Reference
#include "access/xlogdefs.h"
#include "storage/lwlock.h"
#include "storage/sync.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
 
#define SlruPagePrecedesUnitTests(ctl, per_page)   do {} while (0)
 

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, SyncRequestHandler sync_handler)
 
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 SimpleLruWriteAll (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)
 
int SlruSyncFileTag (SlruCtl ctl, const FileTag *ftag, char *path)
 
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

#define SLRU_PAGES_PER_SEGMENT   32

Definition at line 34 of file slru.h.

◆ SlruPagePrecedesUnitTests

#define SlruPagePrecedesUnitTests (   ctl,
  per_page 
)    do {} while (0)

Definition at line 156 of file slru.h.

Typedef Documentation

◆ SlruCtl

typedef SlruCtlData* SlruCtl

Definition at line 139 of file slru.h.

◆ SlruCtlData

typedef struct SlruCtlData SlruCtlData

◆ SlruScanCallback

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

Definition at line 161 of file slru.h.

◆ SlruShared

Definition at line 104 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 42 of file slru.h.

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

Function Documentation

◆ SimpleLruDoesPhysicalPageExist()

bool SimpleLruDoesPhysicalPageExist ( SlruCtl  ctl,
int  pageno 
)

Definition at line 627 of file slru.c.

628 {
629  int segno = pageno / SLRU_PAGES_PER_SEGMENT;
630  int rpageno = pageno % SLRU_PAGES_PER_SEGMENT;
631  int offset = rpageno * BLCKSZ;
632  char path[MAXPGPATH];
633  int fd;
634  bool result;
635  off_t endpos;
636 
637  /* update the stats counter of checked pages */
639 
640  SlruFileName(ctl, path, segno);
641 
642  fd = OpenTransientFile(path, O_RDONLY | PG_BINARY);
643  if (fd < 0)
644  {
645  /* expected: file doesn't exist */
646  if (errno == ENOENT)
647  return false;
648 
649  /* report error normally */
651  slru_errno = errno;
652  SlruReportIOError(ctl, pageno, 0);
653  }
654 
655  if ((endpos = lseek(fd, 0, SEEK_END)) < 0)
656  {
658  slru_errno = errno;
659  SlruReportIOError(ctl, pageno, 0);
660  }
661 
662  result = endpos >= (off_t) (offset + BLCKSZ);
663 
664  if (CloseTransientFile(fd) != 0)
665  {
667  slru_errno = errno;
668  return false;
669  }
670 
671  return result;
672 }
#define PG_BINARY
Definition: c.h:1278
int CloseTransientFile(int fd)
Definition: fd.c:2706
int OpenTransientFile(const char *fileName, int fileFlags)
Definition: fd.c:2530
#define MAXPGPATH
static XLogRecPtr endpos
Definition: pg_receivewal.c:56
void pgstat_count_slru_page_exists(int slru_idx)
Definition: pgstat_slru.c:71
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define SlruFileName(ctl, path, seg)
Definition: slru.c:63
static SlruErrorCause slru_errcause
Definition: slru.c:134
static void SlruReportIOError(SlruCtl ctl, int pageno, TransactionId xid)
Definition: slru.c:932
static int slru_errno
Definition: slru.c:135
@ SLRU_SEEK_FAILED
Definition: slru.c:127
@ SLRU_OPEN_FAILED
Definition: slru.c:126
@ SLRU_CLOSE_FAILED
Definition: slru.c:131
#define SLRU_PAGES_PER_SEGMENT
Definition: slru.h:34
SlruShared shared
Definition: slru.h:112
int slru_stats_idx
Definition: slru.h:101

References CloseTransientFile(), endpos, fd(), MAXPGPATH, OpenTransientFile(), PG_BINARY, pgstat_count_slru_page_exists(), SlruWriteAllData::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(), MaybeExtendOffsetSlru(), and test_slru_page_exists().

◆ SimpleLruInit()

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

Definition at line 188 of file slru.c.

191 {
192  SlruShared shared;
193  bool found;
194 
195  shared = (SlruShared) ShmemInitStruct(name,
196  SimpleLruShmemSize(nslots, nlsns),
197  &found);
198 
199  if (!IsUnderPostmaster)
200  {
201  /* Initialize locks and shared memory area */
202  char *ptr;
203  Size offset;
204  int slotno;
205 
206  Assert(!found);
207 
208  memset(shared, 0, sizeof(SlruSharedData));
209 
210  shared->ControlLock = ctllock;
211 
212  shared->num_slots = nslots;
213  shared->lsn_groups_per_page = nlsns;
214 
215  shared->cur_lru_count = 0;
216 
217  /* shared->latest_page_number will be set later */
218 
220 
221  ptr = (char *) shared;
222  offset = MAXALIGN(sizeof(SlruSharedData));
223  shared->page_buffer = (char **) (ptr + offset);
224  offset += MAXALIGN(nslots * sizeof(char *));
225  shared->page_status = (SlruPageStatus *) (ptr + offset);
226  offset += MAXALIGN(nslots * sizeof(SlruPageStatus));
227  shared->page_dirty = (bool *) (ptr + offset);
228  offset += MAXALIGN(nslots * sizeof(bool));
229  shared->page_number = (int *) (ptr + offset);
230  offset += MAXALIGN(nslots * sizeof(int));
231  shared->page_lru_count = (int *) (ptr + offset);
232  offset += MAXALIGN(nslots * sizeof(int));
233 
234  /* Initialize LWLocks */
235  shared->buffer_locks = (LWLockPadded *) (ptr + offset);
236  offset += MAXALIGN(nslots * sizeof(LWLockPadded));
237 
238  if (nlsns > 0)
239  {
240  shared->group_lsn = (XLogRecPtr *) (ptr + offset);
241  offset += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr));
242  }
243 
244  ptr += BUFFERALIGN(offset);
245  for (slotno = 0; slotno < nslots; slotno++)
246  {
247  LWLockInitialize(&shared->buffer_locks[slotno].lock,
248  tranche_id);
249 
250  shared->page_buffer[slotno] = ptr;
251  shared->page_status[slotno] = SLRU_PAGE_EMPTY;
252  shared->page_dirty[slotno] = false;
253  shared->page_lru_count[slotno] = 0;
254  ptr += BLCKSZ;
255  }
256 
257  /* Should fit to estimated shmem size */
258  Assert(ptr - (char *) shared <= SimpleLruShmemSize(nslots, nlsns));
259  }
260  else
261  Assert(found);
262 
263  /*
264  * Initialize the unshared control struct, including directory path. We
265  * assume caller set PagePrecedes.
266  */
267  ctl->shared = shared;
268  ctl->sync_handler = sync_handler;
269  strlcpy(ctl->Dir, subdir, sizeof(ctl->Dir));
270 }
#define MAXALIGN(LEN)
Definition: c.h:795
#define BUFFERALIGN(LEN)
Definition: c.h:797
size_t Size
Definition: c.h:589
const char * name
Definition: encode.c:571
bool IsUnderPostmaster
Definition: globals.c:113
Assert(fmt[strlen(fmt) - 1] !='\n')
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition: lwlock.c:730
int pgstat_get_slru_index(const char *name)
Definition: pgstat_slru.c:132
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:396
Size SimpleLruShmemSize(int nslots, int nlsns)
Definition: slru.c:156
SlruSharedData * SlruShared
Definition: slru.h:104
SyncRequestHandler sync_handler
Definition: slru.h:118
char Dir[64]
Definition: slru.h:136
int num_slots
Definition: slru.h:58
int * page_lru_count
Definition: slru.h:68
XLogRecPtr * group_lsn
Definition: slru.h:79
int cur_lru_count
Definition: slru.h:91
int * page_number
Definition: slru.h:67
int lsn_groups_per_page
Definition: slru.h:80
SlruPageStatus * page_status
Definition: slru.h:65
LWLock * ControlLock
Definition: slru.h:55
bool * page_dirty
Definition: slru.h:66
LWLockPadded * buffer_locks
Definition: slru.h:69
char ** page_buffer
Definition: slru.h:64
LWLock lock
Definition: lwlock.h:69
uint64 XLogRecPtr
Definition: xlogdefs.h:21

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

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

◆ SimpleLruReadPage()

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

Definition at line 396 of file slru.c.

398 {
399  SlruShared shared = ctl->shared;
400 
401  /* Outer loop handles restart if we must wait for someone else's I/O */
402  for (;;)
403  {
404  int slotno;
405  bool ok;
406 
407  /* See if page already is in memory; if not, pick victim slot */
408  slotno = SlruSelectLRUPage(ctl, pageno);
409 
410  /* Did we find the page in memory? */
411  if (shared->page_number[slotno] == pageno &&
412  shared->page_status[slotno] != SLRU_PAGE_EMPTY)
413  {
414  /*
415  * If page is still being read in, we must wait for I/O. Likewise
416  * if the page is being written and the caller said that's not OK.
417  */
418  if (shared->page_status[slotno] == SLRU_PAGE_READ_IN_PROGRESS ||
419  (shared->page_status[slotno] == SLRU_PAGE_WRITE_IN_PROGRESS &&
420  !write_ok))
421  {
422  SimpleLruWaitIO(ctl, slotno);
423  /* Now we must recheck state from the top */
424  continue;
425  }
426  /* Otherwise, it's ready to use */
427  SlruRecentlyUsed(shared, slotno);
428 
429  /* update the stats counter of pages found in the SLRU */
431 
432  return slotno;
433  }
434 
435  /* We found no match; assert we selected a freeable slot */
436  Assert(shared->page_status[slotno] == SLRU_PAGE_EMPTY ||
437  (shared->page_status[slotno] == SLRU_PAGE_VALID &&
438  !shared->page_dirty[slotno]));
439 
440  /* Mark the slot read-busy */
441  shared->page_number[slotno] = pageno;
442  shared->page_status[slotno] = SLRU_PAGE_READ_IN_PROGRESS;
443  shared->page_dirty[slotno] = false;
444 
445  /* Acquire per-buffer lock (cannot deadlock, see notes at top) */
446  LWLockAcquire(&shared->buffer_locks[slotno].lock, LW_EXCLUSIVE);
447 
448  /* Release control lock while doing I/O */
449  LWLockRelease(shared->ControlLock);
450 
451  /* Do the read */
452  ok = SlruPhysicalReadPage(ctl, pageno, slotno);
453 
454  /* Set the LSNs for this newly read-in page to zero */
455  SimpleLruZeroLSNs(ctl, slotno);
456 
457  /* Re-acquire control lock and update page state */
459 
460  Assert(shared->page_number[slotno] == pageno &&
461  shared->page_status[slotno] == SLRU_PAGE_READ_IN_PROGRESS &&
462  !shared->page_dirty[slotno]);
463 
464  shared->page_status[slotno] = ok ? SLRU_PAGE_VALID : SLRU_PAGE_EMPTY;
465 
466  LWLockRelease(&shared->buffer_locks[slotno].lock);
467 
468  /* Now it's okay to ereport if we failed */
469  if (!ok)
470  SlruReportIOError(ctl, pageno, xid);
471 
472  SlruRecentlyUsed(shared, slotno);
473 
474  /* update the stats counter of pages not found in SLRU */
476 
477  return slotno;
478  }
479 }
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1195
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
@ LW_EXCLUSIVE
Definition: lwlock.h:116
void pgstat_count_slru_page_read(int slru_idx)
Definition: pgstat_slru.c:77
void pgstat_count_slru_page_hit(int slru_idx)
Definition: pgstat_slru.c:65
static bool SlruPhysicalReadPage(SlruCtl ctl, int pageno, int slotno)
Definition: slru.c:685
#define SlruRecentlyUsed(shared, slotno)
Definition: slru.c:114
static void SimpleLruZeroLSNs(SlruCtl ctl, int slotno)
Definition: slru.c:325
static void SimpleLruWaitIO(SlruCtl ctl, int slotno)
Definition: slru.c:342
static int SlruSelectLRUPage(SlruCtl ctl, int pageno)
Definition: slru.c:1017

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(), test_slru_page_read(), TransactionIdSetPageStatusInternal(), TrimCLOG(), and TrimMultiXact().

◆ SimpleLruReadPage_ReadOnly()

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

Definition at line 496 of file slru.c.

497 {
498  SlruShared shared = ctl->shared;
499  int slotno;
500 
501  /* Try to find the page while holding only shared lock */
503 
504  /* See if page is already in a buffer */
505  for (slotno = 0; slotno < shared->num_slots; slotno++)
506  {
507  if (shared->page_number[slotno] == pageno &&
508  shared->page_status[slotno] != SLRU_PAGE_EMPTY &&
509  shared->page_status[slotno] != SLRU_PAGE_READ_IN_PROGRESS)
510  {
511  /* See comments for SlruRecentlyUsed macro */
512  SlruRecentlyUsed(shared, slotno);
513 
514  /* update the stats counter of pages found in the SLRU */
516 
517  return slotno;
518  }
519  }
520 
521  /* No luck, so switch to normal exclusive lock and do regular read */
522  LWLockRelease(shared->ControlLock);
524 
525  return SimpleLruReadPage(ctl, pageno, true, xid);
526 }
@ LW_SHARED
Definition: lwlock.h:117
int SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok, TransactionId xid)
Definition: slru.c:396

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(), test_slru_page_readonly(), TransactionIdGetCommitTsData(), and TransactionIdGetStatus().

◆ SimpleLruShmemSize()

Size SimpleLruShmemSize ( int  nslots,
int  nlsns 
)

Definition at line 156 of file slru.c.

157 {
158  Size sz;
159 
160  /* we assume nslots isn't so large as to risk overflow */
161  sz = MAXALIGN(sizeof(SlruSharedData));
162  sz += MAXALIGN(nslots * sizeof(char *)); /* page_buffer[] */
163  sz += MAXALIGN(nslots * sizeof(SlruPageStatus)); /* page_status[] */
164  sz += MAXALIGN(nslots * sizeof(bool)); /* page_dirty[] */
165  sz += MAXALIGN(nslots * sizeof(int)); /* page_number[] */
166  sz += MAXALIGN(nslots * sizeof(int)); /* page_lru_count[] */
167  sz += MAXALIGN(nslots * sizeof(LWLockPadded)); /* buffer_locks[] */
168 
169  if (nlsns > 0)
170  sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */
171 
172  return BUFFERALIGN(sz) + BLCKSZ * nslots;
173 }

References BUFFERALIGN, and MAXALIGN.

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

◆ SimpleLruTruncate()

void SimpleLruTruncate ( SlruCtl  ctl,
int  cutoffPage 
)

Definition at line 1227 of file slru.c.

1228 {
1229  SlruShared shared = ctl->shared;
1230  int slotno;
1231 
1232  /* update the stats counter of truncates */
1234 
1235  /*
1236  * Scan shared memory and remove any pages preceding the cutoff page, to
1237  * ensure we won't rewrite them later. (Since this is normally called in
1238  * or just after a checkpoint, any dirty pages should have been flushed
1239  * already ... we're just being extra careful here.)
1240  */
1242 
1243 restart:
1244 
1245  /*
1246  * While we are holding the lock, make an important safety check: the
1247  * current endpoint page must not be eligible for removal.
1248  */
1249  if (ctl->PagePrecedes(shared->latest_page_number, cutoffPage))
1250  {
1251  LWLockRelease(shared->ControlLock);
1252  ereport(LOG,
1253  (errmsg("could not truncate directory \"%s\": apparent wraparound",
1254  ctl->Dir)));
1255  return;
1256  }
1257 
1258  for (slotno = 0; slotno < shared->num_slots; slotno++)
1259  {
1260  if (shared->page_status[slotno] == SLRU_PAGE_EMPTY)
1261  continue;
1262  if (!ctl->PagePrecedes(shared->page_number[slotno], cutoffPage))
1263  continue;
1264 
1265  /*
1266  * If page is clean, just change state to EMPTY (expected case).
1267  */
1268  if (shared->page_status[slotno] == SLRU_PAGE_VALID &&
1269  !shared->page_dirty[slotno])
1270  {
1271  shared->page_status[slotno] = SLRU_PAGE_EMPTY;
1272  continue;
1273  }
1274 
1275  /*
1276  * Hmm, we have (or may have) I/O operations acting on the page, so
1277  * we've got to wait for them to finish and then start again. This is
1278  * the same logic as in SlruSelectLRUPage. (XXX if page is dirty,
1279  * wouldn't it be OK to just discard it without writing it?
1280  * SlruMayDeleteSegment() uses a stricter qualification, so we might
1281  * not delete this page in the end; even if we don't delete it, we
1282  * won't have cause to read its data again. For now, keep the logic
1283  * the same as it was.)
1284  */
1285  if (shared->page_status[slotno] == SLRU_PAGE_VALID)
1286  SlruInternalWritePage(ctl, slotno, NULL);
1287  else
1288  SimpleLruWaitIO(ctl, slotno);
1289  goto restart;
1290  }
1291 
1292  LWLockRelease(shared->ControlLock);
1293 
1294  /* Now we can remove the old segment(s) */
1295  (void) SlruScanDirectory(ctl, SlruScanDirCbDeleteCutoff, &cutoffPage);
1296 }
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define LOG
Definition: elog.h:31
#define ereport(elevel,...)
Definition: elog.h:149
void pgstat_count_slru_truncate(int slru_idx)
Definition: pgstat_slru.c:95
static void SlruInternalWritePage(SlruCtl ctl, int slotno, SlruWriteAll fdata)
Definition: slru.c:540
bool SlruScanDirectory(SlruCtl ctl, SlruScanCallback callback, void *data)
Definition: slru.c:1554
static bool SlruScanDirCbDeleteCutoff(SlruCtl ctl, char *filename, int segpage, void *data)
Definition: slru.c:1516
bool(* PagePrecedes)(int, int)
Definition: slru.h:130
int latest_page_number
Definition: slru.h:98

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, SlruSharedData::slru_stats_idx, SlruInternalWritePage(), SlruScanDirCbDeleteCutoff(), and SlruScanDirectory().

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

◆ SimpleLruWriteAll()

void SimpleLruWriteAll ( SlruCtl  ctl,
bool  allow_redirtied 
)

Definition at line 1157 of file slru.c.

1158 {
1159  SlruShared shared = ctl->shared;
1160  SlruWriteAllData fdata;
1161  int slotno;
1162  int pageno = 0;
1163  int i;
1164  bool ok;
1165 
1166  /* update the stats counter of flushes */
1168 
1169  /*
1170  * Find and write dirty pages
1171  */
1172  fdata.num_files = 0;
1173 
1175 
1176  for (slotno = 0; slotno < shared->num_slots; slotno++)
1177  {
1178  SlruInternalWritePage(ctl, slotno, &fdata);
1179 
1180  /*
1181  * In some places (e.g. checkpoints), we cannot assert that the slot
1182  * is clean now, since another process might have re-dirtied it
1183  * already. That's okay.
1184  */
1185  Assert(allow_redirtied ||
1186  shared->page_status[slotno] == SLRU_PAGE_EMPTY ||
1187  (shared->page_status[slotno] == SLRU_PAGE_VALID &&
1188  !shared->page_dirty[slotno]));
1189  }
1190 
1191  LWLockRelease(shared->ControlLock);
1192 
1193  /*
1194  * Now close any files that were open
1195  */
1196  ok = true;
1197  for (i = 0; i < fdata.num_files; i++)
1198  {
1199  if (CloseTransientFile(fdata.fd[i]) != 0)
1200  {
1202  slru_errno = errno;
1203  pageno = fdata.segno[i] * SLRU_PAGES_PER_SEGMENT;
1204  ok = false;
1205  }
1206  }
1207  if (!ok)
1209 
1210  /* Ensure that directory entries for new files are on disk. */
1211  if (ctl->sync_handler != SYNC_HANDLER_NONE)
1212  fsync_fname(ctl->Dir, true);
1213 }
void fsync_fname(const char *fname, bool isdir)
Definition: fd.c:667
int i
Definition: isn.c:73
void pgstat_count_slru_flush(int slru_idx)
Definition: pgstat_slru.c:89
int num_files
Definition: slru.c:76
int fd[MAX_WRITEALL_BUFFERS]
Definition: slru.c:77
int segno[MAX_WRITEALL_BUFFERS]
Definition: slru.c:78
@ SYNC_HANDLER_NONE
Definition: sync.h:42
#define InvalidTransactionId
Definition: transam.h:31

References Assert(), CloseTransientFile(), SlruSharedData::ControlLock, SlruCtlData::Dir, SlruWriteAllData::fd, fsync_fname(), i, InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), SlruWriteAllData::num_files, SlruSharedData::num_slots, SlruSharedData::page_dirty, SlruSharedData::page_status, pgstat_count_slru_flush(), SlruWriteAllData::segno, SlruCtlData::shared, SLRU_CLOSE_FAILED, slru_errcause, slru_errno, SLRU_PAGE_EMPTY, SLRU_PAGE_VALID, SLRU_PAGES_PER_SEGMENT, SlruSharedData::slru_stats_idx, SlruInternalWritePage(), SlruReportIOError(), SlruCtlData::sync_handler, and SYNC_HANDLER_NONE.

Referenced by CheckPointCLOG(), CheckPointCommitTs(), CheckPointMultiXact(), CheckPointPredicate(), CheckPointSUBTRANS(), find_multixact_start(), and test_slru_page_writeall().

◆ SimpleLruWritePage()

void SimpleLruWritePage ( SlruCtl  ctl,
int  slotno 
)

◆ SimpleLruZeroPage()

int SimpleLruZeroPage ( SlruCtl  ctl,
int  pageno 
)

Definition at line 281 of file slru.c.

282 {
283  SlruShared shared = ctl->shared;
284  int slotno;
285 
286  /* Find a suitable buffer slot for the page */
287  slotno = SlruSelectLRUPage(ctl, pageno);
288  Assert(shared->page_status[slotno] == SLRU_PAGE_EMPTY ||
289  (shared->page_status[slotno] == SLRU_PAGE_VALID &&
290  !shared->page_dirty[slotno]) ||
291  shared->page_number[slotno] == pageno);
292 
293  /* Mark the slot as containing this page */
294  shared->page_number[slotno] = pageno;
295  shared->page_status[slotno] = SLRU_PAGE_VALID;
296  shared->page_dirty[slotno] = true;
297  SlruRecentlyUsed(shared, slotno);
298 
299  /* Set the buffer to zeroes */
300  MemSet(shared->page_buffer[slotno], 0, BLCKSZ);
301 
302  /* Set the LSNs for this new page to zero */
303  SimpleLruZeroLSNs(ctl, slotno);
304 
305  /* Assume this page is now the latest active page */
306  shared->latest_page_number = pageno;
307 
308  /* update the stats counter of zeroed pages */
310 
311  return slotno;
312 }
#define MemSet(start, val, len)
Definition: c.h:1004
void pgstat_count_slru_page_zeroed(int slru_idx)
Definition: pgstat_slru.c:59

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(), test_slru_page_write(), ZeroCLOGPage(), ZeroCommitTsPage(), ZeroMultiXactMemberPage(), ZeroMultiXactOffsetPage(), and ZeroSUBTRANSPage().

◆ SlruDeleteSegment()

void SlruDeleteSegment ( SlruCtl  ctl,
int  segno 
)

Definition at line 1328 of file slru.c.

1329 {
1330  SlruShared shared = ctl->shared;
1331  int slotno;
1332  bool did_write;
1333 
1334  /* Clean out any possibly existing references to the segment. */
1336 restart:
1337  did_write = false;
1338  for (slotno = 0; slotno < shared->num_slots; slotno++)
1339  {
1340  int pagesegno = shared->page_number[slotno] / SLRU_PAGES_PER_SEGMENT;
1341 
1342  if (shared->page_status[slotno] == SLRU_PAGE_EMPTY)
1343  continue;
1344 
1345  /* not the segment we're looking for */
1346  if (pagesegno != segno)
1347  continue;
1348 
1349  /* If page is clean, just change state to EMPTY (expected case). */
1350  if (shared->page_status[slotno] == SLRU_PAGE_VALID &&
1351  !shared->page_dirty[slotno])
1352  {
1353  shared->page_status[slotno] = SLRU_PAGE_EMPTY;
1354  continue;
1355  }
1356 
1357  /* Same logic as SimpleLruTruncate() */
1358  if (shared->page_status[slotno] == SLRU_PAGE_VALID)
1359  SlruInternalWritePage(ctl, slotno, NULL);
1360  else
1361  SimpleLruWaitIO(ctl, slotno);
1362 
1363  did_write = true;
1364  }
1365 
1366  /*
1367  * Be extra careful and re-check. The IO functions release the control
1368  * lock, so new pages could have been read in.
1369  */
1370  if (did_write)
1371  goto restart;
1372 
1373  SlruInternalDeleteSegment(ctl, segno);
1374 
1375  LWLockRelease(shared->ControlLock);
1376 }
static void SlruInternalDeleteSegment(SlruCtl ctl, int segno)
Definition: slru.c:1305

References SlruSharedData::ControlLock, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), SlruSharedData::num_slots, SlruSharedData::page_dirty, SlruSharedData::page_number, SlruSharedData::page_status, SlruWriteAllData::segno, SlruCtlData::shared, SimpleLruWaitIO(), SLRU_PAGE_EMPTY, SLRU_PAGE_VALID, SLRU_PAGES_PER_SEGMENT, SlruInternalDeleteSegment(), and SlruInternalWritePage().

Referenced by PerformMembersTruncation(), and test_slru_page_delete().

◆ SlruScanDirCbDeleteAll()

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

Definition at line 1531 of file slru.c.

1532 {
1534 
1535  return false; /* keep going */
1536 }

References SLRU_PAGES_PER_SEGMENT, and SlruInternalDeleteSegment().

Referenced by AsyncShmemInit(), DeactivateCommitTs(), and test_slru_scan_cb().

◆ SlruScanDirCbReportPresence()

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

Definition at line 1501 of file slru.c.

1502 {
1503  int cutoffPage = *(int *) data;
1504 
1505  if (SlruMayDeleteSegment(ctl, segpage, cutoffPage))
1506  return true; /* found one; don't iterate any more */
1507 
1508  return false; /* keep going */
1509 }
const void * data
static bool SlruMayDeleteSegment(SlruCtl ctl, int segpage, int cutoffPage)
Definition: slru.c:1392

References data, and SlruMayDeleteSegment().

Referenced by TruncateCLOG(), and TruncateCommitTs().

◆ SlruScanDirectory()

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

Definition at line 1554 of file slru.c.

1555 {
1556  bool retval = false;
1557  DIR *cldir;
1558  struct dirent *clde;
1559  int segno;
1560  int segpage;
1561 
1562  cldir = AllocateDir(ctl->Dir);
1563  while ((clde = ReadDir(cldir, ctl->Dir)) != NULL)
1564  {
1565  size_t len;
1566 
1567  len = strlen(clde->d_name);
1568 
1569  if ((len == 4 || len == 5 || len == 6) &&
1570  strspn(clde->d_name, "0123456789ABCDEF") == len)
1571  {
1572  segno = (int) strtol(clde->d_name, NULL, 16);
1573  segpage = segno * SLRU_PAGES_PER_SEGMENT;
1574 
1575  elog(DEBUG2, "SlruScanDirectory invoking callback on %s/%s",
1576  ctl->Dir, clde->d_name);
1577  retval = callback(ctl, clde->d_name, segpage, data);
1578  if (retval)
1579  break;
1580  }
1581  }
1582  FreeDir(cldir);
1583 
1584  return retval;
1585 }
#define DEBUG2
Definition: elog.h:29
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2806
int FreeDir(DIR *dir)
Definition: fd.c:2858
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2740
const void size_t len
Definition: dirent.c:26
Definition: dirent.h:10
char d_name[MAX_PATH]
Definition: dirent.h:15
static void callback(struct sockaddr *addr, struct sockaddr *mask, void *unused)
Definition: test_ifaddrs.c:46

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

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

◆ SlruSyncFileTag()

int SlruSyncFileTag ( SlruCtl  ctl,
const FileTag ftag,
char *  path 
)

Definition at line 1594 of file slru.c.

1595 {
1596  int fd;
1597  int save_errno;
1598  int result;
1599 
1600  SlruFileName(ctl, path, ftag->segno);
1601 
1602  fd = OpenTransientFile(path, O_RDWR | PG_BINARY);
1603  if (fd < 0)
1604  return -1;
1605 
1607  result = pg_fsync(fd);
1609  save_errno = errno;
1610 
1612 
1613  errno = save_errno;
1614  return result;
1615 }
int pg_fsync(int fd)
Definition: fd.c:361
uint32 segno
Definition: sync.h:55
@ WAIT_EVENT_SLRU_FLUSH_SYNC
Definition: wait_event.h:210
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:271
static void pgstat_report_wait_end(void)
Definition: wait_event.h:287

References CloseTransientFile(), fd(), OpenTransientFile(), PG_BINARY, pg_fsync(), pgstat_report_wait_end(), pgstat_report_wait_start(), FileTag::segno, SlruFileName, and WAIT_EVENT_SLRU_FLUSH_SYNC.

Referenced by clogsyncfiletag(), committssyncfiletag(), multixactmemberssyncfiletag(), multixactoffsetssyncfiletag(), and test_slru_page_sync().