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..46604fe 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,18 @@ 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); + if (!alloc) + { + tb->alloc = palloc(sizeof(SH_ALLOCATOR)); + tb->alloc->HashAlloc = SH_DEFAULT_ALLOC; + tb->alloc->HashFree = SH_DEFAULT_FREE; + tb->alloc->args = tb->ctx; + } + else + tb->alloc = alloc; + + tb->data = tb->alloc->HashAlloc(sizeof(SH_ELEMENT_TYPE) * tb->size, + tb->alloc->args); return tb; } @@ -305,7 +356,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 +389,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 +476,8 @@ SH_GROW(SH_TYPE *tb, uint32 newsize) } } - pfree(olddata); + tb->alloc->HashFree(olddata, tb->alloc->args); + } /* @@ -826,6 +882,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 */