Пример #1
0
int 
mi_rsame(MI_INFO * info, byte * record, int inx)
{
	DBUG_ENTER("mi_rsame");

	if (inx != -1 && !(((ulonglong) 1 << inx) & info->s->state.key_map)) {
		DBUG_RETURN(my_errno = HA_ERR_WRONG_INDEX);
	}
	if (info->lastpos == HA_OFFSET_ERROR || info->update & HA_STATE_DELETED) {
		DBUG_RETURN(my_errno = HA_ERR_KEY_NOT_FOUND);	/* No current record */
	}
	info->update &= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);

	/* Read row from data file */
	if (_mi_readinfo(info, F_RDLCK, 1))
		DBUG_RETURN(my_errno);

	if (inx >= 0) {
		info->lastinx = inx;
		info->lastkey_length = _mi_make_key(info, (uint) inx, info->lastkey, record,
						    info->lastpos);
		if (info->s->concurrent_insert)
			rw_rdlock(&info->s->key_root_lock[inx]);
		VOID(_mi_search(info, info->s->keyinfo + inx, info->lastkey, 0, SEARCH_SAME,
				info->s->state.key_root[inx]));
		if (info->s->concurrent_insert)
			rw_unlock(&info->s->key_root_lock[inx]);
	}
	if (!(*info->read_record) (info, info->lastpos, record))
		DBUG_RETURN(0);
	if (my_errno == HA_ERR_RECORD_DELETED)
		my_errno = HA_ERR_KEY_NOT_FOUND;
	DBUG_RETURN(my_errno);
}				/* mi_rsame */
Пример #2
0
int mi_delete_all_rows(MI_INFO *info)
{
  uint i;
  MYISAM_SHARE *share=info->s;
  MI_STATE_INFO *state=&share->state;
  DBUG_ENTER("mi_delete_all_rows");

  if (share->options & HA_OPTION_READ_ONLY_DATA)
  {
    DBUG_RETURN(my_errno=EACCES);
  }
  if (_mi_readinfo(info,F_WRLCK,1))
    DBUG_RETURN(my_errno);
  if (_mi_mark_file_changed(info))
    goto err;

  info->state->records=info->state->del=state->split=0;
  state->dellink = HA_OFFSET_ERROR;
  state->sortkey=  (ushort) ~0;
  info->state->key_file_length=share->base.keystart;
  info->state->data_file_length=0;
  info->state->empty=info->state->key_empty=0;
  info->state->checksum=0;

  for (i=share->base.max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH ; i-- ; )
    state->key_del[i]= HA_OFFSET_ERROR;
  for (i=0 ; i < share->base.keys ; i++)
    state->key_root[i]= HA_OFFSET_ERROR;

  myisam_log_command(MI_LOG_DELETE_ALL,info,(uchar*) 0,0,0);
  /*
    If we are using delayed keys or if the user has done changes to the tables
    since it was locked then there may be key blocks in the key cache
  */
  flush_key_blocks(share->key_cache, share->kfile, FLUSH_IGNORE_CHANGED);
#ifdef HAVE_MMAP
  if (share->file_map)
    mi_munmap_file(info);
#endif
  if (mysql_file_chsize(info->dfile, 0, 0, MYF(MY_WME)) ||
      mysql_file_chsize(share->kfile, share->base.keystart, 0, MYF(MY_WME)))
    goto err;
  (void) _mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE);
#ifdef HAVE_MMAP
  /* Map again */
  if (share->file_map)
    mi_dynmap_file(info, (my_off_t) 0);
#endif
  allow_break();			/* Allow SIGHUP & SIGINT */
  DBUG_RETURN(0);

