From 3a246cc28572db1b96467f15fd4df2be1e32925d Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 28 Sep 2004 20:46:37 +0000 Subject: [PATCH] Arrange to preallocate all required space for the buffer and FSM hash tables in shared memory. This ensures that overflow of the lock table creates no long-lasting problems. Per discussion with Merlin Moncure. --- src/backend/storage/freespace/freespace.c | 6 ++--- src/backend/storage/ipc/shmem.c | 13 +++++++++-- src/backend/storage/lmgr/lock.c | 4 ++-- src/backend/utils/hash/dynahash.c | 27 ++++++++++++++++++----- src/include/storage/shmem.h | 6 ++--- src/include/utils/hsearch.h | 4 ++-- 6 files changed, 42 insertions(+), 18 deletions(-) diff --git a/src/backend/storage/freespace/freespace.c b/src/backend/storage/freespace/freespace.c index 9def3df748..7a7d204bf5 100644 --- a/src/backend/storage/freespace/freespace.c +++ b/src/backend/storage/freespace/freespace.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/freespace/freespace.c,v 1.34 2004/08/29 05:06:47 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/storage/freespace/freespace.c,v 1.35 2004/09/28 20:46:27 tgl Exp $ * * * NOTES: @@ -283,8 +283,8 @@ InitFreeSpaceMap(void) info.hash = tag_hash; FreeSpaceMapRelHash = ShmemInitHash("Free Space Map Hash", - MaxFSMRelations / 10, - MaxFSMRelations, + MaxFSMRelations + 1, + MaxFSMRelations + 1, &info, (HASH_ELEM | HASH_FUNCTION)); diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c index d9cd885039..29ef5413c8 100644 --- a/src/backend/storage/ipc/shmem.c +++ b/src/backend/storage/ipc/shmem.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/ipc/shmem.c,v 1.80 2004/08/29 05:06:48 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/storage/ipc/shmem.c,v 1.81 2004/09/28 20:46:29 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -262,8 +262,17 @@ InitShmemIndex(void) * shared memory hash table. * * We assume caller is doing some kind of synchronization - * so that two people dont try to create/initialize the + * so that two people don't try to create/initialize the * table at once. + * + * max_size is the estimated maximum number of hashtable entries. This is + * not a hard limit, but the access efficiency will degrade if it is + * exceeded substantially (since it's used to compute directory size and + * the hash table buckets will get overfull). + * + * init_size is the number of hashtable entries to preallocate. For a table + * whose maximum size is certain, this should be equal to max_size; that + * ensures that no run-time out-of-shared-memory failures can occur. */ HTAB * ShmemInitHash(const char *name, /* table string name for shmem index */ diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index f90a3fd0e8..9699469e6d 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.140 2004/09/12 18:30:50 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.141 2004/09/28 20:46:32 tgl Exp $ * * NOTES * Outside modules can create a lock table and acquire/release @@ -241,7 +241,7 @@ LockMethodTableInit(const char *tabName, /* Compute init/max size to request for lock hashtables */ max_table_size = NLOCKENTS(maxBackends); - init_table_size = max_table_size / 10; + init_table_size = max_table_size / 2; /* Allocate a string for the shmem index table lookups. */ /* This is just temp space in this routine, so palloc is OK. */ diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index c55bcf38aa..8078994ba5 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/hash/dynahash.c,v 1.53 2004/08/29 05:06:50 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/hash/dynahash.c,v 1.54 2004/09/28 20:46:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -63,7 +63,7 @@ */ static void *DynaHashAlloc(Size size); static HASHSEGMENT seg_alloc(HTAB *hashp); -static bool element_alloc(HTAB *hashp); +static bool element_alloc(HTAB *hashp, int nelem); static bool dir_realloc(HTAB *hashp); static bool expand_table(HTAB *hashp); static bool hdefault(HTAB *hashp); @@ -228,11 +228,26 @@ hash_create(const char *tabname, long nelem, HASHCTL *info, int flags) CurrentDynaHashCxt = hashp->hcxt; } + /* Build the hash directory structure */ if (!init_htab(hashp, nelem)) { hash_destroy(hashp); return NULL; } + + /* + * For a shared hash table, preallocate the requested number of elements. + * This reduces problems with run-time out-of-shared-memory conditions. + */ + if (flags & HASH_SHARED_MEM) + { + if (!element_alloc(hashp, (int) nelem)) + { + hash_destroy(hashp); + return NULL; + } + } + return hashp; } @@ -631,7 +646,7 @@ hash_search(HTAB *hashp, if (currBucket == NULL) { /* no free elements. allocate another chunk of buckets */ - if (!element_alloc(hashp)) + if (!element_alloc(hashp, HASHELEMENT_ALLOC_INCR)) return NULL; /* out of memory */ currBucket = hctl->freeList; Assert(currBucket != NULL); @@ -898,7 +913,7 @@ seg_alloc(HTAB *hashp) * allocate some new elements and link them into the free list */ static bool -element_alloc(HTAB *hashp) +element_alloc(HTAB *hashp, int nelem) { HASHHDR *hctl = hashp->hctl; Size elementSize; @@ -910,13 +925,13 @@ element_alloc(HTAB *hashp) CurrentDynaHashCxt = hashp->hcxt; tmpElement = (HASHELEMENT *) - hashp->alloc(HASHELEMENT_ALLOC_INCR * elementSize); + hashp->alloc(nelem * elementSize); if (!tmpElement) return false; /* link all the new entries into the freelist */ - for (i = 0; i < HASHELEMENT_ALLOC_INCR; i++) + for (i = 0; i < nelem; i++) { tmpElement->link = hctl->freeList; hctl->freeList = tmpElement; diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index b7a0d7b158..fe67be6ac2 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/storage/shmem.h,v 1.42 2004/08/29 04:13:10 momjian Exp $ + * $PostgreSQL: pgsql/src/include/storage/shmem.h,v 1.43 2004/09/28 20:46:35 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -73,8 +73,8 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); /* size constants for the shmem index table */ /* max size of data structure string name */ #define SHMEM_INDEX_KEYSIZE (48) - /* maximum size of the shmem index table */ -#define SHMEM_INDEX_SIZE (100) + /* max size of the shmem index table (not a hard limit) */ +#define SHMEM_INDEX_SIZE (32) /* this is a hash bucket in the shmem index table */ typedef struct diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index c19f662a61..43a86f7c16 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/hsearch.h,v 1.32 2004/08/29 05:06:59 momjian Exp $ + * $PostgreSQL: pgsql/src/include/utils/hsearch.h,v 1.33 2004/09/28 20:46:37 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -135,7 +135,7 @@ typedef struct HASHCTL #define HASH_FFACTOR 0x008 /* Set fill factor */ #define HASH_FUNCTION 0x010 /* Set user defined hash function */ #define HASH_ELEM 0x020 /* Set key/entry size */ -#define HASH_SHARED_MEM 0x040 /* Set shared mem const */ +#define HASH_SHARED_MEM 0x040 /* Hashtable is in shared memory */ #define HASH_ATTACH 0x080 /* Do not initialize hctl */ #define HASH_ALLOC 0x100 /* Set memory allocator */ #define HASH_CONTEXT 0x200 /* Set explicit memory context */