Commit 7c7ee4d2 authored by unknown's avatar unknown

Manual merge after improving concurrency for key cache reassignment


include/myisam.h:
  Auto merged
isam/isamchk.c:
  Auto merged
myisam/mi_check.c:
  Auto merged
myisam/mi_locking.c:
  Auto merged
myisam/mi_search.c:
  Auto merged
myisam/mi_write.c:
  Auto merged
myisam/myisamchk.c:
  Auto merged
myisam/myisamlog.c:
  Auto merged
mysql-test/r/func_group.result:
  Auto merged
mysys/mf_keycache.c:
  Auto merged
sql/ha_myisam.cc:
  Auto merged
sql/ha_myisam.h:
  Auto merged
sql/item_cmpfunc.h:
  Auto merged
sql/mysqld.cc:
  Auto merged
sql/set_var.cc:
  Auto merged
sql/sql_base.cc:
  Auto merged
sql/sql_lex.cc:
  Auto merged
sql/sql_lex.h:
  Auto merged
sql/sql_parse.cc:
  Auto merged
sql/sql_table.cc:
  Auto merged
sql/sql_test.cc:
  Auto merged
sql/sql_yacc.yy:
  Auto merged
parents cce14aab 7de7c38f
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#define HA_OPEN_DELAY_KEY_WRITE 8 /* Don't update index */ #define HA_OPEN_DELAY_KEY_WRITE 8 /* Don't update index */
#define HA_OPEN_ABORT_IF_CRASHED 16 #define HA_OPEN_ABORT_IF_CRASHED 16
#define HA_OPEN_FOR_REPAIR 32 /* open even if crashed */ #define HA_OPEN_FOR_REPAIR 32 /* open even if crashed */
#define HA_OPEN_TO_ASSIGN 64 /* Open for key cache assignment */
/* The following is parameter to ha_rkey() how to use key */ /* The following is parameter to ha_rkey() how to use key */
...@@ -124,7 +125,8 @@ enum ha_extra_function { ...@@ -124,7 +125,8 @@ enum ha_extra_function {
HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE, /* Cursor will not be used for update */ HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE, /* Cursor will not be used for update */
HA_EXTRA_PREPARE_FOR_DELETE, HA_EXTRA_PREPARE_FOR_DELETE,
HA_EXTRA_PREPARE_FOR_UPDATE, /* Remove read cache if problems */ HA_EXTRA_PREPARE_FOR_UPDATE, /* Remove read cache if problems */
HA_EXTRA_PRELOAD_BUFFER_SIZE /* Set buffer size for preloading */ HA_EXTRA_PRELOAD_BUFFER_SIZE, /* Set buffer size for preloading */
HA_EXTRA_SET_KEY_CACHE /* Set ref to assigned key cache */
}; };
/* The following is parameter to ha_panic() */ /* The following is parameter to ha_panic() */
......
...@@ -558,6 +558,9 @@ typedef SOCKET_SIZE_TYPE size_socket; ...@@ -558,6 +558,9 @@ typedef SOCKET_SIZE_TYPE size_socket;
#define RECORD_CACHE_SIZE (uint) (64*1024-MALLOC_OVERHEAD) #define RECORD_CACHE_SIZE (uint) (64*1024-MALLOC_OVERHEAD)
/* Typical key cash */ /* Typical key cash */
#define KEY_CACHE_SIZE (uint) (8*1024*1024-MALLOC_OVERHEAD) #define KEY_CACHE_SIZE (uint) (8*1024*1024-MALLOC_OVERHEAD)
/* Default size of a key cache block */
#define KEY_CACHE_BLOCK_SIZE (uint) 1024
/* Some things that this system doesn't have */ /* Some things that this system doesn't have */
......
...@@ -111,8 +111,6 @@ extern int NEAR my_errno; /* Last error in mysys */ ...@@ -111,8 +111,6 @@ extern int NEAR my_errno; /* Last error in mysys */
#define MY_WAIT_FOR_USER_TO_FIX_PANIC 60 /* in seconds */ #define MY_WAIT_FOR_USER_TO_FIX_PANIC 60 /* in seconds */
#define MY_WAIT_GIVE_USER_A_MESSAGE 10 /* Every 10 times of prev */ #define MY_WAIT_GIVE_USER_A_MESSAGE 10 /* Every 10 times of prev */
#define MIN_COMPRESS_LENGTH 50 /* Don't compress small bl. */ #define MIN_COMPRESS_LENGTH 50 /* Don't compress small bl. */
#define DEFAULT_KEYCACHE_BLOCK_SIZE 1024
#define MAX_KEYCACHE_BLOCK_SIZE 16384
/* root_alloc flags */ /* root_alloc flags */
#define MY_KEEP_PREALLOC 1 #define MY_KEEP_PREALLOC 1
...@@ -266,7 +264,8 @@ enum cache_type ...@@ -266,7 +264,8 @@ enum cache_type
enum flush_type enum flush_type
{ {
FLUSH_KEEP, FLUSH_RELEASE, FLUSH_IGNORE_CHANGED, FLUSH_FORCE_WRITE FLUSH_KEEP, FLUSH_RELEASE, FLUSH_IGNORE_CHANGED, FLUSH_FORCE_WRITE,
FLUSH_REMOVE
}; };
typedef struct st_record_cache /* Used when cacheing records */ typedef struct st_record_cache /* Used when cacheing records */
...@@ -503,14 +502,46 @@ my_off_t my_b_append_tell(IO_CACHE* info); ...@@ -503,14 +502,46 @@ my_off_t my_b_append_tell(IO_CACHE* info);
#define my_b_bytes_in_cache(info) (uint) (*(info)->current_end - \ #define my_b_bytes_in_cache(info) (uint) (*(info)->current_end - \
*(info)->current_pos) *(info)->current_pos)
/* key_cache_variables */
typedef struct st_keycache
{
ulonglong size;
} KEY_CACHE;
typedef uint32 ha_checksum; typedef uint32 ha_checksum;
/* Pointer to a key cache data structure (see the key cache module) */
typedef struct st_key_cache* KEY_CACHE_HANDLE;
/* Key cache variable structure */
/*
The structure contains the parameters of a key cache that can
be set and undated by regular set global statements.
It also contains read-only statistics parameters.
If the corresponding key cache data structure has been already
created the variable contains the key cache handle.
The variables are put into a named list called key_caches.
At present the variables are only added to this list.
*/
typedef struct st_key_cache_var
{
ulonglong buff_size; /* size the memory allocated for the cache */
ulong block_size; /* size of the blocks in the key cache */
ulong division_limit; /* min. percentage of warm blocks */
ulong age_threshold; /* determines when hot block is downgraded */
KEY_CACHE_HANDLE cache; /* handles for the current and registered */
ulong blocks_used; /* number of currently used blocks */
ulong blocks_changed; /* number of currently dirty blocks */
ulong cache_w_requests; /* number of write requests (write hits) */
ulong cache_write; /* number of writes from the cache to files */
ulong cache_r_requests; /* number of read requests (read hits) */
ulong cache_read; /* number of reads from files to the cache */
int blocks; /* max number of blocks in the cache */
struct st_key_cache_asmt *assign_list; /* list of assignments to the cache */
int assignments; /* number of not completed assignments */
void (*action)(void *); /* optional call back function */
void *extra_info; /* ptr to extra info */
} KEY_CACHE_VAR;
#define DEFAULT_KEY_CACHE_NAME "default"
extern KEY_CACHE_HANDLE *dflt_keycache;
extern KEY_CACHE_VAR dflt_key_cache_var;
#define DFLT_INIT_HITS 3
#include <my_alloc.h> #include <my_alloc.h>
/* Prototypes for mysys and my_func functions */ /* Prototypes for mysys and my_func functions */
...@@ -649,16 +680,26 @@ extern int flush_write_cache(RECORD_CACHE *info); ...@@ -649,16 +680,26 @@ extern int flush_write_cache(RECORD_CACHE *info);
extern long my_clock(void); extern long my_clock(void);
extern sig_handler sigtstp_handler(int signal_number); extern sig_handler sigtstp_handler(int signal_number);
extern void handle_recived_signals(void); extern void handle_recived_signals(void);
extern int init_key_cache(ulong use_mem); extern int init_key_cache(KEY_CACHE_HANDLE *pkeycache,
extern int resize_key_cache(ulong use_mem); uint key_cache_block_size,
extern byte *key_cache_read(File file,my_off_t filepos,byte* buff,uint length, ulong use_mem, KEY_CACHE_VAR* env);
extern int resize_key_cache(KEY_CACHE_HANDLE *pkeycache,
uint key_cache_block_size, ulong use_mem);
extern void change_key_cache_param(KEY_CACHE_HANDLE keycache);
extern byte *key_cache_read(KEY_CACHE_HANDLE keycache,
File file, my_off_t filepos, int level,
byte* buff, uint length,
uint block_length,int return_buffer); uint block_length,int return_buffer);
extern int key_cache_insert(File file, my_off_t filepos, extern int key_cache_insert(KEY_CACHE_HANDLE keycache,
File file, my_off_t filepos, int level,
byte *buff, uint length); byte *buff, uint length);
extern int key_cache_write(File file,my_off_t filepos,byte* buff,uint length, extern int key_cache_write(KEY_CACHE_HANDLE keycache,
File file, my_off_t filepos, int level,
byte* buff, uint length,
uint block_length,int force_write); uint block_length,int force_write);
extern int flush_key_blocks(int file, enum flush_type type); extern int flush_key_blocks(KEY_CACHE_HANDLE keycache,
extern void end_key_cache(void); int file, enum flush_type type);
extern void end_key_cache(KEY_CACHE_HANDLE *pkeycache,my_bool cleanup);
extern sig_handler my_set_alarm_variable(int signo); extern sig_handler my_set_alarm_variable(int signo);
extern void my_string_ptr_sort(void *base,uint items,size_s size); extern void my_string_ptr_sort(void *base,uint items,size_s size);
extern void radixsort_for_str_ptr(uchar* base[], uint number_of_elements, extern void radixsort_for_str_ptr(uchar* base[], uint number_of_elements,
......
...@@ -408,6 +408,9 @@ my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows, ulonglong key_map, ...@@ -408,6 +408,9 @@ my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows, ulonglong key_map,
int mi_init_bulk_insert(MI_INFO *info, ulong cache_size, ha_rows rows); int mi_init_bulk_insert(MI_INFO *info, ulong cache_size, ha_rows rows);
void mi_flush_bulk_insert(MI_INFO *info, uint inx); void mi_flush_bulk_insert(MI_INFO *info, uint inx);
void mi_end_bulk_insert(MI_INFO *info); void mi_end_bulk_insert(MI_INFO *info);
int mi_assign_to_keycache(MI_INFO *info, ulonglong key_map,
KEY_CACHE_VAR *key_cache,
pthread_mutex_t *assign_lock);
int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves); int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves);
#ifdef __cplusplus #ifdef __cplusplus
......
...@@ -50,7 +50,7 @@ int nisam_lock_database(N_INFO *info, int lock_type) ...@@ -50,7 +50,7 @@ int nisam_lock_database(N_INFO *info, int lock_type)
else else
count= --share->w_locks; count= --share->w_locks;
if (info->lock_type == F_WRLCK && !share->w_locks && if (info->lock_type == F_WRLCK && !share->w_locks &&
flush_key_blocks(share->kfile,FLUSH_KEEP)) flush_key_blocks(*dflt_keycache,share->kfile,FLUSH_KEEP))
error=my_errno; error=my_errno;
if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED)) if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
if (end_io_cache(&info->rec_cache)) if (end_io_cache(&info->rec_cache))
...@@ -329,7 +329,7 @@ int _nisam_test_if_changed(register N_INFO *info) ...@@ -329,7 +329,7 @@ int _nisam_test_if_changed(register N_INFO *info)
share->state.uniq != info->last_uniq) share->state.uniq != info->last_uniq)
{ /* Keyfile has changed */ { /* Keyfile has changed */
if (share->state.process != share->this_process) if (share->state.process != share->this_process)
VOID(flush_key_blocks(share->kfile,FLUSH_RELEASE)); VOID(flush_key_blocks(*dflt_keycache,share->kfile,FLUSH_RELEASE));
share->last_process=share->state.process; share->last_process=share->state.process;
info->last_loop= share->state.loop; info->last_loop= share->state.loop;
info->last_uniq= share->state.uniq; info->last_uniq= share->state.uniq;
......
...@@ -27,7 +27,8 @@ uchar *_nisam_fetch_keypage(register N_INFO *info, N_KEYDEF *keyinfo, ...@@ -27,7 +27,8 @@ uchar *_nisam_fetch_keypage(register N_INFO *info, N_KEYDEF *keyinfo,
my_off_t page, uchar *buff, int return_buffer) my_off_t page, uchar *buff, int return_buffer)
{ {
uchar *tmp; uchar *tmp;
tmp=(uchar*) key_cache_read(info->s->kfile,page,(byte*) buff, tmp=(uchar*) key_cache_read(*dflt_keycache,
info->s->kfile,page,DFLT_INIT_HITS,(byte*) buff,
(uint) keyinfo->base.block_length, (uint) keyinfo->base.block_length,
(uint) keyinfo->base.block_length, (uint) keyinfo->base.block_length,
return_buffer); return_buffer);
...@@ -83,7 +84,9 @@ int _nisam_write_keypage(register N_INFO *info, register N_KEYDEF *keyinfo, ...@@ -83,7 +84,9 @@ int _nisam_write_keypage(register N_INFO *info, register N_KEYDEF *keyinfo,
length=keyinfo->base.block_length; length=keyinfo->base.block_length;
} }
#endif #endif
return (key_cache_write(info->s->kfile,page,(byte*) buff,length, return (key_cache_write(*dflt_keycache,
info->s->kfile,page,DFLT_INIT_HITS,
(byte*) buff,length,
(uint) keyinfo->base.block_length, (uint) keyinfo->base.block_length,
(int) (info->lock_type != F_UNLCK))); (int) (info->lock_type != F_UNLCK)));
} /* nisam_write_keypage */ } /* nisam_write_keypage */
...@@ -99,7 +102,9 @@ int _nisam_dispose(register N_INFO *info, N_KEYDEF *keyinfo, my_off_t pos) ...@@ -99,7 +102,9 @@ int _nisam_dispose(register N_INFO *info, N_KEYDEF *keyinfo, my_off_t pos)
old_link=info->s->state.key_del[keynr]; old_link=info->s->state.key_del[keynr];
info->s->state.key_del[keynr]=(ulong) pos; info->s->state.key_del[keynr]=(ulong) pos;
DBUG_RETURN(key_cache_write(info->s->kfile,pos,(byte*) &old_link, DBUG_RETURN(key_cache_write(*dflt_keycache,
info->s->kfile,pos,DFLT_INIT_HITS,
(byte*) &old_link,
sizeof(long), sizeof(long),
(uint) keyinfo->base.block_length, (uint) keyinfo->base.block_length,
(int) (info->lock_type != F_UNLCK))); (int) (info->lock_type != F_UNLCK)));
...@@ -126,7 +131,8 @@ ulong _nisam_new(register N_INFO *info, N_KEYDEF *keyinfo) ...@@ -126,7 +131,8 @@ ulong _nisam_new(register N_INFO *info, N_KEYDEF *keyinfo)
} }
else else
{ {
if (!key_cache_read(info->s->kfile,pos, if (!key_cache_read(*dflt_keycache,
info->s->kfile,pos,DFLT_INIT_HITS,
(byte*) &info->s->state.key_del[keynr], (byte*) &info->s->state.key_del[keynr],
(uint) sizeof(long), (uint) sizeof(long),
(uint) keyinfo->base.block_length,0)) (uint) keyinfo->base.block_length,0))
......
...@@ -56,7 +56,8 @@ int nisam_close(register N_INFO *info) ...@@ -56,7 +56,8 @@ int nisam_close(register N_INFO *info)
if (flag) if (flag)
{ {
if (share->kfile >= 0 && flush_key_blocks(share->kfile,FLUSH_RELEASE)) if (share->kfile >= 0 &&
flush_key_blocks(*dflt_keycache,share->kfile,FLUSH_RELEASE))
error=my_errno; error=my_errno;
if (share->kfile >= 0 && my_close(share->kfile,MYF(0))) if (share->kfile >= 0 && my_close(share->kfile,MYF(0)))
error = my_errno; error = my_errno;
......
...@@ -516,7 +516,8 @@ static int nisamchk(my_string filename) ...@@ -516,7 +516,8 @@ static int nisamchk(my_string filename)
if (!rep_quick) if (!rep_quick)
{ {
if (testflag & T_EXTEND) if (testflag & T_EXTEND)
VOID(init_key_cache(use_buffers)); VOID(init_key_cache(dflt_keycache,KEY_CACHE_BLOCK_SIZE,
use_buffers,&dflt_key_cache_var));
VOID(init_io_cache(&read_cache,datafile,(uint) read_buffer_length, VOID(init_io_cache(&read_cache,datafile,(uint) read_buffer_length,
READ_CACHE,share->pack.header_length,1, READ_CACHE,share->pack.header_length,1,
MYF(MY_WME))); MYF(MY_WME)));
...@@ -1459,7 +1460,8 @@ my_string name; ...@@ -1459,7 +1460,8 @@ my_string name;
printf("Data records: %lu\n",(ulong) share->state.records); printf("Data records: %lu\n",(ulong) share->state.records);
} }
VOID(init_key_cache(use_buffers)); VOID(init_key_cache(dflt_keycache,KEY_CACHE_BLOCK_SIZE,use_buffers,
&dflt_key_cache_var));
if (init_io_cache(&read_cache,info->dfile,(uint) read_buffer_length, if (init_io_cache(&read_cache,info->dfile,(uint) read_buffer_length,
READ_CACHE,share->pack.header_length,1,MYF(MY_WME))) READ_CACHE,share->pack.header_length,1,MYF(MY_WME)))
goto err; goto err;
...@@ -1887,12 +1889,12 @@ static void lock_memory(void) ...@@ -1887,12 +1889,12 @@ static void lock_memory(void)
static int flush_blocks(file) static int flush_blocks(file)
File file; File file;
{ {
if (flush_key_blocks(file,FLUSH_RELEASE)) if (flush_key_blocks(dflt_keycache,file,FLUSH_RELEASE))
{ {
print_error("%d when trying to write bufferts",my_errno); print_error("%d when trying to write bufferts",my_errno);
return(1); return(1);
} }
end_key_cache(); end_key_cache(dflt_keycache,1);
return 0; return 0;
} /* flush_blocks */ } /* flush_blocks */
...@@ -1936,7 +1938,8 @@ int write_info; ...@@ -1936,7 +1938,8 @@ int write_info;
if (share->state.key_root[sort_key] == NI_POS_ERROR) if (share->state.key_root[sort_key] == NI_POS_ERROR)
DBUG_RETURN(0); /* Nothing to do */ DBUG_RETURN(0); /* Nothing to do */
init_key_cache(use_buffers); init_key_cache(dflt_keycache,KEY_CACHE_BLOCK_SIZE,use_buffers,
&dflt_key_cache_var);
if (init_io_cache(&info->rec_cache,-1,(uint) write_buffer_length, if (init_io_cache(&info->rec_cache,-1,(uint) write_buffer_length,
WRITE_CACHE,share->pack.header_length,1, WRITE_CACHE,share->pack.header_length,1,
MYF(MY_WME | MY_WAIT_IF_FULL))) MYF(MY_WME | MY_WAIT_IF_FULL)))
......
...@@ -329,8 +329,8 @@ static int examine_log(my_string file_name, char **table_names) ...@@ -329,8 +329,8 @@ static int examine_log(my_string file_name, char **table_names)
bzero((gptr) com_count,sizeof(com_count)); bzero((gptr) com_count,sizeof(com_count));
init_tree(&tree,0,0,sizeof(file_info),(qsort_cmp2) file_info_compare,1, init_tree(&tree,0,0,sizeof(file_info),(qsort_cmp2) file_info_compare,1,
(tree_element_free) file_info_free, NULL); (tree_element_free) file_info_free, NULL);
VOID(init_key_cache(KEY_CACHE_SIZE)); VOID(init_key_cache(dflt_keycache,KEY_CACHE_BLOCK_SIZE,KEY_CACHE_SIZE,
&dflt_key_cache_var));
files_open=0; access_time=0; files_open=0; access_time=0;
while (access_time++ != number_of_commands && while (access_time++ != number_of_commands &&
!my_b_read(&cache,(byte*) head,9)) !my_b_read(&cache,(byte*) head,9))
...@@ -622,7 +622,7 @@ static int examine_log(my_string file_name, char **table_names) ...@@ -622,7 +622,7 @@ static int examine_log(my_string file_name, char **table_names)
goto end; goto end;
} }
} }
end_key_cache(); end_key_cache(dflt_keycache,1);
delete_tree(&tree); delete_tree(&tree);
VOID(end_io_cache(&cache)); VOID(end_io_cache(&cache));
VOID(my_close(file,MYF(0))); VOID(my_close(file,MYF(0)));
...@@ -642,7 +642,7 @@ static int examine_log(my_string file_name, char **table_names) ...@@ -642,7 +642,7 @@ static int examine_log(my_string file_name, char **table_names)
llstr(isamlog_filepos,llbuff))); llstr(isamlog_filepos,llbuff)));
fflush(stderr); fflush(stderr);
end: end:
end_key_cache(); end_key_cache(dflt_keycache,1);
delete_tree(&tree); delete_tree(&tree);
VOID(end_io_cache(&cache)); VOID(end_io_cache(&cache));
VOID(my_close(file,MYF(0))); VOID(my_close(file,MYF(0)));
......
...@@ -48,7 +48,7 @@ int nisam_panic(enum ha_panic_function flag) ...@@ -48,7 +48,7 @@ int nisam_panic(enum ha_panic_function flag)
if (info->s->base.options & HA_OPTION_READ_ONLY_DATA) if (info->s->base.options & HA_OPTION_READ_ONLY_DATA)
break; break;
#endif #endif
if (flush_key_blocks(info->s->kfile,FLUSH_RELEASE)) if (flush_key_blocks(*dflt_keycache,info->s->kfile,FLUSH_RELEASE))
error=my_errno; error=my_errno;
if (info->opt_flag & WRITE_CACHE_USED) if (info->opt_flag & WRITE_CACHE_USED)
if (flush_io_cache(&info->rec_cache)) if (flush_io_cache(&info->rec_cache))
......
...@@ -156,7 +156,7 @@ int main(int argc, char *argv[]) ...@@ -156,7 +156,7 @@ int main(int argc, char *argv[])
goto err; goto err;
printf("- Writing key:s\n"); printf("- Writing key:s\n");
if (key_cacheing) if (key_cacheing)
init_key_cache(IO_SIZE*16); /* Use a small cache */ init_key_cache(dflt_keycache,512,IO_SIZE*16,0); /* Use a small cache */
if (locking) if (locking)
nisam_lock_database(file,F_WRLCK); nisam_lock_database(file,F_WRLCK);
if (write_cacheing) if (write_cacheing)
...@@ -674,7 +674,7 @@ end: ...@@ -674,7 +674,7 @@ end:
puts("Locking used"); puts("Locking used");
if (use_blob) if (use_blob)
puts("blobs used"); puts("blobs used");
end_key_cache(); end_key_cache(&dflt_keycache,1);
if (blob_buffer) if (blob_buffer)
my_free(blob_buffer,MYF(0)); my_free(blob_buffer,MYF(0));
my_end(MY_CHECK_ERROR | MY_GIVE_INFO); my_end(MY_CHECK_ERROR | MY_GIVE_INFO);
......
...@@ -173,7 +173,7 @@ void start_test(int id) ...@@ -173,7 +173,7 @@ void start_test(int id)
exit(1); exit(1);
} }
if (key_cacheing && rnd(2) == 0) if (key_cacheing && rnd(2) == 0)
init_key_cache(65536L); init_key_cache(dflt_keycache,512,65536L,0);
printf("Process %d, pid: %d\n",id,(int) getpid()); fflush(stdout); printf("Process %d, pid: %d\n",id,(int) getpid()); fflush(stdout);
for (error=i=0 ; i < tests && !error; i++) for (error=i=0 ; i < tests && !error; i++)
......
...@@ -47,7 +47,7 @@ libmyisam_a_SOURCES = mi_open.c mi_extra.c mi_info.c mi_rkey.c \ ...@@ -47,7 +47,7 @@ libmyisam_a_SOURCES = mi_open.c mi_extra.c mi_info.c mi_rkey.c \
mi_range.c mi_dbug.c mi_checksum.c mi_log.c \ mi_range.c mi_dbug.c mi_checksum.c mi_log.c \
mi_changed.c mi_static.c mi_delete_all.c \ mi_changed.c mi_static.c mi_delete_all.c \
mi_delete_table.c mi_rename.c mi_check.c \ mi_delete_table.c mi_rename.c mi_check.c \
mi_preload.c \ mi_keycache.c mi_preload.c \
ft_parser.c ft_stopwords.c ft_static.c \ ft_parser.c ft_stopwords.c ft_static.c \
ft_update.c ft_boolean_search.c ft_nlq_search.c sort.c \ ft_update.c ft_boolean_search.c ft_nlq_search.c sort.c \
rt_index.c rt_key.c rt_mbr.c rt_split.c sp_key.c rt_index.c rt_key.c rt_mbr.c rt_split.c sp_key.c
......
...@@ -230,7 +230,9 @@ static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint nr) ...@@ -230,7 +230,9 @@ static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint nr)
if (next_link > info->state->key_file_length || if (next_link > info->state->key_file_length ||
next_link & (info->s->blocksize-1)) next_link & (info->s->blocksize-1))
DBUG_RETURN(1); DBUG_RETURN(1);
if (!(buff=key_cache_read(info->s->kfile, next_link, (byte*) info->buff, if (!(buff=key_cache_read(*info->s->keycache,
info->s->kfile, next_link, DFLT_INIT_HITS,
(byte*) info->buff,
myisam_block_size, block_size, 1))) myisam_block_size, block_size, 1)))
DBUG_RETURN(1); DBUG_RETURN(1);
next_link=mi_sizekorr(buff); next_link=mi_sizekorr(buff);
...@@ -259,7 +261,8 @@ int chk_size(MI_CHECK *param, register MI_INFO *info) ...@@ -259,7 +261,8 @@ int chk_size(MI_CHECK *param, register MI_INFO *info)
if (!(param->testflag & T_SILENT)) puts("- check file-size"); if (!(param->testflag & T_SILENT)) puts("- check file-size");
flush_key_blocks(info->s->kfile, FLUSH_FORCE_WRITE); /* If called externally */ flush_key_blocks(*info->s->keycache,
info->s->kfile, FLUSH_FORCE_WRITE); /* If called externally */
size=my_seek(info->s->kfile,0L,MY_SEEK_END,MYF(0)); size=my_seek(info->s->kfile,0L,MY_SEEK_END,MYF(0));
if ((skr=(my_off_t) info->state->key_file_length) != size) if ((skr=(my_off_t) info->state->key_file_length) != size)
...@@ -369,8 +372,8 @@ int chk_key(MI_CHECK *param, register MI_INFO *info) ...@@ -369,8 +372,8 @@ int chk_key(MI_CHECK *param, register MI_INFO *info)
if (share->state.key_root[key] == HA_OFFSET_ERROR && if (share->state.key_root[key] == HA_OFFSET_ERROR &&
(info->state->records == 0 || keyinfo->flag & HA_FULLTEXT)) (info->state->records == 0 || keyinfo->flag & HA_FULLTEXT))
continue; continue;
if (!_mi_fetch_keypage(info,keyinfo,share->state.key_root[key],info->buff, if (!_mi_fetch_keypage(info,keyinfo,share->state.key_root[key],
0)) DFLT_INIT_HITS,info->buff,0))
{ {
mi_check_print_error(param,"Can't read indexpage from filepos: %s", mi_check_print_error(param,"Can't read indexpage from filepos: %s",
llstr(share->state.key_root[key],buff)); llstr(share->state.key_root[key],buff));
...@@ -548,7 +551,8 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, ...@@ -548,7 +551,8 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
info->state->key_file_length=(max_length & info->state->key_file_length=(max_length &
~ (my_off_t) (info->s->blocksize-1)); ~ (my_off_t) (info->s->blocksize-1));
} }
if (!_mi_fetch_keypage(info,keyinfo,next_page,temp_buff,0)) if (!_mi_fetch_keypage(info,keyinfo,next_page,
DFLT_INIT_HITS,temp_buff,0))
{ {
mi_check_print_error(param,"Can't read key from filepos: %s",llstr(next_page,llbuff)); mi_check_print_error(param,"Can't read key from filepos: %s",llstr(next_page,llbuff));
goto err; goto err;
...@@ -1120,7 +1124,8 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, ...@@ -1120,7 +1124,8 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
param->testflag|=T_REP; /* for easy checking */ param->testflag|=T_REP; /* for easy checking */
if (!param->using_global_keycache) if (!param->using_global_keycache)
VOID(init_key_cache(param->use_buffers)); VOID(init_key_cache(dflt_keycache,dflt_key_cache_var.block_size,
param->use_buffers,&dflt_key_cache_var));
if (init_io_cache(&param->read_cache,info->dfile, if (init_io_cache(&param->read_cache,info->dfile,
(uint) param->read_buffer_length, (uint) param->read_buffer_length,
...@@ -1441,7 +1446,8 @@ int movepoint(register MI_INFO *info, byte *record, my_off_t oldpos, ...@@ -1441,7 +1446,8 @@ int movepoint(register MI_INFO *info, byte *record, my_off_t oldpos,
nod_flag=mi_test_if_nod(info->buff); nod_flag=mi_test_if_nod(info->buff);
_mi_dpointer(info,info->int_keypos-nod_flag- _mi_dpointer(info,info->int_keypos-nod_flag-
info->s->rec_reflength,newpos); info->s->rec_reflength,newpos);
if (_mi_write_keypage(info,keyinfo,info->last_keypage,info->buff)) if (_mi_write_keypage(info,keyinfo,info->last_keypage,
DFLT_INIT_HITS,info->buff))
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
else else
...@@ -1478,13 +1484,13 @@ void lock_memory(MI_CHECK *param __attribute__((unused))) ...@@ -1478,13 +1484,13 @@ void lock_memory(MI_CHECK *param __attribute__((unused)))
int flush_blocks(MI_CHECK *param, File file) int flush_blocks(MI_CHECK *param, File file)
{ {
if (flush_key_blocks(file,FLUSH_RELEASE)) if (flush_key_blocks(*dflt_keycache,file,FLUSH_RELEASE))
{ {
mi_check_print_error(param,"%d when trying to write bufferts",my_errno); mi_check_print_error(param,"%d when trying to write bufferts",my_errno);
return(1); return(1);
} }
if (!param->using_global_keycache) if (!param->using_global_keycache)
end_key_cache(); end_key_cache(dflt_keycache,1);
return 0; return 0;
} /* flush_blocks */ } /* flush_blocks */
...@@ -1539,7 +1545,7 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name) ...@@ -1539,7 +1545,7 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name)
} }
/* Flush key cache for this file if we are calling this outside myisamchk */ /* Flush key cache for this file if we are calling this outside myisamchk */
flush_key_blocks(share->kfile, FLUSH_IGNORE_CHANGED); flush_key_blocks(*share->keycache,share->kfile, FLUSH_IGNORE_CHANGED);
share->state.version=(ulong) time((time_t*) 0); share->state.version=(ulong) time((time_t*) 0);
old_state= share->state; /* save state if not stored */ old_state= share->state; /* save state if not stored */
...@@ -1603,7 +1609,7 @@ static int sort_one_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, ...@@ -1603,7 +1609,7 @@ static int sort_one_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
mi_check_print_error(param,"Not Enough memory"); mi_check_print_error(param,"Not Enough memory");
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
if (!_mi_fetch_keypage(info,keyinfo,pagepos,buff,0)) if (!_mi_fetch_keypage(info,keyinfo,pagepos,DFLT_INIT_HITS,buff,0))
{ {
mi_check_print_error(param,"Can't read key block from filepos: %s", mi_check_print_error(param,"Can't read key block from filepos: %s",
llstr(pagepos,llbuff)); llstr(pagepos,llbuff));
...@@ -1849,7 +1855,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, ...@@ -1849,7 +1855,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
Flush key cache for this file if we are calling this outside Flush key cache for this file if we are calling this outside
myisamchk myisamchk
*/ */
flush_key_blocks(share->kfile, FLUSH_IGNORE_CHANGED); flush_key_blocks(*share->keycache,share->kfile, FLUSH_IGNORE_CHANGED);
/* Clear the pointers to the given rows */ /* Clear the pointers to the given rows */
for (i=0 ; i < share->base.keys ; i++) for (i=0 ; i < share->base.keys ; i++)
share->state.key_root[i]= HA_OFFSET_ERROR; share->state.key_root[i]= HA_OFFSET_ERROR;
...@@ -1859,7 +1865,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, ...@@ -1859,7 +1865,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
} }
else else
{ {
if (flush_key_blocks(share->kfile, FLUSH_FORCE_WRITE)) if (flush_key_blocks(*share->keycache,share->kfile, FLUSH_FORCE_WRITE))
goto err; goto err;
key_map= ~key_map; /* Create the missing keys */ key_map= ~key_map; /* Create the missing keys */
} }
...@@ -2212,7 +2218,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, ...@@ -2212,7 +2218,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
Flush key cache for this file if we are calling this outside Flush key cache for this file if we are calling this outside
myisamchk myisamchk
*/ */
flush_key_blocks(share->kfile, FLUSH_IGNORE_CHANGED); flush_key_blocks(*share->keycache,share->kfile, FLUSH_IGNORE_CHANGED);
/* Clear the pointers to the given rows */ /* Clear the pointers to the given rows */
for (i=0 ; i < share->base.keys ; i++) for (i=0 ; i < share->base.keys ; i++)
share->state.key_root[i]= HA_OFFSET_ERROR; share->state.key_root[i]= HA_OFFSET_ERROR;
...@@ -2222,7 +2228,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, ...@@ -2222,7 +2228,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
} }
else else
{ {
if (flush_key_blocks(share->kfile, FLUSH_FORCE_WRITE)) if (flush_key_blocks(*share->keycache,share->kfile, FLUSH_FORCE_WRITE))
goto err; goto err;
key_map= ~key_map; /* Create the missing keys */ key_map= ~key_map; /* Create the missing keys */
} }
...@@ -3337,13 +3343,13 @@ static int sort_insert_key(MI_SORT_PARAM *sort_param, ...@@ -3337,13 +3343,13 @@ static int sort_insert_key(MI_SORT_PARAM *sort_param,
bzero((byte*) anc_buff+key_block->last_length, bzero((byte*) anc_buff+key_block->last_length,
keyinfo->block_length- key_block->last_length); keyinfo->block_length- key_block->last_length);
key_file_length=info->state->key_file_length; key_file_length=info->state->key_file_length;
if ((filepos=_mi_new(info,keyinfo)) == HA_OFFSET_ERROR) if ((filepos=_mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
DBUG_RETURN(1); DBUG_RETURN(1);
/* If we read the page from the key cache, we have to write it back to it */ /* If we read the page from the key cache, we have to write it back to it */
if (key_file_length == info->state->key_file_length) if (key_file_length == info->state->key_file_length)
{ {
if (_mi_write_keypage(info, keyinfo, filepos, anc_buff)) if (_mi_write_keypage(info, keyinfo, filepos, DFLT_INIT_HITS, anc_buff))
DBUG_RETURN(1); DBUG_RETURN(1);
} }
else if (my_pwrite(info->s->kfile,(byte*) anc_buff, else if (my_pwrite(info->s->kfile,(byte*) anc_buff,
...@@ -3441,13 +3447,14 @@ int flush_pending_blocks(MI_SORT_PARAM *sort_param) ...@@ -3441,13 +3447,14 @@ int flush_pending_blocks(MI_SORT_PARAM *sort_param)
_mi_kpointer(info,key_block->end_pos,filepos); _mi_kpointer(info,key_block->end_pos,filepos);
key_file_length=info->state->key_file_length; key_file_length=info->state->key_file_length;
bzero((byte*) key_block->buff+length, keyinfo->block_length-length); bzero((byte*) key_block->buff+length, keyinfo->block_length-length);
if ((filepos=_mi_new(info,keyinfo)) == HA_OFFSET_ERROR) if ((filepos=_mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
DBUG_RETURN(1); DBUG_RETURN(1);
/* If we read the page from the key cache, we have to write it back */ /* If we read the page from the key cache, we have to write it back */
if (key_file_length == info->state->key_file_length) if (key_file_length == info->state->key_file_length)
{ {
if (_mi_write_keypage(info, keyinfo, filepos, key_block->buff)) if (_mi_write_keypage(info, keyinfo, filepos,
DFLT_INIT_HITS, key_block->buff))
DBUG_RETURN(1); DBUG_RETURN(1);
} }
else if (my_pwrite(info->s->kfile,(byte*) key_block->buff, else if (my_pwrite(info->s->kfile,(byte*) key_block->buff,
......
...@@ -64,7 +64,7 @@ int mi_close(register MI_INFO *info) ...@@ -64,7 +64,7 @@ int mi_close(register MI_INFO *info)
if (flag) if (flag)
{ {
if (share->kfile >= 0 && if (share->kfile >= 0 &&
flush_key_blocks(share->kfile, flush_key_blocks(*share->keycache,share->kfile,
share->temporary ? FLUSH_IGNORE_CHANGED : share->temporary ? FLUSH_IGNORE_CHANGED :
FLUSH_RELEASE)) FLUSH_RELEASE))
error=my_errno; error=my_errno;
......
...@@ -155,7 +155,7 @@ static int _mi_ck_real_delete(register MI_INFO *info, MI_KEYDEF *keyinfo, ...@@ -155,7 +155,7 @@ static int _mi_ck_real_delete(register MI_INFO *info, MI_KEYDEF *keyinfo,
DBUG_RETURN(my_errno=ENOMEM); DBUG_RETURN(my_errno=ENOMEM);
} }
DBUG_PRINT("info",("root_page: %ld",old_root)); DBUG_PRINT("info",("root_page: %ld",old_root));
if (!_mi_fetch_keypage(info,keyinfo,old_root,root_buff,0)) if (!_mi_fetch_keypage(info,keyinfo,old_root,DFLT_INIT_HITS,root_buff,0))
{ {
error= -1; error= -1;
goto err; goto err;
...@@ -179,11 +179,12 @@ static int _mi_ck_real_delete(register MI_INFO *info, MI_KEYDEF *keyinfo, ...@@ -179,11 +179,12 @@ static int _mi_ck_real_delete(register MI_INFO *info, MI_KEYDEF *keyinfo,
*root=_mi_kpos(nod_flag,root_buff+2+nod_flag); *root=_mi_kpos(nod_flag,root_buff+2+nod_flag);
else else
*root=HA_OFFSET_ERROR; *root=HA_OFFSET_ERROR;
if (_mi_dispose(info,keyinfo,old_root)) if (_mi_dispose(info,keyinfo,old_root,DFLT_INIT_HITS))
error= -1; error= -1;
} }
else else
error=_mi_write_keypage(info,keyinfo,old_root,root_buff); error=_mi_write_keypage(info,keyinfo,old_root,
DFLT_INIT_HITS,root_buff);
} }
} }
err: err:
...@@ -253,7 +254,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -253,7 +254,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
{ {
/* the last entry in sub-tree */ /* the last entry in sub-tree */
DBUG_PRINT("info",("FT2: the last entry")); DBUG_PRINT("info",("FT2: the last entry"));
_mi_dispose(info, keyinfo, root); _mi_dispose(info, keyinfo, root,DFLT_INIT_HITS);
/* fall through to normal delete */ /* fall through to normal delete */
} }
else else
...@@ -268,7 +269,8 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -268,7 +269,8 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
subkeys++; subkeys++;
ft_intXstore(kpos, subkeys); ft_intXstore(kpos, subkeys);
if (!ret_value) if (!ret_value)
ret_value=_mi_write_keypage(info,keyinfo,page,anc_buff); ret_value=_mi_write_keypage(info,keyinfo,page,
DFLT_INIT_HITS,anc_buff);
DBUG_PRINT("exit",("Return: %d",ret_value)); DBUG_PRINT("exit",("Return: %d",ret_value));
DBUG_RETURN(ret_value); DBUG_RETURN(ret_value);
} }
...@@ -287,7 +289,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -287,7 +289,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
DBUG_PRINT("exit",("Return: %d",-1)); DBUG_PRINT("exit",("Return: %d",-1));
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
if (!_mi_fetch_keypage(info,keyinfo,leaf_page,leaf_buff,0)) if (!_mi_fetch_keypage(info,keyinfo,leaf_page,DFLT_INIT_HITS,leaf_buff,0))
goto err; goto err;
} }
...@@ -319,7 +321,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -319,7 +321,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
mi_putint(anc_buff,length,nod_flag); mi_putint(anc_buff,length,nod_flag);
if (!nod_flag) if (!nod_flag)
{ /* On leaf page */ { /* On leaf page */
if (_mi_write_keypage(info,keyinfo,page,anc_buff)) if (_mi_write_keypage(info,keyinfo,page,DFLT_INIT_HITS,anc_buff))
{ {
DBUG_PRINT("exit",("Return: %d",-1)); DBUG_PRINT("exit",("Return: %d",-1));
DBUG_RETURN(-1); DBUG_RETURN(-1);
...@@ -354,7 +356,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -354,7 +356,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
ret_value=_mi_split_page(info,keyinfo,key,anc_buff,lastkey,0) | 2; ret_value=_mi_split_page(info,keyinfo,key,anc_buff,lastkey,0) | 2;
} }
if (save_flag && ret_value != 1) if (save_flag && ret_value != 1)
ret_value|=_mi_write_keypage(info,keyinfo,page,anc_buff); ret_value|=_mi_write_keypage(info,keyinfo,page,DFLT_INIT_HITS,anc_buff);
else else
{ {
DBUG_DUMP("page",(byte*) anc_buff,mi_getint(anc_buff)); DBUG_DUMP("page",(byte*) anc_buff,mi_getint(anc_buff));
...@@ -398,7 +400,7 @@ static int del(register MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *key, ...@@ -398,7 +400,7 @@ static int del(register MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *key,
if (!(next_buff= (uchar*) my_alloca((uint) keyinfo->block_length+ if (!(next_buff= (uchar*) my_alloca((uint) keyinfo->block_length+
MI_MAX_KEY_BUFF*2))) MI_MAX_KEY_BUFF*2)))
DBUG_RETURN(-1); DBUG_RETURN(-1);
if (!_mi_fetch_keypage(info,keyinfo,next_page,next_buff,0)) if (!_mi_fetch_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,next_buff,0))
ret_value= -1; ret_value= -1;
else else
{ {
...@@ -426,7 +428,7 @@ static int del(register MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *key, ...@@ -426,7 +428,7 @@ static int del(register MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *key,
(uchar*) 0,(uchar*) 0,(my_off_t) 0,0); (uchar*) 0,(uchar*) 0,(my_off_t) 0,0);
} }
} }
if (_mi_write_keypage(info,keyinfo,leaf_page,leaf_buff)) if (_mi_write_keypage(info,keyinfo,leaf_page,DFLT_INIT_HITS,leaf_buff))
goto err; goto err;
} }
my_afree((byte*) next_buff); my_afree((byte*) next_buff);
...@@ -436,7 +438,7 @@ static int del(register MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *key, ...@@ -436,7 +438,7 @@ static int del(register MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *key,
/* Remove last key from leaf page */ /* Remove last key from leaf page */
mi_putint(leaf_buff,key_start-leaf_buff,nod_flag); mi_putint(leaf_buff,key_start-leaf_buff,nod_flag);
if (_mi_write_keypage(info,keyinfo,leaf_page,leaf_buff)) if (_mi_write_keypage(info,keyinfo,leaf_page,DFLT_INIT_HITS,leaf_buff))
goto err; goto err;
/* Place last key in ancestor page on deleted key position */ /* Place last key in ancestor page on deleted key position */
...@@ -524,7 +526,7 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -524,7 +526,7 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo,
goto err; goto err;
} }
next_page= _mi_kpos(key_reflength,next_keypos); next_page= _mi_kpos(key_reflength,next_keypos);
if (!_mi_fetch_keypage(info,keyinfo,next_page,buff,0)) if (!_mi_fetch_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,buff,0))
goto err; goto err;
buff_length=mi_getint(buff); buff_length=mi_getint(buff);
DBUG_DUMP("next",(byte*) buff,buff_length); DBUG_DUMP("next",(byte*) buff,buff_length);
...@@ -563,7 +565,7 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -563,7 +565,7 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo,
if (buff_length <= keyinfo->block_length) if (buff_length <= keyinfo->block_length)
{ /* Keys in one page */ { /* Keys in one page */
memcpy((byte*) leaf_buff,(byte*) buff,(size_t) buff_length); memcpy((byte*) leaf_buff,(byte*) buff,(size_t) buff_length);
if (_mi_dispose(info,keyinfo,next_page)) if (_mi_dispose(info,keyinfo,next_page,DFLT_INIT_HITS))
goto err; goto err;
} }
else else
...@@ -612,10 +614,10 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -612,10 +614,10 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo,
(*keyinfo->store_key)(keyinfo,buff+p_length,&s_temp); (*keyinfo->store_key)(keyinfo,buff+p_length,&s_temp);
mi_putint(buff,length+t_length+p_length,nod_flag); mi_putint(buff,length+t_length+p_length,nod_flag);
if (_mi_write_keypage(info,keyinfo,next_page,buff)) if (_mi_write_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,buff))
goto err; goto err;
} }
if (_mi_write_keypage(info,keyinfo,leaf_page,leaf_buff)) if (_mi_write_keypage(info,keyinfo,leaf_page,DFLT_INIT_HITS,leaf_buff))
goto err; goto err;
DBUG_RETURN(anc_length <= ((info->quick_mode ? MI_MIN_BLOCK_LENGTH : DBUG_RETURN(anc_length <= ((info->quick_mode ? MI_MIN_BLOCK_LENGTH :
(uint) keyinfo->underflow_block_length))); (uint) keyinfo->underflow_block_length)));
...@@ -627,7 +629,7 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -627,7 +629,7 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo,
if (!keypos) if (!keypos)
goto err; goto err;
next_page= _mi_kpos(key_reflength,keypos); next_page= _mi_kpos(key_reflength,keypos);
if (!_mi_fetch_keypage(info,keyinfo,next_page,buff,0)) if (!_mi_fetch_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,buff,0))
goto err; goto err;
buff_length=mi_getint(buff); buff_length=mi_getint(buff);
endpos=buff+buff_length; endpos=buff+buff_length;
...@@ -671,7 +673,7 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -671,7 +673,7 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo,
if (buff_length <= keyinfo->block_length) if (buff_length <= keyinfo->block_length)
{ /* Keys in one page */ { /* Keys in one page */
if (_mi_dispose(info,keyinfo,leaf_page)) if (_mi_dispose(info,keyinfo,leaf_page,DFLT_INIT_HITS))
goto err; goto err;
} }
else else
...@@ -718,11 +720,11 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -718,11 +720,11 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo,
(size_t) length); (size_t) length);
(*keyinfo->store_key)(keyinfo,leaf_buff+p_length,&s_temp); (*keyinfo->store_key)(keyinfo,leaf_buff+p_length,&s_temp);
mi_putint(leaf_buff,length+t_length+p_length,nod_flag); mi_putint(leaf_buff,length+t_length+p_length,nod_flag);
if (_mi_write_keypage(info,keyinfo,leaf_page,leaf_buff)) if (_mi_write_keypage(info,keyinfo,leaf_page,DFLT_INIT_HITS,leaf_buff))
goto err; goto err;
mi_putint(buff,endpos-buff,nod_flag); mi_putint(buff,endpos-buff,nod_flag);
} }
if (_mi_write_keypage(info,keyinfo,next_page,buff)) if (_mi_write_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,buff))
goto err; goto err;
DBUG_RETURN(anc_length <= (uint) keyinfo->block_length/2); DBUG_RETURN(anc_length <= (uint) keyinfo->block_length/2);
err: err:
......
...@@ -53,7 +53,7 @@ int mi_delete_all_rows(MI_INFO *info) ...@@ -53,7 +53,7 @@ int mi_delete_all_rows(MI_INFO *info)
If we are using delayed keys or if the user has done changes to the tables If we are using delayed keys or if the user has done changes to the tables
since it was locked then there may be key blocks in the key cache since it was locked then there may be key blocks in the key cache
*/ */
flush_key_blocks(share->kfile, FLUSH_IGNORE_CHANGED); flush_key_blocks(*share->keycache, share->kfile, FLUSH_IGNORE_CHANGED);
if (my_chsize(info->dfile, 0, 0, MYF(MY_WME)) || if (my_chsize(info->dfile, 0, 0, MYF(MY_WME)) ||
my_chsize(share->kfile, share->base.keystart, 0, MYF(MY_WME)) ) my_chsize(share->kfile, share->base.keystart, 0, MYF(MY_WME)) )
goto err; goto err;
......
...@@ -283,7 +283,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) ...@@ -283,7 +283,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
#ifdef __WIN__ #ifdef __WIN__
/* Close the isam and data files as Win32 can't drop an open table */ /* Close the isam and data files as Win32 can't drop an open table */
pthread_mutex_lock(&share->intern_lock); pthread_mutex_lock(&share->intern_lock);
if (flush_key_blocks(share->kfile, if (flush_key_blocks(*share->keycache, share->kfile,
(function == HA_EXTRA_FORCE_REOPEN ? (function == HA_EXTRA_FORCE_REOPEN ?
FLUSH_RELEASE : FLUSH_IGNORE_CHANGED))) FLUSH_RELEASE : FLUSH_IGNORE_CHANGED)))
{ {
...@@ -329,7 +329,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) ...@@ -329,7 +329,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
break; break;
case HA_EXTRA_FLUSH: case HA_EXTRA_FLUSH:
if (!share->temporary) if (!share->temporary)
flush_key_blocks(share->kfile,FLUSH_KEEP); flush_key_blocks(*share->keycache,share->kfile,FLUSH_KEEP);
#ifdef HAVE_PWRITE #ifdef HAVE_PWRITE
_mi_decrement_open_count(info); _mi_decrement_open_count(info);
#endif #endif
...@@ -374,6 +374,9 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) ...@@ -374,6 +374,9 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
case HA_EXTRA_PRELOAD_BUFFER_SIZE: case HA_EXTRA_PRELOAD_BUFFER_SIZE:
info->preload_buff_size= *((ulong *) extra_arg); info->preload_buff_size= *((ulong *) extra_arg);
break; break;
case HA_EXTRA_SET_KEY_CACHE:
share->reg_keycache= share->keycache= (KEY_CACHE_HANDLE *) extra_arg;
break;
case HA_EXTRA_KEY_CACHE: case HA_EXTRA_KEY_CACHE:
case HA_EXTRA_NO_KEY_CACHE: case HA_EXTRA_NO_KEY_CACHE:
default: default:
......
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
Key cache assignments
*/
#include "myisamdef.h"
/*
Assign pages of the index file for a table to a key cache
SYNOPSIS
mi_assign_to_keycache()
info open table
map map of indexes to assign to the key cache
key_cache_ptr pointer to the key cache handle
RETURN VALUE
0 if a success. error code - otherwise.
NOTES.
At present pages for all indexes must be assigned to the same key cache.
In future only pages for indexes specified in the key_map parameter
of the table will be assigned to the specified key cache.
*/
typedef struct st_assign_extra_info
{
pthread_mutex_t *lock;
struct st_my_thread_var *waiting_thread;
} ASSIGN_EXTRA_INFO;
static void remove_key_cache_assign(void *arg)
{
KEY_CACHE_VAR *key_cache= (KEY_CACHE_VAR *) arg;
ASSIGN_EXTRA_INFO *extra_info= (ASSIGN_EXTRA_INFO *) key_cache->extra_info;
struct st_my_thread_var *waiting_thread;
pthread_mutex_t *lock= extra_info->lock;
pthread_mutex_lock(lock);
if (!(--key_cache->assignments) &&
(waiting_thread = extra_info->waiting_thread))
{
my_free(extra_info, MYF(0));
key_cache->extra_info= 0;
if (waiting_thread != my_thread_var)
pthread_cond_signal(&waiting_thread->suspend);
}
pthread_mutex_unlock(lock);
}
int mi_assign_to_keycache(MI_INFO *info, ulonglong key_map,
KEY_CACHE_VAR *key_cache,
pthread_mutex_t *assign_lock)
{
ASSIGN_EXTRA_INFO *extra_info;
int error= 0;
MYISAM_SHARE* share= info->s;
DBUG_ENTER("mi_assign_to_keycache");
share->reg_keycache= &key_cache->cache;
pthread_mutex_lock(assign_lock);
if (!(extra_info= (ASSIGN_EXTRA_INFO *) key_cache->extra_info))
{
if (!(extra_info= (ASSIGN_EXTRA_INFO*) my_malloc(sizeof(ASSIGN_EXTRA_INFO),
MYF(MY_WME | MY_ZEROFILL))))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
key_cache->extra_info= extra_info;
key_cache->action= remove_key_cache_assign;
extra_info->lock= assign_lock;
}
key_cache->assignments++;
pthread_mutex_unlock(assign_lock);
if (!(info->lock_type == F_WRLCK && share->w_locks))
{
if (flush_key_blocks(*share->keycache, share->kfile, FLUSH_REMOVE))
{
error=my_errno;
mi_mark_crashed(info); /* Mark that table must be checked */
}
share->keycache= &key_cache->cache;
}
else
{
extra_info->waiting_thread= my_thread_var;
}
DBUG_RETURN(error);
}
...@@ -34,6 +34,7 @@ int mi_lock_database(MI_INFO *info, int lock_type) ...@@ -34,6 +34,7 @@ int mi_lock_database(MI_INFO *info, int lock_type)
uint count; uint count;
MYISAM_SHARE *share=info->s; MYISAM_SHARE *share=info->s;
uint flag; uint flag;
uint switch_fl= 0;
DBUG_ENTER("mi_lock_database"); DBUG_ENTER("mi_lock_database");
DBUG_PRINT("info",("lock_type: %d", lock_type)); DBUG_PRINT("info",("lock_type: %d", lock_type));
...@@ -60,12 +61,21 @@ int mi_lock_database(MI_INFO *info, int lock_type) ...@@ -60,12 +61,21 @@ int mi_lock_database(MI_INFO *info, int lock_type)
else else
count= --share->w_locks; count= --share->w_locks;
--share->tot_locks; --share->tot_locks;
/*
During a key cache reassignment the current and registered
key caches for the table are different.
*/
if (info->lock_type == F_WRLCK && !share->w_locks && if (info->lock_type == F_WRLCK && !share->w_locks &&
!share->delay_key_write && flush_key_blocks(share->kfile,FLUSH_KEEP)) ((switch_fl= share->keycache != share->reg_keycache) ||
!share->delay_key_write) &&
flush_key_blocks(*share->keycache, share->kfile,
switch_fl ? FLUSH_REMOVE : FLUSH_KEEP))
{ {
error=my_errno; error=my_errno;
mi_mark_crashed(info); /* Mark that table must be checked */ mi_mark_crashed(info); /* Mark that table must be checked */
} }
if (switch_fl)
share->keycache= share->reg_keycache;
if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED)) if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
{ {
if (end_io_cache(&info->rec_cache)) if (end_io_cache(&info->rec_cache))
...@@ -400,7 +410,7 @@ int _mi_test_if_changed(register MI_INFO *info) ...@@ -400,7 +410,7 @@ int _mi_test_if_changed(register MI_INFO *info)
{ /* Keyfile has changed */ { /* Keyfile has changed */
DBUG_PRINT("info",("index file changed")); DBUG_PRINT("info",("index file changed"));
if (share->state.process != share->this_process) if (share->state.process != share->this_process)
VOID(flush_key_blocks(share->kfile,FLUSH_RELEASE)); VOID(flush_key_blocks(*share->keycache,share->kfile,FLUSH_RELEASE));
share->last_process=share->state.process; share->last_process=share->state.process;
info->last_unique= share->state.unique; info->last_unique= share->state.unique;
info->last_loop= share->state.update_count; info->last_loop= share->state.update_count;
......
...@@ -24,14 +24,16 @@ ...@@ -24,14 +24,16 @@
/* Fetch a key-page in memory */ /* Fetch a key-page in memory */
uchar *_mi_fetch_keypage(register MI_INFO *info, MI_KEYDEF *keyinfo, uchar *_mi_fetch_keypage(register MI_INFO *info, MI_KEYDEF *keyinfo,
my_off_t page, uchar *buff, int return_buffer) my_off_t page, int level,
uchar *buff, int return_buffer)
{ {
uchar *tmp; uchar *tmp;
uint page_size; uint page_size;
DBUG_ENTER("_mi_fetch_keypage"); DBUG_ENTER("_mi_fetch_keypage");
DBUG_PRINT("enter",("page: %ld",page)); DBUG_PRINT("enter",("page: %ld",page));
tmp=(uchar*) key_cache_read(info->s->kfile,page,(byte*) buff, tmp=(uchar*) key_cache_read(*info->s->keycache,
info->s->kfile, page, level, (byte*) buff,
(uint) keyinfo->block_length, (uint) keyinfo->block_length,
(uint) keyinfo->block_length, (uint) keyinfo->block_length,
return_buffer); return_buffer);
...@@ -61,7 +63,7 @@ uchar *_mi_fetch_keypage(register MI_INFO *info, MI_KEYDEF *keyinfo, ...@@ -61,7 +63,7 @@ uchar *_mi_fetch_keypage(register MI_INFO *info, MI_KEYDEF *keyinfo,
/* Write a key-page on disk */ /* Write a key-page on disk */
int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo, int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo,
my_off_t page, uchar *buff) my_off_t page, int level, uchar *buff)
{ {
reg3 uint length; reg3 uint length;
DBUG_ENTER("_mi_write_keypage"); DBUG_ENTER("_mi_write_keypage");
...@@ -92,7 +94,8 @@ int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -92,7 +94,8 @@ int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo,
length=keyinfo->block_length; length=keyinfo->block_length;
} }
#endif #endif
DBUG_RETURN((key_cache_write(info->s->kfile,page,(byte*) buff,length, DBUG_RETURN((key_cache_write(*info->s->keycache,
info->s->kfile,page, level, (byte*) buff,length,
(uint) keyinfo->block_length, (uint) keyinfo->block_length,
(int) ((info->lock_type != F_UNLCK) || (int) ((info->lock_type != F_UNLCK) ||
info->s->delay_key_write)))); info->s->delay_key_write))));
...@@ -101,7 +104,8 @@ int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -101,7 +104,8 @@ int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo,
/* Remove page from disk */ /* Remove page from disk */
int _mi_dispose(register MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t pos) int _mi_dispose(register MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t pos,
int level)
{ {
my_off_t old_link; my_off_t old_link;
char buff[8]; char buff[8];
...@@ -112,7 +116,8 @@ int _mi_dispose(register MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t pos) ...@@ -112,7 +116,8 @@ int _mi_dispose(register MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t pos)
info->s->state.key_del[keyinfo->block_size]=pos; info->s->state.key_del[keyinfo->block_size]=pos;
mi_sizestore(buff,old_link); mi_sizestore(buff,old_link);
info->s->state.changed|= STATE_NOT_SORTED_PAGES; info->s->state.changed|= STATE_NOT_SORTED_PAGES;
DBUG_RETURN(key_cache_write(info->s->kfile,pos,buff, DBUG_RETURN(key_cache_write(*info->s->keycache,
info->s->kfile, pos , level, buff,
sizeof(buff), sizeof(buff),
(uint) keyinfo->block_length, (uint) keyinfo->block_length,
(int) (info->lock_type != F_UNLCK))); (int) (info->lock_type != F_UNLCK)));
...@@ -121,7 +126,7 @@ int _mi_dispose(register MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t pos) ...@@ -121,7 +126,7 @@ int _mi_dispose(register MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t pos)
/* Make new page on disk */ /* Make new page on disk */
my_off_t _mi_new(register MI_INFO *info, MI_KEYDEF *keyinfo) my_off_t _mi_new(register MI_INFO *info, MI_KEYDEF *keyinfo, int level)
{ {
my_off_t pos; my_off_t pos;
char buff[8]; char buff[8];
...@@ -140,7 +145,8 @@ my_off_t _mi_new(register MI_INFO *info, MI_KEYDEF *keyinfo) ...@@ -140,7 +145,8 @@ my_off_t _mi_new(register MI_INFO *info, MI_KEYDEF *keyinfo)
} }
else else
{ {
if (!key_cache_read(info->s->kfile,pos, if (!key_cache_read(*info->s->keycache,
info->s->kfile, pos, level,
buff, buff,
(uint) sizeof(buff), (uint) sizeof(buff),
(uint) keyinfo->block_length,0)) (uint) keyinfo->block_length,0))
......
...@@ -48,7 +48,7 @@ int mi_panic(enum ha_panic_function flag) ...@@ -48,7 +48,7 @@ int mi_panic(enum ha_panic_function flag)
if (info->s->options & HA_OPTION_READ_ONLY_DATA) if (info->s->options & HA_OPTION_READ_ONLY_DATA)
break; break;
#endif #endif
if (flush_key_blocks(info->s->kfile,FLUSH_RELEASE)) if (flush_key_blocks(*info->s->keycache,info->s->kfile,FLUSH_RELEASE))
error=my_errno; error=my_errno;
if (info->opt_flag & WRITE_CACHE_USED) if (info->opt_flag & WRITE_CACHE_USED)
if (flush_io_cache(&info->rec_cache)) if (flush_io_cache(&info->rec_cache))
......
...@@ -69,7 +69,7 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves) ...@@ -69,7 +69,7 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves)
if (!(buff= (uchar *) my_malloc(length, MYF(MY_WME)))) if (!(buff= (uchar *) my_malloc(length, MYF(MY_WME))))
DBUG_RETURN(my_errno= HA_ERR_OUT_OF_MEM); DBUG_RETURN(my_errno= HA_ERR_OUT_OF_MEM);
if (flush_key_blocks(share->kfile, FLUSH_RELEASE)) if (flush_key_blocks(*share->keycache,share->kfile, FLUSH_RELEASE))
goto err; goto err;
do do
...@@ -87,7 +87,9 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves) ...@@ -87,7 +87,9 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves)
{ {
if (mi_test_if_nod(buff)) if (mi_test_if_nod(buff))
{ {
if (key_cache_insert(share->kfile, pos, (byte*) buff, block_length)) if (key_cache_insert(*share->keycache,
share->kfile, pos, DFLT_INIT_HITS,
(byte*) buff, block_length))
goto err; goto err;
} }
pos+= block_length; pos+= block_length;
...@@ -97,7 +99,9 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves) ...@@ -97,7 +99,9 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves)
} }
else else
{ {
if (key_cache_insert(share->kfile, pos, (byte*) buff, length)) if (key_cache_insert(*share->keycache,
share->kfile, pos, DFLT_INIT_HITS,
(byte*) buff, length))
goto err; goto err;
pos+= length; pos+= length;
} }
......
...@@ -142,7 +142,7 @@ static double _mi_search_pos(register MI_INFO *info, ...@@ -142,7 +142,7 @@ static double _mi_search_pos(register MI_INFO *info,
if (pos == HA_OFFSET_ERROR) if (pos == HA_OFFSET_ERROR)
DBUG_RETURN(0.5); DBUG_RETURN(0.5);
if (!(buff=_mi_fetch_keypage(info,keyinfo,pos,info->buff,1))) if (!(buff=_mi_fetch_keypage(info,keyinfo,pos,DFLT_INIT_HITS,info->buff,1)))
goto err; goto err;
flag=(*keyinfo->bin_search)(info,keyinfo,buff,key,key_len,nextflag, flag=(*keyinfo->bin_search)(info,keyinfo,buff,key,key_len,nextflag,
&keypos,info->lastkey, &after_key); &keypos,info->lastkey, &after_key);
......
...@@ -76,7 +76,7 @@ int _mi_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -76,7 +76,7 @@ int _mi_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
DBUG_RETURN(1); /* Search at upper levels */ DBUG_RETURN(1); /* Search at upper levels */
} }
if (!(buff=_mi_fetch_keypage(info,keyinfo,pos,info->buff, if (!(buff=_mi_fetch_keypage(info,keyinfo,pos,DFLT_INIT_HITS,info->buff,
test(!(nextflag & SEARCH_SAVE_BUFF))))) test(!(nextflag & SEARCH_SAVE_BUFF)))))
goto err; goto err;
DBUG_DUMP("page",(byte*) buff,mi_getint(buff)); DBUG_DUMP("page",(byte*) buff,mi_getint(buff));
...@@ -119,7 +119,7 @@ int _mi_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -119,7 +119,7 @@ int _mi_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
if (pos != info->last_keypage) if (pos != info->last_keypage)
{ {
uchar *old_buff=buff; uchar *old_buff=buff;
if (!(buff=_mi_fetch_keypage(info,keyinfo,pos,info->buff, if (!(buff=_mi_fetch_keypage(info,keyinfo,pos,DFLT_INIT_HITS,info->buff,
test(!(nextflag & SEARCH_SAVE_BUFF))))) test(!(nextflag & SEARCH_SAVE_BUFF)))))
goto err; goto err;
keypos=buff+(keypos-old_buff); keypos=buff+(keypos-old_buff);
...@@ -1108,7 +1108,7 @@ int _mi_search_next(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -1108,7 +1108,7 @@ int _mi_search_next(register MI_INFO *info, register MI_KEYDEF *keyinfo,
if (info->buff_used) if (info->buff_used)
{ {
if (!_mi_fetch_keypage(info,keyinfo,info->last_search_keypage, if (!_mi_fetch_keypage(info,keyinfo,info->last_search_keypage,
info->buff,0)) DFLT_INIT_HITS,info->buff,0))
DBUG_RETURN(-1); DBUG_RETURN(-1);
info->buff_used=0; info->buff_used=0;
} }
...@@ -1177,7 +1177,7 @@ int _mi_search_first(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -1177,7 +1177,7 @@ int _mi_search_first(register MI_INFO *info, register MI_KEYDEF *keyinfo,
do do
{ {
if (!_mi_fetch_keypage(info,keyinfo,pos,info->buff,0)) if (!_mi_fetch_keypage(info,keyinfo,pos,DFLT_INIT_HITS,info->buff,0))
{ {
info->lastpos= HA_OFFSET_ERROR; info->lastpos= HA_OFFSET_ERROR;
DBUG_RETURN(-1); DBUG_RETURN(-1);
...@@ -1220,7 +1220,7 @@ int _mi_search_last(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -1220,7 +1220,7 @@ int _mi_search_last(register MI_INFO *info, register MI_KEYDEF *keyinfo,
buff=info->buff; buff=info->buff;
do do
{ {
if (!_mi_fetch_keypage(info,keyinfo,pos,buff,0)) if (!_mi_fetch_keypage(info,keyinfo,pos,DFLT_INIT_HITS,buff,0))
{ {
info->lastpos= HA_OFFSET_ERROR; info->lastpos= HA_OFFSET_ERROR;
DBUG_RETURN(-1); DBUG_RETURN(-1);
......
...@@ -50,7 +50,7 @@ int main(int argc,char *argv[]) ...@@ -50,7 +50,7 @@ int main(int argc,char *argv[])
MY_INIT(argv[0]); MY_INIT(argv[0]);
my_init(); my_init();
if (key_cacheing) if (key_cacheing)
init_key_cache(IO_SIZE*16); init_key_cache(dflt_keycache,512,IO_SIZE*16,0);
get_options(argc,argv); get_options(argc,argv);
exit(run_test("test1")); exit(run_test("test1"));
......
...@@ -49,6 +49,7 @@ static int verbose=0,testflag=0, ...@@ -49,6 +49,7 @@ static int verbose=0,testflag=0,
static int pack_seg=HA_SPACE_PACK,pack_type=HA_PACK_KEY,remove_count=-1, static int pack_seg=HA_SPACE_PACK,pack_type=HA_PACK_KEY,remove_count=-1,
create_flag=0; create_flag=0;
static ulong key_cache_size=IO_SIZE*16; static ulong key_cache_size=IO_SIZE*16;
static uint key_cache_block_size=IO_SIZE;
static uint keys=MYISAM_KEYS,recant=1000; static uint keys=MYISAM_KEYS,recant=1000;
static uint use_blob=0; static uint use_blob=0;
...@@ -214,7 +215,7 @@ int main(int argc, char *argv[]) ...@@ -214,7 +215,7 @@ int main(int argc, char *argv[])
if (!silent) if (!silent)
printf("- Writing key:s\n"); printf("- Writing key:s\n");
if (key_cacheing) if (key_cacheing)
init_key_cache(key_cache_size); /* Use a small cache */ init_key_cache(dflt_keycache,key_cache_block_size,key_cache_size,0); /* Use a small cache */
if (locking) if (locking)
mi_lock_database(file,F_WRLCK); mi_lock_database(file,F_WRLCK);
if (write_cacheing) if (write_cacheing)
...@@ -274,7 +275,7 @@ int main(int argc, char *argv[]) ...@@ -274,7 +275,7 @@ int main(int argc, char *argv[])
goto end; goto end;
} }
if (key_cacheing) if (key_cacheing)
resize_key_cache(key_cache_size*2); resize_key_cache(dflt_keycache,key_cache_block_size,key_cache_size*2);
} }
if (!silent) if (!silent)
...@@ -816,16 +817,19 @@ end: ...@@ -816,16 +817,19 @@ end:
puts("Locking used"); puts("Locking used");
if (use_blob) if (use_blob)
puts("blobs used"); puts("blobs used");
#if 0
printf("key cache status: \n\ printf("key cache status: \n\
blocks used:%10lu\n\ blocks used:%10lu\n\
w_requests: %10lu\n\ w_requests: %10lu\n\
writes: %10lu\n\ writes: %10lu\n\
r_requests: %10lu\n\ r_requests: %10lu\n\
reads: %10lu\n", reads: %10lu\n",
my_blocks_used, my_cache_w_requests, my_cache_write, my_blocks_used,
my_cache_w_requests, my_cache_write,
my_cache_r_requests, my_cache_read); my_cache_r_requests, my_cache_read);
#endif
} }
end_key_cache(); end_key_cache(dflt_keycache,1);
if (blob_buffer) if (blob_buffer)
my_free(blob_buffer,MYF(0)); my_free(blob_buffer,MYF(0));
my_end(silent ? MY_CHECK_ERROR : MY_CHECK_ERROR | MY_GIVE_INFO); my_end(silent ? MY_CHECK_ERROR : MY_CHECK_ERROR | MY_GIVE_INFO);
......
...@@ -177,7 +177,7 @@ void start_test(int id) ...@@ -177,7 +177,7 @@ void start_test(int id)
exit(1); exit(1);
} }
if (key_cacheing && rnd(2) == 0) if (key_cacheing && rnd(2) == 0)
init_key_cache(65536L); init_key_cache(dflt_keycache,512,65536L,0);
printf("Process %d, pid: %d\n",id,getpid()); fflush(stdout); printf("Process %d, pid: %d\n",id,getpid()); fflush(stdout);
for (error=i=0 ; i < tests && !error; i++) for (error=i=0 ; i < tests && !error; i++)
......
...@@ -290,8 +290,8 @@ int _mi_enlarge_root(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key, ...@@ -290,8 +290,8 @@ int _mi_enlarge_root(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
mi_putint(info->buff,t_length+2+nod_flag,nod_flag); mi_putint(info->buff,t_length+2+nod_flag,nod_flag);
(*keyinfo->store_key)(keyinfo,info->buff+2+nod_flag,&s_temp); (*keyinfo->store_key)(keyinfo,info->buff+2+nod_flag,&s_temp);
info->buff_used=info->page_changed=1; /* info->buff is used */ info->buff_used=info->page_changed=1; /* info->buff is used */
if ((*root= _mi_new(info,keyinfo)) == HA_OFFSET_ERROR || if ((*root= _mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR ||
_mi_write_keypage(info,keyinfo,*root,info->buff)) _mi_write_keypage(info,keyinfo,*root,DFLT_INIT_HITS,info->buff))
DBUG_RETURN(-1); DBUG_RETURN(-1);
DBUG_RETURN(0); DBUG_RETURN(0);
} /* _mi_enlarge_root */ } /* _mi_enlarge_root */
...@@ -322,7 +322,7 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -322,7 +322,7 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
if (!(temp_buff= (uchar*) my_alloca((uint) keyinfo->block_length+ if (!(temp_buff= (uchar*) my_alloca((uint) keyinfo->block_length+
MI_MAX_KEY_BUFF*2))) MI_MAX_KEY_BUFF*2)))
DBUG_RETURN(-1); DBUG_RETURN(-1);
if (!_mi_fetch_keypage(info,keyinfo,page,temp_buff,0)) if (!_mi_fetch_keypage(info,keyinfo,page,DFLT_INIT_HITS,temp_buff,0))
goto err; goto err;
flag=(*keyinfo->bin_search)(info,keyinfo,temp_buff,key,search_key_length, flag=(*keyinfo->bin_search)(info,keyinfo,temp_buff,key,search_key_length,
...@@ -368,7 +368,7 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -368,7 +368,7 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
subkeys--; /* should there be underflow protection ? */ subkeys--; /* should there be underflow protection ? */
ft_intXstore(keypos, subkeys); ft_intXstore(keypos, subkeys);
if (!error) if (!error)
error=_mi_write_keypage(info,keyinfo,page,temp_buff); error=_mi_write_keypage(info,keyinfo,page,DFLT_INIT_HITS,temp_buff);
my_afree((byte*) temp_buff); my_afree((byte*) temp_buff);
DBUG_RETURN(error); DBUG_RETURN(error);
} }
...@@ -391,7 +391,7 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -391,7 +391,7 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
{ {
error=_mi_insert(info,keyinfo,key,temp_buff,keypos,keybuff,father_buff, error=_mi_insert(info,keyinfo,key,temp_buff,keypos,keybuff,father_buff,
father_keypos,father_page, insert_last); father_keypos,father_page, insert_last);
if (_mi_write_keypage(info,keyinfo,page,temp_buff)) if (_mi_write_keypage(info,keyinfo,page,DFLT_INIT_HITS,temp_buff))
goto err; goto err;
} }
my_afree((byte*) temp_buff); my_afree((byte*) temp_buff);
...@@ -515,7 +515,7 @@ int _mi_split_page(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -515,7 +515,7 @@ int _mi_split_page(register MI_INFO *info, register MI_KEYDEF *keyinfo,
} }
/* Move middle item to key and pointer to new page */ /* Move middle item to key and pointer to new page */
if ((new_pos=_mi_new(info,keyinfo)) == HA_OFFSET_ERROR) if ((new_pos=_mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
DBUG_RETURN(-1); DBUG_RETURN(-1);
_mi_kpointer(info,_mi_move_key(keyinfo,key,key_buff),new_pos); _mi_kpointer(info,_mi_move_key(keyinfo,key,key_buff),new_pos);
...@@ -531,7 +531,7 @@ int _mi_split_page(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -531,7 +531,7 @@ int _mi_split_page(register MI_INFO *info, register MI_KEYDEF *keyinfo,
(*keyinfo->store_key)(keyinfo,info->buff+key_ref_length,&s_temp); (*keyinfo->store_key)(keyinfo,info->buff+key_ref_length,&s_temp);
mi_putint(info->buff,length+t_length+key_ref_length,nod_flag); mi_putint(info->buff,length+t_length+key_ref_length,nod_flag);
if (_mi_write_keypage(info,keyinfo,new_pos,info->buff)) if (_mi_write_keypage(info,keyinfo,new_pos,DFLT_INIT_HITS,info->buff))
DBUG_RETURN(-1); DBUG_RETURN(-1);
DBUG_DUMP("key",(byte*) key,_mi_keylength(keyinfo,key)); DBUG_DUMP("key",(byte*) key,_mi_keylength(keyinfo,key));
DBUG_RETURN(2); /* Middle key up */ DBUG_RETURN(2); /* Middle key up */
...@@ -682,7 +682,7 @@ static int _mi_balance_page(register MI_INFO *info, MI_KEYDEF *keyinfo, ...@@ -682,7 +682,7 @@ static int _mi_balance_page(register MI_INFO *info, MI_KEYDEF *keyinfo,
DBUG_PRINT("test",("use left page: %lu",next_page)); DBUG_PRINT("test",("use left page: %lu",next_page));
} /* father_key_pos ptr to parting key */ } /* father_key_pos ptr to parting key */
if (!_mi_fetch_keypage(info,keyinfo,next_page,info->buff,0)) if (!_mi_fetch_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,info->buff,0))
goto err; goto err;
DBUG_DUMP("next",(byte*) info->buff,mi_getint(info->buff)); DBUG_DUMP("next",(byte*) info->buff,mi_getint(info->buff));
...@@ -722,8 +722,8 @@ static int _mi_balance_page(register MI_INFO *info, MI_KEYDEF *keyinfo, ...@@ -722,8 +722,8 @@ static int _mi_balance_page(register MI_INFO *info, MI_KEYDEF *keyinfo,
memcpy((byte*) buff+2,(byte*) pos+k_length,(size_t) length); memcpy((byte*) buff+2,(byte*) pos+k_length,(size_t) length);
} }
if (_mi_write_keypage(info,keyinfo,next_page,info->buff) || if (_mi_write_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,info->buff) ||
_mi_write_keypage(info,keyinfo,father_page,father_buff)) _mi_write_keypage(info,keyinfo,father_page,DFLT_INIT_HITS,father_buff))
goto err; goto err;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -763,12 +763,13 @@ static int _mi_balance_page(register MI_INFO *info, MI_KEYDEF *keyinfo, ...@@ -763,12 +763,13 @@ static int _mi_balance_page(register MI_INFO *info, MI_KEYDEF *keyinfo,
memcpy((byte*) (right ? key : father_key_pos),pos,(size_t) k_length); memcpy((byte*) (right ? key : father_key_pos),pos,(size_t) k_length);
memcpy((byte*) (right ? father_key_pos : key),tmp_part_key, k_length); memcpy((byte*) (right ? father_key_pos : key),tmp_part_key, k_length);
if ((new_pos=_mi_new(info,keyinfo)) == HA_OFFSET_ERROR) if ((new_pos=_mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
goto err; goto err;
_mi_kpointer(info,key+k_length,new_pos); _mi_kpointer(info,key+k_length,new_pos);
if (_mi_write_keypage(info,keyinfo,(right ? new_pos : next_page), if (_mi_write_keypage(info,keyinfo,(right ? new_pos : next_page),
info->buff) || DFLT_INIT_HITS,info->buff) ||
_mi_write_keypage(info,keyinfo,(right ? next_page : new_pos),extra_buff)) _mi_write_keypage(info,keyinfo,(right ? next_page : new_pos),
DFLT_INIT_HITS,extra_buff))
goto err; goto err;
DBUG_RETURN(1); /* Middle key up */ DBUG_RETURN(1); /* Middle key up */
......
...@@ -44,6 +44,7 @@ static const char *load_default_groups[]= { "myisamchk", 0 }; ...@@ -44,6 +44,7 @@ static const char *load_default_groups[]= { "myisamchk", 0 };
static const char *set_charset_name, *opt_tmpdir; static const char *set_charset_name, *opt_tmpdir;
static CHARSET_INFO *set_charset; static CHARSET_INFO *set_charset;
static long opt_myisam_block_size; static long opt_myisam_block_size;
static long opt_key_cache_block_size;
static const char *my_progname_short; static const char *my_progname_short;
static int stopwords_inited= 0; static int stopwords_inited= 0;
static MY_TMPDIR myisamchk_tmpdir; static MY_TMPDIR myisamchk_tmpdir;
...@@ -148,7 +149,8 @@ int main(int argc, char **argv) ...@@ -148,7 +149,8 @@ int main(int argc, char **argv)
enum options { enum options {
OPT_CHARSETS_DIR=256, OPT_SET_CHARSET,OPT_START_CHECK_POS, OPT_CHARSETS_DIR=256, OPT_SET_CHARSET,OPT_START_CHECK_POS,
OPT_CORRECT_CHECKSUM, OPT_KEY_BUFFER_SIZE, OPT_MYISAM_BLOCK_SIZE, OPT_CORRECT_CHECKSUM, OPT_KEY_BUFFER_SIZE,
OPT_KEY_CACHE_BLOCK_SIZE, OPT_MYISAM_BLOCK_SIZE,
OPT_READ_BUFFER_SIZE, OPT_WRITE_BUFFER_SIZE, OPT_SORT_BUFFER_SIZE, OPT_READ_BUFFER_SIZE, OPT_WRITE_BUFFER_SIZE, OPT_SORT_BUFFER_SIZE,
OPT_SORT_KEY_BLOCKS, OPT_DECODE_BITS, OPT_FT_MIN_WORD_LEN, OPT_SORT_KEY_BLOCKS, OPT_DECODE_BITS, OPT_FT_MIN_WORD_LEN,
OPT_FT_MAX_WORD_LEN, OPT_FT_MAX_WORD_LEN_FOR_SORT OPT_FT_MAX_WORD_LEN, OPT_FT_MAX_WORD_LEN_FOR_SORT
...@@ -283,6 +285,11 @@ static struct my_option my_long_options[] = ...@@ -283,6 +285,11 @@ static struct my_option my_long_options[] =
(gptr*) &check_param.use_buffers, (gptr*) &check_param.use_buffers, 0, (gptr*) &check_param.use_buffers, (gptr*) &check_param.use_buffers, 0,
GET_ULONG, REQUIRED_ARG, (long) USE_BUFFER_INIT, (long) MALLOC_OVERHEAD, GET_ULONG, REQUIRED_ARG, (long) USE_BUFFER_INIT, (long) MALLOC_OVERHEAD,
(long) ~0L, (long) MALLOC_OVERHEAD, (long) IO_SIZE, 0}, (long) ~0L, (long) MALLOC_OVERHEAD, (long) IO_SIZE, 0},
{ "key_cache_block_size", OPT_KEY_CACHE_BLOCK_SIZE, "",
(gptr*) &opt_key_cache_block_size,
(gptr*) &opt_key_cache_block_size, 0,
GET_LONG, REQUIRED_ARG, MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH,
MI_MAX_KEY_BLOCK_LENGTH, 0, MI_MIN_KEY_BLOCK_LENGTH, 0},
{ "myisam_block_size", OPT_MYISAM_BLOCK_SIZE, "", { "myisam_block_size", OPT_MYISAM_BLOCK_SIZE, "",
(gptr*) &opt_myisam_block_size, (gptr*) &opt_myisam_block_size, 0, (gptr*) &opt_myisam_block_size, (gptr*) &opt_myisam_block_size, 0,
GET_LONG, REQUIRED_ARG, MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH, GET_LONG, REQUIRED_ARG, MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH,
...@@ -1025,7 +1032,8 @@ static int myisamchk(MI_CHECK *param, my_string filename) ...@@ -1025,7 +1032,8 @@ static int myisamchk(MI_CHECK *param, my_string filename)
!(param->testflag & (T_FAST | T_FORCE_CREATE))) !(param->testflag & (T_FAST | T_FORCE_CREATE)))
{ {
if (param->testflag & (T_EXTEND | T_MEDIUM)) if (param->testflag & (T_EXTEND | T_MEDIUM))
VOID(init_key_cache(param->use_buffers)); VOID(init_key_cache(dflt_keycache,opt_key_cache_block_size,
param->use_buffers,&dflt_key_cache_var));
VOID(init_io_cache(&param->read_cache,datafile, VOID(init_io_cache(&param->read_cache,datafile,
(uint) param->read_buffer_length, (uint) param->read_buffer_length,
READ_CACHE, READ_CACHE,
...@@ -1448,7 +1456,8 @@ static int mi_sort_records(MI_CHECK *param, ...@@ -1448,7 +1456,8 @@ static int mi_sort_records(MI_CHECK *param,
if (share->state.key_root[sort_key] == HA_OFFSET_ERROR) if (share->state.key_root[sort_key] == HA_OFFSET_ERROR)
DBUG_RETURN(0); /* Nothing to do */ DBUG_RETURN(0); /* Nothing to do */
init_key_cache(param->use_buffers); init_key_cache(dflt_keycache,opt_key_cache_block_size,param->use_buffers,
&dflt_key_cache_var);
if (init_io_cache(&info->rec_cache,-1,(uint) param->write_buffer_length, if (init_io_cache(&info->rec_cache,-1,(uint) param->write_buffer_length,
WRITE_CACHE,share->pack.header_length,1, WRITE_CACHE,share->pack.header_length,1,
MYF(MY_WME | MY_WAIT_IF_FULL))) MYF(MY_WME | MY_WAIT_IF_FULL)))
......
...@@ -166,6 +166,8 @@ typedef struct st_mi_isam_share { /* Shared between opens */ ...@@ -166,6 +166,8 @@ typedef struct st_mi_isam_share { /* Shared between opens */
char *data_file_name, /* Resolved path names from symlinks */ char *data_file_name, /* Resolved path names from symlinks */
*index_file_name; *index_file_name;
byte *file_map; /* mem-map of file if possible */ byte *file_map; /* mem-map of file if possible */
KEY_CACHE_HANDLE *keycache; /* ref to the current key cache */
KEY_CACHE_HANDLE *reg_keycache; /* ref to the registered key cache */
MI_DECODE_TREE *decode_trees; MI_DECODE_TREE *decode_trees;
uint16 *decode_tables; uint16 *decode_tables;
int (*read_record)(struct st_myisam_info*, my_off_t, byte*); int (*read_record)(struct st_myisam_info*, my_off_t, byte*);
...@@ -546,11 +548,12 @@ extern int _mi_search_next(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key, ...@@ -546,11 +548,12 @@ extern int _mi_search_next(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key,
extern int _mi_search_first(MI_INFO *info,MI_KEYDEF *keyinfo,my_off_t pos); extern int _mi_search_first(MI_INFO *info,MI_KEYDEF *keyinfo,my_off_t pos);
extern int _mi_search_last(MI_INFO *info,MI_KEYDEF *keyinfo,my_off_t pos); extern int _mi_search_last(MI_INFO *info,MI_KEYDEF *keyinfo,my_off_t pos);
extern uchar *_mi_fetch_keypage(MI_INFO *info,MI_KEYDEF *keyinfo,my_off_t page, extern uchar *_mi_fetch_keypage(MI_INFO *info,MI_KEYDEF *keyinfo,my_off_t page,
uchar *buff,int return_buffer); int level,uchar *buff,int return_buffer);
extern int _mi_write_keypage(MI_INFO *info,MI_KEYDEF *keyinfo,my_off_t page, extern int _mi_write_keypage(MI_INFO *info,MI_KEYDEF *keyinfo,my_off_t page,
uchar *buff); int level, uchar *buff);
extern int _mi_dispose(MI_INFO *info,MI_KEYDEF *keyinfo,my_off_t pos); extern int _mi_dispose(MI_INFO *info,MI_KEYDEF *keyinfo,my_off_t pos,
extern my_off_t _mi_new(MI_INFO *info,MI_KEYDEF *keyinfo); int level);
extern my_off_t _mi_new(MI_INFO *info,MI_KEYDEF *keyinfo,int level);
extern uint _mi_make_key(MI_INFO *info,uint keynr,uchar *key, extern uint _mi_make_key(MI_INFO *info,uint keynr,uchar *key,
const byte *record,my_off_t filepos); const byte *record,my_off_t filepos);
extern uint _mi_pack_key(MI_INFO *info,uint keynr,uchar *key,uchar *old, extern uint _mi_pack_key(MI_INFO *info,uint keynr,uchar *key,uchar *old,
......
...@@ -333,7 +333,8 @@ static int examine_log(my_string file_name, char **table_names) ...@@ -333,7 +333,8 @@ static int examine_log(my_string file_name, char **table_names)
bzero((gptr) com_count,sizeof(com_count)); bzero((gptr) com_count,sizeof(com_count));
init_tree(&tree,0,0,sizeof(file_info),(qsort_cmp2) file_info_compare,1, init_tree(&tree,0,0,sizeof(file_info),(qsort_cmp2) file_info_compare,1,
(tree_element_free) file_info_free, NULL); (tree_element_free) file_info_free, NULL);
VOID(init_key_cache(KEY_CACHE_SIZE)); VOID(init_key_cache(dflt_keycache,KEY_CACHE_BLOCK_SIZE,KEY_CACHE_SIZE,
&dflt_key_cache_var));
files_open=0; access_time=0; files_open=0; access_time=0;
while (access_time++ != number_of_commands && while (access_time++ != number_of_commands &&
...@@ -647,7 +648,7 @@ static int examine_log(my_string file_name, char **table_names) ...@@ -647,7 +648,7 @@ static int examine_log(my_string file_name, char **table_names)
goto end; goto end;
} }
} }
end_key_cache(); end_key_cache(dflt_keycache,1);
delete_tree(&tree); delete_tree(&tree);
VOID(end_io_cache(&cache)); VOID(end_io_cache(&cache));
VOID(my_close(file,MYF(0))); VOID(my_close(file,MYF(0)));
...@@ -667,7 +668,7 @@ static int examine_log(my_string file_name, char **table_names) ...@@ -667,7 +668,7 @@ static int examine_log(my_string file_name, char **table_names)
llstr(isamlog_filepos,llbuff))); llstr(isamlog_filepos,llbuff)));
fflush(stderr); fflush(stderr);
end: end:
end_key_cache(); end_key_cache(dflt_keycache,1);
delete_tree(&tree); delete_tree(&tree);
VOID(end_io_cache(&cache)); VOID(end_io_cache(&cache));
VOID(my_close(file,MYF(0))); VOID(my_close(file,MYF(0)));
......
...@@ -60,7 +60,7 @@ static int rtree_find_req(MI_INFO *info, MI_KEYDEF *keyinfo, uint search_flag, u ...@@ -60,7 +60,7 @@ static int rtree_find_req(MI_INFO *info, MI_KEYDEF *keyinfo, uint search_flag, u
my_errno = HA_ERR_OUT_OF_MEM; my_errno = HA_ERR_OUT_OF_MEM;
return -1; return -1;
} }
if (!_mi_fetch_keypage(info, keyinfo, page, page_buf, 0)) if (!_mi_fetch_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf, 0))
goto err1; goto err1;
nod_flag = mi_test_if_nod(page_buf); nod_flag = mi_test_if_nod(page_buf);
...@@ -257,7 +257,7 @@ static int rtree_get_req(MI_INFO *info, MI_KEYDEF *keyinfo, uint key_length, ...@@ -257,7 +257,7 @@ static int rtree_get_req(MI_INFO *info, MI_KEYDEF *keyinfo, uint key_length,
if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length))) if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length)))
return -1; return -1;
if (!_mi_fetch_keypage(info, keyinfo, page, page_buf, 0)) if (!_mi_fetch_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf, 0))
goto err1; goto err1;
nod_flag = mi_test_if_nod(page_buf); nod_flag = mi_test_if_nod(page_buf);
...@@ -429,7 +429,7 @@ static int rtree_insert_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key, ...@@ -429,7 +429,7 @@ static int rtree_insert_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
my_errno = HA_ERR_OUT_OF_MEM; my_errno = HA_ERR_OUT_OF_MEM;
return -1; return -1;
} }
if (!_mi_fetch_keypage(info, keyinfo, page, page_buf, 0)) if (!_mi_fetch_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf, 0))
goto err1; goto err1;
nod_flag = mi_test_if_nod(page_buf); nod_flag = mi_test_if_nod(page_buf);
...@@ -445,7 +445,7 @@ static int rtree_insert_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key, ...@@ -445,7 +445,7 @@ static int rtree_insert_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
case 0: /* child was not split */ case 0: /* child was not split */
{ {
rtree_combine_rect(keyinfo->seg, k, key, k, key_length); rtree_combine_rect(keyinfo->seg, k, key, k, key_length);
if (_mi_write_keypage(info, keyinfo, page, page_buf)) if (_mi_write_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf))
goto err1; goto err1;
goto ok; goto ok;
} }
...@@ -462,7 +462,7 @@ static int rtree_insert_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key, ...@@ -462,7 +462,7 @@ static int rtree_insert_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
goto err1; goto err1;
res = rtree_add_key(info, keyinfo, new_key, key_length, res = rtree_add_key(info, keyinfo, new_key, key_length,
page_buf, new_page); page_buf, new_page);
if (_mi_write_keypage(info, keyinfo, page, page_buf)) if (_mi_write_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf))
goto err1; goto err1;
goto ok; goto ok;
} }
...@@ -476,7 +476,7 @@ static int rtree_insert_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key, ...@@ -476,7 +476,7 @@ static int rtree_insert_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
else else
{ {
res = rtree_add_key(info, keyinfo, key, key_length, page_buf, new_page); res = rtree_add_key(info, keyinfo, key, key_length, page_buf, new_page);
if (_mi_write_keypage(info, keyinfo, page, page_buf)) if (_mi_write_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf))
goto err1; goto err1;
goto ok; goto ok;
} }
...@@ -509,12 +509,12 @@ static int rtree_insert_level(MI_INFO *info, uint keynr, uchar *key, ...@@ -509,12 +509,12 @@ static int rtree_insert_level(MI_INFO *info, uint keynr, uchar *key,
{ {
int res; int res;
if ((old_root = _mi_new(info, keyinfo)) == HA_OFFSET_ERROR) if ((old_root = _mi_new(info, keyinfo, DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
return -1; return -1;
info->buff_used = 1; info->buff_used = 1;
mi_putint(info->buff, 2, 0); mi_putint(info->buff, 2, 0);
res = rtree_add_key(info, keyinfo, key, key_length, info->buff, NULL); res = rtree_add_key(info, keyinfo, key, key_length, info->buff, NULL);
if (_mi_write_keypage(info, keyinfo, old_root, info->buff)) if (_mi_write_keypage(info, keyinfo, old_root, DFLT_INIT_HITS, info->buff))
return 1; return 1;
info->s->state.key_root[keynr] = old_root; info->s->state.key_root[keynr] = old_root;
return res; return res;
...@@ -542,7 +542,8 @@ static int rtree_insert_level(MI_INFO *info, uint keynr, uchar *key, ...@@ -542,7 +542,8 @@ static int rtree_insert_level(MI_INFO *info, uint keynr, uchar *key,
} }
mi_putint(new_root_buf, 2, nod_flag); mi_putint(new_root_buf, 2, nod_flag);
if ((new_root = _mi_new(info, keyinfo)) == HA_OFFSET_ERROR) if ((new_root = _mi_new(info, keyinfo, DFLT_INIT_HITS)) ==
HA_OFFSET_ERROR)
goto err1; goto err1;
new_key = new_root_buf + keyinfo->block_length + nod_flag; new_key = new_root_buf + keyinfo->block_length + nod_flag;
...@@ -559,7 +560,8 @@ static int rtree_insert_level(MI_INFO *info, uint keynr, uchar *key, ...@@ -559,7 +560,8 @@ static int rtree_insert_level(MI_INFO *info, uint keynr, uchar *key,
if (rtree_add_key(info, keyinfo, new_key, key_length, new_root_buf, NULL) if (rtree_add_key(info, keyinfo, new_key, key_length, new_root_buf, NULL)
== -1) == -1)
goto err1; goto err1;
if (_mi_write_keypage(info, keyinfo, new_root, new_root_buf)) if (_mi_write_keypage(info, keyinfo, new_root,
DFLT_INIT_HITS, new_root_buf))
goto err1; goto err1;
info->s->state.key_root[keynr] = new_root; info->s->state.key_root[keynr] = new_root;
...@@ -636,7 +638,7 @@ static int rtree_delete_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key, ...@@ -636,7 +638,7 @@ static int rtree_delete_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
my_errno = HA_ERR_OUT_OF_MEM; my_errno = HA_ERR_OUT_OF_MEM;
return -1; return -1;
} }
if (!_mi_fetch_keypage(info, keyinfo, page, page_buf, 0)) if (!_mi_fetch_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf, 0))
goto err1; goto err1;
nod_flag = mi_test_if_nod(page_buf); nod_flag = mi_test_if_nod(page_buf);
...@@ -662,7 +664,8 @@ static int rtree_delete_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key, ...@@ -662,7 +664,8 @@ static int rtree_delete_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
if (rtree_set_key_mbr(info, keyinfo, k, key_length, if (rtree_set_key_mbr(info, keyinfo, k, key_length,
_mi_kpos(nod_flag, k))) _mi_kpos(nod_flag, k)))
goto err1; goto err1;
if (_mi_write_keypage(info, keyinfo, page, page_buf)) if (_mi_write_keypage(info, keyinfo, page,
DFLT_INIT_HITS, page_buf))
goto err1; goto err1;
} }
else else
...@@ -672,7 +675,8 @@ static int rtree_delete_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key, ...@@ -672,7 +675,8 @@ static int rtree_delete_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
level + 1)) level + 1))
goto err1; goto err1;
rtree_delete_key(info, page_buf, k, key_length, nod_flag); rtree_delete_key(info, page_buf, k, key_length, nod_flag);
if (_mi_write_keypage(info, keyinfo, page, page_buf)) if (_mi_write_keypage(info, keyinfo, page,
DFLT_INIT_HITS, page_buf))
goto err1; goto err1;
*page_size = mi_getint(page_buf); *page_size = mi_getint(page_buf);
} }
...@@ -686,7 +690,8 @@ static int rtree_delete_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key, ...@@ -686,7 +690,8 @@ static int rtree_delete_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
case 2: /* vacuous case: last key in the leaf */ case 2: /* vacuous case: last key in the leaf */
{ {
rtree_delete_key(info, page_buf, k, key_length, nod_flag); rtree_delete_key(info, page_buf, k, key_length, nod_flag);
if (_mi_write_keypage(info, keyinfo, page, page_buf)) if (_mi_write_keypage(info, keyinfo, page,
DFLT_INIT_HITS, page_buf))
goto err1; goto err1;
*page_size = mi_getint(page_buf); *page_size = mi_getint(page_buf);
res = 0; res = 0;
...@@ -711,13 +716,13 @@ static int rtree_delete_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key, ...@@ -711,13 +716,13 @@ static int rtree_delete_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
{ {
/* last key in the leaf */ /* last key in the leaf */
res = 2; res = 2;
if (_mi_dispose(info, keyinfo, page)) if (_mi_dispose(info, keyinfo, page, DFLT_INIT_HITS))
goto err1; goto err1;
} }
else else
{ {
res = 0; res = 0;
if (_mi_write_keypage(info, keyinfo, page, page_buf)) if (_mi_write_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf))
goto err1; goto err1;
} }
goto ok; goto ok;
...@@ -783,7 +788,7 @@ int rtree_delete(MI_INFO *info, uint keynr, uchar *key, uint key_length) ...@@ -783,7 +788,7 @@ int rtree_delete(MI_INFO *info, uint keynr, uchar *key, uint key_length)
goto err1; goto err1;
} }
if (!_mi_fetch_keypage(info, keyinfo, ReinsertList.pages[i].offs, if (!_mi_fetch_keypage(info, keyinfo, ReinsertList.pages[i].offs,
page_buf, 0)) DFLT_INIT_HITS, page_buf, 0))
goto err1; goto err1;
nod_flag = mi_test_if_nod(page_buf); nod_flag = mi_test_if_nod(page_buf);
k = rt_PAGE_FIRST_KEY(page_buf, nod_flag); k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
...@@ -798,7 +803,8 @@ int rtree_delete(MI_INFO *info, uint keynr, uchar *key, uint key_length) ...@@ -798,7 +803,8 @@ int rtree_delete(MI_INFO *info, uint keynr, uchar *key, uint key_length)
} }
} }
my_afree((byte*)page_buf); my_afree((byte*)page_buf);
if (_mi_dispose(info, keyinfo, ReinsertList.pages[i].offs)) if (_mi_dispose(info, keyinfo, ReinsertList.pages[i].offs,
DFLT_INIT_HITS))
goto err1; goto err1;
} }
if (ReinsertList.pages) if (ReinsertList.pages)
...@@ -807,7 +813,8 @@ int rtree_delete(MI_INFO *info, uint keynr, uchar *key, uint key_length) ...@@ -807,7 +813,8 @@ int rtree_delete(MI_INFO *info, uint keynr, uchar *key, uint key_length)
/* check for redundant root (not leaf, 1 child) and eliminate */ /* check for redundant root (not leaf, 1 child) and eliminate */
if ((old_root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR) if ((old_root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
goto err1; goto err1;
if (!_mi_fetch_keypage(info, keyinfo, old_root, info->buff, 0)) if (!_mi_fetch_keypage(info, keyinfo, old_root, DFLT_INIT_HITS,
info->buff, 0))
goto err1; goto err1;
nod_flag = mi_test_if_nod(info->buff); nod_flag = mi_test_if_nod(info->buff);
page_size = mi_getint(info->buff); page_size = mi_getint(info->buff);
...@@ -816,7 +823,7 @@ int rtree_delete(MI_INFO *info, uint keynr, uchar *key, uint key_length) ...@@ -816,7 +823,7 @@ int rtree_delete(MI_INFO *info, uint keynr, uchar *key, uint key_length)
{ {
my_off_t new_root = _mi_kpos(nod_flag, my_off_t new_root = _mi_kpos(nod_flag,
rt_PAGE_FIRST_KEY(info->buff, nod_flag)); rt_PAGE_FIRST_KEY(info->buff, nod_flag));
if (_mi_dispose(info, keyinfo, old_root)) if (_mi_dispose(info, keyinfo, old_root, DFLT_INIT_HITS))
goto err1; goto err1;
info->s->state.key_root[keynr] = new_root; info->s->state.key_root[keynr] = new_root;
} }
...@@ -863,7 +870,7 @@ ha_rows rtree_estimate(MI_INFO *info, uint keynr, uchar *key, ...@@ -863,7 +870,7 @@ ha_rows rtree_estimate(MI_INFO *info, uint keynr, uchar *key,
return HA_POS_ERROR; return HA_POS_ERROR;
if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length))) if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length)))
return HA_POS_ERROR; return HA_POS_ERROR;
if (!_mi_fetch_keypage(info, keyinfo, root, page_buf, 0)) if (!_mi_fetch_keypage(info, keyinfo, root, DFLT_INIT_HITS, page_buf, 0))
goto err1; goto err1;
nod_flag = mi_test_if_nod(page_buf); nod_flag = mi_test_if_nod(page_buf);
......
...@@ -88,7 +88,8 @@ int rtree_delete_key(MI_INFO *info, uchar *page_buf, uchar *key, ...@@ -88,7 +88,8 @@ int rtree_delete_key(MI_INFO *info, uchar *page_buf, uchar *key,
int rtree_set_key_mbr(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key, int rtree_set_key_mbr(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
uint key_length, my_off_t child_page) uint key_length, my_off_t child_page)
{ {
if (!_mi_fetch_keypage(info, keyinfo, child_page, info->buff, 0)) if (!_mi_fetch_keypage(info, keyinfo, child_page,
DFLT_INIT_HITS, info->buff, 0))
return -1; return -1;
return rtree_page_mbr(info, keyinfo->seg, info->buff, key, key_length); return rtree_page_mbr(info, keyinfo->seg, info->buff, key, key_length);
......
...@@ -332,10 +332,12 @@ int rtree_split_page(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, uchar *key, ...@@ -332,10 +332,12 @@ int rtree_split_page(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, uchar *key,
mi_putint(page, 2 + n1 * full_length, nod_flag); mi_putint(page, 2 + n1 * full_length, nod_flag);
mi_putint(new_page, 2 + n2 * full_length, nod_flag); mi_putint(new_page, 2 + n2 * full_length, nod_flag);
if ((*new_page_offs= _mi_new(info, keyinfo)) == HA_OFFSET_ERROR) if ((*new_page_offs= _mi_new(info, keyinfo, DFLT_INIT_HITS)) ==
HA_OFFSET_ERROR)
err_code= -1; err_code= -1;
else else
err_code= _mi_write_keypage(info, keyinfo, *new_page_offs, new_page); err_code= _mi_write_keypage(info, keyinfo, *new_page_offs,
DFLT_INIT_HITS, new_page);
my_afree((byte*)new_page); my_afree((byte*)new_page);
......
...@@ -514,7 +514,7 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -514,7 +514,7 @@ id select_type table type possible_keys key key_len ref rows Extra
explain explain
select min(a1) from t1 where a1 != 'KKK'; select min(a1) from t1 where a1 != 'KKK';
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL PRIMARY 3 NULL 14 Using where; Using index 1 SIMPLE t1 range PRIMARY PRIMARY 3 NULL 14 Using where; Using index
explain explain
select max(a3) from t1 where a2 < 2 and a3 < 'SEA'; select max(a3) from t1 where a2 < 2 and a3 < 'SEA';
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
...@@ -560,7 +560,7 @@ explain ...@@ -560,7 +560,7 @@ explain
select concat(min(t1.a1),min(t2.a4)) from t1, t2 where t2.a4 <> 'AME'; select concat(min(t1.a1),min(t2.a4)) from t1, t2 where t2.a4 <> 'AME';
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL PRIMARY 3 NULL 14 Using index 1 SIMPLE t1 index NULL PRIMARY 3 NULL 14 Using index
1 SIMPLE t2 index NULL k2 4 NULL 6 Using where; Using index 1 SIMPLE t2 range k2 k2 4 NULL 6 Using where; Using index
drop table t1, t2; drop table t1, t2;
CREATE TABLE t1 (a int, b int); CREATE TABLE t1 (a int, b int);
select count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1; select count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1;
......
...@@ -41,3 +41,194 @@ SELECT @@default.key_buffer_size; ...@@ -41,3 +41,194 @@ SELECT @@default.key_buffer_size;
ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'default.key_buffer_size' at line 1 ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'default.key_buffer_size' at line 1
SELECT @@skr.table_type="test"; SELECT @@skr.table_type="test";
ERROR HY000: Variable 'table_type' is not a variable component (Can't be used as XXXX.variable_name) ERROR HY000: Variable 'table_type' is not a variable component (Can't be used as XXXX.variable_name)
select @@keycache1.key_cache_block_size;
@@keycache1.key_cache_block_size
0
select @@keycache1.key_buffer_size;
@@keycache1.key_buffer_size
0
set global keycache1.key_cache_block_size=2048;
select @@keycache1.key_buffer_size;
@@keycache1.key_buffer_size
0
select @@keycache1.key_cache_block_size;
@@keycache1.key_cache_block_size
2048
set global keycache1.key_buffer_size=1*1024*1024;
select @@keycache1.key_buffer_size;
@@keycache1.key_buffer_size
1048576
select @@keycache1.key_cache_block_size;
@@keycache1.key_cache_block_size
2048
set global keycache2.key_buffer_size=4*1024*1024;
select @@keycache2.key_buffer_size;
@@keycache2.key_buffer_size
4194304
select @@keycache2.key_cache_block_size;
@@keycache2.key_cache_block_size
1024
set global keycache1.key_buffer_size=0;
select @@keycache1.key_buffer_size;
@@keycache1.key_buffer_size
0
select @@keycache1.key_cache_block_size;
@@keycache1.key_cache_block_size
0
select @@key_buffer_size;
@@key_buffer_size
2097152
select @@key_cache_block_size;
@@key_cache_block_size
1024
drop table if exists t1, t2;
create table t1 (p int primary key, a char(10));
create table t2 (p int primary key, i int, a char(10), key k1(i), key k2(a));
insert into t1 values (1, 'qqqq'), (11, 'yyyy');
insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
(3, 1, 'yyyy'), (4, 3, 'zzzz');
select * from t1;
p a
1 qqqq
11 yyyy
select * from t2;
p i a
1 1 qqqq
2 1 pppp
3 1 yyyy
4 3 zzzz
update t1 set p=2 where p=1;
update t2 set i=2 where i=1;
cache index t1 keys in keycache1;
Table Op Msg_type Msg_text
test.t1 assign_to_keycache status OK
explain select p from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL PRIMARY 4 NULL 2 Using index
select p from t1;
p
2
11
explain select i from t2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index NULL k1 5 NULL 4 Using index
select i from t2;
i
2
2
2
3
explain select count(*) from t1, t2 where t1.p = t2.i;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index PRIMARY PRIMARY 4 NULL 2 Using index
1 SIMPLE t2 ref k1 k1 5 test.t1.p 2 Using where; Using index
select count(*) from t1, t2 where t1.p = t2.i;
count(*)
3
cache index t2 keys in keycache1;
Table Op Msg_type Msg_text
test.t2 assign_to_keycache status OK
update t2 set p=p+1000, i=2 where a='qqqq';
cache index t2 keys in keycache2;
Table Op Msg_type Msg_text
test.t2 assign_to_keycache status OK
insert into t2 values (2000, 3, 'yyyy');
cache index t2 keys in keycache1;
Table Op Msg_type Msg_text
test.t2 assign_to_keycache status OK
update t2 set p=3000 where a='zzzz';
select * from t2;
p i a
1001 2 qqqq
2 2 pppp
3 2 yyyy
3000 3 zzzz
2000 3 yyyy
explain select p from t2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index NULL PRIMARY 4 NULL 5 Using index
select p from t2;
p
2
3
1001
2000
3000
explain select i from t2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index NULL k1 5 NULL 5 Using index
select i from t2;
i
2
2
2
3
3
explain select a from t2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index NULL k2 11 NULL 5 Using index
select a from t2;
a
pppp
qqqq
yyyy
yyyy
zzzz
select @@keycache2.key_buffer_size;
@@keycache2.key_buffer_size
4194304
select @@keycache2.key_cache_block_size;
@@keycache2.key_cache_block_size
1024
set global keycache2.key_buffer_size=0;
select @@keycache2.key_buffer_size;
@@keycache2.key_buffer_size
0
select @@keycache2.key_cache_block_size;
@@keycache2.key_cache_block_size
0
update t2 set p=4000 where a='zzzz';
update t1 set p=p+1;
set global keycache1.key_buffer_size=0;
select * from t2;
p i a
1001 2 qqqq
2 2 pppp
3 2 yyyy
4000 3 zzzz
2000 3 yyyy
select p from t2;
p
2
3
1001
2000
4000
explain select i from t2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index NULL k1 5 NULL 5 Using index
select i from t2;
i
2
2
2
3
3
explain select a from t2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index NULL k2 11 NULL 5 Using index
select a from t2;
a
pppp
qqqq
yyyy
yyyy
zzzz
select * from t1;
p a
3 qqqq
12 yyyy
select p from t1;
p
3
12
# #
# Test of key cache # Test of multiple key caches
# #
SET @save_key_buffer=@@key_buffer_size; SET @save_key_buffer=@@key_buffer_size;
...@@ -40,3 +40,83 @@ SET @@global.key_buffer_size=@save_key_buffer; ...@@ -40,3 +40,83 @@ SET @@global.key_buffer_size=@save_key_buffer;
SELECT @@default.key_buffer_size; SELECT @@default.key_buffer_size;
--error 1271 --error 1271
SELECT @@skr.table_type="test"; SELECT @@skr.table_type="test";
select @@keycache1.key_cache_block_size;
select @@keycache1.key_buffer_size;
set global keycache1.key_cache_block_size=2048;
select @@keycache1.key_buffer_size;
select @@keycache1.key_cache_block_size;
set global keycache1.key_buffer_size=1*1024*1024;
select @@keycache1.key_buffer_size;
select @@keycache1.key_cache_block_size;
set global keycache2.key_buffer_size=4*1024*1024;
select @@keycache2.key_buffer_size;
select @@keycache2.key_cache_block_size;
set global keycache1.key_buffer_size=0;
select @@keycache1.key_buffer_size;
select @@keycache1.key_cache_block_size;
select @@key_buffer_size;
select @@key_cache_block_size;
--disable_warnings
drop table if exists t1, t2;
--enable_warnings
create table t1 (p int primary key, a char(10));
create table t2 (p int primary key, i int, a char(10), key k1(i), key k2(a));
insert into t1 values (1, 'qqqq'), (11, 'yyyy');
insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
(3, 1, 'yyyy'), (4, 3, 'zzzz');
select * from t1;
select * from t2;
update t1 set p=2 where p=1;
update t2 set i=2 where i=1;
cache index t1 keys in keycache1;
explain select p from t1;
select p from t1;
explain select i from t2;
select i from t2;
explain select count(*) from t1, t2 where t1.p = t2.i;
select count(*) from t1, t2 where t1.p = t2.i;
cache index t2 keys in keycache1;
update t2 set p=p+1000, i=2 where a='qqqq';
cache index t2 keys in keycache2;
insert into t2 values (2000, 3, 'yyyy');
cache index t2 keys in keycache1;
update t2 set p=3000 where a='zzzz';
select * from t2;
explain select p from t2;
select p from t2;
explain select i from t2;
select i from t2;
explain select a from t2;
select a from t2;
select @@keycache2.key_buffer_size;
select @@keycache2.key_cache_block_size;
set global keycache2.key_buffer_size=0;
select @@keycache2.key_buffer_size;
select @@keycache2.key_cache_block_size;
update t2 set p=4000 where a='zzzz';
update t1 set p=p+1;
set global keycache1.key_buffer_size=0;
select * from t2;
select p from t2;
explain select i from t2;
select i from t2;
explain select a from t2;
select a from t2;
select * from t1;
select p from t1;
This diff is collapsed.
...@@ -229,6 +229,12 @@ int ha_myisam::open(const char *name, int mode, uint test_if_locked) ...@@ -229,6 +229,12 @@ int ha_myisam::open(const char *name, int mode, uint test_if_locked)
if (!(file=mi_open(name, mode, test_if_locked))) if (!(file=mi_open(name, mode, test_if_locked)))
return (my_errno ? my_errno : -1); return (my_errno ? my_errno : -1);
/* Synchronize key cache assignment of the handler */
KEY_CACHE_VAR *key_cache= table->key_cache ? table->key_cache :
&dflt_key_cache_var;
VOID(mi_extra(file, HA_EXTRA_SET_KEY_CACHE,
(void*) &key_cache->cache));
if (test_if_locked & (HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_TMP_TABLE)) if (test_if_locked & (HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_TMP_TABLE))
VOID(mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0)); VOID(mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0));
info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST); info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
...@@ -691,6 +697,131 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize) ...@@ -691,6 +697,131 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
} }
/*
Assign table indexes to a key cache.
*/
int ha_myisam::assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt)
{
uint len;
KEY_CACHE_VAR *old_key_cache;
KEY_CACHE_VAR *new_key_cache;
const char *errmsg=0;
int error= HA_ADMIN_OK;
ulonglong map= ~(ulonglong) 0;
TABLE_LIST *table_list= table->pos_in_table_list;
const char *new_key_cache_name= table_list->option ?
(const char *) table_list->option :
DEFAULT_KEY_CACHE_NAME;
KEY_CACHE_ASMT *key_cache_asmt= table->key_cache_asmt;
bool triggered= key_cache_asmt->triggered;
DBUG_ENTER("ha_myisam::assign_to_keycache");
VOID(pthread_mutex_lock(&LOCK_assign));
old_key_cache= key_cache_asmt->key_cache;
/* Check validity of the index references */
if (!triggered && table_list->use_index)
{
key_map kmap= get_key_map_from_key_list(table, table_list->use_index);
if (kmap == ~(key_map) 0)
{
errmsg= thd->net.last_error;
error= HA_ADMIN_FAILED;
goto err;
}
if (kmap)
map= kmap;
}
len= strlen(new_key_cache_name);
new_key_cache= get_or_create_key_cache(new_key_cache_name, len);
if (old_key_cache == new_key_cache)
{
/* Nothing to do: table is assigned to the same key cache */
goto ok;
}
if (!new_key_cache ||
(!new_key_cache->cache && ha_key_cache(new_key_cache)))
{
if (key_cache_asmt->triggered)
error= HA_ERR_OUT_OF_MEM;
else
{
char buf[ERRMSGSIZE];
my_snprintf(buf, ERRMSGSIZE,
"Failed to create key cache %s", new_key_cache_name);
errmsg= buf;
error= HA_ADMIN_FAILED;
}
goto err;
}
reassign_key_cache(key_cache_asmt, new_key_cache);
VOID(pthread_mutex_unlock(&LOCK_assign));
error= mi_assign_to_keycache(file, map, new_key_cache, &LOCK_assign);
VOID(pthread_mutex_lock(&LOCK_assign));
if (error && !key_cache_asmt->triggered)
{
switch (error) {
default:
char buf[ERRMSGSIZE+20];
my_snprintf(buf, ERRMSGSIZE,
"Failed to flush to index file (errno: %d)", my_errno);
errmsg= buf;
}
error= HA_ADMIN_CORRUPT;
goto err;
}
goto ok;
err:
if (!triggered)
{
MI_CHECK param;
myisamchk_init(&param);
param.thd= thd;
param.op_name= (char*)"assign_to_keycache";
param.db_name= table->table_cache_key;
param.table_name= table->table_name;
param.testflag= 0;
mi_check_print_error(&param, errmsg);
}
ok:
if (--key_cache_asmt->requests)
{
/* There is a queue of assignments for the table */
/* Remove the first member from the queue */
struct st_my_thread_var *last= key_cache_asmt->queue;
struct st_my_thread_var *thread= last->next;
if (thread->next == thread)
key_cache_asmt->queue= 0;
else
{
last->next= thread->next;
last->next->prev= &last->next;
thread->next= 0;
}
/* Signal the first waiting thread to proceed */
VOID(pthread_cond_signal(&thread->suspend));
}
key_cache_asmt->triggered= 0;
VOID(pthread_mutex_unlock(&LOCK_assign));
DBUG_RETURN(error);
}
/* /*
Preload pages of the index file for a table into the key cache. Preload pages of the index file for a table into the key cache.
*/ */
......
...@@ -128,6 +128,7 @@ class ha_myisam: public handler ...@@ -128,6 +128,7 @@ class ha_myisam: public handler
int optimize(THD* thd, HA_CHECK_OPT* check_opt); int optimize(THD* thd, HA_CHECK_OPT* check_opt);
int restore(THD* thd, HA_CHECK_OPT* check_opt); int restore(THD* thd, HA_CHECK_OPT* check_opt);
int backup(THD* thd, HA_CHECK_OPT* check_opt); int backup(THD* thd, HA_CHECK_OPT* check_opt);
int assign_to_keycache(THD* thd, HA_CHECK_OPT* check_opt);
int preload_keys(THD* thd, HA_CHECK_OPT* check_opt); int preload_keys(THD* thd, HA_CHECK_OPT* check_opt);
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
int dump(THD* thd, int fd); int dump(THD* thd, int fd);
......
...@@ -45,6 +45,12 @@ int ha_myisammrg::open(const char *name, int mode, uint test_if_locked) ...@@ -45,6 +45,12 @@ int ha_myisammrg::open(const char *name, int mode, uint test_if_locked)
DBUG_PRINT("info", ("ha_myisammrg::open exit %d", my_errno)); DBUG_PRINT("info", ("ha_myisammrg::open exit %d", my_errno));
return (my_errno ? my_errno : -1); return (my_errno ? my_errno : -1);
} }
/* Synchronize key cache assignment for the file */
KEY_CACHE_VAR *key_cache= table->key_cache ? table->key_cache :
&dflt_key_cache_var;
VOID(myrg_extra(file, HA_EXTRA_SET_KEY_CACHE,
(void*) &key_cache->cache));
DBUG_PRINT("info", ("ha_myisammrg::open myrg_extrafunc...")) DBUG_PRINT("info", ("ha_myisammrg::open myrg_extrafunc..."))
myrg_extrafunc(file, query_cache_invalidate_by_MyISAM_filename_ref); myrg_extrafunc(file, query_cache_invalidate_by_MyISAM_filename_ref);
if (!(test_if_locked == HA_OPEN_WAIT_IF_LOCKED || if (!(test_if_locked == HA_OPEN_WAIT_IF_LOCKED ||
......
...@@ -235,7 +235,7 @@ public: ...@@ -235,7 +235,7 @@ public:
longlong val_int(); longlong val_int();
enum Functype functype() const { return NE_FUNC; } enum Functype functype() const { return NE_FUNC; }
cond_result eq_cmp_result() const { return COND_FALSE; } cond_result eq_cmp_result() const { return COND_FALSE; }
optimize_type select_optimize() const { return OPTIMIZE_NONE; } optimize_type select_optimize() const { return OPTIMIZE_KEY; }
const char *func_name() const { return "<>"; } const char *func_name() const { return "<>"; }
}; };
......
This diff is collapsed.
This diff is collapsed.
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
TABLE *unused_tables; /* Used by mysql_test */ TABLE *unused_tables; /* Used by mysql_test */
HASH open_cache; /* Used by mysql_test */ HASH open_cache; /* Used by mysql_test */
HASH assign_cache;
static int open_unireg_entry(THD *thd,TABLE *entry,const char *db, static int open_unireg_entry(THD *thd,TABLE *entry,const char *db,
const char *name, const char *alias); const char *name, const char *alias);
...@@ -53,7 +54,6 @@ void table_cache_init(void) ...@@ -53,7 +54,6 @@ void table_cache_init(void)
mysql_rm_tmp_tables(); mysql_rm_tmp_tables();
} }
void table_cache_free(void) void table_cache_free(void)
{ {
DBUG_ENTER("table_cache_free"); DBUG_ENTER("table_cache_free");
...@@ -63,7 +63,6 @@ void table_cache_free(void) ...@@ -63,7 +63,6 @@ void table_cache_free(void)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
uint cached_tables(void) uint cached_tables(void)
{ {
return open_cache.records; return open_cache.records;
...@@ -764,6 +763,8 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, ...@@ -764,6 +763,8 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
reg1 TABLE *table; reg1 TABLE *table;
char key[MAX_DBKEY_LENGTH]; char key[MAX_DBKEY_LENGTH];
uint key_length; uint key_length;
KEY_CACHE_ASMT *key_cache_asmt;
KEY_CACHE_VAR *key_cache;
DBUG_ENTER("open_table"); DBUG_ENTER("open_table");
/* find a unused table in the open table cache */ /* find a unused table in the open table cache */
...@@ -804,6 +805,77 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, ...@@ -804,6 +805,77 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
my_printf_error(ER_TABLE_NOT_LOCKED,ER(ER_TABLE_NOT_LOCKED),MYF(0),alias); my_printf_error(ER_TABLE_NOT_LOCKED,ER(ER_TABLE_NOT_LOCKED),MYF(0),alias);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
VOID(pthread_mutex_lock(&LOCK_assign));
key_cache_asmt= (KEY_CACHE_ASMT*) hash_search(&assign_cache,
(byte*) key, key_length) ;
if (thd->open_options & HA_OPEN_TO_ASSIGN)
{
/* When executing a CACHE INDEX command*/
if (key_cache_asmt)
{
if (key_cache_asmt->requests++)
{
/* Another thread are assigning this table to some key cache*/
/* Put the assignment request into the queue of such requests */
struct st_my_thread_var *last;
struct st_my_thread_var *thread= thd->mysys_var;
if (! (last= key_cache_asmt->queue))
thread->next= thread;
else
{
thread->next= last->next;
last->next= thread;
}
key_cache_asmt->queue= thread;
/* Wait until the request can be processed */
do
{
VOID(pthread_cond_wait(&thread->suspend, &LOCK_assign));
}
while (thread->next);
}
}
else
{
/*
The table has not been explicitly assigned to any key cache yet;
by default it's assigned to the default key cache;
*/
if (!(key_cache_asmt=
(KEY_CACHE_ASMT *) my_malloc(sizeof(*key_cache_asmt),
MYF(MY_WME | MY_ZEROFILL))) ||
!(key_cache_asmt->db_name= my_strdup(db, MYF(MY_WME))) ||
!(key_cache_asmt->table_name= my_strdup(table_name, MYF(MY_WME))) ||
!(key_cache_asmt->table_key= my_memdup((const byte *) key,
key_length, MYF(MY_WME))))
{
VOID(pthread_mutex_unlock(&LOCK_assign));
if (key_cache_asmt)
{
if (key_cache_asmt->db_name)
my_free((gptr) key_cache_asmt->db_name, MYF(0));
if (key_cache_asmt->table_name)
my_free((gptr) key_cache_asmt->table_name, MYF(0));
my_free((gptr) key_cache_asmt, MYF(0));
}
DBUG_RETURN(NULL);
}
key_cache_asmt->key_length= key_length;
key_cache_asmt->key_cache= &dflt_key_cache_var;
VOID(hash_insert(&assign_cache, (byte *) key_cache_asmt));
key_cache_asmt->requests++;
}
key_cache_asmt->to_reassign= 0;
}
key_cache= key_cache_asmt ? key_cache_asmt->key_cache : &dflt_key_cache_var;
VOID(pthread_mutex_unlock(&LOCK_assign));
VOID(pthread_mutex_lock(&LOCK_open)); VOID(pthread_mutex_lock(&LOCK_open));
if (!thd->open_tables) if (!thd->open_tables)
...@@ -846,6 +918,9 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, ...@@ -846,6 +918,9 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
} }
table->prev->next=table->next; /* Remove from unused list */ table->prev->next=table->next; /* Remove from unused list */
table->next->prev=table->prev; table->next->prev=table->prev;
table->key_cache= key_cache;
table->key_cache_asmt= key_cache_asmt;
} }
else else
{ {
...@@ -859,6 +934,8 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, ...@@ -859,6 +934,8 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
VOID(pthread_mutex_unlock(&LOCK_open)); VOID(pthread_mutex_unlock(&LOCK_open));
DBUG_RETURN(NULL); DBUG_RETURN(NULL);
} }
table->key_cache= key_cache;
table->key_cache_asmt= key_cache_asmt;
if (open_unireg_entry(thd, table,db,table_name,alias) || if (open_unireg_entry(thd, table,db,table_name,alias) ||
!(table->table_cache_key=memdup_root(&table->mem_root,(char*) key, !(table->table_cache_key=memdup_root(&table->mem_root,(char*) key,
key_length))) key_length)))
...@@ -877,6 +954,8 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, ...@@ -877,6 +954,8 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
table->in_use=thd; table->in_use=thd;
check_unused(); check_unused();
VOID(pthread_mutex_unlock(&LOCK_open)); VOID(pthread_mutex_unlock(&LOCK_open));
if (refresh) if (refresh)
{ {
...@@ -1648,6 +1727,54 @@ bool rm_temporary_table(enum db_type base, char *path) ...@@ -1648,6 +1727,54 @@ bool rm_temporary_table(enum db_type base, char *path)
DBUG_RETURN(error); DBUG_RETURN(error);
} }
static void free_assign_entry(KEY_CACHE_ASMT *key_cache_asmt)
{
DBUG_ENTER("free_assign_entry");
my_free((gptr) key_cache_asmt->table_key, MYF(0));
my_free((gptr) key_cache_asmt, MYF(0));
DBUG_VOID_RETURN;
}
static byte *assign_cache_key(const byte *record,uint *length,
my_bool not_used __attribute__((unused)))
{
KEY_CACHE_ASMT *entry=(KEY_CACHE_ASMT *) record;
*length=entry->key_length;
return (byte*) entry->table_key;
}
void assign_cache_init(void)
{
VOID(hash_init(&assign_cache, &my_charset_bin,
table_cache_size+16, 0, 0, assign_cache_key,
(hash_free_key) free_assign_entry,0));
}
void assign_cache_free(void)
{
DBUG_ENTER("assign_cache_free");
hash_free(&assign_cache);
DBUG_VOID_RETURN;
}
void reassign_key_cache(KEY_CACHE_ASMT *key_cache_asmt,
KEY_CACHE_VAR *new_key_cache)
{
if (key_cache_asmt->prev)
{
/* Unlink key_cache_asmt from the assignment list for the old key cache */
if ((*key_cache_asmt->prev= key_cache_asmt->next))
key_cache_asmt->next->prev= key_cache_asmt->prev;
}
/* Link key_cache_asmt into the assignment list for the new key cache */
key_cache_asmt->prev= &new_key_cache->assign_list;
if ((key_cache_asmt->next= new_key_cache->assign_list))
key_cache_asmt->next->prev= &key_cache_asmt->next;
new_key_cache->assign_list= key_cache_asmt;
key_cache_asmt->key_cache= new_key_cache;
}
/***************************************************************************** /*****************************************************************************
** find field in list or tables. if field is unqualifed and unique, ** find field in list or tables. if field is unqualifed and unique,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -319,8 +319,9 @@ w_requests: %10lu\n\ ...@@ -319,8 +319,9 @@ w_requests: %10lu\n\
writes: %10lu\n\ writes: %10lu\n\
r_requests: %10lu\n\ r_requests: %10lu\n\
reads: %10lu\n", reads: %10lu\n",
my_blocks_used,my_blocks_changed,my_cache_w_requests, dflt_key_cache_var.blocks_used,dflt_key_cache_var.blocks_changed,
my_cache_write,my_cache_r_requests,my_cache_read); dflt_key_cache_var.cache_w_requests,dflt_key_cache_var.cache_write,
dflt_key_cache_var.cache_r_requests,dflt_key_cache_var.cache_read);
pthread_mutex_unlock(&THR_LOCK_keycache); pthread_mutex_unlock(&THR_LOCK_keycache);
if (thd) if (thd)
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment