summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MANIFEST2
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/H5F.c62
-rw-r--r--src/H5Fefc.c951
-rw-r--r--src/H5Fpkg.h12
-rw-r--r--src/H5Fprivate.h6
-rw-r--r--src/H5Fpublic.h1
-rw-r--r--src/H5Lexternal.c31
-rw-r--r--src/H5Pfapl.c85
-rw-r--r--src/H5Ppublic.h2
-rwxr-xr-xsrc/Makefile.am4
-rw-r--r--src/Makefile.in31
-rw-r--r--test/CMakeLists.txt8
-rw-r--r--test/Makefile.am4
-rw-r--r--test/Makefile.in22
-rw-r--r--test/efc.c3213
-rw-r--r--test/links.c528
17 files changed, 4872 insertions, 91 deletions
diff --git a/MANIFEST b/MANIFEST
index 790d556..dd9c0dc 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -523,6 +523,7 @@
./src/H5Faccum.c
./src/H5Fdbg.c
./src/H5Fdeprec.c
+./src/H5Fefc.c
./src/H5Ffake.c
./src/H5Fio.c
./src/H5Fmount.c
@@ -830,6 +831,7 @@
./test/dtypes.c
./test/dtransform.c
./test/earray.c
+./test/efc.c
./test/enum.c
./test/extend.c
./test/external.c
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 3330b8b..93370c0 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -145,6 +145,7 @@ SET (H5F_SRCS
${HDF5_SRC_DIR}/H5Faccum.c
${HDF5_SRC_DIR}/H5Fdbg.c
${HDF5_SRC_DIR}/H5Fdeprec.c
+ ${HDF5_SRC_DIR}/H5Fefc.c
${HDF5_SRC_DIR}/H5Ffake.c
${HDF5_SRC_DIR}/H5Fio.c
${HDF5_SRC_DIR}/H5Fmount.c
diff --git a/src/H5F.c b/src/H5F.c
index 46d9407..f84dea2 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -292,6 +292,7 @@ H5F_get_access_plist(H5F_t *f, hbool_t app_ref)
H5P_genplist_t *new_plist; /* New property list */
H5P_genplist_t *old_plist; /* Old property list */
void *driver_info=NULL;
+ unsigned efc_size = 0;
hid_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5F_get_access_plist, FAIL)
@@ -330,6 +331,10 @@ H5F_get_access_plist(H5F_t *f, hbool_t app_ref)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set 'small data' cache size")
if(H5P_set(new_plist, H5F_ACS_LATEST_FORMAT_NAME, &(f->shared->latest_format)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set 'latest format' flag")
+ if(f->shared->efc)
+ efc_size = H5F_efc_max_nfiles(f->shared->efc);
+ if(H5P_set(new_plist, H5F_ACS_EFC_SIZE_NAME, &efc_size) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set elink file cache size")
/*
* Since we're resetting the driver ID and info, close them if they
@@ -840,6 +845,7 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf)
} /* end if */
else {
H5P_genplist_t *plist; /* Property list */
+ unsigned efc_size; /* External file cache size */
size_t u; /* Local index variable */
HDassert(lf != NULL);
@@ -902,6 +908,11 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf)
if(H5P_get(plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(f->shared->sdata_aggr.alloc_size)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'small data' cache size")
f->shared->sdata_aggr.feature_flag = H5FD_FEAT_AGGREGATE_SMALLDATA;
+ if(H5P_get(plist, H5F_ACS_EFC_SIZE_NAME, &efc_size) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get elink file cache size")
+ if(efc_size > 0)
+ if(NULL == (f->shared->efc = H5F_efc_create(efc_size)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "can't create external file cache")
/* Get the VFD values to cache */
f->shared->maxaddr = H5FD_get_maxaddr(lf);
@@ -998,6 +1009,13 @@ H5F_dest(H5F_t *f, hid_t dxpl_id, hbool_t flush)
if(H5F_flush(f, dxpl_id) < 0)
HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache")
+ /* Release the external file cache */
+ if(f->shared->efc) {
+ if(H5F_efc_destroy(f->shared->efc) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't destroy external file cache")
+ f->shared->efc = NULL;
+ } /* end if */
+
/* Release objects that depend on the superblock being initialized */
if(f->shared->sblock) {
/* Shutdown file free space manager(s) */
@@ -1903,6 +1921,13 @@ H5F_try_close(H5F_t *f)
if(H5F_close_mounts(f) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't unmount child files")
+ /* If there is more than one reference to the shared file struct and the
+ * file has an external file cache, we should see if it can be closed. This
+ * can happen if a cycle is formed with external file caches */
+ if(f->shared->efc && (f->shared->nrefs > 1))
+ if(H5F_efc_try_close(f) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't attempt to close EFC")
+
/* 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). */
@@ -2929,3 +2954,40 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Fget_free_sections() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5Frelease_file_cache
+ *
+ * Purpose: Releases the external file cache associated with the
+ * provided file, potentially closing any cached files
+ * unless they are held open from somewhere\ else.
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Neil Fortner; December 30, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Frelease_file_cache(hid_t file_id)
+{
+ H5F_t *file; /* File */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(H5Frelease_file_cache, FAIL)
+ H5TRACE1("e", "i", file_id);
+
+ /* Check args */
+ if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
+
+ /* Release the EFC */
+ if(file->shared->efc)
+ if(H5F_efc_release(file->shared->efc) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release external file cache")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Frelease_file_cache() */
+
diff --git a/src/H5Fefc.c b/src/H5Fefc.c
new file mode 100644
index 0000000..eebf143
--- /dev/null
+++ b/src/H5Fefc.c
@@ -0,0 +1,951 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5Defc.c
+ * December 13, 2010
+ * Neil Fortner <nfortne2@hdfgroup.org>
+ *
+ * Purpose: External file caching routines - implements a
+ * cache of external files to minimize the number of
+ * file opens and closes.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+
+
+/* Packages needed by this file... */
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* File access */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5Pprivate.h" /* Property lists */
+
+
+/* Special values for the "tag" field below */
+#define H5F_EFC_TAG_DEFAULT -1
+#define H5F_EFC_TAG_LOCK -2
+#define H5F_EFC_TAG_CLOSE -3
+#define H5F_EFC_TAG_DONTCLOSE -4
+
+/* Structure for each entry in a file's external file cache */
+typedef struct H5F_efc_ent_t {
+ char *name; /* Name of the file */
+ H5F_t *file; /* File object */
+ struct H5F_efc_ent_t *LRU_next; /* Next item in LRU list */
+ struct H5F_efc_ent_t *LRU_prev; /* Previous item in LRU list */
+ unsigned nopen; /* Number of times this file is currently opened by an EFC client */
+} H5F_efc_ent_t;
+
+/* Structure for a shared file struct's external file cache */
+struct H5F_efc_t {
+ H5SL_t *slist; /* Skip list of cached external files */
+ H5F_efc_ent_t *LRU_head; /* Head of LRU list. This is the least recently used file */
+ H5F_efc_ent_t *LRU_tail; /* Tail of LRU list. This is the most recently used file */
+ 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() */
+};
+
+/* 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);
+
+/* Free lists */
+H5FL_DEFINE_STATIC(H5F_efc_ent_t);
+H5FL_DEFINE_STATIC(H5F_efc_t);
+
+
+/*-------------------------------------------------------------------------
+ * 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.
+ *
+ * Return: Pointer to new external file cache object on success
+ * NULL on failure
+ *
+ * Programmer: Neil Fortner
+ * Tuesday, December 14, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+H5F_efc_t *
+H5F_efc_create(unsigned max_nfiles)
+{
+ H5F_efc_t *efc = NULL; /* EFC object */
+ H5F_efc_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5F_efc_create, NULL)
+
+ /* Sanity checks */
+ HDassert(max_nfiles > 0);
+
+ /* Allocate EFC struct */
+ if(NULL == (efc = H5FL_CALLOC(H5F_efc_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+ /* Initialize maximum number of files */
+ efc->max_nfiles = max_nfiles;
+
+ /* Initialize temporary ref count */
+ efc->tag = H5F_EFC_TAG_DEFAULT;
+
+ /* Set the return value */
+ ret_value = efc;
+
+done:
+ if(ret_value == NULL && efc)
+ efc = H5FL_FREE(H5F_efc_t, efc);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_efc_create() */
+
+
+/*-------------------------------------------------------------------------
+ * 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
+ * if it is not already present. If the target file is in
+ * the parent's EFC, simply returns the target file. When
+ * the file object is no longer in use, it should be closed
+ * with H5F_efc_close (will not actually close the file
+ * until it is evicted from the EFC).
+ *
+ * Return: Pointer to open file on success
+ * NULL on failure
+ *
+ * Programmer: Neil Fortner
+ * Tuesday, December 14, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+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_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 */
+ H5F_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5F_efc_open)
+
+ /* Sanity checks */
+ HDassert(parent);
+ HDassert(parent->shared);
+ HDassert(name);
+
+ /* Get external file cache */
+ efc = parent->shared->efc;
+
+ /* Check if the EFC exists. If it does not, just call H5F_open(). We
+ * 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)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "can't open 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
+ * H5F_decr_nopen_objs() in H5L_extern_traverse(). */
+ ret_value->nopen_objs++;
+
+ HGOTO_DONE(ret_value)
+ } /* end if */
+
+ /* Search the skip list for name if the skip list exists, create the skip
+ * list otherwise */
+ if(efc->slist) {
+ if(efc->nfiles > 0)
+ ent = (H5F_efc_ent_t *)H5SL_search(efc->slist, name);
+ } /* end if */
+ else {
+ HDassert(efc->nfiles == 0);
+ if(NULL == (efc->slist = H5SL_create(H5SL_TYPE_STR)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, NULL, "can't create skip list")
+ } /* end else */
+
+ /* If we found the file update the LRU list and return the cached file,
+ * otherwise open the file and cache it */
+ if(ent) {
+ HDassert(efc->LRU_head);
+ HDassert(efc->LRU_tail);
+
+ /* Move ent to the head of the LRU list, if it is not already there */
+ if(ent->LRU_prev) {
+ HDassert(efc->LRU_head != ent);
+
+ /* Remove from current position. Note that once we touch the LRU
+ * list we cannot revert to the previous state. Make sure there can
+ * be no errors between when we first touch the LRU list and when
+ * the cache is in a consistent state! */
+ if(ent->LRU_next)
+ ent->LRU_next->LRU_prev = ent->LRU_prev;
+ else {
+ HDassert(efc->LRU_tail == ent);
+ efc->LRU_tail = ent->LRU_prev;
+ } /* end else */
+ ent->LRU_prev->LRU_next = ent->LRU_next;
+
+ /* Add to head of LRU list */
+ ent->LRU_next = efc->LRU_head;
+ ent->LRU_next->LRU_prev = ent;
+ ent->LRU_prev = NULL;
+ efc->LRU_head = ent;
+ } /* end if */
+
+ /* Mark the file as open */
+ ent->nopen++;
+ } /* end if */
+ else {
+ /* Check if we need to evict something */
+ if(efc->nfiles == efc->max_nfiles) {
+ /* Search for an unopened file from the tail */
+ for(ent = efc->LRU_tail; ent && ent->nopen; ent = ent->LRU_prev);
+
+ /* 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)
+ 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)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "can't open file")
+
+ /* Increment the number of open objects to prevent the file from
+ * being closed out from under us - "simulate" having an open
+ * file id */
+ ret_value->nopen_objs++;
+
+ HGOTO_DONE(ret_value)
+ } /* end else */
+ } /* end if */
+ else
+ /* Allocate new entry */
+ if(NULL == (ent = H5FL_MALLOC(H5F_efc_ent_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+ /* Build new entry */
+ if(NULL == (ent->name = H5MM_strdup(name)))
+ 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)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "can't open file")
+ open_file = TRUE;
+
+ /* 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++;
+
+ /* Add the file to the cache */
+ /* Skip list */
+ if(H5SL_insert(efc->slist, ent, ent->name) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINSERT, NULL, "can't insert entry into skip list")
+
+ /* Add to head of LRU list and update tail if necessary */
+ ent->LRU_next = efc->LRU_head;
+ if(ent->LRU_next)
+ ent->LRU_next->LRU_prev = ent;
+ ent->LRU_prev = NULL;
+ efc->LRU_head = ent;
+ if(!efc->LRU_tail) {
+ HDassert(!ent->LRU_next);
+ efc->LRU_tail = ent;
+ } /* end if */
+
+ /* Mark the file as open */
+ ent->nopen = 1;
+
+ /* Update nfiles and nrefs */
+ efc->nfiles++;
+ if(ent->file->shared->efc)
+ ent->file->shared->efc->nrefs++;
+ } /* end else */
+
+ HDassert(ent);
+ HDassert(ent->file);
+ HDassert(ent->name);
+ HDassert(ent->nopen);
+
+ /* Set the return value */
+ ret_value = ent->file;
+
+done:
+ if(!ret_value)
+ if(ent) {
+ if(open_file) {
+ ent->file->nopen_objs--;
+ if(H5F_try_close(ent->file) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, NULL, "can't close external file")
+ } /* end if */
+ ent->name = (char *)H5MM_xfree(ent->name);
+ ent = H5FL_FREE(H5F_efc_ent_t, ent);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_efc_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_efc_close
+ *
+ * Purpose: Closes (unlocks) a file opened using the external file
+ * cache. The target file is not immediately closed unless
+ * there is no external file cache for the parent file.
+ *
+ * Return: Non-negative on success
+ * Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * Wednesday, December 15, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_efc_close(H5F_t *parent, H5F_t *file)
+{
+ H5F_efc_t *efc = NULL; /* External file cache for parent file */
+ H5F_efc_ent_t *ent = NULL; /* Entry for target file in efc */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5F_efc_close)
+
+ /* Sanity checks */
+ HDassert(parent);
+ HDassert(parent->shared);
+ HDassert(file);
+ HDassert(file->shared);
+
+ /* Get external file cache */
+ efc = parent->shared->efc;
+
+ /* Check if the EFC exists. If it does not, just call H5F_try_close(). We
+ * support this so clients do not have to make 2 different calls depending
+ * on the state of the efc. */
+ if(!efc) {
+ file->nopen_objs--;
+ if(H5F_try_close(file) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close external file")
+
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+
+ /* Scan the parent's LRU list from the head to file file. We do this
+ * instead of a skip list lookup because the file will almost always be at
+ * the head. In the unlikely case that the file is not found, just call
+ * H5F_try_close(). This could happen if the EFC was full of open files
+ * when the file was opened. */
+ for(ent = efc->LRU_head; ent && ent->file != file; ent = ent->LRU_next);
+ if(!ent) {
+ file->nopen_objs--;
+ if(H5F_try_close(file) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close external file")
+ } /* end if */
+ else
+ /* Reduce the open count on this entry */
+ ent->nopen--;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_efc_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_efc_max_nfiles
+ *
+ * Purpose: Returns the maximum number of files in the provided
+ * external file cache.
+ *
+ * Return: Maximum number of files (never fails)
+ *
+ * Programmer: Neil Fortner
+ * Wednesday, December 15, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+H5F_efc_max_nfiles(H5F_efc_t *efc)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_efc_max_nfiles)
+
+ HDassert(efc);
+ HDassert(efc->max_nfiles > 0);
+
+ FUNC_LEAVE_NOAPI(efc->max_nfiles)
+} /* end H5F_efc_max_nfiles */
+
+
+/*-------------------------------------------------------------------------
+ * 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: Neil Fortner
+ * Wednesday, December 15, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_efc_release(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(H5F_efc_release)
+
+ /* Sanity checks */
+ HDassert(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
+ * before calling this one. */
+ HDassert((efc->tag == H5F_EFC_TAG_DEFAULT)
+ || (efc->tag == H5F_EFC_TAG_CLOSE));
+ efc->tag = H5F_EFC_TAG_LOCK;
+
+ /* Walk down the LRU list, releasing any files that are not opened by an EFC
+ * client */
+ ent = efc->LRU_head;
+ while(ent)
+ if(!ent->nopen) {
+ 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 */
+ prev_ent = ent;
+ ent = ent->LRU_next;
+ prev_ent = H5FL_FREE(H5F_efc_ent_t, prev_ent);
+ } /* end if */
+ else
+ /* Can't release file because it's open; just advance the pointer */
+ ent = ent->LRU_next;
+
+ /* Reset tag. No need to reset to CLOSE if that was the original tag, as in
+ * that case the file must be getting closed anyways. */
+ efc->tag = H5F_EFC_TAG_DEFAULT;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5F_efc_release() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_efc_destroy
+ *
+ * Purpose: Frees an external file cache object, releasing it first
+ * if necessary. If it cannot be fully released, for example
+ * if there are open files, returns an error.
+ *
+ * Return: Non-negative on success
+ * Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * Wednesday, December 15, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_efc_destroy(H5F_efc_t *efc)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5F_efc_destroy)
+
+ /* Sanity checks */
+ HDassert(efc);
+
+ if(efc->nfiles > 0) {
+ /* Release (clear) the efc */
+ if(H5F_efc_release(efc) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release external file cache")
+
+ /* If there are still cached files, return an error */
+ if(efc->nfiles > 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "can't destroy EFC after incomplete release")
+ } /* end if */
+
+ HDassert(efc->nfiles == 0);
+ HDassert(efc->LRU_head == NULL);
+ HDassert(efc->LRU_tail == NULL);
+
+ /* Close skip list */
+ if(efc->slist)
+ if(H5SL_close(efc->slist) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "can't close skip list")
+
+ /* Free EFC object */
+ (void)H5FL_FREE(H5F_efc_t, efc);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5F_efc_destroy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_efc_remove_ent
+ *
+ * Purpose: Removes the specified entry from the specified EFC,
+ * closing the file if requested. Does not free the entry.
+ *
+ * Return: Non-negative on success
+ * Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * Wednesday, December 15, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F_efc_remove_ent(H5F_efc_t *efc, H5F_efc_ent_t *ent)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5F_efc_remove_ent)
+
+ /* Sanity checks */
+ HDassert(efc);
+ HDassert(efc->slist);
+ HDassert(ent);
+
+ /* Remove from skip list */
+ if(ent != H5SL_remove(efc->slist, ent->name))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTDELETE, FAIL, "can't delete entry from skip list")
+
+ /* Remove from LRU list */
+ if(ent->LRU_next)
+ ent->LRU_next->LRU_prev = ent->LRU_prev;
+ else {
+ HDassert(efc->LRU_tail == ent);
+ efc->LRU_tail = ent->LRU_prev;
+ } /* end else */
+ if(ent->LRU_prev)
+ ent->LRU_prev->LRU_next = ent->LRU_next;
+ else {
+ HDassert(efc->LRU_head == ent);
+ efc->LRU_head = ent->LRU_next;
+ } /* end else */
+
+ /* Update nfiles and nrefs */
+ efc->nfiles--;
+ if(ent->file->shared->efc)
+ ent->file->shared->efc->nrefs--;
+
+ /* Free the name */
+ ent->name = (char *)H5MM_xfree(ent->name);
+
+ /* Close the file. Note that since H5F_t structs returned from H5F_open()
+ * are *always* unique, there is no need to reference count this struct.
+ * However we must still manipulate the nopen_objs field to prevent the file
+ * from being closed out from under us. */
+ ent->file->nopen_objs--;
+ if(H5F_try_close(ent->file) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close external file")
+ ent->file = NULL;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_efc_remove_ent() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_efc_try_close_tag1
+ *
+ * Purpose: Recursively traverse the EFC tree, keeping a temporary
+ * reference count on each file that assumes all reachable
+ * files will eventually be closed.
+ *
+ * Return: void (never fails)
+ *
+ * Programmer: Neil Fortner
+ * Monday, January 10, 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+H5F_efc_try_close_tag1(H5F_file_t *sf, H5F_file_t **tail)
+{
+ H5F_efc_ent_t *ent = NULL; /* EFC entry */
+ H5F_file_t *esf; /* Convenience pointer to ent->file->shared */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_efc_try_close_tag1)
+
+ /* Sanity checks */
+ HDassert(sf);
+ HDassert(sf->efc);
+ HDassert((sf->efc->tag > 0) || (sf->nrefs == sf->efc->nrefs));
+ HDassert(sf->efc->tag != H5F_EFC_TAG_LOCK);
+ HDassert(tail);
+ HDassert(*tail);
+
+ /* Recurse into this file's cached files */
+ for(ent = sf->efc->LRU_head; ent; ent = ent->LRU_next) {
+ esf = ent->file->shared;
+
+ if(esf->efc) {
+ /* If tag were 0, that would mean there are more actual references
+ * than are counted by nrefs */
+ HDassert(esf->efc->tag != 0);
+
+ /* If tag has been set, we have already visited this file so just
+ * decrement tag and continue */
+ if(esf->efc->tag > 0)
+ esf->efc->tag--;
+ /* If there are references that are not from an EFC, it will never
+ * be possible to close the file. Just continue. Also continue if
+ * the EFC is locked or the file is open (through the EFC). Note
+ * that the reference counts will never match for the root file, but
+ * that's ok because the root file will always have a tag and enter
+ * the branch above. */
+ else if((esf->nrefs == esf->efc->nrefs)
+ && (esf->efc->tag != H5F_EFC_TAG_LOCK) && !(ent->nopen)) {
+ /* If we get here, this file's "tmp_next" pointer must be NULL
+ */
+ HDassert(esf->efc->tmp_next == NULL);
+
+ /* If nrefs > 1, Add this file to the list of files with nrefs >
+ * 1 and initialize tag to the number of references (except this
+ * one) */
+ if(esf->nrefs > 1) {
+ (*tail)->efc->tmp_next = esf;
+ *tail = esf;
+ esf->efc->tag = (int)esf->nrefs - 1;
+ } /* end if */
+
+ /* Recurse into the entry */
+ 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() */
+
+
+/*-------------------------------------------------------------------------
+ * 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
+ * of the provided linked list.
+ *
+ * Return: void (never fails)
+ *
+ * Programmer: Neil Fortner
+ * Monday, January 10, 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+H5F_efc_try_close_tag2(H5F_file_t *sf, H5F_file_t **tail)
+{
+ H5F_efc_ent_t *ent = NULL; /* EFC entry */
+ H5F_file_t *esf; /* Convenience pointer to ent->file->shared */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_efc_try_close_tag2)
+
+ /* Sanity checks */
+ HDassert(sf);
+ HDassert(sf->efc);
+
+ /* Recurse into this file's cached files */
+ for(ent = sf->efc->LRU_head; ent; ent = ent->LRU_next) {
+ esf = ent->file->shared;
+
+ /* Only recurse if the file is tagged CLOSE or DEFAULT. If it is tagged
+ * DONTCLOSE, we have already visited this file *or* it will be the
+ * start point of another iteration. No files should be tagged with a
+ * nonegative value at this point. If it is tagged as DEFAULT, we must
+ * apply the same conditions as in cb1 above for recursion in order to
+ * make sure we do not go off into somewhere cb1 didn't touch. The
+ * root file should never be tagged DEFAULT here, so the reference check
+ * is still appropriate. */
+ if((esf->efc) && ((esf->efc->tag == H5F_EFC_TAG_CLOSE)
+ || ((esf->efc->tag == H5F_EFC_TAG_DEFAULT)
+ && (esf->nrefs == esf->efc->nrefs) && !(ent->nopen)))) {
+ /* tag should always be CLOSE is nrefs > 1 or DEFAULT if nrefs == 1
+ * here */
+ HDassert(((esf->nrefs > 1)
+ && ((esf->efc->tag == H5F_EFC_TAG_CLOSE)))
+ || ((esf->nrefs == 1)
+ && (esf->efc->tag == H5F_EFC_TAG_DEFAULT)));
+
+ /* If tag is set to DONTCLOSE, we have already visited this file
+ * *or* it will be the start point of another iteration so just
+ * continue */
+ if(esf->efc->tag != H5F_EFC_TAG_DONTCLOSE) {
+ /* If tag is CLOSE, set to DONTCLOSE and add to the list of
+ * uncloseable files. */
+ if(esf->efc->tag == H5F_EFC_TAG_CLOSE) {
+ esf->efc->tag = H5F_EFC_TAG_DONTCLOSE;
+ esf->efc->tmp_next = NULL;
+ (*tail)->efc->tmp_next = esf;
+ *tail = esf;
+ } /* end if */
+
+ /* Recurse into the entry */
+ H5F_efc_try_close_tag2(esf, tail);
+ } /* end if */
+ } /* end if */
+ } /* end for */
+
+ FUNC_LEAVE_NOAPI_VOID
+} /* end H5F_efc_try_close_tag2() */
+
+
+/*-------------------------------------------------------------------------
+ * 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
+ * count to drop to 0. Necessary to handle the case where
+ * chained EFCs form a cycle. Note that this function does
+ * not actually close the file (though it closes all children
+ * as appropriate), as that is left up to the calling
+ * function H5F_try_close().
+ *
+ * Because H5F_try_close() has no way of telling if it is
+ * called recursively from within this function, this
+ * function serves as both the root of iteration and the
+ * "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().
+ *
+ * The algorithm basically consists of 3 passes over the EFC
+ * tree. The first pass assumes that every reachable file is
+ * closed, and keeps track of what the final reference count
+ * would be for every reachable file. The files are then
+ * tagged as either closeable or uncloseable based on whether
+ * this reference count drops to 0.
+ *
+ * The second pass initiates a traversal from each file
+ * marked as uncloseable in the first pass, and marks every
+ * file reachable from the initial uncloseable file as
+ * uncloseable. This eliminates files that were marked as
+ * 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()
+ * 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
+ * eventually be closed when their last parent EFC is
+ * released (the last part is guaranteed to be true by the
+ * first 2 passes).
+ *
+ * Return: Non-negative on success
+ * Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * Thursday, January 6, 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+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 */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5F_efc_try_close)
+
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->efc);
+ HDassert(f->shared->nrefs > f->shared->efc->nrefs);
+ HDassert(f->shared->nrefs > 1);
+ HDassert(f->shared->efc->tag < 0);
+
+ if(f->shared->efc->tag == H5F_EFC_TAG_CLOSE) {
+ /* 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)
+ 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
+ * its EFC. This is because, in order to close an open child file, the
+ * client must keep a copy of the parent file open. The algorithm
+ * detect that the parent file is open (directly or through an EFC) and
+ * refuse to close it. Verify that all files were released from this
+ * EFC (i.e. none were open). */
+ HDassert(f->shared->efc->nfiles == 0);
+
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+
+ /* 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
+ * 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
+ * this function, and this file has been marked as uncloseable, so we should
+ * not close/release it */
+ /* If nfiles is 0, then there is nothing to do. Just return. This may also
+ * occur on reentry (for example if this file was previously released). */
+ if((f->shared->nrefs != f->shared->efc->nrefs + 1)
+ || (f->shared->efc->tag == H5F_EFC_TAG_DONTCLOSE)
+ || (f->shared->efc->nfiles == 0))
+ /* We must have reentered this function, and we should not close this
+ * file. Just return. */
+ 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
+ * 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 */
+ HDassert(f->shared->efc->tag == H5F_EFC_TAG_DEFAULT);
+ HDassert(f->shared->efc->tmp_next == NULL);
+
+ /* Set up linked list for traversal into EFC tree. f->shared is guaranteed
+ * to always be at the head. */
+ tail = f->shared;
+
+ /* Set up temporary reference count on root file */
+ f->shared->efc->tag = (int)f->shared->efc->nrefs;
+
+ /* First Pass: simulate closing all files reachable from this one, use "tag"
+ * 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);
+
+ /* Check if f->shared->efc->tag dropped to 0. If it did not,
+ * we cannot close anything. Just reset temporary values and return. */
+ if(f->shared->efc->tag > 0) {
+ sf = f->shared;
+ while(sf) {
+ next = sf->efc->tmp_next;
+ sf->efc->tag = H5F_EFC_TAG_DEFAULT;
+ sf->efc->tmp_next = NULL;
+ sf = next;
+ } /* end while */
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+
+ /* Run through the linked list , separating into two lists, one with tag ==
+ * 0 and one with tag > 0. Mark them as either H5F_EFC_TAG_CLOSE or
+ * H5F_EFC_TAG_DONTCLOSE as appropriate. */
+ sf = f->shared;
+ tail = NULL;
+ while(sf) {
+ HDassert(sf->efc->tag >= 0);
+ next = sf->efc->tmp_next;
+ if(sf->efc->tag > 0) {
+ /* Remove from main list */
+ HDassert(tail);
+ tail->efc->tmp_next = sf->efc->tmp_next;
+ sf->efc->tmp_next = NULL;
+
+ /* Add to uncloseable list */
+ if(!uncloseable_head)
+ uncloseable_head = sf;
+ else
+ uncloseable_tail->efc->tmp_next = sf;
+ uncloseable_tail = sf;
+
+ /* Mark as uncloseable */
+ sf->efc->tag = H5F_EFC_TAG_DONTCLOSE;
+ } /* end if */
+ else {
+ sf->efc->tag = H5F_EFC_TAG_CLOSE;
+ tail = sf;
+ } /* end else */
+ sf = next;
+ } /* end while */
+
+ /* Second pass: Determine which of the reachable files found in pass 1
+ * cannot be closed by releasing the root file's EFC. Run through the
+ * uncloseable list, for each item traverse the files reachable through the
+ * EFC, mark the file as uncloseable, and add it to the list of uncloseable
+ * files (for cleanup). Use "tail" to store the original uncloseable tail
+ * so we know when to stop. We do not need to keep track of the closeable
+ * list any more. */
+ sf = uncloseable_head;
+ if(sf) {
+ tail = uncloseable_tail;
+ HDassert(tail);
+ while(sf != tail->efc->tmp_next) {
+ H5F_efc_try_close_tag2(sf, &uncloseable_tail);
+ sf = sf->efc->tmp_next;
+ } /* end while */
+ } /* end if */
+
+ /* If the root file's tag is still H5F_EFC_TAG_CLOSE, release its EFC. This
+ * 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)
+ 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
+ * H5F_dest(). */
+ HDassert(f->shared->nrefs == 1);
+ } /* end if */
+
+ /* Clean up uncloseable files (reset tag and tmp_next). All closeable files
+ * should have been closed, and therefore do not need to be cleaned up. */
+ if(uncloseable_head) {
+ sf = uncloseable_head;
+ while(sf) {
+ next = sf->efc->tmp_next;
+ HDassert(sf->efc->tag == H5F_EFC_TAG_DONTCLOSE);
+ sf->efc->tag = H5F_EFC_TAG_DEFAULT;
+ sf->efc->tmp_next = NULL;
+ sf = next;
+ } /* end while */
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_efc_try_close() */
+
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index c98bda4..f63fa98 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -127,6 +127,10 @@
+ H5F_SUPERBLOCK_VARLEN_SIZE(v, f))
+/* Forward declaration external file cache struct used below (defined in
+ * H5Fefc.c) */
+typedef struct H5F_efc_t H5F_efc_t;
+
/* Structure for metadata & "small [raw] data" block aggregation fields */
struct H5F_blk_aggr_t {
unsigned long feature_flag; /* Feature flag type */
@@ -200,6 +204,7 @@ typedef struct H5F_file_t {
unsigned nrefs; /* Ref count for times file is opened */
unsigned flags; /* Access Permissions for file */
H5F_mtab_t mtab; /* File mount table */
+ H5F_efc_t *efc; /* External file cache */
/* Cached values from FCPL/superblock */
uint8_t sizeof_addr; /* Size of addresses in file */
@@ -328,6 +333,13 @@ H5_DLL herr_t H5F_sfile_add(H5F_file_t *shared);
H5_DLL H5F_file_t * H5F_sfile_search(H5FD_t *lf);
H5_DLL herr_t H5F_sfile_remove(H5F_file_t *shared);
+/* External file cache routines */
+H5_DLL H5F_efc_t *H5F_efc_create(unsigned max_nfiles);
+H5_DLL unsigned H5F_efc_max_nfiles(H5F_efc_t *efc);
+H5_DLL herr_t H5F_efc_release(H5F_efc_t *efc);
+H5_DLL herr_t H5F_efc_destroy(H5F_efc_t *efc);
+H5_DLL herr_t H5F_efc_try_close(H5F_t *f);
+
/* Testing functions */
#ifdef H5F_TESTING
H5_DLL herr_t H5F_get_sohm_mesg_count_test(hid_t fid, unsigned type_id,
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index 10c2976..22d9acd 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -381,6 +381,7 @@ typedef struct H5F_blk_aggr_t H5F_blk_aggr_t;
#define H5F_ACS_MULTI_TYPE_NAME "multi_type" /* Data type in multi file driver */
#define H5F_ACS_LATEST_FORMAT_NAME "latest_format" /* 'Use latest format version' flag */
#define H5F_ACS_WANT_POSIX_FD_NAME "want_posix_fd" /* Internal: query the file descriptor from the core VFD, instead of the memory address */
+#define H5F_ACS_EFC_SIZE_NAME "efc_size" /* Size of external file cache */
/* ======================== File Mount properties ====================*/
#define H5F_MNT_SYM_LOCAL_NAME "local" /* Whether absolute symlinks local to file. */
@@ -550,6 +551,11 @@ H5_DLL MPI_Comm H5F_mpi_get_comm(const H5F_t *f);
H5_DLL int H5F_mpi_get_size(const H5F_t *f);
#endif /* H5_HAVE_PARALLEL */
+/* External file cache routines */
+H5_DLL 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);
+H5_DLL herr_t H5F_efc_close(H5F_t *parent, H5F_t *file);
+
/* Debugging functions */
H5_DLL herr_t H5F_debug(H5F_t *f, FILE * stream, int indent, int fwidth);
diff --git a/src/H5Fpublic.h b/src/H5Fpublic.h
index 5ca64dc..d87dae6 100644
--- a/src/H5Fpublic.h
+++ b/src/H5Fpublic.h
@@ -198,6 +198,7 @@ H5_DLL ssize_t H5Fget_name(hid_t obj_id, char *name, size_t size);
H5_DLL herr_t H5Fget_info2(hid_t obj_id, H5F_info2_t *finfo);
H5_DLL ssize_t H5Fget_free_sections(hid_t file_id, H5F_mem_t type,
size_t nsects, H5F_sect_info_t *sect_info/*out*/);
+H5_DLL herr_t H5Frelease_file_cache(hid_t file_id);
/* Symbols defined for compatibility with previous versions of the HDF5 API.
*
diff --git a/src/H5Lexternal.c b/src/H5Lexternal.c
index eb2ffe5..03f2e15 100644
--- a/src/H5Lexternal.c
+++ b/src/H5Lexternal.c
@@ -322,7 +322,7 @@ H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group,
/* target file_name is an absolute pathname: see RM for detailed description */
if(CHECK_ABSOLUTE(file_name) || CHECK_ABS_PATH(file_name)) {
/* Try opening file */
- if(NULL == (ext_file = H5F_open(file_name, intent, H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id))) {
+ if(NULL == (ext_file = H5F_efc_open(loc.oloc->file, file_name, intent, H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id))) {
char *ptr = NULL;
H5E_clear_stack(NULL);
@@ -334,7 +334,7 @@ H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group,
} /* end if */
} /* end if */
else if(CHECK_ABS_DRIVE(file_name)) {
- if(NULL == (ext_file = H5F_open(file_name, intent, H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id))) {
+ if(NULL == (ext_file = H5F_efc_open(loc.oloc->file, file_name, intent, H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id))) {
H5E_clear_stack(NULL);
/* strip "<drive-letter>:" */
HDstrcpy(temp_file_name, &file_name[2]);
@@ -361,7 +361,7 @@ H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group,
HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't prepend prefix to filename")
}
- ext_file = H5F_open(full_name, intent, H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id);
+ ext_file = H5F_efc_open(loc.oloc->file, full_name, intent, H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id);
full_name = (char *)H5MM_xfree(full_name);
if(ext_file != NULL)
break;
@@ -379,7 +379,7 @@ H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group,
if(my_prefix) {
if(H5L_build_name(my_prefix, temp_file_name, &full_name/*out*/) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't prepend prefix to filename")
- if(NULL == (ext_file = H5F_open(full_name, intent, H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id)))
+ if(NULL == (ext_file = H5F_efc_open(loc.oloc->file, full_name, intent, H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id)))
H5E_clear_stack(NULL);
full_name = (char *)H5MM_xfree(full_name);
} /* end if */
@@ -392,7 +392,7 @@ H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group,
if(NULL != (extpath = H5F_EXTPATH(loc.oloc->file))) {
if(H5L_build_name(extpath, temp_file_name, &full_name/*out*/) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't prepend prefix to filename")
- if(NULL == (ext_file = H5F_open(full_name, intent, H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id)))
+ if(NULL == (ext_file = H5F_efc_open(loc.oloc->file, full_name, intent, H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id)))
H5E_clear_stack(NULL);
full_name = (char *)H5MM_xfree(full_name);
} /* end if */
@@ -400,7 +400,7 @@ H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group,
/* try the relative file_name stored in temp_file_name */
if(ext_file == NULL) {
- if(NULL == (ext_file = H5F_open(temp_file_name, intent, H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id)))
+ if(NULL == (ext_file = H5F_efc_open(loc.oloc->file, temp_file_name, intent, H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id)))
H5E_clear_stack(NULL);
} /* end if */
@@ -427,32 +427,19 @@ H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group,
HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't prepend prefix to filename")
/* Try opening with the resolved name */
- if(NULL == (ext_file = H5F_open(full_name, intent, H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id)))
+ if(NULL == (ext_file = H5F_efc_open(loc.oloc->file, full_name, intent, H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id)))
HGOTO_ERROR(H5E_LINK, H5E_CANTOPENFILE, FAIL, "unable to open external file, external link file name = '%s', temp_file_name = '%s'", file_name, temp_file_name)
full_name = (char *)H5MM_xfree(full_name);
} /* end if */
- /* Increment the number of open objects, to hold the file open */
- H5F_incr_nopen_objs(ext_file);
-
/* Retrieve the "group location" for the file's root group */
if(H5G_loc_root(ext_file, &root_loc) < 0)
HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "unable to create location for file")
/* Open the object referenced in the external file */
- if((ext_obj = H5O_open_name(&root_loc, obj_name, lapl_id, FALSE)) < 0) {
- H5F_decr_nopen_objs(ext_file);
+ if((ext_obj = H5O_open_name(&root_loc, obj_name, lapl_id, FALSE)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open object")
- } /* end if */
-
- /* Decrement the number of open objects, to let the file close */
- H5F_decr_nopen_objs(ext_file);
-
- /* Close the external file */
- if(H5F_try_close(ext_file) < 0)
- HGOTO_ERROR(H5E_LINK, H5E_CANTCLOSEFILE, FAIL, "problem closing external file")
- ext_file = NULL;
/* Set return value */
ret_value = ext_obj;
@@ -461,7 +448,7 @@ done:
/* Release resources */
if(fapl_id > 0 && H5I_dec_ref(fapl_id) < 0)
HDONE_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close atom for file access property list")
- if(ext_file && H5F_try_close(ext_file) < 0)
+ if(ext_file && H5F_efc_close(loc.oloc->file, ext_file) < 0)
HDONE_ERROR(H5E_LINK, H5E_CANTCLOSEFILE, FAIL, "problem closing external file")
if(parent_group_name && parent_group_name != local_group_name)
parent_group_name = (char *)H5MM_xfree(parent_group_name);
diff --git a/src/H5Pfapl.c b/src/H5Pfapl.c
index 10922da..7dea0b2 100644
--- a/src/H5Pfapl.c
+++ b/src/H5Pfapl.c
@@ -119,6 +119,9 @@
*/
#define H5F_ACS_WANT_POSIX_FD_SIZE sizeof(hbool_t)
#define H5F_ACS_WANT_POSIX_FD_DEF FALSE
+/* Definition for external file cache size */
+#define H5F_ACS_EFC_SIZE_SIZE sizeof(unsigned)
+#define H5F_ACS_EFC_SIZE_DEF 0
/******************/
@@ -211,6 +214,7 @@ H5P_facc_reg_prop(H5P_genclass_t *pclass)
H5FD_mem_t mem_type = H5F_ACS_MULTI_TYPE_DEF; /* Default file space type for multi VFD */
hbool_t latest_format = H5F_ACS_LATEST_FORMAT_DEF; /* Default setting for "use the latest version of the format" flag */
hbool_t want_posix_fd = H5F_ACS_WANT_POSIX_FD_DEF; /* Default setting for retrieving 'handle' from core VFD */
+ unsigned efc_size = H5F_ACS_EFC_SIZE_DEF; /* Default external file cache size */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5P_facc_reg_prop)
@@ -292,6 +296,10 @@ H5P_facc_reg_prop(H5P_genclass_t *pclass)
if(H5P_register_real(pclass, H5F_ACS_WANT_POSIX_FD_NAME, H5F_ACS_WANT_POSIX_FD_SIZE, &want_posix_fd, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+ /* Register the external file cache size */
+ if(H5P_register_real(pclass, H5F_ACS_EFC_SIZE_NAME, H5F_ACS_EFC_SIZE_SIZE, &efc_size, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5P_facc_reg_prop() */
@@ -2016,3 +2024,80 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Pget_libver_bounds() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pset_elink_file_cache_size
+ *
+ * Purpose: Sets the number of files opened through external links
+ * from the file associated with this fapl to be held open
+ * in that file's external file cache. When the maximum
+ * number of files is reached, the least recently used file
+ * is closed (unless it is opened from somewhere else).
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * Friday, December 17, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pset_elink_file_cache_size(hid_t plist_id, unsigned efc_size)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ herr_t ret_value = SUCCEED; /* return value */
+
+ FUNC_ENTER_API(H5Pset_elink_file_cache_size, FAIL)
+ H5TRACE2("e", "iIu", plist_id, efc_size);
+
+ /* Get the plist structure */
+ if(NULL == (plist = H5P_object_verify(plist_id, H5P_FILE_ACCESS)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+
+ /* Set value */
+ if(H5P_set(plist, H5F_ACS_EFC_SIZE_NAME, &efc_size) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set elink file cache size")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Pset_elink_file_cache_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pget_elink_file_cache_size
+ *
+ * Purpose: Gets the number of files opened through external links
+ * from the file associated with this fapl to be held open
+ * in that file's external file cache. When the maximum
+ * number of files is reached, the least recently used file
+ * is closed (unless it is opened from somewhere else).
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * Friday, December 17, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pget_elink_file_cache_size(hid_t plist_id, unsigned *efc_size)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ herr_t ret_value = SUCCEED; /* return value */
+
+ FUNC_ENTER_API(H5Pget_elink_file_cache_size, FAIL)
+ H5TRACE2("e", "i*Iu", plist_id, efc_size);
+
+ /* Get the plist structure */
+ if(NULL == (plist = H5P_object_verify(plist_id, H5P_FILE_ACCESS)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+
+ /* Get value */
+ if(efc_size)
+ if(H5P_get(plist, H5F_ACS_EFC_SIZE_NAME, efc_size) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get elink file cache size")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Pget_elink_file_cache_size() */
+
diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h
index 09eb796..6867b63 100644
--- a/src/H5Ppublic.h
+++ b/src/H5Ppublic.h
@@ -287,6 +287,8 @@ H5_DLL herr_t H5Pset_libver_bounds(hid_t plist_id, H5F_libver_t low,
H5F_libver_t high);
H5_DLL herr_t H5Pget_libver_bounds(hid_t plist_id, H5F_libver_t *low,
H5F_libver_t *high);
+H5_DLL herr_t H5Pset_elink_file_cache_size(hid_t plist_id, unsigned efc_size);
+H5_DLL herr_t H5Pget_elink_file_cache_size(hid_t plist_id, unsigned *efc_size);
/* Dataset creation property list (DCPL) routines */
H5_DLL herr_t H5Pset_layout(hid_t plist_id, H5D_layout_t layout);
diff --git a/src/Makefile.am b/src/Makefile.am
index dc0edb3..ee0a3f5 100755
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -53,8 +53,8 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5E.c H5Edeprec.c H5Eint.c \
H5EA.c H5EAcache.c H5EAdbg.c H5EAdblkpage.c H5EAdblock.c H5EAhdr.c \
H5EAiblock.c H5EAint.c H5EAsblock.c H5EAstat.c H5EAtest.c \
- H5F.c H5Faccum.c H5Fdbg.c H5Fdeprec.c H5Ffake.c H5Fio.c H5Fmount.c \
- H5Fmpi.c H5Fquery.c \
+ H5F.c H5Faccum.c H5Fdbg.c H5Fdeprec.c H5Fefc.c H5Ffake.c H5Fio.c \
+ H5Fmount.c H5Fmpi.c H5Fquery.c \
H5Fsfile.c H5Fsuper.c H5Fsuper_cache.c H5Ftest.c \
H5FA.c H5FAcache.c H5FAdbg.c H5FAdblock.c H5FAdblkpage.c H5FAhdr.c \
H5FAstat.c H5FAtest.c \
diff --git a/src/Makefile.in b/src/Makefile.in
index 55e52ae..51003a0 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -106,19 +106,19 @@ am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \
H5Dtest.lo H5E.lo H5Edeprec.lo H5Eint.lo H5EA.lo H5EAcache.lo \
H5EAdbg.lo H5EAdblkpage.lo H5EAdblock.lo H5EAhdr.lo \
H5EAiblock.lo H5EAint.lo H5EAsblock.lo H5EAstat.lo H5EAtest.lo \
- H5F.lo H5Faccum.lo H5Fdbg.lo H5Fdeprec.lo H5Ffake.lo H5Fio.lo \
- H5Fmount.lo H5Fmpi.lo H5Fquery.lo H5Fsfile.lo H5Fsuper.lo \
- H5Fsuper_cache.lo H5Ftest.lo H5FA.lo H5FAcache.lo H5FAdbg.lo \
- H5FAdblock.lo H5FAdblkpage.lo H5FAhdr.lo H5FAstat.lo \
- H5FAtest.lo H5FD.lo H5FDcore.lo H5FDdirect.lo H5FDfamily.lo \
- H5FDint.lo H5FDlog.lo H5FDmpi.lo H5FDmpio.lo H5FDmpiposix.lo \
- H5FDmulti.lo H5FDsec2.lo H5FDspace.lo H5FDstdio.lo H5FL.lo \
- H5FO.lo H5FS.lo H5FScache.lo H5FSdbg.lo H5FSsection.lo \
- H5FSstat.lo H5FStest.lo H5G.lo H5Gbtree2.lo H5Gcache.lo \
- H5Gcompact.lo H5Gdense.lo H5Gdeprec.lo H5Gent.lo H5Gint.lo \
- H5Glink.lo H5Gloc.lo H5Gname.lo H5Gnode.lo H5Gobj.lo H5Goh.lo \
- H5Groot.lo H5Gstab.lo H5Gtest.lo H5Gtraverse.lo H5HF.lo \
- H5HFbtree2.lo H5HFcache.lo H5HFdbg.lo H5HFdblock.lo \
+ H5F.lo H5Faccum.lo H5Fdbg.lo H5Fdeprec.lo H5Fefc.lo H5Ffake.lo \
+ H5Fio.lo H5Fmount.lo H5Fmpi.lo H5Fquery.lo H5Fsfile.lo \
+ H5Fsuper.lo H5Fsuper_cache.lo H5Ftest.lo H5FA.lo H5FAcache.lo \
+ H5FAdbg.lo H5FAdblock.lo H5FAdblkpage.lo H5FAhdr.lo \
+ H5FAstat.lo H5FAtest.lo H5FD.lo H5FDcore.lo H5FDdirect.lo \
+ H5FDfamily.lo H5FDint.lo H5FDlog.lo H5FDmpi.lo H5FDmpio.lo \
+ H5FDmpiposix.lo H5FDmulti.lo H5FDsec2.lo H5FDspace.lo \
+ H5FDstdio.lo H5FL.lo H5FO.lo H5FS.lo H5FScache.lo H5FSdbg.lo \
+ H5FSsection.lo H5FSstat.lo H5FStest.lo H5G.lo H5Gbtree2.lo \
+ H5Gcache.lo H5Gcompact.lo H5Gdense.lo H5Gdeprec.lo H5Gent.lo \
+ H5Gint.lo H5Glink.lo H5Gloc.lo H5Gname.lo H5Gnode.lo H5Gobj.lo \
+ H5Goh.lo H5Groot.lo H5Gstab.lo H5Gtest.lo H5Gtraverse.lo \
+ H5HF.lo H5HFbtree2.lo H5HFcache.lo H5HFdbg.lo H5HFdblock.lo \
H5HFdtable.lo H5HFhdr.lo H5HFhuge.lo H5HFiblock.lo H5HFiter.lo \
H5HFman.lo H5HFsection.lo H5HFspace.lo H5HFstat.lo H5HFtest.lo \
H5HFtiny.lo H5HG.lo H5HGcache.lo H5HGdbg.lo H5HL.lo \
@@ -486,8 +486,8 @@ libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5E.c H5Edeprec.c H5Eint.c \
H5EA.c H5EAcache.c H5EAdbg.c H5EAdblkpage.c H5EAdblock.c H5EAhdr.c \
H5EAiblock.c H5EAint.c H5EAsblock.c H5EAstat.c H5EAtest.c \
- H5F.c H5Faccum.c H5Fdbg.c H5Fdeprec.c H5Ffake.c H5Fio.c H5Fmount.c \
- H5Fmpi.c H5Fquery.c \
+ H5F.c H5Faccum.c H5Fdbg.c H5Fdeprec.c H5Fefc.c H5Ffake.c H5Fio.c \
+ H5Fmount.c H5Fmpi.c H5Fquery.c \
H5Fsfile.c H5Fsuper.c H5Fsuper_cache.c H5Ftest.c \
H5FA.c H5FAcache.c H5FAdbg.c H5FAdblock.c H5FAdblkpage.c H5FAhdr.c \
H5FAstat.c H5FAtest.c \
@@ -764,6 +764,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Faccum.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fdbg.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fdeprec.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fefc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ffake.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fio.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fmount.Plo@am__quote@
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 98fffe0..9a2dd88 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -177,6 +177,12 @@ ADD_TEST (
dtransform.h5
dtypes4.h5
dtypes5.h5
+ efc0.h5
+ efc1.h5
+ efc2.h5
+ efc3.h5
+ efc4.h5
+ efc5.h5
extlinks16A00000.h5
extlinks16A00001.h5
extlinks16A00002.h5
@@ -256,6 +262,7 @@ SET (H5_TESTS
filter_fail
extend
external
+ efc
objcopy
links
unlink
@@ -415,6 +422,7 @@ IF (HDF5_TEST_VFD)
filter_fail
extend
external
+ efc
objcopy
links
unlink
diff --git a/test/Makefile.am b/test/Makefile.am
index 06c56f8..6f4a46a 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -38,7 +38,7 @@ SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT) links_env$(EXEEXT)
# other current library code tests.
TEST_PROG= testhdf5 lheap ohdr stab gheap cache cache_api cache_tagging \
pool accum hyperslab istore bittests dt_arith \
- dtypes dsets cmpd_dset filter_fail extend external objcopy links unlink \
+ dtypes dsets cmpd_dset filter_fail extend external efc objcopy links unlink \
big mtime fillval mount flush1 flush2 app_ref enum \
set_extent ttsafe \
getname vfd ntypes dangle dtransform reserved cross_read \
@@ -125,7 +125,7 @@ CHECK_CLEANFILES+=accum.h5 cmpd_dset.h5 compact_dataset.h5 dataset.h5 dset_offse
dtransform.h5 test_filters.h5 get_file_name.h5 tstint[1-2].h5 \
unlink_chunked.h5 btree2.h5 objcopy_src.h5 objcopy_dst.h5 \
objcopy_ext.dat trefer1.h5 trefer2.h5 app_ref.h5 farray.h5 \
- earray.h5
+ earray.h5 efc[0-5].h5
# Sources for testhdf5 executable
testhdf5_SOURCES=testhdf5.c tarray.c tattr.c tchecksum.c tconfig.c tfile.c \
diff --git a/test/Makefile.in b/test/Makefile.in
index a734045..98fa754 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -82,7 +82,7 @@ am__EXEEXT_1 = testhdf5$(EXEEXT) lheap$(EXEEXT) ohdr$(EXEEXT) \
hyperslab$(EXEEXT) istore$(EXEEXT) bittests$(EXEEXT) \
dt_arith$(EXEEXT) dtypes$(EXEEXT) dsets$(EXEEXT) \
cmpd_dset$(EXEEXT) filter_fail$(EXEEXT) extend$(EXEEXT) \
- external$(EXEEXT) objcopy$(EXEEXT) links$(EXEEXT) \
+ external$(EXEEXT) efc$(EXEEXT) objcopy$(EXEEXT) links$(EXEEXT) \
unlink$(EXEEXT) big$(EXEEXT) mtime$(EXEEXT) fillval$(EXEEXT) \
mount$(EXEEXT) flush1$(EXEEXT) flush2$(EXEEXT) \
app_ref$(EXEEXT) enum$(EXEEXT) set_extent$(EXEEXT) \
@@ -163,6 +163,10 @@ earray_SOURCES = earray.c
earray_OBJECTS = earray.$(OBJEXT)
earray_LDADD = $(LDADD)
earray_DEPENDENCIES = libh5test.la $(LIBHDF5)
+efc_SOURCES = efc.c
+efc_OBJECTS = efc.$(OBJEXT)
+efc_LDADD = $(LDADD)
+efc_DEPENDENCIES = libh5test.la $(LIBHDF5)
enum_SOURCES = enum.c
enum_OBJECTS = enum.$(OBJEXT)
enum_LDADD = $(LDADD)
@@ -397,9 +401,9 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
SOURCES = $(libh5test_la_SOURCES) accum.c app_ref.c big.c bittests.c \
btree2.c cache.c cache_api.c cache_tagging.c cmpd_dset.c \
cross_read.c dangle.c dsets.c dt_arith.c dtransform.c dtypes.c \
- earray.c enum.c err_compat.c error_test.c extend.c external.c \
- farray.c fheap.c fillval.c filter_fail.c flush1.c flush2.c \
- freespace.c gen_bad_ohdr.c gen_bogus.c gen_cross.c \
+ earray.c efc.c enum.c err_compat.c error_test.c extend.c \
+ external.c farray.c fheap.c fillval.c filter_fail.c flush1.c \
+ flush2.c freespace.c gen_bad_ohdr.c gen_bogus.c gen_cross.c \
gen_deflate.c gen_filespace.c gen_filters.c gen_new_array.c \
gen_new_fill.c gen_new_group.c gen_new_mtime.c gen_new_super.c \
gen_noencoder.c gen_nullspace.c gen_sizes_lheap.c \
@@ -411,7 +415,7 @@ SOURCES = $(libh5test_la_SOURCES) accum.c app_ref.c big.c bittests.c \
DIST_SOURCES = $(libh5test_la_SOURCES) accum.c app_ref.c big.c \
bittests.c btree2.c cache.c cache_api.c cache_tagging.c \
cmpd_dset.c cross_read.c dangle.c dsets.c dt_arith.c \
- dtransform.c dtypes.c earray.c enum.c err_compat.c \
+ dtransform.c dtypes.c earray.c efc.c enum.c err_compat.c \
error_test.c extend.c external.c farray.c fheap.c fillval.c \
filter_fail.c flush1.c flush2.c freespace.c gen_bad_ohdr.c \
gen_bogus.c gen_cross.c gen_deflate.c gen_filespace.c \
@@ -727,7 +731,7 @@ CHECK_CLEANFILES = *.chkexe *.chklog *.clog accum.h5 cmpd_dset.h5 \
err_compat.h5 dtransform.h5 test_filters.h5 get_file_name.h5 \
tstint[1-2].h5 unlink_chunked.h5 btree2.h5 objcopy_src.h5 \
objcopy_dst.h5 objcopy_ext.dat trefer1.h5 trefer2.h5 \
- app_ref.h5 farray.h5 earray.h5
+ app_ref.h5 farray.h5 earray.h5 efc[0-5].h5
INCLUDES = -I$(top_srcdir)/src -I$(top_builddir)/src
# Test script for error_test and err_compat
@@ -744,7 +748,7 @@ SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT) links_env$(EXEEXT)
# other current library code tests.
TEST_PROG = testhdf5 lheap ohdr stab gheap cache cache_api cache_tagging \
pool accum hyperslab istore bittests dt_arith \
- dtypes dsets cmpd_dset filter_fail extend external objcopy links unlink \
+ dtypes dsets cmpd_dset filter_fail extend external efc objcopy links unlink \
big mtime fillval mount flush1 flush2 app_ref enum \
set_extent ttsafe \
getname vfd ntypes dangle dtransform reserved cross_read \
@@ -924,6 +928,9 @@ dtypes$(EXEEXT): $(dtypes_OBJECTS) $(dtypes_DEPENDENCIES)
earray$(EXEEXT): $(earray_OBJECTS) $(earray_DEPENDENCIES)
@rm -f earray$(EXEEXT)
$(LINK) $(earray_OBJECTS) $(earray_LDADD) $(LIBS)
+efc$(EXEEXT): $(efc_OBJECTS) $(efc_DEPENDENCIES)
+ @rm -f efc$(EXEEXT)
+ $(LINK) $(efc_OBJECTS) $(efc_LDADD) $(LIBS)
enum$(EXEEXT): $(enum_OBJECTS) $(enum_DEPENDENCIES)
@rm -f enum$(EXEEXT)
$(LINK) $(enum_OBJECTS) $(enum_LDADD) $(LIBS)
@@ -1104,6 +1111,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dtransform.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dtypes.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/earray.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/efc.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/enum.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/err_compat.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error_test.Po@am__quote@
diff --git a/test/efc.c b/test/efc.c
new file mode 100644
index 0000000..1ee7ce3
--- /dev/null
+++ b/test/efc.c
@@ -0,0 +1,3213 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/* Programmer: Neil Fortner
+ * December 16, 2010
+ */
+
+#include "h5test.h"
+
+#define H5F_PACKAGE
+#include "H5Fpkg.h"
+#include "H5Iprivate.h"
+
+const char *FILENAME[] = {
+ "efc0",
+ "efc1",
+ "efc2",
+ "efc3",
+ "efc4",
+ "efc5",
+ NULL
+};
+
+/* Global patched filename buffer */
+static char filename[6][1024];
+
+/* Global property lists - just copies of the defaults (necessary to use
+ * internal functions */
+hid_t fcpl_id = -1;
+hid_t fapl_id = -1;
+hid_t dxpl_id = -1;
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_single
+ *
+ * Purpose: Tests manipulations on a single external file cache.
+ *
+ * Return: Success: 0
+ * Failure: Number of errors
+ *
+ * Programmer: Neil Fortner
+ * December 16, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+static unsigned
+test_single(void)
+{
+ H5F_t *f0 = NULL; /* Parent file containing EFC */
+ H5F_t *f1 = NULL; /* Child file */
+ H5F_t *f2 = NULL; /* Child file */
+ H5F_t *f3 = NULL; /* Child file */
+ H5F_t *f4 = NULL; /* Child file */
+ H5F_t *ftmp1 = NULL; /* Temp file */
+ H5F_t *ftmp2 = NULL; /* Temp file */
+ H5F_t *ftmp3 = NULL; /* Temp file */
+ H5F_t *ftmp4 = NULL; /* Temp file */
+
+ TESTING("single EFC");
+
+ /* Set EFC size to 3. Do this instead of H5F_efc_create() so we can pass
+ * a file pointer to H5F_efc_open containing the EFC. */
+ if(H5Pset_elink_file_cache_size(fapl_id, 3) < 0)
+ TEST_ERROR
+
+ /* Open parent file */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+
+ /* Disable EFC for child files */
+ if(H5Pset_elink_file_cache_size(fapl_id, 0) < 0)
+ TEST_ERROR
+
+
+ /* Test 1: Open file 1 through EFC, close, then open normally, verify ref
+ * count = 2, release EFC, verify ref count = 1. Verifies a file can be
+ * held open by the EFC. */
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_open(filename[1], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(ftmp1->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp1->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(ftmp1) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 2: Verify that subsequent efc_open requests return the cached top
+ * level file pointer. Open file 1 through EFC, close, open again, verify
+ * file pointers are the same. */
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ ftmp1 = f1;
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f1 != ftmp1)
+ TEST_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 3: Verify LRU functionality. Add four files to the EFC and verify
+ * that the one added first is evicted. Then reopen files in a different
+ * order. Open each file normally after closing through EFC the first time
+ * to track ref counts. */
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_open(filename[1], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(NULL == (f2 = H5F_efc_open(f0, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f2) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_open(filename[2], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 2)
+ TEST_ERROR
+ if(f2->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(NULL == (f3 = H5F_efc_open(f0, filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f3) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_open(filename[3], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 2)
+ TEST_ERROR
+ if(f2->shared->nrefs != 2)
+ TEST_ERROR
+ if(f3->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(NULL == (f4 = H5F_efc_open(f0, filename[4],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f4) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f4 = H5F_open(filename[4], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(f2->shared->nrefs != 2)
+ TEST_ERROR
+ if(f3->shared->nrefs != 2)
+ TEST_ERROR
+ if(f4->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(NULL == (ftmp3 = H5F_efc_open(f0, filename[3], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, ftmp3) < 0)
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(f2->shared->nrefs != 2)
+ TEST_ERROR
+ if(f3->shared->nrefs != 2)
+ TEST_ERROR
+ if(f4->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(NULL == (ftmp2 = H5F_efc_open(f0, filename[2], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, ftmp2) < 0)
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(f2->shared->nrefs != 2)
+ TEST_ERROR
+ if(f3->shared->nrefs != 2)
+ TEST_ERROR
+ if(f4->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(NULL == (ftmp1 = H5F_efc_open(f0, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 2)
+ TEST_ERROR
+ if(f2->shared->nrefs != 2)
+ TEST_ERROR
+ if(f3->shared->nrefs != 2)
+ TEST_ERROR
+ if(f4->shared->nrefs != 1)
+ TEST_ERROR
+
+ if(NULL == (ftmp4 = H5F_efc_open(f0, filename[4], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, ftmp4) < 0)
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 2)
+ TEST_ERROR
+ if(f2->shared->nrefs != 2)
+ TEST_ERROR
+ if(f3->shared->nrefs != 1)
+ TEST_ERROR
+ if(f4->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(f2->shared->nrefs != 1)
+ TEST_ERROR
+ if(f3->shared->nrefs != 1)
+ TEST_ERROR
+ if(f4->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(f2) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(f3) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(f4) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 4: Verify that files kept open through the EFC are not evicted by
+ * H5F_efc_release(). */
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_open(filename[1], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(ftmp1->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp1->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp1->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp1->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(ftmp1) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 5: Verify that files kept open through the EFC are not evicted by
+ * filling up the cache. Open 4 files while holding the first open. Verify
+ * that the second file is evicted. Close the first file, reopen the
+ * second, and verify that the first file is evicted. */
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_open(filename[1], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(ftmp1->shared != f1->shared)
+ TEST_ERROR
+ if(ftmp1->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(NULL == (f2 = H5F_efc_open(f0, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f2) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp2 = H5F_open(filename[2], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(ftmp2->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(NULL == (f3 = H5F_efc_open(f0, filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f3) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp2->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(NULL == (f4 = H5F_efc_open(f0, filename[4],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f4) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp1->shared->nrefs != 2)
+ TEST_ERROR
+ if(ftmp2->shared->nrefs != 1)
+ TEST_ERROR
+
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp1->shared->nrefs != 2)
+ TEST_ERROR
+ if(NULL == (f2 = H5F_efc_open(f0, filename[2], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f2) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp1->shared->nrefs != 1)
+ TEST_ERROR
+ if(ftmp2->shared->nrefs != 2)
+ TEST_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp1->shared->nrefs != 2)
+ TEST_ERROR
+ if(ftmp2->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp1->shared->nrefs != 1)
+ TEST_ERROR
+ if(ftmp2->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(ftmp2) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 6: Verify that having a full EFC filled only with open files
+ * prevents further files from being cached. Open and hold open 3 files
+ * through the EFC, then open the fourth and verify that it was not added to
+ * the EFC. */
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_open(filename[1], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(ftmp1->shared != f1->shared)
+ TEST_ERROR
+ if(ftmp1->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(NULL == (f2 = H5F_efc_open(f0, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp2 = H5F_open(filename[2], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(ftmp2->shared != f2->shared)
+ TEST_ERROR
+ if(ftmp2->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(NULL == (f3 = H5F_efc_open(f0, filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp3 = H5F_open(filename[3], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(ftmp3->shared != f3->shared)
+ TEST_ERROR
+ if(ftmp3->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(NULL == (f4 = H5F_efc_open(f0, filename[4],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f4) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp4 = H5F_open(filename[4], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(ftmp4->shared->nrefs != 1)
+ TEST_ERROR
+
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f2) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f3) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp1->shared->nrefs != 2)
+ TEST_ERROR
+ if(ftmp2->shared->nrefs != 2)
+ TEST_ERROR
+ if(ftmp3->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp1->shared->nrefs != 1)
+ TEST_ERROR
+ if(ftmp2->shared->nrefs != 1)
+ TEST_ERROR
+ if(ftmp3->shared->nrefs != 1)
+ TEST_ERROR
+ if(ftmp4->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(ftmp2) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(ftmp3) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(ftmp4) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 7: Test multiple file opens. Open a file twice, close it once, then
+ * verify that it is not evicted by H5F_efc_release(). */
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_open(filename[1], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(ftmp1->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_efc_close(f0, f2) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp1->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp1->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp1->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(ftmp1) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Close parent file */
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+
+ PASSED();
+
+ return 0;
+
+error:
+ return 1;
+} /* test_single */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_graph_nocycle
+ *
+ * Purpose: Tests manipulations on a graph of files with external file
+ * caches. The graph does not contain cycles.
+ *
+ * Return: Success: 0
+ * Failure: Number of errors
+ *
+ * Programmer: Neil Fortner
+ * January 4, 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+static unsigned
+test_graph_nocycle(void)
+{
+ H5F_t *f0 = NULL; /* Parent file containing EFC */
+ H5F_t *f1 = NULL; /* Child file */
+ H5F_t *f2 = NULL; /* Child file */
+ H5F_t *f3 = NULL; /* Child file */
+ H5F_t *f4 = NULL; /* Child file */
+ H5F_t *ftmp1 = NULL; /* Temp file */
+ H5F_t *ftmp2 = NULL; /* Temp file */
+ H5F_t *ftmp3 = NULL; /* Temp file */
+ H5F_t *ftmp4 = NULL; /* Temp file */
+
+ TESTING("graph of EFCs without cycles");
+
+ /* Set EFC size to 8. Do this instead of H5F_efc_create() so we can pass
+ * a file pointer to H5F_efc_open containing the EFC. Set to a high number
+ * because we don't test the EFC becoming too large in this test. */
+ if(H5Pset_elink_file_cache_size(fapl_id, 8) < 0)
+ TEST_ERROR
+
+
+ /* Test 1: Simple 3 file chain. Open file 1 through file 0, then open file
+ * 2 through file 1. Release file 0's EFC and verify that file 2 gets its
+ * ref count reduced (implying file 1 was closed). Do the same with the
+ * opening order reversed. */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(f1, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, f2) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp2 = H5F_open(filename[2], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(ftmp2->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp2->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(ftmp2) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_open(filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(ftmp1, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_try_close(ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, f2) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp2 = H5F_open(filename[2], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(ftmp2->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp2->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(ftmp2) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 2: 5 file chain. The parent file has 2 child files, each of which
+ * has their own child file. Verifies that releasing the parent's EFC
+ * closes all 4 children. */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(f1, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, f2) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp2 = H5F_open(filename[2], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(ftmp2->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(NULL == (f3 = H5F_efc_open(f0, filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f4 = H5F_efc_open(f3, filename[4],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f3, f4) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f3) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp4 = H5F_open(filename[4], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(ftmp4->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp2->shared->nrefs != 1)
+ TEST_ERROR
+ if(ftmp4->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(ftmp2) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(ftmp4) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 3: Simple "inverted" tree. Two parent files share a child file,
+ * which has its own child file. Verify that the child's child is not
+ * closed until both parents' EFCs are released. First release through one
+ * parent, then reopen through that parent and release the other, then
+ * re-release the first parent. */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_open(filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(f0, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp2 = H5F_efc_open(f1, filename[2], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f2, filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, f3) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f2) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp2) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp3 = H5F_open(filename[3], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(ftmp3->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp3->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(NULL == (f2 = H5F_efc_open(f0, filename[2], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f2) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_release(f1->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp3->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp3->shared->nrefs != 1)
+ TEST_ERROR
+
+ if(H5F_try_close(ftmp3) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(f1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 4: Simple "diamond" tree. The parent file has two children, which
+ * shared the same child. Verify that releasing the parent file closes all
+ * files. */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(f0, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f2, filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, f3) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f1, filename[3], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, f3) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f2) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp3 = H5F_open(filename[3], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(ftmp3->shared->nrefs != 3)
+ TEST_ERROR
+
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp3->shared->nrefs != 1)
+ TEST_ERROR
+
+ if(H5F_try_close(ftmp3) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 5: Dense 5 file graph. f0 caches f1, f2, f3 and f4. f1 and f2
+ * each cache f3 and f4. f3 caches f4. Verify that releasing f0 closes all
+ * files. */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(f0, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f0, filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f4 = H5F_efc_open(f0, filename[4],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f4) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f3) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f1, filename[3], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f4 = H5F_efc_open(f1, filename[4], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, f4) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, f3) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f2, filename[3], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f4 = H5F_efc_open(f2, filename[4], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, f4) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f2) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f4 = H5F_efc_open(f3, filename[4], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f3, f4) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, f3) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp4 = H5F_open(filename[4], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(ftmp4->shared->nrefs != 5)
+ TEST_ERROR
+
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp4->shared->nrefs != 1)
+ TEST_ERROR
+ if(NULL == (ftmp1 = H5F_open(filename[1], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(ftmp1->shared->nrefs != 1)
+ TEST_ERROR
+ if(NULL == (ftmp2 = H5F_open(filename[2], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(ftmp2->shared->nrefs != 1)
+ TEST_ERROR
+ if(NULL == (ftmp3 = H5F_open(filename[3], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(ftmp3->shared->nrefs != 1)
+ TEST_ERROR
+
+ if(H5F_try_close(ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(ftmp2) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(ftmp3) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(ftmp4) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+
+
+ PASSED();
+
+ return 0;
+
+error:
+ return 1;
+} /* test_graph_nocycle */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_graph_cycle
+ *
+ * Purpose: Tests manipulations on a graph of files with external file
+ * caches containing cycles.
+ *
+ * Return: Success: 0
+ * Failure: Number of errors
+ *
+ * Programmer: Neil Fortner
+ * January 6, 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+static unsigned
+test_graph_cycle(void)
+{
+ H5F_t *f0 = NULL; /* File */
+ H5F_t *f1 = NULL; /* File */
+ H5F_t *f2 = NULL; /* File */
+ H5F_t *f3 = NULL; /* File */
+ H5F_t *f4 = NULL; /* File */
+ H5F_t *f5 = NULL; /* File */
+ H5F_t *ftmp0 = NULL; /* Temp file */
+ H5F_t *ftmp1 = NULL; /* Temp file */
+ H5F_t *ftmp2 = NULL; /* Temp file */
+ H5F_t *ftmp3 = NULL; /* Temp file */
+
+ TESTING("graph of EFCs with cycles");
+
+ /* Set EFC size to 8. Do this instead of H5F_efc_create() so we can pass
+ * a file pointer to H5F_efc_open containing the EFC. Set to a high number
+ * because we don't test the EFC becoming too large in this test. */
+ if(H5Pset_elink_file_cache_size(fapl_id, 8) < 0)
+ TEST_ERROR
+
+
+ /* Test 1: File caches itself. Verify that closing the file causes it to be
+ * actually closed, and there is no other unexpected behavior. */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f0, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+
+ if(NULL == (ftmp0 = H5F_efc_open(f0, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 2: Indirectly referenced file caches itself. Same as above except
+ * the file is part of another file's EFC. */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_efc_open(f1, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_open(filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f1) < 0)
+ FAIL_STACK_ERROR
+
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_efc_open(f1, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_open(filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f1) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 3: Simple 2 file cycle */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f1, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f1, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 4: Simple 2 file cycle (indirectly referenced) */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(f1, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_efc_open(f2, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, f2) < 0)
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_open(filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f1) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 5: Parallel double cycle */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f1, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(f0, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f2, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f2) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 3)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 6: Parallel double cycle with release */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f1, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(f0, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f2, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f2) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 3)
+ TEST_ERROR
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 7: Chained parallel double cycle */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f1, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(f1, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_efc_open(f2, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, f2) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f1, filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_efc_open(f3, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f3, ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, f3) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 8: Chained parallel double cycle with release */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f1, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(f1, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_efc_open(f2, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, f2) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f1, filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_efc_open(f3, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f3, ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, f3) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 9: Simple 2 file cycle, extra ID on root */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_open(filename[0], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_efc_open(f1, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared != ftmp0->shared)
+ TEST_ERROR
+ if(f0->shared->nrefs != 3)
+ TEST_ERROR
+ if(H5F_try_close(ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 10: Simple 2 file cycle, extra ID on second file */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_open(filename[1], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f1, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(ftmp1->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp1->shared->nrefs != 2)
+ TEST_ERROR
+ if(NULL == (f0 = H5F_open(filename[0], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_open(filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f1) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 11: Parallel double cycle, extra ID on a child file */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f1, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(f0, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp2 = H5F_open(filename[2], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f2, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f2) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 3)
+ TEST_ERROR
+ if(ftmp2->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp2->shared->nrefs != 2)
+ TEST_ERROR
+ if(NULL == (f0 = H5F_open(filename[0], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 3)
+ TEST_ERROR
+
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(ftmp2) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_open(filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_open(filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f2->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f2) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 12: Parallel double cycle, extra ID on a child file, with release */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f1, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(f0, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp2 = H5F_open(filename[2], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f2, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f2) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 3)
+ TEST_ERROR
+ if(ftmp2->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(ftmp2->shared->nrefs != 1)
+ TEST_ERROR
+
+ if(H5F_efc_release(ftmp2->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(ftmp2->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(ftmp2) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 13: Chained parallel double cycle, extra ID on a child file */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f1, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(f1, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_efc_open(f2, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, f2) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f1, filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp3 = H5F_open(filename[3], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_efc_open(f3, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f3, ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, f3) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(ftmp3->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp3->shared->nrefs != 2)
+ TEST_ERROR
+ if(NULL == (f0 = H5F_open(filename[0], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(ftmp3) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_open(filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_open(filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f2->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f2) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_open(filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f3->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f3) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 14: Chained parallel double cycle, extra ID on a child file, with
+ * release */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f1, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(f1, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_efc_open(f2, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, f2) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f1, filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp3 = H5F_open(filename[3], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_efc_open(f3, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f3, ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, f3) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(ftmp3->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(ftmp3->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(H5F_efc_release(ftmp3->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(ftmp3->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(ftmp3) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 15: One local and one remote cycle */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f1, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(f0, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f2, filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp2 = H5F_efc_open(f3, filename[2], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f3, ftmp2) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, f3) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f2) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_open(filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_open(filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f2->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f2) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_open(filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f3->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f3) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 16: One local and one remote cycle, with release */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f1, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(f0, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f2, filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp2 = H5F_efc_open(f3, filename[2], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f3, ftmp2) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, f3) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f2) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_open(filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_open(filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f2->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f2) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_open(filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f3->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f3) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 17: One local and one remote cycle, remote cycle held open */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f1, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(f0, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f2, filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp3 = H5F_open(filename[3], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp2 = H5F_efc_open(f3, filename[2], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f3, ftmp2) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, f3) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f2) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp3->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(H5F_try_close(ftmp3) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_open(filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_open(filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f2->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f2) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_open(filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f3->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f3) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 18: One local and one remote cycle, remote cycle held open, with
+ * release */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f1, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(f0, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f2, filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp3 = H5F_open(filename[3], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp2 = H5F_efc_open(f3, filename[2], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f3, ftmp2) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, f3) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f2) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(ftmp3->shared->nrefs != 2)
+ TEST_ERROR
+ if(NULL == (f1 = H5F_open(filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_open(filename[2], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f2->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_try_close(f2) < 0)
+ FAIL_STACK_ERROR
+
+ if(H5F_efc_release(ftmp3->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(ftmp3->shared->nrefs != 1)
+ TEST_ERROR
+ if(NULL == (f2 = H5F_open(filename[2], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f2->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f2) < 0)
+ FAIL_STACK_ERROR
+
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(ftmp3) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 19: "Diamond" shape with links moving from bottom (root) to top.
+ * Also cycle between bottom (root) and top and cycles on the sides. */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(f0, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f1, filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, f3) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f2, filename[3], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, f3) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f0, filename[3], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f3, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f3, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f3) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f4 = H5F_efc_open(f1, filename[4],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_efc_open(f4, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f4, ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, f4) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f5 = H5F_efc_open(f2, filename[5],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp2 = H5F_efc_open(f5, filename[2], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f5, ftmp2) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, f5) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f2) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_open(filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_open(filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f2->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f2) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_open(filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f3->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f3) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f4 = H5F_open(filename[4],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f4->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f4) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f5 = H5F_open(filename[5],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f5->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f5) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 20: "Diamond" shape with links moving from bottom (root) to top.
+ * Also cycle between bottom (root) and top, cycles on the sides, and
+ * release the files instead of closing. */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(f0, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f1, filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, f3) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f2, filename[3], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, f3) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f0, filename[3], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f3, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f3, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f3) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f4 = H5F_efc_open(f1, filename[4],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_efc_open(f4, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f4, ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, f4) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f5 = H5F_efc_open(f2, filename[5],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp2 = H5F_efc_open(f5, filename[2], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f5, ftmp2) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, f5) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f2) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_open(filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_open(filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f2->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f2) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_open(filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f3->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f3) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f4 = H5F_open(filename[4],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f4->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f4) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f5 = H5F_open(filename[5],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f5->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f5) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 21: "Diamond" shape with links moving from bottom (root) to top.
+ * Also cycle between bottom (root) and top, cycles on sides held open. */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(f0, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f1, filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, f3) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f2, filename[3], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, f3) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f0, filename[3], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f3, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f3, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f3) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f4 = H5F_efc_open(f1, filename[4],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_efc_open(f4, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f4, ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, f4) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f4 = H5F_open(filename[4], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f5 = H5F_efc_open(f2, filename[5],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp2 = H5F_efc_open(f5, filename[2], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f5, ftmp2) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, f5) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f5 = H5F_open(filename[5], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f2) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(f4->shared->nrefs != 2)
+ TEST_ERROR
+ if(f5->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(f4->shared->nrefs != 2)
+ TEST_ERROR
+ if(f5->shared->nrefs != 2)
+ TEST_ERROR
+ if(NULL == (f0 = H5F_open(filename[0], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(H5F_try_close(f4) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(f5->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(f5->shared->nrefs != 2)
+ TEST_ERROR
+ if(NULL == (f0 = H5F_open(filename[0], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+
+ if(H5F_try_close(f5) < 0)
+ FAIL_STACK_ERROR
+
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_open(filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_open(filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f2->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f2) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_open(filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f3->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f3) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f4 = H5F_open(filename[4],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f4->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f4) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f5 = H5F_open(filename[5],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f5->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f5) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 22: "Diamond" shape with links moving from bottom (root) to top.
+ * Also cycle between bottom (root) and top, cycles on sides held open.
+ * Also release the files instead of closing. */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(f0, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f1, filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, f3) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f2, filename[3], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, f3) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f0, filename[3], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f3, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f3, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f3) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f4 = H5F_efc_open(f1, filename[4],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_efc_open(f4, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f4, ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, f4) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f4 = H5F_open(filename[4], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f5 = H5F_efc_open(f2, filename[5],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp2 = H5F_efc_open(f5, filename[2], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f5, ftmp2) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, f5) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f5 = H5F_open(filename[5], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f2) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(f4->shared->nrefs != 2)
+ TEST_ERROR
+ if(f5->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(f4->shared->nrefs != 2)
+ TEST_ERROR
+ if(f5->shared->nrefs != 2)
+ TEST_ERROR
+ if(NULL == (f3 = H5F_open(filename[3], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f3->shared->nrefs != 3)
+ TEST_ERROR
+ if(H5F_try_close(f3) < 0)
+ FAIL_STACK_ERROR
+
+ if(H5F_efc_release(f4->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(f4->shared->nrefs != 1)
+ TEST_ERROR
+ if(f5->shared->nrefs != 2)
+ TEST_ERROR
+ if(NULL == (f3 = H5F_open(filename[3], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f3->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_try_close(f3) < 0)
+ FAIL_STACK_ERROR
+
+ if(H5F_efc_release(f5->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(f4->shared->nrefs != 1)
+ TEST_ERROR
+ if(f5->shared->nrefs != 1)
+ TEST_ERROR
+ if(NULL == (f3 = H5F_open(filename[3], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f3->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f3) < 0)
+ FAIL_STACK_ERROR
+
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(f4) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(f5) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 23: Dense "ball" of files. 4 files each cache all files (including
+ * itself). */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f0, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(f0, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f0, filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+
+ if(NULL == (ftmp0 = H5F_efc_open(f1, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_efc_open(f1, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp2 = H5F_efc_open(f1, filename[2], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp2) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp3 = H5F_efc_open(f1, filename[3], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp3) < 0)
+ FAIL_STACK_ERROR
+
+ if(NULL == (ftmp0 = H5F_efc_open(f2, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_efc_open(f2, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp2 = H5F_efc_open(f2, filename[2], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, ftmp2) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp3 = H5F_efc_open(f2, filename[3], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, ftmp3) < 0)
+ FAIL_STACK_ERROR
+
+ if(NULL == (ftmp0 = H5F_efc_open(f3, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f3, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_efc_open(f3, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f3, ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp2 = H5F_efc_open(f3, filename[2], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f3, ftmp2) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp3 = H5F_efc_open(f3, filename[3], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f3, ftmp3) < 0)
+ FAIL_STACK_ERROR
+
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f2) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f3) < 0)
+ FAIL_STACK_ERROR
+
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_open(filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_open(filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f2->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f2) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_open(filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f3->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f3) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 24: Dense "ball" of files. 4 files each cache all files (including
+ * itself). Release the files instead of closing. */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f0, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(f0, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f0, filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+
+ if(NULL == (ftmp0 = H5F_efc_open(f1, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_efc_open(f1, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp2 = H5F_efc_open(f1, filename[2], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp2) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp3 = H5F_efc_open(f1, filename[3], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp3) < 0)
+ FAIL_STACK_ERROR
+
+ if(NULL == (ftmp0 = H5F_efc_open(f2, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_efc_open(f2, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp2 = H5F_efc_open(f2, filename[2], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, ftmp2) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp3 = H5F_efc_open(f2, filename[3], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, ftmp3) < 0)
+ FAIL_STACK_ERROR
+
+ if(NULL == (ftmp0 = H5F_efc_open(f3, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f3, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp1 = H5F_efc_open(f3, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f3, ftmp1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp2 = H5F_efc_open(f3, filename[2], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f3, ftmp2) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp3 = H5F_efc_open(f3, filename[3], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f3, ftmp3) < 0)
+ FAIL_STACK_ERROR
+
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f2) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f3) < 0)
+ FAIL_STACK_ERROR
+
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_open(filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_open(filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f2->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f2) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_open(filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f3->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f3) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 25: File held open by EFC client interrupts cycle, with release */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f1, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 26: File held open by EFC does not interrupt cycle, with release */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f1, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_efc_open(f0, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(f2->shared->nrefs != 1)
+ TEST_ERROR
+
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(f2->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_efc_close(f0, f2) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 27: File held open by EFC client through non-parent file does not
+ * interrupt cycle, but parent file does (no valid way around it) */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f1, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_open(filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f2, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f1, filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(f1->shared->nrefs != 2)
+ TEST_ERROR
+ if(f2->shared->nrefs != 1)
+ TEST_ERROR
+ if(f3->shared->nrefs != 1)
+ TEST_ERROR
+
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 2)
+ TEST_ERROR
+ if(f2->shared->nrefs != 1)
+ TEST_ERROR
+ if(f3->shared->nrefs != 1)
+ TEST_ERROR
+ if(NULL == (f0 = H5F_open(filename[0], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+
+ if(H5F_efc_close(f1, f3) < 0)
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 2)
+ TEST_ERROR
+ if(f2->shared->nrefs != 1)
+ TEST_ERROR
+ if(NULL == (f0 = H5F_open(filename[0], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_open(filename[3], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f3->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_try_close(f3) < 0)
+ FAIL_STACK_ERROR
+
+ if(H5F_efc_close(f2, f1) < 0)
+ FAIL_STACK_ERROR
+ if(f2->shared->nrefs != 1)
+ TEST_ERROR
+ if(NULL == (f0 = H5F_open(filename[0], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_open(filename[1], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 3)
+ TEST_ERROR
+ if(H5F_try_close(f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_open(filename[3], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f3->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_try_close(f3) < 0)
+ FAIL_STACK_ERROR
+
+ if(H5F_try_close(f2) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f0 = H5F_open(filename[0], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_open(filename[1], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_open(filename[2], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f2->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f2) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_open(filename[3], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f3->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f3) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 28: File held open by EFC client through non-parent file does not
+ * interrupt cycle, but parent file does (no valid way around it), with
+ * release */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f1, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_open(filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f2, filename[1], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_efc_open(f1, filename[3],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(f1->shared->nrefs != 2)
+ TEST_ERROR
+ if(f2->shared->nrefs != 1)
+ TEST_ERROR
+ if(f3->shared->nrefs != 1)
+ TEST_ERROR
+
+ if(H5F_efc_release(f0->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(f2->shared->nrefs != 1)
+ TEST_ERROR
+ if(f3->shared->nrefs != 1)
+ TEST_ERROR
+
+ if(H5F_efc_release(f2->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(f2->shared->nrefs != 1)
+ TEST_ERROR
+ if(f3->shared->nrefs != 1)
+ TEST_ERROR
+
+ if(H5F_efc_close(f1, f3) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f2, f1) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_release(f2->shared->efc) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(f2->shared->nrefs != 1)
+ TEST_ERROR
+ if(NULL == (f1 = H5F_open(filename[1], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f3 = H5F_open(filename[3], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f3->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f3) < 0)
+ FAIL_STACK_ERROR
+
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_try_close(f2) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 29: File without EFC interrupts cycle */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5Pset_elink_file_cache_size(fapl_id, 0) < 0)
+ TEST_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5Pset_elink_file_cache_size(fapl_id, 8) < 0)
+ TEST_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f1, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+ if(H5F_efc_close(f1, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f0 = H5F_open(filename[0], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_open(filename[1], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f1) < 0)
+ FAIL_STACK_ERROR
+
+
+ /* Test 30: File without EFC does not interrupt cycle */
+ if(NULL == (f0 = H5F_open(filename[0],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_efc_open(f0, filename[1],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(NULL == (ftmp0 = H5F_efc_open(f1, filename[0], H5F_ACC_RDWR, fcpl_id,
+ fapl_id, dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f1, ftmp0) < 0)
+ FAIL_STACK_ERROR
+ if(H5F_efc_close(f0, f1) < 0)
+ FAIL_STACK_ERROR
+ if(H5Pset_elink_file_cache_size(fapl_id, 0) < 0)
+ TEST_ERROR
+ if(NULL == (f2 = H5F_efc_open(f1, filename[2],
+ H5F_ACC_RDWR | H5F_ACC_CREAT | H5F_ACC_TRUNC, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(H5Pset_elink_file_cache_size(fapl_id, 8) < 0)
+ TEST_ERROR
+ if(H5F_efc_close(f1, f2) < 0)
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 2)
+ TEST_ERROR
+
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f0 = H5F_open(filename[0], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f0->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f0) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f1 = H5F_open(filename[1], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f1->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f1) < 0)
+ FAIL_STACK_ERROR
+ if(NULL == (f2 = H5F_open(filename[2], H5F_ACC_RDWR, fcpl_id, fapl_id,
+ dxpl_id)))
+ FAIL_STACK_ERROR
+ if(f2->shared->nrefs != 1)
+ TEST_ERROR
+ if(H5F_try_close(f2) < 0)
+ FAIL_STACK_ERROR
+
+
+ PASSED();
+
+ return 0;
+
+error:
+ return 1;
+} /* test_graph_cycle */
+
+
+/*-------------------------------------------------------------------------
+ * Function: main
+ *
+ * Purpose: Test the external file cache code
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Neil Fortner
+ * December 16, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+main(void)
+{
+ unsigned nerrors = 0; /* track errors */
+
+ /* Test Setup */
+ puts("Testing the external file cache");
+
+ /* Create property lists */
+ fcpl_id = H5Pcreate(H5P_FILE_CREATE);
+ fapl_id = h5_fileaccess();
+ dxpl_id = H5Pcreate(H5P_DATASET_XFER);
+
+ /* Patch filenames */
+ h5_fixname(FILENAME[0], fapl_id, filename[0], sizeof(filename[0]));
+ h5_fixname(FILENAME[1], fapl_id, filename[1], sizeof(filename[1]));
+ h5_fixname(FILENAME[2], fapl_id, filename[2], sizeof(filename[2]));
+ h5_fixname(FILENAME[3], fapl_id, filename[3], sizeof(filename[3]));
+ h5_fixname(FILENAME[4], fapl_id, filename[4], sizeof(filename[4]));
+ h5_fixname(FILENAME[5], fapl_id, filename[5], sizeof(filename[5]));
+
+ /* Test Functions */
+ nerrors += test_single();
+ nerrors += test_graph_nocycle();
+ nerrors += test_graph_cycle();
+
+ /* Close property lists */
+ if(H5Pclose(dxpl_id) < 0)
+ TEST_ERROR
+ if(H5Pclose(fcpl_id) < 0)
+ TEST_ERROR
+
+ if(nerrors)
+ goto error;
+
+ puts("All external file cache tests passed.");
+
+ h5_cleanup(FILENAME, fapl_id);
+
+ return 0;
+
+error:
+ puts("*** TESTS FAILED ***");
+
+ H5E_BEGIN_TRY {
+ H5Pclose(fapl_id);
+ } H5E_END_TRY
+
+ return 1;
+} /* end main() */
+
diff --git a/test/links.c b/test/links.c
index c8ece99..54b4a1b 100644
--- a/test/links.c
+++ b/test/links.c
@@ -6666,6 +6666,421 @@ error:
/*-------------------------------------------------------------------------
+ * Function: external_file_cache
+ *
+ * Purpose: Tests that the external file cache works with external
+ * links in a few basic cases. More complicated cases are
+ * tested by interfacing directly with the cache in efc.c.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Neil Fortner
+ * Thursday, January 13, 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+external_file_cache(hid_t fapl, hbool_t new_format)
+{
+ hid_t my_fapl = (-1); /* Temporary FAPL */
+ hid_t fid1 = (-1); /* File ID */
+ hid_t fid2 = (-1); /* File ID */
+ hid_t fid3 = (-1); /* File ID */
+ hid_t fid4 = (-1); /* File ID */
+ hid_t oid = (-1); /* Object ID */
+ unsigned efc_size;
+ char filename1[NAME_BUF_SIZE];
+ char filename2[NAME_BUF_SIZE];
+ char filename3[NAME_BUF_SIZE];
+ char filename4[NAME_BUF_SIZE];
+
+ if(new_format)
+ TESTING("external file cache with external links (w/new group format)")
+ else
+ TESTING("external file cache with external links")
+
+ /* Set up filenames */
+ h5_fixname(FILENAME[0], fapl, filename1, sizeof filename1);
+ h5_fixname(FILENAME[1], fapl, filename2, sizeof filename2);
+ h5_fixname(FILENAME[2], fapl, filename3, sizeof filename3);
+ h5_fixname(FILENAME[3], fapl, filename4, sizeof filename4);
+
+ /* Verify that the default EFC size is 0 */
+ if(H5Pget_elink_file_cache_size(fapl, &efc_size) < 0)
+ TEST_ERROR
+ if(efc_size != 0)
+ FAIL_PUTS_ERROR("default external file cache size is not 0")
+
+ /* Copy FAPL and enable external file caching */
+ if((my_fapl = H5Pcopy(fapl)) < 0)
+ TEST_ERROR
+ if(H5Pset_elink_file_cache_size(my_fapl, 8) < 0)
+ TEST_ERROR
+
+ /* Verify that the external file cache size has been set */
+ if(H5Pget_elink_file_cache_size(my_fapl, &efc_size) < 0)
+ TEST_ERROR
+ if(efc_size != 8)
+ FAIL_PUTS_ERROR("external file cache size different from expected")
+
+
+ /*
+ * Test 1: One file caches another
+ */
+ /* Create files */
+ if((fid1 = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0)
+ TEST_ERROR
+ if((fid2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0)
+ TEST_ERROR
+
+ /* Create link */
+ if(H5Lcreate_external(filename2, "/", fid1, "link_to_2", H5P_DEFAULT,
+ H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Close file 2 */
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+
+ /* Verify that only 1 file is open */
+ if(H5F_sfile_assert_num(1) < 0)
+ TEST_ERROR
+
+ /* Open and close the target of the external link */
+ if((oid = H5Oopen(fid1, "link_to_2", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if(H5Oclose(oid) < 0)
+ TEST_ERROR
+
+ /* Verify that both files are now open */
+ if(H5F_sfile_assert_num(2) < 0)
+ TEST_ERROR
+
+ /* Close file 1 */
+ if(H5Fclose(fid1) < 0)
+ TEST_ERROR
+
+ /* Verify that both files are now closed */
+ if(H5F_sfile_assert_num(0) < 0)
+ TEST_ERROR
+
+
+ /*
+ * Test 2: One file caches another, release parent's EFC
+ */
+ /* Create files */
+ if((fid1 = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0)
+ TEST_ERROR
+ if((fid2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0)
+ TEST_ERROR
+
+ /* Create link */
+ if(H5Lcreate_external(filename2, "/", fid1, "link_to_2", H5P_DEFAULT,
+ H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Close file 2 */
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+
+ /* Verify that only 1 file is open */
+ if(H5F_sfile_assert_num(1) < 0)
+ TEST_ERROR
+
+ /* Open and close the target of the external link */
+ if((oid = H5Oopen(fid1, "link_to_2", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if(H5Oclose(oid) < 0)
+ TEST_ERROR
+
+ /* Verify that both files are now open */
+ if(H5F_sfile_assert_num(2) < 0)
+ TEST_ERROR
+
+ /* Release file 1's EFC */
+ if(H5Frelease_file_cache(fid1) < 0)
+ TEST_ERROR
+
+ /* Verify that only the parent file is now open */
+ if(H5F_sfile_assert_num(1) < 0)
+ TEST_ERROR
+
+ /* Close file 1 */
+ if(H5Fclose(fid1) < 0)
+ TEST_ERROR
+
+ /* Verify that both files are now closed */
+ if(H5F_sfile_assert_num(0) < 0)
+ TEST_ERROR
+
+
+ /*
+ * Test 3: "Y" shaped tree
+ */
+ /* Create files */
+ if((fid1 = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0)
+ TEST_ERROR
+ if((fid2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0)
+ TEST_ERROR
+ if((fid3 = H5Fcreate(filename3, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0)
+ TEST_ERROR
+ if((fid4 = H5Fcreate(filename4, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0)
+ TEST_ERROR
+
+ /* Create links */
+ if(H5Lcreate_external(filename2, "/", fid1, "link_to_2", H5P_DEFAULT,
+ H5P_DEFAULT) < 0)
+ TEST_ERROR
+ if(H5Lcreate_external(filename3, "/", fid2, "link_to_3", H5P_DEFAULT,
+ H5P_DEFAULT) < 0)
+ TEST_ERROR
+ if(H5Lcreate_external(filename4, "/", fid2, "link_to_4", H5P_DEFAULT,
+ H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Close files 2-4 */
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid3) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid4) < 0)
+ TEST_ERROR
+
+ /* Verify that only 1 file is open */
+ if(H5F_sfile_assert_num(1) < 0)
+ TEST_ERROR
+
+ /* Open and close one branch of the tree */
+ if((oid = H5Oopen(fid1, "link_to_2/link_to_3", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if(H5Oclose(oid) < 0)
+ TEST_ERROR
+
+ /* Verify that files 2 and 3 are now open */
+ if(H5F_sfile_assert_num(3) < 0)
+ TEST_ERROR
+
+ /* Open and close the other branch of the tree */
+ if((oid = H5Oopen(fid1, "link_to_2/link_to_4", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if(H5Oclose(oid) < 0)
+ TEST_ERROR
+
+ /* Verify that all files are now open */
+ if(H5F_sfile_assert_num(4) < 0)
+ TEST_ERROR
+
+ /* Close file 1 */
+ if(H5Fclose(fid1) < 0)
+ TEST_ERROR
+
+ /* Verify that all files are now closed */
+ if(H5F_sfile_assert_num(0) < 0)
+ TEST_ERROR
+
+
+ /*
+ * Test 4: "Y" shaped tree, release parent's EFC
+ */
+ /* Create files */
+ if((fid1 = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0)
+ TEST_ERROR
+ if((fid2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0)
+ TEST_ERROR
+ if((fid3 = H5Fcreate(filename3, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0)
+ TEST_ERROR
+ if((fid4 = H5Fcreate(filename4, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0)
+ TEST_ERROR
+
+ /* Create links */
+ if(H5Lcreate_external(filename2, "/", fid1, "link_to_2", H5P_DEFAULT,
+ H5P_DEFAULT) < 0)
+ TEST_ERROR
+ if(H5Lcreate_external(filename3, "/", fid2, "link_to_3", H5P_DEFAULT,
+ H5P_DEFAULT) < 0)
+ TEST_ERROR
+ if(H5Lcreate_external(filename4, "/", fid2, "link_to_4", H5P_DEFAULT,
+ H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Close files 2-4 */
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid3) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid4) < 0)
+ TEST_ERROR
+
+ /* Verify that only 1 file is open */
+ if(H5F_sfile_assert_num(1) < 0)
+ TEST_ERROR
+
+ /* Open and close one branch of the tree */
+ if((oid = H5Oopen(fid1, "link_to_2/link_to_3", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if(H5Oclose(oid) < 0)
+ TEST_ERROR
+
+ /* Verify that files 2 and 3 are now open */
+ if(H5F_sfile_assert_num(3) < 0)
+ TEST_ERROR
+
+ /* Open and close the other branch of the tree */
+ if((oid = H5Oopen(fid1, "link_to_2/link_to_4", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if(H5Oclose(oid) < 0)
+ TEST_ERROR
+
+ /* Verify that all files are now open */
+ if(H5F_sfile_assert_num(4) < 0)
+ TEST_ERROR
+
+ /* Release file 1's EFC */
+ if(H5Frelease_file_cache(fid1) < 0)
+ TEST_ERROR
+
+ /* Verify that only file 1 is now open */
+ if(H5F_sfile_assert_num(1) < 0)
+ TEST_ERROR
+
+ /* Close file 1 */
+ if(H5Fclose(fid1) < 0)
+ TEST_ERROR
+
+ /* Verify that all files are now closed */
+ if(H5F_sfile_assert_num(0) < 0)
+ TEST_ERROR
+
+
+ /*
+ * Test 3: 3 file cycle
+ */
+ /* Create files */
+ if((fid1 = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0)
+ TEST_ERROR
+ if((fid2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0)
+ TEST_ERROR
+ if((fid3 = H5Fcreate(filename3, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0)
+ TEST_ERROR
+
+ /* Create links */
+ if(H5Lcreate_external(filename2, "/", fid1, "link_to_2", H5P_DEFAULT,
+ H5P_DEFAULT) < 0)
+ TEST_ERROR
+ if(H5Lcreate_external(filename3, "/", fid2, "link_to_3", H5P_DEFAULT,
+ H5P_DEFAULT) < 0)
+ TEST_ERROR
+ if(H5Lcreate_external(filename1, "/", fid3, "link_to_1", H5P_DEFAULT,
+ H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Close files 2-3 */
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid3) < 0)
+ TEST_ERROR
+
+ /* Verify that only 1 file is open */
+ if(H5F_sfile_assert_num(1) < 0)
+ TEST_ERROR
+
+ /* Open and close one complete cycle */
+ if((oid = H5Oopen(fid1, "link_to_2/link_to_3/link_to_1", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if(H5Oclose(oid) < 0)
+ TEST_ERROR
+
+ /* Verify that all files are now open */
+ if(H5F_sfile_assert_num(3) < 0)
+ TEST_ERROR
+
+ /* Close file 1 */
+ if(H5Fclose(fid1) < 0)
+ TEST_ERROR
+
+ /* Verify that all files are now closed */
+ if(H5F_sfile_assert_num(0) < 0)
+ TEST_ERROR
+
+
+ /*
+ * Test 3: 3 file cycle, release parent's EFC
+ */
+ /* Create files */
+ if((fid1 = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0)
+ TEST_ERROR
+ if((fid2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0)
+ TEST_ERROR
+ if((fid3 = H5Fcreate(filename3, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0)
+ TEST_ERROR
+
+ /* Create links */
+ if(H5Lcreate_external(filename2, "/", fid1, "link_to_2", H5P_DEFAULT,
+ H5P_DEFAULT) < 0)
+ TEST_ERROR
+ if(H5Lcreate_external(filename3, "/", fid2, "link_to_3", H5P_DEFAULT,
+ H5P_DEFAULT) < 0)
+ TEST_ERROR
+ if(H5Lcreate_external(filename1, "/", fid3, "link_to_1", H5P_DEFAULT,
+ H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Close files 2-3 */
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid3) < 0)
+ TEST_ERROR
+
+ /* Verify that only 1 file is open */
+ if(H5F_sfile_assert_num(1) < 0)
+ TEST_ERROR
+
+ /* Open and close one complete cycle */
+ if((oid = H5Oopen(fid1, "link_to_2/link_to_3/link_to_1", H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if(H5Oclose(oid) < 0)
+ TEST_ERROR
+
+ /* Verify that all files are now open */
+ if(H5F_sfile_assert_num(3) < 0)
+ TEST_ERROR
+
+ /* Release file 1's EFC */
+ if(H5Frelease_file_cache(fid1) < 0)
+ TEST_ERROR
+
+ /* Verify that only file 1 is now open */
+ if(H5F_sfile_assert_num(1) < 0)
+ TEST_ERROR
+
+ /* Close file 1 */
+ if(H5Fclose(fid1) < 0)
+ TEST_ERROR
+
+ /* Verify that all files are now closed */
+ if(H5F_sfile_assert_num(0) < 0)
+ TEST_ERROR
+
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Oclose(oid);
+ H5Fclose(fid1);
+ H5Fclose(fid2);
+ H5Fclose(fid3);
+ H5Fclose(fid4);
+ H5Pclose(my_fapl);
+ } H5E_END_TRY
+
+ return -1;
+} /* end external_file_cache */
+
+
+/*-------------------------------------------------------------------------
* Function: ud_hard_links
*
* Purpose: Check that the functionality of hard links can be duplicated
@@ -13866,6 +14281,7 @@ main(void)
hid_t fapl, fapl2; /* File access property lists */
int nerrors = 0;
hbool_t new_format; /* Whether to use the new format or not */
+ hbool_t efc; /* Whether to use the external file cache */
const char *env_h5_drvr; /* File Driver value from environment */
env_h5_drvr = HDgetenv("HDF5_DRIVER");
@@ -13907,57 +14323,83 @@ main(void)
#ifndef H5_NO_DEPRECATED_SYMBOLS
nerrors += test_deprec(my_fapl, new_format);
#endif /* H5_NO_DEPRECATED_SYMBOLS */
+
+ /* tests for external link */
+ /* Test external file cache first, so it sees the default efc setting on
+ * the fapl */
+ nerrors += external_file_cache(my_fapl, new_format) < 0 ? 1 : 0;
+
+ /* This test cannot run with the EFC because it assumes that an
+ * intermediate file is not held open */
+ nerrors += external_link_mult(my_fapl, new_format) < 0 ? 1 : 0;
+
+ /* This test cannot run with the EFC because the EFC cannot currently
+ * reopen a cached file with a different intent */
+ nerrors += external_set_elink_acc_flags(my_fapl, new_format) < 0 ? 1 : 0;
+
+ /* Try external link tests both with and without the external file cache
+ */
+ for(efc = FALSE; efc <= TRUE; efc++) {
+ if(efc) {
+ if(H5Pset_elink_file_cache_size(my_fapl, 8) < 0)
+ TEST_ERROR
+ printf("\n---Testing with external file cache---\n");
+ } /* end if */
+ else {
+ if(H5Pset_elink_file_cache_size(my_fapl, 0) < 0)
+ TEST_ERROR
+ printf("\n---Testing without external file cache---\n");
+ } /* end else */
+
#ifndef H5_CANNOT_OPEN_TWICE
- nerrors += external_link_root(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_root(my_fapl, new_format) < 0 ? 1 : 0;
#endif /* H5_CANNOT_OPEN_TWICE */
- nerrors += external_link_path(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_link_mult(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_path(my_fapl, new_format) < 0 ? 1 : 0;
#ifndef H5_CANNOT_OPEN_TWICE
- nerrors += external_link_self(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_link_pingpong(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_link_toomany(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_self(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_pingpong(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_toomany(my_fapl, new_format) < 0 ? 1 : 0;
#endif /* H5_CANNOT_OPEN_TWICE */
- nerrors += external_link_dangling(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_link_recursive(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_link_query(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_link_unlink_compact(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_link_unlink_dense(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_link_move(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_link_ride(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_dangling(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_recursive(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_query(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_unlink_compact(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_unlink_dense(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_move(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_ride(my_fapl, new_format) < 0 ? 1 : 0;
#ifndef H5_CANNOT_OPEN_TWICE
- nerrors += external_link_closing(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_closing(my_fapl, new_format) < 0 ? 1 : 0;
#endif /* H5_CANNOT_OPEN_TWICE */
- nerrors += external_link_endian(new_format) < 0 ? 1 : 0;
- nerrors += external_link_strong(my_fapl, new_format) < 0 ? 1 : 0;
-
- /* tests for external link */
- nerrors += external_link_prefix(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_link_abs_mainpath(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_link_rel_mainpath(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_link_cwd(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_link_abstar(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_link_abstar_cur(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_link_reltar(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_link_chdir(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_set_elink_fapl1(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_set_elink_fapl2(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_set_elink_fapl3(new_format) < 0 ? 1 : 0;
- nerrors += external_set_elink_acc_flags(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_set_elink_cb(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_endian(new_format) < 0 ? 1 : 0;
+ nerrors += external_link_strong(my_fapl, new_format) < 0 ? 1 : 0;
+
+ nerrors += external_link_prefix(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_abs_mainpath(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_rel_mainpath(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_cwd(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_abstar(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_abstar_cur(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_reltar(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_chdir(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_set_elink_fapl1(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_set_elink_fapl2(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_set_elink_fapl3(new_format) < 0 ? 1 : 0;
+ nerrors += external_set_elink_cb(my_fapl, new_format) < 0 ? 1 : 0;
#ifdef H5_HAVE_WINDOW_PATH
- nerrors += external_link_win1(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_link_win2(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_link_win3(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_link_win4(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_link_win5(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_link_win6(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_link_win7(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_link_win8(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_link_win9(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_win1(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_win2(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_win3(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_win4(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_win5(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_win6(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_win7(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_win8(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_link_win9(my_fapl, new_format) < 0 ? 1 : 0;
#endif
- nerrors += external_symlink(env_h5_drvr, my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_copy_invalid_object(my_fapl, new_format) < 0 ? 1 : 0;
- nerrors += external_dont_fail_to_source(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_symlink(env_h5_drvr, my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_copy_invalid_object(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_dont_fail_to_source(my_fapl, new_format) < 0 ? 1 : 0;
+ } /* end for */
/* These tests assume that external links are a form of UD links,
* so assume that everything that passed for external links