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 @@
#define HA_OPEN_DELAY_KEY_WRITE 8 /* Don't update index */
#define HA_OPEN_ABORT_IF_CRASHED 16
#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 */
......@@ -124,7 +125,8 @@ enum ha_extra_function {
HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE, /* Cursor will not be used for update */
HA_EXTRA_PREPARE_FOR_DELETE,
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() */
......
......@@ -558,6 +558,9 @@ typedef SOCKET_SIZE_TYPE size_socket;
#define RECORD_CACHE_SIZE (uint) (64*1024-MALLOC_OVERHEAD)
/* Typical key cash */
#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 */
......
......@@ -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_GIVE_USER_A_MESSAGE 10 /* Every 10 times of prev */
#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 */
#define MY_KEEP_PREALLOC 1
......@@ -266,7 +264,8 @@ enum cache_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 */
......@@ -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 - \
*(info)->current_pos)
/* key_cache_variables */
typedef struct st_keycache
{
ulonglong size;
} KEY_CACHE;
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>
/* Prototypes for mysys and my_func functions */
......@@ -649,16 +680,26 @@ extern int flush_write_cache(RECORD_CACHE *info);
extern long my_clock(void);
extern sig_handler sigtstp_handler(int signal_number);
extern void handle_recived_signals(void);
extern int init_key_cache(ulong use_mem);
extern int resize_key_cache(ulong use_mem);
extern byte *key_cache_read(File file,my_off_t filepos,byte* buff,uint length,
extern int init_key_cache(KEY_CACHE_HANDLE *pkeycache,
uint key_cache_block_size,
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);
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);
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);
extern int flush_key_blocks(int file, enum flush_type type);
extern void end_key_cache(void);
extern int flush_key_blocks(KEY_CACHE_HANDLE keycache,
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 void my_string_ptr_sort(void *base,uint items,size_s size);
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,
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_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);
#ifdef __cplusplus
......
......@@ -50,7 +50,7 @@ int nisam_lock_database(N_INFO *info, int lock_type)
else
count= --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;
if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
if (end_io_cache(&info->rec_cache))
......@@ -329,7 +329,7 @@ int _nisam_test_if_changed(register N_INFO *info)
share->state.uniq != info->last_uniq)
{ /* Keyfile has changed */
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;
info->last_loop= share->state.loop;
info->last_uniq= share->state.uniq;
......
......@@ -27,10 +27,11 @@ uchar *_nisam_fetch_keypage(register N_INFO *info, N_KEYDEF *keyinfo,
my_off_t page, uchar *buff, int return_buffer)
{
uchar *tmp;
tmp=(uchar*) key_cache_read(info->s->kfile,page,(byte*) buff,
(uint) keyinfo->base.block_length,
(uint) keyinfo->base.block_length,
return_buffer);
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,
return_buffer);
if (tmp == info->buff)
{
info->update|=HA_STATE_BUFF_SAVED;
......@@ -83,9 +84,11 @@ int _nisam_write_keypage(register N_INFO *info, register N_KEYDEF *keyinfo,
length=keyinfo->base.block_length;
}
#endif
return (key_cache_write(info->s->kfile,page,(byte*) buff,length,
(uint) keyinfo->base.block_length,
(int) (info->lock_type != F_UNLCK)));
return (key_cache_write(*dflt_keycache,
info->s->kfile,page,DFLT_INIT_HITS,
(byte*) buff,length,
(uint) keyinfo->base.block_length,
(int) (info->lock_type != F_UNLCK)));
} /* nisam_write_keypage */
......@@ -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];
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),
(uint) keyinfo->base.block_length,
(int) (info->lock_type != F_UNLCK)));
......@@ -126,7 +131,8 @@ ulong _nisam_new(register N_INFO *info, N_KEYDEF *keyinfo)
}
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],
(uint) sizeof(long),
(uint) keyinfo->base.block_length,0))
......
......@@ -56,7 +56,8 @@ int nisam_close(register N_INFO *info)
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;
if (share->kfile >= 0 && my_close(share->kfile,MYF(0)))
error = my_errno;
......
......@@ -516,7 +516,8 @@ static int nisamchk(my_string filename)
if (!rep_quick)
{
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,
READ_CACHE,share->pack.header_length,1,
MYF(MY_WME)));
......@@ -1459,7 +1460,8 @@ my_string name;
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,
READ_CACHE,share->pack.header_length,1,MYF(MY_WME)))
goto err;
......@@ -1887,12 +1889,12 @@ static void lock_memory(void)
static int flush_blocks(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);
return(1);
}
end_key_cache();
end_key_cache(dflt_keycache,1);
return 0;
} /* flush_blocks */
......@@ -1936,7 +1938,8 @@ int write_info;
if (share->state.key_root[sort_key] == NI_POS_ERROR)
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,
WRITE_CACHE,share->pack.header_length,1,
MYF(MY_WME | MY_WAIT_IF_FULL)))
......
......@@ -329,8 +329,8 @@ static int examine_log(my_string file_name, char **table_names)
bzero((gptr) com_count,sizeof(com_count));
init_tree(&tree,0,0,sizeof(file_info),(qsort_cmp2) file_info_compare,1,
(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;
while (access_time++ != number_of_commands &&
!my_b_read(&cache,(byte*) head,9))
......@@ -622,7 +622,7 @@ static int examine_log(my_string file_name, char **table_names)
goto end;
}
}
end_key_cache();
end_key_cache(dflt_keycache,1);
delete_tree(&tree);
VOID(end_io_cache(&cache));
VOID(my_close(file,MYF(0)));
......@@ -642,7 +642,7 @@ static int examine_log(my_string file_name, char **table_names)
llstr(isamlog_filepos,llbuff)));
fflush(stderr);
end:
end_key_cache();
end_key_cache(dflt_keycache,1);
delete_tree(&tree);
VOID(end_io_cache(&cache));
VOID(my_close(file,MYF(0)));
......
......@@ -48,7 +48,7 @@ int nisam_panic(enum ha_panic_function flag)
if (info->s->base.options & HA_OPTION_READ_ONLY_DATA)
break;
#endif
if (flush_key_blocks(info->s->kfile,FLUSH_RELEASE))
if (flush_key_blocks(*dflt_keycache,info->s->kfile,FLUSH_RELEASE))
error=my_errno;
if (info->opt_flag & WRITE_CACHE_USED)
if (flush_io_cache(&info->rec_cache))
......
......@@ -156,7 +156,7 @@ int main(int argc, char *argv[])
goto err;
printf("- Writing key:s\n");
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)
nisam_lock_database(file,F_WRLCK);
if (write_cacheing)
......@@ -674,7 +674,7 @@ end:
puts("Locking used");
if (use_blob)
puts("blobs used");
end_key_cache();
end_key_cache(&dflt_keycache,1);
if (blob_buffer)
my_free(blob_buffer,MYF(0));
my_end(MY_CHECK_ERROR | MY_GIVE_INFO);
......
......@@ -173,7 +173,7 @@ void start_test(int id)
exit(1);
}
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);
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 \
mi_range.c mi_dbug.c mi_checksum.c mi_log.c \
mi_changed.c mi_static.c mi_delete_all.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_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
......
......@@ -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 ||
next_link & (info->s->blocksize-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)))
DBUG_RETURN(1);
next_link=mi_sizekorr(buff);
......@@ -259,7 +261,8 @@ int chk_size(MI_CHECK *param, register MI_INFO *info)
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));
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)
if (share->state.key_root[key] == HA_OFFSET_ERROR &&
(info->state->records == 0 || keyinfo->flag & HA_FULLTEXT))
continue;
if (!_mi_fetch_keypage(info,keyinfo,share->state.key_root[key],info->buff,
0))
if (!_mi_fetch_keypage(info,keyinfo,share->state.key_root[key],
DFLT_INIT_HITS,info->buff,0))
{
mi_check_print_error(param,"Can't read indexpage from filepos: %s",
llstr(share->state.key_root[key],buff));
......@@ -548,7 +551,8 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
info->state->key_file_length=(max_length &
~ (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));
goto err;
......@@ -1120,7 +1124,8 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
param->testflag|=T_REP; /* for easy checking */
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,
(uint) param->read_buffer_length,
......@@ -1441,7 +1446,8 @@ int movepoint(register MI_INFO *info, byte *record, my_off_t oldpos,
nod_flag=mi_test_if_nod(info->buff);
_mi_dpointer(info,info->int_keypos-nod_flag-
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);
}
else
......@@ -1478,13 +1484,13 @@ void lock_memory(MI_CHECK *param __attribute__((unused)))
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);
return(1);
}
if (!param->using_global_keycache)
end_key_cache();
end_key_cache(dflt_keycache,1);
return 0;
} /* flush_blocks */
......@@ -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_blocks(share->kfile, FLUSH_IGNORE_CHANGED);
flush_key_blocks(*share->keycache,share->kfile, FLUSH_IGNORE_CHANGED);
share->state.version=(ulong) time((time_t*) 0);
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,
mi_check_print_error(param,"Not Enough memory");
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",
llstr(pagepos,llbuff));
......@@ -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
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 */
for (i=0 ; i < share->base.keys ; i++)
share->state.key_root[i]= HA_OFFSET_ERROR;
......@@ -1859,7 +1865,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
}
else
{
if (flush_key_blocks(share->kfile, FLUSH_FORCE_WRITE))
if (flush_key_blocks(*share->keycache,share->kfile, FLUSH_FORCE_WRITE))
goto err;
key_map= ~key_map; /* Create the missing keys */
}
......@@ -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
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 */
for (i=0 ; i < share->base.keys ; i++)
share->state.key_root[i]= HA_OFFSET_ERROR;
......@@ -2222,7 +2228,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
}
else
{
if (flush_key_blocks(share->kfile, FLUSH_FORCE_WRITE))
if (flush_key_blocks(*share->keycache,share->kfile, FLUSH_FORCE_WRITE))
goto err;
key_map= ~key_map; /* Create the missing keys */
}
......@@ -3337,13 +3343,13 @@ static int sort_insert_key(MI_SORT_PARAM *sort_param,
bzero((byte*) anc_buff+key_block->last_length,
keyinfo->block_length- key_block->last_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);
/* 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 (_mi_write_keypage(info, keyinfo, filepos, anc_buff))
if (_mi_write_keypage(info, keyinfo, filepos, DFLT_INIT_HITS, anc_buff))
DBUG_RETURN(1);
}
else if (my_pwrite(info->s->kfile,(byte*) anc_buff,
......@@ -3441,13 +3447,14 @@ int flush_pending_blocks(MI_SORT_PARAM *sort_param)
_mi_kpointer(info,key_block->end_pos,filepos);
key_file_length=info->state->key_file_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);
/* 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 (_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);
}
else if (my_pwrite(info->s->kfile,(byte*) key_block->buff,
......
......@@ -64,7 +64,7 @@ int mi_close(register MI_INFO *info)
if (flag)
{
if (share->kfile >= 0 &&
flush_key_blocks(share->kfile,
flush_key_blocks(*share->keycache,share->kfile,
share->temporary ? FLUSH_IGNORE_CHANGED :
FLUSH_RELEASE))
error=my_errno;
......
......@@ -155,7 +155,7 @@ static int _mi_ck_real_delete(register MI_INFO *info, MI_KEYDEF *keyinfo,
DBUG_RETURN(my_errno=ENOMEM);
}
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;
goto err;
......@@ -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);
else
*root=HA_OFFSET_ERROR;
if (_mi_dispose(info,keyinfo,old_root))
if (_mi_dispose(info,keyinfo,old_root,DFLT_INIT_HITS))
error= -1;
}
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:
......@@ -253,7 +254,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
{
/* the last entry in sub-tree */
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 */
}
else
......@@ -268,7 +269,8 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
subkeys++;
ft_intXstore(kpos, subkeys);
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_RETURN(ret_value);
}
......@@ -287,7 +289,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
DBUG_PRINT("exit",("Return: %d",-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;
}
......@@ -319,7 +321,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
mi_putint(anc_buff,length,nod_flag);
if (!nod_flag)
{ /* 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_RETURN(-1);
......@@ -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;
}
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
{
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,
if (!(next_buff= (uchar*) my_alloca((uint) keyinfo->block_length+
MI_MAX_KEY_BUFF*2)))
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;
else
{
......@@ -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);
}
}
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;
}
my_afree((byte*) next_buff);
......@@ -436,7 +438,7 @@ static int del(register MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *key,
/* Remove last key from leaf page */
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;
/* 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,
goto err;
}
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;
buff_length=mi_getint(buff);
DBUG_DUMP("next",(byte*) buff,buff_length);
......@@ -563,7 +565,7 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo,
if (buff_length <= keyinfo->block_length)
{ /* Keys in one page */
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;
}
else
......@@ -612,10 +614,10 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo,
(*keyinfo->store_key)(keyinfo,buff+p_length,&s_temp);
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;
}
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;
DBUG_RETURN(anc_length <= ((info->quick_mode ? MI_MIN_BLOCK_LENGTH :
(uint) keyinfo->underflow_block_length)));
......@@ -627,7 +629,7 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo,
if (!keypos)
goto err;
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;
buff_length=mi_getint(buff);
endpos=buff+buff_length;
......@@ -671,7 +673,7 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo,
if (buff_length <= keyinfo->block_length)
{ /* Keys in one page */
if (_mi_dispose(info,keyinfo,leaf_page))
if (_mi_dispose(info,keyinfo,leaf_page,DFLT_INIT_HITS))
goto err;
}
else
......@@ -718,11 +720,11 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo,
(size_t) length);
(*keyinfo->store_key)(keyinfo,leaf_buff+p_length,&s_temp);
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;
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;
DBUG_RETURN(anc_length <= (uint) keyinfo->block_length/2);
err:
......
......@@ -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
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)) ||
my_chsize(share->kfile, share->base.keystart, 0, MYF(MY_WME)) )
goto err;
......
......@@ -283,7 +283,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
#ifdef __WIN__
/* Close the isam and data files as Win32 can't drop an open table */
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 ?
FLUSH_RELEASE : FLUSH_IGNORE_CHANGED)))
{
......@@ -329,7 +329,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
break;
case HA_EXTRA_FLUSH:
if (!share->temporary)
flush_key_blocks(share->kfile,FLUSH_KEEP);
flush_key_blocks(*share->keycache,share->kfile,FLUSH_KEEP);
#ifdef HAVE_PWRITE
_mi_decrement_open_count(info);
#endif
......@@ -374,6 +374,9 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
case HA_EXTRA_PRELOAD_BUFFER_SIZE:
info->preload_buff_size= *((ulong *) extra_arg);
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_NO_KEY_CACHE:
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)
uint count;
MYISAM_SHARE *share=info->s;
uint flag;
uint switch_fl= 0;
DBUG_ENTER("mi_lock_database");
DBUG_PRINT("info",("lock_type: %d", lock_type));
......@@ -60,12 +61,21 @@ int mi_lock_database(MI_INFO *info, int lock_type)
else
count= --share->w_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 &&
!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;
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 (end_io_cache(&info->rec_cache))
......@@ -400,7 +410,7 @@ int _mi_test_if_changed(register MI_INFO *info)
{ /* Keyfile has changed */
DBUG_PRINT("info",("index file changed"));
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;
info->last_unique= share->state.unique;
info->last_loop= share->state.update_count;
......
......@@ -24,14 +24,16 @@
/* Fetch a key-page in memory */
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;
uint page_size;
DBUG_ENTER("_mi_fetch_keypage");
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,
return_buffer);
......@@ -61,7 +63,7 @@ uchar *_mi_fetch_keypage(register MI_INFO *info, MI_KEYDEF *keyinfo,
/* Write a key-page on disk */
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;
DBUG_ENTER("_mi_write_keypage");
......@@ -92,7 +94,8 @@ int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo,
length=keyinfo->block_length;
}
#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,
(int) ((info->lock_type != F_UNLCK) ||
info->s->delay_key_write))));
......@@ -101,7 +104,8 @@ int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo,
/* 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;
char buff[8];
......@@ -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;
mi_sizestore(buff,old_link);
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),
(uint) keyinfo->block_length,
(int) (info->lock_type != F_UNLCK)));
......@@ -121,7 +126,7 @@ int _mi_dispose(register MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t pos)
/* 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;
char buff[8];
......@@ -140,7 +145,8 @@ my_off_t _mi_new(register MI_INFO *info, MI_KEYDEF *keyinfo)
}
else
{
if (!key_cache_read(info->s->kfile,pos,
if (!key_cache_read(*info->s->keycache,
info->s->kfile, pos, level,
buff,
(uint) sizeof(buff),
(uint) keyinfo->block_length,0))
......
......@@ -48,7 +48,7 @@ int mi_panic(enum ha_panic_function flag)
if (info->s->options & HA_OPTION_READ_ONLY_DATA)
break;
#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;
if (info->opt_flag & WRITE_CACHE_USED)
if (flush_io_cache(&info->rec_cache))
......
......@@ -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))))
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;
do
......@@ -87,7 +87,9 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves)
{
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;
}
pos+= block_length;
......@@ -97,7 +99,9 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves)
}
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;
pos+= length;
}
......
......@@ -142,7 +142,7 @@ static double _mi_search_pos(register MI_INFO *info,
if (pos == HA_OFFSET_ERROR)
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;
flag=(*keyinfo->bin_search)(info,keyinfo,buff,key,key_len,nextflag,
&keypos,info->lastkey, &after_key);
......
......@@ -76,7 +76,7 @@ int _mi_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
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)))))
goto err;
DBUG_DUMP("page",(byte*) buff,mi_getint(buff));
......@@ -119,7 +119,7 @@ int _mi_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
if (pos != info->last_keypage)
{
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)))))
goto err;
keypos=buff+(keypos-old_buff);
......@@ -1108,7 +1108,7 @@ int _mi_search_next(register MI_INFO *info, register MI_KEYDEF *keyinfo,
if (info->buff_used)
{
if (!_mi_fetch_keypage(info,keyinfo,info->last_search_keypage,
info->buff,0))
DFLT_INIT_HITS,info->buff,0))
DBUG_RETURN(-1);
info->buff_used=0;
}
......@@ -1177,7 +1177,7 @@ int _mi_search_first(register MI_INFO *info, register MI_KEYDEF *keyinfo,
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;
DBUG_RETURN(-1);
......@@ -1220,7 +1220,7 @@ int _mi_search_last(register MI_INFO *info, register MI_KEYDEF *keyinfo,
buff=info->buff;
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;
DBUG_RETURN(-1);
......
......@@ -50,7 +50,7 @@ int main(int argc,char *argv[])
MY_INIT(argv[0]);
my_init();
if (key_cacheing)
init_key_cache(IO_SIZE*16);
init_key_cache(dflt_keycache,512,IO_SIZE*16,0);
get_options(argc,argv);
exit(run_test("test1"));
......
......@@ -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,
create_flag=0;
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 use_blob=0;
......@@ -214,7 +215,7 @@ int main(int argc, char *argv[])
if (!silent)
printf("- Writing key:s\n");
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)
mi_lock_database(file,F_WRLCK);
if (write_cacheing)
......@@ -274,7 +275,7 @@ int main(int argc, char *argv[])
goto end;
}
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)
......@@ -816,16 +817,19 @@ end:
puts("Locking used");
if (use_blob)
puts("blobs used");
#if 0
printf("key cache status: \n\
blocks used:%10lu\n\
w_requests: %10lu\n\
writes: %10lu\n\
r_requests: %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);
#endif
}
end_key_cache();
end_key_cache(dflt_keycache,1);
if (blob_buffer)
my_free(blob_buffer,MYF(0));
my_end(silent ? MY_CHECK_ERROR : MY_CHECK_ERROR | MY_GIVE_INFO);
......
......@@ -177,7 +177,7 @@ void start_test(int id)
exit(1);
}
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);
for (error=i=0 ; i < tests && !error; i++)
......
......@@ -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);
(*keyinfo->store_key)(keyinfo,info->buff+2+nod_flag,&s_temp);
info->buff_used=info->page_changed=1; /* info->buff is used */
if ((*root= _mi_new(info,keyinfo)) == HA_OFFSET_ERROR ||
_mi_write_keypage(info,keyinfo,*root,info->buff))
if ((*root= _mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR ||
_mi_write_keypage(info,keyinfo,*root,DFLT_INIT_HITS,info->buff))
DBUG_RETURN(-1);
DBUG_RETURN(0);
} /* _mi_enlarge_root */
......@@ -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+
MI_MAX_KEY_BUFF*2)))
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;
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,
subkeys--; /* should there be underflow protection ? */
ft_intXstore(keypos, subkeys);
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);
DBUG_RETURN(error);
}
......@@ -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,
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;
}
my_afree((byte*) temp_buff);
......@@ -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 */
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);
_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,
(*keyinfo->store_key)(keyinfo,info->buff+key_ref_length,&s_temp);
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_DUMP("key",(byte*) key,_mi_keylength(keyinfo,key));
DBUG_RETURN(2); /* Middle key up */
......@@ -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));
} /* 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;
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,
memcpy((byte*) buff+2,(byte*) pos+k_length,(size_t) length);
}
if (_mi_write_keypage(info,keyinfo,next_page,info->buff) ||
_mi_write_keypage(info,keyinfo,father_page,father_buff))
if (_mi_write_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,info->buff) ||
_mi_write_keypage(info,keyinfo,father_page,DFLT_INIT_HITS,father_buff))
goto err;
DBUG_RETURN(0);
}
......@@ -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 ? 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;
_mi_kpointer(info,key+k_length,new_pos);
if (_mi_write_keypage(info,keyinfo,(right ? new_pos : next_page),
info->buff) ||
_mi_write_keypage(info,keyinfo,(right ? next_page : new_pos),extra_buff))
DFLT_INIT_HITS,info->buff) ||
_mi_write_keypage(info,keyinfo,(right ? next_page : new_pos),
DFLT_INIT_HITS,extra_buff))
goto err;
DBUG_RETURN(1); /* Middle key up */
......
......@@ -44,6 +44,7 @@ static const char *load_default_groups[]= { "myisamchk", 0 };
static const char *set_charset_name, *opt_tmpdir;
static CHARSET_INFO *set_charset;
static long opt_myisam_block_size;
static long opt_key_cache_block_size;
static const char *my_progname_short;
static int stopwords_inited= 0;
static MY_TMPDIR myisamchk_tmpdir;
......@@ -148,7 +149,8 @@ int main(int argc, char **argv)
enum options {
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_SORT_KEY_BLOCKS, OPT_DECODE_BITS, OPT_FT_MIN_WORD_LEN,
OPT_FT_MAX_WORD_LEN, OPT_FT_MAX_WORD_LEN_FOR_SORT
......@@ -283,6 +285,11 @@ static struct my_option my_long_options[] =
(gptr*) &check_param.use_buffers, (gptr*) &check_param.use_buffers, 0,
GET_ULONG, REQUIRED_ARG, (long) USE_BUFFER_INIT, (long) MALLOC_OVERHEAD,
(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, "",
(gptr*) &opt_myisam_block_size, (gptr*) &opt_myisam_block_size, 0,
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)
!(param->testflag & (T_FAST | T_FORCE_CREATE)))
{
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,
(uint) param->read_buffer_length,
READ_CACHE,
......@@ -1448,7 +1456,8 @@ static int mi_sort_records(MI_CHECK *param,
if (share->state.key_root[sort_key] == HA_OFFSET_ERROR)
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,
WRITE_CACHE,share->pack.header_length,1,
MYF(MY_WME | MY_WAIT_IF_FULL)))
......
......@@ -166,6 +166,8 @@ typedef struct st_mi_isam_share { /* Shared between opens */
char *data_file_name, /* Resolved path names from symlinks */
*index_file_name;
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;
uint16 *decode_tables;
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,
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 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,
uchar *buff);
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, uchar *buff);
extern int _mi_dispose(MI_INFO *info,MI_KEYDEF *keyinfo,my_off_t pos,
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,
const byte *record,my_off_t filepos);
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)
bzero((gptr) com_count,sizeof(com_count));
init_tree(&tree,0,0,sizeof(file_info),(qsort_cmp2) file_info_compare,1,
(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;
while (access_time++ != number_of_commands &&
......@@ -647,7 +648,7 @@ static int examine_log(my_string file_name, char **table_names)
goto end;
}
}
end_key_cache();
end_key_cache(dflt_keycache,1);
delete_tree(&tree);
VOID(end_io_cache(&cache));
VOID(my_close(file,MYF(0)));
......@@ -667,7 +668,7 @@ static int examine_log(my_string file_name, char **table_names)
llstr(isamlog_filepos,llbuff)));
fflush(stderr);
end:
end_key_cache();
end_key_cache(dflt_keycache,1);
delete_tree(&tree);
VOID(end_io_cache(&cache));
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
my_errno = HA_ERR_OUT_OF_MEM;
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;
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,
if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length)))
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;
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,
my_errno = HA_ERR_OUT_OF_MEM;
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;
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,
case 0: /* child was not split */
{
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 ok;
}
......@@ -462,7 +462,7 @@ static int rtree_insert_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
goto err1;
res = rtree_add_key(info, keyinfo, new_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 ok;
}
......@@ -476,7 +476,7 @@ static int rtree_insert_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
else
{
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 ok;
}
......@@ -509,12 +509,12 @@ static int rtree_insert_level(MI_INFO *info, uint keynr, uchar *key,
{
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;
info->buff_used = 1;
mi_putint(info->buff, 2, 0);
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;
info->s->state.key_root[keynr] = old_root;
return res;
......@@ -542,7 +542,8 @@ static int rtree_insert_level(MI_INFO *info, uint keynr, uchar *key,
}
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;
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,
if (rtree_add_key(info, keyinfo, new_key, key_length, new_root_buf, NULL)
== -1)
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;
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,
my_errno = HA_ERR_OUT_OF_MEM;
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;
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,
if (rtree_set_key_mbr(info, keyinfo, k, key_length,
_mi_kpos(nod_flag, k)))
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;
}
else
......@@ -672,7 +675,8 @@ static int rtree_delete_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
level + 1))
goto err1;
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;
*page_size = mi_getint(page_buf);
}
......@@ -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 */
{
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;
*page_size = mi_getint(page_buf);
res = 0;
......@@ -711,13 +716,13 @@ static int rtree_delete_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
{
/* last key in the leaf */
res = 2;
if (_mi_dispose(info, keyinfo, page))
if (_mi_dispose(info, keyinfo, page, DFLT_INIT_HITS))
goto err1;
}
else
{
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 ok;
......@@ -783,7 +788,7 @@ int rtree_delete(MI_INFO *info, uint keynr, uchar *key, uint key_length)
goto err1;
}
if (!_mi_fetch_keypage(info, keyinfo, ReinsertList.pages[i].offs,
page_buf, 0))
DFLT_INIT_HITS, page_buf, 0))
goto err1;
nod_flag = mi_test_if_nod(page_buf);
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)
}
}
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;
}
if (ReinsertList.pages)
......@@ -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 */
if ((old_root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
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;
nod_flag = mi_test_if_nod(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)
{
my_off_t new_root = _mi_kpos(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;
info->s->state.key_root[keynr] = new_root;
}
......@@ -863,7 +870,7 @@ ha_rows rtree_estimate(MI_INFO *info, uint keynr, uchar *key,
return HA_POS_ERROR;
if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length)))
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;
nod_flag = mi_test_if_nod(page_buf);
......
......@@ -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,
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 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,
mi_putint(page, 2 + n1 * 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;
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);
......
......@@ -514,7 +514,7 @@ id select_type table type possible_keys key key_len ref rows Extra
explain
select min(a1) from t1 where a1 != 'KKK';
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
select max(a3) from t1 where a2 < 2 and a3 < 'SEA';
id select_type table type possible_keys key key_len ref rows Extra
......@@ -560,7 +560,7 @@ explain
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
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;
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;
......
......@@ -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
SELECT @@skr.table_type="test";
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;
......@@ -40,3 +40,83 @@ SET @@global.key_buffer_size=@save_key_buffer;
SELECT @@default.key_buffer_size;
--error 1271
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.
......@@ -228,6 +228,12 @@ int ha_myisam::open(const char *name, int mode, uint test_if_locked)
{
if (!(file=mi_open(name, mode, test_if_locked)))
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))
VOID(mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0));
......@@ -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.
*/
......
......@@ -128,6 +128,7 @@ class ha_myisam: public handler
int optimize(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 assign_to_keycache(THD* thd, HA_CHECK_OPT* check_opt);
int preload_keys(THD* thd, HA_CHECK_OPT* check_opt);
#ifdef HAVE_REPLICATION
int dump(THD* thd, int fd);
......
......@@ -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));
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..."))
myrg_extrafunc(file, query_cache_invalidate_by_MyISAM_filename_ref);
if (!(test_if_locked == HA_OPEN_WAIT_IF_LOCKED ||
......
......@@ -235,7 +235,7 @@ public:
longlong val_int();
enum Functype functype() const { return NE_FUNC; }
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 "<>"; }
};
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -1168,7 +1168,16 @@ TABLE_LIST* st_select_lex_node::get_table_list() { return 0; }
List<Item>* st_select_lex_node::get_item_list() { return 0; }
List<String>* st_select_lex_node::get_use_index() { return 0; }
List<String>* st_select_lex_node::get_ignore_index() { return 0; }
TABLE_LIST *st_select_lex_node::add_table_to_list(THD *thd, Table_ident *table,
LEX_STRING *alias,
ulong table_join_options,
thr_lock_type flags,
List<String> *use_index,
List<String> *ignore_index,
LEX_STRING *option)
{
return 0;
}
ulong st_select_lex_node::get_table_join_options()
{
return 0;
......@@ -1192,6 +1201,28 @@ bool st_select_lex::test_limit()
return(0);
}
/*
Interface method of table list creation for query
......
......@@ -59,7 +59,8 @@ enum enum_sql_command {
SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_ALTER_DB,
SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT,
SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION,
SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK, SQLCOM_PRELOAD_KEYS,
SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK,
SQLCOM_ASSIGN_TO_KEYCACHE, SQLCOM_PRELOAD_KEYS,
SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_ANALYZE,
SQLCOM_ROLLBACK, SQLCOM_ROLLBACK_TO_SAVEPOINT,
SQLCOM_COMMIT, SQLCOM_SAVEPOINT,
......@@ -252,6 +253,13 @@ public:
virtual List<String>* get_use_index();
virtual List<String>* get_ignore_index();
virtual ulong get_table_join_options();
virtual TABLE_LIST *add_table_to_list(THD *thd, Table_ident *table,
LEX_STRING *alias,
ulong table_options,
thr_lock_type flags= TL_UNLOCK,
List<String> *use_index= 0,
List<String> *ignore_index= 0,
LEX_STRING *option= 0);
virtual void set_lock_for_tables(thr_lock_type lock_type) {}
friend class st_select_lex_unit;
......@@ -437,8 +445,8 @@ public:
ulong table_options,
thr_lock_type flags= TL_UNLOCK,
List<String> *use_index= 0,
List<String> *ignore_index= 0);
List<String> *ignore_index= 0,
LEX_STRING *option= 0);
TABLE_LIST* get_table_list();
List<Item>* get_item_list();
List<String>* get_use_index();
......
......@@ -1903,6 +1903,14 @@ mysql_execute_command(THD *thd)
res = mysql_restore_table(thd, tables);
break;
}
case SQLCOM_ASSIGN_TO_KEYCACHE:
{
if (check_db_used(thd, tables) ||
check_access(thd, INDEX_ACL, tables->db, &tables->grant.privilege))
goto error;
res = mysql_assign_to_keycache(thd, tables);
break;
}
case SQLCOM_PRELOAD_KEYS:
{
if (check_db_used(thd, tables) ||
......@@ -4204,7 +4212,8 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
ulong table_options,
thr_lock_type lock_type,
List<String> *use_index,
List<String> *ignore_index)
List<String> *ignore_index,
LEX_STRING *option)
{
register TABLE_LIST *ptr;
char *alias_str;
......@@ -4265,7 +4274,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
if (ignore_index)
ptr->ignore_index=(List<String> *) thd->memdup((gptr) ignore_index,
sizeof(*ignore_index));
ptr->option= option ? option->str : 0;
/* check that used name is unique */
if (lock_type != TL_IGNORE)
{
......
This diff is collapsed.
......@@ -319,8 +319,9 @@ w_requests: %10lu\n\
writes: %10lu\n\
r_requests: %10lu\n\
reads: %10lu\n",
my_blocks_used,my_blocks_changed,my_cache_w_requests,
my_cache_write,my_cache_r_requests,my_cache_read);
dflt_key_cache_var.blocks_used,dflt_key_cache_var.blocks_changed,
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);
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