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