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 is included by all internal myisam files */ 25 26 #include "myisam.h" /* Structs & some defines */ 27 #include "myisampack.h" /* packing of keys */ 28 #include <my_tree.h> 29 #include <my_thread.h> 30 #include "my_thread_local.h" 31 #include <thr_lock.h> 32 #include <mysql/psi/mysql_file.h> 33 #include <mysql/plugin_ftparser.h> 34 35 /* undef map from my_nosys; We need test-if-disk full */ 36 #if defined(my_write) 37 #undef my_write 38 #endif 39 40 typedef struct st_mi_status_info 41 { 42 ha_rows records; /* Rows in table */ 43 ha_rows del; /* Removed rows */ 44 my_off_t empty; /* lost space in datafile */ 45 my_off_t key_empty; /* lost space in indexfile */ 46 my_off_t key_file_length; 47 my_off_t data_file_length; 48 ha_checksum checksum; 49 my_bool uncacheable; /* Active concurrent insert */ 50 } MI_STATUS_INFO; 51 52 typedef struct st_mi_state_info 53 { 54 struct { /* Fileheader */ 55 uchar file_version[4]; 56 uchar options[2]; 57 uchar header_length[2]; 58 uchar state_info_length[2]; 59 uchar base_info_length[2]; 60 uchar base_pos[2]; 61 uchar key_parts[2]; /* Key parts */ 62 uchar unique_key_parts[2]; /* Key parts + unique parts */ 63 uchar keys; /* number of keys in file */ 64 uchar uniques; /* number of UNIQUE definitions */ 65 uchar language; /* Language for indexes */ 66 uchar max_block_size_index; /* max keyblock size */ 67 uchar fulltext_keys; 68 uchar not_used; /* To align to 8 */ 69 } header; 70 71 MI_STATUS_INFO state; 72 ha_rows split; /* number of split blocks */ 73 my_off_t dellink; /* Link to next removed block */ 74 ulonglong auto_increment; 75 ulong process; /* process that updated table last */ 76 ulong unique; /* Unique number for this process */ 77 ulong update_count; /* Updated for each write lock */ 78 ulong status; 79 ulong *rec_per_key_part; 80 my_off_t *key_root; /* Start of key trees */ 81 my_off_t *key_del; /* delete links for trees */ 82 my_off_t rec_per_key_rows; /* Rows when calculating rec_per_key */ 83 84 ulong sec_index_changed; /* Updated when new sec_index */ 85 ulong sec_index_used; /* which extra index are in use */ 86 ulonglong key_map; /* Which keys are in use */ 87 ha_checksum checksum; /* Table checksum */ 88 ulong version; /* timestamp of create */ 89 time_t create_time; /* Time when created database */ 90 time_t recover_time; /* Time for last recover */ 91 time_t check_time; /* Time for last check */ 92 uint sortkey; /* sorted by this key (not used) */ 93 uint open_count; 94 uint8 changed; /* Changed since myisamchk */ 95 96 /* the following isn't saved on disk */ 97 uint state_diff_length; /* Should be 0 */ 98 uint state_length; /* Length of state header in file */ 99 ulong *key_info; 100 } MI_STATE_INFO; 101 102 #define MI_STATE_INFO_SIZE (24+14*8+7*4+2*2+8) 103 #define MI_STATE_KEY_SIZE 8 104 #define MI_STATE_KEYBLOCK_SIZE 8 105 #define MI_STATE_KEYSEG_SIZE 4 106 #define MI_STATE_EXTRA_SIZE ((MI_MAX_KEY+MI_MAX_KEY_BLOCK_SIZE)*MI_STATE_KEY_SIZE + MI_MAX_KEY*MI_MAX_KEY_SEG*MI_STATE_KEYSEG_SIZE) 107 #define MI_KEYDEF_SIZE (2+ 5*2) 108 #define MI_UNIQUEDEF_SIZE (2+1+1) 109 #define HA_KEYSEG_SIZE (6+ 2*2 + 4*2) 110 #define MI_COLUMNDEF_SIZE (2*3+1) 111 #define MI_BASE_INFO_SIZE (5*8 + 8*4 + 4 + 4*2 + 16) 112 #define MI_INDEX_BLOCK_MARGIN 16 /* Safety margin for .MYI tables */ 113 114 typedef struct st_mi_base_info 115 { 116 my_off_t keystart; /* Start of keys */ 117 my_off_t max_data_file_length; 118 my_off_t max_key_file_length; 119 my_off_t margin_key_file_length; 120 ha_rows records,reloc; /* Create information */ 121 ulong mean_row_length; /* Create information */ 122 ulong reclength; /* length of unpacked record */ 123 ulong pack_reclength; /* Length of full packed rec. */ 124 ulong min_pack_length; 125 ulong max_pack_length; /* Max possibly length of packed rec.*/ 126 ulong min_block_length; 127 ulong fields, /* fields in table */ 128 pack_fields; /* packed fields in table */ 129 uint rec_reflength; /* = 2-8 */ 130 uint key_reflength; /* = 2-8 */ 131 uint keys; /* same as in state.header */ 132 uint auto_key; /* Which key-1 is a auto key */ 133 uint blobs; /* Number of blobs */ 134 uint pack_bits; /* Length of packed bits */ 135 uint max_key_block_length; /* Max block length */ 136 uint max_key_length; /* Max key length */ 137 /* Extra allocation when using dynamic record format */ 138 uint extra_alloc_bytes; 139 uint extra_alloc_procent; 140 /* The following are from the header */ 141 uint key_parts,all_key_parts; 142 } MI_BASE_INFO; 143 144 145 /* Structs used intern in database */ 146 147 typedef struct st_mi_blob /* Info of record */ 148 { 149 ulong offset; /* Offset to blob in record */ 150 uint pack_length; /* Type of packed length */ 151 ulong length; /* Calc:ed for each record */ 152 } MI_BLOB; 153 154 155 typedef struct st_mi_isam_pack { 156 ulong header_length; 157 uint ref_length; 158 uchar version; 159 } MI_PACK; 160 161 #define MAX_NONMAPPED_INSERTS 1000 162 163 typedef struct st_mi_isam_share { /* Shared between opens */ 164 MI_STATE_INFO state; 165 MI_BASE_INFO base; 166 MI_KEYDEF ft2_keyinfo; /* Second-level ft-key definition */ 167 MI_KEYDEF *keyinfo; /* Key definitions */ 168 MI_UNIQUEDEF *uniqueinfo; /* unique definitions */ 169 HA_KEYSEG *keyparts; /* key part info */ 170 MI_COLUMNDEF *rec; /* Pointer to field information */ 171 MI_PACK pack; /* Data about packed records */ 172 MI_BLOB *blobs; /* Pointer to blobs */ 173 LIST *in_use; /* List of threads using this table */ 174 char *unique_file_name; /* realpath() of index file */ 175 char *data_file_name, /* Resolved path names from symlinks */ 176 *index_file_name; 177 uchar *file_map; /* mem-map of file if possible */ 178 KEY_CACHE *key_cache; /* ref to the current key cache */ 179 MI_DECODE_TREE *decode_trees; 180 uint16 *decode_tables; 181 int (*read_record)(struct st_myisam_info*, my_off_t, uchar*); 182 int (*write_record)(struct st_myisam_info*, const uchar*); 183 int (*update_record)(struct st_myisam_info*, my_off_t, const uchar*); 184 int (*delete_record)(struct st_myisam_info*); 185 int (*read_rnd)(struct st_myisam_info*, uchar*, my_off_t, my_bool); 186 int (*compare_record)(struct st_myisam_info*, const uchar *); 187 /* Function to use for a row checksum. */ 188 ha_checksum (*calc_checksum)(struct st_myisam_info*, const uchar *); 189 int (*compare_unique)(struct st_myisam_info*, MI_UNIQUEDEF *, 190 const uchar *record, my_off_t pos); 191 size_t (*file_read)(MI_INFO *, uchar *, size_t, my_off_t, myf); 192 size_t (*file_write)(MI_INFO *, const uchar *, size_t, my_off_t, myf); 193 invalidator_by_filename invalidator; /* query cache invalidator */ 194 ulong this_process; /* processid */ 195 ulong last_process; /* For table-change-check */ 196 ulong last_version; /* Version on start */ 197 ulong options; /* Options used */ 198 ulong min_pack_length; /* Theese are used by packed data */ 199 ulong max_pack_length; 200 ulong state_diff_length; 201 uint rec_reflength; /* rec_reflength in use now */ 202 uint unique_name_length; 203 uint32 ftkeys; /* Number of full-text keys + 1 */ 204 File kfile; /* Shared keyfile */ 205 File data_file; /* Shared data file */ 206 int mode; /* mode of file on open */ 207 uint reopen; /* How many times reopened */ 208 uint w_locks,r_locks,tot_locks; /* Number of read/write locks */ 209 uint blocksize; /* blocksize of keyfile */ 210 myf write_flag; 211 enum data_file_type data_file_type; 212 /* Below flag is needed to make log tables work with concurrent insert */ 213 my_bool is_log_table; 214 215 my_bool changed, /* If changed since lock */ 216 global_changed, /* If changed since open */ 217 not_flushed, 218 temporary,delay_key_write, 219 concurrent_insert, 220 have_rtree; 221 222 THR_LOCK lock; 223 mysql_mutex_t intern_lock; /* Locking for use with _locking */ 224 mysql_rwlock_t *key_root_lock; 225 my_off_t mmaped_length; 226 uint nonmmaped_inserts; /* counter of writing in non-mmaped 227 area */ 228 mysql_rwlock_t mmap_lock; 229 } MYISAM_SHARE; 230 231 typedef uint mi_bit_type; 232 233 typedef struct st_mi_bit_buff { /* Used for packing of record */ 234 mi_bit_type current_byte; 235 uint bits; 236 uchar *pos,*end,*blob_pos,*blob_end; 237 uint error; 238 } MI_BIT_BUFF; 239 240 C_MODE_START 241 typedef ICP_RESULT (*index_cond_func_t)(void *param); 242 C_MODE_END 243 244 struct st_myisam_info { 245 MYISAM_SHARE *s; /* Shared between open:s */ 246 MI_STATUS_INFO *state,save_state; 247 MI_BLOB *blobs; /* Pointer to blobs */ 248 MI_BIT_BUFF bit_buff; 249 /* accumulate indexfile changes between write's */ 250 TREE *bulk_insert; 251 DYNAMIC_ARRAY *ft1_to_ft2; /* used only in ft1->ft2 conversion */ 252 MEM_ROOT ft_memroot; /* used by the parser */ 253 MYSQL_FTPARSER_PARAM *ftparser_param; /* share info between init/deinit */ 254 LIST in_use; /* Thread using this table */ 255 char *filename; /* parameter to open filename */ 256 uchar *buff, /* Temp area for key */ 257 *lastkey,*lastkey2; /* Last used search key */ 258 259 /* Key used in mi_rnext_same and filled by mi_rkey. */ 260 uchar *rnext_same_key; 261 uchar *first_mbr_key; /* Searhed spatial key */ 262 uchar *rec_buff; /* Tempbuff for recordpack */ 263 uchar *int_keypos, /* Save position for next/previous */ 264 *int_maxpos; /* -""- */ 265 uint int_nod_flag; /* -""- */ 266 uint32 int_keytree_version; /* -""- */ 267 int (*read_record)(struct st_myisam_info*, my_off_t, uchar*); 268 invalidator_by_filename invalidator; /* query cache invalidator */ 269 ulong this_unique; /* uniq filenumber or thread */ 270 ulong last_unique; /* last unique number */ 271 ulong this_loop; /* counter for this open */ 272 ulong last_loop; /* last used counter */ 273 my_off_t lastpos, /* Last record position */ 274 nextpos; /* Position to next record */ 275 my_off_t save_lastpos; 276 my_off_t pos; /* Intern variable */ 277 my_off_t last_keypage; /* Last key page read */ 278 my_off_t last_search_keypage; /* Last keypage when searching */ 279 my_off_t dupp_key_pos; 280 ha_checksum checksum; /* Temp storage for row checksum */ 281 /* QQ: the folloing two xxx_length fields should be removed, 282 as they are not compatible with parallel repair */ 283 ulong packed_length,blob_length; /* Length of found, packed record */ 284 int dfile; /* The datafile */ 285 uint opt_flag; /* Optim. for space/speed */ 286 uint update; /* If file changed since open */ 287 int lastinx; /* Last used index */ 288 uint lastkey_length; /* Length of key in lastkey */ 289 uint last_rkey_length; /* Last length in mi_rkey() */ 290 enum ha_rkey_function last_key_func; /* CONTAIN, OVERLAP, etc */ 291 uint save_lastkey_length; 292 uint pack_key_length; /* For MYISAMMRG */ 293 uint16 last_used_keyseg; /* For MyISAMMRG */ 294 int errkey; /* Got last error on this key */ 295 int lock_type; /* How database was locked */ 296 int tmp_lock_type; /* When locked by readinfo */ 297 uint data_changed; /* Somebody has changed data */ 298 uint save_update; /* When using KEY_READ */ 299 int save_lastinx; 300 LIST open_list; 301 IO_CACHE rec_cache; /* When cacheing records */ 302 uint preload_buff_size; /* When preloading indexes */ 303 myf lock_wait; /* is 0 or MY_DONT_WAIT */ 304 my_bool was_locked; /* Was locked in panic */ 305 my_bool append_insert_at_end; /* Set if concurrent insert */ 306 my_bool quick_mode; 307 my_bool page_changed; /* If info->buff can't be used for rnext */ 308 my_bool buff_used; /* If info->buff has to be reread for rnext */ 309 my_bool once_flags; /* For MYISAMMRG */ 310 311 /* Used in mi_rnext_same to fill rnext_same_key for the first time. */ 312 my_bool set_rnext_same_key; 313 314 index_cond_func_t index_cond_func; /* Index condition function */ 315 void *index_cond_func_arg; /* parameter for the func */ 316 #ifdef _WIN32 317 my_bool owned_by_merge; /* This MyISAM table is part of a merge union */ 318 #endif 319 THR_LOCK_DATA lock; 320 uchar *rtree_recursion_state; /* For RTREE */ 321 int rtree_recursion_depth; 322 }; 323 324 typedef struct st_buffpek { 325 my_off_t file_pos; /* Where we are in the sort file */ 326 uchar *base,*key; /* Key pointers */ 327 ha_rows count; /* Number of rows in table */ 328 ulong mem_count; /* numbers of keys in memory */ 329 ulong max_keys; /* Max keys in buffert */ 330 } BUFFPEK; 331 332 typedef struct st_mi_sort_param 333 { 334 my_thread_handle thr; 335 IO_CACHE read_cache, tempfile, tempfile_for_exceptions; 336 DYNAMIC_ARRAY buffpek; 337 MI_BIT_BUFF bit_buff; /* For parallel repair of packrec. */ 338 339 /* 340 The next two are used to collect statistics, see update_key_parts for 341 description. 342 */ 343 ulonglong unique[MI_MAX_KEY_SEG+1]; 344 ulonglong notnull[MI_MAX_KEY_SEG+1]; 345 ulonglong sortbuff_size; 346 347 my_off_t pos,max_pos,filepos,start_recpos; 348 uint key, key_length,real_key_length; 349 uint maxbuffers, keys, find_length, sort_keys_length; 350 my_bool fix_datafile, master; 351 my_bool calc_checksum; /* calculate table checksum */ 352 MI_KEYDEF *keyinfo; 353 HA_KEYSEG *seg; 354 SORT_INFO *sort_info; 355 uchar **sort_keys; 356 uchar *rec_buff; 357 void *wordlist, *wordptr; 358 MEM_ROOT wordroot; 359 uchar *record; 360 MY_TMPDIR *tmpdir; 361 int (*key_cmp)(struct st_mi_sort_param *, const void *, const void *); 362 int (*key_read)(struct st_mi_sort_param *,void *); 363 int (*key_write)(struct st_mi_sort_param *, const void *); 364 void (*lock_in_memory)(MI_CHECK *); 365 int (*write_keys)(struct st_mi_sort_param *, uchar **, 366 uint , struct st_buffpek *, IO_CACHE *); 367 uint (*read_to_buffer)(IO_CACHE *,struct st_buffpek *, uint); 368 int (*write_key)(struct st_mi_sort_param *, IO_CACHE *,uchar *, 369 uint, uint); 370 } MI_SORT_PARAM; 371 372 /* Some defines used by isam-funktions */ 373 374 #define USE_WHOLE_KEY MI_MAX_KEY_BUFF*2 /* Use whole key in _mi_search() */ 375 #define F_EXTRA_LCK -1 376 377 /* bits in opt_flag */ 378 #define MEMMAP_USED 32 379 #define REMEMBER_OLD_POS 64 380 381 #define WRITEINFO_UPDATE_KEYFILE 1 382 #define WRITEINFO_NO_UNLOCK 2 383 384 /* once_flags */ 385 #define USE_PACKED_KEYS 1 386 #define RRND_PRESERVE_LASTINX 2 387 388 /* bits in state.changed */ 389 390 #define STATE_CHANGED 1 391 #define STATE_CRASHED 2 392 #define STATE_CRASHED_ON_REPAIR 4 393 #define STATE_NOT_ANALYZED 8 394 #define STATE_NOT_OPTIMIZED_KEYS 16 395 #define STATE_NOT_SORTED_PAGES 32 396 397 /* options to mi_read_cache */ 398 399 #define READING_NEXT 1 400 #define READING_HEADER 2 401 402 #define mi_getint(x) ((uint) mi_uint2korr(x) & 32767) 403 #define mi_putint(x,y,nod) { uint16 boh=(nod ? (uint16) 32768 : 0) + (uint16) (y);\ 404 mi_int2store(x,boh); } 405 #define mi_test_if_nod(x) (x[0] & 128 ? info->s->base.key_reflength : 0) 406 #define mi_report_crashed(A, B) _mi_report_crashed((A), (B), __FILE__, __LINE__) 407 #define mi_mark_crashed(x) do{(x)->s->state.changed|= STATE_CRASHED; \ 408 DBUG_PRINT("error", ("Marked table crashed")); \ 409 mi_report_crashed((x), 0); \ 410 }while(0) 411 #define mi_mark_crashed_on_repair(x) do{(x)->s->state.changed|= \ 412 STATE_CRASHED|STATE_CRASHED_ON_REPAIR; \ 413 (x)->update|= HA_STATE_CHANGED; \ 414 DBUG_PRINT("error", \ 415 ("Marked table crashed")); \ 416 }while(0) 417 #define mi_is_crashed(x) ((x)->s->state.changed & STATE_CRASHED) 418 #define mi_is_crashed_on_repair(x) ((x)->s->state.changed & STATE_CRASHED_ON_REPAIR) 419 #define mi_print_error(SHARE, ERRNO) \ 420 mi_report_error((ERRNO), (SHARE)->index_file_name) 421 422 /* Functions to store length of space packed keys, VARCHAR or BLOB keys */ 423 424 #define store_key_length(key,length) \ 425 { if ((length) < 255) \ 426 { *(key)=(length); } \ 427 else \ 428 { *(key)=255; mi_int2store((key)+1,(length)); } \ 429 } 430 431 #define get_key_full_length(length,key) \ 432 { if ((uchar) *(key) != 255) \ 433 length= ((uint) (uchar) *((key)++))+1; \ 434 else \ 435 { length=mi_uint2korr((key)+1)+3; (key)+=3; } \ 436 } 437 438 #define get_key_full_length_rdonly(length,key) \ 439 { if ((uchar) *(key) != 255) \ 440 length= ((uint) (uchar) *((key)))+1; \ 441 else \ 442 { length=mi_uint2korr((key)+1)+3; } \ 443 } 444 445 #define get_pack_length(length) ((length) >= 255 ? 3 : 1) 446 447 #define MI_MIN_BLOCK_LENGTH 20 /* Because of delete-link */ 448 #define MI_EXTEND_BLOCK_LENGTH 20 /* Don't use to small record-blocks */ 449 #define MI_SPLIT_LENGTH ((MI_EXTEND_BLOCK_LENGTH+4)*2) 450 #define MI_MAX_DYN_BLOCK_HEADER 20 /* Max prefix of record-block */ 451 #define MI_BLOCK_INFO_HEADER_LENGTH 20 452 #define MI_DYN_DELETE_BLOCK_HEADER 20 /* length of delete-block-header */ 453 #define MI_DYN_MAX_BLOCK_LENGTH ((1L << 24)-4L) 454 #define MI_DYN_MAX_ROW_LENGTH (MI_DYN_MAX_BLOCK_LENGTH - MI_SPLIT_LENGTH) 455 #define MI_DYN_ALIGN_SIZE 4 /* Align blocks on this */ 456 #define MI_MAX_DYN_HEADER_BYTE 13 /* max header byte for dynamic rows */ 457 #define MI_MAX_BLOCK_LENGTH ((((ulong) 1 << 24)-1) & (~ (ulong) (MI_DYN_ALIGN_SIZE-1))) 458 #define MI_REC_BUFF_OFFSET ALIGN_SIZE(MI_DYN_DELETE_BLOCK_HEADER+sizeof(uint32)) 459 460 461 #define PACK_TYPE_SELECTED 1 /* Bits in field->pack_type */ 462 #define PACK_TYPE_SPACE_FIELDS 2 463 #define PACK_TYPE_ZERO_FILL 4 464 #define MI_FOUND_WRONG_KEY 32738 /* Impossible value from ha_key_cmp */ 465 466 #define MI_MAX_KEY_BLOCK_SIZE (MI_MAX_KEY_BLOCK_LENGTH/MI_MIN_KEY_BLOCK_LENGTH) 467 #define MI_BLOCK_SIZE(key_length,data_pointer,key_pointer,block_size) (((((key_length)+(data_pointer)+(key_pointer))*4+(key_pointer)+2)/(block_size)+1)*(block_size)) 468 #define MI_MAX_KEYPTR_SIZE 5 /* For calculating block lengths */ 469 #define MI_MIN_KEYBLOCK_LENGTH 50 /* When to split delete blocks */ 470 471 #define MI_MIN_SIZE_BULK_INSERT_TREE 16384 /* this is per key */ 472 #define MI_MIN_ROWS_TO_USE_BULK_INSERT 100 473 #define MI_MIN_ROWS_TO_DISABLE_INDEXES 100 474 #define MI_MIN_ROWS_TO_USE_WRITE_CACHE 10 475 476 /* The UNIQUE check is done with a hashed long key */ 477 478 #define MI_UNIQUE_HASH_TYPE HA_KEYTYPE_ULONG_INT 479 #define mi_unique_store(A,B) mi_int4store((A),(B)) 480 481 extern mysql_mutex_t THR_LOCK_myisam; 482 483 #ifdef __cplusplus 484 extern "C" { 485 #endif 486 487 /* Some extern variables */ 488 489 extern LIST *myisam_open_list; 490 extern uchar myisam_file_magic[], myisam_pack_file_magic[]; 491 extern uint myisam_read_vec[], myisam_readnext_vec[]; 492 extern uint myisam_quick_table_bits; 493 extern File myisam_log_file; 494 extern ulong myisam_pid; 495 496 /* This is used by _mi_calc_xxx_key_length och _mi_store_key */ 497 498 typedef struct st_mi_s_param 499 { 500 uint ref_length,key_length, 501 n_ref_length, 502 n_length, 503 totlength, 504 part_of_prev_key,prev_length,pack_marker; 505 uchar *key, *prev_key,*next_key_pos; 506 my_bool store_not_null; 507 } MI_KEY_PARAM; 508 509 /* Prototypes for intern functions */ 510 511 extern int _mi_read_dynamic_record(MI_INFO *info,my_off_t filepos,uchar *buf); 512 extern int _mi_write_dynamic_record(MI_INFO*, const uchar*); 513 extern int _mi_update_dynamic_record(MI_INFO*, my_off_t, const uchar*); 514 extern int _mi_delete_dynamic_record(MI_INFO *info); 515 extern int _mi_cmp_dynamic_record(MI_INFO *info,const uchar *record); 516 extern int _mi_read_rnd_dynamic_record(MI_INFO *, uchar *,my_off_t, my_bool); 517 extern int _mi_write_blob_record(MI_INFO*, const uchar*); 518 extern int _mi_update_blob_record(MI_INFO*, my_off_t, const uchar*); 519 extern int _mi_read_static_record(MI_INFO *info, my_off_t filepos,uchar *buf); 520 extern int _mi_write_static_record(MI_INFO*, const uchar*); 521 extern int _mi_update_static_record(MI_INFO*, my_off_t, const uchar*); 522 extern int _mi_delete_static_record(MI_INFO *info); 523 extern int _mi_cmp_static_record(MI_INFO *info,const uchar *record); 524 extern int _mi_read_rnd_static_record(MI_INFO*, uchar *,my_off_t, my_bool); 525 extern int _mi_ck_write(MI_INFO *info,uint keynr,uchar *key,uint length); 526 extern int _mi_ck_real_write_btree(MI_INFO *info, MI_KEYDEF *keyinfo, 527 uchar *key, uint key_length, 528 my_off_t *root, uint comp_flag); 529 extern int _mi_enlarge_root(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key, my_off_t *root); 530 extern int _mi_insert(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key, 531 uchar *anc_buff,uchar *key_pos,uchar *key_buff, 532 uchar *father_buff, uchar *father_keypos, 533 my_off_t father_page, my_bool insert_last); 534 extern int _mi_split_page(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key, 535 uchar *buff,uchar *key_buff, my_bool insert_last); 536 extern uchar *_mi_find_half_pos(uint nod_flag,MI_KEYDEF *keyinfo,uchar *page, 537 uchar *key,uint *return_key_length, 538 uchar **after_key); 539 extern int _mi_calc_static_key_length(MI_KEYDEF *keyinfo,uint nod_flag, 540 uchar *key_pos, uchar *org_key, 541 uchar *key_buff, 542 uchar *key, MI_KEY_PARAM *s_temp); 543 extern int _mi_calc_var_key_length(MI_KEYDEF *keyinfo,uint nod_flag, 544 uchar *key_pos, uchar *org_key, 545 uchar *key_buff, 546 uchar *key, MI_KEY_PARAM *s_temp); 547 extern int _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag, 548 uchar *key_pos, uchar *org_key, 549 uchar *prev_key, 550 uchar *key, MI_KEY_PARAM *s_temp); 551 extern int _mi_calc_bin_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag, 552 uchar *key_pos,uchar *org_key, 553 uchar *prev_key, 554 uchar *key, MI_KEY_PARAM *s_temp); 555 void _mi_store_static_key(MI_KEYDEF *keyinfo, uchar *key_pos, 556 MI_KEY_PARAM *s_temp); 557 void _mi_store_var_pack_key(MI_KEYDEF *keyinfo, uchar *key_pos, 558 MI_KEY_PARAM *s_temp); 559 void _mi_store_bin_pack_key(MI_KEYDEF *keyinfo, uchar *key_pos, 560 MI_KEY_PARAM *s_temp); 561 562 extern int _mi_ck_delete(MI_INFO *info,uint keynr,uchar *key,uint key_length); 563 extern int _mi_readinfo(MI_INFO *info,int lock_flag,int check_keybuffer); 564 extern int _mi_writeinfo(MI_INFO *info,uint options); 565 extern int _mi_test_if_changed(MI_INFO *info); 566 extern int _mi_mark_file_changed(MI_INFO *info); 567 extern int _mi_decrement_open_count(MI_INFO *info); 568 extern int _mi_check_index(MI_INFO *info,int inx); 569 extern int _mi_search(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key,uint key_len, 570 uint nextflag,my_off_t pos); 571 extern int _mi_bin_search(struct st_myisam_info *info,MI_KEYDEF *keyinfo, 572 uchar *page,uchar *key,uint key_len,uint comp_flag, 573 uchar * *ret_pos,uchar *buff, my_bool *was_last_key); 574 extern int _mi_seq_search(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *page, 575 uchar *key,uint key_len,uint comp_flag, 576 uchar **ret_pos,uchar *buff, my_bool *was_last_key); 577 extern int _mi_prefix_search(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *page, 578 uchar *key,uint key_len,uint comp_flag, 579 uchar **ret_pos,uchar *buff, my_bool *was_last_key); 580 extern my_off_t _mi_kpos(uint nod_flag,uchar *after_key); 581 extern void _mi_kpointer(MI_INFO *info,uchar *buff,my_off_t pos); 582 extern my_off_t _mi_dpos(MI_INFO *info, uint nod_flag,uchar *after_key); 583 extern my_off_t _mi_rec_pos(MYISAM_SHARE *info, uchar *ptr); 584 extern void _mi_dpointer(MI_INFO *info, uchar *buff,my_off_t pos); 585 extern int ha_key_cmp(HA_KEYSEG *keyseg, uchar *a,uchar *b, 586 uint key_length,uint nextflag,uint *diff_length); 587 extern uint _mi_get_static_key(MI_KEYDEF *keyinfo,uint nod_flag,uchar * *page, 588 uchar *key); 589 extern uint _mi_get_pack_key(MI_KEYDEF *keyinfo,uint nod_flag,uchar * *page, 590 uchar *key); 591 extern uint _mi_get_binary_pack_key(MI_KEYDEF *keyinfo, uint nod_flag, 592 uchar **page_pos, uchar *key); 593 extern uchar *_mi_get_last_key(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *keypos, 594 uchar *lastkey,uchar *endpos, 595 uint *return_key_length); 596 extern uchar *_mi_get_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, 597 uchar *key, uchar *keypos, uint *return_key_length); 598 extern uint _mi_keylength(MI_KEYDEF *keyinfo,uchar *key); 599 extern uint _mi_keylength_part(MI_KEYDEF *keyinfo, uchar *key, 600 HA_KEYSEG *end); 601 extern uchar *_mi_move_key(MI_KEYDEF *keyinfo,uchar *to,uchar *from); 602 extern int _mi_search_next(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key, 603 uint key_length,uint nextflag,my_off_t pos); 604 extern int _mi_search_first(MI_INFO *info,MI_KEYDEF *keyinfo,my_off_t pos); 605 extern int _mi_search_last(MI_INFO *info,MI_KEYDEF *keyinfo,my_off_t pos); 606 extern uchar *_mi_fetch_keypage(MI_INFO *info,MI_KEYDEF *keyinfo,my_off_t page, 607 int level,uchar *buff,int return_buffer); 608 extern int _mi_write_keypage(MI_INFO *info,MI_KEYDEF *keyinfo,my_off_t page, 609 int level, uchar *buff); 610 extern int _mi_dispose(MI_INFO *info,MI_KEYDEF *keyinfo,my_off_t pos, 611 int level); 612 extern my_off_t _mi_new(MI_INFO *info,MI_KEYDEF *keyinfo,int level); 613 extern uint _mi_make_key(MI_INFO *info,uint keynr,uchar *key, 614 const uchar *record,my_off_t filepos); 615 extern uint _mi_pack_key(MI_INFO *info, uint keynr, uchar *key, 616 uchar *old, key_part_map keypart_map, 617 HA_KEYSEG **last_used_keyseg); 618 extern int _mi_read_key_record(MI_INFO *info,my_off_t filepos,uchar *buf); 619 extern int _mi_read_cache(IO_CACHE *info,uchar *buff,my_off_t pos, 620 uint length,int re_read_if_possibly); 621 extern ulonglong retrieve_auto_increment(MI_INFO *info,const uchar *record); 622 623 extern uchar *mi_alloc_rec_buff(MI_INFO *,ulong, uchar**); 624 #define mi_get_rec_buff_ptr(info,buf) \ 625 ((((info)->s->options & HA_OPTION_PACK_RECORD) && (buf)) ? \ 626 (buf) - MI_REC_BUFF_OFFSET : (buf)) 627 #define mi_get_rec_buff_len(info,buf) \ 628 (*((uint32 *)(mi_get_rec_buff_ptr(info,buf)))) 629 630 extern ulong _mi_rec_unpack(MI_INFO *info,uchar *to,uchar *from, 631 ulong reclength); 632 extern my_bool _mi_rec_check(MI_INFO *info,const uchar *record, uchar *packpos, 633 ulong packed_length, my_bool with_checkum); 634 extern int _mi_write_part_record(MI_INFO *info,my_off_t filepos,ulong length, 635 my_off_t next_filepos,uchar **record, 636 ulong *reclength,int *flag); 637 extern void _mi_print_key(FILE *stream,HA_KEYSEG *keyseg,const uchar *key, 638 uint length); 639 extern my_bool _mi_read_pack_info(MI_INFO *info,pbool fix_keys); 640 extern int _mi_read_pack_record(MI_INFO *info,my_off_t filepos,uchar *buf); 641 extern int _mi_read_rnd_pack_record(MI_INFO*, uchar *,my_off_t, my_bool); 642 extern int _mi_pack_rec_unpack(MI_INFO *info, MI_BIT_BUFF *bit_buff, 643 uchar *to, uchar *from, ulong reclength); 644 extern ulonglong mi_safe_mul(ulonglong a,ulonglong b); 645 extern int _mi_ft_update(MI_INFO *info, uint keynr, uchar *keybuf, 646 const uchar *oldrec, const uchar *newrec, my_off_t pos); 647 648 #ifdef __cplusplus 649 } 650 #endif 651 652 struct st_sort_info; 653 654 655 typedef struct st_mi_block_info { /* Parameter to _mi_get_block_info */ 656 uchar header[MI_BLOCK_INFO_HEADER_LENGTH]; 657 ulong rec_len; 658 ulong data_len; 659 ulong block_len; 660 ulong blob_len; 661 my_off_t filepos; 662 my_off_t next_filepos; 663 my_off_t prev_filepos; 664 uint second_read; 665 uint offset; 666 } MI_BLOCK_INFO; 667 668 /* bits in return from _mi_get_block_info */ 669 670 #define BLOCK_FIRST 1 671 #define BLOCK_LAST 2 672 #define BLOCK_DELETED 4 673 #define BLOCK_ERROR 8 /* Wrong data */ 674 #define BLOCK_SYNC_ERROR 16 /* Right data at wrong place */ 675 #define BLOCK_FATAL_ERROR 32 /* hardware-error */ 676 677 #define NEED_MEM ((uint) 10*4*(IO_SIZE+32)+32) /* Nead for recursion */ 678 #define MAXERR 20 679 #define BUFFERS_WHEN_SORTING 16 /* Alloc for sort-key-tree */ 680 #define WRITE_COUNT MY_HOW_OFTEN_TO_WRITE 681 #define INDEX_TMP_EXT ".TMM" 682 #define DATA_TMP_EXT ".TMD" 683 684 #define UPDATE_TIME 1 685 #define UPDATE_STAT 2 686 #define UPDATE_SORT 4 687 #define UPDATE_AUTO_INC 8 688 #define UPDATE_OPEN_COUNT 16 689 690 #define USE_BUFFER_INIT (((1024L*512L-MALLOC_OVERHEAD)/IO_SIZE)*IO_SIZE) 691 #define READ_BUFFER_INIT (1024L*256L-MALLOC_OVERHEAD) 692 #define SORT_BUFFER_INIT (2048L*1024L-MALLOC_OVERHEAD) 693 #define MIN_SORT_BUFFER (4096-MALLOC_OVERHEAD) 694 695 enum myisam_log_commands { 696 MI_LOG_OPEN,MI_LOG_WRITE,MI_LOG_UPDATE,MI_LOG_DELETE,MI_LOG_CLOSE,MI_LOG_EXTRA,MI_LOG_LOCK,MI_LOG_DELETE_ALL 697 }; 698 699 #define myisam_log(a,b,c,d) if (myisam_log_file >= 0) _myisam_log(a,b,c,d) 700 #define myisam_log_command(a,b,c,d,e) if (myisam_log_file >= 0) _myisam_log_command(a,b,c,d,e) 701 #define myisam_log_record(a,b,c,d,e) if (myisam_log_file >= 0) _myisam_log_record(a,b,c,d,e) 702 703 #define fast_mi_writeinfo(INFO) if (!(INFO)->s->tot_locks) (void) _mi_writeinfo((INFO),0) 704 #define fast_mi_readinfo(INFO) ((INFO)->lock_type == F_UNLCK) && _mi_readinfo((INFO),F_RDLCK,1) 705 706 #ifdef __cplusplus 707 extern "C" { 708 #endif 709 710 extern uint _mi_get_block_info(MI_BLOCK_INFO *,File, my_off_t); 711 extern uint _mi_rec_pack(MI_INFO *info,uchar *to,const uchar *from); 712 extern uint _mi_pack_get_block_info(MI_INFO *myisam, MI_BIT_BUFF *bit_buff, 713 MI_BLOCK_INFO *info, uchar **rec_buff_p, 714 File file, my_off_t filepos); 715 extern void _mi_store_blob_length(uchar *pos,uint pack_length,uint length); 716 extern void _myisam_log(enum myisam_log_commands command,MI_INFO *info, 717 const uchar *buffert,uint length); 718 extern void _myisam_log_command(enum myisam_log_commands command, 719 MI_INFO *info, const uchar *buffert, 720 uint length, int result); 721 extern void _myisam_log_record(enum myisam_log_commands command,MI_INFO *info, 722 const uchar *record,my_off_t filepos, 723 int result); 724 extern void mi_report_error(int errcode, const char *file_name); 725 extern my_bool _mi_memmap_file(MI_INFO *info); 726 extern void _mi_unmap_file(MI_INFO *info); 727 extern uint save_pack_length(uint version, uchar *block_buff, ulong length); 728 extern uint read_pack_length(uint version, const uchar *buf, ulong *length); 729 extern uint calc_pack_length(uint version, ulong length); 730 extern size_t mi_mmap_pread(MI_INFO *info, uchar *Buffer, 731 size_t Count, my_off_t offset, myf MyFlags); 732 extern size_t mi_mmap_pwrite(MI_INFO *info, const uchar *Buffer, 733 size_t Count, my_off_t offset, myf MyFlags); 734 extern size_t mi_nommap_pread(MI_INFO *info, uchar *Buffer, 735 size_t Count, my_off_t offset, myf MyFlags); 736 extern size_t mi_nommap_pwrite(MI_INFO *info, const uchar *Buffer, 737 size_t Count, my_off_t offset, myf MyFlags); 738 739 uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite); 740 uchar *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state); 741 uint mi_state_info_read_dsk(File file, MI_STATE_INFO *state, my_bool pRead); 742 uint mi_base_info_write(File file, MI_BASE_INFO *base); 743 uchar *my_n_base_info_read(uchar *ptr, MI_BASE_INFO *base); 744 int mi_keyseg_write(File file, const HA_KEYSEG *keyseg); 745 uchar *mi_keyseg_read(uchar *ptr, HA_KEYSEG *keyseg); 746 uint mi_keydef_write(File file, MI_KEYDEF *keydef); 747 uchar *mi_keydef_read(uchar *ptr, MI_KEYDEF *keydef); 748 uint mi_uniquedef_write(File file, MI_UNIQUEDEF *keydef); 749 uchar *mi_uniquedef_read(uchar *ptr, MI_UNIQUEDEF *keydef); 750 uint mi_recinfo_write(File file, MI_COLUMNDEF *recinfo); 751 uchar *mi_recinfo_read(uchar *ptr, MI_COLUMNDEF *recinfo); 752 extern int mi_disable_indexes(MI_INFO *info); 753 extern int mi_enable_indexes(MI_INFO *info); 754 extern int mi_indexes_are_disabled(MI_INFO *info); 755 ulong _my_calc_total_blob_length(MI_INFO *info, const uchar *record); 756 ha_checksum mi_checksum(MI_INFO *info, const uchar *buf); 757 ha_checksum mi_static_checksum(MI_INFO *info, const uchar *buf); 758 my_bool mi_check_unique(MI_INFO *info, MI_UNIQUEDEF *def, uchar *record, 759 ha_checksum unique_hash, my_off_t pos); 760 ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const uchar *buf); 761 int _mi_cmp_static_unique(MI_INFO *info, MI_UNIQUEDEF *def, 762 const uchar *record, my_off_t pos); 763 int _mi_cmp_dynamic_unique(MI_INFO *info, MI_UNIQUEDEF *def, 764 const uchar *record, my_off_t pos); 765 int mi_unique_comp(MI_UNIQUEDEF *def, const uchar *a, const uchar *b, 766 my_bool null_are_equal); 767 void mi_get_status(void* param, int concurrent_insert); 768 void mi_update_status(void* param); 769 void mi_restore_status(void* param); 770 void mi_copy_status(void* to,void *from); 771 my_bool mi_check_status(void* param); 772 void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows); 773 774 extern MI_INFO *test_if_reopen(char *filename); 775 my_bool check_table_is_closed(const char *name, const char *where); 776 int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, const char *orn_name, 777 File file_to_dup); 778 779 int mi_open_keyfile(MYISAM_SHARE *share); 780 void mi_setup_functions(MYISAM_SHARE *share); 781 my_bool mi_dynmap_file(MI_INFO *info, my_off_t size); 782 int mi_munmap_file(MI_INFO *info); 783 void mi_remap_file(MI_INFO *info, my_off_t size); 784 void _mi_report_crashed(MI_INFO *file, const char *message, 785 const char *sfile, uint sline); 786 787 int mi_check_index_cond(MI_INFO *info, uint keynr, uchar *record); 788 789 /* Functions needed by mi_check */ 790 volatile int *killed_ptr(MI_CHECK *param); 791 void mi_check_print_error(MI_CHECK *param, const char *fmt,...); 792 void mi_check_print_warning(MI_CHECK *param, const char *fmt,...); 793 void mi_check_print_info(MI_CHECK *param, const char *fmt,...); 794 int flush_pending_blocks(MI_SORT_PARAM *param); 795 int sort_ft_buf_flush(MI_SORT_PARAM *sort_param); 796 int thr_write_keys(MI_SORT_PARAM *sort_param); 797 void *thr_find_all_keys(void *arg); 798 int flush_blocks(MI_CHECK *param, KEY_CACHE *key_cache, File file); 799 800 int sort_write_record(MI_SORT_PARAM *sort_param); 801 int _create_index_by_sort(MI_SORT_PARAM *info, my_bool no_messages, ulonglong); 802 803 extern void mi_set_index_cond_func(MI_INFO *info, index_cond_func_t func, 804 void *func_arg); 805 806 extern thread_local_key_t keycache_tls_key; 807 #ifdef __cplusplus 808 } 809 #endif 810 811 #ifdef HAVE_PSI_INTERFACE 812 C_MODE_START 813 extern PSI_mutex_key mi_key_mutex_MYISAM_SHARE_intern_lock, 814 mi_key_mutex_MI_SORT_INFO_mutex, mi_key_mutex_MI_CHECK_print_msg; 815 816 extern PSI_rwlock_key mi_key_rwlock_MYISAM_SHARE_key_root_lock, 817 mi_key_rwlock_MYISAM_SHARE_mmap_lock; 818 819 extern PSI_cond_key mi_key_cond_MI_SORT_INFO_cond, 820 mi_keycache_thread_var_suspend; 821 822 extern PSI_file_key mi_key_file_datatmp, mi_key_file_dfile, mi_key_file_kfile, 823 mi_key_file_log; 824 825 extern PSI_thread_key mi_key_thread_find_all_keys; 826 827 void init_myisam_psi_keys(); 828 C_MODE_END 829 #endif /* HAVE_PSI_INTERFACE */ 830 831 C_MODE_START 832 833 extern PSI_memory_key mi_key_memory_MYISAM_SHARE; 834 extern PSI_memory_key mi_key_memory_MI_INFO; 835 extern PSI_memory_key mi_key_memory_MI_INFO_ft1_to_ft2; 836 extern PSI_memory_key mi_key_memory_MI_INFO_bulk_insert; 837 extern PSI_memory_key mi_key_memory_record_buffer; 838 extern PSI_memory_key mi_key_memory_FTB; 839 extern PSI_memory_key mi_key_memory_FT_INFO; 840 extern PSI_memory_key mi_key_memory_FTPARSER_PARAM; 841 extern PSI_memory_key mi_key_memory_ft_memroot; 842 extern PSI_memory_key mi_key_memory_ft_stopwords; 843 extern PSI_memory_key mi_key_memory_MI_SORT_PARAM; 844 extern PSI_memory_key mi_key_memory_MI_SORT_PARAM_wordroot; 845 extern PSI_memory_key mi_key_memory_SORT_FT_BUF; 846 extern PSI_memory_key mi_key_memory_SORT_KEY_BLOCKS; 847 extern PSI_memory_key mi_key_memory_filecopy; 848 extern PSI_memory_key mi_key_memory_SORT_INFO_buffer; 849 extern PSI_memory_key mi_key_memory_MI_DECODE_TREE; 850 extern PSI_memory_key mi_key_memory_MYISAM_SHARE_decode_tables; 851 extern PSI_memory_key mi_key_memory_preload_buffer; 852 extern PSI_memory_key mi_key_memory_stPageList_pages; 853 extern PSI_memory_key mi_key_memory_keycache_thread_var; 854 855 C_MODE_END 856 857