diff options
Diffstat (limited to 'src/H5Adense.c')
-rw-r--r-- | src/H5Adense.c | 716 |
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() */ + |