00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "myisam_priv.h"
00019
00020 #include <string.h>
00021 #include <algorithm>
00022 #include <memory>
00023 #include <boost/scoped_ptr.hpp>
00024 #include <boost/scoped_array.hpp>
00025
00026 #include <drizzled/charset_info.h>
00027 #include <drizzled/internal/m_string.h>
00028 #include <drizzled/util/test.h>
00029 #include <drizzled/global_charset_info.h>
00030 #include <drizzled/charset.h>
00031 #include <drizzled/memory/multi_malloc.h>
00032
00033
00034 using namespace std;
00035 using namespace drizzled;
00036
00037 static void setup_key_functions(MI_KEYDEF *keyinfo);
00038 static unsigned char *mi_keydef_read(unsigned char *ptr, MI_KEYDEF *keydef);
00039 static unsigned char *mi_keyseg_read(unsigned char *ptr, HA_KEYSEG *keyseg);
00040 static unsigned char *mi_recinfo_read(unsigned char *ptr, MI_COLUMNDEF *recinfo);
00041 static uint64_t mi_safe_mul(uint64_t a, uint64_t b);
00042 static unsigned char *mi_state_info_read(unsigned char *ptr, MI_STATE_INFO *state);
00043 static unsigned char *mi_uniquedef_read(unsigned char *ptr, MI_UNIQUEDEF *def);
00044 static unsigned char *my_n_base_info_read(unsigned char *ptr, MI_BASE_INFO *base);
00045
00046 #define disk_pos_assert(pos, end_pos) \
00047 if (pos > end_pos) \
00048 { \
00049 errno=HA_ERR_CRASHED; \
00050 goto err; \
00051 }
00052
00053
00054
00055
00056
00057
00058
00059 MI_INFO *test_if_reopen(char *filename)
00060 {
00061 list<MI_INFO *>::iterator it= myisam_open_list.begin();
00062 while (it != myisam_open_list.end())
00063 {
00064 MI_INFO *info= *it;
00065 MYISAM_SHARE *share=info->s;
00066 if (!strcmp(share->unique_file_name,filename) && share->last_version)
00067 return info;
00068 ++it;
00069 }
00070 return 0;
00071 }
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 MI_INFO *mi_open(const drizzled::identifier::Table &identifier, int mode, uint32_t open_flags)
00083 {
00084 int lock_error,kfile,open_mode,save_errno,have_rtree=0;
00085 uint32_t i,j,len,errpos,head_length,base_pos,offset,info_length,keys,
00086 key_parts,unique_key_parts,fulltext_keys,uniques;
00087 char name_buff[FN_REFLEN], org_name[FN_REFLEN], index_name[FN_REFLEN],
00088 data_name[FN_REFLEN], rp_buff[PATH_MAX];
00089 unsigned char *disk_cache= NULL;
00090 unsigned char *disk_pos, *end_pos;
00091 MI_INFO info,*m_info,*old_info;
00092 boost::scoped_ptr<MYISAM_SHARE> share_buff_ap(new MYISAM_SHARE);
00093 MYISAM_SHARE &share_buff= *share_buff_ap.get();
00094 MYISAM_SHARE *share;
00095 boost::scoped_array<ulong> rec_per_key_part_ap(new ulong[HA_MAX_POSSIBLE_KEY*MI_MAX_KEY_SEG]);
00096 ulong *rec_per_key_part= rec_per_key_part_ap.get();
00097 internal::my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
00098 uint64_t max_key_file_length, max_data_file_length;
00099
00100 kfile= -1;
00101 lock_error=1;
00102 errpos=0;
00103 head_length=sizeof(share_buff.state.header);
00104 memset(&info, 0, sizeof(info));
00105
00106 (void)internal::fn_format(org_name,
00107 identifier.getPath().c_str(),
00108 "",
00109 MI_NAME_IEXT,
00110 MY_UNPACK_FILENAME);
00111 if (!realpath(org_name,rp_buff))
00112 internal::my_load_path(rp_buff,org_name, NULL);
00113 rp_buff[FN_REFLEN-1]= '\0';
00114 strcpy(name_buff,rp_buff);
00115 THR_LOCK_myisam.lock();
00116 if (!(old_info=test_if_reopen(name_buff)))
00117 {
00118 share= &share_buff;
00119 memset(&share_buff, 0, sizeof(share_buff));
00120 share_buff.state.rec_per_key_part=rec_per_key_part;
00121 share_buff.state.key_root=key_root;
00122 share_buff.state.key_del=key_del;
00123 share_buff.setKeyCache();
00124
00125 if ((kfile=internal::my_open(name_buff,(open_mode=O_RDWR),MYF(0))) < 0)
00126 {
00127 if ((errno != EROFS && errno != EACCES) ||
00128 mode != O_RDONLY ||
00129 (kfile=internal::my_open(name_buff,(open_mode=O_RDONLY),MYF(0))) < 0)
00130 goto err;
00131 }
00132 share->mode=open_mode;
00133 errpos=1;
00134 if (internal::my_read(kfile, share->state.header.file_version, head_length,
00135 MYF(MY_NABP)))
00136 {
00137 errno= HA_ERR_NOT_A_TABLE;
00138 goto err;
00139 }
00140 if (memcmp(share->state.header.file_version, myisam_file_magic, 4))
00141 {
00142 errno=HA_ERR_NOT_A_TABLE;
00143 goto err;
00144 }
00145 share->options= mi_uint2korr(share->state.header.options);
00146 static const uint64_t OLD_FILE_OPTIONS= HA_OPTION_PACK_RECORD |
00147 HA_OPTION_PACK_KEYS |
00148 HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA |
00149 HA_OPTION_TEMP_COMPRESS_RECORD |
00150 HA_OPTION_TMP_TABLE;
00151 if (share->options & ~OLD_FILE_OPTIONS)
00152 {
00153 errno=HA_ERR_OLD_FILE;
00154 goto err;
00155 }
00156
00157
00158 ssize_t sym_link_size= readlink(org_name,index_name,FN_REFLEN-1);
00159 if (sym_link_size >= 0 )
00160 index_name[sym_link_size]= '\0';
00161 if (!strcmp(name_buff, org_name) || sym_link_size == -1)
00162 (void) strcpy(index_name, org_name);
00163 *strrchr(org_name, '.')= '\0';
00164 (void) internal::fn_format(data_name,org_name,"",MI_NAME_DEXT,
00165 MY_APPEND_EXT|MY_UNPACK_FILENAME|MY_RESOLVE_SYMLINKS);
00166
00167 info_length=mi_uint2korr(share->state.header.header_length);
00168 base_pos=mi_uint2korr(share->state.header.base_pos);
00169 if (!(disk_cache= (unsigned char*) malloc(info_length+128)))
00170 {
00171 errno=ENOMEM;
00172 goto err;
00173 }
00174 end_pos=disk_cache+info_length;
00175 errpos=2;
00176
00177 lseek(kfile,0,SEEK_SET);
00178 errpos=3;
00179 if (internal::my_read(kfile,disk_cache,info_length,MYF(MY_NABP)))
00180 {
00181 errno=HA_ERR_CRASHED;
00182 goto err;
00183 }
00184 len=mi_uint2korr(share->state.header.state_info_length);
00185 keys= (uint) share->state.header.keys;
00186 uniques= (uint) share->state.header.uniques;
00187 fulltext_keys= (uint) share->state.header.fulltext_keys;
00188 key_parts= mi_uint2korr(share->state.header.key_parts);
00189 unique_key_parts= mi_uint2korr(share->state.header.unique_key_parts);
00190 share->state_diff_length=len-MI_STATE_INFO_SIZE;
00191
00192 mi_state_info_read(disk_cache, &share->state);
00193 len= mi_uint2korr(share->state.header.base_info_length);
00194 disk_pos= my_n_base_info_read(disk_cache + base_pos, &share->base);
00195 share->state.state_length=base_pos;
00196
00197 if (share->state.changed & STATE_CRASHED)
00198 {
00199 errno=((share->state.changed & STATE_CRASHED_ON_REPAIR) ?
00200 HA_ERR_CRASHED_ON_REPAIR : HA_ERR_CRASHED_ON_USAGE);
00201 goto err;
00202 }
00203
00204
00205 if (share->base.keystart > 65535 || share->base.rec_reflength > 8)
00206 {
00207 errno=HA_ERR_CRASHED;
00208 goto err;
00209 }
00210
00211 if (share->base.max_key_length > MI_MAX_KEY_BUFF || keys > MI_MAX_KEY ||
00212 key_parts > MI_MAX_KEY * MI_MAX_KEY_SEG)
00213 {
00214 errno=HA_ERR_UNSUPPORTED;
00215 goto err;
00216 }
00217
00218
00219 max_data_file_length=
00220 (share->options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ?
00221 (((uint64_t) 1 << (share->base.rec_reflength*8))-1) :
00222 (mi_safe_mul(share->base.pack_reclength,
00223 (uint64_t) 1 << (share->base.rec_reflength*8))-1);
00224 max_key_file_length=
00225 mi_safe_mul(MI_MIN_KEY_BLOCK_LENGTH,
00226 ((uint64_t) 1 << (share->base.key_reflength*8))-1);
00227 #if SIZEOF_OFF_T == 4
00228 set_if_smaller(max_data_file_length, INT32_MAX);
00229 set_if_smaller(max_key_file_length, INT32_MAX);
00230 #endif
00231 if (share->base.raid_type)
00232 {
00233 errno=HA_ERR_UNSUPPORTED;
00234 goto err;
00235 }
00236 share->base.max_data_file_length=(internal::my_off_t) max_data_file_length;
00237 share->base.max_key_file_length=(internal::my_off_t) max_key_file_length;
00238
00239 if (share->options & HA_OPTION_COMPRESS_RECORD)
00240 share->base.max_key_length+=2;
00241
00242
00243 share->base.max_key_length+= share->base.key_reflength;
00244
00245 if (!drizzled::memory::multi_malloc(false,
00246 &share,sizeof(*share),
00247 &share->state.rec_per_key_part,sizeof(long)*key_parts,
00248 &share->keyinfo,keys*sizeof(MI_KEYDEF),
00249 &share->uniqueinfo,uniques*sizeof(MI_UNIQUEDEF),
00250 &share->keyparts,
00251 (key_parts+unique_key_parts+keys+uniques) * sizeof(HA_KEYSEG),
00252 &share->rec, (share->base.fields+1)*sizeof(MI_COLUMNDEF),
00253 &share->blobs,sizeof(MI_BLOB)*share->base.blobs,
00254 &share->unique_file_name,strlen(name_buff)+1,
00255 &share->index_file_name,strlen(index_name)+1,
00256 &share->data_file_name,strlen(data_name)+1,
00257 &share->state.key_root,keys*sizeof(uint64_t),
00258 &share->state.key_del,
00259 (share->state.header.max_block_size_index*sizeof(uint64_t)),
00260 NULL))
00261 goto err;
00262 errpos=4;
00263 *share=share_buff;
00264 memcpy(share->state.rec_per_key_part, rec_per_key_part,
00265 sizeof(long)*key_parts);
00266 memcpy(share->state.key_root, key_root,
00267 sizeof(internal::my_off_t)*keys);
00268 memcpy(share->state.key_del, key_del,
00269 sizeof(internal::my_off_t) * share->state.header.max_block_size_index);
00270 strcpy(share->unique_file_name, name_buff);
00271 share->unique_name_length= strlen(name_buff);
00272 strcpy(share->index_file_name, index_name);
00273 strcpy(share->data_file_name, data_name);
00274
00275 share->blocksize=min((uint32_t)IO_SIZE,myisam_block_size);
00276 {
00277 HA_KEYSEG *pos=share->keyparts;
00278 for (i=0 ; i < keys ; i++)
00279 {
00280 share->keyinfo[i].share= share;
00281 disk_pos=mi_keydef_read(disk_pos, &share->keyinfo[i]);
00282 disk_pos_assert(disk_pos + share->keyinfo[i].keysegs * HA_KEYSEG_SIZE,
00283 end_pos);
00284 set_if_smaller(share->blocksize,(uint)share->keyinfo[i].block_length);
00285 share->keyinfo[i].seg=pos;
00286 for (j=0 ; j < share->keyinfo[i].keysegs; j++,pos++)
00287 {
00288 disk_pos=mi_keyseg_read(disk_pos, pos);
00289 if (pos->flag & HA_BLOB_PART &&
00290 ! (share->options & (HA_OPTION_COMPRESS_RECORD |
00291 HA_OPTION_PACK_RECORD)))
00292 {
00293 errno= HA_ERR_CRASHED;
00294 goto err;
00295 }
00296 if (pos->type == HA_KEYTYPE_TEXT ||
00297 pos->type == HA_KEYTYPE_VARTEXT1 ||
00298 pos->type == HA_KEYTYPE_VARTEXT2)
00299 {
00300 if (!pos->language)
00301 pos->charset=default_charset_info;
00302 else if (!(pos->charset= get_charset(pos->language)))
00303 {
00304 errno=HA_ERR_UNKNOWN_CHARSET;
00305 goto err;
00306 }
00307 }
00308 else if (pos->type == HA_KEYTYPE_BINARY)
00309 pos->charset= &my_charset_bin;
00310 }
00311 setup_key_functions(share->keyinfo+i);
00312 share->keyinfo[i].end=pos;
00313 pos->type=HA_KEYTYPE_END;
00314 pos->length=share->base.rec_reflength;
00315 pos->null_bit=0;
00316 pos->flag=0;
00317 pos++;
00318 }
00319 for (i=0 ; i < uniques ; i++)
00320 {
00321 disk_pos=mi_uniquedef_read(disk_pos, &share->uniqueinfo[i]);
00322 disk_pos_assert(disk_pos + share->uniqueinfo[i].keysegs *
00323 HA_KEYSEG_SIZE, end_pos);
00324 share->uniqueinfo[i].seg=pos;
00325 for (j=0 ; j < share->uniqueinfo[i].keysegs; j++,pos++)
00326 {
00327 disk_pos=mi_keyseg_read(disk_pos, pos);
00328 if (pos->type == HA_KEYTYPE_TEXT ||
00329 pos->type == HA_KEYTYPE_VARTEXT1 ||
00330 pos->type == HA_KEYTYPE_VARTEXT2)
00331 {
00332 if (!pos->language)
00333 pos->charset=default_charset_info;
00334 else if (!(pos->charset= get_charset(pos->language)))
00335 {
00336 errno=HA_ERR_UNKNOWN_CHARSET;
00337 goto err;
00338 }
00339 }
00340 }
00341 share->uniqueinfo[i].end=pos;
00342 pos->type=HA_KEYTYPE_END;
00343 pos->null_bit=0;
00344 pos->flag=0;
00345 pos++;
00346 }
00347 }
00348
00349 disk_pos_assert(disk_pos + share->base.fields *MI_COLUMNDEF_SIZE, end_pos);
00350 for (i=j=offset=0 ; i < share->base.fields ; i++)
00351 {
00352 disk_pos=mi_recinfo_read(disk_pos,&share->rec[i]);
00353 share->rec[i].pack_type=0;
00354 share->rec[i].huff_tree=0;
00355 share->rec[i].offset=offset;
00356 if (share->rec[i].type == (int) FIELD_BLOB)
00357 {
00358 share->blobs[j].pack_length=
00359 share->rec[i].length-portable_sizeof_char_ptr;
00360 share->blobs[j].offset=offset;
00361 j++;
00362 }
00363 offset+=share->rec[i].length;
00364 }
00365 share->rec[i].type=(int) FIELD_LAST;
00366 if (offset > share->base.reclength)
00367 {
00368 errno= HA_ERR_CRASHED;
00369 goto err;
00370 }
00371
00372 if (! lock_error)
00373 {
00374 lock_error=1;
00375 }
00376
00377 if (mi_open_datafile(&info, share, -1))
00378 goto err;
00379 errpos=5;
00380
00381 share->kfile=kfile;
00382 share->this_process=(ulong) getpid();
00383 share->last_process= share->state.process;
00384 share->base.key_parts=key_parts;
00385 share->base.all_key_parts=key_parts+unique_key_parts;
00386 if (!(share->last_version=share->state.version))
00387 share->last_version=1;
00388 share->rec_reflength=share->base.rec_reflength;
00389 share->base.margin_key_file_length=(share->base.max_key_file_length -
00390 (keys ? MI_INDEX_BLOCK_MARGIN *
00391 share->blocksize * keys : 0));
00392 share->blocksize=min((uint32_t)IO_SIZE,myisam_block_size);
00393 share->data_file_type=STATIC_RECORD;
00394 if (share->options & HA_OPTION_PACK_RECORD)
00395 share->data_file_type = DYNAMIC_RECORD;
00396 free(disk_cache);
00397 disk_cache= NULL;
00398 mi_setup_functions(share);
00399 share->is_log_table= false;
00400 if (myisam_concurrent_insert)
00401 {
00402 share->concurrent_insert=
00403 ((share->options & (HA_OPTION_READ_ONLY_DATA | HA_OPTION_TMP_TABLE |
00404 HA_OPTION_COMPRESS_RECORD |
00405 HA_OPTION_TEMP_COMPRESS_RECORD)) ||
00406 (open_flags & HA_OPEN_TMP_TABLE) || have_rtree) ? 0 : 1;
00407 if (share->concurrent_insert)
00408 {
00409 assert(0);
00410 }
00411 }
00412 }
00413 else
00414 {
00415 share= old_info->s;
00416 if (mode == O_RDWR && share->mode == O_RDONLY)
00417 {
00418 errno=EACCES;
00419 goto err;
00420 }
00421 if (mi_open_datafile(&info, share, old_info->dfile))
00422 goto err;
00423 errpos=5;
00424 have_rtree= old_info->rtree_recursion_state != NULL;
00425 }
00426
00427
00428 if (!drizzled::memory::multi_malloc(MY_WME,
00429 &m_info,sizeof(MI_INFO),
00430 &info.blobs,sizeof(MI_BLOB)*share->base.blobs,
00431 &info.buff,(share->base.max_key_block_length*2+
00432 share->base.max_key_length),
00433 &info.lastkey,share->base.max_key_length*3+1,
00434 &info.first_mbr_key, share->base.max_key_length,
00435 &info.filename, identifier.getPath().length()+1,
00436 &info.rtree_recursion_state,have_rtree ? 1024 : 0,
00437 NULL))
00438 goto err;
00439 errpos=6;
00440
00441 if (!have_rtree)
00442 info.rtree_recursion_state= NULL;
00443
00444 strcpy(info.filename, identifier.getPath().c_str());
00445 memcpy(info.blobs,share->blobs,sizeof(MI_BLOB)*share->base.blobs);
00446 info.lastkey2=info.lastkey+share->base.max_key_length;
00447
00448 info.s=share;
00449 info.lastpos= HA_OFFSET_ERROR;
00450 info.update= (short) (HA_STATE_NEXT_FOUND+HA_STATE_PREV_FOUND);
00451 info.opt_flag=READ_CHECK_USED;
00452 info.this_unique= (ulong) info.dfile;
00453 if (share->data_file_type == COMPRESSED_RECORD)
00454 info.this_unique= share->state.unique;
00455 info.this_loop=0;
00456 info.last_unique= share->state.unique;
00457 info.last_loop= share->state.update_count;
00458 if (mode == O_RDONLY)
00459 share->options|=HA_OPTION_READ_ONLY_DATA;
00460 info.lock_type=F_UNLCK;
00461 info.quick_mode=0;
00462 info.bulk_insert=0;
00463 info.errkey= -1;
00464 info.page_changed=1;
00465 info.read_record=share->read_record;
00466 share->reopen++;
00467 share->write_flag=MYF(MY_NABP | MY_WAIT_IF_FULL);
00468 if (share->options & HA_OPTION_READ_ONLY_DATA)
00469 {
00470 info.lock_type=F_RDLCK;
00471 share->r_locks++;
00472 share->tot_locks++;
00473 }
00474 if ((open_flags & HA_OPEN_TMP_TABLE) ||
00475 (share->options & HA_OPTION_TMP_TABLE))
00476 {
00477 share->temporary=share->delay_key_write=1;
00478 share->write_flag=MYF(MY_NABP);
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489 info.lock_type=F_WRLCK;
00490 }
00491
00492 share->delay_key_write= 1;
00493 info.state= &share->state.state;
00494
00495
00496
00497
00498 if (!mi_alloc_rec_buff(&info, SIZE_MAX, &info.rec_buff))
00499 goto err;
00500 memset(info.rec_buff, 0, mi_get_rec_buff_len(&info, info.rec_buff));
00501
00502 *m_info=info;
00503 myisam_open_list.push_front(m_info);
00504
00505 THR_LOCK_myisam.unlock();
00506 return(m_info);
00507
00508 err:
00509 if (disk_cache != NULL)
00510 free(disk_cache);
00511 save_errno=errno ? errno : HA_ERR_END_OF_FILE;
00512 if ((save_errno == HA_ERR_CRASHED) ||
00513 (save_errno == HA_ERR_CRASHED_ON_USAGE) ||
00514 (save_errno == HA_ERR_CRASHED_ON_REPAIR))
00515 mi_report_error(save_errno, identifier.getPath().c_str());
00516 switch (errpos) {
00517 case 6:
00518 free((unsigned char*) m_info);
00519
00520 case 5:
00521 internal::my_close(info.dfile,MYF(0));
00522 if (old_info)
00523 break;
00524
00525 case 4:
00526 free((unsigned char*) share);
00527
00528 case 3:
00529
00530 case 1:
00531 internal::my_close(kfile,MYF(0));
00532
00533 case 0:
00534 default:
00535 break;
00536 }
00537 THR_LOCK_myisam.unlock();
00538 errno=save_errno;
00539 return (NULL);
00540 }
00541
00542
00543 unsigned char *mi_alloc_rec_buff(MI_INFO *info, size_t length, unsigned char **buf)
00544 {
00545 uint32_t extra;
00546 uint32_t old_length= 0;
00547
00548 if (! *buf || length > (old_length=mi_get_rec_buff_len(info, *buf)))
00549 {
00550 unsigned char *newptr = *buf;
00551
00552
00553 if (length == SIZE_MAX)
00554 {
00555 if (info->s->options & HA_OPTION_COMPRESS_RECORD)
00556 length= max(info->s->base.pack_reclength, info->s->max_pack_length);
00557 else
00558 length= info->s->base.pack_reclength;
00559 length= max((uint32_t)length, info->s->base.max_key_length);
00560
00561 if (newptr && length == old_length)
00562 return newptr;
00563 }
00564
00565 extra= ((info->s->options & HA_OPTION_PACK_RECORD) ?
00566 ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER)+MI_SPLIT_LENGTH+
00567 MI_REC_BUFF_OFFSET : 0);
00568 if (extra && newptr)
00569 newptr-= MI_REC_BUFF_OFFSET;
00570 void *tmpnewptr= NULL;
00571 if (!(tmpnewptr= realloc(newptr, length+extra+8)))
00572 return newptr;
00573 newptr= (unsigned char *)tmpnewptr;
00574 *((uint32_t *) newptr)= (uint32_t) length;
00575 *buf= newptr+(extra ? MI_REC_BUFF_OFFSET : 0);
00576 }
00577 return *buf;
00578 }
00579
00580
00581 static uint64_t mi_safe_mul(uint64_t a, uint64_t b)
00582 {
00583 uint64_t max_val= ~ (uint64_t) 0;
00584
00585 if (!a || max_val / a < b)
00586 return max_val;
00587 return a*b;
00588 }
00589
00590
00591
00592 void mi_setup_functions(register MYISAM_SHARE *share)
00593 {
00594 if (share->options & HA_OPTION_PACK_RECORD)
00595 {
00596 share->read_record=_mi_read_dynamic_record;
00597 share->read_rnd=_mi_read_rnd_dynamic_record;
00598 share->delete_record=_mi_delete_dynamic_record;
00599 share->compare_record=_mi_cmp_dynamic_record;
00600 share->compare_unique=_mi_cmp_dynamic_unique;
00601 share->calc_checksum= mi_checksum;
00602
00603
00604 share->base.pack_reclength+= share->base.pack_bits;
00605 if (share->base.blobs)
00606 {
00607 share->update_record=_mi_update_blob_record;
00608 share->write_record=_mi_write_blob_record;
00609 }
00610 else
00611 {
00612 share->write_record=_mi_write_dynamic_record;
00613 share->update_record=_mi_update_dynamic_record;
00614 }
00615 }
00616 else
00617 {
00618 share->read_record=_mi_read_static_record;
00619 share->read_rnd=_mi_read_rnd_static_record;
00620 share->delete_record=_mi_delete_static_record;
00621 share->compare_record=_mi_cmp_static_record;
00622 share->update_record=_mi_update_static_record;
00623 share->write_record=_mi_write_static_record;
00624 share->compare_unique=_mi_cmp_static_unique;
00625 share->calc_checksum= mi_static_checksum;
00626 }
00627 share->file_read= mi_nommap_pread;
00628 share->file_write= mi_nommap_pwrite;
00629 share->calc_checksum=0;
00630 }
00631
00632
00633 static void setup_key_functions(register MI_KEYDEF *keyinfo)
00634 {
00635 {
00636 keyinfo->ck_insert = _mi_ck_write;
00637 keyinfo->ck_delete = _mi_ck_delete;
00638 }
00639 if (keyinfo->flag & HA_BINARY_PACK_KEY)
00640 {
00641 keyinfo->bin_search=_mi_seq_search;
00642 keyinfo->get_key=_mi_get_binary_pack_key;
00643 keyinfo->pack_key=_mi_calc_bin_pack_key_length;
00644 keyinfo->store_key=_mi_store_bin_pack_key;
00645 }
00646 else if (keyinfo->flag & HA_VAR_LENGTH_KEY)
00647 {
00648 keyinfo->get_key= _mi_get_pack_key;
00649 if (keyinfo->seg[0].flag & HA_PACK_KEY)
00650 {
00651
00652
00653
00654
00655
00656
00657
00658
00659 if (!keyinfo->seg->charset || use_strnxfrm(keyinfo->seg->charset) ||
00660 (keyinfo->seg->flag & HA_NULL_PART) ||
00661 (keyinfo->seg->charset->mbminlen > 1))
00662 keyinfo->bin_search=_mi_seq_search;
00663 else
00664 keyinfo->bin_search=_mi_prefix_search;
00665 keyinfo->pack_key=_mi_calc_var_pack_key_length;
00666 keyinfo->store_key=_mi_store_var_pack_key;
00667 }
00668 else
00669 {
00670 keyinfo->bin_search=_mi_seq_search;
00671 keyinfo->pack_key=_mi_calc_var_key_length;
00672 keyinfo->store_key=_mi_store_static_key;
00673 }
00674 }
00675 else
00676 {
00677 keyinfo->bin_search=_mi_bin_search;
00678 keyinfo->get_key=_mi_get_static_key;
00679 keyinfo->pack_key=_mi_calc_static_key_length;
00680 keyinfo->store_key=_mi_store_static_key;
00681 }
00682 return;
00683 }
00684
00685
00686
00687
00688
00689
00690 uint32_t mi_state_info_write(int file, MI_STATE_INFO *state, uint32_t pWrite)
00691 {
00692 unsigned char buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
00693 unsigned char *ptr=buff;
00694 uint i, keys= (uint) state->header.keys,
00695 key_blocks=state->header.max_block_size_index;
00696
00697 memcpy(ptr,&state->header,sizeof(state->header));
00698 ptr+=sizeof(state->header);
00699
00700
00701 mi_int2store(ptr,state->open_count); ptr +=2;
00702 *ptr++= (unsigned char)state->changed; *ptr++= state->sortkey;
00703 mi_rowstore(ptr,state->state.records); ptr +=8;
00704 mi_rowstore(ptr,state->state.del); ptr +=8;
00705 mi_rowstore(ptr,state->split); ptr +=8;
00706 mi_sizestore(ptr,state->dellink); ptr +=8;
00707 mi_sizestore(ptr,state->state.key_file_length); ptr +=8;
00708 mi_sizestore(ptr,state->state.data_file_length); ptr +=8;
00709 mi_sizestore(ptr,state->state.empty); ptr +=8;
00710 mi_sizestore(ptr,state->state.key_empty); ptr +=8;
00711 mi_int8store(ptr,state->auto_increment); ptr +=8;
00712 mi_int8store(ptr,(uint64_t) state->state.checksum);ptr +=8;
00713 mi_int4store(ptr,state->process); ptr +=4;
00714 mi_int4store(ptr,state->unique); ptr +=4;
00715 mi_int4store(ptr,state->status); ptr +=4;
00716 mi_int4store(ptr,state->update_count); ptr +=4;
00717
00718 ptr+=state->state_diff_length;
00719
00720 for (i=0; i < keys; i++)
00721 {
00722 mi_sizestore(ptr,state->key_root[i]); ptr +=8;
00723 }
00724 for (i=0; i < key_blocks; i++)
00725 {
00726 mi_sizestore(ptr,state->key_del[i]); ptr +=8;
00727 }
00728 if (pWrite & 2)
00729 {
00730 uint32_t key_parts= mi_uint2korr(state->header.key_parts);
00731 mi_int4store(ptr,state->sec_index_changed); ptr +=4;
00732 mi_int4store(ptr,state->sec_index_used); ptr +=4;
00733 mi_int4store(ptr,state->version); ptr +=4;
00734 mi_int8store(ptr,state->key_map); ptr +=8;
00735 mi_int8store(ptr,(uint64_t) state->create_time); ptr +=8;
00736 mi_int8store(ptr,(uint64_t) state->recover_time); ptr +=8;
00737 mi_int8store(ptr,(uint64_t) state->check_time); ptr +=8;
00738 mi_sizestore(ptr,state->rec_per_key_rows); ptr+=8;
00739 for (i=0 ; i < key_parts ; i++)
00740 {
00741 mi_int4store(ptr,state->rec_per_key_part[i]); ptr+=4;
00742 }
00743 }
00744
00745 if (pWrite & 1)
00746 return(my_pwrite(file, buff, (size_t) (ptr-buff), 0L,
00747 MYF(MY_NABP | MY_THREADSAFE)) != 0);
00748 return(internal::my_write(file, buff, (size_t) (ptr-buff),
00749 MYF(MY_NABP)) != 0);
00750 }
00751
00752
00753 static unsigned char *mi_state_info_read(unsigned char *ptr, MI_STATE_INFO *state)
00754 {
00755 uint32_t i,keys,key_parts,key_blocks;
00756 memcpy(&state->header,ptr, sizeof(state->header));
00757 ptr +=sizeof(state->header);
00758 keys=(uint) state->header.keys;
00759 key_parts=mi_uint2korr(state->header.key_parts);
00760 key_blocks=state->header.max_block_size_index;
00761
00762 state->open_count = mi_uint2korr(ptr); ptr +=2;
00763 state->changed= *ptr++;
00764 state->sortkey = (uint) *ptr++;
00765 state->state.records= mi_rowkorr(ptr); ptr +=8;
00766 state->state.del = mi_rowkorr(ptr); ptr +=8;
00767 state->split = mi_rowkorr(ptr); ptr +=8;
00768 state->dellink= mi_sizekorr(ptr); ptr +=8;
00769 state->state.key_file_length = mi_sizekorr(ptr); ptr +=8;
00770 state->state.data_file_length= mi_sizekorr(ptr); ptr +=8;
00771 state->state.empty = mi_sizekorr(ptr); ptr +=8;
00772 state->state.key_empty= mi_sizekorr(ptr); ptr +=8;
00773 state->auto_increment=mi_uint8korr(ptr); ptr +=8;
00774 state->state.checksum=(internal::ha_checksum) mi_uint8korr(ptr); ptr +=8;
00775 state->process= mi_uint4korr(ptr); ptr +=4;
00776 state->unique = mi_uint4korr(ptr); ptr +=4;
00777 state->status = mi_uint4korr(ptr); ptr +=4;
00778 state->update_count=mi_uint4korr(ptr); ptr +=4;
00779
00780 ptr+= state->state_diff_length;
00781
00782 for (i=0; i < keys; i++)
00783 {
00784 state->key_root[i]= mi_sizekorr(ptr); ptr +=8;
00785 }
00786 for (i=0; i < key_blocks; i++)
00787 {
00788 state->key_del[i] = mi_sizekorr(ptr); ptr +=8;
00789 }
00790 state->sec_index_changed = mi_uint4korr(ptr); ptr +=4;
00791 state->sec_index_used = mi_uint4korr(ptr); ptr +=4;
00792 state->version = mi_uint4korr(ptr); ptr +=4;
00793 state->key_map = mi_uint8korr(ptr); ptr +=8;
00794 state->create_time = (time_t) mi_sizekorr(ptr); ptr +=8;
00795 state->recover_time =(time_t) mi_sizekorr(ptr); ptr +=8;
00796 state->check_time = (time_t) mi_sizekorr(ptr); ptr +=8;
00797 state->rec_per_key_rows=mi_sizekorr(ptr); ptr +=8;
00798 for (i=0 ; i < key_parts ; i++)
00799 {
00800 state->rec_per_key_part[i]= mi_uint4korr(ptr); ptr+=4;
00801 }
00802 return ptr;
00803 }
00804
00805
00806 uint32_t mi_state_info_read_dsk(int file, MI_STATE_INFO *state, bool pRead)
00807 {
00808 unsigned char buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
00809
00810 if (pRead)
00811 {
00812 if (my_pread(file, buff, state->state_length,0L, MYF(MY_NABP)))
00813 return 1;
00814 }
00815 else if (internal::my_read(file, buff, state->state_length,MYF(MY_NABP)))
00816 return 1;
00817 mi_state_info_read(buff, state);
00818
00819 return 0;
00820 }
00821
00822
00823
00824
00825
00826
00827 uint32_t mi_base_info_write(int file, MI_BASE_INFO *base)
00828 {
00829 unsigned char buff[MI_BASE_INFO_SIZE], *ptr=buff;
00830
00831 mi_sizestore(ptr,base->keystart); ptr +=8;
00832 mi_sizestore(ptr,base->max_data_file_length); ptr +=8;
00833 mi_sizestore(ptr,base->max_key_file_length); ptr +=8;
00834 mi_rowstore(ptr,base->records); ptr +=8;
00835 mi_rowstore(ptr,base->reloc); ptr +=8;
00836 mi_int4store(ptr,base->mean_row_length); ptr +=4;
00837 mi_int4store(ptr,base->reclength); ptr +=4;
00838 mi_int4store(ptr,base->pack_reclength); ptr +=4;
00839 mi_int4store(ptr,base->min_pack_length); ptr +=4;
00840 mi_int4store(ptr,base->max_pack_length); ptr +=4;
00841 mi_int4store(ptr,base->min_block_length); ptr +=4;
00842 mi_int4store(ptr,base->fields); ptr +=4;
00843 mi_int4store(ptr,base->pack_fields); ptr +=4;
00844 *ptr++=base->rec_reflength;
00845 *ptr++=base->key_reflength;
00846 *ptr++=base->keys;
00847 *ptr++=base->auto_key;
00848 mi_int2store(ptr,base->pack_bits); ptr +=2;
00849 mi_int2store(ptr,base->blobs); ptr +=2;
00850 mi_int2store(ptr,base->max_key_block_length); ptr +=2;
00851 mi_int2store(ptr,base->max_key_length); ptr +=2;
00852 mi_int2store(ptr,base->extra_alloc_bytes); ptr +=2;
00853 *ptr++= base->extra_alloc_procent;
00854
00855 *ptr++= 0;
00856 mi_int2store(ptr,UINT16_C(0)); ptr +=2;
00857 mi_int4store(ptr,UINT32_C(0)); ptr +=4;
00858
00859 memset(ptr, 0, 6); ptr +=6;
00860 return internal::my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
00861 }
00862
00863
00864 static unsigned char *my_n_base_info_read(unsigned char *ptr, MI_BASE_INFO *base)
00865 {
00866 base->keystart = mi_sizekorr(ptr); ptr +=8;
00867 base->max_data_file_length = mi_sizekorr(ptr); ptr +=8;
00868 base->max_key_file_length = mi_sizekorr(ptr); ptr +=8;
00869 base->records = (ha_rows) mi_sizekorr(ptr); ptr +=8;
00870 base->reloc = (ha_rows) mi_sizekorr(ptr); ptr +=8;
00871 base->mean_row_length = mi_uint4korr(ptr); ptr +=4;
00872 base->reclength = mi_uint4korr(ptr); ptr +=4;
00873 base->pack_reclength = mi_uint4korr(ptr); ptr +=4;
00874 base->min_pack_length = mi_uint4korr(ptr); ptr +=4;
00875 base->max_pack_length = mi_uint4korr(ptr); ptr +=4;
00876 base->min_block_length = mi_uint4korr(ptr); ptr +=4;
00877 base->fields = mi_uint4korr(ptr); ptr +=4;
00878 base->pack_fields = mi_uint4korr(ptr); ptr +=4;
00879
00880 base->rec_reflength = *ptr++;
00881 base->key_reflength = *ptr++;
00882 base->keys= *ptr++;
00883 base->auto_key= *ptr++;
00884 base->pack_bits = mi_uint2korr(ptr); ptr +=2;
00885 base->blobs = mi_uint2korr(ptr); ptr +=2;
00886 base->max_key_block_length= mi_uint2korr(ptr); ptr +=2;
00887 base->max_key_length = mi_uint2korr(ptr); ptr +=2;
00888 base->extra_alloc_bytes = mi_uint2korr(ptr); ptr +=2;
00889 base->extra_alloc_procent = *ptr++;
00890
00891
00892 ptr+= 7;
00893
00894 ptr+=6;
00895 return ptr;
00896 }
00897
00898
00899
00900
00901
00902 uint32_t mi_keydef_write(int file, MI_KEYDEF *keydef)
00903 {
00904 unsigned char buff[MI_KEYDEF_SIZE];
00905 unsigned char *ptr=buff;
00906
00907 *ptr++ = (unsigned char) keydef->keysegs;
00908 *ptr++ = keydef->key_alg;
00909 mi_int2store(ptr,keydef->flag); ptr +=2;
00910 mi_int2store(ptr,keydef->block_length); ptr +=2;
00911 mi_int2store(ptr,keydef->keylength); ptr +=2;
00912 mi_int2store(ptr,keydef->minlength); ptr +=2;
00913 mi_int2store(ptr,keydef->maxlength); ptr +=2;
00914 return internal::my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
00915 }
00916
00917 static unsigned char *mi_keydef_read(unsigned char *ptr, MI_KEYDEF *keydef)
00918 {
00919 keydef->keysegs = (uint) *ptr++;
00920 keydef->key_alg = *ptr++;
00921
00922 keydef->flag = mi_uint2korr(ptr); ptr +=2;
00923 keydef->block_length = mi_uint2korr(ptr); ptr +=2;
00924 keydef->keylength = mi_uint2korr(ptr); ptr +=2;
00925 keydef->minlength = mi_uint2korr(ptr); ptr +=2;
00926 keydef->maxlength = mi_uint2korr(ptr); ptr +=2;
00927 keydef->block_size_index= keydef->block_length/MI_MIN_KEY_BLOCK_LENGTH-1;
00928 keydef->underflow_block_length=keydef->block_length/3;
00929 keydef->version = 0;
00930 return ptr;
00931 }
00932
00933
00934
00935
00936
00937 int mi_keyseg_write(int file, const HA_KEYSEG *keyseg)
00938 {
00939 unsigned char buff[HA_KEYSEG_SIZE];
00940 unsigned char *ptr=buff;
00941 ulong pos;
00942
00943 *ptr++= keyseg->type;
00944 *ptr++= keyseg->language;
00945 *ptr++= keyseg->null_bit;
00946 *ptr++= keyseg->bit_start;
00947 *ptr++= keyseg->bit_end;
00948 *ptr++= keyseg->bit_length;
00949 mi_int2store(ptr,keyseg->flag); ptr+=2;
00950 mi_int2store(ptr,keyseg->length); ptr+=2;
00951 mi_int4store(ptr,keyseg->start); ptr+=4;
00952 pos= keyseg->null_bit ? keyseg->null_pos : keyseg->bit_pos;
00953 mi_int4store(ptr, pos);
00954 ptr+=4;
00955
00956 return internal::my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
00957 }
00958
00959
00960 static unsigned char *mi_keyseg_read(unsigned char *ptr, HA_KEYSEG *keyseg)
00961 {
00962 keyseg->type = *ptr++;
00963 keyseg->language = *ptr++;
00964 keyseg->null_bit = *ptr++;
00965 keyseg->bit_start = *ptr++;
00966 keyseg->bit_end = *ptr++;
00967 keyseg->bit_length = *ptr++;
00968 keyseg->flag = mi_uint2korr(ptr); ptr +=2;
00969 keyseg->length = mi_uint2korr(ptr); ptr +=2;
00970 keyseg->start = mi_uint4korr(ptr); ptr +=4;
00971 keyseg->null_pos = mi_uint4korr(ptr); ptr +=4;
00972 keyseg->charset=0;
00973 if (keyseg->null_bit)
00974 keyseg->bit_pos= (uint16_t)(keyseg->null_pos + (keyseg->null_bit == 7));
00975 else
00976 {
00977 keyseg->bit_pos= (uint16_t)keyseg->null_pos;
00978 keyseg->null_pos= 0;
00979 }
00980 return ptr;
00981 }
00982
00983
00984
00985
00986
00987 uint32_t mi_uniquedef_write(int file, MI_UNIQUEDEF *def)
00988 {
00989 unsigned char buff[MI_UNIQUEDEF_SIZE];
00990 unsigned char *ptr=buff;
00991
00992 mi_int2store(ptr,def->keysegs); ptr+=2;
00993 *ptr++= (unsigned char) def->key;
00994 *ptr++ = (unsigned char) def->null_are_equal;
00995
00996 return internal::my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
00997 }
00998
00999 static unsigned char *mi_uniquedef_read(unsigned char *ptr, MI_UNIQUEDEF *def)
01000 {
01001 def->keysegs = mi_uint2korr(ptr);
01002 def->key = ptr[2];
01003 def->null_are_equal=ptr[3];
01004 return ptr+4;
01005 }
01006
01007
01008
01009
01010
01011 uint32_t mi_recinfo_write(int file, MI_COLUMNDEF *recinfo)
01012 {
01013 unsigned char buff[MI_COLUMNDEF_SIZE];
01014 unsigned char *ptr=buff;
01015
01016 mi_int2store(ptr,recinfo->type); ptr +=2;
01017 mi_int2store(ptr,recinfo->length); ptr +=2;
01018 *ptr++ = recinfo->null_bit;
01019 mi_int2store(ptr,recinfo->null_pos); ptr+= 2;
01020 return internal::my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
01021 }
01022
01023 static unsigned char *mi_recinfo_read(unsigned char *ptr, MI_COLUMNDEF *recinfo)
01024 {
01025 recinfo->type= mi_sint2korr(ptr); ptr +=2;
01026 recinfo->length=mi_uint2korr(ptr); ptr +=2;
01027 recinfo->null_bit= (uint8_t) *ptr++;
01028 recinfo->null_pos=mi_uint2korr(ptr); ptr +=2;
01029 return ptr;
01030 }
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041 int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, int file_to_dup)
01042 {
01043 (void)file_to_dup;
01044 info->dfile=internal::my_open(share->data_file_name, share->mode,
01045 MYF(MY_WME));
01046 return info->dfile >= 0 ? 0 : 1;
01047 }
01048
01049
01050 int mi_open_keyfile(MYISAM_SHARE *share)
01051 {
01052 if ((share->kfile=internal::my_open(share->unique_file_name, share->mode,
01053 MYF(MY_WME))) < 0)
01054 return 1;
01055 return 0;
01056 }
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073 int mi_disable_indexes(MI_INFO *info)
01074 {
01075 MYISAM_SHARE *share= info->s;
01076
01077 mi_clear_all_keys_active(share->state.key_map);
01078 return 0;
01079 }
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101 int mi_enable_indexes(MI_INFO *info)
01102 {
01103 int error= 0;
01104 MYISAM_SHARE *share= info->s;
01105
01106 if (share->state.state.data_file_length ||
01107 (share->state.state.key_file_length != share->base.keystart))
01108 {
01109 mi_print_error(info->s, HA_ERR_CRASHED);
01110 error= HA_ERR_CRASHED;
01111 }
01112 else
01113 mi_set_all_keys_active(share->state.key_map, share->base.keys);
01114 return error;
01115 }
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134 int mi_indexes_are_disabled(MI_INFO *info)
01135 {
01136 MYISAM_SHARE *share= info->s;
01137
01138
01139
01140
01141
01142
01143 if (!share->base.keys ||
01144 (mi_is_all_keys_active(share->state.key_map, share->base.keys)))
01145 return 0;
01146
01147
01148 if (mi_is_any_key_active(share->state.key_map))
01149 return 1;
01150
01151
01152
01153
01154
01155 return 2;
01156 }
01157