summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/H5AC.c2
-rw-r--r--src/H5F.c71
-rw-r--r--src/H5HG.c13
-rw-r--r--src/H5HL.c14
-rw-r--r--src/H5I.c7
-rw-r--r--src/H5Iprivate.h2
-rw-r--r--src/H5MF.c5
-rw-r--r--src/H5O.c12
-rw-r--r--src/H5T.c92
-rw-r--r--src/H5Tprivate.h1
-rw-r--r--src/H5Tpublic.h1
11 files changed, 191 insertions, 29 deletions
diff --git a/src/H5AC.c b/src/H5AC.c
index 9813af7..41e9a28 100644
--- a/src/H5AC.c
+++ b/src/H5AC.c
@@ -399,7 +399,7 @@ H5AC_flush(H5F_t *f, const H5AC_class_t *type, const haddr_t *addr,
if (status < 0) {
map = H5MM_xfree(map);
HRETURN_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL,
- "can't flush cache");
+ "unable to flush cache");
}
cache->diagnostics[slot->type->id].nflushes++;
if (destroy)
diff --git a/src/H5F.c b/src/H5F.c
index f29eec7..ae9254c 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -44,6 +44,7 @@ static char RcsId[] = "@(#)$Revision$";
#include <H5Gprivate.h> /*symbol tables */
#include <H5MMprivate.h> /*core memory management */
#include <H5Pprivate.h> /*property lists */
+#include <H5Tprivate.h> /*data types */
#include <ctype.h>
#include <sys/types.h>
@@ -97,7 +98,7 @@ static void H5F_term_interface(void);
/* PRIVATE PROTOTYPES */
static H5F_t *H5F_new(H5F_file_t *shared);
-static H5F_t *H5F_dest(H5F_t *f);
+static herr_t H5F_dest(H5F_t *f);
static herr_t H5F_flush(H5F_t *f, hbool_t invalidate);
static herr_t H5F_locate_signature(H5F_low_t *f_handle,
const H5F_access_t *access_parms,
@@ -342,7 +343,7 @@ H5Fget_access_template (hid_t file_id)
keys.
--------------------------------------------------------------------------*/
static intn
-H5F_compare_files(const void * _obj, const void * _key)
+H5F_compare_files(void * _obj, const void * _key)
{
const H5F_t *obj = (const H5F_t *) _obj;
const H5F_search_t *key = (const H5F_search_t *) _key;
@@ -510,16 +511,14 @@ H5F_new(H5F_file_t *shared)
/*-------------------------------------------------------------------------
* Function: H5F_dest
*
- * Purpose: Destroys a file structure. This function does not flush
- * the cache or anything else; it only frees memory associated
- * with the file struct. The shared info for the file is freed
+ * Purpose: Destroys a file structure. This function flushes the cache
+ * but doesn't do any other cleanup other than freeing memory
+ * for the file struct. The shared info for the file is freed
* only when its reference count reaches zero.
*
- * Errors:
- *
- * Return: Success: NULL
+ * Return: Success: SUCCEED
*
- * Failure: NULL
+ * Failure: FAIL
*
* Programmer: Robb Matzke
* matzke@llnl.gov
@@ -529,22 +528,28 @@ H5F_new(H5F_file_t *shared)
*
*-------------------------------------------------------------------------
*/
-static H5F_t *
+static herr_t
H5F_dest(H5F_t *f)
{
- FUNC_ENTER(H5F_dest, NULL);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER(H5F_dest, FAIL);
if (f) {
if (0 == --(f->shared->nrefs)) {
/* Do not close the root group since we didn't count it */
- H5AC_dest(f);
+ if (H5AC_dest(f)) {
+ HERROR (H5E_FILE, H5E_CANTINIT, "problems closing file");
+ ret_value = FAIL; /*but keep going*/
+ }
f->shared = H5MM_xfree(f->shared);
}
f->name = H5MM_xfree(f->name);
H5MM_xfree(f);
}
- FUNC_LEAVE(NULL);
+ FUNC_LEAVE(ret_value);
}
+
/*-------------------------------------------------------------------------
* Function: H5F_open
@@ -1242,7 +1247,7 @@ H5F_flush(H5F_t *f, hbool_t invalidate)
/* flush (and invalidate) the entire cache */
if (H5AC_flush(f, NULL, 0, invalidate) < 0) {
- HRETURN_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "can't flush cache");
+ HRETURN_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache");
}
/* encode the file boot block */
@@ -1312,8 +1317,9 @@ H5F_close(H5F_t *f)
while (H5G_pop(f)>=0) /*void*/;
/* Flush the boot block and caches */
- if (H5F_flush(f, TRUE) < 0) {
- HRETURN_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "can't flush cache");
+ if (H5F_flush(f, FALSE) < 0) {
+ HRETURN_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL,
+ "unable to flush cache");
}
/*
@@ -1336,14 +1342,31 @@ H5F_close(H5F_t *f)
fprintf(stderr, "H5F: H5F_close: operation completed\n");
#endif
}
+
+ /* Invalidate shared data types since they depend on the H5F_t pointer */
+ H5I_search (H5_DATATYPE, H5T_invalidate_cb, f);
- /* Dump debugging info */
- if (f->intent & H5F_ACC_DEBUG) H5AC_debug(f);
+ /*
+ * If this is the last reference to the shared part of the file then
+ * close it also.
+ */
+ if (1==f->shared->nrefs) {
+ /* Flush again just to be safe, but this time clean up the cache */
+ if (H5F_flush (f, TRUE)<0) {
+ HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL,
+ "unable to flush cache");
+ }
- /* Close files and release resources */
- H5F_low_close(f->shared->lf, &(f->shared->access_parms));
- f = H5F_dest(f);
+ /* Dump debugging info */
+ if (f->intent & H5F_ACC_DEBUG) H5AC_debug(f);
+ /* Close files and release resources */
+ H5F_low_close(f->shared->lf, &(f->shared->access_parms));
+ }
+ if (H5F_dest(f)<0) {
+ HRETURN_ERROR (H5E_FILE, H5E_CANTINIT, FAIL,
+ "problems closing file");
+ }
FUNC_LEAVE(SUCCEED);
}
@@ -1400,8 +1423,10 @@ H5Fclose(hid_t fid)
* Decrement reference count on atom. When it reaches zero the file will
* be closed.
*/
- H5I_dec_ref (fid);
-
+ if (H5I_dec_ref (fid)<0) {
+ HGOTO_ERROR (H5E_ATOM, H5E_CANTINIT, FAIL, "problems closing file");
+ }
+
done:
FUNC_LEAVE(ret_value < 0 ? FAIL : SUCCEED);
}
diff --git a/src/H5HG.c b/src/H5HG.c
index 9af1074..176c687 100644
--- a/src/H5HG.c
+++ b/src/H5HG.c
@@ -488,6 +488,11 @@ H5HG_insert (H5F_t *f, size_t size, void *obj, H5HG_t *hobj/*out*/)
assert (0==size || obj);
assert (hobj);
+ if (0==(f->intent & H5F_ACC_RDWR)) {
+ HRETURN_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL,
+ "no write intent on file");
+ }
+
/* Find a large enough collection on the CWFS list */
need = size + H5HG_SIZEOF_OBJHDR (f);
for (cwfsno=0; cwfsno<f->shared->ncwfs; cwfsno++) {
@@ -692,6 +697,10 @@ H5HG_link (H5F_t *f, H5HG_t *hobj, intn adjust)
/* Check args */
assert (f);
assert (hobj);
+ if (0==(f->intent & H5F_ACC_RDWR)) {
+ HRETURN_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL,
+ "no write intent on file");
+ }
/* Load the heap */
if (NULL==(heap=H5AC_find (f, H5AC_GHEAP, &(hobj->addr), NULL, NULL))) {
@@ -743,6 +752,10 @@ H5HG_remove (H5F_t *f, H5HG_t *hobj)
/* Check args */
assert (f);
assert (hobj);
+ if (0==(f->intent & H5F_ACC_RDWR)) {
+ HRETURN_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL,
+ "no write intent on file");
+ }
/* Load the heap */
if (NULL==(heap=H5AC_find (f, H5AC_GHEAP, &(hobj->addr), NULL, NULL))) {
diff --git a/src/H5HL.c b/src/H5HL.c
index 8c141a0..d7f83c0 100644
--- a/src/H5HL.c
+++ b/src/H5HL.c
@@ -537,6 +537,10 @@ H5HL_insert(H5F_t *f, const haddr_t *addr, size_t buf_size, const void *buf)
assert(addr && H5F_addr_defined(addr));
assert(buf_size > 0);
assert(buf);
+ if (0==(f->intent & H5F_ACC_RDWR)) {
+ HRETURN_ERROR (H5E_HEAP, H5E_WRITEERROR, (size_t)(-1),
+ "no write intent on file");
+ }
if (NULL == (heap = H5AC_find(f, H5AC_LHEAP, addr, NULL, NULL))) {
HRETURN_ERROR(H5E_HEAP, H5E_CANTLOAD, (size_t)(-1),
@@ -686,6 +690,10 @@ H5HL_write(H5F_t *f, const haddr_t *addr, size_t offset, size_t size,
assert(addr && H5F_addr_defined(addr));
assert(buf);
assert (offset==H5HL_ALIGN (offset));
+ if (0==(f->intent & H5F_ACC_RDWR)) {
+ HRETURN_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL,
+ "no write intent on file");
+ }
if (NULL == (heap = H5AC_find(f, H5AC_LHEAP, addr, NULL, NULL))) {
HRETURN_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL,
@@ -741,8 +749,12 @@ H5HL_remove(H5F_t *f, const haddr_t *addr, size_t offset, size_t size)
assert(addr && H5F_addr_defined(addr));
assert(size > 0);
assert (offset==H5HL_ALIGN (offset));
- size = H5HL_ALIGN (size);
+ if (0==(f->intent & H5F_ACC_RDWR)) {
+ HRETURN_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL,
+ "no write intent on file");
+ }
+ size = H5HL_ALIGN (size);
if (NULL == (heap = H5AC_find(f, H5AC_LHEAP, addr, NULL, NULL))) {
HRETURN_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL,
"unable to load heap");
diff --git a/src/H5I.c b/src/H5I.c
index 028108f..b958a3e 100644
--- a/src/H5I.c
+++ b/src/H5I.c
@@ -640,7 +640,12 @@ H5I_dec_ref(hid_t id)
* call the user's 'free' function for the atom's information,
* otherwise just leak memory.
*/
- if (grp_ptr->free_func) (grp_ptr->free_func)(obj);
+ if (grp_ptr->free_func) {
+ if ((grp_ptr->free_func)(obj)<0) {
+ HRETURN_ERROR (H5E_ATOM, H5E_CANTINIT, FAIL,
+ "unable to free atom");
+ }
+ }
}
ret_value = SUCCEED;
}
diff --git a/src/H5Iprivate.h b/src/H5Iprivate.h
index c339390..45f9e85 100644
--- a/src/H5Iprivate.h
+++ b/src/H5Iprivate.h
@@ -89,7 +89,7 @@ typedef struct {
} H5I_id_group_t;
/* Type of the function to compare objects & keys */
-typedef intn (*H5I_search_func_t) (const void * obj, const void * key);
+typedef intn (*H5I_search_func_t) (void * obj, const void * key);
/* Private Functions in H5I.c */
intn H5I_init_group (H5I_group_t grp, intn hash_size, uintn reserved,
diff --git a/src/H5MF.c b/src/H5MF.c
index 46d5bae..a50d98f 100644
--- a/src/H5MF.c
+++ b/src/H5MF.c
@@ -63,6 +63,11 @@ H5MF_alloc(H5F_t *f, intn op, size_t size, haddr_t *addr /*out */ )
assert(size > 0);
assert(addr);
+ /* Fail if we don't have write access */
+ if (0==(f->intent & H5F_ACC_RDWR)) {
+ HRETURN_ERROR (H5E_RESOURCE, H5E_CANTINIT, FAIL, "file is read-only");
+ }
+
/*
* Eventually we'll maintain a free list(s) and try to satisfy requests
* from there. But for now we just allocate more memory from the end of
diff --git a/src/H5O.c b/src/H5O.c
index 87f29fc..e7a51fa 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -694,6 +694,10 @@ H5O_link(H5G_entry_t *ent, intn adjust)
assert(ent);
assert(ent->file);
assert(H5F_addr_defined(&(ent->header)));
+ if (0==(ent->file->intent & H5F_ACC_RDWR)) {
+ HGOTO_ERROR (H5E_OHDR, H5E_WRITEERROR, FAIL,
+ "no write intent on file");
+ }
/* get header */
if (NULL == (oh = H5AC_protect(ent->file, H5AC_OHDR, &(ent->header),
@@ -967,6 +971,10 @@ H5O_modify(H5G_entry_t *ent, const H5O_class_t *type, intn overwrite,
assert(type);
assert(mesg);
assert (0==(flags & ~H5O_FLAG_BITS));
+ if (0==(ent->file->intent & H5F_ACC_RDWR)) {
+ HGOTO_ERROR (H5E_OHDR, H5E_WRITEERROR, FAIL,
+ "no write intent on file");
+ }
if (NULL == (oh = H5AC_protect(ent->file, H5AC_OHDR, &(ent->header),
NULL, NULL))) {
@@ -1102,6 +1110,10 @@ H5O_remove(H5G_entry_t *ent, const H5O_class_t *type, intn sequence)
assert(ent->file);
assert(H5F_addr_defined(&(ent->header)));
assert(type);
+ if (0==(ent->file->intent & H5F_ACC_RDWR)) {
+ HRETURN_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL,
+ "no write intent on file");
+ }
/* load the object header */
if (NULL == (oh = H5AC_protect(ent->file, H5AC_OHDR, &(ent->header),
diff --git a/src/H5T.c b/src/H5T.c
index be72fa6..c45003d 100644
--- a/src/H5T.c
+++ b/src/H5T.c
@@ -12,8 +12,9 @@ static char RcsId[] = "@(#)$Revision$";
#define H5T_PACKAGE /*suppress error about including H5Tpkg */
#include <H5private.h> /*generic functions */
-#include <H5Iprivate.h> /*ID functions */
-#include <H5Eprivate.h> /*error handling */
+#include <H5Iprivate.h> /*ID functions */
+#include <H5Eprivate.h> /*error handling */
+#include <H5Gprivate.h> /*groups */
#include <H5HGprivate.h> /*global heap */
#include <H5MMprivate.h> /*memory management */
#include <H5Sprivate.h> /*data space */
@@ -2206,6 +2207,50 @@ H5Tshare (hid_t loc_id, hid_t type_id)
/*-------------------------------------------------------------------------
+ * Function: H5Tis_shared
+ *
+ * Purpose: Determines if a data type is shared in the specified file.
+ * The TYPE_ID is the type in question and LOC_ID is a file id
+ * or group id (a group id is used only to identify the file).
+ *
+ * Return: Success: TRUE or FALSE
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Friday, April 3, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+hbool_t
+H5Tis_shared (hid_t loc_id, hid_t type_id)
+{
+ H5G_t *loc = NULL;
+ H5T_t *dt = NULL;
+ hbool_t ret_value = FAIL;
+
+ FUNC_ENTER (H5Tis_shared, FAIL);
+
+ /* Check arguments */
+ if (NULL==(loc=H5G_loc (loc_id))) {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location");
+ }
+ if (H5_DATATYPE!=H5I_group (type_id) ||
+ NULL==(dt=H5I_object (type_id))) {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+ }
+
+ /* Is it sharable */
+ ret_value = (H5HG_defined (&(dt->sh_heap)) &&
+ dt->sh_file->shared==H5G_fileof(loc)->shared) ? TRUE : FALSE;
+
+ FUNC_LEAVE (ret_value);
+}
+
+
+/*-------------------------------------------------------------------------
* Function: H5Tregister_hard
*
* Purpose: Register a hard conversion function for a data type
@@ -2771,6 +2816,49 @@ H5T_unshare (H5T_t *dt)
/*-------------------------------------------------------------------------
+ * Function: H5T_invalidate_cb
+ *
+ * Purpose: This is a callback function for H5I_search(). When a file is
+ * closed we scan through the data type list and invalidate
+ * shared info for all types that have sharing enabled for the
+ * specified file. This insures that we don't having dangling
+ * pointers from data types to files. We have to do this with
+ * data types but not datasets because a dataset_id always
+ * corresponds to an open object header which prevents the file
+ * from closing in the first place, but a data type can exist
+ * independent of a file and doesn't have an object header.
+ *
+ * Return: Success: 0, this function never returns a non-zero
+ * value because that would terminate
+ * H5I_search().
+ *
+ * Failure: 0
+ *
+ * Programmer: Robb Matzke
+ * Friday, April 3, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+intn
+H5T_invalidate_cb (void *obj, const void *call_data)
+{
+ H5T_t *dt = (H5T_t *)obj;
+ const H5F_t *f = (const H5F_t*)call_data; /*used only for comparison*/
+
+ FUNC_ENTER (H5T_invalidate, 0);
+
+ if (H5HG_defined (&(dt->sh_heap)) && dt->sh_file->shared==f->shared) {
+ H5T_unshare (dt);
+ H5E_clear ();
+ }
+
+ FUNC_LEAVE (0);
+}
+
+
+/*-------------------------------------------------------------------------
* Function: H5T_is_atomic
*
* Purpose: Determines if a data type is an atomic type.
diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h
index 27d27f3..ea80fcb 100644
--- a/src/H5Tprivate.h
+++ b/src/H5Tprivate.h
@@ -34,6 +34,7 @@ H5T_t *H5T_copy (const H5T_t *old_dt);
herr_t H5T_close (H5T_t *dt);
herr_t H5T_share (H5F_t *f, H5T_t *dt);
herr_t H5T_unshare (H5T_t *dt);
+intn H5T_invalidate_cb (void *obj, const void *call_data);
size_t H5T_get_size (const H5T_t *dt);
intn H5T_cmp (const H5T_t *dt1, const H5T_t *dt2);
hbool_t H5T_is_atomic (const H5T_t *dt);
diff --git a/src/H5Tpublic.h b/src/H5Tpublic.h
index f362cdf..60a0311 100644
--- a/src/H5Tpublic.h
+++ b/src/H5Tpublic.h
@@ -185,6 +185,7 @@ herr_t H5Tclose (hid_t type_id);
hbool_t H5Tequal (hid_t type1_id, hid_t type2_id);
herr_t H5Tlock (hid_t type_id);
herr_t H5Tshare (hid_t location_id, hid_t type_id);
+hbool_t H5Tis_shared (hid_t location_id, hid_t type_id);
/* Operations defined on compound data types */
herr_t H5Tinsert (hid_t parent_id, const char *name, off_t offset,