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