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-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
7010 tgl@sss.pgh.pa.us 41 :CBC 1679 : BufTableShmemSize(int size)
42 : : {
43 : 1679 : 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
7458 JanWieck@Yahoo.com 51 : 898 : InitBufTable(int size)
52 : : {
53 : : HASHCTL info;
54 : :
55 : : /* assume no locking is needed yet */
56 : :
57 : : /* BufferTag maps to Buffer */
9716 bruce@momjian.us 58 : 898 : info.keysize = sizeof(BufferTag);
8231 tgl@sss.pgh.pa.us 59 : 898 : info.entrysize = sizeof(BufferLookupEnt);
6475 60 : 898 : info.num_partitions = NUM_BUFFER_PARTITIONS;
61 : :
8231 62 : 898 : SharedBufHash = ShmemInitHash("Shared Buffer Lookup Table",
63 : : size, size,
64 : : &info,
65 : : HASH_ELEM | HASH_BLOBS | HASH_PARTITION);
10141 scrappy@hub.org 66 : 898 : }
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
6475 tgl@sss.pgh.pa.us 78 : 52674195 : BufTableHashCode(BufferTag *tagPtr)
79 : : {
80 : 52674195 : 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 : 51370804 : BufTableLookup(BufferTag *tagPtr, uint32 hashcode)
91 : : {
92 : : BufferLookupEnt *result;
93 : :
94 : : result = (BufferLookupEnt *)
95 : 51370804 : hash_search_with_hash_value(SharedBufHash,
96 : : tagPtr,
97 : : hashcode,
98 : : HASH_FIND,
99 : : NULL);
100 : :
9716 bruce@momjian.us 101 [ + + ]: 51370804 : if (!result)
7458 JanWieck@Yahoo.com 102 : 1513982 : return -1;
103 : :
104 : 49856822 : 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
6475 tgl@sss.pgh.pa.us 118 : 1582728 : BufTableInsert(BufferTag *tagPtr, uint32 hashcode, int buf_id)
119 : : {
120 : : BufferLookupEnt *result;
121 : : bool found;
122 : :
6981 123 [ - + ]: 1582728 : Assert(buf_id >= 0); /* -1 is reserved for not-in-table */
6756 bruce@momjian.us 124 [ - + ]: 1582728 : Assert(tagPtr->blockNum != P_NEW); /* invalid tag */
125 : :
126 : : result = (BufferLookupEnt *)
6475 tgl@sss.pgh.pa.us 127 : 1582728 : hash_search_with_hash_value(SharedBufHash,
128 : : tagPtr,
129 : : hashcode,
130 : : HASH_ENTER,
131 : : &found);
132 : :
6981 133 [ + + ]: 1582728 : if (found) /* found something already in the table */
134 : 2718 : return result->id;
135 : :
7010 136 : 1580010 : result->id = buf_id;
137 : :
6981 138 : 1580010 : 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
6475 148 : 1096820 : BufTableDelete(BufferTag *tagPtr, uint32 hashcode)
149 : : {
150 : : BufferLookupEnt *result;
151 : :
152 : : result = (BufferLookupEnt *)
153 : 1096820 : hash_search_with_hash_value(SharedBufHash,
154 : : tagPtr,
155 : : hashcode,
156 : : HASH_REMOVE,
157 : : NULL);
158 : :
7458 JanWieck@Yahoo.com 159 [ - + ]: 1096820 : if (!result) /* shouldn't happen */
7570 tgl@sss.pgh.pa.us 160 [ # # ]:UBC 0 : elog(ERROR, "shared buffer hash table corrupted");
10141 scrappy@hub.org 161 :CBC 1096820 : }
|