mirror of https://github.com/postgres/postgres
Retrofit hashtable and shared-mem-size-estimation bug fixes
into REL6_4.
This commit is contained in:
parent
0fda84bfcd
commit
2ecbf94430
|
@ -7,7 +7,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.19 1998/09/01 04:31:39 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.19.2.1 1999/03/07 02:01:08 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -33,7 +33,6 @@
|
||||||
#include "storage/lmgr.h"
|
#include "storage/lmgr.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
#include "utils/dynahash.h"
|
|
||||||
#include "utils/hsearch.h"
|
#include "utils/hsearch.h"
|
||||||
#include "utils/memutils.h"
|
#include "utils/memutils.h"
|
||||||
#include "executor/execdebug.h" /* for NDirectFileRead */
|
#include "executor/execdebug.h" /* for NDirectFileRead */
|
||||||
|
@ -270,21 +269,11 @@ int
|
||||||
BufferShmemSize()
|
BufferShmemSize()
|
||||||
{
|
{
|
||||||
int size = 0;
|
int size = 0;
|
||||||
int nbuckets;
|
|
||||||
int nsegs;
|
|
||||||
int tmp;
|
|
||||||
|
|
||||||
nbuckets = 1 << (int) my_log2((NBuffers - 1) / DEF_FFACTOR + 1);
|
/* size of shmem index hash table */
|
||||||
nsegs = 1 << (int) my_log2((nbuckets - 1) / DEF_SEGSIZE + 1);
|
size += hash_estimate_size(SHMEM_INDEX_SIZE,
|
||||||
|
SHMEM_INDEX_KEYSIZE,
|
||||||
/* size of shmem index table */
|
SHMEM_INDEX_DATASIZE);
|
||||||
size += MAXALIGN(my_log2(SHMEM_INDEX_SIZE) * sizeof(void *)); /* HTAB->dir */
|
|
||||||
size += MAXALIGN(sizeof(HHDR)); /* HTAB->hctl */
|
|
||||||
size += MAXALIGN(DEF_SEGSIZE * sizeof(SEGMENT));
|
|
||||||
size += BUCKET_ALLOC_INCR *
|
|
||||||
(MAXALIGN(sizeof(BUCKET_INDEX)) +
|
|
||||||
MAXALIGN(SHMEM_INDEX_KEYSIZE) +
|
|
||||||
MAXALIGN(SHMEM_INDEX_DATASIZE));
|
|
||||||
|
|
||||||
/* size of buffer descriptors */
|
/* size of buffer descriptors */
|
||||||
size += MAXALIGN((NBuffers + 1) * sizeof(BufferDesc));
|
size += MAXALIGN((NBuffers + 1) * sizeof(BufferDesc));
|
||||||
|
@ -293,17 +282,13 @@ BufferShmemSize()
|
||||||
size += NBuffers * MAXALIGN(BLCKSZ);
|
size += NBuffers * MAXALIGN(BLCKSZ);
|
||||||
|
|
||||||
/* size of buffer hash table */
|
/* size of buffer hash table */
|
||||||
size += MAXALIGN(my_log2(NBuffers) * sizeof(void *)); /* HTAB->dir */
|
size += hash_estimate_size(NBuffers,
|
||||||
size += MAXALIGN(sizeof(HHDR)); /* HTAB->hctl */
|
sizeof(BufferTag),
|
||||||
size += nsegs * MAXALIGN(DEF_SEGSIZE * sizeof(SEGMENT));
|
sizeof(Buffer));
|
||||||
tmp = (int) ceil((double) NBuffers / BUCKET_ALLOC_INCR);
|
|
||||||
size += tmp * BUCKET_ALLOC_INCR *
|
|
||||||
(MAXALIGN(sizeof(BUCKET_INDEX)) +
|
|
||||||
MAXALIGN(sizeof(BufferTag)) +
|
|
||||||
MAXALIGN(sizeof(Buffer)));
|
|
||||||
|
|
||||||
#ifdef BMTRACE
|
#ifdef BMTRACE
|
||||||
size += (BMT_LIMIT * sizeof(bmtrace)) + sizeof(long);
|
size += (BMT_LIMIT * sizeof(bmtrace)) + sizeof(long);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipci.c,v 1.16 1998/09/01 03:25:10 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipci.c,v 1.16.2.1 1999/03/07 02:00:46 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -71,11 +71,17 @@ CreateSharedMemoryAndSemaphores(IPCKey key)
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
CreateSpinlocks(IPCKeyGetSpinLockSemaphoreKey(key));
|
CreateSpinlocks(IPCKeyGetSpinLockSemaphoreKey(key));
|
||||||
size = BufferShmemSize() + LockShmemSize();
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Size of the primary shared-memory block is estimated via
|
||||||
|
* moderately-accurate estimates for the big hogs, plus 100K for
|
||||||
|
* the stuff that's too small to bother with estimating.
|
||||||
|
*/
|
||||||
|
size = BufferShmemSize() + LockShmemSize();
|
||||||
#ifdef STABLE_MEMORY_STORAGE
|
#ifdef STABLE_MEMORY_STORAGE
|
||||||
size += MMShmemSize();
|
size += MMShmemSize();
|
||||||
#endif
|
#endif
|
||||||
|
size += 100000;
|
||||||
|
|
||||||
if (DebugLvl > 1)
|
if (DebugLvl > 1)
|
||||||
{
|
{
|
||||||
|
@ -113,8 +119,6 @@ CreateSharedMemoryAndSemaphores(IPCKey key)
|
||||||
void
|
void
|
||||||
AttachSharedMemoryAndSemaphores(IPCKey key)
|
AttachSharedMemoryAndSemaphores(IPCKey key)
|
||||||
{
|
{
|
||||||
int size;
|
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* create rather than attach if using private key
|
* create rather than attach if using private key
|
||||||
* ----------------
|
* ----------------
|
||||||
|
@ -136,8 +140,7 @@ AttachSharedMemoryAndSemaphores(IPCKey key)
|
||||||
* attach the buffer manager buffer pool (and semaphore)
|
* attach the buffer manager buffer pool (and semaphore)
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
size = BufferShmemSize() + LockShmemSize();
|
InitShmem(key, 0);
|
||||||
InitShmem(key, size);
|
|
||||||
InitBufferPool(key);
|
InitBufferPool(key);
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/shmem.c,v 1.31 1998/09/01 04:31:49 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/shmem.c,v 1.31.2.1 1999/03/07 02:00:46 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -215,7 +215,7 @@ InitShmem(unsigned int key, unsigned int size)
|
||||||
/* create OR attach to the shared memory shmem index */
|
/* create OR attach to the shared memory shmem index */
|
||||||
info.keysize = SHMEM_INDEX_KEYSIZE;
|
info.keysize = SHMEM_INDEX_KEYSIZE;
|
||||||
info.datasize = SHMEM_INDEX_DATASIZE;
|
info.datasize = SHMEM_INDEX_DATASIZE;
|
||||||
hash_flags = (HASH_ELEM);
|
hash_flags = HASH_ELEM;
|
||||||
|
|
||||||
/* This will acquire the shmem index lock, but not release it. */
|
/* This will acquire the shmem index lock, but not release it. */
|
||||||
ShmemIndex = ShmemInitHash("ShmemIndex",
|
ShmemIndex = ShmemInitHash("ShmemIndex",
|
||||||
|
@ -340,8 +340,8 @@ ShmemIsValid(unsigned long addr)
|
||||||
*/
|
*/
|
||||||
HTAB *
|
HTAB *
|
||||||
ShmemInitHash(char *name, /* table string name for shmem index */
|
ShmemInitHash(char *name, /* table string name for shmem index */
|
||||||
long init_size, /* initial size */
|
long init_size, /* initial table size */
|
||||||
long max_size, /* max size of the table */
|
long max_size, /* max size of the table (NOT USED) */
|
||||||
HASHCTL *infoP, /* info about key and bucket size */
|
HASHCTL *infoP, /* info about key and bucket size */
|
||||||
int hash_flags) /* info about infoP */
|
int hash_flags) /* info about infoP */
|
||||||
{
|
{
|
||||||
|
@ -349,18 +349,20 @@ ShmemInitHash(char *name, /* table string name for shmem index */
|
||||||
long *location;
|
long *location;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* shared memory hash tables have a fixed max size so that the control
|
* Hash tables allocated in shared memory have a fixed directory;
|
||||||
* structures don't try to grow. The segbase is for calculating
|
* it can't grow or other backends wouldn't be able to find it.
|
||||||
* pointer values. The shared memory allocator must be specified.
|
* The segbase is for calculating pointer values.
|
||||||
|
* The shared memory allocator must be specified too.
|
||||||
*/
|
*/
|
||||||
|
infoP->dsize = infoP->max_dsize = DEF_DIRSIZE;
|
||||||
infoP->segbase = (long *) ShmemBase;
|
infoP->segbase = (long *) ShmemBase;
|
||||||
infoP->alloc = ShmemAlloc;
|
infoP->alloc = ShmemAlloc;
|
||||||
infoP->max_size = max_size;
|
hash_flags |= HASH_SHARED_MEM | HASH_DIRSIZE;
|
||||||
hash_flags |= HASH_SHARED_MEM;
|
|
||||||
|
|
||||||
/* look it up in the shmem index */
|
/* look it up in the shmem index */
|
||||||
location =
|
location = ShmemInitStruct(name,
|
||||||
ShmemInitStruct(name, my_log2(max_size) + sizeof(HHDR), &found);
|
sizeof(HHDR) + DEF_DIRSIZE * sizeof(SEG_OFFSET),
|
||||||
|
&found);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* shmem index is corrupted. Let someone else give the error
|
* shmem index is corrupted. Let someone else give the error
|
||||||
|
@ -376,13 +378,11 @@ ShmemInitHash(char *name, /* table string name for shmem index */
|
||||||
if (found)
|
if (found)
|
||||||
hash_flags |= HASH_ATTACH;
|
hash_flags |= HASH_ATTACH;
|
||||||
|
|
||||||
/* these structures were allocated or bound in ShmemInitStruct */
|
/* Now provide the header and directory pointers */
|
||||||
/* control information and parameters */
|
|
||||||
infoP->hctl = (long *) location;
|
infoP->hctl = (long *) location;
|
||||||
/* directory for hash lookup */
|
infoP->dir = (long *) (((char*) location) + sizeof(HHDR));
|
||||||
infoP->dir = (long *) (location + sizeof(HHDR));
|
|
||||||
|
|
||||||
return hash_create(init_size, infoP, hash_flags);;
|
return hash_create(init_size, infoP, hash_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.38 1998/10/08 18:29:57 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.38.2.1 1999/03/07 02:00:49 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* Outside modules can create a lock table and acquire/release
|
* Outside modules can create a lock table and acquire/release
|
||||||
|
@ -42,7 +42,6 @@
|
||||||
#include "storage/spin.h"
|
#include "storage/spin.h"
|
||||||
#include "storage/proc.h"
|
#include "storage/proc.h"
|
||||||
#include "storage/lock.h"
|
#include "storage/lock.h"
|
||||||
#include "utils/dynahash.h"
|
|
||||||
#include "utils/hsearch.h"
|
#include "utils/hsearch.h"
|
||||||
#include "utils/memutils.h"
|
#include "utils/memutils.h"
|
||||||
#include "utils/palloc.h"
|
#include "utils/palloc.h"
|
||||||
|
@ -340,8 +339,8 @@ LockMethodTableInit(char *tabName,
|
||||||
* to find the different locks.
|
* to find the different locks.
|
||||||
* ----------------------
|
* ----------------------
|
||||||
*/
|
*/
|
||||||
info.keysize = sizeof(LOCKTAG);
|
info.keysize = SHMEM_LOCKTAB_KEYSIZE;
|
||||||
info.datasize = sizeof(LOCK);
|
info.datasize = SHMEM_LOCKTAB_DATASIZE;
|
||||||
info.hash = tag_hash;
|
info.hash = tag_hash;
|
||||||
hash_flags = (HASH_ELEM | HASH_FUNCTION);
|
hash_flags = (HASH_ELEM | HASH_FUNCTION);
|
||||||
|
|
||||||
|
@ -362,8 +361,8 @@ LockMethodTableInit(char *tabName,
|
||||||
* the same lock, additional information must be saved (locks per tx).
|
* the same lock, additional information must be saved (locks per tx).
|
||||||
* -------------------------
|
* -------------------------
|
||||||
*/
|
*/
|
||||||
info.keysize = XID_TAGSIZE;
|
info.keysize = SHMEM_XIDTAB_KEYSIZE;
|
||||||
info.datasize = sizeof(XIDLookupEnt);
|
info.datasize = SHMEM_XIDTAB_DATASIZE;
|
||||||
info.hash = tag_hash;
|
info.hash = tag_hash;
|
||||||
hash_flags = (HASH_ELEM | HASH_FUNCTION);
|
hash_flags = (HASH_ELEM | HASH_FUNCTION);
|
||||||
|
|
||||||
|
@ -1491,35 +1490,26 @@ int
|
||||||
LockShmemSize()
|
LockShmemSize()
|
||||||
{
|
{
|
||||||
int size = 0;
|
int size = 0;
|
||||||
int nLockBuckets,
|
|
||||||
nLockSegs;
|
|
||||||
int nXidBuckets,
|
|
||||||
nXidSegs;
|
|
||||||
|
|
||||||
nLockBuckets = 1 << (int) my_log2((NLOCKENTS - 1) / DEF_FFACTOR + 1);
|
|
||||||
nLockSegs = 1 << (int) my_log2((nLockBuckets - 1) / DEF_SEGSIZE + 1);
|
|
||||||
|
|
||||||
nXidBuckets = 1 << (int) my_log2((NLOCKS_PER_XACT - 1) / DEF_FFACTOR + 1);
|
|
||||||
nXidSegs = 1 << (int) my_log2((nLockBuckets - 1) / DEF_SEGSIZE + 1);
|
|
||||||
|
|
||||||
size += MAXALIGN(NBACKENDS * sizeof(PROC)); /* each MyProc */
|
|
||||||
size += MAXALIGN(NBACKENDS * sizeof(LOCKMETHODCTL)); /* each
|
|
||||||
* lockMethodTable->ctl */
|
|
||||||
size += MAXALIGN(sizeof(PROC_HDR)); /* ProcGlobal */
|
size += MAXALIGN(sizeof(PROC_HDR)); /* ProcGlobal */
|
||||||
|
size += MAXALIGN(MaxBackendId * sizeof(PROC)); /* each MyProc */
|
||||||
|
size += MAXALIGN(MaxBackendId * sizeof(LOCKMETHODCTL)); /* each
|
||||||
|
* lockMethodTable->ctl */
|
||||||
|
|
||||||
size += MAXALIGN(my_log2(NLOCKENTS) * sizeof(void *));
|
/* lockHash table */
|
||||||
size += MAXALIGN(sizeof(HHDR));
|
size += hash_estimate_size(NLOCKENTS,
|
||||||
size += nLockSegs * MAXALIGN(DEF_SEGSIZE * sizeof(SEGMENT));
|
SHMEM_LOCKTAB_KEYSIZE,
|
||||||
size += NLOCKENTS * /* XXX not multiple of BUCKET_ALLOC_INCR? */
|
SHMEM_LOCKTAB_DATASIZE);
|
||||||
(MAXALIGN(sizeof(BUCKET_INDEX)) +
|
|
||||||
MAXALIGN(sizeof(LOCK))); /* contains hash key */
|
|
||||||
|
|
||||||
size += MAXALIGN(my_log2(NBACKENDS) * sizeof(void *));
|
/* xidHash table */
|
||||||
size += MAXALIGN(sizeof(HHDR));
|
size += hash_estimate_size(MaxBackendId,
|
||||||
size += nXidSegs * MAXALIGN(DEF_SEGSIZE * sizeof(SEGMENT));
|
SHMEM_XIDTAB_KEYSIZE,
|
||||||
size += NBACKENDS * /* XXX not multiple of BUCKET_ALLOC_INCR? */
|
SHMEM_XIDTAB_DATASIZE);
|
||||||
(MAXALIGN(sizeof(BUCKET_INDEX)) +
|
|
||||||
MAXALIGN(sizeof(XIDLookupEnt))); /* contains hash key */
|
/* Since the lockHash entry count above is only an estimate,
|
||||||
|
* add 10% safety margin.
|
||||||
|
*/
|
||||||
|
size += size / 10;
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/storage/smgr/Attic/mm.c,v 1.12 1998/09/01 04:32:07 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/storage/smgr/Attic/mm.c,v 1.12.2.1 1999/03/07 02:00:52 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -25,7 +25,6 @@
|
||||||
#include "storage/shmem.h"
|
#include "storage/shmem.h"
|
||||||
#include "storage/spin.h"
|
#include "storage/spin.h"
|
||||||
|
|
||||||
#include "utils/dynahash.h"
|
|
||||||
#include "utils/hsearch.h"
|
#include "utils/hsearch.h"
|
||||||
#include "utils/rel.h"
|
#include "utils/rel.h"
|
||||||
#include "utils/memutils.h"
|
#include "utils/memutils.h"
|
||||||
|
@ -111,7 +110,7 @@ mminit()
|
||||||
}
|
}
|
||||||
|
|
||||||
info.keysize = sizeof(MMCacheTag);
|
info.keysize = sizeof(MMCacheTag);
|
||||||
info.datasize = sizeof(int);
|
info.datasize = sizeof(MMHashEntry) - sizeof(MMCacheTag);
|
||||||
info.hash = tag_hash;
|
info.hash = tag_hash;
|
||||||
|
|
||||||
MMCacheHT = (HTAB *) ShmemInitHash("Main memory store HT",
|
MMCacheHT = (HTAB *) ShmemInitHash("Main memory store HT",
|
||||||
|
@ -125,7 +124,7 @@ mminit()
|
||||||
}
|
}
|
||||||
|
|
||||||
info.keysize = sizeof(MMRelTag);
|
info.keysize = sizeof(MMRelTag);
|
||||||
info.datasize = sizeof(int);
|
info.datasize = sizeof(MMRelHashEntry) - sizeof(MMRelTag);
|
||||||
info.hash = tag_hash;
|
info.hash = tag_hash;
|
||||||
|
|
||||||
MMRelCacheHT = (HTAB *) ShmemInitHash("Main memory rel HT",
|
MMRelCacheHT = (HTAB *) ShmemInitHash("Main memory rel HT",
|
||||||
|
@ -565,36 +564,20 @@ int
|
||||||
MMShmemSize()
|
MMShmemSize()
|
||||||
{
|
{
|
||||||
int size = 0;
|
int size = 0;
|
||||||
int nbuckets;
|
|
||||||
int nsegs;
|
|
||||||
int tmp;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* first compute space occupied by the (dbid,relid,blkno) hash table
|
* first compute space occupied by the (dbid,relid,blkno) hash table
|
||||||
*/
|
*/
|
||||||
|
size += hash_estimate_size(MMNBUFFERS,
|
||||||
nbuckets = 1 << (int) my_log2((MMNBUFFERS - 1) / DEF_FFACTOR + 1);
|
0, /* MMHashEntry includes key */
|
||||||
nsegs = 1 << (int) my_log2((nbuckets - 1) / DEF_SEGSIZE + 1);
|
sizeof(MMHashEntry));
|
||||||
|
|
||||||
size += MAXALIGN(my_log2(MMNBUFFERS) * sizeof(void *));
|
|
||||||
size += MAXALIGN(sizeof(HHDR));
|
|
||||||
size += nsegs * MAXALIGN(DEF_SEGSIZE * sizeof(SEGMENT));
|
|
||||||
tmp = (int) ceil((double) MMNBUFFERS / BUCKET_ALLOC_INCR);
|
|
||||||
size += tmp * BUCKET_ALLOC_INCR *
|
|
||||||
(MAXALIGN(sizeof(BUCKET_INDEX)) +
|
|
||||||
MAXALIGN(sizeof(MMHashEntry))); /* contains hash key */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* now do the same for the rel hash table
|
* now do the same for the rel hash table
|
||||||
*/
|
*/
|
||||||
|
size += hash_estimate_size(MMNRELATIONS,
|
||||||
size += MAXALIGN(my_log2(MMNRELATIONS) * sizeof(void *));
|
0, /* MMRelHashEntry includes key */
|
||||||
size += MAXALIGN(sizeof(HHDR));
|
sizeof(MMRelHashEntry));
|
||||||
size += nsegs * MAXALIGN(DEF_SEGSIZE * sizeof(SEGMENT));
|
|
||||||
tmp = (int) ceil((double) MMNRELATIONS / BUCKET_ALLOC_INCR);
|
|
||||||
size += tmp * BUCKET_ALLOC_INCR *
|
|
||||||
(MAXALIGN(sizeof(BUCKET_INDEX)) +
|
|
||||||
MAXALIGN(sizeof(MMRelHashEntry))); /* contains hash key */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* finally, add in the memory block we use directly
|
* finally, add in the memory block we use directly
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* dynahash.c--
|
* dynahash.c
|
||||||
* dynamic hashing
|
* dynamic hashing
|
||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/hash/dynahash.c,v 1.16 1998/09/01 04:33:11 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/hash/dynahash.c,v 1.16.2.1 1999/03/07 02:01:02 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -174,7 +174,9 @@ hash_create(int nelem, HASHCTL *info, int flags)
|
||||||
|
|
||||||
if (flags & HASH_SHARED_MEM)
|
if (flags & HASH_SHARED_MEM)
|
||||||
{
|
{
|
||||||
/* ctl structure is preallocated for shared memory tables */
|
/* ctl structure is preallocated for shared memory tables.
|
||||||
|
* Note that HASH_DIRSIZE had better be set as well.
|
||||||
|
*/
|
||||||
|
|
||||||
hashp->hctl = (HHDR *) info->hctl;
|
hashp->hctl = (HHDR *) info->hctl;
|
||||||
hashp->segbase = (char *) info->segbase;
|
hashp->segbase = (char *) info->segbase;
|
||||||
|
@ -190,6 +192,7 @@ hash_create(int nelem, HASHCTL *info, int flags)
|
||||||
{
|
{
|
||||||
/* setup hash table defaults */
|
/* setup hash table defaults */
|
||||||
|
|
||||||
|
hashp->hctl = NULL;
|
||||||
hashp->alloc = (dhalloc_ptr) MEM_ALLOC;
|
hashp->alloc = (dhalloc_ptr) MEM_ALLOC;
|
||||||
hashp->dir = NULL;
|
hashp->dir = NULL;
|
||||||
hashp->segbase = NULL;
|
hashp->segbase = NULL;
|
||||||
|
@ -210,11 +213,6 @@ hash_create(int nelem, HASHCTL *info, int flags)
|
||||||
hctl->accesses = hctl->collisions = 0;
|
hctl->accesses = hctl->collisions = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (flags & HASH_BUCKET)
|
|
||||||
{
|
|
||||||
hctl->bsize = info->bsize;
|
|
||||||
hctl->bshift = my_log2(info->bsize);
|
|
||||||
}
|
|
||||||
if (flags & HASH_SEGMENT)
|
if (flags & HASH_SEGMENT)
|
||||||
{
|
{
|
||||||
hctl->ssize = info->ssize;
|
hctl->ssize = info->ssize;
|
||||||
|
@ -224,13 +222,12 @@ hash_create(int nelem, HASHCTL *info, int flags)
|
||||||
hctl->ffactor = info->ffactor;
|
hctl->ffactor = info->ffactor;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SHM hash tables have fixed maximum size (allocate a maximal sized
|
* SHM hash tables have fixed directory size passed by the caller.
|
||||||
* directory).
|
|
||||||
*/
|
*/
|
||||||
if (flags & HASH_DIRSIZE)
|
if (flags & HASH_DIRSIZE)
|
||||||
{
|
{
|
||||||
hctl->max_dsize = my_log2(info->max_size);
|
hctl->max_dsize = info->max_dsize;
|
||||||
hctl->dsize = my_log2(info->dsize);
|
hctl->dsize = info->dsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -254,8 +251,8 @@ hash_create(int nelem, HASHCTL *info, int flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Allocate and initialize an HTAB structure
|
* Set default HHDR parameters.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
hdefault(HTAB *hashp)
|
hdefault(HTAB *hashp)
|
||||||
{
|
{
|
||||||
|
@ -264,8 +261,6 @@ hdefault(HTAB *hashp)
|
||||||
MemSet(hashp->hctl, 0, sizeof(HHDR));
|
MemSet(hashp->hctl, 0, sizeof(HHDR));
|
||||||
|
|
||||||
hctl = hashp->hctl;
|
hctl = hashp->hctl;
|
||||||
hctl->bsize = DEF_BUCKET_SIZE;
|
|
||||||
hctl->bshift = DEF_BUCKET_SHIFT;
|
|
||||||
hctl->ssize = DEF_SEGSIZE;
|
hctl->ssize = DEF_SEGSIZE;
|
||||||
hctl->sshift = DEF_SEGSIZE_SHIFT;
|
hctl->sshift = DEF_SEGSIZE_SHIFT;
|
||||||
hctl->dsize = DEF_DIRSIZE;
|
hctl->dsize = DEF_DIRSIZE;
|
||||||
|
@ -295,42 +290,44 @@ init_htab(HTAB *hashp, int nelem)
|
||||||
SEG_OFFSET *segp;
|
SEG_OFFSET *segp;
|
||||||
int nbuckets;
|
int nbuckets;
|
||||||
int nsegs;
|
int nsegs;
|
||||||
int l2;
|
|
||||||
HHDR *hctl;
|
HHDR *hctl;
|
||||||
|
|
||||||
hctl = hashp->hctl;
|
hctl = hashp->hctl;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Divide number of elements by the fill factor and determine a
|
* Divide number of elements by the fill factor to determine a
|
||||||
* desired number of buckets. Allocate space for the next greater
|
* desired number of buckets. Allocate space for the next greater
|
||||||
* power of two number of buckets
|
* power of two number of buckets
|
||||||
*/
|
*/
|
||||||
nelem = (nelem - 1) / hctl->ffactor + 1;
|
nelem = (nelem - 1) / hctl->ffactor + 1;
|
||||||
|
|
||||||
l2 = my_log2(nelem);
|
nbuckets = 1 << my_log2(nelem);
|
||||||
nbuckets = 1 << l2;
|
|
||||||
|
|
||||||
hctl->max_bucket = hctl->low_mask = nbuckets - 1;
|
hctl->max_bucket = hctl->low_mask = nbuckets - 1;
|
||||||
hctl->high_mask = (nbuckets << 1) - 1;
|
hctl->high_mask = (nbuckets << 1) - 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Figure number of directory segments needed, round up to a power of 2
|
||||||
|
*/
|
||||||
nsegs = (nbuckets - 1) / hctl->ssize + 1;
|
nsegs = (nbuckets - 1) / hctl->ssize + 1;
|
||||||
nsegs = 1 << my_log2(nsegs);
|
nsegs = 1 << my_log2(nsegs);
|
||||||
|
|
||||||
if (nsegs > hctl->dsize)
|
|
||||||
hctl->dsize = nsegs;
|
|
||||||
|
|
||||||
/* Use two low order bits of points ???? */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if ( !(hctl->mem = bit_alloc ( nbuckets )) ) return(-1); if (
|
* Make sure directory is big enough.
|
||||||
* !(hctl->mod = bit_alloc ( nbuckets )) ) return(-1);
|
* If pre-allocated directory is too small, choke (caller screwed up).
|
||||||
*/
|
*/
|
||||||
|
if (nsegs > hctl->dsize)
|
||||||
|
{
|
||||||
|
if (!(hashp->dir))
|
||||||
|
hctl->dsize = nsegs;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* allocate a directory */
|
/* Allocate a directory */
|
||||||
if (!(hashp->dir))
|
if (!(hashp->dir))
|
||||||
{
|
{
|
||||||
hashp->dir =
|
hashp->dir = (SEG_OFFSET *) hashp->alloc(hctl->dsize * sizeof(SEG_OFFSET));
|
||||||
(SEG_OFFSET *) hashp->alloc(hctl->dsize * sizeof(SEG_OFFSET));
|
|
||||||
if (!hashp->dir)
|
if (!hashp->dir)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -347,11 +344,9 @@ init_htab(HTAB *hashp, int nelem)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HASH_DEBUG
|
#if HASH_DEBUG
|
||||||
fprintf(stderr, "%s\n%s%x\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%x\n%s%x\n%s%d\n%s%d\n",
|
fprintf(stderr, "%s\n%s%x\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%x\n%s%x\n%s%d\n%s%d\n",
|
||||||
"init_htab:",
|
"init_htab:",
|
||||||
"TABLE POINTER ", hashp,
|
"TABLE POINTER ", hashp,
|
||||||
"BUCKET SIZE ", hctl->bsize,
|
|
||||||
"BUCKET SHIFT ", hctl->bshift,
|
|
||||||
"DIRECTORY SIZE ", hctl->dsize,
|
"DIRECTORY SIZE ", hctl->dsize,
|
||||||
"SEGMENT SIZE ", hctl->ssize,
|
"SEGMENT SIZE ", hctl->ssize,
|
||||||
"SEGMENT SHIFT ", hctl->sshift,
|
"SEGMENT SHIFT ", hctl->sshift,
|
||||||
|
@ -365,14 +360,59 @@ init_htab(HTAB *hashp, int nelem)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Estimate the space needed for a hashtable containing the given number
|
||||||
|
* of entries of given size.
|
||||||
|
* NOTE: this is used to estimate the footprint of hashtables in shared
|
||||||
|
* memory; therefore it does not count HTAB which is in local memory.
|
||||||
|
* NB: assumes that all hash structure parameters have default values!
|
||||||
|
*/
|
||||||
|
long
|
||||||
|
hash_estimate_size(long num_entries, long keysize, long datasize)
|
||||||
|
{
|
||||||
|
long size = 0;
|
||||||
|
long nBuckets,
|
||||||
|
nSegments,
|
||||||
|
nDirEntries,
|
||||||
|
nRecordAllocs,
|
||||||
|
recordSize;
|
||||||
|
|
||||||
|
/* estimate number of buckets wanted */
|
||||||
|
nBuckets = 1L << my_log2((num_entries - 1) / DEF_FFACTOR + 1);
|
||||||
|
/* # of segments needed for nBuckets */
|
||||||
|
nSegments = 1L << my_log2((nBuckets - 1) / DEF_SEGSIZE + 1);
|
||||||
|
/* directory entries */
|
||||||
|
nDirEntries = DEF_DIRSIZE;
|
||||||
|
while (nDirEntries < nSegments)
|
||||||
|
nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */
|
||||||
|
|
||||||
|
/* fixed control info */
|
||||||
|
size += MAXALIGN(sizeof(HHDR)); /* but not HTAB, per above */
|
||||||
|
/* directory */
|
||||||
|
size += MAXALIGN(nDirEntries * sizeof(SEG_OFFSET));
|
||||||
|
/* segments */
|
||||||
|
size += nSegments * MAXALIGN(DEF_SEGSIZE * sizeof(BUCKET_INDEX));
|
||||||
|
/* records --- allocated in groups of BUCKET_ALLOC_INCR */
|
||||||
|
recordSize = sizeof(BUCKET_INDEX) + keysize + datasize;
|
||||||
|
recordSize = MAXALIGN(recordSize);
|
||||||
|
nRecordAllocs = (num_entries - 1) / BUCKET_ALLOC_INCR + 1;
|
||||||
|
size += nRecordAllocs * BUCKET_ALLOC_INCR * recordSize;
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/********************** DESTROY ROUTINES ************************/
|
/********************** DESTROY ROUTINES ************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX this sure looks thoroughly broken to me --- tgl 2/99.
|
||||||
|
* It's freeing every entry individually --- but they weren't
|
||||||
|
* allocated individually, see bucket_alloc!! Why doesn't it crash?
|
||||||
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
hash_destroy(HTAB *hashp)
|
hash_destroy(HTAB *hashp)
|
||||||
{
|
{
|
||||||
/* cannot destroy a shared memory hash table */
|
|
||||||
Assert(!hashp->segbase);
|
|
||||||
|
|
||||||
if (hashp != NULL)
|
if (hashp != NULL)
|
||||||
{
|
{
|
||||||
SEG_OFFSET segNum;
|
SEG_OFFSET segNum;
|
||||||
|
@ -384,6 +424,13 @@ hash_destroy(HTAB *hashp)
|
||||||
q;
|
q;
|
||||||
ELEMENT *curr;
|
ELEMENT *curr;
|
||||||
|
|
||||||
|
/* cannot destroy a shared memory hash table */
|
||||||
|
Assert(!hashp->segbase);
|
||||||
|
/* allocation method must be one we know how to free, too */
|
||||||
|
Assert(hashp->alloc == (dhalloc_ptr) MEM_ALLOC);
|
||||||
|
|
||||||
|
hash_stats("destroy", hashp);
|
||||||
|
|
||||||
for (segNum = 0; nsegs > 0; nsegs--, segNum++)
|
for (segNum = 0; nsegs > 0; nsegs--, segNum++)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -397,11 +444,10 @@ hash_destroy(HTAB *hashp)
|
||||||
MEM_FREE((char *) curr);
|
MEM_FREE((char *) curr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free((char *) segp);
|
MEM_FREE((char *) segp);
|
||||||
}
|
}
|
||||||
MEM_FREE((char *) hashp->dir);
|
MEM_FREE((char *) hashp->dir);
|
||||||
MEM_FREE((char *) hashp->hctl);
|
MEM_FREE((char *) hashp->hctl);
|
||||||
hash_stats("destroy", hashp);
|
|
||||||
MEM_FREE((char *) hashp);
|
MEM_FREE((char *) hashp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -603,7 +649,7 @@ hash_search(HTAB *hashp,
|
||||||
/* link into chain */
|
/* link into chain */
|
||||||
*prevIndexPtr = currIndex;
|
*prevIndexPtr = currIndex;
|
||||||
|
|
||||||
/* copy key and data */
|
/* copy key into record */
|
||||||
destAddr = (char *) &(curr->key);
|
destAddr = (char *) &(curr->key);
|
||||||
memmove(destAddr, keyPtr, hctl->keysize);
|
memmove(destAddr, keyPtr, hctl->keysize);
|
||||||
curr->next = INVALID_INDEX;
|
curr->next = INVALID_INDEX;
|
||||||
|
@ -618,13 +664,10 @@ hash_search(HTAB *hashp,
|
||||||
*/
|
*/
|
||||||
if (++hctl->nkeys / (hctl->max_bucket + 1) > hctl->ffactor)
|
if (++hctl->nkeys / (hctl->max_bucket + 1) > hctl->ffactor)
|
||||||
{
|
{
|
||||||
|
/* NOTE: failure to expand table is not a fatal error,
|
||||||
/*
|
* it just means we have to run at higher fill factor than we wanted.
|
||||||
* fprintf(stderr,"expanding on '%s'\n",keyPtr);
|
|
||||||
* hash_stats("expanded table",hashp);
|
|
||||||
*/
|
*/
|
||||||
if (!expand_table(hashp))
|
expand_table(hashp);
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
return &(curr->key);
|
return &(curr->key);
|
||||||
}
|
}
|
||||||
|
@ -725,23 +768,25 @@ expand_table(HTAB *hashp)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
hctl = hashp->hctl;
|
hctl = hashp->hctl;
|
||||||
new_bucket = ++hctl->max_bucket;
|
|
||||||
old_bucket = (hctl->max_bucket & hctl->low_mask);
|
|
||||||
|
|
||||||
|
new_bucket = hctl->max_bucket + 1;
|
||||||
new_segnum = new_bucket >> hctl->sshift;
|
new_segnum = new_bucket >> hctl->sshift;
|
||||||
new_segndx = MOD(new_bucket, hctl->ssize);
|
new_segndx = MOD(new_bucket, hctl->ssize);
|
||||||
|
|
||||||
if (new_segnum >= hctl->nsegs)
|
if (new_segnum >= hctl->nsegs)
|
||||||
{
|
{
|
||||||
|
/* Allocate new segment if necessary -- could fail if dir full */
|
||||||
/* Allocate new segment if necessary */
|
|
||||||
if (new_segnum >= hctl->dsize)
|
if (new_segnum >= hctl->dsize)
|
||||||
dir_realloc(hashp);
|
if (! dir_realloc(hashp))
|
||||||
|
return 0;
|
||||||
if (!(hashp->dir[new_segnum] = seg_alloc(hashp)))
|
if (!(hashp->dir[new_segnum] = seg_alloc(hashp)))
|
||||||
return 0;
|
return 0;
|
||||||
hctl->nsegs++;
|
hctl->nsegs++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* OK, we got a new bucket */
|
||||||
|
hctl->max_bucket++;
|
||||||
|
old_bucket = (hctl->max_bucket & hctl->low_mask);
|
||||||
|
|
||||||
if (new_bucket > hctl->high_mask)
|
if (new_bucket > hctl->high_mask)
|
||||||
{
|
{
|
||||||
|
@ -790,31 +835,32 @@ static int
|
||||||
dir_realloc(HTAB *hashp)
|
dir_realloc(HTAB *hashp)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
char **p_ptr;
|
char *old_p;
|
||||||
|
long new_dsize;
|
||||||
long old_dirsize;
|
long old_dirsize;
|
||||||
long new_dirsize;
|
long new_dirsize;
|
||||||
|
|
||||||
|
|
||||||
if (hashp->hctl->max_dsize != NO_MAX_DSIZE)
|
if (hashp->hctl->max_dsize != NO_MAX_DSIZE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Reallocate directory */
|
/* Reallocate directory */
|
||||||
old_dirsize = hashp->hctl->dsize * sizeof(SEGMENT *);
|
new_dsize = hashp->hctl->dsize << 1;
|
||||||
new_dirsize = old_dirsize << 1;
|
old_dirsize = hashp->hctl->dsize * sizeof(SEG_OFFSET);
|
||||||
|
new_dirsize = new_dsize * sizeof(SEG_OFFSET);
|
||||||
|
|
||||||
p_ptr = (char **) hashp->dir;
|
old_p = (char *) hashp->dir;
|
||||||
p = (char *) hashp->alloc((unsigned long) new_dirsize);
|
p = (char *) hashp->alloc((unsigned long) new_dirsize);
|
||||||
|
|
||||||
if (p != NULL)
|
if (p != NULL)
|
||||||
{
|
{
|
||||||
memmove(p, *p_ptr, old_dirsize);
|
memmove(p, old_p, old_dirsize);
|
||||||
MemSet(*p_ptr + old_dirsize, 0, new_dirsize - old_dirsize);
|
MemSet(p + old_dirsize, 0, new_dirsize - old_dirsize);
|
||||||
free((char *) *p_ptr);
|
MEM_FREE((char *) old_p);
|
||||||
*p_ptr = p;
|
hashp->dir = (SEG_OFFSET *) p;
|
||||||
hashp->hctl->dsize = new_dirsize;
|
hashp->hctl->dsize = new_dsize;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -824,15 +870,14 @@ seg_alloc(HTAB *hashp)
|
||||||
SEGMENT segp;
|
SEGMENT segp;
|
||||||
SEG_OFFSET segOffset;
|
SEG_OFFSET segOffset;
|
||||||
|
|
||||||
|
|
||||||
segp = (SEGMENT) hashp->alloc((unsigned long)
|
segp = (SEGMENT) hashp->alloc((unsigned long)
|
||||||
sizeof(SEGMENT) * hashp->hctl->ssize);
|
sizeof(BUCKET_INDEX) * hashp->hctl->ssize);
|
||||||
|
|
||||||
if (!segp)
|
if (!segp)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
MemSet((char *) segp, 0,
|
MemSet((char *) segp, 0,
|
||||||
(long) sizeof(SEGMENT) * hashp->hctl->ssize);
|
(long) sizeof(BUCKET_INDEX) * hashp->hctl->ssize);
|
||||||
|
|
||||||
segOffset = MAKE_HASHOFFSET(hashp, segp);
|
segOffset = MAKE_HASHOFFSET(hashp, segp);
|
||||||
return segOffset;
|
return segOffset;
|
||||||
|
@ -850,11 +895,11 @@ bucket_alloc(HTAB *hashp)
|
||||||
BUCKET_INDEX tmpIndex,
|
BUCKET_INDEX tmpIndex,
|
||||||
lastIndex;
|
lastIndex;
|
||||||
|
|
||||||
bucketSize =
|
/* Each bucket has a BUCKET_INDEX header plus user data. */
|
||||||
sizeof(BUCKET_INDEX) + hashp->hctl->keysize + hashp->hctl->datasize;
|
bucketSize = sizeof(BUCKET_INDEX) + hashp->hctl->keysize + hashp->hctl->datasize;
|
||||||
|
|
||||||
/* make sure its aligned correctly */
|
/* make sure its aligned correctly */
|
||||||
bucketSize += sizeof(long *) - (bucketSize % sizeof(long *));
|
bucketSize = MAXALIGN(bucketSize);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* tmpIndex is the shmem offset into the first bucket of the array.
|
* tmpIndex is the shmem offset into the first bucket of the array.
|
||||||
|
@ -871,8 +916,10 @@ bucket_alloc(HTAB *hashp)
|
||||||
lastIndex = hashp->hctl->freeBucketIndex;
|
lastIndex = hashp->hctl->freeBucketIndex;
|
||||||
hashp->hctl->freeBucketIndex = tmpIndex;
|
hashp->hctl->freeBucketIndex = tmpIndex;
|
||||||
|
|
||||||
/* initialize each bucket to point to the one behind it */
|
/* initialize each bucket to point to the one behind it.
|
||||||
for (i = 0; i < (BUCKET_ALLOC_INCR - 1); i++)
|
* NOTE: loop sets last bucket incorrectly; we fix below.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < BUCKET_ALLOC_INCR; i++)
|
||||||
{
|
{
|
||||||
tmpBucket = GET_BUCKET(hashp, tmpIndex);
|
tmpBucket = GET_BUCKET(hashp, tmpIndex);
|
||||||
tmpIndex += bucketSize;
|
tmpIndex += bucketSize;
|
||||||
|
@ -881,20 +928,21 @@ bucket_alloc(HTAB *hashp)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* the last bucket points to the old freelist head (which is probably
|
* the last bucket points to the old freelist head (which is probably
|
||||||
* invalid or we wouldnt be here)
|
* invalid or we wouldn't be here)
|
||||||
*/
|
*/
|
||||||
tmpBucket->next = lastIndex;
|
tmpBucket->next = lastIndex;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* calculate the log base 2 of num */
|
/* calculate ceil(log base 2) of num */
|
||||||
int
|
int
|
||||||
my_log2(long num)
|
my_log2(long num)
|
||||||
{
|
{
|
||||||
int i = 1;
|
int i;
|
||||||
int limit;
|
long limit;
|
||||||
|
|
||||||
for (i = 0, limit = 1; limit < num; limit = 2 * limit, i++);
|
for (i = 0, limit = 1; limit < num; i++, limit <<= 1)
|
||||||
|
;
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: lock.h,v 1.19 1998/10/08 18:30:45 momjian Exp $
|
* $Id: lock.h,v 1.19.2.1 1999/03/07 02:00:47 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -175,6 +175,9 @@ typedef struct XIDLookupEnt
|
||||||
SHM_QUEUE queue;
|
SHM_QUEUE queue;
|
||||||
} XIDLookupEnt;
|
} XIDLookupEnt;
|
||||||
|
|
||||||
|
#define SHMEM_XIDTAB_KEYSIZE sizeof(XIDTAG)
|
||||||
|
#define SHMEM_XIDTAB_DATASIZE (sizeof(XIDLookupEnt) - SHMEM_XIDTAB_KEYSIZE)
|
||||||
|
|
||||||
#define XID_TAGSIZE (sizeof(XIDTAG))
|
#define XID_TAGSIZE (sizeof(XIDTAG))
|
||||||
#define XIDENT_LOCKMETHOD(xident) (XIDTAG_LOCKMETHOD((xident).tag))
|
#define XIDENT_LOCKMETHOD(xident) (XIDTAG_LOCKMETHOD((xident).tag))
|
||||||
|
|
||||||
|
@ -211,6 +214,9 @@ typedef struct LOCK
|
||||||
int nActive;
|
int nActive;
|
||||||
} LOCK;
|
} LOCK;
|
||||||
|
|
||||||
|
#define SHMEM_LOCKTAB_KEYSIZE sizeof(LOCKTAG)
|
||||||
|
#define SHMEM_LOCKTAB_DATASIZE (sizeof(LOCK) - SHMEM_LOCKTAB_KEYSIZE)
|
||||||
|
|
||||||
#define LOCK_LOCKMETHOD(lock) (LOCKTAG_LOCKMETHOD((lock).tag))
|
#define LOCK_LOCKMETHOD(lock) (LOCKTAG_LOCKMETHOD((lock).tag))
|
||||||
|
|
||||||
#define LockGetLock_nHolders(l) l->nHolders
|
#define LockGetLock_nHolders(l) l->nHolders
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: hsearch.h,v 1.9 1998/09/01 04:39:12 momjian Exp $
|
* $Id: hsearch.h,v 1.9.2.1 1999/03/07 02:01:09 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -16,16 +16,23 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Constants
|
* Constants
|
||||||
|
*
|
||||||
|
* A hash table has a top-level "directory", each of whose entries points
|
||||||
|
* to a "segment" of ssize bucket headers. The maximum number of hash
|
||||||
|
* buckets is thus dsize * ssize (but dsize may be expansible). Of course,
|
||||||
|
* the number of records in the table can be larger, but we don't want a
|
||||||
|
* whole lot of records per bucket or performance goes down.
|
||||||
|
*
|
||||||
|
* In a hash table allocated in shared memory, the directory cannot be
|
||||||
|
* expanded because it must stay at a fixed address.
|
||||||
*/
|
*/
|
||||||
#define DEF_BUCKET_SIZE 256
|
|
||||||
#define DEF_BUCKET_SHIFT 8/* log2(BUCKET) */
|
|
||||||
#define DEF_SEGSIZE 256
|
#define DEF_SEGSIZE 256
|
||||||
#define DEF_SEGSIZE_SHIFT 8 /* log2(SEGSIZE) */
|
#define DEF_SEGSIZE_SHIFT 8 /* log2(SEGSIZE) */
|
||||||
#define DEF_DIRSIZE 256
|
#define DEF_DIRSIZE 256
|
||||||
#define PRIME1 37
|
#define DEF_FFACTOR 1 /* default fill factor */
|
||||||
|
|
||||||
|
#define PRIME1 37 /* for the hash function */
|
||||||
#define PRIME2 1048583
|
#define PRIME2 1048583
|
||||||
#define DEF_FFACTOR 1
|
|
||||||
#define SPLTMAX 8
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -46,10 +53,8 @@ typedef unsigned long SEG_OFFSET;
|
||||||
|
|
||||||
typedef struct hashhdr
|
typedef struct hashhdr
|
||||||
{
|
{
|
||||||
long bsize; /* Bucket/Page Size */
|
|
||||||
long bshift; /* Bucket shift */
|
|
||||||
long dsize; /* Directory Size */
|
long dsize; /* Directory Size */
|
||||||
long ssize; /* Segment Size */
|
long ssize; /* Segment Size --- must be power of 2 */
|
||||||
long sshift; /* Segment shift */
|
long sshift; /* Segment shift */
|
||||||
long max_bucket; /* ID of Maximum bucket in use */
|
long max_bucket; /* ID of Maximum bucket in use */
|
||||||
long high_mask; /* Mask to modulo into entire table */
|
long high_mask; /* Mask to modulo into entire table */
|
||||||
|
@ -59,8 +64,7 @@ typedef struct hashhdr
|
||||||
long nsegs; /* Number of allocated segments */
|
long nsegs; /* Number of allocated segments */
|
||||||
long keysize; /* hash key length in bytes */
|
long keysize; /* hash key length in bytes */
|
||||||
long datasize; /* elem data length in bytes */
|
long datasize; /* elem data length in bytes */
|
||||||
long max_dsize; /* 'dsize' limit if directory is fixed
|
long max_dsize; /* 'dsize' limit if directory is fixed size */
|
||||||
* size */
|
|
||||||
BUCKET_INDEX freeBucketIndex;
|
BUCKET_INDEX freeBucketIndex;
|
||||||
/* index of first free bucket */
|
/* index of first free bucket */
|
||||||
#ifdef HASH_STATISTICS
|
#ifdef HASH_STATISTICS
|
||||||
|
@ -83,14 +87,13 @@ typedef struct htab
|
||||||
|
|
||||||
typedef struct hashctl
|
typedef struct hashctl
|
||||||
{
|
{
|
||||||
long bsize; /* Bucket Size */
|
|
||||||
long ssize; /* Segment Size */
|
long ssize; /* Segment Size */
|
||||||
long dsize; /* Dirsize Size */
|
long dsize; /* Dirsize Size */
|
||||||
long ffactor; /* Fill factor */
|
long ffactor; /* Fill factor */
|
||||||
long (*hash) (); /* Hash Function */
|
long (*hash) (); /* Hash Function */
|
||||||
long keysize; /* hash key length in bytes */
|
long keysize; /* hash key length in bytes */
|
||||||
long datasize; /* elem data length in bytes */
|
long datasize; /* elem data length in bytes */
|
||||||
long max_size; /* limit to dsize if directory size is
|
long max_dsize; /* limit to dsize if directory size is
|
||||||
* limited */
|
* limited */
|
||||||
long *segbase; /* base for calculating bucket + seg ptrs */
|
long *segbase; /* base for calculating bucket + seg ptrs */
|
||||||
long *(*alloc) (); /* memory allocation function */
|
long *(*alloc) (); /* memory allocation function */
|
||||||
|
@ -100,7 +103,6 @@ typedef struct hashctl
|
||||||
} HASHCTL;
|
} HASHCTL;
|
||||||
|
|
||||||
/* Flags to indicate action for hctl */
|
/* Flags to indicate action for hctl */
|
||||||
#define HASH_BUCKET 0x001 /* Setting bucket size */
|
|
||||||
#define HASH_SEGMENT 0x002 /* Setting segment size */
|
#define HASH_SEGMENT 0x002 /* Setting segment size */
|
||||||
#define HASH_DIRSIZE 0x004 /* Setting directory size */
|
#define HASH_DIRSIZE 0x004 /* Setting directory size */
|
||||||
#define HASH_FFACTOR 0x008 /* Setting fill factor */
|
#define HASH_FFACTOR 0x008 /* Setting fill factor */
|
||||||
|
@ -136,6 +138,7 @@ extern void hash_stats(char *where, HTAB *hashp);
|
||||||
extern long *hash_search(HTAB *hashp, char *keyPtr, HASHACTION action,
|
extern long *hash_search(HTAB *hashp, char *keyPtr, HASHACTION action,
|
||||||
bool *foundPtr);
|
bool *foundPtr);
|
||||||
extern long *hash_seq(HTAB *hashp);
|
extern long *hash_seq(HTAB *hashp);
|
||||||
|
extern long hash_estimate_size(long num_entries, long keysize, long datasize);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* prototypes from functions in hashfn.c
|
* prototypes from functions in hashfn.c
|
||||||
|
|
Loading…
Reference in New Issue