From 0f040c40f0b8759ea7af6b2dcbf6bb75e92e34dd Mon Sep 17 00:00:00 2001 From: Raymond Lu Date: Thu, 26 Oct 2006 21:41:19 -0500 Subject: [svn-r12820] Added fragmental copy buffer to H5FD_direct_write. This buffer size is set through H5Pset_fapl_direct. It's been added to H5FD_direct_read in the previous checkin. Still, a test is needed at later checkin. --- src/H5FDdirect.c | 218 +++++++++++++++++++++++++++++++++---------------------- src/H5FDdirect.h | 10 +-- test/h5test.c | 2 +- test/vfd.c | 8 +- 4 files changed, 141 insertions(+), 97 deletions(-) diff --git a/src/H5FDdirect.c b/src/H5FDdirect.c index 93a64f5..bf826aa 100644 --- a/src/H5FDdirect.c +++ b/src/H5FDdirect.c @@ -50,9 +50,9 @@ static hid_t H5FD_DIRECT_g = 0; /* Driver-specific file access properties */ typedef struct H5FD_direct_fapl_t { - hsize_t mboundary; /* Memory boundary for alignment */ - hsize_t fbsize; /* File system block size */ - hsize_t cbsize; /* Maximal buffer size for copying user data */ + size_t mboundary; /* Memory boundary for alignment */ + size_t fbsize; /* File system block size */ + size_t cbsize; /* Maximal buffer size for copying user data */ } H5FD_direct_fapl_t; /* @@ -306,7 +306,7 @@ H5FD_direct_term(void) *------------------------------------------------------------------------- */ herr_t -H5Pset_fapl_direct(hid_t fapl_id, hsize_t boundary, hsize_t block_size, hsize_t cbuf_size) +H5Pset_fapl_direct(hid_t fapl_id, size_t boundary, size_t block_size, size_t cbuf_size) { H5P_genplist_t *plist; /* Property list pointer */ H5FD_direct_fapl_t fa; @@ -360,8 +360,8 @@ done: *------------------------------------------------------------------------- */ herr_t -H5Pget_fapl_direct(hid_t fapl_id, hsize_t *boundary/*out*/, hsize_t *block_size/*out*/, - hsize_t *cbuf_size/*out*/) +H5Pget_fapl_direct(hid_t fapl_id, size_t *boundary/*out*/, size_t *block_size/*out*/, + size_t *cbuf_size/*out*/) { H5FD_direct_fapl_t *fa; H5P_genplist_t *plist; /* Property list pointer */ @@ -861,13 +861,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, tmp_size; + size_t alloc_size, dup_size; void *copy_buf, *p1, *p2, *p3; - hsize_t _boundary; - hsize_t _fbsize; - hsize_t _cbsize; + size_t _boundary; + size_t _fbsize; + size_t _cbsize; haddr_t copy_addr = addr; - hsize_t copy_size = size; + size_t copy_size = size; herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5FD_direct_read, FAIL) @@ -893,7 +893,7 @@ H5FD_direct_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, ha /* if the data is aligned, read it directly from the file. If not, read a bigger * and aligned data first, then copy the data into memory buffer. */ - if((addr%_fbsize==0) && (size%_fbsize==0) && ((haddr_t)buf%_boundary==0)) { + if((addr%_fbsize==0) && (size%_fbsize==0) && ((size_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) @@ -945,10 +945,10 @@ H5FD_direct_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, ha * 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) { + dup_size = alloc_size; + while(dup_size > 0) { do { - nbytes = HDread(file->fd, p1, tmp_size); + nbytes = HDread(file->fd, p1, dup_size); } while(-1==nbytes && EINTR==errno); if (-1==nbytes) /* error */ @@ -958,10 +958,10 @@ H5FD_direct_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, ha break; } else { assert(nbytes>0); - assert((size_t)nbytes<=tmp_size); + assert((size_t)nbytes<=dup_size); H5_CHECK_OVERFLOW(nbytes,ssize_t,size_t); H5_CHECK_OVERFLOW(nbytes,ssize_t,haddr_t); - tmp_size -= (size_t)nbytes; + dup_size -= (size_t)nbytes; p1 = (unsigned char*)p1 + nbytes; } } @@ -970,29 +970,30 @@ H5FD_direct_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, ha * 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; + p2 = (unsigned char*)copy_buf + (size_t)(copy_addr % _fbsize); if(size < _cbsize) memcpy(p3, p2, size); - else if(size >= _cbsize && copy_size <= alloc_size) + else if(size >= _cbsize && copy_size <= (alloc_size-(size_t)(copy_addr%_fbsize))) 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); + else if(size >= _cbsize && copy_size > (alloc_size-(size_t)(copy_addr%_fbsize))) { + memcpy(p3, p2, (alloc_size - (size_t)(copy_addr % _fbsize))); + p3 = (unsigned char*)p3 + (alloc_size - (size_t)(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); + if(copy_size > (alloc_size - (size_t)(copy_addr % _fbsize))) + copy_size -= (alloc_size - (size_t)(copy_addr % _fbsize)); else copy_size = 0; - copy_addr += (alloc_size - copy_addr % _fbsize); + copy_addr += (alloc_size - (size_t)(copy_addr % _fbsize)); } while (copy_size > 0); /*Final step: update address and buffer*/ addr += (haddr_t)size; buf = (unsigned char*)buf + size; - HDfree(copy_buf); + if(copy_buf) + HDfree(copy_buf); } /* Update current position */ @@ -1035,10 +1036,12 @@ H5FD_direct_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, h H5FD_direct_t *file = (H5FD_direct_t*)_file; ssize_t nbytes; size_t alloc_size, dup_size; - void *copy_buf, *p1, *p2; - hsize_t _boundary; - hsize_t _fbsize; - hsize_t _cbsize; + void *copy_buf, *p1, *p2, *p3; + size_t _boundary; + size_t _fbsize; + size_t _cbsize; + haddr_t copy_addr = addr; + size_t copy_size = size; herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5FD_direct_write, FAIL) @@ -1065,7 +1068,7 @@ H5FD_direct_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, h * the aligned data first, update buffer with user data, then write the * data out. */ - if((addr%_fbsize==0) && (size%_fbsize==0) && ((haddr_t)buf%_boundary==0)) { + if((addr%_fbsize==0) && (size%_fbsize==0) && ((size_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) @@ -1086,78 +1089,119 @@ H5FD_direct_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, h buf = (const char*)buf + nbytes; } } else { - /* allocate memory needed for the Direct IO option. Make a - * bigger buffer for aligned I/O + /* 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. */ - alloc_size = (size / _fbsize + 1) * _fbsize + _fbsize; + if(size < _cbsize) + alloc_size = (size / _fbsize + 1) * _fbsize + _fbsize; + else + alloc_size = _cbsize; +/*printf("alloc_size=%ld, size=%ld, _fbsize=%ld, _cbsize=%ld\n", alloc_size, size, _fbsize, +_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 right 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 first, being careful of interrupted system calls, - * partial results, and the end of the file. - */ - p2 = copy_buf; - dup_size = alloc_size; - while(dup_size > 0) { - do { - nbytes = read(file->fd, p2, dup_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<=dup_size); - H5_CHECK_OVERFLOW(nbytes,ssize_t,size_t); - H5_CHECK_OVERFLOW(nbytes,ssize_t,haddr_t); - dup_size -= (size_t)nbytes; - p2 = (unsigned char*)p2 + nbytes; + p3 = buf; + do { + /* + * Read the aligned data first if the aligned region doesn't fall entirely in + * the range to be writen. Be careful of interrupted system calls, partial + * results, and the end of the file. + */ + memset(copy_buf, 0, alloc_size); + p2 = copy_buf; + dup_size = alloc_size; + if(copy_addr <= addr || (copy_addr + alloc_size) >= (addr + size)) { + while(dup_size > 0) { + do { + nbytes = read(file->fd, p2, dup_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<=dup_size); + H5_CHECK_OVERFLOW(nbytes,ssize_t,size_t); + H5_CHECK_OVERFLOW(nbytes,ssize_t,haddr_t); + dup_size -= (size_t)nbytes; + p2 = (unsigned char*)p2 + nbytes; + } + } } - } - /*append or copy the data to be written to the aligned buffer.*/ - p1 = (unsigned char*)copy_buf + addr % _fbsize; - memcpy(p1, buf, size); + /* look for the right position and append or copy the data to be written to + * the aligned 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. + */ + p1 = (unsigned char*)copy_buf + (size_t)(copy_addr % _fbsize); + if(size < _cbsize) + memcpy(p1, p3, size); + else if(size >= _cbsize && copy_size <= (alloc_size-(size_t)(copy_addr%_fbsize))) { +/*printf("copy_size=%d, alloc_size=%d, size=%d, copy_addr%_fbsize=%ld\n", copy_size, alloc_size, +size, copy_addr%_fbsize);*/ + memcpy(p1, p3, copy_size); + }else if(size >= _cbsize && copy_size > (alloc_size-(size_t)(copy_addr%_fbsize))) { + memcpy(p1, p3, (alloc_size - (size_t)(copy_addr % _fbsize))); + p3 = (unsigned char*)p3 + (alloc_size - (size_t)(copy_addr % _fbsize)); + } + + /*look for the aligned position for writing the data*/ + 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") + + /* + * Write the data, being careful of interrupted system calls and partial write. + * It doesn't truncate the extra data introduced by alignment because that step + * is done in H5FD_direct_flush. + */ + p2 = copy_buf; + dup_size = alloc_size; + while (dup_size>0) { + do { + nbytes = HDwrite(file->fd, p2, dup_size); + } while (-1==nbytes && EINTR==errno); - /*look for the aligned position for writing the data*/ - if(file_seek(file->fd, (file_offset_t)(addr - addr % _fbsize), SEEK_SET) < 0) - HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position") + if (-1==nbytes) { /* error */ + HSYS_GOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed") + } + if (0==nbytes) { + /* end of file but not end of format address space */ + break; + } else { + assert(nbytes>0); + assert((size_t)nbytes<=dup_size); + H5_CHECK_OVERFLOW(nbytes,ssize_t,size_t); + H5_CHECK_OVERFLOW(nbytes,ssize_t,haddr_t); + dup_size -= (size_t)nbytes; + p2 = (unsigned char*)p2 + nbytes; + } + } - /* - * Write the data, being careful of interrupted system calls and partial write. - * It doesn't truncate the extra data introduced by alignment because that step - * is done in H5FD_direct_flush. - */ - p2 = copy_buf; - while (alloc_size>0) { - do { - nbytes = HDwrite(file->fd, p2, alloc_size); - } while (-1==nbytes && EINTR==errno); + /* update the size and address of data being read. */ + if(copy_size > (alloc_size - (size_t)(copy_addr % _fbsize))) + copy_size -= (alloc_size - (size_t)(copy_addr % _fbsize)); + else + copy_size = 0; - if (-1==nbytes) { /* error */ - HSYS_GOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed") - } - 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; - p2 = (unsigned char*)p2 + nbytes; - } + copy_addr += (alloc_size - (size_t)(copy_addr % _fbsize)); + } while (copy_size > 0); /*Update the address and size*/ addr += (haddr_t)size; buf = (const char*)buf + size; - - HDfree(copy_buf); + + if(copy_buf) + HDfree(copy_buf); } /* Update current position and eof */ diff --git a/src/H5FDdirect.h b/src/H5FDdirect.h index 754cd3b..e4cdc32 100644 --- a/src/H5FDdirect.h +++ b/src/H5FDdirect.h @@ -38,14 +38,14 @@ extern "C" { * Application can set these values through the function H5Pset_fapl_direct. */ #define MBOUNDARY_DEF 4096 #define FBSIZE_DEF 4096 -#define CBSIZE_DEF 128*1024*1024 +#define CBSIZE_DEF 16*1024*1024 H5_DLL hid_t H5FD_direct_init(void); H5_DLL void H5FD_direct_term(void); -H5_DLL herr_t H5Pset_fapl_direct(hid_t fapl_id, hsize_t alignment, hsize_t block_size, - hsize_t cbuf_size); -H5_DLL herr_t H5Pget_fapl_direct(hid_t fapl_id, hsize_t *boundary/*out*/, - hsize_t *block_size/*out*/, hsize_t *cbuf_size/*out*/); +H5_DLL herr_t H5Pset_fapl_direct(hid_t fapl_id, size_t alignment, size_t block_size, + size_t cbuf_size); +H5_DLL herr_t H5Pget_fapl_direct(hid_t fapl_id, size_t *boundary/*out*/, + size_t *block_size/*out*/, size_t *cbuf_size/*out*/); #ifdef __cplusplus } diff --git a/test/h5test.c b/test/h5test.c index 6c9e8ee..93f992e 100644 --- a/test/h5test.c +++ b/test/h5test.c @@ -581,7 +581,7 @@ h5_fileaccess(void) #ifdef H5_HAVE_DIRECT /* Linux direct read() and write() system calls. Set memory boundary, file block size, * and copy buffer size to the default values. */ - if (H5Pset_fapl_direct(fapl, 0, 0, 0)<0) return -1; + if (H5Pset_fapl_direct(fapl, 1024, 4096, 8*4096)<0) return -1; #endif } else { /* Unknown driver */ diff --git a/test/vfd.c b/test/vfd.c index 02e2478..8c1fb23 100644 --- a/test/vfd.c +++ b/test/vfd.c @@ -29,7 +29,7 @@ #define CORE_INCREMENT (4*KB) #define MBOUNDARY 512 #define FBSIZE 4096 -#define CBSIZE 64*1024*1024 +#define CBSIZE 4096 const char *FILENAME[] = { "sec2_file", @@ -145,9 +145,9 @@ test_direct(void) char filename[1024]; int *fhandle=NULL; hsize_t file_size; - hsize_t mbound; - hsize_t fbsize; - hsize_t cbsize; + size_t mbound; + size_t fbsize; + size_t cbsize; #endif /*H5_HAVE_DIRECT*/ TESTING("Direct I/O file driver"); -- cgit v0.12