#include <my_base.h>#include <m_ctype.h>#include "keycache.h"#include "my_handler.h"#include <mysql/plugin.h>Include dependency graph for myisam.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.
| #define mi_clear_all_keys_active | ( | _keymap_ | ) | (_keymap_)= 0 |
Definition at line 121 of file myisam.h.
Referenced by mi_disable_indexes(), mi_init_bulk_insert(), save_state(), and save_state_mrg().
| #define mi_clear_key_active | ( | _keymap_, | |||
| _keyno_ | ) | (_keymap_)&= (~ (ULL(1) << (_keyno_))) |
Definition at line 110 of file myisam.h.
Referenced by mi_disable_non_unique_index(), and mi_extra().
| #define mi_copy_keys_active | ( | _to_, | |||
| _maxkeys_, | |||||
| _from_ | ) |
Value:
(_to_)= (mi_get_mask_all_keys_active(_maxkeys_) & \ (_from_))
Definition at line 128 of file myisam.h.
Referenced by myisamchk().
| #define mi_get_mask_all_keys_active | ( | _keys_ | ) |
Value:
(((_keys_) < MI_KEYMAP_BITS) ? \ ((ULL(1) << (_keys_)) - ULL(1)) : \ (~ ULL(0)))
Definition at line 84 of file myisam.h.
Referenced by ha_myisam::repair().
| #define mi_intersect_keys_active | ( | _to_, | |||
| _from_ | ) | (_to_)&= (_from_) |
| #define mi_is_all_keys_active | ( | _keymap_, | |||
| _keys_ | ) | ((_keymap_) == mi_get_mask_all_keys_active(_keys_)) |
Definition at line 117 of file myisam.h.
Referenced by descript(), ha_myisam::enable_indexes(), open_isam_files(), save_state(), and ha_myisam::start_bulk_insert().
| #define mi_is_any_intersect_keys_active | ( | _keymap1_, | |||
| _keys_, | |||||
| _keymap2_ | ) |
Value:
((_keymap1_) & (_keymap2_) & \
mi_get_mask_all_keys_active(_keys_))
Definition at line 125 of file myisam.h.
Referenced by myisamchk().
| #define mi_is_any_key_active | ( | _keymap_ | ) | test((_keymap_)) |
Definition at line 115 of file myisam.h.
Referenced by chk_key(), chk_size(), mi_extra(), mi_indexes_are_disabled(), mi_preload(), mi_test_if_sort_rep(), and myisamchk().
| #define mi_is_key_active | ( | _keymap_, | |||
| _keyno_ | ) | test((_keymap_) & (ULL(1) << (_keyno_))) |
Definition at line 106 of file myisam.h.
Referenced by _mi_check_index(), chk_key(), find_record_with_key(), mi_init_bulk_insert(), mi_repair_by_sort(), mi_repair_parallel(), mi_rsame(), mi_rsame_with_pos(), mi_sort_index(), mi_sort_records(), movepoint(), update_auto_increment_key(), and writekeys().
| #define MI_KEY_BLOCK_LENGTH 1024 |
| #define MI_KEYMAP_HIGH_MASK (ULL(1) << (MI_KEYMAP_BITS - 1)) |
| #define MI_MAX_KEY MAX_INDEXES |
Definition at line 50 of file myisam.h.
Referenced by get_one_option(), ha_myisammrg::max_supported_keys(), ha_myisam::max_supported_keys(), mi_create(), and mi_open().
| #define MI_MAX_KEY_BLOCK_LENGTH 16384 |
| #define MI_MAX_KEY_BUFF (MI_MAX_KEY_LENGTH+MI_MAX_KEY_SEG*6+8+8) |
Definition at line 61 of file myisam.h.
Referenced by _mi_balance_page(), _mi_ck_real_delete(), _mi_find_last_pos(), _mi_get_binary_pack_key(), _mi_keynr(), _mi_prefix_search(), _mi_search(), _mi_search_next(), _mi_seq_search(), d_search(), del(), find_record_with_key(), ftb_query_add_word(), keys_free(), mi_open(), mi_update(), sort_record_index(), underflow(), and w_search().
| #define MI_MAX_KEY_LENGTH 1000 |
Definition at line 58 of file myisam.h.
Referenced by ha_myisam::get_auto_increment(), get_one_option(), ha_myisammrg::max_supported_key_length(), ha_myisam::max_supported_key_length(), ha_myisammrg::max_supported_key_part_length(), and ha_myisam::max_supported_key_part_length().
| #define MI_MAX_KEY_SEG 16 |
| #define MI_MAX_MSG_BUF 1024 |
| #define MI_MAX_POSSIBLE_KEY 255 |
Definition at line 46 of file myisam.h.
Referenced by chk_data_link(), mi_create(), mi_open(), and mi_sort_index().
| #define MI_MAX_POSSIBLE_KEY_BUFF (1024+6+6) |
| #define MI_MIN_KEY_BLOCK_LENGTH 1024 |
Definition at line 70 of file myisam.h.
Referenced by _mi_kpointer(), _mi_kpos(), _mi_write_keypage(), check_k_link(), get_options(), main(), mi_delete_all_rows(), mi_keydef_read(), and mi_open().
| #define MI_NAME_DEXT ".MYD" |
Definition at line 64 of file myisam.h.
Referenced by ha_myisam::backup(), compress(), ha_myisam::info(), mi_delete_table(), mi_open(), mi_rename(), mi_sort_records(), myisamchk(), and ha_myisam::restore().
| #define MI_NAME_IEXT ".MYI" |
Definition at line 63 of file myisam.h.
Referenced by compress(), ha_myisam::info(), mi_delete_table(), mi_open(), mi_rename(), mi_sort_index(), and myisamchk().
| #define mi_portable_sizeof_char_ptr 8 |
Definition at line 73 of file myisam.h.
Referenced by _mi_rec_check(), _mi_rec_pack(), _mi_rec_unpack(), create_tmp_table(), create_virtual_tmp_table(), main(), mi_checksum(), mi_create(), run_test(), and uf_blob().
| #define mi_set_all_keys_active | ( | _keymap_, | |||
| _keys_ | ) | (_keymap_)= mi_get_mask_all_keys_active(_keys_) |
| #define mi_set_key_active | ( | _keymap_, | |||
| _keyno_ | ) | (_keymap_)|= (ULL(1) << (_keyno_)) |
| #define MI_UNIQUE_HASH_LENGTH 4 |
Definition at line 217 of file myisam.h.
Referenced by create_myisam_tmp_table(), create_tmp_table(), mi_check_unique(), and run_test().
| #define O_DATA_LOST 4 |
Definition at line 375 of file myisam.h.
Referenced by mi_check_print_error(), mi_check_print_warning(), and sort_get_next_record().
| #define O_NEW_DATA 2 |
| #define O_NEW_INDEX 1 |
| #define T_AUTO_INC 1 |
Definition at line 330 of file myisam.h.
Referenced by chk_key(), get_one_option(), get_options(), and myisamchk().
| #define T_AUTO_REPAIR 2 |
Definition at line 331 of file myisam.h.
Referenced by ha_myisam::check_and_repair(), and mi_check_print_msg().
| #define T_BACKUP_DATA 4 |
Definition at line 332 of file myisam.h.
Referenced by ha_myisam::check_and_repair(), get_one_option(), and myisamchk().
| #define T_CALC_CHECKSUM 8 |
Definition at line 333 of file myisam.h.
Referenced by get_one_option(), get_options(), mi_repair(), mi_repair_by_sort(), mi_repair_parallel(), ha_myisam::repair(), and ha_myisam::restore().
| #define T_CHECK 16 |
Definition at line 334 of file myisam.h.
Referenced by ha_myisam::analyze(), ha_myisam::check(), get_one_option(), and myisamchk().
| #define T_CHECK_ONLY_CHANGED 32 |
Definition at line 335 of file myisam.h.
Referenced by ha_myisam::check(), get_one_option(), and myisamchk().
| #define T_CREATE_MISSING_KEYS 64 |
Definition at line 336 of file myisam.h.
Referenced by ha_myisam::enable_indexes(), mi_check_print_msg(), mi_repair(), mi_repair_by_sort(), mi_repair_parallel(), and ha_myisam::repair().
| #define T_DESCRIPT 128 |
Definition at line 337 of file myisam.h.
Referenced by get_one_option(), myisamchk(), and recreate_table().
| #define T_DONT_CHECK_CHECKSUM 256 |
| #define T_EXTEND 512 |
Definition at line 339 of file myisam.h.
Referenced by ha_myisam::check(), get_one_option(), main(), myisamchk(), mysql_checksum_table(), ha_archive::optimize(), ha_archive::repair(), and ha_myisam::repair().
| #define T_FAST (1L << 10) |
Definition at line 340 of file myisam.h.
Referenced by ha_myisam::analyze(), ha_myisam::check(), get_one_option(), and myisamchk().
| #define T_FORCE_CREATE (1L << 11) |
Definition at line 341 of file myisam.h.
Referenced by get_one_option(), get_options(), main(), myisamchk(), ha_myisam::optimize(), and ha_myisam::repair().
| #define T_FORCE_UNIQUENESS (1L << 12) |
Definition at line 342 of file myisam.h.
Referenced by get_one_option(), mi_repair(), and myisamchk().
| #define T_INFO (1L << 13) |
Definition at line 343 of file myisam.h.
Referenced by chk_key(), get_one_option(), main(), and myisamchk().
| #define T_MEDIUM (1L << 14) |
Definition at line 344 of file myisam.h.
Referenced by ha_myisam::check(), ha_myisam::check_and_repair(), get_one_option(), handler::ha_check_for_upgrade(), and myisamchk().
| #define T_QUICK (1L << 15) |
Definition at line 345 of file myisam.h.
Referenced by ha_myisam::check(), ha_myisam::check_and_repair(), ha_myisam::enable_indexes(), get_one_option(), get_options(), mi_repair(), myisamchk(), mysql_checksum_table(), ha_myisam::repair(), ha_myisam::restore(), and sort_delete_record().
| #define T_READONLY (1L << 16) |
Definition at line 346 of file myisam.h.
Referenced by get_one_option(), get_options(), and myisamchk().
| #define T_REP (1L << 17) |
Definition at line 347 of file myisam.h.
Referenced by get_one_option(), main(), mi_repair(), mi_repair_by_sort(), mi_repair_parallel(), myisamchk(), ha_myisam::repair(), and update_auto_increment_key().
| #define T_REP_ANY (T_REP | T_REP_BY_SORT | T_REP_PARALLEL) |
Definition at line 363 of file myisam.h.
Referenced by get_one_option(), get_options(), main(), and myisamchk().
| #define T_REP_BY_SORT (1L << 18) |
Definition at line 348 of file myisam.h.
Referenced by ha_myisam::enable_indexes(), get_one_option(), main(), myisamchk(), ha_myisam::optimize(), and ha_myisam::repair().
| #define T_REP_PARALLEL (1L << 19) |
| #define T_RETRY_WITHOUT_QUICK (1L << 20) |
Definition at line 350 of file myisam.h.
Referenced by chk_del(), chk_size(), mi_repair(), ha_myisam::repair(), sort_get_next_record(), and sort_key_write().
| #define T_SAFE_REPAIR (1L << 21) |
Definition at line 351 of file myisam.h.
Referenced by ha_myisam::check_and_repair(), and mi_check_print_msg().
| #define T_SILENT (1L << 22) |
Definition at line 352 of file myisam.h.
Referenced by ha_myisam::analyze(), ha_myisam::check(), chk_data_link(), chk_del(), chk_key(), chk_size(), descript(), ha_myisam::enable_indexes(), get_one_option(), main(), mi_check_print_error(), mi_check_print_warning(), mi_repair(), mi_repair_by_sort(), mi_repair_parallel(), mi_sort_index(), mi_sort_records(), myisamchk(), ha_myisam::optimize(), ha_myisam::repair(), and update_auto_increment_key().
| #define T_SORT_INDEX (1L << 23) |
Definition at line 353 of file myisam.h.
Referenced by get_one_option(), get_options(), main(), myisamchk(), ha_myisam::optimize(), and ha_myisam::repair().
| #define T_SORT_RECORDS (1L << 24) |
Definition at line 354 of file myisam.h.
Referenced by get_one_option(), get_options(), main(), and myisamchk().
| #define T_STATISTICS (1L << 25) |
Definition at line 355 of file myisam.h.
Referenced by ha_myisam::analyze(), ha_myisam::check(), chk_index(), chk_key(), get_one_option(), get_options(), myisamchk(), ha_myisam::optimize(), and ha_myisam::repair().
| #define T_UNPACK (1L << 26) |
Definition at line 356 of file myisam.h.
Referenced by get_one_option(), get_options(), mi_repair(), mi_repair_by_sort(), mi_repair_parallel(), myisamchk(), recreate_table(), and set_data_file_type().
| #define T_UPDATE_STATE (1L << 27) |
Definition at line 357 of file myisam.h.
Referenced by chk_status(), get_one_option(), get_options(), and myisamchk().
| #define T_VERBOSE (1L << 28) |
Definition at line 358 of file myisam.h.
Referenced by check_k_link(), chk_del(), chk_key(), descript(), get_one_option(), mi_repair(), myisamchk(), and sort_key_write().
| #define T_VERY_SILENT (1L << 29) |
Definition at line 359 of file myisam.h.
Referenced by chk_size(), get_one_option(), ha_myisam::repair(), ha_myisam::restore(), and update_auto_increment_key().
| #define T_WAIT_FOREVER (1L << 30) |
Definition at line 360 of file myisam.h.
Referenced by get_one_option(), lock_file(), myisamchk(), and recreate_table().
| #define T_WRITE_LOOP ((ulong) 1L << 31) |
Definition at line 361 of file myisam.h.
Referenced by get_one_option(), get_options(), and sort_write_record().
| #define TT_FOR_UPGRADE 2 |
Definition at line 371 of file myisam.h.
Referenced by handler::ha_check(), and handler::ha_check_for_upgrade().
| #define TT_USEFRM 1 |
Definition at line 370 of file myisam.h.
Referenced by mysql_repair_table(), and prepare_for_repair().
| typedef void(* ) invalidator_by_filename(const char *filename) |
| typedef struct st_mi_check_param MI_CHECK |
| typedef struct st_columndef MI_COLUMNDEF |
| typedef struct st_mi_create_info MI_CREATE_INFO |
| typedef struct st_mi_decode_tree MI_DECODE_TREE |
| typedef struct st_myisam_info MI_INFO |
| typedef struct st_mi_isaminfo MI_ISAMINFO |
| typedef struct st_mi_keydef MI_KEYDEF |
| typedef struct st_unique_def MI_UNIQUEDEF |
| typedef struct st_sort_ft_buf SORT_FT_BUF |
| typedef struct st_sort_info SORT_INFO |
| typedef struct st_sort_key_blocks SORT_KEY_BLOCKS |
| enum enum_mi_stats_method |
| MI_STATS_METHOD_NULLS_NOT_EQUAL | |
| MI_STATS_METHOD_NULLS_EQUAL | |
| MI_STATS_METHOD_IGNORE_NULLS |
Definition at line 394 of file myisam.h.
00395 { 00396 /* Treat NULLs as inequal when collecting statistics (default for 4.1/5.0) */ 00397 MI_STATS_METHOD_NULLS_NOT_EQUAL, 00398 /* Treat NULLs as equal when collecting statistics (like 4.0 did) */ 00399 MI_STATS_METHOD_NULLS_EQUAL, 00400 /* Ignore NULLs - count only tuples without NULLs in the index components */ 00401 MI_STATS_METHOD_IGNORE_NULLS 00402 } enum_mi_stats_method;
Definition at line 1268 of file mi_dynrec.c.
References uint2korr, uint3korr, and uint4korr.
Referenced by _mi_ft_segiterator(), _mi_make_key(), _mi_rec_check(), _mi_rec_unpack(), _my_calc_total_blob_length(), fix_blob_pointers(), mi_checksum(), mi_unique_comp(), and mi_unique_hash().
01269 { 01270 switch (length) { 01271 case 1: 01272 return (uint) (uchar) *pos; 01273 case 2: 01274 return (uint) uint2korr(pos); 01275 case 3: 01276 return uint3korr(pos); 01277 case 4: 01278 return uint4korr(pos); 01279 default: 01280 break; 01281 } 01282 return 0; /* Impossible */ 01283 }
Here is the caller graph for this function:

