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); }
static int rtree_insert_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key, uint key_length, my_off_t page, my_off_t *new_page, int ins_level, int level) { uchar *k; uint nod_flag; uchar *page_buf; int res; DBUG_ENTER("rtree_insert_req"); if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length + MI_MAX_KEY_BUFF))) { my_errno = HA_ERR_OUT_OF_MEM; DBUG_RETURN(-1); /* purecov: inspected */ } if (!_mi_fetch_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf, 0)) goto err1; nod_flag = mi_test_if_nod(page_buf); DBUG_PRINT("rtree", ("page: %lu level: %d ins_level: %d nod_flag: %u", (ulong) page, level, ins_level, nod_flag)); if ((ins_level == -1 && nod_flag) || /* key: go down to leaf */ (ins_level > -1 && ins_level > level)) /* branch: go down to ins_level */ { if ((k = rtree_pick_key(info, keyinfo, key, key_length, page_buf, nod_flag)) == NULL) goto err1; switch ((res = rtree_insert_req(info, keyinfo, key, key_length, _mi_kpos(nod_flag, k), new_page, ins_level, level + 1))) { case 0: /* child was not split */ { rtree_combine_rect(keyinfo->seg, k, key, k, key_length); if (_mi_write_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf)) goto err1; goto ok; } case 1: /* child was split */ { uchar *new_key = page_buf + keyinfo->block_length + nod_flag; /* set proper MBR for key */ if (rtree_set_key_mbr(info, keyinfo, k, key_length, _mi_kpos(nod_flag, k))) goto err1; /* add new key for new page */ _mi_kpointer(info, new_key - nod_flag, *new_page); if (rtree_set_key_mbr(info, keyinfo, new_key, key_length, *new_page)) goto err1; res = rtree_add_key(info, keyinfo, new_key, key_length, page_buf, new_page); if (_mi_write_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf)) goto err1; goto ok; } default: case -1: /* error */ { goto err1; } } } else { res = rtree_add_key(info, keyinfo, key, key_length, page_buf, new_page); if (_mi_write_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf)) goto err1; goto ok; } ok: my_afree((uchar*)page_buf); DBUG_RETURN(res); err1: my_afree((uchar*)page_buf); DBUG_RETURN(-1); /* purecov: inspected */ }