mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-31 00:03:57 -04: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