545
* Read from the st_io_cache into a buffer and feed asynchronously from disk when needed.
547
* @param info st_io_cache pointer
548
* @param Buffer Buffer to retrieve count bytes from file
549
* @param Count Number of bytes to read into Buffer
551
* @retval -1 An error has occurred; errno is set.
553
* @retval 1 An error has occurred; st_io_cache to error state.
555
int _my_b_async_read(st_io_cache *info, unsigned char *Buffer, size_t Count)
557
size_t length_local,read_length,diff_length,left_length,use_length,org_Count;
559
my_off_t next_pos_in_file;
560
unsigned char *read_buffer;
562
memcpy(Buffer,info->read_pos,
563
(left_length= (size_t) (info->read_end-info->read_pos)));
569
{ /* wait for read block */
570
info->inited=0; /* No more block to read */
571
my_aiowait(&info->aio_result); /* Wait for outstanding req */
572
if (info->aio_result.result.aio_errno)
574
if (info->myflags & MY_WME)
575
my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG),
576
my_filename(info->file),
577
info->aio_result.result.aio_errno);
578
errno=info->aio_result.result.aio_errno;
582
if (! (read_length= (size_t) info->aio_result.result.aio_return) ||
583
read_length == (size_t) -1)
585
errno=0; /* For testing */
586
info->error= (read_length == (size_t) -1 ? -1 :
587
(int) (read_length+left_length));
590
info->pos_in_file+= (size_t) (info->read_end - info->request_pos);
592
if (info->request_pos != info->buffer)
593
info->request_pos=info->buffer;
595
info->request_pos=info->buffer+info->read_length;
596
info->read_pos=info->request_pos;
597
next_pos_in_file=info->aio_read_pos+read_length;
599
/* Check if pos_in_file is changed
600
(_ni_read_cache may have skipped some bytes) */
602
if (info->aio_read_pos < info->pos_in_file)
603
{ /* Fix if skipped bytes */
604
if (info->aio_read_pos + read_length < info->pos_in_file)
606
read_length=0; /* Skip block */
607
next_pos_in_file=info->pos_in_file;
611
my_off_t offset= (info->pos_in_file - info->aio_read_pos);
612
info->pos_in_file=info->aio_read_pos; /* Whe are here */
613
info->read_pos=info->request_pos+offset;
614
read_length-=offset; /* Bytes left from read_pos */
617
/* Copy found bytes to buffer */
618
length_local=min(Count,read_length);
619
memcpy(Buffer,info->read_pos,(size_t) length_local);
620
Buffer+=length_local;
622
left_length+=length_local;
623
info->read_end=info->rc_pos+read_length;
624
info->read_pos+=length_local;
627
next_pos_in_file=(info->pos_in_file+ (size_t)
628
(info->read_end - info->request_pos));
630
/* If reading large blocks, or first read or read with skip */
633
if (next_pos_in_file == info->end_of_file)
635
info->error=(int) (read_length+left_length);
639
if (lseek(info->file,next_pos_in_file,SEEK_SET) == MY_FILEPOS_ERROR)
645
read_length=IO_SIZE*2- (size_t) (next_pos_in_file & (IO_SIZE-1));
646
if (Count < read_length)
647
{ /* Small block, read to cache */
648
if ((read_length=my_read(info->file,info->request_pos,
649
read_length, info->myflags)) == (size_t) -1)
650
return info->error= -1;
651
use_length=min(Count,read_length);
652
memcpy(Buffer,info->request_pos,(size_t) use_length);
653
info->read_pos=info->request_pos+Count;
654
info->read_end=info->request_pos+read_length;
655
info->pos_in_file=next_pos_in_file; /* Start of block in cache */
656
next_pos_in_file+=read_length;
658
if (Count != use_length)
659
{ /* Didn't find hole block */
660
if (info->myflags & (MY_WME | MY_FAE | MY_FNABP) && Count != org_Count)
661
my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG),
662
my_filename(info->file),errno);
663
info->error=(int) (read_length+left_length);
668
{ /* Big block, don't cache it */
669
if ((read_length= my_read(info->file,Buffer, Count,info->myflags))
672
info->error= read_length == (size_t) -1 ? -1 : read_length+left_length;
675
info->read_pos=info->read_end=info->request_pos;
676
info->pos_in_file=(next_pos_in_file+=Count);
680
/* Read next block with asyncronic io */
681
diff_length=(next_pos_in_file & (IO_SIZE-1));
682
max_length= info->read_length - diff_length;
683
if (max_length > info->end_of_file - next_pos_in_file)
684
max_length= (size_t) (info->end_of_file - next_pos_in_file);
686
if (info->request_pos != info->buffer)
687
read_buffer=info->buffer;
689
read_buffer=info->buffer+info->read_length;
690
info->aio_read_pos=next_pos_in_file;
693
info->aio_result.result.aio_errno=AIO_INPROGRESS; /* Marker for test */
694
if (aioread(info->file,read_buffer, max_length,
695
(my_off_t) next_pos_in_file,SEEK_SET,
696
&info->aio_result.result))
697
{ /* Skip async io */
699
if (info->request_pos != info->buffer)
701
memmove(info->buffer, info->request_pos,
702
(size_t) (info->read_end - info->read_pos));
703
info->request_pos=info->buffer;
704
info->read_pos-=info->read_length;
705
info->read_end-=info->read_length;
707
info->read_length=info->buffer_length; /* Use hole buffer */
708
info->read_function=_my_b_read; /* Use normal IO_READ next */
711
info->inited=info->aio_result.pending=1;
713
return 0; /* Block read, async in use */
714
} /* _my_b_async_read */
720
492
* Read one byte when buffer is empty