diff options
-rw-r--r-- | MANIFEST | 1 | ||||
-rwxr-xr-x | configure | 2 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | src/H5AC.c | 2 | ||||
-rw-r--r-- | src/H5F.c | 71 | ||||
-rw-r--r-- | src/H5HG.c | 13 | ||||
-rw-r--r-- | src/H5HL.c | 14 | ||||
-rw-r--r-- | src/H5I.c | 7 | ||||
-rw-r--r-- | src/H5Iprivate.h | 2 | ||||
-rw-r--r-- | src/H5MF.c | 5 | ||||
-rw-r--r-- | src/H5O.c | 12 | ||||
-rw-r--r-- | src/H5T.c | 92 | ||||
-rw-r--r-- | src/H5Tprivate.h | 1 | ||||
-rw-r--r-- | src/H5Tpublic.h | 1 | ||||
-rw-r--r-- | test/.distdep | 16 | ||||
-rw-r--r-- | test/Makefile.in | 16 | ||||
-rw-r--r-- | test/shtype.c | 288 |
17 files changed, 510 insertions, 35 deletions
@@ -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 @@ -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 @@ -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) @@ -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); } @@ -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))) { @@ -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"); @@ -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, @@ -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 @@ -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), @@ -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; +} |