mi_open.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:33k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    
  3.    This program is free software; you can redistribute it and/or modify
  4.    it under the terms of the GNU General Public License as published by
  5.    the Free Software Foundation; either version 2 of the License, or
  6.    (at your option) any later version.
  7.    
  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.
  12.    
  13.    You should have received a copy of the GNU General Public License
  14.    along with this program; if not, write to the Free Software
  15.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  16. /* open a isam-database */
  17. #include "fulltext.h"
  18. #include <m_ctype.h>
  19. #if defined(MSDOS) || defined(__WIN__)
  20. #ifdef __WIN__
  21. #include <fcntl.h>
  22. #else
  23. #include <process.h> /* Prototype for getpid */
  24. #endif
  25. #endif
  26. #ifdef VMS
  27. #include "static.c"
  28. #endif
  29. static void setup_functions(MYISAM_SHARE *info);
  30. static void setup_key_functions(MI_KEYDEF *keyinfo);
  31. #define get_next_element(to,pos,size) { memcpy((char*) to,pos,(size_t) size); 
  32. pos+=size;}
  33. /******************************************************************************
  34. ** Return the shared struct if the table is already open.
  35. ** In MySQL the server will handle version issues.
  36. ******************************************************************************/
  37. static MI_INFO *test_if_reopen(char *filename)
  38. {
  39.   LIST *pos;
  40.   for (pos=myisam_open_list ; pos ; pos=pos->next)
  41.   {
  42.     MI_INFO *info=(MI_INFO*) pos->data;
  43.     MYISAM_SHARE *share=info->s;
  44.     if (!strcmp(share->filename,filename) && share->last_version)
  45.       return info;
  46.   }
  47.   return 0;
  48. }
  49. /******************************************************************************
  50.   open a MyISAM database.
  51.   See my_base.h for the handle_locking argument
  52.   if handle_locking and HA_OPEN_ABORT_IF_CRASHED then abort if the table
  53.   is marked crashed or if we are not using locking and the table doesn't
  54.   have an open count of 0.
  55. ******************************************************************************/
  56. MI_INFO *mi_open(const char *name, int mode, uint open_flags)
  57. {
  58.   int lock_error,kfile,open_mode,save_errno;
  59.   uint i,j,len,errpos,head_length,base_pos,offset,info_length,extra,keys,
  60.     key_parts,unique_key_parts,tmp_length,uniques;
  61.   char name_buff[FN_REFLEN],*disk_cache,*disk_pos;
  62.   MI_INFO info,*m_info,*old_info;
  63.   MYISAM_SHARE share_buff,*share;
  64.   ulong rec_per_key_part[MI_MAX_POSSIBLE_KEY*MI_MAX_KEY_SEG];
  65.   my_off_t key_root[MI_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
  66.   ulonglong max_key_file_length, max_data_file_length;
  67.   DBUG_ENTER("mi_open");
  68.   LINT_INIT(m_info);
  69.   kfile= -1;
  70.   lock_error=1;
  71.   errpos=0;
  72.   head_length=sizeof(share_buff.state.header);
  73.   bzero((byte*) &info,sizeof(info));
  74.   VOID(fn_format(name_buff,name,"",MI_NAME_IEXT,4+16+32));
  75.   pthread_mutex_lock(&THR_LOCK_myisam);
  76.   if (!(old_info=test_if_reopen(name_buff)))
  77.   {
  78.     share= &share_buff;
  79.     bzero((gptr) &share_buff,sizeof(share_buff));
  80.     share_buff.state.rec_per_key_part=rec_per_key_part;
  81.     share_buff.state.key_root=key_root;
  82.     share_buff.state.key_del=key_del;
  83.     if ((kfile=my_open(name_buff,(open_mode=O_RDWR) | O_SHARE,MYF(0))) < 0)
  84.     {
  85.       if ((errno != EROFS && errno != EACCES) ||
  86.   mode != O_RDONLY ||
  87.   (kfile=my_open(name_buff,(open_mode=O_RDONLY) | O_SHARE,MYF(0))) < 0)
  88. goto err;
  89.     }
  90.     share->mode=open_mode;
  91.     errpos=1;
  92.     if (my_read(kfile,(char*) share->state.header.file_version,head_length,
  93. MYF(MY_NABP)))
  94.       goto err;
  95.     if (memcmp((byte*) share->state.header.file_version,
  96.        (byte*) myisam_file_magic, 4))
  97.     {
  98.       DBUG_PRINT("error",("Wrong header in %s",name_buff));
  99.       DBUG_DUMP("error_dump",(char*) share->state.header.file_version,
  100. head_length);
  101.       my_errno=HA_ERR_CRASHED;
  102.       goto err;
  103.     }
  104.     share->options= mi_uint2korr(share->state.header.options);
  105.     if (share->options &
  106. ~(HA_OPTION_PACK_RECORD | HA_OPTION_PACK_KEYS |
  107.   HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA |
  108.   HA_OPTION_TEMP_COMPRESS_RECORD | HA_OPTION_CHECKSUM |
  109.   HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE))
  110.     {
  111.       DBUG_PRINT("error",("wrong options: 0x%lx",
  112.   share->options));
  113.       my_errno=HA_ERR_OLD_FILE;
  114.       goto err;
  115.     }
  116.     info_length=mi_uint2korr(share->state.header.header_length);
  117.     base_pos=mi_uint2korr(share->state.header.base_pos);
  118.     if (!(disk_cache=(char*) my_alloca(info_length)))
  119.     {
  120.       my_errno=ENOMEM;
  121.       goto err;
  122.     }
  123.     errpos=2;
  124.     VOID(my_seek(kfile,0L,MY_SEEK_SET,MYF(0)));
  125.     if (!(open_flags & HA_OPEN_TMP_TABLE))
  126.     {
  127.       if ((lock_error=my_lock(kfile,F_RDLCK,0L,F_TO_EOF,
  128.       MYF(open_flags & HA_OPEN_WAIT_IF_LOCKED ?
  129.   0 : MY_DONT_WAIT))) &&
  130.   !(open_flags & HA_OPEN_IGNORE_IF_LOCKED))
  131. goto err;
  132.     }
  133.     errpos=3;
  134.     if (my_read(kfile,disk_cache,info_length,MYF(MY_NABP)))
  135.       goto err;
  136.     len=mi_uint2korr(share->state.header.state_info_length);
  137.     keys=    (uint) share->state.header.keys;
  138.     uniques= (uint) share->state.header.uniques;
  139.     key_parts= mi_uint2korr(share->state.header.key_parts);
  140.     unique_key_parts= mi_uint2korr(share->state.header.unique_key_parts);
  141.     tmp_length=(MI_STATE_INFO_SIZE + keys * MI_STATE_KEY_SIZE +
  142. key_parts*MI_STATE_KEYSEG_SIZE +
  143. share->state.header.max_block_size*MI_STATE_KEYBLOCK_SIZE);
  144.     if (len != MI_STATE_INFO_SIZE)
  145.     {
  146.       DBUG_PRINT("warning",
  147.  ("saved_state_info_length: %d  state_info_length: %d",
  148.   len,MI_STATE_INFO_SIZE));
  149.     }
  150.     share->state_diff_length=len-MI_STATE_INFO_SIZE;
  151.     mi_state_info_read(disk_cache, &share->state);
  152.     len= mi_uint2korr(share->state.header.base_info_length);
  153.     if (len != MI_BASE_INFO_SIZE)
  154.     {
  155.       DBUG_PRINT("warning",("saved_base_info_length: %d  base_info_length: %d",
  156.     len,MI_BASE_INFO_SIZE))
  157.     }
  158.     disk_pos=my_n_base_info_read(disk_cache+base_pos, &share->base);
  159.     share->state.state_length=base_pos;
  160.     if (!(open_flags & HA_OPEN_FOR_REPAIR) &&
  161. ((share->state.changed & STATE_CRASHED) ||
  162.  ((open_flags & HA_OPEN_ABORT_IF_CRASHED) &&
  163.   (my_disable_locking && share->state.open_count))))
  164.     {
  165.       DBUG_PRINT("error",("Table is marked as crashed"));
  166.       my_errno=((share->state.changed & STATE_CRASHED_ON_REPAIR) ?
  167. HA_ERR_CRASHED_ON_REPAIR : HA_ERR_CRASHED_ON_USAGE);
  168.       goto err;
  169.     }
  170.     /* sanity check */
  171.     if (share->base.keystart > 65535 || share->base.rec_reflength > 8)
  172.     {
  173.       my_errno=HA_ERR_CRASHED;
  174.       goto err;
  175.     }
  176.     if (share->base.max_key_length > MI_MAX_KEY_BUFF || keys > MI_MAX_KEY ||
  177. key_parts >= MI_MAX_KEY * MI_MAX_KEY_SEG)
  178.     {
  179.       DBUG_PRINT("error",("Wrong key info:  Max_key_length: %d  keys: %d  key_parts: %d", share->base.max_key_length, keys, key_parts));
  180.       my_errno=HA_ERR_UNSUPPORTED;
  181.       goto err;
  182.     }
  183.     /* Correct max_file_length based on length of sizeof_t */
  184.     max_data_file_length=
  185.       (share->options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ?
  186.       (((ulonglong) 1 << (share->base.rec_reflength*8))-1) :
  187.       (mi_safe_mul(share->base.reclength,
  188.    (ulonglong) 1 << (share->base.rec_reflength*8))-1);
  189.     max_key_file_length=
  190.       mi_safe_mul(MI_KEY_BLOCK_LENGTH,
  191.   ((ulonglong) 1 << (share->base.key_reflength*8))-1);
  192. #if SIZEOF_OFF_T == 4
  193.     set_if_smaller(max_data_file_length, INT_MAX32);
  194.     set_if_smaller(max_key_file_length, INT_MAX32);
  195. #endif
  196. #if USE_RAID && SYSTEM_SIZEOF_OFF_T == 4
  197.     set_if_smaller(max_key_file_length, INT_MAX32);
  198.     if (!share->base.raid_type)
  199.     {
  200.       set_if_smaller(max_data_file_length, INT_MAX32);
  201.     }
  202.     else
  203.     {
  204.       set_if_smaller(max_data_file_length,
  205.      (ulonglong) share->base.raid_chunks << 31);
  206.     }
  207. #elif !defined(USE_RAID)
  208.     if (share->base.raid_type)
  209.     {
  210.       DBUG_PRINT("error",("Table uses RAID but we don't have RAID support"));
  211.       my_errno=HA_ERR_UNSUPPORTED;
  212.       goto err;
  213.     }
  214. #endif
  215.     share->base.max_data_file_length=(my_off_t) max_data_file_length;
  216.     share->base.max_key_file_length=(my_off_t) max_key_file_length;
  217.     if (share->options & HA_OPTION_COMPRESS_RECORD)
  218.       share->base.max_key_length+=2; /* For safety */
  219.     if (!my_multi_malloc(MY_WME,
  220.  &share,sizeof(*share),
  221.  &share->state.rec_per_key_part,sizeof(long)*key_parts,
  222.  &share->keyinfo,keys*sizeof(MI_KEYDEF),
  223.  &share->uniqueinfo,uniques*sizeof(MI_UNIQUEDEF),
  224.  &share->keyparts,
  225.  (key_parts+unique_key_parts+keys+uniques) *
  226.  sizeof(MI_KEYSEG),
  227.  &share->rec,
  228.  (share->base.fields+1)*sizeof(MI_COLUMNDEF),
  229.  &share->blobs,sizeof(MI_BLOB)*share->base.blobs,
  230.  &share->filename,strlen(name_buff)+1,
  231.  &share->state.key_root,keys*sizeof(my_off_t),
  232.  &share->state.key_del,
  233.  (share->state.header.max_block_size*sizeof(my_off_t)),
  234. #ifdef THREAD
  235.  &share->key_root_lock,sizeof(rw_lock_t)*keys,
  236. #endif
  237.  NullS))
  238.       goto err;
  239.     errpos=4;
  240.     *share=share_buff;
  241.     memcpy((char*) share->state.rec_per_key_part,
  242.    (char*) rec_per_key_part, sizeof(long)*key_parts);
  243.     memcpy((char*) share->state.key_root,
  244.    (char*) key_root, sizeof(my_off_t)*keys);
  245.     memcpy((char*) share->state.key_del,
  246.    (char*) key_del, (sizeof(my_off_t) *
  247.      share->state.header.max_block_size));
  248.     strmov(share->filename,name_buff);
  249.     share->blocksize=min(IO_SIZE,myisam_block_size);
  250.     {
  251.       MI_KEYSEG *pos=share->keyparts;
  252.       for (i=0 ; i < keys ; i++)
  253.       {
  254. disk_pos=mi_keydef_read(disk_pos, &share->keyinfo[i]);
  255. set_if_smaller(share->blocksize,share->keyinfo[i].block_length);
  256. share->keyinfo[i].seg=pos;
  257. for (j=0 ; j < share->keyinfo[i].keysegs; j++,pos++)
  258. {
  259.   disk_pos=mi_keyseg_read(disk_pos, pos);
  260.   if (pos->type == HA_KEYTYPE_TEXT || pos->type == HA_KEYTYPE_VARTEXT)
  261.   {
  262.     if (!pos->language)
  263.       pos->charset=default_charset_info;
  264.     else if (!(pos->charset= get_charset(pos->language, MYF(MY_WME))))
  265.     {
  266.       my_errno=HA_ERR_UNKNOWN_CHARSET;
  267.       goto err;
  268.     }
  269.   }
  270. }
  271. if (share->keyinfo[i].flag & HA_FULLTEXT)     /* SerG */
  272. {
  273.   share->keyinfo[i].seg=pos-FT_SEGS;     /* SerG */
  274.   share->fulltext_index=1;
  275. }
  276. share->keyinfo[i].end=pos;
  277. pos->type=HA_KEYTYPE_END; /* End */
  278. pos->length=share->base.rec_reflength;
  279. pos->null_bit=0;
  280. pos++;
  281.       }
  282.       for (i=0 ; i < uniques ; i++)
  283.       {
  284. disk_pos=mi_uniquedef_read(disk_pos, &share->uniqueinfo[i]);
  285. share->uniqueinfo[i].seg=pos;
  286. for (j=0 ; j < share->uniqueinfo[i].keysegs; j++,pos++)
  287. {
  288.   disk_pos=mi_keyseg_read(disk_pos, pos);
  289.   if (pos->type == HA_KEYTYPE_TEXT || pos->type == HA_KEYTYPE_VARTEXT)
  290.   {
  291.     if (!pos->language)
  292.       pos->charset=default_charset_info;
  293.     else if (!(pos->charset= get_charset(pos->language, MYF(MY_WME))))
  294.     {
  295.       my_errno=HA_ERR_UNKNOWN_CHARSET;
  296.       goto err;
  297.     }
  298.   }
  299. }
  300. share->uniqueinfo[i].end=pos;
  301. pos->type=HA_KEYTYPE_END; /* End */
  302. pos->null_bit=0;
  303. pos++;
  304.       }
  305.     }
  306.     for (i=0 ; i < keys ; i++)
  307.       setup_key_functions(share->keyinfo+i);
  308.     for (i=j=offset=0 ; i < share->base.fields ; i++)
  309.     {
  310.       disk_pos=mi_recinfo_read(disk_pos,&share->rec[i]);
  311.       share->rec[i].pack_type=0;
  312.       share->rec[i].huff_tree=0;
  313.       share->rec[i].offset=offset;
  314.       if (share->rec[i].type == (int) FIELD_BLOB)
  315.       {
  316. share->blobs[j].pack_length=
  317.   share->rec[i].length-mi_portable_sizeof_char_ptr;;
  318. share->blobs[j].offset=offset;
  319. j++;
  320.       }
  321.       offset+=share->rec[i].length;
  322.     }
  323.     share->rec[i].type=(int) FIELD_LAST; /* End marker */
  324.     if (! lock_error)
  325.     {
  326.       VOID(my_lock(kfile,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE)));
  327.       lock_error=1; /* Database unlocked */
  328.     }
  329.     if (mi_open_datafile(&info, share))
  330.       goto err;
  331.     errpos=5;
  332.     share->kfile=kfile;
  333.     share->this_process=(ulong) getpid();
  334.     share->rnd= (int)  share->this_process; /* rnd-counter for splits */
  335. #ifndef DBUG_OFF
  336.     share->rnd=0; /* To make things repeatable */
  337. #endif
  338.     share->last_process= share->state.process;
  339.     share->base.key_parts=key_parts;
  340.     share->base.all_key_parts=key_parts+unique_key_parts;
  341.     if (!(share->last_version=share->state.version))
  342.       share->last_version=1; /* Safety */
  343.     share->rec_reflength=share->base.rec_reflength; /* May be changed */
  344.     share->base.margin_key_file_length=(share->base.max_key_file_length -
  345. (keys ? MI_INDEX_BLOCK_MARGIN *
  346.  share->blocksize * keys : 0));
  347.     share->blocksize=min(IO_SIZE,myisam_block_size);
  348.     share->data_file_type=STATIC_RECORD;
  349.     if (share->options & HA_OPTION_COMPRESS_RECORD)
  350.     {
  351.       share->data_file_type = COMPRESSED_RECORD;
  352.       share->options|= HA_OPTION_READ_ONLY_DATA;
  353.       info.s=share;
  354.       if (_mi_read_pack_info(&info,
  355.      (pbool)
  356.      test(!(share->options &
  357.     (HA_OPTION_PACK_RECORD |
  358.      HA_OPTION_TEMP_COMPRESS_RECORD)))))
  359. goto err;
  360.     }
  361.     else if (share->options & HA_OPTION_PACK_RECORD)
  362.       share->data_file_type = DYNAMIC_RECORD;
  363.     my_afree((gptr) disk_cache);
  364.     setup_functions(share);
  365. #ifdef THREAD
  366.     thr_lock_init(&share->lock);
  367.     VOID(pthread_mutex_init(&share->intern_lock,NULL));
  368.     for (i=0; i<keys; i++)
  369.       VOID(my_rwlock_init(&share->key_root_lock[i], NULL));
  370.     if (!thr_lock_inited)
  371.     {
  372.       /* Probably a single threaded program; Don't use concurrent inserts */
  373.       myisam_concurrent_insert=0;
  374.     }
  375.     else if (myisam_concurrent_insert)
  376.     {
  377.       share->concurrent_insert=
  378. ((share->options & (HA_OPTION_READ_ONLY_DATA | HA_OPTION_TMP_TABLE |
  379.    HA_OPTION_COMPRESS_RECORD |
  380.    HA_OPTION_TEMP_COMPRESS_RECORD)) ||
  381.  (open_flags & HA_OPEN_TMP_TABLE)) ? 0 : 1;
  382.       if (share->concurrent_insert)
  383.       {
  384. share->lock.get_status=mi_get_status;
  385. share->lock.copy_status=mi_copy_status;
  386. share->lock.update_status=mi_update_status;
  387. share->lock.check_status=mi_check_status;
  388.       }
  389.     }
  390. #endif
  391.   }
  392.   else
  393.   {
  394.     share= old_info->s;
  395.     if (mode == O_RDWR && share->mode == O_RDONLY)
  396.     {
  397.       my_errno=EACCES; /* Can't open in write mode */
  398.       goto err;
  399.     }
  400.     if (mi_open_datafile(&info, share))
  401.       goto err;
  402.     errpos=5;
  403.   }
  404.   /* alloc and set up private structure parts */
  405.   if (!my_multi_malloc(MY_WME,
  406.        &m_info,sizeof(MI_INFO),
  407.        &info.blobs,sizeof(MI_BLOB)*share->base.blobs,
  408.        &info.buff,(share->base.max_key_block_length*2+
  409.    share->base.max_key_length),
  410.        &info.lastkey,share->base.max_key_length*3+1,
  411.        &info.filename,strlen(name)+1,
  412.        NullS))
  413.     goto err;
  414.   errpos=6;
  415.   strmov(info.filename,name);
  416.   memcpy(info.blobs,share->blobs,sizeof(MI_BLOB)*share->base.blobs);
  417.   info.lastkey2=info.lastkey+share->base.max_key_length;
  418.   info.s=share;
  419.   info.lastpos= HA_OFFSET_ERROR;
  420.   info.update= (short) (HA_STATE_NEXT_FOUND+HA_STATE_PREV_FOUND);
  421.   info.opt_flag=READ_CHECK_USED;
  422.   info.this_unique= (ulong) info.dfile; /* Uniq number in process */
  423.   if (share->data_file_type == COMPRESSED_RECORD)
  424.     info.this_unique= share->state.unique;
  425.   info.this_loop=0; /* Update counter */
  426.   info.last_unique= share->state.unique;
  427.   info.last_loop=   share->state.update_count;
  428.   if (mode == O_RDONLY)
  429.     share->options|=HA_OPTION_READ_ONLY_DATA;
  430.   info.lock_type=F_UNLCK;
  431.   info.quick_mode=0;
  432.   info.errkey= -1;
  433.   info.page_changed=1;
  434.   pthread_mutex_lock(&share->intern_lock);
  435.   info.read_record=share->read_record;
  436.   share->reopen++;
  437.   share->write_flag=MYF(MY_NABP | MY_WAIT_IF_FULL);
  438.   if (share->options & HA_OPTION_READ_ONLY_DATA)
  439.   {
  440.     info.lock_type=F_RDLCK;
  441.     share->r_locks++;
  442.   }
  443.   if ((open_flags & HA_OPEN_TMP_TABLE) ||
  444.       (share->options & HA_OPTION_TMP_TABLE))
  445.   {
  446.     share->temporary=share->delay_key_write=1;
  447.     share->write_flag=MYF(MY_NABP);
  448.     share->w_locks++; /* We don't have to update status */
  449.     info.lock_type=F_WRLCK;
  450.   }
  451.   if (((open_flags & HA_OPEN_DELAY_KEY_WRITE) ||
  452.       (share->options & HA_OPTION_DELAY_KEY_WRITE)) &&
  453.       myisam_delay_key_write)
  454.     share->delay_key_write=1;
  455.   info.state= &share->state.state; /* Change global values by default */
  456.   pthread_mutex_unlock(&share->intern_lock);
  457.   /* Allocate buffer for one record */
  458.   extra=0;
  459.   if (share->options & HA_OPTION_PACK_RECORD)
  460.     extra=ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER)+MI_SPLIT_LENGTH+
  461.       MI_DYN_DELETE_BLOCK_HEADER;
  462.   tmp_length=max(share->base.pack_reclength,share->base.max_key_length);
  463.   info.alloced_rec_buff_length=tmp_length;
  464.   if (!(info.rec_alloc=(byte*) my_malloc(tmp_length+extra+8,
  465.  MYF(MY_WME | MY_ZEROFILL))))
  466.     goto err;
  467.   if (extra)
  468.     info.rec_buff=info.rec_alloc+ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER);
  469.   else
  470.     info.rec_buff=info.rec_alloc;
  471.   *m_info=info;
  472. #ifdef THREAD
  473.   thr_lock_data_init(&share->lock,&m_info->lock,(void*) m_info);
  474. #endif
  475.   m_info->open_list.data=(void*) m_info;
  476.   myisam_open_list=list_add(myisam_open_list,&m_info->open_list);
  477.   pthread_mutex_unlock(&THR_LOCK_myisam);
  478.   if (myisam_log_file >= 0)
  479.   {
  480.     intern_filename(name_buff,share->filename);
  481.     _myisam_log(MI_LOG_OPEN,m_info,name_buff,(uint) strlen(name_buff));
  482.   }
  483.   DBUG_RETURN(m_info);
  484. err:
  485.   save_errno=my_errno ? my_errno : HA_ERR_END_OF_FILE;
  486.   switch (errpos) {
  487.   case 6:
  488.     my_free((gptr) m_info,MYF(0));
  489.     /* fall through */
  490.   case 5:
  491.     VOID(my_close(info.dfile,MYF(0)));
  492.     if (old_info)
  493.       break; /* Don't remove open table */
  494.     /* fall through */
  495.   case 4:
  496.     my_free((gptr) share,MYF(0));
  497.     /* fall through */
  498.   case 3:
  499.     if (! lock_error)
  500.       VOID(my_lock(kfile, F_UNLCK, 0L, F_TO_EOF, MYF(MY_SEEK_NOT_DONE)));
  501.     /* fall through */
  502.   case 2:
  503.     my_afree((gptr) disk_cache);
  504.     /* fall through */
  505.   case 1:
  506.     VOID(my_close(kfile,MYF(0)));
  507.     /* fall through */
  508.   case 0:
  509.   default:
  510.     break;
  511.   }
  512.   pthread_mutex_unlock(&THR_LOCK_myisam);
  513.   my_errno=save_errno;
  514.   DBUG_RETURN (NULL);
  515. } /* mi_open */
  516. ulonglong mi_safe_mul(ulonglong a, ulonglong b)
  517. {
  518.   ulonglong max_val= ~ (ulonglong) 0; /* my_off_t is unsigned */
  519.   if (!a || max_val / a < b)
  520.     return max_val;
  521.   return a*b;
  522. }
  523. /* Set up functions in structs */
  524. static void setup_functions(register MYISAM_SHARE *share)
  525. {
  526.   if (share->options & HA_OPTION_COMPRESS_RECORD)
  527.   {
  528.     share->read_record=_mi_read_pack_record;
  529.     share->read_rnd=_mi_read_rnd_pack_record;
  530.     if (!(share->options & HA_OPTION_TEMP_COMPRESS_RECORD))
  531.       share->calc_checksum=0; /* No checksum */
  532.     else if (share->options & HA_OPTION_PACK_RECORD)
  533.       share->calc_checksum= mi_checksum;
  534.     else
  535.       share->calc_checksum= mi_static_checksum;
  536.   }
  537.   else if (share->options & HA_OPTION_PACK_RECORD)
  538.   {
  539.     share->read_record=_mi_read_dynamic_record;
  540.     share->read_rnd=_mi_read_rnd_dynamic_record;
  541.     share->delete_record=_mi_delete_dynamic_record;
  542.     share->compare_record=_mi_cmp_dynamic_record;
  543.     share->compare_unique=_mi_cmp_dynamic_unique;
  544.     share->calc_checksum= mi_checksum;
  545.     if (share->base.blobs)
  546.     {
  547.       share->update_record=_mi_update_blob_record;
  548.       share->write_record=_mi_write_blob_record;
  549.     }
  550.     else
  551.     {
  552.       share->write_record=_mi_write_dynamic_record;
  553.       share->update_record=_mi_update_dynamic_record;
  554.     }
  555.   }
  556.   else
  557.   {
  558.     share->read_record=_mi_read_static_record;
  559.     share->read_rnd=_mi_read_rnd_static_record;
  560.     share->delete_record=_mi_delete_static_record;
  561.     share->compare_record=_mi_cmp_static_record;
  562.     share->update_record=_mi_update_static_record;
  563.     share->write_record=_mi_write_static_record;
  564.     share->compare_unique=_mi_cmp_static_unique;
  565.     share->calc_checksum= mi_static_checksum;
  566.   }
  567.   if (!(share->options & HA_OPTION_CHECKSUM))
  568.     share->calc_checksum=0;
  569.   return;
  570. }
  571. static void setup_key_functions(register MI_KEYDEF *keyinfo)
  572. {
  573.   if (keyinfo->flag & HA_BINARY_PACK_KEY)
  574.   { /* Simple prefix compression */
  575.     keyinfo->bin_search=_mi_seq_search;
  576.     keyinfo->get_key=_mi_get_binary_pack_key;
  577.     keyinfo->pack_key=_mi_calc_bin_pack_key_length;
  578.     keyinfo->store_key=_mi_store_bin_pack_key;
  579.   }
  580.   else if (keyinfo->flag & HA_VAR_LENGTH_KEY)
  581.   {
  582.     keyinfo->bin_search=_mi_seq_search;
  583.     keyinfo->get_key= _mi_get_pack_key;
  584.     if (keyinfo->seg[0].flag & HA_PACK_KEY)
  585.     { /* Prefix compression */
  586.       keyinfo->pack_key=_mi_calc_var_pack_key_length;
  587.       keyinfo->store_key=_mi_store_var_pack_key;
  588.     }
  589.     else
  590.     {
  591.       keyinfo->pack_key=_mi_calc_var_key_length; /* Variable length key */
  592.       keyinfo->store_key=_mi_store_static_key;
  593.     }
  594.   }
  595.   else
  596.   {
  597.     keyinfo->bin_search=_mi_bin_search;
  598.     keyinfo->get_key=_mi_get_static_key;
  599.     keyinfo->pack_key=_mi_calc_static_key_length;
  600.     keyinfo->store_key=_mi_store_static_key;
  601.   }
  602.   return;
  603. }
  604. /***************************************************************************
  605. ** Function to save and store the header in the index file (.MSI)
  606. ***************************************************************************/
  607. uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite)
  608. {
  609.   uchar  buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
  610.   uchar *ptr=buff;
  611.   uint i, keys= (uint) state->header.keys,
  612. key_blocks=state->header.max_block_size;
  613.   memcpy_fixed(ptr,&state->header,sizeof(state->header));
  614.   ptr+=sizeof(state->header);
  615.   /* open_count must be first because of _mi_mark_file_changed ! */
  616.   mi_int2store(ptr,state->open_count); ptr +=2;
  617.   *ptr++= (uchar)state->changed; *ptr++= state->sortkey;
  618.   mi_rowstore(ptr,state->state.records); ptr +=8;
  619.   mi_rowstore(ptr,state->state.del); ptr +=8;
  620.   mi_rowstore(ptr,state->split); ptr +=8;
  621.   mi_sizestore(ptr,state->dellink); ptr +=8;
  622.   mi_sizestore(ptr,state->state.key_file_length); ptr +=8;
  623.   mi_sizestore(ptr,state->state.data_file_length); ptr +=8;
  624.   mi_sizestore(ptr,state->state.empty); ptr +=8;
  625.   mi_sizestore(ptr,state->state.key_empty); ptr +=8;
  626.   mi_int8store(ptr,state->auto_increment); ptr +=8;
  627.   mi_int8store(ptr,(ulonglong) state->checksum);ptr +=8;
  628.   mi_int4store(ptr,state->process); ptr +=4;
  629.   mi_int4store(ptr,state->unique); ptr +=4;
  630.   mi_int4store(ptr,state->status); ptr +=4;
  631.   mi_int4store(ptr,state->update_count); ptr +=4;
  632.   ptr+=state->state_diff_length;
  633.   for (i=0; i < keys; i++)
  634.   {
  635.     mi_sizestore(ptr,state->key_root[i]); ptr +=8;
  636.   }
  637.   for (i=0; i < key_blocks; i++)
  638.   {
  639.     mi_sizestore(ptr,state->key_del[i]); ptr +=8;
  640.   }
  641.   if (pWrite & 2) /* From isamchk */
  642.   {
  643.     uint key_parts= mi_uint2korr(state->header.key_parts);
  644.     mi_int4store(ptr,state->sec_index_changed); ptr +=4;
  645.     mi_int4store(ptr,state->sec_index_used); ptr +=4;
  646.     mi_int4store(ptr,state->version); ptr +=4;
  647.     mi_int8store(ptr,state->key_map); ptr +=8;
  648.     mi_int8store(ptr,(ulonglong) state->create_time); ptr +=8;
  649.     mi_int8store(ptr,(ulonglong) state->recover_time); ptr +=8;
  650.     mi_int8store(ptr,(ulonglong) state->check_time); ptr +=8;
  651.     mi_sizestore(ptr,state->rec_per_key_rows); ptr+=8;
  652.     for (i=0 ; i < key_parts ; i++)
  653.     {
  654.       mi_int4store(ptr,state->rec_per_key_part[i]);  ptr+=4;
  655.     }
  656.   }
  657.   if (pWrite & 1)
  658.      return my_pwrite(file,(char*) buff, (uint) (ptr-buff), 0L,
  659.       MYF(MY_NABP | MY_THREADSAFE));
  660.   else
  661.     return my_write(file,  (char*) buff, (uint) (ptr-buff), MYF(MY_NABP));
  662. }
  663. char *mi_state_info_read(char *ptr, MI_STATE_INFO *state)
  664. {
  665.   uint i,keys,key_parts,key_blocks;
  666.   memcpy_fixed(&state->header,ptr, sizeof(state->header));
  667.   ptr +=sizeof(state->header);
  668.   keys=(uint) state->header.keys;
  669.   key_parts=mi_uint2korr(state->header.key_parts);
  670.   key_blocks=state->header.max_block_size;
  671.   state->open_count = mi_uint2korr(ptr); ptr +=2;
  672.   state->changed= (bool) *ptr++;
  673.   state->sortkey = (uint) *ptr++;
  674.   state->state.records= mi_rowkorr(ptr); ptr +=8;
  675.   state->state.del = mi_rowkorr(ptr); ptr +=8;
  676.   state->split = mi_rowkorr(ptr); ptr +=8;
  677.   state->dellink= mi_sizekorr(ptr); ptr +=8;
  678.   state->state.key_file_length = mi_sizekorr(ptr); ptr +=8;
  679.   state->state.data_file_length= mi_sizekorr(ptr); ptr +=8;
  680.   state->state.empty = mi_sizekorr(ptr); ptr +=8;
  681.   state->state.key_empty= mi_sizekorr(ptr); ptr +=8;
  682.   state->auto_increment=mi_uint8korr(ptr); ptr +=8;
  683.   state->checksum=(ha_checksum) mi_uint8korr(ptr); ptr +=8;
  684.   state->process= mi_uint4korr(ptr); ptr +=4;
  685.   state->unique = mi_uint4korr(ptr); ptr +=4;
  686.   state->status = mi_uint4korr(ptr); ptr +=4;
  687.   state->update_count=mi_uint4korr(ptr); ptr +=4;
  688.   for (i=0; i < keys; i++)
  689.   {
  690.     state->key_root[i]= mi_sizekorr(ptr); ptr +=8;
  691.   }
  692.   for (i=0; i < key_blocks; i++)
  693.   {
  694.     state->key_del[i] = mi_sizekorr(ptr); ptr +=8;
  695.   }
  696.   ptr+= state->state_diff_length;
  697.   state->sec_index_changed = mi_uint4korr(ptr); ptr +=4;
  698.   state->sec_index_used =    mi_uint4korr(ptr); ptr +=4;
  699.   state->version     = mi_uint4korr(ptr); ptr +=4;
  700.   state->key_map     = mi_uint8korr(ptr); ptr +=8;
  701.   state->create_time = (time_t) mi_sizekorr(ptr); ptr +=8;
  702.   state->recover_time =(time_t) mi_sizekorr(ptr); ptr +=8;
  703.   state->check_time =  (time_t) mi_sizekorr(ptr); ptr +=8;
  704.   state->rec_per_key_rows=mi_sizekorr(ptr); ptr +=8;
  705.   for (i=0 ; i < key_parts ; i++)
  706.   {
  707.     state->rec_per_key_part[i]= mi_uint4korr(ptr); ptr+=4;
  708.   }
  709.   return ptr;
  710. }
  711. uint mi_state_info_read_dsk(File file, MI_STATE_INFO *state, my_bool pRead)
  712. {
  713.   char buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
  714.   if (pRead)
  715.   {
  716.     if (my_pread(file, buff, state->state_length,0L, MYF(MY_NABP)))
  717.       return (MY_FILE_ERROR);
  718.   }
  719.   else if (my_read(file, buff, state->state_length,MYF(MY_NABP)))
  720.     return (MY_FILE_ERROR);
  721.   mi_state_info_read(buff, state);
  722.   return 0;
  723. }
  724. /****************************************************************************
  725. **  store and read of MI_BASE_INFO
  726. ****************************************************************************/
  727. uint mi_base_info_write(File file, MI_BASE_INFO *base)
  728. {
  729.   uchar buff[MI_BASE_INFO_SIZE], *ptr=buff;
  730.   mi_sizestore(ptr,base->keystart); ptr +=8;
  731.   mi_sizestore(ptr,base->max_data_file_length); ptr +=8;
  732.   mi_sizestore(ptr,base->max_key_file_length); ptr +=8;
  733.   mi_rowstore(ptr,base->records); ptr +=8;
  734.   mi_rowstore(ptr,base->reloc); ptr +=8;
  735.   mi_int4store(ptr,base->mean_row_length); ptr +=4;
  736.   mi_int4store(ptr,base->reclength); ptr +=4;
  737.   mi_int4store(ptr,base->pack_reclength); ptr +=4;
  738.   mi_int4store(ptr,base->min_pack_length); ptr +=4;
  739.   mi_int4store(ptr,base->max_pack_length); ptr +=4;
  740.   mi_int4store(ptr,base->min_block_length); ptr +=4;
  741.   mi_int4store(ptr,base->fields); ptr +=4;
  742.   mi_int4store(ptr,base->pack_fields); ptr +=4;
  743.   *ptr++=base->rec_reflength;
  744.   *ptr++=base->key_reflength;
  745.   *ptr++=base->keys;
  746.   *ptr++=base->auto_key;
  747.   mi_int2store(ptr,base->pack_bits); ptr +=2;
  748.   mi_int2store(ptr,base->blobs); ptr +=2;
  749.   mi_int2store(ptr,base->max_key_block_length); ptr +=2;
  750.   mi_int2store(ptr,base->max_key_length); ptr +=2;
  751.   mi_int2store(ptr,base->extra_alloc_bytes); ptr +=2;
  752.   *ptr++= base->extra_alloc_procent;
  753.   *ptr++= base->raid_type;
  754.   mi_int2store(ptr,base->raid_chunks); ptr +=2;
  755.   mi_int4store(ptr,base->raid_chunksize); ptr +=4;
  756.   bzero(ptr,6); ptr +=6; /* extra */
  757.   return my_write(file,(char*) buff, (uint) (ptr-buff), MYF(MY_NABP));
  758. }
  759. char *my_n_base_info_read(char *ptr, MI_BASE_INFO *base)
  760. {
  761.   base->keystart = mi_sizekorr(ptr); ptr +=8;
  762.   base->max_data_file_length = mi_sizekorr(ptr); ptr +=8;
  763.   base->max_key_file_length = mi_sizekorr(ptr); ptr +=8;
  764.   base->records =  (ha_rows) mi_sizekorr(ptr); ptr +=8;
  765.   base->reloc = (ha_rows) mi_sizekorr(ptr); ptr +=8;
  766.   base->mean_row_length = mi_uint4korr(ptr); ptr +=4;
  767.   base->reclength = mi_uint4korr(ptr); ptr +=4;
  768.   base->pack_reclength = mi_uint4korr(ptr); ptr +=4;
  769.   base->min_pack_length = mi_uint4korr(ptr); ptr +=4;
  770.   base->max_pack_length = mi_uint4korr(ptr); ptr +=4;
  771.   base->min_block_length = mi_uint4korr(ptr); ptr +=4;
  772.   base->fields = mi_uint4korr(ptr); ptr +=4;
  773.   base->pack_fields = mi_uint4korr(ptr); ptr +=4;
  774.   base->rec_reflength = *ptr++;
  775.   base->key_reflength = *ptr++;
  776.   base->keys= *ptr++;
  777.   base->auto_key= *ptr++;
  778.   base->pack_bits = mi_uint2korr(ptr); ptr +=2;
  779.   base->blobs = mi_uint2korr(ptr); ptr +=2;
  780.   base->max_key_block_length= mi_uint2korr(ptr); ptr +=2;
  781.   base->max_key_length = mi_uint2korr(ptr); ptr +=2;
  782.   base->extra_alloc_bytes = mi_uint2korr(ptr); ptr +=2;
  783.   base->extra_alloc_procent = *ptr++;
  784.   base->raid_type= *ptr++;
  785.   base->raid_chunks= mi_uint2korr(ptr); ptr +=2;
  786.   base->raid_chunksize= mi_uint4korr(ptr); ptr +=4;
  787.   /* TO BE REMOVED: Fix for old RAID files */
  788.   if (base->raid_type == 0)
  789.   {
  790.     base->raid_chunks=0;
  791.     base->raid_chunksize=0;
  792.   }
  793.   ptr+=6;
  794.   return ptr;
  795. }
  796. /*--------------------------------------------------------------------------
  797.   mi_keydef
  798. ---------------------------------------------------------------------------*/
  799. uint mi_keydef_write(File file, MI_KEYDEF *keydef)
  800. {
  801.   uchar buff[MI_KEYDEF_SIZE];
  802.   uchar *ptr=buff;
  803.   *ptr++ = (uchar) keydef->keysegs;
  804.   *ptr++ = 0; /* not used */
  805.   mi_int2store(ptr,keydef->flag); ptr +=2;
  806.   mi_int2store(ptr,keydef->block_length); ptr +=2;
  807.   mi_int2store(ptr,keydef->keylength); ptr +=2;
  808.   mi_int2store(ptr,keydef->minlength); ptr +=2;
  809.   mi_int2store(ptr,keydef->maxlength); ptr +=2;
  810.   return my_write(file,(char*) buff, (uint) (ptr-buff), MYF(MY_NABP));
  811. }
  812. char *mi_keydef_read(char *ptr, MI_KEYDEF *keydef)
  813. {
  814.    keydef->keysegs = (uint) *ptr++;
  815.    ptr++;
  816.    keydef->flag = mi_uint2korr(ptr); ptr +=2;
  817.    keydef->block_length = mi_uint2korr(ptr); ptr +=2;
  818.    keydef->keylength = mi_uint2korr(ptr); ptr +=2;
  819.    keydef->minlength = mi_uint2korr(ptr); ptr +=2;
  820.    keydef->maxlength = mi_uint2korr(ptr); ptr +=2;
  821.    keydef->block_size = keydef->block_length/MI_KEY_BLOCK_LENGTH-1;
  822.    keydef->underflow_block_length=keydef->block_length/3;
  823.    keydef->version = 0; /* Not saved */
  824.    return ptr;
  825. }
  826. /***************************************************************************
  827. **  mi_keyseg
  828. ***************************************************************************/
  829. int mi_keyseg_write(File file, const MI_KEYSEG *keyseg)
  830. {
  831.   uchar buff[MI_KEYSEG_SIZE];
  832.   uchar *ptr=buff;
  833.   *ptr++ =keyseg->type;
  834.   *ptr++ =keyseg->language;
  835.   *ptr++ =keyseg->null_bit;
  836.   *ptr++ =keyseg->bit_start;
  837.   *ptr++ =keyseg->bit_end;
  838.   *ptr++ =0; /* Not used */
  839.   mi_int2store(ptr,keyseg->flag); ptr+=2;
  840.   mi_int2store(ptr,keyseg->length); ptr+=2;
  841.   mi_int4store(ptr,keyseg->start); ptr+=4;
  842.   mi_int4store(ptr,keyseg->null_pos); ptr+=4;
  843.   return my_write(file,(char*) buff, (uint) (ptr-buff), MYF(MY_NABP));
  844. }
  845. char *mi_keyseg_read(char *ptr, MI_KEYSEG *keyseg)
  846. {
  847.    keyseg->type = *ptr++;
  848.    keyseg->language = *ptr++;
  849.    keyseg->null_bit = *ptr++;
  850.    keyseg->bit_start = *ptr++;
  851.    keyseg->bit_end = *ptr++;
  852.    ptr++;
  853.    keyseg->flag = mi_uint2korr(ptr);  ptr +=2;
  854.    keyseg->length = mi_uint2korr(ptr);  ptr +=2;
  855.    keyseg->start = mi_uint4korr(ptr);  ptr +=4;
  856.    keyseg->null_pos = mi_uint4korr(ptr);  ptr +=4;
  857.    keyseg->charset=0; /* Will be filled in later */
  858.    return ptr;
  859. }
  860. /*--------------------------------------------------------------------------
  861.   mi_uniquedef
  862. ---------------------------------------------------------------------------*/
  863. uint mi_uniquedef_write(File file, MI_UNIQUEDEF *def)
  864. {
  865.   uchar buff[MI_UNIQUEDEF_SIZE];
  866.   uchar *ptr=buff;
  867.   mi_int2store(ptr,def->keysegs); ptr+=2;
  868.   *ptr++=  (uchar) def->key;
  869.   *ptr++ = (uchar) def->null_are_equal;
  870.   return my_write(file,(char*) buff, (uint) (ptr-buff), MYF(MY_NABP));
  871. }
  872. char *mi_uniquedef_read(char *ptr, MI_UNIQUEDEF *def)
  873. {
  874.    def->keysegs = mi_uint2korr(ptr);
  875.    def->key = ptr[2];
  876.    def->null_are_equal=ptr[3];
  877.    return ptr+4; /* 1 extra byte */
  878. }
  879. /***************************************************************************
  880. **  MI_COLUMNDEF
  881. ***************************************************************************/
  882. uint mi_recinfo_write(File file, MI_COLUMNDEF *recinfo)
  883. {
  884.   uchar buff[MI_COLUMNDEF_SIZE];
  885.   uchar *ptr=buff;
  886.   mi_int2store(ptr,recinfo->type); ptr +=2;
  887.   mi_int2store(ptr,recinfo->length); ptr +=2;
  888.   *ptr++ = recinfo->null_bit;
  889.   mi_int2store(ptr,recinfo->null_pos); ptr+= 2;
  890.   return my_write(file,(char*) buff, (uint) (ptr-buff), MYF(MY_NABP));
  891. }
  892. char *mi_recinfo_read(char *ptr, MI_COLUMNDEF *recinfo)
  893. {
  894.    recinfo->type=  mi_sint2korr(ptr); ptr +=2;
  895.    recinfo->length=mi_uint2korr(ptr); ptr +=2;
  896.    recinfo->null_bit= (uint8) *ptr++;
  897.    recinfo->null_pos=mi_uint2korr(ptr); ptr +=2;
  898.    return ptr;
  899. }
  900. /**************************************************************************
  901.  ** Help functions for recover
  902.  *************************************************************************/
  903. int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share)
  904. {
  905.   char name_buff[FN_REFLEN];
  906.   (void) fn_format(name_buff, share->filename,"",MI_NAME_DEXT, 2+4);
  907. #ifdef USE_RAID
  908.   if (share->base.raid_type)
  909.   {
  910.     if ((info->dfile=my_raid_open(name_buff,
  911.   share->mode | O_SHARE,
  912.   share->base.raid_type,
  913.   share->base.raid_chunks,
  914.   share->base.raid_chunksize,
  915.   MYF(MY_WME | MY_RAID))) < 0)
  916.       return 1;
  917.   }
  918.   else
  919. #endif
  920.     if ((info->dfile=my_open(name_buff, share->mode | O_SHARE,
  921.      MYF(MY_WME))) < 0)
  922.       return 1;
  923.   return 0;
  924. }
  925. int mi_open_keyfile(MYISAM_SHARE *share)
  926. {
  927.   if ((share->kfile=my_open(share->filename, share->mode | O_SHARE,
  928.     MYF(MY_WME))) < 0)
  929.     return 1;
  930.   return 0;
  931. }