PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
buf_table.c
Go to the documentation of this file.
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-2017, 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/bufmgr.h"
25 #include "storage/buf_internals.h"
26 
27 
28 /* entry for buffer lookup hashtable */
29 typedef struct
30 {
31  BufferTag key; /* Tag of a disk page */
32  int id; /* Associated buffer ID */
34 
36 
37 
38 /*
39  * Estimate space needed for mapping hashtable
40  * size is the desired hash table size (possibly more than NBuffers)
41  */
42 Size
44 {
45  return hash_estimate_size(size, sizeof(BufferLookupEnt));
46 }
47 
48 /*
49  * Initialize shmem hash table for mapping buffers
50  * size is the desired hash table size (possibly more than NBuffers)
51  */
52 void
53 InitBufTable(int size)
54 {
55  HASHCTL info;
56 
57  /* assume no locking is needed yet */
58 
59  /* BufferTag maps to Buffer */
60  info.keysize = sizeof(BufferTag);
61  info.entrysize = sizeof(BufferLookupEnt);
63 
64  SharedBufHash = ShmemInitHash("Shared Buffer Lookup Table",
65  size, size,
66  &info,
68 }
69 
70 /*
71  * BufTableHashCode
72  * Compute the hash code associated with a BufferTag
73  *
74  * This must be passed to the lookup/insert/delete routines along with the
75  * tag. We do it like this because the callers need to know the hash code
76  * in order to determine which buffer partition to lock, and we don't want
77  * to do the hash computation twice (hash_any is a bit slow).
78  */
79 uint32
81 {
82  return get_hash_value(SharedBufHash, (void *) tagPtr);
83 }
84 
85 /*
86  * BufTableLookup
87  * Lookup the given BufferTag; return buffer ID, or -1 if not found
88  *
89  * Caller must hold at least share lock on BufMappingLock for tag's partition
90  */
91 int
92 BufTableLookup(BufferTag *tagPtr, uint32 hashcode)
93 {
95 
96  result = (BufferLookupEnt *)
97  hash_search_with_hash_value(SharedBufHash,
98  (void *) tagPtr,
99  hashcode,
100  HASH_FIND,
101  NULL);
102 
103  if (!result)
104  return -1;
105 
106  return result->id;
107 }
108 
109 /*
110  * BufTableInsert
111  * Insert a hashtable entry for given tag and buffer ID,
112  * unless an entry already exists for that tag
113  *
114  * Returns -1 on successful insertion. If a conflicting entry exists
115  * already, returns the buffer ID in that entry.
116  *
117  * Caller must hold exclusive lock on BufMappingLock for tag's partition
118  */
119 int
120 BufTableInsert(BufferTag *tagPtr, uint32 hashcode, int buf_id)
121 {
123  bool found;
124 
125  Assert(buf_id >= 0); /* -1 is reserved for not-in-table */
126  Assert(tagPtr->blockNum != P_NEW); /* invalid tag */
127 
128  result = (BufferLookupEnt *)
129  hash_search_with_hash_value(SharedBufHash,
130  (void *) tagPtr,
131  hashcode,
132  HASH_ENTER,
133  &found);
134 
135  if (found) /* found something already in the table */
136  return result->id;
137 
138  result->id = buf_id;
139 
140  return -1;
141 }
142 
143 /*
144  * BufTableDelete
145  * Delete the hashtable entry for given tag (which must exist)
146  *
147  * Caller must hold exclusive lock on BufMappingLock for tag's partition
148  */
149 void
150 BufTableDelete(BufferTag *tagPtr, uint32 hashcode)
151 {
153 
154  result = (BufferLookupEnt *)
155  hash_search_with_hash_value(SharedBufHash,
156  (void *) tagPtr,
157  hashcode,
158  HASH_REMOVE,
159  NULL);
160 
161  if (!result) /* shouldn't happen */
162  elog(ERROR, "shared buffer hash table corrupted");
163 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:915
void BufTableDelete(BufferTag *tagPtr, uint32 hashcode)
Definition: buf_table.c:150
#define HASH_ELEM
Definition: hsearch.h:87
uint32 BufTableHashCode(BufferTag *tagPtr)
Definition: buf_table.c:80
Size entrysize
Definition: hsearch.h:73
struct buftag BufferTag
void InitBufTable(int size)
Definition: buf_table.c:53
return result
Definition: formatting.c:1633
#define P_NEW
Definition: bufmgr.h:82
int BufTableLookup(BufferTag *tagPtr, uint32 hashcode)
Definition: buf_table.c:92
#define HASH_PARTITION
Definition: hsearch.h:83
Definition: dynahash.c:208
uint32 get_hash_value(HTAB *hashp, const void *keyPtr)
Definition: dynahash.c:856
int BufTableInsert(BufferTag *tagPtr, uint32 hashcode, int buf_id)
Definition: buf_table.c:120
#define ERROR
Definition: elog.h:43
BufferTag key
Definition: buf_table.c:31
long num_partitions
Definition: hsearch.h:67
#define NUM_BUFFER_PARTITIONS
Definition: lwlock.h:113
unsigned int uint32
Definition: c.h:268
Size hash_estimate_size(long num_entries, Size entrysize)
Definition: dynahash.c:728
#define HASH_BLOBS
Definition: hsearch.h:88
Size keysize
Definition: hsearch.h:72
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
static HTAB * SharedBufHash
Definition: buf_table.c:35
size_t Size
Definition: c.h:356
BlockNumber blockNum
Definition: buf_internals.h:95
#define elog
Definition: elog.h:219
HTAB * ShmemInitHash(const char *name, long init_size, long max_size, HASHCTL *infoP, int hash_flags)
Definition: shmem.c:317
Size BufTableShmemSize(int size)
Definition: buf_table.c:43