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 | |
24 | typedef void *Block; |
25 | |
26 | /* Possible arguments for GetAccessStrategy() */ |
27 | typedef 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() */ |
37 | typedef 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 */ |
50 | struct WritebackContext; |
51 | |
52 | /* in globals.c ... this duplicates miscadmin.h */ |
53 | extern PGDLLIMPORT int NBuffers; |
54 | |
55 | /* in bufmgr.c */ |
56 | extern bool zero_damaged_pages; |
57 | extern int bgwriter_lru_maxpages; |
58 | extern double bgwriter_lru_multiplier; |
59 | extern bool track_io_timing; |
60 | extern int target_prefetch_pages; |
61 | |
62 | extern int checkpoint_flush_after; |
63 | extern int backend_flush_after; |
64 | extern int bgwriter_flush_after; |
65 | |
66 | /* in buf_init.c */ |
67 | extern PGDLLIMPORT char *BufferBlocks; |
68 | |
69 | /* in guc.c */ |
70 | extern int effective_io_concurrency; |
71 | |
72 | /* in localbuf.c */ |
73 | extern PGDLLIMPORT int NLocBuffer; |
74 | extern PGDLLIMPORT Block *LocalBufferBlockPointers; |
75 | extern 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 | */ |
164 | extern bool ComputeIoConcurrency(int io_concurrency, double *target); |
165 | extern void PrefetchBuffer(Relation reln, ForkNumber forkNum, |
166 | BlockNumber blockNum); |
167 | extern Buffer ReadBuffer(Relation reln, BlockNumber blockNum); |
168 | extern Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, |
169 | BlockNumber blockNum, ReadBufferMode mode, |
170 | BufferAccessStrategy strategy); |
171 | extern Buffer ReadBufferWithoutRelcache(RelFileNode rnode, |
172 | ForkNumber forkNum, BlockNumber blockNum, |
173 | ReadBufferMode mode, BufferAccessStrategy strategy); |
174 | extern void ReleaseBuffer(Buffer buffer); |
175 | extern void UnlockReleaseBuffer(Buffer buffer); |
176 | extern void MarkBufferDirty(Buffer buffer); |
177 | extern void IncrBufferRefCount(Buffer buffer); |
178 | extern Buffer ReleaseAndReadBuffer(Buffer buffer, Relation relation, |
179 | BlockNumber blockNum); |
180 | |
181 | extern void InitBufferPool(void); |
182 | extern void InitBufferPoolAccess(void); |
183 | extern void InitBufferPoolBackend(void); |
184 | extern void AtEOXact_Buffers(bool isCommit); |
185 | extern void PrintBufferLeakWarning(Buffer buffer); |
186 | extern void CheckPointBuffers(int flags); |
187 | extern BlockNumber BufferGetBlockNumber(Buffer buffer); |
188 | extern BlockNumber RelationGetNumberOfBlocksInFork(Relation relation, |
189 | ForkNumber forkNum); |
190 | extern void FlushOneBuffer(Buffer buffer); |
191 | extern void FlushRelationBuffers(Relation rel); |
192 | extern void FlushDatabaseBuffers(Oid dbid); |
193 | extern void DropRelFileNodeBuffers(RelFileNodeBackend rnode, |
194 | ForkNumber forkNum, BlockNumber firstDelBlock); |
195 | extern void DropRelFileNodesAllBuffers(RelFileNodeBackend *rnodes, int nnodes); |
196 | extern void DropDatabaseBuffers(Oid dbid); |
197 | |
198 | #define RelationGetNumberOfBlocks(reln) \ |
199 | RelationGetNumberOfBlocksInFork(reln, MAIN_FORKNUM) |
200 | |
201 | extern bool BufferIsPermanent(Buffer buffer); |
202 | extern XLogRecPtr BufferGetLSNAtomic(Buffer buffer); |
203 | |
204 | #ifdef NOT_USED |
205 | extern void PrintPinnedBufs(void); |
206 | #endif |
207 | extern Size BufferShmemSize(void); |
208 | extern void BufferGetTag(Buffer buffer, RelFileNode *rnode, |
209 | ForkNumber *forknum, BlockNumber *blknum); |
210 | |
211 | extern void MarkBufferDirtyHint(Buffer buffer, bool buffer_std); |
212 | |
213 | extern void UnlockBuffers(void); |
214 | extern void LockBuffer(Buffer buffer, int mode); |
215 | extern bool ConditionalLockBuffer(Buffer buffer); |
216 | extern void LockBufferForCleanup(Buffer buffer); |
217 | extern bool ConditionalLockBufferForCleanup(Buffer buffer); |
218 | extern bool IsBufferCleanupOK(Buffer buffer); |
219 | extern bool HoldingBufferPinThatDelaysRecovery(void); |
220 | |
221 | extern void AbortBufferIO(void); |
222 | |
223 | extern void BufmgrCommit(void); |
224 | extern bool BgBufferSync(struct WritebackContext *wb_context); |
225 | |
226 | extern void AtProcExit_LocalBuffers(void); |
227 | |
228 | extern void TestForOldSnapshot_impl(Snapshot snapshot, Relation relation); |
229 | |
230 | /* in freelist.c */ |
231 | extern BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype); |
232 | extern 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 | */ |
263 | static inline void |
264 | TestForOldSnapshot(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 | |