26 #include "myisamdef.h"
29 static char zero_string[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
31 static int write_dynamic_record(
MI_INFO *info,
const uchar *
record,
33 static int _mi_find_writepos(
MI_INFO *info,ulong reclength,my_off_t *filepos,
35 static int update_dynamic_record(
MI_INFO *info,my_off_t filepos,uchar *
record,
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,
45 #define my_alloca(A) my_malloc((A),MYF(0))
46 #define my_afree(A) my_free((A))
64 my_bool mi_dynmap_file(
MI_INFO *info, my_off_t
size)
66 DBUG_ENTER(
"mi_dynmap_file");
67 if (size == 0 || size > (my_off_t) (~((
size_t) 0)))
70 DBUG_PRINT(
"warning", (
"File is too large for mmap"));
72 DBUG_PRINT(
"warning", (
"Do not mmap zero-length"));
83 info->s->file_map= (uchar*)
84 my_mmap(0, (
size_t)
size,
85 info->s->mode==O_RDONLY ? PROT_READ :
86 PROT_READ | PROT_WRITE,
87 MAP_SHARED | MAP_NORESERVE,
89 if (info->s->file_map == (uchar*) MAP_FAILED)
91 info->s->file_map= NULL;
94 #if defined(HAVE_MADVISE)
95 madvise((
char*) info->s->file_map, size, MADV_RANDOM);
97 info->s->mmaped_length=
size;
98 info->s->file_read= mi_mmap_pread;
99 info->s->file_write= mi_mmap_pwrite;
116 int mi_munmap_file(
MI_INFO *info)
119 DBUG_ENTER(
"mi_unmap_file");
120 if ((ret= my_munmap((
void*) info->s->file_map, info->s->mmaped_length)))
122 info->s->file_read= mi_nommap_pread;
123 info->s->file_write= mi_nommap_pwrite;
124 info->s->file_map= 0;
125 info->s->mmaped_length= 0;
140 void mi_remap_file(
MI_INFO *info, my_off_t size)
142 if (info->s->file_map)
144 mi_munmap_file(info);
145 mi_dynmap_file(info, size);
167 size_t Count, my_off_t
offset, myf MyFlags)
169 DBUG_PRINT(
"info", (
"mi_read with mmap %d\n", info->dfile));
170 if (info->s->concurrent_insert)
180 if (info->s->mmaped_length >= offset + Count)
182 memcpy(Buffer, info->s->file_map + offset, Count);
183 if (info->s->concurrent_insert)
189 if (info->s->concurrent_insert)
198 size_t mi_nommap_pread(
MI_INFO *info, uchar *Buffer,
199 size_t Count, my_off_t offset, myf MyFlags)
221 size_t mi_mmap_pwrite(
MI_INFO *info,
const uchar *Buffer,
222 size_t Count, my_off_t offset, myf MyFlags)
224 DBUG_PRINT(
"info", (
"mi_write with mmap %d\n", info->dfile));
225 if (info->s->concurrent_insert)
235 if (info->s->mmaped_length >= offset + Count)
237 memcpy(info->s->file_map + offset, Buffer, Count);
238 if (info->s->concurrent_insert)
244 info->s->nonmmaped_inserts++;
245 if (info->s->concurrent_insert)
255 size_t mi_nommap_pwrite(
MI_INFO *info,
const uchar *Buffer,
256 size_t Count, my_off_t offset, myf MyFlags)
262 int _mi_write_dynamic_record(
MI_INFO *info,
const uchar *
record)
264 ulong reclength=_mi_rec_pack(info,info->rec_buff,record);
265 return (write_dynamic_record(info,info->rec_buff,reclength));
268 int _mi_update_dynamic_record(
MI_INFO *info, my_off_t pos,
const uchar *record)
270 uint length=_mi_rec_pack(info,info->rec_buff,record);
271 return (update_dynamic_record(info,pos,info->rec_buff,length));
274 int _mi_write_blob_record(
MI_INFO *info,
const uchar *record)
278 ulong reclength,reclength2,
extra;
280 extra= (ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER)+MI_SPLIT_LENGTH+
281 MI_DYN_DELETE_BLOCK_HEADER+1);
282 reclength= (info->s->base.pack_reclength +
283 _my_calc_total_blob_length(info,record)+ extra);
284 if (!(rec_buff=(uchar*) my_alloca(reclength)))
286 my_errno= HA_ERR_OUT_OF_MEM;
289 reclength2= _mi_rec_pack(info,rec_buff+ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER),
291 DBUG_PRINT(
"info",(
"reclength: %lu reclength2: %lu",
292 reclength, reclength2));
293 DBUG_ASSERT(reclength2 <= reclength);
294 error=write_dynamic_record(info,rec_buff+ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER),
301 int _mi_update_blob_record(
MI_INFO *info, my_off_t pos,
const uchar *record)
305 ulong reclength,extra;
307 extra= (ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER)+MI_SPLIT_LENGTH+
308 MI_DYN_DELETE_BLOCK_HEADER);
309 reclength= (info->s->base.pack_reclength+
310 _my_calc_total_blob_length(info,record)+ extra);
311 if (!(rec_buff=(uchar*) my_alloca(reclength)))
313 my_errno= HA_ERR_OUT_OF_MEM;
316 reclength=_mi_rec_pack(info,rec_buff+ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER),
318 error=update_dynamic_record(info,pos,
319 rec_buff+ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER),
326 int _mi_delete_dynamic_record(
MI_INFO *info)
328 return delete_dynamic_record(info,info->lastpos,0);
334 static int write_dynamic_record(
MI_INFO *info,
const uchar *record,
340 DBUG_ENTER(
"write_dynamic_record");
353 if (unlikely(info->s->base.max_data_file_length -
354 info->state->data_file_length <
355 reclength + MI_MAX_DYN_BLOCK_HEADER))
357 if (info->s->base.max_data_file_length - info->state->data_file_length +
358 info->state->empty - info->state->del * MI_MAX_DYN_BLOCK_HEADER <
359 reclength + MI_MAX_DYN_BLOCK_HEADER)
361 my_errno=HA_ERR_RECORD_FILE_FULL;
368 if (_mi_find_writepos(info,reclength,&filepos,&length))
370 if (_mi_write_part_record(info,filepos,length,
371 (info->append_insert_at_end ?
372 HA_OFFSET_ERROR : info->s->state.dellink),
373 (uchar**) &record,&reclength,&flag))
385 static int _mi_find_writepos(
MI_INFO *info,
392 DBUG_ENTER(
"_mi_find_writepos");
394 if (info->s->state.dellink != HA_OFFSET_ERROR &&
395 !info->append_insert_at_end)
398 *filepos=info->s->state.dellink;
399 block_info.second_read=0;
400 info->rec_cache.seek_not_done=1;
401 if (!(_mi_get_block_info(&block_info,info->dfile,info->s->state.dellink) &
404 DBUG_PRINT(
"error",(
"Delete link crashed"));
405 my_errno=HA_ERR_WRONG_IN_RECORD;
408 info->s->state.dellink=block_info.next_filepos;
410 info->state->empty-= block_info.block_len;
411 *length= block_info.block_len;
416 *filepos=info->state->data_file_length;
417 if ((tmp=reclength+3 +
test(reclength >= (65520-3))) <
418 info->s->base.min_block_length)
419 tmp= info->s->base.min_block_length;
421 tmp= ((tmp+MI_DYN_ALIGN_SIZE-1) &
422 (~ (ulong) (MI_DYN_ALIGN_SIZE-1)));
423 if (info->state->data_file_length >
424 (info->s->base.max_data_file_length - tmp))
426 my_errno=HA_ERR_RECORD_FILE_FULL;
429 if (tmp > MI_MAX_BLOCK_LENGTH)
430 tmp=MI_MAX_BLOCK_LENGTH;
432 info->state->data_file_length+= tmp;
433 info->s->state.split++;
434 info->update|=HA_STATE_WRITE_AT_END;
449 DBUG_ENTER(
"unlink_deleted_block");
450 if (block_info->filepos == info->s->state.dellink)
453 info->s->state.dellink=block_info->next_filepos;
460 if (!(_mi_get_block_info(&tmp,info->dfile,block_info->prev_filepos)
463 mi_sizestore(tmp.header+4,block_info->next_filepos);
464 if (info->s->file_write(info, tmp.header+4,8,
465 block_info->prev_filepos+4, MYF(MY_NABP)))
468 if (block_info->next_filepos != HA_OFFSET_ERROR)
470 if (!(_mi_get_block_info(&tmp,info->dfile,block_info->next_filepos)
473 mi_sizestore(tmp.header+12,block_info->prev_filepos);
474 if (info->s->file_write(info, tmp.header+12,8,
475 block_info->next_filepos+12,
482 info->state->empty-= block_info->block_len;
483 info->s->state.split--;
490 if (info->nextpos == block_info->filepos)
491 info->nextpos+=block_info->block_len;
511 static int update_backward_delete_link(
MI_INFO *info, my_off_t delete_block,
515 DBUG_ENTER(
"update_backward_delete_link");
517 if (delete_block != HA_OFFSET_ERROR)
519 block_info.second_read=0;
520 if (_mi_get_block_info(&block_info,info->dfile,delete_block)
524 mi_sizestore(buff,filepos);
525 if (info->s->file_write(info,buff, 8, delete_block+12, MYF(MY_NABP)))
530 my_errno=HA_ERR_WRONG_IN_RECORD;
540 static int delete_dynamic_record(
MI_INFO *info, my_off_t filepos,
546 my_bool remove_next_block;
547 DBUG_ENTER(
"delete_dynamic_record");
550 error= update_backward_delete_link(info, info->s->state.dellink, filepos);
552 block_info.second_read=second_read;
556 if ((b_type=_mi_get_block_info(&block_info,info->dfile,filepos))
557 & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
558 BLOCK_FATAL_ERROR) ||
559 (length=(uint) (block_info.filepos-filepos) +block_info.block_len) <
562 my_errno=HA_ERR_WRONG_IN_RECORD;
566 del_block.second_read=0;
568 if (_mi_get_block_info(&del_block,info->dfile,filepos+length) &
569 BLOCK_DELETED && del_block.block_len+length < MI_DYN_MAX_BLOCK_LENGTH)
573 length+=del_block.block_len;
576 block_info.header[0]=0;
577 mi_int3store(block_info.header+1,length);
578 mi_sizestore(block_info.header+4,info->s->state.dellink);
579 if (b_type & BLOCK_LAST)
580 memset(block_info.header + 12, 255, 8);
582 mi_sizestore(block_info.header+12,block_info.next_filepos);
583 if (info->s->file_write(info,(uchar*) block_info.header,20,filepos,
586 info->s->state.dellink = filepos;
588 info->state->empty+=length;
589 filepos=block_info.next_filepos;
592 if (remove_next_block && unlink_deleted_block(info,&del_block))
594 }
while (!(b_type & BLOCK_LAST));
602 int _mi_write_part_record(
MI_INFO *info,
605 my_off_t next_filepos,
610 ulong head_length,res_length,extra_length,long_block,del_length;
611 uchar *pos,*record_end;
612 my_off_t next_delete_block;
613 uchar
temp[MI_SPLIT_LENGTH+MI_DYN_DELETE_BLOCK_HEADER];
614 DBUG_ENTER(
"_mi_write_part_record");
616 next_delete_block=HA_OFFSET_ERROR;
618 res_length=extra_length=0;
619 if (length > *reclength + MI_SPLIT_LENGTH)
621 res_length=MY_ALIGN(length- *reclength - MI_EXTEND_BLOCK_LENGTH,
625 long_block= (length < 65520L && *reclength < 65520L) ? 0 : 1;
626 if (length == *reclength+ 3 + long_block)
629 temp[0]=(uchar) (1+ *flag)+(uchar) long_block;
632 mi_int3store(temp+1,*reclength);
637 mi_int2store(temp+1,*reclength);
641 else if (length-long_block < *reclength+4)
643 if (next_filepos == HA_OFFSET_ERROR)
644 next_filepos= (info->s->state.dellink != HA_OFFSET_ERROR &&
645 !info->append_insert_at_end ?
646 info->s->state.dellink : info->state->data_file_length);
649 if (*reclength > MI_MAX_BLOCK_LENGTH)
653 mi_int4store(temp+1,*reclength);
654 mi_int3store(temp+5,length-head_length);
655 mi_sizestore((uchar*) temp+8,next_filepos);
659 head_length=5+8+long_block*2;
660 temp[0]=5+(uchar) long_block;
663 mi_int3store(temp+1,*reclength);
664 mi_int3store(temp+4,length-head_length);
665 mi_sizestore((uchar*) temp+7,next_filepos);
669 mi_int2store(temp+1,*reclength);
670 mi_int2store(temp+3,length-head_length);
671 mi_sizestore((uchar*) temp+5,next_filepos);
677 head_length=3+8+long_block;
678 temp[0]=11+(uchar) long_block;
681 mi_int3store(temp+1,length-head_length);
682 mi_sizestore((uchar*) temp+4,next_filepos);
686 mi_int2store(temp+1,length-head_length);
687 mi_sizestore((uchar*) temp+3,next_filepos);
693 head_length=4+long_block;
694 extra_length= length- *reclength-head_length;
695 temp[0]= (uchar) (3+ *flag)+(uchar) long_block;
698 mi_int3store(temp+1,*reclength);
699 temp[4]= (uchar) (extra_length);
703 mi_int2store(temp+1,*reclength);
704 temp[3]= (uchar) (extra_length);
706 length= *reclength+head_length;
708 DBUG_DUMP(
"header",(uchar*) temp,head_length);
711 record_end= *record+length-head_length;
712 del_length=(res_length ? MI_DYN_DELETE_BLOCK_HEADER : 0);
713 bmove((uchar*) (*record-head_length),(uchar*) temp,head_length);
714 memcpy(temp,record_end,(
size_t) (extra_length+del_length));
715 memset(record_end, 0, extra_length);
721 my_off_t next_block=filepos+length+extra_length+res_length;
723 del_block.second_read=0;
724 if (next_block < info->state->data_file_length &&
725 info->s->state.dellink != HA_OFFSET_ERROR)
727 if ((_mi_get_block_info(&del_block,info->dfile,next_block)
729 res_length + del_block.block_len < MI_DYN_MAX_BLOCK_LENGTH)
731 if (unlink_deleted_block(info,&del_block))
733 res_length+=del_block.block_len;
738 pos=record_end+extra_length;
740 mi_int3store(pos+1,res_length);
741 mi_sizestore(pos+4,info->s->state.dellink);
742 memset(pos + 12, 255, 8);
743 next_delete_block=info->s->state.dellink;
744 info->s->state.dellink= filepos+length+extra_length;
746 info->state->empty+=res_length;
747 info->s->state.split++;
749 if (info->opt_flag & WRITE_CACHE_USED &&
750 info->update & HA_STATE_WRITE_AT_END)
752 if (info->update & HA_STATE_EXTEND_BLOCK)
754 info->update&= ~HA_STATE_EXTEND_BLOCK;
755 if (my_block_write(&info->rec_cache,(uchar*) *record-head_length,
756 length+extra_length+del_length,filepos))
759 else if (my_b_write(&info->rec_cache,(uchar*) *record-head_length,
760 length+extra_length+del_length))
765 info->rec_cache.seek_not_done=1;
766 if (info->s->file_write(info,(uchar*) *record-head_length,length+extra_length+
767 del_length,filepos,info->s->write_flag))
770 memcpy(record_end,temp,(
size_t) (extra_length+del_length));
772 *reclength-=(length-head_length);
778 if (update_backward_delete_link(info, next_delete_block,
779 info->s->state.dellink))
785 DBUG_PRINT(
"exit",(
"errno: %d",my_errno));
792 static int update_dynamic_record(
MI_INFO *info, my_off_t filepos, uchar *record,
799 DBUG_ENTER(
"update_dynamic_record");
801 flag=block_info.second_read=0;
815 if (unlikely(info->s->base.max_data_file_length -
816 info->state->data_file_length < reclength))
822 if ((error=_mi_get_block_info(&block_info,info->dfile,filepos))
823 & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR | BLOCK_FATAL_ERROR))
825 DBUG_PRINT(
"error",(
"Got wrong block info"));
826 if (!(error & BLOCK_FATAL_ERROR))
827 my_errno=HA_ERR_WRONG_IN_RECORD;
834 if (block_info.rec_len < reclength)
836 if (info->s->base.max_data_file_length - info->state->data_file_length +
837 info->state->empty - info->state->del * MI_MAX_DYN_BLOCK_HEADER <
838 reclength - block_info.rec_len + MI_MAX_DYN_BLOCK_HEADER)
840 my_errno=HA_ERR_RECORD_FILE_FULL;
844 block_info.second_read=0;
847 while (reclength > 0)
849 if (filepos != info->s->state.dellink)
851 block_info.next_filepos= HA_OFFSET_ERROR;
852 if ((error=_mi_get_block_info(&block_info,info->dfile,filepos))
853 & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
856 DBUG_PRINT(
"error",(
"Got wrong block info"));
857 if (!(error & BLOCK_FATAL_ERROR))
858 my_errno=HA_ERR_WRONG_IN_RECORD;
861 length=(ulong) (block_info.filepos-filepos) + block_info.block_len;
862 if (length < reclength)
864 uint tmp=MY_ALIGN(reclength - length + 3 +
865 test(reclength >= 65520L),MI_DYN_ALIGN_SIZE);
867 tmp= MY_MIN(length+tmp, MI_MAX_BLOCK_LENGTH)-length;
869 if (block_info.filepos + block_info.block_len ==
870 info->state->data_file_length &&
871 info->state->data_file_length <
872 info->s->base.max_data_file_length-tmp)
875 DBUG_PRINT(
"info",(
"Extending file with %d bytes",tmp));
876 if (info->nextpos == info->state->data_file_length)
878 info->state->data_file_length+= tmp;
879 info->update|= HA_STATE_WRITE_AT_END | HA_STATE_EXTEND_BLOCK;
882 else if (length < MI_MAX_BLOCK_LENGTH - MI_MIN_BLOCK_LENGTH)
892 del_block.second_read=0;
893 if (_mi_get_block_info(&del_block,info->dfile,
894 block_info.filepos + block_info.block_len) &
898 DBUG_PRINT(
"info",(
"Extending current block"));
899 if (unlink_deleted_block(info,&del_block))
901 if ((length+=del_block.block_len) > MI_MAX_BLOCK_LENGTH)
908 ulong rest_length= length-MI_MAX_BLOCK_LENGTH;
909 set_if_bigger(rest_length, MI_MIN_BLOCK_LENGTH);
910 next_pos= del_block.filepos+ del_block.block_len - rest_length;
912 if (update_backward_delete_link(info, info->s->state.dellink,
917 del_block.header[0]=0;
918 mi_int3store(del_block.header+1, rest_length);
919 mi_sizestore(del_block.header+4,info->s->state.dellink);
920 memset(del_block.header + 12, 255, 8);
921 if (info->s->file_write(info,(uchar*) del_block.header,20, next_pos,
924 info->s->state.dellink= next_pos;
925 info->s->state.split++;
927 info->state->empty+= rest_length;
928 length-= rest_length;
936 if (_mi_find_writepos(info,reclength,&filepos,&length))
939 if (_mi_write_part_record(info,filepos,length,block_info.next_filepos,
940 &record,&reclength,&flag))
942 if ((filepos=block_info.next_filepos) == HA_OFFSET_ERROR)
945 filepos=info->s->state.dellink;
949 if (block_info.next_filepos != HA_OFFSET_ERROR)
956 info->rec_cache.seek_not_done= 1;
957 if (delete_dynamic_record(info,block_info.next_filepos,1))
968 uint _mi_rec_pack(
MI_INFO *info,
register uchar *
to,
969 register const uchar *from)
971 uint length,new_length,flag,bit,
i;
972 uchar *pos,*end,*startpos,*packpos;
973 enum en_fieldtype
type;
976 DBUG_ENTER(
"_mi_rec_pack");
979 startpos=packpos=
to; to+= info->s->base.pack_bits; blob=info->blobs;
982 for (i=info->s->base.fields ; i-- > 0; from+= length,rec++)
984 length=(uint) rec->length;
985 if ((type = (
enum en_fieldtype) rec->type) != FIELD_NORMAL)
987 if (type == FIELD_BLOB)
994 size_t tmp_length=length-portable_sizeof_char_ptr;
995 memcpy((uchar*) to,from,tmp_length);
996 memcpy(&temp_pos,from+tmp_length,
sizeof(
char*));
997 memcpy(to+tmp_length,temp_pos,(
size_t) blob->length);
998 to+=tmp_length+blob->length;
1002 else if (type == FIELD_SKIP_ZERO)
1004 if (memcmp((uchar*) from,zero_string,length) == 0)
1008 memcpy((uchar*) to,from,(
size_t) length); to+=length;
1011 else if (type == FIELD_SKIP_ENDSPACE ||
1012 type == FIELD_SKIP_PRESPACE)
1014 pos= (uchar*) from; end= (uchar*) from + length;
1015 if (type == FIELD_SKIP_ENDSPACE)
1017 while (end > from && *(end-1) ==
' ')
1022 while (pos < end && *pos ==
' ')
1025 new_length=(uint) (end-pos);
1026 if (new_length +1 +
test(rec->length > 255 && new_length > 127)
1029 if (rec->length > 255 && new_length > 127)
1031 to[0]= (uchar) ((new_length & 127) + 128);
1032 to[1]= (uchar) (new_length >> 7);
1036 *to++= (uchar) new_length;
1037 memcpy((uchar*) to,pos,(
size_t) new_length); to+=new_length;
1042 memcpy(to,from,(
size_t) length); to+=length;
1045 else if (type == FIELD_VARCHAR)
1047 uint pack_length= HA_VARCHAR_PACKLENGTH(rec->length -1);
1049 if (pack_length == 1)
1051 tmp_length= (uint) *(uchar*) from;
1056 tmp_length= uint2korr(from);
1057 store_key_length_inc(to,tmp_length);
1059 memcpy(to, from+pack_length,tmp_length);
1065 memcpy(to,from,(
size_t) length); to+=length;
1068 if ((bit= bit << 1) >= 256)
1070 *packpos++= (uchar) flag;
1076 memcpy(to,from,(
size_t) length); to+=length;
1080 *packpos= (uchar) flag;
1081 if (info->s->calc_checksum)
1082 *to++= (uchar) info->checksum;
1083 DBUG_PRINT(
"exit",(
"packed length: %d",(
int) (to-startpos)));
1084 DBUG_RETURN((uint) (to-startpos));
1094 my_bool _mi_rec_check(
MI_INFO *info,
const uchar *record, uchar *rec_buff,
1095 ulong packed_length, my_bool with_checksum)
1097 uint length,new_length,flag,bit,
i;
1098 uchar *pos,*end,*packpos,*
to;
1099 enum en_fieldtype
type;
1101 DBUG_ENTER(
"_mi_rec_check");
1103 packpos=rec_buff; to= rec_buff+info->s->base.pack_bits;
1105 flag= *packpos; bit=1;
1107 for (i=info->s->base.fields ; i-- > 0; record+= length, rec++)
1109 length=(uint) rec->length;
1110 if ((type = (
enum en_fieldtype) rec->type) != FIELD_NORMAL)
1112 if (type == FIELD_BLOB)
1115 _mi_calc_blob_length(length-portable_sizeof_char_ptr,record);
1116 if (!blob_length && !(flag & bit))
1119 to+=length - portable_sizeof_char_ptr+ blob_length;
1121 else if (type == FIELD_SKIP_ZERO)
1123 if (memcmp((uchar*) record,zero_string,length) == 0)
1131 else if (type == FIELD_SKIP_ENDSPACE ||
1132 type == FIELD_SKIP_PRESPACE)
1134 pos= (uchar*) record; end= (uchar*) record + length;
1135 if (type == FIELD_SKIP_ENDSPACE)
1137 while (end > record && *(end-1) ==
' ')
1142 while (pos < end && *pos ==
' ')
1145 new_length=(uint) (end-pos);
1146 if (new_length +1 +
test(rec->length > 255 && new_length > 127)
1151 if (rec->length > 255 && new_length > 127)
1154 if (to[0] != (uchar) ((new_length & 127) + 128) ||
1155 to[1] != (uchar) (new_length >> 7))
1160 else if (*to++ != (uchar) new_length)
1167 else if (type == FIELD_VARCHAR)
1169 uint pack_length= HA_VARCHAR_PACKLENGTH(rec->length -1);
1171 if (pack_length == 1)
1173 tmp_length= (uint) *(uchar*) record;
1179 tmp_length= uint2korr(record);
1180 to+= get_pack_length(tmp_length)+tmp_length;
1189 if ((bit= bit << 1) >= 256)
1198 if (packed_length != (uint) (to - rec_buff) +
test(info->s->calc_checksum) ||
1199 (bit != 1 && (flag & ~(bit - 1))))
1201 if (with_checksum && ((uchar) info->checksum != (uchar) *to))
1203 DBUG_PRINT(
"error",(
"wrong checksum for row"));
1218 ulong _mi_rec_unpack(
register MI_INFO *info,
register uchar *to, uchar *from,
1221 uint flag,bit,length,rec_length,min_pack_length;
1222 enum en_fieldtype
type;
1223 uchar *from_end,*to_end,*packpos;
1225 DBUG_ENTER(
"_mi_rec_unpack");
1227 to_end=to + info->s->base.reclength;
1228 from_end=from+found_length;
1229 flag= (uchar) *from; bit=1; packpos=from;
1230 if (found_length < info->s->base.min_pack_length)
1232 from+= info->s->base.pack_bits;
1233 min_pack_length=info->s->base.min_pack_length - info->s->base.pack_bits;
1235 for (rec=info->s->rec , end_field=rec+info->s->base.fields ;
1236 rec < end_field ; to+= rec_length, rec++)
1238 rec_length=rec->length;
1239 if ((type = (
enum en_fieldtype) rec->type) != FIELD_NORMAL &&
1240 (type != FIELD_CHECK))
1242 if (type == FIELD_VARCHAR)
1244 uint pack_length= HA_VARCHAR_PACKLENGTH(rec_length-1);
1245 if (pack_length == 1)
1247 length= (uint) *(uchar*) from;
1248 if (length > rec_length-1)
1254 get_key_length(length, from);
1255 if (length > rec_length-2)
1257 int2store(to,length);
1259 if (from+length > from_end)
1261 memcpy(to+pack_length, from, length);
1268 if (type == FIELD_BLOB || type == FIELD_SKIP_ZERO)
1269 memset(to, 0, rec_length);
1270 else if (type == FIELD_SKIP_ENDSPACE ||
1271 type == FIELD_SKIP_PRESPACE)
1273 if (rec->length > 255 && *from & 128)
1275 if (from + 1 >= from_end)
1277 length= (*from & 127)+ ((uint) (uchar) *(from+1) << 7); from+=2;
1281 if (from == from_end)
1283 length= (uchar) *from++;
1286 if (length >= rec_length ||
1287 min_pack_length + length > (uint) (from_end - from))
1289 if (type == FIELD_SKIP_ENDSPACE)
1291 memcpy(to,(uchar*) from,(
size_t) length);
1292 memset(to + length,
' ', rec_length-length);
1296 memset(to,
' ', rec_length-length);
1297 memcpy(to+rec_length-length,(uchar*) from,(
size_t) length);
1302 else if (type == FIELD_BLOB)
1304 uint size_length=rec_length- portable_sizeof_char_ptr;
1305 ulong blob_length=_mi_calc_blob_length(size_length,from);
1306 ulong from_left= (ulong) (from_end - from);
1307 if (from_left < size_length ||
1308 from_left - size_length < blob_length ||
1309 from_left - size_length - blob_length < min_pack_length)
1311 memcpy(to, from, (
size_t) size_length);
1313 memcpy(to+size_length, &from,
sizeof(
char*));
1318 if (type == FIELD_SKIP_ENDSPACE || type == FIELD_SKIP_PRESPACE)
1320 if (min_pack_length + rec_length > (uint) (from_end - from))
1322 memcpy(to,(uchar*) from,(
size_t) rec_length); from+=rec_length;
1324 if ((bit= bit << 1) >= 256)
1326 flag= (uchar) *++packpos; bit=1;
1331 if (min_pack_length > (uint) (from_end - from))
1333 min_pack_length-=rec_length;
1334 memcpy(to, (uchar*) from, (
size_t) rec_length);
1338 if (info->s->calc_checksum)
1340 if (to == to_end && from == from_end && (bit == 1 || !(flag & ~(bit-1))))
1341 DBUG_RETURN(found_length);
1344 my_errno= HA_ERR_WRONG_IN_RECORD;
1345 DBUG_PRINT(
"error",(
"to_end: 0x%lx -> 0x%lx from_end: 0x%lx -> 0x%lx",
1346 (
long) to, (
long) to_end, (
long) from, (
long) from_end));
1347 DBUG_DUMP(
"from",(uchar*) info->rec_buff,info->s->base.min_pack_length);
1348 DBUG_RETURN(MY_FILE_ERROR);
1354 ulong _my_calc_total_blob_length(
MI_INFO *info,
const uchar *record)
1359 for (length=0, blob= info->blobs, end=blob+info->s->base.blobs ;
1363 blob->length=_mi_calc_blob_length(blob->pack_length,record + blob->offset);
1364 length+=blob->length;
1370 ulong _mi_calc_blob_length(uint length,
const uchar *pos)
1374 return (uint) (uchar) *pos;
1376 return (uint) uint2korr(pos);
1378 return uint3korr(pos);
1380 return uint4korr(pos);
1388 void _mi_store_blob_length(uchar *pos,uint pack_length,uint length)
1390 switch (pack_length) {
1392 *pos= (uchar) length;
1395 int2store(pos,length);
1398 int3store(pos,length);
1401 int4store(pos,length);
1441 int _mi_read_dynamic_record(
MI_INFO *info, my_off_t filepos, uchar *
buf)
1443 int block_of_record;
1444 uint b_type,UNINIT_VAR(left_length);
1445 uchar *UNINIT_VAR(to);
1448 DBUG_ENTER(
"mi_read_dynamic_record");
1450 if (filepos != HA_OFFSET_ERROR)
1454 block_info.second_read= 0;
1458 if (filepos == HA_OFFSET_ERROR)
1460 if (info->opt_flag & WRITE_CACHE_USED &&
1461 info->rec_cache.pos_in_file < filepos + MI_BLOCK_INFO_HEADER_LENGTH &&
1462 flush_io_cache(&info->rec_cache))
1464 info->rec_cache.seek_not_done=1;
1465 if ((b_type= _mi_get_block_info(&block_info, file, filepos))
1466 & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
1469 if (b_type & (BLOCK_SYNC_ERROR | BLOCK_DELETED))
1470 my_errno=HA_ERR_RECORD_DELETED;
1473 if (block_of_record++ == 0)
1475 if (block_info.rec_len > (uint) info->s->base.max_pack_length)
1477 if (info->s->base.blobs)
1479 if (!(to=mi_alloc_rec_buff(info, block_info.rec_len,
1485 left_length=block_info.rec_len;
1487 if (left_length < block_info.data_len || ! block_info.data_len)
1491 uint offset= (uint) (block_info.filepos - filepos);
1492 uint prefetch_len= (
sizeof(block_info.header) - offset);
1493 filepos+=
sizeof(block_info.header);
1495 if (prefetch_len > block_info.data_len)
1496 prefetch_len= block_info.data_len;
1499 memcpy((uchar*) to, block_info.header + offset, prefetch_len);
1500 block_info.data_len-= prefetch_len;
1501 left_length-= prefetch_len;
1506 if (block_info.data_len)
1508 if (info->opt_flag & WRITE_CACHE_USED &&
1509 info->rec_cache.pos_in_file < filepos + block_info.data_len &&
1510 flush_io_cache(&info->rec_cache))
1517 if (info->s->file_read(info, (uchar*) to, block_info.data_len,
1518 filepos, MYF(MY_NABP)))
1520 left_length-=block_info.data_len;
1521 to+=block_info.data_len;
1523 filepos= block_info.next_filepos;
1524 }
while (left_length);
1526 info->update|= HA_STATE_AKTIV;
1527 fast_mi_writeinfo(info);
1528 DBUG_RETURN(_mi_rec_unpack(info,buf,info->rec_buff,block_info.rec_len) !=
1529 MY_FILE_ERROR ? 0 : -1);
1531 fast_mi_writeinfo(info);
1535 my_errno=HA_ERR_WRONG_IN_RECORD;
1537 (void) _mi_writeinfo(info,0);
1544 const uchar *record, my_off_t pos)
1546 uchar *rec_buff,*old_record;
1548 DBUG_ENTER(
"_mi_cmp_dynamic_unique");
1550 if (!(old_record=my_alloca(info->s->base.reclength)))
1554 rec_buff=info->rec_buff;
1555 if (info->s->base.blobs)
1557 error=_mi_read_dynamic_record(info,pos,old_record);
1559 error=mi_unique_comp(def, record, old_record, def->null_are_equal);
1560 if (info->s->base.blobs)
1562 my_free(mi_get_rec_buff_ptr(info, info->rec_buff));
1563 info->rec_buff=rec_buff;
1565 my_afree(old_record);
1572 int _mi_cmp_dynamic_record(
register MI_INFO *info,
register const uchar *record)
1574 uint flag,reclength,b_type;
1578 DBUG_ENTER(
"_mi_cmp_dynamic_record");
1580 if (info->opt_flag & WRITE_CACHE_USED)
1582 info->update&= ~(HA_STATE_WRITE_AT_END | HA_STATE_EXTEND_BLOCK);
1583 if (flush_io_cache(&info->rec_cache))
1586 info->rec_cache.seek_not_done=1;
1590 buffer=info->rec_buff;
1591 if ((info->opt_flag & READ_CHECK_USED))
1593 if (info->s->base.blobs)
1595 if (!(buffer=(uchar*) my_alloca(info->s->base.pack_reclength+
1596 _my_calc_total_blob_length(info,record))))
1599 reclength=_mi_rec_pack(info,buffer,record);
1602 filepos=info->lastpos;
1603 flag=block_info.second_read=0;
1604 block_info.next_filepos=filepos;
1605 while (reclength > 0)
1607 if ((b_type=_mi_get_block_info(&block_info,info->dfile,
1608 block_info.next_filepos))
1609 & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
1612 if (b_type & (BLOCK_SYNC_ERROR | BLOCK_DELETED))
1613 my_errno=HA_ERR_RECORD_CHANGED;
1619 if (reclength != block_info.rec_len)
1621 my_errno=HA_ERR_RECORD_CHANGED;
1624 }
else if (reclength < block_info.data_len)
1626 my_errno=HA_ERR_WRONG_IN_RECORD;
1629 reclength-=block_info.data_len;
1630 if (_mi_cmp_buffer(info->dfile,record,block_info.filepos,
1631 block_info.data_len))
1633 my_errno=HA_ERR_RECORD_CHANGED;
1637 record+=block_info.data_len;
1642 if (buffer != info->rec_buff)
1643 my_afree((uchar*) buffer);
1644 DBUG_RETURN(my_errno);
1650 static int _mi_cmp_buffer(File file,
const uchar *buff, my_off_t filepos,
1654 uchar temp_buff[IO_SIZE*2];
1655 DBUG_ENTER(
"_mi_cmp_buffer");
1657 next_length= IO_SIZE*2 - (uint) (filepos & (IO_SIZE-1));
1659 while (length > IO_SIZE*2)
1661 if (
mysql_file_pread(file, temp_buff, next_length, filepos, MYF(MY_NABP)) ||
1662 memcmp(buff, temp_buff, next_length))
1664 filepos+=next_length;
1666 length-= next_length;
1667 next_length=IO_SIZE*2;
1671 DBUG_RETURN(memcmp(buff,temp_buff,length));
1711 int _mi_read_rnd_dynamic_record(
MI_INFO *info, uchar *buf,
1712 register my_off_t filepos,
1713 my_bool skip_deleted_blocks)
1715 int block_of_record, info_read, save_errno;
1716 uint left_len,b_type;
1717 uchar *UNINIT_VAR(to);
1720 DBUG_ENTER(
"_mi_read_rnd_dynamic_record");
1724 if (info->lock_type == F_UNLCK)
1726 #ifndef UNSAFE_LOCKING
1727 if (share->tot_locks == 0)
1729 if (my_lock(share->kfile,F_RDLCK,0L,F_TO_EOF,
1730 MYF(MY_SEEK_NOT_DONE) | info->lock_wait))
1731 DBUG_RETURN(my_errno);
1734 info->tmp_lock_type=F_RDLCK;
1741 block_info.second_read= 0;
1745 if (filepos >= info->state->data_file_length)
1750 info->rec_cache.seek_not_done=1;
1751 if (mi_state_info_read_dsk(share->kfile,&share->state,1))
1754 if (filepos >= info->state->data_file_length)
1756 my_errno= HA_ERR_END_OF_FILE;
1760 if (info->opt_flag & READ_CACHE_USED)
1762 if (_mi_read_cache(&info->rec_cache,(uchar*) block_info.header,filepos,
1763 sizeof(block_info.header),
1764 (!block_of_record && skip_deleted_blocks ?
1765 READING_NEXT : 0) | READING_HEADER))
1767 b_type=_mi_get_block_info(&block_info,-1,filepos);
1771 if (info->opt_flag & WRITE_CACHE_USED &&
1772 info->rec_cache.pos_in_file < filepos + MI_BLOCK_INFO_HEADER_LENGTH &&
1773 flush_io_cache(&info->rec_cache))
1774 DBUG_RETURN(my_errno);
1775 info->rec_cache.seek_not_done=1;
1776 b_type=_mi_get_block_info(&block_info,info->dfile,filepos);
1779 if (b_type & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
1782 if ((b_type & (BLOCK_DELETED | BLOCK_SYNC_ERROR))
1783 && skip_deleted_blocks)
1785 filepos=block_info.filepos+block_info.block_len;
1786 block_info.second_read=0;
1789 if (b_type & (BLOCK_DELETED | BLOCK_SYNC_ERROR))
1796 if (block_of_record != 0)
1799 my_errno=HA_ERR_RECORD_DELETED;
1800 info->lastpos=block_info.filepos;
1801 info->nextpos=block_info.filepos+block_info.block_len;
1805 if (block_of_record == 0)
1807 if (block_info.rec_len > (uint) share->base.max_pack_length)
1809 info->lastpos=filepos;
1810 if (share->base.blobs)
1812 if (!(to= mi_alloc_rec_buff(info, block_info.rec_len,
1818 left_len=block_info.rec_len;
1820 if (left_len < block_info.data_len)
1825 uint offset=(uint) (block_info.filepos - filepos);
1826 uint tmp_length= (
sizeof(block_info.header) - offset);
1827 filepos=block_info.filepos;
1829 if (tmp_length > block_info.data_len)
1830 tmp_length= block_info.data_len;
1833 memcpy((uchar*) to, block_info.header+offset,tmp_length);
1834 block_info.data_len-=tmp_length;
1835 left_len-=tmp_length;
1837 filepos+=tmp_length;
1841 if (block_info.data_len)
1843 if (info->opt_flag & READ_CACHE_USED)
1845 if (_mi_read_cache(&info->rec_cache,(uchar*) to,filepos,
1846 block_info.data_len,
1847 (!block_of_record && skip_deleted_blocks) ?
1853 if (info->opt_flag & WRITE_CACHE_USED &&
1854 info->rec_cache.pos_in_file <
1855 block_info.filepos + block_info.data_len &&
1856 flush_io_cache(&info->rec_cache))
1863 my_errno= HA_ERR_WRONG_IN_RECORD;
1872 if (block_of_record++ == 0)
1874 info->nextpos= block_info.filepos + block_info.block_len;
1875 skip_deleted_blocks= 0;
1877 left_len-=block_info.data_len;
1878 to+=block_info.data_len;
1879 filepos=block_info.next_filepos;
1882 info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED;
1883 fast_mi_writeinfo(info);
1884 if (_mi_rec_unpack(info,buf,info->rec_buff,block_info.rec_len) !=
1887 DBUG_RETURN(my_errno);
1890 my_errno=HA_ERR_WRONG_IN_RECORD;
1892 save_errno=my_errno;
1893 (void) _mi_writeinfo(info,0);
1894 DBUG_RETURN(my_errno=save_errno);
1900 uint _mi_get_block_info(
MI_BLOCK_INFO *info, File file, my_off_t filepos)
1903 uchar *header=info->header;
1914 sizeof(info->header))
1917 DBUG_DUMP(
"header",header,MI_BLOCK_INFO_HEADER_LENGTH);
1918 if (info->second_read)
1920 if (info->header[0] <= 6 || info->header[0] == 13)
1921 return_val=BLOCK_SYNC_ERROR;
1925 if (info->header[0] > 6 && info->header[0] != 13)
1926 return_val=BLOCK_SYNC_ERROR;
1928 info->next_filepos= HA_OFFSET_ERROR;
1930 switch (info->header[0]) {
1932 if ((info->block_len=(uint) mi_uint3korr(header+1)) <
1933 MI_MIN_BLOCK_LENGTH ||
1934 (info->block_len & (MI_DYN_ALIGN_SIZE -1)))
1936 info->filepos=filepos;
1937 info->next_filepos=mi_sizekorr(header+4);
1938 info->prev_filepos=mi_sizekorr(header+12);
1939 #if SIZEOF_OFF_T == 4
1940 if ((mi_uint4korr(header+4) != 0 &&
1941 (mi_uint4korr(header+4) != (ulong) ~0 ||
1942 info->next_filepos != (ulong) ~0)) ||
1943 (mi_uint4korr(header+12) != 0 &&
1944 (mi_uint4korr(header+12) != (ulong) ~0 ||
1945 info->prev_filepos != (ulong) ~0)))
1948 return return_val | BLOCK_DELETED;
1951 info->rec_len=info->data_len=info->block_len=mi_uint2korr(header+1);
1952 info->filepos=filepos+3;
1953 return return_val | BLOCK_FIRST | BLOCK_LAST;
1955 info->rec_len=info->data_len=info->block_len=mi_uint3korr(header+1);
1956 info->filepos=filepos+4;
1957 return return_val | BLOCK_FIRST | BLOCK_LAST;
1960 info->rec_len=mi_uint4korr(header+1);
1961 info->block_len=info->data_len=mi_uint3korr(header+5);
1962 info->next_filepos=mi_sizekorr(header+8);
1963 info->second_read=1;
1964 info->filepos=filepos+16;
1965 return return_val | BLOCK_FIRST;
1968 info->rec_len=info->data_len=mi_uint2korr(header+1);
1969 info->block_len=info->rec_len+ (uint) header[3];
1970 info->filepos=filepos+4;
1971 return return_val | BLOCK_FIRST | BLOCK_LAST;
1973 info->rec_len=info->data_len=mi_uint3korr(header+1);
1974 info->block_len=info->rec_len+ (uint) header[4];
1975 info->filepos=filepos+5;
1976 return return_val | BLOCK_FIRST | BLOCK_LAST;
1979 info->rec_len=mi_uint2korr(header+1);
1980 info->block_len=info->data_len=mi_uint2korr(header+3);
1981 info->next_filepos=mi_sizekorr(header+5);
1982 info->second_read=1;
1983 info->filepos=filepos+13;
1984 return return_val | BLOCK_FIRST;
1986 info->rec_len=mi_uint3korr(header+1);
1987 info->block_len=info->data_len=mi_uint3korr(header+4);
1988 info->next_filepos=mi_sizekorr(header+7);
1989 info->second_read=1;
1990 info->filepos=filepos+15;
1991 return return_val | BLOCK_FIRST;
1995 info->data_len=info->block_len=mi_uint2korr(header+1);
1996 info->filepos=filepos+3;
1997 return return_val | BLOCK_LAST;
1999 info->data_len=info->block_len=mi_uint3korr(header+1);
2000 info->filepos=filepos+4;
2001 return return_val | BLOCK_LAST;
2004 info->data_len=mi_uint2korr(header+1);
2005 info->block_len=info->data_len+ (uint) header[3];
2006 info->filepos=filepos+4;
2007 return return_val | BLOCK_LAST;
2009 info->data_len=mi_uint3korr(header+1);
2010 info->block_len=info->data_len+ (uint) header[4];
2011 info->filepos=filepos+5;
2012 return return_val | BLOCK_LAST;
2015 info->data_len=info->block_len=mi_uint2korr(header+1);
2016 info->next_filepos=mi_sizekorr(header+3);
2017 info->second_read=1;
2018 info->filepos=filepos+11;
2021 info->data_len=info->block_len=mi_uint3korr(header+1);
2022 info->next_filepos=mi_sizekorr(header+4);
2023 info->second_read=1;
2024 info->filepos=filepos+12;
2029 my_errno=HA_ERR_WRONG_IN_RECORD;