summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/H5F.c168
-rw-r--r--src/H5Fpkg.h1
-rw-r--r--src/H5Fprivate.h8
-rw-r--r--src/H5Fsuper.c4
-rw-r--r--src/H5Gloc.c70
-rw-r--r--src/H5Gpkg.h1
-rw-r--r--src/H5I.c12
-rw-r--r--src/H5Lexternal.c158
-rw-r--r--src/H5O.c71
-rw-r--r--src/H5Oprivate.h1
-rw-r--r--test/links.c89
11 files changed, 398 insertions, 185 deletions
diff --git a/src/H5F.c b/src/H5F.c
index fd8dc24..bd51aa9 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -972,27 +972,6 @@ done:
* matzke@llnl.gov
* Jul 18 1997
*
- * Modifications:
- *
- * Robb Matzke, 1998-10-14
- * Nothing happens unless the reference count for the H5F_t goes to
- * zero. The reference counts are decremented here.
- *
- * Robb Matzke, 1999-02-19
- * More careful about decrementing reference counts so they don't go
- * negative or wrap around to some huge value. Nothing happens if a
- * reference count is already zero.
- *
- * Robb Matzke, 2000-10-31
- * H5FL_FREE() aborts if called with a null pointer (unlike the
- * original H5MM_free()).
- *
- * Pedro Vicente, <pvn@ncsa.uiuc.edu> 18 Sep 2002
- * Added `id to name' support.
- *
- * James Laird, 2007-1-29
- * H5F_dest now frees superblock extension oloc.
- *
*-------------------------------------------------------------------------
*/
static herr_t
@@ -1004,6 +983,7 @@ H5F_dest(H5F_t *f, hid_t dxpl_id)
/* Sanity check */
HDassert(f);
+ HDassert(f->shared);
if(1 == f->shared->nrefs) {
/* Flush at this point since the file will be closed */
@@ -1085,6 +1065,7 @@ H5F_dest(H5F_t *f, hid_t dxpl_id)
f->mtab.nalloc = 0;
if(H5FO_top_dest(f) < 0)
HDONE_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "problems closing file")
+ f->shared = NULL;
H5FL_FREE(H5F_t, f);
FUNC_LEAVE_NOAPI(ret_value)
@@ -1566,9 +1547,8 @@ H5Fopen(const char *filename, unsigned flags, hid_t fapl_id)
new_file->file_id = ret_value;
done:
- if(ret_value < 0 && new_file)
- if(H5F_close(new_file) < 0)
- HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "problems closing file")
+ if(ret_value < 0 && new_file && H5F_try_close(new_file) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "problems closing file")
FUNC_LEAVE_API(ret_value)
} /* end H5Fopen() */
@@ -1674,50 +1654,6 @@ done:
* matzke@llnl.gov
* Aug 29 1997
*
- * Modifications:
- * rky 1998-08-28
- * Only p0 writes metadata to disk.
- *
- * Robb Matzke, 1998-10-16
- * Added the `scope' argument to indicate what should be
- * flushed. If the value is H5F_SCOPE_GLOBAL then the entire
- * virtual file is flushed; a value of H5F_SCOPE_LOCAL means
- * that only the specified file is flushed. A value of
- * H5F_SCOPE_DOWN means flush the specified file and all
- * children.
- *
- * Robb Matzke, 1999-08-02
- * If ALLOC_ONLY is non-zero then all this function does is
- * allocate space for the userblock and superblock. Also
- * rewritten to use the virtual file layer.
- *
- * Robb Matzke, 1999-08-16
- * The driver information block is encoded and either allocated
- * or written to disk.
- *
- * Raymond Lu, 2001-10-14
- * Changed to new generic property list.
- *
- * Quincey Koziol, 2002-05-20
- * Added 'closing' parameter
- *
- * Quincey Koziol, 2002-06-05
- * Added boot block & driver info block checksumming, to avoid
- * writing them out when they haven't changed.
- *
- * Quincey Koziol, 2002-06-06
- * Return the remainders of the metadata & "small data" blocks to
- * the free list of blocks for the file.
- *
- * Bill Wendling, 2003-03-18
- * Modified the flags being passed in to be one flag instead
- * of several.
- *
- * John Mainzer, 2005-01-07
- * H5AC (and H5C) now have their own system of flags. Hence
- * we must now translate between the H5F_FLUSH flags and the
- * H5AC flags. Added code to handle this detail.
- *
*-------------------------------------------------------------------------
*/
static herr_t
@@ -1835,19 +1771,6 @@ done:
* Programmer: Robb Matzke
* Tuesday, September 23, 1997
*
- * Modifications:
- * Robb Matzke, 1998-10-14
- * Nothing happens unless the H5F_t reference count is one (the
- * file is flushed anyway). The reference count is decremented
- * by H5F_dest().
- *
- * Robb Matzke, 1999-08-02
- * Modified to use the virtual file layer.
- *
- * Bill Wendling, 2003-03-18
- * Modified H5F_flush call to take one flag instead of
- * several Boolean flags.
- *
*-------------------------------------------------------------------------
*/
static herr_t
@@ -1919,6 +1842,7 @@ H5F_try_close(H5F_t *f)
/* Sanity check */
HDassert(f);
+ HDassert(f->shared);
/* Check if this file is already in the process of closing */
if(f->closing)
@@ -2903,6 +2827,88 @@ H5F_use_latest_format(const H5F_t *f)
/*-------------------------------------------------------------------------
+ * Function: H5F_get_fc_degree
+ *
+ * Purpose: Retrieve the 'file close degree' for the file.
+ *
+ * Return: Success: Non-negative, the 'file close degree'
+ *
+ * Failure: (can't happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Mar 5 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+H5F_close_degree_t
+H5F_get_fc_degree(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_fc_degree)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->fc_degree)
+} /* end H5F_get_fc_degree() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_incr_nopen_objs
+ *
+ * Purpose: Increment the number of open objects for a file.
+ *
+ * Return: Success: The number of open objects, after the increment
+ *
+ * Failure: (can't happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Mar 6 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+H5F_incr_nopen_objs(H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_incr_nopen_objs)
+
+ HDassert(f);
+
+ FUNC_LEAVE_NOAPI(++f->nopen_objs)
+} /* end H5F_incr_nopen_objs() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_decr_nopen_objs
+ *
+ * Purpose: Decrement the number of open objects for a file.
+ *
+ * Return: Success: The number of open objects, after the decrement
+ *
+ * Failure: (can't happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Mar 6 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+H5F_decr_nopen_objs(H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_decr_nopen_objs)
+
+ HDassert(f);
+
+ FUNC_LEAVE_NOAPI(--f->nopen_objs)
+} /* end H5F_decr_nopen_objs() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5F_block_read
*
* Purpose: Reads some data from a file/server/etc into a buffer.
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index e8df026..616bb81 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -162,7 +162,6 @@ H5FL_EXTERN(H5F_file_t);
/* General routines */
H5_DLL herr_t H5F_init(void);
-H5_DLL herr_t H5F_try_close(H5F_t *f);
H5_DLL haddr_t H5F_locate_signature(H5FD_t *file, hid_t dxpl_id);
/* File mount related routines */
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index 1084ab5..264218f 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -255,7 +255,7 @@ typedef struct H5F_t H5F_t;
#define H5F_RDCC_NBYTES(F) ((F)->shared->rdcc_nbytes)
#define H5F_RDCC_W0(F) ((F)->shared->rdcc_w0)
/* Check for file driver feature enabled */
-#define H5F_HAS_FEATURE(F,FL) ((F)->shared->lf->feature_flags&(FL))
+#define H5F_HAS_FEATURE(F,FL) ((F)->shared->lf->feature_flags & (FL))
/* B-tree node raw page */
#define H5F_GRP_BTREE_SHARED(F) ((F)->shared->grp_btree_shared)
/* Base address of file */
@@ -265,6 +265,7 @@ typedef struct H5F_t H5F_t;
#define H5F_GC_REF(F) ((F)->shared->gc_ref)
#define H5F_USE_LATEST_FORMAT(F) ((F)->shared->latest_format)
#define H5F_INTENT(F) ((F)->intent)
+#define H5F_GET_FC_DEGREE(F) ((F)->shared->fc_degree)
#else /* H5F_PACKAGE */
#define H5F_FCPL(F) (H5F_get_fcpl(F))
#define H5F_SIZEOF_ADDR(F) (H5F_sizeof_addr(F))
@@ -281,6 +282,7 @@ typedef struct H5F_t H5F_t;
#define H5F_GC_REF(F) (H5F_gc_ref(F))
#define H5F_USE_LATEST_FORMAT(F) (H5F_use_latest_format(F))
#define H5F_INTENT(F) (H5F_get_intent(F))
+#define H5F_GET_FC_DEGREE(F) (H5F_get_fc_degree(F))
#endif /* H5F_PACKAGE */
@@ -405,6 +407,7 @@ struct H5RC_t;
/* Private functions */
H5_DLL H5F_t *H5F_open(const char *name, unsigned flags, hid_t fcpl_id,
hid_t fapl_id, hid_t dxpl_id);
+H5_DLL herr_t H5F_try_close(H5F_t *f);
/* Functions than retrieve values from the file struct */
H5_DLL hid_t H5F_get_driver_id(const H5F_t *f);
@@ -421,6 +424,8 @@ H5_DLL int H5F_mpi_get_rank(const H5F_t *f);
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 */
+H5_DLL unsigned H5F_incr_nopen_objs(H5F_t *f);
+H5_DLL unsigned H5F_decr_nopen_objs(H5F_t *f);
/* Functions than check file mounting information */
H5_DLL hbool_t H5F_is_mount(const H5F_t *file);
@@ -440,6 +445,7 @@ H5_DLL struct H5RC_t *H5F_grp_btree_shared(const H5F_t *f);
H5_DLL size_t H5F_sieve_buf_size(const H5F_t *f);
H5_DLL unsigned H5F_gc_ref(const H5F_t *f);
H5_DLL hbool_t H5F_use_latest_format(const H5F_t *f);
+H5_DLL H5F_close_degree_t H5F_get_fc_degree(const H5F_t *f);
/* Functions that operate on blocks of bytes wrt super block */
H5_DLL herr_t H5F_block_read(const H5F_t *f, H5FD_mem_t type, haddr_t addr,
diff --git a/src/H5Fsuper.c b/src/H5Fsuper.c
index 547502d..0df22bb 100644
--- a/src/H5Fsuper.c
+++ b/src/H5Fsuper.c
@@ -613,8 +613,8 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
H5O_msg_reset(H5O_DRVINFO_ID, &drvinfo);
} /* end else */
- /* Close the extension. Bump the version number to avoid closing the
- * file (since this will be the only open object).
+ /* Close the extension. Twiddle the number of open objects to avoid
+ * closing the file (since this will be the only open object).
*/
f->nopen_objs++;
if(H5O_close(&ext_loc) < 0)
diff --git a/src/H5Gloc.c b/src/H5Gloc.c
index d447d20..247f185 100644
--- a/src/H5Gloc.c
+++ b/src/H5Gloc.c
@@ -133,23 +133,13 @@ H5G_loc(hid_t loc_id, H5G_loc_t *loc)
{
H5F_t *f;
+ /* Get the file struct */
if(NULL == (f = H5I_object(loc_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file ID")
- if(NULL == (loc->oloc = H5G_oloc(H5G_rootof(f))))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location for root group")
- if(NULL == (loc->path = H5G_nameof(H5G_rootof(f))))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get path for root group")
-
- /* Patch up root group's object location to reflect this file */
- /* (Since the root group info is only stored once for files which
- * share an underlying low-level file)
- */
- /* (but only for non-mounted files) */
- if(!H5F_is_mount(f))
- {
- loc->oloc->file = f;
- loc->oloc->holding_file = FALSE;
- }
+
+ /* Construct a group location for root group of the file */
+ if(H5G_loc_root(f, loc) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "unable to create location for file")
} /* end case */
break;
@@ -230,6 +220,56 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5G_loc_root
+ *
+ * Purpose: Construct a "group location" for the root group of a file
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Mar 5 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_loc_root(H5F_t *f, H5G_loc_t *loc)
+{
+ H5G_t *root_grp; /* Pointer to root group's info */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5G_loc_root, FAIL)
+
+ HDassert(f);
+ HDassert(loc);
+
+ /* Retrieve the root group for the file */
+ root_grp = H5G_rootof(f);
+ HDassert(root_grp);
+
+ /* Build the group location for the root group */
+ if(NULL == (loc->oloc = H5G_oloc(root_grp)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location for root group")
+ if(NULL == (loc->path = H5G_nameof(root_grp)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get path for root group")
+
+ /* Patch up root group's object location to reflect this file */
+ /* (Since the root group info is only stored once for files which
+ * share an underlying low-level file)
+ */
+ /* (but only for non-mounted files) */
+ if(!H5F_is_mount(f)) {
+ loc->oloc->file = f;
+ loc->oloc->holding_file = FALSE;
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_loc_root() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5G_loc_copy
*
* Purpose: Copy over information for a location
diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h
index b02155d..181d5e4 100644
--- a/src/H5Gpkg.h
+++ b/src/H5Gpkg.h
@@ -533,6 +533,7 @@ H5_DLL H5RS_str_t *H5G_build_fullpath_refstr_str(H5RS_str_t *path_r, const char
/*
* These functions operate on group "locations"
*/
+H5_DLL herr_t H5G_loc_root(H5F_t *f, H5G_loc_t *loc);
H5_DLL herr_t H5G_loc_copy(H5G_loc_t *dst, const H5G_loc_t *src, H5_copy_depth_t depth);
H5_DLL herr_t H5G_loc_insert(H5G_loc_t *grp_loc, const char *name,
H5G_loc_t *obj_loc, hid_t dxpl_id);
diff --git a/src/H5I.c b/src/H5I.c
index 771e45d..195bb38 100644
--- a/src/H5I.c
+++ b/src/H5I.c
@@ -2077,15 +2077,11 @@ H5I_get_file_id(hid_t obj_id)
if(H5I_inc_ref(ret_value) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTSET, FAIL, "incrementing file ID failed")
}
- else if(type == H5I_DATATYPE) {
+ else if(type == H5I_DATATYPE || type == H5I_GROUP || type == H5I_DATASET || type == H5I_ATTR) {
if(H5G_loc(obj_id, &loc) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "not a named datatype")
- ret_value = H5F_get_id(loc.oloc->file);
- }
- else if(type == H5I_GROUP || type == H5I_DATASET || type == H5I_ATTR) {
- if(H5G_loc(obj_id, &loc) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't get symbol table info")
- ret_value = H5F_get_id(loc.oloc->file);
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't get object location")
+ if((ret_value = H5F_get_id(loc.oloc->file)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't get file ID")
}
else
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid object ID")
diff --git a/src/H5Lexternal.c b/src/H5Lexternal.c
index 5357f6a..074cb47 100644
--- a/src/H5Lexternal.c
+++ b/src/H5Lexternal.c
@@ -13,19 +13,20 @@
* access to either file, you may request a copy from help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-#define H5L_PACKAGE /*suppress error about including H5Lpkg */
#define H5G_PACKAGE /*suppress error about including H5Gpkg */
+#define H5L_PACKAGE /*suppress error about including H5Lpkg */
/* Interface initialization */
#define H5_INTERFACE_INIT_FUNC H5L_init_extern_interface
#include "H5private.h" /* Generic Functions */
-#include "H5Lpkg.h" /* Links */
#include "H5Eprivate.h" /* Error handling */
+#include "H5Gpkg.h" /* Groups */
+#include "H5Iprivate.h" /* IDs */
+#include "H5Lpkg.h" /* Links */
#include "H5MMprivate.h" /* Memory management */
#include "H5Opublic.h" /* File objects */
-#include "H5Ppublic.h" /* Property lists */
-#include "H5Gpkg.h" /* Groups */
+#include "H5Pprivate.h" /* Property lists */
static hid_t H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group,
void * udata, size_t UNUSED udata_size, hid_t lapl_id);
@@ -92,74 +93,117 @@ static hid_t
H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group,
void * udata, size_t UNUSED udata_size, hid_t lapl_id)
{
- hid_t fid;
- char *file_name;
- char *obj_name;
- ssize_t prefix_len; /* External link prefix length */
- size_t fname_len;
- hbool_t fname_alloc = FALSE;
- unsigned intent;
- hid_t fapl_id;
- hid_t ret_value = -1;
-
- file_name = (char *) udata;
+ H5P_genplist_t *plist; /* Property list pointer */
+ char *my_prefix; /* Library's copy of the prefix */
+ H5G_loc_t root_loc; /* Location of root group in external file */
+ H5G_loc_t loc; /* Location of object */
+ H5F_t *ext_file = NULL; /* File struct for external file */
+ char *file_name = (char *)udata;
+ char *obj_name;
+ size_t fname_len;
+ hbool_t fname_alloc = FALSE;
+ unsigned intent;
+ hid_t fapl_id = -1;
+ hid_t ret_value = -1;
+
+ FUNC_ENTER_NOAPI(H5L_extern_traverse, FAIL)
+
+ /* Sanity checks */
+ HDassert(file_name);
+
+ /* Gather some information from the external link's user data */
fname_len = HDstrlen(file_name);
- obj_name = ((char *) udata) + fname_len + 1;
+ obj_name = ((char *)udata) + fname_len + 1;
+
+ /* Get the plist structure */
+ if(NULL == (plist = H5P_object_verify(lapl_id, H5P_LINK_ACCESS)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+
+ /* Get the current prefix */
+ if(H5P_get(plist, H5L_ACS_ELINK_PREFIX_NAME, &my_prefix) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get external link prefix")
- /* See if the external link prefix property is set */
- if((prefix_len = H5Pget_elink_prefix(lapl_id, NULL, (size_t)0)) < 0)
- goto error;
+ /* Check for prefix being set, if so, prepend it to the filename */
+ if(my_prefix) {
+ size_t prefix_len = HDstrlen(my_prefix);
- /* If so, prepend it to the filename */
- if(prefix_len > 0)
- {
/* Allocate a buffer to hold the filename plus prefix */
- file_name = H5MM_malloc(prefix_len + fname_len + 1);
+ if(NULL == (file_name = H5MM_malloc(prefix_len + fname_len + 1)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate filename buffer")
fname_alloc = TRUE;
/* Copy the prefix into the buffer */
- if(H5Pget_elink_prefix(lapl_id, file_name, (size_t)(prefix_len + 1)) < 0)
- goto error;
+ HDstrcpy(file_name, my_prefix);
/* Add the external link's filename to the prefix supplied */
HDstrcat(file_name, udata);
- }
+ } /* end if */
+
+ /* Get the location for the group holding the external link */
+ if(H5G_loc(cur_group, &loc) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't get object location")
/* Whatever access properties and intent the user used on the old file,
* use the same ones to open the new file. If this is a bad default,
* users can override this callback using H5Lregister.
*/
- if((fid = H5Iget_file_id(cur_group)) < 0)
- goto error;
- if(H5Fget_intent(fid, &intent) < 0)
- goto error;
- if((fapl_id = H5Fget_access_plist(fid)) < 0)
- goto error;
- if(H5Fclose(fid) < 0)
- goto error;
-
- if((fid = H5Fopen(file_name, intent, fapl_id)) < 0)
- goto error;
-
- ret_value = H5Oopen(fid, obj_name, lapl_id); /* If this fails, our return value will be negative. */
- if(H5Pclose(fapl_id) < 0)
- goto error;
- if(H5Fclose(fid) < 0)
- goto error;
+ intent = H5F_INTENT(loc.oloc->file);
+ if((fapl_id = H5F_get_access_plist(loc.oloc->file)) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't get file access property list")
+
+ /* Check for non-"weak" file close degree for parent file */
+ if(H5F_GET_FC_DEGREE(loc.oloc->file) != H5F_CLOSE_WEAK) {
+ H5P_genplist_t *fa_plist; /* Property list pointer */
+ H5F_close_degree_t fc_degree = H5F_CLOSE_WEAK; /* File close degree */
+
+ /* Get the plist structure */
+ if(NULL == (fa_plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+
+ /* Set file close degree for new file to "weak" */
+ if(H5P_set(fa_plist, H5F_ACS_CLOSE_DEGREE_NAME, &fc_degree) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file close degree")
+ } /* end if */
+
+ /* Open the external file */
+ /* (extra work with file intent to mask off inappropriate flags) */
+ if(NULL == (ext_file = H5F_open(file_name, ((intent & H5F_ACC_RDWR) ? H5F_ACC_RDWR : H5F_ACC_RDONLY), H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id)))
+ HGOTO_ERROR(H5E_LINK, H5E_CANTOPENFILE, FAIL, "unable to open external file")
+
+ /* 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((ret_value = H5O_open_name(&root_loc, obj_name, lapl_id)) < 0) {
+ H5F_decr_nopen_objs(ext_file);
+ 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;
- /* Free file_name if it's been allocated */
- if(fname_alloc)
- H5MM_xfree(file_name);
-
- return ret_value;
+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)
+ HDONE_ERROR(H5E_LINK, H5E_CANTCLOSEFILE, FAIL, "problem closing external file")
-error:
/* Free file_name if it's been allocated */
if(fname_alloc)
H5MM_xfree(file_name);
- return -1;
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5L_extern_traverse() */
/*-------------------------------------------------------------------------
@@ -183,18 +227,20 @@ static ssize_t
H5L_extern_query(const char UNUSED * link_name, void * udata,
size_t udata_size, void * buf /*out*/, size_t buf_size)
{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5L_extern_query)
+
/* If the buffer is NULL, skip writing anything in it and just return
* the size needed */
if(buf) {
if(udata_size < buf_size)
buf_size = udata_size;
- /* Copy the udata verbatim up to buf_size*/
+ /* Copy the udata verbatim up to buf_size */
HDmemcpy(buf, udata, buf_size);
- }
+ } /* end if */
- return udata_size;
-}
+ FUNC_LEAVE_NOAPI(udata_size)
+} /* end H5L_extern_query() */
/*-------------------------------------------------------------------------
@@ -254,7 +300,7 @@ H5Lcreate_external(const char *file_name, const char *obj_name,
done:
if(temp_name != NULL)
H5MM_free(temp_name);
- FUNC_LEAVE_API(ret_value);
+ FUNC_LEAVE_API(ret_value)
} /* end H5Lcreate_external() */
diff --git a/src/H5O.c b/src/H5O.c
index 874b4c8..ca740de 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -195,10 +195,6 @@ hid_t
H5Oopen(hid_t loc_id, const char *name, hid_t lapl_id)
{
H5G_loc_t loc;
- H5G_loc_t obj_loc; /* Location used to open group */
- H5G_name_t obj_path; /* Opened object group hier. path */
- H5O_loc_t obj_oloc; /* Opened object object location */
- hbool_t loc_found = FALSE; /* Entry at 'name' found */
hid_t ret_value = FAIL;
FUNC_ENTER_API(H5Oopen, FAIL)
@@ -210,25 +206,11 @@ H5Oopen(hid_t loc_id, const char *name, hid_t lapl_id)
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
- /* Set up opened group location to fill in */
- obj_loc.oloc = &obj_oloc;
- obj_loc.path = &obj_path;
- H5G_loc_reset(&obj_loc);
-
- /* Find the object's location */
- if(H5G_loc_find(&loc, name, &obj_loc/*out*/, lapl_id, H5AC_dxpl_id) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found")
- loc_found = TRUE;
-
/* Open the object */
- if((ret_value = H5O_open_by_loc(&obj_loc, H5AC_dxpl_id)) < 0)
+ if((ret_value = H5O_open_name(&loc, name, lapl_id)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open object")
done:
- if(ret_value < 0 && loc_found)
- if(H5G_loc_free(&obj_loc) < 0)
- HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't free location")
-
FUNC_LEAVE_API(ret_value)
} /* end H5Oopen() */
@@ -817,6 +799,57 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5O_open_name
+ *
+ * Purpose: Opens an object within an HDF5 file.
+ *
+ * Return: Success: An open object identifier
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * March 5 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5O_open_name(H5G_loc_t *loc, const char *name, hid_t lapl_id)
+{
+ H5G_loc_t obj_loc; /* Location used to open group */
+ H5G_name_t obj_path; /* Opened object group hier. path */
+ H5O_loc_t obj_oloc; /* Opened object object location */
+ hbool_t loc_found = FALSE; /* Entry at 'name' found */
+ hid_t ret_value = FAIL;
+
+ FUNC_ENTER_NOAPI(H5O_open_name, FAIL)
+
+ /* Check args */
+ HDassert(loc);
+ HDassert(name && *name);
+
+ /* Set up opened group location to fill in */
+ obj_loc.oloc = &obj_oloc;
+ obj_loc.path = &obj_path;
+ H5G_loc_reset(&obj_loc);
+
+ /* Find the object's location */
+ if(H5G_loc_find(loc, name, &obj_loc/*out*/, lapl_id, H5AC_dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found")
+ loc_found = TRUE;
+
+ /* Open the object */
+ if((ret_value = H5O_open_by_loc(&obj_loc, H5AC_dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open object")
+
+done:
+ if(ret_value < 0 && loc_found)
+ if(H5G_loc_free(&obj_loc) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't free location")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_open_name() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5O_open_by_loc
*
* Purpose: Opens an object and returns an ID given its group loction.
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index c08b97d..3fb2255 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -435,6 +435,7 @@ H5_DLL herr_t H5O_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr);
H5_DLL herr_t H5O_get_info(H5O_loc_t *oloc, H5O_info_t *oinfo, hid_t dxpl_id);
H5_DLL herr_t H5O_obj_type(const H5O_loc_t *loc, H5O_type_t *obj_type, hid_t dxpl_id);
H5_DLL herr_t H5O_get_create_plist(const H5O_loc_t *loc, hid_t dxpl_id, struct H5P_genplist_t *oc_plist);
+H5_DLL hid_t H5O_open_name(H5G_loc_t *loc, const char *name, hid_t lapl_id);
/* Object header message routines */
H5_DLL herr_t H5O_msg_create(const H5O_loc_t *loc, unsigned type_id, unsigned mesg_flags,
diff --git a/test/links.c b/test/links.c
index 6b7e5b2..813b232 100644
--- a/test/links.c
+++ b/test/links.c
@@ -2367,7 +2367,7 @@ external_link_toomany(hid_t fapl, hbool_t new_format)
} H5E_END_TRY;
if (gid >= 0) {
H5_FAILED();
- puts(" Should have failed for sequence of too many nested links.");
+ printf("%d: Should have failed for sequence of too many nested links.", __LINE__);
goto error;
}
@@ -3531,7 +3531,7 @@ error:
return -1;
}
-
+
/*-------------------------------------------------------------------------
* Function: ext_link_endian
*
@@ -3621,6 +3621,90 @@ error:
} H5E_END_TRY;
return -1;
}
+
+
+/*-------------------------------------------------------------------------
+ * Function: external_link_strong
+ *
+ * Purpose: Check that external links work properly when they opened in
+ * a file with "strong" file close degree.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Quincey Koziol
+ * Monday, March 5, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+external_link_strong(hid_t fapl, hbool_t new_format)
+{
+ hid_t my_fapl; /* File access property list */
+ hid_t fid1 = (-1), fid2 = (-1); /* File ID */
+ hid_t gid1 = (-1), gid2 = (-1); /* Group IDs */
+ char objname[NAME_BUF_SIZE]; /* Object name */
+ ssize_t name_len; /* Length of object name */
+ char filename1[NAME_BUF_SIZE],
+ filename2[NAME_BUF_SIZE];
+
+ if(new_format)
+ TESTING("that external files work with strong file close degree (w/new group format)")
+ else
+ TESTING("that external files work with strong file close degree")
+
+ /* Set up filenames */
+ h5_fixname(FILENAME[0], fapl, filename1, sizeof filename1);
+ h5_fixname(FILENAME[1], fapl, filename2, sizeof filename2);
+
+ /* Copy file access property list */
+ if((my_fapl = H5Pcopy(fapl)) < 0) TEST_ERROR
+
+ /* Set strong file close degree */
+ if(H5Pset_fclose_degree(my_fapl, H5F_CLOSE_STRONG) < 0) TEST_ERROR
+
+ /* Create a group at /A/B/C in first file */
+ if((fid1 = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0) TEST_ERROR
+ if((gid1 = H5Gcreate(fid1, "A", (size_t)0)) < 0) TEST_ERROR
+ if(H5Gclose(gid1) < 0) TEST_ERROR
+ if((gid1 = H5Gcreate(fid1, "A/B", (size_t)0)) < 0) TEST_ERROR
+ if(H5Gclose(gid1) < 0) TEST_ERROR
+ if((gid1 = H5Gcreate(fid1, "A/B/C", (size_t)0)) < 0) TEST_ERROR
+ if(H5Gclose(gid1) < 0) TEST_ERROR
+ if(H5Fclose(fid1) < 0) TEST_ERROR
+
+ /* Create an external link /W/X/DLINK in second file to <filename1>:/A/B/C */
+ if((fid2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR
+ if((gid2 = H5Gcreate(fid2, "/W", (size_t)0)) < 0) TEST_ERROR
+ if(H5Gclose(gid2) < 0) TEST_ERROR
+ if((gid2 = H5Gcreate(fid2, "/W/X", (size_t)0)) < 0) TEST_ERROR
+ if(H5Lcreate_external(filename1, "/A/B/C", gid2, "DLINK", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR
+ if(H5Gclose(gid2) < 0) TEST_ERROR
+ if(H5Fclose(fid2) < 0) TEST_ERROR
+
+ /* Access external link from file #1 */
+ if((fid2 = H5Fopen(filename2, H5F_ACC_RDONLY, fapl)) < 0) TEST_ERROR
+ if((gid2 = H5Gopen(fid2, "/W/X/DLINK")) < 0) TEST_ERROR
+ if((name_len = H5Iget_name(gid2, objname, (size_t)NAME_BUF_SIZE )) < 0) TEST_ERROR
+ if(HDstrcmp(objname, "/A/B/C")) TEST_ERROR
+ if(H5Gclose(gid2) < 0) TEST_ERROR
+ if(H5Fclose(fid2) < 0) TEST_ERROR
+
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Gclose(fapl);
+ H5Gclose(gid2);
+ H5Gclose(gid1);
+ H5Fclose(fid2);
+ H5Fclose(fid1);
+ } H5E_END_TRY;
+ return -1;
+} /* end external_link_strong() */
+
/*-------------------------------------------------------------------------
* Function: ud_hard_links
@@ -9552,6 +9636,7 @@ main(void)
nerrors += external_link_closing((new_format ? fapl2 : fapl), new_format) < 0 ? 1 : 0;
#endif /* H5_CANNOT_OPEN_TWICE */
nerrors += external_link_endian((new_format ? fapl2 : fapl), new_format) < 0 ? 1 : 0;
+ nerrors += external_link_strong((new_format ? fapl2 : fapl), new_format) < 0 ? 1 : 0;
/* These tests assume that external links are a form of UD links,
* so assume that everything that passed for external links