From 9a433b99a56dc575f1c0b11f95b744de61859dbb Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Thu, 9 Jan 2003 12:20:03 -0500 Subject: [svn-r6252] Purpose: Lots of performance improvements & a couple new internal API interfaces. Description: Performance Improvements: - Cached file offset & length sizes in shared file struct, to avoid constantly looking them up in the FCPL. - Generic property improvements: - Added "revision" number to generic property classes to speed up comparisons. - Changed method of storing properties from using a hash-table to the TBBT routines in the library. - Share the propery names between classes and the lists derived from them. - Removed redundant 'def_value' buffer from each property. - Switching code to use a "copy on write" strategy for properties in each list, where the properties in each list are shared with the properties in the class, until a property's value is changed in a list. - Fixed error in layout code which was allocating too many buffers. - Redefined public macros of the form (H5open()/H5check, ) internally to only be (), avoiding innumerable useless calls to H5open() and H5check_version(). - Reuse already zeroed buffers in H5F_contig_fill instead of constantly re-zeroing them. - Don't write fill values if writing entire dataset. - Use gettimeofday() system call instead of time() system when checking the modification time of a dataset. - Added reference counted string API and use it for tracking the names of objects opening in a file (for the ID->name code). - Removed redundant H5P_get() calls in B-tree routines. - Redefine H5T datatype macros internally to the library, to avoid calling H5check redundantly. - Keep dataspace information for dataset locally instead of reading from disk each time. Added new module to track open objects in a file, to allow this (which will be useful eventually for some FPH5 metadata caching issues). - Remove H5AC_find macro which was inlining metadata cache lookups, and call function instead. - Remove redundant memset() calls from H5G_namei() routine. - Remove redundant checking of object type when locating objects in metadata cache and rely on the address only. - Create default dataset object to use when default dataset creation property list is used to create datasets, bypassing querying for all the property list values. - Use default I/O vector size when performing raw data with the default dataset transfer property list, instead of querying for I/O vector size. - Remove H5P_DEFAULT internally to the library, replacing it with more specific default property list based on the type of property list needed. - Remove redundant memset() calls in object header message (H5O*) routines. - Remove redunant memset() calls in data I/O routines. - Split free-list allocation routines into malloc() and calloc()- like routines, instead of one combined routine. - Remove lots of indirection in H5O*() routines. - Simplify metadata cache entry comparison routine (used when flushing entire cache out). - Only enable metadata cache statistics when H5AC_DEBUG is turned on, instead of always tracking them. - Simplify address comparison macro (H5F_addr_eq). - Remove redundant metadata cache entry protections during dataset creation by protecting the object header once and making all the modifications necessary for the dataset creation before unprotecting it. - Reduce # of "number of element in extent" computations performed by computing and storing the value during dataspace creation. - Simplify checking for group location's file information, when file has not been involving in file-mounting operations. - Use binary encoding for modification time, instead of ASCII. - Hoist H5HL_peek calls (to get information in a local heap) out of loops in many group routine. - Use static variable for iterators of selections, instead of dynamically allocation them each time. - Lookup & insert new entries in one step, avoiding traversing group's B-tree twice. - Fixed memory leak in H5Gget_objname_idx() routine (tangential to performance improvements, but fixed along the way). - Use free-list for reference counted strings. - Don't bother copying object names into cached group entries, since they are re-created when an object is opened. The benchmark I used to measure these results created several thousand small (2K) datasets in a file and wrote out the data for them. This is Elena's "regular.c" benchmark. These changes resulted in approximately ~4.3x speedup of the development branch when compared to the previous code in the development branch and ~1.4x speedup compared to the release branch. Additionally, these changes reduce the total memory used (code and data) by the development branch by ~800KB, bringing the development branch back into the same ballpark as the release branch. I'll send out a more detailed description of the benchmark results as a followup note. New internal API routines: Added "reference counted strings" API for tracking strings that get used by multiple owners without duplicating the strings. Added "ternary search tree" API for text->object mappings. Platforms tested: Tested h5committest {arabica (fortran), eirene (fortran, C++) modi4 (parallel, fortran)} Other platforms/configurations tested? FreeBSD 4.7 (sleipnir) serial & parallel Solaris 2.6 (baldric) serial --- MANIFEST | 12 +- configure | 83 +- configure.in | 10 +- release_docs/RELEASE.txt | 2 + src/H5.c | 6 +- src/H5A.c | 10 +- src/H5AC.c | 181 ++-- src/H5ACprivate.h | 7 + src/H5B.c | 142 ++-- src/H5Bprivate.h | 2 - src/H5D.c | 1096 ++++++++++++------------ src/H5Dcontig.c | 106 ++- src/H5Distore.c | 13 +- src/H5Dprivate.h | 35 +- src/H5Dseq.c | 46 +- src/H5E.c | 2 + src/H5Epublic.h | 4 +- src/H5F.c | 327 +++++--- src/H5FD.c | 39 +- src/H5FDfamily.c | 41 +- src/H5FDgass.c | 8 +- src/H5FDlog.c | 6 +- src/H5FDlog.h | 4 +- src/H5FDmpio.c | 12 +- src/H5FDmpiposix.c | 6 +- src/H5FDmulti.c | 24 +- src/H5FDsec2.c | 2 +- src/H5FDsrb.c | 7 +- src/H5FDstream.c | 2 +- src/H5FL.c | 209 ++++- src/H5FLprivate.h | 38 +- src/H5FO.c | 277 +++++++ src/H5FOprivate.h | 42 + src/H5FPclient.c | 6 +- src/H5Fcontig.c | 106 ++- src/H5Fistore.c | 13 +- src/H5Fpkg.h | 15 +- src/H5Fprivate.h | 46 +- src/H5Fpublic.h | 24 +- src/H5Fseq.c | 46 +- src/H5G.c | 521 +++++++----- src/H5Gent.c | 26 +- src/H5Gnode.c | 170 ++-- src/H5Gpkg.h | 1 - src/H5Gprivate.h | 11 +- src/H5Gstab.c | 76 +- src/H5HG.c | 28 +- src/H5HL.c | 76 +- src/H5I.c | 12 +- src/H5MMprivate.h | 4 +- src/H5O.c | 395 +++++++-- src/H5Oattr.c | 11 +- src/H5Ocomp.c | 492 ----------- src/H5Odtype.c | 26 +- src/H5Oefl.c | 3 +- src/H5Ofill.c | 121 ++- src/H5Ofphdf5.c | 4 +- src/H5Olayout.c | 6 +- src/H5Omtime.c | 208 ++++- src/H5Opline.c | 493 +++++++++++ src/H5Oplist.c | 206 ++--- src/H5Oprivate.h | 41 +- src/H5Osdspace.c | 18 +- src/H5Ostab.c | 6 +- src/H5P.c | 1891 +++++++++++++++++++++++++++--------------- src/H5Pdcpl.c | 62 +- src/H5Pfapl.c | 8 +- src/H5Ppkg.h | 27 +- src/H5Pprivate.h | 5 + src/H5Ppublic.h | 64 +- src/H5R.c | 23 +- src/H5RS.c | 390 +++++++++ src/H5RSprivate.h | 52 ++ src/H5S.c | 149 +++- src/H5ST.c | 795 ++++++++++++++++++ src/H5STprivate.h | 61 ++ src/H5Sall.c | 4 +- src/H5Shyper.c | 73 +- src/H5Smpio.c | 12 +- src/H5Spkg.h | 3 +- src/H5Spoint.c | 8 +- src/H5Sprivate.h | 40 +- src/H5Sselect.c | 322 +++---- src/H5T.c | 159 ++-- src/H5TB.c | 192 ++++- src/H5TBprivate.h | 11 +- src/H5Tconv.c | 128 +-- src/H5Tprivate.h | 1 + src/H5Tpublic.h | 174 ++-- src/H5Tvlen.c | 12 - src/H5detect.c | 2 +- src/Makefile.in | 26 +- test/Makefile.in | 15 +- test/dsets.c | 15 +- test/fillval.c | 2 +- test/gen_new_mtime.c | 65 ++ test/gen_old_mtime.c | 66 ++ test/istore.c | 3 +- test/mtime.c | 68 +- test/ntypes.c | 1 - test/ohdr.c | 13 +- test/tattr.c | 25 +- test/testhdf5.c | 2 + test/testhdf5.h | 2 + test/tgenprop.c | 38 +- test/titerate.c | 14 +- test/tmtimen.h5 | Bin 0 -> 1576 bytes test/tmtimeo.h5 | Bin 0 -> 1576 bytes test/trefstr.c | 378 +++++++++ test/ttst.c | 400 +++++++++ test/tvlstr.c | 9 +- tools/h5dump/h5dump.c | 2 +- tools/h5dump/h5dumpgentest.c | 2 +- 113 files changed, 8194 insertions(+), 3632 deletions(-) create mode 100644 src/H5FO.c create mode 100644 src/H5FOprivate.h delete mode 100644 src/H5Ocomp.c create mode 100644 src/H5Opline.c create mode 100644 src/H5RS.c create mode 100644 src/H5RSprivate.h create mode 100644 src/H5ST.c create mode 100644 src/H5STprivate.h create mode 100644 test/gen_new_mtime.c create mode 100644 test/gen_old_mtime.c create mode 100644 test/tmtimen.h5 create mode 100644 test/tmtimeo.h5 create mode 100644 test/trefstr.c create mode 100644 test/ttst.c diff --git a/MANIFEST b/MANIFEST index e25c841..80a88f0 100644 --- a/MANIFEST +++ b/MANIFEST @@ -830,6 +830,8 @@ ./src/H5FDstream.h ./src/H5FL.c ./src/H5FLprivate.h +./src/H5FO.c +./src/H5FOprivate.h ./src/H5FP.c ./src/H5FPclient.c ./src/H5FPprivate.h @@ -859,7 +861,6 @@ ./src/H5MPprivate.h ./src/H5O.c ./src/H5Oattr.c -./src/H5Ocomp.c ./src/H5Ocont.c ./src/H5Odtype.c ./src/H5Oefl.c @@ -869,6 +870,7 @@ ./src/H5Omtime.c ./src/H5Oname.c ./src/H5Onull.c +./src/H5Opline.c ./src/H5Oplist.c ./src/H5Oprivate.h ./src/H5Opublic.h @@ -886,6 +888,8 @@ ./src/H5R.c ./src/H5Rprivate.h ./src/H5Rpublic.h +./src/H5RS.c +./src/H5RSprivate.h ./src/H5S.c ./src/H5Sall.c ./src/H5Shyper.c @@ -896,6 +900,8 @@ ./src/H5Sprivate.h ./src/H5Spublic.h ./src/H5Sselect.c +./src/H5ST.c +./src/H5STprivate.h ./src/H5T.c ./src/H5Tbit.c ./src/H5Tconv.c @@ -958,6 +964,8 @@ ./test/gen_old_array.c _DO_NOT_DISTRIBUTE_ ./test/gen_new_array.c _DO_NOT_DISTRIBUTE_ ./test/gen_new_fill.c _DO_NOT_DISTRIBUTE_ +./test/gen_old_mtime.c _DO_NOT_DISTRIBUTE_ +./test/gen_new_mtime.c _DO_NOT_DISTRIBUTE_ ./test/set_extent.c ./test/srb_append.c ./test/srb_read.c @@ -978,6 +986,8 @@ ./test/titerate.c ./test/tmeta.c ./test/tmisc.c +./test/tmtimen.h5 +./test/tmtimeo.h5 ./test/ttime.c ./test/trefer.c ./test/tselect.c diff --git a/configure b/configure index 861fe77..48826df 100755 --- a/configure +++ b/configure @@ -7788,6 +7788,83 @@ fi +for ac_func in difftime gettimeofday +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. */ +#include +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +char (*f) (); + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +f = $ac_func; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +eval "$as_ac_var=no" +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + @@ -28619,8 +28696,7 @@ rm -f conftest.$ac_objext conftest.$ac_ext - -for ac_func in difftime fork gethostname getpwuid getrusage +for ac_func in fork gethostname getpwuid getrusage do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 @@ -28699,8 +28775,7 @@ done - -for ac_func in gettimeofday BSDgettimeofday longjmp setsysinfo sigaction +for ac_func in BSDgettimeofday longjmp setsysinfo sigaction do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 diff --git a/configure.in b/configure.in index 0e1640b..7ed536e 100644 --- a/configure.in +++ b/configure.in @@ -468,6 +468,12 @@ dnl AC_HEADER_STDC AC_HEADER_TIME +dnl ---------------------------------------------------------------------- +dnl Check for these two functions before is checked for, otherwise +dnl they are not detected correctly on Solaris [2.6]. +dnl +AC_CHECK_FUNCS(difftime gettimeofday) + dnl Unix AC_CHECK_HEADERS([sys/resource.h sys/time.h unistd.h sys/ioctl.h sys/stat.h]) AC_CHECK_HEADERS([sys/socket.h sys/types.h]) @@ -1287,8 +1293,8 @@ AC_MSG_RESULT(no)) dnl ---------------------------------------------------------------------- dnl Check for functions. dnl -AC_CHECK_FUNCS(difftime fork gethostname getpwuid getrusage) -AC_CHECK_FUNCS(gettimeofday BSDgettimeofday longjmp setsysinfo sigaction) +AC_CHECK_FUNCS(fork gethostname getpwuid getrusage) +AC_CHECK_FUNCS(BSDgettimeofday longjmp setsysinfo sigaction) AC_CHECK_FUNCS(signal snprintf vsnprintf strdup system waitpid) dnl ---------------------------------------------------------------------- diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 39d2fd9..c548de4 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -236,6 +236,8 @@ Documentation o Performance ------------- + * Improved dataset creation time by about 30% (relative to the 1.4.x + branch). New Features diff --git a/src/H5.c b/src/H5.c index 13cda68..742cd77 100644 --- a/src/H5.c +++ b/src/H5.c @@ -1388,9 +1388,7 @@ H5_bandwidth(char *buf/*out*/, double nbytes, double nseconds) * * WARNING: DO NOT CALL ANY HDF5 FUNCTION THAT CALLS FUNC_ENTER(). DOING * SO MAY CAUSE H5_trace() TO BE INVOKED RECURSIVELY OR MAY - * CAUSE LIBRARY INITIALIZATIONS THAT ARE NOT DESIRED. DO NOT - * USE THE H5T_*_* CONSTANTS SINCE THEY CALL H5_open() WHICH - * INVOKES FUNC_ENTER(). + * CAUSE LIBRARY INITIALIZATIONS THAT ARE NOT DESIRED. * * Return: void * @@ -1453,7 +1451,7 @@ H5_trace (double *returning, const char *func, const char *type, ...) if (H5_debug_g.ttimes) { H5_timer_begin(&event_time); } else { - memset(&event_time, 0, sizeof event_time); + HDmemset(&event_time, 0, sizeof event_time); } /* Print the first part of the line. This is the indication of the diff --git a/src/H5A.c b/src/H5A.c index 8f7f0bb..ab180d2 100644 --- a/src/H5A.c +++ b/src/H5A.c @@ -275,7 +275,7 @@ H5A_create(const H5G_entry_t *ent, const char *name, const H5T_t *type, H5E_clear (); /* Create the attribute message and save the attribute index */ - if (H5O_modify(&(attr->ent), H5O_ATTR, H5O_NEW_MESG, 0, attr) < 0) + if (H5O_modify(&(attr->ent), H5O_ATTR, H5O_NEW_MESG, 0, 1, attr) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to update attribute header messages"); /* Register the new attribute and get an ID for it */ @@ -635,7 +635,7 @@ H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf) /* Perform data type conversion */ if (H5T_convert(tpath, src_id, dst_id, nelmts, 0, 0, tconv_buf, bkg_buf, - H5P_DEFAULT)<0) { + H5P_DATASET_XFER_DEFAULT)<0) { HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "data type conversion failed"); } @@ -650,7 +650,7 @@ H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf) /* Modify the attribute data */ attr->data=tconv_buf; /* Set the data pointer temporarily */ - if (H5O_modify(&(attr->ent), H5O_ATTR, idx, 0, attr) < 0) + if (H5O_modify(&(attr->ent), H5O_ATTR, idx, 0, 1, attr) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to update attribute header messages"); @@ -787,7 +787,7 @@ H5A_read(H5A_t *attr, const H5T_t *mem_type, void *buf) } /* Perform data type conversion. */ - if (H5T_convert(tpath, src_id, dst_id, nelmts, 0, 0, tconv_buf, bkg_buf, H5P_DEFAULT)<0) + if (H5T_convert(tpath, src_id, dst_id, nelmts, 0, 0, tconv_buf, bkg_buf, H5P_DATASET_XFER_DEFAULT)<0) HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "data type conversion failed"); /* Copy the converted data into the user's buffer */ @@ -1223,7 +1223,7 @@ H5A_rename(H5G_entry_t *ent, const char *old_name, const char *new_name) found_attr->initialized=TRUE; /* Modify the attribute message */ - if (H5O_modify(ent, H5O_ATTR, idx, 0, found_attr) < 0) + if (H5O_modify(ent, H5O_ATTR, idx, 0, 1, found_attr) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to update attribute header messages"); /* Close the attribute */ diff --git a/src/H5AC.c b/src/H5AC.c index dfdf6d4..fa4f1cb 100644 --- a/src/H5AC.c +++ b/src/H5AC.c @@ -4,7 +4,7 @@ * *------------------------------------------------------------------------- * - * Created: hdf5cache.c + * Created: H5AC.c * Jul 9 1997 * Robb Matzke * @@ -103,7 +103,7 @@ H5AC_init_interface(void) assert(H5P_CLS_DATASET_XFER_g!=(-1)); /* Get the dataset transfer property list class object */ - if (NULL == (xfer_pclass = H5I_object_verify(H5P_CLS_DATASET_XFER_g, H5I_GENPROP_CLS))) + if (NULL == (xfer_pclass = H5I_object(H5P_CLS_DATASET_XFER_g))) HGOTO_ERROR(H5E_CACHE, H5E_BADATOM, FAIL, "can't get property list class"); /* Create a new dataset transfer property list */ @@ -206,14 +206,14 @@ H5AC_create(H5F_t *f, int size_hint) assert(NULL == f->shared->cache); if (size_hint < 1) size_hint = H5AC_NSLOTS; - if (NULL==(f->shared->cache = cache = H5FL_ALLOC(H5AC_t,1))) + if (NULL==(f->shared->cache = cache = H5FL_CALLOC(H5AC_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); cache->nslots = size_hint; - cache->slot = H5FL_ARR_ALLOC(H5AC_info_ptr_t,cache->nslots,1); + cache->slot = H5FL_ARR_CALLOC(H5AC_info_ptr_t,cache->nslots); if (NULL==cache->slot) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); #ifdef H5AC_DEBUG - if ((cache->prot = H5FL_ARR_ALLOC(H5AC_prot_t,cache->nslots,1))==NULL) + if ((cache->prot = H5FL_ARR_CALLOC(H5AC_prot_t,cache->nslots))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); #endif /* H5AC_DEBUG */ @@ -341,13 +341,13 @@ H5AC_find_f(H5F_t *f, const H5AC_class_t *type, haddr_t addr, { unsigned idx; herr_t status; - void *thing = NULL; + void *thing; H5AC_flush_func_t flush; - H5AC_info_t **info = NULL; - H5AC_t *cache = NULL; + H5AC_info_t **info; + H5AC_t *cache; void *ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5AC_find, NULL); + FUNC_ENTER_NOAPI(H5AC_find_f, NULL); assert(f); assert(f->shared->cache); @@ -355,6 +355,8 @@ H5AC_find_f(H5F_t *f, const H5AC_class_t *type, haddr_t addr, assert(type->load); assert(type->flush); assert(H5F_addr_defined(addr)); + + /* Get local copies of information */ idx = H5AC_HASH(f, addr); cache = f->shared->cache; info = cache->slot + idx; @@ -362,18 +364,18 @@ H5AC_find_f(H5F_t *f, const H5AC_class_t *type, haddr_t addr, /* * Return right away if the item is in the cache. */ - if ((*info) && (*info)->type == type && H5F_addr_eq((*info)->addr, addr)) { + if ((*info) && H5F_addr_eq(addr,(*info)->addr)) { + /* Sanity check that the object in the cache is the correct type */ + assert((*info)->type==type); + +#ifdef H5AC_DEBUG cache->diagnostics[type->id].nhits++; +#endif /* H5AC_DEBUG */ HGOTO_DONE(*info); } +#ifdef H5AC_DEBUG cache->diagnostics[type->id].nmisses++; - - /* - * Fail if the item in the cache is at the correct address but is - * of the wrong type. - */ - if ((*info) && (*info)->type && (*info)->type != type && H5F_addr_eq((*info)->addr, addr)) - HGOTO_ERROR(H5E_CACHE, H5E_BADTYPE, NULL, "internal error (correct address, wrong type)"); +#endif /* H5AC_DEBUG */ #ifdef H5AC_DEBUG /* @@ -403,7 +405,9 @@ H5AC_find_f(H5F_t *f, const H5AC_class_t *type, haddr_t addr, * Free the previous cache entry if there is one. */ if (*info) { +#ifdef H5AC_DEBUG H5AC_subid_t type_id=(*info)->type->id; /* Remember this for later */ +#endif /* H5AC_DEBUG */ flush = (*info)->type->flush; status = (flush)(f, H5AC_dxpl_id, TRUE, (*info)->addr, (*info)); @@ -416,7 +420,9 @@ H5AC_find_f(H5F_t *f, const H5AC_class_t *type, haddr_t addr, HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, NULL, "unable to flush just-loaded object"); HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, NULL, "unable to flush existing cached object"); } +#ifdef H5AC_DEBUG cache->diagnostics[type_id].nflushes++; +#endif /* H5AC_DEBUG */ } /* @@ -459,37 +465,29 @@ H5AC_compare(const void *_a, const void *_b) int a = *((const int *) _a); int b = *((const int *) _b); int ret_value=0; + H5AC_info_t *slot_a; + H5AC_info_t *slot_b; /* Use FUNC_ENTER_NOINIT here to avoid performance issues */ FUNC_ENTER_NOINIT(H5AC_compare); assert(current_cache_g); - if(NULL==current_cache_g->slot[a] || NULL == current_cache_g->slot[b]) { - if(NULL==current_cache_g->slot[a]) { - if (NULL == current_cache_g->slot[b]) { - HGOTO_DONE(0); - } else - HGOTO_DONE(-1); - } - else { - HGOTO_DONE(1); - } - } - else if (NULL == current_cache_g->slot[a]->type) { - if (NULL == current_cache_g->slot[b]->type) { - HGOTO_DONE(0); - } else - HGOTO_DONE(-1); - } else if (NULL == current_cache_g->slot[b]->type) { - HGOTO_DONE(1); - } else if (current_cache_g->slot[a]->addr < current_cache_g->slot[b]->addr) { - HGOTO_DONE(-1); - } else if (current_cache_g->slot[a]->addr > current_cache_g->slot[b]->addr) { - HGOTO_DONE(1); + /* Create aliases for slots */ + slot_a=current_cache_g->slot[a]; + slot_b=current_cache_g->slot[b]; + + assert(slot_a); + assert(slot_b); + assert(slot_a->type); + assert(slot_b->type); + + if (slot_a->addr < slot_b->addr) { + ret_value=(-1); + } else if (slot_a->addr > slot_b->addr) { + ret_value=1; } -done: FUNC_LEAVE(ret_value); } #endif @@ -524,21 +522,23 @@ done: herr_t H5AC_flush(H5F_t *f, const H5AC_class_t *type, haddr_t addr, hbool_t destroy) { - unsigned i; + unsigned i; herr_t status; H5AC_flush_func_t flush=NULL; H5AC_info_t **info; #ifdef H5AC_SORT_BY_ADDR int *map = NULL; #endif /* H5AC_SORT_BY_ADDR */ - unsigned nslots; - H5AC_t *cache = NULL; + unsigned nslots; + H5AC_t *cache; herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5AC_flush, FAIL); assert(f); assert(f->shared->cache); + + /* Get local copy of this information */ cache = f->shared->cache; if (!H5F_addr_defined(addr)) { @@ -549,7 +549,7 @@ H5AC_flush(H5F_t *f, const H5AC_class_t *type, haddr_t addr, hbool_t destroy) * Sort the cache entries by address since flushing them in * ascending order by address may be much more efficient. */ - if (NULL==(map=H5FL_ARR_ALLOC(int,cache->nslots,0))) + if (NULL==(map=H5FL_ARR_MALLOC(int,cache->nslots))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); for (i = nslots = 0; i < cache->nslots; i++) { if (cache->slot[i]!=NULL) @@ -581,7 +581,9 @@ H5AC_flush(H5F_t *f, const H5AC_class_t *type, haddr_t addr, hbool_t destroy) continue; #endif /* H5AC_SORT_BY_ADDR */ if (!type || type == (*info)->type) { +#ifdef H5AC_DEBUG H5AC_subid_t type_id=(*info)->type->id; /* Remember this for later */ +#endif /* H5AC_DEBUG */ flush = (*info)->type->flush; @@ -592,20 +594,16 @@ H5AC_flush(H5F_t *f, const H5AC_class_t *type, haddr_t addr, hbool_t destroy) } /* end if */ else status = (flush)(f, H5P_DATASET_XFER_DEFAULT, destroy, (*info)->addr, (*info)); - if (status < 0) { -#ifdef H5AC_SORT_BY_ADDR - map = H5FL_ARR_FREE(int,map); -#endif /* H5AC_SORT_BY_ADDR */ + if (status < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache"); - } + +#ifdef H5AC_DEBUG cache->diagnostics[type_id].nflushes++; +#endif /* H5AC_DEBUG */ if (destroy) (*info)= NULL; } } -#ifdef H5AC_SORT_BY_ADDR - map = H5FL_ARR_FREE(int,map); -#endif /* H5AC_SORT_BY_ADDR */ /* * If there are protected object then fail. However, everything @@ -616,9 +614,10 @@ H5AC_flush(H5F_t *f, const H5AC_class_t *type, haddr_t addr, hbool_t destroy) } else { i = H5AC_HASH(f, addr); if (cache->slot[i] && (!type || cache->slot[i]->type == type) && - H5F_addr_eq(cache->slot[i]->addr, addr)) { - + H5F_addr_eq(addr,cache->slot[i]->addr)) { +#ifdef H5AC_DEBUG H5AC_subid_t type_id=cache->slot[i]->type->id; /* Remember this for later */ +#endif /* H5AC_DEBUG */ /* * Flush just this entry. @@ -627,13 +626,20 @@ H5AC_flush(H5F_t *f, const H5AC_class_t *type, haddr_t addr, hbool_t destroy) if ((flush)(f, H5AC_dxpl_id, destroy, cache->slot[i]->addr, cache->slot[i]) < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush object"); +#ifdef H5AC_DEBUG cache->diagnostics[type_id].nflushes++; +#endif /* H5AC_DEBUG */ if (destroy) cache->slot[i]= NULL; } } done: +#ifdef H5AC_SORT_BY_ADDR + if(map!=NULL) + map = H5FL_ARR_FREE(int,map); +#endif /* H5AC_SORT_BY_ADDR */ + FUNC_LEAVE(ret_value); } @@ -662,10 +668,10 @@ done: herr_t H5AC_set(H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing) { - unsigned idx; - H5AC_flush_func_t flush=NULL; - H5AC_info_t **info = NULL; - H5AC_t *cache = NULL; + unsigned idx; + H5AC_flush_func_t flush; + H5AC_info_t **info; + H5AC_t *cache; herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5AC_set, FAIL); @@ -677,6 +683,7 @@ H5AC_set(H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing) assert(H5F_addr_defined(addr)); assert(thing); + /* Get local copy of this information */ idx = H5AC_HASH(f, addr); cache = f->shared->cache; info = cache->slot + idx; @@ -693,19 +700,26 @@ H5AC_set(H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing) #endif + /* Flush any object already in cache slot */ if ((*info)) { +#ifdef H5AC_DEBUG H5AC_subid_t type_id=(*info)->type->id; /* Remember this for later */ +#endif /* H5AC_DEBUG */ flush = (*info)->type->flush; if ((flush)(f, H5AC_dxpl_id, TRUE, (*info)->addr, (*info)) < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush object"); +#ifdef H5AC_DEBUG cache->diagnostics[type_id].nflushes++; +#endif /* H5AC_DEBUG */ } (*info)=thing; (*info)->type = type; (*info)->addr = addr; +#ifdef H5AC_DEBUG cache->diagnostics[type->id].ninits++; +#endif /* H5AC_DEBUG */ done: FUNC_LEAVE(ret_value); @@ -737,9 +751,9 @@ herr_t H5AC_rename(H5F_t *f, const H5AC_class_t *type, haddr_t old_addr, haddr_t new_addr) { - unsigned old_idx, new_idx; - H5AC_flush_func_t flush=NULL; - H5AC_t *cache = NULL; + unsigned old_idx, new_idx; + H5AC_flush_func_t flush; + H5AC_t *cache; herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5AC_rename, FAIL); @@ -748,6 +762,7 @@ H5AC_rename(H5F_t *f, const H5AC_class_t *type, haddr_t old_addr, assert(f->shared->cache); assert(type); + /* Get local copy of this information */ old_idx = H5AC_HASH(f, old_addr); new_idx = H5AC_HASH(f, new_addr); cache = f->shared->cache; @@ -771,7 +786,7 @@ H5AC_rename(H5F_t *f, const H5AC_class_t *type, haddr_t old_addr, * new hash value is the same as the old one. */ if (cache->slot[old_idx]->type != type || - H5F_addr_ne(cache->slot[old_idx]->addr, old_addr)) { + H5F_addr_ne(cache->slot[old_idx]->addr, old_addr)) { HGOTO_DONE(SUCCEED); } if (old_idx == new_idx) { @@ -782,13 +797,17 @@ H5AC_rename(H5F_t *f, const H5AC_class_t *type, haddr_t old_addr, * Free the item from the destination cache line. */ if (cache->slot[new_idx]) { +#ifdef H5AC_DEBUG H5AC_subid_t type_id=cache->slot[new_idx]->type->id; /* Remember this for later */ +#endif /* H5AC_DEBUG */ flush = cache->slot[new_idx]->type->flush; if ((flush)(f, H5AC_dxpl_id, TRUE, cache->slot[new_idx]->addr, cache->slot[new_idx]) < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush object"); +#ifdef H5AC_DEBUG cache->diagnostics[type_id].nflushes++; +#endif /* H5AC_DEBUG */ } /* @@ -836,9 +855,9 @@ H5AC_protect(H5F_t *f, const H5AC_class_t *type, haddr_t addr, const void *udata1, void *udata2) { int idx; - void *thing = NULL; - H5AC_t *cache = NULL; - H5AC_info_t **info = NULL; + void *thing; + H5AC_t *cache; + H5AC_info_t **info; void *ret_value; /* Return value */ #ifdef H5AC_DEBUG @@ -862,6 +881,7 @@ H5AC_protect(H5F_t *f, const H5AC_class_t *type, haddr_t addr, assert(type->flush); assert(H5F_addr_defined(addr)); + /* Get local copy of this information */ idx = H5AC_HASH(f, addr); cache = f->shared->cache; info = cache->slot + idx; @@ -869,22 +889,20 @@ H5AC_protect(H5F_t *f, const H5AC_class_t *type, haddr_t addr, prot = cache->prot + idx; #endif /* H5AC_DEBUG */ - if ((*info) && (*info)->type == type && H5F_addr_eq((*info)->addr, addr)) { + if ((*info) && H5F_addr_eq(addr,(*info)->addr)) { + /* Sanity check that the object in the cache is the correct type */ + assert((*info)->type==type); + /* * The object is already cached; simply remove it from the cache. */ +#ifdef H5AC_DEBUG cache->diagnostics[(*info)->type->id].nhits++; +#endif /* H5AC_DEBUG */ thing = (*info); (*info)->type = NULL; (*info)->addr = HADDR_UNDEF; (*info)= NULL; - - } else if ((*info) && (*info)->type && H5F_addr_eq((*info)->addr, addr)) { - /* - * Right address but wrong object type. - */ - HGOTO_ERROR(H5E_CACHE, H5E_BADTYPE, NULL, "internal error"); - } else { #ifdef H5AC_DEBUG /* @@ -902,7 +920,9 @@ H5AC_protect(H5F_t *f, const H5AC_class_t *type, haddr_t addr, * Load a new thing. If it can't be loaded, then return an error * without preempting anything. */ +#ifdef H5AC_DEBUG cache->diagnostics[type->id].nmisses++; +#endif /* H5AC_DEBUG */ if (NULL == (thing = (type->load)(f, H5P_DATASET_XFER_DEFAULT, addr, udata1, udata2))) HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, NULL, "unable to load object"); } @@ -963,11 +983,11 @@ done: herr_t H5AC_unprotect(H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing) { - unsigned idx; - H5AC_flush_func_t flush=NULL; - H5AC_t *cache = NULL; - H5AC_info_t **info = NULL; - herr_t ret_value=SUCCEED; /* Return value */ + unsigned idx; + H5AC_flush_func_t flush; + H5AC_t *cache; + H5AC_info_t **info; + herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5AC_unprotect, FAIL); @@ -979,6 +999,7 @@ H5AC_unprotect(H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing) assert(H5F_addr_defined(addr)); assert(thing); + /* Get local copy of this information */ idx = H5AC_HASH(f, addr); cache = f->shared->cache; info = cache->slot + idx; @@ -988,13 +1009,17 @@ H5AC_unprotect(H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing) * better not be another copy of the protected object. */ if (*info) { +#ifdef H5AC_DEBUG H5AC_subid_t type_id=(*info)->type->id; /* Remember this for later */ +#endif /* H5AC_DEBUG */ assert(H5F_addr_ne((*info)->addr, addr)); flush = (*info)->type->flush; if ((flush)(f, H5AC_dxpl_id, TRUE, (*info)->addr, (*info)) < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush object"); +#ifdef H5AC_DEBUG cache->diagnostics[type_id].nflushes++; +#endif /* H5AC_DEBUG */ } #ifdef H5AC_DEBUG /* diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h index 44d4ca8..d587df6 100644 --- a/src/H5ACprivate.h +++ b/src/H5ACprivate.h @@ -99,12 +99,14 @@ typedef struct H5AC_t { H5AC_prot_t *prot; /*the protected slots */ #endif /* H5AC_DEBUG */ int nprots; /*number of protected objects */ +#ifdef H5AC_DEBUG struct { unsigned nhits; /*number of cache hits */ unsigned nmisses; /*number of cache misses */ unsigned ninits; /*number of cache inits */ unsigned nflushes; /*number of flushes to disk */ } diagnostics[H5AC_NTYPES]; /*diagnostics for each type of object*/ +#endif /* H5AC_DEBUG */ } H5AC_t; #ifdef H5_HAVE_PARALLEL @@ -133,6 +135,10 @@ H5_DLL herr_t H5AC_set(H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *thing); H5_DLL herr_t H5AC_debug(H5F_t *f); +/* This seems to be slower than just calling H5AC_find_f, which performs the + * cache lookup also. - QAK + */ +#ifdef OLD_WAY #define H5AC_find(F,TYPE,ADDR,UDATA1,UDATA2) \ ((F)->shared->cache->slot[H5AC_HASH(F,ADDR)]!=NULL && \ ((F)->shared->cache->slot[H5AC_HASH(F,ADDR)]->type==(TYPE) && \ @@ -140,6 +146,7 @@ H5_DLL herr_t H5AC_debug(H5F_t *f); ((F)->shared->cache->diagnostics[(TYPE)->id].nhits++, \ (F)->shared->cache->slot[H5AC_HASH(F,ADDR)]) : \ H5AC_find_f(F, TYPE, ADDR, UDATA1, UDATA2)) +#endif /* OLD_WAY */ #endif /* !_H5ACprivate_H */ diff --git a/src/H5B.c b/src/H5B.c index 700cf3f..a0386b0 100644 --- a/src/H5B.c +++ b/src/H5B.c @@ -212,7 +212,7 @@ H5B_create(H5F_t *f, const H5B_class_t *type, void *udata, size = H5B_nodesize(f, type, &total_native_keysize, sizeof_rkey); if (HADDR_UNDEF==(*addr_p=H5MF_alloc(f, H5FD_MEM_BTREE, (hsize_t)size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for B-tree root node"); - if (NULL==(bt = H5FL_ALLOC(H5B_t,1))) + if (NULL==(bt = H5FL_CALLOC(H5B_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree root node"); bt->type = type; bt->sizeof_rkey = sizeof_rkey; @@ -222,10 +222,10 @@ H5B_create(H5F_t *f, const H5B_class_t *type, void *udata, bt->left = HADDR_UNDEF; bt->right = HADDR_UNDEF; bt->nchildren = 0; - if (NULL==(bt->page=H5FL_BLK_ALLOC(page,size,1)) || - NULL==(bt->native=H5FL_BLK_ALLOC(native_block,total_native_keysize,0)) || - NULL==(bt->child=H5FL_ARR_ALLOC(haddr_t,(size_t)(2*H5B_Kvalue(f,type)),0)) || - NULL==(bt->key=H5FL_ARR_ALLOC(H5B_key_t,(size_t)(2*H5B_Kvalue(f,type)+1),0))) + if (NULL==(bt->page=H5FL_BLK_CALLOC(page,size)) || + NULL==(bt->native=H5FL_BLK_MALLOC(native_block,total_native_keysize)) || + NULL==(bt->child=H5FL_ARR_MALLOC(haddr_t,(size_t)(2*H5F_KVALUE(f,type)))) || + NULL==(bt->key=H5FL_ARR_MALLOC(H5B_key_t,(size_t)(2*H5F_KVALUE(f,type)+1)))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree root node"); /* @@ -234,7 +234,7 @@ H5B_create(H5F_t *f, const H5B_class_t *type, void *udata, * translated to native format. */ for (i = 0, offset = H5B_SIZEOF_HDR(f); - i < 2 * H5B_Kvalue(f, type); + i < 2 * H5F_KVALUE(f, type); i++, offset += bt->sizeof_rkey + H5F_SIZEOF_ADDR(f)) { bt->key[i].dirty = FALSE; @@ -246,9 +246,9 @@ H5B_create(H5F_t *f, const H5B_class_t *type, void *udata, /* * The last possible key... */ - bt->key[2 * H5B_Kvalue(f, type)].dirty = FALSE; - bt->key[2 * H5B_Kvalue(f, type)].rkey = bt->page + offset; - bt->key[2 * H5B_Kvalue(f, type)].nkey = NULL; + bt->key[2 * H5F_KVALUE(f, type)].dirty = FALSE; + bt->key[2 * H5F_KVALUE(f, type)].rkey = bt->page + offset; + bt->key[2 * H5F_KVALUE(f, type)].nkey = NULL; /* * Cache the new B-tree node. @@ -276,54 +276,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5B_Kvalue - * - * Purpose: Replaced a macro to retrieve a B-tree key value for a certain - * type, now that the generic properties are being used to store - * the B-tree values. - * - * Return: Success: Non-negative, and the B-tree key value is - * returned. - * - * Failure: Negative (should not happen) - * - * Programmer: Raymond Lu - * slu@ncsa.uiuc.edu - * Oct 14 2001 - * - * Modifications: - * Quincey Koziol, 2001-10-15 - * Added this header and removed unused ret_value variable. - *------------------------------------------------------------------------- - */ -int -H5B_Kvalue(H5F_t *f, const H5B_class_t *type) -{ - int btree_k[H5B_NUM_BTREE_ID]; - H5P_genplist_t *plist; - int ret_value; /* Return value */ - - FUNC_ENTER_NOAPI(H5B_Kvalue, FAIL); - - assert(f); - assert(type); - - /* Check arguments */ - if (NULL == (plist = H5I_object(f->shared->fcpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list"); - - if(H5P_get(plist, H5F_CRT_BTREE_RANK_NAME, btree_k) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get rank for btree internal nodes"); - - /* Set return value */ - ret_value=btree_k[type->id]; - -done: - FUNC_LEAVE(ret_value); -} /* end H5B_Kvalue() */ - - -/*------------------------------------------------------------------------- * Function: H5B_load * * Purpose: Loads a B-tree node from the disk. @@ -364,17 +316,17 @@ H5B_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_type, void *udata) assert(type); assert(type->get_sizeof_rkey); - if (NULL==(bt = H5FL_ALLOC(H5B_t,1))) + if (NULL==(bt = H5FL_CALLOC(H5B_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); bt->sizeof_rkey = (type->get_sizeof_rkey) (f, udata); size = H5B_nodesize(f, type, &total_nkey_size, bt->sizeof_rkey); bt->type = type; bt->dirty = FALSE; bt->ndirty = 0; - if (NULL==(bt->page=H5FL_BLK_ALLOC(page,size,0)) || - NULL==(bt->native=H5FL_BLK_ALLOC(native_block,total_nkey_size,0)) || - NULL==(bt->key=H5FL_ARR_ALLOC(H5B_key_t,(size_t)(2*H5B_Kvalue(f,type)+1),0)) || - NULL==(bt->child=H5FL_ARR_ALLOC(haddr_t,(size_t)(2*H5B_Kvalue(f,type)),0))) + if (NULL==(bt->page=H5FL_BLK_MALLOC(page,size)) || + NULL==(bt->native=H5FL_BLK_MALLOC(native_block,total_nkey_size)) || + NULL==(bt->key=H5FL_ARR_MALLOC(H5B_key_t,(size_t)(2*H5F_KVALUE(f,type)+1))) || + NULL==(bt->child=H5FL_ARR_MALLOC(haddr_t,(size_t)(2*H5F_KVALUE(f,type))))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); if (H5F_block_read(f, H5FD_MEM_BTREE, addr, size, dxpl_id, bt->page)<0) HGOTO_ERROR(H5E_BTREE, H5E_READERROR, NULL, "can't read B-tree node"); @@ -398,7 +350,7 @@ H5B_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_type, void *udata) H5F_addr_decode(f, (const uint8_t **) &p, &(bt->right)); /* the child/key pairs */ - for (i = 0; i < 2 * H5B_Kvalue(f, type); i++) { + for (i = 0; i < 2 * H5F_KVALUE(f, type); i++) { bt->key[i].dirty = FALSE; bt->key[i].rkey = p; @@ -413,9 +365,9 @@ H5B_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_type, void *udata) } } - bt->key[2 * H5B_Kvalue(f, type)].dirty = FALSE; - bt->key[2 * H5B_Kvalue(f, type)].rkey = p; - bt->key[2 * H5B_Kvalue(f, type)].nkey = NULL; + bt->key[2 * H5F_KVALUE(f, type)].dirty = FALSE; + bt->key[2 * H5F_KVALUE(f, type)].rkey = p; + bt->key[2 * H5F_KVALUE(f, type)].nkey = NULL; /* Set return value */ ret_value = bt; @@ -675,9 +627,9 @@ H5B_split(H5F_t *f, const H5B_class_t *type, H5B_t *old_bt, haddr_t old_addr, /* * Initialize variables. */ - assert(old_bt->nchildren == 2 * H5B_Kvalue(f, type)); + assert(old_bt->nchildren == 2 * H5F_KVALUE(f, type)); recsize = old_bt->sizeof_rkey + H5F_SIZEOF_ADDR(f); - k = H5B_Kvalue(f, type); + k = H5F_KVALUE(f, type); #ifdef H5B_DEBUG if (H5DEBUG(B)) { @@ -770,7 +722,7 @@ H5B_split(H5F_t *f, const H5B_class_t *type, H5B_t *old_bt, haddr_t old_addr, new_bt->right = old_bt->right; if (H5F_addr_defined(old_bt->right)) { - if (NULL == (tmp_bt = H5AC_find(f, H5AC_BT, old_bt->right, type, udata))) + if (NULL == (tmp_bt = H5AC_find_f(f, H5AC_BT, old_bt->right, type, udata))) HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load right sibling"); tmp_bt->dirty = TRUE; tmp_bt->left = *new_addr_p; @@ -919,7 +871,7 @@ H5B_insert(H5F_t *f, const H5B_class_t *type, haddr_t addr, assert(H5B_INS_RIGHT == my_ins); /* the current root */ - if (NULL == (bt = H5AC_find(f, H5AC_BT, addr, type, udata))) + if (NULL == (bt = H5AC_find_f(f, H5AC_BT, addr, type, udata))) HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to locate root of B-tree"); level = bt->level; if (!lt_key_changed) { @@ -929,7 +881,7 @@ H5B_insert(H5F_t *f, const H5B_class_t *type, haddr_t addr, } /* the new node */ - if (NULL == (bt = H5AC_find(f, H5AC_BT, child, type, udata))) + if (NULL == (bt = H5AC_find_f(f, H5AC_BT, child, type, udata))) HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load new node"); if (!rt_key_changed) { if (!bt->key[bt->nchildren].nkey && @@ -948,7 +900,7 @@ H5B_insert(H5F_t *f, const H5B_class_t *type, haddr_t addr, HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate file space to move root"); /* update the new child's left pointer */ - if (NULL == (bt = H5AC_find(f, H5AC_BT, child, type, udata))) + if (NULL == (bt = H5AC_find_f(f, H5AC_BT, child, type, udata))) HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load new child"); bt->dirty = TRUE; bt->left = old_root; @@ -958,7 +910,7 @@ H5B_insert(H5F_t *f, const H5B_class_t *type, haddr_t addr, * at the new location -QAK */ /* Bring the old root into the cache if it's not already */ - if (NULL == (bt = H5AC_find(f, H5AC_BT, addr, type, udata))) + if (NULL == (bt = H5AC_find_f(f, H5AC_BT, addr, type, udata))) HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load new child"); /* Make certain the old root info is marked as dirty before moving it, */ @@ -1038,7 +990,7 @@ H5B_insert_child(H5F_t *f, const H5B_class_t *type, H5B_t *bt, FUNC_ENTER_NOINIT(H5B_insert_child); assert(bt); - assert(bt->nchildren<2*H5B_Kvalue(f, type)); + assert(bt->nchildren<2*H5F_KVALUE(f, type)); bt->dirty = TRUE; recsize = bt->sizeof_rkey + H5F_SIZEOF_ADDR(f); @@ -1383,7 +1335,7 @@ H5B_insert_helper(H5F_t *f, haddr_t addr, const H5B_class_t *type, /* * If this node is full then split it before inserting the new child. */ - if (bt->nchildren == 2 * H5B_Kvalue(f, type)) { + if (bt->nchildren == 2 * H5F_KVALUE(f, type)) { if (H5B_split(f, type, bt, addr, idx, split_ratios, udata, new_node_p/*out*/)<0) HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, H5B_INS_ERROR, "unable to split node"); @@ -1488,7 +1440,7 @@ H5B_iterate (H5F_t *f, const H5B_class_t *type, H5B_operator_t op, haddr_t addr, assert(H5F_addr_defined(addr)); assert(udata); - if (NULL == (bt=H5AC_find(f, H5AC_BT, addr, type, udata))) + if (NULL == (bt=H5AC_find_f(f, H5AC_BT, addr, type, udata))) HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load B-tree node"); if (bt->level > 0) { /* Keep following the left-most child until we reach a leaf node. */ @@ -1499,8 +1451,8 @@ H5B_iterate (H5F_t *f, const H5B_class_t *type, H5B_operator_t op, haddr_t addr, * We've reached the left-most leaf. Now follow the right-sibling * pointer from leaf to leaf until we've processed all leaves. */ - if (NULL==(child=H5FL_ARR_ALLOC(haddr_t,(size_t)(2*H5B_Kvalue(f,type)),0)) || - NULL==(key=H5MM_malloc((2*H5B_Kvalue(f, type)+1)*type->sizeof_nkey))) + if (NULL==(child=H5FL_ARR_MALLOC(haddr_t,(size_t)(2*H5F_KVALUE(f,type)))) || + NULL==(key=H5MM_malloc((2*H5F_KVALUE(f, type)+1)*type->sizeof_nkey))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); for (cur_addr=addr, ret_value=0; H5F_addr_defined(cur_addr); cur_addr=next_addr) { @@ -1509,7 +1461,7 @@ H5B_iterate (H5F_t *f, const H5B_class_t *type, H5B_operator_t op, haddr_t addr, * leave the B-tree node protected during an application * callback. */ - if (NULL==(bt=H5AC_find (f, H5AC_BT, cur_addr, type, udata))) + if (NULL==(bt=H5AC_find_f (f, H5AC_BT, cur_addr, type, udata))) HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL, "B-tree node"); for (i=0; inchildren; i++) child[i] = bt->child[i]; @@ -1698,13 +1650,13 @@ H5B_remove_helper(H5F_t *f, haddr_t addr, const H5B_class_t *type, bt->ndirty = 0; if (level>0) { if (H5F_addr_defined(bt->left)) { - if (NULL==(sibling=H5AC_find(f, H5AC_BT, bt->left, type, udata))) + if (NULL==(sibling=H5AC_find_f(f, H5AC_BT, bt->left, type, udata))) HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, H5B_INS_ERROR, "unable to unlink node from tree"); sibling->right = bt->right; sibling->dirty = TRUE; } if (H5F_addr_defined(bt->right)) { - if (NULL==(sibling=H5AC_find(f, H5AC_BT, bt->right, type, udata))) + if (NULL==(sibling=H5AC_find_f(f, H5AC_BT, bt->right, type, udata))) HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, H5B_INS_ERROR, "unable to unlink node from tree"); sibling->left = bt->left; sibling->dirty = TRUE; @@ -1862,7 +1814,7 @@ H5B_remove(H5F_t *f, const H5B_class_t *type, haddr_t addr, void *udata) * If the B-tree is now empty then make sure we mark the root node as * being at level zero */ - if (NULL==(bt=H5AC_find(f, H5AC_BT, addr, type, udata))) + if (NULL==(bt=H5AC_find_f(f, H5AC_BT, addr, type, udata))) HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load B-tree root node"); if (0==bt->nchildren && 0!=bt->level) { bt->level = 0; @@ -1915,20 +1867,20 @@ H5B_nodesize(H5F_t *f, const H5B_class_t *type, assert(f); assert(type); assert(sizeof_rkey > 0); - assert(H5B_Kvalue(f, type) > 0); + assert(H5F_KVALUE(f, type) > 0); /* * Total native key size. */ if (total_nkey_size) - *total_nkey_size = (2 * H5B_Kvalue(f, type) + 1) * type->sizeof_nkey; + *total_nkey_size = (2 * H5F_KVALUE(f, type) + 1) * type->sizeof_nkey; /* * Total node size. */ size = (H5B_SIZEOF_HDR(f) + /*node header */ - 2 * H5B_Kvalue(f, type) * H5F_SIZEOF_ADDR(f) + /*child pointers */ - (2 * H5B_Kvalue(f, type) + 1) * sizeof_rkey); /*keys */ + 2 * H5F_KVALUE(f, type) * H5F_SIZEOF_ADDR(f) + /*child pointers */ + (2 * H5F_KVALUE(f, type) + 1) * sizeof_rkey); /*keys */ /* Set return value */ ret_value=size; @@ -1979,19 +1931,19 @@ H5B_copy(H5F_t *f, const H5B_t *old_bt) size = H5B_nodesize(f, old_bt->type, &total_native_keysize, old_bt->sizeof_rkey); /* Allocate memory for the new H5B_t object */ - if (NULL==(new_node = H5FL_ALLOC(H5B_t,0))) + if (NULL==(new_node = H5FL_MALLOC(H5B_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for B-tree root node"); /* Copy the main structure */ HDmemcpy(new_node,old_bt,sizeof(H5B_t)); /* Compute the number of keys in this node */ - nkeys=2*H5B_Kvalue(f,old_bt->type); + nkeys=2*H5F_KVALUE(f,old_bt->type); - if (NULL==(new_node->page=H5FL_BLK_ALLOC(page,size,0)) || - NULL==(new_node->native=H5FL_BLK_ALLOC(native_block,total_native_keysize,0)) || - NULL==(new_node->child=H5FL_ARR_ALLOC(haddr_t,nkeys,0)) || - NULL==(new_node->key=H5FL_ARR_ALLOC(H5B_key_t,(nkeys+1),0))) + if (NULL==(new_node->page=H5FL_BLK_MALLOC(page,size)) || + NULL==(new_node->native=H5FL_BLK_MALLOC(native_block,total_native_keysize)) || + NULL==(new_node->child=H5FL_ARR_MALLOC(haddr_t,nkeys)) || + NULL==(new_node->key=H5FL_ARR_MALLOC(H5B_key_t,(nkeys+1)))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for B-tree root node"); /* Copy the other structures */ @@ -2064,7 +2016,7 @@ H5B_debug(H5F_t *f, haddr_t addr, FILE *stream, int indent, int fwidth, /* * Load the tree node. */ - if (NULL == (bt = H5AC_find(f, H5AC_BT, addr, type, udata))) + if (NULL == (bt = H5AC_find_f(f, H5AC_BT, addr, type, udata))) HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load B-tree node"); /* @@ -2101,7 +2053,7 @@ H5B_debug(H5F_t *f, haddr_t addr, FILE *stream, int indent, int fwidth, HDfprintf(stream, "%*s%-*s %d (%d)\n", indent, "", fwidth, "Number of children (max):", (int) (bt->nchildren), - (int) (2 * H5B_Kvalue(f, type))); + (int) (2 * H5F_KVALUE(f, type))); /* * Print the child addresses @@ -2164,7 +2116,7 @@ H5B_assert(H5F_t *f, haddr_t addr, const H5B_class_t *type, void *udata) } } /* Initialize the queue */ - bt = H5AC_find(f, H5AC_BT, addr, type, udata); + bt = H5AC_find_f(f, H5AC_BT, addr, type, udata); assert(bt); cur = H5MM_calloc(sizeof(struct child_t)); assert (cur); diff --git a/src/H5Bprivate.h b/src/H5Bprivate.h index 3a59d93..d22edcb 100644 --- a/src/H5Bprivate.h +++ b/src/H5Bprivate.h @@ -140,6 +140,4 @@ H5_DLL herr_t H5B_remove(H5F_t *f, const H5B_class_t *type, haddr_t addr, void *udata); H5_DLL herr_t H5B_iterate (H5F_t *f, const H5B_class_t *type, H5B_operator_t op, haddr_t addr, void *udata); -H5_DLL int H5B_Kvalue(H5F_t *f, const H5B_class_t *type); - #endif diff --git a/src/H5D.c b/src/H5D.c index 7485d7e..cab38cd 100644 --- a/src/H5D.c +++ b/src/H5D.c @@ -19,6 +19,7 @@ #include "H5Eprivate.h" /* Error handling */ #include "H5FDprivate.h" /* File drivers */ #include "H5FLprivate.h" /* Free Lists */ +#include "H5FOprivate.h" /* File objects */ #include "H5Gprivate.h" /* Group headers */ #include "H5HLprivate.h" /* Name heap */ #include "H5Iprivate.h" /* IDs */ @@ -64,12 +65,25 @@ static int interface_initialize_g = 0; /* Local functions */ static herr_t H5D_init_interface(void); -static herr_t H5D_alloc_storage (H5F_t *f, H5D_t *dset,H5D_time_alloc_t time_alloc); -static herr_t H5D_init_storage(H5D_t *dataset); -H5D_t * H5D_new(hid_t dcpl_id); +static herr_t H5D_alloc_storage (H5F_t *f, H5D_t *dset,H5D_time_alloc_t time_alloc, + hbool_t update_time, hbool_t full_overwrite); +static herr_t H5D_init_storage(H5D_t *dataset, hbool_t full_overwrite); +static H5D_t * H5D_new(hid_t dcpl_id, hbool_t creating); +static H5D_t * H5D_create(H5G_entry_t *loc, const char *name, const H5T_t *type, + const H5S_t *space, hid_t dcpl_id); +static H5D_t * H5D_open_oid(H5G_entry_t *ent); +static herr_t H5D_read(H5D_t *dataset, const H5T_t *mem_type, + const H5S_t *mem_space, const H5S_t *file_space, + hid_t dset_xfer_plist, void *buf/*out*/); +static herr_t H5D_write(H5D_t *dataset, const H5T_t *mem_type, + const H5S_t *mem_space, const H5S_t *file_space, + hid_t dset_xfer_plist, const void *buf); static herr_t H5D_fill(const void *fill, const H5T_t *fill_type, void *buf, const H5T_t *buf_type, const H5S_t *space); static herr_t H5D_get_space_status(H5D_t *dset, H5D_space_status_t *allocation); +static hsize_t H5D_get_storage_size(H5D_t *dset); +static haddr_t H5D_get_offset(H5D_t *dset); +static herr_t H5D_set_extent(H5D_t *dataset, const hsize_t *size); /* Declare a free list to manage the H5D_t struct */ H5FL_DEFINE_STATIC(H5D_t); @@ -86,6 +100,9 @@ H5FL_BLK_DEFINE_STATIC(vlen_vl_buf); /* Declare a free list to manage other blocks of VL data */ H5FL_BLK_DEFINE_STATIC(vlen_fl_buf); +/* Define a static "default" dataset structure to use to initialize new datasets */ +static H5D_t H5D_def_dset; + /*------------------------------------------------------------------------- * Function: H5D_init @@ -188,6 +205,7 @@ H5D_init_interface(void) H5O_efl_t efl = H5D_CRT_EXT_FILE_LIST_DEF; H5O_pline_t pline = H5D_CRT_DATA_PIPELINE_DEF; + H5P_genplist_t *def_dcpl; /* Default Dataset Creation Property list */ size_t nprops; /* Number of properties */ herr_t ret_value = SUCCEED; /* Return value */ @@ -202,7 +220,7 @@ H5D_init_interface(void) assert(H5P_CLS_DATASET_XFER_g!=(-1)); /* Get the pointer to the dataset transfer class */ - if (NULL == (xfer_pclass = H5I_object_verify(H5P_CLS_DATASET_XFER_g, H5I_GENPROP_CLS))) + if (NULL == (xfer_pclass = H5I_object(H5P_CLS_DATASET_XFER_g))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list class"); /* Get the number of properties in the class */ @@ -282,7 +300,7 @@ H5D_init_interface(void) assert(H5P_CLS_DATASET_CREATE_g != -1); /* Get the pointer to the dataset creation class */ - if(NULL == (crt_pclass = H5I_object_verify(H5P_CLS_DATASET_CREATE_g, H5I_GENPROP_CLS))) + if(NULL == (crt_pclass = H5I_object(H5P_CLS_DATASET_CREATE_g))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list class"); /* Get the number of properties in the class */ @@ -331,6 +349,37 @@ H5D_init_interface(void) HGOTO_ERROR (H5E_PLIST, H5E_CANTREGISTER, FAIL, "can't register default property list"); } /* end if */ + /* Reset the "default dataset" information */ + HDmemset(&H5D_def_dset,0,sizeof(H5D_t)); + + /* Get the default dataset cretion property list values and initialize the + * default dataset with them. + */ + if (NULL == (def_dcpl = H5I_object(H5P_LST_DATASET_CREATE_g))) + HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, NULL, "can't get default dataset creation property list"); + + /* Set up the default allocation time information */ + if(H5P_get(def_dcpl, H5D_CRT_ALLOC_TIME_NAME, &H5D_def_dset.alloc_time) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve space allocation time"); + if(H5D_def_dset.alloc_time==H5D_ALLOC_TIME_DEFAULT) + H5D_def_dset.alloc_time=H5D_ALLOC_TIME_LATE; + + /* Get the default external file list information */ + if(H5P_get(def_dcpl, H5D_CRT_EXT_FILE_LIST_NAME, &H5D_def_dset.efl) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve external file list"); + + /* Get the default data storage method */ + if(H5P_get(def_dcpl, H5D_CRT_LAYOUT_NAME, &H5D_def_dset.layout.type) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve layout"); + + /* Get the default fill value time */ + if (H5P_get(def_dcpl, H5D_CRT_FILL_TIME_NAME, &H5D_def_dset.fill_time) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve fill time"); + + /* Get the default fill value */ + if (H5P_get(def_dcpl, H5D_CRT_FILL_VALUE_NAME, &H5D_def_dset.fill) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve fill value"); + done: FUNC_LEAVE(ret_value); } @@ -404,25 +453,21 @@ H5D_crt_copy(hid_t new_plist_id, hid_t old_plist_id, void UNUSED *copy_data) FUNC_ENTER_NOAPI(H5D_crt_copy, FAIL); /* Verify property list ID */ - if (NULL == (new_plist = H5P_object_verify(new_plist_id,H5P_DATASET_CREATE))) + if (NULL == (new_plist = H5I_object(new_plist_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list"); - if (NULL == (old_plist = H5P_object_verify(old_plist_id,H5P_DATASET_CREATE))) + if (NULL == (old_plist = H5I_object(old_plist_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list"); /* Get the fill value, external file list, and data pipeline properties * from the old property list */ - HDmemset(&src_fill,0,sizeof(H5O_fill_t)); if(H5P_get(old_plist, H5D_CRT_FILL_VALUE_NAME, &src_fill) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get fill value"); - HDmemset(&src_efl,0,sizeof(H5O_efl_t)); if(H5P_get(old_plist, H5D_CRT_EXT_FILE_LIST_NAME, &src_efl) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get external file list"); - HDmemset(&src_pline,0,sizeof(H5O_pline_t)); if(H5P_get(old_plist, H5D_CRT_DATA_PIPELINE_NAME, &src_pline) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get pipeline"); /* Make copies of fill value, external file list, and data pipeline */ - HDmemset(&dst_fill,0,sizeof(H5O_fill_t)); if(src_fill.buf && (NULL==H5O_copy(H5O_FILL, &src_fill, &dst_fill))) { HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't copy fill value"); } @@ -433,7 +478,6 @@ H5D_crt_copy(hid_t new_plist_id, hid_t old_plist_id, void UNUSED *copy_data) HDmemset(&dst_efl,0,sizeof(H5O_efl_t)); if(NULL==H5O_copy(H5O_EFL, &src_efl, &dst_efl)) HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't copy external file list"); - HDmemset(&dst_pline,0,sizeof(H5O_pline_t)); if(NULL==H5O_copy(H5O_PLINE, &src_pline, &dst_pline)) HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't copy data pipeline"); @@ -481,18 +525,15 @@ H5D_crt_close(hid_t dcpl_id, void UNUSED *close_data) FUNC_ENTER_NOAPI(H5D_crt_close, FAIL); /* Check arguments */ - if (NULL == (plist = H5P_object_verify(dcpl_id,H5P_DATASET_CREATE))) + if (NULL == (plist = H5I_object(dcpl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list"); /* Get the fill value, external file list, and data pipeline properties * from the old property list */ - HDmemset(&fill,0,sizeof(H5O_fill_t)); if(H5P_get(plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get fill value"); - HDmemset(&efl,0,sizeof(H5O_efl_t)); if(H5P_get(plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get external file list"); - HDmemset(&pline,0,sizeof(H5O_pline_t)); if(H5P_get(plist, H5D_CRT_DATA_PIPELINE_NAME, &pline) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get pipeline"); @@ -540,7 +581,7 @@ H5D_xfer_create(hid_t dxpl_id, void UNUSED *create_data) FUNC_ENTER_NOAPI(H5D_xfer_create, FAIL); /* Check arguments */ - if (NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER))) + if (NULL == (plist = H5I_object(dxpl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list"); /* Get the driver information */ @@ -634,7 +675,7 @@ H5D_xfer_close(hid_t dxpl_id, void UNUSED *close_data) FUNC_ENTER_NOAPI(H5D_xfer_close, FAIL); /* Check arguments */ - if (NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER))) + if (NULL == (plist = H5I_object(dxpl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list"); if(H5P_get(plist, H5D_XFER_VFL_ID_NAME, &driver_id)<0) @@ -717,8 +758,9 @@ H5Dcreate(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id, HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); if(H5P_DEFAULT == plist_id) plist_id = H5P_DATASET_CREATE_DEFAULT; - if(TRUE != H5P_isa_class(plist_id, H5P_DATASET_CREATE)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not dataset create property list"); + else + if(TRUE != H5P_isa_class(plist_id, H5P_DATASET_CREATE)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not dataset create property list"); /* build and open the new dataset */ if (NULL == (new_dset = H5D_create(loc, name, type, space, plist_id))) @@ -728,6 +770,10 @@ H5Dcreate(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id, if ((ret_value = H5I_register(H5I_DATASET, new_dset)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register dataset"); + /* Add the dataset to the list of opened objects in the file */ + if(H5FO_insert(new_dset->ent.file,new_dset->ent.header,ret_value)<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "can't insert dataset into list of open objects"); + done: if(ret_value<0) { if(new_dset!=NULL) @@ -762,7 +808,7 @@ hid_t H5Dopen(hid_t loc_id, const char *name) { H5G_entry_t *loc = NULL; /*location holding the dataset */ - H5D_t *dataset = NULL; /*the dataset */ + H5G_entry_t ent; /*dataset symbol table entry */ hid_t ret_value; FUNC_ENTER_API(H5Dopen, FAIL); @@ -774,20 +820,15 @@ H5Dopen(hid_t loc_id, const char *name) if (!name || !*name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name"); - /* Find the dataset */ - if (NULL == (dataset = H5D_open(loc, name))) - HGOTO_ERROR(H5E_DATASET, H5E_NOTFOUND, FAIL, "dataset not found"); - - /* Create an atom for the dataset */ - if ((ret_value = H5I_register(H5I_DATASET, dataset)) < 0) + /* Find the dataset object */ + if (H5G_find(loc, name, NULL, &ent) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_NOTFOUND, FAIL, "not found"); + + /* Open the dataset */ + if ((ret_value = H5D_open(&ent)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "can't register dataset"); done: - if(ret_value<0) { - if(dataset!=NULL) - H5D_close(dataset); - } /* end if */ - FUNC_LEAVE(ret_value); } @@ -874,7 +915,7 @@ H5Dget_space(hid_t dset_id) HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset"); /* Read the data space message and return a data space object */ - if (NULL==(space=H5D_get_space (dset))) + if (NULL==(space=H5S_copy (dset->space))) HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to get data space"); /* Create an atom */ @@ -892,42 +933,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5D_get_space - * - * Purpose: Returns the data space associated with the dataset. - * - * Return: Success: Ptr to a copy of the data space. - * - * Failure: NULL - * - * Programmer: Robb Matzke - * Tuesday, August 25, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -H5S_t * -H5D_get_space(H5D_t *dset) -{ - H5S_t *space; - H5S_t *ret_value; /* Return value */ - - FUNC_ENTER_NOAPI(H5D_get_space, NULL); - assert(dset); - - if (NULL==(space=H5S_read(&(dset->ent)))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to load space info from dataset header"); - - /* Set return value */ - ret_value=space; - -done: - FUNC_LEAVE(ret_value); -} - - -/*------------------------------------------------------------------------- * Function: H5Dget_space_status * * Purpose: Returns the status of data space allocation. @@ -981,7 +986,7 @@ done: */ static herr_t H5D_get_space_status(H5D_t *dset, H5D_space_status_t *allocation) { - H5S_t *space=NULL; /* Dataset's dataspace */ + H5S_t *space; /* Dataset's dataspace */ hsize_t space_allocated; /* The number of bytes allocated for chunks */ hssize_t total_elem; /* The total number of elements in dataspace */ size_t type_size; /* The size of the datatype for the dataset */ @@ -990,9 +995,11 @@ static herr_t H5D_get_space_status(H5D_t *dset, H5D_space_status_t *allocation) FUNC_ENTER_NOINIT(H5D_get_space_status); + assert(dset); + /* Get the dataset's dataspace */ - if((space=H5D_get_space(dset))==NULL) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get dataspace"); + space=dset->space; + assert(space); /* Get the total number of elements in dataset's dataspace */ if((total_elem=H5S_get_simple_extent_npoints(space))<0) @@ -1022,8 +1029,6 @@ static herr_t H5D_get_space_status(H5D_t *dset, H5D_space_status_t *allocation) } /* end else */ done: - if(space) - H5S_close(space); FUNC_LEAVE(ret_value); } @@ -1247,9 +1252,9 @@ H5Dread(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, /* Get the default dataset transfer property list if the user didn't provide one */ if (H5P_DEFAULT == plist_id) plist_id= H5P_DATASET_XFER_DEFAULT; - - if (TRUE!=H5P_isa_class(plist_id,H5P_DATASET_XFER)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms"); + else + if (TRUE!=H5P_isa_class(plist_id,H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms"); if (!buf) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no output buffer"); @@ -1338,9 +1343,9 @@ H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, /* Get the default dataset transfer property list if the user didn't provide one */ if (H5P_DEFAULT == plist_id) plist_id= H5P_DATASET_XFER_DEFAULT; - - if (TRUE!=H5P_isa_class(plist_id,H5P_DATASET_XFER)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms"); + else + if (TRUE!=H5P_isa_class(plist_id,H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms"); if (!buf) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no output buffer"); @@ -1416,8 +1421,8 @@ done: * *------------------------------------------------------------------------- */ -H5D_t * -H5D_new(hid_t dcpl_id) +static H5D_t * +H5D_new(hid_t dcpl_id, hbool_t creating) { H5P_genplist_t *plist; /* Property list created */ H5D_t *new_dset = NULL; /* New dataset object */ @@ -1425,16 +1430,31 @@ H5D_new(hid_t dcpl_id) FUNC_ENTER_NOAPI(H5D_new, NULL); - if (NULL==(new_dset = H5FL_ALLOC(H5D_t,1))) + if (NULL==(new_dset = H5FL_MALLOC(H5D_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - if(H5P_DEFAULT == dcpl_id) - dcpl_id = H5P_DATASET_CREATE_DEFAULT; - /* Get the property list */ - if (NULL == (plist = H5P_object_verify(dcpl_id,H5P_DATASET_CREATE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a property list"); + /* If we are using the default dataset creation property list, during creation + * don't bother to copy it, just increment the reference count + */ + if(creating && dcpl_id == H5P_DATASET_CREATE_DEFAULT) { + /* Copy the default dataset information */ + HDmemcpy(new_dset,&H5D_def_dset,sizeof(H5D_t)); + + if(H5I_inc_ref(dcpl_id)<0) + HGOTO_ERROR (H5E_DATASET, H5E_CANTINC, NULL, "Can't increment default DCPL ID"); + new_dset->dcpl_id = dcpl_id; + } /* end if */ + else { + /* Reset the dataset information */ + HDmemset(new_dset,0,sizeof(H5D_t)); + + /* Get the property list */ + if (NULL == (plist = H5I_object(dcpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a property list"); + + new_dset->dcpl_id = H5P_copy_plist(plist); + } /* end else */ - new_dset->dcpl_id = H5P_copy_plist(plist); new_dset->ent.header = HADDR_UNDEF; /* Set return value */ @@ -1442,8 +1462,11 @@ H5D_new(hid_t dcpl_id) done: if(ret_value==NULL) { - if(new_dset!=NULL) + if(new_dset!=NULL) { + if(new_dset->dcpl_id!=0) + H5I_dec_ref(new_dset->dcpl_id); H5FL_FREE(H5D_t,new_dset); + } /* end if */ } /* end if */ FUNC_LEAVE(ret_value); @@ -1451,7 +1474,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5D_update_entry_cache + * Function: H5D_update_entry_info * * Purpose: Create and fill an H5G_entry_t object for insertion into * the group LOC. @@ -1471,72 +1494,86 @@ done: * *------------------------------------------------------------------------- */ -herr_t -H5D_update_entry_cache(H5F_t *file, H5G_entry_t *ent, H5G_entry_t *loc, - const char *name, const H5S_t *space, - H5P_genplist_t *plist, H5O_layout_t *layout, H5T_t *type, - hbool_t allocate_header, haddr_t header) +static herr_t +H5D_update_entry_info(H5F_t *file, H5D_t *dset, H5P_genplist_t *plist) { - H5O_pline_t dcpl_pline; - H5D_alloc_time_t alloc_time; size_t ohdr_size = H5D_MINHDR_SIZE; /* Size of dataset's object header */ + H5G_entry_t *ent=NULL; /* Dataset's group entry */ + H5O_layout_t *layout; /* Dataset's layout information */ + H5T_t *type; /* Dataset's datatype */ + H5S_t *space; /* Dataset's dataspace */ + H5D_alloc_time_t alloc_time;/* Dataset's allocation time */ + H5O_efl_t *efl; /* Dataset's external file list */ /* fill value variables */ H5D_fill_time_t fill_time; - H5O_fill_t fill_prop = { NULL, 0, NULL }; + H5O_fill_t *fill_prop; /* Pointer to dataset's fill value information */ H5O_fill_new_t fill = { NULL, 0, NULL, H5D_ALLOC_TIME_LATE, H5D_FILL_TIME_ALLOC, TRUE }; H5D_fill_value_t fill_status; + H5O_t *oh=NULL; /* Pointer to dataset's object header */ + /* return code */ herr_t ret_value = SUCCEED; - FUNC_ENTER_NOAPI(H5D_update_entry_cache, FAIL); + FUNC_ENTER_NOAPI(H5D_update_entry_info, FAIL); + + /* Sanity checking */ + assert(file); + assert(dset); + /* Pick up former parameters */ + ent=&dset->ent; + layout=&dset->layout; + type=dset->type; + space=dset->space; + alloc_time=dset->alloc_time; + efl=&dset->efl; + + /* Add the dataset's raw data size to the size of the header, if the raw data will be stored as compact */ if (layout->type == H5D_COMPACT) ohdr_size += layout->size; - /* If TRUE, then allocate the space in the file for the header */ - if (allocate_header) { - /* Create (open for write access) an object header */ - if (H5O_create(file, ohdr_size, ent) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, - "unable to create dataset object header"); - } else { - /* - * Just initialize the header to the specified address and open - * it for us - */ - HDmemset(ent, 0, sizeof(H5G_entry_t)); + /* Create (open for write access) an object header */ + if (H5O_create(file, ohdr_size, ent) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create dataset object header"); - if (H5O_init(file, ohdr_size, ent, header) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, - "unable to initialize dataset object header"); - } + /* Get a pointer to the object header itself */ + if((oh=H5O_protect(ent))==NULL) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to protect dataset object header"); - /* - * Retrieve properties of fill value and others. Copy them into new fill - * value struct. Convert the fill value to the dataset type and write - * the message - */ - if (H5P_get(plist, H5D_CRT_ALLOC_TIME_NAME, &alloc_time) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve space allocation time"); + /* Point at dataset's copy, to cache it for later */ + fill_prop=&dset->fill; + fill_time=dset->fill_time; - if (H5P_get(plist, H5D_CRT_FILL_TIME_NAME, &fill_time) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve fill time"); + /* Check if dataset has non-default creation property list */ + if(dset->dcpl_id!=H5P_DATASET_CREATE_DEFAULT) { + /* + * Retrieve properties of fill value and others. Copy them into new fill + * value struct. Convert the fill value to the dataset type and write + * the message + */ + if (H5P_get(plist, H5D_CRT_FILL_TIME_NAME, &fill_time) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve fill time"); + dset->fill_time=fill_time; /* Cache this for later */ - if (H5P_fill_value_defined(plist, &fill_status) < 0) + if(fill_time==H5D_FILL_TIME_NEVER && H5T_detect_class(type, H5T_VLEN)) + HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "Dataset doesn't support VL datatype when fill value is not defined"); + + /* Get the fill value information from the property list */ + if (H5P_get(plist, H5D_CRT_FILL_VALUE_NAME, fill_prop) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve fill value"); + } /* end if */ + + if (H5P_is_fill_value_defined(fill_prop, &fill_status) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't tell if fill value defined"); if (fill_status == H5D_FILL_VALUE_DEFAULT || fill_status == H5D_FILL_VALUE_USER_DEFINED) { - if (H5P_get(plist, H5D_CRT_FILL_VALUE_NAME, &fill_prop) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve fill value"); - - if (H5O_copy(H5O_FILL, &fill_prop, &fill) == NULL) + if (H5O_copy(H5O_FILL, fill_prop, &fill) == NULL) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT,FAIL, "unable to copy fill value"); - if (fill_prop.buf && fill_prop.size > 0 && H5O_fill_convert(&fill, type) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, - "unable to convert fill value to dataset type"); + if (fill_prop->buf && fill_prop->size > 0 && H5O_fill_convert(&fill, type) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to convert fill value to dataset type"); fill.fill_defined = TRUE; } else if (fill_status == H5D_FILL_VALUE_UNDEFINED) { @@ -1544,8 +1581,7 @@ H5D_update_entry_cache(H5F_t *file, H5G_entry_t *ent, H5G_entry_t *loc, fill.type = fill.buf = NULL; fill.fill_defined = FALSE; } else { - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, - "unable to determine if fill value is defined"); + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to determine if fill value is defined"); } fill.alloc_time = alloc_time; @@ -1555,79 +1591,51 @@ H5D_update_entry_cache(H5F_t *file, H5G_entry_t *ent, H5G_entry_t *loc, HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT,FAIL, "unable to create dataset"); /* Write new fill value message */ - if (H5O_modify(ent, H5O_FILL_NEW, 0, H5O_FLAG_CONSTANT, &fill) < 0) + if (H5O_append(file, oh, H5O_FILL_NEW, H5O_FLAG_CONSTANT, &fill) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update fill value header message"); - H5O_reset(H5O_FILL, &fill_prop); - if (fill.buf && H5O_copy(H5O_FILL, &fill, &fill_prop) == NULL) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT,FAIL,"unable to copy fill value"); + /* If there is valid information for the old fill value struct, update it */ + if (fill.buf) { + /* Clear any previous values */ + H5O_reset(H5O_FILL, fill_prop); - H5O_reset(H5O_FILL_NEW, &fill); + /* Copy new fill value information to old fill value struct */ + if(H5O_copy(H5O_FILL, &fill, fill_prop) == NULL) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT,FAIL,"unable to copy fill value"); - /* Write old fill value */ - if (fill_prop.buf && H5O_modify(ent, H5O_FILL, 0, H5O_FLAG_CONSTANT, &fill_prop) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, - "unable to update fill value header message"); + /* Write old fill value */ + if (fill_prop->buf && H5O_append(file, oh, H5O_FILL, H5O_FLAG_CONSTANT, fill_prop) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update fill value header message"); - if (H5P_set(plist, H5D_CRT_FILL_VALUE_NAME, &fill_prop) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set fill value"); + /* Update dataset creation property */ + if (H5P_set(plist, H5D_CRT_FILL_VALUE_NAME, fill_prop) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set fill value"); + } /* end if */ /* Update the type and space header messages */ - if (H5O_modify(ent, H5O_DTYPE, 0, H5O_FLAG_CONSTANT | H5O_FLAG_SHARED, type) < 0 || - H5S_modify(ent, space) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, - "unable to update type or space header messages"); + if (H5O_append(file, oh, H5O_DTYPE, H5O_FLAG_CONSTANT | H5O_FLAG_SHARED, type) < 0 || + H5S_append(file, oh, space) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update type or space header messages"); - /* Update the filters message */ - if (H5P_get(plist, H5D_CRT_DATA_PIPELINE_NAME, &dcpl_pline) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve pipeline filter"); - - if (dcpl_pline.nfilters > 0 && - H5O_modify(ent, H5O_PLINE, 0, H5O_FLAG_CONSTANT, &dcpl_pline) < 0) - HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update filter header message"); - - /* Add a modification time message. */ - if (H5O_touch(ent, TRUE) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, - "unable to update modification time message"); - - /* Give the dataset a name */ - if (H5G_insert(loc, name, ent) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to name dataset"); + /* Update the filters message, if this is a chunked dataset */ + if(layout->type==H5D_CHUNKED) { + H5O_pline_t pline; /* Chunked data I/O pipeline info */ -done: - FUNC_LEAVE(ret_value); -} + if (H5P_get(plist, H5D_CRT_DATA_PIPELINE_NAME, &pline) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve pipeline filter"); - -/*------------------------------------------------------------------------- - * Function: H5D_update_external_storage_cache - * - * Purpose: Update the external cache if the dataset uses external - * files. - * - * This code was originally found at the end of H5D_create() - * but was placed here for general use. - * - * Return: Success: SUCCEED - * Failure: FAIL - * - * Errors: - * - * Programmer: Bill Wendling - * Thursday, October 31, 2002 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5D_update_external_storage_cache(H5F_t *file, H5G_entry_t *ent, - H5O_efl_t *efl, H5O_layout_t *layout) -{ - herr_t ret_value = SUCCEED; + if (pline.nfilters > 0 && + H5O_append(file, oh, H5O_PLINE, H5O_FLAG_CONSTANT, &pline) < 0) + HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update filter header message"); + } /* end if */ - FUNC_ENTER_NOAPI(H5D_update_external_storage_cache, FAIL); + /* + * Allocate storage if space allocate time is early; otherwise delay + * allocation until later. + */ + if (alloc_time == H5D_ALLOC_TIME_EARLY) + if (H5D_alloc_storage(file, dset, H5D_ALLOC_CREATE, FALSE, FALSE) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize storage"); /* Update external storage message */ if (efl->nused > 0) { @@ -1639,13 +1647,11 @@ H5D_update_external_storage_cache(H5F_t *file, H5G_entry_t *ent, if (H5HL_create(file, heap_size, &efl->heap_addr/*out*/) < 0 || H5HL_insert(file, efl->heap_addr, 1, "") == (size_t)(-1)) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, - "unable to create external file list name heap"); + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create external file list name heap"); for (i = 0; i < efl->nused; ++i) { size_t offset = H5HL_insert(file, efl->heap_addr, - HDstrlen(efl->slot[i].name) + 1, - efl->slot[i].name); + HDstrlen(efl->slot[i].name) + 1, efl->slot[i].name); assert(0 == efl->slot[i].name_offset); @@ -1655,16 +1661,26 @@ H5D_update_external_storage_cache(H5F_t *file, H5G_entry_t *ent, efl->slot[i].name_offset = offset; } - if (H5O_modify(ent, H5O_EFL, 0, H5O_FLAG_CONSTANT, efl) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, - "unable to update external file list message"); + if (H5O_append(file, oh, H5O_EFL, H5O_FLAG_CONSTANT, efl) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update external file list message"); } /* Update layout message */ - if (H5D_COMPACT != layout->type && H5O_modify(ent, H5O_LAYOUT, 0, 0, layout) < 0) + /* (Don't make layout message constant yet, since space may not be allocated) */ + /* Note: this is relying on H5D_alloc_storage not calling H5O_modify during dataset creation */ + if (H5D_COMPACT != layout->type && H5O_append(file, oh, H5O_LAYOUT, 0, layout) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update layout"); + /* Add a modification time message. */ + if (H5O_touch_oh(file, oh, TRUE) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update modification time message"); + done: + /* Release pointer to object header itself */ + if(ent!=NULL && oh!=NULL) + if(H5O_unprotect(ent,oh)<0) + HDONE_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to unprotect dataset object header"); + FUNC_LEAVE(ret_value); } @@ -1726,7 +1742,7 @@ done: * *------------------------------------------------------------------------- */ -H5D_t * +static H5D_t * H5D_create(H5G_entry_t *loc, const char *name, const H5T_t *type, const H5S_t *space, hid_t dcpl_id) { @@ -1736,16 +1752,10 @@ H5D_create(H5G_entry_t *loc, const char *name, const H5T_t *type, hsize_t comp_data_size; unsigned u; hsize_t max_dim[H5O_LAYOUT_NDIMS]={0}; - H5O_efl_t efl; - H5F_t *f = NULL; - H5O_pline_t dcpl_pline; - H5D_layout_t dcpl_layout; + H5F_t *file; int chunk_ndims = 0; hsize_t chunk_size[32]={0}; - H5D_alloc_time_t alloc_time; - H5D_fill_time_t fill_time; - H5P_genplist_t *plist; /* Property list */ - H5P_genplist_t *new_plist; /* New Property list */ + H5P_genplist_t *new_plist=NULL; /* New Property list */ FUNC_ENTER_NOAPI(H5D_create, NULL); @@ -1755,97 +1765,105 @@ H5D_create(H5G_entry_t *loc, const char *name, const H5T_t *type, assert (type); assert (space); - /* Get property list object */ - if (NULL == (plist = H5P_object_verify(dcpl_id,H5P_DATASET_CREATE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "can't get dataset creation property list"); - - if(H5P_get(plist, H5D_CRT_DATA_PIPELINE_NAME, &dcpl_pline) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve pipeline filter"); - if(H5P_get(plist, H5D_CRT_LAYOUT_NAME, &dcpl_layout) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve layout"); - if(dcpl_pline.nfilters > 0 && H5D_CHUNKED != dcpl_layout) - HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, NULL, "filters can only be used with chunked layout"); - if(H5P_get(plist, H5D_CRT_ALLOC_TIME_NAME, &alloc_time) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve space allocation time"); - - /* Check if the alloc_time is the default and set it accordingly */ - if(alloc_time==H5D_ALLOC_TIME_DEFAULT) { - switch(dcpl_layout) { - case H5D_COMPACT: - alloc_time=H5D_ALLOC_TIME_EARLY; - break; - - case H5D_CONTIGUOUS: - alloc_time=H5D_ALLOC_TIME_LATE; - break; - - case H5D_CHUNKED: - alloc_time=H5D_ALLOC_TIME_INCR; - break; - - default: - HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, NULL, "not implemented yet"); - } /* end switch */ - } /* end if */ - - /* Don't allow compact datasets to allocate space later */ - if(dcpl_layout==H5D_COMPACT && alloc_time!=H5D_ALLOC_TIME_EARLY) - HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, NULL, "compact dataset doesn't support late space allocation"); - - /* What file is the dataset being added to? */ - if (NULL==(f=H5G_insertion_file(loc, name))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to locate insertion point"); - - /* If MPIO or MPIPOSIX is used, no filter support yet. */ - if((IS_H5FD_MPIO(f) || IS_H5FD_MPIPOSIX(f)) && dcpl_pline.nfilters > 0) - HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, NULL, "Parallel I/O does not support filters yet"); - - /* Check if this dataset is going into a parallel file and set space allocation time */ - if(IS_H5FD_MPIO(f) || IS_H5FD_MPIPOSIX(f)) - alloc_time=H5D_ALLOC_TIME_EARLY; - - if(H5P_get(plist, H5D_CRT_FILL_TIME_NAME, &fill_time) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve fill time"); - - if(fill_time==H5D_FILL_TIME_NEVER && H5T_detect_class(type, H5T_VLEN)) - HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, NULL, "Dataset doesn't support VL datatype when fill value is not defined"); - - /* Initialize the dataset object */ - if(NULL == (new_dset = H5D_new(dcpl_id))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - /* Check if the datatype is "sensible" for use in a dataset */ if(H5T_is_sensible(type)!=TRUE) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "datatype is not sensible"); + /* Initialize the dataset object */ + if(NULL == (new_dset = H5D_new(dcpl_id,TRUE))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + /* Copy datatype for dataset */ if((new_dset->type = H5T_copy(type, H5T_COPY_ALL))==NULL) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy datatype"); + /* What file is the dataset being added to? */ + if (NULL==(file=H5G_insertion_file(loc, name))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to locate insertion point"); + /* Mark any VL datatypes as being on disk now */ - if (H5T_vlen_mark(new_dset->type, f, H5T_VLEN_DISK)<0) + if (H5T_vlen_mark(new_dset->type, file, H5T_VLEN_DISK)<0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "invalid VL location"); - /* Get new dataset's property list object */ - if (NULL == (new_plist = H5I_object(new_dset->dcpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "can't get dataset creation property list"); + /* Copy dataspace for dataset */ + if((new_dset->space = H5S_copy(space))==NULL) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy dataspace"); + + /* Set the dataset's dataspace to 'all' selection */ + if(H5S_select_all(new_dset->space,1)<0) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTSET, NULL, "unable to set all selection"); + + /* Check if the dataset has a non-default DCPL & get important values, if so */ + if(new_dset->dcpl_id!=H5P_DATASET_CREATE_DEFAULT) { + H5D_layout_t dcpl_layout; /* Dataset's layout information */ + H5O_pline_t dcpl_pline; /* Dataset's I/O pipeline information */ + H5D_alloc_time_t alloc_time; /* Dataset's allocation time */ + + /* Get new dataset's property list object */ + if (NULL == (new_plist = H5I_object(new_dset->dcpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "can't get dataset creation property list"); + + if(H5P_get(new_plist, H5D_CRT_DATA_PIPELINE_NAME, &dcpl_pline) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve pipeline filter"); + if(H5P_get(new_plist, H5D_CRT_LAYOUT_NAME, &dcpl_layout) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve layout"); + if(dcpl_pline.nfilters > 0 && H5D_CHUNKED != dcpl_layout) + HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, NULL, "filters can only be used with chunked layout"); + if(H5P_get(new_plist, H5D_CRT_ALLOC_TIME_NAME, &alloc_time) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve space allocation time"); + + /* Check if the alloc_time is the default and set it accordingly */ + if(alloc_time==H5D_ALLOC_TIME_DEFAULT) { + switch(dcpl_layout) { + case H5D_COMPACT: + alloc_time=H5D_ALLOC_TIME_EARLY; + break; + + case H5D_CONTIGUOUS: + alloc_time=H5D_ALLOC_TIME_LATE; + break; + + case H5D_CHUNKED: + alloc_time=H5D_ALLOC_TIME_INCR; + break; + + default: + HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, NULL, "not implemented yet"); + } /* end switch */ + } /* end if */ - /* Set the alloc_time for the dataset, in case the default was used */ - if(H5P_set(new_plist, H5D_CRT_ALLOC_TIME_NAME, &alloc_time) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "can't set allocation time"); + /* Don't allow compact datasets to allocate space later */ + if(dcpl_layout==H5D_COMPACT && alloc_time!=H5D_ALLOC_TIME_EARLY) + HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, NULL, "compact dataset doesn't support late space allocation"); - if(H5P_get(new_plist, H5D_CRT_CHUNK_DIM_NAME, &chunk_ndims) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve layout"); + /* Set the alloc_time for the dataset, in case the default was used */ + new_dset->alloc_time=alloc_time; + + /* If MPIO or MPIPOSIX is used, no filter support yet. */ + if((IS_H5FD_MPIO(file) || IS_H5FD_MPIPOSIX(file)) && dcpl_pline.nfilters > 0) + HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, NULL, "Parallel I/O does not support filters yet"); + + /* Chunked datasets are non-default, so retrieve their info here */ + if(H5P_get(new_plist, H5D_CRT_CHUNK_DIM_NAME, &chunk_ndims) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve layout"); - if(H5P_get(new_plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve external file list"); + /* Get the dataset's external file list information */ + if(H5P_get(new_plist, H5D_CRT_EXT_FILE_LIST_NAME, &new_dset->efl) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve external file list"); - /* Total raw data size */ - if(H5P_get(new_plist, H5D_CRT_LAYOUT_NAME, &(new_dset->layout.type)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve layout"); - new_dset->layout.ndims = H5S_get_simple_extent_ndims(space) + 1; + /* Get the dataset's data storage method */ + if(H5P_get(new_plist, H5D_CRT_LAYOUT_NAME, &(new_dset->layout.type)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve layout"); + } /* end if */ + + /* Check if this dataset is going into a parallel file and set space allocation time */ + if(IS_H5FD_MPIO(file) || IS_H5FD_MPIPOSIX(file)) + new_dset->alloc_time=H5D_ALLOC_TIME_EARLY; + + /* Set up layout information */ + new_dset->layout.ndims = H5S_get_simple_extent_ndims(new_dset->space) + 1; assert((unsigned)(new_dset->layout.ndims) <= NELMTS(new_dset->layout.dim)); - new_dset->layout.dim[new_dset->layout.ndims-1] = H5T_get_size(new_dset->type); + new_dset->layout.dim[new_dset->layout.ndims-1] = H5T_get_size(new_dset->type); new_dset->layout.addr = HADDR_UNDEF; /* Initialize to no address */ switch (new_dset->layout.type) { @@ -1855,15 +1873,15 @@ H5D_create(H5G_entry_t *loc, const char *name, const H5T_t *type, * Also, only the slowest varying dimension of a simple data space * can be extendible. */ - if ((ndims=H5S_get_simple_extent_dims(space, new_dset->layout.dim, max_dim))<0) + if ((ndims=H5S_get_simple_extent_dims(new_dset->space, new_dset->layout.dim, max_dim))<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to initialize contiguous storage"); for (i=1; inew_dset->layout.dim[i]) HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, NULL, "only the first dimension can be extendible"); } - if (efl.nused>0) { - hsize_t max_points = H5S_get_npoints_max (space); - hsize_t max_storage = H5O_efl_total_size (&efl); + if (new_dset->efl.nused>0) { + hsize_t max_points = H5S_get_npoints_max (new_dset->space); + hsize_t max_storage = H5O_efl_total_size (&new_dset->efl); if (H5S_UNLIMITED==max_points) { if (H5O_EFL_UNLIMITED!=max_storage) @@ -1883,9 +1901,9 @@ H5D_create(H5G_entry_t *loc, const char *name, const H5T_t *type, * Chunked storage allows any type of data space extension, so we * don't even bother checking. */ - if(chunk_ndims != H5S_get_simple_extent_ndims(space)) + if(chunk_ndims != H5S_get_simple_extent_ndims(new_dset->space)) HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, NULL, "dimensionality of chunks doesn't match the data space"); - if (efl.nused>0) + if (new_dset->efl.nused>0) HGOTO_ERROR (H5E_DATASET, H5E_BADVALUE, NULL, "external storage not supported with chunked layout"); /* @@ -1895,7 +1913,7 @@ H5D_create(H5G_entry_t *loc, const char *name, const H5T_t *type, if(H5P_get(new_plist, H5D_CRT_CHUNK_SIZE_NAME, chunk_size) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve chunk size"); - if (H5S_get_simple_extent_dims(space, NULL, max_dim)<0) + if (H5S_get_simple_extent_dims(new_dset->space, NULL, max_dim)<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to query maximum dimensions"); for (u=0; ulayout.ndims-1; u++) { if(max_dim[u] != H5S_UNLIMITED && max_dim[u] < chunk_size[u]) @@ -1917,7 +1935,7 @@ H5D_create(H5G_entry_t *loc, const char *name, const H5T_t *type, /* Verify data size is smaller than maximum header message size * (64KB) minus other layout message fields. */ - comp_data_size=H5O_MAX_SIZE-H5O_layout_meta_size(f, &(new_dset->layout)); + comp_data_size=H5O_MAX_SIZE-H5O_layout_meta_size(file, &(new_dset->layout)); if(new_dset->layout.size > comp_data_size) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "compact dataset size is bigger than header message maximum size"); if ((ndims=H5S_get_simple_extent_dims(space, new_dset->layout.dim, max_dim))<0) @@ -1931,38 +1949,32 @@ H5D_create(H5G_entry_t *loc, const char *name, const H5T_t *type, } /* end switch */ /* - * Update the entry cache. That is, create and add a new - * "H5G_entry_t" object to the group this dataset is being initially - * created in. + * Update the dataset's entry info. */ - if (H5D_update_entry_cache(f, &new_dset->ent, loc, name, space, new_plist, - &new_dset->layout, new_dset->type, TRUE, (haddr_t)0) != SUCCEED) + if (H5D_update_entry_info(file, new_dset, new_plist) != SUCCEED) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "can't update the metadata cache"); - /* - * Allocate storage if space allocate time is early; otherwise delay - * allocation until later. + /* + * Give the dataset a name. That is, create and add a new + * "H5G_entry_t" object to the group this dataset is being initially + * created in. */ - if (H5P_get(new_plist, H5D_CRT_ALLOC_TIME_NAME, &alloc_time) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve space allocation time"); - - if (alloc_time == H5D_ALLOC_TIME_EARLY) - if (H5D_alloc_storage(f, new_dset, H5D_ALLOC_CREATE) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to initialize storage"); - - /* Update the external storage cache if this is an external object */ - if (H5D_update_external_storage_cache(f, &new_dset->ent, &efl, &new_dset->layout) != SUCCEED) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "can't update the external metadata cache"); + if (H5G_insert(loc, name, &new_dset->ent) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to name dataset"); /* Success */ ret_value = new_dset; done: if (!ret_value && new_dset) { + if (new_dset->space) + H5S_close(new_dset->space); if (new_dset->type) H5T_close(new_dset->type); if (H5F_addr_defined(new_dset->ent.header)) H5O_close(&(new_dset->ent)); + if(new_dset->dcpl_id!=0) + H5I_dec_ref(new_dset->dcpl_id); new_dset->ent.file = NULL; H5FL_FREE(H5D_t,new_dset); } @@ -2024,53 +2036,59 @@ done: *------------------------------------------------------------------------- * Function: H5D_open * - * Purpose: Finds a dataset named NAME in file F and builds a descriptor - * for it, opening it for access. - * - * Return: Success: Pointer to a new dataset descriptor. + * Purpose: Checks if dataset is already open, or opens a dataset for + * access. * - * Failure: NULL + * Return: Success: Dataset ID + * Failure: FAIL * * Errors: * - * Programmer: Robb Matzke - * Thursday, December 4, 1997 + * Programmer: Quincey Koziol + * Friday, December 20, 2002 * * Modifications: - * Robb Matzke, 9 Jun 1998 - * The data space message is no longer cached in the dataset struct. - * - * Quincey Koziol, 12 Oct 1998 - * Moved guts of function into H5D_open_oid - * - * Pedro Vicente, 18 Sep 2002 - * Added `id to name' support. * *------------------------------------------------------------------------- */ -H5D_t * -H5D_open(H5G_entry_t *loc, const char *name) +hid_t +H5D_open(H5G_entry_t *ent) { - H5D_t *dataset = NULL; /*the dataset which was found */ - H5D_t *ret_value = NULL; /*return value */ - H5G_entry_t ent; /*dataset symbol table entry */ + hid_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5D_open, NULL); /* check args */ - assert (loc); - assert (name && *name); + assert (ent); - /* Find the dataset object */ - if (H5G_find(loc, name, NULL, &ent) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_NOTFOUND, NULL, "not found"); + /* Check if dataset was already open */ + if((ret_value=H5FO_opened(ent->file,ent->header))<0) { + H5D_t *dataset; /*the dataset which was found */ - /* Open the dataset object */ - if ((dataset=H5D_open_oid(&ent)) ==NULL) - HGOTO_ERROR(H5E_DATASET, H5E_NOTFOUND, NULL, "not found"); + H5E_clear(); - /* Success */ - ret_value = dataset; + /* Open the dataset object */ + if ((dataset=H5D_open_oid(ent)) ==NULL) + HGOTO_ERROR(H5E_DATASET, H5E_NOTFOUND, FAIL, "not found"); + + /* Create an atom for the dataset */ + if ((ret_value = H5I_register(H5I_DATASET, dataset)) < 0) { + H5D_close(dataset); + HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "can't register dataset"); + } /* end if */ + + /* Add the dataset to the list of opened objects in the file */ + if(H5FO_insert(ent->file,ent->header,ret_value)<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "can't insert dataset into list of open objects"); + } /* end if */ + else { + /* Dataset is already open, increment the reference count on the ID */ + if(H5I_inc_ref(ret_value)<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINC, FAIL, "Can't increment dataset ID"); + + /* Release the dataset entry we located earlier */ + H5G_free_ent_name(ent); + } /* end else */ done: FUNC_LEAVE(ret_value); @@ -2104,15 +2122,14 @@ done: * *------------------------------------------------------------------------- */ -H5D_t * +static H5D_t * H5D_open_oid(H5G_entry_t *ent) { H5D_t *dataset = NULL; /*new dataset struct */ H5D_t *ret_value = NULL; /*return value */ H5O_fill_new_t fill = {NULL, 0, NULL, H5D_ALLOC_TIME_LATE, H5D_FILL_TIME_ALLOC, TRUE}; - H5O_fill_t fill_prop = {NULL, 0, NULL}; + H5O_fill_t *fill_prop; /* Pointer to dataset's fill value area */ H5O_pline_t pline; /* I/O pipeline information */ - H5O_efl_t efl; /* External file information */ H5D_layout_t layout; /* Dataset layout */ int chunk_ndims; H5P_genplist_t *plist; /* Property list */ @@ -2123,7 +2140,7 @@ H5D_open_oid(H5G_entry_t *ent) assert (ent); /* Allocate the dataset structure */ - if(NULL==(dataset = H5D_new(H5P_DEFAULT))) + if(NULL==(dataset = H5D_new(H5P_DATASET_CREATE_DEFAULT,FALSE))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); /* Shallow copy (take ownership) of the group entry object */ @@ -2137,12 +2154,14 @@ H5D_open_oid(H5G_entry_t *ent) if (NULL==(dataset->type=H5O_read(&(dataset->ent), H5O_DTYPE, 0, NULL))) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to load type info from dataset header"); + if (NULL==(dataset->space=H5S_read(&(dataset->ent)))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to load space info from dataset header"); + /* Get dataset creation property list object */ if (NULL == (plist = H5I_object(dataset->dcpl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "can't get dataset creation property list"); /* Get the optional filters message */ - HDmemset(&pline,0,sizeof(H5O_pline_t)); if(NULL == H5O_read(&(dataset->ent), H5O_PLINE, 0, &pline)) { H5E_clear(); HDmemset(&pline, 0, sizeof(pline)); @@ -2195,10 +2214,13 @@ H5D_open_oid(H5G_entry_t *ent) HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, NULL, "not implemented yet"); } /* end switch */ + /* Point at dataset's copy, to cache it for later */ + fill_prop=&dataset->fill; + /* Retrieve & release the previous fill-value settings */ - if(H5P_get(plist, H5D_CRT_FILL_VALUE_NAME, &fill_prop) < 0) + if(H5P_get(plist, H5D_CRT_FILL_VALUE_NAME, fill_prop) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't get fill value"); - H5O_reset(H5O_FILL, &fill_prop); + H5O_reset(H5O_FILL, fill_prop); /* Get the new fill value message */ if(NULL == H5O_read(&(dataset->ent), H5O_FILL_NEW, 0, &fill)) { @@ -2224,35 +2246,37 @@ H5D_open_oid(H5G_entry_t *ent) } /* end switch */ } /* end if */ if(fill.fill_defined) { - if(NULL==H5O_copy(H5O_FILL, &fill, &fill_prop)) + if(NULL==H5O_copy(H5O_FILL, &fill, fill_prop)) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "can't copy fill value"); } else { /* For compatibility with v1.4. Retrieve the old fill value message. * If size is 0, make it -1 for undefined. */ - if(NULL == H5O_read(&(dataset->ent), H5O_FILL, 0, &fill_prop)) { + if(NULL == H5O_read(&(dataset->ent), H5O_FILL, 0, fill_prop)) { H5E_clear(); - HDmemset(&fill_prop, 0, sizeof(fill_prop)); + HDmemset(fill_prop, 0, sizeof(H5O_fill_t)); } - if(fill_prop.size == 0) { - fill_prop.type = fill_prop.buf = NULL; - fill_prop.size = (size_t)-1; + if(fill_prop->size == 0) { + fill_prop->type = fill_prop->buf = NULL; + fill_prop->size = (size_t)-1; } } /* end else */ - /* Set fill value properties */ - if(H5P_set(plist, H5D_CRT_FILL_VALUE_NAME, &fill_prop) < 0) + /* Set revised fill value properties */ + if(H5P_set(plist, H5D_CRT_FILL_VALUE_NAME, fill_prop) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set fill value"); + dataset->alloc_time=fill.alloc_time; /* Cache this for later */ if(H5P_set(plist, H5D_CRT_ALLOC_TIME_NAME, &fill.alloc_time) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set fill value"); + dataset->fill_time=fill.fill_time; /* Cache this for later */ if(H5P_set(plist, H5D_CRT_FILL_TIME_NAME, &fill.fill_time) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set fill value"); /* Get the external file list message, which might not exist. Space is * also undefined when space allocate time is H5D_ALLOC_TIME_LATE. */ if( !H5F_addr_defined(dataset->layout.addr)) { - HDmemset(&efl,0,sizeof(H5O_efl_t)); - if(NULL != H5O_read(&(dataset->ent), H5O_EFL, 0, &efl)) - if(H5P_set(plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0) + HDmemset(&dataset->efl,0,sizeof(H5O_efl_t)); + if(NULL != H5O_read(&(dataset->ent), H5O_EFL, 0, &dataset->efl)) + if(H5P_set(plist, H5D_CRT_EXT_FILE_LIST_NAME, &dataset->efl) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set external file list"); } /* @@ -2263,7 +2287,7 @@ H5D_open_oid(H5G_entry_t *ent) if ((H5F_get_intent(dataset->ent.file) & H5F_ACC_RDWR) && (dataset->layout.type!=H5D_COMPACT && dataset->layout.addr==HADDR_UNDEF) && (IS_H5FD_MPIO(dataset->ent.file) || IS_H5FD_MPIPOSIX(dataset->ent.file))) { - if (H5D_alloc_storage(dataset->ent.file, dataset,H5D_ALLOC_OPEN)<0) + if (H5D_alloc_storage(dataset->ent.file, dataset,H5D_ALLOC_OPEN, TRUE, FALSE)<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to initialize file storage"); } @@ -2274,6 +2298,8 @@ done: if (ret_value==NULL && dataset) { if (H5F_addr_defined(dataset->ent.header)) H5O_close(&(dataset->ent)); + if (dataset->space) + H5S_close(dataset->space); if (dataset->type) H5T_close(dataset->type); dataset->ent.file = NULL; @@ -2317,19 +2343,23 @@ H5D_close(H5D_t *dataset) assert(dataset && dataset->ent.file); /* - * Release data type and creation property list -- there isn't much we - * can do if one of these fails, so we just continue. + * Release datatype, dataspace and creation property list -- there isn't + * much we can do if one of these fails, so we just continue. */ - free_failed = (H5T_close(dataset->type) < 0 || + free_failed=(H5T_close(dataset->type)<0 || H5S_close(dataset->space)<0 || H5I_dec_ref(dataset->dcpl_id) < 0); /* Update header message of layout for compact dataset. */ if(dataset->layout.type==H5D_COMPACT && dataset->layout.dirty) { - if(H5O_modify(&(dataset->ent), H5O_LAYOUT, 0, 0, &(dataset->layout))<0) + if(H5O_modify(&(dataset->ent), H5O_LAYOUT, 0, 0, 1, &(dataset->layout))<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update layout message"); dataset->layout.dirty = FALSE; } /* end if */ + /* Remove the dataset from the list of opened objects in the file */ + if(H5FO_delete(dataset->ent.file,dataset->ent.header)<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "can't remove dataset from list of open objects"); + /* Close the dataset object */ H5O_close(&(dataset->ent)); @@ -2400,7 +2430,7 @@ done: * *------------------------------------------------------------------------- */ -herr_t +static herr_t H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, const H5S_t *file_space, hid_t dxpl_id, void *buf/*out*/) { @@ -2413,8 +2443,11 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, hid_t src_id = -1, dst_id = -1;/*temporary type atoms */ H5S_conv_t *sconv=NULL; /*space conversion funcs*/ H5S_sel_iter_t mem_iter; /*memory selection iteration info*/ + hbool_t mem_iter_init=0; /*memory selection iteration info has been initialized */ H5S_sel_iter_t bkg_iter; /*background iteration info*/ + hbool_t bkg_iter_init=0; /*background iteration info has been initialized */ H5S_sel_iter_t file_iter; /*file selection iteration info*/ + hbool_t file_iter_init=0; /*file selection iteration info has been initialized */ herr_t ret_value = SUCCEED; /*return value */ herr_t status; /*function return status*/ size_t src_type_size; /*size of source type */ @@ -2422,7 +2455,6 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, size_t target_size; /*desired buffer size */ hsize_t request_nelmts; /*requested strip mine */ H5T_bkg_t need_bkg; /*type of background buf*/ - H5S_t *free_this_space=NULL; /*data space to free */ #ifdef H5_HAVE_PARALLEL H5FD_mpio_dxpl_t *dx = NULL; H5FD_mpio_xfer_t xfer_mode=H5FD_MPIO_INDEPENDENT; /*xfer_mode for this request */ @@ -2432,10 +2464,6 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, #ifdef H5S_DEBUG H5_timer_t timer; #endif - H5O_efl_t efl; /* External File List info */ - H5O_fill_t fill; /* Fill value info */ - H5D_fill_time_t fill_time; /* When to write the fill values */ - H5D_fill_value_t fill_status; /* Whether/How the fill value is defined */ H5P_genplist_t *dx_plist=NULL; /* Data transfer property list */ H5P_genplist_t *dc_plist; /* Dataset creation roperty list */ unsigned sconv_flags=0; /* Flags for the space conversion */ @@ -2447,24 +2475,16 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, assert(mem_type); assert(buf); - /* Initialize these before any errors can occur */ - HDmemset(&mem_iter,0,sizeof(H5S_sel_iter_t)); - HDmemset(&bkg_iter,0,sizeof(H5S_sel_iter_t)); - HDmemset(&file_iter,0,sizeof(H5S_sel_iter_t)); - /* Get the dataset's creation property list */ if (NULL == (dc_plist = H5I_object(dataset->dcpl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list"); /* Get the dataset transfer property list */ - if (NULL == (dx_plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER))) + if (NULL == (dx_plist = H5I_object(dxpl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list"); - if (!file_space) { - if (NULL==(free_this_space=H5S_read (&(dataset->ent)))) - HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to read data space from dataset header"); - file_space = free_this_space; - } /* end if */ + if (!file_space) + file_space = dataset->space; if (!mem_space) mem_space = file_space; nelmts = (*mem_space->select.get_npoints)(mem_space); @@ -2500,15 +2520,7 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "src and dest data spaces have different sizes"); /* Retrieve dataset properties */ - if(H5P_fill_value_defined(dc_plist, &fill_status)<0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't tell if fill value defined"); - if((fill_status==H5D_FILL_VALUE_DEFAULT || fill_status==H5D_FILL_VALUE_USER_DEFINED) - && H5P_get(dc_plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL,"can't retrieve fill value"); - if(H5P_get(dc_plist, H5D_CRT_FILL_TIME_NAME, &fill_time) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL,"can't retrieve fill time"); - if(H5P_get(dc_plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve external file list"); + /* */ /* If space hasn't been allocated and not using external storage, * return fill value to buffer if fill time is upon allocation, or @@ -2516,8 +2528,20 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, * fill time is NEVER, there is no way to tell whether part of data * has been overwritten. So just proceed in reading. */ - if(nelmts > 0 && efl.nused==0 && dataset->layout.type!=H5D_COMPACT + if(nelmts > 0 && dataset->efl.nused==0 && dataset->layout.type!=H5D_COMPACT && dataset->layout.addr==HADDR_UNDEF) { + H5O_fill_t fill; /* Fill value info */ + H5D_fill_time_t fill_time; /* When to write the fill values */ + H5D_fill_value_t fill_status; /* Whether/How the fill value is defined */ + + /* Retrieve dataset's fill-value properties */ + if(H5P_fill_value_defined(dc_plist, &fill_status)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't tell if fill value defined"); + if((fill_status==H5D_FILL_VALUE_DEFAULT || fill_status==H5D_FILL_VALUE_USER_DEFINED) + && H5P_get(dc_plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL,"can't retrieve fill value"); + if(H5P_get(dc_plist, H5D_CRT_FILL_TIME_NAME, &fill_time) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL,"can't retrieve fill time"); /* Should be impossible, but check anyway... */ if(fill_status == H5D_FILL_VALUE_UNDEFINED && fill_time == H5D_FILL_TIME_ALLOC) @@ -2581,10 +2605,10 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, H5_timer_begin(&timer); #endif /* Sanity check dataset, then read it */ - assert(dataset->layout.addr!=HADDR_UNDEF || efl.nused>0 || dataset->layout.type==H5D_COMPACT); + assert(dataset->layout.addr!=HADDR_UNDEF || dataset->efl.nused>0 || dataset->layout.type==H5D_COMPACT); status = (sconv->read)(dataset->ent.file, &(dataset->layout), - dc_plist, H5T_get_size(dataset->type), - file_space, mem_space, dxpl_id, buf/*out*/); + dc_plist, &(dataset->efl), H5T_get_size(dataset->type), + file_space, mem_space, dxpl_id, buf/*out*/); #ifdef H5S_DEBUG H5_timer_end(&(sconv->stats[1].read_timer), &timer); sconv->stats[1].read_nbytes += nelmts * H5T_get_size(dataset->type); @@ -2636,10 +2660,13 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, /* Figure out the strip mine size. */ if ((*file_space->select.iter_init)(file_space, src_type_size, &file_iter)<0) HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize file selection information"); + file_iter_init=1; /*file selection iteration info has been initialized */ if ((*mem_space->select.iter_init)(mem_space, dst_type_size, &mem_iter)<0) HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information"); + mem_iter_init=1; /*file selection iteration info has been initialized */ if ((*mem_space->select.iter_init)(mem_space, dst_type_size, &bkg_iter)<0) HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize background selection information"); + bkg_iter_init=1; /*file selection iteration info has been initialized */ /* Sanity check elements in temporary buffer */ if (request_nelmts<=0) @@ -2662,13 +2689,13 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, } /* end else */ if (NULL==(tconv_buf=H5P_peek_voidp(dx_plist,H5D_XFER_TCONV_BUF_NAME))) { /* Allocate temporary buffer */ - if((tconv_buf=H5FL_BLK_ALLOC(type_conv,target_size,0))==NULL) + if((tconv_buf=H5FL_BLK_MALLOC(type_conv,target_size))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion"); } /* end if */ if (need_bkg && NULL==(bkg_buf=H5P_peek_voidp(dx_plist,H5D_XFER_BKGR_BUF_NAME))) { /* Allocate background buffer */ H5_CHECK_OVERFLOW((request_nelmts*dst_type_size),hsize_t,size_t); - if((bkg_buf=H5FL_BLK_ALLOC(type_conv,(size_t)(request_nelmts*dst_type_size),0))==NULL) + if((bkg_buf=H5FL_BLK_MALLOC(type_conv,(size_t)(request_nelmts*dst_type_size)))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for background conversion"); } /* end if */ @@ -2687,9 +2714,9 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, H5_timer_begin(&timer); #endif /* Sanity check that space is allocated, then read data from it */ - assert(dataset->layout.addr!=HADDR_UNDEF || efl.nused > 0); + assert(dataset->layout.addr!=HADDR_UNDEF || dataset->efl.nused > 0); n = H5S_select_fgath(dataset->ent.file, &(dataset->layout), - dc_plist, src_type_size, file_space, + dc_plist, &(dataset->efl), src_type_size, file_space, &file_iter, smine_nelmts, dxpl_id, tconv_buf/*out*/); #ifdef H5S_DEBUG @@ -2753,9 +2780,12 @@ done: } /* end if */ #endif /*H5_HAVE_PARALLEL*/ /* Release selection iterators */ - (*file_space->select.iter_release)(&file_iter); - (*mem_space->select.iter_release)(&mem_iter); - (*mem_space->select.iter_release)(&bkg_iter); + if(file_iter_init) + (*file_space->select.iter_release)(&file_iter); + if(mem_iter_init) + (*mem_space->select.iter_release)(&mem_iter); + if(bkg_iter_init) + (*mem_space->select.iter_release)(&bkg_iter); if (src_id >= 0) H5I_dec_ref(src_id); @@ -2766,8 +2796,6 @@ done: H5FL_BLK_FREE(type_conv,tconv_buf); if (bkg_buf && NULL==H5P_peek_voidp(dx_plist,H5D_XFER_BKGR_BUF_NAME)) H5FL_BLK_FREE(type_conv,bkg_buf); - if (free_this_space) - H5S_close(free_this_space); FUNC_LEAVE(ret_value); } /* end H5D_read() */ @@ -2816,7 +2844,7 @@ done: * *------------------------------------------------------------------------- */ -herr_t +static herr_t H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, const H5S_t *file_space, hid_t dxpl_id, const void *buf) { @@ -2829,8 +2857,11 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, hid_t src_id = -1, dst_id = -1;/*temporary type atoms */ H5S_conv_t *sconv=NULL; /*space conversion funcs*/ H5S_sel_iter_t mem_iter; /*memory selection iteration info*/ + hbool_t mem_iter_init=0; /*memory selection iteration info has been initialized */ H5S_sel_iter_t bkg_iter; /*background iteration info*/ + hbool_t bkg_iter_init=0; /*background iteration info has been initialized */ H5S_sel_iter_t file_iter; /*file selection iteration info*/ + hbool_t file_iter_init=0; /*file selection iteration info has been initialized */ herr_t ret_value = SUCCEED; /*return value */ herr_t status; /*function return status*/ size_t src_type_size; /*size of source type */ @@ -2838,7 +2869,6 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, size_t target_size; /*desired buffer size */ hsize_t request_nelmts; /*requested strip mine */ H5T_bkg_t need_bkg; /*type of background buf*/ - H5S_t *free_this_space=NULL; /*data space to free */ #ifdef H5_HAVE_PARALLEL H5FD_mpio_dxpl_t *dx = NULL; H5FD_mpio_xfer_t xfer_mode=H5FD_MPIO_INDEPENDENT; /*xfer_mode for this request */ @@ -2848,10 +2878,6 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, #ifdef H5S_DEBUG H5_timer_t timer; #endif - H5O_efl_t efl; /* External File List info */ - H5O_fill_t fill; /* Fill value info */ - H5D_fill_time_t fill_time; /* When to write the fill values */ - H5D_alloc_time_t alloc_time; /* When to allocate raw data space */ H5P_genplist_t *dx_plist=NULL; /* Data transfer property list */ H5P_genplist_t *dc_plist; /* Dataset creation roperty list */ unsigned sconv_flags=0; /* Flags for the space conversion */ @@ -2863,24 +2889,16 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, assert(mem_type); assert(buf); - /* Initialize these before any errors can occur */ - HDmemset(&mem_iter,0,sizeof(H5S_sel_iter_t)); - HDmemset(&bkg_iter,0,sizeof(H5S_sel_iter_t)); - HDmemset(&file_iter,0,sizeof(H5S_sel_iter_t)); - /* Get the dataset's creation property list */ if (NULL == (dc_plist = H5I_object(dataset->dcpl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list"); /* Get the dataset transfer property list */ - if (NULL == (dx_plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER))) + if (NULL == (dx_plist = H5I_object(dxpl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list"); - if (!file_space) { - if (NULL==(free_this_space=H5S_read (&(dataset->ent)))) - HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to read data space from dataset header"); - file_space = free_this_space; - } /* end if */ + if (!file_space) + file_space = dataset->space; if (!mem_space) mem_space = file_space; nelmts = (*mem_space->select.get_npoints)(mem_space); @@ -2941,20 +2959,19 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "src and dest data spaces have different sizes"); /* Retrieve dataset properties */ - if(H5P_get(dc_plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve fill value"); - if(H5P_get(dc_plist, H5D_CRT_FILL_TIME_NAME, &fill_time) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve fill time"); - if(H5P_get(dc_plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve external file list"); - if(H5P_get(dc_plist, H5D_CRT_ALLOC_TIME_NAME, &alloc_time) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve space allocation time"); + /* */ /* Allocate data space and initialize it if it hasn't been. */ if(nelmts > 0 && dataset->layout.type!=H5D_COMPACT && dataset->layout.addr==HADDR_UNDEF) { + hssize_t file_nelmts; /* Number of elements in file dataset's dataspace */ + + /* Get the number of elements in file dataset's dataspace */ + if((file_nelmts=H5S_get_simple_extent_npoints(file_space))<0) + HGOTO_ERROR (H5E_DATASET, H5E_BADVALUE, FAIL, "can't retrieve number of elements in file dataset"); + /* Allocate storage */ - if(H5D_alloc_storage(dataset->ent.file, dataset,H5D_ALLOC_WRITE)<0) + if(H5D_alloc_storage(dataset->ent.file, dataset,H5D_ALLOC_WRITE, TRUE, (hbool_t)((hsize_t)file_nelmts==nelmts ? TRUE : FALSE))<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize storage"); } /* end if */ @@ -3005,8 +3022,8 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, H5_timer_begin(&timer); #endif status = (sconv->write)(dataset->ent.file, &(dataset->layout), - dc_plist, H5T_get_size(dataset->type), - file_space, mem_space, dxpl_id, buf); + dc_plist, &(dataset->efl), H5T_get_size(dataset->type), + file_space, mem_space, dxpl_id, buf); #ifdef H5S_DEBUG H5_timer_end(&(sconv->stats[0].write_timer), &timer); sconv->stats[0].write_nbytes += nelmts * H5T_get_size(mem_type); @@ -3061,10 +3078,13 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, /* Figure out the strip mine size. */ if ((*file_space->select.iter_init)(file_space, dst_type_size, &file_iter)<0) HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize file selection information"); + file_iter_init=1; /*file selection iteration info has been initialized */ if ((*mem_space->select.iter_init)(mem_space, src_type_size, &mem_iter)<0) HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information"); + mem_iter_init=1; /*file selection iteration info has been initialized */ if ((*file_space->select.iter_init)(file_space, dst_type_size, &bkg_iter)<0) HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize background selection information"); + bkg_iter_init=1; /*file selection iteration info has been initialized */ /* * Get a temporary buffer for type conversion unless the app has already @@ -3087,13 +3107,13 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, } /* end else */ if (NULL==(tconv_buf=H5P_peek_voidp(dx_plist,H5D_XFER_TCONV_BUF_NAME))) { /* Allocate temporary buffer */ - if((tconv_buf=H5FL_BLK_ALLOC(type_conv,target_size,0))==NULL) + if((tconv_buf=H5FL_BLK_MALLOC(type_conv,target_size))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion"); } /* end if */ if (need_bkg && NULL==(bkg_buf=H5P_peek_voidp(dx_plist,H5D_XFER_BKGR_BUF_NAME))) { /* Allocate background buffer */ H5_CHECK_OVERFLOW((request_nelmts*dst_type_size),hsize_t,size_t); - if((bkg_buf=H5FL_BLK_ALLOC(type_conv,(size_t)(request_nelmts*dst_type_size),1))==NULL) + if((bkg_buf=H5FL_BLK_CALLOC(type_conv,(size_t)(request_nelmts*dst_type_size)))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for background conversion"); } /* end if */ @@ -3126,9 +3146,8 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, H5_timer_begin(&timer); #endif n = H5S_select_fgath(dataset->ent.file, &(dataset->layout), - dc_plist, dst_type_size, file_space, - &bkg_iter, smine_nelmts, dxpl_id, - bkg_buf/*out*/); + dc_plist, &(dataset->efl), dst_type_size, file_space, + &bkg_iter, smine_nelmts, dxpl_id, bkg_buf/*out*/); #ifdef H5S_DEBUG H5_timer_end(&(sconv->stats[0].bkg_timer), &timer); @@ -3152,9 +3171,8 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, H5_timer_begin(&timer); #endif status = H5S_select_fscat(dataset->ent.file, &(dataset->layout), - dc_plist, dst_type_size, - file_space, &file_iter, smine_nelmts, - dxpl_id, tconv_buf); + dc_plist, &(dataset->efl), dst_type_size, file_space, &file_iter, + smine_nelmts, dxpl_id, tconv_buf); #ifdef H5S_DEBUG H5_timer_end(&(sconv->stats[0].scat_timer), &timer); @@ -3186,9 +3204,12 @@ done: } /* end if */ #endif /*H5_HAVE_PARALLEL*/ /* Release selection iterators */ - (*file_space->select.iter_release)(&file_iter); - (*mem_space->select.iter_release)(&mem_iter); - (*file_space->select.iter_release)(&bkg_iter); + if(file_iter_init) + (*file_space->select.iter_release)(&file_iter); + if(mem_iter_init) + (*mem_space->select.iter_release)(&mem_iter); + if(bkg_iter_init) + (*file_space->select.iter_release)(&bkg_iter); if (src_id >= 0) H5I_dec_ref(src_id); @@ -3199,8 +3220,6 @@ done: H5FL_BLK_FREE(type_conv,tconv_buf); if (bkg_buf && NULL==H5P_peek_voidp(dx_plist,H5D_XFER_BKGR_BUF_NAME)) H5FL_BLK_FREE(type_conv,bkg_buf); - if (free_this_space) - H5S_close(free_this_space); FUNC_LEAVE(ret_value); } /* end H5D_write() */ @@ -3230,8 +3249,6 @@ H5D_extend (H5D_t *dataset, const hsize_t *size) { int changed; /* Flag to indicate that the dataspace was successfully extended */ H5S_t *space = NULL; /* Dataset's dataspace */ - H5D_alloc_time_t alloc_time; /* When to allocate raw data space */ - H5P_genplist_t *plist; /* Property list */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5D_extend, FAIL); @@ -3240,12 +3257,6 @@ H5D_extend (H5D_t *dataset, const hsize_t *size) assert (dataset); assert (size); - /* Get the dataset creation property list */ - if (NULL == (plist = H5I_object(dataset->dcpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list"); - if(H5P_get(plist, H5D_CRT_ALLOC_TIME_NAME, &alloc_time) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve space allocation time"); - /* * NOTE: Restrictions on extensions were checked when the dataset was * created. All extensions are allowed here since none should be @@ -3253,24 +3264,22 @@ H5D_extend (H5D_t *dataset, const hsize_t *size) */ /* Increase the size of the data space */ - if (NULL==(space=H5S_read (&(dataset->ent)))) - HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to read data space info from dataset header"); + space=dataset->space; if ((changed=H5S_extend (space, size))<0) HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to increase size of data space"); if (changed>0){ /* Save the new dataspace in the file if necessary */ - if (H5S_modify (&(dataset->ent), space)<0) + if (H5S_modify (&(dataset->ent), space, TRUE)<0) HGOTO_ERROR (H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update file with new dataspace"); /* Allocate space for the new parts of the dataset, if appropriate */ - if(alloc_time==H5D_ALLOC_TIME_EARLY) - if (H5D_alloc_storage(dataset->ent.file, dataset, H5D_ALLOC_EXTEND)<0) + if(dataset->alloc_time==H5D_ALLOC_TIME_EARLY) + if (H5D_alloc_storage(dataset->ent.file, dataset, H5D_ALLOC_EXTEND, TRUE, FALSE)<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize dataset with fill value"); } /* end if */ done: - H5S_close(space); FUNC_LEAVE (ret_value); } @@ -3347,7 +3356,7 @@ H5D_typeof (H5D_t *dset) * *------------------------------------------------------------------------- */ -H5F_t * +static H5F_t * H5D_get_file (const H5D_t *dset) { /* Use FUNC_ENTER_NOINIT here to avoid performance issues */ @@ -3379,12 +3388,9 @@ H5D_get_file (const H5D_t *dset) *------------------------------------------------------------------------- */ static herr_t -H5D_alloc_storage (H5F_t *f, H5D_t *dset/*in,out*/, H5D_time_alloc_t time_alloc) +H5D_alloc_storage (H5F_t *f, H5D_t *dset/*in,out*/, H5D_time_alloc_t time_alloc, + hbool_t update_time, hbool_t full_overwrite) { - H5P_genplist_t *plist; /* Dataset's creation property list */ - H5O_efl_t efl; /* External File List info */ - H5D_fill_time_t fill_time; /* When to write fill values */ - H5D_alloc_time_t alloc_time; /* When to allocate raw data space */ struct H5O_layout_t *layout; /* The dataset's layout information */ hsize_t nbytes; /* The number of bytes in the dataset */ unsigned space_allocated=0; /* Flag to indicate that space was allocated */ @@ -3397,23 +3403,11 @@ H5D_alloc_storage (H5F_t *f, H5D_t *dset/*in,out*/, H5D_time_alloc_t time_alloc) assert (f); assert (dset); - /* Get external file list properties */ - if (NULL == (plist = H5I_object(dset->dcpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list"); - if(H5P_get(plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve external file list"); - /* If the data is stored in external files, don't set an address for the layout * We assume that external storage is already * allocated by the caller, or at least will be before I/O is performed. */ - if(efl.nused==0) { - /* Get properties needed */ - if(H5P_get(plist, H5D_CRT_FILL_TIME_NAME, &fill_time) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve fill time"); - if(H5P_get(plist, H5D_CRT_ALLOC_TIME_NAME, &alloc_time) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve space allocation time"); - + if(dset->efl.nused==0) { /* Get a pointer to the dataset's layout information */ layout=&(dset->layout); @@ -3441,6 +3435,11 @@ H5D_alloc_storage (H5F_t *f, H5D_t *dset/*in,out*/, H5D_time_alloc_t time_alloc) /* Indicate that we allocated space */ space_allocated=1; } /* end if */ + + /* If MPIO or MPIPOSIX is used, indicate that space was allocated, so the B-tree gets expanded */ + if(IS_H5FD_MPIO(f) || IS_H5FD_MPIPOSIX(f)) + space_allocated=1; + break; case H5D_COMPACT: @@ -3462,19 +3461,22 @@ H5D_alloc_storage (H5F_t *f, H5D_t *dset/*in,out*/, H5D_time_alloc_t time_alloc) HGOTO_ERROR (H5E_IO, H5E_UNSUPPORTED, FAIL, "unsupported storage layout"); } /* end switch */ - /* If we are filling the dataset on allocation, do that now */ - if(fill_time==H5D_FILL_TIME_ALLOC - && !(alloc_time==H5D_ALLOC_TIME_INCR && time_alloc==H5D_ALLOC_WRITE)) { - if(H5D_init_storage(dset) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize dataset with fill value"); - } /* end if */ + /* Check if we actually allocated space before performing other actions */ + if(space_allocated) { + /* If we are filling the dataset on allocation, do that now */ + if(dset->fill_time==H5D_FILL_TIME_ALLOC + && !(dset->alloc_time==H5D_ALLOC_TIME_INCR && time_alloc==H5D_ALLOC_WRITE)) { + if(H5D_init_storage(dset, full_overwrite) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize dataset with fill value"); + } /* end if */ - /* Also update header message for layout with new address - * (this is only for forward compatibility). - */ - if(space_allocated && time_alloc!=H5D_ALLOC_CREATE) - if (H5O_modify (&(dset->ent), H5O_LAYOUT, 0, H5O_FLAG_CONSTANT, &(dset->layout)) < 0) - HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update layout message"); + /* Also update header message for layout with new address + * (this is only for forward compatibility). + */ + if(time_alloc!=H5D_ALLOC_CREATE) + if (H5O_modify (&(dset->ent), H5O_LAYOUT, 0, H5O_FLAG_CONSTANT, update_time, &(dset->layout)) < 0) + HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update layout message"); + } /* end if */ } /* end if */ done: @@ -3504,13 +3506,11 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5D_init_storage(H5D_t *dset) +H5D_init_storage(H5D_t *dset, hbool_t full_overwrite) { hssize_t snpoints; /* Number of points in space (for error checking) */ size_t npoints; /* Number of points in space */ - H5S_t *space = NULL; /* Dataset's dataspace */ - H5O_fill_t fill; /* Fill value information */ - H5O_efl_t efl; /* External File List info */ + H5S_t *space; /* Dataset's dataspace */ H5P_genplist_t *plist; /* Property list */ herr_t ret_value = SUCCEED; /* Return value */ @@ -3518,17 +3518,8 @@ H5D_init_storage(H5D_t *dset) assert(dset); - /* Get fill value, external file list, and data pipeline properties */ - if (NULL == (plist = H5I_object(dset->dcpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list"); - if(H5P_get(plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get fill value"); - if(H5P_get(plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve external file list"); - /* Get the dataset's dataspace */ - if (NULL==(space=H5S_read (&(dset->ent)))) - HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to read data space from dataset header"); + space=dset->space; /* Get the number of elements in the dataset's dataspace */ snpoints = H5S_get_simple_extent_npoints(space); @@ -3537,19 +3528,31 @@ H5D_init_storage(H5D_t *dset) switch (dset->layout.type) { case H5D_COMPACT: - /* If the fill value is defined, initialize the data buffer with it */ - if(fill.buf) - /* Initialize the cached data buffer with the fill value */ - H5V_array_fill(dset->layout.buf, fill.buf, fill.size, npoints); - else /* If the fill value is default, zero set data buf. */ - HDmemset(dset->layout.buf, 0, dset->layout.size); + /* If we will be immediately overwriting the values, don't bother to clear them */ + if(!full_overwrite) { + /* If the fill value is defined, initialize the data buffer with it */ + if(dset->fill.buf) + /* Initialize the cached data buffer with the fill value */ + H5V_array_fill(dset->layout.buf, dset->fill.buf, dset->fill.size, npoints); + else /* If the fill value is default, zero set data buf. */ + HDmemset(dset->layout.buf, 0, dset->layout.size); + } /* end if */ break; case H5D_CONTIGUOUS: - if (H5F_contig_fill(dset->ent.file, H5P_DATASET_XFER_DEFAULT, - &(dset->layout), plist, space, H5T_get_size(dset->type))<0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to allocate all chunks of dataset"); - break; + /* Don't write default fill values to external files */ + /* If we will be immediately overwriting the values, don't bother to clear them */ + if((dset->efl.nused==0 || dset->fill.buf) && !full_overwrite) { + /* Get dataset's creation property list */ + if (NULL == (plist = H5I_object(dset->dcpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list"); + + if (H5F_contig_fill(dset->ent.file, H5P_DATASET_XFER_DEFAULT, + &(dset->layout), plist, &(dset->efl), space, + &dset->fill, H5T_get_size(dset->type))<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to allocate all chunks of dataset"); + } /* end if */ + break; case H5D_CHUNKED: /* @@ -3561,21 +3564,22 @@ H5D_init_storage(H5D_t *dset) int ndims; hsize_t dim[H5O_LAYOUT_NDIMS]; + /* Get dataset's creation property list */ + if (NULL == (plist = H5I_object(dset->dcpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list"); + if ((ndims=H5S_get_simple_extent_dims(space, dim, NULL))<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to get simple data space info"); dim[ndims] = dset->layout.dim[ndims]; if (H5F_istore_allocate(dset->ent.file, H5P_DATASET_XFER_DEFAULT, - &(dset->layout), dim, plist)<0) + &(dset->layout), dim, plist, full_overwrite)<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to allocate all chunks of dataset"); } /* end if */ break; } /* end switch */ done: - if (space) - H5S_close(space); - FUNC_LEAVE(ret_value); } @@ -3638,7 +3642,7 @@ done: * *------------------------------------------------------------------------- */ -hsize_t +static hsize_t H5D_get_storage_size(H5D_t *dset) { unsigned u; /* Index variable */ @@ -3732,7 +3736,7 @@ done: * *------------------------------------------------------------------------- */ -haddr_t +static haddr_t H5D_get_offset(H5D_t *dset) { haddr_t ret_value; @@ -3894,9 +3898,9 @@ H5Dvlen_reclaim(hid_t type_id, hid_t space_id, hid_t plist_id, void *buf) /* Get the default dataset transfer property list if the user didn't provide one */ if (H5P_DEFAULT == plist_id) plist_id= H5P_DATASET_XFER_DEFAULT; - - if (TRUE!=H5P_isa_class(plist_id,H5P_DATASET_XFER)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms"); + else + if (TRUE!=H5P_isa_class(plist_id,H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms"); /* Call H5Diterate with args, etc. */ ret_value=H5Diterate(buf,type_id,space_id,H5T_vlen_reclaim,&plist_id); @@ -3923,7 +3927,7 @@ done: * *------------------------------------------------------------------------- */ -void * +static void * H5D_vlen_get_buf_size_alloc(size_t size, void *info) { H5T_vlen_bufsize_t *vlen_bufsize=(H5T_vlen_bufsize_t *)info; @@ -3970,7 +3974,7 @@ done: * *------------------------------------------------------------------------- */ -herr_t +static herr_t H5D_vlen_get_buf_size(void UNUSED *elem, hid_t type_id, hsize_t UNUSED ndim, hssize_t *point, void *op_data) { H5T_vlen_bufsize_t *vlen_bufsize=(H5T_vlen_bufsize_t *)op_data; @@ -4060,9 +4064,9 @@ H5Dvlen_get_buf_size(hid_t dataset_id, hid_t type_id, hid_t space_id, HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't create dataspace"); /* Grab the temporary buffers required */ - if((vlen_bufsize.fl_tbuf=H5FL_BLK_ALLOC(vlen_fl_buf,1,0))==NULL) + if((vlen_bufsize.fl_tbuf=H5FL_BLK_MALLOC(vlen_fl_buf,1))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "no temporary buffers available"); - if((vlen_bufsize.vl_tbuf=H5FL_BLK_ALLOC(vlen_vl_buf,1,0))==NULL) + if((vlen_bufsize.vl_tbuf=H5FL_BLK_MALLOC(vlen_vl_buf,1))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "no temporary buffers available"); /* Get the pointer to the dataset transfer class */ @@ -4160,7 +4164,7 @@ H5D_fill(const void *fill, const H5T_t *fill_type, void *buf, const H5T_t *buf_t /* Get the maximum buffer size needed and allocate it */ buf_size=MAX(src_type_size,dst_type_size); - if (NULL==(tconv_buf = H5FL_BLK_ALLOC(type_elem,buf_size,0)) || NULL==(bkg_buf = H5FL_BLK_ALLOC(type_elem,buf_size,1))) + if (NULL==(tconv_buf = H5FL_BLK_MALLOC(type_elem,buf_size)) || NULL==(bkg_buf = H5FL_BLK_CALLOC(type_elem,buf_size))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); /* Copy the user's data into the buffer for conversion */ @@ -4180,7 +4184,7 @@ H5D_fill(const void *fill, const H5T_t *fill_type, void *buf, const H5T_t *buf_t } /* Perform data type conversion */ - if (H5T_convert(tpath, src_id, dst_id, (hsize_t)1, 0, 0, tconv_buf, bkg_buf, H5P_DEFAULT)<0) + if (H5T_convert(tpath, src_id, dst_id, (hsize_t)1, 0, 0, tconv_buf, bkg_buf, H5P_DATASET_XFER_DEFAULT)<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "data type conversion failed"); /* Fill the selection in the memory buffer */ @@ -4311,7 +4315,7 @@ done: * *------------------------------------------------------------------------- */ -herr_t +static herr_t H5D_set_extent(H5D_t *dset, const hsize_t *size) { hsize_t curr_dims[H5O_LAYOUT_NDIMS]; /* Current dimension sizes */ @@ -4319,7 +4323,6 @@ H5D_set_extent(H5D_t *dset, const hsize_t *size) herr_t ret_value = SUCCEED; /* Return value */ H5S_t *space = NULL; H5P_genplist_t *plist; - H5D_alloc_time_t alloc_time; /* When to allocate raw data space */ int u; unsigned shrink = 0; /* Flag to indicate a dimension has shrank */ unsigned expand = 0; /* Flag to indicate a dimension has grown */ @@ -4335,8 +4338,7 @@ H5D_set_extent(H5D_t *dset, const hsize_t *size) * Get the data space *------------------------------------------------------------------------- */ - if(NULL == (space = H5S_read(&(dset->ent)))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to read data space info from dset header"); + space = dset->space; /*------------------------------------------------------------------------- * Check if we are shrinking or expanding any of the dimensions @@ -4361,23 +4363,17 @@ H5D_set_extent(H5D_t *dset, const hsize_t *size) /* Don't bother updating things, unless they've changed */ if(changed) { - /* Get the dataset creation property list */ - if(NULL == (plist = H5I_object(dset->dcpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dset creation property list"); - if(H5P_get(plist, H5D_CRT_ALLOC_TIME_NAME, &alloc_time) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve space allocation time"); - /*------------------------------------------------------------------------- * Modify the dataset storage *------------------------------------------------------------------------- */ /* Save the new dataspace in the file if necessary */ - if(H5S_modify(&(dset->ent), space) < 0) + if(H5S_modify(&(dset->ent), space, TRUE) < 0) HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update file with new dataspace"); /* Allocate space for the new parts of the dataset, if appropriate */ - if(expand && alloc_time==H5D_ALLOC_TIME_EARLY) - if(H5D_alloc_storage(dset->ent.file, dset, H5D_ALLOC_EXTEND) < 0) + if(expand && dset->alloc_time==H5D_ALLOC_TIME_EARLY) + if(H5D_alloc_storage(dset->ent.file, dset, H5D_ALLOC_EXTEND, TRUE, FALSE) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize dataset storage"); @@ -4387,6 +4383,10 @@ H5D_set_extent(H5D_t *dset, const hsize_t *size) *------------------------------------------------------------------------- */ if(shrink && H5D_CHUNKED == dset->layout.type) { + /* Get the dataset creation property list */ + if(NULL == (plist = H5I_object(dset->dcpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dset creation property list"); + /* Remove excess chunks */ if(H5F_istore_prune_by_extent(dset->ent.file, &dset->layout, space) < 0) HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to remove chunks "); @@ -4398,8 +4398,6 @@ H5D_set_extent(H5D_t *dset, const hsize_t *size) } /* end if */ done: - if(space) - H5S_close(space); FUNC_LEAVE(ret_value); } @@ -4449,7 +4447,7 @@ H5D_flush(H5F_t *f) if(NULL==(dataset=H5I_object_verify(id_list[j], H5I_DATASET))) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to get dataset object"); if(dataset->layout.type==H5D_COMPACT && dataset->layout.dirty) - if(H5O_modify(&(dataset->ent), H5O_LAYOUT, 0, 0, &(dataset->layout))<0) + if(H5O_modify(&(dataset->ent), H5O_LAYOUT, 0, 0, 1, &(dataset->layout))<0) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to update layout message"); dataset->layout.dirty = FALSE; } @@ -4459,7 +4457,7 @@ done: if(id_list!=NULL) H5MM_xfree(id_list); FUNC_LEAVE(ret_value); -} +} /* end H5D_flush() */ /*------------------------------------------------------------------------- diff --git a/src/H5Dcontig.c b/src/H5Dcontig.c index fce1ba9..a63a9ce 100644 --- a/src/H5Dcontig.c +++ b/src/H5Dcontig.c @@ -36,8 +36,11 @@ static int interface_initialize_g = 0; /* Declare a PQ free list to manage the sieve buffer information */ H5FL_BLK_DEFINE(sieve_buf); -/* Extern the free list to manage blocks of type conversion data */ -H5FL_BLK_EXTERN(type_conv); +/* Declare the free list to manage blocks of non-zero fill-value data */ +H5FL_BLK_DEFINE_STATIC(non_zero_fill); + +/* Declare the free list to manage blocks of zero fill-value data */ +H5FL_BLK_DEFINE_STATIC(zero_fill); /*------------------------------------------------------------------------- @@ -56,11 +59,10 @@ H5FL_BLK_EXTERN(type_conv); */ herr_t H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, - struct H5P_genplist_t *dc_plist, const struct H5S_t *space, - size_t elmt_size) + struct H5P_genplist_t *dc_plist, const struct H5O_efl_t *efl, + const struct H5S_t *space, + const struct H5O_fill_t *fill, size_t elmt_size) { - H5O_fill_t fill; /* Fill value information */ - H5O_efl_t efl; /* External File List info */ hssize_t snpoints; /* Number of points in space (for error checking) */ size_t npoints; /* Number of points in space */ size_t ptsperbuf; /* Maximum # of points which fit in the buffer */ @@ -77,6 +79,7 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, unsigned blocks_written=0; /* Flag to indicate that chunk was actually written */ unsigned using_mpi=0; /* Flag to indicate that the file is being accessed with an MPI-capable file driver */ #endif /* H5_HAVE_PARALLEL */ + int non_zero_fill_f=(-1); /* Indicate that a non-zero fill-value was used */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5F_contig_fill, FAIL); @@ -91,12 +94,6 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, assert(space); assert(elmt_size>0); - /* Get necessary properties from dataset creation property list */ - if(H5P_get(dc_plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) - HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "can't get fill value"); - if(H5P_get(dc_plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve external file list"); - #ifdef H5_HAVE_PARALLEL /* Retrieve up MPI parameters */ if(IS_H5FD_MPIO(f)) { @@ -136,46 +133,62 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, assert(snpoints>=0); H5_ASSIGN_OVERFLOW(npoints,snpoints,hssize_t,size_t); - /* Don't write default fill-values to external files */ - if(efl.nused>0 && !fill.buf) - HGOTO_DONE(SUCCEED); - - /* If fill value is library default, use the element size */ - if(!fill.buf) - fill.size=elmt_size; + /* If fill value is not library default, use it to set the element size */ + if(fill->buf) + elmt_size=fill->size; /* * Fill the entire current extent with the fill value. We can do * this quite efficiently by making sure we copy the fill value * in relatively large pieces. */ - ptsperbuf = MAX(1, bufsize/fill.size); - bufsize = ptsperbuf*fill.size; - - /* Allocate temporary buffer */ - if ((buf=H5FL_BLK_ALLOC(type_conv,bufsize,0))==NULL) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fill buffer"); - - /* Fill the buffer with the user's fill value */ - if(fill.buf) - H5V_array_fill(buf, fill.buf, fill.size, ptsperbuf); - else /* Fill the buffer with the default fill value */ - HDmemset(buf,0,bufsize); + ptsperbuf = MAX(1, bufsize/elmt_size); + bufsize = ptsperbuf*elmt_size; + + /* Fill the buffer with the user's fill value */ + if(fill->buf) { + /* Allocate temporary buffer */ + if ((buf=H5FL_BLK_MALLOC(non_zero_fill,bufsize))==NULL) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fill buffer"); + + H5V_array_fill(buf, fill->buf, elmt_size, ptsperbuf); + + /* Indicate that a non-zero fill buffer was used */ + non_zero_fill_f=1; + } /* end if */ + else { /* Fill the buffer with the default fill value */ + htri_t buf_avail; + + /* Check if there is an already zeroed out buffer available */ + buf_avail=H5FL_BLK_AVAIL(zero_fill,bufsize); + assert(buf_avail!=FAIL); + + /* Allocate temporary buffer (zeroing it if no buffer is available) */ + if(!buf_avail) + buf=H5FL_BLK_CALLOC(zero_fill,bufsize); + else + buf=H5FL_BLK_MALLOC(zero_fill,bufsize); + if(buf==NULL) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fill buffer"); + + /* Indicate that a zero fill buffer was used */ + non_zero_fill_f=0; + } /* end else */ - /* Start at the beginning of the dataset */ - addr = 0; + /* Start at the beginning of the dataset */ + addr = 0; - /* Loop through writing the fill value to the dataset */ - while (npoints>0) { - size = MIN(ptsperbuf, npoints) * fill.size; + /* Loop through writing the fill value to the dataset */ + while (npoints>0) { + size = MIN(ptsperbuf, npoints) * elmt_size; #ifdef H5_HAVE_PARALLEL /* Check if this file is accessed with an MPI-capable file driver */ if(using_mpi) { /* Round-robin write the chunks out from only one process */ if(mpi_round==mpi_rank) { - if (H5F_seq_write(f, dxpl_id, layout, dc_plist, space, - fill.size, size, addr, buf)<0) + if (H5F_seq_write(f, dxpl_id, layout, dc_plist, efl, space, + elmt_size, size, addr, buf)<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to write fill value to dataset"); } /* end if */ mpi_round=(++mpi_round)%mpi_size; @@ -185,8 +198,8 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, } /* end if */ else { #endif /* H5_HAVE_PARALLEL */ - if (H5F_seq_write(f, dxpl_id, layout, dc_plist, space, - fill.size, size, addr, buf)<0) + if (H5F_seq_write(f, dxpl_id, layout, dc_plist, efl, space, + elmt_size, size, addr, buf)<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to write fill value to dataset"); #ifdef H5_HAVE_PARALLEL } /* end else */ @@ -211,8 +224,13 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, done: /* Free the buffer for fill values */ - if (buf) - H5FL_BLK_FREE(type_conv,buf); + if (buf) { + assert(non_zero_fill_f>=0); + if(non_zero_fill_f) + H5FL_BLK_FREE(non_zero_fill,buf); + else + H5FL_BLK_FREE(zero_fill,buf); + } /* end if */ FUNC_LEAVE(ret_value); } @@ -661,7 +679,7 @@ H5F_contig_readv(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr, } /* end if */ else { /* Allocate room for the data sieve buffer */ - if (NULL==(f->shared->sieve_buf=H5FL_BLK_ALLOC(sieve_buf,f->shared->sieve_buf_size,0))) + if (NULL==(f->shared->sieve_buf=H5FL_BLK_MALLOC(sieve_buf,f->shared->sieve_buf_size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); /* Determine the new sieve buffer size & location */ @@ -1128,7 +1146,7 @@ H5F_contig_writev(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr, } /* end if */ else { /* Allocate room for the data sieve buffer */ - if (NULL==(f->shared->sieve_buf=H5FL_BLK_ALLOC(sieve_buf,f->shared->sieve_buf_size,0))) + if (NULL==(f->shared->sieve_buf=H5FL_BLK_MALLOC(sieve_buf,f->shared->sieve_buf_size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); /* Determine the new sieve buffer size & location */ diff --git a/src/H5Distore.c b/src/H5Distore.c index ea74165..f617092 100644 --- a/src/H5Distore.c +++ b/src/H5Distore.c @@ -862,7 +862,7 @@ H5F_istore_init (H5F_t *f) HDmemset (rdcc, 0, sizeof(H5F_rdcc_t)); if (f->shared->rdcc_nbytes>0 && f->shared->rdcc_nelmts>0) { rdcc->nslots = f->shared->rdcc_nelmts; - rdcc->slot = H5FL_ARR_ALLOC (H5F_rdcc_ent_ptr_t,rdcc->nslots,1); + rdcc->slot = H5FL_ARR_CALLOC (H5F_rdcc_ent_ptr_t,rdcc->nslots); if (NULL==rdcc->slot) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); } @@ -1440,7 +1440,7 @@ H5F_istore_lock(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL, "unable to preempt chunk(s) from cache"); /* Create a new entry */ - ent = H5FL_ALLOC(H5F_rdcc_ent_t,0); + ent = H5FL_MALLOC(H5F_rdcc_ent_t); ent->locked = 0; ent->dirty = FALSE; ent->chunk_size = chunk_size; @@ -1943,8 +1943,9 @@ H5F_istore_write(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, #ifdef H5_HAVE_PARALLEL /* Additional sanity check when operating in parallel */ - if (chunk_addr==HADDR_UNDEF || pline.nfilters>0) + if (chunk_addr==HADDR_UNDEF || pline.nfilters>0) { HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "unable to locate raw data chunk"); + } #endif /* H5_HAVE_PARALLEL */ /* @@ -2312,7 +2313,7 @@ done: */ herr_t H5F_istore_allocate(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, - const hsize_t *space_dim, H5P_genplist_t *dc_plist) + const hsize_t *space_dim, H5P_genplist_t *dc_plist, hbool_t full_overwrite) { hssize_t chunk_offset[H5O_LAYOUT_NDIMS]; /* Offset of current chunk */ hsize_t chunk_size; /* Size of chunk in bytes */ @@ -2407,7 +2408,7 @@ H5F_istore_allocate(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, } /* end for */ /* Check if fill values should be written to blocks */ - if(fill_time != H5D_FILL_TIME_NEVER) { + if(fill_time != H5D_FILL_TIME_NEVER && !full_overwrite) { /* Allocate chunk buffer for processes to use when writing fill values */ H5_CHECK_OVERFLOW(chunk_size,hsize_t,size_t); if (NULL==(chunk = H5MM_malloc((size_t)chunk_size))) @@ -2484,7 +2485,7 @@ H5F_istore_allocate(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to allocate chunk"); /* Check if fill values should be written to blocks */ - if(fill_time != H5D_FILL_TIME_NEVER) { + if(fill_time != H5D_FILL_TIME_NEVER && !full_overwrite) { #ifdef H5_HAVE_PARALLEL /* Check if this file is accessed with an MPI-capable file driver */ if(using_mpi) { diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h index 7f2a0ce..cfef073 100644 --- a/src/H5Dprivate.h +++ b/src/H5Dprivate.h @@ -147,44 +147,24 @@ typedef struct H5D_t { H5G_entry_t ent; /* cached object header stuff */ H5T_t *type; /* datatype of this dataset */ + H5S_t *space; /* dataspace of this dataset */ hid_t dcpl_id; /* dataset creation property id */ H5O_layout_t layout; /* data layout */ + /* Cache some frequently accessed values from the DCPL */ + H5O_efl_t efl; /* External file list information */ + H5D_alloc_time_t alloc_time; /* Dataset allocation time */ + H5D_fill_time_t fill_time; /* Dataset fill value writing time */ + H5O_fill_t fill; /* Dataset fill value information */ } H5D_t; /* Functions defined in H5D.c */ H5_DLL herr_t H5D_init(void); - -H5_DLL herr_t H5D_update_entry_cache(H5F_t *f, H5G_entry_t *ent, H5G_entry_t *loc, - const char *name, const H5S_t *space, - H5P_genplist_t *new_plist, H5O_layout_t *layout, - H5T_t *type, hbool_t allocate_header, - haddr_t header); -H5_DLL herr_t H5D_update_external_storage_cache(H5F_t *file, H5G_entry_t *ent, - H5O_efl_t *efl, H5O_layout_t *layout); - -H5_DLL H5D_t *H5D_create(H5G_entry_t *loc, const char *name, - const H5T_t *type, const H5S_t *space, - hid_t dcpl_id); -H5_DLL H5D_t *H5D_open(H5G_entry_t *loc, const char *name); +H5_DLL hid_t H5D_open(H5G_entry_t *ent); H5_DLL herr_t H5D_close(H5D_t *dataset); H5_DLL htri_t H5D_isa(H5G_entry_t *ent); -H5_DLL herr_t H5D_read(H5D_t *dataset, const H5T_t *mem_type, - const H5S_t *mem_space, const H5S_t *file_space, - hid_t dset_xfer_plist, void *buf/*out*/); -H5_DLL herr_t H5D_write(H5D_t *dataset, const H5T_t *mem_type, - const H5S_t *mem_space, const H5S_t *file_space, - hid_t dset_xfer_plist, const void *buf); H5_DLL herr_t H5D_extend(H5D_t *dataset, const hsize_t *size); H5_DLL H5G_entry_t *H5D_entof(H5D_t *dataset); H5_DLL H5T_t *H5D_typeof(H5D_t *dset); -H5_DLL H5S_t *H5D_get_space(H5D_t *dset); -H5_DLL H5D_t * H5D_open_oid(H5G_entry_t *ent); -H5_DLL H5F_t * H5D_get_file(const H5D_t *dset); -H5_DLL hsize_t H5D_get_storage_size(H5D_t *dset); -H5_DLL haddr_t H5D_get_offset(H5D_t *dset); -H5_DLL void *H5D_vlen_get_buf_size_alloc(size_t size, void *info); -H5_DLL herr_t H5D_vlen_get_buf_size(void *elem, hid_t type_id, hsize_t ndim, - hssize_t *point, void *op_data); H5_DLL herr_t H5D_crt_copy(hid_t new_plist_t, hid_t old_plist_t, void *copy_data); H5_DLL herr_t H5D_crt_close(hid_t dxpl_id, void *close_data); @@ -192,7 +172,6 @@ H5_DLL herr_t H5D_xfer_create(hid_t dxpl_id, void *create_data); H5_DLL herr_t H5D_xfer_copy(hid_t new_plist_id, hid_t old_plist_id, void *copy_data); H5_DLL herr_t H5D_xfer_close(hid_t dxpl_id, void *close_data); -H5_DLL herr_t H5D_set_extent(H5D_t *dataset, const hsize_t *size); H5_DLL herr_t H5D_flush(H5F_t *f); diff --git a/src/H5Dseq.c b/src/H5Dseq.c index 6176003..9592725 100644 --- a/src/H5Dseq.c +++ b/src/H5Dseq.c @@ -59,9 +59,9 @@ static int interface_initialize_g = 0; */ herr_t H5F_seq_read(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, - H5P_genplist_t *dc_plist, - const H5S_t *file_space, size_t elmt_size, - size_t seq_len, hsize_t dset_offset, void *buf/*out*/) + H5P_genplist_t *dc_plist, const H5O_efl_t *efl, + const H5S_t *file_space, size_t elmt_size, + size_t seq_len, hsize_t dset_offset, void *buf/*out*/) { herr_t ret_value=SUCCEED; /* Return value */ @@ -70,10 +70,11 @@ H5F_seq_read(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, /* Check args */ assert(f); assert(layout); + assert(efl); assert(buf); assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); - if (H5F_seq_readv(f, dxpl_id, layout, dc_plist, file_space, elmt_size, 1, &seq_len, &dset_offset, buf)<0) + if (H5F_seq_readv(f, dxpl_id, layout, dc_plist, efl, file_space, elmt_size, 1, &seq_len, &dset_offset, buf)<0) HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "vector read failed"); done: @@ -104,9 +105,9 @@ done: */ herr_t H5F_seq_write(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout, - H5P_genplist_t *dc_plist, - const H5S_t *file_space, size_t elmt_size, - size_t seq_len, hsize_t dset_offset, const void *buf) + H5P_genplist_t *dc_plist, const H5O_efl_t *efl, + const H5S_t *file_space, size_t elmt_size, + size_t seq_len, hsize_t dset_offset, const void *buf) { herr_t ret_value=SUCCEED; /* Return value */ @@ -115,10 +116,11 @@ H5F_seq_write(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout, /* Check args */ assert(f); assert(layout); + assert(efl); assert(buf); assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); - if (H5F_seq_writev(f, dxpl_id, layout, dc_plist, file_space, elmt_size, 1, &seq_len, &dset_offset, buf)<0) + if (H5F_seq_writev(f, dxpl_id, layout, dc_plist, efl, file_space, elmt_size, 1, &seq_len, &dset_offset, buf)<0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vector write failed"); done: @@ -151,7 +153,7 @@ done: */ herr_t H5F_seq_readv(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, - H5P_genplist_t *dc_plist, + H5P_genplist_t *dc_plist, const H5O_efl_t *efl, const H5S_t *file_space, size_t elmt_size, size_t nseq, size_t seq_len_arr[], hsize_t dset_offset_arr[], void *_buf/*out*/) @@ -172,7 +174,6 @@ H5F_seq_readv(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, unsigned u; /*counters */ size_t v; /*counters */ int i,j; /*counters */ - struct H5O_efl_t efl; /* External File List info */ #ifdef H5_HAVE_PARALLEL H5FD_mpio_xfer_t xfer_mode=H5FD_MPIO_INDEPENDENT; H5P_genplist_t *plist=NULL; /* Property list */ @@ -184,6 +185,7 @@ H5F_seq_readv(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, /* Check args */ assert(f); assert(layout); + assert(efl); assert(real_buf); /* Make certain we have the correct type of property list */ assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); @@ -221,14 +223,10 @@ H5F_seq_readv(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, HGOTO_ERROR (H5E_DATASET, H5E_READERROR, FAIL, "collective access on non-contiguous datasets not supported yet"); #endif /* H5_HAVE_PARALLEL */ - /* Get necessary properties from property list */ - if(H5P_get(dc_plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get EFL value"); - switch (layout->type) { case H5D_CONTIGUOUS: /* Read directly from file if the dataset is in an external file */ - if (efl.nused>0) { + if (efl->nused>0) { /* Iterate through the sequence vectors */ for(v=0; v0) + if (efl->nused>0) HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "chunking and external files are mutually exclusive"); /* Compute the file offset coordinates and hyperslab size */ @@ -542,7 +540,7 @@ done: */ herr_t H5F_seq_writev(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout, - H5P_genplist_t *dc_plist, + H5P_genplist_t *dc_plist, const H5O_efl_t *efl, const H5S_t *file_space, size_t elmt_size, size_t nseq, size_t seq_len_arr[], hsize_t dset_offset_arr[], const void *_buf) @@ -563,7 +561,6 @@ H5F_seq_writev(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout, unsigned u; /*counters */ size_t v; /*counters */ int i,j; /*counters */ - struct H5O_efl_t efl; /* External File List info */ #ifdef H5_HAVE_PARALLEL H5FD_mpio_xfer_t xfer_mode=H5FD_MPIO_INDEPENDENT; H5P_genplist_t *plist=NULL; /* Property list */ @@ -575,6 +572,7 @@ H5F_seq_writev(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout, /* Check args */ assert(f); assert(layout); + assert(efl); assert(real_buf); /* Make certain we have the correct type of property list */ assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); @@ -612,14 +610,10 @@ H5F_seq_writev(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout, HGOTO_ERROR (H5E_DATASET, H5E_WRITEERROR, FAIL, "collective access on chunked datasets not supported yet"); #endif /* H5_HAVE_PARALLEL */ - /* Get necessary properties from property list */ - if(H5P_get(dc_plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get EFL value"); - switch (layout->type) { case H5D_CONTIGUOUS: /* Write directly to file if the dataset is in an external file */ - if (efl.nused>0) { + if (efl->nused>0) { /* Iterate through the sequence vectors */ for(v=0; v0) + if (efl->nused>0) HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "chunking and external files are mutually exclusive"); /* Compute the file offset coordinates and hyperslab size */ diff --git a/src/H5E.c b/src/H5E.c index 98bfe1d..8b9ab13 100644 --- a/src/H5E.c +++ b/src/H5E.c @@ -72,6 +72,8 @@ static const H5E_major_mesg_t H5E_major_mesg_g[] = { {H5E_VFL, "Virtual File Layer"}, {H5E_TBBT, "Threaded, Balanced, Binary Trees"}, {H5E_FPHDF5, "Flexible Parallel HDF5"}, + {H5E_TST, "Ternary Search Trees"}, + {H5E_RS, "Reference Counted Strings"}, }; static const H5E_minor_mesg_t H5E_minor_mesg_g[] = { diff --git a/src/H5Epublic.h b/src/H5Epublic.h index 09e5af2..607bbf2 100644 --- a/src/H5Epublic.h +++ b/src/H5Epublic.h @@ -101,7 +101,9 @@ typedef enum H5E_major_t { H5E_REFERENCE, /*References */ H5E_VFL, /*Virtual File Layer */ H5E_TBBT, /*Threaded, Balanced, Binary Trees */ - H5E_FPHDF5 /*Flexible Parallel HDF5 */ + H5E_FPHDF5, /*Flexible Parallel HDF5 */ + H5E_TST, /*Ternary Search Trees */ + H5E_RS /*Reference Counted Strings */ } H5E_major_t; /* Declare an enumerated type which holds all the valid minor HDF error codes */ diff --git a/src/H5F.c b/src/H5F.c index 492dc42..bafda9a 100644 --- a/src/H5F.c +++ b/src/H5F.c @@ -243,7 +243,7 @@ H5F_init_interface(void) assert(H5P_CLS_FILE_CREATE_g!=-1); /* Get the pointer to file creation class */ - if(NULL == (crt_pclass = H5I_object_verify(H5P_CLS_FILE_CREATE_g, H5I_GENPROP_CLS))) + if(NULL == (crt_pclass = H5I_object(H5P_CLS_FILE_CREATE_g))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list class"); /* Get the number of properties in the class */ @@ -326,7 +326,7 @@ H5F_init_interface(void) assert(H5P_CLS_FILE_ACCESS_g!=-1); /* Get the pointer to file creation class */ - if(NULL == (acs_pclass = H5I_object_verify(H5P_CLS_FILE_ACCESS_g, H5I_GENPROP_CLS))) + if(NULL == (acs_pclass = H5I_object(H5P_CLS_FILE_ACCESS_g))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list class"); /* Get the number of properties in the class */ @@ -407,7 +407,7 @@ H5F_init_interface(void) assert(H5P_CLS_MOUNT_g!=-1); /* Get the pointer to file mount class */ - if(NULL == (mnt_pclass = H5I_object_verify(H5P_CLS_MOUNT_g, H5I_GENPROP_CLS))) + if(NULL == (mnt_pclass = H5I_object(H5P_CLS_MOUNT_g))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list class"); /* Get the number of properties in the class */ @@ -503,7 +503,7 @@ H5F_acs_create(hid_t fapl_id, void UNUSED *copy_data) FUNC_ENTER_NOAPI(H5F_acs_create, FAIL); /* Check argument */ - if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS))) + if(NULL == (plist = H5I_object(fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list"); /* Retrieve properties */ @@ -558,7 +558,7 @@ H5F_acs_close(hid_t fapl_id, void UNUSED *close_data) FUNC_ENTER_NOAPI(H5F_acs_close, FAIL); /* Check argument */ - if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS))) + if(NULL == (plist = H5I_object(fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list"); if(H5P_get(plist, H5F_ACS_FILE_DRV_ID_NAME, &driver_id) < 0) @@ -610,9 +610,9 @@ H5F_acs_copy(hid_t new_fapl_id, hid_t old_fapl_id, void UNUSED *copy_data) FUNC_ENTER_NOAPI(H5F_acs_copy, FAIL); - if(NULL == (new_plist = H5I_object_verify(new_fapl_id, H5I_GENPROP_LST))) + if(NULL == (new_plist = H5I_object(new_fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list"); - if(NULL == (old_plist = H5I_object_verify(old_fapl_id, H5I_GENPROP_LST))) + if(NULL == (old_plist = H5I_object(old_fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list"); /* Get values from old property list */ @@ -1375,7 +1375,7 @@ H5Fis_hdf5(const char *name) HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "no file name specified"); /* Open the file at the virtual file layer */ - if (NULL==(file=H5FD_open(name, H5F_ACC_RDONLY, H5P_DEFAULT, HADDR_UNDEF))) + if (NULL==(file=H5FD_open(name, H5F_ACC_RDONLY, H5P_FILE_ACCESS_DEFAULT, HADDR_UNDEF))) HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to open file"); /* The file is an hdf5 file if the hdf5 file signature can be found */ @@ -1428,13 +1428,13 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id) FUNC_ENTER_NOINIT(H5F_new); - if (NULL==(f=H5FL_ALLOC(H5F_t,1))) + if (NULL==(f=H5FL_CALLOC(H5F_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); if (shared) { f->shared = shared; } else { - f->shared = H5FL_ALLOC(H5F_file_t,1); + f->shared = H5FL_CALLOC(H5F_file_t); f->shared->boot_addr = HADDR_UNDEF; f->shared->base_addr = HADDR_UNDEF; f->shared->freespace_addr = HADDR_UNDEF; @@ -1445,16 +1445,19 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id) * new file handle. We do this early because some values might need * to change as the file is being opened. */ - if(H5P_DEFAULT == fcpl_id) - fcpl_id = H5P_FILE_CREATE_DEFAULT; - if(NULL == (plist = H5P_object_verify(fcpl_id,H5P_FILE_CREATE))) + if(NULL == (plist = H5I_object(fcpl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not property list"); f->shared->fcpl_id = H5P_copy_plist(plist); + /* Get the FCPL values to cache */ + if(H5P_get(plist, H5F_CRT_ADDR_BYTE_NUM_NAME, &f->shared->sizeof_addr)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get byte number for address"); + if(H5P_get(plist, H5F_CRT_OBJ_BYTE_NUM_NAME, &f->shared->sizeof_size)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get byte number for object size"); + if(H5P_get(plist, H5F_CRT_SYM_LEAF_NAME, &f->shared->sym_leaf_k)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get byte number for object size"); - if(H5P_DEFAULT == fapl_id) - fapl_id = H5P_FILE_ACCESS_DEFAULT; - if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS))) + if(NULL == (plist = H5I_object(fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not file access property list"); if(H5P_get(plist, H5F_ACS_META_CACHE_SIZE_NAME, &(f->shared->mdc_nelmts)) < 0) @@ -1486,6 +1489,10 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id) /* Create the chunk cache */ H5F_istore_init(f); + + /* Create the file's "open object" information */ + if(H5FO_create(f)<0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create open object TBBT"); } /* end else */ f->shared->nrefs++; @@ -1561,13 +1568,17 @@ H5F_dest(H5F_t *f) f->shared->root_grp=NULL; } if (H5AC_dest(f)) { - HERROR(H5E_FILE, H5E_CANTINIT, "problems closing file"); + HERROR(H5E_FILE, H5E_CANTRELEASE, "problems closing file"); ret_value = FAIL; /*but keep going*/ } if (H5F_istore_dest (f)<0) { - HERROR(H5E_FILE, H5E_CANTINIT, "problems closing file"); + HERROR(H5E_FILE, H5E_CANTRELEASE, "problems closing file"); ret_value = FAIL; /*but keep going*/ } + if (H5FO_dest(f)<0) { + HERROR(H5E_FILE, H5E_CANTRELEASE, "problems closing file"); + ret_value = FAIL; /*but keep going*/ + } /* end if */ f->shared->cwfs = H5MM_xfree (f->shared->cwfs); /* Free the data sieve buffer, if it's been allocated */ @@ -1837,6 +1848,16 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id) * empty or not. */ if (0==H5FD_get_eof(lf) && (flags & H5F_ACC_RDWR)) { + /* Get values to cache from the FCPL */ + if(H5P_get(c_plist, H5F_CRT_ADDR_BYTE_NUM_NAME,&shared->sizeof_addr)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set byte number in an address"); + if(H5P_get(c_plist, H5F_CRT_OBJ_BYTE_NUM_NAME, &shared->sizeof_size)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set byte number for object size"); + if(H5P_get(c_plist, H5F_CRT_SYM_LEAF_NAME, &shared->sym_leaf_k)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set rank for symbol table leaf nodes"); + if(H5P_get(c_plist, H5F_CRT_BTREE_RANK_NAME, &shared->btree_k[0])<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "unable to get rank for btree internal nodes"); + /* * The superblock starts immediately after the user-defined header, * which we have already insured is a proper size. The base address @@ -1903,6 +1924,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id) HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad byte number in an address"); if(H5P_set(c_plist, H5F_CRT_ADDR_BYTE_NUM_NAME,&sizeof_addr)<0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set byte number in an address"); + shared->sizeof_addr=sizeof_addr; /* Keep a local copy also */ /* Size of file sizes */ sizeof_size = *p++; @@ -1911,6 +1933,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id) HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad byte number for object size"); if(H5P_set(c_plist, H5F_CRT_OBJ_BYTE_NUM_NAME, &sizeof_size)<0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set byte number for object size"); + shared->sizeof_size=sizeof_size; /* Keep a local copy also */ /* Reserved byte */ p++; @@ -1921,6 +1944,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id) HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, NULL, "bad symbol table leaf node 1/2 rank"); if(H5P_set(c_plist, H5F_CRT_SYM_LEAF_NAME, &sym_leaf_k)<0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set rank for symbol table leaf nodes"); + shared->sym_leaf_k=sym_leaf_k; /* Keep a local copy also */ /* Need 'get' call to set other array values */ if(H5P_get(c_plist, H5F_CRT_BTREE_RANK_NAME, btree_k)<0) @@ -1930,6 +1954,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id) HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, NULL, "bad 1/2 rank for btree internal nodes"); if(H5P_set(c_plist, H5F_CRT_BTREE_RANK_NAME, btree_k)<0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set rank for btree internal nodes"); + HDmemcpy(shared->btree_k,btree_k,sizeof(int)*H5B_NUM_BTREE_ID); /* Keep a local copy also */ /* File consistency flags. Not really used yet */ UINT32DECODE(p, shared->consist_flags); @@ -2033,9 +2058,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id) * second time or later, verify the access property list value matches * the degree in shared file structure. */ - if(H5P_DEFAULT == fapl_id) - fapl_id = H5P_FILE_ACCESS_DEFAULT; - if(NULL == (a_plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS))) + if(NULL == (a_plist = H5I_object(fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not file access property list"); if(H5P_get(a_plist, H5F_CLOSE_DEGREE_NAME, &fc_degree) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get file close degree"); @@ -2138,14 +2161,16 @@ H5Fcreate(const char *filename, unsigned flags, hid_t fcpl_id, /* Check file creation property list */ if(H5P_DEFAULT == fcpl_id) fcpl_id = H5P_FILE_CREATE_DEFAULT; - if(TRUE != H5P_isa_class(fcpl_id, H5P_FILE_CREATE)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not file create property list"); + else + if(TRUE != H5P_isa_class(fcpl_id, H5P_FILE_CREATE)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not file create property list"); /* Check the file access property list */ if(H5P_DEFAULT == fapl_id) fapl_id = H5P_FILE_ACCESS_DEFAULT; - if(TRUE != H5P_isa_class(fapl_id, H5P_FILE_ACCESS)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not file access property list"); + else + if(TRUE != H5P_isa_class(fapl_id, H5P_FILE_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not file access property list"); /* * Adjust bit flags by turning on the creation bit and making sure that @@ -2230,11 +2255,12 @@ H5Fopen(const char *filename, unsigned flags, hid_t fapl_id) HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file open flags"); if(H5P_DEFAULT == fapl_id) fapl_id = H5P_FILE_ACCESS_DEFAULT; - if(TRUE != H5P_isa_class(fapl_id, H5P_FILE_ACCESS)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not file access property list"); + else + if(TRUE != H5P_isa_class(fapl_id, H5P_FILE_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not file access property list"); /* Open the file */ - if (NULL==(new_file=H5F_open(filename, flags, H5P_DEFAULT, fapl_id))) + if (NULL==(new_file=H5F_open(filename, flags, H5P_FILE_CREATE_DEFAULT, fapl_id))) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to open file"); /* Get an atom for the file */ @@ -2399,8 +2425,6 @@ H5F_flush(H5F_t *f, H5F_scope_t scope, hbool_t invalidate, int freespace_vers; /* Freespace info version */ int obj_dir_vers; /* Object header info version */ int share_head_vers;/* Shared header info version */ - int btree_k[H5B_NUM_BTREE_ID]; /* B-tree size info */ - unsigned sym_leaf_k; /* Number of symbols in B-tree leafs */ H5P_genplist_t *plist; /* Property list */ herr_t ret_value; /* Return value */ @@ -2492,10 +2516,6 @@ H5F_flush(H5F_t *f, H5F_scope_t scope, hbool_t invalidate, HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get object directory version"); if(H5P_get(plist, H5F_CRT_SHARE_HEAD_VERS_NAME, &share_head_vers) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get shared-header format version"); - if(H5P_get(plist, H5F_CRT_SYM_LEAF_NAME, &sym_leaf_k) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get rank for symbol table leaf nodes"); - if(H5P_get(plist, H5F_CRT_BTREE_RANK_NAME, btree_k) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get rank for btree internal nodes"); /* encode the file boot block */ p = sbuf; @@ -2511,8 +2531,8 @@ H5F_flush(H5F_t *f, H5F_scope_t scope, hbool_t invalidate, assert (H5F_SIZEOF_SIZE(f)<=255); *p++ = (uint8_t)H5F_SIZEOF_SIZE(f); *p++ = 0; /*reserved */ - UINT16ENCODE(p, sym_leaf_k); - UINT16ENCODE(p, btree_k[H5B_SNODE_ID]); + UINT16ENCODE(p, f->shared->sym_leaf_k); + UINT16ENCODE(p, f->shared->btree_k[H5B_SNODE_ID]); UINT32ENCODE(p, f->shared->consist_flags); H5F_addr_encode(f, &p, f->shared->base_addr); H5F_addr_encode(f, &p, f->shared->freespace_addr); @@ -2904,6 +2924,7 @@ H5F_mount(H5G_entry_t *loc, const char *name, H5F_t *child, H5F_t *parent = NULL; /*file containing mount point */ int lt, rt, md, cmp; /*binary search indices */ H5G_entry_t *ent = NULL; /*temporary symbol table entry */ + H5RS_str_t *name_r; /* Ref-counted version of name */ herr_t ret_value = SUCCEED; /*return value */ FUNC_ENTER_NOINIT(H5F_mount); @@ -2975,8 +2996,11 @@ H5F_mount(H5G_entry_t *loc, const char *name, H5F_t *child, /* Search the open IDs and replace names for mount operation */ /* We pass H5G_UNKNOWN as object type; search all IDs */ - if (H5G_replace_name( H5G_UNKNOWN, loc, name, NULL, NULL, NULL, OP_MOUNT )<0) + name_r=H5RS_wrap(name); + assert(name_r); + if (H5G_replace_name( H5G_UNKNOWN, loc, name_r, NULL, NULL, NULL, OP_MOUNT )<0) HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "unable to replace name"); + H5RS_decr(name_r); done: if (ret_value<0 && mount_point) @@ -3050,7 +3074,7 @@ H5F_unmount(H5G_entry_t *loc, const char *name) for (i=0; imtab.nmounts; i++) { if (parent->mtab.child[i].file==child) { /* Search the open IDs replace names to reflect unmount operation */ - if (H5G_replace_name( H5G_UNKNOWN, mnt_ent, mnt_ent->user_path, NULL, NULL, NULL, OP_UNMOUNT )<0) + if (H5G_replace_name( H5G_UNKNOWN, mnt_ent, mnt_ent->user_path_r, NULL, NULL, NULL, OP_UNMOUNT )<0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to replace name "); /* Unmount the child */ @@ -3181,6 +3205,74 @@ done: /*------------------------------------------------------------------------- + * Function: H5F_has_mount + * + * Purpose: Check if a file has mounted files within it. + * + * Return: Success: TRUE/FALSE + * Failure: Negative + * + * Programmer: Quincey Koziol + * Thursday, January 2, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +htri_t +H5F_has_mount(const H5F_t *file) +{ + htri_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5F_has_mount, FAIL); + + assert(file); + + if(file->mtab.nmounts>0) + ret_value=TRUE; + else + ret_value=FALSE; + +done: + FUNC_LEAVE(ret_value); +} /* end H5F_has_mount() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_is_mount + * + * Purpose: Check if a file is mounted within another file. + * + * Return: Success: TRUE/FALSE + * Failure: Negative + * + * Programmer: Quincey Koziol + * Thursday, January 2, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +htri_t +H5F_is_mount(const H5F_t *file) +{ + htri_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5F_is_mount, FAIL); + + assert(file); + + if(file->mtab.parent!=NULL) + ret_value=TRUE; + else + ret_value=FALSE; + +done: + FUNC_LEAVE(ret_value); +} /* end H5F_is_mount() */ + + +/*------------------------------------------------------------------------- * Function: H5Fmount * * Purpose: Mount file CHILD_ID onto the group specified by LOC_ID and @@ -3214,8 +3306,9 @@ H5Fmount(hid_t loc_id, const char *name, hid_t child_id, hid_t plist_id) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file"); if(H5P_DEFAULT == plist_id) plist_id = H5P_MOUNT_DEFAULT; - if(TRUE != H5P_isa_class(plist_id, H5P_MOUNT)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not property list"); + else + if(TRUE != H5P_isa_class(plist_id, H5P_MOUNT)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not property list"); /* Do the mount */ if (H5F_mount(loc, name, child, plist_id)<0) @@ -3307,7 +3400,7 @@ H5Freopen(hid_t file_id) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file"); /* Get a new "top level" file struct, sharing the same "low level" file struct */ - if (NULL==(new_file=H5F_new(old_file->shared, H5P_DEFAULT, H5P_DEFAULT))) + if (NULL==(new_file=H5F_new(old_file->shared, H5P_FILE_CREATE_DEFAULT, H5P_FILE_ACCESS_DEFAULT))) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to reopen file"); /* Keep old file's read/write intent in new file */ @@ -3373,27 +3466,14 @@ H5F_get_intent(const H5F_t *f) size_t H5F_sizeof_addr(const H5F_t *f) { - size_t sizeof_addr = 0; - H5P_genplist_t *plist; /* Property list */ - size_t ret_value; /* Return value */ - - FUNC_ENTER_NOAPI(H5F_sizeof_addr, 0); + /* Use FUNC_ENTER_NOINIT here to avoid performance issues */ + FUNC_ENTER_NOINIT(H5F_sizeof_addr); assert(f); assert(f->shared); - /* Get property list */ - if(NULL == (plist = H5I_object(f->shared->fcpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, UFAIL, "not a property list"); - - if(H5P_get(plist, H5F_CRT_ADDR_BYTE_NUM_NAME, &sizeof_addr)<0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, UFAIL, "can't get byte number for address"); - - /* Set return value */ - ret_value=sizeof_addr; - done: - FUNC_LEAVE(ret_value); + FUNC_LEAVE(f->shared->sizeof_addr); } @@ -3419,31 +3499,88 @@ done: size_t H5F_sizeof_size(const H5F_t *f) { - size_t sizeof_size = 0; - H5P_genplist_t *plist; /* Property list */ - size_t ret_value; /* Return value */ - - FUNC_ENTER_NOAPI(H5F_sizeof_size, 0); + /* Use FUNC_ENTER_NOINIT here to avoid performance issues */ + FUNC_ENTER_NOINIT(H5F_sizeof_size); assert(f); assert(f->shared); - /* Get property list */ - if(NULL == (plist = H5I_object(f->shared->fcpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, UFAIL, "not a property list"); +done: + FUNC_LEAVE(f->shared->sizeof_size); +} - if(H5P_get(plist, H5F_CRT_OBJ_BYTE_NUM_NAME, &sizeof_size)<0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, UFAIL, "can't get byte number for object size"); + +/*------------------------------------------------------------------------- + * Function: H5F_sym_leaf_k + * + * Purpose: Replaced a macro to retrieve the symbol table leaf size, + * now that the generic properties are being used to store + * the values. + * + * Return: Success: Non-negative, and the symbol table leaf size is + * returned. + * + * Failure: Negative (should not happen) + * + * Programmer: Raymond Lu + * slu@ncsa.uiuc.edu + * Oct 14 2001 + * + * Modifications: + * Quincey Koziol, 2001-10-15 + * Added this header and removed unused ret_value variable. + *------------------------------------------------------------------------- + */ +unsigned H5F_sym_leaf_k(const H5F_t *f) +{ + /* Use FUNC_ENTER_NOINIT here to avoid performance issues */ + FUNC_ENTER_NOINIT(H5F_sym_leaf_k); - /* Set return value */ - ret_value=sizeof_size; + assert(f); + assert(f->shared); done: - FUNC_LEAVE(ret_value); + FUNC_LEAVE(f->shared->sym_leaf_k); } /*------------------------------------------------------------------------- + * Function: H5F_Kvalue + * + * Purpose: Replaced a macro to retrieve a B-tree key value for a certain + * type, now that the generic properties are being used to store + * the B-tree values. + * + * Return: Success: Non-negative, and the B-tree key value is + * returned. + * + * Failure: Negative (should not happen) + * + * Programmer: Raymond Lu + * slu@ncsa.uiuc.edu + * Oct 14 2001 + * + * Modifications: + * Quincey Koziol, 2001-10-15 + * Added this header and removed unused ret_value variable. + *------------------------------------------------------------------------- + */ +int +H5F_Kvalue(const H5F_t *f, const H5B_class_t *type) +{ + /* Use FUNC_ENTER_NOINIT here to avoid performance issues */ + FUNC_ENTER_NOINIT(H5F_Kvalue); + + assert(f); + assert(f->shared); + assert(type); + +done: + FUNC_LEAVE(f->shared->btree_k[type->id]); +} /* end H5F_Kvalue() */ + + +/*------------------------------------------------------------------------- * Function: H5F_get_driver_id * * Purpose: Quick and dirty routine to retrieve the file's 'driver_id' value @@ -3509,23 +3646,35 @@ done: FUNC_LEAVE(ret_value); } /* end H5F_get_fileno() */ - + +/*------------------------------------------------------------------------- + * Function: H5F_get_base_addr + * + * Purpose: Quick and dirty routine to retrieve the file's 'base_addr' value + * (Mainly added to stop non-file routines from poking about in the + * H5F_t data structure) + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Raymond Lu + * December 20, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ haddr_t H5F_get_base_addr(const H5F_t *f) { - haddr_t ret_value; - - FUNC_ENTER_NOAPI(H5F_get_base_addr, FAIL); + /* Use FUNC_ENTER_NOINIT here to avoid performance issues */ + FUNC_ENTER_NOINIT(H5F_get_base_addr); assert(f); assert(f->shared); - /* Retrieve the file's base address */ - ret_value = f->shared->base_addr; - done: - FUNC_LEAVE(ret_value); -} + FUNC_LEAVE(f->shared->base_addr); +} /* end H5F_get_bass_addr() */ /*------------------------------------------------------------------------- @@ -3800,9 +3949,6 @@ H5F_debug(H5F_t *f, haddr_t UNUSED addr, FILE * stream, int indent, int fwidth) { hsize_t userblock_size; - int btree_k[H5B_NUM_BTREE_ID]; - unsigned sym_leaf_k; - size_t sizeof_addr, sizeof_size; int boot_vers, freespace_vers, obj_dir_vers, share_head_vers; H5P_genplist_t *plist; /* Property list */ herr_t ret_value=SUCCEED; /* Return value */ @@ -3822,15 +3968,6 @@ H5F_debug(H5F_t *f, haddr_t UNUSED addr, FILE * stream, int indent, if(H5P_get(plist, H5F_CRT_USER_BLOCK_NAME, &userblock_size)<0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get user block size"); - if(H5P_get(plist, H5F_CRT_SYM_LEAF_NAME, &sym_leaf_k)<0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get rank for symbol table leaf nodes"); - if(H5P_get(plist, H5F_CRT_BTREE_RANK_NAME, btree_k)<0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get rank for btree nodes"); - - if(H5P_get(plist, H5F_CRT_ADDR_BYTE_NUM_NAME, &sizeof_addr)<0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get byte number for an address"); - if(H5P_get(plist, H5F_CRT_OBJ_BYTE_NUM_NAME, &sizeof_size)<0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get byte number for object size"); if(H5P_get(plist, H5F_CRT_BOOT_VERS_NAME, &boot_vers)<0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get boot block version"); @@ -3868,14 +4005,14 @@ H5F_debug(H5F_t *f, haddr_t UNUSED addr, FILE * stream, int indent, HDfprintf(stream, "%*s%-*s %lu bytes\n", indent, "", fwidth, "Size of user block:", (unsigned long) userblock_size); HDfprintf(stream, "%*s%-*s %u bytes\n", indent, "", fwidth, - "Size of file size_t type:", (unsigned) sizeof_size); + "Size of file size_t type:", (unsigned) f->shared->sizeof_size); HDfprintf(stream, "%*s%-*s %u bytes\n", indent, "", fwidth, - "Size of file haddr_t type:", (unsigned) sizeof_addr); + "Size of file haddr_t type:", (unsigned) f->shared->sizeof_addr); HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, - "Symbol table leaf node 1/2 rank:", sym_leaf_k); + "Symbol table leaf node 1/2 rank:", f->shared->sym_leaf_k); HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, "Symbol table internal node 1/2 rank:", - (unsigned) (btree_k[H5B_SNODE_ID])); + (unsigned) (f->shared->btree_k[H5B_SNODE_ID])); HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, "Boot block version number:", (unsigned) boot_vers); HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, diff --git a/src/H5FD.c b/src/H5FD.c index 60ab418..70098ce 100644 --- a/src/H5FD.c +++ b/src/H5FD.c @@ -513,7 +513,7 @@ H5FD_fapl_copy(hid_t driver_id, const void *old_fapl) FUNC_ENTER_NOAPI(H5FD_fapl_copy, NULL); /* Check args */ - if (NULL==(driver=H5I_object_verify(driver_id,H5I_VFL))) + if (NULL==(driver=H5I_object(driver_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a driver ID"); if (!old_fapl) HGOTO_DONE(NULL); /*but no error*/ @@ -560,7 +560,7 @@ H5FD_fapl_free(hid_t driver_id, void *fapl) FUNC_ENTER_NOAPI(H5FD_fapl_free, FAIL); /* Check args */ - if (NULL==(driver=H5I_object_verify(driver_id,H5I_VFL))) + if (NULL==(driver=H5I_object(driver_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a driver ID"); /* Allow driver to free or do it ourselves */ @@ -606,7 +606,7 @@ H5FD_dxpl_copy(hid_t driver_id, const void *old_dxpl) FUNC_ENTER_NOAPI(H5FD_dxpl_copy, NULL); /* Check args */ - if (NULL==(driver=H5I_object_verify(driver_id,H5I_VFL))) + if (NULL==(driver=H5I_object(driver_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a driver ID"); if (!old_dxpl) HGOTO_DONE(NULL); /*but no error*/ @@ -653,7 +653,7 @@ H5FD_dxpl_free(hid_t driver_id, void *dxpl) FUNC_ENTER_NOAPI(H5FD_dxpl_free, FAIL); /* Check args */ - if (NULL==(driver=H5I_object_verify(driver_id,H5I_VFL))) + if (NULL==(driver=H5I_object(driver_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a driver ID"); /* Allow driver to free or do it ourselves */ @@ -731,6 +731,13 @@ H5FDopen(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr) FUNC_ENTER_API(H5FDopen, NULL); + /* Check arguments */ + if(H5P_DEFAULT == fapl_id) + fapl_id = H5P_FILE_ACCESS_DEFAULT; + else + if (TRUE!=H5P_isa_class(fapl_id,H5P_FILE_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list"); + if (NULL==(ret_value=H5FD_open(name, flags, fapl_id, maxaddr))) HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, NULL, "unable to open file"); @@ -773,10 +780,8 @@ H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr) FUNC_ENTER_NOAPI(H5FD_open, NULL); - /* Check arguments */ - if(H5P_DEFAULT == fapl_id) - fapl_id = H5P_FILE_ACCESS_DEFAULT; - if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS))) + /* Get file access property list */ + if(NULL == (plist = H5I_object(fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list"); if (0==maxaddr) @@ -786,7 +791,7 @@ H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get driver ID"); /* Get driver info */ - if (NULL==(driver=H5I_object_verify(driver_id,H5I_VFL))) + if (NULL==(driver=H5I_object(driver_id))) HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, NULL, "invalid driver ID in file access property list"); if (NULL==driver->open) HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, NULL, "file driver has no `open' method"); @@ -1392,7 +1397,7 @@ H5FD_alloc(H5FD_t *file, H5FD_mem_t type, hsize_t size) else { /* Attempt to allocate memory for temporary node */ - tmp = H5FL_ALLOC(H5FD_free_t,0); + tmp = H5FL_MALLOC(H5FD_free_t); #ifdef H5F_DEBUG if (H5DEBUG(F)) { HDfprintf(H5DEBUG(F), @@ -1807,7 +1812,7 @@ H5FD_free(H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size) tail_size=(file->accum_loc+file->accum_size)-tail_addr; /* Write out the part of the accumulator after the block to free */ - if (H5FD_write(file, H5FD_MEM_DEFAULT, H5P_DEFAULT, tail_addr, tail_size, file->meta_accum+(tail_addr-file->accum_loc))<0) + if (H5FD_write(file, H5FD_MEM_DEFAULT, H5P_DATASET_XFER_DEFAULT, tail_addr, tail_size, file->meta_accum+(tail_addr-file->accum_loc))<0) HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "file write request failed"); } /* end if */ @@ -1904,7 +1909,7 @@ H5FD_free(H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size) } /* end if */ else { /* Allocate a new node to hold the free block's information */ - if(NULL==(last = H5FL_ALLOC(H5FD_free_t,0))) + if(NULL==(last = H5FL_MALLOC(H5FD_free_t))) HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate node for free space info"); last->addr = addr; @@ -2336,8 +2341,9 @@ H5FDread(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size /* Get the default dataset transfer property list if the user didn't provide one */ if (H5P_DEFAULT == dxpl_id) dxpl_id= H5P_DATASET_XFER_DEFAULT; - if (TRUE!=H5P_isa_class(dxpl_id,H5P_DATASET_XFER)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list"); + else + if (TRUE!=H5P_isa_class(dxpl_id,H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list"); if (!buf) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null result buffer"); @@ -2563,8 +2569,9 @@ H5FDwrite(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t siz /* Get the default dataset transfer property list if the user didn't provide one */ if (H5P_DEFAULT == dxpl_id) dxpl_id= H5P_DATASET_XFER_DEFAULT; - if (TRUE!=H5P_isa_class(dxpl_id,H5P_DATASET_XFER)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list"); + else + if (TRUE!=H5P_isa_class(dxpl_id,H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list"); if (!buf) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null buffer"); diff --git a/src/H5FDfamily.c b/src/H5FDfamily.c index 00a98db..f6ad440 100644 --- a/src/H5FDfamily.c +++ b/src/H5FDfamily.c @@ -194,8 +194,11 @@ H5Pset_fapl_family(hid_t fapl_id, hsize_t memb_size, hid_t memb_fapl_id) /* Check arguments */ if(TRUE != H5P_isa_class(fapl_id, H5P_FILE_ACCESS)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list"); - if(memb_fapl_id!=H5P_DEFAULT && TRUE != H5P_isa_class(memb_fapl_id, H5P_FILE_ACCESS)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access list"); + if(H5P_DEFAULT == memb_fapl_id) + memb_fapl_id = H5P_FILE_ACCESS_DEFAULT; + else + if(TRUE != H5P_isa_class(memb_fapl_id, H5P_FILE_ACCESS)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access list"); /* * Initialize driver specific information. No need to copy it into the FA @@ -345,8 +348,8 @@ H5FD_family_fapl_copy(const void *_old_fa) memcpy(new_fa, old_fa, sizeof(H5FD_family_fapl_t)); /* Deep copy the property list objects in the structure */ - if(old_fa->memb_fapl_id==H5P_DEFAULT) - new_fa->memb_fapl_id = H5P_DEFAULT; + if(old_fa->memb_fapl_id==H5P_FILE_ACCESS_DEFAULT) + H5I_inc_ref(new_fa->memb_fapl_id); else { if(NULL == (plist = H5I_object(old_fa->memb_fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list"); @@ -427,9 +430,14 @@ H5FD_family_dxpl_copy(const void *_old_dx) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); memcpy(new_dx, old_dx, sizeof(H5FD_family_dxpl_t)); - if(NULL == (plist = H5I_object(old_dx->memb_dxpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list"); - new_dx->memb_dxpl_id = H5P_copy_plist(plist); + + if(old_dx->memb_dxpl_id==H5P_DATASET_XFER_DEFAULT) + H5I_inc_ref(new_dx->memb_dxpl_id); + else { + if(NULL == (plist = H5I_object(old_dx->memb_dxpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list"); + new_dx->memb_dxpl_id = H5P_copy_plist(plist); + } /* end else */ /* Set return value */ ret_value=new_dx; @@ -515,8 +523,9 @@ H5FD_family_open(const char *name, unsigned flags, hid_t fapl_id, /* Initialize file from file access properties */ if (NULL==(file=H5MM_calloc(sizeof(H5FD_family_t)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate file struct"); - if (H5P_DEFAULT==fapl_id) { - file->memb_fapl_id = H5P_DEFAULT; + if (H5P_FILE_ACCESS_DEFAULT==fapl_id) { + file->memb_fapl_id = H5P_FILE_ACCESS_DEFAULT; + H5I_inc_ref(file->memb_fapl_id); file->memb_size = 1024*1024*1024; /*1GB*/ } else { H5FD_family_fapl_t *fa; @@ -524,8 +533,8 @@ H5FD_family_open(const char *name, unsigned flags, hid_t fapl_id, if(NULL == (plist = H5I_object(fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list"); fa = H5P_get_driver_info(plist); - if(fa->memb_fapl_id==H5P_DEFAULT) - file->memb_fapl_id = H5P_DEFAULT; + if(fa->memb_fapl_id==H5P_FILE_ACCESS_DEFAULT) + H5I_inc_ref(file->memb_fapl_id); else { if(NULL == (plist = H5I_object(fa->memb_fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list"); @@ -920,8 +929,6 @@ H5FD_family_get_handle(H5FD_t *_file, hid_t fapl, void** file_handle) FUNC_ENTER_NOAPI(H5FD_family_get_handle, FAIL); /* Get the plist structure and family offset */ - if(H5P_DEFAULT == fapl) - fapl = H5Pcreate(H5P_FILE_ACCESS); if(NULL == (plist = H5P_object_verify(fapl, H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); if(H5P_get(plist, H5F_ACS_FAMILY_OFFSET_NAME, &offset) < 0) @@ -963,7 +970,7 @@ H5FD_family_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, si { H5FD_family_t *file = (H5FD_family_t*)_file; unsigned char *buf = (unsigned char*)_buf; - hid_t memb_dxpl_id = H5P_DEFAULT; + hid_t memb_dxpl_id = H5P_DATASET_XFER_DEFAULT; int i; haddr_t sub; size_t req; @@ -979,7 +986,7 @@ H5FD_family_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, si */ if(NULL == (plist = H5I_object(dxpl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list"); - if (H5P_DEFAULT!=dxpl_id && H5FD_FAMILY==H5P_get_driver(plist)) { + if (H5P_DATASET_XFER_DEFAULT!=dxpl_id && H5FD_FAMILY==H5P_get_driver(plist)) { H5FD_family_dxpl_t *dx = H5P_get_driver_info(plist); assert(TRUE==H5P_isa_class(dxpl_id, H5P_DATASET_XFER)); @@ -1040,7 +1047,7 @@ H5FD_family_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, s { H5FD_family_t *file = (H5FD_family_t*)_file; const unsigned char *buf = (const unsigned char*)_buf; - hid_t memb_dxpl_id = H5P_DEFAULT; + hid_t memb_dxpl_id = H5P_DATASET_XFER_DEFAULT; int i; haddr_t sub; size_t req; @@ -1056,7 +1063,7 @@ H5FD_family_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, s */ if(NULL == (plist = H5I_object(dxpl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list"); - if (H5P_DEFAULT!=dxpl_id && H5FD_FAMILY==H5P_get_driver(plist)) { + if (H5P_DATASET_XFER_DEFAULT!=dxpl_id && H5FD_FAMILY==H5P_get_driver(plist)) { H5FD_family_dxpl_t *dx = H5P_get_driver_info(plist); assert(TRUE==H5P_isa_class(dxpl_id, H5P_DATASET_XFER)); diff --git a/src/H5FDgass.c b/src/H5FDgass.c index 1f01240..4b42b27 100644 --- a/src/H5FDgass.c +++ b/src/H5FDgass.c @@ -17,15 +17,11 @@ #include "H5MMprivate.h" /* Memory allocation */ #include "H5Pprivate.h" /*property lists */ - -#undef MAX -#define MAX(X,Y) ((X)>(Y)?(X):(Y)) +#ifdef H5_HAVE_GASS /* The driver identification number, initialized at runtime */ static hid_t H5FD_GASS_g = 0; -#ifdef H5_HAVE_GASS - /* File operations */ #define OP_UNKNOWN 0 #define OP_READ 1 @@ -363,7 +359,7 @@ H5FD_gass_open(const char *name, unsigned flags, hid_t fapl_id, /* Obtain a pointer to gass-specific file access properties */ if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list"); - if (H5P_DEFAULT==fapl_id || H5FD_GASS!=H5P_get_driver(plist)) { + if (H5P_FILE_ACCESS_DEFAULT==fapl_id || H5FD_GASS!=H5P_get_driver(plist)) { GASS_INFO_NULL (_fa.info); /* _fa.info = GASS_INFO_NULL; */ /* _fa.info = {0,0}; */ /*default*/ diff --git a/src/H5FDlog.c b/src/H5FDlog.c index 5e81260..f42da62 100644 --- a/src/H5FDlog.c +++ b/src/H5FDlog.c @@ -39,7 +39,7 @@ static hid_t H5FD_LOG_g = 0; /* Driver-specific file access properties */ typedef struct H5FD_log_fapl_t { - char *logfile; /* Allocated log file name */ + char *logfile; /* Allocated log file name */ unsigned flags; /* Flags for logging behavior */ size_t buf_size; /* Size of buffers for track flavor and number of times each byte is accessed */ } H5FD_log_fapl_t; @@ -283,7 +283,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5Pset_fapl_log(hid_t fapl_id, char *logfile, int verbosity) +H5Pset_fapl_log(hid_t fapl_id, const char *logfile, int verbosity) { H5FD_log_fapl_t fa; /* File access property list information */ H5P_genplist_t *plist; /* Property list pointer */ @@ -330,7 +330,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5Pset_fapl_log(hid_t fapl_id, char *logfile, unsigned flags, size_t buf_size) +H5Pset_fapl_log(hid_t fapl_id, const char *logfile, unsigned flags, size_t buf_size) { H5FD_log_fapl_t fa; /* File access property list information */ H5P_genplist_t *plist; /* Property list pointer */ diff --git a/src/H5FDlog.h b/src/H5FDlog.h index adb4e0a..3a4bfc9 100644 --- a/src/H5FDlog.h +++ b/src/H5FDlog.h @@ -48,9 +48,9 @@ extern "C" { H5_DLL hid_t H5FD_log_init(void); #ifdef H5_WANT_H5_V1_4_COMPAT -H5_DLL herr_t H5Pset_fapl_log(hid_t fapl_id, char *logfile, int verbosity); +H5_DLL herr_t H5Pset_fapl_log(hid_t fapl_id, const char *logfile, int verbosity); #else /* H5_WANT_H5_V1_4_COMPAT */ -H5_DLL herr_t H5Pset_fapl_log(hid_t fapl_id, char *logfile, unsigned flags, size_t buf_size); +H5_DLL herr_t H5Pset_fapl_log(hid_t fapl_id, const char *logfile, unsigned flags, size_t buf_size); #endif /* H5_WANT_H5_V1_4_COMPAT */ #ifdef __cplusplus diff --git a/src/H5FDmpio.c b/src/H5FDmpio.c index 73a66db..0a483f0 100644 --- a/src/H5FDmpio.c +++ b/src/H5FDmpio.c @@ -25,6 +25,8 @@ #include "H5MMprivate.h" /* Memory allocation */ #include "H5Pprivate.h" /*property lists */ +#ifdef H5_HAVE_PARALLEL + /* * The driver identification number, initialized at runtime if H5_HAVE_PARALLEL * is defined. This allows applications to still have the H5FD_MPIO @@ -33,8 +35,6 @@ */ static hid_t H5FD_MPIO_g = 0; -#ifdef H5_HAVE_PARALLEL - /* * The description of a file belonging to this driver. * The EOF value is only used just after the file is opened in order for the @@ -255,6 +255,9 @@ H5Pset_fapl_mpio(hid_t fapl_id, MPI_Comm comm, MPI_Info info) FUNC_ENTER_API(H5Pset_fapl_mpio, FAIL); H5TRACE3("e","iMcMi",fapl_id,comm,info); + if(fapl_id==H5P_DEFAULT) + HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list"); + /* Check arguments */ if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a file access list"); @@ -370,6 +373,9 @@ H5Pset_dxpl_mpio(hid_t dxpl_id, H5FD_mpio_xfer_t xfer_mode) FUNC_ENTER_API(H5Pset_dxpl_mpio, FAIL); H5TRACE2("e","iDt",dxpl_id,xfer_mode); + if(dxpl_id==H5P_DEFAULT) + HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list"); + /* Check arguments */ if(NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER))) HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl"); @@ -848,7 +854,7 @@ H5FD_mpio_open(const char *name, unsigned flags, hid_t fapl_id, /* Obtain a pointer to mpio-specific file access properties */ if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list"); - if (H5P_DEFAULT==fapl_id || H5FD_MPIO!=H5P_get_driver(plist)) { + if (H5P_FILE_ACCESS_DEFAULT==fapl_id || H5FD_MPIO!=H5P_get_driver(plist)) { _fa.comm = MPI_COMM_SELF; /*default*/ _fa.info = MPI_INFO_NULL; /*default*/ fa = &_fa; diff --git a/src/H5FDmpiposix.c b/src/H5FDmpiposix.c index 63b445b..f1a2768 100644 --- a/src/H5FDmpiposix.c +++ b/src/H5FDmpiposix.c @@ -53,6 +53,8 @@ # include #endif +#ifdef H5_HAVE_PARALLEL + /* * The driver identification number, initialized at runtime if H5_HAVE_PARALLEL * is defined. This allows applications to still have the H5FD_MPIPOSIX @@ -61,8 +63,6 @@ */ static hid_t H5FD_MPIPOSIX_g = 0; -#ifdef H5_HAVE_PARALLEL - /* File operations */ #define OP_UNKNOWN 0 #define OP_READ 1 @@ -569,7 +569,7 @@ H5FD_mpiposix_open(const char *name, unsigned flags, hid_t fapl_id, /* Obtain a pointer to mpiposix-specific file access properties */ if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list"); - if (H5P_DEFAULT==fapl_id || H5FD_MPIPOSIX!=H5P_get_driver(plist)) { + if (H5P_FILE_ACCESS_DEFAULT==fapl_id || H5FD_MPIPOSIX!=H5P_get_driver(plist)) { _fa.comm = MPI_COMM_SELF; /*default*/ fa = &_fa; } /* end if */ diff --git a/src/H5FDmulti.c b/src/H5FDmulti.c index 9a9667e..45ee689 100644 --- a/src/H5FDmulti.c +++ b/src/H5FDmulti.c @@ -417,7 +417,7 @@ H5Pset_fapl_multi(hid_t fapl_id, const H5FD_mem_t *memb_map, } if (!memb_fapl) { for (mt=H5FD_MEM_DEFAULT; mtfd = fd; diff --git a/src/H5FDsrb.c b/src/H5FDsrb.c index bd44382..f2d87c8 100644 --- a/src/H5FDsrb.c +++ b/src/H5FDsrb.c @@ -17,11 +17,10 @@ #include "H5Pprivate.h" /*property lists */ -/* The driver identification number, initialized at runtime */ -static hid_t H5FD_SRB_g = 0; - #ifdef H5_HAVE_SRB +/* The driver identification number, initialized at runtime */ +static hid_t H5FD_SRB_g = 0; /* * This driver supports systems that have the lseek64() function by defining @@ -320,7 +319,7 @@ H5FD_srb_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr) if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list"); - if(H5P_DEFAULT==fapl_id || H5FD_SRB!=H5P_get_driver(plist)) { + if(H5P_FILE_ACCESS_DEFAULT==fapl_id || H5FD_SRB!=H5P_get_driver(plist)) { HDmemset((void*)&_fa, 0, sizeof(H5FD_srb_fapl_t)); fa = &_fa; } diff --git a/src/H5FDstream.c b/src/H5FDstream.c index ee3ca99..a5c89bf 100644 --- a/src/H5FDstream.c +++ b/src/H5FDstream.c @@ -594,7 +594,7 @@ H5FD_stream_open (const char *filename, #endif fapl = NULL; - if (H5P_DEFAULT != fapl_id) { + if (H5P_FILE_ACCESS_DEFAULT != fapl_id) { if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list"); fapl = H5P_get_driver_info (plist); diff --git a/src/H5FL.c b/src/H5FL.c index 917821c..1e49834 100644 --- a/src/H5FL.c +++ b/src/H5FL.c @@ -34,12 +34,12 @@ static int interface_initialize_g = 0; Default limits on how much memory can accumulate on each free list before it is garbage collected. */ -static size_t H5FL_reg_glb_mem_lim=1*16*65536;/* Default to 1MB limit on all regular free lists */ -static size_t H5FL_reg_lst_mem_lim=1*65536; /* Default to 64KB limit on each regular free list */ -static size_t H5FL_arr_glb_mem_lim=4*16*65536;/* Default to 4MB limit on all array free lists */ -static size_t H5FL_arr_lst_mem_lim=4*65536; /* Default to 256KB limit on each array free list */ -static size_t H5FL_blk_glb_mem_lim=16*16*65536; /* Default to 16MB limit on all block free lists */ -static size_t H5FL_blk_lst_mem_lim=16*65536; /* Default to 1024KB (1MB) limit on each block free list */ +static size_t H5FL_reg_glb_mem_lim=1*1024*1024; /* Default to 1MB limit on all regular free lists */ +static size_t H5FL_reg_lst_mem_lim=1*65536; /* Default to 64KB limit on each regular free list */ +static size_t H5FL_arr_glb_mem_lim=4*1024*1024; /* Default to 4MB limit on all array free lists */ +static size_t H5FL_arr_lst_mem_lim=4*65536; /* Default to 256KB limit on each array free list */ +static size_t H5FL_blk_glb_mem_lim=16*1024*1024; /* Default to 16MB limit on all block free lists */ +static size_t H5FL_blk_lst_mem_lim=1024*1024; /* Default to 1024KB (1MB) limit on each block free list */ /* A garbage collection node for regular free lists */ typedef struct H5FL_reg_gc_node_t { @@ -248,7 +248,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5FL_reg_alloc + * Function: H5FL_reg_malloc * * Purpose: Allocate a block on a free list * @@ -263,11 +263,11 @@ done: *------------------------------------------------------------------------- */ void * -H5FL_reg_alloc(H5FL_reg_head_t *head, unsigned clear) +H5FL_reg_malloc(H5FL_reg_head_t *head) { void *ret_value; /* Pointer to object to return */ - FUNC_ENTER_NOAPI(H5FL_reg_alloc, NULL); + FUNC_ENTER_NOAPI(H5FL_reg_malloc, NULL); /* Double check parameters */ assert(head); @@ -301,13 +301,46 @@ H5FL_reg_alloc(H5FL_reg_head_t *head, unsigned clear) head->allocated++; } /* end else */ - /* Clear to zeros, if asked */ - if(clear) - HDmemset(ret_value,0,head->size); +done: + FUNC_LEAVE (ret_value); +} /* end H5FL_reg_malloc() */ + + +/*------------------------------------------------------------------------- + * Function: H5FL_reg_calloc + * + * Purpose: Allocate a block on a free list and clear it to zeros + * + * Return: Success: Pointer to a valid object + * Failure: NULL + * + * Programmer: Quincey Koziol + * Monday, December 23, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void * +H5FL_reg_calloc(H5FL_reg_head_t *head) +{ + void *ret_value; /* Pointer to object to return */ + + FUNC_ENTER_NOAPI(H5FL_reg_calloc, NULL); + + /* Double check parameters */ + assert(head); + + /* Allocate the block */ + if (NULL==(ret_value = H5FL_reg_malloc(head))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + + /* Clear to zeros */ + HDmemset(ret_value,0,head->size); done: FUNC_LEAVE (ret_value); -} /* end H5FL_reg_alloc() */ +} /* end H5FL_reg_calloc() */ /*------------------------------------------------------------------------- @@ -562,7 +595,7 @@ H5FL_blk_create_list(H5FL_blk_node_t **head, size_t size) FUNC_ENTER_NOINIT(H5FL_blk_create_list); /* Allocate room for the new free list node */ - if(NULL==(temp=H5FL_ALLOC(H5FL_blk_node_t,0))) + if(NULL==(temp=H5FL_MALLOC(H5FL_blk_node_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for chunk info"); /* Set the correct values for the new free list */ @@ -632,7 +665,45 @@ done: /*------------------------------------------------------------------------- - * Function: H5FL_blk_alloc + * Function: H5FL_blk_free_block_avail + * + * Purpose: Checks if a free block of the appropriate size is available + * for a given list. + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, December 16, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +htri_t +H5FL_blk_free_block_avail(H5FL_blk_head_t *head, size_t size) +{ + H5FL_blk_node_t *free_list; /* The free list of nodes of correct size */ + htri_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5FL_blk_free_block_avail, FAIL); + + /* Double check parameters */ + assert(head); + + /* check if there is a free list for blocks of this size */ + /* and if there are any blocks available on the list */ + if((free_list=H5FL_blk_find_list(&(head->head),size))!=NULL && free_list->list!=NULL) + ret_value=TRUE; + else + ret_value=FALSE; +done: + FUNC_LEAVE(ret_value); +} /* end H5FL_blk_free_block_avail() */ + + +/*------------------------------------------------------------------------- + * Function: H5FL_blk_malloc * * Purpose: Allocates memory for a block. This routine is used * instead of malloc because the block can be kept on a free list so @@ -650,13 +721,13 @@ done: *------------------------------------------------------------------------- */ void * -H5FL_blk_alloc(H5FL_blk_head_t *head, size_t size, unsigned clear) +H5FL_blk_malloc(H5FL_blk_head_t *head, size_t size) { H5FL_blk_node_t *free_list; /* The free list of nodes of correct size */ H5FL_blk_list_t *temp; /* Temp. ptr to the new native list allocated */ void *ret_value; /* Pointer to the block to return to the user */ - FUNC_ENTER_NOAPI(H5FL_blk_alloc, NULL); + FUNC_ENTER_NOAPI(H5FL_blk_malloc, NULL); /* Double check parameters */ assert(head); @@ -702,13 +773,50 @@ H5FL_blk_alloc(H5FL_blk_head_t *head, size_t size, unsigned clear) ret_value=((char *)temp)+sizeof(H5FL_blk_list_t); } /* end else */ - /* Clear the block to zeros, if requested */ - if(clear) - HDmemset(ret_value,0,size); +done: + FUNC_LEAVE(ret_value); +} /* end H5FL_blk_malloc() */ + + +/*------------------------------------------------------------------------- + * Function: H5FL_blk_calloc + * + * Purpose: Allocates memory for a block and clear it to zeros. + * This routine is used + * instead of malloc because the block can be kept on a free list so + * they don't thrash malloc/free as much. + * + * Return: Success: valid pointer to the block + * + * Failure: NULL + * + * Programmer: Quincey Koziol + * Monday, December 23, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void * +H5FL_blk_calloc(H5FL_blk_head_t *head, size_t size) +{ + void *ret_value; /* Pointer to the block to return to the user */ + + FUNC_ENTER_NOAPI(H5FL_blk_calloc, NULL); + + /* Double check parameters */ + assert(head); + + /* Allocate the block */ + if (NULL==(ret_value = H5FL_blk_malloc(head,size))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + + /* Clear the block to zeros */ + HDmemset(ret_value,0,size); done: FUNC_LEAVE(ret_value); -} /* end H5FL_blk_alloc() */ +} /* end H5FL_blk_calloc() */ /*------------------------------------------------------------------------- @@ -818,7 +926,7 @@ H5FL_blk_realloc(H5FL_blk_head_t *head, void *block, size_t new_size) /* check if we are actually changing the size of the buffer */ if(new_size!=temp->size) { - if((ret_value=H5FL_blk_alloc(head,new_size,0))==NULL) + if((ret_value=H5FL_blk_malloc(head,new_size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for block"); blk_size=MIN(new_size,temp->size); HDmemcpy(ret_value,block,blk_size); @@ -829,7 +937,7 @@ H5FL_blk_realloc(H5FL_blk_head_t *head, void *block, size_t new_size) } /* end if */ /* Not re-allocating, just allocate a fresh block */ else - ret_value=H5FL_blk_alloc(head,new_size,0); + ret_value=H5FL_blk_malloc(head,new_size); done: FUNC_LEAVE(ret_value); @@ -1141,7 +1249,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5FL_arr_alloc + * Function: H5FL_arr_malloc * * Purpose: Allocate an array of objects * @@ -1156,13 +1264,13 @@ done: *------------------------------------------------------------------------- */ void * -H5FL_arr_alloc(H5FL_arr_head_t *head, size_t elem, unsigned clear) +H5FL_arr_malloc(H5FL_arr_head_t *head, size_t elem) { H5FL_arr_node_t *new_obj; /* Pointer to the new free list node allocated */ void *ret_value; /* Pointer to object to return */ size_t mem_size; /* Size of memory block being recycled */ - FUNC_ENTER_NOAPI(H5FL_arr_alloc, NULL); + FUNC_ENTER_NOAPI(H5FL_arr_malloc, NULL); /* Double check parameters */ assert(head); @@ -1215,18 +1323,51 @@ H5FL_arr_alloc(H5FL_arr_head_t *head, size_t elem, unsigned clear) /* Get a pointer to the new block */ ret_value=((char *)new_obj)+sizeof(H5FL_arr_node_t); } /* end else */ - - /* Clear to zeros, if asked */ - if(clear) - HDmemset(ret_value,0,mem_size); } /* end if */ /* No fixed number of elements, use PQ routine */ else - ret_value=H5FL_blk_alloc(&(head->u.queue),mem_size,clear); + ret_value=H5FL_blk_malloc(&(head->u.queue),mem_size); + +done: + FUNC_LEAVE (ret_value); +} /* end H5FL_arr_malloc() */ + + +/*------------------------------------------------------------------------- + * Function: H5FL_arr_calloc + * + * Purpose: Allocate an array of objects and clear it to zeros + * + * Return: Success: Pointer to a valid array object + * Failure: NULL + * + * Programmer: Quincey Koziol + * Monday, December 23, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void * +H5FL_arr_calloc(H5FL_arr_head_t *head, size_t elem) +{ + void *ret_value; /* Pointer to object to return */ + + FUNC_ENTER_NOAPI(H5FL_arr_calloc, NULL); + + /* Double check parameters */ + assert(head); + + /* Allocate the array */ + if (NULL==(ret_value = H5FL_arr_malloc(head,elem))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + + /* Clear to zeros */ + HDmemset(ret_value,0,head->size*elem); done: FUNC_LEAVE (ret_value); -} /* end H5FL_arr_alloc() */ +} /* end H5FL_arr_calloc() */ /*------------------------------------------------------------------------- @@ -1258,7 +1399,7 @@ H5FL_arr_realloc(H5FL_arr_head_t *head, void * obj, size_t new_elem) /* Check if we are really allocating the object */ if(obj==NULL) { - ret_value=H5FL_arr_alloc(head,new_elem,0); + ret_value=H5FL_arr_malloc(head,new_elem); } /* end if */ else { /* Check if there is a maximum number of elements in array */ @@ -1272,7 +1413,7 @@ H5FL_arr_realloc(H5FL_arr_head_t *head, void * obj, size_t new_elem) /* Check if the size is really changing */ if(temp->nelem!=new_elem) { /* Get the new array of objects */ - ret_value=H5FL_arr_alloc(head,new_elem,0); + ret_value=H5FL_arr_malloc(head,new_elem); /* Copy the appropriate amount of elements */ blk_size=head->size*MIN(temp->nelem,new_elem); diff --git a/src/H5FLprivate.h b/src/H5FLprivate.h index 35b3555..72e28d8 100644 --- a/src/H5FLprivate.h +++ b/src/H5FLprivate.h @@ -66,7 +66,10 @@ typedef struct H5FL_reg_head_t { #define H5FL_DEFINE_STATIC(t) static H5FL_DEFINE(t) /* Allocate an object of type 't' */ -#define H5FL_ALLOC(t,clr) H5FL_reg_alloc(&(t##_free_list),clr) +#define H5FL_MALLOC(t) H5FL_reg_malloc(&(t##_free_list)) + +/* Allocate an object of type 't' and clear it to all zeros */ +#define H5FL_CALLOC(t) H5FL_reg_calloc(&(t##_free_list)) /* Free an object of type 't' */ #define H5FL_FREE(t,obj) H5FL_reg_free(&(t##_free_list),obj) @@ -80,7 +83,8 @@ typedef struct H5FL_reg_head_t { #define H5FL_DEFINE(t) int t##_reg_free_list_placeholder #define H5FL_EXTERN(t) extern int t##_reg_free_list_placeholder #define H5FL_DEFINE_STATIC(t) static H5FL_DEFINE(t) -#define H5FL_ALLOC(t,clr) (clr ? H5MM_calloc(sizeof(t)) : H5MM_malloc(sizeof(t))) +#define H5FL_MALLOC(t) H5MM_malloc(sizeof(t)) +#define H5FL_CALLOC(t) H5MM_calloc(sizeof(t)) #define H5FL_FREE(t,obj) H5MM_xfree(obj) #endif /* H5_NO_REG_FREE_LISTS */ @@ -124,7 +128,10 @@ typedef struct H5FL_blk_head_t { #define H5FL_BLK_DEFINE_STATIC(t) static H5FL_BLK_DEFINE(t) /* Allocate an block of type 't' */ -#define H5FL_BLK_ALLOC(t,size,clr) H5FL_blk_alloc(&(t##_pq),size,clr) +#define H5FL_BLK_MALLOC(t,size) H5FL_blk_malloc(&(t##_pq),size) + +/* Allocate an block of type 't' and clear it to zeros */ +#define H5FL_BLK_CALLOC(t,size) H5FL_blk_calloc(&(t##_pq),size) /* Free a block of type 't' */ #define H5FL_BLK_FREE(t,blk) H5FL_blk_free(&(t##_pq),blk) @@ -132,13 +139,18 @@ typedef struct H5FL_blk_head_t { /* Re-allocate a block of type 't' */ #define H5FL_BLK_REALLOC(t,blk,new_size) H5FL_blk_realloc(&(t##_pq),blk,new_size) +/* Check if there is a free block available to re-use */ +#define H5FL_BLK_AVAIL(t,size) H5FL_blk_free_block_avail(&(t##_pq),size) + #else /* H5_NO_BLK_FREE_LISTS */ #define H5FL_BLK_DEFINE(t) int t##_blk_free_list_placeholder #define H5FL_BLK_EXTERN(t) extern int t##_blk_free_list_placeholder #define H5FL_BLK_DEFINE_STATIC(t) static H5FL_BLK_DEFINE(t) -#define H5FL_BLK_ALLOC(t,size,clr) (clr ? H5MM_calloc(size) : H5MM_malloc(size)) +#define H5FL_BLK_MALLOC(t,size) H5MM_malloc(size) +#define H5FL_BLK_CALLOC(t,size) H5MM_calloc(size) #define H5FL_BLK_FREE(t,blk) H5MM_xfree(blk) #define H5FL_BLK_REALLOC(t,blk,new_size) H5MM_realloc(blk,new_size) +#define H5FL_BLK_AVAIL(t,size) (FALSE) #endif /* H5_NO_BLK_FREE_LISTS */ /* Data structure to store each array in free list */ @@ -178,7 +190,10 @@ typedef struct H5FL_arr_head_t { #define H5FL_ARR_DEFINE_STATIC(t,m) static H5FL_ARR_DEFINE(t,m) /* Allocate an array of type 't' */ -#define H5FL_ARR_ALLOC(t,elem,clr) H5FL_arr_alloc(&(t##_arr_free_list),elem,clr) +#define H5FL_ARR_MALLOC(t,elem) H5FL_arr_malloc(&(t##_arr_free_list),elem) + +/* Allocate an array of type 't' and clear it to all zeros */ +#define H5FL_ARR_CALLOC(t,elem) H5FL_arr_calloc(&(t##_arr_free_list),elem) /* Free an array of type 't' */ #define H5FL_ARR_FREE(t,obj) H5FL_arr_free(&(t##_arr_free_list),obj) @@ -190,7 +205,8 @@ typedef struct H5FL_arr_head_t { #define H5FL_ARR_DEFINE(t,m) int t##_arr_free_list_placeholder #define H5FL_ARR_EXTERN(t) extern int t##_arr_free_list_placeholder #define H5FL_ARR_DEFINE_STATIC(t,m) static H5FL_ARR_DEFINE(t,m) -#define H5FL_ARR_ALLOC(t,elem,clr) (clr ? H5MM_calloc(elem*sizeof(t)) : H5MM_malloc(elem*sizeof(t))) +#define H5FL_ARR_MALLOC(t,elem) H5MM_malloc(elem*sizeof(t)) +#define H5FL_ARR_CALLOC(t,elem) H5MM_calloc(elem*sizeof(t)) #define H5FL_ARR_FREE(t,obj) H5MM_xfree(obj) #define H5FL_ARR_REALLOC(t,obj,new_elem) H5MM_realloc(obj,new_elem*sizeof(t)) #endif /* H5_NO_ARR_FREE_LISTS */ @@ -198,12 +214,16 @@ typedef struct H5FL_arr_head_t { /* * Library prototypes. */ -H5_DLL void * H5FL_blk_alloc(H5FL_blk_head_t *head, size_t size, unsigned clear); +H5_DLL void * H5FL_blk_malloc(H5FL_blk_head_t *head, size_t size); +H5_DLL void * H5FL_blk_calloc(H5FL_blk_head_t *head, size_t size); H5_DLL void * H5FL_blk_free(H5FL_blk_head_t *head, void *block); H5_DLL void * H5FL_blk_realloc(H5FL_blk_head_t *head, void *block, size_t new_size); -H5_DLL void * H5FL_reg_alloc(H5FL_reg_head_t *head, unsigned clear); +H5_DLL htri_t H5FL_blk_free_block_avail(H5FL_blk_head_t *head, size_t size); +H5_DLL void * H5FL_reg_malloc(H5FL_reg_head_t *head); +H5_DLL void * H5FL_reg_calloc(H5FL_reg_head_t *head); H5_DLL void * H5FL_reg_free(H5FL_reg_head_t *head, void *obj); -H5_DLL void * H5FL_arr_alloc(H5FL_arr_head_t *head, size_t elem, unsigned clear); +H5_DLL void * H5FL_arr_malloc(H5FL_arr_head_t *head, size_t elem); +H5_DLL void * H5FL_arr_calloc(H5FL_arr_head_t *head, size_t elem); H5_DLL void * H5FL_arr_free(H5FL_arr_head_t *head, void *obj); H5_DLL void * H5FL_arr_realloc(H5FL_arr_head_t *head, void *obj, size_t new_elem); H5_DLL herr_t H5FL_garbage_coll(void); diff --git a/src/H5FO.c b/src/H5FO.c new file mode 100644 index 0000000..29f3998 --- /dev/null +++ b/src/H5FO.c @@ -0,0 +1,277 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* + * Open object info algorithms. + * + * These are used to track the objects currently open in a file, for various + * internal mechanisms which need to be aware of such things. + * + */ + +#define H5F_PACKAGE /*suppress error about including H5Fpkg */ + +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fpkg.h" /* File access */ +#include "H5FLprivate.h" /* Free lists */ +#include "H5FOprivate.h" /* File objects */ + +#define PABLO_MASK H5FO_mask + +/* Interface initialization */ +static int interface_initialize_g = 0; +#define INTERFACE_INIT NULL + +/* Private typedefs */ + +/* Information about object objects in a file */ +typedef struct H5FO_open_obj_t { + haddr_t addr; /* Address of object header for object */ + /* THIS MUST BE FIRST FOR TBBT ROUTINES */ + hid_t id; /* Current ID for object */ +} H5FO_open_obj_t; + +/* Declare a free list to manage the H5FO_open_obj_t struct */ +H5FL_DEFINE_STATIC(H5FO_open_obj_t); + + +/*-------------------------------------------------------------------------- + NAME + H5FO_create + PURPOSE + Create an open object info set + USAGE + herr_t H5FO_create(f) + H5F_t *f; IN/OUT: File to create opened object info set for + + RETURNS + Returns non-negative on success, negative on failure + DESCRIPTION + Create a new open object info set. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5FO_create(H5F_t *f) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FO_create,FAIL); + + /* Sanity check */ + assert(f); + assert(f->shared); + + /* Create TBBT used to store open object info */ + if((f->shared->open_objs=H5TB_fast_dmake(H5TB_FAST_HADDR_COMPARE))==NULL) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to create open object TBBT"); + +done: + FUNC_LEAVE(ret_value); +} /* end H5FO_create() */ + + +/*-------------------------------------------------------------------------- + NAME + H5FO_opened + PURPOSE + Checks if an object at an address is already open in the file. + USAGE + hid_t H5FO_opened(f,addr) + const H5F_t *f; IN: File to check opened object info set + haddr_t addr; IN: Address of object to check + + RETURNS + Returns a non-negative ID for the object on success, negative on failure + DESCRIPTION + Check is an object at an address (the address of the object's object header) + is already open in the file and return the ID for that object if it is open. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +hid_t +H5FO_opened(const H5F_t *f, haddr_t addr) +{ + H5TB_NODE *obj_node; /* TBBT node holding open object */ + H5FO_open_obj_t *open_obj; /* Information about open object */ + hid_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5FO_opened,FAIL); + + /* Sanity check */ + assert(f); + assert(f->shared); + assert(f->shared->open_objs); + assert(H5F_addr_defined(addr)); + + /* Get the object node from the TBBT */ + if((obj_node=H5TB_dfind(f->shared->open_objs,&addr,NULL))!=NULL) { + open_obj=H5TB_NODE_DATA(obj_node); + assert(open_obj); + ret_value=open_obj->id; + assert(ret_value>0); + } /* end if */ + else + ret_value=FAIL; + +done: + FUNC_LEAVE(ret_value); +} /* end H5FO_opened() */ + + +/*-------------------------------------------------------------------------- + NAME + H5FO_insert + PURPOSE + Insert a newly opened object/ID pair into the opened object info set + USAGE + herr_t H5FO_insert(f,addr,id) + H5F_t *f; IN/OUT: File's opened object info set + haddr_t addr; IN: Address of object to insert + hid_t id; IN: ID of object to insert + + RETURNS + Returns a non-negative on success, negative on failure + DESCRIPTION + Insert an object/ID pair into the opened object info set. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5FO_insert(H5F_t *f, haddr_t addr, hid_t id) +{ + H5FO_open_obj_t *open_obj; /* Information about open object */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FO_insert,FAIL); + + /* Sanity check */ + assert(f); + assert(f->shared); + assert(f->shared->open_objs); + assert(H5F_addr_defined(addr)); + assert(id>0); + + /* Allocate new opened object information structure */ + if((open_obj=H5FL_MALLOC(H5FO_open_obj_t))==NULL) + HGOTO_ERROR(H5E_CACHE,H5E_NOSPACE,NULL,"memory allocation failed"); + + /* Assign information */ + open_obj->addr=addr; + open_obj->id=id; + + /* Insert into TBBT */ + if(H5TB_dins(f->shared->open_objs,open_obj,open_obj)==NULL) + HGOTO_ERROR(H5E_CACHE,H5E_CANTINSERT,FAIL,"can't insert object into TBBT"); + +done: + FUNC_LEAVE(ret_value); +} /* end H5FO_insert() */ + + +/*-------------------------------------------------------------------------- + NAME + H5FO_delete + PURPOSE + Remove an opened object/ID pair from the opened object info set + USAGE + herr_t H5FO_delete(f,addr) + H5F_t *f; IN/OUT: File's opened object info set + haddr_t addr; IN: Address of object to remove + + RETURNS + Returns a non-negative on success, negative on failure + DESCRIPTION + Remove an object/ID pair from the opened object info. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5FO_delete(H5F_t *f, haddr_t addr) +{ + H5TB_NODE *obj_node; /* TBBT node holding open object */ + H5FO_open_obj_t *open_obj; /* Information about open object */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FO_delete,FAIL); + + /* Sanity check */ + assert(f); + assert(f->shared); + assert(f->shared->open_objs); + assert(H5F_addr_defined(addr)); + + /* Get the object node from the TBBT */ + if((obj_node=H5TB_dfind(f->shared->open_objs,&addr,NULL))==NULL) + HGOTO_ERROR(H5E_CACHE,H5E_NOTFOUND,FAIL,"can't locate object in TBBT"); + + /* Remove from TBBT */ + if((open_obj=H5TB_rem(&f->shared->open_objs->root,obj_node,NULL))==NULL) + HGOTO_ERROR(H5E_CACHE,H5E_CANTRELEASE,FAIL,"can't remove object from TBBT"); + + /* Release the object information */ + H5FL_FREE(H5FO_open_obj_t,open_obj); + +done: + FUNC_LEAVE(ret_value); +} /* end H5FO_delete() */ + + +/*-------------------------------------------------------------------------- + NAME + H5FO_dest + PURPOSE + Destroy an open object info set + USAGE + herr_t H5FO_create(f) + H5F_t *f; IN/OUT: File's opened object info set + + RETURNS + Returns a non-negative on success, negative on failure + DESCRIPTION + Destroy an existing open object info set. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5FO_dest(H5F_t *f) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FO_dest,FAIL); + + /* Sanity check */ + assert(f); + assert(f->shared); + assert(f->shared->open_objs); + + /* Check if the object info set is empty */ + if(H5TB_count(f->shared->open_objs)!=0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTRELEASE, FAIL, "objects still in open object info set"); + + /* Release the open object info set TBBT */ + f->shared->open_objs=H5TB_dfree(f->shared->open_objs,NULL,NULL); + +done: + FUNC_LEAVE(ret_value); +} /* end H5FO_dest() */ + diff --git a/src/H5FOprivate.h b/src/H5FOprivate.h new file mode 100644 index 0000000..6f89ec2 --- /dev/null +++ b/src/H5FOprivate.h @@ -0,0 +1,42 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* + * This file contains library private information about the H5FO module + */ +#ifndef _H5FOprivate_H +#define _H5FOprivate_H + +#ifdef LATER +#include "H5FOpublic.h" +#endif /* LATER */ + +/* Private headers needed by this file */ +#include "H5private.h" +#include "H5TBprivate.h" /* TBBTs */ + +/* Typedefs */ + +/* Typedef for open object cache */ +typedef H5TB_TREE H5FO_t; /* Currently, all open objects are stored in TBBT */ + +/* Macros */ + +/* Private routines */ +H5_DLL herr_t H5FO_create(H5F_t *f); +H5_DLL hid_t H5FO_opened(const H5F_t *f, haddr_t addr); +H5_DLL herr_t H5FO_insert(H5F_t *f, haddr_t addr, hid_t id); +H5_DLL herr_t H5FO_delete(H5F_t *f, haddr_t addr); +H5_DLL herr_t H5FO_dest(H5F_t *f); + +#endif /* _H5FOprivate_H */ + diff --git a/src/H5FPclient.c b/src/H5FPclient.c index cae4c60..7912b4e 100644 --- a/src/H5FPclient.c +++ b/src/H5FPclient.c @@ -583,6 +583,7 @@ H5FP_update_file_cache(hid_t file_id, struct SAP_sync *sap_sync, uint8_t *msg) HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group"); switch (sap_sync->action) { +#ifdef OLD_WAY case H5FP_ACT_CREATE: if (sap_sync->obj_type == H5FP_OBJ_DATASET) { H5O_efl_t efl; @@ -598,7 +599,7 @@ H5FP_update_file_cache(hid_t file_id, struct SAP_sync *sap_sync, uint8_t *msg) fmeta->sdim->size, fmeta->sdim->max) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't set dimensions"); - if (H5D_update_entry_cache(file, ent, H5G_entof(grp), + if (H5D_update_entry_info(file, ent, H5G_entof(grp), fmeta->dset->s, space, fmeta->plist, fmeta->layout, fmeta->dtype, FALSE, fmeta->header) == FAIL) @@ -607,7 +608,7 @@ H5FP_update_file_cache(hid_t file_id, struct SAP_sync *sap_sync, uint8_t *msg) if (H5P_get(fmeta->plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get external file list"); - if (H5D_update_external_storage_cache(file, ent, &efl, fmeta->layout) == FAIL) + if (H5D_update_external_storage_info(file, ent, &efl, fmeta->layout) == FAIL) HGOTO_ERROR(H5E_FPHDF5, H5E_CANTINIT, FAIL, "can't update external file layout metadata cache"); } @@ -624,6 +625,7 @@ H5FP_update_file_cache(hid_t file_id, struct SAP_sync *sap_sync, uint8_t *msg) } break; +#endif /* OLD_WAY */ case H5FP_ACT_DELETE: default: diff --git a/src/H5Fcontig.c b/src/H5Fcontig.c index fce1ba9..a63a9ce 100644 --- a/src/H5Fcontig.c +++ b/src/H5Fcontig.c @@ -36,8 +36,11 @@ static int interface_initialize_g = 0; /* Declare a PQ free list to manage the sieve buffer information */ H5FL_BLK_DEFINE(sieve_buf); -/* Extern the free list to manage blocks of type conversion data */ -H5FL_BLK_EXTERN(type_conv); +/* Declare the free list to manage blocks of non-zero fill-value data */ +H5FL_BLK_DEFINE_STATIC(non_zero_fill); + +/* Declare the free list to manage blocks of zero fill-value data */ +H5FL_BLK_DEFINE_STATIC(zero_fill); /*------------------------------------------------------------------------- @@ -56,11 +59,10 @@ H5FL_BLK_EXTERN(type_conv); */ herr_t H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, - struct H5P_genplist_t *dc_plist, const struct H5S_t *space, - size_t elmt_size) + struct H5P_genplist_t *dc_plist, const struct H5O_efl_t *efl, + const struct H5S_t *space, + const struct H5O_fill_t *fill, size_t elmt_size) { - H5O_fill_t fill; /* Fill value information */ - H5O_efl_t efl; /* External File List info */ hssize_t snpoints; /* Number of points in space (for error checking) */ size_t npoints; /* Number of points in space */ size_t ptsperbuf; /* Maximum # of points which fit in the buffer */ @@ -77,6 +79,7 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, unsigned blocks_written=0; /* Flag to indicate that chunk was actually written */ unsigned using_mpi=0; /* Flag to indicate that the file is being accessed with an MPI-capable file driver */ #endif /* H5_HAVE_PARALLEL */ + int non_zero_fill_f=(-1); /* Indicate that a non-zero fill-value was used */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5F_contig_fill, FAIL); @@ -91,12 +94,6 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, assert(space); assert(elmt_size>0); - /* Get necessary properties from dataset creation property list */ - if(H5P_get(dc_plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) - HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "can't get fill value"); - if(H5P_get(dc_plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve external file list"); - #ifdef H5_HAVE_PARALLEL /* Retrieve up MPI parameters */ if(IS_H5FD_MPIO(f)) { @@ -136,46 +133,62 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, assert(snpoints>=0); H5_ASSIGN_OVERFLOW(npoints,snpoints,hssize_t,size_t); - /* Don't write default fill-values to external files */ - if(efl.nused>0 && !fill.buf) - HGOTO_DONE(SUCCEED); - - /* If fill value is library default, use the element size */ - if(!fill.buf) - fill.size=elmt_size; + /* If fill value is not library default, use it to set the element size */ + if(fill->buf) + elmt_size=fill->size; /* * Fill the entire current extent with the fill value. We can do * this quite efficiently by making sure we copy the fill value * in relatively large pieces. */ - ptsperbuf = MAX(1, bufsize/fill.size); - bufsize = ptsperbuf*fill.size; - - /* Allocate temporary buffer */ - if ((buf=H5FL_BLK_ALLOC(type_conv,bufsize,0))==NULL) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fill buffer"); - - /* Fill the buffer with the user's fill value */ - if(fill.buf) - H5V_array_fill(buf, fill.buf, fill.size, ptsperbuf); - else /* Fill the buffer with the default fill value */ - HDmemset(buf,0,bufsize); + ptsperbuf = MAX(1, bufsize/elmt_size); + bufsize = ptsperbuf*elmt_size; + + /* Fill the buffer with the user's fill value */ + if(fill->buf) { + /* Allocate temporary buffer */ + if ((buf=H5FL_BLK_MALLOC(non_zero_fill,bufsize))==NULL) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fill buffer"); + + H5V_array_fill(buf, fill->buf, elmt_size, ptsperbuf); + + /* Indicate that a non-zero fill buffer was used */ + non_zero_fill_f=1; + } /* end if */ + else { /* Fill the buffer with the default fill value */ + htri_t buf_avail; + + /* Check if there is an already zeroed out buffer available */ + buf_avail=H5FL_BLK_AVAIL(zero_fill,bufsize); + assert(buf_avail!=FAIL); + + /* Allocate temporary buffer (zeroing it if no buffer is available) */ + if(!buf_avail) + buf=H5FL_BLK_CALLOC(zero_fill,bufsize); + else + buf=H5FL_BLK_MALLOC(zero_fill,bufsize); + if(buf==NULL) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fill buffer"); + + /* Indicate that a zero fill buffer was used */ + non_zero_fill_f=0; + } /* end else */ - /* Start at the beginning of the dataset */ - addr = 0; + /* Start at the beginning of the dataset */ + addr = 0; - /* Loop through writing the fill value to the dataset */ - while (npoints>0) { - size = MIN(ptsperbuf, npoints) * fill.size; + /* Loop through writing the fill value to the dataset */ + while (npoints>0) { + size = MIN(ptsperbuf, npoints) * elmt_size; #ifdef H5_HAVE_PARALLEL /* Check if this file is accessed with an MPI-capable file driver */ if(using_mpi) { /* Round-robin write the chunks out from only one process */ if(mpi_round==mpi_rank) { - if (H5F_seq_write(f, dxpl_id, layout, dc_plist, space, - fill.size, size, addr, buf)<0) + if (H5F_seq_write(f, dxpl_id, layout, dc_plist, efl, space, + elmt_size, size, addr, buf)<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to write fill value to dataset"); } /* end if */ mpi_round=(++mpi_round)%mpi_size; @@ -185,8 +198,8 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, } /* end if */ else { #endif /* H5_HAVE_PARALLEL */ - if (H5F_seq_write(f, dxpl_id, layout, dc_plist, space, - fill.size, size, addr, buf)<0) + if (H5F_seq_write(f, dxpl_id, layout, dc_plist, efl, space, + elmt_size, size, addr, buf)<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to write fill value to dataset"); #ifdef H5_HAVE_PARALLEL } /* end else */ @@ -211,8 +224,13 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, done: /* Free the buffer for fill values */ - if (buf) - H5FL_BLK_FREE(type_conv,buf); + if (buf) { + assert(non_zero_fill_f>=0); + if(non_zero_fill_f) + H5FL_BLK_FREE(non_zero_fill,buf); + else + H5FL_BLK_FREE(zero_fill,buf); + } /* end if */ FUNC_LEAVE(ret_value); } @@ -661,7 +679,7 @@ H5F_contig_readv(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr, } /* end if */ else { /* Allocate room for the data sieve buffer */ - if (NULL==(f->shared->sieve_buf=H5FL_BLK_ALLOC(sieve_buf,f->shared->sieve_buf_size,0))) + if (NULL==(f->shared->sieve_buf=H5FL_BLK_MALLOC(sieve_buf,f->shared->sieve_buf_size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); /* Determine the new sieve buffer size & location */ @@ -1128,7 +1146,7 @@ H5F_contig_writev(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr, } /* end if */ else { /* Allocate room for the data sieve buffer */ - if (NULL==(f->shared->sieve_buf=H5FL_BLK_ALLOC(sieve_buf,f->shared->sieve_buf_size,0))) + if (NULL==(f->shared->sieve_buf=H5FL_BLK_MALLOC(sieve_buf,f->shared->sieve_buf_size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); /* Determine the new sieve buffer size & location */ diff --git a/src/H5Fistore.c b/src/H5Fistore.c index ea74165..f617092 100644 --- a/src/H5Fistore.c +++ b/src/H5Fistore.c @@ -862,7 +862,7 @@ H5F_istore_init (H5F_t *f) HDmemset (rdcc, 0, sizeof(H5F_rdcc_t)); if (f->shared->rdcc_nbytes>0 && f->shared->rdcc_nelmts>0) { rdcc->nslots = f->shared->rdcc_nelmts; - rdcc->slot = H5FL_ARR_ALLOC (H5F_rdcc_ent_ptr_t,rdcc->nslots,1); + rdcc->slot = H5FL_ARR_CALLOC (H5F_rdcc_ent_ptr_t,rdcc->nslots); if (NULL==rdcc->slot) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); } @@ -1440,7 +1440,7 @@ H5F_istore_lock(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL, "unable to preempt chunk(s) from cache"); /* Create a new entry */ - ent = H5FL_ALLOC(H5F_rdcc_ent_t,0); + ent = H5FL_MALLOC(H5F_rdcc_ent_t); ent->locked = 0; ent->dirty = FALSE; ent->chunk_size = chunk_size; @@ -1943,8 +1943,9 @@ H5F_istore_write(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, #ifdef H5_HAVE_PARALLEL /* Additional sanity check when operating in parallel */ - if (chunk_addr==HADDR_UNDEF || pline.nfilters>0) + if (chunk_addr==HADDR_UNDEF || pline.nfilters>0) { HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "unable to locate raw data chunk"); + } #endif /* H5_HAVE_PARALLEL */ /* @@ -2312,7 +2313,7 @@ done: */ herr_t H5F_istore_allocate(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, - const hsize_t *space_dim, H5P_genplist_t *dc_plist) + const hsize_t *space_dim, H5P_genplist_t *dc_plist, hbool_t full_overwrite) { hssize_t chunk_offset[H5O_LAYOUT_NDIMS]; /* Offset of current chunk */ hsize_t chunk_size; /* Size of chunk in bytes */ @@ -2407,7 +2408,7 @@ H5F_istore_allocate(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, } /* end for */ /* Check if fill values should be written to blocks */ - if(fill_time != H5D_FILL_TIME_NEVER) { + if(fill_time != H5D_FILL_TIME_NEVER && !full_overwrite) { /* Allocate chunk buffer for processes to use when writing fill values */ H5_CHECK_OVERFLOW(chunk_size,hsize_t,size_t); if (NULL==(chunk = H5MM_malloc((size_t)chunk_size))) @@ -2484,7 +2485,7 @@ H5F_istore_allocate(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to allocate chunk"); /* Check if fill values should be written to blocks */ - if(fill_time != H5D_FILL_TIME_NEVER) { + if(fill_time != H5D_FILL_TIME_NEVER && !full_overwrite) { #ifdef H5_HAVE_PARALLEL /* Check if this file is accessed with an MPI-capable file driver */ if(using_mpi) { diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h index 4c42ced..9326060 100644 --- a/src/H5Fpkg.h +++ b/src/H5Fpkg.h @@ -17,10 +17,13 @@ #define _H5Fpkg_H #include "H5Fprivate.h" +#include "H5FOprivate.h" /* File objects */ /* This is a near top-level header! Try not to include much! */ #include "H5private.h" +#include "H5Bpublic.h" /* B-tree header, for H5B_NUM_BTREE_ID */ + /* * Feature: Define this constant to be non-zero if you want to enable code * that minimizes the number of calls to lseek(). This has a huge @@ -94,6 +97,13 @@ typedef struct H5F_file_t { H5FD_t *lf; /* Lower level file handle for I/O */ unsigned nrefs; /* Ref count for times file is opened */ uint32_t consist_flags; /* File Consistency Flags */ + + /* Cached values from FCPL */ + size_t sizeof_addr; /* Size of addresses in file */ + size_t sizeof_size; /* Size of offsets in file */ + unsigned sym_leaf_k; /* Size of leaves in symbol tables */ + int btree_k[H5B_NUM_BTREE_ID]; /* B-tree key values for each type */ + haddr_t boot_addr; /* Absolute address of boot block */ haddr_t base_addr; /* Absolute base address for rel.addrs. */ haddr_t freespace_addr; /* Relative address of free-space info */ @@ -110,8 +120,9 @@ typedef struct H5F_file_t { hsize_t alignment; /* Alignment */ unsigned gc_ref; /* Garbage-collect references? */ struct H5G_t *root_grp; /* Open root group */ - int ncwfs; /* Num entries on cwfs list */ + int ncwfs; /* Num entries on cwfs list */ struct H5HG_heap_t **cwfs; /* Global heap cache */ + H5FO_t *open_objs; /* Open objects in file */ /* Data Sieve Buffering fields */ unsigned char *sieve_buf; /* Buffer to hold data sieve buffer */ @@ -121,7 +132,7 @@ typedef struct H5F_file_t { unsigned sieve_dirty; /* Flag to indicate that the data sieve buffer is dirty */ H5F_rdcc_t rdcc; /* Raw data chunk cache */ - H5F_close_degree_t fc_degree; /* File close behavior degree */ + H5F_close_degree_t fc_degree; /* File close behavior degree */ } H5F_file_t; /* A record of the mount table */ diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 42f174c..395b5e2 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -152,8 +152,10 @@ typedef struct H5F_t H5F_t; (X)+(haddr_t)(Z)<(X)) #define H5F_addr_hash(X,M) ((unsigned)((X)%(M))) #define H5F_addr_defined(X) (X!=HADDR_UNDEF) +/* The H5F_addr_eq() macro guarantees that Y is not HADDR_UNDEF by making + * certain that X is not HADDR_UNDEF and then checking that X equals Y + */ #define H5F_addr_eq(X,Y) ((X)!=HADDR_UNDEF && \ - (Y)!=HADDR_UNDEF && \ (X)==(Y)) #define H5F_addr_ne(X,Y) (!H5F_addr_eq((X),(Y))) #define H5F_addr_lt(X,Y) ((X)!=HADDR_UNDEF && \ @@ -174,12 +176,22 @@ typedef struct H5F_t H5F_t; #define H5F_addr_overlap(O1,L1,O2,L2) ((O1O2) || \ (O1>=O2 && O1<(O2+L2))) +/* If the module using this macro is allowed access to the private variables, access them directly */ +#ifdef H5F_PACKAGE /* size of size_t and off_t as they exist on disk */ +#define H5F_SIZEOF_ADDR(F) ((F)->shared->sizeof_addr) +#define H5F_SIZEOF_SIZE(F) ((F)->shared->sizeof_size) +/* Size of symbol table leafs */ +#define H5F_SYM_LEAF_K(F) ((F)->shared->sym_leaf_k) +/* B-tree key value size */ +#define H5F_KVALUE(F,T) ((F)->shared->btree_k[(T)->id]) +#else /* H5F_PACKAGE */ #define H5F_SIZEOF_ADDR(F) (H5F_sizeof_addr(F)) #define H5F_SIZEOF_SIZE(F) (H5F_sizeof_size(F)) +#define H5F_SYM_LEAF_K(F) (H5F_sym_leaf_k(F)) +#define H5F_KVALUE(F,T) (H5F_Kvalue(F,T)) +#endif /* H5F_PACKAGE */ -H5_DLL size_t H5F_sizeof_addr(const H5F_t *f); -H5_DLL size_t H5F_sizeof_size(const H5F_t *f); /* Macros to encode/decode offset/length's for storing in the file */ #ifdef NOT_YET @@ -344,6 +356,7 @@ struct H5O_pline_t; struct H5O_fill_t; struct H5P_genplist_t; struct H5S_t; +struct H5B_class_t; /* Private functions, not part of the publicly documented API */ H5_DLL herr_t H5F_init(void); @@ -356,6 +369,17 @@ H5_DLL herr_t H5F_get_obj_ids(H5F_t *f, unsigned types, hid_t *obj_id_list); H5_DLL herr_t H5F_get_vfd_handle(H5F_t *file, hid_t fapl, void** file_handle); H5_DLL haddr_t H5F_get_base_addr(const H5F_t *f); +/* Functions than check file mounting information */ +H5_DLL htri_t H5F_is_mount(const H5F_t *file); +H5_DLL htri_t H5F_has_mount(const H5F_t *file); + +/* Functions than retrieve values set from the FCPL */ +H5_DLL size_t H5F_sizeof_addr(const H5F_t *f); +H5_DLL size_t H5F_sizeof_size(const H5F_t *f); +H5_DLL unsigned H5F_sym_leaf_k(const H5F_t *f); +H5_DLL int H5F_Kvalue(const H5F_t *f, const struct H5B_class_t *type); + + /* Functions that operate on array storage */ H5_DLL herr_t H5F_arr_read (H5F_t *f, hid_t dxpl_id, const struct H5O_layout_t *layout, @@ -381,24 +405,24 @@ H5_DLL herr_t H5F_block_write(H5F_t *f, H5FD_mem_t type, haddr_t addr, /* Functions that operate on byte sequences */ H5_DLL herr_t H5F_seq_read(H5F_t *f, hid_t dxpl_id, const struct H5O_layout_t *layout, - struct H5P_genplist_t *dc_plist, + struct H5P_genplist_t *dc_plist, const struct H5O_efl_t *efl, const struct H5S_t *file_space, size_t elmt_size, size_t seq_len, hsize_t file_offset, void *_buf/*out*/); H5_DLL herr_t H5F_seq_write (H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, - struct H5P_genplist_t *dc_plist, + struct H5P_genplist_t *dc_plist, const struct H5O_efl_t *efl, const struct H5S_t *file_space, size_t elmt_size, size_t seq_len, hsize_t file_offset, const void *_buf); /* Functions that operate on vectors of byte sequences */ H5_DLL herr_t H5F_seq_readv(H5F_t *f, hid_t dxpl_id, const struct H5O_layout_t *layout, - struct H5P_genplist_t *dc_plist, + struct H5P_genplist_t *dc_plist, const struct H5O_efl_t *efl, const struct H5S_t *file_space, size_t elmt_size, size_t nseq, size_t seq_len[], hsize_t file_offset[], void *_buf/*out*/); H5_DLL herr_t H5F_seq_writev(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, - struct H5P_genplist_t *dc_plist, + struct H5P_genplist_t *dc_plist, const struct H5O_efl_t *efl, const struct H5S_t *file_space, size_t elmt_size, size_t nseq, size_t seq_len[], hsize_t file_offset[], const void *_buf); @@ -406,15 +430,15 @@ H5_DLL herr_t H5F_seq_writev(H5F_t *f, hid_t dxpl_id, /* Functions that operate on contiguous storage */ H5_DLL herr_t H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, struct H5P_genplist_t *dc_plist, - const struct H5S_t *space, size_t elmt_size); + const struct H5O_efl_t *efl, const struct H5S_t *space, + const struct H5O_fill_t *fill, size_t elmt_size); /* Functions that operate on indexed storage */ H5_DLL herr_t H5F_istore_create(H5F_t *f, struct H5O_layout_t *layout/*in,out*/); H5_DLL herr_t H5F_istore_allocate (H5F_t *f, hid_t dxpl_id, - const struct H5O_layout_t *layout, - const hsize_t *space_dim, - struct H5P_genplist_t *dc_plist); + const struct H5O_layout_t *layout, const hsize_t *space_dim, + struct H5P_genplist_t *dc_plist, hbool_t full_overwrite); H5_DLL hsize_t H5F_istore_allocated(H5F_t *f, unsigned ndims, haddr_t addr); H5_DLL herr_t H5F_istore_dump_btree(H5F_t *f, FILE *stream, unsigned ndims, haddr_t addr); diff --git a/src/H5Fpublic.h b/src/H5Fpublic.h index adddd83..edee20b 100644 --- a/src/H5Fpublic.h +++ b/src/H5Fpublic.h @@ -28,13 +28,25 @@ * which are compatible with the library to which the application is linked. * We're assuming that these constants are used rather early in the hdf5 * session. + * + * NOTE: When adding H5F_ACC_* macros, remember to redefine them in H5Fprivate.h + * */ -#define H5F_ACC_RDONLY (H5check(),0x0000u) /*absence of rdwr => rd-only */ -#define H5F_ACC_RDWR (H5check(),0x0001u) /*open for read and write */ -#define H5F_ACC_TRUNC (H5check(),0x0002u) /*overwrite existing files */ -#define H5F_ACC_EXCL (H5check(),0x0004u) /*fail if file already exists*/ -#define H5F_ACC_DEBUG (H5check(),0x0008u) /*print debug info */ -#define H5F_ACC_CREAT (H5check(),0x0010u) /*create non-existing files */ + +/* When this header is included from H5Fprivate.h, don't make calls to H5check() */ +#undef H5CHECK +#ifndef _H5Fprivate_H +#define H5CHECK H5check(), +#else /* _H5Fprivate_H */ +#define H5CHECK +#endif /* _H5Fprivate_H */ + +#define H5F_ACC_RDONLY (H5CHECK 0x0000u) /*absence of rdwr => rd-only */ +#define H5F_ACC_RDWR (H5CHECK 0x0001u) /*open for read and write */ +#define H5F_ACC_TRUNC (H5CHECK 0x0002u) /*overwrite existing files */ +#define H5F_ACC_EXCL (H5CHECK 0x0004u) /*fail if file already exists*/ +#define H5F_ACC_DEBUG (H5CHECK 0x0008u) /*print debug info */ +#define H5F_ACC_CREAT (H5CHECK 0x0010u) /*create non-existing files */ #define H5F_OBJ_FILE (0x0001u) #define H5F_OBJ_DATASET (0x0002u) diff --git a/src/H5Fseq.c b/src/H5Fseq.c index 6176003..9592725 100644 --- a/src/H5Fseq.c +++ b/src/H5Fseq.c @@ -59,9 +59,9 @@ static int interface_initialize_g = 0; */ herr_t H5F_seq_read(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, - H5P_genplist_t *dc_plist, - const H5S_t *file_space, size_t elmt_size, - size_t seq_len, hsize_t dset_offset, void *buf/*out*/) + H5P_genplist_t *dc_plist, const H5O_efl_t *efl, + const H5S_t *file_space, size_t elmt_size, + size_t seq_len, hsize_t dset_offset, void *buf/*out*/) { herr_t ret_value=SUCCEED; /* Return value */ @@ -70,10 +70,11 @@ H5F_seq_read(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, /* Check args */ assert(f); assert(layout); + assert(efl); assert(buf); assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); - if (H5F_seq_readv(f, dxpl_id, layout, dc_plist, file_space, elmt_size, 1, &seq_len, &dset_offset, buf)<0) + if (H5F_seq_readv(f, dxpl_id, layout, dc_plist, efl, file_space, elmt_size, 1, &seq_len, &dset_offset, buf)<0) HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "vector read failed"); done: @@ -104,9 +105,9 @@ done: */ herr_t H5F_seq_write(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout, - H5P_genplist_t *dc_plist, - const H5S_t *file_space, size_t elmt_size, - size_t seq_len, hsize_t dset_offset, const void *buf) + H5P_genplist_t *dc_plist, const H5O_efl_t *efl, + const H5S_t *file_space, size_t elmt_size, + size_t seq_len, hsize_t dset_offset, const void *buf) { herr_t ret_value=SUCCEED; /* Return value */ @@ -115,10 +116,11 @@ H5F_seq_write(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout, /* Check args */ assert(f); assert(layout); + assert(efl); assert(buf); assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); - if (H5F_seq_writev(f, dxpl_id, layout, dc_plist, file_space, elmt_size, 1, &seq_len, &dset_offset, buf)<0) + if (H5F_seq_writev(f, dxpl_id, layout, dc_plist, efl, file_space, elmt_size, 1, &seq_len, &dset_offset, buf)<0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vector write failed"); done: @@ -151,7 +153,7 @@ done: */ herr_t H5F_seq_readv(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, - H5P_genplist_t *dc_plist, + H5P_genplist_t *dc_plist, const H5O_efl_t *efl, const H5S_t *file_space, size_t elmt_size, size_t nseq, size_t seq_len_arr[], hsize_t dset_offset_arr[], void *_buf/*out*/) @@ -172,7 +174,6 @@ H5F_seq_readv(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, unsigned u; /*counters */ size_t v; /*counters */ int i,j; /*counters */ - struct H5O_efl_t efl; /* External File List info */ #ifdef H5_HAVE_PARALLEL H5FD_mpio_xfer_t xfer_mode=H5FD_MPIO_INDEPENDENT; H5P_genplist_t *plist=NULL; /* Property list */ @@ -184,6 +185,7 @@ H5F_seq_readv(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, /* Check args */ assert(f); assert(layout); + assert(efl); assert(real_buf); /* Make certain we have the correct type of property list */ assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); @@ -221,14 +223,10 @@ H5F_seq_readv(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, HGOTO_ERROR (H5E_DATASET, H5E_READERROR, FAIL, "collective access on non-contiguous datasets not supported yet"); #endif /* H5_HAVE_PARALLEL */ - /* Get necessary properties from property list */ - if(H5P_get(dc_plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get EFL value"); - switch (layout->type) { case H5D_CONTIGUOUS: /* Read directly from file if the dataset is in an external file */ - if (efl.nused>0) { + if (efl->nused>0) { /* Iterate through the sequence vectors */ for(v=0; v0) + if (efl->nused>0) HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "chunking and external files are mutually exclusive"); /* Compute the file offset coordinates and hyperslab size */ @@ -542,7 +540,7 @@ done: */ herr_t H5F_seq_writev(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout, - H5P_genplist_t *dc_plist, + H5P_genplist_t *dc_plist, const H5O_efl_t *efl, const H5S_t *file_space, size_t elmt_size, size_t nseq, size_t seq_len_arr[], hsize_t dset_offset_arr[], const void *_buf) @@ -563,7 +561,6 @@ H5F_seq_writev(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout, unsigned u; /*counters */ size_t v; /*counters */ int i,j; /*counters */ - struct H5O_efl_t efl; /* External File List info */ #ifdef H5_HAVE_PARALLEL H5FD_mpio_xfer_t xfer_mode=H5FD_MPIO_INDEPENDENT; H5P_genplist_t *plist=NULL; /* Property list */ @@ -575,6 +572,7 @@ H5F_seq_writev(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout, /* Check args */ assert(f); assert(layout); + assert(efl); assert(real_buf); /* Make certain we have the correct type of property list */ assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); @@ -612,14 +610,10 @@ H5F_seq_writev(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout, HGOTO_ERROR (H5E_DATASET, H5E_WRITEERROR, FAIL, "collective access on chunked datasets not supported yet"); #endif /* H5_HAVE_PARALLEL */ - /* Get necessary properties from property list */ - if(H5P_get(dc_plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get EFL value"); - switch (layout->type) { case H5D_CONTIGUOUS: /* Write directly to file if the dataset is in an external file */ - if (efl.nused>0) { + if (efl->nused>0) { /* Iterate through the sequence vectors */ for(v=0; v0) + if (efl->nused>0) HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "chunking and external files are mutually exclusive"); /* Compute the file offset coordinates and hyperslab size */ diff --git a/src/H5G.c b/src/H5G.c index d6d4ea1..bc63e05 100644 --- a/src/H5G.c +++ b/src/H5G.c @@ -111,16 +111,25 @@ static size_t H5G_comp_alloc_g = 0; /*sizeof component buffer */ /* Struct only used by change name callback function */ typedef struct H5G_names_t { H5G_entry_t *loc; - const char *src_name; + H5RS_str_t *src_name; H5G_entry_t *src_loc; - const char *dst_name; + H5RS_str_t *dst_name; H5G_entry_t *dst_loc; H5G_names_op_t op; } H5G_names_t; +/* Enum for H5G_namei actions */ +typedef enum { + H5G_NAMEI_TRAVERSE, /* Just traverse groups */ + H5G_NAMEI_INSERT /* Insert entry in group */ +}H5G_namei_act_t ; + /* Declare a free list to manage the H5G_t struct */ H5FL_DEFINE(H5G_t); +/* Declare extern the PQ free list for the wrapped strings */ +H5FL_BLK_EXTERN(str_buf); + /* Private prototypes */ static herr_t H5G_replace_ent(void *obj_ptr, hid_t obj_id, const void *key); static herr_t H5G_traverse_slink(H5G_entry_t *grp_ent/*in,out*/, @@ -1186,21 +1195,28 @@ H5G_basename(const char *name, size_t *size_p) * Modified to deep copies of symbol table entries * Added `id to name' support. * + * Quincey Koziol, 2003-01-06 + * Added "action" and "ent" parameters to allow different actions when + * working on the last component of a name. (Specifically, this allows + * inserting an entry into a group, instead of trying to look it up) + * *------------------------------------------------------------------------- */ static herr_t H5G_namei(H5G_entry_t *loc_ent, const char *name, const char **rest/*out*/, H5G_entry_t *grp_ent/*out*/, H5G_entry_t *obj_ent/*out*/, - unsigned target, int *nlinks/*out*/) + unsigned target, int *nlinks/*out*/, H5G_namei_act_t action, + H5G_entry_t *ent) { H5G_entry_t _grp_ent; /*entry for current group */ H5G_entry_t _obj_ent; /*entry found */ size_t nchars; /*component name length */ int _nlinks = H5G_NLINKS; const char *s = NULL; - unsigned null_obj = obj_ent == NULL ? 1 : 0; /* Flag to indicate this function was called with obj_ent set to NULL */ - unsigned null_grp = grp_ent == NULL ? 1 : 0; /* Flag to indicate this function was called with grp_ent set to NULL */ - unsigned group_copy = 0; /* Flag to indicate that the group entry is copied */ + unsigned null_obj; /* Flag to indicate this function was called with obj_ent set to NULL */ + unsigned null_grp; /* Flag to indicate this function was called with grp_ent set to NULL */ + unsigned group_copy = 0; /* Flag to indicate that the group entry is copied */ + unsigned last_comp = 0; /* Flag to indicate that a component is the last component in the name */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOINIT(H5G_namei); @@ -1209,13 +1225,17 @@ H5G_namei(H5G_entry_t *loc_ent, const char *name, const char **rest/*out*/, if (rest) *rest = name; if (!grp_ent) { - HDmemset(&_grp_ent,0,sizeof(H5G_entry_t)); grp_ent = &_grp_ent; + null_grp = 1; } /* end if */ + else + null_grp = 0; if (!obj_ent) { - HDmemset(&_obj_ent,0,sizeof(H5G_entry_t)); obj_ent = &_obj_ent; + null_obj = 1; } /* end if */ + else + null_obj = 0; if (!nlinks) nlinks = &_nlinks; @@ -1293,21 +1313,46 @@ H5G_namei(H5G_entry_t *loc_ent, const char *name, const char **rest/*out*/, /* Set flag that we've copied a new entry into the group entry */ group_copy =1; - if (H5G_stab_find(grp_ent, H5G_comp_g, obj_ent/*out*/ )<0) { - /* - * Component was not found in the current symbol table, possibly - * because GRP_ENT isn't a symbol table. - */ - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "component not found"); - } + /* Check if this is the last component of the name */ + if(!((s=H5G_component(name+nchars, NULL)) && *s)) + last_comp=1; + + switch(action) { + case H5G_NAMEI_TRAVERSE: + if (H5G_stab_find(grp_ent, H5G_comp_g, obj_ent/*out*/ )<0) { + /* + * Component was not found in the current symbol table, possibly + * because GRP_ENT isn't a symbol table. + */ + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "component not found"); + } + break; + + case H5G_NAMEI_INSERT: + if(!last_comp) { + if (H5G_stab_find(grp_ent, H5G_comp_g, obj_ent/*out*/ )<0) { + /* + * Component was not found in the current symbol table, possibly + * because GRP_ENT isn't a symbol table. + */ + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "component not found"); + } + } /* end if */ + else { + if (H5G_stab_insert(grp_ent, H5G_comp_g, ent) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert name"); + HGOTO_DONE(SUCCEED); + } /* end else */ + break; + } /* end switch */ /* * If we found a symbolic link then we should follow it. But if this * is the last component of the name and the H5G_TARGET_SLINK bit of * TARGET is set then we don't follow it. */ - if(H5G_CACHED_SLINK==obj_ent->type && (0==(target & H5G_TARGET_SLINK) || - ((s=H5G_component(name+nchars, NULL)) && *s))) { + if(H5G_CACHED_SLINK==obj_ent->type && + (0==(target & H5G_TARGET_SLINK) || !last_comp)) { if ((*nlinks)-- <= 0) HGOTO_ERROR (H5E_SYM, H5E_SLINK, FAIL, "too many symbolic links"); if (H5G_traverse_slink (grp_ent, obj_ent, nlinks)<0) @@ -1319,10 +1364,8 @@ H5G_namei(H5G_entry_t *loc_ent, const char *name, const char **rest/*out*/, * the H5G_TARGET_MOUNT bit of TARGET is set and this is the last * component of the name. */ - if (0==(target & H5G_TARGET_MOUNT) || - ((s=H5G_component(name+nchars, NULL)) && *s)) { + if (0==(target & H5G_TARGET_MOUNT) || !last_comp) H5F_mountpoint(obj_ent/*in,out*/); - } /* next component */ name += nchars; @@ -1376,7 +1419,7 @@ H5G_traverse_slink (H5G_entry_t *grp_ent/*in,out*/, const char *clv = NULL; /*cached link value */ char *linkval = NULL; /*the copied link value */ H5G_entry_t tmp_grp_ent; /* Temporary copy of group entry */ - char *tmp_user_path=NULL, *tmp_canon_path=NULL; /* Temporary pointer to object's user path & canonical path */ + H5RS_str_t *tmp_user_path_r=NULL, *tmp_canon_path_r=NULL; /* Temporary pointer to object's user path & canonical path */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5G_traverse_slink, FAIL); @@ -1393,10 +1436,10 @@ H5G_traverse_slink (H5G_entry_t *grp_ent/*in,out*/, linkval = H5MM_xstrdup (clv); /* Hold the entry's name (& old_name) to restore later */ - tmp_user_path=obj_ent->user_path; - obj_ent->user_path=NULL; - tmp_canon_path=obj_ent->canon_path; - obj_ent->canon_path=NULL; + tmp_user_path_r=obj_ent->user_path_r; + obj_ent->user_path_r=NULL; + tmp_canon_path_r=obj_ent->canon_path_r; + obj_ent->canon_path_r=NULL; /* Free the names for the group entry */ H5G_free_ent_name(grp_ent); @@ -1405,24 +1448,24 @@ H5G_traverse_slink (H5G_entry_t *grp_ent/*in,out*/, H5G_ent_copy(&tmp_grp_ent,grp_ent,H5G_COPY_DEEP); /* Traverse the link */ - if (H5G_namei (&tmp_grp_ent, linkval, NULL, grp_ent, obj_ent, H5G_TARGET_NORMAL, nlinks)) + if (H5G_namei (&tmp_grp_ent, linkval, NULL, grp_ent, obj_ent, H5G_TARGET_NORMAL, nlinks, H5G_NAMEI_TRAVERSE, NULL)) HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "unable to follow symbolic link"); /* Free the entry's names, we will use the original name for the object */ H5G_free_ent_name(obj_ent); /* Restore previous name for object */ - obj_ent->user_path = tmp_user_path; - tmp_user_path=NULL; - obj_ent->canon_path = tmp_canon_path; - tmp_canon_path=NULL; + obj_ent->user_path_r = tmp_user_path_r; + tmp_user_path_r=NULL; + obj_ent->canon_path_r = tmp_canon_path_r; + tmp_canon_path_r=NULL; done: /* Error cleanup */ - if(tmp_user_path) - H5MM_xfree(tmp_user_path); - if(tmp_canon_path) - H5MM_xfree(tmp_canon_path); + if(tmp_user_path_r) + H5RS_decr(tmp_user_path_r); + if(tmp_canon_path_r) + H5RS_decr(tmp_canon_path_r); /* Release cloned copy of group entry */ H5G_free_ent_name(&tmp_grp_ent); @@ -1475,6 +1518,7 @@ H5G_mkroot (H5F_t *f, H5G_entry_t *ent) */ if (!ent) { ent = &new_root; + HDmemset(ent, 0, sizeof(H5G_entry_t)); if (H5G_stab_create (f, 256, ent/*out*/)<0) HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "unable to create root group"); if (1 != H5O_link (ent, 1)) @@ -1493,10 +1537,10 @@ H5G_mkroot (H5F_t *f, H5G_entry_t *ent) } /* Create the path names for the root group's entry */ - ent->user_path=HDstrdup("/"); - assert(ent->user_path); - ent->canon_path=HDstrdup("/"); - assert(ent->canon_path); + ent->user_path_r=H5RS_create("/"); + assert(ent->user_path_r); + ent->canon_path_r=H5RS_create("/"); + assert(ent->canon_path_r); ent->user_path_hidden=0; /* @@ -1504,7 +1548,7 @@ H5G_mkroot (H5F_t *f, H5G_entry_t *ent) * don't count the root group as an open object. The root group will * never be closed. */ - if (NULL==(f->shared->root_grp = H5FL_ALLOC (H5G_t,1))) + if (NULL==(f->shared->root_grp = H5FL_CALLOC (H5G_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); f->shared->root_grp->ent = *ent; f->shared->root_grp->nref = 1; @@ -1544,11 +1588,8 @@ done: H5G_t * H5G_create(H5G_entry_t *loc, const char *name, size_t size_hint) { - const char *rest = NULL; /*the base name */ - H5G_entry_t grp_ent; /*group containing new group */ - char _comp[1024]; /*name component */ - size_t nchars; /*number of characters in compon*/ H5G_t *grp = NULL; /*new group */ + H5F_t *file; /* File new group will be in */ H5G_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5G_create, NULL); @@ -1557,51 +1598,28 @@ H5G_create(H5G_entry_t *loc, const char *name, size_t size_hint) assert(loc); assert(name && *name); - /* lookup name */ - if (0 == H5G_namei(loc, name, &rest, &grp_ent, NULL, H5G_TARGET_NORMAL, NULL)) - HGOTO_ERROR(H5E_SYM, H5E_EXISTS, NULL, "already exists"); - H5E_clear(); /*it's OK that we didn't find it */ - assert(H5F_addr_defined(grp_ent.header)); - - /* should be one null-terminated component left */ - rest = H5G_component(rest, &nchars); - assert(rest && *rest); - if (rest[nchars]) { - const char *t = H5G_component(rest+nchars, NULL); - if (t && *t) { - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "missing component"); - } else if (nchars+1 > sizeof _comp) { - HGOTO_ERROR(H5E_SYM, H5E_COMPLEN, NULL, "component is too long"); - } else { - /* null terminate */ - HDmemcpy(_comp, rest, nchars); - _comp[nchars] = '\0'; - rest = _comp; - } - } - /* create an open group */ - if (NULL==(grp = H5FL_ALLOC(H5G_t,1))) + if (NULL==(grp = H5FL_CALLOC(H5G_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - if (H5G_stab_create(grp_ent.file, size_hint, &(grp->ent)/*out*/) < 0) + + /* What file is the group being added to? */ + if (NULL==(file=H5G_insertion_file(loc, name))) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "unable to locate insertion point"); + + /* Create the group entry */ + if (H5G_stab_create(file, size_hint, &(grp->ent)/*out*/) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "can't create grp"); /* insert child name into parent */ - if (1!=H5O_link(&(grp->ent), 1)) - HGOTO_ERROR(H5E_SYM, H5E_LINK, NULL, "link inc failure"); - if (H5G_stab_insert(&grp_ent, rest, &(grp->ent)) < 0) { - H5O_close(&(grp->ent)); - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "can't insert"); - } + if(H5G_insert(loc,name,&(grp->ent))<0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, NULL, "can't insert group"); + grp->nref = 1; /* Set return value */ ret_value=grp; done: - /* Free the group entry created from H5G_namei() */ - H5G_free_ent_name(&grp_ent); - if(ret_value==NULL) { if(grp!=NULL) H5FL_FREE(H5G_t,grp); @@ -1733,7 +1751,7 @@ H5G_open_oid(H5G_entry_t *ent) assert(ent); /* Open the object, making sure it's a group */ - if (NULL==(grp = H5FL_ALLOC(H5G_t,1))) + if (NULL==(grp = H5FL_CALLOC(H5G_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); /* Copy over (take ownership) of the group entry object */ @@ -1894,10 +1912,6 @@ done: herr_t H5G_insert(H5G_entry_t *loc, const char *name, H5G_entry_t *ent) { - const char *rest = NULL; /*part of name not existing yet */ - H5G_entry_t grp; /*entry for group to contain obj */ - size_t nchars; /*number of characters in name */ - char _comp[1024]; /*name component */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5G_insert, FAIL); @@ -1908,44 +1922,18 @@ H5G_insert(H5G_entry_t *loc, const char *name, H5G_entry_t *ent) assert (ent); /* - * Look up the name -- it shouldn't exist yet. + * Lookup and insert the name -- it shouldn't exist yet. */ - if (H5G_namei(loc, name, &rest, &grp, NULL, H5G_TARGET_NORMAL, NULL)>=0) + if (H5G_namei(loc, name, NULL, NULL, NULL, H5G_TARGET_NORMAL, NULL, H5G_NAMEI_INSERT, ent)<0) HGOTO_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "already exists"); - H5E_clear(); /*it's OK that we didn't find it */ - rest = H5G_component(rest, &nchars); - - /* - * There should be one component left. Make sure it's null - * terminated. - */ - if (rest[nchars]) { - if (H5G_component(rest + nchars, NULL)) { - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "component not found"); - } else if (nchars + 1 > sizeof _comp) { - HGOTO_ERROR(H5E_SYM, H5E_COMPLEN, FAIL, "component is too long"); - } else { - /* null terminate */ - HDmemcpy(_comp, rest, nchars); - _comp[nchars] = '\0'; - rest = _comp; - } - } /* * Insert the object into a symbol table. */ if (H5O_link(ent, 1) < 0) HGOTO_ERROR(H5E_SYM, H5E_LINK, FAIL, "unable to increment hard link count"); - if (H5G_stab_insert(&grp, rest, ent) < 0) { - H5O_link(ent, -1); - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to insert name"); - } done: - /*Free the ID to name buffer */ - H5G_free_ent_name(&grp); - FUNC_LEAVE(ret_value); } @@ -1989,7 +1977,7 @@ H5G_find(H5G_entry_t *loc, const char *name, assert (loc); assert (name && *name); - if (H5G_namei(loc, name, NULL, grp_ent, obj_ent, H5G_TARGET_NORMAL, NULL)<0) + if (H5G_namei(loc, name, NULL, grp_ent, obj_ent, H5G_TARGET_NORMAL, NULL, H5G_NAMEI_TRAVERSE, NULL)<0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found"); done: @@ -2184,8 +2172,8 @@ H5G_link (H5G_entry_t *cur_loc, const char *cur_name, H5G_entry_t *new_loc, * Lookup the the new_name so we can get the group which will contain * the new entry. The entry shouldn't exist yet. */ - if (H5G_namei (new_loc, new_name, &rest, &grp_ent, NULL, - H5G_TARGET_NORMAL, NULL)>=0) + if (H5G_namei(new_loc, new_name, &rest, &grp_ent, NULL, + H5G_TARGET_NORMAL, NULL, H5G_NAMEI_TRAVERSE, NULL)>=0) HGOTO_ERROR (H5E_SYM, H5E_EXISTS, FAIL, "already exists"); H5E_clear (); /*it's okay that we didn't find it*/ rest = H5G_component (rest, &nchars); @@ -2239,7 +2227,7 @@ H5G_link (H5G_entry_t *cur_loc, const char *cur_name, H5G_entry_t *new_loc, break; case H5G_LINK_HARD: - if (H5G_namei(cur_loc, cur_name, NULL, NULL, &cur_obj, namei_flags, NULL)<0) + if (H5G_namei(cur_loc, cur_name, NULL, NULL, &cur_obj, namei_flags, NULL, H5G_NAMEI_TRAVERSE, NULL)<0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "source object not found"); if (H5G_insert (new_loc, new_name, &cur_obj)<0) HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "unable to create new name/link for object"); @@ -2339,8 +2327,8 @@ H5G_get_objinfo (H5G_entry_t *loc, const char *name, hbool_t follow_link, if (statbuf) HDmemset (statbuf, 0, sizeof *statbuf); /* Find the object's symbol table entry */ - if (H5G_namei (loc, name, NULL, &grp_ent/*out*/, &obj_ent/*out*/, - (unsigned)(follow_link?H5G_TARGET_NORMAL:H5G_TARGET_SLINK), NULL)<0) + if (H5G_namei(loc, name, NULL, &grp_ent/*out*/, &obj_ent/*out*/, + (unsigned)(follow_link?H5G_TARGET_NORMAL:H5G_TARGET_SLINK), NULL, H5G_NAMEI_TRAVERSE, NULL)<0) HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "unable to stat object"); /* @@ -2374,7 +2362,10 @@ H5G_get_objinfo (H5G_entry_t *loc, const char *name, hbool_t follow_link, statbuf->type = H5G_LINK; if (NULL==H5O_read(&obj_ent, H5O_MTIME, 0, &(statbuf->mtime))) { H5E_clear(); - statbuf->mtime = 0; + if (NULL==H5O_read(&obj_ent, H5O_MTIME_NEW, 0, &(statbuf->mtime))) { + H5E_clear(); + statbuf->mtime = 0; + } } statbuf->type = H5G_get_type(&obj_ent); H5E_clear(); /*clear errors resulting from checking type*/ @@ -2450,7 +2441,7 @@ done: ssize_t H5G_get_objname_by_idx(H5G_t *grp, hsize_t idx, char* name, size_t size) { - ssize_t ret_value = FAIL; + ssize_t ret_value; H5G_bt_ud3_t udata; FUNC_ENTER_NOAPI(H5G_get_objname_by_idx, FAIL); @@ -2472,10 +2463,10 @@ H5G_get_objname_by_idx(H5G_t *grp, hsize_t idx, char* name, size_t size) name[size-1]='\0'; } - /* Free the duplicated name */ - H5MM_xfree(udata.name); - done: + /* Free the duplicated name */ + if(udata.name!=NULL) + H5MM_xfree(udata.name); FUNC_LEAVE(ret_value); } @@ -2558,8 +2549,8 @@ H5G_linkval (H5G_entry_t *loc, const char *name, size_t size, char *buf/*out*/) * Get the symbol table entry for the link head and the symbol table * entry for the group in which the link head appears. */ - if (H5G_namei (loc, name, NULL, &grp_ent/*out*/, &obj_ent/*out*/, - H5G_TARGET_SLINK, NULL)<0) + if (H5G_namei(loc, name, NULL, &grp_ent/*out*/, &obj_ent/*out*/, + H5G_TARGET_SLINK, NULL, H5G_NAMEI_TRAVERSE, NULL)<0) HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "symbolic link was not found"); if (H5G_CACHED_SLINK!=obj_ent.type) HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "object is not a symbolic link"); @@ -2615,7 +2606,7 @@ H5G_set_comment(H5G_entry_t *loc, const char *name, const char *buf) /* Get the symbol table entry for the object */ if (H5G_namei(loc, name, NULL, NULL, &obj_ent/*out*/, H5G_TARGET_NORMAL, - NULL)<0) + NULL, H5G_NAMEI_TRAVERSE, NULL)<0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found"); /* Remove the previous comment message if any */ @@ -2624,7 +2615,7 @@ H5G_set_comment(H5G_entry_t *loc, const char *name, const char *buf) /* Add the new message */ if (buf && *buf) { comment.s = H5MM_xstrdup(buf); - if (H5O_modify(&obj_ent, H5O_NAME, H5O_NEW_MESG, 0, &comment)<0) + if (H5O_modify(&obj_ent, H5O_NAME, H5O_NEW_MESG, 0, 1, &comment)<0) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to set comment object header message"); H5O_reset(H5O_NAME, &comment); } @@ -2669,7 +2660,7 @@ H5G_get_comment(H5G_entry_t *loc, const char *name, size_t bufsize, char *buf) /* Get the symbol table entry for the object */ if (H5G_namei(loc, name, NULL, NULL, &obj_ent/*out*/, H5G_TARGET_NORMAL, - NULL)<0) + NULL, H5G_NAMEI_TRAVERSE, NULL)<0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found"); /* Get the message */ @@ -2717,6 +2708,7 @@ H5G_unlink(H5G_entry_t *loc, const char *name) size_t len; const char *base=NULL; H5G_stat_t statbuf; /* Info about object to unlink */ + H5RS_str_t *name_r; /* Ref-counted version of name */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5G_unlink, FAIL); @@ -2733,7 +2725,7 @@ H5G_unlink(H5G_entry_t *loc, const char *name) /* Get the entry for the group that contains the object to be unlinked */ if (H5G_namei(loc, name, NULL, &grp_ent, &obj_ent, - H5G_TARGET_SLINK|H5G_TARGET_MOUNT, NULL)<0) + H5G_TARGET_SLINK|H5G_TARGET_MOUNT, NULL, H5G_NAMEI_TRAVERSE, NULL)<0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found"); if (!H5F_addr_defined(grp_ent.header)) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "no containing group specified"); @@ -2745,8 +2737,11 @@ H5G_unlink(H5G_entry_t *loc, const char *name) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to unlink name from symbol table"); /* Search the open IDs and replace names for unlinked object */ - if (H5G_replace_name(statbuf.type, &obj_ent, name, NULL, NULL, NULL, OP_UNLINK )<0) + name_r=H5RS_wrap(name); + assert(name_r); + if (H5G_replace_name(statbuf.type, &obj_ent, name_r, NULL, NULL, NULL, OP_UNLINK )<0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to replace name"); + H5RS_decr(name_r); done: /* Free the ID to name buffers */ @@ -2785,6 +2780,8 @@ H5G_move(H5G_entry_t *src_loc, const char *src_name, H5G_entry_t *dst_loc, char *linkval=NULL; size_t lv_size=32; H5G_entry_t obj_ent; /* Object entry for object being moved */ + H5RS_str_t *src_name_r; /* Ref-counted version of src name */ + H5RS_str_t *dst_name_r; /* Ref-counted version of dest name */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5G_move, FAIL); @@ -2825,10 +2822,16 @@ H5G_move(H5G_entry_t *src_loc, const char *src_name, H5G_entry_t *dst_loc, * This has to be done here because H5G_link and H5G_unlink have * internal object entries, and do not modify the entries list */ - if (H5G_namei (src_loc, src_name, NULL, NULL, &obj_ent, H5G_TARGET_NORMAL|H5G_TARGET_SLINK, NULL)) + if (H5G_namei(src_loc, src_name, NULL, NULL, &obj_ent, H5G_TARGET_NORMAL|H5G_TARGET_SLINK, NULL, H5G_NAMEI_TRAVERSE, NULL)) HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "unable to follow symbolic link"); - if (H5G_replace_name(sb.type, &obj_ent, src_name, src_loc, dst_name, dst_loc, OP_MOVE )<0) + src_name_r=H5RS_wrap(src_name); + assert(src_name_r); + dst_name_r=H5RS_wrap(dst_name); + assert(dst_name_r); + if (H5G_replace_name(sb.type, &obj_ent, src_name_r, src_loc, dst_name_r, dst_loc, OP_MOVE )<0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to replace name "); + H5RS_decr(src_name_r); + H5RS_decr(dst_name_r); H5G_free_ent_name(&obj_ent); /* Remove the old name */ @@ -2864,37 +2867,53 @@ done: H5F_t * H5G_insertion_file(H5G_entry_t *loc, const char *name) { - const char *rest; - H5G_entry_t grp_ent; - size_t size; H5F_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5G_insertion_file, NULL); + assert(loc); assert(name && *name); - /* - * Look up the name to get the containing group and to make sure the name - * doesn't already exist. + /* Check if the location the object will be inserted into is part of a + * file mounting chain (either a parent or a child) and perform a more + * rigorous determination of the location's file (which traverses into + * mounted files, etc.). */ - if (H5G_namei(loc, name, &rest, &grp_ent, NULL, H5G_TARGET_NORMAL, NULL)>=0) - HGOTO_ERROR(H5E_SYM, H5E_EXISTS, NULL, "name already exists"); - H5E_clear(); + if(H5F_has_mount(loc->file) || H5F_is_mount(loc->file)) { + const char *rest; + H5G_entry_t grp_ent; + size_t size; + + /* + * Look up the name to get the containing group and to make sure the name + * doesn't already exist. + */ + if (H5G_namei(loc, name, &rest, &grp_ent, NULL, H5G_TARGET_NORMAL, NULL, H5G_NAMEI_TRAVERSE, NULL)>=0) { + H5G_free_ent_name(&grp_ent); + HGOTO_ERROR(H5E_SYM, H5E_EXISTS, NULL, "name already exists"); + } /* end if */ + H5E_clear(); + + /* Make sure only the last component wasn't resolved */ + rest = H5G_component(rest, &size); + assert(*rest && size>0); + rest = H5G_component(rest+size, NULL); + if (*rest) { + H5G_free_ent_name(&grp_ent); + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "insertion point not found"); + } /* end if */ - /* Make sure only the last component wasn't resolved */ - rest = H5G_component(rest, &size); - assert(*rest && size>0); - rest = H5G_component(rest+size, NULL); - if (*rest) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "insertion point not found"); + /* Set return value */ + ret_value=grp_ent.file; - /* Set return value */ - ret_value=grp_ent.file; + /* Free the ID to name buffer */ + H5G_free_ent_name(&grp_ent); + } /* end if */ + else + /* Use the location's file */ + ret_value=loc->file; done: - /* Free the ID to name buffer */ - H5G_free_ent_name(&grp_ent); - FUNC_LEAVE(ret_value); } @@ -2967,10 +2986,14 @@ H5G_free_ent_name(H5G_entry_t *ent) /* Check args */ assert(ent); - if(ent->user_path) - ent->user_path = H5MM_xfree(ent->user_path); - if(ent->canon_path) - ent->canon_path = H5MM_xfree(ent->canon_path); + if(ent->user_path_r) { + H5RS_decr(ent->user_path_r); + ent->user_path_r=NULL; + } /* end if */ + if(ent->canon_path_r) { + H5RS_decr(ent->canon_path_r); + ent->canon_path_r=NULL; + } /* end if */ done: FUNC_LEAVE(ret_value); @@ -3001,8 +3024,8 @@ done: */ herr_t H5G_replace_name( int type, H5G_entry_t *loc, - const char *src_name, H5G_entry_t *src_loc, - const char *dst_name, H5G_entry_t *dst_loc, H5G_names_op_t op ) + H5RS_str_t *src_name, H5G_entry_t *src_loc, + H5RS_str_t *dst_name, H5G_entry_t *dst_loc, H5G_names_op_t op ) { H5G_names_t names; /* Structure to hold operation information for callback */ unsigned search_group=0; /* Flag to indicate that groups are to be searched */ @@ -3095,16 +3118,22 @@ done: *------------------------------------------------------------------------- */ static htri_t -H5G_common_path(const char *fullpath, const char *prefix) +H5G_common_path(const H5RS_str_t *fullpath_r, const H5RS_str_t *prefix_r) { + const char *fullpath; /* Pointer to actual fullpath string */ + const char *prefix; /* Pointer to actual prefix string */ size_t nchars1,nchars2; /* Number of characters in components */ htri_t ret_value=FALSE; /* Return value */ FUNC_ENTER_NOINIT(H5G_common_path); /* Get component of each name */ + fullpath=H5RS_GET_STR(fullpath_r); + assert(fullpath); fullpath=H5G_component(fullpath,&nchars1); assert(fullpath); + prefix=H5RS_GET_STR(prefix_r); + assert(prefix); prefix=H5G_component(prefix,&nchars2); assert(prefix); @@ -3199,12 +3228,11 @@ H5G_replace_ent(void *obj_ptr, hid_t obj_id, const void *key) *------------------------------------------------------------------------- */ case OP_MOUNT: - if(ent->file->mtab.parent && HDstrcmp(ent->user_path,ent->canon_path)) { + if(ent->file->mtab.parent && H5RS_cmp(ent->user_path_r,ent->canon_path_r)) { /* Find the "top" file in the chain of mounted files */ top_ent_file=ent->file->mtab.parent; - while(top_ent_file->mtab.parent!=NULL) { + while(top_ent_file->mtab.parent!=NULL) top_ent_file=top_ent_file->mtab.parent; - } /* end while */ } /* end if */ else top_ent_file=ent->file; @@ -3213,8 +3241,8 @@ H5G_replace_ent(void *obj_ptr, hid_t obj_id, const void *key) if(top_ent_file->shared == names->loc->file->shared) { /* Check if the source is along the entry's path */ /* (But not actually the entry itself) */ - if(H5G_common_path(ent->user_path,names->src_name) && - HDstrcmp(ent->user_path,names->src_name)!=0) { + if(H5G_common_path(ent->user_path_r,names->src_name) && + H5RS_cmp(ent->user_path_r,names->src_name)!=0) { /* Hide the user path */ ent->user_path_hidden++; } /* end if */ @@ -3229,9 +3257,8 @@ H5G_replace_ent(void *obj_ptr, hid_t obj_id, const void *key) if(ent->file->mtab.parent) { /* Find the "top" file in the chain of mounted files for the entry */ top_ent_file=ent->file->mtab.parent; - while(top_ent_file->mtab.parent!=NULL) { + while(top_ent_file->mtab.parent!=NULL) top_ent_file=top_ent_file->mtab.parent; - } /* end while */ } /* end if */ else top_ent_file=ent->file; @@ -3239,9 +3266,8 @@ H5G_replace_ent(void *obj_ptr, hid_t obj_id, const void *key) if(names->loc->file->mtab.parent) { /* Find the "top" file in the chain of mounted files for the location */ top_loc_file=names->loc->file->mtab.parent; - while(top_loc_file->mtab.parent!=NULL) { + while(top_loc_file->mtab.parent!=NULL) top_loc_file=top_loc_file->mtab.parent; - } /* end while */ } /* end if */ else top_loc_file=names->loc->file; @@ -3249,7 +3275,7 @@ H5G_replace_ent(void *obj_ptr, hid_t obj_id, const void *key) if(ent->user_path_hidden) { /* If the ID's entry is not in the file we operated on, skip it */ if(top_ent_file->shared == top_loc_file->shared) { - if(H5G_common_path(ent->user_path,names->src_name)) { + if(H5G_common_path(ent->user_path_r,names->src_name)) { /* Un-hide the user path */ ent->user_path_hidden--; } /* end if */ @@ -3258,9 +3284,12 @@ H5G_replace_ent(void *obj_ptr, hid_t obj_id, const void *key) else { /* If the ID's entry is not in the file we operated on, skip it */ if(top_ent_file->shared == top_loc_file->shared) { - if(ent->user_path && H5G_common_path(ent->user_path,names->src_name)) { + if(ent->user_path_r && H5G_common_path(ent->user_path_r,names->src_name)) { /* Free user path */ - ent->user_path=H5MM_xfree(ent->user_path); + if(ent->user_path_r!=NULL) { + H5RS_decr(ent->user_path_r); + ent->user_path_r=NULL; + } /* end if */ } /* end if */ } /* end if */ } /* end else */ @@ -3276,16 +3305,22 @@ H5G_replace_ent(void *obj_ptr, hid_t obj_id, const void *key) /* Check if we are referring to the same object */ if(H5F_addr_eq(ent->header, names->loc->header)) { /* Check if the object was opened with the same canonical path as the one being moved */ - if(HDstrcmp(ent->canon_path,names->loc->canon_path)==0) { + if(H5RS_cmp(ent->canon_path_r,names->loc->canon_path_r)==0) { /* Free user path */ - ent->user_path=H5MM_xfree(ent->user_path); + if(ent->user_path_r!=NULL) { + H5RS_decr(ent->user_path_r); + ent->user_path_r=NULL; + } /* end if */ } /* end if */ } /* end if */ else { /* Check if the location being unlinked is in the canonical path for the current object */ - if(H5G_common_path(ent->canon_path,names->loc->canon_path)) { + if(H5G_common_path(ent->canon_path_r,names->loc->canon_path_r)) { /* Free user path */ - ent->user_path=H5MM_xfree(ent->user_path); + if(ent->user_path_r!=NULL) { + H5RS_decr(ent->user_path_r); + ent->user_path_r=NULL; + } /* end if */ } /* end if */ } /* end else */ } /* end if */ @@ -3298,90 +3333,116 @@ H5G_replace_ent(void *obj_ptr, hid_t obj_id, const void *key) case OP_MOVE: /* H5Gmove case, check for relative names case */ /* If the ID's entry is not in the file we operated on, skip it */ if(ent->file->shared == names->loc->file->shared) { - char *src_path; /* Full user path of source name */ - char *dst_path; /* Full user path of destination name */ - char *canon_src_path; /* Pointer to canonical part of source path */ - char *canon_dst_path; /* Pointer to canonical part of destination path */ + H5RS_str_t *src_path_r; /* Full user path of source name */ + H5RS_str_t *dst_path_r; /* Full user path of destination name */ + H5RS_str_t *canon_src_path_r; /* Copy of canonical part of source path */ + H5RS_str_t *canon_dst_path_r; /* Copy of canonical part of destination path */ /* Make certain that the source and destination names are full (not relative) paths */ - if(*(names->src_name)!='/') { + if(*(H5RS_GET_STR(names->src_name))!='/') { + const char *src_name; /* Pointer to raw string of src_name */ + char *src_path; /* Full user path of source name */ + const char *src_user_path; /* Pointer to raw string of src path */ size_t src_path_len; /* Length of the source path */ unsigned need_sep; /* Flag to indicate if separator is needed */ + /* Get the pointer to the raw src user path */ + src_user_path=H5RS_GET_STR(names->src_loc->user_path_r); + /* Get the length of the name for the source group's user path */ - src_path_len=HDstrlen(names->src_loc->user_path); + src_path_len=HDstrlen(src_user_path); /* Determine if there is a trailing separator in the name */ - if(names->src_loc->user_path[src_path_len-1]=='/') + if(src_user_path[src_path_len-1]=='/') need_sep=0; else need_sep=1; + /* Get the pointer to the raw src user path */ + src_name=H5RS_GET_STR(names->src_name); + /* Add in the length needed for the '/' separator and the relative path */ - src_path_len+=HDstrlen(names->src_name)+need_sep; + src_path_len+=HDstrlen(src_name)+need_sep; /* Allocate space for the path */ - if(NULL==(src_path = H5MM_malloc(src_path_len+1))) + if(NULL==(src_path = H5FL_BLK_MALLOC(str_buf,src_path_len+1))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - HDstrcpy(src_path,names->src_loc->user_path); + HDstrcpy(src_path,src_user_path); if(need_sep) HDstrcat(src_path,"/"); - HDstrcat(src_path,names->src_name); + HDstrcat(src_path,src_name); + + /* Create reference counted string for src path */ + src_path_r=H5RS_own(src_path); } /* end if */ else - src_path=HDstrdup(names->src_name); - if(*(names->dst_name)!='/') { - size_t dst_path_len; /* Length of the destination path */ + src_path_r=H5RS_dup(names->src_name); + if(*(H5RS_GET_STR(names->dst_name))!='/') { + const char *dst_name; /* Pointer to raw string of dst_name */ + char *dst_path; /* Full user path of destination name */ + const char *dst_user_path; /* Pointer to raw string of dst path */ + size_t dst_path_len; /* Length of the destination path */ unsigned need_sep; /* Flag to indicate if separator is needed */ + /* Get the pointer to the raw dst user path */ + dst_user_path=H5RS_GET_STR(names->dst_loc->user_path_r); + /* Get the length of the name for the destination group's user path */ - dst_path_len=HDstrlen(names->dst_loc->user_path); + dst_path_len=HDstrlen(dst_user_path); /* Determine if there is a trailing separator in the name */ - if(names->dst_loc->user_path[dst_path_len-1]=='/') + if(dst_user_path[dst_path_len-1]=='/') need_sep=0; else need_sep=1; + /* Get the pointer to the raw dst user path */ + dst_name=H5RS_GET_STR(names->dst_name); + /* Add in the length needed for the '/' separator and the relative path */ - dst_path_len+=HDstrlen(names->dst_name)+need_sep; + dst_path_len+=HDstrlen(dst_name)+need_sep; /* Allocate space for the path */ - if(NULL==(dst_path = H5MM_malloc(dst_path_len+1))) + if(NULL==(dst_path = H5FL_BLK_MALLOC(str_buf,dst_path_len+1))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - HDstrcpy(dst_path,names->dst_loc->user_path); + HDstrcpy(dst_path,dst_user_path); if(need_sep) HDstrcat(dst_path,"/"); - HDstrcat(dst_path,names->dst_name); + HDstrcat(dst_path,dst_name); + + /* Create reference counted string for dst path */ + dst_path_r=H5RS_own(dst_path); } /* end if */ else - dst_path=HDstrdup(names->dst_name); + dst_path_r=H5RS_dup(names->dst_name); /* Get the canonical parts of the source and destination names */ /* Check if the object being moved was accessed through a mounted file */ - if(HDstrcmp(names->loc->user_path,names->loc->canon_path)!=0) { + if(H5RS_cmp(names->loc->user_path_r,names->loc->canon_path_r)!=0) { size_t non_canon_name_len; /* Length of non-canonical part of name */ /* Get current string lengths */ - non_canon_name_len=HDstrlen(names->loc->user_path)-HDstrlen(names->loc->canon_path); + non_canon_name_len=H5RS_len(names->loc->user_path_r)-H5RS_len(names->loc->canon_path_r); - canon_src_path=src_path+non_canon_name_len; - canon_dst_path=dst_path+non_canon_name_len; + canon_src_path_r=H5RS_create(H5RS_GET_STR(src_path_r)+non_canon_name_len); + canon_dst_path_r=H5RS_create(H5RS_GET_STR(dst_path_r)+non_canon_name_len); } /* end if */ else { - canon_src_path=src_path; - canon_dst_path=dst_path; + canon_src_path_r=H5RS_dup(src_path_r); + canon_dst_path_r=H5RS_dup(dst_path_r); } /* end else */ /* Check if the link being changed in the file is along the canonical path for this object */ - if(H5G_common_path(ent->canon_path,canon_src_path)) { + if(H5G_common_path(ent->canon_path_r,canon_src_path_r)) { size_t user_dst_len; /* Length of destination user path */ size_t canon_dst_len; /* Length of destination canonical path */ - char *old_user_path; /* Pointer to previous user path */ - char *tail_path; /* Pointer to "tail" of path */ + const char *old_user_path; /* Pointer to previous user path */ + char *new_user_path; /* Pointer to new user path */ + char *new_canon_path; /* Pointer to new canonical path */ + const char *tail_path; /* Pointer to "tail" of path */ size_t tail_len; /* Pointer to "tail" of path */ char *src_canon_prefix; /* Pointer to source canonical path prefix of component which is moving */ size_t src_canon_prefix_len;/* Length of the source canonical path prefix */ @@ -3391,6 +3452,12 @@ H5G_replace_ent(void *obj_ptr, hid_t obj_id, const void *key) size_t user_prefix_len; /* Length of the user path prefix */ char *src_comp; /* The source name of the component which is actually changing */ char *dst_comp; /* The destination name of the component which is actually changing */ + const char *canon_src_path; /* pointer to canonical part of source path */ + const char *canon_dst_path; /* pointer to canonical part of destination path */ + + /* Get the pointers to the raw strings */ + canon_src_path=H5RS_GET_STR(canon_src_path_r); + canon_dst_path=H5RS_GET_STR(canon_dst_path_r); /* Get the source & destination components */ src_comp=HDstrrchr(canon_src_path,'/'); @@ -3411,46 +3478,48 @@ H5G_replace_ent(void *obj_ptr, hid_t obj_id, const void *key) HDstrncpy(dst_canon_prefix,canon_dst_path,dst_canon_prefix_len); dst_canon_prefix[dst_canon_prefix_len]='\0'; + /* Hold this for later use */ + old_user_path=H5RS_GET_STR(ent->user_path_r); + /* Find the user prefix for the entry */ - user_prefix_len=HDstrlen(ent->user_path)-HDstrlen(ent->canon_path); + user_prefix_len=HDstrlen(old_user_path)-H5RS_len(ent->canon_path_r); if(NULL==(user_prefix = H5MM_malloc(user_prefix_len+1))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - HDstrncpy(user_prefix,ent->user_path,user_prefix_len); + HDstrncpy(user_prefix,old_user_path,user_prefix_len); user_prefix[user_prefix_len]='\0'; - /* Hold this for later use */ - old_user_path=ent->user_path; - /* Set the tail path info */ tail_path=old_user_path+user_prefix_len+src_canon_prefix_len+HDstrlen(src_comp); tail_len=HDstrlen(tail_path); - /* Free the old canonical path */ - H5MM_xfree(ent->canon_path); - /* Get the length of the destination paths */ user_dst_len=user_prefix_len+dst_canon_prefix_len+HDstrlen(dst_comp)+tail_len; canon_dst_len=dst_canon_prefix_len+HDstrlen(dst_comp)+tail_len; /* Allocate space for the new user path */ - if(NULL==(ent->user_path = H5MM_malloc(user_dst_len+1))) + if(NULL==(new_user_path = H5FL_BLK_MALLOC(str_buf,user_dst_len+1))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); /* Allocate space for the new canonical path */ - if(NULL==(ent->canon_path = H5MM_malloc(canon_dst_len+1))) + if(NULL==(new_canon_path = H5FL_BLK_MALLOC(str_buf,canon_dst_len+1))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); /* Create the new names */ - HDstrcpy(ent->user_path,user_prefix); - HDstrcat(ent->user_path,dst_canon_prefix); - HDstrcat(ent->user_path,dst_comp); - HDstrcat(ent->user_path,tail_path); - HDstrcpy(ent->canon_path,dst_canon_prefix); - HDstrcat(ent->canon_path,dst_comp); - HDstrcat(ent->canon_path,tail_path); - - /* Free the old user path */ - H5MM_xfree(old_user_path); + HDstrcpy(new_user_path,user_prefix); + HDstrcat(new_user_path,dst_canon_prefix); + HDstrcat(new_user_path,dst_comp); + HDstrcat(new_user_path,tail_path); + HDstrcpy(new_canon_path,dst_canon_prefix); + HDstrcat(new_canon_path,dst_comp); + HDstrcat(new_canon_path,tail_path); + + /* Release the old user & canonical paths */ + H5RS_decr(ent->user_path_r); + H5RS_decr(ent->canon_path_r); + + /* Take ownership of the new user & canonical paths */ + ent->user_path_r=H5RS_own(new_user_path); + ent->canon_path_r=H5RS_own(new_canon_path); /* Free the extra paths allocated */ H5MM_xfree(src_canon_prefix); @@ -3460,8 +3529,10 @@ H5G_replace_ent(void *obj_ptr, hid_t obj_id, const void *key) /* Free the extra paths allocated */ - H5MM_xfree(src_path); - H5MM_xfree(dst_path); + H5RS_decr(src_path_r); + H5RS_decr(dst_path_r); + H5RS_decr(canon_src_path_r); + H5RS_decr(canon_dst_path_r); } /* end if */ break; diff --git a/src/H5Gent.c b/src/H5Gent.c index 4e0a4f9..3bf1a58 100644 --- a/src/H5Gent.c +++ b/src/H5Gent.c @@ -357,6 +357,9 @@ done: * of the functions in the library. * - Added 'depth' parameter to determine how much of the group * entry structure we want to copy. The new depths are: + * H5G_COPY_NULL - Copy all the fields from the + * source to the destination, but set the destination's + * user path and canonical path to NULL. * H5G_COPY_LIMITED - Copy all the fields from the * source to the destination, except for the user path * field, keeping it the same as its @@ -373,19 +376,19 @@ done: herr_t H5G_ent_copy(H5G_entry_t *dst, const H5G_entry_t *src, H5G_ent_copy_depth_t depth) { - char *tmp_user_path=NULL; /* Temporary string pointers for entry's user path */ + H5RS_str_t *tmp_user_path_r=NULL; /* Temporary string pointer for entry's user path */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5G_ent_copy, FAIL); - /* check arguments */ - assert( src ); - assert( dst ); + /* Check arguments */ + assert(src); + assert(dst); /* If the depth is "very shallow", keep the old entry's user path */ if(depth==H5G_COPY_LIMITED) { - tmp_user_path=dst->user_path; - H5MM_xfree(dst->canon_path); + tmp_user_path_r=dst->user_path_r; + H5RS_decr(dst->canon_path_r); } /* end if */ /* Copy the top level information */ @@ -393,11 +396,14 @@ H5G_ent_copy(H5G_entry_t *dst, const H5G_entry_t *src, H5G_ent_copy_depth_t dept /* Deep copy the names */ if(depth==H5G_COPY_DEEP) { - dst->user_path=H5MM_xstrdup(src->user_path); - dst->canon_path=H5MM_xstrdup(src->canon_path); + dst->user_path_r=H5RS_dup(src->user_path_r); + dst->canon_path_r=H5RS_dup(src->canon_path_r); } else if(depth==H5G_COPY_LIMITED) { - dst->user_path=tmp_user_path; - dst->canon_path=H5MM_xstrdup(src->canon_path); + dst->user_path_r=tmp_user_path_r; + dst->canon_path_r=H5RS_dup(src->canon_path_r); + } else if(depth==H5G_COPY_NULL) { + dst->user_path_r=NULL; + dst->canon_path_r=NULL; } /* end if */ done: diff --git a/src/H5Gnode.c b/src/H5Gnode.c index 98fde41..d850910 100644 --- a/src/H5Gnode.c +++ b/src/H5Gnode.c @@ -224,7 +224,7 @@ H5G_node_size(H5F_t *f) FUNC_ENTER_NOINIT(H5G_node_size); FUNC_LEAVE(H5G_NODE_SIZEOF_HDR(f) + - (2 * H5G_node_k(f)) * H5G_SIZEOF_ENTRY(f)); + (2 * H5F_SYM_LEAF_K(f)) * H5G_SIZEOF_ENTRY(f)); } @@ -267,13 +267,13 @@ H5G_node_create(H5F_t *f, H5B_ins_t UNUSED op, void *_lt_key, assert(f); assert(H5B_INS_FIRST == op); - if (NULL==(sym = H5FL_ALLOC(H5G_node_t,1))) + if (NULL==(sym = H5FL_CALLOC(H5G_node_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); size = H5G_node_size(f); if (HADDR_UNDEF==(*addr_p=H5MF_alloc(f, H5FD_MEM_BTREE, size))) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to allocate file space"); sym->dirty = TRUE; - sym->entry = H5FL_ARR_ALLOC(H5G_entry_t,(2*H5G_node_k(f)),1); + sym->entry = H5FL_ARR_CALLOC(H5G_entry_t,(2*H5F_SYM_LEAF_K(f))); if (NULL==sym->entry) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); if (H5AC_set(f, H5AC_SNODE, *addr_p, sym) < 0) @@ -366,7 +366,7 @@ H5G_node_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5G_node_ size = H5G_node_size(f); /* Allocate temporary buffer */ - if ((buf=H5FL_BLK_ALLOC(symbol_node,size, 0))==NULL) + if ((buf=H5FL_BLK_MALLOC(symbol_node,size))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); p=buf; @@ -401,10 +401,6 @@ H5G_node_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5G_node_ * preempted from the cache. */ if (destroy) { - /* Free the ID to name buffer */ - for (i=0; insyms; i++) - H5G_free_ent_name(&(sym->entry[i])); - sym->entry = H5FL_ARR_FREE(H5G_entry_t,sym->entry); H5FL_FREE(H5G_node_t,sym); } @@ -460,11 +456,11 @@ H5G_node_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void * UNUSED _udata1 * Initialize variables. */ size = H5G_node_size(f); - if ((buf=H5FL_BLK_ALLOC(symbol_node,size,0))==NULL) + if ((buf=H5FL_BLK_MALLOC(symbol_node,size))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for symbol table node"); p=buf; - if (NULL==(sym = H5FL_ALLOC(H5G_node_t,1)) || - NULL==(sym->entry=H5FL_ARR_ALLOC(H5G_entry_t,(2*H5G_node_k(f)),1))) + if (NULL==(sym = H5FL_CALLOC(H5G_node_t)) || + NULL==(sym->entry=H5FL_ARR_CALLOC(H5G_entry_t,(2*H5F_SYM_LEAF_K(f))))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); if (H5F_block_read(f, H5FD_MEM_BTREE, addr, size, dxpl_id, buf) < 0) HGOTO_ERROR(H5E_SYM, H5E_READERROR, NULL, "unable to read symbol table node"); @@ -534,6 +530,7 @@ H5G_node_cmp2(H5F_t *f, void *_lt_key, void *_udata, void *_rt_key) H5G_node_key_t *lt_key = (H5G_node_key_t *) _lt_key; H5G_node_key_t *rt_key = (H5G_node_key_t *) _rt_key; const char *s1, *s2; + const char *base; /* Base of heap */ int ret_value; FUNC_ENTER_NOAPI(H5G_node_cmp2, FAIL); @@ -542,11 +539,14 @@ H5G_node_cmp2(H5F_t *f, void *_lt_key, void *_udata, void *_rt_key) assert(lt_key); assert(rt_key); - if (NULL == (s1 = H5HL_peek(f, udata->heap_addr, lt_key->offset))) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read symbol name"); - if (NULL == (s2 = H5HL_peek(f, udata->heap_addr, rt_key->offset))) + /* Get base address of heap */ + if (NULL == (base = H5HL_peek(f, udata->heap_addr, 0))) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read symbol name"); + /* Get pointers to string names */ + s1=base+lt_key->offset; + s2=base+rt_key->offset; + /* Set return value */ ret_value = HDstrcmp(s1, s2); @@ -585,23 +585,26 @@ done: static int H5G_node_cmp3(H5F_t *f, void *_lt_key, void *_udata, void *_rt_key) { - H5G_bt_ud1_t *udata = (H5G_bt_ud1_t *) _udata; - H5G_node_key_t *lt_key = (H5G_node_key_t *) _lt_key; - H5G_node_key_t *rt_key = (H5G_node_key_t *) _rt_key; - const char *s; - int ret_value=0; /* Return value */ + H5G_bt_ud1_t *udata = (H5G_bt_ud1_t *) _udata; + H5G_node_key_t *lt_key = (H5G_node_key_t *) _lt_key; + H5G_node_key_t *rt_key = (H5G_node_key_t *) _rt_key; + const char *s; + const char *base; /* Base of heap */ + int ret_value=0; /* Return value */ FUNC_ENTER_NOAPI(H5G_node_cmp3, FAIL); - /* left side */ - if (NULL == (s = H5HL_peek(f, udata->heap_addr, lt_key->offset))) + /* Get base address of heap */ + if (NULL == (base = H5HL_peek(f, udata->heap_addr, 0))) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read symbol name"); + + /* left side */ + s=base+lt_key->offset; if (HDstrcmp(udata->name, s) <= 0) HGOTO_DONE(-1); /* right side */ - if (NULL == (s = H5HL_peek(f, udata->heap_addr, rt_key->offset))) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read symbol name"); + s=base+rt_key->offset; if (HDstrcmp(udata->name, s) > 0) HGOTO_DONE(1); @@ -647,6 +650,7 @@ H5G_node_found(H5F_t *f, haddr_t addr, const void UNUSED *_lt_key, H5G_node_t *sn = NULL; int lt = 0, idx = 0, rt, cmp = 1; const char *s; + const char *base; /* Base of heap */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5G_node_found, FAIL); @@ -664,14 +668,17 @@ H5G_node_found(H5F_t *f, haddr_t addr, const void UNUSED *_lt_key, if (NULL == (sn = H5AC_protect(f, H5AC_SNODE, addr, NULL, NULL))) HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, FAIL, "unable to protect symbol table node"); + /* Get base address of heap */ + if (NULL == (base = H5HL_peek(f, bt_udata->heap_addr, 0))) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read symbol name"); + /* * Binary search. */ rt = sn->nsyms; while (lt < rt && cmp) { idx = (lt + rt) / 2; - if (NULL == (s = H5HL_peek(f, bt_udata->heap_addr, sn->entry[idx].name_off))) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read symbol name"); + s=base+sn->entry[idx].name_off; cmp = HDstrcmp(bt_udata->name, s); if (cmp < 0) { @@ -750,10 +757,11 @@ H5G_node_insert(H5F_t *f, haddr_t addr, void UNUSED *_lt_key, H5G_node_t *sn = NULL, *snrt = NULL; size_t offset; /*offset of name in heap */ const char *s; + const char *base; /* Base of heap */ int idx = -1, cmp = 1; int lt = 0, rt; /*binary search cntrs */ - H5B_ins_t ret_value = H5B_INS_ERROR; H5G_node_t *insert_into = NULL; /*node that gets new entry*/ + H5B_ins_t ret_value = H5B_INS_ERROR; FUNC_ENTER_NOAPI(H5G_node_insert, H5B_INS_ERROR); @@ -773,14 +781,17 @@ H5G_node_insert(H5F_t *f, haddr_t addr, void UNUSED *_lt_key, if (NULL == (sn = H5AC_protect(f, H5AC_SNODE, addr, NULL, NULL))) HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to protect symbol table node"); + /* Get base address of heap */ + if (NULL == (base = H5HL_peek(f, bt_udata->heap_addr, 0))) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5B_INS_ERROR, "unable to read symbol name"); + /* * Where does the new symbol get inserted? We use a binary search. */ rt = sn->nsyms; while (lt < rt) { idx = (lt + rt) / 2; - if (NULL == (s = H5HL_peek(f, bt_udata->heap_addr, sn->entry[idx].name_off))) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5B_INS_ERROR, "unable to read symbol name"); + s=base+sn->entry[idx].name_off; if (0 == (cmp = HDstrcmp(bt_udata->name, s))) /*already present */ HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, H5B_INS_ERROR, "symbol is already present in symbol table"); if (cmp < 0) { @@ -799,7 +810,7 @@ H5G_node_insert(H5F_t *f, haddr_t addr, void UNUSED *_lt_key, bt_udata->ent.name_off = offset; if (0==offset || (size_t)(-1)==offset) HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, H5B_INS_ERROR, "unable to insert symbol name into heap"); - if ((size_t)(sn->nsyms) >= 2*H5G_node_k(f)) { + if ((size_t)(sn->nsyms) >= 2*H5F_SYM_LEAF_K(f)) { /* * The node is full. Split it into a left and right * node and return the address of the new right node (the @@ -811,31 +822,31 @@ H5G_node_insert(H5F_t *f, haddr_t addr, void UNUSED *_lt_key, if (H5G_node_create(f, H5B_INS_FIRST, NULL, NULL, NULL, new_node_p/*out*/)<0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5B_INS_ERROR, "unable to split symbol table node"); - if (NULL==(snrt=H5AC_find(f, H5AC_SNODE, *new_node_p, NULL, NULL))) + if (NULL==(snrt=H5AC_find_f(f, H5AC_SNODE, *new_node_p, NULL, NULL))) HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to split symbol table node"); - HDmemcpy(snrt->entry, sn->entry + H5G_node_k(f), - H5G_node_k(f) * sizeof(H5G_entry_t)); - snrt->nsyms = H5G_node_k(f); + HDmemcpy(snrt->entry, sn->entry + H5F_SYM_LEAF_K(f), + H5F_SYM_LEAF_K(f) * sizeof(H5G_entry_t)); + snrt->nsyms = H5F_SYM_LEAF_K(f); snrt->dirty = TRUE; /* The left node */ - HDmemset(sn->entry + H5G_node_k(f), 0, - H5G_node_k(f) * sizeof(H5G_entry_t)); - sn->nsyms = H5G_node_k(f); + HDmemset(sn->entry + H5F_SYM_LEAF_K(f), 0, + H5F_SYM_LEAF_K(f) * sizeof(H5G_entry_t)); + sn->nsyms = H5F_SYM_LEAF_K(f); sn->dirty = TRUE; /* The middle key */ md_key->offset = sn->entry[sn->nsyms - 1].name_off; /* Where to insert the new entry? */ - if (idx <= (int)H5G_node_k(f)) { + if (idx <= (int)H5F_SYM_LEAF_K(f)) { insert_into = sn; - if (idx == (int)H5G_node_k(f)) + if (idx == (int)H5F_SYM_LEAF_K(f)) md_key->offset = offset; } else { - idx -= H5G_node_k(f); + idx -= H5F_SYM_LEAF_K(f); insert_into = snrt; - if (idx == (int)H5G_node_k (f)) { + if (idx == (int)H5F_SYM_LEAF_K (f)) { rt_key->offset = offset; *rt_key_changed = TRUE; } @@ -856,7 +867,7 @@ H5G_node_insert(H5F_t *f, haddr_t addr, void UNUSED *_lt_key, HDmemmove(insert_into->entry + idx + 1, insert_into->entry + idx, (insert_into->nsyms - idx) * sizeof(H5G_entry_t)); - H5G_ent_copy(&(insert_into->entry[idx]), &(bt_udata->ent),H5G_COPY_DEEP); + H5G_ent_copy(&(insert_into->entry[idx]), &(bt_udata->ent),H5G_COPY_NULL); insert_into->entry[idx].dirty = TRUE; insert_into->nsyms += 1; @@ -905,9 +916,10 @@ H5G_node_remove(H5F_t *f, haddr_t addr, void *_lt_key/*in,out*/, H5G_node_key_t *rt_key = (H5G_node_key_t*)_rt_key; H5G_bt_ud1_t *bt_udata = (H5G_bt_ud1_t*)_udata; H5G_node_t *sn = NULL; - H5B_ins_t ret_value = H5B_INS_ERROR; int lt=0, rt, idx=0, cmp=1; const char *s = NULL; + const char *base; /* Base of heap */ + H5B_ins_t ret_value = H5B_INS_ERROR; FUNC_ENTER_NOAPI(H5G_node_remove, H5B_INS_ERROR); @@ -922,13 +934,15 @@ H5G_node_remove(H5F_t *f, haddr_t addr, void *_lt_key/*in,out*/, if (NULL==(sn=H5AC_protect(f, H5AC_SNODE, addr, NULL, NULL))) HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to protect symbol table node"); + /* Get base address of heap */ + if (NULL == (base = H5HL_peek(f, bt_udata->heap_addr, 0))) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5B_INS_ERROR, "unable to read symbol name"); + /* Find the name with a binary search */ rt = sn->nsyms; while (ltheap_addr, - sn->entry[idx].name_off))) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5B_INS_ERROR, "unable to read symbol name"); + s=base+sn->entry[idx].name_off; cmp = HDstrcmp(bt_udata->name, s); if (cmp<0) { rt = idx; @@ -941,8 +955,7 @@ H5G_node_remove(H5F_t *f, haddr_t addr, void *_lt_key/*in,out*/, if (H5G_CACHED_SLINK==sn->entry[idx].type) { /* Remove the symbolic link value */ - if ((s=H5HL_peek(f, bt_udata->heap_addr, - sn->entry[idx].cache.slink.lval_offset))) + if ((s=H5HL_peek(f, bt_udata->heap_addr, sn->entry[idx].cache.slink.lval_offset))) H5HL_remove(f, bt_udata->heap_addr, sn->entry[idx].cache.slink.lval_offset, HDstrlen(s)+1); H5E_clear(); /*no big deal*/ } else { @@ -957,9 +970,6 @@ H5G_node_remove(H5F_t *f, haddr_t addr, void *_lt_key/*in,out*/, H5HL_remove(f, bt_udata->heap_addr, sn->entry[idx].name_off, HDstrlen(s)+1); H5E_clear(); /*no big deal*/ - /* Free the ID to name buffer for the entry being squeezed out */ - H5G_free_ent_name(sn->entry+idx); - /* Remove the entry from the symbol table node */ if (1==sn->nsyms) { /* @@ -1070,7 +1080,7 @@ H5G_node_iterate (H5F_t *f, void UNUSED *_lt_key, haddr_t addr, * Save information about the symbol table node since we can't lock it * because we're about to call an application function. */ - if (NULL == (sn = H5AC_find(f, H5AC_SNODE, addr, NULL, NULL))) + if (NULL == (sn = H5AC_find_f(f, H5AC_SNODE, addr, NULL, NULL))) HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_ITER_ERROR, "unable to load symbol table node"); nsyms = sn->nsyms; if (NULL==(name_off = H5MM_malloc (nsyms*sizeof(name_off[0])))) @@ -1082,12 +1092,11 @@ H5G_node_iterate (H5F_t *f, void UNUSED *_lt_key, haddr_t addr, /* * Iterate over the symbol table node entries. */ - for (i=0, ret_value=0; iskip>0) { --bt_udata->skip; } else { - name = H5HL_peek (f, bt_udata->group->ent.cache.stab.heap_addr, - name_off[i]); + name = H5HL_peek (f, bt_udata->group->ent.cache.stab.heap_addr, name_off[i]); assert (name); n = HDstrlen (name); if (n+1>sizeof(buf)) { @@ -1149,7 +1158,7 @@ H5G_node_sumup(H5F_t *f, void UNUSED *_lt_key, haddr_t addr, assert(num_objs); /* Find the object node and add the number of symbol entries. */ - if (NULL == (sn = H5AC_find(f, H5AC_SNODE, addr, NULL, NULL))) + if (NULL == (sn = H5AC_find_f(f, H5AC_SNODE, addr, NULL, NULL))) HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_ITER_ERROR, "unable to load symbol table node"); *num_objs += sn->nsyms; @@ -1195,14 +1204,14 @@ H5G_node_name(H5F_t *f, void UNUSED *_lt_key, haddr_t addr, assert(bt_udata); - if (NULL == (sn = H5AC_find(f, H5AC_SNODE, addr, NULL, NULL))) + if (NULL == (sn = H5AC_find_f(f, H5AC_SNODE, addr, NULL, NULL))) HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_ITER_ERROR, "unable to load symbol table node"); /* Find the node, locate the object symbol table entry and retrieve the name */ if(bt_udata->idx >= bt_udata->num_objs && bt_udata->idx < (bt_udata->num_objs+sn->nsyms)) { loc_idx = bt_udata->idx - bt_udata->num_objs; name_off = sn->entry[loc_idx].name_off; - name = (const char*)H5HL_peek (f, bt_udata->group->ent.cache.stab.heap_addr, name_off); + name = H5HL_peek (f, bt_udata->group->ent.cache.stab.heap_addr, name_off); assert (name); bt_udata->name = H5MM_strdup (name); HGOTO_DONE(H5B_ITER_STOP); @@ -1247,7 +1256,7 @@ H5G_node_type(H5F_t *f, void UNUSED *_lt_key, haddr_t addr, assert(bt_udata); /* Find the node, locate the object symbol table entry and retrieve the type */ - if (NULL == (sn = H5AC_find(f, H5AC_SNODE, addr, NULL, NULL))) + if (NULL == (sn = H5AC_find_f(f, H5AC_SNODE, addr, NULL, NULL))) HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_ITER_ERROR, "unable to load symbol table node"); if(bt_udata->idx >= bt_udata->num_objs && bt_udata->idx < (bt_udata->num_objs+sn->nsyms)) { @@ -1318,7 +1327,7 @@ H5G_node_debug(H5F_t *f, haddr_t addr, FILE * stream, int indent, "Size of Node (in bytes):", (unsigned)H5G_node_size(f)); fprintf(stream, "%*s%-*s %d of %d\n", indent, "", fwidth, "Number of Symbols:", - sn->nsyms, 2 * H5G_node_k(f)); + sn->nsyms, 2 * H5F_SYM_LEAF_K(f)); indent += 3; fwidth = MAX(0, fwidth - 3); @@ -1339,46 +1348,3 @@ done: FUNC_LEAVE(ret_value); } - -/*------------------------------------------------------------------------- - * Function: H5G_node_k - * - * Purpose: Replaced a macro to retrieve the symbol table leaf size, - * now that the generic properties are being used to store - * the values. - * - * Return: Success: Non-negative, and the symbol table leaf size is - * returned. - * - * Failure: Negative (should not happen) - * - * Programmer: Raymond Lu - * slu@ncsa.uiuc.edu - * Oct 14 2001 - * - * Modifications: - * Quincey Koziol, 2001-10-15 - * Added this header and removed unused ret_value variable. - *------------------------------------------------------------------------- - */ -unsigned H5G_node_k(const H5F_t *f) -{ - unsigned sym_leaf_k; - H5P_genplist_t *plist; /* Property list pointer */ - unsigned ret_value; /* Return value */ - - FUNC_ENTER_NOAPI(H5G_node_k, UFAIL); - - assert(f); - - if(NULL == (plist = H5I_object(f->shared->fcpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, UFAIL, "not a file access property list"); - if(H5P_get(plist, H5F_CRT_SYM_LEAF_NAME, &sym_leaf_k) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, UFAIL, "can't get rank for symbol table leaf node"); - - /* Set return value */ - ret_value=sym_leaf_k; - -done: - FUNC_LEAVE(ret_value); -} diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h index 3fc8bd3..b058ea3 100644 --- a/src/H5Gpkg.h +++ b/src/H5Gpkg.h @@ -151,7 +151,6 @@ H5_DLL herr_t H5G_ent_encode_vec(H5F_t *f, uint8_t **pp, const H5G_entry_t *ent, int n); /* Functions that understand symbol table nodes */ -H5_DLL unsigned H5G_node_k(const H5F_t *f); H5_DLL H5B_iterate_t H5G_node_iterate (H5F_t *f, void UNUSED *_lt_key, haddr_t addr, void UNUSED *_rt_key, void *_udata); H5_DLL H5B_iterate_t H5G_node_sumup(H5F_t *f, void UNUSED *_lt_key, haddr_t addr, diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h index 8515b2d..be360cb 100644 --- a/src/H5Gprivate.h +++ b/src/H5Gprivate.h @@ -26,6 +26,7 @@ #include "H5private.h" #include "H5Bprivate.h" #include "H5Fprivate.h" +#include "H5RSprivate.h" /* Reference-counted strings */ /* * Define this to enable debugging. @@ -95,8 +96,13 @@ typedef struct H5G_entry_t { H5G_type_t type; /*type of information cached */ H5G_cache_t cache; /*cached data from object header */ H5F_t *file; /*file to which this obj hdr belongs */ +#ifdef OLD_WAY char *user_path; /* Path to object, as opened by user */ char *canon_path; /* Path to object, as found in file */ +#else /* OLD_WAY */ + H5RS_str_t *user_path_r; /* Path to object, as opened by user */ + H5RS_str_t *canon_path_r; /* Path to object, as found in file */ +#endif /* OLD_WAY */ unsigned user_path_hidden; /* Whether the user's path is valid */ } H5G_entry_t; @@ -123,6 +129,7 @@ typedef enum { /* Depth of group entry copy */ typedef enum { + H5G_COPY_NULL, /* Null destination names */ H5G_COPY_LIMITED, /* Limited copy from source to destination, omitting name & old name fields */ H5G_COPY_SHALLOW, /* Copy from source to destination, including name & old name fields */ H5G_COPY_DEEP /* Deep copy from source to destination, including duplicating name & old name fields */ @@ -174,8 +181,8 @@ H5_DLL herr_t H5G_ent_encode(H5F_t *f, uint8_t **pp, const H5G_entry_t *ent); H5_DLL herr_t H5G_ent_decode(H5F_t *f, const uint8_t **pp, H5G_entry_t *ent/*out*/); H5_DLL herr_t H5G_replace_name(int type, H5G_entry_t *loc, - const char *src_name, H5G_entry_t *src_loc, - const char *dst_name, H5G_entry_t *dst_loc, H5G_names_op_t op); + H5RS_str_t *src_name, H5G_entry_t *src_loc, + H5RS_str_t *dst_name, H5G_entry_t *dst_loc, H5G_names_op_t op); H5_DLL herr_t H5G_ent_copy(H5G_entry_t *dst, const H5G_entry_t *src, H5G_ent_copy_depth_t depth); H5_DLL herr_t H5G_free_grp_name(H5G_t *grp); diff --git a/src/H5Gstab.c b/src/H5Gstab.c index 12d0ccb..e5e2535 100644 --- a/src/H5Gstab.c +++ b/src/H5Gstab.c @@ -12,6 +12,7 @@ #include "H5private.h" #include "H5Eprivate.h" #include "H5Fpkg.h" /*file access */ +#include "H5FLprivate.h" /*Free Lists */ #include "H5Gpkg.h" #include "H5HLprivate.h" #include "H5MMprivate.h" @@ -21,6 +22,9 @@ static int interface_initialize_g = 0; #define INTERFACE_INIT NULL +/* Declare extern the PQ free list for the wrapped strings */ +H5FL_BLK_EXTERN(str_buf); + /* Private prototypes */ static herr_t H5G_insert_name(H5G_entry_t *loc, H5G_entry_t *obj, const char *name); @@ -95,7 +99,7 @@ H5G_stab_create(H5F_t *f, size_t init, H5G_entry_t *self/*out*/) * Insert the symbol table message into the object header and the symbol * table entry. */ - if (H5O_modify(self, H5O_STAB, H5O_NEW_MESG, H5O_FLAG_CONSTANT, &stab)<0) { + if (H5O_modify(self, H5O_STAB, H5O_NEW_MESG, H5O_FLAG_CONSTANT, 1, &stab)<0) { H5O_close(self); HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create message"); } @@ -160,8 +164,8 @@ H5G_stab_find(H5G_entry_t *grp_ent, const char *name, /* change OBJ_ENT only if found */ else { if (obj_ent) { - /* do a deep copy */ - if (H5G_ent_copy(obj_ent, &(udata.ent),H5G_COPY_DEEP)<0) + /* do a NULL copy, since the obj_ent name will be constructed in H5G_insert_name() */ + if (H5G_ent_copy(obj_ent, &(udata.ent),H5G_COPY_NULL)<0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to copy entry"); /* insert the name into the symbol entry OBJ_ENT */ @@ -224,7 +228,7 @@ H5G_stab_insert(H5G_entry_t *grp_ent, const char *name, H5G_entry_t *obj_ent) udata.operation = H5G_OPER_INSERT; udata.name = name; udata.heap_addr = stab.heap_addr; - H5G_ent_copy(&(udata.ent),obj_ent,H5G_COPY_SHALLOW); /* Shallow copy here, deep copy happens in H5G_node_insert() callback() */ + H5G_ent_copy(&(udata.ent),obj_ent,H5G_COPY_NULL); /* NULL copy here, no copies happens in H5G_node_insert() callback() */ /* insert */ if (H5B_insert(grp_ent->file, H5B_SNODE, stab.btree_addr, split_ratios, &udata) < 0) @@ -301,6 +305,8 @@ done: static herr_t H5G_insert_name(H5G_entry_t *loc, H5G_entry_t *obj, const char *name) { + char *new_user_path; /* Pointer to new user path */ + char *new_canon_path; /* Pointer to new canonical path */ size_t name_len; /* Length of name to append */ size_t user_path_len; /* Length of location's user path name */ size_t canon_path_len; /* Length of location's canonical path name */ @@ -313,55 +319,79 @@ H5G_insert_name(H5G_entry_t *loc, H5G_entry_t *obj, const char *name) assert(name); /* Only attempt to build a new name if the location's name exists */ - if(loc->canon_path) { + if(loc->canon_path_r) { + const char *loc_user_path; /* Pointer to raw string for user path */ + const char *loc_canon_path; /* Pointer to raw string for canonical path */ /* Reset the object's previous names, if they exist */ - H5MM_xfree(obj->user_path); - H5MM_xfree(obj->canon_path); + if(obj->user_path_r) { + H5RS_decr(obj->user_path_r); + obj->user_path_r=NULL; + } /* end if */ + if(obj->canon_path_r) { + H5RS_decr(obj->canon_path_r); + obj->canon_path_r=NULL; + } /* end if */ obj->user_path_hidden=0; /* Get the length of the strings involved */ - user_path_len = HDstrlen(loc->user_path); - canon_path_len = HDstrlen(loc->canon_path); + user_path_len = H5RS_len(loc->user_path_r); + canon_path_len = H5RS_len(loc->canon_path_r); name_len = HDstrlen(name); /* Modify the object's user path */ + /* Get the raw string for the user path */ + loc_user_path=H5RS_GET_STR(loc->user_path_r); + assert(loc_user_path); + /* The location's user path already ends in a '/' separator */ - if ('/'==loc->user_path[user_path_len-1]) { - if (NULL==(obj->user_path = H5MM_malloc (user_path_len+name_len+1))) + if ('/'==loc_user_path[user_path_len-1]) { + if (NULL==(new_user_path = H5FL_BLK_MALLOC(str_buf,user_path_len+name_len+1))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - HDstrcpy(obj->user_path, loc->user_path); + HDstrcpy(new_user_path, loc_user_path); } /* end if */ /* The location's user path needs a separator */ else { - if (NULL==(obj->user_path = H5MM_malloc (user_path_len+1+name_len+1))) + if (NULL==(new_user_path = H5FL_BLK_MALLOC(str_buf,user_path_len+1+name_len+1))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - HDstrcpy(obj->user_path, loc->user_path); - HDstrcat(obj->user_path, "/"); + HDstrcpy(new_user_path, loc_user_path); + HDstrcat(new_user_path, "/"); } /* end else */ /* Append the component's name */ - HDstrcat(obj->user_path, name); + HDstrcat(new_user_path, name); + + /* Give ownership of the user path to the entry */ + obj->user_path_r=H5RS_own(new_user_path); + assert(obj->user_path_r); /* Modify the object's canonical path */ + /* Get the raw string for the canonical path */ + loc_canon_path=H5RS_GET_STR(loc->canon_path_r); + assert(loc_canon_path); + /* The location's canonical path already ends in a '/' separator */ - if ('/'==loc->canon_path[canon_path_len-1]) { - if (NULL==(obj->canon_path = H5MM_malloc (canon_path_len+name_len+1))) + if ('/'==loc_canon_path[canon_path_len-1]) { + if (NULL==(new_canon_path = H5FL_BLK_MALLOC(str_buf,canon_path_len+name_len+1))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - HDstrcpy(obj->canon_path, loc->canon_path); + HDstrcpy(new_canon_path, loc_canon_path); } /* end if */ /* The location's canonical path needs a separator */ else { - if (NULL==(obj->canon_path = H5MM_malloc (canon_path_len+1+name_len+1))) + if (NULL==(new_canon_path = H5FL_BLK_MALLOC(str_buf,canon_path_len+1+name_len+1))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - HDstrcpy(obj->canon_path, loc->canon_path); - HDstrcat(obj->canon_path, "/"); + HDstrcpy(new_canon_path, loc_canon_path); + HDstrcat(new_canon_path, "/"); } /* end else */ /* Append the component's name */ - HDstrcat(obj->canon_path, name); + HDstrcat(new_canon_path, name); + + /* Give ownership of the canonical path to the entry */ + obj->canon_path_r=H5RS_own(new_canon_path); + assert(obj->canon_path_r); } /* end if */ done: diff --git a/src/H5HG.c b/src/H5HG.c index bc4a6de..27a5f6d 100644 --- a/src/H5HG.c +++ b/src/H5HG.c @@ -127,19 +127,19 @@ H5HG_create (H5F_t *f, size_t size) HGOTO_ERROR (H5E_HEAP, H5E_CANTINIT, NULL, "unable to allocate file space for global heap"); } - if (NULL==(heap = H5FL_ALLOC (H5HG_heap_t,1))) { + if (NULL==(heap = H5FL_CALLOC (H5HG_heap_t))) { HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); } heap->addr = addr; heap->size = size; heap->dirty = TRUE; - if (NULL==(heap->chunk = H5FL_BLK_ALLOC (heap_chunk,size,0))) { + if (NULL==(heap->chunk = H5FL_BLK_MALLOC (heap_chunk,size))) { HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); } heap->nalloc = H5HG_NOBJS (f, size); - if (NULL==(heap->obj = H5FL_ARR_ALLOC (H5HG_obj_t,heap->nalloc,1))) { + if (NULL==(heap->obj = H5FL_ARR_CALLOC (H5HG_obj_t,heap->nalloc))) { HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); } @@ -246,12 +246,12 @@ H5HG_load (H5F_t *f, hid_t dxpl_id, haddr_t addr, const void * UNUSED udata1, assert (!udata2); /* Read the initial 4k page */ - if (NULL==(heap = H5FL_ALLOC (H5HG_heap_t,1))) { + if (NULL==(heap = H5FL_CALLOC (H5HG_heap_t))) { HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); } heap->addr = addr; - if (NULL==(heap->chunk = H5FL_BLK_ALLOC (heap_chunk,H5HG_MINSIZE,0))) { + if (NULL==(heap->chunk = H5FL_BLK_MALLOC (heap_chunk,H5HG_MINSIZE))) { HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); } @@ -301,7 +301,7 @@ H5HG_load (H5F_t *f, hid_t dxpl_id, haddr_t addr, const void * UNUSED udata1, /* Decode each object */ p = heap->chunk + H5HG_SIZEOF_HDR (f); nalloc = H5HG_NOBJS (f, heap->size); - if (NULL==(heap->obj = H5FL_ARR_ALLOC (H5HG_obj_t,nalloc,1))) { + if (NULL==(heap->obj = H5FL_ARR_CALLOC (H5HG_obj_t,nalloc))) { HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); } @@ -671,7 +671,7 @@ H5HG_peek (H5F_t *f, H5HG_t *hobj) assert (hobj); /* Load the heap and return a pointer to the object */ - if (NULL==(heap=H5AC_find (f, H5AC_GHEAP, hobj->addr, NULL, NULL))) + if (NULL==(heap=H5AC_find_f (f, H5AC_GHEAP, hobj->addr, NULL, NULL))) HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL, "unable to load heap"); assert (hobj->idx>0 && hobj->idxnalloc); ret_value = heap->obj[hobj->idx].begin + H5HG_SIZEOF_OBJHDR (f); @@ -679,7 +679,7 @@ H5HG_peek (H5F_t *f, H5HG_t *hobj) /* * Advance the heap in the CWFS list. We might have done this already - * with the H5AC_find(), but it won't hurt to do it twice. + * with the H5AC_find_f(), but it won't hurt to do it twice. */ if (heap->obj[0].begin) { for (i=0; ishared->ncwfs; i++) { @@ -733,7 +733,7 @@ H5HG_read (H5F_t *f, H5HG_t *hobj, void *object/*out*/) assert (hobj); /* Load the heap */ - if (NULL==(heap=H5AC_find (f, H5AC_GHEAP, hobj->addr, NULL, NULL))) + if (NULL==(heap=H5AC_find_f (f, H5AC_GHEAP, hobj->addr, NULL, NULL))) HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL, "unable to load heap"); assert (hobj->idx>0 && hobj->idxnalloc); assert (heap->obj[hobj->idx].begin); @@ -745,7 +745,7 @@ H5HG_read (H5F_t *f, H5HG_t *hobj, void *object/*out*/) /* * Advance the heap in the CWFS list. We might have done this already - * with the H5AC_find(), but it won't hurt to do it twice. + * with the H5AC_find_f(), but it won't hurt to do it twice. */ if (heap->obj[0].begin) { for (i=0; ishared->ncwfs; i++) { @@ -802,7 +802,7 @@ H5HG_link (H5F_t *f, H5HG_t *hobj, int adjust) HGOTO_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))) + if (NULL==(heap=H5AC_find_f (f, H5AC_GHEAP, hobj->addr, NULL, NULL))) HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap"); assert (hobj->idx>0 && hobj->idxnalloc); assert (heap->obj[hobj->idx].begin); @@ -855,7 +855,7 @@ H5HG_remove (H5F_t *f, H5HG_t *hobj) HGOTO_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))) + if (NULL==(heap=H5AC_find_f (f, H5AC_GHEAP, hobj->addr, NULL, NULL))) HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap"); assert (hobj->idx>0 && hobj->idxnalloc); assert (heap->obj[hobj->idx].begin); @@ -899,7 +899,7 @@ H5HG_remove (H5F_t *f, H5HG_t *hobj) } else { /* * If the heap is in the CWFS list then advance it one position. The - * H5AC_find() might have done that too, but that's okay. If the + * H5AC_find_f() might have done that too, but that's okay. If the * heap isn't on the CWFS list then add it to the end. */ for (i=0; ishared->ncwfs; i++) { @@ -959,7 +959,7 @@ H5HG_debug(H5F_t *f, haddr_t addr, FILE *stream, int indent, assert(indent >= 0); assert(fwidth >= 0); - if (NULL == (h = H5AC_find(f, H5AC_GHEAP, addr, NULL, NULL))) + if (NULL == (h = H5AC_find_f(f, H5AC_GHEAP, addr, NULL, NULL))) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load global heap collection"); fprintf(stream, "%*sGlobal Heap Collection...\n", indent, ""); fprintf(stream, "%*s%-*s %d\n", indent, "", fwidth, diff --git a/src/H5HL.c b/src/H5HL.c index d9e5d9c..e4b117c 100644 --- a/src/H5HL.c +++ b/src/H5HL.c @@ -111,6 +111,7 @@ H5HL_create(H5F_t *f, size_t size_hint, haddr_t *addr_p/*out*/) { H5HL_t *heap = NULL; hsize_t total_size; /*total heap size on disk */ + size_t sizeof_hdr; /* Cache H5HL header size for file */ herr_t ret_value = FAIL; FUNC_ENTER_NOAPI(H5HL_create, FAIL); @@ -124,29 +125,32 @@ H5HL_create(H5F_t *f, size_t size_hint, haddr_t *addr_p/*out*/) } size_hint = H5HL_ALIGN(size_hint); + /* Cache this for later */ + sizeof_hdr= H5HL_SIZEOF_HDR(f); + /* allocate file version */ - total_size = H5HL_SIZEOF_HDR(f) + size_hint; + total_size = sizeof_hdr + size_hint; if (HADDR_UNDEF==(*addr_p=H5MF_alloc(f, H5FD_MEM_LHEAP, total_size))) { HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate file memory"); } /* allocate memory version */ - if (NULL==(heap = H5FL_ALLOC(H5HL_t,1))) { + if (NULL==(heap = H5FL_CALLOC(H5HL_t))) { HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); } - heap->addr = *addr_p + (hsize_t)H5HL_SIZEOF_HDR(f); + heap->addr = *addr_p + (hsize_t)sizeof_hdr; heap->disk_alloc = size_hint; heap->mem_alloc = size_hint; - if (NULL==(heap->chunk = H5FL_BLK_ALLOC(heap_chunk,(H5HL_SIZEOF_HDR(f) + size_hint),1))) { + if (NULL==(heap->chunk = H5FL_BLK_CALLOC(heap_chunk,(sizeof_hdr + size_hint)))) { HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); } /* free list */ if (size_hint) { - if (NULL==(heap->freelist = H5FL_ALLOC(H5HL_free_t,0))) { + if (NULL==(heap->freelist = H5FL_MALLOC(H5HL_free_t))) { HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); } @@ -206,6 +210,7 @@ H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void * UNUSED udata1, void * UNUSED udata2) { uint8_t hdr[52]; + size_t sizeof_hdr; /* Cache H5HL header size for file */ const uint8_t *p = NULL; H5HL_t *heap = NULL; H5HL_free_t *fl = NULL, *tail = NULL; @@ -214,17 +219,20 @@ H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void * UNUSED udata1, FUNC_ENTER_NOAPI(H5HL_load, NULL); + /* Cache this for later */ + sizeof_hdr= H5HL_SIZEOF_HDR(f); + /* check arguments */ assert(f); assert(H5F_addr_defined(addr)); - assert(H5HL_SIZEOF_HDR(f) <= sizeof hdr); + assert(sizeof_hdr <= sizeof(hdr)); assert(!udata1); assert(!udata2); - if (H5F_block_read(f, H5FD_MEM_LHEAP, addr, H5HL_SIZEOF_HDR(f), dxpl_id, hdr) < 0) + if (H5F_block_read(f, H5FD_MEM_LHEAP, addr, sizeof_hdr, dxpl_id, hdr) < 0) HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read heap header"); p = hdr; - if (NULL==(heap = H5FL_ALLOC(H5HL_t,1))) + if (NULL==(heap = H5FL_CALLOC(H5HL_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); /* magic number */ @@ -246,19 +254,19 @@ H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void * UNUSED udata1, /* data */ H5F_addr_decode(f, &p, &(heap->addr)); - heap->chunk = H5FL_BLK_ALLOC(heap_chunk,(H5HL_SIZEOF_HDR(f) + heap->mem_alloc),1); + heap->chunk = H5FL_BLK_CALLOC(heap_chunk,(sizeof_hdr + heap->mem_alloc)); if (NULL==heap->chunk) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); if (heap->disk_alloc && H5F_block_read(f, H5FD_MEM_LHEAP, heap->addr, heap->disk_alloc, - dxpl_id, heap->chunk + H5HL_SIZEOF_HDR(f)) < 0) + dxpl_id, heap->chunk + sizeof_hdr) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to read heap data"); /* free list */ while (H5HL_FREE_NULL != free_block) { if (free_block >= heap->disk_alloc) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list"); - if (NULL==(fl = H5FL_ALLOC(H5HL_free_t,0))) + if (NULL==(fl = H5FL_MALLOC(H5HL_free_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); fl->offset = free_block; fl->prev = tail; @@ -267,7 +275,7 @@ H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void * UNUSED udata1, tail = fl; if (!heap->freelist) heap->freelist = fl; - p = heap->chunk + H5HL_SIZEOF_HDR(f) + free_block; + p = heap->chunk + sizeof_hdr + free_block; H5F_DECODE_LENGTH(f, p, free_block); H5F_DECODE_LENGTH(f, p, fl->size); @@ -323,6 +331,7 @@ H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HL_t *heap) uint8_t *p = heap->chunk; H5HL_free_t *fl = heap->freelist; haddr_t hdr_end_addr; + size_t sizeof_hdr; /* Cache H5HL header size for file */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5HL_flush, FAIL); @@ -333,6 +342,9 @@ H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HL_t *heap) assert(heap); if (heap->dirty) { + /* Cache this for later */ + sizeof_hdr= H5HL_SIZEOF_HDR(f); + /* * If the heap grew larger than disk storage then move the * data segment of the heap to a larger contiguous block of @@ -367,7 +379,7 @@ H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HL_t *heap) */ while (fl) { assert (fl->offset == H5HL_ALIGN (fl->offset)); - p = heap->chunk + H5HL_SIZEOF_HDR(f) + fl->offset; + p = heap->chunk + sizeof_hdr + fl->offset; if (fl->next) { H5F_ENCODE_LENGTH(f, p, fl->next->offset); } else { @@ -380,19 +392,19 @@ H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HL_t *heap) /* * Copy buffer to disk. */ - hdr_end_addr = addr + (hsize_t)H5HL_SIZEOF_HDR(f); + hdr_end_addr = addr + (hsize_t)sizeof_hdr; if (H5F_addr_eq(heap->addr, hdr_end_addr)) { /* The header and data are contiguous */ if (H5F_block_write(f, H5FD_MEM_LHEAP, addr, - (H5HL_SIZEOF_HDR(f)+heap->disk_alloc), + (sizeof_hdr+heap->disk_alloc), dxpl_id, heap->chunk) < 0) HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header and data to file"); } else { - if (H5F_block_write(f, H5FD_MEM_LHEAP, addr, H5HL_SIZEOF_HDR(f), + if (H5F_block_write(f, H5FD_MEM_LHEAP, addr, sizeof_hdr, dxpl_id, heap->chunk)<0) HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header to file"); if (H5F_block_write(f, H5FD_MEM_LHEAP, heap->addr, heap->disk_alloc, - dxpl_id, heap->chunk + H5HL_SIZEOF_HDR(f)) < 0) + dxpl_id, heap->chunk + sizeof_hdr) < 0) HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap data to file"); } @@ -456,7 +468,7 @@ H5HL_read(H5F_t *f, haddr_t addr, size_t offset, size_t size, void *buf) assert(f); assert (H5F_addr_defined(addr)); - if (NULL == (heap = H5AC_find(f, H5AC_LHEAP, addr, NULL, NULL))) + if (NULL == (heap = H5AC_find_f(f, H5AC_LHEAP, addr, NULL, NULL))) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to load heap"); assert(offset < heap->mem_alloc); assert(offset + size <= heap->mem_alloc); @@ -507,8 +519,8 @@ done: const void * H5HL_peek(H5F_t *f, haddr_t addr, size_t offset) { - H5HL_t *heap = NULL; - const void *ret_value = NULL; + H5HL_t *heap; + const void *ret_value; FUNC_ENTER_NOAPI(H5HL_peek, NULL); @@ -516,7 +528,7 @@ H5HL_peek(H5F_t *f, haddr_t addr, size_t offset) assert(f); assert(H5F_addr_defined(addr)); - if (NULL == (heap = H5AC_find(f, H5AC_LHEAP, addr, NULL, NULL))) + if (NULL == (heap = H5AC_find_f(f, H5AC_LHEAP, addr, NULL, NULL))) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to load heap"); assert(offset < heap->mem_alloc); @@ -584,6 +596,7 @@ H5HL_insert(H5F_t *f, haddr_t addr, size_t buf_size, const void *buf) size_t offset = 0; size_t need_size, old_size, need_more; hbool_t found; + size_t sizeof_hdr; /* Cache H5HL header size for file */ size_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5HL_insert, (size_t)(-1)); @@ -596,10 +609,13 @@ H5HL_insert(H5F_t *f, haddr_t addr, size_t buf_size, const void *buf) if (0==(f->intent & H5F_ACC_RDWR)) HGOTO_ERROR (H5E_HEAP, H5E_WRITEERROR, (size_t)(-1), "no write intent on file"); - if (NULL == (heap = H5AC_find(f, H5AC_LHEAP, addr, NULL, NULL))) + if (NULL == (heap = H5AC_find_f(f, H5AC_LHEAP, addr, NULL, NULL))) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, (size_t)(-1), "unable to load heap"); heap->dirty += 1; + /* Cache this for later */ + sizeof_hdr= H5HL_SIZEOF_HDR(f); + /* * In order to keep the free list descriptors aligned on word boundaries, * whatever that might mean, we round the size up to the next multiple of @@ -669,7 +685,7 @@ H5HL_insert(H5F_t *f, haddr_t addr, size_t buf_size, const void *buf) */ offset = heap->mem_alloc; if (need_more - need_size >= H5HL_SIZEOF_FREE(f)) { - if (NULL==(fl = H5FL_ALLOC(H5HL_free_t,0))) + if (NULL==(fl = H5FL_MALLOC(H5HL_free_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "memory allocation failed"); fl->offset = heap->mem_alloc + need_size; fl->size = need_more - need_size; @@ -699,17 +715,17 @@ H5HL_insert(H5F_t *f, haddr_t addr, size_t buf_size, const void *buf) old_size = heap->mem_alloc; heap->mem_alloc += need_more; heap->chunk = H5FL_BLK_REALLOC(heap_chunk,heap->chunk, - (H5HL_SIZEOF_HDR(f) + heap->mem_alloc)); + (sizeof_hdr + heap->mem_alloc)); if (NULL==heap->chunk) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "memory allocation failed"); /* clear new section so junk doesn't appear in the file */ - HDmemset(heap->chunk + H5HL_SIZEOF_HDR(f) + old_size, 0, need_more); + HDmemset(heap->chunk + sizeof_hdr + old_size, 0, need_more); } /* * Copy the data into the heap */ - HDmemcpy(heap->chunk + H5HL_SIZEOF_HDR(f) + offset, buf, buf_size); + HDmemcpy(heap->chunk + sizeof_hdr + offset, buf, buf_size); /* Set return value */ ret_value=offset; @@ -757,7 +773,7 @@ H5HL_write(H5F_t *f, haddr_t addr, size_t offset, size_t size, const void *buf) if (0==(f->intent & H5F_ACC_RDWR)) HGOTO_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file"); - if (NULL == (heap = H5AC_find(f, H5AC_LHEAP, addr, NULL, NULL))) + if (NULL == (heap = H5AC_find_f(f, H5AC_LHEAP, addr, NULL, NULL))) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap"); assert(offset < heap->mem_alloc); assert(offset + size <= heap->mem_alloc); @@ -815,7 +831,7 @@ H5HL_remove(H5F_t *f, haddr_t addr, size_t offset, size_t size) HGOTO_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))) + if (NULL == (heap = H5AC_find_f(f, H5AC_LHEAP, addr, NULL, NULL))) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap"); assert(offset < heap->mem_alloc); assert(offset + size <= heap->mem_alloc); @@ -883,7 +899,7 @@ H5HL_remove(H5F_t *f, haddr_t addr, size_t offset, size_t size) /* * Add an entry to the free list. */ - if (NULL==(fl = H5FL_ALLOC(H5HL_free_t,0))) + if (NULL==(fl = H5FL_MALLOC(H5HL_free_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); fl->offset = offset; fl->size = size; @@ -936,7 +952,7 @@ H5HL_debug(H5F_t *f, haddr_t addr, FILE * stream, int indent, int fwidth) assert(indent >= 0); assert(fwidth >= 0); - if (NULL == (h = H5AC_find(f, H5AC_LHEAP, addr, NULL, NULL))) + if (NULL == (h = H5AC_find_f(f, H5AC_LHEAP, addr, NULL, NULL))) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap"); fprintf(stream, "%*sLocal Heap...\n", indent, ""); fprintf(stream, "%*s%-*s %d\n", indent, "", fwidth, diff --git a/src/H5I.c b/src/H5I.c index b2a0eac..fa92bf9 100644 --- a/src/H5I.c +++ b/src/H5I.c @@ -359,8 +359,10 @@ H5I_clear_group(H5I_type_t grp, hbool_t force) * Do nothing to the object if the reference count is larger than * one and forcing is off. */ - if (!force && cur->count>1) + if (!force && cur->count>1) { + next=cur->next; continue; + } /* end if */ /* Check for a 'free' function and call it, if it exists */ if (grp_ptr->free_func && (grp_ptr->free_func)(cur->obj_ptr)<0) { @@ -540,7 +542,7 @@ H5I_register(H5I_type_t grp, void *object) grp_ptr = H5I_id_group_list_g[grp]; if (grp_ptr == NULL || grp_ptr->count <= 0) HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid group"); - if ((id_ptr = H5FL_ALLOC(H5I_id_info_t,0)) == NULL) + if ((id_ptr = H5FL_MALLOC(H5I_id_info_t)) == NULL) HGOTO_ERROR(H5E_ATOM, H5E_NOSPACE, FAIL, "memory allocation failed"); /* Create the struct & it's ID */ @@ -1156,11 +1158,11 @@ H5Iget_name(hid_t id, char *name/*out*/, size_t size) /* get symbol table entry */ if(NULL!=(ent = H5G_loc(id))) { - if (ent->user_path != NULL && ent->user_path_hidden==0) { - len = HDstrlen(ent->user_path); + if (ent->user_path_r != NULL && ent->user_path_hidden==0) { + len = H5RS_len(ent->user_path_r); if(name) { - HDstrncpy(name, ent->user_path, MIN(len+1,size)); + HDstrncpy(name, H5RS_GET_STR(ent->user_path_r), MIN(len+1,size)); if(len >= size) name[size-1]='\0'; } /* end if */ diff --git a/src/H5MMprivate.h b/src/H5MMprivate.h index 1dac78e..5e98b0e 100644 --- a/src/H5MMprivate.h +++ b/src/H5MMprivate.h @@ -15,7 +15,7 @@ *------------------------------------------------------------------------- */ #ifndef _H5MMprivate_H -#define _H5MMprivate_h +#define _H5MMprivate_H #include "H5MMpublic.h" @@ -29,7 +29,7 @@ #define H5MM_malloc(Z) HDmalloc(MAX(1,Z)) #define H5MM_calloc(Z) HDcalloc(1,MAX(1,Z)) #endif /* H5_MALLOC_WORKS */ -#define H5MM_free(Z) HDfree(1,Z) +#define H5MM_free(Z) HDfree(Z) /* * Library prototypes... diff --git a/src/H5O.c b/src/H5O.c index 7817b55..e266b86 100644 --- a/src/H5O.c +++ b/src/H5O.c @@ -27,6 +27,10 @@ #include "H5Oprivate.h" #include "H5Pprivate.h" +#ifdef H5_HAVE_GETTIMEOFDAY +#include +#endif /* H5_HAVE_GETTIMEOFDAY */ + #define PABLO_MASK H5O_mask /* PRIVATE PROTOTYPES */ @@ -39,7 +43,6 @@ static unsigned H5O_alloc(H5F_t *f, H5O_t *oh, const H5O_class_t *type, size_t size); static unsigned H5O_alloc_extend_chunk(H5O_t *oh, unsigned chunkno, size_t size); static unsigned H5O_alloc_new_chunk(H5F_t *f, H5O_t *oh, size_t size); -static herr_t H5O_touch_oh(H5F_t *f, H5O_t *oh, hbool_t force); /* H5O inherits cache-like properties from H5AC */ static const H5AC_class_t H5AC_OHDR[1] = {{ @@ -73,6 +76,7 @@ static const H5O_class_t *const message_type_g[] = { NULL, /*0x000F Shared header message */ H5O_CONT, /*0x0010 Object header continuation */ H5O_STAB, /*0x0011 Symbol table */ + H5O_MTIME_NEW, /*0x0012 New Object modification date and time */ }; /* @@ -168,7 +172,6 @@ H5O_create(H5F_t *f, size_t size_hint, H5G_entry_t *ent/*out*/) assert(f); assert(ent); - HDmemset(ent, 0, sizeof(H5G_entry_t)); size_hint = H5O_ALIGN (MAX (H5O_MIN_SIZE, size_hint)); /* allocate disk space for header and first chunk */ @@ -224,7 +227,7 @@ H5O_init(H5F_t *f, size_t size_hint, H5G_entry_t *ent/*out*/, haddr_t header) ent->header = header; /* allocate the object header and fill in header fields */ - if (NULL == (oh = H5FL_ALLOC(H5O_t, 1))) + if (NULL == (oh = H5FL_MALLOC(H5O_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); oh->dirty = TRUE; @@ -235,7 +238,7 @@ H5O_init(H5F_t *f, size_t size_hint, H5G_entry_t *ent/*out*/, haddr_t header) oh->nchunks = 1; oh->alloc_nchunks = H5O_NCHUNKS; - if (NULL == (oh->chunk = H5FL_ARR_ALLOC(H5O_chunk_t, oh->alloc_nchunks, 0))) + if (NULL == (oh->chunk = H5FL_ARR_MALLOC(H5O_chunk_t, oh->alloc_nchunks))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); tmp_addr = ent->header + (hsize_t)H5O_SIZEOF_HDR(f); @@ -243,14 +246,14 @@ H5O_init(H5F_t *f, size_t size_hint, H5G_entry_t *ent/*out*/, haddr_t header) oh->chunk[0].addr = tmp_addr; oh->chunk[0].size = size_hint; - if (NULL == (oh->chunk[0].image = H5FL_BLK_ALLOC(chunk_image, size_hint, 1))) + if (NULL == (oh->chunk[0].image = H5FL_BLK_CALLOC(chunk_image, size_hint))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); /* create the message list and initialize the first message */ oh->nmesgs = 1; oh->alloc_nmesgs = H5O_NMESGS; - if (NULL == (oh->mesg = H5FL_ARR_ALLOC(H5O_mesg_t, oh->alloc_nmesgs, 1))) + if (NULL == (oh->mesg = H5FL_ARR_CALLOC(H5O_mesg_t, oh->alloc_nmesgs))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); oh->mesg[0].type = H5O_NULL; @@ -431,7 +434,7 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void * UNUSED _udata1, assert(!_udata2); /* allocate ohdr and init chunk list */ - if (NULL==(oh = H5FL_ALLOC(H5O_t,1))) + if (NULL==(oh = H5FL_CALLOC(H5O_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); /* read fixed-lenth part of object header */ @@ -461,7 +464,7 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void * UNUSED _udata1, /* build the message array */ oh->alloc_nmesgs = MAX(H5O_NMESGS, nmesgs); - if (NULL==(oh->mesg=H5FL_ARR_ALLOC(H5O_mesg_t,oh->alloc_nmesgs,1))) + if (NULL==(oh->mesg=H5FL_ARR_CALLOC(H5O_mesg_t,oh->alloc_nmesgs))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); /* read each chunk from disk */ @@ -483,7 +486,7 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void * UNUSED _udata1, oh->chunk[chunkno].dirty = FALSE; oh->chunk[chunkno].addr = chunk_addr; oh->chunk[chunkno].size = chunk_size; - if (NULL==(oh->chunk[chunkno].image = H5FL_BLK_ALLOC(chunk_image,chunk_size,0))) + if (NULL==(oh->chunk[chunkno].image = H5FL_BLK_MALLOC(chunk_image,chunk_size))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); if (H5F_block_read(f, H5FD_MEM_OHDR, chunk_addr, chunk_size, dxpl_id, oh->chunk[chunkno].image) < 0) @@ -595,6 +598,7 @@ H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_t *oh) uint8_t buf[16], *p; int id; unsigned u; + H5O_mesg_t *curr_msg; /* Pointer to current message being operated on */ H5O_cont_t *cont = NULL; herr_t (*encode)(H5F_t*, uint8_t*, const void*) = NULL; unsigned combine=0; /* Whether to combine the object header prefix & the first chunk */ @@ -642,26 +646,26 @@ H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_t *oh) } /* end else */ /* encode messages */ - for (u = 0; u < oh->nmesgs; u++) { - if (oh->mesg[u].dirty) { - p = oh->mesg[u].raw - H5O_SIZEOF_MSGHDR(f); + for (u = 0, curr_msg=&oh->mesg[0]; u < oh->nmesgs; u++,curr_msg++) { + if (curr_msg->dirty) { + p = curr_msg->raw - H5O_SIZEOF_MSGHDR(f); - id = oh->mesg[u].type->id; + id = curr_msg->type->id; UINT16ENCODE(p, id); - assert (oh->mesg[u].raw_sizemesg[u].raw_size); - *p++ = oh->mesg[u].flags; + assert (curr_msg->raw_sizeraw_size); + *p++ = curr_msg->flags; *p++ = 0; /*reserved*/ *p++ = 0; /*reserved*/ *p++ = 0; /*reserved*/ - if (oh->mesg[u].native) { - assert(oh->mesg[u].type->encode); + if (curr_msg->native) { + assert(curr_msg->type->encode); /* allocate file space for chunks that have none yet */ - if (H5O_CONT_ID == oh->mesg[u].type->id && - !H5F_addr_defined(((H5O_cont_t *)(oh->mesg[u].native))->addr)) { - cont = (H5O_cont_t *) (oh->mesg[u].native); + if (H5O_CONT_ID == curr_msg->type->id && + !H5F_addr_defined(((H5O_cont_t *)(curr_msg->native))->addr)) { + cont = (H5O_cont_t *) (curr_msg->native); assert(cont->chunkno < oh->nchunks); assert(!H5F_addr_defined(oh->chunk[cont->chunkno].addr)); cont->size = oh->chunk[cont->chunkno].size; @@ -676,23 +680,23 @@ H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_t *oh) * encode a Shared Object message instead of the object * which is being shared. */ - assert(oh->mesg[u].raw >= - oh->chunk[oh->mesg[u].chunkno].image); - assert (oh->mesg[u].raw_size == - H5O_ALIGN (oh->mesg[u].raw_size)); - assert(oh->mesg[u].raw + oh->mesg[u].raw_size <= - oh->chunk[oh->mesg[u].chunkno].image + - oh->chunk[oh->mesg[u].chunkno].size); - if (oh->mesg[u].flags & H5O_FLAG_SHARED) { + assert(curr_msg->raw >= + oh->chunk[curr_msg->chunkno].image); + assert (curr_msg->raw_size == + H5O_ALIGN (curr_msg->raw_size)); + assert(curr_msg->raw + curr_msg->raw_size <= + oh->chunk[curr_msg->chunkno].image + + oh->chunk[curr_msg->chunkno].size); + if (curr_msg->flags & H5O_FLAG_SHARED) { encode = H5O_SHARED->encode; } else { - encode = oh->mesg[u].type->encode; + encode = curr_msg->type->encode; } - if ((encode)(f, oh->mesg[u].raw, oh->mesg[u].native)<0) + if ((encode)(f, curr_msg->raw, curr_msg->native)<0) HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "unable to encode object header message"); } - oh->mesg[u].dirty = FALSE; - oh->chunk[oh->mesg[u].chunkno].dirty = TRUE; + curr_msg->dirty = FALSE; + oh->chunk[curr_msg->chunkno].dirty = TRUE; } } @@ -702,7 +706,7 @@ H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_t *oh) assert(H5F_addr_defined(oh->chunk[u].addr)); if(u==0 && combine) { /* Allocate space for the combined prefix and first chunk */ - if((p=H5FL_BLK_ALLOC(chunk_image,(H5O_SIZEOF_HDR(f)+oh->chunk[u].size),0))==NULL) + if((p=H5FL_BLK_MALLOC(chunk_image,(H5O_SIZEOF_HDR(f)+oh->chunk[u].size)))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); /* Copy in the prefix */ @@ -739,11 +743,11 @@ H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_t *oh) oh->chunk = H5FL_ARR_FREE(H5O_chunk_t,oh->chunk); /* destroy messages */ - for (u = 0; u < oh->nmesgs; u++) { - if (oh->mesg[u].flags & H5O_FLAG_SHARED) { - H5O_free(H5O_SHARED, oh->mesg[u].native); + for (u = 0, curr_msg=&oh->mesg[0]; u < oh->nmesgs; u++,curr_msg++) { + if (curr_msg->flags & H5O_FLAG_SHARED) { + H5O_free(H5O_SHARED, curr_msg->native); } else { - H5O_free(oh->mesg[u].type, oh->mesg[u].native); + H5O_free(curr_msg->type, curr_msg->native); } } oh->mesg = H5FL_ARR_FREE(H5O_mesg_t,oh->mesg); @@ -969,7 +973,7 @@ H5O_count (H5G_entry_t *ent, const H5O_class_t *type) assert (type); /* Load the object header */ - if (NULL==(oh=H5AC_find (ent->file, H5AC_OHDR, ent->header, NULL, NULL))) + if (NULL==(oh=H5AC_find_f (ent->file, H5AC_OHDR, ent->header, NULL, NULL))) HGOTO_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header"); for (u=acc=0; unmesgs; u++) { @@ -1020,7 +1024,7 @@ H5O_exists(H5G_entry_t *ent, const H5O_class_t *type, int sequence) assert(sequence>=0); /* Load the object header */ - if (NULL==(oh=H5AC_find(ent->file, H5AC_OHDR, ent->header, NULL, NULL))) + if (NULL==(oh=H5AC_find_f(ent->file, H5AC_OHDR, ent->header, NULL, NULL))) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header"); /* Scan through the messages looking for the right one */ @@ -1182,7 +1186,7 @@ H5O_find_in_ohdr(H5F_t *f, haddr_t addr, const H5O_class_t **type_p, assert(type_p); /* Load the object header */ - if (NULL == (oh = H5AC_find(f, H5AC_OHDR, addr, NULL, NULL))) + if (NULL == (oh = H5AC_find_f(f, H5AC_OHDR, addr, NULL, NULL))) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, UFAIL, "unable to load object header"); /* Scan through the messages looking for the right one */ @@ -1244,6 +1248,10 @@ done: * the sequence number 5 if there is no message with sequence * number 4). * + * The UPDATE_TIME argument is a boolean that allows the caller + * to skip updating the modification time. This is useful when + * several calls to H5O_modify will be made in a sequence. + * * Return: Success: The sequence number of the message that * was modified or created. * @@ -1264,14 +1272,15 @@ done: */ int H5O_modify(H5G_entry_t *ent, const H5O_class_t *type, int overwrite, - unsigned flags, const void *mesg) + unsigned flags, unsigned update_time, const void *mesg) { - H5O_t *oh = NULL; + H5O_t *oh=NULL; int sequence; - unsigned idx; + unsigned idx; /* Index of message to modify */ + H5O_mesg_t *idx_msg; /* Pointer to message to modify */ int ret_value = FAIL; - size_t size = 0; - H5O_shared_t sh_mesg = {0,{{0,0}}}; + size_t size=0; + H5O_shared_t sh_mesg; FUNC_ENTER_NOAPI(H5O_modify, FAIL); @@ -1290,8 +1299,8 @@ H5O_modify(H5G_entry_t *ent, const H5O_class_t *type, int overwrite, HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header"); /* Count similar messages */ - for (idx = 0, sequence = -1; idx < oh->nmesgs; idx++) { - if (type->id != oh->mesg[idx].type->id) + for (idx = 0, sequence = -1, idx_msg=&oh->mesg[0]; idx < oh->nmesgs; idx++, idx_msg++) { + if (type->id != idx_msg->type->id) continue; if (++sequence == overwrite) break; @@ -1311,6 +1320,8 @@ H5O_modify(H5G_entry_t *ent, const H5O_class_t *type, int overwrite, if (overwrite < 0) { /* Allocate space for the new message */ if (flags & H5O_FLAG_SHARED) { + HDmemset(&sh_mesg,0,sizeof(H5O_shared_t)); + if (NULL==type->get_share) HGOTO_ERROR (H5E_OHDR, H5E_UNSUPPORTED, FAIL, "message class is not sharable"); if ((type->get_share)(ent->file, mesg, &sh_mesg/*out*/)<0) { @@ -1342,7 +1353,8 @@ H5O_modify(H5G_entry_t *ent, const H5O_class_t *type, int overwrite, size = (H5O_SHARED->raw_size)(ent->file, &sh_mesg); } } - if (0==(flags & H5O_FLAG_SHARED)) { + /* This can't be an 'else' statement due to the possibility of the shared bit getting turned off above */ + if (0== (flags & H5O_FLAG_SHARED)) { size = (type->raw_size) (ent->file, mesg); if (size>=H5O_MAX_SIZE) HGOTO_ERROR (H5E_OHDR, H5E_CANTINIT, FAIL, "object header message is too large (16k max)"); @@ -1358,25 +1370,28 @@ H5O_modify(H5G_entry_t *ent, const H5O_class_t *type, int overwrite, HGOTO_ERROR (H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to modify shared (constant) message"); } + /* Set pointer to the correct message */ + idx_msg=&oh->mesg[idx]; /* Copy the native value into the object header */ if (flags & H5O_FLAG_SHARED) { - if (NULL==(oh->mesg[idx].native = H5MM_malloc (sizeof (H5O_shared_t)))) + if (NULL==(idx_msg->native = H5MM_malloc (sizeof (H5O_shared_t)))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - HDmemcpy(oh->mesg[idx].native,&sh_mesg,sizeof(H5O_shared_t)); + HDmemcpy(idx_msg->native,&sh_mesg,sizeof(H5O_shared_t)); } else { - if (oh->mesg[idx].native) - H5O_reset (oh->mesg[idx].type, oh->mesg[idx].native); - oh->mesg[idx].native = (type->copy) (mesg, oh->mesg[idx].native); - if (NULL == oh->mesg[idx].native) + if (idx_msg->native) + H5O_reset (idx_msg->type, idx_msg->native); + idx_msg->native = (type->copy) (mesg, idx_msg->native); + if (NULL == idx_msg->native) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to copy message to object header"); } /* Update the modification time message if any */ - H5O_touch_oh(ent->file, oh, FALSE); + if(update_time) + H5O_touch_oh(ent->file, oh, FALSE); - oh->mesg[idx].flags = flags; - oh->mesg[idx].dirty = TRUE; + idx_msg->flags = flags; + idx_msg->dirty = TRUE; oh->dirty = TRUE; /* Set return value */ @@ -1391,6 +1406,206 @@ done: /*------------------------------------------------------------------------- + * Function: H5O_protect + * + * Purpose: Wrapper around H5AC_protect for use during a H5O_protect-> + * H5O_append->...->H5O_append->H5O_unprotect sequence of calls + * during an object's creation. + * + * Return: Success: Pointer to the object header structure for the + * object. + * + * Failure: NULL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Dec 31 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +H5O_t * +H5O_protect(H5G_entry_t *ent) +{ + H5O_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_protect, NULL); + + /* check args */ + 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, NULL, "no write intent on file"); + + if (NULL == (ret_value = H5AC_protect(ent->file, H5AC_OHDR, ent->header, NULL, NULL))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "unable to load object header"); + +done: + FUNC_LEAVE(ret_value); +} /* end H5O_protect() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_unprotect + * + * Purpose: Wrapper around H5AC_unprotect for use during a H5O_protect-> + * H5O_append->...->H5O_append->H5O_unprotect sequence of calls + * during an object's creation. + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Dec 31 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_unprotect(H5G_entry_t *ent, H5O_t *oh) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_unprotect, FAIL); + + /* check args */ + assert(ent); + assert(ent->file); + assert(H5F_addr_defined(ent->header)); + assert(oh); + + if (H5AC_unprotect(ent->file, H5AC_OHDR, ent->header, oh) < 0) + HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); + +done: + FUNC_LEAVE(ret_value); +} /* end H5O_unprotect() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_append + * + * Purpose: Simplified version of H5O_modify, used when creating a new + * object header message (usually during object creation) + * + * Modifies an existing message or creates a new message. + * The cache fields in that symbol table entry ENT are *not* + * updated, you must do that separately because they often + * depend on multiple object header messages. Besides, we + * don't know which messages will be constant and which will + * not. + * + * Return: Success: The sequence number of the message that + * was created. + * + * Failure: Negative + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Dec 31 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int +H5O_append(H5F_t *f, H5O_t *oh, const H5O_class_t *type, + unsigned flags, const void *mesg) +{ + unsigned idx; /* Index of message to modify */ + H5O_mesg_t *idx_msg; /* Pointer to message to modify */ + int ret_value = FAIL; + size_t size=0; + H5O_shared_t sh_mesg; + + FUNC_ENTER_NOAPI(H5O_append, FAIL); + + /* check args */ + assert(f); + assert(oh); + assert(type); + assert(0==(flags & ~H5O_FLAG_BITS)); + assert(mesg); + + /* Allocate space for the new message */ + if (flags & H5O_FLAG_SHARED) { + HDmemset(&sh_mesg,0,sizeof(H5O_shared_t)); + + if (NULL==type->get_share) + HGOTO_ERROR (H5E_OHDR, H5E_UNSUPPORTED, FAIL, "message class is not sharable"); + if ((type->get_share)(f, mesg, &sh_mesg/*out*/)<0) { + /* + * If the message isn't shared then turn off the shared bit + * and treat it as an unshared message. + */ + H5E_clear (); + flags &= ~H5O_FLAG_SHARED; + } else if (sh_mesg.in_gh) { + /* + * The shared message is stored in the global heap. + * Increment the reference count on the global heap message. + */ + if (H5HG_link (f, &(sh_mesg.u.gh), 1)<0) + HGOTO_ERROR (H5E_OHDR, H5E_LINK, FAIL, "unable to adjust shared object link count"); + size = (H5O_SHARED->raw_size)(f, &sh_mesg); + } else { + /* + * The shared message is stored in some other object header. + * The other object header must be in the same file as the + * new object header. Increment the reference count on that + * object header. + */ + if (sh_mesg.u.ent.file->shared != f->shared) + HGOTO_ERROR(H5E_OHDR, H5E_LINK, FAIL, "interfile hard links are not allowed"); + if (H5O_link (&(sh_mesg.u.ent), 1)<0) + HGOTO_ERROR (H5E_OHDR, H5E_LINK, FAIL, "unable to adjust shared object link count"); + size = (H5O_SHARED->raw_size)(f, &sh_mesg); + } + } + /* This can't be an 'else' statement due to the possibility of the shared bit getting turned off above */ + if (0== (flags & H5O_FLAG_SHARED)) { + size = (type->raw_size) (f, mesg); + if (size>=H5O_MAX_SIZE) + HGOTO_ERROR (H5E_OHDR, H5E_CANTINIT, FAIL, "object header message is too large (16k max)"); + } + if ((idx = H5O_alloc(f, oh, type, size)) == UFAIL) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to allocate space for message"); + + /* Set pointer to the correct message */ + idx_msg=&oh->mesg[idx]; + + /* Copy the native value into the object header */ + if (flags & H5O_FLAG_SHARED) { + if (NULL==(idx_msg->native = H5MM_malloc (sizeof (H5O_shared_t)))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + HDmemcpy(idx_msg->native,&sh_mesg,sizeof(H5O_shared_t)); + } else { + if (idx_msg->native) + H5O_reset (idx_msg->type, idx_msg->native); + idx_msg->native = (type->copy) (mesg, idx_msg->native); + if (NULL == idx_msg->native) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to copy message to object header"); + } + + idx_msg->flags = flags; + idx_msg->dirty = TRUE; + oh->dirty = TRUE; + + /* Set return value */ + ret_value = idx; + +done: + FUNC_LEAVE(ret_value); +} /* end H5O_append() */ + + +/*------------------------------------------------------------------------- * Function: H5O_touch_oh * * Purpose: If FORCE is non-zero then create a modification time message @@ -1406,11 +1621,14 @@ done: * *------------------------------------------------------------------------- */ -static herr_t +herr_t H5O_touch_oh(H5F_t *f, H5O_t *oh, hbool_t force) { unsigned idx; - time_t now = HDtime(NULL); +#ifdef H5_HAVE_GETTIMEOFDAY + struct timeval now_tv; +#endif /* H5_HAVE_GETTIMEOFDAY */ + time_t now; size_t size; herr_t ret_value=SUCCEED; /* Return value */ @@ -1420,22 +1638,29 @@ H5O_touch_oh(H5F_t *f, H5O_t *oh, hbool_t force) /* Look for existing message */ for (idx=0; idxnmesgs; idx++) { - if (H5O_MTIME==oh->mesg[idx].type) + if (H5O_MTIME==oh->mesg[idx].type || H5O_MTIME_NEW==oh->mesg[idx].type) break; } +#ifdef H5_HAVE_GETTIMEOFDAY + HDgettimeofday(&now_tv,NULL); + now=now_tv.tv_sec; +#else /* H5_HAVE_GETTIMEOFDAY */ + now = HDtime(NULL); +#endif /* H5_HAVE_GETTIMEOFDAY */ + /* Create a new message */ if (idx==oh->nmesgs) { if (!force) HGOTO_DONE(SUCCEED); /*nothing to do*/ - size = (H5O_MTIME->raw_size)(f, &now); - if ((idx=H5O_alloc(f, oh, H5O_MTIME, size))==UFAIL) + size = (H5O_MTIME_NEW->raw_size)(f, &now); + if ((idx=H5O_alloc(f, oh, H5O_MTIME_NEW, size))==UFAIL) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to allocate space for modification time message"); } /* Update the native part */ if (NULL==oh->mesg[idx].native) { - if (NULL==(oh->mesg[idx].native = H5FL_ALLOC(time_t,0))) + if (NULL==(oh->mesg[idx].native = H5FL_MALLOC(time_t))) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "memory allocation failed for modification time message"); } *((time_t*)(oh->mesg[idx].native)) = now; @@ -1833,7 +2058,7 @@ H5O_alloc_new_chunk(H5F_t *f, H5O_t *oh, size_t size) oh->chunk[chunkno].dirty = TRUE; oh->chunk[chunkno].addr = HADDR_UNDEF; oh->chunk[chunkno].size = size; - if (NULL==(oh->chunk[chunkno].image = p = H5FL_BLK_ALLOC(chunk_image,size,1))) + if (NULL==(oh->chunk[chunkno].image = p = H5FL_BLK_CALLOC(chunk_image,size))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, UFAIL, "memory allocation failed"); /* @@ -1944,9 +2169,8 @@ done: static unsigned H5O_alloc(H5F_t *f, H5O_t *oh, const H5O_class_t *type, size_t size) { - unsigned chunkno; unsigned idx; - unsigned null_idx; + H5O_mesg_t *msg; /* Pointer to newly allocated message */ size_t aligned_size = H5O_ALIGN(size); unsigned ret_value; /* Return value */ @@ -1975,6 +2199,8 @@ H5O_alloc(H5F_t *f, H5O_t *oh, const H5O_class_t *type, size_t size) /* if we didn't find one, then allocate more header space */ if (idx >= oh->nmesgs) { + unsigned chunkno; + /* * Look for a chunk which hasn't had disk space allocated yet * since we can just increase the size of that chunk. @@ -1995,9 +2221,15 @@ H5O_alloc(H5F_t *f, H5O_t *oh, const H5O_class_t *type, size_t size) } } + /* Set pointer to newly allocated message */ + msg=&oh->mesg[idx]; + /* do we need to split the null message? */ - if (oh->mesg[idx].raw_size > aligned_size) { - assert(oh->mesg[idx].raw_size - aligned_size >= H5O_SIZEOF_MSGHDR(f)); + if (msg->raw_size > aligned_size) { + H5O_mesg_t *null_msg; /* Pointer to null message */ + size_t mesg_size = aligned_size+ H5O_SIZEOF_MSGHDR(f); /* Total size of newly allocated message */ + + assert(msg->raw_size - aligned_size >= H5O_SIZEOF_MSGHDR(f)); if (oh->nmesgs >= oh->alloc_nmesgs) { int old_alloc=oh->alloc_nmesgs; @@ -2013,23 +2245,20 @@ H5O_alloc(H5F_t *f, H5O_t *oh, const H5O_class_t *type, size_t size) HDmemset(&oh->mesg[old_alloc],0, (oh->alloc_nmesgs-old_alloc)*sizeof(H5O_mesg_t)); } - null_idx = oh->nmesgs++; - oh->mesg[null_idx].type = H5O_NULL; - oh->mesg[null_idx].dirty = TRUE; - oh->mesg[null_idx].native = NULL; - oh->mesg[null_idx].raw = oh->mesg[idx].raw + - aligned_size + - H5O_SIZEOF_MSGHDR(f); - oh->mesg[null_idx].raw_size = oh->mesg[idx].raw_size - - (aligned_size + H5O_SIZEOF_MSGHDR(f)); - oh->mesg[null_idx].chunkno = oh->mesg[idx].chunkno; - oh->mesg[idx].raw_size = aligned_size; + null_msg=&oh->mesg[oh->nmesgs++]; + null_msg->type = H5O_NULL; + null_msg->dirty = TRUE; + null_msg->native = NULL; + null_msg->raw = msg->raw + mesg_size; + null_msg->raw_size = msg->raw_size - mesg_size; + null_msg->chunkno = msg->chunkno; + msg->raw_size = aligned_size; } /* initialize the new message */ - oh->mesg[idx].type = type; - oh->mesg[idx].dirty = TRUE; - oh->mesg[idx].native = NULL; + msg->type = type; + msg->dirty = TRUE; + msg->native = NULL; oh->dirty = TRUE; diff --git a/src/H5Oattr.c b/src/H5Oattr.c index 40da90a..34e209a 100644 --- a/src/H5Oattr.c +++ b/src/H5Oattr.c @@ -134,14 +134,23 @@ H5O_attr_decode(H5F_t *f, const uint8_t *p, H5O_shared_t UNUSED *sh) p += H5O_ALIGN(attr->dt_size); /* decode the attribute dataspace */ - if (NULL==(attr->ds = H5FL_ALLOC(H5S_t,1))) + if (NULL==(attr->ds = H5FL_CALLOC(H5S_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); if((simple=(H5O_SDSPACE->decode)(f,p,NULL))!=NULL) { + hsize_t nelem; /* Number of elements in extent */ + unsigned u; /* Local index variable */ + attr->ds->extent.type = H5S_SIMPLE; HDmemcpy(&(attr->ds->extent.u.simple),simple, sizeof(H5S_simple_t)); H5FL_FREE(H5S_simple_t,simple); + + /* Compute the number of elements in the extent */ + for(u=0, nelem=1; uds->extent.u.simple.rank; u++) + nelem*=attr->ds->extent.u.simple.size[u]; + attr->ds->extent.nelem = nelem; } else { attr->ds->extent.type = H5S_SCALAR; + attr->ds->extent.nelem = 1; } /* Default to entire dataspace being selected */ if(H5S_select_all(attr->ds,0)<0) diff --git a/src/H5Ocomp.c b/src/H5Ocomp.c deleted file mode 100644 index 8899c34..0000000 --- a/src/H5Ocomp.c +++ /dev/null @@ -1,492 +0,0 @@ -/* - * Copyright (C) 1998-2001 NCSA - * All rights reserved. - * - * Programmer: Robb Matzke - * Wednesday, April 15, 1998 - * - * Purpose: Data filter pipeline message. - */ -#include "H5private.h" -#include "H5Eprivate.h" -#include "H5FLprivate.h" /*Free Lists */ -#include "H5MMprivate.h" -#include "H5Oprivate.h" - -/* Interface initialization */ -#define PABLO_MASK H5O_pline_mask -static int interface_initialize_g = 0; -#define INTERFACE_INIT NULL - -#define H5O_PLINE_VERSION 1 - -static herr_t H5O_pline_encode (H5F_t *f, uint8_t *p, const void *mesg); -static void *H5O_pline_decode (H5F_t *f, const uint8_t *p, H5O_shared_t *sh); -static void *H5O_pline_copy (const void *_mesg, void *_dest); -static size_t H5O_pline_size (H5F_t *f, const void *_mesg); -static herr_t H5O_pline_reset (void *_mesg); -static herr_t H5O_pline_free (void *_mesg); -static herr_t H5O_pline_debug (H5F_t *f, const void *_mesg, - FILE * stream, int indent, int fwidth); - -/* This message derives from H5O */ -const H5O_class_t H5O_PLINE[1] = {{ - H5O_PLINE_ID, /* message id number */ - "filter pipeline", /* message name for debugging */ - sizeof(H5O_pline_t), /* native message size */ - H5O_pline_decode, /* decode message */ - H5O_pline_encode, /* encode message */ - H5O_pline_copy, /* copy the native value */ - H5O_pline_size, /* size of raw message */ - H5O_pline_reset, /* reset method */ - H5O_pline_free, /* free method */ - NULL, /* get share method */ - NULL, /* set share method */ - H5O_pline_debug, /* debug the message */ -}}; - - -/* Declare a free list to manage the H5O_pline_t struct */ -H5FL_DEFINE(H5O_pline_t); - - -/*------------------------------------------------------------------------- - * Function: H5O_pline_decode - * - * Purpose: Decodes a filter pipeline message. - * - * Return: Success: Ptr to the native message. - * - * Failure: NULL - * - * Programmer: Robb Matzke - * Wednesday, April 15, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static void * -H5O_pline_decode(H5F_t UNUSED *f, const uint8_t *p, - H5O_shared_t UNUSED *sh) -{ - H5O_pline_t *pline = NULL; - void *ret_value; - unsigned version; - size_t i, j, n, name_length; - - FUNC_ENTER_NOAPI(H5O_pline_decode, NULL); - - /* check args */ - assert(p); - - /* Decode */ - if (NULL==(pline = H5FL_ALLOC(H5O_pline_t,1))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - version = *p++; - if (version!=H5O_PLINE_VERSION) - HGOTO_ERROR(H5E_PLINE, H5E_CANTLOAD, NULL, "bad version number for filter pipeline message"); - pline->nfilters = *p++; - if (pline->nfilters>32) - HGOTO_ERROR(H5E_PLINE, H5E_CANTLOAD, NULL, "filter pipeline message has too many filters"); - p += 6; /*reserved*/ - pline->nalloc = pline->nfilters; - pline->filter = H5MM_calloc(pline->nalloc*sizeof(pline->filter[0])); - if (NULL==pline->filter) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - for (i=0; infilters; i++) { - UINT16DECODE(p, pline->filter[i].id); - UINT16DECODE(p, name_length); - if (name_length % 8) - HGOTO_ERROR(H5E_PLINE, H5E_CANTLOAD, NULL, "filter name length is not a multiple of eight"); - UINT16DECODE(p, pline->filter[i].flags); - UINT16DECODE(p, pline->filter[i].cd_nelmts); - if (name_length) { - /* - * Get the name, allocating an extra byte for an extra null - * terminator just in case there isn't one in the file (there - * should be, but to be safe...) - */ - pline->filter[i].name = H5MM_malloc(name_length+1); - HDmemcpy(pline->filter[i].name, p, name_length); - pline->filter[i].name[name_length] = '\0'; - p += name_length; - } - if ((n=pline->filter[i].cd_nelmts)) { - /* - * Read the client data values and the padding - */ - pline->filter[i].cd_values = H5MM_malloc(n*sizeof(unsigned)); - if (NULL==pline->filter[i].cd_values) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for client data"); - for (j=0; jfilter[i].cd_nelmts; j++) - UINT32DECODE(p, pline->filter[i].cd_values[j]); - if (pline->filter[i].cd_nelmts % 2) - p += 4; /*padding*/ - } - } - - /* Set return value */ - ret_value = pline; - -done: - if (NULL==ret_value && pline) { - if (pline->filter) { - for (i=0; infilters; i++) { - H5MM_xfree(pline->filter[i].name); - H5MM_xfree(pline->filter[i].cd_values); - } - H5MM_xfree(pline->filter); - } - H5FL_FREE(H5O_pline_t,pline); - } - - FUNC_LEAVE(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5O_pline_encode - * - * Purpose: Encodes message MESG into buffer P. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Wednesday, April 15, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5O_pline_encode (H5F_t UNUSED *f, uint8_t *p/*out*/, const void *mesg) -{ - const H5O_pline_t *pline = (const H5O_pline_t*)mesg; - size_t i, j, name_length; - const char *name=NULL; - H5Z_class_t *cls=NULL; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5O_pline_encode, FAIL); - - /* Check args */ - assert (p); - assert (mesg); - - *p++ = H5O_PLINE_VERSION; - *p++ = (uint8_t)(pline->nfilters); - *p++ = 0; /*reserved 1*/ - *p++ = 0; /*reserved 2*/ - *p++ = 0; /*reserved 3*/ - *p++ = 0; /*reserved 4*/ - *p++ = 0; /*reserved 5*/ - *p++ = 0; /*reserved 6*/ - - for (i=0; infilters; i++) { - /* - * Get the filter name. If the pipeline message has a name in it then - * use that one. Otherwise try to look up the filter and get the name - * as it was registered. - */ - if (NULL==(name=pline->filter[i].name) && - (cls=H5Z_find(pline->filter[i].id))) - name = cls->name; - name_length = name ? HDstrlen(name)+1 : 0; - - /* Encode the filter */ - UINT16ENCODE(p, pline->filter[i].id); - UINT16ENCODE(p, H5O_ALIGN(name_length)); - UINT16ENCODE(p, pline->filter[i].flags); - UINT16ENCODE(p, pline->filter[i].cd_nelmts); - if (name_length>0) { - HDmemcpy(p, name, name_length); - p += name_length; - while (name_length++ % 8) - *p++ = 0; - } - for (j=0; jfilter[i].cd_nelmts; j++) - UINT32ENCODE(p, pline->filter[i].cd_values[j]); - if (pline->filter[i].cd_nelmts % 2) - UINT32ENCODE(p, 0); - } - -done: - FUNC_LEAVE (ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5O_pline_copy - * - * Purpose: Copies a filter pipeline message from SRC to DST allocating - * DST if necessary. If DST is already allocated then we assume - * that it isn't initialized. - * - * Return: Success: Ptr to DST or allocated result. - * - * Failure: NULL - * - * Programmer: Robb Matzke - * Wednesday, April 15, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static void * -H5O_pline_copy (const void *_src, void *_dst/*out*/) -{ - const H5O_pline_t *src = (const H5O_pline_t *)_src; - H5O_pline_t *dst = (H5O_pline_t *)_dst; - size_t i; - H5O_pline_t *ret_value = NULL; - - FUNC_ENTER_NOAPI(H5O_pline_copy, NULL); - - if (!dst && NULL==(dst = H5FL_ALLOC (H5O_pline_t,0))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - - *dst = *src; - dst->nalloc = dst->nfilters; - if (dst->nalloc>0) { - dst->filter = H5MM_calloc(dst->nalloc * sizeof(dst->filter[0])); - if (NULL==dst->filter) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - } else { - dst->filter = NULL; - } - - for (i=0; infilters; i++) { - dst->filter[i] = src->filter[i]; - if (src->filter[i].name) { - dst->filter[i].name = H5MM_xstrdup(src->filter[i].name); - } - if (src->filter[i].cd_nelmts>0) { - dst->filter[i].cd_values = H5MM_malloc(src->filter[i].cd_nelmts* - sizeof(unsigned)); - if (NULL==dst->filter[i].cd_values) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - HDmemcpy (dst->filter[i].cd_values, src->filter[i].cd_values, - src->filter[i].cd_nelmts * sizeof(unsigned)); - } - } - - /* Set return value */ - ret_value = dst; - -done: - if (!ret_value && dst) { - if (dst->filter) { - for (i=0; infilters; i++) { - H5MM_xfree(dst->filter[i].name); - H5MM_xfree(dst->filter[i].cd_values); - } - H5MM_xfree(dst->filter); - } - if (!_dst) - H5FL_FREE(H5O_pline_t,dst); - } - - FUNC_LEAVE (ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5O_pline_size - * - * Purpose: Determines the size of a raw filter pipeline message. - * - * Return: Success: Size of message. - * - * Failure: zero - * - * Programmer: Robb Matzke - * Wednesday, April 15, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static size_t -H5O_pline_size (H5F_t UNUSED *f, const void *mesg) -{ - const H5O_pline_t *pline = (const H5O_pline_t*)mesg; - size_t i, size, name_len; - const char *name = NULL; - H5Z_class_t *cls = NULL; - size_t ret_value; /* Return value */ - - FUNC_ENTER_NOAPI(H5O_pline_size, 0); - - /* Message header */ - size = 1 + /*version */ - 1 + /*number of filters */ - 6; /*reserved */ - - for (i=0; infilters; i++) { - /* Get the name of the filter, same as done with H5O_pline_encode() */ - if (NULL==(name=pline->filter[i].name) && - (cls=H5Z_find(pline->filter[i].id))) - name = cls->name; - name_len = name ? HDstrlen(name)+1 : 0; - - - size += 2 + /*filter identification number */ - 2 + /*name length */ - 2 + /*flags */ - 2 + /*number of client data values */ - H5O_ALIGN(name_len); /*length of the filter name */ - - size += pline->filter[i].cd_nelmts * 4; - if (pline->filter[i].cd_nelmts % 2) - size += 4; - } - - /* Set return value */ - ret_value=size; - -done: - FUNC_LEAVE (ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5O_pline_reset - * - * Purpose: Resets a filter pipeline message by clearing all filters. - * The MESG buffer is not freed. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Wednesday, April 15, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5O_pline_reset (void *mesg) -{ - H5O_pline_t *pline = (H5O_pline_t*)mesg; - size_t i; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5O_pline_reset, FAIL); - - assert (pline); - - for (i=0; infilters; i++) { - H5MM_xfree(pline->filter[i].name); - H5MM_xfree(pline->filter[i].cd_values); - } - H5MM_xfree(pline->filter); - HDmemset(pline, 0, sizeof *pline); - -done: - FUNC_LEAVE (ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5O_pline_free - * - * Purpose: Free's the message - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * Saturday, March 11, 2000 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5O_pline_free (void *mesg) -{ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5O_pline_free, FAIL); - - assert (mesg); - - H5FL_FREE(H5O_pline_t,mesg); - -done: - FUNC_LEAVE (ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5O_pline_debug - * - * Purpose: Prints debugging information for filter pipeline message MESG - * on output stream STREAM. Each line is indented INDENT - * characters and the field name takes up FWIDTH characters. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Wednesday, April 15, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5O_pline_debug (H5F_t UNUSED *f, const void *mesg, FILE *stream, - int indent, int fwidth) -{ - const H5O_pline_t *pline = (const H5O_pline_t *)mesg; - size_t i, j; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5O_pline_debug, FAIL); - - /* check args */ - assert(f); - assert(pline); - assert(stream); - assert(indent >= 0); - assert(fwidth >= 0); - - fprintf(stream, "%*s%-*s %lu/%lu\n", indent, "", fwidth, - "Number of filters:", - (unsigned long)(pline->nfilters), - (unsigned long)(pline->nalloc)); - - for (i=0; infilters; i++) { - char name[32]; - sprintf(name, "Filter at position %lu", (unsigned long)i); - fprintf(stream, "%*s%-*s\n", indent, "", fwidth, name); - fprintf(stream, "%*s%-*s 0x%04x\n", indent+3, "", MAX(0, fwidth-3), - "Filter identification:", - (unsigned)(pline->filter[i].id)); - if (pline->filter[i].name) { - fprintf(stream, "%*s%-*s \"%s\"\n", indent+3, "", MAX(0, fwidth-3), - "Filter name:", - pline->filter[i].name); - } else { - fprintf(stream, "%*s%-*s NONE\n", indent+3, "", MAX(0, fwidth-3), - "Filter name:"); - } - fprintf(stream, "%*s%-*s 0x%04x\n", indent+3, "", MAX(0, fwidth-3), - "Flags:", - (unsigned)(pline->filter[i].flags)); - fprintf(stream, "%*s%-*s %lu\n", indent+3, "", MAX(0, fwidth-3), - "Num CD values:", - (unsigned long)(pline->filter[i].cd_nelmts)); - for (j=0; jfilter[i].cd_nelmts; j++) { - char field_name[32]; - sprintf(field_name, "CD value %lu", (unsigned long)j); - fprintf(stream, "%*s%-*s %lu\n", indent+6, "", MAX(0, fwidth-6), - field_name, - (unsigned long)(pline->filter[i].cd_values[j])); - } - } - -done: - FUNC_LEAVE(ret_value); -} diff --git a/src/H5Odtype.c b/src/H5Odtype.c index 1d8b254..4244c41 100644 --- a/src/H5Odtype.c +++ b/src/H5Odtype.c @@ -48,7 +48,7 @@ const H5O_class_t H5O_DTYPE[1] = {{ H5O_dtype_copy, /* copy the native value */ H5O_dtype_size, /* size of raw message */ H5O_dtype_reset, /* reset method */ - H5O_dtype_free, /* free method */ + H5O_dtype_free, /* free method */ H5O_dtype_get_share, /* get share method */ H5O_dtype_set_share, /* set share method */ H5O_dtype_debug, /* debug the message */ @@ -227,7 +227,7 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt) } /* end if */ /* Allocate space for the field's datatype */ - temp_type = H5FL_ALLOC (H5T_t,1); + temp_type = H5FL_CALLOC (H5T_t); if (NULL==temp_type) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); temp_type->ent.header = HADDR_UNDEF; @@ -289,7 +289,7 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt) */ dt->u.enumer.nmembs = dt->u.enumer.nalloc = flags & 0xffff; assert(dt->u.enumer.nmembs>=0); - if (NULL==(dt->parent=H5FL_ALLOC(H5T_t,1))) + if (NULL==(dt->parent=H5FL_CALLOC(H5T_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); dt->parent->ent.header = HADDR_UNDEF; if (H5O_dtype_decode_helper(f, pp, dt->parent)<0) @@ -343,7 +343,7 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt) } /* end if */ /* Decode base type of VL information */ - if (NULL==(dt->parent = H5FL_ALLOC(H5T_t,1))) + if (NULL==(dt->parent = H5FL_CALLOC(H5T_t))) HGOTO_ERROR (H5E_DATATYPE, H5E_NOSPACE, FAIL, "memory allocation failed"); dt->parent->ent.header = HADDR_UNDEF; if (H5O_dtype_decode_helper(f, pp, dt->parent)<0) @@ -381,7 +381,7 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt) UINT32DECODE(*pp, dt->u.array.perm[j]); /* Decode base type of array */ - if (NULL==(dt->parent = H5FL_ALLOC(H5T_t,1))) + if (NULL==(dt->parent = H5FL_CALLOC(H5T_t))) HGOTO_ERROR (H5E_DATATYPE, H5E_NOSPACE, FAIL, "memory allocation failed"); dt->parent->ent.header = HADDR_UNDEF; if (H5O_dtype_decode_helper(f, pp, dt->parent)<0) @@ -794,7 +794,7 @@ H5O_dtype_decode(H5F_t *f, const uint8_t *p, /* check args */ assert(p); - if (NULL==(dt = H5FL_ALLOC(H5T_t,1))) + if (NULL==(dt = H5FL_CALLOC(H5T_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); dt->ent.header = HADDR_UNDEF; @@ -1009,18 +1009,12 @@ static herr_t H5O_dtype_reset(void *_mesg) { H5T_t *dt = (H5T_t *) _mesg; - H5T_t *tmp = NULL; herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5O_dtype_reset, FAIL); - if (dt) { - if (NULL==(tmp = H5FL_ALLOC(H5T_t,0))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - *tmp = *dt; - H5T_close(tmp); - HDmemset(dt, 0, sizeof(H5T_t)); - } + if (dt) + H5T_free(dt); done: FUNC_LEAVE(ret_value); @@ -1130,8 +1124,8 @@ H5O_dtype_set_share (H5F_t UNUSED *f, void *_mesg/*in,out*/, H5G_ent_copy(&(dt->ent),&(sh->u.ent),H5G_COPY_SHALLOW); /* Reset the names of the copied symbol table entry */ - dt->ent.user_path = NULL; - dt->ent.canon_path = NULL; + dt->ent.user_path_r = NULL; + dt->ent.canon_path_r = NULL; /* Note that the datatype is a named datatype */ dt->state = H5T_STATE_NAMED; diff --git a/src/H5Oefl.c b/src/H5Oefl.c index 388aa4a..c81002b 100644 --- a/src/H5Oefl.c +++ b/src/H5Oefl.c @@ -341,7 +341,8 @@ H5O_efl_reset(void *_mesg) mesg->slot[i].name = H5MM_xfree (mesg->slot[i].name); mesg->heap_addr = HADDR_UNDEF; mesg->nused = mesg->nalloc = 0; - mesg->slot = H5MM_xfree(mesg->slot); + if(mesg->slot) + mesg->slot = H5MM_xfree(mesg->slot); done: FUNC_LEAVE(ret_value); diff --git a/src/H5Ofill.c b/src/H5Ofill.c index dd734b9..92d2000 100644 --- a/src/H5Ofill.c +++ b/src/H5Ofill.c @@ -10,6 +10,7 @@ */ #include "H5private.h" #include "H5Eprivate.h" +#include "H5FLprivate.h" /*Free Lists */ #include "H5Iprivate.h" #include "H5MMprivate.h" #include "H5Oprivate.h" @@ -22,6 +23,7 @@ static herr_t H5O_fill_new_encode(H5F_t *f, uint8_t *p, const void *_mesg); static void *H5O_fill_new_copy(const void *_mesg, void *_dest); static size_t H5O_fill_new_size(H5F_t *f, const void *_mesg); static herr_t H5O_fill_new_reset(void *_mesg); +static herr_t H5O_fill_new_free(void *_mesg); static herr_t H5O_fill_new_debug(H5F_t *f, const void *_mesg, FILE *stream, int indent, int fwidth); @@ -30,6 +32,7 @@ static herr_t H5O_fill_encode(H5F_t *f, uint8_t *p, const void *_mesg); static void *H5O_fill_copy(const void *_mesg, void *_dest); static size_t H5O_fill_size(H5F_t *f, const void *_mesg); static herr_t H5O_fill_reset(void *_mesg); +static herr_t H5O_fill_free(void *_mesg); static herr_t H5O_fill_debug(H5F_t *f, const void *_mesg, FILE *stream, int indent, int fwidth); @@ -43,7 +46,7 @@ const H5O_class_t H5O_FILL[1] = {{ H5O_fill_copy, /*copy the native value */ H5O_fill_size, /*raw message size */ H5O_fill_reset, /*free internal memory */ - NULL, /* free method */ + H5O_fill_free, /* free method */ NULL, /*get share method */ NULL, /*set share method */ H5O_fill_debug, /*debug the message */ @@ -59,7 +62,7 @@ const H5O_class_t H5O_FILL_NEW[1] = {{ H5O_fill_new_copy, /*copy the native value */ H5O_fill_new_size, /*raw message size */ H5O_fill_new_reset, /*free internal memory */ - NULL, /* free method */ + H5O_fill_new_free, /* free method */ NULL, /*get share method */ NULL, /*set share method */ H5O_fill_new_debug, /*debug the message */ @@ -71,6 +74,12 @@ const H5O_class_t H5O_FILL_NEW[1] = {{ static int interface_initialize_g = 0; #define INTERFACE_INIT NULL +/* Declare a free list to manage the H5O_fill_new_t struct */ +H5FL_DEFINE(H5O_fill_new_t); + +/* Declare a free list to manage the H5O_fill_t struct */ +H5FL_DEFINE(H5O_fill_t); + /*------------------------------------------------------------------------- * Function: H5O_fill_new_decode @@ -104,7 +113,7 @@ H5O_fill_new_decode(H5F_t UNUSED *f, const uint8_t *p, assert(p); assert(!sh); - if (NULL==(mesg=H5MM_calloc(sizeof(H5O_fill_new_t)))) + if (NULL==(mesg=H5FL_CALLOC(H5O_fill_new_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value message"); /* Version */ @@ -137,7 +146,7 @@ done: if (!ret_value && mesg) { if(mesg->buf) H5MM_xfree(mesg->buf); - H5MM_xfree(mesg); + H5FL_FREE(H5O_fill_new_t,mesg); } FUNC_LEAVE(ret_value); @@ -173,7 +182,7 @@ H5O_fill_decode(H5F_t UNUSED *f, const uint8_t *p, assert(p); assert(!sh); - if (NULL==(mesg=H5MM_calloc(sizeof(H5O_fill_t)))) + if (NULL==(mesg=H5FL_CALLOC(H5O_fill_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value message"); UINT32DECODE(p, mesg->size); if (mesg->size>0) { @@ -189,7 +198,7 @@ done: if (!ret_value && mesg) { if(mesg->buf) H5MM_xfree(mesg->buf); - H5MM_xfree(mesg); + H5FL_FREE(H5O_fill_t,mesg); } FUNC_LEAVE(ret_value); @@ -311,13 +320,16 @@ H5O_fill_new_copy(const void *_mesg, void *_dest) assert(mesg); - if (!dest && NULL==(dest=H5MM_calloc(sizeof(H5O_fill_new_t)))) + if (!dest && NULL==(dest=H5FL_MALLOC(H5O_fill_new_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill message"); /* Copy data type of fill value */ - if (mesg->type && - NULL==(dest->type=H5T_copy(mesg->type, H5T_COPY_TRANSIENT))) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy fill value data type"); + if (mesg->type) { + if(NULL==(dest->type=H5T_copy(mesg->type, H5T_COPY_TRANSIENT))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy fill value data type"); + } /* end if */ + else + dest->type=NULL; /* Copy fill value and its size */ if (mesg->buf) { @@ -326,7 +338,11 @@ H5O_fill_new_copy(const void *_mesg, void *_dest) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value"); dest->size = mesg->size; HDmemcpy(dest->buf, mesg->buf, (size_t)mesg->size); - } + } /* end if */ + else { + dest->buf=NULL; + dest->size=0; + } /* end else */ /* Copy three fill value attributes */ dest->alloc_time = mesg->alloc_time; @@ -343,7 +359,7 @@ done: if (dest->type) H5T_close(dest->type); if (!_dest) - H5MM_xfree(dest); + H5FL_FREE(H5O_fill_new_t,dest); } FUNC_LEAVE(ret_value); @@ -378,17 +394,24 @@ H5O_fill_copy(const void *_mesg, void *_dest) assert(mesg); - if (!dest && NULL==(dest=H5MM_calloc(sizeof(H5O_fill_t)))) + if (!dest && NULL==(dest=H5FL_CALLOC(H5O_fill_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill message"); - if (mesg->type && - NULL==(dest->type=H5T_copy(mesg->type, H5T_COPY_TRANSIENT))) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy fill value data type"); + + if (mesg->type) { + if(NULL==(dest->type=H5T_copy(mesg->type, H5T_COPY_TRANSIENT))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy fill value data type"); + } /* end if */ + else + dest->type=NULL; + if (mesg->buf) { if (NULL==(dest->buf=H5MM_malloc(mesg->size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value"); dest->size = mesg->size; HDmemcpy(dest->buf, mesg->buf, mesg->size); - } + } /* end if */ + else + dest->buf=NULL; /* Set return value */ ret_value = dest; @@ -400,7 +423,7 @@ done: if (dest->type) H5T_close(dest->type); if (!_dest) - H5MM_xfree(dest); + H5FL_FREE(H5O_fill_t,dest); } FUNC_LEAVE(ret_value); @@ -567,6 +590,66 @@ done: /*------------------------------------------------------------------------- + * Function: H5O_fill_new_free + * + * Purpose: Free's the message + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Thursday, December 5, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_fill_new_free (void *mesg) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_fill_new_free, FAIL); + + assert (mesg); + + H5FL_FREE(H5O_fill_new_t,mesg); + +done: + FUNC_LEAVE (ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_fill_free + * + * Purpose: Free's the message + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Thursday, December 5, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_fill_free (void *mesg) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_fill_free, FAIL); + + assert (mesg); + + H5FL_FREE(H5O_fill_t,mesg); + +done: + FUNC_LEAVE (ret_value); +} + + +/*------------------------------------------------------------------------- * Function: H5O_fill_new_debug * * Purpose: Prints debugging info for the message. @@ -721,7 +804,7 @@ H5O_fill_convert(void *_fill, H5T_t *dset_type) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion"); /* Do the conversion */ - if (H5T_convert(tpath, src_id, dst_id, (hsize_t)1, 0, 0, buf, bkg, H5P_DEFAULT)<0) + if (H5T_convert(tpath, src_id, dst_id, (hsize_t)1, 0, 0, buf, bkg, H5P_DATASET_XFER_DEFAULT)<0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "data type conversion failed"); /* Update the fill message */ diff --git a/src/H5Ofphdf5.c b/src/H5Ofphdf5.c index 5b4afb3..a35d001 100644 --- a/src/H5Ofphdf5.c +++ b/src/H5Ofphdf5.c @@ -107,7 +107,7 @@ H5O_fphdf5_decode(H5F_t *f, const uint8_t *p, H5O_shared_t UNUSED *sh) assert(!sh); /* decode */ - fmeta = H5FL_ALLOC(H5O_fphdf5_t, 1); + fmeta = H5FL_CALLOC(H5O_fphdf5_t); /* decode the OID first */ NBYTEDECODE(p, fmeta->oid, sizeof(fmeta->oid)); @@ -333,7 +333,7 @@ H5O_fphdf5_copy(const void *mesg, void *dest) /* check args */ assert(src); - if (!dst && NULL == (dst = H5FL_ALLOC(H5O_fphdf5_t, 0))) + if (!dst && NULL == (dst = H5FL_MALLOC(H5O_fphdf5_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); /* copy the individual metadata*/ diff --git a/src/H5Olayout.c b/src/H5Olayout.c index 8be6627..41c173e 100644 --- a/src/H5Olayout.c +++ b/src/H5Olayout.c @@ -93,7 +93,7 @@ H5O_layout_decode(H5F_t *f, const uint8_t *p, H5O_shared_t UNUSED *sh) assert (!sh); /* decode */ - if (NULL==(mesg = H5FL_ALLOC(H5O_layout_t,1))) + if (NULL==(mesg = H5FL_CALLOC(H5O_layout_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); /* Version. 1 when space allocated; 2 when space allocation is delayed */ @@ -248,7 +248,7 @@ H5O_layout_copy(const void *_mesg, void *_dest) /* check args */ assert(mesg); - if (!dest && NULL==(dest=H5FL_ALLOC(H5O_layout_t,0))) + if (!dest && NULL==(dest=H5FL_MALLOC(H5O_layout_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); /* copy */ @@ -387,7 +387,7 @@ H5O_layout_reset (void *_mesg) mesg->buf=H5MM_xfree(mesg->buf); /* Reset the message */ - HDmemset(mesg, 0, sizeof(H5O_layout_t)); + mesg->type=H5D_CONTIGUOUS; } /* end if */ done: diff --git a/src/H5Omtime.c b/src/H5Omtime.c index e31dece..ff3eb5a 100644 --- a/src/H5Omtime.c +++ b/src/H5Omtime.c @@ -20,11 +20,16 @@ #define PABLO_MASK H5O_mtime_mask +static void *H5O_mtime_new_decode(H5F_t *f, const uint8_t *p, H5O_shared_t *sh); +static herr_t H5O_mtime_new_encode(H5F_t *f, uint8_t *p, const void *_mesg); +static size_t H5O_mtime_new_size(H5F_t *f, const void *_mesg); + static void *H5O_mtime_decode(H5F_t *f, const uint8_t *p, H5O_shared_t *sh); static herr_t H5O_mtime_encode(H5F_t *f, uint8_t *p, const void *_mesg); static void *H5O_mtime_copy(const void *_mesg, void *_dest); static size_t H5O_mtime_size(H5F_t *f, const void *_mesg); -static herr_t H5O_mtime_free (void *_mesg); +static herr_t H5O_mtime_reset(void *_mesg); +static herr_t H5O_mtime_free(void *_mesg); static herr_t H5O_mtime_debug(H5F_t *f, const void *_mesg, FILE *stream, int indent, int fwidth); @@ -37,8 +42,25 @@ const H5O_class_t H5O_MTIME[1] = {{ H5O_mtime_encode, /*encode message */ H5O_mtime_copy, /*copy the native value */ H5O_mtime_size, /*raw message size */ - NULL, /*free internal memory */ - H5O_mtime_free, /* free method */ + H5O_mtime_reset, /* reset method */ + H5O_mtime_free, /* free method */ + NULL, /*get share method */ + NULL, /*set share method */ + H5O_mtime_debug, /*debug the message */ +}}; + +/* This message derives from H5O */ +/* (Only encode, decode & size routines are different from old mtime routines) */ +const H5O_class_t H5O_MTIME_NEW[1] = {{ + H5O_MTIME_NEW_ID, /*message id number */ + "mtime_new", /*message name for debugging */ + sizeof(time_t), /*native message size */ + H5O_mtime_new_decode, /*decode message */ + H5O_mtime_new_encode, /*encode message */ + H5O_mtime_copy, /*copy the native value */ + H5O_mtime_new_size, /*raw message size */ + H5O_mtime_reset, /* reset method */ + H5O_mtime_free, /* free method */ NULL, /*get share method */ NULL, /*set share method */ H5O_mtime_debug, /*debug the message */ @@ -48,11 +70,74 @@ const H5O_class_t H5O_MTIME[1] = {{ static int interface_initialize_g = 0; #define INTERFACE_INIT NULL +/* Current version of new mtime information */ +#define H5O_MTIME_VERSION 1 + +/* Track whether tzset routine was called */ +static int ntzset=0; + /* Declare a free list to manage the time_t struct */ H5FL_DEFINE(time_t); /*------------------------------------------------------------------------- + * Function: H5O_mtime_new_decode + * + * Purpose: Decode a new modification time message and return a pointer to a + * new time_t value. + * + * Return: Success: Ptr to new message in native struct. + * + * Failure: NULL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Jan 3 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void * +H5O_mtime_new_decode(H5F_t UNUSED *f, const uint8_t *p, + H5O_shared_t UNUSED *sh) +{ + time_t *mesg, the_time; + int version; /* Version of mtime information */ + void *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_mtime_new_decode, NULL); + + /* check args */ + assert(f); + assert(p); + assert (!sh); + + /* decode */ + version = *p++; + if(version!=H5O_MTIME_VERSION) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for mtime message"); + + /* Skip reserved bytes */ + p+=3; + + /* Get the time_t from the file */ + UINT32DECODE(p, the_time); + + /* The return value */ + if (NULL==(mesg = H5FL_MALLOC(time_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + *mesg = the_time; + + /* Set return value */ + ret_value=mesg; + +done: + FUNC_LEAVE(ret_value); +} /* end H5O_mtime_new_decode() */ + + +/*------------------------------------------------------------------------- * Function: H5O_mtime_decode * * Purpose: Decode a modification time message and return a pointer to a @@ -77,7 +162,6 @@ H5O_mtime_decode(H5F_t UNUSED *f, const uint8_t *p, time_t *mesg, the_time; int i; struct tm tm; - static int ncalls=0; void *ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5O_mtime_decode, NULL); @@ -88,7 +172,10 @@ H5O_mtime_decode(H5F_t UNUSED *f, const uint8_t *p, assert (!sh); /* Initialize time zone information */ - if (0==ncalls++) HDtzset(); + if (!ntzset) { + HDtzset(); + ntzset=1; + } /* end if */ /* decode */ for (i=0; i<14; i++) { @@ -166,7 +253,7 @@ H5O_mtime_decode(H5F_t UNUSED *f, const uint8_t *p, #endif /* The return value */ - if (NULL==(mesg = H5FL_ALLOC(time_t,1))) + if (NULL==(mesg = H5FL_MALLOC(time_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); *mesg = the_time; @@ -179,6 +266,50 @@ done: /*------------------------------------------------------------------------- + * Function: H5O_mtime_new_encode + * + * Purpose: Encodes a new modification time message. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Jan 3 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_mtime_new_encode(H5F_t UNUSED *f, uint8_t *p, const void *_mesg) +{ + const time_t *mesg = (const time_t *) _mesg; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_mtime_new_encode, FAIL); + + /* check args */ + assert(f); + assert(p); + assert(mesg); + + /* Version */ + *p++ = H5O_MTIME_VERSION; + + /* Reserved bytes */ + *p++ = 0; + *p++ = 0; + *p++ = 0; + + /* Encode time */ + UINT32ENCODE(p, *mesg); + +done: + FUNC_LEAVE(ret_value); +} /* end H5O_mtime_new_encode() */ + + +/*------------------------------------------------------------------------- * Function: H5O_mtime_encode * * Purpose: Encodes a modification time message. @@ -247,7 +378,7 @@ H5O_mtime_copy(const void *_mesg, void *_dest) /* check args */ assert(mesg); - if (!dest && NULL==(dest = H5FL_ALLOC(time_t,0))) + if (!dest && NULL==(dest = H5FL_MALLOC(time_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); /* copy */ @@ -262,6 +393,42 @@ done: /*------------------------------------------------------------------------- + * Function: H5O_mtime_new_size + * + * Purpose: Returns the size of the raw message in bytes not + * counting the message type or size fields, but only the data + * fields. This function doesn't take into account + * alignment. + * + * Return: Success: Message data size in bytes w/o alignment. + * + * Failure: 0 + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Jan 3 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static size_t +H5O_mtime_new_size(H5F_t * UNUSED f, const void * UNUSED mesg) +{ + size_t ret_value=8; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_mtime_new_size, 0); + + /* check args */ + assert(f); + assert(mesg); + +done: + FUNC_LEAVE(ret_value); +} /* end H5O_mtime_new_size() */ + + +/*------------------------------------------------------------------------- * Function: H5O_mtime_size * * Purpose: Returns the size of the raw message in bytes not @@ -298,6 +465,33 @@ done: /*------------------------------------------------------------------------- + * Function: H5O_mtime_reset + * + * Purpose: Frees resources within a modification time message, but doesn't free + * the message itself. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Mondey, December 23, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_mtime_reset(void UNUSED *_mesg) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_mtime_reset, FAIL); + +done: + FUNC_LEAVE(ret_value); +} + + +/*------------------------------------------------------------------------- * Function: H5O_mtime_free * * Purpose: Free's the message diff --git a/src/H5Opline.c b/src/H5Opline.c new file mode 100644 index 0000000..eb42f5b --- /dev/null +++ b/src/H5Opline.c @@ -0,0 +1,493 @@ +/* + * Copyright (C) 1998-2001 NCSA + * All rights reserved. + * + * Programmer: Robb Matzke + * Wednesday, April 15, 1998 + * + * Purpose: Data filter pipeline message. + */ +#include "H5private.h" +#include "H5Eprivate.h" +#include "H5FLprivate.h" /*Free Lists */ +#include "H5MMprivate.h" +#include "H5Oprivate.h" + +/* Interface initialization */ +#define PABLO_MASK H5O_pline_mask +static int interface_initialize_g = 0; +#define INTERFACE_INIT NULL + +#define H5O_PLINE_VERSION 1 + +static herr_t H5O_pline_encode (H5F_t *f, uint8_t *p, const void *mesg); +static void *H5O_pline_decode (H5F_t *f, const uint8_t *p, H5O_shared_t *sh); +static void *H5O_pline_copy (const void *_mesg, void *_dest); +static size_t H5O_pline_size (H5F_t *f, const void *_mesg); +static herr_t H5O_pline_reset (void *_mesg); +static herr_t H5O_pline_free (void *_mesg); +static herr_t H5O_pline_debug (H5F_t *f, const void *_mesg, + FILE * stream, int indent, int fwidth); + +/* This message derives from H5O */ +const H5O_class_t H5O_PLINE[1] = {{ + H5O_PLINE_ID, /* message id number */ + "filter pipeline", /* message name for debugging */ + sizeof(H5O_pline_t), /* native message size */ + H5O_pline_decode, /* decode message */ + H5O_pline_encode, /* encode message */ + H5O_pline_copy, /* copy the native value */ + H5O_pline_size, /* size of raw message */ + H5O_pline_reset, /* reset method */ + H5O_pline_free, /* free method */ + NULL, /* get share method */ + NULL, /* set share method */ + H5O_pline_debug, /* debug the message */ +}}; + + +/* Declare a free list to manage the H5O_pline_t struct */ +H5FL_DEFINE(H5O_pline_t); + + +/*------------------------------------------------------------------------- + * Function: H5O_pline_decode + * + * Purpose: Decodes a filter pipeline message. + * + * Return: Success: Ptr to the native message. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * Wednesday, April 15, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void * +H5O_pline_decode(H5F_t UNUSED *f, const uint8_t *p, + H5O_shared_t UNUSED *sh) +{ + H5O_pline_t *pline = NULL; + void *ret_value; + unsigned version; + size_t i, j, n, name_length; + + FUNC_ENTER_NOAPI(H5O_pline_decode, NULL); + + /* check args */ + assert(p); + + /* Decode */ + if (NULL==(pline = H5FL_CALLOC(H5O_pline_t))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + version = *p++; + if (version!=H5O_PLINE_VERSION) + HGOTO_ERROR(H5E_PLINE, H5E_CANTLOAD, NULL, "bad version number for filter pipeline message"); + pline->nfilters = *p++; + if (pline->nfilters>32) + HGOTO_ERROR(H5E_PLINE, H5E_CANTLOAD, NULL, "filter pipeline message has too many filters"); + p += 6; /*reserved*/ + pline->nalloc = pline->nfilters; + pline->filter = H5MM_calloc(pline->nalloc*sizeof(pline->filter[0])); + if (NULL==pline->filter) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + for (i=0; infilters; i++) { + UINT16DECODE(p, pline->filter[i].id); + UINT16DECODE(p, name_length); + if (name_length % 8) + HGOTO_ERROR(H5E_PLINE, H5E_CANTLOAD, NULL, "filter name length is not a multiple of eight"); + UINT16DECODE(p, pline->filter[i].flags); + UINT16DECODE(p, pline->filter[i].cd_nelmts); + if (name_length) { + /* + * Get the name, allocating an extra byte for an extra null + * terminator just in case there isn't one in the file (there + * should be, but to be safe...) + */ + pline->filter[i].name = H5MM_malloc(name_length+1); + HDmemcpy(pline->filter[i].name, p, name_length); + pline->filter[i].name[name_length] = '\0'; + p += name_length; + } + if ((n=pline->filter[i].cd_nelmts)) { + /* + * Read the client data values and the padding + */ + pline->filter[i].cd_values = H5MM_malloc(n*sizeof(unsigned)); + if (NULL==pline->filter[i].cd_values) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for client data"); + for (j=0; jfilter[i].cd_nelmts; j++) + UINT32DECODE(p, pline->filter[i].cd_values[j]); + if (pline->filter[i].cd_nelmts % 2) + p += 4; /*padding*/ + } + } + + /* Set return value */ + ret_value = pline; + +done: + if (NULL==ret_value && pline) { + if (pline->filter) { + for (i=0; infilters; i++) { + H5MM_xfree(pline->filter[i].name); + H5MM_xfree(pline->filter[i].cd_values); + } + H5MM_xfree(pline->filter); + } + H5FL_FREE(H5O_pline_t,pline); + } + + FUNC_LEAVE(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_pline_encode + * + * Purpose: Encodes message MESG into buffer P. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Wednesday, April 15, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_pline_encode (H5F_t UNUSED *f, uint8_t *p/*out*/, const void *mesg) +{ + const H5O_pline_t *pline = (const H5O_pline_t*)mesg; + size_t i, j, name_length; + const char *name=NULL; + H5Z_class_t *cls=NULL; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_pline_encode, FAIL); + + /* Check args */ + assert (p); + assert (mesg); + + *p++ = H5O_PLINE_VERSION; + *p++ = (uint8_t)(pline->nfilters); + *p++ = 0; /*reserved 1*/ + *p++ = 0; /*reserved 2*/ + *p++ = 0; /*reserved 3*/ + *p++ = 0; /*reserved 4*/ + *p++ = 0; /*reserved 5*/ + *p++ = 0; /*reserved 6*/ + + for (i=0; infilters; i++) { + /* + * Get the filter name. If the pipeline message has a name in it then + * use that one. Otherwise try to look up the filter and get the name + * as it was registered. + */ + if (NULL==(name=pline->filter[i].name) && + (cls=H5Z_find(pline->filter[i].id))) + name = cls->name; + name_length = name ? HDstrlen(name)+1 : 0; + + /* Encode the filter */ + UINT16ENCODE(p, pline->filter[i].id); + UINT16ENCODE(p, H5O_ALIGN(name_length)); + UINT16ENCODE(p, pline->filter[i].flags); + UINT16ENCODE(p, pline->filter[i].cd_nelmts); + if (name_length>0) { + HDmemcpy(p, name, name_length); + p += name_length; + while (name_length++ % 8) + *p++ = 0; + } + for (j=0; jfilter[i].cd_nelmts; j++) + UINT32ENCODE(p, pline->filter[i].cd_values[j]); + if (pline->filter[i].cd_nelmts % 2) + UINT32ENCODE(p, 0); + } + +done: + FUNC_LEAVE (ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_pline_copy + * + * Purpose: Copies a filter pipeline message from SRC to DST allocating + * DST if necessary. If DST is already allocated then we assume + * that it isn't initialized. + * + * Return: Success: Ptr to DST or allocated result. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * Wednesday, April 15, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void * +H5O_pline_copy (const void *_src, void *_dst/*out*/) +{ + const H5O_pline_t *src = (const H5O_pline_t *)_src; + H5O_pline_t *dst = (H5O_pline_t *)_dst; + size_t i; + H5O_pline_t *ret_value = NULL; + + FUNC_ENTER_NOAPI(H5O_pline_copy, NULL); + + if (!dst && NULL==(dst = H5FL_MALLOC (H5O_pline_t))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + + *dst = *src; + dst->nalloc = dst->nfilters; + if (dst->nalloc>0) { + dst->filter = H5MM_calloc(dst->nalloc * sizeof(dst->filter[0])); + if (NULL==dst->filter) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + } else { + dst->filter = NULL; + } + + for (i=0; infilters; i++) { + dst->filter[i] = src->filter[i]; + if (src->filter[i].name) { + dst->filter[i].name = H5MM_xstrdup(src->filter[i].name); + } + if (src->filter[i].cd_nelmts>0) { + dst->filter[i].cd_values = H5MM_malloc(src->filter[i].cd_nelmts* + sizeof(unsigned)); + if (NULL==dst->filter[i].cd_values) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + HDmemcpy (dst->filter[i].cd_values, src->filter[i].cd_values, + src->filter[i].cd_nelmts * sizeof(unsigned)); + } + } + + /* Set return value */ + ret_value = dst; + +done: + if (!ret_value && dst) { + if (dst->filter) { + for (i=0; infilters; i++) { + H5MM_xfree(dst->filter[i].name); + H5MM_xfree(dst->filter[i].cd_values); + } + H5MM_xfree(dst->filter); + } + if (!_dst) + H5FL_FREE(H5O_pline_t,dst); + } + + FUNC_LEAVE (ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_pline_size + * + * Purpose: Determines the size of a raw filter pipeline message. + * + * Return: Success: Size of message. + * + * Failure: zero + * + * Programmer: Robb Matzke + * Wednesday, April 15, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static size_t +H5O_pline_size (H5F_t UNUSED *f, const void *mesg) +{ + const H5O_pline_t *pline = (const H5O_pline_t*)mesg; + size_t i, size, name_len; + const char *name = NULL; + H5Z_class_t *cls = NULL; + size_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_pline_size, 0); + + /* Message header */ + size = 1 + /*version */ + 1 + /*number of filters */ + 6; /*reserved */ + + for (i=0; infilters; i++) { + /* Get the name of the filter, same as done with H5O_pline_encode() */ + if (NULL==(name=pline->filter[i].name) && + (cls=H5Z_find(pline->filter[i].id))) + name = cls->name; + name_len = name ? HDstrlen(name)+1 : 0; + + + size += 2 + /*filter identification number */ + 2 + /*name length */ + 2 + /*flags */ + 2 + /*number of client data values */ + H5O_ALIGN(name_len); /*length of the filter name */ + + size += pline->filter[i].cd_nelmts * 4; + if (pline->filter[i].cd_nelmts % 2) + size += 4; + } + + /* Set return value */ + ret_value=size; + +done: + FUNC_LEAVE (ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_pline_reset + * + * Purpose: Resets a filter pipeline message by clearing all filters. + * The MESG buffer is not freed. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Wednesday, April 15, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_pline_reset (void *mesg) +{ + H5O_pline_t *pline = (H5O_pline_t*)mesg; + size_t i; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_pline_reset, FAIL); + + assert (pline); + + for (i=0; infilters; i++) { + H5MM_xfree(pline->filter[i].name); + H5MM_xfree(pline->filter[i].cd_values); + } + if(pline->filter) + H5MM_xfree(pline->filter); + HDmemset(pline, 0, sizeof *pline); + +done: + FUNC_LEAVE (ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_pline_free + * + * Purpose: Free's the message + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Saturday, March 11, 2000 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_pline_free (void *mesg) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_pline_free, FAIL); + + assert (mesg); + + H5FL_FREE(H5O_pline_t,mesg); + +done: + FUNC_LEAVE (ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_pline_debug + * + * Purpose: Prints debugging information for filter pipeline message MESG + * on output stream STREAM. Each line is indented INDENT + * characters and the field name takes up FWIDTH characters. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Wednesday, April 15, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_pline_debug (H5F_t UNUSED *f, const void *mesg, FILE *stream, + int indent, int fwidth) +{ + const H5O_pline_t *pline = (const H5O_pline_t *)mesg; + size_t i, j; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_pline_debug, FAIL); + + /* check args */ + assert(f); + assert(pline); + assert(stream); + assert(indent >= 0); + assert(fwidth >= 0); + + fprintf(stream, "%*s%-*s %lu/%lu\n", indent, "", fwidth, + "Number of filters:", + (unsigned long)(pline->nfilters), + (unsigned long)(pline->nalloc)); + + for (i=0; infilters; i++) { + char name[32]; + sprintf(name, "Filter at position %lu", (unsigned long)i); + fprintf(stream, "%*s%-*s\n", indent, "", fwidth, name); + fprintf(stream, "%*s%-*s 0x%04x\n", indent+3, "", MAX(0, fwidth-3), + "Filter identification:", + (unsigned)(pline->filter[i].id)); + if (pline->filter[i].name) { + fprintf(stream, "%*s%-*s \"%s\"\n", indent+3, "", MAX(0, fwidth-3), + "Filter name:", + pline->filter[i].name); + } else { + fprintf(stream, "%*s%-*s NONE\n", indent+3, "", MAX(0, fwidth-3), + "Filter name:"); + } + fprintf(stream, "%*s%-*s 0x%04x\n", indent+3, "", MAX(0, fwidth-3), + "Flags:", + (unsigned)(pline->filter[i].flags)); + fprintf(stream, "%*s%-*s %lu\n", indent+3, "", MAX(0, fwidth-3), + "Num CD values:", + (unsigned long)(pline->filter[i].cd_nelmts)); + for (j=0; jfilter[i].cd_nelmts; j++) { + char field_name[32]; + sprintf(field_name, "CD value %lu", (unsigned long)j); + fprintf(stream, "%*s%-*s %lu\n", indent+6, "", MAX(0, fwidth-6), + field_name, + (unsigned long)(pline->filter[i].cd_values[j])); + } + } + +done: + FUNC_LEAVE(ret_value); +} diff --git a/src/H5Oplist.c b/src/H5Oplist.c index 554d0b7..352df06 100644 --- a/src/H5Oplist.c +++ b/src/H5Oplist.c @@ -65,6 +65,12 @@ static int interface_initialize_g = 0; /* Declare external the free list for hsize_t arrays */ H5FL_ARR_EXTERN(hsize_t); +/* Declare the external free list for the H5P_genprop_t struct */ +H5FL_EXTERN(H5P_genprop_t); + +/* Declare the external free list for the H5P_genplist_t struct */ +H5FL_EXTERN(H5P_genplist_t); + #define UINT_ENCODE(dst, src) \ if (sizeof(src) == 2) { \ UINT16ENCODE(dst, src); \ @@ -131,7 +137,7 @@ H5O_plist_decode(H5F_t UNUSED *f, const uint8_t *p, H5O_shared_t UNUSED *sh) H5P_genclass_t *pclass; /* property list class to modify */ hid_t new_plist_id; /* property list ID of new list created */ int version; /* message version number */ - unsigned int i, nprops, hashsize; + unsigned int i, nprops; void *ret_value; FUNC_ENTER_NOAPI(H5O_plist_decode, NULL); @@ -169,11 +175,9 @@ H5O_plist_decode(H5F_t UNUSED *f, const uint8_t *p, H5O_shared_t UNUSED *sh) ++p; UINT_DECODE(p, nprops); - UINT_DECODE(p, hashsize); /* Allocate new property list */ - if ((new_plist = H5MM_calloc(sizeof(H5P_genplist_t) + - ((hashsize - 1) * sizeof(H5P_genprop_t *)))) == NULL) + if ((new_plist = H5FL_CALLOC(H5P_genplist_t)) == NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); /* Initialize new property list */ @@ -183,7 +187,11 @@ H5O_plist_decode(H5F_t UNUSED *f, const uint8_t *p, H5O_shared_t UNUSED *sh) new_plist->class_init = 0; /* Initially, wait until the class callback finishes to set */ - /* Create new property list */ + /* Initialize the TBBT to hold the properties */ + if((new_plist->props=H5TB_fast_dmake(H5TB_FAST_STR_COMPARE))==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTMAKETREE,NULL,"can't create TBBT for properties"); + + /* Insert properties into property list */ for (i = 0; i < nprops; ++i) { H5P_genprop_t *tprop; unsigned str_len; @@ -192,35 +200,19 @@ H5O_plist_decode(H5F_t UNUSED *f, const uint8_t *p, H5O_shared_t UNUSED *sh) * Allocate and initialize the property structure which is going * to hold the information we're reading in. */ - if (NULL == (tprop = H5MM_malloc(sizeof(H5P_genprop_t)))) + if (NULL == (tprop = H5FL_CALLOC(H5P_genprop_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - tprop->create = NULL; - tprop->def_value = NULL; - tprop->set = NULL; - tprop->get = NULL; - tprop->del = NULL; - tprop->copy = NULL; - tprop->close = NULL; - tprop->next = NULL; - - /* Grab the XORed value of the name and get the length of the name */ - UINT_DECODE(p, tprop->xor_val); + /* Grab the length of the name */ UINT_DECODE(p, str_len); - if (str_len) { - /* If there is a name, allocate space for it and copy */ - if (NULL == (tprop->name = H5MM_malloc(str_len + 1))) { - H5MM_xfree(tprop); - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - } - - HDmemcpy(tprop->name, p, str_len + 1); - p += str_len + 1; - } else { - tprop->name = NULL; - ++p; + /* Allocate space for the name and copy it */ + if (NULL == (tprop->name = H5MM_malloc(str_len + 1))) { + H5FL_FREE(H5P_genprop_t,tprop); + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); } + HDmemcpy(tprop->name, p, str_len + 1); + p += str_len + 1; /* Grab the size of the "value" data */ UINT_DECODE(p, tprop->size); @@ -228,18 +220,21 @@ H5O_plist_decode(H5F_t UNUSED *f, const uint8_t *p, H5O_shared_t UNUSED *sh) /* Allocate and memcpy the value part of the property. */ if ((tprop->value = H5MM_malloc(tprop->size)) == NULL) { H5MM_xfree(tprop->name); - H5MM_xfree(tprop); + H5FL_FREE(H5P_genprop_t,tprop); HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); } HDmemcpy(tprop->value, p, tprop->size); p += tprop->size; + /* Set the property's type */ + tprop->type=H5P_PROP_WITHIN_LIST; + /* Insert the initialized property into the property list */ - if (H5P_add_prop(new_plist->props, new_plist->pclass->hashsize, tprop) < 0) { + if (H5P_add_prop(new_plist->props, tprop) < 0) { H5MM_xfree(tprop->value); H5MM_xfree(tprop->name); - H5MM_xfree(tprop); + H5FL_FREE(H5P_genprop_t,tprop); HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, NULL, "Can't insert property into list"); } @@ -292,9 +287,8 @@ static herr_t H5O_plist_encode(H5F_t UNUSED *f, uint8_t *p, const void *mesg) { const H5P_genplist_t *plist = (const H5P_genplist_t *)mesg; + char *class_path; /* Pointer to class path generated for property list */ herr_t ret_value = SUCCEED; - unsigned int i; - char *class_path; FUNC_ENTER_NOAPI(H5O_plist_encode, FAIL); @@ -333,45 +327,47 @@ H5O_plist_encode(H5F_t UNUSED *f, uint8_t *p, const void *mesg) HDfree(class_path); UINT_ENCODE(p, plist->nprops); - UINT_ENCODE(p, plist->pclass->hashsize); - for (i = 0; i < plist->pclass->hashsize; ++i) { - H5P_genprop_t *tprop = plist->props[i]; + /* Encode the properties for this property list */ + if(plist->nprops>0) { + H5TB_NODE *curr_node; /* Current node in TBBT */ + H5P_genprop_t *tprop; /* Pointer to property */ + + /* Walk through the properties in the old class */ + curr_node=H5TB_first(plist->props->root); + while(curr_node!=NULL) { + size_t s; /* Length of property name */ - /* Walk through the list of properties at each hash location */ - while (tprop) { - const char *n = tprop->name; + /* Get a pointer to the property from the node */ + tprop=curr_node->data; + assert(tprop->name); /* Properties are guaranteed to have names */ /* * Copy the meat of the generic property: * - * 1. The XORed version of the name + * 1. The length of the property name * 2. The name of the property * 3. The size of the property value * 4. The property value */ - UINT_ENCODE(p, tprop->xor_val); - if (n && *n) { - size_t s = HDstrlen(n); + /* Get the name's length & encode it */ + s = HDstrlen(tprop->name); + UINT_ENCODE(p, s); - UINT_ENCODE(p, s); - HDmemcpy(p, n, s + 1); - p += s + 1; - } else { - /* if there isn't a name, put a NULL there */ - UINT_ENCODE(p, 0u); - *p++ = '\0'; - } + /* Encode the name itself */ + HDmemcpy(p, tprop->name, s + 1); + p += s + 1; + /* Encode the property value's size & data */ UINT_ENCODE(p, tprop->size); HDmemcpy(p, tprop->value, tprop->size); p += tprop->size; - /* Go to next registered property in class */ - tprop = tprop->next; - } - } + /* Get the next property node in the TBBT */ + curr_node=H5TB_next(curr_node); + } /* end while */ + } /* end if */ done: FUNC_LEAVE(ret_value); @@ -398,37 +394,17 @@ static size_t H5O_plist_size(H5F_t UNUSED *f, const void *mesg) { const H5P_genplist_t *plist = (const H5P_genplist_t *)mesg; - const H5P_genclass_t *pclass; + char *class_path=NULL; /* Pointer to class path generated for property list */ size_t ret_value; - char *class_path = NULL; - unsigned i; FUNC_ENTER_NOAPI(H5O_plist_size, 0); /* check args */ assert(plist); - ret_value = 2 + /*version info */ + ret_value = 1 + /*version info */ 1; /*reserved */ - /* - * Loop through the class and its parent(s) to gather the complete - * length of the name. The class name encoded will look like: - * - * DerivedClass/ParentClass/.../BaseClass - */ - pclass = plist->pclass; - - while (pclass) { - if (pclass->name) - ret_value += HDstrlen(pclass->name);/*length of class name */ - - if ((pclass = pclass->parent) != NULL) - ++ret_value; /*separating "/" */ - } - - ++ret_value; /*terminating NULL */ - class_path = H5P_get_class_path(plist->pclass); if (class_path) @@ -437,31 +413,29 @@ H5O_plist_size(H5F_t UNUSED *f, const void *mesg) ++ret_value; HDfree(class_path); - ret_value += sizeof(plist->nprops) + /*num properties */ - sizeof(plist->pclass->hashsize); /*hash size */ - for (i = 0; i < plist->pclass->hashsize; ++i) { - H5P_genprop_t *tprop = plist->props[i]; + ret_value += sizeof(plist->nprops); /*num properties */ - /* Walk through the list of properties at each hash location */ - while (tprop) { - const char *n = tprop->name; + /* Calculate the size of the properties for this property list */ + if(plist->nprops>0) { + H5TB_NODE *curr_node; /* Current node in TBBT */ + H5P_genprop_t *tprop; /* Pointer to property */ - ret_value += sizeof(tprop->xor_val) + /*xored value */ - sizeof(size_t); /*length of the name */ + /* Walk through the properties in the old class */ + curr_node=H5TB_first(plist->props->root); + while(curr_node!=NULL) { + /* Get a pointer to the property from the node */ + tprop=curr_node->data; - if (n && *n) - ret_value += HDstrlen(n) + 1; /*the name */ - else - ++ret_value; /*the name: NULL */ + ret_value += sizeof(size_t); /*length of the name */ + ret_value += HDstrlen(tprop->name) + 1; /*the name */ + ret_value += sizeof(tprop->size) + /*size of data size */ + tprop->size; /*the data */ - ret_value += sizeof(tprop->size) + /*size of data size */ - tprop->size; /*the data */ - - /* Go to next registered property in class */ - tprop = tprop->next; - } - } + /* Get the next property node in the TBBT */ + curr_node=H5TB_next(curr_node); + } /* end while */ + } /* end if */ done: FUNC_LEAVE(ret_value); @@ -513,8 +487,7 @@ H5O_plist_debug(H5F_t UNUSED *f, const void *mesg, FILE *stream, int indent, int fwidth) { const H5P_genplist_t *plist = (const H5P_genplist_t *)mesg; - herr_t ret_value = SUCCEED; - unsigned int i; + herr_t ret_value=SUCCEED; FUNC_ENTER_NOAPI(H5O_plist_debug, FAIL); @@ -531,27 +504,30 @@ H5O_plist_debug(H5F_t UNUSED *f, const void *mesg, FILE *stream, HDfprintf(stream, "%*sProperties {\n", indent, ""); indent += 2; - for (i = 0; i < plist->pclass->hashsize; ++i) { - H5P_genprop_t *tprop = plist->props[i]; + /* Calculate the size of the properties for this property list */ + if(plist->nprops>0) { + H5TB_NODE *curr_node; /* Current node in TBBT */ + H5P_genprop_t *tprop; /* Pointer to property */ - /* Walk through the list of properties at each hash location */ - while (tprop) { + /* Walk through the properties in the old class */ + curr_node=H5TB_first(plist->props->root); + while(curr_node!=NULL) { register unsigned int j; + /* Get a pointer to the property from the node */ + tprop=curr_node->data; + HDfprintf(stream, "%*sProperty {\n", indent, ""); indent += 2; /* - * Copy the meat of the generic property: + * Print the meat of the generic property: * * 1. The name of the property - * 2. The XORed version of the name - * 3. The size of the property value - * 4. The property value + * 2. The size of the property value + * 3. The property value */ - HDfprintf(stream, "%*sName: ", indent, ""); - HDfprintf(stream, "%s\n", tprop->name ? tprop->name : "(null)"); - HDfprintf(stream, "%*sXOR Value: %d\n", indent, "", tprop->xor_val); + HDfprintf(stream, "%*sName: %s\n", indent, "", tprop->name); HDfprintf(stream, "%*sValue Size: %d\n", indent, "", tprop->size); HDfprintf(stream, "%*sValue: ", indent, ""); @@ -561,10 +537,10 @@ H5O_plist_debug(H5F_t UNUSED *f, const void *mesg, FILE *stream, indent -= 2; HDfprintf(stream, "\n%*s}\n", indent, ""); - /* Go to next registered property in class */ - tprop = tprop->next; - } - } + /* Get the next property node in the TBBT */ + curr_node=H5TB_next(curr_node); + } /* end while */ + } /* end if */ indent -= 2; HDfprintf(stream, "%*s}\n", indent, ""); diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index 00b9e8f..651dbca 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -91,7 +91,7 @@ typedef struct H5O_class_t { herr_t (*reset)(void *); /*free nested data structs */ herr_t (*free)(void *); /*free main data struct */ herr_t (*get_share)(H5F_t*, const void*, struct H5O_shared_t*); - herr_t (*set_share)(H5F_t*, void*, const struct H5O_shared_t*); + herr_t (*set_share)(H5F_t*, void*, const struct H5O_shared_t*); herr_t (*debug)(H5F_t*, const void*, FILE*, int, int); } H5O_class_t; @@ -116,14 +116,14 @@ typedef struct H5O_t { H5AC_info_t cache_info; /* Information for H5AC cache functions, _must_ be */ /* first field in structure */ hbool_t dirty; /*out of data wrt disk */ - int version; /*version number */ - int nlink; /*link count */ + int version; /*version number */ + int nlink; /*link count */ unsigned nmesgs; /*number of messages */ - unsigned alloc_nmesgs; /*number of message slots */ - H5O_mesg_t *mesg; /*array of messages */ + unsigned alloc_nmesgs; /*number of message slots */ + H5O_mesg_t *mesg; /*array of messages */ unsigned nchunks; /*number of chunks */ - unsigned alloc_nchunks; /*chunks allocated */ - H5O_chunk_t *chunk; /*array of chunks */ + unsigned alloc_nchunks; /*chunks allocated */ + H5O_chunk_t *chunk; /*array of chunks */ } H5O_t; /* @@ -194,9 +194,9 @@ typedef struct H5O_efl_entry_t { typedef struct H5O_efl_t { haddr_t heap_addr; /*address of name heap */ - int nalloc; /*number of slots allocated */ - int nused; /*number of slots used */ - H5O_efl_entry_t *slot; /*array of external file entries */ + int nalloc; /*number of slots allocated */ + int nused; /*number of slots used */ + H5O_efl_entry_t *slot; /*array of external file entries */ } H5O_efl_t; /* @@ -227,10 +227,10 @@ typedef struct H5O_pline_t { size_t nalloc; /*num elements in `filter' array */ struct { H5Z_filter_t id; /*filter identification number */ - unsigned flags; /*defn and invocation flags */ + unsigned flags; /*defn and invocation flags */ char *name; /*optional filter name */ size_t cd_nelmts; /*number of elements in cd_values[] */ - unsigned *cd_values; /*client data values */ + unsigned *cd_values; /*client data values */ } *filter; /*array of filters */ } H5O_pline_t; @@ -303,9 +303,15 @@ typedef struct H5O_stab_t { } H5O_stab_t; /* + * Modification time message (new format on disk). The message is just a `time_t'. + */ +#define H5O_MTIME_NEW_ID 0x0012 +H5_DLLVAR const H5O_class_t H5O_MTIME_NEW[1]; + +/* * Generic property list message. */ -#define H5O_PLIST_ID 0x0012 +#define H5O_PLIST_ID 0x0013 H5_DLLVAR const H5O_class_t H5O_PLIST[1]; /* operates on an H5P_genplist_t struct */ @@ -314,7 +320,7 @@ H5_DLLVAR const H5O_class_t H5O_PLIST[1]; /* * Flexible parallel message */ -#define H5O_FPHDF5_ID 0x0013 +#define H5O_FPHDF5_ID 0x0014 H5_DLLVAR const H5O_class_t H5O_FPHDF5[1]; struct H5S_simple_t; @@ -349,8 +355,13 @@ H5_DLL htri_t H5O_exists(H5G_entry_t *ent, const H5O_class_t *type, H5_DLL void *H5O_read(H5G_entry_t *ent, const H5O_class_t *type, int sequence, void *mesg); H5_DLL int H5O_modify(H5G_entry_t *ent, const H5O_class_t *type, - int overwrite, unsigned flags, const void *mesg); + int overwrite, unsigned flags, unsigned update_time, const void *mesg); +H5_DLL H5O_t * H5O_protect(H5G_entry_t *ent); +H5_DLL herr_t H5O_unprotect(H5G_entry_t *ent, H5O_t *oh); +H5_DLL int H5O_append(H5F_t *f, H5O_t *oh, const H5O_class_t *type, + unsigned flags, const void *mesg); H5_DLL herr_t H5O_touch(H5G_entry_t *ent, hbool_t force); +H5_DLL herr_t H5O_touch_oh(H5F_t *f, H5O_t *oh, hbool_t force); H5_DLL herr_t H5O_remove(H5G_entry_t *ent, const H5O_class_t *type, int sequence); H5_DLL herr_t H5O_reset(const H5O_class_t *type, void *native); diff --git a/src/H5Osdspace.c b/src/H5Osdspace.c index 1ff3a18..6114e51 100644 --- a/src/H5Osdspace.c +++ b/src/H5Osdspace.c @@ -44,7 +44,7 @@ const H5O_class_t H5O_SDSPACE[1] = {{ H5O_sdspace_copy, /* copy the native value */ H5O_sdspace_size, /* size of symbol table entry */ H5O_sdspace_reset, /* default reset method */ - H5O_sdspace_free, /* free method */ + H5O_sdspace_free, /* free method */ NULL, /* get share method */ NULL, /* set share method */ H5O_sdspace_debug, /* debug the message */ @@ -105,7 +105,7 @@ H5O_sdspace_decode(H5F_t *f, const uint8_t *p, H5O_shared_t UNUSED *sh) assert (!sh); /* decode */ - if ((sdim = H5FL_ALLOC(H5S_simple_t,1)) != NULL) { + if ((sdim = H5FL_CALLOC(H5S_simple_t)) != NULL) { version = *p++; if (version!=H5O_SDSPACE_VERSION) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "wrong version number in data space message"); @@ -116,19 +116,19 @@ H5O_sdspace_decode(H5F_t *f, const uint8_t *p, H5O_shared_t UNUSED *sh) p += 5; /*reserved*/ if (sdim->rank > 0) { - if (NULL==(sdim->size=H5FL_ARR_ALLOC(hsize_t,sdim->rank,0))) + if (NULL==(sdim->size=H5FL_ARR_MALLOC(hsize_t,sdim->rank))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); for (u = 0; u < sdim->rank; u++) H5F_DECODE_LENGTH (f, p, sdim->size[u]); if (flags & H5S_VALID_MAX) { - if (NULL==(sdim->max=H5FL_ARR_ALLOC(hsize_t,sdim->rank,0))) + if (NULL==(sdim->max=H5FL_ARR_MALLOC(hsize_t,sdim->rank))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); for (u = 0; u < sdim->rank; u++) H5F_DECODE_LENGTH (f, p, sdim->max[u]); } #ifdef LATER if (flags & H5S_VALID_PERM) { - if (NULL==(sdim->perm=H5FL_ARR_ALLOC(hsize_t,sdim->rank,0))) + if (NULL==(sdim->perm=H5FL_ARR_MALLOC(hsize_t,sdim->rank))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); for (u = 0; u < sdim->rank; u++) UINT32DECODE(p, sdim->perm[u]); @@ -254,25 +254,25 @@ H5O_sdspace_copy(const void *mesg, void *dest) /* check args */ assert(src); - if (!dst && NULL==(dst = H5FL_ALLOC(H5S_simple_t,0))) + if (!dst && NULL==(dst = H5FL_MALLOC(H5S_simple_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); /* deep copy -- pointed-to values are copied also */ HDmemcpy(dst, src, sizeof(H5S_simple_t)); if (src->size) { - if (NULL==(dst->size = H5FL_ARR_ALLOC(hsize_t,src->rank,0))) + if (NULL==(dst->size = H5FL_ARR_MALLOC(hsize_t,src->rank))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); HDmemcpy (dst->size, src->size, src->rank*sizeof(src->size[0])); } if (src->max) { - if (NULL==(dst->max=H5FL_ARR_ALLOC(hsize_t,src->rank,0))) + if (NULL==(dst->max=H5FL_ARR_MALLOC(hsize_t,src->rank))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); HDmemcpy (dst->max, src->max, src->rank*sizeof(src->max[0])); } #ifdef LATER if (src->perm) { - if (NULL==(dst->perm=H5FL_ARR_ALLOC(hsize_t,src->rank,0))) + if (NULL==(dst->perm=H5FL_ARR_MALLOC(hsize_t,src->rank))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); HDmemcpy (dst->perm, src->perm, src->rank*sizeof(src->perm[0])); } diff --git a/src/H5Ostab.c b/src/H5Ostab.c index 1675c51..182f280 100644 --- a/src/H5Ostab.c +++ b/src/H5Ostab.c @@ -88,7 +88,7 @@ H5O_stab_decode(H5F_t *f, const uint8_t *p, H5O_shared_t UNUSED *sh) assert (!sh); /* decode */ - if (NULL==(stab = H5FL_ALLOC(H5O_stab_t,1))) + if (NULL==(stab = H5FL_CALLOC(H5O_stab_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); H5F_addr_decode(f, &p, &(stab->btree_addr)); H5F_addr_decode(f, &p, &(stab->heap_addr)); @@ -177,7 +177,7 @@ H5O_stab_fast(const H5G_cache_t *cache, const H5O_class_t *type, void *_mesg) if (H5O_STAB == type) { if (_mesg) { stab = (H5O_stab_t *) _mesg; - } else if (NULL==(stab = H5FL_ALLOC(H5O_stab_t,1))) { + } else if (NULL==(stab = H5FL_CALLOC(H5O_stab_t))) { HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); } stab->btree_addr = cache->stab.btree_addr; @@ -221,7 +221,7 @@ H5O_stab_copy(const void *_mesg, void *_dest) /* check args */ assert(stab); - if (!dest && NULL==(dest = H5FL_ALLOC(H5O_stab_t,1))) + if (!dest && NULL==(dest = H5FL_MALLOC(H5O_stab_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); /* copy */ diff --git a/src/H5P.c b/src/H5P.c index 7913b78..a7341cb 100644 --- a/src/H5P.c +++ b/src/H5P.c @@ -21,7 +21,8 @@ #include "H5private.h" /* Generic Functions */ #include "H5Dprivate.h" /* Datasets */ #include "H5Eprivate.h" /* Error handling */ -#include "H5Fprivate.h" /* Files */ +#include "H5Fprivate.h" /* Files */ +#include "H5FLprivate.h" /* Free lists */ #include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ #include "H5Ppkg.h" /* Property lists */ @@ -34,6 +35,8 @@ static int interface_initialize_g = 0; #define INTERFACE_INIT H5P_init_interface static herr_t H5P_init_interface(void); +/* Local variables */ + /* * Predefined property list classes. These are initialized at runtime by * H5P_init_interface() in this source file. @@ -56,6 +59,19 @@ hid_t H5P_LST_DATASET_CREATE_g = FAIL; hid_t H5P_LST_DATASET_XFER_g = FAIL; hid_t H5P_LST_MOUNT_g = FAIL; +/* Track the revision count of a class, to make comparisons faster */ +static unsigned H5P_next_rev=0; +#define H5P_GET_NEXT_REV (H5P_next_rev++) + +/* Declare a free list to manage the H5P_genprop_t struct */ +H5FL_DEFINE(H5P_genprop_t); + +/* Declare a free list to manage the H5P_genplist_t struct */ +H5FL_DEFINE(H5P_genplist_t); + +/* Declare a free list to manage the H5P_genclass_t struct */ +H5FL_DEFINE_STATIC(H5P_genclass_t); + /* Local typedefs */ /* Typedef for checking for duplicate class names in parent class */ @@ -66,15 +82,84 @@ typedef struct { /* Local static functions */ static H5P_genclass_t *H5P_create_class(H5P_genclass_t *par_class, - const char *name, unsigned hashsize, unsigned internal, + const char *name, unsigned internal, H5P_cls_create_func_t cls_create, void *create_data, H5P_cls_copy_func_t cls_copy, void *copy_data, H5P_cls_close_func_t cls_close, void *close_data); static herr_t H5P_unregister(H5P_genclass_t *pclass, const char *name); -static H5P_genprop_t *H5P_dup_prop(H5P_genprop_t *oprop); +static H5P_genprop_t *H5P_dup_prop(H5P_genprop_t *oprop, H5P_prop_within_t type); static herr_t H5P_free_prop(H5P_genprop_t *prop); +/*-------------------------------------------------------------------------- + NAME + H5P_do_prop_cb1 + PURPOSE + Internal routine to call a property list callback routine and update + the property list accordingly. + USAGE + herr_t H5P_do_prop_cb1(tree,prop,cb) + H5TB_TREE *tree; IN/OUT: TBBT to hold changed properties + H5P_genprop_t *prop; IN: Property to call callback for + H5P_prp_cb1_t *cb; IN: Callback routine to call + RETURNS + Returns non-negative on success, negative on failure. + DESCRIPTION + Calls the callback routine passed in. If the callback routine changes + the property value, then the property is duplicated and added to TBBT. + + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5P_do_prop_cb1(H5TB_TREE *tree, H5P_genprop_t *prop, H5P_prp_cb1_t cb) +{ + void *tmp_value=NULL; /* Temporary value buffer */ + H5P_genprop_t *pcopy=NULL; /* Copy of property to insert into TBBT */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOINIT(H5P_do_prop_cb1); + + /* Allocate space for a temporary copy of the property value */ + if (NULL==(tmp_value=H5MM_malloc(prop->size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for temporary property value"); + HDmemcpy(tmp_value,prop->value,prop->size); + + /* Call "type 1" callback ('create', 'copy' or 'close') */ + if(cb(prop->name,prop->size,tmp_value)<0) + HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, NULL,"Property callback failed"); + + /* Check if the property value changed */ + if(HDmemcmp(tmp_value,prop->value,prop->size)) { + /* Make a copy of the class's property */ + if((pcopy=H5P_dup_prop(prop,H5P_PROP_WITHIN_LIST))==NULL) + HGOTO_ERROR (H5E_PLIST, H5E_CANTCOPY, NULL,"Can't copy property"); + + /* Copy the changed value into the new property */ + HDmemcpy(pcopy->value,tmp_value,prop->size); + + /* Insert the changed property into the property list */ + if(H5P_add_prop(tree,pcopy)<0) + HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, NULL,"Can't insert property into TBBT"); + } /* end if */ + +done: + /* Release the temporary value buffer */ + if(tmp_value!=NULL) + H5MM_xfree(tmp_value); + + /* Cleanup on failure */ + if(ret_value<0) { + if(pcopy!=NULL) + H5P_free_prop(pcopy); + } /* end if */ + + FUNC_LEAVE(ret_value); +} /* end H5P_do_prop_cb1() */ + + /*------------------------------------------------------------------------- * Function: H5P_init * @@ -106,60 +191,6 @@ done: /*-------------------------------------------------------------------------- NAME - H5P_xor_name -- Generate an xor'ed value for a string -USAGE - unsigned H5P_xor_name(s) - const char *s; IN: String to operate over -RETURNS - Always returns valid value -DESCRIPTION - Generates an xor'ed value for a string ---------------------------------------------------------------------------*/ -static unsigned -H5P_xor_name(const char *s) -{ - unsigned ret=0; - unsigned char temp; - - /* Use FUNC_ENTER_NOINIT here to avoid performance issues */ - FUNC_ENTER_NOINIT(H5P_xor_name); - - if(s!=NULL) - while(*s!='\0') { - temp=(ret>>24)&0xff; - ret <<= 8; - ret |= temp; - ret ^= *s++; - } - - FUNC_LEAVE(ret); -} /* end H5P_xor_name() */ - - -/*-------------------------------------------------------------------------- -NAME - H5P_hash_name -- Generate a hash value for a string -USAGE - unsigned H5P_hash_name(s, hashsize) - const char *s; IN: String to operate over - unsigned; IN: Size of hash table to clip against -RETURNS - Always returns valid value -DESCRIPTION - Generates a hash location based on an xor'ed value for a string ---------------------------------------------------------------------------*/ -static unsigned -H5P_hash_name(const char *s, unsigned hashsize) -{ - /* Use FUNC_ENTER_NOINIT here to avoid performance issues */ - FUNC_ENTER_NOINIT(H5P_hash_name); - - FUNC_LEAVE(H5P_xor_name(s)%hashsize); -} /* end H5P_hash_name() */ - - -/*-------------------------------------------------------------------------- -NAME H5P_init_interface -- Initialize interface-specific information USAGE herr_t H5P_init_interface() @@ -195,7 +226,7 @@ H5P_init_interface(void) /* Allocate the root class */ assert(H5P_CLS_NO_CLASS_g==(-1)); - if (NULL==(root_class = H5P_create_class (NULL,"root",H5P_NO_CLASS_HASH_SIZE,1,NULL,NULL,NULL,NULL,NULL,NULL))) + if (NULL==(root_class = H5P_create_class (NULL,"root",1,NULL,NULL,NULL,NULL,NULL,NULL))) HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, FAIL, "class initialization failed"); /* Register the root class */ @@ -206,7 +237,7 @@ H5P_init_interface(void) /* Allocate the file creation class */ assert(H5P_CLS_FILE_CREATE_g==(-1)); - if (NULL==(pclass = H5P_create_class (root_class,"file create",H5P_FILE_CREATE_HASH_SIZE,1,NULL,NULL,NULL,NULL,NULL,NULL))) + if (NULL==(pclass = H5P_create_class (root_class,"file create",1,NULL,NULL,NULL,NULL,NULL,NULL))) HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, FAIL, "class initialization failed"); /* Register the file creation class */ @@ -215,7 +246,7 @@ H5P_init_interface(void) /* Allocate the file access class */ assert(H5P_CLS_FILE_ACCESS_g==(-1)); - if (NULL==(pclass = H5P_create_class (root_class,"file access",H5P_FILE_ACCESS_HASH_SIZE,1,H5F_acs_create,NULL,H5F_acs_copy,NULL,H5F_acs_close,NULL))) + if (NULL==(pclass = H5P_create_class (root_class,"file access",1,H5F_acs_create,NULL,H5F_acs_copy,NULL,H5F_acs_close,NULL))) HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, FAIL, "class initialization failed"); /* Register the file access class */ @@ -226,7 +257,7 @@ H5P_init_interface(void) /* Allocate the dataset creation class */ assert(H5P_CLS_DATASET_CREATE_g==(-1)); - if (NULL==(pclass = H5P_create_class (root_class,"dataset create",H5P_DATASET_CREATE_HASH_SIZE,1,NULL,NULL,H5D_crt_copy,NULL,H5D_crt_close,NULL))) + if (NULL==(pclass = H5P_create_class (root_class,"dataset create",1,NULL,NULL,H5D_crt_copy,NULL,H5D_crt_close,NULL))) HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, FAIL, "class initialization failed"); /* Register the dataset creation class */ @@ -235,7 +266,7 @@ H5P_init_interface(void) /* Allocate the data xfer class */ assert(H5P_CLS_DATASET_XFER_g==(-1)); - if (NULL==(pclass = H5P_create_class (root_class,"data xfer",H5P_DATASET_XFER_HASH_SIZE,1,H5D_xfer_create,NULL,H5D_xfer_copy,NULL,H5D_xfer_close,NULL))) + if (NULL==(pclass = H5P_create_class (root_class,"data xfer",1,H5D_xfer_create,NULL,H5D_xfer_copy,NULL,H5D_xfer_close,NULL))) HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, FAIL, "class initialization failed"); /* Register the data xfer class */ @@ -244,7 +275,7 @@ H5P_init_interface(void) /* Allocate the mount class */ assert(H5P_CLS_MOUNT_g==(-1)); - if (NULL==(pclass = H5P_create_class (root_class,"file mount",H5P_MOUNT_HASH_SIZE,1,NULL,NULL,NULL,NULL,NULL,NULL))) + if (NULL==(pclass = H5P_create_class (root_class,"file mount",1,NULL,NULL,NULL,NULL,NULL,NULL))) HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, FAIL, "class initialization failed"); /* Register the mount class */ @@ -357,10 +388,8 @@ H5P_term_interface(void) static H5P_genclass_t * H5P_copy_pclass(H5P_genclass_t *pclass) { - H5P_genclass_t *new_pclass = NULL; /* Property list class copied */ - H5P_genprop_t *tmp; /* Temporary pointer to parent class properties */ - H5P_genprop_t *pcopy; /* Copy of property to insert into class */ - unsigned u; /* Local index variable */ + H5P_genclass_t *new_pclass = NULL; /* Property list class copied */ + H5P_genprop_t *pcopy; /* Copy of property to insert into class */ H5P_genclass_t *ret_value=NULL; /* return value */ FUNC_ENTER_NOINIT(H5P_copy_pclass); @@ -372,32 +401,30 @@ H5P_copy_pclass(H5P_genclass_t *pclass) */ /* Create the new property list class */ - if (NULL==(new_pclass=H5P_create_class(pclass->parent, pclass->name, pclass->hashsize, 0, pclass->create_func, pclass->create_data, pclass->copy_func, pclass->copy_data, pclass->close_func, pclass->close_data))) + if (NULL==(new_pclass=H5P_create_class(pclass->parent, pclass->name, 0, pclass->create_func, pclass->create_data, pclass->copy_func, pclass->copy_data, pclass->close_func, pclass->close_data))) HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, NULL, "unable to create property list class"); /* Copy the properties registered for this class */ if(pclass->nprops>0) { - /* Walk through the hash table */ - for(u=0; uhashsize; u++) { - tmp=pclass->props[u]; + H5TB_NODE *curr_node; /* Current node in TBBT */ - /* Walk through the list of properties at each hash location */ - while(tmp!=NULL) { - /* Make a copy of the class's property */ - if((pcopy=H5P_dup_prop(tmp))==NULL) - HGOTO_ERROR (H5E_PLIST, H5E_CANTCOPY, NULL,"Can't copy property"); + /* Walk through the properties in the old class */ + curr_node=H5TB_first(pclass->props->root); + while(curr_node!=NULL) { + /* Make a copy of the class's property */ + if((pcopy=H5P_dup_prop(curr_node->data,H5P_PROP_WITHIN_CLASS))==NULL) + HGOTO_ERROR (H5E_PLIST, H5E_CANTCOPY, NULL,"Can't copy property"); - /* Insert the initialized property into the property list */ - if(H5P_add_prop(new_pclass->props,new_pclass->hashsize,pcopy)<0) - HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, NULL,"Can't insert property into class"); + /* Insert the initialized property into the property list */ + if(H5P_add_prop(new_pclass->props,pcopy)<0) + HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, NULL,"Can't insert property into class"); - /* Increment property count for class */ - new_pclass->nprops++; + /* Increment property count for class */ + new_pclass->nprops++; - /* Go to next registered property in class */ - tmp=tmp->next; - } /* end while */ - } /* end for */ + /* Get the next property node in the TBBT */ + curr_node=H5TB_next(curr_node); + } /* end while */ } /* end if */ /* Set the return value */ @@ -432,13 +459,16 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -hid_t H5P_copy_plist(H5P_genplist_t *old_plist) +hid_t +H5P_copy_plist(H5P_genplist_t *old_plist) { + H5P_genclass_t *tclass; /* Temporary class pointer */ H5P_genplist_t *new_plist=NULL; /* New property list generated from copy */ - H5P_genprop_t *tprop; /* Temporary pointer to properties */ + H5P_genprop_t *tmp; /* Temporary pointer to properties */ H5P_genprop_t *new_prop; /* New property created for copy */ hid_t new_plist_id; /* Property list ID of new list created */ - unsigned u; /* Local index variable */ + H5TB_NODE *curr_node; /* Current node in TBBT */ + H5TB_TREE *seen=NULL; /* TBBT containing properties already seen */ hid_t ret_value=FAIL; /* return value */ FUNC_ENTER_NOAPI(H5P_copy_plist, FAIL); @@ -449,8 +479,8 @@ hid_t H5P_copy_plist(H5P_genplist_t *old_plist) * Create new property list object */ - /* Allocate room for the property list & it's hash table of properties */ - if (NULL==(new_plist = H5MM_calloc (sizeof(H5P_genplist_t)+((old_plist->pclass->hashsize-1)*sizeof(H5P_genprop_t *))))) + /* Allocate room for the property list */ + if (NULL==(new_plist = H5FL_CALLOC(H5P_genplist_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL,"memory allocation failed"); /* Set class state */ @@ -458,14 +488,54 @@ hid_t H5P_copy_plist(H5P_genplist_t *old_plist) new_plist->nprops = 0; /* Initially the plist has the same number of properties as the class */ new_plist->class_init = 0; /* Initially, wait until the class callback finishes to set */ + /* Initialize the TBBT to hold the changed properties */ + if((new_plist->props=H5TB_fast_dmake(H5TB_FAST_STR_COMPARE))==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTMAKETREE,FAIL,"can't create TBBT for changed properties"); + + /* Create the TBBT for deleted properties */ + if((new_plist->del=H5TB_fast_dmake(H5TB_FAST_STR_COMPARE))==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTMAKETREE,NULL,"can't create TBBT for deleted properties"); + + /* Create the TBBT to hold names of properties already seen + * (This prevents a property in the class hierarchy from having it's + * 'create' callback called, if a property in the class hierarchy has + * already been seen) + */ + if((seen=H5TB_fast_dmake(H5TB_FAST_STR_COMPARE))==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTMAKETREE,NULL,"can't create TBBT for seen properties"); + + /* Cycle through the deleted properties & copy them into the new list's deleted section */ + if(old_plist->del->root) { + curr_node=H5TB_first(old_plist->del->root); + while(curr_node) { + char *new_name; /* Pointer to new name */ + + /* Duplicate string for insertion into new deleted property TBBT */ + if((new_name=H5MM_xstrdup(curr_node->data))==NULL) + HGOTO_ERROR(H5E_RESOURCE,H5E_NOSPACE,FAIL,"memory allocation failed"); + + /* Insert property name into deleted list */ + if(H5TB_dins(new_plist->del,new_name,new_name)==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTINSERT,NULL,"can't insert property into deleted TBBT"); + + /* Add property name to "seen" list */ + if(H5TB_dins(seen,new_name,new_name)==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTINSERT,NULL,"can't insert property into seen TBBT"); + + /* Get the next property node in the TBBT */ + curr_node=H5TB_next(curr_node); + } /* end while */ + } /* end if */ + /* Cycle through the properties and copy them also */ - for(u=0; upclass->hashsize; u++) { - tprop=old_plist->props[u]; + if(old_plist->props->root) { + curr_node=H5TB_first(old_plist->props->root); + while(curr_node) { + /* Get a pointer to the node's property */ + tmp=curr_node->data; - /* Walk through the list of properties at each hash location */ - while(tprop!=NULL) { /* Make a copy of the list's property */ - if((new_prop=H5P_dup_prop(tprop))==NULL) + if((new_prop=H5P_dup_prop(tmp,H5P_PROP_WITHIN_LIST))==NULL) HGOTO_ERROR (H5E_PLIST, H5E_CANTCOPY, FAIL,"Can't copy property"); /* Call property copy callback, if it exists */ @@ -477,16 +547,61 @@ hid_t H5P_copy_plist(H5P_genplist_t *old_plist) } /* end if */ /* Insert the initialized property into the property list */ - if(H5P_add_prop(new_plist->props,new_plist->pclass->hashsize,new_prop)<0) + if(H5P_add_prop(new_plist->props,new_prop)<0) { + H5P_free_prop(new_prop); HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, FAIL,"Can't insert property into list"); + } /* end if */ + + /* Add property name to "seen" list */ + if(H5TB_dins(seen,new_prop->name,new_prop->name)==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTINSERT,NULL,"can't insert property into seen TBBT"); /* Increment the number of properties in list */ new_plist->nprops++; - /* Go to next registered property in class */ - tprop=tprop->next; + /* Get the next property node in the TBBT */ + curr_node=H5TB_next(curr_node); } /* end while */ - } /* end for */ + } /* end if */ + + /* + * Check for copying class properties (up through list of parent classes also), + * initialize each with default value & make property 'copy' callback. + */ + tclass=old_plist->pclass; + while(tclass!=NULL) { + if(tclass->nprops>0) { + /* Walk through the properties in the old class */ + curr_node=H5TB_first(tclass->props->root); + while(curr_node!=NULL) { + /* Get pointer to property from node */ + tmp=curr_node->data; + + /* Only "copy" properties we haven't seen before */ + if(H5TB_dfind(seen,tmp->name,NULL)==NULL) { + /* Call property creation callback, if it exists */ + if(tmp->copy) { + /* Call the callback & insert changed value into tree (if necessary) */ + if(H5P_do_prop_cb1(new_plist->props,tmp,tmp->copy)<0) + HGOTO_ERROR (H5E_PLIST, H5E_CANTCOPY, NULL,"Can't create property"); + } /* end if */ + + /* Add property name to "seen" list */ + if(H5TB_dins(seen,tmp->name,tmp->name)==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTINSERT,NULL,"can't insert property into seen TBBT"); + + /* Increment the number of properties in list */ + new_plist->nprops++; + } /* end if */ + + /* Get the next property node in the TBBT */ + curr_node=H5TB_next(curr_node); + } /* end while */ + } /* end if */ + + /* Go up to parent class */ + tclass=tclass->parent; + } /* end while */ /* Increment the number of property lists derived from class */ if(H5P_access_class(new_plist->pclass,H5P_MOD_INC_LST)<0) @@ -515,6 +630,10 @@ hid_t H5P_copy_plist(H5P_genplist_t *old_plist) ret_value=new_plist_id; done: + /* Release the tree of 'seen' properties */ + if(seen!=NULL) + H5TB_dfree(seen,NULL,NULL); + if (ret_value<0 && new_plist) H5P_close(new_plist); @@ -543,7 +662,8 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -hid_t H5Pcopy(hid_t id) +hid_t +H5Pcopy(hid_t id) { void *obj; /* Property object to copy */ hid_t ret_value=FALSE; /* return value */ @@ -592,6 +712,7 @@ done: USAGE H5P_genprop_t *H5P_dup_prop(oprop) H5P_genprop_t *oprop; IN: Pointer to property to copy + H5P_prop_within_t type; IN: Type of object the property will be inserted into RETURNS Returns a pointer to the newly created duplicate of a property on success, NULL on failure. @@ -603,7 +724,7 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static H5P_genprop_t * -H5P_dup_prop(H5P_genprop_t *oprop) +H5P_dup_prop(H5P_genprop_t *oprop, H5P_prop_within_t type) { H5P_genprop_t *prop=NULL; /* Pointer to new property copied */ H5P_genprop_t *ret_value; /* Return value */ @@ -611,16 +732,47 @@ H5P_dup_prop(H5P_genprop_t *oprop) FUNC_ENTER_NOINIT(H5P_dup_prop); assert(oprop); + assert(type!=H5P_PROP_WITHIN_UNKNOWN); /* Allocate the new property */ - if (NULL==(prop = H5MM_malloc (sizeof(H5P_genprop_t)))) + if (NULL==(prop = H5FL_MALLOC (H5P_genprop_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); /* Copy basic property information */ HDmemcpy(prop,oprop,sizeof(H5P_genprop_t)); - /* Duplicate name */ - prop->name = H5MM_xstrdup(oprop->name); + /* Check if we should duplicate the name or share it */ + + /* Duplicating property for a class */ + if(type==H5P_PROP_WITHIN_CLASS) { + assert(oprop->type==H5P_PROP_WITHIN_CLASS); + assert(oprop->shared_name==0); + + /* Duplicate name */ + prop->name = H5MM_xstrdup(oprop->name); + } /* end if */ + /* Duplicating property for a list */ + else { + /* Check if we are duplicating a property from a list or a class */ + + /* Duplicating a property from a list */ + if(oprop->type==H5P_PROP_WITHIN_LIST) { + /* If the old property's name wasn't shared, we have to copy it here also */ + if(!oprop->shared_name) + prop->name = H5MM_xstrdup(oprop->name); + } /* end if */ + /* Duplicating a property from a class */ + else { + assert(oprop->type==H5P_PROP_WITHIN_CLASS); + assert(oprop->shared_name==0); + + /* Share the name */ + prop->shared_name=1; + + /* Set the type */ + prop->type=type; + } /* end else */ + } /* end else */ /* Duplicate current value, if it exists */ if(oprop->value!=NULL) { @@ -630,17 +782,6 @@ H5P_dup_prop(H5P_genprop_t *oprop) HDmemcpy(prop->value,oprop->value,prop->size); } /* end if */ - /* Duplicate default value, if it exists */ - if(oprop->def_value!=NULL) { - assert(prop->size>0); - if (NULL==(prop->def_value = H5MM_malloc (prop->size))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - HDmemcpy(prop->def_value,oprop->def_value,prop->size); - } /* end if */ - - /* Reset the link to the next property */ - prop->next=NULL; - /* Set return value */ ret_value=prop; @@ -652,9 +793,7 @@ done: H5MM_xfree(prop->name); if(prop->value!=NULL) H5MM_xfree(prop->value); - if(prop->def_value!=NULL) - H5MM_xfree(prop->def_value); - H5MM_xfree(prop); + H5FL_FREE(H5P_genprop_t,prop); } /* end if */ } /* end if */ @@ -668,12 +807,12 @@ done: PURPOSE Internal routine to create a new property USAGE - H5P_genprop_t *H5P_create_prop(name,size,def_value,prp_create,prp_set, + H5P_genprop_t *H5P_create_prop(name,size,type,value,prp_create,prp_set, prp_get,prp_delete,prp_close) const char *name; IN: Name of property to register size_t size; IN: Size of property in bytes - void *def_value; IN: Pointer to buffer containing default value - for property in newly created property lists + H5P_prop_within_t type; IN: Type of object the property will be inserted into + void *value; IN: Pointer to buffer containing value for property H5P_prp_create_func_t prp_create; IN: Function pointer to property creation callback H5P_prp_set_func_t prp_set; IN: Function pointer to property set callback @@ -693,7 +832,8 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static H5P_genprop_t * -H5P_create_prop(const char *name, size_t size, void *def_value, void *value, +H5P_create_prop(const char *name, size_t size, H5P_prop_within_t type, + void *value, H5P_prp_create_func_t prp_create, H5P_prp_set_func_t prp_set, H5P_prp_get_func_t prp_get, H5P_prp_delete_func_t prp_delete, H5P_prp_copy_func_t prp_copy, H5P_prp_close_func_t prp_close) @@ -704,16 +844,18 @@ H5P_create_prop(const char *name, size_t size, void *def_value, void *value, FUNC_ENTER_NOINIT(H5P_create_prop); assert(name); - assert((size>0 && (def_value!=NULL || value!=NULL)) || (size==0)); + assert((size>0 && value!=NULL) || (size==0)); + assert(type!=H5P_PROP_WITHIN_UNKNOWN); /* Allocate the new property */ - if (NULL==(prop = H5MM_malloc (sizeof(H5P_genprop_t)))) + if (NULL==(prop = H5FL_MALLOC (H5P_genprop_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); /* Set the property initial values */ - prop->xor_val = H5P_xor_name(name); /* Generate the XOR'd value for the name */ prop->name = H5MM_xstrdup(name); /* Duplicate name */ + prop->shared_name=0; prop->size=size; + prop->type=type; /* Duplicate value, if it exists */ if(value!=NULL) { @@ -724,15 +866,6 @@ H5P_create_prop(const char *name, size_t size, void *def_value, void *value, else prop->value=NULL; - /* Duplicate default value, if it exists */ - if(def_value!=NULL) { - if (NULL==(prop->def_value = H5MM_malloc (prop->size))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - HDmemcpy(prop->def_value,def_value,prop->size); - } /* end if */ - else - prop->def_value=NULL; - /* Set the function pointers */ prop->create=prp_create; prop->set=prp_set; @@ -741,9 +874,6 @@ H5P_create_prop(const char *name, size_t size, void *def_value, void *value, prop->copy=prp_copy; prop->close=prp_close; - /* Reset the link to the next property */ - prop->next=NULL; - /* Set return value */ ret_value=prop; @@ -755,9 +885,7 @@ done: H5MM_xfree(prop->name); if(prop->value!=NULL) H5MM_xfree(prop->value); - if(prop->def_value!=NULL) - H5MM_xfree(prop->def_value); - H5MM_xfree(prop); + H5FL_FREE(H5P_genprop_t,prop); } /* end if */ } /* end if */ @@ -769,95 +897,142 @@ done: NAME H5P_add_prop PURPOSE - Internal routine to insert a property into a property hash table + Internal routine to insert a property into a property TBBT USAGE - herr_t H5P_add_prop(hash, hashsize, prop) - H5P_gen_prop_t *hash[]; IN/OUT: Pointer to array of properties for hash table - unsigned hashsize; IN: Size of hash table + herr_t H5P_add_prop(tree, prop) + H5TB_TREE *tree; IN/OUT: Pointer to TBBT of properties H5P_genprop_t *prop; IN: Pointer to property to insert RETURNS Returns non-negative on success, negative on failure. DESCRIPTION - Inserts a property into a hash table of properties, using the hashed - property name. + Inserts a property into a TBBT of properties. GLOBAL VARIABLES COMMENTS, BUGS, ASSUMPTIONS EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5P_add_prop(H5P_genprop_t *hash[], unsigned hashsize, H5P_genprop_t *prop) +H5P_add_prop(H5TB_TREE *tree, H5P_genprop_t *prop) { - unsigned loc; /* Hash table location */ + herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_NOINIT(H5P_add_prop); + FUNC_ENTER_NOAPI(H5P_add_prop,FAIL); - assert(hash); - assert(hashsize>0); + assert(tree); assert(prop); + assert(prop->type!=H5P_PROP_WITHIN_UNKNOWN); - /* Get correct hash table location */ - loc=H5P_hash_name(prop->name,hashsize); - - /* Insert property into hash table */ - prop->next=hash[loc]; - hash[loc]=prop; + /* Insert property into TBBT */ + if(H5TB_dins(tree,prop,prop->name)==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTINSERT,FAIL,"can't insert property into TBBT"); - FUNC_LEAVE (SUCCEED); +done: + FUNC_LEAVE(ret_value); } /* H5P_add_prop() */ /*-------------------------------------------------------------------------- NAME - H5P_find_prop + H5P_find_prop_plist PURPOSE - Internal routine to check for a property in a hash table + Internal routine to check for a property in a property list's TBBT USAGE - H5P_genprop_t *H5P_find_prop(hash, hashsize, name) - H5P_genprop_t *hash[]; IN: Pointer to array of properties for hash table - unsigned hashsize; IN: Size of hash table + H5P_genprop_t *H5P_find_prop(plist, name) + H5P_genplist_t *plist; IN: Pointer to property list to check const char *name; IN: Name of property to check for RETURNS Returns pointer to property on success, NULL on failure. DESCRIPTION - Checks for a property in a hash table of properties. + Checks for a property in a property list's TBBT of properties. GLOBAL VARIABLES COMMENTS, BUGS, ASSUMPTIONS EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ static H5P_genprop_t * -H5P_find_prop(H5P_genprop_t *hash[], unsigned hashsize, const char *name) +H5P_find_prop_plist(H5P_genplist_t *plist, const char *name) { + H5TB_NODE *prop_node; /* TBBT node holding property */ H5P_genprop_t *ret_value; /* Property pointer return value */ - unsigned loc; /* Hash table location */ - unsigned xor_val; /* XOR'ed value of the name to look for */ - FUNC_ENTER_NOINIT(H5P_find_prop); + FUNC_ENTER_NOINIT(H5P_find_prop_plist); - assert(hash); - assert(hashsize>0); + assert(plist); assert(name); - /* Get correct hash table location */ - loc=H5P_hash_name(name,hashsize); - - /* Get the XOR'ed value for the name to search for, to speed up comparisons */ - xor_val=H5P_xor_name(name); - - /* Locate property in list */ - ret_value=hash[loc]; - while(ret_value!=NULL) { - /* Check for name matching */ - if(ret_value->xor_val==xor_val && HDstrcmp(ret_value->name,name)==0) - break; - - /* Advance to the next property */ - ret_value=ret_value->next; - } /* end while */ + /* Check if the property has been deleted from list */ + if(H5TB_dfind(plist->del,name,NULL)!=NULL) { + HGOTO_ERROR(H5E_PLIST,H5E_NOTFOUND,NULL,"can't find property in TBBT"); + } /* end if */ + else { + /* Get the property node from the TBBT */ + if((prop_node=H5TB_dfind(plist->props,name,NULL))!=NULL) { + /* Get the property from the node */ + ret_value=prop_node->data; + } /* end if */ + else { + H5P_genclass_t *tclass; /* Temporary class pointer */ + + tclass=plist->pclass; + while(tclass!=NULL) { + /* Find the property in the class */ + if((prop_node=H5TB_dfind(tclass->props,name,NULL))!=NULL) + /* Get pointer to actual property & leave */ + HGOTO_DONE(prop_node->data); + + /* Go up to parent class */ + tclass=tclass->parent; + } /* end while */ + + /* If we've gotten this far, we haven't found the property */ + HGOTO_ERROR(H5E_PLIST,H5E_NOTFOUND,NULL,"can't find property in TBBT"); + } /* end else */ + } /* end else */ + +done: + FUNC_LEAVE (ret_value); +} /* H5P_find_prop_plist() */ + + +/*-------------------------------------------------------------------------- + NAME + H5P_find_prop_pclass + PURPOSE + Internal routine to check for a property in a class TBBT + USAGE + H5P_genprop_t *H5P_find_prop_class(tree, name) + H5P_genclass *pclass; IN: Pointer generic property class to check + const char *name; IN: Name of property to check for + RETURNS + Returns pointer to property on success, NULL on failure. + DESCRIPTION + Checks for a property in a class' TBBT of properties. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static H5P_genprop_t * +H5P_find_prop_pclass(H5P_genclass_t *pclass, const char *name) +{ + H5TB_NODE *prop_node; /* TBBT node holding property */ + H5P_genprop_t *ret_value; /* Property pointer return value */ + + FUNC_ENTER_NOINIT(H5P_find_prop_pclass); + + assert(pclass); + assert(name); + + /* Get the property node from the TBBT */ + if((prop_node=H5TB_dfind(pclass->props,name,NULL))==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_NOTFOUND,NULL,"can't find property in TBBT"); + + /* Get the property from the node */ + ret_value=prop_node->data; +done: FUNC_LEAVE (ret_value); -} /* H5P_find_prop() */ +} /* H5P_find_prop_pclass() */ /*-------------------------------------------------------------------------- @@ -885,15 +1060,15 @@ H5P_free_prop(H5P_genprop_t *prop) assert(prop); - /* Release the property value and default value if they exist */ - if(prop->size>0) { - if(prop->value) - H5MM_xfree(prop->value); - if(prop->def_value) - H5MM_xfree(prop->def_value); - } /* end if */ - H5MM_xfree(prop->name); - H5MM_xfree(prop); + /* Release the property value if it exists */ + if(prop->value) + H5MM_xfree(prop->value); + + /* Only free the name if we own it */ + if(prop->shared_name==0) + H5MM_xfree(prop->name); + + H5FL_FREE(H5P_genprop_t,prop); FUNC_LEAVE (SUCCEED); } /* H5P_free_prop() */ @@ -903,11 +1078,10 @@ H5P_free_prop(H5P_genprop_t *prop) NAME H5P_free_all_prop PURPOSE - Internal routine to remove all properties from a property hash table + Internal routine to remove all properties from a property TBBT USAGE - herr_t H5P_free_all_prop(hash, hashsize, make_cb) - H5P_gen_prop_t *hash[]; IN/OUT: Pointer to array of properties for hash table - unsigned hashsize; IN: Size of hash table + herr_t H5P_free_all_prop(tree, make_cb) + H5TB_TREE *tree; IN/OUT: Pointer to property TBBT unsigned make_cb; IN: Whether to make property callbacks or not RETURNS Returns non-negative on success, negative on failure. @@ -920,35 +1094,39 @@ H5P_free_prop(H5P_genprop_t *prop) REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5P_free_all_prop(H5P_genprop_t *hash[], unsigned hashsize, unsigned make_cb) +H5P_free_all_prop(H5TB_TREE *tree,unsigned make_cb) { - H5P_genprop_t *tprop, *next;/* Temporary pointer to properties */ - unsigned u; /* Local index variable */ + H5P_genprop_t *tprop; /* Temporary pointer to properties */ + H5TB_NODE *curr_node, *next_node; /* Current & next nodes in TBBT */ + herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOINIT(H5P_free_all_prop); - assert(hash); - assert(hashsize>0); + assert(tree); /* Work through all the properties... */ - for(u=0; unext; + curr_node=H5TB_first(tree->root); + while(curr_node!=NULL) { + /* Get the next node in the TBBT */ + next_node=H5TB_next(curr_node); - /* Call the close callback and ignore the return value, there's nothing we can do about it */ - if(make_cb && tprop->close!=NULL) - (tprop->close)(tprop->name,tprop->size,tprop->value); + /* Remove the node from the TBBT */ + if((tprop=H5TB_rem(&tree->root,curr_node,NULL))==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTDELETE,FAIL,"can't remove property from TBBT"); - /* Free the property, ignoring return value, nothing we can do */ - H5P_free_prop(tprop); + /* Call the close callback and ignore the return value, there's nothing we can do about it */ + if(make_cb && tprop->close!=NULL) + (tprop->close)(tprop->name,tprop->size,tprop->value); - tprop=next; - } /* end while */ - } /* end for */ + /* Free the property, ignoring return value, nothing we can do */ + H5P_free_prop(tprop); - FUNC_LEAVE (SUCCEED); + /* Advance to the next property node in the TBBT */ + curr_node=next_node; + } /* end while */ + +done: + FUNC_LEAVE (ret_value); } /* H5P_free_all_prop() */ @@ -1027,9 +1205,13 @@ H5P_access_class(H5P_genclass_t *pclass, H5P_class_mod_t mod) H5MM_xfree(pclass->name); /* Free the class properties without making callbacks */ - H5P_free_all_prop(pclass->props,pclass->hashsize,0); + if(pclass->nprops>0) + H5P_free_all_prop(pclass->props,0); - H5MM_xfree(pclass); + /* Free the property tree itself */ + H5TB_dfree(pclass->props,NULL,NULL); + + H5FL_FREE(H5P_genclass_t,pclass); /* Reduce the number of dependent classes on parent class also */ if(par_class!=NULL) @@ -1091,11 +1273,10 @@ H5P_check_class(void *_obj, hid_t id, const void *_key) PURPOSE Internal routine to create a new property list class. USAGE - H5P_genclass_t H5P_create_class(par_class, name, hashsize, internal, + H5P_genclass_t H5P_create_class(par_class, name, internal, cls_create, create_data, cls_close, close_data) H5P_genclass_t *par_class; IN: Pointer to parent class const char *name; IN: Name of class we are creating - unsigned hashsize; IN: Number of buckets in hash table unsigned internal; IN: Whether this is an internal class or not H5P_cls_create_func_t; IN: The callback function to call when each property list in this class is created. @@ -1120,7 +1301,7 @@ H5P_check_class(void *_obj, hid_t id, const void *_key) REVISION LOG --------------------------------------------------------------------------*/ static H5P_genclass_t * -H5P_create_class(H5P_genclass_t *par_class, const char *name, unsigned hashsize, unsigned internal, +H5P_create_class(H5P_genclass_t *par_class, const char *name, unsigned internal, H5P_cls_create_func_t cls_create, void *create_data, H5P_cls_copy_func_t cls_copy, void *copy_data, H5P_cls_close_func_t cls_close, void *close_data @@ -1136,23 +1317,26 @@ H5P_create_class(H5P_genclass_t *par_class, const char *name, unsigned hashsize, /* (This allows the root of the tree to be created with this routine -QAK) */ if(!internal) { assert(par_class); - assert(hashsize>0); } - /* Allocate room for the class & it's hash table of properties */ - if (NULL==(pclass = H5MM_calloc (sizeof(H5P_genclass_t)+((hashsize-1)*sizeof(H5P_genprop_t *))))) + /* Allocate room for the class */ + if (NULL==(pclass = H5FL_CALLOC(H5P_genclass_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL,"memory allocation failed"); /* Set class state */ pclass->parent = par_class; pclass->name = H5MM_xstrdup(name); pclass->nprops = 0; /* Classes are created without properties initially */ - pclass->hashsize = hashsize; pclass->plists = 0; /* No properties lists of this class yet */ pclass->classes = 0; /* No classes derived from this class yet */ pclass->ref_count = 1; /* This is the first reference to the new class */ pclass->internal = internal; pclass->deleted = 0; /* Not deleted yet... :-) */ + pclass->revision = H5P_GET_NEXT_REV; /* Get a revision number for the class */ + + /* Create the TBBT for properties */ + if((pclass->props=H5TB_fast_dmake(H5TB_FAST_STR_COMPARE))==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTMAKETREE,NULL,"can't create TBBT for properties"); /* Set callback functions and pass-along data */ pclass->create_func = cls_create; @@ -1175,7 +1359,7 @@ done: /* Free any resources allocated */ if(ret_value==NULL) { if(pclass!=NULL) - H5MM_xfree(pclass); + H5FL_FREE(H5P_genclass_t,pclass); } FUNC_LEAVE (ret_value); @@ -1188,11 +1372,10 @@ done: PURPOSE Create a new property list class. USAGE - hid_t H5Pcreate_class(parent, name, hashsize, cls_create, create_data, + hid_t H5Pcreate_class(parent, name, cls_create, create_data, cls_close, close_data) hid_t parent; IN: Property list class ID of parent class const char *name; IN: Name of class we are creating - unsigned hashsize; IN: Number of buckets in hash table H5P_cls_create_func_t cls_create; IN: The callback function to call when each property list in this class is created. @@ -1218,7 +1401,7 @@ done: REVISION LOG --------------------------------------------------------------------------*/ hid_t -H5Pcreate_class(hid_t parent, const char *name, unsigned hashsize, +H5Pcreate_class(hid_t parent, const char *name, H5P_cls_create_func_t cls_create, void *create_data, H5P_cls_copy_func_t cls_copy, void *copy_data, H5P_cls_close_func_t cls_close, void *close_data @@ -1229,7 +1412,7 @@ H5Pcreate_class(hid_t parent, const char *name, unsigned hashsize, hid_t ret_value; /* Return value */ FUNC_ENTER_API(H5Pcreate_class, FAIL); - H5TRACE9("i","isIuxxxxxx",parent,name,hashsize,cls_create,create_data, + H5TRACE8("i","isxxxxxx",parent,name,cls_create,create_data, cls_copy,copy_data,cls_close,close_data); /* Check arguments. */ @@ -1237,8 +1420,6 @@ H5Pcreate_class(hid_t parent, const char *name, unsigned hashsize, HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list class"); if (!name || !*name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid class name"); - if (hashsize==0) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "hashsize too small"); if ((create_data!=NULL && cls_create==NULL) || (copy_data!=NULL && cls_copy==NULL) || (close_data!=NULL && cls_close==NULL)) @@ -1251,7 +1432,7 @@ H5Pcreate_class(hid_t parent, const char *name, unsigned hashsize, HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't retrieve parent class"); /* Create the new property list class */ - if (NULL==(pclass=H5P_create_class(par_class, name, hashsize, 0, cls_create, create_data, cls_copy, copy_data, cls_close, close_data))) + if (NULL==(pclass=H5P_create_class(par_class, name, 0, cls_create, create_data, cls_copy, copy_data, cls_close, close_data))) HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, FAIL, "unable to create property list class"); /* Get an atom for the class */ @@ -1291,14 +1472,14 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -static H5P_genplist_t *H5P_create(H5P_genclass_t *pclass) +static H5P_genplist_t * +H5P_create(H5P_genclass_t *pclass) { - H5P_genclass_t *tclass=NULL; /* Temporary class pointer */ - H5P_genplist_t *plist=NULL; /* New property list created */ - H5P_genplist_t *ret_value; /* return value */ - H5P_genprop_t *tmp; /* Temporary pointer to parent class properties */ - H5P_genprop_t *pcopy; /* Copy of property to insert into class */ - unsigned u; /* Local index variable */ + H5P_genclass_t *tclass; /* Temporary class pointer */ + H5P_genplist_t *plist=NULL; /* New property list created */ + H5P_genprop_t *tmp; /* Temporary pointer to parent class properties */ + H5TB_TREE *seen=NULL; /* TBBT to hold names of properties already seen */ + H5P_genplist_t *ret_value; /* Return value */ FUNC_ENTER_NOINIT(H5P_create); @@ -1308,8 +1489,8 @@ static H5P_genplist_t *H5P_create(H5P_genclass_t *pclass) * Create new property list object */ - /* Allocate room for the property list & it's hash table of properties */ - if (NULL==(plist = H5MM_calloc (sizeof(H5P_genplist_t)+((pclass->hashsize-1)*sizeof(H5P_genprop_t *))))) + /* Allocate room for the property list */ + if (NULL==(plist = H5FL_CALLOC(H5P_genplist_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL,"memory allocation failed"); /* Set class state */ @@ -1317,57 +1498,57 @@ static H5P_genplist_t *H5P_create(H5P_genclass_t *pclass) plist->nprops = 0; /* Initially the plist has the same number of properties as the class */ plist->class_init = 0; /* Initially, wait until the class callback finishes to set */ + /* Create the TBBT for changed properties */ + if((plist->props=H5TB_fast_dmake(H5TB_FAST_STR_COMPARE))==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTMAKETREE,NULL,"can't create TBBT for changed properties"); + + /* Create the TBBT for deleted properties */ + if((plist->del=H5TB_fast_dmake(H5TB_FAST_STR_COMPARE))==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTMAKETREE,NULL,"can't create TBBT for deleted properties"); + + /* Create the TBBT to hold names of properties already seen + * (This prevents a property in the class hierarchy from having it's + * 'create' callback called, if a property in the class hierarchy has + * already been seen) + */ + if((seen=H5TB_fast_dmake(H5TB_FAST_STR_COMPARE))==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTMAKETREE,NULL,"can't create TBBT for seen properties"); + /* - * Copy class properties (up through list of parent classes also), + * Check if we should copy class properties (up through list of parent classes also), * initialize each with default value & make property 'create' callback. */ tclass=pclass; while(tclass!=NULL) { if(tclass->nprops>0) { - /* Walk through the hash table */ - for(u=0; uhashsize; u++) { - tmp=tclass->props[u]; - /* Walk through the list of properties at each hash location */ - while(tmp!=NULL) { - /* Check for property already existing in list */ - if(H5P_find_prop(plist->props,pclass->hashsize,tmp->name)==NULL) { - /* Make a copy of the class's property */ - if((pcopy=H5P_dup_prop(tmp))==NULL) - HGOTO_ERROR (H5E_PLIST, H5E_CANTCOPY, NULL,"Can't copy property"); - - /* Create initial value from default value for non-zero sized properties */ - if(pcopy->size>0) { - /* Properties from the class should have any values yet, but should have a default */ - assert(pcopy->value==NULL); - assert(pcopy->def_value); - - /* Allocate space for the property value & copy default value */ - if (NULL==(pcopy->value = H5MM_malloc (pcopy->size))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - - HDmemcpy(pcopy->value,pcopy->def_value,pcopy->size); - } /* end if */ - - /* Call property creation callback, if it exists */ - if(pcopy->create) { - if((pcopy->create)(pcopy->name,pcopy->size,pcopy->value)<0) { - H5P_free_prop(pcopy); - HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, NULL,"Can't initialize property"); - } /* end if */ - } /* end if */ + H5TB_NODE *curr_node; /* Current node in TBBT */ + + /* Walk through the properties in the old class */ + curr_node=H5TB_first(tclass->props->root); + while(curr_node!=NULL) { + /* Get pointer to property from node */ + tmp=curr_node->data; + + /* Only "create" properties we haven't seen before */ + if(H5TB_dfind(seen,tmp->name,NULL)==NULL) { + /* Call property creation callback, if it exists */ + if(tmp->create) { + /* Call the callback & insert changed value into tree (if necessary) */ + if(H5P_do_prop_cb1(plist->props,tmp,tmp->create)<0) + HGOTO_ERROR (H5E_PLIST, H5E_CANTCOPY, NULL,"Can't create property"); + } /* end if */ - /* Insert the initialized property into the property list */ - if(H5P_add_prop(plist->props,pclass->hashsize,pcopy)<0) - HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, NULL,"Can't insert property into class"); + /* Add property name to "seen" list */ + if(H5TB_dins(seen,tmp->name,tmp->name)==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTINSERT,NULL,"can't insert property into seen TBBT"); - /* Increment the number of properties in list */ - plist->nprops++; - } /* end if */ + /* Increment the number of properties in list */ + plist->nprops++; + } /* end if */ - /* Go to next registered property in class */ - tmp=tmp->next; - } /* end while */ - } /* end for */ + /* Get the next property node in the TBBT */ + curr_node=H5TB_next(curr_node); + } /* end while */ } /* end if */ /* Go up to parent class */ @@ -1382,14 +1563,25 @@ static H5P_genplist_t *H5P_create(H5P_genclass_t *pclass) ret_value=plist; done: + /* Release the tree of 'seen' properties */ + if(seen!=NULL) + H5TB_dfree(seen,NULL,NULL); + /* Release resources allocated on failure */ if(ret_value==NULL) { if(plist!=NULL) { - /* Close & free all the properties */ - H5P_free_all_prop(plist->props,pclass->hashsize,1); + /* Close & free any changed properties */ + if(plist->props) { + H5P_free_all_prop(plist->props,1); + H5TB_dfree(plist->props,NULL,NULL); + } /* end if */ - /* Decrement the number of property lists derived from the class */ - pclass->plists--; + /* Release the deleted property TBBT */ + if(plist->del) + H5TB_dfree(plist->del,NULL,NULL); + + /* Release the property list itself */ + H5FL_FREE(H5P_genplist_t,plist); } /* end if */ } /* end if */ @@ -1419,7 +1611,8 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -hid_t H5P_create_id(H5P_genclass_t *pclass) +hid_t +H5P_create_id(H5P_genclass_t *pclass) { H5P_genplist_t *plist=NULL; /* Property list created */ hid_t plist_id=FAIL; /* Property list ID */ @@ -1485,7 +1678,8 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -hid_t H5Pcreate(hid_t cls_id) +hid_t +H5Pcreate(hid_t cls_id) { H5P_genclass_t *pclass; /* Property list class to modify */ hid_t ret_value; /* return value */ @@ -1636,16 +1830,15 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -herr_t H5P_register(H5P_genclass_t *pclass, const char *name, size_t size, +herr_t +H5P_register(H5P_genclass_t *pclass, const char *name, size_t size, void *def_value, H5P_prp_create_func_t prp_create, H5P_prp_set_func_t prp_set, H5P_prp_get_func_t prp_get, H5P_prp_delete_func_t prp_delete, H5P_prp_copy_func_t prp_copy, H5P_prp_close_func_t prp_close) { H5P_genclass_t *new_class; /* New class pointer */ - H5P_genprop_t *tmp_prop; /* Temporary property pointer */ H5P_genprop_t *new_prop=NULL; /* Temporary property pointer */ H5P_genprop_t *pcopy; /* Property copy */ - unsigned u; /* Local index variable */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5P_register, FAIL); @@ -1655,51 +1848,60 @@ herr_t H5P_register(H5P_genclass_t *pclass, const char *name, size_t size, assert((size>0 && def_value!=NULL) || (size==0)); /* Check for duplicate named properties */ - if((tmp_prop=H5P_find_prop(pclass->props,pclass->hashsize,name))!=NULL) + if(H5TB_dfind(pclass->props,name,NULL)!=NULL) HGOTO_ERROR(H5E_PLIST, H5E_EXISTS, FAIL, "property already exists"); /* Check if class needs to be split because property lists or classes have * been created since the last modification was made to the class. */ if(pclass->plists>0 || pclass->classes>0) { - if((new_class=H5P_create_class(pclass->parent,pclass->name,pclass->hashsize, + if((new_class=H5P_create_class(pclass->parent,pclass->name, pclass->internal,pclass->create_func,pclass->create_data, pclass->copy_func,pclass->copy_data, pclass->close_func,pclass->close_data))==NULL) HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "can't copy class"); - /* Walk through the hash table of the old class and copy properties */ - for(u=0; uhashsize; u++) { - tmp_prop=pclass->props[u]; - while(tmp_prop!=NULL) { + /* Walk through the TBBT of the old class and copy properties */ + if(pclass->nprops>0) { + H5TB_NODE *curr_node; /* Current node in TBBT */ + + /* Walk through the properties in the old class */ + curr_node=H5TB_first(pclass->props->root); + while(curr_node!=NULL) { /* Make a copy of the class's property */ - if((pcopy=H5P_dup_prop(tmp_prop))==NULL) - HGOTO_ERROR (H5E_PLIST, H5E_CANTCOPY, FAIL,"Can't copy property"); + if((pcopy=H5P_dup_prop(curr_node->data,H5P_PROP_WITHIN_CLASS))==NULL) + HGOTO_ERROR (H5E_PLIST, H5E_CANTCOPY, NULL,"Can't copy property"); + + /* Insert the initialized property into the property list */ + if(H5P_add_prop(new_class->props,pcopy)<0) + HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, NULL,"Can't insert property into class"); - /* Insert the property into the new property class */ - if(H5P_add_prop(new_class->props,pclass->hashsize,pcopy)<0) - HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, FAIL,"Can't insert property into class"); + /* Increment property count for class */ + new_class->nprops++; - /* Go to next registered property in class */ - tmp_prop=tmp_prop->next; + /* Get the next property node in the TBBT */ + curr_node=H5TB_next(curr_node); } /* end while */ - } /* end for */ + } /* end if */ /* Use the new class instead of the old one */ pclass=new_class; } /* end if */ /* Create property object from parameters */ - if((new_prop=H5P_create_prop(name,size,def_value,NULL,prp_create,prp_set,prp_get,prp_delete,prp_copy,prp_close))==NULL) + if((new_prop=H5P_create_prop(name,size,H5P_PROP_WITHIN_CLASS,def_value,prp_create,prp_set,prp_get,prp_delete,prp_copy,prp_close))==NULL) HGOTO_ERROR (H5E_PLIST, H5E_CANTCREATE, FAIL,"Can't create property"); /* Insert property into property list class */ - if(H5P_add_prop(pclass->props,pclass->hashsize,new_prop)<0) + if(H5P_add_prop(pclass->props,new_prop)<0) HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, FAIL,"Can't insert property into class"); /* Increment property count for class */ pclass->nprops++; + /* Update the revision for the class */ + pclass->revision = H5P_GET_NEXT_REV; + done: if(ret_value==FAIL) { if(new_prop!=NULL) { @@ -1707,9 +1909,7 @@ done: H5MM_xfree(new_prop->name); if(new_prop->value!=NULL) H5MM_xfree(new_prop->value); - if(new_prop->def_value!=NULL) - H5MM_xfree(new_prop->def_value); - H5MM_xfree(new_prop); + H5FL_FREE(H5P_genprop_t,new_prop); } /* end if */ } /* end if */ FUNC_LEAVE (ret_value); @@ -1847,7 +2047,8 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -herr_t H5Pregister(hid_t cls_id, const char *name, size_t size, void *def_value, +herr_t +H5Pregister(hid_t cls_id, const char *name, size_t size, void *def_value, H5P_prp_create_func_t prp_create, H5P_prp_set_func_t prp_set, H5P_prp_get_func_t prp_get, H5P_prp_delete_func_t prp_delete, H5P_prp_copy_func_t prp_copy, H5P_prp_close_func_t prp_close) @@ -1986,8 +2187,9 @@ H5P_insert(H5P_genplist_t *plist, const char *name, size_t size, H5P_prp_delete_func_t prp_delete, H5P_prp_copy_func_t prp_copy, H5P_prp_close_func_t prp_close) { - H5P_genprop_t *new_prop=NULL; /* Temporary property pointer */ - herr_t ret_value=SUCCEED; /* Return value */ + H5P_genprop_t *new_prop=NULL; /* Temporary property pointer */ + H5TB_NODE *prop_node; /* TBBT node holding property */ + herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOINIT(H5P_insert); @@ -1996,15 +2198,44 @@ H5P_insert(H5P_genplist_t *plist, const char *name, size_t size, assert((size>0 && value!=NULL) || (size==0)); /* Check for duplicate named properties */ - if(H5P_find_prop(plist->props,plist->pclass->hashsize,name)!=NULL) + if(H5TB_dfind(plist->props,name,NULL)!=NULL) HGOTO_ERROR(H5E_PLIST, H5E_EXISTS, FAIL, "property already exists"); + /* Check if the property has been deleted */ + if((prop_node=H5TB_dfind(plist->del,name,NULL))!=NULL) { + /* Remove the property name from the deleted property TBBT */ + if(H5TB_rem(&plist->del->root,prop_node,NULL)==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTDELETE,FAIL,"can't remove property from deleted TBBT"); + + /* Fall through to add property to list */ + } /* end if */ + else { + H5P_genclass_t *tclass; /* Temporary class pointer */ + + /* Check if the property is already in the class hierarchy */ + tclass=plist->pclass; + while(tclass!=NULL) { + if(tclass->nprops>0) { + /* Find the property in the class */ + if(H5TB_dfind(tclass->props,name,NULL)!=NULL) + HGOTO_ERROR(H5E_PLIST, H5E_EXISTS, FAIL, "property already exists"); + } /* end if */ + + /* Go up to parent class */ + tclass=tclass->parent; + } /* end while */ + + /* Fall through to add property to list */ + } /* end else */ + + /* Ok to add to property list */ + /* Create property object from parameters */ - if((new_prop=H5P_create_prop(name,size,NULL,value,NULL,prp_set,prp_get,prp_delete,prp_copy,prp_close))==NULL) + if((new_prop=H5P_create_prop(name,size,H5P_PROP_WITHIN_LIST,value,NULL,prp_set,prp_get,prp_delete,prp_copy,prp_close))==NULL) HGOTO_ERROR (H5E_PLIST, H5E_CANTCREATE, FAIL,"Can't create property"); /* Insert property into property list class */ - if(H5P_add_prop(plist->props,plist->pclass->hashsize,new_prop)<0) + if(H5P_add_prop(plist->props,new_prop)<0) HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, FAIL,"Can't insert property into class"); /* Increment property count for class */ @@ -2017,9 +2248,7 @@ done: H5MM_xfree(new_prop->name); if(new_prop->value!=NULL) H5MM_xfree(new_prop->value); - if(new_prop->def_value!=NULL) - H5MM_xfree(new_prop->def_value); - H5MM_xfree(new_prop); + H5FL_FREE(H5P_genprop_t,new_prop); } /* end if */ } /* end if */ @@ -2132,7 +2361,8 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -herr_t H5Pinsert(hid_t plist_id, const char *name, size_t size, void *value, +herr_t +H5Pinsert(hid_t plist_id, const char *name, size_t size, void *value, H5P_prp_set_func_t prp_set, H5P_prp_get_func_t prp_get, H5P_prp_delete_func_t prp_delete, H5P_prp_copy_func_t prp_copy, H5P_prp_close_func_t prp_close) @@ -2190,9 +2420,12 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -herr_t H5P_set(H5P_genplist_t *plist, const char *name, const void *value) +herr_t +H5P_set(H5P_genplist_t *plist, const char *name, const void *value) { + H5P_genclass_t *tclass; /* Temporary class pointer */ H5P_genprop_t *prop; /* Temporary property pointer */ + H5TB_NODE *prop_node; /* TBBT node holding property */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5P_set, FAIL); @@ -2201,36 +2434,123 @@ herr_t H5P_set(H5P_genplist_t *plist, const char *name, const void *value) assert(name); assert(value); - /* Find property */ - if((prop=H5P_find_prop(plist->props,plist->pclass->hashsize,name))==NULL) + /* Check if the property has been deleted */ + if(H5TB_dfind(plist->del,name,NULL)!=NULL) HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property doesn't exist"); - /* Check for property size >0 */ - if(prop->size==0) - HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "property has zero size"); + /* Find property in changed list */ + if((prop_node=H5TB_dfind(plist->props,name,NULL))!=NULL) { + /* Get pointer to actual property */ + prop=prop_node->data; + + /* Check for property size >0 */ + if(prop->size==0) + HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "property has zero size"); - /* Make a copy of the value and pass to 'set' callback */ - if(prop->set!=NULL) { - void *tmp_value; /* Temporary value for property */ + /* Make a copy of the value and pass to 'set' callback */ + if(prop->set!=NULL) { + void *tmp_value; /* Temporary value for property */ - /* Make a copy of the current value, in case the callback fails */ - if (NULL==(tmp_value=H5MM_malloc(prop->size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed temporary property value"); - HDmemcpy(tmp_value,value,prop->size); + /* Make a copy of the current value, in case the callback fails */ + if (NULL==(tmp_value=H5MM_malloc(prop->size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed temporary property value"); + HDmemcpy(tmp_value,value,prop->size); - /* Call user's callback */ - if((*(prop->set))(plist->plist_id,name,prop->size,tmp_value)<0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't set property value"); + /* Call user's callback */ + if((*(prop->set))(plist->plist_id,name,prop->size,tmp_value)<0) { + H5MM_xfree(tmp_value); + HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't set property value"); + } /* end if */ - /* Copy new [possibly unchanged] value into property value */ - HDmemcpy(prop->value,tmp_value,prop->size); + /* Copy new [possibly unchanged] value into property value */ + HDmemcpy(prop->value,tmp_value,prop->size); - /* Free the temporary value buffer */ - H5MM_xfree(tmp_value); + /* Free the temporary value buffer */ + H5MM_xfree(tmp_value); + } /* end if */ + /* No 'set' callback, just copy value */ + else + HDmemcpy(prop->value,value,prop->size); } /* end if */ - /* No 'set' callback, just copy value */ - else - HDmemcpy(prop->value,value,prop->size); + else { + /* + * Check if we should set class properties (up through list of parent classes also), + * & make property 'set' callback. + */ + tclass=plist->pclass; + while(tclass!=NULL) { + if(tclass->nprops>0) { + /* Find the property in the class */ + if((prop_node=H5TB_dfind(tclass->props,name,NULL))!=NULL) { + H5P_genprop_t *pcopy; /* Copy of property to insert into TBBT */ + + /* Get pointer to actual property */ + prop=prop_node->data; + + /* Check for property size >0 */ + if(prop->size==0) + HGOTO_ERROR(H5E_PLIST,H5E_BADVALUE,FAIL,"property has zero size"); + + /* Make a copy of the value and pass to 'set' callback */ + if(prop->set!=NULL) { + void *tmp_value; /* Temporary value for property */ + + /* Make a copy of the current value, in case the callback fails */ + if (NULL==(tmp_value=H5MM_malloc(prop->size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed temporary property value"); + HDmemcpy(tmp_value,value,prop->size); + + /* Call user's callback */ + if((*(prop->set))(plist->plist_id,name,prop->size,tmp_value)<0) { + H5MM_xfree(tmp_value); + HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't set property value"); + } /* end if */ + + if(HDmemcmp(tmp_value,prop->value,prop->size)) { + /* Make a copy of the class's property */ + if((pcopy=H5P_dup_prop(prop,H5P_PROP_WITHIN_LIST))==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTCOPY,FAIL,"Can't copy property"); + + /* Copy new value into property value */ + HDmemcpy(pcopy->value,tmp_value,pcopy->size); + + /* Insert the changed property into the property list */ + if(H5P_add_prop(plist->props,pcopy)<0) + HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, FAIL,"Can't insert changed property into TBBT"); + } /* end if */ + + /* Free the temporary value buffer */ + H5MM_xfree(tmp_value); + } /* end if */ + /* No 'set' callback, just copy value */ + else { + if(HDmemcmp(value,prop->value,prop->size)) { + /* Make a copy of the class's property */ + if((pcopy=H5P_dup_prop(prop,H5P_PROP_WITHIN_LIST))==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTCOPY,FAIL,"Can't copy property"); + + HDmemcpy(pcopy->value,value,pcopy->size); + + /* Insert the changed property into the property list */ + if(H5P_add_prop(plist->props,pcopy)<0) + HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, FAIL,"Can't insert changed property into TBBT"); + } /* end if */ + } /* end else */ + + /* Leave */ + HGOTO_DONE(SUCCEED); + } /* end while */ + } /* end if */ + + /* Go up to parent class */ + tclass=tclass->parent; + } /* end while */ + + /* If we get this far, then it wasn't in the list of changed properties, + * nor in the properties in the class hierarchy, indicate an error + */ + HGOTO_ERROR(H5E_PLIST,H5E_NOTFOUND,FAIL,"can't find property in TBBT"); + } /* end else */ done: FUNC_LEAVE (ret_value); @@ -2268,7 +2588,8 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -herr_t H5Pset(hid_t plist_id, const char *name, void *value) +herr_t +H5Pset(hid_t plist_id, const char *name, void *value) { H5P_genplist_t *plist; /* Property list to modify */ herr_t ret_value=SUCCEED; /* return value */ @@ -2323,12 +2644,31 @@ H5P_exist_plist(H5P_genplist_t *plist, const char *name) assert(plist); assert(name); - /* Check for property in property list */ - if(H5P_find_prop(plist->props,plist->pclass->hashsize,name)==NULL) + /* Check for property in deleted property list */ + if(H5TB_dfind(plist->del,name,NULL)!=NULL) ret_value=0; - else - ret_value=1; + else { + /* Check for property in changed property list */ + if(H5TB_dfind(plist->props,name,NULL)!=NULL) + ret_value=1; + else { + H5P_genclass_t *tclass; /* Temporary class pointer */ + + tclass=plist->pclass; + while(tclass!=NULL) { + if(H5TB_dfind(tclass->props,name,NULL)!=NULL) + HGOTO_DONE(1); + + /* Go up to parent class */ + tclass=tclass->parent; + } /* end while */ + + /* If we've reached here, we couldn't find the property */ + ret_value=0; + } /* end else */ + } /* end else */ +done: FUNC_LEAVE (ret_value); } /* H5P_exist_plist() */ @@ -2365,7 +2705,7 @@ H5P_exist_pclass(H5P_genclass_t *pclass, const char *name) assert(name); /* Check for property in property list */ - if(H5P_find_prop(pclass->props,pclass->hashsize,name)==NULL) + if(H5TB_dfind(pclass->props,name,NULL)==NULL) ret_value=0; else ret_value=1; @@ -2396,7 +2736,8 @@ H5P_exist_pclass(H5P_genclass_t *pclass, const char *name) EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -htri_t H5Pexist(hid_t id, const char *name) +htri_t +H5Pexist(hid_t id, const char *name) { H5P_genplist_t *plist; /* Property list to query */ H5P_genclass_t *pclass; /* Property class to query */ @@ -2467,7 +2808,7 @@ H5P_get_size_plist(H5P_genplist_t *plist, const char *name, size_t *size) assert(size); /* Find property */ - if((prop=H5P_find_prop(plist->props,plist->pclass->hashsize,name))==NULL) + if((prop=H5P_find_prop_plist(plist,name))==NULL) HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property doesn't exist"); /* Get property size */ @@ -2513,7 +2854,7 @@ H5P_get_size_pclass(H5P_genclass_t *pclass, const char *name, size_t *size) assert(size); /* Find property */ - if((prop=H5P_find_prop(pclass->props,pclass->hashsize,name))==NULL) + if((prop=H5P_find_prop_pclass(pclass,name))==NULL) HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property doesn't exist"); /* Get property size */ @@ -2547,7 +2888,8 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -herr_t H5Pget_size(hid_t id, const char *name, size_t *size) +herr_t +H5Pget_size(hid_t id, const char *name, size_t *size) { H5P_genclass_t *pclass; /* Property class to query */ H5P_genplist_t *plist; /* Property list to query */ @@ -2643,7 +2985,8 @@ H5P_get_class(H5P_genplist_t *plist) EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -hid_t H5Pget_class(hid_t plist_id) +hid_t +H5Pget_class(hid_t plist_id) { H5P_genplist_t *plist; /* Property list to query */ H5P_genclass_t *pclass=NULL; /* Property list class */ @@ -2730,7 +3073,8 @@ H5P_get_nprops_plist(H5P_genplist_t *plist, size_t *nprops) EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -herr_t H5P_get_nprops_pclass(H5P_genclass_t *pclass, size_t *nprops) +herr_t +H5P_get_nprops_pclass(H5P_genclass_t *pclass, size_t *nprops) { herr_t ret_value=SUCCEED; /* Return value */ @@ -2770,7 +3114,8 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -herr_t H5Pget_nprops(hid_t id, size_t *nprops) +herr_t +H5Pget_nprops(hid_t id, size_t *nprops) { H5P_genplist_t *plist; /* Property list to query */ H5P_genclass_t *pclass; /* Property class to query */ @@ -2853,13 +3198,6 @@ H5P_cmp_prop(H5P_genprop_t *prop1, H5P_genprop_t *prop2) if((cmp_value=HDmemcmp(prop1->value,prop2->value,prop1->size))!=0) HGOTO_DONE(cmp_value); - /* Check if they both have default values allocated (or not allocated) */ - if(prop1->def_value==NULL && prop2->def_value!=NULL) HGOTO_DONE(-1); - if(prop1->def_value!=NULL && prop2->def_value==NULL) HGOTO_DONE(1); - if(prop1->def_value!=NULL) - if((cmp_value=HDmemcmp(prop1->def_value,prop2->def_value,prop1->size))!=0) - HGOTO_DONE(cmp_value); - /* Check if they both have the same 'create' callback */ if(prop1->create==NULL && prop2->create!=NULL) HGOTO_DONE(-1); if(prop1->create!=NULL && prop2->create==NULL) HGOTO_DONE(1); @@ -2890,8 +3228,6 @@ H5P_cmp_prop(H5P_genprop_t *prop1, H5P_genprop_t *prop2) if(prop1->close!=NULL && prop2->close==NULL) HGOTO_DONE(1); if(prop1->close!=prop2->close) HGOTO_DONE(-1); - /* Don't check the 'next' field, they must be equal by now */ - done: FUNC_LEAVE (ret_value); } /* H5P_cmp_prop() */ @@ -2922,16 +3258,19 @@ done: static int H5P_cmp_class(H5P_genclass_t *pclass1, H5P_genclass_t *pclass2) { - H5P_genprop_t *tprop1, *tprop2;/* Temporary pointer to properties */ - unsigned u; /* Local index variable */ - int cmp_value; /* Value from comparison */ - int ret_value=0; /* return value */ + H5TB_NODE *tnode1,*tnode2; /* Temporary pointer to propery nodes */ + int cmp_value; /* Value from comparison */ + int ret_value=0; /* Return value */ FUNC_ENTER_NOINIT(H5P_cmp_class); assert(pclass1); assert(pclass2); + /* Use the revision number to quickly check for identical classes */ + if(pclass1->revision==pclass2->revision) + HGOTO_DONE(0); + /* Check the name */ if((cmp_value=HDstrcmp(pclass1->name,pclass2->name))!=0) HGOTO_DONE(cmp_value); @@ -2940,10 +3279,6 @@ H5P_cmp_class(H5P_genclass_t *pclass1, H5P_genclass_t *pclass2) if(pclass1->nprops < pclass2->nprops) HGOTO_DONE(-1); if(pclass1->nprops > pclass2->nprops) HGOTO_DONE(1); - /* Check the hashsize */ - if(pclass1->hashsize < pclass2->hashsize) HGOTO_DONE(-1); - if(pclass1->hashsize > pclass2->hashsize) HGOTO_DONE(1); - /* Check the number of property lists created from the class */ if(pclass1->plists < pclass2->plists) HGOTO_DONE(-1); if(pclass1->plists > pclass2->plists) HGOTO_DONE(1); @@ -2979,29 +3314,21 @@ H5P_cmp_class(H5P_genclass_t *pclass1, H5P_genclass_t *pclass2) if(pclass1->close_data > pclass2->close_data) HGOTO_DONE(1); /* Cycle through the properties and compare them also */ - for(u=0; uhashsize; u++) { - tprop1=pclass1->props[u]; - tprop2=pclass2->props[u]; - - /* Check if they both have properties in this hash location */ - if(tprop1==NULL && tprop2!=NULL) HGOTO_DONE(-1); - if(tprop1!=NULL && tprop2==NULL) HGOTO_DONE(1); - - /* Check the actual properties */ - while(tprop1!=NULL && tprop2!=NULL) { - /* Compare the two properties */ - if((cmp_value=H5P_cmp_prop(tprop1,tprop2))!=0) - HGOTO_DONE(cmp_value); - - /* Advance the pointers */ - tprop1=tprop1->next; - tprop2=tprop2->next; + tnode1=H5TB_first(pclass1->props->root); + tnode2=H5TB_first(pclass2->props->root); + while(tnode1 || tnode2) { + /* Check if they both have properties in this TBBT node */ + if(tnode1==NULL && tnode2!=NULL) HGOTO_DONE(-1); + if(tnode1!=NULL && tnode2==NULL) HGOTO_DONE(1); + + /* Compare the two properties */ + if((cmp_value=H5P_cmp_prop(tnode1->data,tnode2->data))!=0) + HGOTO_DONE(cmp_value); - /* Check if they both have properties in this location */ - if(tprop1==NULL && tprop2!=NULL) HGOTO_DONE(-1); - if(tprop1!=NULL && tprop2==NULL) HGOTO_DONE(1); - } /* end while */ - } /* end for */ + /* Advance the pointers */ + tnode1=H5TB_next(tnode1); + tnode2=H5TB_next(tnode2); + } /* end while */ done: FUNC_LEAVE (ret_value); @@ -3033,8 +3360,7 @@ done: static int H5P_cmp_plist(H5P_genplist_t *plist1, H5P_genplist_t *plist2) { - H5P_genprop_t *tprop1, *tprop2;/* Temporary pointer to properties */ - unsigned u; /* Local index variable */ + H5TB_NODE *tnode1,*tnode2; /* Temporary pointer to propery nodes */ int cmp_value; /* Value from comparison */ int ret_value=0; /* return value */ @@ -3043,10 +3369,6 @@ H5P_cmp_plist(H5P_genplist_t *plist1, H5P_genplist_t *plist2) assert(plist1); assert(plist2); - /* Check the parent class */ - if(plist1->pclass < plist2->pclass) HGOTO_DONE(-1); - if(plist1->pclass > plist2->pclass) HGOTO_DONE(1); - /* Check the number of properties */ if(plist1->nprops < plist2->nprops) HGOTO_DONE(-1); if(plist1->nprops > plist2->nprops) HGOTO_DONE(1); @@ -3055,24 +3377,57 @@ H5P_cmp_plist(H5P_genplist_t *plist1, H5P_genplist_t *plist2) if(plist1->class_init < plist2->class_init) HGOTO_DONE(-1); if(plist1->class_init > plist2->class_init) HGOTO_DONE(1); - /* Cycle through the properties and compare them also */ - for(u=0; upclass->hashsize; u++) { - tprop1=plist1->props[u]; + /* Check for identical deleted properties */ + if(plist1->del->root) { + /* Check for no deleted properties in plist2 */ + if(plist2->del->root==NULL) HGOTO_DONE(1); + + tnode1=H5TB_first(plist1->del->root); + tnode2=H5TB_first(plist2->del->root); + while(tnode1 || tnode2) { + /* Check if they both have properties in this TBBT node */ + if(tnode1==NULL && tnode2!=NULL) HGOTO_DONE(-1); + if(tnode1!=NULL && tnode2==NULL) HGOTO_DONE(1); + + /* Compare the two deleted properties */ + if((cmp_value=HDstrcmp(tnode1->data,tnode2->data))!=0) + HGOTO_DONE(cmp_value); + + /* Advance the pointers */ + tnode1=H5TB_next(tnode1); + tnode2=H5TB_next(tnode2); + } /* end while */ + } /* end if */ + else + if(plist2->del->root!=NULL) HGOTO_DONE (-1); - /* Check the actual properties */ - while(tprop1!=NULL) { - /* Find a property with the same name in the second property list */ - if((tprop2=H5P_find_prop(plist2->props,plist2->pclass->hashsize,tprop1->name))==NULL) - HGOTO_DONE(1); + /* Cycle through the changed properties and compare them also */ + if(plist1->props->root) { + /* Check for no changed properties in plist2 */ + if(plist2->props->root==NULL) HGOTO_DONE(1); + + tnode1=H5TB_first(plist1->props->root); + tnode2=H5TB_first(plist2->props->root); + while(tnode1 || tnode2) { + /* Check if they both have properties in this TBBT node */ + if(tnode1==NULL && tnode2!=NULL) HGOTO_DONE(-1); + if(tnode1!=NULL && tnode2==NULL) HGOTO_DONE(1); /* Compare the two properties */ - if((cmp_value=H5P_cmp_prop(tprop1,tprop2))!=0) + if((cmp_value=H5P_cmp_prop(tnode1->data,tnode2->data))!=0) HGOTO_DONE(cmp_value); - /* Advance to next property */ - tprop1=tprop1->next; + /* Advance the pointers */ + tnode1=H5TB_next(tnode1); + tnode2=H5TB_next(tnode2); } /* end while */ - } /* end for */ + } /* end if */ + else + if(plist2->props->root!=NULL) HGOTO_DONE (-1); + + /* Check the parent classes */ + if((cmp_value=H5P_cmp_class(plist1->pclass,plist2->pclass))!=0) + HGOTO_DONE(cmp_value); done: FUNC_LEAVE (ret_value); @@ -3099,7 +3454,8 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -htri_t H5Pequal(hid_t id1, hid_t id2) +htri_t +H5Pequal(hid_t id1, hid_t id2) { void *obj1, *obj2; /* Property objects to compare */ htri_t ret_value=FALSE; /* return value */ @@ -3205,7 +3561,8 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -htri_t H5P_isa_class(hid_t plist_id, hid_t pclass_id) +htri_t +H5P_isa_class(hid_t plist_id, hid_t pclass_id) { H5P_genplist_t *plist; /* Property list to query */ H5P_genclass_t *pclass; /* Property list class */ @@ -3251,7 +3608,8 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -htri_t H5Pisa_class(hid_t plist_id, hid_t pclass_id) +htri_t +H5Pisa_class(hid_t plist_id, hid_t pclass_id) { htri_t ret_value; /* return value */ @@ -3300,7 +3658,8 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -void *H5P_object_verify(hid_t plist_id, hid_t pclass_id) +void * +H5P_object_verify(hid_t plist_id, hid_t pclass_id) { void *ret_value; /* return value */ @@ -3321,100 +3680,6 @@ done: /*-------------------------------------------------------------------------- NAME - H5P_iterate_props - PURPOSE - Internal routine to iterate over a hashtable of properties - USAGE - herr_t H5P_iterate_props(id, hash, hashsize, idx, iter_func, iter_data) - hid_t id; IN: ID of property object iterating over - H5P_gen_prop_t *hash[]; IN: Pointer to array of properties for hash table - unsigned hashsize; IN: Size of hash table - int *idx; IN/OUT: Index of the property to begin with - H5P_iterate_t iter_func; IN: Function pointer to function to be - called with each property iterated over. - void *iter_data; IN/OUT: Pointer to iteration data from user - RETURNS - Success: Returns the return value of the last call to ITER_FUNC if it was - non-zero, or zero if all properties have been processed. - Failure: negative value - DESCRIPTION - This routine iterates over the properties in the property object specified -with ID. For each property in the object, the ITER_DATA and some -additional information, specified below, are passed to the ITER_FUNC function. -The iteration begins with the IDX property in the object and the next element -to be processed by the operator is returned in IDX. If IDX is NULL, then the -iterator starts at the first property; since no stopping point is returned in -this case, the iterator cannot be restarted if one of the calls to its operator -returns non-zero. - -The prototype for H5P_iterate_t is: - typedef herr_t (*H5P_iterate_t)(hid_t id, const char *name, void *iter_data); -The operation receives the property list or class identifier for the object -being iterated over, ID, the name of the current property within the object, -NAME, and the pointer to the operator data passed in to H5Piterate, ITER_DATA. - -The return values from an operator are: - Zero causes the iterator to continue, returning zero when all properties - have been processed. - Positive causes the iterator to immediately return that positive value, - indicating short-circuit success. The iterator can be restarted at the - index of the next property. - Negative causes the iterator to immediately return that value, indicating - failure. The iterator can be restarted at the index of the next - property. - -H5Piterate assumes that the properties in the object identified by ID remains -unchanged through the iteration. If the membership changes during the -iteration, the function's behavior is undefined. - - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ -static int -H5P_iterate_props(hid_t id, H5P_genprop_t *hash[], unsigned hashsize, int *idx, H5P_iterate_t iter_func, void *iter_data) -{ - H5P_genprop_t *prop; /* Temporary property pointer */ - unsigned u; /* Local index variable */ - int curr_idx=0; /* Current iteration index */ - int ret_value=0; /* Return value */ - - FUNC_ENTER_NOINIT(H5P_iterate_props); - - assert(hash); - assert(hashsize>0); - assert(idx); - assert(iter_func); - - /* Cycle through the properties and compare them also */ - for(u=0; u=*idx) - ret_value=(*iter_func)(id,prop->name,iter_data); - - /* Increment the iteration index if iteration function succeeded */ - if(ret_value==0) - curr_idx++; - - /* Advance the pointer */ - prop=prop->next; - } /* end while */ - } /* end for */ - - /* Set the index we stopped at */ - *idx=curr_idx; - - FUNC_LEAVE (ret_value); -} /* H5P_iterate_props() */ - - -/*-------------------------------------------------------------------------- - NAME H5P_iterate_plist PURPOSE Internal routine to iterate over the properties in a property list @@ -3467,8 +3732,13 @@ iteration, the function's behavior is undefined. static int H5P_iterate_plist(hid_t plist_id, int *idx, H5P_iterate_t iter_func, void *iter_data) { + H5P_genclass_t *tclass; /* Temporary class pointer */ H5P_genplist_t *plist; /* Property list pointer */ - int ret_value; /* Return value */ + H5P_genprop_t *tmp; /* Temporary pointer to properties */ + H5TB_TREE *seen=NULL; /* TBBT to hold names of properties already seen */ + H5TB_NODE *curr_node; /* Current node in TBBT */ + int curr_idx=0; /* Current iteration index */ + int ret_value=FAIL; /* Return value */ FUNC_ENTER_NOINIT(H5P_iterate_plist); @@ -3479,10 +3749,90 @@ H5P_iterate_plist(hid_t plist_id, int *idx, H5P_iterate_t iter_func, void *iter_ if (NULL == (plist = H5I_object_verify(plist_id, H5I_GENPROP_LST))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list"); - /* Iterate through the properties in the property list */ - ret_value=H5P_iterate_props(plist_id, plist->props, plist->pclass->hashsize, idx, iter_func, iter_data); + /* Create the TBBT to hold names of properties already seen + */ + if((seen=H5TB_fast_dmake(H5TB_FAST_STR_COMPARE))==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTMAKETREE,NULL,"can't create TBBT for seen properties"); + + /* Walk through the changed properties in the list */ + if(plist->props->root) { + curr_node=H5TB_first(plist->props->root); + while(curr_node!=NULL) { + /* Get pointer to property from node */ + tmp=curr_node->data; + + /* Check if we've found the correctly indexed property */ + if(curr_idx>=*idx) { + /* Call the callback function */ + ret_value=(*iter_func)(plist_id,tmp->name,iter_data); + + if(ret_value!=0) + HGOTO_DONE(ret_value); + } /* end if */ + + /* Increment the current index */ + curr_idx++; + + /* Add property name to "seen" list */ + if(H5TB_dins(seen,tmp->name,tmp->name)==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTINSERT,NULL,"can't insert property into seen TBBT"); + + /* Get the next property node in the TBBT */ + curr_node=H5TB_next(curr_node); + } /* end while */ + } /* end if */ + + /* Walk up the class hiearchy */ + tclass=plist->pclass; + while(tclass!=NULL) { + if(tclass->nprops>0) { + /* Walk through the properties in the class */ + curr_node=H5TB_first(tclass->props->root); + while(curr_node!=NULL) { + /* Get pointer to property from node */ + tmp=curr_node->data; + + /* Only call iterator callback for properties we haven't seen + * before and that haven't been deleted + */ + if(H5TB_dfind(seen,tmp->name,NULL)==NULL && + H5TB_dfind(plist->del,tmp->name,NULL)==NULL) { + + + /* Check if we've found the correctly indexed property */ + if(curr_idx>=*idx) { + /* Call the callback function */ + ret_value=(*iter_func)(plist_id,tmp->name,iter_data); + + if(ret_value!=0) + HGOTO_DONE(ret_value); + } /* end if */ + + /* Increment the current index */ + curr_idx++; + + /* Add property name to "seen" list */ + if(H5TB_dins(seen,tmp->name,tmp->name)==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTINSERT,NULL,"can't insert property into seen TBBT"); + } /* end if */ + + /* Get the next property node in the TBBT */ + curr_node=H5TB_next(curr_node); + } /* end while */ + } /* end if */ + + /* Go up to parent class */ + tclass=tclass->parent; + } /* end while */ done: + /* Set the index we stopped at */ + *idx=curr_idx; + + /* Release the tree of 'seen' properties */ + if(seen!=NULL) + H5TB_dfree(seen,NULL,NULL); + FUNC_LEAVE (ret_value); } /* H5P_iterate_plist() */ @@ -3542,7 +3892,10 @@ static int H5P_iterate_pclass(hid_t pclass_id, int *idx, H5P_iterate_t iter_func, void *iter_data) { H5P_genclass_t *pclass; /* Property list pointer */ - int ret_value; /* Return value */ + H5TB_NODE *curr_node; /* Current node in TBBT */ + H5P_genprop_t *prop; /* Temporary property pointer */ + int curr_idx=0; /* Current iteration index */ + int ret_value=FAIL; /* Return value */ FUNC_ENTER_NOINIT(H5P_iterate_pclass); @@ -3553,10 +3906,33 @@ H5P_iterate_pclass(hid_t pclass_id, int *idx, H5P_iterate_t iter_func, void *ite if (NULL == (pclass = H5I_object_verify(pclass_id, H5I_GENPROP_CLS))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property class"); - /* Iterate through the properties in the property list */ - ret_value=H5P_iterate_props(pclass_id, pclass->props, pclass->hashsize, idx, iter_func, iter_data); + /* Set the current index */ + curr_idx=*idx; + + /* Cycle through the properties and call the callback */ + curr_node=H5TB_index(pclass->props->root,(unsigned)*idx); + while(curr_node!=NULL) { + /* Get the property for the node */ + prop=curr_node->data; + + /* Call the callback function */ + ret_value=(*iter_func)(pclass_id,prop->name,iter_data); + + /* Check if iteration function succeeded */ + if(ret_value!=0) + HGOTO_DONE(ret_value); + + /* Increment the iteration index */ + curr_idx++; + + /* Get the next property node in the TBBT */ + curr_node=H5TB_next(curr_node); + } /* end while */ done: + /* Set the index we stopped at */ + *idx=curr_idx; + FUNC_LEAVE (ret_value); } /* H5P_iterate_pclass() */ @@ -3613,7 +3989,8 @@ iteration, the function's behavior is undefined. EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -int H5Piterate(hid_t id, int *idx, H5P_iterate_t iter_func, void *iter_data) +int +H5Piterate(hid_t id, int *idx, H5P_iterate_t iter_func, void *iter_data) { int fake_idx=0; /* Index when user doesn't provide one */ int ret_value; /* return value */ @@ -3672,7 +4049,8 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -unsigned H5P_peek_unsigned(H5P_genplist_t *plist, const char *name) +unsigned +H5P_peek_unsigned(H5P_genplist_t *plist, const char *name) { unsigned ret_value; /* return value */ @@ -3716,7 +4094,8 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -hid_t H5P_peek_hid_t(H5P_genplist_t *plist, const char *name) +hid_t +H5P_peek_hid_t(H5P_genplist_t *plist, const char *name) { hid_t ret_value; /* return value */ @@ -3760,7 +4139,8 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -void *H5P_peek_voidp(H5P_genplist_t *plist, const char *name) +void * +H5P_peek_voidp(H5P_genplist_t *plist, const char *name) { void * ret_value; /* return value */ @@ -3804,7 +4184,8 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -hsize_t H5P_peek_hsize_t(H5P_genplist_t *plist, const char *name) +hsize_t +H5P_peek_hsize_t(H5P_genplist_t *plist, const char *name) { hsize_t ret_value; /* return value */ @@ -3848,7 +4229,8 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -size_t H5P_peek_size_t(H5P_genplist_t *plist, const char *name) +size_t +H5P_peek_size_t(H5P_genplist_t *plist, const char *name) { size_t ret_value; /* return value */ @@ -3893,9 +4275,12 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -herr_t H5P_get(H5P_genplist_t *plist, const char *name, void *value) +herr_t +H5P_get(H5P_genplist_t *plist, const char *name, void *value) { + H5P_genclass_t *tclass; /* Temporary class pointer */ H5P_genprop_t *prop; /* Temporary property pointer */ + H5TB_NODE *prop_node; /* TBBT node holding property */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5P_get, FAIL); @@ -3904,36 +4289,113 @@ herr_t H5P_get(H5P_genplist_t *plist, const char *name, void *value) assert(name); assert(value); - /* Find property */ - if((prop=H5P_find_prop(plist->props,plist->pclass->hashsize,name))==NULL) + /* Check if the property has been deleted */ + if(H5TB_dfind(plist->del,name,NULL)!=NULL) HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property doesn't exist"); - /* Check for property size >0 */ - if(prop->size==0) - HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "property has zero size"); + /* Find property */ + if((prop_node=H5TB_dfind(plist->props,name,NULL))!=NULL) { + /* Get pointer to actual property */ + prop=prop_node->data; + + /* Check for property size >0 */ + if(prop->size==0) + HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "property has zero size"); - /* Make a copy of the value and pass to 'get' callback */ - if(prop->get!=NULL) { - void *tmp_value; /* Temporary value for property */ + /* Make a copy of the value and pass to 'get' callback */ + if(prop->get!=NULL) { + void *tmp_value; /* Temporary value for property */ - /* Make a copy of the current value, in case the callback fails */ - if (NULL==(tmp_value=H5MM_malloc(prop->size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed temporary property value"); - HDmemcpy(tmp_value,prop->value,prop->size); + /* Make a copy of the current value, in case the callback fails */ + if (NULL==(tmp_value=H5MM_malloc(prop->size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed temporary property value"); + HDmemcpy(tmp_value,prop->value,prop->size); - /* Call user's callback */ - if((*(prop->get))(plist->plist_id,name,prop->size,tmp_value)<0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't get property value"); + /* Call user's callback */ + if((*(prop->get))(plist->plist_id,name,prop->size,tmp_value)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't get property value"); - /* Copy new [possibly unchanged] value into return value */ - HDmemcpy(value,tmp_value,prop->size); + /* Copy new [possibly unchanged] value into return value */ + HDmemcpy(value,tmp_value,prop->size); - /* Free the temporary value buffer */ - H5MM_xfree(tmp_value); + /* Free the temporary value buffer */ + H5MM_xfree(tmp_value); + } /* end if */ + /* No 'get' callback, just copy value */ + else + HDmemcpy(value,prop->value,prop->size); } /* end if */ - /* No 'get' callback, just copy value */ - else - HDmemcpy(value,prop->value,prop->size); + else { + /* + * Check if we should get class properties (up through list of parent classes also), + * & make property 'get' callback. + */ + tclass=plist->pclass; + while(tclass!=NULL) { + if(tclass->nprops>0) { + /* Find the property in the class */ + if((prop_node=H5TB_dfind(tclass->props,name,NULL))!=NULL) { + /* Get pointer to actual property */ + prop=prop_node->data; + + /* Check for property size >0 */ + if(prop->size==0) + HGOTO_ERROR(H5E_PLIST,H5E_BADVALUE,FAIL,"property has zero size"); + + /* Call the 'get' callback, if there is one */ + if(prop->get!=NULL) { + void *tmp_value; /* Temporary value for property */ + + /* Make a copy of the current value, in case the callback fails */ + if (NULL==(tmp_value=H5MM_malloc(prop->size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed temporary property value"); + HDmemcpy(tmp_value,prop->value,prop->size); + + /* Call user's callback */ + if((*(prop->get))(plist->plist_id,name,prop->size,tmp_value)<0) { + H5MM_xfree(tmp_value); + HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't set property value"); + } /* end if */ + + if(HDmemcmp(tmp_value,prop->value,prop->size)) { + H5P_genprop_t *pcopy; /* Copy of property to insert into TBBT */ + + /* Make a copy of the class's property */ + if((pcopy=H5P_dup_prop(prop,H5P_PROP_WITHIN_LIST))==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTCOPY,FAIL,"Can't copy property"); + + /* Copy new value into property value */ + HDmemcpy(pcopy->value,tmp_value,prop->size); + + /* Insert the changed property into the property list */ + if(H5P_add_prop(plist->props,pcopy)<0) + HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, FAIL,"Can't insert changed property into TBBT"); + } /* end if */ + + /* Copy new [possibly unchanged] value into return value */ + HDmemcpy(value,tmp_value,prop->size); + + /* Free the temporary value buffer */ + H5MM_xfree(tmp_value); + } /* end if */ + /* No 'get' callback, just copy value */ + else + HDmemcpy(value,prop->value,prop->size); + + /* Leave */ + HGOTO_DONE(SUCCEED); + } /* end while */ + } /* end if */ + + /* Go up to parent class */ + tclass=tclass->parent; + } /* end while */ + + /* If we get this far, then it wasn't in the list of changed properties, + * nor in the properties in the class hierarchy, indicate an error + */ + HGOTO_ERROR(H5E_PLIST,H5E_NOTFOUND,FAIL,"can't find property in TBBT"); + } /* end else */ done: FUNC_LEAVE (ret_value); @@ -3968,7 +4430,8 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -herr_t H5Pget(hid_t plist_id, const char *name, void * value) +herr_t +H5Pget(hid_t plist_id, const char *name, void * value) { H5P_genplist_t *plist; /* Property list pointer */ herr_t ret_value=SUCCEED; /* return value */ @@ -4021,63 +4484,106 @@ done: herr_t H5P_remove(hid_t plist_id, H5P_genplist_t *plist, const char *name) { + H5P_genclass_t *tclass; /* Temporary class pointer */ + H5TB_NODE *curr_node; /* TBBT node holding property */ H5P_genprop_t *prop; /* Temporary property pointer */ - H5P_genprop_t *tprop, *prev;/* Temporary pointer to properties */ - unsigned loc; /* Hash table location */ - herr_t ret_value=SUCCEED; /* Return value */ + char *del_name; /* Pointer to deleted name */ + herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_NOINIT(H5P_remove); + FUNC_ENTER_NOAPI(H5P_remove,FAIL); assert(plist); assert(name); - /* Find the property in the property list */ - if((prop=H5P_find_prop(plist->props,plist->pclass->hashsize,name))==NULL) - HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property doesn't exist"); + /* Indicate that the property isn't in the list if it has been deleted already */ + if(H5TB_dfind(plist->del,name,NULL)!=NULL) + HGOTO_ERROR(H5E_PLIST,H5E_NOTFOUND,FAIL,"can't find property in TBBT"); - /* Pass value to 'close' callback, if it exists */ - if(prop->del!=NULL) { - /* Call user's callback */ - if((*(prop->del))(plist_id,name,prop->size,prop->value)<0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't close property value"); - } /* end if */ + /* Get the property node from the changed property TBBT */ + if((curr_node=H5TB_dfind(plist->props,name,NULL))!=NULL) { + /* Get pointer to property for node */ + prop=curr_node->data; - /* Get correct hash table location */ - loc=H5P_hash_name(name,plist->pclass->hashsize); - - /* Remove property from property list */ - /* Check if the property being removed is at the head of the list for a hash location */ - if(prop==plist->props[loc]) { - /* Jump over the property we are deleting */ - plist->props[loc]=prop->next; + /* Pass value to 'close' callback, if it exists */ + if(prop->del!=NULL) { + /* Call user's callback */ + if((*(prop->del))(plist_id,name,prop->size,prop->value)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't close property value"); + } /* end if */ + + /* Duplicate string for insertion into new deleted property TBBT */ + if((del_name=H5MM_xstrdup(name))==NULL) + HGOTO_ERROR(H5E_RESOURCE,H5E_NOSPACE,FAIL,"memory allocation failed"); + + /* Insert property name into deleted list */ + if(H5TB_dins(plist->del,del_name,del_name)==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTINSERT,FAIL,"can't insert property into deleted TBBT"); + + /* Remove the property from the TBBT */ + if(H5TB_rem(&plist->props->root,curr_node,NULL)==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTDELETE,FAIL,"can't remove property from TBBT"); /* Free the property, ignoring return value, nothing we can do */ H5P_free_prop(prop); + + /* Decrement the number of properties in list */ + plist->nprops--; } /* end if */ + /* Walk through all the properties in the class hierarchy, looking for the property */ else { - /* Set up initial pointers */ - prev=tprop=plist->props[loc]; - tprop=tprop->next; - while(tprop!=NULL) { - if(tprop==prop) { - /* Jump over the property we are deleting */ - prev->next=prop->next; - - /* Free the property, ignoring return value, nothing we can do */ - H5P_free_prop(prop); - - /* Break out of while loop */ - break; + /* + * Check if we should delete class properties (up through list of parent classes also), + * & make property 'delete' callback. + */ + tclass=plist->pclass; + while(tclass!=NULL) { + if(tclass->nprops>0) { + /* Find the property in the class */ + if((prop=H5P_find_prop_pclass(tclass,name))!=NULL) { + /* Pass value to 'del' callback, if it exists */ + if(prop->del!=NULL) { + void *tmp_value; /* Temporary value buffer */ + + /* Allocate space for a temporary copy of the property value */ + if (NULL==(tmp_value=H5MM_malloc(prop->size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for temporary property value"); + HDmemcpy(tmp_value,prop->value,prop->size); + + /* Call user's callback */ + if((*(prop->del))(plist_id,name,prop->size,tmp_value)<0) { + H5MM_xfree(tmp_value); + HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't close property value"); + } /* end if */ + + /* Release the temporary value buffer */ + H5MM_xfree(tmp_value); + } /* end if */ + + /* Duplicate string for insertion into new deleted property TBBT */ + if((del_name=H5MM_xstrdup(name))==NULL) + HGOTO_ERROR(H5E_RESOURCE,H5E_NOSPACE,FAIL,"memory allocation failed"); + + /* Insert property name into deleted list */ + if(H5TB_dins(plist->del,del_name,del_name)==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTINSERT,FAIL,"can't insert property into deleted TBBT"); + + /* Decrement the number of properties in list */ + plist->nprops--; + + /* Leave */ + HGOTO_DONE(SUCCEED); + } /* end while */ } /* end if */ - /* Move to the next nodes */ - prev=tprop; - tprop=tprop->next; + /* Go up to parent class */ + tclass=tclass->parent; } /* end while */ - } /* end else */ - /* Decrement the number of properties in list */ - plist->nprops--; + /* If we get this far, then it wasn't in the list of changed properties, + * nor in the properties in the class hierarchy, indicate an error + */ + HGOTO_ERROR(H5E_PLIST,H5E_NOTFOUND,FAIL,"can't find property in TBBT"); + } /* end else */ done: FUNC_LEAVE (ret_value); @@ -4110,7 +4616,8 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -herr_t H5Premove(hid_t plist_id, const char *name) +herr_t +H5Premove(hid_t plist_id, const char *name) { H5P_genplist_t *plist; /* Property list to modify */ herr_t ret_value; /* return value */ @@ -4180,20 +4687,17 @@ H5P_copy_prop_plist(hid_t dst_id, hid_t src_id, const char *name) if(NULL == (src_plist = H5I_object(src_id)) || NULL == (dst_plist = H5I_object(dst_id))) HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property object doesn't exist"); - /* Check if the property exists in the destination */ - prop=H5P_find_prop(dst_plist->props,dst_plist->pclass->hashsize,name); - /* If the property exists in the destination alread */ - if(prop!=NULL) { + if(H5P_find_prop_plist(dst_plist,name)!=NULL) { /* Delete the property from the destination list, calling the 'close' callback if necessary */ if(H5P_remove(dst_id,dst_plist,name)<0) HGOTO_ERROR(H5E_PLIST, H5E_CANTDELETE, FAIL, "unable to remove property"); /* Get the pointer to the source property */ - prop=H5P_find_prop(src_plist->props,src_plist->pclass->hashsize,name); + prop=H5P_find_prop_plist(src_plist,name); /* Make a copy of the source property */ - if((new_prop=H5P_dup_prop(prop))==NULL) + if((new_prop=H5P_dup_prop(prop,H5P_PROP_WITHIN_LIST))==NULL) HGOTO_ERROR (H5E_PLIST, H5E_CANTCOPY, FAIL,"Can't copy property"); /* Call property copy callback, if it exists */ @@ -4203,7 +4707,7 @@ H5P_copy_prop_plist(hid_t dst_id, hid_t src_id, const char *name) } /* end if */ /* Insert the initialized property into the property list */ - if(H5P_add_prop(dst_plist->props,dst_plist->pclass->hashsize,new_prop)<0) + if(H5P_add_prop(dst_plist->props,new_prop)<0) HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, FAIL,"Can't insert property into list"); /* Increment the number of properties in list */ @@ -4212,10 +4716,10 @@ H5P_copy_prop_plist(hid_t dst_id, hid_t src_id, const char *name) /* If not, get the information required to do an H5Pinsert with the property into the destination list */ else { /* Get the pointer to the source property */ - prop=H5P_find_prop(src_plist->props,src_plist->pclass->hashsize,name); + prop=H5P_find_prop_plist(src_plist,name); /* Create property object from parameters */ - if((new_prop=H5P_create_prop(prop->name,prop->size,prop->def_value,prop->value,prop->create,prop->set,prop->get,prop->del,prop->copy,prop->copy))==NULL) + if((new_prop=H5P_create_prop(prop->name,prop->size,H5P_PROP_WITHIN_LIST,prop->value,prop->create,prop->set,prop->get,prop->del,prop->copy,prop->copy))==NULL) HGOTO_ERROR (H5E_PLIST, H5E_CANTCREATE, FAIL,"Can't create property"); /* Call property creation callback, if it exists */ @@ -4225,7 +4729,7 @@ H5P_copy_prop_plist(hid_t dst_id, hid_t src_id, const char *name) } /* end if */ /* Insert property into property list class */ - if(H5P_add_prop(dst_plist->props,dst_plist->pclass->hashsize,new_prop)<0) + if(H5P_add_prop(dst_plist->props,new_prop)<0) HGOTO_ERROR (H5E_PLIST, H5E_CANTINSERT, FAIL,"Can't insert property into class"); /* Increment property count for class */ @@ -4274,7 +4778,7 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5P_copy_prop_pclass(H5P_genclass_t *dst_pclass, H5P_genclass_t UNUSED *src_pclass, const char *name) +H5P_copy_prop_pclass(H5P_genclass_t *dst_pclass, H5P_genclass_t *src_pclass, const char *name) { H5P_genprop_t *prop; /* Temporary property pointer */ herr_t ret_value=SUCCEED; /* return value */ @@ -4285,18 +4789,19 @@ H5P_copy_prop_pclass(H5P_genclass_t *dst_pclass, H5P_genclass_t UNUSED *src_pcla assert(src_pclass); assert(name); - /* Check if the property exists in the destination */ - prop=H5P_find_prop(dst_pclass->props,dst_pclass->hashsize,name); - /* If the property exists in the destination already */ - if(prop!=NULL) { + if(H5P_exist_pclass(dst_pclass,name)) { /* Delete the old property from the destination class */ if(H5P_unregister(dst_pclass,name)<0) HGOTO_ERROR(H5E_PLIST, H5E_CANTDELETE, FAIL, "unable to remove property"); } /* end if */ + /* Get the property from the source */ + if((prop=H5P_find_prop_pclass(src_pclass,name))==NULL) + HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "unable to locate property"); + /* Register the property into the destination */ - if(H5P_register(dst_pclass,name,prop->size,prop->def_value,prop->create,prop->set,prop->get,prop->del,prop->copy,prop->close)<0) + if(H5P_register(dst_pclass,name,prop->size,prop->value,prop->create,prop->set,prop->get,prop->del,prop->copy,prop->close)<0) HGOTO_ERROR(H5E_PLIST, H5E_CANTDELETE, FAIL, "unable to remove property"); done: @@ -4404,9 +4909,8 @@ done: static herr_t H5P_unregister(H5P_genclass_t *pclass, const char *name) { + H5TB_NODE *prop_node; /* TBBT node holding property */ H5P_genprop_t *prop; /* Temporary property pointer */ - H5P_genprop_t *tprop, *prev;/* Temporary pointer to properties */ - unsigned loc; /* Hash table location */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOINIT(H5P_unregister); @@ -4414,46 +4918,26 @@ H5P_unregister(H5P_genclass_t *pclass, const char *name) assert(pclass); assert(name); - /* Find the property in the property list */ - if((prop=H5P_find_prop(pclass->props,pclass->hashsize,name))==NULL) - HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property doesn't exist"); + /* Get the property node from the TBBT */ + if((prop_node=H5TB_dfind(pclass->props,name,NULL))==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_NOTFOUND,NULL,"can't find property in TBBT"); - /* Get correct hash table location */ - loc=H5P_hash_name(name,pclass->hashsize); - - /* Remove property from property list */ - /* Check if the property being removed is at the head of the list for a hash location */ - if(prop==pclass->props[loc]) { - pclass->props[loc]=prop->next; + /* Get the pointer to the property */ + prop=prop_node->data; - /* Free the property, ignoring return value, nothing we can do */ - H5P_free_prop(prop); - } /* end if */ - else { - /* Set up initial pointers */ - prev=tprop=pclass->props[loc]; - tprop=tprop->next; - while(tprop!=NULL) { - if(tprop==prop) { - /* Jump over the property we are deleting */ - prev->next=prop->next; - - /* Free the property, ignoring return value, nothing we can do */ - H5P_free_prop(prop); - - /* Break out of while loop */ - break; - } /* end if */ + /* Remove the property from the TBBT */ + if(H5TB_rem(&pclass->props->root,prop_node,NULL)==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTDELETE,FAIL,"can't remove property from TBBT"); - /* Move to the next nodes */ - prev=tprop; - tprop=tprop->next; - } /* end while */ - } /* end else */ + /* Free the property, ignoring return value, nothing we can do */ + H5P_free_prop(prop); /* Decrement the number of registered properties in class */ pclass->nprops--; + /* Update the revision for the class */ + pclass->revision = H5P_GET_NEXT_REV; + done: FUNC_LEAVE (ret_value); } /* H5P_unregister() */ @@ -4480,7 +4964,8 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -herr_t H5Punregister(hid_t pclass_id, const char *name) +herr_t +H5Punregister(hid_t pclass_id, const char *name) { H5P_genclass_t *pclass; /* Property list class to modify */ herr_t ret_value; /* return value */ @@ -4529,8 +5014,12 @@ done: herr_t H5P_close(void *_plist) { + H5P_genclass_t *tclass; /* Temporary class pointer */ H5P_genplist_t *plist=(H5P_genplist_t *)_plist; - herr_t ret_value=SUCCEED; /* return value */ + H5TB_TREE *seen=NULL; /* TBBT to hold names of properties already seen */ + H5TB_NODE *curr_node; /* Current node in TBBT */ + H5P_genprop_t *tmp; /* Temporary pointer to properties */ + herr_t ret_value=SUCCEED; /* return value */ FUNC_ENTER_NOINIT(H5P_close); @@ -4542,17 +5031,106 @@ H5P_close(void *_plist) (plist->pclass->close_func)(plist->plist_id,plist->pclass->close_data); } /* end if */ - /* Make calls to any property close callbacks which exist */ - H5P_free_all_prop(plist->props,plist->pclass->hashsize,1); + /* Create the TBBT to hold names of properties already seen + * (This prevents a property in the class hierarchy from having it's + * 'close' callback called, if a property in the class hierarchy has + * already been seen) + */ + if((seen=H5TB_fast_dmake(H5TB_FAST_STR_COMPARE))==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTMAKETREE,NULL,"can't create TBBT for seen properties"); + + /* Walk through the changed properties in the list */ + if(plist->props->root) { + curr_node=H5TB_first(plist->props->root); + while(curr_node!=NULL) { + /* Get pointer to property from node */ + tmp=curr_node->data; + + /* Call property close callback, if it exists */ + if(tmp->close) { + /* Call the 'close' callback */ + (tmp->close)(tmp->name,tmp->size,tmp->value); + } /* end if */ + + /* Add property name to "seen" list */ + if(H5TB_dins(seen,tmp->name,tmp->name)==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTINSERT,NULL,"can't insert property into seen TBBT"); + + /* Get the next property node in the TBBT */ + curr_node=H5TB_next(curr_node); + } /* end while */ + } /* end if */ + + /* + * Check if we should remove class properties (up through list of parent classes also), + * initialize each with default value & make property 'remove' callback. + */ + tclass=plist->pclass; + while(tclass!=NULL) { + if(tclass->nprops>0) { + /* Walk through the properties in the class */ + curr_node=H5TB_first(tclass->props->root); + while(curr_node!=NULL) { + /* Get pointer to property from node */ + tmp=curr_node->data; + + /* Only "delete" properties we haven't seen before + * and that haven't already been deleted + */ + if(H5TB_dfind(seen,tmp->name,NULL)==NULL && + H5TB_dfind(plist->del,tmp->name,NULL)==NULL) { + + /* Call property close callback, if it exists */ + if(tmp->close) { + void *tmp_value; /* Temporary value buffer */ + + /* Allocate space for a temporary copy of the property value */ + if (NULL==(tmp_value=H5MM_malloc(tmp->size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for temporary property value"); + HDmemcpy(tmp_value,tmp->value,tmp->size); + + /* Call the 'close' callback */ + (tmp->close)(tmp->name,tmp->size,tmp_value); + + /* Release the temporary value buffer */ + H5MM_xfree(tmp_value); + } /* end if */ + + /* Add property name to "seen" list */ + if(H5TB_dins(seen,tmp->name,tmp->name)==NULL) + HGOTO_ERROR(H5E_PLIST,H5E_CANTINSERT,NULL,"can't insert property into seen TBBT"); + } /* end if */ + + /* Get the next property node in the TBBT */ + curr_node=H5TB_next(curr_node); + } /* end while */ + } /* end if */ + + /* Go up to parent class */ + tclass=tclass->parent; + } /* end while */ /* Decrement class's dependant property list value! */ if(H5P_access_class(plist->pclass,H5P_MOD_DEC_LST)<0) HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, FAIL, "Can't decrement class ref count"); + /* Free the list of 'seen' properties */ + seen=H5TB_dfree(seen,NULL,NULL); + + /* Free the list of deleted property names */ + H5TB_dfree(plist->del,free,NULL); + + /* Free the property tree itself */ + H5TB_dfree(plist->props,H5P_free_prop,NULL); + /* Destroy property list object */ - H5MM_xfree(plist); + H5FL_FREE(H5P_genplist_t,plist); done: + /* Release the tree of 'seen' properties */ + if(seen!=NULL) + H5TB_dfree(seen,NULL,NULL); + FUNC_LEAVE (ret_value); } /* H5P_close() */ @@ -4578,7 +5156,8 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -herr_t H5Pclose(hid_t plist_id) +herr_t +H5Pclose(hid_t plist_id) { H5P_genplist_t *plist; /* Property list created */ herr_t ret_value=SUCCEED; /* return value */ @@ -4625,7 +5204,8 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -char *H5P_get_class_name(H5P_genclass_t *pclass) +char * +H5P_get_class_name(H5P_genclass_t *pclass) { char *ret_value; /* return value */ @@ -4661,7 +5241,8 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -char *H5Pget_class_name(hid_t pclass_id) +char * +H5Pget_class_name(hid_t pclass_id) { H5P_genclass_t *pclass; /* Property class to query */ char *ret_value; /* return value */ @@ -4889,7 +5470,8 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -hid_t H5P_open_class_path_test(const char *path) +hid_t +H5P_open_class_path_test(const char *path) { H5P_genclass_t *pclass=NULL;/* Property class to query */ hid_t ret_value; /* Return value */ @@ -4970,7 +5552,8 @@ H5P_get_class_parent(H5P_genclass_t *pclass) EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -hid_t H5Pget_class_parent(hid_t pclass_id) +hid_t +H5Pget_class_parent(hid_t pclass_id) { H5P_genclass_t *pclass; /* Property class to query */ H5P_genclass_t *parent=NULL; /* Parent's property class */ diff --git a/src/H5Pdcpl.c b/src/H5Pdcpl.c index c034156..92ebfc2 100644 --- a/src/H5Pdcpl.c +++ b/src/H5Pdcpl.c @@ -963,7 +963,7 @@ H5Pget_fill_value(hid_t plist_id, hid_t type_id, void *value/*out*/) HDmemcpy(buf, fill.buf, H5T_get_size(fill.type)); /* Do the conversion */ - if (H5T_convert(tpath, src_id, type_id, (hsize_t)1, 0, 0, buf, bkg, H5P_DEFAULT)<0) + if (H5T_convert(tpath, src_id, type_id, (hsize_t)1, 0, 0, buf, bkg, H5P_DATASET_XFER_DEFAULT)<0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "data type conversion failed"); if (buf!=value) HDmemcpy(value, buf, H5T_get_size(type)); @@ -980,7 +980,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5P_fill_value_defined + * Function: H5P_is_fill_value_defined * * Purpose: Check if fill value is defined. Internal version of function * @@ -990,35 +990,30 @@ done: * Wednesday, January 16, 2002 * * Modifications: - * + * Extracted from H5P_fill_value_defined, QAK, Dec. 13, 2002 * *------------------------------------------------------------------------- */ herr_t -H5P_fill_value_defined(H5P_genplist_t *plist, H5D_fill_value_t *status) +H5P_is_fill_value_defined(const struct H5O_fill_t *fill, H5D_fill_value_t *status) { herr_t ret_value = SUCCEED; - H5O_fill_t fill; - FUNC_ENTER_NOAPI(H5P_fill_value_defined, FAIL); + FUNC_ENTER_NOAPI(H5P_is_fill_value_defined, FAIL); - assert(plist); + assert(fill); assert(status); - /* Get the fill value struct */ - if(H5P_get(plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get fill value"); - /* Check if the fill value was never set */ - if(fill.size == (size_t)-1 && !fill.buf) { + if(fill->size == (size_t)-1 && !fill->buf) { *status = H5D_FILL_VALUE_UNDEFINED; } /* Check if the fill value was set to the default fill value by the library */ - else if(fill.size == 0 && !fill.buf) { + else if(fill->size == 0 && !fill->buf) { *status = H5D_FILL_VALUE_DEFAULT; } /* Check if the fill value was set by the application */ - else if(fill.size > 0 && fill.buf) { + else if(fill->size > 0 && fill->buf) { *status = H5D_FILL_VALUE_USER_DEFINED; } else { @@ -1028,6 +1023,45 @@ H5P_fill_value_defined(H5P_genplist_t *plist, H5D_fill_value_t *status) done: FUNC_LEAVE(ret_value); +} /* end H5P_is_fill_value_defined() */ + + +/*------------------------------------------------------------------------- + * Function: H5P_fill_value_defined + * + * Purpose: Check if fill value is defined. Internal version of function + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Raymond Lu + * Wednesday, January 16, 2002 + * + * Modifications: + * + * + *------------------------------------------------------------------------- + */ +herr_t +H5P_fill_value_defined(H5P_genplist_t *plist, H5D_fill_value_t *status) +{ + herr_t ret_value = SUCCEED; + H5O_fill_t fill; + + FUNC_ENTER_NOAPI(H5P_fill_value_defined, FAIL); + + assert(plist); + assert(status); + + /* Get the fill value struct */ + if(H5P_get(plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get fill value"); + + /* Get the fill-value status */ + if(H5P_is_fill_value_defined(&fill, status) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't check fill value status"); + +done: + FUNC_LEAVE(ret_value); } /* end H5P_fill_value_defined() */ diff --git a/src/H5Pfapl.c b/src/H5Pfapl.c index 2e32e0a..ba4be48 100644 --- a/src/H5Pfapl.c +++ b/src/H5Pfapl.c @@ -526,7 +526,7 @@ herr_t H5Pset_family_offset(hid_t fapl_id, hsize_t offset) /* Get the plist structure */ if(H5P_DEFAULT == fapl_id) - fapl_id = H5Pcreate(H5P_FILE_ACCESS); + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "can't modify default property list"); if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); /* Set values */ @@ -600,7 +600,7 @@ herr_t H5Pget_family_offset(hid_t fapl_id, hsize_t *offset) /* Get the plist structure */ if(H5P_DEFAULT == fapl_id) - fapl_id = H5Pcreate(H5P_FILE_ACCESS); + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "can't modify default property list"); if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); /* Set values */ @@ -674,7 +674,7 @@ herr_t H5Pset_multi_type(hid_t fapl_id, H5FD_mem_t type) /* Get the plist structure */ if(H5P_DEFAULT == fapl_id) - fapl_id = H5Pcreate(H5P_FILE_ACCESS); + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "can't modify default property list"); if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); /* Set values */ @@ -748,7 +748,7 @@ herr_t H5Pget_multi_type(hid_t fapl_id, H5FD_mem_t *type) /* Get the plist structure */ if(H5P_DEFAULT == fapl_id) - fapl_id = H5Pcreate(H5P_FILE_ACCESS); + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "can't modify default property list"); if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); /* Set values */ diff --git a/src/H5Ppkg.h b/src/H5Ppkg.h index b600769..65b76a0 100644 --- a/src/H5Ppkg.h +++ b/src/H5Ppkg.h @@ -24,6 +24,14 @@ #endif #include "H5Pprivate.h" +#include "H5TBprivate.h" /* TBBTs */ + +/* Define enum for type of object that property is within */ +typedef enum { + H5P_PROP_WITHIN_UNKNOWN=0, /* Property container is unknown */ + H5P_PROP_WITHIN_LIST, /* Property is within a list */ + H5P_PROP_WITHIN_CLASS /* Property is within a class */ +} H5P_prop_within_t; /* Define enum for modifications to class */ typedef enum { @@ -40,21 +48,19 @@ typedef enum { /* Define structure to hold property information */ typedef struct H5P_genprop_t { /* Values for this property */ - unsigned xor_val; /* XOR'ed version of the name, for faster comparisons */ char *name; /* Name of property */ size_t size; /* Size of property value */ void *value; /* Pointer to property value */ + H5P_prop_within_t type; /* Type of object the property is within */ + unsigned shared_name; /* Boolean: whether the name is shared or not */ /* Callback function pointers & info */ H5P_prp_create_func_t create; /* Function to call when a property is created */ - void *def_value; /* Pointer to default value to pass along to create callback */ H5P_prp_set_func_t set; /* Function to call when a property value is set */ H5P_prp_get_func_t get; /* Function to call when a property value is retrieved */ H5P_prp_delete_func_t del; /* Function to call when a property is deleted */ H5P_prp_copy_func_t copy; /* Function to call when a property is copied */ H5P_prp_close_func_t close; /* Function to call when a property is closed */ - - struct H5P_genprop_t *next; /* Pointer to the next property in this list */ } H5P_genprop_t; /* Define structure to hold class information */ @@ -62,12 +68,13 @@ struct H5P_genclass_t { struct H5P_genclass_t *parent; /* Pointer to parent class */ char *name; /* Name of property list class */ size_t nprops; /* Number of properties in class */ - unsigned hashsize; /* Hash table size */ unsigned plists; /* Number of property lists that have been created since the last modification to the class */ unsigned classes; /* Number of classes that have been derived since the last modification to the class */ unsigned ref_count; /* Number of oustanding ID's open on this class object */ unsigned internal; /* Whether this class is internal to the library or not */ unsigned deleted; /* Whether this class has been deleted and is waiting for dependent classes & proplists to close */ + unsigned revision; /* Revision number of a particular class (global) */ + H5TB_TREE *props; /* TBBT containing properties */ /* Callback function pointers & info */ H5P_cls_create_func_t create_func; /* Function to call when a property list is created */ @@ -76,8 +83,6 @@ struct H5P_genclass_t { void *copy_data; /* Pointer to user data to pass along to copy callback */ H5P_cls_close_func_t close_func; /* Function to call when a property list is closed */ void *close_data; /* Pointer to user data to pass along to close callback */ - - H5P_genprop_t *props[1]; /* Hash table of pointers to properties in the class */ }; /* Define structure to hold property list information */ @@ -86,14 +91,14 @@ struct H5P_genplist_t { hid_t plist_id; /* Copy of the property list ID (for use in close callback) */ size_t nprops; /* Number of properties in class */ unsigned class_init:1; /* Whether the class initialization callback finished successfully */ - - /* Hash size for a property list is same as class */ - H5P_genprop_t *props[1]; /* Hash table of pointers to properties in the list */ + H5TB_TREE *del; /* TBBT containing names of deleted properties */ + H5TB_TREE *props; /* TBBT containing properties */ }; /* Private functions, not part of the publicly documented API */ -H5_DLL herr_t H5P_add_prop(H5P_genprop_t *hash[], unsigned hashsize, H5P_genprop_t *prop); +H5_DLL herr_t H5P_add_prop(H5TB_TREE *props, H5P_genprop_t *prop); H5_DLL herr_t H5P_access_class(H5P_genclass_t *pclass, H5P_class_mod_t mod); +H5_DLL int H5P_tbbt_strcmp(const void *k1, const void *k2, int UNUSED cmparg); #endif /* _H5Ppkg_H */ diff --git a/src/H5Pprivate.h b/src/H5Pprivate.h index dca48be..d854936 100644 --- a/src/H5Pprivate.h +++ b/src/H5Pprivate.h @@ -25,6 +25,9 @@ typedef struct H5P_genplist_t H5P_genplist_t; typedef struct H5P_genclass_t H5P_genclass_t; +/* Forward declarations for prototypes arguments */ +struct H5O_fill_t; + /* Private functions, not part of the publicly documented API */ H5_DLL herr_t H5P_init(void); @@ -60,6 +63,8 @@ H5_DLL herr_t H5P_get_multi_type(H5P_genplist_t *plist, H5FD_mem_t *type); H5_DLL herr_t H5P_set_vlen_mem_manager(H5P_genplist_t *plist, H5MM_allocate_t alloc_func, void *alloc_info, H5MM_free_t free_func, void *free_info); +H5_DLL herr_t H5P_is_fill_value_defined(const struct H5O_fill_t *fill, + H5D_fill_value_t *status); H5_DLL herr_t H5P_fill_value_defined(H5P_genplist_t *plist, H5D_fill_value_t *status); diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h index 615967c..3ac1029 100644 --- a/src/H5Ppublic.h +++ b/src/H5Ppublic.h @@ -57,12 +57,14 @@ typedef herr_t (*H5P_cls_copy_func_t)(hid_t new_prop_id, hid_t old_prop_id, typedef herr_t (*H5P_cls_close_func_t)(hid_t prop_id, void *close_data); /* Define property list callback function pointer types */ -typedef herr_t (*H5P_prp_create_func_t)(const char *name, size_t size, void *def_value); -typedef herr_t (*H5P_prp_set_func_t)(hid_t prop_id, const char *name, size_t size, void *value); -typedef herr_t (*H5P_prp_get_func_t)(hid_t prop_id, const char *name, size_t size, void *value); -typedef herr_t (*H5P_prp_delete_func_t)(hid_t prop_id, const char *name, size_t size, void *value); -typedef herr_t (*H5P_prp_copy_func_t)(const char *name, size_t size, void *value); -typedef herr_t (*H5P_prp_close_func_t)(const char *name, size_t size, void *value); +typedef herr_t (*H5P_prp_cb1_t)(const char *name, size_t size, void *value); +typedef herr_t (*H5P_prp_cb2_t)(hid_t prop_id, const char *name, size_t size, void *value); +typedef H5P_prp_cb1_t H5P_prp_create_func_t; +typedef H5P_prp_cb2_t H5P_prp_set_func_t; +typedef H5P_prp_cb2_t H5P_prp_get_func_t; +typedef H5P_prp_cb2_t H5P_prp_delete_func_t; +typedef H5P_prp_cb1_t H5P_prp_copy_func_t; +typedef H5P_prp_cb1_t H5P_prp_close_func_t; /* Define property list iteration function type */ typedef herr_t (*H5P_iterate_t)(hid_t id, const char *name, void *iter_data); @@ -73,19 +75,25 @@ extern "C" { /* * The library created property list classes + * + * NOTE: When adding H5P_* macros, remember to redefine them in H5Pprivate.h + * */ -#define H5P_NO_CLASS (H5open(), H5P_CLS_NO_CLASS_g) -#define H5P_NO_CLASS_HASH_SIZE 1 /* 1, not 0, otherwise allocations get weird */ -#define H5P_FILE_CREATE (H5open(), H5P_CLS_FILE_CREATE_g) -#define H5P_FILE_CREATE_HASH_SIZE 17 -#define H5P_FILE_ACCESS (H5open(), H5P_CLS_FILE_ACCESS_g) -#define H5P_FILE_ACCESS_HASH_SIZE 17 -#define H5P_DATASET_CREATE (H5open(), H5P_CLS_DATASET_CREATE_g) -#define H5P_DATASET_CREATE_HASH_SIZE 17 -#define H5P_DATASET_XFER (H5open(), H5P_CLS_DATASET_XFER_g) -#define H5P_DATASET_XFER_HASH_SIZE 17 -#define H5P_MOUNT (H5open(), H5P_CLS_MOUNT_g) -#define H5P_MOUNT_HASH_SIZE 17 + +/* When this header is included from H5Pprivate.h, don't make calls to H5open() */ +#undef H5OPEN +#ifndef _H5Pprivate_H +#define H5OPEN H5open(), +#else /* _H5Pprivate_H */ +#define H5OPEN +#endif /* _H5Pprivate_H */ + +#define H5P_NO_CLASS (H5OPEN H5P_CLS_NO_CLASS_g) +#define H5P_FILE_CREATE (H5OPEN H5P_CLS_FILE_CREATE_g) +#define H5P_FILE_ACCESS (H5OPEN H5P_CLS_FILE_ACCESS_g) +#define H5P_DATASET_CREATE (H5OPEN H5P_CLS_DATASET_CREATE_g) +#define H5P_DATASET_XFER (H5OPEN H5P_CLS_DATASET_XFER_g) +#define H5P_MOUNT (H5OPEN H5P_CLS_MOUNT_g) H5_DLLVAR hid_t H5P_CLS_NO_CLASS_g; H5_DLLVAR hid_t H5P_CLS_FILE_CREATE_g; H5_DLLVAR hid_t H5P_CLS_FILE_ACCESS_g; @@ -95,13 +103,16 @@ H5_DLLVAR hid_t H5P_CLS_MOUNT_g; /* * The library created default property lists + * + * NOTE: When adding H5P_* macros, remember to redefine them in H5Pprivate.h + * */ -#define H5P_NO_CLASS_DEFAULT (H5open(), H5P_LST_NO_CLASS_g) -#define H5P_FILE_CREATE_DEFAULT (H5open(), H5P_LST_FILE_CREATE_g) -#define H5P_FILE_ACCESS_DEFAULT (H5open(), H5P_LST_FILE_ACCESS_g) -#define H5P_DATASET_CREATE_DEFAULT (H5open(), H5P_LST_DATASET_CREATE_g) -#define H5P_DATASET_XFER_DEFAULT (H5open(), H5P_LST_DATASET_XFER_g) -#define H5P_MOUNT_DEFAULT (H5open(), H5P_LST_MOUNT_g) +#define H5P_NO_CLASS_DEFAULT (H5OPEN H5P_LST_NO_CLASS_g) +#define H5P_FILE_CREATE_DEFAULT (H5OPEN H5P_LST_FILE_CREATE_g) +#define H5P_FILE_ACCESS_DEFAULT (H5OPEN H5P_LST_FILE_ACCESS_g) +#define H5P_DATASET_CREATE_DEFAULT (H5OPEN H5P_LST_DATASET_CREATE_g) +#define H5P_DATASET_XFER_DEFAULT (H5OPEN H5P_LST_DATASET_XFER_g) +#define H5P_MOUNT_DEFAULT (H5OPEN H5P_LST_MOUNT_g) H5_DLLVAR hid_t H5P_LST_NO_CLASS_g; H5_DLLVAR hid_t H5P_LST_FILE_CREATE_g; H5_DLLVAR hid_t H5P_LST_FILE_ACCESS_g; @@ -109,11 +120,8 @@ H5_DLLVAR hid_t H5P_LST_DATASET_CREATE_g; H5_DLLVAR hid_t H5P_LST_DATASET_XFER_g; H5_DLLVAR hid_t H5P_LST_MOUNT_g; -/* Default hash table size */ -#define H5P_DEFAULT_HASH_SIZE 17 - /* Public functions */ -H5_DLL hid_t H5Pcreate_class(hid_t parent, const char *name, unsigned hashsize, +H5_DLL hid_t H5Pcreate_class(hid_t parent, const char *name, H5P_cls_create_func_t cls_create, void *create_data, H5P_cls_copy_func_t cls_copy, void *copy_data, H5P_cls_close_func_t cls_close, void *close_data); diff --git a/src/H5R.c b/src/H5R.c index 795bc56..1ffa827 100644 --- a/src/H5R.c +++ b/src/H5R.c @@ -331,7 +331,6 @@ done: static hid_t H5R_dereference(H5F_t *file, H5R_type_t ref_type, void *_ref) { - H5D_t *dataset; /* Pointer to dataset to open */ H5G_t *group; /* Pointer to group to open */ H5T_t *datatype; /* Pointer to datatype to open */ H5G_entry_t ent; /* Symbol table entry */ @@ -428,14 +427,9 @@ H5R_dereference(H5F_t *file, H5R_type_t ref_type, void *_ref) break; case H5G_DATASET: - if ((dataset=H5D_open_oid(&ent)) == NULL) + /* Open the dataset */ + if ((ret_value=H5D_open(&ent)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_NOTFOUND, FAIL, "not found"); - - /* Create an atom for the dataset */ - if ((ret_value = H5I_register(H5I_DATASET, dataset)) < 0) { - H5D_close(dataset); - HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "can't register dataset"); - } break; default: @@ -524,7 +518,6 @@ done: static H5S_t * H5R_get_region(H5F_t *file, H5R_type_t UNUSED ref_type, void *_ref) { - H5D_t *dataset; /* Pointer to dataset to open */ H5G_entry_t ent; /* Symbol table entry */ uint8_t *p; /* Pointer to OID to store */ hdset_reg_ref_t *ref=(hdset_reg_ref_t *)_ref; /* Get pointer to correct type of reference struct */ @@ -556,12 +549,8 @@ H5R_get_region(H5F_t *file, H5R_type_t UNUSED ref_type, void *_ref) p=(uint8_t *)buf; H5F_addr_decode(ent.file,(const uint8_t **)&p,&(ent.header)); - /* Open the dataset object */ - if ((dataset=H5D_open_oid(&ent)) == NULL) - HGOTO_ERROR(H5E_DATASET, H5E_NOTFOUND, NULL, "not found"); - - /* Copy the dataspace object */ - if ((ret_value=H5D_get_space(dataset)) == NULL) + /* Open and copy the dataset's dataspace */ + if ((ret_value=H5S_read(&ent)) == NULL) HGOTO_ERROR(H5E_DATASPACE, H5E_NOTFOUND, NULL, "not found"); /* Unserialize the selection */ @@ -571,10 +560,6 @@ H5R_get_region(H5F_t *file, H5R_type_t UNUSED ref_type, void *_ref) /* Free the buffer allocated in H5HG_read() */ H5MM_xfree(buf); - /* Close the dataset we opened */ - if (H5D_close(dataset) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CLOSEERROR, NULL, "not found"); - done: FUNC_LEAVE(ret_value); } /* end H5R_get_region() */ diff --git a/src/H5RS.c b/src/H5RS.c new file mode 100644 index 0000000..f6f18ac --- /dev/null +++ b/src/H5RS.c @@ -0,0 +1,390 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* + * Reference counted string algorithms. + * + * These are used for various internal strings which get copied multiple times. + * + */ + +#include "H5Eprivate.h" /* Error handling */ +#include "H5FLprivate.h" /* Free lists */ +#include "H5RSprivate.h" /* Reference-counted strings */ + +#define PABLO_MASK H5RS_mask + +/* Interface initialization */ +static int interface_initialize_g = 0; +#define INTERFACE_INIT NULL + +/* Declare a free list to manage the H5RS_str_t struct */ +H5FL_DEFINE_STATIC(H5RS_str_t); + +/* Declare the PQ free list for the wrapped strings */ +H5FL_BLK_DEFINE(str_buf); + + +/*-------------------------------------------------------------------------- + NAME + H5RS_xstrdup + PURPOSE + Duplicate the string being reference counted + USAGE + char *H5RS_xstrdup(s) + const char *s; IN: String to duplicate + + RETURNS + Returns a pointer to a new string on success, NULL on failure. + DESCRIPTION + Duplicate a string buffer being reference counted. Use this instead of + [H5MM_][x]strdup, in order to use the free-list memory routines. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static char * +H5RS_xstrdup(const char *s) +{ + char *ret_value; /* Return value */ + + FUNC_ENTER_NOINIT(H5RS_xstrdup); + + if (s) { + ret_value = H5FL_BLK_MALLOC(str_buf,HDstrlen(s) + 1); + assert (ret_value); + HDstrcpy(ret_value, s); + } /* end if */ + else + ret_value=NULL; + + FUNC_LEAVE(ret_value); +} /* end H5RS_xstrdup() */ + + +/*-------------------------------------------------------------------------- + NAME + H5RS_create + PURPOSE + Create a reference counted string + USAGE + H5RS_str_t *H5RS_create(s) + const char *s; IN: String to initialize ref-counted string with + + RETURNS + Returns a pointer to a new ref-counted string on success, NULL on failure. + DESCRIPTION + Create a reference counted string. The string passed in is copied into an + internal buffer. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +H5RS_str_t * +H5RS_create(const char *s) +{ + H5RS_str_t *ret_value=NULL; /* Return value */ + + FUNC_ENTER_NOAPI(H5RS_create,NULL); + + /* Allocate ref-counted string structure */ + if((ret_value=H5FL_MALLOC(H5RS_str_t))==NULL) + HGOTO_ERROR(H5E_RS,H5E_NOSPACE,NULL,"memory allocation failed"); + + /* Set the internal fields */ + ret_value->s=H5RS_xstrdup(s); + ret_value->wrapped=0; + ret_value->n=1; + +done: + FUNC_LEAVE(ret_value); +} /* end H5RS_create() */ + + +/*-------------------------------------------------------------------------- + NAME + H5RS_wrap + PURPOSE + "Wrap" a reference counted string around an existing string + USAGE + H5RS_str_t *H5RS_wrap(s) + const char *s; IN: String to wrap ref-counted string around + + RETURNS + Returns a pointer to a new ref-counted string on success, NULL on failure. + DESCRIPTION + Wrap a reference counted string around an existing string, which is not + duplicated, unless its reference count gets incremented. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +H5RS_str_t * +H5RS_wrap(char *s) +{ + H5RS_str_t *ret_value=NULL; /* Return value */ + + FUNC_ENTER_NOAPI(H5RS_wrap,NULL); + + /* Allocate ref-counted string structure */ + if((ret_value=H5FL_MALLOC(H5RS_str_t))==NULL) + HGOTO_ERROR(H5E_RS,H5E_NOSPACE,NULL,"memory allocation failed"); + + /* Set the internal fields */ + ret_value->s=s; + ret_value->wrapped=1; + ret_value->n=1; + +done: + FUNC_LEAVE(ret_value); +} /* end H5RS_wrap() */ + + +/*-------------------------------------------------------------------------- + NAME + H5RS_own + PURPOSE + Transfer ownership of a regular string to a reference counted string + USAGE + H5RS_str_t *H5RS_own(s) + const char *s; IN: String to transfer ownership of + + RETURNS + Returns a pointer to a new ref-counted string on success, NULL on failure. + DESCRIPTION + Transfer ownership of a dynamically allocated string to a reference counted + string. The routine which passed in the string should not attempt to free + it, the reference counting string routines will do that when the reference + count drops to zero. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +H5RS_str_t * +H5RS_own(char *s) +{ + H5RS_str_t *ret_value=NULL; /* Return value */ + + FUNC_ENTER_NOAPI(H5RS_own,NULL); + + /* Allocate ref-counted string structure */ + if((ret_value=H5FL_MALLOC(H5RS_str_t))==NULL) + HGOTO_ERROR(H5E_RS,H5E_NOSPACE,NULL,"memory allocation failed"); + + /* Set the internal fields */ + ret_value->s=s; + ret_value->wrapped=0; + ret_value->n=1; + +done: + FUNC_LEAVE(ret_value); +} /* end H5RS_own() */ + + +/*-------------------------------------------------------------------------- + NAME + H5RS_decr + PURPOSE + Decrement the reference count for a ref-counted string + USAGE + herr_t H5RS_decr(rs) + H5RS_str_t *rs; IN/OUT: Ref-counted string to decrement count of + + RETURNS + Non-negative on success/Negative on failure + DESCRIPTION + Decrement the reference count for a reference counted string. If the + reference count drops to zero, the reference counted string is deleted. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5RS_decr(H5RS_str_t *rs) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5RS_decr,FAIL); + + /* Sanity check */ + assert(rs); + assert(rs->n > 0); + + /* Decrement reference count for string */ + if((--rs->n)==0) { + if(!rs->wrapped) + H5FL_BLK_FREE(str_buf,rs->s); + H5FL_FREE(H5RS_str_t,rs); + } /* end if */ + +done: + FUNC_LEAVE(ret_value); +} /* end H5RS_decr() */ + + +/*-------------------------------------------------------------------------- + NAME + H5RS_incr + PURPOSE + Increment the reference count for a ref-counted string + USAGE + herr_t H5RS_incr(rs) + H5RS_str_t *rs; IN/OUT: Ref-counted string to increment count of + + RETURNS + Non-negative on success/Negative on failure + DESCRIPTION + Increment the reference count for a reference counted string. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5RS_incr(H5RS_str_t *rs) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5RS_incr,FAIL); + + /* Sanity check */ + assert(rs); + assert(rs->n > 0); + + /* If the ref-counted string started life as a wrapper around an existing + * string, duplicate the string now, so that the wrapped string can go out + * scope appropriately. + */ + if(rs->wrapped) { + rs->s=H5RS_xstrdup(rs->s); + rs->wrapped=0; + } /* end if */ + + /* Increment reference count for string */ + rs->n++; + +done: + FUNC_LEAVE(ret_value); +} /* end H5RS_incr() */ + + +/*-------------------------------------------------------------------------- + NAME + H5RS_dup + PURPOSE + "Duplicate" a ref-counted string + USAGE + H5RS_str_t H5RS_incr(rs) + H5RS_str_t *rs; IN/OUT: Ref-counted string to "duplicate" + + RETURNS + Returns a pointer to ref-counted string on success, NULL on failure. + DESCRIPTION + Increment the reference count for the reference counted string and return + a pointer to it. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +H5RS_str_t * +H5RS_dup(H5RS_str_t *ret_value) +{ + FUNC_ENTER_NOAPI(H5RS_dup,NULL); + + /* Check for valid reference counted string */ + if(ret_value!=NULL) + /* Increment reference count for string */ + ret_value->n++; + +done: + FUNC_LEAVE(ret_value); +} /* end H5RS_dup() */ + + +/*-------------------------------------------------------------------------- + NAME + H5RS_cmp + PURPOSE + Compare two ref-counted strings + USAGE + int H5RS_cmp(rs1,rs2) + const H5RS_str_t *rs1; IN: First Ref-counted string to compare + const H5RS_str_t *rs2; IN: Second Ref-counted string to compare + + RETURNS + Returns positive, negative or 0 for comparison of two r-strings [same as + strcmp()] + DESCRIPTION + Compare two ref-counted strings and return a value indicating their sort + order [same as strcmp()] + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +int +H5RS_cmp(const H5RS_str_t *rs1, const H5RS_str_t *rs2) +{ + /* Can't return invalid value from this function */ + FUNC_ENTER_NOINIT(H5RS_cmp); + + /* Sanity check */ + assert(rs1); + assert(rs1->s); + assert(rs2); + assert(rs2->s); + + FUNC_LEAVE(HDstrcmp(rs1->s,rs2->s)); +} /* end H5RS_cmp() */ + + +/*-------------------------------------------------------------------------- + NAME + H5RS_len + PURPOSE + Compute the length of a ref-counted string + USAGE + ssize_t H5RS_cmp(rs) + const H5RS_str_t *rs; IN: Ref-counted string to compute length of + + RETURNS + Returns non-negative value on success, negative value on failure + DESCRIPTION + Compute the length of a ref-counted string. [same as strlen()] + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +ssize_t +H5RS_len(const H5RS_str_t *rs) +{ + ssize_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5RS_len,FAIL); + + /* Sanity check */ + assert(rs); + assert(rs->s); + + ret_value=HDstrlen(rs->s); + +done: + FUNC_LEAVE(ret_value); +} /* end H5RS_len() */ + diff --git a/src/H5RSprivate.h b/src/H5RSprivate.h new file mode 100644 index 0000000..086396f --- /dev/null +++ b/src/H5RSprivate.h @@ -0,0 +1,52 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* + * This file contains private information about the H5RS module + */ +#ifndef _H5RSprivate_H +#define _H5RSprivate_H + +#ifdef LATER +#include "H5RSpublic.h" +#endif /* LATER */ + +/* Private headers needed by this file */ +#include "H5private.h" + +/* Typedefs */ + +/* Typedef for reference counted string */ +typedef struct { + char *s; /* String to be reference counted */ + unsigned wrapped; /* Indicates that the string to be ref-counted is not copied */ + unsigned n; /* Reference count of number of pointers sharing string */ +} H5RS_str_t; + +/* Macros */ + +/* Get the pointer to the actual string */ +#define H5RS_GET_STR(rs) ((rs)->s) +#define H5RS_GET_COUNT(rs) ((rs)->n) + +/* Private routines */ +H5_DLL H5RS_str_t *H5RS_create(const char *s); +H5_DLL H5RS_str_t *H5RS_wrap(char *s); +H5_DLL H5RS_str_t *H5RS_own(char *s); +H5_DLL herr_t H5RS_decr(H5RS_str_t *rs); +H5_DLL herr_t H5RS_incr(H5RS_str_t *rs); +H5_DLL H5RS_str_t *H5RS_dup(H5RS_str_t *s); +H5_DLL int H5RS_cmp(const H5RS_str_t *rs1, const H5RS_str_t *rs2); +H5_DLL ssize_t H5RS_len(const H5RS_str_t *rs); + +#endif /* _H5STprivate_H */ + diff --git a/src/H5S.c b/src/H5S.c index 6424ada..0127056 100644 --- a/src/H5S.c +++ b/src/H5S.c @@ -303,8 +303,21 @@ H5S_create(H5S_class_t type) FUNC_ENTER_NOAPI(H5S_create, NULL); /* Create a new data space */ - if((ret_value = H5FL_ALLOC(H5S_t,1))!=NULL) { + if((ret_value = H5FL_CALLOC(H5S_t))!=NULL) { ret_value->extent.type = type; + + switch(type) { + case H5S_SCALAR: + ret_value->extent.nelem = 1; + break; + case H5S_SIMPLE: + ret_value->extent.nelem = 0; + break; + default: + assert("unknown dataspace (extent) type" && 0); + break; + } /* end switch */ + if(H5S_select_all(ret_value,0)<0) HGOTO_ERROR (H5E_DATASPACE, H5E_CANTSET, NULL, "unable to set all selection"); } /* end if */ @@ -647,12 +660,12 @@ H5S_extent_copy(H5S_extent_t *dst, const H5S_extent_t *src) case H5S_SIMPLE: if (src->u.simple.size) { - dst->u.simple.size = H5FL_ARR_ALLOC(hsize_t,src->u.simple.rank,0); + dst->u.simple.size = H5FL_ARR_MALLOC(hsize_t,src->u.simple.rank); for (u = 0; u < src->u.simple.rank; u++) dst->u.simple.size[u] = src->u.simple.size[u]; } if (src->u.simple.max) { - dst->u.simple.max = H5FL_ARR_ALLOC(hsize_t,src->u.simple.rank,0); + dst->u.simple.max = H5FL_ARR_MALLOC(hsize_t,src->u.simple.rank); for (u = 0; u < src->u.simple.rank; u++) dst->u.simple.max[u] = src->u.simple.max[u]; } @@ -697,7 +710,7 @@ H5S_copy(const H5S_t *src) FUNC_ENTER_NOAPI(H5S_copy, NULL); - if (NULL==(dst = H5FL_ALLOC(H5S_t,0))) + if (NULL==(dst = H5FL_MALLOC(H5S_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); /* Copy the field in the struct */ @@ -740,30 +753,14 @@ hssize_t H5S_get_simple_extent_npoints(const H5S_t *ds) { hssize_t ret_value; - unsigned u; FUNC_ENTER_NOAPI(H5S_get_simple_extent_npoints, -1); /* check args */ assert(ds); - switch (ds->extent.type) { - case H5S_SCALAR: - ret_value = 1; - break; - - case H5S_SIMPLE: - for (ret_value=1, u=0; uextent.u.simple.rank; u++) - ret_value *= ds->extent.u.simple.size[u]; - break; - - case H5S_COMPLEX: - HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "complex data spaces are not supported yet"); - - default: - assert("unknown data space class" && 0); - HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "internal error (unknown data space class)"); - } + /* Get the number of elements in extent */ + ret_value = ds->extent.nelem; done: FUNC_LEAVE(ret_value); @@ -1078,7 +1075,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5S_modify(H5G_entry_t *ent, const H5S_t *ds) +H5S_modify(H5G_entry_t *ent, const H5S_t *ds, hbool_t update_time) { herr_t ret_value=SUCCEED; /* Return value */ @@ -1090,7 +1087,7 @@ H5S_modify(H5G_entry_t *ent, const H5S_t *ds) switch (ds->extent.type) { case H5S_SCALAR: case H5S_SIMPLE: - if (H5O_modify(ent, H5O_SDSPACE, 0, 0, &(ds->extent.u.simple))<0) + if (H5O_modify(ent, H5O_SDSPACE, 0, 0, update_time, &(ds->extent.u.simple))<0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't update simple data space message"); break; @@ -1108,6 +1105,52 @@ done: /*------------------------------------------------------------------------- + * Function: H5S_append + * + * Purpose: Updates a data space by adding a message to an object + * header. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, December 31, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5S_append(H5F_t *f, H5O_t *oh, const H5S_t *ds) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5S_append, FAIL); + + assert(f); + assert(oh); + assert(ds); + + switch (ds->extent.type) { + case H5S_SCALAR: + case H5S_SIMPLE: + if (H5O_append(f, oh, H5O_SDSPACE, 0, &(ds->extent.u.simple))<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't update simple data space message"); + break; + + case H5S_COMPLEX: + HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "complex data spaces are not implemented yet"); + + default: + assert("unknown data space class" && 0); + break; + } + +done: + FUNC_LEAVE(ret_value); +} /* end H5S_append() */ + + +/*------------------------------------------------------------------------- * Function: H5S_read * * Purpose: Reads the data space from an object header. @@ -1136,23 +1179,34 @@ H5S_read(H5G_entry_t *ent) /* check args */ assert(ent); - if (NULL==(ds = H5FL_ALLOC(H5S_t,1))) + if (NULL==(ds = H5FL_CALLOC(H5S_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); if (H5O_read(ent, H5O_SDSPACE, 0, &(ds->extent.u.simple)) == NULL) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, NULL, "unable to load dataspace info from dataset header"); - if(ds->extent.u.simple.rank != 0) - ds->extent.type = H5S_SIMPLE; - else - ds->extent.type = H5S_SCALAR; + if(ds->extent.u.simple.rank != 0) { + hsize_t nelem; /* Number of elements in extent */ + unsigned u; /* Local index variable */ + + ds->extent.type = H5S_SIMPLE; + + /* Compute the number of elements in the extent */ + for(u=0, nelem=1; uextent.u.simple.rank; u++) + nelem*=ds->extent.u.simple.size[u]; + ds->extent.nelem = nelem; + } /* end if */ + else { + ds->extent.type = H5S_SCALAR; + ds->extent.nelem = 1; + } /* end else */ /* Default to entire dataspace being selected */ if(H5S_select_all(ds,0)<0) HGOTO_ERROR (H5E_DATASPACE, H5E_CANTSET, NULL, "unable to set all selection"); /* Allocate space for the offset and set it to zeros */ - if (NULL==(ds->select.offset = H5FL_ARR_ALLOC(hssize_t,ds->extent.u.simple.rank,1))) + if (NULL==(ds->select.offset = H5FL_ARR_CALLOC(hssize_t,ds->extent.u.simple.rank))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); /* Set the value for successful return */ @@ -1407,7 +1461,7 @@ H5S_set_extent_simple (H5S_t *space, unsigned rank, const hsize_t *dims, space->select.offset=H5FL_ARR_FREE(hssize_t,space->select.offset); /* Allocate space for the offset and set it to zeros */ - if (NULL==(space->select.offset = H5FL_ARR_ALLOC(hssize_t,rank,1))) + if (NULL==(space->select.offset = H5FL_ARR_CALLOC(hssize_t,rank))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); /* shift out of the previous state to a "simple" dataspace */ @@ -1433,18 +1487,27 @@ H5S_set_extent_simple (H5S_t *space, unsigned rank, const hsize_t *dims, if (rank == 0) { /* scalar variable */ space->extent.type = H5S_SCALAR; + space->extent.nelem = 1; space->extent.u.simple.rank = 0; /* set to scalar rank */ } else { + hsize_t nelem; /* Number of elements in extent */ + unsigned u; /* Local index variable */ + space->extent.type = H5S_SIMPLE; /* Set the rank and copy the dims */ space->extent.u.simple.rank = rank; - space->extent.u.simple.size = H5FL_ARR_ALLOC(hsize_t,rank,0); + space->extent.u.simple.size = H5FL_ARR_MALLOC(hsize_t,rank); HDmemcpy(space->extent.u.simple.size, dims, sizeof(hsize_t) * rank); + /* Compute the number of elements in the extent */ + for(u=0, nelem=1; uextent.u.simple.rank; u++) + nelem*=space->extent.u.simple.size[u]; + space->extent.nelem = nelem; + /* Copy the maximum dimensions if specified */ if(max!=NULL) { - space->extent.u.simple.max = H5FL_ARR_ALLOC(hsize_t,rank,0); + space->extent.u.simple.max = H5FL_ARR_MALLOC(hsize_t,rank); HDmemcpy(space->extent.u.simple.max, max, sizeof(hsize_t) * rank); } /* end if */ } @@ -1629,6 +1692,7 @@ H5S_extend (H5S_t *space, const hsize_t *size) assert (space && H5S_SIMPLE==space->extent.type); assert (size); + /* Check through all the dimensions to see if modifying the dataspace is allowed */ for (u=0; uextent.u.simple.rank; u++) { if (space->extent.u.simple.size[u]extent.u.simple.max && @@ -1641,10 +1705,16 @@ H5S_extend (H5S_t *space, const hsize_t *size) /* Update */ if (ret_value) { - for (u=0; uextent.u.simple.rank; u++) { + hsize_t nelem; /* Number of elements in extent */ + + /* Change the dataspace size & re-compute the number of elements in the extent */ + for (u=0, nelem=1; uextent.u.simple.rank; u++) { if (space->extent.u.simple.size[u]extent.u.simple.size[u] = size[u]; + + nelem*=space->extent.u.simple.size[u]; } + space->extent.nelem = nelem; } done: @@ -1872,7 +1942,7 @@ H5Soffset_simple(hid_t space_id, const hssize_t *offset) /* Allocate space for new offset */ if(space->select.offset==NULL) { - if (NULL==(space->select.offset = H5FL_ARR_ALLOC(hssize_t,space->extent.u.simple.rank,0))) + if (NULL==(space->select.offset = H5FL_ARR_MALLOC(hssize_t,space->extent.u.simple.rank))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); } @@ -1922,9 +1992,14 @@ H5S_set_extent( H5S_t *space, const hsize_t *size ) /* Update */ if (ret_value) { - /* Update dimensions with new values */ - for ( u = 0; u < space->extent.u.simple.rank; u++ ) + hsize_t nelem; /* Number of elements in extent */ + + /* Change the dataspace size & re-compute the number of elements in the extent */ + for (u=0, nelem=1; u < space->extent.u.simple.rank; u++ ) { space->extent.u.simple.size[u] = size[u]; + nelem*=space->extent.u.simple.size[u]; + } /* end for */ + space->extent.nelem = nelem; } /* end if */ done: diff --git a/src/H5ST.c b/src/H5ST.c new file mode 100644 index 0000000..35b6ab8 --- /dev/null +++ b/src/H5ST.c @@ -0,0 +1,795 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* TERNARY SEARCH TREE ALGS + This code is described in "Ternary Search Trees" by Jon +Bentley and Robert Sedgewick in the April, 1998, Dr. Dobb's Journal. +*/ + +#include "H5Eprivate.h" /* Error handling */ +#include "H5FLprivate.h" /* Free lists */ +#include "H5STprivate.h" /* Ternary search trees */ + +#define PABLO_MASK H5ST_mask +static int interface_initialize_g = 0; +#define INTERFACE_INIT NULL + +/* Declare a free list to manage the H5ST_node_t struct */ +H5FL_DEFINE_STATIC(H5ST_node_t); + +/* Declare a free list to manage the H5ST_tree_t struct */ +H5FL_DEFINE_STATIC(H5ST_tree_t); + + +/*-------------------------------------------------------------------------- + NAME + H5ST_create + PURPOSE + Create a TST + USAGE + H5ST_ptr_t H5ST_create() + + RETURNS + Returns a pointer to the new TST tree on success, NULL on failure. + DESCRIPTION + Create a TST. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +H5ST_tree_t * +H5ST_create(void) +{ + H5ST_tree_t *ret_value=NULL; /* Return value */ + + FUNC_ENTER_NOAPI(H5ST_create,NULL); + + /* Allocate wrapper for TST */ + if((ret_value=H5FL_MALLOC(H5ST_tree_t))==NULL) + HGOTO_ERROR(H5E_RESOURCE,H5E_NOSPACE,NULL,"memory allocation failed"); + + /* Set the internal fields */ + ret_value->root=NULL; + +done: + FUNC_LEAVE(ret_value); +} /* end H5ST_create() */ + + +/*-------------------------------------------------------------------------- + NAME + H5ST_close_internal + PURPOSE + Close a TST, deallocating it. + USAGE + herr_t H5ST_close(p) + H5ST_ptr_t p; IN/OUT: Root of TST to free + + RETURNS + Returns non-negative on success, negative on failure. + DESCRIPTION + Close a TST, freeing all nodes. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5ST_close_internal(H5ST_ptr_t p) +{ + FUNC_ENTER_NOINIT(H5ST_close_internal); + + /* Recursively free TST */ + if(p) { + H5ST_close_internal(p->lokid); + if (p->splitchar) + H5ST_close_internal(p->eqkid); + H5ST_close_internal(p->hikid); + H5FL_FREE(H5ST_node_t,p); + } /* end if */ + + FUNC_LEAVE(SUCCEED); +} /* end H5ST_close_internal() */ + + +/*-------------------------------------------------------------------------- + NAME + H5ST_close + PURPOSE + Close a TST, deallocating it. + USAGE + herr_t H5ST_close(tree) + H5ST_tree_t *tree; IN/OUT: TST tree to free + + RETURNS + Returns non-negative on success, negative on failure. + DESCRIPTION + Close a TST, freeing all nodes. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5ST_close(H5ST_tree_t *tree) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5ST_close,FAIL); + + /* Check arguments */ + if(tree==NULL) + HGOTO_ERROR(H5E_ARGS,H5E_BADVALUE,FAIL,"invalid TST"); + + /* Free the TST itself */ + if(H5ST_close_internal(tree->root)<0) + HGOTO_ERROR(H5E_TST,H5E_CANTFREE,FAIL,"can't free TST"); + + /* Free root node itself */ + H5FL_FREE(H5ST_tree_t,tree); + +done: + FUNC_LEAVE(ret_value); +} /* end H5ST_close() */ + + +/*-------------------------------------------------------------------------- + NAME + H5ST_insert + PURPOSE + Insert a string/object pair into a TST + USAGE + herr_t H5ST_insert(tree,s,obj) + H5ST_tree_t *tree; IN/OUT: TST to insert string into + const char *s; IN: String to use as key for object + void *obj; IN: Pointer to object to insert + + RETURNS + Returns non-negative on success, negative on failure. + DESCRIPTION + Insert a key (string)/object pair into a TST + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5ST_insert(H5ST_tree_t *tree, const char *s, void *obj) +{ + int d; /* Comparison value */ + H5ST_ptr_t pp, *p; /* Pointer to current node and pointer to that */ + H5ST_ptr_t parent=NULL; /* Pointer to parent node */ + H5ST_ptr_t up=NULL; /* Pointer to up node */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5ST_insert,FAIL); + + /* Find the correct location to insert object */ + p = &tree->root; + while((pp = *p)) { + /* If this node matches the character in the key, then drop down to the lower tree */ + if ((d = *s - pp->splitchar) == 0) { + if (*s++ == 0) + HGOTO_ERROR(H5E_TST,H5E_EXISTS,FAIL,"key already in tree"); + up=pp; + p = &(pp->eqkid); + } /* end if */ + else { + /* Walk through the current tree, searching for the matching character */ + parent=pp; + if (d < 0) + p = &(pp->lokid); + else + p = &(pp->hikid); + } /* end else */ + } /* end while */ + + /* Finish walking through the key string, adding nodes until the end */ + for (;;) { + if((*p = H5FL_MALLOC(H5ST_node_t))==NULL) + HGOTO_ERROR(H5E_RESOURCE,H5E_NOSPACE,FAIL,"memory allocation failed"); + pp = *p; + pp->splitchar = *s; + pp->up = up; + pp->parent = parent; + pp->lokid = pp->eqkid = pp->hikid = NULL; + + /* If this is the end of the key string, break out */ + if (*s++ == 0) { + pp->eqkid = (H5ST_ptr_t) obj; + break; + } /* end if */ + + /* Continue to next character */ + parent=NULL; + up=pp; + p = &(pp->eqkid); + } /* end for */ + +done: + FUNC_LEAVE(ret_value); +} /* end H5ST_insert() */ + + +/*-------------------------------------------------------------------------- + NAME + H5ST_search + PURPOSE + Determine if a key is in the TST + USAGE + hbool_t H5ST_search(tree,s) + H5ST_tree_t *tree; IN: TST to find string in + const char *s; IN: String to use as key to locate + + RETURNS + Success: TRUE if key string in TST, FALSE if not + Failure: negative + DESCRIPTION + Locate a key (string) in a TST + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +htri_t +H5ST_search(H5ST_tree_t *tree, const char *s) +{ + H5ST_ptr_t p; /* Temporary pointer to TST node */ + htri_t ret_value=FALSE; /* Return value */ + + FUNC_ENTER_NOAPI(H5ST_search,FAIL); + + p = tree->root; + while (p) { + if (*s < p->splitchar) + p = p->lokid; + else if (*s == p->splitchar) { + if (*s++ == 0) + HGOTO_DONE(TRUE); + p = p->eqkid; + } else + p = p->hikid; + } /* end while */ + +done: + FUNC_LEAVE(ret_value); +} /* end H5ST_search() */ + + +/*-------------------------------------------------------------------------- + NAME + H5ST_find_internal + PURPOSE + Find the node matching a particular key string + USAGE + H5ST_ptr_t H5ST_find(p,s) + H5ST_ptr_t p; IN: TST to find string in + const char *s; IN: String to use as key to locate + + RETURNS + Success: Non-NULL + Failure: NULL + DESCRIPTION + Locate a key (string) in a TST + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static H5ST_ptr_t +H5ST_find_internal(H5ST_ptr_t p, const char *s) +{ + H5ST_ptr_t ret_value=NULL; /* Return value */ + + FUNC_ENTER_NOINIT(H5ST_find_internal); + + while (p) { + if (*s < p->splitchar) + p = p->lokid; + else if (*s == p->splitchar) { + if (*s++ == 0) + HGOTO_DONE(p); + p = p->eqkid; + } else + p = p->hikid; + } /* end while */ + +done: + FUNC_LEAVE(ret_value); +} /* end H5ST_find_internal() */ + + +/*-------------------------------------------------------------------------- + NAME + H5ST_find + PURPOSE + Find the node matching a particular key string + USAGE + H5ST_ptr_t H5ST_find(tree,s) + H5ST_tree_t *tree; IN: TST to find string in + const char *s; IN: String to use as key to locate + + RETURNS + Success: Non-NULL + Failure: NULL + DESCRIPTION + Locate a key (string) in a TST + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +H5ST_ptr_t +H5ST_find(H5ST_tree_t *tree, const char *s) +{ + H5ST_ptr_t ret_value=NULL; /* Return value */ + + FUNC_ENTER_NOAPI(H5ST_find,NULL); + + if((ret_value=H5ST_find_internal(tree->root,s))==NULL) + HGOTO_ERROR(H5E_TST,H5E_NOTFOUND,NULL,"key not found in TST"); + +done: + FUNC_LEAVE(ret_value); +} /* end H5ST_find() */ + + +/*-------------------------------------------------------------------------- + NAME + H5ST_locate + PURPOSE + Find an object in a TST + USAGE + void *H5ST_locate(tree,s) + H5ST_tree_t *tree; IN: TST to locate object within + const char *s; IN: String of key for object to locate + RETURNS + Success: Non-NULL, pointer to object stored for key + Failure: Negative + DESCRIPTION + Locate a node in a TST, returning the object from the node. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +void * +H5ST_locate(H5ST_tree_t *tree, const char *s) +{ + H5ST_ptr_t node; /* Pointer to node located */ + void *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5ST_locate,NULL); + + /* Locate the node to remove */ + if((node=H5ST_find_internal(tree->root,s))==NULL) + HGOTO_ERROR(H5E_TST,H5E_NOTFOUND,NULL,"key not found in TST"); + + /* Get the pointer to the object to return */ + ret_value=node->eqkid; + +done: + FUNC_LEAVE(ret_value); +} /* H5ST_locate() */ + + +/*-------------------------------------------------------------------------- + NAME + H5ST_findfirst_internal + PURPOSE + Find the first node in a TST + USAGE + H5ST_ptr_t H5ST_findfirst_internal(p) + H5ST_ptr_t p; IN: TST to locate first node within + RETURNS + Success: Non-NULL + Failure: NULL + DESCRIPTION + Get the first (lexicographically) node in a TST + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static H5ST_ptr_t +H5ST_findfirst_internal(H5ST_ptr_t p) +{ + H5ST_ptr_t ret_value=NULL; /* Return value */ + + FUNC_ENTER_NOINIT(H5ST_findfirst_internal); + + while(p) { + /* Find least node in current tree */ + while(p->lokid) + p=p->lokid; + + /* Is least node '\0'? */ + if(p->splitchar=='\0') { + /* Return it */ + HGOTO_DONE(p); + } /* end if */ + else { + /* Go down to next level of tree */ + p=p->eqkid; + } /* end else */ + } /* end while */ + +done: + FUNC_LEAVE(ret_value); +} /* end H5ST_findfirst_internal() */ + + +/*-------------------------------------------------------------------------- + NAME + H5ST_findfirst + PURPOSE + Find the first node in a TST + USAGE + H5ST_ptr_t H5ST_findfirst(tree) + H5ST_tree_t *tree; IN: TST to locate first node within + RETURNS + Success: Non-NULL + Failure: NULL + DESCRIPTION + Get the first (lexicographically) node in a TST + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +H5ST_ptr_t +H5ST_findfirst(H5ST_tree_t *tree) +{ + H5ST_ptr_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5ST_findfirst,NULL); + + if((ret_value=H5ST_findfirst_internal(tree->root))==NULL) + HGOTO_ERROR(H5E_TST,H5E_NOTFOUND,NULL,"no nodes in TST"); + +done: + FUNC_LEAVE(ret_value); +} /* end H5ST_findfirst() */ + + +/*-------------------------------------------------------------------------- + NAME + H5ST_getnext + PURPOSE + Internal routine to find the next node in a given level of a TST + USAGE + H5ST_ptr_t H5ST_getnext(p) + H5ST_ptr_t *p; IN: Pointer to node to find next node from + RETURNS + Success: Non-NULL + Failure: NULL + DESCRIPTION + Get the next (lexicographically) node in the current level of a TST + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static H5ST_ptr_t +H5ST_getnext(H5ST_ptr_t p) +{ + H5ST_ptr_t ret_value=NULL; /* Return value */ + + FUNC_ENTER_NOINIT(H5ST_getnext); + + /* If the node to continue from has higher-valued nodes attached */ + if(p->hikid) { + /* Go to first higher-valued node */ + p=p->hikid; + + /* Find least node from here */ + while(p->lokid) + p=p->lokid; + HGOTO_DONE(p); + } /* end if */ + else { + H5ST_ptr_t q; /* Temporary TST node pointer */ + + /* Go up one level in current tree */ + q=p->parent; + if(q==NULL) + HGOTO_DONE(NULL); + + /* While the previous node was the higher-valued node, keep backing up the tree */ + while(q->hikid==p) { + p=q; + q=p->parent; + if(q==NULL) + HGOTO_DONE(NULL); + } /* end while */ + HGOTO_DONE(q); + } /* end else */ + +done: + FUNC_LEAVE(ret_value); +} /* end H5ST_getnext() */ + + +/*-------------------------------------------------------------------------- + NAME + H5ST_findnext + PURPOSE + Find the next node from a node in a TST + USAGE + H5ST_ptr_t H5ST_findnext(p) + H5ST_ptr_t p; IN: Current node to continue from + RETURNS + Success: Non-NULL + Failure: NULL + DESCRIPTION + Get the next (lexicographically) node in a TST + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +H5ST_ptr_t +H5ST_findnext(H5ST_ptr_t p) +{ + H5ST_ptr_t q; /* Temporary pointer to TST node */ + H5ST_ptr_t ret_value=NULL; /* Return value */ + + FUNC_ENTER_NOAPI(H5ST_findnext,NULL); + + /* Find the next node at the current level, or go back up the tree */ + do { + q=H5ST_getnext(p); + if(q) { + HGOTO_DONE(H5ST_findfirst_internal(q->eqkid)); + } /* end if */ + else + p=p->up; + } while(p); + +done: + FUNC_LEAVE(ret_value); +} /* end H5ST_findnext() */ + + +/*-------------------------------------------------------------------------- + NAME + H5ST_delete_internal + PURPOSE + Delete a node from a TST + USAGE + herr_t H5ST_delete_internal(root,p) + H5ST_ptr_t *root; IN/OUT: Root of TST to delete node from + H5ST_ptr_t p; IN: Node to delete + RETURNS + Success: Non-negative + Failure: Negative + DESCRIPTION + Delete a node from a TST. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + This should be the final node for a string. + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5ST_delete_internal(H5ST_ptr_t *root, H5ST_ptr_t p) +{ + H5ST_ptr_t q, /* Temporary pointer to TST node */ + newp; /* Pointer to node which will replace deleted node in tree */ + + FUNC_ENTER_NOINIT(H5ST_delete_internal); + + /* Find node to replace one being deleted */ + if(p->lokid) { + /* If the deleted node has lo & hi kids, attach them together */ + if(p->hikid) { + q=p->lokid; + while(q->hikid) + q=q->hikid; + q->hikid=p->hikid; + p->hikid->parent=q; + } /* end if */ + newp=p->lokid; + } /* end if */ + else if(p->hikid) { + newp=p->hikid; + } /* end if */ + else { + newp=NULL; + } /* end else */ + + /* Deleted node is in middle of tree */ + if(p->parent) { + /* Attach new node to correct side of parent */ + if(p==p->parent->lokid) + p->parent->lokid=newp; + else + p->parent->hikid=newp; + if(newp) + newp->parent=p->parent; + } /* end if */ + else { + if(newp) + newp->parent=p->parent; + if(p->up) { + p->up->eqkid=newp; + /* If we deleted the last node in the TST, delete the upper node also */ + if(newp==NULL) + H5ST_delete_internal(root,p->up); + } /* end if */ + else /* Deleted last node at top level of tree */ + *root=newp; + } /* end else */ + + H5FL_FREE(H5ST_node_t,p); + + FUNC_LEAVE(SUCCEED); +} /* end H5ST_delete_internal() */ + + +/*-------------------------------------------------------------------------- + NAME + H5ST_delete + PURPOSE + Delete a node from a TST + USAGE + herr_t H5ST_delete(tree,p) + H5ST_tree_t *tree; IN/OUT: TST to delete node from + H5ST_ptr_t p; IN: Node to delete + RETURNS + Success: Non-negative + Failure: Negative + DESCRIPTION + Delete a node from a TST. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + This should be the final node for a string. + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5ST_delete(H5ST_tree_t *tree, H5ST_ptr_t p) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5ST_delete,FAIL); + + if(H5ST_delete_internal(&tree->root,p)<0) + HGOTO_ERROR(H5E_TST,H5E_CANTDELETE,FAIL,"can't delete node from TST"); + +done: + FUNC_LEAVE(ret_value); +} /* end H5ST_delete() */ + + +/*-------------------------------------------------------------------------- + NAME + H5ST_remove + PURPOSE + Remove a node from a TST + USAGE + void *H5ST_remove(tree,s) + H5ST_tree_t *tree; IN/OUT: TST to remove node from + const char *s; IN: String of key for node to remove + RETURNS + Success: Non-NULL, pointer to object stored for key + Failure: Negative + DESCRIPTION + Remove a node from a TST, returning the object from the node. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +void * +H5ST_remove(H5ST_tree_t *tree, const char *s) +{ + H5ST_ptr_t node; /* Pointer to node to remove */ + void *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5ST_remove,NULL); + + /* Locate the node to remove */ + if((node=H5ST_find_internal(tree->root,s))==NULL) + HGOTO_ERROR(H5E_TST,H5E_NOTFOUND,NULL,"key not found in TST"); + + /* Get the pointer to the object to return */ + ret_value=node->eqkid; + + /* Remove the node from the TST */ + if(H5ST_delete_internal(&tree->root,node)<0) + HGOTO_ERROR(H5E_TST,H5E_CANTDELETE,NULL,"can't delete node from TST"); + +done: + FUNC_LEAVE(ret_value); +} /* H5ST_remove() */ + +#ifdef H5ST_DEBUG + +/*-------------------------------------------------------------------------- + NAME + H5ST_dump_internal + PURPOSE + Dump all the nodes of a TST + USAGE + herr_t H5ST_dump(p) + H5ST_ptr_t p; IN: Root of TST to dump + RETURNS + Success: Non-negative + Failure: Negative + DESCRIPTION + Dump information for a TST. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5ST_dump_internal(H5ST_ptr_t p) +{ + FUNC_ENTER_NOINIT(H5ST_dump_internal); + + if (p) { + printf("p=%p\n",p); + printf("\tp->up=%p\n",p->up); + printf("\tp->parent=%p\n",p->parent); + printf("\tp->lokid=%p\n",p->lokid); + printf("\tp->hikid=%p\n",p->hikid); + printf("\tp->eqkid=%p\n",p->eqkid); + printf("\tp->splitchar=%c\n",p->splitchar); + + H5ST_dump_internal(p->lokid); + if (p->splitchar) + H5ST_dump_internal(p->eqkid); + else + printf("%s\n", (char *) p->eqkid); + H5ST_dump_internal(p->hikid); + } /* end if */ + +done: + FUNC_LEAVE(SUCCEED); +} /* end H5ST_dump_internal() */ + + +/*-------------------------------------------------------------------------- + NAME + H5ST_dump + PURPOSE + Dump all the nodes of a TST + USAGE + herr_t H5ST_dump(tree) + H5ST_tree_t *tree; IN: TST to dump + RETURNS + Success: Non-negative + Failure: Negative + DESCRIPTION + Dump information for a TST. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5ST_dump(H5ST_tree_t *tree) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5ST_dump,NULL); + + /* Dump the tree */ + H5ST_dump_internal(tree->root); + +done: + FUNC_LEAVE(ret_value); +} /* end H5ST_dump() */ +#endif /* H5ST_DEBUG */ diff --git a/src/H5STprivate.h b/src/H5STprivate.h new file mode 100644 index 0000000..60452a6 --- /dev/null +++ b/src/H5STprivate.h @@ -0,0 +1,61 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* + * This file contains private information about the H5ST module + */ +#ifndef _H5STprivate_H +#define _H5STprivate_H + +#ifdef LATER +#include "H5STpublic.h" +#endif /* LATER */ + +/* Private headers needed by this file */ +#include "H5private.h" + +/* Typedefs */ + +/* Internal nodes for TST */ +typedef struct H5ST_node *H5ST_ptr_t; +typedef struct H5ST_node { + char splitchar; /* Character represented at node */ + H5ST_ptr_t up; /* Pointer to the node in the tree above (before) this node */ + H5ST_ptr_t parent; /* Pointer to the next higher tree node in this tree */ + H5ST_ptr_t lokid; /* Pointer to the lower node from this one, in this tree */ + H5ST_ptr_t eqkid; /* Pointer to the parent node in the next tree down (after) this node */ + H5ST_ptr_t hikid; /* Pointer to the higher node from this one, in this tree */ +} H5ST_node_t; + +/* Wrapper about TST */ +typedef struct { + H5ST_ptr_t root; /* Pointer to actual TST */ +} H5ST_tree_t; + +/* Macro to access "data" pointer in H5ST_node_t's returned from functions */ +#define H5ST_NODE_DATA(p) ((void *)(p->eqkid)) + +/* Private routines */ +H5_DLL H5ST_tree_t *H5ST_create(void); +H5_DLL herr_t H5ST_close(H5ST_tree_t *p); +H5_DLL herr_t H5ST_insert(H5ST_tree_t *root, const char *s, void *obj); +H5_DLL htri_t H5ST_search(H5ST_tree_t *root, const char *s); +H5_DLL H5ST_ptr_t H5ST_find(H5ST_tree_t *root, const char *s); +H5_DLL void *H5ST_locate(H5ST_tree_t *root, const char *s); +H5_DLL H5ST_ptr_t H5ST_findfirst(H5ST_tree_t *p); +H5_DLL H5ST_ptr_t H5ST_findnext(H5ST_ptr_t p); +H5_DLL void *H5ST_remove(H5ST_tree_t *root, const char *s); +H5_DLL herr_t H5ST_delete(H5ST_tree_t *root, H5ST_ptr_t p); +H5_DLL herr_t H5ST_dump(H5ST_ptr_t p); + +#endif /* _H5STprivate_H */ + diff --git a/src/H5Sall.c b/src/H5Sall.c index ab12d70..8bab11c 100644 --- a/src/H5Sall.c +++ b/src/H5Sall.c @@ -175,7 +175,6 @@ done: hsize_t H5S_all_npoints (const H5S_t *space) { - unsigned u; /* Counters */ hsize_t ret_value; FUNC_ENTER_NOAPI(H5S_all_npoints, 0); @@ -183,8 +182,7 @@ H5S_all_npoints (const H5S_t *space) /* Check args */ assert (space); - for(u=0, ret_value=1; uextent.u.simple.rank; u++) - ret_value*=space->extent.u.simple.size[u]; + ret_value=(hsize_t)H5S_get_simple_extent_npoints(space); done: FUNC_LEAVE (ret_value); diff --git a/src/H5Shyper.c b/src/H5Shyper.c index 3eec64e..994238f 100644 --- a/src/H5Shyper.c +++ b/src/H5Shyper.c @@ -156,10 +156,14 @@ H5S_hyper_iter_init (const H5S_t *space, size_t elmt_size, H5S_sel_iter_t *sel_i sel_iter->hyp.iter_rank=cont_dim; /* Allocate the position & initialize to initial location */ - sel_iter->hyp.off = H5FL_ARR_ALLOC(hsize_t,cont_dim,0); - sel_iter->hyp.diminfo = H5FL_ARR_ALLOC(H5S_hyper_dim_t,cont_dim,0); - sel_iter->hyp.size = H5FL_ARR_ALLOC(hsize_t,cont_dim,0); - sel_iter->hyp.sel_off = H5FL_ARR_ALLOC(hssize_t,cont_dim,0); + sel_iter->hyp.off = H5FL_ARR_MALLOC(hsize_t,cont_dim); + assert(sel_iter->hyp.off); + sel_iter->hyp.diminfo = H5FL_ARR_MALLOC(H5S_hyper_dim_t,cont_dim); + assert(sel_iter->hyp.diminfo); + sel_iter->hyp.size = H5FL_ARR_MALLOC(hsize_t,cont_dim); + assert(sel_iter->hyp.size); + sel_iter->hyp.sel_off = H5FL_ARR_MALLOC(hssize_t,cont_dim); + assert(sel_iter->hyp.sel_off); /* "Flatten" dataspace extent and selection information */ for(i=space->extent.u.simple.rank-1, acc=1; i>=0; i--) { @@ -197,10 +201,20 @@ H5S_hyper_iter_init (const H5S_t *space, size_t elmt_size, H5S_sel_iter_t *sel_i } /* end if */ else { /* Allocate the position & initialize to initial location */ - sel_iter->hyp.off = H5FL_ARR_ALLOC(hsize_t,space->extent.u.simple.rank,0); + sel_iter->hyp.off = H5FL_ARR_MALLOC(hsize_t,space->extent.u.simple.rank); + assert(sel_iter->hyp.off); for(u=0; uextent.u.simple.rank; u++) sel_iter->hyp.off[u]=tdiminfo[u].start; + + /* Initialize other regular region information also (for release) */ + sel_iter->hyp.diminfo = NULL; + sel_iter->hyp.size = NULL; + sel_iter->hyp.sel_off = NULL; } /* end else */ + + /* Initialize irregular region information also (for release) */ + sel_iter->hyp.spans=NULL; + sel_iter->hyp.span=NULL; } /* end if */ else { /* Initialize the information needed for non-regular hyperslab I/O */ @@ -211,8 +225,10 @@ H5S_hyper_iter_init (const H5S_t *space, size_t elmt_size, H5S_sel_iter_t *sel_i H5S_hyper_span_precompute(sel_iter->hyp.spans,elmt_size); /* Allocate the span tree pointers, span pointers and positions */ - sel_iter->hyp.span = H5FL_ARR_ALLOC(H5S_hyper_span_t,space->extent.u.simple.rank,0); - sel_iter->hyp.off = H5FL_ARR_ALLOC(hsize_t,space->extent.u.simple.rank,0); + sel_iter->hyp.span = H5FL_ARR_MALLOC(H5S_hyper_span_t,space->extent.u.simple.rank); + assert(sel_iter->hyp.span); + sel_iter->hyp.off = H5FL_ARR_MALLOC(hsize_t,space->extent.u.simple.rank); + assert(sel_iter->hyp.off); /* Initialize the starting span_info's and spans */ spans=sel_iter->hyp.spans; @@ -230,6 +246,11 @@ H5S_hyper_iter_init (const H5S_t *space, size_t elmt_size, H5S_sel_iter_t *sel_i /* Get the pointer to the next level down */ spans=spans->head->down; } /* end for */ + + /* Initialize regular region information also (for release) */ + sel_iter->hyp.diminfo = NULL; + sel_iter->hyp.size = NULL; + sel_iter->hyp.sel_off = NULL; } /* end else */ done: @@ -499,7 +520,7 @@ H5S_hyper_new_span (hssize_t low, hssize_t high, H5S_hyper_span_info_t *down, H5 FUNC_ENTER_NOINIT(H5S_hyper_new_span); /* Allocate a new span node */ - if((ret_value = H5FL_ALLOC(H5S_hyper_span_t,0))==NULL) + if((ret_value = H5FL_MALLOC(H5S_hyper_span_t))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab span"); /* Copy the span's basic information */ @@ -710,7 +731,7 @@ H5S_hyper_copy_span_helper (H5S_hyper_span_info_t *spans) } /* end if */ else { /* Allocate a new span_info node */ - if((ret_value = H5FL_ALLOC(H5S_hyper_span_info_t,0))==NULL) + if((ret_value = H5FL_MALLOC(H5S_hyper_span_info_t))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab span"); /* Copy the span_info information */ @@ -1033,7 +1054,7 @@ H5S_hyper_copy (H5S_t *dst, const H5S_t *src) /* Check if there is regular hyperslab information to copy */ if(src->select.sel_info.hslab.diminfo!=NULL) { /* Create the per-dimension selection info */ - if((new_diminfo = H5FL_ARR_ALLOC(H5S_hyper_dim_t,src->extent.u.simple.rank,0))==NULL) + if((new_diminfo = H5FL_ARR_MALLOC(H5S_hyper_dim_t,src->extent.u.simple.rank))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate per-dimension array"); /* Copy the per-dimension selection info */ @@ -1046,7 +1067,7 @@ H5S_hyper_copy (H5S_t *dst, const H5S_t *src) dst->select.sel_info.hslab.diminfo = new_diminfo; /* Create the per-dimension selection info */ - if((new_diminfo = H5FL_ARR_ALLOC(H5S_hyper_dim_t,src->extent.u.simple.rank,0))==NULL) + if((new_diminfo = H5FL_ARR_MALLOC(H5S_hyper_dim_t,src->extent.u.simple.rank))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate per-dimension array"); /* Copy the per-dimension selection info */ @@ -1676,13 +1697,13 @@ H5S_hyper_deserialize (H5S_t *space, const uint8_t *buf) UINT32DECODE(buf,num_elem); /* decode the number of points */ /* Allocate space for the coordinates */ - if((start = H5FL_ARR_ALLOC(hsize_t,rank,0))==NULL) + if((start = H5FL_ARR_MALLOC(hsize_t,rank))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab information"); - if((end = H5FL_ARR_ALLOC(hsize_t,rank,0))==NULL) + if((end = H5FL_ARR_MALLOC(hsize_t,rank))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab information"); - if((block = H5FL_ARR_ALLOC(hsize_t,rank,0))==NULL) + if((block = H5FL_ARR_MALLOC(hsize_t,rank))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab information"); - if((count = H5FL_ARR_ALLOC(hsize_t,rank,0))==NULL) + if((count = H5FL_ARR_MALLOC(hsize_t,rank))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab information"); /* Set the count for all blocks */ @@ -2603,7 +2624,7 @@ H5S_hyper_append_span (H5S_hyper_span_t **prev_span, H5S_hyper_span_info_t ** sp assert(*span_tree==NULL); /* Allocate a new span_info node */ - if((*span_tree = H5FL_ALLOC(H5S_hyper_span_info_t,0))==NULL) + if((*span_tree = H5FL_MALLOC(H5S_hyper_span_info_t))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span"); /* Set the span tree's basic information */ @@ -3631,7 +3652,7 @@ H5S_hyper_make_spans (unsigned rank, const hssize_t *start, const hsize_t *strid /* Generate all the spans segments for this dimension */ for(u=0; uextent.u.simple.rank,0))==NULL) + if ((_stride=H5FL_ARR_MALLOC(hsize_t,space->extent.u.simple.rank))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for stride buffer"); H5V_array_fill(_stride,&fill,sizeof(hssize_t),space->extent.u.simple.rank); stride = _stride; @@ -3942,7 +3963,7 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, hssize_t fill=1; /* Allocate temporary buffer */ - if ((_block=H5FL_ARR_ALLOC(hsize_t,space->extent.u.simple.rank,0))==NULL) + if ((_block=H5FL_ARR_MALLOC(hsize_t,space->extent.u.simple.rank))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for stride buffer"); H5V_array_fill(_block,&fill,sizeof(hssize_t),space->extent.u.simple.rank); block = _block; @@ -4046,7 +4067,7 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release hyperslab"); /* Copy all the application per-dimension selection info into the space descriptor */ - if((diminfo = H5FL_ARR_ALLOC(H5S_hyper_dim_t,space->extent.u.simple.rank,0))==NULL) + if((diminfo = H5FL_ARR_MALLOC(H5S_hyper_dim_t,space->extent.u.simple.rank))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate per-dimension vector"); for(u=0; uextent.u.simple.rank; u++) { diminfo[u].start = start[u]; @@ -4057,7 +4078,7 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, space->select.sel_info.hslab.app_diminfo = diminfo; /* Allocate room for the optimized per-dimension selection info */ - if((diminfo = H5FL_ARR_ALLOC(H5S_hyper_dim_t,space->extent.u.simple.rank,0))==NULL) + if((diminfo = H5FL_ARR_MALLOC(H5S_hyper_dim_t,space->extent.u.simple.rank))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate per-dimension vector"); /* Optimize the hyperslab selection to detect contiguously selected block/stride information */ @@ -4479,7 +4500,7 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, hssize_t fill=1; /* Allocate temporary buffer */ - if ((_stride=H5FL_ARR_ALLOC(hsize_t,space->extent.u.simple.rank,0))==NULL) + if ((_stride=H5FL_ARR_MALLOC(hsize_t,space->extent.u.simple.rank))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for stride buffer"); H5V_array_fill(_stride,&fill,sizeof(hssize_t),space->extent.u.simple.rank); stride = _stride; @@ -4490,7 +4511,7 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, hssize_t fill=1; /* Allocate temporary buffer */ - if ((_block=H5FL_ARR_ALLOC(hsize_t,space->extent.u.simple.rank,0))==NULL) + if ((_block=H5FL_ARR_MALLOC(hsize_t,space->extent.u.simple.rank))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for stride buffer"); H5V_array_fill(_block,&fill,sizeof(hssize_t),space->extent.u.simple.rank); block = _block; @@ -4595,7 +4616,7 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release hyperslab"); /* Copy all the application per-dimension selection info into the space descriptor */ - if((diminfo = H5FL_ARR_ALLOC(H5S_hyper_dim_t,space->extent.u.simple.rank,0))==NULL) + if((diminfo = H5FL_ARR_MALLOC(H5S_hyper_dim_t,space->extent.u.simple.rank))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate per-dimension vector"); for(u=0; uextent.u.simple.rank; u++) { diminfo[u].start = start[u]; @@ -4606,7 +4627,7 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, space->select.sel_info.hslab.app_diminfo = diminfo; /* Allocate room for the optimized per-dimension selection info */ - if((diminfo = H5FL_ARR_ALLOC(H5S_hyper_dim_t,space->extent.u.simple.rank,0))==NULL) + if((diminfo = H5FL_ARR_MALLOC(H5S_hyper_dim_t,space->extent.u.simple.rank))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate per-dimension vector"); /* Optimize the hyperslab selection to detect contiguously selected block/stride information */ diff --git a/src/H5Smpio.c b/src/H5Smpio.c index 9b3f132..1fc2ea9 100644 --- a/src/H5Smpio.c +++ b/src/H5Smpio.c @@ -950,9 +950,9 @@ done: */ herr_t H5S_mpio_spaces_read(H5F_t *f, const H5O_layout_t *layout, - H5P_genplist_t UNUSED *dc_plist, size_t elmt_size, - const H5S_t *file_space, const H5S_t *mem_space, - hid_t dxpl_id, void *buf/*out*/) + H5P_genplist_t UNUSED *dc_plist, const H5O_efl_t UNUSED *efl, size_t elmt_size, + const H5S_t *file_space, const H5S_t *mem_space, hid_t dxpl_id, + void *buf/*out*/) { herr_t ret_value; @@ -989,9 +989,9 @@ done: */ herr_t H5S_mpio_spaces_write(H5F_t *f, H5O_layout_t *layout, - H5P_genplist_t UNUSED *dc_plist, size_t elmt_size, - const H5S_t *file_space, const H5S_t *mem_space, - hid_t dxpl_id, const void *buf) + H5P_genplist_t UNUSED *dc_plist, const H5O_efl_t UNUSED *efl, size_t elmt_size, + const H5S_t *file_space, const H5S_t *mem_space, hid_t dxpl_id, + const void *buf) { herr_t ret_value; diff --git a/src/H5Spkg.h b/src/H5Spkg.h index 97b5052..fc74733 100644 --- a/src/H5Spkg.h +++ b/src/H5Spkg.h @@ -33,7 +33,8 @@ typedef struct H5S_simple_t { /* Extent container */ typedef struct { - H5S_class_t type; /* Type of extent */ + H5S_class_t type; /* Type of extent */ + hsize_t nelem; /* Number of elements in extent */ union { H5S_simple_t simple; /* Simple dimensionality information */ } u; diff --git a/src/H5Spoint.c b/src/H5Spoint.c index 14d30d4..0072c15 100644 --- a/src/H5Spoint.c +++ b/src/H5Spoint.c @@ -167,7 +167,7 @@ H5S_point_add (H5S_t *space, H5S_seloper_t op, size_t num_elem, const hssize_t * top=curr=NULL; for(i=0; ipnt = H5MM_malloc(space->extent.u.simple.rank*sizeof(hssize_t)))==NULL) @@ -350,7 +350,7 @@ H5S_select_elements (H5S_t *space, H5S_seloper_t op, size_t num_elem, /* Allocate space for the point selection information if necessary */ if(space->select.type!=H5S_SEL_POINTS || space->select.sel_info.pnt_lst==NULL) { - if((space->select.sel_info.pnt_lst = H5FL_ALLOC(H5S_pnt_list_t,1))==NULL) + if((space->select.sel_info.pnt_lst = H5FL_CALLOC(H5S_pnt_list_t))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate element information"); } /* end if */ @@ -412,14 +412,14 @@ H5S_point_copy (H5S_t *dst, const H5S_t *src) assert(dst); /* Allocate room for the head of the point list */ - if((dst->select.sel_info.pnt_lst=H5FL_ALLOC(H5S_pnt_list_t,0))==NULL) + if((dst->select.sel_info.pnt_lst=H5FL_MALLOC(H5S_pnt_list_t))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate point node"); curr=src->select.sel_info.pnt_lst->head; new_head=NULL; while(curr!=NULL) { /* Create each point */ - if((new_node=H5FL_ALLOC(H5S_pnt_node_t,0))==NULL) + if((new_node=H5FL_MALLOC(H5S_pnt_node_t))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate point node"); if((new_node->pnt = H5MM_malloc(src->extent.u.simple.rank*sizeof(hssize_t)))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate coordinate information"); diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h index 1daaf04..0c267ac 100644 --- a/src/H5Sprivate.h +++ b/src/H5Sprivate.h @@ -103,16 +103,16 @@ typedef struct H5S_conv_t { /* Read from file to application w/o intermediate scratch buffer */ herr_t (*read)(H5F_t *f, const struct H5O_layout_t *layout, - H5P_genplist_t *dc_plist, size_t elmt_size, - const H5S_t *file_space, const H5S_t *mem_space, - hid_t dxpl_id, void *buf/*out*/); + H5P_genplist_t *dc_plist, const H5O_efl_t *efl, + size_t elmt_size, const H5S_t *file_space, + const H5S_t *mem_space, hid_t dxpl_id, void *buf/*out*/); /* Write directly from app buffer to file */ herr_t (*write)(H5F_t *f, struct H5O_layout_t *layout, - H5P_genplist_t *dc_plist, size_t elmt_size, - const H5S_t *file_space, const H5S_t *mem_space, - hid_t dxpl_id, const void *buf); + H5P_genplist_t *dc_plist, const H5O_efl_t *efl, + size_t elmt_size, const H5S_t *file_space, + const H5S_t *mem_space, hid_t dxpl_id, const void *buf); #ifdef H5S_DEBUG struct { @@ -150,7 +150,9 @@ H5_DLL int H5S_get_simple_extent_dims(const H5S_t *ds, hsize_t dims[]/*out*/, hsize_t max_dims[]/*out*/); H5_DLL herr_t H5S_set_extent_simple (H5S_t *space, unsigned rank, const hsize_t *dims, const hsize_t *max); -H5_DLL herr_t H5S_modify(struct H5G_entry_t *ent, const H5S_t *space); +H5_DLL herr_t H5S_modify(struct H5G_entry_t *ent, const H5S_t *space, + hbool_t update_time); +H5_DLL herr_t H5S_append(H5F_t *f, H5O_t *oh, const H5S_t *ds); H5_DLL H5S_t *H5S_read(struct H5G_entry_t *ent); H5_DLL int H5S_cmp(const H5S_t *ds1, const H5S_t *ds2); H5_DLL htri_t H5S_is_simple(const H5S_t *sdim); @@ -169,13 +171,13 @@ H5_DLL herr_t H5S_select_iterate(void *buf, hid_t type_id, H5S_t *space, H5_DLL herr_t H5S_select_fill(void *fill, size_t fill_size, const H5S_t *space, void *buf); H5_DLL herr_t H5S_select_fscat (H5F_t *f, struct H5O_layout_t *layout, - H5P_genplist_t *dc_plist, size_t elmt_size, const H5S_t *file_space, - H5S_sel_iter_t *file_iter, hsize_t nelmts, hid_t dxpl_id, - const void *_buf); + H5P_genplist_t *dc_plist, const H5O_efl_t *efl, size_t elmt_size, + const H5S_t *file_space, H5S_sel_iter_t *file_iter, hsize_t nelmts, + hid_t dxpl_id, const void *_buf); H5_DLL hsize_t H5S_select_fgath (H5F_t *f, const struct H5O_layout_t *layout, - H5P_genplist_t *dc_plist, size_t elmt_size, const H5S_t *file_space, - H5S_sel_iter_t *file_iter, hsize_t nelmts, hid_t dxpl_id, - void *buf); + H5P_genplist_t *dc_plist, const H5O_efl_t *efl, size_t elmt_size, + const H5S_t *file_space, H5S_sel_iter_t *file_iter, hsize_t nelmts, + hid_t dxpl_id, void *buf); H5_DLL herr_t H5S_select_mscat (const void *_tscat_buf, size_t elmt_size, const H5S_t *space, H5S_sel_iter_t *iter, hsize_t nelmts, hid_t dxpl_id, void *_buf/*out*/); @@ -183,11 +185,13 @@ H5_DLL hsize_t H5S_select_mgath (const void *_buf, size_t elmt_size, const H5S_t *space, H5S_sel_iter_t *iter, hsize_t nelmts, hid_t dxpl_id, void *_tgath_buf/*out*/); H5_DLL herr_t H5S_select_read(H5F_t *f, const struct H5O_layout_t *layout, - H5P_genplist_t *dc_plist, size_t elmt_size, const H5S_t *file_space, - const H5S_t *mem_space, hid_t dxpl_id, void *buf/*out*/); + H5P_genplist_t *dc_plist, const H5O_efl_t *efl, size_t elmt_size, + const H5S_t *file_space, const H5S_t *mem_space, hid_t dxpl_id, + void *buf/*out*/); H5_DLL herr_t H5S_select_write(H5F_t *f, struct H5O_layout_t *layout, - H5P_genplist_t *dc_plist, size_t elmt_size, const H5S_t *file_space, - const H5S_t *mem_space, hid_t dxpl_id, const void *buf/*out*/); + H5P_genplist_t *dc_plist, const H5O_efl_t *efl, size_t elmt_size, + const H5S_t *file_space, const H5S_t *mem_space, hid_t dxpl_id, + const void *buf/*out*/); /* Needed for internal use of selections in H5Fistore code */ H5_DLL herr_t H5S_select_all(H5S_t *space, unsigned rel_prev); @@ -200,6 +204,7 @@ H5_DLL herr_t H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, const hssize H5_DLL herr_t H5S_mpio_spaces_read(H5F_t *f, const struct H5O_layout_t *layout, H5P_genplist_t *dc_plist, + const H5O_efl_t *efl, size_t elmt_size, const H5S_t *file_space, const H5S_t *mem_space, hid_t dxpl_id, void *buf/*out*/); @@ -208,6 +213,7 @@ H5_DLL herr_t H5S_mpio_spaces_read(H5F_t *f, H5_DLL herr_t H5S_mpio_spaces_write(H5F_t *f, struct H5O_layout_t *layout, H5P_genplist_t *dc_plist, + const H5O_efl_t *efl, size_t elmt_size, const H5S_t *file_space, const H5S_t *mem_space, hid_t dxpl_id, const void *buf); diff --git a/src/H5Sselect.c b/src/H5Sselect.c index 0fb429e..edc8fa7 100644 --- a/src/H5Sselect.c +++ b/src/H5Sselect.c @@ -32,15 +32,56 @@ H5FL_ARR_DEFINE_STATIC(size_t,-1); /* Declare a free list to manage arrays of hsize_t */ H5FL_ARR_DEFINE_STATIC(hsize_t,-1); -/* Declare a free list to manage the H5S_sel_iter_t struct */ -H5FL_DEFINE_STATIC(H5S_sel_iter_t); - /* Declare a free list to manage blocks of single datatype element data */ H5FL_BLK_EXTERN(type_elem); /*-------------------------------------------------------------------------- NAME + H5S_get_vector_size + PURPOSE + Gets the size of the I/O vector + USAGE + ssize_t H5S_get_vector_size(dxpl_id) + hid_t dxpl_id; IN: The dataset transfer property list to query + RETURNS + Non-negative number of entries in I/O vector on success, negative on failure + DESCRIPTION + Retrieves the number of I/O vector entries to use for a given dataset + transfer. If the default dataset property list is used, the default + number of I/O vectors is returned. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static ssize_t +H5S_get_vector_size(hid_t dxpl_id) +{ + ssize_t ret_value; /* return value */ + + FUNC_ENTER_NOINIT(H5S_get_vector_size); + + if(dxpl_id==H5P_DATASET_XFER_DEFAULT) { + ret_value=H5D_XFER_HYPER_VECTOR_SIZE_DEF; + } /* end if */ + else { + H5P_genplist_t *dx_plist; /* Dataset transfer property list */ + + /* Get the hyperslab vector size */ + if(NULL == (dx_plist = H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list"); + if (H5P_get(dx_plist,H5D_XFER_HYPER_VECTOR_SIZE_NAME,&ret_value)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get value"); + } /* end else */ + +done: + FUNC_LEAVE (ret_value); +} /* H5S_get_vector_size() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_select_copy PURPOSE Copy a selection from one dataspace to another @@ -75,7 +116,7 @@ H5S_select_copy (H5S_t *dst, const H5S_t *src) /* Need to copy order information still */ /* Copy offset information */ - if (NULL==(dst->select.offset = H5FL_ARR_ALLOC(hssize_t,src->extent.u.simple.rank,1))) + if (NULL==(dst->select.offset = H5FL_ARR_CALLOC(hssize_t,src->extent.u.simple.rank))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); if(src->select.offset!=NULL) HDmemcpy(dst->select.offset,src->select.offset,(src->extent.u.simple.rank*sizeof(hssize_t))); @@ -342,8 +383,8 @@ H5S_select_iterate(void *buf, hid_t type_id, H5S_t *space, H5D_operator_t op, void *operator_data) { H5T_t *dt; /* Datatype structure */ - H5P_genplist_t *dx_plist; /* Dataset transfer property list */ - H5S_sel_iter_t *iter=NULL; /* Selection iteration info */ + H5S_sel_iter_t iter; /* Selection iteration info */ + hbool_t iter_init=0; /* Selection iteration info has been initialized */ uint8_t *loc; /* Current element location in buffer */ hssize_t coords[H5O_LAYOUT_NDIMS]; /* Coordinates of element in dataspace */ hssize_t nelmts; /* Number of elements in selection */ @@ -353,7 +394,7 @@ H5S_select_iterate(void *buf, hid_t type_id, H5S_t *space, H5D_operator_t op, hsize_t tmp_off; /* Temporary offset within sequence */ size_t *len=NULL; /* Array to store sequence lengths */ size_t curr_len; /* Length of bytes left to process in sequence */ - size_t vector_size; /* Value for vector size */ + ssize_t vector_size; /* Value for vector size */ size_t nseq; /* Number of sequences generated */ size_t curr_seq; /* Current sequnce being worked on */ size_t nbytes; /* Number of bytes used in sequences */ @@ -374,15 +415,13 @@ H5S_select_iterate(void *buf, hid_t type_id, H5S_t *space, H5D_operator_t op, /* Get the hyperslab vector size */ /* (from the default data transfer property list, for now) */ - dx_plist = H5I_object(H5P_DATASET_XFER_DEFAULT); - assert(dx_plist); - if (H5P_get(dx_plist,H5D_XFER_HYPER_VECTOR_SIZE_NAME,&vector_size)<0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get value"); + if((vector_size=H5S_get_vector_size(H5P_DATASET_XFER_DEFAULT))<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get I/O vector size"); /* Allocate the vector I/O arrays */ - if((len = H5FL_ARR_ALLOC(size_t,vector_size,0))==NULL) + if((len = H5FL_ARR_MALLOC(size_t,(size_t)vector_size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array"); - if((off = H5FL_ARR_ALLOC(hsize_t,vector_size,0))==NULL) + if((off = H5FL_ARR_MALLOC(hsize_t,(size_t)vector_size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array"); /* Get the datatype size */ @@ -391,13 +430,10 @@ H5S_select_iterate(void *buf, hid_t type_id, H5S_t *space, H5D_operator_t op, if((elmt_size=H5T_get_size(dt))==0) HGOTO_ERROR(H5E_DATATYPE, H5E_BADSIZE, FAIL, "datatype size invalid"); - /* Allocate iterator */ - if((iter = H5FL_ALLOC(H5S_sel_iter_t,1))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate selection iterator"); - /* Initialize iterator */ - if ((*space->select.iter_init)(space, elmt_size, iter)<0) + if ((*space->select.iter_init)(space, elmt_size, &iter)<0) HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator"); + iter_init=1; /* Selection iteration info has been initialized */ /* Get the number of elements in selection */ if((nelmts = (*space->select.get_npoints)(space))<0) @@ -419,7 +455,7 @@ H5S_select_iterate(void *buf, hid_t type_id, H5S_t *space, H5D_operator_t op, /* Loop, while elements left in selection */ while(max_bytes>0 && user_ret==0) { /* Get the sequences of bytes */ - if((*space->select.get_seq_list)(space,0,iter,elmt_size,vector_size,max_bytes,&nseq,&nbytes,off,len)<0) + if((*space->select.get_seq_list)(space,0,&iter,elmt_size,(size_t)vector_size,max_bytes,&nseq,&nbytes,off,len)<0) HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed"); /* Loop, while sequences left to process */ @@ -462,10 +498,9 @@ H5S_select_iterate(void *buf, hid_t type_id, H5S_t *space, H5D_operator_t op, done: /* Release selection iterator */ - if(iter!=NULL) { - if ((*space->select.iter_release)(iter)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); - H5FL_FREE(H5S_sel_iter_t,iter); + if(iter_init) { + if ((*space->select.iter_release)(&iter)<0) + HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); } /* end if */ /* Release length & offset vectors */ @@ -661,14 +696,14 @@ done: herr_t H5S_select_fill(void *_fill, size_t fill_size, const H5S_t *space, void *_buf) { - H5P_genplist_t *dx_plist; /* Dataset transfer property list */ - H5S_sel_iter_t *iter=NULL; /* Selection iteration info */ + H5S_sel_iter_t iter; /* Selection iteration info */ + hbool_t iter_init=0; /* Selection iteration info has been initialized */ uint8_t *buf; /* Current location in buffer */ void *fill=_fill; /* Alias for fill-value buffer */ hssize_t nelmts; /* Number of elements in selection */ hsize_t *off=NULL; /* Array to store sequence offsets */ size_t *len=NULL; /* Array to store sequence lengths */ - size_t vector_size; /* Value for vector size */ + ssize_t vector_size; /* Value for vector size */ size_t nseq; /* Number of sequences generated */ size_t curr_seq; /* Current sequnce being worked on */ size_t nbytes; /* Number of bytes used in sequences */ @@ -684,30 +719,25 @@ H5S_select_fill(void *_fill, size_t fill_size, const H5S_t *space, void *_buf) /* Check if we need a temporary fill value buffer */ if(fill==NULL) { - if (NULL==(fill = H5FL_BLK_ALLOC(type_elem,fill_size,1))) + if (NULL==(fill = H5FL_BLK_CALLOC(type_elem,fill_size))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "fill value buffer allocation failed"); } /* end if */ /* Get the hyperslab vector size */ /* (from the default data transfer property list, for now) */ - dx_plist = H5I_object(H5P_DATASET_XFER_DEFAULT); - assert(dx_plist); - if (H5P_get(dx_plist,H5D_XFER_HYPER_VECTOR_SIZE_NAME,&vector_size)<0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get value"); + if((vector_size=H5S_get_vector_size(H5P_DATASET_XFER_DEFAULT))<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get I/O vector size"); /* Allocate the vector I/O arrays */ - if((len = H5FL_ARR_ALLOC(size_t,vector_size,0))==NULL) + if((len = H5FL_ARR_MALLOC(size_t,(size_t)vector_size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array"); - if((off = H5FL_ARR_ALLOC(hsize_t,vector_size,0))==NULL) + if((off = H5FL_ARR_MALLOC(hsize_t,(size_t)vector_size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array"); - /* Allocate iterator */ - if((iter = H5FL_ALLOC(H5S_sel_iter_t,1))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate selection iterator"); - /* Initialize iterator */ - if ((*space->select.iter_init)(space, fill_size, iter)<0) + if ((*space->select.iter_init)(space, fill_size, &iter)<0) HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator"); + iter_init=1; /* Selection iteration info has been initialized */ /* Get the number of elements in selection */ if((nelmts = (*space->select.get_npoints)(space))<0) @@ -720,7 +750,7 @@ H5S_select_fill(void *_fill, size_t fill_size, const H5S_t *space, void *_buf) /* Loop, while elements left in selection */ while(max_bytes>0) { /* Get the sequences of bytes */ - if((*space->select.get_seq_list)(space,0,iter,fill_size,vector_size,max_bytes,&nseq,&nbytes,off,len)<0) + if((*space->select.get_seq_list)(space,0,&iter,fill_size,(size_t)vector_size,max_bytes,&nseq,&nbytes,off,len)<0) HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed"); /* Loop over sequences */ @@ -739,10 +769,9 @@ H5S_select_fill(void *_fill, size_t fill_size, const H5S_t *space, void *_buf) done: /* Release selection iterator */ - if(iter!=NULL) { - if ((*space->select.iter_release)(iter)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); - H5FL_FREE(H5S_sel_iter_t,iter); + if(iter_init) { + if ((*space->select.iter_release)(&iter)<0) + HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); } /* end if */ /* Release length & offset vectors */ @@ -779,18 +808,17 @@ done: */ herr_t H5S_select_fscat (H5F_t *f, struct H5O_layout_t *layout, - H5P_genplist_t *dc_plist, size_t elmt_size, - const H5S_t *space, H5S_sel_iter_t *iter, - hsize_t nelmts, hid_t dxpl_id, const void *_buf) + H5P_genplist_t *dc_plist, const H5O_efl_t *efl, size_t elmt_size, + const H5S_t *space, H5S_sel_iter_t *iter, hsize_t nelmts, + hid_t dxpl_id, const void *_buf) { const uint8_t *buf=_buf; /* Alias for pointer arithmetic */ hsize_t *off=NULL; /* Array to store sequence offsets */ size_t *len=NULL; /* Array to store sequence lengths */ - size_t vector_size; /* Value for vector size */ + ssize_t vector_size; /* Value for vector size */ size_t maxbytes; /* Number of bytes in the buffer */ size_t nseq; /* Number of sequences generated */ size_t nbytes; /* Number of bytes used in sequences */ - H5P_genplist_t *dx_plist; /* Dataset transfer property list */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5S_select_fscat, FAIL); @@ -799,6 +827,7 @@ H5S_select_fscat (H5F_t *f, struct H5O_layout_t *layout, assert (f); assert (layout); assert (elmt_size>0); + assert (efl); assert (space); assert (iter); assert (nelmts>0); @@ -806,15 +835,13 @@ H5S_select_fscat (H5F_t *f, struct H5O_layout_t *layout, assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); /* Get the hyperslab vector size */ - if(NULL == (dx_plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list"); - if (H5P_get(dx_plist,H5D_XFER_HYPER_VECTOR_SIZE_NAME,&vector_size)<0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get value"); + if((vector_size=H5S_get_vector_size(dxpl_id))<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get I/O vector size"); /* Allocate the vector I/O arrays */ - if((len = H5FL_ARR_ALLOC(size_t,vector_size,0))==NULL) + if((len = H5FL_ARR_MALLOC(size_t,(size_t)vector_size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array"); - if((off = H5FL_ARR_ALLOC(hsize_t,vector_size,0))==NULL) + if((off = H5FL_ARR_MALLOC(hsize_t,(size_t)vector_size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array"); /* Compute the number of bytes available in buffer */ @@ -823,11 +850,11 @@ H5S_select_fscat (H5F_t *f, struct H5O_layout_t *layout, /* Loop until all elements are written */ while(maxbytes>0) { /* Get list of sequences for selection to write */ - if((*space->select.get_seq_list)(space,H5S_GET_SEQ_LIST_SORTED,iter,elmt_size,vector_size,maxbytes,&nseq,&nbytes,off,len)<0) + if((*space->select.get_seq_list)(space,H5S_GET_SEQ_LIST_SORTED,iter,elmt_size,(size_t)vector_size,maxbytes,&nseq,&nbytes,off,len)<0) HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed"); /* Write sequence list out */ - if (H5F_seq_writev(f, dxpl_id, layout, dc_plist, space, elmt_size, nseq, len, off, buf)<0) + if (H5F_seq_writev(f, dxpl_id, layout, dc_plist, efl, space, elmt_size, nseq, len, off, buf)<0) HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error"); /* Update buffer */ @@ -872,19 +899,17 @@ done: */ hsize_t H5S_select_fgath (H5F_t *f, const struct H5O_layout_t *layout, - H5P_genplist_t *dc_plist, - size_t elmt_size, const H5S_t *space, - H5S_sel_iter_t *iter, hsize_t nelmts, hid_t dxpl_id, - void *_buf/*out*/) + H5P_genplist_t *dc_plist, const H5O_efl_t *efl, size_t elmt_size, + const H5S_t *space, H5S_sel_iter_t *iter, hsize_t nelmts, + hid_t dxpl_id, void *_buf/*out*/) { uint8_t *buf=_buf; /* Alias for pointer arithmetic */ hsize_t *off=NULL; /* Array to store sequence offsets */ size_t *len=NULL; /* Array to store sequence lengths */ - size_t vector_size; /* Value for vector size */ + ssize_t vector_size; /* Value for vector size */ size_t maxbytes; /* Number of bytes in the buffer */ size_t nseq; /* Number of sequences generated */ size_t nbytes; /* Number of bytes used in sequences */ - H5P_genplist_t *dx_plist; /* Dataset transfer property list */ hsize_t ret_value=nelmts; /* Return value */ FUNC_ENTER_NOAPI(H5S_select_fgath, 0); @@ -893,21 +918,20 @@ H5S_select_fgath (H5F_t *f, const struct H5O_layout_t *layout, assert (f); assert (layout); assert (elmt_size>0); + assert (efl); assert (space); assert (iter); assert (nelmts>0); assert (_buf); /* Get the hyperslab vector size */ - if(NULL == (dx_plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a file access property list"); - if (H5P_get(dx_plist,H5D_XFER_HYPER_VECTOR_SIZE_NAME,&vector_size)<0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, 0, "unable to get value"); + if((vector_size=H5S_get_vector_size(dxpl_id))<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, 0, "unable to get I/O vector size"); /* Allocate the vector I/O arrays */ - if((len = H5FL_ARR_ALLOC(size_t,vector_size,0))==NULL) + if((len = H5FL_ARR_MALLOC(size_t,(size_t)vector_size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate I/O length vector array"); - if((off = H5FL_ARR_ALLOC(hsize_t,vector_size,0))==NULL) + if((off = H5FL_ARR_MALLOC(hsize_t,(size_t)vector_size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate I/O offset vector array"); /* Compute the number of bytes available in buffer */ @@ -916,11 +940,11 @@ H5S_select_fgath (H5F_t *f, const struct H5O_layout_t *layout, /* Loop until all elements are written */ while(maxbytes>0) { /* Get list of sequences for selection to write */ - if((*space->select.get_seq_list)(space,H5S_GET_SEQ_LIST_SORTED,iter,elmt_size,vector_size,maxbytes,&nseq,&nbytes,off,len)<0) + if((*space->select.get_seq_list)(space,H5S_GET_SEQ_LIST_SORTED,iter,elmt_size,(size_t)vector_size,maxbytes,&nseq,&nbytes,off,len)<0) HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed"); /* Read sequence list in */ - if (H5F_seq_readv(f, dxpl_id, layout, dc_plist, space, elmt_size, nseq, len, off, buf)<0) + if (H5F_seq_readv(f, dxpl_id, layout, dc_plist, efl, space, elmt_size, nseq, len, off, buf)<0) HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, 0, "read error"); /* Update buffer */ @@ -961,11 +985,10 @@ herr_t H5S_select_mscat (const void *_tscat_buf, size_t elmt_size, const H5S_t *space, H5S_sel_iter_t *iter, hsize_t nelmts, hid_t dxpl_id, void *_buf/*out*/) { - H5P_genplist_t *dx_plist; /* Dataset transfer property list */ uint8_t *buf=(uint8_t *)_buf; /* Get local copies for address arithmetic */ const uint8_t *tscat_buf=(const uint8_t *)_tscat_buf; hsize_t *off=NULL; /* Array to store sequence offsets */ - size_t vector_size; /* Value for vector size */ + ssize_t vector_size; /* Value for vector size */ size_t *len=NULL; /* Array to store sequence lengths */ size_t curr_len; /* Length of bytes left to process in sequence */ size_t maxbytes; /* Number of bytes in the buffer */ @@ -985,15 +1008,13 @@ H5S_select_mscat (const void *_tscat_buf, size_t elmt_size, const H5S_t *space, assert (buf); /* Get the hyperslab vector size */ - if(NULL == (dx_plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list"); - if (H5P_get(dx_plist,H5D_XFER_HYPER_VECTOR_SIZE_NAME,&vector_size)<0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get value"); + if((vector_size=H5S_get_vector_size(dxpl_id))<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get I/O vector size"); /* Allocate the vector I/O arrays */ - if((len = H5FL_ARR_ALLOC(size_t,vector_size,0))==NULL) + if((len = H5FL_ARR_MALLOC(size_t,(size_t)vector_size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array"); - if((off = H5FL_ARR_ALLOC(hsize_t,vector_size,0))==NULL) + if((off = H5FL_ARR_MALLOC(hsize_t,(size_t)vector_size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array"); /* Compute the number of bytes available in buffer */ @@ -1002,7 +1023,7 @@ H5S_select_mscat (const void *_tscat_buf, size_t elmt_size, const H5S_t *space, /* Loop until all elements are written */ while(maxbytes>0) { /* Get list of sequences for selection to write */ - if((*space->select.get_seq_list)(space,0,iter,elmt_size,vector_size,maxbytes,&nseq,&nbytes,off,len)<0) + if((*space->select.get_seq_list)(space,0,iter,elmt_size,(size_t)vector_size,maxbytes,&nseq,&nbytes,off,len)<0) HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed"); /* Loop, while sequences left to process */ @@ -1053,11 +1074,10 @@ hsize_t H5S_select_mgath (const void *_buf, size_t elmt_size, const H5S_t *space, H5S_sel_iter_t *iter, hsize_t nelmts, hid_t dxpl_id, void *_tgath_buf/*out*/) { - H5P_genplist_t *dx_plist; /* Dataset transfer property list */ const uint8_t *buf=(const uint8_t *)_buf; /* Get local copies for address arithmetic */ uint8_t *tgath_buf=(uint8_t *)_tgath_buf; hsize_t *off=NULL; /* Array to store sequence offsets */ - size_t vector_size; /* Value for vector size */ + ssize_t vector_size; /* Value for vector size */ size_t *len=NULL; /* Array to store sequence lengths */ size_t curr_len; /* Length of bytes left to process in sequence */ size_t maxbytes; /* Number of bytes in the buffer */ @@ -1077,15 +1097,13 @@ H5S_select_mgath (const void *_buf, size_t elmt_size, const H5S_t *space, assert (tgath_buf); /* Get the hyperslab vector size */ - if(NULL == (dx_plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a dataset transfer property list"); - if (H5P_get(dx_plist,H5D_XFER_HYPER_VECTOR_SIZE_NAME,&vector_size)<0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, 0, "unable to get value"); + if((vector_size=H5S_get_vector_size(dxpl_id))<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, 0, "unable to get I/O vector size"); /* Allocate the vector I/O arrays */ - if((len = H5FL_ARR_ALLOC(size_t,vector_size,0))==NULL) + if((len = H5FL_ARR_MALLOC(size_t,(size_t)vector_size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate I/O length vector array"); - if((off = H5FL_ARR_ALLOC(hsize_t,vector_size,0))==NULL) + if((off = H5FL_ARR_MALLOC(hsize_t,(size_t)vector_size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate I/O offset vector array"); /* Compute the number of bytes available in buffer */ @@ -1094,7 +1112,7 @@ H5S_select_mgath (const void *_buf, size_t elmt_size, const H5S_t *space, /* Loop until all elements are written */ while(maxbytes>0) { /* Get list of sequences for selection to write */ - if((*space->select.get_seq_list)(space,0,iter,elmt_size,vector_size,maxbytes,&nseq,&nbytes,off,len)<0) + if((*space->select.get_seq_list)(space,0,iter,elmt_size,(size_t)vector_size,maxbytes,&nseq,&nbytes,off,len)<0) HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed"); /* Loop, while sequences left to process */ @@ -1138,16 +1156,17 @@ done: */ herr_t H5S_select_read(H5F_t *f, const H5O_layout_t *layout, H5P_genplist_t *dc_plist, - size_t elmt_size, const H5S_t *file_space, - const H5S_t *mem_space, hid_t dxpl_id, void *_buf/*out*/) + const H5O_efl_t *efl, size_t elmt_size, const H5S_t *file_space, + const H5S_t *mem_space, hid_t dxpl_id, void *_buf/*out*/) { - H5P_genplist_t *dx_plist; /* Dataset transfer property list */ - H5S_sel_iter_t *mem_iter=NULL; /* Memory selection iteration info */ - H5S_sel_iter_t *file_iter=NULL; /* File selection iteration info */ + H5S_sel_iter_t mem_iter; /* Memory selection iteration info */ + hbool_t mem_iter_init=0; /* Memory selection iteration info has been initialized */ + H5S_sel_iter_t file_iter; /* File selection iteration info */ + hbool_t file_iter_init=0; /* File selection iteration info has been initialized */ uint8_t *buf=NULL; /* Local buffer pointer, for address arithmetic */ hsize_t *mem_off=NULL; /* Array to store sequence offsets in memory */ hsize_t *file_off=NULL; /* Array to store sequence offsets in the file */ - size_t vector_size; /* Value for vector size */ + ssize_t vector_size; /* Value for vector size */ size_t *mem_len=NULL; /* Array to store sequence lengths in memory */ size_t *file_len=NULL; /* Array to store sequence lengths in the file */ size_t maxbytes; /* Number of bytes in selection */ @@ -1168,40 +1187,33 @@ H5S_select_read(H5F_t *f, const H5O_layout_t *layout, H5P_genplist_t *dc_plist, /* Check args */ assert(f); + assert(efl); assert(_buf); assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); /* Get the hyperslab vector size */ - if(NULL == (dx_plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list"); - if (H5P_get(dx_plist,H5D_XFER_HYPER_VECTOR_SIZE_NAME,&vector_size)<0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get value"); + if((vector_size=H5S_get_vector_size(dxpl_id))<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get I/O vector size"); /* Allocate the vector I/O arrays */ - if((mem_len = H5FL_ARR_ALLOC(size_t,vector_size,0))==NULL) + if((mem_len = H5FL_ARR_MALLOC(size_t,(size_t)vector_size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array"); - if((mem_off = H5FL_ARR_ALLOC(hsize_t,vector_size,0))==NULL) + if((mem_off = H5FL_ARR_MALLOC(hsize_t,(size_t)vector_size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array"); - if((file_len = H5FL_ARR_ALLOC(size_t,vector_size,0))==NULL) + if((file_len = H5FL_ARR_MALLOC(size_t,(size_t)vector_size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array"); - if((file_off = H5FL_ARR_ALLOC(hsize_t,vector_size,0))==NULL) + if((file_off = H5FL_ARR_MALLOC(hsize_t,(size_t)vector_size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array"); - /* Allocate file iterator */ - if((file_iter = H5FL_ALLOC(H5S_sel_iter_t,1))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate selection iterator"); - /* Initialize file iterator */ - if ((*file_space->select.iter_init)(file_space, elmt_size, file_iter)<0) + if ((*file_space->select.iter_init)(file_space, elmt_size, &file_iter)<0) HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator"); - - /* Allocate memory iterator */ - if((mem_iter = H5FL_ALLOC(H5S_sel_iter_t,1))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate selection iterator"); + file_iter_init=1; /* File selection iteration info has been initialized */ /* Initialize memory iterator */ - if ((*mem_space->select.iter_init)(mem_space, elmt_size, mem_iter)<0) + if ((*mem_space->select.iter_init)(mem_space, elmt_size, &mem_iter)<0) HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator"); + mem_iter_init=1; /* Memory selection iteration info has been initialized */ /* Get number of bytes in selection */ maxbytes=(*file_space->select.get_npoints)(file_space)*elmt_size; @@ -1215,7 +1227,7 @@ H5S_select_read(H5F_t *f, const H5O_layout_t *layout, H5P_genplist_t *dc_plist, /* Check if more file sequences are needed */ if(curr_file_seq>=file_nseq) { /* Get sequences for file selection */ - if((*file_space->select.get_seq_list)(file_space,H5S_GET_SEQ_LIST_SORTED,file_iter,elmt_size,vector_size,maxbytes,&file_nseq,&file_nbytes,file_off,file_len)<0) + if((*file_space->select.get_seq_list)(file_space,H5S_GET_SEQ_LIST_SORTED,&file_iter,elmt_size,(size_t)vector_size,maxbytes,&file_nseq,&file_nbytes,file_off,file_len)<0) HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed"); /* Start at the beginning of the sequences again */ @@ -1225,7 +1237,7 @@ H5S_select_read(H5F_t *f, const H5O_layout_t *layout, H5P_genplist_t *dc_plist, /* Check if more memory sequences are needed */ if(curr_mem_seq>=mem_nseq) { /* Get sequences for memory selection */ - if((*mem_space->select.get_seq_list)(mem_space,0,mem_iter,elmt_size,vector_size,maxbytes,&mem_nseq,&mem_nbytes,mem_off,mem_len)<0) + if((*mem_space->select.get_seq_list)(mem_space,0,&mem_iter,elmt_size,(size_t)vector_size,maxbytes,&mem_nseq,&mem_nbytes,mem_off,mem_len)<0) HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed"); /* Start at the beginning of the sequences again */ @@ -1271,7 +1283,7 @@ H5S_select_read(H5F_t *f, const H5O_layout_t *layout, H5P_genplist_t *dc_plist, partial_file=0; /* Read file sequences into current memory sequence */ - if (H5F_seq_readv(f, dxpl_id, layout, dc_plist, file_space, elmt_size, tot_file_seq, &file_len[orig_file_seq], &file_off[orig_file_seq], buf)<0) + if (H5F_seq_readv(f, dxpl_id, layout, dc_plist, efl, file_space, elmt_size, tot_file_seq, &file_len[orig_file_seq], &file_off[orig_file_seq], buf)<0) HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error"); /* Update last file sequence, if it was partially accessed */ @@ -1308,7 +1320,7 @@ H5S_select_read(H5F_t *f, const H5O_layout_t *layout, H5P_genplist_t *dc_plist, tmp_file_len=mem_len[curr_mem_seq]; /* Read part of current file sequence into current memory sequence */ - if (H5F_seq_read(f, dxpl_id, layout, dc_plist, file_space, elmt_size, tmp_file_len, file_off[curr_file_seq], buf)<0) + if (H5F_seq_read(f, dxpl_id, layout, dc_plist, efl, file_space, elmt_size, tmp_file_len, file_off[curr_file_seq], buf)<0) HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error"); /* Update current file sequence information */ @@ -1331,17 +1343,15 @@ H5S_select_read(H5F_t *f, const H5O_layout_t *layout, H5P_genplist_t *dc_plist, done: /* Release file selection iterator */ - if(file_iter!=NULL) { - if ((*file_space->select.iter_release)(file_iter)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); - H5FL_FREE(H5S_sel_iter_t,file_iter); + if(file_iter_init) { + if ((*file_space->select.iter_release)(&file_iter)<0) + HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); } /* end if */ /* Release memory selection iterator */ - if(mem_iter!=NULL) { - if ((*mem_space->select.iter_release)(mem_iter)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); - H5FL_FREE(H5S_sel_iter_t,mem_iter); + if(mem_iter_init) { + if ((*mem_space->select.iter_release)(&mem_iter)<0) + HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); } /* end if */ /* Free vector arrays */ @@ -1373,16 +1383,17 @@ done: */ herr_t H5S_select_write(H5F_t *f, H5O_layout_t *layout, H5P_genplist_t *dc_plist, - size_t elmt_size, const H5S_t *file_space, - const H5S_t *mem_space, hid_t dxpl_id, const void *_buf/*out*/) + const H5O_efl_t *efl, size_t elmt_size, const H5S_t *file_space, + const H5S_t *mem_space, hid_t dxpl_id, const void *_buf/*out*/) { - H5P_genplist_t *dx_plist; /* Dataset transfer property list */ - H5S_sel_iter_t *mem_iter=NULL; /* Memory selection iteration info */ - H5S_sel_iter_t *file_iter=NULL; /* File selection iteration info */ + H5S_sel_iter_t mem_iter; /* Memory selection iteration info */ + hbool_t mem_iter_init=0; /* Memory selection iteration info has been initialized */ + H5S_sel_iter_t file_iter; /* File selection iteration info */ + hbool_t file_iter_init=0; /* File selection iteration info has been initialized */ const uint8_t *buf=NULL; /* Local buffer pointer, for address arithmetic */ hsize_t *mem_off=NULL; /* Array to store sequence offsets in memory */ hsize_t *file_off=NULL; /* Array to store sequence offsets in the file */ - size_t vector_size; /* Value for vector size */ + ssize_t vector_size; /* Value for vector size */ size_t *mem_len=NULL; /* Array to store sequence lengths in memory */ size_t *file_len=NULL; /* Array to store sequence lengths in the file */ size_t maxbytes; /* Number of bytes in selection */ @@ -1403,40 +1414,33 @@ H5S_select_write(H5F_t *f, H5O_layout_t *layout, H5P_genplist_t *dc_plist, /* Check args */ assert(f); + assert(efl); assert(_buf); assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); /* Get the hyperslab vector size */ - if(NULL == (dx_plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list"); - if (H5P_get(dx_plist,H5D_XFER_HYPER_VECTOR_SIZE_NAME,&vector_size)<0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get value"); + if((vector_size=H5S_get_vector_size(dxpl_id))<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get I/O vector size"); /* Allocate the vector I/O arrays */ - if((mem_len = H5FL_ARR_ALLOC(size_t,vector_size,0))==NULL) + if((mem_len = H5FL_ARR_MALLOC(size_t,(size_t)vector_size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array"); - if((mem_off = H5FL_ARR_ALLOC(hsize_t,vector_size,0))==NULL) + if((mem_off = H5FL_ARR_MALLOC(hsize_t,(size_t)vector_size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array"); - if((file_len = H5FL_ARR_ALLOC(size_t,vector_size,0))==NULL) + if((file_len = H5FL_ARR_MALLOC(size_t,(size_t)vector_size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array"); - if((file_off = H5FL_ARR_ALLOC(hsize_t,vector_size,0))==NULL) + if((file_off = H5FL_ARR_MALLOC(hsize_t,(size_t)vector_size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array"); - /* Allocate file iterator */ - if((file_iter = H5FL_ALLOC(H5S_sel_iter_t,1))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate selection iterator"); - /* Initialize file iterator */ - if ((*file_space->select.iter_init)(file_space, elmt_size, file_iter)<0) + if ((*file_space->select.iter_init)(file_space, elmt_size, &file_iter)<0) HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator"); - - /* Allocate memory iterator */ - if((mem_iter = H5FL_ALLOC(H5S_sel_iter_t,1))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate selection iterator"); + file_iter_init=1; /* File selection iteration info has been initialized */ /* Initialize memory iterator */ - if ((*mem_space->select.iter_init)(mem_space, elmt_size, mem_iter)<0) + if ((*mem_space->select.iter_init)(mem_space, elmt_size, &mem_iter)<0) HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator"); + mem_iter_init=1; /* Memory selection iteration info has been initialized */ /* Get number of bytes in selection */ maxbytes=(*file_space->select.get_npoints)(file_space)*elmt_size; @@ -1450,7 +1454,7 @@ H5S_select_write(H5F_t *f, H5O_layout_t *layout, H5P_genplist_t *dc_plist, /* Check if more file sequences are needed */ if(curr_file_seq>=file_nseq) { /* Get sequences for file selection */ - if((*file_space->select.get_seq_list)(file_space,H5S_GET_SEQ_LIST_SORTED,file_iter,elmt_size,vector_size,maxbytes,&file_nseq,&file_nbytes,file_off,file_len)<0) + if((*file_space->select.get_seq_list)(file_space,H5S_GET_SEQ_LIST_SORTED,&file_iter,elmt_size,(size_t)vector_size,maxbytes,&file_nseq,&file_nbytes,file_off,file_len)<0) HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed"); /* Start at the beginning of the sequences again */ @@ -1460,7 +1464,7 @@ H5S_select_write(H5F_t *f, H5O_layout_t *layout, H5P_genplist_t *dc_plist, /* Check if more memory sequences are needed */ if(curr_mem_seq>=mem_nseq) { /* Get sequences for memory selection */ - if((*mem_space->select.get_seq_list)(mem_space,0,mem_iter,elmt_size,vector_size,maxbytes,&mem_nseq,&mem_nbytes,mem_off,mem_len)<0) + if((*mem_space->select.get_seq_list)(mem_space,0,&mem_iter,elmt_size,(size_t)vector_size,maxbytes,&mem_nseq,&mem_nbytes,mem_off,mem_len)<0) HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed"); /* Start at the beginning of the sequences again */ @@ -1506,7 +1510,7 @@ H5S_select_write(H5F_t *f, H5O_layout_t *layout, H5P_genplist_t *dc_plist, partial_file=0; /* Write current memory sequence into file sequences */ - if (H5F_seq_writev(f, dxpl_id, layout, dc_plist, file_space, elmt_size, tot_file_seq, &file_len[orig_file_seq], &file_off[orig_file_seq], buf)<0) + if (H5F_seq_writev(f, dxpl_id, layout, dc_plist, efl, file_space, elmt_size, tot_file_seq, &file_len[orig_file_seq], &file_off[orig_file_seq], buf)<0) HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error"); /* Update last file sequence, if it was partially accessed */ @@ -1543,7 +1547,7 @@ H5S_select_write(H5F_t *f, H5O_layout_t *layout, H5P_genplist_t *dc_plist, tmp_file_len=mem_len[curr_mem_seq]; /* Write part of current memory sequence to current file sequence */ - if (H5F_seq_write(f, dxpl_id, layout, dc_plist, file_space, elmt_size, tmp_file_len, file_off[curr_file_seq], buf)<0) + if (H5F_seq_write(f, dxpl_id, layout, dc_plist, efl, file_space, elmt_size, tmp_file_len, file_off[curr_file_seq], buf)<0) HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error"); /* Update current file sequence information */ @@ -1566,17 +1570,15 @@ H5S_select_write(H5F_t *f, H5O_layout_t *layout, H5P_genplist_t *dc_plist, done: /* Release file selection iterator */ - if(file_iter!=NULL) { - if ((*file_space->select.iter_release)(file_iter)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); - H5FL_FREE(H5S_sel_iter_t,file_iter); + if(file_iter_init) { + if ((*file_space->select.iter_release)(&file_iter)<0) + HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); } /* end if */ /* Release memory selection iterator */ - if(mem_iter!=NULL) { - if ((*mem_space->select.iter_release)(mem_iter)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); - H5FL_FREE(H5S_sel_iter_t,mem_iter); + if(mem_iter_init) { + if ((*mem_space->select.iter_release)(&mem_iter)<0) + HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); } /* end if */ /* Free vector arrays */ diff --git a/src/H5T.c b/src/H5T.c index 51b14d5..64cc2e3 100644 --- a/src/H5T.c +++ b/src/H5T.c @@ -1522,7 +1522,7 @@ H5T_init_interface(void) /* Opaque data */ if(H5T_NATIVE_OPAQUE_g<0) { - if (NULL==(dt = H5FL_ALLOC(H5T_t,1))) + if (NULL==(dt = H5FL_CALLOC(H5T_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); /* Set information */ @@ -1544,7 +1544,7 @@ H5T_init_interface(void) /* One-byte character string */ if(H5T_C_S1_g<0) { - if (NULL==(dt = H5FL_ALLOC(H5T_t,1))) + if (NULL==(dt = H5FL_CALLOC(H5T_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); dt->state = H5T_STATE_IMMUTABLE; @@ -1570,7 +1570,7 @@ H5T_init_interface(void) /* One-byte character string */ if(H5T_FORTRAN_S1_g<0) { - if (NULL==(dt = H5FL_ALLOC(H5T_t,1))) + if (NULL==(dt = H5FL_CALLOC(H5T_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); dt->state = H5T_STATE_IMMUTABLE; @@ -1596,7 +1596,7 @@ H5T_init_interface(void) /* Object pointer (i.e. object header address in file) */ if(H5T_STD_REF_OBJ_g<0) { - if (NULL==(dt = H5FL_ALLOC(H5T_t,1))) + if (NULL==(dt = H5FL_CALLOC(H5T_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); dt->state = H5T_STATE_IMMUTABLE; @@ -1616,7 +1616,7 @@ H5T_init_interface(void) /* Dataset Region pointer (i.e. selection inside a dataset) */ if(H5T_STD_REF_DSETREG_g<0) { - if (NULL==(dt = H5FL_ALLOC(H5T_t,1))) + if (NULL==(dt = H5FL_CALLOC(H5T_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); dt->state = H5T_STATE_IMMUTABLE; @@ -1897,7 +1897,7 @@ H5T_term_interface(void) H5T_print_stats(path, &nprint/*in,out*/); path->cdata.command = H5T_CONV_FREE; if ((path->func)(FAIL, FAIL, &(path->cdata), - (hsize_t)0, 0, 0, NULL, NULL,H5P_DEFAULT)<0) { + (hsize_t)0, 0, 0, NULL, NULL,H5P_DATASET_XFER_DEFAULT)<0) { #ifdef H5T_DEBUG if (H5DEBUG(T)) { fprintf (H5DEBUG(T), "H5T: conversion function " @@ -2688,7 +2688,7 @@ hid_t H5Tget_native_type(hid_t type_id, H5T_direction_t direction) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); if(direction!=H5T_DIR_DEFAULT && direction!=H5T_DIR_ASCEND - && direction!=H5T_DIR_DESCEND) + && direction!=H5T_DIR_DESCEND) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not valid direction value"); if((new_dt = H5T_get_native_type(dt, direction, NULL, NULL, &comp_size))==NULL) @@ -2732,7 +2732,7 @@ H5T_t* H5T_get_native_type(H5T_t *dtype, H5T_direction_t direction, size_t *stru int nmemb; /* Number of members in compound & enum types */ H5T_t *super_type; /* Super type of VL, array and enum datatypes */ H5T_t *nat_super_type; /* Native form of VL, array & enum super datatype */ - H5T_t *new_type; /* New native datatype */ + H5T_t *new_type=NULL; /* New native datatype */ int i; /* Local index variable */ H5T_t *ret_value; /* Return value */ @@ -2771,7 +2771,7 @@ H5T_t* H5T_get_native_type(H5T_t *dtype, H5T_direction_t direction, size_t *stru size_t pointer_size; if(H5T_is_variable_str(dtype)) { - if(NULL==(dt=H5I_object_verify(H5T_C_S1, H5I_DATATYPE))) + if(NULL==(dt=H5I_object(H5T_C_S1))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type"); if((ret_value=H5T_copy(dt, H5T_COPY_TRANSIENT))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve float type"); @@ -2788,7 +2788,7 @@ H5T_t* H5T_get_native_type(H5T_t *dtype, H5T_direction_t direction, size_t *stru } else { /*size_t char_size;*/ - if(NULL==(dt=H5I_object_verify(H5T_NATIVE_UCHAR, H5I_DATATYPE))) + if(NULL==(dt=H5I_object(H5T_NATIVE_UCHAR))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type"); if((ret_value=H5T_copy(dt, H5T_COPY_TRANSIENT))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve float type"); @@ -2801,8 +2801,6 @@ H5T_t* H5T_get_native_type(H5T_t *dtype, H5T_direction_t direction, size_t *stru if(H5T_cmp_offset(comp_size, offset, sizeof(char), size, align, struct_align)<0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot compute compound offset"); - if(H5T_close(dt)<0) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "can't close data type"); } } break; @@ -2821,13 +2819,12 @@ H5T_t* H5T_get_native_type(H5T_t *dtype, H5T_direction_t direction, size_t *stru size_t align; size_t ref_size; int not_equal; - H5T_t *dt; if((ret_value=H5T_copy(dtype, H5T_COPY_TRANSIENT))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve float type"); /* Decide if the data type is object or dataset region reference. */ - if(NULL==(dt=H5I_object_verify(H5T_STD_REF_OBJ_g, H5I_DATATYPE))) + if(NULL==(dt=H5I_object(H5T_STD_REF_OBJ_g))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type"); not_equal = H5T_cmp(ret_value, dt); @@ -2975,7 +2972,6 @@ H5T_t* H5T_get_native_type(H5T_t *dtype, H5T_direction_t direction, size_t *stru size_t super_offset=0; size_t super_size=0; size_t super_align=0; - int i; /* Retrieve dimension information for array data type */ if((array_rank=H5T_get_array_ndims(dtype))<=0) @@ -3006,7 +3002,8 @@ H5T_t* H5T_get_native_type(H5T_t *dtype, H5T_direction_t direction, size_t *stru for(i=0; i=0); + if(NULL==(dt=H5I_object(tid))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type"); if((ret_value=H5T_copy(dt, H5T_COPY_TRANSIENT))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve float type"); @@ -3216,8 +3214,8 @@ done: H5T_t* H5T_get_native_float(size_t size, H5T_direction_t direction, size_t *struct_align, size_t *offset, size_t *comp_size) { H5T_t *dt=NULL; /* Appropriate native datatype to copy */ - hid_t tid; /* Datatype ID of appropriate native datatype */ - size_t align; /* Alignment necessary for native datatype */ + hid_t tid=(-1); /* Datatype ID of appropriate native datatype */ + size_t align=0; /* Alignment necessary for native datatype */ enum match_type { /* The different kinds of floating point types we can match */ H5T_NATIVE_FLOAT_MATCH_FLOAT, H5T_NATIVE_FLOAT_MATCH_DOUBLE, @@ -3273,7 +3271,8 @@ H5T_t* H5T_get_native_float(size_t size, H5T_direction_t direction, size_t *stru } /* end switch */ /* Create new native type */ - if(NULL==(dt=H5I_object_verify(tid, H5I_DATATYPE))) + assert(tid>=0); + if(NULL==(dt=H5I_object(tid))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type"); if((ret_value=H5T_copy(dt, H5T_COPY_TRANSIENT))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve float type"); @@ -5201,7 +5200,7 @@ H5T_enum_create(H5T_t *parent) assert(parent); /* Build new type */ - if (NULL==(ret_value = H5FL_ALLOC(H5T_t,1))) + if (NULL==(ret_value = H5FL_CALLOC(H5T_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); ret_value->type = H5T_ENUM; ret_value->parent = H5T_copy(parent, H5T_COPY_ALL); @@ -5546,7 +5545,7 @@ H5T_vlen_create(H5T_t *base) assert(base); /* Build new type */ - if (NULL==(dt = H5FL_ALLOC(H5T_t,1))) + if (NULL==(dt = H5FL_CALLOC(H5T_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); dt->ent.header = HADDR_UNDEF; dt->type = H5T_VLEN; @@ -5797,7 +5796,7 @@ H5T_register(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register data types for conv query"); HDmemset(&cdata, 0, sizeof cdata); cdata.command = H5T_CONV_INIT; - if ((func)(tmp_sid, tmp_did, &cdata, (hsize_t)0, 0, 0, NULL, NULL, H5P_DEFAULT)<0) { + if ((func)(tmp_sid, tmp_did, &cdata, (hsize_t)0, 0, 0, NULL, NULL, H5P_DATASET_XFER_DEFAULT)<0) { H5I_dec_ref(tmp_sid); H5I_dec_ref(tmp_did); tmp_sid = tmp_did = -1; @@ -5806,7 +5805,7 @@ H5T_register(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, } /* end if */ /* Create a new conversion path */ - if (NULL==(new_path=H5FL_ALLOC(H5T_path_t,1))) + if (NULL==(new_path=H5FL_CALLOC(H5T_path_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); HDstrncpy(new_path->name, name, H5T_NAMELEN); new_path->name[H5T_NAMELEN-1] = '\0'; @@ -5824,7 +5823,7 @@ H5T_register(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, /* Free old path */ H5T_print_stats(old_path, &nprint); old_path->cdata.command = H5T_CONV_FREE; - if ((old_path->func)(tmp_sid, tmp_did, &(old_path->cdata), (hsize_t)0, 0, 0, NULL, NULL, H5P_DEFAULT)<0) { + if ((old_path->func)(tmp_sid, tmp_did, &(old_path->cdata), (hsize_t)0, 0, 0, NULL, NULL, H5P_DATASET_XFER_DEFAULT)<0) { #ifdef H5T_DEBUG if (H5DEBUG(T)) { fprintf (H5DEBUG(T), "H5T: conversion function 0x%08lx " @@ -5986,7 +5985,7 @@ H5T_unregister(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, H5T_print_stats(path, &nprint); path->cdata.command = H5T_CONV_FREE; if ((path->func)(FAIL, FAIL, &(path->cdata), (hsize_t)0, 0, 0, NULL, NULL, - H5P_DEFAULT)<0) { + H5P_DATASET_XFER_DEFAULT)<0) { #ifdef H5T_DEBUG if (H5DEBUG(T)) { fprintf(H5DEBUG(T), "H5T: conversion function 0x%08lx failed " @@ -6141,9 +6140,13 @@ H5Tconvert(hid_t src_id, hid_t dst_id, hsize_t nelmts, void *buf, /* Check args */ if (NULL==(src=H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL==(dst=H5I_object_verify(dst_id,H5I_DATATYPE)) || - (H5P_DEFAULT!=plist_id && TRUE != H5P_isa_class(plist_id, H5P_DATASET_XFER))) + NULL==(dst=H5I_object_verify(dst_id,H5I_DATATYPE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + if(H5P_DEFAULT == plist_id) + plist_id = H5P_DATASET_XFER_DEFAULT; + else + if(TRUE != H5P_isa_class(plist_id, H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not dataset transfer property list"); /* Find the conversion function */ if (NULL==(tpath=H5T_path_find(src, dst, NULL, NULL))) @@ -6272,7 +6275,7 @@ H5T_create(H5T_class_t type, size_t size) case H5T_OPAQUE: case H5T_COMPOUND: - if (NULL==(dt = H5FL_ALLOC(H5T_t,1))) + if (NULL==(dt = H5FL_CALLOC(H5T_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); dt->type = type; break; @@ -6291,7 +6294,7 @@ H5T_create(H5T_class_t type, size_t size) } else { HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "no applicable native integer type"); } - if (NULL==(dt = H5FL_ALLOC(H5T_t,1))) + if (NULL==(dt = H5FL_CALLOC(H5T_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); dt->type = type; if (NULL==(dt->parent=H5T_copy(H5I_object(subtype), H5T_COPY_ALL))) @@ -6506,7 +6509,7 @@ H5T_copy(const H5T_t *old_dt, H5T_copy_t method) assert(old_dt); /* Allocate space */ - if (NULL==(new_dt = H5FL_ALLOC(H5T_t,0))) + if (NULL==(new_dt = H5FL_MALLOC(H5T_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); /* Copy actual information */ @@ -6725,7 +6728,7 @@ H5T_commit (H5G_entry_t *loc, const char *name, H5T_t *type) */ if (H5O_create (file, 64, &(type->ent))<0) HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to create data type object header"); - if (H5O_modify (&(type->ent), H5O_DTYPE, 0, H5O_FLAG_CONSTANT, type)<0) + if (H5O_modify (&(type->ent), H5O_DTYPE, 0, H5O_FLAG_CONSTANT, 1, type)<0) HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to update type header message"); if (H5G_insert (loc, name, &(type->ent))<0) HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to name data type"); @@ -6789,36 +6792,27 @@ done: /*------------------------------------------------------------------------- - * Function: H5T_close + * Function: H5T_release * - * Purpose: Frees a data type and all associated memory. If the data - * type is locked then nothing happens. + * Purpose: Frees all memory associated with a datatype, but does not + * free the H5T_t structure (which should be done in H5T_close). * * Return: Non-negative on success/Negative on failure * - * Programmer: Robb Matzke - * Monday, December 8, 1997 + * Programmer: Quincey Koziol + * Monday, January 6, 2003 * * Modifications: - * Robb Matzke, 1999-04-27 - * This function fails if the datatype state is IMMUTABLE. - * - * Robb Matzke, 1999-05-20 - * Closes opaque types also. - * - * Pedro Vicente, 22 Aug 2002 - * Added "ID to name" support * *------------------------------------------------------------------------- */ herr_t -H5T_close(H5T_t *dt) +H5T_free(H5T_t *dt) { int i; - H5T_t *parent = dt->parent; herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5T_close, FAIL); + FUNC_ENTER_NOAPI(H5T_free, FAIL); assert(dt); @@ -6866,15 +6860,58 @@ H5T_close(H5T_t *dt) /* Free the ID to name info */ H5G_free_ent_name(&(dt->ent)); - /* Free the datatype struct */ - H5FL_FREE(H5T_t,dt); - /* Close the parent */ - if (parent && H5T_close(parent)<0) + if (dt->parent && H5T_close(dt->parent)<0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to close parent data type"); done: FUNC_LEAVE(ret_value); +} /* end H5T_free() */ + + +/*------------------------------------------------------------------------- + * Function: H5T_close + * + * Purpose: Frees a data type and all associated memory. If the data + * type is locked then nothing happens. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Monday, December 8, 1997 + * + * Modifications: + * Robb Matzke, 1999-04-27 + * This function fails if the datatype state is IMMUTABLE. + * + * Robb Matzke, 1999-05-20 + * Closes opaque types also. + * + * Pedro Vicente, 22 Aug 2002 + * Added "ID to name" support + * + * Quincey Koziol, 2003-01-06 + * Moved "guts" of function to H5T_free() + * + *------------------------------------------------------------------------- + */ +herr_t +H5T_close(H5T_t *dt) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5T_close, FAIL); + + assert(dt); + + if(H5T_free(dt)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "unable to free datatype"); + + /* Free the datatype struct */ + H5FL_FREE(H5T_t,dt); + +done: + FUNC_LEAVE(ret_value); } @@ -8267,13 +8304,13 @@ H5T_path_find(const H5T_t *src, const H5T_t *dst, const char *name, if (NULL==(H5T_g.path=H5MM_malloc(128*sizeof(H5T_path_t*)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for type conversion path table"); H5T_g.apaths = 128; - if (NULL==(H5T_g.path[0]=H5FL_ALLOC(H5T_path_t,1))) + if (NULL==(H5T_g.path[0]=H5FL_CALLOC(H5T_path_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for no-op conversion path"); HDstrcpy(H5T_g.path[0]->name, "no-op"); H5T_g.path[0]->func = H5T_conv_noop; H5T_g.path[0]->cdata.command = H5T_CONV_INIT; if (H5T_conv_noop(FAIL, FAIL, &(H5T_g.path[0]->cdata), (hsize_t)0, 0, 0, - NULL, NULL, H5P_DEFAULT)<0) { + NULL, NULL, H5P_DATASET_XFER_DEFAULT)<0) { #ifdef H5T_DEBUG if (H5DEBUG(T)) { fprintf(H5DEBUG(T), "H5T: unable to initialize no-op " @@ -8330,7 +8367,7 @@ H5T_path_find(const H5T_t *src, const H5T_t *dst, const char *name, * the path. */ if (!table || func) { - if (NULL==(path=H5FL_ALLOC(H5T_path_t,1))) + if (NULL==(path=H5FL_CALLOC(H5T_path_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for type conversion path"); if (name && *name) { HDstrncpy(path->name, name, H5T_NAMELEN); @@ -8360,7 +8397,7 @@ H5T_path_find(const H5T_t *src, const H5T_t *dst, const char *name, HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register destination conversion type for query"); path->cdata.command = H5T_CONV_INIT; if ((func)(src_id, dst_id, &(path->cdata), (hsize_t)0, 0, 0, NULL, NULL, - H5P_DEFAULT)<0) + H5P_DATASET_XFER_DEFAULT)<0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to initialize conversion function"); if (src_id>=0) H5I_dec_ref(src_id); if (dst_id>=0) H5I_dec_ref(dst_id); @@ -8388,7 +8425,7 @@ H5T_path_find(const H5T_t *src, const H5T_t *dst, const char *name, HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register conversion types for query"); path->cdata.command = H5T_CONV_INIT; if ((H5T_g.soft[i].func) (src_id, dst_id, &(path->cdata), - (hsize_t)0, 0, 0, NULL, NULL, H5P_DEFAULT)<0) { + (hsize_t)0, 0, 0, NULL, NULL, H5P_DATASET_XFER_DEFAULT)<0) { HDmemset (&(path->cdata), 0, sizeof(H5T_cdata_t)); H5E_clear(); /*ignore the error*/ } else { @@ -8432,7 +8469,7 @@ H5T_path_find(const H5T_t *src, const H5T_t *dst, const char *name, H5T_print_stats(table, &nprint/*in,out*/); table->cdata.command = H5T_CONV_FREE; if ((table->func)(FAIL, FAIL, &(table->cdata), (hsize_t)0, 0, 0, NULL, NULL, - H5P_DEFAULT)<0) { + H5P_DATASET_XFER_DEFAULT)<0) { #ifdef H5T_DEBUG if (H5DEBUG(T)) { fprintf(H5DEBUG(T), "H5T: conversion function 0x%08lx free " @@ -8794,7 +8831,7 @@ H5T_array_create(H5T_t *base, int ndims, const hsize_t dim[/* ndims */], assert(dim); /* Build new type */ - if (NULL==(ret_value = H5FL_ALLOC(H5T_t,1))) + if (NULL==(ret_value = H5FL_CALLOC(H5T_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); ret_value->ent.header = HADDR_UNDEF; diff --git a/src/H5TB.c b/src/H5TB.c index 391101f..5f04732 100644 --- a/src/H5TB.c +++ b/src/H5TB.c @@ -90,7 +90,7 @@ /* Local Function Prototypes */ static H5TB_NODE * H5TB_end(H5TB_NODE * root, int side); -static H5TB_NODE *H5TB_ffind(H5TB_NODE * root, void * key, unsigned fast_compare, +static H5TB_NODE *H5TB_ffind(H5TB_NODE * root, const void * key, unsigned fast_compare, H5TB_NODE ** pp); static herr_t H5TB_balance(H5TB_NODE ** root, H5TB_NODE * ptr, int side, int added); static H5TB_NODE *H5TB_swapkid(H5TB_NODE ** root, H5TB_NODE * ptr, int side); @@ -105,12 +105,148 @@ static herr_t H5TB_dumpNode(H5TB_NODE *node, void (*key_dump)(void *,void *), /* Declare a free list to manage the H5TB_NODE struct */ H5FL_DEFINE_STATIC(H5TB_NODE); +/* Declare a free list to manage the H5TB_TREE struct */ +H5FL_DEFINE_STATIC(H5TB_TREE); + #define PABLO_MASK H5TB_mask static int interface_initialize_g = 0; #define INTERFACE_INIT NULL /*------------------------------------------------------------------------- + * Function: H5TB_strcmp + * + * Purpose: Key comparison routine for TBBT routines + * + * Return: same as strcmp() + * + * Programmer: Quincey Koziol + * Wednesday, December 4, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +H5TB_strcmp(const void *k1, const void *k2, int UNUSED cmparg) +{ + FUNC_ENTER_NOINIT(H5TB_strcmp); + + assert(k1); + assert(k2); + + FUNC_LEAVE(HDstrcmp(k1,k2)); +} /* end H5TB_strcmp() */ + + +/*------------------------------------------------------------------------- + * Function: H5TB_addr_cmp + * + * Purpose: Key comparison routine for TBBT routines + * + * Return: same as H5F_addr_cmp() + * + * Programmer: Quincey Koziol + * Friday, December 20, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +H5TB_addr_cmp(const void *k1, const void *k2, int UNUSED cmparg) +{ + FUNC_ENTER_NOINIT(H5TB_addr_cmp); + + assert(k1); + assert(k2); + + FUNC_LEAVE(H5F_addr_cmp(*(const haddr_t *)k1,*(const haddr_t *)k2)); +} /* end H5TB_addr_cmp() */ + + +/*------------------------------------------------------------------------- + * Function: H5TB_int_cmp + * + * Purpose: Key comparison routine for TBBT routines + * + * Return: same as comparing two integers + * + * Programmer: Quincey Koziol + * Friday, December 20, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +H5TB_int_cmp(const void *k1, const void *k2, int UNUSED cmparg) +{ + FUNC_ENTER_NOINIT(H5TB_int_cmp); + + assert(k1); + assert(k2); + + FUNC_LEAVE(*(const int *)k1 - *(const int *)k2); +} /* end H5TB_int_cmp() */ + + +/*------------------------------------------------------------------------- + * Function: H5TB_fast_dmake + * + * Purpose: Wrapper around H5TB_dmake for callers which want to use + * a "fast comparison" key. + * + * Return: Success: Pointer to a valid H5TB tree + * Failure: NULL + * + * Programmer: Quincey Koziol + * Friday, December 20, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +H5TB_TREE * +H5TB_fast_dmake(unsigned fast_compare) +{ + H5TB_cmp_t compar; /* Key comparison function */ + int cmparg; /* Key comparison value */ + H5TB_TREE *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5TB_fast_dmake, NULL); + + /* Get the corret fast comparison routine */ + switch(fast_compare) { + case H5TB_FAST_HADDR_COMPARE: + compar=H5TB_addr_cmp; + cmparg=-1; + break; + + case H5TB_FAST_INTN_COMPARE: + compar=H5TB_int_cmp; + cmparg=-1; + break; + + case H5TB_FAST_STR_COMPARE: + compar=H5TB_strcmp; + cmparg=-1; + break; + + default: + HGOTO_ERROR (H5E_TBBT, H5E_BADVALUE, NULL, "invalid fast comparison type"); + } /* end switch */ + + /* Set return value */ + if((ret_value=H5TB_dmake(compar,cmparg,fast_compare))==NULL) + HGOTO_ERROR (H5E_TBBT, H5E_CANTCREATE, NULL, "can't create TBBT"); + +done: + FUNC_LEAVE (ret_value); +} /* end H5TB_fast_dmake() */ + + +/*------------------------------------------------------------------------- * Function: H5TB_dmake * * Purpose: Allocates and initializes an empty threaded, balanced, binary tree @@ -192,7 +328,7 @@ H5TB_dmake(H5TB_cmp_t cmp, int arg, unsigned fast_compare) FUNC_ENTER_NOAPI(H5TB_dmake, NULL); - if (NULL == (tree = H5MM_malloc(sizeof(H5TB_TREE)))) + if (NULL == (tree = H5FL_MALLOC(H5TB_TREE))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); tree->root = NULL; @@ -234,7 +370,7 @@ done: *------------------------------------------------------------------------- */ H5TB_NODE * -H5TB_dfind(H5TB_TREE * tree, void * key, H5TB_NODE ** pp) +H5TB_dfind(H5TB_TREE * tree, const void * key, H5TB_NODE ** pp) { H5TB_NODE *ret_value; @@ -242,10 +378,16 @@ H5TB_dfind(H5TB_TREE * tree, void * key, H5TB_NODE ** pp) assert(tree); - if(tree->fast_compare!=0) - ret_value=H5TB_ffind(tree->root, key, tree->fast_compare, pp); - else - ret_value=H5TB_find(tree->root, key, tree->compar, tree->cmparg, pp); + if(tree->root) + if(tree->fast_compare!=0) + ret_value=H5TB_ffind(tree->root, key, tree->fast_compare, pp); + else + ret_value=H5TB_find(tree->root, key, tree->compar, tree->cmparg, pp); + else { + if (NULL != pp) + *pp = NULL; + ret_value=NULL; + } /* end else */ done: FUNC_LEAVE (ret_value); @@ -280,7 +422,7 @@ done: *------------------------------------------------------------------------- */ H5TB_NODE * -H5TB_find(H5TB_NODE * root, void * key, +H5TB_find(H5TB_NODE * root, const void * key, H5TB_cmp_t compar, int arg, H5TB_NODE ** pp) { H5TB_NODE *ptr = root; @@ -461,7 +603,7 @@ H5TB_index(H5TB_NODE * root, unsigned indx) if (NULL != ptr) { /* Termination condition is if the index equals the number of children on out left plus the current node */ - while (ptr != NULL && indx != ((unsigned) LeftCnt(ptr)) + 1 ) { + while (ptr != NULL && indx != ((unsigned) LeftCnt(ptr)) ) { if (indx <= (unsigned) LeftCnt(ptr)) { ptr = ptr->Lchild; } /* end if */ @@ -564,7 +706,7 @@ H5TB_ins(H5TB_NODE ** root, void * item, void * key, H5TB_cmp_t compar, int arg) if (NULL != H5TB_find(*root, (key ? key : item), compar, arg, &parent)) HGOTO_ERROR (H5E_TBBT, H5E_EXISTS, NULL, "node already in tree"); - if (NULL == (ptr = H5FL_ALLOC(H5TB_NODE,0))) + if (NULL == (ptr = H5FL_MALLOC(H5TB_NODE))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); ptr->data = item; ptr->key = key ? key : item; @@ -760,12 +902,13 @@ H5TB_rem(H5TB_NODE ** root, H5TB_NODE * node, void * *kp) H5FL_FREE(H5TB_NODE,leaf); H5TB_balance(root, par, side, -1); - ((H5TB_TREE *) root)->count--; - /* Set return value */ ret_value=data; done: + if(ret_value) + ((H5TB_TREE *) root)->count--; + FUNC_LEAVE(ret_value); } /* end H5TB_rem() */ @@ -945,7 +1088,7 @@ H5TB_dfree(H5TB_TREE * tree, void(*fd) (void * /* item */), void(*fk) (void * /* H5TB_free(&tree->root, fd, fk); /* Free the tree root */ - H5MM_xfree(tree); + H5FL_FREE(H5TB_TREE,tree); } /* end if */ done: @@ -1254,7 +1397,7 @@ done: /* This routine is based on tbbtfind (fix bugs in both places!) */ /* Returns a pointer to the found node (or NULL) */ static H5TB_NODE * -H5TB_ffind(H5TB_NODE * root, void * key, unsigned fast_compare, H5TB_NODE ** pp) +H5TB_ffind(H5TB_NODE * root, const void * key, unsigned fast_compare, H5TB_NODE ** pp) { H5TB_NODE *ptr = root; H5TB_NODE *parent = NULL; @@ -1267,7 +1410,7 @@ H5TB_ffind(H5TB_NODE * root, void * key, unsigned fast_compare, H5TB_NODE ** pp) switch(fast_compare) { case H5TB_FAST_HADDR_COMPARE: if (ptr) { - while (0 != (cmp = H5F_addr_cmp(*(haddr_t *)key,*(haddr_t *)ptr->key))) { + while (0 != (cmp = H5F_addr_cmp(*(const haddr_t *)key,*(haddr_t *)ptr->key))) { parent = ptr; side = (cmp < 0) ? LEFT : RIGHT; if (!HasChild(ptr, side)) @@ -1284,7 +1427,24 @@ H5TB_ffind(H5TB_NODE * root, void * key, unsigned fast_compare, H5TB_NODE ** pp) case H5TB_FAST_INTN_COMPARE: if (ptr) { - while (0 != (cmp = (*(int *)key - *(int *)ptr->key))) { + while (0 != (cmp = (*(const int *)key - *(int *)ptr->key))) { + parent = ptr; + side = (cmp < 0) ? LEFT : RIGHT; + if (!HasChild(ptr, side)) + break; + ptr = ptr->link[side]; + } /* end while */ + } /* end if */ + if (NULL != pp) + *pp = parent; + + /* Set return value */ + ret_value= (0 == cmp) ? ptr : NULL; + break; + + case H5TB_FAST_STR_COMPARE: + if (ptr) { + while (0 != (cmp = HDstrcmp(key,ptr->key))) { parent = ptr; side = (cmp < 0) ? LEFT : RIGHT; if (!HasChild(ptr, side)) diff --git a/src/H5TBprivate.h b/src/H5TBprivate.h index f1d6bef..9c2ccc5 100644 --- a/src/H5TBprivate.h +++ b/src/H5TBprivate.h @@ -23,7 +23,7 @@ #endif /* LATER */ /* Typedef for key comparison function */ -typedef int (*H5TB_cmp_t)(void *k1, void *k2, int cmparg); +typedef int (*H5TB_cmp_t)(const void *k1, const void *k2, int cmparg); /* Shortcut macros for links */ # define PARENT 0 @@ -89,6 +89,10 @@ typedef struct H5TB_tree /* Define the "fast compare" values */ #define H5TB_FAST_HADDR_COMPARE 1 #define H5TB_FAST_INTN_COMPARE 2 +#define H5TB_FAST_STR_COMPARE 3 + +/* Define an access macro for getting a node's data */ +#define H5TB_NODE_DATA(n) ((n)->data) #if defined c_plusplus || defined __cplusplus extern "C" @@ -96,8 +100,9 @@ extern "C" #endif /* c_plusplus || __cplusplus */ H5_DLL H5TB_TREE *H5TB_dmake (H5TB_cmp_t cmp, int arg, unsigned fast_compare); -H5_DLL H5TB_NODE *H5TB_dfind (H5TB_TREE * tree, void * key, H5TB_NODE ** pp); -H5_DLL H5TB_NODE *H5TB_find(H5TB_NODE * root, void * key, H5TB_cmp_t cmp, +H5_DLL H5TB_TREE *H5TB_fast_dmake (unsigned fast_compare); +H5_DLL H5TB_NODE *H5TB_dfind (H5TB_TREE * tree, const void * key, H5TB_NODE ** pp); +H5_DLL H5TB_NODE *H5TB_find(H5TB_NODE * root, const void * key, H5TB_cmp_t cmp, int arg, H5TB_NODE ** pp); H5_DLL H5TB_NODE *H5TB_dless (H5TB_TREE * tree, void * key, H5TB_NODE ** pp); H5_DLL H5TB_NODE *H5TB_less (H5TB_NODE * root, void * key, H5TB_cmp_t cmp, diff --git a/src/H5Tconv.c b/src/H5Tconv.c index 0444d2c..7f389ec 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -283,8 +283,8 @@ H5FL_BLK_DEFINE_STATIC(array_seq); case H5T_CONV_INIT: \ /* Sanity check and initialize statistics */ \ cdata->need_bkg = H5T_BKG_NO; \ - if (NULL==(st=H5I_object_verify(src_id,H5I_DATATYPE)) || \ - NULL==(dt=H5I_object_verify(dst_id,H5I_DATATYPE))) { \ + if (NULL==(st=H5I_object(src_id)) || \ + NULL==(dt=H5I_object(dst_id))) { \ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, \ "unable to dereference data type object ID"); \ } \ @@ -292,13 +292,13 @@ H5FL_BLK_DEFINE_STATIC(array_seq); HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, \ "disagreement about data type size"); \ } \ - CI_ALLOC_PRIV \ + CI_ALLOC_PRIV \ break; \ \ case H5T_CONV_FREE: \ /* Print and free statistics */ \ CI_PRINT_STATS(STYPE,DTYPE); \ - CI_FREE_PRIV \ + CI_FREE_PRIV \ break; \ \ case H5T_CONV_CONV: \ @@ -488,8 +488,8 @@ H5T_conv_order_opt(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, switch (cdata->command) { case H5T_CONV_INIT: /* Capability query */ - if (NULL == (src = H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL == (dst = H5I_object_verify(dst_id,H5I_DATATYPE))) + if (NULL == (src = H5I_object(src_id)) || + NULL == (dst = H5I_object(dst_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); if (src->size != dst->size || 0 != src->u.atomic.offset || @@ -528,8 +528,8 @@ H5T_conv_order_opt(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, case H5T_CONV_CONV: /* The conversion */ - if (NULL == (src = H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL == (dst = H5I_object_verify(dst_id,H5I_DATATYPE))) + if (NULL == (src = H5I_object(src_id)) || + NULL == (dst = H5I_object(dst_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); buf_stride = buf_stride ? buf_stride : src->size; @@ -872,8 +872,8 @@ H5T_conv_order(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, switch (cdata->command) { case H5T_CONV_INIT: /* Capability query */ - if (NULL == (src = H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL == (dst = H5I_object_verify(dst_id,H5I_DATATYPE))) + if (NULL == (src = H5I_object(src_id)) || + NULL == (dst = H5I_object(dst_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); if (src->size != dst->size || 0 != src->u.atomic.offset || 0 != dst->u.atomic.offset || @@ -909,8 +909,8 @@ H5T_conv_order(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, case H5T_CONV_CONV: /* The conversion */ - if (NULL == (src = H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL == (dst = H5I_object_verify(dst_id,H5I_DATATYPE))) + if (NULL == (src = H5I_object(src_id)) || + NULL == (dst = H5I_object(dst_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); buf_stride = buf_stride ? buf_stride : src->size; @@ -974,8 +974,8 @@ H5T_conv_b_b(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, switch(cdata->command) { case H5T_CONV_INIT: /* Capability query */ - if (NULL == (src = H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL == (dst = H5I_object_verify(dst_id,H5I_DATATYPE))) + if (NULL == (src = H5I_object(src_id)) || + NULL == (dst = H5I_object(dst_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); if (H5T_ORDER_LE!=src->u.atomic.order && H5T_ORDER_BE!=src->u.atomic.order) @@ -991,8 +991,8 @@ H5T_conv_b_b(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, case H5T_CONV_CONV: /* Get the data types */ - if (NULL==(src=H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL==(dst=H5I_object_verify(dst_id,H5I_DATATYPE))) + if (NULL==(src=H5I_object(src_id)) || + NULL==(dst=H5I_object(dst_id))) HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); /* @@ -1339,8 +1339,8 @@ H5T_conv_struct(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, * otherwise initialize the `priv' field of `cdata' with information * that remains (almost) constant for this conversion path. */ - if (NULL == (src = H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL == (dst = H5I_object_verify(dst_id,H5I_DATATYPE))) + if (NULL == (src = H5I_object(src_id)) || + NULL == (dst = H5I_object(dst_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); assert (H5T_COMPOUND==src->type); assert (H5T_COMPOUND==dst->type); @@ -1364,8 +1364,8 @@ H5T_conv_struct(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, /* * Conversion. */ - if (NULL == (src = H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL == (dst = H5I_object_verify(dst_id,H5I_DATATYPE))) + if (NULL == (src = H5I_object(src_id)) || + NULL == (dst = H5I_object(dst_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); assert (priv); assert (bkg && cdata->need_bkg); @@ -1571,8 +1571,8 @@ H5T_conv_struct_opt(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, * otherwise initialize the `priv' field of `cdata' with information * that remains (almost) constant for this conversion path. */ - if (NULL == (src = H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL == (dst = H5I_object_verify(dst_id,H5I_DATATYPE))) + if (NULL == (src = H5I_object(src_id)) || + NULL == (dst = H5I_object(dst_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); assert (H5T_COMPOUND==src->type); assert (H5T_COMPOUND==dst->type); @@ -1638,8 +1638,8 @@ H5T_conv_struct_opt(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, /* * Conversion. */ - if (NULL == (src = H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL == (dst = H5I_object_verify(dst_id,H5I_DATATYPE))) + if (NULL == (src = H5I_object(src_id)) || + NULL == (dst = H5I_object(dst_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); /* Update cached data if necessary */ @@ -1934,8 +1934,8 @@ H5T_conv_enum(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, * the `priv' field of `cdata' with information about the underlying * integer conversion. */ - if (NULL == (src = H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL == (dst = H5I_object_verify(dst_id,H5I_DATATYPE))) + if (NULL == (src = H5I_object(src_id)) || + NULL == (dst = H5I_object(dst_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); assert (H5T_ENUM==src->type); assert (H5T_ENUM==dst->type); @@ -1959,8 +1959,8 @@ H5T_conv_enum(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, break; case H5T_CONV_CONV: - if (NULL == (src = H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL == (dst = H5I_object_verify(dst_id,H5I_DATATYPE))) + if (NULL == (src = H5I_object(src_id)) || + NULL == (dst = H5I_object(dst_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); assert (H5T_ENUM==src->type); assert (H5T_ENUM==dst->type); @@ -2132,8 +2132,8 @@ H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, * information that remains (almost) constant for this * conversion path. */ - if (NULL == (src = H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL == (dst = H5I_object_verify(dst_id,H5I_DATATYPE))) + if (NULL == (src = H5I_object(src_id)) || + NULL == (dst = H5I_object(dst_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); assert (H5T_VLEN==src->type); assert (H5T_VLEN==dst->type); @@ -2151,8 +2151,8 @@ H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, /* * Conversion. */ - if (NULL == (src = H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL == (dst = H5I_object_verify(dst_id,H5I_DATATYPE))) + if (NULL == (src = H5I_object(src_id)) || + NULL == (dst = H5I_object(dst_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); /* @@ -2209,7 +2209,7 @@ H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, /* Get initial conversion buffer */ conv_buf_size=MAX(src_base_size,dst_base_size); - if ((conv_buf=H5FL_BLK_ALLOC(vlen_seq,conv_buf_size,1))==NULL) + if ((conv_buf=H5FL_BLK_CALLOC(vlen_seq,conv_buf_size))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion"); /* Set up conversion path for base elements */ @@ -2225,7 +2225,7 @@ H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, if(tpath->cdata.need_bkg||H5T_detect_class(dst->parent,H5T_VLEN)) { /* Set up initial background buffer */ tmp_buf_size=MAX(src_base_size,dst_base_size); - if ((tmp_buf=H5FL_BLK_ALLOC(vlen_seq,tmp_buf_size,1))==NULL) + if ((tmp_buf=H5FL_BLK_CALLOC(vlen_seq,tmp_buf_size))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion"); } /* end if */ @@ -2340,13 +2340,6 @@ H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, } /* end if */ } - /* Release the conversion buffer (always allocated) */ - H5FL_BLK_FREE(vlen_seq,conv_buf); - - /* Release the background buffer, if we have one */ - if(tmp_buf!=NULL) - H5FL_BLK_FREE(vlen_seq,tmp_buf); - /* Release the temporary datatype IDs used */ if (tsrc_id >= 0) H5I_dec_ref(tsrc_id); @@ -2359,6 +2352,13 @@ H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, } /* end switch */ done: + /* Release the conversion buffer (always allocated, except on errors) */ + if(conv_buf!=NULL) + H5FL_BLK_FREE(vlen_seq,conv_buf); + /* Release the background buffer, if we have one */ + if(tmp_buf!=NULL) + H5FL_BLK_FREE(vlen_seq,tmp_buf); + FUNC_LEAVE (ret_value); } @@ -2407,8 +2407,8 @@ H5T_conv_array(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, * information that remains (almost) constant for this * conversion path. */ - if (NULL == (src = H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL == (dst = H5I_object_verify(dst_id,H5I_DATATYPE))) + if (NULL == (src = H5I_object(src_id)) || + NULL == (dst = H5I_object(dst_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); assert (H5T_ARRAY==src->type); assert (H5T_ARRAY==dst->type); @@ -2438,8 +2438,8 @@ H5T_conv_array(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, /* * Conversion. */ - if (NULL == (src = H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL == (dst = H5I_object_verify(dst_id,H5I_DATATYPE))) + if (NULL == (src = H5I_object(src_id)) || + NULL == (dst = H5I_object(dst_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); /* @@ -2477,7 +2477,7 @@ H5T_conv_array(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, if(tpath->cdata.need_bkg) { /* Allocate background buffer */ bkg_buf_size=src->u.array.nelem*MAX(src->size,dst->size); - if ((bkg_buf=H5FL_BLK_ALLOC(array_seq,bkg_buf_size,0))==NULL) + if ((bkg_buf=H5FL_BLK_MALLOC(array_seq,bkg_buf_size))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion"); } /* end if */ @@ -2560,8 +2560,8 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, switch (cdata->command) { case H5T_CONV_INIT: - if (NULL==(src=H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL==(dst=H5I_object_verify(dst_id,H5I_DATATYPE))) + if (NULL==(src=H5I_object(src_id)) || + NULL==(dst=H5I_object(dst_id))) HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); if (H5T_ORDER_LE!=src->u.atomic.order && H5T_ORDER_BE!=src->u.atomic.order) @@ -2579,8 +2579,8 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, case H5T_CONV_CONV: /* Get the data types */ - if (NULL==(src=H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL==(dst=H5I_object_verify(dst_id,H5I_DATATYPE))) + if (NULL==(src=H5I_object(src_id)) || + NULL==(dst=H5I_object(dst_id))) HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); /* @@ -2899,8 +2899,8 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, switch (cdata->command) { case H5T_CONV_INIT: - if (NULL==(src_p=H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL==(dst_p=H5I_object_verify(dst_id,H5I_DATATYPE))) + if (NULL==(src_p=H5I_object(src_id)) || + NULL==(dst_p=H5I_object(dst_id))) HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); src = src_p->u.atomic; dst = dst_p->u.atomic; @@ -2920,8 +2920,8 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, case H5T_CONV_CONV: /* Get the data types */ - if (NULL==(src_p=H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL==(dst_p=H5I_object_verify(dst_id,H5I_DATATYPE))) + if (NULL==(src_p=H5I_object(src_id)) || + NULL==(dst_p=H5I_object(dst_id))) HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); src = src_p->u.atomic; dst = dst_p->u.atomic; @@ -3308,8 +3308,8 @@ H5T_conv_s_s (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, switch (cdata->command) { case H5T_CONV_INIT: - if (NULL==(src=H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL==(dst=H5I_object_verify(dst_id,H5I_DATATYPE))) + if (NULL==(src=H5I_object(src_id)) || + NULL==(dst=H5I_object(dst_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); if (8*src->size != src->u.atomic.prec || 8*dst->size != dst->u.atomic.prec) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bad precision"); @@ -3328,8 +3328,8 @@ H5T_conv_s_s (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, case H5T_CONV_CONV: /* Get the data types */ - if (NULL==(src=H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL==(dst=H5I_object_verify(dst_id,H5I_DATATYPE))) + if (NULL==(src=H5I_object(src_id)) || + NULL==(dst=H5I_object(dst_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); /* @@ -6473,8 +6473,8 @@ H5T_conv_float_double (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, switch (cdata->command) { case H5T_CONV_INIT: cdata->need_bkg = H5T_BKG_NO; - if (NULL==(st=H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL==(dt=H5I_object_verify(dst_id,H5I_DATATYPE))) + if (NULL==(st=H5I_object(src_id)) || + NULL==(dt=H5I_object(dst_id))) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to dereference data type object ID"); if (st->size!=sizeof(float) || dt->size!=sizeof(double)) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "disagreement about data type size"); @@ -6593,8 +6593,8 @@ H5T_conv_double_float (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, switch (cdata->command) { case H5T_CONV_INIT: cdata->need_bkg = H5T_BKG_NO; - if (NULL==(st=H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL==(dt=H5I_object_verify(dst_id,H5I_DATATYPE))) + if (NULL==(st=H5I_object(src_id)) || + NULL==(dt=H5I_object(dst_id))) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to dereference data type object ID"); if (st->size!=sizeof(double) || dt->size!=sizeof(float)) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "disagreement about data type size"); @@ -6731,8 +6731,8 @@ H5T_conv_i32le_f64le (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, case H5T_CONV_CONV: /* The conversion */ - if (NULL==(src=H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL==H5I_object_verify(dst_id,H5I_DATATYPE)) + if (NULL==(src=H5I_object(src_id)) || + NULL==H5I_object(dst_id)) HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); s = (uint8_t*)buf + (buf_stride?buf_stride:4)*(nelmts-1); diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h index d9f4520..7491749 100644 --- a/src/H5Tprivate.h +++ b/src/H5Tprivate.h @@ -101,6 +101,7 @@ H5_DLL H5T_t *H5T_create(H5T_class_t type, size_t size); H5_DLL H5T_t *H5T_copy(const H5T_t *old_dt, H5T_copy_t method); H5_DLL herr_t H5T_commit(H5G_entry_t *loc, const char *name, H5T_t *type); H5_DLL herr_t H5T_lock(H5T_t *dt, hbool_t immutable); +H5_DLL herr_t H5T_free(H5T_t *dt); H5_DLL herr_t H5T_close(H5T_t *dt); H5_DLL herr_t H5T_unregister(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, H5T_conv_t func); diff --git a/src/H5Tpublic.h b/src/H5Tpublic.h index 2bfc7da..a96d2bb 100644 --- a/src/H5Tpublic.h +++ b/src/H5Tpublic.h @@ -196,13 +196,21 @@ typedef herr_t (*H5T_overflow_t)(hid_t src_id, hid_t dst_id, extern "C" { #endif +/* When this header is included from H5Tprivate.h, don't make calls to H5open() */ +#undef H5OPEN +#ifndef _H5Tprivate_H +#define H5OPEN H5open(), +#else /* _H5Tprivate_H */ +#define H5OPEN +#endif /* _H5Tprivate_H */ + /* * The IEEE floating point types in various byte orders. */ -#define H5T_IEEE_F32BE (H5open(), H5T_IEEE_F32BE_g) -#define H5T_IEEE_F32LE (H5open(), H5T_IEEE_F32LE_g) -#define H5T_IEEE_F64BE (H5open(), H5T_IEEE_F64BE_g) -#define H5T_IEEE_F64LE (H5open(), H5T_IEEE_F64LE_g) +#define H5T_IEEE_F32BE (H5OPEN H5T_IEEE_F32BE_g) +#define H5T_IEEE_F32LE (H5OPEN H5T_IEEE_F32LE_g) +#define H5T_IEEE_F64BE (H5OPEN H5T_IEEE_F64BE_g) +#define H5T_IEEE_F64LE (H5OPEN H5T_IEEE_F64LE_g) H5_DLLVAR hid_t H5T_IEEE_F32BE_g; H5_DLLVAR hid_t H5T_IEEE_F32LE_g; H5_DLLVAR hid_t H5T_IEEE_F64BE_g; @@ -212,32 +220,32 @@ H5_DLLVAR hid_t H5T_IEEE_F64LE_g; * These are "standard" types. For instance, signed (2's complement) and * unsigned integers of various sizes and byte orders. */ -#define H5T_STD_I8BE (H5open(), H5T_STD_I8BE_g) -#define H5T_STD_I8LE (H5open(), H5T_STD_I8LE_g) -#define H5T_STD_I16BE (H5open(), H5T_STD_I16BE_g) -#define H5T_STD_I16LE (H5open(), H5T_STD_I16LE_g) -#define H5T_STD_I32BE (H5open(), H5T_STD_I32BE_g) -#define H5T_STD_I32LE (H5open(), H5T_STD_I32LE_g) -#define H5T_STD_I64BE (H5open(), H5T_STD_I64BE_g) -#define H5T_STD_I64LE (H5open(), H5T_STD_I64LE_g) -#define H5T_STD_U8BE (H5open(), H5T_STD_U8BE_g) -#define H5T_STD_U8LE (H5open(), H5T_STD_U8LE_g) -#define H5T_STD_U16BE (H5open(), H5T_STD_U16BE_g) -#define H5T_STD_U16LE (H5open(), H5T_STD_U16LE_g) -#define H5T_STD_U32BE (H5open(), H5T_STD_U32BE_g) -#define H5T_STD_U32LE (H5open(), H5T_STD_U32LE_g) -#define H5T_STD_U64BE (H5open(), H5T_STD_U64BE_g) -#define H5T_STD_U64LE (H5open(), H5T_STD_U64LE_g) -#define H5T_STD_B8BE (H5open(), H5T_STD_B8BE_g) -#define H5T_STD_B8LE (H5open(), H5T_STD_B8LE_g) -#define H5T_STD_B16BE (H5open(), H5T_STD_B16BE_g) -#define H5T_STD_B16LE (H5open(), H5T_STD_B16LE_g) -#define H5T_STD_B32BE (H5open(), H5T_STD_B32BE_g) -#define H5T_STD_B32LE (H5open(), H5T_STD_B32LE_g) -#define H5T_STD_B64BE (H5open(), H5T_STD_B64BE_g) -#define H5T_STD_B64LE (H5open(), H5T_STD_B64LE_g) -#define H5T_STD_REF_OBJ (H5open(), H5T_STD_REF_OBJ_g) -#define H5T_STD_REF_DSETREG (H5open(), H5T_STD_REF_DSETREG_g) +#define H5T_STD_I8BE (H5OPEN H5T_STD_I8BE_g) +#define H5T_STD_I8LE (H5OPEN H5T_STD_I8LE_g) +#define H5T_STD_I16BE (H5OPEN H5T_STD_I16BE_g) +#define H5T_STD_I16LE (H5OPEN H5T_STD_I16LE_g) +#define H5T_STD_I32BE (H5OPEN H5T_STD_I32BE_g) +#define H5T_STD_I32LE (H5OPEN H5T_STD_I32LE_g) +#define H5T_STD_I64BE (H5OPEN H5T_STD_I64BE_g) +#define H5T_STD_I64LE (H5OPEN H5T_STD_I64LE_g) +#define H5T_STD_U8BE (H5OPEN H5T_STD_U8BE_g) +#define H5T_STD_U8LE (H5OPEN H5T_STD_U8LE_g) +#define H5T_STD_U16BE (H5OPEN H5T_STD_U16BE_g) +#define H5T_STD_U16LE (H5OPEN H5T_STD_U16LE_g) +#define H5T_STD_U32BE (H5OPEN H5T_STD_U32BE_g) +#define H5T_STD_U32LE (H5OPEN H5T_STD_U32LE_g) +#define H5T_STD_U64BE (H5OPEN H5T_STD_U64BE_g) +#define H5T_STD_U64LE (H5OPEN H5T_STD_U64LE_g) +#define H5T_STD_B8BE (H5OPEN H5T_STD_B8BE_g) +#define H5T_STD_B8LE (H5OPEN H5T_STD_B8LE_g) +#define H5T_STD_B16BE (H5OPEN H5T_STD_B16BE_g) +#define H5T_STD_B16LE (H5OPEN H5T_STD_B16LE_g) +#define H5T_STD_B32BE (H5OPEN H5T_STD_B32BE_g) +#define H5T_STD_B32LE (H5OPEN H5T_STD_B32LE_g) +#define H5T_STD_B64BE (H5OPEN H5T_STD_B64BE_g) +#define H5T_STD_B64LE (H5OPEN H5T_STD_B64LE_g) +#define H5T_STD_REF_OBJ (H5OPEN H5T_STD_REF_OBJ_g) +#define H5T_STD_REF_DSETREG (H5OPEN H5T_STD_REF_DSETREG_g) H5_DLLVAR hid_t H5T_STD_I8BE_g; H5_DLLVAR hid_t H5T_STD_I8LE_g; H5_DLLVAR hid_t H5T_STD_I16BE_g; @@ -268,10 +276,10 @@ H5_DLLVAR hid_t H5T_STD_REF_DSETREG_g; /* * Types which are particular to Unix. */ -#define H5T_UNIX_D32BE (H5open(), H5T_UNIX_D32BE_g) -#define H5T_UNIX_D32LE (H5open(), H5T_UNIX_D32LE_g) -#define H5T_UNIX_D64BE (H5open(), H5T_UNIX_D64BE_g) -#define H5T_UNIX_D64LE (H5open(), H5T_UNIX_D64LE_g) +#define H5T_UNIX_D32BE (H5OPEN H5T_UNIX_D32BE_g) +#define H5T_UNIX_D32LE (H5OPEN H5T_UNIX_D32LE_g) +#define H5T_UNIX_D64BE (H5OPEN H5T_UNIX_D64BE_g) +#define H5T_UNIX_D64LE (H5OPEN H5T_UNIX_D64LE_g) H5_DLLVAR hid_t H5T_UNIX_D32BE_g; H5_DLLVAR hid_t H5T_UNIX_D32LE_g; H5_DLLVAR hid_t H5T_UNIX_D64BE_g; @@ -281,13 +289,13 @@ H5_DLLVAR hid_t H5T_UNIX_D64LE_g; * Types particular to the C language. String types use `bytes' instead * of `bits' as their size. */ -#define H5T_C_S1 (H5open(), H5T_C_S1_g) +#define H5T_C_S1 (H5OPEN H5T_C_S1_g) H5_DLLVAR hid_t H5T_C_S1_g; /* * Types particular to Fortran. */ -#define H5T_FORTRAN_S1 (H5open(), H5T_FORTRAN_S1_g) +#define H5T_FORTRAN_S1 (H5OPEN H5T_FORTRAN_S1_g) H5_DLLVAR hid_t H5T_FORTRAN_S1_g; /* @@ -357,29 +365,29 @@ H5_DLLVAR hid_t H5T_FORTRAN_S1_g; * same as `LONG' and `DOUBLE' respectively. */ #define H5T_NATIVE_CHAR (CHAR_MIN?H5T_NATIVE_SCHAR:H5T_NATIVE_UCHAR) -#define H5T_NATIVE_SCHAR (H5open(), H5T_NATIVE_SCHAR_g) -#define H5T_NATIVE_UCHAR (H5open(), H5T_NATIVE_UCHAR_g) -#define H5T_NATIVE_SHORT (H5open(), H5T_NATIVE_SHORT_g) -#define H5T_NATIVE_USHORT (H5open(), H5T_NATIVE_USHORT_g) -#define H5T_NATIVE_INT (H5open(), H5T_NATIVE_INT_g) -#define H5T_NATIVE_UINT (H5open(), H5T_NATIVE_UINT_g) -#define H5T_NATIVE_LONG (H5open(), H5T_NATIVE_LONG_g) -#define H5T_NATIVE_ULONG (H5open(), H5T_NATIVE_ULONG_g) -#define H5T_NATIVE_LLONG (H5open(), H5T_NATIVE_LLONG_g) -#define H5T_NATIVE_ULLONG (H5open(), H5T_NATIVE_ULLONG_g) -#define H5T_NATIVE_FLOAT (H5open(), H5T_NATIVE_FLOAT_g) -#define H5T_NATIVE_DOUBLE (H5open(), H5T_NATIVE_DOUBLE_g) -#define H5T_NATIVE_LDOUBLE (H5open(), H5T_NATIVE_LDOUBLE_g) -#define H5T_NATIVE_B8 (H5open(), H5T_NATIVE_B8_g) -#define H5T_NATIVE_B16 (H5open(), H5T_NATIVE_B16_g) -#define H5T_NATIVE_B32 (H5open(), H5T_NATIVE_B32_g) -#define H5T_NATIVE_B64 (H5open(), H5T_NATIVE_B64_g) -#define H5T_NATIVE_OPAQUE (H5open(), H5T_NATIVE_OPAQUE_g) -#define H5T_NATIVE_HADDR (H5open(), H5T_NATIVE_HADDR_g) -#define H5T_NATIVE_HSIZE (H5open(), H5T_NATIVE_HSIZE_g) -#define H5T_NATIVE_HSSIZE (H5open(), H5T_NATIVE_HSSIZE_g) -#define H5T_NATIVE_HERR (H5open(), H5T_NATIVE_HERR_g) -#define H5T_NATIVE_HBOOL (H5open(), H5T_NATIVE_HBOOL_g) +#define H5T_NATIVE_SCHAR (H5OPEN H5T_NATIVE_SCHAR_g) +#define H5T_NATIVE_UCHAR (H5OPEN H5T_NATIVE_UCHAR_g) +#define H5T_NATIVE_SHORT (H5OPEN H5T_NATIVE_SHORT_g) +#define H5T_NATIVE_USHORT (H5OPEN H5T_NATIVE_USHORT_g) +#define H5T_NATIVE_INT (H5OPEN H5T_NATIVE_INT_g) +#define H5T_NATIVE_UINT (H5OPEN H5T_NATIVE_UINT_g) +#define H5T_NATIVE_LONG (H5OPEN H5T_NATIVE_LONG_g) +#define H5T_NATIVE_ULONG (H5OPEN H5T_NATIVE_ULONG_g) +#define H5T_NATIVE_LLONG (H5OPEN H5T_NATIVE_LLONG_g) +#define H5T_NATIVE_ULLONG (H5OPEN H5T_NATIVE_ULLONG_g) +#define H5T_NATIVE_FLOAT (H5OPEN H5T_NATIVE_FLOAT_g) +#define H5T_NATIVE_DOUBLE (H5OPEN H5T_NATIVE_DOUBLE_g) +#define H5T_NATIVE_LDOUBLE (H5OPEN H5T_NATIVE_LDOUBLE_g) +#define H5T_NATIVE_B8 (H5OPEN H5T_NATIVE_B8_g) +#define H5T_NATIVE_B16 (H5OPEN H5T_NATIVE_B16_g) +#define H5T_NATIVE_B32 (H5OPEN H5T_NATIVE_B32_g) +#define H5T_NATIVE_B64 (H5OPEN H5T_NATIVE_B64_g) +#define H5T_NATIVE_OPAQUE (H5OPEN H5T_NATIVE_OPAQUE_g) +#define H5T_NATIVE_HADDR (H5OPEN H5T_NATIVE_HADDR_g) +#define H5T_NATIVE_HSIZE (H5OPEN H5T_NATIVE_HSIZE_g) +#define H5T_NATIVE_HSSIZE (H5OPEN H5T_NATIVE_HSSIZE_g) +#define H5T_NATIVE_HERR (H5OPEN H5T_NATIVE_HERR_g) +#define H5T_NATIVE_HBOOL (H5OPEN H5T_NATIVE_HBOOL_g) H5_DLLVAR hid_t H5T_NATIVE_SCHAR_g; H5_DLLVAR hid_t H5T_NATIVE_UCHAR_g; H5_DLLVAR hid_t H5T_NATIVE_SHORT_g; @@ -405,12 +413,12 @@ H5_DLLVAR hid_t H5T_NATIVE_HERR_g; H5_DLLVAR hid_t H5T_NATIVE_HBOOL_g; /* C9x integer types */ -#define H5T_NATIVE_INT8 (H5open(), H5T_NATIVE_INT8_g) -#define H5T_NATIVE_UINT8 (H5open(), H5T_NATIVE_UINT8_g) -#define H5T_NATIVE_INT_LEAST8 (H5open(), H5T_NATIVE_INT_LEAST8_g) -#define H5T_NATIVE_UINT_LEAST8 (H5open(), H5T_NATIVE_UINT_LEAST8_g) -#define H5T_NATIVE_INT_FAST8 (H5open(), H5T_NATIVE_INT_FAST8_g) -#define H5T_NATIVE_UINT_FAST8 (H5open(), H5T_NATIVE_UINT_FAST8_g) +#define H5T_NATIVE_INT8 (H5OPEN H5T_NATIVE_INT8_g) +#define H5T_NATIVE_UINT8 (H5OPEN H5T_NATIVE_UINT8_g) +#define H5T_NATIVE_INT_LEAST8 (H5OPEN H5T_NATIVE_INT_LEAST8_g) +#define H5T_NATIVE_UINT_LEAST8 (H5OPEN H5T_NATIVE_UINT_LEAST8_g) +#define H5T_NATIVE_INT_FAST8 (H5OPEN H5T_NATIVE_INT_FAST8_g) +#define H5T_NATIVE_UINT_FAST8 (H5OPEN H5T_NATIVE_UINT_FAST8_g) H5_DLLVAR hid_t H5T_NATIVE_INT8_g; H5_DLLVAR hid_t H5T_NATIVE_UINT8_g; H5_DLLVAR hid_t H5T_NATIVE_INT_LEAST8_g; @@ -418,12 +426,12 @@ H5_DLLVAR hid_t H5T_NATIVE_UINT_LEAST8_g; H5_DLLVAR hid_t H5T_NATIVE_INT_FAST8_g; H5_DLLVAR hid_t H5T_NATIVE_UINT_FAST8_g; -#define H5T_NATIVE_INT16 (H5open(), H5T_NATIVE_INT16_g) -#define H5T_NATIVE_UINT16 (H5open(), H5T_NATIVE_UINT16_g) -#define H5T_NATIVE_INT_LEAST16 (H5open(), H5T_NATIVE_INT_LEAST16_g) -#define H5T_NATIVE_UINT_LEAST16 (H5open(), H5T_NATIVE_UINT_LEAST16_g) -#define H5T_NATIVE_INT_FAST16 (H5open(), H5T_NATIVE_INT_FAST16_g) -#define H5T_NATIVE_UINT_FAST16 (H5open(), H5T_NATIVE_UINT_FAST16_g) +#define H5T_NATIVE_INT16 (H5OPEN H5T_NATIVE_INT16_g) +#define H5T_NATIVE_UINT16 (H5OPEN H5T_NATIVE_UINT16_g) +#define H5T_NATIVE_INT_LEAST16 (H5OPEN H5T_NATIVE_INT_LEAST16_g) +#define H5T_NATIVE_UINT_LEAST16 (H5OPEN H5T_NATIVE_UINT_LEAST16_g) +#define H5T_NATIVE_INT_FAST16 (H5OPEN H5T_NATIVE_INT_FAST16_g) +#define H5T_NATIVE_UINT_FAST16 (H5OPEN H5T_NATIVE_UINT_FAST16_g) H5_DLLVAR hid_t H5T_NATIVE_INT16_g; H5_DLLVAR hid_t H5T_NATIVE_UINT16_g; H5_DLLVAR hid_t H5T_NATIVE_INT_LEAST16_g; @@ -431,12 +439,12 @@ H5_DLLVAR hid_t H5T_NATIVE_UINT_LEAST16_g; H5_DLLVAR hid_t H5T_NATIVE_INT_FAST16_g; H5_DLLVAR hid_t H5T_NATIVE_UINT_FAST16_g; -#define H5T_NATIVE_INT32 (H5open(), H5T_NATIVE_INT32_g) -#define H5T_NATIVE_UINT32 (H5open(), H5T_NATIVE_UINT32_g) -#define H5T_NATIVE_INT_LEAST32 (H5open(), H5T_NATIVE_INT_LEAST32_g) -#define H5T_NATIVE_UINT_LEAST32 (H5open(), H5T_NATIVE_UINT_LEAST32_g) -#define H5T_NATIVE_INT_FAST32 (H5open(), H5T_NATIVE_INT_FAST32_g) -#define H5T_NATIVE_UINT_FAST32 (H5open(), H5T_NATIVE_UINT_FAST32_g) +#define H5T_NATIVE_INT32 (H5OPEN H5T_NATIVE_INT32_g) +#define H5T_NATIVE_UINT32 (H5OPEN H5T_NATIVE_UINT32_g) +#define H5T_NATIVE_INT_LEAST32 (H5OPEN H5T_NATIVE_INT_LEAST32_g) +#define H5T_NATIVE_UINT_LEAST32 (H5OPEN H5T_NATIVE_UINT_LEAST32_g) +#define H5T_NATIVE_INT_FAST32 (H5OPEN H5T_NATIVE_INT_FAST32_g) +#define H5T_NATIVE_UINT_FAST32 (H5OPEN H5T_NATIVE_UINT_FAST32_g) H5_DLLVAR hid_t H5T_NATIVE_INT32_g; H5_DLLVAR hid_t H5T_NATIVE_UINT32_g; H5_DLLVAR hid_t H5T_NATIVE_INT_LEAST32_g; @@ -444,12 +452,12 @@ H5_DLLVAR hid_t H5T_NATIVE_UINT_LEAST32_g; H5_DLLVAR hid_t H5T_NATIVE_INT_FAST32_g; H5_DLLVAR hid_t H5T_NATIVE_UINT_FAST32_g; -#define H5T_NATIVE_INT64 (H5open(), H5T_NATIVE_INT64_g) -#define H5T_NATIVE_UINT64 (H5open(), H5T_NATIVE_UINT64_g) -#define H5T_NATIVE_INT_LEAST64 (H5open(), H5T_NATIVE_INT_LEAST64_g) -#define H5T_NATIVE_UINT_LEAST64 (H5open(), H5T_NATIVE_UINT_LEAST64_g) -#define H5T_NATIVE_INT_FAST64 (H5open(), H5T_NATIVE_INT_FAST64_g) -#define H5T_NATIVE_UINT_FAST64 (H5open(), H5T_NATIVE_UINT_FAST64_g) +#define H5T_NATIVE_INT64 (H5OPEN H5T_NATIVE_INT64_g) +#define H5T_NATIVE_UINT64 (H5OPEN H5T_NATIVE_UINT64_g) +#define H5T_NATIVE_INT_LEAST64 (H5OPEN H5T_NATIVE_INT_LEAST64_g) +#define H5T_NATIVE_UINT_LEAST64 (H5OPEN H5T_NATIVE_UINT_LEAST64_g) +#define H5T_NATIVE_INT_FAST64 (H5OPEN H5T_NATIVE_INT_FAST64_g) +#define H5T_NATIVE_UINT_FAST64 (H5OPEN H5T_NATIVE_UINT_FAST64_g) H5_DLLVAR hid_t H5T_NATIVE_INT64_g; H5_DLLVAR hid_t H5T_NATIVE_UINT64_g; H5_DLLVAR hid_t H5T_NATIVE_INT_LEAST64_g; diff --git a/src/H5Tvlen.c b/src/H5Tvlen.c index b8a4a25..145fc3b 100644 --- a/src/H5Tvlen.c +++ b/src/H5Tvlen.c @@ -232,10 +232,6 @@ H5T_vlen_seq_mem_write(hid_t plist_id, H5F_t UNUSED *f, void *vl_addr, void *buf /* Use the user's memory allocation routine is one is defined */ - /* Get the default dataset transfer property list if the user didn't provide one */ - if (H5P_DEFAULT == plist_id) - plist_id= H5P_DATASET_XFER_DEFAULT; - /* Get the allocation function & info */ if(NULL == (plist = H5P_object_verify(plist_id,H5P_DATASET_XFER))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list"); @@ -367,10 +363,6 @@ H5T_vlen_str_mem_write(hid_t plist_id, H5F_t UNUSED *f, void *vl_addr, void *buf /* Use the user's memory allocation routine if one is defined */ - /* Get the default dataset transfer property list if the user didn't provide one */ - if (H5P_DEFAULT == plist_id) - plist_id= H5P_DATASET_XFER_DEFAULT; - /* Get the allocation function & info */ if(NULL == (plist = H5P_object_verify(plist_id,H5P_DATASET_XFER))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list"); @@ -706,10 +698,6 @@ H5T_vlen_reclaim(void *elem, hid_t type_id, hsize_t UNUSED ndim, hssize_t UNUSED if (NULL==(dt=H5I_object_verify(type_id,H5I_DATATYPE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - /* Get the default dataset transfer property list if the user didn't provide one */ - if (H5P_DEFAULT == plist_id) - plist_id= H5P_DATASET_XFER_DEFAULT; - /* Get the free func & information */ if(NULL == (plist = H5P_object_verify(plist_id,H5P_DATASET_XFER))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list"); diff --git a/src/H5detect.c b/src/H5detect.c index 0d19208..39ee57b 100644 --- a/src/H5detect.c +++ b/src/H5detect.c @@ -495,7 +495,7 @@ H5TN_init_interface(void)\n\ /* The part common to fixed and floating types */ printf("\ - if (NULL==(dt = H5FL_ALLOC (H5T_t,1)))\n\ + if (NULL==(dt = H5FL_CALLOC (H5T_t)))\n\ HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL,\"memory allocation failed\");\n\ dt->state = H5T_STATE_IMMUTABLE;\n\ dt->ent.header = HADDR_UNDEF;\n\ diff --git a/src/Makefile.in b/src/Makefile.in index 1d4f82f..76b7152 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -32,13 +32,14 @@ LIB_SRC=H5.c H5A.c H5AC.c H5B.c H5D.c H5E.c H5F.c H5Farray.c H5Fcontig.c \ H5Fcompact.c H5Fistore.c H5Fseq.c H5FD.c H5FDcore.c H5FDfamily.c \ H5FDgass.c H5FDlog.c H5FDmpio.c H5FDmpiposix.c H5FDmulti.c H5FDsec2.c \ H5FDsrb.c H5FDstdio.c H5FDstream.c H5FL.c H5FP.c H5FPclient.c \ - H5FPserver.c H5G.c H5Gent.c H5Gnode.c H5Gstab.c H5HG.c H5HL.c H5I.c \ - H5MF.c H5MM.c H5O.c H5Oattr.c H5Ocomp.c H5Ocont.c H5Odtype.c H5Oefl.c \ + H5FO.c H5FPserver.c H5G.c H5Gent.c H5Gnode.c H5Gstab.c H5HG.c H5HL.c \ + H5I.c H5MF.c H5MM.c H5O.c H5Oattr.c H5Ocont.c H5Odtype.c H5Oefl.c \ H5Ofill.c H5Ofphdf5.c H5Olayout.c H5Omtime.c H5Oname.c H5Onull.c \ - H5Oplist.c H5Osdspace.c H5Oshared.c H5Ostab.c H5P.c H5Pdcpl.c \ - H5Pdxpl.c H5Pfapl.c H5Pfcpl.c H5R.c H5S.c H5Sall.c H5Shyper.c \ - H5Smpio.c H5Snone.c H5Spoint.c H5Sselect.c H5T.c H5Tbit.c H5Tconv.c \ - H5Tinit.c H5Tvlen.c H5TB.c H5TS.c H5V.c H5Z.c H5Zdeflate.c H5Zshuffle.c + H5Opline.c H5Oplist.c H5Osdspace.c H5Oshared.c H5Ostab.c H5P.c \ + H5Pdcpl.c H5Pdxpl.c H5Pfapl.c H5Pfcpl.c H5R.c H5RS.c H5S.c H5Sall.c \ + H5Shyper.c H5Smpio.c H5Snone.c H5Spoint.c H5Sselect.c H5ST.c H5T.c \ + H5Tbit.c H5Tconv.c H5Tinit.c H5Tvlen.c H5TB.c H5TS.c H5V.c H5Z.c \ + H5Zdeflate.c H5Zshuffle.c LIB_OBJ=$(LIB_SRC:.c=.lo) @@ -47,7 +48,7 @@ MOSTLYCLEAN=H5detect.o H5detect.lo H5detect H5Tinit.o H5Tinit.lo H5Tinit.c ## Public header files (to be installed)... PUB_HDR=H5public.h H5Apublic.h H5ACpublic.h H5Bpublic.h H5Dpublic.h \ - H5Epublic.h H5Fpublic.h H5FDpublic.h H5FDcore.h H5FDfamily.h \ + H5Epublic.h H5Fpublic.h H5FDpublic.h H5FDcore.h H5FDfamily.h \ H5FDgass.h H5FDlog.h H5FDmpio.h H5FDmpiposix.h H5FDmulti.h H5FDsec2.h \ H5FDsrb.h H5FDstdio.h H5FDstream.h H5FPpublic.h H5Gpublic.h \ H5HGpublic.h H5HLpublic.h H5Ipublic.h H5MMpublic.h H5Opublic.h \ @@ -57,11 +58,12 @@ PUB_HDR=H5public.h H5Apublic.h H5ACpublic.h H5Bpublic.h H5Dpublic.h \ ## Other header files (not to be installed)... PRIVATE_HDR=H5private.h H5Aprivate.h H5Apkg.h H5ACprivate.h H5Bprivate.h \ H5Dprivate.h H5Eprivate.h H5Fprivate.h H5FDprivate.h \ - H5FLprivate.h H5FPprivate.h H5Gprivate.h H5Gpkg.h H5HGprivate.h \ - H5HLprivate.h H5Iprivate.h H5MFprivate.h H5MMprivate.h \ - H5Oprivate.h H5Pprivate.h H5Ppkg.h H5Rprivate.h H5Sprivate.h \ - H5Tprivate.h H5TBprivate.h H5Tpkg.h H5TSprivate.h H5Vprivate.h \ - H5Zprivate.h H5config.h + H5FLprivate.h H5FOprivate.h H5FPprivate.h H5Gprivate.h H5Gpkg.h \ + H5HGprivate.h H5HLprivate.h H5Iprivate.h H5MFprivate.h \ + H5MMprivate.h H5Oprivate.h H5Pprivate.h H5Ppkg.h H5Rprivate.h \ + H5RSprivate.h H5Sprivate.h H5STprivate.h H5Tprivate.h \ + H5TBprivate.h H5Tpkg.h H5TSprivate.h H5Vprivate.h H5Zprivate.h \ + H5config.h ## Number format detection ## The LD_LIBRARY_PATH setting is a klutch. diff --git a/test/Makefile.in b/test/Makefile.in index 0ea2fa5..860c4cc 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -65,11 +65,12 @@ TEST_SRC=big.c bittests.c cmpd_dset.c dsets.c dtypes.c extend.c \ external.c fillval.c flush1.c flush2.c gheap.c h5test.c hyperslab.c \ istore.c lheap.c links.c mount.c mtime.c ohdr.c stab.c tarray.c \ tattr.c tconfig.c testhdf5.c testmeta.c tfile.c tgenprop.c th5s.c \ - titerate.c tmeta.c trefer.c tselect.c ttime.c ttbbt.c tvltypes.c \ - tvlstr.c tmisc.c unlink.c enum.c ttsafe.c ttsafe_dcreate.c \ - ttsafe_error.c ttsafe_cancel.c ttsafe_acreate.c gass_write.c \ - gass_read.c gass_append.c srb_read.c srb_write.c srb_append.c \ - stream_test.c set_extent.c getname.c file_handle.c ntypes.c + titerate.c tmeta.c trefer.c trefstr.c tselect.c ttime.c ttbbt.c \ + ttst.c tvltypes.c tvlstr.c tmisc.c unlink.c enum.c ttsafe.c \ + ttsafe_dcreate.c ttsafe_error.c ttsafe_cancel.c ttsafe_acreate.c \ + gass_write.c gass_read.c gass_append.c srb_read.c srb_write.c \ + srb_append.c stream_test.c set_extent.c getname.c file_handle.c \ + ntypes.c TEST_OBJ=$(TEST_SRC:.c=.lo) @@ -90,8 +91,8 @@ timings _timings: $(TIMINGS) $(TEST_PROGS): $(LIB) $(LIBHDF5) TESTHDF5_OBJ=testhdf5.lo tarray.lo tattr.lo tconfig.lo tfile.lo tgenprop.lo \ - th5s.lo titerate.lo tmeta.lo ttime.lo trefer.lo tselect.lo ttbbt.lo \ - tvltypes.lo tvlstr.lo tmisc.lo + th5s.lo titerate.lo tmeta.lo ttime.lo trefer.lo trefstr.lo tselect.lo \ + ttbbt.lo ttst.lo tvltypes.lo tvlstr.lo tmisc.lo TTS_OBJ=ttsafe.lo ttsafe_dcreate.lo ttsafe_error.lo ttsafe_cancel.lo \ ttsafe_acreate.lo diff --git a/test/dsets.c b/test/dsets.c index 3a7e561..e41748e 100644 --- a/test/dsets.c +++ b/test/dsets.c @@ -327,9 +327,8 @@ test_userblock_offset(hid_t fapl) { char filename[32]; hid_t file, fcpl, dataset, space; - int i, j, n; + int i, j; hsize_t dims[2]; -/* FILE *f;*/ int f; haddr_t offset; int rdata[100][200]; @@ -339,19 +338,11 @@ test_userblock_offset(hid_t fapl) h5_fixname(FILENAME[2], fapl, filename, sizeof filename); if((fcpl=H5Pcreate(H5P_FILE_CREATE))<0) goto error; - if(H5Pset_userblock(fcpl, USER_BLOCK)<0) goto error; + if(H5Pset_userblock(fcpl, (hsize_t)USER_BLOCK)<0) goto error; - if ((file=H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl))<0) { + if ((file=H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl))<0) goto error; - } - /* Initialize the dataset */ - /*for (i = n = 0; i < 100; i++) { - for (j = 0; j < 200; j++) { - points[i][j] = n++; - } - }*/ - /* Create the data space */ dims[0] = 100; dims[1] = 200; diff --git a/test/fillval.c b/test/fillval.c index 587999a..d15bfc5 100644 --- a/test/fillval.c +++ b/test/fillval.c @@ -1264,7 +1264,7 @@ test_compatible(void) char *srcdir = getenv("srcdir"); /*where the src code is located*/ char testfile[512]=""; /* test file name */ - TESTING("contiguous dataset compatibility with v. 1.5"); + TESTING("contiguous dataset compatibility with v. 1.4"); /* Generate correct name for test file by prepending the source path */ if(srcdir && ((strlen(srcdir) + strlen(FILE_COMPATIBLE) + 1) < diff --git a/test/gen_new_mtime.c b/test/gen_new_mtime.c new file mode 100644 index 0000000..1bf1ef9 --- /dev/null +++ b/test/gen_new_mtime.c @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2003 NCSA + * All rights reserved. + * + * Programmer: Quincey Koziol + * Friday, January 3, 2003 + * + * Purpose: Create a dataset, which should have the newer mtime information + * stored in it. + * This program is used to create the test file `tmtimen.h5' which + * has the new format for mtime information. + * To build the test file, this program MUST be compiled and linked with + * the hdf5-1.5+ series of libraries and the generated test file must be + * put into the 'test' directory in the 1.5+ branch of the library. + */ + +#include "hdf5.h" + +#define TESTFILE "tmtimen.h5" + + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: + * + * Return: Success: + * + * Failure: + * + * Programmer: Quincey Koziol + * Friday, January 3, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int +main(void) +{ + hid_t file, space, dset; + + /* Create the file */ + file = H5Fcreate(TESTFILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + if(file<0) + printf("file<0!\n"); + + /* Create the dataspace (for dataset) */ + space = H5Screate(H5S_SCALAR); + if(space<0) + printf("space<0!\n"); + + /* Create the dataset with compound array fields */ + dset = H5Dcreate(file, "Dataset1", H5T_NATIVE_INT, space, H5P_DEFAULT); + if(dset<0) + printf("dset<0!\n"); + + H5Dclose(dset); + H5Sclose(space); + H5Fclose(file); + + return 0; +} + + diff --git a/test/gen_old_mtime.c b/test/gen_old_mtime.c new file mode 100644 index 0000000..b9a8186 --- /dev/null +++ b/test/gen_old_mtime.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2003 NCSA + * All rights reserved. + * + * Programmer: Quincey Koziol + * Friday, January 3, 2003 + * + * Purpose: Create a dataset, which should have the older mtime information + * stored in it. + * This program is used to create the test file `tmtimeo.h5' which + * has the new format for mtime information. + * To build the test file, this program MUST be compiled and linked with + * the hdf5-1.4+ series of libraries and the generated test file must be + * put into the 'test' directory in the 1.5+ branch of the library. + */ + +#include "hdf5.h" + +#define TESTFILE "tmtimeo.h5" + + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: + * + * Return: Success: + * + * Failure: + * + * Programmer: Quincey Koziol + * Friday, January 3, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int +main(void) +{ + hid_t file, space, dset; + + /* Create the file */ + file = H5Fcreate(TESTFILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + if(file<0) + printf("file<0!\n"); + + /* Create the dataspace (for dataset) */ + space = H5Screate(H5S_SCALAR); + if(space<0) + printf("space<0!\n"); + + /* Create the dataset with compound array fields */ + dset = H5Dcreate(file, "Dataset1", H5T_NATIVE_INT, space, H5P_DEFAULT); + if(dset<0) + printf("dset<0!\n"); + + H5Dclose(dset); + H5Sclose(space); + H5Fclose(file); + + return 0; +} + + + diff --git a/test/istore.c b/test/istore.c index e79754a..3dfb8cf 100644 --- a/test/istore.c +++ b/test/istore.c @@ -100,6 +100,7 @@ new_object(H5F_t *f, const char *name, unsigned ndims, H5G_entry_t *ent/*out*/) unsigned u; /* Create the object header */ + HDmemset(ent,0,sizeof(H5G_entry_t)); if (H5O_create(f, 64, ent)) { H5_FAILED(); puts(" H5O_create() = NULL"); @@ -118,7 +119,7 @@ new_object(H5F_t *f, const char *name, unsigned ndims, H5G_entry_t *ent/*out*/) } /* Create the root of the B-tree that describes chunked storage */ H5F_istore_create (f, &layout/*in,out*/); - if (H5O_modify(ent, H5O_LAYOUT, H5O_NEW_MESG, 0, &layout) < 0) { + if (H5O_modify(ent, H5O_LAYOUT, H5O_NEW_MESG, 0, 1, &layout) < 0) { H5_FAILED(); puts(" H5O_modify istore message failure."); goto error; diff --git a/test/mtime.c b/test/mtime.c index 55e0c21..b94cadf 100644 --- a/test/mtime.c +++ b/test/mtime.c @@ -17,6 +17,11 @@ const char *FILENAME[] = { NULL }; +#define TESTFILE1 "tmtimeo.h5" +#define MTIME1 1041605080 +#define TESTFILE2 "tmtimen.h5" +#define MTIME2 1041606478 + /*------------------------------------------------------------------------- * Function: main @@ -31,6 +36,11 @@ const char *FILENAME[] = { * Thursday, July 30, 1998 * * Modifications: + * Added checks for old and new modification time messages + * in pre-created datafiles (generated with gen_old_mtime.c and + * gen_new_mtime.c). + * Quincey Koziol + * Friday, January 3, 2003 * *------------------------------------------------------------------------- */ @@ -101,9 +111,65 @@ main(void) printf(" got: %s\n ans: %s\n", buf1, buf2); return 1; } + PASSED(); - /* All looks good */ + /* Check opening existing file with old-style modification time information + * and make certain that the time is correct + */ + TESTING("accessing old modification time messages"); + + { + char testfile[512]=""; + char *srcdir = HDgetenv("srcdir"); + if (srcdir && ((HDstrlen(srcdir) + strlen(TESTFILE1) + 1) < sizeof(testfile))){ + HDstrcpy(testfile, srcdir); + HDstrcat(testfile, "/"); + } + HDstrcat(testfile, TESTFILE1); + file = H5Fopen(testfile, H5F_ACC_RDONLY, H5P_DEFAULT); + if (file >= 0){ + if(H5Gget_objinfo(file, "/Dataset1", TRUE, &sb1)<0) + return 1; + if(sb1.mtime!=MTIME1) return 1; + if (H5Fclose(file)<0) return 1; + } + else { + printf("***cannot open the pre-created old modification test file (%s)\n", + testfile); + return 1; + } /* end else */ + } PASSED(); + + /* Check opening existing file with new-style modification time information + * and make certain that the time is correct + */ + TESTING("accessing new modification time messages"); + + { + char testfile[512]=""; + char *srcdir = HDgetenv("srcdir"); + if (srcdir && ((HDstrlen(srcdir) + strlen(TESTFILE2) + 1) < sizeof(testfile))){ + HDstrcpy(testfile, srcdir); + HDstrcat(testfile, "/"); + } + HDstrcat(testfile, TESTFILE2); + file = H5Fopen(testfile, H5F_ACC_RDONLY, H5P_DEFAULT); + if (file >= 0){ + if(H5Gget_objinfo(file, "/Dataset1", TRUE, &sb2)<0) + return 1; + if(sb2.mtime!=MTIME2) return 1; + if (H5Fclose(file)<0) return 1; + } + else { + printf("***cannot open the pre-created old modification test file (%s)\n", + testfile); + return 1; + } /* end else */ + } + PASSED(); + + /* All looks good */ puts("All modification time tests passed."); h5_cleanup(FILENAME, fapl); return 0; diff --git a/test/ntypes.c b/test/ntypes.c index 69d56c9..fcdd9fb 100644 --- a/test/ntypes.c +++ b/test/ntypes.c @@ -1503,7 +1503,6 @@ test_refer_dtype2(hid_t file) *drbuf; /* Buffer for reading numeric data from disk */ uint8_t *tu8; /* Temporary pointer to uint8 data */ int i; /* counting variables */ - herr_t ret; /* Generic return value */ /* Output message about test being performed */ TESTING("dataset region reference"); diff --git a/test/ohdr.c b/test/ohdr.c index 69d7f10..ddd4ed6 100644 --- a/test/ohdr.c +++ b/test/ohdr.c @@ -62,6 +62,7 @@ main(void) * Test object header creation */ TESTING("object header creation"); + HDmemset(&oh_ent,0,sizeof(H5G_entry_t)); if (H5O_create(f, 64, &oh_ent/*out*/)<0) { H5_FAILED(); H5Eprint(stdout); @@ -73,7 +74,7 @@ main(void) TESTING("message creation"); stab.btree_addr = 11111111; stab.heap_addr = 22222222; - if (H5O_modify(&oh_ent, H5O_STAB, H5O_NEW_MESG, 0, &stab)<0) { + if (H5O_modify(&oh_ent, H5O_STAB, H5O_NEW_MESG, 0, 1, &stab)<0) { H5_FAILED(); H5Eprint(stdout); goto error; @@ -105,7 +106,7 @@ main(void) TESTING("message modification"); stab.btree_addr = 33333333; stab.heap_addr = 44444444; - if (H5O_modify(&oh_ent, H5O_STAB, 0, 0, &stab)<0) { + if (H5O_modify(&oh_ent, H5O_STAB, 0, 0, 1, &stab)<0) { H5_FAILED(); H5Eprint(stdout); goto error; @@ -138,7 +139,7 @@ main(void) TESTING("duplicate message creation"); stab.btree_addr = 55555555; stab.heap_addr = 66666666; - if (H5O_modify(&oh_ent, H5O_STAB, H5O_NEW_MESG, 0, &stab)<0) { + if (H5O_modify(&oh_ent, H5O_STAB, H5O_NEW_MESG, 0, 1, &stab)<0) { H5_FAILED(); H5Eprint(stdout); goto error; @@ -170,7 +171,7 @@ main(void) TESTING("duplicate message modification"); stab.btree_addr = 77777777; stab.heap_addr = 88888888; - if (H5O_modify(&oh_ent, H5O_STAB, 1, 0, &stab)<0) { + if (H5O_modify(&oh_ent, H5O_STAB, 1, 0, 1, &stab)<0) { H5_FAILED(); H5Eprint(stdout); goto error; @@ -204,7 +205,7 @@ main(void) for (i=0; i<40; i++) { stab.btree_addr = (i+1)*1000+1; stab.heap_addr = (i+1)*1000+2; - if (H5O_modify(&oh_ent, H5O_STAB, H5O_NEW_MESG, 0, &stab)<0) { + if (H5O_modify(&oh_ent, H5O_STAB, H5O_NEW_MESG, 0, 1, &stab)<0) { H5_FAILED(); H5Eprint(stdout); goto error; @@ -225,7 +226,7 @@ main(void) for (i=0; i<10; i++) { stab.btree_addr = (i + 1) * 1000 + 10; stab.heap_addr = (i + 1) * 1000 + 20; - if (H5O_modify(&oh_ent, H5O_STAB, H5O_NEW_MESG, 0, &stab)<0) { + if (H5O_modify(&oh_ent, H5O_STAB, H5O_NEW_MESG, 0, 1, &stab)<0) { H5_FAILED(); H5Eprint(stdout); goto error; diff --git a/test/tattr.c b/test/tattr.c index aea6287..e375ccf 100644 --- a/test/tattr.c +++ b/test/tattr.c @@ -100,7 +100,7 @@ test_attr_basic_write(void) hid_t attr, attr2; /* Attribute ID */ hsize_t attr_size; /* storage size for attribute */ ssize_t attr_name_size; /* size of attribute name */ - char *attr_name; /* name of attribute */ + char *attr_name=NULL; /* name of attribute */ hsize_t dims1[] = {SPACE1_DIM1, SPACE1_DIM2, SPACE1_DIM3}; hsize_t dims2[] = {ATTR1_DIM1}; hsize_t dims3[] = {ATTR2_DIM1,ATTR2_DIM2}; @@ -121,6 +121,7 @@ test_attr_basic_write(void) /* Create a dataset */ dataset=H5Dcreate(fid1,"Dataset1",H5T_NATIVE_UCHAR,sid1,H5P_DEFAULT); + CHECK(dataset, FAIL, "H5Dcreate"); /* Create dataspace for attribute */ sid2 = H5Screate_simple(ATTR1_RANK, dims2, NULL); @@ -161,7 +162,7 @@ test_attr_basic_write(void) /* Verify values read in */ for(i=0; i=0) { + num_errs++; + printf("%d: string comparison incorrect!\n",__LINE__); + } /* end if */ + + /* Check the lengths of the strings also */ + len=H5RS_len(rs1); + VERIFY(len, 3, "H5RS_len"); + len=H5RS_len(rs2); + VERIFY(len, 4, "H5RS_len"); + + /* Decrement reference count for strings */ + ret=H5RS_decr(rs2); + CHECK(ret, FAIL, "H5RS_decr"); + ret=H5RS_decr(rs1); + CHECK(ret, FAIL, "H5RS_decr"); + +} /* end test_refstr_cmp() */ + +/**************************************************************** +** +** test_refstr_wrap(): Test basic H5RS (ref-counted strings) code. +** Tests wrapping ref-counted strings around existing strings. +** +****************************************************************/ +static void +test_refstr_wrap(void) +{ + H5RS_str_t *rs; /* Ref-counted string created */ + const char *s; /* Pointer to raw string in ref-counted string */ + char buf[16]; /* Buffer to wrap */ + int cmp; /* Comparison value */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(5, ("Testing Wrapping Ref-Counted Strings\n")); + + /* Initialize buffer */ + HDstrcpy(buf,"foo"); + + /* Wrap ref-counted string around existing buffer */ + rs=H5RS_wrap(buf); + CHECK(rs, NULL, "H5RS_wrap"); + + /* Get pointer to raw string in ref-counted string */ + s=H5RS_GET_STR(rs); + CHECK(s, NULL, "H5RS_GET_STR"); + VERIFY(s, buf, "wrapping"); + cmp=HDstrcmp(s,buf); + VERIFY(cmp, 0, "HDstrcmp"); + + /* Increment reference count (should duplicate string) */ + ret=H5RS_incr(rs); + CHECK(ret, FAIL, "H5RS_incr"); + + /* Change the buffer initially wrapped */ + buf[0]='F'; + + /* Get pointer to raw string in ref-counted string */ + s=H5RS_GET_STR(rs); + CHECK(s, NULL, "H5RS_GET_STR"); + CHECK(s, buf, "wrapping"); + cmp=HDstrcmp(s,buf); + if(cmp<=0) { + num_errs++; + printf("%d: string comparison incorrect!\n",__LINE__); + } /* end if */ + + /* Decrement reference count for string */ + ret=H5RS_decr(rs); + CHECK(ret, FAIL, "H5RS_decr"); + ret=H5RS_decr(rs); + CHECK(ret, FAIL, "H5RS_decr"); + +} /* end test_refstr_wrap() */ + +/**************************************************************** +** +** test_refstr_own(): Test basic H5RS (ref-counted strings) code. +** Tests transferring ownership of dynamically allocated strings +** to ref-counted strings. +** +****************************************************************/ +static void +test_refstr_own(void) +{ + H5RS_str_t *rs; /* Ref-counted string created */ + char *s; /* Pointer to string to transfer */ + const char *t; /* Temporary pointers to string */ + int cmp; /* Comparison value */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(5, ("Testing Transferring Ref-Counted Strings\n")); + + /* Initialize buffer */ + s = H5FL_BLK_MALLOC(str_buf,HDstrlen("foo") + 1); + HDstrcpy(s, "foo"); + + /* Transfer ownership of dynamically allocated string to ref-counted string */ + rs=H5RS_own(s); + CHECK(rs, NULL, "H5RS_own"); + + /* Get pointer to raw string in ref-counted string */ + t=H5RS_GET_STR(rs); + CHECK(t, NULL, "H5RS_GET_STR"); + VERIFY(t, s, "transferring"); + cmp=HDstrcmp(s,t); + VERIFY(cmp, 0, "HDstrcmp"); + + /* Increment reference count (should NOT duplicate string) */ + ret=H5RS_incr(rs); + CHECK(ret, FAIL, "H5RS_incr"); + + /* Change the buffer initially wrapped */ + *s='F'; + + /* Get pointer to raw string in ref-counted string */ + t=H5RS_GET_STR(rs); + CHECK(t, NULL, "H5RS_GET_STR"); + VERIFY(t, s, "transferring"); + cmp=HDstrcmp(t,s); + VERIFY(cmp, 0, "HDstrcmp"); + + /* Decrement reference count for string */ + ret=H5RS_decr(rs); + CHECK(ret, FAIL, "H5RS_decr"); + ret=H5RS_decr(rs); + CHECK(ret, FAIL, "H5RS_decr"); + +} /* end test_refstr_own() */ + +/**************************************************************** +** +** test_refstr_finalize(): Test basic H5RS (ref-counted strings) code. +** Wrap up data for ref-counted string testing +** +****************************************************************/ +static void +test_refstr_finalize(void) +{ +} /* end test_refstr_finalize() */ + +/**************************************************************** +** +** test_refstr(): Main H5RS testing routine. +** +****************************************************************/ +void +test_refstr(void) +{ + /* Output message about test being performed */ + MESSAGE(5, ("Testing Reference Counted Strings\n")); + + /* Initialize ref-counted strings testing data */ + test_refstr_init(); + + /* Actual ref-counted strings tests */ + test_refstr_create(); /* Test ref-counted string creation */ + test_refstr_count(); /* Test ref-counted string counting */ + test_refstr_dup(); /* Test ref-counted string duplication */ + test_refstr_cmp(); /* Test ref-counted string comparison */ + test_refstr_wrap(); /* Test ref-counted string wrapping */ + test_refstr_own(); /* Test ref-counted string ownership transfer */ + + /* Finalize ref-counted strings testing data */ + test_refstr_finalize(); +} /* end test_refstr() */ + diff --git a/test/ttst.c b/test/ttst.c new file mode 100644 index 0000000..eb9ebef --- /dev/null +++ b/test/ttst.c @@ -0,0 +1,400 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + FILE + tst.c + Test HDF Ternary Search Tree (tst) routines. + + REMARKS + + DESIGN + + BUGS/LIMITATIONS + + EXPORTED ROUTINES + + AUTHOR + Quincey Koziol + + MODIFICATION HISTORY + 12/9/02 - Started coding + */ + +#include + +#include "testhdf5.h" +#include "H5STprivate.h" + +/* Test words to insert into s TST */ +static const char *words[]={ + "We", "hold", "these", "truths", "to", "be", "self-evident,", "that", + "all", "men", "are", "created", "equal,", "that", "they", "are", "endowed", + "by", "their", "Creator", "with", "certain", "unalienable", "Rights,", + "that", "among", "these", "are", "Life,", "Liberty", "and", "the", + "pursuit", "of", "Happiness." +}; +/* Number of words in test words set */ +size_t num_words; + +/* Number of unique words in test word set */ +size_t num_uniq_words; +/* Unique words in test word set */ +char **uniq_words; +/* Randomized order version of words in test word set */ +char **rand_uniq_words; +/* Sorted order version of words in test word set */ +char **sort_uniq_words; + +static int tst_strcmp(const void *_s1, const void *_s2) +{ + return(HDstrcmp(*(const char **)_s1,*(const char **)_s2)); +} + +/**************************************************************** +** +** test_tst_init(): Test basic H5ST (ternary search tree) selection code. +** Initialize data for TST testing +** +****************************************************************/ +static void +test_tst_init(void) +{ + time_t curr_time; /* Current time, for seeding random number generator */ + char *tmp_word=NULL;/* Temporary pointer to word in word set */ + size_t u,v,w; /* Local index variables */ + + /* Compute the number of words in the test set */ + num_words=sizeof(words)/sizeof(words[0]); + + /* Determine the number of unique words in test set */ + /* (Not particularly efficient, be careful if many words are added to set) */ + num_uniq_words=0; + for(u=0; ueqkid,uniq_words[u])) { + num_errs++; + printf("%d: TST node values don't match!, found->eqkid=%s, uniq_words[%u]=%s\n",__LINE__,(char *)found->eqkid,(unsigned)u,uniq_words[u]); + } /* end if */ + + obj=H5ST_locate(tree,uniq_words[u]); + CHECK(obj, NULL, "H5ST_locate"); + + if(HDstrcmp((const char *)obj,uniq_words[u])) { + num_errs++; + printf("%d: TST objects don't match!, obj=%s, uniq_words[%u]=%s\n",__LINE__,(char *)obj,(unsigned)u,uniq_words[u]); + } /* end if */ + } /* end for */ + + /* Verify that words not in the TST aren't found */ + check=H5ST_search(tree,"foo"); + VERIFY(check, FALSE, "H5ST_search"); + check=H5ST_search(tree,"bar"); + VERIFY(check, FALSE, "H5ST_search"); + check=H5ST_search(tree,"baz"); + VERIFY(check, FALSE, "H5ST_search"); + + /* Close the TST */ + ret=H5ST_close(tree); + CHECK(ret, FAIL, "H5ST_close"); +} /* end test_tst_insert() */ + +/**************************************************************** +** +** test_tst_iterate(): Test basic H5ST (ternary search tree) code. +** Tests iterating through key/value pairs in TST +** +****************************************************************/ +static void +test_tst_iterate(void) +{ + H5ST_tree_t *tree; /* TST created */ + H5ST_ptr_t found; /* Pointer to TST node found */ + size_t u; /* Local index counter */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(5, ("Testing Iterating Over TSTs\n")); + + /* Create the TST */ + tree=H5ST_create(); + CHECK(tree, NULL, "H5ST_create"); + + /* Insert unique words into TST, in random order */ + for(u=0; ueqkid,sort_uniq_words[u])) { + num_errs++; + printf("%d: TST node values don't match!, found->eqkid=%s, sort_uniq_words[%u]=%s\n",__LINE__,(char *)found->eqkid,(unsigned)u,sort_uniq_words[u]); + } /* end if */ + + /* Advance to next string in TST */ + found=H5ST_findnext(found); + u++; + } while(found!=NULL); + + /* Close the TST */ + ret=H5ST_close(tree); + CHECK(ret, FAIL, "H5ST_close"); +} /* end test_tst_iterate() */ + +/**************************************************************** +** +** test_tst_remove(): Test basic H5ST (ternary search tree) code. +** Tests removing key/value pairs by string value in TST +** +****************************************************************/ +static void +test_tst_remove(void) +{ + H5ST_tree_t *tree; /* TST created */ + H5ST_ptr_t found; /* Pointer to TST node found */ + void *obj; /* Pointer to object removed from TST */ + htri_t check; /* Is string in TST? */ + size_t u; /* Local index counter */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(5, ("Testing Removing String Values from TSTs\n")); + + /* Create the TST */ + tree=H5ST_create(); + CHECK(tree, NULL, "H5ST_create"); + + /* Insert unique words into TST, in random order */ + for(u=0; ueqkid,rand_uniq_words[u])) { + num_errs++; + printf("%d: TST node values don't match!, found->eqkid=%s, rand_uniq_words[%u]=%s\n",__LINE__,(char *)found->eqkid,(unsigned)u,rand_uniq_words[u]); + } /* end if */ + + /* Remove the node */ + ret=H5ST_delete(tree,found); + CHECK(ret, FAIL, "H5ST_delete"); + + /* Check that the string can't be found in the TST any longer */ + check=H5ST_search(tree,rand_uniq_words[u]); + VERIFY(check, FALSE, "H5ST_search"); + } /* end for */ + + /* Close the TST */ + ret=H5ST_close(tree); + CHECK(ret, FAIL, "H5ST_close"); +} /* end test_tst_remove() */ + +/**************************************************************** +** +** test_tst_finalize(): Test basic H5ST (ternary search tree) selection code. +** Wrap up data for TST testing +** +****************************************************************/ +static void +test_tst_finalize(void) +{ + /* Release memory for unordered, randomized and sorted order unique words */ + HDfree(uniq_words); + HDfree(rand_uniq_words); + HDfree(sort_uniq_words); +} /* end test_tst_finalize() */ + +/**************************************************************** +** +** test_tst(): Main H5ST selection testing routine. +** +****************************************************************/ +void +test_tst(void) +{ + /* Output message about test being performed */ + MESSAGE(5, ("Testing Ternary Search Trees\n")); + + /* Initialize TST testing data */ + test_tst_init(); + + /* Actual TST tests */ + test_tst_create(); /* Test TST creation */ + test_tst_insert(); /* Test TST insertion */ + test_tst_iterate(); /* Test TST iteration */ + test_tst_remove(); /* Test TST deletion */ + + /* Finalize TST testing data */ + test_tst_finalize(); +} /* end test_tst() */ + diff --git a/test/tvlstr.c b/test/tvlstr.c index cd15fa8..a8cbd84 100644 --- a/test/tvlstr.c +++ b/test/tvlstr.c @@ -256,17 +256,12 @@ test_vlstrings_special(void) const char *wdata[SPACE1_DIM1] = {"one", "two", "", "four"}; const char *wdata2[SPACE1_DIM1] = {NULL, NULL, NULL, NULL}; char *rdata[SPACE1_DIM1]; /* Information read in */ - hid_t dataspace, dataset2; hid_t fid1; /* HDF5 File IDs */ hid_t dataset; /* Dataset ID */ hid_t sid1; /* Dataspace ID */ hid_t tid1; /* Datatype ID */ - hid_t xfer_pid; /* Dataset transfer property list ID */ hsize_t dims1[] = {SPACE1_DIM1}; - hsize_t size; /* Number of bytes which will be used */ unsigned i; /* counting variable */ - int str_used; /* String data in memory */ - int mem_used=0; /* Memory used during allocation */ herr_t ret; /* Generic return value */ /* Output message about test being performed */ @@ -313,6 +308,10 @@ test_vlstrings_special(void) } /* end if */ } /* end for */ + /* Reclaim the read VL data */ + ret=H5Dvlen_reclaim(tid1,sid1,H5P_DEFAULT,rdata); + CHECK(ret, FAIL, "H5Dvlen_reclaim"); + /* Close Dataset */ ret = H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); diff --git a/tools/h5dump/h5dump.c b/tools/h5dump/h5dump.c index c1abc13..9ec4cbd 100644 --- a/tools/h5dump/h5dump.c +++ b/tools/h5dump/h5dump.c @@ -4595,7 +4595,7 @@ xml_print_strs(hid_t did, int source) hid_t type, space; void *buf; char *bp; - char *onestring; + char *onestring=NULL; hsize_t ssiz; size_t tsiz, str_size; size_t i; diff --git a/tools/h5dump/h5dumpgentest.c b/tools/h5dump/h5dumpgentest.c index f0e9515..593dc8d 100644 --- a/tools/h5dump/h5dumpgentest.c +++ b/tools/h5dump/h5dumpgentest.c @@ -2850,7 +2850,7 @@ static void gent_vlstr(void) "Now we are engaged in a great civil war,", "testing whether that nation or any nation so conceived and so dedicated can long endure." }; /* Information to write */ - char *string_att= "This is the string for the attribute"; + const char *string_att= "This is the string for the attribute"; hid_t fid1; /* HDF5 File IDs */ hid_t dataset, root; /* Dataset ID */ hid_t sid1, dataspace;/* Dataspace ID */ -- cgit v0.12