citus/src/include/distributed/hash_helpers.h

133 lines
4.5 KiB
C

/*-------------------------------------------------------------------------
* hash_helpers.h
*
* Copyright (c) Citus Data, Inc.
*
*-------------------------------------------------------------------------
*/
#ifndef HASH_HELPERS_H
#define HASH_HELPERS_H
#include "postgres.h"
#include "distributed/pg_version_constants.h"
#include "utils/hsearch.h"
/*
* assert_valid_hash_key2 checks if a type that contains 2 fields contains no
* padding bytes. This is necessary to use a type as a hash key with tag_hash.
*/
#define assert_valid_hash_key2(type, field1, field2) \
StaticAssertDecl( \
sizeof(type) == sizeof(((type) { 0 }).field1) \
+ sizeof(((type) { 0 }).field2), \
# type " has padding bytes, but is used as a hash key in a simple hash");
/*
* assert_valid_hash_key3 checks if a type that contains 3 fields contains no
* padding bytes. This is necessary to use a type as a hash key with tag_hash.
*/
#define assert_valid_hash_key3(type, field1, field2, field3) \
StaticAssertDecl( \
sizeof(type) == sizeof(((type) { 0 }).field1) \
+ sizeof(((type) { 0 }).field2) \
+ sizeof(((type) { 0 }).field3), \
# type " has padding bytes, but is used as a hash key in a simple hash");
extern void hash_delete_all(HTAB *htab);
/*
* foreach_htab -
* a convenience macro which loops through a HTAB
*/
#define foreach_htab(var, status, htab) \
hash_seq_init((status), (htab)); \
for ((var) = hash_seq_search(status); \
(var) != NULL; \
(var) = hash_seq_search(status))
extern void foreach_htab_cleanup(void *var, HASH_SEQ_STATUS *status);
extern HTAB * CreateSimpleHashWithNameAndSizeInternal(Size keysize, Size entrysize,
char *name, long nelem);
/*
* CreatesSimpleHash creates a hash table that hash its key using the tag_hash
* and stores then entries in the CurrentMemoryContext.
*
* We use 32 as the initial number of elements that fit into this hash
* table. This value seems a reasonable tradeof between two issues:
* 1. An empty hashmap shouldn't take up a lot of space
* 2. Doing a few inserts shouldn't require growing the hashmap
*
* NOTE: No performance testing has been performed when choosing this
* value. If this ever turns out to be a problem, feel free to do some
* performance tests.
*
* IMPORTANT: Because this uses tag_hash it's required that the keyType
* contains no automatic padding bytes, because that will result in tag_hash
* returning undefined values. You can check this using assert_valid_hash_keyX.
*/
#define CreateSimpleHash(keyType, entryType) \
CreateSimpleHashWithNameAndSize(keyType, entryType, \
# entryType "Hash", 32)
/*
* Same as CreateSimpleHash but allows specifying the name
*/
#define CreateSimpleHashWithName(keyType, entryType, name) \
CreateSimpleHashWithNameAndSize(keyType, entryType, \
name, 32)
/*
* CreateSimpleHashWithSize is the same as CreateSimpleHash, but allows
* configuring of the amount of elements that initially fit in the hash table.
*/
#define CreateSimpleHashWithSize(keyType, entryType, size) \
CreateSimpleHashWithNameAndSize(keyType, entryType, \
# entryType "Hash", size)
#define CreateSimpleHashWithNameAndSize(keyType, entryType, name, size) \
CreateSimpleHashWithNameAndSizeInternal(sizeof(keyType), \
sizeof(entryType), \
name, size)
/*
* CreatesSimpleHashSet creates a hash set that hashes its values using the
* tag_hash and stores the values in the CurrentMemoryContext.
*/
#define CreateSimpleHashSet(keyType) \
CreateSimpleHashWithName(keyType, keyType, \
# keyType "HashSet")
/*
* CreatesSimpleHashSetWithSize creates a hash set that hashes its values using
* the tag_hash and stores the values in the CurrentMemoryContext. It allows
* specifying its number of elements.
*/
#define CreateSimpleHashSetWithSize(keyType, size) \
CreateSimpleHashWithNameAndSize(keyType, keyType, # keyType "HashSet", size)
/*
* CreatesSimpleHashSetWithName creates a hash set that hashes its values using the
* tag_hash and stores the values in the CurrentMemoryContext. It allows
* specifying its name.
*/
#define CreateSimpleHashSetWithName(keyType, name) \
CreateSimpleHashWithName(keyType, keyType, name)
/*
* CreatesSimpleHashSetWithName creates a hash set that hashes its values using the
* tag_hash and stores the values in the CurrentMemoryContext. It allows
* specifying its name and number of elements.
*/
#define CreateSimpleHashSetWithNameAndSize(keyType, name, size) \
CreateSimpleHashWithNameAndSize(keyType, keyType, name, size)
#endif