Esempio n. 1
0
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));
}
Esempio n. 3
0
/*
  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;
}
Esempio n. 4
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);
}
Esempio n. 6
0
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);
}