~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/mi_open.c

  • Committer: Monty Taylor
  • Date: 2008-08-16 21:06:22 UTC
  • Revision ID: monty@inaugust.com-20080816210622-zpnn13unyinqzn72
Updated po files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 
18
18
#include "myisamdef.h"
19
19
#include <mystrings/m_ctype.h>
20
 
#include <mystrings/m_string.h>
21
 
#include <drizzled/util/test.h>
22
 
 
23
 
#include <string.h>
24
20
 
25
21
static void setup_key_functions(MI_KEYDEF *keyinfo);
 
22
#define get_next_element(to,pos,size) \
 
23
  do {                                \
 
24
    memcpy(to, pos, size);            \
 
25
    pos+=size;                        \
 
26
  } while (0)
 
27
 
26
28
 
27
29
#define disk_pos_assert(pos, end_pos) \
28
30
if (pos > end_pos)             \
60
62
  have an open count of 0.
61
63
******************************************************************************/
62
64
 
63
 
MI_INFO *mi_open(const char *name, int mode, uint32_t open_flags)
 
65
MI_INFO *mi_open(const char *name, int mode, uint open_flags)
64
66
{
65
67
  int lock_error,kfile,open_mode,save_errno,have_rtree=0;
66
 
  uint32_t i,j,len,errpos,head_length,base_pos,offset,info_length,keys,
 
68
  uint i,j,len,errpos,head_length,base_pos,offset,info_length,keys,
67
69
    key_parts,unique_key_parts,fulltext_keys,uniques;
68
70
  char name_buff[FN_REFLEN], org_name[FN_REFLEN], index_name[FN_REFLEN],
69
71
       data_name[FN_REFLEN];
70
 
  unsigned char *disk_cache= NULL;
71
 
  unsigned char *disk_pos, *end_pos;
 
72
  uchar *disk_cache, *disk_pos, *end_pos;
72
73
  MI_INFO info,*m_info,*old_info;
73
74
  MYISAM_SHARE share_buff,*share;
74
75
  ulong rec_per_key_part[HA_MAX_POSSIBLE_KEY*MI_MAX_KEY_SEG];
91
92
    share_buff.state.rec_per_key_part=rec_per_key_part;
92
93
    share_buff.state.key_root=key_root;
93
94
    share_buff.state.key_del=key_del;
94
 
    share_buff.key_cache= multi_key_cache_search((unsigned char*) name_buff,
 
95
    share_buff.key_cache= multi_key_cache_search((uchar*) name_buff,
95
96
                                                 strlen(name_buff));
96
97
 
97
 
    if ((kfile=my_open(name_buff,(open_mode=O_RDWR),MYF(0))) < 0)
 
98
    if ((kfile=my_open(name_buff,(open_mode=O_RDWR) | O_SHARE,MYF(0))) < 0)
98
99
    {
99
100
      if ((errno != EROFS && errno != EACCES) ||
100
101
          mode != O_RDONLY ||
101
 
          (kfile=my_open(name_buff,(open_mode=O_RDONLY),MYF(0))) < 0)
 
102
          (kfile=my_open(name_buff,(open_mode=O_RDONLY) | O_SHARE,MYF(0))) < 0)
102
103
        goto err;
103
104
    }
104
105
    share->mode=open_mode;
134
135
    /* Don't call realpath() if the name can't be a link */
135
136
    if (!strcmp(name_buff, org_name) ||
136
137
        my_readlink(index_name, org_name, MYF(0)) == -1)
137
 
      (void) strcpy(index_name, org_name);
 
138
      (void) stpcpy(index_name, org_name);
138
139
    *strrchr(org_name, '.')= '\0';
139
140
    (void) fn_format(data_name,org_name,"",MI_NAME_DEXT,
140
141
                     MY_APPEND_EXT|MY_UNPACK_FILENAME|MY_RESOLVE_SYMLINKS);
141
142
 
142
143
    info_length=mi_uint2korr(share->state.header.header_length);
143
144
    base_pos=mi_uint2korr(share->state.header.base_pos);
144
 
    if (!(disk_cache= (unsigned char*) malloc(info_length+128)))
 
145
    if (!(disk_cache= (uchar*) my_alloca(info_length+128)))
145
146
    {
146
147
      my_errno=ENOMEM;
147
148
      goto err;
149
150
    end_pos=disk_cache+info_length;
150
151
    errpos=2;
151
152
 
152
 
    lseek(kfile,0,SEEK_SET);
 
153
    VOID(my_seek(kfile,0L,MY_SEEK_SET,MYF(0)));
153
154
    errpos=3;
154
155
    if (my_read(kfile,disk_cache,info_length,MYF(MY_NABP)))
155
156
    {
203
204
      mi_safe_mul(MI_MIN_KEY_BLOCK_LENGTH,
204
205
                  ((uint64_t) 1 << (share->base.key_reflength*8))-1);
205
206
#if SIZEOF_OFF_T == 4
206
 
    set_if_smaller(max_data_file_length, INT32_MAX);
207
 
    set_if_smaller(max_key_file_length, INT32_MAX);
 
207
    set_if_smaller(max_data_file_length, INT_MAX32);
 
208
    set_if_smaller(max_key_file_length, INT_MAX32);
208
209
#endif
209
210
    if (share->base.raid_type)
210
211
    {
237
238
                         &share->state.key_root,keys*sizeof(my_off_t),
238
239
                         &share->state.key_del,
239
240
                         (share->state.header.max_block_size_index*sizeof(my_off_t)),
240
 
                         &share->key_root_lock,sizeof(pthread_rwlock_t)*keys,
241
 
                         &share->mmap_lock,sizeof(pthread_rwlock_t),
242
 
                         NULL))
 
241
                         &share->key_root_lock,sizeof(rw_lock_t)*keys,
 
242
                         &share->mmap_lock,sizeof(rw_lock_t),
 
243
                         NullS))
