mirror of
https://github.com/postgres/postgres.git
synced 2025-04-21 12:05:57 +03:00
Refactor initial hash lookup in dynahash.c
The same pattern is used three times in dynahash.c to retrieve a bucket number and a hash bucket from a hash value. This has popped up while discussing improvements for the type cache, where this piece of refactoring would become useful. Note that hash_search_with_hash_value() does not need the bucket number, just the hash bucket. Author: Teodor Sigaev Reviewed-by: Aleksander Alekseev, Michael Paquier Discussion: https://postgr.es/m/5812a6e5-68ae-4d84-9d85-b443176966a1@sigaev.ru
This commit is contained in:
parent
4169850f0b
commit
cc5ef90edd
@ -273,6 +273,8 @@ static void hdefault(HTAB *hashp);
|
||||
static int choose_nelem_alloc(Size entrysize);
|
||||
static bool init_htab(HTAB *hashp, long nelem);
|
||||
static void hash_corrupted(HTAB *hashp);
|
||||
static uint32 hash_initial_lookup(HTAB *hashp, uint32 hashvalue,
|
||||
HASHBUCKET **bucketptr);
|
||||
static long next_pow2_long(long num);
|
||||
static int next_pow2_int(long num);
|
||||
static void register_seq_scan(HTAB *hashp);
|
||||
@ -972,10 +974,6 @@ hash_search_with_hash_value(HTAB *hashp,
|
||||
HASHHDR *hctl = hashp->hctl;
|
||||
int freelist_idx = FREELIST_IDX(hctl, hashvalue);
|
||||
Size keysize;
|
||||
uint32 bucket;
|
||||
long segment_num;
|
||||
long segment_ndx;
|
||||
HASHSEGMENT segp;
|
||||
HASHBUCKET currBucket;
|
||||
HASHBUCKET *prevBucketPtr;
|
||||
HashCompareFunc match;
|
||||
@ -1008,17 +1006,7 @@ hash_search_with_hash_value(HTAB *hashp,
|
||||
/*
|
||||
* Do the initial lookup
|
||||
*/
|
||||
bucket = calc_bucket(hctl, hashvalue);
|
||||
|
||||
segment_num = bucket >> hashp->sshift;
|
||||
segment_ndx = MOD(bucket, hashp->ssize);
|
||||
|
||||
segp = hashp->dir[segment_num];
|
||||
|
||||
if (segp == NULL)
|
||||
hash_corrupted(hashp);
|
||||
|
||||
prevBucketPtr = &segp[segment_ndx];
|
||||
(void) hash_initial_lookup(hashp, hashvalue, &prevBucketPtr);
|
||||
currBucket = *prevBucketPtr;
|
||||
|
||||
/*
|
||||
@ -1159,14 +1147,10 @@ hash_update_hash_key(HTAB *hashp,
|
||||
const void *newKeyPtr)
|
||||
{
|
||||
HASHELEMENT *existingElement = ELEMENT_FROM_KEY(existingEntry);
|
||||
HASHHDR *hctl = hashp->hctl;
|
||||
uint32 newhashvalue;
|
||||
Size keysize;
|
||||
uint32 bucket;
|
||||
uint32 newbucket;
|
||||
long segment_num;
|
||||
long segment_ndx;
|
||||
HASHSEGMENT segp;
|
||||
HASHBUCKET currBucket;
|
||||
HASHBUCKET *prevBucketPtr;
|
||||
HASHBUCKET *oldPrevPtr;
|
||||
@ -1187,17 +1171,8 @@ hash_update_hash_key(HTAB *hashp,
|
||||
* this to be able to unlink it from its hash chain, but as a side benefit
|
||||
* we can verify the validity of the passed existingEntry pointer.
|
||||
*/
|
||||
bucket = calc_bucket(hctl, existingElement->hashvalue);
|
||||
|
||||
segment_num = bucket >> hashp->sshift;
|
||||
segment_ndx = MOD(bucket, hashp->ssize);
|
||||
|
||||
segp = hashp->dir[segment_num];
|
||||
|
||||
if (segp == NULL)
|
||||
hash_corrupted(hashp);
|
||||
|
||||
prevBucketPtr = &segp[segment_ndx];
|
||||
bucket = hash_initial_lookup(hashp, existingElement->hashvalue,
|
||||
&prevBucketPtr);
|
||||
currBucket = *prevBucketPtr;
|
||||
|
||||
while (currBucket != NULL)
|
||||
@ -1219,18 +1194,7 @@ hash_update_hash_key(HTAB *hashp,
|
||||
* chain we want to put the entry into.
|
||||
*/
|
||||
newhashvalue = hashp->hash(newKeyPtr, hashp->keysize);
|
||||
|
||||
newbucket = calc_bucket(hctl, newhashvalue);
|
||||
|
||||
segment_num = newbucket >> hashp->sshift;
|
||||
segment_ndx = MOD(newbucket, hashp->ssize);
|
||||
|
||||
segp = hashp->dir[segment_num];
|
||||
|
||||
if (segp == NULL)
|
||||
hash_corrupted(hashp);
|
||||
|
||||
prevBucketPtr = &segp[segment_ndx];
|
||||
newbucket = hash_initial_lookup(hashp, newhashvalue, &prevBucketPtr);
|
||||
currBucket = *prevBucketPtr;
|
||||
|
||||
/*
|
||||
@ -1741,6 +1705,33 @@ element_alloc(HTAB *hashp, int nelem, int freelist_idx)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do initial lookup of a bucket for the given hash value, retrieving its
|
||||
* bucket number and its hash bucket.
|
||||
*/
|
||||
static inline uint32
|
||||
hash_initial_lookup(HTAB *hashp, uint32 hashvalue, HASHBUCKET **bucketptr)
|
||||
{
|
||||
HASHHDR *hctl = hashp->hctl;
|
||||
HASHSEGMENT segp;
|
||||
long segment_num;
|
||||
long segment_ndx;
|
||||
uint32 bucket;
|
||||
|
||||
bucket = calc_bucket(hctl, hashvalue);
|
||||
|
||||
segment_num = bucket >> hashp->sshift;
|
||||
segment_ndx = MOD(bucket, hashp->ssize);
|
||||
|
||||
segp = hashp->dir[segment_num];
|
||||
|
||||
if (segp == NULL)
|
||||
hash_corrupted(hashp);
|
||||
|
||||
*bucketptr = &segp[segment_ndx];
|
||||
return bucket;
|
||||
}
|
||||
|
||||
/* complain when we have detected a corrupted hashtable */
|
||||
static void
|
||||
hash_corrupted(HTAB *hashp)
|
||||
|
Loading…
x
Reference in New Issue
Block a user