diff --git a/src/backend/executor/execGrouping.c b/src/backend/executor/execGrouping.c
index 47c9656..14f8c2d 100644
--- a/src/backend/executor/execGrouping.c
+++ b/src/backend/executor/execGrouping.c
@@ -330,7 +330,7 @@ BuildTupleHashTable(int numCols, AttrNumber *keyColIdx,
else
hashtable->hash_iv = 0;
- hashtable->hashtab = tuplehash_create(tablecxt, nbuckets);
+ hashtable->hashtab = tuplehash_create(tablecxt, nbuckets, NULL);
hashtable->hashtab->private_data = hashtable;
return hashtable;
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 7b31948..0885812 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -244,7 +244,7 @@ tbm_create_pagetable(TIDBitmap *tbm)
Assert(tbm->status != TBM_HASH);
Assert(tbm->pagetable == NULL);
- tbm->pagetable = pagetable_create(tbm->mcxt, 128);
+ tbm->pagetable = pagetable_create(tbm->mcxt, 128, NULL);
/* If entry1 is valid, push it into the hashtable */
if (tbm->status == TBM_ONE_PAGE)
diff --git a/src/include/lib/simplehash.h b/src/include/lib/simplehash.h
index 12aedbc..e2c8f44 100644
--- a/src/include/lib/simplehash.h
+++ b/src/include/lib/simplehash.h
@@ -66,6 +66,7 @@
#define SH_STATUS_EMPTY SH_MAKE_NAME(EMPTY)
#define SH_STATUS_IN_USE SH_MAKE_NAME(IN_USE)
#define SH_ITERATOR SH_MAKE_NAME(iterator)
+#define SH_ALLOCATOR SH_MAKE_NAME(alloc)
/* function declarations */
#define SH_CREATE SH_MAKE_NAME(create)
@@ -78,6 +79,7 @@
#define SH_START_ITERATE_AT SH_MAKE_NAME(start_iterate_at)
#define SH_ITERATE SH_MAKE_NAME(iterate)
#define SH_STAT SH_MAKE_NAME(stat)
+#define SH_COPY SH_MAKE_NAME(copy)
/* internal helper functions (no externally visible prototypes) */
#define SH_COMPUTE_PARAMETERS SH_MAKE_NAME(compute_parameters)
@@ -90,6 +92,18 @@
/* generate forward declarations necessary to use the hash table */
#ifdef SH_DECLARE
+typedef struct SH_ALLOCATOR
+{
+ /* Allocation function */
+ void *(*HashAlloc) (Size size, void *args);
+
+ /* Free function */
+ void (*HashFree) (void *pointer, void *args);
+
+ /* Arguments to be passed to alloc and free functions */
+ void *args;
+} SH_ALLOCATOR;
+
/* type definitions */
typedef struct SH_TYPE
{
@@ -112,6 +126,9 @@ typedef struct SH_TYPE
/* hash buckets */
SH_ELEMENT_TYPE *data;
+ /* hash allocator */
+ SH_ALLOCATOR *alloc;
+
/* memory context to use for allocations */
MemoryContext ctx;
@@ -133,7 +150,8 @@ typedef struct SH_ITERATOR
} SH_ITERATOR;
/* externally visible function prototypes */
-SH_SCOPE SH_TYPE *SH_CREATE(MemoryContext ctx, uint32 nelements);
+SH_SCOPE SH_TYPE *SH_CREATE(MemoryContext ctx, uint32 nelements,
+ SH_ALLOCATOR *alloc);
SH_SCOPE void SH_DESTROY(SH_TYPE *tb);
SH_SCOPE void SH_GROW(SH_TYPE *tb, uint32 newsize);
SH_SCOPE SH_ELEMENT_TYPE *SH_INSERT(SH_TYPE *tb, SH_KEY_TYPE key, bool *found);
@@ -143,6 +161,7 @@ SH_SCOPE void SH_START_ITERATE(SH_TYPE *tb, SH_ITERATOR *iter);
SH_SCOPE void SH_START_ITERATE_AT(SH_TYPE *tb, SH_ITERATOR *iter, uint32 at);
SH_SCOPE SH_ELEMENT_TYPE *SH_ITERATE(SH_TYPE *tb, SH_ITERATOR *iter);
SH_SCOPE void SH_STAT(SH_TYPE *tb);
+SH_SCOPE void SH_COPY(SH_TYPE *src_tb, SH_TYPE *dst_tb, SH_ELEMENT_TYPE *data);
#endif /* SH_DECLARE */
@@ -276,15 +295,38 @@ SH_ENTRY_HASH(SH_TYPE *tb, SH_ELEMENT_TYPE * entry)
#endif
}
+/* default memory allocator function */
+static void *
+SH_DEFAULT_ALLOC(Size size, void *args)
+{
+ MemoryContext context = (MemoryContext) args;
+
+ return MemoryContextAllocExtended(context, size,
+ MCXT_ALLOC_HUGE | MCXT_ALLOC_ZERO);
+}
+
+/* default memory free function */
+static void
+SH_DEFAULT_FREE(void *pointer, void *args)
+{
+ pfree(pointer);
+}
+
/*
* Create a hash table with enough space for `nelements` distinct members,
* allocating required memory in the passed-in context.
+ *
+ * WARNING : alloc is an allocator handle which provides memory allocator
+ * function for storing hash elements. User needs to be aware that providing
+ * allocator does not store complete hash table in the allocator memory i.e
+ * hash table will still be allocated in local memory. However all the
+ * elements will be stored in the memory provided by the allocator.
*/
SH_SCOPE SH_TYPE *
-SH_CREATE(MemoryContext ctx, uint32 nelements)
+SH_CREATE(MemoryContext ctx, uint32 nelements, SH_ALLOCATOR *alloc)
{
- SH_TYPE *tb;
- uint64 size;
+ SH_TYPE *tb;
+ uint64 size;
tb = MemoryContextAllocZero(ctx, sizeof(SH_TYPE));
tb->ctx = ctx;
@@ -294,9 +336,19 @@ SH_CREATE(MemoryContext ctx, uint32 nelements)
SH_COMPUTE_PARAMETERS(tb, size);
- tb->data = MemoryContextAllocExtended(tb->ctx,
- sizeof(SH_ELEMENT_TYPE) * tb->size,
- MCXT_ALLOC_HUGE | MCXT_ALLOC_ZERO);
+ tb->alloc = palloc(sizeof(SH_ALLOCATOR));
+
+ if (!alloc)
+ {
+ tb->alloc->HashAlloc = SH_DEFAULT_ALLOC;
+ tb->alloc->HashFree = SH_DEFAULT_FREE;
+ tb->alloc->args = tb->ctx;
+ }
+ else
+ memcpy(tb->alloc, alloc, sizeof(SH_ALLOCATOR));
+
+ tb->data = tb->alloc->HashAlloc(sizeof(SH_ELEMENT_TYPE) * tb->size,
+ tb->alloc->args);
return tb;
}
@@ -305,7 +357,12 @@ SH_CREATE(MemoryContext ctx, uint32 nelements)
SH_SCOPE void
SH_DESTROY(SH_TYPE *tb)
{
- pfree(tb->data);
+ if (tb->alloc)
+ {
+ tb->alloc->HashFree(tb->data, tb->alloc->args);
+ pfree(tb->alloc);
+ }
+
pfree(tb);
}
@@ -333,9 +390,8 @@ SH_GROW(SH_TYPE *tb, uint32 newsize)
/* compute parameters for new table */
SH_COMPUTE_PARAMETERS(tb, newsize);
- tb->data = MemoryContextAllocExtended(
- tb->ctx, sizeof(SH_ELEMENT_TYPE) * tb->size,
- MCXT_ALLOC_HUGE | MCXT_ALLOC_ZERO);
+ tb->data = tb->alloc->HashAlloc(sizeof(SH_ELEMENT_TYPE) * tb->size,
+ tb->alloc->args);
newdata = tb->data;
@@ -421,7 +477,8 @@ SH_GROW(SH_TYPE *tb, uint32 newsize)
}
}
- pfree(olddata);
+ tb->alloc->HashFree(olddata, tb->alloc->args);
+
}
/*
@@ -826,6 +883,18 @@ SH_STAT(SH_TYPE *tb)
total_collisions, max_collisions, avg_collisions);
}
+/*
+ * Copy information from src_tb to dst_tb, it only copies those informations
+ * which are required by SH_ITERATE. Also store input data as hashtable data.
+ */
+SH_SCOPE void
+SH_COPY (SH_TYPE *src_tb, SH_TYPE *dst_tb, SH_ELEMENT_TYPE *data)
+{
+ dst_tb->size = src_tb->size;
+ dst_tb->sizemask = src_tb->sizemask;
+ dst_tb->data = data;
+}
+
#endif /* SH_DEFINE */