243
244
      goto err;
244
245
    errpos=4;
245
246
    *share=share_buff;
249
250
           sizeof(my_off_t)*keys);
250
251
    memcpy(share->state.key_del, key_del,
251
252
           sizeof(my_off_t) * share->state.header.max_block_size_index);
252
 
    strcpy(share->unique_file_name, name_buff);
 
253
    stpcpy(share->unique_file_name, name_buff);
253
254
    share->unique_name_length= strlen(name_buff);
254
 
    strcpy(share->index_file_name,  index_name);
255
 
    strcpy(share->data_file_name,   data_name);
 
255
    stpcpy(share->index_file_name,  index_name);
 
256
    stpcpy(share->data_file_name,   data_name);
256
257
 
257
 
    share->blocksize=cmin(IO_SIZE,myisam_block_size);
 
258
    share->blocksize=min(IO_SIZE,myisam_block_size);
258
259
    {
259
260
      HA_KEYSEG *pos=share->keyparts;
260
261
      for (i=0 ; i < keys ; i++)
373
374
    share->base.margin_key_file_length=(share->base.max_key_file_length -
374
375
                                        (keys ? MI_INDEX_BLOCK_MARGIN *
375
376
                                         share->blocksize * keys : 0));
376
 
    share->blocksize=cmin(IO_SIZE,myisam_block_size);
 
377
    share->blocksize=min(IO_SIZE,myisam_block_size);
377
378
    share->data_file_type=STATIC_RECORD;
378
379
    if (share->options & HA_OPTION_PACK_RECORD)
379
380
      share->data_file_type = DYNAMIC_RECORD;
380
 
    free(disk_cache);
381
 
    disk_cache= NULL;
 
381
    my_afree(disk_cache);
382
382
    mi_setup_functions(share);
383
383
    share->is_log_table= false;
384
384
    thr_lock_init(&share->lock);
385
 
    pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST);
 
385
    VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST));
386
386
    for (i=0; i<keys; i++)
387
 
      pthread_rwlock_init(&share->key_root_lock[i], NULL);
388
 
    pthread_rwlock_init(&share->mmap_lock, NULL);
 
387
      VOID(my_rwlock_init(&share->key_root_lock[i], NULL));
 
