diff options
Diffstat (limited to 'src/backend/storage/buffer/buf_table.c')
-rw-r--r-- | src/backend/storage/buffer/buf_table.c | 56 |
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"); |