codekingpro/portable-devtools
115k
1/*-------------------------------------------------------------------------2 *3 * bufmgr.h4 * POSTGRES buffer manager definitions.5 *6 *7 * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group8 * Portions Copyright (c) 1994, Regents of the University of California9 *10 * src/include/storage/bufmgr.h11 *12 *-------------------------------------------------------------------------13 */14#ifndef BUFMGR_H15#define BUFMGR_H16 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 24typedef void *Block;25 26/*27 * Possible arguments for GetAccessStrategy().28 *29 * If adding a new BufferAccessStrategyType, also add a new IOContext so30 * IO statistics using this strategy are tracked.31 */32typedef enum BufferAccessStrategyType33{34 BAS_NORMAL, /* Normal random access */35 BAS_BULKREAD, /* Large read-only scan (hint bit updates are36 * ok) */37 BAS_BULKWRITE, /* Large multi-block write (e.g. COPY IN) */38 BAS_VACUUM /* VACUUM */39} BufferAccessStrategyType;40 41/* Possible modes for ReadBufferExtended() */42typedef enum43{44 RBM_NORMAL, /* Normal read */45 RBM_ZERO_AND_LOCK, /* Don't read from disk, caller will46 * initialize. Also locks the page. */47 RBM_ZERO_AND_CLEANUP_LOCK, /* Like RBM_ZERO_AND_LOCK, but locks the page48 * 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 WAL51 * replay; otherwise same as RBM_NORMAL */52} ReadBufferMode;53 54/*55 * Type returned by PrefetchBuffer().56 */57typedef struct PrefetchBufferResult58{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 */66typedef enum ExtendBufferedFlags67{68 /*69 * Don't acquire extension lock. This is safe only if the relation isn't70 * shared, an access exclusive lock is held or if this is the startup71 * 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 likely80 * 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 * Some functions identify relations either by relation or smgr +96 * relpersistence. Used via the BMR_REL()/BMR_SMGR() macros below. This97 * allows us to use the same function for both recovery and normal operation.98 */99typedef struct BufferManagerRelation100{101 Relation rel;102 struct SMgrRelationData *smgr;103 char relpersistence;104} BufferManagerRelation;105 106#define BMR_REL(p_rel) ((BufferManagerRelation){.rel = p_rel})107#define BMR_SMGR(p_smgr, p_relpersistence) ((BufferManagerRelation){.smgr = p_smgr, .relpersistence = p_relpersistence})108 109 110/* forward declared, to avoid having to expose buf_internals.h here */111struct WritebackContext;112 113/* forward declared, to avoid including smgr.h here */114struct SMgrRelationData;115 116/* in globals.c ... this duplicates miscadmin.h */117extern PGDLLIMPORT int NBuffers;118 119/* in bufmgr.c */120extern PGDLLIMPORT bool zero_damaged_pages;121extern PGDLLIMPORT int bgwriter_lru_maxpages;122extern PGDLLIMPORT double bgwriter_lru_multiplier;123extern PGDLLIMPORT bool track_io_timing;124 125/* only applicable when prefetching is available */126#ifdef USE_PREFETCH127#define DEFAULT_EFFECTIVE_IO_CONCURRENCY 1128#define DEFAULT_MAINTENANCE_IO_CONCURRENCY 10129#else130#define DEFAULT_EFFECTIVE_IO_CONCURRENCY 0131#define DEFAULT_MAINTENANCE_IO_CONCURRENCY 0132#endif133extern PGDLLIMPORT int effective_io_concurrency;134extern PGDLLIMPORT int maintenance_io_concurrency;135 136extern PGDLLIMPORT int checkpoint_flush_after;137extern PGDLLIMPORT int backend_flush_after;138extern PGDLLIMPORT int bgwriter_flush_after;139 140/* in buf_init.c */141extern PGDLLIMPORT char *BufferBlocks;142 143/* in localbuf.c */144extern PGDLLIMPORT int NLocBuffer;145extern PGDLLIMPORT Block *LocalBufferBlockPointers;146extern PGDLLIMPORT int32 *LocalRefCount;147 148/* upper limit for effective_io_concurrency */149#define MAX_IO_CONCURRENCY 1000150 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 0158#define BUFFER_LOCK_SHARE 1159#define BUFFER_LOCK_EXCLUSIVE 2160 161 162/*163 * prototypes for functions in bufmgr.c164 */165extern PrefetchBufferResult PrefetchSharedBuffer(struct SMgrRelationData *smgr_reln,166 ForkNumber forkNum,167 BlockNumber blockNum);168extern PrefetchBufferResult PrefetchBuffer(Relation reln, ForkNumber forkNum,169 BlockNumber blockNum);170extern bool ReadRecentBuffer(RelFileLocator rlocator, ForkNumber forkNum,171 BlockNumber blockNum, Buffer recent_buffer);172extern Buffer ReadBuffer(Relation reln, BlockNumber blockNum);173extern Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum,174 BlockNumber blockNum, ReadBufferMode mode,175 BufferAccessStrategy strategy);176extern Buffer ReadBufferWithoutRelcache(RelFileLocator rlocator,177 ForkNumber forkNum, BlockNumber blockNum,178 ReadBufferMode mode, BufferAccessStrategy strategy,179 bool permanent);180extern void ReleaseBuffer(Buffer buffer);181extern void UnlockReleaseBuffer(Buffer buffer);182extern void MarkBufferDirty(Buffer buffer);183extern void IncrBufferRefCount(Buffer buffer);184extern void CheckBufferIsPinnedOnce(Buffer buffer);185extern Buffer ReleaseAndReadBuffer(Buffer buffer, Relation relation,186 BlockNumber blockNum);187 188extern Buffer ExtendBufferedRel(BufferManagerRelation bmr,189 ForkNumber forkNum,190 BufferAccessStrategy strategy,191 uint32 flags);192extern BlockNumber ExtendBufferedRelBy(BufferManagerRelation bmr,193 ForkNumber fork,194 BufferAccessStrategy strategy,195 uint32 flags,196 uint32 extend_by,197 Buffer *buffers,198 uint32 *extended_by);199extern Buffer ExtendBufferedRelTo(BufferManagerRelation bmr,200 ForkNumber fork,201 BufferAccessStrategy strategy,202 uint32 flags,203 BlockNumber extend_to,204 ReadBufferMode mode);205 206extern void InitBufferPoolAccess(void);207extern void AtEOXact_Buffers(bool isCommit);208extern void PrintBufferLeakWarning(Buffer buffer);209extern void CheckPointBuffers(int flags);210extern BlockNumber BufferGetBlockNumber(Buffer buffer);211extern BlockNumber RelationGetNumberOfBlocksInFork(Relation relation,212 ForkNumber forkNum);213extern void FlushOneBuffer(Buffer buffer);214extern void FlushRelationBuffers(Relation rel);215extern void FlushRelationsAllBuffers(struct SMgrRelationData **smgrs, int nrels);216extern void CreateAndCopyRelationData(RelFileLocator src_rlocator,217 RelFileLocator dst_rlocator,218 bool permanent);219extern void FlushDatabaseBuffers(Oid dbid);220extern void DropRelationBuffers(struct SMgrRelationData *smgr_reln,221 ForkNumber *forkNum,222 int nforks, BlockNumber *firstDelBlock);223extern void DropRelationsAllBuffers(struct SMgrRelationData **smgr_reln,224 int nlocators);225extern void DropDatabaseBuffers(Oid dbid);226 227#define RelationGetNumberOfBlocks(reln) \228 RelationGetNumberOfBlocksInFork(reln, MAIN_FORKNUM)229 230extern bool BufferIsPermanent(Buffer buffer);231extern XLogRecPtr BufferGetLSNAtomic(Buffer buffer);232 233#ifdef NOT_USED234extern void PrintPinnedBufs(void);235#endif236extern void BufferGetTag(Buffer buffer, RelFileLocator *rlocator,237 ForkNumber *forknum, BlockNumber *blknum);238 239extern void MarkBufferDirtyHint(Buffer buffer, bool buffer_std);240 241extern void UnlockBuffers(void);242extern void LockBuffer(Buffer buffer, int mode);243extern bool ConditionalLockBuffer(Buffer buffer);244extern void LockBufferForCleanup(Buffer buffer);245extern bool ConditionalLockBufferForCleanup(Buffer buffer);246extern bool IsBufferCleanupOK(Buffer buffer);247extern bool HoldingBufferPinThatDelaysRecovery(void);248 249extern void AbortBufferIO(Buffer buffer);250 251extern bool BgBufferSync(struct WritebackContext *wb_context);252 253extern void TestForOldSnapshot_impl(Snapshot snapshot, Relation relation);254 255/* in buf_init.c */256extern void InitBufferPool(void);257extern Size BufferShmemSize(void);258 259/* in localbuf.c */260extern void AtProcExit_LocalBuffers(void);261 262/* in freelist.c */263 264extern BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype);265extern BufferAccessStrategy GetAccessStrategyWithSize(BufferAccessStrategyType btype,266 int ring_size_kb);267extern int GetAccessStrategyBufferCount(BufferAccessStrategy strategy);268 269extern void FreeAccessStrategy(BufferAccessStrategy strategy);270 271 272/* inline functions */273 274/*275 * Although this header file is nominally backend-only, certain frontend276 * programs like pg_waldump include it. For compilers that emit static277 * inline functions even when they're unused, that leads to unsatisfied278 * external references; hence hide these with #ifndef FRONTEND.279 */280 281#ifndef FRONTEND282 283/*284 * BufferIsValid285 * True iff the given buffer number is valid (either as a shared286 * 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 the295 * BufferIsInvalid() macro, in that it also did sanity checks to verify296 * that the buffer number was in range. Most likely, this macro was297 * originally intended only to be used in assertions, but its use has298 * since expanded quite a bit, and the overhead of making those checks299 * even in non-assert-enabled builds can be significant. Thus, we've300 * now demoted the range checks to assertions within the macro itself.301 */302static inline bool303BufferIsValid(Buffer bufnum)304{305 Assert(bufnum <= NBuffers);306 Assert(bufnum >= -NLocBuffer);307 308 return bufnum != InvalidBuffer;309}310 311/*312 * BufferGetBlock313 * Returns a reference to a disk page image associated with a buffer.314 *315 * Note:316 * Assumes buffer is valid.317 */318static inline Block319BufferGetBlock(Buffer buffer)320{321 Assert(BufferIsValid(buffer));322 323 if (BufferIsLocal(buffer))324 return LocalBufferBlockPointers[-buffer - 1];325 else326 return (Block) (BufferBlocks + ((Size) (buffer - 1)) * BLCKSZ);327}328 329/*330 * BufferGetPageSize331 * 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 valid337 * (formatted) disk page.338 */339/* XXX should dig out of buffer descriptor */340static inline Size341BufferGetPageSize(Buffer buffer)342{343 AssertMacro(BufferIsValid(buffer));344 return (Size) BLCKSZ;345}346 347/*348 * BufferGetPage349 * 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 nearby352 * call to TestForOldSnapshot(). See the definition of that for details.353 */354static inline Page355BufferGetPage(Buffer buffer)356{357 return (Page) BufferGetBlock(buffer);358}359 360/*361 * Check whether the given snapshot is too old to have safely read the given362 * 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() call365 * that is executed as part of a scan. It is not needed for calls made for366 * modifying the page (for example, to position to the right place to insert a367 * new index tuple or for vacuuming). It may also be omitted where calls to368 * lower-level functions will have already performed the test.369 *370 * Note that a NULL snapshot argument is allowed and causes a fast return371 * without error; this is to support call sites which can be called from372 * either scans or index modification areas.373 *374 * For best performance, keep the tests that are fastest and/or most likely to375 * exclude a page from old snapshot testing near the front.376 */377static inline void378TestForOldSnapshot(Snapshot snapshot, Relation relation, Page page)379{380 Assert(relation != NULL);381 382 if (old_snapshot_threshold >= 0383 && (snapshot) != NULL384 && ((snapshot)->snapshot_type == SNAPSHOT_MVCC385 || (snapshot)->snapshot_type == SNAPSHOT_TOAST)386 && !XLogRecPtrIsInvalid((snapshot)->lsn)387 && PageGetLSN(page) > (snapshot)->lsn)388 TestForOldSnapshot_impl(snapshot, relation);389}390 391#endif /* FRONTEND */392 393#endif /* BUFMGR_H */394 