int rtree_add_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key, uint key_length, uchar *page_buf, my_off_t *new_page) { uint page_size = mi_getint(page_buf); uint nod_flag = mi_test_if_nod(page_buf); DBUG_ENTER("rtree_add_key"); if (page_size + key_length + info->s->base.rec_reflength <= keyinfo->block_length) { /* split won't be necessary */ if (nod_flag) { /* save key */ DBUG_ASSERT(_mi_kpos(nod_flag, key) < info->state->key_file_length); memcpy(rt_PAGE_END(page_buf), key - nod_flag, key_length + nod_flag); page_size += key_length + nod_flag; } else { /* save key */ DBUG_ASSERT(_mi_dpos(info, nod_flag, key + key_length + info->s->base.rec_reflength) < info->state->data_file_length + info->s->base.pack_reclength); memcpy(rt_PAGE_END(page_buf), key, key_length + info->s->base.rec_reflength); page_size += key_length + info->s->base.rec_reflength; } mi_putint(page_buf, page_size, nod_flag); DBUG_RETURN(0); } DBUG_RETURN((rtree_split_page(info, keyinfo, page_buf, key, key_length, new_page) ? -1 : 1)); }
uint _mi_ft_convert_to_ft2(MI_INFO *info, uint keynr, uchar *key) { my_off_t root; DYNAMIC_ARRAY *da=info->ft1_to_ft2; MI_KEYDEF *keyinfo=&info->s->ft2_keyinfo; uchar *key_ptr= (uchar*) dynamic_array_ptr(da, 0), *end; uint length, key_length; DBUG_ENTER("_mi_ft_convert_to_ft2"); /* we'll generate one pageful at once, and insert the rest one-by-one */ /* calculating the length of this page ...*/ length=(keyinfo->block_length-2) / keyinfo->keylength; set_if_smaller(length, da->elements); length=length * keyinfo->keylength; get_key_full_length_rdonly(key_length, key); while (_mi_ck_delete(info, keynr, key, key_length) == 0) { /* nothing to do here. _mi_ck_delete() will populate info->ft1_to_ft2 with deleted keys */ } /* creating pageful of keys */ mi_putint(info->buff,length+2,0); memcpy(info->buff+2, key_ptr, length); info->buff_used=info->page_changed=1; /* info->buff is used */ if ((root= _mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR || _mi_write_keypage(info,keyinfo,root,DFLT_INIT_HITS,info->buff)) DBUG_RETURN(-1); /* inserting the rest of key values */ end= (uchar*) dynamic_array_ptr(da, da->elements); for (key_ptr+=length; key_ptr < end; key_ptr+=keyinfo->keylength) if(_mi_ck_real_write_btree(info, keyinfo, key_ptr, 0, &root, SEARCH_SAME)) DBUG_RETURN(-1); /* now, writing the word key entry */ ft_intXstore(key+key_length, - (int) da->elements); _mi_dpointer(info, key+key_length+HA_FT_WLEN, root); DBUG_RETURN(_mi_ck_real_write_btree(info, info->s->keyinfo+keynr, key, 0, &info->s->state.key_root[keynr], SEARCH_SAME)); }
/* Delete key from the page */ int rtree_delete_key(MI_INFO *info, uchar *page_buf, uchar *key, uint key_length, uint nod_flag) { uint16 page_size = mi_getint(page_buf); uchar *key_start; key_start= key - nod_flag; if (!nod_flag) key_length += info->s->base.rec_reflength; memmove(key_start, key + key_length, page_size - key_length - (key - page_buf)); page_size-= key_length + nod_flag; mi_putint(page_buf, page_size, nod_flag); return 0; }
int _mi_enlarge_root(register MI_INFO * info, uint keynr, uchar * key) { uint t_length , nod_flag; reg2 MI_KEYDEF *keyinfo; MI_KEY_PARAM s_temp; MYISAM_SHARE *share = info->s; DBUG_ENTER("_mi_enlarge_root"); nod_flag = (share->state.key_root[keynr] != HA_OFFSET_ERROR) ? share->base.key_reflength : 0; _mi_kpointer(info, info->buff + 2, share->state.key_root[keynr]); /* if nod */ keyinfo = share->keyinfo + keynr; t_length = (*keyinfo->pack_key) (keyinfo, nod_flag, (uchar *) 0, (uchar *) 0, (uchar *) 0, key, &s_temp); mi_putint(info->buff, t_length + 2 + nod_flag, nod_flag); (*keyinfo->store_key) (keyinfo, info->buff + 2 + nod_flag, &s_temp); info->buff_used = info->page_changed = 1; /* info->buff is used */ if ((share->state.key_root[keynr] = _mi_new(info, keyinfo)) == HA_OFFSET_ERROR || _mi_write_keypage(info, keyinfo, share->state.key_root[keynr], info->buff)) DBUG_RETURN(-1); DBUG_RETURN(0); } /* _mi_enlarge_root */
static int rtree_insert_level(MI_INFO *info, uint keynr, uchar *key, uint key_length, int ins_level) { my_off_t old_root; MI_KEYDEF *keyinfo = info->s->keyinfo + keynr; int res; my_off_t new_page; DBUG_ENTER("rtree_insert_level"); if ((old_root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR) { if ((old_root = _mi_new(info, keyinfo, DFLT_INIT_HITS)) == HA_OFFSET_ERROR) DBUG_RETURN(-1); info->buff_used = 1; mi_putint(info->buff, 2, 0); res = rtree_add_key(info, keyinfo, key, key_length, info->buff, NULL); if (_mi_write_keypage(info, keyinfo, old_root, DFLT_INIT_HITS, info->buff)) DBUG_RETURN(1); info->s->state.key_root[keynr] = old_root; DBUG_RETURN(res); } switch ((res = rtree_insert_req(info, keyinfo, key, key_length, old_root, &new_page, ins_level, 0))) { case 0: /* root was not split */ { break; } case 1: /* root was split, grow a new root */ { uchar *new_root_buf= info->buff + info->s->base.max_key_block_length; my_off_t new_root; uchar *new_key; uint nod_flag = info->s->base.key_reflength; DBUG_PRINT("rtree", ("root was split, grow a new root")); mi_putint(new_root_buf, 2, nod_flag); if ((new_root = _mi_new(info, keyinfo, DFLT_INIT_HITS)) == HA_OFFSET_ERROR) goto err1; new_key = new_root_buf + keyinfo->block_length + nod_flag; _mi_kpointer(info, new_key - nod_flag, old_root); if (rtree_set_key_mbr(info, keyinfo, new_key, key_length, old_root)) goto err1; if (rtree_add_key(info, keyinfo, new_key, key_length, new_root_buf, NULL) == -1) goto err1; _mi_kpointer(info, new_key - nod_flag, new_page); if (rtree_set_key_mbr(info, keyinfo, new_key, key_length, new_page)) goto err1; if (rtree_add_key(info, keyinfo, new_key, key_length, new_root_buf, NULL) == -1) goto err1; if (_mi_write_keypage(info, keyinfo, new_root, DFLT_INIT_HITS, new_root_buf)) goto err1; info->s->state.key_root[keynr] = new_root; DBUG_PRINT("rtree", ("new root page: %lu level: %d nod_flag: %u", (ulong) new_root, 0, mi_test_if_nod(new_root_buf))); break; err1: DBUG_RETURN(-1); /* purecov: inspected */ } default: case -1: /* error */ { break; } } DBUG_RETURN(res); }
int rtree_split_page(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, uchar *key, uint key_length, my_off_t *new_page_offs) { int n1, n2; /* Number of items in groups */ SplitStruct *task; SplitStruct *cur; SplitStruct *stop; double *coord_buf; double *next_coord; int n_dim; uchar *source_cur, *cur1, *cur2; uchar *new_page= info->buff; int err_code= 0; uint nod_flag= mi_test_if_nod(page); uint full_length= key_length + (nod_flag ? nod_flag : info->s->base.rec_reflength); int max_keys= (mi_getint(page)-2) / (full_length); DBUG_ENTER("rtree_split_page"); DBUG_PRINT("rtree", ("splitting block")); n_dim = keyinfo->keysegs / 2; if (!(coord_buf= (double*) my_alloca(n_dim * 2 * sizeof(double) * (max_keys + 1 + 4) + sizeof(SplitStruct) * (max_keys + 1)))) DBUG_RETURN(-1); /* purecov: inspected */ task= (SplitStruct *)(coord_buf + n_dim * 2 * (max_keys + 1 + 4)); next_coord = coord_buf; stop = task + max_keys; source_cur = rt_PAGE_FIRST_KEY(page, nod_flag); for (cur = task; cur < stop; ++cur, source_cur = rt_PAGE_NEXT_KEY(source_cur, key_length, nod_flag)) { cur->coords = reserve_coords(&next_coord, n_dim); cur->key = source_cur; rtree_d_mbr(keyinfo->seg, source_cur, key_length, cur->coords); } cur->coords = reserve_coords(&next_coord, n_dim); rtree_d_mbr(keyinfo->seg, key, key_length, cur->coords); cur->key = key; if (split_rtree_node(task, max_keys + 1, mi_getint(page) + full_length + 2, full_length, rt_PAGE_MIN_SIZE(keyinfo->block_length), 2, 2, &next_coord, n_dim)) { err_code = 1; goto split_err; } info->buff_used= 1; stop = task + (max_keys + 1); cur1 = rt_PAGE_FIRST_KEY(page, nod_flag); cur2 = rt_PAGE_FIRST_KEY(new_page, nod_flag); n1= n2 = 0; for (cur = task; cur < stop; ++cur) { uchar *to; if (cur->n_node == 1) { to = cur1; cur1 = rt_PAGE_NEXT_KEY(cur1, key_length, nod_flag); ++n1; } else { to = cur2; cur2 = rt_PAGE_NEXT_KEY(cur2, key_length, nod_flag); ++n2; } if (to != cur->key) memcpy(to - nod_flag, cur->key - nod_flag, full_length); } mi_putint(page, 2 + n1 * full_length, nod_flag); mi_putint(new_page, 2 + n2 * full_length, nod_flag); if ((*new_page_offs= _mi_new(info, keyinfo, DFLT_INIT_HITS)) == HA_OFFSET_ERROR) err_code= -1; else err_code= _mi_write_keypage(info, keyinfo, *new_page_offs, DFLT_INIT_HITS, new_page); DBUG_PRINT("rtree", ("split new block: %lu", (ulong) *new_page_offs)); split_err: my_afree((uchar*) coord_buf); DBUG_RETURN(err_code); }