summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRobb Matzke <matzke@llnl.gov>1998-04-03 21:11:05 (GMT)
committerRobb Matzke <matzke@llnl.gov>1998-04-03 21:11:05 (GMT)
commit92571bbe1d77c74ddefeeba6ac0b2097593c058d (patch)
tree610c3a65c2d3fa5dabfda39635770029bb734646 /src
parenta780cdd178f849afbc8cbb24e416eef733cbc9f2 (diff)
downloadhdf5-92571bbe1d77c74ddefeeba6ac0b2097593c058d.zip
hdf5-92571bbe1d77c74ddefeeba6ac0b2097593c058d.tar.gz
hdf5-92571bbe1d77c74ddefeeba6ac0b2097593c058d.tar.bz2
[svn-r336] Changes since 19980402
---------------------- ./MANIFEST ./test/Makefile.in ./test/shtype.c [NEW] Added some tests for shared data types. ./configure.in Removed MF and HL from the default debug list since. MF because it hasn't been implemented yet and HL because it produces lots of annoying messages about adjusting the size of local heaps. ./src/H5F.c ./src/H5T.c ./src/H5Tprivate.h Fixed a bug with opening the same file twice. The first close on the file_id incorrectly closed shared data structs. Closing a file now correctly unshares data types that might be pointing into that file. ./src/H5T.c ./src/H5Tpublic.h Added an H5Tis_shared(). The caller supplies a file and a data type and the function returns true if the data type is currently marked for sharing in that file. ./src/H5AC.c ./src/H5F.c ./src/H5HL.c ./src/H5HG.c ./src/H5MF.c ./src/H5O.c We now detect errors sooner when writing to a read-only file. In the past, the error might not show up until the cached item was flushed, and it was sometimes possible to not even get an error! ./src/H5I.c ./src/H5Iprivate.h If the search function fails then H5I_search() returns failure. Also, the first argument for the search function isn't const anymore because we might want the search to have side effects (like calling H5T_unshare() for all shared data types whose file just closed).
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,