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-2024, 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 : 26 : /* entry for buffer lookup hashtable */ 27 : typedef struct 28 : { 29 : BufferTag key; /* Tag of a disk page */ 30 : int id; /* Associated buffer ID */ 31 : } BufferLookupEnt; 32 : 33 : static HTAB *SharedBufHash; 34 : 35 : 36 : /* 37 : * Estimate space needed for mapping hashtable 38 : * size is the desired hash table size (possibly more than NBuffers) 39 : */ 40 : Size 41 3534 : BufTableShmemSize(int size) 42 : { 43 3534 : return hash_estimate_size(size, sizeof(BufferLookupEnt)); 44 : } 45 : 46 : /* 47 : * Initialize shmem hash table for mapping buffers 48 : * size is the desired hash table size (possibly more than NBuffers) 49 : */ 50 : void 51 1902 : InitBufTable(int size) 52 : { 53 : HASHCTL info; 54 : 55 : /* assume no locking is needed yet */ 56 : 57 : /* BufferTag maps to Buffer */ 58 1902 : info.keysize = sizeof(BufferTag); 59 1902 : info.entrysize = sizeof(BufferLookupEnt); 60 1902 : info.num_partitions = NUM_BUFFER_PARTITIONS; 61 : 62 1902 : SharedBufHash = ShmemInitHash("Shared Buffer Lookup Table", 63 : size, size, 64 : &info, 65 : HASH_ELEM | HASH_BLOBS | HASH_PARTITION); 66 1902 : } 67 : 68 : /* 69 : * BufTableHashCode 70 : * Compute the hash code associated with a BufferTag 71 : * 72 : * This must be passed to the lookup/insert/delete routines along with the 73 : * tag. We do it like this because the callers need to know the hash code 74 : * in order to determine which buffer partition to lock, and we don't want 75 : * to do the hash computation twice (hash_any is a bit slow). 76 : */ 77 : uint32 78 108721898 : BufTableHashCode(BufferTag *tagPtr) 79 : { 80 108721898 : return get_hash_value(SharedBufHash, (void *) tagPtr); 81 : } 82 : 83 : /* 84 : * BufTableLookup 85 : * Lookup the given BufferTag; return buffer ID, or -1 if not found 86 : * 87 : * Caller must hold at least share lock on BufMappingLock for tag's partition 88 : */ 89 : int 90 106066812 : BufTableLookup(BufferTag *tagPtr, uint32 hashcode) 91 : { 92 : BufferLookupEnt *result; 93 : 94 : result = (BufferLookupEnt *) 95 106066812 : hash_search_with_hash_value(SharedBufHash, 96 : tagPtr, 97 : hashcode, 98 : HASH_FIND, 99 : NULL); 100 : 101 106066812 : if (!result) 102 2980766 : return -1; 103 : 104 103086046 : return result->id; 105 : } 106 : 107 : /* 108 : * BufTableInsert 109 : * Insert a hashtable entry for given tag and buffer ID, 110 : * unless an entry already exists for that tag 111 : * 112 : * Returns -1 on successful insertion. If a conflicting entry exists 113 : * already, returns the buffer ID in that entry. 114 : * 115 : * Caller must hold exclusive lock on BufMappingLock for tag's partition 116 : */ 117 : int 118 3220332 : BufTableInsert(BufferTag *tagPtr, uint32 hashcode, int buf_id) 119 : { 120 : BufferLookupEnt *result; 121 : bool found; 122 : 123 : Assert(buf_id >= 0); /* -1 is reserved for not-in-table */ 124 : Assert(tagPtr->blockNum != P_NEW); /* invalid tag */ 125 : 126 : result = (BufferLookupEnt *) 127 3220332 : hash_search_with_hash_value(SharedBufHash, 128 : tagPtr, 129 : hashcode, 130 : HASH_ENTER, 131 : &found); 132 : 133 3220332 : if (found) /* found something already in the table */ 134 524 : return result->id; 135 : 136 3219808 : result->id = buf_id; 137 : 138 3219808 : return -1; 139 : } 140 : 141 : /* 142 : * BufTableDelete 143 : * Delete the hashtable entry for given tag (which must exist) 144 : * 145 : * Caller must hold exclusive lock on BufMappingLock for tag's partition 146 : */ 147 : void 148 2241718 : BufTableDelete(BufferTag *tagPtr, uint32 hashcode) 149 : { 150 : BufferLookupEnt *result; 151 : 152 : result = (BufferLookupEnt *) 153 2241718 : hash_search_with_hash_value(SharedBufHash, 154 : tagPtr, 155 : hashcode, 156 : HASH_REMOVE, 157 : NULL); 158 : 159 2241718 : if (!result) /* shouldn't happen */ 160 0 : elog(ERROR, "shared buffer hash table corrupted"); 161 2241718 : }