diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/H5A.c | 75 | ||||
-rw-r--r-- | src/H5Adense.c | 65 | ||||
-rw-r--r-- | src/H5Apkg.h | 4 | ||||
-rw-r--r-- | src/H5B2.c | 16 | ||||
-rw-r--r-- | src/H5Oattribute.c | 139 | ||||
-rw-r--r-- | src/H5Opkg.h | 1 |
6 files changed, 225 insertions, 75 deletions
@@ -73,7 +73,6 @@ static H5A_t *H5A_open_by_name(const H5G_loc_t *loc, const char *name, static herr_t H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id); static herr_t H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_t dxpl_id); static hsize_t H5A_get_storage_size(const H5A_t *attr); -static herr_t H5A_find_idx_by_name(const void *mesg, unsigned idx, void *op_data); /*********************/ @@ -233,7 +232,6 @@ H5Acreate(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id, hid_t ret_value; /* Return value */ FUNC_ENTER_API(H5Acreate, FAIL) - H5TRACE5("i","isiii",loc_id,name,type_id,space_id,plist_id); /* check arguments */ if(H5I_FILE == H5I_get_type(loc_id) || H5I_ATTR == H5I_get_type(loc_id)) @@ -288,14 +286,12 @@ done: */ static hid_t H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type, - const H5S_t *space, hid_t acpl_id, hid_t dxpl_id) + const H5S_t *space, hid_t acpl_id, hid_t dxpl_id) { H5A_t *attr = NULL; - H5A_iter_cb1 cb; /* Iterator callback */ - H5P_genplist_t *ac_plist=NULL; /* New Property list */ H5O_shared_t sh_mesg; - htri_t tri_ret; /* htri_t return value */ - hid_t ret_value = FAIL; + htri_t tri_ret; /* htri_t return value */ + hid_t ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5A_create) @@ -308,13 +304,14 @@ H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type, /* Reset shared message information */ HDmemset(&sh_mesg, 0, sizeof(H5O_shared_t)); - /* Iterate over the existing attributes to check for duplicates */ - cb.name = name; - cb.idx = (-1); -/* XXX: Add support/test for dense attribute storage */ - if((ret_value = H5O_msg_iterate(loc->oloc, H5O_ATTR_ID, H5A_find_idx_by_name, &cb, dxpl_id)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "error iterating over attributes") - if(ret_value > 0) + /* Check for existing attribute with same name */ + /* (technically, the "attribute create" operation will fail for a duplicated + * name, but it's going to be hard to unwind all the special cases on + * failure, so just check first, for now - QAK) + */ + if((tri_ret = H5O_attr_exists(loc->oloc, name, H5AC_ind_dxpl_id)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "error checking attributes") + else if(tri_ret > 0) HGOTO_ERROR(H5E_ATTR, H5E_ALREADYEXISTS, FAIL, "attribute already exists") /* Check if the dataspace has an extent set (or is NULL) */ @@ -329,8 +326,10 @@ H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type, if(acpl_id == H5P_DEFAULT) attr->encoding = H5F_DEFAULT_CSET; else { + H5P_genplist_t *ac_plist; /* ACPL Property list */ + /* Get a local copy of the attribute creation property list */ - if (NULL == (ac_plist = H5I_object(acpl_id))) + if(NULL == (ac_plist = H5I_object(acpl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") if(H5P_get(ac_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &(attr->encoding)) < 0) @@ -420,7 +419,7 @@ H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type, HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open") attr->obj_opened = TRUE; - /* Create the attribute message */ + /* Create the attribute on the object */ if(H5O_attr_create(&(attr->oloc), dxpl_id, attr) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to create attribute in object header") @@ -442,50 +441,6 @@ done: /*-------------------------------------------------------------------------- NAME - H5A_find_idx_by_name - PURPOSE - Iterator callback to determine the index of a attribute - USAGE - herr_t H5A_find_idx_by_name (mesg, idx, op_data) - const H5A_t *mesg; IN: Pointer to attribute - unsigned idx; IN: Index of attribute - void *op_data; IN: Op data passed in - RETURNS - Non-negative on success, negative on failure - - DESCRIPTION - This function determines if an attribute matches the name to search - for (from the 'op_data') and sets the index value in the 'op_data'. ---------------------------------------------------------------------------*/ -static herr_t -H5A_find_idx_by_name(const void *_mesg, unsigned idx, void *_op_data) -{ - const H5A_t *mesg = (const H5A_t *)_mesg; /* Pointer to attribute */ - H5A_iter_cb1 *op_data = (H5A_iter_cb1 *)_op_data; /* Pointer to op data */ - int ret_value; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_find_idx_by_name) - - HDassert(mesg); - HDassert(op_data); - - /* - * Compare found attribute name to queried name and set the idx in the - * callback info if names are the same. - */ - if(HDstrcmp(mesg->name, op_data->name) == 0) { - op_data->idx = idx; - ret_value = H5_ITER_STOP; - } /* end if */ - else - ret_value = H5_ITER_CONT; - - FUNC_LEAVE_NOAPI(ret_value) -} /* H5A_find_idx_by_name() */ - - -/*-------------------------------------------------------------------------- - NAME H5Aopen_name PURPOSE Opens an attribute for an object by looking up the attribute name diff --git a/src/H5Adense.c b/src/H5Adense.c index 9d98dc0..7395189 100644 --- a/src/H5Adense.c +++ b/src/H5Adense.c @@ -183,7 +183,7 @@ H5FL_BLK_DEFINE(ser_attr); *------------------------------------------------------------------------- */ static herr_t -H5A_dense_build_table_cb(const H5A_t *attr, uint8_t mesg_flags, void *_udata) +H5A_dense_build_table_cb(const H5A_t *attr, unsigned mesg_flags, void *_udata) { H5A_dense_bt_ud_t *udata = (H5A_dense_bt_ud_t *)_udata; /* 'User data' passed in */ herr_t ret_value = H5_ITER_CONT; /* Return value */ @@ -1172,6 +1172,69 @@ done: /*------------------------------------------------------------------------- + * Function: H5A_dense_exists + * + * Purpose: Check if an attribute exists in dense storage structures for + * an object + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Dec 11 2006 + * + *------------------------------------------------------------------------- + */ +htri_t +H5A_dense_exists(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *name) +{ + H5A_bt2_ud_common_t udata; /* User data for v2 B-tree modify */ + H5HF_t *fheap = NULL; /* Fractal heap handle */ + htri_t ret_value = TRUE; /* Return value */ + + FUNC_ENTER_NOAPI(H5A_dense_exists, NULL) + + /* + * Check arguments. + */ + HDassert(f); + HDassert(oh); + HDassert(name); + + /* Open the fractal heap */ + if(NULL == (fheap = H5HF_open(f, dxpl_id, oh->attr_fheap_addr))) + HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap") + + /* Create the "udata" information for v2 B-tree record 'find' */ + udata.f = f; + udata.dxpl_id = dxpl_id; + udata.fheap = fheap; + udata.name = name; + udata.name_hash = H5_checksum_lookup3(name, HDstrlen(name), 0); + udata.flags = 0; + udata.corder = -1; /* XXX: None yet */ + udata.found_op = NULL; /* v2 B-tree comparison callback */ + udata.found_op_data = NULL; + +/* XXX: test for shared attributes */ + /* Find the attribute in the 'name' index */ + if(H5B2_find(f, dxpl_id, H5A_BT2_NAME, oh->name_bt2_addr, &udata, NULL, NULL) < 0) { + /* Assume that the failure was just not finding the attribute & clear stack */ + H5E_clear_stack(NULL); + + ret_value = FALSE; + } /* end if */ + +done: + /* Release resources */ + if(fheap && H5HF_close(fheap, dxpl_id) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5A_dense_exists() */ + + +/*------------------------------------------------------------------------- * Function: H5A_dense_delete * * Purpose: Delete all dense storage structures for attributes on an object diff --git a/src/H5Apkg.h b/src/H5Apkg.h index 85be22e..11dd43d 100644 --- a/src/H5Apkg.h +++ b/src/H5Apkg.h @@ -122,7 +122,7 @@ typedef struct { } H5A_attr_table_t; /* Attribute iteration operator for internal library callbacks */ -typedef herr_t (*H5A_lib_iterate_t)(const H5A_t *attr, uint8_t mesg_flags, +typedef herr_t (*H5A_lib_iterate_t)(const H5A_t *attr, unsigned mesg_flags, void *op_data); /* Describe kind of callback to make for each attribute */ @@ -172,6 +172,8 @@ H5_DLL herr_t H5A_dense_iterate(H5F_t *f, hid_t dxpl_id, hid_t loc_id, unsigned *last_attr, const H5A_attr_iterate_t *attr_op, void *op_data); H5_DLL herr_t H5A_dense_remove(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *name); +H5_DLL htri_t H5A_dense_exists(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, + const char *name); /* Attribute table operations */ H5_DLL herr_t H5A_dense_build_table(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, @@ -328,10 +328,10 @@ herr_t H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr, void *udata, H5B2_found_t op, void *op_data) { - H5B2_t *bt2=NULL; /* Pointer to the B-tree header */ - H5RC_t *bt2_shared=NULL; /* Pointer to ref-counter for shared B-tree info */ + H5B2_t *bt2 = NULL; /* Pointer to the B-tree header */ + H5RC_t *bt2_shared = NULL; /* Pointer to ref-counter for shared B-tree info */ H5B2_shared_t *shared; /* Pointer to B-tree's shared information */ - hbool_t incr_rc=FALSE; /* Flag to indicate that we've incremented the B-tree's shared info reference count */ + hbool_t incr_rc = FALSE; /* Flag to indicate that we've incremented the B-tree's shared info reference count */ H5B2_node_ptr_t curr_node_ptr; /* Node pointer info for current node */ unsigned depth; /* Current depth of the tree */ int cmp; /* Comparison value of records */ @@ -346,16 +346,16 @@ H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr, HDassert(H5F_addr_defined(addr)); /* Look up the B-tree header */ - if (NULL == (bt2 = H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, addr, type, NULL, H5AC_READ))) + if(NULL == (bt2 = H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, addr, type, NULL, H5AC_READ))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree header") /* Safely grab pointer to reference counted shared B-tree info, so we can release the B-tree header if necessary */ - bt2_shared=bt2->shared; + bt2_shared = bt2->shared; H5RC_INC(bt2_shared); - incr_rc=TRUE; + incr_rc = TRUE; /* Get the pointer to the shared B-tree info */ - shared=H5RC_GET_OBJ(bt2_shared); + shared = H5RC_GET_OBJ(bt2_shared); HDassert(shared); /* Make copy of the root node pointer to start search with */ @@ -370,7 +370,7 @@ H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr, bt2 = NULL; /* Check for empty tree */ - if(curr_node_ptr.node_nrec==0) + if(curr_node_ptr.node_nrec == 0) HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "B-tree has no records") /* Walk down B-tree to find record or leaf node where record is located */ diff --git a/src/H5Oattribute.c b/src/H5Oattribute.c index 7d22319..7d5e496 100644 --- a/src/H5Oattribute.c +++ b/src/H5Oattribute.c @@ -143,7 +143,7 @@ typedef struct { /*------------------------------------------------------------------------- - * Function: H5O_msg_attr_to_dense_cb + * Function: H5O_attr_to_dense_cb * * Purpose: Object header iterator callback routine to convert compact * attributes to dense attributes @@ -157,13 +157,13 @@ typedef struct { *------------------------------------------------------------------------- */ static herr_t -H5A_attr_to_dense_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/, +H5O_attr_to_dense_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/, unsigned UNUSED sequence, unsigned *oh_flags_ptr, void *_udata/*in,out*/) { H5O_iter_cvt_t *udata = (H5O_iter_cvt_t *)_udata; /* Operator user data */ herr_t ret_value = H5_ITER_CONT; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5A_attr_to_dense_cb) + FUNC_ENTER_NOAPI_NOINIT(H5O_attr_to_dense_cb) /* check args */ HDassert(oh); @@ -182,7 +182,7 @@ H5A_attr_to_dense_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/, done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5A_attr_to_dense_cb() */ +} /* end H5O_attr_to_dense_cb() */ /*------------------------------------------------------------------------- @@ -248,7 +248,7 @@ HDfprintf(stderr, "%s: converting attributes to dense storage\n", FUNC); /* Iterate over existing attributes, moving them to dense storage */ /* XXX: Test this with shared attributes */ - op.lib_op = H5A_attr_to_dense_cb; + op.lib_op = H5O_attr_to_dense_cb; if(H5O_msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, TRUE, op, &udata, dxpl_id, &oh_flags) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTCONVERT, FAIL, "error converting attributes to dense storage") } /* end if */ @@ -936,6 +936,7 @@ H5O_attr_remove_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/, /* check args */ HDassert(oh); HDassert(mesg); + HDassert(!udata->found); /* Check for shared message */ if(mesg->flags & H5O_MSG_FLAG_SHARED) { @@ -1151,3 +1152,131 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_attr_count */ + +/*------------------------------------------------------------------------- + * Function: H5O_attr_exists_cb + * + * Purpose: Object header iterator callback routine to check for an + * attribute stored compactly, by name. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Dec 11 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_attr_exists_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/, + unsigned UNUSED sequence, unsigned UNUSED *oh_flags_ptr, void *_udata/*in,out*/) +{ + H5O_iter_rm_t *udata = (H5O_iter_rm_t *)_udata; /* Operator user data */ + herr_t ret_value = H5_ITER_CONT; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_attr_exists_cb) + + /* check args */ + HDassert(oh); + HDassert(mesg); + HDassert(!udata->found); + + /* Check for shared message */ + if(mesg->flags & H5O_MSG_FLAG_SHARED) { + H5A_t shared_attr; /* Copy of shared attribute */ + + /* + * If the message is shared then then the native pointer points to an + * H5O_MSG_SHARED message. We use that information to look up the real + * message in the global heap or some other object header. + */ + if(NULL == H5O_shared_read(udata->f, udata->dxpl_id, mesg->native, H5O_MSG_ATTR, &shared_attr)) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, H5_ITER_ERROR, "unable to read shared attribute") + + /* Check for correct attribute message */ + if(HDstrcmp(shared_attr.name, udata->name) == 0) + /* Indicate that this message is the attribute sought */ + udata->found = TRUE; + + /* Release copy of shared attribute */ + H5O_attr_reset(&shared_attr); + } /* end if */ + else { + /* Check for correct attribute message */ + if(HDstrcmp(((H5A_t *)mesg->native)->name, udata->name) == 0) + /* Indicate that this message is the attribute sought */ + udata->found = TRUE; + } /* end else */ + + /* Check for finding correct message to delete */ + if(udata->found) { + /* Stop iterating */ + ret_value = H5_ITER_STOP; + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_attr_exists_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_attr_exists + * + * Purpose: Determine if an attribute with a particular name exists on an object + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Monday, December 11, 2006 + * + *------------------------------------------------------------------------- + */ +htri_t +H5O_attr_exists(const H5O_loc_t *loc, const char *name, hid_t dxpl_id) +{ + H5O_t *oh = NULL; /* Pointer to actual object header */ + unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */ + htri_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_attr_exists) + + /* Check arguments */ + HDassert(loc); + HDassert(name); + + /* Protect the object header to iterate over */ + if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ))) + HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, FAIL, "unable to load object header") + + /* Check for attributes stored densely */ + if(H5F_addr_defined(oh->attr_fheap_addr)) { + /* Check if attribute exists in dense storage */ + if((ret_value = H5A_dense_exists(loc->file, dxpl_id, oh, name)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_BADITER, FAIL, "error checking for existence of attribute") + } /* end if */ + else { + H5O_iter_rm_t udata; /* User data for callback */ + H5O_mesg_operator_t op; /* Wrapper for operator */ + + /* Set up user data for callback */ + udata.f = loc->file; + udata.dxpl_id = dxpl_id; + udata.name = name; + udata.found = FALSE; + + /* Iterate over existing attributes, checking for attribute with same name */ + op.lib_op = H5O_attr_exists_cb; + if(H5O_msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, TRUE, op, &udata, dxpl_id, &oh_flags) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_BADITER, FAIL, "error checking for existence of attribute") + + /* Check that we found the attribute */ + ret_value = udata.found; + } /* end else */ + +done: + if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_ATTR, H5E_PROTECT, FAIL, "unable to release object header") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_attr_exists */ + diff --git a/src/H5Opkg.h b/src/H5Opkg.h index 07ccdd4..e0c7292 100644 --- a/src/H5Opkg.h +++ b/src/H5Opkg.h @@ -432,6 +432,7 @@ H5_DLL herr_t H5O_attr_iterate(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id H5_DLL herr_t H5O_attr_remove(const H5O_loc_t *loc, const char *name, hid_t dxpl_id); H5_DLL int H5O_attr_count(const H5O_loc_t *loc, hid_t dxpl_id); +H5_DLL htri_t H5O_attr_exists(const H5O_loc_t *loc, const char *name, hid_t dxpl_id); /* These functions operate on object locations */ H5_DLL H5O_loc_t *H5O_get_loc(hid_t id); |