Definition at line 856 of file mi_check.c.
References st_mi_isam_share::base, st_columndef::base_type, COMPRESSED_RECORD, st_mi_isam_share::data_file_type, DBUG_ENTER, DBUG_RETURN, empty, error, FIELD_BLOB, FIELD_VARCHAR, st_mi_base_info::fields, flag, st_mi_check_param::glob_crc, st_mi_isam_pack::header_length, key, keyinfo, LINT_INIT, mi_check_print_error(), MI_MAX_POSSIBLE_KEY, my_malloc(), MYF, st_mi_isam_share::pack, st_mi_base_info::pack_reclength, pos(), st_mi_isam_share::rec, records, st_myisam_info::s, T_SILENT, st_mi_check_param::testflag, and to.
Referenced by ha_myisam::check(), and myisamchk().
00857 { 00858 int error,got_error,flag; 00859 uint key,left_length,b_type,field; 00860 ha_rows records,del_blocks; 00861 my_off_t used,empty,pos,splits,start_recpos, 00862 del_length,link_used,start_block; 00863 byte *record,*to; 00864 char llbuff[22],llbuff2[22],llbuff3[22]; 00865 ha_checksum intern_record_checksum; 00866 ha_checksum key_checksum[MI_MAX_POSSIBLE_KEY]; 00867 my_bool static_row_size; 00868 MI_KEYDEF *keyinfo; 00869 MI_BLOCK_INFO block_info; 00870 DBUG_ENTER("chk_data_link"); 00871 00872 if (!(param->testflag & T_SILENT)) 00873 { 00874 if (extend) 00875 puts("- check records and index references"); 00876 else 00877 puts("- check record links"); 00878 } 00879 00880 if (!(record= (byte*) my_malloc(info->s->base.pack_reclength,MYF(0)))) 00881 { 00882 mi_check_print_error(param,"Not enough memory for record"); 00883 DBUG_RETURN(-1); 00884 } 00885 records=del_blocks=0; 00886 used=link_used=splits=del_length=0; 00887 intern_record_checksum=param->glob_crc=0; 00888 LINT_INIT(left_length); LINT_INIT(start_recpos); LINT_INIT(to); 00889 got_error=error=0; 00890 empty=info->s->pack.header_length; 00891 00892 /* Check how to calculate checksum of rows */ 00893 static_row_size=1; 00894 if (info->s->data_file_type == COMPRESSED_RECORD) 00895 { 00896 for (field=0 ; field < info->s->base.fields ; field++) 00897 { 00898 if (info->s->rec[field].base_type == FIELD_BLOB || 00899 info->s->rec[field].base_type == FIELD_VARCHAR) 00900 { 00901 static_row_size=0; 00902 break; 00903 } 00904 } 00905 } 00906 00907 pos=my_b_tell(¶m->read_cache); 00908 bzero((char*) key_checksum, info->s->base.keys * sizeof(key_checksum[0])); 00909 while (pos < info->state->data_file_length) 00910 { 00911 if (*killed_ptr(param)) 00912 goto err2; 00913 switch (info->s->data_file_type) { 00914 case STATIC_RECORD: 00915 if (my_b_read(¶m->read_cache,(byte*) record, 00916 info->s->base.pack_reclength)) 00917 goto err; 00918 start_recpos=pos; 00919 pos+=info->s->base.pack_reclength; 00920 splits++; 00921 if (*record == '\0') 00922 { 00923 del_blocks++; 00924 del_length+=info->s->base.pack_reclength; 00925 continue; /* Record removed */ 00926 } 00927 param->glob_crc+= mi_static_checksum(info,record); 00928 used+=info->s->base.pack_reclength; 00929 break; 00930 case DYNAMIC_RECORD: 00931 flag=block_info.second_read=0; 00932 block_info.next_filepos=pos; 00933 do 00934 { 00935 if (_mi_read_cache(¶m->read_cache,(byte*) block_info.header, 00936 (start_block=block_info.next_filepos), 00937 sizeof(block_info.header), 00938 (flag ? 0 : READING_NEXT) | READING_HEADER)) 00939 goto err; 00940 if (start_block & (MI_DYN_ALIGN_SIZE-1)) 00941 { 00942 mi_check_print_error(param,"Wrong aligned block at %s", 00943 llstr(start_block,llbuff)); 00944 goto err2; 00945 } 00946 b_type=_mi_get_block_info(&block_info,-1,start_block); 00947 if (b_type & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR | 00948 BLOCK_FATAL_ERROR)) 00949 { 00950 if (b_type & BLOCK_SYNC_ERROR) 00951 { 00952 if (flag) 00953 { 00954 mi_check_print_error(param,"Unexpected byte: %d at link: %s", 00955 (int) block_info.header[0], 00956 llstr(start_block,llbuff)); 00957 goto err2; 00958 } 00959 pos=block_info.filepos+block_info.block_len; 00960 goto next; 00961 } 00962 if (b_type & BLOCK_DELETED) 00963 { 00964 if (block_info.block_len < info->s->base.min_block_length) 00965 { 00966 mi_check_print_error(param, 00967 "Deleted block with impossible length %lu at %s", 00968 block_info.block_len,llstr(pos,llbuff)); 00969 goto err2; 00970 } 00971 if ((block_info.next_filepos != HA_OFFSET_ERROR && 00972 block_info.next_filepos >= info->state->data_file_length) || 00973 (block_info.prev_filepos != HA_OFFSET_ERROR && 00974 block_info.prev_filepos >= info->state->data_file_length)) 00975 { 00976 mi_check_print_error(param,"Delete link points outside datafile at %s", 00977 llstr(pos,llbuff)); 00978 goto err2; 00979 } 00980 del_blocks++; 00981 del_length+=block_info.block_len; 00982 pos=block_info.filepos+block_info.block_len; 00983 splits++; 00984 goto next; 00985 } 00986 mi_check_print_error(param,"Wrong bytesec: %d-%d-%d at linkstart: %s", 00987 block_info.header[0],block_info.header[1], 00988 block_info.header[2], 00989 llstr(start_block,llbuff)); 00990 goto err2; 00991 } 00992 if (info->state->data_file_length < block_info.filepos+ 00993 block_info.block_len) 00994 { 00995 mi_check_print_error(param, 00996 "Recordlink that points outside datafile at %s", 00997 llstr(pos,llbuff)); 00998 got_error=1; 00999 break; 01000 } 01001 splits++; 01002 if (!flag++) /* First block */ 01003 { 01004 start_recpos=pos; 01005 pos=block_info.filepos+block_info.block_len; 01006 if (block_info.rec_len > (uint) info->s->base.max_pack_length) 01007 { 01008 mi_check_print_error(param,"Found too long record (%lu) at %s", 01009 (ulong) block_info.rec_len, 01010 llstr(start_recpos,llbuff)); 01011 got_error=1; 01012 break; 01013 } 01014 if (info->s->base.blobs) 01015 { 01016 if (!(to= mi_alloc_rec_buff(info, block_info.rec_len, 01017 &info->rec_buff))) 01018 { 01019 mi_check_print_error(param, 01020 "Not enough memory (%lu) for blob at %s", 01021 (ulong) block_info.rec_len, 01022 llstr(start_recpos,llbuff)); 01023 got_error=1; 01024 break; 01025 } 01026 } 01027 else 01028 to= info->rec_buff; 01029 left_length=block_info.rec_len; 01030 } 01031 if (left_length < block_info.data_len) 01032 { 01033 mi_check_print_error(param,"Found too long record (%lu) at %s", 01034 (ulong) block_info.data_len, 01035 llstr(start_recpos,llbuff)); 01036 got_error=1; 01037 break; 01038 } 01039 if (_mi_read_cache(¶m->read_cache,(byte*) to,block_info.filepos, 01040 (uint) block_info.data_len, 01041 flag == 1 ? READING_NEXT : 0)) 01042 goto err; 01043 to+=block_info.data_len; 01044 link_used+= block_info.filepos-start_block; 01045 used+= block_info.filepos - start_block + block_info.data_len; 01046 empty+=block_info.block_len-block_info.data_len; 01047 left_length-=block_info.data_len; 01048 if (left_length) 01049 { 01050 if (b_type & BLOCK_LAST) 01051 { 01052 mi_check_print_error(param, 01053 "Wrong record length %s of %s at %s", 01054 llstr(block_info.rec_len-left_length,llbuff), 01055 llstr(block_info.rec_len, llbuff2), 01056 llstr(start_recpos,llbuff3)); 01057 got_error=1; 01058 break; 01059 } 01060 if (info->state->data_file_length < block_info.next_filepos) 01061 { 01062 mi_check_print_error(param, 01063 "Found next-recordlink that points outside datafile at %s", 01064 llstr(block_info.filepos,llbuff)); 01065 got_error=1; 01066 break; 01067 } 01068 } 01069 } while (left_length); 01070 if (! got_error) 01071 { 01072 if (_mi_rec_unpack(info,record,info->rec_buff,block_info.rec_len) == 01073 MY_FILE_ERROR) 01074 { 01075 mi_check_print_error(param,"Found wrong record at %s", 01076 llstr(start_recpos,llbuff)); 01077 got_error=1; 01078 } 01079 else 01080 { 01081 info->checksum=mi_checksum(info,record); 01082 if (param->testflag & (T_EXTEND | T_MEDIUM | T_VERBOSE)) 01083 { 01084 if (_mi_rec_check(info,record, info->rec_buff,block_info.rec_len, 01085 test(info->s->calc_checksum))) 01086 { 01087 mi_check_print_error(param,"Found wrong packed record at %s", 01088 llstr(start_recpos,llbuff)); 01089 got_error=1; 01090 } 01091 } 01092 if (!got_error) 01093 param->glob_crc+= info->checksum; 01094 } 01095 } 01096 else if (!flag) 01097 pos=block_info.filepos+block_info.block_len; 01098 break; 01099 case COMPRESSED_RECORD: 01100 if (_mi_read_cache(¶m->read_cache,(byte*) block_info.header, pos, 01101 info->s->pack.ref_length, READING_NEXT)) 01102 goto err; 01103 start_recpos=pos; 01104 splits++; 01105 VOID(_mi_pack_get_block_info(info,&block_info, -1, start_recpos)); 01106 pos=block_info.filepos+block_info.rec_len; 01107 if (block_info.rec_len < (uint) info->s->min_pack_length || 01108 block_info.rec_len > (uint) info->s->max_pack_length) 01109 { 01110 mi_check_print_error(param, 01111 "Found block with wrong recordlength: %d at %s", 01112 block_info.rec_len, llstr(start_recpos,llbuff)); 01113 got_error=1; 01114 break; 01115 } 01116 if (_mi_read_cache(¶m->read_cache,(byte*) info->rec_buff, 01117 block_info.filepos, block_info.rec_len, READING_NEXT)) 01118 goto err; 01119 if (_mi_pack_rec_unpack(info,record,info->rec_buff,block_info.rec_len)) 01120 { 01121 mi_check_print_error(param,"Found wrong record at %s", 01122 llstr(start_recpos,llbuff)); 01123 got_error=1; 01124 } 01125 if (static_row_size) 01126 param->glob_crc+= mi_static_checksum(info,record); 01127 else 01128 param->glob_crc+= mi_checksum(info,record); 01129 link_used+= (block_info.filepos - start_recpos); 01130 used+= (pos-start_recpos); 01131 } /* switch */ 01132 if (! got_error) 01133 { 01134 intern_record_checksum+=(ha_checksum) start_recpos; 01135 records++; 01136 if (param->testflag & T_WRITE_LOOP && records % WRITE_COUNT == 0) 01137 { 01138 printf("%s\r", llstr(records,llbuff)); VOID(fflush(stdout)); 01139 } 01140 01141 /* Check if keys match the record */ 01142 01143 for (key=0,keyinfo= info->s->keyinfo; key < info->s->base.keys; 01144 key++,keyinfo++) 01145 { 01146 if (mi_is_key_active(info->s->state.key_map, key)) 01147 { 01148 if(!(keyinfo->flag & HA_FULLTEXT)) 01149 { 01150 uint key_length=_mi_make_key(info,key,info->lastkey,record, 01151 start_recpos); 01152 if (extend) 01153 { 01154 /* We don't need to lock the key tree here as we don't allow 01155 concurrent threads when running myisamchk 01156 */ 01157 int search_result= 01158 #ifdef HAVE_RTREE_KEYS 01159 (keyinfo->flag & HA_SPATIAL) ? 01160 rtree_find_first(info, key, info->lastkey, key_length, 01161 MBR_EQUAL | MBR_DATA) : 01162 #endif 01163 _mi_search(info,keyinfo,info->lastkey,key_length, 01164 SEARCH_SAME, info->s->state.key_root[key]); 01165 if (search_result) 01166 { 01167 mi_check_print_error(param,"Record at: %10s " 01168 "Can't find key for index: %2d", 01169 llstr(start_recpos,llbuff),key+1); 01170 if (error++ > MAXERR || !(param->testflag & T_VERBOSE)) 01171 goto err2; 01172 } 01173 } 01174 else 01175 key_checksum[key]+=mi_byte_checksum((byte*) info->lastkey, 01176 key_length); 01177 } 01178 } 01179 } 01180 } 01181 else 01182 { 01183 got_error=0; 01184 if (error++ > MAXERR || !(param->testflag & T_VERBOSE)) 01185 goto err2; 01186 } 01187 next:; /* Next record */ 01188 } 01189 if (param->testflag & T_WRITE_LOOP) 01190 { 01191 VOID(fputs(" \r",stdout)); VOID(fflush(stdout)); 01192 } 01193 if (records != info->state->records) 01194 { 01195 mi_check_print_error(param,"Record-count is not ok; is %-10s Should be: %s", 01196 llstr(records,llbuff), llstr(info->state->records,llbuff2)); 01197 error=1; 01198 } 01199 else if (param->record_checksum && 01200 param->record_checksum != intern_record_checksum) 01201 { 01202 mi_check_print_error(param, 01203 "Keypointers and record positions doesn't match"); 01204 error=1; 01205 } 01206 else if (param->glob_crc != info->state->checksum && 01207 (info->s->options & 01208 (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))) 01209 { 01210 mi_check_print_warning(param, 01211 "Record checksum is not the same as checksum stored in the index file\n"); 01212 error=1; 01213 } 01214 else if (!extend) 01215 { 01216 for (key=0 ; key < info->s->base.keys; key++) 01217 { 01218 if (key_checksum[key] != param->key_crc[key] && 01219 !(info->s->keyinfo[key].flag & (HA_FULLTEXT | HA_SPATIAL))) 01220 { 01221 mi_check_print_error(param,"Checksum for key: %2d doesn't match checksum for records", 01222 key+1); 01223 error=1; 01224 } 01225 } 01226 } 01227 01228 if (del_length != info->state->empty) 01229 { 01230 mi_check_print_warning(param, 01231 "Found %s deleted space. Should be %s", 01232 llstr(del_length,llbuff2), 01233 llstr(info->state->empty,llbuff)); 01234 } 01235 if (used+empty+del_length != info->state->data_file_length) 01236 { 01237 mi_check_print_warning(param, 01238 "Found %s record-data and %s unused data and %s deleted-data", 01239 llstr(used,llbuff),llstr(empty,llbuff2), 01240 llstr(del_length,llbuff3)); 01241 mi_check_print_warning(param, 01242 "Total %s, Should be: %s", 01243 llstr((used+empty+del_length),llbuff), 01244 llstr(info->state->data_file_length,llbuff2)); 01245 } 01246 if (del_blocks != info->state->del) 01247 { 01248 mi_check_print_warning(param, 01249 "Found %10s deleted blocks Should be: %s", 01250 llstr(del_blocks,llbuff), 01251 llstr(info->state->del,llbuff2)); 01252 } 01253 if (splits != info->s->state.split) 01254 { 01255 mi_check_print_warning(param, 01256 "Found %10s parts Should be: %s parts", 01257 llstr(splits,llbuff), 01258 llstr(info->s->state.split,llbuff2)); 01259 } 01260 if (param->testflag & T_INFO) 01261 { 01262 if (param->warning_printed || param->error_printed) 01263 puts(""); 01264 if (used != 0 && ! param->error_printed) 01265 { 01266 printf("Records:%18s M.recordlength:%9lu Packed:%14.0f%%\n", 01267 llstr(records,llbuff), (long)((used-link_used)/records), 01268 (info->s->base.blobs ? 0.0 : 01269 (ulonglong2double((ulonglong) info->s->base.reclength*records)- 01270 my_off_t2double(used))/ 01271 ulonglong2double((ulonglong) info->s->base.reclength*records)*100.0)); 01272 printf("Recordspace used:%9.0f%% Empty space:%12d%% Blocks/Record: %6.2f\n", 01273 (ulonglong2double(used-link_used)/ulonglong2double(used-link_used+empty)*100.0), 01274 (!records ? 100 : (int) (ulonglong2double(del_length+empty)/ 01275 my_off_t2double(used)*100.0)), 01276 ulonglong2double(splits - del_blocks) / records); 01277 } 01278 printf("Record blocks:%12s Delete blocks:%10s\n", 01279 llstr(splits-del_blocks,llbuff),llstr(del_blocks,llbuff2)); 01280 printf("Record data: %12s Deleted data: %10s\n", 01281 llstr(used-link_used,llbuff),llstr(del_length,llbuff2)); 01282 printf("Lost space: %12s Linkdata: %10s\n", 01283 llstr(empty,llbuff),llstr(link_used,llbuff2)); 01284 } 01285 my_free((gptr) record,MYF(0)); 01286 DBUG_RETURN (error); 01287 err: 01288 mi_check_print_error(param,"got error: %d when reading datafile at record: %s",my_errno, llstr(records,llbuff)); 01289 err2: 01290 my_free((gptr) record,MYF(0)); 01291 param->testflag|=T_RETRY_WITHOUT_QUICK; 01292 DBUG_RETURN(1); 01293 } /* chk_data_link */
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 116 of file mi_check.c.
References _mi_rec_pos(), DBUG_ENTER, DBUG_RETURN, empty, HA_OFFSET_ERROR, HA_OPTION_PACK_RECORD, killed_ptr(), LINT_INIT, llstr(), mi_check_print_error(), mi_check_print_warning(), mi_sizekorr, mi_uint3korr, MY_NABP, my_pread(), MYF, st_mi_check_param::record_checksum, reg2, T_RETRY_WITHOUT_QUICK, T_SILENT, T_VERBOSE, and st_mi_check_param::testflag.
Referenced by ha_myisam::check(), and myisamchk().
00117 { 00118 reg2 ha_rows i; 00119 uint delete_link_length; 00120 my_off_t empty,next_link,old_link; 00121 char buff[22],buff2[22]; 00122 DBUG_ENTER("chk_del"); 00123 00124 LINT_INIT(old_link); 00125 param->record_checksum=0; 00126 delete_link_length=((info->s->options & HA_OPTION_PACK_RECORD) ? 20 : 00127 info->s->rec_reflength+1); 00128 00129 if (!(test_flag & T_SILENT)) 00130 puts("- check record delete-chain"); 00131 00132 next_link=info->s->state.dellink; 00133 if (info->state->del == 0) 00134 { 00135 if (test_flag & T_VERBOSE) 00136 { 00137 puts("No recordlinks"); 00138 } 00139 } 00140 else 00141 { 00142 if (test_flag & T_VERBOSE) 00143 printf("Recordlinks: "); 00144 empty=0; 00145 for (i= info->state->del ; i > 0L && next_link != HA_OFFSET_ERROR ; i--) 00146 { 00147 if (*killed_ptr(param)) 00148 DBUG_RETURN(1); 00149 if (test_flag & T_VERBOSE) 00150 printf(" %9s",llstr(next_link,buff)); 00151 if (next_link >= info->state->data_file_length) 00152 goto wrong; 00153 if (my_pread(info->dfile,(char*) buff,delete_link_length, 00154 next_link,MYF(MY_NABP))) 00155 { 00156 if (test_flag & T_VERBOSE) puts(""); 00157 mi_check_print_error(param,"Can't read delete-link at filepos: %s", 00158 llstr(next_link,buff)); 00159 DBUG_RETURN(1); 00160 } 00161 if (*buff != '\0') 00162 { 00163 if (test_flag & T_VERBOSE) puts(""); 00164 mi_check_print_error(param,"Record at pos: %s is not remove-marked", 00165 llstr(next_link,buff)); 00166 goto wrong; 00167 } 00168 if (info->s->options & HA_OPTION_PACK_RECORD) 00169 { 00170 my_off_t prev_link=mi_sizekorr(buff+12); 00171 if (empty && prev_link != old_link) 00172 { 00173 if (test_flag & T_VERBOSE) puts(""); 00174 mi_check_print_error(param,"Deleted block at %s doesn't point back at previous delete link",llstr(next_link,buff2)); 00175 goto wrong; 00176 } 00177 old_link=next_link; 00178 next_link=mi_sizekorr(buff+4); 00179 empty+=mi_uint3korr(buff+1); 00180 } 00181 else 00182 { 00183 param->record_checksum+=(ha_checksum) next_link; 00184 next_link=_mi_rec_pos(info->s,(uchar*) buff+1); 00185 empty+=info->s->base.pack_reclength; 00186 } 00187 } 00188 if (test_flag & T_VERBOSE) 00189 puts("\n"); 00190 if (empty != info->state->empty) 00191 { 00192 mi_check_print_warning(param, 00193 "Found %s deleted space in delete link chain. Should be %s", 00194 llstr(empty,buff2), 00195 llstr(info->state->empty,buff)); 00196 } 00197 if (next_link != HA_OFFSET_ERROR) 00198 { 00199 mi_check_print_error(param, 00200 "Found more than the expected %s deleted rows in delete link chain", 00201 llstr(info->state->del, buff)); 00202 goto wrong; 00203 } 00204 if (i != 0) 00205 { 00206 mi_check_print_error(param, 00207 "Found %s deleted rows in delete link chain. Should be %s", 00208 llstr(info->state->del - i, buff2), 00209 llstr(info->state->del, buff)); 00210 goto wrong; 00211 } 00212 } 00213 DBUG_RETURN(0); 00214 00215 wrong: 00216 param->testflag|=T_RETRY_WITHOUT_QUICK; 00217 if (test_flag & T_VERBOSE) puts(""); 00218 mi_check_print_error(param,"record delete-link-chain corrupted"); 00219 DBUG_RETURN(1); 00220 } /* chk_del */
Here is the call graph for this function:

Here is the caller graph for this function:

Referenced by ha_myisam::analyze(), ha_myisam::check(), myisamchk(), and ha_myisam::repair().
Here is the caller graph for this function:

| int filecopy | ( | MI_CHECK * | param, | |
| File | to, | |||
| File | from, | |||
| my_off_t | start, | |||
| my_off_t | length, | |||
| const char * | type | |||
| ) |
Definition at line 1949 of file mi_check.c.
References DBUG_ENTER, DBUG_RETURN, err, IO_SIZE, mi_check_print_error(), min, my_errno, my_free, my_malloc(), MY_NABP, my_read, my_seek(), MY_SEEK_SET, my_write, MYF, st_mi_check_param::myf_rw, VOID, and st_mi_check_param::write_buffer_length.
Referenced by mi_repair(), mi_repair_by_sort(), mi_repair_parallel(), mi_sort_index(), and mi_sort_records().
01951 { 01952 char tmp_buff[IO_SIZE],*buff; 01953 ulong buff_length; 01954 DBUG_ENTER("filecopy"); 01955 01956 buff_length=(ulong) min(param->write_buffer_length,length); 01957 if (!(buff=my_malloc(buff_length,MYF(0)))) 01958 { 01959 buff=tmp_buff; buff_length=IO_SIZE; 01960 } 01961 01962 VOID(my_seek(from,start,MY_SEEK_SET,MYF(0))); 01963 while (length > buff_length) 01964 { 01965 if (my_read(from,(byte*) buff,buff_length,MYF(MY_NABP)) || 01966 my_write(to,(byte*) buff,buff_length,param->myf_rw)) 01967 goto err; 01968 length-= buff_length; 01969 } 01970 if (my_read(from,(byte*) buff,(uint) length,MYF(MY_NABP)) || 01971 my_write(to,(byte*) buff,(uint) length,param->myf_rw)) 01972 goto err; 01973 if (buff != tmp_buff) 01974 my_free(buff,MYF(0)); 01975 DBUG_RETURN(0); 01976 err: 01977 if (buff != tmp_buff) 01978 my_free(buff,MYF(0)); 01979 mi_check_print_error(param,"Can't copy %s to tempfile, error %d", 01980 type,my_errno); 01981 DBUG_RETURN(1); 01982 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int lock_file | ( | MI_CHECK * | param, | |
| File | file, | |||
| my_off_t | start, | |||
| int | lock_type, | |||
| const char * | filetype, | |||
| const char * | filename | |||
| ) |
Definition at line 1932 of file mi_check.c.
References F_TO_EOF, mi_check_print_error(), MY_DONT_WAIT, my_errno, my_lock(), MY_SEEK_NOT_DONE, MYF, T_WAIT_FOREVER, and st_mi_check_param::testflag.
Referenced by myisamchk(), run_scheduler(), and run_task().
01934 { 01935 if (my_lock(file,lock_type,start,F_TO_EOF, 01936 param->testflag & T_WAIT_FOREVER ? MYF(MY_SEEK_NOT_DONE) : 01937 MYF(MY_SEEK_NOT_DONE | MY_DONT_WAIT))) 01938 { 01939 mi_check_print_error(param," %d when locking %s '%s'",my_errno,filetype,filename); 01940 param->error_printed=2; /* Don't give that data is crashed */ 01941 return 1; 01942 } 01943 return 0; 01944 } /* lock_file */
Here is the call graph for this function:

Here is the caller graph for this function:

| void lock_memory | ( | MI_CHECK * | param | ) |
Referenced by mi_repair(), mi_repair_by_sort(), mi_repair_parallel(), mi_sort_records(), and myisamchk().
Here is the caller graph for this function:

Referenced by ha_myisam::assign_to_keycache(), and mi_change_key_cache().
Here is the caller graph for this function:

Definition at line 137 of file mi_keycache.c.
References DBUG_ENTER, DBUG_VOID_RETURN, mi_assign_to_key_cache(), multi_key_cache_change(), myisam_open_list, pos(), pthread_mutex_lock, pthread_mutex_unlock, and st_myisam_info::s.
Referenced by ha_change_key_cache().
00139 { 00140 LIST *pos; 00141 DBUG_ENTER("mi_change_key_cache"); 00142 00143 /* 00144 Lock list to ensure that no one can close the table while we manipulate it 00145 */ 00146 pthread_mutex_lock(&THR_LOCK_myisam); 00147 for (pos=myisam_open_list ; pos ; pos=pos->next) 00148 { 00149 MI_INFO *info= (MI_INFO*) pos->data; 00150 MYISAM_SHARE *share= info->s; 00151 if (share->key_cache == old_key_cache) 00152 mi_assign_to_key_cache(info, (ulonglong) ~0, new_key_cache); 00153 } 00154 00155 /* 00156 We have to do the following call while we have the lock on the 00157 MyISAM list structure to ensure that another thread is not trying to 00158 open a new table that will be associted with the old key cache 00159 */ 00160 multi_key_cache_change(old_key_cache, new_key_cache); 00161 pthread_mutex_unlock(&THR_LOCK_myisam); 00162 DBUG_VOID_RETURN; 00163 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int mi_close | ( | struct st_myisam_info * | file | ) |
Referenced by ha_myisam::close(), close_some_file(), file_info_free(), main(), mi_delete_table(), mi_panic(), mi_rename(), mrg_close(), myisamchk(), myrg_close(), myrg_open(), open_isam_file(), open_isam_files(), recreate_table(), run_test(), start_test(), test_rrnd(), and test_write().
Here is the caller graph for this function:

| int mi_create | ( | const char * | name, | |
| uint | keys, | |||
| MI_KEYDEF * | keydef, | |||
| uint | columns, | |||
| MI_COLUMNDEF * | columndef, | |||
| uint | uniques, | |||
| MI_UNIQUEDEF * | uniquedef, | |||
| MI_CREATE_INFO * | create_info, | |||
| uint | flags | |||
| ) |
Definition at line 35 of file mi_create.c.
References bzero, create_flag, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, FIELD_BLOB, FIELD_CHECK, FIELD_NORMAL, FIELD_SKIP_ENDSPACE, FIELD_SKIP_PRESPACE, FIELD_SKIP_ZERO, FIELD_VARCHAR, filename, FN_REFLEN, HA_DONT_TOUCH_DATA, HA_OPTION_CHECKSUM, HA_OPTION_COMPRESS_RECORD, HA_OPTION_DELAY_KEY_WRITE, HA_OPTION_PACK_RECORD, HA_OPTION_READ_ONLY_DATA, HA_OPTION_TEMP_COMPRESS_RECORD, HA_OPTION_TMP_TABLE, HA_WRONG_CREATE_OPTION, INT_MAX32, key_length, keyseg, st_columndef::length, LINT_INIT, st_mi_create_info::max_rows, MI_MAX_KEY, MI_MAX_KEY_BLOCK_SIZE, MI_MAX_KEY_SEG, MI_MAX_POSSIBLE_KEY, mi_portable_sizeof_char_ptr, my_errno, my_malloc(), MY_WME, MY_ZEROFILL, MYF, offset, st_mi_create_info::old_options, options(), recinfo, reclength, st_mi_create_info::reloc_rows, test, and st_columndef::type.
Referenced by create_myisam_tmp_table(), main(), recreate_table(), and run_test().
00039 { 00040 register uint i,j; 00041 File dfile,file; 00042 int errpos,save_errno, create_mode= O_RDWR | O_TRUNC; 00043 myf create_flag; 00044 uint fields,length,max_key_length,packed,pointer,real_length_diff, 00045 key_length,info_length,key_segs,options,min_key_length_skip, 00046 base_pos,long_varchar_count,varchar_length, 00047 max_key_block_length,unique_key_parts,fulltext_keys,offset; 00048 uint aligned_key_start, block_length; 00049 ulong reclength, real_reclength,min_pack_length; 00050 char filename[FN_REFLEN],linkname[FN_REFLEN], *linkname_ptr; 00051 ulong pack_reclength; 00052 ulonglong tot_length,max_rows, tmp; 00053 enum en_fieldtype type; 00054 MYISAM_SHARE share; 00055 MI_KEYDEF *keydef,tmp_keydef; 00056 MI_UNIQUEDEF *uniquedef; 00057 HA_KEYSEG *keyseg,tmp_keyseg; 00058 MI_COLUMNDEF *rec; 00059 ulong *rec_per_key_part; 00060 my_off_t key_root[MI_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE]; 00061 MI_CREATE_INFO tmp_create_info; 00062 DBUG_ENTER("mi_create"); 00063 DBUG_PRINT("enter", ("keys: %u columns: %u uniques: %u flags: %u", 00064 keys, columns, uniques, flags)); 00065 00066 if (!ci) 00067 { 00068 bzero((char*) &tmp_create_info,sizeof(tmp_create_info)); 00069 ci=&tmp_create_info; 00070 } 00071 00072 if (keys + uniques > MI_MAX_KEY || columns == 0) 00073 { 00074 DBUG_RETURN(my_errno=HA_WRONG_CREATE_OPTION); 00075 } 00076 LINT_INIT(dfile); 00077 LINT_INIT(file); 00078 errpos=0; 00079 options=0; 00080 bzero((byte*) &share,sizeof(share)); 00081 00082 if (flags & HA_DONT_TOUCH_DATA) 00083 { 00084 if (!(ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD)) 00085 options=ci->old_options & 00086 (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD | 00087 HA_OPTION_READ_ONLY_DATA | HA_OPTION_CHECKSUM | 00088 HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE); 00089 else 00090 options=ci->old_options & 00091 (HA_OPTION_CHECKSUM | HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE); 00092 } 00093 00094 if (ci->reloc_rows > ci->max_rows) 00095 ci->reloc_rows=ci->max_rows; /* Check if wrong parameter */ 00096 00097 if (!(rec_per_key_part= 00098 (ulong*) my_malloc((keys + uniques)*MI_MAX_KEY_SEG*sizeof(long), 00099 MYF(MY_WME | MY_ZEROFILL)))) 00100 DBUG_RETURN(my_errno); 00101 00102 /* Start by checking fields and field-types used */ 00103 00104 reclength=varchar_length=long_varchar_count=packed= 00105 min_pack_length=pack_reclength=0; 00106 for (rec=recinfo, fields=0 ; 00107 fields != columns ; 00108 rec++,fields++) 00109 { 00110 reclength+=rec->length; 00111 if ((type=(enum en_fieldtype) rec->type) != FIELD_NORMAL && 00112 type != FIELD_CHECK) 00113 { 00114 packed++; 00115 if (type == FIELD_BLOB) 00116 { 00117 share.base.blobs++; 00118 if (pack_reclength != INT_MAX32) 00119 { 00120 if (rec->length == 4+mi_portable_sizeof_char_ptr) 00121 pack_reclength= INT_MAX32; 00122 else 00123 pack_reclength+=(1 << ((rec->length-mi_portable_sizeof_char_ptr)*8)); /* Max blob length */ 00124 } 00125 } 00126 else if (type == FIELD_SKIP_PRESPACE || 00127 type == FIELD_SKIP_ENDSPACE) 00128 { 00129 if (pack_reclength != INT_MAX32) 00130 pack_reclength+= rec->length > 255 ? 2 : 1; 00131 min_pack_length++; 00132 } 00133 else if (type == FIELD_VARCHAR) 00134 { 00135 varchar_length+= rec->length-1; /* Used for min_pack_length */ 00136 packed--; 00137 pack_reclength++; 00138 min_pack_length++; 00139 /* We must test for 257 as length includes pack-length */ 00140 if (test(rec->length >= 257)) 00141 { 00142 long_varchar_count++; 00143 pack_reclength+= 2; /* May be packed on 3 bytes */ 00144 } 00145 } 00146 else if (type != FIELD_SKIP_ZERO) 00147 { 00148 min_pack_length+=rec->length; 00149 packed--; /* Not a pack record type */ 00150 } 00151 } 00152 else /* FIELD_NORMAL */ 00153 min_pack_length+=rec->length; 00154 } 00155 if ((packed & 7) == 1) 00156 { /* Bad packing, try to remove a zero-field */ 00157 while (rec != recinfo) 00158 { 00159 rec--; 00160 if (rec->type == (int) FIELD_SKIP_ZERO && rec->length == 1) 00161 { 00162 rec->type=(int) FIELD_NORMAL; 00163 packed--; 00164 min_pack_length++; 00165 break; 00166 } 00167 } 00168 } 00169 00170 if (packed || (flags & HA_PACK_RECORD)) 00171 options|=HA_OPTION_PACK_RECORD; /* Must use packed records */ 00172 /* We can't use checksum with static length rows */ 00173 if (!(options & HA_OPTION_PACK_RECORD)) 00174 options&= ~HA_OPTION_CHECKSUM; 00175 if (!(options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD))) 00176 min_pack_length+= varchar_length; 00177 if (flags & HA_CREATE_TMP_TABLE) 00178 { 00179 options|= HA_OPTION_TMP_TABLE; 00180 create_mode|= O_EXCL | O_NOFOLLOW; 00181 } 00182 if (flags & HA_CREATE_CHECKSUM || (options & HA_OPTION_CHECKSUM)) 00183 { 00184 options|= HA_OPTION_CHECKSUM; 00185 min_pack_length++; 00186 } 00187 if (flags & HA_CREATE_DELAY_KEY_WRITE) 00188 options|= HA_OPTION_DELAY_KEY_WRITE; 00189 if (flags & HA_CREATE_RELIES_ON_SQL_LAYER) 00190 options|= HA_OPTION_RELIES_ON_SQL_LAYER; 00191 00192 packed=(packed+7)/8; 00193 if (pack_reclength != INT_MAX32) 00194 pack_reclength+= reclength+packed + 00195 test(test_all_bits(options, HA_OPTION_CHECKSUM | HA_PACK_RECORD)); 00196 min_pack_length+=packed; 00197 00198 if (!ci->data_file_length && ci->max_rows) 00199 { 00200 if (pack_reclength == INT_MAX32 || 00201 (~(ulonglong) 0)/ci->max_rows < (ulonglong) pack_reclength) 00202 ci->data_file_length= ~(ulonglong) 0; 00203 else 00204 ci->data_file_length=(ulonglong) ci->max_rows*pack_reclength; 00205 } 00206 else if (!ci->max_rows) 00207 ci->max_rows=(ha_rows) (ci->data_file_length/(min_pack_length + 00208 ((options & HA_OPTION_PACK_RECORD) ? 00209 3 : 0))); 00210 00211 if (options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD)) 00212 pointer=mi_get_pointer_length(ci->data_file_length,myisam_data_pointer_size); 00213 else 00214 pointer=mi_get_pointer_length(ci->max_rows,myisam_data_pointer_size); 00215 if (!(max_rows=(ulonglong) ci->max_rows)) 00216 max_rows= ((((ulonglong) 1 << (pointer*8)) -1) / min_pack_length); 00217 00218 00219 real_reclength=reclength; 00220 if (!(options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD))) 00221 { 00222 if (reclength <= pointer) 00223 reclength=pointer+1; /* reserve place for delete link */ 00224 } 00225 else 00226 reclength+= long_varchar_count; /* We need space for varchar! */ 00227 00228 max_key_length=0; tot_length=0 ; key_segs=0; 00229 fulltext_keys=0; 00230 max_key_block_length=0; 00231 share.state.rec_per_key_part=rec_per_key_part; 00232 share.state.key_root=key_root; 00233 share.state.key_del=key_del; 00234 if (uniques) 00235 { 00236 max_key_block_length= myisam_block_size; 00237 max_key_length= MI_UNIQUE_HASH_LENGTH + pointer; 00238 } 00239 00240 for (i=0, keydef=keydefs ; i < keys ; i++ , keydef++) 00241 { 00242 00243 share.state.key_root[i]= HA_OFFSET_ERROR; 00244 min_key_length_skip=length=real_length_diff=0; 00245 key_length=pointer; 00246 if (keydef->flag & HA_SPATIAL) 00247 { 00248 #ifdef HAVE_SPATIAL 00249 /* BAR TODO to support 3D and more dimensions in the future */ 00250 uint sp_segs=SPDIMS*2; 00251 keydef->flag=HA_SPATIAL; 00252 00253 if (flags & HA_DONT_TOUCH_DATA) 00254 { 00255 /* 00256 called by myisamchk - i.e. table structure was taken from 00257 MYI file and SPATIAL key *does have* additional sp_segs keysegs. 00258 keydef->seg here points right at the GEOMETRY segment, 00259 so we only need to decrease keydef->keysegs. 00260 (see recreate_table() in mi_check.c) 00261 */ 00262 keydef->keysegs-=sp_segs-1; 00263 } 00264 00265 for (j=0, keyseg=keydef->seg ; (int) j < keydef->keysegs ; 00266 j++, keyseg++) 00267 { 00268 if (keyseg->type != HA_KEYTYPE_BINARY && 00269 keyseg->type != HA_KEYTYPE_VARBINARY1 && 00270 keyseg->type != HA_KEYTYPE_VARBINARY2) 00271 { 00272 my_errno=HA_WRONG_CREATE_OPTION; 00273 goto err; 00274 } 00275 } 00276 keydef->keysegs+=sp_segs; 00277 key_length+=SPLEN*sp_segs; 00278 length++; /* At least one length byte */ 00279 min_key_length_skip+=SPLEN*2*SPDIMS; 00280 #else 00281 my_errno= HA_ERR_UNSUPPORTED; 00282 goto err; 00283 #endif /*HAVE_SPATIAL*/ 00284 } 00285 else if (keydef->flag & HA_FULLTEXT) 00286 { 00287 keydef->flag=HA_FULLTEXT | HA_PACK_KEY | HA_VAR_LENGTH_KEY; 00288 options|=HA_OPTION_PACK_KEYS; /* Using packed keys */ 00289 00290 for (j=0, keyseg=keydef->seg ; (int) j < keydef->keysegs ; 00291 j++, keyseg++) 00292 { 00293 if (keyseg->type != HA_KEYTYPE_TEXT && 00294 keyseg->type != HA_KEYTYPE_VARTEXT1 && 00295 keyseg->type != HA_KEYTYPE_VARTEXT2) 00296 { 00297 my_errno=HA_WRONG_CREATE_OPTION; 00298 goto err; 00299 } 00300 if (!(keyseg->flag & HA_BLOB_PART) && 00301 (keyseg->type == HA_KEYTYPE_VARTEXT1 || 00302 keyseg->type == HA_KEYTYPE_VARTEXT2)) 00303 { 00304 /* Make a flag that this is a VARCHAR */ 00305 keyseg->flag|= HA_VAR_LENGTH_PART; 00306 /* Store in bit_start number of bytes used to pack the length */ 00307 keyseg->bit_start= ((keyseg->type == HA_KEYTYPE_VARTEXT1)? 00308 1 : 2); 00309 } 00310 } 00311 00312 fulltext_keys++; 00313 key_length+= HA_FT_MAXBYTELEN+HA_FT_WLEN; 00314 length++; /* At least one length byte */ 00315 min_key_length_skip+=HA_FT_MAXBYTELEN; 00316 real_length_diff=HA_FT_MAXBYTELEN-FT_MAX_WORD_LEN_FOR_SORT; 00317 } 00318 else 00319 { 00320 /* Test if prefix compression */ 00321 if (keydef->flag & HA_PACK_KEY) 00322 { 00323 /* Can't use space_compression on number keys */ 00324 if ((keydef->seg[0].flag & HA_SPACE_PACK) && 00325 keydef->seg[0].type == (int) HA_KEYTYPE_NUM) 00326 keydef->seg[0].flag&= ~HA_SPACE_PACK; 00327 00328 /* Only use HA_PACK_KEY when first segment is a variable length key */ 00329 if (!(keydef->seg[0].flag & (HA_SPACE_PACK | HA_BLOB_PART | 00330 HA_VAR_LENGTH_PART))) 00331 { 00332 /* pack relative to previous key */ 00333 keydef->flag&= ~HA_PACK_KEY; 00334 keydef->flag|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY; 00335 } 00336 else 00337 { 00338 keydef->seg[0].flag|=HA_PACK_KEY; /* for easyer intern test */ 00339 keydef->flag|=HA_VAR_LENGTH_KEY; 00340 options|=HA_OPTION_PACK_KEYS; /* Using packed keys */ 00341 } 00342 } 00343 if (keydef->flag & HA_BINARY_PACK_KEY) 00344 options|=HA_OPTION_PACK_KEYS; /* Using packed keys */ 00345 00346 if (keydef->flag & HA_AUTO_KEY && ci->with_auto_increment) 00347 share.base.auto_key=i+1; 00348 for (j=0, keyseg=keydef->seg ; j < keydef->keysegs ; j++, keyseg++) 00349 { 00350 /* numbers are stored with high by first to make compression easier */ 00351 switch (keyseg->type) { 00352 case HA_KEYTYPE_SHORT_INT: 00353 case HA_KEYTYPE_LONG_INT: 00354 case HA_KEYTYPE_FLOAT: 00355 case HA_KEYTYPE_DOUBLE: 00356 case HA_KEYTYPE_USHORT_INT: 00357 case HA_KEYTYPE_ULONG_INT: 00358 case HA_KEYTYPE_LONGLONG: 00359 case HA_KEYTYPE_ULONGLONG: 00360 case HA_KEYTYPE_INT24: 00361 case HA_KEYTYPE_UINT24: 00362 case HA_KEYTYPE_INT8: 00363 keyseg->flag|= HA_SWAP_KEY; 00364 break; 00365 case HA_KEYTYPE_VARTEXT1: 00366 case HA_KEYTYPE_VARTEXT2: 00367 case HA_KEYTYPE_VARBINARY1: 00368 case HA_KEYTYPE_VARBINARY2: 00369 if (!(keyseg->flag & HA_BLOB_PART)) 00370 { 00371 /* Make a flag that this is a VARCHAR */ 00372 keyseg->flag|= HA_VAR_LENGTH_PART; 00373 /* Store in bit_start number of bytes used to pack the length */ 00374 keyseg->bit_start= ((keyseg->type == HA_KEYTYPE_VARTEXT1 || 00375 keyseg->type == HA_KEYTYPE_VARBINARY1) ? 00376 1 : 2); 00377 } 00378 break; 00379 default: 00380 break; 00381 } 00382 if (keyseg->flag & HA_SPACE_PACK) 00383 { 00384 DBUG_ASSERT(!(keyseg->flag & HA_VAR_LENGTH_PART)); 00385 keydef->flag |= HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY; 00386 options|=HA_OPTION_PACK_KEYS; /* Using packed keys */ 00387 length++; /* At least one length byte */ 00388 min_key_length_skip+=keyseg->length; 00389 if (keyseg->length >= 255) 00390 { /* prefix may be 3 bytes */ 00391 min_key_length_skip+=2; 00392 length+=2; 00393 } 00394 } 00395 if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART)) 00396 { 00397 DBUG_ASSERT(!test_all_bits(keyseg->flag, 00398 (HA_VAR_LENGTH_PART | HA_BLOB_PART))); 00399 keydef->flag|=HA_VAR_LENGTH_KEY; 00400 length++; /* At least one length byte */ 00401 options|=HA_OPTION_PACK_KEYS; /* Using packed keys */ 00402 min_key_length_skip+=keyseg->length; 00403 if (keyseg->length >= 255) 00404 { /* prefix may be 3 bytes */ 00405 min_key_length_skip+=2; 00406 length+=2; 00407 } 00408 } 00409 key_length+= keyseg->length; 00410 if (keyseg->null_bit) 00411 { 00412 key_length++; 00413 options|=HA_OPTION_PACK_KEYS; 00414 keyseg->flag|=HA_NULL_PART; 00415 keydef->flag|=HA_VAR_LENGTH_KEY | HA_NULL_PART_KEY; 00416 } 00417 } 00418 } /* if HA_FULLTEXT */ 00419 key_segs+=keydef->keysegs; 00420 if (keydef->keysegs > MI_MAX_KEY_SEG) 00421 { 00422 my_errno=HA_WRONG_CREATE_OPTION; 00423 goto err; 00424 } 00425 /* 00426 key_segs may be 0 in the case when we only want to be able to 00427 add on row into the table. This can happen with some DISTINCT queries 00428 in MySQL 00429 */ 00430 if ((keydef->flag & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME && 00431 key_segs) 00432 share.state.rec_per_key_part[key_segs-1]=1L; 00433 length+=key_length; 00434 /* Get block length for key, if defined by user */ 00435 block_length= (keydef->block_length ? 00436 my_round_up_to_next_power(keydef->block_length) : 00437 myisam_block_size); 00438 block_length= max(block_length, MI_MIN_KEY_BLOCK_LENGTH); 00439 block_length= min(block_length, MI_MAX_KEY_BLOCK_LENGTH); 00440 00441 keydef->block_length= MI_BLOCK_SIZE(length-real_length_diff, 00442 pointer,MI_MAX_KEYPTR_SIZE, 00443 block_length); 00444 if (keydef->block_length > MI_MAX_KEY_BLOCK_LENGTH || 00445 length >= MI_MAX_KEY_BUFF) 00446 { 00447 my_errno=HA_WRONG_CREATE_OPTION; 00448 goto err; 00449 } 00450 set_if_bigger(max_key_block_length,keydef->block_length); 00451 keydef->keylength= (uint16) key_length; 00452 keydef->minlength= (uint16) (length-min_key_length_skip); 00453 keydef->maxlength= (uint16) length; 00454 00455 if (length > max_key_length) 00456 max_key_length= length; 00457 tot_length+= (max_rows/(ulong) (((uint) keydef->block_length-5)/ 00458 (length*2)))* 00459 (ulong) keydef->block_length; 00460 } 00461 for (i=max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH ; i-- ; ) 00462 key_del[i]=HA_OFFSET_ERROR; 00463 00464 unique_key_parts=0; 00465 offset=reclength-uniques*MI_UNIQUE_HASH_LENGTH; 00466 for (i=0, uniquedef=uniquedefs ; i < uniques ; i++ , uniquedef++) 00467 { 00468 uniquedef->key=keys+i; 00469 unique_key_parts+=uniquedef->keysegs; 00470 share.state.key_root[keys+i]= HA_OFFSET_ERROR; 00471 tot_length+= (max_rows/(ulong) (((uint) myisam_block_size-5)/ 00472 ((MI_UNIQUE_HASH_LENGTH + pointer)*2)))* 00473 (ulong) myisam_block_size; 00474 } 00475 keys+=uniques; /* Each unique has 1 key */ 00476 key_segs+=uniques; /* Each unique has 1 key seg */ 00477 00478 base_pos=(MI_STATE_INFO_SIZE + keys * MI_STATE_KEY_SIZE + 00479 max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH* 00480 MI_STATE_KEYBLOCK_SIZE+ 00481 key_segs*MI_STATE_KEYSEG_SIZE); 00482 info_length=base_pos+(uint) (MI_BASE_INFO_SIZE+ 00483 keys * MI_KEYDEF_SIZE+ 00484 uniques * MI_UNIQUEDEF_SIZE + 00485 (key_segs + unique_key_parts)*HA_KEYSEG_SIZE+ 00486 columns*MI_COLUMNDEF_SIZE); 00487 DBUG_PRINT("info", ("info_length: %u", info_length)); 00488 /* There are only 16 bits for the total header length. */ 00489 if (info_length > 65535) 00490 { 00491 my_printf_error(0, "MyISAM table '%s' has too many columns and/or " 00492 "indexes and/or unique constraints.", 00493 MYF(0), name + dirname_length(name)); 00494 my_errno= HA_WRONG_CREATE_OPTION; 00495 goto err; 00496 } 00497 00498 bmove(share.state.header.file_version,(byte*) myisam_file_magic,4); 00499 ci->old_options=options| (ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD ? 00500 HA_OPTION_COMPRESS_RECORD | 00501 HA_OPTION_TEMP_COMPRESS_RECORD: 0); 00502 mi_int2store(share.state.header.options,ci->old_options); 00503 mi_int2store(share.state.header.header_length,info_length); 00504 mi_int2store(share.state.header.state_info_length,MI_STATE_INFO_SIZE); 00505 mi_int2store(share.state.header.base_info_length,MI_BASE_INFO_SIZE); 00506 mi_int2store(share.state.header.base_pos,base_pos); 00507 share.state.header.language= (ci->language ? 00508 ci->language : default_charset_info->number); 00509 share.state.header.max_block_size_index= max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH; 00510 00511 share.state.dellink = HA_OFFSET_ERROR; 00512 share.state.process= (ulong) getpid(); 00513 share.state.unique= (ulong) 0; 00514 share.state.update_count=(ulong) 0; 00515 share.state.version= (ulong) time((time_t*) 0); 00516 share.state.sortkey= (ushort) ~0; 00517 share.state.auto_increment=ci->auto_increment; 00518 share.options=options; 00519 share.base.rec_reflength=pointer; 00520 /* Get estimate for index file length (this may be wrong for FT keys) */ 00521 tmp= (tot_length + max_key_block_length * keys * 00522 MI_INDEX_BLOCK_MARGIN) / MI_MIN_KEY_BLOCK_LENGTH; 00523 /* 00524 use maximum of key_file_length we calculated and key_file_length value we 00525 got from MYI file header (see also myisampack.c:save_state) 00526 */ 00527 share.base.key_reflength= 00528 mi_get_pointer_length(max(ci->key_file_length,tmp),3); 00529 share.base.keys= share.state.header.keys= keys; 00530 share.state.header.uniques= uniques; 00531 share.state.header.fulltext_keys= fulltext_keys; 00532 mi_int2store(share.state.header.key_parts,key_segs); 00533 mi_int2store(share.state.header.unique_key_parts,unique_key_parts); 00534 00535 mi_set_all_keys_active(share.state.key_map, keys); 00536 aligned_key_start= my_round_up_to_next_power(max_key_block_length ? 00537 max_key_block_length : 00538 myisam_block_size); 00539 00540 share.base.keystart= share.state.state.key_file_length= 00541 MY_ALIGN(info_length, aligned_key_start); 00542 share.base.max_key_block_length=max_key_block_length; 00543 share.base.max_key_length=ALIGN_SIZE(max_key_length+4); 00544 share.base.records=ci->max_rows; 00545 share.base.reloc= ci->reloc_rows; 00546 share.base.reclength=real_reclength; 00547 share.base.pack_reclength=reclength+ test(options & HA_OPTION_CHECKSUM); 00548 share.base.max_pack_length=pack_reclength; 00549 share.base.min_pack_length=min_pack_length; 00550 share.base.pack_bits=packed; 00551 share.base.fields=fields; 00552 share.base.pack_fields=packed; 00553 #ifdef USE_RAID 00554 share.base.raid_type=ci->raid_type; 00555 share.base.raid_chunks=ci->raid_chunks; 00556 share.base.raid_chunksize=ci->raid_chunksize; 00557 #endif 00558 00559 /* max_data_file_length and max_key_file_length are recalculated on open */ 00560 if (options & HA_OPTION_TMP_TABLE) 00561 share.base.max_data_file_length=(my_off_t) ci->data_file_length; 00562 00563 share.base.min_block_length= 00564 (share.base.pack_reclength+3 < MI_EXTEND_BLOCK_LENGTH && 00565 ! share.base.blobs) ? 00566 max(share.base.pack_reclength,MI_MIN_BLOCK_LENGTH) : 00567 MI_EXTEND_BLOCK_LENGTH; 00568 if (! (flags & HA_DONT_TOUCH_DATA)) 00569 share.state.create_time= (long) time((time_t*) 0); 00570 00571 pthread_mutex_lock(&THR_LOCK_myisam); 00572 00573 if (ci->index_file_name) 00574 { 00575 char *iext= strrchr(ci->index_file_name, '.'); 00576 int have_iext= iext && !strcmp(iext, MI_NAME_IEXT); 00577 if (options & HA_OPTION_TMP_TABLE) 00578 { 00579 char *path; 00580 /* chop off the table name, tempory tables use generated name */ 00581 if ((path= strrchr(ci->index_file_name, FN_LIBCHAR))) 00582 *path= '\0'; 00583 fn_format(filename, name, ci->index_file_name, MI_NAME_IEXT, 00584 MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_APPEND_EXT); 00585 } 00586 else 00587 { 00588 fn_format(filename, ci->index_file_name, "", MI_NAME_IEXT, 00589 MY_UNPACK_FILENAME | (have_iext ? MY_REPLACE_EXT : 00590 MY_APPEND_EXT)); 00591 } 00592 fn_format(linkname, name, "", MI_NAME_IEXT, 00593 MY_UNPACK_FILENAME|MY_APPEND_EXT); 00594 linkname_ptr=linkname; 00595 /* 00596 Don't create the table if the link or file exists to ensure that one 00597 doesn't accidently destroy another table. 00598 */ 00599 create_flag=0; 00600 } 00601 else 00602 { 00603 fn_format(filename, name, "", MI_NAME_IEXT, 00604 (MY_UNPACK_FILENAME | 00605 (flags & HA_DONT_TOUCH_DATA) ? MY_RETURN_REAL_PATH : 0) | 00606 MY_APPEND_EXT); 00607 linkname_ptr=0; 00608 /* Replace the current file */ 00609 create_flag=MY_DELETE_OLD; 00610 } 00611 00612 /* 00613 If a MRG_MyISAM table is in use, the mapped MyISAM tables are open, 00614 but no entry is made in the table cache for them. 00615 A TRUNCATE command checks for the table in the cache only and could 00616 be fooled to believe, the table is not open. 00617 Pull the emergency brake in this situation. (Bug #8306) 00618 */ 00619 if (test_if_reopen(filename)) 00620 { 00621 my_printf_error(0, "MyISAM table '%s' is in use " 00622 "(most likely by a MERGE table). Try FLUSH TABLES.", 00623 MYF(0), name + dirname_length(name)); 00624 goto err; 00625 } 00626 00627 if ((file= my_create_with_symlink(linkname_ptr, filename, 0, create_mode, 00628 MYF(MY_WME | create_flag))) < 0) 00629 goto err; 00630 errpos=1; 00631 00632 if (!(flags & HA_DONT_TOUCH_DATA)) 00633 { 00634 #ifdef USE_RAID 00635 if (share.base.raid_type) 00636 { 00637 (void) fn_format(filename, name, "", MI_NAME_DEXT, 00638 MY_UNPACK_FILENAME | MY_APPEND_EXT); 00639 if ((dfile=my_raid_create(filename, 0, create_mode, 00640 share.base.raid_type, 00641 share.base.raid_chunks, 00642 share.base.raid_chunksize, 00643 MYF(MY_WME | MY_RAID))) < 0) 00644 goto err; 00645 } 00646 else 00647 #endif 00648 { 00649 if (ci->data_file_name) 00650 { 00651 char *dext= strrchr(ci->data_file_name, '.'); 00652 int have_dext= dext && !strcmp(dext, MI_NAME_DEXT); 00653 00654 if (options & HA_OPTION_TMP_TABLE) 00655 { 00656 char *path; 00657 /* chop off the table name, tempory tables use generated name */ 00658 if ((path= strrchr(ci->data_file_name, FN_LIBCHAR))) 00659 *path= '\0'; 00660 fn_format(filename, name, ci->data_file_name, MI_NAME_DEXT, 00661 MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_APPEND_EXT); 00662 } 00663 else 00664 { 00665 fn_format(filename, ci->data_file_name, "", MI_NAME_DEXT, 00666 MY_UNPACK_FILENAME | 00667 (have_dext ? MY_REPLACE_EXT : MY_APPEND_EXT)); 00668 } 00669 00670 fn_format(linkname, name, "",MI_NAME_DEXT, 00671 MY_UNPACK_FILENAME | MY_APPEND_EXT); 00672 linkname_ptr=linkname; 00673 create_flag=0; 00674 } 00675 else 00676 { 00677 fn_format(filename,name,"", MI_NAME_DEXT, 00678 MY_UNPACK_FILENAME | MY_APPEND_EXT); 00679 linkname_ptr=0; 00680 create_flag=MY_DELETE_OLD; 00681 } 00682 if ((dfile= 00683 my_create_with_symlink(linkname_ptr, filename, 0, create_mode, 00684 MYF(MY_WME | create_flag))) < 0) 00685 goto err; 00686 } 00687 errpos=3; 00688 } 00689 00690 DBUG_PRINT("info", ("write state info and base info")); 00691 if (mi_state_info_write(file, &share.state, 2) || 00692 mi_base_info_write(file, &share.base)) 00693 goto err; 00694 #ifndef DBUG_OFF 00695 if ((uint) my_tell(file,MYF(0)) != base_pos+ MI_BASE_INFO_SIZE) 00696 { 00697 uint pos=(uint) my_tell(file,MYF(0)); 00698 DBUG_PRINT("warning",("base_length: %d != used_length: %d", 00699 base_pos+ MI_BASE_INFO_SIZE, pos)); 00700 } 00701 #endif 00702 00703 /* Write key and keyseg definitions */ 00704 DBUG_PRINT("info", ("write key and keyseg definitions")); 00705 for (i=0 ; i < share.base.keys - uniques; i++) 00706 { 00707 uint sp_segs=(keydefs[i].flag & HA_SPATIAL) ? 2*SPDIMS : 0; 00708 00709 if (mi_keydef_write(file, &keydefs[i])) 00710 goto err; 00711 for (j=0 ; j < keydefs[i].keysegs-sp_segs ; j++) 00712 if (mi_keyseg_write(file, &keydefs[i].seg[j])) 00713 goto err; 00714 #ifdef HAVE_SPATIAL 00715 for (j=0 ; j < sp_segs ; j++) 00716 { 00717 HA_KEYSEG sseg; 00718 sseg.type=SPTYPE; 00719 sseg.language= 7; /* Binary */ 00720 sseg.null_bit=0; 00721 sseg.bit_start=0; 00722 sseg.bit_end=0; 00723 sseg.bit_length= 0; 00724 sseg.bit_pos= 0; 00725 sseg.length=SPLEN; 00726 sseg.null_pos=0; 00727 sseg.start=j*SPLEN; 00728 sseg.flag= HA_SWAP_KEY; 00729 if (mi_keyseg_write(file, &sseg)) 00730 goto err; 00731 } 00732 #endif 00733 } 00734 /* Create extra keys for unique definitions */ 00735 offset=reclength-uniques*MI_UNIQUE_HASH_LENGTH; 00736 bzero((char*) &tmp_keydef,sizeof(tmp_keydef)); 00737 bzero((char*) &tmp_keyseg,sizeof(tmp_keyseg)); 00738 for (i=0; i < uniques ; i++) 00739 { 00740 tmp_keydef.keysegs=1; 00741 tmp_keydef.flag= HA_UNIQUE_CHECK; 00742 tmp_keydef.block_length= (uint16)myisam_block_size; 00743 tmp_keydef.keylength= MI_UNIQUE_HASH_LENGTH + pointer; 00744 tmp_keydef.minlength=tmp_keydef.maxlength=tmp_keydef.keylength; 00745 tmp_keyseg.type= MI_UNIQUE_HASH_TYPE; 00746 tmp_keyseg.length= MI_UNIQUE_HASH_LENGTH; 00747 tmp_keyseg.start= offset; 00748 offset+= MI_UNIQUE_HASH_LENGTH; 00749 if (mi_keydef_write(file,&tmp_keydef) || 00750 mi_keyseg_write(file,(&tmp_keyseg))) 00751 goto err; 00752 } 00753 00754 /* Save unique definition */ 00755 DBUG_PRINT("info", ("write unique definitions")); 00756 for (i=0 ; i < share.state.header.uniques ; i++) 00757 { 00758 HA_KEYSEG *keyseg_end; 00759 keyseg= uniquedefs[i].seg; 00760 if (mi_uniquedef_write(file, &uniquedefs[i])) 00761 goto err; 00762 for (keyseg= uniquedefs[i].seg, keyseg_end= keyseg+ uniquedefs[i].keysegs; 00763 keyseg < keyseg_end; 00764 keyseg++) 00765 { 00766 switch (keyseg->type) { 00767 case HA_KEYTYPE_VARTEXT1: 00768 case HA_KEYTYPE_VARTEXT2: 00769 case HA_KEYTYPE_VARBINARY1: 00770 case HA_KEYTYPE_VARBINARY2: 00771 if (!(keyseg->flag & HA_BLOB_PART)) 00772 { 00773 keyseg->flag|= HA_VAR_LENGTH_PART; 00774 keyseg->bit_start= ((keyseg->type == HA_KEYTYPE_VARTEXT1 || 00775 keyseg->type == HA_KEYTYPE_VARBINARY1) ? 00776 1 : 2); 00777 } 00778 break; 00779 default: 00780 break; 00781 } 00782 if (mi_keyseg_write(file, keyseg)) 00783 goto err; 00784 } 00785 } 00786 DBUG_PRINT("info", ("write field definitions")); 00787 for (i=0 ; i < share.base.fields ; i++) 00788 if (mi_recinfo_write(file, &recinfo[i])) 00789 goto err; 00790 00791 #ifndef DBUG_OFF 00792 if ((uint) my_tell(file,MYF(0)) != info_length) 00793 { 00794 uint pos= (uint) my_tell(file,MYF(0)); 00795 DBUG_PRINT("warning",("info_length: %d != used_length: %d", 00796 info_length, pos)); 00797 } 00798 #endif 00799 00800 /* Enlarge files */ 00801 DBUG_PRINT("info", ("enlarge to keystart: %lu", (ulong) share.base.keystart)); 00802 if (my_chsize(file,(ulong) share.base.keystart,0,MYF(0))) 00803 goto err; 00804 00805 if (! (flags & HA_DONT_TOUCH_DATA)) 00806 { 00807 #ifdef USE_RELOC 00808 if (my_chsize(dfile,share.base.min_pack_length*ci->reloc_rows,0,MYF(0))) 00809 goto err; 00810 #endif 00811 errpos=2; 00812 if (my_close(dfile,MYF(0))) 00813 goto err; 00814 } 00815 errpos=0; 00816 pthread_mutex_unlock(&THR_LOCK_myisam); 00817 if (my_close(file,MYF(0))) 00818 goto err; 00819 my_free((char*) rec_per_key_part,MYF(0)); 00820 DBUG_RETURN(0); 00821 00822 err: 00823 pthread_mutex_unlock(&THR_LOCK_myisam); 00824 save_errno=my_errno; 00825 switch (errpos) { 00826 case 3: 00827 VOID(my_close(dfile,MYF(0))); 00828 /* fall through */ 00829 case 2: 00830 /* QQ: Tõnu should add a call to my_raid_delete() here */ 00831 if (! (flags & HA_DONT_TOUCH_DATA)) 00832 my_delete_with_symlink(fn_format(filename,name,"",MI_NAME_DEXT, 00833 MY_UNPACK_FILENAME | MY_APPEND_EXT), 00834 MYF(0)); 00835 /* fall through */ 00836 case 1: 00837 VOID(my_close(file,MYF(0))); 00838 if (! (flags & HA_DONT_TOUCH_DATA)) 00839 my_delete_with_symlink(fn_format(filename,name,"",MI_NAME_IEXT, 00840 MY_UNPACK_FILENAME | MY_APPEND_EXT), 00841 MYF(0)); 00842 } 00843 my_free((char*) rec_per_key_part, MYF(0)); 00844 DBUG_RETURN(my_errno=save_errno); /* return the fatal errno */ 00845 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int mi_delete | ( | struct st_myisam_info * | file, | |
| const byte * | buff | |||
| ) |
Definition at line 36 of file mi_delete.c.
References DBUG_ENTER, DBUG_EXECUTE_IF, DBUG_RETURN, HA_ERR_CRASHED, HA_ERR_KEY_NOT_FOUND, HA_STATE_AKTIV, mi_print_error, my_errno, st_myisam_info::s, and st_myisam_info::update.
Referenced by ha_myisam::delete_row(), examine_log(), main(), myrg_delete(), and run_test().
00037 { 00038 uint i; 00039 uchar *old_key; 00040 int save_errno; 00041 char lastpos[8]; 00042 00043 MYISAM_SHARE *share=info->s; 00044 DBUG_ENTER("mi_delete"); 00045 00046 /* Test if record is in datafile */ 00047 00048 DBUG_EXECUTE_IF("myisam_pretend_crashed_table_on_usage", 00049 mi_print_error(info->s, HA_ERR_CRASHED); 00050 DBUG_RETURN(my_errno= HA_ERR_CRASHED);); 00051 DBUG_EXECUTE_IF("my_error_test_undefined_error", 00052 mi_print_error(info->s, INT_MAX); 00053 DBUG_RETURN(my_errno= INT_MAX);); 00054 if (!(info->update & HA_STATE_AKTIV)) 00055 { 00056 DBUG_RETURN(my_errno=HA_ERR_KEY_NOT_FOUND); /* No database read */ 00057 } 00058 if (share->options & HA_OPTION_READ_ONLY_DATA) 00059 { 00060 DBUG_RETURN(my_errno=EACCES); 00061 } 00062 if (_mi_readinfo(info,F_WRLCK,1)) 00063 DBUG_RETURN(my_errno); 00064 if (info->s->calc_checksum) 00065 info->checksum=(*info->s->calc_checksum)(info,record); 00066 if ((*share->compare_record)(info,record)) 00067 goto err; /* Error on read-check */ 00068 00069 if (_mi_mark_file_changed(info)) 00070 goto err; 00071 00072 /* Remove all keys from the .ISAM file */ 00073 00074 old_key=info->lastkey2; 00075 for (i=0 ; i < share->base.keys ; i++ ) 00076 { 00077 if (mi_is_key_active(info->s->state.key_map, i)) 00078 { 00079 info->s->keyinfo[i].version++; 00080 if (info->s->keyinfo[i].flag & HA_FULLTEXT ) 00081 { 00082 if (_mi_ft_del(info,i,(char*) old_key,record,info->lastpos)) 00083 goto err; 00084 } 00085 else 00086 { 00087 if (info->s->keyinfo[i].ck_delete(info,i,old_key, 00088 _mi_make_key(info,i,old_key,record,info->lastpos))) 00089 goto err; 00090 } 00091 /* The above changed info->lastkey2. Inform mi_rnext_same(). */ 00092 info->update&= ~HA_STATE_RNEXT_SAME; 00093 } 00094 } 00095 00096 if ((*share->delete_record)(info)) 00097 goto err; /* Remove record from database */ 00098 info->state->checksum-=info->checksum; 00099 00100 info->update= HA_STATE_CHANGED+HA_STATE_DELETED+HA_STATE_ROW_CHANGED; 00101 info->state->records--; 00102 00103 mi_sizestore(lastpos,info->lastpos); 00104 myisam_log_command(MI_LOG_DELETE,info,(byte*) lastpos,sizeof(lastpos),0); 00105 VOID(_mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE)); 00106 allow_break(); /* Allow SIGHUP & SIGINT */ 00107 if (info->invalidator != 0) 00108 { 00109 DBUG_PRINT("info", ("invalidator... '%s' (delete)", info->filename)); 00110 (*info->invalidator)(info->filename); 00111 info->invalidator=0; 00112 } 00113 DBUG_RETURN(0); 00114 00115 err: 00116 save_errno=my_errno; 00117 mi_sizestore(lastpos,info->lastpos); 00118 myisam_log_command(MI_LOG_DELETE,info,(byte*) lastpos, sizeof(lastpos),0); 00119 if (save_errno != HA_ERR_RECORD_CHANGED) 00120 { 00121 mi_print_error(info->s, HA_ERR_CRASHED); 00122 mi_mark_crashed(info); /* mark table crashed */ 00123 } 00124 VOID(_mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE)); 00125 info->update|=HA_STATE_WRITTEN; /* Buffer changed */ 00126 allow_break(); /* Allow SIGHUP & SIGINT */ 00127 my_errno=save_errno; 00128 if (save_errno == HA_ERR_KEY_NOT_FOUND) 00129 { 00130 mi_print_error(info->s, HA_ERR_CRASHED); 00131 my_errno=HA_ERR_CRASHED; 00132 } 00133 00134 DBUG_RETURN(my_errno); 00135 } /* mi_delete */
Here is the caller graph for this function:

| int mi_delete_all_rows | ( | struct st_myisam_info * | info | ) |
Definition at line 22 of file mi_delete_all.c.
References _mi_mark_file_changed(), _mi_readinfo(), _mi_writeinfo(), allow_break(), st_mi_isam_share::base, st_mi_status_info::checksum, st_mi_status_info::data_file_length, DBUG_ENTER, DBUG_RETURN, st_mi_status_info::del, st_mi_state_info::dellink, st_myisam_info::dfile, st_mi_status_info::empty, err, F_WRLCK, FLUSH_IGNORE_CHANGED, flush_key_blocks(), HA_OFFSET_ERROR, HA_OPTION_READ_ONLY_DATA, HA_STATE_WRITTEN, st_mi_isam_share::key_cache, st_mi_state_info::key_del, st_mi_status_info::key_empty, st_mi_status_info::key_file_length, st_mi_state_info::key_root, st_mi_base_info::keys, st_mi_base_info::keystart, st_mi_isam_share::kfile, st_mi_base_info::max_key_block_length, MI_LOG_DELETE_ALL, MI_MIN_KEY_BLOCK_LENGTH, mi_remap_file(), st_mi_isam_share::mmap_lock, my_chsize(), my_errno, MY_WME, MYF, myisam_log_command, st_mi_isam_share::options, st_mi_status_info::records, rw_unlock, rw_wrlock, st_myisam_info::s, st_mi_state_info::sortkey, st_mi_state_info::split, st_mi_isam_share::state, st_myisam_info::state, st_myisam_info::update, VOID, and WRITEINFO_UPDATE_KEYFILE.
Referenced by ha_myisam::delete_all_rows().
00023 { 00024 uint i; 00025 MYISAM_SHARE *share=info->s; 00026 MI_STATE_INFO *state=&share->state; 00027 DBUG_ENTER("mi_delete_all_rows"); 00028 00029 if (share->options & HA_OPTION_READ_ONLY_DATA) 00030 { 00031 DBUG_RETURN(my_errno=EACCES); 00032 } 00033 if (_mi_readinfo(info,F_WRLCK,1)) 00034 DBUG_RETURN(my_errno); 00035 if (_mi_mark_file_changed(info)) 00036 goto err; 00037 00038 info->state->records=info->state->del=state->split=0; 00039 state->dellink = HA_OFFSET_ERROR; 00040 state->sortkey= (ushort) ~0; 00041 info->state->key_file_length=share->base.keystart; 00042 info->state->data_file_length=0; 00043 info->state->empty=info->state->key_empty=0; 00044 info->state->checksum=0; 00045 00046 for (i=share->base.max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH ; i-- ; ) 00047 state->key_del[i]= HA_OFFSET_ERROR; 00048 for (i=0 ; i < share->base.keys ; i++) 00049 state->key_root[i]= HA_OFFSET_ERROR; 00050 00051 myisam_log_command(MI_LOG_DELETE_ALL,info,(byte*) 0,0,0); 00052 /* 00053 If we are using delayed keys or if the user has done changes to the tables 00054 since it was locked then there may be key blocks in the key cache 00055 */ 00056 flush_key_blocks(share->key_cache, share->kfile, FLUSH_IGNORE_CHANGED); 00057 if (my_chsize(info->dfile, 0, 0, MYF(MY_WME)) || 00058 my_chsize(share->kfile, share->base.keystart, 0, MYF(MY_WME)) ) 00059 goto err; 00060 VOID(_mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE)); 00061 #ifdef HAVE_MMAP 00062 /* Resize mmaped area */ 00063 rw_wrlock(&info->s->mmap_lock); 00064 mi_remap_file(info, (my_off_t)0); 00065 rw_unlock(&info->s->mmap_lock); 00066 #endif 00067 allow_break(); /* Allow SIGHUP & SIGINT */ 00068 DBUG_RETURN(0); 00069 00070 err: 00071 { 00072 int save_errno=my_errno; 00073 VOID(_mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE)); 00074 info->update|=HA_STATE_WRITTEN; /* Buffer changed */ 00075 allow_break(); /* Allow SIGHUP & SIGINT */ 00076 DBUG_RETURN(my_errno=save_errno); 00077 } 00078 } /* mi_delete */
Here is the call graph for this function:

Here is the caller graph for this function:

| int mi_delete_table | ( | const char * | name | ) |
Definition at line 23 of file mi_delete_table.c.
References st_mi_isam_share::base, check_table_is_closed(), DBUG_ENTER, DBUG_RETURN, fn_format(), FN_REFLEN, from, HA_OPEN_FOR_REPAIR, info, mi_close(), MI_NAME_DEXT, MI_NAME_IEXT, mi_open(), MY_APPEND_EXT, my_delete_with_symlink(), my_errno, my_raid_delete, MY_UNPACK_FILENAME, MY_WME, MYF, st_mi_base_info::raid_chunks, st_mi_base_info::raid_type, and st_myisam_info::s.
Referenced by ha_myisam::delete_table().
00024 { 00025 char from[FN_REFLEN]; 00026 #ifdef USE_RAID 00027 uint raid_type=0,raid_chunks=0; 00028 #endif 00029 DBUG_ENTER("mi_delete_table"); 00030 00031 #ifdef EXTRA_DEBUG 00032 check_table_is_closed(name,"delete"); 00033 #endif 00034 #ifdef USE_RAID 00035 { 00036 MI_INFO *info; 00037 /* 00038 When built with RAID support, we need to determine if this table 00039 makes use of the raid feature. If yes, we need to remove all raid 00040 chunks. This is done with my_raid_delete(). Unfortunately it is 00041 necessary to open the table just to check this. We use 00042 'open_for_repair' to be able to open even a crashed table. If even 00043 this open fails, we assume no raid configuration for this table 00044 and try to remove the normal data file only. This may however 00045 leave the raid chunks behind. 00046 */ 00047 if (!(info= mi_open(name, O_RDONLY, HA_OPEN_FOR_REPAIR))) 00048 raid_type= 0; 00049 else 00050 { 00051 raid_type= info->s->base.raid_type; 00052 raid_chunks= info->s->base.raid_chunks; 00053 mi_close(info); 00054 } 00055 } 00056 #ifdef EXTRA_DEBUG 00057 check_table_is_closed(name,"delete"); 00058 #endif 00059 #endif /* USE_RAID */ 00060 00061 fn_format(from,name,"",MI_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT); 00062 if (my_delete_with_symlink(from, MYF(MY_WME))) 00063 DBUG_RETURN(my_errno); 00064 fn_format(from,name,"",MI_NAME_DEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT); 00065 #ifdef USE_RAID 00066 if (raid_type) 00067 DBUG_RETURN(my_raid_delete(from, raid_chunks, MYF(MY_WME)) ? my_errno : 0); 00068 #endif 00069 DBUG_RETURN(my_delete_with_symlink(from, MYF(MY_WME)) ? my_errno : 0); 00070 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 4267 of file mi_check.c.
Referenced by ha_myisam::start_bulk_insert().
04268 { 04269 MYISAM_SHARE *share=info->s; 04270 MI_KEYDEF *key=share->keyinfo; 04271 uint i; 04272 04273 DBUG_ASSERT(info->state->records == 0 && 04274 (!rows || rows >= MI_MIN_ROWS_TO_DISABLE_INDEXES)); 04275 for (i=0 ; i < share->base.keys ; i++,key++) 04276 { 04277 if (!(key->flag & (HA_NOSAME | HA_SPATIAL | HA_AUTO_KEY)) && 04278 ! mi_too_big_key_for_sort(key,rows) && info->s->base.auto_key != i+1) 04279 { 04280 mi_clear_key_active(share->state.key_map, i); 04281 info->update|= HA_STATE_CHANGED; 04282 } 04283 } 04284 }
Here is the caller graph for this function:

| void mi_end_bulk_insert | ( | MI_INFO * | info | ) |
Definition at line 1029 of file mi_write.c.
References st_mi_isam_share::base, st_myisam_info::bulk_insert, delete_tree(), is_tree_inited, st_mi_base_info::keys, my_free, MYF, and st_myisam_info::s.
Referenced by ha_myisam::end_bulk_insert().
01030 { 01031 if (info->bulk_insert) 01032 { 01033 uint i; 01034 for (i=0 ; i < info->s->base.keys ; i++) 01035 { 01036 if (is_tree_inited(& info->bulk_insert[i])) 01037 { 01038 delete_tree(& info->bulk_insert[i]); 01039 } 01040 } 01041 my_free((void *)info->bulk_insert, MYF(0)); 01042 info->bulk_insert=0; 01043 } 01044 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int mi_extra | ( | struct st_myisam_info * | file, | |
| enum ha_extra_function | function, | |||
| void * | extra_arg | |||
| ) |
Definition at line 41 of file mi_extra.c.
References _mi_memmap_file(), _mi_read_key_record(), st_mi_base_info::auto_key, st_mi_isam_share::base, bmove(), st_mi_isam_share::changed, st_mi_state_info::changed, st_mi_isam_share::concurrent_insert, st_mi_status_info::data_file_length, st_mi_isam_share::data_file_type, DBUG_ENTER, DBUG_PRINT, st_myisam_info::dfile, DYNAMIC_RECORD, end_io_cache(), st_io_cache::end_of_file, error, F_EXTRA_LCK, F_UNLCK, st_mi_isam_share::file_map, flush_io_cache, st_mi_isam_share::global_changed, HA_ERR_CRASHED, HA_EXTRA_CACHE, HA_EXTRA_FLUSH_CACHE, HA_EXTRA_KEYREAD, HA_EXTRA_KEYREAD_CHANGE_POS, HA_EXTRA_NO_CACHE, HA_EXTRA_NO_KEYREAD, HA_EXTRA_NO_KEYS, HA_EXTRA_NO_READCHECK, HA_EXTRA_NO_USER_CHANGE, HA_EXTRA_NO_WAIT_LOCK, HA_EXTRA_PREPARE_FOR_UPDATE, HA_EXTRA_READCHECK, HA_EXTRA_REINIT_CACHE, HA_EXTRA_REMEMBER_POS, HA_EXTRA_RESET_STATE, HA_EXTRA_RESTORE_POS, HA_EXTRA_WAIT_LOCK, HA_EXTRA_WRITE_CACHE, HA_NOSAME, HA_OFFSET_ERROR, HA_OPTION_COMPRESS_RECORD, HA_OPTION_PACK_RECORD, HA_STATE_CHANGED, HA_STATE_EXTEND_BLOCK, HA_STATE_NEXT_FOUND, HA_STATE_PREV_FOUND, HA_STATE_ROW_CHANGED, HA_STATE_WRITE_AT_END, HA_STATE_WRITTEN, st_mi_state_info::header, init_io_cache(), key, st_mi_state_info::key_map, KEY_READ_USED, st_mi_isam_share::keyinfo, st_mi_base_info::keys, st_myisam_info::last_search_keypage, st_myisam_info::lastinx, st_myisam_info::lastkey, st_myisam_info::lastkey_length, st_myisam_info::lastpos, st_myisam_info::lock_type, st_myisam_info::lock_wait, st_mi_base_info::max_key_length, MEMMAP_USED, mi_clear_key_active, mi_is_any_key_active, mi_mark_crashed, mi_print_error, min, my_default_record_cache_size, MY_DONT_WAIT, my_errno, MY_WAIT_IF_FULL, MYF, st_myisam_info::nextpos, st_mi_state_info::open_count, st_myisam_info::opt_flag, OPT_NO_ROWS, st_mi_isam_share::options, st_myisam_info::page_changed, pthread_mutex_lock, pthread_mutex_unlock, READ_CACHE, READ_CACHE_USED, READ_CHECK_USED, st_myisam_info::read_record, st_mi_isam_share::read_record, st_myisam_info::rec_cache, RECORD_CACHE_SIZE, reinit_io_cache(), REMEMBER_OLD_POS, st_myisam_info::s, st_myisam_info::save_lastinx, st_myisam_info::save_lastkey_length, st_myisam_info::save_lastpos, st_myisam_info::save_update, st_mi_isam_share::state, st_mi_state_info::state, st_myisam_info::state, STATE_CHANGED, STATE_NOT_ANALYZED, test, st_mi_state_info::uniques, st_myisam_info::update, WRITE_CACHE, WRITE_CACHE_USED, and st_mi_isam_share::write_flag.
Referenced by chk_key(), ha_myisam::disable_indexes(), ha_myisam::end_bulk_insert(), examine_log(), ha_myisam::extra(), ha_myisam::extra_opt(), main(), mrg_reset(), mrg_rrnd(), myrg_extra(), myrg_rrnd(), ha_myisam::open(), ha_myisam::preload_keys(), ha_myisam::start_bulk_insert(), test_rrnd(), test_write(), and update_auto_increment_key().
00042 { 00043 int error=0; 00044 ulong cache_size; 00045 MYISAM_SHARE *share=info->s; 00046 DBUG_ENTER("mi_extra"); 00047 DBUG_PRINT("enter",("function: %d",(int) function)); 00048 00049 switch (function) { 00050 case HA_EXTRA_RESET_STATE: /* Reset state (don't free buffers) */ 00051 info->lastinx= 0; /* Use first index as def */ 00052 info->last_search_keypage=info->lastpos= HA_OFFSET_ERROR; 00053 info->page_changed=1; 00054 /* Next/prev gives first/last */ 00055 if (info->opt_flag & READ_CACHE_USED) 00056 { 00057 reinit_io_cache(&info->rec_cache,READ_CACHE,0, 00058 (pbool) (info->lock_type != F_UNLCK), 00059 (pbool) test(info->update & HA_STATE_ROW_CHANGED) 00060 ); 00061 } 00062 info->update= ((info->update & HA_STATE_CHANGED) | HA_STATE_NEXT_FOUND | 00063 HA_STATE_PREV_FOUND); 00064 break; 00065 case HA_EXTRA_CACHE: 00066 if (info->lock_type == F_UNLCK && 00067 (share->options & HA_OPTION_PACK_RECORD)) 00068 { 00069 error=1; /* Not possibly if not locked */ 00070 my_errno=EACCES; 00071 break; 00072 } 00073 if (info->s->file_map) /* Don't use cache if mmap */ 00074 break; 00075 #if defined(HAVE_MMAP) && defined(HAVE_MADVISE) 00076 if ((share->options & HA_OPTION_COMPRESS_RECORD)) 00077 { 00078 pthread_mutex_lock(&share->intern_lock); 00079 if (_mi_memmap_file(info)) 00080 { 00081 /* We don't nead MADV_SEQUENTIAL if small file */ 00082 madvise(share->file_map,share->state.state.data_file_length, 00083 share->state.state.data_file_length <= RECORD_CACHE_SIZE*16 ? 00084 MADV_RANDOM : MADV_SEQUENTIAL); 00085 pthread_mutex_unlock(&share->intern_lock); 00086 break; 00087 } 00088 pthread_mutex_unlock(&share->intern_lock); 00089 } 00090 #endif 00091 if (info->opt_flag & WRITE_CACHE_USED) 00092 { 00093 info->opt_flag&= ~WRITE_CACHE_USED; 00094 if ((error=end_io_cache(&info->rec_cache))) 00095 break; 00096 } 00097 if (!(info->opt_flag & 00098 (READ_CACHE_USED | WRITE_CACHE_USED | MEMMAP_USED))) 00099 { 00100 cache_size= (extra_arg ? *(ulong*) extra_arg : 00101 my_default_record_cache_size); 00102 if (!(init_io_cache(&info->rec_cache,info->dfile, 00103 (uint) min(info->state->data_file_length+1, 00104 cache_size), 00105 READ_CACHE,0L,(pbool) (info->lock_type != F_UNLCK), 00106 MYF(share->write_flag & MY_WAIT_IF_FULL)))) 00107 { 00108 info->opt_flag|=READ_CACHE_USED; 00109 info->update&= ~HA_STATE_ROW_CHANGED; 00110 } 00111 if (share->concurrent_insert) 00112 info->rec_cache.end_of_file=info->state->data_file_length; 00113 } 00114 break; 00115 case HA_EXTRA_REINIT_CACHE: 00116 if (info->opt_flag & READ_CACHE_USED) 00117 { 00118 reinit_io_cache(&info->rec_cache,READ_CACHE,info->nextpos, 00119 (pbool) (info->lock_type != F_UNLCK), 00120 (pbool) test(info->update & HA_STATE_ROW_CHANGED)); 00121 info->update&= ~HA_STATE_ROW_CHANGED; 00122 if (share->concurrent_insert) 00123 info->rec_cache.end_of_file=info->state->data_file_length; 00124 } 00125 break; 00126 case HA_EXTRA_WRITE_CACHE: 00127 if (info->lock_type == F_UNLCK) 00128 { 00129 error=1; /* Not possibly if not locked */ 00130 break; 00131 } 00132 00133 cache_size= (extra_arg ? *(ulong*) extra_arg : 00134 my_default_record_cache_size); 00135 if (!(info->opt_flag & 00136 (READ_CACHE_USED | WRITE_CACHE_USED | OPT_NO_ROWS)) && 00137 !share->state.header.uniques) 00138 if (!(init_io_cache(&info->rec_cache,info->dfile, cache_size, 00139 WRITE_CACHE,info->state->data_file_length, 00140 (pbool) (info->lock_type != F_UNLCK), 00141 MYF(share->write_flag & MY_WAIT_IF_FULL)))) 00142 { 00143 info->opt_flag|=WRITE_CACHE_USED; 00144 info->update&= ~(HA_STATE_ROW_CHANGED | 00145 HA_STATE_WRITE_AT_END | 00146 HA_STATE_EXTEND_BLOCK); 00147 } 00148 break; 00149 case HA_EXTRA_PREPARE_FOR_UPDATE: 00150 if (info->s->data_file_type != DYNAMIC_RECORD) 00151 break; 00152 /* Remove read/write cache if dynamic rows */ 00153 case HA_EXTRA_NO_CACHE: 00154 if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED)) 00155 { 00156 info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); 00157 error=end_io_cache(&info->rec_cache); 00158 /* Sergei will insert full text index caching here */ 00159 } 00160 #if defined(HAVE_MMAP) && defined(HAVE_MADVISE) 00161 if (info->opt_flag & MEMMAP_USED) 00162 madvise(share->file_map,share->state.state.data_file_length,MADV_RANDOM); 00163 #endif 00164 break; 00165 case HA_EXTRA_FLUSH_CACHE: 00166 if (info->opt_flag & WRITE_CACHE_USED) 00167 { 00168 if ((error=flush_io_cache(&info->rec_cache))) 00169 { 00170 mi_print_error(info->s, HA_ERR_CRASHED); 00171 mi_mark_crashed(info); /* Fatal error found */ 00172 } 00173 } 00174 break; 00175 case HA_EXTRA_NO_READCHECK: 00176 info->opt_flag&= ~READ_CHECK_USED; /* No readcheck */ 00177 break; 00178 case HA_EXTRA_READCHECK: 00179 info->opt_flag|= READ_CHECK_USED; 00180 break; 00181 case HA_EXTRA_KEYREAD: /* Read only keys to record */ 00182 case HA_EXTRA_REMEMBER_POS: 00183 info->opt_flag |= REMEMBER_OLD_POS; 00184 bmove((byte*) info->lastkey+share->base.max_key_length*2, 00185 (byte*) info->lastkey,info->lastkey_length); 00186 info->save_update= info->update; 00187 info->save_lastinx= info->lastinx; 00188 info->save_lastpos= info->lastpos; 00189 info->save_lastkey_length=info->lastkey_length; 00190 if (function == HA_EXTRA_REMEMBER_POS) 00191 break; 00192 /* fall through */ 00193 case HA_EXTRA_KEYREAD_CHANGE_POS: 00194 info->opt_flag |= KEY_READ_USED; 00195 info->read_record=_mi_read_key_record; 00196 break; 00197 case HA_EXTRA_NO_KEYREAD: 00198 case HA_EXTRA_RESTORE_POS: 00199 if (info->opt_flag & REMEMBER_OLD_POS) 00200 { 00201 bmove((byte*) info->lastkey, 00202 (byte*) info->lastkey+share->base.max_key_length*2, 00203 info->save_lastkey_length); 00204 info->update= info->save_update | HA_STATE_WRITTEN; 00205 info->lastinx= info->save_lastinx; 00206 info->lastpos= info->save_lastpos; 00207 info->lastkey_length=info->save_lastkey_length; 00208 } 00209 info->read_record= share->read_record; 00210 info->opt_flag&= ~(KEY_READ_USED | REMEMBER_OLD_POS); 00211 break; 00212 case HA_EXTRA_NO_USER_CHANGE: /* Database is somehow locked agains changes */ 00213 info->lock_type= F_EXTRA_LCK; /* Simulate as locked */ 00214 break; 00215 case HA_EXTRA_WAIT_LOCK: 00216 info->lock_wait=0; 00217 break; 00218 case HA_EXTRA_NO_WAIT_LOCK: 00219 info->lock_wait=MY_DONT_WAIT; 00220 break; 00221 case HA_EXTRA_NO_KEYS: 00222 if (info->lock_type == F_UNLCK) 00223 { 00224 error=1; /* Not possibly if not lock */ 00225 break; 00226 } 00227 if (mi_is_any_key_active(share->state.key_map)) 00228 { 00229 MI_KEYDEF *key=share->keyinfo; 00230 uint i; 00231 for (i=0 ; i < share->base.keys ; i++,key++) 00232 { 00233 if (!(key->flag & HA_NOSAME) && info->s->base.auto_key != i+1) 00234 { 00235 mi_clear_key_active(share->state.key_map, i); 00236 info->update|= HA_STATE_CHANGED; 00237 } 00238 } 00239 00240 if (!share->changed) 00241 { 00242 share->state.changed|= STATE_CHANGED | STATE_NOT_ANALYZED; 00243 share->changed=1; /* Update on close */ 00244 if (!share->global_changed) 00245 { 00246 share->global_changed=1; 00247 share->state.open_count++; 00248 } 00249 } 00250 share->state.state= *info->state; 00251 error=mi_state_info_write(share->kfile,&share->state,1 | 2); 00252 } 00253 break; 00254 case HA_EXTRA_FORCE_REOPEN: 00255 pthread_mutex_lock(&THR_LOCK_myisam); 00256 share->last_version= 0L; /* Impossible version */ 00257 pthread_mutex_unlock(&THR_LOCK_myisam); 00258 break; 00259 case HA_EXTRA_PREPARE_FOR_DELETE: 00260 pthread_mutex_lock(&THR_LOCK_myisam); 00261 share->last_version= 0L; /* Impossible version */ 00262 #ifdef __WIN__ 00263 /* Close the isam and data files as Win32 can't drop an open table */ 00264 pthread_mutex_lock(&share->intern_lock); 00265 if (flush_key_blocks(share->key_cache, share->kfile, 00266 (function == HA_EXTRA_FORCE_REOPEN ? 00267 FLUSH_RELEASE : FLUSH_IGNORE_CHANGED))) 00268 { 00269 error=my_errno; 00270 share->changed=1; 00271 mi_print_error(info->s, HA_ERR_CRASHED); 00272 mi_mark_crashed(info); /* Fatal error found */ 00273 } 00274 if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED)) 00275 { 00276 info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); 00277 error=end_io_cache(&info->rec_cache); 00278 } 00279 if (info->lock_type != F_UNLCK && ! info->was_locked) 00280 { 00281 info->was_locked=info->lock_type; 00282 if (mi_lock_database(info,F_UNLCK)) 00283 error=my_errno; 00284 info->lock_type = F_UNLCK; 00285 } 00286 if (share->kfile >= 0) 00287 _mi_decrement_open_count(info); 00288 if (share->kfile >= 0 && my_close(share->kfile,MYF(0))) 00289 error=my_errno; 00290 { 00291 LIST *list_element ; 00292 for (list_element=myisam_open_list ; 00293 list_element ; 00294 list_element=list_element->next) 00295 { 00296 MI_INFO *tmpinfo=(MI_INFO*) list_element->data; 00297 if (tmpinfo->s == info->s) 00298 { 00299 if (tmpinfo->dfile >= 0 && my_close(tmpinfo->dfile,MYF(0))) 00300 error = my_errno; 00301 tmpinfo->dfile= -1; 00302 } 00303 } 00304 } 00305 share->kfile= -1; /* Files aren't open anymore */ 00306 pthread_mutex_unlock(&share->intern_lock); 00307 #endif 00308 pthread_mutex_unlock(&THR_LOCK_myisam); 00309 break; 00310 case HA_EXTRA_FLUSH: 00311 if (!share->temporary) 00312 flush_key_blocks(share->key_cache, share->kfile, FLUSH_KEEP); 00313 #ifdef HAVE_PWRITE 00314 _mi_decrement_open_count(info); 00315 #endif 00316 if (share->not_flushed) 00317 { 00318 share->not_flushed=0; 00319 if (my_sync(share->kfile, MYF(0))) 00320 error= my_errno; 00321 if (my_sync(info->dfile, MYF(0))) 00322 error= my_errno; 00323 if (error) 00324 { 00325 share->changed=1; 00326 mi_print_error(info->s, HA_ERR_CRASHED); 00327 mi_mark_crashed(info); /* Fatal error found */ 00328 } 00329 } 00330 if (share->base.blobs) 00331 mi_alloc_rec_buff(info, -1, &info->rec_buff); 00332 break; 00333 case HA_EXTRA_NORMAL: /* Theese isn't in use */ 00334 info->quick_mode=0; 00335 break; 00336 case HA_EXTRA_QUICK: 00337 info->quick_mode=1; 00338 break; 00339 case HA_EXTRA_NO_ROWS: 00340 if (!share->state.header.uniques) 00341 info->opt_flag|= OPT_NO_ROWS; 00342 break; 00343 case HA_EXTRA_PRELOAD_BUFFER_SIZE: 00344 info->preload_buff_size= *((ulong *) extra_arg); 00345 break; 00346 case HA_EXTRA_CHANGE_KEY_TO_UNIQUE: 00347 case HA_EXTRA_CHANGE_KEY_TO_DUP: 00348 mi_extra_keyflag(info, function); 00349 break; 00350 case HA_EXTRA_MMAP: 00351 #ifdef HAVE_MMAP 00352 pthread_mutex_lock(&share->intern_lock); 00353 if (!share->file_map) 00354 { 00355 if (mi_dynmap_file(info, share->state.state.data_file_length)) 00356 { 00357 DBUG_PRINT("warning",("mmap failed: errno: %d",errno)); 00358 error= my_errno= errno; 00359 } 00360 else 00361 { 00362 share->file_read= mi_mmap_pread; 00363 share->file_write= mi_mmap_pwrite; 00364 } 00365 } 00366 pthread_mutex_unlock(&share->intern_lock); 00367 #endif 00368 break; 00369 case HA_EXTRA_MARK_AS_LOG_TABLE: 00370 pthread_mutex_lock(&share->intern_lock); 00371 share->is_log_table= TRUE; 00372 pthread_mutex_unlock(&share->intern_lock); 00373 break; 00374 case HA_EXTRA_KEY_CACHE: 00375 case HA_EXTRA_NO_KEY_CACHE: 00376 default: 00377 break; 00378 } 00379 { 00380 char tmp[1]; 00381 tmp[0]=function; 00382 myisam_log_command(MI_LOG_EXTRA,info,(byte*) tmp,1,error); 00383 } 00384 DBUG_RETURN(error); 00385 } /* mi_extra */
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1020 of file mi_write.c.
References st_myisam_info::bulk_insert, is_tree_inited, and reset_tree().
Referenced by ha_myisam::get_auto_increment().
01021 { 01022 if (info->bulk_insert) 01023 { 01024 if (is_tree_inited(&info->bulk_insert[inx])) 01025 reset_tree(&info->bulk_insert[inx]); 01026 } 01027 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 848 of file mi_create.c.
References DBUG_ASSERT.
Referenced by mi_status(), and write_header().
00849 { 00850 DBUG_ASSERT(def >= 2 && def <= 7); 00851 if (file_length) /* If not default */ 00852 { 00853 #ifdef NOT_YET_READY_FOR_8_BYTE_POINTERS 00854 if (file_length >= (longlong) 1 << 56) 00855 def=8; 00856 #endif 00857 if (file_length >= (longlong) 1 << 48) 00858 def=7; 00859 if (file_length >= (longlong) 1 << 40) 00860 def=6; 00861 else if (file_length >= (longlong) 1 << 32) 00862 def=5; 00863 else if (file_length >= (1L << 24)) 00864 def=4; 00865 else if (file_length >= (1L << 16)) 00866 def=3; 00867 else 00868 def=2; 00869 } 00870 return def; 00871 }
Here is the caller graph for this function:

Definition at line 958 of file mi_write.c.
References st_mi_base_info::auto_key, st_mi_isam_share::base, st_myisam_info::bulk_insert, DBUG_ASSERT, DBUG_ENTER, DBUG_PRINT, flag, HA_NOSAME, key, st_mi_state_info::key_map, st_mi_isam_share::keyinfo, st_mi_base_info::keys, mi_clear_all_keys_active, mi_is_key_active, MI_MIN_ROWS_TO_USE_BULK_INSERT, mi_set_key_active, st_myisam_info::s, st_mi_isam_share::state, and TREE_ELEMENT_EXTRA_SIZE.
Referenced by ha_myisam::start_bulk_insert().
00959 { 00960 MYISAM_SHARE *share=info->s; 00961 MI_KEYDEF *key=share->keyinfo; 00962 bulk_insert_param *params; 00963 uint i, num_keys, total_keylength; 00964 ulonglong key_map; 00965 DBUG_ENTER("_mi_init_bulk_insert"); 00966 DBUG_PRINT("enter",("cache_size: %lu", cache_size)); 00967 00968 DBUG_ASSERT(!info->bulk_insert && 00969 (!rows || rows >= MI_MIN_ROWS_TO_USE_BULK_INSERT)); 00970 00971 mi_clear_all_keys_active(key_map); 00972 for (i=total_keylength=num_keys=0 ; i < share->base.keys ; i++) 00973 { 00974 if (! (key[i].flag & HA_NOSAME) && (share->base.auto_key != i + 1) && 00975 mi_is_key_active(share->state.key_map, i)) 00976 { 00977 num_keys++; 00978 mi_set_key_active(key_map, i); 00979 total_keylength+=key[i].maxlength+TREE_ELEMENT_EXTRA_SIZE; 00980 } 00981 } 00982 00983 if (num_keys==0 || 00984 num_keys * MI_MIN_SIZE_BULK_INSERT_TREE > cache_size) 00985 DBUG_RETURN(0); 00986 00987 if (rows && rows*total_keylength < cache_size) 00988 cache_size=rows; 00989 else 00990 cache_size/=total_keylength*16; 00991 00992 info->bulk_insert=(TREE *) 00993 my_malloc((sizeof(TREE)*share->base.keys+ 00994 sizeof(bulk_insert_param)*num_keys),MYF(0)); 00995 00996 if (!info->bulk_insert) 00997 DBUG_RETURN(HA_ERR_OUT_OF_MEM); 00998 00999 params=(bulk_insert_param *)(info->bulk_insert+share->base.keys); 01000 for (i=0 ; i < share->base.keys ; i++) 01001 { 01002 if (mi_is_key_active(key_map, i)) 01003 { 01004 params->info=info; 01005 params->keynr=i; 01006 /* Only allocate a 16'th of the buffer at a time */ 01007 init_tree(&info->bulk_insert[i], 01008 cache_size * key[i].maxlength, 01009 cache_size * key[i].maxlength, 0, 01010 (qsort_cmp2)keys_compare, 0, 01011 (tree_element_free) keys_free, (void *)params++); 01012 } 01013 else 01014 info->bulk_insert[i].root=0; 01015 } 01016 01017 DBUG_RETURN(0); 01018 }
Here is the caller graph for this function:

| int mi_is_changed | ( | struct st_myisam_info * | info | ) |
Definition at line 23 of file mi_changed.c.
References _mi_writeinfo(), st_myisam_info::data_changed, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, fast_mi_readinfo, int(), and VOID.
Referenced by main().
00024 { 00025 int result; 00026 DBUG_ENTER("mi_is_changed"); 00027 if (fast_mi_readinfo(info)) 00028 DBUG_RETURN(-1); 00029 VOID(_mi_writeinfo(info,0)); 00030 result=(int) info->data_changed; 00031 info->data_changed=0; 00032 DBUG_PRINT("exit",("result: %d",result)); 00033 DBUG_RETURN(result); 00034 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int mi_lock_database | ( | struct st_myisam_info * | file, | |
| int | lock_type | |||
| ) |
Definition at line 28 of file mi_locking.c.
References _mi_test_if_changed(), st_mi_isam_share::changed, count, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, st_mi_isam_share::delay_key_write, end_io_cache(), error, F_EXTRA_LCK, F_RDLCK, F_TO_EOF, F_UNLCK, F_WRLCK, flag, FLUSH_KEEP, flush_key_blocks(), ftparser_call_deinitializer(), st_mi_isam_share::global_changed, HA_ERR_CRASHED, HA_OPTION_READ_ONLY_DATA, st_mi_isam_share::index_file_name, int(), st_mi_isam_share::key_cache, st_mi_isam_share::kfile, st_mi_isam_share::last_process, st_myisam_info::lock_type, MAX_NONMAPPED_INSERTS, MI_LOG_LOCK, mi_mark_crashed, mi_print_error, mi_remap_file(), mi_state_info_read_dsk(), mi_state_info_write(), my_errno, my_lock(), MY_SEEK_NOT_DONE, my_sync(), MY_WME, MYF, myisam_flush, myisam_log_command, st_mi_isam_share::not_flushed, st_mi_state_info::open_count, st_mi_isam_share::options, st_mi_state_info::process, pthread_mutex_lock, pthread_mutex_unlock, st_mi_isam_share::r_locks, READ_CACHE_USED, rw_unlock, rw_wrlock, st_myisam_info::s, st_mi_isam_share::state, st_mi_isam_share::this_process, st_mi_isam_share::tot_locks, st_mi_state_info::unique, st_mi_state_info::update_count, VOID, st_mi_isam_share::w_locks, and WRITE_CACHE_USED.
Referenced by _mi_decrement_open_count(), examine_log(), ha_myisam::external_lock(), main(), mi_close(), mi_panic(), myisamchk(), myrg_lock_database(), open_isam_file(), ha_myisam::repair(), start_test(), test_read(), test_rrnd(), test_update(), and test_write().
00029 { 00030 int error; 00031 uint count; 00032 MYISAM_SHARE *share=info->s; 00033 uint flag; 00034 DBUG_ENTER("mi_lock_database"); 00035 DBUG_PRINT("enter",("lock_type: %d old lock %d r_locks: %u w_locks: %u " 00036 "global_changed: %d open_count: %u name: '%s'", 00037 lock_type, info->lock_type, share->r_locks, 00038 share->w_locks, 00039 share->global_changed, share->state.open_count, 00040 share->index_file_name)); 00041 if (share->options & HA_OPTION_READ_ONLY_DATA || 00042 info->lock_type == lock_type) 00043 DBUG_RETURN(0); 00044 if (lock_type == F_EXTRA_LCK) /* Used by TMP tables */ 00045 { 00046 ++share->w_locks; 00047 ++share->tot_locks; 00048 info->lock_type= lock_type; 00049 DBUG_RETURN(0); 00050 } 00051 00052 flag=error=0; 00053 pthread_mutex_lock(&share->intern_lock); 00054 if (share->kfile >= 0) /* May only be false on windows */ 00055 { 00056 switch (lock_type) { 00057 case F_UNLCK: 00058 ftparser_call_deinitializer(info); 00059 if (info->lock_type == F_RDLCK) 00060 count= --share->r_locks; 00061 else 00062 count= --share->w_locks; 00063 --share->tot_locks; 00064 if (info->lock_type == F_WRLCK && !share->w_locks && 00065 !share->delay_key_write && flush_key_blocks(share->key_cache, 00066 share->kfile,FLUSH_KEEP)) 00067 { 00068 error=my_errno; 00069 mi_print_error(info->s, HA_ERR_CRASHED); 00070 mi_mark_crashed(info); /* Mark that table must be checked */ 00071 } 00072 if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED)) 00073 { 00074 if (end_io_cache(&info->rec_cache)) 00075 { 00076 error=my_errno; 00077 mi_print_error(info->s, HA_ERR_CRASHED); 00078 mi_mark_crashed(info); 00079 } 00080 } 00081 if (!count) 00082 { 00083 DBUG_PRINT("info",("changed: %u w_locks: %u", 00084 (uint) share->changed, share->w_locks)); 00085 if (share->changed && !share->w_locks) 00086 { 00087 #ifdef HAVE_MMAP 00088 if ((info->s->mmaped_length != info->s->state.state.data_file_length) && 00089 (info->s->nonmmaped_inserts > MAX_NONMAPPED_INSERTS)) 00090 { 00091 if (info->s->concurrent_insert) 00092 rw_wrlock(&info->s->mmap_lock); 00093 mi_remap_file(info, info->s->state.state.data_file_length); 00094 info->s->nonmmaped_inserts= 0; 00095 if (info->s->concurrent_insert) 00096 rw_unlock(&info->s->mmap_lock); 00097 } 00098 #endif 00099 share->state.process= share->last_process=share->this_process; 00100 share->state.unique= info->last_unique= info->this_unique; 00101 share->state.update_count= info->last_loop= ++info->this_loop; 00102 if (mi_state_info_write(share->kfile, &share->state, 1)) 00103 error=my_errno; 00104 share->changed=0; 00105 if (myisam_flush) 00106 { 00107 if (my_sync(share->kfile, MYF(0))) 00108 error= my_errno; 00109 if (my_sync(info->dfile, MYF(0))) 00110 error= my_errno; 00111 } 00112 else 00113 share->not_flushed=1; 00114 if (error) 00115 { 00116 mi_print_error(info->s, HA_ERR_CRASHED); 00117 mi_mark_crashed(info); 00118 } 00119 } 00120 if (info->lock_type != F_EXTRA_LCK) 00121 { 00122 if (share->r_locks) 00123 { /* Only read locks left */ 00124 flag=1; 00125 if (my_lock(share->kfile,F_RDLCK,0L,F_TO_EOF, 00126 MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error) 00127 error=my_errno; 00128 } 00129 else if (!share->w_locks) 00130 { /* No more locks */ 00131 flag=1; 00132 if (my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF, 00133 MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error) 00134 error=my_errno; 00135 } 00136 } 00137 } 00138 info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); 00139 info->lock_type= F_UNLCK; 00140 break; 00141 case F_RDLCK: 00142 if (info->lock_type == F_WRLCK) 00143 { 00144 /* 00145 Change RW to READONLY 00146 00147 mysqld does not turn write locks to read locks, 00148 so we're never here in mysqld. 00149 */ 00150 if (share->w_locks == 1) 00151 { 00152 flag=1; 00153 if (my_lock(share->kfile,lock_type,0L,F_TO_EOF, 00154 MYF(MY_SEEK_NOT_DONE))) 00155 { 00156 error=my_errno; 00157 break; 00158 } 00159 } 00160 share->w_locks--; 00161 share->r_locks++; 00162 info->lock_type=lock_type; 00163 break; 00164 } 00165 if (!share->r_locks && !share->w_locks) 00166 { 00167 flag=1; 00168 if (my_lock(share->kfile,lock_type,0L,F_TO_EOF, 00169 info->lock_wait | MY_SEEK_NOT_DONE)) 00170 { 00171 error=my_errno; 00172 break; 00173 } 00174 if (mi_state_info_read_dsk(share->kfile, &share->state, 1)) 00175 { 00176 error=my_errno; 00177 VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE))); 00178 my_errno=error; 00179 break; 00180 } 00181 } 00182 VOID(_mi_test_if_changed(info)); 00183 share->r_locks++; 00184 share->tot_locks++; 00185 info->lock_type=lock_type; 00186 break; 00187 case F_WRLCK: 00188 if (info->lock_type == F_RDLCK) 00189 { /* Change READONLY to RW */ 00190 if (share->r_locks == 1) 00191 { 00192 flag=1; 00193 if (my_lock(share->kfile,lock_type,0L,F_TO_EOF, 00194 MYF(info->lock_wait | MY_SEEK_NOT_DONE))) 00195 { 00196 error=my_errno; 00197 break; 00198 } 00199 share->r_locks--; 00200 share->w_locks++; 00201 info->lock_type=lock_type; 00202 break; 00203 } 00204 } 00205 if (!(share->options & HA_OPTION_READ_ONLY_DATA)) 00206 { 00207 if (!share->w_locks) 00208 { 00209 flag=1; 00210 if (my_lock(share->kfile,lock_type,0L,F_TO_EOF, 00211 info->lock_wait | MY_SEEK_NOT_DONE)) 00212 { 00213 error=my_errno; 00214 break; 00215 } 00216 if (!share->r_locks) 00217 { 00218 if (mi_state_info_read_dsk(share->kfile, &share->state, 1)) 00219 { 00220 error=my_errno; 00221 VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF, 00222 info->lock_wait | MY_SEEK_NOT_DONE)); 00223 my_errno=error; 00224 break; 00225 } 00226 } 00227 } 00228 } 00229 VOID(_mi_test_if_changed(info)); 00230 00231 info->lock_type=lock_type; 00232 info->invalidator=info->s->invalidator; 00233 share->w_locks++; 00234 share->tot_locks++; 00235 break; 00236 default: 00237 break; /* Impossible */ 00238 } 00239 } 00240 pthread_mutex_unlock(&share->intern_lock); 00241 #if defined(FULL_LOG) || defined(_lint) 00242 lock_type|=(int) (flag << 8); /* Set bit to set if real lock */ 00243 myisam_log_command(MI_LOG_LOCK,info,(byte*) &lock_type,sizeof(lock_type), 00244 error); 00245 #endif 00246 DBUG_RETURN(error); 00247 } /* mi_lock_database */
Here is the call graph for this function:

Here is the caller graph for this function:

| int mi_log | ( | int | activate_log | ) |
Definition at line 45 of file mi_log.c.
References DBUG_ENTER, DBUG_RETURN, error, fn_format(), FN_REFLEN, log_type, my_close(), my_create(), my_errno, MYF, myisam_log_file, myisam_log_filename, myisam_pid, and O_BINARY.
Referenced by init_server_components(), main(), mi_panic(), and start_test().
00046 { 00047 int error=0; 00048 char buff[FN_REFLEN]; 00049 DBUG_ENTER("mi_log"); 00050 00051 log_type=activate_log; 00052 if (activate_log) 00053 { 00054 if (!myisam_pid) 00055 myisam_pid=(ulong) getpid(); 00056 if (myisam_log_file < 0) 00057 { 00058 if ((myisam_log_file = my_create(fn_format(buff,myisam_log_filename, 00059 "",".log",4), 00060 0,(O_RDWR | O_BINARY | O_APPEND),MYF(0))) 00061 < 0) 00062 DBUG_RETURN(my_errno); 00063 } 00064 } 00065 else if (myisam_log_file >= 0) 00066 { 00067 error=my_close(myisam_log_file,MYF(0)) ? my_errno : 0 ; 00068 myisam_log_file= -1; 00069 } 00070 DBUG_RETURN(error); 00071 }
Here is the call graph for this function:

Here is the caller graph for this function:

| struct st_myisam_info* mi_open | ( | const char * | name, | |
| int | mode, | |||
| uint | wait_if_locked | |||
| ) |
Definition at line 76 of file mi_open.c.
References st_mi_isam_share::base, st_mi_state_info::base_info_length, st_mi_state_info::base_pos, bzero, st_mi_state_info::changed, charset, DBUG_DUMP, DBUG_ENTER, DBUG_EXECUTE_IF, DBUG_PRINT, default_charset_info, disk_pos_assert, err, errno, F_RDLCK, F_TO_EOF, st_mi_state_info::file_version, fn_format(), FN_REFLEN, ft_keysegs, FT_SEGS, st_mi_state_info::fulltext_keys, get_charset(), HA_ERR_CRASHED, HA_ERR_CRASHED_ON_REPAIR, HA_ERR_CRASHED_ON_USAGE, HA_ERR_NOT_A_TABLE, HA_ERR_OLD_FILE, HA_ERR_UNKNOWN_CHARSET, HA_ERR_UNSUPPORTED, HA_FT_WLEN, HA_FULLTEXT, HA_KEY_ALG_RTREE, HA_KEYSEG_SIZE, HA_KEYTYPE_TEXT, HA_KEYTYPE_VARTEXT1, HA_KEYTYPE_VARTEXT2, HA_OPEN_ABORT_IF_CRASHED, HA_OPEN_FOR_REPAIR, HA_OPEN_FROM_SQL_LAYER, HA_OPEN_IGNORE_IF_LOCKED, HA_OPEN_TMP_TABLE, HA_OPEN_WAIT_IF_LOCKED, HA_OPTION_CHECKSUM, HA_OPTION_COMPRESS_RECORD, HA_OPTION_DELAY_KEY_WRITE, HA_OPTION_PACK_KEYS, HA_OPTION_PACK_RECORD, HA_OPTION_READ_ONLY_DATA, HA_OPTION_RELIES_ON_SQL_LAYER, HA_OPTION_TEMP_COMPRESS_RECORD, HA_OPTION_TMP_TABLE, HA_SPATIAL, HAVE_SPATIAL, st_mi_state_info::header, st_mi_state_info::header_length, info, INT_MAX32, IO_SIZE, st_mi_state_info::key_parts, st_mi_base_info::key_reflength, keys, st_mi_state_info::keys, st_mi_base_info::keystart, LINT_INIT, st_mi_base_info::max_data_file_length, st_mi_base_info::max_key_file_length, st_mi_base_info::max_key_length, memcmp(), memcpy, MI_BASE_INFO_SIZE, mi_keydef_read(), mi_keyseg_read(), MI_MAX_KEY, MI_MAX_KEY_BLOCK_SIZE, MI_MAX_KEY_BUFF, MI_MAX_KEY_SEG, MI_MAX_POSSIBLE_KEY, MI_MIN_KEY_BLOCK_LENGTH, MI_NAME_DEXT, MI_NAME_IEXT, mi_safe_mul(), mi_state_info_read(), MI_STATE_INFO_SIZE, mi_uint2korr, min, st_mi_isam_share::mode, multi_key_cache_search(), my_alloca, MY_APPEND_EXT, my_disable_locking, MY_DONT_WAIT, my_errno, my_lock(), my_multi_malloc(), my_n_base_info_read(), MY_NABP, my_open(), my_read, my_readlink(), my_realpath(), MY_RESOLVE_SYMLINKS, my_seek(), MY_SEEK_SET, MY_UNPACK_FILENAME, MY_WME, MYF, myisam_block_size, myisam_file_magic, NullS, O_SHARE, offset, st_mi_state_info::open_count, st_mi_isam_share::options, st_mi_state_info::options, st_mi_base_info::pack_reclength, pos(), pthread_mutex_lock, st_mi_base_info::raid_chunks, st_mi_base_info::raid_type, st_mi_state_info::rec_per_key_part, st_mi_base_info::rec_reflength, set_if_smaller, setup_key_functions(), SPDIMS, st_mi_isam_share::state, STATE_CRASHED, STATE_CRASHED_ON_REPAIR, st_mi_isam_share::state_diff_length, st_mi_state_info::state_info_length, st_mi_state_info::state_length, strcmp(), strlen(), strmov(), strrchr(), strstr(), test_if_reopen(), THREAD, st_mi_state_info::unique_key_parts, st_mi_state_info::uniques, and VOID.
Referenced by examine_log(), main(), mi_delete_table(), mi_rename(), myisamchk(), myrg_open(), ha_myisam::open(), open_isam_file(), recreate_table(), reopen_closed_file(), run_test(), and start_test().
00077 { 00078 int lock_error,kfile,open_mode,save_errno,have_rtree=0; 00079 uint i,j,len,errpos,head_length,base_pos,offset,info_length,keys, 00080 key_parts,unique_key_parts,fulltext_keys,uniques; 00081 char name_buff[FN_REFLEN], org_name[FN_REFLEN], index_name[FN_REFLEN], 00082 data_name[FN_REFLEN]; 00083 char *disk_cache, *disk_pos, *end_pos; 00084 MI_INFO info,*m_info,*old_info; 00085 MYISAM_SHARE share_buff,*share; 00086 ulong rec_per_key_part[MI_MAX_POSSIBLE_KEY*MI_MAX_KEY_SEG]; 00087 my_off_t key_root[MI_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE]; 00088 ulonglong max_key_file_length, max_data_file_length; 00089 DBUG_ENTER("mi_open"); 00090 00091 LINT_INIT(m_info); 00092 kfile= -1; 00093 lock_error=1; 00094 errpos=0; 00095 head_length=sizeof(share_buff.state.header); 00096 bzero((byte*) &info,sizeof(info)); 00097 00098 my_realpath(name_buff, fn_format(org_name,name,"",MI_NAME_IEXT, 00099 MY_UNPACK_FILENAME),MYF(0)); 00100 pthread_mutex_lock(&THR_LOCK_myisam); 00101 if (!(old_info=test_if_reopen(name_buff))) 00102 { 00103 share= &share_buff; 00104 bzero((gptr) &share_buff,sizeof(share_buff)); 00105 share_buff.state.rec_per_key_part=rec_per_key_part; 00106 share_buff.state.key_root=key_root; 00107 share_buff.state.key_del=key_del; 00108 share_buff.key_cache= multi_key_cache_search(name_buff, strlen(name_buff)); 00109 00110 DBUG_EXECUTE_IF("myisam_pretend_crashed_table_on_open", 00111 if (strstr(name, "/t1")) 00112 { 00113 my_errno= HA_ERR_CRASHED; 00114 goto err; 00115 }); 00116 if ((kfile=my_open(name_buff,(open_mode=O_RDWR) | O_SHARE,MYF(0))) < 0) 00117 { 00118 if ((errno != EROFS && errno != EACCES) || 00119 mode != O_RDONLY || 00120 (kfile=my_open(name_buff,(open_mode=O_RDONLY) | O_SHARE,MYF(0))) < 0) 00121 goto err; 00122 } 00123 share->mode=open_mode; 00124 errpos=1; 00125 if (my_read(kfile,(char*) share->state.header.file_version,head_length, 00126 MYF(MY_NABP))) 00127 { 00128 my_errno= HA_ERR_NOT_A_TABLE; 00129 goto err; 00130 } 00131 if (memcmp((byte*) share->state.header.file_version, 00132 (byte*) myisam_file_magic, 4)) 00133 { 00134 DBUG_PRINT("error",("Wrong header in %s",name_buff)); 00135 DBUG_DUMP("error_dump",(char*) share->state.header.file_version, 00136 head_length); 00137 my_errno=HA_ERR_NOT_A_TABLE; 00138 goto err; 00139 } 00140 share->options= mi_uint2korr(share->state.header.options); 00141 if (share->options & 00142 ~(HA_OPTION_PACK_RECORD | HA_OPTION_PACK_KEYS | 00143 HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA | 00144 HA_OPTION_TEMP_COMPRESS_RECORD | HA_OPTION_CHECKSUM | 00145 HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE | 00146 HA_OPTION_RELIES_ON_SQL_LAYER)) 00147 { 00148 DBUG_PRINT("error",("wrong options: 0x%lx", share->options)); 00149 my_errno=HA_ERR_OLD_FILE; 00150 goto err; 00151 } 00152 if ((share->options & HA_OPTION_RELIES_ON_SQL_LAYER) && 00153 ! (open_flags & HA_OPEN_FROM_SQL_LAYER)) 00154 { 00155 DBUG_PRINT("error", ("table cannot be openned from non-sql layer")); 00156 my_errno= HA_ERR_UNSUPPORTED; 00157 goto err; 00158 } 00159 /* Don't call realpath() if the name can't be a link */ 00160 if (!strcmp(name_buff, org_name) || 00161 my_readlink(index_name, org_name, MYF(0)) == -1) 00162 (void) strmov(index_name, org_name); 00163 *strrchr(org_name, '.')= '\0'; 00164 (void) fn_format(data_name,org_name,"",MI_NAME_DEXT, 00165 MY_APPEND_EXT|MY_UNPACK_FILENAME|MY_RESOLVE_SYMLINKS); 00166 00167 info_length=mi_uint2korr(share->state.header.header_length); 00168 base_pos=mi_uint2korr(share->state.header.base_pos); 00169 if (!(disk_cache=(char*) my_alloca(info_length+128))) 00170 { 00171 my_errno=ENOMEM; 00172 goto err; 00173 } 00174 end_pos=disk_cache+info_length; 00175 errpos=2; 00176 00177 VOID(my_seek(kfile,0L,MY_SEEK_SET,MYF(0))); 00178 if (!(open_flags & HA_OPEN_TMP_TABLE)) 00179 { 00180 if ((lock_error=my_lock(kfile,F_RDLCK,0L,F_TO_EOF, 00181 MYF(open_flags & HA_OPEN_WAIT_IF_LOCKED ? 00182 0 : MY_DONT_WAIT))) && 00183 !(open_flags & HA_OPEN_IGNORE_IF_LOCKED)) 00184 goto err; 00185 } 00186 errpos=3; 00187 if (my_read(kfile,disk_cache,info_length,MYF(MY_NABP))) 00188 { 00189 my_errno=HA_ERR_CRASHED; 00190 goto err; 00191 } 00192 len=mi_uint2korr(share->state.header.state_info_length); 00193 keys= (uint) share->state.header.keys; 00194 uniques= (uint) share->state.header.uniques; 00195 fulltext_keys= (uint) share->state.header.fulltext_keys; 00196 key_parts= mi_uint2korr(share->state.header.key_parts); 00197 unique_key_parts= mi_uint2korr(share->state.header.unique_key_parts); 00198 if (len != MI_STATE_INFO_SIZE) 00199 { 00200 DBUG_PRINT("warning", 00201 ("saved_state_info_length: %d state_info_length: %d", 00202 len,MI_STATE_INFO_SIZE)); 00203 } 00204 share->state_diff_length=len-MI_STATE_INFO_SIZE; 00205 00206 mi_state_info_read((uchar*) disk_cache, &share->state); 00207 len= mi_uint2korr(share->state.header.base_info_length); 00208 if (len != MI_BASE_INFO_SIZE) 00209 { 00210 DBUG_PRINT("warning",("saved_base_info_length: %d base_info_length: %d", 00211 len,MI_BASE_INFO_SIZE)); 00212 } 00213 disk_pos= (char*) 00214 my_n_base_info_read((uchar*) disk_cache + base_pos, &share->base); 00215 share->state.state_length=base_pos; 00216 00217 if (!(open_flags & HA_OPEN_FOR_REPAIR) && 00218 ((share->state.changed & STATE_CRASHED) || 00219 ((open_flags & HA_OPEN_ABORT_IF_CRASHED) && 00220 (my_disable_locking && share->state.open_count)))) 00221 { 00222 DBUG_PRINT("error",("Table is marked as crashed")); 00223 my_errno=((share->state.changed & STATE_CRASHED_ON_REPAIR) ? 00224 HA_ERR_CRASHED_ON_REPAIR : HA_ERR_CRASHED_ON_USAGE); 00225 goto err; 00226 } 00227 00228 /* sanity check */ 00229 if (share->base.keystart > 65535 || share->base.rec_reflength > 8) 00230 { 00231 my_errno=HA_ERR_CRASHED; 00232 goto err; 00233 } 00234 00235 key_parts+=fulltext_keys*FT_SEGS; 00236 if (share->base.max_key_length > MI_MAX_KEY_BUFF || keys > MI_MAX_KEY || 00237 key_parts >= MI_MAX_KEY * MI_MAX_KEY_SEG) 00238 { 00239 DBUG_PRINT("error",("Wrong key info: Max_key_length: %d keys: %d key_parts: %d", share->base.max_key_length, keys, key_parts)); 00240 my_errno=HA_ERR_UNSUPPORTED; 00241 goto err; 00242 } 00243 00244 /* Correct max_file_length based on length of sizeof(off_t) */ 00245 max_data_file_length= 00246 (share->options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ? 00247 (((ulonglong) 1 << (share->base.rec_reflength*8))-1) : 00248 (mi_safe_mul(share->base.pack_reclength, 00249 (ulonglong) 1 << (share->base.rec_reflength*8))-1); 00250 max_key_file_length= 00251 mi_safe_mul(MI_MIN_KEY_BLOCK_LENGTH, 00252 ((ulonglong) 1 << (share->base.key_reflength*8))-1); 00253 #if SIZEOF_OFF_T == 4 00254 set_if_smaller(max_data_file_length, INT_MAX32); 00255 set_if_smaller(max_key_file_length, INT_MAX32); 00256 #endif 00257 #if USE_RAID && SYSTEM_SIZEOF_OFF_T == 4 00258 set_if_smaller(max_key_file_length, INT_MAX32); 00259 if (!share->base.raid_type) 00260 { 00261 set_if_smaller(max_data_file_length, INT_MAX32); 00262 } 00263 else 00264 { 00265 set_if_smaller(max_data_file_length, 00266 (ulonglong) share->base.raid_chunks << 31); 00267 } 00268 #elif !defined(USE_RAID) 00269 if (share->base.raid_type) 00270 { 00271 DBUG_PRINT("error",("Table uses RAID but we don't have RAID support")); 00272 my_errno=HA_ERR_UNSUPPORTED; 00273 goto err; 00274 } 00275 #endif 00276 share->base.max_data_file_length=(my_off_t) max_data_file_length; 00277 share->base.max_key_file_length=(my_off_t) max_key_file_length; 00278 00279 if (share->options & HA_OPTION_COMPRESS_RECORD) 00280 share->base.max_key_length+=2; /* For safety */ 00281 00282 if (!my_multi_malloc(MY_WME, 00283 &share,sizeof(*share), 00284 &share->state.rec_per_key_part,sizeof(long)*key_parts, 00285 &share->keyinfo,keys*sizeof(MI_KEYDEF), 00286 &share->uniqueinfo,uniques*sizeof(MI_UNIQUEDEF), 00287 &share->keyparts, 00288 (key_parts+unique_key_parts+keys+uniques) * 00289 sizeof(HA_KEYSEG), 00290 &share->rec, 00291 (share->base.fields+1)*sizeof(MI_COLUMNDEF), 00292 &share->blobs,sizeof(MI_BLOB)*share->base.blobs, 00293 &share->unique_file_name,strlen(name_buff)+1, 00294 &share->index_file_name,strlen(index_name)+1, 00295 &share->data_file_name,strlen(data_name)+1, 00296 &share->state.key_root,keys*sizeof(my_off_t), 00297 &share->state.key_del, 00298 (share->state.header.max_block_size_index*sizeof(my_off_t)), 00299 #ifdef THREAD 00300 &share->key_root_lock,sizeof(rw_lock_t)*keys, 00301 #endif 00302 &share->mmap_lock,sizeof(rw_lock_t), 00303 NullS)) 00304 goto err; 00305 errpos=4; 00306 *share=share_buff; 00307 memcpy((char*) share->state.rec_per_key_part, 00308 (char*) rec_per_key_part, sizeof(long)*key_parts); 00309 memcpy((char*) share->state.key_root, 00310 (char*) key_root, sizeof(my_off_t)*keys); 00311 memcpy((char*) share->state.key_del, 00312 (char*) key_del, (sizeof(my_off_t) * 00313 share->state.header.max_block_size_index)); 00314 strmov(share->unique_file_name, name_buff); 00315 share->unique_name_length= strlen(name_buff); 00316 strmov(share->index_file_name, index_name); 00317 strmov(share->data_file_name, data_name); 00318 00319 share->blocksize=min(IO_SIZE,myisam_block_size); 00320 { 00321 HA_KEYSEG *pos=share->keyparts; 00322 for (i=0 ; i < keys ; i++) 00323 { 00324 share->keyinfo[i].share= share; 00325 disk_pos=mi_keydef_read(disk_pos, &share->keyinfo[i]); 00326 disk_pos_assert(disk_pos + share->keyinfo[i].keysegs * HA_KEYSEG_SIZE, 00327 end_pos); 00328 if (share->keyinfo[i].key_alg == HA_KEY_ALG_RTREE) 00329 have_rtree=1; 00330 set_if_smaller(share->blocksize,share->keyinfo[i].block_length); 00331 share->keyinfo[i].seg=pos; 00332 for (j=0 ; j < share->keyinfo[i].keysegs; j++,pos++) 00333 { 00334 disk_pos=mi_keyseg_read(disk_pos, pos); 00335 00336 if (pos->type == HA_KEYTYPE_TEXT || 00337 pos->type == HA_KEYTYPE_VARTEXT1 || 00338 pos->type == HA_KEYTYPE_VARTEXT2) 00339 { 00340 if (!pos->language) 00341 pos->charset=default_charset_info; 00342 else if (!(pos->charset= get_charset(pos->language, MYF(MY_WME)))) 00343 { 00344 my_errno=HA_ERR_UNKNOWN_CHARSET; 00345 goto err; 00346 } 00347 } 00348 } 00349 if (share->keyinfo[i].flag & HA_SPATIAL) 00350 { 00351 #ifdef HAVE_SPATIAL 00352 uint sp_segs=SPDIMS*2; 00353 share->keyinfo[i].seg=pos-sp_segs; 00354 share->keyinfo[i].keysegs--; 00355 #else 00356 my_errno=HA_ERR_UNSUPPORTED; 00357 goto err; 00358 #endif 00359 } 00360 else if (share->keyinfo[i].flag & HA_FULLTEXT) 00361 { 00362 if (!fulltext_keys) 00363 { /* 4.0 compatibility code, to be removed in 5.0 */ 00364 share->keyinfo[i].seg=pos-FT_SEGS; 00365 share->keyinfo[i].keysegs-=FT_SEGS; 00366 } 00367 else 00368 { 00369 uint j; 00370 share->keyinfo[i].seg=pos; 00371 for (j=0; j < FT_SEGS; j++) 00372 { 00373 *pos=ft_keysegs[j]; 00374 pos[0].language= pos[-1].language; 00375 if (!(pos[0].charset= pos[-1].charset)) 00376 { 00377 my_errno=HA_ERR_CRASHED; 00378 goto err; 00379 } 00380 pos++; 00381 } 00382 } 00383 if (!share->ft2_keyinfo.seg) 00384 { 00385 memcpy(& share->ft2_keyinfo, & share->keyinfo[i], sizeof(MI_KEYDEF)); 00386 share->ft2_keyinfo.keysegs=1; 00387 share->ft2_keyinfo.flag=0; 00388 share->ft2_keyinfo.keylength= 00389 share->ft2_keyinfo.minlength= 00390 share->ft2_keyinfo.maxlength=HA_FT_WLEN+share->base.rec_reflength; 00391 share->ft2_keyinfo.seg=pos-1; 00392 share->ft2_keyinfo.end=pos; 00393 setup_key_functions(& share->ft2_keyinfo); 00394 } 00395 } 00396 setup_key_functions(share->keyinfo+i); 00397 share->keyinfo[i].end=pos; 00398 pos->type=HA_KEYTYPE_END; /* End */ 00399 pos->length=share->base.rec_reflength; 00400 pos->null_bit=0; 00401 pos->flag=0; /* For purify */ 00402 pos++; 00403 } 00404 for (i=0 ; i < uniques ; i++) 00405 { 00406 disk_pos=mi_uniquedef_read(disk_pos, &share->uniqueinfo[i]); 00407 disk_pos_assert(disk_pos + share->uniqueinfo[i].keysegs * 00408 HA_KEYSEG_SIZE, end_pos); 00409 share->uniqueinfo[i].seg=pos; 00410 for (j=0 ; j < share->uniqueinfo[i].keysegs; j++,pos++) 00411 { 00412 disk_pos=mi_keyseg_read(disk_pos, pos); 00413 if (pos->type == HA_KEYTYPE_TEXT || 00414 pos->type == HA_KEYTYPE_VARTEXT1 || 00415 pos->type == HA_KEYTYPE_VARTEXT2) 00416 { 00417 if (!pos->language) 00418 pos->charset=default_charset_info; 00419 else if (!(pos->charset= get_charset(pos->language, MYF(MY_WME)))) 00420 { 00421 my_errno=HA_ERR_UNKNOWN_CHARSET; 00422 goto err; 00423 } 00424 } 00425 } 00426 share->uniqueinfo[i].end=pos; 00427 pos->type=HA_KEYTYPE_END; /* End */ 00428 pos->null_bit=0; 00429 pos->flag=0; 00430 pos++; 00431 } 00432 share->ftparsers= 0; 00433 } 00434 00435 disk_pos_assert(disk_pos + share->base.fields *MI_COLUMNDEF_SIZE, end_pos); 00436 for (i=j=offset=0 ; i < share->base.fields ; i++) 00437 { 00438 disk_pos=mi_recinfo_read(disk_pos,&share->rec[i]); 00439 share->rec[i].pack_type=0; 00440 share->rec[i].huff_tree=0; 00441 share->rec[i].offset=offset; 00442 if (share->rec[i].type == (int) FIELD_BLOB) 00443 { 00444 share->blobs[j].pack_length= 00445 share->rec[i].length-mi_portable_sizeof_char_ptr;; 00446 share->blobs[j].offset=offset; 00447 j++; 00448 } 00449 offset+=share->rec[i].length; 00450 } 00451 share->rec[i].type=(int) FIELD_LAST; /* End marker */ 00452 00453 if (! lock_error) 00454 { 00455 VOID(my_lock(kfile,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE))); 00456 lock_error=1; /* Database unlocked */ 00457 } 00458 00459 if (mi_open_datafile(&info, share, -1)) 00460 goto err; 00461 errpos=5; 00462 00463 share->kfile=kfile; 00464 share->this_process=(ulong) getpid(); 00465 share->last_process= share->state.process; 00466 share->base.key_parts=key_parts; 00467 share->base.all_key_parts=key_parts+unique_key_parts; 00468 if (!(share->last_version=share->state.version)) 00469 share->last_version=1; /* Safety */ 00470 share->rec_reflength=share->base.rec_reflength; /* May be changed */ 00471 share->base.margin_key_file_length=(share->base.max_key_file_length - 00472 (keys ? MI_INDEX_BLOCK_MARGIN * 00473 share->blocksize * keys : 0)); 00474 share->blocksize=min(IO_SIZE,myisam_block_size); 00475 share->data_file_type=STATIC_RECORD; 00476 if (share->options & HA_OPTION_COMPRESS_RECORD) 00477 { 00478 share->data_file_type = COMPRESSED_RECORD; 00479 share->options|= HA_OPTION_READ_ONLY_DATA; 00480 info.s=share; 00481 if (_mi_read_pack_info(&info, 00482 (pbool) 00483 test(!(share->options & 00484 (HA_OPTION_PACK_RECORD | 00485 HA_OPTION_TEMP_COMPRESS_RECORD))))) 00486 goto err; 00487 } 00488 else if (share->options & HA_OPTION_PACK_RECORD) 00489 share->data_file_type = DYNAMIC_RECORD; 00490 my_afree((gptr) disk_cache); 00491 mi_setup_functions(share); 00492 share->is_log_table= FALSE; 00493 #ifdef THREAD 00494 thr_lock_init(&share->lock); 00495 VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST)); 00496 for (i=0; i<keys; i++) 00497 VOID(my_rwlock_init(&share->key_root_lock[i], NULL)); 00498 VOID(my_rwlock_init(&share->mmap_lock, NULL)); 00499 if (!thr_lock_inited) 00500 { 00501 /* Probably a single threaded program; Don't use concurrent inserts */ 00502 myisam_concurrent_insert=0; 00503 } 00504 else if (myisam_concurrent_insert) 00505 { 00506 share->concurrent_insert= 00507 ((share->options & (HA_OPTION_READ_ONLY_DATA | HA_OPTION_TMP_TABLE | 00508 HA_OPTION_COMPRESS_RECORD | 00509 HA_OPTION_TEMP_COMPRESS_RECORD)) || 00510 (open_flags & HA_OPEN_TMP_TABLE) || 00511 have_rtree) ? 0 : 1; 00512 if (share->concurrent_insert) 00513 { 00514 share->lock.get_status=mi_get_status; 00515 share->lock.copy_status=mi_copy_status; 00516 share->lock.update_status=mi_update_status; 00517 share->lock.check_status=mi_check_status; 00518 } 00519 } 00520 #endif 00521 } 00522 else 00523 { 00524 share= old_info->s; 00525 if (mode == O_RDWR && share->mode == O_RDONLY) 00526 { 00527 my_errno=EACCES; /* Can't open in write mode */ 00528 goto err; 00529 } 00530 if (mi_open_datafile(&info, share, old_info->dfile)) 00531 goto err; 00532 errpos=5; 00533 have_rtree= old_info->rtree_recursion_state != NULL; 00534 } 00535 00536 /* alloc and set up private structure parts */ 00537 if (!my_multi_malloc(MY_WME, 00538 &m_info,sizeof(MI_INFO), 00539 &info.blobs,sizeof(MI_BLOB)*share->base.blobs, 00540 &info.buff,(share->base.max_key_block_length*2+ 00541 share->base.max_key_length), 00542 &info.lastkey,share->base.max_key_length*3+1, 00543 &info.first_mbr_key, share->base.max_key_length, 00544 &info.filename,strlen(name)+1, 00545 &info.rtree_recursion_state,have_rtree ? 1024 : 0, 00546 NullS)) 00547 goto err; 00548 errpos=6; 00549 00550 if (!have_rtree) 00551 info.rtree_recursion_state= NULL; 00552 00553 strmov(info.filename,name); 00554 memcpy(info.blobs,share->blobs,sizeof(MI_BLOB)*share->base.blobs); 00555 info.lastkey2=info.lastkey+share->base.max_key_length; 00556 00557 info.s=share; 00558 info.lastpos= HA_OFFSET_ERROR; 00559 info.update= (short) (HA_STATE_NEXT_FOUND+HA_STATE_PREV_FOUND); 00560 info.opt_flag=READ_CHECK_USED; 00561 info.this_unique= (ulong) info.dfile; /* Uniq number in process */ 00562 if (share->data_file_type == COMPRESSED_RECORD) 00563 info.this_unique= share->state.unique; 00564 info.this_loop=0; /* Update counter */ 00565 info.last_unique= share->state.unique; 00566 info.last_loop= share->state.update_count; 00567 if (mode == O_RDONLY) 00568 share->options|=HA_OPTION_READ_ONLY_DATA; 00569 info.lock_type=F_UNLCK; 00570 info.quick_mode=0; 00571 info.bulk_insert=0; 00572 info.ft1_to_ft2=0; 00573 info.errkey= -1; 00574 info.page_changed=1; 00575 pthread_mutex_lock(&share->intern_lock); 00576 info.read_record=share->read_record; 00577 share->reopen++; 00578 share->write_flag=MYF(MY_NABP | MY_WAIT_IF_FULL); 00579 if (share->options & HA_OPTION_READ_ONLY_DATA) 00580 { 00581 info.lock_type=F_RDLCK; 00582 share->r_locks++; 00583 share->tot_locks++; 00584 } 00585 if ((open_flags & HA_OPEN_TMP_TABLE) || 00586 (share->options & HA_OPTION_TMP_TABLE)) 00587 { 00588 share->temporary=share->delay_key_write=1; 00589 share->write_flag=MYF(MY_NABP); 00590 share->w_locks++; /* We don't have to update status */ 00591 share->tot_locks++; 00592 info.lock_type=F_WRLCK; 00593 } 00594 if (((open_flags & HA_OPEN_DELAY_KEY_WRITE) || 00595 (share->options & HA_OPTION_DELAY_KEY_WRITE)) && 00596 myisam_delay_key_write) 00597 share->delay_key_write=1; 00598 info.state= &share->state.state; /* Change global values by default */ 00599 pthread_mutex_unlock(&share->intern_lock); 00600 00601 /* Allocate buffer for one record */ 00602 00603 /* prerequisites: bzero(info) && info->s=share; are met. */ 00604 if (!mi_alloc_rec_buff(&info, -1, &info.rec_buff)) 00605 goto err; 00606 bzero(info.rec_buff, mi_get_rec_buff_len(&info, info.rec_buff)); 00607 00608 *m_info=info; 00609 #ifdef THREAD 00610 thr_lock_data_init(&share->lock,&m_info->lock,(void*) m_info); 00611 #endif 00612 m_info->open_list.data=(void*) m_info; 00613 myisam_open_list=list_add(myisam_open_list,&m_info->open_list); 00614 00615 pthread_mutex_unlock(&THR_LOCK_myisam); 00616 if (myisam_log_file >= 0) 00617 { 00618 intern_filename(name_buff,share->index_file_name); 00619 _myisam_log(MI_LOG_OPEN,m_info,name_buff,(uint) strlen(name_buff)); 00620 } 00621 DBUG_RETURN(m_info); 00622 00623 err: 00624 save_errno=my_errno ? my_errno : HA_ERR_END_OF_FILE; 00625 if ((save_errno == HA_ERR_CRASHED) || 00626 (save_errno == HA_ERR_CRASHED_ON_USAGE) || 00627 (save_errno == HA_ERR_CRASHED_ON_REPAIR)) 00628 mi_report_error(save_errno, name); 00629 switch (errpos) { 00630 case 6: 00631 my_free((gptr) m_info,MYF(0)); 00632 /* fall through */ 00633 case 5: 00634 VOID(my_close(info.dfile,MYF(0))); 00635 if (old_info) 00636 break; /* Don't remove open table */ 00637 /* fall through */ 00638 case 4: 00639 my_free((gptr) share,MYF(0)); 00640 /* fall through */ 00641 case 3: 00642 if (! lock_error) 00643 VOID(my_lock(kfile, F_UNLCK, 0L, F_TO_EOF, MYF(MY_SEEK_NOT_DONE))); 00644 /* fall through */ 00645 case 2: 00646 my_afree((gptr) disk_cache); 00647 /* fall through */ 00648 case 1: 00649 VOID(my_close(kfile,MYF(0))); 00650 /* fall through */ 00651 case 0: 00652 default: 00653 break; 00654 } 00655 pthread_mutex_unlock(&THR_LOCK_myisam); 00656 my_errno=save_errno; 00657 DBUG_RETURN (NULL); 00658 } /* mi_open */
Here is the call graph for this function:

Here is the caller graph for this function:

| int mi_panic | ( | enum ha_panic_function | function | ) |
Definition at line 27 of file mi_panic.c.
References st_list::data, DBUG_ENTER, DBUG_RETURN, error, F_UNLCK, flush_io_cache, flush_key_blocks(), FLUSH_RELEASE, fn_format(), FN_REFLEN, ft_free_stopwords(), HA_OPTION_READ_ONLY_DATA, HA_PANIC_CLOSE, HA_PANIC_READ, HA_PANIC_WRITE, info, mi_close(), mi_lock_database(), mi_log(), my_close(), my_errno, my_open(), MY_WME, MYF, myisam_open_list, st_list::next, pthread_mutex_lock, pthread_mutex_unlock, READ_CACHE, READ_CACHE_USED, reinit_io_cache(), VOID, and WRITE_CACHE_USED.
Referenced by main(), myisam_init(), and myrg_panic().
00028 { 00029 int error=0; 00030 LIST *list_element,*next_open; 00031 MI_INFO *info; 00032 DBUG_ENTER("mi_panic"); 00033 00034 pthread_mutex_lock(&THR_LOCK_myisam); 00035 for (list_element=myisam_open_list ; list_element ; list_element=next_open) 00036 { 00037 next_open=list_element->next; /* Save if close */ 00038 info=(MI_INFO*) list_element->data; 00039 switch (flag) { 00040 case HA_PANIC_CLOSE: 00041 pthread_mutex_unlock(&THR_LOCK_myisam); /* Not exactly right... */ 00042 if (mi_close(info)) 00043 error=my_errno; 00044 pthread_mutex_lock(&THR_LOCK_myisam); 00045 break; 00046 case HA_PANIC_WRITE: /* Do this to free databases */ 00047 #ifdef CANT_OPEN_FILES_TWICE 00048 if (info->s->options & HA_OPTION_READ_ONLY_DATA) 00049 break; 00050 #endif 00051 if (flush_key_blocks(info->s->key_cache, info->s->kfile, FLUSH_RELEASE)) 00052 error=my_errno; 00053 if (info->opt_flag & WRITE_CACHE_USED) 00054 if (flush_io_cache(&info->rec_cache)) 00055 error=my_errno; 00056 if (info->opt_flag & READ_CACHE_USED) 00057 { 00058 if (flush_io_cache(&info->rec_cache)) 00059 error=my_errno; 00060 reinit_io_cache(&info->rec_cache,READ_CACHE,0, 00061 (pbool) (info->lock_type != F_UNLCK),1); 00062 } 00063 if (info->lock_type != F_UNLCK && ! info->was_locked) 00064 { 00065 info->was_locked=info->lock_type; 00066 if (mi_lock_database(info,F_UNLCK)) 00067 error=my_errno; 00068 } 00069 #ifdef CANT_OPEN_FILES_TWICE 00070 if (info->s->kfile >= 0 && my_close(info->s->kfile,MYF(0))) 00071 error = my_errno; 00072 if (info->dfile >= 0 && my_close(info->dfile,MYF(0))) 00073 error = my_errno; 00074 info->s->kfile=info->dfile= -1; /* Files aren't open anymore */ 00075 break; 00076 #endif 00077 case HA_PANIC_READ: /* Restore to before WRITE */ 00078 #ifdef CANT_OPEN_FILES_TWICE 00079 { /* Open closed files */ 00080 char name_buff[FN_REFLEN]; 00081 if (info->s->kfile < 0) 00082 if ((info->s->kfile= my_open(fn_format(name_buff,info->filename,"", 00083 N_NAME_IEXT,4),info->mode, 00084 MYF(MY_WME))) < 0) 00085 error = my_errno; 00086 if (info->dfile < 0) 00087 { 00088 if ((info->dfile= my_open(fn_format(name_buff,info->filename,"", 00089 N_NAME_DEXT,4),info->mode, 00090 MYF(MY_WME))) < 0) 00091 error = my_errno; 00092 info->rec_cache.file=info->dfile; 00093 } 00094 } 00095 #endif 00096 if (info->was_locked) 00097 { 00098 if (mi_lock_database(info, info->was_locked)) 00099 error=my_errno; 00100 info->was_locked=0; 00101 } 00102 break; 00103 } 00104 } 00105 if (flag == HA_PANIC_CLOSE) 00106 { 00107 VOID(mi_log(0)); /* Close log if neaded */ 00108 ft_free_stopwords(); 00109 } 00110 pthread_mutex_unlock(&THR_LOCK_myisam); 00111 if (!error) 00112 DBUG_RETURN(0); 00113 DBUG_RETURN(my_errno=error); 00114 } /* mi_panic */
Here is the call graph for this function:

Here is the caller graph for this function:

| my_off_t mi_position | ( | struct st_myisam_info * | file | ) |
Definition at line 26 of file mi_info.c.
References st_myisam_info::lastpos.
Referenced by main(), and ha_myisam::position().
00027 { 00028 return info->lastpos; 00029 }
Here is the caller graph for this function:

Definition at line 42 of file mi_preload.c.
References st_mi_isam_share::base, st_mi_keydef::block_length, DBUG_ENTER, DBUG_RETURN, DFLT_INIT_HITS, err, errno, flush_key_blocks(), FLUSH_RELEASE, HA_ERR_NON_UNIQUE_BLOCK_SIZE, HA_ERR_OUT_OF_MEM, st_mi_state_info::header, st_mi_isam_share::key_cache, key_cache_insert(), st_mi_status_info::key_file_length, keyinfo, st_mi_isam_share::keyinfo, keys, st_mi_state_info::keys, st_mi_base_info::keystart, st_mi_isam_share::kfile, mi_is_any_key_active, mi_test_if_nod, MY_ALLOW_ZERO_PTR, my_errno, MY_FAE, MY_FNABP, my_free, my_malloc(), my_pread(), MY_WME, MYF, NULL, pos(), st_myisam_info::preload_buff_size, st_myisam_info::s, set_if_bigger, st_mi_isam_share::state, and st_mi_state_info::state.
Referenced by ha_myisam::preload_keys().
00043 { 00044 uint i; 00045 ulong length, block_length= 0; 00046 uchar *buff= NULL; 00047 MYISAM_SHARE* share= info->s; 00048 uint keys= share->state.header.keys; 00049 MI_KEYDEF *keyinfo= share->keyinfo; 00050 my_off_t key_file_length= share->state.state.key_file_length; 00051 my_off_t pos= share->base.keystart; 00052 DBUG_ENTER("mi_preload"); 00053 00054 if (!keys || !mi_is_any_key_active(key_map) || key_file_length == pos) 00055 DBUG_RETURN(0); 00056 00057 block_length= keyinfo[0].block_length; 00058 00059 /* Check whether all indexes use the same block size */ 00060 for (i= 1 ; i < keys ; i++) 00061 { 00062 if (keyinfo[i].block_length != block_length) 00063 DBUG_RETURN(my_errno= HA_ERR_NON_UNIQUE_BLOCK_SIZE); 00064 } 00065 00066 length= info->preload_buff_size/block_length * block_length; 00067 set_if_bigger(length, block_length); 00068 00069 if (!(buff= (uchar *) my_malloc(length, MYF(MY_WME)))) 00070 DBUG_RETURN(my_errno= HA_ERR_OUT_OF_MEM); 00071 00072 if (flush_key_blocks(share->key_cache,share->kfile, FLUSH_RELEASE)) 00073 goto err; 00074 00075 do 00076 { 00077 /* Read the next block of index file into the preload buffer */ 00078 if ((my_off_t) length > (key_file_length-pos)) 00079 length= (ulong) (key_file_length-pos); 00080 if (my_pread(share->kfile, (byte*) buff, length, pos, MYF(MY_FAE|MY_FNABP))) 00081 goto err; 00082 00083 if (ignore_leaves) 00084 { 00085 uchar *end= buff+length; 00086 do 00087 { 00088 if (mi_test_if_nod(buff)) 00089 { 00090 if (key_cache_insert(share->key_cache, 00091 share->kfile, pos, DFLT_INIT_HITS, 00092 (byte*) buff, block_length)) 00093 goto err; 00094 } 00095 pos+= block_length; 00096 } 00097 while ((buff+= block_length) != end); 00098 buff= end-length; 00099 } 00100 else 00101 { 00102 if (key_cache_insert(share->key_cache, 00103 share->kfile, pos, DFLT_INIT_HITS, 00104 (byte*) buff, length)) 00105 goto err; 00106 pos+= length; 00107 } 00108 } 00109 while (pos != key_file_length); 00110 00111 my_free((char*) buff, MYF(0)); 00112 DBUG_RETURN(0); 00113 00114 err: 00115 my_free((char*) buff, MYF(MY_ALLOW_ZERO_PTR)); 00116 DBUG_RETURN(my_errno= errno); 00117 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ha_rows mi_records_in_range | ( | struct st_myisam_info * | info, | |
| int | inx, | |||
| key_range * | min_key, | |||
| key_range * | max_key | |||
| ) |
Definition at line 52 of file mi_range.c.
References _mi_check_index(), _mi_pack_key(), _mi_record_pos(), st_mi_isam_share::base, st_mi_isam_share::concurrent_insert, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, fast_mi_readinfo, fast_mi_writeinfo, st_key_range::flag, HA_KEY_ALG_BTREE, HA_KEY_ALG_RTREE, HA_POS_ERROR, HA_STATE_CHANGED, HA_STATE_ROW_CHANGED, st_key_range::key, st_mi_keydef::key_alg, st_mi_isam_share::keyinfo, st_myisam_info::lastkey, st_key_range::length, st_mi_base_info::max_key_length, myisam_read_vec, st_mi_status_info::records, rw_rdlock, rw_unlock, st_myisam_info::s, st_myisam_info::state, and st_myisam_info::update.
Referenced by main(), myrg_records_in_range(), and ha_myisam::records_in_range().
00054 { 00055 ha_rows start_pos,end_pos,res; 00056 DBUG_ENTER("mi_records_in_range"); 00057 00058 if ((inx = _mi_check_index(info,inx)) < 0) 00059 DBUG_RETURN(HA_POS_ERROR); 00060 00061 if (fast_mi_readinfo(info)) 00062 DBUG_RETURN(HA_POS_ERROR); 00063 info->update&= (HA_STATE_CHANGED+HA_STATE_ROW_CHANGED); 00064 if (info->s->concurrent_insert) 00065 rw_rdlock(&info->s->key_root_lock[inx]); 00066 00067 switch(info->s->keyinfo[inx].key_alg){ 00068 #ifdef HAVE_RTREE_KEYS 00069 case HA_KEY_ALG_RTREE: 00070 { 00071 uchar * key_buff; 00072 uint start_key_len; 00073 00074 key_buff= info->lastkey+info->s->base.max_key_length; 00075 start_key_len= _mi_pack_key(info,inx, key_buff, 00076 (uchar*) min_key->key, min_key->length, 00077 (HA_KEYSEG**) 0); 00078 res= rtree_estimate(info, inx, key_buff, start_key_len, 00079 myisam_read_vec[min_key->flag]); 00080 res= res ? res : 1; /* Don't return 0 */ 00081 break; 00082 } 00083 #endif 00084 case HA_KEY_ALG_BTREE: 00085 default: 00086 start_pos= (min_key ? 00087 _mi_record_pos(info, min_key->key, min_key->length, 00088 min_key->flag) : 00089 (ha_rows) 0); 00090 end_pos= (max_key ? 00091 _mi_record_pos(info, max_key->key, max_key->length, 00092 max_key->flag) : 00093 info->state->records+ (ha_rows) 1); 00094 res= (end_pos < start_pos ? (ha_rows) 0 : 00095 (end_pos == start_pos ? (ha_rows) 1 : end_pos-start_pos)); 00096 if (start_pos == HA_POS_ERROR || end_pos == HA_POS_ERROR) 00097 res=HA_POS_ERROR; 00098 } 00099 00100 if (info->s->concurrent_insert) 00101 rw_unlock(&info->s->key_root_lock[inx]); 00102 fast_mi_writeinfo(info); 00103 00104 DBUG_PRINT("info",("records: %ld",(ulong) (res))); 00105 DBUG_RETURN(res); 00106 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int mi_rename | ( | const char * | from, | |
| const char * | to | |||
| ) |
Definition at line 23 of file mi_rename.c.
References st_mi_isam_share::base, check_table_is_closed(), DBUG_ENTER, DBUG_RETURN, fn_format(), FN_REFLEN, from, info, mi_close(), MI_NAME_DEXT, MI_NAME_IEXT, mi_open(), MY_APPEND_EXT, my_errno, my_rename_with_symlink(), MY_UNPACK_FILENAME, MY_WME, MYF, st_mi_base_info::raid_chunks, st_mi_base_info::raid_type, st_myisam_info::s, and to.
Referenced by ha_myisam::rename_table().
00024 { 00025 char from[FN_REFLEN],to[FN_REFLEN]; 00026 #ifdef USE_RAID 00027 uint raid_type=0,raid_chunks=0; 00028 #endif 00029 DBUG_ENTER("mi_rename"); 00030 00031 #ifdef EXTRA_DEBUG 00032 check_table_is_closed(old_name,"rename old_table"); 00033 check_table_is_closed(new_name,"rename new table2"); 00034 #endif 00035 #ifdef USE_RAID 00036 { 00037 MI_INFO *info; 00038 if (!(info=mi_open(old_name, O_RDONLY, 0))) 00039 DBUG_RETURN(my_errno); 00040 raid_type = info->s->base.raid_type; 00041 raid_chunks = info->s->base.raid_chunks; 00042 mi_close(info); 00043 } 00044 #ifdef EXTRA_DEBUG 00045 check_table_is_closed(old_name,"rename raidcheck"); 00046 #endif 00047 #endif /* USE_RAID */ 00048 00049 fn_format(from,old_name,"",MI_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT); 00050 fn_format(to,new_name,"",MI_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT); 00051 if (my_rename_with_symlink(from, to, MYF(MY_WME))) 00052 DBUG_RETURN(my_errno); 00053 fn_format(from,old_name,"",MI_NAME_DEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT); 00054 fn_format(to,new_name,"",MI_NAME_DEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT); 00055 #ifdef USE_RAID 00056 if (raid_type) 00057 DBUG_RETURN(my_raid_rename(from, to, raid_chunks, MYF(MY_WME)) ? my_errno : 00058 0); 00059 #endif 00060 DBUG_RETURN(my_rename_with_symlink(from, to,MYF(MY_WME)) ? my_errno : 0); 00061 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1299 of file mi_check.c.
References _mi_make_key(), _mi_print_key(), st_mi_isam_share::base, bzero, st_mi_check_param::calc_checksum, st_mi_isam_share::data_file_name, DATA_TMP_EXT, DBUG_DUMP, DBUG_ENTER, del(), dflt_key_cache, st_io_cache::end_of_file, err, error, filecopy(), fn_format(), st_mi_check_param::glob_crc, HA_ERR_FOUND_DUPP_KEY, HA_OFFSET_ERROR, HA_OPTION_CHECKSUM, HA_OPTION_COMPRESS_RECORD, HA_STATE_CHANGED, HA_STATE_ROW_CHANGED, st_mi_state_info::header, st_mi_isam_pack::header_length, init_io_cache(), init_key_cache(), st_mi_check_param::key_cache_block_size, st_mi_state_info::key_del, st_mi_state_info::key_map, st_mi_state_info::key_root, st_mi_isam_share::keyinfo, st_mi_base_info::keys, st_mi_base_info::keystart, llstr(), lock_memory(), st_mi_state_info::max_block_size_index, mi_alloc_rec_buff(), mi_check_print_error(), mi_check_print_info(), mi_int2store, mi_set_all_keys_active, my_errno, my_malloc(), my_raid_create, my_seek(), MY_SEEK_END, MY_WAIT_IF_FULL, MY_WME, MYF, st_mi_isam_share::options, st_mi_state_info::options, st_mi_isam_share::pack, st_mi_base_info::pack_reclength, st_mi_base_info::raid_chunks, st_mi_base_info::raid_chunksize, st_mi_base_info::raid_type, st_mi_check_param::read_buffer_length, st_mi_check_param::read_cache, READ_CACHE, st_mi_keydef::seg, set_data_file_type(), sort_get_next_record(), sort_write_record(), st_mi_state_info::split, st_mi_isam_share::state, T_CALC_CHECKSUM, T_CREATE_MISSING_KEYS, T_FORCE_UNIQUENESS, T_QUICK, T_REP, T_RETRY_WITHOUT_QUICK, T_SILENT, T_UNPACK, T_VERBOSE, st_mi_check_param::temp_filename, st_mi_check_param::testflag, st_mi_check_param::tmpfile_createflag, st_mi_check_param::use_buffers, USE_WHOLE_KEY, st_mi_check_param::using_global_keycache, VOID, st_mi_check_param::write_buffer_length, WRITE_CACHE, WRITE_CACHE_USED, and writekeys().
Referenced by myisamchk(), and ha_myisam::repair().
01301 { 01302 int error,got_error; 01303 uint i; 01304 ha_rows start_records,new_header_length; 01305 my_off_t del; 01306 File new_file; 01307 MYISAM_SHARE *share=info->s; 01308 char llbuff[22],llbuff2[22]; 01309 SORT_INFO sort_info; 01310 MI_SORT_PARAM sort_param; 01311 DBUG_ENTER("mi_repair"); 01312 01313 bzero((char *)&sort_info, sizeof(sort_info)); 01314 bzero((char *)&sort_param, sizeof(sort_param)); 01315 start_records=info->state->records; 01316 new_header_length=(param->testflag & T_UNPACK) ? 0L : 01317 share->pack.header_length; 01318 got_error=1; 01319 new_file= -1; 01320 sort_param.sort_info=&sort_info; 01321 01322 if (!(param->testflag & T_SILENT)) 01323 { 01324 printf("- recovering (with keycache) MyISAM-table '%s'\n",name); 01325 printf("Data records: %s\n", llstr(info->state->records,llbuff)); 01326 } 01327 param->testflag|=T_REP; /* for easy checking */ 01328 01329 if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)) 01330 param->testflag|=T_CALC_CHECKSUM; 01331 01332 if (!param->using_global_keycache) 01333 VOID(init_key_cache(dflt_key_cache, param->key_cache_block_size, 01334 param->use_buffers, 0, 0)); 01335 01336 if (init_io_cache(¶m->read_cache,info->dfile, 01337 (uint) param->read_buffer_length, 01338 READ_CACHE,share->pack.header_length,1,MYF(MY_WME))) 01339 { 01340 bzero(&info->rec_cache,sizeof(info->rec_cache)); 01341 goto err; 01342 } 01343 if (!rep_quick) 01344 if (init_io_cache(&info->rec_cache,-1,(uint) param->write_buffer_length, 01345 WRITE_CACHE, new_header_length, 1, 01346 MYF(MY_WME | MY_WAIT_IF_FULL))) 01347 goto err; 01348 info->opt_flag|=WRITE_CACHE_USED; 01349 if (!(sort_param.record=(byte*) my_malloc((uint) share->base.pack_reclength, 01350 MYF(0))) || 01351 !mi_alloc_rec_buff(info, -1, &sort_param.rec_buff)) 01352 { 01353 mi_check_print_error(param, "Not enough memory for extra record"); 01354 goto err; 01355 } 01356 01357 if (!rep_quick) 01358 { 01359 /* Get real path for data file */ 01360 if ((new_file=my_raid_create(fn_format(param->temp_filename, 01361 share->data_file_name, "", 01362 DATA_TMP_EXT, 2+4), 01363 0,param->tmpfile_createflag, 01364 share->base.raid_type, 01365 share->base.raid_chunks, 01366 share->base.raid_chunksize, 01367 MYF(0))) < 0) 01368 { 01369 mi_check_print_error(param,"Can't create new tempfile: '%s'", 01370 param->temp_filename); 01371 goto err; 01372 } 01373 if (filecopy(param,new_file,info->dfile,0L,new_header_length, 01374 "datafile-header")) 01375 goto err; 01376 info->s->state.dellink= HA_OFFSET_ERROR; 01377 info->rec_cache.file=new_file; 01378 if (param->testflag & T_UNPACK) 01379 { 01380 share->options&= ~HA_OPTION_COMPRESS_RECORD; 01381 mi_int2store(share->state.header.options,share->options); 01382 } 01383 } 01384 sort_info.info=info; 01385 sort_info.param = param; 01386 sort_param.read_cache=param->read_cache; 01387 sort_param.pos=sort_param.max_pos=share->pack.header_length; 01388 sort_param.filepos=new_header_length; 01389 param->read_cache.end_of_file=sort_info.filelength= 01390 my_seek(info->dfile,0L,MY_SEEK_END,MYF(0)); 01391 sort_info.dupp=0; 01392 sort_param.fix_datafile= (my_bool) (! rep_quick); 01393 sort_param.master=1; 01394 sort_info.max_records= ~(ha_rows) 0; 01395 01396 set_data_file_type(&sort_info, share); 01397 del=info->state->del; 01398 info->state->records=info->state->del=share->state.split=0; 01399 info->state->empty=0; 01400 param->glob_crc=0; 01401 if (param->testflag & T_CALC_CHECKSUM) 01402 param->calc_checksum=1; 01403 01404 info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); 01405 01406 /* 01407 Clear all keys. Note that all key blocks allocated until now remain 01408 "dead" parts of the key file. (Bug #4692) 01409 */ 01410 for (i=0 ; i < info->s->base.keys ; i++) 01411 share->state.key_root[i]= HA_OFFSET_ERROR; 01412 01413 /* Drop the delete chain. */ 01414 for (i=0 ; i < share->state.header.max_block_size_index ; i++) 01415 share->state.key_del[i]= HA_OFFSET_ERROR; 01416 01417 /* 01418 If requested, activate (enable) all keys in key_map. In this case, 01419 all indexes will be (re-)built. 01420 */ 01421 if (param->testflag & T_CREATE_MISSING_KEYS) 01422 mi_set_all_keys_active(share->state.key_map, share->base.keys); 01423 01424 info->state->key_file_length=share->base.keystart; 01425 01426 lock_memory(param); /* Everything is alloced */ 01427 01428 /* Re-create all keys, which are set in key_map. */ 01429 while (!(error=sort_get_next_record(&sort_param))) 01430 { 01431 if (writekeys(param,info,(byte*)sort_param.record,sort_param.filepos)) 01432 { 01433 if (my_errno != HA_ERR_FOUND_DUPP_KEY) 01434 goto err; 01435 DBUG_DUMP("record",(byte*) sort_param.record,share->base.pack_reclength); 01436 mi_check_print_info(param,"Duplicate key %2d for record at %10s against new record at %10s", 01437 info->errkey+1, 01438 llstr(sort_param.start_recpos,llbuff), 01439 llstr(info->dupp_key_pos,llbuff2)); 01440 if (param->testflag & T_VERBOSE) 01441 { 01442 VOID(_mi_make_key(info,(uint) info->errkey,info->lastkey, 01443 sort_param.record,0L)); 01444 _mi_print_key(stdout,share->keyinfo[info->errkey].seg,info->lastkey, 01445 USE_WHOLE_KEY); 01446 } 01447 sort_info.dupp++; 01448 if ((param->testflag & (T_FORCE_UNIQUENESS|T_QUICK)) == T_QUICK) 01449 { 01450 param->testflag|=T_RETRY_WITHOUT_QUICK; 01451 param->error_printed=1; 01452 goto err; 01453 } 01454 continue; 01455 } 01456 if (sort_write_record(&sort_param)) 01457 goto err; 01458 } 01459 if (error > 0 || write_data_suffix(&sort_info, (my_bool)!rep_quick) || 01460 flush_io_cache(&info->rec_cache) || param->read_cache.error < 0) 01461 goto err; 01462 01463 if (param->testflag & T_WRITE_LOOP) 01464 { 01465 VOID(fputs(" \r",stdout)); VOID(fflush(stdout)); 01466 } 01467 if (my_chsize(share->kfile,info->state->key_file_length,0,MYF(0))) 01468 { 01469 mi_check_print_warning(param, 01470 "Can't change size of indexfile, error: %d", 01471 my_errno); 01472 goto err; 01473 } 01474 01475 if (rep_quick && del+sort_info.dupp != info->state->del) 01476 { 01477 mi_check_print_error(param,"Couldn't fix table with quick recovery: Found wrong number of deleted records"); 01478 mi_check_print_error(param,"Run recovery again without -q"); 01479 got_error=1; 01480 param->retry_repair=1; 01481 param->testflag|=T_RETRY_WITHOUT_QUICK; 01482 goto err; 01483 } 01484 if (param->testflag & T_SAFE_REPAIR) 01485 { 01486 /* Don't repair if we loosed more than one row */ 01487 if (info->state->records+1 < start_records) 01488 { 01489 info->state->records=start_records; 01490 got_error=1; 01491 goto err; 01492 } 01493 } 01494 01495 if (!rep_quick) 01496 { 01497 my_close(info->dfile,MYF(0)); 01498 info->dfile=new_file; 01499 info->state->data_file_length=sort_param.filepos; 01500 share->state.version=(ulong) time((time_t*) 0); /* Force reopen */ 01501 } 01502 else 01503 { 01504 info->state->data_file_length=sort_param.max_pos; 01505 } 01506 if (param->testflag & T_CALC_CHECKSUM) 01507 info->state->checksum=param->glob_crc; 01508 01509 if (!(param->testflag & T_SILENT)) 01510 { 01511 if (start_records != info->state->records) 01512 printf("Data records: %s\n", llstr(info->state->records,llbuff)); 01513 if (sort_info.dupp) 01514 mi_check_print_warning(param, 01515 "%s records have been removed", 01516 llstr(sort_info.dupp,llbuff)); 01517 } 01518 01519 got_error=0; 01520 /* If invoked by external program that uses thr_lock */ 01521 if (&share->state.state != info->state) 01522 memcpy( &share->state.state, info->state, sizeof(*info->state)); 01523 01524 err: 01525 if (!got_error) 01526 { 01527 /* Replace the actual file with the temporary file */ 01528 if (new_file >= 0) 01529 { 01530 my_close(new_file,MYF(0)); 01531 info->dfile=new_file= -1; 01532 if (change_to_newfile(share->data_file_name,MI_NAME_DEXT, 01533 DATA_TMP_EXT, share->base.raid_chunks, 01534 (param->testflag & T_BACKUP_DATA ? 01535 MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) || 01536 mi_open_datafile(info,share,-1)) 01537 got_error=1; 01538 } 01539 } 01540 if (got_error) 01541 { 01542 if (! param->error_printed) 01543 mi_check_print_error(param,"%d for record at pos %s",my_errno, 01544 llstr(sort_param.start_recpos,llbuff)); 01545 if (new_file >= 0) 01546 { 01547 VOID(my_close(new_file,MYF(0))); 01548 VOID(my_raid_delete(param->temp_filename,info->s->base.raid_chunks, 01549 MYF(MY_WME))); 01550 info->rec_cache.file=-1; /* don't flush data to new_file, it's closed */ 01551 } 01552 mi_mark_crashed_on_repair(info); 01553 } 01554 my_free(mi_get_rec_buff_ptr(info, sort_param.rec_buff), 01555 MYF(MY_ALLOW_ZERO_PTR)); 01556 my_free(sort_param.record,MYF(MY_ALLOW_ZERO_PTR)); 01557 my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR)); 01558 VOID(end_io_cache(¶m->read_cache)); 01559 info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); 01560 VOID(end_io_cache(&info->rec_cache)); 01561 got_error|=flush_blocks(param, share->key_cache, share->kfile); 01562 if (!got_error && param->testflag & T_UNPACK) 01563 { 01564 share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD; 01565 share->pack.header_length=0; 01566 share->data_file_type=sort_info.new_data_file_type; 01567 } 01568 share->state.changed|= (STATE_NOT_OPTIMIZED_KEYS | STATE_NOT_SORTED_PAGES | 01569 STATE_NOT_ANALYZED); 01570 DBUG_RETURN(got_error); 01571 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int mi_repair_by_sort | ( | MI_CHECK * | param, | |
| register MI_INFO * | info, | |||
| const char * | name, | |||
| int | rep_quick | |||
| ) |
Definition at line 2000 of file mi_check.c.
References alloc_key_blocks(), st_mi_isam_share::base, bzero, st_mi_check_param::calc_checksum, COMPRESSED_RECORD, st_mi_isam_share::data_file_name, st_mi_isam_share::data_file_type, DATA_TMP_EXT, DBUG_ENTER, del(), st_mi_state_info::dellink, DYNAMIC_RECORD, st_io_cache::end_of_file, err, st_io_cache::file, filecopy(), FLUSH_FORCE_WRITE, FLUSH_IGNORE_CHANGED, flush_key_blocks(), fn_format(), FT_MAX_WORD_LEN_FOR_SORT, ft_min_word_len, FTPARSER_MEMROOT_ALLOC_SIZE, get_pack_length, st_mi_check_param::glob_crc, HA_BLOB_PART, HA_FT_MAXBYTELEN, HA_KEYTYPE_END, HA_NULL_PART, HA_OFFSET_ERROR, HA_OPTION_CHECKSUM, HA_OPTION_COMPRESS_RECORD, HA_SPACE_PACK, HA_STATE_CHANGED, HA_STATE_ROW_CHANGED, HA_VAR_LENGTH_PART, st_mi_state_info::header, st_mi_isam_pack::header_length, init_alloc_root(), init_io_cache(), st_mi_isam_share::key_cache, st_mi_state_info::key_del, st_mi_state_info::key_map, st_mi_state_info::key_root, st_mi_isam_share::keyinfo, st_mi_base_info::keys, keyseg, st_mi_base_info::keystart, st_mi_isam_share::kfile, st_HA_KEYSEG::length, llstr(), lock_memory(), max, st_mi_state_info::max_block_size_index, st_mi_base_info::max_key_block_length, memcpy, mi_alloc_rec_buff(), mi_check_print_error(), mi_int2store, mi_is_key_active, st_mi_base_info::min_block_length, st_mi_base_info::min_pack_length, my_malloc(), my_raid_create, my_seek(), MY_SEEK_END, MY_WAIT_IF_FULL, MY_WME, MYF, st_mi_check_param::myf_rw, NULL, st_mi_isam_share::options, st_mi_state_info::options, st_mi_isam_share::pack, st_mi_base_info::pack_reclength, st_mi_base_info::raid_chunks, st_mi_base_info::raid_chunksize, st_mi_base_info::raid_type, st_mi_check_param::read_buffer_length, st_mi_check_param::read_cache, READ_CACHE, st_mi_check_param::rec_per_key_part, st_mi_state_info::rec_per_key_part, st_mi_isam_share::rec_reflength, st_mi_keydef::seg, set_data_file_type(), st_mi_check_param::sort_buffer_length, sort_ft_key_read(), sort_ft_key_write(), st_mi_check_param::sort_key_blocks, sort_key_cmp(), st_mi_state_info::split, st_mi_isam_share::state, T_CALC_CHECKSUM, T_CREATE_MISSING_KEYS, T_REP, T_SILENT, T_UNPACK, st_mi_check_param::temp_filename, test, st_mi_check_param::testflag, st_mi_check_param::tmpdir, st_mi_check_param::tmpfile_createflag, st_HA_KEYSEG::type, st_mi_check_param::write_buffer_length, WRITE_CACHE, and WRITE_CACHE_USED.
Referenced by mi_repair_parallel(), myisamchk(), and ha_myisam::repair().
02002 { 02003 int got_error; 02004 uint i; 02005 ulong length; 02006 ha_rows start_records; 02007 my_off_t new_header_length,del; 02008 File new_file; 02009 MI_SORT_PARAM sort_param; 02010 MYISAM_SHARE *share=info->s; 02011 HA_KEYSEG *keyseg; 02012 ulong *rec_per_key_part; 02013 char llbuff[22]; 02014 SORT_INFO sort_info; 02015 ulonglong key_map=share->state.key_map; 02016 DBUG_ENTER("mi_repair_by_sort"); 02017 02018 start_records=info->state->records; 02019 got_error=1; 02020 new_file= -1; 02021 new_header_length=(param->testflag & T_UNPACK) ? 0 : 02022 share->pack.header_length; 02023 if (!(param->testflag & T_SILENT)) 02024 { 02025 printf("- recovering (with sort) MyISAM-table '%s'\n",name); 02026 printf("Data records: %s\n", llstr(start_records,llbuff)); 02027 } 02028 param->testflag|=T_REP; /* for easy checking */ 02029 02030 if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)) 02031 param->testflag|=T_CALC_CHECKSUM; 02032 02033 bzero((char*)&sort_info,sizeof(sort_info)); 02034 bzero((char *)&sort_param, sizeof(sort_param)); 02035 if (!(sort_info.key_block= 02036 alloc_key_blocks(param, 02037 (uint) param->sort_key_blocks, 02038 share->base.max_key_block_length)) 02039 || init_io_cache(¶m->read_cache,info->dfile, 02040 (uint) param->read_buffer_length, 02041 READ_CACHE,share->pack.header_length,1,MYF(MY_WME)) || 02042 (! rep_quick && 02043 init_io_cache(&info->rec_cache,info->dfile, 02044 (uint) param->write_buffer_length, 02045 WRITE_CACHE,new_header_length,1, 02046 MYF(MY_WME | MY_WAIT_IF_FULL) & param->myf_rw))) 02047 goto err; 02048 sort_info.key_block_end=sort_info.key_block+param->sort_key_blocks; 02049 info->opt_flag|=WRITE_CACHE_USED; 02050 info->rec_cache.file=info->dfile; /* for sort_delete_record */ 02051 02052 if (!(sort_param.record=(byte*) my_malloc((uint) share->base.pack_reclength, 02053 MYF(0))) || 02054 !mi_alloc_rec_buff(info, -1, &sort_param.rec_buff)) 02055 { 02056 mi_check_print_error(param, "Not enough memory for extra record"); 02057 goto err; 02058 } 02059 if (!rep_quick) 02060 { 02061 /* Get real path for data file */ 02062 if ((new_file=my_raid_create(fn_format(param->temp_filename, 02063 share->data_file_name, "", 02064 DATA_TMP_EXT, 2+4), 02065 0,param->tmpfile_createflag, 02066 share->base.raid_type, 02067 share->base.raid_chunks, 02068 share->base.raid_chunksize, 02069 MYF(0))) < 0) 02070 { 02071 mi_check_print_error(param,"Can't create new tempfile: '%s'", 02072 param->temp_filename); 02073 goto err; 02074 } 02075 if (filecopy(param, new_file,info->dfile,0L,new_header_length, 02076 "datafile-header")) 02077 goto err; 02078 if (param->testflag & T_UNPACK) 02079 { 02080 share->options&= ~HA_OPTION_COMPRESS_RECORD; 02081 mi_int2store(share->state.header.options,share->options); 02082 } 02083 share->state.dellink= HA_OFFSET_ERROR; 02084 info->rec_cache.file=new_file; 02085 } 02086 02087 info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); 02088 if (!(param->testflag & T_CREATE_MISSING_KEYS)) 02089 { 02090 /* 02091 Flush key cache for this file if we are calling this outside 02092 myisamchk 02093 */ 02094 flush_key_blocks(share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED); 02095 /* Clear the pointers to the given rows */ 02096 for (i=0 ; i < share->base.keys ; i++) 02097 share->state.key_root[i]= HA_OFFSET_ERROR; 02098 for (i=0 ; i < share->state.header.max_block_size_index ; i++) 02099 share->state.key_del[i]= HA_OFFSET_ERROR; 02100 info->state->key_file_length=share->base.keystart; 02101 } 02102 else 02103 { 02104 if (flush_key_blocks(share->key_cache,share->kfile, FLUSH_FORCE_WRITE)) 02105 goto err; 02106 key_map= ~key_map; /* Create the missing keys */ 02107 } 02108 02109 sort_info.info=info; 02110 sort_info.param = param; 02111 02112 set_data_file_type(&sort_info, share); 02113 sort_param.filepos=new_header_length; 02114 sort_info.dupp=0; 02115 sort_info.buff=0; 02116 param->read_cache.end_of_file=sort_info.filelength= 02117 my_seek(param->read_cache.file,0L,MY_SEEK_END,MYF(0)); 02118 02119 sort_param.wordlist=NULL; 02120 init_alloc_root(&sort_param.wordroot, FTPARSER_MEMROOT_ALLOC_SIZE, 0); 02121 02122 if (share->data_file_type == DYNAMIC_RECORD) 02123 length=max(share->base.min_pack_length+1,share->base.min_block_length); 02124 else if (share->data_file_type == COMPRESSED_RECORD) 02125 length=share->base.min_block_length; 02126 else 02127 length=share->base.pack_reclength; 02128 sort_info.max_records= 02129 ((param->testflag & T_CREATE_MISSING_KEYS) ? info->state->records : 02130 (ha_rows) (sort_info.filelength/length+1)); 02131 sort_param.key_cmp=sort_key_cmp; 02132 sort_param.lock_in_memory=lock_memory; 02133 sort_param.tmpdir=param->tmpdir; 02134 sort_param.sort_info=&sort_info; 02135 sort_param.fix_datafile= (my_bool) (! rep_quick); 02136 sort_param.master =1; 02137 02138 del=info->state->del; 02139 param->glob_crc=0; 02140 if (param->testflag & T_CALC_CHECKSUM) 02141 param->calc_checksum=1; 02142 02143 rec_per_key_part= param->rec_per_key_part; 02144 for (sort_param.key=0 ; sort_param.key < share->base.keys ; 02145 rec_per_key_part+=sort_param.keyinfo->keysegs, sort_param.key++) 02146 { 02147 sort_param.read_cache=param->read_cache; 02148 sort_param.keyinfo=share->keyinfo+sort_param.key; 02149 sort_param.seg=sort_param.keyinfo->seg; 02150 if (! mi_is_key_active(key_map, sort_param.key)) 02151 { 02152 /* Remember old statistics for key */ 02153 memcpy((char*) rec_per_key_part, 02154 (char*) (share->state.rec_per_key_part + 02155 (uint) (rec_per_key_part - param->rec_per_key_part)), 02156 sort_param.keyinfo->keysegs*sizeof(*rec_per_key_part)); 02157 continue; 02158 } 02159 02160 if ((!(param->testflag & T_SILENT))) 02161 printf ("- Fixing index %d\n",sort_param.key+1); 02162 sort_param.max_pos=sort_param.pos=share->pack.header_length; 02163 keyseg=sort_param.seg; 02164 bzero((char*) sort_param.unique,sizeof(sort_param.unique)); 02165 sort_param.key_length=share->rec_reflength; 02166 for (i=0 ; keyseg[i].type != HA_KEYTYPE_END; i++) 02167 { 02168 sort_param.key_length+=keyseg[i].length; 02169 if (keyseg[i].flag & HA_SPACE_PACK) 02170 sort_param.key_length+=get_pack_length(keyseg[i].length); 02171 if (keyseg[i].flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART)) 02172 sort_param.key_length+=2 + test(keyseg[i].length >= 127); 02173 if (keyseg[i].flag & HA_NULL_PART) 02174 sort_param.key_length++; 02175 } 02176 info->state->records=info->state->del=share->state.split=0; 02177 info->state->empty=0; 02178 02179 if (sort_param.keyinfo->flag & HA_FULLTEXT) 02180 { 02181 uint ft_max_word_len_for_sort=FT_MAX_WORD_LEN_FOR_SORT* 02182 sort_param.keyinfo->seg->charset->mbmaxlen; 02183 sort_param.key_length+=ft_max_word_len_for_sort-HA_FT_MAXBYTELEN; 02184 /* 02185 fulltext indexes may have much more entries than the 02186 number of rows in the table. We estimate the number here. 02187 02188 Note, built-in parser is always nr. 0 - see ftparser_call_initializer() 02189 */ 02190 if (sort_param.keyinfo->ftparser_nr == 0) 02191 { 02192 /* 02193 for built-in parser the number of generated index entries 02194 cannot be larger than the size of the data file divided 02195 by the minimal word's length 02196 */ 02197 sort_info.max_records= 02198 (ha_rows) (sort_info.filelength/ft_min_word_len+1); 02199 } 02200 else 02201 { 02202 /* 02203 for external plugin parser we cannot tell anything at all :( 02204 so, we'll use all the sort memory and start from ~10 buffpeks. 02205 (see _create_index_by_sort) 02206 */ 02207 sort_info.max_records= 02208 10*param->sort_buffer_length/sort_param.key_length; 02209 } 02210 02211 sort_param.key_read=sort_ft_key_read; 02212 sort_param.key_write=sort_ft_key_write; 02213 } 02214 else 02215 { 02216 sort_param.key_read=sort_key_read; 02217 sort_param.key_write=sort_key_write; 02218 } 02219 02220 if (_create_index_by_sort(&sort_param, 02221 (my_bool) (!(param->testflag & T_VERBOSE)), 02222 (uint) param->sort_buffer_length)) 02223 { 02224 param->retry_repair=1; 02225 goto err; 02226 } 02227 param->calc_checksum=0; /* No need to calc glob_crc */ 02228 free_root(&sort_param.wordroot, MYF(0)); 02229 02230 /* Set for next loop */ 02231 sort_info.max_records= (ha_rows) info->state->records; 02232 02233 if (param->testflag & T_STATISTICS) 02234 update_key_parts(sort_param.keyinfo, rec_per_key_part, sort_param.unique, 02235 param->stats_method == MI_STATS_METHOD_IGNORE_NULLS? 02236 sort_param.notnull: NULL,(ulonglong) info->state->records); 02237 mi_set_key_active(share->state.key_map, sort_param.key); 02238 02239 if (sort_param.fix_datafile) 02240 { 02241 param->read_cache.end_of_file=sort_param.filepos; 02242 if (write_data_suffix(&sort_info,1) || end_io_cache(&info->rec_cache)) 02243 goto err; 02244 if (param->testflag & T_SAFE_REPAIR) 02245 { 02246 /* Don't repair if we loosed more than one row */ 02247 if (info->state->records+1 < start_records) 02248 { 02249 info->state->records=start_records; 02250 goto err; 02251 } 02252 } 02253 share->state.state.data_file_length = info->state->data_file_length= 02254 sort_param.filepos; 02255 /* Only whole records */ 02256 share->state.version=(ulong) time((time_t*) 0); 02257 my_close(info->dfile,MYF(0)); 02258 info->dfile=new_file; 02259 share->data_file_type=sort_info.new_data_file_type; 02260 share->pack.header_length=(ulong) new_header_length; 02261 sort_param.fix_datafile=0; 02262 } 02263 else 02264 info->state->data_file_length=sort_param.max_pos; 02265 02266 param->read_cache.file=info->dfile; /* re-init read cache */ 02267 reinit_io_cache(¶m->read_cache,READ_CACHE,share->pack.header_length, 02268 1,1); 02269 } 02270 02271 if (param->testflag & T_WRITE_LOOP) 02272 { 02273 VOID(fputs(" \r",stdout)); VOID(fflush(stdout)); 02274 } 02275 02276 if (rep_quick && del+sort_info.dupp != info->state->del) 02277 { 02278 mi_check_print_error(param,"Couldn't fix table with quick recovery: Found wrong number of deleted records"); 02279 mi_check_print_error(param,"Run recovery again without -q"); 02280 got_error=1; 02281 param->retry_repair=1; 02282 param->testflag|=T_RETRY_WITHOUT_QUICK; 02283 goto err; 02284 } 02285 02286 if (rep_quick & T_FORCE_UNIQUENESS) 02287 { 02288 my_off_t skr=info->state->data_file_length+ 02289 (share->options & HA_OPTION_COMPRESS_RECORD ? 02290 MEMMAP_EXTRA_MARGIN : 0); 02291 #ifdef USE_RELOC 02292 if (share->data_file_type == STATIC_RECORD && 02293 skr < share->base.reloc*share->base.min_pack_length) 02294 skr=share->base.reloc*share->base.min_pack_length; 02295 #endif 02296 if (skr != sort_info.filelength && !info->s->base.raid_type) 02297 if (my_chsize(info->dfile,skr,0,MYF(0))) 02298 mi_check_print_warning(param, 02299 "Can't change size of datafile, error: %d", 02300 my_errno); 02301 } 02302 if (param->testflag & T_CALC_CHECKSUM) 02303 info->state->checksum=param->glob_crc; 02304 02305 if (my_chsize(share->kfile,info->state->key_file_length,0,MYF(0))) 02306 mi_check_print_warning(param, 02307 "Can't change size of indexfile, error: %d", 02308 my_errno); 02309 02310 if (!(param->testflag & T_SILENT)) 02311 { 02312 if (start_records != info->state->records) 02313 printf("Data records: %s\n", llstr(info->state->records,llbuff)); 02314 if (sort_info.dupp) 02315 mi_check_print_warning(param, 02316 "%s records have been removed", 02317 llstr(sort_info.dupp,llbuff)); 02318 } 02319 got_error=0; 02320 02321 if (&share->state.state != info->state) 02322 memcpy( &share->state.state, info->state, sizeof(*info->state)); 02323 02324 err: 02325 got_error|= flush_blocks(param, share->key_cache, share->kfile); 02326 VOID(end_io_cache(&info->rec_cache)); 02327 if (!got_error) 02328 { 02329 /* Replace the actual file with the temporary file */ 02330 if (new_file >= 0) 02331 { 02332 my_close(new_file,MYF(0)); 02333 info->dfile=new_file= -1; 02334 if (change_to_newfile(share->data_file_name,MI_NAME_DEXT, 02335 DATA_TMP_EXT, share->base.raid_chunks, 02336 (param->testflag & T_BACKUP_DATA ? 02337 MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) || 02338 mi_open_datafile(info,share,-1)) 02339 got_error=1; 02340 } 02341 } 02342 if (got_error) 02343 { 02344 if (! param->error_printed) 02345 mi_check_print_error(param,"%d when fixing table",my_errno); 02346 if (new_file >= 0) 02347 { 02348 VOID(my_close(new_file,MYF(0))); 02349 VOID(my_raid_delete(param->temp_filename,share->base.raid_chunks, 02350 MYF(MY_WME))); 02351 if (info->dfile == new_file) 02352 info->dfile= -1; 02353 } 02354 mi_mark_crashed_on_repair(info); 02355 } 02356 else if (key_map == share->state.key_map) 02357 share->state.changed&= ~STATE_NOT_OPTIMIZED_KEYS; 02358 share->state.changed|=STATE_NOT_SORTED_PAGES; 02359 02360 my_free(mi_get_rec_buff_ptr(info, sort_param.rec_buff), 02361 MYF(MY_ALLOW_ZERO_PTR)); 02362 my_free(sort_param.record,MYF(MY_ALLOW_ZERO_PTR)); 02363 my_free((gptr) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR)); 02364 my_free((gptr) sort_info.ft_buf, MYF(MY_ALLOW_ZERO_PTR)); 02365 my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR)); 02366 VOID(end_io_cache(¶m->read_cache)); 02367 info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); 02368 if (!got_error && (param->testflag & T_UNPACK)) 02369 { 02370 share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD; 02371 share->pack.header_length=0; 02372 } 02373 DBUG_RETURN(got_error); 02374 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int mi_repair_parallel | ( | MI_CHECK * | param, | |
| register MI_INFO * | info, | |||
| const char * | name, | |||
| int | rep_quick | |||
| ) |
Definition at line 2396 of file mi_check.c.
References alloc_key_blocks(), st_mi_isam_share::base, bzero, st_mi_check_param::calc_checksum, st_HA_KEYSEG::charset, COMPRESSED_RECORD, st_mi_isam_share::data_file_name, st_mi_isam_share::data_file_type, DATA_TMP_EXT, DBUG_ENTER, del(), st_mi_state_info::dellink, DYNAMIC_RECORD, st_io_cache::end_of_file, err, st_io_cache::file, filecopy(), st_mi_sort_param::filepos, st_mi_sort_param::fix_datafile, st_mi_keydef::flag, st_HA_KEYSEG::flag, FLUSH_FORCE_WRITE, FLUSH_IGNORE_CHANGED, flush_key_blocks(), fn_format(), FT_MAX_WORD_LEN_FOR_SORT, FTPARSER_MEMROOT_ALLOC_SIZE, get_pack_length, st_mi_check_param::glob_crc, HA_BLOB_PART, HA_FT_MAXBYTELEN, HA_KEYTYPE_END, HA_NULL_PART, HA_OFFSET_ERROR, HA_OPTION_CHECKSUM, HA_OPTION_COMPRESS_RECORD, HA_SPACE_PACK, HA_STATE_CHANGED, HA_STATE_ROW_CHANGED, HA_VAR_LENGTH_PART, st_mi_state_info::header, st_mi_isam_pack::header_length, init_alloc_root(), init_io_cache(), key, st_mi_isam_share::key_cache, st_mi_sort_param::key_cmp, st_mi_state_info::key_del, st_mi_sort_param::key_length, st_mi_state_info::key_map, st_mi_sort_param::key_read, st_mi_state_info::key_root, st_mi_sort_param::key_write, st_mi_sort_param::keyinfo, st_mi_isam_share::keyinfo, keyinfo, st_mi_base_info::keys, keyseg, st_mi_keydef::keysegs, st_mi_base_info::keystart, st_mi_isam_share::kfile, st_HA_KEYSEG::length, llstr(), st_mi_sort_param::lock_in_memory, lock_memory(), st_mi_sort_param::master, max, st_mi_state_info::max_block_size_index, st_mi_base_info::max_key_block_length, st_mi_sort_param::max_pos, charset_info_st::mbmaxlen, memcpy, mi_alloc_rec_buff(), mi_check_print_error(), mi_int2store, mi_is_key_active, mi_repair_by_sort(), st_mi_base_info::min_block_length, st_mi_base_info::min_pack_length, my_malloc(), my_raid_create, my_seek(), MY_SEEK_END, MY_WAIT_IF_FULL, MY_WME, MY_ZEROFILL, MYF, st_mi_check_param::myf_rw, st_mi_isam_share::options, st_mi_state_info::options, st_mi_isam_share::pack, st_mi_base_info::pack_reclength, st_mi_sort_param::pos, st_mi_base_info::raid_chunks, st_mi_base_info::raid_chunksize, st_mi_base_info::raid_type, st_mi_check_param::read_buffer_length, st_mi_check_param::read_cache, READ_CACHE, st_mi_check_param::rec_per_key_part, st_mi_state_info::rec_per_key_part, st_mi_isam_share::rec_reflength, st_mi_sort_param::record, st_mi_sort_param::seg, st_mi_keydef::seg, set_data_file_type(), sort_ft_key_read(), sort_ft_key_write(), st_mi_sort_param::sort_info, st_mi_check_param::sort_key_blocks, sort_key_cmp(), sort_key_read(), sort_key_write(), st_mi_state_info::split, st_mi_isam_share::state, T_CALC_CHECKSUM, T_CREATE_MISSING_KEYS, T_REP, T_SILENT, T_UNPACK, st_mi_check_param::temp_filename, test, st_mi_check_param::testflag, thr_attr, st_mi_sort_param::tmpdir, st_mi_check_param::tmpdir, st_mi_check_param::tmpfile_createflag, st_HA_KEYSEG::type, st_mi_check_param::write_buffer_length, WRITE_CACHE, and WRITE_CACHE_USED.
Referenced by myisamchk(), and ha_myisam::repair().
02398 { 02399 #ifndef THREAD 02400 return mi_repair_by_sort(param, info, name, rep_quick); 02401 #else 02402 int got_error; 02403 uint i,key, total_key_length, istep; 02404 ulong rec_length; 02405 ha_rows start_records; 02406 my_off_t new_header_length,del; 02407 File new_file; 02408 MI_SORT_PARAM *sort_param=0; 02409 MYISAM_SHARE *share=info->s; 02410 ulong *rec_per_key_part; 02411 HA_KEYSEG *keyseg; 02412 char llbuff[22]; 02413 IO_CACHE_SHARE io_share; 02414 SORT_INFO sort_info; 02415 ulonglong key_map=share->state.key_map; 02416 pthread_attr_t thr_attr; 02417 DBUG_ENTER("mi_repair_parallel"); 02418 02419 start_records=info->state->records; 02420 got_error=1; 02421 new_file= -1; 02422 new_header_length=(param->testflag & T_UNPACK) ? 0 : 02423 share->pack.header_length; 02424 if (!(param->testflag & T_SILENT)) 02425 { 02426 printf("- parallel recovering (with sort) MyISAM-table '%s'\n",name); 02427 printf("Data records: %s\n", llstr(start_records,llbuff)); 02428 } 02429 param->testflag|=T_REP; /* for easy checking */ 02430 02431 if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)) 02432 param->testflag|=T_CALC_CHECKSUM; 02433 02434 bzero((char*)&sort_info,sizeof(sort_info)); 02435 if (!(sort_info.key_block= 02436 alloc_key_blocks(param, 02437 (uint) param->sort_key_blocks, 02438 share->base.max_key_block_length)) 02439 || init_io_cache(¶m->read_cache,info->dfile, 02440 (uint) param->read_buffer_length, 02441 READ_CACHE,share->pack.header_length,1,MYF(MY_WME)) || 02442 (! rep_quick && 02443 init_io_cache(&info->rec_cache,info->dfile, 02444 (uint) param->write_buffer_length, 02445 WRITE_CACHE,new_header_length,1, 02446 MYF(MY_WME | MY_WAIT_IF_FULL) & param->myf_rw))) 02447 goto err; 02448 sort_info.key_block_end=sort_info.key_block+param->sort_key_blocks; 02449 info->opt_flag|=WRITE_CACHE_USED; 02450 info->rec_cache.file=info->dfile; /* for sort_delete_record */ 02451 02452 if (!rep_quick) 02453 { 02454 /* Get real path for data file */ 02455 if ((new_file=my_raid_create(fn_format(param->temp_filename, 02456 share->data_file_name, "", 02457 DATA_TMP_EXT, 02458 2+4), 02459 0,param->tmpfile_createflag, 02460 share->base.raid_type, 02461 share->base.raid_chunks, 02462 share->base.raid_chunksize, 02463 MYF(0))) < 0) 02464 { 02465 mi_check_print_error(param,"Can't create new tempfile: '%s'", 02466 param->temp_filename); 02467 goto err; 02468 } 02469 if (filecopy(param, new_file,info->dfile,0L,new_header_length, 02470 "datafile-header")) 02471 goto err; 02472 if (param->testflag & T_UNPACK) 02473 { 02474 share->options&= ~HA_OPTION_COMPRESS_RECORD; 02475 mi_int2store(share->state.header.options,share->options); 02476 } 02477 share->state.dellink= HA_OFFSET_ERROR; 02478 info->rec_cache.file=new_file; 02479 } 02480 02481 info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); 02482 if (!(param->testflag & T_CREATE_MISSING_KEYS)) 02483 { 02484 /* 02485 Flush key cache for this file if we are calling this outside 02486 myisamchk 02487 */ 02488 flush_key_blocks(share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED); 02489 /* Clear the pointers to the given rows */ 02490 for (i=0 ; i < share->base.keys ; i++) 02491 share->state.key_root[i]= HA_OFFSET_ERROR; 02492 for (i=0 ; i < share->state.header.max_block_size_index ; i++) 02493 share->state.key_del[i]= HA_OFFSET_ERROR; 02494 info->state->key_file_length=share->base.keystart; 02495 } 02496 else 02497 { 02498 if (flush_key_blocks(share->key_cache,share->kfile, FLUSH_FORCE_WRITE)) 02499 goto err; 02500 key_map= ~key_map; /* Create the missing keys */ 02501 } 02502 02503 sort_info.info=info; 02504 sort_info.param = param; 02505 02506 set_data_file_type(&sort_info, share); 02507 sort_info.dupp=0; 02508 sort_info.buff=0; 02509 param->read_cache.end_of_file=sort_info.filelength= 02510 my_seek(param->read_cache.file,0L,MY_SEEK_END,MYF(0)); 02511 02512 if (share->data_file_type == DYNAMIC_RECORD) 02513 rec_length=max(share->base.min_pack_length+1,share->base.min_block_length); 02514 else if (share->data_file_type == COMPRESSED_RECORD) 02515 rec_length=share->base.min_block_length; 02516 else 02517 rec_length=share->base.pack_reclength; 02518 /* 02519 +1 below is required hack for parallel repair mode. 02520 The info->state->records value, that is compared later 02521 to sort_info.max_records and cannot exceed it, is 02522 increased in sort_key_write. In mi_repair_by_sort, sort_key_write 02523 is called after sort_key_read, where the comparison is performed, 02524 but in parallel mode master thread can call sort_key_write 02525 before some other repair thread calls sort_key_read. 02526 Furthermore I'm not even sure +1 would be enough. 02527 May be sort_info.max_records shold be always set to max value in 02528 parallel mode. 02529 */ 02530 sort_info.max_records= 02531 ((param->testflag & T_CREATE_MISSING_KEYS) ? info->state->records + 1: 02532 (ha_rows) (sort_info.filelength/rec_length+1)); 02533 02534 del=info->state->del; 02535 param->glob_crc=0; 02536 if (param->testflag & T_CALC_CHECKSUM) 02537 param->calc_checksum=1; 02538 02539 if (!(sort_param=(MI_SORT_PARAM *) 02540 my_malloc((uint) share->base.keys * 02541 (sizeof(MI_SORT_PARAM) + share->base.pack_reclength), 02542 MYF(MY_ZEROFILL)))) 02543 { 02544 mi_check_print_error(param,"Not enough memory for key!"); 02545 goto err; 02546 } 02547 total_key_length=0; 02548 rec_per_key_part= param->rec_per_key_part; 02549 info->state->records=info->state->del=share->state.split=0; 02550 info->state->empty=0; 02551 02552 for (i=key=0, istep=1 ; key < share->base.keys ; 02553 rec_per_key_part+=sort_param[i].keyinfo->keysegs, i+=istep, key++) 02554 { 02555 sort_param[i].key=key; 02556 sort_param[i].keyinfo=share->keyinfo+key; 02557 sort_param[i].seg=sort_param[i].keyinfo->seg; 02558 if (! mi_is_key_active(key_map, key)) 02559 { 02560 /* Remember old statistics for key */ 02561 memcpy((char*) rec_per_key_part, 02562 (char*) (share->state.rec_per_key_part+ 02563 (uint) (rec_per_key_part - param->rec_per_key_part)), 02564 sort_param[i].keyinfo->keysegs*sizeof(*rec_per_key_part)); 02565 istep=0; 02566 continue; 02567 } 02568 istep=1; 02569 if ((!(param->testflag & T_SILENT))) 02570 printf ("- Fixing index %d\n",key+1); 02571 if (sort_param[i].keyinfo->flag & HA_FULLTEXT) 02572 { 02573 sort_param[i].key_read=sort_ft_key_read; 02574 sort_param[i].key_write=sort_ft_key_write; 02575 } 02576 else 02577 { 02578 sort_param[i].key_read=sort_key_read; 02579 sort_param[i].key_write=sort_key_write; 02580 } 02581 sort_param[i].key_cmp=sort_key_cmp; 02582 sort_param[i].lock_in_memory=lock_memory; 02583 sort_param[i].tmpdir=param->tmpdir; 02584 sort_param[i].sort_info=&sort_info; 02585 sort_param[i].master=0; 02586 sort_param[i].fix_datafile=0; 02587 02588 sort_param[i].filepos=new_header_length; 02589 sort_param[i].max_pos=sort_param[i].pos=share->pack.header_length; 02590 02591 sort_param[i].record= (((char *)(sort_param+share->base.keys))+ 02592 (share->base.pack_reclength * i)); 02593 if (!mi_alloc_rec_buff(info, -1, &sort_param[i].rec_buff)) 02594 { 02595 mi_check_print_error(param,"Not enough memory!"); 02596 goto err; 02597 } 02598 02599 sort_param[i].key_length=share->rec_reflength; 02600 for (keyseg=sort_param[i].seg; keyseg->type != HA_KEYTYPE_END; 02601 keyseg++) 02602 { 02603 sort_param[i].key_length+=keyseg->length; 02604 if (keyseg->flag & HA_SPACE_PACK) 02605 sort_param[i].key_length+=get_pack_length(keyseg->length); 02606 if (keyseg->flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART)) 02607 sort_param[i].key_length+=2 + test(keyseg->length >= 127); 02608 if (keyseg->flag & HA_NULL_PART) 02609 sort_param[i].key_length++; 02610 } 02611 total_key_length+=sort_param[i].key_length; 02612 02613 if (sort_param[i].keyinfo->flag & HA_FULLTEXT) 02614 { 02615 uint ft_max_word_len_for_sort=FT_MAX_WORD_LEN_FOR_SORT* 02616 sort_param[i].keyinfo->seg->charset->mbmaxlen; 02617 sort_param[i].key_length+=ft_max_word_len_for_sort-HA_FT_MAXBYTELEN; 02618 init_alloc_root(&sort_param[i].wordroot, FTPARSER_MEMROOT_ALLOC_SIZE, 0); 02619 } 02620 } 02621 sort_info.total_keys=i; 02622 sort_param[0].master= 1; 02623 sort_param[0].fix_datafile= (my_bool)(! rep_quick); 02624 02625 sort_info.got_error=0; 02626 pthread_mutex_init(&sort_info.mutex, MY_MUTEX_INIT_FAST); 02627 pthread_cond_init(&sort_info.cond, 0); 02628 pthread_mutex_lock(&sort_info.mutex); 02629 02630 init_io_cache_share(¶m->read_cache, &io_share, i); 02631 (void) pthread_attr_init(&thr_attr); 02632 (void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); 02633 02634 for (i=0 ; i < sort_info.total_keys ; i++) 02635 { 02636 sort_param[i].read_cache=param->read_cache; 02637 /* 02638 two approaches: the same amount of memory for each thread 02639 or the memory for the same number of keys for each thread... 02640 In the second one all the threads will fill their sort_buffers 02641 (and call write_keys) at the same time, putting more stress on i/o. 02642 */ 02643 sort_param[i].sortbuff_size= 02644 #ifndef USING_SECOND_APPROACH 02645 param->sort_buffer_length/sort_info.total_keys; 02646 #else 02647 param->sort_buffer_length*sort_param[i].key_length/total_key_length; 02648 #endif 02649 if (pthread_create(&sort_param[i].thr, &thr_attr, 02650 thr_find_all_keys, 02651 (void *) (sort_param+i))) 02652 { 02653 mi_check_print_error(param,"Cannot start a repair thread"); 02654 remove_io_thread(¶m->read_cache); 02655 sort_info.got_error=1; 02656 } 02657 else 02658 sort_info.threads_running++; 02659 } 02660 (void) pthread_attr_destroy(&thr_attr); 02661 02662 /* waiting for all threads to finish */ 02663 while (sort_info.threads_running) 02664 pthread_cond_wait(&sort_info.cond, &sort_info.mutex); 02665 pthread_mutex_unlock(&sort_info.mutex); 02666 02667 if ((got_error= thr_write_keys(sort_param))) 02668 { 02669 param->retry_repair=1; 02670 goto err; 02671 } 02672 got_error=1; /* Assume the following may go wrong */ 02673 02674 if (sort_param[0].fix_datafile) 02675 { 02676 if (write_data_suffix(&sort_info,1) || end_io_cache(&info->rec_cache)) 02677 goto err; 02678 if (param->testflag & T_SAFE_REPAIR) 02679 { 02680 /* Don't repair if we loosed more than one row */ 02681 if (info->state->records+1 < start_records) 02682 { 02683 info->state->records=start_records; 02684 goto err; 02685 } 02686 } 02687 share->state.state.data_file_length= info->state->data_file_length= 02688 sort_param->filepos; 02689 /* Only whole records */ 02690 share->state.version=(ulong) time((time_t*) 0); 02691 my_close(info->dfile,MYF(0)); 02692 info->dfile=new_file; 02693 share->data_file_type=sort_info.new_data_file_type; 02694 share->pack.header_length=(ulong) new_header_length; 02695 } 02696 else 02697 info->state->data_file_length=sort_param->max_pos; 02698 02699 if (rep_quick && del+sort_info.dupp != info->state->del) 02700 { 02701 mi_check_print_error(param,"Couldn't fix table with quick recovery: Found wrong number of deleted records"); 02702 mi_check_print_error(param,"Run recovery again without -q"); 02703 param->retry_repair=1; 02704 param->testflag|=T_RETRY_WITHOUT_QUICK; 02705 goto err; 02706 } 02707 02708 if (rep_quick & T_FORCE_UNIQUENESS) 02709 { 02710 my_off_t skr=info->state->data_file_length+ 02711 (share->options & HA_OPTION_COMPRESS_RECORD ? 02712 MEMMAP_EXTRA_MARGIN : 0); 02713 #ifdef USE_RELOC 02714 if (share->data_file_type == STATIC_RECORD && 02715 skr < share->base.reloc*share->base.min_pack_length) 02716 skr=share->base.reloc*share->base.min_pack_length; 02717 #endif 02718 if (skr != sort_info.filelength && !info->s->base.raid_type) 02719 if (my_chsize(info->dfile,skr,0,MYF(0))) 02720 mi_check_print_warning(param, 02721 "Can't change size of datafile, error: %d", 02722 my_errno); 02723 } 02724 if (param->testflag & T_CALC_CHECKSUM) 02725 info->state->checksum=param->glob_crc; 02726 02727 if (my_chsize(share->kfile,info->state->key_file_length,0,MYF(0))) 02728 mi_check_print_warning(param, 02729 "Can't change size of indexfile, error: %d", my_errno); 02730 02731 if (!(param->testflag & T_SILENT)) 02732 { 02733 if (start_records != info->state->records) 02734 printf("Data records: %s\n", llstr(info->state->records,llbuff)); 02735 if (sort_info.dupp) 02736 mi_check_print_warning(param, 02737 "%s records have been removed", 02738 llstr(sort_info.dupp,llbuff)); 02739 } 02740 got_error=0; 02741 02742 if (&share->state.state != info->state) 02743 memcpy(&share->state.state, info->state, sizeof(*info->state)); 02744 02745 err: 02746 got_error|= flush_blocks(param, share->key_cache, share->kfile); 02747 VOID(end_io_cache(&info->rec_cache)); 02748 if (!got_error) 02749 { 02750 /* Replace the actual file with the temporary file */ 02751 if (new_file >= 0) 02752 { 02753 my_close(new_file,MYF(0)); 02754 info->dfile=new_file= -1; 02755 if (change_to_newfile(share->data_file_name,MI_NAME_DEXT, 02756 DATA_TMP_EXT, share->base.raid_chunks, 02757 (param->testflag & T_BACKUP_DATA ? 02758 MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) || 02759 mi_open_datafile(info,share,-1)) 02760 got_error=1; 02761 } 02762 } 02763 if (got_error) 02764 { 02765 if (! param->error_printed) 02766 mi_check_print_error(param,"%d when fixing table",my_errno); 02767 if (new_file >= 0) 02768 { 02769 VOID(my_close(new_file,MYF(0))); 02770 VOID(my_raid_delete(param->temp_filename,share->base.raid_chunks, 02771 MYF(MY_WME))); 02772 if (info->dfile == new_file) 02773 info->dfile= -1; 02774 } 02775 mi_mark_crashed_on_repair(info); 02776 } 02777 else if (key_map == share->state.key_map) 02778 share->state.changed&= ~STATE_NOT_OPTIMIZED_KEYS; 02779 share->state.changed|=STATE_NOT_SORTED_PAGES; 02780 02781 pthread_cond_destroy (&sort_info.cond); 02782 pthread_mutex_destroy(&sort_info.mutex); 02783 02784 my_free((gptr) sort_info.ft_buf, MYF(MY_ALLOW_ZERO_PTR)); 02785 my_free((gptr) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR)); 02786 my_free((gptr) sort_param,MYF(MY_ALLOW_ZERO_PTR)); 02787 my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR)); 02788 VOID(end_io_cache(¶m->read_cache)); 02789 info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); 02790 if (!got_error && (param->testflag & T_UNPACK)) 02791 { 02792 share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD; 02793 share->pack.header_length=0; 02794 } 02795 DBUG_RETURN(got_error); 02796 #endif /* THREAD */ 02797 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int mi_reset | ( | struct st_myisam_info * | file | ) |
Definition at line 411 of file mi_extra.c.
References st_mi_isam_share::base, st_mi_base_info::blobs, st_mi_status_info::data_file_length, DBUG_ENTER, DBUG_RETURN, end_io_cache(), error, st_mi_isam_share::file_map, HA_OFFSET_ERROR, HA_STATE_CHANGED, HA_STATE_NEXT_FOUND, HA_STATE_PREV_FOUND, KEY_READ_USED, st_myisam_info::last_search_keypage, st_myisam_info::lastinx, st_myisam_info::lastpos, MEMMAP_USED, mi_alloc_rec_buff(), st_myisam_info::opt_flag, st_myisam_info::page_changed, st_myisam_info::quick_mode, READ_CACHE_USED, st_myisam_info::rec_buff, st_myisam_info::rec_cache, REMEMBER_OLD_POS, st_myisam_info::s, st_mi_isam_share::state, st_mi_state_info::state, st_myisam_info::update, and WRITE_CACHE_USED.
Referenced by main(), mrg_rrnd(), myrg_reset(), ha_myisam::reset(), and ha_myisam::rnd_init().
00412 { 00413 int error= 0; 00414 MYISAM_SHARE *share=info->s; 00415 DBUG_ENTER("mi_reset"); 00416 /* 00417 Free buffers and reset the following flags: 00418 EXTRA_CACHE, EXTRA_WRITE_CACHE, EXTRA_KEYREAD, EXTRA_QUICK 00419 00420 If the row buffer cache is large (for dynamic tables), reduce it 00421 to save memory. 00422 */ 00423 if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED)) 00424 { 00425 info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); 00426 error= end_io_cache(&info->rec_cache); 00427 } 00428 if (share->base.blobs) 00429 mi_alloc_rec_buff(info, -1, &info->rec_buff); 00430 #if defined(HAVE_MMAP) && defined(HAVE_MADVISE) 00431 if (info->opt_flag & MEMMAP_USED) 00432 madvise(share->file_map,share->state.state.data_file_length,MADV_RANDOM); 00433 #endif 00434 info->opt_flag&= ~(KEY_READ_USED | REMEMBER_OLD_POS); 00435 info->quick_mode=0; 00436 info->lastinx= 0; /* Use first index as def */ 00437 info->last_search_keypage= info->lastpos= HA_OFFSET_ERROR; 00438 info->page_changed= 1; 00439 info->update= ((info->update & HA_STATE_CHANGED) | HA_STATE_NEXT_FOUND | 00440 HA_STATE_PREV_FOUND); 00441 DBUG_RETURN(error); 00442 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int mi_rfirst | ( | struct st_myisam_info * | file, | |
| byte * | buf, | |||
| int | inx | |||
| ) |
Definition at line 21 of file mi_rfirst.c.
References DBUG_ENTER, DBUG_RETURN, HA_OFFSET_ERROR, HA_STATE_PREV_FOUND, st_myisam_info::lastpos, mi_rnext(), and st_myisam_info::update.
Referenced by ha_myisam::index_first(), main(), and myrg_rfirst().
00022 { 00023 DBUG_ENTER("mi_rfirst"); 00024 info->lastpos= HA_OFFSET_ERROR; 00025 info->update|= HA_STATE_PREV_FOUND; 00026 DBUG_RETURN(mi_rnext(info,buf,inx)); 00027 } /* mi_rfirst */
Here is the call graph for this function:

Here is the caller graph for this function:

| int mi_rkey | ( | struct st_myisam_info * | file, | |
| byte * | buf, | |||
| int | inx, | |||
| const byte * | key, | |||
| uint | key_len, | |||
| enum ha_rkey_function | search_flag | |||
| ) |
Definition at line 25 of file mi_rkey.c.
References _mi_check_index(), _mi_keylength_part(), _mi_pack_key(), _mi_print_key(), _mi_search(), _mi_search_next(), bmove(), bzero, st_mi_isam_share::concurrent_insert, DBUG_ENTER, DBUG_EXECUTE, DBUG_FILE, DBUG_PRINT, DBUG_RETURN, err, fast_mi_readinfo, st_mi_keydef::flag, HA_ERR_CRASHED, HA_ERR_KEY_NOT_FOUND, HA_KEY_ALG_BTREE, HA_KEY_ALG_RTREE, HA_OFFSET_ERROR, HA_READ_AFTER_KEY, HA_READ_KEY_EXACT, HA_STATE_AKTIV, HA_STATE_CHANGED, HA_STATE_NEXT_FOUND, HA_STATE_ROW_CHANGED, HA_VAR_LENGTH_KEY, keyinfo, st_mi_isam_share::keyinfo, memcpy, mi_print_error, my_errno, myisam_read_vec, myisam_readnext_vec, rw_rdlock, rw_unlock, st_myisam_info::s, SEARCH_FIND, SEARCH_LAST, SEARCH_NO_FIND, st_mi_keydef::seg, USE_PACKED_KEYS, and USE_WHOLE_KEY.
Referenced by chk_key(), find_record_with_key(), ha_myisam::get_auto_increment(), ha_myisam::index_read(), ha_myisam::index_read_idx(), ha_myisam::index_read_last(), main(), myrg_rkey(), run_test(), test_read(), and test_update().
00027 { 00028 uchar *key_buff; 00029 MYISAM_SHARE *share=info->s; 00030 MI_KEYDEF *keyinfo; 00031 HA_KEYSEG *last_used_keyseg; 00032 uint pack_key_length, use_key_length, nextflag; 00033 DBUG_ENTER("mi_rkey"); 00034 DBUG_PRINT("enter", ("base: %lx buf: %lx inx: %d search_flag: %d", 00035 (long) info, (long) buf, inx, search_flag)); 00036 00037 if ((inx = _mi_check_index(info,inx)) < 0) 00038 DBUG_RETURN(my_errno); 00039 00040 info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); 00041 info->last_key_func= search_flag; 00042 keyinfo= share->keyinfo + inx; 00043 00044 if (info->once_flags & USE_PACKED_KEYS) 00045 { 00046 info->once_flags&= ~USE_PACKED_KEYS; /* Reset flag */ 00047 /* 00048 key is already packed!; This happens when we are using a MERGE TABLE 00049 */ 00050 key_buff=info->lastkey+info->s->base.max_key_length; 00051 pack_key_length= key_len; 00052 bmove(key_buff,

