Skip to content

Commit 6ae4e8e

Browse files
committed
Allow simplehash to use already-calculated hash values.
Add _lookup_hash and _insert_hash functions for callers that have already calculated the hash value of the key. The immediate use case is for hash algorithms that write to disk in partitions. The hash value can be calculated once, used to perform a lookup, used to select the partition, then written to the partition along with the tuple. When the tuple is read back, the hash value does not need to be recalculated. Author: Jeff Davis Reviewed-by: Andres Freund Discussion: https://postgr.es/m/48abe675e1330f0c264ab2fe0d4ff23eb244f9ef.camel%40j-davis.com
1 parent 7266d09 commit 6ae4e8e

File tree

1 file changed

+65
-9
lines changed

1 file changed

+65
-9
lines changed

src/include/lib/simplehash.h

+65-9
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,10 @@
7474
#define SH_DESTROY SH_MAKE_NAME(destroy)
7575
#define SH_RESET SH_MAKE_NAME(reset)
7676
#define SH_INSERT SH_MAKE_NAME(insert)
77+
#define SH_INSERT_HASH SH_MAKE_NAME(insert_hash)
7778
#define SH_DELETE SH_MAKE_NAME(delete)
7879
#define SH_LOOKUP SH_MAKE_NAME(lookup)
80+
#define SH_LOOKUP_HASH SH_MAKE_NAME(lookup_hash)
7981
#define SH_GROW SH_MAKE_NAME(grow)
8082
#define SH_START_ITERATE SH_MAKE_NAME(start_iterate)
8183
#define SH_START_ITERATE_AT SH_MAKE_NAME(start_iterate_at)
@@ -91,6 +93,8 @@
9193
#define SH_DISTANCE_FROM_OPTIMAL SH_MAKE_NAME(distance)
9294
#define SH_INITIAL_BUCKET SH_MAKE_NAME(initial_bucket)
9395
#define SH_ENTRY_HASH SH_MAKE_NAME(entry_hash)
96+
#define SH_INSERT_HASH_INTERNAL SH_MAKE_NAME(insert_hash_internal)
97+
#define SH_LOOKUP_HASH_INTERNAL SH_MAKE_NAME(lookup_hash_internal)
9498

9599
/* generate forward declarations necessary to use the hash table */
96100
#ifdef SH_DECLARE
@@ -144,7 +148,11 @@ SH_SCOPE void SH_DESTROY(SH_TYPE * tb);
144148
SH_SCOPE void SH_RESET(SH_TYPE * tb);
145149
SH_SCOPE void SH_GROW(SH_TYPE * tb, uint32 newsize);
146150
SH_SCOPE SH_ELEMENT_TYPE *SH_INSERT(SH_TYPE * tb, SH_KEY_TYPE key, bool *found);
151+
SH_SCOPE SH_ELEMENT_TYPE *SH_INSERT_HASH(SH_TYPE * tb, SH_KEY_TYPE key,
152+
uint32 hash, bool *found);
147153
SH_SCOPE SH_ELEMENT_TYPE *SH_LOOKUP(SH_TYPE * tb, SH_KEY_TYPE key);
154+
SH_SCOPE SH_ELEMENT_TYPE *SH_LOOKUP_HASH(SH_TYPE * tb, SH_KEY_TYPE key,
155+
uint32 hash);
148156
SH_SCOPE bool SH_DELETE(SH_TYPE * tb, SH_KEY_TYPE key);
149157
SH_SCOPE void SH_START_ITERATE(SH_TYPE * tb, SH_ITERATOR * iter);
150158
SH_SCOPE void SH_START_ITERATE_AT(SH_TYPE * tb, SH_ITERATOR * iter, uint32 at);
@@ -492,14 +500,12 @@ SH_GROW(SH_TYPE * tb, uint32 newsize)
492500
}
493501

494502
/*
495-
* Insert the key key into the hash-table, set *found to true if the key
496-
* already exists, false otherwise. Returns the hash-table entry in either
497-
* case.
503+
* This is a separate static inline function, so it can be reliably be inlined
504+
* into its wrapper functions even if SH_SCOPE is extern.
498505
*/
499-
SH_SCOPE SH_ELEMENT_TYPE *
500-
SH_INSERT(SH_TYPE * tb, SH_KEY_TYPE key, bool *found)
506+
static inline SH_ELEMENT_TYPE *
507+
SH_INSERT_HASH_INTERNAL(SH_TYPE * tb, SH_KEY_TYPE key, uint32 hash, bool *found)
501508
{
502-
uint32 hash = SH_HASH_KEY(tb, key);
503509
uint32 startelem;
504510
uint32 curelem;
505511
SH_ELEMENT_TYPE *data;
@@ -664,12 +670,36 @@ SH_INSERT(SH_TYPE * tb, SH_KEY_TYPE key, bool *found)
664670
}
665671

