summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2005-08-08 18:41:35 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2005-08-08 18:41:35 (GMT)
commit502b4c206d238dff6bdca09075ffeb426a365a9e (patch)
treecbe48af2cf27d0ddb9a57d3828245b4428221320
parentc5781c8289ad4abc83073f5b53a20179169eb59c (diff)
downloadhdf5-502b4c206d238dff6bdca09075ffeb426a365a9e.zip
hdf5-502b4c206d238dff6bdca09075ffeb426a365a9e.tar.gz
hdf5-502b4c206d238dff6bdca09075ffeb426a365a9e.tar.bz2
[svn-r11215] Purpose:
Bug fix & code cleanup Description: Fix another bug in the file mounting code and refactor the unmount code that it is simpler. Platforms tested: FreeBSD 4.11 (sleipnir) Linux 2.4 Too minor to require h5committest
-rw-r--r--MANIFEST1
-rw-r--r--src/H5F.c212
-rw-r--r--src/H5Fmount.c89
-rw-r--r--src/H5Fpkg.h5
-rw-r--r--src/H5Fprivate.h3
-rw-r--r--src/H5Fsfile.c226
-rwxr-xr-xsrc/Makefile.am2
-rw-r--r--src/Makefile.in42
-rw-r--r--test/mount.c1203
-rw-r--r--test/tfile.c4
-rw-r--r--tools/h5diff/h5diff_common.c2
-rw-r--r--tools/lib/h5diff.h2
12 files changed, 1537 insertions, 254 deletions
diff --git a/MANIFEST b/MANIFEST
index 1201958..0d8bd06 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -429,6 +429,7 @@ a------------------------------------------------------------------------------
./src/H5F.c
./src/H5Fdbg.c
./src/H5Fmount.c
+./src/H5Fsfile.c
./src/H5Fsuper.c
./src/H5Fpkg.h
./src/H5Fprivate.h
diff --git a/src/H5F.c b/src/H5F.c
index ea9e608..4cd5b67 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -60,12 +60,6 @@ typedef struct H5F_olist_t {
int max_index; /* Maximum # of IDs to put into array */
} H5F_olist_t;
-/* Struct for tracking "shared" file structs */
-typedef struct H5F_sfile_node_t {
- H5F_file_t *shared; /* Pointer to "shared" struct */
- struct H5F_sfile_node_t *next; /* Pointer to next node */
-} H5F_sfile_node_t;
-
/* PRIVATE PROTOTYPES */
#ifdef NOT_YET
@@ -81,23 +75,12 @@ static unsigned H5F_get_objects(const H5F_t *f, unsigned types, int max_objs, hi
static int H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key);
static herr_t H5F_get_vfd_handle(const H5F_t *file, hid_t fapl, void** file_handle);
-/* Routines to operate on the shared file list */
-static herr_t H5F_shared_add(H5F_file_t *shared);
-static H5F_file_t * H5F_shared_search(H5FD_t *lf);
-static herr_t H5F_shared_remove(H5F_file_t *shared);
-
/* Declare a free list to manage the H5F_t struct */
H5FL_DEFINE_STATIC(H5F_t);
/* Declare a free list to manage the H5F_file_t struct */
H5FL_DEFINE_STATIC(H5F_file_t);
-/* Declare a free list to manage the H5F_sfile_node_t struct */
-H5FL_DEFINE_STATIC(H5F_sfile_node_t);
-
-/* Declare a local variable to track the shared file information */
-H5F_sfile_node_t *H5F_sfile_head_g = NULL;
-
/*-------------------------------------------------------------------------
* Function: H5F_init
@@ -452,7 +435,7 @@ H5F_term_interface(void)
H5I_clear_type(H5I_FILE, FALSE);
} else {
/* Make certain we've cleaned up all the shared file objects */
- HDassert(H5F_sfile_head_g == NULL);
+ H5F_sfile_assert_num(0);
H5I_dec_type_ref(H5I_FILE);
H5_interface_initialize_g = 0;
@@ -1535,7 +1518,7 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create open object data structure")
/* Add new "shared" struct to list of open files */
- if(H5F_shared_add(f->shared) < 0)
+ if(H5F_sfile_add(f->shared) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to append to list of open files")
} /* end else */
@@ -1601,7 +1584,7 @@ H5F_dest(H5F_t *f, hid_t dxpl_id)
if (1==f->shared->nrefs) {
/* Remove shared file struct from list of open files */
- if(H5F_shared_remove(f->shared) < 0) {
+ if(H5F_sfile_remove(f->shared) < 0) {
HERROR(H5E_FILE, H5E_CANTRELEASE, "problems closing file");
ret_value = FAIL; /*but keep going*/
} /* end if */
@@ -1811,7 +1794,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t d
} /* end if */
/* Is the file already open? */
- if ((shared = H5F_shared_search(lf)) != NULL) {
+ if ((shared = H5F_sfile_search(lf)) != NULL) {
/*
* The file is already open, so use that one instead of the one we
* just opened. We only one one H5FD_t* per file so one doesn't
@@ -2579,6 +2562,24 @@ H5F_close(H5F_t *f)
HDassert(f);
HDassert(f->file_id > 0); /* This routine should only be called when a file ID's ref count drops to zero */
+ /* Perform checks for "semi" file close degree here, since closing the
+ * file is not allowed if there are objects still open */
+ if(f->shared->fc_degree == H5F_CLOSE_SEMI) {
+ unsigned nopen_files = 0; /* Number of open files in file/mount hierarchy */
+ unsigned nopen_objs = 0; /* Number of open objects in file/mount hierarchy */
+
+ /* Get the number of open objects and open files on this file/mount hierarchy */
+ if(H5F_mount_count_ids(f, &nopen_files, &nopen_objs) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_MOUNT, FAIL, "problem checking mount hierarchy")
+
+ /* If there are no other file IDs open on this file/mount hier., but
+ * there are still open objects, issue an error and bail out now,
+ * without decrementing the file ID's reference count and triggering
+ * a "real" attempt at closing the file */
+ if(nopen_files == 1 && nopen_objs > 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, there are objects still open")
+ } /* end if */
+
/* Reset the file ID for this file */
f->file_id = -1;
@@ -2781,43 +2782,15 @@ done:
herr_t
H5Fclose(hid_t file_id)
{
- H5F_t *f;
herr_t ret_value = SUCCEED;
FUNC_ENTER_API(H5Fclose, FAIL)
H5TRACE1("e","i",file_id);
/* Check/fix arguments. */
- if (NULL == (f = H5I_object_verify(file_id,H5I_FILE)))
+ if (H5I_FILE != H5I_get_type(file_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file ID")
- /* Perform checks for "semi" file close degree here, since closing the
- * file ID will mess things up if we need to return FAIL */
- if(f->shared->fc_degree == H5F_CLOSE_SEMI) {
- int ref_count; /* Reference count for file's ID */
-
- /* Get the reference count for this ID */
- if((ref_count = H5I_get_ref(file_id)) < 0)
- HGOTO_ERROR (H5E_ATOM, H5E_CANTGET, FAIL, "can't get ID ref count")
-
- /* If we will be decrementing the reference count to zero, check for objects open */
- if(ref_count == 1) {
- unsigned nopen_files = 0; /* Number of open files in file/mount hierarchy */
- unsigned nopen_objs = 0; /* Number of open objects in file/mount hierarchy */
-
- /* Get the number of open objects and open files on this file/mount hierarchy */
- if(H5F_mount_count_ids(f, &nopen_files, &nopen_objs) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_MOUNT, FAIL, "problem checking mount hierarchy")
-
- /* If there are no other file IDs open on this file/mount hier., but
- * there are still open objects, issue an error and bail out now,
- * before decrementing the file ID's reference count and triggering
- * a "real" attempt at closing the file */
- if(nopen_files == 1 && nopen_objs > 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, there are objects still open")
- } /* end if */
- } /* end if */
-
/*
* Decrement reference count on atom. When it reaches zero the file will
* be closed.
@@ -4163,142 +4136,3 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Fget_name() */
-
-/*-------------------------------------------------------------------------
- * Function: H5F_shared_add
- *
- * Purpose: Add a "shared" file struct to the list of open files
- *
- * Return: SUCCEED/FAIL
- *
- * Programmer: Quincey Koziol
- * Monday, July 18, 2005
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5F_shared_add(H5F_file_t *shared)
-{
- H5F_sfile_node_t *new_shared; /* New shared file node */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5F_shared_add)
-
- /* Sanity check */
- HDassert(shared);
-
- /* Allocate new shared file node */
- if (NULL == (new_shared = H5FL_CALLOC(H5F_sfile_node_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
-
- /* Set shared file value */
- new_shared->shared = shared;
-
- /* Prepend to list of shared files open */
- new_shared->next = H5F_sfile_head_g;
- H5F_sfile_head_g = new_shared;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_shared_add() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_shared_search
- *
- * Purpose: Search for a "shared" file with low-level file info that
- * matches
- *
- * Return: Non-NULL on success / NULL on failure
- *
- * Programmer: Quincey Koziol
- * Monday, July 18, 2005
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static H5F_file_t *
-H5F_shared_search(H5FD_t *lf)
-{
- H5F_sfile_node_t *curr; /* Current shared file node */
- H5F_file_t *ret_value = NULL; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_shared_search)
-
- /* Sanity check */
- HDassert(lf);
-
- /* Iterate through low-level files for matching low-level file info */
- curr = H5F_sfile_head_g;
- while(curr) {
- /* Check for match */
- if(0==H5FD_cmp(curr->shared->lf, lf))
- HGOTO_DONE(curr->shared)
-
- /* Advance to next shared file node */
- curr = curr->next;
- } /* end while */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_shared_search() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_shared_remove
- *
- * Purpose: Remove a "shared" file struct from the list of open files
- *
- * Return: SUCCEED/FAIL
- *
- * Programmer: Quincey Koziol
- * Monday, July 18, 2005
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5F_shared_remove(H5F_file_t *shared)
-{
- H5F_sfile_node_t *curr; /* Current shared file node */
- H5F_sfile_node_t *last; /* Last shared file node */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5F_shared_remove)
-
- /* Sanity check */
- HDassert(shared);
-
- /* Locate shared file node with correct shared file */
- last = NULL;
- curr = H5F_sfile_head_g;
- while(curr && curr->shared != shared) {
- /* Advance to next node */
- last = curr;
- curr = curr->next;
- } /* end while */
-
- /* Indicate error if the node wasn't found */
- if(curr == NULL)
- HGOTO_ERROR(H5E_FILE, H5E_NOTFOUND, FAIL, "can't find shared file info")
-
- /* Remove node found from list */
- if(last != NULL)
- /* Removing middle or tail node in list */
- last->next = curr->next;
- else
- /* Removing head node in list */
- H5F_sfile_head_g = curr->next;
-
- /* Release the shared file node struct */
- /* (the shared file info itself is freed elsewhere) */
- H5FL_FREE(H5F_sfile_node_t, curr);
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_shared_remove() */
-
diff --git a/src/H5Fmount.c b/src/H5Fmount.c
index 7e234a5..18feb9c 100644
--- a/src/H5Fmount.c
+++ b/src/H5Fmount.c
@@ -34,7 +34,7 @@
NAME
H5F_init_mount_interface -- Initialize interface-specific information
USAGE
- herr_t H5T_init_mount_interface()
+ herr_t H5F_init_mount_interface()
RETURNS
Non-negative on success/Negative on failure
@@ -256,15 +256,15 @@ static herr_t
H5F_unmount(H5G_entry_t *loc, const char *name, hid_t dxpl_id)
{
H5G_t *mounted = NULL; /*mount point group */
+ H5G_t *child_group = NULL; /* Child's group in parent mtab */
+ H5F_t *child_file = NULL; /* Child's file in parent mtab */
H5G_entry_t *mnt_ent = NULL; /*mounted symbol table entry */
H5F_t *child = NULL; /*mounted file */
H5F_t *parent = NULL; /*file where mounted */
H5G_entry_t *ent = NULL; /*temporary symbol table entry */
- H5G_entry_t mnt_open_ent; /* entry used to open mount point*/
- herr_t ret_value = FAIL; /*return value */
- unsigned i; /*coutners */
- unsigned lt, rt, md=0; /*binary search indices */
- int cmp; /*binary search comparison value*/
+ H5G_entry_t mnt_open_ent; /* entry used to open mount point*/
+ int child_idx; /* Index of child in parent's mtab */
+ herr_t ret_value = SUCCEED; /*return value */
FUNC_ENTER_NOAPI_NOINIT(H5F_unmount)
@@ -283,37 +283,27 @@ H5F_unmount(H5G_entry_t *loc, const char *name, hid_t dxpl_id)
child = H5G_fileof(mounted);
mnt_ent = H5G_entof(mounted);
ent = H5G_entof(child->shared->root_grp);
+ child_idx = -1;
if (child->mtab.parent && H5F_addr_eq(mnt_ent->header, ent->header)) {
+ unsigned u; /*counters */
+
/*
* We've been given the root group of the child. We do a reverse
* lookup in the parent's mount table to find the correct entry.
*/
parent = child->mtab.parent;
- for (i=0; i<parent->mtab.nmounts; i++) {
- if (parent->mtab.child[i].file==child) {
- /* Search the open IDs replace names to reflect unmount operation */
- if (H5G_replace_name( H5G_UNKNOWN, mnt_ent, mnt_ent->user_path_r, NULL, NULL, NULL, OP_UNMOUNT )<0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to replace name ")
-
- /* Unmount the child */
- parent->mtab.nmounts -= 1;
- if(H5G_unmount(parent->mtab.child[md].group)<0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to reset group mounted flag")
- if(H5G_close(parent->mtab.child[i].group)<0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close unmounted group")
- child->mtab.parent = NULL;
- if(H5F_try_close(child)<0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close unmounted file")
-
- /* Eliminate the mount point from the table */
- HDmemmove(parent->mtab.child+i, parent->mtab.child+i+1,
- (parent->mtab.nmounts-i)* sizeof(parent->mtab.child[0]));
- ret_value = SUCCEED;
+ for (u=0; u<parent->mtab.nmounts; u++) {
+ if (parent->mtab.child[u].file==child) {
+ /* Found the correct index */
+ child_idx = u;
+ break;
}
}
- HDassert(ret_value>=0);
} else {
+ unsigned lt, rt, md=0; /*binary search indices */
+ int cmp; /*binary search comparison value*/
+
/*
* We've been given the mount point in the parent. We use a binary
* search in the parent to locate the mounted file, if any.
@@ -335,22 +325,37 @@ H5F_unmount(H5G_entry_t *loc, const char *name, hid_t dxpl_id)
if (cmp)
HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "not a mount point")
- /* Unmount the child */
- parent->mtab.nmounts -= 1;
- if(H5G_unmount(parent->mtab.child[md].group)<0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to reset group mounted flag")
- if(H5G_close(parent->mtab.child[md].group)<0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close unmounted group")
- parent->mtab.child[md].file->mtab.parent = NULL;
- if(H5F_try_close(parent->mtab.child[md].file)<0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close unmounted file")
-
- /* Eliminate the mount point from the table */
- HDmemmove(parent->mtab.child+md, parent->mtab.child+md+1,
- (parent->mtab.nmounts-md)*sizeof(parent->mtab.child[0]));
- ret_value = SUCCEED;
+ /* Found the correct index */
+ child_idx = md;
+ mnt_ent = ent;
}
-
+
+ HDassert(child_idx >= 0);
+
+ /* Search the open IDs replace names to reflect unmount operation */
+ if (H5G_replace_name(H5G_UNKNOWN, mnt_ent, mnt_ent->user_path_r, NULL, NULL, NULL, OP_UNMOUNT )<0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to replace name ")
+
+ /* Save the information about the child from the mount table */
+ child_group = parent->mtab.child[child_idx].group;
+ child_file = parent->mtab.child[child_idx].file;
+
+ /* Eliminate the mount point from the table */
+ HDmemmove(parent->mtab.child+child_idx, parent->mtab.child+child_idx+1,
+ (parent->mtab.nmounts-child_idx)*sizeof(parent->mtab.child[0]));
+ parent->mtab.nmounts -= 1;
+
+ /* Unmount the child file from the parent file */
+ if(H5G_unmount(child_group)<0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to reset group mounted flag")
+ if(H5G_close(child_group)<0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close unmounted group")
+
+ /* Detach child file from parent & see if it should close */
+ child_file->mtab.parent = NULL;
+ if(H5F_try_close(child_file)<0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close unmounted file")
+
done:
if (mounted)
if(H5G_close(mounted)<0 && ret_value>=0)
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index 596103e..8e68d0b 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -178,5 +178,10 @@ H5_DLL hsize_t H5F_init_superblock(const H5F_t *f, hid_t dxpl_id);
H5_DLL herr_t H5F_write_superblock(H5F_t *f, hid_t dxpl_id, uint8_t *buf);
H5_DLL herr_t H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_entry_t *root_ent, haddr_t addr, uint8_t *buf, size_t buf_size);
+/* Shared file list related routines */
+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);
+
#endif
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index 52b92dc..697a260 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -481,6 +481,9 @@ H5_DLL herr_t H5F_acs_close(hid_t fapl_id, void *close_data);
H5_DLL herr_t H5F_acs_copy(hid_t new_fapl_id, hid_t old_fapl_id,
void *close_data);
+/* Shared file list related routines */
+H5_DLL herr_t H5F_sfile_assert_num(unsigned n);
+
/* Debugging functions */
H5_DLL herr_t H5F_debug(H5F_t *f, hid_t dxpl_id, FILE * stream, int indent, int fwidth);
diff --git a/src/H5Fsfile.c b/src/H5Fsfile.c
new file mode 100644
index 0000000..70eb420
--- /dev/null
+++ b/src/H5Fsfile.c
@@ -0,0 +1,226 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#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 "H5FDprivate.h" /* File drivers */
+#include "H5FLprivate.h" /* Free lists */
+
+/* PRIVATE TYPEDEFS */
+
+/* Struct for tracking "shared" file structs */
+typedef struct H5F_sfile_node_t {
+ H5F_file_t *shared; /* Pointer to "shared" file struct */
+ struct H5F_sfile_node_t *next; /* Pointer to next node */
+} H5F_sfile_node_t;
+
+/* PRIVATE PROTOTYPES */
+
+/* PRIVATE VARIABLES */
+
+/* Declare a free list to manage the H5F_sfile_node_t struct */
+H5FL_DEFINE_STATIC(H5F_sfile_node_t);
+
+/* Declare a local variable to track the shared file information */
+H5F_sfile_node_t *H5F_sfile_head_g = NULL;
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_sfile_assert_empty
+ *
+ * Purpose: Sanity checking that shared file list is empty
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Monday, July 25, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_sfile_assert_num(unsigned n)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sfile_assert_num)
+
+ if(n == 0) {
+ /* Sanity checking */
+ HDassert(H5F_sfile_head_g == NULL);
+ } /* end if */
+ else {
+ unsigned count; /* Number of open shared files */
+ H5F_sfile_node_t *curr; /* Current shared file node */
+
+ /* Iterate through low-level files for matching low-level file info */
+ curr = H5F_sfile_head_g;
+ count = 0;
+ while(curr) {
+ /* Increment # of open shared file structs */
+ count++;
+
+ /* Advance to next shared file node */
+ curr = curr->next;
+ } /* end while */
+
+ /* Sanity checking */
+ HDassert(count == n);
+ } /* end else */
+
+ FUNC_LEAVE_NOAPI(SUCCEED);
+} /* H5F_sfile_assert_num() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_sfile_add
+ *
+ * Purpose: Add a "shared" file struct to the list of open files
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Monday, July 18, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_sfile_add(H5F_file_t *shared)
+{
+ H5F_sfile_node_t *new_shared; /* New shared file node */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5F_sfile_add)
+
+ /* Sanity check */
+ HDassert(shared);
+
+ /* Allocate new shared file node */
+ if (NULL == (new_shared = H5FL_CALLOC(H5F_sfile_node_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Set shared file value */
+ new_shared->shared = shared;
+
+ /* Prepend to list of shared files open */
+ new_shared->next = H5F_sfile_head_g;
+ H5F_sfile_head_g = new_shared;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_sfile_add() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_sfile_search
+ *
+ * Purpose: Search for a "shared" file with low-level file info that
+ * matches
+ *
+ * Return: Non-NULL on success / NULL on failure
+ *
+ * Programmer: Quincey Koziol
+ * Monday, July 18, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+H5F_file_t *
+H5F_sfile_search(H5FD_t *lf)
+{
+ H5F_sfile_node_t *curr; /* Current shared file node */
+ H5F_file_t *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sfile_search)
+
+ /* Sanity check */
+ HDassert(lf);
+
+ /* Iterate through low-level files for matching low-level file info */
+ curr = H5F_sfile_head_g;
+ while(curr) {
+ /* Check for match */
+ if(0==H5FD_cmp(curr->shared->lf, lf))
+ HGOTO_DONE(curr->shared)
+
+ /* Advance to next shared file node */
+ curr = curr->next;
+ } /* end while */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_sfile_search() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_sfile_remove
+ *
+ * Purpose: Remove a "shared" file struct from the list of open files
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Monday, July 18, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_sfile_remove(H5F_file_t *shared)
+{
+ H5F_sfile_node_t *curr; /* Current shared file node */
+ H5F_sfile_node_t *last; /* Last shared file node */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5F_sfile_remove)
+
+ /* Sanity check */
+ HDassert(shared);
+
+ /* Locate shared file node with correct shared file */
+ last = NULL;
+ curr = H5F_sfile_head_g;
+ while(curr && curr->shared != shared) {
+ /* Advance to next node */
+ last = curr;
+ curr = curr->next;
+ } /* end while */
+
+ /* Indicate error if the node wasn't found */
+ if(curr == NULL)
+ HGOTO_ERROR(H5E_FILE, H5E_NOTFOUND, FAIL, "can't find shared file info")
+
+ /* Remove node found from list */
+ if(last != NULL)
+ /* Removing middle or tail node in list */
+ last->next = curr->next;
+ else
+ /* Removing head node in list */
+ H5F_sfile_head_g = curr->next;
+
+ /* Release the shared file node struct */
+ /* (the shared file info itself is freed elsewhere) */
+ H5FL_FREE(H5F_sfile_node_t, curr);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_sfile_remove() */
+
diff --git a/src/Makefile.am b/src/Makefile.am
index 0644418..7091120 100755
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -48,7 +48,7 @@ libhdf5_la_SOURCES= H5.c H5A.c H5AC.c H5B.c H5B2.c H5B2cache.c H5B2dbg.c \
H5Dcontig.c \
H5Dcompact.c \
H5Defl.c H5Dio.c H5Distore.c H5Dmpio.c H5Dselect.c H5Dtest.c H5E.c H5F.c \
- H5Fdbg.c H5Fmount.c H5Fsuper.c H5FD.c H5FDcore.c \
+ H5Fdbg.c H5Fmount.c H5Fsfile.c H5Fsuper.c H5FD.c H5FDcore.c \
H5FDfamily.c H5FDfphdf5.c H5FDlog.c H5FDmpi.c H5FDmpio.c \
H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDstdio.c \
H5FDstream.c H5FL.c H5FO.c H5FP.c H5FPclient.c H5FPserver.c H5FS.c \
diff --git a/src/Makefile.in b/src/Makefile.in
index c92dabe..109c53f 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -88,25 +88,26 @@ am_libhdf5_la_OBJECTS = H5.lo H5A.lo H5AC.lo H5B.lo H5B2.lo \
H5BTdbg.lo H5BTtest.lo H5C.lo H5D.lo H5Dcontig.lo \
H5Dcompact.lo H5Defl.lo H5Dio.lo H5Distore.lo H5Dmpio.lo \
H5Dselect.lo H5Dtest.lo H5E.lo H5F.lo H5Fdbg.lo H5Fmount.lo \
- H5Fsuper.lo H5FD.lo H5FDcore.lo H5FDfamily.lo H5FDfphdf5.lo \
- H5FDlog.lo H5FDmpi.lo H5FDmpio.lo H5FDmpiposix.lo H5FDmulti.lo \
- H5FDsec2.lo H5FDstdio.lo H5FDstream.lo H5FL.lo H5FO.lo H5FP.lo \
- H5FPclient.lo H5FPserver.lo H5FS.lo H5G.lo H5Gent.lo \
- H5Gnode.lo H5Gstab.lo H5HG.lo H5HGdbg.lo H5HL.lo H5HLdbg.lo \
- H5HP.lo H5I.lo H5MF.lo H5MM.lo H5MP.lo H5MPtest.lo H5O.lo \
- H5Oattr.lo H5Obogus.lo H5Ocont.lo H5Odtype.lo H5Oefl.lo \
- H5Ofill.lo H5Olayout.lo H5Omtime.lo H5Oname.lo H5Onull.lo \
- H5Opline.lo H5Osdspace.lo H5Oshared.lo H5Ostab.lo H5P.lo \
- H5Pdcpl.lo H5Pdxpl.lo H5Pfapl.lo H5Pfcpl.lo H5Pocpl.lo \
- H5Ptest.lo H5R.lo H5RC.lo H5RS.lo H5S.lo H5Sall.lo H5Shyper.lo \
- H5Smpio.lo H5Snone.lo H5Spoint.lo H5Sselect.lo H5Stest.lo \
- H5SH.lo H5SHcache.lo H5SHdbg.lo H5SL.lo H5ST.lo H5T.lo \
- H5Tarray.lo H5Tbit.lo H5Tcommit.lo H5Tcompound.lo H5Tconv.lo \
- H5Tcset.lo H5Tenum.lo H5Tfields.lo H5Tfixed.lo H5Tfloat.lo \
- H5Tinit.lo H5Tnative.lo H5Toffset.lo H5Topaque.lo H5Torder.lo \
- H5Tpad.lo H5Tprecis.lo H5Tstrpad.lo H5Tvlen.lo H5TS.lo H5V.lo \
- H5Z.lo H5Zdeflate.lo H5Zfletcher32.lo H5Znbit.lo H5Zshuffle.lo \
- H5Zszip.lo H5Zscaleoffset.lo H5Ztrans.lo
+ H5Fsfile.lo H5Fsuper.lo H5FD.lo H5FDcore.lo H5FDfamily.lo \
+ H5FDfphdf5.lo H5FDlog.lo H5FDmpi.lo H5FDmpio.lo \
+ H5FDmpiposix.lo H5FDmulti.lo H5FDsec2.lo H5FDstdio.lo \
+ H5FDstream.lo H5FL.lo H5FO.lo H5FP.lo H5FPclient.lo \
+ H5FPserver.lo H5FS.lo H5G.lo H5Gent.lo H5Gnode.lo H5Gstab.lo \
+ H5HG.lo H5HGdbg.lo H5HL.lo H5HLdbg.lo H5HP.lo H5I.lo H5MF.lo \
+ H5MM.lo H5MP.lo H5MPtest.lo H5O.lo H5Oattr.lo H5Obogus.lo \
+ H5Ocont.lo H5Odtype.lo H5Oefl.lo H5Ofill.lo H5Olayout.lo \
+ H5Omtime.lo H5Oname.lo H5Onull.lo H5Opline.lo H5Osdspace.lo \
+ H5Oshared.lo H5Ostab.lo H5P.lo H5Pdcpl.lo H5Pdxpl.lo \
+ H5Pfapl.lo H5Pfcpl.lo H5Pocpl.lo H5Ptest.lo H5R.lo H5RC.lo \
+ H5RS.lo H5S.lo H5Sall.lo H5Shyper.lo H5Smpio.lo H5Snone.lo \
+ H5Spoint.lo H5Sselect.lo H5Stest.lo H5SH.lo H5SHcache.lo \
+ H5SHdbg.lo H5SL.lo H5ST.lo H5T.lo H5Tarray.lo H5Tbit.lo \
+ H5Tcommit.lo H5Tcompound.lo H5Tconv.lo H5Tcset.lo H5Tenum.lo \
+ H5Tfields.lo H5Tfixed.lo H5Tfloat.lo H5Tinit.lo H5Tnative.lo \
+ H5Toffset.lo H5Topaque.lo H5Torder.lo H5Tpad.lo H5Tprecis.lo \
+ H5Tstrpad.lo H5Tvlen.lo H5TS.lo H5V.lo H5Z.lo H5Zdeflate.lo \
+ H5Zfletcher32.lo H5Znbit.lo H5Zshuffle.lo H5Zszip.lo \
+ H5Zscaleoffset.lo H5Ztrans.lo
libhdf5_la_OBJECTS = $(am_libhdf5_la_OBJECTS)
PROGRAMS = $(noinst_PROGRAMS)
H5detect_SOURCES = H5detect.c
@@ -380,7 +381,7 @@ libhdf5_la_SOURCES = H5.c H5A.c H5AC.c H5B.c H5B2.c H5B2cache.c H5B2dbg.c \
H5Dcontig.c \
H5Dcompact.c \
H5Defl.c H5Dio.c H5Distore.c H5Dmpio.c H5Dselect.c H5Dtest.c H5E.c H5F.c \
- H5Fdbg.c H5Fmount.c H5Fsuper.c H5FD.c H5FDcore.c \
+ H5Fdbg.c H5Fmount.c H5Fsfile.c H5Fsuper.c H5FD.c H5FDcore.c \
H5FDfamily.c H5FDfphdf5.c H5FDlog.c H5FDmpi.c H5FDmpio.c \
H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDstdio.c \
H5FDstream.c H5FL.c H5FO.c H5FP.c H5FPclient.c H5FPserver.c H5FS.c \
@@ -583,6 +584,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FS.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fdbg.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fmount.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fsfile.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fsuper.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5G.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gent.Plo@am__quote@
diff --git a/test/mount.c b/test/mount.c
index 4813fa0..762c7b1 100644
--- a/test/mount.c
+++ b/test/mount.c
@@ -19,6 +19,7 @@
* Purpose: Tests file mounting.
*/
#include "h5test.h"
+#include "H5Fprivate.h" /* File access */
#include "H5Iprivate.h" /* IDs */
const char *FILENAME[] = {
@@ -26,6 +27,9 @@ const char *FILENAME[] = {
"mount_2",
"mount_3",
"mount_4",
+ "mount_5",
+ "mount_6",
+ "mount_7",
NULL
};
@@ -1004,6 +1008,8 @@ test_close(hid_t fapl)
/* Check that all file IDs have been closed */
if(H5I_nmembers(H5I_FILE) != 0)
TEST_ERROR
+ if(H5F_sfile_assert_num(0) != 0)
+ TEST_ERROR
/* Build the virtual file again */
if ((file1=H5Fopen(filename1, H5F_ACC_RDWR, fapl))<0 ||
@@ -1021,6 +1027,8 @@ test_close(hid_t fapl)
/* Check that all file IDs have been closed */
if(H5I_nmembers(H5I_FILE) != 0)
TEST_ERROR
+ if(H5F_sfile_assert_num(0) != 0)
+ TEST_ERROR
/* Shut down */
PASSED();
@@ -1665,6 +1673,8 @@ test_missing_unmount(hid_t fapl)
/* Check that all file IDs have been closed */
if(H5I_nmembers(H5I_FILE) != 0)
TEST_ERROR
+ if(H5F_sfile_assert_num(0) != 0)
+ TEST_ERROR
PASSED();
return 0;
@@ -1799,6 +1809,8 @@ test_hold_open_file(hid_t fapl)
/* Check that all file IDs have been closed */
if(H5I_nmembers(H5I_FILE) != 0)
TEST_ERROR
+ if(H5F_sfile_assert_num(0) != 0)
+ TEST_ERROR
PASSED();
return 0;
@@ -1954,6 +1966,8 @@ test_hold_open_group(hid_t fapl)
/* Check that all file IDs have been closed */
if(H5I_nmembers(H5I_FILE) != 0)
TEST_ERROR
+ if(H5F_sfile_assert_num(0) != 0)
+ TEST_ERROR
PASSED();
return 0;
@@ -2098,6 +2112,8 @@ test_fcdegree_same(hid_t fapl)
/* Check that all file IDs have been closed */
if(H5I_nmembers(H5I_FILE) != 0)
TEST_ERROR
+ if(H5F_sfile_assert_num(0) != 0)
+ TEST_ERROR
PASSED();
return 0;
@@ -2238,6 +2254,8 @@ test_fcdegree_semi(hid_t fapl)
/* Check that all file IDs have been closed */
if(H5I_nmembers(H5I_FILE) != 0)
TEST_ERROR
+ if(H5F_sfile_assert_num(0) != 0)
+ TEST_ERROR
PASSED();
return 0;
@@ -2374,6 +2392,8 @@ test_fcdegree_strong(hid_t fapl)
/* Check that all file IDs have been closed */
if(H5I_nmembers(H5I_FILE) != 0)
TEST_ERROR
+ if(H5F_sfile_assert_num(0) != 0)
+ TEST_ERROR
PASSED();
return 0;
@@ -2576,6 +2596,8 @@ test_acc_perm(hid_t fapl)
/* Check that all file IDs have been closed */
if(H5I_nmembers(H5I_FILE) != 0)
TEST_ERROR
+ if(H5F_sfile_assert_num(0) != 0)
+ TEST_ERROR
PASSED();
return 0;
@@ -2594,7 +2616,1183 @@ error:
} H5E_END_TRY;
return 1;
} /* end test_acc_perm() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_mult_mount
+ *
+ * Purpose: Test that the library correctly handles mounting a file
+ * multiple times at different locations in the parent file(s)
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Quincey Koziol
+ * Monday, July 25, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_mult_mount(hid_t fapl)
+{
+ hid_t fid1 = -1, fid2 = -1, fid3 = -1, fid3_2 = -1; /* File IDs */
+ hid_t gidA = -1, gidB = -1; /* Group IDs in file #1 */
+ hid_t gidM = -1, gidN = -1, gidAM = -1; /* Group IDs in file #2 */
+ hid_t gidS = -1, gidT = -1, gidU = -1, gidBS = -1, gidAMT = -1; /* Group IDs in file #3 */
+ char name[NAME_BUF_SIZE]; /* Buffer for filename retrieved */
+ char filename1[1024],
+ filename2[1024],
+ filename3[1024]; /* Name of files to mount */
+
+ TESTING("multiple mounts");
+
+ h5_fixname(FILENAME[0], fapl, filename1, sizeof filename1);
+ h5_fixname(FILENAME[1], fapl, filename2, sizeof filename2);
+ h5_fixname(FILENAME[2], fapl, filename3, sizeof filename3);
+
+ /* Create file #1 */
+ if((fid1 = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidA = H5Gcreate(fid1, "A", (size_t)0)) < 0)
+ TEST_ERROR
+
+ if(H5Gclose(gidA) < 0)
+ TEST_ERROR
+
+ if((gidB = H5Gcreate(fid1, "B", (size_t)0)) < 0)
+ TEST_ERROR
+
+ if(H5Gclose(gidB) < 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid1) < 0)
+ TEST_ERROR
+
+
+ /* Create file #2 */
+ if((fid2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidM = H5Gcreate(fid2, "M", (size_t)0)) < 0)
+ TEST_ERROR
+
+ if(H5Gclose(gidM) < 0)
+ TEST_ERROR
+
+ if((gidN = H5Gcreate(fid2, "N", (size_t)0)) < 0)
+ TEST_ERROR
+
+ if(H5Gclose(gidN) < 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+
+
+ /* Create file #3 */
+ if((fid3 = H5Fcreate(filename3, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidS = H5Gcreate(fid3, "S", (size_t)0)) < 0)
+ TEST_ERROR
+
+ if(H5Gclose(gidS) < 0)
+ TEST_ERROR
+
+ if((gidT = H5Gcreate(fid3, "T", (size_t)0)) < 0)
+ TEST_ERROR
+
+ if(H5Gclose(gidT) < 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid3) < 0)
+ TEST_ERROR
+
+
+ /* Re-open files and mount file #2 in file #1 */
+ if((fid1 = H5Fopen(filename1, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidA = H5Gopen(fid1, "A")) < 0)
+ TEST_ERROR
+
+ if((gidB = H5Gopen(fid1, "B")) < 0)
+ TEST_ERROR
+
+ if((fid2 = H5Fopen(filename2, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Mount files together */
+ if(H5Fmount(gidA, ".", fid2, H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Open group in mounted file */
+ if((gidAM = H5Gopen(fid1, "A/M")) < 0)
+ TEST_ERROR
+
+ /* Open file #3 again */
+ if((fid3 = H5Fopen(filename3, H5F_ACC_RDWR, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Mount file #3 on file #2 */
+ if(H5Fmount(gidAM, ".", fid3, H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Re-open file #3 */
+ if((fid3_2 = H5Freopen(fid3)) < 0)
+ TEST_ERROR
+
+ /* Mount file #3 on file #1 also */
+ if(H5Fmount(gidB, ".", fid3_2, H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Open object in file #3 through file #2 mount path */
+ if((gidAMT = H5Gopen(fid1, "A/M/T")) < 0)
+ TEST_ERROR
+
+ /* Check name */
+ if(H5Iget_name(gidAMT, name, (size_t)NAME_BUF_SIZE ) < 0)
+ TEST_ERROR
+ if(HDstrcmp(name, "/A/M/T"))
+ TEST_ERROR
+
+ /* Create object in file #3 */
+ if((gidU = H5Gcreate(gidAMT, "U", (size_t)0)) < 0)
+ TEST_ERROR
+
+ if(H5Gclose(gidU) < 0)
+ TEST_ERROR
+
+ /* Open object in file #3 through file #1 mount path */
+ if((gidBS = H5Gopen(fid1, "B/S")) < 0)
+ TEST_ERROR
+
+ /* Check name */
+ if(H5Iget_name(gidBS, name, (size_t)NAME_BUF_SIZE ) < 0)
+ TEST_ERROR
+ if(HDstrcmp(name, "/B/S"))
+ TEST_ERROR
+
+ /* Re-open object created in file #3 through file #1 mount path */
+ if((gidU = H5Gopen(gidBS, "/B/T/U")) < 0)
+ TEST_ERROR
+
+ if(H5Gclose(gidU) < 0)
+ TEST_ERROR
+
+ /* Close groups in file #3 */
+ if(H5Gclose(gidBS) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidAMT) < 0)
+ TEST_ERROR
+
+ /* Close group in file #2 */
+ if(H5Gclose(gidAM) < 0)
+ TEST_ERROR
+
+ /* Close groups in file #1 */
+ if(H5Gclose(gidA) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidB) < 0)
+ TEST_ERROR
+
+ /* Close file #3 IDs */
+ if(H5Fclose(fid3) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid3_2) < 0)
+ TEST_ERROR
+
+ /* Close file #2 */
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+
+ /* Close file #1 */
+ if(H5Fclose(fid1) < 0)
+ TEST_ERROR
+
+
+ /* Check that all file IDs have been closed */
+ if(H5I_nmembers(H5I_FILE) != 0)
+ TEST_ERROR
+ if(H5F_sfile_assert_num(0) != 0)
+ TEST_ERROR
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Gclose(gidU);
+ H5Gclose(gidAMT);
+ H5Gclose(gidT);
+ H5Gclose(gidBS);
+ H5Gclose(gidS);
+ H5Gclose(gidAM);
+ H5Gclose(gidN);
+ H5Gclose(gidM);
+ H5Gclose(gidB);
+ H5Gclose(gidA);
+ H5Fclose(fid3_2);
+ H5Fclose(fid3);
+ H5Fclose(fid2);
+ H5Fclose(fid1);
+ } H5E_END_TRY;
+ return 1;
+} /* end test_mult_mount() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_nested_survive
+ *
+ * Purpose: Test that the library correctly handles unmounting & remounting
+ * a file with files mounted on it
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Quincey Koziol
+ * Monday, July 25, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_nested_survive(hid_t fapl)
+{
+ hid_t fid1 = -1, fid2 = -1, fid3 = -1; /* File IDs */
+ hid_t gidA = -1; /* Group IDs in file #1 */
+ hid_t gidM = -1, gidAM = -1; /* Group IDs in file #2 */
+ hid_t gidS = -1, gidMS = -1, gidAMS = -1; /* Group IDs in file #3 */
+ char name[NAME_BUF_SIZE]; /* Buffer for filename retrieved */
+ ssize_t name_len; /* Filename length */
+ char filename1[1024],
+ filename2[1024],
+ filename3[1024]; /* Name of files to mount */
+ TESTING("nested mounts survive");
+
+ h5_fixname(FILENAME[0], fapl, filename1, sizeof filename1);
+ h5_fixname(FILENAME[1], fapl, filename2, sizeof filename2);
+ h5_fixname(FILENAME[2], fapl, filename3, sizeof filename3);
+
+ /* Create file #1 */
+ if((fid1 = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidA = H5Gcreate(fid1, "A", (size_t)0)) < 0)
+ TEST_ERROR
+
+ if(H5Gclose(gidA) < 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid1) < 0)
+ TEST_ERROR
+
+
+ /* Create file #2 */
+ if((fid2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidM = H5Gcreate(fid2, "M", (size_t)0)) < 0)
+ TEST_ERROR
+
+ if(H5Gclose(gidM) < 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+
+
+ /* Create file #3 */
+ if((fid3 = H5Fcreate(filename3, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidS = H5Gcreate(fid3, "S", (size_t)0)) < 0)
+ TEST_ERROR
+
+ if(H5Gclose(gidS) < 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid3) < 0)
+ TEST_ERROR
+
+
+ /* Re-open files and mount file #2 in file #1 */
+ if((fid1 = H5Fopen(filename1, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidA = H5Gopen(fid1, "A")) < 0)
+ TEST_ERROR
+
+ if((fid2 = H5Fopen(filename2, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Mount files together */
+ if(H5Fmount(gidA, ".", fid2, H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Open group in mounted file */
+ if((gidAM = H5Gopen(fid1, "A/M")) < 0)
+ TEST_ERROR
+
+ /* Open file #3 again */
+ if((fid3 = H5Fopen(filename3, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Mount file #3 on file #2 */
+ if(H5Fmount(gidAM, ".", fid3, H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Open object in file #3 through file #1 mount path */
+ if((gidAMS = H5Gopen(fid1, "A/M/S")) < 0)
+ TEST_ERROR
+
+ /* Close group in file #3 */
+ if(H5Gclose(gidAMS) < 0)
+ TEST_ERROR
+
+ /* Check name */
+ if((name_len = H5Iget_name(gidAM, name, (size_t)NAME_BUF_SIZE )) < 0)
+ TEST_ERROR
+ if(name_len == 0 || HDstrcmp(name, "/A/M"))
+ TEST_ERROR
+
+ /* Unmount file #2 from file #1 */
+ if(H5Funmount(gidA, ".") < 0)
+ TEST_ERROR
+
+ /* Check name (should be unavailable) */
+ if((name_len = H5Iget_name(gidAM, name, (size_t)NAME_BUF_SIZE )) < 0)
+ TEST_ERROR
+ if(name_len != 0)
+ TEST_ERROR
+
+ /* Open object in file #3 through file #1 mount path (should fail) */
+ H5E_BEGIN_TRY {
+ gidAMS = H5Gopen(fid1, "A/M/S");
+ } H5E_END_TRY;
+ if(gidAMS >= 0)
+ TEST_ERROR
+
+ /* Open object in file #3 through file #2 mount path */
+ if((gidMS = H5Gopen(fid2, "M/S")) < 0)
+ TEST_ERROR
+
+ /* Check name */
+ if(H5Iget_name(gidMS, name, (size_t)NAME_BUF_SIZE ) < 0)
+ TEST_ERROR
+ if(HDstrcmp(name, "/M/S"))
+ TEST_ERROR
+
+ /* Close group in file #3 */
+ if(H5Gclose(gidMS) < 0)
+ TEST_ERROR
+
+ /* Re-mount file #2 on file #1 */
+ if(H5Fmount(gidA, ".", fid2, H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Open object in file #3 through file #1 mount path again */
+ if((gidAMS = H5Gopen(fid1, "A/M/S")) < 0)
+ TEST_ERROR
+
+ /* Check name */
+ if(H5Iget_name(gidAMS, name, (size_t)NAME_BUF_SIZE ) < 0)
+ TEST_ERROR
+ if(HDstrcmp(name, "/A/M/S"))
+ TEST_ERROR
+
+ /* Close group in file #3 */
+ if(H5Gclose(gidAMS) < 0)
+ TEST_ERROR
+
+ /* Close group in file #2 */
+ if(H5Gclose(gidAM) < 0)
+ TEST_ERROR
+
+ /* Close groups in file #1 */
+ if(H5Gclose(gidA) < 0)
+ TEST_ERROR
+
+ /* Close file #3 IDs */
+ if(H5Fclose(fid3) < 0)
+ TEST_ERROR
+
+ /* Close file #2 */
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+
+ /* Close file #1 */
+ if(H5Fclose(fid1) < 0)
+ TEST_ERROR
+
+
+ /* Check that all file IDs have been closed */
+ if(H5I_nmembers(H5I_FILE) != 0)
+ TEST_ERROR
+ if(H5F_sfile_assert_num(0) != 0)
+ TEST_ERROR
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Gclose(gidAMS);
+ H5Gclose(gidMS);
+ H5Gclose(gidS);
+ H5Gclose(gidAM);
+ H5Gclose(gidM);
+ H5Gclose(gidA);
+ H5Fclose(fid3);
+ H5Fclose(fid2);
+ H5Fclose(fid1);
+ } H5E_END_TRY;
+ return 1;
+} /* end test_nested_survive() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_close_parent
+ *
+ * Purpose: Test that the library correctly handles holding open a child
+ * file while unmounting & closing parent.
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Quincey Koziol
+ * Monday, July 25, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_close_parent(hid_t fapl)
+{
+ hid_t fid1 = -1, fid2 = -1; /* File IDs */
+ hid_t gidA = -1; /* Group IDs in file #1 */
+ hid_t gidM = -1; /* Group IDs in file #2 */
+ char name[NAME_BUF_SIZE]; /* Buffer for filename retrieved */
+ ssize_t name_len; /* Filename length */
+ char filename1[1024],
+ filename2[1024]; /* Name of files to mount */
+
+ TESTING("close parent");
+
+ h5_fixname(FILENAME[0], fapl, filename1, sizeof filename1);
+ h5_fixname(FILENAME[1], fapl, filename2, sizeof filename2);
+
+ /* Create file #1 */
+ if((fid1 = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidA = H5Gcreate(fid1, "A", (size_t)0)) < 0)
+ TEST_ERROR
+
+ if(H5Gclose(gidA) < 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid1) < 0)
+ TEST_ERROR
+
+
+ /* Create file #2 */
+ if((fid2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidM = H5Gcreate(fid2, "M", (size_t)0)) < 0)
+ TEST_ERROR
+
+ if(H5Gclose(gidM) < 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+
+
+ /* Re-open files and mount file #2 in file #1 */
+ if((fid1 = H5Fopen(filename1, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidA = H5Gopen(fid1, "A")) < 0)
+ TEST_ERROR
+
+ if((fid2 = H5Fopen(filename2, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Mount files together */
+ if(H5Fmount(gidA, ".", fid2, H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Open group in mounted file */
+ if((gidM = H5Gopen(fid1, "A/M")) < 0)
+ TEST_ERROR
+
+ /* Close group in file #1 */
+ if(H5Gclose(gidA) < 0)
+ TEST_ERROR
+
+ /* Close files #1 & #2 */
+ if(H5Fclose(fid1) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+
+ /* Check that all file IDs have been closed */
+ if(H5I_nmembers(H5I_FILE) != 0)
+ TEST_ERROR
+
+ /* Both underlying shared files should be open still */
+ if(H5F_sfile_assert_num(2) != 0)
+ TEST_ERROR
+
+ /* Check the name of "M" is still defined */
+ if((name_len = H5Iget_name(gidM, name, (size_t)NAME_BUF_SIZE )) < 0)
+ TEST_ERROR
+ if(name_len == 0 || HDstrcmp(name, "/A/M"))
+ TEST_ERROR
+
+ /* Unmount file #2 from file #1, closing file #1 */
+ if(H5Funmount(gidM, "/A") < 0)
+ TEST_ERROR
+
+ /* Check the name of "M" is not defined any longer */
+ if((name_len = H5Iget_name(gidM, name, (size_t)NAME_BUF_SIZE )) < 0)
+ TEST_ERROR
+ if(name_len != 0)
+ TEST_ERROR
+
+ /* Just file #2's underlying shared file should be open still */
+ if(H5F_sfile_assert_num(1) != 0)
+ TEST_ERROR
+
+ /* Close group in file #2, letting file #2 close */
+ if(H5Gclose(gidM) < 0)
+ TEST_ERROR
+
+ /* All underlying shared file structs should be closed */
+ if(H5F_sfile_assert_num(0) != 0)
+ TEST_ERROR
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Gclose(gidM);
+ H5Gclose(gidA);
+ H5Fclose(fid2);
+ H5Fclose(fid1);
+ } H5E_END_TRY;
+ return 1;
+} /* end test_close_parent() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_cut_graph
+ *
+ * Purpose: Test that the library correctly handles cutting a graph of
+ * mounted files.
+ *
+ * Initial file mounting graph is built up to this:
+ *
+ * [1]
+ * / \
+ * / \
+ * "A" "B"
+ * / \
+ * / \
+ * [2] [3]
+ * / \ / \
+ * "D" "E" "H" "I"
+ * / \ / \
+ * [4] [5] [6] [7]
+ * | | | |
+ * "K" "M" "O" "Q"
+ *
+ * ( where [n] is a file in mounting hierarchy and "X" is a group
+ * in a file )
+ *
+ * Objects in file #5 & file #7 are opened and all other
+ * file & object IDs to the hierarchy are closed.
+ *
+ * Then file #2 is unmounted from file #1, which should make a
+ * small tree of files 2, 4 & 5 and a larger tree of files 1, 3,
+ * 6 & 7.
+ *
+ * Then, the object in file #5 is closed, which should release its
+ * small tree of files.
+ *
+ * Then, file #3 is unmounted from file #1, making it's tree
+ * only 3, 6 & 7.
+ *
+ * Then, the object in file #7 is closed, which should release the
+ * remaining small tree of files.
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Quincey Koziol
+ * Monday, July 25, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_cut_graph(hid_t fapl)
+{
+ hid_t fid1 = -1, fid2 = -1, fid3 = -1,
+ fid4 = -1, fid5 = -1, fid6 = -1, fid7 = -1; /* File IDs */
+ hid_t gidA = -1, gidB = -1; /* Group IDs in file #1 */
+ hid_t gidD = -1, gidE = -1; /* Group IDs in file #2 */
+ hid_t gidH = -1, gidI = -1; /* Group IDs in file #3 */
+ hid_t gidK = -1; /* Group IDs in file #4 */
+ hid_t gidM = -1; /* Group IDs in file #5 */
+ hid_t gidO = -1; /* Group IDs in file #6 */
+ hid_t gidQ = -1; /* Group IDs in file #7 */
+ char name[NAME_BUF_SIZE]; /* Buffer for filename retrieved */
+ ssize_t name_len; /* Filename length */
+ int obj_count; /* Number of objects open */
+ char filename1[NAME_BUF_SIZE],
+ filename2[NAME_BUF_SIZE],
+ filename3[NAME_BUF_SIZE],
+ filename4[NAME_BUF_SIZE],
+ filename5[NAME_BUF_SIZE],
+ filename6[NAME_BUF_SIZE],
+ filename7[NAME_BUF_SIZE]; /* Name of files to mount */
+
+ TESTING("cutting mount graph");
+
+ 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 filename3);
+ h5_fixname(FILENAME[4], fapl, filename5, sizeof filename3);
+ h5_fixname(FILENAME[5], fapl, filename6, sizeof filename3);
+ h5_fixname(FILENAME[6], fapl, filename7, sizeof filename3);
+
+ /* Create file #1 & it's groups */
+ if((fid1 = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidA = H5Gcreate(fid1, "A", (size_t)0)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidA) < 0)
+ TEST_ERROR
+
+ if((gidB = H5Gcreate(fid1, "B", (size_t)0)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidB) < 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid1) < 0)
+ TEST_ERROR
+
+
+ /* Create file #2 & it's groups */
+ if((fid2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidD = H5Gcreate(fid2, "D", (size_t)0)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidD) < 0)
+ TEST_ERROR
+
+ if((gidE = H5Gcreate(fid2, "E", (size_t)0)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidE) < 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+
+
+ /* Create file #3 & it's groups */
+ if((fid3 = H5Fcreate(filename3, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidH = H5Gcreate(fid3, "H", (size_t)0)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidH) < 0)
+ TEST_ERROR
+
+ if((gidI = H5Gcreate(fid3, "I", (size_t)0)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidI) < 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid3) < 0)
+ TEST_ERROR
+
+ /* Create file #4 & it's group */
+ if((fid4 = H5Fcreate(filename4, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidK = H5Gcreate(fid4, "K", (size_t)0)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidK) < 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid4) < 0)
+ TEST_ERROR
+
+ /* Create file #5 & it's group */
+ if((fid5 = H5Fcreate(filename5, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidM = H5Gcreate(fid5, "M", (size_t)0)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidM) < 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid5) < 0)
+ TEST_ERROR
+
+ /* Create file #6 & it's group */
+ if((fid6 = H5Fcreate(filename6, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidO = H5Gcreate(fid6, "O", (size_t)0)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidO) < 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid6) < 0)
+ TEST_ERROR
+
+ /* Create file #7 & it's group */
+ if((fid7 = H5Fcreate(filename7, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidQ = H5Gcreate(fid7, "Q", (size_t)0)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidQ) < 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid7) < 0)
+ TEST_ERROR
+
+
+ /* Re-open files and build mount hierarchy */
+ if((fid1 = H5Fopen(filename1, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Mount file #2 at /A */
+ if((fid2 = H5Fopen(filename2, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if(H5Fmount(fid1, "/A", fid2, H5P_DEFAULT) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+
+ /* Mount file #3 at /B */
+ if((fid3 = H5Fopen(filename3, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if(H5Fmount(fid1, "/B", fid3, H5P_DEFAULT) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid3) < 0)
+ TEST_ERROR
+
+ /* Mount file #4 at /A/D */
+ if((fid4 = H5Fopen(filename4, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if(H5Fmount(fid1, "/A/D", fid4, H5P_DEFAULT) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid4) < 0)
+ TEST_ERROR
+
+ /* Mount file #5 at /A/E */
+ if((fid5 = H5Fopen(filename5, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if(H5Fmount(fid1, "/A/E", fid5, H5P_DEFAULT) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid5) < 0)
+ TEST_ERROR
+
+ /* Mount file #6 at /B/H */
+ if((fid6 = H5Fopen(filename6, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if(H5Fmount(fid1, "/B/H", fid6, H5P_DEFAULT) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid6) < 0)
+ TEST_ERROR
+
+ /* Mount file #7 at /B/H */
+ if((fid7 = H5Fopen(filename7, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if(H5Fmount(fid1, "/B/I", fid7, H5P_DEFAULT) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid7) < 0)
+ TEST_ERROR
+
+ /* Open object in file #5 */
+ if((gidM = H5Gopen(fid1, "A/E/M")) < 0)
+ TEST_ERROR
+
+ /* Check name */
+ if((name_len = H5Iget_name(gidM, name, (size_t)NAME_BUF_SIZE )) < 0)
+ TEST_ERROR
+ if(name_len == 0 || HDstrcmp(name, "/A/E/M"))
+ TEST_ERROR
+
+ /* Open object in file #7 */
+ if((gidQ = H5Gopen(fid1, "B/I/Q")) < 0)
+ TEST_ERROR
+
+ /* Check name */
+ if((name_len = H5Iget_name(gidQ, name, (size_t)NAME_BUF_SIZE )) < 0)
+ TEST_ERROR
+ if(name_len == 0 || HDstrcmp(name, "/B/I/Q"))
+ TEST_ERROR
+
+ /* Close file #1 */
+ if(H5Fclose(fid1) < 0)
+ TEST_ERROR
+
+
+ /* Get a new file ID for file #5 */
+ if((fid5 = H5Iget_file_id(gidM)) < 0)
+ TEST_ERROR
+
+ /* Check the number of objects currently open */
+ if((obj_count = H5Fget_obj_count(fid5, H5F_OBJ_ALL)) < 0)
+ TEST_ERROR
+ if(obj_count != 2) /* one object and the file ID */
+ TEST_ERROR
+
+ /* Close ID on file #5 */
+ if(H5Fclose(fid5) < 0)
+ TEST_ERROR
+
+
+ /* Get a new file ID for file #7 */
+ if((fid7 = H5Iget_file_id(gidQ)) < 0)
+ TEST_ERROR
+
+ /* Check the number of objects currently open */
+ if((obj_count = H5Fget_obj_count(fid7, H5F_OBJ_ALL)) < 0)
+ TEST_ERROR
+ if(obj_count != 2) /* one object and the file ID */
+ TEST_ERROR
+
+ /* Close ID on file #7 */
+ if(H5Fclose(fid7) < 0)
+ TEST_ERROR
+
+ /* Check that all file IDs have been closed */
+ if(H5I_nmembers(H5I_FILE) != 0)
+ TEST_ERROR
+
+
+ /* Unmount file #2 from file #1, cutting the graph */
+ if(H5Funmount(gidM, "/A") < 0)
+ TEST_ERROR
+
+ /* Attempt to open an object in file #4, from file #1 */
+ H5E_BEGIN_TRY {
+ gidK = H5Gopen(gidQ, "/A/D/K");
+ } H5E_END_TRY;
+ if(gidK >= 0)
+ TEST_ERROR
+
+ /* Open object in file #4 from file #5 */
+ if((gidK = H5Gopen(gidM, "/D/K")) < 0)
+ TEST_ERROR
+
+ /* Check the name of "K" is correct */
+ if((name_len = H5Iget_name(gidK, name, (size_t)NAME_BUF_SIZE )) < 0)
+ TEST_ERROR
+ if(name_len == 0 || HDstrcmp(name, "/D/K"))
+ TEST_ERROR
+
+ if(H5Gclose(gidK) < 0)
+ TEST_ERROR
+
+ /* Attempt to open an object in file #6, from file #5 */
+ H5E_BEGIN_TRY {
+ gidO = H5Gopen(gidM, "/B/H/O");
+ } H5E_END_TRY;
+ if(gidO >= 0)
+ TEST_ERROR
+
+ /* Open object in file #6 from file #7 */
+ if((gidO = H5Gopen(gidQ, "/B/H/O")) < 0)
+ TEST_ERROR
+
+ /* Check the name of "O" is correct */
+ if((name_len = H5Iget_name(gidO, name, (size_t)NAME_BUF_SIZE )) < 0)
+ TEST_ERROR
+ if(name_len == 0 || HDstrcmp(name, "/B/H/O"))
+ TEST_ERROR
+
+ if(H5Gclose(gidO) < 0)
+ TEST_ERROR
+
+ /* Check the name of "M" is not defined any longer */
+ if((name_len = H5Iget_name(gidM, name, (size_t)NAME_BUF_SIZE )) < 0)
+ TEST_ERROR
+ if(name_len != 0)
+ TEST_ERROR
+
+ /* Check the name of "Q" is still defined */
+ if((name_len = H5Iget_name(gidQ, name, (size_t)NAME_BUF_SIZE )) < 0)
+ TEST_ERROR
+ if(name_len == 0 || HDstrcmp(name, "/B/I/Q"))
+ TEST_ERROR
+
+ /* Check that all seven underlying files are still opened */
+ if(H5F_sfile_assert_num(7) != 0)
+ TEST_ERROR
+
+ /* Close "M" in file #5, which should close files 2, 4 & 5 */
+ if(H5Gclose(gidM) < 0)
+ TEST_ERROR
+
+ /* Check that only four underlying files are still opened */
+ if(H5F_sfile_assert_num(4) != 0)
+ TEST_ERROR
+
+ /* Unmount file #3 from file #1, cutting the graph */
+ if(H5Funmount(gidQ, "/B") < 0)
+ TEST_ERROR
+
+ /* Check that only three underlying files are still opened */
+ /* (File #1 should close after being cut off from the graph) */
+ if(H5F_sfile_assert_num(3) != 0)
+ TEST_ERROR
+
+ /* Check the name of "Q" is not defined any longer */
+ if((name_len = H5Iget_name(gidQ, name, (size_t)NAME_BUF_SIZE )) < 0)
+ TEST_ERROR
+ if(name_len != 0)
+ TEST_ERROR
+
+ /* Open object in file #6 from file #7 */
+ if((gidO = H5Gopen(gidQ, "/H/O")) < 0)
+ TEST_ERROR
+
+ /* Check the name of "O" is correct */
+ if((name_len = H5Iget_name(gidO, name, (size_t)NAME_BUF_SIZE )) < 0)
+ TEST_ERROR
+ if(name_len == 0 || HDstrcmp(name, "/H/O"))
+ TEST_ERROR
+
+ if(H5Gclose(gidO) < 0)
+ TEST_ERROR
+
+ /* Close last object and let files 3, 6 & 7 close */
+ if(H5Gclose(gidQ) < 0)
+ TEST_ERROR
+
+ /* Verify that all underlying shared files have been closed now */
+ if(H5F_sfile_assert_num(0) != 0)
+ TEST_ERROR
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Gclose(gidQ);
+ H5Gclose(gidO);
+ H5Gclose(gidM);
+ H5Gclose(gidK);
+ H5Gclose(gidI);
+ H5Gclose(gidH);
+ H5Gclose(gidE);
+ H5Gclose(gidD);
+ H5Gclose(gidB);
+ H5Gclose(gidA);
+ H5Fclose(fid7);
+ H5Fclose(fid6);
+ H5Fclose(fid5);
+ H5Fclose(fid4);
+ H5Fclose(fid3);
+ H5Fclose(fid2);
+ H5Fclose(fid1);
+ } H5E_END_TRY;
+ return 1;
+} /* end test_cut_graph() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_symlink
+ *
+ * Purpose: Test that the library correctly handles symlinks across
+ * mounted files.
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Quincey Koziol
+ * Monday, July 25, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_symlink(hid_t fapl)
+{
+ hid_t fid1 = -1, fid2 = -1, fid3 = -1; /* File IDs */
+ hid_t gidA = -1, gidB = -1; /* Group IDs in file #1 */
+ hid_t gidD = -1, gidE = -1; /* Group IDs in file #2 */
+ hid_t gidH = -1, gidI = -1; /* Group IDs in file #3 */
+ hid_t gidL = -1; /* Group IDs through soft link to file #3 */
+ char name[NAME_BUF_SIZE]; /* Buffer for filename retrieved */
+ ssize_t name_len; /* Filename length */
+ char filename1[NAME_BUF_SIZE],
+ filename2[NAME_BUF_SIZE],
+ filename3[NAME_BUF_SIZE]; /* Name of files to mount */
+
+ TESTING("symlinks");
+
+ h5_fixname(FILENAME[0], fapl, filename1, sizeof filename1);
+ h5_fixname(FILENAME[1], fapl, filename2, sizeof filename2);
+ h5_fixname(FILENAME[2], fapl, filename3, sizeof filename3);
+
+ /* Create file #1 & it's groups */
+ if((fid1 = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidA = H5Gcreate(fid1, "A", (size_t)0)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidA) < 0)
+ TEST_ERROR
+
+ if((gidB = H5Gcreate(fid1, "B", (size_t)0)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidB) < 0)
+ TEST_ERROR
+
+ /* Create soft link to mounted object */
+ if(H5Glink(fid1, H5G_LINK_SOFT, "./A/D/H", "L") < 0) /* Soft link */
+ TEST_ERROR
+
+ if(H5Fclose(fid1) < 0)
+ TEST_ERROR
+
+
+ /* Create file #2 & it's groups */
+ if((fid2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidD = H5Gcreate(fid2, "D", (size_t)0)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidD) < 0)
+ TEST_ERROR
+
+ if((gidE = H5Gcreate(fid2, "E", (size_t)0)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidE) < 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+
+
+ /* Create file #3 & it's groups */
+ if((fid3 = H5Fcreate(filename3, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ if((gidH = H5Gcreate(fid3, "H", (size_t)0)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidH) < 0)
+ TEST_ERROR
+
+ if((gidI = H5Gcreate(fid3, "I", (size_t)0)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidI) < 0)
+ TEST_ERROR
+
+ if(H5Fclose(fid3) < 0)
+ TEST_ERROR
+
+
+ /* Re-open files and build mount hierarchy */
+ if((fid1 = H5Fopen(filename1, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ /* Mount file #2 at /A */
+ if((fid2 = H5Fopen(filename2, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if(H5Fmount(fid1, "/A", fid2, H5P_DEFAULT) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+
+ /* Attempt to open an object in file #3 (should fail) */
+ H5E_BEGIN_TRY {
+ gidL = H5Gopen(fid1, "L");
+ } H5E_END_TRY;
+ if(gidL >= 0)
+ TEST_ERROR
+
+ /* Mount file #3 at /A/D */
+ if((fid3 = H5Fopen(filename3, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+ if(H5Fmount(fid1, "/A/D", fid3, H5P_DEFAULT) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid3) < 0)
+ TEST_ERROR
+
+ /* Open soft link to object in file #3 */
+ if((gidL = H5Gopen(fid1, "L")) < 0)
+ TEST_ERROR
+
+ /* Check the name of "L" is correct */
+ if((name_len = H5Iget_name(gidL, name, (size_t)NAME_BUF_SIZE )) < 0)
+ TEST_ERROR
+ if(name_len == 0 || HDstrcmp(name, "/L"))
+ TEST_ERROR
+
+ /* Close file #1 */
+ if(H5Fclose(fid1) < 0)
+ TEST_ERROR
+
+ /* Verify that all 3 underlying shared files are still open */
+ if(H5F_sfile_assert_num(3) != 0)
+ TEST_ERROR
+
+ /* Close object opened through soft link */
+ if(H5Gclose(gidL) < 0)
+ TEST_ERROR
+
+ /* Verify that all underlying shared files have been closed now */
+ if(H5F_sfile_assert_num(0) != 0)
+ TEST_ERROR
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Gclose(gidL);
+ H5Gclose(gidI);
+ H5Gclose(gidH);
+ H5Gclose(gidE);
+ H5Gclose(gidD);
+ H5Gclose(gidB);
+ H5Gclose(gidA);
+ H5Fclose(fid3);
+ H5Fclose(fid2);
+ H5Fclose(fid1);
+ } H5E_END_TRY;
+ return 1;
+} /* end test_symlink() */
+
/*-------------------------------------------------------------------------
* Function: main
@@ -2644,6 +3842,11 @@ main(void)
nerrors += test_fcdegree_semi(fapl);
nerrors += test_fcdegree_strong(fapl);
nerrors += test_acc_perm(fapl);
+ nerrors += test_mult_mount(fapl);
+ nerrors += test_nested_survive(fapl);
+ nerrors += test_close_parent(fapl);
+ nerrors += test_cut_graph(fapl);
+ nerrors += test_symlink(fapl);
if (nerrors) goto error;
puts("All mount tests passed.");
diff --git a/test/tfile.c b/test/tfile.c
index 05a0765..ece7cdb 100644
--- a/test/tfile.c
+++ b/test/tfile.c
@@ -576,6 +576,10 @@ test_file_close(void)
ret = H5Fclose(fid2);
VERIFY(ret, FAIL, "H5Fclose");
+ /* Same check with H5Idec_ref() (should fail also) */
+ ret = H5Idec_ref(fid2);
+ VERIFY(ret, FAIL, "H5Idec_ref");
+
ret = H5Gclose(group_id3);
CHECK(ret, FAIL, "H5Gclose");
diff --git a/tools/h5diff/h5diff_common.c b/tools/h5diff/h5diff_common.c
index 51ba881..691fe8a 100644
--- a/tools/h5diff/h5diff_common.c
+++ b/tools/h5diff/h5diff_common.c
@@ -131,7 +131,7 @@ void parse_input(int argc, const char* argv[], const char** fname1, const char**
printf("<-n %s> is not a valid option\n", argv[i+1] );
usage();
}
- options->count = atoi(argv[i+1]);
+ options->count = atol(argv[i+1]);
i++; /* go to next */
}
else
diff --git a/tools/lib/h5diff.h b/tools/lib/h5diff.h
index cdaabaa..a307cb8 100644
--- a/tools/lib/h5diff.h
+++ b/tools/lib/h5diff.h
@@ -59,7 +59,7 @@ typedef struct {
int p; /* relative error to compare*/
double percent; /* relative error value */
int n; /* count, compare up to count */
- int count; /* count value */
+ hsize_t count; /* count value */
int err_stat; /* an error ocurred (1, error, 0, no error) */
int cmn_objs; /* do we have comparable objects */
int not_cmp; /* are the objects comparable */