diff options
author | Raymond Lu <songyulu@hdfgroup.org> | 2006-10-19 22:35:45 (GMT) |
---|---|---|
committer | Raymond Lu <songyulu@hdfgroup.org> | 2006-10-19 22:35:45 (GMT) |
commit | 15135723d6f2e5d0d4bdb433ffacc9828a737c5b (patch) | |
tree | 04c47d7ee185097f4c039e7801555b79efa04451 | |
parent | 4c8e9ca84833a7e6adf610410edd9cc4067dea68 (diff) | |
download | hdf5-15135723d6f2e5d0d4bdb433ffacc9828a737c5b.zip hdf5-15135723d6f2e5d0d4bdb433ffacc9828a737c5b.tar.gz hdf5-15135723d6f2e5d0d4bdb433ffacc9828a737c5b.tar.bz2 |
[svn-r12788] Enable the algorithm of Direct driver to read data in fragment from file. If the application
requests large data from file, to avoid using too much of memory for copying data from library's
own aligned buffer to application's (unaligned) buffer, this step is done in fragment. The next
step checkin is to handle writing data in fragment.
-rw-r--r-- | src/H5FDdirect.c | 112 |
1 files changed, 76 insertions, 36 deletions
diff --git a/src/H5FDdirect.c b/src/H5FDdirect.c index b3b2b0f..0f95f7fb 100644 --- a/src/H5FDdirect.c +++ b/src/H5FDdirect.c @@ -860,11 +860,13 @@ H5FD_direct_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, ha { H5FD_direct_t *file = (H5FD_direct_t*)_file; ssize_t nbytes; - size_t alloc_size; - void *copy_buf, *p1, *p2; + size_t alloc_size, tmp_size; + void *copy_buf, *p1, *p2, *p3; hsize_t _boundary; hsize_t _fbsize; hsize_t _cbsize; + haddr_t copy_addr = addr; + hsize_t copy_size = size; herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5FD_direct_read, FAIL) @@ -891,6 +893,11 @@ H5FD_direct_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, ha * and aligned data first, then copy the data into memory buffer. */ if((addr%_fbsize==0) && (size%_fbsize==0) && ((haddr_t)buf%_boundary==0)) { + /* Seek to the correct location */ + if ((addr!=file->pos || OP_READ!=file->op) && + file_seek(file->fd, (file_offset_t)addr, SEEK_SET)<0) + HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position") + while (size>0) { do { nbytes = HDread(file->fd, buf, size); @@ -911,48 +918,76 @@ H5FD_direct_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, ha buf = (char*)buf + nbytes; } } else { - /* allocate memory needed for the Direct IO option. Make a bigger - * buffer for aligned I/O. */ - alloc_size = (size / _fbsize + 1) * _fbsize + _fbsize; + /* allocate memory needed for the Direct IO option up to the maximal + * copy buffer size. Make a bigger buffer for aligned I/O if size is + * smaller than maximal copy buffer. */ + if(size < _cbsize) + alloc_size = (size / _fbsize + 1) * _fbsize + _fbsize; + else + alloc_size = _cbsize; if (posix_memalign(©_buf, _boundary, alloc_size) != 0) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "posix_memalign failed") - memset(copy_buf, 0, alloc_size); /* look for the aligned position for reading the data */ - if(file_seek(file->fd, (file_offset_t)(addr - addr % _fbsize), SEEK_SET) < 0) + if(file_seek(file->fd, (file_offset_t)(copy_addr - copy_addr % _fbsize), SEEK_SET) < 0) HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position") /* - * Read the aligned data in file first, being careful of interrupted system calls, - * partial results, and the end of the file. + * Read the aligned data in file into aligned buffer first, then copy the data + * into the final buffer. If the data size is bigger than maximal copy buffer + * size, do the reading by segment (the outer while loop). If not, do one step + * reading. */ - p1 = copy_buf; - while(alloc_size > 0) { - do { - nbytes = HDread(file->fd, p1, alloc_size); - } while(-1==nbytes && EINTR==errno); - - if (-1==nbytes) /* error */ - HSYS_GOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file read failed") - if (0==nbytes) { - /* end of file but not end of format address space */ - break; - } else { - assert(nbytes>0); - assert((size_t)nbytes<=alloc_size); - H5_CHECK_OVERFLOW(nbytes,ssize_t,size_t); - H5_CHECK_OVERFLOW(nbytes,ssize_t,haddr_t); - alloc_size -= (size_t)nbytes; - p1 = (unsigned char*)p1 + nbytes; - } - } - - /*look for the right position to copy the data and copy the data - *to the original buffer.*/ - p2 = (unsigned char*)copy_buf + addr % _fbsize; - memcpy(buf, p2, size); - - /*update address and buffer*/ + p3 = buf; + do { + /* Read the aligned data in file first, being careful of interrupted system calls, + * partial results, and the end of the file. */ + memset(copy_buf, 0, alloc_size); + p1 = copy_buf; + tmp_size = alloc_size; + while(tmp_size > 0) { + do { + nbytes = HDread(file->fd, p1, tmp_size); + } while(-1==nbytes && EINTR==errno); + + if (-1==nbytes) /* error */ + HSYS_GOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file read failed") + if (0==nbytes) { + /* end of file but not end of format address space */ + break; + } else { + assert(nbytes>0); + assert((size_t)nbytes<=tmp_size); + H5_CHECK_OVERFLOW(nbytes,ssize_t,size_t); + H5_CHECK_OVERFLOW(nbytes,ssize_t,haddr_t); + tmp_size -= (size_t)nbytes; + p1 = (unsigned char*)p1 + nbytes; + } + } + + /* look for the right position and copy the data to the original buffer. + * Consider all possible situations here: file address is not aligned on + * file block size; the end of data address is not aligned; the end of data + * address is aligned; data size is smaller or bigger than maximal copy size.*/ + p2 = (unsigned char*)copy_buf + copy_addr % _fbsize; + if(size < _cbsize) + memcpy(p3, p2, size); + else if(size >= _cbsize && copy_size <= alloc_size) + memcpy(p3, p2, copy_size); + else if(size >= _cbsize && copy_size > alloc_size) { + memcpy(p3, p2, (alloc_size - copy_addr % _fbsize)); + p3 = (unsigned char*)p3 + (alloc_size - copy_addr % _fbsize); + } + + /* update the size and address of data being read. */ + if(copy_size > (alloc_size - copy_addr % _fbsize)) + copy_size -= (alloc_size - copy_addr % _fbsize); + else + copy_size = 0; + copy_addr += (alloc_size - copy_addr % _fbsize); + } while (copy_size > 0); + + /*Final step: update address and buffer*/ addr += (haddr_t)size; buf = (unsigned char*)buf + size; @@ -1030,6 +1065,11 @@ H5FD_direct_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, h * data out. */ if((addr%_fbsize==0) && (size%_fbsize==0) && ((haddr_t)buf%_boundary==0)) { + /* Seek to the correct location */ + if ((addr!=file->pos || OP_WRITE!=file->op) && + file_seek(file->fd, (file_offset_t)addr, SEEK_SET)<0) + HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position") + while (size>0) { do { nbytes = HDwrite(file->fd, buf, size); |