1 /* 2 Copyright (c) 2000, 2021, Oracle and/or its affiliates. 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License, version 2.0, 6 as published by the Free Software Foundation. 7 8 This program is also distributed with certain software (including 9 but not limited to OpenSSL) that is licensed under separate terms, 10 as designated in a particular file or component or in included license 11 documentation. The authors of MySQL hereby grant you an additional 12 permission to link the program and your derivative works with the 13 separately licensed software that they have included with MySQL. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License, version 2.0, for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program; if not, write to the Free Software 22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 23 24 /* This file should be included when using myisam_funktions */ 25 26 #ifndef _myisam_h 27 #define _myisam_h 28 29 #include "my_base.h" 30 #include "m_ctype.h" 31 #include "keycache.h" 32 #include "my_compare.h" 33 #include "my_check_opt.h" 34 #include "m_string.h" 35 36 #ifdef __cplusplus 37 extern "C" { 38 #endif 39 40 /* 41 Limit max keys according to HA_MAX_POSSIBLE_KEY 42 */ 43 44 #if MAX_INDEXES > HA_MAX_POSSIBLE_KEY 45 #define MI_MAX_KEY HA_MAX_POSSIBLE_KEY /* Max allowed keys */ 46 #else 47 #define MI_MAX_KEY MAX_INDEXES /* Max allowed keys */ 48 #endif 49 50 #define MI_MAX_POSSIBLE_KEY_BUFF HA_MAX_POSSIBLE_KEY_BUFF 51 /* 52 The following defines can be increased if necessary. 53 But beware the dependency of MI_MAX_POSSIBLE_KEY_BUFF and MI_MAX_KEY_LENGTH. 54 */ 55 #define MI_MAX_KEY_LENGTH 4000 /* Max length in bytes */ 56 #define MI_MAX_KEY_SEG 16 /* Max segments for key */ 57 58 #define MI_MAX_KEY_BUFF (MI_MAX_KEY_LENGTH+MI_MAX_KEY_SEG*6+8+8) 59 #define MI_MAX_MSG_BUF 1024 /* used in CHECK TABLE, REPAIR TABLE */ 60 #define MI_NAME_IEXT ".MYI" 61 #define MI_NAME_DEXT ".MYD" 62 63 /* Possible values for myisam_block_size (must be power of 2) */ 64 #define MI_KEY_BLOCK_LENGTH 1024 /* default key block length */ 65 #define MI_MIN_KEY_BLOCK_LENGTH 1024 /* Min key block length */ 66 #define MI_MAX_KEY_BLOCK_LENGTH 16384 67 68 /* 69 In the following macros '_keyno_' is 0 .. keys-1. 70 If there can be more keys than bits in the key_map, the highest bit 71 is for all upper keys. They cannot be switched individually. 72 This means that clearing of high keys is ignored, setting one high key 73 sets all high keys. 74 */ 75 #define MI_KEYMAP_BITS (8 * SIZEOF_LONG_LONG) 76 #define MI_KEYMAP_HIGH_MASK (1ULL << (MI_KEYMAP_BITS - 1)) 77 #define mi_get_mask_all_keys_active(_keys_) \ 78 (((_keys_) < MI_KEYMAP_BITS) ? \ 79 ((1ULL << (_keys_)) - 1ULL) : \ 80 (~ 0ULL)) 81 82 #if MI_MAX_KEY > MI_KEYMAP_BITS 83 84 #define mi_is_key_active(_keymap_,_keyno_) \ 85 (((_keyno_) < MI_KEYMAP_BITS) ? \ 86 MY_TEST((_keymap_) & (1ULL << (_keyno_))) : \ 87 MY_TEST((_keymap_) & MI_KEYMAP_HIGH_MASK)) 88 #define mi_set_key_active(_keymap_,_keyno_) \ 89 (_keymap_)|= (((_keyno_) < MI_KEYMAP_BITS) ? \ 90 (1ULL << (_keyno_)) : \ 91 MI_KEYMAP_HIGH_MASK) 92 #define mi_clear_key_active(_keymap_,_keyno_) \ 93 (_keymap_)&= (((_keyno_) < MI_KEYMAP_BITS) ? \ 94 (~ (1ULL << (_keyno_))) : \ 95 (~ (0ULL)) /*ignore*/ ) 96 97 #else 98 99 #define mi_is_key_active(_keymap_,_keyno_) \ 100 MY_TEST((_keymap_) & (1ULL << (_keyno_))) 101 #define mi_set_key_active(_keymap_,_keyno_) \ 102 (_keymap_)|= (1ULL << (_keyno_)) 103 #define mi_clear_key_active(_keymap_,_keyno_) \ 104 (_keymap_)&= (~ (1ULL << (_keyno_))) 105 106 #endif 107 108 #define mi_is_any_key_active(_keymap_) \ 109 MY_TEST((_keymap_)) 110 #define mi_is_all_keys_active(_keymap_,_keys_) \ 111 ((_keymap_) == mi_get_mask_all_keys_active(_keys_)) 112 #define mi_set_all_keys_active(_keymap_,_keys_) \ 113 (_keymap_)= mi_get_mask_all_keys_active(_keys_) 114 #define mi_clear_all_keys_active(_keymap_) \ 115 (_keymap_)= 0 116 #define mi_intersect_keys_active(_to_,_from_) \ 117 (_to_)&= (_from_) 118 #define mi_is_any_intersect_keys_active(_keymap1_,_keys_,_keymap2_) \ 119 ((_keymap1_) & (_keymap2_) & \ 120 mi_get_mask_all_keys_active(_keys_)) 121 #define mi_copy_keys_active(_to_,_maxkeys_,_from_) \ 122 (_to_)= (mi_get_mask_all_keys_active(_maxkeys_) & \ 123 (_from_)) 124 125 /* Param to/from mi_status */ 126 127 typedef struct st_mi_isaminfo /* Struct from h_info */ 128 { 129 ha_rows records; /* Records in database */ 130 ha_rows deleted; /* Deleted records in database */ 131 my_off_t recpos; /* Pos for last used record */ 132 my_off_t newrecpos; /* Pos if we write new record */ 133 my_off_t dupp_key_pos; /* Position to record with dupp key */ 134 my_off_t data_file_length, /* Length of data file */ 135 max_data_file_length, 136 index_file_length, 137 max_index_file_length, 138 delete_length; 139 ulong reclength; /* Recordlength */ 140 ulong mean_reclength; /* Mean recordlength (if packed) */ 141 ulonglong auto_increment; 142 ulonglong key_map; /* Which keys are used */ 143 char *data_file_name, *index_file_name; 144 uint keys; /* Number of keys in use */ 145 uint options; /* HA_OPTION_... used */ 146 int errkey, /* With key was dupplicated on err */ 147 sortkey; /* clustered by this key */ 148 File filenr; /* (uniq) filenr for datafile */ 149 time_t create_time; /* When table was created */ 150 time_t check_time; 151 time_t update_time; 152 uint reflength; 153 ulong record_offset; 154 ulong *rec_per_key; /* for sql optimizing */ 155 } MI_ISAMINFO; 156 157 158 typedef struct st_mi_create_info 159 { 160 const char *index_file_name, *data_file_name; /* If using symlinks */ 161 ha_rows max_rows; 162 ha_rows reloc_rows; 163 ulonglong auto_increment; 164 ulonglong data_file_length; 165 ulonglong key_file_length; 166 uint old_options; 167 uint16 language; 168 my_bool with_auto_increment; 169 } MI_CREATE_INFO; 170 171 struct st_myisam_info; /* For referense */ 172 struct st_mi_isam_share; 173 typedef struct st_myisam_info MI_INFO; 174 struct st_mi_s_param; 175 176 typedef struct st_mi_keydef /* Key definition with open & info */ 177 { 178 struct st_mi_isam_share *share; /* Pointer to base (set in mi_open) */ 179 uint16 keysegs; /* Number of key-segment */ 180 uint16 flag; /* NOSAME, PACK_USED */ 181 182 uint8 key_alg; /* BTREE, RTREE */ 183 uint16 block_length; /* Length of keyblock (auto) */ 184 uint16 underflow_block_length; /* When to execute underflow */ 185 uint16 keylength; /* Tot length of keyparts (auto) */ 186 uint16 minlength; /* min length of (packed) key (auto) */ 187 uint16 maxlength; /* max length of (packed) key (auto) */ 188 uint16 block_size_index; /* block_size (auto) */ 189 uint32 version; /* For concurrent read/write */ 190 uint32 ftkey_nr; /* full-text index number */ 191 192 HA_KEYSEG *seg,*end; 193 struct st_mysql_ftparser *parser; /* Fulltext [pre]parser */ 194 int (*bin_search)(struct st_myisam_info *info,struct st_mi_keydef *keyinfo, 195 uchar *page,uchar *key, 196 uint key_len,uint comp_flag,uchar * *ret_pos, 197 uchar *buff, my_bool *was_last_key); 198 uint (*get_key)(struct st_mi_keydef *keyinfo,uint nod_flag,uchar * *page, 199 uchar *key); 200 int (*pack_key)(struct st_mi_keydef *keyinfo,uint nod_flag,uchar *next_key, 201 uchar *org_key, uchar *prev_key, uchar *key, 202 struct st_mi_s_param *s_temp); 203 void (*store_key)(struct st_mi_keydef *keyinfo, uchar *key_pos, 204 struct st_mi_s_param *s_temp); 205 int (*ck_insert)(struct st_myisam_info *inf, uint k_nr, uchar *k, uint klen); 206 int (*ck_delete)(struct st_myisam_info *inf, uint k_nr, uchar *k, uint klen); 207 } MI_KEYDEF; 208 209 210 #define MI_UNIQUE_HASH_LENGTH 4 211 212 typedef struct st_unique_def /* Segment definition of unique */ 213 { 214 uint16 keysegs; /* Number of key-segment */ 215 uchar key; /* Mapped to which key */ 216 uint8 null_are_equal; 217 HA_KEYSEG *seg,*end; 218 } MI_UNIQUEDEF; 219 220 typedef struct st_mi_decode_tree /* Decode huff-table */ 221 { 222 uint16 *table; 223 uint quick_table_bits; 224 uchar *intervalls; 225 } MI_DECODE_TREE; 226 227 228 struct st_mi_bit_buff; 229 230 /* 231 Note that null markers should always be first in a row ! 232 When creating a column, one should only specify: 233 type, length, null_bit and null_pos 234 */ 235 236 typedef struct st_columndef /* column information */ 237 { 238 int16 type; /* en_fieldtype */ 239 uint16 length; /* length of field */ 240 uint32 offset; /* Offset to position in row */ 241 uint8 null_bit; /* If column may be 0 */ 242 uint16 null_pos; /* position for null marker */ 243 244 void (*unpack)(struct st_columndef *rec,struct st_mi_bit_buff *buff, 245 uchar *start,uchar *end); 246 enum en_fieldtype base_type; 247 uint space_length_bits,pack_type; 248 MI_DECODE_TREE *huff_tree; 249 } MI_COLUMNDEF; 250 251 252 extern char * myisam_log_filename; /* Name of logfile */ 253 extern ulong myisam_block_size; 254 extern ulong myisam_concurrent_insert; 255 extern my_bool myisam_flush,myisam_delay_key_write,myisam_single_user; 256 extern my_off_t myisam_max_temp_length; 257 extern ulong myisam_data_pointer_size; 258 259 /* usually used to check if a symlink points into the mysql data home */ 260 /* which is normally forbidden */ 261 extern int (*myisam_test_invalid_symlink)(const char *filename); 262 extern ulonglong myisam_mmap_size, myisam_mmap_used; 263 extern mysql_mutex_t THR_LOCK_myisam_mmap; 264 265 /* Prototypes for myisam-functions */ 266 267 extern int mi_close_share(struct st_myisam_info *file, my_bool *closed_share); 268 #define mi_close(file) mi_close_share(file, NULL) 269 extern int mi_delete(struct st_myisam_info *file,const uchar *buff); 270 extern struct st_myisam_info *mi_open_share(const char *name, 271 struct st_mi_isam_share *old_share, 272 int mode, 273 uint wait_if_locked); 274 #define mi_open(name, mode, wait_if_locked) \ 275 mi_open_share(name, NULL, mode, wait_if_locked) 276 extern int mi_panic(enum ha_panic_function function); 277 extern int mi_rfirst(struct st_myisam_info *file,uchar *buf,int inx); 278 extern int mi_rkey(MI_INFO *info, uchar *buf, int inx, const uchar *key, 279 key_part_map keypart_map, enum ha_rkey_function search_flag); 280 extern int mi_rlast(struct st_myisam_info *file,uchar *buf,int inx); 281 extern int mi_rnext(struct st_myisam_info *file,uchar *buf,int inx); 282 extern int mi_rnext_same(struct st_myisam_info *info, uchar *buf); 283 extern int mi_rprev(struct st_myisam_info *file,uchar *buf,int inx); 284 extern int mi_rrnd(struct st_myisam_info *file,uchar *buf, my_off_t pos); 285 extern int mi_scan_init(struct st_myisam_info *file); 286 extern int mi_scan(struct st_myisam_info *file,uchar *buf); 287 extern int mi_rsame(struct st_myisam_info *file,uchar *record,int inx); 288 extern int mi_rsame_with_pos(struct st_myisam_info *file,uchar *record, 289 int inx, my_off_t pos); 290 extern int mi_update(struct st_myisam_info *file,const uchar *old, 291 uchar *new_record); 292 extern int mi_write(struct st_myisam_info *file,uchar *buff); 293 extern my_off_t mi_position(struct st_myisam_info *file); 294 extern int mi_status(struct st_myisam_info *info, MI_ISAMINFO *x, uint flag); 295 extern int mi_lock_database(struct st_myisam_info *file,int lock_type); 296 extern int mi_create(const char *name,uint keys,MI_KEYDEF *keydef, 297 uint columns, MI_COLUMNDEF *columndef, 298 uint uniques, MI_UNIQUEDEF *uniquedef, 299 MI_CREATE_INFO *create_info, uint flags); 300 extern int mi_delete_table(const char *name); 301 extern int mi_rename(const char *from, const char *to); 302 extern int mi_extra(struct st_myisam_info *file, 303 enum ha_extra_function function, 304 void *extra_arg); 305 extern int mi_reset(struct st_myisam_info *file); 306 extern ha_rows mi_records_in_range(MI_INFO *info, int inx, 307 key_range *min_key, key_range *max_key); 308 extern int mi_log(int activate_log); 309 extern int mi_is_changed(struct st_myisam_info *info); 310 extern int mi_delete_all_rows(struct st_myisam_info *info); 311 extern ulong _mi_calc_blob_length(uint length , const uchar *pos); 312 extern uint mi_get_pointer_length(ulonglong file_length, uint def); 313 314 #define MEMMAP_EXTRA_MARGIN 7 /* Write this as a suffix for mmap file */ 315 /* this is used to pass to mysql_myisamchk_table */ 316 317 #define MYISAMCHK_REPAIR 1 /* equivalent to myisamchk -r */ 318 #define MYISAMCHK_VERIFY 2 /* Verify, run repair if failure */ 319 320 /* 321 Flags used by myisamchk.c or/and ha_myisam.cc that are NOT passed 322 to mi_check.c follows: 323 */ 324 325 #define TT_USEFRM 1 326 #define TT_FOR_UPGRADE 2 327 328 #define O_NEW_INDEX 1 /* Bits set in out_flag */ 329 #define O_NEW_DATA 2 330 #define O_DATA_LOST 4 331 332 /* these struct is used by my_check to tell it what to do */ 333 334 typedef struct st_sort_key_blocks /* Used when sorting */ 335 { 336 uchar *buff,*end_pos; 337 uchar lastkey[MI_MAX_POSSIBLE_KEY_BUFF]; 338 uint last_length; 339 int inited; 340 } SORT_KEY_BLOCKS; 341 342 343 /* 344 MyISAM supports several statistics collection methods. Currently statistics 345 collection method is not stored in MyISAM file and has to be specified for 346 each table analyze/repair operation in MI_CHECK::stats_method. 347 */ 348 349 typedef enum 350 { 351 /* Treat NULLs as inequal when collecting statistics (default for 4.1/5.0) */ 352 MI_STATS_METHOD_NULLS_NOT_EQUAL, 353 /* Treat NULLs as equal when collecting statistics (like 4.0 did) */ 354 MI_STATS_METHOD_NULLS_EQUAL, 355 /* Ignore NULLs - count only tuples without NULLs in the index components */ 356 MI_STATS_METHOD_IGNORE_NULLS 357 } enum_mi_stats_method; 358 359 typedef struct st_mi_check_param 360 { 361 ulonglong auto_increment_value; 362 ulonglong max_data_file_length; 363 ulonglong keys_in_use; 364 ulonglong max_record_length; 365 ulonglong sort_buffer_length; 366 my_off_t search_after_block; 367 my_off_t new_file_pos,key_file_blocks; 368 my_off_t keydata,totaldata,key_blocks,start_check_pos; 369 ha_rows total_records,total_deleted; 370 ha_checksum record_checksum,glob_crc; 371 ulonglong use_buffers; 372 ulong read_buffer_length, write_buffer_length, sort_key_blocks; 373 uint out_flag,warning_printed,error_printed,verbose; 374 uint opt_sort_key,total_files,max_level; 375 uint testflag, key_cache_block_size; 376 uint16 language; 377 my_bool using_global_keycache, opt_lock_memory, opt_follow_links; 378 my_bool retry_repair, force_sort; 379 char temp_filename[FN_REFLEN],*isam_file_name; 380 MY_TMPDIR *tmpdir; 381 int tmpfile_createflag; 382 myf myf_rw; 383 IO_CACHE read_cache; 384 385 /* 386 The next two are used to collect statistics, see update_key_parts for 387 description. 388 */ 389 ulonglong unique_count[MI_MAX_KEY_SEG+1]; 390 ulonglong notnull_count[MI_MAX_KEY_SEG+1]; 391 392 ha_checksum key_crc[HA_MAX_POSSIBLE_KEY]; 393 ulong rec_per_key_part[MI_MAX_KEY_SEG*HA_MAX_POSSIBLE_KEY]; 394 void *thd; 395 const char *db_name, *table_name; 396 const char *op_name; 397 enum_mi_stats_method stats_method; 398 mysql_mutex_t print_msg_mutex; 399 my_bool need_print_msg_lock; 400 } MI_CHECK; 401 402 typedef struct st_sort_ft_buf 403 { 404 uchar *buf, *end; 405 int count; 406 uchar lastkey[MI_MAX_KEY_BUFF]; 407 } SORT_FT_BUF; 408 409 typedef struct st_sort_info 410 { 411 my_off_t filelength,dupp,buff_length; 412 ha_rows max_records; 413 uint current_key, total_keys; 414 myf myf_rw; 415 enum data_file_type new_data_file_type; 416 MI_INFO *info; 417 MI_CHECK *param; 418 uchar *buff; 419 SORT_KEY_BLOCKS *key_block,*key_block_end; 420 SORT_FT_BUF *ft_buf; 421 /* sync things */ 422 uint got_error, threads_running; 423 mysql_mutex_t mutex; 424 mysql_cond_t cond; 425 } SORT_INFO; 426 427 /* functions in mi_check */ 428 void myisamchk_init(MI_CHECK *param); 429 int chk_status(MI_CHECK *param, MI_INFO *info); 430 int chk_del(MI_CHECK *param, MI_INFO *info, uint test_flag); 431 int chk_size(MI_CHECK *param, MI_INFO *info); 432 int chk_key(MI_CHECK *param, MI_INFO *info); 433 int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend); 434 int mi_repair(MI_CHECK *param, MI_INFO *info, 435 char * name, int rep_quick, my_bool no_copy_stat); 436 int mi_sort_index(MI_CHECK *param, MI_INFO *info, char * name, 437 my_bool no_copy_stat); 438 int mi_repair_by_sort(MI_CHECK *param, MI_INFO *info, 439 const char * name, int rep_quick, my_bool no_copy_stat); 440 int mi_repair_parallel(MI_CHECK *param, MI_INFO *info, 441 const char * name, int rep_quick, my_bool no_copy_stat); 442 int change_to_newfile(const char * filename, const char * old_ext, 443 const char * new_ext, myf myflags); 444 int lock_file(MI_CHECK *param, File file, my_off_t start, int lock_type, 445 const char *filetype, const char *filename); 446 void lock_memory(MI_CHECK *param); 447 void update_auto_increment_key(MI_CHECK *param, MI_INFO *info, 448 my_bool repair); 449 int update_state_info(MI_CHECK *param, MI_INFO *info,uint update); 450 void update_key_parts(MI_KEYDEF *keyinfo, ulong *rec_per_key_part, 451 ulonglong *unique, ulonglong *notnull, 452 ulonglong records); 453 int filecopy(MI_CHECK *param, File to,File from,my_off_t start, 454 my_off_t length, const char *type); 455 int movepoint(MI_INFO *info,uchar *record,my_off_t oldpos, 456 my_off_t newpos, uint prot_key); 457 int write_data_suffix(SORT_INFO *sort_info, my_bool fix_datafile); 458 int test_if_almost_full(MI_INFO *info); 459 int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename); 460 void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows); 461 my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows, ulonglong key_map, 462 my_bool force); 463 464 int mi_init_bulk_insert(MI_INFO *info, ulong cache_size, ha_rows rows); 465 void mi_flush_bulk_insert(MI_INFO *info, uint inx); 466 void mi_end_bulk_insert(MI_INFO *info); 467 int mi_assign_to_key_cache(MI_INFO *info, ulonglong key_map, 468 KEY_CACHE *key_cache); 469 void mi_change_key_cache(KEY_CACHE *old_key_cache, 470 KEY_CACHE *new_key_cache); 471 int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves); 472 473 extern st_keycache_thread_var main_thread_keycache_var; 474 st_keycache_thread_var *keycache_thread_var(); 475 #ifdef __cplusplus 476 } 477 #endif 478 #endif 479