|
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* buf_table.c
|
|
|
|
|
* routines for finding buffers in the buffer pool.
|
|
|
|
|
*
|
|
|
|
|
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
|
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* IDENTIFICATION
|
|
|
|
|
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_table.c,v 1.31 2003/11/13 05:34:58 wieck Exp $
|
|
|
|
|
*
|
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
/*
|
|
|
|
|
* OLD COMMENTS
|
|
|
|
|
*
|
|
|
|
|
* Data Structures:
|
|
|
|
|
*
|
|
|
|
|
* Buffers are identified by their BufferTag (buf.h). This
|
|
|
|
|
* file contains routines for allocating a shmem hash table to
|
|
|
|
|
* map buffer tags to buffer descriptors.
|
|
|
|
|
*
|
|
|
|
|
* Synchronization:
|
|
|
|
|
*
|
|
|
|
|
* All routines in this file assume BufMgrLock is held by their caller.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "postgres.h"
|
|
|
|
|
|
|
|
|
|
#include "storage/buf_internals.h"
|
|
|
|
|
#include "storage/bufmgr.h"
|
|
|
|
|
|
|
|
|
|
static HTAB *SharedBufHash;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Initialize shmem hash table for mapping buffers
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
InitBufTable(void)
|
|
|
|
|
{
|
|
|
|
|
HASHCTL info;
|
|
|
|
|
|
|
|
|
|
/* assume lock is held */
|
|
|
|
|
|
|
|
|
|
/* BufferTag maps to Buffer */
|
|
|
|
|
info.keysize = sizeof(BufferTag);
|
|
|
|
|
info.entrysize = sizeof(BufferLookupEnt);
|
|
|
|
|
info.hash = tag_hash;
|
|
|
|
|
|
|
|
|
|
SharedBufHash = ShmemInitHash("Shared Buffer Lookup Table",
|
|
|
|
|
NBuffers, NBuffers,
|
|
|
|
|
&info,
|
|
|
|
|
HASH_ELEM | HASH_FUNCTION);
|
|
|
|
|
|
|
|
|
|
if (!SharedBufHash)
|
|
|
|
|
elog(FATAL, "could not initialize shared buffer hash table");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BufferDesc *
|
|
|
|
|
BufTableLookup(BufferTag *tagPtr)
|
|
|
|
|
{
|
|
|
|
|
BufferLookupEnt *result;
|
|
|
|
|
|
|
|
|
|
if (tagPtr->blockNum == P_NEW)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
result = (BufferLookupEnt *)
|
|
|
|
|
hash_search(SharedBufHash, (void *) tagPtr, HASH_FIND, NULL);
|
|
|
|
|
if (!result)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
return &(BufferDescriptors[result->id]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* BufTableDelete
|
|
|
|
|
*/
|
|
|
|
|
bool
|
|
|
|
|
BufTableDelete(BufferDesc *buf)
|
|
|
|
|
{
|
|
|
|
|
BufferLookupEnt *result;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* buffer not initialized or has been removed from table already.
|
|
|
|
|
* BM_DELETED keeps us from removing buffer twice.
|
|
|
|
|
*/
|
|
|
|
|
if (buf->flags & BM_DELETED)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
buf->flags |= BM_DELETED;
|
|
|
|
|
|
|
|
|
|
result = (BufferLookupEnt *)
|
|
|
|
|
hash_search(SharedBufHash, (void *) &(buf->tag), HASH_REMOVE, NULL);
|
|
|
|
|
|
|
|
|
|
if (!result) /* shouldn't happen */
|
|
|
|
|
elog(ERROR, "shared buffer hash table corrupted");
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Clear the buffer's tag. This doesn't matter for the hash table,
|
|
|
|
|
* since the buffer is already removed from it, but it ensures that
|
|
|
|
|
* sequential searches through the buffer table won't think the buffer
|
|
|
|
|
* is still valid for its old page.
|
|
|
|
|
*/
|
|
|
|
|
buf->tag.rnode.relNode = InvalidOid;
|
|
|
|
|
buf->tag.rnode.tblNode = InvalidOid;
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
BufTableInsert(BufferDesc *buf)
|
|
|
|
|
{
|
|
|
|
|
BufferLookupEnt *result;
|
|
|
|
|
bool found;
|
|
|
|
|
|
|
|
|
|
/* cannot insert it twice */
|
|
|
|
|
Assert(buf->flags & BM_DELETED);
|
|
|
|
|
buf->flags &= ~(BM_DELETED);
|
|
|
|
|
|
|
|
|
|
result = (BufferLookupEnt *)
|
|
|
|
|
hash_search(SharedBufHash, (void *) &(buf->tag), HASH_ENTER, &found);
|
|
|
|
|
|
|
|
|
|
if (!result)
|
|
|
|
|
ereport(ERROR,
|
|
|
|
|
(errcode(ERRCODE_OUT_OF_MEMORY),
|
|
|
|
|
errmsg("out of shared memory")));
|
|
|
|
|
|
|
|
|
|
if (found) /* found something else in the table? */
|
|
|
|
|
elog(ERROR, "shared buffer hash table corrupted");
|
|
|
|
|
|
|
|
|
|
result->id = buf->buf_id;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* prints out collision stats for the buf table */
|
|
|
|
|
#ifdef NOT_USED
|
|
|
|
|
void
|
|
|
|
|
DBG_LookupListCheck(int nlookup)
|
|
|
|
|
{
|
|
|
|
|
nlookup = 10;
|
|
|
|
|
|
|
|
|
|
hash_stats("Shared", SharedBufHash);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|