summaryrefslogtreecommitdiffstats
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
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).
-rw-r--r--MANIFEST1
-rwxr-xr-xconfigure2
-rw-r--r--configure.in2
-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
-rw-r--r--test/.distdep16
-rw-r--r--test/Makefile.in16
-rw-r--r--test/shtype.c288
17 files changed, 510 insertions, 35 deletions
diff --git a/MANIFEST b/MANIFEST
index 9bfacae..58e473b 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -195,6 +195,7 @@
./test/hyperslab.c
./test/iopipe.c
./test/istore.c
+./test/shtype.c
./test/testhdf5.c
./test/testhdf5.h
./test/tfile.c
diff --git a/configure b/configure
index 4bb5a4d..371b3e2 100755
--- a/configure
+++ b/configure
@@ -2023,7 +2023,7 @@ fi
all_packages="ac,b,d,e,f,g,hg,hl,i,mf,mm,o,p,s,t,v"
if test X = "X$DEBUG_PKG" -o Xyes = "X$DEBUG_PKG"; then
- DEBUG_PKG=ac,b,d,e,f,g,hg,hl,i,mf,mm,p,s,t,v
+ DEBUG_PKG=ac,b,d,e,f,g,hg,i,mm,p,s,t,v
CPPFLAGS="$CPPFLAGS -UNDEBUG"
echo "$ac_t""default ($DEBUG_PKG)" 1>&6
elif test Xall = "X$DEBUG_PKG"; then
diff --git a/configure.in b/configure.in
index 8476064..53fff9d 100644
--- a/configure.in
+++ b/configure.in
@@ -204,7 +204,7 @@ AC_ARG_ENABLE(debug,
all_packages="ac,b,d,e,f,g,hg,hl,i,mf,mm,o,p,s,t,v"
if test X = "X$DEBUG_PKG" -o Xyes = "X$DEBUG_PKG"; then
- DEBUG_PKG=ac,b,d,e,f,g,hg,hl,i,mf,mm,p,s,t,v
+ DEBUG_PKG=ac,b,d,e,f,g,hg,i,mm,p,s,t,v
CPPFLAGS="$CPPFLAGS -UNDEBUG"
AC_MSG_RESULT(default ($DEBUG_PKG))
elif test Xall = "X$DEBUG_PKG"; then
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,
diff --git a/test/.distdep b/test/.distdep
index 895c967..5cbdc57 100644
--- a/test/.distdep
+++ b/test/.distdep
@@ -287,3 +287,19 @@ gheap.o: \
../src/H5Bpublic.h \
../src/H5HGprivate.h \
../src/H5HGpublic.h
+shtype.o: \
+ shtype.c \
+ ../src/hdf5.h \
+ ../src/H5public.h \
+ ../src/H5config.h \
+ ../src/H5ACpublic.h \
+ ../src/H5Bpublic.h \
+ ../src/H5Dpublic.h \
+ ../src/H5Ipublic.h \
+ ../src/H5Epublic.h \
+ ../src/H5Fpublic.h \
+ ../src/H5Gpublic.h \
+ ../src/H5HLpublic.h \
+ ../src/H5MFpublic.h \
+ ../src/H5MMpublic.h \
+ ../src/H5Opublic.h
diff --git a/test/Makefile.in b/test/Makefile.in
index 7017e9d..10e9135 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -12,8 +12,9 @@ CPPFLAGS=-I. -I../src @CPPFLAGS@
# These are our main targets. They should be listed in the order to be
# executed, generally most specific tests to least specific tests.
PROGS=testhdf5 gheap hyperslab istore dtypes dsets cmpd_dset extend external \
- iopipe
-TESTS=testhdf5 gheap hyperslab istore dtypes dsets cmpd_dset extend external
+ shtype iopipe
+TESTS=testhdf5 gheap hyperslab istore dtypes dsets cmpd_dset extend external \
+ shtype
TIMINGS=iopipe
# Temporary files
@@ -22,7 +23,8 @@ MOSTLYCLEAN=cmpd_dset.h5 dataset.h5 extend.h5 istore.h5 tfile1.h5 tfile2.h5 \
extern_1.h5 extern_2.h5 extern_3.h5 extern_1.raw extern_1b.raw \
extern_2.raw extern_2b.raw extern_3.raw extern_3b.raw \
extern_4.raw extern_4b.raw iopipe.raw iopipe.h5 gheap0.h5 \
- gheap1.h5 gheap2.h5 gheap3.h5 gheap4.h5
+ gheap1.h5 gheap2.h5 gheap3.h5 gheap4.h5 shtype0.h5 shtype1.h5 \
+ shtype2a.h5 shtype2b.h5 shtype3.h5
# Source and object files for programs... The PROG_SRC list contains all the
# source files and is used for things like dependencies, archiving, etc. The
@@ -30,7 +32,7 @@ MOSTLYCLEAN=cmpd_dset.h5 dataset.h5 extend.h5 istore.h5 tfile1.h5 tfile2.h5 \
# overlap with other tests.
PROG_SRC=testhdf5.c tfile.c theap.c tmeta.c tohdr.c tstab.c th5s.c dtypes.c \
hyperslab.c istore.c dsets.c cmpd_dset.c extend.c external.c \
- iopipe.c gheap.c
+ iopipe.c gheap.c shtype.c
PROG_OBJ=$(PROG_SRC:.c=.o)
TESTHDF5_SRC=testhdf5.c tfile.c theap.c tmeta.c tohdr.c tstab.c th5s.c
@@ -63,6 +65,9 @@ EXTERNAL_OBJ=$(EXTERNAL_SRC:.c=.o)
GRPTIME_SRC=grptime.c
GRPTIME_OBJ=$(GRPTIME_SRC:.c=.o)
+SHTYPE_SRC=shtype.c
+SHTYPE_OBJ=$(SHTYPE_SRC:.c=.o)
+
IOPIPE_SRC=iopipe.c
IOPIPE_OBJ=$(IOPIPE_SRC:.c=.o)
@@ -107,6 +112,9 @@ extend: $(EXTEND_OBJ) ../src/libhdf5.a
external: $(EXTERNAL_OBJ) ../src/libhdf5.a
$(CC) $(CFLAGS) -o $@ $(EXTERNAL_OBJ) ../src/libhdf5.a $(LIBS)
+shtype: $(SHTYPE_OBJ) ../src/libhdf5.a
+ $(CC) $(CFLAGS) -o $@ $(SHTYPE_OBJ) ../src/libhdf5.a $(LIBS)
+
iopipe: $(IOPIPE_OBJ) ../src/libhdf5.a
$(CC) $(CFLAGS) -o $@ $(IOPIPE_OBJ) ../src/libhdf5.a $(LIBS)
diff --git a/test/shtype.c b/test/shtype.c
new file mode 100644
index 0000000..e1b1aa9
--- /dev/null
+++ b/test/shtype.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 1998 NCSA
+ * All rights reserved.
+ *
+ * Programmer: Robb Matzke <matzke@llnl.gov>
+ * Thursday, April 2, 1998
+ *
+ * Purpose: Tests datasets with shared data types.
+ */
+#include <assert.h>
+#include <hdf5.h>
+
+
+/*-------------------------------------------------------------------------
+ * Function: display_error_cb
+ *
+ * Purpose: Displays the error stack after printing "*FAILED*".
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, March 4, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+display_error_cb (void *client_data)
+{
+ puts ("*FAILED*");
+ H5Eprint (stdout);
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_1
+ *
+ * Purpose: Create a shared data type and use it to create a dataset.
+ * Then query that dataset's type and use it to create a second
+ * dataset. Both datasets should share a single data type.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * Thursday, April 2, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_1 (void)
+{
+ hid_t f, d1, d2, s1, t1, t2;
+ size_t size[1] = {1};
+
+ printf ("%-70s", "...creating/quering datasets with shared type");
+ fflush (stdout);
+
+ f = H5Fcreate ("shtype1.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+ if (f<0) goto error;
+ if ((s1 = H5Screate_simple (1, size, size))<0) goto error;
+ if ((t1 = H5Tcopy (H5T_NATIVE_INT))<0) goto error;
+ if (H5Tshare (f, t1)<0) goto error;
+
+ /* Create the first dataset */
+ if ((d1 = H5Dcreate (f, "d1", t1, s1, H5P_DEFAULT))<0) goto error;
+ if (H5Dclose (d1)<0) goto error;
+
+ /* Get the type of the first dataset to use for the second */
+ if ((d1 = H5Dopen (f, "d1"))<0) goto error;
+ if ((t2 = H5Dget_type (d1))<0) goto error;
+ if (H5Dclose (d1)<0) goto error;
+
+ /* Create the second datatype */
+ if ((d2 = H5Dcreate (f, "d2", t2, s1, H5P_DEFAULT))<0) goto error;
+ if (H5Dclose (d2)<0) goto error;
+
+ if (H5Sclose (s1)<0) goto error;
+ if (H5Fclose (f)<0) goto error;
+
+ puts (" PASSED");
+ return 0;
+
+ error:
+ return -1;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_2
+ *
+ * Purpose: Create lots of datasets that have their own types, then
+ * create another file with lots of datasets that share a type
+ * and compare the file sizes.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * Thursday, April 2, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_2 (void)
+{
+ hid_t f1, f2, t1, t2, s1, d1, d2;
+ size_t size[1] = {1};
+ char buf[32];
+ int i;
+
+ printf ("%-70s", "...compare shared and unshared types");
+ fflush (stdout);
+
+ f1 = H5Fcreate ("shtype2a.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+ if (f1<0) goto error;
+ f2 = H5Fcreate ("shtype2b.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+ if (f2<0) goto error;
+ s1 = H5Screate_simple (1, size, size);
+ if (s1<0) goto error;
+
+ /* Create a large compound type */
+ if ((t1 = H5Tcreate (H5T_COMPOUND, 100))<0) goto error;
+ for (i=0; i<10; i++) {
+ sprintf (buf, "member-%d", i);
+ if (H5Tinsert (t1, buf, i*sizeof(int), H5T_NATIVE_INT)<0) goto error;
+ }
+
+ /* Create a shared version of that type for file #2 */
+ if ((t2 = H5Tcopy (t1))<0) goto error;
+ if (H5Tshare (f2, t2)<0) goto error;
+
+ /* Create the datasets */
+ for (i=0; i<1000; i++) {
+ sprintf (buf, "dset%04d", i);
+ d1 = H5Dcreate (f1, buf, t1, s1, H5P_DEFAULT);
+ if (d1<0) goto error;
+ if (H5Dclose (d1)<0) goto error;
+ d2 = H5Dcreate (f2, buf, t2, s1, H5P_DEFAULT);
+ if (d2<0) goto error;
+ if (H5Dclose (d2)<0) goto error;
+ }
+
+ /* Close things */
+ if (H5Sclose (s1)<0) goto error;
+ if (H5Tclose (t1)<0) goto error;
+ if (H5Tclose (t2)<0) goto error;
+ if (H5Fclose (f1)<0) goto error;
+ if (H5Fclose (f2)<0) goto error;
+
+ puts (" PASSED");
+ return 0;
+
+ error:
+ return -1;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_3
+ *
+ * Purpose: Tries to create a shared type in a read-only file.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * Friday, April 3, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_3 (void)
+{
+ hid_t f1, s1, t1, d1;
+ size_t size[1] = {1};
+ herr_t status, (*ef)(void*)=NULL;
+ void *ed = NULL;
+
+ printf ("%-70s", "...shared types and read-only files");
+ fflush (stdout);
+
+ /*
+ * Create the file first since we can't create a file for read-only
+ * access. Add a dataset with a shared type. Then close it and open it
+ * for read-only. The shared type causes a global heap to be allocated.
+ */
+ f1 = H5Fcreate ("shtype3.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+ if (f1<0) goto error;
+ if ((s1 = H5Screate_simple (1, size, size))<0) goto error;
+ if ((t1 = H5Tcopy (H5T_NATIVE_INT))<0) goto error;
+ if (H5Tshare (f1, t1)<0) goto error;
+ if ((d1 = H5Dcreate (f1, "d1", t1, s1, H5P_DEFAULT))<0) goto error;
+ if (H5Sclose (s1)<0) goto error;
+ if (H5Dclose (d1)<0) goto error;
+ if (H5Fclose (f1)<0) goto error;
+ f1 = H5Fopen ("shtype3.h5", H5F_ACC_RDONLY, H5P_DEFAULT);
+ if (f1<0) goto error;
+ assert (0==H5Tis_shared (f1, t1));
+
+ /*
+ * Create a shared data type. We know that H5MF_alloc() will fail on a
+ * read-only file so there's not much point in trying to create a global
+ * heap. But what happens if we modify a global heap in the cache? So
+ * lets try to get a collection loaded into memory by reading the shared
+ * type. Then creating another shared type will just upate memory unless
+ * an error is correctly detected.
+ */
+ if ((d1 = H5Dopen (f1, "d1"))<0) goto error;
+ if (H5Dclose (d1)<0) goto error;
+ if (H5Eget_auto (&ef, &ed)<0) goto error;
+ if (H5Eset_auto (NULL, NULL)<0) goto error;
+ status = H5Tshare (f1, t1);
+ if (H5Eset_auto (ef, ed)<0) goto error;
+ if (status>=0) {
+ puts ("*FAILED*");
+ puts (" H5Tshare() should have failed but didn't.");
+ goto error;
+ }
+
+ /* Close the file */
+ if (H5Fclose (f1)<0) goto error;
+
+ puts (" PASSED");
+ return 0;
+
+ error:
+ return -1;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: main
+ *
+ * Purpose:
+ *
+ * Return: Success:
+ *
+ * Failure:
+ *
+ * Programmer: Robb Matzke
+ * Thursday, April 2, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+main (void)
+{
+ int nerrors = 0;
+ hid_t f1, g1;
+
+ /* Make sure diagnostics get emitted before we start doing real stuff */
+ f1 = H5Fcreate ("shtype0.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+ g1 = H5Gcreate (f1, "howdy", 0);
+ H5Gclose (g1);
+ H5Fclose (f1);
+
+ /* Set the error handler */
+ H5Eset_auto (display_error_cb, NULL);
+
+ /* Run the tests */
+ nerrors += test_1()<0 ? 1 : 0;
+ nerrors += test_2()<0 ? 1 : 0;
+ nerrors += test_3()<0 ? 1 : 0;
+
+ /* Report results */
+ if (nerrors) {
+ puts ("*** Shared data type test(s) failed ***");
+ } else {
+ puts ("All shared data type tests passed.");
+ }
+ return nerrors ? 1 : 0;
+}