Commit 1103abda authored by Daniel Black's avatar Daniel Black Committed by Sergey Vojtovich

keycache: restructure functions that are controlled by arguements

finish_resize_simple_key_cache removed argument acquire for acquiring
locks.

resize_simple_key_cache enforces assertion that the cache is inited.

read_block was really two functions, primary and secondary so separated
as such. Make the callers of read_block explictly use the required function.
Signed-off-by: default avatarDaniel Black <daniel@linux.vnet.ibm.com>
parent 0750b5f8
...@@ -749,7 +749,6 @@ int prepare_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, ...@@ -749,7 +749,6 @@ int prepare_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
SYNOPSIS SYNOPSIS
finish_resize_simple_key_cache() finish_resize_simple_key_cache()
keycache pointer to the control block of a simple key cache keycache pointer to the control block of a simple key cache
acquire_lock <=> acquire the key cache lock at start
DESCRIPTION DESCRIPTION
This function performs finalizing actions for the operation of This function performs finalizing actions for the operation of
...@@ -757,8 +756,6 @@ int prepare_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, ...@@ -757,8 +756,6 @@ int prepare_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
keycache as a pointer to the control block structure of the type keycache as a pointer to the control block structure of the type
SIMPLE_KEY_CACHE_CB for this key cache. The function sets the flag SIMPLE_KEY_CACHE_CB for this key cache. The function sets the flag
in_resize in this structure to FALSE. in_resize in this structure to FALSE.
The parameter acquire_lock says whether the key cache lock must be
acquired at the start of the function.
RETURN VALUE RETURN VALUE
none none
...@@ -770,14 +767,10 @@ int prepare_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, ...@@ -770,14 +767,10 @@ int prepare_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
*/ */
static static
void finish_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, void finish_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache)
my_bool acquire_lock)
{ {
DBUG_ENTER("finish_resize_simple_key_cache"); DBUG_ENTER("finish_resize_simple_key_cache");
if (acquire_lock)
keycache_pthread_mutex_lock(&keycache->cache_lock);
mysql_mutex_assert_owner(&keycache->cache_lock); mysql_mutex_assert_owner(&keycache->cache_lock);
/* /*
...@@ -849,8 +842,7 @@ int resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, ...@@ -849,8 +842,7 @@ int resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
int blocks= 0; int blocks= 0;
DBUG_ENTER("resize_simple_key_cache"); DBUG_ENTER("resize_simple_key_cache");
if (!keycache->key_cache_inited) DBUG_ASSERT(keycache->key_cache_inited);
DBUG_RETURN(blocks);
/* /*
Note that the cache_lock mutex and the resize_queue are left untouched. Note that the cache_lock mutex and the resize_queue are left untouched.
...@@ -866,7 +858,7 @@ int resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, ...@@ -866,7 +858,7 @@ int resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
changed_blocks_hash_size); changed_blocks_hash_size);
finish: finish:
finish_resize_simple_key_cache(keycache, 0); finish_resize_simple_key_cache(keycache);
DBUG_RETURN(blocks); DBUG_RETURN(blocks);
} }
...@@ -2611,12 +2603,11 @@ static BLOCK_LINK *find_key_block(SIMPLE_KEY_CACHE_CB *keycache, ...@@ -2611,12 +2603,11 @@ static BLOCK_LINK *find_key_block(SIMPLE_KEY_CACHE_CB *keycache,
SYNOPSIS SYNOPSIS
read_block() read_block_{primary|secondary}()
keycache pointer to a key cache data structure keycache pointer to a key cache data structure
block block to which buffer the data is to be read block block to which buffer the data is to be read
read_length size of data to be read read_length size of data to be read
min_length at least so much data must be read min_length at least so much data must be read
primary <-> the current thread will read the data
RETURN VALUE RETURN VALUE
None None
...@@ -2630,17 +2621,16 @@ static BLOCK_LINK *find_key_block(SIMPLE_KEY_CACHE_CB *keycache, ...@@ -2630,17 +2621,16 @@ static BLOCK_LINK *find_key_block(SIMPLE_KEY_CACHE_CB *keycache,
portion is less than read_length, but not less than min_length. portion is less than read_length, but not less than min_length.
*/ */
static void read_block(SIMPLE_KEY_CACHE_CB *keycache, static void read_block_primary(SIMPLE_KEY_CACHE_CB *keycache,
BLOCK_LINK *block, uint read_length, BLOCK_LINK *block, uint read_length,
uint min_length, my_bool primary) uint min_length)
{ {
size_t got_length; size_t got_length;
/* On entry cache_lock is locked */ /* On entry cache_lock is locked */
KEYCACHE_THREAD_TRACE("read_block"); KEYCACHE_THREAD_TRACE("read_block_primary");
if (primary)
{
/* /*
This code is executed only by threads that submitted primary This code is executed only by threads that submitted primary
requests. Until block->status contains BLOCK_READ, all other requests. Until block->status contains BLOCK_READ, all other
...@@ -2654,7 +2644,7 @@ static void read_block(SIMPLE_KEY_CACHE_CB *keycache, ...@@ -2654,7 +2644,7 @@ static void read_block(SIMPLE_KEY_CACHE_CB *keycache,
fail_block(block)); fail_block(block));
DBUG_ASSERT((block->requests > 0) || fail_block(block)); DBUG_ASSERT((block->requests > 0) || fail_block(block));
KEYCACHE_DBUG_PRINT("read_block", KEYCACHE_DBUG_PRINT("read_block_primary",
("page to be read by primary request")); ("page to be read by primary request"));
keycache->global_cache_read++; keycache->global_cache_read++;
...@@ -2692,13 +2682,20 @@ static void read_block(SIMPLE_KEY_CACHE_CB *keycache, ...@@ -2692,13 +2682,20 @@ static void read_block(SIMPLE_KEY_CACHE_CB *keycache,
keycache->key_cache_block_size. keycache->key_cache_block_size.
*/ */
} }
KEYCACHE_DBUG_PRINT("read_block", KEYCACHE_DBUG_PRINT("read_block_primary",
("primary request: new page in cache")); ("primary request: new page in cache"));
/* Signal that all pending requests for this page now can be processed */ /* Signal that all pending requests for this page now can be processed */
release_whole_queue(&block->wqueue[COND_FOR_REQUESTED]); release_whole_queue(&block->wqueue[COND_FOR_REQUESTED]);
}
else DBUG_ASSERT(keycache->can_be_used);
{ }
static void read_block_secondary(SIMPLE_KEY_CACHE_CB *keycache,
BLOCK_LINK *block)
{
KEYCACHE_THREAD_TRACE("read_block_secondary");
/* /*
This code is executed only by threads that submitted secondary This code is executed only by threads that submitted secondary
requests. At this point it could happen that the cache block is requests. At this point it could happen that the cache block is
...@@ -2708,12 +2705,16 @@ static void read_block(SIMPLE_KEY_CACHE_CB *keycache, ...@@ -2708,12 +2705,16 @@ static void read_block(SIMPLE_KEY_CACHE_CB *keycache,
for the requested file block nor the file and position. So we have for the requested file block nor the file and position. So we have
to assert this in the caller. to assert this in the caller.
*/ */
KEYCACHE_DBUG_PRINT("read_block", KEYCACHE_DBUG_PRINT("read_block_secondary",
("secondary request waiting for new page to be read")); ("secondary request waiting for new page to be read"));
wait_on_queue(&block->wqueue[COND_FOR_REQUESTED], &keycache->cache_lock); wait_on_queue(&block->wqueue[COND_FOR_REQUESTED], &keycache->cache_lock);
KEYCACHE_DBUG_PRINT("read_block",
KEYCACHE_DBUG_PRINT("read_block_secondary",
("secondary request: new page in cache")); ("secondary request: new page in cache"));
}
DBUG_ASSERT(keycache->can_be_used);
DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE));
} }
...@@ -2858,22 +2859,24 @@ uchar *simple_key_cache_read(SIMPLE_KEY_CACHE_CB *keycache, ...@@ -2858,22 +2859,24 @@ uchar *simple_key_cache_read(SIMPLE_KEY_CACHE_CB *keycache,
} }
if (!(block->status & BLOCK_ERROR)) if (!(block->status & BLOCK_ERROR))
{ {
if (page_st != PAGE_READ) if (page_st == PAGE_TO_BE_READ)
{
MYSQL_KEYCACHE_READ_MISS();
read_block_primary(keycache, block,
keycache->key_cache_block_size, read_length+offset);
}
else if (page_st == PAGE_WAIT_TO_BE_READ)
{ {
MYSQL_KEYCACHE_READ_MISS(); MYSQL_KEYCACHE_READ_MISS();
/* The requested page is to be read into the block buffer */ /* The requested page is to be read into the block buffer */
read_block(keycache, block, read_block_secondary(keycache, block);
keycache->key_cache_block_size, read_length+offset,
(my_bool)(page_st == PAGE_TO_BE_READ));
/* /*
A secondary request must now have the block assigned to the A secondary request must now have the block assigned to the
requested file block. It does not hurt to check it for requested file block.
primary requests too.
*/ */
DBUG_ASSERT(keycache->can_be_used);
DBUG_ASSERT(block->hash_link->file == file); DBUG_ASSERT(block->hash_link->file == file);
DBUG_ASSERT(block->hash_link->diskpos == filepos); DBUG_ASSERT(block->hash_link->diskpos == filepos);
DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE));
} }
else if (block->length < read_length + offset) else if (block->length < read_length + offset)
{ {
...@@ -3077,23 +3080,30 @@ int simple_key_cache_insert(SIMPLE_KEY_CACHE_CB *keycache, ...@@ -3077,23 +3080,30 @@ int simple_key_cache_insert(SIMPLE_KEY_CACHE_CB *keycache,
} }
if (!(block->status & BLOCK_ERROR)) if (!(block->status & BLOCK_ERROR))
{ {
if ((page_st == PAGE_WAIT_TO_BE_READ) || if (page_st == PAGE_WAIT_TO_BE_READ)
((page_st == PAGE_TO_BE_READ) &&
(offset || (read_length < keycache->key_cache_block_size))))
{ {
/* /*
Either
this is a secondary request for a block to be read into the this is a secondary request for a block to be read into the
cache. The block is in eviction. It is not yet assigned to cache. The block is in eviction. It is not yet assigned to
the requested file block (It does not point to the right the requested file block (It does not point to the right
hash_link). So we cannot call remove_reader() on the block. hash_link). So we cannot call remove_reader() on the block.
And we cannot access the hash_link directly here. We need to And we cannot access the hash_link directly here. We need to
wait until the assignment is complete. read_block() executes wait until the assignment is complete. read_block_secondary()
the correct wait when called with primary == FALSE. executes the correct wait.
*/
Or read_block_secondary(keycache, block);
/*
A secondary request must now have the block assigned to the
requested file block.
*/
DBUG_ASSERT(block->hash_link->file == file);
DBUG_ASSERT(block->hash_link->diskpos == filepos);
}
else if (page_st == PAGE_TO_BE_READ &&
(offset || (read_length < keycache->key_cache_block_size)))
{
/*
this is a primary request for a block to be read into the this is a primary request for a block to be read into the
cache and the supplied data does not fill the whole block. cache and the supplied data does not fill the whole block.
...@@ -3108,17 +3118,8 @@ int simple_key_cache_insert(SIMPLE_KEY_CACHE_CB *keycache, ...@@ -3108,17 +3118,8 @@ int simple_key_cache_insert(SIMPLE_KEY_CACHE_CB *keycache,
Though reading again what the caller did read already is an Though reading again what the caller did read already is an
expensive operation, we need to do this for correctness. expensive operation, we need to do this for correctness.
*/ */
read_block(keycache, block, keycache->key_cache_block_size, read_block_primary(keycache, block, keycache->key_cache_block_size,
read_length + offset, (page_st == PAGE_TO_BE_READ)); read_length + offset);
/*
A secondary request must now have the block assigned to the
requested file block. It does not hurt to check it for
primary requests too.
*/
DBUG_ASSERT(keycache->can_be_used);
DBUG_ASSERT(block->hash_link->file == file);
DBUG_ASSERT(block->hash_link->diskpos == filepos);
DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE));
} }
else if (page_st == PAGE_TO_BE_READ) else if (page_st == PAGE_TO_BE_READ)
{ {
...@@ -3413,19 +3414,17 @@ int simple_key_cache_write(SIMPLE_KEY_CACHE_CB *keycache, ...@@ -3413,19 +3414,17 @@ int simple_key_cache_write(SIMPLE_KEY_CACHE_CB *keycache,
reading the file block. If the read completes after us, it reading the file block. If the read completes after us, it
overwrites our new contents with the old contents. So we have to overwrites our new contents with the old contents. So we have to
wait for the other thread to complete the read of this block. wait for the other thread to complete the read of this block.
read_block() takes care for the wait. read_block_primary|secondary() takes care for the wait.
*/ */
if (!(block->status & BLOCK_ERROR) && if (!(block->status & BLOCK_ERROR))
((page_st == PAGE_TO_BE_READ &&
(offset || read_length < keycache->key_cache_block_size)) ||
(page_st == PAGE_WAIT_TO_BE_READ)))
{ {
read_block(keycache, block, if (page_st == PAGE_TO_BE_READ &&
(offset || read_length < keycache->key_cache_block_size))
{
read_block_primary(keycache, block,
offset + read_length >= keycache->key_cache_block_size? offset + read_length >= keycache->key_cache_block_size?
offset : keycache->key_cache_block_size, offset : keycache->key_cache_block_size,
offset, (page_st == PAGE_TO_BE_READ)); offset);
DBUG_ASSERT(keycache->can_be_used);
DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE));
/* /*
Prevent block from flushing and from being selected for to be Prevent block from flushing and from being selected for to be
freed. This must be set when we release the cache_lock. freed. This must be set when we release the cache_lock.
...@@ -3433,6 +3432,12 @@ int simple_key_cache_write(SIMPLE_KEY_CACHE_CB *keycache, ...@@ -3433,6 +3432,12 @@ int simple_key_cache_write(SIMPLE_KEY_CACHE_CB *keycache,
*/ */
block->status|= BLOCK_FOR_UPDATE; block->status|= BLOCK_FOR_UPDATE;
} }
else if (page_st == PAGE_WAIT_TO_BE_READ)
{
read_block_secondary(keycache, block);
block->status|= BLOCK_FOR_UPDATE;
}
}
/* /*
The block should always be assigned to the requested file block The block should always be assigned to the requested file block
here. It need not be BLOCK_READ when overwriting the whole block. here. It need not be BLOCK_READ when overwriting the whole block.
...@@ -5279,7 +5284,8 @@ int resize_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache, ...@@ -5279,7 +5284,8 @@ int resize_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache,
{ {
for (i= 0; i < partitions; i++) for (i= 0; i < partitions; i++)
{ {
finish_resize_simple_key_cache(keycache->partition_array[i], 1); keycache_pthread_mutex_lock(&keycache->partition_array[i]->cache_lock);
finish_resize_simple_key_cache(keycache->partition_array[i]);
} }
} }
DBUG_RETURN(blocks); DBUG_RETURN(blocks);
......
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