diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2007-05-14 20:24:08 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2007-05-14 20:24:08 (GMT) |
commit | 31ff357f3190a869147378a9a136510be2caafd7 (patch) | |
tree | 5220b17a8e4b6c434b799108719a1dc15d6c0326 /src | |
parent | 1726061075e9adc99ac2286fb542438acc79c4ab (diff) | |
download | hdf5-31ff357f3190a869147378a9a136510be2caafd7.zip hdf5-31ff357f3190a869147378a9a136510be2caafd7.tar.gz hdf5-31ff357f3190a869147378a9a136510be2caafd7.tar.bz2 |
[svn-r13753] Description:
Check in "unique, but sharable" optimization to ISOHM code, which
allows object header messages that are only used in one object to remain in
the sole user's header, but migrates messages that are used in more than one
header into the ISOHM heap.
Tested on:
Mac OS X/32 10.4.9 (amazon)
FreeBSD/32 6.2 (duty)
Linux/32 2.6 (chicago)
Linux/64 2.6 (chicago2)
Diffstat (limited to 'src')
49 files changed, 1933 insertions, 1081 deletions
@@ -368,12 +368,11 @@ H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type, /* 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, H5O_DTYPE_ID, attr->dt) < 0) + if(H5SM_try_share(attr->oloc.file, dxpl_id, NULL, H5O_DTYPE_ID, attr->dt, NULL) < 0) HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "trying to share datatype failed") - if(H5SM_try_share(attr->oloc.file, dxpl_id, H5O_SDSPACE_ID, attr->ds) < 0) + if(H5SM_try_share(attr->oloc.file, dxpl_id, NULL, H5O_SDSPACE_ID, attr->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) @@ -2022,7 +2021,22 @@ H5A_copy(H5A_t *_new_attr, const H5A_t *old_attr) HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "unable to copy attribute datatype") if(NULL == (new_attr->ds = H5S_copy(old_attr->ds, FALSE))) HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "unable to copy attribute dataspace") -/* XXX: Copy the object location and group path? -QAK */ + +#if defined(H5_USING_PURIFY) || !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_PURIFY */ + + /* 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") + 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") /* Copy the attribute data, if there is any */ if(old_attr->data) { diff --git a/src/H5Abtree2.c b/src/H5Abtree2.c index 02e1bed..e289920 100644 --- a/src/H5Abtree2.c +++ b/src/H5Abtree2.c @@ -193,7 +193,7 @@ H5A_dense_fh_name_cmp(const void *obj, size_t UNUSED obj_len, void *_udata) if(udata->cmp == 0 && udata->found_op) { /* Check whether we should "reconstitute" the shared message info */ if(udata->record->flags & H5O_MSG_FLAG_SHARED) - H5SM_reconstitute(&(attr->sh_loc), udata->record->id); + H5SM_reconstitute(&(attr->sh_loc), udata->f, H5O_ATTR_ID, udata->record->id); /* Set the creation order index for the attribute */ attr->crt_idx = udata->record->corder; @@ -325,7 +325,7 @@ H5A_dense_btree2_name_compare(const void *_bt2_udata, const void *_bt2_rec) #endif /* QAK */ /* Check for attribute in shared storage */ - if(bt2_rec->flags) + if(bt2_rec->flags & H5O_MSG_FLAG_SHARED) fheap = bt2_udata->shared_fheap; else fheap = bt2_udata->fheap; @@ -382,7 +382,7 @@ H5A_dense_btree2_name_compare(const void *_bt2_udata, const void *_bt2_rec) if(ret_value == 0 && bt2_udata->found_op) { /* Check whether we should "reconstitute" the shared message info */ if(bt2_rec->flags & H5O_MSG_FLAG_SHARED) - H5SM_reconstitute(&(attr->sh_loc), bt2_rec->id); + H5SM_reconstitute(&(attr->sh_loc), bt2_udata->f, H5O_ATTR_ID, bt2_rec->id); /* Set the creation order index for the attribute */ attr->crt_idx = bt2_rec->corder; diff --git a/src/H5Adense.c b/src/H5Adense.c index 6e2a1ca..892a334 100644 --- a/src/H5Adense.c +++ b/src/H5Adense.c @@ -364,7 +364,7 @@ H5A_dense_open(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *na } /* end if */ } /* end if */ - /* Create the "udata" information for v2 B-tree record modify */ + /* Create the "udata" information for v2 B-tree record find */ udata.f = f; udata.dxpl_id = dxpl_id; udata.fheap = fheap; @@ -442,11 +442,11 @@ H5A_dense_insert(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, H5A_t *attr) mesg_flags |= H5O_MSG_FLAG_SHARED; else { /* Should this attribute be written as a SOHM? */ - if((shared_mesg = H5SM_try_share(f, dxpl_id, H5O_ATTR_ID, attr)) > 0) - /* Mark the message as shared */ - mesg_flags |= H5O_MSG_FLAG_SHARED; - else if(shared_mesg < 0) + if(H5SM_try_share(f, dxpl_id, NULL, H5O_ATTR_ID, attr, &mesg_flags) < 0) HGOTO_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL, "error determining if message should be shared") + + /* Attributes can't be "unique be shareable" yet */ + HDassert(!(mesg_flags & H5O_MSG_FLAG_SHAREABLE)); } /* end else */ /* Retrieve the address of the shared message's fractal heap */ @@ -607,7 +607,7 @@ H5A_dense_write_bt2_cb(void *_record, void *_op_data, hbool_t *changed) /* Check for modifying shared attribute */ if(record->flags & H5O_MSG_FLAG_SHARED) { /* Update the shared attribute in the SOHM info */ - if(H5O_attr_update_shared(op_data->f, op_data->dxpl_id, op_data->attr, NULL) < 0) + if(H5O_attr_update_shared(op_data->f, op_data->dxpl_id, NULL, op_data->attr, NULL) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update attribute in shared storage") /* Update record's heap ID */ @@ -811,7 +811,7 @@ H5A_dense_copy_fh_cb(const void *obj, size_t UNUSED obj_len, void *_udata) /* Check whether we should "reconstitute" the shared message info */ if(udata->record->flags & H5O_MSG_FLAG_SHARED) - H5SM_reconstitute(&(udata->attr->sh_loc), udata->record->id); + H5SM_reconstitute(&(udata->attr->sh_loc), udata->f, H5O_ATTR_ID, udata->record->id); done: FUNC_LEAVE_NOAPI(ret_value) @@ -900,7 +900,7 @@ H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char * else if(shared_mesg > 0) { /* Reset shared status of copy */ /* (so it will get shared again if necessary) */ - attr_copy->sh_loc.flags = 0; + attr_copy->sh_loc.type = H5O_SHARE_TYPE_UNSHARED; } /* end if */ /* Change name of attribute */ @@ -929,14 +929,14 @@ H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char * */ if(attr_rc == 1) { /* Increment reference count on attribute components */ - if(H5O_attr_link(f, dxpl_id, attr_copy) < 0) + if(H5O_attr_link(f, dxpl_id, NULL, attr_copy) < 0) HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust attribute link count") } /* end if */ } /* end if */ else if(shared_mesg == 0) { /* Increment reference count on attribute components */ /* (so that they aren't deleted when the attribute is removed shortly) */ - if(H5O_attr_link(f, dxpl_id, attr_copy) < 0) + if(H5O_attr_link(f, dxpl_id, NULL, attr_copy) < 0) HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust attribute link count") } /* end if */ else if(shared_mesg < 0) @@ -1209,7 +1209,7 @@ H5A_dense_remove_bt2_cb(const void *_record, void *_udata) /* Set up the user data for the v2 B-tree 'record remove' callback */ udata->common.corder = attr->crt_idx; - /* Remove the record from the name index v2 B-tree */ + /* Remove the record from the creation order index v2 B-tree */ if(H5B2_remove(udata->common.f, udata->common.dxpl_id, H5A_BT2_CORDER, udata->corder_bt2_addr, udata, NULL, NULL) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTREMOVE, FAIL, "unable to remove attribute from creation order index v2 B-tree") } /* end if */ @@ -1217,13 +1217,13 @@ H5A_dense_remove_bt2_cb(const void *_record, void *_udata) /* Check for removing shared attribute */ if(record->flags & H5O_MSG_FLAG_SHARED) { /* Decrement the reference count on the shared attribute message */ - if(H5SM_try_delete(udata->common.f, udata->common.dxpl_id, H5O_ATTR_ID, &(attr->sh_loc)) < 0) + if(H5SM_delete(udata->common.f, udata->common.dxpl_id, NULL, &(attr->sh_loc)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to delete shared attribute") } /* end if */ else { /* Perform the deletion action on the attribute */ /* (takes care of shared & committed datatype/dataspace components) */ - if(H5O_attr_delete(udata->common.f, udata->common.dxpl_id, attr) < 0) + if(H5O_attr_delete(udata->common.f, udata->common.dxpl_id, NULL, attr) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute") /* Remove record from fractal heap */ @@ -1370,7 +1370,7 @@ H5A_dense_remove_by_idx_bt2_cb(const void *_record, void *_bt2_udata) } /* end if */ else { /* Create a shared message location from the heap ID for this record */ - H5SM_reconstitute(&sh_loc, record->id); + H5SM_reconstitute(&sh_loc, bt2_udata->f, H5O_ATTR_ID, record->id); /* Use the separate shared location */ use_sh_loc = TRUE; @@ -1424,13 +1424,13 @@ H5A_dense_remove_by_idx_bt2_cb(const void *_record, void *_bt2_udata) sh_loc_ptr = &(fh_udata.attr->sh_loc); /* Decrement the reference count on the shared attribute message */ - if(H5SM_try_delete(bt2_udata->f, bt2_udata->dxpl_id, H5O_ATTR_ID, sh_loc_ptr) < 0) + if(H5SM_delete(bt2_udata->f, bt2_udata->dxpl_id, NULL, sh_loc_ptr) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to delete shared attribute") } /* end if */ else { /* Perform the deletion action on the attribute */ /* (takes care of shared & committed datatype/dataspace components) */ - if(H5O_attr_delete(bt2_udata->f, bt2_udata->dxpl_id, fh_udata.attr) < 0) + if(H5O_attr_delete(bt2_udata->f, bt2_udata->dxpl_id, NULL, fh_udata.attr) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute") /* Remove record from fractal heap */ @@ -1689,10 +1689,10 @@ H5A_dense_delete_bt2_cb(const void *_record, void *_bt2_udata) H5O_shared_t sh_mesg; /* Temporary shared message info */ /* "reconstitute" the shared message info for the attribute */ - H5SM_reconstitute(&sh_mesg, record->id); + H5SM_reconstitute(&sh_mesg, bt2_udata->f, H5O_ATTR_ID, record->id); /* Decrement the reference count on the shared attribute message */ - if(H5SM_try_delete(bt2_udata->f, bt2_udata->dxpl_id, H5O_ATTR_ID, &sh_mesg) < 0) + if(H5SM_delete(bt2_udata->f, bt2_udata->dxpl_id, NULL, &sh_mesg) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to delete shared attribute") } /* end if */ else { @@ -1713,7 +1713,7 @@ H5A_dense_delete_bt2_cb(const void *_record, void *_bt2_udata) /* Perform the deletion action on the attribute */ /* (takes care of shared/committed datatype & dataspace components) */ - if(H5O_attr_delete(bt2_udata->f, bt2_udata->dxpl_id, fh_udata.attr) < 0) + if(H5O_attr_delete(bt2_udata->f, bt2_udata->dxpl_id, NULL, fh_udata.attr) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute") } /* end else */ @@ -1766,7 +1766,6 @@ H5A_dense_delete(H5F_t *f, hid_t dxpl_id, H5O_ainfo_t *ainfo) udata.name = NULL; udata.name_hash = 0; udata.flags = 0; - udata.corder = 0; udata.found_op = NULL; /* v2 B-tree comparison callback */ udata.found_op_data = NULL; diff --git a/src/H5Apkg.h b/src/H5Apkg.h index 3d96a9a..10cebee 100644 --- a/src/H5Apkg.h +++ b/src/H5Apkg.h @@ -227,8 +227,8 @@ H5_DLL H5A_t *H5O_attr_open_by_name(const H5O_loc_t *loc, const char *name, hid_t dxpl_id); H5_DLL H5A_t *H5O_attr_open_by_idx(const H5O_loc_t *loc, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, hid_t dxpl_id); -H5_DLL herr_t H5O_attr_update_shared(H5F_t *f, hid_t dxpl_id, H5A_t *attr, - H5O_shared_t *sh_mesg); +H5_DLL herr_t H5O_attr_update_shared(H5F_t *f, hid_t dxpl_id, H5O_t *oh, + H5A_t *attr, H5O_shared_t *sh_mesg); H5_DLL herr_t H5O_attr_write(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr); H5_DLL herr_t H5O_attr_rename(const H5O_loc_t *loc, hid_t dxpl_id, @@ -65,6 +65,9 @@ typedef struct { /* General stuff */ static herr_t H5D_init_storage(H5D_t *dataset, hbool_t full_overwrite, hid_t dxpl_id); static H5D_shared_t *H5D_new(hid_t dcpl_id, hbool_t creating, hbool_t vl_type); +static herr_t H5D_init_type(H5F_t *file, const H5D_t *dset, hid_t type_id, + const H5T_t *type); +static herr_t H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset); static herr_t H5D_open_oid(H5D_t *dataset, hid_t dxpl_id); static herr_t H5D_get_space_status(H5D_t *dset, H5D_space_status_t *allocation, hid_t dxpl_id); static hsize_t H5D_get_storage_size(H5D_t *dset, hid_t dxpl_id); @@ -73,7 +76,6 @@ static herr_t H5D_iterate(void *buf, hid_t type_id, H5S_t *space, H5D_operator_t op, void *operator_data); static herr_t H5D_extend(H5D_t *dataset, const hsize_t *size, hid_t dxpl_id); static herr_t H5D_set_extent(H5D_t *dataset, const hsize_t *size, hid_t dxpl_id); -static herr_t H5D_init_type(H5F_t *file, const H5D_t *dset, hid_t type_id, const H5T_t *type); /*********************/ @@ -1008,7 +1010,7 @@ H5D_init_type(H5F_t *file, const H5D_t *dset, hid_t type_id, const H5T_t *type) htri_t immutable; /* Flag whether the type is immutable */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5D_init_type, FAIL) + FUNC_ENTER_NOAPI_NOINIT(H5D_init_type) /* Sanity checking */ HDassert(file); @@ -1079,7 +1081,7 @@ H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset) hbool_t fill_changed = FALSE; /* Flag indicating the fill value was changed */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5D_update_oh_info, FAIL) + FUNC_ENTER_NOAPI_NOINIT(H5D_update_oh_info) /* Sanity checking */ HDassert(file); @@ -1160,11 +1162,20 @@ H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset) if(H5O_msg_append(file, dxpl_id, oh, H5O_FILL_NEW_ID, H5O_MSG_FLAG_CONSTANT, 0, fill_prop) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update new fill value header message") - /* If there is valid information for the old fill value struct, update it */ + /* If there is valid information for the old fill value struct, add it */ /* (only if we aren't trying to write the latest version of the file format) */ if(fill_prop->buf && !use_latest_format) { + H5O_fill_t old_fill_prop; /* Copy of fill value property, for writing as "old" fill value */ + + /* Shallow copy the fill value property */ + /* (we only want to make certain that the shared component isnt' modified) */ + HDmemcpy(&old_fill_prop, fill_prop, sizeof(old_fill_prop)); + + /* Reset shared component info */ + H5O_msg_reset_share(H5O_FILL_ID, &old_fill_prop); + /* Write old fill value */ - if(H5O_msg_append(file, dxpl_id, oh, H5O_FILL_ID, H5O_MSG_FLAG_CONSTANT, 0, fill_prop) < 0) + if(H5O_msg_append(file, dxpl_id, oh, H5O_FILL_ID, H5O_MSG_FLAG_CONSTANT, 0, &old_fill_prop) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update old fill value header message") } /* end if */ diff --git a/src/H5Gdense.c b/src/H5Gdense.c index 0b7ae9e..a8a54b5 100644 --- a/src/H5Gdense.c +++ b/src/H5Gdense.c @@ -1376,7 +1376,7 @@ H5G_dense_remove_fh_cb(const void *obj, size_t UNUSED obj_len, void *_udata) /* Perform the deletion action on the link, if requested */ /* (call message "delete" callback directly: *ick* - QAK) */ - if(H5O_link_delete(udata->f, udata->dxpl_id, lnk) < 0) + if(H5O_link_delete(udata->f, udata->dxpl_id, NULL, lnk) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete link") done: @@ -1618,7 +1618,7 @@ H5G_dense_remove_by_idx_bt2_cb(const void *_record, void *_bt2_udata) /* Perform the deletion action on the link */ /* (call link message "delete" callback directly: *ick* - QAK) */ - if(H5O_link_delete(bt2_udata->f, bt2_udata->dxpl_id, fh_udata.lnk) < 0) + if(H5O_link_delete(bt2_udata->f, bt2_udata->dxpl_id, NULL, fh_udata.lnk) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete link") /* Release the space allocated for the link */ @@ -1444,7 +1444,7 @@ H5O_delete_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh) */ for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) { /* Free any space referred to in the file from this message */ - if(H5O_delete_mesg(f, dxpl_id, curr_msg) < 0) + if(H5O_delete_mesg(f, dxpl_id, oh, curr_msg) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message") } /* end for */ @@ -1761,11 +1761,10 @@ H5O_loc_hold_file(H5O_loc_t *loc) HDassert(loc->file); /* If this location is not already holding its file open, do so. */ - if(!loc->holding_file) - { + if(!loc->holding_file) { loc->file->nopen_objs++; loc->holding_file = TRUE; - } + } /* end if */ FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5O_loc_hold_file() */ @@ -2088,3 +2087,33 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_obj_create() */ + +/*------------------------------------------------------------------------- + * Function: H5O_get_oh_addr + * + * Purpose: Retrieve the address of the object header + * + * Note: This routine participates in the "Inlining C struct access" + * pattern, don't call it directly, use the appropriate macro + * defined in H5Oprivate.h. + * + * Return: Success: Valid haddr_t + * Failure: HADDR_UNDEF + * + * Programmer: Quincey Koziol + * March 15 2007 + * + *------------------------------------------------------------------------- + */ +haddr_t +H5O_get_oh_addr(const H5O_t *oh) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_get_oh_addr) + + HDassert(oh); + HDassert(oh->chunk); + + FUNC_LEAVE_NOAPI(oh->chunk[0].addr) +} /* end H5O_get_oh_addr() */ + diff --git a/src/H5Oainfo.c b/src/H5Oainfo.c index c49786d..968b165 100644 --- a/src/H5Oainfo.c +++ b/src/H5Oainfo.c @@ -40,11 +40,13 @@ static herr_t H5O_ainfo_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, con static void *H5O_ainfo_copy(const void *_mesg, void *_dest); static size_t H5O_ainfo_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg); static herr_t H5O_ainfo_free(void *_mesg); -static herr_t H5O_ainfo_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg); +static herr_t H5O_ainfo_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, + void *_mesg); static herr_t H5O_ainfo_pre_copy_file(H5F_t *file_src, const void *mesg_src, hbool_t *deleted, const H5O_copy_t *cpy_info, void *udata); static void *H5O_ainfo_copy_file(H5F_t *file_src, void *mesg_src, - H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata); + H5F_t *file_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info, void *udata, + hid_t dxpl_id); static herr_t H5O_ainfo_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -53,7 +55,7 @@ const H5O_msg_class_t H5O_MSG_AINFO[1] = {{ H5O_AINFO_ID, /*message id number */ "ainfo", /*message name for debugging */ sizeof(H5O_ainfo_t), /*native message size */ - FALSE, /* messages are sharable? */ + 0, /* messages are sharable? */ H5O_ainfo_decode, /*decode message */ H5O_ainfo_encode, /*encode message */ H5O_ainfo_copy, /*copy the native value */ @@ -62,7 +64,7 @@ const H5O_msg_class_t H5O_MSG_AINFO[1] = {{ H5O_ainfo_free, /* free method */ H5O_ainfo_delete, /* file delete method */ NULL, /* link method */ - NULL, /*set share method */ + NULL, /*set share method */ NULL, /*can share method */ H5O_ainfo_pre_copy_file, /* pre copy native value to file */ H5O_ainfo_copy_file, /* copy native value to file */ @@ -327,9 +329,9 @@ H5O_ainfo_free(void *mesg) *------------------------------------------------------------------------- */ static herr_t -H5O_ainfo_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg) +H5O_ainfo_delete(H5F_t *f, hid_t dxpl_id, H5O_t UNUSED *open_oh, void *_mesg) { - const H5O_ainfo_t *ainfo = (const H5O_ainfo_t *)_mesg; + H5O_ainfo_t *ainfo = (H5O_ainfo_t *)_mesg; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_ainfo_delete) @@ -340,7 +342,7 @@ H5O_ainfo_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg) /* If the object is using "dense" attribute storage, delete it */ if(H5F_addr_defined(ainfo->fheap_addr)) - if(H5A_dense_delete(f, dxpl_id, (H5O_ainfo_t *)ainfo) < 0) /* Casting away const OK - QAK */ + if(H5A_dense_delete(f, dxpl_id, ainfo) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free dense attribute storage") done: @@ -397,8 +399,8 @@ H5O_ainfo_pre_copy_file(H5F_t UNUSED *file_src, const void UNUSED *native_src, */ static void * H5O_ainfo_copy_file(H5F_t UNUSED *file_src, void *mesg_src, - H5F_t UNUSED *file_dst, hid_t UNUSED dxpl_id, H5O_copy_t UNUSED *cpy_info, - void UNUSED *udata) + H5F_t UNUSED *file_dst, hbool_t UNUSED *recompute_size, + H5O_copy_t UNUSED *cpy_info, void UNUSED *udata, hid_t UNUSED dxpl_id) { H5O_ainfo_t *ainfo_src = (H5O_ainfo_t *)mesg_src; H5O_ainfo_t *ainfo_dst = NULL; diff --git a/src/H5Oalloc.c b/src/H5Oalloc.c index 70c627f..6badfb7 100644 --- a/src/H5Oalloc.c +++ b/src/H5Oalloc.c @@ -1053,7 +1053,7 @@ H5O_release_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5O_mesg_t *mesg, /* Check if we should operate on the message */ if(adj_link) { /* Free any space referred to in the file from this message */ - if(H5O_delete_mesg(f, dxpl_id, mesg) < 0) + if(H5O_delete_mesg(f, dxpl_id, oh, mesg) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message") } /* end if */ diff --git a/src/H5Oattr.c b/src/H5Oattr.c index dbe9b0c..9c6daee 100644 --- a/src/H5Oattr.c +++ b/src/H5Oattr.c @@ -37,7 +37,8 @@ static herr_t H5O_attr_free(void *mesg); static herr_t H5O_attr_pre_copy_file(H5F_t *file_src, const void *mesg_src, hbool_t *deleted, const H5O_copy_t *cpy_info, void *udata); static void *H5O_attr_copy_file(H5F_t *file_src, const H5O_msg_class_t *mesg_type, - void *native_src, H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata); + void *native_src, H5F_t *file_dst, hbool_t *recompute_size, + H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id); static herr_t H5O_attr_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info); @@ -69,7 +70,7 @@ const H5O_msg_class_t H5O_MSG_ATTR[1] = {{ H5O_ATTR_ID, /* message id number */ "attribute", /* message name for debugging */ sizeof(H5A_t), /* native message size */ - TRUE, /* messages are sharable? */ + H5O_SHARE_IS_SHARABLE, /* messages are sharable? */ H5O_attr_shared_decode, /* decode message */ H5O_attr_shared_encode, /* encode message */ H5O_attr_copy, /* copy the native value */ @@ -78,7 +79,7 @@ const H5O_msg_class_t H5O_MSG_ATTR[1] = {{ H5O_attr_free, /* free method */ H5O_attr_shared_delete, /* file delete method */ H5O_attr_shared_link, /* link method */ - H5O_shared_copy, /* set share method */ + NULL, /*set share method */ NULL, /*can share method */ H5O_attr_pre_copy_file, /* pre copy native value to file */ H5O_attr_shared_copy_file, /* copy native value to file */ @@ -243,7 +244,7 @@ H5O_attr_decode(H5F_t *f, hid_t dxpl_id, unsigned UNUSED mesg_flags, ret_value = attr; done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_attr_decode() */ @@ -262,31 +263,15 @@ done: DESCRIPTION This function encodes the native memory form of the attribute message in the "raw" disk form. - * - * Modifications: - * Robb Matzke, 17 Jul 1998 - * Added padding for alignment. - * - * Robb Matzke, 20 Jul 1998 - * Added a version number at the beginning. - * - * Raymond Lu, 8 April 2004 - * For dataspace, changed the operation on H5S_simple_t to - * H5S_extent_t - * - * James Laird, 15 November 2005 - * Added character encoding (version 3) - * --------------------------------------------------------------------------*/ static herr_t H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg) { const H5A_t *attr = (const H5A_t *) mesg; size_t name_len; /* Attribute name length */ - htri_t is_shared_ret; /* Return value from H5O_msg_is_shared */ unsigned version; /* Attribute version */ - hbool_t type_shared; /* Flag to indicate that a shared datatype is used for this attribute */ - hbool_t space_shared; /* Flag to indicate that a shared dataspace is used for this attribute */ + htri_t is_type_shared; /* Flag to indicate that a shared datatype is used for this attribute */ + htri_t is_space_shared; /* Flag to indicate that a shared dataspace is used for this attribute */ hbool_t use_latest_format; /* Flag indicating the newest file format should be used */ unsigned flags = 0; /* Attribute flags */ herr_t ret_value = SUCCEED; /* Return value */ @@ -302,26 +287,18 @@ H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg) use_latest_format = H5F_USE_LATEST_FORMAT(f); /* Check whether datatype and dataspace are shared */ - if((is_shared_ret = H5O_msg_is_shared(H5O_DTYPE_ID, attr->dt)) < 0) + if((is_type_shared = H5O_msg_is_shared(H5O_DTYPE_ID, attr->dt)) < 0) HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "can't determine if datatype is shared") - else if(is_shared_ret) - type_shared = TRUE; - else - type_shared = FALSE; - if((is_shared_ret = H5O_msg_is_shared(H5O_SDSPACE_ID, attr->ds)) < 0) + if((is_space_shared = H5O_msg_is_shared(H5O_SDSPACE_ID, attr->ds)) < 0) HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "can't determine if dataspace is shared") - else if(is_shared_ret) - space_shared = TRUE; - else - space_shared = FALSE; /* Check which version to write out */ if(use_latest_format) version = H5O_ATTR_VERSION_LATEST; /* Write out latest version of format */ else if(attr->encoding != H5T_CSET_ASCII) version = H5O_ATTR_VERSION_3; /* Write version which includes the character encoding */ - else if(type_shared || space_shared) + else if(is_type_shared || is_space_shared) version = H5O_ATTR_VERSION_2; /* Write out version with flag for shared datatype & dataspaces */ else version = H5O_ATTR_VERSION_1; /* Write out basic version */ @@ -331,8 +308,8 @@ H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg) /* Set attribute flags if version >1 */ if(version >= H5O_ATTR_VERSION_2) { - flags = (type_shared ? H5O_ATTR_FLAG_TYPE_SHARED : 0 ); - flags |= (space_shared ? H5O_ATTR_FLAG_SPACE_SHARED : 0); + flags = (is_type_shared ? H5O_ATTR_FLAG_TYPE_SHARED : 0 ); + flags |= (is_space_shared ? H5O_ATTR_FLAG_SPACE_SHARED : 0); *p++ = flags; /* Set flags for attribute */ } /* end if */ else @@ -444,10 +421,6 @@ done: This function returns the size of the raw attribute message on success. (Not counting the message type or size fields, only the data portion of the message). It doesn't take into account alignment. - * - * Modified: - * Robb Matzke, 17 Jul 1998 - * Added padding between message parts for alignment. --------------------------------------------------------------------------*/ static size_t H5O_attr_size(const H5F_t *f, const void *_mesg) @@ -531,8 +504,6 @@ H5O_attr_size(const H5F_t *f, const void *_mesg) * Programmer: Robb Matzke * Tuesday, December 9, 1997 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t @@ -559,8 +530,6 @@ H5O_attr_reset(void *_mesg) * Programmer: Quincey Koziol * Thursday, November 18, 2004 * - * Modifications: - * *------------------------------------------------------------------------- */ static herr_t @@ -586,14 +555,12 @@ H5O_attr_free(void *mesg) * Programmer: Quincey Koziol * Friday, September 26, 2003 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t -H5O_attr_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg) +H5O_attr_delete(H5F_t *f, hid_t dxpl_id, H5O_t *oh, void *_mesg) { - const H5A_t *attr = (const H5A_t *) _mesg; + H5A_t *attr = (H5A_t *) _mesg; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_attr_delete) @@ -603,11 +570,11 @@ H5O_attr_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg) HDassert(attr); /* Decrement reference count on datatype in file */ - if((H5O_MSG_DTYPE->del)(f, dxpl_id, attr->dt) < 0) + if((H5O_MSG_DTYPE->del)(f, dxpl_id, oh, attr->dt) < 0) HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust datatype link count") /* Decrement reference count on dataspace in file */ - if((H5O_MSG_SDSPACE->del)(f, dxpl_id, attr->ds) < 0) + if((H5O_MSG_SDSPACE->del)(f, dxpl_id, oh, attr->ds) < 0) HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust dataspace link count") done: @@ -629,9 +596,9 @@ done: *------------------------------------------------------------------------- */ herr_t -H5O_attr_link(H5F_t *f, hid_t dxpl_id, const void *_mesg) +H5O_attr_link(H5F_t *f, hid_t dxpl_id, H5O_t *oh, void *_mesg) { - const H5A_t *attr = (const H5A_t *) _mesg; + H5A_t *attr = (H5A_t *) _mesg; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_attr_link) @@ -646,9 +613,9 @@ H5O_attr_link(H5F_t *f, hid_t dxpl_id, const void *_mesg) * message is deleted. */ /* Increment reference count on datatype & dataspace in file */ - if((H5O_MSG_DTYPE->link)(f, dxpl_id, attr->dt) < 0) + if((H5O_MSG_DTYPE->link)(f, dxpl_id, oh, attr->dt) < 0) HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust datatype link count") - if((H5O_MSG_SDSPACE->link)(f, dxpl_id, attr->ds) < 0) + if((H5O_MSG_SDSPACE->link)(f, dxpl_id, oh, attr->ds) < 0) HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust dataspace link count") done: @@ -703,17 +670,12 @@ H5O_attr_pre_copy_file(H5F_t UNUSED *file_src, const void UNUSED *native_src, * Programmer: Quincey Koziol * November 1, 2005 * - * Modifications: Peter Cao - * December 17, 2005: datatype conversion for variable length datatype - * August 1, 2006: fix reference datatype - * - * *------------------------------------------------------------------------- */ static void * H5O_attr_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t UNUSED *mesg_type, - void *native_src, H5F_t *file_dst, hid_t dxpl_id, - H5O_copy_t *cpy_info, void UNUSED *udata) + void *native_src, H5F_t *file_dst, hbool_t *recompute_size, + H5O_copy_t *cpy_info, void UNUSED *udata, hid_t dxpl_id) { H5A_t *attr_src = (H5A_t *)native_src; H5A_t *attr_dst = NULL; @@ -779,15 +741,18 @@ H5O_attr_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t UNUSED *mesg_ty /* Copy the shared object from source to destination */ if(H5O_copy_header_map(src_oloc, dst_oloc, dxpl_id, cpy_info, FALSE) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy object") - } else { + + /* Update shared message info from named datatype info */ + H5T_update_shared(attr_dst->dt); + } /* end if */ + else { /* If the datatype is not named, it may have been shared in the * source file's heap. Un-share it for now. We'll try to shared * it in the destination file below. */ if(H5O_msg_reset_share(H5O_DTYPE_ID, attr_dst->dt) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to reset datatype sharing") - } - /* end if */ + } /* end else */ /* Copy the dataspace for the attribute */ attr_dst->ds = H5S_copy(attr_src->ds, FALSE); @@ -803,19 +768,24 @@ H5O_attr_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t UNUSED *mesg_ty /* Try to share both the datatype and dataset. This does nothing if the * datatype is committed or sharing is disabled. */ - if(H5SM_try_share(file_dst, dxpl_id, H5O_DTYPE_ID, attr_dst->dt) < 0) + if(H5SM_try_share(file_dst, dxpl_id, NULL, H5O_DTYPE_ID, attr_dst->dt, NULL) < 0) HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, NULL, "can't share attribute datatype") - if(H5SM_try_share(file_dst, dxpl_id, H5O_SDSPACE_ID, attr_dst->ds) <0) + if(H5SM_try_share(file_dst, dxpl_id, NULL, H5O_SDSPACE_ID, attr_dst->ds, NULL) < 0) HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, NULL, "can't share attribute dataspace") /* Compute the sizes of the datatype and dataspace. This is their raw * size unless they're shared. */ - attr_dst->dt_size = H5O_msg_raw_size(file_dst, H5O_DTYPE_ID, FALSE, attr_src->dt); + attr_dst->dt_size = H5O_msg_raw_size(file_dst, H5O_DTYPE_ID, FALSE, attr_dst->dt); HDassert(attr_dst->dt_size > 0); - attr_dst->ds_size = H5O_msg_raw_size(file_dst, H5O_SDSPACE_ID, FALSE, attr_src->ds); + attr_dst->ds_size = H5O_msg_raw_size(file_dst, H5O_SDSPACE_ID, FALSE, attr_dst->ds); HDassert(attr_dst->ds_size > 0); + /* Check whether to recompute the size of the attribute */ + /* (happens when the datatype or dataspace changes sharing status) */ + if(attr_dst->dt_size != attr_src->dt_size || attr_dst->ds_size != attr_src->ds_size) + *recompute_size = TRUE; + /* Compute the size of the data */ H5_ASSIGN_OVERFLOW(attr_dst->data_size, H5S_GET_EXTENT_NPOINTS(attr_dst->ds) * H5T_get_size(attr_dst->dt), hsize_t, size_t); diff --git a/src/H5Oattribute.c b/src/H5Oattribute.c index 45c1f8a..ddf5a35 100644 --- a/src/H5Oattribute.c +++ b/src/H5Oattribute.c @@ -368,7 +368,7 @@ H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr) * *ick* -QAK, 2007/01/08 */ if(attr_rc > 1) { - if(H5O_attr_delete(loc->file, dxpl_id, attr) < 0) + if(H5O_attr_delete(loc->file, dxpl_id, oh, attr) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute") } /* end if */ } /* end if */ @@ -598,7 +598,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5O_attr_update_shared(H5F_t *f, hid_t dxpl_id, H5A_t *attr, +H5O_attr_update_shared(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5A_t *attr, H5O_shared_t *update_sh_mesg) { H5O_shared_t sh_mesg; /* Shared object header message */ @@ -613,12 +613,16 @@ H5O_attr_update_shared(H5F_t *f, hid_t dxpl_id, H5A_t *attr, HDassert(attr); /* Extract shared message info from current attribute (for later use) */ - if(H5O_shared_copy(&sh_mesg, &(attr->sh_loc)) < 0) + if(H5O_set_shared(&sh_mesg, &(attr->sh_loc)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "can't get shared message") + /* Reset existing sharing information */ + if(H5O_msg_reset_share(H5O_ATTR_ID, attr) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to reset attribute sharing") + /* Store new version of message as a SOHM */ /* (should always work, since we're not changing the size of the attribute) */ - if((shared_mesg = H5SM_try_share(f, dxpl_id, H5O_ATTR_ID, attr)) == 0) + if((shared_mesg = H5SM_try_share(f, dxpl_id, oh, H5O_ATTR_ID, attr, NULL)) == 0) HGOTO_ERROR(H5E_ATTR, H5E_BADMESG, FAIL, "attribute changed sharing status") else if(shared_mesg < 0) HGOTO_ERROR(H5E_ATTR, H5E_BADMESG, FAIL, "can't share attribute") @@ -630,23 +634,25 @@ H5O_attr_update_shared(H5F_t *f, hid_t dxpl_id, H5A_t *attr, /* If the newly shared attribute needs to share "ownership" of the shared * components (ie. its reference count is 1), increment the reference * count on any shared components of the attribute, so that they won't - * be removed from the file. (Essentially a "copy on write" operation). + * be removed from the file by the following "delete" operation on the + * original attribute shared message info. (Essentially a "copy on + * write" operation). * * *ick* -QAK, 2007/01/08 */ if(attr_rc == 1) { /* Increment reference count on attribute components */ - if(H5O_attr_link(f, dxpl_id, attr) < 0) + if(H5O_attr_link(f, dxpl_id, oh, attr) < 0) HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust attribute link count") } /* end if */ /* Remove the old attribute from the SOHM storage */ - if(H5SM_try_delete(f, dxpl_id, H5O_ATTR_ID, &sh_mesg) < 0) + if(H5SM_delete(f, dxpl_id, oh, &sh_mesg) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to delete shared attribute in shared storage") /* Extract updated shared message info from modified attribute, if requested */ if(update_sh_mesg) - if(H5O_shared_copy(update_sh_mesg, &(attr->sh_loc)) < 0) + if(H5O_set_shared(update_sh_mesg, &(attr->sh_loc)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "can't get shared message") done: @@ -669,7 +675,7 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5O_attr_write_cb(H5O_t UNUSED *oh, H5O_mesg_t *mesg/*in,out*/, +H5O_attr_write_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/, unsigned UNUSED sequence, hbool_t *oh_modified, void *_udata/*in,out*/) { H5O_iter_wrt_t *udata = (H5O_iter_wrt_t *)_udata; /* Operator user data */ @@ -684,20 +690,22 @@ H5O_attr_write_cb(H5O_t UNUSED *oh, H5O_mesg_t *mesg/*in,out*/, /* Check for correct attribute message to modify */ if(HDstrcmp(((H5A_t *)mesg->native)->name, udata->attr->name) == 0) { - /* Update the shared attribute in the SOHM storage */ - if(mesg->flags & H5O_MSG_FLAG_SHARED) { - if(H5O_attr_update_shared(udata->f, udata->dxpl_id, udata->attr, (H5O_shared_t *)mesg->native) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, H5_ITER_ERROR, "unable to update attribute in shared storage") - } /* end if */ - /* Allocate storage for the message's data, if necessary */ if(((H5A_t *)mesg->native)->data == NULL) if(NULL == (((H5A_t *)mesg->native)->data = H5FL_BLK_MALLOC(attr_buf, udata->attr->data_size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "memory allocation failed") /* Copy the data into the header message */ + /* (Needs to occur before updating the shared message, or the hash + * value on the old & new messages will be the same) + */ HDmemcpy(((H5A_t *)mesg->native)->data, udata->attr->data, udata->attr->data_size); + /* Update the shared attribute in the SOHM storage */ + if(mesg->flags & H5O_MSG_FLAG_SHARED) + if(H5O_attr_update_shared(udata->f, udata->dxpl_id, oh, udata->attr, (H5O_shared_t *)mesg->native) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, H5_ITER_ERROR, "unable to update attribute in shared storage") + /* Mark message as dirty */ mesg->dirty = TRUE; @@ -880,7 +888,7 @@ H5O_attr_rename_mod_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/, /* Check for shared message */ if(mesg->flags & H5O_MSG_FLAG_SHARED) { /* Update the shared attribute in the SOHM storage */ - if(H5O_attr_update_shared(udata->f, udata->dxpl_id, mesg->native, NULL) < 0) + if(H5O_attr_update_shared(udata->f, udata->dxpl_id, oh, mesg->native, NULL) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, H5_ITER_ERROR, "unable to update attribute in shared storage") } /* end if */ else { @@ -1214,12 +1222,12 @@ H5O_attr_remove_update(const H5O_loc_t *loc, H5O_t *oh, H5O_ainfo_t *ainfo, else if(shared_mesg == 0) { /* Increment reference count on attribute components */ /* (so that they aren't deleted when the dense attribute storage is deleted) */ - if(H5O_attr_link(loc->file, dxpl_id, &(atable.attrs[u])) < 0) + if(H5O_attr_link(loc->file, dxpl_id, oh, &(atable.attrs[u])) < 0) HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust attribute link count") } /* end if */ else { - /* Reset 'shared' status, so attributes will be shared again */ - atable.attrs[u].sh_loc.flags = 0; + /* Reset 'shared' status, so attribute will be shared again */ + atable.attrs[u].sh_loc.type = H5O_SHARE_TYPE_UNSHARED; } /* end else */ /* Insert attribute message into object header */ diff --git a/src/H5Obogus.c b/src/H5Obogus.c index 4def755..1233ec0 100644 --- a/src/H5Obogus.c +++ b/src/H5Obogus.c @@ -49,7 +49,7 @@ const H5O_msg_class_t H5O_MSG_BOGUS[1] = {{ H5O_BOGUS_ID, /*message id number */ "bogus", /*message name for debugging */ 0, /*native message size */ - FALSE, /* messages are sharable? */ + 0, /* messages are sharable? */ H5O_bogus_decode, /*decode message */ H5O_bogus_encode, /*encode message */ NULL, /*copy the native value */ diff --git a/src/H5Obtreek.c b/src/H5Obtreek.c index cab323d..57f8f47 100644 --- a/src/H5Obtreek.c +++ b/src/H5Obtreek.c @@ -40,7 +40,7 @@ const H5O_msg_class_t H5O_MSG_BTREEK[1] = {{ H5O_BTREEK_ID, /*message id number */ "v1 B-tree 'K' values", /*message name for debugging */ sizeof(H5O_btreek_t), /*native message size */ - FALSE, /* messages are sharable? */ + 0, /* messages are sharable? */ H5O_btreek_decode, /*decode message */ H5O_btreek_encode, /*encode message */ H5O_btreek_copy, /*copy the native value */ @@ -49,7 +49,7 @@ const H5O_msg_class_t H5O_MSG_BTREEK[1] = {{ NULL, /* free method */ NULL, /* file delete method */ NULL, /* link method */ - NULL, /* set share method */ + NULL, /*set share method */ NULL, /*can share method */ NULL, /* pre copy native value to file */ NULL, /* copy native value to file */ diff --git a/src/H5Ocache.c b/src/H5Ocache.c index d574fe8..2f89327 100644 --- a/src/H5Ocache.c +++ b/src/H5Ocache.c @@ -479,7 +479,7 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1, size_t mesg_size; /* Size of message read in */ unsigned id; /* ID (type) of current message */ uint8_t flags; /* Flags for current message */ - H5O_msg_crt_idx_t crt_idx = H5O_MAX_CRT_ORDER_IDX; /* Creation index for current message */ + H5O_msg_crt_idx_t crt_idx = 0; /* Creation index for current message */ /* Decode message prefix info */ diff --git a/src/H5Ocont.c b/src/H5Ocont.c index 1415734..92c4a3c 100644 --- a/src/H5Ocont.c +++ b/src/H5Ocont.c @@ -41,7 +41,7 @@ static void *H5O_cont_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const static herr_t H5O_cont_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg); static size_t H5O_cont_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg); static herr_t H5O_cont_free(void *mesg); -static herr_t H5O_cont_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg); +static herr_t H5O_cont_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, void *_mesg); static herr_t H5O_cont_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -50,7 +50,7 @@ const H5O_msg_class_t H5O_MSG_CONT[1] = {{ H5O_CONT_ID, /*message id number */ "hdr continuation", /*message name for debugging */ sizeof(H5O_cont_t), /*native message size */ - FALSE, /* messages are sharable? */ + 0, /* messages are sharable? */ H5O_cont_decode, /*decode message */ H5O_cont_encode, /*encode message */ NULL, /*no copy method */ @@ -59,7 +59,7 @@ const H5O_msg_class_t H5O_MSG_CONT[1] = {{ H5O_cont_free, /* free method */ H5O_cont_delete, /* file delete method */ NULL, /* link method */ - NULL, /*set share method */ + NULL, /*set share method */ NULL, /*can share method */ NULL, /* pre copy native value to file */ NULL, /* copy native value to file */ @@ -223,9 +223,9 @@ H5O_cont_free(void *mesg) *------------------------------------------------------------------------- */ static herr_t -H5O_cont_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg) +H5O_cont_delete(H5F_t *f, hid_t dxpl_id, H5O_t UNUSED *open_oh, void *_mesg) { - const H5O_cont_t *mesg = (const H5O_cont_t *) _mesg; + H5O_cont_t *mesg = (H5O_cont_t *) _mesg; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_cont_delete) diff --git a/src/H5Ocopy.c b/src/H5Ocopy.c index 71d4c0a..ebb1303 100644 --- a/src/H5Ocopy.c +++ b/src/H5Ocopy.c @@ -253,10 +253,8 @@ H5Ocopy(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id, HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object") done: - if(loc_found) { - if(H5G_loc_free(&src_loc) < 0) - HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't free location") - } + if(loc_found && H5G_loc_free(&src_loc) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't free location") if(obj_open) H5O_close(&src_oloc); @@ -301,12 +299,11 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, const H5O_msg_class_t *copy_type; /* Type of message to use for copying */ const H5O_obj_class_t *obj_class = NULL; /* Type of object we are copying */ void *udata = NULL; /* User data for passing to message callbacks */ - size_t dst_oh_size; /* Total size of the destination OH */ + uint64_t dst_oh_size; /* Total size of the destination OH */ size_t dst_oh_null; /* Size of the null message to add to destination OH */ unsigned dst_oh_gap; /* Size of the gap in chunk #0 of destination OH */ uint8_t *current_pos; /* Current position in destination image */ size_t msghdr_size; - hbool_t shared; /* Whether copy_file callback created a shared message */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI_NOINIT(H5O_copy_header_real) @@ -399,7 +396,7 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, if(copy_type->pre_copy_file) { /* Decode the message if necessary. */ - H5O_LOAD_NATIVE(oloc_src->file, dxpl_id, mesg_src, FAIL) + H5O_LOAD_NATIVE(oloc_src->file, dxpl_id, oh_src, mesg_src, FAIL) /* Perform "pre copy" operation on message */ if((copy_type->pre_copy_file)(oloc_src->file, mesg_src->native, &(deleted[mesgno]), cpy_info, udata) < 0) @@ -466,39 +463,43 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, /* copy this message into destination file */ if(copy_type->copy_file) { - hbool_t recompute_size = FALSE; /* Whether to recompute the destination message's size */ + htri_t is_shared; /* Whether message is shared */ + hbool_t recompute_size; /* Whether copy_file callback created a shared message */ /* Decode the message if necessary. */ - H5O_LOAD_NATIVE(oloc_src->file, dxpl_id, mesg_src, FAIL) + H5O_LOAD_NATIVE(oloc_src->file, dxpl_id, oh_src, mesg_src, FAIL) /* Copy the source message */ + recompute_size = FALSE; if((mesg_dst->native = H5O_msg_copy_file(copy_type, - oloc_src->file, mesg_src->native, oloc_dst->file, dxpl_id, - &shared, cpy_info, udata)) == NULL) + oloc_src->file, mesg_src->native, oloc_dst->file, + &recompute_size, cpy_info, udata, dxpl_id)) == NULL) HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object header message") + /* Check if new message is shared */ + if((is_shared = H5O_msg_is_shared(copy_type->id, mesg_dst->native)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to query message's shared status") + /* In being copied, the message may have become shared or stopped - * being shared. If its sharing status has changed, recalculate - * its size and set/unset its sharing flag. + * being shared, set/unset its sharing flag. */ - if(shared == TRUE && !(mesg_dst->flags & H5O_MSG_FLAG_SHARED)) { - /* Set shared flag */ + if(is_shared && !(mesg_dst->flags & H5O_MSG_FLAG_SHARED)) { mesg_dst->flags |= H5O_MSG_FLAG_SHARED; - /* Recompute shared message size (mesg_dst->native is really - * shared) - */ - recompute_size = TRUE; + /* Recompute message size (mesg_dst->native is really shared) */ + recompute_size = TRUE; } /* end if */ - else if(shared == FALSE && (mesg_dst->flags & H5O_MSG_FLAG_SHARED)) { - /* Unset shared flag */ + else if(!is_shared && (mesg_dst->flags & H5O_MSG_FLAG_SHARED)) { mesg_dst->flags &= ~H5O_MSG_FLAG_SHARED; - /* Recompute native message size (msg_dest->native is no longer - * shared) - */ + /* Recompute message size (msg_dest->native is no longer shared) */ recompute_size = TRUE; - } /* end else */ + } /* end if */ + + /* Recompute message's size */ + /* (its sharing status or one of its components (for attributes) + * could have changed) + */ if(recompute_size) mesg_dst->raw_size = H5O_ALIGN_OH(oh_dst, H5O_msg_raw_size(oloc_dst->file, mesg_dst->type->id, FALSE, mesg_dst->native)); @@ -569,12 +570,12 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, addr_new = oh_dst->chunk[0].addr; /* Create memory image for the new chunk */ - if(NULL == (oh_dst->chunk[0].image = H5FL_BLK_MALLOC(chunk_image, dst_oh_size))) + if(NULL == (oh_dst->chunk[0].image = H5FL_BLK_MALLOC(chunk_image, (size_t)dst_oh_size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") /* Set dest. chunk information */ oh_dst->chunk[0].dirty = TRUE; - oh_dst->chunk[0].size = dst_oh_size; + oh_dst->chunk[0].size = (size_t)dst_oh_size; oh_dst->chunk[0].gap = dst_oh_gap; /* Set up raw pointers and copy messages that didn't need special @@ -582,7 +583,7 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, * allocated. */ HDassert(H5O_SIZEOF_MSGHDR_OH(oh_src) == H5O_SIZEOF_MSGHDR_OH(oh_dst)); - msghdr_size = H5O_SIZEOF_MSGHDR_OH(oh_src); + msghdr_size = H5O_SIZEOF_MSGHDR_OH(oh_dst); current_pos = oh_dst->chunk[0].image; @@ -646,7 +647,7 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, } /* end if */ /* Make sure we filled the chunk, except for room at the end for a checksum */ - HDassert(current_pos + dst_oh_gap + dst_oh_null + H5O_SIZEOF_CHKSUM_OH(oh_dst) == dst_oh_size + oh_dst->chunk[0].image); + HDassert(current_pos + dst_oh_gap + dst_oh_null + H5O_SIZEOF_CHKSUM_OH(oh_dst) == (size_t)dst_oh_size + oh_dst->chunk[0].image); /* Set the dest. object location to the first chunk address */ HDassert(H5F_addr_defined(addr_new)); diff --git a/src/H5Odbg.c b/src/H5Odbg.c index c73360f..e77dcfd 100644 --- a/src/H5Odbg.c +++ b/src/H5Odbg.c @@ -488,7 +488,7 @@ H5O_debug_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, haddr_t addr, FILE *stream, i /* decode the message */ debug_type = oh->mesg[i].type; if(NULL == oh->mesg[i].native && debug_type->decode) - H5O_LOAD_NATIVE(f, dxpl_id, &oh->mesg[i], FAIL) + H5O_LOAD_NATIVE(f, dxpl_id, oh, &oh->mesg[i], FAIL) /* print the message */ HDfprintf(stream, "%*s%-*s\n", indent + 3, "", MAX(0, fwidth - 3), diff --git a/src/H5Odrvinfo.c b/src/H5Odrvinfo.c index 7e43d82..727449b 100644 --- a/src/H5Odrvinfo.c +++ b/src/H5Odrvinfo.c @@ -41,7 +41,7 @@ const H5O_msg_class_t H5O_MSG_DRVINFO[1] = {{ H5O_DRVINFO_ID, /*message id number */ "driver info", /*message name for debugging */ sizeof(H5O_drvinfo_t), /*native message size */ - FALSE, /* messages are sharable? */ + 0, /* messages are sharable? */ H5O_drvinfo_decode, /*decode message */ H5O_drvinfo_encode, /*encode message */ H5O_drvinfo_copy, /*copy the native value */ @@ -50,7 +50,7 @@ const H5O_msg_class_t H5O_MSG_DRVINFO[1] = {{ NULL, /* free method */ NULL, /* file delete method */ NULL, /* link method */ - NULL, /* set share method */ + NULL, /*set share method */ NULL, /*can share method */ NULL, /* pre copy native value to file */ NULL, /* copy native value to file */ diff --git a/src/H5Odtype.c b/src/H5Odtype.c index 9112b1f..742d00b 100644 --- a/src/H5Odtype.c +++ b/src/H5Odtype.c @@ -39,7 +39,8 @@ static htri_t H5O_dtype_can_share(const void *_mesg); static herr_t H5O_dtype_pre_copy_file(H5F_t *file_src, const void *mesg_src, hbool_t *deleted, const H5O_copy_t *cpy_info, void *_udata); static void *H5O_dtype_copy_file(H5F_t *file_src, const H5O_msg_class_t *mesg_type, - void *native_src, H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata); + void *native_src, H5F_t *file_dst, hbool_t *recompute_size, + H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id); static herr_t H5O_dtype_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -67,7 +68,7 @@ const H5O_msg_class_t H5O_MSG_DTYPE[1] = {{ H5O_DTYPE_ID, /* message id number */ "datatype", /* message name for debugging */ sizeof(H5T_t), /* native message size */ - TRUE, /* messages are sharable? */ + H5O_SHARE_IS_SHARABLE|H5O_SHARE_IN_OHDR, /* messages are sharable? */ H5O_dtype_shared_decode, /* decode message */ H5O_dtype_shared_encode, /* encode message */ H5O_dtype_copy, /* copy the native value */ @@ -1045,7 +1046,7 @@ static void * H5O_dtype_copy(const void *_src, void *_dst) { const H5T_t *src = (const H5T_t *) _src; - H5T_t *dst = NULL; + H5T_t *dst; void *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_dtype_copy) @@ -1299,20 +1300,26 @@ H5O_dtype_set_share(void *_mesg/*in,out*/, const H5O_shared_t *sh) /* Make sure the shared message location is initialized, so that it * either has valid sharing information or is set to 0. */ - HDassert(sh->flags & (H5O_SHARED_IN_HEAP_FLAG | H5O_COMMITTED_FLAG) || sh->flags == H5O_NOT_SHARED); + HDassert(sh->type <= H5O_SHARE_TYPE_HERE); /* Make sure we're not sharing a committed type in the heap */ - HDassert(sh->flags & H5O_COMMITTED_FLAG || + HDassert(sh->type == H5O_SHARE_TYPE_COMMITTED || (dt->shared->state != H5T_STATE_OPEN && dt->shared->state != H5T_STATE_NAMED)); /* Copy the shared information */ - if(H5O_shared_copy(&(dt->sh_loc), sh) < 0) + if(H5O_set_shared(&(dt->sh_loc), sh) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy shared message info") /* If this is now a committed datatype, set its state properly. */ - if(sh->flags & H5O_COMMITTED_FLAG) + if(sh->type == H5O_SHARE_TYPE_COMMITTED) { dt->shared->state = H5T_STATE_NAMED; + /* Set up the object location for the datatype also */ + dt->oloc.file = sh->file; + dt->oloc.addr = sh->u.loc.oh_addr;; + dt->oloc.holding_file = FALSE; + } /* end if */ + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_dtype_set_share() */ @@ -1429,8 +1436,8 @@ done: */ static void * H5O_dtype_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t *mesg_type, - void *native_src, H5F_t *file_dst, hid_t UNUSED dxpl_id, - H5O_copy_t UNUSED *cpy_info, void UNUSED *udata) + void *native_src, H5F_t *file_dst, hbool_t UNUSED *recompute_size, + H5O_copy_t UNUSED *cpy_info, void UNUSED *udata, hid_t UNUSED dxpl_id) { H5T_t *dst_mesg = NULL; /* Destination datatype */ void *ret_value = NULL; /* Return value */ @@ -1448,9 +1455,8 @@ H5O_dtype_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t *mesg_type, ret_value = dst_mesg; done: - if(NULL == ret_value) { + if(NULL == ret_value) H5O_msg_free(mesg_type->id, dst_mesg); - } FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_dtype_copy_file() */ diff --git a/src/H5Oefl.c b/src/H5Oefl.c index cf34ead..5fa9d6a 100644 --- a/src/H5Oefl.c +++ b/src/H5Oefl.c @@ -35,7 +35,8 @@ static void *H5O_efl_copy(const void *_mesg, void *_dest); static size_t H5O_efl_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg); static herr_t H5O_efl_reset(void *_mesg); static void *H5O_efl_copy_file(H5F_t *file_src, void *mesg_src, - H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata); + H5F_t *file_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info, + void *udata, hid_t dxpl_id); static herr_t H5O_efl_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -44,7 +45,7 @@ const H5O_msg_class_t H5O_MSG_EFL[1] = {{ H5O_EFL_ID, /*message id number */ "external file list", /*message name for debugging */ sizeof(H5O_efl_t), /*native message size */ - FALSE, /* messages are sharable? */ + 0, /* messages are sharable? */ H5O_efl_decode, /*decode message */ H5O_efl_encode, /*encode message */ H5O_efl_copy, /*copy native value */ @@ -417,7 +418,8 @@ done: */ static void * H5O_efl_copy_file(H5F_t UNUSED *file_src, void *mesg_src, H5F_t *file_dst, - hid_t dxpl_id, H5O_copy_t UNUSED *cpy_info, void UNUSED *_udata) + hbool_t UNUSED *recompute_size, H5O_copy_t UNUSED *cpy_info, + void UNUSED *_udata, hid_t dxpl_id) { H5O_efl_t *efl_src = (H5O_efl_t *) mesg_src; H5O_efl_t *efl_dst = NULL; diff --git a/src/H5Ofill.c b/src/H5Ofill.c index 2e36565..d81b769 100644 --- a/src/H5Ofill.c +++ b/src/H5Ofill.c @@ -98,7 +98,7 @@ const H5O_msg_class_t H5O_MSG_FILL[1] = {{ H5O_FILL_ID, /*message id number */ "fill", /*message name for debugging */ sizeof(H5O_fill_t), /*native message size */ - TRUE, /* messages are sharable? */ + H5O_SHARE_IS_SHARABLE|H5O_SHARE_IN_OHDR, /* messages are sharable? */ H5O_fill_shared_decode, /*decode message */ H5O_fill_shared_encode, /*encode message */ H5O_fill_copy, /*copy the native value */ @@ -107,7 +107,7 @@ const H5O_msg_class_t H5O_MSG_FILL[1] = {{ H5O_fill_free, /* free method */ H5O_fill_shared_delete, /* file delete method */ H5O_fill_shared_link, /* link method */ - H5O_shared_copy, /* set share method */ + NULL, /* set share method */ NULL, /*can share method */ NULL, /* pre copy native value to file */ H5O_fill_shared_copy_file, /* copy native value to file */ @@ -122,7 +122,7 @@ const H5O_msg_class_t H5O_MSG_FILL_NEW[1] = {{ H5O_FILL_NEW_ID, /*message id number */ "fill_new", /*message name for debugging */ sizeof(H5O_fill_t), /*native message size */ - TRUE, /* messages are sharable? */ + H5O_SHARE_IS_SHARABLE|H5O_SHARE_IN_OHDR, /* messages are sharable? */ H5O_fill_new_shared_decode, /*decode message */ H5O_fill_new_shared_encode, /*encode message */ H5O_fill_copy, /*copy the native value */ @@ -131,7 +131,7 @@ const H5O_msg_class_t H5O_MSG_FILL_NEW[1] = {{ H5O_fill_free, /* free method */ H5O_fill_new_shared_delete, /* file delete method */ H5O_fill_new_shared_link, /* link method */ - H5O_shared_copy, /* set share method */ + NULL, /* set share method */ NULL, /*can share method */ NULL, /* pre copy native value to file */ H5O_fill_new_shared_copy_file, /* copy native value to file */ diff --git a/src/H5Oginfo.c b/src/H5Oginfo.c index adeb2d5..5888f58 100644 --- a/src/H5Oginfo.c +++ b/src/H5Oginfo.c @@ -46,7 +46,7 @@ const H5O_msg_class_t H5O_MSG_GINFO[1] = {{ H5O_GINFO_ID, /*message id number */ "ginfo", /*message name for debugging */ sizeof(H5O_ginfo_t), /*native message size */ - FALSE, /* messages are sharable? */ + 0, /* messages are sharable? */ H5O_ginfo_decode, /*decode message */ H5O_ginfo_encode, /*encode message */ H5O_ginfo_copy, /*copy the native value */ diff --git a/src/H5Olayout.c b/src/H5Olayout.c index bdc7d15..ce079ed 100644 --- a/src/H5Olayout.c +++ b/src/H5Olayout.c @@ -39,9 +39,11 @@ static void *H5O_layout_copy(const void *_mesg, void *_dest); static size_t H5O_layout_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg); static herr_t H5O_layout_reset(void *_mesg); static herr_t H5O_layout_free(void *_mesg); -static herr_t H5O_layout_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg); +static herr_t H5O_layout_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, + void *_mesg); static void *H5O_layout_copy_file(H5F_t *file_src, void *mesg_src, - H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata); + H5F_t *file_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info, + void *udata, hid_t dxpl_id); static herr_t H5O_layout_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -50,7 +52,7 @@ const H5O_msg_class_t H5O_MSG_LAYOUT[1] = {{ H5O_LAYOUT_ID, /*message id number */ "layout", /*message name for debugging */ sizeof(H5O_layout_t), /*native message size */ - FALSE, /* messages are sharable? */ + 0, /* messages are sharable? */ H5O_layout_decode, /*decode message */ H5O_layout_encode, /*encode message */ H5O_layout_copy, /*copy the native value */ @@ -554,9 +556,9 @@ H5O_layout_free (void *_mesg) *------------------------------------------------------------------------- */ static herr_t -H5O_layout_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg) +H5O_layout_delete(H5F_t *f, hid_t dxpl_id, H5O_t UNUSED *open_oh, void *_mesg) { - const H5O_layout_t *mesg = (const H5O_layout_t *) _mesg; + H5O_layout_t *mesg = (H5O_layout_t *) _mesg; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_layout_delete) @@ -608,7 +610,8 @@ done: */ static void * H5O_layout_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst, - hid_t dxpl_id, H5O_copy_t *cpy_info, void *_udata) + hbool_t UNUSED *recompute_size, H5O_copy_t *cpy_info, void *_udata, + hid_t dxpl_id) { H5D_copy_file_ud_t *udata = (H5D_copy_file_ud_t *)_udata; /* Dataset copying user data */ H5O_layout_t *layout_src = (H5O_layout_t *) mesg_src; diff --git a/src/H5Olinfo.c b/src/H5Olinfo.c index eade420..660b0e1 100644 --- a/src/H5Olinfo.c +++ b/src/H5Olinfo.c @@ -40,10 +40,11 @@ static herr_t H5O_linfo_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, con static void *H5O_linfo_copy(const void *_mesg, void *_dest); static size_t H5O_linfo_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg); static herr_t H5O_linfo_free(void *_mesg); -static herr_t H5O_linfo_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg); -static void *H5O_linfo_copy_file(H5F_t *file_src, - void *native_src, H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, - void *udata); +static herr_t H5O_linfo_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, + void *_mesg); +static void *H5O_linfo_copy_file(H5F_t *file_src, void *native_src, + H5F_t *file_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info, + void *udata, hid_t dxpl_id); static herr_t H5O_linfo_post_copy_file(const H5O_loc_t *parent_src_oloc, const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info); static herr_t H5O_linfo_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, @@ -54,7 +55,7 @@ const H5O_msg_class_t H5O_MSG_LINFO[1] = {{ H5O_LINFO_ID, /*message id number */ "linfo", /*message name for debugging */ sizeof(H5O_linfo_t), /*native message size */ - FALSE, /* messages are sharable? */ + 0, /* messages are sharable? */ H5O_linfo_decode, /*decode message */ H5O_linfo_encode, /*encode message */ H5O_linfo_copy, /*copy the native value */ @@ -338,9 +339,9 @@ H5O_linfo_free(void *mesg) *------------------------------------------------------------------------- */ static herr_t -H5O_linfo_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg) +H5O_linfo_delete(H5F_t *f, hid_t dxpl_id, H5O_t UNUSED *open_oh, void *_mesg) { - const H5O_linfo_t *linfo = (const H5O_linfo_t *)_mesg; + H5O_linfo_t *linfo = (H5O_linfo_t *)_mesg; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_linfo_delete) @@ -351,7 +352,7 @@ H5O_linfo_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg) /* If the group is using "dense" link storage, delete it */ if(H5F_addr_defined(linfo->fheap_addr)) - if(H5G_dense_delete(f, dxpl_id, (H5O_linfo_t *)linfo, TRUE) < 0) /* Casting away const OK - QAK */ + if(H5G_dense_delete(f, dxpl_id, linfo, TRUE) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free dense link storage") done: @@ -375,7 +376,8 @@ done: */ static void * H5O_linfo_copy_file(H5F_t UNUSED *file_src, void *native_src, H5F_t *file_dst, - hid_t dxpl_id, H5O_copy_t *cpy_info, void UNUSED *udata) + hbool_t UNUSED *recompute_size, H5O_copy_t *cpy_info, void UNUSED *udata, + hid_t dxpl_id) { H5O_linfo_t *linfo_src = (H5O_linfo_t *) native_src; H5O_linfo_t *linfo_dst = NULL; diff --git a/src/H5Olink.c b/src/H5Olink.c index 655e35a..a11bf9a 100644 --- a/src/H5Olink.c +++ b/src/H5Olink.c @@ -47,7 +47,8 @@ static herr_t H5O_link_free(void *_mesg); static herr_t H5O_link_pre_copy_file(H5F_t *file_src, const void *mesg_src, hbool_t *deleted, const H5O_copy_t *cpy_info, void *udata); static void *H5O_link_copy_file(H5F_t *file_src, void *native_src, - H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata); + H5F_t *file_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info, void *udata, + hid_t dxpl_id); static herr_t H5O_link_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info); static herr_t H5O_link_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, @@ -58,7 +59,7 @@ const H5O_msg_class_t H5O_MSG_LINK[1] = {{ H5O_LINK_ID, /*message id number */ "link", /*message name for debugging */ sizeof(H5O_link_t), /*native message size */ - FALSE, /* messages are sharable? */ + 0, /* messages are sharable? */ H5O_link_decode, /*decode message */ H5O_link_encode, /*encode message */ H5O_link_copy, /*copy the native value */ @@ -587,9 +588,9 @@ H5O_link_free(void *_mesg) *------------------------------------------------------------------------- */ herr_t -H5O_link_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg) +H5O_link_delete(H5F_t *f, hid_t dxpl_id, H5O_t UNUSED *open_oh, void *_mesg) { - const H5O_link_t *lnk = (const H5O_link_t *)_mesg; + H5O_link_t *lnk = (H5O_link_t *)_mesg; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5O_link_delete, FAIL) @@ -699,7 +700,8 @@ H5O_link_pre_copy_file(H5F_t UNUSED *file_src, const void UNUSED *native_src, */ static void * H5O_link_copy_file(H5F_t UNUSED *file_src, void *native_src, H5F_t UNUSED *file_dst, - hid_t UNUSED dxpl_id, H5O_copy_t UNUSED *cpy_info, void UNUSED *udata) + hbool_t UNUSED *recompute_size, H5O_copy_t UNUSED *cpy_info, void UNUSED *udata, + hid_t UNUSED dxpl_id) { H5O_link_t *link_src = (H5O_link_t *)native_src; H5O_link_t *link_dst = NULL; diff --git a/src/H5Omessage.c b/src/H5Omessage.c index 6eedc1f..7c5a38d 100644 --- a/src/H5Omessage.c +++ b/src/H5Omessage.c @@ -348,30 +348,42 @@ H5O_msg_write_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_msg_class_t *ty /* Check for modifying a constant message */ if(idx_msg->flags & H5O_MSG_FLAG_CONSTANT) HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to modify constant message") - else if(idx_msg->flags & H5O_MSG_FLAG_SHARED) { - /* This message is shared, but it's being modified. This is valid if - * it's shared in the heap . - * First, make sure it's not a committed message; these can't ever - * be modified. + /* This message is shared, but it's being modified. */ + else if((idx_msg->flags & H5O_MSG_FLAG_SHARED) || (idx_msg->flags & H5O_MSG_FLAG_SHAREABLE)) { + htri_t status; /* Status of "try share" call */ + + /* First, sanity check to make sure it's not a committed message; + * these can't ever be modified. + */ + HDassert(((H5O_shared_t *)idx_msg->native)->type != H5O_SHARE_TYPE_COMMITTED); + + /* Also, sanity check that a message doesn't switch status from being + * shared (or sharable) to being unsharable. (Which could cause + * a message to increase in size in the object header) */ - HDassert(!(((H5O_shared_t *)idx_msg->native)->flags & H5O_COMMITTED_FLAG)); + HDassert(!(mesg_flags & H5O_MSG_FLAG_DONTSHARE)); /* Remove the old message from the SOHM index */ - if(H5SM_try_delete(f, dxpl_id, idx_msg->type->id, (H5O_shared_t *)idx_msg->native) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to delete message from SOHM table") - - /* Should this message be written as a SOHM? */ - if(!(mesg_flags & H5O_MSG_FLAG_DONTSHARE)) { - htri_t shared_mesg; /* Whether the message should be shared */ - -/* XXX: Maybe this should be before the "try_delete" call? */ -/* (and the try_delete would need to use a copy of the message's shared info) */ - if((shared_mesg = H5SM_try_share(f, dxpl_id, idx_msg->type->id, mesg)) > 0) - /* Mark the message as shared */ - mesg_flags |= H5O_MSG_FLAG_SHARED; - else if(shared_mesg < 0) - HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "error while trying to share message") - } /* end if */ + /* (It would be more efficient to try to share the message first, then + * delete it (avoiding thrashing the index in the case the ref. + * count on the message is one), but this causes problems when + * the location of the object changes (from in another object's + * header to the SOHM heap), so just delete it first -QAK) + */ + if(H5SM_delete(f, dxpl_id, oh, (H5O_shared_t *)idx_msg->native) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete message from SOHM index") + + /* If we're replacing a shared message, the new message must be shared + * (or else it may increase in size!), so pass in NULL for the OH + * location. + * + * XXX: This doesn't handle freeing extra space in object header from + * a message shrinking. + */ + if((status = H5SM_try_share(f, dxpl_id, ((mesg_flags & H5O_MSG_FLAG_SHARED) ? NULL : oh), idx_msg->type->id, mesg, &mesg_flags)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "error while trying to share message") + if(status == FALSE && (mesg_flags & H5O_MSG_FLAG_SHARED)) + HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "message changed sharing status") } /* end if */ /* Copy the information for the message */ @@ -491,7 +503,7 @@ H5O_msg_read_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id, * Decode the message if necessary. If the message is shared then retrieve * native message through the shared interface. */ - H5O_LOAD_NATIVE(f, dxpl_id, &(oh->mesg[idx]), NULL) + H5O_LOAD_NATIVE(f, dxpl_id, oh, &(oh->mesg[idx]), NULL) /* * The object header caches the native message (along with @@ -572,7 +584,8 @@ H5O_msg_reset_real(const H5O_msg_class_t *type, void *native) if(type->reset) { if((type->reset)(native) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "reset method failed") - } else + } /* end if */ + else HDmemset(native, 0, type->native_size); } /* end if */ @@ -1244,7 +1257,7 @@ H5O_msg_iterate_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *type, for(sequence = 0, idx = 0, idx_msg = &oh->mesg[0]; idx < oh->nmesgs && !ret_value; idx++, idx_msg++) { if(type == idx_msg->type) { /* Decode the message if necessary. */ - H5O_LOAD_NATIVE(f, dxpl_id, idx_msg, FAIL) + H5O_LOAD_NATIVE(f, dxpl_id, oh, idx_msg, FAIL) /* Check for making an "internal" (i.e. within the H5O package) callback */ if(op->op_type == H5O_MESG_OP_LIB) @@ -1321,7 +1334,7 @@ H5O_msg_raw_size(const H5F_t *f, unsigned type_id, hbool_t disable_shared, HDassert(mesg); /* Compute the raw data size for the mesg */ - if((ret_value = (type->raw_size)(f, disable_shared, mesg)) == 0) + if(0 == (ret_value = (type->raw_size)(f, disable_shared, mesg))) HGOTO_ERROR(H5E_OHDR, H5E_CANTCOUNT, 0, "unable to determine size of message") done: @@ -1466,7 +1479,7 @@ htri_t H5O_msg_can_share(unsigned type_id, const void *mesg) { const H5O_msg_class_t *type; /* Actual H5O class type for the ID */ - htri_t ret_value = FALSE; + htri_t ret_value; FUNC_ENTER_NOAPI_NOFUNC(H5O_msg_can_share) @@ -1477,16 +1490,14 @@ H5O_msg_can_share(unsigned type_id, const void *mesg) HDassert(mesg); /* If there is a can_share callback, use it */ - if((type->can_share)) + if(type->can_share) ret_value = (type->can_share)(mesg); else { /* Otherwise, the message can be shared if messages of this type are - * shareable in general; i.e., if they have a set_share callback + * shareable in general; i.e., if they have the "is_sharable" flag + * in the "share_flags" class member set. */ - if(type->set_share) - ret_value = TRUE; - else - ret_value = FALSE; + ret_value = (type->share_flags & H5O_SHARE_IS_SHARABLE) ? TRUE : FALSE; } /* end else */ FUNC_LEAVE_NOAPI(ret_value) @@ -1494,6 +1505,43 @@ H5O_msg_can_share(unsigned type_id, const void *mesg) /*------------------------------------------------------------------------- + * Function: H5O_msg_can_share_in_ohdr + * + * Purpose: Check if the message class allows its messages to be shared + * in the object's header. + * + * Return: Object can be shared: TRUE + * Object cannot be shared: FALSE + * + * Programmer: Quincey Koziol + * March 15 2007 + * + *------------------------------------------------------------------------- + */ +htri_t +H5O_msg_can_share_in_ohdr(unsigned type_id) +{ + const H5O_msg_class_t *type; /* Actual H5O class type for the ID */ + htri_t ret_value; + + FUNC_ENTER_NOAPI_NOFUNC(H5O_msg_can_share_in_ohdr) + + /* Check args */ + HDassert(type_id < NELMTS(H5O_msg_class_g)); + type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */ + HDassert(type); + + /* Otherwise, the message can be shared if messages of this type are + * shareable in general; i.e., if they have the "is_sharable" flag + * in the "share_flags" class member set. + */ + ret_value = (type->share_flags & H5O_SHARE_IN_OHDR) ? TRUE : FALSE; + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_msg_can_share_in_ohdr() */ + + +/*------------------------------------------------------------------------- * Function: H5O_msg_is_shared * * Purpose: Call the 'is_shared' method for a @@ -1522,11 +1570,11 @@ H5O_msg_is_shared(unsigned type_id, const void *mesg) HDassert(type); HDassert(mesg); - /* If message class isn't sharable, then obviously it's not a shared message! */ - if(!(type->is_sharable)) - ret_value = FALSE; + /* If messages in a class aren't sharable, then obviously this message isn't shared! :-) */ + if(type->share_flags & H5O_SHARE_IS_SHARABLE) + ret_value = H5O_IS_STORED_SHARED(((const H5O_shared_t *)mesg)->type); else - ret_value = H5O_IS_SHARED(((const H5O_shared_t *)mesg)->flags); + ret_value = FALSE; FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_msg_is_shared() */ @@ -1547,27 +1595,36 @@ H5O_msg_is_shared(unsigned type_id, const void *mesg) *------------------------------------------------------------------------- */ herr_t -H5O_msg_set_share(unsigned type_id, H5O_shared_t *share, void *mesg) +H5O_msg_set_share(unsigned type_id, const H5O_shared_t *share, void *mesg) { const H5O_msg_class_t *type; /* Actual H5O class type for the ID */ - herr_t ret_value; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5O_msg_set_share, FAIL) /* Check args */ - HDassert(share); HDassert(type_id < NELMTS(H5O_msg_class_g)); type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */ HDassert(type); - HDassert(type->set_share); + HDassert(type->share_flags & H5O_SHARE_IS_SHARABLE); HDassert(mesg); - HDassert(share->flags != H5O_NOT_SHARED); + HDassert(share); + HDassert(share->type != H5O_SHARE_TYPE_UNSHARED); - /* Set this message as the shared message for the message, wiping out - * any information that was there before + /* If there's a special action for this class that needs to be performed + * when setting the shared component, do that */ - if((ret_value = (type->set_share)(mesg, share)) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to set shared message information") + if(type->set_share) { + if((type->set_share)(mesg, share) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to set shared message information") + } /* end if */ + else { + /* Set this message as the shared component for the message, wiping out + * any information that was there before + */ + if(H5O_set_shared((H5O_shared_t *)mesg, share) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to set shared message information") + } /* end else */ done: FUNC_LEAVE_NOAPI(ret_value) @@ -1592,30 +1649,63 @@ herr_t H5O_msg_reset_share(unsigned type_id, void *mesg) { const H5O_msg_class_t *type; /* Actual H5O class type for the ID */ - H5O_shared_t sh_mesg; /* Shared message */ - herr_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5O_msg_reset_share, FAIL) + FUNC_ENTER_NOAPI_NOFUNC(H5O_msg_reset_share) /* Check args */ HDassert(type_id < NELMTS(H5O_msg_class_g)); type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */ HDassert(type); - HDassert(type->set_share); + HDassert(type->share_flags & H5O_SHARE_IS_SHARABLE); HDassert(mesg); - /* Initialize the shared message to zero. */ - HDmemset(&sh_mesg, 0, sizeof(H5O_shared_t)); + /* Reset the shared component in the message to zero. */ + HDmemset((H5O_shared_t *)mesg, 0, sizeof(H5O_shared_t)); - /* Set this message as the shared message for the message, wiping out - * any information that was there before - */ - if((ret_value = (type->set_share)(mesg, &sh_mesg)) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to reset shared message information") + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_msg_reset_share() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_msg_get_crt_index + * + * Purpose: Call the 'get creation index' method for a message. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * March 15 2007 + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_msg_get_crt_index(unsigned type_id, const void *mesg, H5O_msg_crt_idx_t *crt_idx) +{ + const H5O_msg_class_t *type; /* Actual H5O class type for the ID */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(H5O_msg_get_crt_index, FAIL) + + /* Check args */ + HDassert(type_id < NELMTS(H5O_msg_class_g)); + type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */ + HDassert(type); + HDassert(mesg); + HDassert(crt_idx); + + /* If there is a "get_crt_index callback, use it */ + if(type->get_crt_index) { + /* Retrieve the creation index from the native message */ + if((type->get_crt_index)(mesg, crt_idx) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to retrieve creation index") + } /* end if */ + else + *crt_idx = 0; done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5O_msg_reset_share() */ +} /* end H5O_msg_get_crt_index() */ /*------------------------------------------------------------------------- @@ -1664,9 +1754,6 @@ done: * Purpose: Decode a binary object description and return a new * object handle. * - * Note: This routine is not guaranteed to work with all possible - * header messages, use with care. - * * Return: Success: Pointer to object(data type or space) * * Failure: NULL @@ -1720,10 +1807,9 @@ done: */ void * H5O_msg_copy_file(const H5O_msg_class_t *type, H5F_t *file_src, - void *native_src, H5F_t *file_dst, hid_t dxpl_id, - hbool_t *shared, H5O_copy_t *cpy_info, void *udata) + void *native_src, H5F_t *file_dst, hbool_t *recompute_size, + H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id) { - htri_t is_shared; /* Whether message is shared */ void *native_mesg = NULL; void *ret_value; @@ -1735,19 +1821,15 @@ H5O_msg_copy_file(const H5O_msg_class_t *type, H5F_t *file_src, HDassert(file_src); HDassert(native_src); HDassert(file_dst); + HDassert(recompute_size); HDassert(cpy_info); /* The copy_file callback will return an H5O_shared_t only if the message * to be copied is a committed datatype. */ - if(NULL == (native_mesg = (type->copy_file)(file_src, native_src, file_dst, dxpl_id, cpy_info, udata))) + if(NULL == (native_mesg = (type->copy_file)(file_src, native_src, file_dst, recompute_size, cpy_info, udata, dxpl_id))) HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy object header message to file") - /* Check if new message is shared */ - if((is_shared = H5O_msg_is_shared(type->id, native_mesg)) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to query message's shared status") - *shared = is_shared; - /* Set return value */ ret_value = native_mesg; @@ -1794,20 +1876,14 @@ H5O_msg_alloc(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_msg_class_t *type, HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, UFAIL, "error determining if message is shared") else if(shared_mesg > 0) { /* Increment message's reference count */ - if(type->link && (type->link)(f, dxpl_id, native) < 0) + if(type->link && (type->link)(f, dxpl_id, oh, native) < 0) HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, UFAIL, "unable to adjust shared message ref count") *mesg_flags |= H5O_MSG_FLAG_SHARED; } /* end if */ else { - /* Avoid unsharable messages */ - if(!(*mesg_flags & H5O_MSG_FLAG_DONTSHARE)) { - /* Attempt to share message */ - if((shared_mesg = H5SM_try_share(f, dxpl_id, type->id, native)) > 0) - /* Mark the message as shared */ - *mesg_flags |= H5O_MSG_FLAG_SHARED; - else if(shared_mesg < 0) - HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, UFAIL, "error determining if message should be shared") - } /* end if */ + /* Attempt to share message */ + if(H5SM_try_share(f, dxpl_id, oh, type->id, native, mesg_flags) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, UFAIL, "error determining if message should be shared") } /* end else */ /* Allocate space in the object header for the message */ @@ -1891,6 +1967,10 @@ done: * (while the shared message code needs to delete messages in * the heap). * + * open_oh is a pointer to a currently open object header so + * that the library doesn't try to re-protect it. If there is + * no such object header, it should be NULL. + * * Return: Success: Non-negative * Failure: Negative * @@ -1900,7 +1980,8 @@ done: *------------------------------------------------------------------------- */ herr_t -H5O_msg_delete(H5F_t *f, hid_t dxpl_id, unsigned type_id, const void *mesg) +H5O_msg_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned type_id, + void *mesg) { const H5O_msg_class_t *type; /* Actual H5O class type for the ID */ herr_t ret_value = SUCCEED; /* Return value */ @@ -1914,7 +1995,7 @@ H5O_msg_delete(H5F_t *f, hid_t dxpl_id, unsigned type_id, const void *mesg) HDassert(type); /* delete */ - if((type->del) && (type->del)(f, dxpl_id, mesg) < 0) + if((type->del) && (type->del)(f, dxpl_id, open_oh, mesg) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message") done: @@ -1938,7 +2019,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_mesg_t *mesg) +H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5O_mesg_t *mesg) { const H5O_msg_class_t *type = mesg->type; /* Type of object to free */ herr_t ret_value = SUCCEED; /* Return value */ @@ -1948,13 +2029,14 @@ H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_mesg_t *mesg) /* Check args */ HDassert(f); HDassert(mesg); + HDassert(oh); /* Check if there is a file space deletion callback for this type of message */ if(type->del) { /* Decode the message if necessary. */ - H5O_LOAD_NATIVE(f, dxpl_id, mesg, FAIL) + H5O_LOAD_NATIVE(f, dxpl_id, oh, mesg, FAIL) - if((type->del)(f, dxpl_id, mesg->native) < 0) + if((type->del)(f, dxpl_id, oh, mesg->native) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message") } /* end if */ diff --git a/src/H5Omtime.c b/src/H5Omtime.c index c7e9d90..39d9a16 100644 --- a/src/H5Omtime.c +++ b/src/H5Omtime.c @@ -51,7 +51,7 @@ const H5O_msg_class_t H5O_MSG_MTIME[1] = {{ H5O_MTIME_ID, /*message id number */ "mtime", /*message name for debugging */ sizeof(time_t), /*native message size */ - FALSE, /* messages are sharable? */ + 0, /* messages are sharable? */ H5O_mtime_decode, /*decode message */ H5O_mtime_encode, /*encode message */ H5O_mtime_copy, /*copy the native value */ @@ -76,7 +76,7 @@ const H5O_msg_class_t H5O_MSG_MTIME_NEW[1] = {{ H5O_MTIME_NEW_ID, /*message id number */ "mtime_new", /*message name for debugging */ sizeof(time_t), /*native message size */ - FALSE, /* messages are sharable? */ + 0, /* messages are sharable? */ H5O_mtime_new_decode, /*decode message */ H5O_mtime_new_encode, /*encode message */ H5O_mtime_copy, /*copy the native value */ diff --git a/src/H5Oname.c b/src/H5Oname.c index 8d7ff09..44ab432 100644 --- a/src/H5Oname.c +++ b/src/H5Oname.c @@ -46,7 +46,7 @@ const H5O_msg_class_t H5O_MSG_NAME[1] = {{ H5O_NAME_ID, /*message id number */ "name", /*message name for debugging */ sizeof(H5O_name_t), /*native message size */ - FALSE, /* messages are sharable? */ + 0, /* messages are sharable? */ H5O_name_decode, /*decode message */ H5O_name_encode, /*encode message */ H5O_name_copy, /*copy the native value */ diff --git a/src/H5Onull.c b/src/H5Onull.c index 8a7d8fb..a6c6524 100644 --- a/src/H5Onull.c +++ b/src/H5Onull.c @@ -35,7 +35,7 @@ const H5O_msg_class_t H5O_MSG_NULL[1] = {{ H5O_NULL_ID, /*message id number */ "null", /*message name for debugging */ 0, /*native message size */ - FALSE, /*messages are sharable? */ + 0, /* messages are sharable? */ NULL, /*no decode method */ NULL, /*no encode method */ NULL, /*no copy method */ diff --git a/src/H5Opkg.h b/src/H5Opkg.h index a999638..411297e 100644 --- a/src/H5Opkg.h +++ b/src/H5Opkg.h @@ -176,7 +176,7 @@ /* Load native information for a message, if it's not already present */ /* (Only works for messages with decode callback) */ -#define H5O_LOAD_NATIVE(F, DXPL, MSG, ERR) \ +#define H5O_LOAD_NATIVE(F, DXPL, OH, MSG, ERR) \ if(NULL == (MSG)->native) { \ const H5O_msg_class_t *msg_type = (MSG)->type; \ \ @@ -185,6 +185,11 @@ if(NULL == ((MSG)->native = (msg_type->decode)((F), (DXPL), (MSG)->flags, (MSG)->raw))) \ HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, ERR, "unable to decode message") \ \ + /* Set the message's "shared info", if it's shareable */ \ + if((MSG)->flags & H5O_MSG_FLAG_SHAREABLE) { \ + H5O_UPDATE_SHARED((H5O_shared_t *)(MSG)->native, H5O_SHARE_TYPE_HERE, (F), msg_type->id, (MSG)->crt_idx, (OH)->chunk[0].addr) \ + } /* end if */ \ + \ /* Set the message's "creation index", if it has one */ \ if(msg_type->set_crt_index) { \ /* Set the creation index for the message */ \ @@ -193,25 +198,29 @@ } /* end if */ \ } /* end if */ +/* Flags for a message class's "sharability" */ +#define H5O_SHARE_IS_SHARABLE 0x01 +#define H5O_SHARE_IN_OHDR 0x02 + /* The "message class" type */ struct H5O_msg_class_t { unsigned id; /*message type ID on disk */ const char *name; /*for debugging */ size_t native_size; /*size of native message */ - hbool_t is_sharable; /*are messages of this class sharable? */ + unsigned share_flags; /* Message sharing settings */ void *(*decode)(H5F_t*, hid_t, unsigned, const uint8_t *); herr_t (*encode)(H5F_t*, hbool_t, uint8_t*, const void *); void *(*copy)(const void *, void *); /*copy native value */ size_t (*raw_size)(const H5F_t *, hbool_t, const void *);/*sizeof encoded message */ herr_t (*reset)(void *); /*free nested data structs */ herr_t (*free)(void *); /*free main data struct */ - herr_t (*del)(H5F_t *, hid_t, const void *); /* Delete space in file referenced by this message */ - herr_t (*link)(H5F_t *, hid_t, const void *); /* Increment any links in file reference by this message */ - herr_t (*set_share)(void*, const H5O_shared_t*); /* Set shared information */ + herr_t (*del)(H5F_t *, hid_t, H5O_t *, void *); /* Delete space in file referenced by this message */ + herr_t (*link)(H5F_t *, hid_t, H5O_t *, void *); /* Increment any links in file reference by this message */ + herr_t (*set_share)(void*, const H5O_shared_t*); /* Set shared information */ htri_t (*can_share)(const void *); /* Is message allowed to be shared? */ herr_t (*pre_copy_file)(H5F_t *, const void *, hbool_t *, const H5O_copy_t *, void *); /*"pre copy" action when copying native value to file */ - void *(*copy_file)(H5F_t *, void *, H5F_t *, hid_t, H5O_copy_t *, void *); /*copy native value to file */ + void *(*copy_file)(H5F_t *, void *, H5F_t *, hbool_t *, H5O_copy_t *, void *, hid_t); /*copy native value to file */ herr_t (*post_copy_file)(const H5O_loc_t *, const void *, H5O_loc_t *, void *, hid_t, H5O_copy_t *); /*"post copy" action when copying native value to file */ herr_t (*get_crt_index)(const void *, H5O_msg_crt_idx_t *); /* Get message's creation index */ herr_t (*set_crt_index)(void *, H5O_msg_crt_idx_t); /* Set message's creation index */ @@ -460,7 +469,7 @@ H5_DLLVAR const H5O_obj_class_t H5O_OBJ_DATATYPE[1]; /* Package-local function prototypes */ H5_DLL herr_t H5O_flush_msgs(H5F_t *f, H5O_t *oh); H5_DLL hid_t H5O_open_by_loc(const H5G_loc_t *obj_loc, hid_t dxpl_id); -H5_DLL herr_t H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_mesg_t *mesg); +H5_DLL herr_t H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, H5O_mesg_t *mesg); H5_DLL const H5O_obj_class_t *H5O_obj_class_real(H5O_t *oh); /* Object header message routines */ @@ -481,8 +490,8 @@ H5_DLL htri_t H5O_msg_exists_oh(const H5O_t *oh, unsigned type_id); H5_DLL herr_t H5O_msg_remove_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *type, int sequence, H5O_operator_t op, void *op_data, hbool_t adj_link, hid_t dxpl_id); H5_DLL void *H5O_msg_copy_file(const H5O_msg_class_t *type, H5F_t *file_src, - void *mesg_src, H5F_t *file_dst, hid_t dxpl_id, hbool_t *shared, - H5O_copy_t *cpy_info, void *udata); + void *mesg_src, H5F_t *file_dst, hbool_t *recompute_size, + H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id); H5_DLL herr_t H5O_msg_iterate_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *type, const H5O_mesg_operator_t *op, void *op_data, hid_t dxpl_id); @@ -498,20 +507,20 @@ H5_DLL herr_t H5O_release_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5_DLL void * H5O_shared_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *buf, const H5O_msg_class_t *type); H5_DLL herr_t H5O_shared_encode(const H5F_t *f, uint8_t *buf/*out*/, const H5O_shared_t *sh_mesg); H5_DLL size_t H5O_shared_size(const H5F_t *f, const H5O_shared_t *sh_mesg); -H5_DLL herr_t H5O_shared_delete(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *sh_mesg, - const H5O_msg_class_t *mesg_type); -H5_DLL herr_t H5O_shared_link(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *sh_mesg, - const H5O_msg_class_t *mesg_type); -H5_DLL herr_t H5O_shared_copy_file(H5F_t *file_src, H5F_t *file_dst, hid_t dxpl_id, +H5_DLL herr_t H5O_shared_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, + const H5O_msg_class_t *mesg_type, H5O_shared_t *sh_mesg); +H5_DLL herr_t H5O_shared_link(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, + const H5O_msg_class_t *mesg_type, H5O_shared_t *sh_mesg); +H5_DLL herr_t H5O_shared_copy_file(H5F_t *file_src, H5F_t *file_dst, const H5O_msg_class_t *mesg_type, const void *_native_src, void *_native_dst, - H5O_copy_t *cpy_info, void *udata); + hbool_t *recompute_size, H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id); H5_DLL herr_t H5O_shared_debug(const H5O_shared_t *mesg, FILE *stream, int indent, int fwidth); /* Attribute message operators */ H5_DLL herr_t H5O_attr_reset(void *_mesg); -H5_DLL herr_t H5O_attr_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg); -H5_DLL herr_t H5O_attr_link(H5F_t *f, hid_t dxpl_id, const void *_mesg); +H5_DLL herr_t H5O_attr_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, void *_mesg); +H5_DLL herr_t H5O_attr_link(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, void *_mesg); /* These functions operate on object locations */ H5_DLL H5O_loc_t *H5O_get_loc(hid_t id); diff --git a/src/H5Opline.c b/src/H5Opline.c index f956eba..09b52cc 100644 --- a/src/H5Opline.c +++ b/src/H5Opline.c @@ -64,7 +64,7 @@ const H5O_msg_class_t H5O_MSG_PLINE[1] = {{ H5O_PLINE_ID, /* message id number */ "filter pipeline", /* message name for debugging */ sizeof(H5O_pline_t), /* native message size */ - TRUE, /* messages are sharable? */ + H5O_SHARE_IS_SHARABLE|H5O_SHARE_IN_OHDR, /* messages are sharable? */ H5O_pline_shared_decode, /* decode message */ H5O_pline_shared_encode, /* encode message */ H5O_pline_copy, /* copy the native value */ @@ -73,7 +73,7 @@ const H5O_msg_class_t H5O_MSG_PLINE[1] = {{ H5O_pline_free, /* free method */ H5O_pline_shared_delete, /* file delete method */ H5O_pline_shared_link, /* link method */ - H5O_shared_copy, /* set share method */ + NULL, /* set share method */ NULL, /*can share method */ H5O_pline_pre_copy_file, /* pre copy native value to file */ H5O_pline_shared_copy_file, /* copy native value to file */ diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index 0689838..543f929 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -73,7 +73,8 @@ typedef struct H5O_t H5O_t; #define H5O_MSG_FLAG_FAIL_IF_UNKNOWN 0x08u #define H5O_MSG_FLAG_MARK_IF_UNKNOWN 0x10u #define H5O_MSG_FLAG_WAS_UNKNOWN 0x20u -#define H5O_MSG_FLAG_BITS (H5O_MSG_FLAG_CONSTANT|H5O_MSG_FLAG_SHARED|H5O_MSG_FLAG_DONTSHARE|H5O_MSG_FLAG_FAIL_IF_UNKNOWN|H5O_MSG_FLAG_MARK_IF_UNKNOWN|H5O_MSG_FLAG_WAS_UNKNOWN) +#define H5O_MSG_FLAG_SHAREABLE 0x40u +#define H5O_MSG_FLAG_BITS (H5O_MSG_FLAG_CONSTANT|H5O_MSG_FLAG_SHARED|H5O_MSG_FLAG_DONTSHARE|H5O_MSG_FLAG_FAIL_IF_UNKNOWN|H5O_MSG_FLAG_MARK_IF_UNKNOWN|H5O_MSG_FLAG_WAS_UNKNOWN|H5O_MSG_FLAG_SHAREABLE) /* Flags for updating messages */ #define H5O_UPDATE_TIME 0x01u @@ -93,6 +94,22 @@ typedef struct H5O_t H5O_t; /* ========= Object Copy properties ============ */ #define H5O_CPY_OPTION_NAME "copy object" /* Copy options */ +/* If the module using this macro is allowed access to the private variables, access them directly */ +#ifdef H5O_PACKAGE +#define H5O_OH_GET_ADDR(O) ((O)->chunk[0].addr) +#else /* H5O_PACKAGE */ +#define H5O_OH_GET_ADDR(O) (H5O_get_oh_addr(O)) +#endif /* H5O_PACKAGE */ + +/* Set the fields in a shared message structure */ +#define H5O_UPDATE_SHARED(SH_MESG, SH_TYPE, F, MSG_TYPE, CRT_IDX, OH_ADDR) \ + (SH_MESG)->type = (SH_TYPE); \ + (SH_MESG)->file = (F); \ + (SH_MESG)->msg_type_id = (MSG_TYPE); \ + (SH_MESG)->u.loc.index = (CRT_IDX); \ + (SH_MESG)->u.loc.oh_addr = (OH_ADDR); + + /* Fractal heap ID type for shared message & attribute heap IDs. */ typedef uint64_t H5O_fheap_id_t; @@ -145,29 +162,44 @@ typedef struct H5O_copy_t { /* (this should never exist in a file) */ -/* Shared object message flags. +/* Shared object message types. * Shared objects can be committed, in which case the shared message contains * the location of the object header that holds the message, or shared in the * heap, in which case the shared message holds their heap ID. */ -#define H5O_NOT_SHARED 0 -#define H5O_SHARED_IN_HEAP_FLAG 0x01 -#define H5O_COMMITTED_FLAG 0x02 +#define H5O_SHARE_TYPE_UNSHARED 0 /* Message is not shared */ +#define H5O_SHARE_TYPE_SOHM 1 /* Message is stored in SOHM heap */ +#define H5O_SHARE_TYPE_COMMITTED 2 /* Message is stored in another object header */ +#define H5O_SHARE_TYPE_HERE 3 /* Message is stored in this object header, but is sharable */ + +/* Detect messages that aren't stored in message's object header */ +#define H5O_IS_STORED_SHARED(T) ((((T) == H5O_SHARE_TYPE_SOHM) || ((T) == H5O_SHARE_TYPE_COMMITTED)) ? TRUE : FALSE) + +/* Detect shared messages that are "tracked" in some other location */ +#define H5O_IS_TRACKED_SHARED(T) ((T) > 0) + + +/* Specify the object header address and index needed + * to locate a message in another object header. + */ +typedef struct H5O_mesg_loc_t { + H5O_msg_crt_idx_t index; /* index within object header */ + haddr_t oh_addr; /* address of object header */ +} H5O_mesg_loc_t; -#define H5O_IS_SHARED(F) (((F) & (H5O_SHARED_IN_HEAP_FLAG | H5O_COMMITTED_FLAG)) ? TRUE : FALSE) /* * Shared object header message info. - * This needs to go first because other messages can be shared and - * include a H5O_shared_t struct - * The oloc shouldn't ever be holding open a file; if it ever is (if - * H5O_loc_hold_file was ever called on it) it won't be closed properly, - * since shared messages don't close their olocs. + * + * (This structure is used in other messages that can be shared and will + * include a H5O_shared_t struct as the first field in their "native" type) */ typedef struct H5O_shared_t { - unsigned flags; /* flags describing how message is shared */ + unsigned type; /* Type describing how message is shared */ + H5F_t *file; /* File that message is located within */ + unsigned msg_type_id; /* Message's type ID */ union { - H5O_loc_t oloc; /* object location info */ + H5O_mesg_loc_t loc; /* Object location info */ H5O_fheap_id_t heap_id; /* ID within the SOHM heap */ } u; } H5O_shared_t; @@ -486,6 +518,7 @@ H5_DLL herr_t H5O_get_create_plist(const H5O_loc_t *loc, hid_t dxpl_id, struct H H5_DLL hid_t H5O_open_name(H5G_loc_t *loc, const char *name, hid_t lapl_id); H5_DLL herr_t H5O_get_nlinks(const H5O_loc_t *loc, hid_t dxpl_id, hsize_t *nlinks); H5_DLL void *H5O_obj_create(H5F_t *f, H5O_type_t obj_type, void *crt_info, H5G_loc_t *obj_loc, hid_t dxpl_id); +H5_DLL haddr_t H5O_get_oh_addr(const H5O_t *oh); /* Object header message routines */ H5_DLL herr_t H5O_msg_create(const H5O_loc_t *loc, unsigned type_id, unsigned mesg_flags, @@ -515,13 +548,18 @@ H5_DLL size_t H5O_msg_size_oh(const H5F_t *f, const H5O_t *oh, unsigned type_id, const void *mesg, size_t extra_raw); H5_DLL htri_t H5O_msg_is_shared(unsigned type_id, const void *mesg); H5_DLL htri_t H5O_msg_can_share(unsigned type_id, const void *mesg); -H5_DLL herr_t H5O_msg_set_share(unsigned type_id, H5O_shared_t *share, void *mesg); +H5_DLL htri_t H5O_msg_can_share_in_ohdr(unsigned type_id); +H5_DLL herr_t H5O_msg_set_share(unsigned type_id, const H5O_shared_t *share, + void *mesg); H5_DLL herr_t H5O_msg_reset_share(unsigned type_id, void *mesg); +H5_DLL herr_t H5O_msg_get_crt_index(unsigned type_id, const void *mesg, + H5O_msg_crt_idx_t *crt_idx); H5_DLL herr_t H5O_msg_encode(H5F_t *f, unsigned type_id, hbool_t disable_shared, unsigned char *buf, const void *obj); H5_DLL void* H5O_msg_decode(H5F_t *f, hid_t dxpl_id, unsigned type_id, const unsigned char *buf); -H5_DLL herr_t H5O_msg_delete(H5F_t *f, hid_t dxpl_id, unsigned type_id, const void *mesg); +H5_DLL herr_t H5O_msg_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, + unsigned type_id, void *mesg); /* Object copying routines */ H5_DLL herr_t H5O_copy_header_map(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, @@ -552,10 +590,11 @@ H5_DLL herr_t H5O_fill_reset_dyn(H5O_fill_t *fill); H5_DLL herr_t H5O_fill_convert(H5O_fill_t *fill, H5T_t *type, hbool_t *fill_changed, hid_t dxpl_id); /* Link operators */ -H5_DLL herr_t H5O_link_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg); +H5_DLL herr_t H5O_link_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, + void *_mesg); /* Shared message operators */ -H5_DLL herr_t H5O_shared_copy(void *dst, const H5O_shared_t *src); +H5_DLL herr_t H5O_set_shared(H5O_shared_t *dst, const H5O_shared_t *src); /* Attribute operators */ H5_DLL hsize_t H5O_attr_count_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh); diff --git a/src/H5Orefcount.c b/src/H5Orefcount.c index 85ff4c0..2fd3f94 100644 --- a/src/H5Orefcount.c +++ b/src/H5Orefcount.c @@ -48,7 +48,7 @@ const H5O_msg_class_t H5O_MSG_REFCOUNT[1] = {{ H5O_REFCOUNT_ID, /*message id number */ "refcount", /*message name for debugging */ sizeof(H5O_refcount_t), /*native message size */ - FALSE, /* messages are sharable? */ + 0, /* messages are sharable? */ H5O_refcount_decode, /*decode message */ H5O_refcount_encode, /*encode message */ H5O_refcount_copy, /*copy the native value */ diff --git a/src/H5Osdspace.c b/src/H5Osdspace.c index 124a7de..348f894 100644 --- a/src/H5Osdspace.c +++ b/src/H5Osdspace.c @@ -60,7 +60,7 @@ const H5O_msg_class_t H5O_MSG_SDSPACE[1] = {{ H5O_SDSPACE_ID, /* message id number */ "dataspace", /* message name for debugging */ sizeof(H5S_extent_t), /* native message size */ - TRUE, /* messages are sharable? */ + H5O_SHARE_IS_SHARABLE|H5O_SHARE_IN_OHDR, /* messages are sharable? */ H5O_sdspace_shared_decode, /* decode message */ H5O_sdspace_shared_encode, /* encode message */ H5O_sdspace_copy, /* copy the native value */ @@ -69,7 +69,7 @@ const H5O_msg_class_t H5O_MSG_SDSPACE[1] = {{ H5O_sdspace_free, /* free method */ H5O_sdspace_shared_delete, /* file delete method */ H5O_sdspace_shared_link, /* link method */ - H5O_shared_copy, /* set share method */ + NULL, /* set share method */ NULL, /*can share method */ H5O_sdspace_pre_copy_file, /* pre copy native value to file */ H5O_sdspace_shared_copy_file,/* copy native value to file */ @@ -316,11 +316,6 @@ H5O_sdspace_encode(H5F_t *f, uint8_t *p, const void *_mesg) DESCRIPTION This function copies a native (memory) simple dimensionality message, allocating the destination structure if necessary. - MODIFICATIONS - Raymond Lu - April 8, 2004 - Changed operation on H5S_simple_t to H5S_extent_t. - --------------------------------------------------------------------------*/ static void * H5O_sdspace_copy(const void *mesg, void *dest) @@ -332,20 +327,20 @@ H5O_sdspace_copy(const void *mesg, void *dest) FUNC_ENTER_NOAPI_NOINIT(H5O_sdspace_copy) /* check args */ - assert(src); - if (!dst && NULL==(dst = H5FL_MALLOC(H5S_extent_t))) + HDassert(src); + if(!dst && NULL == (dst = H5FL_MALLOC(H5S_extent_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Copy extent information */ - if(H5S_extent_copy(dst,src)<0) + if(H5S_extent_copy(dst, src) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy extent") /* Set return value */ - ret_value=dst; + ret_value = dst; done: FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5O_sdspace_copy() */ /*-------------------------------------------------------------------------- diff --git a/src/H5Oshared.c b/src/H5Oshared.c index 141fafb..b4f5def 100644 --- a/src/H5Oshared.c +++ b/src/H5Oshared.c @@ -91,15 +91,15 @@ H5O_shared_read(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *shared, HDassert(f); HDassert(shared); HDassert(type); - HDassert(type->set_share); + HDassert(type->share_flags & H5O_SHARE_IS_SHARABLE); /* This message could have a heap ID (SOHM) or the address of an object * header on disk (named datatype) */ - HDassert(shared->flags != H5O_NOT_SHARED); + HDassert(H5O_IS_STORED_SHARED(shared->type)); /* Check for implicit shared object header message */ - if(shared->flags & H5O_SHARED_IN_HEAP_FLAG) { + if(shared->type == H5O_SHARE_TYPE_SOHM) { haddr_t fheap_addr; size_t buf_size; @@ -128,19 +128,24 @@ H5O_shared_read(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *shared, HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "can't read message from fractal heap.") /* Decode the message */ - if(NULL == (ret_value = H5O_msg_decode(f, dxpl_id, type->id, buf))) + if(NULL == (ret_value = (type->decode)(f, dxpl_id, 0, buf))) HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "can't decode shared message.") } /* end if */ else { - HDassert(shared->flags & H5O_COMMITTED_FLAG); + H5O_loc_t oloc; /* Location for object header where message is stored */ + + HDassert(shared->type == H5O_SHARE_TYPE_COMMITTED); /* Get the shared message from an object header */ - if(NULL == (ret_value = H5O_msg_read(&(shared->u.oloc), type->id, NULL, dxpl_id))) + oloc.file = f; + oloc.addr = shared->u.loc.oh_addr; + oloc.holding_file = FALSE; + if(NULL == (ret_value = H5O_msg_read(&oloc, type->id, NULL, dxpl_id))) HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read message") } /* end else */ /* Mark the message as shared */ - if((type->set_share)(ret_value, shared) < 0) + if(H5O_msg_set_share(type->id, shared, ret_value) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to set sharing information") done: @@ -176,8 +181,8 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5O_shared_link_adj(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *shared, - const H5O_msg_class_t *type, int adjust) +H5O_shared_link_adj(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, + const H5O_msg_class_t *type, H5O_shared_t *shared, int adjust) { herr_t ret_value = SUCCEED; /* Return value */ @@ -188,30 +193,37 @@ H5O_shared_link_adj(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *shared, HDassert(shared); /* Check for type of shared message */ - if(shared->flags & H5O_COMMITTED_FLAG) { + if(shared->type == H5O_SHARE_TYPE_COMMITTED) { + H5O_loc_t oloc; /* Location for object header where message is stored */ + /* * The shared message is stored in some other object header. * The other object header must be in the same file as the * new object header. Adjust the reference count on that * object header. */ - if(shared->u.oloc.file->shared != f->shared) + if(shared->file->shared != f->shared) HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "interfile hard links are not allowed") - if(H5O_link(&(shared->u.oloc), adjust, dxpl_id) < 0) + + /* Get the shared message from an object header */ + oloc.file = f; + oloc.addr = shared->u.loc.oh_addr; + oloc.holding_file = FALSE; + + if(H5O_link(&oloc, adjust, dxpl_id) < 0) HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared object link count") } /* end if */ else { - HDassert(shared->flags & H5O_SHARED_IN_HEAP_FLAG); + HDassert(shared->type == H5O_SHARE_TYPE_SOHM || shared->type == H5O_SHARE_TYPE_HERE); /* Check for decrementing reference count on shared message */ if(adjust < 0) { - if(H5SM_try_delete(f, dxpl_id, type->id, shared) < 0) + if(H5SM_delete(f, dxpl_id, open_oh, shared) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "unable to delete message from SOHM table") } /* end if */ /* Check for incrementing reference count on message */ else if(adjust > 0) { - /* Casting away const OK -QAK */ - if(H5SM_try_share(f, dxpl_id, type->id, (void *)shared) < 0) + if(H5SM_try_share(f, dxpl_id, open_oh, type->id, shared, NULL) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTINC, FAIL, "error trying to share message") } /* end if */ } /* end else */ @@ -252,13 +264,13 @@ H5O_shared_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *buf, const H5O_msg_cla if(version < H5O_SHARED_VERSION_1 || version > H5O_SHARED_VERSION_LATEST) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for shared object message") - /* Get the shared information flags + /* Get the shared information type * Flags are unused before version 3. */ if(version >= H5O_SHARED_VERSION_2) - sh_mesg.flags = *buf++; + sh_mesg.type = *buf++; else { - sh_mesg.flags = H5O_COMMITTED_FLAG; + sh_mesg.type = H5O_SHARE_TYPE_COMMITTED; buf++; } /* end else */ @@ -267,31 +279,38 @@ H5O_shared_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *buf, const H5O_msg_cla buf += 6; /* Body */ - if(version == H5O_SHARED_VERSION_1) - H5G_obj_ent_decode(f, &buf, &sh_mesg.u.oloc); + if(version == H5O_SHARED_VERSION_1) { + /* Initialize other location fields */ + sh_mesg.u.loc.index = 0; + + /* Decode stored "symbol table entry" into message location */ + buf += H5F_SIZEOF_SIZE(f); /* Skip over local heap address */ + H5F_addr_decode(f, &buf, &(sh_mesg.u.loc.oh_addr)); + } /* end if */ else if (version >= H5O_SHARED_VERSION_2) { /* If this message is in the heap, copy a heap ID. * Otherwise, it is a named datatype, so copy an H5O_loc_t. */ - if(sh_mesg.flags & H5O_SHARED_IN_HEAP_FLAG) { - HDassert(version >= H5O_SHARED_VERSION_3 ); + if(sh_mesg.type == H5O_SHARE_TYPE_SOHM) { + HDassert(version >= H5O_SHARED_VERSION_3); HDmemcpy(&sh_mesg.u.heap_id, buf, sizeof(sh_mesg.u.heap_id)); - } + } /* end if */ else { /* The H5O_COMMITTED_FLAG should be set if this message * is from an older version before the flag existed. */ if(version < H5O_SHARED_VERSION_3) - sh_mesg.flags = H5O_COMMITTED_FLAG; + sh_mesg.type = H5O_SHARE_TYPE_COMMITTED; - HDassert(sh_mesg.flags & H5O_COMMITTED_FLAG); - - H5F_addr_decode(f, &buf, &sh_mesg.u.oloc.addr); - sh_mesg.u.oloc.file = f; - sh_mesg.u.oloc.holding_file = FALSE; + sh_mesg.u.loc.index = 0; + H5F_addr_decode(f, &buf, &sh_mesg.u.loc.oh_addr); } /* end else */ } /* end else if */ + /* Set file pointer & message type for all types of shared messages */ + sh_mesg.file = f; + sh_mesg.msg_type_id = type->id; + /* Retrieve actual message, through decoded shared message info */ if(NULL == (ret_value = H5O_shared_read(f, dxpl_id, &sh_mesg, type))) HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to retrieve native message") @@ -328,37 +347,34 @@ H5O_shared_encode(const H5F_t *f, uint8_t *buf/*out*/, const H5O_shared_t *sh_me /* If this message is shared in the heap, we need to use version 3 of the * encoding and encode the SHARED_IN_HEAP flag. */ - if(sh_mesg->flags & H5O_SHARED_IN_HEAP_FLAG || H5F_USE_LATEST_FORMAT(f)) + if(sh_mesg->type == H5O_SHARE_TYPE_SOHM || H5F_USE_LATEST_FORMAT(f)) version = H5O_SHARED_VERSION_LATEST; else { - HDassert(sh_mesg->flags & H5O_COMMITTED_FLAG); + HDassert(sh_mesg->type == H5O_SHARE_TYPE_COMMITTED); version = H5O_SHARED_VERSION_2; /* version 1 is no longer used */ } /* end else */ *buf++ = version; - *buf++ = (unsigned)sh_mesg->flags; + *buf++ = (unsigned)sh_mesg->type; /* Encode either the heap ID of the message or the address of the * object header that holds it. */ - if(sh_mesg->flags & H5O_SHARED_IN_HEAP_FLAG) + if(sh_mesg->type == H5O_SHARE_TYPE_SOHM) HDmemcpy(buf, &(sh_mesg->u.heap_id), sizeof(sh_mesg->u.heap_id)); else - H5F_addr_encode(f, &buf, sh_mesg->u.oloc.addr); + H5F_addr_encode(f, &buf, sh_mesg->u.loc.oh_addr); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5O_shared_encode() */ /*------------------------------------------------------------------------- - * Function: H5O_shared_copy - * - * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if - * necessary. + * Function: H5O_set_shared * - * Return: Success: Ptr to _DEST + * Purpose: Sets the shared component for a message. * - * Failure: NULL + * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu @@ -367,28 +383,19 @@ H5O_shared_encode(const H5F_t *f, uint8_t *buf/*out*/, const H5O_shared_t *sh_me *------------------------------------------------------------------------- */ herr_t -H5O_shared_copy(void *_dst, const H5O_shared_t *src) +H5O_set_shared(H5O_shared_t *dst, const H5O_shared_t *src) { - H5O_shared_t *dst = (H5O_shared_t *)_dst; - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_shared_copy) + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_set_shared) /* check args */ HDassert(dst); HDassert(src); /* copy */ - dst->flags = src->flags; - if(src->flags & H5O_COMMITTED_FLAG) - H5O_loc_copy(&(dst->u.oloc), &(src->u.oloc), H5_COPY_DEEP); - else if(src->flags & H5O_SHARED_IN_HEAP_FLAG) - dst->u.heap_id = src->u.heap_id; - else - /* This message's sharing information is being reset */ - HDassert(src->flags == H5O_NOT_SHARED); + *dst = *src; FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5O_shared_copy() */ +} /* end H5O_set_shared() */ /*------------------------------------------------------------------------- @@ -411,16 +418,16 @@ H5O_shared_size(const H5F_t *f, const H5O_shared_t *sh_mesg) FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_shared_size) - if(sh_mesg->flags & H5O_COMMITTED_FLAG) { + if(sh_mesg->type == H5O_SHARE_TYPE_COMMITTED) { ret_value = 1 + /*version */ - 1 + /*the flags field */ + 1 + /*the type field */ H5F_SIZEOF_ADDR(f); /*sharing by another obj hdr */ } /* end if */ else { - HDassert(sh_mesg->flags & H5O_SHARED_IN_HEAP_FLAG); + HDassert(sh_mesg->type == H5O_SHARE_TYPE_SOHM); ret_value = 1 + /*version */ - 1 + /*the flags field */ - H5O_FHEAP_ID_LEN; /* Shared in the heap */ + 1 + /*the type field */ + H5O_FHEAP_ID_LEN; /* Shared in the heap */ } /* end else */ FUNC_LEAVE_NOAPI(ret_value) @@ -440,8 +447,8 @@ H5O_shared_size(const H5F_t *f, const H5O_shared_t *sh_mesg) *------------------------------------------------------------------------- */ herr_t -H5O_shared_delete(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *sh_mesg, - const H5O_msg_class_t *type) +H5O_shared_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, + const H5O_msg_class_t *type, H5O_shared_t *sh_mesg) { herr_t ret_value = SUCCEED; /* Return value */ @@ -461,7 +468,7 @@ H5O_shared_delete(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *sh_mesg, */ /* Decrement the reference count on the shared object */ - if(H5O_shared_link_adj(f, dxpl_id, sh_mesg, type, -1) < 0) + if(H5O_shared_link_adj(f, dxpl_id, open_oh, type, sh_mesg, -1) < 0) HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared object link count") done: @@ -483,8 +490,8 @@ done: *------------------------------------------------------------------------- */ herr_t -H5O_shared_link(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *sh_mesg, - const H5O_msg_class_t *type) +H5O_shared_link(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, + const H5O_msg_class_t *type, H5O_shared_t *sh_mesg) { herr_t ret_value = SUCCEED; /* Return value */ @@ -495,7 +502,7 @@ H5O_shared_link(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *sh_mesg, HDassert(sh_mesg); /* Increment the reference count on the shared object */ - if(H5O_shared_link_adj(f, dxpl_id, sh_mesg, type, 1) < 0) + if(H5O_shared_link_adj(f, dxpl_id, open_oh, type, sh_mesg, 1) < 0) HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared object link count") done: @@ -517,9 +524,10 @@ done: *------------------------------------------------------------------------- */ herr_t -H5O_shared_copy_file(H5F_t *file_src, H5F_t *file_dst, hid_t dxpl_id, +H5O_shared_copy_file(H5F_t *file_src, H5F_t *file_dst, const H5O_msg_class_t *mesg_type, const void *_native_src, void *_native_dst, - H5O_copy_t *cpy_info, void UNUSED *udata) + hbool_t *recompute_size, H5O_copy_t *cpy_info, void UNUSED *udata, + hid_t dxpl_id) { const H5O_shared_t *shared_src = (const H5O_shared_t *)_native_src; /* Alias to shared info in native source */ H5O_shared_t *shared_dst = (H5O_shared_t *)_native_dst; /* Alias to shared info in native destination message */ @@ -533,6 +541,7 @@ H5O_shared_copy_file(H5F_t *file_src, H5F_t *file_dst, hid_t dxpl_id, HDassert(mesg_type); HDassert(shared_src); HDassert(shared_dst); + HDassert(recompute_size); HDassert(cpy_info); /* Committed shared messages create a shared message at the destination @@ -540,18 +549,24 @@ H5O_shared_copy_file(H5F_t *file_src, H5F_t *file_dst, hid_t dxpl_id, * * SOHMs try to share the destination message. */ - if(shared_src->flags & H5O_COMMITTED_FLAG) { - /* Set up destination message's shared info */ - shared_dst->u.oloc.file = file_dst; - shared_dst->flags = shared_src->flags; + if(shared_src->type == H5O_SHARE_TYPE_COMMITTED) { + H5O_loc_t dst_oloc; + H5O_loc_t src_oloc; /* Copy the shared object from source to destination */ - if(H5O_copy_header_map(&(shared_src->u.oloc), &(shared_dst->u.oloc), dxpl_id, cpy_info, FALSE) < 0) + dst_oloc.file = file_dst; + src_oloc.file = shared_src->file; + src_oloc.addr = shared_src->u.loc.oh_addr; + if(H5O_copy_header_map(&src_oloc, &dst_oloc, dxpl_id, cpy_info, FALSE) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object") + + /* Set up destination message's shared info */ + H5O_UPDATE_SHARED(shared_dst, H5O_SHARE_TYPE_COMMITTED, file_dst, mesg_type->id, 0, dst_oloc.addr) } /* end if */ else { /* Try to share new message in the destination file. */ - if(H5SM_try_share(file_dst, dxpl_id, mesg_type->id, _native_dst) < 0) + /* JAMES: message is always shared in heap in dest. file */ + if(H5SM_try_share(file_dst, dxpl_id, NULL, mesg_type->id, _native_dst, NULL) < 0) HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to determine if message should be shared") } /* end else */ @@ -583,26 +598,42 @@ H5O_shared_debug(const H5O_shared_t *mesg, FILE *stream, int indent, int fwidth) HDassert(indent >= 0); HDassert(fwidth >= 0); - HDfprintf(stream, "%*s%-*s %x\n", indent, "", fwidth, - "Shared Message Flags:", - mesg->flags); - if(mesg->flags & H5O_COMMITTED_FLAG) { - HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, - "Sharing method:", - "Obj Hdr"); - HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, - "Object address:", - mesg->u.oloc.addr); - } /* end if */ - else { - HDassert(mesg->flags & H5O_SHARED_IN_HEAP_FLAG); - HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, - "Sharing method:", - "SOHM Heap"); - HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, - "Heap ID:", - mesg->u.heap_id); - } /* end else */ + switch(mesg->type) { + case H5O_SHARE_TYPE_UNSHARED: + HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, + "Shared Message type:", + "Unshared"); + break; + + case H5O_SHARE_TYPE_COMMITTED: + HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, + "Shared Message type:", + "Obj Hdr"); + HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, + "Object address:", + mesg->u.loc.oh_addr); + break; + + case H5O_SHARE_TYPE_SOHM: + HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, + "Shared Message type:", + "SOHM"); + HDfprintf(stream, "%*s%-*s %016llx\n", indent, "", fwidth, + "Heap ID:", + (unsigned long long)mesg->u.heap_id); + break; + + case H5O_SHARE_TYPE_HERE: + HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, + "Shared Message type:", + "Here"); + break; + + default: + HDfprintf(stream, "%*s%-*s %s (%u)\n", indent, "", fwidth, + "Shared Message type:", + "Unknown", (unsigned)mesg->type); + } /* end switch */ FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5O_shared_debug() */ diff --git a/src/H5Oshared.h b/src/H5Oshared.h index 268e605..27d2ac3 100644 --- a/src/H5Oshared.h +++ b/src/H5Oshared.h @@ -116,8 +116,11 @@ H5O_SHARED_ENCODE(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mes #error "Need to define H5O_SHARED_ENCODE_REAL macro!" #endif /* H5O_SHARED_ENCODE_REAL */ - /* Check for shared message */ - if(H5O_IS_SHARED(sh_mesg->flags) && !disable_shared) { + /* Sanity check */ + HDassert(sh_mesg->type == H5O_SHARE_TYPE_UNSHARED || sh_mesg->msg_type_id == H5O_SHARED_TYPE->id); + + /* Check for message stored elsewhere */ + if(H5O_IS_STORED_SHARED(sh_mesg->type) && !disable_shared) { /* Encode shared message into buffer */ if(H5O_shared_encode(f, p, sh_mesg) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "unable to encode shared message") @@ -168,8 +171,8 @@ H5O_SHARED_SIZE(const H5F_t *f, hbool_t disable_shared, const void *_mesg) #error "Need to define H5O_SHARED_SIZE_REAL macro!" #endif /* H5O_SHARED_SIZE_REAL */ - /* Check for shared message */ - if(H5O_IS_SHARED(sh_mesg->flags) && !disable_shared) { + /* Check for message stored elsewhere */ + if(H5O_IS_STORED_SHARED(sh_mesg->type) && !disable_shared) { /* Retrieve encoded size of shared message */ if(0 == (ret_value = H5O_shared_size(f, sh_mesg))) HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, 0, "unable to retrieve encoded size of shared message") @@ -204,9 +207,9 @@ done: *------------------------------------------------------------------------- */ static H5_inline herr_t -H5O_SHARED_DELETE(H5F_t *f, hid_t dxpl_id, const void *_mesg) +H5O_SHARED_DELETE(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, void *_mesg) { - const H5O_shared_t *sh_mesg = (const H5O_shared_t *)_mesg; /* Pointer to shared message portion of actual message */ + H5O_shared_t *sh_mesg = (H5O_shared_t *)_mesg; /* Pointer to shared message portion of actual message */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_SHARED_DELETE) @@ -218,16 +221,16 @@ H5O_SHARED_DELETE(H5F_t *f, hid_t dxpl_id, const void *_mesg) #error "Need to define H5O_SHARED_DELETE macro!" #endif /* H5O_SHARED_DELETE */ - /* Check for shared message */ - if(H5O_IS_SHARED(sh_mesg->flags)) { + /* Check for message tracked elsewhere */ + if(H5O_IS_TRACKED_SHARED(sh_mesg->type)) { /* Decrement the reference count on the shared message/object */ - if(H5O_shared_delete(f, dxpl_id, sh_mesg, H5O_SHARED_TYPE) < 0) + if(H5O_shared_delete(f, dxpl_id, open_oh, H5O_SHARED_TYPE, sh_mesg) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "unable to decrement ref count for shared message") } /* end if */ #ifdef H5O_SHARED_DELETE_REAL else { /* Decrement the reference count on the native message directly */ - if(H5O_SHARED_DELETE_REAL(f, dxpl_id, _mesg) < 0) + if(H5O_SHARED_DELETE_REAL(f, dxpl_id, open_oh, _mesg) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "unable to decrement ref count for native message") } /* end else */ #endif /* H5O_SHARED_DELETE_REAL */ @@ -256,9 +259,9 @@ done: *------------------------------------------------------------------------- */ static H5_inline herr_t -H5O_SHARED_LINK(H5F_t *f, hid_t dxpl_id, const void *_mesg) +H5O_SHARED_LINK(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, void *_mesg) { - const H5O_shared_t *sh_mesg = (const H5O_shared_t *)_mesg; /* Pointer to shared message portion of actual message */ + H5O_shared_t *sh_mesg = (H5O_shared_t *)_mesg; /* Pointer to shared message portion of actual message */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_SHARED_LINK) @@ -270,16 +273,16 @@ H5O_SHARED_LINK(H5F_t *f, hid_t dxpl_id, const void *_mesg) #error "Need to define H5O_SHARED_LINK macro!" #endif /* H5O_SHARED_LINK */ - /* Check for shared message */ - if(H5O_IS_SHARED(sh_mesg->flags)) { + /* Check for message tracked elsewhere */ + if(H5O_IS_TRACKED_SHARED(sh_mesg->type)) { /* Increment the reference count on the shared message/object */ - if(H5O_shared_link(f, dxpl_id, sh_mesg, H5O_SHARED_TYPE) < 0) + if(H5O_shared_link(f, dxpl_id, open_oh, H5O_SHARED_TYPE, sh_mesg) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTINC, FAIL, "unable to increment ref count for shared message") } /* end if */ #ifdef H5O_SHARED_LINK_REAL else { /* Increment the reference count on the native message directly */ - if(H5O_SHARED_LINK_REAL(f, dxpl_id, _mesg) < 0) + if(H5O_SHARED_LINK_REAL(f, dxpl_id, open_oh, _mesg) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTINC, FAIL, "unable to increment ref count for native message") } /* end else */ #endif /* H5O_SHARED_LINK_REAL */ @@ -307,9 +310,8 @@ done: *------------------------------------------------------------------------- */ static H5_inline void * -H5O_SHARED_COPY_FILE(H5F_t *file_src, - void *_native_src, H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, - void *udata) +H5O_SHARED_COPY_FILE(H5F_t *file_src, void *_native_src, H5F_t *file_dst, + hbool_t *recompute_size, H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id) { void *dst_mesg = NULL; /* Destination message */ void *ret_value; /* Return value */ @@ -325,7 +327,7 @@ H5O_SHARED_COPY_FILE(H5F_t *file_src, #ifdef H5O_SHARED_COPY_FILE_REAL /* Call native message's copy file callback to copy the message */ - if(NULL == (dst_mesg = H5O_SHARED_COPY_FILE_REAL(file_src, H5O_SHARED_TYPE, _native_src, file_dst, dxpl_id, cpy_info, udata))) + if(NULL == (dst_mesg = H5O_SHARED_COPY_FILE_REAL(file_src, H5O_SHARED_TYPE, _native_src, file_dst, recompute_size, cpy_info, udata, dxpl_id))) HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy native message to another file") #else /* H5O_SHARED_COPY_FILE_REAL */ /* No copy file callback defined, just copy the message itself */ @@ -337,8 +339,8 @@ H5O_SHARED_COPY_FILE(H5F_t *file_src, HDmemset(dst_mesg, 0, sizeof(H5O_shared_t)); /* Handle sharing destination message */ - if(H5O_shared_copy_file(file_src, file_dst, dxpl_id, H5O_SHARED_TYPE, - _native_src, dst_mesg, cpy_info, udata) < 0) + if(H5O_shared_copy_file(file_src, file_dst, H5O_SHARED_TYPE, + _native_src, dst_mesg, recompute_size, cpy_info, udata, dxpl_id) < 0) HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, NULL, "unable to determine if message should be shared") /* Set return value */ @@ -389,8 +391,8 @@ H5O_SHARED_DEBUG(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE *stream, #error "Need to define H5O_SHARED_DEBUG_REAL macro!" #endif /* H5O_SHARED_DEBUG_REAL */ - /* Check for shared message */ - if(H5O_IS_SHARED(sh_mesg->flags)) { + /* Check for message stored elsewhere */ + if(H5O_IS_STORED_SHARED(sh_mesg->type)) { /* Print shared message information */ if(H5O_shared_debug(sh_mesg, stream, indent, fwidth) < 0) HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to display shared message info") @@ -400,7 +402,6 @@ H5O_SHARED_DEBUG(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE *stream, if(H5O_SHARED_DEBUG_REAL(f, dxpl_id, _mesg, stream, indent, fwidth) < 0) HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to display native message info") - done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_SHARED_DEBUG() */ diff --git a/src/H5Oshmesg.c b/src/H5Oshmesg.c index 7ac5ed6..e66bdec 100644 --- a/src/H5Oshmesg.c +++ b/src/H5Oshmesg.c @@ -40,7 +40,7 @@ const H5O_msg_class_t H5O_MSG_SHMESG[1] = {{ H5O_SHMESG_ID, /*message id number */ "shared message table", /*message name for debugging */ sizeof(H5O_shmesg_table_t), /*native message size */ - FALSE, /* messages are sharable? */ + 0, /* messages are sharable? */ H5O_shmesg_decode, /*decode message */ H5O_shmesg_encode, /*encode message */ H5O_shmesg_copy, /*copy the native value */ diff --git a/src/H5Ostab.c b/src/H5Ostab.c index 196db27..978b9c5 100644 --- a/src/H5Ostab.c +++ b/src/H5Ostab.c @@ -41,9 +41,10 @@ static herr_t H5O_stab_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, cons static void *H5O_stab_copy(const void *_mesg, void *_dest); static size_t H5O_stab_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg); static herr_t H5O_stab_free(void *_mesg); -static herr_t H5O_stab_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg); +static herr_t H5O_stab_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, void *_mesg); static void *H5O_stab_copy_file(H5F_t *file_src, void *native_src, - H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata); + H5F_t *file_dst, hbool_t *recompute_size, H5O_copy_t *cpy_info, void *udata, + hid_t dxpl_id); static herr_t H5O_stab_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info); static herr_t H5O_stab_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, @@ -54,7 +55,7 @@ const H5O_msg_class_t H5O_MSG_STAB[1] = {{ H5O_STAB_ID, /*message id number */ "stab", /*message name for debugging */ sizeof(H5O_stab_t), /*native message size */ - FALSE, /* messages are sharable? */ + 0, /* messages are sharable? */ H5O_stab_decode, /*decode message */ H5O_stab_encode, /*encode message */ H5O_stab_copy, /*copy the native value */ @@ -270,7 +271,7 @@ H5O_stab_free (void *mesg) *------------------------------------------------------------------------- */ static herr_t -H5O_stab_delete(H5F_t *f, hid_t dxpl_id, const void *mesg) +H5O_stab_delete(H5F_t *f, hid_t dxpl_id, H5O_t UNUSED *open_oh, void *mesg) { herr_t ret_value = SUCCEED; /* Return value */ @@ -305,7 +306,8 @@ done: */ static void * H5O_stab_copy_file(H5F_t *file_src, void *native_src, H5F_t *file_dst, - hid_t dxpl_id, H5O_copy_t UNUSED *cpy_info, void UNUSED *udata) + hbool_t UNUSED *recompute_size, H5O_copy_t UNUSED *cpy_info, void UNUSED *udata, + hid_t dxpl_id) { H5O_stab_t *stab_src = (H5O_stab_t *) native_src; H5O_stab_t *stab_dst = NULL; diff --git a/src/H5Pdcpl.c b/src/H5Pdcpl.c index 1e9f108..c16a2c5 100644 --- a/src/H5Pdcpl.c +++ b/src/H5Pdcpl.c @@ -60,7 +60,7 @@ /* Definitions for fill value. size=0 means fill value will be 0 as * library default; size=-1 means fill value is undefined. */ #define H5D_CRT_FILL_VALUE_SIZE sizeof(H5O_fill_t) -#define H5D_CRT_FILL_VALUE_DEF {{0, {{NULL, HADDR_UNDEF, FALSE}}}, NULL, 0, NULL, H5D_ALLOC_TIME_LATE, H5D_FILL_TIME_IFSET, FALSE} +#define H5D_CRT_FILL_VALUE_DEF {{0, NULL, H5O_NULL_ID, {{0, HADDR_UNDEF}}}, NULL, 0, NULL, H5D_ALLOC_TIME_LATE, H5D_FILL_TIME_IFSET, FALSE} #define H5D_CRT_FILL_VALUE_CMP H5P_fill_value_cmp /* Definitions for space allocation time state */ #define H5D_CRT_ALLOC_TIME_STATE_SIZE sizeof(unsigned) @@ -71,7 +71,7 @@ #define H5D_CRT_EXT_FILE_LIST_CMP H5P_dcrt_ext_file_list_cmp /* Definitions for data filter pipeline */ #define H5D_CRT_DATA_PIPELINE_SIZE sizeof(H5O_pline_t) -#define H5D_CRT_DATA_PIPELINE_DEF {{0, {{NULL, HADDR_UNDEF, FALSE}}}, 0, 0, NULL} +#define H5D_CRT_DATA_PIPELINE_DEF {{0, NULL, H5O_NULL_ID, {{0, HADDR_UNDEF}}}, 0, 0, NULL} #define H5D_CRT_DATA_PIPELINE_CMP H5P_dcrt_data_pipeline_cmp @@ -94,7 +94,7 @@ H5S_init_interface(void) /* Initialize the atom group for the file IDs */ if(H5I_register_type(H5I_DATASPACE, (size_t)H5I_DATASPACEID_HASHSIZE, H5S_RESERVED_ATOMS, (H5I_free_t)H5S_close) < 0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize interface"); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize interface") #ifdef H5_HAVE_PARALLEL { @@ -303,42 +303,54 @@ H5S_term_interface(void) static H5S_t * H5S_create(H5S_class_t type) { - H5S_t *ret_value; + H5S_t *new_ds = NULL; /* New dataspace created */ + H5S_t *ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5S_create, NULL); + FUNC_ENTER_NOAPI_NOINIT(H5S_create) /* Create a new data space */ - if((ret_value = H5FL_MALLOC(H5S_t))!=NULL) { - ret_value->extent.type = type; - ret_value->extent.rank = 0; - ret_value->extent.size = ret_value->extent.max = NULL; - - switch(type) { - case H5S_SCALAR: - ret_value->extent.nelem = 1; - break; - case H5S_SIMPLE: - case H5S_NULL: - ret_value->extent.nelem = 0; - break; - default: - assert("unknown dataspace (extent) type" && 0); - break; - } /* end switch */ - - /* Start with "all" selection */ - if(H5S_select_all(ret_value,0)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTSET, NULL, "unable to set all selection"); - - /* Reset common selection info pointer */ - ret_value->select.sel_info.hslab=NULL; - - /* Reset "shared" info on extent */ - ret_value->extent.sh_loc.flags = 0; - } /* end if */ + if(NULL == (new_ds = H5FL_MALLOC(H5S_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* Initialize default dataspace state */ + new_ds->extent.type = type; + new_ds->extent.rank = 0; + new_ds->extent.size = new_ds->extent.max = NULL; + + switch(type) { + case H5S_SCALAR: + new_ds->extent.nelem = 1; + break; + + case H5S_SIMPLE: + case H5S_NULL: + new_ds->extent.nelem = 0; + break; + + default: + HDassert("unknown dataspace (extent) type" && 0); + break; + } /* end switch */ + + /* Start with "all" selection */ + if(H5S_select_all(new_ds, 0) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, NULL, "unable to set all selection") + + /* Reset common selection info pointer */ + new_ds->select.sel_info.hslab = NULL; + + /* Reset "shared" info on extent */ + if(H5O_msg_reset_share(H5O_SDSPACE_ID, &(new_ds->extent.sh_loc)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRESET, NULL, "unable to reset shared component info") + + /* Set return value */ + ret_value = new_ds; done: - FUNC_LEAVE_NOAPI(ret_value); + if(ret_value == NULL && new_ds) + H5S_close(new_ds); + + FUNC_LEAVE_NOAPI(ret_value) } /* end H5S_create() */ @@ -370,21 +382,19 @@ H5Screate(H5S_class_t type) H5TRACE1("i", "Sc", type); /* Check args */ - if(type<=H5S_NO_CLASS || type> H5S_NULL) /* don't allow complex dataspace yet */ - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid dataspace type"); + if(type <= H5S_NO_CLASS || type > H5S_NULL) /* don't allow complex dataspace yet */ + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid dataspace type") - if (NULL==(new_ds=H5S_create(type))) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create dataspace"); + if(NULL == (new_ds = H5S_create(type))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create dataspace") /* Atomize */ - if ((ret_value=H5I_register (H5I_DATASPACE, new_ds))<0) - HGOTO_ERROR (H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register data space atom"); + if((ret_value = H5I_register (H5I_DATASPACE, new_ds)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register data space atom") done: - if (ret_value < 0) { - if(new_ds!=NULL) - H5S_close(new_ds); - } /* end if */ + if(ret_value < 0 && new_ds) + H5S_close(new_ds); FUNC_LEAVE_API(ret_value); } /* end H5Screate() */ @@ -487,11 +497,11 @@ H5Sclose(hid_t space_id) /* Check args */ if (NULL == H5I_object_verify(space_id,H5I_DATASPACE)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") /* When the reference count reaches zero the resources are freed */ if (H5I_dec_ref(space_id) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "problem freeing id"); + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "problem freeing id") done: FUNC_LEAVE_API(ret_value); @@ -526,15 +536,15 @@ H5Scopy(hid_t space_id) /* Check args */ if (NULL==(src=(H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE))) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") /* Copy */ if (NULL==(dst=H5S_copy (src, FALSE))) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to copy data space"); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to copy data space") /* Atomize */ if ((ret_value=H5I_register (H5I_DATASPACE, dst))<0) - HGOTO_ERROR (H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register data space atom"); + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register data space atom") done: if(ret_value<0) { @@ -572,13 +582,13 @@ H5Sextent_copy(hid_t dst_id,hid_t src_id) /* Check args */ if (NULL==(src=(H5S_t *)H5I_object_verify(src_id, H5I_DATASPACE))) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") if (NULL==(dst=(H5S_t *)H5I_object_verify(dst_id, H5I_DATASPACE))) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") /* Copy */ if (H5S_extent_copy(&(dst->extent),&(src->extent))<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy extent"); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy extent") done: FUNC_LEAVE_API(ret_value); @@ -642,7 +652,7 @@ H5S_extent_copy(H5S_extent_t *dst, const H5S_extent_t *src) } /* end switch */ /* Copy the shared object info */ - if(H5O_shared_copy(&(dst->sh_loc), &(src->sh_loc)) < 0) + if(H5O_set_shared(&(dst->sh_loc), &(src->sh_loc)) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy shared information") done: @@ -765,7 +775,7 @@ H5Sget_simple_extent_npoints(hid_t space_id) /* Check args */ if (NULL == (ds = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") ret_value = H5S_GET_EXTENT_NPOINTS(ds); @@ -834,7 +844,7 @@ H5S_get_npoints_max(const H5S_t *ds) default: assert("unknown data space class" && 0); - HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, 0, "internal error (unknown data space class)"); + HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, 0, "internal error (unknown data space class)") } done: @@ -869,7 +879,7 @@ H5Sget_simple_extent_ndims(hid_t space_id) /* Check args */ if (NULL == (ds = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") ret_value = H5S_GET_EXTENT_NDIMS(ds); @@ -918,7 +928,7 @@ H5S_get_simple_extent_ndims(const H5S_t *ds) default: assert("unknown data space class" && 0); - HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "internal error (unknown data space class)"); + HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "internal error (unknown data space class)") } done: @@ -960,7 +970,7 @@ H5Sget_simple_extent_dims(hid_t space_id, hsize_t dims[]/*out*/, /* Check args */ if (NULL == (ds = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace"); + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") ret_value = H5S_get_simple_extent_dims(ds, dims, maxdims); @@ -1019,7 +1029,7 @@ H5S_get_simple_extent_dims(const H5S_t *ds, hsize_t dims[], hsize_t max_dims[]) default: assert("unknown data space class" && 0); - HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "internal error (unknown data space class)"); + HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "internal error (unknown data space class)") } done: @@ -1184,17 +1194,17 @@ H5S_is_simple(const H5S_t *sdim) { htri_t ret_value; - FUNC_ENTER_NOAPI(H5S_is_simple, FAIL); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_is_simple) /* Check args and all the boring stuff. */ - assert(sdim); + HDassert(sdim); + /* H5S_NULL shouldn't be simple dataspace */ ret_value = (H5S_GET_EXTENT_TYPE(sdim) == H5S_SIMPLE || H5S_GET_EXTENT_TYPE(sdim) == H5S_SCALAR) ? TRUE : FALSE; -done: - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_is_simple() */ /*-------------------------------------------------------------------------- @@ -1222,7 +1232,7 @@ H5Sis_simple(hid_t space_id) /* Check args and all the boring stuff. */ if ((space = (H5S_t *)H5I_object_verify(space_id,H5I_DATASPACE)) == NULL) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a data space"); + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a data space") ret_value = H5S_is_simple(space); @@ -1276,31 +1286,31 @@ H5Sset_extent_simple(hid_t space_id, int rank, const hsize_t dims[/*rank*/], /* Check args */ if ((space = (H5S_t *)H5I_object_verify(space_id,H5I_DATASPACE)) == NULL) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a data space"); + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a data space") if (rank > 0 && dims == NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no dimensions specified"); + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no dimensions specified") if (rank<0 || rank>H5S_MAX_RANK) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid rank"); + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid rank") if (dims) { for (u=0; u<rank; u++) { if (H5S_UNLIMITED==dims[u]) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "current dimension must have a specific size, not H5S_UNLIMITED"); + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "current dimension must have a specific size, not H5S_UNLIMITED") if (((max!=NULL && max[u]!=H5S_UNLIMITED) || max==NULL) && dims[u]==0) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid dimension size"); + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid dimension size") } } if (max!=NULL) { if(dims==NULL) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "maximum dimension specified, but no current dimensions specified"); + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "maximum dimension specified, but no current dimensions specified") for (u=0; u<rank; u++) { if (max[u]!=H5S_UNLIMITED && max[u]<dims[u]) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid maximum dimension size"); + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid maximum dimension size") } } /* Do it */ if (H5S_set_extent_simple(space, (unsigned)rank, dims, max)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to set simple extent"); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to set simple extent") done: FUNC_LEAVE_API(ret_value); @@ -1323,27 +1333,28 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5S_set_extent_simple (H5S_t *space, unsigned rank, const hsize_t *dims, +H5S_set_extent_simple(H5S_t *space, unsigned rank, const hsize_t *dims, const hsize_t *max) { unsigned u; /* Local index variable */ - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5S_set_extent_simple, FAIL); + FUNC_ENTER_NOAPI_NOINIT(H5S_set_extent_simple) /* Check args */ - assert(rank<=H5S_MAX_RANK); - assert(0==rank || dims); + HDassert(rank <= H5S_MAX_RANK); + HDassert(0 == rank || dims); /* shift out of the previous state to a "simple" dataspace. */ - if(H5S_extent_release(&space->extent)<0) - HGOTO_ERROR (H5E_RESOURCE, H5E_CANTFREE, FAIL, "failed to release previous dataspace extent"); + if(H5S_extent_release(&space->extent) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "failed to release previous dataspace extent") - if (rank == 0) { /* scalar variable */ + if(rank == 0) { /* scalar variable */ space->extent.type = H5S_SCALAR; space->extent.nelem = 1; space->extent.rank = 0; /* set to scalar rank */ - } else { + } /* end if */ + else { hsize_t nelem; /* Number of elements in extent */ space->extent.type = H5S_SIMPLE; @@ -1366,22 +1377,22 @@ H5S_set_extent_simple (H5S_t *space, unsigned rank, const hsize_t *dims, } /* end if */ else space->extent.max = NULL; - } + } /* end else */ /* Selection related cleanup */ /* Set offset to zeros */ - for(u=0; u<space->extent.rank; u++) - space->select.offset[u]=0; + for(u = 0; u < space->extent.rank; u++) + space->select.offset[u] = 0; /* If the selection is 'all', update the number of elements selected */ - if(H5S_GET_SELECT_TYPE(space)==H5S_SEL_ALL) - if(H5S_select_all(space, FALSE)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection"); + if(H5S_GET_SELECT_TYPE(space) == H5S_SEL_ALL) + if(H5S_select_all(space, FALSE) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection") done: - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S_set_extent_simple() */ #ifdef H5S_DEBUG @@ -1449,7 +1460,7 @@ H5S_find (const H5S_t *mem_space, const H5S_t *file_space) * The path wasn't found. Create a new path. */ if (NULL==(path = H5MM_calloc(sizeof(*path)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for data space conversion path"); + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for data space conversion path") /* Initialize file & memory conversion functions */ path->ftype = H5S_GET_SELECT_TYPE(file_space); @@ -1463,7 +1474,7 @@ H5S_find (const H5S_t *mem_space, const H5S_t *file_space) H5S_iostats_t **p = H5MM_realloc(H5S_iostats_g, n*sizeof(H5S_iostats_g[0])); if (NULL==p) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for data space conversion path table"); + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for data space conversion path table") H5S_aiostats_g = n; H5S_iostats_g = p; } /* end if */ @@ -1587,34 +1598,34 @@ H5Screate_simple(int rank, const hsize_t dims[/*rank*/], /* Check arguments */ if (rank<0) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "dimensionality cannot be negative"); + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dimensionality cannot be negative") if (rank>H5S_MAX_RANK) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dimensionality is too large"); + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dimensionality is too large") if (!dims && dims!=0) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "no dimensions specified"); + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no dimensions specified") /* Check whether the current dimensions are valid */ for (i=0; i<rank; i++) { if (H5S_UNLIMITED==dims[i]) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "current dimension must have a specific size, not H5S_UNLIMITED"); + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "current dimension must have a specific size, not H5S_UNLIMITED") if (maxdims) { if (H5S_UNLIMITED!=maxdims[i] && maxdims[i]<dims[i]) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "maxdims is smaller than dims"); + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "maxdims is smaller than dims") if (H5S_UNLIMITED!=maxdims[i] && dims[i]==0) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "zero sized dimension for non-unlimited dimension"); + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "zero sized dimension for non-unlimited dimension") } else { if (dims[i]==0) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "zero sized dimension for non-unlimited dimension"); + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "zero sized dimension for non-unlimited dimension") } } /* Create the space and set the extent */ if(NULL==(space=H5S_create_simple((unsigned)rank,dims,maxdims))) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace"); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace") /* Atomize */ if ((ret_value=H5I_register (H5I_DATASPACE, space))<0) - HGOTO_ERROR (H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace ID"); + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace ID") done: if (ret_value<0) { @@ -1658,9 +1669,9 @@ H5S_create_simple(unsigned rank, const hsize_t dims[/*rank*/], /* Create the space and set the extent */ if(NULL==(ret_value=H5S_create(H5S_SIMPLE))) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTCREATE, NULL, "can't create simple dataspace"); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, NULL, "can't create simple dataspace") if(H5S_set_extent_simple(ret_value,rank,dims,maxdims)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, NULL, "can't set dimensions"); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, NULL, "can't set dimensions") done: FUNC_LEAVE_NOAPI(ret_value); @@ -1696,10 +1707,10 @@ H5Sencode(hid_t obj_id, void *buf, size_t *nalloc) /* Check argument and retrieve object */ if (NULL==(dspace=(H5S_t *)H5I_object_verify(obj_id, H5I_DATASPACE))) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") if(H5S_encode(dspace, (unsigned char *)buf, nalloc)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "can't encode datatype"); + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "can't encode datatype") done: FUNC_LEAVE_API(ret_value); @@ -1731,7 +1742,7 @@ H5S_encode(H5S_t *obj, unsigned char *buf, size_t *nalloc) H5F_t *f = NULL; /* Fake file structure*/ herr_t ret_value = SUCCEED; - FUNC_ENTER_NOAPI(H5S_encode, FAIL) + FUNC_ENTER_NOAPI_NOINIT(H5S_encode) /* Allocate "fake" file structure */ if(NULL == (f = H5F_fake_alloc((size_t)0))) @@ -1811,7 +1822,7 @@ H5Sdecode(const void *buf) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "empty buffer") if((ds = H5S_decode((const unsigned char *)buf)) == NULL) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDECODE, FAIL, "can't decode object"); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDECODE, FAIL, "can't decode object") /* Register the type and return the ID */ if((ret_value = H5I_register(H5I_DATASPACE, ds)) < 0) @@ -1848,15 +1859,15 @@ H5S_decode(const unsigned char *buf) size_t sizeof_size; /* 'Size of sizes' for file */ H5S_t *ret_value; - FUNC_ENTER_NOAPI(H5S_decode, NULL) + FUNC_ENTER_NOAPI_NOINIT(H5S_decode) /* Decode the type of the information */ if(*buf++ != H5O_SDSPACE_ID) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADMESG, NULL, "not an encoded dataspace"); + HGOTO_ERROR(H5E_DATASPACE, H5E_BADMESG, NULL, "not an encoded dataspace") /* Decode the version of the dataspace information */ if(*buf++ != H5S_ENCODE_VERSION) - HGOTO_ERROR(H5E_DATASPACE, H5E_VERSION, NULL, "unknown version of encoded dataspace"); + HGOTO_ERROR(H5E_DATASPACE, H5E_VERSION, NULL, "unknown version of encoded dataspace") /* Decode the "size of size" information */ sizeof_size = *buf++; @@ -1885,7 +1896,7 @@ H5S_decode(const unsigned char *buf) /* Initialize to "all" selection. Deserialization relies on valid existing selection. */ if(H5S_select_all(ds, 0) < 0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTSET, NULL, "unable to set all selection") + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, NULL, "unable to set all selection") /* Decode the select part of dataspace. I believe this part always exists. */ if(H5S_SELECT_DESERIALIZE(ds, buf) < 0) @@ -1970,7 +1981,7 @@ H5Sget_simple_extent_type(hid_t sid) /* Check arguments */ if (NULL == (space = (H5S_t *)H5I_object_verify(sid, H5I_DATASPACE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5S_NO_CLASS, "not a dataspace"); + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5S_NO_CLASS, "not a dataspace") ret_value=H5S_GET_EXTENT_TYPE(space); @@ -2004,11 +2015,11 @@ H5Sset_extent_none(hid_t space_id) /* Check args */ if (NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a data space"); + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a data space") /* Clear the previous extent from the dataspace */ if(H5S_extent_release(&space->extent)<0) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTDELETE, FAIL, "can't release previous dataspace"); + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTDELETE, FAIL, "can't release previous dataspace") space->extent.type=H5S_NO_CLASS; @@ -2044,16 +2055,16 @@ H5Soffset_simple(hid_t space_id, const hssize_t *offset) /* Check args */ if (NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a data space"); + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a data space") if (space->extent.rank==0 || (H5S_GET_EXTENT_TYPE(space)==H5S_SCALAR || H5S_GET_EXTENT_TYPE(space)==H5S_NULL)) - HGOTO_ERROR(H5E_ATOM, H5E_UNSUPPORTED, FAIL, "can't set offset on scalar or null dataspace"); + HGOTO_ERROR(H5E_ATOM, H5E_UNSUPPORTED, FAIL, "can't set offset on scalar or null dataspace") if (offset == NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no offset specified"); + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no offset specified") /* Set the selection offset */ if(H5S_select_offset(space,offset)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't set offset"); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't set offset") done: FUNC_LEAVE_API(ret_value); @@ -2091,7 +2102,7 @@ H5S_set_extent( H5S_t *space, const hsize_t *size ) for ( u = 0; u < space->extent.rank; u++ ) { if ( space->extent.max && H5S_UNLIMITED != space->extent.max[u] && space->extent.max[u]!=size[u] ) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL,"dimension cannot be modified"); + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,"dimension cannot be modified") ret_value++; } /* end for */ @@ -2174,7 +2185,7 @@ H5S_set_extent_real( H5S_t *space, const hsize_t *size ) /* If the selection is 'all', update the number of elements selected */ if(H5S_GET_SELECT_TYPE(space)==H5S_SEL_ALL) if(H5S_select_all(space, FALSE)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection"); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection") done: FUNC_LEAVE_NOAPI(ret_value); @@ -2237,7 +2248,7 @@ H5S_extent_equal(const H5S_t *ds1, const H5S_t *ds2) unsigned u; /* Local index variable */ htri_t ret_value = TRUE; /* Return value */ - FUNC_ENTER_NOAPI(H5S_extent_equal, FAIL) + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_extent_equal) /* Check args */ HDassert(ds1); @@ -2255,20 +2266,18 @@ H5S_extent_equal(const H5S_t *ds1, const H5S_t *ds2) if(ds1->extent.rank > 0) { HDassert(ds1->extent.size); HDassert(ds2->extent.size); - for(u = 0; u < ds1->extent.rank; u++) { + for(u = 0; u < ds1->extent.rank; u++) if(ds1->extent.size[u] != ds2->extent.size[u]) HGOTO_DONE(FALSE) - } /* end for */ } /* end if */ /* Make certain the dataspaces' maximum dimensions are the same size */ if(ds1->extent.rank > 0) { /* Check for no maximum dimensions on dataspaces */ if(ds1->extent.max != NULL && ds2->extent.max != NULL) { - for(u = 0; u < ds1->extent.rank; u++) { + for(u = 0; u < ds1->extent.rank; u++) if(ds1->extent.max[u] != ds2->extent.max[u]) HGOTO_DONE(FALSE) - } /* end for */ } /* end if */ else if((ds1->extent.max == NULL && ds2->extent.max != NULL) || @@ -17,8 +17,9 @@ /* Module Setup */ /****************/ -#define H5SM_PACKAGE /*suppress error about including H5SMpkg */ #define H5F_PACKAGE /*suppress error about including H5Fpkg */ +#define H5O_PACKAGE /*suppress error about including H5Opkg */ +#define H5SM_PACKAGE /*suppress error about including H5SMpkg */ /***********/ /* Headers */ @@ -30,8 +31,10 @@ #include "H5FLprivate.h" /* Free Lists */ #include "H5MFprivate.h" /* File memory management */ #include "H5MMprivate.h" /* Memory management */ +#include "H5Opkg.h" /* Object Headers */ #include "H5SMpkg.h" /* Shared object header messages */ + /****************/ /* Local Macros */ /****************/ @@ -40,6 +43,14 @@ /******************/ /* Local Typedefs */ /******************/ +/* Udata struct for calls to H5SM_read_iter_op */ +typedef struct H5SM_read_udata_t { + H5F_t *file; /* File in which sharing is happening (in) */ + unsigned type_id; /* Type of the message (in) */ + size_t buf_size; /* Size of the encoded message (out) */ + void * encoding_buf; /* The encoded message (out) */ + H5O_msg_crt_idx_t idx; /* Creation index of this message */ +} H5SM_read_udata_t; /********************/ @@ -52,14 +63,21 @@ static herr_t H5SM_delete_index(H5F_t *f, H5SM_index_header_t *header, static haddr_t H5SM_create_list(H5F_t *f, H5SM_index_header_t *header, hid_t dxpl_id); static size_t H5SM_find_in_list(const H5SM_list_t *list, const H5SM_mesg_key_t *key, size_t *empty_pos); static herr_t H5SM_convert_list_to_btree(H5F_t * f, H5SM_index_header_t * header, - H5SM_list_t **_list, H5HF_t *fheap, hid_t dxpl_id); + H5SM_list_t **_list, H5HF_t *fheap, H5O_t *open_oh, hid_t dxpl_id); static herr_t H5SM_convert_btree_to_list(H5F_t * f, H5SM_index_header_t * header, hid_t dxpl_id); -static herr_t H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5SM_index_header_t *header, - unsigned type_id, void *mesg, unsigned *cache_flags_ptr); -static herr_t H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, - H5SM_index_header_t *header, unsigned type_id, const H5O_shared_t * mesg, - unsigned *cache_flags, void ** encoded_mesg); +static herr_t H5SM_incr_ref(void *record, void *_op_data, hbool_t *changed); +static herr_t H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, + H5SM_index_header_t *header, unsigned type_id, void *mesg, + unsigned *cache_flags_ptr); +static herr_t H5SM_decr_ref(void *record, void *op_data, hbool_t *changed); +static herr_t H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, + H5SM_index_header_t *header, const H5O_shared_t * mesg, + unsigned *cache_flags, void ** /*out*/ encoded_mesg); static herr_t H5SM_type_to_flag(unsigned type_id, unsigned *type_flag); +static herr_t H5SM_read_iter_op(const void *_mesg, unsigned idx, void *_udata); +static herr_t H5SM_read_mesg(H5F_t *f, const H5SM_sohm_t *mesg, H5HF_t *fheap, + H5O_t * open_oh, hid_t dxpl_id, size_t *encoding_size /*out*/, + void ** encoded_mesg /*out*/); /*********************/ @@ -249,9 +267,7 @@ H5SM_type_to_flag(unsigned type_id, unsigned *type_flag) case H5O_DTYPE_ID: *type_flag = H5O_MESG_DTYPE_FLAG; break; -#ifdef NOT_YET case H5O_FILL_ID: -#endif /* NOT_YET */ case H5O_FILL_NEW_ID: *type_flag = H5O_MESG_FILL_FLAG; break; @@ -439,26 +455,25 @@ H5SM_create_index(H5F_t *f, H5SM_index_header_t *header, hid_t dxpl_id) HDassert(header->btree_min <= header->list_max + 1); /* In most cases, the index starts as a list */ - if(header->list_max > 0) - { + if(header->list_max > 0) { header->index_type = H5SM_LIST; if((list_addr = H5SM_create_list(f, header, dxpl_id)) == HADDR_UNDEF) HGOTO_ERROR(H5E_SOHM, H5E_CANTCREATE, FAIL, "list creation failed for SOHM index") header->index_addr = list_addr; - } - else /* index is a B-tree */ - { + } /* end if */ + /* index is a B-tree */ + else { header->index_type = H5SM_BTREE; if(H5B2_create(f, dxpl_id, H5SM_INDEX, (size_t)H5SM_B2_NODE_SIZE, (size_t)H5SM_SOHM_ENTRY_SIZE(f), H5SM_B2_SPLIT_PERCENT, - H5SM_B2_MERGE_PERCENT, &tree_addr) <0) + H5SM_B2_MERGE_PERCENT, &tree_addr) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTCREATE, FAIL, "B-tree creation failed for SOHM index") header->index_addr = tree_addr; - } + } /* end else */ /* Create a heap to hold the shared messages that the list or B-tree will index */ HDmemset(&fheap_cparam, 0, sizeof(fheap_cparam)); @@ -473,7 +488,7 @@ H5SM_create_index(H5F_t *f, H5SM_index_header_t *header, hid_t dxpl_id) if(NULL == (fheap = H5HF_create(f, dxpl_id, &fheap_cparam))) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to create fractal heap") - if(H5HF_get_heap_addr(fheap, &(header->heap_addr )) < 0) + if(H5HF_get_heap_addr(fheap, &(header->heap_addr)) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTGETSIZE, FAIL, "can't get fractal heap address") #ifndef NDEBUG @@ -533,7 +548,8 @@ H5SM_delete_index(H5F_t *f, H5SM_index_header_t *header, hid_t dxpl_id, hbool_t list_size = H5SM_LIST_SIZE(f, header->list_max); if(H5MF_xfree(f, H5FD_MEM_SOHM_INDEX, dxpl_id, header->index_addr, list_size) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to free shared message list") - } else { + } /* end if */ + else { HDassert(header->index_type == H5SM_BTREE); /* Delete from the B-tree. */ @@ -543,21 +559,22 @@ H5SM_delete_index(H5F_t *f, H5SM_index_header_t *header, hid_t dxpl_id, hbool_t /* Revert to list unless B-trees can have zero records */ if(header->btree_min > 0) header->index_type = H5SM_LIST; - } + } /* end else */ /* Free the index's heap if requested. */ if(delete_heap == TRUE) { if(H5HF_delete(f, dxpl_id, header->heap_addr) < 0) HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "unable to delete fractal heap") - } + header->heap_addr = HADDR_UNDEF; + } /* end if */ + /* Reset index info */ header->index_addr = HADDR_UNDEF; - header->heap_addr = HADDR_UNDEF; header->num_messages = 0; done: FUNC_LEAVE_NOAPI(ret_value) -}/* end H5SM_delete_index */ +} /* end H5SM_delete_index */ /*------------------------------------------------------------------------- @@ -576,7 +593,7 @@ done: *------------------------------------------------------------------------- */ static haddr_t -H5SM_create_list(H5F_t *f, H5SM_index_header_t * header, hid_t dxpl_id) +H5SM_create_list(H5F_t *f, H5SM_index_header_t *header, hid_t dxpl_id) { H5SM_list_t *list = NULL; /* List of messages */ hsize_t x; /* Counter variable */ @@ -600,11 +617,10 @@ H5SM_create_list(H5F_t *f, H5SM_index_header_t * header, hid_t dxpl_id) /* Initialize messages in list */ HDmemset(list->messages, 0, sizeof(H5SM_sohm_t) * num_entries); + for(x=0; x<num_entries; x++) + list->messages[x].location = H5SM_NO_LOC; - for(x=0; x<num_entries; x++) { - list->messages[x].ref_count=0; - } - + /* Point list at header passed in */ list->header = header; /* Allocate space for the list on disk */ @@ -620,17 +636,15 @@ H5SM_create_list(H5F_t *f, H5SM_index_header_t * header, hid_t dxpl_id) ret_value = addr; done: - if(ret_value == HADDR_UNDEF) - { - if(list != NULL) - { + if(ret_value == HADDR_UNDEF) { + if(list != NULL) { if(list->messages != NULL) H5FL_ARR_FREE(H5SM_sohm_t, list->messages); H5FL_FREE(H5SM_list_t, list); - } + } /* end if */ if(addr != HADDR_UNDEF) H5MF_xfree(f, H5FD_MEM_SOHM_INDEX, dxpl_id, addr, size); - } + } /* end if */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5SM_create_list */ @@ -657,49 +671,62 @@ done: * *------------------------------------------------------------------------- */ -herr_t -H5SM_convert_list_to_btree(H5F_t * f, H5SM_index_header_t * header, - H5SM_list_t **_list, H5HF_t *fheap, hid_t dxpl_id) +static herr_t +H5SM_convert_list_to_btree(H5F_t *f, H5SM_index_header_t *header, + H5SM_list_t **_list, H5HF_t *fheap, H5O_t *open_oh, hid_t dxpl_id) { - H5SM_index_header_t temp_header; - H5SM_list_t *list; - H5SM_mesg_key_t key; - haddr_t tree_addr; + H5SM_list_t *list; /* Pointer to the existing message list */ + H5SM_mesg_key_t key; /* Key for inserting records in v2 B-tree */ + haddr_t tree_addr; /* New v2 B-tree's address */ + size_t num_messages; /* Number of messages being tracked */ size_t x; + void * encoding_buf = NULL; herr_t ret_value = SUCCEED; - FUNC_ENTER_NOAPI(H5SM_convert_list_to_btree, FAIL) + FUNC_ENTER_NOAPI_NOINIT(H5SM_convert_list_to_btree) HDassert(_list && *_list); HDassert(header); + /* Get pointer to list of messages to convert */ list = *_list; - /* Copy the old index header */ - HDmemcpy(&temp_header, header, sizeof(H5SM_index_header_t)); + /* Create the new v2 B-tree for tracking the messages */ if(H5B2_create(f, dxpl_id, H5SM_INDEX, (size_t)H5SM_B2_NODE_SIZE, (size_t)H5SM_SOHM_ENTRY_SIZE(f), H5SM_B2_SPLIT_PERCENT, - H5SM_B2_MERGE_PERCENT, &tree_addr) <0) + H5SM_B2_MERGE_PERCENT, &tree_addr) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTCREATE, FAIL, "B-tree creation failed for SOHM index") - /* Insert each record into the new B-tree */ - for(x = 0; x < header->list_max; x++) - { - /* Set up key values that all messages will use. Since these messages - * are in the heap, they have a heap ID and no encoding. - */ - key.encoding = NULL; - key.encoding_size = 0; - key.fheap = fheap; + /* Set up key values that all messages will use. Since these messages + * are in the heap, they have a heap ID and no encoding or type_id. + */ + key.file = f; + key.dxpl_id = dxpl_id; + key.fheap = fheap; + key.encoding_size = 0; + key.encoding = NULL; - if(list->messages[x].ref_count > 0) - { + /* Insert each record into the new B-tree */ + for(x = 0; x < header->list_max; x++) { + if(list->messages[x].location != H5SM_NO_LOC) { + /* Copy message into key */ key.message = list->messages[x]; + /* Get the encoded message */ + if(H5SM_read_mesg(f, &(key.message), fheap, open_oh, dxpl_id, &key.encoding_size, &encoding_buf) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTLOAD, FAIL, "Couldn't read SOHM message in list") + + key.encoding = encoding_buf; + + /* Insert the message into the B-tree */ if(H5B2_insert(f, dxpl_id, H5SM_INDEX, tree_addr, &key) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "couldn't add SOHM to B-tree") - } - } + + /* Free buffer from H5SM_read_mesg */ + if(encoding_buf) + encoding_buf = H5MM_xfree(encoding_buf); + } /* end if */ + } /* end for */ /* Unprotect list in cache and release heap */ if(H5AC_unprotect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, list, H5AC__DELETED_FLAG) < 0) @@ -709,16 +736,23 @@ H5SM_convert_list_to_btree(H5F_t * f, H5SM_index_header_t * header, /* Delete the old list index (but not its heap, which the new index is * still using!) */ - HDmemcpy(&temp_header, header, sizeof(H5SM_index_header_t)); - if(H5SM_delete_index(f, &temp_header, dxpl_id, FALSE) < 0) + num_messages = header->num_messages; /* preserve this across the index deletion */ + if(H5SM_delete_index(f, header, dxpl_id, FALSE) < 0) HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "can't free list index") + /* Set/restore header info */ header->index_addr = tree_addr; header->index_type = H5SM_BTREE; + header->num_messages = num_messages; done: + /* Free the buffer, if it hasn't already been freed (because of error) */ + if(encoding_buf) + encoding_buf = H5MM_xfree(encoding_buf); + FUNC_LEAVE_NOAPI(ret_value) -} +} /* H5SM_convert_list_to_btree() */ + /*------------------------------------------------------------------------- * Function: H5SM_convert_btree_to_list @@ -892,14 +926,47 @@ done: /*------------------------------------------------------------------------- * Function: H5SM_try_share * - * Purpose: Attempts to share an object header message. If the message - * should be shared (if sharing has been enabled and this - * message qualified), turns the message into a shared message. - * - * If not, returns FALSE and does nothing. + * Purpose: Attempts to share an object header message. + * + * MESG_LOC is an H5O_mesg_loc_t struct that gives the message's + * location in an object header (address and index). This + * function sets the type_id in MESG_LOC. + * If MESG_LOC is not NULL, this message will be "unique but + * shareable" and will be entered in the index but not actually + * shared. If it is NULL, this message will be fully shared if + * it is shareable at all. + * + * OPEN_OH is the object header that is currently open and + * protected. If NULL, the SM module will protect any object + * header it needs (which can cause an error if that OH is + * already protected!). + * + * MESG_FLAGS will have the H5O_MSG_FLAG_SHAREABLE or + * H5O_MSG_FLAG_SHARED flag set if one is appropriate. This is + * the only way to tell the difference between a message that + * has just been fully shared and a message that is only + * "shareable" and is still in the object header, so it cannot + * be NULL if MESG_LOC is not NULL. If MESG_LOC is NULL, then + * the message won't be "unique but shareable" and MESG_FLAGS + * can be NULL as well. + * + * If the message should be shared (if sharing has been + * enabled and this message qualifies), this function turns the + * message into a shared message, sets the H5O_MSG_FLAG_SHARED + * flag in mesg_flags, and returns TRUE. + * + * If the message isn't shared, returns FALSE. If the message + * isn't shared but was entered in the shared message index, + * the H5O_MSG_FLAG_SHAREABLE flag will be set in mesg_flags + * and returns TRUE. * * If this message was already shared, increments its reference - * count and leaves it otherwise unchanged. + * count, and leaves it otherwise unchanged, returning TRUE and + * setting the H5O_MSG_FLAG_SHARED flag in mesg_flags. + * + * If mesg_flags is NULL, the calling function should just look + * at the return value to determine if the message was shared + * or not. Such messages should never be "unique but shareable." * * Return: TRUE if message is now a SOHM * FALSE if this message is not a SOHM @@ -911,7 +978,8 @@ done: *------------------------------------------------------------------------- */ htri_t -H5SM_try_share(H5F_t *f, hid_t dxpl_id, unsigned type_id, void *mesg) +H5SM_try_share(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned type_id, + void *mesg, unsigned *mesg_flags) { H5SM_master_table_t *table = NULL; unsigned cache_flags = H5AC__NO_FLAGS_SET; @@ -922,6 +990,8 @@ H5SM_try_share(H5F_t *f, hid_t dxpl_id, unsigned type_id, void *mesg) FUNC_ENTER_NOAPI(H5SM_try_share, FAIL) /* "trivial" sharing checks */ + if(mesg_flags && (*mesg_flags & H5O_MSG_FLAG_DONTSHARE)) + HGOTO_DONE(FALSE) if((tri_ret = H5SM_can_share_common(f, type_id, mesg)) < 0) HGOTO_ERROR(H5E_SOHM, H5E_BADTYPE, FAIL, "'trivial' sharing checks returned error") if(tri_ret == FALSE) @@ -937,18 +1007,32 @@ H5SM_try_share(H5F_t *f, hid_t dxpl_id, unsigned type_id, void *mesg) if(tri_ret == FALSE) HGOTO_DONE(FALSE) + /* At this point, the message will be shared. */ + /* If the index hasn't been allocated yet, create it */ - if(table->indexes[index_num].index_addr == HADDR_UNDEF) - { + if(table->indexes[index_num].index_addr == HADDR_UNDEF) { if(H5SM_create_index(f, &(table->indexes[index_num]), dxpl_id) < 0) HGOTO_ERROR(H5E_SOHM, H5E_CANTINIT, FAIL, "unable to create SOHM index") cache_flags |= H5AC__DIRTIED_FLAG; } /* end if */ - /* Write the message as a shared message */ - if(H5SM_write_mesg(f, dxpl_id, &(table->indexes[index_num]), type_id, mesg, &cache_flags) < 0) + /* Write the message as a shared message. This may or may not cause the + * message to become shared (if it is unique, it will not be shared). + */ + if(H5SM_write_mesg(f, dxpl_id, open_oh, &(table->indexes[index_num]), + type_id, mesg, &cache_flags) < 0) HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "can't write shared message") + /* Set flags if this message was "written" without error; it is now + * either fully shared or "shareable". + */ + if(mesg_flags) { + if(((H5O_shared_t *)mesg)->type == H5O_SHARE_TYPE_HERE) + *mesg_flags |= H5O_MSG_FLAG_SHAREABLE; + else + *mesg_flags |= H5O_MSG_FLAG_SHARED; + } /* end if */ + done: /* Release the master SOHM table */ if(table && H5AC_unprotect(f, dxpl_id, H5AC_SOHM_TABLE, f->shared->sohm_addr, table, cache_flags) < 0) @@ -959,18 +1043,83 @@ done: /*------------------------------------------------------------------------- + * Function: H5SM_incr_ref + * + * Purpose: Increment the reference count for a SOHM message and return + * the message's heap ID. + * + * The message pointer is actually returned via op_data, which + * should be a pointer to a H5SM_fheap_id_t. + * + * Return: Non-negative on success + * Negative on failure + * + * Programmer: James Laird + * Monday, November 6, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_incr_ref(void *record, void *_op_data, hbool_t *changed) +{ + H5SM_sohm_t *message = (H5SM_sohm_t *) record; + H5SM_incr_ref_opdata *op_data = (H5SM_incr_ref_opdata *) _op_data; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT(H5SM_incr_ref) + + HDassert(record); + HDassert(op_data); + HDassert(changed); + + /* If the message was previously shared in an object header, share + * it in the heap now. + */ + if(message->location == H5SM_IN_OH) { + HDassert(op_data->key && op_data->key->fheap); + + /* Put the message in the heap and record its new heap ID */ + if(H5HF_insert(op_data->key->fheap, op_data->dxpl_id, op_data->key->encoding_size, op_data->key->encoding, &message->u.heap_loc.fheap_id) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "unable to insert message into fractal heap") + + message->location = H5SM_IN_HEAP; + message->u.heap_loc.ref_count = 2; + } /* end if */ + else { + HDassert(message->location == H5SM_IN_HEAP); + /* If it's already in the heap, just increment the ref count */ + ++message->u.heap_loc.ref_count; + } /* end else */ + + /* If we got here, the message has changed */ + *changed = TRUE; + + /* Check for retrieving the heap ID */ + if(op_data) + op_data->fheap_id = message->u.heap_loc.fheap_id; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5SM_incr_ref() */ + + +/*------------------------------------------------------------------------- * Function: H5SM_write_mesg * - * Purpose: Writes a message to an existing index and change the message - * to reflect that it's now shared. + * Purpose: Adds a shareable message to an index. If this is the first + * such message and we have an object header location for this + * message, we record it in the index but don't modify the + * message passed in. * - * If the message is already in the index, increment its - * reference count instead of writing it again and make the - * user's copy point to the copy we wrote before. + * If the message is already in the index or we don't have an + * object header location for it, it is shared in the heap + * and this function sets its sharing struct to reflect this. * * The index could be a list or a B-tree. * - * Return: Non-negative on success/Negative on failure + * Return: TRUE if message is now shared + * FALSE if message is in index but is not shared + * Negative on failure * * Programmer: James Laird * Tuesday, May 2, 2006 @@ -978,8 +1127,9 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5SM_index_header_t *header, - unsigned type_id, void *mesg, unsigned *cache_flags_ptr) +H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, + H5SM_index_header_t *header, unsigned type_id, void *mesg, + unsigned *cache_flags_ptr) { H5SM_list_t *list = NULL; /* List index */ H5SM_mesg_key_t key; /* Key used to search the index */ @@ -993,14 +1143,15 @@ H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5SM_index_header_t *header, FUNC_ENTER_NOAPI_NOINIT(H5SM_write_mesg) - HDassert(cache_flags_ptr); + /* Sanity check */ HDassert(header); HDassert(header->index_type != H5SM_BADTYPE); + HDassert(cache_flags_ptr); /* Encode the message to be written */ - if((buf_size = H5O_msg_raw_size(f, type_id, TRUE, mesg)) <= 0) + if((buf_size = H5O_msg_raw_size(f, type_id, TRUE, mesg)) == 0) HGOTO_ERROR(H5E_OHDR, H5E_BADSIZE, FAIL, "can't find message size") - if(NULL == (encoding_buf = H5MM_calloc(buf_size))) + if(NULL == (encoding_buf = H5MM_malloc(buf_size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate buffer for encoding") if(H5O_msg_encode(f, type_id, TRUE, (unsigned char *)encoding_buf, mesg) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "can't encode message to be shared") @@ -1010,20 +1161,19 @@ H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5SM_index_header_t *header, HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap") /* Set up a key for the message to be written */ - key.message.fheap_id = 0; /* Message doesn't yet have a heap ID */ - key.message.hash = H5_checksum_lookup3(encoding_buf, buf_size, type_id); - key.message.ref_count = 1; - + key.dxpl_id = dxpl_id; + key.file = f; + key.fheap = fheap; key.encoding = encoding_buf; key.encoding_size = buf_size; - key.fheap = fheap; + key.message.hash = H5_checksum_lookup3(encoding_buf, buf_size, type_id); + key.message.location = H5SM_NO_LOC; /* Assume the message is already in the index and try to increment its * reference count. If this fails, the message isn't in the index after * all and we'll need to add it. */ - if(header->index_type == H5SM_LIST) - { + if(header->index_type == H5SM_LIST) { size_t list_pos; /* Position in a list index */ /* The index is a list; get it from the cache */ @@ -1035,76 +1185,134 @@ H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5SM_index_header_t *header, * later. */ list_pos = H5SM_find_in_list(list, &key, &empty_pos); - if(list_pos != UFAIL) - { - /* The message was in the index. Increment its reference count. */ - ++(list->messages[list_pos].ref_count); + if(list_pos != UFAIL) { + /* If the message was previously shared in an object header, share + * it in the heap now. + */ + if(list->messages[list_pos].location == H5SM_IN_OH) { + /* Put the message in the heap and record its new heap ID */ + if(H5HF_insert(fheap, dxpl_id, key.encoding_size, key.encoding, &shared.u.heap_id) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "unable to insert message into fractal heap") + + list->messages[list_pos].location = H5SM_IN_HEAP; + list->messages[list_pos].u.heap_loc.fheap_id = shared.u.heap_id; + list->messages[list_pos].u.heap_loc.ref_count = 2; + } /* end if */ + else { + /* If the message was already in the heap, increase its ref count */ + HDassert(list->messages[list_pos].location == H5SM_IN_HEAP); + ++(list->messages[list_pos].u.heap_loc.ref_count); + } /* end else */ /* Set up the shared location to point to the shared location */ - shared.u.heap_id = list->messages[list_pos].fheap_id; + shared.u.heap_id = list->messages[list_pos].u.heap_loc.fheap_id; found = TRUE; } /* end if */ } /* end if */ - else /* Index is a B-tree */ - { + /* Index is a B-tree */ + else { + H5SM_incr_ref_opdata op_data; + HDassert(header->index_type == H5SM_BTREE); + op_data.key = &key; + op_data.dxpl_id = dxpl_id; + /* If this returns failure, it means that the message wasn't found. */ - /* If it succeeds, the heap_id in the shared struct will be set */ - if(H5B2_modify(f, dxpl_id, H5SM_INDEX, header->index_addr, &key, H5SM_incr_ref, &shared.u.heap_id) >= 0) - found = TRUE; + /* If it succeeds, set the heap_id in the shared struct. It will + * return a heap ID, since a message with a reference count greater + * than 1 is always shared in the heap. + */ + if(H5B2_modify(f, dxpl_id, H5SM_INDEX, header->index_addr, &key, H5SM_incr_ref, &op_data) >= 0) { + shared.u.heap_id = op_data.fheap_id; + found = TRUE; + } /* end if */ } /* end else */ - /* Set up a shared message so that we can make this message shared once it's - * written to the index. This message is always stored to the heap, not to - * an object header. - */ - shared.flags = H5O_SHARED_IN_HEAP_FLAG; + if(found) + /* If the message was found, it's shared in the heap (now). Set up a + * shared message so we can mark it as shared. + */ + shared.type = H5O_SHARE_TYPE_SOHM; + else { + htri_t share_in_ohdr; /* Whether the new message can be shared in another object's header */ - /* If the message isn't in the list, add it */ - if(!found) - { - /* Put the message in the heap and record its new heap ID */ - if(H5HF_insert(fheap, dxpl_id, key.encoding_size, key.encoding, &shared.u.heap_id) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "unable to insert message into fractal heap") + /* Add the message to the index */ + + /* Check if the message can be shared in another object's header */ + if((share_in_ohdr = H5O_msg_can_share_in_ohdr(type_id)) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_BADTYPE, FAIL, "'share in ohdr' check returned error") - key.message.fheap_id = shared.u.heap_id; + /* If this message can be shared in an object header location, it is + * "shareable" but not shared in the heap. Insert it in the index + * but don't modify the original message. + * + * If it can't be shared in an object header location or there's no + * object header location available, insert it in the heap. + */ + if(share_in_ohdr && open_oh) { + /* Set up shared component info */ + shared.type = H5O_SHARE_TYPE_HERE; + /* Retrieve any creation index from the native message */ + if(H5O_msg_get_crt_index(type_id, mesg, &shared.u.loc.index) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, FAIL, "unable to retrieve creation index") + shared.u.loc.oh_addr = H5O_OH_GET_ADDR(open_oh); + + /* Copy shared component info into key for inserting into index */ + key.message.location = H5SM_IN_OH; + key.message.u.mesg_loc = shared.u.loc; + } /* end if */ + else { + /* Put the message in the heap and record its new heap ID */ + if(H5HF_insert(fheap, dxpl_id, key.encoding_size, key.encoding, &shared.u.heap_id) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "unable to insert message into fractal heap") + + /* Set up shared component info */ + /* (heap ID set above) */ + shared.type = H5O_SHARE_TYPE_SOHM; + + key.message.location = H5SM_IN_HEAP; + key.message.u.heap_loc.fheap_id = shared.u.heap_id; + key.message.u.heap_loc.ref_count = 1; + } /* end else */ + + /* Set common information */ + key.message.msg_type_id = type_id; /* Check whether the list has grown enough that it needs to become a B-tree */ if(header->index_type == H5SM_LIST && header->num_messages >= header->list_max) - { - if(H5SM_convert_list_to_btree(f, header, &list, fheap, dxpl_id) < 0) + if(H5SM_convert_list_to_btree(f, header, &list, fheap, open_oh, dxpl_id) < 0) HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "unable to convert list to B-tree") - } - /* Insert the new message into the SOHM index */ - if(header->index_type == H5SM_LIST) - { + if(header->index_type == H5SM_LIST) { /* Index is a list. Find an empty spot if we haven't already */ - if(empty_pos == UFAIL) { + if(empty_pos == UFAIL) if((H5SM_find_in_list(list, NULL, &empty_pos) == UFAIL) || empty_pos == UFAIL) HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "unable to find empty entry in list") - } /* Insert message into list */ - HDassert(list->messages[empty_pos].ref_count == 0); + HDassert(list->messages[empty_pos].location == H5SM_NO_LOC); + HDassert(key.message.location != H5SM_NO_LOC); list->messages[empty_pos] = key.message; - HDassert(list->messages[empty_pos].ref_count > 0); - } - else /* Index is a B-tree */ - { + } /* end if */ + /* Index is a B-tree */ + else { HDassert(header->index_type == H5SM_BTREE); if(H5B2_insert(f, dxpl_id, H5SM_INDEX, header->index_addr, &key) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "couldn't add SOHM to B-tree") - } + } /* end else */ ++(header->num_messages); (*cache_flags_ptr) |= H5AC__DIRTIED_FLAG; - } + } /* end else */ - /* Change the original message passed in to reflect that it's now shared */ + /* Set the file pointer & message type for the shared component */ + shared.file = f; + shared.msg_type_id = type_id; + + /* Update the original message's shared component */ if(H5O_msg_set_share(type_id, &shared, mesg) < 0) HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "unable to set sharing information") @@ -1125,12 +1333,16 @@ done: /*------------------------------------------------------------------------- - * Function: H5SM_try_delete + * Function: H5SM_delete * * Purpose: Given an object header message that is being deleted, * checks if it is a SOHM. If so, decrements its reference * count. * + * If an object header is currently protected, it needs to + * be passed in as open_oh so the SM code doesn't try to + * re-protect it. + * * Return: Non-negative on success/Negative on failure * * Programmer: James Laird @@ -1139,26 +1351,24 @@ done: *------------------------------------------------------------------------- */ herr_t -H5SM_try_delete(H5F_t *f, hid_t dxpl_id, unsigned type_id, - const H5O_shared_t *sh_mesg) +H5SM_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, H5O_shared_t *sh_mesg) { H5SM_master_table_t *table = NULL; unsigned cache_flags = H5AC__NO_FLAGS_SET; ssize_t index_num; void *mesg_buf = NULL; void *native_mesg = NULL; + unsigned type_id; /* Message type ID to operate on */ herr_t ret_value = SUCCEED; - FUNC_ENTER_NOAPI(H5SM_try_delete, FAIL) + FUNC_ENTER_NOAPI(H5SM_delete, FAIL) HDassert(f); + HDassert(f->shared->sohm_addr != HADDR_UNDEF); HDassert(sh_mesg); - /* Make sure SHARED_IN_HEAP flag is set; if not, there's no message to delete */ - if(0 == (sh_mesg->flags & H5O_SHARED_IN_HEAP_FLAG)) - HGOTO_DONE(SUCCEED); - - HDassert(f->shared->sohm_addr != HADDR_UNDEF); + /* Get message type */ + type_id = sh_mesg->msg_type_id; /* Look up the master SOHM table */ if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, f->shared->sohm_addr, NULL, NULL, H5AC_WRITE))) @@ -1172,7 +1382,7 @@ H5SM_try_delete(H5F_t *f, hid_t dxpl_id, unsigned type_id, * zero and any file space it uses needs to be freed. mesg_buf holds the * serialized form of the message. */ - if(H5SM_delete_from_index(f, dxpl_id, &(table->indexes[index_num]), type_id, sh_mesg, &cache_flags, &mesg_buf) < 0) + if(H5SM_delete_from_index(f, dxpl_id, open_oh, &(table->indexes[index_num]), sh_mesg, &cache_flags, &mesg_buf) < 0) HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "unable to delete mesage from SOHM index") /* Release the master SOHM table */ @@ -1188,7 +1398,7 @@ H5SM_try_delete(H5F_t *f, hid_t dxpl_id, unsigned type_id, if(NULL == (native_mesg = H5O_msg_decode(f, dxpl_id, type_id, (const unsigned char *)mesg_buf))) HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "can't decode shared message.") - if(H5O_msg_delete(f, dxpl_id, type_id, native_mesg) < 0) + if(H5O_msg_delete(f, dxpl_id, open_oh, type_id, native_mesg) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "can't delete shared message.") } /* end if */ @@ -1197,15 +1407,16 @@ done: if(table && H5AC_unprotect(f, dxpl_id, H5AC_SOHM_TABLE, f->shared->sohm_addr, table, cache_flags) < 0) HDONE_ERROR(H5E_CACHE, H5E_CANTRELEASE, FAIL, "unable to close SOHM master table") + /* Release any native message we decoded */ if(native_mesg) H5O_msg_free(type_id, native_mesg); - /* Free buf */ + /* Free encoding buf */ if(mesg_buf) mesg_buf = H5MM_xfree(mesg_buf); FUNC_LEAVE_NOAPI(ret_value) -} /* end H5SM_try_delete() */ +} /* end H5SM_delete() */ /*------------------------------------------------------------------------- @@ -1235,7 +1446,7 @@ H5SM_find_in_list(const H5SM_list_t *list, const H5SM_mesg_key_t *key, size_t *e size_t x; size_t ret_value; - FUNC_ENTER_NOAPI_NOINIT(H5SM_find_in_list) + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_find_in_list) HDassert(list); /* Both key and empty_pos can be NULL, but not both! */ @@ -1249,15 +1460,20 @@ H5SM_find_in_list(const H5SM_list_t *list, const H5SM_mesg_key_t *key, size_t *e * Also record the first empty position we find. */ for(x = 0; x < list->header->list_max; x++) { - if(key && (list->messages[x].ref_count > 0) && + if(key && (list->messages[x].location != H5SM_NO_LOC) && (0 == H5SM_message_compare(key, &(list->messages[x])))) HGOTO_DONE(x) - else if(empty_pos && *empty_pos == UFAIL && list->messages[x].ref_count == 0) + else if(empty_pos && list->messages[x].location == H5SM_NO_LOC) { + /* Note position */ *empty_pos = x; - } + + /* Found earlier position possible, don't check any more */ + empty_pos = NULL; + } /* end if */ + } /* end for */ /* If we reached this point, we didn't find the message */ - HGOTO_ERROR(H5E_SOHM, H5E_NOTFOUND, UFAIL, "message not in list") + ret_value = UFAIL; done: FUNC_LEAVE_NOAPI(ret_value) @@ -1293,6 +1509,52 @@ H5SM_get_hash_fh_cb(const void *obj, size_t obj_len, void *_udata) /*------------------------------------------------------------------------- + * Function: H5SM_decr_ref + * + * Purpose: Decrement the reference count for a SOHM message. Doesn't + * remove the record from the B-tree even if the refcount + * reaches zero. + * + * The new message is returned through op_data. If its + * reference count is zero, the calling function should + * remove this record from the B-tree. + * + * Return: Non-negative on success + * Negative on failure + * + * Programmer: James Laird + * Monday, November 6, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_decr_ref(void *record, void *op_data, hbool_t *changed) +{ + H5SM_sohm_t *message = (H5SM_sohm_t *) record; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_decr_ref) + + HDassert(record); + HDassert(op_data); + HDassert(changed); + + /* Adjust the message's reference count if it's stored in the heap. + * Messages stored in object headers always have refcounts of 1, + * so the calling function should know to just delete such a message + */ + if(message->location == H5SM_IN_HEAP) { + --message->u.heap_loc.ref_count; + *changed = TRUE; + } /* end if */ + + if(op_data) + *(H5SM_sohm_t *)op_data = *message; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5SM_decr_ref() */ + + +/*------------------------------------------------------------------------- * Function: H5SM_delete_from_index * * Purpose: Decrement the reference count for a particular message in this @@ -1310,55 +1572,125 @@ H5SM_get_hash_fh_cb(const void *obj, size_t obj_len, void *_udata) *------------------------------------------------------------------------- */ static herr_t -H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5SM_index_header_t *header, - unsigned type_id, const H5O_shared_t * mesg, unsigned *cache_flags, - void ** /*out*/ encoded_mesg) +H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, + H5SM_index_header_t *header, const H5O_shared_t *mesg, + unsigned *cache_flags, void ** /*out*/ encoded_mesg) { H5SM_list_t *list = NULL; H5SM_mesg_key_t key; - H5SM_sohm_t message; /* Deleted message returned from index */ - H5SM_sohm_t *message_ptr; /* Pointer to deleted message returned from index */ - size_t buf_size; /* Size of the encoded message */ + H5SM_sohm_t message; /* Deleted message returned from index */ + H5SM_sohm_t *message_ptr; /* Pointer to deleted message returned from index */ + H5HF_t *fheap = NULL; /* Fractal heap that contains the message */ + size_t buf_size; /* Size of the encoded message */ void * encoding_buf = NULL; /* Buffer for encoded message */ - H5HF_t *fheap = NULL; /* Fractal heap that contains the message */ + H5O_loc_t oloc; + H5O_t *oh = NULL; + unsigned type_id; /* Message type to operate on */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI_NOINIT(H5SM_delete_from_index) + /* Sanity check */ + HDassert(f); HDassert(header); HDassert(mesg); HDassert(cache_flags); - HDassert(mesg->flags & H5O_SHARED_IN_HEAP_FLAG); HDassert(*encoded_mesg == NULL); - - /* Open the heap that this message is in */ + + /* Get the message type for later */ + type_id = mesg->msg_type_id; + + /* Open the heap for this type of message. */ if(NULL == (fheap = H5HF_open(f, dxpl_id, header->heap_addr))) HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap") - /* Get the size of the message in the heap */ - if(H5HF_get_obj_len(fheap, dxpl_id, &(mesg->u.heap_id), &buf_size) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get message size from fractal heap.") + /* Get the message size and encoded message for the message to be deleted, + * either from its OH or from the heap. + */ + /* JAMES: could H5SM_read_mesg do this? We need to set up key->message + * anyway. + */ + if(mesg->type == H5O_SHARE_TYPE_HERE) { + /* Read message from object header */ + H5SM_read_udata_t udata; + const H5O_msg_class_t *type = NULL; /* Actual H5O class type for the ID */ + H5O_mesg_operator_t op; /* Wrapper for operator */ + + HDassert(open_oh); + type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */ + HDassert(type); + + /* If the message we are deleting is not in the object header passed in, + * we need to open & protect its object header + */ + if(mesg->u.loc.oh_addr != H5O_OH_GET_ADDR(open_oh)) { + /* Reset object location for operation */ + if(H5O_loc_reset(&oloc) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTRESET, FAIL, "unable to initialize location") + + /* Open the object in the file */ + oloc.file = f; + oloc.addr = mesg->u.loc.oh_addr; + if(H5O_open(&oloc) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to open object header") + + /* Load the object header from the cache */ + if(NULL == (oh = H5AC_protect(oloc.file, dxpl_id, H5AC_OHDR, oloc.addr, NULL, NULL, H5AC_WRITE))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header") + } /* end if */ + else + oh = open_oh; + + /* Set up user data for message iteration */ + udata.file = f; + udata.type_id = type_id; + udata.idx = mesg->u.loc.index; + udata.encoding_buf = NULL; + + /* Use the "real" iterate routine so it doesn't try to protect the OH */ + op.op_type = H5O_MESG_OP_APP; + op.u.app_op = H5SM_read_iter_op; + if((ret_value = H5O_msg_iterate_real(f, oh, type, &op, &udata, dxpl_id)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "unable to iterate over object header messages") + + /* Record the returned values */ + buf_size = udata.buf_size; + encoding_buf = udata.encoding_buf; + HDassert(buf_size > 0 && encoding_buf); + + key.message.location = H5SM_IN_OH; + key.message.msg_type_id = type_id; + key.message.u.mesg_loc = mesg->u.loc; + } /* end if */ + else { + /* Get the size of the message in the heap */ + if(H5HF_get_obj_len(fheap, dxpl_id, &(mesg->u.heap_id), &buf_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get message size from fractal heap.") - /* Allocate a buffer to hold the message */ - if(NULL == (encoding_buf = H5MM_malloc(buf_size))) - HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, FAIL, "memory allocation failed") + /* Allocate a buffer to hold the message */ + if(NULL == (encoding_buf = H5MM_malloc(buf_size))) + HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, FAIL, "memory allocation failed") - /* Read the message from the heap and get its hash */ - if(H5HF_read(fheap, dxpl_id, &(mesg->u.heap_id), encoding_buf) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "can't read message from fractal heap.") + /* Read the message from the heap */ + if(H5HF_read(fheap, dxpl_id, &(mesg->u.heap_id), encoding_buf) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "can't read message from fractal heap.") - key.message.hash = H5_checksum_lookup3(encoding_buf, buf_size, type_id); + key.message.location = H5SM_IN_HEAP; + key.message.msg_type_id = type_id; + key.message.u.heap_loc.ref_count = 0; /* Refcount isn't relevant here */ + key.message.u.heap_loc.fheap_id = mesg->u.heap_id; + } /* end else */ /* Set up key for message to be deleted. */ + key.file = f; + key.dxpl_id = dxpl_id; + key.fheap = fheap; key.encoding = encoding_buf; key.encoding_size = buf_size; - key.message.fheap_id = mesg->u.heap_id; - key.message.ref_count = 0; /* Refcount isn't relevant here */ - key.fheap = fheap; + key.message.hash = H5_checksum_lookup3(encoding_buf, buf_size, type_id); /* Try to find the message in the index */ - if(header->index_type == H5SM_LIST) - { + if(header->index_type == H5SM_LIST) { size_t list_pos; /* Position of the message in the list */ /* If the index is stored as a list, get it from the cache */ @@ -1369,13 +1701,14 @@ H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5SM_index_header_t *header, if((list_pos = H5SM_find_in_list(list, &key, NULL)) == UFAIL) HGOTO_ERROR(H5E_SOHM, H5E_NOTFOUND, FAIL, "message not in index") - --(list->messages[list_pos].ref_count); + if(list->messages[list_pos].location == H5SM_IN_HEAP) + --(list->messages[list_pos].u.heap_loc.ref_count); /* Point to the message */ message_ptr = &list->messages[list_pos]; } /* end if */ - else /* Index is a B-tree */ - { + else { + /* Index is a B-tree */ HDassert(header->index_type == H5SM_BTREE); /* If this returns failure, it means that the message wasn't found. @@ -1387,39 +1720,32 @@ H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5SM_index_header_t *header, message_ptr = &message; } /* end else */ - /* If the ref count is zero, delete the message from the index */ - if(message_ptr->ref_count <= 0) - { - size_t buf_size; + /* If the ref count is zero or this message was in an OH (which always + * has a ref count of 1) delete the message from the index + */ + if(message_ptr->location == H5SM_IN_OH || message_ptr->u.heap_loc.ref_count == 0) { + /* Save the location */ + H5SM_storage_loc_t old_loc = message_ptr->location; - /* Close the message being deleted, since it may need to adjust - * other reference counts (e.g., an attribute needs to free its - * shared datatype). - */ - /* Get the size of the message in the heap */ - if(H5HF_get_obj_len(fheap, dxpl_id, &(message_ptr->fheap_id), &buf_size) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't get message size from fractal heap.") + /* Updated the index header, so set its dirty flag */ + --header->num_messages; + *cache_flags |= H5AC__DIRTIED_FLAG; /* Remove the message from the index */ if(header->index_type == H5SM_LIST) - message_ptr->ref_count = 0; - else - { + message_ptr->location = H5SM_NO_LOC; + else { if(H5B2_remove(f, dxpl_id, H5SM_INDEX, header->index_addr, &key, NULL, NULL) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTREMOVE, FAIL, "unable to delete message") - } + } /* end else */ - /* Updated the index header, so set its dirty flag */ - --header->num_messages; - *cache_flags |= H5AC__DIRTIED_FLAG; + /* Remove the message from the heap if it was stored in the heap*/ + if(old_loc == H5SM_IN_HEAP) + if(H5HF_remove(fheap, dxpl_id, &(message_ptr->u.heap_loc.fheap_id)) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTREMOVE, FAIL, "unable to remove message from heap") - /* Remove the message from the heap */ - if(H5HF_remove(fheap, dxpl_id, &(message_ptr->fheap_id)) < 0) - HGOTO_ERROR(H5E_SOHM, H5E_CANTREMOVE, FAIL, "unable to remove message from heap") - /* Return the message's encoding so any messages it references can be - * freed - */ + /* Return the message's encoding so anything it references can be freed */ *encoded_mesg = encoding_buf; /* If there are no messages left in the index, delete it */ @@ -1438,9 +1764,8 @@ H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5SM_index_header_t *header, /* Delete the index and its heap */ if(H5SM_delete_index(f, header, dxpl_id, TRUE) < 0) HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "can't delete empty index") - - } else if(header->index_type == H5SM_BTREE && header->num_messages < header->btree_min) - { + } /* end if */ + else if(header->index_type == H5SM_BTREE && header->num_messages < header->btree_min) { /* Otherwise, if we've just passed the btree-to-list cutoff, convert * this B-tree into a list */ @@ -1450,6 +1775,15 @@ H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5SM_index_header_t *header, } /* end if */ done: + /* Unprotect & close the object header if we opened one */ + if(oh && oh != open_oh) { + if(H5AC_unprotect(oloc.file, dxpl_id, H5AC_OHDR, oloc.addr, oh, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header") + + if(H5O_close(&oloc) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to close object header") + } /* end if */ + /* Release the SOHM list */ if(list && H5AC_unprotect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, list, H5AC__DIRTIED_FLAG) < 0) HDONE_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "unable to close SOHM index") @@ -1461,8 +1795,8 @@ done: /* Free the message encoding, if we're not returning it in encoded_mesg * or if there's been an error. */ - if(key.encoding && (NULL == *encoded_mesg || ret_value < 0)) - key.encoding = H5MM_xfree(key.encoding); + if(encoding_buf && (NULL == *encoded_mesg || ret_value < 0)) + encoding_buf = H5MM_xfree(encoding_buf); FUNC_LEAVE_NOAPI(ret_value) } /* end H5SM_delete_from_index() */ @@ -1585,17 +1919,27 @@ done: *------------------------------------------------------------------------- */ herr_t -H5SM_message_encode(const H5F_t UNUSED *f, uint8_t *raw, const void *_nrecord) +H5SM_message_encode(const H5F_t *f, uint8_t *raw, const void *_nrecord) { const H5SM_sohm_t *message = (const H5SM_sohm_t *)_nrecord; FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_message_encode) - /* Encode the SOHM's fields */ - *raw++ = 0; /* The "location" of the message (will be replaced in following checkin) */ + *raw++ = message->location; UINT32ENCODE(raw, message->hash); - UINT32ENCODE(raw, message->ref_count); - UINT64ENCODE(raw, message->fheap_id); + + if(message->location == H5SM_IN_HEAP) { + UINT32ENCODE(raw, message->u.heap_loc.ref_count); + UINT64ENCODE(raw, message->u.heap_loc.fheap_id); + } /* end if */ + else { + HDassert(message->location == H5SM_IN_OH); + + *raw++ = 0; /* reserved (possible flags byte) */ + *raw++ = message->msg_type_id; + UINT16ENCODE(raw, message->u.mesg_loc.index); + H5F_addr_encode(f, &raw, message->u.mesg_loc.oh_addr); + } /* end else */ FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5SM_message_encode */ @@ -1621,11 +1965,21 @@ H5SM_message_decode(const H5F_t UNUSED *f, const uint8_t *raw, void *_nrecord) FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_message_decode) - /* Encode the SOHM's fields */ - raw++; /* skip unused "location" field right now */ + message->location = *raw++; UINT32DECODE(raw, message->hash); - UINT32DECODE(raw, message->ref_count); - UINT64DECODE(raw, message->fheap_id); + + if(message->location == H5SM_IN_HEAP) { + UINT32DECODE(raw, message->u.heap_loc.ref_count); + UINT64DECODE(raw, message->u.heap_loc.fheap_id); + } /* end if */ + else { + HDassert(message->location == H5SM_IN_OH); + + raw++; /* reserved */ + message->msg_type_id = *raw++; + UINT16DECODE(raw, message->u.mesg_loc.index); + H5F_addr_decode(f, &raw, &message->u.mesg_loc.oh_addr); + } /* end else */ FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5SM_message_decode */ @@ -1645,7 +1999,8 @@ H5SM_message_decode(const H5F_t UNUSED *f, const uint8_t *raw, void *_nrecord) *------------------------------------------------------------------------- */ herr_t -H5SM_reconstitute(H5O_shared_t *sh_mesg, H5O_fheap_id_t heap_id) +H5SM_reconstitute(H5O_shared_t *sh_mesg, H5F_t *f, unsigned msg_type_id, + H5O_fheap_id_t heap_id) { FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_reconstitute) @@ -1653,7 +2008,9 @@ H5SM_reconstitute(H5O_shared_t *sh_mesg, H5O_fheap_id_t heap_id) HDassert(sh_mesg); /* Set flag for shared message */ - sh_mesg->flags = H5O_SHARED_IN_HEAP_FLAG; + sh_mesg->type = H5O_SHARE_TYPE_SOHM; + sh_mesg->file = f; + sh_mesg->msg_type_id = msg_type_id; sh_mesg->u.heap_id = heap_id; FUNC_LEAVE_NOAPI(SUCCEED) @@ -1696,7 +2053,7 @@ H5SM_get_refcount_bt2_cb(const void *_record, void *_op_data) /*------------------------------------------------------------------------- * Function: H5SM_get_refcount * - * Purpose: Retrieve the reference count for a message + * Purpose: Retrieve the reference count for a message shared in the heap * * Return: Non-negative on success/Negative on failure * @@ -1715,9 +2072,9 @@ H5SM_get_refcount(H5F_t *f, hid_t dxpl_id, unsigned type_id, H5SM_index_header_t *header=NULL; /* Index header for message type */ H5SM_mesg_key_t key; /* Key for looking up message */ H5SM_sohm_t message; /* Shared message returned from callback */ - size_t buf_size; /* Size of the encoded message */ - void *encoding_buf = NULL; /* Buffer for encoded message */ ssize_t index_num; /* Table index for message type */ + size_t buf_size; /* Size of the encoded message */ + void * encoding_buf = NULL; /* Buffer for encoded message */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5SM_get_refcount) @@ -1731,35 +2088,31 @@ H5SM_get_refcount(H5F_t *f, hid_t dxpl_id, unsigned type_id, if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, f->shared->sohm_addr, NULL, NULL, H5AC_READ))) HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table") - /* Find the correct index and try to delete from it */ + /* Find the correct index and find the message in it */ if((index_num = H5SM_get_index(table, type_id)) < 0) HGOTO_ERROR(H5E_SOHM, H5E_NOTFOUND, FAIL, "unable to find correct SOHM index") header = &(table->indexes[index_num]); - /* Open the heap that this message is in */ + /* Open the heap for this message type */ if(NULL == (fheap = H5HF_open(f, dxpl_id, header->heap_addr))) HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap") - /* Get the size of the message in the heap */ - if(H5HF_get_obj_len(fheap, dxpl_id, &(sh_mesg->u.heap_id), &buf_size) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get message size from fractal heap.") - - /* Allocate a buffer to hold the message */ - if(NULL == (encoding_buf = H5MM_malloc(buf_size))) - HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, FAIL, "memory allocation failed") + /* Set up a SOHM message to correspond to the shared message passed in */ + key.message.location = H5SM_IN_HEAP; + key.message.u.heap_loc.fheap_id = sh_mesg->u.heap_id; + key.message.u.heap_loc.ref_count = 0; /* Ref count isn't needed to find message */ - /* Read the message from the heap and get its hash */ - if(H5HF_read(fheap, dxpl_id, &(sh_mesg->u.heap_id), encoding_buf) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "can't read message from fractal heap.") - - key.message.hash = H5_checksum_lookup3(encoding_buf, buf_size, type_id); + /* Get the encoded message */ + if(H5SM_read_mesg(f, &key.message, fheap, NULL, dxpl_id, &buf_size, &encoding_buf) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap") /* Set up key for message to locate */ + key.file = f; + key.dxpl_id = dxpl_id; + key.fheap = fheap; key.encoding = encoding_buf; key.encoding_size = buf_size; - key.message.fheap_id = sh_mesg->u.heap_id; - key.message.ref_count = 0; /* Ref count isn't needed to find message */ - key.fheap = fheap; + key.message.hash = H5_checksum_lookup3(encoding_buf, buf_size, type_id); /* Try to find the message in the index */ if(header->index_type == H5SM_LIST) { @@ -1776,8 +2129,8 @@ H5SM_get_refcount(H5F_t *f, hid_t dxpl_id, unsigned type_id, /* Copy the message */ message = list->messages[list_pos]; } /* end if */ - else /* Index is a B-tree */ - { + else { + /* Index is a B-tree */ HDassert(header->index_type == H5SM_BTREE); /* Look up the message in the v2 B-tree */ @@ -1786,7 +2139,8 @@ H5SM_get_refcount(H5F_t *f, hid_t dxpl_id, unsigned type_id, } /* end else */ /* Set the refcount for the message */ - *ref_count = message.ref_count; + HDassert(message.location == H5SM_IN_HEAP); + *ref_count = message.u.heap_loc.ref_count; done: /* Release resources */ @@ -1796,7 +2150,6 @@ done: HDONE_ERROR(H5E_CACHE, H5E_CANTRELEASE, FAIL, "unable to close SOHM master table") if(fheap && H5HF_close(fheap, dxpl_id) < 0) HDONE_ERROR(H5E_HEAP, H5E_CLOSEERROR, FAIL, "can't close fractal heap") - if(encoding_buf) encoding_buf = H5MM_xfree(encoding_buf); @@ -1805,6 +2158,179 @@ done: /*------------------------------------------------------------------------- + * Function: H5SM_read_iter_op + * + * Purpose: OH iteration callback to get the encoded version of a message + * by index. + * + * The buffer needs to be freed. + * + * Return: 0 if this is not the message we're searching for + * 1 if this is the message we're searching for (with encoded + * value returned in udata) + * negative on error + * + * Programmer: James Laird + * Wednesday, February 21, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_read_iter_op(const void *_mesg, unsigned idx, void *_udata) +{ + H5SM_read_udata_t *udata = (H5SM_read_udata_t *) _udata; + unsigned char *buf = NULL; + herr_t ret_value = H5_ITER_CONT; + + FUNC_ENTER_NOAPI_NOINIT(H5SM_read_iter_op) + + /* + * Check arguments. + */ + HDassert(_mesg); + HDassert(udata); + HDassert(NULL == udata->encoding_buf); + + /* Check the creation index for this message */ + if(idx == udata->idx) { + size_t raw_size; + + raw_size = H5O_msg_raw_size(udata->file, udata->type_id, TRUE, _mesg); + HDassert(raw_size); + + if(NULL == (buf = HDmalloc(raw_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "memory allocation failed") + + /* JAMES: is there a faster way to get the encoded value here? Do we already have a raw value? */ + if(H5O_msg_encode(udata->file, udata->type_id, TRUE, buf, _mesg) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, H5_ITER_ERROR, "can't encode message from object header") + + udata->encoding_buf = buf; + udata->buf_size = raw_size; + + ret_value = H5_ITER_STOP; + } /* end if */ + +done: + if(ret_value < 0 && buf) + HDfree(buf); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5SM_read_iter_op() */ + + +/*------------------------------------------------------------------------- + * Function: H5SM_read_mesg + * + * Purpose: Given an H5SM_sohm_t sohm, encodes the message into a buffer. + * This buffer should then be freed. + * + * Return: Non-negative on success/negative on error + * + * Programmer: James Laird + * Wednesday, February 21, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5SM_read_mesg(H5F_t *f, const H5SM_sohm_t *mesg, H5HF_t *fheap, + H5O_t *open_oh, hid_t dxpl_id, size_t *encoding_size /*out*/, + void ** encoded_mesg /*out*/) +{ + size_t buf_size; + void * encoding_buf=NULL; + herr_t ret_value = SUCCEED; + H5O_loc_t oloc; + H5O_t *oh = NULL; + FUNC_ENTER_NOAPI(H5SM_read_mesg, FAIL) + + HDassert(f); + HDassert(mesg); + HDassert(fheap); + + /* Get the message size and encoded message for the message to be deleted, + * either from its OH or from the heap. + */ + if(mesg->location == H5SM_IN_OH) { + /* Read message from object header */ + H5SM_read_udata_t udata; + const H5O_msg_class_t *type = NULL; /* Actual H5O class type for the ID */ + H5O_mesg_operator_t op; /* Wrapper for operator */ + + type = H5O_msg_class_g[mesg->msg_type_id]; /* map the type ID to the actual type object */ + HDassert(type); + + /* Reset object location for operation */ + if(H5O_loc_reset(&oloc) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTRESET, FAIL, "unable to initialize location") + + if(NULL == open_oh || mesg->u.mesg_loc.oh_addr != H5O_OH_GET_ADDR(open_oh)) { + /* Open the object in the file */ + oloc.file = f; + oloc.addr = mesg->u.mesg_loc.oh_addr; + if(H5O_open(&oloc) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to open object header") + + /* Load the object header from the cache */ + if(NULL == (oh = H5AC_protect(oloc.file, dxpl_id, H5AC_OHDR, oloc.addr, NULL, NULL, H5AC_READ))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header") + } /* end if */ + else + oh = open_oh; + + /* Set up user data for message iteration */ + udata.file = f; + udata.type_id = mesg->msg_type_id; + udata.encoding_buf = NULL; + + /* Use the "real" iterate routine so it doesn't try to protect the OH */ + op.op_type = H5O_MESG_OP_APP; + op.u.app_op = H5SM_read_iter_op; + if((ret_value = H5O_msg_iterate_real(f, oh, type, &op, &udata, dxpl_id)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "unable to iterate over object header messages") + + /* Record the returned values */ + buf_size = udata.buf_size; + encoding_buf = udata.encoding_buf; + } /* end if */ + else { + HDassert(mesg->location == H5SM_IN_HEAP); + + /* Get the size of the message in the heap */ + if(H5HF_get_obj_len(fheap, dxpl_id, &(mesg->u.heap_loc.fheap_id), &buf_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get message size from fractal heap.") + + /* Allocate a buffer to hold the message */ + if(NULL == (encoding_buf = H5MM_malloc(buf_size))) + HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Read the message from the heap */ + /* JAMES: do one op here, as above? */ + if(H5HF_read(fheap, dxpl_id, &(mesg->u.heap_loc.fheap_id), encoding_buf) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "can't read message from fractal heap.") + } /* end else */ + + *encoded_mesg = encoding_buf; + *encoding_size = buf_size; + +done: + /* Close the object header if we opened one and had an error */ + if(oh && oh != open_oh) { + if(H5AC_unprotect(oloc.file, dxpl_id, H5AC_OHDR, oloc.addr, oh, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header") + + if(H5O_close(&oloc) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to close object header") + } /* end if */ + + if(ret_value < 0 && encoding_buf) + encoding_buf = H5MM_xfree(encoding_buf); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5SM_read_mesg */ + + +/*------------------------------------------------------------------------- * Function: H5SM_table_debug * * Purpose: Print debugging information for the master table. @@ -1859,7 +2385,7 @@ H5SM_table_debug(H5F_t *f, hid_t dxpl_id, haddr_t table_addr, HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table") HDfprintf(stream, "%*sShared Message Master Table...\n", indent, ""); - for(x=0; x<num_indexes; ++x) { + for(x = 0; x < num_indexes; ++x) { HDfprintf(stream, "%*sIndex %d...\n", indent, "", x); HDfprintf(stream, "%*s%-*s %s\n", indent + 3, "", fwidth, "SOHM Index Type:", @@ -1880,13 +2406,14 @@ H5SM_table_debug(H5F_t *f, hid_t dxpl_id, haddr_t table_addr, "Maximum list size:", table->indexes[x].list_max); HDfprintf(stream, "%*s%-*s %Zu\n", indent + 3, "", fwidth, "Minimum B-tree size:", table->indexes[x].btree_min); - } + } /* end for */ done: if(table && H5AC_unprotect(f, dxpl_id, H5AC_SOHM_TABLE, table_addr, table, H5AC__NO_FLAGS_SET) < 0) HDONE_ERROR(H5E_CACHE, H5E_CANTRELEASE, FAIL, "unable to close SOHM master table") + FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5SM_table_debug() */ /*------------------------------------------------------------------------- @@ -1939,19 +2466,37 @@ H5SM_list_debug(H5F_t *f, hid_t dxpl_id, haddr_t list_addr, HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, FAIL, "unable to load SOHM index") HDfprintf(stream, "%*sShared Message List Index...\n", indent, ""); - for(x=0; x<num_messages; ++x) { + for(x = 0; x < num_messages; ++x) { HDfprintf(stream, "%*sShared Object Header Message %d...\n", indent, "", x); - HDfprintf(stream, "%*s%-*s %Zu\n", indent + 3, "", fwidth, - "Heap ID:", list->messages[x].fheap_id); HDfprintf(stream, "%*s%-*s %Zu\n", indent + 3, "", fwidth, /* JAMES: better flag for this? */ "Hash value:", list->messages[x].hash); - HDfprintf(stream, "%*s%-*s %u\n", indent + 3, "", fwidth, - "Reference count:", list->messages[x].ref_count); - } + if(list->messages[x].location == H5SM_IN_HEAP) { + HDfprintf(stream, "%*s%-*s %s\n", indent + 3, "", fwidth, + "Location:", "in heap"); + HDfprintf(stream, "%*s%-*s %Zu\n", indent + 3, "", fwidth, + "Heap ID:", list->messages[x].u.heap_loc.fheap_id); + HDfprintf(stream, "%*s%-*s %u\n", indent + 3, "", fwidth, + "Reference count:", list->messages[x].u.heap_loc.ref_count); + } /* end if */ + else if(list->messages[x].location == H5SM_IN_OH) { + HDfprintf(stream, "%*s%-*s %s\n", indent + 3, "", fwidth, + "Location:", "in object header"); + HDfprintf(stream, "%*s%-*s %a\n", indent + 3, "", fwidth, + "Object header address:", list->messages[x].u.mesg_loc.oh_addr); + HDfprintf(stream, "%*s%-*s %u\n", indent + 3, "", fwidth, + "Message creation index:", list->messages[x].u.mesg_loc.oh_addr); + HDfprintf(stream, "%*s%-*s %u\n", indent + 3, "", fwidth, + "Message type ID:", list->messages[x].msg_type_id); + } /* end if */ + else + HDfprintf(stream, "%*s%-*s %s\n", indent + 3, "", fwidth, + "Location:", "invalid"); + } /* end for */ done: if(list && H5AC_unprotect(f, dxpl_id, H5AC_SOHM_LIST, list_addr, list, H5AC__NO_FLAGS_SET) < 0) HDONE_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "unable to close SOHM index") + FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5SM_list_debug() */ diff --git a/src/H5SMbtree2.c b/src/H5SMbtree2.c index c85770dd..3cd2f23 100755 --- a/src/H5SMbtree2.c +++ b/src/H5SMbtree2.c @@ -36,16 +36,20 @@ /* Local Typedefs */ /******************/ -/* Udata struct for call to H5SM_btree_compare_cb */ +/* Udata struct for calls to H5SM_btree_compare_cb and H5SM_compare_iter_op*/ typedef struct H5SM_compare_udata_t { - H5SM_mesg_key_t *key; /* Key; compare this against record in heap */ - herr_t ret; /* Return value; set this to result of memcmp */ + const H5SM_mesg_key_t *key; /* Key; compare this against stored message */ + H5O_msg_crt_idx_t idx; /* Index of the message in the OH, if applicable */ + unsigned type_id; /* Type ID of the type being compared */ + herr_t ret; /* Return value; set this to result of memcmp */ } H5SM_compare_udata_t; + /********************/ /* Local Prototypes */ /********************/ +/* v2 B-tree callbacks */ static herr_t H5SM_btree_compare_cb(const void *obj, size_t obj_len, void *_udata); static herr_t H5SM_btree_store(void *native, const void *udata); static herr_t H5SM_btree_retrieve(void *udata, const void *native); @@ -98,21 +102,85 @@ H5SM_btree_compare_cb(const void *obj, size_t obj_len, void *_udata) FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_btree_compare_cb) /* If the encoding sizes are different, it's not the same object */ - if(udata->key->encoding_size != obj_len) { - if(udata->key->encoding_size > obj_len) - udata->ret = 1; - else - udata->ret = -1; - } else { + if(udata->key->encoding_size > obj_len) + udata->ret = 1; + else if(udata->key->encoding_size < obj_len) + udata->ret = -1; + else /* Sizes are the same. Return result of memcmp */ udata->ret = HDmemcmp(udata->key->encoding, obj, obj_len); - } FUNC_LEAVE_NOAPI(ret_value) } /* end H5SM_btree_compare_cb() */ /*------------------------------------------------------------------------- + * Function: H5SM_compare_iter_op + * + * Purpose: OH iteration callback to compare a key against a message in + * an OH + * + * Return: 0 if this is not the message we're searching for + * 1 if this is the message we're searching for (with memcmp + * result returned in udata) + * negative on error + * + * Programmer: James Laird + * Wednesday, February 7, 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_compare_iter_op(const void *_mesg, unsigned idx, void *_udata) +{ + H5SM_compare_udata_t *udata = (H5SM_compare_udata_t *) _udata; + unsigned char *buf = NULL; + herr_t ret_value = H5_ITER_CONT; + + FUNC_ENTER_NOAPI_NOINIT(H5SM_compare_iter_op) + + /* + * Check arguments. + */ + HDassert(_mesg); + HDassert(udata && udata->key); + + /* Check the creation index for this message */ + if(idx == udata->idx) { + size_t raw_size; + + /* Retrieve the length of the unshared version of the message */ + raw_size = H5O_msg_raw_size(udata->key->file, udata->type_id, TRUE, _mesg); + HDassert(raw_size > 0); + + if(udata->key->encoding_size > raw_size) + udata->ret = 1; + else if(udata->key->encoding_size < raw_size) + udata->ret = -1; + else { + if(NULL == (buf = HDmalloc(raw_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "memory allocation failed") + + /* JAMES: is there a faster way to get the encoded value here? Do we already have a raw value? */ + if(H5O_msg_encode(udata->key->file, udata->type_id, TRUE, buf, _mesg) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, H5_ITER_ERROR, "unable to encode message from object header") + + udata->ret = HDmemcmp(udata->key->encoding, buf, raw_size); + } /* end else */ + + /* Indicate that we found the message we were looking for */ + ret_value = H5_ITER_STOP; + } /* end if */ + +done: + if(buf) + HDfree(buf); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5SM_compare_iter_op() */ + + +/*------------------------------------------------------------------------- * Function: H5SM_message_compare * * Purpose: Determine whether the search key rec1 represents a shared @@ -133,52 +201,80 @@ H5SM_message_compare(const void *rec1, const void *rec2) { const H5SM_mesg_key_t *key = (const H5SM_mesg_key_t *) rec1; const H5SM_sohm_t *mesg = (const H5SM_sohm_t *) rec2; - int64_t hash_diff; /* Has to be able to hold two 32-bit values */ herr_t ret_value = 0; FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_message_compare) - /* JAMES: might be able to spare a sentinel byte instead of worrying about - * refcounts. Here, we need to find a deleted message in a B-tree to - * actually delete it. - */ - /* JAMES HDassert(mesg->ref_count > 0); */ - /* If the key has an fheap ID, we're looking for a message that's * already in the index; if the fheap ID matches, we've found the message * and can stop immediately. + * Likewise, if the message has an OH location that is matched by the + * message in the index, we've found the message. */ - if(key->message.fheap_id == mesg->fheap_id) - HGOTO_DONE(0); - - hash_diff = key->message.hash; - hash_diff -= mesg->hash; + if(mesg->location == H5SM_IN_HEAP && key->message.location == H5SM_IN_HEAP) { + if(key->message.u.heap_loc.fheap_id == mesg->u.heap_loc.fheap_id) + HGOTO_DONE(0); + } /* end if */ + else if(mesg->location == H5SM_IN_OH && key->message.location == H5SM_IN_OH) { + if(key->message.u.mesg_loc.oh_addr == mesg->u.mesg_loc.oh_addr && + key->message.u.mesg_loc.index == mesg->u.mesg_loc.index && + key->message.msg_type_id == mesg->msg_type_id) + HGOTO_DONE(0); + } /* end if */ + /* Compare hash values */ + if(key->message.hash > mesg->hash) + ret_value = 1; + else if(key->message.hash < mesg->hash) + ret_value = -1; /* If the hash values match, make sure the messages are really the same */ - if(0 == hash_diff) { - /* Hash values match; compare the encoded message with the one in - * the heap. - */ - H5SM_compare_udata_t udata; - herr_t ret; + else { + /* Hash values match; compare the encoded message with the one in + * the index. + */ + H5SM_compare_udata_t udata; + herr_t status; + HDassert(key->message.hash == mesg->hash); HDassert(key->encoding_size > 0 && key->encoding); - /* Casting away const OK. -JML */ + + /* Set up user data for callback */ udata.key = key; - /* Call heap op routine with comparison callback */ - ret = H5HF_op(key->fheap, H5AC_dxpl_id, &(mesg->fheap_id), H5SM_btree_compare_cb, &udata); - HDassert(ret >= 0); + /* Compare the encoded message with either the message in the heap or + * the message in an object header. + */ + if(mesg->location == H5SM_IN_HEAP) { + /* Call heap op routine with comparison callback */ + status = H5HF_op(key->fheap, H5AC_dxpl_id, &(mesg->u.heap_loc.fheap_id), H5SM_btree_compare_cb, &udata); + HDassert(status >= 0); + } /* end if */ + else { + H5O_loc_t oloc; /* Object owning the message */ + + /* Sanity checks */ + HDassert(key->file); + HDassert(mesg->location == H5SM_IN_OH); + + /* Reset the object location */ + status = H5O_loc_reset(&oloc); + HDassert(status >= 0); + + /* Set up object location */ + oloc.file = key->file; + oloc.addr = mesg->u.mesg_loc.oh_addr; + + /* Finish setting up user data for iterator */ + udata.idx = mesg->u.mesg_loc.index; + udata.type_id = mesg->msg_type_id; + + /* JAMES: is this okay? */ + status = H5O_msg_iterate(&oloc, mesg->msg_type_id, H5SM_compare_iter_op, &udata, key->dxpl_id); + HDassert(status >= 0); + } /* end else */ ret_value = udata.ret; } /* end if */ - else { - /* Compress 64-bit hash_diff to fit in an herr_t */ - if(hash_diff > 0) - ret_value = 1; - else - ret_value = -1; - } done: FUNC_LEAVE_NOAPI(ret_value) @@ -263,92 +359,22 @@ H5SM_btree_debug(FILE *stream, const H5F_t UNUSED *f, hid_t UNUSED dxpl_id, FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_btree_debug) - HDfprintf(stream, "%*s%-*s {%a, %lo, %Hx}\n", indent, "", fwidth, "Shared Message:", - sohm->fheap_id, sohm->hash, sohm->ref_count); + if(sohm->location == H5SM_IN_HEAP) + HDfprintf(stream, "%*s%-*s {%a, %lo, %Hx}\n", indent, "", fwidth, + "Shared Message in heap:", + sohm->u.heap_loc.fheap_id, sohm->hash, sohm->u.heap_loc.ref_count); + else { + HDassert(sohm->location == H5SM_IN_OH); + HDfprintf(stream, "%*s%-*s {%a, %lo, %Hx, %Hx}\n", indent, "", fwidth, + "Shared Message in OH:", + sohm->u.mesg_loc.oh_addr, sohm->hash, sohm->msg_type_id, sohm->u.mesg_loc.index); + } /* end else */ FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5SM_btree_debug */ /*------------------------------------------------------------------------- - * Function: H5SM_incr_ref - * - * Purpose: Increment the reference count for a SOHM message and return - * the message's heap ID. - * - * The message pointer is actually returned via op_data, which - * should be a pointer to a H5SM_fheap_id_t. - * - * Return: Non-negative on success - * Negative on failure - * - * Programmer: James Laird - * Monday, November 6, 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5SM_incr_ref(void *record, void *op_data, hbool_t *changed) -{ - H5SM_sohm_t *message = (H5SM_sohm_t *) record; - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_incr_ref) - - HDassert(record); - HDassert(op_data); - HDassert(changed); - - ++message->ref_count; - *changed = TRUE; - - if(op_data) - *(H5O_fheap_id_t *)op_data = message->fheap_id; - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5SM_incr_ref() */ - - -/*------------------------------------------------------------------------- - * Function: H5SM_decr_ref - * - * Purpose: Decrement the reference count for a SOHM message. Doesn't - * remove the record from the B-tree even if the refcount - * reaches zero. - * - * The new message is returned through op_data. If its - * reference count is zero, the calling function should - * remove this record from the B-tree. - * - * Return: Non-negative on success - * Negative on failure - * - * Programmer: James Laird - * Monday, November 6, 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5SM_decr_ref(void *record, void *op_data, hbool_t *changed) -{ - H5SM_sohm_t *message = (H5SM_sohm_t *) record; - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_decr_ref) - - HDassert(record); - HDassert(op_data); - HDassert(changed); - - --message->ref_count; - *changed = TRUE; - - if(op_data) - *(H5SM_sohm_t *)op_data = *message; - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5SM_decr_ref() */ - - -/*------------------------------------------------------------------------- * Function: H5SM_btree_convert_to_list_op * * Purpose: An H5B2_remove_t callback function to convert a SOHM @@ -367,29 +393,25 @@ H5SM_decr_ref(void *record, void *op_data, hbool_t *changed) herr_t H5SM_btree_convert_to_list_op(const void * record, void *op_data) { - const H5SM_sohm_t *message = (const H5SM_sohm_t *) record; - const H5SM_list_t *list = (const H5SM_list_t *) op_data; - hsize_t x; + const H5SM_sohm_t *message = (const H5SM_sohm_t *)record; + const H5SM_list_t *list = (const H5SM_list_t *)op_data; + size_t mesg_idx; /* Index of message to modify */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_btree_convert_to_list_op) + /* Sanity checks */ HDassert(record); HDassert(op_data); - /* Insert this message into the list */ - for(x=0; x<list->header->list_max; x++) - { - if(list->messages[x].ref_count == 0) - { - HDmemcpy(&(list->messages[x]), message, sizeof(H5SM_sohm_t)); - HDassert(list->messages[x].ref_count > 0); - break; - } - } + /* Get the message index, and increment the # of messages in list */ + mesg_idx = list->header->num_messages++; + HDassert(list->header->num_messages <= list->header->list_max); - /* Increment the number of messages in the list */ - ++list->header->num_messages; + /* Insert this message at the end of the list */ + HDassert(list->messages[mesg_idx].location == H5SM_NO_LOC); + HDassert(message->location != H5SM_NO_LOC); + HDmemcpy(&(list->messages[mesg_idx]), message, sizeof(H5SM_sohm_t)); FUNC_LEAVE_NOAPI(SUCCEED) -} +} /* end H5SM_btree_convert_to_list_op() */ diff --git a/src/H5SMcache.c b/src/H5SMcache.c index 168b4e4..07941fb 100644 --- a/src/H5SMcache.c +++ b/src/H5SMcache.c @@ -433,7 +433,7 @@ H5SM_flush_list(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5SM_lis /* Write messages from the messages array to disk */ mesgs_written = 0; for(x=0; x<list->header->list_max && mesgs_written < list->header->num_messages; x++) { - if(list->messages[x].ref_count > 0) { + if(list->messages[x].location != H5SM_NO_LOC) { if(H5SM_message_encode(f, p, &(list->messages[x]))< 0) HGOTO_ERROR(H5E_SOHM, H5E_CANTFLUSH, FAIL, "unable to write shared message to disk") @@ -552,7 +552,7 @@ H5SM_load_list(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *udata1, /* Initialize the rest of the array */ for(x = header->num_messages; x < header->list_max; x++) - list->messages[x].ref_count = 0; + list->messages[x].location = H5SM_NO_LOC; ret_value = list; diff --git a/src/H5SMpkg.h b/src/H5SMpkg.h index 13935ab..2723bc7 100755 --- a/src/H5SMpkg.h +++ b/src/H5SMpkg.h @@ -45,11 +45,18 @@ #define H5SM_TABLE_SIZEOF_MAGIC 4 #define H5SM_SIZEOF_CHECKSUM 4 -#define H5SM_SOHM_ENTRY_SIZE(f) (1 /* "location" (unused right now) */ \ - + 4 /* Hash value */ \ - + 4 /* reference count*/ \ +#define H5SM_HEAP_LOC_SIZE (4 /* Reference count */ \ + sizeof(H5O_fheap_id_t)) /* size of heap ID on disk */ +#define H5SM_OH_LOC_SIZE(f) (1 /* reserved (possible flags?) */ \ + + 1 /* message type ID */ \ + + 2 /* creation index of message in OH */ \ + + H5F_SIZEOF_ADDR(f)) /* address of OH */ + +#define H5SM_SOHM_ENTRY_SIZE(f) (1 /* Message location */ \ + + 4 /* Hash value */ \ + + MAX(H5SM_HEAP_LOC_SIZE, H5SM_OH_LOC_SIZE(f))) + #define H5SM_TABLE_SIZE(f) ( H5SM_TABLE_SIZEOF_MAGIC \ + H5SM_SIZEOF_CHECKSUM) /* Checksum */ @@ -103,29 +110,37 @@ * disk. */ +/* Where a message is stored */ +typedef enum { + H5SM_NO_LOC = -1, + H5SM_IN_HEAP = 0, /* Message is stored in the heap */ + H5SM_IN_OH /* Message is stored in an object header */ +} H5SM_storage_loc_t; + +/* Typedef for a record's location if it's stored in the heap */ +typedef struct { + hsize_t ref_count; /* Number of times this message is used in the file */ + H5O_fheap_id_t fheap_id; /* ID of the OHM in the fractal heap */ +} H5SM_heap_loc_t; + /* Typedef for a SOHM index node */ typedef struct { - uint32_t hash; /* Hash value for OHM */ - H5O_fheap_id_t fheap_id; /* ID of the OHM in the fractal heap */ - hsize_t ref_count; /* Number of times this message is used */ + H5SM_storage_loc_t location; /* Type of message location */ + uint32_t hash; /* Hash value for encoded OHM */ + unsigned msg_type_id; /* Message's type ID */ + union { + H5O_mesg_loc_t mesg_loc; /* Location of message in object header */ + H5SM_heap_loc_t heap_loc; /* Heap ID for message in SOHM heap */ + } u; } H5SM_sohm_t; +/* Types of message indices */ typedef enum { H5SM_BADTYPE = -1, H5SM_LIST, /* Index is an unsorted list */ H5SM_BTREE /* Index is a sorted B-tree */ } H5SM_index_type_t; -/* Typedef for searching an index (list or B-tree) */ -typedef struct { - H5SM_sohm_t message; /* The message to find/insert. - * If the message doesn't yet have a - * heap ID, the heap ID will be 0. */ - void *encoding; /* The message encoded, or NULL */ - size_t encoding_size; /* Size of the encoding, or 0 */ - H5HF_t *fheap; /* The heap for this message type, open. */ -} H5SM_mesg_key_t; - /* Typedef for a SOHM index header */ typedef struct { unsigned mesg_types; /* Bit flag vector of message types */ @@ -157,6 +172,18 @@ struct H5SM_master_table_t { H5SM_index_header_t *indexes; /* Array of num_indexes indexes */ }; +/* Typedef for searching an index (list or B-tree) */ +typedef struct { + H5F_t *file; /* File in which sharing is happening */ + hid_t dxpl_id; /* DXPL for sharing messages in heap */ + H5HF_t *fheap; /* The heap for this message type, open. */ + void *encoding; /* The message encoded, or NULL */ + size_t encoding_size; /* Size of the encoding, or 0 */ + H5SM_sohm_t message; /* The message to find/insert. + * If the message doesn't yet have a + * heap ID, the heap ID will be 0. */ +} H5SM_mesg_key_t; + /* * Data exchange structure to pass through the fractal heap layer for the * H5HF_op function when computing a hash value for a message. @@ -169,6 +196,13 @@ typedef struct { uint32_t hash; /* Hash value */ } H5SM_fh_ud_gh_t; +/* Typedef to increment a reference count in the B-tree */ +typedef struct { + H5SM_mesg_key_t *key; /* IN: key for message being incremented */ + H5O_fheap_id_t fheap_id; /* OUT: fheap ID of record */ + hid_t dxpl_id; +} H5SM_incr_ref_opdata; + /****************************/ /* Package Variables */ @@ -202,10 +236,6 @@ H5_DLL herr_t H5SM_message_decode(const H5F_t *f, const uint8_t *raw, H5_DLL herr_t H5SM_message_compare(const void *rec1, const void *rec2); -/* H5B2_modify_t callbacks to adjust record's refcount. */ -H5_DLL herr_t H5SM_incr_ref(void *record, void *op_data, hbool_t *changed); -H5_DLL herr_t H5SM_decr_ref(void *record, void *op_data, hbool_t *changed); - /* H5B2_remove_t callback to add messages to a list index */ H5_DLL herr_t H5SM_btree_convert_to_list_op(const void * record, void *op_data); diff --git a/src/H5SMprivate.h b/src/H5SMprivate.h index 88249b9..0f3d3e0 100755 --- a/src/H5SMprivate.h +++ b/src/H5SMprivate.h @@ -43,15 +43,17 @@ H5_DLL herr_t H5SM_init(H5F_t *f, H5P_genplist_t *fc_plist, const H5O_loc_t *ext_loc, hid_t dxpl_id); H5_DLL htri_t H5SM_can_share(H5F_t *f, hid_t dxpl_id, H5SM_master_table_t *table, ssize_t *sohm_index_num, unsigned type_id, const void *mesg); -H5_DLL htri_t H5SM_try_share(H5F_t *f, hid_t dxpl_id, unsigned type_id, - void *mesg); -H5_DLL herr_t H5SM_try_delete(H5F_t *f, hid_t dxpl_id, unsigned type_id, const H5O_shared_t *mesg); +H5_DLL htri_t H5SM_try_share(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, + unsigned type_id, void *mesg, unsigned *mesg_flags); +H5_DLL herr_t H5SM_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, + H5O_shared_t *sh_mesg); H5_DLL herr_t H5SM_get_info(const H5O_loc_t *ext_loc, H5P_genplist_t *fc_plist, hid_t dxpl_id); H5_DLL htri_t H5SM_type_shared(H5F_t *f, unsigned type_id, hid_t dxpl_id); H5_DLL herr_t H5SM_get_fheap_addr(H5F_t *f, hid_t dxpl_id, unsigned type_id, haddr_t *fheap_addr); -H5_DLL herr_t H5SM_reconstitute(H5O_shared_t *sh_mesg, H5O_fheap_id_t heap_id); +H5_DLL herr_t H5SM_reconstitute(H5O_shared_t *sh_mesg, H5F_t *f, + unsigned msg_type_id, H5O_fheap_id_t heap_id); H5_DLL herr_t H5SM_get_refcount(H5F_t *f, hid_t dxpl_id, unsigned type_id, const H5O_shared_t *sh_mesg, hsize_t *ref_count); @@ -406,7 +406,7 @@ static H5T_t *H5T_decode(const unsigned char *buf); /* Define a macro for common code for all newly allocate datatypes */ #define H5T_INIT_TYPE_ALLOC_COMMON(TYPE) { \ - dt->sh_loc.flags = H5O_NOT_SHARED; \ + dt->sh_loc.type = H5O_SHARE_TYPE_UNSHARED; \ dt->shared->type = TYPE; \ } @@ -3005,7 +3005,7 @@ H5T_create(H5T_class_t type, size_t size) dt->shared->size = size; /* Set return value */ - ret_value=dt; + ret_value = dt; done: if(ret_value==NULL) { @@ -3107,22 +3107,22 @@ H5T_copy(const H5T_t *old_dt, H5T_copy_t method) * Return a transient type (locked or unlocked) or an opened named * type. Immutable transient types are degraded to read-only. */ - if(old_dt->sh_loc.flags & H5O_COMMITTED_FLAG) { + if(old_dt->sh_loc.type == H5O_SHARE_TYPE_COMMITTED) { /* Check if the object is already open */ - if((reopened_fo = H5FO_opened(old_dt->sh_loc.u.oloc.file, old_dt->sh_loc.u.oloc.addr)) == NULL) { + if((reopened_fo = H5FO_opened(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr)) == NULL) { /* Clear any errors from H5FO_opened() */ H5E_clear_stack(NULL); /* Open named datatype again */ - if(H5O_open(&(old_dt->sh_loc.u.oloc)) < 0) + if(H5O_open(&old_dt->oloc) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to reopen named data type"); /* Insert opened named datatype into opened object list for the file */ - if(H5FO_insert(old_dt->sh_loc.u.oloc.file, old_dt->sh_loc.u.oloc.addr, new_dt->shared, FALSE)<0) + if(H5FO_insert(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr, new_dt->shared, FALSE)<0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, NULL, "can't insert datatype into list of open objects") /* Increment object count for the object in the top file */ - if(H5FO_top_incr(old_dt->sh_loc.u.oloc.file, old_dt->sh_loc.u.oloc.addr) < 0) + if(H5FO_top_incr(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count") new_dt->shared->fo_count = 1; @@ -3136,14 +3136,14 @@ H5T_copy(const H5T_t *old_dt, H5T_copy_t method) reopened_fo->fo_count++; /* Check if the object has been opened through the top file yet */ - if(H5FO_top_count(old_dt->sh_loc.u.oloc.file, old_dt->sh_loc.u.oloc.addr) == 0) { + if(H5FO_top_count(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr) == 0) { /* Open the object through this top file */ - if(H5O_open(&(old_dt->sh_loc.u.oloc)) < 0) + if(H5O_open(&old_dt->oloc) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to open object header") } /* end if */ /* Increment object count for the object in the top file */ - if(H5FO_top_incr(old_dt->sh_loc.u.oloc.file, old_dt->sh_loc.u.oloc.addr) < 0) + if(H5FO_top_incr(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count") } /* end else */ new_dt->shared->state = H5T_STATE_OPEN; @@ -3259,28 +3259,32 @@ H5T_copy(const H5T_t *old_dt, H5T_copy_t method) break; } /* end switch */ - /* Set the path name if the original type was a named type and the new - * type is also named. + /* Set the cached location & name path if the original type was a named + * type and the new type is also named. */ - if(H5G_name_reset(&(new_dt->path)) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "unable to reset path") + if(H5O_loc_reset(&new_dt->oloc) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRESET, NULL, "unable to initialize location") + if(H5G_name_reset(&new_dt->path) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to reset path") if(new_dt->shared->state == H5T_STATE_NAMED || new_dt->shared->state == H5T_STATE_OPEN) { + if(H5O_loc_copy(&(new_dt->oloc), &(old_dt->oloc), H5_COPY_DEEP) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy object location") if(H5G_name_copy(&(new_dt->path), &(old_dt->path), H5_COPY_DEEP) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "unable to copy path") + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to copy path") } /* end if */ /* Copy shared location information if the new type is named or if it is * shared in the heap. */ - if(old_dt->sh_loc.flags & H5O_SHARED_IN_HEAP_FLAG || - new_dt->shared->state == H5T_STATE_NAMED || new_dt->shared->state == H5T_STATE_OPEN) - { - if(H5O_shared_copy(&(new_dt->sh_loc), &(old_dt->sh_loc)) < 0) + if(old_dt->sh_loc.type == H5O_SHARE_TYPE_SOHM || + new_dt->shared->state == H5T_STATE_NAMED || new_dt->shared->state == H5T_STATE_OPEN) { + if(H5O_set_shared(&(new_dt->sh_loc), &(old_dt->sh_loc)) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy shared information") } /* end if */ else - new_dt->sh_loc.flags = H5O_NOT_SHARED; + /* Reset shared component info */ + H5O_msg_reset_share(H5O_DTYPE_ID, new_dt); /* Set return value */ ret_value = new_dt; @@ -3368,8 +3372,9 @@ H5T_alloc(void) /* Allocate & initialize new datatype info */ if(NULL == (dt = H5FL_CALLOC(H5T_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + H5O_loc_reset(&(dt->oloc)); H5G_name_reset(&(dt->path)); - dt->sh_loc.flags = H5O_NOT_SHARED; + H5O_msg_reset_share(H5O_DTYPE_ID, dt); if(NULL == (dt->shared = H5FL_CALLOC(H5T_shared_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") @@ -3378,13 +3383,12 @@ H5T_alloc(void) ret_value = dt; done: - if(ret_value == NULL) { + if(ret_value == NULL) if(dt != NULL) { if(dt->shared != NULL) H5FL_FREE(H5T_shared_t, dt->shared); H5FL_FREE(H5T_t, dt); } /* end if */ - } /* end if */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5T_alloc() */ @@ -3419,15 +3423,16 @@ H5T_free(H5T_t *dt) * remove from the list of open objects in the file. */ if(H5T_STATE_OPEN == dt->shared->state) { - HDassert(dt->sh_loc.flags & H5O_COMMITTED_FLAG); - HDassert(H5F_addr_defined(dt->sh_loc.u.oloc.addr)); + HDassert(dt->sh_loc.type == H5O_SHARE_TYPE_COMMITTED); + HDassert(H5F_addr_defined(dt->sh_loc.u.loc.oh_addr)); + HDassert(H5F_addr_defined(dt->oloc.addr)); /* Remove the datatype from the list of opened objects in the file */ - if(H5FO_top_decr(dt->sh_loc.u.oloc.file, dt->sh_loc.u.oloc.addr) < 0) + if(H5FO_top_decr(dt->sh_loc.file, dt->sh_loc.u.loc.oh_addr) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "can't decrement count for object") - if(H5FO_delete(dt->sh_loc.u.oloc.file, H5AC_dxpl_id, dt->sh_loc.u.oloc.addr) < 0) + if(H5FO_delete(dt->sh_loc.file, H5AC_dxpl_id, dt->sh_loc.u.loc.oh_addr) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "can't remove datatype from list of open objects") - if(H5O_close(&(dt->sh_loc.u.oloc)) < 0) + if(H5O_close(&dt->oloc) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to close data type object header") dt->shared->state = H5T_STATE_NAMED; } /* end if */ @@ -3524,16 +3529,18 @@ H5T_close(H5T_t *dt) * remove from the list of open objects in the file. */ if(H5T_STATE_OPEN == dt->shared->state) { - HDassert(dt->sh_loc.flags & H5O_COMMITTED_FLAG); + HDassert(dt->sh_loc.type == H5O_SHARE_TYPE_COMMITTED); /* Decrement the ref. count for this object in the top file */ - if(H5FO_top_decr(dt->sh_loc.u.oloc.file, dt->sh_loc.u.oloc.addr) < 0) + if(H5FO_top_decr(dt->sh_loc.file, dt->sh_loc.u.loc.oh_addr) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "can't decrement count for object") /* Check reference count for this object in the top file */ - if(H5FO_top_count(dt->sh_loc.u.oloc.file, dt->sh_loc.u.oloc.addr) == 0) - if(H5O_close(&(dt->sh_loc.u.oloc)) < 0) + if(H5FO_top_count(dt->sh_loc.file, dt->sh_loc.u.loc.oh_addr) == 0) { + /* Close object location for named datatype */ + if(H5O_close(&dt->oloc) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to close") + } /* end if */ } /* end if */ /* Free the group hier. path since we're not calling H5T_free*/ @@ -4652,8 +4659,8 @@ H5T_oloc(H5T_t *dt) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "not a named datatype") case H5T_STATE_NAMED: case H5T_STATE_OPEN: - HDassert(dt->sh_loc.flags & H5O_COMMITTED_FLAG); - ret_value = &(dt->sh_loc.u.oloc); + HDassert(dt->sh_loc.type == H5O_SHARE_TYPE_COMMITTED); + ret_value = &dt->oloc; break; } /* end switch */ diff --git a/src/H5Tcommit.c b/src/H5Tcommit.c index 73d1c3d..ff0a48c 100644 --- a/src/H5Tcommit.c +++ b/src/H5Tcommit.c @@ -175,25 +175,25 @@ done: * to return it to the state it was in before it was committed. */ if(ret_value < 0 && ocrt_info.new_obj) { - if(dt->shared->state == H5T_STATE_OPEN && dt->sh_loc.flags & H5O_COMMITTED_FLAG) { + if(dt->shared->state == H5T_STATE_OPEN && dt->sh_loc.type == H5O_SHARE_TYPE_COMMITTED) { /* Remove the datatype from the list of opened objects in the file */ - if(H5FO_top_decr(dt->sh_loc.u.oloc.file, dt->sh_loc.u.oloc.addr) < 0) + if(H5FO_top_decr(dt->sh_loc.file, dt->sh_loc.u.loc.oh_addr) < 0) HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "can't decrement count for object") - if(H5FO_delete(dt->sh_loc.u.oloc.file, dxpl_id, dt->sh_loc.u.oloc.addr) < 0) + if(H5FO_delete(dt->sh_loc.file, dxpl_id, dt->sh_loc.u.loc.oh_addr) < 0) HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "can't remove dataset from list of open objects") /* Close the datatype object */ - if(H5O_close(&(dt->sh_loc.u.oloc)) < 0) + if(H5O_close(&(dt->oloc)) < 0) HDONE_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to release object header") /* Remove the datatype's object header from the file */ - if(H5O_delete(dt->sh_loc.u.oloc.file, dxpl_id, dt->sh_loc.u.oloc.addr) < 0) + if(H5O_delete(dt->sh_loc.file, dxpl_id, dt->sh_loc.u.loc.oh_addr) < 0) HDONE_ERROR(H5E_DATATYPE, H5E_CANTDELETE, FAIL, "unable to delete object header") /* Mark datatype as being back in memory */ - if(H5T_set_loc(dt, dt->sh_loc.u.oloc.file, H5T_LOC_MEMORY)) + if(H5T_set_loc(dt, dt->sh_loc.file, H5T_LOC_MEMORY)) HDONE_ERROR(H5E_DATATYPE, H5E_CANTDELETE, FAIL, "unable to return datatype to memory") - dt->sh_loc.flags = H5O_NOT_SHARED; + dt->sh_loc.type = H5O_SHARE_TYPE_UNSHARED; dt->shared->state = old_state; } /* end if */ } /* end if */ @@ -278,7 +278,7 @@ H5T_commit(H5F_t *file, H5T_t *type, hid_t tcpl_id, hid_t dxpl_id) { H5O_loc_t temp_oloc; /* Temporary object header location */ H5G_name_t temp_path; /* Temporary path */ - hbool_t loc_init=FALSE; /* Have temp_oloc and temp_path been initialized? */ + hbool_t loc_init = FALSE; /* Have temp_oloc and temp_path been initialized? */ size_t dtype_size; /* Size of the datatype message */ herr_t ret_value = SUCCEED; /* Return value */ @@ -328,21 +328,21 @@ H5T_commit(H5F_t *file, H5T_t *type, hid_t tcpl_id, hid_t dxpl_id) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to update type header message") /* Copy the new object header's location into the datatype, taking ownership of it */ - if(H5O_loc_copy(&(type->sh_loc.u.oloc), &temp_oloc, H5_COPY_SHALLOW) < 0) + if(H5O_loc_copy(&(type->oloc), &temp_oloc, H5_COPY_SHALLOW) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy datatype location") if(H5G_name_copy(&(type->path), &temp_path, H5_COPY_SHALLOW) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy datatype location") loc_init = FALSE; /* Set the shared info fields */ - type->sh_loc.flags = H5O_COMMITTED_FLAG; + H5T_update_shared(type); type->shared->state = H5T_STATE_OPEN; type->shared->fo_count = 1; /* Add datatype to the list of open objects in the file */ - if(H5FO_top_incr(type->sh_loc.u.oloc.file, type->sh_loc.u.oloc.addr) < 0) + if(H5FO_top_incr(type->sh_loc.file, type->sh_loc.u.loc.oh_addr) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, FAIL, "can't incr object ref. count") - if(H5FO_insert(type->sh_loc.u.oloc.file, type->sh_loc.u.oloc.addr, type->shared, TRUE) < 0) + if(H5FO_insert(type->sh_loc.file, type->sh_loc.u.loc.oh_addr, type->shared, TRUE) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "can't insert datatype into list of open objects") /* Mark datatype as being on memory now. Since this datatype may still be used in memory @@ -356,12 +356,12 @@ done: H5O_loc_free(&temp_oloc); H5G_name_free(&temp_path); } /* end if */ - if((type->shared->state == H5T_STATE_TRANSIENT || type->shared->state == H5T_STATE_RDONLY) && (type->sh_loc.flags & H5O_COMMITTED_FLAG)) { - if(H5O_close(&(type->sh_loc.u.oloc)) < 0) + if((type->shared->state == H5T_STATE_TRANSIENT || type->shared->state == H5T_STATE_RDONLY) && (type->sh_loc.type == H5O_SHARE_TYPE_COMMITTED)) { + if(H5O_close(&(type->oloc)) < 0) HDONE_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to release object header") - if(H5O_delete(file, dxpl_id, type->sh_loc.u.oloc.addr) < 0) + if(H5O_delete(file, dxpl_id, type->sh_loc.u.loc.oh_addr) < 0) HDONE_ERROR(H5E_DATATYPE, H5E_CANTDELETE, FAIL, "unable to delete object header") - type->sh_loc.flags = H5O_NOT_SHARED; + type->sh_loc.type = H5O_SHARE_TYPE_UNSHARED; } /* end if */ } /* end if */ @@ -451,10 +451,10 @@ H5T_link(const H5T_t *type, int adjust, hid_t dxpl_id) FUNC_ENTER_NOAPI(H5T_link, FAIL) HDassert(type); - HDassert(type->sh_loc.flags & H5O_COMMITTED_FLAG); + HDassert(type->sh_loc.type == H5O_SHARE_TYPE_COMMITTED); /* Adjust the link count on the named datatype */ - if((ret_value = H5O_link(&(type->sh_loc.u.oloc), adjust, dxpl_id)) < 0) + if((ret_value = H5O_link(&type->oloc, adjust, dxpl_id)) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_LINKCOUNT, FAIL, "unable to adjust named datatype link count") done: @@ -591,18 +591,13 @@ H5Tget_create_plist(hid_t dtype_id) /* Retrieve further information, if the datatype is committed */ if(status > 0) { H5P_genplist_t *new_plist; /* New datatype creation property list */ - H5O_loc_t *type_oloc; /* Object location for committed datatype */ /* Get property list object for new TCPL */ if(NULL == (new_plist = H5I_object(new_tcpl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list") - /* Get the datatype's object location */ - if(NULL == (type_oloc = H5T_oloc(type))) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to get object location of datatype") - /* Retrieve any object creation properties */ - if(H5O_get_create_plist(type_oloc, H5AC_ind_dxpl_id, new_plist) < 0) + if(H5O_get_create_plist(&type->oloc, H5AC_ind_dxpl_id, new_plist) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't get object creation info") } /* end if */ @@ -653,11 +648,11 @@ H5T_open(const H5G_loc_t *loc, hid_t dxpl_id) HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, NULL, "not found") /* Add the datatype to the list of opened objects in the file */ - if(H5FO_insert(dt->sh_loc.u.oloc.file, dt->sh_loc.u.oloc.addr, dt->shared, FALSE) < 0) + if(H5FO_insert(dt->sh_loc.file, dt->sh_loc.u.loc.oh_addr, dt->shared, FALSE) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, NULL, "can't insert datatype into list of open objects") /* Increment object count for the object in the top file */ - if(H5FO_top_incr(dt->sh_loc.u.oloc.file, dt->sh_loc.u.oloc.addr) < 0) + if(H5FO_top_incr(dt->sh_loc.file, dt->sh_loc.u.loc.oh_addr) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count") /* Mark any datatypes as being in memory now */ @@ -672,7 +667,7 @@ H5T_open(const H5G_loc_t *loc, hid_t dxpl_id) #if defined(H5_USING_PURIFY) || !defined(NDEBUG) /* Clear object location */ - if(H5O_loc_reset(&(dt->sh_loc.u.oloc)) < 0) + if(H5O_loc_reset(&(dt->oloc)) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to reset location") /* Clear path name */ @@ -681,27 +676,31 @@ H5T_open(const H5G_loc_t *loc, hid_t dxpl_id) #endif /* H5_USING_PURIFY */ /* Shallow copy (take ownership) of the object location object */ - if(H5O_loc_copy(&(dt->sh_loc.u.oloc), loc->oloc, H5_COPY_SHALLOW) < 0) + if(H5O_loc_copy(&dt->oloc, loc->oloc, H5_COPY_SHALLOW) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy object location") /* Shallow copy (take ownership) of the group hier. path */ if(H5G_name_copy(&(dt->path), loc->path, H5_COPY_SHALLOW) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy path") + /* Set the shared component info */ + H5T_update_shared(dt); + + /* Point to shared datatype info */ dt->shared = shared_fo; - dt->sh_loc.flags |= H5O_COMMITTED_FLAG; + /* Increment ref. count on shared info */ shared_fo->fo_count++; /* Check if the object has been opened through the top file yet */ - if(H5FO_top_count(dt->sh_loc.u.oloc.file, dt->sh_loc.u.oloc.addr) == 0) { + if(H5FO_top_count(dt->sh_loc.file, dt->sh_loc.u.loc.oh_addr) == 0) { /* Open the object through this top file */ - if(H5O_open(&(dt->sh_loc.u.oloc)) < 0) + if(H5O_open(&(dt->oloc)) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to open object header") } /* end if */ /* Increment object count for the object in the top file */ - if(H5FO_top_incr(dt->sh_loc.u.oloc.file, dt->sh_loc.u.oloc.addr) < 0) + if(H5FO_top_incr(dt->sh_loc.file, dt->sh_loc.u.loc.oh_addr) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count") } /* end else */ @@ -713,7 +712,7 @@ done: if(shared_fo == NULL) /* Need to free shared fo */ H5FL_FREE(H5T_shared_t, dt->shared); - H5O_loc_free(&(dt->sh_loc.u.oloc)); + H5O_loc_free(&(dt->oloc)); H5G_name_free(&(dt->path)); H5FL_FREE(H5T_t, dt); @@ -758,16 +757,18 @@ H5T_open_oid(const H5G_loc_t *loc, hid_t dxpl_id) /* Mark the type as named and open */ dt->shared->state = H5T_STATE_OPEN; - dt->sh_loc.flags |= H5O_COMMITTED_FLAG; /* Shallow copy (take ownership) of the object location object */ - if(H5O_loc_copy(&(dt->sh_loc.u.oloc), loc->oloc, H5_COPY_SHALLOW) < 0) + if(H5O_loc_copy(&dt->oloc, loc->oloc, H5_COPY_SHALLOW) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy object location") /* Shallow copy (take ownership) of the group hier. path */ if(H5G_name_copy(&(dt->path), loc->path, H5_COPY_SHALLOW) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy path") + /* Set the shared component info */ + H5T_update_shared(dt); + /* Set return value */ ret_value = dt; @@ -779,3 +780,29 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5T_open_oid() */ + +/*------------------------------------------------------------------------- + * Function: H5T_update_shared + * + * Purpose: Update the shared location information from the object location + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Friday, April 13, 2007 + * + *------------------------------------------------------------------------- + */ +herr_t +H5T_update_shared(H5T_t *dt) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_update_shared) + + HDassert(dt); + + /* Set the shared location fields from the named datatype info */ + H5O_UPDATE_SHARED(&(dt->sh_loc), H5O_SHARE_TYPE_COMMITTED, dt->oloc.file, H5O_DTYPE_ID, 0, dt->oloc.addr) + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5T_update_shared() */ + diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h index d7cd35d..c9fba39 100644 --- a/src/H5Tpkg.h +++ b/src/H5Tpkg.h @@ -312,7 +312,6 @@ typedef struct H5T_shared_t { hsize_t fo_count; /* number of references to this file object */ H5T_state_t state; /*current state of the type */ H5T_class_t type; /*which class of type is this? */ - H5F_t *sh_file;/*file pointer if this is a shared type */ size_t size; /*total size of an instance of this type */ hbool_t force_conv;/* Set if this type always needs to be converted and H5T_conv_noop cannot be called */ struct H5T_t *parent;/*parent type for derived datatypes */ @@ -330,6 +329,7 @@ struct H5T_t { H5O_shared_t sh_loc; /* Shared message info (must be first) */ H5T_shared_t *shared; /* all other information */ + H5O_loc_t oloc; /* Object location, if the type is a named type */ H5G_name_t path; /* group hier. path if the type is a named type */ }; diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h index 9ab7566..a566a0a 100644 --- a/src/H5Tprivate.h +++ b/src/H5Tprivate.h @@ -106,5 +106,7 @@ H5_DLL H5R_type_t H5T_get_ref_type(const H5T_t *dt); H5_DLL H5T_t *H5T_open(const H5G_loc_t *loc, hid_t dxpl_id); H5_DLL htri_t H5T_committed(const H5T_t *type); H5_DLL int H5T_link(const H5T_t *type, int adjust, hid_t dxpl_id); +H5_DLL herr_t H5T_update_shared(H5T_t *type); + +#endif /* _H5Tprivate_H */ -#endif |