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

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 "isamdef.h"
  18. #if defined(MSDOS) || defined(__WIN__)
  19. #ifdef __WIN__
  20. #include <fcntl.h>
  21. #else
  22. #include <process.h> /* Prototype for getpid */
  23. #endif
  24. #endif
  25. #ifdef VMS
  26. #include "static.c"
  27. #endif
  28. static void setup_functions(ISAM_SHARE *info);
  29. static void setup_key_functions(N_KEYDEF *keyinfo);
  30. #define get_next_element(to,pos,size) { memcpy((char*) to,pos,(size_t) size); 
  31. pos+=size;}
  32. /******************************************************************************
  33. ** Return the shared struct if the table is already open.
  34. ** In MySQL the server will handle version issues.
  35. ******************************************************************************/
  36. static N_INFO *test_if_reopen(char *filename)
  37. {
  38.   LIST *pos;
  39.   for (pos=nisam_open_list ; pos ; pos=pos->next)
  40.   {
  41.     N_INFO *info=(N_INFO*) pos->data;
  42.     ISAM_SHARE *share=info->s;
  43.     if (!strcmp(share->filename,filename) && share->last_version)
  44.       return info;
  45.   }
  46.   return 0;
  47. }
  48. /******************************************************************************
  49.   open a isam database.
  50.   By default exit with error if database is locked
  51.   if handle_locking & HA_OPEN_WAIT_IF_LOCKED then wait if database is locked
  52.   if handle_locking & HA_OPEN_IGNORE_IF_LOCKED then continue, but count-vars
  53.     in st_i_info may be wrong. count-vars are automaticly fixed after next
  54.     isam request.
  55. ******************************************************************************/
  56. N_INFO *nisam_open(const char *name, int mode, uint handle_locking)
  57. {
  58.   int lock_error,kfile,open_mode,save_errno;
  59.   uint i,j,len,errpos,head_length,base_pos,offset,info_length,extra;
  60.   char name_buff[FN_REFLEN],*disk_cache,*disk_pos;
  61.   N_INFO info,*m_info,*old_info;
  62.   ISAM_SHARE share_buff,*share;
  63.   DBUG_ENTER("nisam_open");
  64.   LINT_INIT(m_info);
  65.   kfile= -1;
  66.   lock_error=1;
  67.   errpos=0;
  68.   head_length=sizeof(share_buff.state.header);
  69.   bzero((byte*) &info,sizeof(info));
  70.   VOID(fn_format(name_buff,name,"",N_NAME_IEXT,4+16+32));
  71.   pthread_mutex_lock(&THR_LOCK_isam);
  72.   if (!(old_info=test_if_reopen(name_buff)))
  73.   {
  74.     share= &share_buff;
  75.     bzero((gptr) &share_buff,sizeof(share_buff));
  76.     if ((kfile=my_open(name_buff,(open_mode=O_RDWR) | O_SHARE,MYF(0))) < 0)
  77.     {
  78.       if ((errno != EROFS && errno != EACCES) ||
  79.   mode != O_RDONLY ||
  80.   (kfile=my_open(name_buff,(open_mode=O_RDONLY) | O_SHARE,MYF(0))) < 0)
  81. goto err;
  82.     }
  83.     errpos=1;
  84.     if (my_read(kfile,(char*) share->state.header.file_version,head_length,
  85. MYF(MY_NABP)))
  86.       goto err;
  87.     if (memcmp((byte*) share->state.header.file_version,
  88.        (byte*) nisam_file_magic, 3) ||
  89. share->state.header.file_version[3] == 0 ||
  90. (uchar) share->state.header.file_version[3] > 3)
  91.     {
  92.       DBUG_PRINT("error",("Wrong header in %s",name_buff));
  93.       DBUG_DUMP("error_dump",(char*) share->state.header.file_version,
  94. head_length);
  95.       my_errno=HA_ERR_CRASHED;
  96.       goto err;
  97.     }
  98.     if (uint2korr(share->state.header.options) &
  99. ~(HA_OPTION_PACK_RECORD | HA_OPTION_PACK_KEYS |
  100.   HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA |
  101.   HA_OPTION_TEMP_COMPRESS_RECORD))
  102.     {
  103.       DBUG_PRINT("error",("wrong options: 0x%lx",
  104.   uint2korr(share->state.header.options)));
  105.       my_errno=HA_ERR_OLD_FILE;
  106.       goto err;
  107.     }
  108.     info_length=uint2korr(share->state.header.header_length);
  109.     base_pos=uint2korr(share->state.header.base_pos);
  110.     if (!(disk_cache=(char*) my_alloca(info_length)))
  111.     {
  112.       my_errno=ENOMEM;
  113.       goto err;
  114.     }
  115.     errpos=2;
  116.     VOID(my_seek(kfile,0L,MY_SEEK_SET,MYF(0)));
  117. #ifndef NO_LOCKING
  118.     if (!(handle_locking & HA_OPEN_TMP_TABLE))
  119.     {
  120.       if ((lock_error=my_lock(kfile,F_RDLCK,0L,F_TO_EOF,
  121.       MYF(handle_locking & HA_OPEN_WAIT_IF_LOCKED ?
  122.   0 : MY_DONT_WAIT))) &&
  123.   !(handle_locking & HA_OPEN_IGNORE_IF_LOCKED))
  124. goto err;
  125.     }
  126. #endif
  127.     errpos=3;
  128.     if (my_read(kfile,disk_cache,info_length,MYF(MY_NABP)))
  129.       goto err;
  130.     len=uint2korr(share->state.header.state_info_length);
  131.     if (len != sizeof(N_STATE_INFO))
  132.     {
  133.       DBUG_PRINT("warning",
  134.  ("saved_state_info_length: %d  base_info_length: %d",
  135.   len,sizeof(N_STATE_INFO)));
  136.     }
  137.     if (len > sizeof(N_STATE_INFO))
  138.       len=sizeof(N_STATE_INFO);
  139.     share->state_length=len;
  140.     memcpy(&share->state.header.file_version[0],disk_cache,(size_t) len);
  141.     len=uint2korr(share->state.header.base_info_length);
  142.     if (len != sizeof(N_BASE_INFO))
  143.     {
  144.       DBUG_PRINT("warning",("saved_base_info_length: %d  base_info_length: %d",
  145.     len,sizeof(N_BASE_INFO)));
  146.       if (len <= offsetof(N_BASE_INFO,sortkey))
  147. share->base.sortkey=(ushort) ~0;
  148.     }
  149.     memcpy((char*) (byte*) &share->base,disk_cache+base_pos,
  150.    (size_t) min(len,sizeof(N_BASE_INFO)));
  151.     disk_pos=disk_cache+base_pos+len;
  152.     share->base.options=uint2korr(share->state.header.options);
  153.     if (share->base.max_key_length > N_MAX_KEY_BUFF)
  154.     {
  155.       my_errno=HA_ERR_UNSUPPORTED;
  156.       goto err;
  157.     }
  158.     if (share->base.options & HA_OPTION_COMPRESS_RECORD)
  159.       share->base.max_key_length+=2; /* For safety */
  160.     if (!my_multi_malloc(MY_WME,
  161.  &share,sizeof(*share),
  162.  &share->keyinfo,share->base.keys*sizeof(N_KEYDEF),
  163.  &share->rec,(share->base.fields+1)*sizeof(N_RECINFO),
  164.  &share->blobs,sizeof(N_BLOB)*share->base.blobs,
  165.  &share->filename,strlen(name_buff)+1,
  166.  NullS))
  167.       goto err;
  168.     errpos=4;
  169.     *share=share_buff;
  170.     strmov(share->filename,name_buff);
  171.     /* Fix key in used if old nisam-database */
  172.     if (share->state_length <= offsetof(N_STATE_INFO,keys))
  173.       share->state.keys=share->base.keys;
  174.     share->blocksize=min(IO_SIZE,nisam_block_size);
  175.     for (i=0 ; i < share->base.keys ; i++)
  176.     {
  177.       get_next_element(&share->keyinfo[i].base,disk_pos,sizeof(N_SAVE_KEYDEF));
  178.       setup_key_functions(share->keyinfo+i);
  179.       set_if_smaller(share->blocksize,share->keyinfo[i].base.block_length);
  180.       for (j=0 ; j <= share->keyinfo[i].base.keysegs ; j++)
  181.       {
  182. get_next_element(&share->keyinfo[i].seg[j],disk_pos,
  183.  sizeof(N_SAVE_KEYSEG));
  184.       }
  185.     }
  186.     if (!share->blocksize)
  187.     {
  188.       my_errno=HA_ERR_CRASHED;
  189.       goto err;
  190.     }
  191.     for (i=j=offset=0 ; i < share->base.fields ; i++)
  192.     {
  193.       get_next_element(&share->rec[i].base,disk_pos,sizeof(N_SAVE_RECINFO));
  194. #ifndef NOT_PACKED_DATABASES
  195.       share->rec[i].pack_type=0;
  196.       share->rec[i].huff_tree=0;
  197. #endif
  198.       if (share->rec[i].base.type == (int) FIELD_BLOB)
  199.       {
  200. share->blobs[j].pack_length=share->rec[i].base.length;
  201. share->blobs[j].offset=offset;
  202. j++;
  203. offset+=sizeof(char*);
  204.       }
  205.       offset+=share->rec[i].base.length;
  206.     }
  207.     share->rec[i].base.type=(int) FIELD_LAST;
  208. #ifndef NO_LOCKING
  209.     if (! lock_error)
  210.     {
  211.       VOID(my_lock(kfile,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE)));
  212.       lock_error=1; /* Database unlocked */
  213.     }
  214. #endif
  215.     if ((info.dfile=my_open(fn_format(name_buff,name,"",N_NAME_DEXT,2+4),
  216.     mode | O_SHARE,
  217.     MYF(MY_WME))) < 0)
  218.       goto err;
  219.     errpos=5;
  220.     share->kfile=kfile;
  221.     share->mode=open_mode;
  222.     share->this_process=(ulong) getpid();
  223.     share->rnd= (int)  share->this_process; /* rnd-counter for splitts */
  224. #ifndef DBUG_OFF
  225.     share->rnd=0; /* To make things repeatable */
  226. #endif
  227.     share->last_process= share->state.process;
  228.     if (!(share->last_version=share->state.version))
  229.       share->last_version=1; /* Safety */
  230.     share->rec_reflength=share->base.rec_reflength; /* May be changed */
  231.     share->data_file_type=STATIC_RECORD;
  232.     if (share->base.options & HA_OPTION_COMPRESS_RECORD)
  233.     {
  234.       share->data_file_type = COMPRESSED_RECORD;
  235.       share->base.options|= HA_OPTION_READ_ONLY_DATA;
  236.       info.s=share;
  237.       if (_nisam_read_pack_info(&info,
  238. (pbool) test(!(share->base.options &
  239.        (HA_OPTION_PACK_RECORD |
  240. HA_OPTION_TEMP_COMPRESS_RECORD)))))
  241. goto err;
  242.     }
  243.     else if (share->base.options & HA_OPTION_PACK_RECORD)
  244.       share->data_file_type = DYNAMIC_RECORD;
  245.     my_afree((gptr) disk_cache);
  246.     setup_functions(share);
  247. #ifdef THREAD
  248.     thr_lock_init(&share->lock);
  249.     VOID(pthread_mutex_init(&share->intern_lock,NULL));
  250. #endif
  251.   }
  252.   else
  253.   {
  254.     share= old_info->s;
  255.     if (mode == O_RDWR && share->mode == O_RDONLY)
  256.     {
  257.       my_errno=EACCES; /* Can't open in write mode*/
  258.       goto err;
  259.     }
  260.     if ((info.dfile=my_open(fn_format(name_buff,old_info->filename,"",
  261.       N_NAME_DEXT,2+4),
  262.     mode | O_SHARE,MYF(MY_WME))) < 0)
  263.     {
  264.       my_errno=errno;
  265.       goto err;
  266.     }
  267.     errpos=5;
  268.   }
  269.   /* alloc and set up private structure parts */
  270.   if (!my_multi_malloc(MY_WME,
  271.        &m_info,sizeof(N_INFO),
  272.        &info.blobs,sizeof(N_BLOB)*share->base.blobs,
  273.        &info.buff,(share->base.max_block*2+
  274.    share->base.max_key_length),
  275.        &info.lastkey,share->base.max_key_length*3+1,
  276.        &info.filename,strlen(name)+1,
  277.        NullS))
  278.     goto err;
  279.   errpos=6;
  280.   strmov(info.filename,name);
  281.   memcpy(info.blobs,share->blobs,sizeof(N_BLOB)*share->base.blobs);
  282.   info.s=share;
  283.   info.lastpos= NI_POS_ERROR;
  284.   info.update= (short) (HA_STATE_NEXT_FOUND+HA_STATE_PREV_FOUND);
  285.   info.opt_flag=READ_CHECK_USED;
  286.   info.alloced_rec_buff_length=share->base.pack_reclength;
  287.   info.this_uniq= (ulong) info.dfile; /* Uniq number in process */
  288.   info.this_loop=0; /* Update counter */
  289.   info.last_uniq= share->state.uniq;
  290.   info.last_loop= share->state.loop;
  291.   info.options=share->base.options |
  292.     (mode == O_RDONLY ? HA_OPTION_READ_ONLY_DATA : 0);
  293.   info.lock_type=F_UNLCK;
  294.   info.errkey= -1;
  295.   pthread_mutex_lock(&share->intern_lock);
  296.   info.read_record=share->read_record;
  297.   share->reopen++;
  298.   if (share->base.options & HA_OPTION_READ_ONLY_DATA)
  299.   {
  300.     info.lock_type=F_RDLCK;
  301.     share->r_locks++;
  302.     info.this_uniq=share->state.uniq; /* Row checksum */
  303.   }
  304. #ifndef NO_LOCKING
  305.   if (handle_locking & HA_OPEN_TMP_TABLE)
  306. #endif
  307.   {
  308.     share->w_locks++; /* We don't have to update status */
  309.     info.lock_type=F_WRLCK;
  310.   }
  311.   pthread_mutex_unlock(&share->intern_lock);
  312.   /* Allocate buffer for one record */
  313.   extra=0;
  314.   if (share->base.options & HA_OPTION_PACK_RECORD)
  315.     extra=ALIGN_SIZE(MAX_DYN_BLOCK_HEADER)+N_SPLITT_LENGTH+
  316.       DYN_DELETE_BLOCK_HEADER;
  317.   if (!(info.rec_alloc=(byte*) my_malloc(share->base.pack_reclength+extra+
  318.  6,
  319.  MYF(MY_WME | MY_ZEROFILL))))
  320.     goto err;
  321.   if (extra)
  322.     info.rec_buff=info.rec_alloc+ALIGN_SIZE(MAX_DYN_BLOCK_HEADER);
  323.   else
  324.     info.rec_buff=info.rec_alloc;
  325.   *m_info=info;
  326. #ifdef THREAD
  327.   thr_lock_data_init(&share->lock,&m_info->lock,NULL);
  328. #endif
  329.   m_info->open_list.data=(void*) m_info;
  330.   nisam_open_list=list_add(nisam_open_list,&m_info->open_list);
  331.   pthread_mutex_unlock(&THR_LOCK_isam);
  332.   nisam_log_simple(LOG_OPEN,m_info,share->filename,
  333.    (uint) strlen(share->filename));
  334.   DBUG_RETURN(m_info);
  335. err:
  336.   save_errno=my_errno ? my_errno : HA_ERR_END_OF_FILE;
  337.   switch (errpos) {
  338.   case 6:
  339.     my_free((gptr) m_info,MYF(0));
  340.     /* fall through */
  341.   case 5:
  342.     VOID(my_close(info.dfile,MYF(0)));
  343.     if (old_info)
  344.       break; /* Don't remove open table */
  345.     /* fall through */
  346.   case 4:
  347.     my_free((gptr) share,MYF(0));
  348.     /* fall through */
  349.   case 3:
  350. #ifndef NO_LOCKING
  351.     if (! lock_error)
  352.       VOID(my_lock(kfile, F_UNLCK, 0L, F_TO_EOF, MYF(MY_SEEK_NOT_DONE)));
  353. #endif
  354.     /* fall through */
  355.   case 2:
  356.     my_afree((gptr) disk_cache);
  357.     /* fall through */
  358.   case 1:
  359.     VOID(my_close(kfile,MYF(0)));
  360.     /* fall through */
  361.   case 0:
  362.   default:
  363.     break;
  364.   }
  365.   pthread_mutex_unlock(&THR_LOCK_isam);
  366.   my_errno=save_errno;
  367.   DBUG_RETURN (NULL);
  368. } /* nisam_open */
  369. /* Set up functions in structs */
  370. static void setup_functions(register ISAM_SHARE *share)
  371. {
  372.   if (share->base.options & HA_OPTION_COMPRESS_RECORD)
  373.   {
  374.     share->read_record=_nisam_read_pack_record;
  375.     share->read_rnd=_nisam_read_rnd_pack_record;
  376.   }
  377.   else if (share->base.options & HA_OPTION_PACK_RECORD)
  378.   {
  379.     share->read_record=_nisam_read_dynamic_record;
  380.     share->read_rnd=_nisam_read_rnd_dynamic_record;
  381.     share->delete_record=_nisam_delete_dynamic_record;
  382.     share->compare_record=_nisam_cmp_dynamic_record;
  383.     if (share->base.blobs)
  384.     {
  385.       share->update_record=_nisam_update_blob_record;
  386.       share->write_record=_nisam_write_blob_record;
  387.     }
  388.     else
  389.     {
  390.       share->write_record=_nisam_write_dynamic_record;
  391.       share->update_record=_nisam_update_dynamic_record;
  392.     }
  393.   }
  394.   else
  395.   {
  396.     share->read_record=_nisam_read_static_record;
  397.     share->read_rnd=_nisam_read_rnd_static_record;
  398.     share->delete_record=_nisam_delete_static_record;
  399.     share->compare_record=_nisam_cmp_static_record;
  400.     share->update_record=_nisam_update_static_record;
  401.     share->write_record=_nisam_write_static_record;
  402.   }
  403.   return;
  404. }
  405. static void setup_key_functions(register N_KEYDEF *keyinfo)
  406. {
  407.   if (keyinfo->base.flag & (HA_PACK_KEY | HA_SPACE_PACK_USED))
  408.   {
  409.     keyinfo->bin_search=_nisam_seq_search;
  410.     keyinfo->get_key=_nisam_get_key;
  411.   }
  412.   else
  413.   {
  414.     keyinfo->bin_search=_nisam_bin_search;
  415.     keyinfo->get_key=_nisam_get_static_key;
  416.   }
  417.   return;
  418. }