open.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:14k
源码类别:

MySQL数据库

开发平台:

Visual C++

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