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