59#define DSHASH_NUM_PARTITIONS_LOG2 7
60#define DSHASH_NUM_PARTITIONS (1 << DSHASH_NUM_PARTITIONS_LOG2)
63#define DSHASH_MAGIC 0x75ff6a20
114#define ENTRY_FROM_ITEM(item) \
115 ((char *)(item) + MAXALIGN(sizeof(dshash_table_item)))
118#define ITEM_FROM_ENTRY(entry) \
119 ((dshash_table_item *)((char *)(entry) - \
120 MAXALIGN(sizeof(dshash_table_item))))
123#define NUM_SPLITS(size_log2) \
124 (size_log2 - DSHASH_NUM_PARTITIONS_LOG2)
127#define NUM_BUCKETS(size_log2) \
128 (((size_t) 1) << (size_log2))
131#define BUCKETS_PER_PARTITION(size_log2) \
132 (((size_t) 1) << NUM_SPLITS(size_log2))
135#define MAX_COUNT_PER_PARTITION(hash_table) \
136 (BUCKETS_PER_PARTITION(hash_table->size_log2) / 2 + \
137 BUCKETS_PER_PARTITION(hash_table->size_log2) / 4)
140#define PARTITION_FOR_HASH(hash) \
141 (hash >> ((sizeof(dshash_hash) * CHAR_BIT) - DSHASH_NUM_PARTITIONS_LOG2))
149#define BUCKET_INDEX_FOR_HASH_AND_SIZE(hash, size_log2) \
150 (hash >> ((sizeof(dshash_hash) * CHAR_BIT) - (size_log2)))
153#define BUCKET_INDEX_FOR_PARTITION(partition, size_log2) \
154 ((partition) << NUM_SPLITS(size_log2))
157#define PARTITION_FOR_BUCKET_INDEX(bucket_idx, size_log2) \
158 ((bucket_idx) >> NUM_SPLITS(size_log2))
161#define BUCKET_FOR_HASH(hash_table, hash) \
162 (hash_table->buckets[ \
163 BUCKET_INDEX_FOR_HASH_AND_SIZE(hash, \
164 hash_table->size_log2)])
188 const void *
a,
const void *
b);
192#define PARTITION_LOCK(hash_table, i) \
193 (&(hash_table)->control->partitions[(i)].lock)
195#define ASSERT_NO_PARTITION_LOCKS_HELD_BY_ME(hash_table) \
196 Assert(!LWLockAnyHeldByMe(&(hash_table)->control->partitions[0].lock, \
197 DSHASH_NUM_PARTITIONS, sizeof(dshash_partition)))
218 hash_table->
area = area;
219 hash_table->
params = *params;
252 (
errcode(ERRCODE_OUT_OF_MEMORY),
254 errdetail(
"Failed on DSA request of size %zu.",
283 hash_table->
area = area;
284 hash_table->
params = *params;
333 for (
i = 0;
i < size; ++
i)
343 next_item_pointer = item->
next;
345 item_pointer = next_item_pointer;
438 size_t partition_index;
574 return memcmp(
a,
b, size);
592 (void) memcpy(
dest, src, size);
601 Assert(strlen((
const char *)
a) < size);
602 Assert(strlen((
const char *)
b) < size);
604 return strcmp((
const char *)
a, (
const char *)
b);
613 Assert(strlen((
const char *) v) < size);
624 Assert(strlen((
const char *) src) < size);
626 (void) strcpy((
char *)
dest, (
const char *) src);
795 "hash table size = %zu\n", (
size_t) 1 << hash_table->
size_log2);
802 fprintf(stderr,
" partition %zu\n",
i);
804 " active buckets (key count = %zu)\n", partition->
count);
806 for (
j = begin;
j < end; ++
j)
820 fprintf(stderr,
" bucket %zu (key count = %zu)\n",
j, count);
864 size_t new_size = ((size_t) 1) << new_size_log2;
901 for (
i = 0;
i < size; ++
i)
911 next_item_pointer = item->
next;
915 item_pointer = next_item_pointer;
923 hash_table->
buckets = new_buckets;
961 item_pointer = item->
next;
977 item->
next = *bucket;
978 *bucket = item_pointer;
1022 *bucket_head =
next;
1026 bucket_head = &item->
next;
1045 if (bucket_item == item)
1051 *bucket_head =
next;
1054 bucket_head = &bucket_item->
next;
1078 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