Logo Search packages:      
Sourcecode: postgresql-8.4 version File versions  Download package

buf_table.c
/*-------------------------------------------------------------------------
 *
 * buf_table.c
 *      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 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-2009, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *      $PostgreSQL: pgsql/src/backend/storage/buffer/buf_table.c,v 1.50 2009/01/01 17:23:47 momjian Exp $
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

#include "storage/bufmgr.h"
#include "storage/buf_internals.h"


/* entry for buffer lookup hashtable */
00029 typedef struct
{
      BufferTag   key;              /* Tag of a disk page */
      int               id;                     /* Associated buffer ID */
} BufferLookupEnt;

static HTAB *SharedBufHash;


/*
 * Estimate space needed for mapping hashtable
 *          size is the desired hash table size (possibly more than NBuffers)
 */
Size
BufTableShmemSize(int size)
{
      return hash_estimate_size(size, sizeof(BufferLookupEnt));
}

/*
 * Initialize shmem hash table for mapping buffers
 *          size is the desired hash table size (possibly more than NBuffers)
 */
void
InitBufTable(int size)
{
      HASHCTL           info;

      /* assume no locking is needed yet */

      /* BufferTag maps to Buffer */
      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_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 for tag's partition
 */
int
BufTableLookup(BufferTag *tagPtr, uint32 hashcode)
{
      BufferLookupEnt *result;

      result = (BufferLookupEnt *)
            hash_search_with_hash_value(SharedBufHash,
                                                      (void *) tagPtr,
                                                      hashcode,
                                                      HASH_FIND,
                                                      NULL);

      if (!result)
            return -1;

      return result->id;
}

/*
 * BufTableInsert
 *          Insert a hashtable entry for given tag and buffer ID,
 *          unless an entry already exists for that tag
 *
 * Returns -1 on successful insertion.    If a conflicting entry exists
 * already, returns the buffer ID in that entry.
 *
 * Caller must hold exclusive lock on BufMappingLock for tag's partition
 */
int
BufTableInsert(BufferTag *tagPtr, uint32 hashcode, int buf_id)
{
      BufferLookupEnt *result;
      bool        found;

      Assert(buf_id >= 0);          /* -1 is reserved for not-in-table */
      Assert(tagPtr->blockNum != P_NEW);  /* invalid tag */

      result = (BufferLookupEnt *)
            hash_search_with_hash_value(SharedBufHash,
                                                      (void *) tagPtr,
                                                      hashcode,
                                                      HASH_ENTER,
                                                      &found);

      if (found)                          /* found something already in the table */
            return result->id;

      result->id = buf_id;

      return -1;
}

/*
 * BufTableDelete
 *          Delete the hashtable entry for given tag (which must exist)
 *
 * Caller must hold exclusive lock on BufMappingLock for tag's partition
 */
void
BufTableDelete(BufferTag *tagPtr, uint32 hashcode)
{
      BufferLookupEnt *result;

      result = (BufferLookupEnt *)
            hash_search_with_hash_value(SharedBufHash,
                                                      (void *) tagPtr,
                                                      hashcode,
                                                      HASH_REMOVE,
                                                      NULL);

      if (!result)                        /* shouldn't happen */
            elog(ERROR, "shared buffer hash table corrupted");
}

Generated by  Doxygen 1.6.0   Back to index