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>
Wed, 25 Jul 2012 15:35:47 +0000 (11:35 -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();
 }