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)
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();
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
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);
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();
}