18
18
#include "myisamdef.h"
19
19
#include <mystrings/m_ctype.h>
20
#include <mystrings/m_string.h>
21
#include <drizzled/util/test.h>
21
27
static void setup_key_functions(MI_KEYDEF *keyinfo);
22
#define get_next_element(to,pos,size) \
24
memcpy(to, pos, size); \
29
29
#define disk_pos_assert(pos, end_pos) \
30
30
if (pos > end_pos) \
42
42
MI_INFO *test_if_reopen(char *filename)
46
for (pos=myisam_open_list ; pos ; pos=pos->next)
44
list<MI_INFO *>::iterator it= myisam_open_list.begin();
45
while (it != myisam_open_list.end())
48
MI_INFO *info=(MI_INFO*) pos->data;
49
48
MYISAM_SHARE *share=info->s;
50
49
if (!strcmp(share->unique_file_name,filename) && share->last_version)
62
62
have an open count of 0.
63
63
******************************************************************************/
65
MI_INFO *mi_open(const char *name, int mode, uint open_flags)
65
MI_INFO *mi_open(const char *name, int mode, uint32_t open_flags)
67
67
int lock_error,kfile,open_mode,save_errno,have_rtree=0;
68
uint i,j,len,errpos,head_length,base_pos,offset,info_length,keys,
68
uint32_t i,j,len,errpos,head_length,base_pos,offset,info_length,keys,
69
69
key_parts,unique_key_parts,fulltext_keys,uniques;
70
70
char name_buff[FN_REFLEN], org_name[FN_REFLEN], index_name[FN_REFLEN],
71
71
data_name[FN_REFLEN];
72
uchar *disk_cache, *disk_pos, *end_pos;
72
unsigned char *disk_cache= NULL;
73
unsigned char *disk_pos, *end_pos;
73
74
MI_INFO info,*m_info,*old_info;
74
75
MYISAM_SHARE share_buff,*share;
75
76
ulong rec_per_key_part[HA_MAX_POSSIBLE_KEY*MI_MAX_KEY_SEG];
92
93
share_buff.state.rec_per_key_part=rec_per_key_part;
93
94
share_buff.state.key_root=key_root;
94
95
share_buff.state.key_del=key_del;
95
share_buff.key_cache= multi_key_cache_search((uchar*) name_buff,
96
share_buff.key_cache= multi_key_cache_search((unsigned char*) name_buff,
96
97
strlen(name_buff));
98
if ((kfile=my_open(name_buff,(open_mode=O_RDWR) | O_SHARE,MYF(0))) < 0)
99
if ((kfile=my_open(name_buff,(open_mode=O_RDWR),MYF(0))) < 0)
100
101
if ((errno != EROFS && errno != EACCES) ||
101
102
mode != O_RDONLY ||
102
(kfile=my_open(name_buff,(open_mode=O_RDONLY) | O_SHARE,MYF(0))) < 0)
103
(kfile=my_open(name_buff,(open_mode=O_RDONLY),MYF(0))) < 0)
105
106
share->mode=open_mode;
135
136
/* Don't call realpath() if the name can't be a link */
136
137
if (!strcmp(name_buff, org_name) ||
137
138
my_readlink(index_name, org_name, MYF(0)) == -1)
138
(void) stpcpy(index_name, org_name);
139
(void) strcpy(index_name, org_name);
139
140
*strrchr(org_name, '.')= '\0';
140
141
(void) fn_format(data_name,org_name,"",MI_NAME_DEXT,
141
142
MY_APPEND_EXT|MY_UNPACK_FILENAME|MY_RESOLVE_SYMLINKS);
143
144
info_length=mi_uint2korr(share->state.header.header_length);
144
145
base_pos=mi_uint2korr(share->state.header.base_pos);
145
if (!(disk_cache= (uchar*) my_alloca(info_length+128)))
146
if (!(disk_cache= (unsigned char*) malloc(info_length+128)))
150
151
end_pos=disk_cache+info_length;
153
VOID(my_seek(kfile,0L,MY_SEEK_SET,MYF(0)));
154
lseek(kfile,0,SEEK_SET);
155
156
if (my_read(kfile,disk_cache,info_length,MYF(MY_NABP)))
204
205
mi_safe_mul(MI_MIN_KEY_BLOCK_LENGTH,
205
206
((uint64_t) 1 << (share->base.key_reflength*8))-1);
206
207
#if SIZEOF_OFF_T == 4
207
set_if_smaller(max_data_file_length, INT_MAX32);
208
set_if_smaller(max_key_file_length, INT_MAX32);
208
set_if_smaller(max_data_file_length, INT32_MAX);
209
set_if_smaller(max_key_file_length, INT32_MAX);
210
211
if (share->base.raid_type)
238
239
&share->state.key_root,keys*sizeof(my_off_t),
239
240
&share->state.key_del,
240
241
(share->state.header.max_block_size_index*sizeof(my_off_t)),
241
&share->key_root_lock,sizeof(rw_lock_t)*keys,
242
&share->mmap_lock,sizeof(rw_lock_t),
242
&share->key_root_lock,sizeof(pthread_rwlock_t)*keys,
243
&share->mmap_lock,sizeof(pthread_rwlock_t),
246
247
*share=share_buff;
250
251
sizeof(my_off_t)*keys);
251
252
memcpy(share->state.key_del, key_del,
252
253
sizeof(my_off_t) * share->state.header.max_block_size_index);
253
stpcpy(share->unique_file_name, name_buff);
254
strcpy(share->unique_file_name, name_buff);
254
255
share->unique_name_length= strlen(name_buff);
255
stpcpy(share->index_file_name, index_name);
256
stpcpy(share->data_file_name, data_name);
256
strcpy(share->index_file_name, index_name);
257
strcpy(share->data_file_name, data_name);
258
share->blocksize=min(IO_SIZE,myisam_block_size);
259
share->blocksize=cmin(IO_SIZE,myisam_block_size);
260
261
HA_KEYSEG *pos=share->keyparts;
261
262
for (i=0 ; i < keys ; i++)
264
265
disk_pos=mi_keydef_read(disk_pos, &share->keyinfo[i]);
265
266
disk_pos_assert(disk_pos + share->keyinfo[i].keysegs * HA_KEYSEG_SIZE,
267
set_if_smaller(share->blocksize,share->keyinfo[i].block_length);
268
set_if_smaller(share->blocksize,(uint)share->keyinfo[i].block_length);
268
269
share->keyinfo[i].seg=pos;
269
270
for (j=0 ; j < share->keyinfo[i].keysegs; j++,pos++)
283
284
if (!pos->language)
284
285
pos->charset=default_charset_info;
285
else if (!(pos->charset= get_charset(pos->language, MYF(MY_WME))))
286
else if (!(pos->charset= get_charset(pos->language)))
287
288
my_errno=HA_ERR_UNKNOWN_CHARSET;
315
316
if (!pos->language)
316
317
pos->charset=default_charset_info;
317
else if (!(pos->charset= get_charset(pos->language, MYF(MY_WME))))
318
else if (!(pos->charset= get_charset(pos->language)))
319
320
my_errno=HA_ERR_UNKNOWN_CHARSET;
374
375
share->base.margin_key_file_length=(share->base.max_key_file_length -
375
376
(keys ? MI_INDEX_BLOCK_MARGIN *
376
377
share->blocksize * keys : 0));
377
share->blocksize=min(IO_SIZE,myisam_block_size);
378
share->blocksize=cmin(IO_SIZE,myisam_block_size);
378
379
share->data_file_type=STATIC_RECORD;
379
380
if (share->options & HA_OPTION_PACK_RECORD)
380
381
share->data_file_type = DYNAMIC_RECORD;
381
my_afree(disk_cache);
382
384
mi_setup_functions(share);
383
385
share->is_log_table= false;
384
386
thr_lock_init(&share->lock);
385
VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST));
387
pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST);
386
388
for (i=0; i<keys; i++)
387
VOID(my_rwlock_init(&share->key_root_lock[i], NULL));
388
VOID(my_rwlock_init(&share->mmap_lock, NULL));
389
pthread_rwlock_init(&share->key_root_lock[i], NULL);
390
pthread_rwlock_init(&share->mmap_lock, NULL);
389
391
if (!thr_lock_inited)
391
393
/* Probably a single threaded program; Don't use concurrent inserts */
440
442
&info.first_mbr_key, share->base.max_key_length,
441
443
&info.filename,strlen(name)+1,
442
444
&info.rtree_recursion_state,have_rtree ? 1024 : 0,
448
450
info.rtree_recursion_state= NULL;
450
stpcpy(info.filename,name);
452
strcpy(info.filename,name);
451
453
memcpy(info.blobs,share->blobs,sizeof(MI_BLOB)*share->base.blobs);
452
454
info.lastkey2=info.lastkey+share->base.max_key_length;
505
507
thr_lock_data_init(&share->lock,&m_info->lock,(void*) m_info);
506
m_info->open_list.data=(void*) m_info;
507
myisam_open_list=list_add(myisam_open_list,&m_info->open_list);
508
myisam_open_list.push_front(m_info);
509
510
pthread_mutex_unlock(&THR_LOCK_myisam);
514
if (disk_cache != NULL)
513
516
save_errno=my_errno ? my_errno : HA_ERR_END_OF_FILE;
514
517
if ((save_errno == HA_ERR_CRASHED) ||
515
518
(save_errno == HA_ERR_CRASHED_ON_USAGE) ||
517
520
mi_report_error(save_errno, name);
518
521
switch (errpos) {
520
my_free((uchar*) m_info,MYF(0));
523
free((unsigned char*) m_info);
521
524
/* fall through */
523
VOID(my_close(info.dfile,MYF(0)));
526
my_close(info.dfile,MYF(0));
525
528
break; /* Don't remove open table */
526
529
/* fall through */
528
my_free((uchar*) share,MYF(0));
531
free((unsigned char*) share);
529
532
/* fall through */
531
534
/* fall through */
533
my_afree(disk_cache);
536
VOID(my_close(kfile,MYF(0)));
536
my_close(kfile,MYF(0));
537
537
/* fall through */
548
uchar *mi_alloc_rec_buff(MI_INFO *info, ulong length, uchar **buf)
548
unsigned char *mi_alloc_rec_buff(MI_INFO *info, size_t length, unsigned char **buf)
551
551
uint32_t old_length= 0;
553
553
if (! *buf || length > (old_length=mi_get_rec_buff_len(info, *buf)))
555
uchar *newptr = *buf;
555
unsigned char *newptr = *buf;
557
557
/* to simplify initial init of info->rec_buf in mi_open and mi_extra */
558
558
if (length == (ulong) -1)
560
560
if (info->s->options & HA_OPTION_COMPRESS_RECORD)
561
length= max(info->s->base.pack_reclength, info->s->max_pack_length);
561
length= cmax(info->s->base.pack_reclength, info->s->max_pack_length);
563
563
length= info->s->base.pack_reclength;
564
length= max(length, info->s->base.max_key_length);
564
length= cmax(length, info->s->base.max_key_length);
565
565
/* Avoid unnecessary realloc */
566
566
if (newptr && length == old_length)
572
572
MI_REC_BUFF_OFFSET : 0);
573
573
if (extra && newptr)
574
574
newptr-= MI_REC_BUFF_OFFSET;
575
if (!(newptr=(uchar*) my_realloc((uchar*)newptr, length+extra+8,
576
MYF(MY_ALLOW_ZERO_PTR))))
575
void *tmpnewptr= NULL;
576
if (!(tmpnewptr= realloc(newptr, length+extra+8)))
578
newptr= (unsigned char *)tmpnewptr;
578
579
*((uint32_t *) newptr)= (uint32_t) length;
579
580
*buf= newptr+(extra ? MI_REC_BUFF_OFFSET : 0);
693
694
Function to save and store the header in the index file (.MYI)
696
uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite)
697
uint32_t mi_state_info_write(File file, MI_STATE_INFO *state, uint32_t pWrite)
698
uchar buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
699
unsigned char buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
700
unsigned char *ptr=buff;
700
701
uint i, keys= (uint) state->header.keys,
701
702
key_blocks=state->header.max_block_size_index;
706
707
/* open_count must be first because of _mi_mark_file_changed ! */
707
708
mi_int2store(ptr,state->open_count); ptr +=2;
708
*ptr++= (uchar)state->changed; *ptr++= state->sortkey;
709
*ptr++= (unsigned char)state->changed; *ptr++= state->sortkey;
709
710
mi_rowstore(ptr,state->state.records); ptr +=8;
710
711
mi_rowstore(ptr,state->state.del); ptr +=8;
711
712
mi_rowstore(ptr,state->split); ptr +=8;
734
735
if (pWrite & 2) /* From isamchk */
736
uint key_parts= mi_uint2korr(state->header.key_parts);
737
uint32_t key_parts= mi_uint2korr(state->header.key_parts);
737
738
mi_int4store(ptr,state->sec_index_changed); ptr +=4;
738
739
mi_int4store(ptr,state->sec_index_used); ptr +=4;
739
740
mi_int4store(ptr,state->version); ptr +=4;
759
uchar *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state)
760
unsigned char *mi_state_info_read(unsigned char *ptr, MI_STATE_INFO *state)
761
uint i,keys,key_parts,key_blocks;
762
uint32_t i,keys,key_parts,key_blocks;
762
763
memcpy(&state->header,ptr, sizeof(state->header));
763
764
ptr +=sizeof(state->header);
764
765
keys=(uint) state->header.keys;
812
uint mi_state_info_read_dsk(File file, MI_STATE_INFO *state, bool pRead)
813
uint32_t mi_state_info_read_dsk(File file, MI_STATE_INFO *state, bool pRead)
814
uchar buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
815
unsigned char buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
816
817
if (!myisam_single_user)
832
833
** store and read of MI_BASE_INFO
833
834
****************************************************************************/
835
uint mi_base_info_write(File file, MI_BASE_INFO *base)
836
uint32_t mi_base_info_write(File file, MI_BASE_INFO *base)
837
uchar buff[MI_BASE_INFO_SIZE], *ptr=buff;
838
unsigned char buff[MI_BASE_INFO_SIZE], *ptr=buff;
839
840
mi_sizestore(ptr,base->keystart); ptr +=8;
840
841
mi_sizestore(ptr,base->max_data_file_length); ptr +=8;
859
860
mi_int2store(ptr,base->max_key_length); ptr +=2;
860
861
mi_int2store(ptr,base->extra_alloc_bytes); ptr +=2;
861
862
*ptr++= base->extra_alloc_procent;
862
*ptr++= base->raid_type;
863
mi_int2store(ptr,base->raid_chunks); ptr +=2;
864
mi_int4store(ptr,base->raid_chunksize); ptr +=4;
863
/* old raid info slots */
865
mi_int2store(ptr,UINT16_C(0)); ptr +=2;
866
mi_int4store(ptr,UINT32_C(0)); ptr +=4;
865
868
memset(ptr, 0, 6); ptr +=6; /* extra */
866
869
return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
870
uchar *my_n_base_info_read(uchar *ptr, MI_BASE_INFO *base)
873
unsigned char *my_n_base_info_read(unsigned char *ptr, MI_BASE_INFO *base)
872
875
base->keystart = mi_sizekorr(ptr); ptr +=8;
873
876
base->max_data_file_length = mi_sizekorr(ptr); ptr +=8;
893
896
base->max_key_length = mi_uint2korr(ptr); ptr +=2;
894
897
base->extra_alloc_bytes = mi_uint2korr(ptr); ptr +=2;
895
898
base->extra_alloc_procent = *ptr++;
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)
903
base->raid_chunksize=0;
900
/* advance past raid_type (1) raid_chunks (2) and raid_chunksize (4) */
912
909
---------------------------------------------------------------------------*/
914
uint mi_keydef_write(File file, MI_KEYDEF *keydef)
911
uint32_t mi_keydef_write(File file, MI_KEYDEF *keydef)
916
uchar buff[MI_KEYDEF_SIZE];
913
unsigned char buff[MI_KEYDEF_SIZE];
914
unsigned char *ptr=buff;
919
*ptr++ = (uchar) keydef->keysegs;
916
*ptr++ = (unsigned char) keydef->keysegs;
920
917
*ptr++ = keydef->key_alg; /* Rtree or Btree */
921
918
mi_int2store(ptr,keydef->flag); ptr +=2;
922
919
mi_int2store(ptr,keydef->block_length); ptr +=2;
926
923
return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
929
uchar *mi_keydef_read(uchar *ptr, MI_KEYDEF *keydef)
926
unsigned char *mi_keydef_read(unsigned char *ptr, MI_KEYDEF *keydef)
931
928
keydef->keysegs = (uint) *ptr++;
932
929
keydef->key_alg = *ptr++; /* Rtree or Btree */
964
961
pos= keyseg->null_bit ? keyseg->null_pos : keyseg->bit_pos;
965
962
mi_int4store(ptr, pos);
968
965
return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
972
uchar *mi_keyseg_read(uchar *ptr, HA_KEYSEG *keyseg)
969
unsigned char *mi_keyseg_read(unsigned char *ptr, HA_KEYSEG *keyseg)
974
971
keyseg->type = *ptr++;
975
972
keyseg->language = *ptr++;
997
994
---------------------------------------------------------------------------*/
999
uint mi_uniquedef_write(File file, MI_UNIQUEDEF *def)
996
uint32_t mi_uniquedef_write(File file, MI_UNIQUEDEF *def)
1001
uchar buff[MI_UNIQUEDEF_SIZE];
998
unsigned char buff[MI_UNIQUEDEF_SIZE];
999
unsigned char *ptr=buff;
1004
1001
mi_int2store(ptr,def->keysegs); ptr+=2;
1005
*ptr++= (uchar) def->key;
1006
*ptr++ = (uchar) def->null_are_equal;
1002
*ptr++= (unsigned char) def->key;
1003
*ptr++ = (unsigned char) def->null_are_equal;
1008
1005
return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
1011
uchar *mi_uniquedef_read(uchar *ptr, MI_UNIQUEDEF *def)
1008
unsigned char *mi_uniquedef_read(unsigned char *ptr, MI_UNIQUEDEF *def)
1013
1010
def->keysegs = mi_uint2korr(ptr);
1014
1011
def->key = ptr[2];
1020
1017
** MI_COLUMNDEF
1021
1018
***************************************************************************/
1023
uint mi_recinfo_write(File file, MI_COLUMNDEF *recinfo)
1020
uint32_t mi_recinfo_write(File file, MI_COLUMNDEF *recinfo)
1025
uchar buff[MI_COLUMNDEF_SIZE];
1022
unsigned char buff[MI_COLUMNDEF_SIZE];
1023
unsigned char *ptr=buff;
1028
1025
mi_int2store(ptr,recinfo->type); ptr +=2;
1029
1026
mi_int2store(ptr,recinfo->length); ptr +=2;
1032
1029
return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
1035
uchar *mi_recinfo_read(uchar *ptr, MI_COLUMNDEF *recinfo)
1032
unsigned char *mi_recinfo_read(unsigned char *ptr, MI_COLUMNDEF *recinfo)
1037
1034
recinfo->type= mi_sint2korr(ptr); ptr +=2;
1038
1035
recinfo->length=mi_uint2korr(ptr); ptr +=2;
1050
1047
exist a dup()-like call that would give us two different file descriptors.
1051
1048
*************************************************************************/
1053
int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share,
1054
File file_to_dup __attribute__((unused)))
1050
int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, File file_to_dup)
1056
info->dfile=my_open(share->data_file_name, share->mode | O_SHARE,
1053
info->dfile=my_open(share->data_file_name, share->mode,
1058
1055
return info->dfile >= 0 ? 0 : 1;
1062
1059
int mi_open_keyfile(MYISAM_SHARE *share)
1064
if ((share->kfile=my_open(share->unique_file_name, share->mode | O_SHARE,
1061
if ((share->kfile=my_open(share->unique_file_name, share->mode,
1065
1062
MYF(MY_WME))) < 0)