1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-12 05:01:15 +03:00

Clean up non-reentrant interface for hash_seq/HashTableWalk, so that

starting a new hashtable search no longer clobbers any other search
active anywhere in the system.  Fix RelationCacheInvalidate() so that
it will not crash or go into an infinite loop if invoked recursively,
as for example by a second SI Reset message arriving while we are still
processing a prior one.
This commit is contained in:
Tom Lane
2001-01-02 04:33:24 +00:00
parent 25d88e4c53
commit 1b8a219eef
8 changed files with 149 additions and 158 deletions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/hash/dynahash.c,v 1.32 2000/06/28 03:32:34 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/hash/dynahash.c,v 1.33 2001/01/02 04:33:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -681,50 +681,54 @@ hash_search(HTAB *hashp,
}
/*
* hash_seq -- sequentially search through hash table and return
* all the elements one by one, return NULL on error and
* return TRUE in the end.
* hash_seq_init/_search
* Sequentially search through hash table and return
* all the elements one by one, return NULL on error and
* return (long *) TRUE in the end.
*
* NOTE: caller may delete the returned element before continuing the scan.
* However, deleting any other element while the scan is in progress is
* UNDEFINED (it might be the one that curIndex is pointing at!). Also,
* if elements are added to the table while the scan is in progress, it is
* unspecified whether they will be visited by the scan or not.
*/
long *
hash_seq(HTAB *hashp)
void
hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
{
static long curBucket = 0;
static BUCKET_INDEX curIndex;
ELEMENT *curElem;
long segment_num;
long segment_ndx;
SEGMENT segp;
HHDR *hctl;
status->hashp = hashp;
status->curBucket = 0;
status->curIndex = INVALID_INDEX;
}
if (hashp == NULL)
long *
hash_seq_search(HASH_SEQ_STATUS *status)
{
HTAB *hashp = status->hashp;
HHDR *hctl = hashp->hctl;
while (status->curBucket <= hctl->max_bucket)
{
long segment_num;
long segment_ndx;
SEGMENT segp;
/*
* reset static state
*/
curBucket = 0;
curIndex = INVALID_INDEX;
return (long *) NULL;
}
hctl = hashp->hctl;
while (curBucket <= hctl->max_bucket)
{
if (curIndex != INVALID_INDEX)
if (status->curIndex != INVALID_INDEX)
{
curElem = GET_BUCKET(hashp, curIndex);
curIndex = curElem->next;
if (curIndex == INVALID_INDEX) /* end of this bucket */
++curBucket;
/* Continuing scan of curBucket... */
ELEMENT *curElem;
curElem = GET_BUCKET(hashp, status->curIndex);
status->curIndex = curElem->next;
if (status->curIndex == INVALID_INDEX) /* end of this bucket */
++status->curBucket;
return &(curElem->key);
}
/*
* initialize the search within this bucket.
*/
segment_num = curBucket >> hctl->sshift;
segment_ndx = MOD(curBucket, hctl->ssize);
segment_num = status->curBucket >> hctl->sshift;
segment_ndx = MOD(status->curBucket, hctl->ssize);
/*
* first find the right segment in the table directory.
@@ -742,10 +746,10 @@ hash_seq(HTAB *hashp)
* directory of valid stuff. if there are elements in the bucket
* chains that point to the freelist we're in big trouble.
*/
curIndex = segp[segment_ndx];
status->curIndex = segp[segment_ndx];
if (curIndex == INVALID_INDEX) /* empty bucket */
++curBucket;
if (status->curIndex == INVALID_INDEX) /* empty bucket */
++status->curBucket;
}
return (long *) TRUE; /* out of buckets */