Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * slru.h
4 : * Simple LRU buffering for transaction status logfiles
5 : *
6 : * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : * src/include/access/slru.h
10 : *
11 : *-------------------------------------------------------------------------
12 : */
13 : #ifndef SLRU_H
14 : #define SLRU_H
15 :
16 : #include "access/transam.h"
17 : #include "access/xlogdefs.h"
18 : #include "storage/lwlock.h"
19 : #include "storage/sync.h"
20 :
21 : /*
22 : * To avoid overflowing internal arithmetic and the size_t data type, the
23 : * number of buffers must not exceed this number.
24 : */
25 : #define SLRU_MAX_ALLOWED_BUFFERS ((1024 * 1024 * 1024) / BLCKSZ)
26 :
27 : /*
28 : * Page status codes. Note that these do not include the "dirty" bit.
29 : * page_dirty can be true only in the VALID or WRITE_IN_PROGRESS states;
30 : * in the latter case it implies that the page has been re-dirtied since
31 : * the write started.
32 : */
33 : typedef enum
34 : {
35 : SLRU_PAGE_EMPTY, /* buffer is not in use */
36 : SLRU_PAGE_READ_IN_PROGRESS, /* page is being read in */
37 : SLRU_PAGE_VALID, /* page is valid and not being written */
38 : SLRU_PAGE_WRITE_IN_PROGRESS, /* page is being written out */
39 : } SlruPageStatus;
40 :
41 : /*
42 : * Shared-memory state
43 : *
44 : * SLRU bank locks are used to protect access to the other fields, except
45 : * latest_page_number, which uses atomics; see comment in slru.c.
46 : */
47 : typedef struct SlruSharedData
48 : {
49 : /* Number of buffers managed by this SLRU structure */
50 : int num_slots;
51 :
52 : /*
53 : * Arrays holding info for each buffer slot. Page number is undefined
54 : * when status is EMPTY, as is page_lru_count.
55 : */
56 : char **page_buffer;
57 : SlruPageStatus *page_status;
58 : bool *page_dirty;
59 : int64 *page_number;
60 : int *page_lru_count;
61 :
62 : /* The buffer_locks protects the I/O on each buffer slots */
63 : LWLockPadded *buffer_locks;
64 :
65 : /* Locks to protect the in memory buffer slot access in SLRU bank. */
66 : LWLockPadded *bank_locks;
67 :
68 : /*----------
69 : * A bank-wise LRU counter is maintained because we do a victim buffer
70 : * search within a bank. Furthermore, manipulating an individual bank
71 : * counter avoids frequent cache invalidation since we update it every time
72 : * we access the page.
73 : *
74 : * We mark a page "most recently used" by setting
75 : * page_lru_count[slotno] = ++bank_cur_lru_count[bankno];
76 : * The oldest page in the bank is therefore the one with the highest value
77 : * of
78 : * bank_cur_lru_count[bankno] - page_lru_count[slotno]
79 : * The counts will eventually wrap around, but this calculation still
80 : * works as long as no page's age exceeds INT_MAX counts.
81 : *----------
82 : */
83 : int *bank_cur_lru_count;
84 :
85 : /*
86 : * Optional array of WAL flush LSNs associated with entries in the SLRU
87 : * pages. If not zero/NULL, we must flush WAL before writing pages (true
88 : * for pg_xact, false for everything else). group_lsn[] has
89 : * lsn_groups_per_page entries per buffer slot, each containing the
90 : * highest LSN known for a contiguous group of SLRU entries on that slot's
91 : * page.
92 : */
93 : XLogRecPtr *group_lsn;
94 : int lsn_groups_per_page;
95 :
96 : /*
97 : * latest_page_number is the page number of the current end of the log;
98 : * this is not critical data, since we use it only to avoid swapping out
99 : * the latest page.
100 : */
101 : pg_atomic_uint64 latest_page_number;
102 :
103 : /* SLRU's index for statistics purposes (might not be unique) */
104 : int slru_stats_idx;
105 : } SlruSharedData;
106 :
107 : typedef SlruSharedData *SlruShared;
108 :
109 : /*
110 : * SlruCtlData is an unshared structure that points to the active information
111 : * in shared memory.
112 : */
113 : typedef struct SlruCtlData
114 : {
115 : SlruShared shared;
116 :
117 : /* Number of banks in this SLRU. */
118 : uint16 nbanks;
119 :
120 : /*
121 : * If true, use long segment file names. Otherwise, use short file names.
122 : *
123 : * For details about the file name format, see SlruFileName().
124 : */
125 : bool long_segment_names;
126 :
127 : /*
128 : * Which sync handler function to use when handing sync requests over to
129 : * the checkpointer. SYNC_HANDLER_NONE to disable fsync (eg pg_notify).
130 : */
131 : SyncRequestHandler sync_handler;
132 :
133 : /*
134 : * Decide whether a page is "older" for truncation and as a hint for
135 : * evicting pages in LRU order. Return true if every entry of the first
136 : * argument is older than every entry of the second argument. Note that
137 : * !PagePrecedes(a,b) && !PagePrecedes(b,a) need not imply a==b; it also
138 : * arises when some entries are older and some are not. For SLRUs using
139 : * SimpleLruTruncate(), this must use modular arithmetic. (For others,
140 : * the behavior of this callback has no functional implications.) Use
141 : * SlruPagePrecedesUnitTests() in SLRUs meeting its criteria.
142 : */
143 : bool (*PagePrecedes) (int64, int64);
144 :
145 : /*
146 : * Callback to provide more details on an I/O error. This is called as
147 : * part of ereport(), and the callback function is expected to call
148 : * errdetail() to provide more context on the SLRU access.
149 : *
150 : * The opaque_data argument here is the argument that was passed to the
151 : * SimpleLruReadPage() function.
152 : */
153 : int (*errdetail_for_io_error) (const void *opaque_data);
154 :
155 : /*
156 : * Dir is set during SimpleLruInit and does not change thereafter. Since
157 : * it's always the same, it doesn't need to be in shared memory.
158 : */
159 : char Dir[64];
160 : } SlruCtlData;
161 :
162 : typedef SlruCtlData *SlruCtl;
163 :
164 : /*
165 : * Get the SLRU bank lock for given SlruCtl and the pageno.
166 : *
167 : * This lock needs to be acquired to access the slru buffer slots in the
168 : * respective bank.
169 : */
170 : static inline LWLock *
746 alvherre@alvh.no-ip. 171 CBC 3014130 : SimpleLruGetBankLock(SlruCtl ctl, int64 pageno)
172 : {
173 : int bankno;
174 :
430 175 3014130 : bankno = pageno % ctl->nbanks;
746 176 3014130 : return &(ctl->shared->bank_locks[bankno].lock);
177 : }
178 :
179 : extern Size SimpleLruShmemSize(int nslots, int nlsns);
180 : extern int SimpleLruAutotuneBuffers(int divisor, int max);
181 : extern void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns,
182 : const char *subdir, int buffer_tranche_id,
183 : int bank_tranche_id, SyncRequestHandler sync_handler,
184 : bool long_segment_names);
185 : extern int SimpleLruZeroPage(SlruCtl ctl, int64 pageno);
186 : extern void SimpleLruZeroAndWritePage(SlruCtl ctl, int64 pageno);
187 : extern int SimpleLruReadPage(SlruCtl ctl, int64 pageno, bool write_ok,
188 : const void *opaque_data);
189 : extern int SimpleLruReadPage_ReadOnly(SlruCtl ctl, int64 pageno,
190 : const void *opaque_data);
191 : extern void SimpleLruWritePage(SlruCtl ctl, int slotno);
192 : extern void SimpleLruWriteAll(SlruCtl ctl, bool allow_redirtied);
193 : #ifdef USE_ASSERT_CHECKING
194 : extern void SlruPagePrecedesUnitTests(SlruCtl ctl, int per_page);
195 : #else
196 : #define SlruPagePrecedesUnitTests(ctl, per_page) do {} while (0)
197 : #endif
198 : extern void SimpleLruTruncate(SlruCtl ctl, int64 cutoffPage);
199 : extern bool SimpleLruDoesPhysicalPageExist(SlruCtl ctl, int64 pageno);
200 :
201 : typedef bool (*SlruScanCallback) (SlruCtl ctl, char *filename, int64 segpage,
202 : void *data);
203 : extern bool SlruScanDirectory(SlruCtl ctl, SlruScanCallback callback, void *data);
204 : extern void SlruDeleteSegment(SlruCtl ctl, int64 segno);
205 :
206 : extern int SlruSyncFileTag(SlruCtl ctl, const FileTag *ftag, char *path);
207 :
208 : /* SlruScanDirectory public callbacks */
209 : extern bool SlruScanDirCbReportPresence(SlruCtl ctl, char *filename,
210 : int64 segpage, void *data);
211 : extern bool SlruScanDirCbDeleteAll(SlruCtl ctl, char *filename, int64 segpage,
212 : void *data);
213 : extern bool check_slru_buffers(const char *name, int *newval);
214 :
215 : #endif /* SLRU_H */
|