diff options
-rw-r--r-- | MANIFEST | 1 | ||||
-rw-r--r-- | src/H5A.c | 137 | ||||
-rw-r--r-- | src/H5Adense.c | 363 | ||||
-rw-r--r-- | src/H5Aint.c | 511 | ||||
-rw-r--r-- | src/H5Apkg.h | 24 | ||||
-rw-r--r-- | src/H5Aprivate.h | 1 | ||||
-rw-r--r-- | src/H5Gdense.c | 27 | ||||
-rw-r--r-- | src/H5Oattr.c | 8 | ||||
-rw-r--r-- | src/H5Oattribute.c | 194 | ||||
-rw-r--r-- | src/H5Opkg.h | 7 | ||||
-rwxr-xr-x | src/H5SM.c | 30 | ||||
-rwxr-xr-x | src/H5SMprivate.h | 1 | ||||
-rwxr-xr-x | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/Makefile.in | 5 | ||||
-rw-r--r-- | test/tattr.c | 94 | ||||
-rw-r--r-- | test/titerate.c | 4 |
16 files changed, 948 insertions, 462 deletions
@@ -413,6 +413,7 @@ ./src/H5Abtree2.c ./src/H5Adense.c ./src/H5Adeprec.c +./src/H5Aint.c ./src/H5Apkg.h ./src/H5Aprivate.h ./src/H5Apublic.h @@ -67,7 +67,8 @@ typedef struct H5A_iter_cb1 { 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); -static hid_t H5A_open(H5G_loc_t *loc, unsigned idx, hid_t dxpl_id); +static herr_t H5A_open_common(const H5G_loc_t *loc, H5A_t *attr); +static H5A_t *H5A_open_by_idx(H5G_loc_t *loc, unsigned idx, hid_t dxpl_id); static H5A_t *H5A_open_by_name(const H5G_loc_t *loc, const char *name, hid_t dxpl_id); static herr_t H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id); @@ -515,6 +516,7 @@ hid_t H5Aopen_idx(hid_t loc_id, unsigned idx) { H5G_loc_t loc; /* Object location */ + H5A_t *attr = NULL; /* Attribute opened */ hid_t ret_value; FUNC_ENTER_API(H5Aopen_idx, FAIL) @@ -526,49 +528,51 @@ H5Aopen_idx(hid_t loc_id, unsigned idx) if(H5G_loc(loc_id, &loc) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") - /* Go do the real work for opening the attribute */ -/* XXX: Add support & tests for attributes in dense storage */ - if((ret_value = H5A_open(&loc, idx, H5AC_dxpl_id)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to open attribute") + /* Open the attribute in the object header */ + if(NULL == (attr = H5A_open_by_idx(&loc, idx, H5AC_ind_dxpl_id))) + HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open attribute") + + /* Register the attribute and get an ID for it */ + if((ret_value = H5I_register(H5I_ATTR, attr)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register attribute for ID") done: + /* Cleanup on failure */ + if(ret_value < 0 && attr) + (void)H5A_close(attr); + FUNC_LEAVE_API(ret_value) } /* H5Aopen_idx() */ /*------------------------------------------------------------------------- - * Function: H5A_open + * Function: H5A_open_common * * Purpose: - * This is the guts of the H5Aopen_xxx functions + * Finishes initializing an attributes the open + * * Usage: - * herr_t H5A_open (ent, idx) - * const H5G_entry_t *ent; IN: Pointer to symbol table entry for object to attribute - * unsigned idx; IN: index of attribute to open (0-based) + * herr_t H5A_open_common(loc, name, dxpl_id) + * const H5G_loc_t *loc; IN: Pointer to group location for object + * H5A_t *attr; IN/OUT: Pointer to attribute to initialize * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol - * April 2, 1998 + * December 18, 2006 * *------------------------------------------------------------------------- */ -static hid_t -H5A_open(H5G_loc_t *loc, unsigned idx, hid_t dxpl_id) +static herr_t +H5A_open_common(const H5G_loc_t *loc, H5A_t *attr) { - H5A_t *attr = NULL; - hid_t ret_value; + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5A_open) + FUNC_ENTER_NOAPI_NOINIT(H5A_open_common) /* check args */ HDassert(loc); - - /* Read in attribute with H5O_msg_read() */ - H5_CHECK_OVERFLOW(idx, unsigned, int); - if(NULL == (attr = (H5A_t *)H5O_msg_read(loc->oloc, H5O_ATTR_ID, (int)idx, NULL, dxpl_id))) - HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to load attribute info from dataset header") - attr->initialized = TRUE; + HDassert(attr); #if defined(H5_USING_PURIFY) || !defined(NDEBUG) /* Clear object location */ @@ -593,17 +597,59 @@ H5A_open(H5G_loc_t *loc, unsigned idx, hid_t dxpl_id) HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open") attr->obj_opened = TRUE; - /* Register the attribute and get an ID for it */ - if((ret_value = H5I_register(H5I_ATTR, attr)) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register attribute for ID") +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5A_open_common() */ + + +/*------------------------------------------------------------------------- + * Function: H5A_open_by_idx + * + * Purpose: + * Open an attribute according to its index order + * Usage: + * herr_t H5A_open (loc, idx) + * const H5G_loc_t *loc; IN: Pointer to group location for object to open attribute + * unsigned idx; IN: index of attribute to open (0-based) + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * April 2, 1998 + * + *------------------------------------------------------------------------- + */ +static H5A_t * +H5A_open_by_idx(H5G_loc_t *loc, unsigned idx, hid_t dxpl_id) +{ + H5A_t *attr = NULL; + H5A_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5A_open_by_idx) + + /* check args */ + HDassert(loc); + + /* Read in attribute from object header */ +/* XXX: This uses name index order currently, but should use creation order, once it's implemented */ + if(NULL == (attr = H5O_attr_open_by_idx(loc->oloc, (hsize_t)idx, dxpl_id))) + HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to load attribute info from object header") + attr->initialized = TRUE; + + /* Finish initializing attribute */ + if(H5A_open_common(loc, attr) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to initialize attribute") + + /* Set return value */ + ret_value = attr; done: /* Cleanup on failure */ - if(ret_value < 0 && attr) + if(ret_value == NULL && attr) (void)H5A_close(attr); FUNC_LEAVE_NOAPI(ret_value) -} /* H5A_open() */ +} /* H5A_open_by_idx() */ /*------------------------------------------------------------------------- @@ -638,32 +684,13 @@ H5A_open_by_name(const H5G_loc_t *loc, const char *name, hid_t dxpl_id) HDassert(name); /* Read in attribute from object header */ - if(NULL == (attr = H5O_attr_open(loc->oloc, name, dxpl_id))) + if(NULL == (attr = H5O_attr_open_by_name(loc->oloc, name, dxpl_id))) HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to load attribute info from object header") attr->initialized = TRUE; -#if defined(H5_USING_PURIFY) || !defined(NDEBUG) - /* Clear object location */ - if(H5O_loc_reset(&(attr->oloc)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to reset location") - - /* Clear path name */ - if(H5G_name_reset(&(attr->path)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to reset path") -#endif /* H5_USING_PURIFY */ - - /* Deep copy of the symbol table entry */ - if(H5O_loc_copy(&(attr->oloc), loc->oloc, H5_COPY_DEEP) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to copy entry") - - /* Deep copy of the group hier. path */ - if(H5G_name_copy(&(attr->path), loc->path, H5_COPY_DEEP) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to copy entry") - - /* Hold the symbol table entry (and file) open */ - if(H5O_open(&(attr->oloc)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to open") - attr->obj_opened = TRUE; + /* Finish initializing attribute */ + if(H5A_open_common(loc, attr) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to initialize attribute") /* Set return value */ ret_value = attr; @@ -1345,6 +1372,7 @@ herr_t H5Aiterate(hid_t loc_id, unsigned *attr_num, H5A_operator_t op, void *op_data) { H5G_loc_t loc; /* Object location */ + H5A_attr_iter_op_t attr_op; /* Attribute operator */ unsigned start_idx; /* Index of attribute to start iterating at */ herr_t ret_value; /* Return value */ @@ -1357,9 +1385,14 @@ H5Aiterate(hid_t loc_id, unsigned *attr_num, H5A_operator_t op, void *op_data) if(H5G_loc(loc_id, &loc) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + /* Build attribute operator info */ + attr_op.op_type = H5A_ATTR_OP_APP; + attr_op.u.app_op = op; + /* Call attribute iteration routine */ start_idx = (attr_num ? (unsigned)*attr_num : 0); - if((ret_value = H5O_attr_iterate(loc_id, loc.oloc, H5AC_ind_dxpl_id, start_idx, attr_num, op, op_data)) < 0) +/* XXX: Uses "native" name index order currently - should use creation order */ + if((ret_value = H5O_attr_iterate(loc_id, loc.oloc, H5AC_ind_dxpl_id, H5_ITER_NATIVE, start_idx, attr_num, &attr_op, op_data)) < 0) HERROR(H5E_ATTR, H5E_BADITER, "error iterating over attributes"); done: @@ -1475,7 +1508,7 @@ H5A_copy(H5A_t *_new_attr, const H5A_t *old_attr) /* Allocate attribute structure */ if(_new_attr == NULL) { - if(NULL == (new_attr = H5FL_MALLOC(H5A_t))) + if(NULL == (new_attr = H5FL_CALLOC(H5A_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") allocated_attr = TRUE; } /* end if */ diff --git a/src/H5Adense.c b/src/H5Adense.c index c5de1a9..d6231cf 100644 --- a/src/H5Adense.c +++ b/src/H5Adense.c @@ -38,7 +38,6 @@ #include "H5private.h" /* Generic Functions */ #include "H5Apkg.h" /* Attributes */ #include "H5Eprivate.h" /* Error handling */ -#include "H5MMprivate.h" /* Memory management */ #include "H5Opkg.h" /* Object headers */ #include "H5SMprivate.h" /* Shared object header messages */ @@ -74,12 +73,6 @@ /* Local Typedefs */ /******************/ -/* Data exchange structure to use when building table of attributes for an object */ -typedef struct { - H5A_attr_table_t *atable; /* Pointer to attribute table to build */ - size_t curr_attr; /* Current attribute to operate on */ -} H5A_dense_bt_ud_t; - /* * Data exchange structure for dense attribute storage. This structure is * passed through the v2 B-tree layer when modifying attributes. @@ -108,7 +101,7 @@ typedef struct { hid_t loc_id; /* Object ID for application callback */ unsigned skip; /* Number of attributes to skip */ unsigned count; /* The # of attributes visited */ - const H5A_attr_iterate_t *attr_op; /* Callback for each attribute */ + const H5A_attr_iter_op_t *attr_op; /* Callback for each attribute */ void *op_data; /* Callback data for each attribute */ /* upward */ @@ -140,7 +133,6 @@ typedef struct { } H5A_fh_ud_rm_t; - /********************/ /* Package Typedefs */ /********************/ @@ -150,8 +142,6 @@ typedef struct { /* Local Prototypes */ /********************/ -static herr_t H5A_attr_sort_table(H5A_attr_table_t *atable, H5_index_t idx_type, - H5_iter_order_t order); /*********************/ /* Package Variables */ @@ -173,240 +163,6 @@ H5FL_BLK_DEFINE(ser_attr); /*------------------------------------------------------------------------- - * Function: H5A_dense_build_table_cb - * - * Purpose: Callback routine for building table of attributes from dense - * attribute storage. - * - * Return: Success: Non-negative - * Failure: Negative - * - * Programmer: Quincey Koziol - * koziol@hdfgroup.org - * Dec 11 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -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 */ - - FUNC_ENTER_NOAPI_NOINIT(H5A_dense_build_table_cb) - - /* check arguments */ - HDassert(attr); - HDassert(udata); - HDassert(udata->curr_attr < udata->atable->nattrs); - - /* Copy attribute information */ - if(NULL == H5A_copy(&udata->atable->attrs[udata->curr_attr], attr)) - HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute") - udata->atable->flags[udata->curr_attr] = mesg_flags; - - /* Increment number of attributes stored */ - udata->curr_attr++; - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5A_dense_build_table_cb() */ - - -/*------------------------------------------------------------------------- - * Function: H5A_dense_build_table - * - * Purpose: Builds a table containing a sorted list of attributes for - * an object - * - * Note: Used for building table of attributes in non-native iteration - * order for an index - * - * Return: Success: Non-negative - * Failure: Negative - * - * Programmer: Quincey Koziol - * Dec 11, 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5A_dense_build_table(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, - H5_index_t UNUSED idx_type, H5_iter_order_t UNUSED order, - H5A_attr_table_t *atable) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5A_dense_build_table) - - /* Sanity check */ - HDassert(f); - HDassert(oh); - HDassert(atable); - - /* Set size of table */ - H5_CHECK_OVERFLOW(oh->nattrs, /* From: */ hsize_t, /* To: */ size_t); - atable->nattrs = (size_t)oh->nattrs; - - /* Allocate space for the table entries */ - if(atable->nattrs > 0) { - H5A_dense_bt_ud_t udata; /* User data for iteration callback */ - H5A_attr_iterate_t attr_op; /* Attribute operator */ - - /* Allocate the table to store the attributes */ - if((atable->attrs = H5MM_malloc(sizeof(H5A_t) * atable->nattrs)) == NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - if((atable->flags = H5MM_malloc(sizeof(uint8_t) * atable->nattrs)) == NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - - /* Set up user data for iteration */ - udata.atable = atable; - udata.curr_attr = 0; - - /* Build iterator operator */ - attr_op.op_type = H5A_ATTR_OP_LIB; - attr_op.u.lib_op = H5A_dense_build_table_cb; - - /* Iterate over the links in the group, building a table of the link messages */ - if(H5A_dense_iterate(f, dxpl_id, (hid_t)0, oh->attr_fheap_addr, oh->name_bt2_addr, - (unsigned)0, NULL, &attr_op, &udata) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "error building attribute table") - - /* Sort attribute table in correct iteration order */ - if(H5A_attr_sort_table(atable, H5_INDEX_NAME, H5_ITER_INC) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTSORT, FAIL, "error sorting attribute table") - } /* end if */ - else - atable->attrs = NULL; - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5A_dense_build_table() */ - - -/*------------------------------------------------------------------------- - * Function: H5A_attr_cmp_name_inc - * - * Purpose: Callback routine for comparing two attribute names, in - * increasing alphabetic order - * - * Return: An integer less than, equal to, or greater than zero if the - * first argument is considered to be respectively less than, - * equal to, or greater than the second. If two members compare - * as equal, their order in the sorted array is undefined. - * (i.e. same as strcmp()) - * - * Programmer: Quincey Koziol - * koziol@hdfgroup.org - * Dec 11 2005 - * - *------------------------------------------------------------------------- - */ -static int -H5A_attr_cmp_name_inc(const void *attr1, const void *attr2) -{ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_attr_cmp_name_inc) - - FUNC_LEAVE_NOAPI(HDstrcmp(((const H5A_t *)attr1)->name, ((const H5A_t *)attr2)->name)) -} /* end H5A_attr_cmp_name_inc() */ - - -/*------------------------------------------------------------------------- - * Function: H5A_attr_sort_table - * - * Purpose: Sort table containing a list of attributes for an object - * - * Return: Success: Non-negative - * Failure: Negative - * - * Programmer: Quincey Koziol - * Dec 11, 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5A_attr_sort_table(H5A_attr_table_t *atable, H5_index_t idx_type, - H5_iter_order_t order) -{ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_attr_sort_table) - - /* Sanity check */ - HDassert(atable); - - /* Pick appropriate sorting routine */ -#ifdef NOT_YET - if(idx_type == H5_INDEX_NAME) { - if(order == H5_ITER_INC) -#else /* NOT_YET */ -HDassert(idx_type == H5_INDEX_NAME); -HDassert(order == H5_ITER_INC); -#endif /* NOT_YET */ - HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t), H5A_attr_cmp_name_inc); -#ifdef NOT_YET - else if(order == H5_ITER_DEC) - HDqsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G_link_cmp_name_dec); - else - HDassert(order == H5_ITER_NATIVE); - } /* end if */ - else { - HDassert(idx_type == H5_INDEX_CRT_ORDER); - if(order == H5_ITER_INC) - HDqsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G_link_cmp_corder_inc); - else if(order == H5_ITER_DEC) - HDqsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G_link_cmp_corder_dec); - else - HDassert(order == H5_ITER_NATIVE); - } /* end else */ -#endif /* NOT_YET */ - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5A_attr_sort_table() */ - - -/*------------------------------------------------------------------------- - * Function: H5A_attr_release_table - * - * Purpose: Release table containing a list of attributes for an object - * - * Return: Success: Non-negative - * Failure: Negative - * - * Programmer: Quincey Koziol - * Dec 11, 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5A_attr_release_table(H5A_attr_table_t *atable) -{ - size_t u; /* Local index variable */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5A_attr_release_table) - - /* Sanity check */ - HDassert(atable); - - /* Release attribute info, if any */ - if(atable->nattrs > 0) { - /* Free attribute message information */ - for(u = 0; u < atable->nattrs; u++) - if(H5A_free(&(atable->attrs[u])) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release attribute") - - /* Free table of attributes */ - H5MM_xfree(atable->attrs); - H5MM_xfree(atable->flags); - } /* end if */ - else - HDassert(atable->attrs == NULL); - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5A_attr_release_table() */ - - -/*------------------------------------------------------------------------- * Function: H5A_dense_create * * Purpose: Creates dense attribute storage structures for an object @@ -996,6 +752,10 @@ H5A_dense_iterate_bt2_cb(const void *_record, void *_bt2_udata) 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: @@ -1005,7 +765,7 @@ H5A_dense_iterate_bt2_cb(const void *_record, void *_bt2_udata) case H5A_ATTR_OP_LIB: /* Call the library's callback */ - ret_value = (bt2_udata->attr_op->u.lib_op)(fh_udata.attr, record->flags, bt2_udata->op_data); + ret_value = (bt2_udata->attr_op->u.lib_op)(fh_udata.attr, bt2_udata->op_data); } /* end switch */ /* Release the space allocated for the attribute */ @@ -1040,13 +800,14 @@ done: */ 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, unsigned skip, unsigned *last_attr, - const H5A_attr_iterate_t *attr_op, void *op_data) + haddr_t name_bt2_addr, H5_iter_order_t order, unsigned skip, + unsigned *last_attr, const H5A_attr_iter_op_t *attr_op, void *op_data) { H5A_bt2_ud_it_t udata; /* User data for iterator callback */ H5HF_t *fheap = NULL; /* Fractal heap handle */ H5HF_t *shared_fheap = NULL; /* Fractal heap handle for shared header messages */ - htri_t attr_sharable; /* Flag indicating attributes are sharable */ + H5A_attr_table_t atable = {0, NULL}; /* Table of attributes */ + hsize_t nrec; /* # of records in v2 B-tree */ herr_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5A_dense_iterate, FAIL) @@ -1059,61 +820,75 @@ H5A_dense_iterate(H5F_t *f, hid_t dxpl_id, hid_t loc_id, haddr_t attr_fheap_addr HDassert(H5F_addr_defined(name_bt2_addr)); HDassert(attr_op); - /* Check for skipping too many links */ - if(skip > 0) { - hsize_t nrec; /* # of records in v2 B-tree */ - - /* Retrieve # of records in name index */ - /* (# of records in all indices the same) */ - if(H5B2_get_nrec(f, dxpl_id, H5A_BT2_NAME, name_bt2_addr, &nrec) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't retrieve # of records in index") + /* Retrieve # of records in name index */ + /* (# of records in all indices the same) */ + if(H5B2_get_nrec(f, dxpl_id, H5A_BT2_NAME, name_bt2_addr, &nrec) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't retrieve # of records in index") + /* Check for skipping too many attributes */ + if(skip > 0) { /* Check for bad starting index */ if((hsize_t)skip >= nrec) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified") } /* end if */ - /* Open the fractal heap */ - if(NULL == (fheap = H5HF_open(f, dxpl_id, attr_fheap_addr))) - HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap") + /* Check on iteration order */ + /* ("native" iteration order is unordered for this attribute storage mechanism) */ + if(order == H5_ITER_NATIVE) { + htri_t attr_sharable; /* Flag indicating attributes are sharable */ - /* 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") + /* Open the fractal heap */ + if(NULL == (fheap = H5HF_open(f, dxpl_id, attr_fheap_addr))) + HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap") - /* Get handle for shared object heap, if attributes are sharable */ - if(attr_sharable) { - haddr_t shared_fheap_addr; /* Address of fractal heap to use */ + /* 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") - /* 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") + /* Get handle for shared object heap, if attributes are sharable */ + if(attr_sharable) { + haddr_t shared_fheap_addr; /* Address of fractal heap to use */ - /* 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 */ + /* 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") - /* Construct the user data for v2 B-tree iterator callback */ - udata.f = f; - udata.dxpl_id = dxpl_id; - udata.fheap = fheap; - udata.shared_fheap = shared_fheap; - udata.loc_id = loc_id; - udata.skip = skip; - udata.count = 0; - udata.attr_op = attr_op; - udata.op_data = op_data; - - /* Iterate over the records in the v2 B-tree's "native" order */ - /* (by hash of name) */ - if((ret_value = H5B2_iterate(f, dxpl_id, H5A_BT2_NAME, name_bt2_addr, - H5A_dense_iterate_bt2_cb, &udata)) < 0) - HERROR(H5E_ATTR, H5E_BADITER, "attribute iteration failed"); - - /* Update last attribute looked at */ - if(last_attr) - *last_attr = udata.count; + /* 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 */ + + /* Construct the user data for v2 B-tree iterator callback */ + udata.f = f; + udata.dxpl_id = dxpl_id; + udata.fheap = fheap; + udata.shared_fheap = shared_fheap; + udata.loc_id = loc_id; + udata.skip = skip; + udata.count = 0; + udata.attr_op = attr_op; + udata.op_data = op_data; + + /* Iterate over the records in the v2 B-tree's "native" order */ + /* (by hash of name) */ + if((ret_value = H5B2_iterate(f, dxpl_id, H5A_BT2_NAME, name_bt2_addr, + H5A_dense_iterate_bt2_cb, &udata)) < 0) + HERROR(H5E_ATTR, H5E_BADITER, "attribute iteration failed"); + + /* Update last attribute looked at */ + if(last_attr) + *last_attr = udata.count; + } /* end if */ + else { + /* Build the table of attributes for this object */ + if(H5A_dense_build_table(f, dxpl_id, nrec, attr_fheap_addr, name_bt2_addr, + H5_INDEX_NAME, order, &atable) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "error building table of attributes") + + /* Iterate over attributes in table */ + if((ret_value = H5A_attr_iterate_table(&atable, skip, last_attr, loc_id, attr_op, op_data)) < 0) + HERROR(H5E_ATTR, H5E_CANTNEXT, "iteration operator failed"); + } /* end else */ done: /* Release resources */ @@ -1121,6 +896,8 @@ 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(atable.attrs && H5A_attr_release_table(&atable) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to release attribute table") FUNC_LEAVE_NOAPI(ret_value) } /* end H5A_dense_iterate() */ diff --git a/src/H5Aint.c b/src/H5Aint.c new file mode 100644 index 0000000..1d6e9ab --- /dev/null +++ b/src/H5Aint.c @@ -0,0 +1,511 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5Aint.c + * Dec 18 2006 + * Quincey Koziol <koziol@hdfgroup.org> + * + * Purpose: Internal routines for managing attributes. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5A_PACKAGE /*suppress error about including H5Apkg */ +#define H5O_PACKAGE /*suppress error about including H5Opkg */ + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Apkg.h" /* Attributes */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Opkg.h" /* Object headers */ + + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + +/* Data exchange structure to use when building table of compact attributes for an object */ +typedef struct { + H5F_t *f; /* Pointer to file that fractal heap is in */ + hid_t dxpl_id; /* DXPL for operation */ + H5A_attr_table_t *atable; /* Pointer to attribute table to build */ + size_t curr_attr; /* Current attribute to operate on */ +} H5A_compact_bt_ud_t; + +/* Data exchange structure to use when building table of dense attributes for an object */ +typedef struct { + H5A_attr_table_t *atable; /* Pointer to attribute table to build */ + size_t curr_attr; /* Current attribute to operate on */ +} H5A_dense_bt_ud_t; + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + +static herr_t H5A_compact_build_table_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/, + unsigned sequence, unsigned *oh_flags_ptr, void *_udata/*in,out*/); +static herr_t H5A_dense_build_table_cb(const H5A_t *attr, void *_udata); +static int H5A_attr_cmp_name_inc(const void *attr1, const void *attr2); +static herr_t H5A_attr_sort_table(H5A_attr_table_t *atable, H5_index_t idx_type, + H5_iter_order_t order); + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + + +/*------------------------------------------------------------------------- + * Function: H5A_compact_build_table_cb + * + * Purpose: Object header iterator callback routine to copy attribute + * into table. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Dec 18 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5A_compact_build_table_cb(H5O_t UNUSED *oh, H5O_mesg_t *mesg/*in,out*/, + unsigned UNUSED sequence, unsigned UNUSED *oh_flags_ptr, void *_udata/*in,out*/) +{ + H5A_compact_bt_ud_t *udata = (H5A_compact_bt_ud_t *)_udata; /* Operator user data */ + herr_t ret_value = H5_ITER_CONT; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5A_compact_build_table_cb) + + /* check args */ + HDassert(mesg); + + /* 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, + n * sizeof(H5A_t)); + + if(!table) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "unable to extend attribute table") + udata->atable->attrs = table; + udata->atable->nattrs = n; + } /* end if */ + + /* Check for shared message */ + if(mesg->flags & H5O_MSG_FLAG_SHARED) { + /* + * 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, &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)) + HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute") + } /* end else */ + + /* Increment current attribute */ + udata->curr_attr++; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5A_compact_build_table_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5A_compact_build_table + * + * Purpose: Builds a table containing a sorted list of attributes for + * an object + * + * Note: Used for building table of attributes in non-native iteration + * order for an index + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Dec 18, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5A_compact_build_table(H5F_t *f, hid_t dxpl_id, H5O_t *oh, + H5_index_t UNUSED idx_type, H5_iter_order_t order, + H5A_attr_table_t *atable, unsigned *oh_flags) +{ + H5A_compact_bt_ud_t udata; /* User data for iteration callback */ + H5O_mesg_operator_t op; /* Wrapper for operator */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5A_compact_build_table) + + /* Sanity check */ + HDassert(f); + HDassert(oh); + HDassert(atable); + + /* Initialize table */ + atable->attrs = NULL; + atable->nattrs = 0; + + /* Set up user data for iteration */ + udata.f = f; + udata.dxpl_id = dxpl_id; + udata.atable = atable; + udata.curr_attr = 0; + + /* Iterate over existing attributes, checking for attribute with same name */ + op.lib_op = H5A_compact_build_table_cb; + if(H5O_msg_iterate_real(f, oh, H5O_MSG_ATTR, TRUE, op, &udata, dxpl_id, oh_flags) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_BADITER, FAIL, "error building attribute table") + + /* Correct # of attributes in table */ + atable->nattrs = udata.curr_attr; + + /* Sort attribute table in correct iteration order */ + if(H5A_attr_sort_table(atable, H5_INDEX_NAME, order) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTSORT, FAIL, "error sorting attribute table") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5A_compact_build_table() */ + + +/*------------------------------------------------------------------------- + * Function: H5A_dense_build_table_cb + * + * Purpose: Callback routine for building table of attributes from dense + * attribute storage. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Dec 11 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5A_dense_build_table_cb(const H5A_t *attr, 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 */ + + FUNC_ENTER_NOAPI_NOINIT(H5A_dense_build_table_cb) + + /* check arguments */ + HDassert(attr); + HDassert(udata); + HDassert(udata->curr_attr < udata->atable->nattrs); + + /* Copy attribute information */ + if(NULL == H5A_copy(&udata->atable->attrs[udata->curr_attr], attr)) + HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute") + + /* Increment number of attributes stored */ + udata->curr_attr++; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5A_dense_build_table_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5A_dense_build_table + * + * Purpose: Builds a table containing a sorted list of attributes for + * an object + * + * Note: Used for building table of attributes in non-native iteration + * order for an index + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Dec 11, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5A_dense_build_table(H5F_t *f, hid_t dxpl_id, hsize_t nattrs, haddr_t attr_fheap_addr, + haddr_t name_bt2_addr, H5_index_t UNUSED idx_type, H5_iter_order_t order, + H5A_attr_table_t *atable) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5A_dense_build_table) + + /* Sanity check */ + HDassert(f); + HDassert(H5F_addr_defined(attr_fheap_addr)); + HDassert(H5F_addr_defined(name_bt2_addr)); + HDassert(atable); + + /* Set size of table */ + H5_CHECK_OVERFLOW(nattrs, /* From: */ hsize_t, /* To: */ size_t); + atable->nattrs = (size_t)nattrs; + + /* Allocate space for the table entries */ + if(atable->nattrs > 0) { + H5A_dense_bt_ud_t udata; /* User data for iteration callback */ + 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) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Set up user data for iteration */ + udata.atable = atable; + udata.curr_attr = 0; + + /* Build iterator operator */ + attr_op.op_type = H5A_ATTR_OP_LIB; + attr_op.u.lib_op = H5A_dense_build_table_cb; + + /* Iterate over the links in the group, building a table of the link messages */ + if(H5A_dense_iterate(f, dxpl_id, (hid_t)0, attr_fheap_addr, name_bt2_addr, + H5_ITER_NATIVE, (unsigned)0, NULL, &attr_op, &udata) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "error building attribute table") + + /* Sort attribute table in correct iteration order */ + if(H5A_attr_sort_table(atable, H5_INDEX_NAME, order) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTSORT, FAIL, "error sorting attribute table") + } /* end if */ + else + atable->attrs = NULL; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5A_dense_build_table() */ + + +/*------------------------------------------------------------------------- + * Function: H5A_attr_cmp_name_inc + * + * Purpose: Callback routine for comparing two attribute names, in + * increasing alphabetic order + * + * Return: An integer less than, equal to, or greater than zero if the + * first argument is considered to be respectively less than, + * equal to, or greater than the second. If two members compare + * as equal, their order in the sorted array is undefined. + * (i.e. same as strcmp()) + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Dec 11 2005 + * + *------------------------------------------------------------------------- + */ +static int +H5A_attr_cmp_name_inc(const void *attr1, const void *attr2) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_attr_cmp_name_inc) + + FUNC_LEAVE_NOAPI(HDstrcmp(((const H5A_t *)attr1)->name, ((const H5A_t *)attr2)->name)) +} /* end H5A_attr_cmp_name_inc() */ + + +/*------------------------------------------------------------------------- + * Function: H5A_attr_sort_table + * + * Purpose: Sort table containing a list of attributes for an object + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Dec 11, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5A_attr_sort_table(H5A_attr_table_t *atable, H5_index_t idx_type, + H5_iter_order_t order) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_attr_sort_table) + + /* Sanity check */ + HDassert(atable); + + /* Pick appropriate comparison routine */ +#ifdef NOT_YET + if(idx_type == H5_INDEX_NAME) { +#else /* NOT_YET */ +HDassert(idx_type == H5_INDEX_NAME); +#endif /* NOT_YET */ + if(order == H5_ITER_INC) + HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t), H5A_attr_cmp_name_inc); +#ifdef NOT_YET + else if(order == H5_ITER_DEC) + HDqsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G_link_cmp_name_dec); +#endif /* NOT_YET */ + else + HDassert(order == H5_ITER_NATIVE); +#ifdef NOT_YET + } /* end if */ + else { + HDassert(idx_type == H5_INDEX_CRT_ORDER); + if(order == H5_ITER_INC) + HDqsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G_link_cmp_corder_inc); + else if(order == H5_ITER_DEC) + HDqsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G_link_cmp_corder_dec); + else + HDassert(order == H5_ITER_NATIVE); + } /* end else */ +#endif /* NOT_YET */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5A_attr_sort_table() */ + + +/*------------------------------------------------------------------------- + * Function: H5A_attr_iterate_table + * + * Purpose: Iterate over table containing a list of attributes for an object, + * making appropriate callbacks + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Dec 18, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5A_attr_iterate_table(const H5A_attr_table_t *atable, unsigned skip, + unsigned *last_attr, hid_t loc_id, const H5A_attr_iter_op_t *attr_op, + void *op_data) +{ + size_t u; /* Local index variable */ + herr_t ret_value = H5_ITER_CONT; /* Return value */ + + FUNC_ENTER_NOAPI(H5A_attr_iterate_table, FAIL) + + /* Sanity check */ + HDassert(atable); + HDassert(attr_op); + + /* Skip over attributes, if requested */ + if(last_attr) + *last_attr = skip; + + /* Iterate over attribute messages */ + H5_ASSIGN_OVERFLOW(/* To: */ u, /* From: */ skip, /* From: */ unsigned, /* To: */ size_t) + for(; u < atable->nattrs && !ret_value; u++) { + /* Check which type of callback to make */ + switch(attr_op->op_type) { + case H5A_ATTR_OP_APP: + /* Make the application callback */ + ret_value = (attr_op->u.app_op)(loc_id, atable->attrs[u].name, op_data); + break; + + case H5A_ATTR_OP_LIB: + /* Call the library's callback */ + ret_value = (attr_op->u.lib_op)(&(atable->attrs[u]), op_data); + } /* end switch */ + + /* Increment the number of entries passed through */ + if(last_attr) + (*last_attr)++; + } /* end for */ + + /* Check for callback failure and pass along return value */ + if(ret_value < 0) + HERROR(H5E_ATTR, H5E_CANTNEXT, "iteration operator failed"); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5A_attr_iterate_table() */ + + +/*------------------------------------------------------------------------- + * Function: H5A_attr_release_table + * + * Purpose: Release table containing a list of attributes for an object + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Dec 11, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5A_attr_release_table(H5A_attr_table_t *atable) +{ + size_t u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5A_attr_release_table) + + /* Sanity check */ + HDassert(atable); + + /* Release attribute info, if any */ + if(atable->nattrs > 0) { + /* Free attribute message information */ + for(u = 0; u < atable->nattrs; u++) + if(H5A_free(&(atable->attrs[u])) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to release attribute") + + /* Free table of attributes */ + H5MM_xfree(atable->attrs); + } /* end if */ + else + HDassert(atable->attrs == NULL); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5A_attr_release_table() */ + diff --git a/src/H5Apkg.h b/src/H5Apkg.h index 5f8d477..ca7983f 100644 --- a/src/H5Apkg.h +++ b/src/H5Apkg.h @@ -119,15 +119,13 @@ typedef struct H5A_bt2_ud_ins_t { typedef struct { size_t nattrs; /* # of attributes in table */ H5A_t *attrs; /* Pointer to array of attributes */ - uint8_t *flags; /* Pointer to array of message flags for attributes */ } H5A_attr_table_t; /* Attribute iteration operator for internal library callbacks */ -typedef herr_t (*H5A_lib_iterate_t)(const H5A_t *attr, unsigned mesg_flags, - void *op_data); +typedef herr_t (*H5A_lib_iterate_t)(const H5A_t *attr, void *op_data); /* Describe kind of callback to make for each attribute */ -typedef struct { +struct H5A_attr_iter_op_t { enum { H5A_ATTR_OP_APP, /* Application callback */ H5A_ATTR_OP_LIB /* Library internal callback */ @@ -136,7 +134,7 @@ typedef struct { H5A_operator_t app_op; /* Application callback for each attribute */ H5A_lib_iterate_t lib_op; /* Library internal callback for each attribute */ } u; -} H5A_attr_iterate_t; +}; /*****************************/ @@ -169,16 +167,24 @@ H5_DLL H5A_t *H5A_dense_open(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, H5_DLL herr_t H5A_dense_write(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const H5A_t *attr); 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, unsigned skip, - unsigned *last_attr, const H5A_attr_iterate_t *attr_op, void *op_data); + 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, + 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, - H5_index_t idx_type, H5_iter_order_t order, H5A_attr_table_t *atable); +H5_DLL herr_t H5A_compact_build_table(H5F_t *f, hid_t dxpl_id, H5O_t *oh, + H5_index_t idx_type, H5_iter_order_t order, H5A_attr_table_t *atable, + unsigned *oh_flags); +H5_DLL herr_t H5A_dense_build_table(H5F_t *f, hid_t dxpl_id, hsize_t nattrs, + haddr_t attr_fheap_addr, haddr_t name_bt2_addr, H5_index_t idx_type, + H5_iter_order_t order, H5A_attr_table_t *atable); +H5_DLL herr_t H5A_attr_iterate_table(const H5A_attr_table_t *atable, + unsigned skip, unsigned *last_attr, hid_t loc_id, + const H5A_attr_iter_op_t *attr_op, void *op_data); H5_DLL herr_t H5A_attr_release_table(H5A_attr_table_t *atable); /* Attribute object header routines */ diff --git a/src/H5Aprivate.h b/src/H5Aprivate.h index 75ccafd..ca14ebc 100644 --- a/src/H5Aprivate.h +++ b/src/H5Aprivate.h @@ -36,6 +36,7 @@ /* Forward references of package typedefs */ typedef struct H5A_t H5A_t; +typedef struct H5A_attr_iter_op_t H5A_attr_iter_op_t; /*****************************/ diff --git a/src/H5Gdense.c b/src/H5Gdense.c index b0924ba..aaa2ea3 100644 --- a/src/H5Gdense.c +++ b/src/H5Gdense.c @@ -90,7 +90,7 @@ typedef struct { /* downward (from application) */ hid_t gid; /* Group ID for application callback */ hsize_t skip; /* Number of links to skip */ - hsize_t *last_lnk; /* Pointer to the last link operated on */ + hsize_t count; /* Count of records operated on */ const H5G_link_iterate_t *lnk_op; /* Callback for each link */ void *op_data; /* Callback data for each link */ @@ -722,7 +722,7 @@ done: if(fheap && H5HF_close(fheap, dxpl_id) < 0) HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close fractal heap") if(ltable.lnks && H5G_link_release_table(<able) < 0) - HDONE_ERROR(H5E_SYM, H5E_CANTFREE, H5G_UNKNOWN, "unable to release link table") + HDONE_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link table") FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_dense_lookup_by_idx() */ @@ -940,8 +940,7 @@ H5G_dense_iterate_bt2_cb(const void *_record, void *_bt2_udata) /* Increment the number of entries passed through */ /* (whether we skipped them or not) */ - if(bt2_udata->last_lnk) - (*bt2_udata->last_lnk)++; + bt2_udata->count++; /* Check for callback failure and pass along return value */ if(ret_value < 0) @@ -983,10 +982,6 @@ H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, HDassert(linfo); HDassert(lnk_op && lnk_op->u.lib_op); - /* Open the fractal heap */ - if(NULL == (fheap = H5HF_open(f, dxpl_id, linfo->link_fheap_addr))) - HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap") - /* Check for skipping too many links */ if(skip > 0) { hsize_t nrec; /* # of records in v2 B-tree */ @@ -1006,13 +1001,17 @@ H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, if(order == H5_ITER_NATIVE) { H5G_bt2_ud_it_t udata; /* User data for iterator callback */ + /* Open the fractal heap */ + if(NULL == (fheap = H5HF_open(f, dxpl_id, linfo->link_fheap_addr))) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap") + /* Construct the user data for v2 B-tree iterator callback */ udata.f = f; udata.dxpl_id = dxpl_id; udata.fheap = fheap; udata.gid = gid; udata.skip = skip; - udata.last_lnk = last_lnk; + udata.count = 0; udata.lnk_op = lnk_op; udata.op_data = op_data; @@ -1021,6 +1020,10 @@ H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, if((ret_value = H5B2_iterate(f, dxpl_id, H5G_BT2_NAME, linfo->name_bt2_addr, H5G_dense_iterate_bt2_cb, &udata)) < 0) HERROR(H5E_SYM, H5E_BADITER, "link iteration failed"); + + /* Update last link looked at */ + if(last_lnk) + *last_lnk = udata.count; } /* end if */ else { /* Build the table of links for this group */ @@ -1037,7 +1040,7 @@ done: if(fheap && H5HF_close(fheap, dxpl_id) < 0) HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close fractal heap") if(ltable.lnks && H5G_link_release_table(<able) < 0) - HDONE_ERROR(H5E_SYM, H5E_CANTFREE, H5G_UNKNOWN, "unable to release link table") + HDONE_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link table") FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_dense_iterate() */ @@ -1236,7 +1239,7 @@ done: if(fheap && H5HF_close(fheap, dxpl_id) < 0) HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close fractal heap") if(ltable.lnks && H5G_link_release_table(<able) < 0) - HDONE_ERROR(H5E_SYM, H5E_CANTFREE, H5G_UNKNOWN, "unable to release link table") + HDONE_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link table") FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_dense_get_name_by_idx() */ @@ -1726,7 +1729,7 @@ done: if(fheap && H5HF_close(fheap, dxpl_id) < 0) HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close fractal heap") if(ltable.lnks && H5G_link_release_table(<able) < 0) - HDONE_ERROR(H5E_SYM, H5E_CANTFREE, H5G_UNKNOWN, "unable to release link table") + HDONE_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link table") FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_dense_remove_by_idx() */ diff --git a/src/H5Oattr.c b/src/H5Oattr.c index 8b8edc5..75b7d3a 100644 --- a/src/H5Oattr.c +++ b/src/H5Oattr.c @@ -1092,7 +1092,7 @@ H5O_attr_get_share(const void *_mesg, H5O_shared_t *sh /*out*/) FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_attr_get_share) - HDassert (mesg); + HDassert(mesg); ret_value = H5O_msg_copy(H5O_SHARED_ID, &(mesg->sh_loc), sh); @@ -1120,8 +1120,8 @@ H5O_attr_set_share(void *_mesg/*in,out*/, const H5O_shared_t *sh) FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_attr_set_share) - HDassert (mesg); - HDassert (sh); + HDassert(mesg); + HDassert(sh); if(NULL == H5O_msg_copy(H5O_SHARED_ID, sh, &(mesg->sh_loc))) ret_value = FAIL; @@ -1159,7 +1159,7 @@ H5O_attr_is_shared(const void *_mesg) * library read a "committed attribute" if we ever create one in * the future. */ - if(mesg->sh_loc.flags & (H5O_COMMITTED_FLAG | H5O_SHARED_IN_HEAP_FLAG)) + if(H5O_IS_SHARED(mesg->sh_loc.flags)) ret_value = TRUE; else ret_value = FALSE; diff --git a/src/H5Oattribute.c b/src/H5Oattribute.c index 4e1532c..2d43d9b 100644 --- a/src/H5Oattribute.c +++ b/src/H5Oattribute.c @@ -374,7 +374,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5O_attr_open + * Function: H5O_attr_open_by_name * * Purpose: Open an existing attribute in an object header. * @@ -386,13 +386,13 @@ done: *------------------------------------------------------------------------- */ H5A_t * -H5O_attr_open(const H5O_loc_t *loc, const char *name, hid_t dxpl_id) +H5O_attr_open_by_name(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 */ H5A_t *ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5O_attr_open) + FUNC_ENTER_NOAPI_NOINIT(H5O_attr_open_by_name) /* Check arguments */ HDassert(loc); @@ -443,7 +443,79 @@ done: HDONE_ERROR(H5E_ATTR, H5E_PROTECT, NULL, "unable to release object header") FUNC_LEAVE_NOAPI(ret_value) -} /* end H5O_attr_open */ +} /* end H5O_attr_open_by_name() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_attr_open_by_idx + * + * Purpose: Callback routine opening an attribute by index + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Dec 18 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_attr_open_by_idx_cb(const H5A_t *attr, void *_ret_attr) +{ + H5A_t **ret_attr = (H5A_t **)_ret_attr; /* 'User data' passed in */ + herr_t ret_value = H5_ITER_STOP; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_attr_open_by_idx_cb) + + /* check arguments */ + HDassert(attr); + HDassert(ret_attr); + + /* Copy attribute information */ + if(NULL == (*ret_attr = H5A_copy(NULL, attr))) + HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_attr_open_by_idx_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_attr_open_by_idx + * + * Purpose: Open an existing attribute in an object header according to + * an index. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Monday, December 18, 2006 + * + *------------------------------------------------------------------------- + */ +H5A_t * +H5O_attr_open_by_idx(const H5O_loc_t *loc, hsize_t n, hid_t dxpl_id) +{ + H5A_attr_iter_op_t attr_op; /* Attribute operator */ + H5A_t *ret_value = NULL; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_attr_open_by_idx) + + /* Check arguments */ + HDassert(loc); + + /* Build attribute operator info */ + attr_op.op_type = H5A_ATTR_OP_LIB; + attr_op.u.lib_op = H5O_attr_open_by_idx_cb; + + /* Iterate over attributes to locate correct one */ + if(H5O_attr_iterate((hid_t)-1, loc, dxpl_id, H5_ITER_INC, (unsigned)n, NULL, &attr_op, &ret_value) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_BADITER, NULL, "can't locate attribute") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_attr_open_by_idx() */ /*------------------------------------------------------------------------- @@ -613,7 +685,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5O_attr_rename_dup_cb + * Function: H5O_attr_rename_chk_cb * * Purpose: Object header iterator callback routine to check for * duplicate name during rename @@ -627,13 +699,13 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5O_attr_rename_dup_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/, +H5O_attr_rename_chk_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/, unsigned UNUSED sequence, unsigned UNUSED *oh_flags_ptr, void *_udata/*in,out*/) { H5O_iter_ren_t *udata = (H5O_iter_ren_t *)_udata; /* Operator user data */ herr_t ret_value = H5_ITER_CONT; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5O_attr_rename_dup_cb) + FUNC_ENTER_NOAPI_NOINIT(H5O_attr_rename_chk_cb) /* check args */ HDassert(oh); @@ -677,7 +749,7 @@ H5O_attr_rename_dup_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/, done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5O_attr_rename_dup_cb() */ +} /* end H5O_attr_rename_chk_cb() */ /*------------------------------------------------------------------------- @@ -804,7 +876,7 @@ HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "renaming attributes in dense stora udata.found = FALSE; /* Iterate over attributes, to check if "new name" exists already */ - op.lib_op = H5O_attr_rename_dup_cb; + op.lib_op = H5O_attr_rename_chk_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_CANTUPDATE, FAIL, "error updating attribute") @@ -844,87 +916,72 @@ done: */ herr_t H5O_attr_iterate(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id, - unsigned skip, unsigned *last_attr, H5A_operator_t op, void *op_data) + H5_iter_order_t order, unsigned skip, unsigned *last_attr, + const H5A_attr_iter_op_t *attr_op, void *op_data) { H5O_t *oh = NULL; /* Pointer to actual object header */ - haddr_t attr_fheap_addr; /* Address of fractal heap for dense attribute storage */ - haddr_t name_bt2_addr; /* Address of v2 B-tree for name index on dense attribute storage */ + unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */ + H5A_attr_table_t atable = {0, NULL}; /* Table of attributes */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_attr_iterate) /* Check arguments */ HDassert(loc); - HDassert(op); + HDassert(attr_op); /* 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") - /* Retrieve the information about dense attribute storage */ + /* Check for attributes stored densely */ if(oh->version > H5O_VERSION_1 && H5F_addr_defined(oh->attr_fheap_addr)) { + haddr_t attr_fheap_addr; /* Address of fractal heap for dense attribute storage */ + haddr_t name_bt2_addr; /* Address of v2 B-tree for name index on dense attribute storage */ + + /* Retrieve the information about dense attribute storage */ attr_fheap_addr = oh->attr_fheap_addr; name_bt2_addr = oh->name_bt2_addr; - } /* end if */ - else - attr_fheap_addr = name_bt2_addr = HADDR_UNDEF; - /* Release the object header */ - if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_PROTECT, FAIL, "unable to release object header") - oh = NULL; - - /* Check for attributes stored densely */ - if(H5F_addr_defined(attr_fheap_addr)) { - H5A_attr_iterate_t attr_op; /* Attribute operator */ - - /* Build attribute operator info */ - attr_op.op_type = H5A_ATTR_OP_APP; - attr_op.u.app_op = op; + /* Release the object header */ + if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_PROTECT, FAIL, "unable to release object header") + oh = NULL; + /* Iterate over attributes in dense storage */ if((ret_value = H5A_dense_iterate(loc->file, dxpl_id, loc_id, attr_fheap_addr, - name_bt2_addr, skip, last_attr, &attr_op, op_data)) < 0) + name_bt2_addr, order, skip, last_attr, attr_op, op_data)) < 0) HERROR(H5E_ATTR, H5E_BADITER, "error iterating over attributes"); } /* end if */ else { - unsigned idx; /* Current attribute to operate on */ - - /* Check for skipping over too many attributes */ - if((int)skip < H5O_msg_count(loc, H5O_ATTR_ID, dxpl_id)) { - H5A_t found_attr; /* Copy of attribute for callback */ - - /* Read each attribute and call application's callback */ - /* (this could be made more efficient by iterating over the - * attribute header messages with H5O_msg_iterate, but then - * the object header would be locked during the callback into - * the application code, causing problems if they attempt to - * do anything with the object the attribute is on - QAK) - */ - idx = skip; - while(H5O_msg_read(loc, H5O_ATTR_ID, (int)idx, &found_attr, dxpl_id) != NULL) { - /* Call application's callback */ - idx++; - if((ret_value = (op)(loc_id, found_attr.name, op_data)) != 0) { - H5A_free(&found_attr); - break; - } /* end if */ - H5A_free(&found_attr); - } /* end while */ - - /* Clear error stack from running off end of attributes */ - if(ret_value == 0) - H5E_clear_stack(NULL); - } /* end if */ - else - if(skip > 0) + /* Build table of attributes for compact storage */ + if(H5A_compact_build_table(loc->file, dxpl_id, oh, H5_INDEX_NAME, H5_ITER_INC, &atable, &oh_flags) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "error building attribute table") + + /* Release the object header */ + if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_PROTECT, FAIL, "unable to release object header") + oh = NULL; + + /* Check for skipping too many attributes */ + if(skip > 0) { + /* Check for bad starting index */ + if(skip >= atable.nattrs) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified") + } /* end if */ - /* Update last attribute looked at */ - if(last_attr) - *last_attr = idx; + /* Iterate over attributes in table */ + if((ret_value = H5A_attr_iterate_table(&atable, skip, last_attr, loc_id, attr_op, op_data)) < 0) + HERROR(H5E_ATTR, H5E_CANTNEXT, "iteration operator failed"); } /* end else */ done: + /* Release resources */ + 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") + if(atable.attrs && H5A_attr_release_table(&atable) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to release attribute table") + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_attr_iterate */ @@ -1079,12 +1136,12 @@ H5O_attr_remove(const H5O_loc_t *loc, const char *name, hid_t dxpl_id) HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete dense attribute storage") } /* end if */ else { - H5A_attr_table_t atable = {0, NULL, NULL}; /* Table of attributes */ + H5A_attr_table_t atable = {0, NULL}; /* Table of attributes */ hbool_t can_convert = TRUE; /* Whether converting to attribute messages is possible */ size_t u; /* Local index */ /* Build the table of attributes for this object */ - if(H5A_dense_build_table(loc->file, dxpl_id, oh, H5_INDEX_NAME, H5_ITER_NATIVE, &atable) < 0) + if(H5A_dense_build_table(loc->file, dxpl_id, oh->nattrs, oh->attr_fheap_addr, oh->name_bt2_addr, H5_INDEX_NAME, H5_ITER_NATIVE, &atable) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "error building attribute table") /* Inspect attributes in table for ones that can't be converted back @@ -1100,8 +1157,13 @@ H5O_attr_remove(const H5O_loc_t *loc, const char *name, hid_t dxpl_id) /* If ok, insert attributes as object header messages */ if(can_convert) { /* Insert attribute messages into object header */ + /* (Set the "shared" message flag for all attributes added - + * attributes that are actually shared will be converted + * to shared messages and attributes that are not shared + * will have the flag turned off -QAK) + */ for(u = 0; u < oh->nattrs; u++) - if(H5O_msg_append_real(loc->file, dxpl_id, oh, H5O_MSG_ATTR, (unsigned)atable.flags[u], H5O_UPDATE_TIME, &(atable.attrs[u]), &oh_flags) < 0) + if(H5O_msg_append_real(loc->file, dxpl_id, oh, H5O_MSG_ATTR, H5O_MSG_FLAG_SHARED, H5O_UPDATE_TIME, &(atable.attrs[u]), &oh_flags) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "can't create message") /* Remove the dense storage */ diff --git a/src/H5Opkg.h b/src/H5Opkg.h index 8b52c2e..2b367db 100644 --- a/src/H5Opkg.h +++ b/src/H5Opkg.h @@ -421,14 +421,17 @@ H5_DLL void * H5O_shared_read(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *share /* Attribute operations */ H5_DLL herr_t H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr); -H5_DLL H5A_t *H5O_attr_open(const H5O_loc_t *loc, const char *name, +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, hsize_t n, hid_t dxpl_id); 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, const char *old_name, const char *new_name); H5_DLL herr_t H5O_attr_iterate(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id, - unsigned skip, unsigned *last_attr, H5A_operator_t op, void *op_data); + H5_iter_order_t order, unsigned skip, unsigned *last_attr, + const H5A_attr_iter_op_t *op, void *op_data); 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); @@ -1185,3 +1185,33 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5SM_get_info() */ + +/*------------------------------------------------------------------------- + * Function: H5SM_reconstitute + * + * Purpose: Reconstitute a shared object header message structure from + * a plain heap ID. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Monday, December 18, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5SM_reconstitute(H5O_shared_t *sh_mesg, const uint8_t *heap_id) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_reconstitute) + + /* Sanity check args */ + HDassert(sh_mesg); + HDassert(heap_id); + + /* Set flag for shared message */ + sh_mesg->flags = H5O_SHARED_IN_HEAP_FLAG; + HDmemcpy(&sh_mesg->u.heap_id, heap_id, H5SM_FHEAP_ID_LEN); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5SM_reconstitute() */ + diff --git a/src/H5SMprivate.h b/src/H5SMprivate.h index 2308167..fd421e1 100755 --- a/src/H5SMprivate.h +++ b/src/H5SMprivate.h @@ -50,6 +50,7 @@ H5_DLL herr_t H5SM_get_info(H5F_t *f, unsigned *index_flags, unsigned *minsizes, unsigned *list_to_btree, unsigned *btree_to_list, hid_t dxpl_id); H5_DLL htri_t H5SM_type_shared(H5F_t *f, unsigned type_id, hid_t dxpl_id); H5_DLL haddr_t H5SM_get_fheap_addr(H5F_t *f, unsigned type_id, hid_t dxpl_id); +H5_DLL herr_t H5SM_reconstitute(H5O_shared_t *sh_mesg, const uint8_t *heap_id); #endif /*_H5SMprivate_H*/ diff --git a/src/Makefile.am b/src/Makefile.am index 44c318f..630e7fb 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -41,7 +41,8 @@ DISTCLEANFILES=H5pubconf.h # library sources libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ - H5A.c H5Abtree2.c H5Adense.c H5Adeprec.c H5AC.c H5B.c H5Bcache.c \ + H5A.c H5Abtree2.c H5Adense.c H5Adeprec.c H5Aint.c \ + H5AC.c H5B.c H5Bcache.c \ H5B2.c H5B2cache.c H5B2dbg.c H5B2int.c H5B2stat.c H5B2test.c \ H5C.c H5CS.c H5D.c H5Dcompact.c H5Dcontig.c \ H5Defl.c H5Dio.c H5Distore.c H5Dmpio.c H5Doh.c H5Dselect.c H5Dtest.c \ diff --git a/src/Makefile.in b/src/Makefile.in index 9221d38..90d13cd 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -82,7 +82,7 @@ LTLIBRARIES = $(lib_LTLIBRARIES) libhdf5_la_LIBADD = am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \ H5timer.lo H5trace.lo H5A.lo H5Abtree2.lo H5Adense.lo \ - H5Adeprec.lo H5AC.lo H5B.lo H5Bcache.lo H5B2.lo H5B2cache.lo \ + H5Adeprec.lo H5Aint.lo H5AC.lo H5B.lo H5Bcache.lo H5B2.lo H5B2cache.lo \ H5B2dbg.lo H5B2int.lo H5B2stat.lo H5B2test.lo H5C.lo H5CS.lo \ H5D.lo H5Dcompact.lo H5Dcontig.lo H5Defl.lo H5Dio.lo \ H5Distore.lo H5Dmpio.lo H5Doh.lo H5Dselect.lo H5Dtest.lo \ @@ -398,7 +398,7 @@ DISTCLEANFILES = H5pubconf.h # library sources libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ - H5A.c H5Abtree2.c H5Adense.c H5Adeprec.c H5AC.c H5B.c H5Bcache.c \ + H5A.c H5Abtree2.c H5Adense.c H5Adeprec.c H5Aint.c H5AC.c H5B.c H5Bcache.c \ H5B2.c H5B2cache.c H5B2dbg.c H5B2int.c H5B2stat.c H5B2test.c \ H5C.c H5CS.c H5D.c H5Dcompact.c H5Dcontig.c \ H5Defl.c H5Dio.c H5Distore.c H5Dmpio.c H5Doh.c H5Dselect.c H5Dtest.c \ @@ -572,6 +572,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Abtree2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Adense.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Adeprec.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Aint.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5B.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5B2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5B2cache.Plo@am__quote@ diff --git a/test/tattr.c b/test/tattr.c index 3e7e73d..5860dae 100644 --- a/test/tattr.c +++ b/test/tattr.c @@ -1683,6 +1683,65 @@ test_attr_dtype_shared(hid_t fapl) /**************************************************************** ** +** test_attr_dense_verify(): Test basic H5A (attribute) code. +** Verify attributes on object +** +****************************************************************/ +static void +test_attr_dense_verify(hid_t loc_id, unsigned max_attr) +{ + char attrname[NAME_BUF_SIZE]; /* Name of attribute */ + hid_t attr; /* Attribute ID */ + unsigned value; /* Attribute value */ + unsigned u; /* Local index variable */ + herr_t ret; /* Generic return value */ + + /* Re-open all the attributes by name and verify the data */ + for(u = 0; u < max_attr; u++) { + /* Open attribute */ + sprintf(attrname, "attr %02u", u); + attr = H5Aopen_name(loc_id, attrname); + CHECK(attr, FAIL, "H5Aopen"); + + /* Read data from the attribute */ + ret = H5Aread(attr, H5T_NATIVE_UINT, &value); + CHECK(ret, FAIL, "H5Aread"); + VERIFY(value, u, "H5Aread"); + + /* Close attribute */ + ret = H5Aclose(attr); + CHECK(ret, FAIL, "H5Aclose"); + } /* end for */ + + /* Re-open all the attributes by index and verify the data */ + for(u = 0; u < max_attr; u++) { + size_t name_len; /* Length of attribute name */ + char check_name[ATTR_NAME_LEN]; /* Buffer for checking attribute names */ + + /* Open attribute */ + attr = H5Aopen_idx(loc_id, u); + CHECK(attr, FAIL, "H5Aopen_idx"); + + /* Verify Name */ + sprintf(attrname, "attr %02u", u); + name_len = H5Aget_name(attr, (size_t)ATTR_NAME_LEN, check_name); + VERIFY(name_len, HDstrlen(attrname), "H5Aget_name"); + if(HDstrcmp(check_name, attrname)) + TestErrPrintf("attribute name different: attr_name = '%s', should be '%s'\n", check_name, attrname); + + /* Read data from the attribute */ + ret = H5Aread(attr, H5T_NATIVE_UINT, &value); + CHECK(ret, FAIL, "H5Aread"); + VERIFY(value, u, "H5Aread"); + + /* Close attribute */ + ret = H5Aclose(attr); + CHECK(ret, FAIL, "H5Aclose"); + } /* end for */ +} /* test_attr_dense_verify() */ + +/**************************************************************** +** ** test_attr_dense_create(): Test basic H5A (attribute) code. ** Tests "dense" attribute storage creation ** @@ -1852,6 +1911,9 @@ HDfprintf(stderr, "max_compact = %u, min_dense = %u\n", max_compact, min_dense); /* Close attribute */ ret = H5Aclose(attr); CHECK(ret, FAIL, "H5Aclose"); + + /* Verify attributes written so far */ + test_attr_dense_verify(dataset, u); } /* end for */ /* Check on dataset's attribute storage status */ @@ -1880,24 +1942,8 @@ HDfprintf(stderr, "max_compact = %u, min_dense = %u\n", max_compact, min_dense); ret = H5Sclose(sid); CHECK(ret, FAIL, "H5Sclose"); - /* Re-open all the attributes and verify the data */ - for(u = 0; u <= max_compact; u++) { - unsigned value; - - /* Open attribute */ - sprintf(attrname, "attr %02u", u); - attr = H5Aopen_name(dataset, attrname); - CHECK(attr, FAIL, "H5Aopen"); - - /* Read data from the attribute */ - ret = H5Aread(attr, H5T_NATIVE_UINT, &value); - CHECK(ret, FAIL, "H5Aread"); - VERIFY(value, u, "H5Aread"); - - /* Close attribute */ - ret = H5Aclose(attr); - CHECK(ret, FAIL, "H5Aclose"); - } /* end for */ + /* Verify all the attributes written */ + test_attr_dense_verify(dataset, (u + 1)); /* Close Dataset */ ret = H5Dclose(dataset); @@ -1978,7 +2024,7 @@ HDfprintf(stderr, "max_compact = %u, min_dense = %u\n", max_compact, min_dense); /* Check # of attributes */ attr_count = H5Aget_num_attrs(dataset); CHECK(attr_count, FAIL, "H5Aget_num_attrs"); - VERIFY(attr_count, (u + 1), "H5Aget_num_attrs"); + VERIFY(attr_count, (int)(u + 1), "H5Aget_num_attrs"); } /* end for */ /* Check on dataset's attribute storage status */ @@ -2012,6 +2058,9 @@ HDfprintf(stderr, "max_compact = %u, min_dense = %u\n", max_compact, min_dense); sprintf(attrname, "attr %02u", u); ret = H5Adelete(dataset, attrname); CHECK(ret, FAIL, "H5Adelete"); + + /* Verify attributes still left */ + test_attr_dense_verify(dataset, u); } /* end for */ /* Check on dataset's attribute storage status */ @@ -2023,6 +2072,13 @@ HDfprintf(stderr, "max_compact = %u, min_dense = %u\n", max_compact, min_dense); ret = H5Adelete(dataset, attrname); CHECK(ret, FAIL, "H5Adelete"); + /* Check on dataset's attribute storage status */ + is_dense = H5O_is_attr_dense_test(dataset); + VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test"); + + /* Verify attributes still left */ + test_attr_dense_verify(dataset, (u - 1)); + /* Close Dataset */ ret = H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); diff --git a/test/titerate.c b/test/titerate.c index 539a9fa..aa78581 100644 --- a/test/titerate.c +++ b/test/titerate.c @@ -361,11 +361,11 @@ aiter_cb(hid_t UNUSED group, const char *name, void *op_data) case RET_CHANGE: count++; - return(count > 10 ? 1: 0); + return(count > 10 ? 1 : 0); case RET_CHANGE2: count2++; - return(count2 > 10 ? 1: 0); + return(count2 > 10 ? 1 : 0); default: printf("invalid iteration command"); |