summaryrefslogtreecommitdiff
path: root/mysys/mf_keycache.c
diff options
context:
space:
mode:
authorunknown <monty@mashka.mysql.fi>2003-11-18 13:47:27 +0200
committerunknown <monty@mashka.mysql.fi>2003-11-18 13:47:27 +0200
commite72124c4ccad5b390b84562389175dcd7355769c (patch)
tree0a23d90c946c5f05a8c160fc7c6ef3f05505fc79 /mysys/mf_keycache.c
parent61e682b8adafdfae736327fee4ea0263e1a0bd37 (diff)
downloadmariadb-git-e72124c4ccad5b390b84562389175dcd7355769c.tar.gz
CLIENT_MULTI_QUERIES -> CLIENT_MULTI_STATEMENTS
New multi-key-cache handling. This was needed becasue the old one didn't work reliable with MERGE tables. ALTER TABLE table_name ... CHARACTER SET ... now changes all char/varchar/text columns to the given character set (One must use ALTER TABLE ... DEFAULT CHARACTER SET ... to change the default character set) Fixed that have_compress is detected properly (fixes problems with func_compress.test on platforms without zlib) New syntax for CACHE INDEX ('keys' is optional if no index name is given and one mentions the key cache name only ones) Removed compiler warnings Added mysql_set_server_option() to allow clients like PHP to easaily set/reset the multi-statement flag. BUILD/compile-pentium-valgrind-max: Add test of isam client/mysql.cc: CLIENT_MULTI_QUERIES -> CLIENT_MULTI_STATEMENTS include/my_base.h: Remove HA_EXTRA_SET_KEY_CACHE include/my_no_pthread.h: Add defines to ignore rw-locks when running without threads include/my_sys.h: Added function for multi-key-caches include/myisam.h: Added function to handle multi-key-caches include/mysql.h: Added mysql_set_server_option include/mysql_com.h: CLIENT_MULTI_QUERIES -> CLIENT_MULTI_STATEMENTS Added enum_mysql_set_option include/mysqld_error.h: Added error message for unknown key cache innobase/srv/srv0start.c: Removed warning that is confused for MySQL users libmysql/libmysql.c: Added mysql_set_server_option() libmysql/libmysql.def: Added mysql_set_server_option() myisam/ft_nlq_search.c: Removed compiler warning myisam/ft_static.c: Removed compiler warning and fixed wrong return value myisam/mi_check.c: Clean up multi-key-cache usage myisam/mi_checksum.c: Removed not used variable myisam/mi_close.c: keycache -> key_cache myisam/mi_delete_all.c: keycache -> key_cache myisam/mi_extra.c: keycache -> key_cache Removed HA_EXTRA_SET_KEY_CACHE myisam/mi_keycache.c: Changed logic so that it's MyISAM that is responsible for assign tables to different key caches instead of the upper level myisam/mi_locking.c: Don't change key cache on unlock (must be done before) myisam/mi_open.c: Fetch key cache to use from multi_key_cache_search() myisam/mi_page.c: keycache -> key_cache myisam/mi_panic.c: keycache -> key_cache myisam/mi_preload.c: keycache -> key_cache myisam/mi_test1.c: Use KEY_CACHE_BLOCK_SIZE myisam/mi_test2.c: Always test resize_key_cache() myisam/mi_test3.c: Use KEY_CACHE_BLOCK_SIZE instead of 512 myisam/myisamchk.c: update for multiple key caches myisam/myisamdef.h: Remove reg_keycache Add unique_name_length for storing length of unique_file_name myisam/myisamlog.c: Change how end_key_cache() is called mysql-test/mysql-test-run.sh: Fixed web link Added name of failed test to abort row. mysql-test/r/alter_table.result: Testing of ALTER TABLE ... [DEFAULT] CHARACTER SET mysql-test/r/case.result: Update result for DEFAULT CHARSET... mysql-test/r/cast.result: Update result for DEFAULT CHARSET... mysql-test/r/create.result: Update result for DEFAULT CHARSET... mysql-test/r/ctype_collate.result: Update result for DEFAULT CHARSET... mysql-test/r/ctype_latin1_de.result: Update result for DEFAULT CHARSET... mysql-test/r/ctype_many.result: Update result for DEFAULT CHARSET... mysql-test/r/ctype_mb.result: Update result for DEFAULT CHARSET... mysql-test/r/ctype_recoding.result: Update result for DEFAULT CHARSET... mysql-test/r/ctype_ucs.result: Update result for DEFAULT CHARSET... mysql-test/r/derived.result: Use STRAIGHT_JOIN to make join order predictable mysql-test/r/fulltext.result: Update result for DEFAULT CHARSET... mysql-test/r/func_str.result: Update result for DEFAULT CHARSET... mysql-test/r/func_system.result: Update result for DEFAULT CHARSET... mysql-test/r/gis-rtree.result: Update result for DEFAULT CHARSET... mysql-test/r/innodb.result: Update result for DEFAULT CHARSET... mysql-test/r/key_cache.result: Update test for new key cache syntax. Added more tests mysql-test/r/merge.result: Update result for DEFAULT CHARSET... mysql-test/r/preload.result: New syntax mysql-test/r/show_check.result: Update result for DEFAULT CHARSET... mysql-test/r/sql_mode.result: Update result for DEFAULT CHARSET... mysql-test/r/subselect.result: Update result for DEFAULT CHARSET... mysql-test/r/type_blob.result: Update result for DEFAULT CHARSET... mysql-test/r/type_enum.result: Update result for DEFAULT CHARSET... mysql-test/r/type_nchar.result: Update result for DEFAULT CHARSET... mysql-test/r/type_set.result: Update result for DEFAULT CHARSET... mysql-test/r/union.result: Use STRAIGHT_JOIN to make join order predictable mysql-test/t/alter_table.test: Testing of ALTER TABLE ... [DEFAULT] CHARACTER SET mysql-test/t/ctype_many.test: Update result for DEFAULT CHARSET... mysql-test/t/derived.test: Use STRAIGHT_JOIN to make join order predictable mysql-test/t/isam.test: Use disable warnings for test loop mysql-test/t/join.test: Update test now when we only support 61 tables in join mysql-test/t/key_cache.test: Update test for new key cache syntax. Added more tests mysql-test/t/preload.test: Update for new syntax mysql-test/t/union.test: Use STRAIGHT_JOIN to make join order predictable mysys/Makefile.am: Added mf_keycaches.c mysys/hash.c: TRUE -> 1 mysys/mf_keycache.c: Removed compiler warnings Striped end space Fixed indentation and improved function comments TRUE -> 1 Changed parameters to end_key_cache() to make it easer to use Fixed bug when using key blocks size > 1024 bytes (First part of index file could be overwritten with wrong data) Split function flush_key_blocks into two functions to not get mutex used twice when called from flush_all_key_blocks() mysys/my_bitmap.c: More debugging Safe bitmap_free() Fixed indentation mysys/my_getopt.c: Ensure that we initialize option->value, option->max_value and value from GET_ASK_ADDR mysys/my_thr_init.c: Remove not used mutex THR_LOCK_keycache mysys/typelib.c: Fixed function comments sql-common/client.c: CLIENT_MULTI_QUERIES -> CLIENT_MULTI_STATEMENTS Fixed the multi_result flag is set also on SELECT;s sql/ha_myisam.cc: Fixed multiple key_cache handling (Now done on MyISAM level) sql/ha_myisammrg.cc: Fixed multiple key_cache handling (Now done on MyISAM level) sql/handler.cc: New multi key cache handling sql/handler.h: New multi key cache handling Added support for default character set sql/item.h: Added function cleanup() (Needed for prepared statements / cursors) sql/item_cmpfunc.h: Added cleanup function sql/item_func.cc: Indentation cleanup sql/mysql_priv.h: New multi-key-cache functions Removed LOCK_assign sql/mysqld.cc: New multi-key-cache handling Fixed that variable have_compress is set correctly sql/protocol.cc: SELECT didn't work reliable in multi-statements sql/set_var.cc: Support for new key cache variables sql/set_var.h: Support for new key cache variables sql/share/czech/errmsg.txt: New error messages sql/share/danish/errmsg.txt: New error messages sql/share/dutch/errmsg.txt: New error messages sql/share/english/errmsg.txt: New error messages sql/share/estonian/errmsg.txt: New error messages sql/share/french/errmsg.txt: New error messages sql/share/german/errmsg.txt: New error messages sql/share/greek/errmsg.txt: New error messages sql/share/hungarian/errmsg.txt: New error messages sql/share/italian/errmsg.txt: New error messages sql/share/japanese/errmsg.txt: New error messages sql/share/korean/errmsg.txt: New error messages sql/share/norwegian-ny/errmsg.txt: New error messages sql/share/norwegian/errmsg.txt: New error messages sql/share/polish/errmsg.txt: New error messages sql/share/portuguese/errmsg.txt: New error messages sql/share/romanian/errmsg.txt: New error messages sql/share/russian/errmsg.txt: New error messages sql/share/serbian/errmsg.txt: New error messages sql/share/slovak/errmsg.txt: New error messages sql/share/spanish/errmsg.txt: New error messages sql/share/swedish/errmsg.txt: New error messages sql/share/ukrainian/errmsg.txt: New error messages sql/sql_base.cc: Removed all key_cache handling (this is now done on MyISAM level) Change table_charset -> default_table_charset sql/sql_db.cc: table_charset -> default_table_charset sql/sql_delete.cc: table_charset -> default_table_charset sql/sql_lex.cc: CLIENT_MULTI_QUERIES -> CLIENT_MULTI_STATEMENTS sql/sql_lex.h: New option to store a name and length sql/sql_parse.cc: Support for mysql_set_server_option() Reset "default" keycache status variables in 'FLUSH STATUS' (Need to be improved later) sql/sql_show.cc: Add DEFAULT before CHARSET (for table character sets) Fetch key cache variables from 'sql_key_cache' sql/sql_table.cc: table_charset -> default_table_charset New multi-key-cache handling sql/sql_test.cc: Write information from all key caches sql/sql_yacc.yy: Changed syntax for CACHE INDEX ... Force user to use DEFAULT before database/table level character sets sql/structs.h: Added SHOW_KEY_CACHE_LONG (to get values from sql_key_cache) sql/table.cc: table_charset -> default_table_charset sql/table.h: New key cache handling (this is now done in mysys/mf_keycaches.c) sql/unireg.h: A
Diffstat (limited to 'mysys/mf_keycache.c')
-rw-r--r--mysys/mf_keycache.c349
1 files changed, 195 insertions, 154 deletions
diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c
index 2f5a704234d..280b69b18bf 100644
--- a/mysys/mf_keycache.c
+++ b/mysys/mf_keycache.c
@@ -142,7 +142,7 @@ typedef struct st_block_link
KEY_CACHE_VAR dflt_key_cache_var=
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
KEY_CACHE_HANDLE *dflt_keycache= &dflt_key_cache_var.cache;
@@ -168,7 +168,7 @@ typedef struct st_key_cache
ulong warm_blocks; /* number of blocks in warm sub-chain */
#if defined(KEYCACHE_DEBUG)
long blocks_available; /* number of blocks available in the LRU chain */
-#endif
+#endif
HASH_LINK **hash_root; /* arr. of entries into hash table buckets */
HASH_LINK *hash_link_root; /* memory for hash table links */
HASH_LINK *free_hash_list; /* list of free hash links */
@@ -184,7 +184,7 @@ typedef struct st_key_cache
} KEY_CACHE;
static int flush_all_key_blocks(KEY_CACHE_HANDLE keycache);
-static void test_key_cache(KEY_CACHE *keycache,
+static void test_key_cache(KEY_CACHE *keycache,
const char *where, my_bool lock);
#define KEYCACHE_HASH(f, pos) \
@@ -284,7 +284,7 @@ static uint next_power(uint value)
SYNOPSIS
init_ky_cache()
pkeycache in/out pointer to the key cache handle
- key_cache_block_size size of blocks to keep cached data
+ key_cache_block_size size of blocks to keep cached data
use_mem total memory to use for the key cache
env ref to other parameters of the key cache, if any
@@ -299,7 +299,7 @@ static uint next_power(uint value)
handle for a key cache with new blocks.
It's assumed that no two threads call this function simultaneously
referring to the same key cache handle.
-
+
*/
int init_key_cache(KEY_CACHE_HANDLE *pkeycache, uint key_cache_block_size,
@@ -308,14 +308,14 @@ int init_key_cache(KEY_CACHE_HANDLE *pkeycache, uint key_cache_block_size,
uint blocks, hash_links, length;
int error;
KEY_CACHE *keycache;
-
DBUG_ENTER("init_key_cache");
+ DBUG_ASSERT(key_cache_block_size >= 512);
if (!(keycache= (KEY_CACHE *) *pkeycache) &&
!(keycache= (KEY_CACHE *) my_malloc(sizeof(KEY_CACHE),
MYF(MY_ZEROFILL))))
DBUG_RETURN(0);
-
+
keycache->env= env;
KEYCACHE_DEBUG_OPEN;
@@ -332,30 +332,30 @@ int init_key_cache(KEY_CACHE_HANDLE *pkeycache, uint key_cache_block_size,
if (! keycache->key_cache_inited)
{
- keycache->key_cache_inited= TRUE;
+ keycache->key_cache_inited= 1;
keycache->disk_blocks= -1;
pthread_mutex_init(&keycache->cache_lock, MY_MUTEX_INIT_FAST);
keycache->key_cache_shift= my_bit_log2(key_cache_block_size);
keycache->key_cache_mem_size= use_mem;
keycache->key_cache_block_size= key_cache_block_size;
DBUG_PRINT("info", ("key_cache_block_size: %u",
- key_cache_block_size));
+ key_cache_block_size));
}
-
- /*
- These are safety deallocations: actually we always call the
- function after having called end_key_cache that deallocates
- these memory itself.
- */
+
+ /*
+ These are safety deallocations: actually we always call the
+ function after having called end_key_cache that deallocates
+ these memory itself.
+ */
if (keycache->block_mem)
- my_free_lock((gptr) keycache->block_mem, MYF(0));
+ my_free_lock((gptr) keycache->block_mem, MYF(0));
keycache->block_mem= NULL;
if (keycache->block_root)
- my_free((gptr) keycache->block_root, MYF(0));
+ my_free((gptr) keycache->block_root, MYF(0));
keycache->block_root= NULL;
blocks= (uint) (use_mem / (sizeof(BLOCK_LINK) + 2 * sizeof(HASH_LINK) +
- sizeof(HASH_LINK*) * 5/4 + key_cache_block_size));
+ sizeof(HASH_LINK*) * 5/4 + key_cache_block_size));
/* It doesn't make sense to have too few blocks (less than 8) */
if (blocks >= 8 && keycache->disk_blocks < 0)
{
@@ -371,18 +371,18 @@ int init_key_cache(KEY_CACHE_HANDLE *pkeycache, uint key_cache_block_size,
#endif
while ((length= (ALIGN_SIZE(blocks * sizeof(BLOCK_LINK)) +
ALIGN_SIZE(hash_links * sizeof(HASH_LINK)) +
- ALIGN_SIZE(sizeof(HASH_LINK*) *
+ ALIGN_SIZE(sizeof(HASH_LINK*) *
keycache->hash_entries))) +
((ulong) blocks << keycache->key_cache_shift) > use_mem)
blocks--;
/* Allocate memory for cache page buffers */
- if ((keycache->block_mem=
- my_malloc_lock((ulong) blocks * keycache->key_cache_block_size,
- MYF(0))))
+ if ((keycache->block_mem=
+ my_malloc_lock((ulong) blocks * keycache->key_cache_block_size,
+ MYF(0))))
{
/*
- Allocate memory for blocks, hash_links and hash entries;
- For each block 2 hash links are allocated
+ Allocate memory for blocks, hash_links and hash entries;
+ For each block 2 hash links are allocated
*/
if ((keycache->block_root= (BLOCK_LINK*) my_malloc((uint) length,
MYF(0))))
@@ -402,13 +402,13 @@ int init_key_cache(KEY_CACHE_HANDLE *pkeycache, uint key_cache_block_size,
ALIGN_SIZE(blocks*sizeof(BLOCK_LINK)));
keycache->hash_link_root= (HASH_LINK*) ((char*) keycache->hash_root +
ALIGN_SIZE((sizeof(HASH_LINK*) *
- keycache->hash_entries)));
+ keycache->hash_entries)));
bzero((byte*) keycache->block_root,
- keycache->disk_blocks * sizeof(BLOCK_LINK));
+ keycache->disk_blocks * sizeof(BLOCK_LINK));
bzero((byte*) keycache->hash_root,
keycache->hash_entries * sizeof(HASH_LINK*));
bzero((byte*) keycache->hash_link_root,
- keycache->hash_links * sizeof(HASH_LINK));
+ keycache->hash_links * sizeof(HASH_LINK));
keycache->hash_links_used= 0;
keycache->free_hash_list= NULL;
keycache->blocks_used= keycache->blocks_changed= 0;
@@ -422,21 +422,21 @@ int init_key_cache(KEY_CACHE_HANDLE *pkeycache, uint key_cache_block_size,
keycache->used_ins= NULL;
keycache->keycache_time= 0;
keycache->warm_blocks= 0;
- keycache->min_warm_blocks= env && env->division_limit ?
- blocks * env->division_limit / 100 + 1 :
- blocks;
- keycache->age_threshold= env && env->age_threshold ?
- blocks * env->age_threshold / 100 :
- blocks;
+ keycache->min_warm_blocks= (env && env->division_limit ?
+ blocks * env->division_limit / 100 + 1 :
+ blocks);
+ keycache->age_threshold= (env && env->age_threshold ?
+ blocks * env->age_threshold / 100 :
+ blocks);
keycache->waiting_for_hash_link.last_thread= NULL;
keycache->waiting_for_block.last_thread= NULL;
DBUG_PRINT("exit",
- ("disk_blocks: %d block_root: %lx hash_entries: %d hash_root: %lx \
+ ("disk_blocks: %d block_root: %lx hash_entries: %d hash_root: %lx \
hash_links: %d hash_link_root %lx",
- keycache->disk_blocks, keycache->block_root,
- keycache->hash_entries, keycache->hash_root,
- keycache->hash_links, keycache->hash_link_root));
+ keycache->disk_blocks, keycache->block_root,
+ keycache->hash_entries, keycache->hash_root,
+ keycache->hash_links, keycache->hash_link_root));
}
bzero((gptr) keycache->changed_blocks,
sizeof(keycache->changed_blocks[0]) * CHANGED_BLOCKS_HASH);
@@ -445,7 +445,8 @@ int init_key_cache(KEY_CACHE_HANDLE *pkeycache, uint key_cache_block_size,
if (env)
env->blocks= keycache->disk_blocks > 0 ? keycache->disk_blocks : 0;
- *pkeycache= keycache;
+ *pkeycache= keycache;
+ DBUG_PRINT("exit", ("key_cache: %lx", keycache));
DBUG_RETURN((int) blocks);
err:
@@ -473,8 +474,8 @@ err:
SYNOPSIS
resize_key_cache()
- pkeycache in/out pointer to the key cache handle
- key_cache_block_size size of blocks to keep cached data
+ pkeycache in/out pointer to the key cache handle
+ key_cache_block_size size of blocks to keep cached data
use_mem total memory to use for the new key cache
RETURN VALUE
@@ -485,8 +486,8 @@ err:
The function first compares the memory size and the block size parameters
with the corresponding parameters of the key cache referred by
*pkeycache. If they differ the function free the the memory allocated
- for the old key cache blocks by calling the end_key_cache function
- and then rebuilds the key cache with new blocks by calling init_key_cache.
+ for the old key cache blocks by calling the end_key_cache function
+ and then rebuilds the key cache with new blocks by calling init_key_cache.
*/
int resize_key_cache(KEY_CACHE_HANDLE *pkeycache, uint key_cache_block_size,
@@ -494,6 +495,7 @@ int resize_key_cache(KEY_CACHE_HANDLE *pkeycache, uint key_cache_block_size,
{
int blocks;
KEY_CACHE *keycache= *pkeycache;
+ DBUG_ENTER("resize_key_cache");
if (key_cache_block_size == keycache->key_cache_block_size &&
use_mem == keycache->key_cache_mem_size)
@@ -507,20 +509,20 @@ int resize_key_cache(KEY_CACHE_HANDLE *pkeycache, uint key_cache_block_size,
return 0;
}
keycache_pthread_mutex_unlock(&keycache->cache_lock);
- end_key_cache(pkeycache, 0);
+ end_key_cache(keycache, 0);
/* the following will work even if memory is 0 */
- blocks=init_key_cache(pkeycache, key_cache_block_size, use_mem,
- keycache->env);
+ blocks= init_key_cache(pkeycache, key_cache_block_size, use_mem,
+ keycache->env);
return blocks;
}
/*
- Change the key cache parameters
+ Change the key cache parameters
SYNOPSIS
change_key_cache_param()
- keycache the key cache handle
+ keycache the key cache handle
RETURN VALUE
none
@@ -537,14 +539,15 @@ void change_key_cache_param(KEY_CACHE_HANDLE keycache)
KEY_CACHE_VAR *env= keycache->env;
DBUG_ENTER("change_key_cache_param");
- if (!env)
- return;
- if (env->division_limit)
- keycache->min_warm_blocks= keycache->disk_blocks *
- env->division_limit / 100 + 1;
- if (env->age_threshold)
- keycache->age_threshold= keycache->disk_blocks *
- env->age_threshold / 100;
+ if (env)
+ {
+ if (env->division_limit)
+ keycache->min_warm_blocks= (keycache->disk_blocks *
+ env->division_limit / 100 + 1);
+ if (env->age_threshold)
+ keycache->age_threshold= (keycache->disk_blocks *
+ env->age_threshold / 100);
+ }
DBUG_VOID_RETURN;
}
@@ -554,7 +557,7 @@ void change_key_cache_param(KEY_CACHE_HANDLE keycache)
SYNOPSIS
end_key_cache()
- pkeycache in/out pointer to the key cache handle
+ pkeycache in/out pointer to the key cache handle
cleanup <-> the key cache data structure is freed as well
RETURN VALUE
@@ -562,15 +565,18 @@ void change_key_cache_param(KEY_CACHE_HANDLE keycache)
NOTES.
If the cleanup parameter is TRUE the data structure with all associated
- elements are freed completely and NULL is assigned to *pkeycache.
- Otherwise only memory used by the key cache blocks is freed.
+ elements are freed completely
+ Otherwise only memory used by the key cache blocks is freed.
*/
-void end_key_cache(KEY_CACHE_HANDLE *pkeycache, my_bool cleanup)
+void end_key_cache(KEY_CACHE_HANDLE keycache, my_bool cleanup)
{
- KEY_CACHE *keycache= *pkeycache;
- KEY_CACHE_VAR *env= keycache->env;
+ KEY_CACHE_VAR *env;;
DBUG_ENTER("end_key_cache");
+ DBUG_PRINT("enter", ("key_cache: %lx", keycache));
+
+ if (!keycache)
+ DBUG_VOID_RETURN;
if (keycache->disk_blocks > 0)
{
if (keycache->block_mem)
@@ -584,18 +590,19 @@ void end_key_cache(KEY_CACHE_HANDLE *pkeycache, my_bool cleanup)
}
KEYCACHE_DEBUG_CLOSE;
keycache->key_cache_inited= 0;
- if (env)
+ if ((env= keycache->env))
+ {
DBUG_PRINT("status",
("used: %d changed: %d w_requests: %ld \
writes: %ld r_requests: %ld reads: %ld",
- env->blocks_used, env->blocks_changed,
+ env->blocks_used, env->blocks_changed,
env->cache_w_requests, env->cache_write,
env->cache_r_requests, env->cache_read));
+ }
if (cleanup)
{
pthread_mutex_destroy(&keycache->cache_lock);
- my_free((gptr) *pkeycache, MYF(0));
- *pkeycache= NULL;
+ my_free((gptr) keycache, MYF(0));
}
DBUG_VOID_RETURN;
} /* end_key_cache */
@@ -606,8 +613,8 @@ void end_key_cache(KEY_CACHE_HANDLE *pkeycache, my_bool cleanup)
SYNOPSIS
link_into_queue()
- wqueue pointer to the queue structure
- thread pointer to the thread to be added to the queue
+ wqueue pointer to the queue structure
+ thread pointer to the thread to be added to the queue
RETURN VALUE
none
@@ -643,8 +650,8 @@ static inline void link_into_queue(KEYCACHE_WQUEUE *wqueue,
SYNOPSIS
unlink_from_queue()
- wqueue pointer to the queue structure
- thread pointer to the thread to be removed from the queue
+ wqueue pointer to the queue structure
+ thread pointer to the thread to be removed from the queue
RETURN VALUE
none
@@ -677,8 +684,8 @@ static inline void unlink_from_queue(KEYCACHE_WQUEUE *wqueue,
SYNOPSIS
add_to_queue()
- wqueue pointer to the queue structure
- thread pointer to the thread to be added to the queue
+ wqueue pointer to the queue structure
+ thread pointer to the thread to be added to the queue
RETURN VALUE
none
@@ -709,8 +716,8 @@ static inline void add_to_queue(KEYCACHE_WQUEUE *wqueue,
SYNOPSIS
realease_queue()
- wqueue pointer to the queue structure
- thread pointer to the thread to be added to the queue
+ wqueue pointer to the queue structure
+ thread pointer to the thread to be added to the queue
RETURN VALUE
none
@@ -718,7 +725,7 @@ static inline void add_to_queue(KEYCACHE_WQUEUE *wqueue,
NOTES.
See notes for add_to_queue
When removed from the queue each thread is signaled via condition
- variable thread->suspend.
+ variable thread->suspend.
*/
static void release_queue(KEYCACHE_WQUEUE *wqueue)
@@ -809,7 +816,7 @@ static inline void link_to_changed_list(KEY_CACHE *keycache,
SYNOPSIS
link_block()
- keycache pointer to a key cache data structure
+ keycache pointer to a key cache data structure
block pointer to the block to link to the LRU chain
hot <-> to link the block into the hot subchain
at_end <-> to link the block at the end of the subchain
@@ -818,11 +825,11 @@ static inline void link_to_changed_list(KEY_CACHE *keycache,
none
NOTES.
- The LRU chain is represented by a curcular list of block structures.
- The list is double-linked of the type (**prev,*next) type.
- The LRU chain is divided into two parts - hot and warm.
+ The LRU chain is represented by a curcular list of block structures.
+ The list is double-linked of the type (**prev,*next) type.
+ The LRU chain is divided into two parts - hot and warm.
There are two pointers to access the last blocks of these two
- parts. The beginning of the warm part follows right after the
+ parts. The beginning of the warm part follows right after the
end of the hot part.
Only blocks of the warm part can be used for replacement.
The first block from the beginning of this subchain is always
@@ -836,12 +843,12 @@ static inline void link_to_changed_list(KEY_CACHE *keycache,
| +------+ W A R M +------+ |
+----| beg |---->...----| end |----+
+------+ +------+ins
- first for eviction
+ first for eviction
*/
static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot,
my_bool at_end)
-{
+{
BLOCK_LINK *ins;
BLOCK_LINK **pins;
@@ -881,7 +888,7 @@ static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot,
return;
}
pins= hot ? &keycache->used_ins : &keycache->used_last;
- ins= *pins;
+ ins= *pins;
if (ins)
{
ins->next_used->prev_used= &block->next_used;
@@ -915,7 +922,7 @@ static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot,
SYNOPSIS
unlink_block()
- keycache pointer to a key cache data structure
+ keycache pointer to a key cache data structure
block pointer to the block to unlink from the LRU chain
RETURN VALUE
@@ -938,7 +945,7 @@ static void unlink_block(KEY_CACHE *keycache, BLOCK_LINK *block)
keycache->used_last= STRUCT_PTR(BLOCK_LINK, next_used, block->prev_used);
if (keycache->used_ins == block)
keycache->used_ins=STRUCT_PTR(BLOCK_LINK, next_used, block->prev_used);
- }
+ }
block->next_used= NULL;
KEYCACHE_THREAD_TRACE("unlink_block");
@@ -972,27 +979,27 @@ static void reg_requests(KEY_CACHE *keycache, BLOCK_LINK *block, int count)
SYNOPSIS
unreg_block()
- keycache pointer to a key cache data structure
+ keycache pointer to a key cache data structure
block pointer to the block to link to the LRU chain
at_end <-> to link the block at the end of the LRU chain
RETURN VALUE
none
- NOTES.
+ NOTES.
Every linking to the LRU chain decrements by one a special block
counter (if it's positive). If the at_end parameter is TRUE the block is
added either at the end of warm sub-chain or at the end of hot sub-chain.
- It is added to the hot subchain if its counter is zero and number of
- blocks in warm sub-chain is not less than some low limit (determined by
+ It is added to the hot subchain if its counter is zero and number of
+ blocks in warm sub-chain is not less than some low limit (determined by
the division_limit parameter). Otherwise the block is added to the warm
sub-chain. If the at_end parameter is FALSE the block is always added
- at beginning of the warm sub-chain.
+ at beginning of the warm sub-chain.
Thus a warm block can be promoted to the hot sub-chain when its counter
becomes zero for the first time.
At the same time the block at the very beginning of the hot subchain
might be moved to the beginning of the warm subchain if it stays untouched
- for a too long time (this time is determined by parameter age_threshold).
+ for a too long time (this time is determined by parameter age_threshold).
*/
static inline void unreg_request(KEY_CACHE *keycache,
@@ -1123,7 +1130,7 @@ static void unlink_hash(KEY_CACHE *keycache, HASH_LINK *hash_link)
Get the hash link for a page
*/
-static HASH_LINK *get_hash_link(KEY_CACHE *keycache,
+static HASH_LINK *get_hash_link(KEY_CACHE *keycache,
int file, my_off_t filepos)
{
reg1 HASH_LINK *hash_link, **start;
@@ -1206,16 +1213,16 @@ restart:
Get a block for the file page requested by a keycache read/write operation;
If the page is not in the cache return a free block, if there is none
return the lru block after saving its buffer if the page is dirty.
-
+
SYNOPSIS
find_key_block()
- keycache pointer to a key cache data structure
+ keycache pointer to a key cache data structure
file handler for the file to read page from
filepos position of the page in the file
init_hits_left how initialize the block counter for the page
wrmode <-> get for writing
- page_st out {PAGE_READ,PAGE_TO_BE_READ,PAGE_WAIT_TO_BE_READ}
+ page_st out {PAGE_READ,PAGE_TO_BE_READ,PAGE_WAIT_TO_BE_READ}
RETURN VALUE
Pointer to the found block if successful, 0 - otherwise
@@ -1227,15 +1234,15 @@ restart:
If not, the function first chooses a block for this page. If there is
no not used blocks in the key cache yet, the function takes the block
at the very beginning of the warm sub-chain. It saves the page in that
- block if it's dirty before returning the pointer to it.
+ block if it's dirty before returning the pointer to it.
The function returns in the page_st parameter the following values:
PAGE_READ - if page already in the block,
PAGE_TO_BE_READ - if it is to be read yet by the current thread
- WAIT_TO_BE_READ - if it is to be read by another thread
+ WAIT_TO_BE_READ - if it is to be read by another thread
If an error occurs THE BLOCK_ERROR bit is set in the block status.
It might happen that there are no blocks in LRU chain (in warm part) -
all blocks are unlinked for some read/write operations. Then the function
- waits until first of this operations links any block back.
+ waits until first of this operations links any block back.
*/
static BLOCK_LINK *find_key_block(KEY_CACHE *keycache,
@@ -1388,9 +1395,11 @@ restart:
The call is thread safe because only the current
thread might change the block->hash_link value
*/
- error=my_pwrite(block->hash_link->file, block->buffer,
- block->length, block->hash_link->diskpos,
- MYF(MY_NABP | MY_WAIT_IF_FULL));
+ error= my_pwrite(block->hash_link->file,
+ block->buffer+block->offset,
+ block->length - block->offset,
+ block->hash_link->diskpos+ block->offset,
+ MYF(MY_NABP | MY_WAIT_IF_FULL));
keycache_pthread_mutex_lock(&keycache->cache_lock);
if (keycache->env)
keycache->env->cache_write++;
@@ -1465,12 +1474,12 @@ restart:
SYNOPSIS
read_block()
- 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
- read_length size of data to be read
- min_length at least so much data must be read
- primary <-> the current thread will read the data
-
+ read_length size of data to be read
+ min_length at least so much data must be read
+ primary <-> the current thread will read the data
+
RETURN VALUE
None
@@ -1551,15 +1560,15 @@ static void read_block(KEY_CACHE *keycache,
SYNOPSIS
key_cache_read()
- keycache pointer to a key cache data structure
+ keycache pointer to a key cache data structure
file handler for the file for the block of data to be read
filepos position of the block of data in the file
level determines the weight of the data
- buff buffer to where the data must be placed
+ buff buffer to where the data must be placed
length length of the buffer
- block_length length of the block in the key cache buffer
- return_buffer return pointer to the key cache buffer with the data
-
+ block_length length of the block in the key cache buffer
+ return_buffer return pointer to the key cache buffer with the data
+
RETURN VALUE
Returns address from where the data is placed if sucessful, 0 - otherwise.
@@ -1584,7 +1593,7 @@ byte *key_cache_read(KEY_CACHE_HANDLE keycache,
DBUG_PRINT("enter", ("file %u, filepos %lu, length %u",
(uint) file, (ulong) filepos, length));
- if (keycache->disk_blocks > 0)
+ if (keycache && keycache->disk_blocks > 0)
{
/* Key cache is used */
reg1 BLOCK_LINK *block;
@@ -1613,7 +1622,7 @@ byte *key_cache_read(KEY_CACHE_HANDLE keycache,
if (block->status != BLOCK_ERROR && page_st != PAGE_READ)
{
/* The requested page is to be read into the block buffer */
- read_block(keycache, block,
+ read_block(keycache, block,
keycache->key_cache_block_size, read_length+offset,
(my_bool)(page_st == PAGE_TO_BE_READ));
}
@@ -1677,7 +1686,7 @@ byte *key_cache_read(KEY_CACHE_HANDLE keycache,
}
/* Key cache is not used */
- if (keycache->env)
+ if (keycache && keycache->env)
{
statistic_increment(keycache->env->cache_r_requests,
&keycache->cache_lock);
@@ -1696,13 +1705,13 @@ byte *key_cache_read(KEY_CACHE_HANDLE keycache,
SYNOPSIS
key_cache_insert()
- keycache pointer to a key cache data structure
+ keycache pointer to a key cache data structure
file handler for the file to insert data from
filepos position of the block of data in the file to insert
level determines the weight of the data
buff buffer to read data from
length length of the data in the buffer
-
+
RETURN VALUE
0 if a success, 1 - otherwise.
*/
@@ -1777,20 +1786,20 @@ int key_cache_insert(KEY_CACHE_HANDLE keycache,
/*
- Write a buffer into a cached file.
-
+ Write a buffer into a cached file.
+
SYNOPSIS
key_cache_write()
- keycache pointer to a key cache data structure
+ keycache pointer to a key cache data structure
file handler for the file to write data to
filepos position in the file to write data to
level determines the weight of the data
- buff buffer with the data
+ buff buffer with the data
length length of the buffer
dont_write if is 0 then all dirty pages involved in writing
- should have been flushed from key cache
-
+ should have been flushed from key cache
+
RETURN VALUE
0 if a success, 1 - otherwise.
@@ -1798,7 +1807,7 @@ int key_cache_insert(KEY_CACHE_HANDLE keycache,
The function copies the data of size length from buff into buffers
for key cache blocks that are assigned to contain the portion of
the file starting with position filepos.
- It ensures that this data is flushed to the file if dont_write is FALSE.
+ It ensures that this data is flushed to the file if dont_write is FALSE.
Filepos must be a multiple of 'block_length', but it doesn't
have to be a multiple of key_cache_block_size;
*/
@@ -1811,15 +1820,16 @@ int key_cache_write(KEY_CACHE_HANDLE keycache,
{
reg1 BLOCK_LINK *block;
int error=0;
-
DBUG_ENTER("key_cache_write");
- DBUG_PRINT("enter", ("file %u, filepos %lu, length %u block_length %u",
- (uint) file, (ulong) filepos, length, block_length));
+ DBUG_PRINT("enter",
+ ("file %u filepos %lu length %u block_length %u key_block_length: %u",
+ (uint) file, (ulong) filepos, length, block_length,
+ keycache ? keycache->key_cache_block_size : 0));
if (!dont_write)
{
/* Force writing from buff into disk */
- if (keycache->env)
+ if (keycache && keycache->env)
statistic_increment(keycache->env->cache_write,
&keycache->cache_lock);
if (my_pwrite(file, buff, length, filepos, MYF(MY_NABP | MY_WAIT_IF_FULL)))
@@ -1831,7 +1841,7 @@ int key_cache_write(KEY_CACHE_HANDLE keycache,
test_key_cache(keycache, "start of key_cache_write", 1););
#endif
- if (keycache->disk_blocks > 0)
+ if (keycache && keycache->disk_blocks > 0)
{
/* Key cache is used */
uint read_length;
@@ -1872,7 +1882,7 @@ int key_cache_write(KEY_CACHE_HANDLE keycache,
if (! (block->status & BLOCK_ERROR))
{
if (!(read_length & 511))
- bmove512(block->buffer+offset, buff, read_length);
+ bmove512(block->buffer+offset, buff, read_length);
else
memcpy(block->buffer+offset, buff, (size_t) read_length);
}
@@ -1903,14 +1913,14 @@ int key_cache_write(KEY_CACHE_HANDLE keycache,
/* Key cache is not used */
if (dont_write)
{
- if (keycache->env)
+ if (keycache && keycache->env)
{
statistic_increment(keycache->env->cache_w_requests,
- &keycache->cache_lock);
- statistic_increment(keycache->env->cache_write,
+ &keycache->cache_lock);
+ statistic_increment(keycache->env->cache_write,
&keycache->cache_lock);
}
- if (my_pwrite(file, (byte*) buff, length, filepos,
+ if (my_pwrite(file, (byte*) buff, length, filepos,
MYF(MY_NABP | MY_WAIT_IF_FULL)))
error=1;
}
@@ -1991,8 +2001,10 @@ static int flush_cached_blocks(KEY_CACHE *keycache,
KEYCACHE_DBUG_PRINT("flush_cached_blocks",
("block %u to be flushed", BLOCK_NUMBER(block)));
keycache_pthread_mutex_unlock(&keycache->cache_lock);
- error= my_pwrite(file, block->buffer+block->offset, block->length,
- block->hash_link->diskpos,
+ error= my_pwrite(file,
+ block->buffer+block->offset,
+ block->length - block->offset,
+ block->hash_link->diskpos+ block->offset,
MYF(MY_NABP | MY_WAIT_IF_FULL));
keycache_pthread_mutex_lock(&keycache->cache_lock);
if (keycache->env)
@@ -2024,27 +2036,30 @@ static int flush_cached_blocks(KEY_CACHE *keycache,
/*
- Flush all blocks for a file to disk
-
- SYNOPSIS
+ flush all key blocks for a file to disk, but don't do any mutex locks
flush_key_blocks()
- keycache pointer to a key cache data structure
+ keycache pointer to a key cache data structure
file handler for the file to flush to
flush_type type of the flush
-
- RETURN VALUE
- 0 if a success, 1 - otherwise.
- */
-int flush_key_blocks(KEY_CACHE_HANDLE keycache,
- File file, enum flush_type type)
+ NOTES
+ This function doesn't do any mutex locks because it needs to be called both
+ from flush_key_blocks and flush_all_key_blocks (the later one does the
+ mutex lock in the resize_key_cache() function).
+
+ RETURN
+ 0 ok
+ 1 error
+*/
+
+static int flush_key_blocks_int(KEY_CACHE_HANDLE keycache,
+ File file, enum flush_type type)
{
KEY_CACHE_VAR *env;
BLOCK_LINK *cache_buff[FLUSH_CACHE],**cache;
int last_errno= 0;
-
- DBUG_ENTER("flush_key_blocks");
+ DBUG_ENTER("flush_key_blocks_int");
DBUG_PRINT("enter",("file: %d blocks_used: %d blocks_changed: %d",
file, keycache->blocks_used, keycache->blocks_changed));
@@ -2053,8 +2068,6 @@ int flush_key_blocks(KEY_CACHE_HANDLE keycache,
test_key_cache(keycache, "start of flush_key_blocks", 0););
#endif
- keycache_pthread_mutex_lock(&keycache->cache_lock);
-
cache= cache_buff;
if (keycache->disk_blocks > 0 &&
(!my_disable_flush_key_blocks || type != FLUSH_KEEP))
@@ -2132,7 +2145,7 @@ restart:
This happens only if there is not enough
memory for the big block
*/
- if ((error= flush_cached_blocks(keycache, file, cache,
+ if ((error= flush_cached_blocks(keycache, file, cache,
end,type)))
last_errno=error;
/*
@@ -2214,12 +2227,8 @@ restart:
}
}
- keycache_pthread_mutex_unlock(&keycache->cache_lock);
-
if (type == FLUSH_REMOVE && (env= keycache->env) && (env->action))
- {
(*env->action)((void *) env);
- }
#ifndef DBUG_OFF
DBUG_EXECUTE("check_keycache",
@@ -2234,6 +2243,37 @@ restart:
/*
+ Flush all blocks for a file to disk
+
+ SYNOPSIS
+
+ flush_key_blocks()
+ keycache pointer to a key cache data structure
+ file handler for the file to flush to
+ flush_type type of the flush
+
+ RETURN
+ 0 ok
+ 1 error
+ */
+
+int flush_key_blocks(KEY_CACHE_HANDLE key_cache,
+ File file, enum flush_type type)
+{
+ int res;
+ DBUG_ENTER("flush_key_blocks");
+ DBUG_PRINT("enter", ("key_cache: %lx", key_cache));
+
+ if (!key_cache || !key_cache->disk_blocks)
+ DBUG_RETURN(0);
+ keycache_pthread_mutex_lock(&key_cache->cache_lock);
+ res= flush_key_blocks_int(key_cache, file, type);
+ keycache_pthread_mutex_unlock(&key_cache->cache_lock);
+ DBUG_RETURN(res);
+}
+
+
+/*
Flush all blocks in the key cache to disk
*/
@@ -2253,7 +2293,8 @@ static int flush_all_key_blocks(KEY_CACHE *keycache)
cnt++;
KEYCACHE_DBUG_ASSERT(cnt <= keycache->blocks_used);
#endif
- if (flush_key_blocks(keycache, block->hash_link->file, FLUSH_RELEASE))
+ if (flush_key_blocks_int(keycache, block->hash_link->file,
+ FLUSH_RELEASE))
return 1;
break;
}