[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.
This commit is contained in:
Raymond Lu 2006-10-26 21:41:19 -05:00
parent 469f6d30b1
commit 0f040c40f0
4 changed files with 141 additions and 97 deletions

View File

@ -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(&copy_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")
/*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")
/*
* 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);
/*
* 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);
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;
}
}
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;
}
/* 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;
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 */

View File

@ -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
}

View File

@ -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 */

View File

@ -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");