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;
343 next_item_pointer = item->
next;
345 item_pointer = next_item_pointer;
438 size_t partition_index;
574 return memcmp(
a,
b,
size);
604 return strcmp((
const char *)
a, (
const char *)
b);
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;
909 next_item_pointer = item->
next;
913 item_pointer = next_item_pointer;
921 hash_table->
buckets = new_buckets;
959 item_pointer = item->
next;
975 item->
next = *bucket;
976 *bucket = item_pointer;
1020 *bucket_head =
next;
1024 bucket_head = &item->
next;
1043 if (bucket_item == item)
1049 *bucket_head =
next;
1052 bucket_head = &bucket_item->
next;
1076 hash_table->
arg) == 0;
#define PG_USED_FOR_ASSERTS_ONLY
#define Assert(condition)
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_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)
#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)
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)
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)
#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)
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
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)
uint32 string_hash(const void *key, Size keysize)
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)
static pg_noinline void Size size
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