Many files:

  Added mmap support for MyISAM engine
parent 21cc3ae5
...@@ -1819,7 +1819,7 @@ AC_CHECK_FUNCS(alarm bcmp bfill bmove bzero chsize cuserid fchmod fcntl \ ...@@ -1819,7 +1819,7 @@ AC_CHECK_FUNCS(alarm bcmp bfill bmove bzero chsize cuserid fchmod fcntl \
getcwd gethostbyaddr_r gethostbyname_r getpass getpassphrase getpwnam \ getcwd gethostbyaddr_r gethostbyname_r getpass getpassphrase getpwnam \
getpwuid getrlimit getrusage getwd gmtime_r index initgroups isnan \ getpwuid getrlimit getrusage getwd gmtime_r index initgroups isnan \
localtime_r locking longjmp lrand48 madvise mallinfo memcpy memmove \ localtime_r locking longjmp lrand48 madvise mallinfo memcpy memmove \
mkstemp mlockall perror poll pread pthread_attr_create mmap getpagesize \ mkstemp mlockall perror poll pread pthread_attr_create mmap mmap64 getpagesize \
pthread_attr_getstacksize pthread_attr_setprio pthread_attr_setschedparam \ pthread_attr_getstacksize pthread_attr_setprio pthread_attr_setschedparam \
pthread_attr_setstacksize pthread_condattr_create pthread_getsequence_np \ pthread_attr_setstacksize pthread_condattr_create pthread_getsequence_np \
pthread_key_delete pthread_rwlock_rdlock pthread_setprio \ pthread_key_delete pthread_rwlock_rdlock pthread_setprio \
......
...@@ -152,7 +152,8 @@ enum ha_extra_function { ...@@ -152,7 +152,8 @@ enum ha_extra_function {
other fields intact. When this is off (by default) InnoDB will use memcpy other fields intact. When this is off (by default) InnoDB will use memcpy
to overwrite entire row. to overwrite entire row.
*/ */
HA_EXTRA_KEYREAD_PRESERVE_FIELDS HA_EXTRA_KEYREAD_PRESERVE_FIELDS,
HA_EXTRA_MMAP
}; };
/* The following is parameter to ha_panic() */ /* The following is parameter to ha_panic() */
......
...@@ -821,7 +821,11 @@ my_bool my_gethwaddr(uchar *to); ...@@ -821,7 +821,11 @@ my_bool my_gethwaddr(uchar *to);
#define MAP_NOSYNC 0 #define MAP_NOSYNC 0
#endif #endif
#ifdef HAVE_MMAP64
#define my_mmap(a,b,c,d,e,f) mmap64(a,b,c,d,e,f)
#else
#define my_mmap(a,b,c,d,e,f) mmap(a,b,c,d,e,f) #define my_mmap(a,b,c,d,e,f) mmap(a,b,c,d,e,f)
#endif
#ifdef HAVE_GETPAGESIZE #ifdef HAVE_GETPAGESIZE
#define my_getpagesize() getpagesize() #define my_getpagesize() getpagesize()
#else #else
......
...@@ -304,6 +304,10 @@ int ha_myisam::open(const char *name, int mode, uint test_if_locked) ...@@ -304,6 +304,10 @@ int ha_myisam::open(const char *name, int mode, uint test_if_locked)
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));
if (!(test_if_locked & HA_OPEN_TMP_TABLE) && opt_myisam_use_mmap)
VOID(mi_extra(file, HA_EXTRA_MMAP, 0));
info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST); info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED)) if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
VOID(mi_extra(file, HA_EXTRA_WAIT_LOCK, 0)); VOID(mi_extra(file, HA_EXTRA_WAIT_LOCK, 0));
......
...@@ -1215,7 +1215,7 @@ extern bool volatile abort_loop, shutdown_in_progress, grant_option; ...@@ -1215,7 +1215,7 @@ extern bool volatile abort_loop, shutdown_in_progress, grant_option;
extern bool mysql_proc_table_exists; extern bool mysql_proc_table_exists;
extern uint volatile thread_count, thread_running, global_read_lock; extern uint volatile thread_count, thread_running, global_read_lock;
extern my_bool opt_sql_bin_update, opt_safe_user_create, opt_no_mix_types; extern my_bool opt_sql_bin_update, opt_safe_user_create, opt_no_mix_types;
extern my_bool opt_safe_show_db, opt_local_infile; extern my_bool opt_safe_show_db, opt_local_infile, opt_myisam_use_mmap;
extern my_bool opt_slave_compressed_protocol, use_temp_pool; extern my_bool opt_slave_compressed_protocol, use_temp_pool;
extern my_bool opt_readonly, lower_case_file_system; extern my_bool opt_readonly, lower_case_file_system;
extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs; extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs;
......
...@@ -428,6 +428,7 @@ my_bool opt_secure_auth= 0; ...@@ -428,6 +428,7 @@ my_bool opt_secure_auth= 0;
my_bool opt_log_slow_admin_statements= 0; my_bool opt_log_slow_admin_statements= 0;
my_bool lower_case_file_system= 0; my_bool lower_case_file_system= 0;
my_bool opt_large_pages= 0; my_bool opt_large_pages= 0;
my_bool opt_myisam_use_mmap= 0;
uint opt_large_page_size= 0; uint opt_large_page_size= 0;
my_bool opt_old_style_user_limits= 0, trust_function_creators= 0; my_bool opt_old_style_user_limits= 0, trust_function_creators= 0;
/* /*
...@@ -4558,6 +4559,7 @@ enum options_mysqld ...@@ -4558,6 +4559,7 @@ enum options_mysqld
OPT_MAX_ERROR_COUNT, OPT_MULTI_RANGE_COUNT, OPT_MYISAM_DATA_POINTER_SIZE, OPT_MAX_ERROR_COUNT, OPT_MULTI_RANGE_COUNT, OPT_MYISAM_DATA_POINTER_SIZE,
OPT_MYISAM_BLOCK_SIZE, OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE, OPT_MYISAM_BLOCK_SIZE, OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE,
OPT_MYISAM_MAX_SORT_FILE_SIZE, OPT_MYISAM_SORT_BUFFER_SIZE, OPT_MYISAM_MAX_SORT_FILE_SIZE, OPT_MYISAM_SORT_BUFFER_SIZE,
OPT_MYISAM_USE_MMAP,
OPT_MYISAM_STATS_METHOD, OPT_MYISAM_STATS_METHOD,
OPT_NET_BUFFER_LENGTH, OPT_NET_RETRY_COUNT, OPT_NET_BUFFER_LENGTH, OPT_NET_RETRY_COUNT,
OPT_NET_READ_TIMEOUT, OPT_NET_WRITE_TIMEOUT, OPT_NET_READ_TIMEOUT, OPT_NET_WRITE_TIMEOUT,
...@@ -5767,6 +5769,11 @@ The minimum value for this variable is 4096.", ...@@ -5767,6 +5769,11 @@ The minimum value for this variable is 4096.",
(gptr*) &global_system_variables.myisam_sort_buff_size, (gptr*) &global_system_variables.myisam_sort_buff_size,
(gptr*) &max_system_variables.myisam_sort_buff_size, 0, (gptr*) &max_system_variables.myisam_sort_buff_size, 0,
GET_ULONG, REQUIRED_ARG, 8192*1024, 4, ~0L, 0, 1, 0}, GET_ULONG, REQUIRED_ARG, 8192*1024, 4, ~0L, 0, 1, 0},
{"myisam_use_mmap", OPT_MYISAM_USE_MMAP,
"Use memory mapping for read/write MyISAM tables",
(gptr*) &opt_myisam_use_mmap,
(gptr*) &opt_myisam_use_mmap, 0, GET_BOOL, NO_ARG, 0,
0, 0, 0, 0, 0},
{"myisam_stats_method", OPT_MYISAM_STATS_METHOD, {"myisam_stats_method", OPT_MYISAM_STATS_METHOD,
"Specifies how MyISAM index statistics collection code should threat NULLs. " "Specifies how MyISAM index statistics collection code should threat NULLs. "
"Possible values of name are \"nulls_unequal\" (default behavior for 4.1/5.0), " "Possible values of name are \"nulls_unequal\" (default behavior for 4.1/5.0), "
......
...@@ -153,6 +153,10 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table, ...@@ -153,6 +153,10 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
info->table=table; info->table=table;
info->file= table->file; info->file= table->file;
info->forms= &info->table; /* Only one table */ info->forms= &info->table; /* Only one table */
if (table->s->tmp_table == TMP_TABLE && !table->sort.addon_field)
VOID(table->file->extra(HA_EXTRA_MMAP));
if (table->sort.addon_field) if (table->sort.addon_field)
{ {
info->rec_buf= table->sort.addon_buf; info->rec_buf= table->sort.addon_buf;
......
...@@ -314,6 +314,8 @@ sys_var_long_ptr sys_myisam_data_pointer_size("myisam_data_pointer_size", ...@@ -314,6 +314,8 @@ sys_var_long_ptr sys_myisam_data_pointer_size("myisam_data_pointer_size",
sys_var_thd_ulonglong sys_myisam_max_sort_file_size("myisam_max_sort_file_size", &SV::myisam_max_sort_file_size, fix_myisam_max_sort_file_size, 1); sys_var_thd_ulonglong sys_myisam_max_sort_file_size("myisam_max_sort_file_size", &SV::myisam_max_sort_file_size, fix_myisam_max_sort_file_size, 1);
sys_var_thd_ulong sys_myisam_repair_threads("myisam_repair_threads", &SV::myisam_repair_threads); sys_var_thd_ulong sys_myisam_repair_threads("myisam_repair_threads", &SV::myisam_repair_threads);
sys_var_thd_ulong sys_myisam_sort_buffer_size("myisam_sort_buffer_size", &SV::myisam_sort_buff_size); sys_var_thd_ulong sys_myisam_sort_buffer_size("myisam_sort_buffer_size", &SV::myisam_sort_buff_size);
sys_var_bool_ptr sys_myisam_use_mmap("myisam_use_mmap",
&opt_myisam_use_mmap);
sys_var_thd_enum sys_myisam_stats_method("myisam_stats_method", sys_var_thd_enum sys_myisam_stats_method("myisam_stats_method",
&SV::myisam_stats_method, &SV::myisam_stats_method,
...@@ -789,6 +791,7 @@ struct show_var_st init_vars[]= { ...@@ -789,6 +791,7 @@ struct show_var_st init_vars[]= {
{sys_myisam_repair_threads.name, (char*) &sys_myisam_repair_threads, {sys_myisam_repair_threads.name, (char*) &sys_myisam_repair_threads,
SHOW_SYS}, SHOW_SYS},
{sys_myisam_sort_buffer_size.name, (char*) &sys_myisam_sort_buffer_size, SHOW_SYS}, {sys_myisam_sort_buffer_size.name, (char*) &sys_myisam_sort_buffer_size, SHOW_SYS},
{sys_myisam_use_mmap.name, (char*) &sys_myisam_use_mmap, SHOW_SYS},
{sys_myisam_stats_method.name, (char*) &sys_myisam_stats_method, SHOW_SYS}, {sys_myisam_stats_method.name, (char*) &sys_myisam_stats_method, SHOW_SYS},
......
...@@ -96,6 +96,7 @@ int mi_close(register MI_INFO *info) ...@@ -96,6 +96,7 @@ int mi_close(register MI_INFO *info)
{ {
int i,keys; int i,keys;
keys = share->state.header.keys; keys = share->state.header.keys;
VOID(rwlock_destroy(&share->mmap_lock));
for(i=0; i<keys; i++) { for(i=0; i<keys; i++) {
VOID(rwlock_destroy(&share->key_root_lock[i])); VOID(rwlock_destroy(&share->key_root_lock[i]));
} }
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
int mi_delete_all_rows(MI_INFO *info) int mi_delete_all_rows(MI_INFO *info)
{ {
uint i; uint i;
char buf[22];
MYISAM_SHARE *share=info->s; MYISAM_SHARE *share=info->s;
MI_STATE_INFO *state=&share->state; MI_STATE_INFO *state=&share->state;
DBUG_ENTER("mi_delete_all_rows"); DBUG_ENTER("mi_delete_all_rows");
...@@ -58,6 +59,12 @@ int mi_delete_all_rows(MI_INFO *info) ...@@ -58,6 +59,12 @@ int mi_delete_all_rows(MI_INFO *info)
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;
VOID(_mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE)); VOID(_mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
#ifdef HAVE_MMAP
/* Resize mmaped area */
rw_wrlock(&info->s->mmap_lock);
mi_remap_file(info, (my_off_t)0);
rw_unlock(&info->s->mmap_lock);
#endif
allow_break(); /* Allow SIGHUP & SIGINT */ allow_break(); /* Allow SIGHUP & SIGINT */
DBUG_RETURN(0); DBUG_RETURN(0);
......
...@@ -50,6 +50,174 @@ static int _mi_cmp_buffer(File file, const byte *buff, my_off_t filepos, ...@@ -50,6 +50,174 @@ static int _mi_cmp_buffer(File file, const byte *buff, my_off_t filepos,
/* Interface function from MI_INFO */ /* Interface function from MI_INFO */
#ifdef HAVE_MMAP
/*
Create mmaped area for MyISAM handler
SYNOPSIS
mi_dynmap_file()
info MyISAM handler
RETURN
0 ok
1 error.
*/
my_bool mi_dynmap_file(MI_INFO *info, my_off_t size)
{
DBUG_ENTER("mi_dynmap_file");
info->s->file_map= (byte*)
my_mmap(0, (size_t)(size + MEMMAP_EXTRA_MARGIN),
info->s->mode==O_RDONLY ? PROT_READ :
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_NORESERVE,
info->dfile, 0L);
if (info->s->file_map == (byte*) MAP_FAILED)
{
info->s->file_map= NULL;
DBUG_RETURN(1);
}
#if defined(HAVE_MADVISE)
madvise(info->s->file_map, size, MADV_RANDOM);
#endif
info->s->mmaped_length= size;
DBUG_RETURN(0);
}
/*
Resize mmaped area for MyISAM handler
SYNOPSIS
mi_remap_file()
info MyISAM handler
RETURN
*/
void mi_remap_file(MI_INFO *info, my_off_t size)
{
if (info->s->file_map)
{
VOID(my_munmap(info->s->file_map,
(size_t) info->s->mmaped_length + MEMMAP_EXTRA_MARGIN));
mi_dynmap_file(info, size);
}
}
#endif
/*
Read bytes from MySAM handler, using mmap or pread
SYNOPSIS
mi_mmap_pread()
info MyISAM handler
Buffer Input buffer
Count Count of bytes for read
offset Start position
MyFlags
RETURN
0 ok
*/
uint mi_mmap_pread(MI_INFO *info, byte *Buffer,
uint Count, my_off_t offset, myf MyFlags)
{
DBUG_PRINT("info", ("mi_read with mmap %d\n", info->dfile));
if (info->s->concurrent_insert)
rw_rdlock(&info->s->mmap_lock);
/*
The following test may fail in the following cases:
- We failed to remap a memory area (fragmented memory?)
- This thread has done some writes, but not yet extended the
memory mapped area.
*/
if (info->s->mmaped_length >= offset + Count)
{
memcpy(Buffer, info->s->file_map + offset, Count);
if (info->s->concurrent_insert)
rw_unlock(&info->s->mmap_lock);
return 0;
}
else
{
if (info->s->concurrent_insert)
rw_unlock(&info->s->mmap_lock);
return my_pread(info->dfile, Buffer, Count, offset, MyFlags);
}
}
/* wrapper for my_pread in case if mmap isn't used */
uint mi_nommap_pread(MI_INFO *info, byte *Buffer,
uint Count, my_off_t offset, myf MyFlags)
{
return my_pread(info->dfile, Buffer, Count, offset, MyFlags);
}
/*
Write bytes to MySAM handler, using mmap or pwrite
SYNOPSIS
mi_mmap_pwrite()
info MyISAM handler
Buffer Output buffer
Count Count of bytes for write
offset Start position
MyFlags
RETURN
0 ok
!=0 error. In this case return error from pwrite
*/
uint mi_mmap_pwrite(MI_INFO *info, byte *Buffer,
uint Count, my_off_t offset, myf MyFlags)
{
DBUG_PRINT("info", ("mi_write with mmap %d\n", info->dfile));
if (info->s->concurrent_insert)
rw_rdlock(&info->s->mmap_lock);
/*
The following test may fail in the following cases:
- We failed to remap a memory area (fragmented memory?)
- This thread has done some writes, but not yet extended the
memory mapped area.
*/
if (info->s->mmaped_length >= offset + Count)
{
memcpy(info->s->file_map + offset, Buffer, Count);
if (info->s->concurrent_insert)
rw_unlock(&info->s->mmap_lock);
return 0;
}
else
{
if (info->s->concurrent_insert)
rw_unlock(&info->s->mmap_lock);
return my_pwrite(info->dfile, Buffer, Count, offset, MyFlags);
}
}
/* wrapper for my_pwrite in case if mmap isn't used */
uint mi_nommap_pwrite(MI_INFO *info, byte *Buffer,
uint Count, my_off_t offset, myf MyFlags)
{
return my_pwrite(info->dfile, Buffer, Count, offset, MyFlags);
}
int _mi_write_dynamic_record(MI_INFO *info, const byte *record) int _mi_write_dynamic_record(MI_INFO *info, const byte *record)
{ {
ulong reclength=_mi_rec_pack(info,info->rec_buff,record); ulong reclength=_mi_rec_pack(info,info->rec_buff,record);
...@@ -243,7 +411,7 @@ static bool unlink_deleted_block(MI_INFO *info, MI_BLOCK_INFO *block_info) ...@@ -243,7 +411,7 @@ static bool unlink_deleted_block(MI_INFO *info, MI_BLOCK_INFO *block_info)
& BLOCK_DELETED)) & BLOCK_DELETED))
DBUG_RETURN(1); /* Something is wrong */ DBUG_RETURN(1); /* Something is wrong */
mi_sizestore(tmp.header+4,block_info->next_filepos); mi_sizestore(tmp.header+4,block_info->next_filepos);
if (my_pwrite(info->dfile,(char*) tmp.header+4,8, if (info->s->file_write(info,(char*) tmp.header+4,8,
block_info->prev_filepos+4, MYF(MY_NABP))) block_info->prev_filepos+4, MYF(MY_NABP)))
DBUG_RETURN(1); DBUG_RETURN(1);
/* Unlink block from next block */ /* Unlink block from next block */
...@@ -253,7 +421,7 @@ static bool unlink_deleted_block(MI_INFO *info, MI_BLOCK_INFO *block_info) ...@@ -253,7 +421,7 @@ static bool unlink_deleted_block(MI_INFO *info, MI_BLOCK_INFO *block_info)
& BLOCK_DELETED)) & BLOCK_DELETED))
DBUG_RETURN(1); /* Something is wrong */ DBUG_RETURN(1); /* Something is wrong */
mi_sizestore(tmp.header+12,block_info->prev_filepos); mi_sizestore(tmp.header+12,block_info->prev_filepos);
if (my_pwrite(info->dfile,(char*) tmp.header+12,8, if (info->s->file_write(info,(char*) tmp.header+12,8,
block_info->next_filepos+12, block_info->next_filepos+12,
MYF(MY_NABP))) MYF(MY_NABP)))
DBUG_RETURN(1); DBUG_RETURN(1);
...@@ -304,7 +472,7 @@ static int update_backward_delete_link(MI_INFO *info, my_off_t delete_block, ...@@ -304,7 +472,7 @@ static int update_backward_delete_link(MI_INFO *info, my_off_t delete_block,
{ {
char buff[8]; char buff[8];
mi_sizestore(buff,filepos); mi_sizestore(buff,filepos);
if (my_pwrite(info->dfile,buff, 8, delete_block+12, MYF(MY_NABP))) if (info->s->file_write(info,buff, 8, delete_block+12, MYF(MY_NABP)))
DBUG_RETURN(1); /* Error on write */ DBUG_RETURN(1); /* Error on write */
} }
else else
...@@ -362,7 +530,7 @@ static int delete_dynamic_record(MI_INFO *info, my_off_t filepos, ...@@ -362,7 +530,7 @@ static int delete_dynamic_record(MI_INFO *info, my_off_t filepos,
bfill(block_info.header+12,8,255); bfill(block_info.header+12,8,255);
else else
mi_sizestore(block_info.header+12,block_info.next_filepos); mi_sizestore(block_info.header+12,block_info.next_filepos);
if (my_pwrite(info->dfile,(byte*) block_info.header,20,filepos, if (info->s->file_write(info,(byte*) block_info.header,20,filepos,
MYF(MY_NABP))) MYF(MY_NABP)))
DBUG_RETURN(1); DBUG_RETURN(1);
info->s->state.dellink = filepos; info->s->state.dellink = filepos;
...@@ -545,7 +713,7 @@ int _mi_write_part_record(MI_INFO *info, ...@@ -545,7 +713,7 @@ int _mi_write_part_record(MI_INFO *info,
else else
{ {
info->rec_cache.seek_not_done=1; info->rec_cache.seek_not_done=1;
if (my_pwrite(info->dfile,(byte*) *record-head_length,length+extra_length+ if (info->s->file_write(info,(byte*) *record-head_length,length+extra_length+
del_length,filepos,info->s->write_flag)) del_length,filepos,info->s->write_flag))
goto err; goto err;
} }
...@@ -655,7 +823,7 @@ static int update_dynamic_record(MI_INFO *info, my_off_t filepos, byte *record, ...@@ -655,7 +823,7 @@ static int update_dynamic_record(MI_INFO *info, my_off_t filepos, byte *record,
mi_int3store(del_block.header+1, rest_length); mi_int3store(del_block.header+1, rest_length);
mi_sizestore(del_block.header+4,info->s->state.dellink); mi_sizestore(del_block.header+4,info->s->state.dellink);
bfill(del_block.header+12,8,255); bfill(del_block.header+12,8,255);
if (my_pwrite(info->dfile,(byte*) del_block.header,20, next_pos, if (info->s->file_write(info,(byte*) del_block.header,20, next_pos,
MYF(MY_NABP))) MYF(MY_NABP)))
DBUG_RETURN(1); DBUG_RETURN(1);
info->s->state.dellink= next_pos; info->s->state.dellink= next_pos;
...@@ -1182,7 +1350,7 @@ int _mi_read_dynamic_record(MI_INFO *info, my_off_t filepos, byte *buf) ...@@ -1182,7 +1350,7 @@ int _mi_read_dynamic_record(MI_INFO *info, my_off_t filepos, byte *buf)
} }
if (left_length < block_info.data_len || ! block_info.data_len) if (left_length < block_info.data_len || ! block_info.data_len)
goto panic; /* Wrong linked record */ goto panic; /* Wrong linked record */
if (my_pread(file,(byte*) to,block_info.data_len,block_info.filepos, if (info->s->file_read(info,(byte*) to,block_info.data_len,block_info.filepos,
MYF(MY_NABP))) MYF(MY_NABP)))
goto panic; goto panic;
left_length-=block_info.data_len; left_length-=block_info.data_len;
......
...@@ -93,6 +93,8 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) ...@@ -93,6 +93,8 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
my_errno=EACCES; my_errno=EACCES;
break; break;
} }
if (info->s->file_map) /* Don't use cache if mmap */
break;
#if defined(HAVE_MMAP) && defined(HAVE_MADVISE) #if defined(HAVE_MMAP) && defined(HAVE_MADVISE)
if ((share->options & HA_OPTION_COMPRESS_RECORD)) if ((share->options & HA_OPTION_COMPRESS_RECORD))
{ {
...@@ -150,6 +152,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) ...@@ -150,6 +152,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
error=1; /* Not possibly if not locked */ error=1; /* Not possibly if not locked */
break; break;
} }
cache_size= (extra_arg ? *(ulong*) extra_arg : cache_size= (extra_arg ? *(ulong*) extra_arg :
my_default_record_cache_size); my_default_record_cache_size);
if (!(info->opt_flag & if (!(info->opt_flag &
...@@ -367,6 +370,25 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) ...@@ -367,6 +370,25 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
case HA_EXTRA_CHANGE_KEY_TO_DUP: case HA_EXTRA_CHANGE_KEY_TO_DUP:
mi_extra_keyflag(info, function); mi_extra_keyflag(info, function);
break; break;
case HA_EXTRA_MMAP:
#ifdef HAVE_MMAP
pthread_mutex_lock(&share->intern_lock);
if (!share->file_map)
{
if (mi_dynmap_file(info, share->state.state.data_file_length))
{
DBUG_PRINT("warning",("mmap failed: errno: %d",errno));
error= my_errno= errno;
}
else
{
share->file_read= mi_mmap_pread;
share->file_write= mi_mmap_pwrite;
}
}
pthread_mutex_unlock(&share->intern_lock);
#endif
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:
......
...@@ -38,7 +38,6 @@ int mi_lock_database(MI_INFO *info, int lock_type) ...@@ -38,7 +38,6 @@ int mi_lock_database(MI_INFO *info, int lock_type)
share->w_locks, share->w_locks,
share->global_changed, share->state.open_count, share->global_changed, share->state.open_count,
share->index_file_name)); share->index_file_name));
if (share->options & HA_OPTION_READ_ONLY_DATA || if (share->options & HA_OPTION_READ_ONLY_DATA ||
info->lock_type == lock_type) info->lock_type == lock_type)
DBUG_RETURN(0); DBUG_RETURN(0);
...@@ -84,6 +83,14 @@ int mi_lock_database(MI_INFO *info, int lock_type) ...@@ -84,6 +83,14 @@ int mi_lock_database(MI_INFO *info, int lock_type)
(uint) share->changed, share->w_locks)); (uint) share->changed, share->w_locks));
if (share->changed && !share->w_locks) if (share->changed && !share->w_locks)
{ {
if (info->s->mmaped_length != info->s->state.state.data_file_length)
{
if (info->s->concurrent_insert)
rw_wrlock(&info->s->mmap_lock);
mi_remap_file(info, info->s->state.state.data_file_length);
if (info->s->concurrent_insert)
rw_unlock(&info->s->mmap_lock);
}
share->state.process= share->last_process=share->this_process; share->state.process= share->last_process=share->this_process;
share->state.unique= info->last_unique= info->this_unique; share->state.unique= info->last_unique= info->this_unique;
share->state.update_count= info->last_loop= ++info->this_loop; share->state.update_count= info->last_loop= ++info->this_loop;
...@@ -215,6 +222,7 @@ int mi_lock_database(MI_INFO *info, int lock_type) ...@@ -215,6 +222,7 @@ int mi_lock_database(MI_INFO *info, int lock_type)
} }
} }
VOID(_mi_test_if_changed(info)); VOID(_mi_test_if_changed(info));
info->lock_type=lock_type; info->lock_type=lock_type;
info->invalidator=info->s->invalidator; info->invalidator=info->s->invalidator;
share->w_locks++; share->w_locks++;
......
...@@ -288,6 +288,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) ...@@ -288,6 +288,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
#ifdef THREAD #ifdef THREAD
&share->key_root_lock,sizeof(rw_lock_t)*keys, &share->key_root_lock,sizeof(rw_lock_t)*keys,
#endif #endif
&share->mmap_lock,sizeof(rw_lock_t),
NullS)) NullS))
goto err; goto err;
errpos=4; errpos=4;
...@@ -459,7 +460,6 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) ...@@ -459,7 +460,6 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
(keys ? MI_INDEX_BLOCK_MARGIN * (keys ? MI_INDEX_BLOCK_MARGIN *
share->blocksize * keys : 0)); share->blocksize * keys : 0));
share->blocksize=min(IO_SIZE,myisam_block_size); share->blocksize=min(IO_SIZE,myisam_block_size);
share->data_file_type=STATIC_RECORD; share->data_file_type=STATIC_RECORD;
if (share->options & HA_OPTION_COMPRESS_RECORD) if (share->options & HA_OPTION_COMPRESS_RECORD)
{ {
...@@ -482,6 +482,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) ...@@ -482,6 +482,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST)); VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST));
for (i=0; i<keys; i++) for (i=0; i<keys; i++)
VOID(my_rwlock_init(&share->key_root_lock[i], NULL)); VOID(my_rwlock_init(&share->key_root_lock[i], NULL));
VOID(my_rwlock_init(&share->mmap_lock, NULL));
if (!thr_lock_inited) if (!thr_lock_inited)
{ {
/* Probably a single threaded program; Don't use concurrent inserts */ /* Probably a single threaded program; Don't use concurrent inserts */
...@@ -736,6 +737,8 @@ void mi_setup_functions(register MYISAM_SHARE *share) ...@@ -736,6 +737,8 @@ void mi_setup_functions(register MYISAM_SHARE *share)
share->compare_unique=_mi_cmp_static_unique; share->compare_unique=_mi_cmp_static_unique;
share->calc_checksum= mi_static_checksum; share->calc_checksum= mi_static_checksum;
} }
share->file_read= mi_nommap_pread;
share->file_write= mi_nommap_pwrite;
if (!(share->options & HA_OPTION_CHECKSUM)) if (!(share->options & HA_OPTION_CHECKSUM))
share->calc_checksum=0; share->calc_checksum=0;
return; return;
......
...@@ -1192,34 +1192,25 @@ my_bool _mi_memmap_file(MI_INFO *info) ...@@ -1192,34 +1192,25 @@ my_bool _mi_memmap_file(MI_INFO *info)
if (!info->s->file_map) if (!info->s->file_map)
{ {
if (my_seek(info->dfile,0L,MY_SEEK_END,MYF(0)) < if (my_seek(info->dfile,0L,MY_SEEK_END,MYF(0)) <
share->state.state.data_file_length+MEMMAP_EXTRA_MARGIN) share->state.state.data_file_length+MEMMAP_EXTRA_MARGIN)
{ {
DBUG_PRINT("warning",("File isn't extended for memmap")); DBUG_PRINT("warning",("File isn't extended for memmap"));
DBUG_RETURN(0); DBUG_RETURN(0);
} }
file_map=(byte*) if (mi_dynmap_file(info, share->state.state.data_file_length))
my_mmap(0,(size_t)(share->state.state.data_file_length+MEMMAP_EXTRA_MARGIN),PROT_READ,
MAP_SHARED | MAP_NORESERVE,info->dfile,0L);
if (file_map == (byte*) MAP_FAILED)
{
DBUG_PRINT("warning",("mmap failed: errno: %d",errno));
my_errno=errno;
DBUG_RETURN(0); DBUG_RETURN(0);
}
info->s->file_map=file_map;
} }
info->opt_flag|= MEMMAP_USED; info->opt_flag|= MEMMAP_USED;
info->read_record=share->read_record=_mi_read_mempack_record; info->read_record= share->read_record= _mi_read_mempack_record;
share->read_rnd=_mi_read_rnd_mempack_record; share->read_rnd= _mi_read_rnd_mempack_record;
DBUG_RETURN(1); DBUG_RETURN(1);
} }
void _mi_unmap_file(MI_INFO *info) void _mi_unmap_file(MI_INFO *info)
{ {
VOID(my_munmap(info->s->file_map, VOID(my_munmap(info->s->file_map,
(size_t) info->s->state.state.data_file_length+ (size_t) info->s->mmaped_length + MEMMAP_EXTRA_MARGIN));
MEMMAP_EXTRA_MARGIN));
} }
......
...@@ -22,20 +22,19 @@ ...@@ -22,20 +22,19 @@
int _mi_write_static_record(MI_INFO *info, const byte *record) int _mi_write_static_record(MI_INFO *info, const byte *record)
{ {
uchar temp[8]; /* max pointer length */ uchar temp[8]; /* max pointer length */
if (info->s->state.dellink != HA_OFFSET_ERROR && if (info->s->state.dellink != HA_OFFSET_ERROR &&
!info->append_insert_at_end) !info->append_insert_at_end)
{ {
my_off_t filepos=info->s->state.dellink; my_off_t filepos=info->s->state.dellink;
info->rec_cache.seek_not_done=1; /* We have done a seek */ info->rec_cache.seek_not_done=1; /* We have done a seek */
if (my_pread(info->dfile,(char*) &temp[0],info->s->base.rec_reflength, if (info->s->file_read(info,(char*) &temp[0],info->s->base.rec_reflength,
info->s->state.dellink+1, info->s->state.dellink+1,
MYF(MY_NABP))) MYF(MY_NABP)))
goto err; goto err;
info->s->state.dellink= _mi_rec_pos(info->s,temp); info->s->state.dellink= _mi_rec_pos(info->s,temp);
info->state->del--; info->state->del--;
info->state->empty-=info->s->base.pack_reclength; info->state->empty-=info->s->base.pack_reclength;
if (my_pwrite(info->dfile, (char*) record, info->s->base.reclength, if (info->s->file_write(info, (char*) record, info->s->base.reclength,
filepos, filepos,
MYF(MY_NABP))) MYF(MY_NABP)))
goto err; goto err;
...@@ -64,19 +63,19 @@ int _mi_write_static_record(MI_INFO *info, const byte *record) ...@@ -64,19 +63,19 @@ int _mi_write_static_record(MI_INFO *info, const byte *record)
else else
{ {
info->rec_cache.seek_not_done=1; /* We have done a seek */ info->rec_cache.seek_not_done=1; /* We have done a seek */
if (my_pwrite(info->dfile,(char*) record,info->s->base.reclength, if (info->s->file_write(info,(char*) record,info->s->base.reclength,
info->state->data_file_length, info->state->data_file_length,
info->s->write_flag)) info->s->write_flag))
goto err; goto err;
if (info->s->base.pack_reclength != info->s->base.reclength) if (info->s->base.pack_reclength != info->s->base.reclength)
{ {
uint length=info->s->base.pack_reclength - info->s->base.reclength; uint length=info->s->base.pack_reclength - info->s->base.reclength;
bzero((char*) temp,length); bzero((char*) temp,length);
if (my_pwrite(info->dfile, (byte*) temp,length, if (info->s->file_write(info, (byte*) temp,length,
info->state->data_file_length+ info->state->data_file_length+
info->s->base.reclength, info->s->base.reclength,
info->s->write_flag)) info->s->write_flag))
goto err; goto err;
} }
} }
info->state->data_file_length+=info->s->base.pack_reclength; info->state->data_file_length+=info->s->base.pack_reclength;
...@@ -90,7 +89,7 @@ int _mi_write_static_record(MI_INFO *info, const byte *record) ...@@ -90,7 +89,7 @@ int _mi_write_static_record(MI_INFO *info, const byte *record)
int _mi_update_static_record(MI_INFO *info, my_off_t pos, const byte *record) int _mi_update_static_record(MI_INFO *info, my_off_t pos, const byte *record)
{ {
info->rec_cache.seek_not_done=1; /* We have done a seek */ info->rec_cache.seek_not_done=1; /* We have done a seek */
return (my_pwrite(info->dfile, return (info->s->file_write(info,
(char*) record,info->s->base.reclength, (char*) record,info->s->base.reclength,
pos, pos,
MYF(MY_NABP)) != 0); MYF(MY_NABP)) != 0);
...@@ -107,7 +106,7 @@ int _mi_delete_static_record(MI_INFO *info) ...@@ -107,7 +106,7 @@ int _mi_delete_static_record(MI_INFO *info)
_mi_dpointer(info,temp+1,info->s->state.dellink); _mi_dpointer(info,temp+1,info->s->state.dellink);
info->s->state.dellink = info->lastpos; info->s->state.dellink = info->lastpos;
info->rec_cache.seek_not_done=1; info->rec_cache.seek_not_done=1;
return (my_pwrite(info->dfile,(byte*) temp, 1+info->s->rec_reflength, return (info->s->file_write(info,(byte*) temp, 1+info->s->rec_reflength,
info->lastpos, MYF(MY_NABP)) != 0); info->lastpos, MYF(MY_NABP)) != 0);
} }
...@@ -131,7 +130,7 @@ int _mi_cmp_static_record(register MI_INFO *info, register const byte *old) ...@@ -131,7 +130,7 @@ int _mi_cmp_static_record(register MI_INFO *info, register const byte *old)
if ((info->opt_flag & READ_CHECK_USED)) if ((info->opt_flag & READ_CHECK_USED))
{ /* If check isn't disabled */ { /* If check isn't disabled */
info->rec_cache.seek_not_done=1; /* We have done a seek */ info->rec_cache.seek_not_done=1; /* We have done a seek */
if (my_pread(info->dfile, (char*) info->rec_buff, info->s->base.reclength, if (info->s->file_read(info, (char*) info->rec_buff, info->s->base.reclength,
info->lastpos, info->lastpos,
MYF(MY_NABP))) MYF(MY_NABP)))
DBUG_RETURN(-1); DBUG_RETURN(-1);
...@@ -154,7 +153,7 @@ int _mi_cmp_static_unique(MI_INFO *info, MI_UNIQUEDEF *def, ...@@ -154,7 +153,7 @@ int _mi_cmp_static_unique(MI_INFO *info, MI_UNIQUEDEF *def,
DBUG_ENTER("_mi_cmp_static_unique"); DBUG_ENTER("_mi_cmp_static_unique");
info->rec_cache.seek_not_done=1; /* We have done a seek */ info->rec_cache.seek_not_done=1; /* We have done a seek */
if (my_pread(info->dfile, (char*) info->rec_buff, info->s->base.reclength, if (info->s->file_read(info, (char*) info->rec_buff, info->s->base.reclength,
pos, MYF(MY_NABP))) pos, MYF(MY_NABP)))
DBUG_RETURN(-1); DBUG_RETURN(-1);
DBUG_RETURN(mi_unique_comp(def, record, info->rec_buff, DBUG_RETURN(mi_unique_comp(def, record, info->rec_buff,
...@@ -180,7 +179,7 @@ int _mi_read_static_record(register MI_INFO *info, register my_off_t pos, ...@@ -180,7 +179,7 @@ int _mi_read_static_record(register MI_INFO *info, register my_off_t pos,
return(-1); return(-1);
info->rec_cache.seek_not_done=1; /* We have done a seek */ info->rec_cache.seek_not_done=1; /* We have done a seek */
error=my_pread(info->dfile,(char*) record,info->s->base.reclength, error=info->s->file_read(info,(char*) record,info->s->base.reclength,
pos,MYF(MY_NABP)) != 0; pos,MYF(MY_NABP)) != 0;
fast_mi_writeinfo(info); fast_mi_writeinfo(info);
if (! error) if (! error)
......
...@@ -179,6 +179,8 @@ typedef struct st_mi_isam_share { /* Shared between opens */ ...@@ -179,6 +179,8 @@ typedef struct st_mi_isam_share { /* Shared between opens */
ha_checksum (*calc_checksum)(struct st_myisam_info*, const byte *); ha_checksum (*calc_checksum)(struct st_myisam_info*, const byte *);
int (*compare_unique)(struct st_myisam_info*, MI_UNIQUEDEF *, int (*compare_unique)(struct st_myisam_info*, MI_UNIQUEDEF *,
const byte *record, my_off_t pos); const byte *record, my_off_t pos);
uint (*file_read)(MI_INFO *, byte *, uint, my_off_t, myf);
uint (*file_write)(MI_INFO *, byte *, uint, my_off_t, myf);
invalidator_by_filename invalidator; /* query cache invalidator */ invalidator_by_filename invalidator; /* query cache invalidator */
ulong this_process; /* processid */ ulong this_process; /* processid */
ulong last_process; /* For table-change-check */ ulong last_process; /* For table-change-check */
...@@ -207,6 +209,8 @@ typedef struct st_mi_isam_share { /* Shared between opens */ ...@@ -207,6 +209,8 @@ typedef struct st_mi_isam_share { /* Shared between opens */
pthread_mutex_t intern_lock; /* Locking for use with _locking */ pthread_mutex_t intern_lock; /* Locking for use with _locking */
rw_lock_t *key_root_lock; rw_lock_t *key_root_lock;
#endif #endif
my_off_t mmaped_length;
rw_lock_t mmap_lock;
} MYISAM_SHARE; } MYISAM_SHARE;
...@@ -685,6 +689,14 @@ extern void _mi_unmap_file(MI_INFO *info); ...@@ -685,6 +689,14 @@ extern void _mi_unmap_file(MI_INFO *info);
extern uint save_pack_length(uint version, byte *block_buff, ulong length); extern uint save_pack_length(uint version, byte *block_buff, ulong length);
extern uint read_pack_length(uint version, const uchar *buf, ulong *length); extern uint read_pack_length(uint version, const uchar *buf, ulong *length);
extern uint calc_pack_length(uint version, ulong length); extern uint calc_pack_length(uint version, ulong length);
extern uint mi_mmap_pread(MI_INFO *info, byte *Buffer,
uint Count, my_off_t offset, myf MyFlags);
extern uint mi_mmap_pwrite(MI_INFO *info, byte *Buffer,
uint Count, my_off_t offset, myf MyFlags);
extern uint mi_nommap_pread(MI_INFO *info, byte *Buffer,
uint Count, my_off_t offset, myf MyFlags);
extern uint mi_nommap_pwrite(MI_INFO *info, byte *Buffer,
uint Count, my_off_t offset, myf MyFlags);
uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite); uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite);
uchar *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state); uchar *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state);
......
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