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 */
17
17
Functions to handle space-packed-records and blobs
19
19
A row may be stored in one or more linked blocks.
20
20
The block size is between MI_MIN_BLOCK_LENGTH and MI_MAX_BLOCK_LENGTH.
21
21
Each block is aligned on MI_DYN_ALIGN_SIZE.
23
23
of blocks. For the differnet block types, look at _mi_get_block_info()
26
#include "myisam_priv.h"
29
#include <sys/types.h>
31
#ifdef HAVE_SYS_MMAN_H
34
#include <drizzled/util/test.h>
35
#include <drizzled/error.h>
40
using namespace drizzled;
26
#include "myisamdef.h"
43
28
/* Enough for comparing if number is zero */
44
29
static char zero_string[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
46
static int write_dynamic_record(MI_INFO *info,const unsigned char *record,
31
static int write_dynamic_record(MI_INFO *info,const uchar *record,
48
static int _mi_find_writepos(MI_INFO *info,ulong reclength,internal::my_off_t *filepos,
33
static int _mi_find_writepos(MI_INFO *info,ulong reclength,my_off_t *filepos,
50
static int update_dynamic_record(MI_INFO *info,internal::my_off_t filepos,unsigned char *record,
35
static int update_dynamic_record(MI_INFO *info,my_off_t filepos,uchar *record,
52
static int delete_dynamic_record(MI_INFO *info,internal::my_off_t filepos,
53
uint32_t second_read);
54
static int _mi_cmp_buffer(int file, const unsigned char *buff, internal::my_off_t filepos,
37
static int delete_dynamic_record(MI_INFO *info,my_off_t filepos,
39
static int _mi_cmp_buffer(File file, const uchar *buff, my_off_t filepos,
42
/* Play it safe; We have a small stack when using threads */
45
#define my_alloca(A) my_malloc((A),MYF(0))
46
#define my_afree(A) my_free((A),MYF(0))
57
48
/* Interface function from MI_INFO */
61
53
Create mmaped area for MyISAM handler
72
bool mi_dynmap_file(MI_INFO *info, internal::my_off_t size)
64
bool mi_dynmap_file(MI_INFO *info, my_off_t size)
74
if (size > (internal::my_off_t) (~((size_t) 0)) - MEMMAP_EXTRA_MARGIN)
66
if (size > (my_off_t) (~((size_t) 0)) - MEMMAP_EXTRA_MARGIN)
83
75
mapping. When swap space is not reserved one might get SIGSEGV
84
76
upon a write if no physical memory is available.
86
info->s->file_map= (unsigned char*)
87
mmap(NULL, (size_t)(size + MEMMAP_EXTRA_MARGIN),
88
info->s->mode==O_RDONLY ? PROT_READ :
89
PROT_READ | PROT_WRITE,
90
MAP_SHARED | MAP_NORESERVE,
92
if (info->s->file_map == (unsigned char*) MAP_FAILED)
78
info->s->file_map= (uchar*)
79
my_mmap(0, (size_t)(size + MEMMAP_EXTRA_MARGIN),
80
info->s->mode==O_RDONLY ? PROT_READ :
81
PROT_READ | PROT_WRITE,
82
MAP_SHARED | MAP_NORESERVE,
84
if (info->s->file_map == (uchar*) MAP_FAILED)
94
86
info->s->file_map= NULL;
97
/* per krow we should look at removing the following code */
98
#if !defined(TARGET_OS_SOLARIS)
89
#if defined(HAVE_MADVISE)
99
90
madvise((char*) info->s->file_map, size, MADV_RANDOM);
101
92
info->s->mmaped_length= size;
116
void mi_remap_file(MI_INFO *info, internal::my_off_t size)
107
void mi_remap_file(MI_INFO *info, my_off_t size)
118
109
if (info->s->file_map)
120
munmap((char*) info->s->file_map,
121
(size_t) info->s->mmaped_length + MEMMAP_EXTRA_MARGIN);
111
my_munmap((char*) info->s->file_map,
112
(size_t) info->s->mmaped_length + MEMMAP_EXTRA_MARGIN);
122
113
mi_dynmap_file(info, size);
133
125
Buffer Input buffer
134
126
Count Count of bytes for read
135
127
offset Start position
142
size_t mi_mmap_pread(MI_INFO *info, unsigned char *Buffer,
143
size_t Count, internal::my_off_t offset, myf MyFlags)
134
size_t mi_mmap_pread(MI_INFO *info, uchar *Buffer,
135
size_t Count, my_off_t offset, myf MyFlags)
137
if (info->s->concurrent_insert)
138
rw_rdlock(&info->s->mmap_lock);
146
141
The following test may fail in the following cases:
147
142
- We failed to remap a memory area (fragmented memory?)
152
147
if (info->s->mmaped_length >= offset + Count)
154
149
memcpy(Buffer, info->s->file_map + offset, Count);
150
if (info->s->concurrent_insert)
151
rw_unlock(&info->s->mmap_lock);
156
if (info->s->concurrent_insert)
157
rw_unlock(&info->s->mmap_lock);
159
158
return my_pread(info->dfile, Buffer, Count, offset, MyFlags);
164
163
/* wrapper for my_pread in case if mmap isn't used */
166
size_t mi_nommap_pread(MI_INFO *info, unsigned char *Buffer,
167
size_t Count, internal::my_off_t offset, myf MyFlags)
165
size_t mi_nommap_pread(MI_INFO *info, uchar *Buffer,
166
size_t Count, my_off_t offset, myf MyFlags)
169
168
return my_pread(info->dfile, Buffer, Count, offset, MyFlags);
179
178
Buffer Output buffer
180
179
Count Count of bytes for write
181
180
offset Start position
186
185
!=0 error. In this case return error from pwrite
189
size_t mi_mmap_pwrite(MI_INFO *info, const unsigned char *Buffer,
190
size_t Count, internal::my_off_t offset, myf MyFlags)
188
size_t mi_mmap_pwrite(MI_INFO *info, const uchar *Buffer,
189
size_t Count, my_off_t offset, myf MyFlags)
191
if (info->s->concurrent_insert)
192
rw_rdlock(&info->s->mmap_lock);
194
195
The following test may fail in the following cases:
200
201
if (info->s->mmaped_length >= offset + Count)
202
memcpy(info->s->file_map + offset, Buffer, Count);
203
memcpy(info->s->file_map + offset, Buffer, Count);
204
if (info->s->concurrent_insert)
205
rw_unlock(&info->s->mmap_lock);
207
210
info->s->nonmmaped_inserts++;
211
if (info->s->concurrent_insert)
212
rw_unlock(&info->s->mmap_lock);
208
213
return my_pwrite(info->dfile, Buffer, Count, offset, MyFlags);
214
219
/* wrapper for my_pwrite in case if mmap isn't used */
216
size_t mi_nommap_pwrite(MI_INFO *info, const unsigned char *Buffer,
217
size_t Count, internal::my_off_t offset, myf MyFlags)
221
size_t mi_nommap_pwrite(MI_INFO *info, const uchar *Buffer,
222
size_t Count, my_off_t offset, myf MyFlags)
219
224
return my_pwrite(info->dfile, Buffer, Count, offset, MyFlags);
223
int _mi_write_dynamic_record(MI_INFO *info, const unsigned char *record)
228
int _mi_write_dynamic_record(MI_INFO *info, const uchar *record)
225
230
ulong reclength=_mi_rec_pack(info,info->rec_buff,record);
226
231
return (write_dynamic_record(info,info->rec_buff,reclength));
229
int _mi_update_dynamic_record(MI_INFO *info, internal::my_off_t pos, const unsigned char *record)
234
int _mi_update_dynamic_record(MI_INFO *info, my_off_t pos, const uchar *record)
231
uint32_t length=_mi_rec_pack(info,info->rec_buff,record);
236
uint length=_mi_rec_pack(info,info->rec_buff,record);
232
237
return (update_dynamic_record(info,pos,info->rec_buff,length));
235
int _mi_write_blob_record(MI_INFO *info, const unsigned char *record)
240
int _mi_write_blob_record(MI_INFO *info, const uchar *record)
237
unsigned char *rec_buff;
239
244
ulong reclength,reclength2,extra;
245
250
#ifdef NOT_USED /* We now support big rows */
246
251
if (reclength > MI_DYN_MAX_ROW_LENGTH)
248
errno=HA_ERR_TO_BIG_ROW;
253
my_errno=HA_ERR_TO_BIG_ROW;
252
if (!(rec_buff=(unsigned char*) malloc(reclength)))
257
if (!(rec_buff=(uchar*) my_alloca(reclength)))
254
errno= HA_ERR_OUT_OF_MEM;
259
my_errno= HA_ERR_OUT_OF_MEM; /* purecov: inspected */
257
262
reclength2= _mi_rec_pack(info,rec_buff+ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER),
259
264
assert(reclength2 <= reclength);
260
265
error=write_dynamic_record(info,rec_buff+ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER),
267
int _mi_update_blob_record(MI_INFO *info, internal::my_off_t pos, const unsigned char *record)
272
int _mi_update_blob_record(MI_INFO *info, my_off_t pos, const uchar *record)
269
unsigned char *rec_buff;
271
276
ulong reclength,extra;
277
282
#ifdef NOT_USED /* We now support big rows */
278
283
if (reclength > MI_DYN_MAX_ROW_LENGTH)
280
errno=HA_ERR_TO_BIG_ROW;
285
my_errno=HA_ERR_TO_BIG_ROW;
284
if (!(rec_buff=(unsigned char*) malloc(reclength)))
289
if (!(rec_buff=(uchar*) my_alloca(reclength)))
286
errno= HA_ERR_OUT_OF_MEM;
291
my_errno= HA_ERR_OUT_OF_MEM; /* purecov: inspected */
289
294
reclength=_mi_rec_pack(info,rec_buff+ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER),
305
310
/* Write record to data-file */
307
static int write_dynamic_record(MI_INFO *info, const unsigned char *record,
312
static int write_dynamic_record(MI_INFO *info, const uchar *record,
312
internal::my_off_t filepos;
342
347
if (_mi_write_part_record(info,filepos,length,
343
348
(info->append_insert_at_end ?
344
349
HA_OFFSET_ERROR : info->s->state.dellink),
345
(unsigned char**) &record,&reclength,&flag))
350
(uchar**) &record,&reclength,&flag))
347
352
} while (reclength);
357
362
static int _mi_find_writepos(MI_INFO *info,
358
363
ulong reclength, /* record length */
359
internal::my_off_t *filepos, /* Return file pos */
364
my_off_t *filepos, /* Return file pos */
360
365
ulong *length) /* length of block at filepos */
362
367
MI_BLOCK_INFO block_info;
372
377
if (!(_mi_get_block_info(&block_info,info->dfile,info->s->state.dellink) &
375
errno=HA_ERR_WRONG_IN_RECORD;
380
my_errno=HA_ERR_WRONG_IN_RECORD;
378
383
info->s->state.dellink=block_info.next_filepos;
393
398
if (info->state->data_file_length >
394
399
(info->s->base.max_data_file_length - tmp))
396
errno=HA_ERR_RECORD_FILE_FULL;
401
my_errno=HA_ERR_RECORD_FILE_FULL;
399
404
if (tmp > MI_MAX_BLOCK_LENGTH)
477
482
1 error. In this case my_error is set.
480
static int update_backward_delete_link(MI_INFO *info, internal::my_off_t delete_block,
481
internal::my_off_t filepos)
485
static int update_backward_delete_link(MI_INFO *info, my_off_t delete_block,
483
488
MI_BLOCK_INFO block_info;
488
493
if (_mi_get_block_info(&block_info,info->dfile,delete_block)
491
unsigned char buff[8];
492
497
mi_sizestore(buff,filepos);
493
498
if (info->s->file_write(info,buff, 8, delete_block+12, MYF(MY_NABP)))
494
499
return(1); /* Error on write */
498
errno=HA_ERR_WRONG_IN_RECORD;
503
my_errno=HA_ERR_WRONG_IN_RECORD;
499
504
return(1); /* Wrong delete link */
505
510
/* Delete datarecord from database */
506
511
/* info->rec_cache.seek_not_done is updated in cmp_record */
508
static int delete_dynamic_record(MI_INFO *info, internal::my_off_t filepos,
509
uint32_t second_read)
513
static int delete_dynamic_record(MI_INFO *info, my_off_t filepos,
511
uint32_t length,b_type;
512
517
MI_BLOCK_INFO block_info,del_block;
514
519
bool remove_next_block;
547
552
memset(block_info.header+12, 255, 8);
549
554
mi_sizestore(block_info.header+12,block_info.next_filepos);
550
if (info->s->file_write(info,(unsigned char*) block_info.header,20,filepos,
555
if (info->s->file_write(info,(uchar*) block_info.header,20,filepos,
553
558
info->s->state.dellink = filepos;
567
572
/* Write a block to datafile */
569
574
int _mi_write_part_record(MI_INFO *info,
570
internal::my_off_t filepos, /* points at empty block */
575
my_off_t filepos, /* points at empty block */
571
576
ulong length, /* length of block */
572
internal::my_off_t next_filepos,/* Next empty block */
573
unsigned char **record, /* pointer to record ptr */
577
my_off_t next_filepos,/* Next empty block */
578
uchar **record, /* pointer to record ptr */
574
579
ulong *reclength, /* length of *record */
575
580
int *flag) /* *flag == 0 if header */
577
582
ulong head_length,res_length,extra_length,long_block,del_length;
578
unsigned char *pos,*record_end;
579
internal::my_off_t next_delete_block;
580
unsigned char temp[MI_SPLIT_LENGTH+MI_DYN_DELETE_BLOCK_HEADER];
583
uchar *pos,*record_end;
584
my_off_t next_delete_block;
585
uchar temp[MI_SPLIT_LENGTH+MI_DYN_DELETE_BLOCK_HEADER];
582
587
next_delete_block=HA_OFFSET_ERROR;
592
597
if (length == *reclength+ 3 + long_block)
594
599
/* Block is exactly of the right length */
595
temp[0]=(unsigned char) (1+ *flag)+(unsigned char) long_block; /* Flag is 0 or 6 */
600
temp[0]=(uchar) (1+ *flag)+(uchar) long_block; /* Flag is 0 or 6 */
598
603
mi_int3store(temp+1,*reclength);
619
624
mi_int4store(temp+1,*reclength);
620
625
mi_int3store(temp+5,length-head_length);
621
mi_sizestore((unsigned char*) temp+8,next_filepos);
626
mi_sizestore((uchar*) temp+8,next_filepos);
625
630
head_length=5+8+long_block*2;
626
temp[0]=5+(unsigned char) long_block;
631
temp[0]=5+(uchar) long_block;
629
634
mi_int3store(temp+1,*reclength);
630
635
mi_int3store(temp+4,length-head_length);
631
mi_sizestore((unsigned char*) temp+7,next_filepos);
636
mi_sizestore((uchar*) temp+7,next_filepos);
635
640
mi_int2store(temp+1,*reclength);
636
641
mi_int2store(temp+3,length-head_length);
637
mi_sizestore((unsigned char*) temp+5,next_filepos);
642
mi_sizestore((uchar*) temp+5,next_filepos);
643
648
head_length=3+8+long_block;
644
temp[0]=11+(unsigned char) long_block;
649
temp[0]=11+(uchar) long_block;
647
652
mi_int3store(temp+1,length-head_length);
648
mi_sizestore((unsigned char*) temp+4,next_filepos);
653
mi_sizestore((uchar*) temp+4,next_filepos);
652
657
mi_int2store(temp+1,length-head_length);
653
mi_sizestore((unsigned char*) temp+3,next_filepos);
658
mi_sizestore((uchar*) temp+3,next_filepos);
658
663
{ /* Block with empty info last */
659
664
head_length=4+long_block;
660
665
extra_length= length- *reclength-head_length;
661
temp[0]= (unsigned char) (3+ *flag)+(unsigned char) long_block; /* 3,4 or 9,10 */
666
temp[0]= (uchar) (3+ *flag)+(uchar) long_block; /* 3,4 or 9,10 */
664
669
mi_int3store(temp+1,*reclength);
665
temp[4]= (unsigned char) (extra_length);
670
temp[4]= (uchar) (extra_length);
669
674
mi_int2store(temp+1,*reclength);
670
temp[3]= (unsigned char) (extra_length);
675
temp[3]= (uchar) (extra_length);
672
677
length= *reclength+head_length; /* Write only what is needed */
675
680
/* Make a long block for one write */
676
681
record_end= *record+length-head_length;
677
682
del_length=(res_length ? MI_DYN_DELETE_BLOCK_HEADER : 0);
678
memmove(*record - head_length, temp, head_length);
683
memcpy(*record - head_length, temp, head_length);
679
684
memcpy(temp,record_end,(size_t) (extra_length+del_length));
680
685
memset(record_end, 0, extra_length);
717
722
if (info->update & HA_STATE_EXTEND_BLOCK)
719
724
info->update&= ~HA_STATE_EXTEND_BLOCK;
720
if (my_block_write(&info->rec_cache,(unsigned char*) *record-head_length,
725
if (my_block_write(&info->rec_cache,(uchar*) *record-head_length,
721
726
length+extra_length+del_length,filepos))
724
else if (my_b_write(&info->rec_cache,(unsigned char*) *record-head_length,
729
else if (my_b_write(&info->rec_cache,(uchar*) *record-head_length,
725
730
length+extra_length+del_length))
730
735
info->rec_cache.seek_not_done=1;
731
if (info->s->file_write(info,(unsigned char*) *record-head_length,length+extra_length+
736
if (info->s->file_write(info,(uchar*) *record-head_length,length+extra_length+
732
737
del_length,filepos,info->s->write_flag))
754
759
/* update record from datafile */
756
static int update_dynamic_record(MI_INFO *info, internal::my_off_t filepos, unsigned char *record,
761
static int update_dynamic_record(MI_INFO *info, my_off_t filepos, uchar *record,
762
767
MI_BLOCK_INFO block_info;
816
821
BLOCK_FATAL_ERROR))
818
823
if (!(error & BLOCK_FATAL_ERROR))
819
errno=HA_ERR_WRONG_IN_RECORD;
824
my_errno=HA_ERR_WRONG_IN_RECORD;
822
827
length=(ulong) (block_info.filepos-filepos) + block_info.block_len;
823
828
if (length < reclength)
825
uint32_t tmp=MY_ALIGN(reclength - length + 3 +
830
uint tmp=MY_ALIGN(reclength - length + 3 +
826
831
test(reclength >= 65520L),MI_DYN_ALIGN_SIZE);
827
832
/* Don't create a block bigger than MI_MAX_BLOCK_LENGTH */
828
tmp= min(length+tmp, MI_MAX_BLOCK_LENGTH)-length;
833
tmp= cmin(length+tmp, MI_MAX_BLOCK_LENGTH)-length;
829
834
/* Check if we can extend this block */
830
835
if (block_info.filepos + block_info.block_len ==
831
836
info->state->data_file_length &&
863
868
New block was too big, link overflow part back to
866
internal::my_off_t next_pos;
867
872
ulong rest_length= length-MI_MAX_BLOCK_LENGTH;
868
set_if_bigger(rest_length, (ulong)MI_MIN_BLOCK_LENGTH);
873
set_if_bigger(rest_length, MI_MIN_BLOCK_LENGTH);
869
874
next_pos= del_block.filepos+ del_block.block_len - rest_length;
871
876
if (update_backward_delete_link(info, info->s->state.dellink,
877
882
mi_int3store(del_block.header+1, rest_length);
878
883
mi_sizestore(del_block.header+4,info->s->state.dellink);
879
884
memset(del_block.header+12, 255, 8);
880
if (info->s->file_write(info,(unsigned char*) del_block.header,20, next_pos,
885
if (info->s->file_write(info,(uchar*) del_block.header,20, next_pos,
883
888
info->s->state.dellink= next_pos;
917
922
/* Pack a record. Return new reclength */
919
uint32_t _mi_rec_pack(MI_INFO *info, register unsigned char *to,
920
register const unsigned char *from)
924
uint _mi_rec_pack(MI_INFO *info, register uchar *to,
925
register const uchar *from)
922
927
uint length,new_length,flag,bit,i;
923
unsigned char *pos,*end,*startpos,*packpos;
928
uchar *pos,*end,*startpos,*packpos;
924
929
enum en_fieldtype type;
925
930
register MI_COLUMNDEF *rec;
962
967
else if (type == FIELD_SKIP_ENDSPACE ||
963
968
type == FIELD_SKIP_PRESPACE)
965
pos= (unsigned char*) from; end= (unsigned char*) from + length;
970
pos= (uchar*) from; end= (uchar*) from + length;
966
971
if (type == FIELD_SKIP_ENDSPACE)
967
972
{ /* Pack trailing spaces */
968
973
while (end > from && *(end-1) == ' ')
980
985
if (rec->length > 255 && new_length > 127)
982
to[0]= (unsigned char) ((new_length & 127) + 128);
983
to[1]= (unsigned char) (new_length >> 7);
987
to[0]= (uchar) ((new_length & 127) + 128);
988
to[1]= (uchar) (new_length >> 7);
987
*to++= (unsigned char) new_length;
992
*to++= (uchar) new_length;
988
993
memcpy(to, pos, new_length);
998
1003
else if (type == FIELD_VARCHAR)
1000
uint32_t pack_length= ha_varchar_packlength(rec->length -1);
1001
uint32_t tmp_length;
1005
uint pack_length= HA_VARCHAR_PACKLENGTH(rec->length -1);
1002
1007
if (pack_length == 1)
1004
tmp_length= (uint) *(unsigned char*) from;
1009
tmp_length= (uint) *(uchar*) from;
1045
1050
Returns 0 if record is ok.
1048
bool _mi_rec_check(MI_INFO *info,const unsigned char *record, unsigned char *rec_buff,
1053
bool _mi_rec_check(MI_INFO *info,const uchar *record, uchar *rec_buff,
1049
1054
ulong packed_length, bool with_checksum)
1051
1056
uint length,new_length,flag,bit,i;
1052
unsigned char *pos,*end,*packpos,*to;
1057
uchar *pos,*end,*packpos,*to;
1053
1058
enum en_fieldtype type;
1054
1059
register MI_COLUMNDEF *rec;
1084
1089
else if (type == FIELD_SKIP_ENDSPACE ||
1085
1090
type == FIELD_SKIP_PRESPACE)
1087
pos= (unsigned char*) record; end= (unsigned char*) record + length;
1092
pos= (uchar*) record; end= (uchar*) record + length;
1088
1093
if (type == FIELD_SKIP_ENDSPACE)
1089
1094
{ /* Pack trailing spaces */
1090
1095
while (end > record && *(end-1) == ' ')
1104
1109
if (rec->length > 255 && new_length > 127)
1106
if (to[0] != (unsigned char) ((new_length & 127) + 128) ||
1107
to[1] != (unsigned char) (new_length >> 7))
1111
/* purecov: begin inspected */
1112
if (to[0] != (uchar) ((new_length & 127) + 128) ||
1113
to[1] != (uchar) (new_length >> 7))
1111
else if (*to++ != (unsigned char) new_length)
1118
else if (*to++ != (uchar) new_length)
1113
1120
to+=new_length;
1118
1125
else if (type == FIELD_VARCHAR)
1120
uint32_t pack_length= ha_varchar_packlength(rec->length -1);
1121
uint32_t tmp_length;
1127
uint pack_length= HA_VARCHAR_PACKLENGTH(rec->length -1);
1122
1129
if (pack_length == 1)
1124
tmp_length= (uint) *(unsigned char*) record;
1131
tmp_length= (uint) *(uchar*) record;
1125
1132
to+= 1+ tmp_length;
1164
1171
/* Unpacks a record */
1165
/* Returns -1 and errno =HA_ERR_RECORD_DELETED if reclength isn't */
1172
/* Returns -1 and my_errno =HA_ERR_RECORD_DELETED if reclength isn't */
1166
1173
/* right. Returns reclength (>0) if ok */
1168
ulong _mi_rec_unpack(register MI_INFO *info, register unsigned char *to, unsigned char *from,
1175
ulong _mi_rec_unpack(register MI_INFO *info, register uchar *to, uchar *from,
1169
1176
ulong found_length)
1171
uint32_t flag,bit,length,rec_length,min_pack_length;
1178
uint flag,bit,length,rec_length,min_pack_length;
1172
1179
enum en_fieldtype type;
1173
unsigned char *from_end,*to_end,*packpos;
1180
uchar *from_end,*to_end,*packpos;
1174
1181
register MI_COLUMNDEF *rec,*end_field;
1176
1183
to_end=to + info->s->base.reclength;
1177
1184
from_end=from+found_length;
1178
flag= (unsigned char) *from; bit=1; packpos=from;
1185
flag= (uchar) *from; bit=1; packpos=from;
1179
1186
if (found_length < info->s->base.min_pack_length)
1181
1188
from+= info->s->base.pack_bits;
1191
1198
if (type == FIELD_VARCHAR)
1193
uint32_t pack_length= ha_varchar_packlength(rec_length-1);
1200
uint pack_length= HA_VARCHAR_PACKLENGTH(rec_length-1);
1194
1201
if (pack_length == 1)
1196
length= (uint) *(unsigned char*) from;
1203
length= (uint) *(uchar*) from;
1197
1204
if (length > rec_length-1)
1224
1231
if (from + 1 >= from_end)
1226
length= (*from & 127)+ ((uint) (unsigned char) *(from+1) << 7); from+=2;
1233
length= (*from & 127)+ ((uint) (uchar) *(from+1) << 7); from+=2;
1230
1237
if (from == from_end)
1232
length= (unsigned char) *from++;
1239
length= (uchar) *from++;
1234
1241
min_pack_length--;
1235
1242
if (length >= rec_length ||
1251
1258
else if (type == FIELD_BLOB)
1253
uint32_t size_length=rec_length- portable_sizeof_char_ptr;
1260
uint size_length=rec_length- portable_sizeof_char_ptr;
1254
1261
ulong blob_length=_mi_calc_blob_length(size_length,from);
1255
1262
ulong from_left= (ulong) (from_end - from);
1256
1263
if (from_left < size_length ||
1291
1298
return(found_length);
1294
errno= HA_ERR_WRONG_IN_RECORD;
1301
my_errno= HA_ERR_WRONG_IN_RECORD;
1295
1302
return(MY_FILE_ERROR);
1296
1303
} /* _mi_rec_unpack */
1299
1306
/* Calc length of blob. Update info in blobs->length */
1301
ulong _my_calc_total_blob_length(MI_INFO *info, const unsigned char *record)
1308
ulong _my_calc_total_blob_length(MI_INFO *info, const uchar *record)
1304
1311
MI_BLOB *blob,*end;
1317
ulong _mi_calc_blob_length(uint32_t length, const unsigned char *pos)
1324
ulong _mi_calc_blob_length(uint length, const uchar *pos)
1319
1326
switch (length) {
1321
return (uint) (unsigned char) *pos;
1328
return (uint) (uchar) *pos;
1323
1330
return (uint) uint2korr(pos);
1335
void _my_store_blob_length(unsigned char *pos,uint32_t pack_length,uint32_t length)
1342
void _my_store_blob_length(uchar *pos,uint pack_length,uint length)
1337
1344
switch (pack_length) {
1339
*pos= (unsigned char) length;
1346
*pos= (uchar) length;
1342
1349
int2store(pos,length);
1388
int _mi_read_dynamic_record(MI_INFO *info, internal::my_off_t filepos, unsigned char *buf)
1395
int _mi_read_dynamic_record(MI_INFO *info, my_off_t filepos, uchar *buf)
1390
1397
int block_of_record;
1391
uint32_t b_type, left_length= 0;
1392
unsigned char *to= NULL;
1398
uint b_type, left_length= 0;
1393
1400
MI_BLOCK_INFO block_info;
1396
1403
if (filepos != HA_OFFSET_ERROR)
1434
1441
goto panic; /* Wrong linked record */
1435
1442
/* copy information that is already read */
1437
uint32_t offset= (uint) (block_info.filepos - filepos);
1438
uint32_t prefetch_len= (sizeof(block_info.header) - offset);
1444
uint offset= (uint) (block_info.filepos - filepos);
1445
uint prefetch_len= (sizeof(block_info.header) - offset);
1439
1446
filepos+= sizeof(block_info.header);
1441
1448
if (prefetch_len > block_info.data_len)
1460
1467
there is no equivalent without seeking. We are at the right
1461
1468
position already. :(
1463
if (info->s->file_read(info, (unsigned char*) to, block_info.data_len,
1470
if (info->s->file_read(info, (uchar*) to, block_info.data_len,
1464
1471
filepos, MYF(MY_NABP)))
1466
1473
left_length-=block_info.data_len;
1487
1494
/* compare unique constraint between stored rows */
1489
1496
int _mi_cmp_dynamic_unique(MI_INFO *info, MI_UNIQUEDEF *def,
1490
const unsigned char *record, internal::my_off_t pos)
1497
const uchar *record, my_off_t pos)
1492
unsigned char *rec_buff,*old_record;
1499
uchar *rec_buff,*old_record;
1495
if (!(old_record=(unsigned char *)malloc(info->s->base.reclength)))
1502
if (!(old_record=my_alloca(info->s->base.reclength)))
1498
1505
/* Don't let the compare destroy blobs that may be in use */
1504
1511
error=mi_unique_comp(def, record, old_record, def->null_are_equal);
1505
1512
if (info->s->base.blobs)
1507
void * rec_buff_ptr= mi_get_rec_buff_ptr(info, info->rec_buff);
1508
if (rec_buff_ptr != NULL)
1514
my_free(mi_get_rec_buff_ptr(info, info->rec_buff), MYF(MY_ALLOW_ZERO_PTR));
1510
1515
info->rec_buff=rec_buff;
1517
my_afree(old_record);
1517
1522
/* Compare of record one disk with packed record in memory */
1519
int _mi_cmp_dynamic_record(register MI_INFO *info, register const unsigned char *record)
1524
int _mi_cmp_dynamic_record(register MI_INFO *info, register const uchar *record)
1521
uint32_t flag,reclength,b_type;
1522
internal::my_off_t filepos;
1523
unsigned char *buffer;
1526
uint flag,reclength,b_type;
1524
1529
MI_BLOCK_INFO block_info;
1526
1531
if (info->opt_flag & WRITE_CACHE_USED)
1565
1570
if (reclength != block_info.rec_len)
1567
errno=HA_ERR_RECORD_CHANGED;
1572
my_errno=HA_ERR_RECORD_CHANGED;
1570
1575
} else if (reclength < block_info.data_len)
1572
errno=HA_ERR_WRONG_IN_RECORD;
1577
my_errno=HA_ERR_WRONG_IN_RECORD;
1575
1580
reclength-=block_info.data_len;
1576
1581
if (_mi_cmp_buffer(info->dfile,record,block_info.filepos,
1577
1582
block_info.data_len))
1579
errno=HA_ERR_RECORD_CHANGED;
1584
my_errno=HA_ERR_RECORD_CHANGED;
1583
1588
record+=block_info.data_len;
1588
1593
if (buffer != info->rec_buff)
1589
free((unsigned char*) buffer);
1594
my_afree((uchar*) buffer);
1594
1599
/* Compare file to buffert */
1596
static int _mi_cmp_buffer(int file, const unsigned char *buff, internal::my_off_t filepos,
1601
static int _mi_cmp_buffer(File file, const uchar *buff, my_off_t filepos,
1599
uint32_t next_length;
1600
unsigned char temp_buff[IO_SIZE*2];
1605
uchar temp_buff[IO_SIZE*2];
1602
1607
next_length= IO_SIZE*2 - (uint) (filepos & (IO_SIZE-1));
1656
int _mi_read_rnd_dynamic_record(MI_INFO *info, unsigned char *buf,
1657
register internal::my_off_t filepos,
1661
int _mi_read_rnd_dynamic_record(MI_INFO *info, uchar *buf,
1662
register my_off_t filepos,
1658
1663
bool skip_deleted_blocks)
1660
1665
int block_of_record, info_read, save_errno;
1661
uint32_t left_len,b_type;
1662
unsigned char *to= NULL;
1666
uint left_len,b_type;
1663
1668
MI_BLOCK_INFO block_info;
1664
1669
MYISAM_SHARE *share=info->s;
1689
1694
if (filepos >= info->state->data_file_length)
1691
errno= HA_ERR_END_OF_FILE;
1696
my_errno= HA_ERR_END_OF_FILE;
1695
1700
if (info->opt_flag & READ_CACHE_USED)
1697
if (_mi_read_cache(&info->rec_cache,(unsigned char*) block_info.header,filepos,
1702
if (_mi_read_cache(&info->rec_cache,(uchar*) block_info.header,filepos,
1698
1703
sizeof(block_info.header),
1699
1704
(!block_of_record && skip_deleted_blocks ?
1700
1705
READING_NEXT : 0) | READING_HEADER))
1706
1711
if (info->opt_flag & WRITE_CACHE_USED &&
1707
1712
info->rec_cache.pos_in_file < filepos + MI_BLOCK_INFO_HEADER_LENGTH &&
1708
1713
flush_io_cache(&info->rec_cache))
1710
1715
info->rec_cache.seek_not_done=1;
1711
1716
b_type=_mi_get_block_info(&block_info,info->dfile,filepos);
1724
1729
if (b_type & (BLOCK_DELETED | BLOCK_SYNC_ERROR))
1726
errno=HA_ERR_RECORD_DELETED;
1731
my_errno=HA_ERR_RECORD_DELETED;
1727
1732
info->lastpos=block_info.filepos;
1728
1733
info->nextpos=block_info.filepos+block_info.block_len;
1750
1755
/* copy information that is already read */
1752
uint32_t offset=(uint) (block_info.filepos - filepos);
1753
uint32_t tmp_length= (sizeof(block_info.header) - offset);
1757
uint offset=(uint) (block_info.filepos - filepos);
1758
uint tmp_length= (sizeof(block_info.header) - offset);
1754
1759
filepos=block_info.filepos;
1756
1761
if (tmp_length > block_info.data_len)
1770
1775
if (info->opt_flag & READ_CACHE_USED)
1772
if (_mi_read_cache(&info->rec_cache,(unsigned char*) to,filepos,
1777
if (_mi_read_cache(&info->rec_cache,(uchar*) to,filepos,
1773
1778
block_info.data_len,
1774
1779
(!block_of_record && skip_deleted_blocks) ?
1775
1780
READING_NEXT : 0))
1782
1787
block_info.filepos + block_info.data_len &&
1783
1788
flush_io_cache(&info->rec_cache))
1785
/* lseek(info->dfile,filepos,SEEK_SET); */
1786
if (internal::my_read(info->dfile,(unsigned char*) to,block_info.data_len,MYF(MY_NABP)))
1790
/* my_seek(info->dfile,filepos,MY_SEEK_SET,MYF(0)); */
1791
if (my_read(info->dfile,(uchar*) to,block_info.data_len,MYF(MY_NABP)))
1789
errno= HA_ERR_WRONG_IN_RECORD; /* Unexpected end of file */
1794
my_errno= HA_ERR_WRONG_IN_RECORD; /* Unexpected end of file */
1810
1815
if (_mi_rec_unpack(info,buf,info->rec_buff,block_info.rec_len) !=
1813
return(errno); /* Wrong record */
1818
return(my_errno); /* Wrong record */
1816
errno=HA_ERR_WRONG_IN_RECORD; /* Something is fatal wrong */
1821
my_errno=HA_ERR_WRONG_IN_RECORD; /* Something is fatal wrong */
1823
save_errno=my_errno;
1819
1824
_mi_writeinfo(info,0);
1820
return(errno=save_errno);
1825
return(my_errno=save_errno);
1824
1829
/* Read and process header from a dynamic-record-file */
1826
uint32_t _mi_get_block_info(MI_BLOCK_INFO *info, int file, internal::my_off_t filepos)
1831
uint _mi_get_block_info(MI_BLOCK_INFO *info, File file, my_off_t filepos)
1828
uint32_t return_val=0;
1829
unsigned char *header=info->header;
1834
uchar *header=info->header;
1835
1840
pointer set to the end of the header after this function.
1836
1841
my_pread() may leave the file pointer untouched.
1838
lseek(file,filepos,SEEK_SET);
1839
if (internal::my_read(file, header, sizeof(info->header),MYF(0)) !=
1843
my_seek(file,filepos,MY_SEEK_SET,MYF(0));
1844
if (my_read(file, header, sizeof(info->header),MYF(0)) !=
1840
1845
sizeof(info->header))