summaryrefslogtreecommitdiff
path: root/mysys
diff options
context:
space:
mode:
authorunknown <monty@mysql.com>2003-11-20 22:06:25 +0200
committerunknown <monty@mysql.com>2003-11-20 22:06:25 +0200
commit35da5e43fbd3653c39358669365e2c329e1e555c (patch)
tree685b3a2a60fc00121d338cb0b5f84b4cd028bfe1 /mysys
parentf25cbdd9141004e6e9f0a7313d763c1cc1de36ec (diff)
downloadmariadb-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.c5
-rw-r--r--mysys/mf_keycache.c452
-rw-r--r--mysys/mf_keycaches.c15
-rw-r--r--mysys/thr_mutex.c23
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)