diff options
author | unknown <monty@mysql.com> | 2003-11-20 22:06:25 +0200 |
---|---|---|
committer | unknown <monty@mysql.com> | 2003-11-20 22:06:25 +0200 |
commit | 35da5e43fbd3653c39358669365e2c329e1e555c (patch) | |
tree | 685b3a2a60fc00121d338cb0b5f84b4cd028bfe1 /mysys | |
parent | f25cbdd9141004e6e9f0a7313d763c1cc1de36ec (diff) | |
download | mariadb-git-35da5e43fbd3653c39358669365e2c329e1e555c.tar.gz |
Merge key cache structures to one
Fixed compiler warnings (IRIX C compiler and VC++)
VC++Files/client/mysqlclient.dsp:
Add missing file to project
VC++Files/libmysql/libmysql.dsp:
Add missing file to project
VC++Files/myisam/myisam.dsp:
Add missing file to project
VC++Files/mysys/mysys.dsp:
Add missing file to project
heap/hp_test1.c:
Fixed wrong call to heap_rkey()
heap/hp_test2.c:
Fixed wrong call to heap_rkey()
include/hash.h:
Move not used (internal) struct to hash.c
include/my_pthread.h:
Made some structs 'const char*' to avoid warnings
include/my_sys.h:
Moved key cache structs and functions to keycache.h
include/myisam.h:
Merge key cache structures to one
include/mysql.h:
Remove STDCALL from internal functions
include/sql_common.h:
Remove STDCALL from internal functions
include/violite.h:
Fixed compiler warning
isam/_locking.c:
Merge key cache structures to one
isam/_page.c:
Merge key cache structures to one
isam/close.c:
Merge key cache structures to one
isam/extra.c:
Merge key cache structures to one
isam/isamchk.c:
Merge key cache structures to one
isam/isamdef.h:
Merge key cache structures to one
isam/isamlog.c:
Merge key cache structures to one
isam/panic.c:
Merge key cache structures to one
isam/test2.c:
Merge key cache structures to one
isam/test3.c:
Merge key cache structures to one
libmysql/client_settings.h:
Remove STDCALL from internal functions
libmysql/libmysql.c:
Remove STDCALL from internal functions
myisam/ft_boolean_search.c:
Fixed compiler warning
myisam/ft_dump.c:
Fixed compiler warnings (%qx is not portable)
myisam/ft_update.c:
Fixed compiler warnings
myisam/mi_check.c:
Merge key cache structures to one
myisam/mi_close.c:
Merge key cache structures to one
myisam/mi_delete_all.c:
Merge key cache structures to one
myisam/mi_extra.c:
Merge key cache structures to one
myisam/mi_keycache.c:
Merge key cache structures to one
myisam/mi_locking.c:
Merge key cache structures to one
myisam/mi_page.c:
Merge key cache structures to one
myisam/mi_panic.c:
Merge key cache structures to one
myisam/mi_preload.c:
Merge key cache structures to one
myisam/mi_test1.c:
Merge key cache structures to one
myisam/mi_test2.c:
Merge key cache structures to one
myisam/mi_test3.c:
Merge key cache structures to one
myisam/myisamchk.c:
Merge key cache structures to one
myisam/myisamdef.h:
Merge key cache structures to one
myisam/myisamlog.c:
Merge key cache structures to one
Removed not used option
myisam/sort.c:
Fixed compiler warnings
myisam/sp_test.c:
Fixed compiler warnings
mysql-test/r/case.result:
Updated results after fix of correct NULL detection in WHEN
mysql-test/r/date_formats.result:
Updated results after fixing date handling
mysql-test/r/symlink.result:
Updated results after adding DEFAULT CHARSET
mysql-test/t/case.test:
New test
mysql-test/t/symlink.test:
Updated error numbers
mysys/hash.c:
Made HASH_LINK struct local
mysys/mf_keycache.c:
Merge key cache structures to one
Fixed key_cache_read() and key_cache_write() to be resize-safe.
mysys/mf_keycaches.c:
Merge key cache structures to one
mysys/thr_mutex.c:
Added test if mutex is initalized
sql-common/client.c:
Remove STDCALL from internal functions
sql/derror.cc:
Added comment
sql/field.cc:
Removed not used variables
sql/ha_innodb.cc:
Fixed compiler warnings (removed not used variables)
sql/ha_myisam.cc:
Merge key cache structures to one
sql/ha_myisammrg.cc:
Removed not used variables
sql/handler.cc:
Merge key cache structures to one
sql/handler.h:
Merge key cache structures to one
sql/item.cc:
Fixed compiler warning
sql/item_cmpfunc.cc:
Remove not used variables
sql/item_func.cc:
Remove not used variables
sql/item_strfunc.cc:
Removed not used variables
sql/item_sum.cc:
Removed not used variables
Moved setting of item_thd to fix_fields()
sql/item_timefunc.cc:
Removed not used variables
sql/mysql_priv.h:
Merge key cache structures to one
sql/mysqld.cc:
Merge key cache structures to one
init_thread_environment() is not called before mysql_init_variables(). This fixes a case where a mutex was not initialized before it was used
sql/opt_sum.cc:
Remove not used variables
sql/protocol.cc:
Don't send errors after ok has been sent
sql/protocol_cursor.cc:
Remove not used variable
Simple optimization
sql/repl_failsafe.cc:
Remove not used variables
sql/set_var.cc:
Merge key cache structures to one
sql/set_var.h:
Merge key cache structures to one
sql/sql_acl.cc:
Remove not used variables
sql/sql_base.cc:
Remove not used function
sql/sql_db.cc:
Remove not used variables
sql/sql_handler.cc:
Remove not used variables
sql/sql_insert.cc:
More DBUG statements
Simple code cleanup
sql/sql_lex.cc:
Remove not used variables
sql/sql_parse.cc:
Remove not used variables
sql/sql_prepare.cc:
Remove not used variables
sql/sql_repl.cc:
Remove not used variables
sql/sql_select.cc:
Remove not used variables
sql/sql_show.cc:
Remove not used variables
sql/sql_table.cc:
Merge key cache structures to one
Removed not used variables
sql/sql_test.cc:
Merge key cache structures to one
sql/strfunc.cc:
Fixed that find_type() returns correct value for partly matched words.
(This fixed the error found by date_formats.test)
sql/time.cc:
Remove not used variables
strings/my_strtoll10.c:
Fixed compiler warnings
Diffstat (limited to 'mysys')
-rw-r--r-- | mysys/hash.c | 5 | ||||
-rw-r--r-- | mysys/mf_keycache.c | 452 | ||||
-rw-r--r-- | mysys/mf_keycaches.c | 15 | ||||
-rw-r--r-- | mysys/thr_mutex.c | 23 |
4 files changed, 222 insertions, 273 deletions
diff --git a/mysys/hash.c b/mysys/hash.c index 516fa171d7c..665e3d11e8d 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -29,6 +29,11 @@ #define HIGHFIND 4 #define HIGHUSED 8 +typedef struct st_hash_info { + uint next; /* index to next key */ + byte *data; /* data for current entry */ +} HASH_LINK; + static uint hash_mask(uint hashnr,uint buffmax,uint maxlength); static void movelink(HASH_LINK *array,uint pos,uint next_link,uint newlink); static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length); diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index a45d967665a..10ec72c220e 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -23,6 +23,7 @@ */ #include "mysys_priv.h" +#include <keycache.h> #include "my_static.h" #include <m_string.h> #include <errno.h> @@ -85,28 +86,22 @@ typedef pthread_cond_t KEYCACHE_CONDVAR; -/* info about requests in a waiting queue */ -typedef struct st_keycache_wqueue -{ - struct st_my_thread_var *last_thread; /* circular list of waiting threads */ -} KEYCACHE_WQUEUE; - /* descriptor of the page in the key cache block buffer */ -typedef struct st_keycache_page +struct st_keycache_page { int file; /* file to which the page belongs to */ my_off_t filepos; /* position of the page in the file */ -} KEYCACHE_PAGE; +}; /* element in the chain of a hash table bucket */ -typedef struct st_hash_link +struct st_hash_link { struct st_hash_link *next, **prev; /* to connect links in the same bucket */ struct st_block_link *block; /* reference to the block for the page: */ File file; /* from such a file */ my_off_t diskpos; /* with such an offset */ uint requests; /* number of requests for the page */ -} HASH_LINK; /* offset is always alighed for key_cache_block_size */ +}; /* simple states of a block */ #define BLOCK_ERROR 1 /* an error occured when performing disk i/o */ @@ -122,7 +117,7 @@ typedef struct st_hash_link #define PAGE_WAIT_TO_BE_READ 2 /* key cache block */ -typedef struct st_block_link +struct st_block_link { struct st_block_link *next_used, **prev_used; /* to connect links in the LRU chain (ring) */ @@ -138,52 +133,14 @@ typedef struct st_block_link uint hits_left; /* number of hits left until promotion */ ulonglong last_hit_time; /* timestamp of the last hit */ KEYCACHE_CONDVAR *condvar; /* condition variable for 'no readers' event */ -} 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 }; -KEY_CACHE_HANDLE *dflt_keycache= &dflt_key_cache_var.cache; -#define CHANGED_BLOCKS_HASH 128 /* must be power of 2 */ +KEY_CACHE dflt_key_cache_var; +KEY_CACHE *dflt_key_cache= &dflt_key_cache_var; + #define FLUSH_CACHE 2000 /* sort this many blocks at once */ -typedef struct st_key_cache -{ - KEY_CACHE_VAR *env; /* pointer to key cache variables (if any) */ - my_bool key_cache_inited; - uint key_cache_shift; - ulong key_cache_mem_size; /* specified size of the cache memory */ - uint key_cache_block_size; /* size of the page buffer of a cache block */ - ulong min_warm_blocks; /* min number of warm blocks; */ - ulong age_threshold; /* age threshold for hot blocks */ - ulonglong keycache_time; /* total number of block link operations */ - uint hash_entries; /* max number of entries in the hash table */ - int hash_links; /* max number of hash links */ - int hash_links_used; /* number of hash links currently used */ - int disk_blocks; /* max number of blocks in the cache */ - ulong blocks_used; /* number of currently used blocks */ - ulong blocks_changed; /* number of currently dirty blocks */ - 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 - 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 */ - BLOCK_LINK *block_root; /* memory for block links */ - byte HUGE_PTR *block_mem; /* memory for block buffers */ - BLOCK_LINK *used_last; /* ptr to the last block of the LRU chain */ - BLOCK_LINK *used_ins; /* ptr to the insertion block in LRU chain */ - pthread_mutex_t cache_lock; /* to lock access to the cache structure */ - KEYCACHE_WQUEUE waiting_for_hash_link; /* waiting for a free hash link */ - KEYCACHE_WQUEUE waiting_for_block; /* requests waiting for a free block */ - BLOCK_LINK *changed_blocks[CHANGED_BLOCKS_HASH]; /* hash for dirty file bl.*/ - BLOCK_LINK *file_blocks[CHANGED_BLOCKS_HASH]; /* hash for other file bl.*/ -} KEY_CACHE; - -static int flush_all_key_blocks(KEY_CACHE_HANDLE keycache); +static int flush_all_key_blocks(KEY_CACHE *keycache); static void test_key_cache(KEY_CACHE *keycache, const char *where, my_bool lock); @@ -202,10 +159,10 @@ static void test_key_cache(KEY_CACHE *keycache, static FILE *keycache_debug_log=NULL; static void keycache_debug_print _VARARGS((const char *fmt,...)); #define KEYCACHE_DEBUG_OPEN \ - keycache_debug_log=fopen(KEYCACHE_DEBUG_LOG, "w") + if (!keycache_debug_log) keycache_debug_log=fopen(KEYCACHE_DEBUG_LOG, "w") #define KEYCACHE_DEBUG_CLOSE \ - if (keycache_debug_log) fclose(keycache_debug_log) + if (keycache_debug_log) { fclose(keycache_debug_log); keycache_debug_log=0; } #else #define KEYCACHE_DEBUG_OPEN #define KEYCACHE_DEBUG_CLOSE @@ -283,76 +240,56 @@ 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 - use_mem total memory to use for the key cache - env ref to other parameters of the key cache, if any + keycache pointer to the key cache handle to initialize + key_cache_block_size size of blocks to keep cached data + use_mem total memory to use for the key cache + division_limit division limit (may be zero) + age_threshold age threshold (may be zero) RETURN VALUE number of blocks in the key cache, if successful, 0 - otherwise. NOTES. - If pkeycache points to an undefined handle (NULL), a new KEY_CACHE - data structure is created and a pointer to it is returned as a new - key cache handle, otherwise *pkeycache is considered as a reused - handle for a key cache with new blocks. + if keycache->key_cache_inited != 0 we assume that the key cache + is already initialized. This is for now used by myisamchk, but shouldn't + be something that a program should rely on! + 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, - ulong use_mem, KEY_CACHE_VAR *env) +int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, + ulong use_mem, uint division_limit, + uint age_threshold) { 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; if (keycache->key_cache_inited && keycache->disk_blocks > 0) { DBUG_PRINT("warning",("key cache already in use")); DBUG_RETURN(0); } - if (env && ! keycache->key_cache_inited) - { - env->cache_w_requests= env->cache_r_requests= 0; - env->cache_read= env->cache_write=0; - } + keycache->global_cache_w_requests= keycache->global_cache_r_requests= 0; + keycache->global_cache_read= keycache->global_cache_write= 0; + keycache->disk_blocks= -1; if (! keycache->key_cache_inited) { 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)); } - /* - 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)); - keycache->block_mem= NULL; - if (keycache->block_root) - my_free((gptr) keycache->block_root, MYF(0)); - keycache->block_root= NULL; + keycache->key_cache_mem_size= use_mem; + keycache->key_cache_block_size= key_cache_block_size; + keycache->key_cache_shift= my_bit_log2(key_cache_block_size); + DBUG_PRINT("info", ("key_cache_block_size: %u", + key_cache_block_size)); blocks= (uint) (use_mem / (sizeof(BLOCK_LINK) + 2 * sizeof(HASH_LINK) + sizeof(HASH_LINK*) * 5/4 + key_cache_block_size)); @@ -412,21 +349,20 @@ int init_key_cache(KEY_CACHE_HANDLE *pkeycache, uint key_cache_block_size, keycache->hash_links_used= 0; keycache->free_hash_list= NULL; keycache->blocks_used= keycache->blocks_changed= 0; - if (env) - env->blocks_used= env->blocks_changed= 0; -#if defined(KEYCACHE_DEBUG) - keycache->blocks_available=0; -#endif + + keycache->global_blocks_used= keycache->global_blocks_changed= 0; + keycache->blocks_available=0; /* For debugging */ + /* The LRU chain is empty after initialization */ keycache->used_last= NULL; 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 : + keycache->min_warm_blocks= (division_limit ? + blocks * division_limit / 100 + 1 : blocks); - keycache->age_threshold= (env && env->age_threshold ? - blocks * env->age_threshold / 100 : + keycache->age_threshold= (age_threshold ? + blocks * age_threshold / 100 : blocks); keycache->waiting_for_hash_link.last_thread= NULL; @@ -437,23 +373,19 @@ int init_key_cache(KEY_CACHE_HANDLE *pkeycache, uint key_cache_block_size, 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); + bzero((gptr) keycache->file_blocks, + sizeof(keycache->file_blocks[0]) * CHANGED_BLOCKS_HASH); } - bzero((gptr) keycache->changed_blocks, - sizeof(keycache->changed_blocks[0]) * CHANGED_BLOCKS_HASH); - bzero((gptr) keycache->file_blocks, - sizeof(keycache->file_blocks[0]) * CHANGED_BLOCKS_HASH); - - if (env) - env->blocks= keycache->disk_blocks > 0 ? keycache->disk_blocks : 0; - *pkeycache= keycache; - DBUG_PRINT("exit", ("key_cache: %lx", keycache)); + + keycache->blocks= keycache->disk_blocks > 0 ? keycache->disk_blocks : 0; DBUG_RETURN((int) blocks); err: error= my_errno; keycache->disk_blocks= 0; - if (env) - env->blocks= 0; + keycache->blocks= 0; if (keycache->block_mem) { my_free_lock((gptr) keycache->block_mem, MYF(0)); @@ -474,9 +406,11 @@ 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 - use_mem total memory to use for the new key cache + keycache in/out 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 + division_limit new division limit (if not zero) + age_threshold new age threshold (if not zero) RETURN VALUE number of blocks in the key cache, if successful, @@ -484,35 +418,38 @@ err: NOTES. 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. + with the key cache values. + + 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. */ -int resize_key_cache(KEY_CACHE_HANDLE *pkeycache, uint key_cache_block_size, - ulong use_mem) +int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, + ulong use_mem, uint division_limit, + uint age_threshold) { 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) - return keycache->disk_blocks; + if (!keycache->key_cache_inited || + (key_cache_block_size == keycache->key_cache_block_size && + use_mem == keycache->key_cache_mem_size)) + DBUG_RETURN(keycache->disk_blocks); keycache_pthread_mutex_lock(&keycache->cache_lock); if (flush_all_key_blocks(keycache)) { /* TODO: if this happens, we should write a warning in the log file ! */ keycache_pthread_mutex_unlock(&keycache->cache_lock); - return 0; + DBUG_RETURN(0); } + end_key_cache(keycache, 0); /* Don't free mutex */ + /* the following will work even if use_mem is 0 */ + blocks= init_key_cache(keycache, key_cache_block_size, use_mem, + division_limit, age_threshold); keycache_pthread_mutex_unlock(&keycache->cache_lock); - 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); return blocks; } @@ -522,7 +459,9 @@ int resize_key_cache(KEY_CACHE_HANDLE *pkeycache, uint key_cache_block_size, SYNOPSIS change_key_cache_param() - keycache the key cache handle + keycache key cache handle + division_limit new division limit (if not zero) + age_threshold new age threshold (if not zero) RETURN VALUE none @@ -530,24 +469,20 @@ int resize_key_cache(KEY_CACHE_HANDLE *pkeycache, uint key_cache_block_size, NOTES. Presently the function resets the key cache parameters concerning midpoint insertion strategy - division_limit and - age_threshold. It corresponding values are passed through - the keycache->env structure. + age_threshold. */ -void change_key_cache_param(KEY_CACHE_HANDLE keycache) +void change_key_cache_param(KEY_CACHE *keycache, uint division_limit, + uint age_threshold) { - KEY_CACHE_VAR *env= keycache->env; DBUG_ENTER("change_key_cache_param"); - 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); - } + if (division_limit) + keycache->min_warm_blocks= (keycache->disk_blocks * + division_limit / 100 + 1); + if (age_threshold) + keycache->age_threshold= (keycache->disk_blocks * + age_threshold / 100); DBUG_VOID_RETURN; } @@ -557,26 +492,21 @@ void change_key_cache_param(KEY_CACHE_HANDLE keycache) SYNOPSIS end_key_cache() - pkeycache in/out pointer to the key cache handle - cleanup <-> the key cache data structure is freed as well + keycache key cache handle + cleanup Complete free (Free also mutex for key cache) RETURN VALUE none - - NOTES. - If the cleanup parameter is TRUE the data structure with all associated - elements are freed completely - Otherwise only memory used by the key cache blocks is freed. */ -void end_key_cache(KEY_CACHE_HANDLE keycache, my_bool cleanup) +void end_key_cache(KEY_CACHE *keycache, my_bool cleanup) { - KEY_CACHE_VAR *env; DBUG_ENTER("end_key_cache"); DBUG_PRINT("enter", ("key_cache: %lx", keycache)); - if (!keycache) + if (!keycache->key_cache_inited) DBUG_VOID_RETURN; + if (keycache->disk_blocks > 0) { if (keycache->block_mem) @@ -587,22 +517,22 @@ void end_key_cache(KEY_CACHE_HANDLE keycache, my_bool cleanup) keycache->block_root= NULL; } keycache->disk_blocks= -1; + /* Reset blocks_changed to be safe if flush_all_key_blocks is called */ + keycache->blocks_changed= 0; } - KEYCACHE_DEBUG_CLOSE; - keycache->key_cache_inited= 0; - 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->cache_w_requests, env->cache_write, - env->cache_r_requests, env->cache_read)); - } + + DBUG_PRINT("status", + ("used: %d changed: %d w_requests: %ld \ +writes: %ld r_requests: %ld reads: %ld", + keycache->global_blocks_used, keycache->global_blocks_changed, + keycache->global_cache_w_requests, keycache->global_cache_write, + keycache->global_cache_r_requests, keycache->global_cache_read)); + if (cleanup) { pthread_mutex_destroy(&keycache->cache_lock); - my_free((gptr) keycache, MYF(0)); + keycache->key_cache_inited= 0; + KEYCACHE_DEBUG_CLOSE; } DBUG_VOID_RETURN; } /* end_key_cache */ @@ -786,8 +716,7 @@ static void link_to_file_list(KEY_CACHE *keycache, { block->status&= ~BLOCK_CHANGED; keycache->blocks_changed--; - if (keycache->env) - keycache->env->blocks_changed--; + keycache->global_blocks_changed--; } } @@ -805,8 +734,7 @@ static inline void link_to_changed_list(KEY_CACHE *keycache, &keycache->changed_blocks[FILE_HASH(block->hash_link->file)]); block->status|=BLOCK_CHANGED; keycache->blocks_changed++; - if (keycache->env) - keycache->env->blocks_changed++; + keycache->global_blocks_changed++; } @@ -1328,8 +1256,7 @@ restart: block->offset= keycache->key_cache_block_size; block->requests= 1; keycache->blocks_used++; - if (keycache->env) - keycache->env->blocks_used++; + keycache->global_blocks_used++; keycache->warm_blocks++; block->hits_left= init_hits_left; block->last_hit_time= 0; @@ -1401,8 +1328,7 @@ restart: 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++; + keycache->global_cache_write++; } block->status|= BLOCK_REASSIGNED; @@ -1441,8 +1367,7 @@ restart: PAGE_READ : PAGE_WAIT_TO_BE_READ; } } - if (keycache->env) - keycache->env->cache_read++; + keycache->global_cache_read++; } else { @@ -1582,42 +1507,47 @@ static void read_block(KEY_CACHE *keycache, have to be a multiple of key_cache_block_size; */ -byte *key_cache_read(KEY_CACHE_HANDLE keycache, +byte *key_cache_read(KEY_CACHE *keycache, File file, my_off_t filepos, int level, byte *buff, uint length, uint block_length __attribute__((unused)), int return_buffer __attribute__((unused))) { int error=0; + uint offset= 0; + byte *start= buff; DBUG_ENTER("key_cache_read"); DBUG_PRINT("enter", ("file %u, filepos %lu, length %u", (uint) file, (ulong) filepos, length)); - if (keycache && keycache->disk_blocks > 0) + if (keycache->disk_blocks > 0) { /* Key cache is used */ reg1 BLOCK_LINK *block; - uint offset= (uint) (filepos & (keycache->key_cache_block_size-1)); - byte *start= buff; uint read_length; uint status; int page_st; -#ifndef THREAD - if (block_length > keycache->key_cache_block_size || offset) - return_buffer=0; -#endif - /* Read data in key_cache_block_size increments */ - filepos-= offset; do { + keycache_pthread_mutex_lock(&keycache->cache_lock); + if (keycache->disk_blocks <= 0) /* Resize failed */ + { + keycache_pthread_mutex_unlock(&keycache->cache_lock); + goto no_key_cache; + } read_length= length > keycache->key_cache_block_size ? keycache->key_cache_block_size : length; KEYCACHE_DBUG_ASSERT(read_length > 0); - keycache_pthread_mutex_lock(&keycache->cache_lock); - if (keycache->env) - keycache->env->cache_r_requests++; + offset= (uint) (filepos & (keycache->key_cache_block_size-1)); + filepos-= offset; +#ifndef THREAD + if (block_length > keycache->key_cache_block_size || offset) + return_buffer=0; +#endif + + keycache->global_cache_r_requests++; block=find_key_block(keycache, file, filepos, level, 0, &page_st); if (block->status != BLOCK_ERROR && page_st != PAGE_READ) { @@ -1673,29 +1603,25 @@ byte *key_cache_read(KEY_CACHE_HANDLE keycache, DBUG_RETURN((byte *) 0); #ifndef THREAD + /* This is only true if we where able to read everything in one block */ if (return_buffer) - return (block->buffer); + return (block->buffer); #endif - buff+= read_length; filepos+= read_length; - offset= 0; } while ((length-= read_length)); DBUG_RETURN(start); } - /* Key cache is not used */ - if (keycache && keycache->env) - { - statistic_increment(keycache->env->cache_r_requests, - &keycache->cache_lock); - statistic_increment(keycache->env->cache_read, - &keycache->cache_lock); - } - if (my_pread(file, (byte*) buff, length, filepos, MYF(MY_NABP))) +no_key_cache: /* Key cache is not used */ + + /* We can't use mutex here as the key cache may not be initialized */ + keycache->global_cache_r_requests++; + keycache->global_cache_read++; + if (my_pread(file, (byte*) buff, length, filepos+offset, MYF(MY_NABP))) error= 1; - DBUG_RETURN(error? (byte*) 0 : buff); + DBUG_RETURN(error ? (byte*) 0 : start); } @@ -1703,20 +1629,23 @@ byte *key_cache_read(KEY_CACHE_HANDLE keycache, Insert a block of file data from a buffer into key cache SYNOPSIS - key_cache_insert() - 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 + 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 + + NOTES + This is used by MyISAM to move all blocks from a index file to the key + cache RETURN VALUE 0 if a success, 1 - otherwise. */ -int key_cache_insert(KEY_CACHE_HANDLE keycache, +int key_cache_insert(KEY_CACHE *keycache, File file, my_off_t filepos, int level, byte *buff, uint length) { @@ -1728,20 +1657,27 @@ int key_cache_insert(KEY_CACHE_HANDLE keycache, { /* Key cache is used */ reg1 BLOCK_LINK *block; - uint offset= (uint) (filepos & (keycache->key_cache_block_size-1)); uint read_length; int page_st; + int error; - /* Read data into key cache from buff in key_cache_block_size increments */ - filepos-= offset; do { + uint offset; + keycache_pthread_mutex_lock(&keycache->cache_lock); + if (keycache->disk_blocks <= 0) /* Resize failed */ + { + keycache_pthread_mutex_unlock(&keycache->cache_lock); + DBUG_RETURN(0); + } read_length= length > keycache->key_cache_block_size ? keycache->key_cache_block_size : length; KEYCACHE_DBUG_ASSERT(read_length > 0); - keycache_pthread_mutex_lock(&keycache->cache_lock); - if (keycache->env) - keycache->env->cache_r_requests++; + offset= (uint) (filepos & (keycache->key_cache_block_size-1)); + /* Read data into key cache from buff in key_cache_block_size incr. */ + filepos-= offset; + + keycache->global_cache_r_requests++; block= find_key_block(keycache, file, filepos, level, 0, &page_st); if (block->status != BLOCK_ERROR && page_st != PAGE_READ) { @@ -1770,14 +1706,14 @@ int key_cache_insert(KEY_CACHE_HANDLE keycache, */ unreg_request(keycache, block, 1); + error= (block->status & BLOCK_ERROR); keycache_pthread_mutex_unlock(&keycache->cache_lock); - if (block->status & BLOCK_ERROR) + if (error) DBUG_RETURN(1); buff+= read_length; filepos+= read_length; - offset=0; } while ((length-= read_length)); } @@ -1812,7 +1748,7 @@ int key_cache_insert(KEY_CACHE_HANDLE keycache, have to be a multiple of key_cache_block_size; */ -int key_cache_write(KEY_CACHE_HANDLE keycache, +int key_cache_write(KEY_CACHE *keycache, File file, my_off_t filepos, int level, byte *buff, uint length, uint block_length __attribute__((unused)), @@ -1829,9 +1765,7 @@ int key_cache_write(KEY_CACHE_HANDLE keycache, if (!dont_write) { /* Force writing from buff into disk */ - if (keycache && keycache->env) - statistic_increment(keycache->env->cache_write, - &keycache->cache_lock); + keycache->global_cache_write++; if (my_pwrite(file, buff, length, filepos, MYF(MY_NABP | MY_WAIT_IF_FULL))) DBUG_RETURN(1); } @@ -1841,23 +1775,29 @@ int key_cache_write(KEY_CACHE_HANDLE keycache, test_key_cache(keycache, "start of key_cache_write", 1);); #endif - if (keycache && keycache->disk_blocks > 0) + if (keycache->disk_blocks > 0) { /* Key cache is used */ uint read_length; - uint offset= (uint) (filepos & (keycache->key_cache_block_size-1)); int page_st; - /* Write data in key_cache_block_size increments */ - filepos-= offset; do { + uint offset; + keycache_pthread_mutex_lock(&keycache->cache_lock); + if (keycache->disk_blocks <= 0) /* Resize failed */ + { + keycache_pthread_mutex_unlock(&keycache->cache_lock); + goto no_key_cache; + } read_length= length > keycache->key_cache_block_size ? - keycache->key_cache_block_size : length; + keycache->key_cache_block_size : length; KEYCACHE_DBUG_ASSERT(read_length > 0); - keycache_pthread_mutex_lock(&keycache->cache_lock); - if (keycache->env) - keycache->env->cache_w_requests++; + offset= (uint) (filepos & (keycache->key_cache_block_size-1)); + /* Write data in key_cache_block_size increments */ + filepos-= offset; + + keycache->global_cache_w_requests++; block= find_key_block(keycache, file, filepos, level, 1, &page_st); if (block->status != BLOCK_ERROR && page_st != PAGE_READ && (offset || read_length < keycache->key_cache_block_size)) @@ -1907,25 +1847,21 @@ int key_cache_write(KEY_CACHE_HANDLE keycache, offset= 0; } while ((length-= read_length)); + goto end; } - else + +no_key_cache: + /* Key cache is not used */ + if (dont_write) { - /* Key cache is not used */ - if (dont_write) - { - if (keycache && keycache->env) - { - statistic_increment(keycache->env->cache_w_requests, - &keycache->cache_lock); - statistic_increment(keycache->env->cache_write, - &keycache->cache_lock); - } - if (my_pwrite(file, (byte*) buff, length, filepos, - MYF(MY_NABP | MY_WAIT_IF_FULL))) - error=1; - } + keycache->global_cache_w_requests++; + keycache->global_cache_write++; + if (my_pwrite(file, (byte*) buff, length, filepos, + MYF(MY_NABP | MY_WAIT_IF_FULL))) + error=1; } +end: #if !defined(DBUG_OFF) && defined(EXTRA_DEBUG) DBUG_EXECUTE("exec", test_key_cache(keycache, "end of key_cache_write", 1);); @@ -2007,8 +1943,7 @@ static int flush_cached_blocks(KEY_CACHE *keycache, 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++; + keycache->global_cache_write++; if (error) { block->status|= BLOCK_ERROR; @@ -2019,8 +1954,7 @@ static int flush_cached_blocks(KEY_CACHE *keycache, if (! (type == FLUSH_KEEP || type == FLUSH_FORCE_WRITE)) { keycache->blocks_changed--; - if (keycache->env) - keycache->env->blocks_changed--; + keycache->global_blocks_changed--; free_block(keycache, block); } else @@ -2053,10 +1987,9 @@ static int flush_cached_blocks(KEY_CACHE *keycache, 1 error */ -static int flush_key_blocks_int(KEY_CACHE_HANDLE keycache, +static int flush_key_blocks_int(KEY_CACHE *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_int"); @@ -2161,8 +2094,7 @@ restart: { /* It's a temporary file */ keycache->blocks_changed--; - if (keycache->env) - keycache->env->blocks_changed--; + keycache->global_blocks_changed--; free_block(keycache, block); } } @@ -2227,8 +2159,8 @@ restart: } } - if (type == FLUSH_REMOVE && (env= keycache->env) && (env->action)) - (*env->action)((void *) env); + if (type == FLUSH_REMOVE && keycache->action) + (*keycache->action)(keycache); #ifndef DBUG_OFF DBUG_EXECUTE("check_keycache", @@ -2257,14 +2189,14 @@ restart: 1 error */ -int flush_key_blocks(KEY_CACHE_HANDLE key_cache, +int flush_key_blocks(KEY_CACHE *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) + if (key_cache->disk_blocks <= 0) DBUG_RETURN(0); keycache_pthread_mutex_lock(&key_cache->cache_lock); res= flush_key_blocks_int(key_cache, file, type); diff --git a/mysys/mf_keycaches.c b/mysys/mf_keycaches.c index 1d770e17719..806f83dc7d8 100644 --- a/mysys/mf_keycaches.c +++ b/mysys/mf_keycaches.c @@ -23,6 +23,7 @@ */ #include "mysys_priv.h" +#include <keycache.h> #include <hash.h> #include <m_string.h> @@ -295,7 +296,7 @@ static SAFE_HASH key_cache_hash; my_bool multi_keycache_init(void) { - return safe_hash_init(&key_cache_hash, 16, (byte*) dflt_keycache); + return safe_hash_init(&key_cache_hash, 16, (byte*) dflt_key_cache); } @@ -321,11 +322,11 @@ void multi_keycache_free(void) key cache to use */ -KEY_CACHE_HANDLE *multi_key_cache_search(byte *key, uint length) +KEY_CACHE *multi_key_cache_search(byte *key, uint length) { if (!key_cache_hash.hash.records) - return dflt_keycache; - return (KEY_CACHE_HANDLE*) safe_hash_search(&key_cache_hash, key, length); + return dflt_key_cache; + return (KEY_CACHE*) safe_hash_search(&key_cache_hash, key, length); } @@ -346,14 +347,14 @@ KEY_CACHE_HANDLE *multi_key_cache_search(byte *key, uint length) my_bool multi_key_cache_set(const byte *key, uint length, - KEY_CACHE_HANDLE *key_cache) + KEY_CACHE *key_cache) { return safe_hash_set(&key_cache_hash, key, length, (byte*) key_cache); } -void multi_key_cache_change(KEY_CACHE_HANDLE *old_data, - KEY_CACHE_HANDLE *new_data) +void multi_key_cache_change(KEY_CACHE *old_data, + KEY_CACHE *new_data) { safe_hash_change(&key_cache_hash, (byte*) old_data, (byte*) new_data); } diff --git a/mysys/thr_mutex.c b/mysys/thr_mutex.c index 3abac2dc737..474334efcc0 100644 --- a/mysys/thr_mutex.c +++ b/mysys/thr_mutex.c @@ -54,12 +54,15 @@ void safe_mutex_global_init(void) int safe_mutex_init(safe_mutex_t *mp, const pthread_mutexattr_t *attr __attribute__((unused)), - const char *file __attribute__((unused)), - uint line __attribute__((unused))) + const char *file, + uint line) { bzero((char*) mp,sizeof(*mp)); pthread_mutex_init(&mp->global,MY_MUTEX_INIT_ERRCHK); pthread_mutex_init(&mp->mutex,attr); + /* Mark that mutex is initialized */ + mp->file= file; + mp->line= line; #ifdef SAFE_MUTEX_DETECT_DESTROY /* @@ -70,7 +73,7 @@ int safe_mutex_init(safe_mutex_t *mp, { struct st_safe_mutex_info_t *info =mp->info; - info->init_file= (char *) file; + info->init_file= file; info->init_line= line; info->prev= NULL; info->next= NULL; @@ -92,6 +95,13 @@ int safe_mutex_init(safe_mutex_t *mp, int safe_mutex_lock(safe_mutex_t *mp,const char *file, uint line) { int error; + if (!mp->file) + { + fprintf(stderr,"safe_mutex: Trying to lock unitialized mutex at %s, line %d", file, line); + fflush(stderr); + abort(); + } + pthread_mutex_lock(&mp->global); if (mp->count > 0 && pthread_equal(pthread_self(),mp->thread)) { @@ -117,7 +127,7 @@ line %d more than 1 time\n", file,line); abort(); } mp->thread=pthread_self(); - mp->file= (char*) file; + mp->file= file; mp->line=line; pthread_mutex_unlock(&mp->global); return error; @@ -204,7 +214,7 @@ int safe_cond_wait(pthread_cond_t *cond, safe_mutex_t *mp, const char *file, abort(); } mp->thread=pthread_self(); - mp->file= (char*) file; + mp->file= file; mp->line=line; pthread_mutex_unlock(&mp->global); return error; @@ -242,7 +252,7 @@ int safe_cond_timedwait(pthread_cond_t *cond, safe_mutex_t *mp, abort(); } mp->thread=pthread_self(); - mp->file= (char*) file; + mp->file= file; mp->line=line; pthread_mutex_unlock(&mp->global); return error; @@ -268,6 +278,7 @@ int safe_mutex_destroy(safe_mutex_t *mp, const char *file, uint line) if (pthread_mutex_destroy(&mp->mutex)) error=1; #endif + mp->file= 0; /* Mark destroyed */ #ifdef SAFE_MUTEX_DETECT_DESTROY if (mp->info) |