12
12
You should have received a copy of the GNU General Public License
13
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
16
/* open a isam-database */
20
20
#include <string.h>
21
21
#include <algorithm>
23
#include <boost/scoped_ptr.hpp>
24
#include <boost/scoped_array.hpp>
26
#include "drizzled/charset_info.h"
27
#include "drizzled/internal/m_string.h"
23
#include "mystrings/m_ctype.h"
24
#include "mystrings/m_string.h"
28
25
#include "drizzled/util/test.h"
29
#include "drizzled/global_charset_info.h"
30
#include "drizzled/charset.h"
31
26
#include "drizzled/memory/multi_malloc.h"
34
29
using namespace std;
35
using namespace drizzled;
37
31
static void setup_key_functions(MI_KEYDEF *keyinfo);
38
32
static unsigned char *mi_keydef_read(unsigned char *ptr, MI_KEYDEF *keydef);
79
73
have an open count of 0.
80
74
******************************************************************************/
82
MI_INFO *mi_open(const drizzled::TableIdentifier &identifier, int mode, uint32_t open_flags)
76
MI_INFO *mi_open(const char *name, int mode, uint32_t open_flags)
84
78
int lock_error,kfile,open_mode,save_errno,have_rtree=0;
85
79
uint32_t i,j,len,errpos,head_length,base_pos,offset,info_length,keys,
89
83
unsigned char *disk_cache= NULL;
90
84
unsigned char *disk_pos, *end_pos;
91
85
MI_INFO info,*m_info,*old_info;
92
boost::scoped_ptr<MYISAM_SHARE> share_buff_ap(new MYISAM_SHARE);
93
MYISAM_SHARE &share_buff= *share_buff_ap.get();
95
boost::scoped_array<ulong> rec_per_key_part_ap(new ulong[HA_MAX_POSSIBLE_KEY*MI_MAX_KEY_SEG]);
96
ulong *rec_per_key_part= rec_per_key_part_ap.get();
97
internal::my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
86
MYISAM_SHARE share_buff,*share;
87
ulong rec_per_key_part[HA_MAX_POSSIBLE_KEY*MI_MAX_KEY_SEG];
88
my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
98
89
uint64_t max_key_file_length, max_data_file_length;
103
94
head_length=sizeof(share_buff.state.header);
104
95
memset(&info, 0, sizeof(info));
106
(void)internal::fn_format(org_name,
107
identifier.getPath().c_str(),
97
(void)fn_format(org_name,name,"",MI_NAME_IEXT, MY_UNPACK_FILENAME);
111
98
if (!realpath(org_name,rp_buff))
112
internal::my_load_path(rp_buff,org_name, NULL);
99
my_load_path(rp_buff,org_name, NULL);
113
100
rp_buff[FN_REFLEN-1]= '\0';
114
101
strcpy(name_buff,rp_buff);
115
THR_LOCK_myisam.lock();
102
pthread_mutex_lock(&THR_LOCK_myisam);
116
103
if (!(old_info=test_if_reopen(name_buff)))
118
105
share= &share_buff;
120
107
share_buff.state.rec_per_key_part=rec_per_key_part;
121
108
share_buff.state.key_root=key_root;
122
109
share_buff.state.key_del=key_del;
123
share_buff.setKeyCache();
110
share_buff.key_cache= dflt_key_cache;
125
if ((kfile=internal::my_open(name_buff,(open_mode=O_RDWR),MYF(0))) < 0)
112
if ((kfile=my_open(name_buff,(open_mode=O_RDWR),MYF(0))) < 0)
127
114
if ((errno != EROFS && errno != EACCES) ||
128
115
mode != O_RDONLY ||
129
(kfile=internal::my_open(name_buff,(open_mode=O_RDONLY),MYF(0))) < 0)
116
(kfile=my_open(name_buff,(open_mode=O_RDONLY),MYF(0))) < 0)
132
119
share->mode=open_mode;
134
if (internal::my_read(kfile, share->state.header.file_version, head_length,
121
if (my_read(kfile, share->state.header.file_version, head_length,
137
errno= HA_ERR_NOT_A_TABLE;
124
my_errno= HA_ERR_NOT_A_TABLE;
140
127
if (memcmp(share->state.header.file_version, myisam_file_magic, 4))
142
errno=HA_ERR_NOT_A_TABLE;
129
my_errno=HA_ERR_NOT_A_TABLE;
145
132
share->options= mi_uint2korr(share->state.header.options);
146
static const uint64_t OLD_FILE_OPTIONS= HA_OPTION_PACK_RECORD |
147
HA_OPTION_PACK_KEYS |
148
HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA |
149
HA_OPTION_TEMP_COMPRESS_RECORD |
151
if (share->options & ~OLD_FILE_OPTIONS)
134
~(HA_OPTION_PACK_RECORD | HA_OPTION_PACK_KEYS |
135
HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA |
136
HA_OPTION_TEMP_COMPRESS_RECORD |
153
errno=HA_ERR_OLD_FILE;
140
my_errno=HA_ERR_OLD_FILE;
161
148
if (!strcmp(name_buff, org_name) || sym_link_size == -1)
162
149
(void) strcpy(index_name, org_name);
163
150
*strrchr(org_name, '.')= '\0';
164
(void) internal::fn_format(data_name,org_name,"",MI_NAME_DEXT,
151
(void) fn_format(data_name,org_name,"",MI_NAME_DEXT,
165
152
MY_APPEND_EXT|MY_UNPACK_FILENAME|MY_RESOLVE_SYMLINKS);
167
154
info_length=mi_uint2korr(share->state.header.header_length);
168
155
base_pos=mi_uint2korr(share->state.header.base_pos);
169
156
if (!(disk_cache= (unsigned char*) malloc(info_length+128)))
174
161
end_pos=disk_cache+info_length;
177
164
lseek(kfile,0,SEEK_SET);
179
if (internal::my_read(kfile,disk_cache,info_length,MYF(MY_NABP)))
166
if (my_read(kfile,disk_cache,info_length,MYF(MY_NABP)))
181
errno=HA_ERR_CRASHED;
168
my_errno=HA_ERR_CRASHED;
184
171
len=mi_uint2korr(share->state.header.state_info_length);
194
181
disk_pos= my_n_base_info_read(disk_cache + base_pos, &share->base);
195
182
share->state.state_length=base_pos;
197
if (share->state.changed & STATE_CRASHED)
184
if (!(open_flags & HA_OPEN_FOR_REPAIR) &&
185
((share->state.changed & STATE_CRASHED) ||
186
((open_flags & HA_OPEN_ABORT_IF_CRASHED) &&
187
(share->state.open_count))))
199
errno=((share->state.changed & STATE_CRASHED_ON_REPAIR) ?
189
my_errno=((share->state.changed & STATE_CRASHED_ON_REPAIR) ?
200
190
HA_ERR_CRASHED_ON_REPAIR : HA_ERR_CRASHED_ON_USAGE);
204
194
/* sanity check */
205
195
if (share->base.keystart > 65535 || share->base.rec_reflength > 8)
207
errno=HA_ERR_CRASHED;
197
my_errno=HA_ERR_CRASHED;
211
201
if (share->base.max_key_length > MI_MAX_KEY_BUFF || keys > MI_MAX_KEY ||
212
202
key_parts > MI_MAX_KEY * MI_MAX_KEY_SEG)
214
errno=HA_ERR_UNSUPPORTED;
204
my_errno=HA_ERR_UNSUPPORTED;
231
221
if (share->base.raid_type)
233
errno=HA_ERR_UNSUPPORTED;
223
my_errno=HA_ERR_UNSUPPORTED;
236
share->base.max_data_file_length=(internal::my_off_t) max_data_file_length;
237
share->base.max_key_file_length=(internal::my_off_t) max_key_file_length;
226
share->base.max_data_file_length=(my_off_t) max_data_file_length;
227
share->base.max_key_file_length=(my_off_t) max_key_file_length;
239
229
if (share->options & HA_OPTION_COMPRESS_RECORD)
240
230
share->base.max_key_length+=2; /* For safety */
257
247
&share->state.key_root,keys*sizeof(uint64_t),
258
248
&share->state.key_del,
259
249
(share->state.header.max_block_size_index*sizeof(uint64_t)),
250
&share->key_root_lock,sizeof(pthread_rwlock_t)*keys,
251
&share->mmap_lock,sizeof(pthread_rwlock_t),
264
256
memcpy(share->state.rec_per_key_part, rec_per_key_part,
265
257
sizeof(long)*key_parts);
266
258
memcpy(share->state.key_root, key_root,
267
sizeof(internal::my_off_t)*keys);
259
sizeof(my_off_t)*keys);
268
260
memcpy(share->state.key_del, key_del,
269
sizeof(internal::my_off_t) * share->state.header.max_block_size_index);
261
sizeof(my_off_t) * share->state.header.max_block_size_index);
270
262
strcpy(share->unique_file_name, name_buff);
271
263
share->unique_name_length= strlen(name_buff);
272
264
strcpy(share->index_file_name, index_name);
397
389
disk_cache= NULL;
398
390
mi_setup_functions(share);
399
391
share->is_log_table= false;
400
if (myisam_concurrent_insert)
392
thr_lock_init(&share->lock);
393
pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST);
394
for (i=0; i<keys; i++)
395
pthread_rwlock_init(&share->key_root_lock[i], NULL);
396
pthread_rwlock_init(&share->mmap_lock, NULL);
397
if (!thr_lock_inited)
399
/* Probably a single threaded program; Don't use concurrent inserts */
400
myisam_concurrent_insert=0;
402
else if (myisam_concurrent_insert)
402
404
share->concurrent_insert=
403
405
((share->options & (HA_OPTION_READ_ONLY_DATA | HA_OPTION_TMP_TABLE |
406
408
(open_flags & HA_OPEN_TMP_TABLE) || have_rtree) ? 0 : 1;
407
409
if (share->concurrent_insert)
411
share->lock.get_status= mi_get_status;
412
share->lock.copy_status= mi_copy_status;
413
share->lock.update_status= mi_update_status;
414
share->lock.restore_status= mi_restore_status;
415
share->lock.check_status= mi_check_status;
415
421
share= old_info->s;
416
422
if (mode == O_RDWR && share->mode == O_RDONLY)
418
errno=EACCES; /* Can't open in write mode */
424
my_errno=EACCES; /* Can't open in write mode */
421
427
if (mi_open_datafile(&info, share, old_info->dfile))
432
438
share->base.max_key_length),
433
439
&info.lastkey,share->base.max_key_length*3+1,
434
440
&info.first_mbr_key, share->base.max_key_length,
435
&info.filename, identifier.getPath().length()+1,
441
&info.filename,strlen(name)+1,
436
442
&info.rtree_recursion_state,have_rtree ? 1024 : 0,
442
448
info.rtree_recursion_state= NULL;
444
strcpy(info.filename, identifier.getPath().c_str());
450
strcpy(info.filename,name);
445
451
memcpy(info.blobs,share->blobs,sizeof(MI_BLOB)*share->base.blobs);
446
452
info.lastkey2=info.lastkey+share->base.max_key_length;
492
499
share->delay_key_write= 1;
493
500
info.state= &share->state.state; /* Change global values by default */
501
pthread_mutex_unlock(&share->intern_lock);
495
503
/* Allocate buffer for one record */
497
505
/* prerequisites: memset(info, 0) && info->s=share; are met. */
498
if (!mi_alloc_rec_buff(&info, SIZE_MAX, &info.rec_buff))
506
if (!mi_alloc_rec_buff(&info, -1, &info.rec_buff))
500
508
memset(info.rec_buff, 0, mi_get_rec_buff_len(&info, info.rec_buff));
511
thr_lock_data_init(&share->lock,&m_info->lock,(void*) m_info);
503
512
myisam_open_list.push_front(m_info);
505
THR_LOCK_myisam.unlock();
514
pthread_mutex_unlock(&THR_LOCK_myisam);
509
518
if (disk_cache != NULL)
510
519
free(disk_cache);
511
save_errno=errno ? errno : HA_ERR_END_OF_FILE;
520
save_errno=my_errno ? my_errno : HA_ERR_END_OF_FILE;
512
521
if ((save_errno == HA_ERR_CRASHED) ||
513
522
(save_errno == HA_ERR_CRASHED_ON_USAGE) ||
514
523
(save_errno == HA_ERR_CRASHED_ON_REPAIR))
515
mi_report_error(save_errno, identifier.getPath().c_str());
524
mi_report_error(save_errno, name);
516
525
switch (errpos) {
518
527
free((unsigned char*) m_info);
519
528
/* fall through */
521
internal::my_close(info.dfile,MYF(0));
530
my_close(info.dfile,MYF(0));
523
532
break; /* Don't remove open table */
524
533
/* fall through */
550
559
unsigned char *newptr = *buf;
552
561
/* to simplify initial init of info->rec_buf in mi_open and mi_extra */
553
if (length == SIZE_MAX)
562
if (length == (ulong) -1)
555
564
if (info->s->options & HA_OPTION_COMPRESS_RECORD)
556
565
length= max(info->s->base.pack_reclength, info->s->max_pack_length);
581
590
static uint64_t mi_safe_mul(uint64_t a, uint64_t b)
583
uint64_t max_val= ~ (uint64_t) 0; /* internal::my_off_t is unsigned */
592
uint64_t max_val= ~ (uint64_t) 0; /* my_off_t is unsigned */
585
594
if (!a || max_val / a < b)
687
696
Function to save and store the header in the index file (.MYI)
690
uint32_t mi_state_info_write(int file, MI_STATE_INFO *state, uint32_t pWrite)
699
uint32_t mi_state_info_write(File file, MI_STATE_INFO *state, uint32_t pWrite)
692
701
unsigned char buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
693
702
unsigned char *ptr=buff;
746
755
return(my_pwrite(file, buff, (size_t) (ptr-buff), 0L,
747
756
MYF(MY_NABP | MY_THREADSAFE)) != 0);
748
return(internal::my_write(file, buff, (size_t) (ptr-buff),
757
return(my_write(file, buff, (size_t) (ptr-buff),
749
758
MYF(MY_NABP)) != 0);
771
780
state->state.empty = mi_sizekorr(ptr); ptr +=8;
772
781
state->state.key_empty= mi_sizekorr(ptr); ptr +=8;
773
782
state->auto_increment=mi_uint8korr(ptr); ptr +=8;
774
state->state.checksum=(internal::ha_checksum) mi_uint8korr(ptr); ptr +=8;
783
state->state.checksum=(ha_checksum) mi_uint8korr(ptr); ptr +=8;
775
784
state->process= mi_uint4korr(ptr); ptr +=4;
776
785
state->unique = mi_uint4korr(ptr); ptr +=4;
777
786
state->status = mi_uint4korr(ptr); ptr +=4;
806
uint32_t mi_state_info_read_dsk(int file, MI_STATE_INFO *state, bool pRead)
815
uint32_t mi_state_info_read_dsk(File file, MI_STATE_INFO *state, bool pRead)
808
817
unsigned char buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
812
821
if (my_pread(file, buff, state->state_length,0L, MYF(MY_NABP)))
815
else if (internal::my_read(file, buff, state->state_length,MYF(MY_NABP)))
824
else if (my_read(file, buff, state->state_length,MYF(MY_NABP)))
817
826
mi_state_info_read(buff, state);
824
833
** store and read of MI_BASE_INFO
825
834
****************************************************************************/
827
uint32_t mi_base_info_write(int file, MI_BASE_INFO *base)
836
uint32_t mi_base_info_write(File file, MI_BASE_INFO *base)
829
838
unsigned char buff[MI_BASE_INFO_SIZE], *ptr=buff;
857
866
mi_int4store(ptr,UINT32_C(0)); ptr +=4;
859
868
memset(ptr, 0, 6); ptr +=6; /* extra */
860
return internal::my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
869
return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
900
909
---------------------------------------------------------------------------*/
902
uint32_t mi_keydef_write(int file, MI_KEYDEF *keydef)
911
uint32_t mi_keydef_write(File file, MI_KEYDEF *keydef)
904
913
unsigned char buff[MI_KEYDEF_SIZE];
905
914
unsigned char *ptr=buff;
911
920
mi_int2store(ptr,keydef->keylength); ptr +=2;
912
921
mi_int2store(ptr,keydef->minlength); ptr +=2;
913
922
mi_int2store(ptr,keydef->maxlength); ptr +=2;
914
return internal::my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
923
return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
917
926
static unsigned char *mi_keydef_read(unsigned char *ptr, MI_KEYDEF *keydef)
935
944
***************************************************************************/
937
int mi_keyseg_write(int file, const HA_KEYSEG *keyseg)
946
int mi_keyseg_write(File file, const HA_KEYSEG *keyseg)
939
948
unsigned char buff[HA_KEYSEG_SIZE];
940
949
unsigned char *ptr=buff;
953
962
mi_int4store(ptr, pos);
956
return internal::my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
965
return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
985
994
---------------------------------------------------------------------------*/
987
uint32_t mi_uniquedef_write(int file, MI_UNIQUEDEF *def)
996
uint32_t mi_uniquedef_write(File file, MI_UNIQUEDEF *def)
989
998
unsigned char buff[MI_UNIQUEDEF_SIZE];
990
999
unsigned char *ptr=buff;
993
1002
*ptr++= (unsigned char) def->key;
994
1003
*ptr++ = (unsigned char) def->null_are_equal;
996
return internal::my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
1005
return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
999
1008
static unsigned char *mi_uniquedef_read(unsigned char *ptr, MI_UNIQUEDEF *def)
1008
1017
** MI_COLUMNDEF
1009
1018
***************************************************************************/
1011
uint32_t mi_recinfo_write(int file, MI_COLUMNDEF *recinfo)
1020
uint32_t mi_recinfo_write(File file, MI_COLUMNDEF *recinfo)
1013
1022
unsigned char buff[MI_COLUMNDEF_SIZE];
1014
1023
unsigned char *ptr=buff;
1017
1026
mi_int2store(ptr,recinfo->length); ptr +=2;
1018
1027
*ptr++ = recinfo->null_bit;
1019
1028
mi_int2store(ptr,recinfo->null_pos); ptr+= 2;
1020
return internal::my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
1029
return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
1023
1032
static unsigned char *mi_recinfo_read(unsigned char *ptr, MI_COLUMNDEF *recinfo)
1038
1047
exist a dup()-like call that would give us two different file descriptors.
1039
1048
*************************************************************************/
1041
int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, int file_to_dup)
1050
int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, File file_to_dup)
1043
1052
(void)file_to_dup;
1044
info->dfile=internal::my_open(share->data_file_name, share->mode,
1053
info->dfile=my_open(share->data_file_name, share->mode,
1046
1055
return info->dfile >= 0 ? 0 : 1;
1050
1059
int mi_open_keyfile(MYISAM_SHARE *share)
1052
if ((share->kfile=internal::my_open(share->unique_file_name, share->mode,
1061
if ((share->kfile=my_open(share->unique_file_name, share->mode,
1053
1062
MYF(MY_WME))) < 0)