コード例 #1
0
ファイル: mi_statrec.c プロジェクト: Baoxiyi-Github/Mysql
int _mi_read_static_record(register MI_INFO *info, register my_off_t pos,
			   register uchar *record)
{
  int error;

  if (pos != HA_OFFSET_ERROR)
  {
    if (info->opt_flag & WRITE_CACHE_USED &&
	info->rec_cache.pos_in_file <= pos &&
	flush_io_cache(&info->rec_cache))
      return(-1);
    info->rec_cache.seek_not_done=1;		/* We have done a seek */

    error=info->s->file_read(info, record, info->s->base.reclength,
		   pos,MYF(MY_NABP)) != 0;
    fast_mi_writeinfo(info);
    if (! error)
    {
      if (!*record)
      {
	my_errno=HA_ERR_RECORD_DELETED;
	return(1);				/* Record is deleted */
      }
      info->update|= HA_STATE_AKTIV;		/* Record is read */
      return(0);
    }
    return(-1);					/* Error on read */
  }
  fast_mi_writeinfo(info);			/* No such record */
  return(-1);
}
コード例 #2
0
ファイル: mi_range.c プロジェクト: Tsuiwiki/infobright
ha_rows mi_records_in_range(MI_INFO *info, int inx,
                            key_range *min_key, key_range *max_key)
{
  ha_rows start_pos,end_pos,res;
  DBUG_ENTER("mi_records_in_range");

  if ((inx = _mi_check_index(info,inx)) < 0)
    DBUG_RETURN(HA_POS_ERROR);

  if (fast_mi_readinfo(info))
    DBUG_RETURN(HA_POS_ERROR);
  info->update&= (HA_STATE_CHANGED+HA_STATE_ROW_CHANGED);
  if (info->s->concurrent_insert)
    rw_rdlock(&info->s->key_root_lock[inx]);

  switch(info->s->keyinfo[inx].key_alg){
#ifdef HAVE_RTREE_KEYS
  case HA_KEY_ALG_RTREE:
  {
    uchar * key_buff;
    uint start_key_len;

    /*
      The problem is that the optimizer doesn't support
      RTree keys properly at the moment.
      Hope this will be fixed some day.
      But now NULL in the min_key means that we
      didn't make the task for the RTree key
      and expect BTree functionality from it.
      As it's not able to handle such request
      we return the error.
    */
    if (!min_key)
    {
      res= HA_POS_ERROR;
      break;
    }
    key_buff= info->lastkey+info->s->base.max_key_length;
    start_key_len= _mi_pack_key(info,inx, key_buff,
                                (uchar*) min_key->key, min_key->keypart_map,
                                (HA_KEYSEG**) 0);
    res= rtree_estimate(info, inx, key_buff, start_key_len,
                        myisam_read_vec[min_key->flag]);
    res= res ? res : 1;                       /* Don't return 0 */
    break;
  }
#endif
  case HA_KEY_ALG_BTREE:
  default:
    start_pos= (min_key ?  _mi_record_pos(info, min_key->key,
                                          min_key->keypart_map, min_key->flag)
                        : (ha_rows) 0);
    end_pos=   (max_key ?  _mi_record_pos(info, max_key->key,
                                          max_key->keypart_map, max_key->flag)
                        : info->state->records + (ha_rows) 1);
    res= (end_pos < start_pos ? (ha_rows) 0 :
          (end_pos == start_pos ? (ha_rows) 1 : end_pos-start_pos));
    if (start_pos == HA_POS_ERROR || end_pos == HA_POS_ERROR)
      res=HA_POS_ERROR;
  }

  if (info->s->concurrent_insert)
    rw_unlock(&info->s->key_root_lock[inx]);
  fast_mi_writeinfo(info);

  DBUG_PRINT("info",("records: %ld",(ulong) (res)));
  DBUG_RETURN(res);
}
コード例 #3
0
ファイル: mi_statrec.c プロジェクト: Baoxiyi-Github/Mysql
int _mi_read_rnd_static_record(MI_INFO *info, uchar *buf,
			       register my_off_t filepos,
			       my_bool skip_deleted_blocks)
{
  int locked,error,cache_read;
  uint cache_length;
  MYISAM_SHARE *share=info->s;
  DBUG_ENTER("_mi_read_rnd_static_record");

  cache_read=0;
  cache_length=0;
  if (info->opt_flag & WRITE_CACHE_USED &&
      (info->rec_cache.pos_in_file <= filepos || skip_deleted_blocks) &&
      flush_io_cache(&info->rec_cache))
    DBUG_RETURN(my_errno);
  if (info->opt_flag & READ_CACHE_USED)
  {						/* Cache in use */
    if (filepos == my_b_tell(&info->rec_cache) &&
	(skip_deleted_blocks || !filepos))
    {
      cache_read=1;				/* Read record using cache */
      cache_length=(uint) (info->rec_cache.read_end - info->rec_cache.read_pos);
    }
    else
      info->rec_cache.seek_not_done=1;		/* Filepos is changed */
  }
  locked=0;
  if (info->lock_type == F_UNLCK)
  {
    if (filepos >= info->state->data_file_length)
    {						/* Test if new records */
      if (_mi_readinfo(info,F_RDLCK,0))
	DBUG_RETURN(my_errno);
      locked=1;
    }
    else
    {						/* We don't nead new info */
#ifndef UNSAFE_LOCKING
      if ((! cache_read || share->base.reclength > cache_length) &&
	  share->tot_locks == 0)
      {						/* record not in cache */
	if (my_lock(share->kfile,F_RDLCK,0L,F_TO_EOF,
		    MYF(MY_SEEK_NOT_DONE) | info->lock_wait))
	  DBUG_RETURN(my_errno);
	locked=1;
      }
#else
      info->tmp_lock_type=F_RDLCK;
#endif
    }
  }
  if (filepos >= info->state->data_file_length)
  {
    DBUG_PRINT("test",("filepos: %ld (%ld)  records: %ld  del: %ld",
		       (long) filepos/share->base.reclength, (long) filepos,
		       (long) info->state->records, (long) info->state->del));
    fast_mi_writeinfo(info);
    DBUG_RETURN(my_errno=HA_ERR_END_OF_FILE);
  }
  info->lastpos= filepos;
  info->nextpos= filepos+share->base.pack_reclength;

  if (! cache_read)			/* No cacheing */
  {
    if ((error=_mi_read_static_record(info,filepos,buf)))
    {
      if (error > 0)
	error=my_errno=HA_ERR_RECORD_DELETED;
      else
	error=my_errno;
    }
    DBUG_RETURN(error);
  }

  /*
    Read record with caching. If my_b_read() returns TRUE, less than the
    requested bytes have been read. In this case rec_cache.error is
    either -1 for a read error, or contains the number of bytes copied
    into the buffer.
  */
  error=my_b_read(&info->rec_cache,(uchar*) buf,share->base.reclength);
  if (info->s->base.pack_reclength != info->s->base.reclength && !error)
  {
    char tmp[8];				/* Skill fill bytes */
    error=my_b_read(&info->rec_cache,(uchar*) tmp,
		    info->s->base.pack_reclength - info->s->base.reclength);
  }
  if (locked)
    (void) _mi_writeinfo(info,0);		/* Unlock keyfile */
  if (!error)
  {
    if (!buf[0])
    {						/* Record is removed */
      DBUG_RETURN(my_errno=HA_ERR_RECORD_DELETED);
    }
						/* Found and may be updated */
    info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED;
    DBUG_RETURN(0);
  }
  /* error is TRUE. my_errno should be set if rec_cache.error == -1 */
  if (info->rec_cache.error != -1 || my_errno == 0)
  {
    /*
      If we could not get a full record, we either have a broken record,
      or are at end of file.
    */
    if (info->rec_cache.error == 0)
      my_errno= HA_ERR_END_OF_FILE;
    else
      my_errno= HA_ERR_WRONG_IN_RECORD;
  }
  DBUG_RETURN(my_errno);			/* Something wrong (EOF?) */
}
コード例 #4
0
ファイル: mi_info.c プロジェクト: isleon/Jaxer
int mi_status(MI_INFO *info, register MI_ISAMINFO *x, uint flag)
{
  MY_STAT state;
  MYISAM_SHARE *share=info->s;
  DBUG_ENTER("mi_status");

  x->recpos  = info->lastpos;
  if (flag == HA_STATUS_POS)
    DBUG_RETURN(0);				/* Compatible with ISAM */
  if (!(flag & HA_STATUS_NO_LOCK))
  {
    pthread_mutex_lock(&share->intern_lock);
    VOID(_mi_readinfo(info,F_RDLCK,0));
    fast_mi_writeinfo(info);
    pthread_mutex_unlock(&share->intern_lock);
  }
  if (flag & HA_STATUS_VARIABLE)
  {
    x->records	 	= info->state->records;
    x->deleted	 	= info->state->del;
    x->delete_length	= info->state->empty;
    x->data_file_length	=info->state->data_file_length;
    x->index_file_length=info->state->key_file_length;

    x->keys	 	= share->state.header.keys;
    x->check_time	= share->state.check_time;
    x->mean_reclength= x->records ?
      (ulong) ((x->data_file_length - x->delete_length) / x->records) :
      (ulong) share->min_pack_length;
  }
  if (flag & HA_STATUS_ERRKEY)
  {
    x->errkey	 = info->errkey;
    x->dupp_key_pos= info->dupp_key_pos;
  }
  if (flag & HA_STATUS_CONST)
  {
    x->reclength	= share->base.reclength;
    x->max_data_file_length=share->base.max_data_file_length;
    x->max_index_file_length=info->s->base.max_key_file_length;
    x->filenr	 = info->dfile;
    x->options	 = share->options;
    x->create_time=share->state.create_time;
    x->reflength= mi_get_pointer_length(share->base.max_data_file_length,
                                        myisam_data_pointer_size);
    x->record_offset= ((share->options &
			(HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ?
		       0L : share->base.pack_reclength);
    x->sortkey= -1;				/* No clustering */
    x->rec_per_key	= share->state.rec_per_key_part;
    x->key_map	 	= share->state.key_map;
    x->data_file_name   = share->data_file_name;
    x->index_file_name  = share->index_file_name;
    /*
      The following should be included even if we are not compiling with
      USE_RAID as the client must be able to request it!
    */
    x->raid_type= share->base.raid_type;
    x->raid_chunks= share->base.raid_chunks;
    x->raid_chunksize= share->base.raid_chunksize;
  }
  if ((flag & HA_STATUS_TIME) && !my_fstat(info->dfile,&state,MYF(0)))
    x->update_time=state.st_mtime;
  else
    x->update_time=0;
  if (flag & HA_STATUS_AUTO)
  {
    x->auto_increment= share->state.auto_increment+1;
    if (!x->auto_increment)			/* This shouldn't happen */
      x->auto_increment= ~(ulonglong) 0;
  }
  DBUG_RETURN(0);
}
コード例 #5
0
int mi_rnext(MI_INFO *info, uchar *buf, int inx)
{
  int error,changed;
  uint flag;
  ICP_RESULT icp_res= ICP_MATCH;
  uint update_mask= HA_STATE_NEXT_FOUND;
  DBUG_ENTER("mi_rnext");

  if ((inx = _mi_check_index(info,inx)) < 0)
    DBUG_RETURN(my_errno);
  flag=SEARCH_BIGGER;				/* Read next */
  if (info->lastpos == HA_OFFSET_ERROR && info->update & HA_STATE_PREV_FOUND)
    flag=0;					/* Read first */

  if (fast_mi_readinfo(info))
    DBUG_RETURN(my_errno);
  if (info->s->concurrent_insert)
    mysql_rwlock_rdlock(&info->s->key_root_lock[inx]);
  changed=_mi_test_if_changed(info);
  if (!flag)
  {
    switch(info->s->keyinfo[inx].key_alg){
#ifdef HAVE_RTREE_KEYS
    case HA_KEY_ALG_RTREE:
      error=rtree_get_first(info,inx,info->lastkey_length);
      break;
#endif
    case HA_KEY_ALG_BTREE:
    default:
      error=_mi_search_first(info,info->s->keyinfo+inx,
			   info->s->state.key_root[inx]);
      break;
    }
    /*
      "search first" failed. This means we have no pivot for
      "search next", or in other words MI_INFO::lastkey is
      likely uninitialized.

      Normally SQL layer would never request "search next" if
      "search first" failed. But HANDLER may do anything.

      As mi_rnext() without preceding mi_rkey()/mi_rfirst()
      equals to mi_rfirst(), we must restore original state
      as if failing mi_rfirst() was not called.
    */
    if (error)
      update_mask|= HA_STATE_PREV_FOUND;
  }
  else
  {
    switch (info->s->keyinfo[inx].key_alg) {
#ifdef HAVE_RTREE_KEYS
    case HA_KEY_ALG_RTREE:
      /*
	Note that rtree doesn't support that the table
	may be changed since last call, so we do need
	to skip rows inserted by other threads like in btree
      */
      error= rtree_get_next(info,inx,info->lastkey_length);
      break;
#endif
    case HA_KEY_ALG_BTREE:
    default:
      if (!changed)
	error= _mi_search_next(info,info->s->keyinfo+inx,info->lastkey,
			       info->lastkey_length,flag,
			       info->s->state.key_root[inx]);
      else
	error= _mi_search(info,info->s->keyinfo+inx,info->lastkey,
			  USE_WHOLE_KEY,flag, info->s->state.key_root[inx]);
    }
  }

  if (!error)
  {
    while ((info->s->concurrent_insert &&
            info->lastpos >= info->state->data_file_length) ||
           (info->index_cond_func &&
           (icp_res= mi_check_index_cond(info, inx, buf)) == ICP_NO_MATCH))
    {
      /*
        If we are at the last key on the key page, allow writers to
        access the index.
      */
      if (info->int_keypos >= info->int_maxpos &&
          mi_yield_and_check_if_killed(info, inx))
      {
        error= 1;
        break;
      }

      /* 
         Skip rows that are either inserted by other threads since
         we got a lock or do not match pushed index conditions
      */
      if  ((error=_mi_search_next(info,info->s->keyinfo+inx,
                                  info->lastkey,
                                  info->lastkey_length,
                                  SEARCH_BIGGER,
                                  info->s->state.key_root[inx])))
        break;
    }
  }
  
  if (info->s->concurrent_insert)
    mysql_rwlock_unlock(&info->s->key_root_lock[inx]);

	/* Don't clear if database-changed */
  info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
  info->update|= update_mask;

  if (error || icp_res != ICP_MATCH)
  {
    fast_mi_writeinfo(info);
    if (my_errno == HA_ERR_KEY_NOT_FOUND)
      my_errno=HA_ERR_END_OF_FILE;
  }
  else if (!buf)
  {
    fast_mi_writeinfo(info);
    DBUG_RETURN(info->lastpos==HA_OFFSET_ERROR ? my_errno : 0);
  }
  else if (!(*info->read_record)(info,info->lastpos,buf))
  {
    info->update|= HA_STATE_AKTIV;		/* Record is read */
    DBUG_RETURN(0);
  }
  DBUG_PRINT("error",("Got error: %d,  errno: %d",error, my_errno));
  DBUG_RETURN(my_errno);
} /* mi_rnext */