diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2006-02-27 14:52:21 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2006-02-27 14:52:21 (GMT) |
commit | 658bf4a8fb16cd3334b3fbfa2628226ffc20931f (patch) | |
tree | fea930220af70816b8ee849a24bb0c0e47c3acb9 | |
parent | 3713db1174ff83154ff63f93b4ba512eebed9748 (diff) | |
download | hdf5-658bf4a8fb16cd3334b3fbfa2628226ffc20931f.zip hdf5-658bf4a8fb16cd3334b3fbfa2628226ffc20931f.tar.gz hdf5-658bf4a8fb16cd3334b3fbfa2628226ffc20931f.tar.bz2 |
[svn-r11968] Purpose:
Incrementtal checkin
Description:
Revise & update v2 B-tree code to separate the internal package-specific
routines from the library-callable "private" routines.
Similar updates for the fractal heap code.
Platforms tested:
FreeBSD 4.11 (sleipnir)
Mac OSX (amazon)
-rw-r--r-- | MANIFEST | 2 | ||||
-rw-r--r-- | src/H5B2.c | 3321 | ||||
-rw-r--r-- | src/H5B2cache.c | 150 | ||||
-rw-r--r-- | src/H5B2int.c | 3357 | ||||
-rw-r--r-- | src/H5B2pkg.h | 39 | ||||
-rw-r--r-- | src/H5HF.c | 101 | ||||
-rw-r--r-- | src/H5HFcache.c | 27 | ||||
-rw-r--r-- | src/H5HFdbg.c | 12 | ||||
-rw-r--r-- | src/H5HFint.c | 197 | ||||
-rw-r--r-- | src/H5HFpkg.h | 20 | ||||
-rw-r--r-- | src/H5HFprivate.h | 13 | ||||
-rw-r--r-- | src/H5HFtest.c | 18 | ||||
-rwxr-xr-x | src/Makefile.am | 7 | ||||
-rw-r--r-- | src/Makefile.in | 13 | ||||
-rw-r--r-- | test/fheap.c | 32 |
15 files changed, 3791 insertions, 3518 deletions
@@ -406,6 +406,7 @@ ./src/H5B2.c ./src/H5B2cache.c ./src/H5B2dbg.c +./src/H5B2int.c ./src/H5B2pkg.h ./src/H5B2private.h ./src/H5B2public.h @@ -495,6 +496,7 @@ ./src/H5HF.c ./src/H5HFcache.c ./src/H5HFdbg.c +./src/H5HFint.c ./src/H5HFpkg.h ./src/H5HFprivate.h ./src/H5HFpublic.h @@ -46,84 +46,16 @@ /* Local Macros */ /****************/ -/* Format overhead for each node (on disk) */ -#define H5B2_OVERHEAD_SIZE (H5B2_SIZEOF_MAGIC+1) /* Signature + version # */ - -/* Number of records that fit into internal node */ -#define H5B2_NUM_INT_REC(f,n,r) (((n)-(H5B2_OVERHEAD_SIZE+H5B2_NODE_POINTER_SIZE(f)))/((r)+H5B2_NODE_POINTER_SIZE(f))) - -/* Number of records that fit into leaf node */ -#define H5B2_NUM_LEAF_REC(n,r) (((n)-H5B2_OVERHEAD_SIZE)/(r)) - -/* Uncomment this macro to enable extra sanity checking */ -/* #define H5B2_DEBUG */ - /******************/ /* Local Typedefs */ /******************/ + /********************/ /* Local Prototypes */ /********************/ -/* Helper functions */ -static herr_t H5B2_shared_free(void *_shared); -static herr_t H5B2_create_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, - H5B2_node_ptr_t *node_ptr); -static herr_t H5B2_create_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, - H5B2_node_ptr_t *node_ptr); -static int H5B2_locate_record(const H5B2_class_t *type, unsigned nrec, - size_t *rec_off, const uint8_t *native, const void *udata, unsigned *idx); -static herr_t H5B2_split_root(H5F_t *f, hid_t dxpl_id, H5B2_t *bt2, - unsigned *bt2_flags_ptr, H5RC_t *bt2_shared); -static herr_t H5B2_redistribute2(H5F_t *f, hid_t dxpl_id, unsigned depth, - H5B2_internal_t *internal, unsigned idx); -static herr_t H5B2_split2(H5F_t *f, hid_t dxpl_id, unsigned depth, - H5B2_node_ptr_t *curr_node_ptr, unsigned * parent_cache_info_flags_ptr, - H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx); -static herr_t H5B2_split3(H5F_t *f, hid_t dxpl_id, unsigned depth, - H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags, - H5B2_internal_t *internal, unsigned *internal_flags, unsigned idx); -static herr_t H5B2_redistribute3(H5F_t *f, hid_t dxpl_id, unsigned depth, - H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx); -static herr_t H5B2_merge2(H5F_t *f, hid_t dxpl_id, unsigned depth, - H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags_ptr, - H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx); -static herr_t H5B2_merge3(H5F_t *f, hid_t dxpl_id, unsigned depth, - H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags_ptr, - H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx); -static herr_t H5B2_swap_leaf(H5F_t *f, hid_t dxpl_id, unsigned depth, - H5B2_internal_t *internal, unsigned *internal_flags_ptr, - unsigned idx, void *swap_loc); -static herr_t H5B2_insert_internal(H5F_t *f, hid_t dxpl_id, - H5RC_t *bt2_shared, unsigned depth, unsigned *parent_cache_info_flags_ptr, - H5B2_node_ptr_t *curr_node_ptr, void *udata); -static herr_t H5B2_insert_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, - H5B2_node_ptr_t *curr_node_ptr, void *udata); -static herr_t H5B2_remove_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, - hbool_t *depth_decreased, void *swap_loc, unsigned depth, H5AC_info_t *parent_cache_info, - hbool_t * parent_cache_info_dirtied_ptr, H5B2_node_ptr_t *curr_node_ptr, void *udata); -static herr_t H5B2_remove_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, - H5B2_node_ptr_t *curr_node_ptr, void *udata); -static herr_t H5B2_iterate_node(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, - unsigned depth, const H5B2_node_ptr_t *curr_node, H5B2_operator_t op, - void *op_data); -static herr_t H5B2_neighbor_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, - H5B2_node_ptr_t *curr_node_ptr, void *neighbor_loc, - H5B2_compare_t comp, void *udata, H5B2_found_t op, void *op_data); -static herr_t H5B2_neighbor_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, - unsigned depth, H5B2_node_ptr_t *curr_node_ptr, void *neighbor_loc, - H5B2_compare_t comp, void *udata, H5B2_found_t op, void *op_data); -static herr_t H5B2_delete_node(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, - unsigned depth, const H5B2_node_ptr_t *curr_node); -#ifdef H5B2_DEBUG -static herr_t H5B2_assert_leaf(H5B2_shared_t *shared, H5B2_leaf_t *leaf); -static herr_t H5B2_assert_leaf2(H5B2_shared_t *shared, H5B2_leaf_t *leaf, H5B2_leaf_t *leaf2); -static herr_t H5B2_assert_internal(hsize_t parent_all_nrec, H5B2_shared_t *shared, H5B2_internal_t *internal); -static herr_t H5B2_assert_internal2(hsize_t parent_all_nrec, H5B2_shared_t *shared, H5B2_internal_t *internal, H5B2_internal_t *internal2); -#endif /* H5B2_DEBUG */ - /*********************/ /* Package Variables */ @@ -132,171 +64,15 @@ static herr_t H5B2_assert_internal2(hsize_t parent_all_nrec, H5B2_shared_t *shar /* Declare a free list to manage the H5B2_t struct */ H5FL_DEFINE(H5B2_t); -/* Declare a free list to manage the H5B2_internal_t struct */ -H5FL_DEFINE(H5B2_internal_t); - -/* Declare a free list to manage the H5B2_leaf_t struct */ -H5FL_DEFINE(H5B2_leaf_t); - /*****************************/ /* Library Private Variables */ /*****************************/ + /*******************/ /* Local Variables */ /*******************/ -/* Declare a free list to manage B-tree node pages to/from disk */ -H5FL_BLK_DEFINE_STATIC(node_page); - -/* Declare a free list to manage the 'size_t' sequence information */ -H5FL_SEQ_DEFINE_STATIC(size_t); - -/* Declare a free list to manage the H5B2_shared_t struct */ -H5FL_DEFINE_STATIC(H5B2_shared_t); - - - -/*------------------------------------------------------------------------- - * Function: H5B2_shared_init - * - * Purpose: Allocate & initialize shared B-tree info - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Feb 2 2005 - * - *------------------------------------------------------------------------- - */ -herr_t -H5B2_shared_init (H5F_t *f, H5B2_t *bt2, const H5B2_class_t *type, - size_t node_size, size_t rrec_size, - unsigned split_percent, unsigned merge_percent) -{ - H5B2_shared_t *shared = NULL; /* Shared B-tree information */ - unsigned u; /* Local index variable */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5B2_shared_init) - - /* Allocate space for the shared information */ - if(NULL == (shared = H5FL_CALLOC(H5B2_shared_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree shared information") - - /* Assign user's information */ - shared->split_percent = split_percent; - shared->merge_percent = merge_percent; - shared->node_size = node_size; - shared->rrec_size = rrec_size; - - /* Compute derived information */ - shared->internal_nrec = H5B2_NUM_INT_REC(f, shared->node_size, shared->rrec_size); - shared->split_int_nrec = (shared->internal_nrec * shared->split_percent) / 100; - shared->merge_int_nrec = (shared->internal_nrec * shared->merge_percent) / 100; - - shared->leaf_nrec = H5B2_NUM_LEAF_REC(shared->node_size, shared->rrec_size); - shared->split_leaf_nrec = (shared->leaf_nrec * shared->split_percent) / 100; - shared->merge_leaf_nrec = (shared->leaf_nrec * shared->merge_percent) / 100; - - /* Assign common type information */ - shared->type = type; - - /* Allocate "page" for node I/O */ - if((shared->page = H5FL_BLK_MALLOC(node_page, shared->node_size)) == NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") -#ifdef H5_USING_PURIFY -HDmemset(shared->page,0,shared->node_size); -#endif /* H5_USING_PURIFY */ - - /* Create factory for internal node native record storage */ - if((shared->int_fac = H5FL_fac_init(type->nrec_size * shared->internal_nrec)) == NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create internal node native key block factory") - - /* Create factory for leaf node native record storage */ - if((shared->leaf_fac = H5FL_fac_init(type->nrec_size * shared->leaf_nrec)) == NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create leaf node native key block factory") - - /* Create factory for internal node node pointer storage */ - if((shared->node_ptr_fac = H5FL_fac_init(sizeof(H5B2_node_ptr_t) * (shared->internal_nrec + 1))) == NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create internal node node pointer block factory") - - /* Allocate array of pointers to internal node native keys */ - if((shared->nat_off = H5FL_SEQ_MALLOC(size_t, MAX(shared->internal_nrec, shared->leaf_nrec))) == NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - - /* Initialize offsets in native key block */ - for(u = 0; u < MAX(shared->internal_nrec, shared->leaf_nrec); u++) - shared->nat_off[u]=type->nrec_size*u; - - /* Make shared B-tree info reference counted */ - if(NULL == (bt2->shared = H5RC_create(shared, H5B2_shared_free))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create ref-count wrapper for shared B-tree info") - -done: - if(ret_value < 0) - if(shared) - H5B2_shared_free(shared); - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5B2_shared_init() */ - - -/*------------------------------------------------------------------------- - * Function: H5B2_shared_free - * - * Purpose: Free shared B-tree info - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Feb 2 2005 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B2_shared_free(void *_shared) -{ - H5B2_shared_t *shared = (H5B2_shared_t *)_shared; - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI_NOINIT(H5B2_shared_free) - - /* Sanity check */ - HDassert(shared); - - /* Free the B-tree node buffer */ - if(shared->page) - H5FL_BLK_FREE(node_page, shared->page); - - /* Destroy factory for internal node native record storage */ - if(shared->int_fac) - if(H5FL_fac_term(shared->int_fac) < 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't destroy internal node native key block factory") - - /* Destroy factory for leaf node native record storage */ - if(shared->leaf_fac) - if(H5FL_fac_term(shared->leaf_fac) < 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't destroy leaf node native key block factory") - - /* Destroy factory for internal node node pointer storage */ - if(shared->node_ptr_fac) - if(H5FL_fac_term(shared->node_ptr_fac) < 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't destroy internal node node pointer block factory") - - /* Free the array of offsets into the native key block */ - if(shared->nat_off) - H5FL_SEQ_FREE(size_t,shared->nat_off); - - /* Free the shared B-tree info itself */ - H5FL_FREE(H5B2_shared_t, shared); - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5B2_shared_free() */ - /*------------------------------------------------------------------------- * Function: H5B2_create @@ -370,2138 +146,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5B2_locate_record - * - * Purpose: Performs a binary search to locate a record in a sorted - * array of records. - * - * Sets *IDX to location of record greater than or equal to - * record to locate. - * - * Return: Comparison value for insertion location. Negative for record - * to locate being less than value in *IDX. Zero for record to - * locate equal to value in *IDX. Positive for record to locate - * being greater than value in *IDX (which should only happen when - * record to locate is greater than all records to search). - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Feb 3 2005 - * - *------------------------------------------------------------------------- - */ -static int -H5B2_locate_record(const H5B2_class_t *type, unsigned nrec, size_t *rec_off, - const uint8_t *native, const void *udata, unsigned *idx) -{ - unsigned lo = 0, hi; /* Low & high index values */ - unsigned my_idx = 0; /* Final index value */ - int cmp = -1; /* Key comparison value */ - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B2_locate_record) - - hi = nrec; - while (lo < hi && cmp) { - my_idx = (lo + hi) / 2; - if ((cmp = (type->compare)(udata, native+rec_off[my_idx])) < 0) - hi = my_idx; - else - lo = my_idx + 1; - } - - *idx = my_idx; - - FUNC_LEAVE_NOAPI(cmp); -} /* end H5B2_locate_record */ - - -/*------------------------------------------------------------------------- - * Function: H5B2_split_root - * - * Purpose: Split the root node - * - * Return: Success: Non-negative - * - * Failure: Negative - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Feb 3 2005 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B2_split_root(H5F_t *f, hid_t dxpl_id, H5B2_t *bt2, unsigned *bt2_flags_ptr, - H5RC_t *bt2_shared) -{ - const H5AC_class_t *child_class; /* Pointer to child node's class info */ - H5B2_internal_t *new_root; /* Pointer to new root node */ - haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */ - void *left_child, *right_child; /* Pointers to child nodes */ - unsigned *left_nrec, *right_nrec; /* Pointers to child # of records */ - uint8_t *left_native, *right_native;/* Pointers to childs' native records */ - H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */ - H5B2_shared_t *shared; /* B-tree's shared info */ - unsigned mid_record; /* Index of "middle" record in current node */ - unsigned old_root_nrec; /* Number of records in root node */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5B2_split_root) - - HDassert(f); - HDassert(bt2); - HDassert(bt2_flags_ptr); - HDassert(bt2_shared); - - /* Get the pointer to the shared B-tree info */ - shared=H5RC_GET_OBJ(bt2_shared); - HDassert(shared); - - if(bt2->depth>0) { - H5B2_internal_t *old_int=NULL, *new_int=NULL; /* Pointers to old & new internal nodes */ - H5B2_node_ptr_t new_int_ptr; /* Node pointer to manage new internal node */ - - /* Create new internal node */ - new_int_ptr.all_nrec=new_int_ptr.node_nrec=0; - if(H5B2_create_internal(f, dxpl_id, bt2_shared, &new_int_ptr)<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new internal node") - - /* Setup information for unlocking child nodes */ - child_class = H5AC_BT2_INT; - left_addr = bt2->root.addr; - right_addr = new_int_ptr.addr; - - /* Protect both leafs */ - if (NULL == (old_int = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, left_addr, &(bt2->root.node_nrec), bt2_shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") - if (NULL == (new_int = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, right_addr, &(new_int_ptr.node_nrec), bt2_shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") - - /* More setup for child nodes */ - left_child = old_int; - right_child = new_int; - left_nrec = &(old_int->nrec); - right_nrec = &(new_int->nrec); - left_native = old_int->int_native; - right_native = new_int->int_native; - left_node_ptrs = old_int->node_ptrs; - right_node_ptrs = new_int->node_ptrs; - } /* end if */ - else { - H5B2_leaf_t *old_leaf=NULL, *new_leaf=NULL; /* Pointers to old & new leaf nodes */ - H5B2_node_ptr_t new_leaf_ptr; /* Node pointer to manage new leaf node */ - - /* Create new leaf node */ - new_leaf_ptr.all_nrec=new_leaf_ptr.node_nrec=0; - if(H5B2_create_leaf(f, dxpl_id, bt2_shared, &new_leaf_ptr)<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new leaf node") - - /* Setup information for unlocking child nodes */ - child_class = H5AC_BT2_LEAF; - left_addr = bt2->root.addr; - right_addr = new_leaf_ptr.addr; - - /* Protect both leafs */ - if (NULL == (old_leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, left_addr, &(bt2->root.node_nrec), bt2_shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") - if (NULL == (new_leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, right_addr, &(new_leaf_ptr.node_nrec), bt2_shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") - - /* More setup for child nodes */ - left_child = old_leaf; - right_child = new_leaf; - left_nrec = &(old_leaf->nrec); - right_nrec = &(new_leaf->nrec); - left_native = old_leaf->leaf_native; - right_native = new_leaf->leaf_native; - } /* end if */ - - /* Set the old number of records in root node */ - old_root_nrec = bt2->root.node_nrec; - - /* Determine "middle" record to promote to new root */ - mid_record = old_root_nrec/2; - - /* Copy "upper half" of records to new child */ - HDmemcpy(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(left_native,shared,mid_record+1),shared->type->nrec_size*(old_root_nrec-(mid_record+1))); - - /* Copy "upper half" of format root's node pointers, if the children of the root are internal nodes */ - if(bt2->depth>0) - HDmemcpy(&(right_node_ptrs[0]),&(left_node_ptrs[mid_record+1]),sizeof(H5B2_node_ptr_t)*(old_root_nrec-mid_record)); - - /* Create new internal node to use as root */ - if(H5B2_create_internal(f, dxpl_id, bt2_shared, &(bt2->root))<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new internal node") - - /* Protect new internal node */ - if (NULL == (new_root = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, bt2->root.addr, &(bt2->root.node_nrec), bt2_shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") - - /* Copy "middle" record to new internal node */ - HDmemcpy(H5B2_INT_NREC(new_root,shared,0),H5B2_NAT_NREC(left_native,shared,mid_record),shared->type->nrec_size); - - /* Set internal node pointers to child nodes */ - new_root->node_ptrs[0].addr = left_addr; - new_root->node_ptrs[1].addr = right_addr; - - /* Update record counts in child nodes */ - new_root->node_ptrs[0].node_nrec = *left_nrec = mid_record; - new_root->node_ptrs[1].node_nrec = *right_nrec = old_root_nrec-(mid_record+1); - - /* Determine total number of records in new child nodes */ - if(bt2->depth>0) { - unsigned u; /* Local index variable */ - hsize_t new_left_all_nrec; /* New total number of records in left child */ - hsize_t new_right_all_nrec; /* New total number of records in right child */ - - /* Compute total of all records in each child node */ - new_left_all_nrec = new_root->node_ptrs[0].node_nrec; - for(u=0; u<(*left_nrec+1); u++) - new_left_all_nrec += left_node_ptrs[u].all_nrec; - - new_right_all_nrec = new_root->node_ptrs[1].node_nrec; - for(u=0; u<(*right_nrec+1); u++) - new_right_all_nrec += right_node_ptrs[u].all_nrec; - - new_root->node_ptrs[0].all_nrec = new_left_all_nrec; - new_root->node_ptrs[1].all_nrec = new_right_all_nrec; - } /* end if */ - else { - new_root->node_ptrs[0].all_nrec = new_root->node_ptrs[0].node_nrec; - new_root->node_ptrs[1].all_nrec = new_root->node_ptrs[1].node_nrec; - } /* end else */ - - /* Update record count in new internal node */ - new_root->nrec = 1; - -#ifdef H5B2_DEBUG - H5B2_assert_internal(bt2->root.all_nrec,shared,new_root); - if(bt2->depth>0) { - H5B2_assert_internal2(new_root->node_ptrs[0].all_nrec,shared,left_child,right_child); - H5B2_assert_internal2(new_root->node_ptrs[1].all_nrec,shared,right_child,left_child); - } /* end if */ - else { - H5B2_assert_leaf2(shared,left_child,right_child); - H5B2_assert_leaf(shared,right_child); - } /* end else */ -#endif /* H5B2_DEBUG */ - /* Release new internal node (marked as dirty) */ - if (H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, bt2->root.addr, new_root, H5AC__DIRTIED_FLAG) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree internal node") - - /* Release child nodes (marked as dirty) */ - if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree leaf node") - if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree leaf node") - - /* Update depth of B-tree */ - bt2->depth++; - - /* Update pointer to B-tree's root node to pointer to new internal node */ - bt2->root.node_nrec = 1; - - /* Mark B-tree header as dirty */ - *bt2_flags_ptr |= H5AC__DIRTIED_FLAG; - -done: - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5B2_split_root */ - - -/*------------------------------------------------------------------------- - * Function: H5B2_redistribute2 - * - * Purpose: Redistribute records between two nodes - * - * Return: Success: Non-negative - * - * Failure: Negative - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Feb 9 2005 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B2_redistribute2(H5F_t *f, hid_t dxpl_id, unsigned depth, H5B2_internal_t *internal, unsigned idx) -{ - const H5AC_class_t *child_class; /* Pointer to child node's class info */ - haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */ - void *left_child, *right_child; /* Pointers to child nodes */ - unsigned *left_nrec, *right_nrec; /* Pointers to child # of records */ - uint8_t *left_native, *right_native; /* Pointers to childs' native records */ - H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */ - H5B2_shared_t *shared; /* B-tree's shared info */ - hssize_t left_moved_nrec=0, right_moved_nrec=0; /* Number of records moved, for internal redistrib */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5B2_redistribute2) - - HDassert(f); - HDassert(internal); - - /* Get the pointer to the shared B-tree info */ - shared=H5RC_GET_OBJ(internal->shared); - HDassert(shared); - - /* Check for the kind of B-tree node to redistribute */ - if(depth>1) { - H5B2_internal_t *left_internal; /* Pointer to left internal node */ - H5B2_internal_t *right_internal; /* Pointer to right internal node */ - - /* Setup information for unlocking child nodes */ - child_class = H5AC_BT2_INT; - left_addr = internal->node_ptrs[idx].addr; - right_addr = internal->node_ptrs[idx+1].addr; - - /* Lock left & right B-tree child nodes */ - if (NULL == (left_internal = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") - if (NULL == (right_internal = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") - - /* More setup for child nodes */ - left_child = left_internal; - right_child = right_internal; - left_nrec = &(left_internal->nrec); - right_nrec = &(right_internal->nrec); - left_native = left_internal->int_native; - right_native = right_internal->int_native; - left_node_ptrs = left_internal->node_ptrs; - right_node_ptrs = right_internal->node_ptrs; - } /* end if */ - else { - H5B2_leaf_t *left_leaf; /* Pointer to left leaf node */ - H5B2_leaf_t *right_leaf; /* Pointer to right leaf node */ - - /* Setup information for unlocking child nodes */ - child_class = H5AC_BT2_LEAF; - left_addr = internal->node_ptrs[idx].addr; - right_addr = internal->node_ptrs[idx+1].addr; - - /* Lock left & right B-tree child nodes */ - if (NULL == (left_leaf = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") - if (NULL == (right_leaf = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") - - /* More setup for child nodes */ - left_child = left_leaf; - right_child = right_leaf; - left_nrec = &(left_leaf->nrec); - right_nrec = &(right_leaf->nrec); - left_native = left_leaf->leaf_native; - right_native = right_leaf->leaf_native; - } /* end else */ - -#ifdef H5B2_DEBUG - H5B2_assert_internal((hsize_t)0,shared,internal); - if(depth>1) { - H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,left_child,right_child); - H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,right_child,left_child); - } /* end if */ - else { - H5B2_assert_leaf2(shared,left_child,right_child); - H5B2_assert_leaf(shared,right_child); - } /* end else */ -#endif /* H5B2_DEBUG */ - - /* Determine whether to shuffle records left or right */ - if(*left_nrec<*right_nrec) { - /* Moving record from right node to left */ - - unsigned new_right_nrec = (*left_nrec+*right_nrec)/2; /* New number of records for right child */ - unsigned move_nrec = *right_nrec - new_right_nrec; /* Number of records to move from right node to left */ - - /* Copy record from parent node down into left child */ - HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size); - - /* See if we need to move records from right node */ - if(move_nrec>1) - HDmemcpy(H5B2_NAT_NREC(left_native,shared,(*left_nrec+1)),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(move_nrec-1)); - - /* Move record from right node into parent node */ - HDmemcpy(H5B2_INT_NREC(internal,shared,idx),H5B2_NAT_NREC(right_native,shared,(move_nrec-1)),shared->type->nrec_size); - - /* Slide records in right node down */ - HDmemmove(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(right_native,shared,move_nrec),shared->type->nrec_size*new_right_nrec); - - /* Handle node pointers, if we have an internal node */ - if(depth>1) { - hsize_t moved_nrec=move_nrec; /* Total number of records moved, for internal redistrib */ - unsigned u; /* Local index variable */ - - /* Count the number of records being moved */ - for(u=0; u<move_nrec; u++) - moved_nrec += right_node_ptrs[u].all_nrec; - left_moved_nrec = moved_nrec; - right_moved_nrec -= moved_nrec; - - /* Copy node pointers from right node to left */ - HDmemcpy(&(left_node_ptrs[*left_nrec+1]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*move_nrec); - - /* Slide node pointers in right node down */ - HDmemmove(&(right_node_ptrs[0]),&(right_node_ptrs[move_nrec]),sizeof(H5B2_node_ptr_t)*(new_right_nrec+1)); - } /* end if */ - - /* Update number of records in child nodes */ - *left_nrec += move_nrec; - *right_nrec = new_right_nrec; - } /* end if */ - else { - /* Moving record from left node to right */ - - unsigned new_left_nrec = (*left_nrec+*right_nrec)/2; /* New number of records for left child */ - unsigned move_nrec = *left_nrec - new_left_nrec; /* Number of records to move from left node to right */ - - /* Slide records in right node up */ - HDmemmove(H5B2_NAT_NREC(right_native,shared,move_nrec), - H5B2_NAT_NREC(right_native,shared,0), - shared->type->nrec_size*(*right_nrec)); - - /* Copy record from parent node down into right child */ - HDmemcpy(H5B2_NAT_NREC(right_native,shared,(move_nrec-1)),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size); - - /* See if we need to move records from left node */ - if(move_nrec>1) - HDmemcpy(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(left_native,shared,((*left_nrec-move_nrec)+1)),shared->type->nrec_size*(move_nrec-1)); - - /* Move record from left node into parent node */ - HDmemcpy(H5B2_INT_NREC(internal,shared,idx),H5B2_NAT_NREC(left_native,shared,(*left_nrec-move_nrec)),shared->type->nrec_size); - - /* Handle node pointers, if we have an internal node */ - if(depth>1) { - hsize_t moved_nrec=move_nrec; /* Total number of records moved, for internal redistrib */ - unsigned u; /* Local index variable */ - - /* Slide node pointers in right node up */ - HDmemmove(&(right_node_ptrs[move_nrec]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*(*right_nrec+1)); - - /* Copy node pointers from left node to right */ - HDmemcpy(&(right_node_ptrs[0]),&(left_node_ptrs[new_left_nrec+1]),sizeof(H5B2_node_ptr_t)*move_nrec); - - /* Count the number of records being moved */ - for(u=0; u<move_nrec; u++) - moved_nrec += right_node_ptrs[u].all_nrec; - left_moved_nrec -= moved_nrec; - right_moved_nrec = moved_nrec; - } /* end if */ - - /* Update number of records in child nodes */ - *left_nrec = new_left_nrec; - *right_nrec += move_nrec; - } /* end else */ - - /* Update # of records in child nodes */ - internal->node_ptrs[idx].node_nrec = *left_nrec; - internal->node_ptrs[idx+1].node_nrec = *right_nrec; - - /* Update total # of records in child B-trees */ - if(depth>1) { - internal->node_ptrs[idx].all_nrec += left_moved_nrec; - internal->node_ptrs[idx+1].all_nrec += right_moved_nrec; - } /* end if */ - else { - internal->node_ptrs[idx].all_nrec = internal->node_ptrs[idx].node_nrec; - internal->node_ptrs[idx+1].all_nrec = internal->node_ptrs[idx+1].node_nrec; - } /* end else */ - -#ifdef H5B2_DEBUG - H5B2_assert_internal((hsize_t)0,shared,internal); - if(depth>1) { - H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,left_child,right_child); - H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,right_child,left_child); - } /* end if */ - else { - H5B2_assert_leaf2(shared,left_child,right_child); - H5B2_assert_leaf(shared,right_child); - } /* end else */ -#endif /* H5B2_DEBUG */ - - /* Release child nodes (marked as dirty) */ - if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") - if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") - -done: - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5B2_redistribute2 */ - - -/*------------------------------------------------------------------------- - * Function: H5B2_split2 - * - * Purpose: Perform a 2->3 node split - * - * Return: Success: Non-negative - * - * Failure: Negative - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Feb 9 2005 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B2_split2(H5F_t *f, hid_t dxpl_id, unsigned depth, H5B2_node_ptr_t *curr_node_ptr, - unsigned *parent_cache_info_flags_ptr, H5B2_internal_t *internal, - unsigned *internal_flags_ptr, unsigned idx) -{ - const H5AC_class_t *child_class; /* Pointer to child node's class info */ - haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */ - haddr_t middle_addr; /* Address of middle child node */ - void *left_child, *right_child; /* Pointers to left & right child nodes */ - void *middle_child; /* Pointer to middle child node */ - unsigned *left_nrec, *right_nrec; /* Pointers to left & right child # of records */ - unsigned *middle_nrec; /* Pointer to middle child # of records */ - uint8_t *left_native, *right_native; /* Pointers to left & right children's native records */ - uint8_t *middle_native; /* Pointer to middle child's native records */ - H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */ - H5B2_node_ptr_t *middle_node_ptrs=NULL;/* Pointers to childs' node pointer info */ - H5B2_shared_t *shared; /* B-tree's shared info */ - hssize_t left_moved_nrec=0, right_moved_nrec=0; /* Number of records moved, for internal split */ - hsize_t middle_moved_nrec=0; /* Number of records moved, for internal split */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5B2_split2) - - HDassert(f); - HDassert(parent_cache_info_flags_ptr); - HDassert(internal); - HDassert(internal_flags_ptr); - - /* Get the pointer to the shared B-tree info */ - shared=H5RC_GET_OBJ(internal->shared); - HDassert(shared); - - /* Slide records in parent node up one space, to make room for promoted record */ - HDmemmove(H5B2_INT_NREC(internal,shared,idx+2),H5B2_INT_NREC(internal,shared,idx+1),shared->type->nrec_size*(internal->nrec-(idx+1))); - HDmemmove(&(internal->node_ptrs[idx+2]),&(internal->node_ptrs[idx+1]),sizeof(H5B2_node_ptr_t)*(internal->nrec-idx)); - - /* Check for the kind of B-tree node to split */ - if(depth>1) { - H5B2_internal_t *left_internal; /* Pointer to left internal node */ - H5B2_internal_t *middle_internal; /* Pointer to middle internal node */ - H5B2_internal_t *right_internal; /* Pointer to right internal node */ - - /* Setup information for unlocking child nodes */ - child_class = H5AC_BT2_INT; - left_addr = internal->node_ptrs[idx].addr; - right_addr = internal->node_ptrs[idx+2].addr; - - /* Lock left & right B-tree child nodes */ - if (NULL == (left_internal = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") - if (NULL == (right_internal = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+2].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") - - /* Create new empty "middle" internal node */ - internal->node_ptrs[idx+1].all_nrec=internal->node_ptrs[idx+1].node_nrec=0; - if(H5B2_create_internal(f, dxpl_id, internal->shared, &(internal->node_ptrs[idx+1]))<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new internal node") - - /* Setup information for unlocking middle child node */ - middle_addr = internal->node_ptrs[idx+1].addr; - - /* Lock "middle" internal node */ - if (NULL == (middle_internal = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") - - /* More setup for accessing child node information */ - left_child = left_internal; - middle_child = middle_internal; - right_child = right_internal; - left_nrec = &(left_internal->nrec); - middle_nrec = &(middle_internal->nrec); - right_nrec = &(right_internal->nrec); - left_native = left_internal->int_native; - middle_native = middle_internal->int_native; - right_native = right_internal->int_native; - left_node_ptrs = left_internal->node_ptrs; - middle_node_ptrs = middle_internal->node_ptrs; - right_node_ptrs = right_internal->node_ptrs; - } /* end if */ - else { - H5B2_leaf_t *left_leaf; /* Pointer to left leaf node */ - H5B2_leaf_t *middle_leaf; /* Pointer to middle leaf node */ - H5B2_leaf_t *right_leaf; /* Pointer to right leaf node */ - - /* Setup information for unlocking child nodes */ - child_class = H5AC_BT2_LEAF; - left_addr = internal->node_ptrs[idx].addr; - right_addr = internal->node_ptrs[idx+2].addr; - - /* Lock left & right B-tree child nodes */ - if (NULL == (left_leaf = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") - if (NULL == (right_leaf = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+2].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") - - /* Create new empty "middle" leaf node */ - internal->node_ptrs[idx+1].all_nrec=internal->node_ptrs[idx+1].node_nrec=0; - if(H5B2_create_leaf(f, dxpl_id, internal->shared, &(internal->node_ptrs[idx+1]))<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new leaf node") - - /* Setup information for unlocking middle child node */ - middle_addr = internal->node_ptrs[idx+1].addr; - - /* Lock "middle" leaf node */ - if (NULL == (middle_leaf = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") - - /* More setup for accessing child node information */ - left_child = left_leaf; - middle_child = middle_leaf; - right_child = right_leaf; - left_nrec = &(left_leaf->nrec); - middle_nrec = &(middle_leaf->nrec); - right_nrec = &(right_leaf->nrec); - left_native = left_leaf->leaf_native; - middle_native = middle_leaf->leaf_native; - right_native = right_leaf->leaf_native; - } /* end else */ - - /* Redistribute records */ - { - /* Compute new # of records in each node */ - unsigned total_nrec = *left_nrec + *right_nrec + 1; - unsigned new_middle_nrec = (total_nrec-2)/3; - unsigned new_left_nrec = ((total_nrec-2)-new_middle_nrec)/2; - unsigned new_right_nrec = (total_nrec-2)-(new_left_nrec+new_middle_nrec); - - /* Fill new middle node */ - { - unsigned curr_middle_idx=0; - - /* Copy record(s) from left node to proper location */ - if(new_left_nrec<(*left_nrec-1)) { - curr_middle_idx=*left_nrec-(new_left_nrec+1); - HDmemcpy(H5B2_NAT_NREC(middle_native,shared,0),H5B2_NAT_NREC(left_native,shared,(new_left_nrec+1)),shared->type->nrec_size*curr_middle_idx); - } /* end if */ - - /* Copy record from parent node to proper location */ - HDmemcpy(H5B2_NAT_NREC(middle_native,shared,curr_middle_idx),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size); - curr_middle_idx++; - - /* Copy record(s) from right node to proper location */ - if(new_right_nrec<(*right_nrec-1)) - HDmemcpy(H5B2_NAT_NREC(middle_native,shared,curr_middle_idx),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(*right_nrec-(new_right_nrec+1))); - - /* Copy node pointers from left and right nodes into middle node */ - if(depth>1) { - hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */ - unsigned move_nptrs; /* Number of node pointers to move */ - unsigned u; /* Local index variable */ - - /* Start tracking the total number of records in middle node */ - middle_moved_nrec = new_middle_nrec; - - /* Copy node pointers from left node */ - move_nptrs = (*left_nrec-new_left_nrec); - HDmemcpy(&(middle_node_ptrs[0]),&(left_node_ptrs[new_left_nrec+1]),sizeof(H5B2_node_ptr_t)*move_nptrs); - - /* Count the number of records being moved from the left node */ - for(u=0, moved_nrec=0; u<move_nptrs; u++) - moved_nrec += middle_node_ptrs[u].all_nrec; - left_moved_nrec -= (moved_nrec+(*left_nrec-new_left_nrec)); - middle_moved_nrec += moved_nrec; - - /* Copy node pointers from right node */ - move_nptrs = (*right_nrec-new_right_nrec); - HDmemcpy(&(middle_node_ptrs[(*left_nrec-new_left_nrec)]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*move_nptrs); - - /* Count the number of records being moved from the right node */ - for(u=0, moved_nrec=0; u<move_nptrs; u++) - moved_nrec += right_node_ptrs[u].all_nrec; - right_moved_nrec -= (moved_nrec+(*right_nrec-new_right_nrec)); - middle_moved_nrec += moved_nrec; - - /* Slide node pointers in right node down */ - HDmemmove(&(right_node_ptrs[0]),&(right_node_ptrs[move_nptrs]),sizeof(H5B2_node_ptr_t)*(new_right_nrec+1)); - } /* end if */ - - } /* end block */ - - /* Update # of records in middle node */ - *middle_nrec=new_middle_nrec; - - /* Promote records to parent node from left & right nodes */ - HDmemcpy(H5B2_INT_NREC(internal,shared,idx),H5B2_NAT_NREC(left_native,shared,new_left_nrec),shared->type->nrec_size); - HDmemcpy(H5B2_INT_NREC(internal,shared,idx+1),H5B2_NAT_NREC(right_native,shared,(*right_nrec-(new_right_nrec+1))),shared->type->nrec_size); - - /* Update # of records in left node */ - *left_nrec = new_left_nrec; - - /* Slide records in right node to proper position */ - HDmemmove(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(right_native,shared,(*right_nrec-new_right_nrec)),shared->type->nrec_size*new_right_nrec); - - /* Update # of records in right node */ - *right_nrec = new_right_nrec; - } /* end block */ - - /* Update # of records in child nodes */ - internal->node_ptrs[idx].node_nrec = *left_nrec; - internal->node_ptrs[idx+1].node_nrec = *middle_nrec; - internal->node_ptrs[idx+2].node_nrec = *right_nrec; - - /* Update total # of records in child B-trees */ - if(depth>1) { - internal->node_ptrs[idx].all_nrec += left_moved_nrec; - internal->node_ptrs[idx+1].all_nrec = middle_moved_nrec; - internal->node_ptrs[idx+2].all_nrec += right_moved_nrec; - } /* end if */ - else { - internal->node_ptrs[idx].all_nrec = internal->node_ptrs[idx].node_nrec; - internal->node_ptrs[idx+1].all_nrec = internal->node_ptrs[idx+1].node_nrec; - internal->node_ptrs[idx+2].all_nrec = internal->node_ptrs[idx+2].node_nrec; - } /* end else */ - - - /* Update # of records in parent node */ - internal->nrec++; - - /* Mark parent as dirty */ - *internal_flags_ptr |= H5AC__DIRTIED_FLAG; - - /* Update grandparent info */ - curr_node_ptr->node_nrec++; - - /* Mark grandparent as dirty */ - *parent_cache_info_flags_ptr |= H5AC__DIRTIED_FLAG; - -#ifdef H5B2_DEBUG - H5B2_assert_internal((hsize_t)0,shared,internal); - if(depth>1) { - H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,left_child,middle_child); - H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,middle_child,left_child); - H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,middle_child,right_child); - H5B2_assert_internal2(internal->node_ptrs[idx+2].all_nrec,shared,right_child,middle_child); - } /* end if */ - else { - H5B2_assert_leaf2(shared,left_child,middle_child); - H5B2_assert_leaf2(shared,middle_child,right_child); - H5B2_assert_leaf(shared,right_child); - } /* end else */ -#endif /* H5B2_DEBUG */ - - /* Unlock child nodes (marked as dirty) */ - if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") - if (H5AC_unprotect(f, dxpl_id, child_class, middle_addr, middle_child, H5AC__DIRTIED_FLAG) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") - if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") - -done: - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5B2_split2 */ - - -/*------------------------------------------------------------------------- - * Function: H5B2_redistribute3 - * - * Purpose: Redistribute records between three nodes - * - * Return: Success: Non-negative - * - * Failure: Negative - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Feb 9 2005 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B2_redistribute3(H5F_t *f, hid_t dxpl_id, unsigned depth, - H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx) -{ - const H5AC_class_t *child_class; /* Pointer to child node's class info */ - haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */ - haddr_t middle_addr; /* Address of middle child node */ - void *left_child, *right_child; /* Pointers to child nodes */ - void *middle_child; /* Pointers to middle child node */ - unsigned *left_nrec, *right_nrec; /* Pointers to child # of records */ - unsigned *middle_nrec; /* Pointers to middle child # of records */ - uint8_t *left_native, *right_native; /* Pointers to childs' native records */ - uint8_t *middle_native; /* Pointers to middle child's native records */ - H5B2_shared_t *shared; /* B-tree's shared info */ - H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */ - H5B2_node_ptr_t *middle_node_ptrs=NULL;/* Pointers to childs' node pointer info */ - hssize_t left_moved_nrec=0, right_moved_nrec=0; /* Number of records moved, for internal split */ - hssize_t middle_moved_nrec=0; /* Number of records moved, for internal split */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5B2_redistribute3) - - HDassert(f); - HDassert(internal); - HDassert(internal_flags_ptr); - - /* Get the pointer to the shared B-tree info */ - shared=H5RC_GET_OBJ(internal->shared); - HDassert(shared); - - /* Check for the kind of B-tree node to redistribute */ - if(depth>1) { - H5B2_internal_t *left_internal; /* Pointer to left internal node */ - H5B2_internal_t *middle_internal; /* Pointer to middle internal node */ - H5B2_internal_t *right_internal; /* Pointer to right internal node */ - - /* Setup information for unlocking child nodes */ - child_class = H5AC_BT2_INT; - left_addr = internal->node_ptrs[idx-1].addr; - middle_addr = internal->node_ptrs[idx].addr; - right_addr = internal->node_ptrs[idx+1].addr; - - /* Lock B-tree child nodes */ - if (NULL == (left_internal = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx-1].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") - if (NULL == (middle_internal = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") - if (NULL == (right_internal = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") - - /* More setup for child nodes */ - left_child = left_internal; - middle_child = middle_internal; - right_child = right_internal; - left_nrec = &(left_internal->nrec); - middle_nrec = &(middle_internal->nrec); - right_nrec = &(right_internal->nrec); - left_native = left_internal->int_native; - middle_native = middle_internal->int_native; - right_native = right_internal->int_native; - left_node_ptrs = left_internal->node_ptrs; - middle_node_ptrs = middle_internal->node_ptrs; - right_node_ptrs = right_internal->node_ptrs; - } /* end if */ - else { - H5B2_leaf_t *left_leaf; /* Pointer to left leaf node */ - H5B2_leaf_t *middle_leaf; /* Pointer to middle leaf node */ - H5B2_leaf_t *right_leaf; /* Pointer to right leaf node */ - - /* Setup information for unlocking child nodes */ - child_class = H5AC_BT2_LEAF; - left_addr = internal->node_ptrs[idx-1].addr; - middle_addr = internal->node_ptrs[idx].addr; - right_addr = internal->node_ptrs[idx+1].addr; - - /* Lock B-tree child nodes */ - if (NULL == (left_leaf = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx-1].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") - if (NULL == (middle_leaf = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") - if (NULL == (right_leaf = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") - - /* More setup for child nodes */ - left_child = left_leaf; - middle_child = middle_leaf; - right_child = right_leaf; - left_nrec = &(left_leaf->nrec); - middle_nrec = &(middle_leaf->nrec); - right_nrec = &(right_leaf->nrec); - left_native = left_leaf->leaf_native; - middle_native = middle_leaf->leaf_native; - right_native = right_leaf->leaf_native; - } /* end else */ - - /* Redistribute records */ - { - /* Compute new # of records in each node */ - unsigned total_nrec = *left_nrec + *middle_nrec + *right_nrec + 2; - unsigned new_middle_nrec = (total_nrec-2)/3; - unsigned new_left_nrec = ((total_nrec-2)-new_middle_nrec)/2; - unsigned new_right_nrec = (total_nrec-2)-(new_left_nrec+new_middle_nrec); - unsigned curr_middle_nrec = *middle_nrec; - - /* Move records into left node */ - if(new_left_nrec>*left_nrec) { - unsigned moved_middle_nrec=0; /* Number of records moved into left node */ - - /* Move left parent record down to left node */ - HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec),H5B2_INT_NREC(internal,shared,idx-1),shared->type->nrec_size); - - /* Move records from middle node into left node */ - if((new_left_nrec-1)>*left_nrec) { - moved_middle_nrec = new_left_nrec-(*left_nrec+1); - HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec+1),H5B2_NAT_NREC(middle_native,shared,0),shared->type->nrec_size*moved_middle_nrec); - } /* end if */ - - /* Move record from middle node up to parent node */ - HDmemcpy(H5B2_INT_NREC(internal,shared,idx-1),H5B2_NAT_NREC(middle_native,shared,moved_middle_nrec),shared->type->nrec_size); - moved_middle_nrec++; - - /* Slide records in middle node down */ - HDmemmove(H5B2_NAT_NREC(middle_native,shared,0),H5B2_NAT_NREC(middle_native,shared,moved_middle_nrec),shared->type->nrec_size*(*middle_nrec-moved_middle_nrec)); - - /* Move node pointers also if this is an internal node */ - if(depth>1) { - hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */ - unsigned move_nptrs; /* Number of node pointers to move */ - unsigned u; /* Local index variable */ - - /* Move middle node pointers into left node */ - move_nptrs = new_left_nrec - *left_nrec; - HDmemcpy(&(left_node_ptrs[*left_nrec+1]),&(middle_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*move_nptrs); - - /* Count the number of records being moved into the left node */ - for(u=0, moved_nrec=0; u<move_nptrs; u++) - moved_nrec += middle_node_ptrs[u].all_nrec; - left_moved_nrec = moved_nrec+move_nptrs; - middle_moved_nrec -= moved_nrec+move_nptrs; - - /* Slide the node pointers in middle node down */ - HDmemmove(&(middle_node_ptrs[0]),&(middle_node_ptrs[move_nptrs]),sizeof(H5B2_node_ptr_t)*((*middle_nrec-move_nptrs)+1)); - } /* end if */ - - /* Update the current number of records in middle node */ - curr_middle_nrec -= moved_middle_nrec; - } /* end if */ - - /* Move records into right node */ - if(new_right_nrec>*right_nrec) { - unsigned right_nrec_move = new_right_nrec-*right_nrec; /* Number of records to move out of right node */ - - /* Slide records in right node up */ - HDmemmove(H5B2_NAT_NREC(right_native,shared,right_nrec_move),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(*right_nrec)); - - /* Move right parent record down to right node */ - HDmemcpy(H5B2_NAT_NREC(right_native,shared,right_nrec_move-1),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size); - - /* Move records from middle node into right node */ - if(right_nrec_move>1) - HDmemcpy(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(middle_native,shared,((curr_middle_nrec-right_nrec_move)+1)),shared->type->nrec_size*(right_nrec_move-1)); - - /* Move record from middle node up to parent node */ - HDmemcpy(H5B2_INT_NREC(internal,shared,idx),H5B2_NAT_NREC(middle_native,shared,(curr_middle_nrec-right_nrec_move)),shared->type->nrec_size); - - /* Move node pointers also if this is an internal node */ - if(depth>1) { - hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */ - unsigned u; /* Local index variable */ - - /* Slide the node pointers in right node up */ - HDmemmove(&(right_node_ptrs[right_nrec_move]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*(*right_nrec+1)); - - /* Move middle node pointers into right node */ - HDmemcpy(&(right_node_ptrs[0]),&(middle_node_ptrs[(curr_middle_nrec-right_nrec_move)+1]),sizeof(H5B2_node_ptr_t)*right_nrec_move); - - /* Count the number of records being moved into the right node */ - for(u=0, moved_nrec=0; u<right_nrec_move; u++) - moved_nrec += right_node_ptrs[u].all_nrec; - right_moved_nrec = moved_nrec+right_nrec_move; - middle_moved_nrec -= moved_nrec+right_nrec_move; - } /* end if */ - - /* Update the current number of records in middle node */ - curr_middle_nrec -= right_nrec_move; - } /* end if */ - - /* Move records out of left node */ - if(new_left_nrec<*left_nrec) { - unsigned left_nrec_move = *left_nrec-new_left_nrec; /* Number of records to move out of left node */ - - /* Slide middle records up */ - HDmemmove(H5B2_NAT_NREC(middle_native,shared,left_nrec_move),H5B2_NAT_NREC(middle_native,shared,0),shared->type->nrec_size*curr_middle_nrec); - - /* Move left parent record down to middle node */ - HDmemcpy(H5B2_NAT_NREC(middle_native,shared,left_nrec_move-1),H5B2_INT_NREC(internal,shared,idx-1),shared->type->nrec_size); - - /* Move left records to middle node */ - if(left_nrec_move>1) - HDmemmove(H5B2_NAT_NREC(middle_native,shared,0),H5B2_NAT_NREC(left_native,shared,new_left_nrec+1),shared->type->nrec_size*(left_nrec_move-1)); - - /* Move left parent record up from left node */ - HDmemcpy(H5B2_INT_NREC(internal,shared,idx-1),H5B2_NAT_NREC(left_native,shared,new_left_nrec),shared->type->nrec_size); - - /* Move node pointers also if this is an internal node */ - if(depth>1) { - hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */ - unsigned u; /* Local index variable */ - - /* Slide the node pointers in middle node up */ - HDmemmove(&(middle_node_ptrs[left_nrec_move]),&(middle_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*(curr_middle_nrec+1)); - - /* Move left node pointers into middle node */ - HDmemcpy(&(middle_node_ptrs[0]),&(left_node_ptrs[new_left_nrec+1]),sizeof(H5B2_node_ptr_t)*left_nrec_move); - - /* Count the number of records being moved into the left node */ - for(u=0, moved_nrec=0; u<left_nrec_move; u++) - moved_nrec += middle_node_ptrs[u].all_nrec; - left_moved_nrec -= moved_nrec+left_nrec_move; - middle_moved_nrec += moved_nrec+left_nrec_move; - } /* end if */ - - /* Update the current number of records in middle node */ - curr_middle_nrec += left_nrec_move; - } /* end if */ - - /* Move records out of right node */ - if(new_right_nrec<*right_nrec) { - unsigned right_nrec_move = *right_nrec-new_right_nrec; /* Number of records to move out of right node */ - - /* Move right parent record down to middle node */ - HDmemcpy(H5B2_NAT_NREC(middle_native,shared,curr_middle_nrec),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size); - - /* Move right records to middle node */ - HDmemmove(H5B2_NAT_NREC(middle_native,shared,(curr_middle_nrec+1)),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(right_nrec_move-1)); - - /* Move right parent record up from right node */ - HDmemcpy(H5B2_INT_NREC(internal,shared,idx),H5B2_NAT_NREC(right_native,shared,right_nrec_move-1),shared->type->nrec_size); - - /* Slide right records down */ - HDmemmove(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(right_native,shared,right_nrec_move),shared->type->nrec_size*new_right_nrec); - - /* Move node pointers also if this is an internal node */ - if(depth>1) { - hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */ - unsigned u; /* Local index variable */ - - /* Move right node pointers into middle node */ - HDmemcpy(&(middle_node_ptrs[curr_middle_nrec+1]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*right_nrec_move); - - /* Count the number of records being moved into the right node */ - for(u=0, moved_nrec=0; u<right_nrec_move; u++) - moved_nrec += right_node_ptrs[u].all_nrec; - right_moved_nrec -= moved_nrec+right_nrec_move; - middle_moved_nrec += moved_nrec+right_nrec_move; - - /* Slide the node pointers in right node down */ - HDmemmove(&(right_node_ptrs[0]),&(right_node_ptrs[right_nrec_move]),sizeof(H5B2_node_ptr_t)*(new_right_nrec+1)); - } /* end if */ - } /* end if */ - - /* Update # of records in nodes */ - *left_nrec = new_left_nrec; - *middle_nrec = new_middle_nrec; - *right_nrec = new_right_nrec; - } /* end block */ - - /* Update # of records in child nodes */ - internal->node_ptrs[idx-1].node_nrec = *left_nrec; - internal->node_ptrs[idx].node_nrec = *middle_nrec; - internal->node_ptrs[idx+1].node_nrec = *right_nrec; - - /* Update total # of records in child B-trees */ - if(depth>1) { - internal->node_ptrs[idx-1].all_nrec += left_moved_nrec; - internal->node_ptrs[idx].all_nrec += middle_moved_nrec; - internal->node_ptrs[idx+1].all_nrec += right_moved_nrec; - } /* end if */ - else { - internal->node_ptrs[idx-1].all_nrec = internal->node_ptrs[idx-1].node_nrec; - internal->node_ptrs[idx].all_nrec = internal->node_ptrs[idx].node_nrec; - internal->node_ptrs[idx+1].all_nrec = internal->node_ptrs[idx+1].node_nrec; - } /* end else */ - - /* Mark parent as dirty */ - *internal_flags_ptr |= H5AC__DIRTIED_FLAG; - -#ifdef QAK -{ - unsigned u; - - HDfprintf(stderr,"%s: Internal records:\n",FUNC); - for(u=0; u<internal->nrec; u++) { - HDfprintf(stderr,"%s: u=%u\n",FUNC,u); - (shared->type->debug)(stderr,f,dxpl_id,3,4,H5B2_INT_NREC(internal,shared,u),NULL); - } /* end for */ - - HDfprintf(stderr,"%s: Left Child records:\n",FUNC); - for(u=0; u<*left_nrec; u++) { - HDfprintf(stderr,"%s: u=%u\n",FUNC,u); - (shared->type->debug)(stderr,f,dxpl_id,3,4,H5B2_NAT_NREC(left_native,shared,u),NULL); - } /* end for */ - - HDfprintf(stderr,"%s: Middle Child records:\n",FUNC); - for(u=0; u<*middle_nrec; u++) { - HDfprintf(stderr,"%s: u=%u\n",FUNC,u); - (shared->type->debug)(stderr,f,dxpl_id,3,4,H5B2_NAT_NREC(middle_native,shared,u),NULL); - } /* end for */ - - HDfprintf(stderr,"%s: Right Child records:\n",FUNC); - for(u=0; u<*right_nrec; u++) { - HDfprintf(stderr,"%s: u=%u\n",FUNC,u); - (shared->type->debug)(stderr,f,dxpl_id,3,4,H5B2_NAT_NREC(right_native,shared,u),NULL); - } /* end for */ - - for(u=0; u<internal->nrec+1; u++) - HDfprintf(stderr,"%s: internal->node_ptrs[%u]=(%Hu/%u/%a)\n",FUNC,u,internal->node_ptrs[u].all_nrec,internal->node_ptrs[u].node_nrec,internal->node_ptrs[u].addr); - if(depth>1) { - for(u=0; u<*left_nrec+1; u++) - HDfprintf(stderr,"%s: left_node_ptr[%u]=(%Hu/%u/%a)\n",FUNC,u,left_node_ptrs[u].all_nrec,left_node_ptrs[u].node_nrec,left_node_ptrs[u].addr); - for(u=0; u<*middle_nrec+1; u++) - HDfprintf(stderr,"%s: middle_node_ptr[%u]=(%Hu/%u/%a)\n",FUNC,u,middle_node_ptrs[u].all_nrec,middle_node_ptrs[u].node_nrec,middle_node_ptrs[u].addr); - for(u=0; u<*right_nrec+1; u++) - HDfprintf(stderr,"%s: right_node_ptr[%u]=(%Hu/%u/%a)\n",FUNC,u,right_node_ptrs[u].all_nrec,right_node_ptrs[u].node_nrec,right_node_ptrs[u].addr); - } /* end if */ -} -#endif /* QAK */ -#ifdef H5B2_DEBUG - H5B2_assert_internal((hsize_t)0,shared,internal); - if(depth>1) { - H5B2_assert_internal2(internal->node_ptrs[idx-1].all_nrec,shared,left_child,middle_child); - H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,middle_child,left_child); - H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,middle_child,right_child); - H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,right_child,middle_child); - } /* end if */ - else { - H5B2_assert_leaf2(shared,left_child,middle_child); - H5B2_assert_leaf2(shared,middle_child,right_child); - H5B2_assert_leaf(shared,right_child); - } /* end else */ -#endif /* H5B2_DEBUG */ - - /* Unlock child nodes (marked as dirty) */ - if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") - if (H5AC_unprotect(f, dxpl_id, child_class, middle_addr, middle_child, H5AC__DIRTIED_FLAG) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") - if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") - -done: - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5B2_redistribute3 */ - - -/*------------------------------------------------------------------------- - * Function: H5B2_split3 - * - * Purpose: Perform a 3->4 node split - * - * Return: Success: Non-negative - * - * Failure: Negative - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Feb 10 2005 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B2_split3(H5F_t *f, hid_t dxpl_id, unsigned depth, - H5B2_node_ptr_t *curr_node_ptr, - unsigned *parent_cache_info_flags_ptr, H5B2_internal_t *internal, - unsigned *internal_flags_ptr, unsigned idx) -{ - const H5AC_class_t *child_class; /* Pointer to child node's class info */ - haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */ - haddr_t middle_addr; /* Address of middle child node */ - haddr_t new_addr; /* Address of new child node */ - void *left_child, *right_child; /* Pointers to left & right child nodes */ - void *middle_child; /* Pointer to middle child node */ - void *new_child; /* Pointer to new child node */ - unsigned *left_nrec, *right_nrec; /* Pointers to left & right child # of records */ - unsigned *middle_nrec; /* Pointer to middle child # of records */ - unsigned *new_nrec; /* Pointer to new child # of records */ - uint8_t *left_native, *right_native; /* Pointers to left & right children's native records */ - uint8_t *middle_native; /* Pointer to middle child's native records */ - uint8_t *new_native; /* Pointer to new child's native records */ - H5B2_shared_t *shared; /* B-tree's shared info */ - H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */ - H5B2_node_ptr_t *middle_node_ptrs=NULL;/* Pointers to childs' node pointer info */ - H5B2_node_ptr_t *new_node_ptrs=NULL;/* Pointers to childs' node pointer info */ - hssize_t left_moved_nrec=0, right_moved_nrec=0; /* Number of records moved, for internal split */ - hssize_t middle_moved_nrec=0; /* Number of records moved, for internal split */ - hsize_t new_moved_nrec=0; /* Number of records moved, for internal split */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5B2_split3) - - HDassert(f); - HDassert(internal); - - /* Get the pointer to the shared B-tree info */ - shared=H5RC_GET_OBJ(internal->shared); - HDassert(shared); - - /* Slide records in parent node up one space, to make room for promoted record */ - HDmemmove(H5B2_INT_NREC(internal,shared,idx+2),H5B2_INT_NREC(internal,shared,idx+1),shared->type->nrec_size*(internal->nrec-(idx+1))); - HDmemmove(&(internal->node_ptrs[idx+2]),&(internal->node_ptrs[idx+1]),sizeof(H5B2_node_ptr_t)*(internal->nrec-idx)); - - /* Check for the kind of B-tree node to split */ - if(depth>1) { - H5B2_internal_t *left_internal; /* Pointer to left internal node */ - H5B2_internal_t *right_internal; /* Pointer to right internal node */ - H5B2_internal_t *middle_internal; /* Pointer to middle internal node */ - H5B2_internal_t *new_internal; /* Pointer to new internal node */ - - /* Setup information for unlocking child nodes */ - child_class = H5AC_BT2_INT; - left_addr = internal->node_ptrs[idx-1].addr; - middle_addr = internal->node_ptrs[idx].addr; - right_addr = internal->node_ptrs[idx+2].addr; - - /* Lock left & right B-tree child nodes */ - if (NULL == (left_internal = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx-1].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") - if (NULL == (middle_internal = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") - if (NULL == (right_internal = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+2].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") - - /* Create new empty internal node */ - internal->node_ptrs[idx+1].all_nrec=internal->node_ptrs[idx+1].node_nrec=0; - if(H5B2_create_internal(f, dxpl_id, internal->shared, &(internal->node_ptrs[idx+1]))<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new internal node") - - /* Setup information for unlocking middle child node */ - new_addr = internal->node_ptrs[idx+1].addr; - - /* Lock "new" internal node */ - if (NULL == (new_internal = H5AC_protect(f, dxpl_id, child_class, new_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") - - /* More setup for accessing child node information */ - left_child = left_internal; - middle_child = middle_internal; - new_child = new_internal; - right_child = right_internal; - left_nrec = &(left_internal->nrec); - middle_nrec = &(middle_internal->nrec); - new_nrec = &(new_internal->nrec); - right_nrec = &(right_internal->nrec); - left_native = left_internal->int_native; - middle_native = middle_internal->int_native; - new_native = new_internal->int_native; - right_native = right_internal->int_native; - left_node_ptrs = left_internal->node_ptrs; - middle_node_ptrs = middle_internal->node_ptrs; - right_node_ptrs = right_internal->node_ptrs; - new_node_ptrs = new_internal->node_ptrs; - } /* end if */ - else { - H5B2_leaf_t *left_leaf; /* Pointer to left leaf node */ - H5B2_leaf_t *right_leaf; /* Pointer to right leaf node */ - H5B2_leaf_t *middle_leaf; /* Pointer to middle leaf node */ - H5B2_leaf_t *new_leaf; /* Pointer to new leaf node */ - - /* Setup information for unlocking child nodes */ - child_class = H5AC_BT2_LEAF; - left_addr = internal->node_ptrs[idx-1].addr; - middle_addr = internal->node_ptrs[idx].addr; - right_addr = internal->node_ptrs[idx+2].addr; - - /* Lock left & right B-tree child nodes */ - if (NULL == (left_leaf = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx-1].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") - if (NULL == (middle_leaf = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") - if (NULL == (right_leaf = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+2].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") - - /* Create new empty leaf node */ - internal->node_ptrs[idx+1].all_nrec=internal->node_ptrs[idx+1].node_nrec=0; - if(H5B2_create_leaf(f, dxpl_id, internal->shared, &(internal->node_ptrs[idx+1]))<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new leaf node") - - /* Setup information for unlocking middle child node */ - new_addr = internal->node_ptrs[idx+1].addr; - - /* Lock "new" leaf node */ - if (NULL == (new_leaf = H5AC_protect(f, dxpl_id, child_class, new_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") - - /* More setup for accessing child node information */ - left_child = left_leaf; - middle_child = middle_leaf; - new_child = new_leaf; - right_child = right_leaf; - left_nrec = &(left_leaf->nrec); - middle_nrec = &(middle_leaf->nrec); - new_nrec = &(new_leaf->nrec); - right_nrec = &(right_leaf->nrec); - left_native = left_leaf->leaf_native; - middle_native = middle_leaf->leaf_native; - new_native = new_leaf->leaf_native; - right_native = right_leaf->leaf_native; - } /* end else */ - - /* Redistribute records */ - { - /* Compute new # of records in each node */ - unsigned total_nrec = *left_nrec + *middle_nrec + *right_nrec + 2; - unsigned new_new_nrec = (total_nrec-3)/4; - unsigned new_middle_nrec = ((total_nrec-3)-new_new_nrec)/3; - unsigned new_left_nrec = ((total_nrec-3)-(new_middle_nrec+new_new_nrec))/2; - unsigned new_right_nrec = (total_nrec-3)-(new_left_nrec+new_middle_nrec+new_new_nrec); - - /* Partially fill new node from right node */ - { - unsigned right_nrec_move = *right_nrec-new_right_nrec; - - /* Move right record down from parent into new node */ - HDmemcpy(H5B2_NAT_NREC(new_native,shared,(new_new_nrec-right_nrec_move)),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size); - - /* Move records from right node to new node */ - HDmemcpy(H5B2_NAT_NREC(new_native,shared,((new_new_nrec-right_nrec_move)+1)),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(right_nrec_move-1)); - - /* Move record from right node up to parent node */ - HDmemcpy(H5B2_INT_NREC(internal,shared,idx+1),H5B2_NAT_NREC(right_native,shared,(right_nrec_move-1)),shared->type->nrec_size); - - /* Slide records in right node down */ - HDmemmove(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(right_native,shared,right_nrec_move),shared->type->nrec_size*new_right_nrec); - - /* Move node pointers also if this is an internal node */ - if(depth>1) { - hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */ - unsigned u; /* Local index variable */ - - /* Move right node pointers into new node */ - HDmemcpy(&(new_node_ptrs[(new_new_nrec-right_nrec_move)+1]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*right_nrec_move); - - /* Count the number of records being moved into the new node */ - for(u=0, moved_nrec=0; u<right_nrec_move; u++) - moved_nrec += right_node_ptrs[u].all_nrec; - right_moved_nrec -= (moved_nrec+right_nrec_move); - new_moved_nrec += (moved_nrec+right_nrec_move); - - /* Slide the node pointers in right node down */ - HDmemmove(&(right_node_ptrs[0]),&(right_node_ptrs[right_nrec_move]),sizeof(H5B2_node_ptr_t)*(new_right_nrec+1)); - } /* end if */ - } /* end block */ - - /* Finish filling new node from middle node */ - { - unsigned new_nrec_move = new_new_nrec-(*right_nrec-new_right_nrec); - - /* Move records from middle node to new node */ - HDmemcpy(H5B2_NAT_NREC(new_native,shared,0),H5B2_NAT_NREC(middle_native,shared,(*middle_nrec-new_nrec_move)),shared->type->nrec_size*new_nrec_move); - - /* Move record from middle node up to parent node */ - HDmemcpy(H5B2_INT_NREC(internal,shared,idx),H5B2_NAT_NREC(middle_native,shared,((*middle_nrec-new_nrec_move)-1)),shared->type->nrec_size); - - /* Slide records in middle node up */ - HDmemmove(H5B2_NAT_NREC(middle_native,shared,(new_middle_nrec-((*middle_nrec-new_nrec_move)-1))),H5B2_NAT_NREC(middle_native,shared,0),shared->type->nrec_size*(*middle_nrec-(new_nrec_move+1))); - - /* Move node pointers also if this is an internal node */ - if(depth>1) { - hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */ - unsigned u; /* Local index variable */ - - /* Move middle node pointers into new node */ - HDmemcpy(&(new_node_ptrs[0]),&(middle_node_ptrs[(*middle_nrec-new_nrec_move)]),sizeof(H5B2_node_ptr_t)*(new_nrec_move+1)); - - /* Count the number of records being moved into the new node */ - for(u=0, moved_nrec=0; u<new_nrec_move+1; u++) - moved_nrec += new_node_ptrs[u].all_nrec; - middle_moved_nrec -= (moved_nrec+new_nrec_move+1); - new_moved_nrec += (moved_nrec+new_nrec_move); - - /* Slide the node pointers in middle node up */ - HDmemmove(&(middle_node_ptrs[(new_middle_nrec-((*middle_nrec-new_nrec_move)-1))]),&(middle_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*(*middle_nrec-new_nrec_move)); - } /* end if */ - } /* end block */ - - /* Fill middle node from left node */ - { - unsigned left_nrec_move = *left_nrec - new_left_nrec; - - /* Move record from parent node down to middle node */ - HDmemcpy(H5B2_NAT_NREC(middle_native,shared,(left_nrec_move-1)),H5B2_INT_NREC(internal,shared,idx-1),shared->type->nrec_size); - - /* Move records from left node to middle node */ - HDmemcpy(H5B2_NAT_NREC(middle_native,shared,0),H5B2_NAT_NREC(left_native,shared,(new_left_nrec+1)),shared->type->nrec_size*(left_nrec_move-1)); - - /* Move node pointers also if this is an internal node */ - if(depth>1) { - hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */ - unsigned u; /* Local index variable */ - - /* Move left node pointers into middle node */ - HDmemcpy(&(middle_node_ptrs[0]),&(left_node_ptrs[new_left_nrec+1]),sizeof(H5B2_node_ptr_t)*left_nrec_move); - - /* Count the number of records being moved into the middle node */ - for(u=0, moved_nrec=0; u<left_nrec_move; u++) - moved_nrec += middle_node_ptrs[u].all_nrec; - left_moved_nrec -= (moved_nrec+left_nrec_move); - middle_moved_nrec += (moved_nrec+left_nrec_move); - } /* end if */ - } - - /* Move record from left node to parent node */ - HDmemcpy(H5B2_INT_NREC(internal,shared,idx-1),H5B2_NAT_NREC(left_native,shared,new_left_nrec),shared->type->nrec_size); - - /* Update # of records in nodes */ - *left_nrec = new_left_nrec; - *middle_nrec = new_middle_nrec; - *new_nrec = new_new_nrec; - *right_nrec = new_right_nrec; - } /* end block */ - - /* Update # of records in child nodes */ - internal->node_ptrs[idx-1].node_nrec = *left_nrec; - internal->node_ptrs[idx].node_nrec = *middle_nrec; - internal->node_ptrs[idx+1].node_nrec = *new_nrec; - internal->node_ptrs[idx+2].node_nrec = *right_nrec; - - /* Update total # of records in child B-trees */ - if(depth>1) { - internal->node_ptrs[idx-1].all_nrec += left_moved_nrec; - internal->node_ptrs[idx].all_nrec += middle_moved_nrec; - internal->node_ptrs[idx+1].all_nrec = new_moved_nrec; - internal->node_ptrs[idx+2].all_nrec += right_moved_nrec; - } /* end if */ - else { - internal->node_ptrs[idx-1].all_nrec = internal->node_ptrs[idx-1].node_nrec; - internal->node_ptrs[idx].all_nrec = internal->node_ptrs[idx].node_nrec; - internal->node_ptrs[idx+1].all_nrec = internal->node_ptrs[idx+1].node_nrec; - internal->node_ptrs[idx+2].all_nrec = internal->node_ptrs[idx+2].node_nrec; - } /* end else */ - - /* Update # of records in parent node */ - internal->nrec++; - - /* Mark parent as dirty */ - *internal_flags_ptr |= H5AC__DIRTIED_FLAG; - - /* Update grandparent info */ - curr_node_ptr->node_nrec++; - - /* Mark grandparent as dirty */ - *parent_cache_info_flags_ptr |= H5AC__DIRTIED_FLAG; - -#ifdef H5B2_DEBUG - H5B2_assert_internal((hsize_t)0,shared,internal); - if(depth>1) { - H5B2_assert_internal2(internal->node_ptrs[idx-1].all_nrec,shared,left_child,middle_child); - H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,middle_child,left_child); - H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,middle_child,new_child); - H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,new_child,middle_child); - H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,new_child,right_child); - H5B2_assert_internal2(internal->node_ptrs[idx+2].all_nrec,shared,right_child,new_child); - } /* end if */ - else { - H5B2_assert_leaf2(shared,left_child,middle_child); - H5B2_assert_leaf2(shared,middle_child,new_child); - H5B2_assert_leaf2(shared,new_child,right_child); - H5B2_assert_leaf(shared,right_child); - } /* end else */ -#endif /* H5B2_DEBUG */ - - /* Unlock child nodes (mark as dirty) */ - if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") - if (H5AC_unprotect(f, dxpl_id, child_class, middle_addr, middle_child, H5AC__DIRTIED_FLAG) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") - if (H5AC_unprotect(f, dxpl_id, child_class, new_addr, new_child, H5AC__DIRTIED_FLAG) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") - if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") - -done: - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5B2_split3 */ - - -/*------------------------------------------------------------------------- - * Function: H5B2_merge2 - * - * Purpose: Perform a 2->1 node merge - * - * Return: Success: Non-negative - * - * Failure: Negative - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 4 2005 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B2_merge2(H5F_t *f, hid_t dxpl_id, unsigned depth, - H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags_ptr, - H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx) -{ - const H5AC_class_t *child_class; /* Pointer to child node's class info */ - haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */ - void *left_child, *right_child; /* Pointers to left & right child nodes */ - unsigned *left_nrec, *right_nrec; /* Pointers to left & right child # of records */ - uint8_t *left_native, *right_native; /* Pointers to left & right children's native records */ - H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */ - H5B2_shared_t *shared; /* B-tree's shared info */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5B2_merge2) - - HDassert(f); - HDassert(curr_node_ptr); - HDassert(parent_cache_info_flags_ptr); - HDassert(internal); - HDassert(internal_flags_ptr); - - /* Get the pointer to the shared B-tree info */ - shared=H5RC_GET_OBJ(internal->shared); - HDassert(shared); - - /* Check for the kind of B-tree node to split */ - if(depth>1) { - H5B2_internal_t *left_internal; /* Pointer to left internal node */ - H5B2_internal_t *right_internal; /* Pointer to right internal node */ - - /* Setup information for unlocking child nodes */ - child_class = H5AC_BT2_INT; - left_addr = internal->node_ptrs[idx].addr; - right_addr = internal->node_ptrs[idx+1].addr; - - /* Lock left & right B-tree child nodes */ - if (NULL == (left_internal = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") - if (NULL == (right_internal = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") - - /* More setup for accessing child node information */ - left_child = left_internal; - right_child = right_internal; - left_nrec = &(left_internal->nrec); - right_nrec = &(right_internal->nrec); - left_native = left_internal->int_native; - right_native = right_internal->int_native; - left_node_ptrs = left_internal->node_ptrs; - right_node_ptrs = right_internal->node_ptrs; - } /* end if */ - else { - H5B2_leaf_t *left_leaf; /* Pointer to left leaf node */ - H5B2_leaf_t *right_leaf; /* Pointer to right leaf node */ - - /* Setup information for unlocking child nodes */ - child_class = H5AC_BT2_LEAF; - left_addr = internal->node_ptrs[idx].addr; - right_addr = internal->node_ptrs[idx+1].addr; - - /* Lock left & right B-tree child nodes */ - if (NULL == (left_leaf = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") - if (NULL == (right_leaf = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") - - /* More setup for accessing child node information */ - left_child = left_leaf; - right_child = right_leaf; - left_nrec = &(left_leaf->nrec); - right_nrec = &(right_leaf->nrec); - left_native = left_leaf->leaf_native; - right_native = right_leaf->leaf_native; - } /* end else */ - - /* Redistribute records into left node */ - { - /* Copy record from parent node to proper location */ - HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size); - - /* Copy records from right node to left node */ - HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec+1),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(*right_nrec)); - - /* Copy node pointers from right node into left node */ - if(depth>1) - HDmemcpy(&(left_node_ptrs[*left_nrec+1]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*(*right_nrec+1)); - - /* Update # of records in left node */ - *left_nrec += *right_nrec + 1; - } /* end block */ - - /* Update # of records in child nodes */ - internal->node_ptrs[idx].node_nrec = *left_nrec; - - /* Update total # of records in child B-trees */ - internal->node_ptrs[idx].all_nrec += internal->node_ptrs[idx+1].all_nrec + 1; - - /* Slide records in parent node down, to eliminate demoted record */ - if((idx+1) < internal->nrec) { - HDmemmove(H5B2_INT_NREC(internal,shared,idx),H5B2_INT_NREC(internal,shared,idx+1),shared->type->nrec_size*(internal->nrec-(idx+1))); - HDmemmove(&(internal->node_ptrs[idx+1]),&(internal->node_ptrs[idx+2]),sizeof(H5B2_node_ptr_t)*(internal->nrec-(idx+1))); - } /* end if */ - - /* Update # of records in parent node */ - internal->nrec--; - - /* Mark parent as dirty */ - *internal_flags_ptr |= H5AC__DIRTIED_FLAG; - - /* Update grandparent info */ - curr_node_ptr->node_nrec--; - - /* Mark grandparent as dirty */ - *parent_cache_info_flags_ptr |= H5AC__DIRTIED_FLAG; - -#ifdef H5B2_DEBUG - H5B2_assert_internal((hsize_t)0,shared,internal); - if(depth>1) { - H5B2_assert_internal(internal->node_ptrs[idx].all_nrec,shared,left_child); - } /* end if */ - else { - H5B2_assert_leaf(shared,left_child); - } /* end else */ -#endif /* H5B2_DEBUG */ - - /* Unlock left node (marked as dirty) */ - if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") - - /* Delete right node & remove from cache (marked as dirty) */ - if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, right_addr, (hsize_t)shared->node_size)<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node") - if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") - -done: - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5B2_merge2 */ - - -/*------------------------------------------------------------------------- - * Function: H5B2_merge3 - * - * Purpose: Perform a 3->2 node merge - * - * Return: Success: Non-negative - * - * Failure: Negative - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 4 2005 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B2_merge3(H5F_t *f, hid_t dxpl_id, unsigned depth, - H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags_ptr, - H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx) -{ - const H5AC_class_t *child_class; /* Pointer to child node's class info */ - haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */ - haddr_t middle_addr; /* Address of middle child node */ - void *left_child, *right_child; /* Pointers to left & right child nodes */ - void *middle_child; /* Pointer to middle child node */ - unsigned *left_nrec, *right_nrec; /* Pointers to left & right child # of records */ - unsigned *middle_nrec; /* Pointer to middle child # of records */ - uint8_t *left_native, *right_native; /* Pointers to left & right children's native records */ - uint8_t *middle_native; /* Pointer to middle child's native records */ - H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */ - H5B2_node_ptr_t *middle_node_ptrs=NULL;/* Pointer to child's node pointer info */ - H5B2_shared_t *shared; /* B-tree's shared info */ - hsize_t middle_moved_nrec; /* Number of records moved, for internal split */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5B2_merge3) - - HDassert(f); - HDassert(curr_node_ptr); - HDassert(parent_cache_info_flags_ptr); - HDassert(internal); - HDassert(internal_flags_ptr); - - /* Get the pointer to the shared B-tree info */ - shared=H5RC_GET_OBJ(internal->shared); - HDassert(shared); - - /* Check for the kind of B-tree node to split */ - if(depth>1) { - H5B2_internal_t *left_internal; /* Pointer to left internal node */ - H5B2_internal_t *middle_internal; /* Pointer to middle internal node */ - H5B2_internal_t *right_internal; /* Pointer to right internal node */ - - /* Setup information for unlocking child nodes */ - child_class = H5AC_BT2_INT; - left_addr = internal->node_ptrs[idx-1].addr; - middle_addr = internal->node_ptrs[idx].addr; - right_addr = internal->node_ptrs[idx+1].addr; - - /* Lock B-tree child nodes */ - if (NULL == (left_internal = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx-1].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") - if (NULL == (middle_internal = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") - if (NULL == (right_internal = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") - - /* More setup for accessing child node information */ - left_child = left_internal; - middle_child = middle_internal; - right_child = right_internal; - left_nrec = &(left_internal->nrec); - middle_nrec = &(middle_internal->nrec); - right_nrec = &(right_internal->nrec); - left_native = left_internal->int_native; - middle_native = middle_internal->int_native; - right_native = right_internal->int_native; - left_node_ptrs = left_internal->node_ptrs; - middle_node_ptrs = middle_internal->node_ptrs; - right_node_ptrs = right_internal->node_ptrs; - } /* end if */ - else { - H5B2_leaf_t *left_leaf; /* Pointer to left leaf node */ - H5B2_leaf_t *middle_leaf; /* Pointer to middle leaf node */ - H5B2_leaf_t *right_leaf; /* Pointer to right leaf node */ - - /* Setup information for unlocking child nodes */ - child_class = H5AC_BT2_LEAF; - left_addr = internal->node_ptrs[idx-1].addr; - middle_addr = internal->node_ptrs[idx].addr; - right_addr = internal->node_ptrs[idx+1].addr; - - /* Lock B-tree child nodes */ - if (NULL == (left_leaf = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx-1].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") - if (NULL == (middle_leaf = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") - if (NULL == (right_leaf = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") - - /* More setup for accessing child node information */ - left_child = left_leaf; - middle_child = middle_leaf; - right_child = right_leaf; - left_nrec = &(left_leaf->nrec); - middle_nrec = &(middle_leaf->nrec); - right_nrec = &(right_leaf->nrec); - left_native = left_leaf->leaf_native; - middle_native = middle_leaf->leaf_native; - right_native = right_leaf->leaf_native; - } /* end else */ - - /* Redistribute records into left node */ - { - unsigned total_nrec = *left_nrec + *middle_nrec + *right_nrec + 2; - unsigned middle_nrec_move = ((total_nrec - 1) / 2) - *left_nrec; - - /* Set the base number of records moved from middle node */ - middle_moved_nrec = middle_nrec_move; - - /* Copy record from parent node to proper location in left node */ - HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec),H5B2_INT_NREC(internal,shared,idx-1),shared->type->nrec_size); - - /* Copy records from middle node to left node */ - HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec+1),H5B2_NAT_NREC(middle_native,shared,0),shared->type->nrec_size*(middle_nrec_move-1)); - - /* Copy record from middle node to proper location in parent node */ - HDmemcpy(H5B2_INT_NREC(internal,shared,idx-1),H5B2_NAT_NREC(middle_native,shared,(middle_nrec_move-1)),shared->type->nrec_size); - - /* Slide records in middle node down */ - HDmemmove(H5B2_NAT_NREC(middle_native,shared,0),H5B2_NAT_NREC(middle_native,shared,middle_nrec_move),shared->type->nrec_size*(*middle_nrec-middle_nrec_move)); - - /* Move node pointers also if this is an internal node */ - if(depth>1) { - unsigned u; /* Local index variable */ - - /* Copy node pointers from middle node into left node */ - HDmemcpy(&(left_node_ptrs[*left_nrec+1]),&(middle_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*middle_nrec_move); - - /* Count the number of records being moved into the left node */ - for(u=0; u<middle_nrec_move; u++) - middle_moved_nrec += middle_node_ptrs[u].all_nrec; - - /* Slide the node pointers in right node down */ - HDmemmove(&(middle_node_ptrs[0]),&(middle_node_ptrs[middle_nrec_move]),sizeof(H5B2_node_ptr_t)*((*middle_nrec+1)-middle_nrec_move)); - } /* end if */ - - /* Update # of records in left & middle nodes */ - *left_nrec += middle_nrec_move; - *middle_nrec -= middle_nrec_move; - } /* end block */ - - /* Redistribute records into middle node */ - { - /* Copy record from parent node to proper location in middle node */ - HDmemcpy(H5B2_NAT_NREC(middle_native,shared,*middle_nrec),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size); - - /* Copy records from right node to middle node */ - HDmemcpy(H5B2_NAT_NREC(middle_native,shared,*middle_nrec+1),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(*right_nrec)); - - /* Move node pointers also if this is an internal node */ - if(depth>1) - /* Copy node pointers from middle node into left node */ - HDmemcpy(&(middle_node_ptrs[*middle_nrec+1]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*(*right_nrec+1)); - - /* Update # of records in middle node */ - *middle_nrec += *right_nrec + 1; - } /* end block */ - - /* Update # of records in child nodes */ - internal->node_ptrs[idx-1].node_nrec = *left_nrec; - internal->node_ptrs[idx].node_nrec = *middle_nrec; - - /* Update total # of records in child B-trees */ - internal->node_ptrs[idx-1].all_nrec += middle_moved_nrec; - internal->node_ptrs[idx].all_nrec += (internal->node_ptrs[idx+1].all_nrec + 1) - middle_moved_nrec; - - /* Slide records in parent node down, to eliminate demoted record */ - if((idx+1) < internal->nrec) { - HDmemmove(H5B2_INT_NREC(internal,shared,idx),H5B2_INT_NREC(internal,shared,idx+1),shared->type->nrec_size*(internal->nrec-(idx+1))); - HDmemmove(&(internal->node_ptrs[idx+1]),&(internal->node_ptrs[idx+2]),sizeof(H5B2_node_ptr_t)*(internal->nrec-(idx+1))); - } /* end if */ - - /* Update # of records in parent node */ - internal->nrec--; - - /* Mark parent as dirty */ - *internal_flags_ptr |= H5AC__DIRTIED_FLAG; - - /* Update grandparent info */ - curr_node_ptr->node_nrec--; - - /* Mark grandparent as dirty */ - *parent_cache_info_flags_ptr |= H5AC__DIRTIED_FLAG; - -#ifdef H5B2_DEBUG - H5B2_assert_internal((hsize_t)0,shared,internal); - if(depth>1) { - H5B2_assert_internal2(internal->node_ptrs[idx-1].all_nrec,shared,left_child,middle_child); - H5B2_assert_internal(internal->node_ptrs[idx].all_nrec,shared,middle_child); - } /* end if */ - else { - H5B2_assert_leaf2(shared,left_child,middle_child); - H5B2_assert_leaf(shared,middle_child); - } /* end else */ -#endif /* H5B2_DEBUG */ - - /* Unlock left & middle nodes (marked as dirty) */ - if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") - if (H5AC_unprotect(f, dxpl_id, child_class, middle_addr, middle_child, H5AC__DIRTIED_FLAG) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") - - /* Delete right node & remove from cache (marked as dirty) */ - if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, right_addr, (hsize_t)shared->node_size)<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node") - if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") - -done: - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5B2_merge3 */ - - -/*------------------------------------------------------------------------- - * Function: H5B2_swap_leaf - * - * Purpose: Swap a record in a node with a record in a leaf node - * - * Return: Success: Non-negative - * - * Failure: Negative - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 4 2005 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B2_swap_leaf(H5F_t *f, hid_t dxpl_id, unsigned depth, - H5B2_internal_t *internal, unsigned *internal_flags_ptr, - unsigned idx, void *swap_loc) -{ - const H5AC_class_t *child_class; /* Pointer to child node's class info */ - haddr_t child_addr; /* Address of child node */ - void *child; /* Pointer to child node */ - uint8_t *child_native; /* Pointer to child's native records */ - H5B2_shared_t *shared; /* B-tree's shared info */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5B2_swap_leaf) - - HDassert(f); - HDassert(internal); - HDassert(internal_flags_ptr); - HDassert(idx <= internal->nrec); - - /* Get the pointer to the shared B-tree info */ - shared=H5RC_GET_OBJ(internal->shared); - HDassert(shared); - - /* Check for the kind of B-tree node to swap */ - if(depth>1) { - H5B2_internal_t *child_internal; /* Pointer to internal node */ - - /* Setup information for unlocking child node */ - child_class = H5AC_BT2_INT; - child_addr = internal->node_ptrs[idx].addr; - - /* Lock B-tree child nodes */ - if (NULL == (child_internal = H5AC_protect(f, dxpl_id, child_class, child_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") - - /* More setup for accessing child node information */ - child = child_internal; - child_native = child_internal->int_native; - } /* end if */ - else { - H5B2_leaf_t *child_leaf; /* Pointer to leaf node */ - - /* Setup information for unlocking child nodes */ - child_class = H5AC_BT2_LEAF; - child_addr = internal->node_ptrs[idx].addr; - - /* Lock B-tree child node */ - if (NULL == (child_leaf = H5AC_protect(f, dxpl_id, child_class, child_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") - - /* More setup for accessing child node information */ - child = child_leaf; - child_native = child_leaf->leaf_native; - } /* end else */ - - /* Swap records (use disk page as temporary buffer) */ - HDmemcpy(shared->page, H5B2_NAT_NREC(child_native,shared,0), shared->type->nrec_size); - HDmemcpy(H5B2_NAT_NREC(child_native,shared,0), swap_loc, shared->type->nrec_size); - HDmemcpy(swap_loc, shared->page, shared->type->nrec_size); - - /* Mark parent as dirty */ - *internal_flags_ptr |= H5AC__DIRTIED_FLAG; - -#ifdef H5B2_DEBUG - H5B2_assert_internal((hsize_t)0,shared,internal); - if(depth>1) - H5B2_assert_internal(internal->node_ptrs[idx].all_nrec,shared,child); - else - H5B2_assert_leaf(shared,child); -#endif /* H5B2_DEBUG */ - - /* Unlock child node */ - if (H5AC_unprotect(f, dxpl_id, child_class, child_addr, child, H5AC__DIRTIED_FLAG) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") - -done: - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5B2_swap_leaf */ - - -/*------------------------------------------------------------------------- - * Function: H5B2_insert_leaf - * - * Purpose: Adds a new record to a B-tree leaf node. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 3 2005 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B2_insert_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, - H5B2_node_ptr_t *curr_node_ptr, void *udata) -{ - H5B2_leaf_t *leaf; /* Pointer to leaf node */ - H5B2_shared_t *shared; /* Pointer to B-tree's shared information */ - int cmp; /* Comparison value of records */ - unsigned idx; /* Location of record which matches key */ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI_NOINIT(H5B2_insert_leaf) - - /* Check arguments. */ - HDassert(f); - HDassert(bt2_shared); - HDassert(curr_node_ptr); - HDassert(H5F_addr_defined(curr_node_ptr->addr)); - - /* Lock current B-tree node */ - if (NULL == (leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr->addr, &(curr_node_ptr->node_nrec), bt2_shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") - - /* Get the pointer to the shared B-tree info */ - shared=H5RC_GET_OBJ(bt2_shared); - HDassert(shared); - - /* Must have a leaf node with enough space to insert a record now */ - HDassert(curr_node_ptr->node_nrec < shared->split_leaf_nrec); - - /* Sanity check number of records */ - HDassert(curr_node_ptr->all_nrec == curr_node_ptr->node_nrec); - HDassert(leaf->nrec == curr_node_ptr->node_nrec); - - /* Check for inserting into empty leaf */ - if(leaf->nrec==0) - idx=0; - else { - /* Find correct location to insert this record */ - if((cmp = H5B2_locate_record(shared->type,leaf->nrec,shared->nat_off,leaf->leaf_native,udata,&idx)) == 0) - HGOTO_ERROR(H5E_BTREE, H5E_EXISTS, FAIL, "record is already in B-tree") - if(cmp > 0) - idx++; - - /* Make room for new record */ - if(idx<leaf->nrec) - HDmemmove(H5B2_LEAF_NREC(leaf,shared,idx+1),H5B2_LEAF_NREC(leaf,shared,idx),shared->type->nrec_size*(leaf->nrec-idx)); - } /* end else */ - - /* Make callback to store record in native form */ - if((shared->type->store)(H5B2_LEAF_NREC(leaf,shared,idx),udata)<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into leaf node") - - /* Update record count for node pointer to current node */ - curr_node_ptr->all_nrec++; - curr_node_ptr->node_nrec++; - - /* Update record count for current node */ - leaf->nrec++; - -done: - /* Release the B-tree leaf node (marked as dirty) */ - if (leaf && H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr->addr, leaf, H5AC__DIRTIED_FLAG) < 0) - HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release leaf B-tree node") - - FUNC_LEAVE_NOAPI(ret_value) -} /* H5B2_insert_leaf() */ - - -/*------------------------------------------------------------------------- - * Function: H5B2_insert_internal - * - * Purpose: Adds a new record to a B-tree node. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 2 2005 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B2_insert_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, - unsigned depth, unsigned *parent_cache_info_flags_ptr, - H5B2_node_ptr_t *curr_node_ptr, void *udata) -{ - H5B2_internal_t *internal; /* Pointer to internal node */ - unsigned internal_flags = H5AC__NO_FLAGS_SET; - H5B2_shared_t *shared; /* Pointer to B-tree's shared information */ - unsigned idx; /* Location of record which matches key */ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI_NOINIT(H5B2_insert_internal) - - /* Check arguments. */ - HDassert(f); - HDassert(bt2_shared); - HDassert(depth>0); - HDassert(parent_cache_info_flags_ptr); - HDassert(curr_node_ptr); - HDassert(H5F_addr_defined(curr_node_ptr->addr)); - - /* Lock current B-tree node */ - if (NULL == (internal = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr->addr, &(curr_node_ptr->node_nrec), bt2_shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") - - /* Get the pointer to the shared B-tree info */ - shared=H5RC_GET_OBJ(bt2_shared); - HDassert(shared); - -/* Split or redistribute child node pointers, if necessary */ - { - int cmp; /* Comparison value of records */ - unsigned retries; /* Number of times to attempt redistribution */ - size_t split_nrec; /* Number of records to split node at */ - - /* Locate node pointer for child */ - if((cmp=H5B2_locate_record(shared->type,internal->nrec,shared->nat_off,internal->int_native,udata,&idx)) == 0) - HGOTO_ERROR(H5E_BTREE, H5E_EXISTS, FAIL, "record is already in B-tree") - if(cmp>0) - idx++; - - /* Set the number of redistribution retries */ - /* This takes care of the case where a B-tree node needs to be - * redistributed, but redistributing the node causes the index - * for insertion to move to another node, which also needs to be - * redistributed. Now, we loop trying to redistribute and then - * eventually force a split */ - retries = 2; - - /* Determine the correct number of records to split at */ - if(depth==1) - split_nrec = shared->split_leaf_nrec; - else - split_nrec = shared->split_int_nrec; - - /* Preemptively split/redistribute a node we will enter */ - while(internal->node_ptrs[idx].node_nrec == split_nrec) { - /* Attempt to redistribute records among children */ - if(idx==0) { /* Left-most child */ - if(retries>0 && (internal->node_ptrs[idx+1].node_nrec < split_nrec)) { - if(H5B2_redistribute2(f,dxpl_id,depth,internal,idx)<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records") - } /* end if */ - else { - if(H5B2_split2(f,dxpl_id,depth,curr_node_ptr, - parent_cache_info_flags_ptr, internal,&internal_flags,idx)<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to split child node") - } /* end else */ - } /* end if */ - else if(idx==internal->nrec) { /* Right-most child */ - if(retries>0 && (internal->node_ptrs[idx-1].node_nrec < split_nrec)) { - if(H5B2_redistribute2(f,dxpl_id,depth,internal,(idx-1))<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records") - } /* end if */ - else { - if(H5B2_split2(f,dxpl_id,depth,curr_node_ptr, - parent_cache_info_flags_ptr, internal,&internal_flags,(idx-1))<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to split child node") - } /* end else */ - } /* end if */ - else { /* Middle child */ - if(retries>0 && ((internal->node_ptrs[idx+1].node_nrec < split_nrec) || - (internal->node_ptrs[idx-1].node_nrec < split_nrec))) { - if(H5B2_redistribute3(f,dxpl_id,depth,internal,&internal_flags,idx)<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records") - } /* end if */ - else { - if(H5B2_split3(f,dxpl_id,depth,curr_node_ptr, - parent_cache_info_flags_ptr, internal,&internal_flags,idx)<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to split child node") - } /* end else */ - } /* end else */ - - /* Locate node pointer for child (after split/redistribute) */ -/* Actually, this can be easily updated (for 2-node redistrib.) and shouldn't require re-searching */ - if((cmp=H5B2_locate_record(shared->type,internal->nrec,shared->nat_off,internal->int_native,udata,&idx)) == 0) - HGOTO_ERROR(H5E_BTREE, H5E_EXISTS, FAIL, "record is already in B-tree") - if(cmp > 0) - idx++; - - /* Decrement the number of redistribution retries left */ - retries--; - } /* end while */ - } /* end block */ - - /* Attempt to insert node */ - if(depth>1) { - if(H5B2_insert_internal(f, dxpl_id, bt2_shared, depth-1, &internal_flags, &internal->node_ptrs[idx], 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,&internal->node_ptrs[idx],udata)<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into B-tree leaf node") - } /* end else */ - - /* Update record count for node pointer to current node */ - curr_node_ptr->all_nrec++; - - /* Mark node as dirty */ - internal_flags |= H5AC__DIRTIED_FLAG; - -done: - /* Release the B-tree internal node */ - if (internal && H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr->addr, internal, internal_flags) < 0) - HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release internal B-tree node") - - FUNC_LEAVE_NOAPI(ret_value) -} /* H5B2_insert_internal() */ - - -/*------------------------------------------------------------------------- * Function: H5B2_insert * * Purpose: Adds a new record to the B-tree. @@ -2578,251 +222,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5B2_create_leaf - * - * Purpose: Creates empty leaf node of a B-tree and update node pointer - * to point to it. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Feb 2 2005 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B2_create_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, H5B2_node_ptr_t *node_ptr) -{ - H5B2_leaf_t *leaf=NULL; /* Pointer to new leaf node created */ - H5B2_shared_t *shared; /* Shared B-tree information */ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI(H5B2_create_leaf, FAIL) - - /* Check arguments. */ - HDassert(f); - HDassert(bt2_shared); - HDassert(node_ptr); - - /* Allocate memory for leaf information */ - if (NULL==(leaf = H5FL_MALLOC(H5B2_leaf_t))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree leaf info") - - /* Set metadata cache info */ - HDmemset(&leaf->cache_info,0,sizeof(H5AC_info_t)); - - /* Share common B-tree information */ - leaf->shared = bt2_shared; - H5RC_INC(leaf->shared); - - /* Get the pointer to the shared B-tree info */ - shared=H5RC_GET_OBJ(leaf->shared); - HDassert(shared); - - /* Allocate space for the native keys in memory */ - if((leaf->leaf_native=H5FL_FAC_MALLOC(shared->leaf_fac))==NULL) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree leaf native keys") -#ifdef H5_USING_PURIFY -HDmemset(leaf->leaf_native,0,shared->type->nrec_size*shared->leaf_nrec); -#endif /* H5_USING_PURIFY */ - - /* Set number of records */ - leaf->nrec=0; - - /* Allocate space on disk for the leaf */ - if (HADDR_UNDEF==(node_ptr->addr=H5MF_alloc(f, H5FD_MEM_BTREE, dxpl_id, (hsize_t)shared->node_size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for B-tree leaf node") - - /* Cache the new B-tree node */ - if (H5AC_set(f, dxpl_id, H5AC_BT2_LEAF, node_ptr->addr, leaf, H5AC__NO_FLAGS_SET) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "can't add B-tree leaf to cache") - -done: - if (ret_value<0) { - if (leaf) - (void)H5B2_cache_leaf_dest(f,leaf); - } /* end if */ - - FUNC_LEAVE_NOAPI(ret_value) -} /* H5B2_create_leaf() */ - - -/*------------------------------------------------------------------------- - * Function: H5B2_create_internal - * - * Purpose: Creates empty internal node of a B-tree and update node pointer - * to point to it. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Feb 3 2005 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B2_create_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, H5B2_node_ptr_t *node_ptr) -{ - H5B2_internal_t *internal=NULL; /* Pointer to new internal node created */ - H5B2_shared_t *shared; /* Shared B-tree information */ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI(H5B2_create_internal, FAIL) - - /* Check arguments. */ - HDassert(f); - HDassert(bt2_shared); - HDassert(node_ptr); - - /* Allocate memory for internal node information */ - if (NULL==(internal = H5FL_MALLOC(H5B2_internal_t))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree internal info") - - /* Set metadata cache info */ - HDmemset(&internal->cache_info,0,sizeof(H5AC_info_t)); - - /* Share common B-tree information */ - internal->shared = bt2_shared; - H5RC_INC(internal->shared); - - /* Get the pointer to the shared B-tree info */ - shared=H5RC_GET_OBJ(internal->shared); - HDassert(shared); - - /* Allocate space for the native keys in memory */ - if((internal->int_native=H5FL_FAC_MALLOC(shared->int_fac))==NULL) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree internal native keys") -#ifdef H5_USING_PURIFY -HDmemset(internal->int_native,0,shared->type->nrec_size*shared->internal_nrec); -#endif /* H5_USING_PURIFY */ - - /* Allocate space for the node pointers in memory */ - if((internal->node_ptrs=H5FL_FAC_MALLOC(shared->node_ptr_fac))==NULL) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree internal node pointers") -#ifdef H5_USING_PURIFY -HDmemset(internal->node_ptrs,0,sizeof(H5B2_node_ptr_t)*(shared->internal_nrec+1)); -#endif /* H5_USING_PURIFY */ - - /* Set number of records */ - internal->nrec=0; - - /* Allocate space on disk for the internal node */ - if (HADDR_UNDEF==(node_ptr->addr=H5MF_alloc(f, H5FD_MEM_BTREE, dxpl_id, (hsize_t)shared->node_size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for B-tree internal node") - - /* Cache the new B-tree node */ - if (H5AC_set(f, dxpl_id, H5AC_BT2_INT, node_ptr->addr, internal, H5AC__NO_FLAGS_SET) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "can't add B-tree internal node to cache") - -done: - if (ret_value<0) { - if (internal) - (void)H5B2_cache_internal_dest(f,internal); - } /* end if */ - - FUNC_LEAVE_NOAPI(ret_value) -} /* H5B2_create_internal() */ - - -/*------------------------------------------------------------------------- - * Function: H5B2_iterate_node - * - * Purpose: Iterate over all the records from a B-tree node, 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 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B2_iterate_node(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, unsigned depth, - const H5B2_node_ptr_t *curr_node, H5B2_operator_t op, void *op_data) -{ - H5B2_shared_t *shared; /* Pointer to B-tree's shared information */ - const H5AC_class_t *curr_node_class=NULL; /* Pointer to current node's class info */ - void *node=NULL; /* Pointers to current node */ - uint8_t *native; /* Pointers to node's native records */ - H5B2_node_ptr_t *node_ptrs=NULL; /* Pointers to node's node pointers */ - unsigned u; /* Local index */ - herr_t ret_value = H5B2_ITER_CONT; - - FUNC_ENTER_NOAPI(H5B2_iterate_node, FAIL) - - /* Check arguments. */ - HDassert(f); - HDassert(bt2_shared); - HDassert(curr_node); - HDassert(op); - - /* Get the pointer to the shared B-tree info */ - shared=H5RC_GET_OBJ(bt2_shared); - HDassert(shared); - - if(depth>0) { - H5B2_internal_t *internal; /* Pointer to internal node */ - - /* Lock the current B-tree node */ - if (NULL == (internal = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, curr_node->addr, &(curr_node->node_nrec), bt2_shared, H5AC_READ))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") - - /* Set up information about current node */ - curr_node_class = H5AC_BT2_INT; - node = internal; - native = internal->int_native; - node_ptrs = internal->node_ptrs; - } /* end if */ - else { - H5B2_leaf_t *leaf; /* Pointer to leaf node */ - - /* Lock the current B-tree node */ - if (NULL == (leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, curr_node->addr, &(curr_node->node_nrec), bt2_shared, H5AC_READ))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") - - /* Set up information about current node */ - curr_node_class = H5AC_BT2_LEAF; - node = leaf; - native = leaf->leaf_native; - } /* end else */ - - /* Iterate through records */ - for(u=0; u<curr_node->node_nrec && !ret_value; u++) { - /* Descend into child node, if current node is an internal node */ - if(depth>0) { - if((ret_value = H5B2_iterate_node(f,dxpl_id,bt2_shared,depth-1,&(node_ptrs[u]),op,op_data))<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "node iteration failed") - } /* end if */ - - /* Make callback for current record */ - if ((ret_value = (op)(H5B2_NAT_NREC(native,shared,u), op_data)) <0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "iterator function failed") - } /* end for */ - - /* Descend into last child node, if current node is an internal node */ - if(!ret_value && depth>0) { - if((ret_value = H5B2_iterate_node(f,dxpl_id,bt2_shared,depth-1,&(node_ptrs[u]),op,op_data))<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "node iteration failed") - } /* end if */ - -done: - /* Unlock current node */ - if(node) - if (H5AC_unprotect(f, dxpl_id, curr_node_class, curr_node->addr, node, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node") - - FUNC_LEAVE_NOAPI(ret_value) -} /* H5B2_iterate_node() */ - - -/*------------------------------------------------------------------------- * Function: H5B2_iterate * * Purpose: Iterate over all the records in the B-tree, in "in-order" @@ -3242,303 +641,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5B2_remove_leaf - * - * Purpose: Removes a record from a B-tree leaf node. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 3 2005 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B2_remove_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, - H5B2_node_ptr_t *curr_node_ptr, void *udata) -{ - H5B2_leaf_t *leaf; /* Pointer to leaf node */ - haddr_t leaf_addr=HADDR_UNDEF; /* Leaf address on disk */ - unsigned leaf_flags=H5AC__NO_FLAGS_SET; /* Flags for unprotecting leaf node */ - H5B2_shared_t *shared; /* Pointer to B-tree's shared information */ - unsigned idx; /* Location of record which matches key */ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI_NOINIT(H5B2_remove_leaf) - - /* Check arguments. */ - HDassert(f); - HDassert(bt2_shared); - HDassert(curr_node_ptr); - HDassert(H5F_addr_defined(curr_node_ptr->addr)); - - /* Lock current B-tree node */ - leaf_addr = curr_node_ptr->addr; - if (NULL == (leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, leaf_addr, &(curr_node_ptr->node_nrec), bt2_shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") - - /* Get the pointer to the shared B-tree info */ - shared=H5RC_GET_OBJ(bt2_shared); - HDassert(shared); - - /* Sanity check number of records */ - HDassert(curr_node_ptr->all_nrec == curr_node_ptr->node_nrec); - HDassert(leaf->nrec == curr_node_ptr->node_nrec); - - /* Find correct location to remove this record */ - if(H5B2_locate_record(shared->type,leaf->nrec,shared->nat_off,leaf->leaf_native,udata,&idx) != 0) - HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "record is not in B-tree") - - /* Make callback to retrieve record in native form */ - if((shared->type->retrieve)(udata,H5B2_LEAF_NREC(leaf,shared,idx))<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record into leaf node") - - /* Update number of records in node */ - leaf->nrec--; - - /* Mark leaf node as dirty also */ - leaf_flags |= H5AC__DIRTIED_FLAG; - - if(leaf->nrec > 0) { - /* Pack record out of leaf */ - if(idx<leaf->nrec) - HDmemmove(H5B2_LEAF_NREC(leaf,shared,idx),H5B2_LEAF_NREC(leaf,shared,idx+1),shared->type->nrec_size*(leaf->nrec-idx)); - } /* end if */ - else { - /* Release space for B-tree node on disk */ - if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, leaf_addr, (hsize_t)shared->node_size)<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node") - - /* Let the cache know that the object is deleted */ - leaf_flags |= H5AC__DELETED_FLAG; - - /* Reset address of parent node pointer */ - curr_node_ptr->addr = HADDR_UNDEF; - } /* end else */ - - /* Update record count for parent of leaf node */ - curr_node_ptr->node_nrec--; - -done: - /* Release the B-tree leaf node */ - if (leaf && H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, leaf_addr, leaf, leaf_flags) < 0) - HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release leaf B-tree node") - - FUNC_LEAVE_NOAPI(ret_value) -} /* H5B2_remove_leaf() */ - - -/*------------------------------------------------------------------------- - * Function: H5B2_remove_internal - * - * Purpose: Removes a record from a B-tree node. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 3 2005 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B2_remove_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, - hbool_t *depth_decreased, void *swap_loc, unsigned depth, - H5AC_info_t *parent_cache_info, unsigned *parent_cache_info_flags_ptr, - H5B2_node_ptr_t *curr_node_ptr, void *udata) -{ - H5AC_info_t *new_cache_info; /* Pointer to new cache info */ - unsigned *new_cache_info_flags_ptr = NULL; - H5B2_node_ptr_t *new_node_ptr; /* Pointer to new node pointer */ - H5B2_internal_t *internal; /* Pointer to internal node */ - unsigned internal_flags = H5AC__NO_FLAGS_SET; - haddr_t internal_addr; /* Address of internal node */ - H5B2_shared_t *shared; /* Pointer to B-tree's shared information */ - unsigned idx; /* Location of record which matches key */ - size_t merge_nrec; /* Number of records to merge node at */ - hbool_t collapsed_root = FALSE; /* Whether the root was collapsed */ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI_NOINIT(H5B2_remove_internal) - - /* Check arguments. */ - HDassert(f); - HDassert(bt2_shared); - HDassert(depth>0); - HDassert(parent_cache_info); - HDassert(parent_cache_info_flags_ptr); - HDassert(curr_node_ptr); - HDassert(H5F_addr_defined(curr_node_ptr->addr)); - - /* Lock current B-tree node */ - internal_addr = curr_node_ptr->addr; - if (NULL == (internal = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, internal_addr, &(curr_node_ptr->node_nrec), bt2_shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") - - /* Get the pointer to the shared B-tree info */ - shared=H5RC_GET_OBJ(bt2_shared); - HDassert(shared); - - /* Determine the correct number of records to merge at */ - if(depth==1) - merge_nrec = shared->merge_leaf_nrec; - else - merge_nrec = shared->merge_int_nrec; - - /* Check for needing to collapse the root node */ - /* (The root node is the only node allowed to have 1 record) */ - if(internal->nrec == 1 && - ((internal->node_ptrs[0].node_nrec + internal->node_ptrs[1].node_nrec) <= ((merge_nrec * 2) + 1))) { - - /* Merge children of root node */ - if(H5B2_merge2(f,dxpl_id,depth,curr_node_ptr, - parent_cache_info_flags_ptr, internal,&internal_flags,0)<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node") - - /* Release space for root B-tree node on disk */ - if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, internal_addr, (hsize_t)shared->node_size)<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node") - - /* Let the cache know that the object is deleted */ - internal_flags |= H5AC__DELETED_FLAG; - - /* Reset information in parent node pointer */ - curr_node_ptr->addr = internal->node_ptrs[0].addr; - curr_node_ptr->node_nrec = internal->node_ptrs[0].node_nrec; - - /* Indicate that the level of the B-tree decreased */ - *depth_decreased = TRUE; - - /* Set pointers for advancing to child node */ - new_cache_info = parent_cache_info; - new_cache_info_flags_ptr = parent_cache_info_flags_ptr; - new_node_ptr = curr_node_ptr; - - /* Set flag to indicate root was collapsed */ - collapsed_root = TRUE; - } /* end if */ - /* Merge or redistribute child node pointers, if necessary */ - else { - int cmp=0; /* Comparison value of records */ - unsigned retries; /* Number of times to attempt redistribution */ - - /* Locate node pointer for child */ - if(swap_loc) - idx = 0; - else { - cmp=H5B2_locate_record(shared->type,internal->nrec,shared->nat_off,internal->int_native,udata,&idx); - if(cmp >= 0) - idx++; - } /* end else */ - - /* Set the number of redistribution retries */ - /* This takes care of the case where a B-tree node needs to be - * redistributed, but redistributing the node causes the index - * for removal to move to another node, which also needs to be - * redistributed. Now, we loop trying to redistribute and then - * eventually force a merge */ - retries = 2; - - /* Preemptively merge/redistribute a node we will enter */ - while(internal->node_ptrs[idx].node_nrec==merge_nrec) { - /* Attempt to redistribute records among children */ - if(idx==0) { /* Left-most child */ - if(retries>0 && (internal->node_ptrs[idx+1].node_nrec > merge_nrec)) { - if(H5B2_redistribute2(f,dxpl_id,depth,internal,idx)<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records") - } /* end if */ - else { - if(H5B2_merge2(f,dxpl_id,depth,curr_node_ptr, - parent_cache_info_flags_ptr, internal,&internal_flags,idx)<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node") - } /* end else */ - } /* end if */ - else if(idx==internal->nrec) { /* Right-most child */ - if(retries>0 && (internal->node_ptrs[idx-1].node_nrec > merge_nrec)) { - if(H5B2_redistribute2(f,dxpl_id,depth,internal,(idx-1))<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records") - } /* end if */ - else { - if(H5B2_merge2(f,dxpl_id,depth,curr_node_ptr, - parent_cache_info_flags_ptr, internal,&internal_flags,(idx-1))<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node") - } /* end else */ - } /* end if */ - else { /* Middle child */ - if(retries>0 && ((internal->node_ptrs[idx+1].node_nrec > merge_nrec) || - (internal->node_ptrs[idx-1].node_nrec > merge_nrec))) { - if(H5B2_redistribute3(f,dxpl_id,depth,internal,&internal_flags,idx)<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records") - } /* end if */ - else { - if(H5B2_merge3(f,dxpl_id,depth,curr_node_ptr, - parent_cache_info_flags_ptr,internal, &internal_flags,idx)<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node") - } /* end else */ - } /* end else */ - - /* Locate node pointer for child (after merge/redistribute) */ - if(swap_loc) - idx = 0; - else { -/* Actually, this can be easily updated (for 2-node redistrib.) and shouldn't require re-searching */ - cmp=H5B2_locate_record(shared->type,internal->nrec,shared->nat_off,internal->int_native,udata,&idx); - if(cmp >= 0) - idx++; - } /* end else */ - - /* Decrement the number of redistribution retries left */ - retries--; - } /* end while */ - - /* Handle deleting a record from an internal node */ - if(!swap_loc && cmp==0) - swap_loc = H5B2_INT_NREC(internal,shared,idx-1); - - /* Swap record to delete with record from leaf, if we are the last internal node */ - if(swap_loc && depth==1) - if(H5B2_swap_leaf(f,dxpl_id,depth,internal,&internal_flags,idx,swap_loc) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTSWAP, FAIL, "Can't swap records in B-tree") - - /* Set pointers for advancing to child node */ - new_cache_info_flags_ptr = &internal_flags; - new_cache_info = &internal->cache_info; - new_node_ptr = &internal->node_ptrs[idx]; - } /* end else */ - - /* Attempt to remove node */ - if(depth>1) { - if(H5B2_remove_internal(f,dxpl_id,bt2_shared,depth_decreased, swap_loc, depth-1, - new_cache_info,new_cache_info_flags_ptr,new_node_ptr,udata)<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record from B-tree internal node") - } /* end if */ - else { - if(H5B2_remove_leaf(f,dxpl_id,bt2_shared,new_node_ptr,udata)<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record from B-tree leaf node") - } /* end else */ - - /* Update record count for node pointer to current node */ - if(!collapsed_root) - new_node_ptr->all_nrec--; - - /* Mark node as dirty */ - internal_flags |= H5AC__DIRTIED_FLAG; - -#ifdef H5B2_DEBUG - H5B2_assert_internal((!collapsed_root ? (curr_node_ptr->all_nrec-1) : new_node_ptr->all_nrec),shared,internal); -#endif /* H5B2_DEBUG */ - -done: - /* Release the B-tree internal node */ - if (internal && H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, internal_addr, internal, internal_flags) < 0) - HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release internal B-tree node") - - FUNC_LEAVE_NOAPI(ret_value) -} /* H5B2_remove_internal() */ - - -/*------------------------------------------------------------------------- * Function: H5B2_remove * * Purpose: Removes a record from a B-tree. @@ -3654,190 +756,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5B2_neighbor_leaf - * - * Purpose: Locate a record relative to the specified information in a - * B-tree leaf node 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 9 2005 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B2_neighbor_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, - H5B2_node_ptr_t *curr_node_ptr, void *neighbor_loc, - H5B2_compare_t comp, void *udata, H5B2_found_t op, void *op_data) -{ - H5B2_leaf_t *leaf; /* Pointer to leaf node */ - H5B2_shared_t *shared; /* Pointer to B-tree's shared information */ - unsigned idx; /* Location of record which matches key */ - int cmp=0; /* Comparison value of records */ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI_NOINIT(H5B2_neighbor_leaf) - - /* Check arguments. */ - HDassert(f); - HDassert(bt2_shared); - HDassert(curr_node_ptr); - HDassert(H5F_addr_defined(curr_node_ptr->addr)); - HDassert(op); - - /* Lock current B-tree 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 leaf node") - - /* Get the pointer to the shared B-tree info */ - shared=H5RC_GET_OBJ(bt2_shared); - HDassert(shared); - - - /* Locate node pointer for child */ - cmp = H5B2_locate_record(shared->type, leaf->nrec, shared->nat_off, leaf->leaf_native, udata, &idx); - if(cmp > 0) - idx++; - else - if(cmp == 0 && comp == H5B2_COMPARE_GREATER) - idx++; - - /* Set the neighbor location, if appropriate */ - if(comp == H5B2_COMPARE_LESS) { - if(idx > 0) - neighbor_loc = H5B2_LEAF_NREC(leaf,shared,idx-1); - } /* end if */ - else { - HDassert(comp == H5B2_COMPARE_GREATER); - - if(idx < leaf->nrec) - neighbor_loc = H5B2_LEAF_NREC(leaf,shared,idx); - } /* end else */ - - /* Make callback if neighbor record has been found */ - if(neighbor_loc) { - /* Make callback for current record */ - if ((op)(neighbor_loc, op_data) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "'found' callback failed for B-tree neighbor operation") - } /* end if */ - else - HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "unable to find neighbor record in B-tree") - -done: - /* Release the B-tree internal node */ - if (leaf && H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr->addr, leaf, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree leaf node") - - FUNC_LEAVE_NOAPI(ret_value) -} /* H5B2_neighbor_leaf() */ - - -/*------------------------------------------------------------------------- - * Function: H5B2_neighbor_internal - * - * Purpose: Locate a record relative to the specified information in a - * B-tree internal node 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 9 2005 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B2_neighbor_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, - unsigned depth, H5B2_node_ptr_t *curr_node_ptr, void *neighbor_loc, - H5B2_compare_t comp, void *udata, H5B2_found_t op, void *op_data) -{ - H5B2_internal_t *internal; /* Pointer to internal node */ - H5B2_shared_t *shared; /* Pointer to B-tree's shared information */ - unsigned idx; /* Location of record which matches key */ - int cmp=0; /* Comparison value of records */ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI_NOINIT(H5B2_neighbor_internal) - - /* Check arguments. */ - HDassert(f); - HDassert(bt2_shared); - HDassert(depth>0); - HDassert(curr_node_ptr); - HDassert(H5F_addr_defined(curr_node_ptr->addr)); - HDassert(op); - - /* Lock current B-tree node */ - if (NULL == (internal = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, 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") - - /* Get the pointer to the shared B-tree info */ - shared=H5RC_GET_OBJ(bt2_shared); - HDassert(shared); - - /* 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++; - - /* Set the neighbor location, if appropriate */ - if(comp == H5B2_COMPARE_LESS) { - if(idx > 0) - neighbor_loc = H5B2_INT_NREC(internal,shared,idx-1); - } /* end if */ - else { - HDassert(comp == H5B2_COMPARE_GREATER); - - if(idx < internal->nrec) - neighbor_loc = H5B2_INT_NREC(internal,shared,idx); - } /* end else */ - - /* Attempt to find neighboring record */ - if(depth>1) { - if(H5B2_neighbor_internal(f, dxpl_id, bt2_shared, depth-1, &internal->node_ptrs[idx], neighbor_loc, comp, 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, &internal->node_ptrs[idx], neighbor_loc, comp, 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 internal node */ - if (internal && H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr->addr, internal, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release internal B-tree node") - - FUNC_LEAVE_NOAPI(ret_value) -} /* H5B2_neighbor_internal() */ - - -/*------------------------------------------------------------------------- * Function: H5B2_neighbor * * Purpose: Locate a record relative to the specified information in a @@ -3905,83 +823,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5B2_delete_node - * - * Purpose: Iterate over all the nodes in a B-tree node deleting them - * after they no longer have any children - * - * Return: Value from callback, non-negative on success, negative on error - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 9 2005 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B2_delete_node(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, unsigned depth, - const H5B2_node_ptr_t *curr_node) -{ - H5B2_shared_t *shared; /* Pointer to B-tree's shared information */ - const H5AC_class_t *curr_node_class=NULL; /* Pointer to current node's class info */ - void *node=NULL; /* Pointers to current node */ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI(H5B2_delete_node, FAIL) - - /* Check arguments. */ - HDassert(f); - HDassert(bt2_shared); - HDassert(curr_node); - - /* Get the pointer to the shared B-tree info */ - shared=H5RC_GET_OBJ(bt2_shared); - HDassert(shared); - - if(depth>0) { - H5B2_internal_t *internal; /* Pointer to internal node */ - unsigned u; /* Local index */ - - /* Lock the current B-tree node */ - if (NULL == (internal = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, curr_node->addr, &(curr_node->node_nrec), bt2_shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") - - /* Set up information about current node */ - curr_node_class = H5AC_BT2_INT; - node = internal; - - /* Descend into children */ - for(u=0; u<internal->nrec+1; u++) - if(H5B2_delete_node(f, dxpl_id, bt2_shared, depth-1, &(internal->node_ptrs[u]))<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "node descent failed") - } /* end if */ - else { - H5B2_leaf_t *leaf; /* Pointer to leaf node */ - - /* Lock the current B-tree node */ - if (NULL == (leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, curr_node->addr, &(curr_node->node_nrec), bt2_shared, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") - - /* Set up information about current node */ - curr_node_class = H5AC_BT2_LEAF; - node = leaf; - } /* end else */ - - /* Release space for current B-tree node on disk */ - if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, curr_node->addr, (hsize_t)shared->node_size)<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree node") - -done: - /* Unlock & delete current node */ - if(node) - if (H5AC_unprotect(f, dxpl_id, curr_node_class, curr_node->addr, node, H5AC__DELETED_FLAG) < 0) - HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node") - - FUNC_LEAVE_NOAPI(ret_value) -} /* H5B2_delete_node() */ - - -/*------------------------------------------------------------------------- * Function: H5B2_delete * * Purpose: Delete an entire B-tree from a file. @@ -4211,161 +1052,3 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* H5B2_modify() */ -#ifdef H5B2_DEBUG - -/*------------------------------------------------------------------------- - * Function: H5B2_assert_leaf - * - * Purpose: Verify than a leaf node is mostly sane - * - * Return: Non-negative on success, negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Feb 19 2005 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B2_assert_leaf(H5B2_shared_t *shared, H5B2_leaf_t *leaf) -{ - unsigned u,v; /* Local index variables */ - - /* General sanity checking on node */ - HDassert(leaf->nrec<=shared->split_leaf_nrec); - - /* Sanity checking on records */ - for(u=0; u<leaf->nrec; u++) - for(v=0; v<u; v++) - HDassert((shared->type->compare)(H5B2_LEAF_NREC(leaf,shared,u), H5B2_LEAF_NREC(leaf,shared,v))>0); - - return(0); -} /* end H5B2_assert_leaf() */ - - -/*------------------------------------------------------------------------- - * Function: H5B2_assert_leaf2 - * - * Purpose: Verify than a leaf node is mostly sane - * - * Return: Non-negative on success, negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Feb 19 2005 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B2_assert_leaf2(H5B2_shared_t *shared, H5B2_leaf_t *leaf, H5B2_leaf_t *leaf2) -{ - unsigned u,v; /* Local index variables */ - - /* General sanity checking on node */ - HDassert(leaf->nrec<=shared->split_leaf_nrec); - - /* Sanity checking on records */ - for(u=0; u<leaf->nrec; u++) { - HDassert((shared->type->compare)(H5B2_LEAF_NREC(leaf2,shared,0), H5B2_LEAF_NREC(leaf,shared,u))>0); - for(v=0; v<u; v++) - HDassert((shared->type->compare)(H5B2_LEAF_NREC(leaf,shared,u), H5B2_LEAF_NREC(leaf,shared,v))>0); - } /* end for */ - - return(0); -} /* end H5B2_assert_leaf() */ - - -/*------------------------------------------------------------------------- - * Function: H5B2_assert_internal - * - * Purpose: Verify than an internal node is mostly sane - * - * Return: Non-negative on success, negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Feb 19 2005 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B2_assert_internal(hsize_t parent_all_nrec, H5B2_shared_t *shared, H5B2_internal_t *internal) -{ - hsize_t tot_all_nrec; /* Total number of records at or below this node */ - unsigned u,v; /* Local index variables */ - - /* General sanity checking on node */ - HDassert(internal->nrec<=shared->split_int_nrec); - - /* Sanity checking on records */ - for(u=0; u<internal->nrec; u++) - for(v=0; v<u; v++) - HDassert((shared->type->compare)(H5B2_INT_NREC(internal,shared,u), H5B2_INT_NREC(internal,shared,v))>0); - - /* Sanity checking on node pointers */ - tot_all_nrec=internal->nrec; - for(u=0; u<internal->nrec+1; u++) { - tot_all_nrec += internal->node_ptrs[u].all_nrec; - - HDassert(H5F_addr_defined(internal->node_ptrs[u].addr)); - HDassert(internal->node_ptrs[u].addr>0); - for(v=0; v<u; v++) - HDassert(internal->node_ptrs[u].addr!=internal->node_ptrs[v].addr); - } /* end for */ - - /* Sanity check all_nrec total in parent */ - if(parent_all_nrec>0) - HDassert(tot_all_nrec == parent_all_nrec); - - return(0); -} /* end H5B2_assert_internal() */ - - -/*------------------------------------------------------------------------- - * Function: H5B2_assert_internal2 - * - * Purpose: Verify than internal nodes are mostly sane - * - * Return: Non-negative on success, negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Feb 19 2005 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B2_assert_internal2(hsize_t parent_all_nrec, H5B2_shared_t *shared, H5B2_internal_t *internal, H5B2_internal_t *internal2) -{ - hsize_t tot_all_nrec; /* Total number of records at or below this node */ - unsigned u,v; /* Local index variables */ - - /* General sanity checking on node */ - HDassert(internal->nrec<=shared->split_int_nrec); - - /* Sanity checking on records */ - for(u=0; u<internal->nrec; u++) - for(v=0; v<u; v++) - HDassert((shared->type->compare)(H5B2_INT_NREC(internal,shared,u), H5B2_INT_NREC(internal,shared,v))>0); - - /* Sanity checking on node pointers */ - tot_all_nrec=internal->nrec; - for(u=0; u<internal->nrec+1; u++) { - tot_all_nrec += internal->node_ptrs[u].all_nrec; - - HDassert(H5F_addr_defined(internal->node_ptrs[u].addr)); - HDassert(internal->node_ptrs[u].addr>0); - for(v=0; v<u; v++) - HDassert(internal->node_ptrs[u].addr!=internal->node_ptrs[v].addr); - for(v=0; v<internal2->nrec+1; v++) - HDassert(internal->node_ptrs[u].addr!=internal2->node_ptrs[v].addr); - } /* end for */ - - /* Sanity check all_nrec total in parent */ - if(parent_all_nrec>0) - HDassert(tot_all_nrec == parent_all_nrec); - - return(0); -} /* end H5B2_assert_internal2() */ -#endif /* H5B2_DEBUG */ - diff --git a/src/H5B2cache.c b/src/H5B2cache.c index 0ad3242..cad430e 100644 --- a/src/H5B2cache.c +++ b/src/H5B2cache.c @@ -202,6 +202,7 @@ H5B2_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_type, vo H5F_DECODE_LENGTH(f, p, bt2->root.all_nrec); /* Initialize shared B-tree info */ + HDassert((size_t)(p - buf) == size); if(H5B2_shared_init(f, bt2, type, node_size, rrec_size, split_percent, merge_percent) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't create shared B-tree info") @@ -291,7 +292,7 @@ H5B2_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B H5F_ENCODE_LENGTH(f, p, bt2->root.all_nrec); /* Write the B-tree header. */ - HDassert((p - buf) == size); + HDassert((size_t)(p - buf) == size); if(H5F_block_write(f, H5FD_MEM_BTREE, addr, size, dxpl_id, buf) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTFLUSH, FAIL, "unable to save B-tree header to disk") @@ -431,13 +432,13 @@ static H5B2_leaf_t * H5B2_cache_leaf_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nrec, void *_bt2_shared) { const unsigned *nrec = (const unsigned *)_nrec; - H5RC_t *bt2_shared=(H5RC_t *)_bt2_shared; /* Shared B-tree information */ + H5RC_t *bt2_shared = (H5RC_t *)_bt2_shared; /* Shared B-tree information */ H5B2_shared_t *shared; /* Shared B-tree information */ - H5B2_leaf_t *leaf = NULL; + H5B2_leaf_t *leaf = NULL; /* Pointer to lead node loaded */ uint8_t *p; /* Pointer into raw data buffer */ uint8_t *native; /* Pointer to native keys */ unsigned u; /* Local index variable */ - H5B2_leaf_t *ret_value; + H5B2_leaf_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5B2_cache_leaf_load, NULL) @@ -446,49 +447,51 @@ H5B2_cache_leaf_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nrec, v HDassert(H5F_addr_defined(addr)); HDassert(bt2_shared); - if (NULL==(leaf = H5FL_MALLOC(H5B2_leaf_t))) + if(NULL == (leaf = H5FL_MALLOC(H5B2_leaf_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - HDmemset(&leaf->cache_info,0,sizeof(H5AC_info_t)); + HDmemset(&leaf->cache_info, 0, sizeof(H5AC_info_t)); /* Share common B-tree information */ leaf->shared = bt2_shared; H5RC_INC(leaf->shared); /* Get the pointer to the shared B-tree info */ - shared=H5RC_GET_OBJ(leaf->shared); + shared = H5RC_GET_OBJ(leaf->shared); HDassert(shared); /* Read header from disk */ - if (H5F_block_read(f, H5FD_MEM_BTREE, addr, shared->node_size, dxpl_id, shared->page)<0) + if(H5F_block_read(f, H5FD_MEM_BTREE, addr, shared->node_size, dxpl_id, shared->page) < 0) HGOTO_ERROR(H5E_BTREE, H5E_READERROR, NULL, "can't read B-tree leaf node") p = shared->page; - /* magic number */ - if (HDmemcmp(p, H5B2_LEAF_MAGIC, H5B2_SIZEOF_MAGIC)) + /* Magic number */ + if(HDmemcmp(p, H5B2_LEAF_MAGIC, H5B2_SIZEOF_MAGIC)) HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree leaf node signature") p += H5B2_SIZEOF_MAGIC; - /* version */ - if (*p++ != H5B2_LEAF_VERSION) + /* Version */ + if(*p++ != H5B2_LEAF_VERSION) HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree leaf node version") +/* XXX: Add metadata flags & checksum to v2 B-tree metadata (like fractal heap) */ + /* B-tree type */ - if (*p++ != (uint8_t)shared->type->id) + if(*p++ != (uint8_t)shared->type->id) HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "incorrect B-tree type") /* Allocate space for the native keys in memory */ - if((leaf->leaf_native=H5FL_FAC_MALLOC(shared->leaf_fac))==NULL) + if((leaf->leaf_native = H5FL_FAC_MALLOC(shared->leaf_fac)) == NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for B-tree leaf native keys") /* Set the number of records in the leaf */ leaf->nrec = *nrec; /* Deserialize records for leaf node */ - native=leaf->leaf_native; - for(u=0; u<leaf->nrec; u++) { + native = leaf->leaf_native; + for(u = 0; u < leaf->nrec; u++) { /* Decode record */ - if((shared->type->decode)(f,p,native)<0) + if((shared->type->decode)(f, p, native) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, NULL, "unable to decode B-tree record") /* Move to next record */ @@ -496,11 +499,14 @@ H5B2_cache_leaf_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nrec, v native += shared->type->nrec_size; } /* end for */ + /* Sanity check parsing */ + HDassert((size_t)(p - shared->page) <= shared->node_size); + /* Set return value */ ret_value = leaf; done: - if (!ret_value && leaf) + if(!ret_value && leaf) (void)H5B2_cache_leaf_dest(f,leaf); FUNC_LEAVE_NOAPI(ret_value) } /* H5B2_cache_leaf_load() */ /*lint !e818 Can't make udata a pointer to const */ @@ -531,14 +537,14 @@ H5B2_cache_leaf_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5 HDassert(H5F_addr_defined(addr)); HDassert(leaf); - if (leaf->cache_info.is_dirty) { + if(leaf->cache_info.is_dirty) { H5B2_shared_t *shared; /* Shared B-tree information */ uint8_t *p; /* Pointer into raw data buffer */ uint8_t *native; /* Pointer to native keys */ unsigned u; /* Local index variable */ /* Get the pointer to the shared B-tree info */ - shared=H5RC_GET_OBJ(leaf->shared); + shared = H5RC_GET_OBJ(leaf->shared); HDassert(shared); p = shared->page; @@ -554,10 +560,10 @@ H5B2_cache_leaf_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5 *p++ = shared->type->id; /* Serialize records for leaf node */ - native=leaf->leaf_native; - for(u=0; u<leaf->nrec; u++) { + native = leaf->leaf_native; + for(u = 0; u < leaf->nrec; u++) { /* Encode record */ - if((shared->type->encode)(f,p,native)<0) + if((shared->type->encode)(f, p, native) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, FAIL, "unable to encode B-tree record") /* Move to next record */ @@ -566,14 +572,15 @@ H5B2_cache_leaf_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5 } /* end for */ /* Write the B-tree leaf node */ - if (H5F_block_write(f, H5FD_MEM_BTREE, addr, shared->node_size, dxpl_id, shared->page) < 0) + HDassert((size_t)(p - shared->page) <= shared->node_size); + if(H5F_block_write(f, H5FD_MEM_BTREE, addr, shared->node_size, dxpl_id, shared->page) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTFLUSH, FAIL, "unable to save B-tree leaf node to disk") leaf->cache_info.is_dirty = FALSE; } /* end if */ - if (destroy) - if (H5B2_cache_leaf_dest(f,leaf) < 0) + if(destroy) + if(H5B2_cache_leaf_dest(f, leaf) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree leaf node") done: @@ -608,7 +615,7 @@ H5B2_cache_leaf_dest(H5F_t UNUSED *f, H5B2_leaf_t *leaf) HDassert(leaf); /* Get the pointer to the shared B-tree info */ - shared=H5RC_GET_OBJ(leaf->shared); + shared = H5RC_GET_OBJ(leaf->shared); HDassert(shared); /* Release leaf's native key buffer */ @@ -654,8 +661,8 @@ H5B2_cache_leaf_clear(H5F_t *f, H5B2_leaf_t *leaf, hbool_t destroy) /* Reset the dirty flag. */ leaf->cache_info.is_dirty = FALSE; - if (destroy) - if (H5B2_cache_leaf_dest(f, leaf) < 0) + if(destroy) + if(H5B2_cache_leaf_dest(f, leaf) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree leaf node") done: @@ -690,7 +697,7 @@ H5B2_cache_leaf_size(const H5F_t UNUSED *f, const H5B2_leaf_t *leaf, size_t *siz HDassert(size_ptr); /* Get the pointer to the shared B-tree info */ - shared=H5RC_GET_OBJ(leaf->shared); + shared = H5RC_GET_OBJ(leaf->shared); HDassert(shared); /* Set size value */ @@ -721,12 +728,12 @@ H5B2_cache_internal_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nre const unsigned *nrec = (const unsigned *)_nrec; H5RC_t *bt2_shared = (H5RC_t *)_bt2_shared; /* Ref counter for shared B-tree info */ H5B2_shared_t *shared; /* Shared B-tree information */ - H5B2_internal_t *internal = NULL; + H5B2_internal_t *internal = NULL; /* Internal node read */ uint8_t *p; /* Pointer into raw data buffer */ uint8_t *native; /* Pointer to native record info */ H5B2_node_ptr_t *int_node_ptr; /* Pointer to node pointer info */ unsigned u; /* Local index variable */ - H5B2_internal_t *ret_value; + H5B2_internal_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5B2_cache_internal_load, NULL) @@ -735,9 +742,9 @@ H5B2_cache_internal_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nre HDassert(H5F_addr_defined(addr)); HDassert(bt2_shared); - if (NULL==(internal = H5FL_MALLOC(H5B2_internal_t))) + if(NULL == (internal = H5FL_MALLOC(H5B2_internal_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - HDmemset(&internal->cache_info,0,sizeof(H5AC_info_t)); + HDmemset(&internal->cache_info, 0, sizeof(H5AC_info_t)); /* Share common B-tree information */ internal->shared = bt2_shared; @@ -748,40 +755,42 @@ H5B2_cache_internal_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nre HDassert(shared); /* Read header from disk */ - if (H5F_block_read(f, H5FD_MEM_BTREE, addr, shared->node_size, dxpl_id, shared->page)<0) + if(H5F_block_read(f, H5FD_MEM_BTREE, addr, shared->node_size, dxpl_id, shared->page)<0) HGOTO_ERROR(H5E_BTREE, H5E_READERROR, NULL, "can't read B-tree internal node") p = shared->page; - /* magic number */ - if (HDmemcmp(p, H5B2_INT_MAGIC, H5B2_SIZEOF_MAGIC)) + /* Magic number */ + if(HDmemcmp(p, H5B2_INT_MAGIC, H5B2_SIZEOF_MAGIC)) HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree internal node signature") p += H5B2_SIZEOF_MAGIC; - /* version */ - if (*p++ != H5B2_INT_VERSION) + /* Version */ + if(*p++ != H5B2_INT_VERSION) HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree internal node version") +/* XXX: Add metadata flags & checksum to v2 B-tree metadata (like fractal heap) */ + /* B-tree type */ if (*p++ != (uint8_t)shared->type->id) HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "incorrect B-tree type") /* Allocate space for the native keys in memory */ - if((internal->int_native=H5FL_FAC_MALLOC(shared->int_fac))==NULL) + if((internal->int_native = H5FL_FAC_MALLOC(shared->int_fac)) == NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for B-tree internal native keys") /* Allocate space for the node pointers in memory */ - if((internal->node_ptrs=H5FL_FAC_MALLOC(shared->node_ptr_fac))==NULL) + if((internal->node_ptrs = H5FL_FAC_MALLOC(shared->node_ptr_fac)) == NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for B-tree internal node pointers") /* Set the number of records in the leaf */ internal->nrec = *nrec; /* Deserialize records for internal node */ - native=internal->int_native; - for(u=0; u<internal->nrec; u++) { + native = internal->int_native; + for(u = 0; u < internal->nrec; u++) { /* Decode record */ - if((shared->type->decode)(f,p,native)<0) + if((shared->type->decode)(f, p, native) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, NULL, "unable to decode B-tree record") /* Move to next record */ @@ -790,8 +799,8 @@ H5B2_cache_internal_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nre } /* end for */ /* Deserialize node pointers for internal node */ - int_node_ptr=internal->node_ptrs; - for(u=0; u<internal->nrec+1; u++) { + int_node_ptr = internal->node_ptrs; + for(u = 0; u < internal->nrec + 1; u++) { /* Decode node pointer */ H5F_addr_decode(f, (const uint8_t **)&p, &(int_node_ptr->addr)); UINT16DECODE(p, int_node_ptr->node_nrec); @@ -801,12 +810,15 @@ H5B2_cache_internal_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nre int_node_ptr++; } /* end for */ + /* Sanity check parsing */ + HDassert((size_t)(p - shared->page) <= shared->node_size); + /* Set return value */ ret_value = internal; done: - if (!ret_value && internal) - (void)H5B2_cache_internal_dest(f,internal); + if(!ret_value && internal) + (void)H5B2_cache_internal_dest(f, internal); FUNC_LEAVE_NOAPI(ret_value) } /* H5B2_cache_internal_load() */ /*lint !e818 Can't make udata a pointer to const */ @@ -836,7 +848,7 @@ H5B2_cache_internal_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr HDassert(H5F_addr_defined(addr)); HDassert(internal); - if (internal->cache_info.is_dirty) { + if(internal->cache_info.is_dirty) { H5B2_shared_t *shared; /* Shared B-tree information */ uint8_t *p; /* Pointer into raw data buffer */ uint8_t *native; /* Pointer to native record info */ @@ -844,26 +856,26 @@ H5B2_cache_internal_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr unsigned u; /* Local index variable */ /* Get the pointer to the shared B-tree info */ - shared=H5RC_GET_OBJ(internal->shared); + shared = H5RC_GET_OBJ(internal->shared); HDassert(shared); p = shared->page; - /* magic number */ + /* Magic number */ HDmemcpy(p, H5B2_INT_MAGIC, H5B2_SIZEOF_MAGIC); p += H5B2_SIZEOF_MAGIC; - /* version # */ + /* Version # */ *p++ = H5B2_INT_VERSION; - /* b-tree type */ + /* B-tree type */ *p++ = shared->type->id; /* Serialize records for internal node */ - native=internal->int_native; - for(u=0; u<internal->nrec; u++) { + native = internal->int_native; + for(u = 0; u < internal->nrec; u++) { /* Encode record */ - if((shared->type->encode)(f,p,native)<0) + if((shared->type->encode)(f, p, native) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, FAIL, "unable to encode B-tree record") /* Move to next record */ @@ -872,8 +884,8 @@ H5B2_cache_internal_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr } /* end for */ /* Serialize node pointers for internal node */ - int_node_ptr=internal->node_ptrs; - for(u=0; u<internal->nrec+1; u++) { + int_node_ptr = internal->node_ptrs; + for(u = 0; u < internal->nrec + 1; u++) { /* Encode node pointer */ H5F_addr_encode(f, &p, int_node_ptr->addr); UINT16ENCODE(p, int_node_ptr->node_nrec); @@ -884,14 +896,15 @@ H5B2_cache_internal_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr } /* end for */ /* Write the B-tree internal node */ - if (H5F_block_write(f, H5FD_MEM_BTREE, addr, shared->node_size, dxpl_id, shared->page) < 0) + HDassert((size_t)(p - shared->page) <= shared->node_size); + if(H5F_block_write(f, H5FD_MEM_BTREE, addr, shared->node_size, dxpl_id, shared->page) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTFLUSH, FAIL, "unable to save B-tree internal node to disk") internal->cache_info.is_dirty = FALSE; } /* end if */ - if (destroy) - if (H5B2_cache_internal_dest(f,internal) < 0) + if(destroy) + if(H5B2_cache_internal_dest(f, internal) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree internal node") done: @@ -926,23 +939,23 @@ H5B2_cache_internal_dest(H5F_t UNUSED *f, H5B2_internal_t *internal) HDassert(internal); /* Get the pointer to the shared B-tree info */ - shared=H5RC_GET_OBJ(internal->shared); + shared = H5RC_GET_OBJ(internal->shared); HDassert(shared); /* Release internal node's native key buffer */ if(internal->int_native) - H5FL_FAC_FREE(shared->int_fac,internal->int_native); + H5FL_FAC_FREE(shared->int_fac, internal->int_native); /* Release internal node's node pointer buffer */ if(internal->node_ptrs) - H5FL_FAC_FREE(shared->node_ptr_fac,internal->node_ptrs); + H5FL_FAC_FREE(shared->node_ptr_fac, internal->node_ptrs); /* Decrement reference count on shared B-tree info */ if(internal->shared) H5RC_DEC(internal->shared); /* Free B-tree internal node info */ - H5FL_FREE(H5B2_internal_t,internal); + H5FL_FREE(H5B2_internal_t, internal); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5B2_cache_internal_dest() */ @@ -976,8 +989,8 @@ H5B2_cache_internal_clear(H5F_t *f, H5B2_internal_t *internal, hbool_t destroy) /* Reset the dirty flag. */ internal->cache_info.is_dirty = FALSE; - if (destroy) - if (H5B2_cache_internal_dest(f, internal) < 0) + if(destroy) + if(H5B2_cache_internal_dest(f, internal) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree internal node") done: @@ -1012,7 +1025,7 @@ H5B2_cache_internal_size(const H5F_t UNUSED *f, const H5B2_internal_t *internal, HDassert(size_ptr); /* Get the pointer to the shared B-tree info */ - shared=H5RC_GET_OBJ(internal->shared); + shared = H5RC_GET_OBJ(internal->shared); HDassert(shared); /* Set size value */ @@ -1021,4 +1034,3 @@ H5B2_cache_internal_size(const H5F_t UNUSED *f, const H5B2_internal_t *internal, FUNC_LEAVE_NOAPI(SUCCEED) } /* H5B2_cache_internal_size() */ - diff --git a/src/H5B2int.c b/src/H5B2int.c new file mode 100644 index 0000000..9b4b8db --- /dev/null +++ b/src/H5B2int.c @@ -0,0 +1,3357 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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: H5B2int.c + * Feb 27 2006 + * Quincey Koziol <koziol@ncsa.uiuc.edu> + * + * Purpose: Internal routines for managing v2 B-trees. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* 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 */ +/****************/ + +/* Format overhead for each node (on disk) */ +#define H5B2_OVERHEAD_SIZE (H5B2_SIZEOF_MAGIC+1) /* Signature + version # */ + +/* Number of records that fit into internal node */ +#define H5B2_NUM_INT_REC(f,n,r) (((n)-(H5B2_OVERHEAD_SIZE+H5B2_NODE_POINTER_SIZE(f)))/((r)+H5B2_NODE_POINTER_SIZE(f))) + +/* Number of records that fit into leaf node */ +#define H5B2_NUM_LEAF_REC(n,r) (((n)-H5B2_OVERHEAD_SIZE)/(r)) + +/* Uncomment this macro to enable extra sanity checking */ +/* #define H5B2_DEBUG */ + +/******************/ +/* Local Typedefs */ +/******************/ + +/********************/ +/* Local Prototypes */ +/********************/ + +/* Helper functions */ +static herr_t H5B2_shared_free(void *_shared); +static herr_t H5B2_create_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, + H5B2_node_ptr_t *node_ptr); +static herr_t H5B2_redistribute2(H5F_t *f, hid_t dxpl_id, unsigned depth, + H5B2_internal_t *internal, unsigned idx); +static herr_t H5B2_split2(H5F_t *f, hid_t dxpl_id, unsigned depth, + H5B2_node_ptr_t *curr_node_ptr, unsigned * parent_cache_info_flags_ptr, + H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx); +static herr_t H5B2_split3(H5F_t *f, hid_t dxpl_id, unsigned depth, + H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags, + H5B2_internal_t *internal, unsigned *internal_flags, unsigned idx); +static herr_t H5B2_redistribute3(H5F_t *f, hid_t dxpl_id, unsigned depth, + H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx); +static herr_t H5B2_merge2(H5F_t *f, hid_t dxpl_id, unsigned depth, + H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags_ptr, + H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx); +static herr_t H5B2_merge3(H5F_t *f, hid_t dxpl_id, unsigned depth, + H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags_ptr, + H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx); +static herr_t H5B2_swap_leaf(H5F_t *f, hid_t dxpl_id, unsigned depth, + H5B2_internal_t *internal, unsigned *internal_flags_ptr, + unsigned idx, void *swap_loc); +#ifdef H5B2_DEBUG +static herr_t H5B2_assert_leaf(H5B2_shared_t *shared, H5B2_leaf_t *leaf); +static herr_t H5B2_assert_leaf2(H5B2_shared_t *shared, H5B2_leaf_t *leaf, H5B2_leaf_t *leaf2); +static herr_t H5B2_assert_internal(hsize_t parent_all_nrec, H5B2_shared_t *shared, H5B2_internal_t *internal); +static herr_t H5B2_assert_internal2(hsize_t parent_all_nrec, H5B2_shared_t *shared, H5B2_internal_t *internal, H5B2_internal_t *internal2); +#endif /* H5B2_DEBUG */ + +/*********************/ +/* Package Variables */ +/*********************/ + +/* Declare a free list to manage the H5B2_internal_t struct */ +H5FL_DEFINE(H5B2_internal_t); + +/* Declare a free list to manage the H5B2_leaf_t struct */ +H5FL_DEFINE(H5B2_leaf_t); + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + +/* Declare a free list to manage B-tree node pages to/from disk */ +H5FL_BLK_DEFINE_STATIC(node_page); + +/* Declare a free list to manage the 'size_t' sequence information */ +H5FL_SEQ_DEFINE_STATIC(size_t); + +/* Declare a free list to manage the H5B2_shared_t struct */ +H5FL_DEFINE_STATIC(H5B2_shared_t); + + + +/*------------------------------------------------------------------------- + * Function: H5B2_shared_init + * + * Purpose: Allocate & initialize shared B-tree info + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 2 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5B2_shared_init (H5F_t *f, H5B2_t *bt2, const H5B2_class_t *type, + size_t node_size, size_t rrec_size, + unsigned split_percent, unsigned merge_percent) +{ + H5B2_shared_t *shared = NULL; /* Shared B-tree information */ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5B2_shared_init) + + /* Allocate space for the shared information */ + if(NULL == (shared = H5FL_CALLOC(H5B2_shared_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree shared information") + + /* Assign user's information */ + shared->split_percent = split_percent; + shared->merge_percent = merge_percent; + shared->node_size = node_size; + shared->rrec_size = rrec_size; + + /* Compute derived information */ + shared->internal_nrec = H5B2_NUM_INT_REC(f, shared->node_size, shared->rrec_size); + shared->split_int_nrec = (shared->internal_nrec * shared->split_percent) / 100; + shared->merge_int_nrec = (shared->internal_nrec * shared->merge_percent) / 100; + + shared->leaf_nrec = H5B2_NUM_LEAF_REC(shared->node_size, shared->rrec_size); + shared->split_leaf_nrec = (shared->leaf_nrec * shared->split_percent) / 100; + shared->merge_leaf_nrec = (shared->leaf_nrec * shared->merge_percent) / 100; + + /* Assign common type information */ + shared->type = type; + + /* Allocate "page" for node I/O */ + if((shared->page = H5FL_BLK_MALLOC(node_page, shared->node_size)) == NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") +#ifdef H5_USING_PURIFY +HDmemset(shared->page,0,shared->node_size); +#endif /* H5_USING_PURIFY */ + + /* Create factory for internal node native record storage */ + if((shared->int_fac = H5FL_fac_init(type->nrec_size * shared->internal_nrec)) == NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create internal node native key block factory") + + /* Create factory for leaf node native record storage */ + if((shared->leaf_fac = H5FL_fac_init(type->nrec_size * shared->leaf_nrec)) == NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create leaf node native key block factory") + + /* Create factory for internal node node pointer storage */ + if((shared->node_ptr_fac = H5FL_fac_init(sizeof(H5B2_node_ptr_t) * (shared->internal_nrec + 1))) == NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create internal node node pointer block factory") + + /* Allocate array of pointers to internal node native keys */ + if((shared->nat_off = H5FL_SEQ_MALLOC(size_t, MAX(shared->internal_nrec, shared->leaf_nrec))) == NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Initialize offsets in native key block */ + for(u = 0; u < MAX(shared->internal_nrec, shared->leaf_nrec); u++) + shared->nat_off[u]=type->nrec_size*u; + + /* Make shared B-tree info reference counted */ + if(NULL == (bt2->shared = H5RC_create(shared, H5B2_shared_free))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create ref-count wrapper for shared B-tree info") + +done: + if(ret_value < 0) + if(shared) + H5B2_shared_free(shared); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5B2_shared_init() */ + + +/*------------------------------------------------------------------------- + * Function: H5B2_shared_free + * + * Purpose: Free shared B-tree info + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 2 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5B2_shared_free(void *_shared) +{ + H5B2_shared_t *shared = (H5B2_shared_t *)_shared; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT(H5B2_shared_free) + + /* Sanity check */ + HDassert(shared); + + /* Free the B-tree node buffer */ + if(shared->page) + H5FL_BLK_FREE(node_page, shared->page); + + /* Destroy factory for internal node native record storage */ + if(shared->int_fac) + if(H5FL_fac_term(shared->int_fac) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't destroy internal node native key block factory") + + /* Destroy factory for leaf node native record storage */ + if(shared->leaf_fac) + if(H5FL_fac_term(shared->leaf_fac) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't destroy leaf node native key block factory") + + /* Destroy factory for internal node node pointer storage */ + if(shared->node_ptr_fac) + if(H5FL_fac_term(shared->node_ptr_fac) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't destroy internal node node pointer block factory") + + /* Free the array of offsets into the native key block */ + if(shared->nat_off) + H5FL_SEQ_FREE(size_t,shared->nat_off); + + /* Free the shared B-tree info itself */ + H5FL_FREE(H5B2_shared_t, shared); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5B2_shared_free() */ + + +/*------------------------------------------------------------------------- + * Function: H5B2_locate_record + * + * Purpose: Performs a binary search to locate a record in a sorted + * array of records. + * + * Sets *IDX to location of record greater than or equal to + * record to locate. + * + * Return: Comparison value for insertion location. Negative for record + * to locate being less than value in *IDX. Zero for record to + * locate equal to value in *IDX. Positive for record to locate + * being greater than value in *IDX (which should only happen when + * record to locate is greater than all records to search). + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 3 2005 + * + *------------------------------------------------------------------------- + */ +int +H5B2_locate_record(const H5B2_class_t *type, unsigned nrec, size_t *rec_off, + const uint8_t *native, const void *udata, unsigned *idx) +{ + unsigned lo = 0, hi; /* Low & high index values */ + unsigned my_idx = 0; /* Final index value */ + int cmp = -1; /* Key comparison value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B2_locate_record) + + hi = nrec; + while (lo < hi && cmp) { + my_idx = (lo + hi) / 2; + if ((cmp = (type->compare)(udata, native+rec_off[my_idx])) < 0) + hi = my_idx; + else + lo = my_idx + 1; + } + + *idx = my_idx; + + FUNC_LEAVE_NOAPI(cmp); +} /* end H5B2_locate_record */ + + +/*------------------------------------------------------------------------- + * Function: H5B2_split_root + * + * Purpose: Split the root node + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 3 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5B2_split_root(H5F_t *f, hid_t dxpl_id, H5B2_t *bt2, unsigned *bt2_flags_ptr, + H5RC_t *bt2_shared) +{ + const H5AC_class_t *child_class; /* Pointer to child node's class info */ + H5B2_internal_t *new_root; /* Pointer to new root node */ + haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */ + void *left_child, *right_child; /* Pointers to child nodes */ + unsigned *left_nrec, *right_nrec; /* Pointers to child # of records */ + uint8_t *left_native, *right_native;/* Pointers to childs' native records */ + H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */ + H5B2_shared_t *shared; /* B-tree's shared info */ + unsigned mid_record; /* Index of "middle" record in current node */ + unsigned old_root_nrec; /* Number of records in root node */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5B2_split_root) + + HDassert(f); + HDassert(bt2); + HDassert(bt2_flags_ptr); + HDassert(bt2_shared); + + /* Get the pointer to the shared B-tree info */ + shared=H5RC_GET_OBJ(bt2_shared); + HDassert(shared); + + if(bt2->depth>0) { + H5B2_internal_t *old_int=NULL, *new_int=NULL; /* Pointers to old & new internal nodes */ + H5B2_node_ptr_t new_int_ptr; /* Node pointer to manage new internal node */ + + /* Create new internal node */ + new_int_ptr.all_nrec=new_int_ptr.node_nrec=0; + if(H5B2_create_internal(f, dxpl_id, bt2_shared, &new_int_ptr)<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new internal node") + + /* Setup information for unlocking child nodes */ + child_class = H5AC_BT2_INT; + left_addr = bt2->root.addr; + right_addr = new_int_ptr.addr; + + /* Protect both leafs */ + if (NULL == (old_int = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, left_addr, &(bt2->root.node_nrec), bt2_shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") + if (NULL == (new_int = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, right_addr, &(new_int_ptr.node_nrec), bt2_shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") + + /* More setup for child nodes */ + left_child = old_int; + right_child = new_int; + left_nrec = &(old_int->nrec); + right_nrec = &(new_int->nrec); + left_native = old_int->int_native; + right_native = new_int->int_native; + left_node_ptrs = old_int->node_ptrs; + right_node_ptrs = new_int->node_ptrs; + } /* end if */ + else { + H5B2_leaf_t *old_leaf=NULL, *new_leaf=NULL; /* Pointers to old & new leaf nodes */ + H5B2_node_ptr_t new_leaf_ptr; /* Node pointer to manage new leaf node */ + + /* Create new leaf node */ + new_leaf_ptr.all_nrec=new_leaf_ptr.node_nrec=0; + if(H5B2_create_leaf(f, dxpl_id, bt2_shared, &new_leaf_ptr)<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new leaf node") + + /* Setup information for unlocking child nodes */ + child_class = H5AC_BT2_LEAF; + left_addr = bt2->root.addr; + right_addr = new_leaf_ptr.addr; + + /* Protect both leafs */ + if (NULL == (old_leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, left_addr, &(bt2->root.node_nrec), bt2_shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") + if (NULL == (new_leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, right_addr, &(new_leaf_ptr.node_nrec), bt2_shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") + + /* More setup for child nodes */ + left_child = old_leaf; + right_child = new_leaf; + left_nrec = &(old_leaf->nrec); + right_nrec = &(new_leaf->nrec); + left_native = old_leaf->leaf_native; + right_native = new_leaf->leaf_native; + } /* end if */ + + /* Set the old number of records in root node */ + old_root_nrec = bt2->root.node_nrec; + + /* Determine "middle" record to promote to new root */ + mid_record = old_root_nrec/2; + + /* Copy "upper half" of records to new child */ + HDmemcpy(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(left_native,shared,mid_record+1),shared->type->nrec_size*(old_root_nrec-(mid_record+1))); + + /* Copy "upper half" of format root's node pointers, if the children of the root are internal nodes */ + if(bt2->depth>0) + HDmemcpy(&(right_node_ptrs[0]),&(left_node_ptrs[mid_record+1]),sizeof(H5B2_node_ptr_t)*(old_root_nrec-mid_record)); + + /* Create new internal node to use as root */ + if(H5B2_create_internal(f, dxpl_id, bt2_shared, &(bt2->root))<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new internal node") + + /* Protect new internal node */ + if (NULL == (new_root = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, bt2->root.addr, &(bt2->root.node_nrec), bt2_shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") + + /* Copy "middle" record to new internal node */ + HDmemcpy(H5B2_INT_NREC(new_root,shared,0),H5B2_NAT_NREC(left_native,shared,mid_record),shared->type->nrec_size); + + /* Set internal node pointers to child nodes */ + new_root->node_ptrs[0].addr = left_addr; + new_root->node_ptrs[1].addr = right_addr; + + /* Update record counts in child nodes */ + new_root->node_ptrs[0].node_nrec = *left_nrec = mid_record; + new_root->node_ptrs[1].node_nrec = *right_nrec = old_root_nrec-(mid_record+1); + + /* Determine total number of records in new child nodes */ + if(bt2->depth>0) { + unsigned u; /* Local index variable */ + hsize_t new_left_all_nrec; /* New total number of records in left child */ + hsize_t new_right_all_nrec; /* New total number of records in right child */ + + /* Compute total of all records in each child node */ + new_left_all_nrec = new_root->node_ptrs[0].node_nrec; + for(u=0; u<(*left_nrec+1); u++) + new_left_all_nrec += left_node_ptrs[u].all_nrec; + + new_right_all_nrec = new_root->node_ptrs[1].node_nrec; + for(u=0; u<(*right_nrec+1); u++) + new_right_all_nrec += right_node_ptrs[u].all_nrec; + + new_root->node_ptrs[0].all_nrec = new_left_all_nrec; + new_root->node_ptrs[1].all_nrec = new_right_all_nrec; + } /* end if */ + else { + new_root->node_ptrs[0].all_nrec = new_root->node_ptrs[0].node_nrec; + new_root->node_ptrs[1].all_nrec = new_root->node_ptrs[1].node_nrec; + } /* end else */ + + /* Update record count in new internal node */ + new_root->nrec = 1; + +#ifdef H5B2_DEBUG + H5B2_assert_internal(bt2->root.all_nrec,shared,new_root); + if(bt2->depth>0) { + H5B2_assert_internal2(new_root->node_ptrs[0].all_nrec,shared,left_child,right_child); + H5B2_assert_internal2(new_root->node_ptrs[1].all_nrec,shared,right_child,left_child); + } /* end if */ + else { + H5B2_assert_leaf2(shared,left_child,right_child); + H5B2_assert_leaf(shared,right_child); + } /* end else */ +#endif /* H5B2_DEBUG */ + /* Release new internal node (marked as dirty) */ + if (H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, bt2->root.addr, new_root, H5AC__DIRTIED_FLAG) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree internal node") + + /* Release child nodes (marked as dirty) */ + if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree leaf node") + if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree leaf node") + + /* Update depth of B-tree */ + bt2->depth++; + + /* Update pointer to B-tree's root node to pointer to new internal node */ + bt2->root.node_nrec = 1; + + /* Mark B-tree header as dirty */ + *bt2_flags_ptr |= H5AC__DIRTIED_FLAG; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5B2_split_root */ + + +/*------------------------------------------------------------------------- + * Function: H5B2_redistribute2 + * + * Purpose: Redistribute records between two nodes + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 9 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5B2_redistribute2(H5F_t *f, hid_t dxpl_id, unsigned depth, H5B2_internal_t *internal, unsigned idx) +{ + const H5AC_class_t *child_class; /* Pointer to child node's class info */ + haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */ + void *left_child, *right_child; /* Pointers to child nodes */ + unsigned *left_nrec, *right_nrec; /* Pointers to child # of records */ + uint8_t *left_native, *right_native; /* Pointers to childs' native records */ + H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */ + H5B2_shared_t *shared; /* B-tree's shared info */ + hssize_t left_moved_nrec=0, right_moved_nrec=0; /* Number of records moved, for internal redistrib */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5B2_redistribute2) + + HDassert(f); + HDassert(internal); + + /* Get the pointer to the shared B-tree info */ + shared=H5RC_GET_OBJ(internal->shared); + HDassert(shared); + + /* Check for the kind of B-tree node to redistribute */ + if(depth>1) { + H5B2_internal_t *left_internal; /* Pointer to left internal node */ + H5B2_internal_t *right_internal; /* Pointer to right internal node */ + + /* Setup information for unlocking child nodes */ + child_class = H5AC_BT2_INT; + left_addr = internal->node_ptrs[idx].addr; + right_addr = internal->node_ptrs[idx+1].addr; + + /* Lock left & right B-tree child nodes */ + if (NULL == (left_internal = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") + if (NULL == (right_internal = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") + + /* More setup for child nodes */ + left_child = left_internal; + right_child = right_internal; + left_nrec = &(left_internal->nrec); + right_nrec = &(right_internal->nrec); + left_native = left_internal->int_native; + right_native = right_internal->int_native; + left_node_ptrs = left_internal->node_ptrs; + right_node_ptrs = right_internal->node_ptrs; + } /* end if */ + else { + H5B2_leaf_t *left_leaf; /* Pointer to left leaf node */ + H5B2_leaf_t *right_leaf; /* Pointer to right leaf node */ + + /* Setup information for unlocking child nodes */ + child_class = H5AC_BT2_LEAF; + left_addr = internal->node_ptrs[idx].addr; + right_addr = internal->node_ptrs[idx+1].addr; + + /* Lock left & right B-tree child nodes */ + if (NULL == (left_leaf = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") + if (NULL == (right_leaf = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") + + /* More setup for child nodes */ + left_child = left_leaf; + right_child = right_leaf; + left_nrec = &(left_leaf->nrec); + right_nrec = &(right_leaf->nrec); + left_native = left_leaf->leaf_native; + right_native = right_leaf->leaf_native; + } /* end else */ + +#ifdef H5B2_DEBUG + H5B2_assert_internal((hsize_t)0,shared,internal); + if(depth>1) { + H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,left_child,right_child); + H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,right_child,left_child); + } /* end if */ + else { + H5B2_assert_leaf2(shared,left_child,right_child); + H5B2_assert_leaf(shared,right_child); + } /* end else */ +#endif /* H5B2_DEBUG */ + + /* Determine whether to shuffle records left or right */ + if(*left_nrec<*right_nrec) { + /* Moving record from right node to left */ + + unsigned new_right_nrec = (*left_nrec+*right_nrec)/2; /* New number of records for right child */ + unsigned move_nrec = *right_nrec - new_right_nrec; /* Number of records to move from right node to left */ + + /* Copy record from parent node down into left child */ + HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size); + + /* See if we need to move records from right node */ + if(move_nrec>1) + HDmemcpy(H5B2_NAT_NREC(left_native,shared,(*left_nrec+1)),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(move_nrec-1)); + + /* Move record from right node into parent node */ + HDmemcpy(H5B2_INT_NREC(internal,shared,idx),H5B2_NAT_NREC(right_native,shared,(move_nrec-1)),shared->type->nrec_size); + + /* Slide records in right node down */ + HDmemmove(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(right_native,shared,move_nrec),shared->type->nrec_size*new_right_nrec); + + /* Handle node pointers, if we have an internal node */ + if(depth>1) { + hsize_t moved_nrec=move_nrec; /* Total number of records moved, for internal redistrib */ + unsigned u; /* Local index variable */ + + /* Count the number of records being moved */ + for(u=0; u<move_nrec; u++) + moved_nrec += right_node_ptrs[u].all_nrec; + left_moved_nrec = moved_nrec; + right_moved_nrec -= moved_nrec; + + /* Copy node pointers from right node to left */ + HDmemcpy(&(left_node_ptrs[*left_nrec+1]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*move_nrec); + + /* Slide node pointers in right node down */ + HDmemmove(&(right_node_ptrs[0]),&(right_node_ptrs[move_nrec]),sizeof(H5B2_node_ptr_t)*(new_right_nrec+1)); + } /* end if */ + + /* Update number of records in child nodes */ + *left_nrec += move_nrec; + *right_nrec = new_right_nrec; + } /* end if */ + else { + /* Moving record from left node to right */ + + unsigned new_left_nrec = (*left_nrec+*right_nrec)/2; /* New number of records for left child */ + unsigned move_nrec = *left_nrec - new_left_nrec; /* Number of records to move from left node to right */ + + /* Slide records in right node up */ + HDmemmove(H5B2_NAT_NREC(right_native,shared,move_nrec), + H5B2_NAT_NREC(right_native,shared,0), + shared->type->nrec_size*(*right_nrec)); + + /* Copy record from parent node down into right child */ + HDmemcpy(H5B2_NAT_NREC(right_native,shared,(move_nrec-1)),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size); + + /* See if we need to move records from left node */ + if(move_nrec>1) + HDmemcpy(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(left_native,shared,((*left_nrec-move_nrec)+1)),shared->type->nrec_size*(move_nrec-1)); + + /* Move record from left node into parent node */ + HDmemcpy(H5B2_INT_NREC(internal,shared,idx),H5B2_NAT_NREC(left_native,shared,(*left_nrec-move_nrec)),shared->type->nrec_size); + + /* Handle node pointers, if we have an internal node */ + if(depth>1) { + hsize_t moved_nrec=move_nrec; /* Total number of records moved, for internal redistrib */ + unsigned u; /* Local index variable */ + + /* Slide node pointers in right node up */ + HDmemmove(&(right_node_ptrs[move_nrec]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*(*right_nrec+1)); + + /* Copy node pointers from left node to right */ + HDmemcpy(&(right_node_ptrs[0]),&(left_node_ptrs[new_left_nrec+1]),sizeof(H5B2_node_ptr_t)*move_nrec); + + /* Count the number of records being moved */ + for(u=0; u<move_nrec; u++) + moved_nrec += right_node_ptrs[u].all_nrec; + left_moved_nrec -= moved_nrec; + right_moved_nrec = moved_nrec; + } /* end if */ + + /* Update number of records in child nodes */ + *left_nrec = new_left_nrec; + *right_nrec += move_nrec; + } /* end else */ + + /* Update # of records in child nodes */ + internal->node_ptrs[idx].node_nrec = *left_nrec; + internal->node_ptrs[idx+1].node_nrec = *right_nrec; + + /* Update total # of records in child B-trees */ + if(depth>1) { + internal->node_ptrs[idx].all_nrec += left_moved_nrec; + internal->node_ptrs[idx+1].all_nrec += right_moved_nrec; + } /* end if */ + else { + internal->node_ptrs[idx].all_nrec = internal->node_ptrs[idx].node_nrec; + internal->node_ptrs[idx+1].all_nrec = internal->node_ptrs[idx+1].node_nrec; + } /* end else */ + +#ifdef H5B2_DEBUG + H5B2_assert_internal((hsize_t)0,shared,internal); + if(depth>1) { + H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,left_child,right_child); + H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,right_child,left_child); + } /* end if */ + else { + H5B2_assert_leaf2(shared,left_child,right_child); + H5B2_assert_leaf(shared,right_child); + } /* end else */ +#endif /* H5B2_DEBUG */ + + /* Release child nodes (marked as dirty) */ + if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") + if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5B2_redistribute2 */ + + +/*------------------------------------------------------------------------- + * Function: H5B2_split2 + * + * Purpose: Perform a 2->3 node split + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 9 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5B2_split2(H5F_t *f, hid_t dxpl_id, unsigned depth, H5B2_node_ptr_t *curr_node_ptr, + unsigned *parent_cache_info_flags_ptr, H5B2_internal_t *internal, + unsigned *internal_flags_ptr, unsigned idx) +{ + const H5AC_class_t *child_class; /* Pointer to child node's class info */ + haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */ + haddr_t middle_addr; /* Address of middle child node */ + void *left_child, *right_child; /* Pointers to left & right child nodes */ + void *middle_child; /* Pointer to middle child node */ + unsigned *left_nrec, *right_nrec; /* Pointers to left & right child # of records */ + unsigned *middle_nrec; /* Pointer to middle child # of records */ + uint8_t *left_native, *right_native; /* Pointers to left & right children's native records */ + uint8_t *middle_native; /* Pointer to middle child's native records */ + H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */ + H5B2_node_ptr_t *middle_node_ptrs=NULL;/* Pointers to childs' node pointer info */ + H5B2_shared_t *shared; /* B-tree's shared info */ + hssize_t left_moved_nrec=0, right_moved_nrec=0; /* Number of records moved, for internal split */ + hsize_t middle_moved_nrec=0; /* Number of records moved, for internal split */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5B2_split2) + + HDassert(f); + HDassert(parent_cache_info_flags_ptr); + HDassert(internal); + HDassert(internal_flags_ptr); + + /* Get the pointer to the shared B-tree info */ + shared=H5RC_GET_OBJ(internal->shared); + HDassert(shared); + + /* Slide records in parent node up one space, to make room for promoted record */ + HDmemmove(H5B2_INT_NREC(internal,shared,idx+2),H5B2_INT_NREC(internal,shared,idx+1),shared->type->nrec_size*(internal->nrec-(idx+1))); + HDmemmove(&(internal->node_ptrs[idx+2]),&(internal->node_ptrs[idx+1]),sizeof(H5B2_node_ptr_t)*(internal->nrec-idx)); + + /* Check for the kind of B-tree node to split */ + if(depth>1) { + H5B2_internal_t *left_internal; /* Pointer to left internal node */ + H5B2_internal_t *middle_internal; /* Pointer to middle internal node */ + H5B2_internal_t *right_internal; /* Pointer to right internal node */ + + /* Setup information for unlocking child nodes */ + child_class = H5AC_BT2_INT; + left_addr = internal->node_ptrs[idx].addr; + right_addr = internal->node_ptrs[idx+2].addr; + + /* Lock left & right B-tree child nodes */ + if (NULL == (left_internal = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") + if (NULL == (right_internal = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+2].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") + + /* Create new empty "middle" internal node */ + internal->node_ptrs[idx+1].all_nrec=internal->node_ptrs[idx+1].node_nrec=0; + if(H5B2_create_internal(f, dxpl_id, internal->shared, &(internal->node_ptrs[idx+1]))<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new internal node") + + /* Setup information for unlocking middle child node */ + middle_addr = internal->node_ptrs[idx+1].addr; + + /* Lock "middle" internal node */ + if (NULL == (middle_internal = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") + + /* More setup for accessing child node information */ + left_child = left_internal; + middle_child = middle_internal; + right_child = right_internal; + left_nrec = &(left_internal->nrec); + middle_nrec = &(middle_internal->nrec); + right_nrec = &(right_internal->nrec); + left_native = left_internal->int_native; + middle_native = middle_internal->int_native; + right_native = right_internal->int_native; + left_node_ptrs = left_internal->node_ptrs; + middle_node_ptrs = middle_internal->node_ptrs; + right_node_ptrs = right_internal->node_ptrs; + } /* end if */ + else { + H5B2_leaf_t *left_leaf; /* Pointer to left leaf node */ + H5B2_leaf_t *middle_leaf; /* Pointer to middle leaf node */ + H5B2_leaf_t *right_leaf; /* Pointer to right leaf node */ + + /* Setup information for unlocking child nodes */ + child_class = H5AC_BT2_LEAF; + left_addr = internal->node_ptrs[idx].addr; + right_addr = internal->node_ptrs[idx+2].addr; + + /* Lock left & right B-tree child nodes */ + if (NULL == (left_leaf = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") + if (NULL == (right_leaf = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+2].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") + + /* Create new empty "middle" leaf node */ + internal->node_ptrs[idx+1].all_nrec=internal->node_ptrs[idx+1].node_nrec=0; + if(H5B2_create_leaf(f, dxpl_id, internal->shared, &(internal->node_ptrs[idx+1]))<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new leaf node") + + /* Setup information for unlocking middle child node */ + middle_addr = internal->node_ptrs[idx+1].addr; + + /* Lock "middle" leaf node */ + if (NULL == (middle_leaf = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") + + /* More setup for accessing child node information */ + left_child = left_leaf; + middle_child = middle_leaf; + right_child = right_leaf; + left_nrec = &(left_leaf->nrec); + middle_nrec = &(middle_leaf->nrec); + right_nrec = &(right_leaf->nrec); + left_native = left_leaf->leaf_native; + middle_native = middle_leaf->leaf_native; + right_native = right_leaf->leaf_native; + } /* end else */ + + /* Redistribute records */ + { + /* Compute new # of records in each node */ + unsigned total_nrec = *left_nrec + *right_nrec + 1; + unsigned new_middle_nrec = (total_nrec-2)/3; + unsigned new_left_nrec = ((total_nrec-2)-new_middle_nrec)/2; + unsigned new_right_nrec = (total_nrec-2)-(new_left_nrec+new_middle_nrec); + + /* Fill new middle node */ + { + unsigned curr_middle_idx=0; + + /* Copy record(s) from left node to proper location */ + if(new_left_nrec<(*left_nrec-1)) { + curr_middle_idx=*left_nrec-(new_left_nrec+1); + HDmemcpy(H5B2_NAT_NREC(middle_native,shared,0),H5B2_NAT_NREC(left_native,shared,(new_left_nrec+1)),shared->type->nrec_size*curr_middle_idx); + } /* end if */ + + /* Copy record from parent node to proper location */ + HDmemcpy(H5B2_NAT_NREC(middle_native,shared,curr_middle_idx),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size); + curr_middle_idx++; + + /* Copy record(s) from right node to proper location */ + if(new_right_nrec<(*right_nrec-1)) + HDmemcpy(H5B2_NAT_NREC(middle_native,shared,curr_middle_idx),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(*right_nrec-(new_right_nrec+1))); + + /* Copy node pointers from left and right nodes into middle node */ + if(depth>1) { + hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */ + unsigned move_nptrs; /* Number of node pointers to move */ + unsigned u; /* Local index variable */ + + /* Start tracking the total number of records in middle node */ + middle_moved_nrec = new_middle_nrec; + + /* Copy node pointers from left node */ + move_nptrs = (*left_nrec-new_left_nrec); + HDmemcpy(&(middle_node_ptrs[0]),&(left_node_ptrs[new_left_nrec+1]),sizeof(H5B2_node_ptr_t)*move_nptrs); + + /* Count the number of records being moved from the left node */ + for(u=0, moved_nrec=0; u<move_nptrs; u++) + moved_nrec += middle_node_ptrs[u].all_nrec; + left_moved_nrec -= (moved_nrec+(*left_nrec-new_left_nrec)); + middle_moved_nrec += moved_nrec; + + /* Copy node pointers from right node */ + move_nptrs = (*right_nrec-new_right_nrec); + HDmemcpy(&(middle_node_ptrs[(*left_nrec-new_left_nrec)]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*move_nptrs); + + /* Count the number of records being moved from the right node */ + for(u=0, moved_nrec=0; u<move_nptrs; u++) + moved_nrec += right_node_ptrs[u].all_nrec; + right_moved_nrec -= (moved_nrec+(*right_nrec-new_right_nrec)); + middle_moved_nrec += moved_nrec; + + /* Slide node pointers in right node down */ + HDmemmove(&(right_node_ptrs[0]),&(right_node_ptrs[move_nptrs]),sizeof(H5B2_node_ptr_t)*(new_right_nrec+1)); + } /* end if */ + + } /* end block */ + + /* Update # of records in middle node */ + *middle_nrec=new_middle_nrec; + + /* Promote records to parent node from left & right nodes */ + HDmemcpy(H5B2_INT_NREC(internal,shared,idx),H5B2_NAT_NREC(left_native,shared,new_left_nrec),shared->type->nrec_size); + HDmemcpy(H5B2_INT_NREC(internal,shared,idx+1),H5B2_NAT_NREC(right_native,shared,(*right_nrec-(new_right_nrec+1))),shared->type->nrec_size); + + /* Update # of records in left node */ + *left_nrec = new_left_nrec; + + /* Slide records in right node to proper position */ + HDmemmove(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(right_native,shared,(*right_nrec-new_right_nrec)),shared->type->nrec_size*new_right_nrec); + + /* Update # of records in right node */ + *right_nrec = new_right_nrec; + } /* end block */ + + /* Update # of records in child nodes */ + internal->node_ptrs[idx].node_nrec = *left_nrec; + internal->node_ptrs[idx+1].node_nrec = *middle_nrec; + internal->node_ptrs[idx+2].node_nrec = *right_nrec; + + /* Update total # of records in child B-trees */ + if(depth>1) { + internal->node_ptrs[idx].all_nrec += left_moved_nrec; + internal->node_ptrs[idx+1].all_nrec = middle_moved_nrec; + internal->node_ptrs[idx+2].all_nrec += right_moved_nrec; + } /* end if */ + else { + internal->node_ptrs[idx].all_nrec = internal->node_ptrs[idx].node_nrec; + internal->node_ptrs[idx+1].all_nrec = internal->node_ptrs[idx+1].node_nrec; + internal->node_ptrs[idx+2].all_nrec = internal->node_ptrs[idx+2].node_nrec; + } /* end else */ + + + /* Update # of records in parent node */ + internal->nrec++; + + /* Mark parent as dirty */ + *internal_flags_ptr |= H5AC__DIRTIED_FLAG; + + /* Update grandparent info */ + curr_node_ptr->node_nrec++; + + /* Mark grandparent as dirty */ + *parent_cache_info_flags_ptr |= H5AC__DIRTIED_FLAG; + +#ifdef H5B2_DEBUG + H5B2_assert_internal((hsize_t)0,shared,internal); + if(depth>1) { + H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,left_child,middle_child); + H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,middle_child,left_child); + H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,middle_child,right_child); + H5B2_assert_internal2(internal->node_ptrs[idx+2].all_nrec,shared,right_child,middle_child); + } /* end if */ + else { + H5B2_assert_leaf2(shared,left_child,middle_child); + H5B2_assert_leaf2(shared,middle_child,right_child); + H5B2_assert_leaf(shared,right_child); + } /* end else */ +#endif /* H5B2_DEBUG */ + + /* Unlock child nodes (marked as dirty) */ + if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") + if (H5AC_unprotect(f, dxpl_id, child_class, middle_addr, middle_child, H5AC__DIRTIED_FLAG) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") + if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5B2_split2 */ + + +/*------------------------------------------------------------------------- + * Function: H5B2_redistribute3 + * + * Purpose: Redistribute records between three nodes + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 9 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5B2_redistribute3(H5F_t *f, hid_t dxpl_id, unsigned depth, + H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx) +{ + const H5AC_class_t *child_class; /* Pointer to child node's class info */ + haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */ + haddr_t middle_addr; /* Address of middle child node */ + void *left_child, *right_child; /* Pointers to child nodes */ + void *middle_child; /* Pointers to middle child node */ + unsigned *left_nrec, *right_nrec; /* Pointers to child # of records */ + unsigned *middle_nrec; /* Pointers to middle child # of records */ + uint8_t *left_native, *right_native; /* Pointers to childs' native records */ + uint8_t *middle_native; /* Pointers to middle child's native records */ + H5B2_shared_t *shared; /* B-tree's shared info */ + H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */ + H5B2_node_ptr_t *middle_node_ptrs=NULL;/* Pointers to childs' node pointer info */ + hssize_t left_moved_nrec=0, right_moved_nrec=0; /* Number of records moved, for internal split */ + hssize_t middle_moved_nrec=0; /* Number of records moved, for internal split */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5B2_redistribute3) + + HDassert(f); + HDassert(internal); + HDassert(internal_flags_ptr); + + /* Get the pointer to the shared B-tree info */ + shared=H5RC_GET_OBJ(internal->shared); + HDassert(shared); + + /* Check for the kind of B-tree node to redistribute */ + if(depth>1) { + H5B2_internal_t *left_internal; /* Pointer to left internal node */ + H5B2_internal_t *middle_internal; /* Pointer to middle internal node */ + H5B2_internal_t *right_internal; /* Pointer to right internal node */ + + /* Setup information for unlocking child nodes */ + child_class = H5AC_BT2_INT; + left_addr = internal->node_ptrs[idx-1].addr; + middle_addr = internal->node_ptrs[idx].addr; + right_addr = internal->node_ptrs[idx+1].addr; + + /* Lock B-tree child nodes */ + if (NULL == (left_internal = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx-1].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") + if (NULL == (middle_internal = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") + if (NULL == (right_internal = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") + + /* More setup for child nodes */ + left_child = left_internal; + middle_child = middle_internal; + right_child = right_internal; + left_nrec = &(left_internal->nrec); + middle_nrec = &(middle_internal->nrec); + right_nrec = &(right_internal->nrec); + left_native = left_internal->int_native; + middle_native = middle_internal->int_native; + right_native = right_internal->int_native; + left_node_ptrs = left_internal->node_ptrs; + middle_node_ptrs = middle_internal->node_ptrs; + right_node_ptrs = right_internal->node_ptrs; + } /* end if */ + else { + H5B2_leaf_t *left_leaf; /* Pointer to left leaf node */ + H5B2_leaf_t *middle_leaf; /* Pointer to middle leaf node */ + H5B2_leaf_t *right_leaf; /* Pointer to right leaf node */ + + /* Setup information for unlocking child nodes */ + child_class = H5AC_BT2_LEAF; + left_addr = internal->node_ptrs[idx-1].addr; + middle_addr = internal->node_ptrs[idx].addr; + right_addr = internal->node_ptrs[idx+1].addr; + + /* Lock B-tree child nodes */ + if (NULL == (left_leaf = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx-1].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") + if (NULL == (middle_leaf = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") + if (NULL == (right_leaf = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") + + /* More setup for child nodes */ + left_child = left_leaf; + middle_child = middle_leaf; + right_child = right_leaf; + left_nrec = &(left_leaf->nrec); + middle_nrec = &(middle_leaf->nrec); + right_nrec = &(right_leaf->nrec); + left_native = left_leaf->leaf_native; + middle_native = middle_leaf->leaf_native; + right_native = right_leaf->leaf_native; + } /* end else */ + + /* Redistribute records */ + { + /* Compute new # of records in each node */ + unsigned total_nrec = *left_nrec + *middle_nrec + *right_nrec + 2; + unsigned new_middle_nrec = (total_nrec-2)/3; + unsigned new_left_nrec = ((total_nrec-2)-new_middle_nrec)/2; + unsigned new_right_nrec = (total_nrec-2)-(new_left_nrec+new_middle_nrec); + unsigned curr_middle_nrec = *middle_nrec; + + /* Move records into left node */ + if(new_left_nrec>*left_nrec) { + unsigned moved_middle_nrec=0; /* Number of records moved into left node */ + + /* Move left parent record down to left node */ + HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec),H5B2_INT_NREC(internal,shared,idx-1),shared->type->nrec_size); + + /* Move records from middle node into left node */ + if((new_left_nrec-1)>*left_nrec) { + moved_middle_nrec = new_left_nrec-(*left_nrec+1); + HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec+1),H5B2_NAT_NREC(middle_native,shared,0),shared->type->nrec_size*moved_middle_nrec); + } /* end if */ + + /* Move record from middle node up to parent node */ + HDmemcpy(H5B2_INT_NREC(internal,shared,idx-1),H5B2_NAT_NREC(middle_native,shared,moved_middle_nrec),shared->type->nrec_size); + moved_middle_nrec++; + + /* Slide records in middle node down */ + HDmemmove(H5B2_NAT_NREC(middle_native,shared,0),H5B2_NAT_NREC(middle_native,shared,moved_middle_nrec),shared->type->nrec_size*(*middle_nrec-moved_middle_nrec)); + + /* Move node pointers also if this is an internal node */ + if(depth>1) { + hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */ + unsigned move_nptrs; /* Number of node pointers to move */ + unsigned u; /* Local index variable */ + + /* Move middle node pointers into left node */ + move_nptrs = new_left_nrec - *left_nrec; + HDmemcpy(&(left_node_ptrs[*left_nrec+1]),&(middle_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*move_nptrs); + + /* Count the number of records being moved into the left node */ + for(u=0, moved_nrec=0; u<move_nptrs; u++) + moved_nrec += middle_node_ptrs[u].all_nrec; + left_moved_nrec = moved_nrec+move_nptrs; + middle_moved_nrec -= moved_nrec+move_nptrs; + + /* Slide the node pointers in middle node down */ + HDmemmove(&(middle_node_ptrs[0]),&(middle_node_ptrs[move_nptrs]),sizeof(H5B2_node_ptr_t)*((*middle_nrec-move_nptrs)+1)); + } /* end if */ + + /* Update the current number of records in middle node */ + curr_middle_nrec -= moved_middle_nrec; + } /* end if */ + + /* Move records into right node */ + if(new_right_nrec>*right_nrec) { + unsigned right_nrec_move = new_right_nrec-*right_nrec; /* Number of records to move out of right node */ + + /* Slide records in right node up */ + HDmemmove(H5B2_NAT_NREC(right_native,shared,right_nrec_move),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(*right_nrec)); + + /* Move right parent record down to right node */ + HDmemcpy(H5B2_NAT_NREC(right_native,shared,right_nrec_move-1),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size); + + /* Move records from middle node into right node */ + if(right_nrec_move>1) + HDmemcpy(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(middle_native,shared,((curr_middle_nrec-right_nrec_move)+1)),shared->type->nrec_size*(right_nrec_move-1)); + + /* Move record from middle node up to parent node */ + HDmemcpy(H5B2_INT_NREC(internal,shared,idx),H5B2_NAT_NREC(middle_native,shared,(curr_middle_nrec-right_nrec_move)),shared->type->nrec_size); + + /* Move node pointers also if this is an internal node */ + if(depth>1) { + hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */ + unsigned u; /* Local index variable */ + + /* Slide the node pointers in right node up */ + HDmemmove(&(right_node_ptrs[right_nrec_move]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*(*right_nrec+1)); + + /* Move middle node pointers into right node */ + HDmemcpy(&(right_node_ptrs[0]),&(middle_node_ptrs[(curr_middle_nrec-right_nrec_move)+1]),sizeof(H5B2_node_ptr_t)*right_nrec_move); + + /* Count the number of records being moved into the right node */ + for(u=0, moved_nrec=0; u<right_nrec_move; u++) + moved_nrec += right_node_ptrs[u].all_nrec; + right_moved_nrec = moved_nrec+right_nrec_move; + middle_moved_nrec -= moved_nrec+right_nrec_move; + } /* end if */ + + /* Update the current number of records in middle node */ + curr_middle_nrec -= right_nrec_move; + } /* end if */ + + /* Move records out of left node */ + if(new_left_nrec<*left_nrec) { + unsigned left_nrec_move = *left_nrec-new_left_nrec; /* Number of records to move out of left node */ + + /* Slide middle records up */ + HDmemmove(H5B2_NAT_NREC(middle_native,shared,left_nrec_move),H5B2_NAT_NREC(middle_native,shared,0),shared->type->nrec_size*curr_middle_nrec); + + /* Move left parent record down to middle node */ + HDmemcpy(H5B2_NAT_NREC(middle_native,shared,left_nrec_move-1),H5B2_INT_NREC(internal,shared,idx-1),shared->type->nrec_size); + + /* Move left records to middle node */ + if(left_nrec_move>1) + HDmemmove(H5B2_NAT_NREC(middle_native,shared,0),H5B2_NAT_NREC(left_native,shared,new_left_nrec+1),shared->type->nrec_size*(left_nrec_move-1)); + + /* Move left parent record up from left node */ + HDmemcpy(H5B2_INT_NREC(internal,shared,idx-1),H5B2_NAT_NREC(left_native,shared,new_left_nrec),shared->type->nrec_size); + + /* Move node pointers also if this is an internal node */ + if(depth>1) { + hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */ + unsigned u; /* Local index variable */ + + /* Slide the node pointers in middle node up */ + HDmemmove(&(middle_node_ptrs[left_nrec_move]),&(middle_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*(curr_middle_nrec+1)); + + /* Move left node pointers into middle node */ + HDmemcpy(&(middle_node_ptrs[0]),&(left_node_ptrs[new_left_nrec+1]),sizeof(H5B2_node_ptr_t)*left_nrec_move); + + /* Count the number of records being moved into the left node */ + for(u=0, moved_nrec=0; u<left_nrec_move; u++) + moved_nrec += middle_node_ptrs[u].all_nrec; + left_moved_nrec -= moved_nrec+left_nrec_move; + middle_moved_nrec += moved_nrec+left_nrec_move; + } /* end if */ + + /* Update the current number of records in middle node */ + curr_middle_nrec += left_nrec_move; + } /* end if */ + + /* Move records out of right node */ + if(new_right_nrec<*right_nrec) { + unsigned right_nrec_move = *right_nrec-new_right_nrec; /* Number of records to move out of right node */ + + /* Move right parent record down to middle node */ + HDmemcpy(H5B2_NAT_NREC(middle_native,shared,curr_middle_nrec),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size); + + /* Move right records to middle node */ + HDmemmove(H5B2_NAT_NREC(middle_native,shared,(curr_middle_nrec+1)),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(right_nrec_move-1)); + + /* Move right parent record up from right node */ + HDmemcpy(H5B2_INT_NREC(internal,shared,idx),H5B2_NAT_NREC(right_native,shared,right_nrec_move-1),shared->type->nrec_size); + + /* Slide right records down */ + HDmemmove(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(right_native,shared,right_nrec_move),shared->type->nrec_size*new_right_nrec); + + /* Move node pointers also if this is an internal node */ + if(depth>1) { + hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */ + unsigned u; /* Local index variable */ + + /* Move right node pointers into middle node */ + HDmemcpy(&(middle_node_ptrs[curr_middle_nrec+1]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*right_nrec_move); + + /* Count the number of records being moved into the right node */ + for(u=0, moved_nrec=0; u<right_nrec_move; u++) + moved_nrec += right_node_ptrs[u].all_nrec; + right_moved_nrec -= moved_nrec+right_nrec_move; + middle_moved_nrec += moved_nrec+right_nrec_move; + + /* Slide the node pointers in right node down */ + HDmemmove(&(right_node_ptrs[0]),&(right_node_ptrs[right_nrec_move]),sizeof(H5B2_node_ptr_t)*(new_right_nrec+1)); + } /* end if */ + } /* end if */ + + /* Update # of records in nodes */ + *left_nrec = new_left_nrec; + *middle_nrec = new_middle_nrec; + *right_nrec = new_right_nrec; + } /* end block */ + + /* Update # of records in child nodes */ + internal->node_ptrs[idx-1].node_nrec = *left_nrec; + internal->node_ptrs[idx].node_nrec = *middle_nrec; + internal->node_ptrs[idx+1].node_nrec = *right_nrec; + + /* Update total # of records in child B-trees */ + if(depth>1) { + internal->node_ptrs[idx-1].all_nrec += left_moved_nrec; + internal->node_ptrs[idx].all_nrec += middle_moved_nrec; + internal->node_ptrs[idx+1].all_nrec += right_moved_nrec; + } /* end if */ + else { + internal->node_ptrs[idx-1].all_nrec = internal->node_ptrs[idx-1].node_nrec; + internal->node_ptrs[idx].all_nrec = internal->node_ptrs[idx].node_nrec; + internal->node_ptrs[idx+1].all_nrec = internal->node_ptrs[idx+1].node_nrec; + } /* end else */ + + /* Mark parent as dirty */ + *internal_flags_ptr |= H5AC__DIRTIED_FLAG; + +#ifdef QAK +{ + unsigned u; + + HDfprintf(stderr,"%s: Internal records:\n",FUNC); + for(u=0; u<internal->nrec; u++) { + HDfprintf(stderr,"%s: u=%u\n",FUNC,u); + (shared->type->debug)(stderr,f,dxpl_id,3,4,H5B2_INT_NREC(internal,shared,u),NULL); + } /* end for */ + + HDfprintf(stderr,"%s: Left Child records:\n",FUNC); + for(u=0; u<*left_nrec; u++) { + HDfprintf(stderr,"%s: u=%u\n",FUNC,u); + (shared->type->debug)(stderr,f,dxpl_id,3,4,H5B2_NAT_NREC(left_native,shared,u),NULL); + } /* end for */ + + HDfprintf(stderr,"%s: Middle Child records:\n",FUNC); + for(u=0; u<*middle_nrec; u++) { + HDfprintf(stderr,"%s: u=%u\n",FUNC,u); + (shared->type->debug)(stderr,f,dxpl_id,3,4,H5B2_NAT_NREC(middle_native,shared,u),NULL); + } /* end for */ + + HDfprintf(stderr,"%s: Right Child records:\n",FUNC); + for(u=0; u<*right_nrec; u++) { + HDfprintf(stderr,"%s: u=%u\n",FUNC,u); + (shared->type->debug)(stderr,f,dxpl_id,3,4,H5B2_NAT_NREC(right_native,shared,u),NULL); + } /* end for */ + + for(u=0; u<internal->nrec+1; u++) + HDfprintf(stderr,"%s: internal->node_ptrs[%u]=(%Hu/%u/%a)\n",FUNC,u,internal->node_ptrs[u].all_nrec,internal->node_ptrs[u].node_nrec,internal->node_ptrs[u].addr); + if(depth>1) { + for(u=0; u<*left_nrec+1; u++) + HDfprintf(stderr,"%s: left_node_ptr[%u]=(%Hu/%u/%a)\n",FUNC,u,left_node_ptrs[u].all_nrec,left_node_ptrs[u].node_nrec,left_node_ptrs[u].addr); + for(u=0; u<*middle_nrec+1; u++) + HDfprintf(stderr,"%s: middle_node_ptr[%u]=(%Hu/%u/%a)\n",FUNC,u,middle_node_ptrs[u].all_nrec,middle_node_ptrs[u].node_nrec,middle_node_ptrs[u].addr); + for(u=0; u<*right_nrec+1; u++) + HDfprintf(stderr,"%s: right_node_ptr[%u]=(%Hu/%u/%a)\n",FUNC,u,right_node_ptrs[u].all_nrec,right_node_ptrs[u].node_nrec,right_node_ptrs[u].addr); + } /* end if */ +} +#endif /* QAK */ +#ifdef H5B2_DEBUG + H5B2_assert_internal((hsize_t)0,shared,internal); + if(depth>1) { + H5B2_assert_internal2(internal->node_ptrs[idx-1].all_nrec,shared,left_child,middle_child); + H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,middle_child,left_child); + H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,middle_child,right_child); + H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,right_child,middle_child); + } /* end if */ + else { + H5B2_assert_leaf2(shared,left_child,middle_child); + H5B2_assert_leaf2(shared,middle_child,right_child); + H5B2_assert_leaf(shared,right_child); + } /* end else */ +#endif /* H5B2_DEBUG */ + + /* Unlock child nodes (marked as dirty) */ + if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") + if (H5AC_unprotect(f, dxpl_id, child_class, middle_addr, middle_child, H5AC__DIRTIED_FLAG) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") + if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5B2_redistribute3 */ + + +/*------------------------------------------------------------------------- + * Function: H5B2_split3 + * + * Purpose: Perform a 3->4 node split + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 10 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5B2_split3(H5F_t *f, hid_t dxpl_id, unsigned depth, + H5B2_node_ptr_t *curr_node_ptr, + unsigned *parent_cache_info_flags_ptr, H5B2_internal_t *internal, + unsigned *internal_flags_ptr, unsigned idx) +{ + const H5AC_class_t *child_class; /* Pointer to child node's class info */ + haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */ + haddr_t middle_addr; /* Address of middle child node */ + haddr_t new_addr; /* Address of new child node */ + void *left_child, *right_child; /* Pointers to left & right child nodes */ + void *middle_child; /* Pointer to middle child node */ + void *new_child; /* Pointer to new child node */ + unsigned *left_nrec, *right_nrec; /* Pointers to left & right child # of records */ + unsigned *middle_nrec; /* Pointer to middle child # of records */ + unsigned *new_nrec; /* Pointer to new child # of records */ + uint8_t *left_native, *right_native; /* Pointers to left & right children's native records */ + uint8_t *middle_native; /* Pointer to middle child's native records */ + uint8_t *new_native; /* Pointer to new child's native records */ + H5B2_shared_t *shared; /* B-tree's shared info */ + H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */ + H5B2_node_ptr_t *middle_node_ptrs=NULL;/* Pointers to childs' node pointer info */ + H5B2_node_ptr_t *new_node_ptrs=NULL;/* Pointers to childs' node pointer info */ + hssize_t left_moved_nrec=0, right_moved_nrec=0; /* Number of records moved, for internal split */ + hssize_t middle_moved_nrec=0; /* Number of records moved, for internal split */ + hsize_t new_moved_nrec=0; /* Number of records moved, for internal split */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5B2_split3) + + HDassert(f); + HDassert(internal); + + /* Get the pointer to the shared B-tree info */ + shared=H5RC_GET_OBJ(internal->shared); + HDassert(shared); + + /* Slide records in parent node up one space, to make room for promoted record */ + HDmemmove(H5B2_INT_NREC(internal,shared,idx+2),H5B2_INT_NREC(internal,shared,idx+1),shared->type->nrec_size*(internal->nrec-(idx+1))); + HDmemmove(&(internal->node_ptrs[idx+2]),&(internal->node_ptrs[idx+1]),sizeof(H5B2_node_ptr_t)*(internal->nrec-idx)); + + /* Check for the kind of B-tree node to split */ + if(depth>1) { + H5B2_internal_t *left_internal; /* Pointer to left internal node */ + H5B2_internal_t *right_internal; /* Pointer to right internal node */ + H5B2_internal_t *middle_internal; /* Pointer to middle internal node */ + H5B2_internal_t *new_internal; /* Pointer to new internal node */ + + /* Setup information for unlocking child nodes */ + child_class = H5AC_BT2_INT; + left_addr = internal->node_ptrs[idx-1].addr; + middle_addr = internal->node_ptrs[idx].addr; + right_addr = internal->node_ptrs[idx+2].addr; + + /* Lock left & right B-tree child nodes */ + if (NULL == (left_internal = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx-1].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") + if (NULL == (middle_internal = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") + if (NULL == (right_internal = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+2].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") + + /* Create new empty internal node */ + internal->node_ptrs[idx+1].all_nrec=internal->node_ptrs[idx+1].node_nrec=0; + if(H5B2_create_internal(f, dxpl_id, internal->shared, &(internal->node_ptrs[idx+1]))<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new internal node") + + /* Setup information for unlocking middle child node */ + new_addr = internal->node_ptrs[idx+1].addr; + + /* Lock "new" internal node */ + if (NULL == (new_internal = H5AC_protect(f, dxpl_id, child_class, new_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") + + /* More setup for accessing child node information */ + left_child = left_internal; + middle_child = middle_internal; + new_child = new_internal; + right_child = right_internal; + left_nrec = &(left_internal->nrec); + middle_nrec = &(middle_internal->nrec); + new_nrec = &(new_internal->nrec); + right_nrec = &(right_internal->nrec); + left_native = left_internal->int_native; + middle_native = middle_internal->int_native; + new_native = new_internal->int_native; + right_native = right_internal->int_native; + left_node_ptrs = left_internal->node_ptrs; + middle_node_ptrs = middle_internal->node_ptrs; + right_node_ptrs = right_internal->node_ptrs; + new_node_ptrs = new_internal->node_ptrs; + } /* end if */ + else { + H5B2_leaf_t *left_leaf; /* Pointer to left leaf node */ + H5B2_leaf_t *right_leaf; /* Pointer to right leaf node */ + H5B2_leaf_t *middle_leaf; /* Pointer to middle leaf node */ + H5B2_leaf_t *new_leaf; /* Pointer to new leaf node */ + + /* Setup information for unlocking child nodes */ + child_class = H5AC_BT2_LEAF; + left_addr = internal->node_ptrs[idx-1].addr; + middle_addr = internal->node_ptrs[idx].addr; + right_addr = internal->node_ptrs[idx+2].addr; + + /* Lock left & right B-tree child nodes */ + if (NULL == (left_leaf = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx-1].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") + if (NULL == (middle_leaf = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") + if (NULL == (right_leaf = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+2].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") + + /* Create new empty leaf node */ + internal->node_ptrs[idx+1].all_nrec=internal->node_ptrs[idx+1].node_nrec=0; + if(H5B2_create_leaf(f, dxpl_id, internal->shared, &(internal->node_ptrs[idx+1]))<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new leaf node") + + /* Setup information for unlocking middle child node */ + new_addr = internal->node_ptrs[idx+1].addr; + + /* Lock "new" leaf node */ + if (NULL == (new_leaf = H5AC_protect(f, dxpl_id, child_class, new_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") + + /* More setup for accessing child node information */ + left_child = left_leaf; + middle_child = middle_leaf; + new_child = new_leaf; + right_child = right_leaf; + left_nrec = &(left_leaf->nrec); + middle_nrec = &(middle_leaf->nrec); + new_nrec = &(new_leaf->nrec); + right_nrec = &(right_leaf->nrec); + left_native = left_leaf->leaf_native; + middle_native = middle_leaf->leaf_native; + new_native = new_leaf->leaf_native; + right_native = right_leaf->leaf_native; + } /* end else */ + + /* Redistribute records */ + { + /* Compute new # of records in each node */ + unsigned total_nrec = *left_nrec + *middle_nrec + *right_nrec + 2; + unsigned new_new_nrec = (total_nrec-3)/4; + unsigned new_middle_nrec = ((total_nrec-3)-new_new_nrec)/3; + unsigned new_left_nrec = ((total_nrec-3)-(new_middle_nrec+new_new_nrec))/2; + unsigned new_right_nrec = (total_nrec-3)-(new_left_nrec+new_middle_nrec+new_new_nrec); + + /* Partially fill new node from right node */ + { + unsigned right_nrec_move = *right_nrec-new_right_nrec; + + /* Move right record down from parent into new node */ + HDmemcpy(H5B2_NAT_NREC(new_native,shared,(new_new_nrec-right_nrec_move)),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size); + + /* Move records from right node to new node */ + HDmemcpy(H5B2_NAT_NREC(new_native,shared,((new_new_nrec-right_nrec_move)+1)),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(right_nrec_move-1)); + + /* Move record from right node up to parent node */ + HDmemcpy(H5B2_INT_NREC(internal,shared,idx+1),H5B2_NAT_NREC(right_native,shared,(right_nrec_move-1)),shared->type->nrec_size); + + /* Slide records in right node down */ + HDmemmove(H5B2_NAT_NREC(right_native,shared,0),H5B2_NAT_NREC(right_native,shared,right_nrec_move),shared->type->nrec_size*new_right_nrec); + + /* Move node pointers also if this is an internal node */ + if(depth>1) { + hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */ + unsigned u; /* Local index variable */ + + /* Move right node pointers into new node */ + HDmemcpy(&(new_node_ptrs[(new_new_nrec-right_nrec_move)+1]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*right_nrec_move); + + /* Count the number of records being moved into the new node */ + for(u=0, moved_nrec=0; u<right_nrec_move; u++) + moved_nrec += right_node_ptrs[u].all_nrec; + right_moved_nrec -= (moved_nrec+right_nrec_move); + new_moved_nrec += (moved_nrec+right_nrec_move); + + /* Slide the node pointers in right node down */ + HDmemmove(&(right_node_ptrs[0]),&(right_node_ptrs[right_nrec_move]),sizeof(H5B2_node_ptr_t)*(new_right_nrec+1)); + } /* end if */ + } /* end block */ + + /* Finish filling new node from middle node */ + { + unsigned new_nrec_move = new_new_nrec-(*right_nrec-new_right_nrec); + + /* Move records from middle node to new node */ + HDmemcpy(H5B2_NAT_NREC(new_native,shared,0),H5B2_NAT_NREC(middle_native,shared,(*middle_nrec-new_nrec_move)),shared->type->nrec_size*new_nrec_move); + + /* Move record from middle node up to parent node */ + HDmemcpy(H5B2_INT_NREC(internal,shared,idx),H5B2_NAT_NREC(middle_native,shared,((*middle_nrec-new_nrec_move)-1)),shared->type->nrec_size); + + /* Slide records in middle node up */ + HDmemmove(H5B2_NAT_NREC(middle_native,shared,(new_middle_nrec-((*middle_nrec-new_nrec_move)-1))),H5B2_NAT_NREC(middle_native,shared,0),shared->type->nrec_size*(*middle_nrec-(new_nrec_move+1))); + + /* Move node pointers also if this is an internal node */ + if(depth>1) { + hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */ + unsigned u; /* Local index variable */ + + /* Move middle node pointers into new node */ + HDmemcpy(&(new_node_ptrs[0]),&(middle_node_ptrs[(*middle_nrec-new_nrec_move)]),sizeof(H5B2_node_ptr_t)*(new_nrec_move+1)); + + /* Count the number of records being moved into the new node */ + for(u=0, moved_nrec=0; u<new_nrec_move+1; u++) + moved_nrec += new_node_ptrs[u].all_nrec; + middle_moved_nrec -= (moved_nrec+new_nrec_move+1); + new_moved_nrec += (moved_nrec+new_nrec_move); + + /* Slide the node pointers in middle node up */ + HDmemmove(&(middle_node_ptrs[(new_middle_nrec-((*middle_nrec-new_nrec_move)-1))]),&(middle_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*(*middle_nrec-new_nrec_move)); + } /* end if */ + } /* end block */ + + /* Fill middle node from left node */ + { + unsigned left_nrec_move = *left_nrec - new_left_nrec; + + /* Move record from parent node down to middle node */ + HDmemcpy(H5B2_NAT_NREC(middle_native,shared,(left_nrec_move-1)),H5B2_INT_NREC(internal,shared,idx-1),shared->type->nrec_size); + + /* Move records from left node to middle node */ + HDmemcpy(H5B2_NAT_NREC(middle_native,shared,0),H5B2_NAT_NREC(left_native,shared,(new_left_nrec+1)),shared->type->nrec_size*(left_nrec_move-1)); + + /* Move node pointers also if this is an internal node */ + if(depth>1) { + hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */ + unsigned u; /* Local index variable */ + + /* Move left node pointers into middle node */ + HDmemcpy(&(middle_node_ptrs[0]),&(left_node_ptrs[new_left_nrec+1]),sizeof(H5B2_node_ptr_t)*left_nrec_move); + + /* Count the number of records being moved into the middle node */ + for(u=0, moved_nrec=0; u<left_nrec_move; u++) + moved_nrec += middle_node_ptrs[u].all_nrec; + left_moved_nrec -= (moved_nrec+left_nrec_move); + middle_moved_nrec += (moved_nrec+left_nrec_move); + } /* end if */ + } + + /* Move record from left node to parent node */ + HDmemcpy(H5B2_INT_NREC(internal,shared,idx-1),H5B2_NAT_NREC(left_native,shared,new_left_nrec),shared->type->nrec_size); + + /* Update # of records in nodes */ + *left_nrec = new_left_nrec; + *middle_nrec = new_middle_nrec; + *new_nrec = new_new_nrec; + *right_nrec = new_right_nrec; + } /* end block */ + + /* Update # of records in child nodes */ + internal->node_ptrs[idx-1].node_nrec = *left_nrec; + internal->node_ptrs[idx].node_nrec = *middle_nrec; + internal->node_ptrs[idx+1].node_nrec = *new_nrec; + internal->node_ptrs[idx+2].node_nrec = *right_nrec; + + /* Update total # of records in child B-trees */ + if(depth>1) { + internal->node_ptrs[idx-1].all_nrec += left_moved_nrec; + internal->node_ptrs[idx].all_nrec += middle_moved_nrec; + internal->node_ptrs[idx+1].all_nrec = new_moved_nrec; + internal->node_ptrs[idx+2].all_nrec += right_moved_nrec; + } /* end if */ + else { + internal->node_ptrs[idx-1].all_nrec = internal->node_ptrs[idx-1].node_nrec; + internal->node_ptrs[idx].all_nrec = internal->node_ptrs[idx].node_nrec; + internal->node_ptrs[idx+1].all_nrec = internal->node_ptrs[idx+1].node_nrec; + internal->node_ptrs[idx+2].all_nrec = internal->node_ptrs[idx+2].node_nrec; + } /* end else */ + + /* Update # of records in parent node */ + internal->nrec++; + + /* Mark parent as dirty */ + *internal_flags_ptr |= H5AC__DIRTIED_FLAG; + + /* Update grandparent info */ + curr_node_ptr->node_nrec++; + + /* Mark grandparent as dirty */ + *parent_cache_info_flags_ptr |= H5AC__DIRTIED_FLAG; + +#ifdef H5B2_DEBUG + H5B2_assert_internal((hsize_t)0,shared,internal); + if(depth>1) { + H5B2_assert_internal2(internal->node_ptrs[idx-1].all_nrec,shared,left_child,middle_child); + H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,middle_child,left_child); + H5B2_assert_internal2(internal->node_ptrs[idx].all_nrec,shared,middle_child,new_child); + H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,new_child,middle_child); + H5B2_assert_internal2(internal->node_ptrs[idx+1].all_nrec,shared,new_child,right_child); + H5B2_assert_internal2(internal->node_ptrs[idx+2].all_nrec,shared,right_child,new_child); + } /* end if */ + else { + H5B2_assert_leaf2(shared,left_child,middle_child); + H5B2_assert_leaf2(shared,middle_child,new_child); + H5B2_assert_leaf2(shared,new_child,right_child); + H5B2_assert_leaf(shared,right_child); + } /* end else */ +#endif /* H5B2_DEBUG */ + + /* Unlock child nodes (mark as dirty) */ + if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") + if (H5AC_unprotect(f, dxpl_id, child_class, middle_addr, middle_child, H5AC__DIRTIED_FLAG) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") + if (H5AC_unprotect(f, dxpl_id, child_class, new_addr, new_child, H5AC__DIRTIED_FLAG) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") + if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5B2_split3 */ + + +/*------------------------------------------------------------------------- + * Function: H5B2_merge2 + * + * Purpose: Perform a 2->1 node merge + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 4 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5B2_merge2(H5F_t *f, hid_t dxpl_id, unsigned depth, + H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags_ptr, + H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx) +{ + const H5AC_class_t *child_class; /* Pointer to child node's class info */ + haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */ + void *left_child, *right_child; /* Pointers to left & right child nodes */ + unsigned *left_nrec, *right_nrec; /* Pointers to left & right child # of records */ + uint8_t *left_native, *right_native; /* Pointers to left & right children's native records */ + H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */ + H5B2_shared_t *shared; /* B-tree's shared info */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5B2_merge2) + + HDassert(f); + HDassert(curr_node_ptr); + HDassert(parent_cache_info_flags_ptr); + HDassert(internal); + HDassert(internal_flags_ptr); + + /* Get the pointer to the shared B-tree info */ + shared=H5RC_GET_OBJ(internal->shared); + HDassert(shared); + + /* Check for the kind of B-tree node to split */ + if(depth>1) { + H5B2_internal_t *left_internal; /* Pointer to left internal node */ + H5B2_internal_t *right_internal; /* Pointer to right internal node */ + + /* Setup information for unlocking child nodes */ + child_class = H5AC_BT2_INT; + left_addr = internal->node_ptrs[idx].addr; + right_addr = internal->node_ptrs[idx+1].addr; + + /* Lock left & right B-tree child nodes */ + if (NULL == (left_internal = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") + if (NULL == (right_internal = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") + + /* More setup for accessing child node information */ + left_child = left_internal; + right_child = right_internal; + left_nrec = &(left_internal->nrec); + right_nrec = &(right_internal->nrec); + left_native = left_internal->int_native; + right_native = right_internal->int_native; + left_node_ptrs = left_internal->node_ptrs; + right_node_ptrs = right_internal->node_ptrs; + } /* end if */ + else { + H5B2_leaf_t *left_leaf; /* Pointer to left leaf node */ + H5B2_leaf_t *right_leaf; /* Pointer to right leaf node */ + + /* Setup information for unlocking child nodes */ + child_class = H5AC_BT2_LEAF; + left_addr = internal->node_ptrs[idx].addr; + right_addr = internal->node_ptrs[idx+1].addr; + + /* Lock left & right B-tree child nodes */ + if (NULL == (left_leaf = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") + if (NULL == (right_leaf = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") + + /* More setup for accessing child node information */ + left_child = left_leaf; + right_child = right_leaf; + left_nrec = &(left_leaf->nrec); + right_nrec = &(right_leaf->nrec); + left_native = left_leaf->leaf_native; + right_native = right_leaf->leaf_native; + } /* end else */ + + /* Redistribute records into left node */ + { + /* Copy record from parent node to proper location */ + HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size); + + /* Copy records from right node to left node */ + HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec+1),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(*right_nrec)); + + /* Copy node pointers from right node into left node */ + if(depth>1) + HDmemcpy(&(left_node_ptrs[*left_nrec+1]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*(*right_nrec+1)); + + /* Update # of records in left node */ + *left_nrec += *right_nrec + 1; + } /* end block */ + + /* Update # of records in child nodes */ + internal->node_ptrs[idx].node_nrec = *left_nrec; + + /* Update total # of records in child B-trees */ + internal->node_ptrs[idx].all_nrec += internal->node_ptrs[idx+1].all_nrec + 1; + + /* Slide records in parent node down, to eliminate demoted record */ + if((idx+1) < internal->nrec) { + HDmemmove(H5B2_INT_NREC(internal,shared,idx),H5B2_INT_NREC(internal,shared,idx+1),shared->type->nrec_size*(internal->nrec-(idx+1))); + HDmemmove(&(internal->node_ptrs[idx+1]),&(internal->node_ptrs[idx+2]),sizeof(H5B2_node_ptr_t)*(internal->nrec-(idx+1))); + } /* end if */ + + /* Update # of records in parent node */ + internal->nrec--; + + /* Mark parent as dirty */ + *internal_flags_ptr |= H5AC__DIRTIED_FLAG; + + /* Update grandparent info */ + curr_node_ptr->node_nrec--; + + /* Mark grandparent as dirty */ + *parent_cache_info_flags_ptr |= H5AC__DIRTIED_FLAG; + +#ifdef H5B2_DEBUG + H5B2_assert_internal((hsize_t)0,shared,internal); + if(depth>1) { + H5B2_assert_internal(internal->node_ptrs[idx].all_nrec,shared,left_child); + } /* end if */ + else { + H5B2_assert_leaf(shared,left_child); + } /* end else */ +#endif /* H5B2_DEBUG */ + + /* Unlock left node (marked as dirty) */ + if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") + + /* Delete right node & remove from cache (marked as dirty) */ + if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, right_addr, (hsize_t)shared->node_size)<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node") + if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5B2_merge2 */ + + +/*------------------------------------------------------------------------- + * Function: H5B2_merge3 + * + * Purpose: Perform a 3->2 node merge + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 4 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5B2_merge3(H5F_t *f, hid_t dxpl_id, unsigned depth, + H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags_ptr, + H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx) +{ + const H5AC_class_t *child_class; /* Pointer to child node's class info */ + haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */ + haddr_t middle_addr; /* Address of middle child node */ + void *left_child, *right_child; /* Pointers to left & right child nodes */ + void *middle_child; /* Pointer to middle child node */ + unsigned *left_nrec, *right_nrec; /* Pointers to left & right child # of records */ + unsigned *middle_nrec; /* Pointer to middle child # of records */ + uint8_t *left_native, *right_native; /* Pointers to left & right children's native records */ + uint8_t *middle_native; /* Pointer to middle child's native records */ + H5B2_node_ptr_t *left_node_ptrs=NULL, *right_node_ptrs=NULL;/* Pointers to childs' node pointer info */ + H5B2_node_ptr_t *middle_node_ptrs=NULL;/* Pointer to child's node pointer info */ + H5B2_shared_t *shared; /* B-tree's shared info */ + hsize_t middle_moved_nrec; /* Number of records moved, for internal split */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5B2_merge3) + + HDassert(f); + HDassert(curr_node_ptr); + HDassert(parent_cache_info_flags_ptr); + HDassert(internal); + HDassert(internal_flags_ptr); + + /* Get the pointer to the shared B-tree info */ + shared=H5RC_GET_OBJ(internal->shared); + HDassert(shared); + + /* Check for the kind of B-tree node to split */ + if(depth>1) { + H5B2_internal_t *left_internal; /* Pointer to left internal node */ + H5B2_internal_t *middle_internal; /* Pointer to middle internal node */ + H5B2_internal_t *right_internal; /* Pointer to right internal node */ + + /* Setup information for unlocking child nodes */ + child_class = H5AC_BT2_INT; + left_addr = internal->node_ptrs[idx-1].addr; + middle_addr = internal->node_ptrs[idx].addr; + right_addr = internal->node_ptrs[idx+1].addr; + + /* Lock B-tree child nodes */ + if (NULL == (left_internal = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx-1].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") + if (NULL == (middle_internal = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") + if (NULL == (right_internal = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") + + /* More setup for accessing child node information */ + left_child = left_internal; + middle_child = middle_internal; + right_child = right_internal; + left_nrec = &(left_internal->nrec); + middle_nrec = &(middle_internal->nrec); + right_nrec = &(right_internal->nrec); + left_native = left_internal->int_native; + middle_native = middle_internal->int_native; + right_native = right_internal->int_native; + left_node_ptrs = left_internal->node_ptrs; + middle_node_ptrs = middle_internal->node_ptrs; + right_node_ptrs = right_internal->node_ptrs; + } /* end if */ + else { + H5B2_leaf_t *left_leaf; /* Pointer to left leaf node */ + H5B2_leaf_t *middle_leaf; /* Pointer to middle leaf node */ + H5B2_leaf_t *right_leaf; /* Pointer to right leaf node */ + + /* Setup information for unlocking child nodes */ + child_class = H5AC_BT2_LEAF; + left_addr = internal->node_ptrs[idx-1].addr; + middle_addr = internal->node_ptrs[idx].addr; + right_addr = internal->node_ptrs[idx+1].addr; + + /* Lock B-tree child nodes */ + if (NULL == (left_leaf = H5AC_protect(f, dxpl_id, child_class, left_addr, &(internal->node_ptrs[idx-1].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") + if (NULL == (middle_leaf = H5AC_protect(f, dxpl_id, child_class, middle_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") + if (NULL == (right_leaf = H5AC_protect(f, dxpl_id, child_class, right_addr, &(internal->node_ptrs[idx+1].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") + + /* More setup for accessing child node information */ + left_child = left_leaf; + middle_child = middle_leaf; + right_child = right_leaf; + left_nrec = &(left_leaf->nrec); + middle_nrec = &(middle_leaf->nrec); + right_nrec = &(right_leaf->nrec); + left_native = left_leaf->leaf_native; + middle_native = middle_leaf->leaf_native; + right_native = right_leaf->leaf_native; + } /* end else */ + + /* Redistribute records into left node */ + { + unsigned total_nrec = *left_nrec + *middle_nrec + *right_nrec + 2; + unsigned middle_nrec_move = ((total_nrec - 1) / 2) - *left_nrec; + + /* Set the base number of records moved from middle node */ + middle_moved_nrec = middle_nrec_move; + + /* Copy record from parent node to proper location in left node */ + HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec),H5B2_INT_NREC(internal,shared,idx-1),shared->type->nrec_size); + + /* Copy records from middle node to left node */ + HDmemcpy(H5B2_NAT_NREC(left_native,shared,*left_nrec+1),H5B2_NAT_NREC(middle_native,shared,0),shared->type->nrec_size*(middle_nrec_move-1)); + + /* Copy record from middle node to proper location in parent node */ + HDmemcpy(H5B2_INT_NREC(internal,shared,idx-1),H5B2_NAT_NREC(middle_native,shared,(middle_nrec_move-1)),shared->type->nrec_size); + + /* Slide records in middle node down */ + HDmemmove(H5B2_NAT_NREC(middle_native,shared,0),H5B2_NAT_NREC(middle_native,shared,middle_nrec_move),shared->type->nrec_size*(*middle_nrec-middle_nrec_move)); + + /* Move node pointers also if this is an internal node */ + if(depth>1) { + unsigned u; /* Local index variable */ + + /* Copy node pointers from middle node into left node */ + HDmemcpy(&(left_node_ptrs[*left_nrec+1]),&(middle_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*middle_nrec_move); + + /* Count the number of records being moved into the left node */ + for(u=0; u<middle_nrec_move; u++) + middle_moved_nrec += middle_node_ptrs[u].all_nrec; + + /* Slide the node pointers in right node down */ + HDmemmove(&(middle_node_ptrs[0]),&(middle_node_ptrs[middle_nrec_move]),sizeof(H5B2_node_ptr_t)*((*middle_nrec+1)-middle_nrec_move)); + } /* end if */ + + /* Update # of records in left & middle nodes */ + *left_nrec += middle_nrec_move; + *middle_nrec -= middle_nrec_move; + } /* end block */ + + /* Redistribute records into middle node */ + { + /* Copy record from parent node to proper location in middle node */ + HDmemcpy(H5B2_NAT_NREC(middle_native,shared,*middle_nrec),H5B2_INT_NREC(internal,shared,idx),shared->type->nrec_size); + + /* Copy records from right node to middle node */ + HDmemcpy(H5B2_NAT_NREC(middle_native,shared,*middle_nrec+1),H5B2_NAT_NREC(right_native,shared,0),shared->type->nrec_size*(*right_nrec)); + + /* Move node pointers also if this is an internal node */ + if(depth>1) + /* Copy node pointers from middle node into left node */ + HDmemcpy(&(middle_node_ptrs[*middle_nrec+1]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*(*right_nrec+1)); + + /* Update # of records in middle node */ + *middle_nrec += *right_nrec + 1; + } /* end block */ + + /* Update # of records in child nodes */ + internal->node_ptrs[idx-1].node_nrec = *left_nrec; + internal->node_ptrs[idx].node_nrec = *middle_nrec; + + /* Update total # of records in child B-trees */ + internal->node_ptrs[idx-1].all_nrec += middle_moved_nrec; + internal->node_ptrs[idx].all_nrec += (internal->node_ptrs[idx+1].all_nrec + 1) - middle_moved_nrec; + + /* Slide records in parent node down, to eliminate demoted record */ + if((idx+1) < internal->nrec) { + HDmemmove(H5B2_INT_NREC(internal,shared,idx),H5B2_INT_NREC(internal,shared,idx+1),shared->type->nrec_size*(internal->nrec-(idx+1))); + HDmemmove(&(internal->node_ptrs[idx+1]),&(internal->node_ptrs[idx+2]),sizeof(H5B2_node_ptr_t)*(internal->nrec-(idx+1))); + } /* end if */ + + /* Update # of records in parent node */ + internal->nrec--; + + /* Mark parent as dirty */ + *internal_flags_ptr |= H5AC__DIRTIED_FLAG; + + /* Update grandparent info */ + curr_node_ptr->node_nrec--; + + /* Mark grandparent as dirty */ + *parent_cache_info_flags_ptr |= H5AC__DIRTIED_FLAG; + +#ifdef H5B2_DEBUG + H5B2_assert_internal((hsize_t)0,shared,internal); + if(depth>1) { + H5B2_assert_internal2(internal->node_ptrs[idx-1].all_nrec,shared,left_child,middle_child); + H5B2_assert_internal(internal->node_ptrs[idx].all_nrec,shared,middle_child); + } /* end if */ + else { + H5B2_assert_leaf2(shared,left_child,middle_child); + H5B2_assert_leaf(shared,middle_child); + } /* end else */ +#endif /* H5B2_DEBUG */ + + /* Unlock left & middle nodes (marked as dirty) */ + if (H5AC_unprotect(f, dxpl_id, child_class, left_addr, left_child, H5AC__DIRTIED_FLAG) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") + if (H5AC_unprotect(f, dxpl_id, child_class, middle_addr, middle_child, H5AC__DIRTIED_FLAG) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") + + /* Delete right node & remove from cache (marked as dirty) */ + if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, right_addr, (hsize_t)shared->node_size)<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node") + if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5B2_merge3 */ + + +/*------------------------------------------------------------------------- + * Function: H5B2_swap_leaf + * + * Purpose: Swap a record in a node with a record in a leaf node + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 4 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5B2_swap_leaf(H5F_t *f, hid_t dxpl_id, unsigned depth, + H5B2_internal_t *internal, unsigned *internal_flags_ptr, + unsigned idx, void *swap_loc) +{ + const H5AC_class_t *child_class; /* Pointer to child node's class info */ + haddr_t child_addr; /* Address of child node */ + void *child; /* Pointer to child node */ + uint8_t *child_native; /* Pointer to child's native records */ + H5B2_shared_t *shared; /* B-tree's shared info */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5B2_swap_leaf) + + HDassert(f); + HDassert(internal); + HDassert(internal_flags_ptr); + HDassert(idx <= internal->nrec); + + /* Get the pointer to the shared B-tree info */ + shared=H5RC_GET_OBJ(internal->shared); + HDassert(shared); + + /* Check for the kind of B-tree node to swap */ + if(depth>1) { + H5B2_internal_t *child_internal; /* Pointer to internal node */ + + /* Setup information for unlocking child node */ + child_class = H5AC_BT2_INT; + child_addr = internal->node_ptrs[idx].addr; + + /* Lock B-tree child nodes */ + if (NULL == (child_internal = H5AC_protect(f, dxpl_id, child_class, child_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") + + /* More setup for accessing child node information */ + child = child_internal; + child_native = child_internal->int_native; + } /* end if */ + else { + H5B2_leaf_t *child_leaf; /* Pointer to leaf node */ + + /* Setup information for unlocking child nodes */ + child_class = H5AC_BT2_LEAF; + child_addr = internal->node_ptrs[idx].addr; + + /* Lock B-tree child node */ + if (NULL == (child_leaf = H5AC_protect(f, dxpl_id, child_class, child_addr, &(internal->node_ptrs[idx].node_nrec), internal->shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") + + /* More setup for accessing child node information */ + child = child_leaf; + child_native = child_leaf->leaf_native; + } /* end else */ + + /* Swap records (use disk page as temporary buffer) */ + HDmemcpy(shared->page, H5B2_NAT_NREC(child_native,shared,0), shared->type->nrec_size); + HDmemcpy(H5B2_NAT_NREC(child_native,shared,0), swap_loc, shared->type->nrec_size); + HDmemcpy(swap_loc, shared->page, shared->type->nrec_size); + + /* Mark parent as dirty */ + *internal_flags_ptr |= H5AC__DIRTIED_FLAG; + +#ifdef H5B2_DEBUG + H5B2_assert_internal((hsize_t)0,shared,internal); + if(depth>1) + H5B2_assert_internal(internal->node_ptrs[idx].all_nrec,shared,child); + else + H5B2_assert_leaf(shared,child); +#endif /* H5B2_DEBUG */ + + /* Unlock child node */ + if (H5AC_unprotect(f, dxpl_id, child_class, child_addr, child, H5AC__DIRTIED_FLAG) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5B2_swap_leaf */ + + +/*------------------------------------------------------------------------- + * Function: H5B2_insert_leaf + * + * Purpose: Adds a new record to a B-tree leaf node. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 3 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5B2_insert_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, + H5B2_node_ptr_t *curr_node_ptr, void *udata) +{ + H5B2_leaf_t *leaf; /* Pointer to leaf node */ + H5B2_shared_t *shared; /* Pointer to B-tree's shared information */ + int cmp; /* Comparison value of records */ + unsigned idx; /* Location of record which matches key */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT(H5B2_insert_leaf) + + /* Check arguments. */ + HDassert(f); + HDassert(bt2_shared); + HDassert(curr_node_ptr); + HDassert(H5F_addr_defined(curr_node_ptr->addr)); + + /* Lock current B-tree node */ + if (NULL == (leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr->addr, &(curr_node_ptr->node_nrec), bt2_shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") + + /* Get the pointer to the shared B-tree info */ + shared=H5RC_GET_OBJ(bt2_shared); + HDassert(shared); + + /* Must have a leaf node with enough space to insert a record now */ + HDassert(curr_node_ptr->node_nrec < shared->split_leaf_nrec); + + /* Sanity check number of records */ + HDassert(curr_node_ptr->all_nrec == curr_node_ptr->node_nrec); + HDassert(leaf->nrec == curr_node_ptr->node_nrec); + + /* Check for inserting into empty leaf */ + if(leaf->nrec==0) + idx=0; + else { + /* Find correct location to insert this record */ + if((cmp = H5B2_locate_record(shared->type,leaf->nrec,shared->nat_off,leaf->leaf_native,udata,&idx)) == 0) + HGOTO_ERROR(H5E_BTREE, H5E_EXISTS, FAIL, "record is already in B-tree") + if(cmp > 0) + idx++; + + /* Make room for new record */ + if(idx<leaf->nrec) + HDmemmove(H5B2_LEAF_NREC(leaf,shared,idx+1),H5B2_LEAF_NREC(leaf,shared,idx),shared->type->nrec_size*(leaf->nrec-idx)); + } /* end else */ + + /* Make callback to store record in native form */ + if((shared->type->store)(H5B2_LEAF_NREC(leaf,shared,idx),udata)<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into leaf node") + + /* Update record count for node pointer to current node */ + curr_node_ptr->all_nrec++; + curr_node_ptr->node_nrec++; + + /* Update record count for current node */ + leaf->nrec++; + +done: + /* Release the B-tree leaf node (marked as dirty) */ + if (leaf && H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr->addr, leaf, H5AC__DIRTIED_FLAG) < 0) + HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release leaf B-tree node") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5B2_insert_leaf() */ + + +/*------------------------------------------------------------------------- + * Function: H5B2_insert_internal + * + * Purpose: Adds a new record to a B-tree node. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 2 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5B2_insert_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, + unsigned depth, unsigned *parent_cache_info_flags_ptr, + H5B2_node_ptr_t *curr_node_ptr, void *udata) +{ + H5B2_internal_t *internal; /* Pointer to internal node */ + unsigned internal_flags = H5AC__NO_FLAGS_SET; + H5B2_shared_t *shared; /* Pointer to B-tree's shared information */ + unsigned idx; /* Location of record which matches key */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT(H5B2_insert_internal) + + /* Check arguments. */ + HDassert(f); + HDassert(bt2_shared); + HDassert(depth>0); + HDassert(parent_cache_info_flags_ptr); + HDassert(curr_node_ptr); + HDassert(H5F_addr_defined(curr_node_ptr->addr)); + + /* Lock current B-tree node */ + if (NULL == (internal = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr->addr, &(curr_node_ptr->node_nrec), bt2_shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") + + /* Get the pointer to the shared B-tree info */ + shared=H5RC_GET_OBJ(bt2_shared); + HDassert(shared); + +/* Split or redistribute child node pointers, if necessary */ + { + int cmp; /* Comparison value of records */ + unsigned retries; /* Number of times to attempt redistribution */ + size_t split_nrec; /* Number of records to split node at */ + + /* Locate node pointer for child */ + if((cmp=H5B2_locate_record(shared->type,internal->nrec,shared->nat_off,internal->int_native,udata,&idx)) == 0) + HGOTO_ERROR(H5E_BTREE, H5E_EXISTS, FAIL, "record is already in B-tree") + if(cmp>0) + idx++; + + /* Set the number of redistribution retries */ + /* This takes care of the case where a B-tree node needs to be + * redistributed, but redistributing the node causes the index + * for insertion to move to another node, which also needs to be + * redistributed. Now, we loop trying to redistribute and then + * eventually force a split */ + retries = 2; + + /* Determine the correct number of records to split at */ + if(depth==1) + split_nrec = shared->split_leaf_nrec; + else + split_nrec = shared->split_int_nrec; + + /* Preemptively split/redistribute a node we will enter */ + while(internal->node_ptrs[idx].node_nrec == split_nrec) { + /* Attempt to redistribute records among children */ + if(idx==0) { /* Left-most child */ + if(retries>0 && (internal->node_ptrs[idx+1].node_nrec < split_nrec)) { + if(H5B2_redistribute2(f,dxpl_id,depth,internal,idx)<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records") + } /* end if */ + else { + if(H5B2_split2(f,dxpl_id,depth,curr_node_ptr, + parent_cache_info_flags_ptr, internal,&internal_flags,idx)<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to split child node") + } /* end else */ + } /* end if */ + else if(idx==internal->nrec) { /* Right-most child */ + if(retries>0 && (internal->node_ptrs[idx-1].node_nrec < split_nrec)) { + if(H5B2_redistribute2(f,dxpl_id,depth,internal,(idx-1))<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records") + } /* end if */ + else { + if(H5B2_split2(f,dxpl_id,depth,curr_node_ptr, + parent_cache_info_flags_ptr, internal,&internal_flags,(idx-1))<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to split child node") + } /* end else */ + } /* end if */ + else { /* Middle child */ + if(retries>0 && ((internal->node_ptrs[idx+1].node_nrec < split_nrec) || + (internal->node_ptrs[idx-1].node_nrec < split_nrec))) { + if(H5B2_redistribute3(f,dxpl_id,depth,internal,&internal_flags,idx)<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records") + } /* end if */ + else { + if(H5B2_split3(f,dxpl_id,depth,curr_node_ptr, + parent_cache_info_flags_ptr, internal,&internal_flags,idx)<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to split child node") + } /* end else */ + } /* end else */ + + /* Locate node pointer for child (after split/redistribute) */ +/* Actually, this can be easily updated (for 2-node redistrib.) and shouldn't require re-searching */ + if((cmp=H5B2_locate_record(shared->type,internal->nrec,shared->nat_off,internal->int_native,udata,&idx)) == 0) + HGOTO_ERROR(H5E_BTREE, H5E_EXISTS, FAIL, "record is already in B-tree") + if(cmp > 0) + idx++; + + /* Decrement the number of redistribution retries left */ + retries--; + } /* end while */ + } /* end block */ + + /* Attempt to insert node */ + if(depth>1) { + if(H5B2_insert_internal(f, dxpl_id, bt2_shared, depth-1, &internal_flags, &internal->node_ptrs[idx], 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,&internal->node_ptrs[idx],udata)<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into B-tree leaf node") + } /* end else */ + + /* Update record count for node pointer to current node */ + curr_node_ptr->all_nrec++; + + /* Mark node as dirty */ + internal_flags |= H5AC__DIRTIED_FLAG; + +done: + /* Release the B-tree internal node */ + if (internal && H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr->addr, internal, internal_flags) < 0) + HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release internal B-tree node") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5B2_insert_internal() */ + + +/*------------------------------------------------------------------------- + * Function: H5B2_create_leaf + * + * Purpose: Creates empty leaf node of a B-tree and update node pointer + * to point to it. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 2 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5B2_create_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, H5B2_node_ptr_t *node_ptr) +{ + H5B2_leaf_t *leaf = NULL; /* Pointer to new leaf node created */ + H5B2_shared_t *shared; /* Shared B-tree information */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT(H5B2_create_leaf) + + /* Check arguments. */ + HDassert(f); + HDassert(bt2_shared); + HDassert(node_ptr); + + /* Allocate memory for leaf information */ + if (NULL==(leaf = H5FL_MALLOC(H5B2_leaf_t))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree leaf info") + + /* Set metadata cache info */ + HDmemset(&leaf->cache_info,0,sizeof(H5AC_info_t)); + + /* Share common B-tree information */ + leaf->shared = bt2_shared; + H5RC_INC(leaf->shared); + + /* Get the pointer to the shared B-tree info */ + shared=H5RC_GET_OBJ(leaf->shared); + HDassert(shared); + + /* Allocate space for the native keys in memory */ + if((leaf->leaf_native=H5FL_FAC_MALLOC(shared->leaf_fac))==NULL) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree leaf native keys") +#ifdef H5_USING_PURIFY +HDmemset(leaf->leaf_native,0,shared->type->nrec_size*shared->leaf_nrec); +#endif /* H5_USING_PURIFY */ + + /* Set number of records */ + leaf->nrec=0; + + /* Allocate space on disk for the leaf */ + if (HADDR_UNDEF==(node_ptr->addr=H5MF_alloc(f, H5FD_MEM_BTREE, dxpl_id, (hsize_t)shared->node_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for B-tree leaf node") + + /* Cache the new B-tree node */ + if (H5AC_set(f, dxpl_id, H5AC_BT2_LEAF, node_ptr->addr, leaf, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "can't add B-tree leaf to cache") + +done: + if (ret_value<0) { + if (leaf) + (void)H5B2_cache_leaf_dest(f,leaf); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5B2_create_leaf() */ + + +/*------------------------------------------------------------------------- + * Function: H5B2_create_internal + * + * Purpose: Creates empty internal node of a B-tree and update node pointer + * to point to it. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 3 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5B2_create_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, H5B2_node_ptr_t *node_ptr) +{ + H5B2_internal_t *internal=NULL; /* Pointer to new internal node created */ + H5B2_shared_t *shared; /* Shared B-tree information */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT(H5B2_create_internal) + + /* Check arguments. */ + HDassert(f); + HDassert(bt2_shared); + HDassert(node_ptr); + + /* Allocate memory for internal node information */ + if (NULL==(internal = H5FL_MALLOC(H5B2_internal_t))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree internal info") + + /* Set metadata cache info */ + HDmemset(&internal->cache_info,0,sizeof(H5AC_info_t)); + + /* Share common B-tree information */ + internal->shared = bt2_shared; + H5RC_INC(internal->shared); + + /* Get the pointer to the shared B-tree info */ + shared=H5RC_GET_OBJ(internal->shared); + HDassert(shared); + + /* Allocate space for the native keys in memory */ + if((internal->int_native=H5FL_FAC_MALLOC(shared->int_fac))==NULL) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree internal native keys") +#ifdef H5_USING_PURIFY +HDmemset(internal->int_native,0,shared->type->nrec_size*shared->internal_nrec); +#endif /* H5_USING_PURIFY */ + + /* Allocate space for the node pointers in memory */ + if((internal->node_ptrs=H5FL_FAC_MALLOC(shared->node_ptr_fac))==NULL) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree internal node pointers") +#ifdef H5_USING_PURIFY +HDmemset(internal->node_ptrs,0,sizeof(H5B2_node_ptr_t)*(shared->internal_nrec+1)); +#endif /* H5_USING_PURIFY */ + + /* Set number of records */ + internal->nrec=0; + + /* Allocate space on disk for the internal node */ + if (HADDR_UNDEF==(node_ptr->addr=H5MF_alloc(f, H5FD_MEM_BTREE, dxpl_id, (hsize_t)shared->node_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for B-tree internal node") + + /* Cache the new B-tree node */ + if (H5AC_set(f, dxpl_id, H5AC_BT2_INT, node_ptr->addr, internal, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "can't add B-tree internal node to cache") + +done: + if (ret_value<0) { + if (internal) + (void)H5B2_cache_internal_dest(f,internal); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5B2_create_internal() */ + + +/*------------------------------------------------------------------------- + * Function: H5B2_iterate_node + * + * Purpose: Iterate over all the records from a B-tree node, 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_node(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, unsigned depth, + const H5B2_node_ptr_t *curr_node, H5B2_operator_t op, void *op_data) +{ + H5B2_shared_t *shared; /* Pointer to B-tree's shared information */ + const H5AC_class_t *curr_node_class=NULL; /* Pointer to current node's class info */ + void *node=NULL; /* Pointers to current node */ + uint8_t *native; /* Pointers to node's native records */ + H5B2_node_ptr_t *node_ptrs=NULL; /* Pointers to node's node pointers */ + unsigned u; /* Local index */ + herr_t ret_value = H5B2_ITER_CONT; + + FUNC_ENTER_NOAPI_NOINIT(H5B2_iterate_node) + + /* Check arguments. */ + HDassert(f); + HDassert(bt2_shared); + HDassert(curr_node); + HDassert(op); + + /* Get the pointer to the shared B-tree info */ + shared=H5RC_GET_OBJ(bt2_shared); + HDassert(shared); + + if(depth>0) { + H5B2_internal_t *internal; /* Pointer to internal node */ + + /* Lock the current B-tree node */ + if (NULL == (internal = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, curr_node->addr, &(curr_node->node_nrec), bt2_shared, H5AC_READ))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") + + /* Set up information about current node */ + curr_node_class = H5AC_BT2_INT; + node = internal; + native = internal->int_native; + node_ptrs = internal->node_ptrs; + } /* end if */ + else { + H5B2_leaf_t *leaf; /* Pointer to leaf node */ + + /* Lock the current B-tree node */ + if (NULL == (leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, curr_node->addr, &(curr_node->node_nrec), bt2_shared, H5AC_READ))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") + + /* Set up information about current node */ + curr_node_class = H5AC_BT2_LEAF; + node = leaf; + native = leaf->leaf_native; + } /* end else */ + + /* Iterate through records */ + for(u=0; u<curr_node->node_nrec && !ret_value; u++) { + /* Descend into child node, if current node is an internal node */ + if(depth>0) { + if((ret_value = H5B2_iterate_node(f,dxpl_id,bt2_shared,depth-1,&(node_ptrs[u]),op,op_data))<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "node iteration failed") + } /* end if */ + + /* Make callback for current record */ + if ((ret_value = (op)(H5B2_NAT_NREC(native,shared,u), op_data)) <0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "iterator function failed") + } /* end for */ + + /* Descend into last child node, if current node is an internal node */ + if(!ret_value && depth>0) { + if((ret_value = H5B2_iterate_node(f,dxpl_id,bt2_shared,depth-1,&(node_ptrs[u]),op,op_data))<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "node iteration failed") + } /* end if */ + +done: + /* Unlock current node */ + if(node) + if (H5AC_unprotect(f, dxpl_id, curr_node_class, curr_node->addr, node, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5B2_iterate_node() */ + + +/*------------------------------------------------------------------------- + * Function: H5B2_remove_leaf + * + * Purpose: Removes a record from a B-tree leaf node. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 3 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5B2_remove_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, + H5B2_node_ptr_t *curr_node_ptr, void *udata) +{ + H5B2_leaf_t *leaf; /* Pointer to leaf node */ + haddr_t leaf_addr=HADDR_UNDEF; /* Leaf address on disk */ + unsigned leaf_flags=H5AC__NO_FLAGS_SET; /* Flags for unprotecting leaf node */ + H5B2_shared_t *shared; /* Pointer to B-tree's shared information */ + unsigned idx; /* Location of record which matches key */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT(H5B2_remove_leaf) + + /* Check arguments. */ + HDassert(f); + HDassert(bt2_shared); + HDassert(curr_node_ptr); + HDassert(H5F_addr_defined(curr_node_ptr->addr)); + + /* Lock current B-tree node */ + leaf_addr = curr_node_ptr->addr; + if (NULL == (leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, leaf_addr, &(curr_node_ptr->node_nrec), bt2_shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") + + /* Get the pointer to the shared B-tree info */ + shared=H5RC_GET_OBJ(bt2_shared); + HDassert(shared); + + /* Sanity check number of records */ + HDassert(curr_node_ptr->all_nrec == curr_node_ptr->node_nrec); + HDassert(leaf->nrec == curr_node_ptr->node_nrec); + + /* Find correct location to remove this record */ + if(H5B2_locate_record(shared->type,leaf->nrec,shared->nat_off,leaf->leaf_native,udata,&idx) != 0) + HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "record is not in B-tree") + + /* Make callback to retrieve record in native form */ + if((shared->type->retrieve)(udata,H5B2_LEAF_NREC(leaf,shared,idx))<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record into leaf node") + + /* Update number of records in node */ + leaf->nrec--; + + /* Mark leaf node as dirty also */ + leaf_flags |= H5AC__DIRTIED_FLAG; + + if(leaf->nrec > 0) { + /* Pack record out of leaf */ + if(idx<leaf->nrec) + HDmemmove(H5B2_LEAF_NREC(leaf,shared,idx),H5B2_LEAF_NREC(leaf,shared,idx+1),shared->type->nrec_size*(leaf->nrec-idx)); + } /* end if */ + else { + /* Release space for B-tree node on disk */ + if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, leaf_addr, (hsize_t)shared->node_size)<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node") + + /* Let the cache know that the object is deleted */ + leaf_flags |= H5AC__DELETED_FLAG; + + /* Reset address of parent node pointer */ + curr_node_ptr->addr = HADDR_UNDEF; + } /* end else */ + + /* Update record count for parent of leaf node */ + curr_node_ptr->node_nrec--; + +done: + /* Release the B-tree leaf node */ + if (leaf && H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, leaf_addr, leaf, leaf_flags) < 0) + HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release leaf B-tree node") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5B2_remove_leaf() */ + + +/*------------------------------------------------------------------------- + * Function: H5B2_remove_internal + * + * Purpose: Removes a record from a B-tree node. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 3 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5B2_remove_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, + hbool_t *depth_decreased, void *swap_loc, unsigned depth, + H5AC_info_t *parent_cache_info, unsigned *parent_cache_info_flags_ptr, + H5B2_node_ptr_t *curr_node_ptr, void *udata) +{ + H5AC_info_t *new_cache_info; /* Pointer to new cache info */ + unsigned *new_cache_info_flags_ptr = NULL; + H5B2_node_ptr_t *new_node_ptr; /* Pointer to new node pointer */ + H5B2_internal_t *internal; /* Pointer to internal node */ + unsigned internal_flags = H5AC__NO_FLAGS_SET; + haddr_t internal_addr; /* Address of internal node */ + H5B2_shared_t *shared; /* Pointer to B-tree's shared information */ + unsigned idx; /* Location of record which matches key */ + size_t merge_nrec; /* Number of records to merge node at */ + hbool_t collapsed_root = FALSE; /* Whether the root was collapsed */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT(H5B2_remove_internal) + + /* Check arguments. */ + HDassert(f); + HDassert(bt2_shared); + HDassert(depth>0); + HDassert(parent_cache_info); + HDassert(parent_cache_info_flags_ptr); + HDassert(curr_node_ptr); + HDassert(H5F_addr_defined(curr_node_ptr->addr)); + + /* Lock current B-tree node */ + internal_addr = curr_node_ptr->addr; + if (NULL == (internal = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, internal_addr, &(curr_node_ptr->node_nrec), bt2_shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") + + /* Get the pointer to the shared B-tree info */ + shared=H5RC_GET_OBJ(bt2_shared); + HDassert(shared); + + /* Determine the correct number of records to merge at */ + if(depth==1) + merge_nrec = shared->merge_leaf_nrec; + else + merge_nrec = shared->merge_int_nrec; + + /* Check for needing to collapse the root node */ + /* (The root node is the only node allowed to have 1 record) */ + if(internal->nrec == 1 && + ((internal->node_ptrs[0].node_nrec + internal->node_ptrs[1].node_nrec) <= ((merge_nrec * 2) + 1))) { + + /* Merge children of root node */ + if(H5B2_merge2(f,dxpl_id,depth,curr_node_ptr, + parent_cache_info_flags_ptr, internal,&internal_flags,0)<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node") + + /* Release space for root B-tree node on disk */ + if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, internal_addr, (hsize_t)shared->node_size)<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node") + + /* Let the cache know that the object is deleted */ + internal_flags |= H5AC__DELETED_FLAG; + + /* Reset information in parent node pointer */ + curr_node_ptr->addr = internal->node_ptrs[0].addr; + curr_node_ptr->node_nrec = internal->node_ptrs[0].node_nrec; + + /* Indicate that the level of the B-tree decreased */ + *depth_decreased = TRUE; + + /* Set pointers for advancing to child node */ + new_cache_info = parent_cache_info; + new_cache_info_flags_ptr = parent_cache_info_flags_ptr; + new_node_ptr = curr_node_ptr; + + /* Set flag to indicate root was collapsed */ + collapsed_root = TRUE; + } /* end if */ + /* Merge or redistribute child node pointers, if necessary */ + else { + int cmp=0; /* Comparison value of records */ + unsigned retries; /* Number of times to attempt redistribution */ + + /* Locate node pointer for child */ + if(swap_loc) + idx = 0; + else { + cmp=H5B2_locate_record(shared->type,internal->nrec,shared->nat_off,internal->int_native,udata,&idx); + if(cmp >= 0) + idx++; + } /* end else */ + + /* Set the number of redistribution retries */ + /* This takes care of the case where a B-tree node needs to be + * redistributed, but redistributing the node causes the index + * for removal to move to another node, which also needs to be + * redistributed. Now, we loop trying to redistribute and then + * eventually force a merge */ + retries = 2; + + /* Preemptively merge/redistribute a node we will enter */ + while(internal->node_ptrs[idx].node_nrec==merge_nrec) { + /* Attempt to redistribute records among children */ + if(idx==0) { /* Left-most child */ + if(retries>0 && (internal->node_ptrs[idx+1].node_nrec > merge_nrec)) { + if(H5B2_redistribute2(f,dxpl_id,depth,internal,idx)<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records") + } /* end if */ + else { + if(H5B2_merge2(f,dxpl_id,depth,curr_node_ptr, + parent_cache_info_flags_ptr, internal,&internal_flags,idx)<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node") + } /* end else */ + } /* end if */ + else if(idx==internal->nrec) { /* Right-most child */ + if(retries>0 && (internal->node_ptrs[idx-1].node_nrec > merge_nrec)) { + if(H5B2_redistribute2(f,dxpl_id,depth,internal,(idx-1))<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records") + } /* end if */ + else { + if(H5B2_merge2(f,dxpl_id,depth,curr_node_ptr, + parent_cache_info_flags_ptr, internal,&internal_flags,(idx-1))<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node") + } /* end else */ + } /* end if */ + else { /* Middle child */ + if(retries>0 && ((internal->node_ptrs[idx+1].node_nrec > merge_nrec) || + (internal->node_ptrs[idx-1].node_nrec > merge_nrec))) { + if(H5B2_redistribute3(f,dxpl_id,depth,internal,&internal_flags,idx)<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records") + } /* end if */ + else { + if(H5B2_merge3(f,dxpl_id,depth,curr_node_ptr, + parent_cache_info_flags_ptr,internal, &internal_flags,idx)<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node") + } /* end else */ + } /* end else */ + + /* Locate node pointer for child (after merge/redistribute) */ + if(swap_loc) + idx = 0; + else { +/* Actually, this can be easily updated (for 2-node redistrib.) and shouldn't require re-searching */ + cmp=H5B2_locate_record(shared->type,internal->nrec,shared->nat_off,internal->int_native,udata,&idx); + if(cmp >= 0) + idx++; + } /* end else */ + + /* Decrement the number of redistribution retries left */ + retries--; + } /* end while */ + + /* Handle deleting a record from an internal node */ + if(!swap_loc && cmp==0) + swap_loc = H5B2_INT_NREC(internal,shared,idx-1); + + /* Swap record to delete with record from leaf, if we are the last internal node */ + if(swap_loc && depth==1) + if(H5B2_swap_leaf(f,dxpl_id,depth,internal,&internal_flags,idx,swap_loc) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTSWAP, FAIL, "Can't swap records in B-tree") + + /* Set pointers for advancing to child node */ + new_cache_info_flags_ptr = &internal_flags; + new_cache_info = &internal->cache_info; + new_node_ptr = &internal->node_ptrs[idx]; + } /* end else */ + + /* Attempt to remove node */ + if(depth>1) { + if(H5B2_remove_internal(f,dxpl_id,bt2_shared,depth_decreased, swap_loc, depth-1, + new_cache_info,new_cache_info_flags_ptr,new_node_ptr,udata)<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record from B-tree internal node") + } /* end if */ + else { + if(H5B2_remove_leaf(f,dxpl_id,bt2_shared,new_node_ptr,udata)<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record from B-tree leaf node") + } /* end else */ + + /* Update record count for node pointer to current node */ + if(!collapsed_root) + new_node_ptr->all_nrec--; + + /* Mark node as dirty */ + internal_flags |= H5AC__DIRTIED_FLAG; + +#ifdef H5B2_DEBUG + H5B2_assert_internal((!collapsed_root ? (curr_node_ptr->all_nrec-1) : new_node_ptr->all_nrec),shared,internal); +#endif /* H5B2_DEBUG */ + +done: + /* Release the B-tree internal node */ + if (internal && H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, internal_addr, internal, internal_flags) < 0) + HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release internal B-tree node") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5B2_remove_internal() */ + + +/*------------------------------------------------------------------------- + * Function: H5B2_neighbor_leaf + * + * Purpose: Locate a record relative to the specified information in a + * B-tree leaf node 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 9 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5B2_neighbor_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, + H5B2_node_ptr_t *curr_node_ptr, void *neighbor_loc, + H5B2_compare_t comp, void *udata, H5B2_found_t op, void *op_data) +{ + H5B2_leaf_t *leaf; /* Pointer to leaf node */ + H5B2_shared_t *shared; /* Pointer to B-tree's shared information */ + unsigned idx; /* Location of record which matches key */ + int cmp=0; /* Comparison value of records */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT(H5B2_neighbor_leaf) + + /* Check arguments. */ + HDassert(f); + HDassert(bt2_shared); + HDassert(curr_node_ptr); + HDassert(H5F_addr_defined(curr_node_ptr->addr)); + HDassert(op); + + /* Lock current B-tree 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 leaf node") + + /* Get the pointer to the shared B-tree info */ + shared=H5RC_GET_OBJ(bt2_shared); + HDassert(shared); + + + /* Locate node pointer for child */ + cmp = H5B2_locate_record(shared->type, leaf->nrec, shared->nat_off, leaf->leaf_native, udata, &idx); + if(cmp > 0) + idx++; + else + if(cmp == 0 && comp == H5B2_COMPARE_GREATER) + idx++; + + /* Set the neighbor location, if appropriate */ + if(comp == H5B2_COMPARE_LESS) { + if(idx > 0) + neighbor_loc = H5B2_LEAF_NREC(leaf,shared,idx-1); + } /* end if */ + else { + HDassert(comp == H5B2_COMPARE_GREATER); + + if(idx < leaf->nrec) + neighbor_loc = H5B2_LEAF_NREC(leaf,shared,idx); + } /* end else */ + + /* Make callback if neighbor record has been found */ + if(neighbor_loc) { + /* Make callback for current record */ + if ((op)(neighbor_loc, op_data) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "'found' callback failed for B-tree neighbor operation") + } /* end if */ + else + HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "unable to find neighbor record in B-tree") + +done: + /* Release the B-tree internal node */ + if (leaf && H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr->addr, leaf, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree leaf node") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5B2_neighbor_leaf() */ + + +/*------------------------------------------------------------------------- + * Function: H5B2_neighbor_internal + * + * Purpose: Locate a record relative to the specified information in a + * B-tree internal node 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 9 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5B2_neighbor_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, + unsigned depth, H5B2_node_ptr_t *curr_node_ptr, void *neighbor_loc, + H5B2_compare_t comp, void *udata, H5B2_found_t op, void *op_data) +{ + H5B2_internal_t *internal; /* Pointer to internal node */ + H5B2_shared_t *shared; /* Pointer to B-tree's shared information */ + unsigned idx; /* Location of record which matches key */ + int cmp=0; /* Comparison value of records */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT(H5B2_neighbor_internal) + + /* Check arguments. */ + HDassert(f); + HDassert(bt2_shared); + HDassert(depth>0); + HDassert(curr_node_ptr); + HDassert(H5F_addr_defined(curr_node_ptr->addr)); + HDassert(op); + + /* Lock current B-tree node */ + if (NULL == (internal = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, 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") + + /* Get the pointer to the shared B-tree info */ + shared=H5RC_GET_OBJ(bt2_shared); + HDassert(shared); + + /* 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++; + + /* Set the neighbor location, if appropriate */ + if(comp == H5B2_COMPARE_LESS) { + if(idx > 0) + neighbor_loc = H5B2_INT_NREC(internal,shared,idx-1); + } /* end if */ + else { + HDassert(comp == H5B2_COMPARE_GREATER); + + if(idx < internal->nrec) + neighbor_loc = H5B2_INT_NREC(internal,shared,idx); + } /* end else */ + + /* Attempt to find neighboring record */ + if(depth>1) { + if(H5B2_neighbor_internal(f, dxpl_id, bt2_shared, depth-1, &internal->node_ptrs[idx], neighbor_loc, comp, 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, &internal->node_ptrs[idx], neighbor_loc, comp, 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 internal node */ + if (internal && H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr->addr, internal, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release internal B-tree node") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5B2_neighbor_internal() */ + + +/*------------------------------------------------------------------------- + * Function: H5B2_delete_node + * + * Purpose: Iterate over all the nodes in a B-tree node deleting them + * after they no longer have any children + * + * Return: Value from callback, non-negative on success, negative on error + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 9 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5B2_delete_node(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, unsigned depth, + const H5B2_node_ptr_t *curr_node) +{ + H5B2_shared_t *shared; /* Pointer to B-tree's shared information */ + const H5AC_class_t *curr_node_class=NULL; /* Pointer to current node's class info */ + void *node=NULL; /* Pointers to current node */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT(H5B2_delete_node) + + /* Check arguments. */ + HDassert(f); + HDassert(bt2_shared); + HDassert(curr_node); + + /* Get the pointer to the shared B-tree info */ + shared=H5RC_GET_OBJ(bt2_shared); + HDassert(shared); + + if(depth>0) { + H5B2_internal_t *internal; /* Pointer to internal node */ + unsigned u; /* Local index */ + + /* Lock the current B-tree node */ + if (NULL == (internal = H5AC_protect(f, dxpl_id, H5AC_BT2_INT, curr_node->addr, &(curr_node->node_nrec), bt2_shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node") + + /* Set up information about current node */ + curr_node_class = H5AC_BT2_INT; + node = internal; + + /* Descend into children */ + for(u=0; u<internal->nrec+1; u++) + if(H5B2_delete_node(f, dxpl_id, bt2_shared, depth-1, &(internal->node_ptrs[u]))<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "node descent failed") + } /* end if */ + else { + H5B2_leaf_t *leaf; /* Pointer to leaf node */ + + /* Lock the current B-tree node */ + if (NULL == (leaf = H5AC_protect(f, dxpl_id, H5AC_BT2_LEAF, curr_node->addr, &(curr_node->node_nrec), bt2_shared, H5AC_WRITE))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree leaf node") + + /* Set up information about current node */ + curr_node_class = H5AC_BT2_LEAF; + node = leaf; + } /* end else */ + + /* Release space for current B-tree node on disk */ + if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, curr_node->addr, (hsize_t)shared->node_size)<0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree node") + +done: + /* Unlock & delete current node */ + if(node) + if (H5AC_unprotect(f, dxpl_id, curr_node_class, curr_node->addr, node, H5AC__DELETED_FLAG) < 0) + HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5B2_delete_node() */ + +#ifdef H5B2_DEBUG + +/*------------------------------------------------------------------------- + * Function: H5B2_assert_leaf + * + * Purpose: Verify than a leaf node is mostly sane + * + * Return: Non-negative on success, negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 19 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5B2_assert_leaf(H5B2_shared_t *shared, H5B2_leaf_t *leaf) +{ + unsigned u,v; /* Local index variables */ + + /* General sanity checking on node */ + HDassert(leaf->nrec<=shared->split_leaf_nrec); + + /* Sanity checking on records */ + for(u=0; u<leaf->nrec; u++) + for(v=0; v<u; v++) + HDassert((shared->type->compare)(H5B2_LEAF_NREC(leaf,shared,u), H5B2_LEAF_NREC(leaf,shared,v))>0); + + return(0); +} /* end H5B2_assert_leaf() */ + + +/*------------------------------------------------------------------------- + * Function: H5B2_assert_leaf2 + * + * Purpose: Verify than a leaf node is mostly sane + * + * Return: Non-negative on success, negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 19 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5B2_assert_leaf2(H5B2_shared_t *shared, H5B2_leaf_t *leaf, H5B2_leaf_t *leaf2) +{ + unsigned u,v; /* Local index variables */ + + /* General sanity checking on node */ + HDassert(leaf->nrec<=shared->split_leaf_nrec); + + /* Sanity checking on records */ + for(u=0; u<leaf->nrec; u++) { + HDassert((shared->type->compare)(H5B2_LEAF_NREC(leaf2,shared,0), H5B2_LEAF_NREC(leaf,shared,u))>0); + for(v=0; v<u; v++) + HDassert((shared->type->compare)(H5B2_LEAF_NREC(leaf,shared,u), H5B2_LEAF_NREC(leaf,shared,v))>0); + } /* end for */ + + return(0); +} /* end H5B2_assert_leaf() */ + + +/*------------------------------------------------------------------------- + * Function: H5B2_assert_internal + * + * Purpose: Verify than an internal node is mostly sane + * + * Return: Non-negative on success, negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 19 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5B2_assert_internal(hsize_t parent_all_nrec, H5B2_shared_t *shared, H5B2_internal_t *internal) +{ + hsize_t tot_all_nrec; /* Total number of records at or below this node */ + unsigned u,v; /* Local index variables */ + + /* General sanity checking on node */ + HDassert(internal->nrec<=shared->split_int_nrec); + + /* Sanity checking on records */ + for(u=0; u<internal->nrec; u++) + for(v=0; v<u; v++) + HDassert((shared->type->compare)(H5B2_INT_NREC(internal,shared,u), H5B2_INT_NREC(internal,shared,v))>0); + + /* Sanity checking on node pointers */ + tot_all_nrec=internal->nrec; + for(u=0; u<internal->nrec+1; u++) { + tot_all_nrec += internal->node_ptrs[u].all_nrec; + + HDassert(H5F_addr_defined(internal->node_ptrs[u].addr)); + HDassert(internal->node_ptrs[u].addr>0); + for(v=0; v<u; v++) + HDassert(internal->node_ptrs[u].addr!=internal->node_ptrs[v].addr); + } /* end for */ + + /* Sanity check all_nrec total in parent */ + if(parent_all_nrec>0) + HDassert(tot_all_nrec == parent_all_nrec); + + return(0); +} /* end H5B2_assert_internal() */ + + +/*------------------------------------------------------------------------- + * Function: H5B2_assert_internal2 + * + * Purpose: Verify than internal nodes are mostly sane + * + * Return: Non-negative on success, negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 19 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5B2_assert_internal2(hsize_t parent_all_nrec, H5B2_shared_t *shared, H5B2_internal_t *internal, H5B2_internal_t *internal2) +{ + hsize_t tot_all_nrec; /* Total number of records at or below this node */ + unsigned u,v; /* Local index variables */ + + /* General sanity checking on node */ + HDassert(internal->nrec<=shared->split_int_nrec); + + /* Sanity checking on records */ + for(u=0; u<internal->nrec; u++) + for(v=0; v<u; v++) + HDassert((shared->type->compare)(H5B2_INT_NREC(internal,shared,u), H5B2_INT_NREC(internal,shared,v))>0); + + /* Sanity checking on node pointers */ + tot_all_nrec=internal->nrec; + for(u=0; u<internal->nrec+1; u++) { + tot_all_nrec += internal->node_ptrs[u].all_nrec; + + HDassert(H5F_addr_defined(internal->node_ptrs[u].addr)); + HDassert(internal->node_ptrs[u].addr>0); + for(v=0; v<u; v++) + HDassert(internal->node_ptrs[u].addr!=internal->node_ptrs[v].addr); + for(v=0; v<internal2->nrec+1; v++) + HDassert(internal->node_ptrs[u].addr!=internal2->node_ptrs[v].addr); + } /* end for */ + + /* Sanity check all_nrec total in parent */ + if(parent_all_nrec>0) + HDassert(tot_all_nrec == parent_all_nrec); + + return(0); +} /* end H5B2_assert_internal2() */ +#endif /* H5B2_DEBUG */ + diff --git a/src/H5B2pkg.h b/src/H5B2pkg.h index 4abf5aa..784b1e5 100644 --- a/src/H5B2pkg.h +++ b/src/H5B2pkg.h @@ -184,6 +184,45 @@ H5_DLLVAR const H5B2_class_t H5B2_TEST[1]; H5_DLL herr_t H5B2_shared_init(H5F_t *f, H5B2_t *bt2, const H5B2_class_t *type, size_t node_size, size_t rrec_size, unsigned split_percent, unsigned merge_percent); +/* Routines for allocating nodes */ +H5_DLL herr_t H5B2_split_root(H5F_t *f, hid_t dxpl_id, H5B2_t *bt2, + unsigned *bt2_flags_ptr, H5RC_t *bt2_shared); +H5_DLL herr_t H5B2_create_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, + H5B2_node_ptr_t *node_ptr); + +/* Routines for inserting records */ +H5_DLL herr_t H5B2_insert_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, + unsigned depth, unsigned *parent_cache_info_flags_ptr, + H5B2_node_ptr_t *curr_node_ptr, void *udata); +H5_DLL herr_t H5B2_insert_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, + H5B2_node_ptr_t *curr_node_ptr, void *udata); + +/* Routines for iterating over nodes/records */ +H5_DLL herr_t H5B2_iterate_node(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, + unsigned depth, const H5B2_node_ptr_t *curr_node, H5B2_operator_t op, + void *op_data); + +/* Routines for locating records */ +H5_DLL int H5B2_locate_record(const H5B2_class_t *type, unsigned nrec, + size_t *rec_off, const uint8_t *native, const void *udata, unsigned *idx); +H5_DLL herr_t H5B2_neighbor_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, + unsigned depth, H5B2_node_ptr_t *curr_node_ptr, void *neighbor_loc, + H5B2_compare_t comp, void *udata, H5B2_found_t op, void *op_data); +H5_DLL herr_t H5B2_neighbor_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, + H5B2_node_ptr_t *curr_node_ptr, void *neighbor_loc, + H5B2_compare_t comp, void *udata, H5B2_found_t op, void *op_data); + +/* Routines for removing records */ +H5_DLL herr_t H5B2_remove_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, + hbool_t *depth_decreased, void *swap_loc, unsigned depth, H5AC_info_t *parent_cache_info, + hbool_t * parent_cache_info_dirtied_ptr, H5B2_node_ptr_t *curr_node_ptr, void *udata); +H5_DLL herr_t H5B2_remove_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, + H5B2_node_ptr_t *curr_node_ptr, void *udata); + +/* Routines for deleting nodes */ +H5_DLL herr_t H5B2_delete_node(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, + unsigned depth, const H5B2_node_ptr_t *curr_node); + /* Metadata cache callbacks */ H5_DLL herr_t H5B2_cache_hdr_dest(H5F_t *f, H5B2_t *b); H5_DLL herr_t H5B2_cache_leaf_dest(H5F_t *f, H5B2_leaf_t *l); @@ -56,7 +56,6 @@ /* Local Prototypes */ /********************/ -static herr_t H5HF_shared_free(void *_shared); /*********************/ /* Package Variables */ @@ -75,82 +74,6 @@ H5FL_DEFINE(H5HF_t); /* Local Variables */ /*******************/ -/* Declare a free list to manage the H5HF_shared_t struct */ -H5FL_DEFINE_STATIC(H5HF_shared_t); - - - -/*------------------------------------------------------------------------- - * Function: H5HF_shared_init - * - * Purpose: Allocate & initialize shared fractal heap info - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Feb 24 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5HF_shared_init(H5F_t *f, H5HF_t *fh, H5HF_type_t type) -{ - H5HF_shared_t *shared = NULL; /* Shared fractal heap information */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_shared_init) - - /* Allocate space for the shared information */ - if(NULL == (shared = H5FL_CALLOC(H5HF_shared_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fractal heap shared information") - - /* Set the type of heap address mapping */ - shared->type = type; - - /* Make shared B-tree info reference counted */ - if(NULL == (fh->shared = H5RC_create(shared, H5HF_shared_free))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create ref-count wrapper for shared fractal heap info") - -done: - if(ret_value < 0) - if(shared) - H5HF_shared_free(shared); - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_shared_init() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_shared_free - * - * Purpose: Free shared fractal heap info - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Feb 24 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HF_shared_free(void *_shared) -{ - H5HF_shared_t *shared = (H5HF_shared_t *)_shared; - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI_NOINIT(H5HF_shared_free) - - /* Sanity check */ - HDassert(shared); - - /* Free the shared info itself */ - H5FL_FREE(H5HF_shared_t, shared); - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_shared_free() */ /*------------------------------------------------------------------------- @@ -168,7 +91,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5HF_create(H5F_t *f, hid_t dxpl_id, H5HF_type_t type, haddr_t *addr_p) +H5HF_create(H5F_t *f, hid_t dxpl_id, H5HF_create_t *cparam, haddr_t *addr_p) { H5HF_t *fh = NULL; /* The new fractal heap header information */ herr_t ret_value = SUCCEED; @@ -191,7 +114,7 @@ H5HF_create(H5F_t *f, hid_t dxpl_id, H5HF_type_t type, haddr_t *addr_p) HDmemset(&fh->cache_info, 0, sizeof(H5AC_info_t)); /* Initialize shared fractal heap info */ - if(H5HF_shared_init(f, fh, type) < 0) + if(H5HF_shared_init(fh, cparam) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create shared fractal heap info") /* Allocate space for the header on disk */ @@ -250,7 +173,7 @@ H5HF_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t size, * Load the fractal heap header. */ if(NULL == (fh = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, addr, NULL, NULL, H5AC_WRITE))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load fractal heap header") + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap header") /* Get the pointer to the shared fractal heap info */ shared = H5RC_GET_OBJ(fh->shared); @@ -258,13 +181,29 @@ H5HF_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t size, /* Check if object is large enough to be standalone */ if(size >= shared->standalone_size) { +HDfprintf(stderr, "%s: size = %Zu\n", FUNC, size); +HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "standalone blocks not supported yet") } /* end if */ else { + /* Check if we are in "append only" mode, or if there's enough room for the object */ + if(shared->write_once) { +HDfprintf(stderr, "%s: size = %Zu\n", FUNC, size); +HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "'write once' managed blocks not supported yet") + } /* end if */ + else if(size <= shared->total_man_free) { +HDfprintf(stderr, "%s: size = %Zu\n", FUNC, size); +HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "allocating internal managed blocks not supported yet") + } /* end if */ + else { + /* Allocate space at end of heap */ + if(H5HF_man_alloc_end(shared, size, obj, id) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate space at end of managed blocks") + } /* end else */ } /* end else */ done: if(fh && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, addr, fh, hdr_flags) < 0) - HDONE_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release fractal heap header") + HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap header") FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_insert() */ diff --git a/src/H5HFcache.c b/src/H5HFcache.c index 9544242..c20d05d 100644 --- a/src/H5HFcache.c +++ b/src/H5HFcache.c @@ -107,7 +107,7 @@ H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *ud size_t size; /* Header size */ uint8_t *buf = NULL; /* Temporary buffer */ uint8_t *p; /* Pointer into raw data buffer */ - H5HF_type_t heap_type; /* Type of heap */ + H5HF_create_t cparam; /* Creation parameters for heap */ uint32_t metadata_chksum; /* Metadata checksum value */ H5HF_t *ret_value; /* Return value */ @@ -155,14 +155,21 @@ H5HF_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *ud if(metadata_chksum != 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect metadata checksum for fractal heap header") - /* Fractal heap type */ - heap_type = *p++; + /* Heap address mapping */ + cparam.addrmap = *p++; HDassert(H5HF_ABSOLUTE == 0); - if(heap_type > H5HF_MAPPED) + if(cparam.addrmap > H5HF_MAPPED) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "incorrect fractal heap type") + /* Min. size of standalone objects */ + UINT32DECODE(p, cparam.standalone_size); + + /* Size of fixed-length objects in heap */ + UINT32DECODE(p, cparam.fixed_len_size); + /* Initialize shared fractal heap info */ - if(H5HF_shared_init(f, fh, heap_type) < 0) + HDassert((size_t)(p - buf) == size); + if(H5HF_shared_init(fh, &cparam) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't create shared fractal heap info") /* Set return value */ @@ -238,8 +245,14 @@ H5HF_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5H HDmemset(p, 0, 4); p += 4; - /* Fractal heap type */ - *p++ = shared->type; + /* Heap address mapping */ + *p++ = shared->addrmap; + + /* Min. size of standalone objects */ + UINT32ENCODE(p, shared->standalone_size); + + /* Size of fixed-length objects in heap */ + UINT32ENCODE(p, shared->fixed_len_size); /* Write the B-tree header. */ HDassert((size_t)(p - buf) == size); diff --git a/src/H5HFdbg.c b/src/H5HFdbg.c index cb6476c..4216e96 100644 --- a/src/H5HFdbg.c +++ b/src/H5HFdbg.c @@ -115,10 +115,16 @@ H5HF_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, * Print the values. */ HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, - "Heap addressing method:", - ((shared->type) == H5HF_ABSOLUTE ? "Absolute" : - ((shared->type) == H5HF_MAPPED ? "Mapped" : + "Heap address mapping method:", + ((shared->addrmap) == H5HF_ABSOLUTE ? "Absolute" : + ((shared->addrmap) == H5HF_MAPPED ? "Mapped" : "Unknown!"))); + HDfprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth, + "Min. size of standalone object:", + (unsigned long)shared->standalone_size); + HDfprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth, + "Fixed length object size:", + (unsigned long)shared->fixed_len_size); done: if(fh && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, addr, fh, H5AC__NO_FLAGS_SET) < 0) diff --git a/src/H5HFint.c b/src/H5HFint.c new file mode 100644 index 0000000..83bb780 --- /dev/null +++ b/src/H5HFint.c @@ -0,0 +1,197 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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: H5HFint.c + * Feb 24 2006 + * Quincey Koziol <koziol@ncsa.uiuc.edu> + * + * Purpose: "Internal" routines for fractal heaps. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5HF_PACKAGE /*suppress error about including H5HFpkg */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5HFpkg.h" /* Fractal heaps */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5MFprivate.h" /* File memory management */ + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + +static herr_t H5HF_shared_free(void *_shared); + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + +/* Declare a free list to manage the H5HF_shared_t struct */ +H5FL_DEFINE_STATIC(H5HF_shared_t); + + + +/*------------------------------------------------------------------------- + * Function: H5HF_shared_init + * + * Purpose: Allocate & initialize shared fractal heap info + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 24 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_shared_init(H5HF_t *fh, H5HF_create_t *cparam) +{ + H5HF_shared_t *shared = NULL; /* Shared fractal heap information */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_shared_init) + + /* Allocate space for the shared information */ + if(NULL == (shared = H5FL_CALLOC(H5HF_shared_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fractal heap shared information") + + /* Set the creation parameters for the heap */ + shared->addrmap = cparam->addrmap; + shared->standalone_size = cparam->standalone_size; + shared->fixed_len_size = cparam->fixed_len_size; + + /* Make shared B-tree info reference counted */ + if(NULL == (fh->shared = H5RC_create(shared, H5HF_shared_free))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create ref-count wrapper for shared fractal heap info") + +done: + if(ret_value < 0) + if(shared) + H5HF_shared_free(shared); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_shared_init() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_shared_free + * + * Purpose: Free shared fractal heap info + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 24 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_shared_free(void *_shared) +{ + H5HF_shared_t *shared = (H5HF_shared_t *)_shared; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_shared_free) + + /* Sanity check */ + HDassert(shared); + + /* Free the shared info itself */ + H5FL_FREE(H5HF_shared_t, shared); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_shared_free() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_alloc_end + * + * Purpose: Allocate space for an object at the end of the heap + * + * Return: Non-negative on success (with heap ID of new object + * filled in), negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 27 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_man_alloc_end(H5HF_shared_t *shared, size_t size, const void *obj, + void *id/*out*/) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_alloc_end) + + /* + * Check arguments. + */ + HDassert(shared); + HDassert(size > 0); + HDassert(obj); + HDassert(id); + + /* Check if this is the first object in the heap */ + if(shared->next_man_block == 0) { + if(size /* + H5HF_DIRECT_OVERHEAD */ <= shared->man_dtable_info.start_block_size) { + } /* end if */ + else { + } /* end else */ +#ifdef QAK +HDfprintf(stderr, "%s: size = %Zu\n", FUNC, size); +HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "allocating first object not supported yet") +#endif /* QAK */ + } /* end if */ + else { +HDfprintf(stderr, "%s: size = %Zu\n", FUNC, size); +HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "allocating objects at end of heap not supported yet") + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_alloc_end() */ + diff --git a/src/H5HFpkg.h b/src/H5HFpkg.h index d311aff..57671c0 100644 --- a/src/H5HFpkg.h +++ b/src/H5HFpkg.h @@ -54,7 +54,9 @@ + 4 /* Metadata checksum */ \ \ /* Fractal heap header specific fields */ \ - + 1 /* Heap type */ \ + + 1 /* Address mapping */ \ + + 4 /* Min. size of standalone object */ \ + + 4 /* Length of fixed-size objects */ \ ) /****************************/ @@ -99,9 +101,9 @@ typedef struct H5HF_shared_t { H5HF_dtable_param_t std_dtable_info; /* Doubling-table info for standalone objects */ /* Information set by user */ - H5HF_type_t type; /* Type of address mapping */ - size_t standalone_size; /* Size of object to store standalone */ - size_t fixed_len_size; /* Size of objects (only for heaps w/fixed-length objects) */ + H5HF_addrmap_t addrmap; /* Type of address mapping */ + uint32_t standalone_size; /* Size of object to store standalone */ + uint32_t fixed_len_size; /* Size of objects (only for heaps w/fixed-length objects) */ /* Information derived from user parameters */ hbool_t fixed_len_obj; /* Are objects in the heap fixed length? */ @@ -136,7 +138,11 @@ H5FL_EXTERN(H5HF_t); /******************************/ /* Routines for managing shared fractal heap info */ -H5_DLL herr_t H5HF_shared_init(H5F_t *f, H5HF_t *fh, H5HF_type_t type); +H5_DLL herr_t H5HF_shared_init(H5HF_t *fh, H5HF_create_t *cparam); + +/* Routines for allocating space */ +herr_t H5HF_man_alloc_end(H5HF_shared_t *shared, size_t size, const void *obj, + void *id/*out*/); /* Metadata cache callbacks */ H5_DLL herr_t H5HF_cache_hdr_dest(H5F_t *f, H5HF_t *b); @@ -147,8 +153,8 @@ H5_DLL herr_t H5HF_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, /* Testing routines */ #ifdef H5HF_TESTING -H5_DLL herr_t H5HF_get_addrmap_test(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr, - H5HF_type_t *heap_type); +H5_DLL herr_t H5HF_get_cparam_test(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr, + H5HF_create_t *cparam); #endif /* H5HF_TESTING */ #endif /* _H5HFpkg_H */ diff --git a/src/H5HFprivate.h b/src/H5HFprivate.h index 49c11c9..62334fa 100644 --- a/src/H5HFprivate.h +++ b/src/H5HFprivate.h @@ -45,7 +45,16 @@ typedef enum { H5HF_ABSOLUTE, /* The heap uses absolute internal addressing */ H5HF_MAPPED /* The heap maps internal addresses to allow compaction */ -} H5HF_type_t; +} H5HF_addrmap_t; + +/* Fractal heap creation parameters */ +typedef struct H5HF_create_t { + H5HF_addrmap_t addrmap; /* Type of address mapping for objects in heap */ + uint32_t standalone_size; /* Size of object to store standalone */ + /* (i.e. max. size of object to manage) */ + uint32_t fixed_len_size; /* Size of objects (0 means variable-sized objects) */ + /* (only for heaps w/fixed-length objects) */ +} H5HF_create_t; /*****************************/ @@ -55,7 +64,7 @@ typedef enum { /***************************************/ /* Library-private Function Prototypes */ /***************************************/ -H5_DLL herr_t H5HF_create(H5F_t *f, hid_t dxpl_id, H5HF_type_t type, +H5_DLL herr_t H5HF_create(H5F_t *f, hid_t dxpl_id, H5HF_create_t *cparam, haddr_t *addr_p); H5_DLL herr_t H5HF_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t size, const void *obj, void *id/*out*/); diff --git a/src/H5HFtest.c b/src/H5HFtest.c index e9a3eeb..ef14b2b 100644 --- a/src/H5HFtest.c +++ b/src/H5HFtest.c @@ -64,9 +64,9 @@ /*------------------------------------------------------------------------- - * Function: H5HF_get_addrmap_test + * Function: H5HF_get_cparam_test * - * Purpose: Retrieve the address mapping type + * Purpose: Retrieve the parameters used to create the fractal heap * * Return: Success: non-negative * @@ -78,18 +78,18 @@ *------------------------------------------------------------------------- */ herr_t -H5HF_get_addrmap_test(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr, H5HF_type_t *heap_type) +H5HF_get_cparam_test(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr, H5HF_create_t *cparam) { H5HF_t *fh = NULL; /* Pointer to the B-tree header */ H5HF_shared_t *shared; /* Shared fractal heap information */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5HF_get_addrmap_test) + FUNC_ENTER_NOAPI_NOINIT(H5HF_get_cparam_test) /* Check arguments. */ HDassert(f); HDassert(H5F_addr_defined(fh_addr)); - HDassert(heap_type); + HDassert(cparam); /* Look up the fractal heap header */ if(NULL == (fh = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, fh_addr, NULL, NULL, H5AC_READ))) @@ -99,8 +99,10 @@ H5HF_get_addrmap_test(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr, H5HF_type_t *hea shared = H5RC_GET_OBJ(fh->shared); HDassert(shared); - /* Get fractal heap address mapping */ - *heap_type = shared->type; + /* Get fractal heap creation parameters */ + cparam->addrmap = shared->addrmap; + cparam->standalone_size = shared->standalone_size; + cparam->fixed_len_size = shared->fixed_len_size; done: /* Release fractal heap header node */ @@ -108,5 +110,5 @@ done: HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap header info") FUNC_LEAVE_NOAPI(ret_value) -} /* H5HF_get_addrmap_test() */ +} /* H5HF_get_cparam_test() */ diff --git a/src/Makefile.am b/src/Makefile.am index dc3629a..0a3abbf 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -37,9 +37,8 @@ libhdf5_la_LDFLAGS= -version-info $(LT_VERS_INTERFACE):$(LT_VERS_REVISION):$(LT_ MOSTLYCLEANFILES=H5Tinit.c # library sources -libhdf5_la_SOURCES= H5.c H5A.c H5AC.c H5B.c H5Bcache.c H5B2.c H5B2cache.c \ - H5B2dbg.c \ - H5B2test.c \ +libhdf5_la_SOURCES= H5.c H5A.c H5AC.c H5B.c H5Bcache.c \ + H5B2.c H5B2cache.c H5B2dbg.c H5B2int.c H5B2test.c \ H5C.c \ H5D.c \ H5Dcompact.c \ @@ -55,7 +54,7 @@ libhdf5_la_SOURCES= H5.c H5A.c H5AC.c H5B.c H5Bcache.c H5B2.c H5B2cache.c \ H5Gstab.c \ H5Gtest.c \ H5Gtraverse.c \ - H5HF.c H5HFcache.c H5HFdbg.c H5HFtest.c \ + H5HF.c H5HFcache.c H5HFdbg.c H5HFint.c H5HFtest.c \ H5HG.c H5HGdbg.c H5HL.c H5HLdbg.c H5HP.c H5I.c H5MF.c H5MM.c \ H5MP.c H5MPtest.c \ H5O.c \ diff --git a/src/Makefile.in b/src/Makefile.in index 1b5ea41..dd8ec8b 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -83,7 +83,7 @@ libLTLIBRARIES_INSTALL = $(INSTALL) LTLIBRARIES = $(lib_LTLIBRARIES) libhdf5_la_LIBADD = am_libhdf5_la_OBJECTS = H5.lo H5A.lo H5AC.lo H5B.lo H5Bcache.lo \ - H5B2.lo H5B2cache.lo H5B2dbg.lo H5B2test.lo H5C.lo H5D.lo \ + H5B2.lo H5B2cache.lo H5B2dbg.lo H5B2int.lo H5B2test.lo H5C.lo H5D.lo \ H5Dcompact.lo H5Dcontig.lo H5Defl.lo H5Dio.lo H5Distore.lo \ H5Dmpio.lo H5Doh.lo H5Dselect.lo H5Dtest.lo H5E.lo H5F.lo \ H5Fdbg.lo H5Fmount.lo H5Fsfile.lo H5Fsuper.lo H5FD.lo \ @@ -93,7 +93,7 @@ am_libhdf5_la_OBJECTS = H5.lo H5A.lo H5AC.lo H5B.lo H5Bcache.lo \ H5FPclient.lo H5FPserver.lo H5FS.lo H5G.lo H5Gent.lo \ H5Glink.lo H5Gloc.lo H5Gname.lo H5Gnode.lo H5Gobj.lo H5Goh.lo \ H5Gstab.lo H5Gtest.lo H5Gtraverse.lo H5HF.lo H5HFcache.lo \ - H5HFdbg.lo H5HFtest.lo H5HG.lo H5HGdbg.lo H5HL.lo H5HLdbg.lo \ + H5HFdbg.lo H5HFint.lo H5HFtest.lo H5HG.lo H5HGdbg.lo H5HL.lo H5HLdbg.lo \ H5HP.lo H5I.lo H5MF.lo H5MM.lo H5MP.lo H5MPtest.lo H5O.lo \ H5Oattr.lo H5Obogus.lo H5Ocache.lo H5Ocont.lo H5Odtype.lo \ H5Oefl.lo H5Ofill.lo H5Oginfo.lo H5Olayout.lo H5Olinfo.lo \ @@ -389,9 +389,8 @@ libhdf5_la_LDFLAGS = -version-info $(LT_VERS_INTERFACE):$(LT_VERS_REVISION):$(LT MOSTLYCLEANFILES = H5Tinit.c # library sources -libhdf5_la_SOURCES = H5.c H5A.c H5AC.c H5B.c H5Bcache.c H5B2.c H5B2cache.c \ - H5B2dbg.c \ - H5B2test.c \ +libhdf5_la_SOURCES = H5.c H5A.c H5AC.c H5B.c H5Bcache.c \ + H5B2.c H5B2cache.c H5B2dbg.c H5B2int.c H5B2test.c \ H5C.c \ H5D.c \ H5Dcompact.c \ @@ -407,7 +406,7 @@ libhdf5_la_SOURCES = H5.c H5A.c H5AC.c H5B.c H5Bcache.c H5B2.c H5B2cache.c \ H5Gstab.c \ H5Gtest.c \ H5Gtraverse.c \ - H5HF.c H5HFcache.c H5HFdbg.c H5HFtest.c \ + H5HF.c H5HFcache.c H5HFdbg.c H5HFint.c H5HFtest.c \ H5HG.c H5HGdbg.c H5HL.c H5HLdbg.c H5HP.c H5I.c H5MF.c H5MM.c \ H5MP.c H5MPtest.c \ H5O.c \ @@ -567,6 +566,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5B2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5B2cache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5B2dbg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5B2int.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5B2test.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Bcache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5C.Plo@am__quote@ @@ -618,6 +618,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HF.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFcache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFdbg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFint.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFtest.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HG.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HGdbg.Plo@am__quote@ diff --git a/test/fheap.c b/test/fheap.c index b1fce69..1a9f8e9 100644 --- a/test/fheap.c +++ b/test/fheap.c @@ -54,7 +54,7 @@ test_create(hid_t fapl) hid_t file = -1; /* File ID */ char filename[1024]; /* Filename to use */ H5F_t *f = NULL; /* Internal file object pointer */ - H5HF_type_t heap_type, test_heap_type; /* Type of address mapping for fractal heap */ + H5HF_create_t cparam, test_cparam; /* Creation parameters for heap */ haddr_t fh_addr; /* Address of fractal heap created */ /* Set the filename to use for this test (dependent on fapl) */ @@ -72,8 +72,10 @@ test_create(hid_t fapl) * Test fractal heap creation (w/absolute address mapping) */ TESTING("Fractal heap creation (w/absolute address mapping)"); - heap_type = H5HF_ABSOLUTE; - if(H5HF_create(f, H5P_DATASET_XFER_DEFAULT, heap_type, &fh_addr/*out*/) < 0) + cparam.addrmap = H5HF_ABSOLUTE; + cparam.standalone_size = 64 * 1024; + cparam.fixed_len_size = 0; + if(H5HF_create(f, H5P_DATASET_XFER_DEFAULT, &cparam, &fh_addr/*out*/) < 0) FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR @@ -81,10 +83,10 @@ test_create(hid_t fapl) /* Query the type of address mapping */ TESTING("Query absolute address mapping setting"); - test_heap_type = H5HF_MAPPED; - if(H5HF_get_addrmap_test(f, H5P_DATASET_XFER_DEFAULT, fh_addr, &test_heap_type) < 0) + HDmemset(&test_cparam, 0, sizeof(H5HF_create_t)); + if(H5HF_get_cparam_test(f, H5P_DATASET_XFER_DEFAULT, fh_addr, &test_cparam) < 0) FAIL_STACK_ERROR - if(test_heap_type != heap_type) + if(HDmemcmp(&cparam, &test_cparam, sizeof(H5HF_create_t))) FAIL_STACK_ERROR PASSED() @@ -92,8 +94,10 @@ test_create(hid_t fapl) * Test fractal heap creation (w/mapped address mapping) */ TESTING("Fractal heap creation (w/mapped address mapping)"); - heap_type = H5HF_MAPPED; - if(H5HF_create(f, H5P_DATASET_XFER_DEFAULT, heap_type, &fh_addr/*out*/) < 0) + cparam.addrmap = H5HF_MAPPED; + cparam.standalone_size = 64 * 1024; + cparam.fixed_len_size = 0; + if(H5HF_create(f, H5P_DATASET_XFER_DEFAULT, &cparam, &fh_addr/*out*/) < 0) FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR @@ -101,10 +105,10 @@ test_create(hid_t fapl) /* Query the type of address mapping */ TESTING("Query mapped address mapping setting"); - test_heap_type = H5HF_ABSOLUTE; - if(H5HF_get_addrmap_test(f, H5P_DATASET_XFER_DEFAULT, fh_addr, &test_heap_type) < 0) + HDmemset(&test_cparam, 0, sizeof(H5HF_create_t)); + if(H5HF_get_cparam_test(f, H5P_DATASET_XFER_DEFAULT, fh_addr, &test_cparam) < 0) FAIL_STACK_ERROR - if(test_heap_type != heap_type) + if(HDmemcmp(&cparam, &test_cparam, sizeof(H5HF_create_t))) FAIL_STACK_ERROR PASSED() @@ -144,6 +148,7 @@ test_abs_insert_first(hid_t fapl) hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */ char filename[1024]; /* Filename to use */ H5F_t *f = NULL; /* Internal file object pointer */ + H5HF_create_t cparam; /* Creation parameters for heap */ haddr_t fh_addr; /* Address of fractal heap created */ unsigned char obj[10]; /* Buffer for object to insert */ haddr_t heap_id; /* Heap ID for object inserted */ @@ -162,7 +167,10 @@ test_abs_insert_first(hid_t fapl) STACK_ERROR /* Create absolute heap */ - if(H5HF_create(f, dxpl, H5HF_ABSOLUTE, &fh_addr/*out*/) < 0) + cparam.addrmap = H5HF_ABSOLUTE; + cparam.standalone_size = 64 * 1024; + cparam.fixed_len_size = 0; + if(H5HF_create(f, dxpl, &cparam, &fh_addr/*out*/) < 0) FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR |