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);
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);
752 "hash table size = %zu\n", (
size_t) 1 << hash_table->
size_log2);
759 fprintf(stderr,
" partition %zu\n",
i);
761 " active buckets (key count = %zu)\n", partition->
count);
763 for (
j = begin;
j < end; ++
j)
777 fprintf(stderr,
" bucket %zu (key count = %zu)\n",
j, count);
821 size_t new_size = ((size_t) 1) << new_size_log2;
856 for (
i = 0;
i < size; ++
i)
866 next_item_pointer = item->
next;
870 item_pointer = next_item_pointer;
878 hash_table->
buckets = new_buckets;
916 item_pointer = item->
next;
932 item->
next = *bucket;
933 *bucket = item_pointer;
981 bucket_head = &item->
next;
1000 if (bucket_item == item)
1006 *bucket_head =
next;
1009 bucket_head = &bucket_item->
next;
1033 hash_table->
arg) == 0;
#define PG_USED_FOR_ASSERTS_ONLY
dsa_pointer dsa_allocate_extended(dsa_area *area, size_t size, int flags)
void * dsa_get_address(dsa_area *area, dsa_pointer dp)
void dsa_free(dsa_area *area, dsa_pointer dp)
#define dsa_allocate0(area, size)
#define dsa_allocate(area, size)
#define InvalidDsaPointer
#define DsaPointerIsValid(x)
bool dshash_delete_key(dshash_table *hash_table, const void *key)
void dshash_delete_entry(dshash_table *hash_table, void *entry)
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)
#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)
void * dshash_find(dshash_table *hash_table, const void *key, bool exclusive)
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)
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
#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)
#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_find_or_insert(dshash_table *hash_table, const void *key, bool *found)
dshash_table * dshash_attach(dsa_area *area, const dshash_parameters *params, dshash_table_handle handle, void *arg)
static void resize(dshash_table *hash_table, size_t new_size_log2)
int dshash_memcmp(const void *a, const void *b, size_t size, void *arg)
struct dshash_table_control dshash_table_control
dshash_table * dshash_create(dsa_area *area, const dshash_parameters *params, void *arg)
#define PARTITION_FOR_HASH(hash)
struct dshash_partition dshash_partition
void * dshash_seq_next(dshash_seq_status *status)
#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)
Assert(fmt[strlen(fmt) - 1] !='\n')
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_table_item * curitem
dshash_table * hash_table
dshash_partition partitions[DSHASH_NUM_PARTITIONS]
dshash_table_handle handle
dshash_table_control * control