diff --git a/configure.in b/configure.in index ed57fa0c72b9baea3fd806820258417a2cfd438e..a01d962e3eaa1bd5061e414b8e9ddd3ca2bf3682 100644 --- a/configure.in +++ b/configure.in @@ -1819,7 +1819,7 @@ AC_CHECK_FUNCS(alarm bcmp bfill bmove bzero chsize cuserid fchmod fcntl \ getcwd gethostbyaddr_r gethostbyname_r getpass getpassphrase getpwnam \ getpwuid getrlimit getrusage getwd gmtime_r index initgroups isnan \ 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_setstacksize pthread_condattr_create pthread_getsequence_np \ pthread_key_delete pthread_rwlock_rdlock pthread_setprio \ diff --git a/include/my_base.h b/include/my_base.h index ebe1c6ab722e43e5827e23b6bfd5b51d24b75ab0..c688591e1d53a4a2a59b4800ece011e2eb7a5034 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -152,7 +152,8 @@ enum ha_extra_function { other fields intact. When this is off (by default) InnoDB will use memcpy to overwrite entire row. */ - HA_EXTRA_KEYREAD_PRESERVE_FIELDS + HA_EXTRA_KEYREAD_PRESERVE_FIELDS, + HA_EXTRA_MMAP }; /* The following is parameter to ha_panic() */ diff --git a/include/my_sys.h b/include/my_sys.h index 44fe383bf4f81f9e266353ae0c5bcd0b00f6d04e..cda308f222a1c41b2807092816a6b22b726bb55c 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -821,7 +821,11 @@ my_bool my_gethwaddr(uchar *to); #define MAP_NOSYNC 0 #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) +#endif #ifdef HAVE_GETPAGESIZE #define my_getpagesize() getpagesize() #else diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 02d814a94516877845d518bbd47e97937ec129c3..dfd8fb23cf4dec00c9b6eab803e167db1855f217 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -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)) 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); if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED)) VOID(mi_extra(file, HA_EXTRA_WAIT_LOCK, 0)); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 4b7a1fc00a8b9bd08222c560bb0fca2372b55520..9c18fb1b8acc25525a2b95c522c42344d33bad0a 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1215,7 +1215,7 @@ extern bool volatile abort_loop, shutdown_in_progress, grant_option; extern bool mysql_proc_table_exists; 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_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_readonly, lower_case_file_system; extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f344becffdea179e688f01ad42a836d0f70d239a..a56082a6ad39e6fc7d21414a25d36ef07fb0ed9e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -428,6 +428,7 @@ my_bool opt_secure_auth= 0; my_bool opt_log_slow_admin_statements= 0; my_bool lower_case_file_system= 0; my_bool opt_large_pages= 0; +my_bool opt_myisam_use_mmap= 0; uint opt_large_page_size= 0; my_bool opt_old_style_user_limits= 0, trust_function_creators= 0; /* @@ -4558,6 +4559,7 @@ enum options_mysqld 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_MAX_SORT_FILE_SIZE, OPT_MYISAM_SORT_BUFFER_SIZE, + OPT_MYISAM_USE_MMAP, OPT_MYISAM_STATS_METHOD, OPT_NET_BUFFER_LENGTH, OPT_NET_RETRY_COUNT, OPT_NET_READ_TIMEOUT, OPT_NET_WRITE_TIMEOUT, @@ -5767,6 +5769,11 @@ The minimum value for this variable is 4096.", (gptr*) &global_system_variables.myisam_sort_buff_size, (gptr*) &max_system_variables.myisam_sort_buff_size, 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, "Specifies how MyISAM index statistics collection code should threat NULLs. " "Possible values of name are \"nulls_unequal\" (default behavior for 4.1/5.0), " diff --git a/sql/records.cc b/sql/records.cc index ff0185195b08c82b62be3e91930bd730acc447c2..5cb9b1e5c478baad6f5ab7e7e8a20cb709ef8132 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -153,6 +153,10 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table, info->table=table; info->file= table->file; 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) { info->rec_buf= table->sort.addon_buf; diff --git a/sql/set_var.cc b/sql/set_var.cc index 19dc22653470f5848542350125e476af9cf01909..9d5fb2940cf1a3e53a1a81c6eaa16d340388ef42 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -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_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_bool_ptr sys_myisam_use_mmap("myisam_use_mmap", + &opt_myisam_use_mmap); sys_var_thd_enum sys_myisam_stats_method("myisam_stats_method", &SV::myisam_stats_method, @@ -789,6 +791,7 @@ struct show_var_st init_vars[]= { {sys_myisam_repair_threads.name, (char*) &sys_myisam_repair_threads, 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}, diff --git a/storage/myisam/mi_close.c b/storage/myisam/mi_close.c index 62f5617de1a60825c1921584e439cdb712ee166c..39a91371323db5a3dc9dc97b86e44bc01ed65c99 100644 --- a/storage/myisam/mi_close.c +++ b/storage/myisam/mi_close.c @@ -96,6 +96,7 @@ int mi_close(register MI_INFO *info) { int i,keys; keys = share->state.header.keys; + VOID(rwlock_destroy(&share->mmap_lock)); for(i=0; i<keys; i++) { VOID(rwlock_destroy(&share->key_root_lock[i])); } diff --git a/storage/myisam/mi_delete_all.c b/storage/myisam/mi_delete_all.c index a30abb95070382d1fd0cee3536f5822d2c6cc361..51f1e44d6d25646c3d4a59c2bc7dd4d2def8181e 100644 --- a/storage/myisam/mi_delete_all.c +++ b/storage/myisam/mi_delete_all.c @@ -22,6 +22,7 @@ int mi_delete_all_rows(MI_INFO *info) { uint i; + char buf[22]; MYISAM_SHARE *share=info->s; MI_STATE_INFO *state=&share->state; DBUG_ENTER("mi_delete_all_rows"); @@ -58,6 +59,12 @@ int mi_delete_all_rows(MI_INFO *info) my_chsize(share->kfile, share->base.keystart, 0, MYF(MY_WME)) ) goto err; 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 */ DBUG_RETURN(0); diff --git a/storage/myisam/mi_dynrec.c b/storage/myisam/mi_dynrec.c index 8de500a73519896b4823d4bba364f73aa92b5744..cdcd7b95ce13e44aa9f7029b9f115c9771433445 100644 --- a/storage/myisam/mi_dynrec.c +++ b/storage/myisam/mi_dynrec.c @@ -50,6 +50,174 @@ static int _mi_cmp_buffer(File file, const byte *buff, my_off_t filepos, /* 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) { 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) & BLOCK_DELETED)) DBUG_RETURN(1); /* Something is wrong */ 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))) DBUG_RETURN(1); /* Unlink block from next block */ @@ -253,7 +421,7 @@ static bool unlink_deleted_block(MI_INFO *info, MI_BLOCK_INFO *block_info) & BLOCK_DELETED)) DBUG_RETURN(1); /* Something is wrong */ 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, MYF(MY_NABP))) DBUG_RETURN(1); @@ -304,7 +472,7 @@ static int update_backward_delete_link(MI_INFO *info, my_off_t delete_block, { char buff[8]; 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 */ } else @@ -362,7 +530,7 @@ static int delete_dynamic_record(MI_INFO *info, my_off_t filepos, bfill(block_info.header+12,8,255); else 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))) DBUG_RETURN(1); info->s->state.dellink = filepos; @@ -545,7 +713,7 @@ int _mi_write_part_record(MI_INFO *info, else { 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)) goto err; } @@ -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_sizestore(del_block.header+4,info->s->state.dellink); 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))) DBUG_RETURN(1); info->s->state.dellink= next_pos; @@ -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) 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))) goto panic; left_length-=block_info.data_len; diff --git a/storage/myisam/mi_extra.c b/storage/myisam/mi_extra.c index 7c0dd13b87085b498999d23630755da54f4e537f..04beb36bb4769417bd75a2173e3e60c67503426c 100644 --- a/storage/myisam/mi_extra.c +++ b/storage/myisam/mi_extra.c @@ -93,6 +93,8 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) my_errno=EACCES; break; } + if (info->s->file_map) /* Don't use cache if mmap */ + break; #if defined(HAVE_MMAP) && defined(HAVE_MADVISE) 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) error=1; /* Not possibly if not locked */ break; } + cache_size= (extra_arg ? *(ulong*) extra_arg : my_default_record_cache_size); if (!(info->opt_flag & @@ -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: mi_extra_keyflag(info, function); 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_NO_KEY_CACHE: default: diff --git a/storage/myisam/mi_locking.c b/storage/myisam/mi_locking.c index 8d48c5242e5b33d8b4d6102e22cf75169e67f436..5d871aa1e38e5a845b6481b0cfff2dfc623f15a7 100644 --- a/storage/myisam/mi_locking.c +++ b/storage/myisam/mi_locking.c @@ -38,7 +38,6 @@ int mi_lock_database(MI_INFO *info, int lock_type) share->w_locks, share->global_changed, share->state.open_count, share->index_file_name)); - if (share->options & HA_OPTION_READ_ONLY_DATA || info->lock_type == lock_type) DBUG_RETURN(0); @@ -84,6 +83,14 @@ int mi_lock_database(MI_INFO *info, int lock_type) (uint) 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.unique= info->last_unique= info->this_unique; share->state.update_count= info->last_loop= ++info->this_loop; @@ -215,6 +222,7 @@ int mi_lock_database(MI_INFO *info, int lock_type) } } VOID(_mi_test_if_changed(info)); + info->lock_type=lock_type; info->invalidator=info->s->invalidator; share->w_locks++; diff --git a/storage/myisam/mi_open.c b/storage/myisam/mi_open.c index 91136bbeef58fa3e22ac4faad8b3e8fa0b66e5be..a09e4514d63ac7441908b0a6271d5ff6881c746d 100644 --- a/storage/myisam/mi_open.c +++ b/storage/myisam/mi_open.c @@ -288,6 +288,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) #ifdef THREAD &share->key_root_lock,sizeof(rw_lock_t)*keys, #endif + &share->mmap_lock,sizeof(rw_lock_t), NullS)) goto err; errpos=4; @@ -459,7 +460,6 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) (keys ? MI_INDEX_BLOCK_MARGIN * share->blocksize * keys : 0)); share->blocksize=min(IO_SIZE,myisam_block_size); - share->data_file_type=STATIC_RECORD; if (share->options & HA_OPTION_COMPRESS_RECORD) { @@ -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)); for (i=0; i<keys; i++) VOID(my_rwlock_init(&share->key_root_lock[i], NULL)); + VOID(my_rwlock_init(&share->mmap_lock, NULL)); if (!thr_lock_inited) { /* Probably a single threaded program; Don't use concurrent inserts */ @@ -736,6 +737,8 @@ void mi_setup_functions(register MYISAM_SHARE *share) share->compare_unique=_mi_cmp_static_unique; share->calc_checksum= mi_static_checksum; } + share->file_read= mi_nommap_pread; + share->file_write= mi_nommap_pwrite; if (!(share->options & HA_OPTION_CHECKSUM)) share->calc_checksum=0; return; diff --git a/storage/myisam/mi_packrec.c b/storage/myisam/mi_packrec.c index e242e9d506d943459024fe4ec04943dfc6f805e7..6a1fca9ede9706f9b58446fbc7be68446ecdf238 100644 --- a/storage/myisam/mi_packrec.c +++ b/storage/myisam/mi_packrec.c @@ -1192,34 +1192,25 @@ my_bool _mi_memmap_file(MI_INFO *info) if (!info->s->file_map) { 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_RETURN(0); } - file_map=(byte*) - 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; + if (mi_dynmap_file(info, share->state.state.data_file_length)) DBUG_RETURN(0); - } - info->s->file_map=file_map; } info->opt_flag|= MEMMAP_USED; - info->read_record=share->read_record=_mi_read_mempack_record; - share->read_rnd=_mi_read_rnd_mempack_record; + info->read_record= share->read_record= _mi_read_mempack_record; + share->read_rnd= _mi_read_rnd_mempack_record; DBUG_RETURN(1); } void _mi_unmap_file(MI_INFO *info) { - VOID(my_munmap(info->s->file_map, - (size_t) info->s->state.state.data_file_length+ - MEMMAP_EXTRA_MARGIN)); + VOID(my_munmap(info->s->file_map, + (size_t) info->s->mmaped_length + MEMMAP_EXTRA_MARGIN)); } diff --git a/storage/myisam/mi_statrec.c b/storage/myisam/mi_statrec.c index 42352f63c6691aef593988da047ad991884e88fa..70e63ef8ce1040fff9f3f21c7cfb4598ae1ce93d 100644 --- a/storage/myisam/mi_statrec.c +++ b/storage/myisam/mi_statrec.c @@ -22,20 +22,19 @@ int _mi_write_static_record(MI_INFO *info, const byte *record) { uchar temp[8]; /* max pointer length */ - if (info->s->state.dellink != HA_OFFSET_ERROR && !info->append_insert_at_end) { my_off_t filepos=info->s->state.dellink; 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, MYF(MY_NABP))) goto err; info->s->state.dellink= _mi_rec_pos(info->s,temp); info->state->del--; 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, MYF(MY_NABP))) goto err; @@ -64,19 +63,19 @@ int _mi_write_static_record(MI_INFO *info, const byte *record) else { 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->s->write_flag)) - goto err; + goto err; if (info->s->base.pack_reclength != info->s->base.reclength) { uint length=info->s->base.pack_reclength - info->s->base.reclength; 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->s->base.reclength, info->s->write_flag)) - goto err; + goto err; } } 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) 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 */ - return (my_pwrite(info->dfile, + return (info->s->file_write(info, (char*) record,info->s->base.reclength, pos, MYF(MY_NABP)) != 0); @@ -107,7 +106,7 @@ int _mi_delete_static_record(MI_INFO *info) _mi_dpointer(info,temp+1,info->s->state.dellink); info->s->state.dellink = info->lastpos; 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); } @@ -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 check isn't disabled */ 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, MYF(MY_NABP))) DBUG_RETURN(-1); @@ -154,7 +153,7 @@ int _mi_cmp_static_unique(MI_INFO *info, MI_UNIQUEDEF *def, DBUG_ENTER("_mi_cmp_static_unique"); 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))) DBUG_RETURN(-1); 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, return(-1); 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; fast_mi_writeinfo(info); if (! error) diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h index 6ccb52aff22b71230bfae0ab6dea9bcf7d877558..564acb82e69eca79acde0882e4fbbc081be7503d 100644 --- a/storage/myisam/myisamdef.h +++ b/storage/myisam/myisamdef.h @@ -179,6 +179,8 @@ typedef struct st_mi_isam_share { /* Shared between opens */ ha_checksum (*calc_checksum)(struct st_myisam_info*, const byte *); int (*compare_unique)(struct st_myisam_info*, MI_UNIQUEDEF *, 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 */ ulong this_process; /* processid */ ulong last_process; /* For table-change-check */ @@ -207,6 +209,8 @@ typedef struct st_mi_isam_share { /* Shared between opens */ pthread_mutex_t intern_lock; /* Locking for use with _locking */ rw_lock_t *key_root_lock; #endif + my_off_t mmaped_length; + rw_lock_t mmap_lock; } MYISAM_SHARE; @@ -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 read_pack_length(uint version, const uchar *buf, 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); uchar *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state);