earthdistance \
file_fdw \
fuzzystrmatch \
+ hashtest \
hstore \
intagg \
intarray \
--- /dev/null
+# contrib/hashtest/Makefile
+
+MODULE_big = hashtest
+OBJS = hashtest.o
+
+EXTENSION = hashtest
+DATA = hashtest--1.0.sql
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = contrib/hashtest
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
--- /dev/null
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION hashtest" to load this file. \quit
+
+CREATE FUNCTION test_dynahash()
+RETURNS void
+AS 'MODULE_PATHNAME', 'test_dynahash'
+LANGUAGE C;
+
+CREATE FUNCTION test_chash()
+RETURNS void
+AS 'MODULE_PATHNAME', 'test_chash'
+LANGUAGE C;
--- /dev/null
+/*-------------------------------------------------------------------------
+ * hashtest.c
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "funcapi.h"
+#include "miscadmin.h"
+#include "storage/ipc.h"
+#include "utils/chash.h"
+
+PG_MODULE_MAGIC;
+
+void _PG_init(void);
+Datum test_dynahash(PG_FUNCTION_ARGS);
+Datum test_chash(PG_FUNCTION_ARGS);
+static void hashtest_shmem_startup(void);
+
+PG_FUNCTION_INFO_V1(test_dynahash);
+PG_FUNCTION_INFO_V1(test_chash);
+
+typedef struct
+{
+ uint32 key;
+ uint32 val;
+} hentry;
+
+static CHashDescriptor cdesc = {
+ "hashtest-chash", /* name */
+ 0xd3c8eae3, /* id */
+ 1048576, /* capacity */
+ sizeof(hentry), /* element size */
+ sizeof(uint32) /* key size */
+};
+
+static shmem_startup_hook_type prev_shmem_startup_hook = NULL;
+static CHashTable chash;
+
+void
+_PG_init(void)
+{
+ if (!process_shared_preload_libraries_in_progress)
+ return;
+ prev_shmem_startup_hook = shmem_startup_hook;
+ shmem_startup_hook = hashtest_shmem_startup;
+ chash = CHashBootstrap(&cdesc);
+ RequestAddinShmemSpace(CHashEstimateSize(chash));
+ RequestAddinShmemSpace(hash_estimate_size(cdesc.capacity,
+ cdesc.element_size));
+}
+
+static void
+hashtest_shmem_startup(void)
+{
+ if (prev_shmem_startup_hook)
+ prev_shmem_startup_hook();
+ chash = CHashInitialize(chash, &cdesc);
+}
+
+Datum
+test_dynahash(PG_FUNCTION_ARGS)
+{
+ PG_RETURN_VOID();
+}
+
+Datum
+test_chash(PG_FUNCTION_ARGS)
+{
+ hentry e;
+ bool found;
+
+ e.key = 1;
+ found = CHashSearch(chash, &e);
+ if (found)
+ elog(LOG, "found");
+ else
+ elog(LOG, "not found");
+
+ PG_RETURN_VOID();
+}
--- /dev/null
+comment = 'hash testing code'
+default_version = '1.0'
+module_pathname = '$libdir/hashtest'
+relocatable = true
for (i = 0; i < table->nbuckets; ++i)
{
table->bucket[i].head = InvalidCHashPtr;
- SpinLockInit(&table->bucket[i].head);
+ SpinLockInit(&table->bucket[i].mutex);
}
for (i = 0; i < table->ngarbage; ++i)
{
table->garbage[i].head = InvalidCHashPtr;
- SpinLockInit(&table->garbage[i].head);
+ SpinLockInit(&table->garbage[i].mutex);
}
for (i = 0; i < table->nfreelists; ++i)
{
table->freelist[i].head = InvalidCHashPtr;
- SpinLockInit(&table->freelist[i].head);
+ SpinLockInit(&table->freelist[i].mutex);
}
/* Put all arena elements on the free lists. */
CHashTableSuppressGC(table, bucket);
/* Scan bucket. */
+ elog(LOG, "table=%p table->bucket=%p", table, table->bucket);
c = table->bucket[bucket].head;
for (;;)
{
/* If we've reached the end of the bucket chain, stop. */
if (c == InvalidCHashPtr)
break;
+ elog(LOG, "table->nbuckets=%d table->bucket_mask=%d bucket=%d c=%d",
+ (int) table->nbuckets, table->bucket_mask, (int) bucket, (int) c);
/* Compare current node by hashcode, then by memcmp. */
n = CHashTableGetNode(table, CHashPtrGetOffset(c));