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