22 #define MAX_POINTER_LENGTH 8
27 uint comp_flag, uchar *key,
28 uint key_length, my_off_t pos, uchar *father_buff,
29 uchar *father_keypos, my_off_t father_page,
32 uchar *curr_buff,uchar *father_buff,
33 uchar *father_keypos,my_off_t father_page);
34 static uchar *_mi_find_last_pos(
MI_KEYDEF *keyinfo, uchar *
page,
35 uchar *key, uint *return_key_length,
37 int _mi_ck_write_tree(
register MI_INFO *info, uint keynr,uchar *key,
39 int _mi_ck_write_btree(
register MI_INFO *info, uint keynr,uchar *key,
51 my_bool lock_tree= share->concurrent_insert;
52 DBUG_ENTER(
"mi_write");
53 DBUG_PRINT(
"enter",(
"isam: %d data: %d",info->s->kfile,info->dfile));
55 DBUG_EXECUTE_IF(
"myisam_pretend_crashed_table_on_usage",
56 mi_print_error(info->s, HA_ERR_CRASHED);
57 DBUG_RETURN(my_errno= HA_ERR_CRASHED););
58 if (share->options & HA_OPTION_READ_ONLY_DATA)
60 DBUG_RETURN(my_errno=EACCES);
62 if (_mi_readinfo(info,F_WRLCK,1))
63 DBUG_RETURN(my_errno);
65 filepos= ((share->state.dellink != HA_OFFSET_ERROR &&
66 !info->append_insert_at_end) ?
67 share->state.dellink :
68 info->state->data_file_length);
70 if (share->base.reloc == (ha_rows) 1 &&
71 share->base.records == (ha_rows) 1 &&
72 info->state->records == (ha_rows) 1)
74 my_errno=HA_ERR_RECORD_FILE_FULL;
77 if (info->state->key_file_length >= share->base.margin_key_file_length)
79 my_errno=HA_ERR_INDEX_FILE_FULL;
82 if (_mi_mark_file_changed(info))
86 if (mi_is_any_key_active(share->state.key_map))
88 for (i= 0 ; i < share->state.header.uniques ; i++)
90 if (mi_check_unique(info, share->uniqueinfo + i, record,
91 mi_unique_hash(share->uniqueinfo + i, record),
100 for (i=0 ; i < share->base.keys ; i++)
102 if (mi_is_key_active(share->state.key_map, i))
104 my_bool local_lock_tree= (lock_tree &&
105 !(info->bulk_insert &&
106 is_tree_inited(&info->bulk_insert[i])));
110 share->keyinfo[
i].version++;
112 if (share->keyinfo[i].flag & HA_FULLTEXT )
114 if (_mi_ft_add(info,i, buff, record, filepos))
118 DBUG_PRINT(
"error",(
"Got error: %d on write",my_errno));
124 if (share->keyinfo[i].ck_insert(info,i,buff,
125 _mi_make_key(info,i,buff,record,filepos)))
129 DBUG_PRINT(
"error",(
"Got error: %d on write",my_errno));
135 info->update&= ~HA_STATE_RNEXT_SAME;
141 if (share->calc_checksum)
142 info->checksum=(*share->calc_checksum)(info,record);
143 if (!(info->opt_flag & OPT_NO_ROWS))
145 if ((*share->write_record)(info,record))
147 info->state->checksum+=info->checksum;
149 if (share->base.auto_key)
150 set_if_bigger(info->s->state.auto_increment,
151 retrieve_auto_increment(info, record));
152 info->update= (HA_STATE_CHANGED | HA_STATE_AKTIV | HA_STATE_WRITTEN |
153 HA_STATE_ROW_CHANGED);
154 info->state->records++;
155 info->lastpos=filepos;
156 myisam_log_record(MI_LOG_WRITE,info,record,filepos,0);
157 (void) _mi_writeinfo(info, WRITEINFO_UPDATE_KEYFILE);
158 if (info->invalidator != 0)
160 DBUG_PRINT(
"info", (
"invalidator... '%s' (update)", info->filename));
161 (*info->invalidator)(info->filename);
173 if (share->is_log_table)
174 mi_update_status((
void*) info);
180 if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_RECORD_FILE_FULL ||
181 my_errno == HA_ERR_NULL_IN_SPATIAL || my_errno == HA_ERR_OUT_OF_MEM)
183 if (info->bulk_insert)
186 for (j=0 ; j < share->base.keys ; j++)
187 mi_flush_bulk_insert(info, j);
189 info->errkey= (int) i;
192 if (mi_is_key_active(share->state.key_map, i))
194 my_bool local_lock_tree= (lock_tree &&
195 !(info->bulk_insert &&
196 is_tree_inited(&info->bulk_insert[i])));
199 if (share->keyinfo[i].flag & HA_FULLTEXT)
201 if (_mi_ft_del(info,i, buff,record,filepos))
210 uint key_length=_mi_make_key(info,i,buff,record,filepos);
211 if (share->keyinfo[i].ck_delete(info, i, buff, key_length))
225 mi_print_error(info->s, HA_ERR_CRASHED);
226 mi_mark_crashed(info);
228 info->update= (HA_STATE_CHANGED | HA_STATE_WRITTEN | HA_STATE_ROW_CHANGED);
232 myisam_log_record(MI_LOG_WRITE,info,record,filepos,my_errno);
233 (void) _mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE);
234 DBUG_RETURN(my_errno=save_errno);
240 int _mi_ck_write(
MI_INFO *info, uint keynr, uchar *key, uint key_length)
242 DBUG_ENTER(
"_mi_ck_write");
244 if (info->bulk_insert && is_tree_inited(&info->bulk_insert[keynr]))
246 DBUG_RETURN(_mi_ck_write_tree(info, keynr, key, key_length));
250 DBUG_RETURN(_mi_ck_write_btree(info, keynr, key, key_length));
259 int _mi_ck_write_btree(
register MI_INFO *info, uint keynr, uchar *key,
264 MI_KEYDEF *keyinfo=info->s->keyinfo+keynr;
265 my_off_t *root=&info->s->state.key_root[keynr];
266 DBUG_ENTER(
"_mi_ck_write_btree");
268 if (keyinfo->flag & HA_SORT_ALLOWS_SAME)
269 comp_flag=SEARCH_BIGGER;
270 else if (keyinfo->flag & (HA_NOSAME|HA_FULLTEXT))
272 comp_flag=SEARCH_FIND | SEARCH_UPDATE;
273 if (keyinfo->flag & HA_NULL_ARE_EQUAL)
274 comp_flag|= SEARCH_NULL_ARE_EQUAL;
277 comp_flag=SEARCH_SAME;
279 error=_mi_ck_real_write_btree(info, keyinfo, key, key_length,
281 if (info->ft1_to_ft2)
284 error= _mi_ft_convert_to_ft2(info, keynr, key);
285 delete_dynamic(info->ft1_to_ft2);
286 my_free(info->ft1_to_ft2);
293 uchar *key, uint key_length, my_off_t *root, uint comp_flag)
296 DBUG_ENTER(
"_mi_ck_real_write_btree");
298 if (*root == HA_OFFSET_ERROR ||
299 (error=w_search(info, keyinfo, comp_flag, key, key_length,
300 *root, (uchar *) 0, (uchar*) 0,
301 (my_off_t) 0, 1)) > 0)
302 error=_mi_enlarge_root(info,keyinfo,key,root);
312 uint t_length,nod_flag;
315 DBUG_ENTER(
"_mi_enlarge_root");
317 nod_flag= (*root != HA_OFFSET_ERROR) ? share->base.key_reflength : 0;
318 _mi_kpointer(info,info->buff+2,*root);
319 t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,(uchar*) 0,
320 (uchar*) 0, (uchar*) 0, key,&s_temp);
321 mi_putint(info->buff,t_length+2+nod_flag,nod_flag);
322 (*keyinfo->store_key)(keyinfo,info->buff+2+nod_flag,&s_temp);
323 info->buff_used=info->page_changed=1;
324 if ((*root= _mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR ||
325 _mi_write_keypage(info,keyinfo,*root,DFLT_INIT_HITS,info->buff))
339 uint comp_flag, uchar *key, uint key_length, my_off_t
page,
340 uchar *father_buff, uchar *father_keypos,
341 my_off_t father_page, my_bool insert_last)
344 uint nod_flag, search_key_length;
345 uchar *temp_buff,*keypos;
346 uchar keybuff[MI_MAX_KEY_BUFF];
347 my_bool was_last_key;
348 my_off_t next_page, dupp_key_pos;
349 DBUG_ENTER(
"w_search");
350 DBUG_PRINT(
"enter",(
"page: %ld", (
long) page));
352 search_key_length= (comp_flag & SEARCH_FIND) ? key_length : USE_WHOLE_KEY;
353 if (!(temp_buff= (uchar*) my_alloca((uint) keyinfo->block_length+
356 if (!_mi_fetch_keypage(info,keyinfo,page,DFLT_INIT_HITS,temp_buff,0))
359 flag=(*keyinfo->bin_search)(info,keyinfo,temp_buff,key,search_key_length,
360 comp_flag, &keypos, keybuff, &was_last_key);
361 nod_flag=mi_test_if_nod(temp_buff);
366 tmp_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,keybuff);
368 dupp_key_pos=_mi_dpos(info,0,keybuff+tmp_key_length);
370 dupp_key_pos= HA_OFFSET_ERROR;
372 if (keyinfo->flag & HA_FULLTEXT)
377 get_key_full_length_rdonly(off, keybuff);
378 subkeys=ft_sintXkorr(keybuff+off);
379 comp_flag=SEARCH_SAME;
383 flag=(*keyinfo->bin_search)(info, keyinfo, temp_buff, key,
384 USE_WHOLE_KEY, comp_flag,
385 &keypos, keybuff, &was_last_key);
390 my_off_t root=dupp_key_pos;
391 keyinfo=&info->s->ft2_keyinfo;
392 get_key_full_length_rdonly(off, key);
394 keypos-=keyinfo->keylength+nod_flag;
395 error=_mi_ck_real_write_btree(info, keyinfo, key, 0,
397 _mi_dpointer(info, keypos+HA_FT_WLEN, root);
399 DBUG_ASSERT(subkeys < 0);
400 ft_intXstore(keypos, subkeys);
402 error=_mi_write_keypage(info,keyinfo,page,DFLT_INIT_HITS,temp_buff);
403 my_afree((uchar*) temp_buff);
409 info->dupp_key_pos= dupp_key_pos;
410 my_afree((uchar*) temp_buff);
411 my_errno=HA_ERR_FOUND_DUPP_KEY;
415 if (flag == MI_FOUND_WRONG_KEY)
419 next_page=_mi_kpos(nod_flag,keypos);
420 if (next_page == HA_OFFSET_ERROR ||
421 (error=w_search(info, keyinfo, comp_flag, key, key_length, next_page,
422 temp_buff, keypos, page, insert_last)) >0)
424 error=_mi_insert(info,keyinfo,key,temp_buff,keypos,keybuff,father_buff,
425 father_keypos,father_page, insert_last);
426 if (_mi_write_keypage(info,keyinfo,page,DFLT_INIT_HITS,temp_buff))
429 my_afree((uchar*) temp_buff);
432 my_afree((uchar*) temp_buff);
433 DBUG_PRINT(
"exit",(
"Error: %d",my_errno));
464 uchar *key, uchar *anc_buff, uchar *key_pos, uchar *key_buff,
465 uchar *father_buff, uchar *father_key_pos, my_off_t father_page,
468 uint a_length,nod_flag;
470 uchar *endpos, *prev_key;
472 DBUG_ENTER(
"_mi_insert");
473 DBUG_PRINT(
"enter",(
"key_pos: 0x%lx", (
long) key_pos));
474 DBUG_EXECUTE(
"key",_mi_print_key(DBUG_FILE,keyinfo->seg,key,USE_WHOLE_KEY););
476 nod_flag=mi_test_if_nod(anc_buff);
477 a_length=mi_getint(anc_buff);
478 endpos= anc_buff+ a_length;
479 prev_key=(key_pos == anc_buff+2+nod_flag ? (uchar*) 0 : key_buff);
480 t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,
481 (key_pos == endpos ? (uchar*) 0 : key_pos),
485 if (key_pos != anc_buff+2+nod_flag && (keyinfo->flag &
486 (HA_BINARY_PACK_KEY | HA_PACK_KEY)))
488 DBUG_DUMP(
"prev_key",(uchar*) key_buff,_mi_keylength(keyinfo,key_buff));
490 if (keyinfo->flag & HA_PACK_KEY)
492 DBUG_PRINT(
"test",(
"t_length: %d ref_len: %d",
493 t_length,s_temp.ref_length));
494 DBUG_PRINT(
"test",(
"n_ref_len: %d n_length: %d key_pos: 0x%lx",
495 s_temp.n_ref_length,s_temp.n_length, (
long) s_temp.key));
500 if (t_length >= keyinfo->maxlength*2+MAX_POINTER_LENGTH)
502 mi_print_error(info->s, HA_ERR_CRASHED);
503 my_errno=HA_ERR_CRASHED;
506 bmove_upp((uchar*) endpos+t_length,(uchar*) endpos,(uint) (endpos-key_pos));
510 if (-t_length >= keyinfo->maxlength*2+MAX_POINTER_LENGTH)
512 mi_print_error(info->s, HA_ERR_CRASHED);
513 my_errno=HA_ERR_CRASHED;
516 bmove(key_pos,key_pos-t_length,(uint) (endpos-key_pos)+t_length);
518 (*keyinfo->store_key)(keyinfo,key_pos,&s_temp);
520 mi_putint(anc_buff,a_length,nod_flag);
521 if (a_length <= keyinfo->block_length)
523 if (keyinfo->block_length - a_length < 32 &&
524 keyinfo->flag & HA_FULLTEXT && key_pos == endpos &&
525 info->s->base.key_reflength <= info->s->rec_reflength &&
526 info->s->options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD))
533 uchar *a=key, *b=anc_buff+2+nod_flag;
534 uint alen, blen, ft2len=info->s->ft2_keyinfo.keylength;
536 DBUG_ASSERT((*b & 128) == 0);
537 #if HA_FT_MAXLEN >= 127
538 blen= mi_uint2korr(b); b+=2;
542 get_key_length(alen,a);
543 DBUG_ASSERT(info->ft1_to_ft2==0);
545 ha_compare_text(keyinfo->seg->charset, a, alen, b, blen, 0, 0)==0)
550 my_init_dynamic_array(info->ft1_to_ft2, ft2len, 300, 50);
561 for (a=anc_buff+a_length ; b < a ; b+=ft2len+2)
563 if (insert_dynamic(info->ft1_to_ft2, b))
565 mi_print_error(info->s, HA_ERR_OUT_OF_MEM);
566 my_errno= HA_ERR_OUT_OF_MEM;
572 mi_putint(anc_buff,2+blen+ft2len+2,0);
582 if (!(keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)) &&
583 father_buff && !insert_last)
584 DBUG_RETURN(_mi_balance_page(info,keyinfo,key,anc_buff,father_buff,
585 father_key_pos,father_page));
586 DBUG_RETURN(_mi_split_page(info,keyinfo,key,anc_buff,key_buff, insert_last));
593 uchar *key, uchar *buff, uchar *key_buff,
594 my_bool insert_last_key)
596 uint length,a_length,key_ref_length,t_length,nod_flag,key_length;
597 uchar *key_pos,*pos, *after_key;
600 DBUG_ENTER(
"mi_split_page");
601 LINT_INIT(after_key);
602 DBUG_DUMP(
"buff",(uchar*) buff,mi_getint(buff));
604 if (info->s->keyinfo+info->lastinx == keyinfo)
605 info->page_changed=1;
607 nod_flag=mi_test_if_nod(buff);
608 key_ref_length=2+nod_flag;
610 key_pos=_mi_find_last_pos(keyinfo,buff,key_buff, &key_length, &after_key);
612 key_pos=_mi_find_half_pos(nod_flag,keyinfo,buff,key_buff, &key_length,
617 length=(uint) (key_pos-buff);
618 a_length=mi_getint(buff);
619 mi_putint(buff,length,nod_flag);
624 DBUG_PRINT(
"test",(
"Splitting nod"));
625 pos=key_pos-nod_flag;
626 memcpy((uchar*) info->buff+2,(uchar*) pos,(
size_t) nod_flag);
630 if ((new_pos=_mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
632 _mi_kpointer(info,_mi_move_key(keyinfo,key,key_buff),new_pos);
635 if (!(*keyinfo->get_key)(keyinfo,nod_flag,&key_pos,key_buff))
638 t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,(uchar *) 0,
639 (uchar*) 0, (uchar*) 0,
641 length=(uint) ((buff+a_length)-key_pos);
642 memcpy((uchar*) info->buff+key_ref_length+t_length,(uchar*) key_pos,
644 (*keyinfo->store_key)(keyinfo,info->buff+key_ref_length,&s_temp);
645 mi_putint(info->buff,length+t_length+key_ref_length,nod_flag);
647 if (_mi_write_keypage(info,keyinfo,new_pos,DFLT_INIT_HITS,info->buff))
649 DBUG_DUMP(
"key",(uchar*) key,_mi_keylength(keyinfo,key));
662 uchar *_mi_find_half_pos(uint nod_flag,
MI_KEYDEF *keyinfo, uchar *page,
663 uchar *key, uint *return_key_length,
666 uint keys,length,key_ref_length;
668 DBUG_ENTER(
"_mi_find_half_pos");
670 key_ref_length=2+nod_flag;
671 length=mi_getint(page)-key_ref_length;
672 page+=key_ref_length;
673 if (!(keyinfo->flag &
674 (HA_PACK_KEY | HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY |
675 HA_BINARY_PACK_KEY)))
677 key_ref_length=keyinfo->keylength+nod_flag;
678 keys=length/(key_ref_length*2);
679 *return_key_length=keyinfo->keylength;
680 end=page+keys*key_ref_length;
681 *after_key=end+key_ref_length;
682 memcpy(key,end,key_ref_length);
686 end=page+length/2-key_ref_length;
691 if (!(length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,key)))
693 }
while (page < end);
694 *return_key_length=length;
696 DBUG_PRINT(
"exit",(
"returns: 0x%lx page: 0x%lx half: 0x%lx",
697 (
long) lastpos, (
long) page, (
long) end));
698 DBUG_RETURN(lastpos);
708 static uchar *_mi_find_last_pos(
MI_KEYDEF *keyinfo, uchar *page,
709 uchar *key, uint *return_key_length,
712 uint keys,length,UNINIT_VAR(last_length),key_ref_length;
713 uchar *end,*lastpos,*UNINIT_VAR(prevpos);
714 uchar key_buff[MI_MAX_KEY_BUFF];
715 DBUG_ENTER(
"_mi_find_last_pos");
718 length=mi_getint(page)-key_ref_length;
719 page+=key_ref_length;
720 if (!(keyinfo->flag &
721 (HA_PACK_KEY | HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY |
722 HA_BINARY_PACK_KEY)))
724 keys=length/keyinfo->keylength-2;
725 *return_key_length=length=keyinfo->keylength;
726 end=page+keys*length;
727 *after_key=end+length;
728 memcpy(key,end,length);
732 end=page+length-key_ref_length;
738 prevpos=lastpos; lastpos=
page;
740 memcpy(key, key_buff, length);
741 if (!(length=(*keyinfo->get_key)(keyinfo,0,&page,key_buff)))
743 mi_print_error(keyinfo->share, HA_ERR_CRASHED);
744 my_errno=HA_ERR_CRASHED;
748 *return_key_length=last_length;
750 DBUG_PRINT(
"exit",(
"returns: 0x%lx page: 0x%lx end: 0x%lx",
751 (
long) prevpos,(
long) page,(
long) end));
752 DBUG_RETURN(prevpos);
760 uchar *key, uchar *curr_buff, uchar *father_buff,
761 uchar *father_key_pos, my_off_t father_page)
764 uint k_length,father_length,father_keylength,nod_flag,curr_keylength,
765 right_length,left_length,new_right_length,new_left_length,extra_length,
767 uchar *pos,*buff,*extra_buff;
768 my_off_t next_page,new_pos;
769 uchar tmp_part_key[MI_MAX_KEY_BUFF];
770 DBUG_ENTER(
"_mi_balance_page");
772 k_length=keyinfo->keylength;
773 father_length=mi_getint(father_buff);
774 father_keylength=k_length+info->s->base.key_reflength;
775 nod_flag=mi_test_if_nod(curr_buff);
776 curr_keylength=k_length+nod_flag;
777 info->page_changed=1;
779 if ((father_key_pos != father_buff+father_length &&
780 (info->state->records & 1)) ||
781 father_key_pos == father_buff+2+info->s->base.key_reflength)
784 next_page= _mi_kpos(info->s->base.key_reflength,
785 father_key_pos+father_keylength);
787 DBUG_PRINT(
"test",(
"use right page: %lu", (ulong) next_page));
792 father_key_pos-=father_keylength;
793 next_page= _mi_kpos(info->s->base.key_reflength,father_key_pos);
795 buff=curr_buff; curr_buff=info->buff;
796 DBUG_PRINT(
"test",(
"use left page: %lu", (ulong) next_page));
799 if (!_mi_fetch_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,info->buff,0))
801 DBUG_DUMP(
"next",(uchar*) info->buff,mi_getint(info->buff));
805 left_length=mi_getint(curr_buff);
806 right_length=mi_getint(buff);
807 keys=(left_length+right_length-4-nod_flag*2)/curr_keylength;
809 if ((right ? right_length : left_length) + curr_keylength <=
810 keyinfo->block_length)
812 new_left_length=2+nod_flag+(keys/2)*curr_keylength;
813 new_right_length=2+nod_flag+((keys+1)/2)*curr_keylength;
814 mi_putint(curr_buff,new_left_length,nod_flag);
815 mi_putint(buff,new_right_length,nod_flag);
817 if (left_length < new_left_length)
819 pos=curr_buff+left_length;
820 memcpy((uchar*) pos,(uchar*) father_key_pos, (
size_t) k_length);
821 memcpy((uchar*) pos+k_length, (uchar*) buff+2,
822 (
size_t) (length=new_left_length - left_length - k_length));
824 memcpy((uchar*) father_key_pos,(uchar*) pos,(
size_t) k_length);
825 bmove((uchar*) buff + 2, (uchar*) pos + k_length, new_right_length - 2);
830 bmove_upp((uchar*) buff+new_right_length,(uchar*) buff+right_length,
832 length=new_right_length-right_length-k_length;
833 memcpy((uchar*) buff+2+length,father_key_pos,(
size_t) k_length);
834 pos=curr_buff+new_left_length;
835 memcpy((uchar*) father_key_pos,(uchar*) pos,(
size_t) k_length);
836 memcpy((uchar*) buff+2,(uchar*) pos+k_length,(
size_t) length);
839 if (_mi_write_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,info->buff) ||
840 _mi_write_keypage(info,keyinfo,father_page,DFLT_INIT_HITS,father_buff))
847 extra_buff=info->buff+info->s->base.max_key_block_length;
848 new_left_length=new_right_length=2+nod_flag+(keys+1)/3*curr_keylength;
850 new_left_length-=curr_keylength;
851 extra_length=nod_flag+left_length+right_length-
852 new_left_length-new_right_length-curr_keylength;
853 DBUG_PRINT(
"info",(
"left_length: %d right_length: %d new_left_length: %d new_right_length: %d extra_length: %d",
854 left_length, right_length,
855 new_left_length, new_right_length,
857 mi_putint(curr_buff,new_left_length,nod_flag);
858 mi_putint(buff,new_right_length,nod_flag);
859 mi_putint(extra_buff,extra_length+2,nod_flag);
862 pos=buff+right_length-extra_length;
863 memcpy((uchar*) extra_buff+2,pos,(
size_t) extra_length);
865 memcpy(tmp_part_key, pos-k_length,k_length);
867 bmove_upp((uchar*) buff+new_right_length,(uchar*) pos-k_length,
868 right_length-extra_length-k_length-2);
870 pos= curr_buff+new_left_length;
871 memcpy((uchar*) buff+2,(uchar*) pos+k_length,
872 (
size_t) (length=left_length-new_left_length-k_length));
874 memcpy((uchar*) buff+2+length,father_key_pos,(
size_t) k_length);
877 memcpy((uchar*) (right ? key : father_key_pos),pos,(
size_t) k_length);
878 memcpy((uchar*) (right ? father_key_pos : key),tmp_part_key, k_length);
880 if ((new_pos=_mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
882 _mi_kpointer(info,key+k_length,new_pos);
883 if (_mi_write_keypage(info,keyinfo,(right ? new_pos : next_page),
884 DFLT_INIT_HITS,info->buff) ||
885 _mi_write_keypage(info,keyinfo,(right ? next_page : new_pos),
886 DFLT_INIT_HITS,extra_buff))
904 int _mi_ck_write_tree(
register MI_INFO *info, uint keynr, uchar *key,
908 DBUG_ENTER(
"_mi_ck_write_tree");
910 error= tree_insert(&info->bulk_insert[keynr], key,
911 key_length + info->s->rec_reflength,
912 info->bulk_insert[keynr].custom_arg) ? 0 : HA_ERR_OUT_OF_MEM ;
923 return ha_key_cmp(param->info->s->keyinfo[param->keynr].seg,
924 key1, key2, USE_WHOLE_KEY, SEARCH_SAME,
935 uchar lastkey[MI_MAX_KEY_BUFF];
941 if (param->info->s->concurrent_insert)
944 param->info->s->keyinfo[param->keynr].version++;
948 keyinfo=param->info->s->keyinfo+param->keynr;
949 keylen=_mi_keylength(keyinfo, key);
950 memcpy(lastkey, key, keylen);
951 return _mi_ck_write_btree(param->info,param->keynr,lastkey,
952 keylen - param->info->s->rec_reflength);
954 if (param->info->s->concurrent_insert)
962 int mi_init_bulk_insert(
MI_INFO *info, ulong cache_size, ha_rows rows)
967 uint
i, num_keys, total_keylength;
969 DBUG_ENTER(
"_mi_init_bulk_insert");
970 DBUG_PRINT(
"enter",(
"cache_size: %lu", cache_size));
972 DBUG_ASSERT(!info->bulk_insert &&
973 (!rows || rows >= MI_MIN_ROWS_TO_USE_BULK_INSERT));
975 mi_clear_all_keys_active(key_map);
976 for (i=total_keylength=num_keys=0 ; i < share->base.keys ; i++)
978 if (! (key[i].flag & HA_NOSAME) && (share->base.auto_key != i + 1) &&
979 mi_is_key_active(share->state.key_map, i))
982 mi_set_key_active(key_map, i);
983 total_keylength+=key[
i].maxlength+TREE_ELEMENT_EXTRA_SIZE;
988 num_keys * MI_MIN_SIZE_BULK_INSERT_TREE > cache_size)
991 if (rows && rows*total_keylength < cache_size)
992 cache_size= (ulong)rows;
994 cache_size/=total_keylength*16;
996 info->bulk_insert=(
TREE *)
997 my_malloc((
sizeof(
TREE)*share->base.keys+
1000 if (!info->bulk_insert)
1001 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
1004 for (i=0 ; i < share->base.keys ; i++)
1006 if (mi_is_key_active(key_map, i))
1011 init_tree(&info->bulk_insert[i],
1012 cache_size * key[i].maxlength,
1013 cache_size * key[i].maxlength, 0,
1014 (qsort_cmp2)keys_compare, 0,
1015 (tree_element_free) keys_free, (
void *)params++);
1018 info->bulk_insert[
i].root=0;
1024 void mi_flush_bulk_insert(
MI_INFO *info, uint inx)
1026 if (info->bulk_insert)
1028 if (is_tree_inited(&info->bulk_insert[inx]))
1029 reset_tree(&info->bulk_insert[inx]);
1033 void mi_end_bulk_insert(
MI_INFO *info)
1035 if (info->bulk_insert)
1038 for (i=0 ; i < info->s->base.keys ; i++)
1040 if (is_tree_inited(& info->bulk_insert[i]))
1042 delete_tree(& info->bulk_insert[i]);
1045 my_free(info->bulk_insert);
1046 info->bulk_insert=0;