diff options
Diffstat (limited to 'src/H5Fint.c')
-rw-r--r-- | src/H5Fint.c | 180 |
1 files changed, 158 insertions, 22 deletions
diff --git a/src/H5Fint.c b/src/H5Fint.c index f1e9fb5..8ad97a8 100644 --- a/src/H5Fint.c +++ b/src/H5Fint.c @@ -76,6 +76,8 @@ typedef struct H5F_olist_t { static int H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key); static herr_t H5F_build_actual_name(const H5F_t *f, const H5P_genplist_t *fapl, const char *name, char ** /*out*/ actual_name);/* Declare a free list to manage the H5F_t struct */ +static herr_t H5F__flush_phase1(H5F_t *f, hid_t dxpl_id); +static herr_t H5F__flush_phase2(H5F_t *f, hid_t dxpl_id, hbool_t closing); /*********************/ @@ -820,15 +822,40 @@ H5F_dest(H5F_t *f, hid_t dxpl_id, hbool_t flush) int actype; /* metadata cache type (enum value) */ H5F_io_info_t fio_info; /* I/O info for operation */ - /* Flush at this point since the file will be closed. + /* Flush at this point since the file will be closed (phase 1). * Only try to flush the file if it was opened with write access, and if * the caller requested a flush. */ if((H5F_ACC_RDWR & H5F_INTENT(f)) && flush) - if(H5F_flush(f, dxpl_id, TRUE) < 0) + if(H5F__flush_phase1(f, dxpl_id) < 0) /* Push error, but keep going*/ HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache") + /* Notify the metadata cache that the file is about to be closed. + * This allows the cache to set up for creating a metadata cache + * image if this has been requested. + */ + if(H5AC_prep_for_file_close(f, dxpl_id) < 0) + /* Push error, but keep going */ + HDONE_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "metadata cache prep for close failed") + + /* Flush at this point since the file will be closed (phase 2). + * Only try to flush the file if it was opened with write access, and if + * the caller requested a flush. + */ + if((H5F_ACC_RDWR & H5F_INTENT(f)) && flush) + if(H5F__flush_phase2(f, dxpl_id, TRUE) < 0) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache") + + /* With the shutdown modifications, the contents of the metadata cache + * should be clean at this point, with the possible exception of the + * the superblock and superblock extension. + * + * Verify this. + */ + HDassert(H5AC_cache_is_clean(f, H5AC_RING_MDFSM)); + /* Release the external file cache */ if(f->shared->efc) { if(H5F_efc_destroy(f->shared->efc) < 0) @@ -837,36 +864,72 @@ H5F_dest(H5F_t *f, hid_t dxpl_id, hbool_t flush) f->shared->efc = NULL; } /* end if */ + /* With the shutdown modifications, the contents of the metadata cache + * should be clean at this point, with the possible exception of the + * the superblock and superblock extension. + * + * Verify this. + */ + HDassert(H5AC_cache_is_clean(f, H5AC_RING_MDFSM)); + /* Release objects that depend on the superblock being initialized */ if(f->shared->sblock) { /* Shutdown file free space manager(s) */ - /* (We should release the free space information now (before truncating - * the file and before the metadata cache is shut down) since the - * free space manager is holding some data structures in memory - * and also because releasing free space can shrink the file's - * 'eoa' value) + /* (We should release the free space information now (before + * truncating the file and before the metadata cache is shut + * down) since the free space manager is holding some data + * structures in memory and also because releasing free space + * can shrink the file's 'eoa' value) + * + * Update 11/1/16: + * + * With recent library shutdown modifications, the free space + * managers should be settled and written to file at this point + * (assuming they are persistent). In this case, closing the + * free space managers should have no effect on EOA. + * + * -- JRM */ if(H5F_ACC_RDWR & H5F_INTENT(f)) { if(H5MF_close(f, dxpl_id) < 0) /* Push error, but keep going*/ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release file free space info") - /* Flush the file again (if requested), as shutting down the - * free space manager may dirty some data structures again. + /* at this point, only the superblock and superblock + * extension should be dirty. */ + HDassert(H5AC_cache_is_clean(f, H5AC_RING_MDFSM)); + if(flush) { /* Clear status_flags */ f->shared->sblock->status_flags &= (uint8_t)(~H5F_SUPER_WRITE_ACCESS); f->shared->sblock->status_flags &= (uint8_t)(~H5F_SUPER_SWMR_WRITE_ACCESS); - /* Mark superblock dirty in cache, so change will get encoded */ - if(H5F_super_dirty(f) < 0) + /* Mark EOA info dirty in cache, so change will get encoded */ + if(H5F_eoa_dirty(f, dxpl_id) < 0) /* Push error, but keep going*/ HDONE_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty") - if(H5F_flush(f, dxpl_id, TRUE) < 0) + /* Release any space allocated to space aggregators, + * so that the eoa value corresponds to the end of the + * space written to in the file. + * + * At most, this should change the superblock or the + * superblock extension messages. + */ + if(H5MF_free_aggrs(f, dxpl_id) < 0) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release file space") + + /* Truncate the file to the current allocated size */ + if(H5FD_truncate(f->shared->lf, dxpl_id, TRUE) < 0) /* Push error, but keep going*/ - HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache") + HDONE_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "low level truncate failed") + + /* at this point, only the superblock and superblock + * extension should be dirty. + */ + HDassert(H5AC_cache_is_clean(f, H5AC_RING_MDFSM)); } /* end if */ } /* end if */ @@ -884,6 +947,13 @@ H5F_dest(H5F_t *f, hid_t dxpl_id, hbool_t flush) HDONE_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin superblock") f->shared->sblock = NULL; } /* end if */ + + /* with the possible exception of the superblock and superblock + * extension, the metadata cache should be clean at this point. + * + * Verify this. + */ + HDassert(H5AC_cache_is_clean(f, H5AC_RING_MDFSM)); /* Remove shared file struct from list of open files */ if(H5F_sfile_remove(f->shared) < 0) @@ -1358,25 +1428,24 @@ done: /*------------------------------------------------------------------------- - * Function: H5F_flush + * Function: H5F_flush_phase1 * - * Purpose: Flushes cached data. + * Purpose: First phase of flushing cached data. * * Return: Non-negative on success/Negative on failure * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Aug 29 1997 + * Programmer: Quincey Koziol + * koziol@lbl.gov + * Jan 1 2017 * *------------------------------------------------------------------------- */ -herr_t -H5F_flush(H5F_t *f, hid_t dxpl_id, hbool_t closing) +static herr_t +H5F__flush_phase1(H5F_t *f, hid_t dxpl_id) { - H5F_io_info_t fio_info; /* I/O info for operation */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_STATIC /* Sanity check arguments */ HDassert(f); @@ -1396,6 +1465,34 @@ H5F_flush(H5F_t *f, hid_t dxpl_id, hbool_t closing) /* Push error, but keep going*/ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release file space") + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F__flush_phase1() */ + + +/*------------------------------------------------------------------------- + * Function: H5F__flush_phase2 + * + * Purpose: Second phase of flushing cached data. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@lbl.gov + * Jan 1 2017 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F__flush_phase2(H5F_t *f, hid_t dxpl_id, hbool_t closing) +{ + H5F_io_info_t fio_info; /* I/O info for operation */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Sanity check arguments */ + HDassert(f); + /* Flush the entire metadata cache */ if(H5AC_flush(f, dxpl_id) < 0) /* Push error, but keep going*/ @@ -1403,6 +1500,7 @@ H5F_flush(H5F_t *f, hid_t dxpl_id, hbool_t closing) /* Truncate the file to the current allocated size */ if(H5FD_truncate(f->shared->lf, dxpl_id, closing) < 0) + /* Push error, but keep going*/ HDONE_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "low level truncate failed") /* Flush the entire metadata cache again since the EOA could have changed in the truncate call. */ @@ -1413,6 +1511,7 @@ H5F_flush(H5F_t *f, hid_t dxpl_id, hbool_t closing) /* Set up I/O info for operation */ fio_info.f = f; if(NULL == (fio_info.dxpl = (H5P_genplist_t *)H5I_object(dxpl_id))) + /* Push error, but keep going*/ HDONE_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list") /* Flush out the metadata accumulator */ @@ -1425,6 +1524,43 @@ H5F_flush(H5F_t *f, hid_t dxpl_id, hbool_t closing) /* Push error, but keep going*/ HDONE_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "low level flush failed") + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F__flush_phase2() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_flush + * + * Purpose: Flushes cached data. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 29 1997 + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_flush(H5F_t *f, hid_t dxpl_id, hbool_t closing) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity check arguments */ + HDassert(f); + + /* First phase of flushing data */ + if(H5F__flush_phase1(f, dxpl_id) < 0) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush file data") + + /* Second phase of flushing data */ + if(H5F__flush_phase2(f, dxpl_id, closing) < 0) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush file data") + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5F_flush() */ |