From f313d8b02a4fa220beb624c26c06e43186c5ae51 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 29 May 2005 04:23:07 +0000 Subject: [PATCH] Modify hash_search() API to prevent future occurrences of the error spotted by Qingqing Zhou. The HASH_ENTER action now automatically fails with elog(ERROR) on out-of-memory --- which incidentally lets us eliminate duplicate error checks in quite a bunch of places. If you really need the old return-NULL-on-out-of-memory behavior, you can ask for HASH_ENTER_NULL. But there is now an Assert in that path checking that you aren't hoping to get that behavior in a palloc-based hash table. Along the way, remove the old HASH_FIND_SAVE/HASH_REMOVE_SAVED actions, which were not being used anywhere anymore, and were surely too ugly and unsafe to want to see revived again. --- contrib/dblink/dblink.c | 5 - contrib/tablefunc/tablefunc.c | 4 - src/backend/access/transam/xlogutils.c | 3 - src/backend/commands/prepare.c | 6 +- src/backend/executor/execGrouping.c | 8 +- src/backend/nodes/tidbitmap.c | 12 --- src/backend/postmaster/pgstat.c | 22 ---- src/backend/storage/buffer/buf_table.c | 5 - src/backend/storage/buffer/localbuf.c | 4 - src/backend/storage/freespace/freespace.c | 4 - src/backend/storage/ipc/shmem.c | 7 +- src/backend/storage/lmgr/lock.c | 8 +- src/backend/storage/smgr/md.c | 10 +- src/backend/storage/smgr/smgr.c | 4 - src/backend/utils/adt/ri_triggers.c | 4 - src/backend/utils/cache/relcache.c | 8 -- src/backend/utils/cache/typcache.c | 8 -- src/backend/utils/fmgr/fmgr.c | 4 - src/backend/utils/hash/dynahash.c | 116 ++++++++++------------ src/backend/utils/mmgr/portalmem.c | 4 - src/include/utils/hsearch.h | 3 +- src/pl/plpgsql/src/pl_comp.c | 4 - src/timezone/pgtz.c | 8 +- 23 files changed, 69 insertions(+), 192 deletions(-) diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c index f23151ac14..b216dbeea9 100644 --- a/contrib/dblink/dblink.c +++ b/contrib/dblink/dblink.c @@ -2061,11 +2061,6 @@ createNewConnection(const char *name, remoteConn * con) hentry = (remoteConnHashEnt *) hash_search(remoteConnHash, key, HASH_ENTER, &found); - if (!hentry) - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); - if (found) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), diff --git a/contrib/tablefunc/tablefunc.c b/contrib/tablefunc/tablefunc.c index c364fc6595..0aa52b5281 100644 --- a/contrib/tablefunc/tablefunc.c +++ b/contrib/tablefunc/tablefunc.c @@ -144,10 +144,6 @@ do { \ snprintf(key, MAX_CATNAME_LEN - 1, "%s", CATDESC->catname); \ hentry = (crosstab_HashEnt*) hash_search(crosstab_HashTable, \ key, HASH_ENTER, &found); \ - if (hentry == NULL) \ - ereport(ERROR, \ - (errcode(ERRCODE_OUT_OF_MEMORY), \ - errmsg("out of memory"))); \ if (found) \ ereport(ERROR, \ (errcode(ERRCODE_DUPLICATE_OBJECT), \ diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c index 3a92cdc9e6..d3bd922895 100644 --- a/src/backend/access/transam/xlogutils.c +++ b/src/backend/access/transam/xlogutils.c @@ -223,9 +223,6 @@ XLogOpenRelation(bool redo, RmgrId rmid, RelFileNode rnode) hentry = (XLogRelCacheEntry *) hash_search(_xlrelcache, (void *) &rnode, HASH_ENTER, &found); - if (hentry == NULL) - elog(PANIC, "XLogOpenRelation: out of memory for cache"); - if (found) elog(PANIC, "XLogOpenRelation: file found on insert into cache"); diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c index 4535de4df2..9801417570 100644 --- a/src/backend/commands/prepare.c +++ b/src/backend/commands/prepare.c @@ -346,9 +346,9 @@ StorePreparedStatement(const char *stmt_name, HASH_ENTER, &found); - /* Shouldn't get a failure, nor a duplicate entry */ - if (!entry || found) - elog(ERROR, "could not store prepared statement \"%s\"", + /* Shouldn't get a duplicate entry */ + if (found) + elog(ERROR, "duplicate prepared statement \"%s\"", stmt_name); /* Fill in the hash table entry with copied data */ diff --git a/src/backend/executor/execGrouping.c b/src/backend/executor/execGrouping.c index fee29e8553..fe0ca36edd 100644 --- a/src/backend/executor/execGrouping.c +++ b/src/backend/executor/execGrouping.c @@ -379,13 +379,9 @@ LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot, } else { - /* created new entry ... we hope */ - if (entry == NULL) - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); - /* + * created new entry + * * Zero any caller-requested space in the entry. (This zaps * the "key data" dynahash.c copied into the new entry, but we * don't care since we're about to overwrite it anyway.) diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c index fd5b45a818..97ddfa15e8 100644 --- a/src/backend/nodes/tidbitmap.c +++ b/src/backend/nodes/tidbitmap.c @@ -220,10 +220,6 @@ tbm_create_pagetable(TIDBitmap *tbm) page = (PagetableEntry *) hash_search(tbm->pagetable, (void *) &tbm->entry1.blockno, HASH_ENTER, &found); - if (page == NULL) - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); Assert(!found); memcpy(page, &tbm->entry1, sizeof(PagetableEntry)); } @@ -726,10 +722,6 @@ tbm_get_pageentry(TIDBitmap *tbm, BlockNumber pageno) page = (PagetableEntry *) hash_search(tbm->pagetable, (void *) &pageno, HASH_ENTER, &found); - if (page == NULL) - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); } /* Initialize it if not present before */ @@ -820,10 +812,6 @@ tbm_mark_page_lossy(TIDBitmap *tbm, BlockNumber pageno) page = (PagetableEntry *) hash_search(tbm->pagetable, (void *) &chunk_pageno, HASH_ENTER, &found); - if (page == NULL) - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); /* Initialize it if not present before */ if (!found) diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index bd9965c671..b2adad433a 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2061,10 +2061,6 @@ pgstat_get_db_entry(int databaseid) result = (PgStat_StatDBEntry *) hash_search(pgStatDBHash, &databaseid, HASH_ENTER, &found); - if (result == NULL) - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory in statistics collector --- abort"))); /* If not found, initialize the new one. */ if (!found) @@ -2126,10 +2122,6 @@ pgstat_sub_backend(int procpid) (void *) &procpid, HASH_ENTER, &found); - if (deadbe == NULL) - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory in statistics collector --- abort"))); if (!found) { @@ -2435,12 +2427,6 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb, (void *) &dbbuf.databaseid, HASH_ENTER, &found); - if (dbentry == NULL) - { - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); - } if (found) { ereport(pgStatRunningInCollector ? LOG : WARNING, @@ -2503,10 +2489,6 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb, tabentry = (PgStat_StatTabEntry *) hash_search(tabhash, (void *) &tabbuf.tableid, HASH_ENTER, &found); - if (tabentry == NULL) - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); if (found) { @@ -2730,10 +2712,6 @@ pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len) tabentry = (PgStat_StatTabEntry *) hash_search(dbentry->tables, (void *) &(tabmsg[i].t_id), HASH_ENTER, &found); - if (tabentry == NULL) - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory in statistics collector --- abort"))); if (!found) { diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index e74fba273f..1a0303b567 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -110,11 +110,6 @@ BufTableInsert(BufferTag *tagPtr, int buf_id) result = (BufferLookupEnt *) hash_search(SharedBufHash, (void *) tagPtr, HASH_ENTER, &found); - if (!result) - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of shared memory"))); - if (found) /* found something already in the table */ return result->id; diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c index ded94fe438..1ad1848acd 100644 --- a/src/backend/storage/buffer/localbuf.c +++ b/src/backend/storage/buffer/localbuf.c @@ -192,10 +192,6 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr) hresult = (LocalBufferLookupEnt *) hash_search(LocalBufHash, (void *) &newTag, HASH_ENTER, &found); - if (!hresult) - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); if (found) /* shouldn't happen */ elog(ERROR, "local buffer hash table corrupted"); hresult->id = b; diff --git a/src/backend/storage/freespace/freespace.c b/src/backend/storage/freespace/freespace.c index 2e16609177..6b121b2750 100644 --- a/src/backend/storage/freespace/freespace.c +++ b/src/backend/storage/freespace/freespace.c @@ -1036,10 +1036,6 @@ create_fsm_rel(RelFileNode *rel) (void *) rel, HASH_ENTER, &found); - if (!fsmrel) - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of shared memory"))); if (!found) { diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c index 8e8bfae7aa..7c8c954b6e 100644 --- a/src/backend/storage/ipc/shmem.c +++ b/src/backend/storage/ipc/shmem.c @@ -235,10 +235,6 @@ InitShmemIndex(void) result = (ShmemIndexEnt *) hash_search(ShmemIndex, (void *) &item, HASH_ENTER, &found); - if (!result) - ereport(FATAL, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of shared memory"))); Assert(!found); @@ -367,7 +363,7 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr) /* look it up in the shmem index */ result = (ShmemIndexEnt *) - hash_search(ShmemIndex, (void *) &item, HASH_ENTER, foundPtr); + hash_search(ShmemIndex, (void *) &item, HASH_ENTER_NULL, foundPtr); if (!result) { @@ -375,7 +371,6 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr) ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); - return NULL; } if (*foundPtr) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 7d9e760d59..05629c0a57 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -470,10 +470,6 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag, locallock = (LOCALLOCK *) hash_search(LockMethodLocalHash[lockmethodid], (void *) &localtag, HASH_ENTER, &found); - if (!locallock) - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); /* * if it's a new locallock object, initialize it @@ -531,7 +527,7 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag, */ lock = (LOCK *) hash_search(LockMethodLockHash[lockmethodid], (void *) locktag, - HASH_ENTER, &found); + HASH_ENTER_NULL, &found); if (!lock) { LWLockRelease(masterLock); @@ -578,7 +574,7 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag, */ proclock = (PROCLOCK *) hash_search(LockMethodProcLockHash[lockmethodid], (void *) &proclocktag, - HASH_ENTER, &found); + HASH_ENTER_NULL, &found); if (!proclock) { /* Ooops, not enough shmem for the proclock */ diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c index 5f31970da9..7d59336577 100644 --- a/src/backend/storage/smgr/md.c +++ b/src/backend/storage/smgr/md.c @@ -805,9 +805,8 @@ register_dirty_segment(SMgrRelation reln, MdfdVec *seg) entry.rnode = reln->smgr_rnode; entry.segno = seg->mdfd_segno; - if (hash_search(pendingOpsTable, &entry, HASH_ENTER, NULL) != NULL) - return true; - /* out of memory: fall through to do it locally */ + (void) hash_search(pendingOpsTable, &entry, HASH_ENTER, NULL); + return true; } else { @@ -838,10 +837,7 @@ RememberFsyncRequest(RelFileNode rnode, BlockNumber segno) entry.rnode = rnode; entry.segno = segno; - if (hash_search(pendingOpsTable, &entry, HASH_ENTER, NULL) == NULL) - ereport(FATAL, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); + (void) hash_search(pendingOpsTable, &entry, HASH_ENTER, NULL); } /* diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c index c04e198591..f5851fae26 100644 --- a/src/backend/storage/smgr/smgr.c +++ b/src/backend/storage/smgr/smgr.c @@ -207,10 +207,6 @@ smgropen(RelFileNode rnode) reln = (SMgrRelation) hash_search(SMgrRelationHash, (void *) &rnode, HASH_ENTER, &found); - if (reln == NULL) - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); /* Initialize it if not present before */ if (!found) diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c index c2278a2f41..ffa614cff9 100644 --- a/src/backend/utils/adt/ri_triggers.c +++ b/src/backend/utils/adt/ri_triggers.c @@ -3466,10 +3466,6 @@ ri_HashPreparedPlan(RI_QueryKey *key, void *plan) entry = (RI_QueryHashEntry *) hash_search(ri_query_cache, (void *) key, HASH_ENTER, &found); - if (entry == NULL) - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); entry->plan = plan; } diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 033b542763..61b55b05db 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -137,10 +137,6 @@ do { \ (void *) &(RELATION->rd_id), \ HASH_ENTER, \ &found); \ - if (idhentry == NULL) \ - ereport(ERROR, \ - (errcode(ERRCODE_OUT_OF_MEMORY), \ - errmsg("out of memory"))); \ /* used to give notice if found -- now just keep quiet */ \ idhentry->reldesc = RELATION; \ } while(0) @@ -1044,10 +1040,6 @@ LookupOpclassInfo(Oid operatorClassOid, opcentry = (OpClassCacheEnt *) hash_search(OpClassCache, (void *) &operatorClassOid, HASH_ENTER, &found); - if (opcentry == NULL) - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); if (found && opcentry->valid) { diff --git a/src/backend/utils/cache/typcache.c b/src/backend/utils/cache/typcache.c index 4ed69ba625..a0a87e17bc 100644 --- a/src/backend/utils/cache/typcache.c +++ b/src/backend/utils/cache/typcache.c @@ -158,10 +158,6 @@ lookup_type_cache(Oid type_id, int flags) typentry = (TypeCacheEntry *) hash_search(TypeCacheHash, (void *) &type_id, HASH_ENTER, &found); - if (typentry == NULL) - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); Assert(!found); /* it wasn't there a moment ago */ MemSet(typentry, 0, sizeof(TypeCacheEntry)); @@ -480,10 +476,6 @@ assign_record_type_typmod(TupleDesc tupDesc) recentry = (RecordCacheEntry *) hash_search(RecordCacheHash, (void *) hashkey, HASH_ENTER, &found); - if (recentry == NULL) - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); if (!found) { /* New entry ... hash_search initialized only the hash key */ diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c index 0d022f86cf..758e03c588 100644 --- a/src/backend/utils/fmgr/fmgr.c +++ b/src/backend/utils/fmgr/fmgr.c @@ -521,10 +521,6 @@ record_C_func(HeapTuple procedureTuple, &fn_oid, HASH_ENTER, &found); - if (entry == NULL) - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); /* OID is already filled in */ entry->fn_xmin = HeapTupleHeaderGetXmin(procedureTuple->t_data); entry->fn_cmin = HeapTupleHeaderGetCmin(procedureTuple->t_data); diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 0fc9abab65..2f1b177704 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -498,22 +498,22 @@ calc_bucket(HASHHDR *hctl, uint32 hash_val) * action is one of: * HASH_FIND: look up key in table * HASH_ENTER: look up key in table, creating entry if not present + * HASH_ENTER_NULL: same, but return NULL if out of memory * HASH_REMOVE: look up key in table, remove entry if present - * HASH_FIND_SAVE: look up key in table, also save in static var - * HASH_REMOVE_SAVED: remove entry saved by HASH_FIND_SAVE * * Return value is a pointer to the element found/entered/removed if any, - * or NULL if no match was found. (NB: in the case of the REMOVE actions, + * or NULL if no match was found. (NB: in the case of the REMOVE action, * the result is a dangling pointer that shouldn't be dereferenced!) - * A NULL result for HASH_ENTER implies we ran out of memory. + * + * HASH_ENTER will normally ereport a generic "out of memory" error if + * it is unable to create a new entry. The HASH_ENTER_NULL operation is + * the same except it will return NULL if out of memory. Note that + * HASH_ENTER_NULL cannot be used with the default palloc-based allocator, + * since palloc internally ereports on out-of-memory. * * If foundPtr isn't NULL, then *foundPtr is set TRUE if we found an * existing entry in the table, FALSE otherwise. This is needed in the * HASH_ENTER case, but is redundant with the return value otherwise. - * - * The HASH_FIND_SAVE/HASH_REMOVE_SAVED interface is a hack to save one - * table lookup in a find/process/remove scenario. Note that no other - * addition or removal in the table can safely happen in between. *---------- */ void * @@ -523,19 +523,15 @@ hash_search(HTAB *hashp, bool *foundPtr) { HASHHDR *hctl = hashp->hctl; - uint32 hashvalue = 0; + Size keysize = hctl->keysize; + uint32 hashvalue; uint32 bucket; long segment_num; long segment_ndx; HASHSEGMENT segp; HASHBUCKET currBucket; HASHBUCKET *prevBucketPtr; - - static struct State - { - HASHBUCKET currBucket; - HASHBUCKET *prevBucketPtr; - } saveState; + HashCompareFunc match; #if HASH_STATISTICS hash_accesses++; @@ -543,54 +539,38 @@ hash_search(HTAB *hashp, #endif /* - * Do the initial lookup (or recall result of prior lookup) + * Do the initial lookup */ - if (action == HASH_REMOVE_SAVED) - { - currBucket = saveState.currBucket; - prevBucketPtr = saveState.prevBucketPtr; + hashvalue = hashp->hash(keyPtr, keysize); + bucket = calc_bucket(hctl, hashvalue); - /* - * Try to catch subsequent errors - */ - Assert(currBucket); - saveState.currBucket = NULL; - } - else - { - HashCompareFunc match; - Size keysize = hctl->keysize; + segment_num = bucket >> hctl->sshift; + segment_ndx = MOD(bucket, hctl->ssize); - hashvalue = hashp->hash(keyPtr, keysize); - bucket = calc_bucket(hctl, hashvalue); + segp = hashp->dir[segment_num]; - segment_num = bucket >> hctl->sshift; - segment_ndx = MOD(bucket, hctl->ssize); + if (segp == NULL) + hash_corrupted(hashp); - segp = hashp->dir[segment_num]; + prevBucketPtr = &segp[segment_ndx]; + currBucket = *prevBucketPtr; - if (segp == NULL) - hash_corrupted(hashp); + /* + * Follow collision chain looking for matching key + */ + match = hashp->match; /* save one fetch in inner loop */ - prevBucketPtr = &segp[segment_ndx]; + while (currBucket != NULL) + { + if (currBucket->hashvalue == hashvalue && + match(ELEMENTKEY(currBucket), keyPtr, keysize) == 0) + break; + prevBucketPtr = &(currBucket->link); currBucket = *prevBucketPtr; - - /* - * Follow collision chain looking for matching key - */ - match = hashp->match; /* save one fetch in inner loop */ - while (currBucket != NULL) - { - if (currBucket->hashvalue == hashvalue && - match(ELEMENTKEY(currBucket), keyPtr, keysize) == 0) - break; - prevBucketPtr = &(currBucket->link); - currBucket = *prevBucketPtr; #if HASH_STATISTICS - hash_collisions++; - hctl->collisions++; + hash_collisions++; + hctl->collisions++; #endif - } } if (foundPtr) @@ -606,17 +586,7 @@ hash_search(HTAB *hashp, return (void *) ELEMENTKEY(currBucket); return NULL; - case HASH_FIND_SAVE: - if (currBucket != NULL) - { - saveState.currBucket = currBucket; - saveState.prevBucketPtr = prevBucketPtr; - return (void *) ELEMENTKEY(currBucket); - } - return NULL; - case HASH_REMOVE: - case HASH_REMOVE_SAVED: if (currBucket != NULL) { Assert(hctl->nentries > 0); @@ -638,6 +608,11 @@ hash_search(HTAB *hashp, } return NULL; + case HASH_ENTER_NULL: + /* ENTER_NULL does not work with palloc-based allocator */ + Assert(hashp->alloc != DynaHashAlloc); + /* FALL THRU */ + case HASH_ENTER: /* Return existing element if found, else create one */ if (currBucket != NULL) @@ -649,7 +624,20 @@ hash_search(HTAB *hashp, { /* no free elements. allocate another chunk of buckets */ if (!element_alloc(hashp, HASHELEMENT_ALLOC_INCR)) - return NULL; /* out of memory */ + { + /* out of memory */ + if (action == HASH_ENTER_NULL) + return NULL; + /* report a generic message */ + if (hashp->isshared) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of shared memory"))); + else + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + } currBucket = hctl->freeList; Assert(currBucket != NULL); } diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c index 3d2d2fadd1..7e1ad44028 100644 --- a/src/backend/utils/mmgr/portalmem.c +++ b/src/backend/utils/mmgr/portalmem.c @@ -72,10 +72,6 @@ do { \ StrNCpy(key, NAME, MAX_PORTALNAME_LEN); \ hentry = (PortalHashEnt*)hash_search(PortalHashTable, \ key, HASH_ENTER, &found); \ - if (hentry == NULL) \ - ereport(ERROR, \ - (errcode(ERRCODE_OUT_OF_MEMORY), \ - errmsg("out of memory"))); \ if (found) \ elog(ERROR, "duplicate portal name"); \ hentry->portal = PORTAL; \ diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index c6e87adfe4..531e8e2515 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -153,8 +153,7 @@ typedef enum HASH_FIND, HASH_ENTER, HASH_REMOVE, - HASH_FIND_SAVE, - HASH_REMOVE_SAVED + HASH_ENTER_NULL } HASHACTION; /* hash_seq status (should be considered an opaque type by callers) */ diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c index 2ec43ba40f..3c96d8ec96 100644 --- a/src/pl/plpgsql/src/pl_comp.c +++ b/src/pl/plpgsql/src/pl_comp.c @@ -2157,10 +2157,6 @@ plpgsql_HashTableInsert(PLpgSQL_function *function, (void *) func_key, HASH_ENTER, &found); - if (hentry == NULL) - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); if (found) elog(WARNING, "trying to insert a function that already exists"); diff --git a/src/timezone/pgtz.c b/src/timezone/pgtz.c index 8d37b0bc20..23dd64533a 100644 --- a/src/timezone/pgtz.c +++ b/src/timezone/pgtz.c @@ -971,6 +971,7 @@ identify_system_timezone(void) * load and parse the TZ definition file every time it is selected. */ static HTAB *timezone_cache = NULL; + static bool init_timezone_hashtable(void) { @@ -1013,14 +1014,18 @@ pg_tzset(const char *name) HASH_FIND, NULL); if (tzp) + { /* Timezone found in cache, nothing more to do */ return tzp; + } if (tzload(name, &tz.state) != 0) { if (name[0] == ':' || tzparse(name, &tz.state, FALSE) != 0) + { /* Unknown timezone. Fail our call instead of loading GMT! */ return NULL; + } } strcpy(tz.TZname, name); @@ -1031,9 +1036,6 @@ pg_tzset(const char *name) HASH_ENTER, NULL); - if (!tzp) - return NULL; - strcpy(tzp->TZname, tz.TZname); memcpy(&tzp->state, &tz.state, sizeof(tz.state)); -- 2.39.5