Commit bcfdc9df authored by Tom Lane's avatar Tom Lane

Repair some pretty serious problems in dynahash.c and

shared memory space allocation.  It's a wonder we have not seen bug
reports traceable to this area ... it's quite clear that the routine
dir_realloc() has never worked correctly, for example.
parent ceb233ed
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.21 1999/02/13 23:17:54 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.22 1999/02/22 06:16:50 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -33,7 +33,6 @@ ...@@ -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 */
...@@ -261,21 +260,11 @@ int ...@@ -261,21 +260,11 @@ int
BufferShmemSize() BufferShmemSize()
{ {
int size = 0; int size = 0;
int nbuckets;
int nsegs; /* size of shmem index hash table */
int tmp; size += hash_estimate_size(SHMEM_INDEX_SIZE,
SHMEM_INDEX_KEYSIZE,
nbuckets = 1 << (int) my_log2((NBuffers - 1) / DEF_FFACTOR + 1); SHMEM_INDEX_DATASIZE);
nsegs = 1 << (int) my_log2((nbuckets - 1) / DEF_SEGSIZE + 1);
/* size of shmem index table */
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));
...@@ -284,17 +273,13 @@ BufferShmemSize() ...@@ -284,17 +273,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 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipci.c,v 1.21 1999/02/21 01:41:44 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipci.c,v 1.22 1999/02/22 06:16:49 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -72,11 +72,19 @@ CreateSharedMemoryAndSemaphores(IPCKey key, int maxBackends) ...@@ -72,11 +72,19 @@ CreateSharedMemoryAndSemaphores(IPCKey key, int maxBackends)
* ---------------- * ----------------
*/ */
CreateSpinlocks(IPCKeyGetSpinLockSemaphoreKey(key)); CreateSpinlocks(IPCKeyGetSpinLockSemaphoreKey(key));
size = BufferShmemSize() + LockShmemSize(maxBackends);
/*
* 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.
* Then we add 10% for a safety margin.
*/
size = BufferShmemSize() + LockShmemSize(maxBackends);
#ifdef STABLE_MEMORY_STORAGE #ifdef STABLE_MEMORY_STORAGE
size += MMShmemSize(); size += MMShmemSize();
#endif #endif
size += 100000;
size += size / 10;
if (DebugLvl > 1) if (DebugLvl > 1)
{ {
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/shmem.c,v 1.36 1999/02/13 23:18:13 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/ipc/shmem.c,v 1.37 1999/02/22 06:16:48 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -65,7 +65,6 @@ ...@@ -65,7 +65,6 @@
#include "storage/shmem.h" #include "storage/shmem.h"
#include "storage/spin.h" #include "storage/spin.h"
#include "storage/proc.h" #include "storage/proc.h"
#include "utils/dynahash.h"
#include "utils/hsearch.h" #include "utils/hsearch.h"
#include "utils/memutils.h" #include "utils/memutils.h"
#include "access/xact.h" #include "access/xact.h"
...@@ -215,7 +214,7 @@ InitShmem(unsigned int key, unsigned int size) ...@@ -215,7 +214,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 +339,8 @@ ShmemIsValid(unsigned long addr) ...@@ -340,8 +339,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,17 +348,20 @@ ShmemInitHash(char *name, /* table string name for shmem index */ ...@@ -349,17 +348,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 = ShmemInitStruct(name, my_log2(max_size) + sizeof(HHDR), &found); location = ShmemInitStruct(name,
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
...@@ -375,13 +377,11 @@ ShmemInitHash(char *name, /* table string name for shmem index */ ...@@ -375,13 +377,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 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.44 1999/02/21 03:49:22 scrappy Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.45 1999/02/22 06:16:52 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 @@ ...@@ -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"
...@@ -1481,36 +1480,21 @@ int ...@@ -1481,36 +1480,21 @@ int
LockShmemSize(int maxBackends) LockShmemSize(int maxBackends)
{ {
int size = 0; int size = 0;
int nLockEnts = NLOCKENTS(maxBackends);
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(sizeof(PROC_HDR)); /* ProcGlobal */
size += MAXALIGN(maxBackends * sizeof(PROC)); /* each MyProc */ size += MAXALIGN(maxBackends * sizeof(PROC)); /* each MyProc */
size += MAXALIGN(maxBackends * sizeof(LOCKMETHODCTL)); /* each size += MAXALIGN(maxBackends * sizeof(LOCKMETHODCTL)); /* each
* lockMethodTable->ctl */ * lockMethodTable->ctl */
size += MAXALIGN(sizeof(PROC_HDR)); /* ProcGlobal */
size += MAXALIGN(my_log2(nLockEnts) * sizeof(void *)); /* lockHash table */
size += MAXALIGN(sizeof(HHDR)); size += hash_estimate_size(NLOCKENTS(maxBackends),
size += nLockSegs * MAXALIGN(DEF_SEGSIZE * sizeof(SEGMENT)); sizeof(LOCKTAG),
size += nLockEnts * /* XXX not multiple of BUCKET_ALLOC_INCR? */ sizeof(LOCK));
(MAXALIGN(sizeof(BUCKET_INDEX)) +
MAXALIGN(sizeof(LOCK))); /* contains hash key */ /* xidHash table */
size += hash_estimate_size(maxBackends,
size += MAXALIGN(my_log2(maxBackends) * sizeof(void *)); XID_TAGSIZE,
size += MAXALIGN(sizeof(HHDR)); sizeof(XIDLookupEnt));
size += nXidSegs * MAXALIGN(DEF_SEGSIZE * sizeof(SEGMENT));
size += maxBackends * /* XXX not multiple of BUCKET_ALLOC_INCR? */
(MAXALIGN(sizeof(BUCKET_INDEX)) +
MAXALIGN(sizeof(XIDLookupEnt))); /* contains hash key */
return size; return size;
} }
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/smgr/Attic/mm.c,v 1.13 1999/02/13 23:18:36 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/smgr/Attic/mm.c,v 1.14 1999/02/22 06:16:57 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -25,7 +25,6 @@ ...@@ -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"
...@@ -565,36 +564,20 @@ int ...@@ -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
......
This diff is collapsed.
...@@ -6,7 +6,7 @@ ...@@ -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.10 1999/02/13 23:22:22 momjian Exp $ * $Id: hsearch.h,v 1.11 1999/02/22 06:16:46 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -16,16 +16,23 @@ ...@@ -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; ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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); ...@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment