From 14e9b46ca21d49e2c3f3b670d4fbf72d7ce14d90 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Fri, 8 Dec 2006 17:05:52 -0500 Subject: [PATCH] [svn-r13037] Description: Move attribute creation code out of H5Omessage.c and into H5Oattr.c Tested on: FreeBSD/32 4.11 (sleipnir) --- src/H5A.c | 19 +++--- src/H5Oattr.c | 146 ++++++++++++++++++++++++++++++++++++++++++ src/H5Omessage.c | 162 +++++++++++++++-------------------------------- src/H5Opkg.h | 3 + src/H5Oprivate.h | 1 + 5 files changed, 210 insertions(+), 121 deletions(-) diff --git a/src/H5A.c b/src/H5A.c index 52bce59ccc..d4ca21b3fc 100644 --- a/src/H5A.c +++ b/src/H5A.c @@ -237,6 +237,8 @@ H5Acreate(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id, HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") if(H5G_loc(loc_id, &loc) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(0 == (H5F_INTENT(loc.oloc->file) & H5F_ACC_RDWR)) + HGOTO_ERROR(H5E_ARGS, H5E_WRITEERROR, FAIL, "no write intent on file") if(!name || !*name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE))) @@ -322,8 +324,7 @@ H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type, /* If the creation property list is H5P_DEFAULT, use the default character encoding */ if(acpl_id == H5P_DEFAULT) attr->encoding = H5F_DEFAULT_CSET; - else - { + else { /* Get a local copy of the attribute creation property list */ if (NULL == (ac_plist = H5I_object(acpl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") @@ -415,9 +416,9 @@ 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 and save the attribute index */ - if(H5O_msg_create(&(attr->oloc), H5O_ATTR_ID, 0, H5O_UPDATE_TIME, attr, dxpl_id) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to update attribute header messages") + /* Create the attribute message */ + if(H5O_attr_create(&(attr->oloc), dxpl_id, attr) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to create attribute in object header") /* Register the new attribute and get an ID for it */ if((ret_value = H5I_register(H5I_ATTR, attr)) < 0) @@ -427,10 +428,10 @@ H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type, attr->initialized = FALSE; done: - if(ret_value < 0) { + /* Cleanup on failure */ + if(ret_value < 0) if(attr) (void)H5A_close(attr); - } /* end if */ FUNC_LEAVE_NOAPI(ret_value) } /* H5A_create() */ @@ -680,10 +681,10 @@ H5A_open(H5G_loc_t *loc, unsigned idx, hid_t dxpl_id) HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register attribute for ID") done: - if(ret_value < 0) { + /* Cleanup on failure */ + if(ret_value < 0) if(attr) (void)H5A_close(attr); - } /* end if */ FUNC_LEAVE_NOAPI(ret_value) } /* H5A_open() */ diff --git a/src/H5Oattr.c b/src/H5Oattr.c index 617614e2ee..9e22011415 100644 --- a/src/H5Oattr.c +++ b/src/H5Oattr.c @@ -29,6 +29,12 @@ #include "H5Spkg.h" /* Dataspaces */ #include "H5SMprivate.h" /* Shared Object Header Messages */ +/* User data for iteration when converting attributes to dense storage */ +typedef struct { + H5F_t *f; /* Pointer to file for insertion */ + hid_t dxpl_id; /* DXPL during iteration */ +} H5O_iter_cvt_t; + /* User data for iteration when updating an attribute */ typedef struct { /* down */ @@ -1265,6 +1271,146 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_attr_debug() */ + +/*------------------------------------------------------------------------- + * Function: H5O_msg_attr_to_dense_cb + * + * Purpose: Object header iterator callback routine to convert compact + * attributes to dense attributes + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Dec 4 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5A_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) + + /* check args */ + HDassert(oh); + HDassert(mesg); + + /* Insert attribute into dense storage */ + if(H5A_dense_insert(udata->f, udata->dxpl_id, oh, mesg->flags, mesg->native) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, H5_ITER_ERROR, "unable to add to dense storage") + + /* Convert message into a null message */ + if(H5O_release_mesg(udata->f, udata->dxpl_id, oh, mesg, TRUE, FALSE) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, H5_ITER_ERROR, "unable to convert into null message") + + /* Indicate that the object header was modified */ + *oh_flags_ptr |= H5AC__DIRTIED_FLAG; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5A_attr_to_dense_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_attr_create + * + * Purpose: Create a new attribute in the object header. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Friday, December 8, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr) +{ + H5O_t *oh = NULL; /* Pointer to actual object header */ + unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */ + unsigned mesg_flags = 0; /* Flags for storing message */ + htri_t shared_mesg; /* Should this message be stored in the Shared Message table? */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_attr_create) + + /* Check arguments */ + HDassert(loc); + HDassert(attr); + + /* Should this message be written as a SOHM? */ + if((shared_mesg = H5SM_try_share(loc->file, dxpl_id, H5O_ATTR_ID, attr)) > 0) + /* Mark the message as shared */ + mesg_flags |= H5O_MSG_FLAG_SHARED; + else if(shared_mesg < 0) + HGOTO_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL, "error determining if message should be shared") + + /* Protect the object header to iterate over */ + if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE))) + HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, FAIL, "unable to load object header") + +#ifdef QAK +HDfprintf(stderr, "%s: adding attribute to new-style object header\n", FUNC); +HDfprintf(stderr, "%s: oh->nattrs = %Hu\n", FUNC, oh->nattrs); +HDfprintf(stderr, "%s: oh->max_compact = %u\n", FUNC, oh->max_compact); +HDfprintf(stderr, "%s: oh->min_dense = %u\n", FUNC, oh->min_dense); +#endif /* QAK */ + /* Check for switching to "dense" attribute storage */ + if(oh->version > H5O_VERSION_1 && oh->nattrs == oh->max_compact && + !H5F_addr_defined(oh->attr_fheap_addr)) { + H5O_iter_cvt_t udata; /* User data for callback */ + H5O_mesg_operator_t op; /* Wrapper for operator */ +#ifdef QAK +HDfprintf(stderr, "%s: converting attributes to dense storage\n", FUNC); +#endif /* QAK */ + + /* Create dense storage for attributes */ + if(H5A_dense_create(loc->file, dxpl_id, oh) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to create dense storage for attributes") + + /* Set up user data for callback */ + udata.f = loc->file; + udata.dxpl_id = dxpl_id; + + /* Iterate over existing attributes, moving them to dense storage */ + op.lib_op = H5A_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 */ + + /* Increment attribute count */ + oh->nattrs++; + + /* Check for storing attribute with dense storage */ + if(H5F_addr_defined(oh->attr_fheap_addr)) { + /* Insert attribute into dense storage */ +#ifdef QAK +HDfprintf(stderr, "%s: inserting attribute to dense storage\n", FUNC); +#endif /* QAK */ + if(H5A_dense_insert(loc->file, dxpl_id, oh, mesg_flags, attr) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to add to dense storage") + } /* end if */ + else { + /* Append new message to object header */ + if(H5O_msg_append_real(loc->file, dxpl_id, oh, H5O_MSG_ATTR, mesg_flags, 0, attr, &oh_flags) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to create new attribute in header") + } /* end else */ + + /* Update the modification time, if any */ + if(H5O_touch_oh(loc->file, dxpl_id, oh, FALSE, &oh_flags) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update time on object") + +done: + if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0) + HDONE_ERROR(H5E_ATTR, H5E_PROTECT, FAIL, "unable to release object header") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_attr_create */ + /*------------------------------------------------------------------------- * Function: H5O_attr_write_cb diff --git a/src/H5Omessage.c b/src/H5Omessage.c index b7bc47d189..1dbe8ffffd 100644 --- a/src/H5Omessage.c +++ b/src/H5Omessage.c @@ -79,12 +79,6 @@ typedef struct { hbool_t adj_link; /* Whether to adjust links when removing messages */ } H5O_iter_rm_t; -/* User data for iteration when converting attributes to dense storage */ -typedef struct { - H5F_t *f; /* Pointer to file for insertion */ - hid_t dxpl_id; /* DXPL during iteration */ -} H5O_iter_to_dense_t; - /********************/ /* Package Typedefs */ @@ -135,8 +129,7 @@ static herr_t H5O_write_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx, * * Purpose: Create a new object header message * - * Return: Success: The sequence number of the message that - * was created. + * Return: Success: Non-negative * * Failure: Negative * @@ -181,49 +174,6 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_msg_create() */ - -/*------------------------------------------------------------------------- - * Function: H5O_msg_attr_to_dense_cb - * - * Purpose: Object header iterator callback routine to convert compact - * attributes to dense attributes - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@hdfgroup.org - * Dec 4 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5O_msg_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_to_dense_t *udata = (H5O_iter_to_dense_t *)_udata; /* Operator user data */ - herr_t ret_value = H5_ITER_CONT; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5O_msg_attr_to_dense_cb) - - /* check args */ - HDassert(oh); - HDassert(mesg); - - /* Insert attribute into dense storage */ - if(H5A_dense_insert(udata->f, udata->dxpl_id, oh, mesg->flags, mesg->native) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, H5_ITER_ERROR, "unable to add to dense storage") - - /* Convert message into a null message */ - if(H5O_release_mesg(udata->f, udata->dxpl_id, oh, mesg, TRUE, FALSE) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, H5_ITER_ERROR, "unable to convert into null message") - - /* Indicate that the object header was modified */ - *oh_flags_ptr |= H5AC__DIRTIED_FLAG; - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5O_msg_attr_to_dense_cb() */ - /*------------------------------------------------------------------------- * Function: H5O_msg_append @@ -232,8 +182,7 @@ done: * object header message (usually during object creation) and * several messages will be added to the object header at once. * - * Return: Success: The sequence number of the message that - * was created. + * Return: Success: Non-negative * * Failure: Negative * @@ -248,12 +197,7 @@ H5O_msg_append(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id, unsigned mesg_flags, unsigned update_flags, void *mesg, unsigned *oh_flags_ptr) { - const H5O_msg_class_t *new_type; /* Actual H5O class type for the ID */ - const void *new_mesg; /* Actual message to write */ const H5O_msg_class_t *type; /* Original H5O class type for the ID */ - H5O_shared_t sh_mesg; /* Shared object header info */ - unsigned idx; /* Index of message to modify */ - hbool_t new_format_attr; /* Whether this message is an attribute in a new-format header */ htri_t shared_mesg; /* Should this message be stored in the Shared Message table? */ herr_t ret_value = SUCCEED; /* Return value */ @@ -262,6 +206,7 @@ H5O_msg_append(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id, /* check args */ HDassert(f); HDassert(oh); + HDassert(H5O_ATTR_ID != type_id); /* Attributes are modified in another routine */ 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); @@ -276,72 +221,65 @@ H5O_msg_append(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id, else if(shared_mesg < 0) HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "error determining if message should be shared") - /* Set the flag for an attribute in a new format header */ - if(H5O_ATTR_ID == type_id && oh->version > H5O_VERSION_1) - new_format_attr = TRUE; - else - new_format_attr = FALSE; + /* Append new message to object header */ + if(H5O_msg_append_real(f, dxpl_id, oh, type, mesg_flags, update_flags, mesg, oh_flags_ptr) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to create new message in header") - /* If the message added is an attribute, check for dense storage */ - if(new_format_attr) { -#ifdef QAK -HDfprintf(stderr, "%s: adding attribute to new-style object header\n", FUNC); -HDfprintf(stderr, "%s: oh->nattrs = %Hu\n", FUNC, oh->nattrs); -HDfprintf(stderr, "%s: oh->max_compact = %u\n", FUNC, oh->max_compact); -HDfprintf(stderr, "%s: oh->min_dense = %u\n", FUNC, oh->min_dense); -#endif /* QAK */ - /* Check for switching to "dense" attribute storage */ - if(oh->nattrs == oh->max_compact && !H5F_addr_defined(oh->attr_fheap_addr)) { - H5O_iter_to_dense_t udata; /* User data for callback */ - H5O_mesg_operator_t op; /* Wrapper for operator */ -#ifdef QAK -HDfprintf(stderr, "%s: converting attributes to dense storage\n", FUNC); -#endif /* QAK */ +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_msg_append() */ - /* Create dense storage for attributes */ - if(H5A_dense_create(f, dxpl_id, oh) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to create dense storage for attributes") + +/*------------------------------------------------------------------------- + * Function: H5O_msg_append_real + * + * Purpose: Append a new message to an object header. + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Dec 8 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_msg_append_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_msg_class_t *type, + unsigned mesg_flags, unsigned update_flags, void *mesg, + unsigned *oh_flags_ptr) +{ + const H5O_msg_class_t *new_type; /* Actual H5O class type for the ID */ + const void *new_mesg; /* Actual message to write */ + H5O_shared_t sh_mesg; /* Shared object header info */ + unsigned idx; /* Index of message to modify */ + herr_t ret_value = SUCCEED; /* Return value */ - /* Set up user data for callback */ - udata.f = f; - udata.dxpl_id = dxpl_id; + FUNC_ENTER_NOAPI(H5O_msg_append_real, FAIL) - /* Iterate over existing attributes, moving them to dense storage */ - op.lib_op = H5O_msg_attr_to_dense_cb; - if(H5O_msg_iterate_real(f, oh, H5O_MSG_ATTR, TRUE, op, &udata, dxpl_id, oh_flags_ptr) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTCONVERT, FAIL, "error converting attributes to dense storage") - } /* end if */ - } /* end if */ + /* check args */ + HDassert(f); + HDassert(oh); + HDassert(type); + HDassert(0 == (mesg_flags & ~H5O_MSG_FLAG_BITS)); + HDassert(mesg); + HDassert(oh_flags_ptr); - /* Check for storing attribute with dense storage */ - if(new_format_attr && H5F_addr_defined(oh->attr_fheap_addr)) { - /* Insert attribute into dense storage */ -#ifdef QAK -HDfprintf(stderr, "%s: inserting attribute to dense storage\n", FUNC); -#endif /* QAK */ - if(H5A_dense_insert(f, dxpl_id, oh, mesg_flags, mesg) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "unable to add to dense storage") - } /* end if */ - else { - /* Create a new message */ - if((idx = H5O_new_mesg(f, oh, &mesg_flags, type, mesg, &sh_mesg, &new_type, &new_mesg, dxpl_id, oh_flags_ptr)) == UFAIL) - HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, FAIL, "unable to create new message") + /* Create a new message */ + if((idx = H5O_new_mesg(f, oh, &mesg_flags, type, mesg, &sh_mesg, &new_type, &new_mesg, dxpl_id, oh_flags_ptr)) == UFAIL) + HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, FAIL, "unable to create new message") - /* Write the information to the message */ - if(H5O_write_mesg(f, dxpl_id, oh, idx, new_type, new_mesg, mesg_flags, update_flags, oh_flags_ptr) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to write message") - } /* end else */ - - /* If the message added is an attribute, increment count */ - if(new_format_attr) - oh->nattrs++; + /* Write the information to the message */ + if(H5O_write_mesg(f, dxpl_id, oh, idx, new_type, new_mesg, mesg_flags, update_flags, oh_flags_ptr) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to write message") #ifdef H5O_DEBUG H5O_assert(oh); #endif /* H5O_DEBUG */ done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5O_msg_append() */ +} /* end H5O_msg_append_real() */ /*------------------------------------------------------------------------- diff --git a/src/H5Opkg.h b/src/H5Opkg.h index f3a2df00d7..eea0102b36 100644 --- a/src/H5Opkg.h +++ b/src/H5Opkg.h @@ -392,6 +392,9 @@ H5_DLL herr_t H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_mesg_t *mesg, H5_DLL const H5O_obj_class_t *H5O_obj_class_real(H5O_t *oh); /* Object header message routines */ +H5_DLL herr_t H5O_msg_append_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, + const H5O_msg_class_t *type, unsigned mesg_flags, unsigned update_flags, + void *mesg, unsigned *oh_flags_ptr); H5_DLL void *H5O_msg_read_real(H5F_t *f, H5O_t *oh, unsigned type_id, int sequence, void *mesg, hid_t dxpl_id); H5_DLL void *H5O_msg_free_real(const H5O_msg_class_t *type, void *mesg); diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index 568a6ee699..e578377e6e 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -464,6 +464,7 @@ H5_DLL herr_t H5O_fill_convert(void *_fill, H5T_t *type, hid_t dxpl_id); H5_DLL herr_t H5O_link_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link); /* Attribute operations */ +H5_DLL herr_t H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, struct H5A_t *attr); H5_DLL herr_t H5O_attr_write(const H5O_loc_t *loc, hid_t dxpl_id, struct H5A_t *attr); H5_DLL herr_t H5O_attr_rename(const H5O_loc_t *loc, hid_t dxpl_id,