aboutsummaryrefslogtreecommitdiff
path: root/src/backend/storage/buffer/buf_table.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/storage/buffer/buf_table.c')
-rw-r--r--src/backend/storage/buffer/buf_table.c56
1 files changed, 43 insertions, 13 deletions
diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c
index 59d1fd17051..864826c1b43 100644
--- a/src/backend/storage/buffer/buf_table.c
+++ b/src/backend/storage/buffer/buf_table.c
@@ -4,8 +4,10 @@
* routines for mapping BufferTags to buffer indexes.
*
* Note: the routines in this file do no locking of their own. The caller
- * must hold a suitable lock on the BufMappingLock, as specified in the
- * comments.
+ * must hold a suitable lock on the appropriate BufMappingLock, as specified
+ * in the comments. We can't do the locking inside these functions because
+ * in most cases the caller needs to adjust the buffer header contents
+ * before the lock is released (see notes in README).
*
*
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
@@ -13,7 +15,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/buffer/buf_table.c,v 1.46 2006/07/14 16:59:19 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/buffer/buf_table.c,v 1.47 2006/07/23 03:07:58 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -58,29 +60,49 @@ InitBufTable(int size)
info.keysize = sizeof(BufferTag);
info.entrysize = sizeof(BufferLookupEnt);
info.hash = tag_hash;
+ info.num_partitions = NUM_BUFFER_PARTITIONS;
SharedBufHash = ShmemInitHash("Shared Buffer Lookup Table",
size, size,
&info,
- HASH_ELEM | HASH_FUNCTION);
+ HASH_ELEM | HASH_FUNCTION | HASH_PARTITION);
if (!SharedBufHash)
elog(FATAL, "could not initialize shared buffer hash table");
}
/*
+ * BufTableHashCode
+ * Compute the hash code associated with a BufferTag
+ *
+ * This must be passed to the lookup/insert/delete routines along with the
+ * tag. We do it like this because the callers need to know the hash code
+ * in order to determine which buffer partition to lock, and we don't want
+ * to do the hash computation twice (hash_any is a bit slow).
+ */
+uint32
+BufTableHashCode(BufferTag *tagPtr)
+{
+ return get_hash_value(SharedBufHash, (void *) tagPtr);
+}
+
+/*
* BufTableLookup
* Lookup the given BufferTag; return buffer ID, or -1 if not found
*
- * Caller must hold at least share lock on BufMappingLock
+ * Caller must hold at least share lock on BufMappingLock for tag's partition
*/
int
-BufTableLookup(BufferTag *tagPtr)
+BufTableLookup(BufferTag *tagPtr, uint32 hashcode)
{
BufferLookupEnt *result;
result = (BufferLookupEnt *)
- hash_search(SharedBufHash, (void *) tagPtr, HASH_FIND, NULL);
+ hash_search_with_hash_value(SharedBufHash,
+ (void *) tagPtr,
+ hashcode,
+ HASH_FIND,
+ NULL);
if (!result)
return -1;
@@ -96,10 +118,10 @@ BufTableLookup(BufferTag *tagPtr)
* Returns -1 on successful insertion. If a conflicting entry exists
* already, returns the buffer ID in that entry.
*
- * Caller must hold write lock on BufMappingLock
+ * Caller must hold exclusive lock on BufMappingLock for tag's partition
*/
int
-BufTableInsert(BufferTag *tagPtr, int buf_id)
+BufTableInsert(BufferTag *tagPtr, uint32 hashcode, int buf_id)
{
BufferLookupEnt *result;
bool found;
@@ -108,7 +130,11 @@ BufTableInsert(BufferTag *tagPtr, int buf_id)
Assert(tagPtr->blockNum != P_NEW); /* invalid tag */
result = (BufferLookupEnt *)
- hash_search(SharedBufHash, (void *) tagPtr, HASH_ENTER, &found);
+ hash_search_with_hash_value(SharedBufHash,
+ (void *) tagPtr,
+ hashcode,
+ HASH_ENTER,
+ &found);
if (found) /* found something already in the table */
return result->id;
@@ -122,15 +148,19 @@ BufTableInsert(BufferTag *tagPtr, int buf_id)
* BufTableDelete
* Delete the hashtable entry for given tag (which must exist)
*
- * Caller must hold write lock on BufMappingLock
+ * Caller must hold exclusive lock on BufMappingLock for tag's partition
*/
void
-BufTableDelete(BufferTag *tagPtr)
+BufTableDelete(BufferTag *tagPtr, uint32 hashcode)
{
BufferLookupEnt *result;
result = (BufferLookupEnt *)
- hash_search(SharedBufHash, (void *) tagPtr, HASH_REMOVE, NULL);
+ hash_search_with_hash_value(SharedBufHash,
+ (void *) tagPtr,
+ hashcode,
+ HASH_REMOVE,
+ NULL);
if (!result) /* shouldn't happen */
elog(ERROR, "shared buffer hash table corrupted");