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