diff options
author | Raymond Lu <songyulu@hdfgroup.org> | 2008-07-22 20:36:31 (GMT) |
---|---|---|
committer | Raymond Lu <songyulu@hdfgroup.org> | 2008-07-22 20:36:31 (GMT) |
commit | 8704820d1c56165fcf930ab21adebea0a48c664f (patch) | |
tree | b74991b3c84c1a6d52e1003c7668863b1fd3dfb4 /src/H5A.c | |
parent | 717388ea0683ff9db970cd8f8998ba9b94d62cf0 (diff) | |
download | hdf5-8704820d1c56165fcf930ab21adebea0a48c664f.zip hdf5-8704820d1c56165fcf930ab21adebea0a48c664f.tar.gz hdf5-8704820d1c56165fcf930ab21adebea0a48c664f.tar.bz2 |
[svn-r15395] When an attribute was opened twice and data was written with one of the handles,
the file didn't have the data. It happened because each handle had its own
object structure, and the empty one overwrote the data with fill value. This is
fixed by making some attribute information like the data be shared in the
attribute structure.
Tested on smirom, kagiso, and linew.
Diffstat (limited to 'src/H5A.c')
-rw-r--r-- | src/H5A.c | 302 |
1 files changed, 163 insertions, 139 deletions
@@ -85,9 +85,12 @@ static herr_t H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_ /* Local Variables */ /*******************/ -/* Declare the free lists for H5A_t's */ +/* Declare the free lists of H5A_t */ H5FL_DEFINE(H5A_t); +/* Declare the free lists for H5A_shared_t's */ +H5FL_DEFINE(H5A_shared_t); + /* Declare a free list to manage blocks of type conversion data */ H5FL_BLK_DEFINE(attr_buf); @@ -392,9 +395,12 @@ H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type, if((attr = H5FL_CALLOC(H5A_t)) == NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for attribute info") + if(NULL == (attr->shared = H5FL_CALLOC(H5A_shared_t))) + HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate shared attr structure") + /* If the creation property list is H5P_DEFAULT, use the default character encoding */ if(acpl_id == H5P_DEFAULT) - attr->encoding = H5F_DEFAULT_CSET; + attr->shared->encoding = H5F_DEFAULT_CSET; else { H5P_genplist_t *ac_plist; /* ACPL Property list */ @@ -402,59 +408,59 @@ H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type, if(NULL == (ac_plist = (H5P_genplist_t *)H5I_object(acpl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") - if(H5P_get(ac_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &(attr->encoding)) < 0) + if(H5P_get(ac_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &(attr->shared->encoding)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get character encoding flag") } /* end else */ /* Copy the attribute name */ - attr->name = H5MM_xstrdup(name); + attr->shared->name = H5MM_xstrdup(name); /* Copy the attribute's datatype */ - attr->dt = H5T_copy(type, H5T_COPY_ALL); + attr->shared->dt = H5T_copy(type, H5T_COPY_ALL); /* Mark any datatypes as being on disk now */ - if(H5T_set_loc(attr->dt, loc->oloc->file, H5T_LOC_DISK) < 0) + if(H5T_set_loc(attr->shared->dt, loc->oloc->file, H5T_LOC_DISK) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location") /* Set the latest format for datatype, if requested */ if(H5F_USE_LATEST_FORMAT(loc->oloc->file)) - if(H5T_set_latest_version(attr->dt) < 0) + if(H5T_set_latest_version(attr->shared->dt) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set latest version of datatype") /* Copy the dataspace for the attribute */ - attr->ds = H5S_copy(space, FALSE, TRUE); + attr->shared->ds = H5S_copy(space, FALSE, TRUE); /* Set the latest format for dataspace, if requested */ if(H5F_USE_LATEST_FORMAT(loc->oloc->file)) - if(H5S_set_latest_version(attr->ds) < 0) + if(H5S_set_latest_version(attr->shared->ds) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set latest version of dataspace") /* Mark it initially set to initialized */ - attr->initialized = TRUE; /*for now, set to false later*/ + attr->shared->initialized = TRUE; /*for now, set to false later*/ /* Copy the object header information */ - if(H5O_loc_copy(&(attr->oloc), loc->oloc, H5_COPY_DEEP) < 0) + if(H5O_loc_copy(&(attr->shared->oloc), loc->oloc, H5_COPY_DEEP) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy entry") /* Deep copy of the group hierarchy path */ if(H5G_name_copy(&(attr->path), loc->path, H5_COPY_DEEP) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy path") + HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "unable to copy path") /* Check if any of the pieces should be (or are already) shared in the * SOHM table */ - if(H5SM_try_share(attr->oloc.file, dxpl_id, NULL, H5O_DTYPE_ID, attr->dt, NULL) < 0) + if(H5SM_try_share(attr->shared->oloc.file, dxpl_id, NULL, H5O_DTYPE_ID, attr->shared->dt, NULL) < 0) HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "trying to share datatype failed") - if(H5SM_try_share(attr->oloc.file, dxpl_id, NULL, H5O_SDSPACE_ID, attr->ds, NULL) < 0) + if(H5SM_try_share(attr->shared->oloc.file, dxpl_id, NULL, H5O_SDSPACE_ID, attr->shared->ds, NULL) < 0) HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "trying to share dataspace failed") /* Check whether datatype is committed & increment ref count * (to maintain ref. count incr/decr similarity with "shared message" * type of datatype sharing) */ - if(H5T_committed(attr->dt)) { + if(H5T_committed(attr->shared->dt)) { /* Increment the reference count on the shared datatype */ - if(H5T_link(attr->dt, 1, dxpl_id) < 0) + if(H5T_link(attr->shared->dt, 1, dxpl_id) < 0) HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared datatype link count") } /* end if */ @@ -462,29 +468,29 @@ H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type, * datatype and dataspace messages themselves, or the size of the "shared" * messages if either or both of them are shared. */ - attr->dt_size = H5O_msg_raw_size(attr->oloc.file, H5O_DTYPE_ID, FALSE, attr->dt); - attr->ds_size = H5O_msg_raw_size(attr->oloc.file, H5O_SDSPACE_ID, FALSE, attr->ds); + attr->shared->dt_size = H5O_msg_raw_size(attr->shared->oloc.file, H5O_DTYPE_ID, FALSE, attr->shared->dt); + attr->shared->ds_size = H5O_msg_raw_size(attr->shared->oloc.file, H5O_SDSPACE_ID, FALSE, attr->shared->ds); /* Get # of elements for attribute's dataspace */ - if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->ds)) < 0) + if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid") H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, size_t); - HDassert(attr->dt_size > 0); - HDassert(attr->ds_size > 0); - attr->data_size = nelmts * H5T_get_size(attr->dt); + HDassert(attr->shared->dt_size > 0); + HDassert(attr->shared->ds_size > 0); + attr->shared->data_size = nelmts * H5T_get_size(attr->shared->dt); /* Hold the symbol table entry (and file) open */ - if(H5O_open(&(attr->oloc)) < 0) + if(H5O_open(&(attr->shared->oloc)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open") attr->obj_opened = TRUE; /* Set the version to encode the attribute with */ - if(H5A_set_version(attr->oloc.file, attr) < 0) + if(H5A_set_version(attr->shared->oloc.file, attr) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "unable to update attribute version") /* Insert the attribute into the object header */ - if(H5O_attr_create(&(attr->oloc), dxpl_id, attr) < 0) + if(H5O_attr_create(&(attr->shared->oloc), dxpl_id, attr) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to create attribute in object header") /* Register the new attribute and get an ID for it */ @@ -492,12 +498,11 @@ H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type, HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register attribute for ID") /* Now it's safe to say it's uninitialized */ - attr->initialized = FALSE; + attr->shared->initialized = FALSE; done: /* Cleanup on failure */ - if(ret_value < 0) - if(attr && H5A_close(attr) < 0) + if(ret_value < 0 && attr && H5A_close(attr) < 0) HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "can't close attribute") FUNC_LEAVE_NOAPI(ret_value) @@ -544,7 +549,7 @@ H5Aopen(hid_t loc_id, const char *attr_name, hid_t UNUSED aapl_id) /* Read in attribute from object header */ if(NULL == (attr = H5O_attr_open_by_name(loc.oloc, attr_name, H5AC_ind_dxpl_id))) HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to load attribute info from object header") - attr->initialized = TRUE; + attr->shared->initialized = TRUE; /* Finish initializing attribute */ if(H5A_open_common(&loc, attr) < 0) @@ -731,7 +736,7 @@ H5A_open_common(const H5G_loc_t *loc, H5A_t *attr) #if defined(H5_USING_MEMCHECKER) || !defined(NDEBUG) /* Clear object location */ - if(H5O_loc_reset(&(attr->oloc)) < 0) + if(H5O_loc_reset(&(attr->shared->oloc)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to reset location") #endif /* H5_USING_MEMCHECKER */ @@ -740,15 +745,15 @@ H5A_open_common(const H5G_loc_t *loc, H5A_t *attr) HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release group hier. path") /* Deep copy of the symbol table entry */ - if(H5O_loc_copy(&(attr->oloc), loc->oloc, H5_COPY_DEEP) < 0) + if(H5O_loc_copy(&(attr->shared->oloc), loc->oloc, H5_COPY_DEEP) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy entry") /* Deep copy of the group hier. path */ if(H5G_name_copy(&(attr->path), loc->path, H5_COPY_DEEP) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy entry") + HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "unable to copy entry") /* Hold the symbol table entry (and file) open */ - if(H5O_open(&(attr->oloc)) < 0) + if(H5O_open(&(attr->shared->oloc)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open") attr->obj_opened = TRUE; @@ -799,7 +804,7 @@ H5A_open_by_idx(const H5G_loc_t *loc, const char *obj_name, H5_index_t idx_type, /* Read in attribute from object header */ if(NULL == (attr = H5O_attr_open_by_idx(obj_loc.oloc, idx_type, order, n, dxpl_id))) HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to load attribute info from object header") - attr->initialized = TRUE; + attr->shared->initialized = TRUE; /* Finish initializing attribute */ if(H5A_open_common(&obj_loc, attr) < 0) @@ -865,7 +870,7 @@ H5A_open_by_name(const H5G_loc_t *loc, const char *obj_name, const char *attr_na /* Read in attribute from object header */ if(NULL == (attr = H5O_attr_open_by_name(obj_loc.oloc, attr_name, dxpl_id))) HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to load attribute info from object header") - attr->initialized = TRUE; + attr->shared->initialized = TRUE; /* Finish initializing attribute */ if(H5A_open_common(loc, attr) < 0) @@ -969,7 +974,7 @@ H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id) HDassert(buf); /* Get # of elements for attribute's dataspace */ - if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->ds)) < 0) + if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid") H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, size_t); @@ -977,17 +982,17 @@ H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id) if(nelmts > 0) { /* Get the memory and file datatype sizes */ src_type_size = H5T_get_size(mem_type); - dst_type_size = H5T_get_size(attr->dt); + dst_type_size = H5T_get_size(attr->shared->dt); /* Convert memory buffer into disk buffer */ /* Set up type conversion function */ - if(NULL == (tpath = H5T_path_find(mem_type, attr->dt, NULL, NULL, dxpl_id, FALSE))) + if(NULL == (tpath = H5T_path_find(mem_type, attr->shared->dt, NULL, NULL, dxpl_id, FALSE))) HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dst datatypes") /* Check for type conversion required */ if(!H5T_path_noop(tpath)) { if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(mem_type, H5T_COPY_ALL))) < 0 || - (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(attr->dt, H5T_COPY_ALL))) < 0) + (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(attr->shared->dt, H5T_COPY_ALL))) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, FAIL, "unable to register types for conversion") /* Get the maximum buffer size needed and allocate it */ @@ -1003,11 +1008,11 @@ H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id) HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "datatype conversion failed") /* Free the previous attribute data buffer, if there is one */ - if(attr->data) - attr->data = H5FL_BLK_FREE(attr_buf, attr->data); + if(attr->shared->data) + attr->shared->data = H5FL_BLK_FREE(attr_buf, attr->shared->data); /* Set the pointer to the attribute data to the converted information */ - attr->data = tconv_buf; + attr->shared->data = tconv_buf; tconv_owned = TRUE; } /* end if */ /* No type conversion necessary */ @@ -1015,21 +1020,21 @@ H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id) HDassert(dst_type_size == src_type_size); /* Allocate the attribute buffer, if there isn't one */ - if(attr->data == NULL) - if(NULL == (attr->data = H5FL_BLK_MALLOC(attr_buf, dst_type_size * nelmts))) + if(attr->shared->data == NULL) + if(NULL == (attr->shared->data = H5FL_BLK_MALLOC(attr_buf, dst_type_size * nelmts))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") /* Copy the attribute data into the user's buffer */ - HDmemcpy(attr->data, buf, (dst_type_size * nelmts)); + HDmemcpy(attr->shared->data, buf, (dst_type_size * nelmts)); } /* end else */ /* Modify the attribute in the object header */ - if(H5O_attr_write(&(attr->oloc), dxpl_id, attr) < 0) + if(H5O_attr_write(&(attr->shared->oloc), dxpl_id, attr) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to modify attribute") } /* end if */ /* Indicate the the attribute doesn't need fill-values */ - attr->initialized = TRUE; + attr->shared->initialized = TRUE; done: /* Release resources */ @@ -1126,27 +1131,27 @@ H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_t dxpl_id) HDassert(buf); /* Create buffer for data to store on disk */ - if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->ds)) < 0) + if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid") H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, size_t); if(nelmts > 0) { /* Get the memory and file datatype sizes */ - src_type_size = H5T_get_size(attr->dt); + src_type_size = H5T_get_size(attr->shared->dt); dst_type_size = H5T_get_size(mem_type); /* Check if the attribute has any data yet, if not, fill with zeroes */ - if(attr->obj_opened && !attr->initialized) + if(attr->obj_opened && !attr->shared->initialized) HDmemset(buf, 0, (dst_type_size * nelmts)); else { /* Attribute exists and has a value */ /* Convert memory buffer into disk buffer */ /* Set up type conversion function */ - if(NULL == (tpath = H5T_path_find(attr->dt, mem_type, NULL, NULL, dxpl_id, FALSE))) + if(NULL == (tpath = H5T_path_find(attr->shared->dt, mem_type, NULL, NULL, dxpl_id, FALSE))) HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dst datatypes") /* Check for type conversion required */ if(!H5T_path_noop(tpath)) { - if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(attr->dt, H5T_COPY_ALL))) < 0 || + if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(attr->shared->dt, H5T_COPY_ALL))) < 0 || (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(mem_type, H5T_COPY_ALL))) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, FAIL, "unable to register types for conversion") @@ -1156,7 +1161,7 @@ H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_t dxpl_id) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") /* Copy the attribute data into the buffer for conversion */ - HDmemcpy(tconv_buf, attr->data, (src_type_size * nelmts)); + HDmemcpy(tconv_buf, attr->shared->data, (src_type_size * nelmts)); /* Perform datatype conversion. */ if(H5T_convert(tpath, src_id, dst_id, nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, dxpl_id) < 0) @@ -1170,7 +1175,7 @@ H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_t dxpl_id) HDassert(dst_type_size == src_type_size); /* Copy the attribute data into the user's buffer */ - HDmemcpy(buf, attr->data, (dst_type_size * nelmts)); + HDmemcpy(buf, attr->shared->data, (dst_type_size * nelmts)); } /* end else */ } /* end else */ } /* end if */ @@ -1221,7 +1226,7 @@ H5Aget_space(hid_t attr_id) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute") /* Copy the attribute's dataspace */ - if(NULL == (ds = H5S_copy(attr->ds, FALSE, TRUE))) + if(NULL == (ds = H5S_copy(attr->shared->ds, FALSE, TRUE))) HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to copy dataspace") /* Atomize */ @@ -1271,7 +1276,7 @@ H5Aget_type(hid_t attr_id) * reopen the type before returning it to the user. Make the type * read-only. */ - if(NULL == (dt = H5T_copy(attr->dt, H5T_COPY_REOPEN))) + if(NULL == (dt = H5T_copy(attr->shared->dt, H5T_COPY_REOPEN))) HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to copy datatype") /* Mark any datatypes as being in memory now */ @@ -1340,7 +1345,7 @@ H5Aget_create_plist(hid_t attr_id) HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "can't get property list") /* Set the character encoding on the new property list */ - if(H5P_set(new_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &(attr->encoding)) < 0) + if(H5P_set(new_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &(attr->shared->encoding)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set character encoding") ret_value = new_plist_id; @@ -1374,21 +1379,53 @@ done: ssize_t H5Aget_name(hid_t attr_id, size_t buf_size, char *buf) { - H5A_t *attr; /* Attribute object for ID */ - size_t copy_len, nbytes; + H5A_t *my_attr; /* Attribute object for ID */ ssize_t ret_value; FUNC_ENTER_API(H5Aget_name, FAIL) H5TRACE3("Zs", "iz*s", attr_id, buf_size, buf); /* check arguments */ - if(NULL == (attr = (H5A_t *)H5I_object_verify(attr_id, H5I_ATTR))) + if(NULL == (my_attr = (H5A_t *)H5I_object_verify(attr_id, H5I_ATTR))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute") if(!buf && buf_size) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid buffer") + /* Call private function in turn */ + if(0 > (ret_value = H5A_get_name(my_attr, buf_size, buf))) + HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get attribute name") + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Aget_name() */ + + +/*-------------------------------------------------------------------------- + NAME + H5A_get_name + PURPOSE + Private function for H5Aget_name. Gets a copy of the name for an + attribute + RETURNS + This function returns the length of the attribute's name (which may be + longer than 'buf_size') on success or negative for failure. + DESCRIPTION + This function retrieves the name of an attribute for an attribute ID. + Up to 'buf_size' characters are stored in 'buf' followed by a '\0' string + terminator. If the name of the attribute is longer than 'buf_size'-1, + the string terminator is stored in the last position of the buffer to + properly terminate the string. +--------------------------------------------------------------------------*/ +ssize_t +H5A_get_name(H5A_t *attr, size_t buf_size, char *buf) +{ + size_t copy_len, nbytes; + ssize_t ret_value; + + FUNC_ENTER_NOAPI(H5A_get_name, FAIL) + /* get the real attribute length */ - nbytes = HDstrlen(attr->name); + nbytes = HDstrlen(attr->shared->name); HDassert((ssize_t)nbytes >= 0); /*overflow, pretty unlikely --rpm*/ /* compute the string length which will fit into the user's buffer */ @@ -1396,7 +1433,7 @@ H5Aget_name(hid_t attr_id, size_t buf_size, char *buf) /* Copy all/some of the name */ if(buf && copy_len > 0) { - HDmemcpy(buf, attr->name, copy_len); + HDmemcpy(buf, attr->shared->name, copy_len); /* Terminate the string */ buf[copy_len]='\0'; @@ -1406,8 +1443,8 @@ H5Aget_name(hid_t attr_id, size_t buf_size, char *buf) ret_value = (ssize_t)nbytes; done: - FUNC_LEAVE_API(ret_value) -} /* H5Aget_name() */ + FUNC_LEAVE_NOAPI(ret_value) +} /* H5A_get_name() */ /*------------------------------------------------------------------------- @@ -1462,11 +1499,11 @@ H5Aget_name_by_idx(hid_t loc_id, const char *obj_name, H5_index_t idx_type, HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "can't open attribute") /* Get the length of the name */ - ret_value = (ssize_t)HDstrlen(attr->name); + ret_value = (ssize_t)HDstrlen(attr->shared->name); /* Copy the name into the user's buffer, if given */ if(name) { - HDstrncpy(name, attr->name, MIN((size_t)(ret_value + 1), size)); + HDstrncpy(name, attr->shared->name, MIN((size_t)(ret_value + 1), size)); if((size_t)ret_value >= size) name[size - 1]='\0'; } /* end if */ @@ -1511,7 +1548,7 @@ H5Aget_storage_size(hid_t attr_id) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not an attribute") /* Set return value */ - ret_value = attr->data_size; + ret_value = attr->shared->data_size; done: FUNC_LEAVE_API(ret_value) @@ -1698,15 +1735,15 @@ H5A_get_info(const H5A_t *attr, H5A_info_t *ainfo) HDassert(ainfo); /* Set info for attribute */ - ainfo->cset = attr->encoding; - ainfo->data_size = attr->data_size; - if(attr->crt_idx == H5O_MAX_CRT_ORDER_IDX) { + ainfo->cset = attr->shared->encoding; + ainfo->data_size = attr->shared->data_size; + if(attr->shared->crt_idx == H5O_MAX_CRT_ORDER_IDX) { ainfo->corder_valid = FALSE; ainfo->corder = 0; } /* end if */ else { ainfo->corder_valid = TRUE; - ainfo->corder = attr->crt_idx; + ainfo->corder = attr->shared->crt_idx; } /* end else */ done: @@ -2259,6 +2296,10 @@ done: * Programmer: Robb Matzke * Thursday, December 4, 1997 * + * Modification:Raymond Lu + * 4 June 2008 + * Changed some attribute information to be shared. + * *------------------------------------------------------------------------- */ H5A_t * @@ -2275,7 +2316,7 @@ H5A_copy(H5A_t *_new_attr, const H5A_t *old_attr) /* Allocate attribute structure */ if(_new_attr == NULL) { - if(NULL == (new_attr = H5FL_MALLOC(H5A_t))) + if(NULL == (new_attr = H5FL_CALLOC(H5A_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") allocated_attr = TRUE; } /* end if */ @@ -2283,44 +2324,20 @@ H5A_copy(H5A_t *_new_attr, const H5A_t *old_attr) new_attr = _new_attr; /* Copy the top level of the attribute */ - *new_attr = *old_attr; + new_attr->sh_loc = old_attr->sh_loc; - /* Don't open the object header for a copy */ - new_attr->obj_opened = FALSE; - - /* Copy the guts of the attribute */ - if(NULL == (new_attr->name = H5MM_xstrdup(old_attr->name))) - HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "unable to copy attribute name") - if(NULL == (new_attr->dt = H5T_copy(old_attr->dt, H5T_COPY_ALL))) - HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "unable to copy attribute datatype") - if(NULL == (new_attr->ds = H5S_copy(old_attr->ds, FALSE, TRUE))) - HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "unable to copy attribute dataspace") - -#if defined(H5_USING_MEMCHECKER) || !defined(NDEBUG) - /* Clear object location */ - if(H5O_loc_reset(&(new_attr->oloc)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to reset location") - - /* Clear path name */ - if(H5G_name_reset(&(new_attr->path)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to reset path") -#endif /* H5_USING_MEMCHECKER */ - - /* Copy the object location and group path */ - if(H5O_loc_copy(&(new_attr->oloc), &(old_attr->oloc), H5_COPY_DEEP) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "can't copy object location") + /* Deep copy of the group hierarchy path */ if(H5G_name_copy(&(new_attr->path), &(old_attr->path), H5_COPY_DEEP) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "can't copy path") + HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "unable to copy path") - /* Copy the attribute data, if there is any */ - if(old_attr->data) { - /* Allocate data buffer for new attribute */ - if(NULL == (new_attr->data = H5FL_BLK_MALLOC(attr_buf, old_attr->data_size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + /* Share some attribute information */ + new_attr->shared = old_attr->shared; - /* Copy the attribute data */ - HDmemcpy(new_attr->data, old_attr->data, old_attr->data_size); - } /* end if */ + /* Increment reference count for shared object */ + new_attr->shared->nrefs++; + + /* Don't open the object header for a copy */ + new_attr->obj_opened = FALSE; /* Set the return value */ ret_value = new_attr; @@ -2359,18 +2376,22 @@ H5A_free(H5A_t *attr) HDassert(attr); /* Free dynamicly allocated items */ - if(attr->name) - H5MM_xfree(attr->name); - if(attr->dt) - if(H5T_close(attr->dt) < 0) + if(attr->shared->name) { + H5MM_xfree(attr->shared->name); + attr->shared->name = NULL; + } + if(attr->shared->dt) { + if(H5T_close(attr->shared->dt) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release datatype info") - if(attr->ds) - if(H5S_close(attr->ds) < 0) + attr->shared->dt = NULL; + } + if(attr->shared->ds) { + if(H5S_close(attr->shared->ds) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release dataspace info") - if(attr->data) - attr->data = H5FL_BLK_FREE(attr_buf, attr->data); - if(H5G_name_free(&(attr->path)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release group hier. path") + attr->shared->ds = NULL; + } + if(attr->shared->data) + attr->shared->data = H5FL_BLK_FREE(attr_buf, attr->shared->data); done: FUNC_LEAVE_NOAPI(ret_value) @@ -2388,7 +2409,9 @@ done: * Monday, December 8, 1997 * * Modifications: - * + * Raymond Lu + * 4 June 2008 + * Changed some attribute object information to be shared. *------------------------------------------------------------------------- */ herr_t @@ -2399,30 +2422,31 @@ H5A_close(H5A_t *attr) FUNC_ENTER_NOAPI(H5A_close, FAIL) HDassert(attr); - - /* Check if the attribute has any data yet, if not, fill with zeroes */ - if(attr->obj_opened && !attr->initialized && attr->data_size) { - uint8_t *tmp_buf = H5FL_BLK_CALLOC(attr_buf, attr->data_size); - if(NULL == tmp_buf) - HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "memory allocation failed for attribute fill-value") - - /* Go write the fill data to the attribute */ - if(H5A_write(attr, attr->dt, tmp_buf, H5AC_dxpl_id) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL, "unable to write attribute") - - /* Free temporary buffer */ - H5FL_BLK_FREE(attr_buf, tmp_buf); - } /* end if */ - - /* Free dynamicly allocated items */ - if(H5A_free(attr) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release attribute info") + HDassert(attr->shared); /* Close the object's symbol-table entry */ - if(attr->obj_opened) - if(H5O_close(&(attr->oloc)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release object header info") + if(attr->obj_opened && (H5O_close(&(attr->shared->oloc)) < 0)) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release object header info") + + /* Reference count can be 0. It only happens when H5A_create fails. */ + if(1 >= attr->shared->nrefs) { + /* Free dynamicly allocated items */ + if(H5A_free(attr) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release attribute info") + + /* Destroy shared attribute struct */ + attr->shared = H5FL_FREE(H5A_shared_t, attr->shared); + } else if(attr->shared->nrefs > 1) { + /* There are other references to the shared part of the attribute. + * Only decrement the reference count. */ + --attr->shared->nrefs; + } + + /* Free group hierarchy path */ + if(H5G_name_free(&(attr->path)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release group hier. path") + attr->shared = NULL; H5FL_FREE(H5A_t, attr); done: @@ -2455,7 +2479,7 @@ H5A_oloc(H5A_t *attr) HDassert(attr); /* Set return value */ - ret_value = &(attr->oloc); + ret_value = &(attr->shared->oloc); done: FUNC_LEAVE_NOAPI(ret_value) |