1/*-------------------------------------------------------------------------
2 *
3 * bufmgr.h
4 * POSTGRES buffer manager definitions.
5 *
6 *
7 * Portions Copyright (c) 1996-2019, 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/relfilenode.h"
21#include "utils/relcache.h"
22#include "utils/snapmgr.h"
23
24typedef void *Block;
25
26/* Possible arguments for GetAccessStrategy() */
27typedef enum BufferAccessStrategyType
28{
29 BAS_NORMAL, /* Normal random access */
30 BAS_BULKREAD, /* Large read-only scan (hint bit updates are
31 * ok) */
32 BAS_BULKWRITE, /* Large multi-block write (e.g. COPY IN) */
33 BAS_VACUUM /* VACUUM */
34} BufferAccessStrategyType;
35
36/* Possible modes for ReadBufferExtended() */
37typedef enum
38{
39 RBM_NORMAL, /* Normal read */
40 RBM_ZERO_AND_LOCK, /* Don't read from disk, caller will
41 * initialize. Also locks the page. */
42 RBM_ZERO_AND_CLEANUP_LOCK, /* Like RBM_ZERO_AND_LOCK, but locks the page
43 * in "cleanup" mode */
44 RBM_ZERO_ON_ERROR, /* Read, but return an all-zeros page on error */
45 RBM_NORMAL_NO_LOG /* Don't log page as invalid during WAL
46 * replay; otherwise same as RBM_NORMAL */
47} ReadBufferMode;
48
49/* forward declared, to avoid having to expose buf_internals.h here */
50struct WritebackContext;
51
52/* in globals.c ... this duplicates miscadmin.h */
53extern PGDLLIMPORT int NBuffers;
54
55/* in bufmgr.c */
56extern bool zero_damaged_pages;
57extern int bgwriter_lru_maxpages;
58extern double bgwriter_lru_multiplier;
59extern bool track_io_timing;
60extern int target_prefetch_pages;
61
62extern int checkpoint_flush_after;
63extern int backend_flush_after;
64extern int bgwriter_flush_after;
65
66/* in buf_init.c */
67extern PGDLLIMPORT char *BufferBlocks;
68
69/* in guc.c */
70extern int effective_io_concurrency;
71
72/* in localbuf.c */
73extern PGDLLIMPORT int NLocBuffer;
74extern PGDLLIMPORT Block *LocalBufferBlockPointers;
75extern PGDLLIMPORT int32 *LocalRefCount;
76
77/* upper limit for effective_io_concurrency */
78#define MAX_IO_CONCURRENCY 1000
79
80/* special block number for ReadBuffer() */
81#define P_NEW InvalidBlockNumber /* grow the file to get a new page */
82
83/*
84 * Buffer content lock modes (mode argument for LockBuffer())
85 */
86#define BUFFER_LOCK_UNLOCK 0
87#define BUFFER_LOCK_SHARE 1
88#define BUFFER_LOCK_EXCLUSIVE 2
89
90/*
91 * These routines are beaten on quite heavily, hence the macroization.
92 */
93
94/*
95 * BufferIsValid
96 * True iff the given buffer number is valid (either as a shared
97 * or local buffer).
98 *
99 * Note: For a long time this was defined the same as BufferIsPinned,
100 * that is it would say False if you didn't hold a pin on the buffer.
101 * I believe this was bogus and served only to mask logic errors.
102 * Code should always know whether it has a buffer reference,
103 * independently of the pin state.
104 *
105 * Note: For a further long time this was not quite the inverse of the
106 * BufferIsInvalid() macro, in that it also did sanity checks to verify
107 * that the buffer number was in range. Most likely, this macro was
108 * originally intended only to be used in assertions, but its use has
109 * since expanded quite a bit, and the overhead of making those checks
110 * even in non-assert-enabled builds can be significant. Thus, we've
111 * now demoted the range checks to assertions within the macro itself.
112 */
113#define BufferIsValid(bufnum) \
114( \
115 AssertMacro((bufnum) <= NBuffers && (bufnum) >= -NLocBuffer), \
116 (bufnum) != InvalidBuffer \
117)
118
119/*
120 * BufferGetBlock
121 * Returns a reference to a disk page image associated with a buffer.
122 *
123 * Note:
124 * Assumes buffer is valid.
125 */
126#define BufferGetBlock(buffer) \
127( \
128 AssertMacro(BufferIsValid(buffer)), \
129 BufferIsLocal(buffer) ? \
130 LocalBufferBlockPointers[-(buffer) - 1] \
131 : \
132 (Block) (BufferBlocks + ((Size) ((buffer) - 1)) * BLCKSZ) \
133)
134
135/*
136 * BufferGetPageSize
137 * Returns the page size within a buffer.
138 *
139 * Notes:
140 * Assumes buffer is valid.
141 *
142 * The buffer can be a raw disk block and need not contain a valid
143 * (formatted) disk page.
144 */
145/* XXX should dig out of buffer descriptor */
146#define BufferGetPageSize(buffer) \
147( \
148 AssertMacro(BufferIsValid(buffer)), \
149 (Size)BLCKSZ \
150)
151
152/*
153 * BufferGetPage
154 * Returns the page associated with a buffer.
155 *
156 * When this is called as part of a scan, there may be a need for a nearby
157 * call to TestForOldSnapshot(). See the definition of that for details.
158 */
159#define BufferGetPage(buffer) ((Page)BufferGetBlock(buffer))
160
161/*
162 * prototypes for functions in bufmgr.c
163 */
164extern bool ComputeIoConcurrency(int io_concurrency, double *target);
165extern void PrefetchBuffer(Relation reln, ForkNumber forkNum,
166 BlockNumber blockNum);
167extern Buffer ReadBuffer(Relation reln, BlockNumber blockNum);
168extern Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum,
169 BlockNumber blockNum, ReadBufferMode mode,
170 BufferAccessStrategy strategy);
171extern Buffer ReadBufferWithoutRelcache(RelFileNode rnode,
172 ForkNumber forkNum, BlockNumber blockNum,
173 ReadBufferMode mode, BufferAccessStrategy strategy);
174extern void ReleaseBuffer(Buffer buffer);
175extern void UnlockReleaseBuffer(Buffer buffer);
176extern void MarkBufferDirty(Buffer buffer);
177extern void IncrBufferRefCount(Buffer buffer);
178extern Buffer ReleaseAndReadBuffer(Buffer buffer, Relation relation,
179 BlockNumber blockNum);
180
181extern void InitBufferPool(void);
182extern void InitBufferPoolAccess(void);
183extern void InitBufferPoolBackend(void);
184extern void AtEOXact_Buffers(bool isCommit);
185extern void PrintBufferLeakWarning(Buffer buffer);
186extern void CheckPointBuffers(int flags);
187extern BlockNumber BufferGetBlockNumber(Buffer buffer);
188extern BlockNumber RelationGetNumberOfBlocksInFork(Relation relation,
189 ForkNumber forkNum);
190extern void FlushOneBuffer(Buffer buffer);
191extern void FlushRelationBuffers(Relation rel);
192extern void FlushDatabaseBuffers(Oid dbid);
193extern void DropRelFileNodeBuffers(RelFileNodeBackend rnode,
194 ForkNumber forkNum, BlockNumber firstDelBlock);
195extern void DropRelFileNodesAllBuffers(RelFileNodeBackend *rnodes, int nnodes);
196extern void DropDatabaseBuffers(Oid dbid);
197
198#define RelationGetNumberOfBlocks(reln) \
199 RelationGetNumberOfBlocksInFork(reln, MAIN_FORKNUM)
200
201extern bool BufferIsPermanent(Buffer buffer);
202extern XLogRecPtr BufferGetLSNAtomic(Buffer buffer);
203
204#ifdef NOT_USED
205extern void PrintPinnedBufs(void);
206#endif
207extern Size BufferShmemSize(void);
208extern void BufferGetTag(Buffer buffer, RelFileNode *rnode,
209 ForkNumber *forknum, BlockNumber *blknum);
210
211extern void MarkBufferDirtyHint(Buffer buffer, bool buffer_std);
212
213extern void UnlockBuffers(void);
214extern void LockBuffer(Buffer buffer, int mode);
215extern bool ConditionalLockBuffer(Buffer buffer);
216extern void LockBufferForCleanup(Buffer buffer);
217extern bool ConditionalLockBufferForCleanup(Buffer buffer);
218extern bool IsBufferCleanupOK(Buffer buffer);
219extern bool HoldingBufferPinThatDelaysRecovery(void);
220
221extern void AbortBufferIO(void);
222
223extern void BufmgrCommit(void);
224extern bool BgBufferSync(struct WritebackContext *wb_context);
225
226extern void AtProcExit_LocalBuffers(void);
227
228extern void TestForOldSnapshot_impl(Snapshot snapshot, Relation relation);
229
230/* in freelist.c */
231extern BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype);
232extern void FreeAccessStrategy(BufferAccessStrategy strategy);
233
234
235/* inline functions */
236
237/*
238 * Although this header file is nominally backend-only, certain frontend
239 * programs like pg_waldump include it. For compilers that emit static
240 * inline functions even when they're unused, that leads to unsatisfied
241 * external references; hence hide these with #ifndef FRONTEND.
242 */
243
244#ifndef FRONTEND
245
246/*
247 * Check whether the given snapshot is too old to have safely read the given
248 * page from the given table. If so, throw a "snapshot too old" error.
249 *
250 * This test generally needs to be performed after every BufferGetPage() call
251 * that is executed as part of a scan. It is not needed for calls made for
252 * modifying the page (for example, to position to the right place to insert a
253 * new index tuple or for vacuuming). It may also be omitted where calls to
254 * lower-level functions will have already performed the test.
255 *
256 * Note that a NULL snapshot argument is allowed and causes a fast return
257 * without error; this is to support call sites which can be called from
258 * either scans or index modification areas.
259 *
260 * For best performance, keep the tests that are fastest and/or most likely to
261 * exclude a page from old snapshot testing near the front.
262 */
263static inline void
264TestForOldSnapshot(Snapshot snapshot, Relation relation, Page page)
265{
266 Assert(relation != NULL);
267
268 if (old_snapshot_threshold >= 0
269 && (snapshot) != NULL
270 && ((snapshot)->snapshot_type == SNAPSHOT_MVCC
271 || (snapshot)->snapshot_type == SNAPSHOT_TOAST)
272 && !XLogRecPtrIsInvalid((snapshot)->lsn)
273 && PageGetLSN(page) > (snapshot)->lsn)
274 TestForOldSnapshot_impl(snapshot, relation);
275}
276
277#endif /* FRONTEND */
278
279#endif /* BUFMGR_H */
280