Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * bufmgr.h
4 : * POSTGRES buffer manager definitions.
5 : *
6 : *
7 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
8 : * Portions Copyright (c) 1994, Regents of the University of California
9 : *
10 : * src/include/storage/bufmgr.h
11 : *
12 : *-------------------------------------------------------------------------
13 : */
14 : #ifndef BUFMGR_H
15 : #define BUFMGR_H
16 :
17 : #include "storage/block.h"
18 : #include "storage/buf.h"
19 : #include "storage/bufpage.h"
20 : #include "storage/relfilelocator.h"
21 : #include "utils/relcache.h"
22 : #include "utils/snapmgr.h"
23 :
24 : typedef void *Block;
25 :
26 : /*
27 : * Possible arguments for GetAccessStrategy().
28 : *
29 : * If adding a new BufferAccessStrategyType, also add a new IOContext so
30 : * IO statistics using this strategy are tracked.
31 : */
32 : typedef enum BufferAccessStrategyType
33 : {
34 : BAS_NORMAL, /* Normal random access */
35 : BAS_BULKREAD, /* Large read-only scan (hint bit updates are
36 : * ok) */
37 : BAS_BULKWRITE, /* Large multi-block write (e.g. COPY IN) */
38 : BAS_VACUUM /* VACUUM */
39 : } BufferAccessStrategyType;
40 :
41 : /* Possible modes for ReadBufferExtended() */
42 : typedef enum
43 : {
44 : RBM_NORMAL, /* Normal read */
45 : RBM_ZERO_AND_LOCK, /* Don't read from disk, caller will
46 : * initialize. Also locks the page. */
47 : RBM_ZERO_AND_CLEANUP_LOCK, /* Like RBM_ZERO_AND_LOCK, but locks the page
48 : * in "cleanup" mode */
49 : RBM_ZERO_ON_ERROR, /* Read, but return an all-zeros page on error */
50 : RBM_NORMAL_NO_LOG /* Don't log page as invalid during WAL
51 : * replay; otherwise same as RBM_NORMAL */
52 : } ReadBufferMode;
53 :
54 : /*
55 : * Type returned by PrefetchBuffer().
56 : */
57 : typedef struct PrefetchBufferResult
58 : {
59 : Buffer recent_buffer; /* If valid, a hit (recheck needed!) */
60 : bool initiated_io; /* If true, a miss resulting in async I/O */
61 : } PrefetchBufferResult;
62 :
63 : /*
64 : * Flags influencing the behaviour of ExtendBufferedRel*
65 : */
66 : typedef enum ExtendBufferedFlags
67 : {
68 : /*
69 : * Don't acquire extension lock. This is safe only if the relation isn't
70 : * shared, an access exclusive lock is held or if this is the startup
71 : * process.
72 : */
73 : EB_SKIP_EXTENSION_LOCK = (1 << 0),
74 :
75 : /* Is this extension part of recovery? */
76 : EB_PERFORMING_RECOVERY = (1 << 1),
77 :
78 : /*
79 : * Should the fork be created if it does not currently exist? This likely
80 : * only ever makes sense for relation forks.
81 : */
82 : EB_CREATE_FORK_IF_NEEDED = (1 << 2),
83 :
84 : /* Should the first (possibly only) return buffer be returned locked? */
85 : EB_LOCK_FIRST = (1 << 3),
86 :
87 : /* Should the smgr size cache be cleared? */
88 : EB_CLEAR_SIZE_CACHE = (1 << 4),
89 :
90 : /* internal flags follow */
91 : EB_LOCK_TARGET = (1 << 5),
92 : } ExtendBufferedFlags;
93 :
94 : /*
95 : * To identify the relation - either relation or smgr + relpersistence has to
96 : * be specified. Used via the EB_REL()/EB_SMGR() macros below. This allows us
97 : * to use the same function for both crash recovery and normal operation.
98 : */
99 : typedef struct ExtendBufferedWhat
100 : {
101 : Relation rel;
102 : struct SMgrRelationData *smgr;
103 : char relpersistence;
104 : } ExtendBufferedWhat;
105 :
106 : #define EB_REL(p_rel) ((ExtendBufferedWhat){.rel = p_rel})
107 : #define EB_SMGR(p_smgr, p_relpersistence) ((ExtendBufferedWhat){.smgr = p_smgr, .relpersistence = p_relpersistence})
108 :
109 :
110 : /* forward declared, to avoid having to expose buf_internals.h here */
111 : struct WritebackContext;
112 :
113 : /* forward declared, to avoid including smgr.h here */
114 : struct SMgrRelationData;
115 :
116 : /* in globals.c ... this duplicates miscadmin.h */
117 : extern PGDLLIMPORT int NBuffers;
118 :
119 : /* in bufmgr.c */
120 : extern PGDLLIMPORT bool zero_damaged_pages;
121 : extern PGDLLIMPORT int bgwriter_lru_maxpages;
122 : extern PGDLLIMPORT double bgwriter_lru_multiplier;
123 : extern PGDLLIMPORT bool track_io_timing;
124 :
125 : /* only applicable when prefetching is available */
126 : #ifdef USE_PREFETCH
127 : #define DEFAULT_EFFECTIVE_IO_CONCURRENCY 1
128 : #define DEFAULT_MAINTENANCE_IO_CONCURRENCY 10
129 : #else
130 : #define DEFAULT_EFFECTIVE_IO_CONCURRENCY 0
131 : #define DEFAULT_MAINTENANCE_IO_CONCURRENCY 0
132 : #endif
133 : extern PGDLLIMPORT int effective_io_concurrency;
134 : extern PGDLLIMPORT int maintenance_io_concurrency;
135 :
136 : extern PGDLLIMPORT int checkpoint_flush_after;
137 : extern PGDLLIMPORT int backend_flush_after;
138 : extern PGDLLIMPORT int bgwriter_flush_after;
139 :
140 : /* in buf_init.c */
141 : extern PGDLLIMPORT char *BufferBlocks;
142 :
143 : /* in localbuf.c */
144 : extern PGDLLIMPORT int NLocBuffer;
145 : extern PGDLLIMPORT Block *LocalBufferBlockPointers;
146 : extern PGDLLIMPORT int32 *LocalRefCount;
147 :
148 : /* upper limit for effective_io_concurrency */
149 : #define MAX_IO_CONCURRENCY 1000
150 :
151 : /* special block number for ReadBuffer() */
152 : #define P_NEW InvalidBlockNumber /* grow the file to get a new page */
153 :
154 : /*
155 : * Buffer content lock modes (mode argument for LockBuffer())
156 : */
157 : #define BUFFER_LOCK_UNLOCK 0
158 : #define BUFFER_LOCK_SHARE 1
159 : #define BUFFER_LOCK_EXCLUSIVE 2
160 :
161 :
162 : /*
163 : * prototypes for functions in bufmgr.c
164 : */
165 : extern PrefetchBufferResult PrefetchSharedBuffer(struct SMgrRelationData *smgr_reln,
166 : ForkNumber forkNum,
167 : BlockNumber blockNum);
168 : extern PrefetchBufferResult PrefetchBuffer(Relation reln, ForkNumber forkNum,
169 : BlockNumber blockNum);
170 : extern bool ReadRecentBuffer(RelFileLocator rlocator, ForkNumber forkNum,
171 : BlockNumber blockNum, Buffer recent_buffer);
172 : extern Buffer ReadBuffer(Relation reln, BlockNumber blockNum);
173 : extern Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum,
174 : BlockNumber blockNum, ReadBufferMode mode,
175 : BufferAccessStrategy strategy);
176 : extern Buffer ReadBufferWithoutRelcache(RelFileLocator rlocator,
177 : ForkNumber forkNum, BlockNumber blockNum,
178 : ReadBufferMode mode, BufferAccessStrategy strategy,
179 : bool permanent);
180 : extern void ReleaseBuffer(Buffer buffer);
181 : extern void UnlockReleaseBuffer(Buffer buffer);
182 : extern void MarkBufferDirty(Buffer buffer);
183 : extern void IncrBufferRefCount(Buffer buffer);
184 : extern void CheckBufferIsPinnedOnce(Buffer buffer);
185 : extern Buffer ReleaseAndReadBuffer(Buffer buffer, Relation relation,
186 : BlockNumber blockNum);
187 :
188 : extern Buffer ExtendBufferedRel(ExtendBufferedWhat eb,
189 : ForkNumber forkNum,
190 : BufferAccessStrategy strategy,
191 : uint32 flags);
192 : extern BlockNumber ExtendBufferedRelBy(ExtendBufferedWhat eb,
193 : ForkNumber fork,
194 : BufferAccessStrategy strategy,
195 : uint32 flags,
196 : uint32 extend_by,
197 : Buffer *buffers,
198 : uint32 *extended_by);
199 : extern Buffer ExtendBufferedRelTo(ExtendBufferedWhat eb,
200 : ForkNumber fork,
201 : BufferAccessStrategy strategy,
202 : uint32 flags,
203 : BlockNumber extend_to,
204 : ReadBufferMode mode);
205 :
206 : extern void InitBufferPoolAccess(void);
207 : extern void AtEOXact_Buffers(bool isCommit);
208 : extern void PrintBufferLeakWarning(Buffer buffer);
209 : extern void CheckPointBuffers(int flags);
210 : extern BlockNumber BufferGetBlockNumber(Buffer buffer);
211 : extern BlockNumber RelationGetNumberOfBlocksInFork(Relation relation,
212 : ForkNumber forkNum);
213 : extern void FlushOneBuffer(Buffer buffer);
214 : extern void FlushRelationBuffers(Relation rel);
215 : extern void FlushRelationsAllBuffers(struct SMgrRelationData **smgrs, int nrels);
216 : extern void CreateAndCopyRelationData(RelFileLocator src_rlocator,
217 : RelFileLocator dst_rlocator,
218 : bool permanent);
219 : extern void FlushDatabaseBuffers(Oid dbid);
220 : extern void DropRelationBuffers(struct SMgrRelationData *smgr_reln,
221 : ForkNumber *forkNum,
222 : int nforks, BlockNumber *firstDelBlock);
223 : extern void DropRelationsAllBuffers(struct SMgrRelationData **smgr_reln,
224 : int nlocators);
225 : extern void DropDatabaseBuffers(Oid dbid);
226 :
227 : #define RelationGetNumberOfBlocks(reln) \
228 : RelationGetNumberOfBlocksInFork(reln, MAIN_FORKNUM)
229 :
230 : extern bool BufferIsPermanent(Buffer buffer);
231 : extern XLogRecPtr BufferGetLSNAtomic(Buffer buffer);
232 :
233 : #ifdef NOT_USED
234 : extern void PrintPinnedBufs(void);
235 : #endif
236 : extern void BufferGetTag(Buffer buffer, RelFileLocator *rlocator,
237 : ForkNumber *forknum, BlockNumber *blknum);
238 :
239 : extern void MarkBufferDirtyHint(Buffer buffer, bool buffer_std);
240 :
241 : extern void UnlockBuffers(void);
242 : extern void LockBuffer(Buffer buffer, int mode);
243 : extern bool ConditionalLockBuffer(Buffer buffer);
244 : extern void LockBufferForCleanup(Buffer buffer);
245 : extern bool ConditionalLockBufferForCleanup(Buffer buffer);
246 : extern bool IsBufferCleanupOK(Buffer buffer);
247 : extern bool HoldingBufferPinThatDelaysRecovery(void);
248 :
249 : extern void AbortBufferIO(Buffer buffer);
250 :
251 : extern bool BgBufferSync(struct WritebackContext *wb_context);
252 :
253 : extern void TestForOldSnapshot_impl(Snapshot snapshot, Relation relation);
254 :
255 : /* in buf_init.c */
256 : extern void InitBufferPool(void);
257 : extern Size BufferShmemSize(void);
258 :
259 : /* in localbuf.c */
260 : extern void AtProcExit_LocalBuffers(void);
261 :
262 : /* in freelist.c */
263 :
264 : extern BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype);
265 : extern BufferAccessStrategy GetAccessStrategyWithSize(BufferAccessStrategyType btype,
266 : int ring_size_kb);
267 : extern int GetAccessStrategyBufferCount(BufferAccessStrategy strategy);
268 :
269 : extern void FreeAccessStrategy(BufferAccessStrategy strategy);
270 :
271 :
272 : /* inline functions */
273 :
274 : /*
275 : * Although this header file is nominally backend-only, certain frontend
276 : * programs like pg_waldump include it. For compilers that emit static
277 : * inline functions even when they're unused, that leads to unsatisfied
278 : * external references; hence hide these with #ifndef FRONTEND.
279 : */
280 :
281 : #ifndef FRONTEND
282 :
283 : /*
284 : * BufferIsValid
285 : * True iff the given buffer number is valid (either as a shared
286 : * or local buffer).
287 : *
288 : * Note: For a long time this was defined the same as BufferIsPinned,
289 : * that is it would say False if you didn't hold a pin on the buffer.
290 : * I believe this was bogus and served only to mask logic errors.
291 : * Code should always know whether it has a buffer reference,
292 : * independently of the pin state.
293 : *
294 : * Note: For a further long time this was not quite the inverse of the
295 : * BufferIsInvalid() macro, in that it also did sanity checks to verify
296 : * that the buffer number was in range. Most likely, this macro was
297 : * originally intended only to be used in assertions, but its use has
298 : * since expanded quite a bit, and the overhead of making those checks
299 : * even in non-assert-enabled builds can be significant. Thus, we've
300 : * now demoted the range checks to assertions within the macro itself.
301 : */
302 : static inline bool
270 tgl 303 GNC 2446052326 : BufferIsValid(Buffer bufnum)
304 : {
305 2446052326 : Assert(bufnum <= NBuffers);
306 2446052326 : Assert(bufnum >= -NLocBuffer);
307 :
308 2446052326 : return bufnum != InvalidBuffer;
309 : }
310 :
311 : /*
312 : * BufferGetBlock
313 : * Returns a reference to a disk page image associated with a buffer.
314 : *
315 : * Note:
316 : * Assumes buffer is valid.
317 : */
318 : static inline Block
319 474494519 : BufferGetBlock(Buffer buffer)
320 : {
321 474494519 : Assert(BufferIsValid(buffer));
322 :
323 474494519 : if (BufferIsLocal(buffer))
324 11677518 : return LocalBufferBlockPointers[-buffer - 1];
325 : else
326 462817001 : return (Block) (BufferBlocks + ((Size) (buffer - 1)) * BLCKSZ);
327 : }
328 :
329 : /*
330 : * BufferGetPageSize
331 : * Returns the page size within a buffer.
332 : *
333 : * Notes:
334 : * Assumes buffer is valid.
335 : *
336 : * The buffer can be a raw disk block and need not contain a valid
337 : * (formatted) disk page.
338 : */
339 : /* XXX should dig out of buffer descriptor */
340 : static inline Size
341 351238 : BufferGetPageSize(Buffer buffer)
342 : {
343 351238 : AssertMacro(BufferIsValid(buffer));
344 351238 : return (Size) BLCKSZ;
345 : }
346 :
347 : /*
348 : * BufferGetPage
349 : * Returns the page associated with a buffer.
350 : *
351 : * When this is called as part of a scan, there may be a need for a nearby
352 : * call to TestForOldSnapshot(). See the definition of that for details.
353 : */
354 : static inline Page
355 474489397 : BufferGetPage(Buffer buffer)
356 : {
357 474489397 : return (Page) BufferGetBlock(buffer);
358 : }
359 :
360 : /*
361 : * Check whether the given snapshot is too old to have safely read the given
362 : * page from the given table. If so, throw a "snapshot too old" error.
363 : *
364 : * This test generally needs to be performed after every BufferGetPage() call
365 : * that is executed as part of a scan. It is not needed for calls made for
366 : * modifying the page (for example, to position to the right place to insert a
367 : * new index tuple or for vacuuming). It may also be omitted where calls to
368 : * lower-level functions will have already performed the test.
369 : *
370 : * Note that a NULL snapshot argument is allowed and causes a fast return
371 : * without error; this is to support call sites which can be called from
372 : * either scans or index modification areas.
373 : *
374 : * For best performance, keep the tests that are fastest and/or most likely to
375 : * exclude a page from old snapshot testing near the front.
376 : */
377 : static inline void
2544 kgrittn 378 GIC 95507743 : TestForOldSnapshot(Snapshot snapshot, Relation relation, Page page)
379 : {
380 95507743 : Assert(relation != NULL);
381 :
382 95507743 : if (old_snapshot_threshold >= 0
383 10385 : && (snapshot) != NULL
1539 andres 384 10151 : && ((snapshot)->snapshot_type == SNAPSHOT_MVCC
385 1032 : || (snapshot)->snapshot_type == SNAPSHOT_TOAST)
2544 kgrittn 386 9119 : && !XLogRecPtrIsInvalid((snapshot)->lsn)
387 9119 : && PageGetLSN(page) > (snapshot)->lsn)
388 651 : TestForOldSnapshot_impl(snapshot, relation);
389 95507740 : }
390 :
391 : #endif /* FRONTEND */
392 :
393 : #endif /* BUFMGR_H */
|