err:
  {
    int save_errno=my_errno;
    (void) _mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE);
    info->update|=HA_STATE_WRITTEN;	/* Buffer changed */
    allow_break();			/* Allow SIGHUP & SIGINT */
    DBUG_RETURN(my_errno=save_errno);
  }
} /* mi_delete */
Пример #3
0
int
mi_rprev(MI_INFO * info, byte * buf, int inx)
{
    int		error     , changed;
    register uint	flag;
    MYISAM_SHARE   *share = info->s;
    DBUG_ENTER("mi_rprev");

    if ((inx = _mi_check_index(info, inx)) < 0)
        DBUG_RETURN(my_errno);
    flag = SEARCH_SMALLER;	/* Read previous */
    if (info->lastpos == HA_OFFSET_ERROR && info->update & HA_STATE_NEXT_FOUND)
        flag = 0;	/* Read last */

    if (_mi_readinfo(info, F_RDLCK, 1))
        DBUG_RETURN(my_errno);
    changed = _mi_test_if_changed(info);
    if (share->concurrent_insert)
        rw_rdlock(&share->key_root_lock[inx]);
    if (!flag)
        error = _mi_search_last(info, share->keyinfo + inx,
                                share->state.key_root[inx]);
    else if (!changed)
        error = _mi_search_next(info, share->keyinfo + inx, info->lastkey,
                                info->lastkey_length, flag,
                                share->state.key_root[inx]);
    else
        error = _mi_search(info, share->keyinfo + inx, info->lastkey,
                           info->lastkey_length, flag, share->state.key_root[inx]);

    if (!error) {
        while (info->lastpos >= info->state->data_file_length) {
            /*
             * Skip rows that are inserted by other threads since
             * we got a lock
             */
            if ((error = _mi_search_next(info, share->keyinfo + inx, info->lastkey,
                                         info->lastkey_length,
                                         SEARCH_SMALLER,
                                         share->state.key_root[inx])))
                break;
        }
    }
    if (share->concurrent_insert)
        rw_unlock(&share->key_root_lock[inx]);
    info->update &= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
    info->update |= HA_STATE_PREV_FOUND;
    if (error) {
        if (my_errno == HA_ERR_KEY_NOT_FOUND)
            my_errno = HA_ERR_END_OF_FILE;
    } else if (!buf) {
        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_RETURN(my_errno);
}				/* mi_rprev */
Пример #4
0
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?) */
}
Пример #5
0
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);
}
Пример #6
0
int 
mi_write(MI_INFO * info, byte * record)
{
	uint		i;
	int		save_errno;
	my_off_t	filepos;
	uchar          *buff;
	MYISAM_SHARE   *share = info->s;
	DBUG_ENTER("mi_write");
	DBUG_PRINT("enter", ("isam: %d  data: %d", info->s->kfile, info->dfile));

	if (share->options & HA_OPTION_READ_ONLY_DATA) {
		DBUG_RETURN(my_errno = EACCES);
	}
	if (_mi_readinfo(info, F_WRLCK, 1))
		DBUG_RETURN(my_errno);
	dont_break();		/* Dont allow SIGHUP or SIGINT */
#if !defined(NO_LOCKING) && defined(USE_RECORD_LOCK)
	if (!info->locked && my_lock(info->dfile, F_WRLCK, 0L, F_TO_EOF,
				   MYF(MY_SEEK_NOT_DONE) | info->lock_wait))
		goto err;
#endif
	filepos = ((share->state.dellink != HA_OFFSET_ERROR) ?
		   share->state.dellink :
		   info->state->data_file_length);

	if (share->base.reloc == (ha_rows) 1 &&
	    share->base.records == (ha_rows) 1 &&
	    info->state->records == (ha_rows) 1) {	/* System file */
		my_errno = HA_ERR_RECORD_FILE_FULL;
		goto err2;
	}
	if (info->state->key_file_length >= share->base.margin_key_file_length) {
		my_errno = HA_ERR_INDEX_FILE_FULL;
		goto err2;
	}
	if (_mi_mark_file_changed(info))
		goto err2;

	/* Calculate and check all unique constraints */
	for (i = 0; i < share->state.header.uniques; i++) {
		if (mi_check_unique(info, share->uniqueinfo + i, record,
			      mi_unique_hash(share->uniqueinfo + i, record),
				    HA_OFFSET_ERROR))
			goto err2;
	}

	/* Write all keys to indextree */

	buff = info->lastkey2;
	for (i = 0; i < share->base.keys; i++) {
		if (((ulonglong) 1 << i) & share->state.key_map) {
			if (share->concurrent_insert) {
				rw_wrlock(&share->key_root_lock[i]);
				share->keyinfo[i].version++;
			}
			if (share->keyinfo[i].flag & HA_FULLTEXT) {	/* SerG *//* SerG */
				if (_mi_ft_add(info, i, (char *)buff, record, filepos)) {	/* SerG *//* SerG */
					if (share->concurrent_insert)
						rw_unlock(&share->key_root_lock[i]);
					DBUG_PRINT("error", ("Got error: %d on write", my_errno));	/* SerG */
					goto err;	/* SerG */
				}	/* SerG */
			}
			 /* SerG */ 
			else {	/* SerG */
				uint		key_length = _mi_make_key(info, i, buff, record, filepos);
				if (_mi_ck_write(info, i, buff, key_length)) {
					if (share->concurrent_insert)
						rw_unlock(&share->key_root_lock[i]);
					DBUG_PRINT("error", ("Got error: %d on write", my_errno));
					goto err;
				}
			}
			if (share->concurrent_insert)
				rw_unlock(&share->key_root_lock[i]);
		}
	}
	if (share->calc_checksum)
		info->checksum = (*share->calc_checksum) (info, record);
	if (!(info->opt_flag & OPT_NO_ROWS)) {
		if ((*share->write_record) (info, record))
			goto err;
		share->state.checksum += info->checksum;
	}
	if (share->base.auto_key)
		update_auto_increment(info, record);
	info->update = (HA_STATE_CHANGED | HA_STATE_AKTIV | HA_STATE_WRITTEN |
			HA_STATE_ROW_CHANGED);
	info->state->records++;
	info->lastpos = filepos;
	myisam_log_record(MI_LOG_WRITE, info, record, filepos, 0);
	VOID(_mi_writeinfo(info, WRITEINFO_UPDATE_KEYFILE));
	allow_break();		/* Allow SIGHUP & SIGINT */
	DBUG_RETURN(0);

err:
	save_errno = my_errno;
	if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_RECORD_FILE_FULL) {
		info->errkey = (int)i;
		while (i-- > 0) {
			if (((ulonglong) 1 << i) & share->state.key_map) {
				if (share->concurrent_insert)
					rw_wrlock(&share->key_root_lock[i]);
				/*
				 * The following code block is for text
				 * searching by SerG
				 */
				if (share->keyinfo[i].flag & HA_FULLTEXT) {
					if (_mi_ft_del(info, i, (char *)buff, record, filepos)) {
						if (share->concurrent_insert)
							rw_unlock(&share->key_root_lock[i]);
						break;
					}
				} else {
					uint		key_length = _mi_make_key(info, i, buff, record, filepos);
					if (_mi_ck_delete(info, i, buff, key_length)) {
						if (share->concurrent_insert)
							rw_unlock(&share->key_root_lock[i]);
						break;
					}
				}
				if (share->concurrent_insert)
					rw_unlock(&share->key_root_lock[i]);
			}
		}
	} else
		mi_mark_crashed(info);
	info->update = (HA_STATE_CHANGED | HA_STATE_WRITTEN | HA_STATE_ROW_CHANGED);
	my_errno = save_errno;
err2:
	save_errno = my_errno;
	myisam_log_record(MI_LOG_WRITE, info, record, filepos, my_errno);
	VOID(_mi_writeinfo(info, WRITEINFO_UPDATE_KEYFILE));
	allow_break();		/* Allow SIGHUP & SIGINT */
	DBUG_RETURN(my_errno = save_errno);
}				/* mi_write */