388
    VOID(my_rwlock_init(&share->mmap_lock, NULL));
389
389
    if (!thr_lock_inited)
390
390
    {
391
391
      /* Probably a single threaded program; Don't use concurrent inserts */
440
440
                       &info.first_mbr_key, share->base.max_key_length,
441
441
                       &info.filename,strlen(name)+1,
442
442
                       &info.rtree_recursion_state,have_rtree ? 1024 : 0,
443
 
                       NULL))
 
443
                       NullS))
444
444
    goto err;
445
445
  errpos=6;
446
446
 
447
447
  if (!have_rtree)
448
448
    info.rtree_recursion_state= NULL;
449
449
 
450
 
  strcpy(info.filename,name);
 
450
  stpcpy(info.filename,name);
451
451
  memcpy(info.blobs,share->blobs,sizeof(MI_BLOB)*share->base.blobs);
452
452
  info.lastkey2=info.lastkey+share->base.max_key_length;
453
453
 
510
510
  return(m_info);
511
511
 
512
512
err:
513
 
  if (disk_cache != NULL)
514
 
    free(disk_cache);
515
513
  save_errno=my_errno ? my_errno : HA_ERR_END_OF_FILE;
516
514
  if ((save_errno == HA_ERR_CRASHED) ||
517
515
      (save_errno == HA_ERR_CRASHED_ON_USAGE) ||
519
517
    mi_report_error(save_errno, name);
520
518
  switch (errpos) {
521
519
  case 6:
522
 
    free((unsigned char*) m_info);
 
520
    my_free((uchar*) m_info,MYF(0));
523
521
    /* fall through */
524
522
  case 5:
525
 
    my_close(info.dfile,MYF(0));
 
523
    VOID(my_close(info.dfile,MYF(0)));
526
524
    if (old_info)
527
525
      break;                                    /* Don't remove open table */
528
526
    /* fall through */
529
527
  case 4:
530
 
    free((unsigned char*) share);
 
528
    my_free((uchar*) share,MYF(0));
531
529
    /* fall through */
532
530
  case 3:
533
531
    /* fall through */
 
532
  case 2:
 
533
    my_afree(disk_cache);
 
534
    /* fall through */
534
535
  case 1:
535
 
    my_close(kfile,MYF(0));
 
536
    VOID(my_close(kfile,MYF(0)));
536
537
    /* fall through */
537
538
  case 0:
538
539
  default:
544
545
} /* mi_open */
545
546
 
546
547
 
547
 
unsigned char *mi_alloc_rec_buff(MI_INFO *info, size_t length, unsigned char **buf)
 
548
uchar *mi_alloc_rec_buff(MI_INFO *info, ulong length, uchar **buf)
548
549
{
549
 
  uint32_t extra;
 
550
  uint extra;
550
551
  uint32_t old_length= 0;
551
552
 
552
553
  if (! *buf || length > (old_length=mi_get_rec_buff_len(info, *buf)))
553
554
  {
554
 
    unsigned char *newptr = *buf;
 
555
    uchar *newptr = *buf;
555
556
 
556
557
    /* to simplify initial init of info->rec_buf in mi_open and mi_extra */
557
558
    if (length == (ulong) -1)
558
559
    {
559
560
      if (info->s->options & HA_OPTION_COMPRESS_RECORD)
560
 
        length= cmax(info->s->base.pack_reclength, info->s->max_pack_length);
 
561
        length= max(info->s->base.pack_reclength, info->s->max_pack_length);
561
562
      else
562
563
        length= info->s->base.pack_reclength;
563
 
      length= cmax(length, info->s->base.max_key_length);
 
564
      length= max(length, info->s->base.max_key_length);
564
565
      /* Avoid unnecessary realloc */
565
566
      if (newptr && length == old_length)
566
567
        return newptr;
571
572
            MI_REC_BUFF_OFFSET : 0);
572
573
    if (extra && newptr)
573
574
      newptr-= MI_REC_BUFF_OFFSET;
574
 
    void *tmpnewptr= NULL;
575
 
    if (!(tmpnewptr= realloc(newptr, length+extra+8))) 
 
575
    if (!(newptr=(uchar*) my_realloc((uchar*)newptr, length+extra+8,
 
576
                                     MYF(MY_ALLOW_ZERO_PTR))))
576
577
      return newptr;
577
 
    newptr= tmpnewptr;
578
578
    *((uint32_t *) newptr)= (uint32_t) length;
579
579
    *buf= newptr+(extra ?  MI_REC_BUFF_OFFSET : 0);
580
580
  }
693
693
   Function to save and store the header in the index file (.MYI)
694
694
*/
695
695
 
696
 
uint32_t mi_state_info_write(File file, MI_STATE_INFO *state, uint32_t pWrite)
 
696
uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite)
697
697
{
698
 
  unsigned char  buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
699
 
  unsigned char *ptr=buff;
 
698
  uchar  buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
 
699
  uchar *ptr=buff;
700
700
  uint  i, keys= (uint) state->header.keys,
701
701
        key_blocks=state->header.max_block_size_index;
702
702
 
705
705
 
706
706
  /* open_count must be first because of _mi_mark_file_changed ! */
707
707
  mi_int2store(ptr,state->open_count);          ptr +=2;
708
 
  *ptr++= (unsigned char)state->changed; *ptr++= state->sortkey;
 
708
  *ptr++= (uchar)state->changed; *ptr++= state->sortkey;
709
709
  mi_rowstore(ptr,state->state.records);        ptr +=8;
710
710
  mi_rowstore(ptr,state->state.del);            ptr +=8;
711
711
  mi_rowstore(ptr,state->split);                ptr +=8;
733
733
  }
734
734
  if (pWrite & 2)                               /* From isamchk */
735
735
  {
736
 
    uint32_t key_parts= mi_uint2korr(state->header.key_parts);
 
736
    uint key_parts= mi_uint2korr(state->header.key_parts);
737
737
    mi_int4store(ptr,state->sec_index_changed); ptr +=4;
738
738
    mi_int4store(ptr,state->sec_index_used);    ptr +=4;
739
739
    mi_int4store(ptr,state->version);           ptr +=4;
756
756
}
757
757
 
758
758
 
759
 
unsigned char *mi_state_info_read(unsigned char *ptr, MI_STATE_INFO *state)
 
759
uchar *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state)
760
760
{
761
 
  uint32_t i,keys,key_parts,key_blocks;
 
761
  uint i,keys,key_parts,key_blocks;
762
762
  memcpy(&state->header,ptr, sizeof(state->header));
763
763
  ptr +=sizeof(state->header);
764
764
  keys=(uint) state->header.keys;
809
809
}
810
810
 
