summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;
+}