1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-06 07:49:08 +03:00

Add helper functions for dshash tables with string keys.

Presently, string keys are not well-supported for dshash tables.
The dshash code always copies key_size bytes into new entries'
keys, and dshash.h only provides compare and hash functions that
forward to memcmp() and tag_hash(), both of which do not stop at
the first NUL.  This means that callers must pad string keys so
that the data beyond the first NUL does not adversely affect the
results of copying, comparing, and hashing the keys.

To better support string keys in dshash tables, this commit does
a couple things:

* A new copy_function field is added to the dshash_parameters
  struct.  This function pointer specifies how the key should be
  copied into new table entries.  For example, we only want to copy
  up to the first NUL byte for string keys.  A dshash_memcpy()
  helper function is provided and used for all existing in-tree
  dshash tables without string keys.

* A set of helper functions for string keys are provided.  These
  helper functions forward to strcmp(), strcpy(), and
  string_hash(), all of which ignore data beyond the first NUL.

This commit also adjusts the DSM registry's dshash table to use the
new helper functions for string keys.

Reviewed-by: Andy Fan
Discussion: https://postgr.es/m/20240119215941.GA1322079%40nathanxps13
This commit is contained in:
Nathan Bossart
2024-02-26 15:47:13 -06:00
parent 5fe08c006c
commit 42a1de3013
6 changed files with 83 additions and 7 deletions

View File

@@ -188,6 +188,8 @@ static bool delete_item_from_bucket(dshash_table *hash_table,
static inline dshash_hash hash_key(dshash_table *hash_table, const void *key);
static inline bool equal_keys(dshash_table *hash_table,
const void *a, const void *b);
static inline void copy_key(dshash_table *hash_table, void *dest,
const void *src);
#define PARTITION_LOCK(hash_table, i) \
(&(hash_table)->control->partitions[(i)].lock)
@@ -583,6 +585,49 @@ dshash_memhash(const void *v, size_t size, void *arg)
return tag_hash(v, size);
}
/*
* A copy function that forwards to memcpy.
*/
void
dshash_memcpy(void *dest, const void *src, size_t size, void *arg)
{
(void) memcpy(dest, src, size);
}
/*
* A compare function that forwards to strcmp.
*/
int
dshash_strcmp(const void *a, const void *b, size_t size, void *arg)
{
Assert(strlen((const char *) a) < size);
Assert(strlen((const char *) b) < size);
return strcmp((const char *) a, (const char *) b);
}
/*
* A hash function that forwards to string_hash.
*/
dshash_hash
dshash_strhash(const void *v, size_t size, void *arg)
{
Assert(strlen((const char *) v) < size);
return string_hash((const char *) v, size);
}
/*
* A copy function that forwards to strcpy.
*/
void
dshash_strcpy(void *dest, const void *src, size_t size, void *arg)
{
Assert(strlen((const char *) src) < size);
(void) strcpy((char *) dest, (const char *) src);
}
/*
* Sequentially scan through dshash table and return all the elements one by
* one, return NULL when all elements have been returned.
@@ -949,7 +994,7 @@ insert_into_bucket(dshash_table *hash_table,
hash_table->params.entry_size +
MAXALIGN(sizeof(dshash_table_item)));
item = dsa_get_address(hash_table->area, item_pointer);
memcpy(ENTRY_FROM_ITEM(item), key, hash_table->params.key_size);
copy_key(hash_table, ENTRY_FROM_ITEM(item), key);
insert_item_into_bucket(hash_table, item_pointer, item, bucket);
return item;
}
@@ -1032,3 +1077,14 @@ equal_keys(dshash_table *hash_table, const void *a, const void *b)
hash_table->params.key_size,
hash_table->arg) == 0;
}
/*
* Copy a key.
*/
static inline void
copy_key(dshash_table *hash_table, void *dest, const void *src)
{
hash_table->params.copy_function(dest, src,
hash_table->params.key_size,
hash_table->arg);
}