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