hdf5/src/H5B2.c
Quincey Koziol 002fe8b35d [svn-r12914] Description:
Checkpoint partially working v2 B-tree delete by index code (ifdef'ed out)
for further work.

Tested on:
    Linux/32 2.6 (chicago)
2006-11-14 15:33:50 -05:00

1189 lines
46 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* 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: H5B2.c
* Jan 31 2005
* Quincey Koziol <koziol@ncsa.uiuc.edu>
*
* Purpose: Implements a B-tree, with several modifications from
* the "standard" methods.
*
* Please see the documentation in:
* doc/html/TechNotes/Btrees.html for a full description
* of how they work, etc.
*
*-------------------------------------------------------------------------
*/
/****************/
/* Module Setup */
/****************/
#define H5B2_PACKAGE /*suppress error about including H5B2pkg */
/***********/
/* Headers */
/***********/
#include "H5private.h" /* Generic Functions */
#include "H5B2pkg.h" /* v2 B-trees */
#include "H5Eprivate.h" /* Error handling */
#include "H5MFprivate.h" /* File memory management */
/****************/
/* Local Macros */
/****************/
/******************/
/* Local Typedefs */
/******************/
/********************/
/* Package Typedefs */
/********************/
/********************/
/* Local Prototypes */
/********************/
/*********************/
/* Package Variables */
/*********************/
/* Declare a free list to manage the H5B2_t struct */
H5FL_DEFINE(H5B2_t);
/*****************************/
/* Library Private Variables */
/*****************************/
/*******************/
/* Local Variables */
/*******************/
/*-------------------------------------------------------------------------
* Function: H5B2_create
*
* Purpose: Creates a new empty B-tree in the file.
*
* Return: Non-negative on success (with address of new B-tree
* filled in), negative on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Jan 31 2005
*
*-------------------------------------------------------------------------
*/
herr_t
H5B2_create(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type,
size_t node_size, size_t rrec_size,
unsigned split_percent, unsigned merge_percent, haddr_t *addr_p)
{
H5B2_t *bt2 = NULL; /* The new B-tree header information */
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5B2_create, FAIL)
/*
* Check arguments.
*/
HDassert(f);
HDassert(type);
HDassert(node_size > 0);
HDassert(rrec_size > 0);
HDassert(merge_percent > 0 && merge_percent <= 100);
HDassert(split_percent > 0 && split_percent <= 100);
HDassert(merge_percent < (split_percent / 2));
HDassert(addr_p);
/*
* Allocate file and memory data structures.
*/
if(NULL == (bt2 = H5FL_MALLOC(H5B2_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree header")
/* Assign internal information */
HDmemset(&bt2->cache_info, 0, sizeof(H5AC_info_t));
bt2->root.addr = HADDR_UNDEF;
bt2->root.node_nrec = 0;
bt2->root.all_nrec = 0;
/* Initialize shared B-tree info */
if(H5B2_shared_init(f, bt2, type, 0, node_size, rrec_size, split_percent, merge_percent) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create shared B-tree info")
/* Allocate space for the header on disk */
if(HADDR_UNDEF == (*addr_p = H5MF_alloc(f, H5FD_MEM_BTREE, dxpl_id, (hsize_t)H5B2_HEADER_SIZE(f))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for B-tree header")
/* Cache the new B-tree node */
if(H5AC_set(f, dxpl_id, H5AC_BT2_HDR, *addr_p, bt2, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "can't add B-tree header to cache")
done:
if(ret_value < 0) {
if(bt2)
(void)H5B2_cache_hdr_dest(f, bt2);
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5B2_create() */
/*-------------------------------------------------------------------------
* Function: H5B2_insert
*
* Purpose: Adds a new record to the B-tree.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Feb 2 2005
*
*-------------------------------------------------------------------------
*/
herr_t
H5B2_insert(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr,
void *udata)
{
H5B2_t *bt2 = NULL; /* Pointer to the B-tree header */
unsigned bt2_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for B-tree header */
H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5B2_insert, FAIL)
/* Check arguments. */
HDassert(f);
HDassert(type);
HDassert(H5F_addr_defined(addr));
/* Look up the b-tree header */
if(NULL == (bt2 = H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, addr, type, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree header")
/* Get the pointer to the shared B-tree info */
shared = H5RC_GET_OBJ(bt2->shared);
HDassert(shared);
/* Check if the root node is allocated yet */
if(!H5F_addr_defined(bt2->root.addr)) {
/* Create root node as leaf node in B-tree */
if(H5B2_create_leaf(f, dxpl_id, bt2->shared, &(bt2->root)) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create root node")
/* Mark B-tree header as dirty, since we updated the address of the root node */
bt2_flags |= H5AC__DIRTIED_FLAG;
} /* end if */
/* Check if we need to split the root node (equiv. to a 1->2 node split) */
else if(bt2->root.node_nrec == shared->node_info[shared->depth].split_nrec) {
/* Split root node */
if(H5B2_split_root(f, dxpl_id, bt2, &bt2_flags) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to split root node")
} /* end if */
/* Attempt to insert record into B-tree */
if(shared->depth > 0) {
if(H5B2_insert_internal(f, dxpl_id, bt2->shared, shared->depth, &bt2_flags, &bt2->root, udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into B-tree internal node")
} /* end if */
else {
if(H5B2_insert_leaf(f, dxpl_id, bt2->shared, &bt2->root, udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into B-tree leaf node")
} /* end else */
/* Mark parent node as dirty */
bt2_flags |= H5AC__DIRTIED_FLAG;
done:
/* Release the B-tree header info */
if(bt2 && H5AC_unprotect(f, dxpl_id, H5AC_BT2_HDR, addr, bt2, bt2_flags) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree header info")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5B2_insert() */
/*-------------------------------------------------------------------------
* Function: H5B2_iterate
*
* Purpose: Iterate over all the records in the B-tree, in "in-order"
* order, making a callback for each record.
*
* If the callback returns non-zero, the iteration breaks out
* without finishing all the records.
*
* Return: Value from callback: non-negative on success, negative on error
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Feb 11 2005
*
*-------------------------------------------------------------------------
*/
herr_t
H5B2_iterate(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr,
H5B2_operator_t op, void *op_data)
{
H5B2_t *bt2=NULL; /* Pointer to the B-tree header */
H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
H5RC_t *bt2_shared=NULL; /* Pointer to ref-counter for shared B-tree info */
hbool_t incr_rc=FALSE; /* Flag to indicate that we've incremented the B-tree's shared info reference count */
H5B2_node_ptr_t root_ptr; /* Node pointer info for root node */
unsigned depth; /* Current depth of the tree */
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5B2_iterate, FAIL)
/* Check arguments. */
HDassert(f);
HDassert(type);
HDassert(H5F_addr_defined(addr));
HDassert(op);
/* Look up the B-tree header */
if(NULL == (bt2 = H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, addr, type, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree header")
/* Safely grab pointer to reference counted shared B-tree info, so we can release the B-tree header if necessary */
bt2_shared = bt2->shared;
H5RC_INC(bt2_shared);
incr_rc = TRUE;
/* Get the pointer to the shared B-tree info */
shared = H5RC_GET_OBJ(bt2->shared);
HDassert(shared);
/* Make copy of the root node pointer */
root_ptr = bt2->root;
/* Current depth of the tree */
depth = shared->depth;
/* Release header */
if(H5AC_unprotect(f, dxpl_id, H5AC_BT2_HDR, addr, bt2, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree header info")
bt2 = NULL;
/* Iterate through records */
if(root_ptr.node_nrec > 0) {
/* Iterate through nodes */
if((ret_value = H5B2_iterate_node(f, dxpl_id, bt2_shared, depth, &root_ptr, op, op_data)) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "node iteration failed")
} /* end if */
done:
/* Check if we need to decrement the reference count for the B-tree's shared info */
if(incr_rc)
H5RC_DEC(bt2_shared);
FUNC_LEAVE_NOAPI(ret_value)
} /* H5B2_iterate() */
/*-------------------------------------------------------------------------
* Function: H5B2_find
*
* Purpose: Locate the specified information in a B-tree and return
* that information by calling the provided 'OP' routine with an
* OP_DATA pointer. The UDATA parameter points to data passed
* to the key comparison function.
*
* The 'OP' routine is called with the record found and the
* OP_DATA pointer, to allow caller to return information about
* the record.
*
* If 'OP' is NULL, then this routine just returns "SUCCEED" when
* a record is present in the B-tree.
*
* Return: Non-negative on success, negative on failure.
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Feb 23 2005
*
*-------------------------------------------------------------------------
*/
herr_t
H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr,
void *udata, H5B2_found_t op, void *op_data)
{
H5B2_t *bt2=NULL; /* Pointer to the B-tree header */
H5RC_t *bt2_shared=NULL; /* Pointer to ref-counter for shared B-tree info */
H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
hbool_t incr_rc=FALSE; /* Flag to indicate that we've incremented the B-tree's shared info reference count */
H5B2_node_ptr_t curr_node_ptr; /* Node pointer info for current node */
unsigned depth; /* Current depth of the tree */
int cmp; /* Comparison value of records */
unsigned idx; /* Location of record which matches key */
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5B2_find, FAIL)
/* Check arguments. */
HDassert(f);
HDassert(type);
HDassert(H5F_addr_defined(addr));
/* Look up the B-tree header */
if (NULL == (bt2 = H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, addr, type, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree header")
/* Safely grab pointer to reference counted shared B-tree info, so we can release the B-tree header if necessary */
bt2_shared=bt2->shared;
H5RC_INC(bt2_shared);
incr_rc=TRUE;
/* Get the pointer to the shared B-tree info */
shared=H5RC_GET_OBJ(bt2_shared);
HDassert(shared);
/* Make copy of the root node pointer to start search with */
curr_node_ptr = bt2->root;
/* Current depth of the tree */
depth = shared->depth;
/* Release header */
if(H5AC_unprotect(f, dxpl_id, H5AC_BT2_HDR, addr, bt2, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree header info")
bt2 = NULL;
/* Check for empty tree */
if(curr_node_ptr.node_nrec==0)
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "B-tree has no records")
/* Walk down B-tree to find record or leaf node where record is located */
cmp = -1;
while(depth > 0 && cmp != 0) {
H5B2_internal_t *internal; /* Pointer to internal node in B-tree */
H5B2_node_ptr_t next_node_ptr; /* Node pointer info for next node */
/* Lock B-tree current node */
if(NULL == (internal = H5B2_protect_internal(f, dxpl_id, bt2_shared, curr_node_ptr.addr, curr_node_ptr.node_nrec, depth, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
/* Locate node pointer for child */
cmp = H5B2_locate_record(shared->type, internal->nrec, shared->nat_off, internal->int_native, udata, &idx);
if(cmp > 0)
idx++;
if(cmp != 0) {
/* Get node pointer for next node to search */
next_node_ptr=internal->node_ptrs[idx];
/* Unlock current node */
if(H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
/* Set pointer to next node to load */
curr_node_ptr = next_node_ptr;
} /* end if */
else {
/* Make callback for current record */
if(op && (op)(H5B2_INT_NREC(internal, shared, idx), op_data) < 0) {
/* Unlock current node */
if (H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "'found' callback failed for B-tree find operation")
} /* end if */
/* Unlock current node */
if(H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
HGOTO_DONE(SUCCEED);
} /* end else */
/* Decrement depth we're at in B-tree */
depth--;
} /* end while */
{
H5B2_leaf_t *leaf; /* Pointer to leaf node in B-tree */
/* Lock B-tree leaf node */
if(NULL == (leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr.addr, &(curr_node_ptr.node_nrec), bt2_shared, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
/* Locate record */
cmp = H5B2_locate_record(shared->type, leaf->nrec, shared->nat_off, leaf->leaf_native, udata, &idx);
if(cmp != 0) {
/* Unlock leaf node */
if(H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr.addr, leaf, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
/* Note: don't push error on stack, leave that to next higher level,
* since many times the B-tree is searched in order to determine
* if an object exists in the B-tree or not. -QAK
*/
#ifdef OLD_WAY
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "key not found in leaf node")
#else /* OLD_WAY */
HGOTO_DONE(FAIL)
#endif /* OLD_WAY */
} /* end if */
else {
/* Make callback for current record */
if(op && (op)(H5B2_LEAF_NREC(leaf, shared, idx), op_data) < 0) {
/* Unlock current node */
if(H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr.addr, leaf, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "'found' callback failed for B-tree find operation")
} /* end if */
} /* end else */
/* Unlock current node */
if(H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr.addr, leaf, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
} /* end block */
done:
/* Check if we need to decrement the reference count for the B-tree's shared info */
if(incr_rc)
H5RC_DEC(bt2_shared);
FUNC_LEAVE_NOAPI(ret_value)
} /* H5B2_find() */
/*-------------------------------------------------------------------------
* Function: H5B2_index
*
* Purpose: Locate the IDX'th record in a B-tree according to the
* ordering used by the B-tree. The IDX values are 0-based.
*
* The 'OP' routine is called with the record found and the
* OP_DATA pointer, to allow caller to return information about
* the record.
*
* Return: Non-negative on success, negative on failure.
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Feb 23 2005
*
*-------------------------------------------------------------------------
*/
herr_t
H5B2_index(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr,
H5_iter_order_t order, hsize_t idx, H5B2_found_t op, void *op_data)
{
H5B2_t *bt2=NULL; /* Pointer to the B-tree header */
H5RC_t *bt2_shared=NULL; /* Pointer to ref-counter for shared B-tree info */
H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
hbool_t incr_rc=FALSE; /* Flag to indicate that we've incremented the B-tree's shared info reference count */
H5B2_node_ptr_t curr_node_ptr; /* Node pointer info for current node */
unsigned depth; /* Current depth of the tree */
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5B2_index, FAIL)
/* Check arguments. */
HDassert(f);
HDassert(type);
HDassert(H5F_addr_defined(addr));
HDassert(op);
/* Look up the B-tree header */
if(NULL == (bt2 = H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, addr, type, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree header")
/* Safely grab pointer to reference counted shared B-tree info, so we can release the B-tree header if necessary */
bt2_shared = bt2->shared;
H5RC_INC(bt2_shared);
incr_rc = TRUE;
/* Get the pointer to the shared B-tree info */
shared = H5RC_GET_OBJ(bt2_shared);
HDassert(shared);
/* Make copy of the root node pointer to start search with */
curr_node_ptr = bt2->root;
/* Current depth of the tree */
depth = shared->depth;
/* Release header */
if(H5AC_unprotect(f, dxpl_id, H5AC_BT2_HDR, addr, bt2, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree header info")
bt2 = NULL;
/* Check for empty tree */
if(curr_node_ptr.node_nrec == 0)
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "B-tree has no records")
/* Check for index greater than the number of records in the tree */
if(idx >= curr_node_ptr.all_nrec)
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "B-tree doesn't have that many records")
/* Check for reverse indexing and map requested index to appropriate forward index */
if(order == H5_ITER_DEC)
idx = curr_node_ptr.all_nrec - (idx + 1);
/* Walk down B-tree to find record or leaf node where record is located */
while(depth > 0) {
H5B2_internal_t *internal; /* Pointer to internal node in B-tree */
H5B2_node_ptr_t next_node_ptr; /* Node pointer info for next node */
unsigned u; /* Local index variable */
/* Lock B-tree current node */
if(NULL == (internal = H5B2_protect_internal(f, dxpl_id, bt2_shared, curr_node_ptr.addr, curr_node_ptr.node_nrec, depth, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
/* Search for record with correct index */
for(u = 0; u < internal->nrec; u++) {
/* Check if record is in child node */
if(internal->node_ptrs[u].all_nrec > idx) {
/* Get node pointer for next node to search */
next_node_ptr = internal->node_ptrs[u];
/* Unlock current node */
if(H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
/* Set pointer to next node to load */
curr_node_ptr = next_node_ptr;
/* Break out of for loop */
break;
} /* end if */
/* Check if record is in this node */
if(internal->node_ptrs[u].all_nrec == idx) {
/* Make callback for current record */
if((op)(H5B2_INT_NREC(internal, shared, u), op_data) < 0) {
/* Unlock current node */
if(H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "'found' callback failed for B-tree find operation")
} /* end if */
/* Unlock current node */
if(H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
HGOTO_DONE(SUCCEED);
} /* end if */
/* Decrement index we are looking for to account for the node we
* just advanced past.
*/
idx -= (internal->node_ptrs[u].all_nrec + 1);
} /* end for */
/* Check last node pointer */
if(u == internal->nrec) {
/* Check if record is in child node */
if(internal->node_ptrs[u].all_nrec > idx) {
/* Get node pointer for next node to search */
next_node_ptr = internal->node_ptrs[u];
/* Unlock current node */
if(H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
/* Set pointer to next node to load */
curr_node_ptr = next_node_ptr;
} /* end if */
else
/* Index that is greater than the number of records in the tree? */
HDassert("Index off end of tree??" && 0);
} /* end if */
/* Decrement depth we're at in B-tree */
depth--;
} /* end while */
{
H5B2_leaf_t *leaf; /* Pointer to leaf node in B-tree */
/* Lock B-tree leaf node */
if(NULL == (leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr.addr, &(curr_node_ptr.node_nrec), bt2_shared, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
/* Sanity check index */
HDassert(idx < leaf->nrec);
/* Make callback for correct record */
if((op)(H5B2_LEAF_NREC(leaf, shared, idx), op_data) < 0) {
/* Unlock current node */
if(H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr.addr, leaf, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "'found' callback failed for B-tree find operation")
} /* end if */
/* Unlock current node */
if(H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr.addr, leaf, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
} /* end block */
done:
/* Check if we need to decrement the reference count for the B-tree's shared info */
if(incr_rc)
H5RC_DEC(bt2_shared);
FUNC_LEAVE_NOAPI(ret_value)
} /* H5B2_index() */
/*-------------------------------------------------------------------------
* Function: H5B2_remove
*
* Purpose: Removes a record from a B-tree.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Feb 25 2005
*
*-------------------------------------------------------------------------
*/
herr_t
H5B2_remove(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr,
void *udata, H5B2_remove_t op, void *op_data)
{
H5B2_t *bt2 = NULL; /* Pointer to the B-tree header */
unsigned bt2_flags = H5AC__NO_FLAGS_SET;
H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5B2_remove, FAIL)
/* Check arguments. */
HDassert(f);
HDassert(type);
HDassert(H5F_addr_defined(addr));
/* Look up the b-tree header */
if(NULL == (bt2 = H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, addr, type, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree header")
/* Get the pointer to the shared B-tree info */
shared = H5RC_GET_OBJ(bt2->shared);
HDassert(shared);
/* Check for empty B-tree */
if(bt2->root.all_nrec == 0)
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "record is not in B-tree")
/* Attempt to remove record from B-tree */
if(shared->depth > 0) {
hbool_t depth_decreased = FALSE; /* Flag to indicate whether the depth of the B-tree decreased */
if(H5B2_remove_internal(f, dxpl_id, bt2->shared, &depth_decreased, NULL, shared->depth,
&(bt2->cache_info), &bt2_flags, &bt2->root, udata, op, op_data) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record from B-tree internal node")
/* Check for decreasing the depth of the B-tree */
if(depth_decreased) {
/* Destroy free list factories for previous depth */
if(shared->node_info[shared->depth].nat_rec_fac)
if(H5FL_fac_term(shared->node_info[shared->depth].nat_rec_fac) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't destroy node's native record block factory")
if(shared->node_info[shared->depth].node_ptr_fac)
if(H5FL_fac_term(shared->node_info[shared->depth].node_ptr_fac) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't destroy node's node pointer block factory")
shared->depth -= depth_decreased;
} /* end for */
} /* end if */
else {
if(H5B2_remove_leaf(f, dxpl_id, bt2->shared, &bt2->root, udata, op, op_data) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record from B-tree leaf node")
} /* end else */
/* Decrement # of records in B-tree */
bt2->root.all_nrec--;
/* Mark parent node as dirty */
bt2_flags |= H5AC__DIRTIED_FLAG;
done:
/* Release the B-tree header info */
if (bt2 && H5AC_unprotect(f, dxpl_id, H5AC_BT2_HDR, addr, bt2, bt2_flags) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree header info")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5B2_remove() */
/*-------------------------------------------------------------------------
* Function: H5B2_remove_by_idx
*
* Purpose: Removes the n'th record from a B-tree.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@hdfgroup.org
* Nov 14 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5B2_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type,
haddr_t addr, H5_iter_order_t order, hsize_t idx, H5B2_remove_t op,
void *op_data)
{
H5B2_t *bt2 = NULL; /* Pointer to the B-tree header */
unsigned bt2_flags = H5AC__NO_FLAGS_SET;
H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5B2_remove_by_idx, FAIL)
/* Check arguments. */
HDassert(f);
HDassert(type);
HDassert(H5F_addr_defined(addr));
/* Look up the b-tree header */
if(NULL == (bt2 = H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, addr, type, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree header")
/* Get the pointer to the shared B-tree info */
shared = H5RC_GET_OBJ(bt2->shared);
HDassert(shared);
/* Check for empty B-tree */
if(bt2->root.all_nrec == 0)
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "record is not in B-tree")
/* Check for index greater than the number of records in the tree */
if(idx >= bt2->root.all_nrec)
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "B-tree doesn't have that many records")
/* Check for reverse indexing and map requested index to appropriate forward index */
if(order == H5_ITER_DEC)
idx = bt2->root.all_nrec - (idx + 1);
/* Attempt to remove record from B-tree */
if(shared->depth > 0) {
hbool_t depth_decreased = FALSE; /* Flag to indicate whether the depth of the B-tree decreased */
if(H5B2_remove_internal_by_idx(f, dxpl_id, bt2->shared, &depth_decreased, NULL, shared->depth,
&(bt2->cache_info), &bt2_flags, &bt2->root, idx, op, op_data) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record from B-tree internal node")
/* Check for decreasing the depth of the B-tree */
if(depth_decreased) {
/* Destroy free list factories for previous depth */
if(shared->node_info[shared->depth].nat_rec_fac)
if(H5FL_fac_term(shared->node_info[shared->depth].nat_rec_fac) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't destroy node's native record block factory")
if(shared->node_info[shared->depth].node_ptr_fac)
if(H5FL_fac_term(shared->node_info[shared->depth].node_ptr_fac) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't destroy node's node pointer block factory")
shared->depth -= depth_decreased;
} /* end for */
} /* end if */
else {
if(H5B2_remove_leaf_by_idx(f, dxpl_id, bt2->shared, &bt2->root, (unsigned)idx, op, op_data) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record from B-tree leaf node")
} /* end else */
/* Decrement # of records in B-tree */
bt2->root.all_nrec--;
/* Mark parent node as dirty */
bt2_flags |= H5AC__DIRTIED_FLAG;
done:
/* Release the B-tree header info */
if (bt2 && H5AC_unprotect(f, dxpl_id, H5AC_BT2_HDR, addr, bt2, bt2_flags) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree header info")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5B2_remove_by_idx() */
/*-------------------------------------------------------------------------
* Function: H5B2_get_nrec
*
* Purpose: Retrieves the number of records in a B-tree
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Feb 25 2005
*
*-------------------------------------------------------------------------
*/
herr_t
H5B2_get_nrec(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr,
hsize_t *nrec)
{
H5B2_t *bt2=NULL; /* Pointer to the B-tree header */
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5B2_get_nrec, FAIL)
/* Check arguments. */
HDassert(f);
HDassert(type);
HDassert(H5F_addr_defined(addr));
HDassert(nrec);
/* Look up the B-tree header */
if (NULL == (bt2 = H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, addr, type, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree header")
/* Get B-tree number of records */
*nrec = bt2->root.all_nrec;
done:
/* Release B-tree header node */
if (bt2 && H5AC_unprotect(f, dxpl_id, H5AC_BT2_HDR, addr, bt2, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree header info")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5B2_get_nrec() */
/*-------------------------------------------------------------------------
* Function: H5B2_neighbor
*
* Purpose: Locate a record relative to the specified information in a
* B-tree and return that information by filling in fields of the
* caller-supplied UDATA pointer depending on the type of leaf node
* requested. The UDATA can point to additional data passed
* to the key comparison function.
*
* The 'OP' routine is called with the record found and the
* OP_DATA pointer, to allow caller to return information about
* the record.
*
* The RANGE indicates whether to search for records less than or
* equal to, or greater than or equal to the information passed
* in with UDATA.
*
* Return: Non-negative on success, negative on failure.
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Mar 8 2005
*
*-------------------------------------------------------------------------
*/
herr_t
H5B2_neighbor(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr,
H5B2_compare_t range, void *udata, H5B2_found_t op, void *op_data)
{
H5B2_t *bt2 = NULL; /* Pointer to the B-tree header */
H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5B2_neighbor, FAIL)
/* Check arguments. */
HDassert(f);
HDassert(type);
HDassert(H5F_addr_defined(addr));
HDassert(op);
/* Look up the B-tree header */
if(NULL == (bt2 = H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, addr, type, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree header")
/* Get the pointer to the shared B-tree info */
shared = H5RC_GET_OBJ(bt2->shared);
HDassert(shared);
/* Check for empty tree */
if(!H5F_addr_defined(bt2->root.addr))
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "B-tree has no records")
/* Attempt to find neighbor record in B-tree */
if(shared->depth > 0) {
if(H5B2_neighbor_internal(f, dxpl_id, bt2->shared, shared->depth, &bt2->root, NULL, range, udata, op, op_data)<0)
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "unable to find neighbor record in B-tree internal node")
} /* end if */
else {
if(H5B2_neighbor_leaf(f, dxpl_id, bt2->shared, &bt2->root, NULL, range, udata, op, op_data)<0)
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "unable to find neighbor record in B-tree leaf node")
} /* end else */
done:
/* Release the B-tree header info */
if (bt2 && H5AC_unprotect(f, dxpl_id, H5AC_BT2_HDR, addr, bt2, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree header info")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5B2_neighbor() */
/*-------------------------------------------------------------------------
* Function: H5B2_delete
*
* Purpose: Delete an entire B-tree from a file.
*
* The 'OP' routine is called for each record and the
* OP_DATA pointer, to allow caller to perform an operation as
* each record is removed from the B-tree.
*
* If 'OP' is NULL, the records are just removed in the process
* of deleting the B-tree.
*
* Note: The records are _not_ guaranteed to be visited in order.
*
* Return: Non-negative on success, negative on failure.
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Mar 9 2005
*
*-------------------------------------------------------------------------
*/
herr_t
H5B2_delete(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr,
H5B2_remove_t op, void *op_data)
{
H5B2_t *bt2 = NULL; /* Pointer to the B-tree header */
H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5B2_delete, FAIL)
/* Check arguments. */
HDassert(f);
HDassert(type);
HDassert(H5F_addr_defined(addr));
/* Look up the B-tree header */
if(NULL == (bt2 = H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, addr, type, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree header")
/* Get the pointer to the shared B-tree info */
shared = H5RC_GET_OBJ(bt2->shared);
HDassert(shared);
/* Delete all nodes in B-tree */
if(H5F_addr_defined(bt2->root.addr))
if(H5B2_delete_node(f, dxpl_id, bt2->shared, shared->depth, &bt2->root, op, op_data) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to delete B-tree nodes")
/* Release space for B-tree node on disk */
if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, addr, (hsize_t)H5B2_HEADER_SIZE(f))<0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree header info")
done:
/* Release the B-tree header info */
if(bt2 && H5AC_unprotect(f, dxpl_id, H5AC_BT2_HDR, addr, bt2, H5AC__DELETED_FLAG) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to delete B-tree header info")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5B2_delete() */
/*-------------------------------------------------------------------------
* Function: H5B2_modify
*
* Purpose: Locate the specified information in a B-tree and modify it.
* The UDATA can point to additional data passed
* to the key comparison function.
*
* The 'OP' routine is called with the record found and the
* OP_DATA pointer, to allow caller to modify information about
* the record.
*
* Return: Non-negative on success, negative on failure.
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Mar 10 2005
*
*-------------------------------------------------------------------------
*/
herr_t
H5B2_modify(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr,
void *udata, H5B2_modify_t op, void *op_data)
{
H5B2_t *bt2=NULL; /* Pointer to the B-tree header */
H5RC_t *bt2_shared=NULL; /* Pointer to ref-counter for shared B-tree info */
H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
hbool_t incr_rc=FALSE; /* Flag to indicate that we've incremented the B-tree's shared info reference count */
H5B2_node_ptr_t curr_node_ptr; /* Node pointer info for current node */
unsigned depth; /* Current depth of the tree */
int cmp; /* Comparison value of records */
unsigned idx; /* Location of record which matches key */
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5B2_modify, FAIL)
/* Check arguments. */
HDassert(f);
HDassert(type);
HDassert(H5F_addr_defined(addr));
HDassert(op);
/* Look up the B-tree header */
if(NULL == (bt2 = H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, addr, type, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree header")
/* Safely grab pointer to reference counted shared B-tree info, so we can release the B-tree header if necessary */
bt2_shared = bt2->shared;
H5RC_INC(bt2_shared);
incr_rc = TRUE;
/* Get the pointer to the shared B-tree info */
shared=H5RC_GET_OBJ(bt2_shared);
HDassert(shared);
/* Make copy of the root node pointer to start search with */
curr_node_ptr = bt2->root;
/* Current depth of the tree */
depth = shared->depth;
/* Release header */
if(H5AC_unprotect(f, dxpl_id, H5AC_BT2_HDR, addr, bt2, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree header info")
bt2 = NULL;
/* Check for empty tree */
if(curr_node_ptr.node_nrec==0)
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "B-tree has no records")
/* Walk down B-tree to find record or leaf node where record is located */
cmp = -1;
while(depth > 0 && cmp != 0) {
unsigned internal_flags = H5AC__NO_FLAGS_SET;
H5B2_internal_t *internal; /* Pointer to internal node in B-tree */
H5B2_node_ptr_t next_node_ptr; /* Node pointer info for next node */
/* Lock B-tree current node */
if(NULL == (internal = H5B2_protect_internal(f, dxpl_id, bt2_shared, curr_node_ptr.addr, curr_node_ptr.node_nrec, depth, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
/* Locate node pointer for child */
cmp = H5B2_locate_record(shared->type, internal->nrec, shared->nat_off, internal->int_native, udata, &idx);
if(cmp > 0)
idx++;
if(cmp != 0) {
/* Get node pointer for next node to search */
next_node_ptr=internal->node_ptrs[idx];
/* Unlock current node */
if (H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
/* Set pointer to next node to load */
curr_node_ptr = next_node_ptr;
} /* end if */
else {
hbool_t changed; /* Whether the 'modify' callback changed the record */
/* Make callback for current record */
if ( (op)(H5B2_INT_NREC(internal,shared,idx), op_data, &changed) <0) {
/* Make certain that the callback didn't modify the value if it failed */
HDassert(changed==FALSE);
/* Unlock current node */
if (H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
HGOTO_ERROR(H5E_BTREE, H5E_CANTMODIFY, FAIL, "'modify' callback failed for B-tree find operation")
} /* end if */
/* Mark the node as dirty if it changed */
internal_flags |= changed ? H5AC__DIRTIED_FLAG : 0;
/* Unlock current node */
if (H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, internal_flags) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
HGOTO_DONE(SUCCEED);
} /* end else */
/* Decrement depth we're at in B-tree */
depth--;
} /* end while */
{
unsigned leaf_flags = H5AC__NO_FLAGS_SET;
H5B2_leaf_t *leaf; /* Pointer to leaf node in B-tree */
hbool_t changed; /* Whether the 'modify' callback changed the record */
/* Lock B-tree leaf node */
if (NULL == (leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr.addr, &(curr_node_ptr.node_nrec), bt2_shared, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
/* Locate record */
cmp = H5B2_locate_record(shared->type, leaf->nrec, shared->nat_off, leaf->leaf_native, udata, &idx);
if(cmp != 0) {
/* Unlock leaf node */
if (H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr.addr, leaf, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
/* Note: don't push error on stack, leave that to next higher level,
* since many times the B-tree is searched in order to determine
* if an object exists in the B-tree or not. -QAK
*/
#ifdef OLD_WAY
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "key not found in leaf node")
#else /* OLD_WAY */
HGOTO_DONE(FAIL)
#endif /* OLD_WAY */
} /* end if */
else {
/* Make callback for current record */
if ((op)(H5B2_LEAF_NREC(leaf,shared,idx), op_data, &changed) <0) {
/* Make certain that the callback didn't modify the value if it failed */
HDassert(changed==FALSE);
/* Unlock current node */
if (H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr.addr, leaf, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
HGOTO_ERROR(H5E_BTREE, H5E_CANTMODIFY, FAIL, "'modify' callback failed for B-tree find operation")
} /* end if */
} /* end else */
/* Mark the node as dirty if it changed */
leaf_flags |= changed ? H5AC__DIRTIED_FLAG : 0;
/* Unlock current node */
if (H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr.addr, leaf, leaf_flags) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
}
done:
/* Check if we need to decrement the reference count for the B-tree's shared info */
if(incr_rc)
H5RC_DEC(bt2_shared);
FUNC_LEAVE_NOAPI(ret_value)
} /* H5B2_modify() */