home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / isam / create.c < prev    next >
C/C++ Source or Header  |  2000-08-31  |  11KB  |  328 lines

  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.  
  17. /* Skapar en isam-databas */
  18.  
  19. #include "isamdef.h"
  20. #if defined(MSDOS) || defined(__WIN__)
  21. #ifdef __WIN__
  22. #include <fcntl.h>
  23. #else
  24. #include <process.h>            /* Prototype for getpid */
  25. #endif
  26. #endif
  27.  
  28.     /*
  29.     ** Old options is used when recreating database, from isamchk
  30.     ** Note that the minimun reclength that MySQL allows for static rows
  31.     ** are 5.  (Will be fixed in the next generation)
  32.     */
  33.  
  34. int nisam_create(const char *name,uint keys,N_KEYDEF *keyinfo,
  35.          N_RECINFO *recinfo,
  36.          ulong records,ulong reloc, uint flags,uint old_options,
  37.          ulong data_file_length)
  38. {
  39.   register uint i,j;
  40.   File dfile,file;
  41.   int errpos,save_errno;
  42.   uint fields,length,max_key_length,packed,pointer,reclength,min_pack_length,
  43.        key_length,info_length,key_segs,options,min_key_length_skipp,max_block,
  44.        base_pos;
  45.   char buff[max(FN_REFLEN,512)];
  46.   ulong tot_length,pack_reclength;
  47.   enum en_fieldtype type;
  48.   ISAM_SHARE share;
  49.   N_KEYDEF *keydef;
  50.   N_KEYSEG *keyseg;
  51.   N_RECINFO *rec;
  52.   DBUG_ENTER("nisam_create");
  53.  
  54.   LINT_INIT(dfile);
  55.   pthread_mutex_lock(&THR_LOCK_isam);
  56.   errpos=0;
  57.   options=0;
  58.   base_pos=512;                    /* Enough for N_STATE_INFO */
  59.   bzero((byte*) &share,sizeof(share));
  60.   if ((file = my_create(fn_format(buff,name,"",N_NAME_IEXT,4),0,
  61.        O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
  62.     goto err;
  63.   errpos=1;
  64.   VOID(fn_format(buff,name,"",N_NAME_DEXT,2+4));
  65.   if (!(flags & HA_DONT_TOUCH_DATA))
  66.   {
  67.     if ((dfile = my_create(buff,0,O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
  68.       goto err;
  69.     errpos=2;
  70.   }
  71.   else if (!(old_options & HA_OPTION_TEMP_COMPRESS_RECORD))
  72.     options=old_options & (HA_OPTION_COMPRESS_RECORD |
  73.                HA_OPTION_READ_ONLY_DATA | HA_OPTION_PACK_RECORD);
  74.   if (reloc > records)
  75.     reloc=records;                /* Check if wrong parameter */
  76.  
  77.     /* Start by checking fields and field-types used */
  78.   reclength=0;
  79.   for (rec=recinfo, fields=packed=min_pack_length=0, pack_reclength=0L;
  80.        rec->base.type != (int) FIELD_LAST;
  81.        rec++,fields++)
  82.   {
  83.     reclength+=rec->base.length;
  84.     if ((type=(enum en_fieldtype) rec->base.type))
  85.     {
  86.       packed++;
  87.       if (type == FIELD_BLOB)
  88.       {
  89.     share.base.blobs++;
  90.     rec->base.length-= sizeof(char*);    /* Don't calc pointer */
  91.     if (pack_reclength != NI_POS_ERROR)
  92.     {
  93.       if (rec->base.length == 4)
  94.         pack_reclength= (ulong) NI_POS_ERROR;
  95.       else
  96.         pack_reclength+=sizeof(char*)+(1 << (rec->base.length*8));
  97.     }
  98.       }
  99.       else if (type == FIELD_SKIPP_PRESPACE ||
  100.            type == FIELD_SKIPP_ENDSPACE)
  101.       {
  102.     if (pack_reclength != NI_POS_ERROR)
  103.       pack_reclength+= rec->base.length > 255 ? 2 : 1;
  104.     min_pack_length++;
  105.       }
  106.       else if (type == FIELD_ZERO)
  107.     packed--;
  108.       else if (type != FIELD_SKIPP_ZERO)
  109.       {
  110.     min_pack_length+=rec->base.length;
  111.     packed--;                /* Not a pack record type */
  112.       }
  113.     }
  114.     else
  115.       min_pack_length+=rec->base.length;
  116.   }
  117.   if ((packed & 7) == 1)
  118.   {                /* Bad packing, try to remove a zero-field */
  119.     while (rec != recinfo)
  120.     {
  121.       rec--;
  122.       if (rec->base.type == (int) FIELD_SKIPP_ZERO && rec->base.length == 1)
  123.       {
  124.     rec->base.type=(int) FIELD_NORMAL;
  125.     packed--;
  126.     min_pack_length++;
  127.     break;
  128.       }
  129.     }
  130.   }
  131.   if (packed && !(options & HA_OPTION_COMPRESS_RECORD))
  132.     options|=HA_OPTION_PACK_RECORD;    /* Must use packed records */
  133.  
  134.   packed=(packed+7)/8;
  135.   if (pack_reclength != NI_POS_ERROR)
  136.     pack_reclength+= reclength+packed;
  137.   min_pack_length+=packed;
  138.  
  139.   if (options & HA_OPTION_COMPRESS_RECORD)
  140.   {
  141.     if (data_file_length >= (1L << 24))
  142.       pointer=4;
  143.     else if (data_file_length >= (1L << 16))
  144.       pointer=3;
  145.     else
  146.       pointer=2;
  147.   }
  148.   else if (((records == 0L && pack_reclength < 255) ||
  149.         options & HA_OPTION_PACK_RECORD) ||
  150.        records >= (ulong) 16000000L ||
  151.        pack_reclength == (ulong) NI_POS_ERROR ||
  152.        ((options & HA_OPTION_PACK_RECORD) &&
  153.         pack_reclength+4 >= (ulong) 14000000L/records))
  154.     pointer=4;
  155.   else if (records == 0L || records >= (ulong) 65000L ||
  156.        ((options & HA_OPTION_PACK_RECORD) &&
  157.         pack_reclength+4 >= (ulong) 60000L/records))
  158.     pointer=3;
  159.   else
  160.     pointer=2;
  161.  
  162.   max_block=max_key_length=0; tot_length=key_segs=0;
  163.   for (i=0, keydef=keyinfo ; i < keys ; i++ , keydef++)
  164.   {
  165.     share.state.key_root[i]= share.state.key_del[i]= NI_POS_ERROR;
  166.     share.base.rec_per_key[i]= (keydef->base.flag & HA_NOSAME) ? 1L : 0L;
  167.     min_key_length_skipp=length=0;
  168.     key_length=pointer;
  169.  
  170.     if (keydef->base.flag & HA_PACK_KEY &&
  171.     keydef->seg[0].base.length > 127)
  172.       keydef->base.flag&= ~HA_PACK_KEY;        /* Can't pack long keys */
  173.     if (keydef->base.flag & HA_PACK_KEY)
  174.     {
  175.       if ((keydef->seg[0].base.flag & HA_SPACE_PACK) &&
  176.       keydef->seg[0].base.type == (int) HA_KEYTYPE_NUM)
  177.     keydef->seg[0].base.flag&= ~HA_SPACE_PACK;
  178.       if (!(keydef->seg[0].base.flag & HA_SPACE_PACK))
  179.     length++;
  180.       keydef->seg[0].base.flag|=HA_PACK_KEY;    /* for easyer intern test */
  181.       options|=HA_OPTION_PACK_KEYS;        /* Using packed keys */
  182.       if (!(keydef->seg[0].base.flag & HA_SPACE_PACK))
  183.     min_key_length_skipp+=keydef->seg[0].base.length;
  184.     }
  185.     keydef->base.keysegs=0;
  186.     for (keyseg=keydef->seg ; keyseg->base.type ; keyseg++)
  187.     {
  188.       keydef->base.keysegs++;
  189.       if (keyseg->base.length > 127)
  190.     keyseg->base.flag&= ~(HA_SPACE_PACK | HA_PACK_KEY);
  191.       if (keyseg->base.flag & HA_SPACE_PACK)
  192.       {
  193.     keydef->base.flag |= HA_SPACE_PACK_USED;
  194.     options|=HA_OPTION_PACK_KEYS;        /* Using packed keys */
  195.     length++;
  196.     min_key_length_skipp+=keyseg->base.length;
  197.       }
  198.       key_length+= keyseg->base.length;
  199.     }
  200.     bzero((gptr) keyseg,sizeof(keyseg[0]));
  201.     keyseg->base.length=(uint16) pointer;    /* Last key part is pointer */
  202.     key_segs+=keydef->base.keysegs;
  203.     length+=key_length;
  204.     keydef->base.block_length=nisam_block_size;
  205.     keydef->base.keylength= (uint16) key_length;
  206.     keydef->base.minlength= (uint16) (length-min_key_length_skipp);
  207.     keydef->base.maxlength= (uint16) length;
  208.  
  209.     if ((uint) keydef->base.block_length > max_block)
  210.       max_block=(uint) keydef->base.block_length;
  211.     if (length > max_key_length)
  212.       max_key_length= length;
  213.     tot_length+= (records/(ulong) (((uint) keydef->base.block_length-5)/
  214.                    (length*2)))*
  215.       (ulong) keydef->base.block_length;
  216.   }
  217.   info_length=(uint) (base_pos+sizeof(N_BASE_INFO)+keys*sizeof(N_SAVE_KEYDEF)+
  218.               (keys+key_segs)*sizeof(N_SAVE_KEYSEG)+
  219.               fields*sizeof(N_SAVE_RECINFO));
  220.  
  221.   bmove(share.state.header.file_version,(byte*) nisam_file_magic,4);
  222.   old_options=options| (old_options & HA_OPTION_TEMP_COMPRESS_RECORD ?
  223.             HA_OPTION_COMPRESS_RECORD |
  224.             HA_OPTION_TEMP_COMPRESS_RECORD: 0);
  225.   int2store(share.state.header.options,old_options);
  226.   int2store(share.state.header.header_length,info_length);
  227.   int2store(share.state.header.state_info_length,sizeof(N_STATE_INFO));
  228.   int2store(share.state.header.base_info_length,sizeof(N_BASE_INFO));
  229.   int2store(share.state.header.base_pos,base_pos);
  230.  
  231.   share.state.dellink = NI_POS_ERROR;
  232.   share.state.process=    (ulong) getpid();
  233.   share.state.uniq=    (ulong) file;
  234.   share.state.loop=    0;
  235.   share.state.version=    (ulong) time((time_t*) 0);
  236.   share.base.options=options;
  237.   share.base.rec_reflength=pointer;
  238.   share.base.key_reflength=((!tot_length || tot_length > 30000000L) ? 3 :
  239.                tot_length > 120000L ? 2 : 1);
  240.   share.base.keys= share.state.keys = keys;
  241.   share.base.keystart = share.state.key_file_length=MY_ALIGN(info_length,
  242.                               nisam_block_size);
  243.   share.base.max_block=max_block;
  244.   share.base.max_key_length=(uint) ALIGN_SIZE(max_key_length+4);
  245.   share.base.records=records;
  246.   share.base.reloc=reloc;
  247.   share.base.reclength=reclength;
  248.   share.base.pack_reclength=
  249.     (uint) (reclength+packed-share.base.blobs*sizeof(char*));
  250.   share.base.max_pack_length=pack_reclength;
  251.   share.base.min_pack_length=min_pack_length;
  252.   share.base.pack_bits=packed;
  253.   share.base.fields=fields;
  254.   share.base.pack_fields=packed;
  255.   share.base.sortkey= (ushort) ~0;
  256.   share.base.max_data_file_length= (pointer == 4) ? ~0L :
  257.     (options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ?
  258.     (1L << (pointer*8)) :
  259.     (pointer == 3 && reclength >= 256L) ? NI_POS_ERROR :
  260.     ((ulong) reclength * (1L << (pointer*8)));
  261.   share.base.max_key_file_length= (share.base.key_reflength == 3 ?
  262.                   NI_POS_ERROR :
  263.                   (1L << (share.base.key_reflength*8))*512);
  264.   share.base.min_block_length=
  265.     (share.base.pack_reclength+3 < N_EXTEND_BLOCK_LENGTH &&
  266.      ! share.base.blobs) ?
  267.     max(share.base.pack_reclength,N_MIN_BLOCK_LENGTH) :
  268.     N_EXTEND_BLOCK_LENGTH;
  269.   if (! (flags & HA_DONT_TOUCH_DATA))
  270.     share.base.create_time= (long) time((time_t*) 0);
  271.  
  272.   bzero(buff,base_pos);
  273.   if (my_write(file,(char*) &share.state,sizeof(N_STATE_INFO),MYF(MY_NABP)) ||
  274.       my_write(file,buff,base_pos-sizeof(N_STATE_INFO),MYF(MY_NABP)) ||
  275.       my_write(file,(char*) &share.base,sizeof(N_BASE_INFO),MYF(MY_NABP)))
  276.     goto err;
  277.  
  278.   for (i=0 ; i < share.base.keys ; i++)
  279.   {
  280.     if (my_write(file,(char*) &keyinfo[i].base,sizeof(N_SAVE_KEYDEF),
  281.          MYF(MY_NABP)))
  282.       goto err;
  283.     for (j=0 ; j <= keyinfo[i].base.keysegs ; j++)
  284.     {
  285.       if (my_write(file,(char*) &keyinfo[i].seg[j].base,sizeof(N_SAVE_KEYSEG),
  286.            MYF(MY_NABP)))
  287.     goto err;
  288.     }
  289.   }
  290.   for (i=0 ; i < share.base.fields ; i++)
  291.     if (my_write(file,(char*) &recinfo[i].base, (uint) sizeof(N_SAVE_RECINFO),
  292.          MYF(MY_NABP)))
  293.       goto err;
  294.  
  295.     /* Enlarge files */
  296.   if (my_chsize(file,(ulong) share.base.keystart,MYF(0)))
  297.     goto err;
  298.  
  299.   if (! (flags & HA_DONT_TOUCH_DATA))
  300.   {
  301. #ifdef USE_RELOC
  302.     if (my_chsize(dfile,share.base.min_pack_length*reloc,MYF(0)))
  303.       goto err;
  304. #endif
  305.     errpos=1;
  306.     if (my_close(dfile,MYF(0)))
  307.       goto err;
  308.   }
  309.   errpos=0;
  310.   pthread_mutex_unlock(&THR_LOCK_isam);
  311.   if (my_close(file,MYF(0)))
  312.     goto err;
  313.   DBUG_RETURN(0);
  314.  
  315. err:
  316.   pthread_mutex_unlock(&THR_LOCK_isam);
  317.   save_errno=my_errno;
  318.   switch (errpos) {
  319.   case 2:
  320.     VOID(my_close(dfile,MYF(0)));
  321.     /* fall through */
  322.   case 1:
  323.     VOID(my_close(file,MYF(0)));
  324.   }
  325.   my_errno=save_errno;                /* R{tt felkod tillbaka */
  326.   DBUG_RETURN(-1);
  327. } /* nisam_create */
  328.