diff options
Diffstat (limited to 'mysys/mf_keycache.c')
-rw-r--r-- | mysys/mf_keycache.c | 252 |
1 files changed, 197 insertions, 55 deletions
diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index e4488318ffd..30f269454c2 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -5821,31 +5821,31 @@ static KEY_CACHE_FUNCS partitioned_key_cache_funcs = ******************************************************************************/ +static +int repartition_key_cache_internal(KEY_CACHE *keycache, + uint key_cache_block_size, size_t use_mem, + uint division_limit, uint age_threshold, + uint partitions, my_bool use_op_lock); /* - Initialize a key cache + Initialize a key cache : internal SYNOPSIS - init_key_cache() + init_key_cache_internal() keycache pointer to the key cache to be initialized key_cache_block_size size of blocks to keep cached data use_mem total memory to use for cache buffers/structures division_limit division limit (may be zero) age_threshold age threshold (may be zero) partitions number of partitions in the key cache + use_op_lock if TRUE use keycache->op_lock, otherwise - ignore it DESCRIPTION - The function creates a control block structure for a key cache and - places the pointer to this block in the structure keycache. - If the value of the parameter 'partitions' is 0 then a simple key cache - is created. Otherwise a partitioned key cache with the specified number - of partitions is created. - The parameter key_cache_block_size specifies the size of the blocks in - the key cache to be created. The parameters division_limit and - age_threshold determine the initial values of those characteristics of - the key cache that are used for midpoint insertion strategy. The parameter - use_mem specifies the total amount of memory to be allocated for the - key cache buffers and for all auxiliary structures. + The function performs the actions required from init_key_cache(). + It has an additional parameter: use_op_lock. When the parameter + is TRUE than the function initializes keycache->op_lock if needed, + then locks it, and unlocks it before the return. Otherwise the actions + with the lock are omitted. RETURN VALUE total number of blocks in key cache partitions, if successful, @@ -5854,19 +5854,22 @@ static KEY_CACHE_FUNCS partitioned_key_cache_funcs = NOTES if keycache->key_cache_inited != 0 we assume that the memory for the control block of the key cache has been already allocated. - - It's assumed that no two threads call this function simultaneously - referring to the same key cache handle. */ -int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, - size_t use_mem, uint division_limit, - uint age_threshold, uint partitions) +static +int init_key_cache_internal(KEY_CACHE *keycache, uint key_cache_block_size, + size_t use_mem, uint division_limit, + uint age_threshold, uint partitions, + my_bool use_op_lock) { void *keycache_cb; int blocks; if (keycache->key_cache_inited) + { + if (use_op_lock) + pthread_mutex_lock(&keycache->op_lock); keycache_cb= keycache->keycache_cb; + } else { if (partitions == 0) @@ -5887,8 +5890,17 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, keycache->key_cache_type= PARTITIONED_KEY_CACHE; keycache->interface_funcs= &partitioned_key_cache_funcs; } + /* + Initialize op_lock if it's not initialized before. + The mutex may have been initialized before if we are being called + from repartition_key_cache_internal(). + */ + if (use_op_lock) + pthread_mutex_init(&keycache->op_lock, MY_MUTEX_INIT_FAST); keycache->keycache_cb= keycache_cb; keycache->key_cache_inited= 1; + if (use_op_lock) + pthread_mutex_lock(&keycache->op_lock); } if (partitions != 0) @@ -5909,11 +5921,58 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, ((SIMPLE_KEY_CACHE_CB *) keycache_cb)->key_cache_mem_size; if (blocks > 0) keycache->can_be_used= 1; + if (use_op_lock) + pthread_mutex_unlock(&keycache->op_lock); return blocks; } /* + Initialize a key cache + + SYNOPSIS + init_key_cache() + keycache pointer to the key cache to be initialized + key_cache_block_size size of blocks to keep cached data + use_mem total memory to use for cache buffers/structures + division_limit division limit (may be zero) + age_threshold age threshold (may be zero) + partitions number of partitions in the key cache + + DESCRIPTION + The function creates a control block structure for a key cache and + places the pointer to this block in the structure keycache. + If the value of the parameter 'partitions' is 0 then a simple key cache + is created. Otherwise a partitioned key cache with the specified number + of partitions is created. + The parameter key_cache_block_size specifies the size of the blocks in + the key cache to be created. The parameters division_limit and + age_threshold determine the initial values of those characteristics of + the key cache that are used for midpoint insertion strategy. The parameter + use_mem specifies the total amount of memory to be allocated for the + key cache buffers and for all auxiliary structures. + The function calls init_key_cache_internal() to perform all these actions + with the last parameter set to TRUE. + + RETURN VALUE + total number of blocks in key cache partitions, if successful, + <= 0 - otherwise. + + NOTES + It's assumed that no two threads call this function simultaneously + referring to the same key cache handle. +*/ + +int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, + size_t use_mem, uint division_limit, + uint age_threshold, uint partitions) +{ + return init_key_cache_internal(keycache, key_cache_block_size, use_mem, + division_limit, age_threshold, partitions, 1); +} + + +/* Resize a key cache SYNOPSIS @@ -5953,11 +6012,13 @@ int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, int blocks= -1; if (keycache->key_cache_inited) { + pthread_mutex_lock(&keycache->op_lock); if ((uint) keycache->param_partitions != keycache->partitions && use_mem) - blocks= repartition_key_cache(keycache, - key_cache_block_size, use_mem, - division_limit, age_threshold, - (uint) keycache->param_partitions); + blocks= repartition_key_cache_internal(keycache, + key_cache_block_size, use_mem, + division_limit, age_threshold, + (uint) keycache->param_partitions, + 0); else { blocks= keycache->interface_funcs->resize(keycache->keycache_cb, @@ -5976,6 +6037,7 @@ int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, ((SIMPLE_KEY_CACHE_CB *)(keycache->keycache_cb))->key_cache_mem_size; keycache->can_be_used= (blocks >= 0); + pthread_mutex_unlock(&keycache->op_lock); } return blocks; } @@ -6009,33 +6071,37 @@ void change_key_cache_param(KEY_CACHE *keycache, uint division_limit, { if (keycache->key_cache_inited) { - + pthread_mutex_lock(&keycache->op_lock); keycache->interface_funcs->change_param(keycache->keycache_cb, division_limit, - age_threshold); + age_threshold); + pthread_mutex_unlock(&keycache->op_lock); } } /* - Destroy a key cache + Destroy a key cache : internal SYNOPSIS - end_key_cache() + end_key_cache_internal() keycache pointer to the key cache to be destroyed cleanup <=> complete free + use_op_lock if TRUE use keycache->op_lock, otherwise - ignore it DESCRIPTION - The function frees the memory allocated for the cache blocks and - auxiliary structures used by the key cache keycache. If the value - of the parameter cleanup is TRUE then all resources used by the key - cache are to be freed. + The function performs the actions required from end_key_cache(). + It has an additional parameter: use_op_lock. When the parameter + is TRUE than the function destroys keycache->op_lock if cleanup is true. + Otherwise the action with the lock is omitted. RETURN VALUE none */ -void end_key_cache(KEY_CACHE *keycache, my_bool cleanup) +static +void end_key_cache_internal(KEY_CACHE *keycache, my_bool cleanup, + my_bool use_op_lock) { if (keycache->key_cache_inited) { @@ -6047,6 +6113,12 @@ void end_key_cache(KEY_CACHE *keycache, my_bool cleanup) my_free(keycache->keycache_cb); keycache->keycache_cb= 0; } + /* + We do not destroy op_lock if we are going to reuse the same key cache. + This happens if we are called from repartition_key_cache_internal(). + */ + if (use_op_lock) + pthread_mutex_destroy(&keycache->op_lock); keycache->key_cache_inited= 0; } keycache->can_be_used= 0; @@ -6055,6 +6127,32 @@ void end_key_cache(KEY_CACHE *keycache, my_bool cleanup) /* + Destroy a key cache + + SYNOPSIS + end_key_cache() + keycache pointer to the key cache to be destroyed + cleanup <=> complete free + + DESCRIPTION + The function frees the memory allocated for the cache blocks and + auxiliary structures used by the key cache keycache. If the value + of the parameter cleanup is TRUE then all resources used by the key + cache are to be freed. + The function calls end_key_cache_internal() to perform all these actions + with the last parameter set to TRUE. + + RETURN VALUE + none +*/ + +void end_key_cache(KEY_CACHE *keycache, my_bool cleanup) +{ + end_key_cache_internal(keycache, cleanup, 1); +} + + +/* Read a block of data from a key cache into a buffer SYNOPSIS @@ -6098,7 +6196,7 @@ uchar *key_cache_read(KEY_CACHE *keycache, uchar *buff, uint length, uint block_length, int return_buffer) { - if (keycache->key_cache_inited && keycache->can_be_used) + if (keycache->can_be_used) return keycache->interface_funcs->read(keycache->keycache_cb, file, filepos, level, buff, length, @@ -6150,7 +6248,7 @@ int key_cache_insert(KEY_CACHE *keycache, File file, my_off_t filepos, int level, uchar *buff, uint length) { - if (keycache->key_cache_inited && keycache->can_be_used) + if (keycache->can_be_used) return keycache->interface_funcs->insert(keycache->keycache_cb, file, filepos, level, buff, length); @@ -6205,7 +6303,7 @@ int key_cache_write(KEY_CACHE *keycache, uchar *buff, uint length, uint block_length, int force_write) { - if (keycache->key_cache_inited && keycache->can_be_used) + if (keycache->can_be_used) return keycache->interface_funcs->write(keycache->keycache_cb, file, file_extra, filepos, level, @@ -6257,7 +6355,7 @@ int flush_key_blocks(KEY_CACHE *keycache, int file, void *file_extra, enum flush_type type) { - if (keycache->key_cache_inited) + if (keycache->can_be_used) return keycache->interface_funcs->flush(keycache->keycache_cb, file, file_extra, type); return 0; @@ -6289,13 +6387,15 @@ int reset_key_cache_counters(const char *name __attribute__((unused)), KEY_CACHE *keycache, void *unused __attribute__((unused))) { + int rc= 0; if (keycache->key_cache_inited) { - - return keycache->interface_funcs->reset_counters(name, - keycache->keycache_cb); + pthread_mutex_lock(&keycache->op_lock); + rc= keycache->interface_funcs->reset_counters(name, + keycache->keycache_cb); + pthread_mutex_unlock(&keycache->op_lock); } - return 0; + return rc; } @@ -6325,11 +6425,63 @@ void get_key_cache_statistics(KEY_CACHE *keycache, uint partition_no, { if (keycache->key_cache_inited) { + pthread_mutex_lock(&keycache->op_lock); keycache->interface_funcs->get_stats(keycache->keycache_cb, partition_no, key_cache_stats); + pthread_mutex_unlock(&keycache->op_lock); } } + +/* + Repartition a key cache : internal + + SYNOPSIS + repartition_key_cache_internal() + keycache pointer to the key cache to be repartitioned + key_cache_block_size size of blocks to keep cached data + use_mem total memory to use for the new key cache + division_limit new division limit (if not zero) + age_threshold new age threshold (if not zero) + partitions new number of partitions in the key cache + use_op_lock if TRUE use keycache->op_lock, otherwise - ignore it + + DESCRIPTION + The function performs the actions required from repartition_key_cache(). + It has an additional parameter: use_op_lock. When the parameter + is TRUE then the function locks keycache->op_lock at start and + unlocks it before the return. Otherwise the actions with the lock + are omitted. + + RETURN VALUE + number of blocks in the key cache, if successful, + 0 - otherwise. +*/ + +static +int repartition_key_cache_internal(KEY_CACHE *keycache, + uint key_cache_block_size, size_t use_mem, + uint division_limit, uint age_threshold, + uint partitions, my_bool use_op_lock) +{ + uint blocks= -1; + if (keycache->key_cache_inited) + { + if (use_op_lock) + pthread_mutex_lock(&keycache->op_lock); + keycache->interface_funcs->resize(keycache->keycache_cb, + key_cache_block_size, 0, + division_limit, age_threshold); + end_key_cache_internal(keycache, 1, 0); + blocks= init_key_cache_internal(keycache, key_cache_block_size, use_mem, + division_limit, age_threshold, partitions, + 0); + if (use_op_lock) + pthread_mutex_unlock(&keycache->op_lock); + } + return blocks; +} + /* Repartition a key cache @@ -6353,16 +6505,14 @@ void get_key_cache_statistics(KEY_CACHE *keycache, uint partition_no, that are used for midpoint insertion strategy. The parameter use_mem specifies the total amount of memory to be allocated for the new key cache buffers and for all auxiliary structures. + The function calls repartition_key_cache_internal() to perform all these + actions with the last parameter set to TRUE. RETURN VALUE number of blocks in the key cache, if successful, 0 - otherwise. NOTES - The function does not block the calls and executions of other functions - from the key cache interface. However it assumes that the calls of - resize_key_cache itself are serialized. - Currently the function is called when the value of the variable key_cache_partitions is being reset for the key cache keycache. */ @@ -6371,16 +6521,8 @@ int repartition_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, size_t use_mem, uint division_limit, uint age_threshold, uint partitions) { - uint blocks= -1; - if (keycache->key_cache_inited) - { - keycache->interface_funcs->resize(keycache->keycache_cb, - key_cache_block_size, 0, - division_limit, age_threshold); - end_key_cache(keycache, 1); - blocks= init_key_cache(keycache, key_cache_block_size, use_mem, - division_limit, age_threshold, partitions); - } - return blocks; + return repartition_key_cache_internal(keycache, key_cache_block_size, use_mem, + division_limit, age_threshold, + partitions, 1); } |