LCOV - differential code coverage report
Current view: top level - src/include/storage - bufmgr.h (source / functions) Coverage Total Hit GIC GNC ECB
Current: Differential Code Coverage HEAD vs 15 Lines: 100.0 % 24 24 10 14 24
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 5 5 1 4 5
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * bufmgr.h
       4                 :  *    POSTGRES buffer manager definitions.
       5                 :  *
       6                 :  *
       7                 :  * Portions Copyright (c) 1996-2023, 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/relfilelocator.h"
      21                 : #include "utils/relcache.h"
      22                 : #include "utils/snapmgr.h"
      23                 : 
      24                 : typedef void *Block;
      25                 : 
      26                 : /*
      27                 :  * Possible arguments for GetAccessStrategy().
      28                 :  *
      29                 :  * If adding a new BufferAccessStrategyType, also add a new IOContext so
      30                 :  * IO statistics using this strategy are tracked.
      31                 :  */
      32                 : typedef enum BufferAccessStrategyType
      33                 : {
      34                 :     BAS_NORMAL,                 /* Normal random access */
      35                 :     BAS_BULKREAD,               /* Large read-only scan (hint bit updates are
      36                 :                                  * ok) */
      37                 :     BAS_BULKWRITE,              /* Large multi-block write (e.g. COPY IN) */
      38                 :     BAS_VACUUM                  /* VACUUM */
      39                 : } BufferAccessStrategyType;
      40                 : 
      41                 : /* Possible modes for ReadBufferExtended() */
      42                 : typedef enum
      43                 : {
      44                 :     RBM_NORMAL,                 /* Normal read */
      45                 :     RBM_ZERO_AND_LOCK,          /* Don't read from disk, caller will
      46                 :                                  * initialize. Also locks the page. */
      47                 :     RBM_ZERO_AND_CLEANUP_LOCK,  /* Like RBM_ZERO_AND_LOCK, but locks the page
      48                 :                                  * 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 WAL
      51                 :                                  * replay; otherwise same as RBM_NORMAL */
      52                 : } ReadBufferMode;
      53                 : 
      54                 : /*
      55                 :  * Type returned by PrefetchBuffer().
      56                 :  */
      57                 : typedef struct PrefetchBufferResult
      58                 : {
      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                 :  */
      66                 : typedef enum ExtendBufferedFlags
      67                 : {
      68                 :     /*
      69                 :      * Don't acquire extension lock. This is safe only if the relation isn't
      70                 :      * shared, an access exclusive lock is held or if this is the startup
      71                 :      * 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 likely
      80                 :      * 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                 :  * To identify the relation - either relation or smgr + relpersistence has to
      96                 :  * be specified. Used via the EB_REL()/EB_SMGR() macros below. This allows us
      97                 :  * to use the same function for both crash recovery and normal operation.
      98                 :  */
      99                 : typedef struct ExtendBufferedWhat
     100                 : {
     101                 :     Relation    rel;
     102                 :     struct SMgrRelationData *smgr;
     103                 :     char        relpersistence;
     104                 : } ExtendBufferedWhat;
     105                 : 
     106                 : #define EB_REL(p_rel) ((ExtendBufferedWhat){.rel = p_rel})
     107                 : #define EB_SMGR(p_smgr, p_relpersistence) ((ExtendBufferedWhat){.smgr = p_smgr, .relpersistence = p_relpersistence})
     108                 : 
     109                 : 
     110                 : /* forward declared, to avoid having to expose buf_internals.h here */
     111                 : struct WritebackContext;
     112                 : 
     113                 : /* forward declared, to avoid including smgr.h here */
     114                 : struct SMgrRelationData;
     115                 : 
     116                 : /* in globals.c ... this duplicates miscadmin.h */
     117                 : extern PGDLLIMPORT int NBuffers;
     118                 : 
     119                 : /* in bufmgr.c */
     120                 : extern PGDLLIMPORT bool zero_damaged_pages;
     121                 : extern PGDLLIMPORT int bgwriter_lru_maxpages;
     122                 : extern PGDLLIMPORT double bgwriter_lru_multiplier;
     123                 : extern PGDLLIMPORT bool track_io_timing;
     124                 : 
     125                 : /* only applicable when prefetching is available */
     126                 : #ifdef USE_PREFETCH
     127                 : #define DEFAULT_EFFECTIVE_IO_CONCURRENCY 1
     128                 : #define DEFAULT_MAINTENANCE_IO_CONCURRENCY 10
     129                 : #else
     130                 : #define DEFAULT_EFFECTIVE_IO_CONCURRENCY 0
     131                 : #define DEFAULT_MAINTENANCE_IO_CONCURRENCY 0
     132                 : #endif
     133                 : extern PGDLLIMPORT int effective_io_concurrency;
     134                 : extern PGDLLIMPORT int maintenance_io_concurrency;
     135                 : 
     136                 : extern PGDLLIMPORT int checkpoint_flush_after;
     137                 : extern PGDLLIMPORT int backend_flush_after;
     138                 : extern PGDLLIMPORT int bgwriter_flush_after;
     139                 : 
     140                 : /* in buf_init.c */
     141                 : extern PGDLLIMPORT char *BufferBlocks;
     142                 : 
     143                 : /* in localbuf.c */
     144                 : extern PGDLLIMPORT int NLocBuffer;
     145                 : extern PGDLLIMPORT Block *LocalBufferBlockPointers;
     146                 : extern PGDLLIMPORT int32 *LocalRefCount;
     147                 : 
     148                 : /* upper limit for effective_io_concurrency */
     149                 : #define MAX_IO_CONCURRENCY 1000
     150                 : 
     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      0
     158                 : #define BUFFER_LOCK_SHARE       1
     159                 : #define BUFFER_LOCK_EXCLUSIVE   2
     160                 : 
     161                 : 
     162                 : /*
     163                 :  * prototypes for functions in bufmgr.c
     164                 :  */
     165                 : extern PrefetchBufferResult PrefetchSharedBuffer(struct SMgrRelationData *smgr_reln,
     166                 :                                                  ForkNumber forkNum,
     167                 :                                                  BlockNumber blockNum);
     168                 : extern PrefetchBufferResult PrefetchBuffer(Relation reln, ForkNumber forkNum,
     169                 :                                            BlockNumber blockNum);
     170                 : extern bool ReadRecentBuffer(RelFileLocator rlocator, ForkNumber forkNum,
     171                 :                              BlockNumber blockNum, Buffer recent_buffer);
     172                 : extern Buffer ReadBuffer(Relation reln, BlockNumber blockNum);
     173                 : extern Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum,
     174                 :                                  BlockNumber blockNum, ReadBufferMode mode,
     175                 :                                  BufferAccessStrategy strategy);
     176                 : extern Buffer ReadBufferWithoutRelcache(RelFileLocator rlocator,
     177                 :                                         ForkNumber forkNum, BlockNumber blockNum,
     178                 :                                         ReadBufferMode mode, BufferAccessStrategy strategy,
     179                 :                                         bool permanent);
     180                 : extern void ReleaseBuffer(Buffer buffer);
     181                 : extern void UnlockReleaseBuffer(Buffer buffer);
     182                 : extern void MarkBufferDirty(Buffer buffer);
     183                 : extern void IncrBufferRefCount(Buffer buffer);
     184                 : extern void CheckBufferIsPinnedOnce(Buffer buffer);
     185                 : extern Buffer ReleaseAndReadBuffer(Buffer buffer, Relation relation,
     186                 :                                    BlockNumber blockNum);
     187                 : 
     188                 : extern Buffer ExtendBufferedRel(ExtendBufferedWhat eb,
     189                 :                                 ForkNumber forkNum,
     190                 :                                 BufferAccessStrategy strategy,
     191                 :                                 uint32 flags);
     192                 : extern BlockNumber ExtendBufferedRelBy(ExtendBufferedWhat eb,
     193                 :                                        ForkNumber fork,
     194                 :                                        BufferAccessStrategy strategy,
     195                 :                                        uint32 flags,
     196                 :                                        uint32 extend_by,
     197                 :                                        Buffer *buffers,
     198                 :                                        uint32 *extended_by);
     199                 : extern Buffer ExtendBufferedRelTo(ExtendBufferedWhat eb,
     200                 :                                   ForkNumber fork,
     201                 :                                   BufferAccessStrategy strategy,
     202                 :                                   uint32 flags,
     203                 :                                   BlockNumber extend_to,
     204                 :                                   ReadBufferMode mode);
     205                 : 
     206                 : extern void InitBufferPoolAccess(void);
     207                 : extern void AtEOXact_Buffers(bool isCommit);
     208                 : extern void PrintBufferLeakWarning(Buffer buffer);
     209                 : extern void CheckPointBuffers(int flags);
     210                 : extern BlockNumber BufferGetBlockNumber(Buffer buffer);
     211                 : extern BlockNumber RelationGetNumberOfBlocksInFork(Relation relation,
     212                 :                                                    ForkNumber forkNum);
     213                 : extern void FlushOneBuffer(Buffer buffer);
     214                 : extern void FlushRelationBuffers(Relation rel);
     215                 : extern void FlushRelationsAllBuffers(struct SMgrRelationData **smgrs, int nrels);
     216                 : extern void CreateAndCopyRelationData(RelFileLocator src_rlocator,
     217                 :                                       RelFileLocator dst_rlocator,
     218                 :                                       bool permanent);
     219                 : extern void FlushDatabaseBuffers(Oid dbid);
     220                 : extern void DropRelationBuffers(struct SMgrRelationData *smgr_reln,
     221                 :                                 ForkNumber *forkNum,
     222                 :                                 int nforks, BlockNumber *firstDelBlock);
     223                 : extern void DropRelationsAllBuffers(struct SMgrRelationData **smgr_reln,
     224                 :                                     int nlocators);
     225                 : extern void DropDatabaseBuffers(Oid dbid);
     226                 : 
     227                 : #define RelationGetNumberOfBlocks(reln) \
     228                 :     RelationGetNumberOfBlocksInFork(reln, MAIN_FORKNUM)
     229                 : 
     230                 : extern bool BufferIsPermanent(Buffer buffer);
     231                 : extern XLogRecPtr BufferGetLSNAtomic(Buffer buffer);
     232                 : 
     233                 : #ifdef NOT_USED
     234                 : extern void PrintPinnedBufs(void);
     235                 : #endif
     236                 : extern void BufferGetTag(Buffer buffer, RelFileLocator *rlocator,
     237                 :                          ForkNumber *forknum, BlockNumber *blknum);
     238                 : 
     239                 : extern void MarkBufferDirtyHint(Buffer buffer, bool buffer_std);
     240                 : 
     241                 : extern void UnlockBuffers(void);
     242                 : extern void LockBuffer(Buffer buffer, int mode);
     243                 : extern bool ConditionalLockBuffer(Buffer buffer);
     244                 : extern void LockBufferForCleanup(Buffer buffer);
     245                 : extern bool ConditionalLockBufferForCleanup(Buffer buffer);
     246                 : extern bool IsBufferCleanupOK(Buffer buffer);
     247                 : extern bool HoldingBufferPinThatDelaysRecovery(void);
     248                 : 
     249                 : extern void AbortBufferIO(Buffer buffer);
     250                 : 
     251                 : extern bool BgBufferSync(struct WritebackContext *wb_context);
     252                 : 
     253                 : extern void TestForOldSnapshot_impl(Snapshot snapshot, Relation relation);
     254                 : 
     255                 : /* in buf_init.c */
     256                 : extern void InitBufferPool(void);
     257                 : extern Size BufferShmemSize(void);
     258                 : 
     259                 : /* in localbuf.c */
     260                 : extern void AtProcExit_LocalBuffers(void);
     261                 : 
     262                 : /* in freelist.c */
     263                 : 
     264                 : extern BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype);
     265                 : extern BufferAccessStrategy GetAccessStrategyWithSize(BufferAccessStrategyType btype,
     266                 :                                                       int ring_size_kb);
     267                 : extern int  GetAccessStrategyBufferCount(BufferAccessStrategy strategy);
     268                 : 
     269                 : extern void FreeAccessStrategy(BufferAccessStrategy strategy);
     270                 : 
     271                 : 
     272                 : /* inline functions */
     273                 : 
     274                 : /*
     275                 :  * Although this header file is nominally backend-only, certain frontend
     276                 :  * programs like pg_waldump include it.  For compilers that emit static
     277                 :  * inline functions even when they're unused, that leads to unsatisfied
     278                 :  * external references; hence hide these with #ifndef FRONTEND.
     279                 :  */
     280                 : 
     281                 : #ifndef FRONTEND
     282                 : 
     283                 : /*
     284                 :  * BufferIsValid
     285                 :  *      True iff the given buffer number is valid (either as a shared
     286                 :  *      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 the
     295                 :  * BufferIsInvalid() macro, in that it also did sanity checks to verify
     296                 :  * that the buffer number was in range.  Most likely, this macro was
     297                 :  * originally intended only to be used in assertions, but its use has
     298                 :  * since expanded quite a bit, and the overhead of making those checks
     299                 :  * even in non-assert-enabled builds can be significant.  Thus, we've
     300                 :  * now demoted the range checks to assertions within the macro itself.
     301                 :  */
     302                 : static inline bool
     303 GNC  2446052326 : BufferIsValid(Buffer bufnum)
     304                 : {
     305      2446052326 :     Assert(bufnum <= NBuffers);
     306      2446052326 :     Assert(bufnum >= -NLocBuffer);
     307                 : 
     308      2446052326 :     return bufnum != InvalidBuffer;
     309                 : }
     310                 : 
     311                 : /*
     312                 :  * BufferGetBlock
     313                 :  *      Returns a reference to a disk page image associated with a buffer.
     314                 :  *
     315                 :  * Note:
     316                 :  *      Assumes buffer is valid.
     317                 :  */
     318                 : static inline Block
     319       474494519 : BufferGetBlock(Buffer buffer)
     320                 : {
     321       474494519 :     Assert(BufferIsValid(buffer));
     322                 : 
     323       474494519 :     if (BufferIsLocal(buffer))
     324        11677518 :         return LocalBufferBlockPointers[-buffer - 1];
     325                 :     else
     326       462817001 :         return (Block) (BufferBlocks + ((Size) (buffer - 1)) * BLCKSZ);
     327                 : }
     328                 : 
     329                 : /*
     330                 :  * BufferGetPageSize
     331                 :  *      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 valid
     337                 :  *      (formatted) disk page.
     338                 :  */
     339                 : /* XXX should dig out of buffer descriptor */
     340                 : static inline Size
     341          351238 : BufferGetPageSize(Buffer buffer)
     342                 : {
     343          351238 :     AssertMacro(BufferIsValid(buffer));
     344          351238 :     return (Size) BLCKSZ;
     345                 : }
     346                 : 
     347                 : /*
     348                 :  * BufferGetPage
     349                 :  *      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 nearby
     352                 :  * call to TestForOldSnapshot().  See the definition of that for details.
     353                 :  */
     354                 : static inline Page
     355       474489397 : BufferGetPage(Buffer buffer)
     356                 : {
     357       474489397 :     return (Page) BufferGetBlock(buffer);
     358                 : }
     359                 : 
     360                 : /*
     361                 :  * Check whether the given snapshot is too old to have safely read the given
     362                 :  * 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() call
     365                 :  * that is executed as part of a scan.  It is not needed for calls made for
     366                 :  * modifying the page (for example, to position to the right place to insert a
     367                 :  * new index tuple or for vacuuming).  It may also be omitted where calls to
     368                 :  * lower-level functions will have already performed the test.
     369                 :  *
     370                 :  * Note that a NULL snapshot argument is allowed and causes a fast return
     371                 :  * without error; this is to support call sites which can be called from
     372                 :  * either scans or index modification areas.
     373                 :  *
     374                 :  * For best performance, keep the tests that are fastest and/or most likely to
     375                 :  * exclude a page from old snapshot testing near the front.
     376                 :  */
     377                 : static inline void
     378 GIC    95507743 : TestForOldSnapshot(Snapshot snapshot, Relation relation, Page page)
     379                 : {
     380        95507743 :     Assert(relation != NULL);
     381                 : 
     382        95507743 :     if (old_snapshot_threshold >= 0
     383           10385 :         && (snapshot) != NULL
     384           10151 :         && ((snapshot)->snapshot_type == SNAPSHOT_MVCC
     385            1032 :             || (snapshot)->snapshot_type == SNAPSHOT_TOAST)
     386            9119 :         && !XLogRecPtrIsInvalid((snapshot)->lsn)
     387            9119 :         && PageGetLSN(page) > (snapshot)->lsn)
     388             651 :         TestForOldSnapshot_impl(snapshot, relation);
     389        95507740 : }
     390                 : 
     391                 : #endif                          /* FRONTEND */
     392                 : 
     393                 : #endif                          /* BUFMGR_H */
        

Generated by: LCOV version v1.16-55-g56c0a2a