Age Owner Branch data TLA 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-2025, 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
7520 tgl@sss.pgh.pa.us 41 :CBC 1909 : BufTableShmemSize(int size)
42 : : {
43 : 1909 : 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
7968 JanWieck@Yahoo.com 51 : 1029 : InitBufTable(int size)
52 : : {
53 : : HASHCTL info;
54 : :
55 : : /* assume no locking is needed yet */
56 : :
57 : : /* BufferTag maps to Buffer */
10226 bruce@momjian.us 58 : 1029 : info.keysize = sizeof(BufferTag);
8741 tgl@sss.pgh.pa.us 59 : 1029 : info.entrysize = sizeof(BufferLookupEnt);
6985 60 : 1029 : info.num_partitions = NUM_BUFFER_PARTITIONS;
61 : :
8741 62 : 1029 : SharedBufHash = ShmemInitHash("Shared Buffer Lookup Table",
63 : : size, size,
64 : : &info,
65 : : HASH_ELEM | HASH_BLOBS | HASH_PARTITION);
10651 scrappy@hub.org 66 : 1029 : }
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
6985 tgl@sss.pgh.pa.us 78 : 56878309 : BufTableHashCode(BufferTag *tagPtr)
79 : : {
282 peter@eisentraut.org 80 : 56878309 : return get_hash_value(SharedBufHash, 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
6985 tgl@sss.pgh.pa.us 90 : 55363912 : BufTableLookup(BufferTag *tagPtr, uint32 hashcode)
91 : : {
92 : : BufferLookupEnt *result;
93 : :
94 : : result = (BufferLookupEnt *)
95 : 55363912 : hash_search_with_hash_value(SharedBufHash,
96 : : tagPtr,
97 : : hashcode,
98 : : HASH_FIND,
99 : : NULL);
100 : :
10226 bruce@momjian.us 101 [ + + ]: 55363912 : if (!result)
7968 JanWieck@Yahoo.com 102 : 1680507 : return -1;
103 : :
104 : 53683405 : 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
6985 tgl@sss.pgh.pa.us 118 : 1888645 : BufTableInsert(BufferTag *tagPtr, uint32 hashcode, int buf_id)
119 : : {
120 : : BufferLookupEnt *result;
121 : : bool found;
122 : :
7491 123 [ - + ]: 1888645 : Assert(buf_id >= 0); /* -1 is reserved for not-in-table */
7266 bruce@momjian.us 124 [ - + ]: 1888645 : Assert(tagPtr->blockNum != P_NEW); /* invalid tag */
125 : :
126 : : result = (BufferLookupEnt *)
6985 tgl@sss.pgh.pa.us 127 : 1888645 : hash_search_with_hash_value(SharedBufHash,
128 : : tagPtr,
129 : : hashcode,
130 : : HASH_ENTER,
131 : : &found);
132 : :
7491 133 [ + + ]: 1888645 : if (found) /* found something already in the table */
134 : 436 : return result->id;
135 : :
7520 136 : 1888209 : result->id = buf_id;
137 : :
7491 138 : 1888209 : 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
6985 148 : 1297425 : BufTableDelete(BufferTag *tagPtr, uint32 hashcode)
149 : : {
150 : : BufferLookupEnt *result;
151 : :
152 : : result = (BufferLookupEnt *)
153 : 1297425 : hash_search_with_hash_value(SharedBufHash,
154 : : tagPtr,
155 : : hashcode,
156 : : HASH_REMOVE,
157 : : NULL);
158 : :
7968 JanWieck@Yahoo.com 159 [ - + ]: 1297425 : if (!result) /* shouldn't happen */
8080 tgl@sss.pgh.pa.us 160 [ # # ]:UBC 0 : elog(ERROR, "shared buffer hash table corrupted");
10651 scrappy@hub.org 161 :CBC 1297425 : }
|