mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-02-17 16:10:24 +08:00
[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:
parent
469f6d30b1
commit
0f040c40f0
218
src/H5FDdirect.c
218
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")
|
||||
|
||||
/*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 */
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user