diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2006-12-19 01:59:28 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2006-12-19 01:59:28 (GMT) |
commit | 43ec5b7ef4df2d72bcde2da9366d55383b8f40e8 (patch) | |
tree | 705125a1b023c990db69abd82ae878eb90800447 /src/H5Aint.c | |
parent | 5865018c85449e4b03bb3f5d5e7d7948e110fe17 (diff) | |
download | hdf5-43ec5b7ef4df2d72bcde2da9366d55383b8f40e8.zip hdf5-43ec5b7ef4df2d72bcde2da9366d55383b8f40e8.tar.gz hdf5-43ec5b7ef4df2d72bcde2da9366d55383b8f40e8.tar.bz2 |
[svn-r13074] Description:
Add support for opening attributes in dense and/or shared storage by
index.
Move routines for building and operating on tables of attributes into
separate source module.
Fix bug where reverting from "dense" to "compact" storage would 'unshare'
attributes.
Minor code cleanups, etc.
Tested on:
Linux/32 2.6 (chicago)
Linux/64 2.6 (chicago2)
Diffstat (limited to 'src/H5Aint.c')
-rw-r--r-- | src/H5Aint.c | 511 |
1 files changed, 511 insertions, 0 deletions
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() */ + |