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