mirror of
https://github.com/postgres/postgres.git
synced 2025-07-11 10:01:57 +03:00
Split the buffer mapping table into multiple separately lockable
partitions, as per discussion. Passes functionality checks, but I don't have any performance data yet.
This commit is contained in:
@ -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");
|
||||
|
Reference in New Issue
Block a user