Improve dynahash test code.
authorRobert Haas <rhaas@postgresql.org>
Wed, 25 Jul 2012 15:35:47 +0000 (11:35 -0400)
committerRobert Haas <rhaas@postgresql.org>
Mon, 13 Oct 2014 17:13:55 +0000 (13:13 -0400)
contrib/hashtest/hashtest.c

index 0b18bfccb9645e976bae8e194592861143fd04e1..a8980f87ac84ccfddae749e4f026c540d2288c54 100644 (file)
@@ -34,9 +34,15 @@ static CHashDescriptor cdesc = {
    sizeof(uint32)      /* key size */
 };
 
+#define DYNAHASH_PARTITIONS        16
+
 static shmem_startup_hook_type prev_shmem_startup_hook = NULL;
 static CHashTable chash;
 static HTAB *dynahash;
+static LWLockId dynahash_lock[DYNAHASH_PARTITIONS];
+
+#define dynahash_get_lock(hashcode) \
+   (dynahash_lock[(hashcode) % DYNAHASH_PARTITIONS])
 
 void
 _PG_init(void)
@@ -49,12 +55,14 @@ _PG_init(void)
    RequestAddinShmemSpace(CHashEstimateSize(chash));
    RequestAddinShmemSpace(hash_estimate_size(cdesc.capacity,
                                              cdesc.element_size));
+   RequestAddinLWLocks(DYNAHASH_PARTITIONS);
 }
 
 static void
 hashtest_shmem_startup(void)
 {
    HASHCTL     info;
+   uint32      i;
 
    if (prev_shmem_startup_hook)
        prev_shmem_startup_hook();
@@ -63,15 +71,18 @@ hashtest_shmem_startup(void)
    chash = CHashInitialize(chash, &cdesc);
 
    /* Initialize shared dynahash table. */
-   info.keysize = sizeof(cdesc.key_size);
-   info.entrysize = sizeof(cdesc.element_size);
+   info.keysize = cdesc.key_size;
+   info.entrysize = cdesc.element_size;
    info.hash = tag_hash;
-   info.num_partitions = 16;
+   info.num_partitions = DYNAHASH_PARTITIONS;
 
    dynahash = ShmemInitHash("hashtest-dynahash",
                             cdesc.capacity, cdesc.capacity,
                             &info,
                             HASH_ELEM | HASH_FUNCTION | HASH_PARTITION);
+
+   for (i = 0; i < DYNAHASH_PARTITIONS; ++i)
+       dynahash_lock[i] = LWLockAssign();
 }
 
 Datum
@@ -115,26 +126,48 @@ dynahash_insert(uint32 key, uint32 val)
    bool    found;
    uint32  hashcode;
    hentry *e;
+   LWLockId    lockid;
 
    hashcode = get_hash_value(dynahash, (void *) &key);
-   /* lock */
+   lockid = dynahash_get_lock(hashcode);
+   LWLockAcquire(lockid, LW_SHARED);
    e = hash_search_with_hash_value(dynahash, (void *) &key,
                                    hashcode, HASH_ENTER, &found);
    if (!found)
        e->val = val;
-   /* unlock */
+   LWLockRelease(lockid);
 
    return !found;
 }
 
+static bool
+dynahash_search(uint32 key, uint32 *val)
+{
+   uint32  hashcode;
+   hentry *e;
+   LWLockId    lockid;
+
+   hashcode = get_hash_value(dynahash, (void *) &key);
+   lockid = dynahash_get_lock(hashcode);
+   LWLockAcquire(lockid, LW_SHARED);
+   e = hash_search_with_hash_value(dynahash, (void *) &key,
+                                   hashcode, HASH_FIND, NULL);
+   if (e)
+       *val = e->val;
+   LWLockRelease(lockid);
+
+   return e != NULL;
+}
+
 Datum
 test_dynahash(PG_FUNCTION_ARGS)
 {
    uint32  i;
-   bool    ok;
 
    for (i = 0; i < 1000000; ++i)
    {
+       bool    ok;
+
        ok = dynahash_insert(i, i * 31);
        if (!ok)
            elog(LOG, "insert %u: failed", i);
@@ -143,5 +176,17 @@ test_dynahash(PG_FUNCTION_ARGS)
            elog(LOG, "insert %u: worked twice", i);
    }
 
+   for (i = 0; i < 1000000; ++i)
+   {
+       bool    ok;
+       uint32  val;
+
+       ok = dynahash_search(i, &val);
+       if (!ok)
+           elog(LOG, "search %u: not found", i);
+       else if (val != i* 31)
+           elog(LOG, "search %u: found %u", i, val);
+   }
+
    PG_RETURN_VOID();
 }