diff options
Diffstat (limited to 'src/H5Gdense.c')
-rw-r--r-- | src/H5Gdense.c | 1890 |
1 files changed, 1890 insertions, 0 deletions
diff --git a/src/H5Gdense.c b/src/H5Gdense.c new file mode 100644 index 0000000..4ae6800 --- /dev/null +++ b/src/H5Gdense.c @@ -0,0 +1,1890 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * 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 COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5Gdense.c + * Sep 9 2006 + * Quincey Koziol <koziol@hdfgroup.org> + * + * Purpose: Routines for operating on "dense" link storage for a + * group in a file. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#include "H5Gmodule.h" /* This source code file is part of the H5G module */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Gpkg.h" /* Groups */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5WBprivate.h" /* Wrapped Buffers */ + + +/****************/ +/* Local Macros */ +/****************/ + +/* Fractal heap creation parameters for "dense" link storage */ +#define H5G_FHEAP_MAN_WIDTH 4 +#define H5G_FHEAP_MAN_START_BLOCK_SIZE 512 +#define H5G_FHEAP_MAN_MAX_DIRECT_SIZE (64 * 1024) +#define H5G_FHEAP_MAN_MAX_INDEX 32 +#define H5G_FHEAP_MAN_START_ROOT_ROWS 1 +#define H5G_FHEAP_CHECKSUM_DBLOCKS TRUE +#define H5G_FHEAP_MAX_MAN_SIZE (4 * 1024) + +/* v2 B-tree creation macros for 'name' field index */ +#define H5G_NAME_BT2_NODE_SIZE 512 +#define H5G_NAME_BT2_MERGE_PERC 40 +#define H5G_NAME_BT2_SPLIT_PERC 100 + +/* v2 B-tree creation macros for 'corder' field index */ +#define H5G_CORDER_BT2_NODE_SIZE 512 +#define H5G_CORDER_BT2_MERGE_PERC 40 +#define H5G_CORDER_BT2_SPLIT_PERC 100 + +/* Size of stack buffer for serialized link */ +#define H5G_LINK_BUF_SIZE 128 + + +/******************/ +/* Local Typedefs */ +/******************/ + +/* Data exchange structure to use when building table of links in group */ +typedef struct { + H5G_link_table_t *ltable; /* Pointer to link table to build */ + size_t curr_lnk; /* Current link to operate on */ +} H5G_dense_bt_ud_t; + +/* + * Data exchange structure to pass through the v2 B-tree layer for the + * H5B2_iterate function when iterating over densely stored links. + */ +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 */ + hsize_t count; /* # of links examined */ + + /* downward (from application) */ + hsize_t skip; /* Number of links to skip */ + H5G_lib_iterate_t op; /* Callback for each link */ + void *op_data; /* Callback data for each link */ + + /* upward */ + int op_ret; /* Return value from callback */ +} H5G_bt2_ud_it_t; + +/* + * Data exchange structure to pass through the fractal heap layer for the + * H5HF_op function when iterating over densely stored links. + */ +typedef struct { + /* downward (internal) */ + H5F_t *f; /* Pointer to file that fractal heap is in */ + hid_t dxpl_id; /* DXPL for operation */ + + /* upward */ + H5O_link_t *lnk; /* Copy of link */ +} H5G_fh_ud_it_t; + +/* + * Data exchange structure for dense link storage. This structure is + * passed through the v2 B-tree layer when removing links. + */ +typedef struct { + /* downward */ + H5G_bt2_ud_common_t common; /* Common info for B-tree user data (must be first) */ + hbool_t rem_from_fheap; /* Whether to remove the link from the fractal heap */ + haddr_t corder_bt2_addr; /* Address of v2 B-tree indexing creation order */ + H5RS_str_t *grp_full_path_r; /* Full path of group where link is removed */ + hbool_t replace_names; /* Whether to replace the names of open objects */ +} H5G_bt2_ud_rm_t; + +/* + * Data exchange structure to pass through the fractal heap layer for the + * H5HF_op function when removing a link from densely stored links. + */ +typedef struct { + /* downward */ + H5F_t *f; /* Pointer to file that fractal heap is in */ + hid_t dxpl_id; /* DXPL for operation */ + haddr_t corder_bt2_addr; /* Address of v2 B-tree indexing creation order */ + H5RS_str_t *grp_full_path_r; /* Full path of group where link is removed */ + hbool_t replace_names; /* Whether to replace the names of open objects */ +} H5G_fh_ud_rm_t; + +/* + * Data exchange structure for dense link storage. This structure is + * passed through the v2 B-tree layer when removing links by index. + */ +typedef struct { + /* downward */ + H5F_t *f; /* Pointer to file that fractal heap is in */ + hid_t dxpl_id; /* DXPL for operation */ + H5HF_t *fheap; /* Fractal heap handle */ + H5_index_t idx_type; /* Primary index for removing link */ + haddr_t other_bt2_addr; /* Address of "other" v2 B-tree indexing link */ + H5RS_str_t *grp_full_path_r; /* Full path of group where link is removed */ +} H5G_bt2_ud_rmbi_t; + +/* + * Data exchange structure to pass through the fractal heap layer for the + * H5HF_op function when removing a link from densely stored links by index. + */ +typedef struct { + /* downward */ + H5F_t *f; /* Pointer to file that fractal heap is in */ + hid_t dxpl_id; /* DXPL for operation */ + + /* upward */ + H5O_link_t *lnk; /* Pointer to link to remove */ +} H5G_fh_ud_rmbi_t; + +/* + * Data exchange structure to pass through the v2 B-tree layer for the + * H5B2_index function when retrieving the name of a link by index. + */ +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) */ + char *name; /* Name buffer to fill */ + size_t name_size; /* Size of name buffer to fill */ + + /* upward */ + ssize_t name_len; /* Full length of name */ +} H5G_bt2_ud_gnbi_t; + +/* + * Data exchange structure to pass through the fractal heap layer for the + * H5HF_op function when retrieving the name of a link by index. + */ +typedef struct { + /* downward (internal) */ + H5F_t *f; /* Pointer to file that fractal heap is in */ + hid_t dxpl_id; /* DXPL for operation */ + + /* downward (from application) */ + char *name; /* Name buffer to fill */ + size_t name_size; /* Size of name buffer to fill */ + + /* upward */ + ssize_t name_len; /* Full length of name */ +} H5G_fh_ud_gnbi_t; + +/* + * Data exchange structure to pass through the v2 B-tree layer for the + * H5B2_index function when retrieving a link by index. + */ +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 */ + + /* upward */ + H5O_link_t *lnk; /* Pointer to link */ +} H5G_bt2_ud_lbi_t; + +/* + * Data exchange structure to pass through the fractal heap layer for the + * H5HF_op function when retrieving a link by index. + */ +typedef struct { + /* downward (internal) */ + H5F_t *f; /* Pointer to file that fractal heap is in */ + hid_t dxpl_id; /* DXPL for operation */ + + /* upward */ + H5O_link_t *lnk; /* Pointer to link */ +} H5G_fh_ud_lbi_t; + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + + +/*------------------------------------------------------------------------- + * Function: H5G__dense_create + * + * Purpose: Creates dense link storage structures for a group + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 9 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G__dense_create(H5F_t *f, hid_t dxpl_id, H5O_linfo_t *linfo, + const H5O_pline_t *pline) +{ + H5HF_create_t fheap_cparam; /* Fractal heap creation parameters */ + H5B2_create_t bt2_cparam; /* v2 B-tree creation parameters */ + H5HF_t *fheap = NULL; /* Fractal heap handle */ + H5B2_t *bt2_name = NULL; /* v2 B-tree handle for names */ + H5B2_t *bt2_corder = NULL; /* v2 B-tree handle for creation order */ + size_t fheap_id_len; /* Fractal heap ID length */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* + * Check arguments. + */ + HDassert(f); + HDassert(linfo); + + /* Set fractal heap creation parameters */ +/* XXX: Give some control of these to applications? */ + HDmemset(&fheap_cparam, 0, sizeof(fheap_cparam)); + fheap_cparam.managed.width = H5G_FHEAP_MAN_WIDTH; + fheap_cparam.managed.start_block_size = H5G_FHEAP_MAN_START_BLOCK_SIZE; + fheap_cparam.managed.max_direct_size = H5G_FHEAP_MAN_MAX_DIRECT_SIZE; + fheap_cparam.managed.max_index = H5G_FHEAP_MAN_MAX_INDEX; + fheap_cparam.managed.start_root_rows = H5G_FHEAP_MAN_START_ROOT_ROWS; + fheap_cparam.checksum_dblocks = H5G_FHEAP_CHECKSUM_DBLOCKS; + fheap_cparam.max_man_size = H5G_FHEAP_MAX_MAN_SIZE; + if(pline) + fheap_cparam.pline = *pline; + + /* Create fractal heap for storing links */ + if(NULL == (fheap = H5HF_create(f, dxpl_id, &fheap_cparam))) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create fractal heap") + + /* Retrieve the heap's address in the file */ + if(H5HF_get_heap_addr(fheap, &(linfo->fheap_addr)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get fractal heap address") +#ifdef QAK +HDfprintf(stderr, "%s: linfo->fheap_addr = %a\n", FUNC, linfo->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_SYM, H5E_CANTGETSIZE, FAIL, "can't get fractal heap ID length") + HDassert(fheap_id_len == H5G_DENSE_FHEAP_ID_LEN); +#ifdef QAK +HDfprintf(stderr, "%s: fheap_id_len = %Zu\n", FUNC, fheap_id_len); +#endif /* QAK */ + + /* Create the name index v2 B-tree */ + HDmemset(&bt2_cparam, 0, sizeof(bt2_cparam)); + bt2_cparam.cls = H5G_BT2_NAME; + bt2_cparam.node_size = (size_t)H5G_NAME_BT2_NODE_SIZE; + H5_CHECK_OVERFLOW(fheap_id_len, /* From: */ hsize_t, /* To: */ uint32_t); + bt2_cparam.rrec_size = 4 + /* Name's hash value */ + (uint32_t)fheap_id_len; /* Fractal heap ID */ + bt2_cparam.split_percent = H5G_NAME_BT2_SPLIT_PERC; + bt2_cparam.merge_percent = H5G_NAME_BT2_MERGE_PERC; + if(NULL == (bt2_name = H5B2_create(f, dxpl_id, &bt2_cparam, NULL))) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create v2 B-tree for name index") + + /* Retrieve the v2 B-tree's address in the file */ + if(H5B2_get_addr(bt2_name, &(linfo->name_bt2_addr)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get v2 B-tree address for name index") +#ifdef QAK +HDfprintf(stderr, "%s: linfo->name_bt2_addr = %a\n", FUNC, linfo->name_bt2_addr); +#endif /* QAK */ + + /* Check if we should create a creation order index v2 B-tree */ + if(linfo->index_corder) { + /* Create the creation order index v2 B-tree */ + HDmemset(&bt2_cparam, 0, sizeof(bt2_cparam)); + bt2_cparam.cls = H5G_BT2_CORDER; + bt2_cparam.node_size = (size_t)H5G_CORDER_BT2_NODE_SIZE; + H5_CHECK_OVERFLOW(fheap_id_len, /* From: */ hsize_t, /* To: */ uint32_t); + bt2_cparam.rrec_size = 8 + /* Creation order value */ + (uint32_t)fheap_id_len; /* Fractal heap ID */ + bt2_cparam.split_percent = H5G_CORDER_BT2_SPLIT_PERC; + bt2_cparam.merge_percent = H5G_CORDER_BT2_MERGE_PERC; + if(NULL == (bt2_corder = H5B2_create(f, dxpl_id, &bt2_cparam, NULL))) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create v2 B-tree for creation order index") + + /* Retrieve the v2 B-tree's address in the file */ + if(H5B2_get_addr(bt2_corder, &(linfo->corder_bt2_addr)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get v2 B-tree address for creation order index") +#ifdef QAK +HDfprintf(stderr, "%s: linfo->corder_bt2_addr = %a\n", FUNC, linfo->corder_bt2_addr); +#endif /* QAK */ + } /* end if */ + +done: + /* Close the open objects */ + if(fheap && H5HF_close(fheap, dxpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close fractal heap") + if(bt2_name && H5B2_close(bt2_name, dxpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for name index") + if(bt2_corder && H5B2_close(bt2_corder, dxpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for creation order index") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G__dense_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5G__dense_insert + * + * Purpose: Insert a link into the dense link storage structures for a group + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 11 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G__dense_insert(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, + const H5O_link_t *lnk) +{ + H5G_bt2_ud_ins_t udata; /* User data for v2 B-tree insertion */ + H5HF_t *fheap = NULL; /* Fractal heap handle */ + H5B2_t *bt2_name = NULL; /* v2 B-tree handle for name index */ + H5B2_t *bt2_corder = NULL; /* v2 B-tree handle for creation order index */ + size_t link_size; /* Size of serialized link in the heap */ + H5WB_t *wb = NULL; /* Wrapped buffer for link data */ + uint8_t link_buf[H5G_LINK_BUF_SIZE]; /* Buffer for serializing link */ + void *link_ptr = NULL; /* Pointer to serialized link */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* + * Check arguments. + */ + HDassert(f); + HDassert(linfo); + HDassert(lnk); +#ifdef QAK +HDfprintf(stderr, "%s: linfo->fheap_addr = %a\n", FUNC, linfo->fheap_addr); +HDfprintf(stderr, "%s: linfo->name_bt2_addr = %a\n", FUNC, linfo->name_bt2_addr); +#endif /* QAK */ + + /* Find out the size of buffer needed for serialized link */ + if((link_size = H5O_msg_raw_size(f, H5O_LINK_ID, FALSE, lnk)) == 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGETSIZE, FAIL, "can't get link size") +#ifdef QAK +HDfprintf(stderr, "%s: HDstrlen(lnk->name) = %Zu, link_size = %Zu\n", FUNC, HDstrlen(lnk->name), link_size); +#endif /* QAK */ + + /* Wrap the local buffer for serialized link */ + if(NULL == (wb = H5WB_wrap(link_buf, sizeof(link_buf)))) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't wrap buffer") + + /* Get a pointer to a buffer that's large enough for link */ + if(NULL == (link_ptr = H5WB_actual(wb, link_size))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't get actual buffer") + + /* Create serialized form of link */ + if(H5O_msg_encode(f, H5O_LINK_ID, FALSE, (unsigned char *)link_ptr, lnk) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTENCODE, FAIL, "can't encode link") + + /* Open the fractal heap */ + if(NULL == (fheap = H5HF_open(f, dxpl_id, linfo->fheap_addr))) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap") + + /* Insert the serialized link into the fractal heap */ + if(H5HF_insert(fheap, dxpl_id, link_size, link_ptr, udata.id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert link into fractal heap") + + /* Open the name index v2 B-tree */ + if(NULL == (bt2_name = H5B2_open(f, dxpl_id, linfo->name_bt2_addr, NULL))) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index") + + /* 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 = lnk->name; + udata.common.name_hash = H5_checksum_lookup3(lnk->name, HDstrlen(lnk->name), 0); + udata.common.corder = lnk->corder; + udata.common.found_op = NULL; + udata.common.found_op_data = NULL; + /* udata.id already set in H5HF_insert() call */ + + /* Insert link into 'name' tracking v2 B-tree */ + if(H5B2_insert(bt2_name, dxpl_id, &udata) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert record into v2 B-tree") + + /* Check if we should create a creation order index v2 B-tree record */ + if(linfo->index_corder) { + /* Open the creation order index v2 B-tree */ + HDassert(H5F_addr_defined(linfo->corder_bt2_addr)); + if(NULL == (bt2_corder = H5B2_open(f, dxpl_id, linfo->corder_bt2_addr, NULL))) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for creation order index") + + /* Insert the record into the creation order index v2 B-tree */ + if(H5B2_insert(bt2_corder, dxpl_id, &udata) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert record into v2 B-tree") + } /* end if */ + +done: + /* Release resources */ + if(fheap && H5HF_close(fheap, dxpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close fractal heap") + if(bt2_name && H5B2_close(bt2_name, dxpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for name index") + if(bt2_corder && H5B2_close(bt2_corder, dxpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for creation order index") + if(wb && H5WB_unwrap(wb) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G__dense_insert() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_dense_lookup_cb + * + * Purpose: Callback when a link is located in an index + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 11 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_dense_lookup_cb(const void *_lnk, void *_user_lnk) +{ + const H5O_link_t *lnk = (const H5O_link_t *)_lnk; /* Record from B-tree */ + H5O_link_t *user_lnk = (H5O_link_t *)_user_lnk; /* User data from v2 B-tree link lookup */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* + * Check arguments. + */ + HDassert(lnk); + HDassert(user_lnk); + + /* Copy link information */ + if(H5O_msg_copy(H5O_LINK_ID, lnk, user_lnk) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy link message") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_dense_lookup_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5G__dense_lookup + * + * Purpose: Look up a link within a group that uses dense link storage + * + * Return: Non-negative (TRUE/FALSE) on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 11 2006 + * + *------------------------------------------------------------------------- + */ +htri_t +H5G__dense_lookup(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, + const char *name, H5O_link_t *lnk) +{ + H5G_bt2_ud_common_t udata; /* User data for v2 B-tree link lookup */ + H5HF_t *fheap = NULL; /* Fractal heap handle */ + H5B2_t *bt2_name = NULL; /* v2 B-tree handle for name index */ + htri_t ret_value = FAIL; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* + * Check arguments. + */ + HDassert(f); + HDassert(linfo); + HDassert(name && *name); + HDassert(lnk); + + /* Open the fractal heap */ + if(NULL == (fheap = H5HF_open(f, dxpl_id, linfo->fheap_addr))) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap") + + /* Open the name index v2 B-tree */ + if(NULL == (bt2_name = H5B2_open(f, dxpl_id, linfo->name_bt2_addr, NULL))) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index") + + /* Construct the user data for v2 B-tree 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.found_op = H5G_dense_lookup_cb; /* v2 B-tree comparison callback */ + udata.found_op_data = lnk; + + /* Find & copy the named link in the 'name' index */ + if((ret_value = H5B2_find(bt2_name, dxpl_id, &udata, NULL, NULL)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to locate link in name index") + +done: + /* Release resources */ + if(fheap && H5HF_close(fheap, dxpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close fractal heap") + if(bt2_name && H5B2_close(bt2_name, dxpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for name index") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G__dense_lookup() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_dense_lookup_by_idx_fh_cb + * + * Purpose: Callback for fractal heap operator, to make copy of link when + * when lookup up a link by index + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Nov 7 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_dense_lookup_by_idx_fh_cb(const void *obj, size_t H5_ATTR_UNUSED obj_len, void *_udata) +{ + H5G_fh_ud_lbi_t *udata = (H5G_fh_ud_lbi_t *)_udata; /* User data for fractal heap 'op' callback */ + H5O_link_t *tmp_lnk = NULL; /* Temporary pointer to link */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Decode link information & keep a copy */ + if(NULL == (tmp_lnk = (H5O_link_t *)H5O_msg_decode(udata->f, udata->dxpl_id, NULL, H5O_LINK_ID, (const unsigned char *)obj))) + HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, FAIL, "can't decode link") + + /* Copy link information */ + if(NULL == H5O_msg_copy(H5O_LINK_ID, tmp_lnk, udata->lnk)) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy link message") + +done: + /* Release the space allocated for the link */ + if(tmp_lnk) + H5O_msg_free(H5O_LINK_ID, tmp_lnk); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_dense_lookup_by_idx_fh_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_dense_lookup_by_idx_bt2_cb + * + * Purpose: v2 B-tree callback for dense link storage lookup by index + * + * Return: H5_ITER_ERROR/H5_ITER_CONT/H5_ITER_STOP + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Nov 7 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_dense_lookup_by_idx_bt2_cb(const void *_record, void *_bt2_udata) +{ + const H5G_dense_bt2_name_rec_t *record = (const H5G_dense_bt2_name_rec_t *)_record; + H5G_bt2_ud_lbi_t *bt2_udata = (H5G_bt2_ud_lbi_t *)_bt2_udata; /* User data for callback */ + H5G_fh_ud_lbi_t fh_udata; /* User data for fractal heap 'op' callback */ + int ret_value = H5_ITER_CONT; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Prepare user data for callback */ + /* down */ + fh_udata.f = bt2_udata->f; + fh_udata.dxpl_id = bt2_udata->dxpl_id; + fh_udata.lnk = bt2_udata->lnk; + + /* Call fractal heap 'op' routine, to copy the link information */ + if(H5HF_op(bt2_udata->fheap, bt2_udata->dxpl_id, record->id, + H5G_dense_lookup_by_idx_fh_cb, &fh_udata) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPERATE, H5_ITER_ERROR, "link found callback failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_dense_lookup_by_idx_bt2_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5G__dense_lookup_by_idx + * + * Purpose: Look up a link within a group that uses dense link storage, + * according to the order of an index + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Nov 7 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G__dense_lookup_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, + H5_index_t idx_type, H5_iter_order_t order, hsize_t n, H5O_link_t *lnk) +{ + H5HF_t *fheap = NULL; /* Fractal heap handle */ + H5G_link_table_t ltable = {0, NULL}; /* Table of links */ + H5B2_t *bt2 = NULL; /* v2 B-tree handle for index */ + haddr_t bt2_addr; /* Address of v2 B-tree to use for lookup */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* + * Check arguments. + */ + HDassert(f); + HDassert(linfo); + HDassert(lnk); + + /* Determine the address of the index to use */ + if(idx_type == H5_INDEX_NAME) { + /* Since names are hashed, getting them in strictly increasing or + * decreasing order requires building a table and sorting it. + * If the order is native, use the B-tree for names. + */ + bt2_addr = HADDR_UNDEF; + } /* end if */ + else { + HDassert(idx_type == H5_INDEX_CRT_ORDER); + + /* This address may not be defined if creation order is tracked, but + * there's no index on it. If there's no v2 B-tree that indexes + * the links and the order is native, use the B-tree for names. + * Otherwise, build a table. + */ + bt2_addr = linfo->corder_bt2_addr; + } /* end else */ + + /* If the order is native and there's no B-tree for indexing the links, + * use the B-tree for names instead of building a table to speed up the + * process. + */ + if(order == H5_ITER_NATIVE && !H5F_addr_defined(bt2_addr)) { + bt2_addr = linfo->name_bt2_addr; + HDassert(H5F_addr_defined(bt2_addr)); + } /* end if */ + + /* If there is an index defined for the field, use it */ + if(H5F_addr_defined(bt2_addr)) { + H5G_bt2_ud_lbi_t udata; /* User data for v2 B-tree link lookup */ + + /* Open the fractal heap */ + if(NULL == (fheap = H5HF_open(f, dxpl_id, linfo->fheap_addr))) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap") + + /* Open the index v2 B-tree */ + if(NULL == (bt2 = H5B2_open(f, dxpl_id, bt2_addr, NULL))) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for index") + + /* Construct the user data for v2 B-tree callback */ + udata.f = f; + udata.dxpl_id = dxpl_id; + udata.fheap = fheap; + udata.lnk = lnk; + + /* Find & copy the link in the appropriate index */ + if(H5B2_index(bt2, dxpl_id, order, n, H5G_dense_lookup_by_idx_bt2_cb, &udata) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to locate link in index") + } /* end if */ + else { /* Otherwise, we need to build a table of the links and sort it */ + /* Build the table of links for this group */ + if(H5G__dense_build_table(f, dxpl_id, linfo, idx_type, order, <able) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "error building table of links") + + /* Check for going out of bounds */ + if(n >= ltable.nlinks) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "index out of bound") + + /* Copy link information */ + if(NULL == H5O_msg_copy(H5O_LINK_ID, <able.lnks[n], lnk)) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy link message") + } /* end else */ + +done: + /* Release resources */ + if(fheap && H5HF_close(fheap, dxpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close fractal heap") + if(bt2 && H5B2_close(bt2, dxpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for index") + if(ltable.lnks && H5G__link_release_table(<able) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link table") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G__dense_lookup_by_idx() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_dense_build_table_cb + * + * Purpose: Callback routine for building table of links from dense + * link storage. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sept 25 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_dense_build_table_cb(const H5O_link_t *lnk, void *_udata) +{ + H5G_dense_bt_ud_t *udata = (H5G_dense_bt_ud_t *)_udata; /* 'User data' passed in */ + herr_t ret_value = H5_ITER_CONT; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* check arguments */ + HDassert(lnk); + HDassert(udata); + HDassert(udata->curr_lnk < udata->ltable->nlinks); + + /* Copy link information */ + if(H5O_msg_copy(H5O_LINK_ID, lnk, &(udata->ltable->lnks[udata->curr_lnk])) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy link message") + + /* Increment number of links stored */ + udata->curr_lnk++; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_dense_build_table_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5G__dense_build_table + * + * Purpose: Builds a table containing a sorted list of links for a group + * + * Note: Used for building table of links in non-native iteration order + * for an index + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Sep 25, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G__dense_build_table(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, + H5_index_t idx_type, H5_iter_order_t order, H5G_link_table_t *ltable) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Sanity check */ + HDassert(f); + HDassert(linfo); + HDassert(ltable); + + /* Set size of table */ + H5_CHECK_OVERFLOW(linfo->nlinks, /* From: */ hsize_t, /* To: */ size_t); + ltable->nlinks = (size_t)linfo->nlinks; + + /* Allocate space for the table entries */ + if(ltable->nlinks > 0) { + H5G_dense_bt_ud_t udata; /* User data for iteration callback */ + + /* Allocate the table to store the links */ + if((ltable->lnks = (H5O_link_t *)H5MM_malloc(sizeof(H5O_link_t) * ltable->nlinks)) == NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Set up user data for iteration */ + udata.ltable = ltable; + udata.curr_lnk = 0; + + /* Iterate over the links in the group, building a table of the link messages */ + if(H5G__dense_iterate(f, dxpl_id, linfo, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0, NULL, H5G_dense_build_table_cb, &udata) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "error iterating over links") + + /* Sort link table in correct iteration order */ + if(H5G__link_sort_table(ltable, idx_type, order) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTSORT, FAIL, "error sorting link messages") + } /* end if */ + else + ltable->lnks = NULL; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G__dense_build_table() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_dense_iterate_fh_cb + * + * Purpose: Callback for fractal heap operator, to make user's callback + * when iterating over links + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 11 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_dense_iterate_fh_cb(const void *obj, size_t H5_ATTR_UNUSED obj_len, void *_udata) +{ + H5G_fh_ud_it_t *udata = (H5G_fh_ud_it_t *)_udata; /* User data for fractal heap 'op' callback */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Decode link 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 - QAK) + */ + if(NULL == (udata->lnk = (H5O_link_t *)H5O_msg_decode(udata->f, udata->dxpl_id, NULL, H5O_LINK_ID, (const unsigned char *)obj))) + HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, FAIL, "can't decode link") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_dense_iterate_fh_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_dense_iterate_bt2_cb + * + * Purpose: v2 B-tree callback for dense link storage iterator + * + * Return: H5_ITER_ERROR/H5_ITER_CONT/H5_ITER_STOP + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 11 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_dense_iterate_bt2_cb(const void *_record, void *_bt2_udata) +{ + const H5G_dense_bt2_name_rec_t *record = (const H5G_dense_bt2_name_rec_t *)_record; + H5G_bt2_ud_it_t *bt2_udata = (H5G_bt2_ud_it_t *)_bt2_udata; /* User data for callback */ + herr_t ret_value = H5_ITER_CONT; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Check for skipping links */ + if(bt2_udata->skip > 0) + --bt2_udata->skip; + else { + H5G_fh_ud_it_t fh_udata; /* User data for fractal heap 'op' callback */ + + /* 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 link information */ + if(H5HF_op(bt2_udata->fheap, bt2_udata->dxpl_id, record->id, + H5G_dense_iterate_fh_cb, &fh_udata) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPERATE, H5_ITER_ERROR, "heap op callback failed") + + /* Make the callback */ + ret_value = (bt2_udata->op)(fh_udata.lnk, bt2_udata->op_data); + + /* Release the space allocated for the link */ + H5O_msg_free(H5O_LINK_ID, fh_udata.lnk); + } /* end else */ + + /* Increment the number of entries 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_SYM, H5E_CANTNEXT, "iteration operator failed"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_dense_iterate_bt2_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5G__dense_iterate + * + * Purpose: Iterate over the objects in a group using dense link storage + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 11 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G__dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, + H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk, + H5G_lib_iterate_t op, void *op_data) +{ + H5HF_t *fheap = NULL; /* Fractal heap handle */ + H5G_link_table_t ltable = {0, NULL}; /* Table of links */ + H5B2_t *bt2 = NULL; /* v2 B-tree handle for index */ + haddr_t bt2_addr; /* Address of v2 B-tree to use for lookup */ + herr_t ret_value = FAIL; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* + * Check arguments. + */ + HDassert(f); + HDassert(linfo); + HDassert(op); + + /* Determine the address of the index to use */ + if(idx_type == H5_INDEX_NAME) { + /* Since names are hashed, getting them in strictly increasing or + * decreasing order requires building a table and sorting it. If + * the order is native, use the B-tree for names. + */ + bt2_addr = HADDR_UNDEF; + } /* end if */ + else { + HDassert(idx_type == H5_INDEX_CRT_ORDER); + + /* This address may not be defined if creation order is tracked, but + * there's no index on it. If there's no v2 B-tree that indexes + * the links and the order is native, use the B-tree for names. + * Otherwise, build a table. + */ + bt2_addr = linfo->corder_bt2_addr; + } /* end else */ + + /* If the order is native and there's no B-tree for indexing the links, + * use the B-tree for names instead of building a table to speed up the + * process. + */ + if(order == H5_ITER_NATIVE && !H5F_addr_defined(bt2_addr)) { + HDassert(H5F_addr_defined(linfo->name_bt2_addr)); + bt2_addr = linfo->name_bt2_addr; + } /* end if */ + + /* Check on iteration order */ + if(order == H5_ITER_NATIVE) { + H5G_bt2_ud_it_t udata; /* User data for iterator callback */ + + /* Sanity check */ + HDassert(H5F_addr_defined(bt2_addr)); + + /* Open the fractal heap */ + if(NULL == (fheap = H5HF_open(f, dxpl_id, linfo->fheap_addr))) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap") + + /* Open the index v2 B-tree */ + if(NULL == (bt2 = H5B2_open(f, dxpl_id, bt2_addr, NULL))) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for index") + + /* Construct the user data for v2 B-tree iterator callback */ + udata.f = f; + udata.dxpl_id = dxpl_id; + udata.fheap = fheap; + 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(bt2, dxpl_id, H5G_dense_iterate_bt2_cb, &udata)) < 0) + HERROR(H5E_SYM, H5E_BADITER, "link iteration failed"); + + /* Update the last link examined, if requested */ + if(last_lnk) + *last_lnk = udata.count; + } /* end if */ + else { + /* Build the table of links for this group */ + if(H5G__dense_build_table(f, dxpl_id, linfo, idx_type, order, <able) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "error building table of links") + + /* Iterate over links in table */ + if((ret_value = H5G__link_iterate_table(<able, skip, last_lnk, op, op_data)) < 0) + HERROR(H5E_SYM, H5E_CANTNEXT, "iteration operator failed"); + } /* end else */ + +done: + /* Release resources */ + if(fheap && H5HF_close(fheap, dxpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close fractal heap") + if(bt2 && H5B2_close(bt2, dxpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for index") + if(ltable.lnks && H5G__link_release_table(<able) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link table") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G__dense_iterate() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_dense_get_name_by_idx_fh_cb + * + * Purpose: Callback for fractal heap operator, to retrieve name according + * to an index + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 19 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_dense_get_name_by_idx_fh_cb(const void *obj, size_t H5_ATTR_UNUSED obj_len, void *_udata) +{ + H5G_fh_ud_gnbi_t *udata = (H5G_fh_ud_gnbi_t *)_udata; /* User data for fractal heap 'op' callback */ + H5O_link_t *lnk; /* Pointer to link created from heap object */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Decode link information */ + if(NULL == (lnk = (H5O_link_t *)H5O_msg_decode(udata->f, udata->dxpl_id, NULL, H5O_LINK_ID, (const unsigned char *)obj))) + HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, FAIL, "can't decode link") + + /* Get the length of the name */ + udata->name_len = (ssize_t)HDstrlen(lnk->name); + + /* Copy the name into the user's buffer, if given */ + if(udata->name) { + HDstrncpy(udata->name, lnk->name, MIN((size_t)(udata->name_len + 1), udata->name_size)); + if((size_t)udata->name_len >= udata->name_size) + udata->name[udata->name_size - 1] = '\0'; + } /* end if */ + + /* Release the space allocated for the link */ + H5O_msg_free(H5O_LINK_ID, lnk); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_dense_get_name_by_idx_fh_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_dense_get_name_by_idx_bt2_cb + * + * Purpose: v2 B-tree callback for dense link storage 'get name by idx' call + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 19 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_dense_get_name_by_idx_bt2_cb(const void *_record, void *_bt2_udata) +{ + const H5G_dense_bt2_name_rec_t *record = (const H5G_dense_bt2_name_rec_t *)_record; + H5G_bt2_ud_gnbi_t *bt2_udata = (H5G_bt2_ud_gnbi_t *)_bt2_udata; /* User data for callback */ + H5G_fh_ud_gnbi_t fh_udata; /* User data for fractal heap 'op' callback */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Prepare user data for callback */ + /* down */ + fh_udata.f = bt2_udata->f; + fh_udata.dxpl_id = bt2_udata->dxpl_id; + fh_udata.name = bt2_udata->name; + fh_udata.name_size = bt2_udata->name_size; + + /* Call fractal heap 'op' routine, to perform user callback */ + if(H5HF_op(bt2_udata->fheap, bt2_udata->dxpl_id, record->id, + H5G_dense_get_name_by_idx_fh_cb, &fh_udata) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPERATE, FAIL, "link found callback failed") + + /* Set the name's full length to return */ + bt2_udata->name_len = fh_udata.name_len; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_dense_get_name_by_idx_bt2_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5G__dense_get_name_by_idx + * + * Purpose: Returns the name of objects in the group by giving index. + * + * Return: Success: Non-negative, length of name + * Failure: Negative + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 19 2006 + * + *------------------------------------------------------------------------- + */ +ssize_t +H5G__dense_get_name_by_idx(H5F_t *f, hid_t dxpl_id, H5O_linfo_t *linfo, + H5_index_t idx_type, H5_iter_order_t order, hsize_t n, char *name, + size_t size) +{ + H5HF_t *fheap = NULL; /* Fractal heap handle */ + H5G_link_table_t ltable = {0, NULL}; /* Table of links */ + H5B2_t *bt2 = NULL; /* v2 B-tree handle for index */ + haddr_t bt2_addr; /* Address of v2 B-tree to use for lookup */ + ssize_t ret_value = -1; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* + * Check arguments. + */ + HDassert(f); + HDassert(linfo); + + /* Determine the address of the index to use */ + if(idx_type == H5_INDEX_NAME) { + /* Since names are hashed, getting them in strictly increasing or + * decreasing order requires building a table and sorting it. If + * the order is native, use the B-tree for names. + */ + bt2_addr = HADDR_UNDEF; + } /* end if */ + else { + HDassert(idx_type == H5_INDEX_CRT_ORDER); + + /* This address may not be defined if creation order is tracked, but + * there's no index on it. If there's no v2 B-tree that indexes + * the links and the order is native, use the B-tree for names. + * Otherwise, build a table. + */ + bt2_addr = linfo->corder_bt2_addr; + } /* end else */ + + /* If the order is native and there's no B-tree for indexing the links, + * use the B-tree for names instead of building a table to speed up the + * process. + */ + if(order == H5_ITER_NATIVE && !H5F_addr_defined(bt2_addr)) { + bt2_addr = linfo->name_bt2_addr; + HDassert(H5F_addr_defined(bt2_addr)); + } /* end if */ + + /* If there is an index defined for the field, use it */ + if(H5F_addr_defined(bt2_addr)) { + H5G_bt2_ud_gnbi_t udata; /* User data for v2 B-tree callback */ + + /* Open the fractal heap */ + if(NULL == (fheap = H5HF_open(f, dxpl_id, linfo->fheap_addr))) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap") + + /* Open the index v2 B-tree */ + if(NULL == (bt2 = H5B2_open(f, dxpl_id, bt2_addr, NULL))) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for index") + + /* 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_size = size; + + /* Retrieve the name according to the v2 B-tree's index order */ + if(H5B2_index(bt2, dxpl_id, order, n, H5G_dense_get_name_by_idx_bt2_cb, &udata) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTLIST, FAIL, "can't locate object in v2 B-tree") + + /* Set return value */ + ret_value = udata.name_len; + } /* end if */ + else { /* Otherwise, we need to build a table of the links and sort it */ + /* Build the table of links for this group */ + if(H5G__dense_build_table(f, dxpl_id, linfo, idx_type, order, <able) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "error building table of links") + + /* Check for going out of bounds */ + if(n >= ltable.nlinks) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "index out of bound") + + /* Get the length of the name */ + ret_value = (ssize_t)HDstrlen(ltable.lnks[n].name); + + /* Copy the name into the user's buffer, if given */ + if(name) { + HDstrncpy(name, ltable.lnks[n].name, MIN((size_t)(ret_value + 1), size)); + if((size_t)ret_value >= size) + name[size - 1]='\0'; + } /* end if */ + } /* end else */ + +done: + /* Release resources */ + if(fheap && H5HF_close(fheap, dxpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close fractal heap") + if(bt2 && H5B2_close(bt2, dxpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for index") + if(ltable.lnks && H5G__link_release_table(<able) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link table") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G__dense_get_name_by_idx() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_dense_remove_fh_cb + * + * Purpose: Callback for fractal heap operator when removing links + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 12 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_dense_remove_fh_cb(const void *obj, size_t H5_ATTR_UNUSED obj_len, void *_udata) +{ + H5G_fh_ud_rm_t *udata = (H5G_fh_ud_rm_t *)_udata; /* User data for fractal heap 'op' callback */ + H5O_link_t *lnk = NULL; /* Pointer to link created from heap object */ + H5B2_t *bt2 = NULL; /* v2 B-tree handle for index */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Decode link information */ + if(NULL == (lnk = (H5O_link_t *)H5O_msg_decode(udata->f, udata->dxpl_id, NULL, H5O_LINK_ID, (const unsigned char *)obj))) + HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, FAIL, "can't decode link") + + /* Check for removing the link from the creation order index */ + if(H5F_addr_defined(udata->corder_bt2_addr)) { + H5G_bt2_ud_common_t bt2_udata; /* Info for B-tree callbacks */ + + /* Open the creation order index v2 B-tree */ + if(NULL == (bt2 = H5B2_open(udata->f, udata->dxpl_id, udata->corder_bt2_addr, NULL))) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for creation order index") + + /* Set up the user data for the v2 B-tree 'record remove' callback */ + HDassert(lnk->corder_valid); + bt2_udata.corder = lnk->corder; + + /* Remove the record from the name index v2 B-tree */ + if(H5B2_remove(bt2, udata->dxpl_id, &bt2_udata, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTREMOVE, FAIL, "unable to remove link from creation order index v2 B-tree") + } /* end if */ + + /* Replace open objects' names, if requested */ + if(udata->replace_names) + if(H5G__link_name_replace(udata->f, udata->dxpl_id, udata->grp_full_path_r, lnk) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTRENAME, FAIL, "unable to rename open objects") + + /* Perform the deletion action on the link, if requested */ + /* (call message "delete" callback directly: *ick* - QAK) */ + if(H5O_link_delete(udata->f, udata->dxpl_id, NULL, lnk) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete link") + +done: + /* Release resources */ + if(bt2 && H5B2_close(bt2, udata->dxpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for creation order index") + if(lnk) + H5O_msg_free(H5O_LINK_ID, lnk); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_dense_remove_fh_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_dense_remove_bt2_cb + * + * Purpose: v2 B-tree callback for dense link storage record removal + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 12 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_dense_remove_bt2_cb(const void *_record, void *_bt2_udata) +{ + const H5G_dense_bt2_name_rec_t *record = (const H5G_dense_bt2_name_rec_t *)_record; + H5G_bt2_ud_rm_t *bt2_udata = (H5G_bt2_ud_rm_t *)_bt2_udata; /* User data for callback */ + H5G_fh_ud_rm_t fh_udata; /* User data for fractal heap 'op' callback */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Set up the user data for fractal heap 'op' callback */ + fh_udata.f = bt2_udata->common.f; + fh_udata.dxpl_id = bt2_udata->common.dxpl_id; + fh_udata.corder_bt2_addr = bt2_udata->corder_bt2_addr; + fh_udata.grp_full_path_r = bt2_udata->grp_full_path_r; + fh_udata.replace_names = bt2_udata->replace_names; + + /* Call fractal heap 'op' routine, to perform user callback */ + if(H5HF_op(bt2_udata->common.fheap, bt2_udata->common.dxpl_id, record->id, + H5G_dense_remove_fh_cb, &fh_udata) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPERATE, FAIL, "link removal callback failed") + + /* Remove record from fractal heap, if requested */ + if(bt2_udata->rem_from_fheap) + if(H5HF_remove(bt2_udata->common.fheap, bt2_udata->common.dxpl_id, record->id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTREMOVE, FAIL, "unable to remove link from fractal heap") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_dense_remove_bt2_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5G__dense_remove + * + * Purpose: Remove a link from the dense storage of a group + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 12 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G__dense_remove(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, + H5RS_str_t *grp_full_path_r, const char *name) +{ + H5HF_t *fheap = NULL; /* Fractal heap handle */ + H5G_bt2_ud_rm_t udata; /* User data for v2 B-tree record removal */ + H5B2_t *bt2 = NULL; /* v2 B-tree handle for index */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* + * Check arguments. + */ + HDassert(f); + HDassert(linfo); + HDassert(name && *name); + + /* Open the fractal heap */ + if(NULL == (fheap = H5HF_open(f, dxpl_id, linfo->fheap_addr))) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap") + + /* Open the name index v2 B-tree */ + if(NULL == (bt2 = H5B2_open(f, dxpl_id, linfo->name_bt2_addr, NULL))) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index") + + /* Set up the user data for the v2 B-tree 'record remove' callback */ + udata.common.f = f; + udata.common.dxpl_id = dxpl_id; + udata.common.fheap = fheap; + udata.common.name = name; + udata.common.name_hash = H5_checksum_lookup3(name, HDstrlen(name), 0); + udata.common.found_op = NULL; + udata.common.found_op_data = NULL; + udata.rem_from_fheap = TRUE; + udata.corder_bt2_addr = linfo->corder_bt2_addr; + udata.grp_full_path_r = grp_full_path_r; + udata.replace_names = TRUE; + + /* Remove the record from the name index v2 B-tree */ + if(H5B2_remove(bt2, dxpl_id, &udata, H5G_dense_remove_bt2_cb, &udata) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTREMOVE, FAIL, "unable to remove link from name index v2 B-tree") + +done: + /* Release resources */ + if(fheap && H5HF_close(fheap, dxpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close fractal heap") + if(bt2 && H5B2_close(bt2, dxpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for name index") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G__dense_remove() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_dense_remove_by_idx_fh_cb + * + * Purpose: Callback for fractal heap operator when removing links by index + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Nov 15 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_dense_remove_by_idx_fh_cb(const void *obj, size_t H5_ATTR_UNUSED obj_len, void *_udata) +{ + H5G_fh_ud_rmbi_t *udata = (H5G_fh_ud_rmbi_t *)_udata; /* User data for fractal heap 'op' callback */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Decode link information */ + if(NULL == (udata->lnk = (H5O_link_t *)H5O_msg_decode(udata->f, udata->dxpl_id, NULL, H5O_LINK_ID, (const unsigned char *)obj))) + HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, H5_ITER_ERROR, "can't decode link") + + /* Can't operate on link here because the fractal heap block is locked */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_dense_remove_by_idx_fh_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_dense_remove_by_idx_bt2_cb + * + * Purpose: v2 B-tree callback for dense link storage record removal by index + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Nov 15 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_dense_remove_by_idx_bt2_cb(const void *_record, void *_bt2_udata) +{ + H5G_bt2_ud_rmbi_t *bt2_udata = (H5G_bt2_ud_rmbi_t *)_bt2_udata; /* User data for callback */ + H5G_fh_ud_rmbi_t fh_udata; /* User data for fractal heap 'op' callback */ + H5B2_t *bt2 = NULL; /* v2 B-tree handle for index */ + const uint8_t *heap_id; /* Heap ID for link */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Determine the index being used */ + if(bt2_udata->idx_type == H5_INDEX_NAME) { + const H5G_dense_bt2_name_rec_t *record = (const H5G_dense_bt2_name_rec_t *)_record; + + /* Set the heap ID to operate on */ + heap_id = record->id; + } /* end if */ + else { + const H5G_dense_bt2_corder_rec_t *record = (const H5G_dense_bt2_corder_rec_t *)_record; + + HDassert(bt2_udata->idx_type == H5_INDEX_CRT_ORDER); + + /* Set the heap ID to operate on */ + heap_id = record->id; + } /* end else */ + + /* Set up the user data for fractal heap 'op' callback */ + fh_udata.f = bt2_udata->f; + fh_udata.dxpl_id = bt2_udata->dxpl_id; + fh_udata.lnk = NULL; + + /* Call fractal heap 'op' routine, to perform user callback */ + if(H5HF_op(bt2_udata->fheap, bt2_udata->dxpl_id, heap_id, + H5G_dense_remove_by_idx_fh_cb, &fh_udata) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPERATE, FAIL, "link removal callback failed") + HDassert(fh_udata.lnk); + + /* Check for removing the link from the "other" index (creation order, when name used and vice versa) */ + if(H5F_addr_defined(bt2_udata->other_bt2_addr)) { + H5G_bt2_ud_common_t other_bt2_udata; /* Info for B-tree callbacks */ + + /* Determine the index being used */ + if(bt2_udata->idx_type == H5_INDEX_NAME) { + /* Set up the user data for the v2 B-tree 'record remove' callback */ + other_bt2_udata.corder = fh_udata.lnk->corder; + } /* end if */ + else { + HDassert(bt2_udata->idx_type == H5_INDEX_CRT_ORDER); + + /* Set up the user data for the v2 B-tree 'record remove' callback */ + other_bt2_udata.f = bt2_udata->f; + other_bt2_udata.dxpl_id = bt2_udata->dxpl_id; + other_bt2_udata.fheap = bt2_udata->fheap; + other_bt2_udata.name = fh_udata.lnk->name; + other_bt2_udata.name_hash = H5_checksum_lookup3(fh_udata.lnk->name, HDstrlen(fh_udata.lnk->name), 0); + other_bt2_udata.found_op = NULL; + other_bt2_udata.found_op_data = NULL; + } /* end else */ + + /* Open the index v2 B-tree */ + if(NULL == (bt2 = H5B2_open(bt2_udata->f, bt2_udata->dxpl_id, bt2_udata->other_bt2_addr, NULL))) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for 'other' index") + + /* Set the common information for the v2 B-tree remove operation */ + + /* Remove the record from the name index v2 B-tree */ + if(H5B2_remove(bt2, bt2_udata->dxpl_id, &other_bt2_udata, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTREMOVE, H5_ITER_ERROR, "unable to remove link from 'other' index v2 B-tree") + } /* end if */ + + /* Replace open objects' names */ + if(H5G__link_name_replace(bt2_udata->f, bt2_udata->dxpl_id, bt2_udata->grp_full_path_r, fh_udata.lnk) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTRENAME, FAIL, "unable to rename open objects") + + /* Perform the deletion action on the link */ + /* (call link message "delete" callback directly: *ick* - QAK) */ + if(H5O_link_delete(bt2_udata->f, bt2_udata->dxpl_id, NULL, fh_udata.lnk) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete link") + + /* Release the space allocated for the link */ + H5O_msg_free(H5O_LINK_ID, fh_udata.lnk); + + /* Remove record from fractal heap */ + if(H5HF_remove(bt2_udata->fheap, bt2_udata->dxpl_id, heap_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTREMOVE, FAIL, "unable to remove link from fractal heap") + +done: + /* Release resources */ + if(bt2 && H5B2_close(bt2, bt2_udata->dxpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for 'other' index") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_dense_remove_by_idx_bt2_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5G__dense_remove_by_idx + * + * Purpose: Remove a link from the dense storage of a group, according to + * to the offset in an indexed order + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Nov 14 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G__dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, + H5RS_str_t *grp_full_path_r, H5_index_t idx_type, H5_iter_order_t order, + hsize_t n) +{ + H5HF_t *fheap = NULL; /* Fractal heap handle */ + H5G_link_table_t ltable = {0, NULL}; /* Table of links */ + H5B2_t *bt2 = NULL; /* v2 B-tree handle for index */ + haddr_t bt2_addr; /* Address of v2 B-tree to use for lookup */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* + * Check arguments. + */ + HDassert(f); + HDassert(linfo); + + /* Determine the address of the index to use */ + if(idx_type == H5_INDEX_NAME) { + /* Since names are hashed, getting them in strictly increasing or + * decreasing order requires building a table and sorting it. If + * the order is native, use the B-tree for names. + */ + bt2_addr = HADDR_UNDEF; + } /* end if */ + else { + HDassert(idx_type == H5_INDEX_CRT_ORDER); + + /* This address may not be defined if creation order is tracked, but + * there's no index on it. If there's no v2 B-tree that indexes + * the links and the order is native, use the B-tree for names. + * Otherwise, build a table. + */ + bt2_addr = linfo->corder_bt2_addr; + } /* end else */ + + /* If the order is native and there's no B-tree for indexing the links, + * use the B-tree for names instead of building a table to speed up the + * process. + */ + if(order == H5_ITER_NATIVE && !H5F_addr_defined(bt2_addr)) { + bt2_addr = linfo->name_bt2_addr; + HDassert(H5F_addr_defined(bt2_addr)); + } /* end if */ + + /* If there is an index defined for the field, use it */ + if(H5F_addr_defined(bt2_addr)) { + H5G_bt2_ud_rmbi_t udata; /* User data for v2 B-tree record removal */ + + /* Open the fractal heap */ + if(NULL == (fheap = H5HF_open(f, dxpl_id, linfo->fheap_addr))) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap") + + /* Open the index v2 B-tree */ + if(NULL == (bt2 = H5B2_open(f, dxpl_id, bt2_addr, NULL))) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for index") + + /* Set up the user data for the v2 B-tree 'remove by index' callback */ + udata.f = f; + udata.dxpl_id = dxpl_id; + udata.fheap = fheap; + udata.idx_type = idx_type; + udata.other_bt2_addr = idx_type == H5_INDEX_NAME ? linfo->corder_bt2_addr : linfo->name_bt2_addr; + udata.grp_full_path_r = grp_full_path_r; + + /* Remove the record from the name index v2 B-tree */ + if(H5B2_remove_by_idx(bt2, dxpl_id, order, n, H5G_dense_remove_by_idx_bt2_cb, &udata) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTREMOVE, FAIL, "unable to remove link from indexed v2 B-tree") + } /* end if */ + else { /* Otherwise, we need to build a table of the links and sort it */ + /* Build the table of links for this group */ + if(H5G__dense_build_table(f, dxpl_id, linfo, idx_type, order, <able) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "error building table of links") + + /* Check for going out of bounds */ + if(n >= ltable.nlinks) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "index out of bound") + + /* Remove the appropriate link from the dense storage */ + if(H5G__dense_remove(f, dxpl_id, linfo, grp_full_path_r, ltable.lnks[n].name) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTREMOVE, FAIL, "unable to remove link from dense storage") + } /* end else */ + +done: + /* Release resources */ + if(fheap && H5HF_close(fheap, dxpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close fractal heap") + if(bt2 && H5B2_close(bt2, dxpl_id) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for index") + if(ltable.lnks && H5G__link_release_table(<able) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link table") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G__dense_remove_by_idx() */ + + +/*------------------------------------------------------------------------- + * Function: H5G__dense_delete + * + * Purpose: Delete the dense storage for a group + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 12 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G__dense_delete(H5F_t *f, hid_t dxpl_id, H5O_linfo_t *linfo, hbool_t adj_link) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* + * Check arguments. + */ + HDassert(f); + HDassert(linfo); + + /* Check if we are to adjust the ref. count for all the links */ + /* (we adjust the ref. count when deleting a group and we _don't_ adjust + * the ref. count when transitioning back to compact storage) + */ + if(adj_link) { + H5HF_t *fheap = NULL; /* Fractal heap handle */ + H5G_bt2_ud_rm_t udata; /* User data for v2 B-tree record removal */ + + /* Open the fractal heap */ + if(NULL == (fheap = H5HF_open(f, dxpl_id, linfo->fheap_addr))) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap") + + /* Set up the user data for the v2 B-tree 'record remove' callback */ + udata.common.f = f; + udata.common.dxpl_id = dxpl_id; + udata.common.fheap = fheap; + udata.common.name = NULL; + udata.common.name_hash = 0; + udata.common.found_op = NULL; + udata.common.found_op_data = NULL; + udata.rem_from_fheap = FALSE; /* handled in "bulk" below by deleting entire heap */ + udata.corder_bt2_addr = linfo->corder_bt2_addr; + udata.grp_full_path_r = NULL; + udata.replace_names = FALSE; + + /* Delete the name index, adjusting the ref. count on links removed */ + if(H5B2_delete(f, dxpl_id, linfo->name_bt2_addr, NULL, H5G_dense_remove_bt2_cb, &udata) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete v2 B-tree for name index") + + /* Close the fractal heap */ + if(H5HF_close(fheap, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close fractal heap") + } /* end if */ + else { + /* Delete the name index, without adjusting the ref. count on the links */ + if(H5B2_delete(f, dxpl_id, linfo->name_bt2_addr, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete v2 B-tree for name index") + } /* end else */ + linfo->name_bt2_addr = HADDR_UNDEF; + + /* Check if we should delete the creation order index v2 B-tree */ + if(linfo->index_corder) { + /* Delete the creation order index, without adjusting the ref. count on the links */ + HDassert(H5F_addr_defined(linfo->corder_bt2_addr)); + if(H5B2_delete(f, dxpl_id, linfo->corder_bt2_addr, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete v2 B-tree for creation order index") + linfo->corder_bt2_addr = HADDR_UNDEF; + } /* end if */ + else + HDassert(!H5F_addr_defined(linfo->corder_bt2_addr)); + + /* Delete the fractal heap */ + if(H5HF_delete(f, dxpl_id, linfo->fheap_addr) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete fractal heap") + linfo->fheap_addr = HADDR_UNDEF; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G__dense_delete() */ + +#ifndef H5_NO_DEPRECATED_SYMBOLS + +/*------------------------------------------------------------------------- + * Function: H5G__dense_get_type_by_idx + * + * Purpose: Returns the type of objects in the group by giving index. + * + * Note: This routine assumes a lookup on the link name index in + * increasing order and isn't currently set up to be as + * flexible as other routines in this code module, because + * the H5Gget_objtype_by_idx that it's supporting is + * deprecated. + * + * Return: Success: Non-negative, object type + * Failure: Negative + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 19 2006 + * + *------------------------------------------------------------------------- + */ +H5G_obj_t +H5G__dense_get_type_by_idx(H5F_t *f, hid_t dxpl_id, H5O_linfo_t *linfo, + hsize_t idx) +{ + H5G_link_table_t ltable = {0, NULL}; /* Table of links */ + H5G_obj_t ret_value = H5G_UNKNOWN; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* + * Check arguments. + */ + HDassert(f); + HDassert(linfo); + + /* Build the table of links for this group */ + if(H5G__dense_build_table(f, dxpl_id, linfo, H5_INDEX_NAME, H5_ITER_INC, <able) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5G_UNKNOWN, "error building table of links") + + /* Check for going out of bounds */ + if(idx >= ltable.nlinks) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5G_UNKNOWN, "index out of bound") + + /* Determine type of object */ + if(ltable.lnks[idx].type == H5L_TYPE_SOFT) + ret_value = H5G_LINK; + else if(ltable.lnks[idx].type >= H5L_TYPE_UD_MIN) + ret_value = H5G_UDLINK; + else if(ltable.lnks[idx].type == H5L_TYPE_HARD) { + H5O_loc_t tmp_oloc; /* Temporary object location */ + H5O_type_t obj_type; /* Type of object at location */ + + /* Build temporary object location */ + tmp_oloc.file = f; + tmp_oloc.addr = ltable.lnks[idx].u.hard.addr; + + /* Get the type of the object */ + if(H5O_obj_type(&tmp_oloc, &obj_type, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5G_UNKNOWN, "can't get object type") + + /* Map to group object type */ + if(H5G_UNKNOWN == (ret_value = H5G_map_obj_type(obj_type))) + HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, H5G_UNKNOWN, "can't determine object type") + } else { + HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, H5G_UNKNOWN, "unknown link type") + } /* end else */ + +done: + /* Release link table */ + if(ltable.lnks && H5G__link_release_table(<able) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTFREE, H5G_UNKNOWN, "unable to release link table") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G__dense_get_type_by_idx() */ +#endif /* H5_NO_DEPRECATED_SYMBOLS */ + |