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