int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves) { uint i; ulong length, block_length= 0; uchar *buff= NULL; MYISAM_SHARE* share= info->s; uint keys= share->state.header.keys; MI_KEYDEF *keyinfo= share->keyinfo; my_off_t key_file_length= share->state.state.key_file_length; my_off_t pos= share->base.keystart; DBUG_ENTER("mi_preload"); if (!keys || !mi_is_any_key_active(key_map) || key_file_length == pos) DBUG_RETURN(0); block_length= keyinfo[0].block_length; if (ignore_leaves) { /* Check whether all indexes use the same block size */ for (i= 1 ; i < keys ; i++) { if (keyinfo[i].block_length != block_length) DBUG_RETURN(my_errno= HA_ERR_NON_UNIQUE_BLOCK_SIZE); } } else block_length= share->key_cache->key_cache_block_size; length= info->preload_buff_size/block_length * block_length; set_if_bigger(length, block_length); if (!(buff= (uchar *) my_malloc(length, MYF(MY_WME)))) DBUG_RETURN(my_errno= HA_ERR_OUT_OF_MEM); if (flush_key_blocks(share->key_cache,share->kfile, FLUSH_RELEASE)) goto err; do { /* Read the next block of index file into the preload buffer */ if ((my_off_t) length > (key_file_length-pos)) length= (ulong) (key_file_length-pos); if (mysql_file_pread(share->kfile, (uchar*) buff, length, pos, MYF(MY_FAE|MY_FNABP))) goto err; if (ignore_leaves) { uchar *end= buff+length; do { if (mi_test_if_nod(buff)) { if (key_cache_insert(share->key_cache, share->kfile, pos, DFLT_INIT_HITS, (uchar*) buff, block_length)) goto err; } pos+= block_length; } while ((buff+= block_length) != end); buff= end-length; } else { if (key_cache_insert(share->key_cache, share->kfile, pos, DFLT_INIT_HITS, (uchar*) buff, length)) goto err; pos+= length; } } while (pos != key_file_length); my_free(buff); DBUG_RETURN(0); err: my_free(buff); DBUG_RETURN(my_errno= errno); }
my_bool _ma_read_cache(MARIA_HA *handler, IO_CACHE *info, uchar *buff, my_off_t pos, size_t length, uint flag) { size_t read_length,in_buff_length; my_off_t offset; uchar *in_buff_pos; DBUG_ENTER("_ma_read_cache"); if (pos < info->pos_in_file) { read_length=length; if ((my_off_t) read_length > (my_off_t) (info->pos_in_file-pos)) read_length=(uint) (info->pos_in_file-pos); info->seek_not_done=1; if (mysql_file_pread(info->file,buff,read_length,pos,MYF(MY_NABP))) DBUG_RETURN(1); if (!(length-=read_length)) DBUG_RETURN(0); pos+=read_length; buff+=read_length; } if (pos >= info->pos_in_file && (offset= (my_off_t) (pos - info->pos_in_file)) < (my_off_t) (info->read_end - info->request_pos)) { in_buff_pos=info->request_pos+(uint) offset; in_buff_length= MY_MIN(length,(size_t) (info->read_end-in_buff_pos)); memcpy(buff,info->request_pos+(uint) offset,(size_t) in_buff_length); if (!(length-=in_buff_length)) DBUG_RETURN(0); pos+=in_buff_length; buff+=in_buff_length; } else in_buff_length=0; if (flag & READING_NEXT) { if (pos != (info->pos_in_file + (uint) (info->read_end - info->request_pos))) { info->pos_in_file=pos; /* Force start here */ info->read_pos=info->read_end=info->request_pos; /* Everything used */ info->seek_not_done=1; } else info->read_pos=info->read_end; /* All block used */ if (!(*info->read_function)(info,buff,length)) DBUG_RETURN(0); read_length=info->error; } else { info->seek_not_done=1; if ((read_length=mysql_file_pread(info->file,buff,length,pos,MYF(0))) == length) DBUG_RETURN(0); } if (!(flag & READING_HEADER) || (int) read_length == -1 || read_length+in_buff_length < 3) { DBUG_PRINT("error", ("Error %d reading next-multi-part block (Got %d bytes)", my_errno, (int) read_length)); if (!my_errno || my_errno == HA_ERR_FILE_TOO_SHORT) { if (!handler->in_check_table) _ma_set_fatal_error(handler->s, HA_ERR_WRONG_IN_RECORD); else my_errno= HA_ERR_WRONG_IN_RECORD; } DBUG_RETURN(1); } bzero(buff+read_length,MARIA_BLOCK_INFO_HEADER_LENGTH - in_buff_length - read_length); DBUG_RETURN(0); } /* _ma_read_cache */