From b4c5e3e00965f4ba6bd6b865cbde3bd33fcdbe47 Mon Sep 17 00:00:00 2001 From: Robb Matzke Date: Thu, 4 Jun 1998 17:27:11 -0500 Subject: [svn-r407] ./src/H5A.c ./src/H5D.c ./src/H5Tconv.c ./src/H5detect.c Updated to work with new internal H5T functions. Fixed some data type memory leaks during error recovery. ./src/H5Dprivate.h Added H5D_typeof() similar to H5D_entof() that returns a pointer directly to the dataset's type. This is used by H5Tcopy() when invoked on a dataset (see below). ./src/H5Epublic.h Fixed typos in H5E_BEGIN_TRY and H5E_END_TRY macros. ./src/H5F.c Closing a file with objects still open reports the file name in the warning message. Removed unnecessary invalidation of shared data types. ./src/H5Gent.c ./src/H5Gpkg.h ./src/H5Gprivate.h Added `const' to some arguments. ./src/H5O.c ./src/H5Oprivate.h ./src/H5Oshared.c An object header message can now be a pointer to a message in some other object header. The pointer is to the first message of the appropriate type in the other object header and hard link counts are maintained automatically to prevent dangling pointers. The old global heap method of message sharing is also supported although nothing actually uses it. ./src/H5Oattr.c ./src/H5Ocomp.c ./src/H5Ocont.c ./src/H5Odtype.c ./src/H5Oefl.c ./src/H5Olayout.c ./src/H5Oname.c ./src/H5Osdspace.c ./src/H5Oshare.c ./src/H5Ostab.c Changed the data type for the shared message info struct to H5O_shared_t and added an extra initializer to the class methods struct for the set_share method. ./src/H5Odtype.c Added the ability to share data type messages by pointing to other object headers. ./src/H5T.c ./src/H5Tpkg.h ./src/H5Tprivate.h ./src/H5Tpublic.h Added named data types and changed the functionality of some API functions as follows: * The term `read-only' means that a type handle cannot be modified with functions like H5Tset_*() or H5Tinsert(). * The term `immutable' means the same as `read-only' with the added restriction that H5Tclose() cannot be called for the type. A transient type is made immutable by calling H5Tlock(). * Handles to named types are always read-only. * Handles to predefined types are immutable. * A transient type can be converted to a named type by calling H5Tcommit(). This function will fail if the type is already named or is immutable. * The API function H5Tcommitted() returns an indication of whether a data type has been commited (or is named). If H5Tcommitted() returns TRUE for a data type obtained by calling H5Dget_type() on a dataset, then the dataset is using a shared data type. * H5Topen() returns a handle to a named type. * H5Tcopy() always returns a handle to a modifiable transient type even when invoked on a named type. Also, when invoked on a dataset it returns a modifiable transient type which is a copy of the dataset's data type. * Using a named data type in the call to H5Dcreate() causes the dataset object header to point to the named data type, but using a transient type causes the type to be copied into the dataset's object header. * The data type returned from H5Dget_type() is a named data type or a read-only transient data type depending on whether the dataset points to a named data type. The old behavior, to return a modifiable transient type, is accomplished by overloading H5Tcopy() to operate on datasets (see above). * H5Tshare(), H5Tunshare(), and H5Tis_shared() have been removed from the API. The following features were *not* implemented because they need more discussion: * A named data type can be opened by applying H5Topen() to a dataset in which case the data type is the data type of the dataset (or the data type to which the dataset points if the dataset has a shared data type). * A named data type can have attributes like groups or datasets. * The members of a compound data type can point to named data types. ./src/h5ls.c Reports `Data type' for named data type objects in the file. --- src/H5A.c | 32 ++- src/H5D.c | 123 ++++++--- src/H5Dprivate.h | 1 + src/H5Epublic.h | 8 +- src/H5F.c | 6 +- src/H5Gent.c | 6 +- src/H5Gpkg.h | 3 +- src/H5Gprivate.h | 6 +- src/H5O.c | 93 +++++-- src/H5Oattr.c | 13 +- src/H5Ocomp.c | 8 +- src/H5Ocont.c | 27 +- src/H5Odtype.c | 97 ++++--- src/H5Oefl.c | 27 +- src/H5Olayout.c | 27 +- src/H5Oname.c | 28 +- src/H5Oprivate.h | 14 +- src/H5Osdspace.c | 27 +- src/H5Oshared.c | 62 +++-- src/H5Ostab.c | 27 +- src/H5T.c | 771 ++++++++++++++++++++++++++++++++++--------------------- src/H5Tconv.c | 5 +- src/H5Tpkg.h | 14 +- src/H5Tprivate.h | 14 +- src/H5Tpublic.h | 5 +- src/H5detect.c | 3 +- src/h5ls.c | 3 + 27 files changed, 924 insertions(+), 526 deletions(-) diff --git a/src/H5A.c b/src/H5A.c index d9ba963..fbce35e 100644 --- a/src/H5A.c +++ b/src/H5A.c @@ -237,7 +237,7 @@ H5A_create(const H5G_entry_t *ent, const char *name, const H5T_t *type, const H5 HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate space for attribute info"); attr->name=HDstrdup(name); - attr->dt=H5T_copy(type); + attr->dt=H5T_copy(type, H5T_COPY_ALL); attr->ds=H5S_copy(space); attr->initialized = TRUE; /*for now, set to false later*/ @@ -638,8 +638,10 @@ H5A_write(H5A_t *attr, const H5T_t *mem_type, void *buf) HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types"); } else if (H5T_conv_noop!=tconv_func) { - if ((src_id = H5I_register(H5_DATATYPE, H5T_copy(mem_type)))<0 || - (dst_id = H5I_register(H5_DATATYPE, H5T_copy(attr->dt)))<0) { + if ((src_id = H5I_register(H5_DATATYPE, + H5T_copy(mem_type, H5T_COPY_ALL)))<0 || + (dst_id = H5I_register(H5_DATATYPE, + H5T_copy(attr->dt, H5T_COPY_ALL)))<0) { HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, FAIL, "unable to register types for conversion"); } @@ -803,8 +805,10 @@ H5A_read(H5A_t *attr, const H5T_t *mem_type, void *buf) HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types"); } else if (H5T_conv_noop!=tconv_func) { - if ((src_id = H5I_register(H5_DATATYPE, H5T_copy(attr->dt)))<0 || - (dst_id = H5I_register(H5_DATATYPE, H5T_copy(mem_type)))<0) { + if ((src_id = H5I_register(H5_DATATYPE, + H5T_copy(attr->dt, H5T_COPY_ALL)))<0 || + (dst_id = H5I_register(H5_DATATYPE, + H5T_copy(mem_type, H5T_COPY_ALL)))<0) { HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, FAIL, "unable to register types for conversion"); } @@ -908,6 +912,14 @@ H5Aget_space(hid_t attr_id) This function retrieves a copy of the datatype for an attribute. The datatype ID returned from this function must be released with H5Tclose or resource leaks will develop. + * + * Modifications: + * Robb Matzke, 4 Jun 1998 + * The data type is reopened if it's a named type before returning it to + * the application. If the data type of the attribute is read-only then + * it is returned to the application as a read-only type. If an error + * occurs when atomizing the return data type then the data type is + * closed. --------------------------------------------------------------------------*/ hid_t H5Aget_type(hid_t attr_id) @@ -924,14 +936,18 @@ H5Aget_type(hid_t attr_id) HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute"); } - /* Copy the attribute's dataspace */ - if (NULL==(dst=H5T_copy (attr->dt))) { + /* + * Copy the attribute's data type. If the type is a named type then + * reopen the type before returning it to the user. + */ + if (NULL==(dst=H5T_copy (attr->dt, H5T_COPY_REOPEN))) { HRETURN_ERROR (H5E_ATTR, H5E_CANTINIT, FAIL, "unable to copy datatype"); } /* Atomize */ if ((ret_value=H5I_register (H5_DATATYPE, dst))<0) { + H5T_close (dst); HRETURN_ERROR (H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register datatype atom"); } @@ -1278,7 +1294,7 @@ H5A_copy(const H5A_t *old_attr) /* Copy the guts of the attribute */ new_attr->name=HDstrdup(old_attr->name); - new_attr->dt=H5T_copy(old_attr->dt); + new_attr->dt=H5T_copy(old_attr->dt, H5T_COPY_ALL); new_attr->ds=H5S_copy(old_attr->ds); if(old_attr->data) { new_attr->data=H5MM_xmalloc(old_attr->data_size); diff --git a/src/H5D.c b/src/H5D.c index ea0eb38..7c8783d 100644 --- a/src/H5D.c +++ b/src/H5D.c @@ -393,6 +393,11 @@ H5Dget_space (hid_t dataset_id) * * Modifications: * + * Robb Matzke, 1 Jun 1998 + * If the dataset has a named data type then a handle to the opened data + * type is returned. Otherwise the returned data type is read-only. If + * atomization of the data type fails then the data type is closed. + * *------------------------------------------------------------------------- */ hid_t @@ -411,20 +416,27 @@ H5Dget_type (hid_t dataset_id) HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset"); } - /* Copy the data type */ - if (NULL==(copied_type=H5T_copy (dataset->type))) { + /* Copy the data type and mark it read-only */ + if (NULL==(copied_type=H5T_copy (dataset->type, H5T_COPY_REOPEN))) { HRETURN_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to copy the data type"); } - + if (H5T_lock (copied_type, FALSE)<0) { + H5T_close (copied_type); + HRETURN_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, + "unable to lock transient data type"); + } + /* Create an atom */ if ((ret_value=H5I_register (H5_DATATYPE, copied_type))<0) { + H5T_close (copied_type); HRETURN_ERROR (H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register data type"); } FUNC_LEAVE (ret_value); } + /*------------------------------------------------------------------------- * Function: H5Dget_create_plist @@ -758,7 +770,7 @@ H5D_create(H5G_t *loc, const char *name, const H5T_t *type, const H5S_t *space, /* Initialize the dataset object */ new_dset = H5MM_xcalloc(1, sizeof(H5D_t)); H5F_addr_undef(&(new_dset->ent.header)); - new_dset->type = H5T_copy(type); + new_dset->type = H5T_copy(type, H5T_COPY_ALL); new_dset->space = H5S_copy(space); new_dset->create_parms = H5P_copy (H5P_DATASET_CREATE, create_parms); efl = &(new_dset->create_parms->efl); @@ -781,35 +793,37 @@ H5D_create(H5G_t *loc, const char *name, const H5T_t *type, const H5S_t *space, "unable to initialize contiguous storage"); } - /* Don't go through all these checks for scalar dataspaces */ - if(ndims>0) { - 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 (H5S_UNLIMITED==max_points) { - if (H5O_EFL_UNLIMITED!=max_storage) { - HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, NULL, - "unlimited data space but finite storage"); - } - } else if (max_points * H5T_get_size (type) < max_points) { - HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, NULL, - "data space * type size overflowed"); - } else if (max_points * H5T_get_size (type) > max_storage) { - HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, NULL, - "data space size exceeds external storage size"); - } - } else if (max_dim[0]>new_dset->layout.dim[0]) { - HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, NULL, - "extendible contiguous non-external dataset"); - } - } + /* Don't go through all these checks for scalar dataspaces */ + if(ndims>0) { + 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 (H5S_UNLIMITED==max_points) { + if (H5O_EFL_UNLIMITED!=max_storage) { + HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, NULL, + "unlimited data space but finite " + "storage"); + } + } else if (max_points * H5T_get_size (type) < max_points) { + HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, NULL, + "data space * type size overflowed"); + } else if (max_points * H5T_get_size (type) > max_storage) { + HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, NULL, + "data space size exceeds external storage " + "size"); + } + } else if (max_dim[0]>new_dset->layout.dim[0]) { + HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, NULL, + "extendible contiguous non-external dataset"); + } + } break; case H5D_CHUNKED: @@ -842,8 +856,7 @@ H5D_create(H5G_t *loc, const char *name, const H5T_t *type, const H5S_t *space, /* Update the type and space header messages */ if (H5O_modify(&(new_dset->ent), H5O_DTYPE, 0, - (H5O_FLAG_CONSTANT|H5O_FLAG_SHARED), - new_dset->type) < 0 || + H5O_FLAG_CONSTANT|H5O_FLAG_SHARED, new_dset->type)<0 || H5S_modify(&(new_dset->ent), new_dset->space) < 0) { HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to update type or space header messages"); @@ -1215,8 +1228,10 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types"); } else if (H5T_conv_noop!=tconv_func) { - if ((src_id=H5I_register(H5_DATATYPE, H5T_copy(dataset->type)))<0 || - (dst_id=H5I_register(H5_DATATYPE, H5T_copy(mem_type)))<0) { + if ((src_id=H5I_register(H5_DATATYPE, + H5T_copy(dataset->type, H5T_COPY_ALL)))<0 || + (dst_id=H5I_register(H5_DATATYPE, + H5T_copy(mem_type, H5T_COPY_ALL)))<0) { HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register types for conversion"); } @@ -1520,8 +1535,10 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types"); } else if (H5T_conv_noop!=tconv_func) { - if ((src_id = H5I_register(H5_DATATYPE, H5T_copy(mem_type)))<0 || - (dst_id = H5I_register(H5_DATATYPE, H5T_copy(dataset->type)))<0) { + if ((src_id = H5I_register(H5_DATATYPE, + H5T_copy(mem_type, H5T_COPY_ALL)))<0 || + (dst_id = H5I_register(H5_DATATYPE, + H5T_copy(dataset->type, H5T_COPY_ALL)))<0) { HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register types for conversion"); } @@ -1793,3 +1810,31 @@ H5D_entof (H5D_t *dataset) { return dataset ? &(dataset->ent) : NULL; } + + +/*------------------------------------------------------------------------- + * Function: H5D_typeof + * + * Purpose: Returns a pointer to the dataset's data type. The data type + * is not copied. + * + * Return: Success: Ptr to the dataset's data type, uncopied. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * Thursday, June 4, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +H5T_t * +H5D_typeof (H5D_t *dset) +{ + FUNC_ENTER (H5D_typeof, NULL); + assert (dset); + assert (dset->type); + FUNC_LEAVE (dset->type); +} + diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h index f144d30..3ed4e2f 100644 --- a/src/H5Dprivate.h +++ b/src/H5Dprivate.h @@ -78,5 +78,6 @@ herr_t H5D_write (H5D_t *dataset, const H5T_t *mem_type, hid_t H5D_find_name (hid_t file_id, H5I_group_t UNUSED, const char *name); herr_t H5D_extend (H5D_t *dataset, const hsize_t *size); H5G_entry_t *H5D_entof (H5D_t *dataset); +H5T_t *H5D_typeof (H5D_t *dset); #endif diff --git a/src/H5Epublic.h b/src/H5Epublic.h index 85c7b60..96ca600 100644 --- a/src/H5Epublic.h +++ b/src/H5Epublic.h @@ -31,20 +31,20 @@ * like: * H5E_BEGIN_TRY { * ...stuff here that's likely to fail... - * } H5E_END_TRY + * } H5E_END_TRY; * * Warning: don't break, return, or longjmp() from the body of the loop or * the error reporting won't be properly restored! */ -#define H5T_BEGIN_TRY do { \ +#define H5E_BEGIN_TRY do { \ herr_t (*H5E_saved_efunc)(void*); \ void *H5E_saved_edata; \ H5Eget_auto (&H5E_saved_efunc, &H5E_saved_edata); \ H5Eset_auto (NULL, NULL); -#define H5T_END_TRY \ +#define H5E_END_TRY \ H5Eset_auto (H5E_saved_efunc, H5E_saved_edata); \ -} +} while(0) /* diff --git a/src/H5F.c b/src/H5F.c index 78d70b3..7d2b619 100644 --- a/src/H5F.c +++ b/src/H5F.c @@ -1384,8 +1384,9 @@ H5F_close(H5F_t *f) */ if (f->nopen>0) { #ifndef NDEBUG - fprintf(stderr, "H5F: H5F_close: %u object header%s still " + fprintf(stderr, "H5F: H5F_close(%s): %u object header%s still " "open (file close will complete when %s closed)\n", + f->name, f->nopen, 1 == f->nopen ? " is" : "s are", 1 == f->nopen ? "that header is" : "those headers are"); @@ -1398,9 +1399,6 @@ H5F_close(H5F_t *f) #endif } - /* Invalidate shared data types since they depend on the H5F_t pointer */ - H5I_search (H5_DATATYPE, H5T_invalidate_cb, f); - /* * If this is the last reference to the shared part of the file then * close it also. diff --git a/src/H5Gent.c b/src/H5Gent.c index 1bcd18f..b2120c0 100644 --- a/src/H5Gent.c +++ b/src/H5Gent.c @@ -240,7 +240,7 @@ H5G_ent_decode(H5F_t *f, const uint8 **pp, H5G_entry_t *ent) *------------------------------------------------------------------------- */ herr_t -H5G_ent_encode_vec(H5F_t *f, uint8 **pp, H5G_entry_t *ent, intn n) +H5G_ent_encode_vec(H5F_t *f, uint8 **pp, const H5G_entry_t *ent, intn n) { intn i; @@ -288,7 +288,7 @@ H5G_ent_encode_vec(H5F_t *f, uint8 **pp, H5G_entry_t *ent, intn n) *------------------------------------------------------------------------- */ herr_t -H5G_ent_encode(H5F_t *f, uint8 **pp, H5G_entry_t *ent) +H5G_ent_encode(H5F_t *f, uint8 **pp, const H5G_entry_t *ent) { uint8 *p_ret = *pp + H5G_SIZEOF_ENTRY(f); @@ -358,7 +358,7 @@ H5G_ent_encode(H5F_t *f, uint8 **pp, H5G_entry_t *ent) *------------------------------------------------------------------------- */ herr_t -H5G_ent_debug(H5F_t __unused__ *f, H5G_entry_t *ent, FILE * stream, +H5G_ent_debug(H5F_t __unused__ *f, const H5G_entry_t *ent, FILE * stream, intn indent, intn fwidth, const haddr_t *heap) { const char *lval = NULL; diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h index 38e07ed..c4579be 100644 --- a/src/H5Gpkg.h +++ b/src/H5Gpkg.h @@ -130,5 +130,6 @@ herr_t H5G_stab_insert (H5G_entry_t *grp_ent, const char *name, */ herr_t H5G_ent_decode_vec (H5F_t *f, const uint8 **pp, H5G_entry_t *ent, intn n); -herr_t H5G_ent_encode_vec (H5F_t *f, uint8 **pp, H5G_entry_t *ent, intn n); +herr_t H5G_ent_encode_vec (H5F_t *f, uint8 **pp, const H5G_entry_t *ent, + intn n); #endif diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h index bbb2a1c..f6a641e 100644 --- a/src/H5Gprivate.h +++ b/src/H5Gprivate.h @@ -122,7 +122,7 @@ herr_t H5G_find (H5G_t *cwg, const char *name, H5G_entry_t *grp_ent/*out*/, herr_t H5G_traverse_slink (H5G_entry_t *grp_ent/*in,out*/, H5G_entry_t *obj_ent/*in,out*/, intn *nlinks/*in,out*/); -herr_t H5G_ent_encode (H5F_t *f, uint8 **pp, H5G_entry_t *ent); +herr_t H5G_ent_encode (H5F_t *f, uint8 **pp, const H5G_entry_t *ent); herr_t H5G_ent_decode (H5F_t *f, const uint8 **pp, H5G_entry_t *ent/*out*/); /* @@ -139,7 +139,7 @@ herr_t H5G_node_debug (H5F_t *f, const haddr_t *addr, FILE * stream, H5G_entry_t *H5G_ent_calloc (H5G_entry_t *init); H5G_cache_t *H5G_ent_cache (H5G_entry_t *ent, H5G_type_t *cache_type); herr_t H5G_ent_modified (H5G_entry_t *ent, H5G_type_t cache_type); -herr_t H5G_ent_debug (H5F_t *f, H5G_entry_t *ent, FILE * stream, intn indent, - intn fwidth, const haddr_t *heap); +herr_t H5G_ent_debug (H5F_t *f, const H5G_entry_t *ent, FILE * stream, + intn indent, intn fwidth, const haddr_t *heap); #endif diff --git a/src/H5O.c b/src/H5O.c index ce369cf..cb625c0 100644 --- a/src/H5O.c +++ b/src/H5O.c @@ -916,27 +916,37 @@ H5O_read(H5G_entry_t *ent, const H5O_class_t *type, intn sequence, void *mesg) /* * If the message is shared then then the native pointer points to an * H5O_SHARED message. We use that information to look up the real - * message in the global heap. + * message in the global heap or some other object header. */ H5O_shared_t *shared; void *tmp_buf, *tmp_mesg; shared = (H5O_shared_t *)(oh->mesg[idx].native); - if (NULL==(tmp_buf = H5HG_read (ent->file, shared, NULL))) { - HGOTO_ERROR (H5E_OHDR, H5E_CANTLOAD, NULL, - "unable to read shared message from global heap"); - } - tmp_mesg = (type->decode)(ent->file, tmp_buf, shared); - tmp_buf = H5MM_xfree (tmp_buf); - if (!tmp_mesg) { - HGOTO_ERROR (H5E_OHDR, H5E_CANTLOAD, NULL, - "unable to decode object header shared message"); - } - if (mesg) { - HDmemcpy (mesg, tmp_mesg, type->native_size); - H5MM_xfree (tmp_mesg); + if (shared->in_gh) { + if (NULL==(tmp_buf = H5HG_read (ent->file, &(shared->u.gh), + NULL))) { + HGOTO_ERROR (H5E_OHDR, H5E_CANTLOAD, NULL, + "unable to read shared message from global heap"); + } + tmp_mesg = (type->decode)(ent->file, tmp_buf, shared); + tmp_buf = H5MM_xfree (tmp_buf); + if (!tmp_mesg) { + HGOTO_ERROR (H5E_OHDR, H5E_CANTLOAD, NULL, + "unable to decode object header shared message"); + } + if (mesg) { + HDmemcpy (mesg, tmp_mesg, type->native_size); + H5MM_xfree (tmp_mesg); + } else { + ret_value = tmp_mesg; + } } else { - ret_value = tmp_mesg; + ret_value = H5O_read (&(shared->u.ent), type, 0, mesg); + if (type->set_share && + (type->set_share)(ent->file, ret_value, shared)<0) { + HGOTO_ERROR (H5E_OHDR, H5E_CANTINIT, NULL, + "unable to set sharing information"); + } } } else { /* @@ -1124,12 +1134,12 @@ H5O_modify(H5G_entry_t *ent, const H5O_class_t *type, intn overwrite, if (overwrite < 0) { /* Allocate space for the new message */ if (flags & H5O_FLAG_SHARED) { - if (NULL==type->share) { + if (NULL==type->get_share) { HGOTO_ERROR (H5E_OHDR, H5E_UNSUPPORTED, FAIL, "message class is not sharable"); } sh_mesg = H5MM_xcalloc (1, sizeof *sh_mesg); - if ((type->share)(ent->file, mesg, sh_mesg/*out*/)<0) { + if ((type->get_share)(ent->file, mesg, sh_mesg/*out*/)<0) { /* * If the message isn't shared then turn off the shared bit * and treat it as an unshared message. @@ -1137,8 +1147,22 @@ H5O_modify(H5G_entry_t *ent, const H5O_class_t *type, intn overwrite, H5E_clear (); flags &= ~H5O_FLAG_SHARED; H5MM_xfree (sh_mesg); + } 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 (ent->file, &(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)(ent->file, sh_mesg); } else { - if (H5HG_link (ent->file, sh_mesg, 1)<0) { + /* + * The shared message is stored in some other object header. + * Increment the reference count on that object header. + */ + if (H5O_link (&(sh_mesg->u.ent), 1)<0) { HGOTO_ERROR (H5E_OHDR, H5E_LINK, FAIL, "unable to adjust shared object link count"); } @@ -1269,10 +1293,18 @@ H5O_remove(H5G_entry_t *ent, const H5O_class_t *type, intn sequence) "unable to decode shared message info"); } } - if (H5HG_link (ent->file, sh_mesg, -1)<0) { - HGOTO_ERROR (H5E_OHDR, H5E_LINK, FAIL, - "unable to decrement link count on shared " - "message"); + if (sh_mesg->in_gh) { + if (H5HG_link (ent->file, &(sh_mesg->u.gh), -1)<0) { + HGOTO_ERROR (H5E_OHDR, H5E_LINK, FAIL, + "unable to decrement link count on " + "shared message"); + } + } else { + if (H5O_link (&(sh_mesg->u.ent), -1)<0) { + HGOTO_ERROR (H5E_OHDR, H5E_LINK, FAIL, + "unable to decrement link count on " + "shared message"); + } } } @@ -1526,7 +1558,8 @@ H5O_alloc_new_chunk(H5F_t *f, H5O_t *oh, size_t size) oh->mesg = H5MM_xrealloc(oh->mesg, oh->alloc_nmesgs * sizeof(H5O_mesg_t)); /* Set new object header info to zeros */ - HDmemset(&oh->mesg[old_alloc],0,(oh->alloc_nmesgs-old_alloc)*sizeof(H5O_mesg_t)); + HDmemset(&oh->mesg[old_alloc], 0, + (oh->alloc_nmesgs-old_alloc)*sizeof(H5O_mesg_t)); } /* @@ -1779,7 +1812,7 @@ H5O_debug(H5F_t *f, const haddr_t *addr, FILE * stream, intn indent, int *sequence; haddr_t tmp_addr; herr_t ret_value = FAIL; - void *(*decode)(H5F_t*, const uint8*, H5HG_t*); + void *(*decode)(H5F_t*, const uint8*, H5O_shared_t*); herr_t (*debug)(H5F_t*, const void*, FILE*, intn, intn)=NULL; FUNC_ENTER(H5O_debug, FAIL); @@ -1912,14 +1945,20 @@ H5O_debug(H5F_t *f, const haddr_t *addr, FILE * stream, intn indent, /* If the message is shared then also print the pointed-to message */ if (oh->mesg[i].flags & H5O_FLAG_SHARED) { - void *p = H5HG_read (f, oh->mesg[i].native, NULL); - void *mesg = (oh->mesg[i].type->decode)(f, p, oh->mesg[i].native); + H5O_shared_t *shared = (H5O_shared_t*)(oh->mesg[i].native); + void *mesg = NULL; + if (shared->in_gh) { + void *p = H5HG_read (f, oh->mesg[i].native, NULL); + mesg = (oh->mesg[i].type->decode)(f, p, oh->mesg[i].native); + H5MM_xfree (p); + } else { + mesg = H5O_read (&(shared->u.ent), oh->mesg[i].type, 0, NULL); + } if (oh->mesg[i].type->debug) { (oh->mesg[i].type->debug)(f, mesg, stream, indent+3, MAX (0, fwidth-3)); } H5O_free (oh->mesg[i].type, mesg); - H5MM_xfree (p); } } sequence = H5MM_xfree(sequence); diff --git a/src/H5Oattr.c b/src/H5Oattr.c index 320c713..2e56a75 100644 --- a/src/H5Oattr.c +++ b/src/H5Oattr.c @@ -29,24 +29,25 @@ static char RcsId[] = "@(#)$Revision$"; /* PRIVATE PROTOTYPES */ static herr_t H5O_attr_encode (H5F_t *f, uint8 *p, const void *mesg); -static void *H5O_attr_decode (H5F_t *f, const uint8 *p, H5HG_t *hobj); +static void *H5O_attr_decode (H5F_t *f, const uint8 *p, H5O_shared_t *sh); static void *H5O_attr_copy (const void *_mesg, void *_dest); static size_t H5O_attr_size (H5F_t *f, const void *_mesg); static herr_t H5O_attr_reset (void *_mesg); static herr_t H5O_attr_debug (H5F_t *f, const void *_mesg, - FILE * stream, intn indent, intn fwidth); + FILE * stream, intn indent, intn fwidth); /* This message derives from H5O */ const H5O_class_t H5O_ATTR[1] = {{ H5O_ATTR_ID, /* message id number */ "attribute", /* message name for debugging */ sizeof(H5A_t), /* native message size */ - H5O_attr_decode, /* decode message */ - H5O_attr_encode, /* encode message */ + H5O_attr_decode, /* decode message */ + H5O_attr_encode, /* encode message */ H5O_attr_copy, /* copy the native value */ H5O_attr_size, /* size of raw message */ H5O_attr_reset, /* reset method */ - NULL, /* no share method (currently) */ + NULL, /* get share method */ + NULL, /* set share method */ H5O_attr_debug, /* debug the message */ }}; @@ -73,7 +74,7 @@ static hbool_t interface_initialize_g = FALSE; function using malloc() and is returned to the caller. --------------------------------------------------------------------------*/ static void * -H5O_attr_decode(H5F_t *f, const uint8 *p, H5HG_t __unused__ *hobj) +H5O_attr_decode(H5F_t *f, const uint8 *p, H5O_shared_t __unused__ *sh) { H5A_t *attr = NULL; H5S_simple_t *simple; /*simple dimensionality information */ diff --git a/src/H5Ocomp.c b/src/H5Ocomp.c index 6b6c2e7..7d659ea 100644 --- a/src/H5Ocomp.c +++ b/src/H5Ocomp.c @@ -16,7 +16,7 @@ /* PRIVATE PROTOTYPES */ static herr_t H5O_comp_encode (H5F_t *f, uint8 *p, const void *mesg); -static void *H5O_comp_decode (H5F_t *f, const uint8 *p, H5HG_t *hobj); +static void *H5O_comp_decode (H5F_t *f, const uint8 *p, H5O_shared_t *sh); static void *H5O_comp_copy (const void *_mesg, void *_dest); static size_t H5O_comp_size (H5F_t *f, const void *_mesg); static herr_t H5O_comp_reset (void *_mesg); @@ -33,7 +33,8 @@ const H5O_class_t H5O_COMPRESS[1] = {{ H5O_comp_copy, /* copy the native value */ H5O_comp_size, /* size of raw message */ H5O_comp_reset, /* reset method */ - NULL, /* share method */ + NULL, /* get share method */ + NULL, /* set share method */ H5O_comp_debug, /* debug the message */ }}; @@ -59,7 +60,8 @@ static hbool_t interface_initialize_g = FALSE; *------------------------------------------------------------------------- */ static void * -H5O_comp_decode(H5F_t __unused__ *f, const uint8 *p, H5HG_t __unused__ *hobj) +H5O_comp_decode(H5F_t __unused__ *f, const uint8 *p, + H5O_shared_t __unused__ *sh) { H5O_compress_t *comp = NULL; diff --git a/src/H5Ocont.c b/src/H5Ocont.c index e9bda3e..ff81be9 100644 --- a/src/H5Ocont.c +++ b/src/H5Ocont.c @@ -25,23 +25,24 @@ #define PABLO_MASK H5O_cont_mask /* PRIVATE PROTOTYPES */ -static void *H5O_cont_decode(H5F_t *f, const uint8 *p, H5HG_t *hobj); +static void *H5O_cont_decode(H5F_t *f, const uint8 *p, H5O_shared_t *sh); static herr_t H5O_cont_encode(H5F_t *f, uint8 *p, const void *_mesg); static herr_t H5O_cont_debug(H5F_t *f, const void *_mesg, FILE * stream, intn indent, intn fwidth); /* This message derives from H5O */ const H5O_class_t H5O_CONT[1] = {{ - H5O_CONT_ID, /*message id number */ - "hdr continuation", /*message name for debugging */ - sizeof(H5O_cont_t), /*native message size */ - H5O_cont_decode, /*decode message */ - H5O_cont_encode, /*encode message */ - NULL, /*no copy method */ - NULL, /*no size method */ - NULL, /*default reset method */ - NULL, /*no share method */ - H5O_cont_debug, /*debugging */ + H5O_CONT_ID, /*message id number */ + "hdr continuation", /*message name for debugging */ + sizeof(H5O_cont_t), /*native message size */ + H5O_cont_decode, /*decode message */ + H5O_cont_encode, /*encode message */ + NULL, /*no copy method */ + NULL, /*no size method */ + NULL, /*default reset method */ + NULL, /*get share method */ + NULL, /*set share method */ + H5O_cont_debug, /*debugging */ }}; /* Interface initialization */ @@ -66,7 +67,7 @@ static intn interface_initialize_g = FALSE; *------------------------------------------------------------------------- */ static void * -H5O_cont_decode(H5F_t *f, const uint8 *p, H5HG_t __unused__ *hobj) +H5O_cont_decode(H5F_t *f, const uint8 *p, H5O_shared_t __unused__ *sh) { H5O_cont_t *cont = NULL; @@ -75,7 +76,7 @@ H5O_cont_decode(H5F_t *f, const uint8 *p, H5HG_t __unused__ *hobj) /* check args */ assert(f); assert(p); - assert (!hobj || !H5HG_defined (hobj)); + assert (!sh); /* decode */ cont = H5MM_xcalloc(1, sizeof(H5O_cont_t)); diff --git a/src/H5Odtype.c b/src/H5Odtype.c index bfbe5a3..9ea0713 100644 --- a/src/H5Odtype.c +++ b/src/H5Odtype.c @@ -29,13 +29,16 @@ static char RcsId[] = "@(#)$Revision$"; /* PRIVATE PROTOTYPES */ static herr_t H5O_dtype_encode (H5F_t *f, uint8 *p, const void *mesg); -static void *H5O_dtype_decode (H5F_t *f, const uint8 *p, H5HG_t *hobj); +static void *H5O_dtype_decode (H5F_t *f, const uint8 *p, H5O_shared_t *sh); static void *H5O_dtype_copy (const void *_mesg, void *_dest); static size_t H5O_dtype_size (H5F_t *f, const void *_mesg); static herr_t H5O_dtype_reset (void *_mesg); +static herr_t H5O_dtype_get_share (H5F_t *f, const void *_mesg, + H5O_shared_t *sh); +static herr_t H5O_dtype_set_share (H5F_t *f, void *_mesg, + const H5O_shared_t *sh); static herr_t H5O_dtype_debug (H5F_t *f, const void *_mesg, FILE * stream, intn indent, intn fwidth); -static herr_t H5O_dtype_share (H5F_t *f, const void *_mesg, H5HG_t *hobj); /* This message derives from H5O */ const H5O_class_t H5O_DTYPE[1] = {{ @@ -47,7 +50,8 @@ 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_share, /* share method */ + H5O_dtype_get_share, /* get share method */ + H5O_dtype_set_share, /* set share method */ H5O_dtype_debug, /* debug the message */ }}; @@ -174,6 +178,7 @@ H5O_dtype_decode_helper(const uint8 **pp, H5T_t *dt) dt->u.compnd.memb[i].perm[2] = (perm_word >> 16) & 0xff; dt->u.compnd.memb[i].perm[3] = (perm_word >> 24) & 0xff; dt->u.compnd.memb[i].type = H5MM_xcalloc (1, sizeof(H5T_t)); + H5F_addr_undef (&(dt->u.compnd.memb[i].type->ent.header)); if (H5O_dtype_decode_helper(pp, dt->u.compnd.memb[i].type) < 0 || H5T_COMPOUND == dt->u.compnd.memb[i].type->type) { for (j = 0; j <= i; j++) @@ -436,7 +441,7 @@ H5O_dtype_encode_helper(uint8 **pp, const H5T_t *dt) function using malloc() and is returned to the caller. --------------------------------------------------------------------------*/ static void * -H5O_dtype_decode(H5F_t *f, const uint8 *p, H5HG_t *hobj) +H5O_dtype_decode(H5F_t *f, const uint8 *p, H5O_shared_t *sh) { H5T_t *dt = NULL; @@ -445,19 +450,16 @@ H5O_dtype_decode(H5F_t *f, const uint8 *p, H5HG_t *hobj) /* check args */ assert(f); assert(p); + assert (!sh); dt = H5MM_xcalloc(1, sizeof(H5T_t)); + H5F_addr_undef (&(dt->ent.header)); if (H5O_dtype_decode_helper(&p, dt) < 0) { H5MM_xfree(dt); HRETURN_ERROR(H5E_DATATYPE, H5E_CANTDECODE, NULL, "can't decode type"); } - if (hobj) { - dt->sh_heap = *hobj; - dt->sh_file = f; - } - FUNC_LEAVE(dt); } @@ -515,7 +517,7 @@ H5O_dtype_encode(H5F_t __unused__ *f, uint8 *p, const void *mesg) This function copies a native (memory) simple datatype message, allocating the destination structure if necessary. --------------------------------------------------------------------------*/ -static void * +static void * H5O_dtype_copy(const void *_src, void *_dst) { const H5T_t *src = (const H5T_t *) _src; @@ -527,7 +529,7 @@ H5O_dtype_copy(const void *_src, void *_dst) assert(src); /* copy */ - if (NULL == (dst = H5T_copy(src))) { + if (NULL == (dst = H5T_copy(src, H5T_COPY_ALL))) { HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "can't copy type"); } /* was result already allocated? */ @@ -627,43 +629,78 @@ H5O_dtype_reset(void *_mesg) /*------------------------------------------------------------------------- - * Function: H5O_dtype_share + * Function: H5O_dtype_get_share * - * Purpose: Returns, through argument HOBJ, whether a data type is shared - * in the specified file. + * Purpose: Returns information about where the shared message is located + * by filling in the SH shared message struct. * - * Return: Success: SUCCEED if the data type is shared in file F, - * and HOBJ is set to the global heap address. + * Return: Success: SUCCEED * - * Failure: FAIL if the data type is not shared, or - * shared but not in file F. The value of HOBJ - * is undefined. + * Failure: FAIL * * Programmer: Robb Matzke - * Thursday, April 2, 1998 + * Monday, June 1, 1998 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t -H5O_dtype_share (H5F_t *f, const void *_mesg, H5HG_t *hobj/*out*/) +H5O_dtype_get_share (H5F_t *f, const void *_mesg, H5O_shared_t *sh/*out*/) { - const H5T_t *dt = (const H5T_t *)_mesg; - - FUNC_ENTER (H5O_dtype_share, FAIL); + const H5T_t *dt = (const H5T_t *)_mesg; - if (!H5HG_defined (&(dt->sh_heap)) || - NULL==dt->sh_file || - dt->sh_file->shared != f->shared) { + FUNC_ENTER (H5O_dtype_get_share, FAIL); + assert (f); + assert (dt); + assert (sh); + + if (H5F_addr_defined (&(dt->ent.header))) { + assert (H5T_STATE_NAMED==dt->state || H5T_STATE_OPEN==dt->state); + sh->in_gh = FALSE; + sh->u.ent = dt->ent; + } else { HRETURN_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, - "data type is not shared"); + "data type is not sharable"); } + + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_dtype_set_share + * + * Purpose: Copies sharing information from SH into the message. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Thursday, June 4, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_dtype_set_share (H5F_t *f, void *_mesg/*in,out*/, const H5O_shared_t *sh) +{ + H5T_t *dt = (H5T_t *)_mesg; - *hobj = dt->sh_heap; + FUNC_ENTER (H5O_dtype_set_share, FAIL); + assert (f); + assert (dt); + assert (sh); + assert (!sh->in_gh); + + dt->ent = sh->u.ent; + dt->state = H5T_STATE_NAMED; + FUNC_LEAVE (SUCCEED); } - + /*-------------------------------------------------------------------------- NAME H5O_dtype_debug diff --git a/src/H5Oefl.c b/src/H5Oefl.c index ba598b7..246aa79 100644 --- a/src/H5Oefl.c +++ b/src/H5Oefl.c @@ -14,7 +14,7 @@ #define PABLO_MASK H5O_efl_mask /* PRIVATE PROTOTYPES */ -static void *H5O_efl_decode(H5F_t *f, const uint8 *p, H5HG_t *hobj); +static void *H5O_efl_decode(H5F_t *f, const uint8 *p, H5O_shared_t *sh); static herr_t H5O_efl_encode(H5F_t *f, uint8 *p, const void *_mesg); static void *H5O_efl_copy(const void *_mesg, void *_dest); static size_t H5O_efl_size(H5F_t *f, const void *_mesg); @@ -24,16 +24,17 @@ static herr_t H5O_efl_debug(H5F_t *f, const void *_mesg, FILE * stream, /* This message derives from H5O */ const H5O_class_t H5O_EFL[1] = {{ - H5O_EFL_ID, /*message id number */ - "external file list", /*message name for debugging */ - sizeof(H5O_efl_t), /*native message size */ - H5O_efl_decode, /*decode message */ - H5O_efl_encode, /*encode message */ - H5O_efl_copy, /*copy native value */ - H5O_efl_size, /*size of message on disk */ - H5O_efl_reset, /*reset method */ - NULL, /*no share method */ - H5O_efl_debug, /*debug the message */ + H5O_EFL_ID, /*message id number */ + "external file list", /*message name for debugging */ + sizeof(H5O_efl_t), /*native message size */ + H5O_efl_decode, /*decode message */ + H5O_efl_encode, /*encode message */ + H5O_efl_copy, /*copy native value */ + H5O_efl_size, /*size of message on disk */ + H5O_efl_reset, /*reset method */ + NULL, /*get share method */ + NULL, /*set share method */ + H5O_efl_debug, /*debug the message */ }}; /* Interface initialization */ @@ -59,7 +60,7 @@ static hbool_t interface_initialize_g = FALSE; *------------------------------------------------------------------------- */ static void * -H5O_efl_decode(H5F_t *f, const uint8 *p, H5HG_t __unused__ *hobj) +H5O_efl_decode(H5F_t *f, const uint8 *p, H5O_shared_t __unused__ *sh) { H5O_efl_t *mesg = NULL; int i; @@ -70,7 +71,7 @@ H5O_efl_decode(H5F_t *f, const uint8 *p, H5HG_t __unused__ *hobj) /* Check args */ assert(f); assert(p); - assert (!hobj || !H5HG_defined (hobj)); + assert (!sh); /* Decode the header */ mesg = H5MM_xcalloc(1, sizeof(H5O_efl_t)); diff --git a/src/H5Olayout.c b/src/H5Olayout.c index 42b21e5..510c0dd 100644 --- a/src/H5Olayout.c +++ b/src/H5Olayout.c @@ -14,7 +14,7 @@ #include /* PRIVATE PROTOTYPES */ -static void *H5O_layout_decode(H5F_t *f, const uint8 *p, H5HG_t *hobj); +static void *H5O_layout_decode(H5F_t *f, const uint8 *p, H5O_shared_t *sh); static herr_t H5O_layout_encode(H5F_t *f, uint8 *p, const void *_mesg); static void *H5O_layout_copy(const void *_mesg, void *_dest); static size_t H5O_layout_size(H5F_t *f, const void *_mesg); @@ -23,16 +23,17 @@ static herr_t H5O_layout_debug(H5F_t *f, const void *_mesg, FILE * stream, /* This message derives from H5O */ const H5O_class_t H5O_LAYOUT[1] = {{ - H5O_LAYOUT_ID, /*message id number */ - "layout", /*message name for debugging */ - sizeof(H5O_layout_t), /*native message size */ - H5O_layout_decode, /*decode message */ - H5O_layout_encode, /*encode message */ - H5O_layout_copy, /*copy the native value */ - H5O_layout_size, /*size of message on disk */ - NULL, /*reset method */ - NULL, /*no share method */ - H5O_layout_debug, /*debug the message */ + H5O_LAYOUT_ID, /*message id number */ + "layout", /*message name for debugging */ + sizeof(H5O_layout_t), /*native message size */ + H5O_layout_decode, /*decode message */ + H5O_layout_encode, /*encode message */ + H5O_layout_copy, /*copy the native value */ + H5O_layout_size, /*size of message on disk */ + NULL, /*reset method */ + NULL, /*get share method */ + NULL, /*set share method */ + H5O_layout_debug, /*debug the message */ }}; /* Interface initialization */ @@ -59,7 +60,7 @@ static hbool_t interface_initialize_g = FALSE; *------------------------------------------------------------------------- */ static void * -H5O_layout_decode(H5F_t *f, const uint8 *p, H5HG_t __unused__ *hobj) +H5O_layout_decode(H5F_t *f, const uint8 *p, H5O_shared_t __unused__ *sh) { H5O_layout_t *mesg = NULL; intn i; @@ -69,7 +70,7 @@ H5O_layout_decode(H5F_t *f, const uint8 *p, H5HG_t __unused__ *hobj) /* check args */ assert(f); assert(p); - assert (!hobj || !H5HG_defined (hobj)); + assert (!sh); /* decode */ mesg = H5MM_xcalloc(1, sizeof(H5O_layout_t)); diff --git a/src/H5Oname.c b/src/H5Oname.c index a31e08d..acf6764 100644 --- a/src/H5Oname.c +++ b/src/H5Oname.c @@ -22,7 +22,7 @@ #define PABLO_MASK H5O_name_mask /* PRIVATE PROTOTYPES */ -static void *H5O_name_decode(H5F_t *f, const uint8 *p, H5HG_t *hobj); +static void *H5O_name_decode(H5F_t *f, const uint8 *p, H5O_shared_t *sh); static herr_t H5O_name_encode(H5F_t *f, uint8 *p, const void *_mesg); static void *H5O_name_copy(const void *_mesg, void *_dest); static size_t H5O_name_size(H5F_t *f, const void *_mesg); @@ -32,16 +32,17 @@ static herr_t H5O_name_debug(H5F_t *f, const void *_mesg, FILE * stream, /* This message derives from H5O */ const H5O_class_t H5O_NAME[1] = {{ - H5O_NAME_ID, /*message id number */ - "name", /*message name for debugging */ - sizeof(H5O_name_t), /*native message size */ - H5O_name_decode, /*decode message */ - H5O_name_encode, /*encode message */ - H5O_name_copy, /*copy the native value */ - H5O_name_size, /*raw message size */ - H5O_name_reset, /*free internal memory */ - NULL, /*no share method */ - H5O_name_debug, /*debug the message */ + H5O_NAME_ID, /*message id number */ + "name", /*message name for debugging */ + sizeof(H5O_name_t), /*native message size */ + H5O_name_decode, /*decode message */ + H5O_name_encode, /*encode message */ + H5O_name_copy, /*copy the native value */ + H5O_name_size, /*raw message size */ + H5O_name_reset, /*free internal memory */ + NULL, /*get share method */ + NULL, /*set share method */ + H5O_name_debug, /*debug the message */ }}; /* Interface initialization */ @@ -68,7 +69,8 @@ static hbool_t interface_initialize_g = FALSE; *------------------------------------------------------------------------- */ static void * -H5O_name_decode(H5F_t __unused__ *f, const uint8 *p, H5HG_t __unused__ *hobj) +H5O_name_decode(H5F_t __unused__ *f, const uint8 *p, + H5O_shared_t __unused__ *sh) { H5O_name_t *mesg; @@ -77,7 +79,7 @@ H5O_name_decode(H5F_t __unused__ *f, const uint8 *p, H5HG_t __unused__ *hobj) /* check args */ assert(f); assert(p); - assert (!hobj || !H5HG_defined (hobj)); + assert (!sh); /* decode */ mesg = H5MM_xcalloc(1, sizeof(H5O_name_t)); diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index 7db9313..677241e 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -66,16 +66,18 @@ 2 + /*sizeof message data */ \ 4) /*reserved */ +struct H5O_shared_t; typedef struct H5O_class_t { intn id; /*message type ID on disk */ const char *name; /*for debugging */ size_t native_size; /*size of native message */ - void *(*decode)(H5F_t*, const uint8*, H5HG_t*); + void *(*decode)(H5F_t*, const uint8*, struct H5O_shared_t*); herr_t (*encode)(H5F_t*, uint8*, const void*); void *(*copy)(const void*, void*); /*copy native value */ size_t (*raw_size)(H5F_t*, const void*);/*sizeof raw val */ herr_t (*reset)(void *); /*free nested data structs */ - herr_t (*share)(H5F_t*, const void*, H5HG_t*); + 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 (*debug)(H5F_t*, const void*, FILE*, intn, intn); } H5O_class_t; @@ -205,7 +207,13 @@ typedef struct H5O_name_t { #define H5O_SHARED_ID 0x000f extern const H5O_class_t H5O_SHARED[1]; -typedef H5HG_t H5O_shared_t; +typedef struct H5O_shared_t { + hbool_t in_gh; /*shared by global heap? */ + union { + H5HG_t gh; /*global heap info */ + H5G_entry_t ent; /*symbol table entry info */ + } u; +} H5O_shared_t; /* * Object header continuation message. diff --git a/src/H5Osdspace.c b/src/H5Osdspace.c index 3a34fea..66361e4 100644 --- a/src/H5Osdspace.c +++ b/src/H5Osdspace.c @@ -25,7 +25,7 @@ static char RcsId[] = "@(#)$Revision$"; #define PABLO_MASK H5O_sdspace_mask /* PRIVATE PROTOTYPES */ -static void *H5O_sdspace_decode(H5F_t *f, const uint8 *p, H5HG_t *hobj); +static void *H5O_sdspace_decode(H5F_t *f, const uint8 *p, H5O_shared_t *sh); static herr_t H5O_sdspace_encode(H5F_t *f, uint8 *p, const void *_mesg); static void *H5O_sdspace_copy(const void *_mesg, void *_dest); static size_t H5O_sdspace_size(H5F_t *f, const void *_mesg); @@ -35,16 +35,17 @@ static herr_t H5O_sdspace_reset(void *_mesg); /* This message derives from H5O */ const H5O_class_t H5O_SDSPACE[1] = {{ - H5O_SDSPACE_ID, /* message id number */ - "simple_dspace", /* message name for debugging */ - sizeof(H5S_simple_t), /* native message size */ - H5O_sdspace_decode, /* decode message */ - H5O_sdspace_encode, /* encode message */ - H5O_sdspace_copy, /* copy the native value */ - H5O_sdspace_size, /* size of symbol table entry */ - H5O_sdspace_reset, /* default reset method */ - NULL, /* no share method */ - H5O_sdspace_debug, /* debug the message */ + H5O_SDSPACE_ID, /* message id number */ + "simple_dspace", /* message name for debugging */ + sizeof(H5S_simple_t), /* native message size */ + H5O_sdspace_decode, /* decode message */ + H5O_sdspace_encode, /* encode message */ + H5O_sdspace_copy, /* copy the native value */ + H5O_sdspace_size, /* size of symbol table entry */ + H5O_sdspace_reset, /* default reset method */ + NULL, /* get share method */ + NULL, /* set share method */ + H5O_sdspace_debug, /* debug the message */ }}; /* Is the interface initialized? */ @@ -75,7 +76,7 @@ static hbool_t interface_initialize_g = FALSE; instead of just four bytes. --------------------------------------------------------------------------*/ static void * -H5O_sdspace_decode(H5F_t *f, const uint8 *p, H5HG_t __unused__ *hobj) +H5O_sdspace_decode(H5F_t *f, const uint8 *p, H5O_shared_t __unused__ *sh) { H5S_simple_t *sdim = NULL;/* New simple dimensionality structure */ intn u; /* local counting variable */ @@ -86,7 +87,7 @@ H5O_sdspace_decode(H5F_t *f, const uint8 *p, H5HG_t __unused__ *hobj) /* check args */ assert(f); assert(p); - assert (!hobj || !H5HG_defined (hobj)); + assert (!sh); /* decode */ if ((sdim = H5MM_xcalloc(1, sizeof(H5S_simple_t))) != NULL) { diff --git a/src/H5Oshared.c b/src/H5Oshared.c index 37c7312..2789297 100644 --- a/src/H5Oshared.c +++ b/src/H5Oshared.c @@ -18,7 +18,7 @@ #include #include -static void *H5O_shared_decode (H5F_t*, const uint8*, H5HG_t *hobj); +static void *H5O_shared_decode (H5F_t*, const uint8*, H5O_shared_t *sh); static herr_t H5O_shared_encode (H5F_t*, uint8*, const void*); static size_t H5O_shared_size (H5F_t*, const void*); static herr_t H5O_shared_debug (H5F_t*, const void*, FILE*, intn, intn); @@ -33,7 +33,8 @@ const H5O_class_t H5O_SHARED[1] = {{ NULL, /*no copy method */ H5O_shared_size, /*size method */ NULL, /*no reset method */ - NULL, /*no share method */ + NULL, /*get share method */ + NULL, /*set share method */ H5O_shared_debug, /*debug method */ }}; @@ -60,7 +61,7 @@ static hbool_t interface_initialize_g = FALSE; *------------------------------------------------------------------------- */ static void * -H5O_shared_decode (H5F_t *f, const uint8 *buf, H5HG_t __unused__ *hobj) +H5O_shared_decode (H5F_t *f, const uint8 *buf, H5O_shared_t __unused__ *sh) { H5O_shared_t *mesg; @@ -69,12 +70,17 @@ H5O_shared_decode (H5F_t *f, const uint8 *buf, H5HG_t __unused__ *hobj) /* Check args */ assert (f); assert (buf); - assert (!hobj || !H5HG_defined (hobj)); + assert (!sh); /* Decode */ mesg = H5MM_xcalloc (1, sizeof *mesg); - H5F_addr_decode (f, &buf, &(mesg->addr)); - INT32DECODE (buf, mesg->idx); + UINT32DECODE (buf, mesg->in_gh); + if (mesg->in_gh) { + H5F_addr_decode (f, &buf, &(mesg->u.gh.addr)); + INT32DECODE (buf, mesg->u.gh.idx); + } else { + H5G_ent_decode (f, &buf, &(mesg->u.ent)); + } FUNC_LEAVE (mesg); } @@ -109,8 +115,13 @@ H5O_shared_encode (H5F_t *f, uint8 *buf/*out*/, const void *_mesg) assert (mesg); /* Encode */ - H5F_addr_encode (f, &buf, &(mesg->addr)); - INT32ENCODE (buf, mesg->idx); + INT32ENCODE (buf, mesg->in_gh); + if (mesg->in_gh) { + H5F_addr_encode (f, &buf, &(mesg->u.gh.addr)); + INT32ENCODE (buf, mesg->u.gh.idx); + } else { + H5G_ent_encode (f, &buf, &(mesg->u.ent)); + } FUNC_LEAVE (SUCCEED); } @@ -135,8 +146,15 @@ H5O_shared_encode (H5F_t *f, uint8 *buf/*out*/, const void *_mesg) static size_t H5O_shared_size (H5F_t *f, const void __unused__ *_mesg) { + size_t size; + FUNC_ENTER (H5O_shared_size, 0); - FUNC_LEAVE (H5F_SIZEOF_ADDR(f)+4); + + size = 4 + /*the flags field */ + MAX (H5F_SIZEOF_ADDR(f)+4, /*sharing via global heap */ + H5G_SIZEOF_ENTRY(f)); /*sharing by another obj hdr */ + + FUNC_LEAVE (size); } @@ -171,14 +189,22 @@ H5O_shared_debug (H5F_t __unused__ *f, const void *_mesg, assert (indent>=0); assert (fwidth>=0); - fprintf (stream, "%*s%-*s ", indent, "", fwidth, - "Collection address:"); - H5F_addr_print (stream, &(mesg->addr)); - fprintf (stream, "\n"); - - fprintf (stream, "%*s%-*s %d\n", indent, "", fwidth, - "Object ID within collection:", - mesg->idx); - + if (mesg->in_gh) { + HDfprintf (stream, "%*s%-*s %s\n", indent, "", fwidth, + "Sharing method", + "Global heap"); + HDfprintf (stream, "%*s%-*s %a\n", indent, "", fwidth, + "Collection address:", + &(mesg->u.gh.addr)); + HDfprintf (stream, "%*s%-*s %d\n", indent, "", fwidth, + "Object ID within collection:", + mesg->u.gh.idx); + } else { + HDfprintf (stream, "%*s%-*s %s\n", indent, "", fwidth, + "Sharing method", + "Obj Hdr"); + H5G_ent_debug (f, &(mesg->u.ent), stream, indent, fwidth, NULL); + } + FUNC_LEAVE (SUCCEED); } diff --git a/src/H5Ostab.c b/src/H5Ostab.c index 37c749b..7eb8d6e 100644 --- a/src/H5Ostab.c +++ b/src/H5Ostab.c @@ -23,7 +23,7 @@ #define PABLO_MASK H5O_stab_mask /* PRIVATE PROTOTYPES */ -static void *H5O_stab_decode(H5F_t *f, const uint8 *p, H5HG_t *hobj); +static void *H5O_stab_decode(H5F_t *f, const uint8 *p, H5O_shared_t *sh); static herr_t H5O_stab_encode(H5F_t *f, uint8 *p, const void *_mesg); static void *H5O_stab_copy(const void *_mesg, void *_dest); static size_t H5O_stab_size(H5F_t *f, const void *_mesg); @@ -32,16 +32,17 @@ static herr_t H5O_stab_debug(H5F_t *f, const void *_mesg, /* This message derives from H5O */ const H5O_class_t H5O_STAB[1] = {{ - H5O_STAB_ID, /*message id number */ - "stab", /*message name for debugging */ - sizeof(H5O_stab_t), /*native message size */ - H5O_stab_decode, /*decode message */ - H5O_stab_encode, /*encode message */ - H5O_stab_copy, /*copy the native value */ - H5O_stab_size, /*size of symbol table entry */ - NULL, /*default reset method */ - NULL, /*no share method */ - H5O_stab_debug, /*debug the message */ + H5O_STAB_ID, /*message id number */ + "stab", /*message name for debugging */ + sizeof(H5O_stab_t), /*native message size */ + H5O_stab_decode, /*decode message */ + H5O_stab_encode, /*encode message */ + H5O_stab_copy, /*copy the native value */ + H5O_stab_size, /*size of symbol table entry */ + NULL, /*default reset method */ + NULL, /*get share method */ + NULL, /*set share method */ + H5O_stab_debug, /*debug the message */ }}; /* Interface initialization */ @@ -67,7 +68,7 @@ static hbool_t interface_initialize_g = FALSE; *------------------------------------------------------------------------- */ static void * -H5O_stab_decode(H5F_t *f, const uint8 *p, H5HG_t __unused__ *hobj) +H5O_stab_decode(H5F_t *f, const uint8 *p, H5O_shared_t __unused__ *sh) { H5O_stab_t *stab; @@ -76,7 +77,7 @@ H5O_stab_decode(H5F_t *f, const uint8 *p, H5HG_t __unused__ *hobj) /* check args */ assert(f); assert(p); - assert (!hobj || !H5HG_defined (hobj)); + assert (!sh); /* decode */ stab = H5MM_xcalloc(1, sizeof(H5O_stab_t)); diff --git a/src/H5T.c b/src/H5T.c index 8648a4e..1e10135 100644 --- a/src/H5T.c +++ b/src/H5T.c @@ -12,6 +12,7 @@ static char RcsId[] = "@(#)$Revision$"; #define H5T_PACKAGE /*suppress error about including H5Tpkg */ #include /*generic functions */ +#include /*datasets (for H5Tcopy) */ #include /*ID functions */ #include /*error handling */ #include /*groups */ @@ -94,6 +95,7 @@ H5T_init_interface(void) (herr_t (*)(void *)) H5T_close)) != FAIL) { ret_value = H5_add_exit(&H5T_term_interface); } + /* * Initialize pre-defined data types that depend on the architecture. */ @@ -158,7 +160,8 @@ H5T_init_interface(void) /* TIME */ dt = H5MM_xcalloc(1, sizeof(H5T_t)); - dt->locked = TRUE; + dt->state = H5T_STATE_IMMUTABLE; + H5F_addr_undef (&(dt->ent.header)); dt->type = H5T_TIME; dt->size = 1; dt->u.atomic.order = H5Tget_order(H5T_NATIVE_INT_g); @@ -173,7 +176,8 @@ H5T_init_interface(void) /* STRING */ dt = H5MM_xcalloc(1, sizeof(H5T_t)); - dt->locked = TRUE; + dt->state = H5T_STATE_IMMUTABLE; + H5F_addr_undef (&(dt->ent.header)); dt->type = H5T_STRING; dt->size = 1; dt->u.atomic.order = H5T_ORDER_NONE; @@ -190,7 +194,8 @@ H5T_init_interface(void) /* BITFIELD */ dt = H5MM_xcalloc(1, sizeof(H5T_t)); - dt->locked = TRUE; + dt->state = H5T_STATE_IMMUTABLE; + H5F_addr_undef (&(dt->ent.header)); dt->type = H5T_BITFIELD; dt->size = 1; dt->u.atomic.order = H5Tget_order(H5T_NATIVE_INT_g); @@ -205,7 +210,8 @@ H5T_init_interface(void) /* OPAQUE */ dt = H5MM_xcalloc(1, sizeof(H5T_t)); - dt->locked = TRUE; + dt->state = H5T_STATE_IMMUTABLE; + H5F_addr_undef (&(dt->ent.header)); dt->type = H5T_OPAQUE; dt->size = 1; dt->u.atomic.order = H5T_ORDER_NONE; @@ -254,7 +260,7 @@ H5T_init_interface(void) /*------------------------------------------------------------------------- * Function: H5T_unlock_cb * - * Purpose: Clear the locked flag for a data type. This function is + * Purpose: Clear the immutable flag for a data type. This function is * called when the library is closing in order to unlock all * registered data types and thus make them free-able. * @@ -270,11 +276,15 @@ H5T_init_interface(void) *------------------------------------------------------------------------- */ static intn -H5T_unlock_cb (void *dt, const void __unused__ *key) +H5T_unlock_cb (void *_dt, const void __unused__ *key) { + H5T_t *dt = (H5T_t *)_dt; + FUNC_ENTER (H5T_unlock_cb, FAIL); assert (dt); - ((H5T_t*)dt)->locked = FALSE; + if (H5T_STATE_IMMUTABLE==dt->state) { + dt->state = H5T_STATE_RDONLY; + } FUNC_LEAVE (0); } @@ -420,6 +430,136 @@ H5Tcreate(H5T_class_t type, size_t size) /*------------------------------------------------------------------------- + * Function: H5Topen + * + * Purpose: Opens a named data type. + * + * Return: Success: Object ID of the named data type. + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Monday, June 1, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +hid_t +H5Topen (hid_t loc_id, const char *name) +{ + H5G_t *loc = NULL; + H5T_t *type = NULL; + hid_t ret_value = FAIL; + + FUNC_ENTER (H5Topen, FAIL); + + /* Check args */ + if (NULL==(loc=H5G_loc (loc_id))) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location"); + } + if (!name || !*name) { + HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "no name"); + } + + /* Open it */ + if (NULL==(type=H5T_open (loc, name))) { + HRETURN_ERROR (H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, + "unable to open named data type"); + } + + /* Register the type and return the ID */ + if ((ret_value=H5I_register (H5_DATATYPE, type))<0) { + H5T_close (type); + HRETURN_ERROR (H5E_DATATYPE, H5E_CANTREGISTER, FAIL, + "unable to register named data type"); + } + + FUNC_LEAVE (ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Tcommit + * + * Purpose: Save a transient data type to a file and turn the type handle + * into a named, immutable type. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Monday, June 1, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tcommit (hid_t loc_id, const char *name, hid_t type_id) +{ + H5G_t *loc = NULL; + H5T_t *type = NULL; + + FUNC_ENTER (H5Tcommit, FAIL); + + /* Check arguments */ + if (NULL==(loc=H5G_loc (loc_id))) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location"); + } + if (!name || !*name) { + HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "no name"); + } + if (H5_DATATYPE!=H5I_group (type_id) || + NULL==(type=H5I_object (type_id))) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + } + + /* Commit the type */ + if (H5T_commit (loc, name, type)<0) { + HRETURN_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, + "unable to commit data type"); + } + + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5Tcommitted + * + * Purpose: Determines if a data type is committed or not. + * + * Return: Success: TRUE if committed, FALSE otherwise. + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Thursday, June 4, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +hbool_t +H5Tcommitted (hid_t type_id) +{ + H5T_t *type = NULL; + + FUNC_ENTER (H5Tcommitted, FAIL); + + /* Check arguments */ + if (H5_DATATYPE!=H5I_group (type_id) || + NULL==(type=H5I_object (type_id))) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + } + + FUNC_LEAVE (H5T_STATE_OPEN==type->state || H5T_STATE_NAMED==type->state); +} + + +/*------------------------------------------------------------------------- * Function: H5Tcopy * * Purpose: Copies a data type. The resulting data type is not locked. @@ -435,6 +575,12 @@ H5Tcreate(H5T_class_t type, size_t size) * * Modifications: * + * Robb Matzke, 4 Jun 1998 + * The returned type is always transient and unlocked. If the TYPE_ID + * argument is a dataset instead of a data type then this function + * returns a transient, modifiable data type which is a copy of the + * dataset's data type. + * *------------------------------------------------------------------------- */ hid_t @@ -442,18 +588,37 @@ H5Tcopy(hid_t type_id) { H5T_t *dt = NULL; H5T_t *new_dt = NULL; + H5D_t *dset = NULL; hid_t ret_value = FAIL; FUNC_ENTER(H5Tcopy, FAIL); - /* Check args */ - if (H5_DATATYPE != H5I_group(type_id) || - NULL == (dt = H5I_object(type_id))) { - HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + switch (H5I_group (type_id)) { + case H5_DATATYPE: + /* The argument is a data type handle */ + if (NULL==(dt=H5I_object (type_id))) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + } + break; + + case H5_DATASET: + /* The argument is a dataset handle */ + if (NULL==(dset=H5I_object (type_id))) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset"); + } + if (NULL==(dt=H5D_typeof (dset))) { + HRETURN_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, + "unable to get the dataset data type"); + } + break; + + default: + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, + "not a data type or dataset"); } /* Copy */ - if (NULL == (new_dt = H5T_copy(dt))) { + if (NULL == (new_dt = H5T_copy(dt, H5T_COPY_TRANSIENT))) { HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "can't copy"); } @@ -496,8 +661,8 @@ H5Tclose(hid_t type_id) NULL == (dt = H5I_object(type_id))) { HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); } - if (dt->locked) { - HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "predefined data type"); + if (H5T_STATE_IMMUTABLE==dt->state) { + HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "immutable data type"); } /* When the reference count reaches zero the resources are freed */ @@ -557,7 +722,8 @@ H5Tequal(hid_t type1_id, hid_t type2_id) * the application doesn't inadvertently change or delete a * predefined type. * - * Once a data type is locked it can never be unlocked. + * Once a data type is locked it can never be unlocked unless + * the entire library is closed. * * Return: Success: SUCCEED * @@ -568,6 +734,10 @@ H5Tequal(hid_t type1_id, hid_t type2_id) * * Modifications: * + * Robb Matzke, 1 Jun 1998 + * It is illegal to lock a named data type since we must allow named + * types to be closed (to release file resources) but locking a type + * prevents that. *------------------------------------------------------------------------- */ herr_t @@ -582,7 +752,14 @@ H5Tlock(hid_t type_id) NULL == (dt = H5I_object(type_id))) { HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); } - dt->locked = TRUE; + if (H5T_STATE_NAMED==dt->state || H5T_STATE_OPEN==dt->state) { + HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, + "unable to lock named data type"); + } + if (H5T_lock (dt, TRUE)<0) { + HRETURN_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, + "unable to lock transient data type"); + } FUNC_LEAVE(SUCCEED); } @@ -703,7 +880,7 @@ H5Tset_size(hid_t type_id, size_t size) !H5T_is_atomic(dt)) { HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an atomic data type"); } - if (dt->locked) { + if (H5T_STATE_TRANSIENT!=dt->state) { HRETURN_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); } if (size <= 0) { @@ -762,7 +939,6 @@ H5Tset_size(hid_t type_id, size_t size) } /* Commit */ - H5T_unshare (dt); dt->size = size; dt->u.atomic.offset = offset; dt->u.atomic.prec = prec; @@ -839,7 +1015,7 @@ H5Tset_order(hid_t type_id, H5T_order_t order) !H5T_is_atomic(dt)) { HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an atomic data type"); } - if (dt->locked) { + if (H5T_STATE_TRANSIENT!=dt->state) { HRETURN_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); } if (order < 0 || order > H5T_ORDER_NONE) { @@ -847,7 +1023,6 @@ H5Tset_order(hid_t type_id, H5T_order_t order) } /* Commit */ - H5T_unshare (dt); dt->u.atomic.order = order; FUNC_LEAVE(SUCCEED); } @@ -939,7 +1114,7 @@ H5Tset_precision(hid_t type_id, size_t prec) !H5T_is_atomic(dt)) { HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an atomic data type"); } - if (dt->locked) { + if (H5T_STATE_TRANSIENT!=dt->state) { HRETURN_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); } if (prec <= 0) { @@ -993,7 +1168,6 @@ H5Tset_precision(hid_t type_id, size_t prec) } /* Commit */ - H5T_unshare (dt); dt->size = size; dt->u.atomic.offset = offset; dt->u.atomic.prec = prec; @@ -1108,7 +1282,7 @@ H5Tset_offset(hid_t type_id, size_t offset) !H5T_is_atomic(dt)) { HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an atomic data type"); } - if (dt->locked) { + if (H5T_STATE_TRANSIENT!=dt->state) { HRETURN_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); } if (H5T_STRING == dt->type && offset != 0) { @@ -1122,7 +1296,6 @@ H5Tset_offset(hid_t type_id, size_t offset) } /* Commit */ - H5T_unshare (dt); dt->u.atomic.offset = offset; FUNC_LEAVE(SUCCEED); @@ -1198,7 +1371,7 @@ H5Tset_pad(hid_t type_id, H5T_pad_t lsb, H5T_pad_t msb) !H5T_is_atomic(dt)) { HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an atomic data type"); } - if (dt->locked) { + if (H5T_STATE_TRANSIENT!=dt->state) { HRETURN_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); } if (lsb < 0 || lsb >= H5T_NPAD || msb < 0 || msb >= H5T_NPAD) { @@ -1206,7 +1379,6 @@ H5Tset_pad(hid_t type_id, H5T_pad_t lsb, H5T_pad_t msb) } /* Commit */ - H5T_unshare (dt); dt->u.atomic.lsb_pad = lsb; dt->u.atomic.msb_pad = msb; @@ -1282,7 +1454,7 @@ H5Tset_sign(hid_t type_id, H5T_sign_t sign) H5T_INTEGER != dt->type) { HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an integer data type"); } - if (dt->locked) { + if (H5T_STATE_TRANSIENT!=dt->state) { HRETURN_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); } if (sign < 0 || sign >= H5T_NSGN) { @@ -1290,7 +1462,6 @@ H5Tset_sign(hid_t type_id, H5T_sign_t sign) } /* Commit */ - H5T_unshare (dt); dt->u.atomic.u.i.sign = sign; FUNC_LEAVE(SUCCEED); } @@ -1383,7 +1554,7 @@ H5Tset_fields(hid_t type_id, size_t spos, size_t epos, size_t esize, HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a floating-point data type"); } - if (dt->locked) { + if (H5T_STATE_TRANSIENT!=dt->state) { HRETURN_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); } if (epos + esize > dt->u.atomic.prec) { @@ -1415,7 +1586,6 @@ H5Tset_fields(hid_t type_id, size_t spos, size_t epos, size_t esize, } /* Commit */ - H5T_unshare (dt); dt->u.atomic.u.f.sign = spos; dt->u.atomic.u.f.epos = epos; dt->u.atomic.u.f.mpos = mpos; @@ -1495,12 +1665,11 @@ H5Tset_ebias(hid_t type_id, size_t ebias) HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a floating-point data type"); } - if (dt->locked) { + if (H5T_STATE_TRANSIENT!=dt->state) { HRETURN_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); } /* Commit */ - H5T_unshare (dt); dt->u.atomic.u.f.ebias = ebias; FUNC_LEAVE(SUCCEED); @@ -1578,7 +1747,7 @@ H5Tset_norm(hid_t type_id, H5T_norm_t norm) HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a floating-point data type"); } - if (dt->locked) { + if (H5T_STATE_TRANSIENT!=dt->state) { HRETURN_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); } if (norm < 0 || norm > H5T_NORM_NONE) { @@ -1586,7 +1755,6 @@ H5Tset_norm(hid_t type_id, H5T_norm_t norm) } /* Commit */ - H5T_unshare (dt); dt->u.atomic.u.f.norm = norm; FUNC_LEAVE(SUCCEED); } @@ -1667,7 +1835,7 @@ H5Tset_inpad(hid_t type_id, H5T_pad_t pad) HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a floating-point data type"); } - if (dt->locked) { + if (H5T_STATE_TRANSIENT!=dt->state) { HRETURN_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); } if (pad < 0 || pad >= H5T_NPAD) { @@ -1676,7 +1844,6 @@ H5Tset_inpad(hid_t type_id, H5T_pad_t pad) } /* Commit */ - H5T_unshare (dt); dt->u.atomic.u.f.pad = pad; FUNC_LEAVE(SUCCEED); } @@ -1754,7 +1921,7 @@ H5Tset_cset(hid_t type_id, H5T_cset_t cset) H5T_STRING != dt->type) { HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a string data type"); } - if (dt->locked) { + if (H5T_STATE_TRANSIENT!=dt->state) { HRETURN_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); } if (cset < 0 || cset >= H5T_NCSET) { @@ -1763,7 +1930,6 @@ H5Tset_cset(hid_t type_id, H5T_cset_t cset) } /* Commit */ - H5T_unshare (dt); dt->u.atomic.u.s.cset = cset; FUNC_LEAVE(SUCCEED); } @@ -1843,7 +2009,7 @@ H5Tset_strpad(hid_t type_id, H5T_str_t strpad) H5T_STRING != dt->type) { HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a string data type"); } - if (dt->locked) { + if (H5T_STATE_TRANSIENT!=dt->state) { HRETURN_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); } if (strpad < 0 || strpad >= H5T_NSTR) { @@ -1851,7 +2017,6 @@ H5Tset_strpad(hid_t type_id, H5T_str_t strpad) } /* Commit */ - H5T_unshare (dt); dt->u.atomic.u.s.pad = strpad; FUNC_LEAVE(SUCCEED); } @@ -2051,6 +2216,10 @@ H5Tget_member_dims(hid_t type_id, int membno, * * Modifications: * + * Robb Matzke, 4 Jun 1998 + * If the member type is a named type then this function returns a + * handle to the re-opened named type. + * *------------------------------------------------------------------------- */ hid_t @@ -2072,7 +2241,8 @@ H5Tget_member_type(hid_t type_id, int membno) } /* Copy data type into an atom */ - if (NULL == (memb_dt = H5T_copy(dt->u.compnd.memb[membno].type))) { + if (NULL == (memb_dt = H5T_copy(dt->u.compnd.memb[membno].type, + H5T_COPY_REOPEN))) { HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy member data type"); } @@ -2128,7 +2298,7 @@ H5Tinsert(hid_t parent_id, const char *name, size_t offset, hid_t member_id) H5T_COMPOUND != parent->type) { HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a compound data type"); } - if (parent->locked) { + if (H5T_STATE_TRANSIENT!=parent->state) { HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "parent type read-only"); } if (!name || !*name) { @@ -2179,7 +2349,7 @@ H5Tpack(hid_t type_id) H5T_COMPOUND != dt->type) { HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a compound data type"); } - if (dt->locked) { + if (H5T_STATE_TRANSIENT!=dt->state) { HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "data type is read-only"); } @@ -2194,98 +2364,6 @@ H5Tpack(hid_t type_id) /*------------------------------------------------------------------------- - * Function: H5Tshare - * - * Purpose: Marks a data type as sharable. Using the type during the - * creation of a dataset will cause the dataset object header to - * point to the type in the global heap instead of containing - * the type directly in its object header. Subsequent - * modifications to a shared type cause the type to become - * unshared. - * - * Return: Success: SUCCEED - * - * Failure: FAIL - * - * Programmer: Robb Matzke - * Tuesday, March 31, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5Tshare (hid_t loc_id, hid_t type_id) -{ - H5G_t *loc = NULL; - H5T_t *dt = NULL; - - FUNC_ENTER (H5Tshare, FAIL); - - /* Check arguments */ - if (NULL==(loc=H5G_loc (loc_id))) { - HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location"); - } - if (H5_DATATYPE!=H5I_group (type_id) || - NULL==(dt=H5I_object (type_id))) { - HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - } - - /* Make it sharable */ - if (H5T_share (H5G_fileof (loc), dt)<0) { - HRETURN_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, - "unable to make data type sharable"); - } - - FUNC_LEAVE (SUCCEED); -} - - -/*------------------------------------------------------------------------- - * Function: H5Tis_shared - * - * Purpose: Determines if a data type is shared in the specified file. - * The TYPE_ID is the type in question and LOC_ID is a file id - * or group id (a group id is used only to identify the file). - * - * Return: Success: TRUE or FALSE - * - * Failure: FAIL - * - * Programmer: Robb Matzke - * Friday, April 3, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -hbool_t -H5Tis_shared (hid_t loc_id, hid_t type_id) -{ - H5G_t *loc = NULL; - H5T_t *dt = NULL; - hbool_t ret_value = FAIL; - - FUNC_ENTER (H5Tis_shared, FAIL); - - /* Check arguments */ - if (NULL==(loc=H5G_loc (loc_id))) { - HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location"); - } - if (H5_DATATYPE!=H5I_group (type_id) || - NULL==(dt=H5I_object (type_id))) { - HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - } - - /* Is it sharable */ - ret_value = (H5HG_defined (&(dt->sh_heap)) && - dt->sh_file->shared==H5G_fileof(loc)->shared) ? TRUE : FALSE; - - FUNC_LEAVE (ret_value); -} - - -/*------------------------------------------------------------------------- * Function: H5Tregister_hard * * Purpose: Register a hard conversion function for a data type @@ -2425,8 +2503,10 @@ H5Tregister_soft(const char *name, H5T_class_t src_cls, H5T_class_t dst_cls, * data type temporarily to an object id before we query the functions * capabilities. */ - if ((src_id = H5I_register(H5_DATATYPE, H5T_copy(path->src))) < 0 || - (dst_id = H5I_register(H5_DATATYPE, H5T_copy(path->dst))) < 0) { + if ((src_id = H5I_register(H5_DATATYPE, + H5T_copy(path->src, H5T_COPY_ALL))) < 0 || + (dst_id = H5I_register(H5_DATATYPE, + H5T_copy(path->dst, H5T_COPY_ALL))) < 0) { HRETURN_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register data types for conv query"); } @@ -2545,9 +2625,11 @@ H5Tunregister(H5T_conv_t func) * object id's for the data types. */ if ((src_id = H5I_register(H5_DATATYPE, - H5T_copy(path->src))) < 0 || + H5T_copy(path->src, + H5T_COPY_ALL))) < 0 || (dst_id = H5I_register(H5_DATATYPE, - H5T_copy(path->dst))) < 0) { + H5T_copy(path->dst, + H5T_COPY_ALL))) < 0) { HRETURN_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register conv types for query"); } @@ -2679,16 +2761,68 @@ H5T_create(H5T_class_t type, size_t size) "unknown data type class"); } + H5F_addr_undef (&(dt->ent.header)); dt->size = size; FUNC_LEAVE(dt); } /*------------------------------------------------------------------------- + * Function: H5T_open + * + * Purpose: Open a named data type. + * + * Return: Success: Ptr to a new data type. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * Monday, June 1, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +H5T_t * +H5T_open (H5G_t *loc, const char *name) +{ + H5T_t *dt = NULL; + H5G_entry_t ent; + + FUNC_ENTER (H5T_open, NULL); + assert (loc); + assert (name && *name); + + /* + * Find the named data type object header and read the data type message + * from it. + */ + if (H5G_find (loc, name, NULL, &ent/*out*/)<0) { + HRETURN_ERROR (H5E_DATATYPE, H5E_NOTFOUND, NULL, "not found"); + } + if (H5O_open (&ent)<0) { + HRETURN_ERROR (H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, + "unable to open named data type"); + } + if (NULL==(dt=H5O_read (&ent, H5O_DTYPE, 0, NULL))) { + H5O_close (&ent); + HRETURN_ERROR (H5E_DATATYPE, H5E_CANTINIT, NULL, + "unable to load type message from object header"); + } + + /* Mark the type as named and open */ + dt->state = H5T_STATE_OPEN; + dt->ent = ent; + + FUNC_LEAVE (dt); +} + + +/*------------------------------------------------------------------------- * Function: H5T_copy * * Purpose: Copies datatype OLD_DT. The resulting data type is not - * locked. + * locked and is a transient type. * * Return: Success: Pointer to a new copy of the OLD_DT argument. * @@ -2699,10 +2833,20 @@ H5T_create(H5T_class_t type, size_t size) * * Modifications: * + * Robb Matzke, 4 Jun 1998 + * Added the METHOD argument. If it's H5T_COPY_TRANSIENT then the + * result will be an unlocked transient type. Otherwise if it's + * H5T_COPY_ALL then the result is a named type if the original is a + * named type, but the result is not opened. Finally, if it's + * H5T_COPY_REOPEN and the original type is a named type then the result + * is a named type and the type object header is opened again. The + * H5T_COPY_REOPEN method is used when returning a named type to the + * application. + * *------------------------------------------------------------------------- */ H5T_t * -H5T_copy(const H5T_t *old_dt) +H5T_copy(const H5T_t *old_dt, H5T_copy_t method) { H5T_t *new_dt=NULL, *tmp=NULL; intn i; @@ -2716,8 +2860,43 @@ H5T_copy(const H5T_t *old_dt) /* copy */ new_dt = H5MM_xcalloc(1, sizeof(H5T_t)); *new_dt = *old_dt; - new_dt->locked = FALSE; + switch (method) { + case H5T_COPY_TRANSIENT: + /* + * Return an unlocked transient type. + */ + new_dt->state = H5T_STATE_TRANSIENT; + HDmemset (&(new_dt->ent), 0, sizeof(new_dt->ent)); + H5F_addr_undef (&(new_dt->ent.header)); + break; + + case H5T_COPY_ALL: + /* + * Return a transient type (locked or unlocked) or an unopened named + * type. + */ + if (H5T_STATE_OPEN==new_dt->state) { + new_dt->state = H5T_STATE_NAMED; + } + break; + + case H5T_COPY_REOPEN: + /* + * Return a transient type (locked or unlocked) or an opened named + * type. + */ + if (H5F_addr_defined (&(new_dt->ent.header))) { + if (H5O_open (&(new_dt->ent))<0) { + H5MM_xfree (new_dt); + HRETURN_ERROR (H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, + "unable to reopen named data type"); + } + new_dt->state = H5T_STATE_OPEN; + } + break; + } + if (H5T_COMPOUND == new_dt->type) { /* * Copy all member fields to new type, then overwrite the @@ -2732,7 +2911,7 @@ H5T_copy(const H5T_t *old_dt) for (i = 0; i < new_dt->u.compnd.nmembs; i++) { s = new_dt->u.compnd.memb[i].name; new_dt->u.compnd.memb[i].name = H5MM_xstrdup(s); - tmp = H5T_copy (old_dt->u.compnd.memb[i].type); + tmp = H5T_copy (old_dt->u.compnd.memb[i].type, method); new_dt->u.compnd.memb[i].type = tmp; } } @@ -2742,179 +2921,178 @@ H5T_copy(const H5T_t *old_dt) /*------------------------------------------------------------------------- - * Function: H5T_close + * Function: H5T_commit * - * Purpose: Frees a data type and all associated memory. If the data - * type is locked then nothing happens. + * Purpose: Commit a type, giving it a name and causing it to become + * immutable. * * Return: Success: SUCCEED * * Failure: FAIL * * Programmer: Robb Matzke - * Monday, December 8, 1997 + * Monday, June 1, 1998 * * Modifications: * *------------------------------------------------------------------------- */ herr_t -H5T_close(H5T_t *dt) +H5T_commit (H5G_t *loc, const char *name, H5T_t *type) { - intn i; - - FUNC_ENTER(H5T_close, FAIL); - - assert(dt); + herr_t ret_value = FAIL; + + FUNC_ENTER (H5T_commit, FAIL); /* - * Don't free locked datatypes unless we are shutting the interface - * down. + * Check arguments. We cannot commit an immutable type because H5Tclose() + * normally fails on such types (try H5Tclose(H5T_NATIVE_INT)) but closing + * a named type should always succeed. */ - if (!dt->locked) { - if (dt && H5T_COMPOUND == dt->type) { - for (i = 0; i < dt->u.compnd.nmembs; i++) { - H5MM_xfree(dt->u.compnd.memb[i].name); - H5T_close (dt->u.compnd.memb[i].type); - } - H5MM_xfree(dt->u.compnd.memb); - H5MM_xfree(dt); + assert (loc); + assert (name && *name); + assert (type); + if (H5T_STATE_NAMED==type->state || H5T_STATE_OPEN==type->state) { + HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, + "data type is already committed"); + } + if (H5T_STATE_IMMUTABLE==type->state) { + HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, + "data type is immutable"); + } - } else if (dt) { - H5MM_xfree(dt); + /* + * Create the object header and open it for write access. Insert the data + * type message and then give the object header a name. + */ + if (H5O_create (H5G_fileof (loc), 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) { + 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"); + } + type->state = H5T_STATE_OPEN; + ret_value = SUCCEED; + + done: + if (ret_value<0) { + if (H5F_addr_defined (&(type->ent.header))) { + H5O_close (&(type->ent)); + H5F_addr_undef (&(type->ent.header)); } } - - FUNC_LEAVE(SUCCEED); + FUNC_LEAVE (ret_value); } /*------------------------------------------------------------------------- - * Function: H5T_share + * Function: H5T_lock + * + * Purpose: Lock a transient data type making it read-only. If IMMUTABLE + * is set then the type cannot be closed except when the library + * itself closes. * - * Purpose: Causes a data type to be marked as sharable. If the data - * type isn't already marked sharable in the specified file then - * it is written to the global heap of that file and the heap - * location information is added to the sh_file and sh_heap - * fields of the data type. + * This function is a no-op if the type is not transient or if + * the type is already read-only or immutable. * * Return: Success: SUCCEED * * Failure: FAIL * * Programmer: Robb Matzke - * Tuesday, March 31, 1998 + * Thursday, June 4, 1998 * * Modifications: * *------------------------------------------------------------------------- */ herr_t -H5T_share (H5F_t *f, H5T_t *dt) +H5T_lock (H5T_t *dt, hbool_t immutable) { - FUNC_ENTER (H5T_share, FAIL); - - /* Check args */ - assert (f); + FUNC_ENTER (H5T_lock, FAIL); assert (dt); - /* - * If the type is sharable in some other file then unshare it first. A - * type can only be sharable in one file at a time. - */ - if (H5HG_defined (&(dt->sh_heap)) && f->shared!=dt->sh_file->shared) { - H5T_unshare (dt); - H5E_clear (); /*don't really care if it fails*/ + switch (dt->state) { + case H5T_STATE_TRANSIENT: + dt->state = immutable ? H5T_STATE_IMMUTABLE : H5T_STATE_RDONLY; + break; + case H5T_STATE_RDONLY: + if (immutable) dt->state = H5T_STATE_IMMUTABLE; + break; + case H5T_STATE_IMMUTABLE: + case H5T_STATE_NAMED: + case H5T_STATE_OPEN: + /*void*/ + break; } - /* - * Write the message to the global heap if it isn't already shared in - * this file. - */ - if (!H5HG_defined (&(dt->sh_heap))) { - if (H5O_share (f, H5O_DTYPE, dt, &(dt->sh_heap))<0) { - HRETURN_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, - "unable to store data type message in global heap"); - } - dt->sh_file = f; - } - FUNC_LEAVE (SUCCEED); } /*------------------------------------------------------------------------- - * Function: H5T_unshare + * Function: H5T_close * - * Purpose: If a data type is in the global heap then this function - * removes that information from the H5T_t struct. + * Purpose: Frees a data type and all associated memory. If the data + * type is locked then nothing happens. * * Return: Success: SUCCEED * * Failure: FAIL * * Programmer: Robb Matzke - * Tuesday, March 31, 1998 + * Monday, December 8, 1997 * * Modifications: * *------------------------------------------------------------------------- */ herr_t -H5T_unshare (H5T_t *dt) +H5T_close(H5T_t *dt) { - FUNC_ENTER (H5T_unshare, FAIL); + intn i; - /* Check args */ - assert (dt); + FUNC_ENTER(H5T_close, FAIL); - H5HG_undef (&(dt->sh_heap)); - dt->sh_file = NULL; + assert(dt); - FUNC_LEAVE (SUCCEED); -} + /* + * If a named type is being closed then close the object header also. + */ + if (H5T_STATE_OPEN==dt->state) { + assert (H5F_addr_defined (&(dt->ent.header))); + if (H5O_close (&(dt->ent))<0) { + HRETURN_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, + "unable to close data type object header"); + } + dt->state = H5T_STATE_NAMED; + } - -/*------------------------------------------------------------------------- - * Function: H5T_invalidate_cb - * - * Purpose: This is a callback function for H5I_search(). When a file is - * closed we scan through the data type list and invalidate - * shared info for all types that have sharing enabled for the - * specified file. This insures that we don't having dangling - * pointers from data types to files. We have to do this with - * data types but not datasets because a dataset_id always - * corresponds to an open object header which prevents the file - * from closing in the first place, but a data type can exist - * independent of a file and doesn't have an object header. - * - * Return: Success: 0, this function never returns a non-zero - * value because that would terminate - * H5I_search(). - * - * Failure: 0 - * - * Programmer: Robb Matzke - * Friday, April 3, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -intn -H5T_invalidate_cb (void *obj, const void *call_data) -{ - H5T_t *dt = (H5T_t *)obj; - const H5F_t *f = (const H5F_t*)call_data; /*used only for comparison*/ - - FUNC_ENTER (H5T_invalidate, 0); + /* + * Don't free locked datatypes unless we are shutting down the + * interface. + */ + if (H5T_STATE_IMMUTABLE!=dt->state) { + if (dt && H5T_COMPOUND == dt->type) { + for (i = 0; i < dt->u.compnd.nmembs; i++) { + H5MM_xfree(dt->u.compnd.memb[i].name); + H5T_close (dt->u.compnd.memb[i].type); + } + H5MM_xfree(dt->u.compnd.memb); + H5MM_xfree(dt); - if (H5HG_defined (&(dt->sh_heap)) && dt->sh_file->shared==f->shared) { - H5T_unshare (dt); - H5E_clear (); + } else if (dt) { + H5MM_xfree(dt); + } } - - FUNC_LEAVE (0); + + FUNC_LEAVE(SUCCEED); } @@ -3003,7 +3181,7 @@ H5T_insert(H5T_t *parent, const char *name, size_t offset, const H5T_t *member) /* check args */ assert(parent && H5T_COMPOUND == parent->type); - assert(!parent->locked); + assert(H5T_STATE_TRANSIENT==parent->state); assert(member); assert(name && *name); @@ -3036,12 +3214,11 @@ H5T_insert(H5T_t *parent, const char *name, size_t offset, const H5T_t *member) } /* Add member to end of member array */ - H5T_unshare (parent); i = parent->u.compnd.nmembs; parent->u.compnd.memb[i].name = H5MM_xstrdup(name); parent->u.compnd.memb[i].offset = offset; parent->u.compnd.memb[i].ndims = 0; /*defaults to scalar */ - parent->u.compnd.memb[i].type = H5T_copy (member); + parent->u.compnd.memb[i].type = H5T_copy (member, H5T_COPY_ALL); parent->u.compnd.nmembs++; FUNC_LEAVE(SUCCEED); @@ -3074,9 +3251,8 @@ H5T_pack(H5T_t *dt) FUNC_ENTER(H5T_pack, FAIL); assert(dt); - assert(!dt->locked); + assert(H5T_STATE_TRANSIENT==dt->state); - H5T_unshare (dt); if (H5T_COMPOUND == dt->type) { /* Recursively pack the members */ for (i = 0; i < dt->u.compnd.nmembs; i++) { @@ -3534,8 +3710,8 @@ H5T_path_find(const char *name, const H5T_t *src, const H5T_t *dst, /* insert */ path = H5T_path_g + md; HDmemset(path, 0, sizeof(H5T_path_t)); - path->src = H5T_copy(src); - path->dst = H5T_copy(dst); + path->src = H5T_copy(src, H5T_COPY_ALL); + path->dst = H5T_copy(dst, H5T_COPY_ALL); /* Associate a function with the path if possible */ if (func) { @@ -3545,8 +3721,10 @@ H5T_path_find(const char *name, const H5T_t *src, const H5T_t *dst, path->is_hard = TRUE; path->cdata.command = H5T_CONV_INIT; path->cdata.stats = H5MM_xcalloc (1, sizeof(H5T_stats_t)); - if ((src_id=H5I_register(H5_DATATYPE, H5T_copy(path->src))) < 0 || - (dst_id=H5I_register(H5_DATATYPE, H5T_copy(path->dst))) < 0) { + if ((src_id=H5I_register(H5_DATATYPE, + H5T_copy(path->src, H5T_COPY_ALL))) < 0 || + (dst_id=H5I_register(H5_DATATYPE, + H5T_copy(path->dst, H5T_COPY_ALL))) < 0) { HRETURN_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register conv types for query"); } @@ -3567,9 +3745,11 @@ H5T_path_find(const char *name, const H5T_t *src, const H5T_t *dst, continue; } if ((src_id=H5I_register(H5_DATATYPE, - H5T_copy(path->src))) < 0 || + H5T_copy(path->src, + H5T_COPY_ALL))) < 0 || (dst_id=H5I_register(H5_DATATYPE, - H5T_copy(path->dst))) < 0) { + H5T_copy(path->dst, + H5T_COPY_ALL))) < 0) { HRETURN_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register conv types for query"); } @@ -3665,7 +3845,7 @@ H5T_timer_end (H5_timer_t *timer, H5T_cdata_t *cdata, size_t nelmts) herr_t H5T_debug(H5T_t *dt, FILE * stream) { - const char *s = ""; + const char *s1="", *s2=""; int i, j; uint64 tmp; @@ -3677,53 +3857,70 @@ H5T_debug(H5T_t *dt, FILE * stream) switch (dt->type) { case H5T_INTEGER: - s = "int"; + s1 = "int"; break; case H5T_FLOAT: - s = "float"; + s1 = "float"; break; case H5T_TIME: - s = "time"; + s1 = "time"; break; case H5T_STRING: - s = "str"; + s1 = "str"; break; case H5T_BITFIELD: - s = "bits"; + s1 = "bits"; break; case H5T_OPAQUE: - s = "opaque"; + s1 = "opaque"; break; case H5T_COMPOUND: - s = "struct"; + s1 = "struct"; break; default: - s = ""; + s1 = ""; + break; + } + + switch (dt->state) { + case H5T_STATE_TRANSIENT: + s2 = "[transient]"; + break; + case H5T_STATE_RDONLY: + s2 = "[constant]"; + break; + case H5T_STATE_IMMUTABLE: + s2 = "[predefined]"; + break; + case H5T_STATE_NAMED: + s2 = "[named,closed]"; + break; + case H5T_STATE_OPEN: + s2 = "[named,open]"; break; } - fprintf(stream, "%s%s {nbytes=%lu", - s, dt->locked ? "[!]" : "", (unsigned long)(dt->size)); + fprintf(stream, "%s%s {nbytes=%lu", s1, s2, (unsigned long)(dt->size)); if (H5T_is_atomic(dt)) { switch (dt->u.atomic.order) { case H5T_ORDER_BE: - s = "BE"; + s1 = "BE"; break; case H5T_ORDER_LE: - s = "LE"; + s1 = "LE"; break; case H5T_ORDER_VAX: - s = "VAX"; + s1 = "VAX"; break; case H5T_ORDER_NONE: - s = "NONE"; + s1 = "NONE"; break; default: - s = "order?"; + s1 = "order?"; break; } - fprintf(stream, ", %s", s); + fprintf(stream, ", %s", s1); if (dt->u.atomic.offset) { fprintf(stream, ", offset=%lu", @@ -3737,39 +3934,39 @@ H5T_debug(H5T_t *dt, FILE * stream) case H5T_INTEGER: switch (dt->u.atomic.u.i.sign) { case H5T_SGN_NONE: - s = "unsigned"; + s1 = "unsigned"; break; case H5T_SGN_2: - s = NULL; + s1 = NULL; break; default: - s = "sign?"; + s1 = "sign?"; break; } - if (s) - fprintf(stream, ", %s", s); + if (s1) + fprintf(stream, ", %s", s1); break; case H5T_FLOAT: switch (dt->u.atomic.u.f.norm) { case H5T_NORM_IMPLIED: - s = "implied"; + s1 = "implied"; break; case H5T_NORM_MSBSET: - s = "msbset"; + s1 = "msbset"; break; case H5T_NORM_NONE: - s = "no-norm"; + s1 = "no-norm"; break; default: - s = "norm?"; + s1 = "norm?"; break; } fprintf(stream, ", sign=%lu+1", (unsigned long) (dt->u.atomic.u.f.sign)); fprintf(stream, ", mant=%lu+%lu (%s)", (unsigned long) (dt->u.atomic.u.f.mpos), - (unsigned long) (dt->u.atomic.u.f.msize), s); + (unsigned long) (dt->u.atomic.u.f.msize), s1); fprintf(stream, ", exp=%lu+%lu", (unsigned long) (dt->u.atomic.u.f.epos), (unsigned long) (dt->u.atomic.u.f.esize)); diff --git a/src/H5Tconv.c b/src/H5Tconv.c index 9a0f833..626859d 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -243,12 +243,13 @@ H5T_conv_struct_init (H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata) } } if (priv->src2dst[i]>=0) { - type = H5T_copy (src->u.compnd.memb[i].type); + type = H5T_copy (src->u.compnd.memb[i].type, H5T_COPY_ALL); tid = H5I_register (H5_DATATYPE, type); assert (tid>=0); priv->src_memb_id[priv->src2dst[i]] = tid; - type = H5T_copy (dst->u.compnd.memb[priv->src2dst[i]].type); + type = H5T_copy (dst->u.compnd.memb[priv->src2dst[i]].type, + H5T_COPY_ALL); tid = H5I_register (H5_DATATYPE, type); assert (tid>=0); priv->dst_memb_id[priv->src2dst[i]] = tid; diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h index bb2bc2b..dea8b48 100644 --- a/src/H5Tpkg.h +++ b/src/H5Tpkg.h @@ -63,10 +63,18 @@ typedef struct H5T_compnd_t { struct H5T_member_t *memb; /*array of struct members */ } H5T_compnd_t; +typedef enum H5T_state_t { + H5T_STATE_TRANSIENT, /*type is a modifiable transient */ + H5T_STATE_RDONLY, /*transient, not modifiable, closable*/ + H5T_STATE_IMMUTABLE, /*constant, not closable */ + H5T_STATE_NAMED, /*named constant, not open */ + H5T_STATE_OPEN /*named constant, open object header */ +} H5T_state_t; + struct H5T_t { - hbool_t locked; /*if locked, then can't be modified */ - H5HG_t sh_heap; /*if defined, type is in global heap */ - H5F_t *sh_file; /*file pointer if this is a shared type */ + H5T_state_t state; /*current state of the type */ + H5G_entry_t ent; /*the type is a named type */ + H5F_t *sh_file;/*file pointer if this is a shared type */ H5T_class_t type; /*which class of type is this? */ size_t size; /*total size of an instance of this type */ union { diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h index 0a1178a..26fe27b 100644 --- a/src/H5Tprivate.h +++ b/src/H5Tprivate.h @@ -34,16 +34,22 @@ typedef struct H5T_stats_t { #endif } H5T_stats_t; +/* How to copy a data type */ +typedef enum H5T_copy_t { + H5T_COPY_TRANSIENT, + H5T_COPY_ALL, + H5T_COPY_REOPEN +} H5T_copy_t; /* Private functions */ herr_t H5T_init (void); herr_t H5T_init_interface (void); +H5T_t *H5T_open (H5G_t *loc, const char *name); H5T_t *H5T_create (H5T_class_t type, size_t size); -H5T_t *H5T_copy (const H5T_t *old_dt); +H5T_t *H5T_copy (const H5T_t *old_dt, H5T_copy_t method); +herr_t H5T_commit (H5G_t *loc, const char *name, H5T_t *type); +herr_t H5T_lock (H5T_t *dt, hbool_t immutable); herr_t H5T_close (H5T_t *dt); -herr_t H5T_share (H5F_t *f, H5T_t *dt); -herr_t H5T_unshare (H5T_t *dt); -intn H5T_invalidate_cb (void *obj, const void *call_data); size_t H5T_get_size (const H5T_t *dt); intn H5T_cmp (const H5T_t *dt1, const H5T_t *dt2); hbool_t H5T_is_atomic (const H5T_t *dt); diff --git a/src/H5Tpublic.h b/src/H5Tpublic.h index 1fc4477..1d7885a 100644 --- a/src/H5Tpublic.h +++ b/src/H5Tpublic.h @@ -178,13 +178,14 @@ extern hid_t H5T_NATIVE_BITFIELD_g; extern hid_t H5T_NATIVE_OPAQUE_g; /* Operations defined on all data types */ +hid_t H5Topen (hid_t loc_id, const char *name); hid_t H5Tcreate (H5T_class_t type, size_t size); hid_t H5Tcopy (hid_t type_id); herr_t H5Tclose (hid_t type_id); hbool_t H5Tequal (hid_t type1_id, hid_t type2_id); herr_t H5Tlock (hid_t type_id); -herr_t H5Tshare (hid_t location_id, hid_t type_id); -hbool_t H5Tis_shared (hid_t location_id, hid_t type_id); +herr_t H5Tcommit (hid_t loc_id, const char *name, hid_t type_id); +hbool_t H5Tcommitted (hid_t type_id); /* Operations defined on compound data types */ herr_t H5Tinsert (hid_t parent_id, const char *name, size_t offset, diff --git a/src/H5detect.c b/src/H5detect.c index 3f7c251..9b7959b 100644 --- a/src/H5detect.c +++ b/src/H5detect.c @@ -306,7 +306,8 @@ H5T_init (void)\n\ /* The part common to fixed and floating types */ printf("\ dt = H5MM_xcalloc (1, sizeof(H5T_t));\n\ - dt->locked = TRUE;\n\ + dt->state = H5T_STATE_IMMUTABLE;\n\ + H5F_addr_undef (&(dt->ent.header));\n\ dt->type = H5T_%s;\n\ dt->size = %d;\n\ dt->u.atomic.order = H5T_ORDER_%s;\n\ diff --git a/src/h5ls.c b/src/h5ls.c index f96448c..64207be 100644 --- a/src/h5ls.c +++ b/src/h5ls.c @@ -89,6 +89,9 @@ list (hid_t group, const char *name, void __unused__ *op_data) strcpy (buf+sizeof(buf)-4, "..."); } printf (" -> %s\n", buf); + } else if ((obj=H5Topen (group, name))>=0) { + printf ("Data type\n"); + H5Tclose (obj); } else { printf ("Unknown Type\n"); } -- cgit v0.12