61#define DSHASH_NUM_PARTITIONS_LOG2 7
62#define DSHASH_NUM_PARTITIONS (1 << DSHASH_NUM_PARTITIONS_LOG2)
65#define DSHASH_MAGIC 0x75ff6a20
116#define ENTRY_FROM_ITEM(item) \
117 ((char *)(item) + MAXALIGN(sizeof(dshash_table_item)))
120#define ITEM_FROM_ENTRY(entry) \
121 ((dshash_table_item *)((char *)(entry) - \
122 MAXALIGN(sizeof(dshash_table_item))))
125#define NUM_SPLITS(size_log2) \
126 (size_log2 - DSHASH_NUM_PARTITIONS_LOG2)
129#define NUM_BUCKETS(size_log2) \
130 (((size_t) 1) << (size_log2))
133#define BUCKETS_PER_PARTITION(size_log2) \
134 (((size_t) 1) << NUM_SPLITS(size_log2))
137#define MAX_COUNT_PER_PARTITION(hash_table) \
138 (BUCKETS_PER_PARTITION(hash_table->size_log2) / 2 + \
139 BUCKETS_PER_PARTITION(hash_table->size_log2) / 4)
142#define PARTITION_FOR_HASH(hash) \
143 (hash >> ((sizeof(dshash_hash) * CHAR_BIT) - DSHASH_NUM_PARTITIONS_LOG2))
151#define BUCKET_INDEX_FOR_HASH_AND_SIZE(hash, size_log2) \
152 (hash >> ((sizeof(dshash_hash) * CHAR_BIT) - (size_log2)))
155#define BUCKET_INDEX_FOR_PARTITION(partition, size_log2) \
156 ((partition) << NUM_SPLITS(size_log2))
159#define PARTITION_FOR_BUCKET_INDEX(bucket_idx, size_log2) \
160 ((bucket_idx) >> NUM_SPLITS(size_log2))
163#define BUCKET_FOR_HASH(hash_table, hash) \
164 (hash_table->buckets[ \
165 BUCKET_INDEX_FOR_HASH_AND_SIZE(hash, \
166 hash_table->size_log2)])
190 const void *
a,
const void *
b);
194#define PARTITION_LOCK(hash_table, i) \
195 (&(hash_table)->control->partitions[(i)].lock)
197#define ASSERT_NO_PARTITION_LOCKS_HELD_BY_ME(hash_table) \
198 Assert(!LWLockAnyHeldByMe(&(hash_table)->control->partitions[0].lock, \
199 DSHASH_NUM_PARTITIONS, sizeof(dshash_partition)))
220 hash_table->
area = area;
221 hash_table->
params = *params;
254 (
errcode(ERRCODE_OUT_OF_MEMORY),
256 errdetail(
"Failed on DSA request of size %zu.",
285 hash_table->
area = area;
286 hash_table->
params = *params;
335 for (
i = 0;
i < size; ++
i)
345 next_item_pointer = item->
next;
347 item_pointer = next_item_pointer;
440 size_t partition_index;
576 return memcmp(
a,
b, size);
594 (void) memcpy(
dest, src, size);
603 Assert(strlen((
const char *)
a) < size);
604 Assert(strlen((
const char *)
b) < size);
606 return strcmp((
const char *)
a, (
const char *)
b);
615 Assert(strlen((
const char *) v) < size);
626 Assert(strlen((
const char *) src) < size);
628 (void) strcpy((
char *)
dest, (
const char *) src);
797 "hash table size = %zu\n", (
size_t) 1 << hash_table->
size_log2);
804 fprintf(stderr,
" partition %zu\n",
i);
806 " active buckets (key count = %zu)\n", partition->
count);
808 for (
j = begin;
j < end; ++
j)
822 fprintf(stderr,
" bucket %zu (key count = %zu)\n",
j, count);
866 size_t new_size = ((size_t) 1) << new_size_log2;
903 for (
i = 0;
i < size; ++
i)
913 next_item_pointer = item->
next;
917 item_pointer = next_item_pointer;
925 hash_table->
buckets = new_buckets;
963 item_pointer = item->
next;
979 item->
next = *bucket;
980 *bucket = item_pointer;
1024 *bucket_head =
next;
1028 bucket_head = &item->
next;
1047 if (bucket_item == item)
1053 *bucket_head =
next;
1056 bucket_head = &bucket_item->
next;
1080 hash_table->
arg) == 0;
#define PG_USED_FOR_ASSERTS_ONLY
#define fprintf(file, fmt, msg)
void * dsa_get_address(dsa_area *area, dsa_pointer dp)
dsa_pointer dsa_allocate_extended(dsa_area *area, size_t size, int flags)
void dsa_free(dsa_area *area, dsa_pointer dp)
#define dsa_allocate(area, size)
#define InvalidDsaPointer
#define DsaPointerIsValid(x)
bool dshash_delete_key(dshash_table *hash_table, const void *key)
void dshash_memcpy(void *dest, const void *src, size_t size, void *arg)
void dshash_delete_entry(dshash_table *hash_table, void *entry)
void dshash_strcpy(void *dest, const void *src, size_t size, void *arg)
void dshash_destroy(dshash_table *hash_table)
void dshash_release_lock(dshash_table *hash_table, void *entry)
#define PARTITION_LOCK(hash_table, i)
void dshash_detach(dshash_table *hash_table)
void dshash_seq_init(dshash_seq_status *status, dshash_table *hash_table, bool exclusive)
void * dshash_find(dshash_table *hash_table, const void *key, bool exclusive)
#define BUCKET_INDEX_FOR_HASH_AND_SIZE(hash, size_log2)
static bool delete_key_from_bucket(dshash_table *hash_table, const void *key, dsa_pointer *bucket_head)
dshash_hash dshash_strhash(const void *v, size_t size, void *arg)
static dshash_hash hash_key(dshash_table *hash_table, const void *key)
#define ASSERT_NO_PARTITION_LOCKS_HELD_BY_ME(hash_table)
#define ITEM_FROM_ENTRY(entry)
dshash_table_handle dshash_get_hash_table_handle(dshash_table *hash_table)
void dshash_dump(dshash_table *hash_table)
static bool equal_keys(dshash_table *hash_table, const void *a, const void *b)
dshash_table * dshash_attach(dsa_area *area, const dshash_parameters *params, dshash_table_handle handle, void *arg)
void dshash_seq_term(dshash_seq_status *status)
static void insert_item_into_bucket(dshash_table *hash_table, dsa_pointer item_pointer, dshash_table_item *item, dsa_pointer *bucket)
static bool delete_item_from_bucket(dshash_table *hash_table, dshash_table_item *item, dsa_pointer *bucket_head)
#define DSHASH_NUM_PARTITIONS
int dshash_strcmp(const void *a, const void *b, size_t size, void *arg)
#define PARTITION_FOR_BUCKET_INDEX(bucket_idx, size_log2)
static dshash_table_item * insert_into_bucket(dshash_table *hash_table, const void *key, dsa_pointer *bucket)
void * dshash_find_or_insert(dshash_table *hash_table, const void *key, bool *found)
#define BUCKET_INDEX_FOR_PARTITION(partition, size_log2)
#define MAX_COUNT_PER_PARTITION(hash_table)
#define ENTRY_FROM_ITEM(item)
#define DSHASH_NUM_PARTITIONS_LOG2
static void delete_item(dshash_table *hash_table, dshash_table_item *item)
dshash_hash dshash_memhash(const void *v, size_t size, void *arg)
#define NUM_BUCKETS(size_log2)
static void ensure_valid_bucket_pointers(dshash_table *hash_table)
static dshash_table_item * find_in_bucket(dshash_table *hash_table, const void *key, dsa_pointer item_pointer)
void * dshash_seq_next(dshash_seq_status *status)
dshash_table * dshash_create(dsa_area *area, const dshash_parameters *params, void *arg)
static void resize(dshash_table *hash_table, size_t new_size_log2)
static void copy_key(dshash_table *hash_table, void *dest, const void *src)
int dshash_memcmp(const void *a, const void *b, size_t size, void *arg)
struct dshash_table_control dshash_table_control
#define PARTITION_FOR_HASH(hash)
struct dshash_partition dshash_partition
#define BUCKET_FOR_HASH(hash_table, hash)
void dshash_delete_current(dshash_seq_status *status)
dsa_pointer dshash_table_handle
int errdetail(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
uint32 tag_hash(const void *key, Size keysize)
uint32 string_hash(const void *key, Size keysize)
Assert(PointerIsAligned(start, uint64))
bool LWLockHeldByMe(LWLock *lock)
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
bool LWLockHeldByMeInMode(LWLock *lock, LWLockMode mode)
void LWLockRelease(LWLock *lock)
void LWLockInitialize(LWLock *lock, int tranche_id)
void pfree(void *pointer)
static unsigned hash(unsigned *uv, int n)
dshash_hash_function hash_function
dshash_compare_function compare_function
dshash_copy_function copy_function
dshash_table_item * curitem
dshash_table * hash_table
dshash_partition partitions[DSHASH_NUM_PARTITIONS]
dshash_table_handle handle
dshash_table_control * control