Commit 9c8165fd authored by Sergey Vojtovich's avatar Sergey Vojtovich

MDEV-6089 - MySQL WL#7305 "Improve MDL scalability by using lock-free hash"

Added initializer callback to lf-hash. Needed to initialize properly non-POD
types.
parent f5bd1d01
...@@ -130,22 +130,26 @@ C_MODE_END ...@@ -130,22 +130,26 @@ C_MODE_END
C_MODE_START C_MODE_START
typedef struct st_lf_hash LF_HASH;
typedef void (*lf_hash_initializer)(LF_HASH *hash, void *dst, const void *src);
#define LF_HASH_UNIQUE 1 #define LF_HASH_UNIQUE 1
/* lf_hash overhead per element (that is, sizeof(LF_SLIST) */ /* lf_hash overhead per element (that is, sizeof(LF_SLIST) */
extern const int LF_HASH_OVERHEAD; extern const int LF_HASH_OVERHEAD;
typedef struct { struct st_lf_hash {
LF_DYNARRAY array; /* hash itself */ LF_DYNARRAY array; /* hash itself */
LF_ALLOCATOR alloc; /* allocator for elements */ LF_ALLOCATOR alloc; /* allocator for elements */
my_hash_get_key get_key; /* see HASH */ my_hash_get_key get_key; /* see HASH */
lf_hash_initializer initializer; /* called when an element is inserted */
CHARSET_INFO *charset; /* see HASH */ CHARSET_INFO *charset; /* see HASH */
uint key_offset, key_length; /* see HASH */ uint key_offset, key_length; /* see HASH */
uint element_size; /* size of memcpy'ed area on insert */ uint element_size; /* size of memcpy'ed area on insert */
uint flags; /* LF_HASH_UNIQUE, etc */ uint flags; /* LF_HASH_UNIQUE, etc */
int32 volatile size; /* size of array */ int32 volatile size; /* size of array */
int32 volatile count; /* number of elements in the hash */ int32 volatile count; /* number of elements in the hash */
} LF_HASH; };
void lf_hash_init(LF_HASH *hash, uint element_size, uint flags, void lf_hash_init(LF_HASH *hash, uint element_size, uint flags,
uint key_offset, uint key_length, my_hash_get_key get_key, uint key_offset, uint key_length, my_hash_get_key get_key,
......
...@@ -319,6 +319,11 @@ static inline uint calc_hash(LF_HASH *hash, const uchar *key, uint keylen) ...@@ -319,6 +319,11 @@ static inline uint calc_hash(LF_HASH *hash, const uchar *key, uint keylen)
static int initialize_bucket(LF_HASH *, LF_SLIST * volatile*, uint, LF_PINS *); static int initialize_bucket(LF_HASH *, LF_SLIST * volatile*, uint, LF_PINS *);
static void default_initializer(LF_HASH *hash, void *dst, const void *src)
{
memcpy(dst, src, hash->element_size);
}
/* /*
Initializes lf_hash, the arguments are compatible with hash_init Initializes lf_hash, the arguments are compatible with hash_init
...@@ -331,6 +336,9 @@ static int initialize_bucket(LF_HASH *, LF_SLIST * volatile*, uint, LF_PINS *); ...@@ -331,6 +336,9 @@ static int initialize_bucket(LF_HASH *, LF_SLIST * volatile*, uint, LF_PINS *);
DYNAMIC_ARRAY. In this case they should be initialize in the DYNAMIC_ARRAY. In this case they should be initialize in the
LF_ALLOCATOR::constructor, and lf_hash_insert should not overwrite them. LF_ALLOCATOR::constructor, and lf_hash_insert should not overwrite them.
See wt_init() for example. See wt_init() for example.
The above works well with PODS. For more complex cases (e.g. C++ classes
with private members) use initializer function.
*/ */
void lf_hash_init(LF_HASH *hash, uint element_size, uint flags, void lf_hash_init(LF_HASH *hash, uint element_size, uint flags,
uint key_offset, uint key_length, my_hash_get_key get_key, uint key_offset, uint key_length, my_hash_get_key get_key,
...@@ -347,6 +355,7 @@ void lf_hash_init(LF_HASH *hash, uint element_size, uint flags, ...@@ -347,6 +355,7 @@ void lf_hash_init(LF_HASH *hash, uint element_size, uint flags,
hash->key_offset= key_offset; hash->key_offset= key_offset;
hash->key_length= key_length; hash->key_length= key_length;
hash->get_key= get_key; hash->get_key= get_key;
hash->initializer= default_initializer;
DBUG_ASSERT(get_key ? !key_offset && !key_length : key_length); DBUG_ASSERT(get_key ? !key_offset && !key_length : key_length);
} }
...@@ -392,7 +401,7 @@ int lf_hash_insert(LF_HASH *hash, LF_PINS *pins, const void *data) ...@@ -392,7 +401,7 @@ int lf_hash_insert(LF_HASH *hash, LF_PINS *pins, const void *data)
node= (LF_SLIST *)lf_alloc_new(pins); node= (LF_SLIST *)lf_alloc_new(pins);
if (unlikely(!node)) if (unlikely(!node))
return -1; return -1;
memcpy(node+1, data, hash->element_size); hash->initializer(hash, node + 1, data);
node->key= hash_key(hash, (uchar *)(node+1), &node->keylen); node->key= hash_key(hash, (uchar *)(node+1), &node->keylen);
hashnr= calc_hash(hash, node->key, node->keylen); hashnr= calc_hash(hash, node->key, node->keylen);
bucket= hashnr % hash->size; bucket= hashnr % hash->size;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment