2 Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
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.
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.
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
18 /* open a isam-database */
25 #if defined(MSDOS) || defined(__WIN__)
29 #include <process.h> /* Prototype for getpid */
36 static void setup_key_functions(MI_KEYDEF
*keyinfo
);
37 #define get_next_element(to,pos,size) { memcpy((char*) to,pos,(size_t) size); \
41 #define disk_pos_assert(pos, end_pos) \
44 my_errno=HA_ERR_CRASHED; \
49 /******************************************************************************
50 ** Return the shared struct if the table is already open.
51 ** In MySQL the server will handle version issues.
52 ******************************************************************************/
54 MI_INFO
*test_if_reopen(char *filename
)
58 for (pos
=myisam_open_list
; pos
; pos
=pos
->next
)
60 MI_INFO
*info
=(MI_INFO
*) pos
->data
;
61 MYISAM_SHARE
*share
=info
->s
;
62 if (!strcmp(share
->unique_file_name
,filename
) && share
->last_version
)
69 /******************************************************************************
70 open a MyISAM database.
71 See my_base.h for the handle_locking argument
72 if handle_locking and HA_OPEN_ABORT_IF_CRASHED then abort if the table
73 is marked crashed or if we are not using locking and the table doesn't
74 have an open count of 0.
75 ******************************************************************************/
77 MI_INFO
*mi_open(const char *name
, int mode
, uint open_flags
)
79 int lock_error
,kfile
,open_mode
,save_errno
,have_rtree
=0, realpath_err
;
80 uint i
,j
,len
,errpos
,head_length
,base_pos
,offset
,info_length
,keys
,
81 key_parts
,unique_key_parts
,fulltext_keys
,uniques
;
82 char name_buff
[FN_REFLEN
], org_name
[FN_REFLEN
], index_name
[FN_REFLEN
],
84 uchar
*disk_cache
, *disk_pos
, *end_pos
;
85 MI_INFO info
,*m_info
,*old_info
;
86 MYISAM_SHARE share_buff
,*share
;
87 ulong rec_per_key_part
[HA_MAX_POSSIBLE_KEY
*MI_MAX_KEY_SEG
];
88 my_off_t key_root
[HA_MAX_POSSIBLE_KEY
],key_del
[MI_MAX_KEY_BLOCK_SIZE
];
89 ulonglong max_key_file_length
, max_data_file_length
;
90 DBUG_ENTER("mi_open");
96 head_length
=sizeof(share_buff
.state
.header
);
97 bzero((uchar
*) &info
,sizeof(info
));
99 realpath_err
= my_realpath(name_buff
,
100 fn_format(org_name
,name
,"",MI_NAME_IEXT
,4),MYF(0));
101 if (my_is_symlink(org_name
) &&
102 (realpath_err
|| (*myisam_test_invalid_symlink
)(name_buff
)))
104 my_errno
= HA_WRONG_CREATE_OPTION
;
108 pthread_mutex_lock(&THR_LOCK_myisam
);
109 if (!(old_info
=test_if_reopen(name_buff
)))
112 bzero((uchar
*) &share_buff
,sizeof(share_buff
));
113 share_buff
.state
.rec_per_key_part
=rec_per_key_part
;
114 share_buff
.state
.key_root
=key_root
;
115 share_buff
.state
.key_del
=key_del
;
116 share_buff
.key_cache
= multi_key_cache_search((uchar
*) name_buff
,
119 DBUG_EXECUTE_IF("myisam_pretend_crashed_table_on_open",
120 if (strstr(name
, "/t1"))
122 my_errno
= HA_ERR_CRASHED
;
125 if ((kfile
=my_open(name_buff
,(open_mode
=O_RDWR
) | O_SHARE
,MYF(0))) < 0)
127 if ((errno
!= EROFS
&& errno
!= EACCES
) ||
129 (kfile
=my_open(name_buff
,(open_mode
=O_RDONLY
) | O_SHARE
,MYF(0))) < 0)
132 share
->mode
=open_mode
;
134 if (my_read(kfile
, share
->state
.header
.file_version
, head_length
,
137 my_errno
= HA_ERR_NOT_A_TABLE
;
140 if (memcmp((uchar
*) share
->state
.header
.file_version
,
141 (uchar
*) myisam_file_magic
, 4))
143 DBUG_PRINT("error",("Wrong header in %s",name_buff
));
144 DBUG_DUMP("error_dump", share
->state
.header
.file_version
,
146 my_errno
=HA_ERR_NOT_A_TABLE
;
149 share
->options
= mi_uint2korr(share
->state
.header
.options
);
151 ~(HA_OPTION_PACK_RECORD
| HA_OPTION_PACK_KEYS
|
152 HA_OPTION_COMPRESS_RECORD
| HA_OPTION_READ_ONLY_DATA
|
153 HA_OPTION_TEMP_COMPRESS_RECORD
| HA_OPTION_CHECKSUM
|
154 HA_OPTION_TMP_TABLE
| HA_OPTION_DELAY_KEY_WRITE
|
155 HA_OPTION_RELIES_ON_SQL_LAYER
))
157 DBUG_PRINT("error",("wrong options: 0x%lx", share
->options
));
158 my_errno
=HA_ERR_OLD_FILE
;
161 if ((share
->options
& HA_OPTION_RELIES_ON_SQL_LAYER
) &&
162 ! (open_flags
& HA_OPEN_FROM_SQL_LAYER
))
164 DBUG_PRINT("error", ("table cannot be openned from non-sql layer"));
165 my_errno
= HA_ERR_UNSUPPORTED
;
168 /* Don't call realpath() if the name can't be a link */
169 if (!strcmp(name_buff
, org_name
) ||
170 my_readlink(index_name
, org_name
, MYF(0)) == -1)
171 (void) strmov(index_name
, org_name
);
172 *strrchr(org_name
, '.')= '\0';
173 (void) fn_format(data_name
,org_name
,"",MI_NAME_DEXT
,
174 MY_APPEND_EXT
|MY_UNPACK_FILENAME
|MY_RESOLVE_SYMLINKS
);
176 info_length
=mi_uint2korr(share
->state
.header
.header_length
);
177 base_pos
=mi_uint2korr(share
->state
.header
.base_pos
);
178 if (!(disk_cache
= (uchar
*) my_alloca(info_length
+128)))
183 end_pos
=disk_cache
+info_length
;
186 VOID(my_seek(kfile
,0L,MY_SEEK_SET
,MYF(0)));
187 if (!(open_flags
& HA_OPEN_TMP_TABLE
))
189 if ((lock_error
=my_lock(kfile
,F_RDLCK
,0L,F_TO_EOF
,
190 MYF(open_flags
& HA_OPEN_WAIT_IF_LOCKED
?
191 0 : MY_DONT_WAIT
))) &&
192 !(open_flags
& HA_OPEN_IGNORE_IF_LOCKED
))
196 if (my_read(kfile
,disk_cache
,info_length
,MYF(MY_NABP
)))
198 my_errno
=HA_ERR_CRASHED
;
201 len
=mi_uint2korr(share
->state
.header
.state_info_length
);
202 keys
= (uint
) share
->state
.header
.keys
;
203 uniques
= (uint
) share
->state
.header
.uniques
;
204 fulltext_keys
= (uint
) share
->state
.header
.fulltext_keys
;
205 key_parts
= mi_uint2korr(share
->state
.header
.key_parts
);
206 unique_key_parts
= mi_uint2korr(share
->state
.header
.unique_key_parts
);
207 if (len
!= MI_STATE_INFO_SIZE
)
209 DBUG_PRINT("warning",
210 ("saved_state_info_length: %d state_info_length: %d",
211 len
,MI_STATE_INFO_SIZE
));
213 share
->state_diff_length
=len
-MI_STATE_INFO_SIZE
;
215 mi_state_info_read(disk_cache
, &share
->state
);
216 len
= mi_uint2korr(share
->state
.header
.base_info_length
);
217 if (len
!= MI_BASE_INFO_SIZE
)
219 DBUG_PRINT("warning",("saved_base_info_length: %d base_info_length: %d",
220 len
,MI_BASE_INFO_SIZE
));
222 disk_pos
= my_n_base_info_read(disk_cache
+ base_pos
, &share
->base
);
223 share
->state
.state_length
=base_pos
;
225 if (!(open_flags
& HA_OPEN_FOR_REPAIR
) &&
226 ((share
->state
.changed
& STATE_CRASHED
) ||
227 ((open_flags
& HA_OPEN_ABORT_IF_CRASHED
) &&
228 (my_disable_locking
&& share
->state
.open_count
))))
230 DBUG_PRINT("error",("Table is marked as crashed. open_flags: %u "
231 "changed: %u open_count: %u !locking: %d",
232 open_flags
, share
->state
.changed
,
233 share
->state
.open_count
, my_disable_locking
));
234 my_errno
=((share
->state
.changed
& STATE_CRASHED_ON_REPAIR
) ?
235 HA_ERR_CRASHED_ON_REPAIR
: HA_ERR_CRASHED_ON_USAGE
);
240 if (share
->base
.keystart
> 65535 || share
->base
.rec_reflength
> 8)
242 my_errno
=HA_ERR_CRASHED
;
246 key_parts
+=fulltext_keys
*FT_SEGS
;
247 if (share
->base
.max_key_length
> MI_MAX_KEY_BUFF
|| keys
> MI_MAX_KEY
||
248 key_parts
> MI_MAX_KEY
* MI_MAX_KEY_SEG
)
250 DBUG_PRINT("error",("Wrong key info: Max_key_length: %d keys: %d key_parts: %d", share
->base
.max_key_length
, keys
, key_parts
));
251 my_errno
=HA_ERR_UNSUPPORTED
;
255 /* Correct max_file_length based on length of sizeof(off_t) */
256 max_data_file_length
=
257 (share
->options
& (HA_OPTION_PACK_RECORD
| HA_OPTION_COMPRESS_RECORD
)) ?
258 (((ulonglong
) 1 << (share
->base
.rec_reflength
*8))-1) :
259 (mi_safe_mul(share
->base
.pack_reclength
,
260 (ulonglong
) 1 << (share
->base
.rec_reflength
*8))-1);
262 mi_safe_mul(MI_MIN_KEY_BLOCK_LENGTH
,
263 ((ulonglong
) 1 << (share
->base
.key_reflength
*8))-1);
264 #if SIZEOF_OFF_T == 4
265 set_if_smaller(max_data_file_length
, INT_MAX32
);
266 set_if_smaller(max_key_file_length
, INT_MAX32
);
268 #if USE_RAID && SYSTEM_SIZEOF_OFF_T == 4
269 set_if_smaller(max_key_file_length
, INT_MAX32
);
270 if (!share
->base
.raid_type
)
272 set_if_smaller(max_data_file_length
, INT_MAX32
);
276 set_if_smaller(max_data_file_length
,
277 (ulonglong
) share
->base
.raid_chunks
<< 31);
279 #elif !defined(USE_RAID)
280 if (share
->base
.raid_type
)
282 DBUG_PRINT("error",("Table uses RAID but we don't have RAID support"));
283 my_errno
=HA_ERR_UNSUPPORTED
;
287 share
->base
.max_data_file_length
=(my_off_t
) max_data_file_length
;
288 share
->base
.max_key_file_length
=(my_off_t
) max_key_file_length
;
290 if (share
->options
& HA_OPTION_COMPRESS_RECORD
)
291 share
->base
.max_key_length
+=2; /* For safety */
293 /* Add space for node pointer */
294 share
->base
.max_key_length
+= share
->base
.key_reflength
;
296 if (!my_multi_malloc(MY_WME
,
297 &share
,sizeof(*share
),
298 &share
->state
.rec_per_key_part
,sizeof(long)*key_parts
,
299 &share
->keyinfo
,keys
*sizeof(MI_KEYDEF
),
300 &share
->uniqueinfo
,uniques
*sizeof(MI_UNIQUEDEF
),
302 (key_parts
+unique_key_parts
+keys
+uniques
) *
305 (share
->base
.fields
+1)*sizeof(MI_COLUMNDEF
),
306 &share
->blobs
,sizeof(MI_BLOB
)*share
->base
.blobs
,
307 &share
->unique_file_name
,strlen(name_buff
)+1,
308 &share
->index_file_name
,strlen(index_name
)+1,
309 &share
->data_file_name
,strlen(data_name
)+1,
310 &share
->state
.key_root
,keys
*sizeof(my_off_t
),
311 &share
->state
.key_del
,
312 (share
->state
.header
.max_block_size_index
*sizeof(my_off_t
)),
314 &share
->key_root_lock
,sizeof(rw_lock_t
)*keys
,
316 &share
->mmap_lock
,sizeof(rw_lock_t
),
321 memcpy((char*) share
->state
.rec_per_key_part
,
322 (char*) rec_per_key_part
, sizeof(long)*key_parts
);
323 memcpy((char*) share
->state
.key_root
,
324 (char*) key_root
, sizeof(my_off_t
)*keys
);
325 memcpy((char*) share
->state
.key_del
,
326 (char*) key_del
, (sizeof(my_off_t
) *
327 share
->state
.header
.max_block_size_index
));
328 strmov(share
->unique_file_name
, name_buff
);
329 share
->unique_name_length
= strlen(name_buff
);
330 strmov(share
->index_file_name
, index_name
);
331 strmov(share
->data_file_name
, data_name
);
333 share
->blocksize
=min(IO_SIZE
,myisam_block_size
);
335 HA_KEYSEG
*pos
=share
->keyparts
;
337 for (i
=0 ; i
< keys
; i
++)
339 share
->keyinfo
[i
].share
= share
;
340 disk_pos
=mi_keydef_read(disk_pos
, &share
->keyinfo
[i
]);
341 disk_pos_assert(disk_pos
+ share
->keyinfo
[i
].keysegs
* HA_KEYSEG_SIZE
,
343 if (share
->keyinfo
[i
].key_alg
== HA_KEY_ALG_RTREE
)
345 set_if_smaller(share
->blocksize
,share
->keyinfo
[i
].block_length
);
346 share
->keyinfo
[i
].seg
=pos
;
347 for (j
=0 ; j
< share
->keyinfo
[i
].keysegs
; j
++,pos
++)
349 disk_pos
=mi_keyseg_read(disk_pos
, pos
);
350 if (pos
->flag
& HA_BLOB_PART
&&
351 ! (share
->options
& (HA_OPTION_COMPRESS_RECORD
|
352 HA_OPTION_PACK_RECORD
)))
354 my_errno
= HA_ERR_CRASHED
;
357 if (pos
->type
== HA_KEYTYPE_TEXT
||
358 pos
->type
== HA_KEYTYPE_VARTEXT1
||
359 pos
->type
== HA_KEYTYPE_VARTEXT2
)
362 pos
->charset
=default_charset_info
;
363 else if (!(pos
->charset
= get_charset(pos
->language
, MYF(MY_WME
))))
365 my_errno
=HA_ERR_UNKNOWN_CHARSET
;
369 else if (pos
->type
== HA_KEYTYPE_BINARY
)
370 pos
->charset
= &my_charset_bin
;
372 if (share
->keyinfo
[i
].flag
& HA_SPATIAL
)
375 uint sp_segs
=SPDIMS
*2;
376 share
->keyinfo
[i
].seg
=pos
-sp_segs
;
377 share
->keyinfo
[i
].keysegs
--;
379 my_errno
=HA_ERR_UNSUPPORTED
;
383 else if (share
->keyinfo
[i
].flag
& HA_FULLTEXT
)
386 { /* 4.0 compatibility code, to be removed in 5.0 */
387 share
->keyinfo
[i
].seg
=pos
-FT_SEGS
;
388 share
->keyinfo
[i
].keysegs
-=FT_SEGS
;
393 share
->keyinfo
[i
].seg
=pos
;
394 for (k
=0; k
< FT_SEGS
; k
++)
397 pos
[0].language
= pos
[-1].language
;
398 if (!(pos
[0].charset
= pos
[-1].charset
))
400 my_errno
=HA_ERR_CRASHED
;
406 if (!share
->ft2_keyinfo
.seg
)
408 memcpy(& share
->ft2_keyinfo
, & share
->keyinfo
[i
], sizeof(MI_KEYDEF
));
409 share
->ft2_keyinfo
.keysegs
=1;
410 share
->ft2_keyinfo
.flag
=0;
411 share
->ft2_keyinfo
.keylength
=
412 share
->ft2_keyinfo
.minlength
=
413 share
->ft2_keyinfo
.maxlength
=HA_FT_WLEN
+share
->base
.rec_reflength
;
414 share
->ft2_keyinfo
.seg
=pos
-1;
415 share
->ft2_keyinfo
.end
=pos
;
416 setup_key_functions(& share
->ft2_keyinfo
);
418 share
->keyinfo
[i
].ftkey_nr
= ftkey_nr
++;
420 setup_key_functions(share
->keyinfo
+i
);
421 share
->keyinfo
[i
].end
=pos
;
422 pos
->type
=HA_KEYTYPE_END
; /* End */
423 pos
->length
=share
->base
.rec_reflength
;
425 pos
->flag
=0; /* For purify */
429 for (i
=0 ; i
< uniques
; i
++)
431 disk_pos
=mi_uniquedef_read(disk_pos
, &share
->uniqueinfo
[i
]);
432 disk_pos_assert(disk_pos
+ share
->uniqueinfo
[i
].keysegs
*
433 HA_KEYSEG_SIZE
, end_pos
);
434 share
->uniqueinfo
[i
].seg
=pos
;
435 for (j
=0 ; j
< share
->uniqueinfo
[i
].keysegs
; j
++,pos
++)
437 disk_pos
=mi_keyseg_read(disk_pos
, pos
);
438 if (pos
->type
== HA_KEYTYPE_TEXT
||
439 pos
->type
== HA_KEYTYPE_VARTEXT1
||
440 pos
->type
== HA_KEYTYPE_VARTEXT2
)
443 pos
->charset
=default_charset_info
;
444 else if (!(pos
->charset
= get_charset(pos
->language
, MYF(MY_WME
))))
446 my_errno
=HA_ERR_UNKNOWN_CHARSET
;
451 share
->uniqueinfo
[i
].end
=pos
;
452 pos
->type
=HA_KEYTYPE_END
; /* End */
457 share
->ftkeys
= ftkey_nr
;
460 disk_pos_assert(disk_pos
+ share
->base
.fields
*MI_COLUMNDEF_SIZE
, end_pos
);
461 for (i
=j
=offset
=0 ; i
< share
->base
.fields
; i
++)
463 disk_pos
=mi_recinfo_read(disk_pos
,&share
->rec
[i
]);
464 share
->rec
[i
].pack_type
=0;
465 share
->rec
[i
].huff_tree
=0;
466 share
->rec
[i
].offset
=offset
;
467 if (share
->rec
[i
].type
== (int) FIELD_BLOB
)
469 share
->blobs
[j
].pack_length
=
470 share
->rec
[i
].length
-portable_sizeof_char_ptr
;
471 share
->blobs
[j
].offset
=offset
;
474 offset
+=share
->rec
[i
].length
;
476 share
->rec
[i
].type
=(int) FIELD_LAST
; /* End marker */
477 if (offset
> share
->base
.reclength
)
479 /* purecov: begin inspected */
480 my_errno
= HA_ERR_CRASHED
;
487 VOID(my_lock(kfile
,F_UNLCK
,0L,F_TO_EOF
,MYF(MY_SEEK_NOT_DONE
)));
488 lock_error
=1; /* Database unlocked */
491 if (mi_open_datafile(&info
, share
, name
, -1))
496 share
->this_process
=(ulong
) getpid();
497 share
->last_process
= share
->state
.process
;
498 share
->base
.key_parts
=key_parts
;
499 share
->base
.all_key_parts
=key_parts
+unique_key_parts
;
500 if (!(share
->last_version
=share
->state
.version
))
501 share
->last_version
=1; /* Safety */
502 share
->rec_reflength
=share
->base
.rec_reflength
; /* May be changed */
503 share
->base
.margin_key_file_length
=(share
->base
.max_key_file_length
-
504 (keys
? MI_INDEX_BLOCK_MARGIN
*
505 share
->blocksize
* keys
: 0));
506 share
->blocksize
=min(IO_SIZE
,myisam_block_size
);
507 share
->data_file_type
=STATIC_RECORD
;
508 if (share
->options
& HA_OPTION_COMPRESS_RECORD
)
510 share
->data_file_type
= COMPRESSED_RECORD
;
511 share
->options
|= HA_OPTION_READ_ONLY_DATA
;
513 if (_mi_read_pack_info(&info
,
515 test(!(share
->options
&
516 (HA_OPTION_PACK_RECORD
|
517 HA_OPTION_TEMP_COMPRESS_RECORD
)))))
520 else if (share
->options
& HA_OPTION_PACK_RECORD
)
521 share
->data_file_type
= DYNAMIC_RECORD
;
522 my_afree(disk_cache
);
523 mi_setup_functions(share
);
524 share
->is_log_table
= FALSE
;
526 thr_lock_init(&share
->lock
);
527 VOID(pthread_mutex_init(&share
->intern_lock
,MY_MUTEX_INIT_FAST
));
528 for (i
=0; i
<keys
; i
++)
529 VOID(my_rwlock_init(&share
->key_root_lock
[i
], NULL
));
530 VOID(my_rwlock_init(&share
->mmap_lock
, NULL
));
531 if (!thr_lock_inited
)
533 /* Probably a single threaded program; Don't use concurrent inserts */
534 myisam_concurrent_insert
=0;
536 else if (myisam_concurrent_insert
)
538 share
->concurrent_insert
=
539 ((share
->options
& (HA_OPTION_READ_ONLY_DATA
| HA_OPTION_TMP_TABLE
|
540 HA_OPTION_COMPRESS_RECORD
|
541 HA_OPTION_TEMP_COMPRESS_RECORD
)) ||
542 (open_flags
& HA_OPEN_TMP_TABLE
) ||
544 if (share
->concurrent_insert
)
546 share
->lock
.get_status
=mi_get_status
;
547 share
->lock
.copy_status
=mi_copy_status
;
548 share
->lock
.update_status
=mi_update_status
;
549 share
->lock
.restore_status
= mi_restore_status
;
550 share
->lock
.check_status
=mi_check_status
;
555 Memory mapping can only be requested after initializing intern_lock.
557 if (open_flags
& HA_OPEN_MMAP
)
560 mi_extra(&info
, HA_EXTRA_MMAP
, 0);
566 if (mode
== O_RDWR
&& share
->mode
== O_RDONLY
)
568 my_errno
=EACCES
; /* Can't open in write mode */
571 if (mi_open_datafile(&info
, share
, name
, old_info
->dfile
))
574 have_rtree
= old_info
->rtree_recursion_state
!= NULL
;
577 /* alloc and set up private structure parts */
578 if (!my_multi_malloc(MY_WME
,
579 &m_info
,sizeof(MI_INFO
),
580 &info
.blobs
,sizeof(MI_BLOB
)*share
->base
.blobs
,
581 &info
.buff
,(share
->base
.max_key_block_length
*2+
582 share
->base
.max_key_length
),
583 &info
.lastkey
,share
->base
.max_key_length
*3+1,
584 &info
.first_mbr_key
, share
->base
.max_key_length
,
585 &info
.filename
,strlen(name
)+1,
586 &info
.rtree_recursion_state
,have_rtree
? 1024 : 0,
592 info
.rtree_recursion_state
= NULL
;
594 strmov(info
.filename
,name
);
595 memcpy(info
.blobs
,share
->blobs
,sizeof(MI_BLOB
)*share
->base
.blobs
);
596 info
.lastkey2
=info
.lastkey
+share
->base
.max_key_length
;
599 info
.lastpos
= HA_OFFSET_ERROR
;
600 info
.update
= (short) (HA_STATE_NEXT_FOUND
+HA_STATE_PREV_FOUND
);
601 info
.opt_flag
=READ_CHECK_USED
;
602 info
.this_unique
= (ulong
) info
.dfile
; /* Uniq number in process */
603 if (share
->data_file_type
== COMPRESSED_RECORD
)
604 info
.this_unique
= share
->state
.unique
;
605 info
.this_loop
=0; /* Update counter */
606 info
.last_unique
= share
->state
.unique
;
607 info
.last_loop
= share
->state
.update_count
;
608 if (mode
== O_RDONLY
)
609 share
->options
|=HA_OPTION_READ_ONLY_DATA
;
610 info
.lock_type
=F_UNLCK
;
616 pthread_mutex_lock(&share
->intern_lock
);
617 info
.read_record
=share
->read_record
;
619 share
->write_flag
=MYF(MY_NABP
| MY_WAIT_IF_FULL
);
620 if (share
->options
& HA_OPTION_READ_ONLY_DATA
)
622 info
.lock_type
=F_RDLCK
;
626 if ((open_flags
& HA_OPEN_TMP_TABLE
) ||
627 (share
->options
& HA_OPTION_TMP_TABLE
))
629 share
->temporary
=share
->delay_key_write
=1;
630 share
->write_flag
=MYF(MY_NABP
);
631 share
->w_locks
++; /* We don't have to update status */
633 info
.lock_type
=F_WRLCK
;
635 if (((open_flags
& HA_OPEN_DELAY_KEY_WRITE
) ||
636 (share
->options
& HA_OPTION_DELAY_KEY_WRITE
)) &&
637 myisam_delay_key_write
)
638 share
->delay_key_write
=1;
639 info
.state
= &share
->state
.state
; /* Change global values by default */
640 pthread_mutex_unlock(&share
->intern_lock
);
642 /* Allocate buffer for one record */
644 /* prerequisites: bzero(info) && info->s=share; are met. */
645 if (!mi_alloc_rec_buff(&info
, -1, &info
.rec_buff
))
647 bzero(info
.rec_buff
, mi_get_rec_buff_len(&info
, info
.rec_buff
));
651 thr_lock_data_init(&share
->lock
,&m_info
->lock
,(void*) m_info
);
653 m_info
->open_list
.data
=(void*) m_info
;
654 myisam_open_list
=list_add(myisam_open_list
,&m_info
->open_list
);
656 pthread_mutex_unlock(&THR_LOCK_myisam
);
658 bzero(info
.buff
, share
->base
.max_key_block_length
* 2);
660 if (myisam_log_file
>= 0)
662 intern_filename(name_buff
,share
->index_file_name
);
663 _myisam_log(MI_LOG_OPEN
, m_info
, (uchar
*) name_buff
, strlen(name_buff
));
668 save_errno
=my_errno
? my_errno
: HA_ERR_END_OF_FILE
;
669 if ((save_errno
== HA_ERR_CRASHED
) ||
670 (save_errno
== HA_ERR_CRASHED_ON_USAGE
) ||
671 (save_errno
== HA_ERR_CRASHED_ON_REPAIR
))
672 mi_report_error(save_errno
, name
);
675 my_free((uchar
*) m_info
,MYF(0));
678 VOID(my_close(info
.dfile
,MYF(0)));
680 break; /* Don't remove open table */
683 my_free((uchar
*) share
,MYF(0));
687 VOID(my_lock(kfile
, F_UNLCK
, 0L, F_TO_EOF
, MYF(MY_SEEK_NOT_DONE
)));
690 my_afree(disk_cache
);
693 VOID(my_close(kfile
,MYF(0)));
699 pthread_mutex_unlock(&THR_LOCK_myisam
);
705 uchar
*mi_alloc_rec_buff(MI_INFO
*info
, ulong length
, uchar
**buf
)
708 uint32
UNINIT_VAR(old_length
);
709 LINT_INIT(old_length
);
711 if (! *buf
|| length
> (old_length
=mi_get_rec_buff_len(info
, *buf
)))
713 uchar
*newptr
= *buf
;
715 /* to simplify initial init of info->rec_buf in mi_open and mi_extra */
716 if (length
== (ulong
) -1)
718 if (info
->s
->options
& HA_OPTION_COMPRESS_RECORD
)
719 length
= max(info
->s
->base
.pack_reclength
, info
->s
->max_pack_length
);
721 length
= info
->s
->base
.pack_reclength
;
722 length
= max(length
, info
->s
->base
.max_key_length
);
723 /* Avoid unnecessary realloc */
724 if (newptr
&& length
== old_length
)
728 extra
= ((info
->s
->options
& HA_OPTION_PACK_RECORD
) ?
729 ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER
)+MI_SPLIT_LENGTH
+
730 MI_REC_BUFF_OFFSET
: 0);
732 newptr
-= MI_REC_BUFF_OFFSET
;
733 if (!(newptr
=(uchar
*) my_realloc((uchar
*)newptr
, length
+extra
+8,
734 MYF(MY_ALLOW_ZERO_PTR
))))
736 *((uint32
*) newptr
)= (uint32
) length
;
737 *buf
= newptr
+(extra
? MI_REC_BUFF_OFFSET
: 0);
743 ulonglong
mi_safe_mul(ulonglong a
, ulonglong b
)
745 ulonglong max_val
= ~ (ulonglong
) 0; /* my_off_t is unsigned */
747 if (!a
|| max_val
/ a
< b
)
752 /* Set up functions in structs */
754 void mi_setup_functions(register MYISAM_SHARE
*share
)
756 if (share
->options
& HA_OPTION_COMPRESS_RECORD
)
758 share
->read_record
=_mi_read_pack_record
;
759 share
->read_rnd
=_mi_read_rnd_pack_record
;
760 if (!(share
->options
& HA_OPTION_TEMP_COMPRESS_RECORD
))
761 share
->calc_checksum
=0; /* No checksum */
762 else if (share
->options
& HA_OPTION_PACK_RECORD
)
763 share
->calc_checksum
= mi_checksum
;
765 share
->calc_checksum
= mi_static_checksum
;
767 else if (share
->options
& HA_OPTION_PACK_RECORD
)
769 share
->read_record
=_mi_read_dynamic_record
;
770 share
->read_rnd
=_mi_read_rnd_dynamic_record
;
771 share
->delete_record
=_mi_delete_dynamic_record
;
772 share
->compare_record
=_mi_cmp_dynamic_record
;
773 share
->compare_unique
=_mi_cmp_dynamic_unique
;
774 share
->calc_checksum
= mi_checksum
;
776 /* add bits used to pack data to pack_reclength for faster allocation */
777 share
->base
.pack_reclength
+= share
->base
.pack_bits
;
778 if (share
->base
.blobs
)
780 share
->update_record
=_mi_update_blob_record
;
781 share
->write_record
=_mi_write_blob_record
;
785 share
->write_record
=_mi_write_dynamic_record
;
786 share
->update_record
=_mi_update_dynamic_record
;
791 share
->read_record
=_mi_read_static_record
;
792 share
->read_rnd
=_mi_read_rnd_static_record
;
793 share
->delete_record
=_mi_delete_static_record
;
794 share
->compare_record
=_mi_cmp_static_record
;
795 share
->update_record
=_mi_update_static_record
;
796 share
->write_record
=_mi_write_static_record
;
797 share
->compare_unique
=_mi_cmp_static_unique
;
798 share
->calc_checksum
= mi_static_checksum
;
800 share
->file_read
= mi_nommap_pread
;
801 share
->file_write
= mi_nommap_pwrite
;
802 if (!(share
->options
& HA_OPTION_CHECKSUM
))
803 share
->calc_checksum
=0;
808 static void setup_key_functions(register MI_KEYDEF
*keyinfo
)
810 if (keyinfo
->key_alg
== HA_KEY_ALG_RTREE
)
812 #ifdef HAVE_RTREE_KEYS
813 keyinfo
->ck_insert
= rtree_insert
;
814 keyinfo
->ck_delete
= rtree_delete
;
816 DBUG_ASSERT(0); /* mi_open should check it never happens */
821 keyinfo
->ck_insert
= _mi_ck_write
;
822 keyinfo
->ck_delete
= _mi_ck_delete
;
824 if (keyinfo
->flag
& HA_BINARY_PACK_KEY
)
825 { /* Simple prefix compression */
826 keyinfo
->bin_search
=_mi_seq_search
;
827 keyinfo
->get_key
=_mi_get_binary_pack_key
;
828 keyinfo
->pack_key
=_mi_calc_bin_pack_key_length
;
829 keyinfo
->store_key
=_mi_store_bin_pack_key
;
831 else if (keyinfo
->flag
& HA_VAR_LENGTH_KEY
)
833 keyinfo
->get_key
= _mi_get_pack_key
;
834 if (keyinfo
->seg
[0].flag
& HA_PACK_KEY
)
835 { /* Prefix compression */
837 _mi_prefix_search() compares end-space against ASCII blank (' ').
838 It cannot be used for character sets, that do not encode the
839 blank character like ASCII does. UCS2 is an example. All
840 character sets with a fixed width > 1 or a mimimum width > 1
841 cannot represent blank like ASCII does. In these cases we have
842 to use _mi_seq_search() for the search.
844 if (!keyinfo
->seg
->charset
|| use_strnxfrm(keyinfo
->seg
->charset
) ||
845 (keyinfo
->seg
->flag
& HA_NULL_PART
) ||
846 (keyinfo
->seg
->charset
->mbminlen
> 1))
847 keyinfo
->bin_search
=_mi_seq_search
;
849 keyinfo
->bin_search
=_mi_prefix_search
;
850 keyinfo
->pack_key
=_mi_calc_var_pack_key_length
;
851 keyinfo
->store_key
=_mi_store_var_pack_key
;
855 keyinfo
->bin_search
=_mi_seq_search
;
856 keyinfo
->pack_key
=_mi_calc_var_key_length
; /* Variable length key */
857 keyinfo
->store_key
=_mi_store_static_key
;
862 keyinfo
->bin_search
=_mi_bin_search
;
863 keyinfo
->get_key
=_mi_get_static_key
;
864 keyinfo
->pack_key
=_mi_calc_static_key_length
;
865 keyinfo
->store_key
=_mi_store_static_key
;
872 Function to save and store the header in the index file (.MYI)
875 uint
mi_state_info_write(File file
, MI_STATE_INFO
*state
, uint pWrite
)
877 uchar buff
[MI_STATE_INFO_SIZE
+ MI_STATE_EXTRA_SIZE
];
879 uint i
, keys
= (uint
) state
->header
.keys
,
880 key_blocks
=state
->header
.max_block_size_index
;
881 DBUG_ENTER("mi_state_info_write");
883 memcpy_fixed(ptr
,&state
->header
,sizeof(state
->header
));
884 ptr
+=sizeof(state
->header
);
886 /* open_count must be first because of _mi_mark_file_changed ! */
887 mi_int2store(ptr
,state
->open_count
); ptr
+=2;
888 *ptr
++= (uchar
)state
->changed
; *ptr
++= state
->sortkey
;
889 mi_rowstore(ptr
,state
->state
.records
); ptr
+=8;
890 mi_rowstore(ptr
,state
->state
.del
); ptr
+=8;
891 mi_rowstore(ptr
,state
->split
); ptr
+=8;
892 mi_sizestore(ptr
,state
->dellink
); ptr
+=8;
893 mi_sizestore(ptr
,state
->state
.key_file_length
); ptr
+=8;
894 mi_sizestore(ptr
,state
->state
.data_file_length
); ptr
+=8;
895 mi_sizestore(ptr
,state
->state
.empty
); ptr
+=8;
896 mi_sizestore(ptr
,state
->state
.key_empty
); ptr
+=8;
897 mi_int8store(ptr
,state
->auto_increment
); ptr
+=8;
898 mi_int8store(ptr
,(ulonglong
) state
->state
.checksum
);ptr
+=8;
899 mi_int4store(ptr
,state
->process
); ptr
+=4;
900 mi_int4store(ptr
,state
->unique
); ptr
+=4;
901 mi_int4store(ptr
,state
->status
); ptr
+=4;
902 mi_int4store(ptr
,state
->update_count
); ptr
+=4;
904 ptr
+=state
->state_diff_length
;
906 for (i
=0; i
< keys
; i
++)
908 mi_sizestore(ptr
,state
->key_root
[i
]); ptr
+=8;
910 for (i
=0; i
< key_blocks
; i
++)
912 mi_sizestore(ptr
,state
->key_del
[i
]); ptr
+=8;
914 if (pWrite
& 2) /* From isamchk */
916 uint key_parts
= mi_uint2korr(state
->header
.key_parts
);
917 mi_int4store(ptr
,state
->sec_index_changed
); ptr
+=4;
918 mi_int4store(ptr
,state
->sec_index_used
); ptr
+=4;
919 mi_int4store(ptr
,state
->version
); ptr
+=4;
920 mi_int8store(ptr
,state
->key_map
); ptr
+=8;
921 mi_int8store(ptr
,(ulonglong
) state
->create_time
); ptr
+=8;
922 mi_int8store(ptr
,(ulonglong
) state
->recover_time
); ptr
+=8;
923 mi_int8store(ptr
,(ulonglong
) state
->check_time
); ptr
+=8;
924 mi_sizestore(ptr
,state
->rec_per_key_rows
); ptr
+=8;
925 for (i
=0 ; i
< key_parts
; i
++)
927 mi_int4store(ptr
,state
->rec_per_key_part
[i
]); ptr
+=4;
932 DBUG_RETURN(my_pwrite(file
, buff
, (size_t) (ptr
-buff
), 0L,
933 MYF(MY_NABP
| MY_THREADSAFE
)) != 0);
934 DBUG_RETURN(my_write(file
, buff
, (size_t) (ptr
-buff
),
939 uchar
*mi_state_info_read(uchar
*ptr
, MI_STATE_INFO
*state
)
941 uint i
,keys
,key_parts
,key_blocks
;
942 memcpy_fixed(&state
->header
,ptr
, sizeof(state
->header
));
943 ptr
+=sizeof(state
->header
);
944 keys
=(uint
) state
->header
.keys
;
945 key_parts
=mi_uint2korr(state
->header
.key_parts
);
946 key_blocks
=state
->header
.max_block_size_index
;
948 state
->open_count
= mi_uint2korr(ptr
); ptr
+=2;
949 state
->changed
= *ptr
++;
950 state
->sortkey
= (uint
) *ptr
++;
951 state
->state
.records
= mi_rowkorr(ptr
); ptr
+=8;
952 state
->state
.del
= mi_rowkorr(ptr
); ptr
+=8;
953 state
->split
= mi_rowkorr(ptr
); ptr
+=8;
954 state
->dellink
= mi_sizekorr(ptr
); ptr
+=8;
955 state
->state
.key_file_length
= mi_sizekorr(ptr
); ptr
+=8;
956 state
->state
.data_file_length
= mi_sizekorr(ptr
); ptr
+=8;
957 state
->state
.empty
= mi_sizekorr(ptr
); ptr
+=8;
958 state
->state
.key_empty
= mi_sizekorr(ptr
); ptr
+=8;
959 state
->auto_increment
=mi_uint8korr(ptr
); ptr
+=8;
960 state
->state
.checksum
=(ha_checksum
) mi_uint8korr(ptr
); ptr
+=8;
961 state
->process
= mi_uint4korr(ptr
); ptr
+=4;
962 state
->unique
= mi_uint4korr(ptr
); ptr
+=4;
963 state
->status
= mi_uint4korr(ptr
); ptr
+=4;
964 state
->update_count
=mi_uint4korr(ptr
); ptr
+=4;
966 ptr
+= state
->state_diff_length
;
968 for (i
=0; i
< keys
; i
++)
970 state
->key_root
[i
]= mi_sizekorr(ptr
); ptr
+=8;
972 for (i
=0; i
< key_blocks
; i
++)
974 state
->key_del
[i
] = mi_sizekorr(ptr
); ptr
+=8;
976 state
->sec_index_changed
= mi_uint4korr(ptr
); ptr
+=4;
977 state
->sec_index_used
= mi_uint4korr(ptr
); ptr
+=4;
978 state
->version
= mi_uint4korr(ptr
); ptr
+=4;
979 state
->key_map
= mi_uint8korr(ptr
); ptr
+=8;
980 state
->create_time
= (time_t) mi_sizekorr(ptr
); ptr
+=8;
981 state
->recover_time
=(time_t) mi_sizekorr(ptr
); ptr
+=8;
982 state
->check_time
= (time_t) mi_sizekorr(ptr
); ptr
+=8;
983 state
->rec_per_key_rows
=mi_sizekorr(ptr
); ptr
+=8;
984 for (i
=0 ; i
< key_parts
; i
++)
986 state
->rec_per_key_part
[i
]= mi_uint4korr(ptr
); ptr
+=4;
992 uint
mi_state_info_read_dsk(File file
, MI_STATE_INFO
*state
, my_bool pRead
)
994 uchar buff
[MI_STATE_INFO_SIZE
+ MI_STATE_EXTRA_SIZE
];
996 if (!myisam_single_user
)
1000 if (my_pread(file
, buff
, state
->state_length
,0L, MYF(MY_NABP
)))
1003 else if (my_read(file
, buff
, state
->state_length
,MYF(MY_NABP
)))
1005 mi_state_info_read(buff
, state
);
1011 /****************************************************************************
1012 ** store and read of MI_BASE_INFO
1013 ****************************************************************************/
1015 uint
mi_base_info_write(File file
, MI_BASE_INFO
*base
)
1017 uchar buff
[MI_BASE_INFO_SIZE
], *ptr
=buff
;
1019 mi_sizestore(ptr
,base
->keystart
); ptr
+=8;
1020 mi_sizestore(ptr
,base
->max_data_file_length
); ptr
+=8;
1021 mi_sizestore(ptr
,base
->max_key_file_length
); ptr
+=8;
1022 mi_rowstore(ptr
,base
->records
); ptr
+=8;
1023 mi_rowstore(ptr
,base
->reloc
); ptr
+=8;
1024 mi_int4store(ptr
,base
->mean_row_length
); ptr
+=4;
1025 mi_int4store(ptr
,base
->reclength
); ptr
+=4;
1026 mi_int4store(ptr
,base
->pack_reclength
); ptr
+=4;
1027 mi_int4store(ptr
,base
->min_pack_length
); ptr
+=4;
1028 mi_int4store(ptr
,base
->max_pack_length
); ptr
+=4;
1029 mi_int4store(ptr
,base
->min_block_length
); ptr
+=4;
1030 mi_int4store(ptr
,base
->fields
); ptr
+=4;
1031 mi_int4store(ptr
,base
->pack_fields
); ptr
+=4;
1032 *ptr
++=base
->rec_reflength
;
1033 *ptr
++=base
->key_reflength
;
1035 *ptr
++=base
->auto_key
;
1036 mi_int2store(ptr
,base
->pack_bits
); ptr
+=2;
1037 mi_int2store(ptr
,base
->blobs
); ptr
+=2;
1038 mi_int2store(ptr
,base
->max_key_block_length
); ptr
+=2;
1039 mi_int2store(ptr
,base
->max_key_length
); ptr
+=2;
1040 mi_int2store(ptr
,base
->extra_alloc_bytes
); ptr
+=2;
1041 *ptr
++= base
->extra_alloc_procent
;
1042 *ptr
++= base
->raid_type
;
1043 mi_int2store(ptr
,base
->raid_chunks
); ptr
+=2;
1044 mi_int4store(ptr
,base
->raid_chunksize
); ptr
+=4;
1045 bzero(ptr
,6); ptr
+=6; /* extra */
1046 return my_write(file
, buff
, (size_t) (ptr
-buff
), MYF(MY_NABP
)) != 0;
1050 uchar
*my_n_base_info_read(uchar
*ptr
, MI_BASE_INFO
*base
)
1052 base
->keystart
= mi_sizekorr(ptr
); ptr
+=8;
1053 base
->max_data_file_length
= mi_sizekorr(ptr
); ptr
+=8;
1054 base
->max_key_file_length
= mi_sizekorr(ptr
); ptr
+=8;
1055 base
->records
= (ha_rows
) mi_sizekorr(ptr
); ptr
+=8;
1056 base
->reloc
= (ha_rows
) mi_sizekorr(ptr
); ptr
+=8;
1057 base
->mean_row_length
= mi_uint4korr(ptr
); ptr
+=4;
1058 base
->reclength
= mi_uint4korr(ptr
); ptr
+=4;
1059 base
->pack_reclength
= mi_uint4korr(ptr
); ptr
+=4;
1060 base
->min_pack_length
= mi_uint4korr(ptr
); ptr
+=4;
1061 base
->max_pack_length
= mi_uint4korr(ptr
); ptr
+=4;
1062 base
->min_block_length
= mi_uint4korr(ptr
); ptr
+=4;
1063 base
->fields
= mi_uint4korr(ptr
); ptr
+=4;
1064 base
->pack_fields
= mi_uint4korr(ptr
); ptr
+=4;
1066 base
->rec_reflength
= *ptr
++;
1067 base
->key_reflength
= *ptr
++;
1069 base
->auto_key
= *ptr
++;
1070 base
->pack_bits
= mi_uint2korr(ptr
); ptr
+=2;
1071 base
->blobs
= mi_uint2korr(ptr
); ptr
+=2;
1072 base
->max_key_block_length
= mi_uint2korr(ptr
); ptr
+=2;
1073 base
->max_key_length
= mi_uint2korr(ptr
); ptr
+=2;
1074 base
->extra_alloc_bytes
= mi_uint2korr(ptr
); ptr
+=2;
1075 base
->extra_alloc_procent
= *ptr
++;
1076 base
->raid_type
= *ptr
++;
1077 base
->raid_chunks
= mi_uint2korr(ptr
); ptr
+=2;
1078 base
->raid_chunksize
= mi_uint4korr(ptr
); ptr
+=4;
1079 /* TO BE REMOVED: Fix for old RAID files */
1080 if (base
->raid_type
== 0)
1082 base
->raid_chunks
=0;
1083 base
->raid_chunksize
=0;
1090 /*--------------------------------------------------------------------------
1092 ---------------------------------------------------------------------------*/
1094 uint
mi_keydef_write(File file
, MI_KEYDEF
*keydef
)
1096 uchar buff
[MI_KEYDEF_SIZE
];
1099 *ptr
++ = (uchar
) keydef
->keysegs
;
1100 *ptr
++ = keydef
->key_alg
; /* Rtree or Btree */
1101 mi_int2store(ptr
,keydef
->flag
); ptr
+=2;
1102 mi_int2store(ptr
,keydef
->block_length
); ptr
+=2;
1103 mi_int2store(ptr
,keydef
->keylength
); ptr
+=2;
1104 mi_int2store(ptr
,keydef
->minlength
); ptr
+=2;
1105 mi_int2store(ptr
,keydef
->maxlength
); ptr
+=2;
1106 return my_write(file
, buff
, (size_t) (ptr
-buff
), MYF(MY_NABP
)) != 0;
1109 uchar
*mi_keydef_read(uchar
*ptr
, MI_KEYDEF
*keydef
)
1111 keydef
->keysegs
= (uint
) *ptr
++;
1112 keydef
->key_alg
= *ptr
++; /* Rtree or Btree */
1114 keydef
->flag
= mi_uint2korr(ptr
); ptr
+=2;
1115 keydef
->block_length
= mi_uint2korr(ptr
); ptr
+=2;
1116 keydef
->keylength
= mi_uint2korr(ptr
); ptr
+=2;
1117 keydef
->minlength
= mi_uint2korr(ptr
); ptr
+=2;
1118 keydef
->maxlength
= mi_uint2korr(ptr
); ptr
+=2;
1119 keydef
->block_size_index
= keydef
->block_length
/MI_MIN_KEY_BLOCK_LENGTH
-1;
1120 keydef
->underflow_block_length
=keydef
->block_length
/3;
1121 keydef
->version
= 0; /* Not saved */
1122 keydef
->parser
= &ft_default_parser
;
1123 keydef
->ftkey_nr
= 0;
1127 /***************************************************************************
1129 ***************************************************************************/
1131 int mi_keyseg_write(File file
, const HA_KEYSEG
*keyseg
)
1133 uchar buff
[HA_KEYSEG_SIZE
];
1137 *ptr
++= keyseg
->type
;
1138 *ptr
++= keyseg
->language
;
1139 *ptr
++= keyseg
->null_bit
;
1140 *ptr
++= keyseg
->bit_start
;
1141 *ptr
++= keyseg
->bit_end
;
1142 *ptr
++= keyseg
->bit_length
;
1143 mi_int2store(ptr
,keyseg
->flag
); ptr
+=2;
1144 mi_int2store(ptr
,keyseg
->length
); ptr
+=2;
1145 mi_int4store(ptr
,keyseg
->start
); ptr
+=4;
1146 pos
= keyseg
->null_bit
? keyseg
->null_pos
: keyseg
->bit_pos
;
1147 mi_int4store(ptr
, pos
);
1150 return my_write(file
, buff
, (size_t) (ptr
-buff
), MYF(MY_NABP
)) != 0;
1154 uchar
*mi_keyseg_read(uchar
*ptr
, HA_KEYSEG
*keyseg
)
1156 keyseg
->type
= *ptr
++;
1157 keyseg
->language
= *ptr
++;
1158 keyseg
->null_bit
= *ptr
++;
1159 keyseg
->bit_start
= *ptr
++;
1160 keyseg
->bit_end
= *ptr
++;
1161 keyseg
->bit_length
= *ptr
++;
1162 keyseg
->flag
= mi_uint2korr(ptr
); ptr
+=2;
1163 keyseg
->length
= mi_uint2korr(ptr
); ptr
+=2;
1164 keyseg
->start
= mi_uint4korr(ptr
); ptr
+=4;
1165 keyseg
->null_pos
= mi_uint4korr(ptr
); ptr
+=4;
1166 keyseg
->charset
=0; /* Will be filled in later */
1167 if (keyseg
->null_bit
)
1168 /* We adjust bit_pos if null_bit is last in the byte */
1169 keyseg
->bit_pos
= (uint16
)(keyseg
->null_pos
+ (keyseg
->null_bit
== (1 << 7)));
1172 keyseg
->bit_pos
= (uint16
)keyseg
->null_pos
;
1173 keyseg
->null_pos
= 0;
1178 /*--------------------------------------------------------------------------
1180 ---------------------------------------------------------------------------*/
1182 uint
mi_uniquedef_write(File file
, MI_UNIQUEDEF
*def
)
1184 uchar buff
[MI_UNIQUEDEF_SIZE
];
1187 mi_int2store(ptr
,def
->keysegs
); ptr
+=2;
1188 *ptr
++= (uchar
) def
->key
;
1189 *ptr
++ = (uchar
) def
->null_are_equal
;
1191 return my_write(file
, buff
, (size_t) (ptr
-buff
), MYF(MY_NABP
)) != 0;
1194 uchar
*mi_uniquedef_read(uchar
*ptr
, MI_UNIQUEDEF
*def
)
1196 def
->keysegs
= mi_uint2korr(ptr
);
1198 def
->null_are_equal
=ptr
[3];
1199 return ptr
+4; /* 1 extra byte */
1202 /***************************************************************************
1204 ***************************************************************************/
1206 uint
mi_recinfo_write(File file
, MI_COLUMNDEF
*recinfo
)
1208 uchar buff
[MI_COLUMNDEF_SIZE
];
1211 mi_int2store(ptr
,recinfo
->type
); ptr
+=2;
1212 mi_int2store(ptr
,recinfo
->length
); ptr
+=2;
1213 *ptr
++ = recinfo
->null_bit
;
1214 mi_int2store(ptr
,recinfo
->null_pos
); ptr
+= 2;
1215 return my_write(file
, buff
, (size_t) (ptr
-buff
), MYF(MY_NABP
)) != 0;
1218 uchar
*mi_recinfo_read(uchar
*ptr
, MI_COLUMNDEF
*recinfo
)
1220 recinfo
->type
= mi_sint2korr(ptr
); ptr
+=2;
1221 recinfo
->length
=mi_uint2korr(ptr
); ptr
+=2;
1222 recinfo
->null_bit
= (uint8
) *ptr
++;
1223 recinfo
->null_pos
=mi_uint2korr(ptr
); ptr
+=2;
1227 /**************************************************************************
1228 Open data file with or without RAID
1229 We can't use dup() here as the data file descriptors need to have different
1230 active seek-positions.
1232 The argument file_to_dup is here for the future if there would on some OS
1233 exist a dup()-like call that would give us two different file descriptors.
1234 *************************************************************************/
1236 int mi_open_datafile(MI_INFO
*info
, MYISAM_SHARE
*share
, const char *org_name
,
1237 File file_to_dup
__attribute__((unused
)))
1239 char *data_name
= share
->data_file_name
;
1240 char real_data_name
[FN_REFLEN
];
1244 fn_format(real_data_name
,org_name
,"",MI_NAME_DEXT
,4);
1245 if (my_is_symlink(real_data_name
))
1247 if (my_realpath(real_data_name
, real_data_name
, MYF(0)) ||
1248 (*myisam_test_invalid_symlink
)(real_data_name
))
1250 my_errno
= HA_WRONG_CREATE_OPTION
;
1253 data_name
= real_data_name
;
1257 if (share
->base
.raid_type
)
1259 info
->dfile
=my_raid_open(data_name
,
1260 share
->mode
| O_SHARE
,
1261 share
->base
.raid_type
,
1262 share
->base
.raid_chunks
,
1263 share
->base
.raid_chunksize
,
1264 MYF(MY_WME
| MY_RAID
));
1268 info
->dfile
=my_open(data_name
, share
->mode
| O_SHARE
, MYF(MY_WME
));
1269 return info
->dfile
>= 0 ? 0 : 1;
1273 int mi_open_keyfile(MYISAM_SHARE
*share
)
1275 if ((share
->kfile
=my_open(share
->unique_file_name
, share
->mode
| O_SHARE
,
1283 Disable all indexes.
1286 mi_disable_indexes()
1287 info A pointer to the MyISAM storage engine MI_INFO struct.
1290 Disable all indexes.
1296 int mi_disable_indexes(MI_INFO
*info
)
1298 MYISAM_SHARE
*share
= info
->s
;
1300 mi_clear_all_keys_active(share
->state
.key_map
);
1310 info A pointer to the MyISAM storage engine MI_INFO struct.
1313 Enable all indexes. The indexes might have been disabled
1314 by mi_disable_index() before.
1315 The function works only if both data and indexes are empty,
1316 otherwise a repair is required.
1317 To be sure, call handler::delete_all_rows() before.
1321 HA_ERR_CRASHED data or index is non-empty.
1324 int mi_enable_indexes(MI_INFO
*info
)
1327 MYISAM_SHARE
*share
= info
->s
;
1329 if (share
->state
.state
.data_file_length
||
1330 (share
->state
.state
.key_file_length
!= share
->base
.keystart
))
1332 mi_print_error(info
->s
, HA_ERR_CRASHED
);
1333 error
= HA_ERR_CRASHED
;
1336 mi_set_all_keys_active(share
->state
.key_map
, share
->base
.keys
);
1342 Test if indexes are disabled.
1345 mi_indexes_are_disabled()
1346 info A pointer to the MyISAM storage engine MI_INFO struct.
1349 Test if indexes are disabled.
1352 0 indexes are not disabled
1353 1 all indexes are disabled
1354 2 non-unique indexes are disabled
1357 int mi_indexes_are_disabled(MI_INFO
*info
)
1359 MYISAM_SHARE
*share
= info
->s
;
1362 No keys or all are enabled. keys is the number of keys. Left shifted
1363 gives us only one bit set. When decreased by one, gives us all all bits
1364 up to this one set and it gets unset.
1366 if (!share
->base
.keys
||
1367 (mi_is_all_keys_active(share
->state
.key_map
, share
->base
.keys
)))
1370 /* All are disabled */
1371 if (mi_is_any_key_active(share
->state
.key_map
))
1375 We have keys. Some enabled, some disabled.
1376 Don't check for any non-unique disabled but return directly 2