Introduce hash_search_with_hash_value() function
authorAlexander Korotkov <[email protected]>
Wed, 7 Aug 2024 03:51:16 +0000 (06:51 +0300)
committerAlexander Korotkov <[email protected]>
Wed, 7 Aug 2024 04:06:17 +0000 (07:06 +0300)
This new function iterates hash entries with given hash values.  This function
is designed to avoid full sequential hash search in the syscache invalidation
callbacks.

Discussion: https://postgr.es/m/5812a6e5-68ae-4d84-9d85-b443176966a1%40sigaev.ru
Author: Teodor Sigaev
Reviewed-by: Aleksander Alekseev, Tom Lane, Michael Paquier, Roman Zharkov
Reviewed-by: Andrei Lepikhov
src/backend/utils/hash/dynahash.c
src/include/utils/hsearch.h

index 145e058fe675b880e34c9b1a549050e6f123860c..8040416a13c166b3fb585cda01d81afc12b7e3c7 100644 (file)
@@ -1387,10 +1387,30 @@ hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
    status->hashp = hashp;
    status->curBucket = 0;
    status->curEntry = NULL;
+   status->hasHashvalue = false;
    if (!hashp->frozen)
        register_seq_scan(hashp);
 }
 
+/*
+ * Same as above but scan by the given hash value.
+ * See also hash_seq_search().
+ */
+void
+hash_seq_init_with_hash_value(HASH_SEQ_STATUS *status, HTAB *hashp,
+                             uint32 hashvalue)
+{
+   HASHBUCKET *bucketPtr;
+
+   hash_seq_init(status, hashp);
+
+   status->hasHashvalue = true;
+   status->hashvalue = hashvalue;
+
+   status->curBucket = hash_initial_lookup(hashp, hashvalue, &bucketPtr);
+   status->curEntry = *bucketPtr;
+}
+
 void *
 hash_seq_search(HASH_SEQ_STATUS *status)
 {
@@ -1404,6 +1424,24 @@ hash_seq_search(HASH_SEQ_STATUS *status)
    uint32      curBucket;
    HASHELEMENT *curElem;
 
+   if (status->hasHashvalue)
+   {
+       /*
+        * Scan entries only in the current bucket because only this bucket
+        * can contain entries with the given hash value.
+        */
+       while ((curElem = status->curEntry) != NULL)
+       {
+           status->curEntry = curElem->link;
+           if (status->hashvalue != curElem->hashvalue)
+               continue;
+           return (void *) ELEMENTKEY(curElem);
+       }
+
+       hash_seq_term(status);
+       return NULL;
+   }
+
    if ((curElem = status->curEntry) != NULL)
    {
        /* Continuing scan of curBucket... */
index da26941f6db5ffda5bd3b960235c724000a319ad..d2919677a2d94a825982cba7fda2325fb45f2701 100644 (file)
@@ -122,6 +122,8 @@ typedef struct
    HTAB       *hashp;
    uint32      curBucket;      /* index of current bucket */
    HASHELEMENT *curEntry;      /* current entry in bucket */
+   bool        hasHashvalue;   /* true if hashvalue was provided */
+   uint32      hashvalue;      /* hashvalue to start seqscan over hash */
 } HASH_SEQ_STATUS;
 
 /*
@@ -141,6 +143,9 @@ extern bool hash_update_hash_key(HTAB *hashp, void *existingEntry,
                                 const void *newKeyPtr);
 extern long hash_get_num_entries(HTAB *hashp);
 extern void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp);
+extern void hash_seq_init_with_hash_value(HASH_SEQ_STATUS *status,
+                                         HTAB *hashp,
+                                         uint32 hashvalue);
 extern void *hash_seq_search(HASH_SEQ_STATUS *status);
 extern void hash_seq_term(HASH_SEQ_STATUS *status);
 extern void hash_freeze(HTAB *hashp);