18
18
#include "myisamdef.h"
19
19
#include <mystrings/m_ctype.h>
20
#include <mystrings/m_string.h>
21
#include <drizzled/util/test.h>
25
21
static void setup_key_functions(MI_KEYDEF *keyinfo);
22
#define get_next_element(to,pos,size) { memcpy((char*) to,pos,(size_t) size); \
27
26
#define disk_pos_assert(pos, end_pos) \
28
27
if (pos > end_pos) \
60
59
have an open count of 0.
61
60
******************************************************************************/
63
MI_INFO *mi_open(const char *name, int mode, uint32_t open_flags)
62
MI_INFO *mi_open(const char *name, int mode, uint open_flags)
65
64
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,
65
uint i,j,len,errpos,head_length,base_pos,offset,info_length,keys,
67
66
key_parts,unique_key_parts,fulltext_keys,uniques;
68
67
char name_buff[FN_REFLEN], org_name[FN_REFLEN], index_name[FN_REFLEN],
69
68
data_name[FN_REFLEN];
70
unsigned char *disk_cache= NULL;
71
unsigned char *disk_pos, *end_pos;
69
uchar *disk_cache, *disk_pos, *end_pos;
72
70
MI_INFO info,*m_info,*old_info;
73
71
MYISAM_SHARE share_buff,*share;
74
72
ulong rec_per_key_part[HA_MAX_POSSIBLE_KEY*MI_MAX_KEY_SEG];
81
79
head_length=sizeof(share_buff.state.header);
82
memset(&info, 0, sizeof(info));
80
memset((uchar*) &info, 0, sizeof(info));
84
82
my_realpath(name_buff, fn_format(org_name,name,"",MI_NAME_IEXT,
85
83
MY_UNPACK_FILENAME),MYF(0));
87
85
if (!(old_info=test_if_reopen(name_buff)))
89
87
share= &share_buff;
90
memset(&share_buff, 0, sizeof(share_buff));
88
memset((uchar*) &share_buff, 0, sizeof(share_buff));
91
89
share_buff.state.rec_per_key_part=rec_per_key_part;
92
90
share_buff.state.key_root=key_root;
93
91
share_buff.state.key_del=key_del;
94
share_buff.key_cache= multi_key_cache_search((unsigned char*) name_buff,
92
share_buff.key_cache= multi_key_cache_search((uchar*) name_buff,
95
93
strlen(name_buff));
97
if ((kfile=my_open(name_buff,(open_mode=O_RDWR),MYF(0))) < 0)
95
if ((kfile=my_open(name_buff,(open_mode=O_RDWR) | O_SHARE,MYF(0))) < 0)
99
97
if ((errno != EROFS && errno != EACCES) ||
100
98
mode != O_RDONLY ||
101
(kfile=my_open(name_buff,(open_mode=O_RDONLY),MYF(0))) < 0)
99
(kfile=my_open(name_buff,(open_mode=O_RDONLY) | O_SHARE,MYF(0))) < 0)
104
102
share->mode=open_mode;
109
107
my_errno= HA_ERR_NOT_A_TABLE;
112
if (memcmp(share->state.header.file_version, myisam_file_magic, 4))
110
if (memcmp((uchar*) share->state.header.file_version,
111
(uchar*) myisam_file_magic, 4))
114
113
my_errno=HA_ERR_NOT_A_TABLE;
134
133
/* Don't call realpath() if the name can't be a link */
135
134
if (!strcmp(name_buff, org_name) ||
136
135
my_readlink(index_name, org_name, MYF(0)) == -1)
137
(void) strcpy(index_name, org_name);
136
(void) strmov(index_name, org_name);
138
137
*strrchr(org_name, '.')= '\0';
139
138
(void) fn_format(data_name,org_name,"",MI_NAME_DEXT,
140
139
MY_APPEND_EXT|MY_UNPACK_FILENAME|MY_RESOLVE_SYMLINKS);
142
141
info_length=mi_uint2korr(share->state.header.header_length);
143
142
base_pos=mi_uint2korr(share->state.header.base_pos);
144
if (!(disk_cache= (unsigned char*) malloc(info_length+128)))
143
if (!(disk_cache= (uchar*) my_alloca(info_length+128)))
149
148
end_pos=disk_cache+info_length;
152
lseek(kfile,0,SEEK_SET);
151
VOID(my_seek(kfile,0L,MY_SEEK_SET,MYF(0)));
154
153
if (my_read(kfile,disk_cache,info_length,MYF(MY_NABP)))
203
202
mi_safe_mul(MI_MIN_KEY_BLOCK_LENGTH,
204
203
((uint64_t) 1 << (share->base.key_reflength*8))-1);
205
204
#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);
205
set_if_smaller(max_data_file_length, INT_MAX32);
206
set_if_smaller(max_key_file_length, INT_MAX32);
209
208
if (share->base.raid_type)
237
236
&share->state.key_root,keys*sizeof(my_off_t),
238
237
&share->state.key_del,
239
238
(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),
239
&share->key_root_lock,sizeof(rw_lock_t)*keys,
240
&share->mmap_lock,sizeof(rw_lock_t),
245
244
*share=share_buff;
246
memcpy(share->state.rec_per_key_part, rec_per_key_part,
247
sizeof(long)*key_parts);
248
memcpy(share->state.key_root, key_root,
249
sizeof(my_off_t)*keys);
250
memcpy(share->state.key_del, key_del,
251
sizeof(my_off_t) * share->state.header.max_block_size_index);
252
strcpy(share->unique_file_name, name_buff);
245
memcpy((char*) share->state.rec_per_key_part,
246
(char*) rec_per_key_part, sizeof(long)*key_parts);
247
memcpy((char*) share->state.key_root,
248
(char*) key_root, sizeof(my_off_t)*keys);
249
memcpy((char*) share->state.key_del,
250
(char*) key_del, (sizeof(my_off_t) *
251
share->state.header.max_block_size_index));
252
strmov(share->unique_file_name, name_buff);
253
253
share->unique_name_length= strlen(name_buff);
254
strcpy(share->index_file_name, index_name);
255
strcpy(share->data_file_name, data_name);
254
strmov(share->index_file_name, index_name);
255
strmov(share->data_file_name, data_name);
257
share->blocksize=cmin(IO_SIZE,myisam_block_size);
257
share->blocksize=min(IO_SIZE,myisam_block_size);
259
259
HA_KEYSEG *pos=share->keyparts;
260
260
for (i=0 ; i < keys ; i++)
373
373
share->base.margin_key_file_length=(share->base.max_key_file_length -
374
374
(keys ? MI_INDEX_BLOCK_MARGIN *
375
375
share->blocksize * keys : 0));
376
share->blocksize=cmin(IO_SIZE,myisam_block_size);
376
share->blocksize=min(IO_SIZE,myisam_block_size);
377
377
share->data_file_type=STATIC_RECORD;
378
if (share->options & HA_OPTION_PACK_RECORD)
378
if (share->options & HA_OPTION_COMPRESS_RECORD)
380
share->data_file_type = COMPRESSED_RECORD;
381
share->options|= HA_OPTION_READ_ONLY_DATA;
383
if (_mi_read_pack_info(&info,
385
test(!(share->options &
386
(HA_OPTION_PACK_RECORD |
387
HA_OPTION_TEMP_COMPRESS_RECORD)))))
390
else if (share->options & HA_OPTION_PACK_RECORD)
379
391
share->data_file_type = DYNAMIC_RECORD;
392
my_afree(disk_cache);
382
393
mi_setup_functions(share);
383
394
share->is_log_table= false;
384
395
thr_lock_init(&share->lock);
385
pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST);
396
VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST));
386
397
for (i=0; i<keys; i++)
387
pthread_rwlock_init(&share->key_root_lock[i], NULL);
388
pthread_rwlock_init(&share->mmap_lock, NULL);
398
VOID(my_rwlock_init(&share->key_root_lock[i], NULL));
399
VOID(my_rwlock_init(&share->mmap_lock, NULL));
389
400
if (!thr_lock_inited)
391
402
/* Probably a single threaded program; Don't use concurrent inserts */
440
451
&info.first_mbr_key, share->base.max_key_length,
441
452
&info.filename,strlen(name)+1,
442
453
&info.rtree_recursion_state,have_rtree ? 1024 : 0,
448
459
info.rtree_recursion_state= NULL;
450
strcpy(info.filename,name);
461
strmov(info.filename,name);
451
462
memcpy(info.blobs,share->blobs,sizeof(MI_BLOB)*share->base.blobs);
452
463
info.lastkey2=info.lastkey+share->base.max_key_length;
507
518
myisam_open_list=list_add(myisam_open_list,&m_info->open_list);
509
520
pthread_mutex_unlock(&THR_LOCK_myisam);
521
if (myisam_log_file >= 0)
523
intern_filename(name_buff,share->index_file_name);
524
_myisam_log(MI_LOG_OPEN, m_info, (uchar*) name_buff, strlen(name_buff));
513
if (disk_cache != NULL)
515
529
save_errno=my_errno ? my_errno : HA_ERR_END_OF_FILE;
516
530
if ((save_errno == HA_ERR_CRASHED) ||
517
531
(save_errno == HA_ERR_CRASHED_ON_USAGE) ||
519
533
mi_report_error(save_errno, name);
520
534
switch (errpos) {
522
free((unsigned char*) m_info);
536
my_free((uchar*) m_info,MYF(0));
523
537
/* fall through */
525
my_close(info.dfile,MYF(0));
539
VOID(my_close(info.dfile,MYF(0)));
527
541
break; /* Don't remove open table */
528
542
/* fall through */
530
free((unsigned char*) share);
544
my_free((uchar*) share,MYF(0));
531
545
/* fall through */
533
547
/* fall through */
549
my_afree(disk_cache);
535
my_close(kfile,MYF(0));
552
VOID(my_close(kfile,MYF(0)));
536
553
/* fall through */
547
unsigned char *mi_alloc_rec_buff(MI_INFO *info, size_t length, unsigned char **buf)
564
uchar *mi_alloc_rec_buff(MI_INFO *info, ulong length, uchar **buf)
550
567
uint32_t old_length= 0;
552
569
if (! *buf || length > (old_length=mi_get_rec_buff_len(info, *buf)))
554
unsigned char *newptr = *buf;
571
uchar *newptr = *buf;
556
573
/* to simplify initial init of info->rec_buf in mi_open and mi_extra */
557
574
if (length == (ulong) -1)
559
576
if (info->s->options & HA_OPTION_COMPRESS_RECORD)
560
length= cmax(info->s->base.pack_reclength, info->s->max_pack_length);
577
length= max(info->s->base.pack_reclength, info->s->max_pack_length);
562
579
length= info->s->base.pack_reclength;
563
length= cmax(length, info->s->base.max_key_length);
580
length= max(length, info->s->base.max_key_length);
564
581
/* Avoid unnecessary realloc */
565
582
if (newptr && length == old_length)
571
588
MI_REC_BUFF_OFFSET : 0);
572
589
if (extra && newptr)
573
590
newptr-= MI_REC_BUFF_OFFSET;
574
void *tmpnewptr= NULL;
575
if (!(tmpnewptr= realloc(newptr, length+extra+8)))
591
if (!(newptr=(uchar*) my_realloc((uchar*)newptr, length+extra+8,
592
MYF(MY_ALLOW_ZERO_PTR))))
578
594
*((uint32_t *) newptr)= (uint32_t) length;
579
595
*buf= newptr+(extra ? MI_REC_BUFF_OFFSET : 0);
596
612
void mi_setup_functions(register MYISAM_SHARE *share)
598
if (share->options & HA_OPTION_PACK_RECORD)
614
if (share->options & HA_OPTION_COMPRESS_RECORD)
616
share->read_record=_mi_read_pack_record;
617
share->read_rnd=_mi_read_rnd_pack_record;
618
if (!(share->options & HA_OPTION_TEMP_COMPRESS_RECORD))
619
share->calc_checksum=0; /* No checksum */
620
else if (share->options & HA_OPTION_PACK_RECORD)
621
share->calc_checksum= mi_checksum;
623
share->calc_checksum= mi_static_checksum;
625
else if (share->options & HA_OPTION_PACK_RECORD)
600
627
share->read_record=_mi_read_dynamic_record;
601
628
share->read_rnd=_mi_read_rnd_dynamic_record;
693
720
Function to save and store the header in the index file (.MYI)
696
uint32_t mi_state_info_write(File file, MI_STATE_INFO *state, uint32_t pWrite)
723
uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite)
698
unsigned char buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
699
unsigned char *ptr=buff;
725
uchar buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
700
727
uint i, keys= (uint) state->header.keys,
701
728
key_blocks=state->header.max_block_size_index;
706
733
/* open_count must be first because of _mi_mark_file_changed ! */
707
734
mi_int2store(ptr,state->open_count); ptr +=2;
708
*ptr++= (unsigned char)state->changed; *ptr++= state->sortkey;
735
*ptr++= (uchar)state->changed; *ptr++= state->sortkey;
709
736
mi_rowstore(ptr,state->state.records); ptr +=8;
710
737
mi_rowstore(ptr,state->state.del); ptr +=8;
711
738
mi_rowstore(ptr,state->split); ptr +=8;
734
761
if (pWrite & 2) /* From isamchk */
736
uint32_t key_parts= mi_uint2korr(state->header.key_parts);
763
uint key_parts= mi_uint2korr(state->header.key_parts);
737
764
mi_int4store(ptr,state->sec_index_changed); ptr +=4;
738
765
mi_int4store(ptr,state->sec_index_used); ptr +=4;
739
766
mi_int4store(ptr,state->version); ptr +=4;
759
unsigned char *mi_state_info_read(unsigned char *ptr, MI_STATE_INFO *state)
786
uchar *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state)
761
uint32_t i,keys,key_parts,key_blocks;
788
uint i,keys,key_parts,key_blocks;
762
789
memcpy(&state->header,ptr, sizeof(state->header));
763
790
ptr +=sizeof(state->header);
764
791
keys=(uint) state->header.keys;
812
uint32_t mi_state_info_read_dsk(File file, MI_STATE_INFO *state, bool pRead)
839
uint mi_state_info_read_dsk(File file, MI_STATE_INFO *state, my_bool pRead)
814
unsigned char buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
841
uchar buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
816
843
if (!myisam_single_user)
832
859
** store and read of MI_BASE_INFO
833
860
****************************************************************************/
835
uint32_t mi_base_info_write(File file, MI_BASE_INFO *base)
862
uint mi_base_info_write(File file, MI_BASE_INFO *base)
837
unsigned char buff[MI_BASE_INFO_SIZE], *ptr=buff;
864
uchar buff[MI_BASE_INFO_SIZE], *ptr=buff;
839
866
mi_sizestore(ptr,base->keystart); ptr +=8;
840
867
mi_sizestore(ptr,base->max_data_file_length); ptr +=8;
859
886
mi_int2store(ptr,base->max_key_length); ptr +=2;
860
887
mi_int2store(ptr,base->extra_alloc_bytes); ptr +=2;
861
888
*ptr++= base->extra_alloc_procent;
862
/* old raid info slots */
864
mi_int2store(ptr,UINT16_C(0)); ptr +=2;
865
mi_int4store(ptr,UINT32_C(0)); ptr +=4;
889
*ptr++= base->raid_type;
890
mi_int2store(ptr,base->raid_chunks); ptr +=2;
891
mi_int4store(ptr,base->raid_chunksize); ptr +=4;
867
892
memset(ptr, 0, 6); ptr +=6; /* extra */
868
893
return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
872
unsigned char *my_n_base_info_read(unsigned char *ptr, MI_BASE_INFO *base)
897
uchar *my_n_base_info_read(uchar *ptr, MI_BASE_INFO *base)
874
899
base->keystart = mi_sizekorr(ptr); ptr +=8;
875
900
base->max_data_file_length = mi_sizekorr(ptr); ptr +=8;
895
920
base->max_key_length = mi_uint2korr(ptr); ptr +=2;
896
921
base->extra_alloc_bytes = mi_uint2korr(ptr); ptr +=2;
897
922
base->extra_alloc_procent = *ptr++;
899
/* advance past raid_type (1) raid_chunks (2) and raid_chunksize (4) */
923
base->raid_type= *ptr++;
924
base->raid_chunks= mi_uint2korr(ptr); ptr +=2;
925
base->raid_chunksize= mi_uint4korr(ptr); ptr +=4;
926
/* TO BE REMOVED: Fix for old RAID files */
927
if (base->raid_type == 0)
930
base->raid_chunksize=0;
908
939
---------------------------------------------------------------------------*/
910
uint32_t mi_keydef_write(File file, MI_KEYDEF *keydef)
941
uint mi_keydef_write(File file, MI_KEYDEF *keydef)
912
unsigned char buff[MI_KEYDEF_SIZE];
913
unsigned char *ptr=buff;
943
uchar buff[MI_KEYDEF_SIZE];
915
*ptr++ = (unsigned char) keydef->keysegs;
946
*ptr++ = (uchar) keydef->keysegs;
916
947
*ptr++ = keydef->key_alg; /* Rtree or Btree */
917
948
mi_int2store(ptr,keydef->flag); ptr +=2;
918
949
mi_int2store(ptr,keydef->block_length); ptr +=2;
922
953
return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
925
unsigned char *mi_keydef_read(unsigned char *ptr, MI_KEYDEF *keydef)
956
uchar *mi_keydef_read(uchar *ptr, MI_KEYDEF *keydef)
927
958
keydef->keysegs = (uint) *ptr++;
928
959
keydef->key_alg = *ptr++; /* Rtree or Btree */
960
991
pos= keyseg->null_bit ? keyseg->null_pos : keyseg->bit_pos;
961
992
mi_int4store(ptr, pos);
964
995
return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
968
unsigned char *mi_keyseg_read(unsigned char *ptr, HA_KEYSEG *keyseg)
999
uchar *mi_keyseg_read(uchar *ptr, HA_KEYSEG *keyseg)
970
1001
keyseg->type = *ptr++;
971
1002
keyseg->language = *ptr++;
993
1024
---------------------------------------------------------------------------*/
995
uint32_t mi_uniquedef_write(File file, MI_UNIQUEDEF *def)
1026
uint mi_uniquedef_write(File file, MI_UNIQUEDEF *def)
997
unsigned char buff[MI_UNIQUEDEF_SIZE];
998
unsigned char *ptr=buff;
1028
uchar buff[MI_UNIQUEDEF_SIZE];
1000
1031
mi_int2store(ptr,def->keysegs); ptr+=2;
1001
*ptr++= (unsigned char) def->key;
1002
*ptr++ = (unsigned char) def->null_are_equal;
1032
*ptr++= (uchar) def->key;
1033
*ptr++ = (uchar) def->null_are_equal;
1004
1035
return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
1007
unsigned char *mi_uniquedef_read(unsigned char *ptr, MI_UNIQUEDEF *def)
1038
uchar *mi_uniquedef_read(uchar *ptr, MI_UNIQUEDEF *def)
1009
1040
def->keysegs = mi_uint2korr(ptr);
1010
1041
def->key = ptr[2];
1016
1047
** MI_COLUMNDEF
1017
1048
***************************************************************************/
1019
uint32_t mi_recinfo_write(File file, MI_COLUMNDEF *recinfo)
1050
uint mi_recinfo_write(File file, MI_COLUMNDEF *recinfo)
1021
unsigned char buff[MI_COLUMNDEF_SIZE];
1022
unsigned char *ptr=buff;
1052
uchar buff[MI_COLUMNDEF_SIZE];
1024
1055
mi_int2store(ptr,recinfo->type); ptr +=2;
1025
1056
mi_int2store(ptr,recinfo->length); ptr +=2;
1028
1059
return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
1031
unsigned char *mi_recinfo_read(unsigned char *ptr, MI_COLUMNDEF *recinfo)
1062
uchar *mi_recinfo_read(uchar *ptr, MI_COLUMNDEF *recinfo)
1033
1064
recinfo->type= mi_sint2korr(ptr); ptr +=2;
1034
1065
recinfo->length=mi_uint2korr(ptr); ptr +=2;
1049
1080
int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share,
1050
1081
File file_to_dup __attribute__((unused)))
1052
info->dfile=my_open(share->data_file_name, share->mode,
1083
info->dfile=my_open(share->data_file_name, share->mode | O_SHARE,
1054
1085
return info->dfile >= 0 ? 0 : 1;