diff options
author | Neil Fortner <nfortne2@hdfgroup.org> | 2010-03-05 17:24:17 (GMT) |
---|---|---|
committer | Neil Fortner <nfortne2@hdfgroup.org> | 2010-03-05 17:24:17 (GMT) |
commit | 179b54da83f293948a531afd6b59e676df7a60e7 (patch) | |
tree | f57b410bccb7fa311043f7a4451f4ca11d8463d7 /src/H5F.c | |
parent | 3a06e04ac5abb30d241118b83e2fc280e981a0b3 (diff) | |
download | hdf5-179b54da83f293948a531afd6b59e676df7a60e7.zip hdf5-179b54da83f293948a531afd6b59e676df7a60e7.tar.gz hdf5-179b54da83f293948a531afd6b59e676df7a60e7.tar.bz2 |
[svn-r18374] Purpose: Fix bugs involving external links
Description:
Previously, the library would reopen the source file when traversing an external
link if unable to find the target file otherwise. This has been corrected.
Also moved the call to H5F_flush from H5F_try_close to H5F_dest, so the file is
only flushed when the last identifier for the file is closed. This prevernts
situations where the library could attempt to flush a file with protected
metadata.
Tested: jam, amani, linew (h5committest); Fedora
Diffstat (limited to 'src/H5F.c')
-rw-r--r-- | src/H5F.c | 48 |
1 files changed, 32 insertions, 16 deletions
@@ -71,7 +71,7 @@ static H5F_t *H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf); static herr_t H5F_build_actual_name(const H5F_t *f, const H5P_genplist_t *fapl, const char *name, char ** /*out*/ actual_name); -static herr_t H5F_dest(H5F_t *f, hid_t dxpl_id); +static herr_t H5F_dest(H5F_t *f, hid_t dxpl_id, hbool_t flush); static herr_t H5F_close(H5F_t *f); /* Declare a free list to manage the H5F_t struct */ @@ -967,7 +967,7 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5F_dest(H5F_t *f, hid_t dxpl_id) +H5F_dest(H5F_t *f, hid_t dxpl_id, hbool_t flush) { herr_t ret_value = SUCCEED; /* Return value */ @@ -978,6 +978,14 @@ H5F_dest(H5F_t *f, hid_t dxpl_id) HDassert(f->shared); if(1 == f->shared->nrefs) { + /* Flush at this point since the file will be closed. + * Only try to flush the file if it was opened with write access, and if + * the caller requested a flush. + */ + if((f->shared->flags & H5F_ACC_RDWR) && flush) + if(H5F_flush(f, dxpl_id) < 0) + HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache") + /* Release objects that depend on the superblock being initialized */ if(f->shared->sblock) { /* Shutdown file free space manager(s) */ @@ -1314,7 +1322,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, done: if(!ret_value && file) - if(H5F_dest(file, dxpl_id) < 0) + if(H5F_dest(file, dxpl_id, FALSE) < 0) HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, NULL, "problems closing file") FUNC_LEAVE_NOAPI(ret_value) @@ -1857,24 +1865,16 @@ H5F_try_close(H5F_t *f) if(H5F_close_mounts(f) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't unmount child files") - /* Flush at this point since the file will be closed. Don't invalidate - * the cache, since this file might still be open using another handle. - * However, make sure we flush in case that handle is read-only; its - * copy of the cache needs to be clean. - * Only try to flush the file if it was opened with write access. - */ - if(f->intent & H5F_ACC_RDWR) { - /* Flush all caches */ - if(H5F_flush(f, H5AC_dxpl_id) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache") - } /* end if */ + /* Delay flush until the shared file struct is closed, in H5F_dest. If the + * application called H5Fclose, it would have been flushed in that function + * (unless it will have been flushed in H5F_dest anyways). */ /* * Destroy the H5F_t struct and decrement the reference count for the * shared H5F_file_t struct. If the reference count for the H5F_file_t * struct reaches zero then destroy it also. */ - if(H5F_dest(f, H5AC_dxpl_id) < 0) + if(H5F_dest(f, H5AC_dxpl_id, TRUE) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "problems closing file") done: @@ -1906,6 +1906,8 @@ done: herr_t H5Fclose(hid_t file_id) { + H5F_t *f = NULL; + int nref; herr_t ret_value = SUCCEED; FUNC_ENTER_API(H5Fclose, FAIL) @@ -1915,6 +1917,20 @@ H5Fclose(hid_t file_id) if(H5I_FILE != H5I_get_type(file_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file ID") + /* Flush file if this is the last reference to this id and we have write + * intent, unless it will be flushed by the "shared" file being closed. + * This is only necessary to replicate previous behaviour, and could be + * disabled by an option/property to improve performance. */ + if(NULL == (f = (H5F_t *)H5I_object(file_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + if((f->shared->nrefs > 1) && (H5F_INTENT(f) & H5F_ACC_RDWR)) { + if((nref = H5I_get_ref(file_id, FALSE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't get ID ref count") + if(nref == 1) + if(H5F_flush(f, H5AC_dxpl_id) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache") + } /* end if */ + /* * Decrement reference count on atom. When it reaches zero the file will * be closed. @@ -1982,7 +1998,7 @@ H5Freopen(hid_t file_id) done: if(ret_value < 0 && new_file) - if(H5F_dest(new_file, H5AC_dxpl_id) < 0) + if(H5F_dest(new_file, H5AC_dxpl_id, FALSE) < 0) HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file") FUNC_LEAVE_API(ret_value) |