LCOV - code coverage report
Current view: top level - src/backend/storage/buffer - buf_table.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 95.5 % 22 21
Test Date: 2026-07-03 19:57:34 Functions: 100.0 % 5 5
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 62.5 % 8 5

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * buf_table.c
       4                 :             :  *    routines for mapping BufferTags to buffer indexes.
       5                 :             :  *
       6                 :             :  * Note: the routines in this file do no locking of their own.  The caller
       7                 :             :  * must hold a suitable lock on the appropriate BufMappingLock, as specified
       8                 :             :  * in the comments.  We can't do the locking inside these functions because
       9                 :             :  * in most cases the caller needs to adjust the buffer header contents
      10                 :             :  * before the lock is released (see notes in README).
      11                 :             :  *
      12                 :             :  *
      13                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
      14                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
      15                 :             :  *
      16                 :             :  *
      17                 :             :  * IDENTIFICATION
      18                 :             :  *    src/backend/storage/buffer/buf_table.c
      19                 :             :  *
      20                 :             :  *-------------------------------------------------------------------------
      21                 :             :  */
      22                 :             : #include "postgres.h"
      23                 :             : 
      24                 :             : #include "storage/buf_internals.h"
      25                 :             : #include "storage/subsystems.h"
      26                 :             : 
      27                 :             : /* entry for buffer lookup hashtable */
      28                 :             : typedef struct
      29                 :             : {
      30                 :             :     BufferTag   key;            /* Tag of a disk page */
      31                 :             :     int         id;             /* Associated buffer ID */
      32                 :             : } BufferLookupEnt;
      33                 :             : 
      34                 :             : static HTAB *SharedBufHash;
      35                 :             : 
      36                 :             : static void BufTableShmemRequest(void *arg);
      37                 :             : 
      38                 :             : const ShmemCallbacks BufTableShmemCallbacks = {
      39                 :             :     .request_fn = BufTableShmemRequest,
      40                 :             :     /* no special initialization needed, the hash table will start empty */
      41                 :             : };
      42                 :             : 
      43                 :             : /*
      44                 :             :  * Register shmem hash table for mapping buffers.
      45                 :             :  *      size is the desired hash table size (possibly more than NBuffers)
      46                 :             :  */
      47                 :             : void
      48                 :        1249 : BufTableShmemRequest(void *arg)
      49                 :             : {
      50                 :             :     int         size;
      51                 :             : 
      52                 :             :     /*
      53                 :             :      * Request the shared buffer lookup hashtable.
      54                 :             :      *
      55                 :             :      * Since we can't tolerate running out of lookup table entries, we must be
      56                 :             :      * sure to specify an adequate table size here.  The maximum steady-state
      57                 :             :      * usage is of course NBuffers entries, but BufferAlloc() tries to insert
      58                 :             :      * a new entry before deleting the old.  In principle this could be
      59                 :             :      * happening in each partition concurrently, so we could need as many as
      60                 :             :      * NBuffers + NUM_BUFFER_PARTITIONS entries.
      61                 :             :      */
      62                 :        1249 :     size = NBuffers + NUM_BUFFER_PARTITIONS;
      63                 :             : 
      64                 :        1249 :     ShmemRequestHash(.name = "Shared Buffer Lookup Table",
      65                 :             :                      .nelems = size,
      66                 :             :                      .ptr = &SharedBufHash,
      67                 :             :                      .hash_info.keysize = sizeof(BufferTag),
      68                 :             :                      .hash_info.entrysize = sizeof(BufferLookupEnt),
      69                 :             :                      .hash_info.num_partitions = NUM_BUFFER_PARTITIONS,
      70                 :             :                      .hash_flags = HASH_ELEM | HASH_BLOBS | HASH_PARTITION | HASH_FIXED_SIZE,
      71                 :             :         );
      72                 :        1249 : }
      73                 :             : 
      74                 :             : /*
      75                 :             :  * BufTableHashCode
      76                 :             :  *      Compute the hash code associated with a BufferTag
      77                 :             :  *
      78                 :             :  * This must be passed to the lookup/insert/delete routines along with the
      79                 :             :  * tag.  We do it like this because the callers need to know the hash code
      80                 :             :  * in order to determine which buffer partition to lock, and we don't want
      81                 :             :  * to do the hash computation twice (hash_any is a bit slow).
      82                 :             :  */
      83                 :             : uint32
      84                 :    86240784 : BufTableHashCode(BufferTag *tagPtr)
      85                 :             : {
      86                 :    86240784 :     return get_hash_value(SharedBufHash, tagPtr);
      87                 :             : }
      88                 :             : 
      89                 :             : /*
      90                 :             :  * BufTableLookup
      91                 :             :  *      Lookup the given BufferTag; return buffer ID, or -1 if not found
      92                 :             :  *
      93                 :             :  * Caller must hold at least share lock on BufMappingLock for tag's partition
      94                 :             :  */
      95                 :             : int
      96                 :    84386234 : BufTableLookup(BufferTag *tagPtr, uint32 hashcode)
      97                 :             : {
      98                 :             :     BufferLookupEnt *result;
      99                 :             : 
     100                 :             :     result = (BufferLookupEnt *)
     101                 :    84386234 :         hash_search_with_hash_value(SharedBufHash,
     102                 :             :                                     tagPtr,
     103                 :             :                                     hashcode,
     104                 :             :                                     HASH_FIND,
     105                 :             :                                     NULL);
     106                 :             : 
     107         [ +  + ]:    84386234 :     if (!result)
     108                 :     2005918 :         return -1;
     109                 :             : 
     110                 :    82380316 :     return result->id;
     111                 :             : }
     112                 :             : 
     113                 :             : /*
     114                 :             :  * BufTableInsert
     115                 :             :  *      Insert a hashtable entry for given tag and buffer ID,
     116                 :             :  *      unless an entry already exists for that tag
     117                 :             :  *
     118                 :             :  * Returns -1 on successful insertion.  If a conflicting entry exists
     119                 :             :  * already, returns the buffer ID in that entry.
     120                 :             :  *
     121                 :             :  * Caller must hold exclusive lock on BufMappingLock for tag's partition
     122                 :             :  */
     123                 :             : int
     124                 :     2276200 : BufTableInsert(BufferTag *tagPtr, uint32 hashcode, int buf_id)
     125                 :             : {
     126                 :             :     BufferLookupEnt *result;
     127                 :             :     bool        found;
     128                 :             : 
     129                 :             :     Assert(buf_id >= 0);     /* -1 is reserved for not-in-table */
     130                 :             :     Assert(tagPtr->blockNum != P_NEW);   /* invalid tag */
     131                 :             : 
     132                 :             :     result = (BufferLookupEnt *)
     133                 :     2276200 :         hash_search_with_hash_value(SharedBufHash,
     134                 :             :                                     tagPtr,
     135                 :             :                                     hashcode,
     136                 :             :                                     HASH_ENTER,
     137                 :             :                                     &found);
     138                 :             : 
     139         [ +  + ]:     2276200 :     if (found)                  /* found something already in the table */
     140                 :         660 :         return result->id;
     141                 :             : 
     142                 :     2275540 :     result->id = buf_id;
     143                 :             : 
     144                 :     2275540 :     return -1;
     145                 :             : }
     146                 :             : 
     147                 :             : /*
     148                 :             :  * BufTableDelete
     149                 :             :  *      Delete the hashtable entry for given tag (which must exist)
     150                 :             :  *
     151                 :             :  * Caller must hold exclusive lock on BufMappingLock for tag's partition
     152                 :             :  */
     153                 :             : void
     154                 :     1573975 : BufTableDelete(BufferTag *tagPtr, uint32 hashcode)
     155                 :             : {
     156                 :             :     BufferLookupEnt *result;
     157                 :             : 
     158                 :             :     result = (BufferLookupEnt *)
     159                 :     1573975 :         hash_search_with_hash_value(SharedBufHash,
     160                 :             :                                     tagPtr,
     161                 :             :                                     hashcode,
     162                 :             :                                     HASH_REMOVE,
     163                 :             :                                     NULL);
     164                 :             : 
     165         [ -  + ]:     1573975 :     if (!result)                /* shouldn't happen */
     166         [ #  # ]:           0 :         elog(ERROR, "shared buffer hash table corrupted");
     167                 :     1573975 : }
        

Generated by: LCOV version 2.0-1