int nisam_is_changed(N_INFO *info) { int result; DBUG_ENTER("nisam_is_changed"); #ifndef NO_LOCKING if (_nisam_readinfo(info,F_RDLCK,1)) DBUG_RETURN(-1); VOID(_nisam_writeinfo(info,0)); #endif result=(int) info->data_changed; info->data_changed=0; DBUG_PRINT("exit",("result: %d",result)); DBUG_RETURN(result); }
int nisam_info(N_INFO *info, register N_ISAMINFO *x, int flag) { struct stat state; ISAM_SHARE *share=info->s; DBUG_ENTER("nisam_info"); x->recpos = info->lastpos; if (flag & (HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE | HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK)) { #ifndef NO_LOCKING if (!(flag & HA_STATUS_NO_LOCK)) { pthread_mutex_lock(&share->intern_lock); VOID(_nisam_readinfo(info,F_RDLCK,0)); VOID(_nisam_writeinfo(info,0)); pthread_mutex_unlock(&share->intern_lock); } #endif x->records = share->state.records; x->deleted = share->state.del; x->delete_length= share->state.empty; x->keys = share->state.keys; x->reclength = share->base.reclength; x->mean_reclength= share->state.records ? (share->state.data_file_length-share->state.empty)/share->state.records : share->min_pack_length; x->data_file_length=share->state.data_file_length; x->max_data_file_length=share->base.max_data_file_length; x->index_file_length=share->state.key_file_length; x->max_index_file_length=share->base.max_key_file_length; x->filenr = info->dfile; x->errkey = info->errkey; x->dupp_key_pos= info->dupp_key_pos; x->options = share->base.options; x->create_time=share->base.create_time; x->isamchk_time=share->base.isamchk_time; x->rec_per_key=share->base.rec_per_key; if ((flag & HA_STATUS_TIME) && !fstat(info->dfile,&state)) x->update_time=state.st_mtime; else x->update_time=0; x->sortkey= -1; /* No clustering */ } DBUG_RETURN(0); } /* nisam_info */
int nisam_rprev(N_INFO *info, byte *buf, int inx) { int error,changed; register uint flag; DBUG_ENTER("nisam_rprev"); if ((inx = _nisam_check_index(info,inx)) < 0) DBUG_RETURN(-1); flag=SEARCH_SMALLER; /* Read previous */ if (info->lastpos == NI_POS_ERROR && info->update & HA_STATE_NEXT_FOUND) flag=0; /* Read last */ #ifndef NO_LOCKING if (_nisam_readinfo(info,F_RDLCK,1)) DBUG_RETURN(-1); #endif changed=_nisam_test_if_changed(info); if (!flag) error=_nisam_search_last(info,info->s->keyinfo+inx,info->s->state.key_root[inx]); else if (!changed) error=_nisam_search_next(info,info->s->keyinfo+inx,info->lastkey,flag, info->s->state.key_root[inx]); else error=_nisam_search(info,info->s->keyinfo+inx,info->lastkey,0,flag, info->s->state.key_root[inx]); info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_BUFF_SAVED); info->update|= HA_STATE_PREV_FOUND; if (error && my_errno == HA_ERR_KEY_NOT_FOUND) my_errno=HA_ERR_END_OF_FILE; if ((*info->read_record)(info,info->lastpos,buf) >=0) { info->update|= HA_STATE_AKTIV; /* Record is read */ DBUG_RETURN(0); } DBUG_RETURN(-1); } /* nisam_rprev */
int nisam_panic(enum ha_panic_function flag) { int error=0; LIST *list_element,*next_open; N_INFO *info; DBUG_ENTER("nisam_panic"); pthread_mutex_lock(&THR_LOCK_isam); for (list_element=nisam_open_list ; list_element ; list_element=next_open) { next_open=list_element->next; /* Save if close */ info=(N_INFO*) list_element->data; switch (flag) { case HA_PANIC_CLOSE: pthread_mutex_unlock(&THR_LOCK_isam); /* Not exactly right... */ if (nisam_close(info)) error=my_errno; pthread_mutex_lock(&THR_LOCK_isam); break; case HA_PANIC_WRITE: /* Do this to free databases */ #ifdef CANT_OPEN_FILES_TWICE if (info->s->base.options & HA_OPTION_READ_ONLY_DATA) break; #endif if (flush_key_blocks(info->s->kfile,FLUSH_RELEASE)) error=my_errno; if (info->opt_flag & WRITE_CACHE_USED) if (flush_io_cache(&info->rec_cache)) error=my_errno; if (info->opt_flag & READ_CACHE_USED) { if (flush_io_cache(&info->rec_cache)) error=my_errno; reinit_io_cache(&info->rec_cache,READ_CACHE,0, (pbool) (info->lock_type != F_UNLCK),1); } #ifndef NO_LOCKING if (info->lock_type != F_UNLCK && ! info->was_locked) { info->was_locked=info->lock_type; if (nisam_lock_database(info,F_UNLCK)) error=my_errno; } #else { int save_status=info->s->w_locks; /* Only w_locks! */ info->s->w_locks=0; if (_nisam_writeinfo(info, test(info->update & HA_STATE_CHANGED))) error=my_errno; info->s->w_locks=save_status; info->update&= ~HA_STATE_CHANGED; /* Not changed */ } #endif /* NO_LOCKING */ #ifdef CANT_OPEN_FILES_TWICE if (info->s->kfile >= 0 && my_close(info->s->kfile,MYF(0))) error = my_errno; if (info->dfile >= 0 && my_close(info->dfile,MYF(0))) error = my_errno; info->s->kfile=info->dfile= -1; /* Files aren't open anymore */ break; #endif case HA_PANIC_READ: /* Restore to before WRITE */ #ifdef CANT_OPEN_FILES_TWICE { /* Open closed files */ char name_buff[FN_REFLEN]; if (info->s->kfile < 0) if ((info->s->kfile= my_open(fn_format(name_buff,info->filename,"", N_NAME_IEXT,4),info->mode, MYF(MY_WME))) < 0) error = my_errno; if (info->dfile < 0) { if ((info->dfile= my_open(fn_format(name_buff,info->filename,"", N_NAME_DEXT,4),info->mode, MYF(MY_WME))) < 0) error = my_errno; info->rec_cache.file=info->dfile; } } #endif #ifndef NO_LOCKING if (info->was_locked) { if (nisam_lock_database(info, info->was_locked)) error=my_errno; info->was_locked=0; } #else { int lock_type,w_locks; lock_type=info->lock_type ; w_locks=info->s->w_locks; info->lock_type=0; info->s->w_locks=0; if (_nisam_readinfo(info,0,1)) /* Read changed data */ error=my_errno; info->lock_type=lock_type; info->s->w_locks=w_locks; } /* Don't use buffer when doing next */ info->update|=HA_STATE_WRITTEN; #endif /* NO_LOCKING */ break; } } if (flag == HA_PANIC_CLOSE) VOID(nisam_log(0)); /* Close log if neaded */ pthread_mutex_unlock(&THR_LOCK_isam); if (!error) DBUG_RETURN(0); my_errno=error; DBUG_RETURN(-1); } /* nisam_panic */
int nisam_update(register N_INFO *info, const byte *oldrec, const byte *newrec) { int flag,key_changed,save_errno; reg3 ulong pos; uint i,length; uchar old_key[N_MAX_KEY_BUFF],*new_key; DBUG_ENTER("nisam_update"); LINT_INIT(save_errno); if (!(info->update & HA_STATE_AKTIV)) { my_errno=HA_ERR_KEY_NOT_FOUND; DBUG_RETURN(-1); } if (info->s->base.options & HA_OPTION_READ_ONLY_DATA) { my_errno=EACCES; DBUG_RETURN(-1); } pos=info->lastpos; #ifndef NO_LOCKING if (_nisam_readinfo(info,F_WRLCK,1)) DBUG_RETURN(-1); #endif if ((*info->s->compare_record)(info,oldrec)) { save_errno=my_errno; goto err_end; /* Record has changed */ } if (info->s->state.key_file_length >= info->s->base.max_key_file_length - info->s->blocksize* INDEX_BLOCK_MARGIN *info->s->state.keys) { save_errno=HA_ERR_INDEX_FILE_FULL; goto err_end; } /* Flyttar de element i isamfilen som m}ste flyttas */ new_key=info->lastkey+info->s->base.max_key_length; key_changed=HA_STATE_KEY_CHANGED; /* We changed current database */ /* Remove key that didn't change */ for (i=0 ; i < info->s->state.keys ; i++) { length=_nisam_make_key(info,i,new_key,newrec,pos); if (length != _nisam_make_key(info,i,old_key,oldrec,pos) || memcmp((byte*) old_key,(byte*) new_key,length)) { if ((int) i == info->lastinx) key_changed|=HA_STATE_WRITTEN; /* Mark that keyfile changed */ if (_nisam_ck_delete(info,i,old_key)) goto err; if (_nisam_ck_write(info,i,new_key)) goto err; } } if ((*info->s->update_record)(info,pos,newrec)) goto err; info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_AKTIV | key_changed); nisam_log_record(LOG_UPDATE,info,newrec,info->lastpos,0); VOID(_nisam_writeinfo(info,test(key_changed))); allow_break(); /* Allow SIGHUP & SIGINT */ DBUG_RETURN(0); err: DBUG_PRINT("error",("key: %d errno: %d",i,my_errno)); save_errno=my_errno; if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_RECORD_FILE_FULL) { info->errkey= (int) i; flag=0; do { length=_nisam_make_key(info,i,new_key,newrec,pos); if (length != _nisam_make_key(info,i,old_key,oldrec,pos) || memcmp((byte*) old_key,(byte*) new_key,length)) { if ((flag++ && _nisam_ck_delete(info,i,new_key)) || _nisam_ck_write(info,i,old_key)) break; } } while (i-- != 0); } info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_AKTIV | key_changed); err_end: nisam_log_record(LOG_UPDATE,info,newrec,info->lastpos,save_errno); VOID(_nisam_writeinfo(info,1)); allow_break(); /* Allow SIGHUP & SIGINT */ my_errno=(save_errno == HA_ERR_KEY_NOT_FOUND) ? HA_ERR_CRASHED : save_errno; DBUG_RETURN(-1); } /* nisam_update */
int nisam_write(N_INFO *info, const byte *record) { uint i; ulong filepos; uchar *buff; DBUG_ENTER("nisam_write"); DBUG_PRINT("enter",("isam: %d data: %d",info->s->kfile,info->dfile)); if (info->s->base.options & HA_OPTION_READ_ONLY_DATA) { my_errno=EACCES; DBUG_RETURN(-1); } #ifndef NO_LOCKING if (_nisam_readinfo(info,F_WRLCK,1)) DBUG_RETURN(-1); #endif 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= ((info->s->state.dellink != NI_POS_ERROR) ? info->s->state.dellink : info->s->state.data_file_length); if (info->s->base.reloc == 1L && info->s->base.records == 1L && info->s->state.records == 1L) { /* System file */ my_errno=HA_ERR_RECORD_FILE_FULL; goto err2; } if (info->s->state.key_file_length >= info->s->base.max_key_file_length - info->s->blocksize* INDEX_BLOCK_MARGIN *info->s->state.keys) { my_errno=HA_ERR_INDEX_FILE_FULL; goto err2; } /* Write all keys to indextree */ buff=info->lastkey+info->s->base.max_key_length; for (i=0 ; i < info->s->state.keys ; i++) { VOID(_nisam_make_key(info,i,buff,record,filepos)); if (_nisam_ck_write(info,i,buff)) goto err; } if ((*info->s->write_record)(info,record)) goto err; info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED |HA_STATE_AKTIV | HA_STATE_WRITTEN); info->s->state.records++; info->lastpos=filepos; nisam_log_record(LOG_WRITE,info,record,filepos,0); VOID(_nisam_writeinfo(info,1)); allow_break(); /* Allow SIGHUP & SIGINT */ DBUG_RETURN(0); err: if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_RECORD_FILE_FULL) { info->errkey= (int) i; while ( i-- > 0) { VOID(_nisam_make_key(info,i,buff,record,filepos)); if (_nisam_ck_delete(info,i,buff)) break; } } info->update=(HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_WRITTEN); err2: nisam_log_record(LOG_WRITE,info,record,filepos,my_errno); VOID(_nisam_writeinfo(info,1)); allow_break(); /* Allow SIGHUP & SIGINT */ DBUG_RETURN(-1); } /* nisam_write */
int _nisam_read_rnd_static_record(N_INFO *info, byte *buf, register ulong filepos, int skipp_deleted_blocks) { int locked,error,cache_read; uint cache_length; ISAM_SHARE *share=info->s; DBUG_ENTER("_nisam_read_rnd_static_record"); cache_read=0; LINT_INIT(cache_length); if (info->opt_flag & WRITE_CACHE_USED && (info->rec_cache.pos_in_file <= filepos || skipp_deleted_blocks) && flush_io_cache(&info->rec_cache)) DBUG_RETURN(-1); if (info->opt_flag & READ_CACHE_USED) { /* Cash in use */ if (filepos == my_b_tell(&info->rec_cache) && (skipp_deleted_blocks || !filepos)) { cache_read=1; /* Read record using cache */ cache_length=(uint) (info->rec_cache.rc_end - info->rec_cache.rc_pos); } else info->rec_cache.seek_not_done=1; /* Filepos is changed */ } #ifndef NO_LOCKING locked=0; if (info->lock_type == F_UNLCK) { if (filepos >= share->state.data_file_length) { /* Test if new records */ if (_nisam_readinfo(info,F_RDLCK,0)) DBUG_RETURN(-1); locked=1; } else { /* We don't nead new info */ #ifndef UNSAFE_LOCKING if ((! cache_read || share->base.reclength > cache_length) && share->r_locks == 0 && share->w_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(-1); locked=1; } #else info->tmp_lock_type=F_RDLCK; #endif } } #endif if (filepos >= share->state.data_file_length) { #ifndef NO_LOCKING DBUG_PRINT("test",("filepos: %ld (%ld) records: %ld del: %ld", filepos/share->base.reclength,filepos, share->state.records, share->state.del)); VOID(_nisam_writeinfo(info,0)); #endif my_errno=HA_ERR_END_OF_FILE; DBUG_RETURN(-1); } info->lastpos= filepos; info->nextpos= filepos+share->base.reclength; if (! cache_read) /* No cacheing */ { error=_nisam_read_static_record(info,filepos,buf); if (error > 0) my_errno=HA_ERR_RECORD_DELETED; DBUG_RETURN(error); } /* Read record with cacheing */ error=my_b_read(&info->rec_cache,(byte*) buf,share->base.reclength); #ifndef NO_LOCKING if (locked) VOID(_nisam_writeinfo(info,0)); /* Unlock keyfile */ #endif if (!error) { if (!buf[0]) { /* Record is removed */ my_errno=HA_ERR_RECORD_DELETED; DBUG_RETURN(1); } /* Found and may be updated */ info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED; DBUG_RETURN(0); } if (info->rec_cache.error != -1 || my_errno == 0) my_errno=HA_ERR_WRONG_IN_RECORD; DBUG_RETURN(-1); /* Something wrong (EOF?) */ }