From a15089ee73ddf92468de1af48babd7f55d9e5b16 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Wed, 3 Jan 2007 14:34:15 -0500 Subject: [svn-r13104] Description: Add support for renaming compact & dense/shared & non-shared attributes in all cases. Tested on: Linux/32 2.6 (chicago) Linux/64 2.6 (chicago2) --- src/H5A.c | 8 +- src/H5Abtree2.c | 13 ++- src/H5Adense.c | 208 ++++++++++++++++++++++++++++----------------- src/H5Aint.c | 8 +- src/H5Apkg.h | 2 + src/H5Oattr.c | 18 ++-- src/H5Oattribute.c | 63 +++++++++----- test/tattr.c | 245 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 8 files changed, 443 insertions(+), 122 deletions(-) diff --git a/src/H5A.c b/src/H5A.c index 6021c21..e10dd39 100644 --- a/src/H5A.c +++ b/src/H5A.c @@ -331,7 +331,7 @@ H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type, 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 = (H5P_genplist_t *)H5I_object(acpl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") if(H5P_get(ac_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &(attr->encoding)) < 0) @@ -1142,15 +1142,15 @@ H5Aget_create_plist(hid_t attr_id) HDassert(H5P_LST_ATTRIBUTE_CREATE_g != -1); /* Get attribute and default attribute creation property list*/ - if(NULL == (attr = H5I_object_verify(attr_id, H5I_ATTR))) + if(NULL == (attr = (H5A_t *)H5I_object_verify(attr_id, H5I_ATTR))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute") - if(NULL == (plist = H5I_object(H5P_LST_ATTRIBUTE_CREATE_g))) + if(NULL == (plist = (H5P_genplist_t *)H5I_object(H5P_LST_ATTRIBUTE_CREATE_g))) HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "can't get default ACPL") /* Create the property list object to return */ if((new_plist_id = H5P_copy_plist(plist)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "unable to copy attribute creation properties") - if(NULL == (new_plist = H5I_object(new_plist_id))) + if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(new_plist_id))) HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "can't get property list") /* Set the character encoding on the new property list */ diff --git a/src/H5Abtree2.c b/src/H5Abtree2.c index dc2478e..5fb37fe 100644 --- a/src/H5Abtree2.c +++ b/src/H5Abtree2.c @@ -36,6 +36,7 @@ #include "H5private.h" /* Generic Functions */ #include "H5Apkg.h" /* Attributes */ #include "H5Eprivate.h" /* Error handling */ +#include "H5SMprivate.h" /* Shared object header messages */ /****************/ @@ -56,6 +57,7 @@ typedef struct H5A_fh_ud_cmp_t { H5F_t *f; /* Pointer to file that fractal heap is in */ hid_t dxpl_id; /* DXPL for operation */ const char *name; /* Name of attribute to compare */ + const H5A_dense_bt2_name_rec_t *record; /* v2 B-tree record for attribute */ H5B2_found_t found_op; /* Callback when correct attribute is found */ void *found_op_data; /* Callback data when correct attribute is found */ @@ -141,16 +143,22 @@ H5A_dense_fh_name_cmp(const void *obj, size_t UNUSED obj_len, void *_udata) FUNC_ENTER_NOAPI_NOINIT(H5A_dense_fh_name_cmp) /* Decode link information */ - if(NULL == (attr = H5O_msg_decode(udata->f, udata->dxpl_id, H5O_ATTR_ID, obj))) + if(NULL == (attr = (H5A_t *)H5O_msg_decode(udata->f, udata->dxpl_id, H5O_ATTR_ID, (const unsigned char *)obj))) HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "can't decode attribute") /* Compare the string values */ udata->cmp = HDstrcmp(udata->name, attr->name); /* Check for correct attribute & callback to make */ - if(udata->cmp == 0 && udata->found_op) + 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); + + /* Make callback */ if((udata->found_op)(attr, udata->found_op_data) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTOPERATE, FAIL, "attribute found callback failed") + } /* end if */ done: /* Release the space allocated for the attrbute */ @@ -260,6 +268,7 @@ H5A_dense_btree2_name_compare(const void *_bt2_udata, const void *_bt2_rec) fh_udata.f = bt2_udata->f; fh_udata.dxpl_id = bt2_udata->dxpl_id; fh_udata.name = bt2_udata->name; + fh_udata.record = bt2_rec; fh_udata.found_op = bt2_udata->found_op; fh_udata.found_op_data = bt2_udata->found_op_data; diff --git a/src/H5Adense.c b/src/H5Adense.c index f47f9c0..9d9746a 100644 --- a/src/H5Adense.c +++ b/src/H5Adense.c @@ -75,7 +75,7 @@ /* * Data exchange structure for dense attribute storage. This structure is - * passed through the v2 B-tree layer when modifying attributes. + * passed through the v2 B-tree layer when modifying the attribute data value. */ typedef struct H5A_bt2_od_wrt_t { /* downward */ @@ -117,6 +117,7 @@ typedef struct { /* downward (internal) */ H5F_t *f; /* Pointer to file that fractal heap is in */ hid_t dxpl_id; /* DXPL for operation */ + const H5A_dense_bt2_name_rec_t *record; /* v2 B-tree record for attribute */ /* upward */ H5A_t *attr; /* Copy of attribute */ @@ -264,7 +265,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5A_dense_open_cb + * Function: H5A_dense_fnd_cb * * Purpose: Callback when an attribute is located in an index * @@ -277,13 +278,13 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5A_dense_open_cb(const void *_attr, void *_user_attr) +H5A_dense_fnd_cb(const void *_attr, void *_user_attr) { const H5A_t *attr = (const H5A_t *)_attr; /* Record from B-tree */ H5A_t **user_attr = (H5A_t **)_user_attr; /* User data from v2 B-tree attribute lookup */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5A_dense_open_cb) + FUNC_ENTER_NOAPI_NOINIT(H5A_dense_fnd_cb) /* * Check arguments. @@ -297,7 +298,7 @@ H5A_dense_open_cb(const void *_attr, void *_user_attr) done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5A_dense_open_cb() */ +} /* end H5A_dense_fnd_cb() */ /*------------------------------------------------------------------------- @@ -361,7 +362,7 @@ H5A_dense_open(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *name) udata.name_hash = H5_checksum_lookup3(name, HDstrlen(name), 0); udata.flags = 0; udata.corder = -1; /* XXX: None yet */ - udata.found_op = H5A_dense_open_cb; /* v2 B-tree comparison callback */ + udata.found_op = H5A_dense_fnd_cb; /* v2 B-tree comparison callback */ udata.found_op_data = &ret_value; /* Find & copy the attribute in the 'name' index */ @@ -720,12 +721,123 @@ H5A_dense_copy_fh_cb(const void *obj, size_t UNUSED obj_len, void *_udata) if(NULL == (udata->attr = (H5A_t *)H5O_msg_decode(udata->f, udata->dxpl_id, H5O_ATTR_ID, (const unsigned char *)obj))) HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, FAIL, "can't decode attribute") + /* 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); + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5A_dense_copy_fh_cb() */ /*------------------------------------------------------------------------- + * Function: H5A_dense_rename + * + * Purpose: Rename an attribute in dense storage structures for an object + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Jan 3 2007 + * + *------------------------------------------------------------------------- + */ +herr_t +H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *old_name, + const char *new_name) +{ + H5A_bt2_ud_common_t udata; /* User data for v2 B-tree modify */ + H5HF_t *fheap = NULL; /* Fractal heap handle */ + H5HF_t *shared_fheap = NULL; /* Fractal heap handle for shared header messages */ + H5A_t *attr_copy = NULL; /* Copy of attribute to rename */ + htri_t attr_sharable; /* Flag indicating attributes are sharable */ + 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(H5A_dense_rename, FAIL) + + /* + * Check arguments. + */ + HDassert(f); + HDassert(oh); + HDassert(old_name); + HDassert(new_name); + + /* Check if attributes are shared in this file */ + if((attr_sharable = H5SM_type_shared(f, H5O_ATTR_ID, dxpl_id)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't determine if attributes are shared") + + /* Get handle for shared object heap, if attributes are sharable */ + if(attr_sharable) { + haddr_t shared_fheap_addr; /* Address of fractal heap to use */ + + /* Retrieve the address of the shared object's fractal heap */ + if(HADDR_UNDEF == (shared_fheap_addr = H5SM_get_fheap_addr(f, H5O_ATTR_ID, dxpl_id))) + HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get shared object heap address") + + /* Open the fractal heap for shared header messages */ + if(NULL == (shared_fheap = H5HF_open(f, dxpl_id, shared_fheap_addr))) + HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap") + } /* end if */ + + /* 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 modify */ + udata.f = f; + udata.dxpl_id = dxpl_id; + udata.fheap = fheap; + udata.shared_fheap = shared_fheap; + udata.name = old_name; + udata.name_hash = H5_checksum_lookup3(old_name, HDstrlen(old_name), 0); + udata.flags = 0; + udata.corder = -1; /* XXX: None yet */ + udata.found_op = H5A_dense_fnd_cb; /* v2 B-tree comparison callback */ + udata.found_op_data = &attr_copy; + + /* Get copy of attribute through 'name' tracking v2 B-tree */ + if(H5B2_find(f, dxpl_id, H5A_BT2_NAME, oh->name_bt2_addr, &udata, NULL, NULL) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to find record in v2 B-tree") + HDassert(attr_copy); + + /* Change name of attribute */ + H5MM_xfree(attr_copy->name); + attr_copy->name = H5MM_xstrdup(new_name); + + /* Should this attribute be written as a SOHM? */ + /* (allows for attributes that change "shared" status) */ + if((shared_mesg = H5SM_try_share(f, dxpl_id, H5O_ATTR_ID, attr_copy)) > 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") + + /* Insert renamed attribute back into dense storage */ + if(H5A_dense_insert(f, dxpl_id, oh, mesg_flags, attr_copy) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to add to dense storage") + + /* Delete old attribute from dense storage */ + if(H5A_dense_remove(f, dxpl_id, oh, old_name) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute in dense storage") + +done: + /* Release resources */ + if(shared_fheap && H5HF_close(shared_fheap, dxpl_id) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap") + if(fheap && H5HF_close(fheap, dxpl_id) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap") + if(attr_copy) + H5O_msg_free(H5O_ATTR_ID, attr_copy); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5A_dense_write() */ + + +/*------------------------------------------------------------------------- * Function: H5A_dense_iterate_bt2_cb * * Purpose: v2 B-tree callback for dense attribute storage iterator @@ -764,16 +876,14 @@ H5A_dense_iterate_bt2_cb(const void *_record, void *_bt2_udata) /* down */ fh_udata.f = bt2_udata->f; fh_udata.dxpl_id = bt2_udata->dxpl_id; + fh_udata.record = record; + fh_udata.attr = NULL; /* Call fractal heap 'op' routine, to copy the attribute information */ if(H5HF_op(fheap, bt2_udata->dxpl_id, record->id, H5A_dense_copy_fh_cb, &fh_udata) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTOPERATE, H5_ITER_ERROR, "heap op callback failed") - /* Check whether we should "reconstitute" the shared message info */ - if(record->flags & H5O_MSG_FLAG_SHARED) - H5SM_reconstitute(&(fh_udata.attr->sh_loc), record->id); - /* Check which type of callback to make */ switch(bt2_udata->attr_op->op_type) { case H5A_ATTR_OP_APP: @@ -922,46 +1032,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5A_dense_remove_fh_cb - * - * Purpose: Callback for fractal heap operator when removing attributes - * - * Return: SUCCEED/FAIL - * - * Programmer: Quincey Koziol - * koziol@hdfgroup.org - * Dec 11 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5A_dense_remove_fh_cb(const void *obj, size_t UNUSED obj_len, void *_udata) -{ - H5A_fh_ud_rm_t *udata = (H5A_fh_ud_rm_t *)_udata; /* User data for fractal heap 'op' callback */ - H5A_t *attr = NULL; /* Pointer to attribute created from heap object */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5A_dense_remove_fh_cb) - - /* Decode attribute */ - if(NULL == (attr = (H5A_t *)H5O_msg_decode(udata->f, udata->dxpl_id, H5O_ATTR_ID, (const unsigned char *)obj))) - HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, FAIL, "can't decode attribute") - - /* Perform the deletion action on the attribute */ - /* (takes care of shared & committed datatype/dataspace components) */ - if(H5O_attr_delete(udata->f, udata->dxpl_id, attr, TRUE) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute") - -done: - /* Release the space allocated for the message */ - if(attr) - H5O_msg_free_real(H5O_MSG_ATTR, attr); - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5A_dense_remove_fh_cb() */ - - -/*------------------------------------------------------------------------- * Function: H5A_dense_remove_bt2_cb * * Purpose: v2 B-tree callback for dense attribute storage record removal @@ -985,41 +1055,21 @@ H5A_dense_remove_bt2_cb(const void *_record, void *_bt2_udata) /* Check for inserting shared attribute */ if(record->flags & H5O_MSG_FLAG_SHARED) { - H5A_fh_ud_cp_t fh_udata; /* User data for fractal heap 'op' callback */ H5O_shared_t sh_mesg; /* Shared object header message */ - /* Set up the user data for fractal heap 'op' callback */ - fh_udata.f = bt2_udata->f; - fh_udata.dxpl_id = bt2_udata->dxpl_id; - fh_udata.attr = NULL; - - /* Call fractal heap 'op' routine, to get copy of the attribute */ - if(H5HF_op(bt2_udata->shared_fheap, bt2_udata->dxpl_id, record->id, - H5A_dense_copy_fh_cb, &fh_udata) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTOPERATE, FAIL, "attribute removal callback failed") - /* Get the shared information for the attribute */ - if(NULL == H5O_attr_get_share(fh_udata.attr, &sh_mesg)) + if(NULL == H5O_attr_get_share(*(H5A_t **)bt2_udata->found_op_data, &sh_mesg)) HGOTO_ERROR(H5E_ATTR, H5E_BADMESG, FAIL, "can't get shared message") /* 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) HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to delete shared attribute") - - /* Release the space allocated for the attribute */ - H5O_msg_free(H5O_ATTR_ID, fh_udata.attr); } /* end if */ else { - H5A_fh_ud_rm_t fh_udata; /* User data for fractal heap 'op' callback */ - - /* Set up the user data for fractal heap 'op' callback */ - fh_udata.f = bt2_udata->f; - fh_udata.dxpl_id = bt2_udata->dxpl_id; - - /* Call fractal heap 'op' routine, to perform user callback */ - if(H5HF_op(bt2_udata->fheap, bt2_udata->dxpl_id, record->id, - H5A_dense_remove_fh_cb, &fh_udata) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTOPERATE, FAIL, "attribute removal callback failed") + /* 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, *(H5A_t **)bt2_udata->found_op_data, TRUE) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute") /* Remove record from fractal heap */ if(H5HF_remove(bt2_udata->fheap, bt2_udata->dxpl_id, record->id) < 0) @@ -1050,6 +1100,7 @@ H5A_dense_remove(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 record removal */ H5HF_t *fheap = NULL; /* Fractal heap handle */ H5HF_t *shared_fheap = NULL; /* Fractal heap handle for shared header messages */ + H5A_t *attr_copy = NULL; /* Copy of attribute to remove */ htri_t attr_sharable; /* Flag indicating attributes are sharable */ herr_t ret_value = SUCCEED; /* Return value */ @@ -1092,8 +1143,8 @@ H5A_dense_remove(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *name) udata.name_hash = H5_checksum_lookup3(name, HDstrlen(name), 0); udata.flags = 0; udata.corder = -1; /* XXX: None yet */ - udata.found_op = NULL; - udata.found_op_data = NULL; + udata.found_op = H5A_dense_fnd_cb; /* v2 B-tree comparison callback */ + udata.found_op_data = &attr_copy; /* Remove the record from the name index v2 B-tree */ if(H5B2_remove(f, dxpl_id, H5A_BT2_NAME, oh->name_bt2_addr, &udata, H5A_dense_remove_bt2_cb, &udata) < 0) @@ -1105,6 +1156,9 @@ done: HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap") if(fheap && H5HF_close(fheap, dxpl_id) < 0) HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap") + if(attr_copy) + H5O_msg_free_real(H5O_MSG_ATTR, attr_copy); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5A_dense_remove() */ diff --git a/src/H5Aint.c b/src/H5Aint.c index 1d6e9ab..456717b 100644 --- a/src/H5Aint.c +++ b/src/H5Aint.c @@ -126,7 +126,7 @@ H5A_compact_build_table_cb(H5O_t UNUSED *oh, H5O_mesg_t *mesg/*in,out*/, /* Check for re-allocating table */ if(udata->curr_attr == udata->atable->nattrs) { size_t n = MAX(1, 2 * udata->atable->nattrs); - H5A_t *table = H5MM_realloc(udata->atable->attrs, + H5A_t *table = (H5A_t *)H5MM_realloc(udata->atable->attrs, n * sizeof(H5A_t)); if(!table) @@ -142,11 +142,11 @@ H5A_compact_build_table_cb(H5O_t UNUSED *oh, H5O_mesg_t *mesg/*in,out*/, * 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, &udata->atable->attrs[udata->curr_attr])) + if(NULL == H5O_shared_read(udata->f, udata->dxpl_id, (const H5O_shared_t *)mesg->native, H5O_MSG_ATTR, &udata->atable->attrs[udata->curr_attr])) HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "unable to read shared attribute") } /* end if */ else { - if(NULL == H5A_copy(&udata->atable->attrs[udata->curr_attr], mesg->native)) + if(NULL == H5A_copy(&udata->atable->attrs[udata->curr_attr], (const H5A_t *)mesg->native)) HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute") } /* end else */ @@ -300,7 +300,7 @@ H5A_dense_build_table(H5F_t *f, hid_t dxpl_id, hsize_t nattrs, haddr_t attr_fhea H5A_attr_iter_op_t attr_op; /* Attribute operator */ /* Allocate the table to store the attributes */ - if((atable->attrs = H5MM_malloc(sizeof(H5A_t) * atable->nattrs)) == NULL) + if((atable->attrs = (H5A_t *)H5MM_malloc(sizeof(H5A_t) * atable->nattrs)) == NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") /* Set up user data for iteration */ diff --git a/src/H5Apkg.h b/src/H5Apkg.h index 8aa73fb..238546f 100644 --- a/src/H5Apkg.h +++ b/src/H5Apkg.h @@ -166,6 +166,8 @@ H5_DLL H5A_t *H5A_dense_open(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *name); H5_DLL herr_t H5A_dense_write(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, H5A_t *attr); +H5_DLL herr_t H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, + const char *old_name, const char *new_name); H5_DLL herr_t H5A_dense_iterate(H5F_t *f, hid_t dxpl_id, hid_t loc_id, haddr_t attr_fheap_addr, haddr_t name_bt2_addr, H5_iter_order_t order, unsigned skip, unsigned *last_attr, const H5A_attr_iter_op_t *attr_op, diff --git a/src/H5Oattr.c b/src/H5Oattr.c index acfc720..8d2aa18 100644 --- a/src/H5Oattr.c +++ b/src/H5Oattr.c @@ -181,18 +181,18 @@ H5O_attr_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p) H5O_shared_t *shared; /* Shared information */ /* Get the shared information */ - if (NULL == (shared = (H5O_MSG_SHARED->decode)(f, dxpl_id, p))) + if (NULL == (shared = (H5O_shared_t *)(H5O_MSG_SHARED->decode)(f, dxpl_id, p))) HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "unable to decode shared message") /* Get the actual datatype information */ - if((attr->dt = H5O_shared_read(f, dxpl_id, shared, H5O_MSG_DTYPE, NULL)) == NULL) + if((attr->dt = (H5T_t *)H5O_shared_read(f, dxpl_id, shared, H5O_MSG_DTYPE, NULL)) == NULL) HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "can't decode attribute datatype") /* Free the shared information */ H5O_msg_free_real(H5O_MSG_SHARED, shared); } /* end if */ else { - if((attr->dt = (H5O_MSG_DTYPE->decode)(f, dxpl_id, p)) == NULL) + if((attr->dt = (H5T_t *)(H5O_MSG_DTYPE->decode)(f, dxpl_id, p)) == NULL) HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "can't decode attribute datatype") } /* end else */ if(version < H5O_ATTR_VERSION_2) @@ -210,18 +210,18 @@ H5O_attr_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p) H5O_shared_t *shared; /* Shared information */ /* Get the shared information */ - if (NULL == (shared = (H5O_MSG_SHARED->decode) (f, dxpl_id, p))) + if (NULL == (shared = (H5O_shared_t *)(H5O_MSG_SHARED->decode)(f, dxpl_id, p))) HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "unable to decode shared message") /* Get the actual datatype information */ - if((extent= H5O_shared_read(f, dxpl_id, shared, H5O_MSG_SDSPACE, NULL))==NULL) + if((extent= (H5S_extent_t *)H5O_shared_read(f, dxpl_id, shared, H5O_MSG_SDSPACE, NULL))==NULL) HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "can't decode attribute dataspace") /* Free the shared information */ H5O_msg_free_real(H5O_MSG_SHARED, shared); } /* end if */ else { - if((extent = (H5O_MSG_SDSPACE->decode)(f, dxpl_id, p)) == NULL) + if((extent = (H5S_extent_t *)(H5O_MSG_SDSPACE->decode)(f, dxpl_id, p)) == NULL) HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "can't decode attribute dataspace") } /* end else */ @@ -473,7 +473,7 @@ H5O_attr_copy(const void *_src, void *_dst) HDassert(_src); /* copy */ - if(NULL == (ret_value = H5A_copy(_dst, _src))) + if(NULL == (ret_value = (H5A_t *)H5A_copy((H5A_t *)_dst, (const H5A_t *)_src))) HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "can't copy attribute") done: @@ -1065,9 +1065,9 @@ done: if(H5I_dec_ref(tid_mem) < 0) HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, NULL, "Can't decrement temporary datatype ID") if(buf) - H5FL_BLK_FREE(attr_buf, buf); + buf = H5FL_BLK_FREE(attr_buf, buf); if(reclaim_buf) - H5FL_BLK_FREE(attr_buf, reclaim_buf); + reclaim_buf = H5FL_BLK_FREE(attr_buf, reclaim_buf); /* Release destination attribute information on failure */ if(!ret_value) diff --git a/src/H5Oattribute.c b/src/H5Oattribute.c index 576ce29..b3b19d4 100644 --- a/src/H5Oattribute.c +++ b/src/H5Oattribute.c @@ -527,7 +527,7 @@ done: * * Programmer: Quincey Koziol * koziol@hdfgroup.org - * Jan 2 2006 + * Jan 2 2007 * *------------------------------------------------------------------------- */ @@ -547,7 +547,7 @@ H5O_attr_update_shared(H5F_t *f, hid_t dxpl_id, H5A_t *attr, /* Increment reference count on attribute components */ /* (Otherwise they may be deleted when the old attribute - * message is deleted.) + * message is removed from the shared message storage.) */ if(H5O_attr_link(f, dxpl_id, attr) < 0) HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust attribute link count") @@ -559,7 +559,7 @@ H5O_attr_update_shared(H5F_t *f, hid_t dxpl_id, H5A_t *attr, else if(shared_mesg < 0) HGOTO_ERROR(H5E_ATTR, H5E_BADMESG, FAIL, "can't share attribute") - /* Remove the old attribute from the SOHM index */ + /* Remove the old attribute from the SOHM storage */ if(H5SM_try_delete(f, dxpl_id, H5O_ATTR_ID, sh_mesg) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to delete shared attribute in shared storage") @@ -610,11 +610,11 @@ H5O_attr_write_cb(H5O_t UNUSED *oh, H5O_mesg_t *mesg/*in,out*/, /* Check for correct attribute message to modify */ if(HDstrcmp(shared_attr.name, udata->attr->name) == 0) { - /* Update the shared attribute in the SOHM info */ + /* Update the shared attribute in the SOHM storage */ if(H5O_attr_update_shared(udata->f, udata->dxpl_id, udata->attr, (const H5O_shared_t *)mesg->native) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, H5_ITER_ERROR, "unable to update attribute in shared storage") - /* Extract shared message info from current attribute */ + /* Extract updated shared message info from modified attribute */ if(NULL == H5O_attr_get_share(udata->attr, (H5O_shared_t *)mesg->native)) HGOTO_ERROR(H5E_ATTR, H5E_BADMESG, H5_ITER_ERROR, "can't get shared info") @@ -799,6 +799,11 @@ done: * Purpose: Object header iterator callback routine to change name of * attribute during rename * + * Note: This routine doesn't currently allow an attribute to change + * its "shared" status, if the name change would cause a size + * difference that would put it into a different category. + * Something for later... + * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol @@ -835,9 +840,23 @@ H5O_attr_rename_mod_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/, /* Check for correct attribute message to modify */ if(HDstrcmp(shared_attr.name, udata->old_name) == 0) { -/* XXX: fix me */ -HDfprintf(stderr, "%s: renaming a shared attribute not supported yet!\n", FUNC); -HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, H5_ITER_ERROR, "renaming a shared attribute not supported yet") + /* Change the name for the attribute */ + H5MM_xfree(shared_attr.name); + shared_attr.name = H5MM_xstrdup(udata->new_name); + + /* Mark message as dirty */ + mesg->dirty = TRUE; + + /* Update the shared attribute in the SOHM storage */ + if(H5O_attr_update_shared(udata->f, udata->dxpl_id, &shared_attr, (const H5O_shared_t *)mesg->native) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, H5_ITER_ERROR, "unable to update attribute in shared storage") + + /* Extract updated shared message info from modified attribute */ + if(NULL == H5O_attr_get_share(&shared_attr, (H5O_shared_t *)mesg->native)) + HGOTO_ERROR(H5E_ATTR, H5E_BADMESG, H5_ITER_ERROR, "can't get shared info") + + /* Indicate that we found the correct attribute */ + udata->found = TRUE; } /* end if */ /* Release copy of shared attribute */ @@ -867,7 +886,7 @@ HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, H5_ITER_ERROR, "renaming a shared attribu * list of messages during the "add the modified attribute" * step, invalidating the message pointer we have here - QAK) */ - attr = mesg->native; + attr = (H5A_t *)mesg->native; mesg->native = NULL; /* If the later version of the object header format, decrement attribute */ @@ -897,6 +916,7 @@ HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, H5_ITER_ERROR, "renaming a shared attribu HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, H5_ITER_ERROR, "unable to relocate renamed attribute in header") /* Decrement the link count on shared components */ + /* (to balance all the link count adjustments out) */ if(H5O_attr_delete(udata->f, udata->dxpl_id, attr, TRUE) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, H5_ITER_ERROR, "unable to delete attribute") @@ -906,15 +926,18 @@ HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, H5_ITER_ERROR, "renaming a shared attribu /* Indicate that we found an existing attribute with the old name */ udata->found = TRUE; - - /* Stop iterating */ - ret_value = H5_ITER_STOP; - - /* Indicate that the object header was modified */ - *oh_flags_ptr |= H5AC__DIRTIED_FLAG; } /* end if */ } /* end else */ + /* Set common info, if we found the correct attribute */ + if(udata->found) { + /* Stop iterating */ + ret_value = H5_ITER_STOP; + + /* Indicate that the object header was modified */ + *oh_flags_ptr |= H5AC__DIRTIED_FLAG; + } /* end if */ + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_attr_rename_mod_cb() */ @@ -933,7 +956,8 @@ done: *------------------------------------------------------------------------- */ herr_t -H5O_attr_rename(const H5O_loc_t *loc, hid_t dxpl_id, const char *old_name, const char *new_name) +H5O_attr_rename(const H5O_loc_t *loc, hid_t dxpl_id, const char *old_name, + const char *new_name) { H5O_t *oh = NULL; /* Pointer to actual object header */ unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */ @@ -952,9 +976,9 @@ H5O_attr_rename(const H5O_loc_t *loc, hid_t dxpl_id, const char *old_name, const /* Check for attributes stored densely */ if(H5F_addr_defined(oh->attr_fheap_addr)) { -/* XXX: fix me */ -HDfprintf(stderr, "%s: renaming attributes in dense storage not supported yet!\n", FUNC); -HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "renaming attributes in dense storage not supported yet") + /* Rename the attribute data in dense storage */ + if(H5A_dense_rename(loc->file, dxpl_id, oh, old_name, new_name) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "error updating attribute") } /* end if */ else { H5O_iter_ren_t udata; /* User data for callback */ @@ -1118,6 +1142,7 @@ H5O_attr_remove_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/, if(NULL == H5O_shared_read(udata->f, udata->dxpl_id, (const H5O_shared_t *)mesg->native, H5O_MSG_ATTR, &shared_attr)) HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, H5_ITER_ERROR, "unable to read shared attribute") +/* XXX: fix me */ HDfprintf(stderr, "%s: removing a shared attribute not supported yet!\n", FUNC); HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "deleting a shared attribute not supported yet") #ifdef NOT_YET diff --git a/test/tattr.c b/test/tattr.c index 4567ef8..c5f0dcc 100644 --- a/test/tattr.c +++ b/test/tattr.c @@ -2233,8 +2233,8 @@ HDfprintf(stderr, "max_compact = %u, min_dense = %u\n", max_compact, min_dense); /* Create attribute */ sprintf(attrname, "new attr %02u", u); - attr = H5Acreate(dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT); - CHECK(attr, FAIL, "H5Acreate"); + attr = H5Aopen_name(dataset, attrname); + CHECK(attr, FAIL, "H5Aopen_name"); /* Read data from the attribute */ ret = H5Aread(attr, H5T_NATIVE_UINT, &value); @@ -2254,7 +2254,6 @@ HDfprintf(stderr, "max_compact = %u, min_dense = %u\n", max_compact, min_dense); ret = H5Fclose(fid); CHECK(ret, FAIL, "H5Fclose"); } /* test_attr_dense_rename() */ -#endif /* QAK */ /**************************************************************** ** @@ -2399,6 +2398,239 @@ HDfprintf(stderr, "max_compact = %u, min_dense = %u\n", max_compact, min_dense); ret = H5Fclose(fid); CHECK(ret, FAIL, "H5Fclose"); } /* test_attr_shared_write() */ +#endif /* QAK */ + +/**************************************************************** +** +** test_attr_shared_rename(): Test basic H5A (attribute) code. +** Tests renaming shared attributes in "compact" & "dense" storage +** +****************************************************************/ +static void +test_attr_shared_rename(hid_t fcpl, hid_t fapl) +{ + hid_t fid; /* HDF5 File ID */ + hid_t dataset, dataset2; /* Dataset ID2 */ + hid_t sid; /* Dataspace ID */ + hid_t attr; /* Attribute ID */ + hid_t dcpl; /* Dataset creation property list ID */ + char attrname[NAME_BUF_SIZE]; /* Name of attribute on first dataset */ + char attrname2[NAME_BUF_SIZE]; /* Name of attribute on second dataset */ + unsigned max_compact; /* Maximum # of attributes to store compactly */ + unsigned min_dense; /* Minimum # of attributes to store "densely" */ + htri_t is_dense; /* Are attributes stored densely? */ + htri_t is_shared; /* Is attributes shared? */ + hsize_t shared_refcount; /* Reference count of shared attribute */ + unsigned attr_value; /* Attribute value */ + unsigned u; /* Local index variable */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(5, ("Testing Renaming Shared Attributes in Compact & Dense Storage\n")); + + /* Create file */ + fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl, fapl); + CHECK(fid, FAIL, "H5Fcreate"); + + /* Create dataspace for dataset */ + sid = H5Screate(H5S_SCALAR); + CHECK(sid, FAIL, "H5Screate"); + + /* Set up to query the object creation properties */ + dcpl = H5Pcreate(H5P_DATASET_CREATE); + CHECK(dcpl, FAIL, "H5Pcreate"); + + /* Create datasets */ + dataset = H5Dcreate(fid, DSET1_NAME, H5T_NATIVE_UCHAR, sid, dcpl); + CHECK(dataset, FAIL, "H5Dcreate"); + dataset2 = H5Dcreate(fid, DSET2_NAME, H5T_NATIVE_UCHAR, sid, dcpl); + CHECK(dataset2, FAIL, "H5Dcreate"); + + /* Retrieve limits for compact/dense attribute storage */ + ret = H5Pget_attr_phase_change(dcpl, &max_compact, &min_dense); + CHECK(ret, FAIL, "H5Pget_attr_phase_change"); +#ifdef QAK +HDfprintf(stderr, "max_compact = %u, min_dense = %u\n", max_compact, min_dense); +#endif /* QAK */ + + /* Check on datasets' attribute storage status */ + is_dense = H5O_is_attr_dense_test(dataset); + VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test"); + is_dense = H5O_is_attr_dense_test(dataset2); + VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test"); + + /* Add attributes to each dataset, until after converting to dense storage */ +/* XXX: Test with shared & committed datatype/dataspace also */ + for(u = 0; u < max_compact * 2; u++) { + /* Create attribute name */ + sprintf(attrname, "attr %02u", u); + + /* Create attribute on first dataset */ + attr = H5Acreate(dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT); + CHECK(attr, FAIL, "H5Acreate"); + + /* Check that attribute is shared */ + is_shared = H5A_is_shared_test(attr); + VERIFY(is_shared, TRUE, "H5A_is_shared_test"); + + /* Check refcount for attribute */ + ret = H5A_get_shared_rc_test(attr, &shared_refcount); + CHECK(ret, FAIL, "H5A_get_shared_rc_test"); + VERIFY(shared_refcount, 1, "H5A_get_shared_rc_test"); + + /* Write data into the attribute */ + attr_value = u + 1; + ret = H5Awrite(attr, H5T_NATIVE_UINT, &attr_value); + CHECK(ret, FAIL, "H5Awrite"); + + /* Close attribute */ + ret = H5Aclose(attr); + CHECK(ret, FAIL, "H5Aclose"); + + /* Check on dataset's attribute storage status */ + is_dense = H5O_is_attr_dense_test(dataset); + if(u < max_compact) + VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test"); + else + VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test"); + + + /* Create attribute on second dataset */ + attr = H5Acreate(dataset2, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT); + CHECK(attr, FAIL, "H5Acreate"); + + /* Check that attribute is shared */ + is_shared = H5A_is_shared_test(attr); + VERIFY(is_shared, TRUE, "H5A_is_shared_test"); + + /* Check refcount for attribute */ + ret = H5A_get_shared_rc_test(attr, &shared_refcount); + CHECK(ret, FAIL, "H5A_get_shared_rc_test"); + VERIFY(shared_refcount, 1, "H5A_get_shared_rc_test"); + + /* Write data into the attribute */ + attr_value = u + 1; + ret = H5Awrite(attr, H5T_NATIVE_UINT, &attr_value); + CHECK(ret, FAIL, "H5Awrite"); + + /* Check refcount for attribute */ + ret = H5A_get_shared_rc_test(attr, &shared_refcount); + CHECK(ret, FAIL, "H5A_get_shared_rc_test"); + VERIFY(shared_refcount, 2, "H5A_get_shared_rc_test"); + + /* Close attribute */ + ret = H5Aclose(attr); + CHECK(ret, FAIL, "H5Aclose"); + + /* Check on dataset's attribute storage status */ + is_dense = H5O_is_attr_dense_test(dataset2); + if(u < max_compact) + VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test"); + else + VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test"); + + + /* Create new attribute name */ + sprintf(attrname2, "new attr %02u", u); + + /* Change second dataset's attribute's name */ + ret = H5Arename(dataset2, attrname, attrname2); + CHECK(ret, FAIL, "H5Arename"); + + + /* Check refcount on attributes now */ + + /* Check refcount on renamed attribute */ + attr = H5Aopen_name(dataset2, attrname2); + CHECK(attr, FAIL, "H5Aopen_name"); + + /* Check that attribute is shared */ + is_shared = H5A_is_shared_test(attr); + VERIFY(is_shared, TRUE, "H5A_is_shared_test"); + + /* Check refcount for attribute */ + ret = H5A_get_shared_rc_test(attr, &shared_refcount); + CHECK(ret, FAIL, "H5A_get_shared_rc_test"); + VERIFY(shared_refcount, 1, "H5A_get_shared_rc_test"); + + /* Close attribute */ + ret = H5Aclose(attr); + CHECK(ret, FAIL, "H5Aclose"); + + /* Check refcount on original attribute */ + attr = H5Aopen_name(dataset, attrname); + CHECK(attr, FAIL, "H5Aopen_name"); + + /* Check that attribute is shared */ + is_shared = H5A_is_shared_test(attr); + VERIFY(is_shared, TRUE, "H5A_is_shared_test"); + + /* Check refcount for attribute */ + ret = H5A_get_shared_rc_test(attr, &shared_refcount); + CHECK(ret, FAIL, "H5A_get_shared_rc_test"); + VERIFY(shared_refcount, 1, "H5A_get_shared_rc_test"); + + /* Close attribute */ + ret = H5Aclose(attr); + CHECK(ret, FAIL, "H5Aclose"); + + + /* Change second dataset's attribute's name back to original */ + ret = H5Arename(dataset2, attrname2, attrname); + CHECK(ret, FAIL, "H5Arename"); + + + /* Check refcount on attributes now */ + + /* Check refcount on renamed attribute */ + attr = H5Aopen_name(dataset2, attrname); + CHECK(attr, FAIL, "H5Aopen_name"); + + /* Check that attribute is shared */ + is_shared = H5A_is_shared_test(attr); + VERIFY(is_shared, TRUE, "H5A_is_shared_test"); + + /* Check refcount for attribute */ + ret = H5A_get_shared_rc_test(attr, &shared_refcount); + CHECK(ret, FAIL, "H5A_get_shared_rc_test"); + VERIFY(shared_refcount, 2, "H5A_get_shared_rc_test"); + + /* Close attribute */ + ret = H5Aclose(attr); + CHECK(ret, FAIL, "H5Aclose"); + + /* Check refcount on original attribute */ + attr = H5Aopen_name(dataset, attrname); + CHECK(attr, FAIL, "H5Aopen_name"); + + /* Check that attribute is shared */ + is_shared = H5A_is_shared_test(attr); + VERIFY(is_shared, TRUE, "H5A_is_shared_test"); + + /* Check refcount for attribute */ + ret = H5A_get_shared_rc_test(attr, &shared_refcount); + CHECK(ret, FAIL, "H5A_get_shared_rc_test"); + VERIFY(shared_refcount, 2, "H5A_get_shared_rc_test"); + + /* Close attribute */ + ret = H5Aclose(attr); + CHECK(ret, FAIL, "H5Aclose"); + } /* end for */ + + /* Close dataspace */ + ret = H5Sclose(sid); + CHECK(ret, FAIL, "H5Sclose"); + + /* Close Datasets */ + ret = H5Dclose(dataset); + CHECK(ret, FAIL, "H5Dclose"); + ret = H5Dclose(dataset2); + CHECK(ret, FAIL, "H5Dclose"); + + /* Close file */ + ret = H5Fclose(fid); + CHECK(ret, FAIL, "H5Fclose"); +} /* test_attr_shared_rename() */ /**************************************************************** ** @@ -2502,16 +2734,15 @@ test_attr(void) test_attr_dense_create(my_fcpl, fapl2); /* Test dense attribute storage creation */ test_attr_dense_open(my_fcpl, fapl2); /* Test opening attributes in dense storage */ test_attr_dense_delete(my_fcpl, fapl2); /* Test deleting attributes in dense storage */ -/* XXX: Rename attribute */ -#ifdef NOT_YET test_attr_dense_rename(my_fcpl, fapl2); /* Test renaming attributes in dense storage */ -#endif /* NOT_YET */ +/* XXX: Remove attribute */ /* XXX: Unlink object */ } /* end for */ /* Tests with both "new format" and "shared" attributes */ test_attr_shared_write(fcpl2, fapl2); /* Test writing to shared attributes in compact & dense storage */ -/* XXX: Rename shared attributes */ + test_attr_shared_rename(fcpl2, fapl2); /* Test writing to shared attributes in compact & dense storage */ +/* XXX: Removing attribute */ #else /* QAK */ HDfprintf(stderr, "Uncomment tests!\n"); #endif /* QAK */ -- cgit v0.12