666672
/*
667-
* Lookup up entry in hash table. Returns NULL if key not present.
673+
* Insert the key key into the hash-table, set *found to true if the key
674+
* already exists, false otherwise. Returns the hash-table entry in either
675+
* case.
668676
*/
669677
SH_SCOPE SH_ELEMENT_TYPE *
670-
SH_LOOKUP(SH_TYPE * tb, SH_KEY_TYPE key)
678+
SH_INSERT(SH_TYPE * tb, SH_KEY_TYPE key, bool *found)
679+
{
680+
uint32 hash = SH_HASH_KEY(tb, key);
681+
682+
return SH_INSERT_HASH_INTERNAL(tb, key, hash, found);
683+
}
684+
685+
/*
686+
* Insert the key key into the hash-table using an already-calculated
687+
* hash. Set *found to true if the key already exists, false
688+
* otherwise. Returns the hash-table entry in either case.
689+
*/
690+
SH_SCOPE SH_ELEMENT_TYPE *
691+
SH_INSERT_HASH(SH_TYPE * tb, SH_KEY_TYPE key, uint32 hash, bool *found)
692+
{
693+
return SH_INSERT_HASH_INTERNAL(tb, key, hash, found);
694+
}
695+
696+
/*
697+
* This is a separate static inline function, so it can be reliably be inlined
698+
* into its wrapper functions even if SH_SCOPE is extern.
699+
*/
700+
static inline SH_ELEMENT_TYPE *
701+
SH_LOOKUP_HASH_INTERNAL(SH_TYPE * tb, SH_KEY_TYPE key, uint32 hash)
671702
{
672-
uint32 hash = SH_HASH_KEY(tb, key);
673703
const uint32 startelem = SH_INITIAL_BUCKET(tb, hash);
674704
uint32 curelem = startelem;
675705

@@ -698,6 +728,28 @@ SH_LOOKUP(SH_TYPE * tb, SH_KEY_TYPE key)
698728
}
699729
}
700730

731+
/*
732+
* Lookup up entry in hash table. Returns NULL if key not present.
733+
*/
734+
SH_SCOPE SH_ELEMENT_TYPE *
735+
SH_LOOKUP(SH_TYPE * tb, SH_KEY_TYPE key)
736+
{
737+
uint32 hash = SH_HASH_KEY(tb, key);
738+
739+
return SH_LOOKUP_HASH_INTERNAL(tb, key, hash);
740+
}
741+
742+
/*
743+
* Lookup up entry in hash table using an already-calculated hash.
744+
*
745+
* Returns NULL if key not present.
746+
*/
747+
SH_SCOPE SH_ELEMENT_TYPE *
748+
SH_LOOKUP_HASH(SH_TYPE * tb, SH_KEY_TYPE key, uint32 hash)
749+
{
750+
return SH_LOOKUP_HASH_INTERNAL(tb, key, hash);
751+
}
752+
701753
/*
702754
* Delete entry from hash table. Returns whether to-be-deleted key was
703755
* present.
@@ -971,8 +1023,10 @@ SH_STAT(SH_TYPE * tb)
9711023
#undef SH_DESTROY
9721024
#undef SH_RESET
9731025
#undef SH_INSERT
1026+
#undef SH_INSERT_HASH
9741027
#undef SH_DELETE
9751028
#undef SH_LOOKUP
1029+
#undef SH_LOOKUP_HASH
9761030
#undef SH_GROW
9771031
#undef SH_START_ITERATE
9781032
#undef SH_START_ITERATE_AT
@@ -989,3 +1043,5 @@ SH_STAT(SH_TYPE * tb)
9891043
#undef SH_PREV
9901044
#undef SH_DISTANCE_FROM_OPTIMAL
9911045
#undef SH_ENTRY_HASH
1046+
#undef SH_INSERT_HASH_INTERNAL
1047+
#undef SH_LOOKUP_HASH_INTERNAL

0 commit comments

Comments
 (0)