diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2006-12-12 00:42:19 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2006-12-12 00:42:19 (GMT) |
commit | a867b8f5fd7ddf31aa23c8814a30444abb8bf6cf (patch) | |
tree | 1320ad77f30ce9cfa7a4d0409f69fe7a50ce3d38 /src/H5Adense.c | |
parent | aa00130f300b2eb04474ff1b2e0eabbbe847b082 (diff) | |
download | hdf5-a867b8f5fd7ddf31aa23c8814a30444abb8bf6cf.zip hdf5-a867b8f5fd7ddf31aa23c8814a30444abb8bf6cf.tar.gz hdf5-a867b8f5fd7ddf31aa23c8814a30444abb8bf6cf.tar.bz2 |
[svn-r13045] Description:
Switch from using H5L_index_t/H5L_INDEX_<foo> to H5_index_t/H5_INDEX_<foo>
in order to accommodate indices on aspects of attributes as well as links.
Add basic support for deleting attributes in dense storage (needs more
support/tests for shared attributes in dense storage still).
Misc. cleanups, etc.
Tested on:
Linux/32 2.6 (chicago)
Linux/64 2.6 (chicago2)
Diffstat (limited to 'src/H5Adense.c')
-rw-r--r-- | src/H5Adense.c | 424 |
1 files changed, 415 insertions, 9 deletions
diff --git a/src/H5Adense.c b/src/H5Adense.c index b374e79..9d98dc0 100644 --- a/src/H5Adense.c +++ b/src/H5Adense.c @@ -38,6 +38,7 @@ #include "H5private.h" /* Generic Functions */ #include "H5Apkg.h" /* Attributes */ #include "H5Eprivate.h" /* Error handling */ +#include "H5MMprivate.h" /* Memory management */ #include "H5Opkg.h" /* Object headers */ @@ -72,6 +73,12 @@ /* 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. @@ -84,7 +91,6 @@ typedef struct H5A_bt2_od_wrt_t { size_t attr_size; /* Size of encode attribute */ } H5A_bt2_od_wrt_t; - /* * Data exchange structure to pass through the v2 B-tree layer for the * H5B2_iterate function when iterating over densely stored attributes. @@ -99,7 +105,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 */ - H5A_operator_t op; /* Callback for each attribute */ + const H5A_attr_iterate_t *attr_op; /* Callback for each attribute */ void *op_data; /* Callback data for each attribute */ /* upward */ @@ -119,6 +125,16 @@ typedef struct { H5A_t *attr; /* Copy of attribute */ } H5A_fh_ud_it_t; +/* + * Data exchange structure to pass through the fractal heap layer for the + * H5HF_op function when removing an attribute from densely stored attributes. + */ +typedef struct { + /* downward */ + H5F_t *f; /* Pointer to file that fractal heap is in */ + hid_t dxpl_id; /* DXPL for operation */ +} H5A_fh_ud_rm_t; + /********************/ /* Package Typedefs */ @@ -129,6 +145,8 @@ 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 */ @@ -150,6 +168,240 @@ 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, uint8_t 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 @@ -666,8 +918,17 @@ HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, H5_ITER_ERROR, "iterating over shared att H5A_dense_iterate_fh_cb, &fh_udata) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTOPERATE, H5_ITER_ERROR, "heap op callback failed") - /* Make the callback */ - ret_value = (bt2_udata->op)(bt2_udata->loc_id, fh_udata.attr->name, bt2_udata->op_data); + /* Check which type of callback to make */ + switch(bt2_udata->attr_op->op_type) { + case H5A_ATTR_OP_APP: + /* Make the application callback */ + ret_value = (bt2_udata->attr_op->u.app_op)(bt2_udata->loc_id, fh_udata.attr->name, bt2_udata->op_data); + break; + + 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); + } /* end switch */ /* Release the space allocated for the attribute */ H5O_msg_free(H5O_ATTR_ID, fh_udata.attr); @@ -701,8 +962,8 @@ 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, H5A_operator_t op, - void *op_data) + haddr_t name_bt2_addr, unsigned skip, unsigned *last_attr, + const H5A_attr_iterate_t *attr_op, void *op_data) { H5A_bt2_ud_it_t udata; /* User data for iterator callback */ H5HF_t *fheap = NULL; /* Fractal heap handle */ @@ -716,7 +977,7 @@ H5A_dense_iterate(H5F_t *f, hid_t dxpl_id, hid_t loc_id, haddr_t attr_fheap_addr HDassert(f); HDassert(H5F_addr_defined(attr_fheap_addr)); HDassert(H5F_addr_defined(name_bt2_addr)); - HDassert(op); + HDassert(attr_op); /* Check for skipping too many links */ if(skip > 0) { @@ -743,7 +1004,7 @@ H5A_dense_iterate(H5F_t *f, hid_t dxpl_id, hid_t loc_id, haddr_t attr_fheap_addr udata.loc_id = loc_id; udata.skip = skip; udata.count = 0; - udata.op = op; + udata.attr_op = attr_op; udata.op_data = op_data; /* Iterate over the records in the v2 B-tree's "native" order */ @@ -766,6 +1027,151 @@ 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 = H5O_msg_decode(udata->f, udata->dxpl_id, H5O_ATTR_ID, 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 + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Dec 11 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5A_dense_remove_bt2_cb(const void *_record, void *_bt2_udata) +{ + const H5A_dense_bt2_name_rec_t *record = (const H5A_dense_bt2_name_rec_t *)_record; + H5A_bt2_ud_common_t *bt2_udata = (H5A_bt2_ud_common_t *)_bt2_udata; /* User data for callback */ + H5A_fh_ud_rm_t fh_udata; /* User data for fractal heap 'op' callback */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5A_dense_remove_bt2_cb) + + /* Check for insertin shared attribute */ + if(record->flags & H5O_MSG_FLAG_SHARED) { +/* XXX: fix me */ +HDfprintf(stderr, "%s: removing shared attributes in dense storage not supported yet!\n", FUNC); +HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "removing shared attributes in dense storage not supported yet") + } /* end if */ + + /* 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") + + /* Remove record from fractal heap */ + if(H5HF_remove(bt2_udata->fheap, bt2_udata->dxpl_id, record->id) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTREMOVE, FAIL, "unable to remove attribute from fractal heap") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5A_dense_remove_bt2_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5A_dense_remove + * + * Purpose: Remove an attribute from the dense storage of an object + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Dec 11 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5A_dense_remove(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *name) +{ + H5HF_t *fheap = NULL; /* Fractal heap handle */ + H5A_bt2_ud_common_t udata; /* User data for v2 B-tree record removal */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5A_dense_remove, FAIL) + + /* + * Check arguments. + */ + HDassert(f); + HDassert(oh); + HDassert(name && *name); + + /* Open the fractal heap */ + if(NULL == (fheap = H5HF_open(f, dxpl_id, oh->attr_fheap_addr))) + HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap") + + /* Set up the user data for the v2 B-tree 'record remove' callback */ + udata.f = f; + udata.dxpl_id = dxpl_id; + udata.fheap = fheap; + udata.name = name; + udata.name_hash = H5_checksum_lookup3(name, HDstrlen(name), 0); + udata.flags = 0; + udata.corder = -1; /* XXX: None yet */ + udata.found_op = NULL; + udata.found_op_data = NULL; + + /* 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) + HGOTO_ERROR(H5E_ATTR, H5E_CANTREMOVE, FAIL, "unable to remove attribute from name index v2 B-tree") + +done: + /* Release resources */ + if(fheap && H5HF_close(fheap, dxpl_id) < 0) + HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5A_dense_remove() */ + + +/*------------------------------------------------------------------------- * Function: H5A_dense_delete * * Purpose: Delete all dense storage structures for attributes on an object @@ -792,7 +1198,7 @@ H5A_dense_delete(H5F_t *f, hid_t dxpl_id, H5O_t *oh) HDassert(oh); /* XXX: iterate through name index v2 B-tree and delete shared attributes */ -/* XXX: we need to delete attributes that use shared & committed components also */ +/* XXX: we need to delete shared/unshared attributes that use shared & committed components also */ /* Delete name index v2 B-tree */ if(H5B2_delete(f, dxpl_id, H5A_BT2_NAME, oh->name_bt2_addr, NULL, NULL) < 0) |