summaryrefslogtreecommitdiffstats
path: root/src/H5Adense.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2006-12-06 22:19:52 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2006-12-06 22:19:52 (GMT)
commit7b368f006eea17a8b08cac9e6e79e58977edf864 (patch)
tree99e0f328dab0a6c3e602684d94aad309f339498d /src/H5Adense.c
parent1fa6d7cbf7062f12bdd85f896d40004f562cc439 (diff)
downloadhdf5-7b368f006eea17a8b08cac9e6e79e58977edf864.zip
hdf5-7b368f006eea17a8b08cac9e6e79e58977edf864.tar.gz
hdf5-7b368f006eea17a8b08cac9e6e79e58977edf864.tar.bz2
[svn-r13028] Description:
Add first pass of "dense" attribute storage to objects. Lots of parts of this are stubbed out, but all the tests are passing and I'll work on the corner cases soon. Eliminated several unused parameters from object header message callback routines. Other, miscellaneous code cleanups, etc. (and probably some things I've forgotten about... :-) Tested on: FreeBSD/32 4.11 (sleipnir) Linux/32 2.4 (heping) AIX/32 5.? (copper)
Diffstat (limited to 'src/H5Adense.c')
-rw-r--r--src/H5Adense.c716
1 files changed, 716 insertions, 0 deletions
diff --git a/src/H5Adense.c b/src/H5Adense.c
new file mode 100644
index 0000000..7cacf13
--- /dev/null
+++ b/src/H5Adense.c
@@ -0,0 +1,716 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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: H5Adense.c
+ * Dec 4 2006
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Routines for operating on "dense" attribute storage
+ * for an object.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* 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 "H5Opkg.h" /* Object headers */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+/* Fractal heap creation parameters for "dense" attribute storage */
+#define H5A_FHEAP_MAN_WIDTH 4
+#define H5A_FHEAP_MAN_START_BLOCK_SIZE 512
+#define H5A_FHEAP_MAN_MAX_DIRECT_SIZE (64 * 1024)
+#define H5A_FHEAP_MAN_MAX_INDEX 32
+#define H5A_FHEAP_MAN_START_ROOT_ROWS 1
+#define H5A_FHEAP_CHECKSUM_DBLOCKS TRUE
+#define H5A_FHEAP_MAX_MAN_SIZE (4 * 1024)
+
+/* v2 B-tree creation macros for 'name' field index */
+#define H5A_NAME_BT2_NODE_SIZE 512
+#define H5A_NAME_BT2_MERGE_PERC 40
+#define H5A_NAME_BT2_SPLIT_PERC 100
+
+/* v2 B-tree creation macros for 'corder' field index */
+#define H5A_CORDER_BT2_NODE_SIZE 512
+#define H5A_CORDER_BT2_MERGE_PERC 40
+#define H5A_CORDER_BT2_SPLIT_PERC 100
+
+/* Size of stack buffer for serialized attribute */
+#define H5A_ATTR_BUF_SIZE 128
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+/*
+ * Data exchange structure for dense attribute storage. This structure is
+ * passed through the v2 B-tree layer when modifying attributes.
+ */
+typedef struct H5A_bt2_od_wrt_t {
+ /* downward */
+ H5HF_t *fheap; /* Fractal heap handle to operate on */
+ hid_t dxpl_id; /* DXPL for operation */
+ void *attr_buf; /* Pointer to encoded attribute to store */
+ 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.
+ */
+typedef struct {
+ /* downward (internal) */
+ H5F_t *f; /* Pointer to file that fractal heap is in */
+ hid_t dxpl_id; /* DXPL for operation */
+ H5HF_t *fheap; /* Fractal heap handle */
+
+ /* downward (from application) */
+ 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 */
+ void *op_data; /* Callback data for each attribute */
+
+ /* upward */
+ int op_ret; /* Return value from callback */
+} H5A_bt2_ud_it_t;
+
+/*
+ * Data exchange structure to pass through the fractal heap layer for the
+ * H5HF_op function when iterating over densely stored attributes.
+ */
+typedef struct {
+ /* downward (internal) */
+ H5F_t *f; /* Pointer to file that fractal heap is in */
+ hid_t dxpl_id; /* DXPL for operation */
+
+ /* upward */
+ H5A_t *attr; /* Copy of attribute */
+} H5A_fh_ud_it_t;
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Declare a free list to manage the serialized attribute information */
+H5FL_BLK_DEFINE(ser_attr);
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_create
+ *
+ * Purpose: Creates dense attribute storage structures for an object
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 4 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5A_dense_create(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
+{
+ H5HF_create_t fheap_cparam; /* Fractal heap creation parameters */
+ H5HF_t *fheap; /* Fractal heap handle */
+ size_t fheap_id_len; /* Fractal heap ID length */
+ size_t bt2_rrec_size; /* v2 B-tree raw record size */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5A_dense_create, FAIL)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(oh);
+
+ /* Set fractal heap creation parameters */
+/* XXX: Give some control of these to applications? */
+ HDmemset(&fheap_cparam, 0, sizeof(fheap_cparam));
+ fheap_cparam.managed.width = H5A_FHEAP_MAN_WIDTH;
+ fheap_cparam.managed.start_block_size = H5A_FHEAP_MAN_START_BLOCK_SIZE;
+ fheap_cparam.managed.max_direct_size = H5A_FHEAP_MAN_MAX_DIRECT_SIZE;
+ fheap_cparam.managed.max_index = H5A_FHEAP_MAN_MAX_INDEX;
+ fheap_cparam.managed.start_root_rows = H5A_FHEAP_MAN_START_ROOT_ROWS;
+ fheap_cparam.checksum_dblocks = H5A_FHEAP_CHECKSUM_DBLOCKS;
+ fheap_cparam.max_man_size = H5A_FHEAP_MAX_MAN_SIZE;
+
+ /* Create fractal heap for storing attributes */
+ if(NULL == (fheap = H5HF_create(f, dxpl_id, &fheap_cparam)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to create fractal heap")
+
+ /* Retrieve the heap's address in the file */
+ if(H5HF_get_heap_addr(fheap, &(oh->attr_fheap_addr)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGETSIZE, FAIL, "can't get fractal heap address")
+#ifdef QAK
+HDfprintf(stderr, "%s: oh->attr_fheap_addr = %a\n", FUNC, oh->attr_fheap_addr);
+#endif /* QAK */
+
+ /* Retrieve the heap's ID length in the file */
+ if(H5HF_get_id_len(fheap, &fheap_id_len) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGETSIZE, FAIL, "can't get fractal heap ID length")
+ HDassert(fheap_id_len == H5A_DENSE_FHEAP_ID_LEN);
+#ifdef QAK
+HDfprintf(stderr, "%s: fheap_id_len = %Zu\n", FUNC, fheap_id_len);
+#endif /* QAK */
+
+ /* Close the fractal heap */
+ if(H5HF_close(fheap, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
+
+ /* Create the name index v2 B-tree */
+ bt2_rrec_size = 4 + /* Name's hash value */
+ fheap_id_len; /* Fractal heap ID */
+ if(H5B2_create(f, dxpl_id, H5A_BT2_NAME,
+ (size_t)H5A_NAME_BT2_NODE_SIZE, bt2_rrec_size,
+ H5A_NAME_BT2_SPLIT_PERC, H5A_NAME_BT2_MERGE_PERC,
+ &(oh->name_bt2_addr)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to create v2 B-tree for name index")
+#ifdef QAK
+HDfprintf(stderr, "%s: oh->name_bt2_addr = %a\n", FUNC, oh->name_bt2_addr);
+#endif /* QAK */
+
+/* XXX: fix me */
+#ifdef NOT_YET
+ /* Check if we should create a creation order index v2 B-tree */
+ if(linfo->index_corder) {
+ /* Create the creation order index v2 B-tree */
+ bt2_rrec_size = 8 + /* Creation order value */
+ fheap_id_len; /* Fractal heap ID */
+ if(H5B2_create(f, dxpl_id, H5A_BT2_CORDER,
+ (size_t)H5A_CORDER_BT2_NODE_SIZE, bt2_rrec_size,
+ H5A_CORDER_BT2_SPLIT_PERC, H5A_CORDER_BT2_MERGE_PERC,
+ &(linfo->corder_bt2_addr)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to create v2 B-tree for name index")
+#ifdef QAK
+HDfprintf(stderr, "%s: linfo->corder_bt2_addr = %a\n", FUNC, linfo->corder_bt2_addr);
+#endif /* QAK */
+ } /* end if */
+#endif /* NOT_YET */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_dense_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_insert
+ *
+ * Purpose: Insert an attribute into dense storage structures for an object
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 4 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5A_dense_insert(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, unsigned mesg_flags,
+ const H5A_t *attr)
+{
+ H5A_bt2_ud_ins_t udata; /* User data for v2 B-tree insertion */
+ H5HF_t *fheap = NULL; /* Fractal heap handle */
+ size_t attr_size; /* Size of serialized attribute in the heap */
+ uint8_t attr_buf[H5A_ATTR_BUF_SIZE]; /* Buffer for serializing attribute */
+ void *attr_ptr = NULL; /* Pointer to serialized attribute */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5A_dense_insert, FAIL)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(oh);
+ HDassert(attr);
+
+ /* Check for insertin shared attribute */
+ if(mesg_flags & H5O_MSG_FLAG_SHARED) {
+/* XXX: fix me */
+HDfprintf(stderr, "%s: inserting shared attributes in dense storage not supported yet!\n", FUNC);
+HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "inserting shared attributes in dense storage not supported yet")
+ } /* end if */
+
+ /* Find out the size of buffer needed for serialized attribute */
+ if((attr_size = H5O_msg_raw_size(f, H5O_ATTR_ID, attr)) == 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGETSIZE, FAIL, "can't get attribute size")
+
+ /* Allocate space for serialized attribute, if necessary */
+ if(attr_size > sizeof(attr_buf)) {
+ if(NULL == (attr_ptr = H5FL_BLK_MALLOC(ser_attr, attr_size)))
+ HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "memory allocation failed")
+ } /* end if */
+ else
+ attr_ptr = attr_buf;
+
+ /* Create serialized form of attribute */
+ if(H5O_msg_encode(f, H5O_ATTR_ID, attr_ptr, attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't encode attribute")
+
+ /* 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")
+
+ /* Insert the serialized attribute into the fractal heap */
+ if(H5HF_insert(fheap, dxpl_id, attr_size, attr_ptr, udata.id) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to insert attribute into fractal heap")
+
+ /* Create the callback information for v2 B-tree record insertion */
+ udata.common.f = f;
+ udata.common.dxpl_id = dxpl_id;
+ udata.common.fheap = fheap;
+ udata.common.name = attr->name;
+ udata.common.name_hash = H5_checksum_lookup3(attr->name, HDstrlen(attr->name), 0);
+ udata.common.flags = mesg_flags;
+ udata.common.corder = -1; /* XXX: None yet */
+ udata.common.found_op = NULL;
+ udata.common.found_op_data = NULL;
+ /* udata.id already set in H5HF_insert() call */
+
+ /* Insert attribute into 'name' tracking v2 B-tree */
+ if(H5B2_insert(f, dxpl_id, H5A_BT2_NAME, oh->name_bt2_addr, &udata) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to insert record into 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")
+ if(attr_ptr && attr_ptr != attr_buf)
+ H5FL_BLK_FREE(ser_attr, attr_ptr);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_dense_insert() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_write_cb
+ *
+ * Purpose: v2 B-tree modify callback to update the data for an attribute
+ *
+ * Return: Success: 0
+ * Failure: 1
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, December 5, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5A_dense_write_cb(void *_record, void *_op_data, hbool_t *changed)
+{
+ H5A_dense_bt2_name_rec_t *record = (H5A_dense_bt2_name_rec_t *)_record; /* Record from B-tree */
+ H5A_bt2_od_wrt_t *op_data = (H5A_bt2_od_wrt_t *)_op_data; /* "op data" from v2 B-tree modify */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5A_dense_write_cb)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(record);
+ HDassert(op_data);
+ HDassert(changed);
+
+ /* Check for modifying shared attribute */
+ if(record->flags & H5O_MSG_FLAG_SHARED) {
+/* XXX: fix me */
+HDfprintf(stderr, "%s: modifying shared attributes in dense storage not supported yet!\n", FUNC);
+HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "modifying shared attributes in dense storage not supported yet")
+ } /* end if */
+
+/* XXX: Add "write" routine (or allow "op" routine to modify values) to
+ * fractal heap code
+ */
+/* Sanity check */
+#ifndef NDEBUG
+{
+ size_t obj_len; /* Length of existing encoded attribute */
+
+ if(H5HF_get_obj_len(op_data->fheap, op_data->dxpl_id, record->id, &obj_len) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGETSIZE, FAIL, "can't get object size")
+ HDassert(obj_len == op_data->attr_size);
+}
+#endif /* NDEBUG */
+ /* Remove existing attribute from heap */
+ if(H5HF_remove(op_data->fheap, op_data->dxpl_id, record->id) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTREMOVE, FAIL, "unable to remove attribute from heap")
+
+ /* Insert new encoded attribute into heap */
+ if(H5HF_insert(op_data->fheap, op_data->dxpl_id, op_data->attr_size, op_data->attr_buf, record->id) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to insert attribute in heap")
+
+ /* Indicate that the B-tree record has changed */
+/* (XXX:We won't need this once we can write to an existing fractal heap object) */
+ *changed = TRUE;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_dense_write_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_write
+ *
+ * Purpose: Modify an attribute in dense storage structures for an object
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 4 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5A_dense_write(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const H5A_t *attr)
+{
+ H5A_bt2_ud_common_t udata; /* User data for v2 B-tree modify */
+ H5A_bt2_od_wrt_t op_data; /* "Op data" for v2 B-tree modify */
+ H5HF_t *fheap = NULL; /* Fractal heap handle */
+ size_t attr_size; /* Size of serialized attribute in the heap */
+ uint8_t attr_buf[H5A_ATTR_BUF_SIZE]; /* Buffer for serializing attribute */
+ void *attr_ptr = NULL; /* Pointer to serialized attribute */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5A_dense_write, FAIL)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(oh);
+ HDassert(attr);
+
+ /* Find out the size of buffer needed for serialized attribute */
+ if((attr_size = H5O_msg_raw_size(f, H5O_ATTR_ID, attr)) == 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGETSIZE, FAIL, "can't get attribute size")
+
+ /* Allocate space for serialized attribute, if necessary */
+ if(attr_size > sizeof(attr_buf)) {
+ if(NULL == (attr_ptr = H5FL_BLK_MALLOC(ser_attr, attr_size)))
+ HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "memory allocation failed")
+ } /* end if */
+ else
+ attr_ptr = attr_buf;
+
+ /* Create serialized form of attribute */
+ if(H5O_msg_encode(f, H5O_ATTR_ID, attr_ptr, attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't encode attribute")
+
+ /* Open the fractal heap */
+ if(NULL == (fheap = H5HF_open(f, dxpl_id, oh->attr_fheap_addr)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
+
+ /* Create the "udata" information for v2 B-tree record modify */
+ udata.f = f;
+ udata.dxpl_id = dxpl_id;
+ udata.fheap = fheap;
+ udata.name = attr->name;
+ udata.name_hash = H5_checksum_lookup3(attr->name, HDstrlen(attr->name), 0);
+ udata.flags = 0;
+ udata.corder = -1; /* XXX: None yet */
+ udata.found_op = NULL;
+ udata.found_op_data = NULL;
+
+ /* Create the "op_data" for the v2 B-tree record modify */
+ op_data.fheap = fheap;
+ op_data.dxpl_id = dxpl_id;
+ op_data.attr_buf = attr_ptr;
+ op_data.attr_size = attr_size;
+
+ /* Modify attribute through 'name' tracking v2 B-tree */
+ if(H5B2_modify(f, dxpl_id, H5A_BT2_NAME, oh->name_bt2_addr, &udata, H5A_dense_write_cb, &op_data) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to modify record in 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")
+ if(attr_ptr && attr_ptr != attr_buf)
+ H5FL_BLK_FREE(ser_attr, attr_ptr);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_dense_write() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_iterate_fh_cb
+ *
+ * Purpose: Callback for fractal heap operator, to make user's callback
+ * when iterating over attributes
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 5 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5A_dense_iterate_fh_cb(const void *obj, size_t UNUSED obj_len, void *_udata)
+{
+ H5A_fh_ud_it_t *udata = (H5A_fh_ud_it_t *)_udata; /* User data for fractal heap 'op' callback */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5A_dense_iterate_fh_cb)
+
+ /* Decode attribute information & keep a copy */
+ /* (we make a copy instead of calling the user/library callback directly in
+ * this routine because this fractal heap 'op' callback routine is called
+ * with the direct block protected and if the callback routine invokes an
+ * HDF5 routine, it could attempt to re-protect that direct block for the
+ * heap, causing the HDF5 routine called to fail)
+ */
+ if(NULL == (udata->attr = H5O_msg_decode(udata->f, udata->dxpl_id, H5O_ATTR_ID, obj)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, FAIL, "can't decode attribute")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_dense_iterate_fh_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_iterate_bt2_cb
+ *
+ * Purpose: v2 B-tree callback for dense attribute storage iterator
+ *
+ * Return: H5_ITER_ERROR/H5_ITER_CONT/H5_ITER_STOP
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 5 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5A_dense_iterate_bt2_cb(const void *_record, void *_bt2_udata)
+{
+ const H5A_dense_bt2_name_rec_t *record = (const H5A_dense_bt2_name_rec_t *)_record; /* Record from B-tree */
+ H5A_bt2_ud_it_t *bt2_udata = (H5A_bt2_ud_it_t *)_bt2_udata; /* User data for callback */
+ herr_t ret_value = H5_ITER_CONT; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5A_dense_iterate_bt2_cb)
+
+ /* Check for skipping attributes */
+ if(bt2_udata->skip > 0)
+ --bt2_udata->skip;
+ else {
+ H5A_fh_ud_it_t fh_udata; /* User data for fractal heap 'op' callback */
+
+ /* Check for iterating over shared attribute */
+ if(record->flags & H5O_MSG_FLAG_SHARED) {
+/* XXX: fix me */
+HDfprintf(stderr, "%s: iterating over shared attributes in dense storage not supported yet!\n", FUNC);
+HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, H5_ITER_ERROR, "iterating over shared attributes in dense storage not supported yet")
+ } /* end if */
+
+ /* Prepare user data for callback */
+ /* down */
+ fh_udata.f = bt2_udata->f;
+ fh_udata.dxpl_id = bt2_udata->dxpl_id;
+
+ /* Call fractal heap 'op' routine, to copy the attribute information */
+ if(H5HF_op(bt2_udata->fheap, bt2_udata->dxpl_id, record->id,
+ 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);
+
+ /* Release the space allocated for the attribute */
+ H5O_msg_free(H5O_ATTR_ID, fh_udata.attr);
+ } /* end else */
+
+ /* Increment the number of attributes passed through */
+ /* (whether we skipped them or not) */
+ bt2_udata->count++;
+
+ /* Check for callback failure and pass along return value */
+ if(ret_value < 0)
+ HERROR(H5E_ATTR, H5E_CANTNEXT, "iteration operator failed");
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_dense_iterate_bt2_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_iterate
+ *
+ * Purpose: Iterate over attributes in dense storage structures for an object
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 5 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+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)
+{
+ H5A_bt2_ud_it_t udata; /* User data for iterator callback */
+ H5HF_t *fheap = NULL; /* Fractal heap handle */
+ herr_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5A_dense_iterate, FAIL)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(H5F_addr_defined(attr_fheap_addr));
+ HDassert(H5F_addr_defined(name_bt2_addr));
+ HDassert(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")
+
+ /* 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")
+
+ /* Construct the user data for v2 B-tree iterator callback */
+ udata.f = f;
+ udata.dxpl_id = dxpl_id;
+ udata.fheap = fheap;
+ udata.loc_id = loc_id;
+ udata.skip = skip;
+ udata.count = 0;
+ udata.op = 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;
+
+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_iterate() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_delete
+ *
+ * Purpose: Delete all dense storage structures for attributes on an object
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 6 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5A_dense_delete(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5A_dense_delete, FAIL)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ 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 */
+
+ /* Delete name index v2 B-tree */
+ if(H5B2_delete(f, dxpl_id, H5A_BT2_NAME, oh->name_bt2_addr, NULL, NULL) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete v2 B-tree for name index")
+ oh->name_bt2_addr = HADDR_UNDEF;
+
+ /* Delete fractal heap */
+ if(H5HF_delete(f, dxpl_id, oh->attr_fheap_addr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete fractal heap")
+ oh->attr_fheap_addr = HADDR_UNDEF;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_dense_delete() */
+