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