811
811
 
812
 
uint32_t mi_state_info_read_dsk(File file, MI_STATE_INFO *state, bool pRead)
 
812
uint mi_state_info_read_dsk(File file, MI_STATE_INFO *state, bool pRead)
813
813
{
814
 
  unsigned char buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
 
814
  uchar buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
815
815
 
816
816
  if (!myisam_single_user)
817
817
  {
832
832
**  store and read of MI_BASE_INFO
833
833
****************************************************************************/
834
834
 
835
 
uint32_t mi_base_info_write(File file, MI_BASE_INFO *base)
 
835
uint mi_base_info_write(File file, MI_BASE_INFO *base)
836
836
{
837
 
  unsigned char buff[MI_BASE_INFO_SIZE], *ptr=buff;
 
837
  uchar buff[MI_BASE_INFO_SIZE], *ptr=buff;
838
838
 
839
839
  mi_sizestore(ptr,base->keystart);                     ptr +=8;
840
840
  mi_sizestore(ptr,base->max_data_file_length);         ptr +=8;
859
859
  mi_int2store(ptr,base->max_key_length);               ptr +=2;
860
860
  mi_int2store(ptr,base->extra_alloc_bytes);            ptr +=2;
861
861
  *ptr++= base->extra_alloc_procent;
862
 
  /* old raid info  slots */
863
 
  *ptr++= 0;
864
 
  mi_int2store(ptr,UINT16_C(0));                        ptr +=2;
865
 
  mi_int4store(ptr,UINT32_C(0));                        ptr +=4;
866
 
 
 
862
  *ptr++= base->raid_type;
 
863
  mi_int2store(ptr,base->raid_chunks);                  ptr +=2;
 
864
  mi_int4store(ptr,base->raid_chunksize);               ptr +=4;
867
865
  memset(ptr, 0, 6);                                    ptr +=6; /* extra */
868
866
  return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
869
867
}
870
868
 
871
869
 
872
 
unsigned char *my_n_base_info_read(unsigned char *ptr, MI_BASE_INFO *base)
 
870
uchar *my_n_base_info_read(uchar *ptr, MI_BASE_INFO *base)
873
871
{
874
872
  base->keystart = mi_sizekorr(ptr);                    ptr +=8;
875
873
  base->max_data_file_length = mi_sizekorr(ptr);        ptr +=8;
895
893
  base->max_key_length = mi_uint2korr(ptr);             ptr +=2;
896
894
  base->extra_alloc_bytes = mi_uint2korr(ptr);          ptr +=2;
897
895
  base->extra_alloc_procent = *ptr++;
898
 
 
899
 
  /* advance past raid_type (1) raid_chunks (2) and raid_chunksize (4) */
900
 
  ptr+= 7;
 
896
  base->raid_type= *ptr++;
 
897
  base->raid_chunks= mi_uint2korr(ptr);                 ptr +=2;
 
898
  base->raid_chunksize= mi_uint4korr(ptr);              ptr +=4;
 
899
  /* TO BE REMOVED: Fix for old RAID files */
 
900
  if (base->raid_type == 0)
 
901
  {
 
902
    base->raid_chunks=0;
 
903
    base->raid_chunksize=0;
 
904
  }
901
905
 
902
906
  ptr+=6;
903
907
  return ptr;
907
911
  mi_keydef
908
912
---------------------------------------------------------------------------*/
909
913
 
910
 
uint32_t mi_keydef_write(File file, MI_KEYDEF *keydef)
 
914
uint mi_keydef_write(File file, MI_KEYDEF *keydef)
911
915
{
912
 
  unsigned char buff[MI_KEYDEF_SIZE];
913
 
  unsigned char *ptr=buff;
 
916
  uchar buff[MI_KEYDEF_SIZE];
 
917
  uchar *ptr=buff;
914
918
 
915
 
  *ptr++ = (unsigned char) keydef->keysegs;
 
919
  *ptr++ = (uchar) keydef->keysegs;
916
920
  *ptr++ = keydef->key_alg;                     /* Rtree or Btree */
917
921
  mi_int2store(ptr,keydef->flag);               ptr +=2;
918
922
  mi_int2store(ptr,keydef->block_length);       ptr +=2;
922
926
  return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
923
927
}
924
928
 
925
 
unsigned char *mi_keydef_read(unsigned char *ptr, MI_KEYDEF *keydef)
 
929
uchar *mi_keydef_read(uchar *ptr, MI_KEYDEF *keydef)
926
930
{
927
931
   keydef->keysegs      = (uint) *ptr++;
928
932
   keydef->key_alg      = *ptr++;               /* Rtree or Btree */
944
948
 
945
949
int mi_keyseg_write(File file, const HA_KEYSEG *keyseg)
946
950
{
947
 
  unsigned char buff[HA_KEYSEG_SIZE];
948
 
  unsigned char *ptr=buff;
 
951
  uchar buff[HA_KEYSEG_SIZE];
 
952
  uchar *ptr=buff;
949
953
  ulong pos;
950
954
 
951
955
  *ptr++= keyseg->type;
960
964
  pos= keyseg->null_bit ? keyseg->null_pos : keyseg->bit_pos;
961
965
  mi_int4store(ptr, pos);
962
966
  ptr+=4;
963
 
 
 
967
  
964
968
  return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
965
969
}
966
970
 
967
971
 
968
 
unsigned char *mi_keyseg_read(unsigned char *ptr, HA_KEYSEG *keyseg)
 
972
uchar *mi_keyseg_read(uchar *ptr, HA_KEYSEG *keyseg)
969
973
{
970
974
   keyseg->type         = *ptr++;
971
975
   keyseg->language     = *ptr++;
992
996
  mi_uniquedef
993
997
---------------------------------------------------------------------------*/
994
998
 
995
 
uint32_t mi_uniquedef_write(File file, MI_UNIQUEDEF *def)
 
999
uint mi_uniquedef_write(File file, MI_UNIQUEDEF *def)
996
1000
{
997
 
  unsigned char buff[MI_UNIQUEDEF_SIZE];
998
 
  unsigned char *ptr=buff;
 
1001
  uchar buff[MI_UNIQUEDEF_SIZE];
 
1002
  uchar *ptr=buff;
999
1003
 
1000
1004
  mi_int2store(ptr,def->keysegs);               ptr+=2;
1001
 
  *ptr++=  (unsigned char) def->key;
1002
 
  *ptr++ = (unsigned char) def->null_are_equal;
 
1005
  *ptr++=  (uchar) def->key;
 
1006
  *ptr++ = (uchar) def->null_are_equal;
1003
1007
 
1004
1008
  return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
1005
1009
}
1006
1010
 
1007
 
unsigned char *mi_uniquedef_read(unsigned char *ptr, MI_UNIQUEDEF *def)
 
1011
uchar *mi_uniquedef_read(uchar *ptr, MI_UNIQUEDEF *def)
1008
1012
{
1009
1013
   def->keysegs = mi_uint2korr(ptr);
1010
1014
   def->key     = ptr[2];
1016
1020
**  MI_COLUMNDEF
1017
1021
***************************************************************************/
1018
1022
 
1019
 
uint32_t mi_recinfo_write(File file, MI_COLUMNDEF *recinfo)
 
1023
uint mi_recinfo_write(File file, MI_COLUMNDEF *recinfo)
1020
1024
{
1021
 
  unsigned char buff[MI_COLUMNDEF_SIZE];
1022
 
  unsigned char *ptr=buff;
 
1025
  uchar buff[MI_COLUMNDEF_SIZE];
 
1026
  uchar *ptr=buff;
1023
1027
 
1024
1028
  mi_int2store(ptr,recinfo->type);      ptr +=2;
1025
1029
  mi_int2store(ptr,recinfo->length);    ptr +=2;
1028
1032
  return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
1029
1033
}
1030
1034
 
1031
 
unsigned char *mi_recinfo_read(unsigned char *ptr, MI_COLUMNDEF *recinfo)
 
1035
uchar *mi_recinfo_read(uchar *ptr, MI_COLUMNDEF *recinfo)
1032
1036
{
1033
1037
   recinfo->type=  mi_sint2korr(ptr);   ptr +=2;
1034
1038
   recinfo->length=mi_uint2korr(ptr);   ptr +=2;
1038
1042
}
1039
1043
 
1040
1044
/**************************************************************************
1041
 
Open data file
 
1045
Open data file with or without RAID
1042
1046
We can't use dup() here as the data file descriptors need to have different
1043
1047
active seek-positions.
1044
1048
 
1049
1053
int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share,
1050
1054
                     File file_to_dup __attribute__((unused)))
1051
1055
{
1052
 
    info->dfile=my_open(share->data_file_name, share->mode,
 
1056
    info->dfile=my_open(share->data_file_name, share->mode | O_SHARE,
1053
1057
                        MYF(MY_WME));
1054
1058
  return info->dfile >= 0 ? 0 : 1;
1055
1059
}
1057
1061
 
1058
1062
int mi_open_keyfile(MYISAM_SHARE *share)
1059
1063
{
1060
 
  if ((share->kfile=my_open(share->unique_file_name, share->mode,
 
1064
  if ((share->kfile=my_open(share->unique_file_name, share->mode | O_SHARE,
1061
1065
                            MYF(MY_WME))) < 0)
1062
1066
    return 1;
1063
1067
  return 0;