diff options
Diffstat (limited to 'src/H5Fefc.c')
-rw-r--r-- | src/H5Fefc.c | 202 |
1 files changed, 132 insertions, 70 deletions
diff --git a/src/H5Fefc.c b/src/H5Fefc.c index 5652d15..77d29f5 100644 --- a/src/H5Fefc.c +++ b/src/H5Fefc.c @@ -29,8 +29,10 @@ /* Packages needed by this file... */ #include "H5private.h" /* Generic Functions */ +#include "H5CXprivate.h" /* API Contexts */ #include "H5Eprivate.h" /* Error handling */ #include "H5Fpkg.h" /* File access */ +#include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ #include "H5Pprivate.h" /* Property lists */ @@ -57,14 +59,15 @@ struct H5F_efc_t { unsigned nfiles; /* Size of the external file cache */ unsigned max_nfiles; /* Maximum size of the external file cache */ unsigned nrefs; /* Number of times this file appears in another file's EFC */ - int tag; /* Temporary variable used by H5F_efc_try_close() */ - H5F_file_t *tmp_next; /* Next file in temporary list used by H5F_efc_try_close() */ + int tag; /* Temporary variable used by H5F__efc_try_close() */ + H5F_shared_t *tmp_next; /* Next file in temporary list used by H5F__efc_try_close() */ }; /* Private prototypes */ -static herr_t H5F_efc_remove_ent(H5F_efc_t *efc, H5F_efc_ent_t *ent); -static void H5F_efc_try_close_tag1(H5F_file_t *sf, H5F_file_t **tail); -static void H5F_efc_try_close_tag2(H5F_file_t *sf, H5F_file_t **tail); +static herr_t H5F__efc_release_real(H5F_efc_t *efc); +static herr_t H5F__efc_remove_ent(H5F_efc_t *efc, H5F_efc_ent_t *ent); +static void H5F__efc_try_close_tag1(H5F_shared_t *sf, H5F_shared_t **tail); +static void H5F__efc_try_close_tag2(H5F_shared_t *sf, H5F_shared_t **tail); /* Free lists */ H5FL_DEFINE_STATIC(H5F_efc_ent_t); @@ -72,11 +75,11 @@ H5FL_DEFINE_STATIC(H5F_efc_t); /*------------------------------------------------------------------------- - * Function: H5F_efc_create + * Function: H5F__efc_create * * Purpose: Allocate and initialize a new external file cache object, * which can the be used to cache open external files. - * the object must be freed with H5F_efc_destroy. + * the object must be freed with H5F__efc_destroy. * * Return: Pointer to new external file cache object on success * NULL on failure @@ -87,12 +90,12 @@ H5FL_DEFINE_STATIC(H5F_efc_t); *------------------------------------------------------------------------- */ H5F_efc_t * -H5F_efc_create(unsigned max_nfiles) +H5F__efc_create(unsigned max_nfiles) { H5F_efc_t *efc = NULL; /* EFC object */ H5F_efc_t *ret_value = NULL; /* Return value */ - FUNC_ENTER_NOAPI(NULL) + FUNC_ENTER_PACKAGE /* Sanity checks */ HDassert(max_nfiles > 0); @@ -115,11 +118,11 @@ done: efc = H5FL_FREE(H5F_efc_t, efc); FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_efc_create() */ +} /* end H5F__efc_create() */ /*------------------------------------------------------------------------- - * Function: H5F_efc_open + * Function: H5F__efc_open * * Purpose: Opens a file using the external file cache. The target * file is added to the external file cache of the parent @@ -138,21 +141,34 @@ done: *------------------------------------------------------------------------- */ H5F_t * -H5F_efc_open(H5F_t *parent, const char *name, unsigned flags, hid_t fcpl_id, - hid_t fapl_id, hid_t dxpl_id) +H5F__efc_open(H5F_t *parent, const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id) { H5F_efc_t *efc = NULL; /* External file cache for parent file */ H5F_efc_ent_t *ent = NULL; /* Entry for target file in efc */ hbool_t open_file = FALSE; /* Whether ent->file needs to be closed in case of error */ + H5P_genplist_t *plist; /* Property list pointer for FAPL */ + H5VL_connector_prop_t connector_prop; /* Property for VOL connector ID & info */ H5F_t *ret_value = NULL; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_PACKAGE /* Sanity checks */ HDassert(parent); HDassert(parent->shared); HDassert(name); + /* Get the VOL info from the fapl */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id))) + HGOTO_ERROR(H5E_FILE, H5E_BADTYPE, NULL, "not a file access property list") + if(H5P_peek(plist, H5F_ACS_VOL_CONN_NAME, &connector_prop) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get VOL connector info") + + /* Stash a copy of the "top-level" connector property, before any pass-through + * connectors modify or unwrap it. + */ + if(H5CX_set_vol_connector_prop(&connector_prop) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set VOL connector info in API context") + /* Get external file cache */ efc = parent->shared->efc; @@ -160,9 +176,13 @@ H5F_efc_open(H5F_t *parent, const char *name, unsigned flags, hid_t fcpl_id, * support this so clients do not have to make 2 different calls depending * on the state of the efc. */ if(!efc) { - if(NULL == (ret_value = H5F_open(name, flags, fcpl_id, fapl_id, dxpl_id))) + if(NULL == (ret_value = H5F_open(name, flags, fcpl_id, fapl_id))) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "can't open file") + /* Make file post open call */ + if(H5F__post_open(ret_value) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "can't finish opening file") + /* Increment the number of open objects to prevent the file from being * closed out from under us - "simulate" having an open file id. Note * that this behaviour replaces the calls to H5F_incr_nopen_objs() and @@ -225,16 +245,20 @@ H5F_efc_open(H5F_t *parent, const char *name, unsigned flags, hid_t fcpl_id, /* Evict the file if found, otherwise just open the target file and * do not add it to cache */ if(ent) { - if(H5F_efc_remove_ent(efc, ent) < 0) + if(H5F__efc_remove_ent(efc, ent) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTREMOVE, NULL, "can't remove entry from external file cache") /* Do not free ent, we will recycle it below */ } /* end if */ else { /* Cannot cache file, just open file and return */ - if(NULL == (ret_value = H5F_open(name, flags, fcpl_id, fapl_id, dxpl_id))) + if(NULL == (ret_value = H5F_open(name, flags, fcpl_id, fapl_id))) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "can't open file") + /* Make file post open call */ + if(H5F__post_open(ret_value) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "can't finish opening file") + /* Increment the number of open objects to prevent the file from * being closed out from under us - "simulate" having an open * file id */ @@ -253,10 +277,14 @@ H5F_efc_open(H5F_t *parent, const char *name, unsigned flags, hid_t fcpl_id, HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Open the file */ - if(NULL == (ent->file = H5F_open(name, flags, fcpl_id, fapl_id, dxpl_id))) + if(NULL == (ent->file = H5F_open(name, flags, fcpl_id, fapl_id))) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "can't open file") open_file = TRUE; + /* Make file post open call */ + if(H5F__post_open(ent->file) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "can't finish opening file") + /* Increment the number of open objects to prevent the file from being * closed out from under us - "simulate" having an open file id */ ent->file->nopen_objs++; @@ -307,7 +335,7 @@ done: } /* end if */ FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_efc_open() */ +} /* end H5F__efc_open() */ /*------------------------------------------------------------------------- @@ -375,7 +403,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5F_efc_max_nfiles + * Function: H5F__efc_max_nfiles * * Purpose: Returns the maximum number of files in the provided * external file cache. @@ -388,19 +416,19 @@ done: *------------------------------------------------------------------------- */ unsigned -H5F_efc_max_nfiles(H5F_efc_t *efc) +H5F__efc_max_nfiles(H5F_efc_t *efc) { - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_PACKAGE_NOERR HDassert(efc); HDassert(efc->max_nfiles > 0); FUNC_LEAVE_NOAPI(efc->max_nfiles) -} /* end H5F_efc_max_nfiles */ +} /* end H5F__efc_max_nfiles */ /*------------------------------------------------------------------------- - * Function: H5F_efc_release + * Function: H5F__efc_release_real * * Purpose: Releases the external file cache, potentially closing any * cached files unless they are held open from somewhere @@ -414,14 +442,14 @@ H5F_efc_max_nfiles(H5F_efc_t *efc) * *------------------------------------------------------------------------- */ -herr_t -H5F_efc_release(H5F_efc_t *efc) +static herr_t +H5F__efc_release_real(H5F_efc_t *efc) { H5F_efc_ent_t *ent = NULL; /* EFC entry */ H5F_efc_ent_t *prev_ent = NULL; /* Previous EFC entry */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC /* Sanity checks */ HDassert(efc); @@ -429,7 +457,7 @@ H5F_efc_release(H5F_efc_t *efc) /* Lock the EFC to prevent manipulation of the EFC wile we are releasing it. * The EFC should never be locked when we enter this function because that * would require a cycle, a cycle would necessarily invoke - * H5F_efc_try_close(), and that function checks the status of the lock + * H5F__efc_try_close(), and that function checks the status of the lock * before calling this one. */ HDassert((efc->tag == H5F_EFC_TAG_DEFAULT) || (efc->tag == H5F_EFC_TAG_CLOSE)); @@ -440,7 +468,7 @@ H5F_efc_release(H5F_efc_t *efc) ent = efc->LRU_head; while(ent) if(!ent->nopen) { - if(H5F_efc_remove_ent(efc, ent) < 0) + if(H5F__efc_remove_ent(efc, ent) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTREMOVE, FAIL, "can't remove entry from external file cache") /* Free the entry and move to next entry in LRU list */ @@ -458,11 +486,45 @@ H5F_efc_release(H5F_efc_t *efc) done: FUNC_LEAVE_NOAPI(ret_value); +} /* end H5F__efc_release_real() */ + + +/*------------------------------------------------------------------------- + * Function: H5F__efc_release + * + * Purpose: Releases the external file cache, potentially closing any + * cached files unless they are held open from somewhere + * else (or are currently opened by a client). + * + * Return: Non-negative on success + * Negative on failure + * + * Programmer: Quincey Koziol + * Sunday, February 18, 2018 + * + *------------------------------------------------------------------------- + */ +herr_t +H5F__efc_release(H5F_efc_t *efc) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Sanity checks */ + HDassert(efc); + + /* Call 'real' routine */ + if(H5F__efc_release_real(efc) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't remove entry from external file cache") + +done: + FUNC_LEAVE_NOAPI(ret_value) } /* end H5F_efc_release() */ /*------------------------------------------------------------------------- - * Function: H5F_efc_destroy + * Function: H5F__efc_destroy * * Purpose: Frees an external file cache object, releasing it first * if necessary. If it cannot be fully released, for example @@ -477,18 +539,18 @@ done: *------------------------------------------------------------------------- */ herr_t -H5F_efc_destroy(H5F_efc_t *efc) +H5F__efc_destroy(H5F_efc_t *efc) { herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_PACKAGE /* Sanity checks */ HDassert(efc); if(efc->nfiles > 0) { /* Release (clear) the efc */ - if(H5F_efc_release(efc) < 0) + if(H5F__efc_release_real(efc) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release external file cache") /* If there are still cached files, return an error */ @@ -510,11 +572,11 @@ H5F_efc_destroy(H5F_efc_t *efc) done: FUNC_LEAVE_NOAPI(ret_value); -} /* end H5F_efc_destroy() */ +} /* end H5F__efc_destroy() */ /*------------------------------------------------------------------------- - * Function: H5F_efc_remove_ent + * Function: H5F__efc_remove_ent * * Purpose: Removes the specified entry from the specified EFC, * closing the file if requested. Does not free the entry. @@ -528,11 +590,11 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5F_efc_remove_ent(H5F_efc_t *efc, H5F_efc_ent_t *ent) +H5F__efc_remove_ent(H5F_efc_t *efc, H5F_efc_ent_t *ent) { herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC /* Sanity checks */ HDassert(efc); @@ -576,11 +638,11 @@ H5F_efc_remove_ent(H5F_efc_t *efc, H5F_efc_ent_t *ent) done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_efc_remove_ent() */ +} /* end H5F__efc_remove_ent() */ /*------------------------------------------------------------------------- - * Function: H5F_efc_try_close_tag1 + * Function: H5F__efc_try_close_tag1 * * Purpose: Recursively traverse the EFC tree, keeping a temporary * reference count on each file that assumes all reachable @@ -594,12 +656,12 @@ done: *------------------------------------------------------------------------- */ static void -H5F_efc_try_close_tag1(H5F_file_t *sf, H5F_file_t **tail) +H5F__efc_try_close_tag1(H5F_shared_t *sf, H5F_shared_t **tail) { H5F_efc_ent_t *ent = NULL; /* EFC entry */ - H5F_file_t *esf; /* Convenience pointer to ent->file->shared */ + H5F_shared_t *esf; /* Convenience pointer to ent->file->shared */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR /* Sanity checks */ HDassert(sf); @@ -644,17 +706,17 @@ H5F_efc_try_close_tag1(H5F_file_t *sf, H5F_file_t **tail) } /* end if */ /* Recurse into the entry */ - H5F_efc_try_close_tag1(ent->file->shared, tail); + H5F__efc_try_close_tag1(ent->file->shared, tail); } /* end if */ } /* end if */ } /* end for */ FUNC_LEAVE_NOAPI_VOID -} /* end H5F_efc_try_close_tag1() */ +} /* end H5F__efc_try_close_tag1() */ /*------------------------------------------------------------------------- - * Function: H5F_efc_try_close_tag2 + * Function: H5F__efc_try_close_tag2 * * Purpose: Recuresively mark all files reachable through this one as * uncloseable, and add newly uncloseable files to the tail @@ -668,12 +730,12 @@ H5F_efc_try_close_tag1(H5F_file_t *sf, H5F_file_t **tail) *------------------------------------------------------------------------- */ static void -H5F_efc_try_close_tag2(H5F_file_t *sf, H5F_file_t **tail) +H5F__efc_try_close_tag2(H5F_shared_t *sf, H5F_shared_t **tail) { H5F_efc_ent_t *ent = NULL; /* EFC entry */ - H5F_file_t *esf; /* Convenience pointer to ent->file->shared */ + H5F_shared_t *esf; /* Convenience pointer to ent->file->shared */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR /* Sanity checks */ HDassert(sf); @@ -715,17 +777,17 @@ H5F_efc_try_close_tag2(H5F_file_t *sf, H5F_file_t **tail) } /* end if */ /* Recurse into the entry */ - H5F_efc_try_close_tag2(esf, tail); + H5F__efc_try_close_tag2(esf, tail); } /* end if */ } /* end if */ } /* end for */ FUNC_LEAVE_NOAPI_VOID -} /* end H5F_efc_try_close_tag2() */ +} /* end H5F__efc_try_close_tag2() */ /*------------------------------------------------------------------------- - * Function: H5F_efc_try_close + * Function: H5F__efc_try_close * * Purpose: Attempts to close the provided (shared) file by checking * to see if the releasing the EFC would cause its reference @@ -741,7 +803,7 @@ H5F_efc_try_close_tag2(H5F_file_t *sf, H5F_file_t **tail) * "callback" for the final pass (the one where the files are * actually closed). The code for the callback case is at * the top of this function; luckily it only consists of a - * (possible) call to H5F_efc_release(). + * (possible) call to H5F__efc_release_real(). * * The algorithm basically consists of 3 passes over the EFC * tree. The first pass assumes that every reachable file is @@ -757,8 +819,8 @@ H5F_efc_try_close_tag2(H5F_file_t *sf, H5F_file_t **tail) * closeable only because the first pass assumed that an * uncloseable file would be closed. * - * The final pass exploits the H5F_efc_release()-> - * H5F_efc_remove_ent()->H5F_try_close()->H5F_efc_try_close() + * The final pass exploits the H5F__efc_release_real()-> + * H5F__efc_remove_ent()->H5F_try_close()->H5F__efc_try_close() * calling chain to recursively close the tree, but only the * files that are still marked as closeable. All files * marked as closeable have their EFCs released, and will @@ -775,16 +837,16 @@ H5F_efc_try_close_tag2(H5F_file_t *sf, H5F_file_t **tail) *------------------------------------------------------------------------- */ herr_t -H5F_efc_try_close(H5F_t *f) +H5F__efc_try_close(H5F_t *f) { - H5F_file_t *tail; /* Tail of linked list of found files. Head will be f->shared. */ - H5F_file_t *uncloseable_head = NULL; /* Head of linked list of files found to be uncloseable by the first pass */ - H5F_file_t *uncloseable_tail = NULL; /* Tail of linked list of files found to be uncloseable by the first pass */ - H5F_file_t *sf; /* Temporary file pointer */ - H5F_file_t *next; /* Temporary file pointer */ + H5F_shared_t *tail; /* Tail of linked list of found files. Head will be f->shared. */ + H5F_shared_t *uncloseable_head = NULL; /* Head of linked list of files found to be uncloseable by the first pass */ + H5F_shared_t *uncloseable_tail = NULL; /* Tail of linked list of files found to be uncloseable by the first pass */ + H5F_shared_t *sf; /* Temporary file pointer */ + H5F_shared_t *next; /* Temporary file pointer */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_PACKAGE /* Sanity checks */ HDassert(f); @@ -798,8 +860,8 @@ H5F_efc_try_close(H5F_t *f) /* We must have reentered this function, and we should close this file. * In actuality, we just release the EFC, the recursion should * eventually reduce this file's reference count to 1 (though possibly - * not from this call to H5F_efc_release()). */ - if(H5F_efc_release(f->shared->efc) < 0) + * not from this call to H5F__efc_release_real()). */ + if(H5F__efc_release_real(f->shared->efc) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release external file cache") /* If we marked the file as closeable, there must be no open files in @@ -816,8 +878,8 @@ H5F_efc_try_close(H5F_t *f) /* Conditions where we should not do anything and just return immediately */ /* If there are references that are not from an EFC or f, it will never * be possible to close the file. Just return. Note that this holds true - * for the case that this file is being closed through H5F_efc_release() - * because that function (through H5F_efc_remove_ent()) decrements the EFC + * for the case that this file is being closed through H5F__efc_release_real() + * because that function (through H5F__efc_remove_ent()) decrements the EFC * reference count before it calls H5F_try_close(). This may occur if this * function is reentered. */ /* If the tag is H5F_EFC_TAG_DONTCLOSE, then we have definitely reentered @@ -833,7 +895,7 @@ H5F_efc_try_close(H5F_t *f) HGOTO_DONE(SUCCEED) /* If the file EFC were locked, that should always mean that there exists - * a reference to this file that is not in an EFC (it may have just been + * a reference to this file that is not in an EFC (it may have just been * removed from an EFC), and should have been caught by the above check */ /* If we get here then we must be beginning a new run. Make sure that the * temporary variables in f->shared->efc are at the default value */ @@ -851,7 +913,7 @@ H5F_efc_try_close(H5F_t *f) * field to keep track of final reference count for each file (including * this one). Keep list of files with starting reference count > 1 (head is * f->shared). */ - H5F_efc_try_close_tag1(f->shared, &tail); + H5F__efc_try_close_tag1(f->shared, &tail); /* Check if f->shared->efc->tag dropped to 0. If it did not, * we cannot close anything. Just reset temporary values and return. */ @@ -909,7 +971,7 @@ H5F_efc_try_close(H5F_t *f) tail = uncloseable_tail; HDassert(tail); while(sf != tail->efc->tmp_next) { - H5F_efc_try_close_tag2(sf, &uncloseable_tail); + H5F__efc_try_close_tag2(sf, &uncloseable_tail); sf = sf->efc->tmp_next; } /* end while */ } /* end if */ @@ -918,7 +980,7 @@ H5F_efc_try_close(H5F_t *f) * should start the recursive release that should close all closeable files. * Also, see the top of this function. */ if(f->shared->efc->tag == H5F_EFC_TAG_CLOSE) { - if(H5F_efc_release(f->shared->efc) < 0) + if(H5F__efc_release_real(f->shared->efc) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release external file cache") /* Make sure the file's reference count is now 1 and will be closed by @@ -941,5 +1003,5 @@ H5F_efc_try_close(H5F_t *f) done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_efc_try_close() */ +} /* end H5F__efc_try_close() */ |