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 */
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 */
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 */
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?) */ }
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); }
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 */