diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2012-04-06 02:57:06 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2012-04-06 02:57:06 (GMT) |
commit | d5a62239587f7cc5de301fa5c6b0919807689818 (patch) | |
tree | 40a36d60dd8ac2d10a45886869cc53d3fdc9181e /src/H5FDcore.c | |
parent | ebf3d99b955c705217227fb7f8ae4405e941399a (diff) | |
download | hdf5-d5a62239587f7cc5de301fa5c6b0919807689818.zip hdf5-d5a62239587f7cc5de301fa5c6b0919807689818.tar.gz hdf5-d5a62239587f7cc5de301fa5c6b0919807689818.tar.bz2 |
[svn-r22254] Description:
Bring r22085:22251 from trunk to revise_chunks branch.
Also tackle some testing issues in test/objcopy.c test and clean up
some warnings.
Tested on:
FreeBSD/32 8.2 (loyalty) w/gcc4.6, w/C++ & FORTRAN, in debug mode
FreeBSD/64 8.2 (freedom) w/gcc4.6, w/C++ & FORTRAN, in debug mode
Linux/32 2.6 (jam) w/PGI compilers, w/default API=1.8.x,
w/C++ & FORTRAN, w/threadsafe, in debug mode
Linux/64-amd64 2.6 (koala) w/Intel compilers, w/default API=1.6.x,
w/C++ & FORTRAN, in production mode
Solaris/32 2.10 (linew) w/deprecated symbols disabled, w/C++ & FORTRAN,
w/szip filter, w/threadsafe, in production mode
Linux/PPC 2.6 (ostrich) w/C++ & FORTRAN, w/threadsafe, in debug mode
Linux/64-ia64 2.6 (ember) w/Intel compilers, w/paralle, C++ & FORTRAN,
in production mode
Mac OS X/32 10.7.3 (amazon) in debug mode
Mac OS X/32 10.7.3 (amazon) w/C++ & FORTRAN, w/threadsafe,
in production mode
Mac OS X/32 10.7.3 (amazon) w/parallel, in debug mode
Diffstat (limited to 'src/H5FDcore.c')
-rw-r--r-- | src/H5FDcore.c | 436 |
1 files changed, 292 insertions, 144 deletions
diff --git a/src/H5FDcore.c b/src/H5FDcore.c index 7fa0e7c..cc48e51 100644 --- a/src/H5FDcore.c +++ b/src/H5FDcore.c @@ -38,8 +38,24 @@ /* The driver identification number, initialized at runtime */ static hid_t H5FD_CORE_g = 0; -/* - * The description of a file belonging to this driver. The `eoa' and `eof' +/* Since Windows doesn't follow the rest of the world when it comes + * to POSIX I/O types, some typedefs and constants are needed to avoid + * making the code messy with #ifdefs. + * NOTE: These are only used when writing data to the backing store on + * file close. + */ +#ifdef H5_HAVE_WIN32_API +typedef unsigned int h5_core_io_t; +typedef int h5_core_io_ret_t; +static int H5_CORE_MAX_IO_BYTES_g = INT_MAX; +#else +/* Unix, everyone else */ +typedef size_t h5_core_io_t; +typedef ssize_t h5_core_io_ret_t; +static size_t H5_CORE_MAX_IO_BYTES_g = SSIZET_MAX; +#endif /* H5_HAVE_WIN32_API */ + +/* The description of a file belonging to this driver. The `eoa' and `eof' * determine the amount of hdf5 address space in use and the high-water mark * of the file (the current size of the underlying memory). */ @@ -54,8 +70,7 @@ typedef struct H5FD_core_t { int fd; /*backing store file descriptor */ /* Information for determining uniqueness of a file with a backing store */ #ifndef H5_HAVE_WIN32_API - /* - * On most systems the combination of device and i-node number uniquely + /* On most systems the combination of device and i-node number uniquely * identify a file. */ dev_t device; /*file device number */ @@ -65,19 +80,28 @@ typedef struct H5FD_core_t { ino_t inode; /*file i-node number */ #endif /*H5_VMS*/ #else - /* - * On H5_HAVE_WIN32_API the low-order word of a unique identifier associated with the - * file and the volume serial number uniquely identify a file. This number - * (which, both? -rpm) may change when the system is restarted or when the - * file is opened. After a process opens a file, the identifier is - * constant until the file is closed. An application can use this - * identifier and the volume serial number to determine whether two - * handles refer to the same file. + /* Files in windows are uniquely identified by the volume serial + * number and the file index (both low and high parts). + * + * There are caveats where these numbers can change, especially + * on FAT file systems. On NTFS, however, a file should keep + * those numbers the same until renamed or deleted (though you + * can use ReplaceFile() on NTFS to keep the numbers the same + * while renaming). + * + * See the MSDN "BY_HANDLE_FILE_INFORMATION Structure" entry for + * more information. + * + * http://msdn.microsoft.com/en-us/library/aa363788(v=VS.85).aspx */ - DWORD fileindexlo; - DWORD fileindexhi; -#endif + DWORD nFileIndexLow; + DWORD nFileIndexHigh; + DWORD dwVolumeSerialNumber; + + HANDLE hFile; /* Native windows file handle */ +#endif /* H5_HAVE_WIN32_API */ hbool_t dirty; /*changes not saved? */ + H5FD_file_image_callbacks_t fi_callbacks; /* file image callbacks */ /* Information from file open flags, for SWMR access */ hbool_t swmr_read; /* Whether the file is open for SWMR read access */ @@ -92,8 +116,7 @@ typedef struct H5FD_core_fapl_t { /* Allocate memory in multiples of this size by default */ #define H5FD_CORE_INCREMENT 8192 -/* - * These macros check for overflow of various quantities. These macros +/* These macros check for overflow of various quantities. These macros * assume that file_offset_t is signed and haddr_t and size_t are unsigned. * * ADDR_OVERFLOW: Checks whether a file address of type `haddr_t' @@ -203,8 +226,6 @@ H5FD_core_init_interface(void) * Programmer: Robb Matzke * Thursday, July 29, 1999 * - * Modifications: - * *------------------------------------------------------------------------- */ hid_t @@ -261,15 +282,6 @@ H5FD_core_term(void) * Programmer: Robb Matzke * Thursday, February 19, 1998 * - * Modifications: - * Robb Matzke, 1999-10-19 - * Added the BACKING_STORE argument. If set then the entire file - * contents are flushed to a file with the same name as this - * core file. - * - * Raymond Lu, 2001-10-25 - * Changed the file access list to the new generic list. - * *------------------------------------------------------------------------- */ herr_t @@ -308,14 +320,6 @@ done: * Programmer: Robb Matzke * Tuesday, August 10, 1999 * - * Modifications: - * Robb Matzke, 1999-10-19 - * Added the BACKING_STORE argument. - * - * Raymond Lu - * 2001-10-25 - * Changed file access list to the new generic property list. - * *------------------------------------------------------------------------- */ herr_t @@ -358,8 +362,6 @@ done: * Programmer: Robb Matzke * Friday, August 13, 1999 * - * Modifications: - * *------------------------------------------------------------------------- */ static void * @@ -399,16 +401,6 @@ done: * Programmer: Robb Matzke * Thursday, July 29, 1999 * - * Modifications: - * Robb Matzke, 1999-10-19 - * The backing store file is created and opened if specified. - * - * Raymond Lu, 2006-11-30 - * Enabled the driver to read an existing file depending on - * the setting of the backing_store and file open flags. - * - * Allen Byrne, 2008-1-23 - * changed if of fapl_id to assert *------------------------------------------------------------------------- */ static H5FD_t * @@ -420,11 +412,11 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id, H5FD_core_fapl_t *fa=NULL; H5P_genplist_t *plist; /* Property list pointer */ #ifdef H5_HAVE_WIN32_API - HFILE filehandle; struct _BY_HANDLE_FILE_INFORMATION fileinfo; #endif h5_stat_t sb; int fd=-1; + H5FD_file_image_info_t file_image_info; H5FD_t *ret_value; FUNC_ENTER_NOAPI_NOINIT @@ -447,10 +439,32 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id, if(H5F_ACC_CREAT & flags) o_flags |= O_CREAT; if(H5F_ACC_EXCL & flags) o_flags |= O_EXCL; + /* Retrieve initial file image info */ + if(H5P_get(plist, H5F_ACS_FILE_IMAGE_INFO_NAME, &file_image_info) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get initial file image info") + + /* If the file image exists and this is an open, make sure the file doesn't exist */ + HDassert(((file_image_info.buffer != NULL) && (file_image_info.size > 0)) || + ((file_image_info.buffer == NULL) && (file_image_info.size == 0))); + if((file_image_info.buffer != NULL) && !(H5F_ACC_CREAT & flags)) { + if(HDopen(name, o_flags, 0666) >= 0) + HGOTO_ERROR(H5E_FILE, H5E_FILEEXISTS, NULL, "file already exists") + + /* If backing store is requested, create and stat the file + * Note: We are forcing the O_CREAT flag here, even though this is + * technically an open. + */ + if(fa->backing_store) { + if((fd = HDopen(name, o_flags | O_CREAT, 0666)) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to create file") + if(HDfstat(fd, &sb) < 0) + HSYS_GOTO_ERROR(H5E_FILE, H5E_BADFILE, NULL, "unable to fstat file") + } /* end if */ + } /* end if */ /* Open backing store, and get stat() from file. The only case that backing * store is off is when the backing_store flag is off and H5F_ACC_CREAT is * on. */ - if(fa->backing_store || !(H5F_ACC_CREAT & flags)) { + else if(fa->backing_store || !(H5F_ACC_CREAT & flags)) { if(fa && (fd = HDopen(name, o_flags, 0666)) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file") if(HDfstat(fd, &sb) < 0) @@ -464,8 +478,7 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id, if(name && *name) file->name = H5MM_xstrdup(name); - /* - * The increment comes from either the file access property list or the + /* The increment comes from either the file access property list or the * default value. But if the file access property list was zero then use * the default value instead. */ @@ -474,13 +487,22 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id, /* If save data in backing store. */ file->backing_store = fa->backing_store; + /* Save file image callbacks */ + file->fi_callbacks = file_image_info.callbacks; + if(fd >= 0) { /* Retrieve information for determining uniqueness of file */ #ifdef H5_HAVE_WIN32_API - filehandle = _get_osfhandle(fd); - (void)GetFileInformationByHandle((HANDLE)filehandle, &fileinfo); - file->fileindexhi = fileinfo.nFileIndexHigh; - file->fileindexlo = fileinfo.nFileIndexLow; + file->hFile = (HANDLE)_get_osfhandle(fd); + if(INVALID_HANDLE_VALUE == file->hFile) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to get Windows file handle") + + if(!GetFileInformationByHandle((HANDLE)file->hFile, &fileinfo)) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to get Windows file information") + + file->nFileIndexHigh = fileinfo.nFileIndexHigh; + file->nFileIndexLow = fileinfo.nFileIndexLow; + file->dwVolumeSerialNumber = fileinfo.dwVolumeSerialNumber; #else /* H5_HAVE_WIN32_API */ file->device = sb.st_dev; #ifdef H5_VMS @@ -499,20 +521,70 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id, size_t size; /* Retrieve file size */ - size = (size_t)sb.st_size; + if(file_image_info.buffer && file_image_info.size > 0) + size = file_image_info.size; + else + size = (size_t)sb.st_size; /* Check if we should allocate the memory buffer and read in existing data */ if(size) { - /* Allocate memory for the file's data */ - if(NULL == (file->mem = (unsigned char*)H5MM_malloc(size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate memory block") + /* Allocate memory for the file's data, using the file image callback if available. */ + if(file->fi_callbacks.image_malloc) { + if(NULL == (file->mem = (unsigned char*)file->fi_callbacks.image_malloc(size, H5FD_FILE_IMAGE_OP_FILE_OPEN, file->fi_callbacks.udata))) + HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "image malloc callback failed") + } /* end if */ + else { + if(NULL == (file->mem = (unsigned char*)H5MM_malloc(size))) + HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "unable to allocate memory block") + } /* end else */ /* Set up data structures */ file->eof = size; - /* Read in existing data */ - if(HDread(file->fd, file->mem, size) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read file") + /* If there is an initial file image, copy it, using the callback if possible */ + if(file_image_info.buffer && file_image_info.size > 0) { + if(file->fi_callbacks.image_memcpy) { + if(file->mem != file->fi_callbacks.image_memcpy(file->mem, file_image_info.buffer, size, H5FD_FILE_IMAGE_OP_FILE_OPEN, file->fi_callbacks.udata)) + HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, NULL, "image_memcpy callback failed") + } /* end if */ + else + HDmemcpy(file->mem, file_image_info.buffer, size); + } /* end if */ + /* Read in existing data from the file if there is no image */ + else { + /* Read in existing data, being careful of interrupted system calls, + * partial results, and the end of the file. + */ + while(size > 0) { + h5_core_io_t bytes_in = 0; /* # of bytes to read */ + h5_core_io_ret_t bytes_read = -1; /* # of bytes actually read */ + + /* Trying to read more bytes than the return type can handle is + * undefined behavior in POSIX. + */ + if(size > H5_CORE_MAX_IO_BYTES_g) + bytes_in = H5_CORE_MAX_IO_BYTES_g; + else + bytes_in = (h5_core_io_t)size; + + do { + bytes_read = HDread(file->fd, file->mem, bytes_in); + } while(-1 == bytes_read && EINTR == errno); + + if(-1 == bytes_read) { /* error */ + int myerrno = errno; + time_t mytime = HDtime(NULL); + HDoff_t myoffset = HDlseek(file->fd, (HDoff_t)0, SEEK_CUR); + + HGOTO_ERROR(H5E_IO, H5E_READERROR, NULL, "file read failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, error message = '%s', file->mem = %p, size = %lu, offset = %llu", HDctime(&mytime), file->name, file->fd, myerrno, HDstrerror(myerrno), file->mem, (unsigned long)size, (unsigned long long)myoffset); + } /* end if */ + + HDassert(bytes_read >= 0); + HDassert((size_t)bytes_read <= size); + + size -= (size_t)bytes_read; + } /* end while */ + } /* end else */ } /* end if */ } /* end if */ @@ -559,8 +631,15 @@ H5FD_core_close(H5FD_t *_file) HDclose(file->fd); if(file->name) H5MM_xfree(file->name); - if(file->mem) - H5MM_xfree(file->mem); + if(file->mem) { + /* Use image callback if available */ + if(file->fi_callbacks.image_free) { + if(file->fi_callbacks.image_free(file->mem, H5FD_FILE_IMAGE_OP_FILE_CLOSE, file->fi_callbacks.udata) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "image_free callback failed") + } /* end if */ + else + H5MM_xfree(file->mem); + } /* end if */ HDmemset(file, 0, sizeof(H5FD_core_t)); H5MM_xfree(file); @@ -585,13 +664,6 @@ done: * Programmer: Robb Matzke * Thursday, July 29, 1999 * - * Modifications: - * Neil Fortner - * Tuesday, March 9, 2010 - * Modified function to compare low level file information if - * a backing store is opened for both files, similar to the - * sec2 file driver. - * *------------------------------------------------------------------------- */ static int @@ -606,11 +678,14 @@ H5FD_core_cmp(const H5FD_t *_f1, const H5FD_t *_f2) if(f1->fd >= 0 && f2->fd >= 0) { /* Compare low level file information for backing store */ #ifdef H5_HAVE_WIN32_API - if (f1->fileindexhi < f2->fileindexhi) HGOTO_DONE(-1) - if (f1->fileindexhi > f2->fileindexhi) HGOTO_DONE(1) + if(f1->dwVolumeSerialNumber < f2->dwVolumeSerialNumber) HGOTO_DONE(-1) + if(f1->dwVolumeSerialNumber > f2->dwVolumeSerialNumber) HGOTO_DONE(1) - if (f1->fileindexlo < f2->fileindexlo) HGOTO_DONE(-1) - if (f1->fileindexlo > f2->fileindexlo) HGOTO_DONE(1) + if(f1->nFileIndexHigh < f2->nFileIndexHigh) HGOTO_DONE(-1) + if(f1->nFileIndexHigh > f2->nFileIndexHigh) HGOTO_DONE(1) + + if(f1->nFileIndexLow < f2->nFileIndexLow) HGOTO_DONE(-1) + if(f1->nFileIndexLow > f2->nFileIndexLow) HGOTO_DONE(1) #else #ifdef H5_DEV_T_IS_SCALAR @@ -685,9 +760,11 @@ H5FD_core_query(const H5FD_t * _file, unsigned long *flags /* out */) *flags |= H5FD_FEAT_ACCUMULATE_METADATA; /* OK to accumulate metadata for faster writes */ *flags |= H5FD_FEAT_DATA_SIEVE; /* OK to perform data sieving for faster raw data reads & writes */ *flags |= H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */ + *flags |= H5FD_FEAT_ALLOW_FILE_IMAGE; /* OK to use file image feature with this VFD */ + *flags |= H5FD_FEAT_CAN_USE_FILE_IMAGE_CALLBACKS; /* OK to use file image callbacks with this VFD */ /* If the backing store is open, a POSIX file handle is available */ - if(file->fd >= 0 && file->backing_store) + if(file && file->fd >= 0 && file->backing_store) *flags |= H5FD_FEAT_POSIX_COMPAT_HANDLE; /* VFD handle is POSIX I/O call compatible */ } /* end if */ @@ -709,11 +786,6 @@ H5FD_core_query(const H5FD_t * _file, unsigned long *flags /* out */) * Programmer: Robb Matzke * Monday, August 2, 1999 * - * Modifications: - * Raymond Lu - * 21 Dec. 2006 - * Added the parameter TYPE. It's only used for MULTI driver. - * *------------------------------------------------------------------------- */ static haddr_t @@ -741,11 +813,6 @@ H5FD_core_get_eoa(const H5FD_t *_file, H5FD_mem_t UNUSED type) * Programmer: Robb Matzke * Thursday, July 29, 1999 * - * Modifications: - * Raymond Lu - * 21 Dec. 2006 - * Added the parameter TYPE. It's only used for MULTI driver. - * *------------------------------------------------------------------------- */ static herr_t @@ -782,8 +849,6 @@ done: * Programmer: Robb Matzke * Thursday, July 29, 1999 * - * Modifications: - * *------------------------------------------------------------------------- */ static haddr_t @@ -807,8 +872,6 @@ H5FD_core_get_eof(const H5FD_t *_file) * Programmer: Raymond Lu * Sept. 16, 2002 * - * Modifications: - * *------------------------------------------------------------------------- */ static herr_t @@ -874,8 +937,6 @@ done: * Programmer: Robb Matzke * Thursday, July 29, 1999 * - * Modifications: - * *------------------------------------------------------------------------- */ /* ARGSUSED */ @@ -888,8 +949,8 @@ H5FD_core_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, hadd FUNC_ENTER_NOAPI_NOINIT - assert(file && file->pub.cls); - assert(buf); + HDassert(file && file->pub.cls); + HDassert(buf); /* Check for overflow conditions */ if (HADDR_UNDEF == addr) @@ -947,8 +1008,6 @@ done: * Programmer: Robb Matzke * Thursday, July 29, 1999 * - * Modifications: - * *------------------------------------------------------------------------- */ /* ARGSUSED */ @@ -985,9 +1044,16 @@ H5FD_core_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, had if((addr + size) % file->increment) new_eof += file->increment; - /* (Re)allocate memory for the file buffer */ - if(NULL == (x = (unsigned char *)H5MM_realloc(file->mem, new_eof))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory block of %llu bytes", (unsigned long long)new_eof) + /* (Re)allocate memory for the file buffer, using callbacks if available */ + if(file->fi_callbacks.image_realloc) { + if(NULL == (x = (unsigned char *)file->fi_callbacks.image_realloc(file->mem, new_eof, H5FD_FILE_IMAGE_OP_FILE_RESIZE, file->fi_callbacks.udata))) + HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate memory block of %llu bytes with callback", (unsigned long long)new_eof) + } /* end if */ + else { + if(NULL == (x = (unsigned char *)H5MM_realloc(file->mem, new_eof))) + HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate memory block of %llu bytes", (unsigned long long)new_eof) + } /* end else */ + #ifdef H5_CLEAR_MEMORY HDmemset(x + file->eof, 0, (size_t)(new_eof - file->eof)); #endif /* H5_CLEAR_MEMORY */ @@ -998,6 +1064,8 @@ HDmemset(x + file->eof, 0, (size_t)(new_eof - file->eof)); /* Write from BUF to memory */ HDmemcpy(file->mem + addr, buf, size); + + /* Mark memory buffer as modified */ file->dirty = TRUE; done: @@ -1018,10 +1086,6 @@ done: * Programmer: Robb Matzke * Friday, October 15, 1999 * - * Modifications: - * Raymond Lu, 2006-11-30 - * Added a condition check for backing store flag, for an - * existing file can be opened for read and write now. *------------------------------------------------------------------------- */ /* ARGSUSED */ @@ -1040,19 +1104,40 @@ H5FD_core_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing) if (0!=HDlseek(file->fd, (off_t)0, SEEK_SET)) HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "error seeking in backing store") + + while (size > 0) { - while (size) { - ssize_t n; - - H5_CHECK_OVERFLOW(size,hsize_t,size_t); - n = HDwrite(file->fd, ptr, (size_t)size); - if (n<0 && EINTR==errno) - continue; - if (n<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "error writing backing store") - ptr += (size_t)n; - size -= (size_t)n; - } + h5_core_io_t bytes_in = 0; /* # of bytes to write */ + h5_core_io_ret_t bytes_wrote = -1; /* # of bytes written */ + + /* Trying to write more bytes than the return type can handle is + * undefined behavior in POSIX. + */ + if(size > H5_CORE_MAX_IO_BYTES_g) + bytes_in = H5_CORE_MAX_IO_BYTES_g; + else + bytes_in = (h5_core_io_t)size; + + do { + bytes_wrote = HDwrite(file->fd, ptr, bytes_in); + } while(-1 == bytes_wrote && EINTR == errno); + + if(-1 == bytes_wrote) { /* error */ + int myerrno = errno; + time_t mytime = HDtime(NULL); + HDoff_t myoffset = HDlseek(file->fd, (HDoff_t)0, SEEK_CUR); + + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "write to backing store failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, error message = '%s', ptr = %p, size = %lu, offset = %llu", HDctime(&mytime), file->name, file->fd, myerrno, HDstrerror(myerrno), ptr, (unsigned long)size, (unsigned long long)myoffset); + } /* end if */ + + HDassert(bytes_wrote > 0); + HDassert((size_t)bytes_wrote <= size); + + size -= (size_t)bytes_wrote; + ptr = (unsigned char *)ptr + bytes_wrote; + + } /* end while */ + file->dirty = FALSE; } @@ -1067,6 +1152,28 @@ done: * Purpose: Makes sure that the true file size is the same (or larger) * than the end-of-address. * + * Addendum -- 12/2/11 + * For file images opened with the core file driver, it is + * necessary that we avoid reallocating the core file driver's + * buffer uneccessarily. + * + * To this end, I have made the following functional changes + * to this function. + * + * If we are closing, and there is no backing store, this + * function becomes a no-op. + * + * If we are closing, and there is backing store, we set the + * eof to equal the eoa, and truncate the backing store to + * the new eof + * + * If we are not closing, we realloc the buffer to size equal + * to the smallest multiple of the allocation increment that + * equals or exceeds the eoa and set the eof accordingly. + * Note that we no longer truncate the backing store to the + * new eof if applicable. + * -- JRM + * * Return: Success: Non-negative * Failure: Negative * @@ -1077,7 +1184,7 @@ done: */ /* ARGSUSED */ static herr_t -H5FD_core_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing) +H5FD_core_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t closing) { H5FD_core_t *file = (H5FD_core_t*)_file; size_t new_eof; /* New size of memory buffer */ @@ -1087,40 +1194,81 @@ H5FD_core_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing) HDassert(file); - /* Determine new size of memory buffer */ - H5_ASSIGN_OVERFLOW(new_eof, file->increment * (file->eoa / file->increment), hsize_t, size_t); - if(file->eoa % file->increment) - new_eof += file->increment; + /* if we are closing and not using backing store, do nothing */ + if(!closing || file->backing_store) { + if(closing) /* set eof to eoa */ + new_eof = file->eoa; + else { /* set eof to smallest multiple of increment that exceeds eoa */ + /* Determine new size of memory buffer */ + H5_ASSIGN_OVERFLOW(new_eof, file->increment * (file->eoa / file->increment), hsize_t, size_t); + if(file->eoa % file->increment) + new_eof += file->increment; + } /* end else */ + + /* Extend the file to make sure it's large enough */ + if(!H5F_addr_eq(file->eof, (haddr_t)new_eof)) { + unsigned char *x; /* Pointer to new buffer for file data */ + + /* (Re)allocate memory for the file buffer, using callback if available */ + if(file->fi_callbacks.image_realloc) { + if(NULL == (x = (unsigned char *)file->fi_callbacks.image_realloc(file->mem, new_eof, H5FD_FILE_IMAGE_OP_FILE_RESIZE, file->fi_callbacks.udata))) + HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate memory block with callback") + } /* end if */ + else { + if(NULL == (x = (unsigned char *)H5MM_realloc(file->mem, new_eof))) + HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate memory block") + } /* end else */ - /* Extend the file to make sure it's large enough */ - if(!H5F_addr_eq(file->eof, (haddr_t)new_eof)) { - unsigned char *x; /* Pointer to new buffer for file data */ - - /* (Re)allocate memory for the file buffer */ - if(NULL == (x = (unsigned char *)H5MM_realloc(file->mem, new_eof))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory block") #ifdef H5_CLEAR_MEMORY -if(file->eof < new_eof) - HDmemset(x + file->eof, 0, (size_t)(new_eof - file->eof)); + if(file->eof < new_eof) + HDmemset(x + file->eof, 0, (size_t)(new_eof - file->eof)); #endif /* H5_CLEAR_MEMORY */ - file->mem = x; + file->mem = x; - /* Update backing store, if using it */ - if(file->fd >= 0 && file->backing_store) { + /* Update backing store, if using it and if closing */ + if(closing && (file->fd >= 0) && file->backing_store) { +#ifdef H5_HAVE_WIN32_API + LARGE_INTEGER li; /* 64-bit (union) integer for SetFilePointer() call */ + DWORD dwPtrLow; /* Low-order pointer bits from SetFilePointer() + * Only used as an error code here. + */ + DWORD dwError; /* DWORD error code from GetLastError() */ + BOOL bError; /* Boolean error flag */ + + /* Windows uses this odd QuadPart union for 32/64-bit portability */ + li.QuadPart = (__int64)file->eoa; + + /* Extend the file to make sure it's large enough. + * + * Since INVALID_SET_FILE_POINTER can technically be a valid return value + * from SetFilePointer(), we also need to check GetLastError(). + */ + dwPtrLow = SetFilePointer(file->hFile, li.LowPart, &li.HighPart, FILE_BEGIN); + if(INVALID_SET_FILE_POINTER == dwPtrLow) { + dwError = GetLastError(); + if(dwError != NO_ERROR ) + HGOTO_ERROR(H5E_FILE, H5E_FILEOPEN, FAIL, "unable to set file pointer") + } + + bError = SetEndOfFile(file->hFile); + if(0 == bError) + HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly") +#else /* H5_HAVE_WIN32_API */ #ifdef H5_VMS - /* Reset seek offset to the beginning of the file, so that the file isn't - * re-extended later. This may happen on Open VMS. */ - if(-1 == HDlseek(file->fd, 0, SEEK_SET)) - HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position") -#endif + /* Reset seek offset to the beginning of the file, so that the file isn't + * re-extended later. This may happen on Open VMS. */ + if(-1 == HDlseek(file->fd, (HDoff_t)0, SEEK_SET)) + HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position") +#endif /* H5_VMS */ + if(-1 == HDftruncate(file->fd, (HDoff_t)new_eof)) + HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly") +#endif /* H5_HAVE_WIN32_API */ + } /* end if */ - if(-1 == HDftruncate(file->fd, (off_t)new_eof)) - HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly") + /* Update the eof value */ + file->eof = new_eof; } /* end if */ - - /* Update the eof value */ - file->eof = new_eof; - } /* end if */ + } /* end if(file->eof < file->eoa) */ done: FUNC_LEAVE_NOAPI(ret_value) |