diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2015-12-29 17:06:36 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2015-12-29 17:06:36 (GMT) |
commit | b5504be6cc6f61b5a8ce78f243b81b6afe9d13c9 (patch) | |
tree | 34c12b398509a0b7585009bd10f4e22982ad9cdb /src | |
parent | 6d8b831b3125ce66e23aba1f3ec16a03e00b5b82 (diff) | |
download | hdf5-b5504be6cc6f61b5a8ce78f243b81b6afe9d13c9.zip hdf5-b5504be6cc6f61b5a8ce78f243b81b6afe9d13c9.tar.gz hdf5-b5504be6cc6f61b5a8ce78f243b81b6afe9d13c9.tar.bz2 |
[svn-r28742] Description:
Add 'update' operation to v2 B-trees, which will insert a new record, or
modify an existing one, depending on if the record exists or not.
Tested on:
MacOSX/64 10.11.2 (amazon) w/serial & parallel
(h5committest forthcoming)
Diffstat (limited to 'src')
-rw-r--r-- | src/H5Abtree2.c | 8 | ||||
-rw-r--r-- | src/H5B2.c | 74 | ||||
-rw-r--r-- | src/H5B2dbg.c | 44 | ||||
-rw-r--r-- | src/H5B2int.c | 401 | ||||
-rw-r--r-- | src/H5B2pkg.h | 27 | ||||
-rw-r--r-- | src/H5B2private.h | 5 | ||||
-rw-r--r-- | src/H5B2test.c | 168 | ||||
-rw-r--r-- | src/H5Gbtree2.c | 8 | ||||
-rw-r--r-- | src/H5HFbtree2.c | 57 | ||||
-rw-r--r-- | src/H5SMbtree2.c | 44 |
10 files changed, 646 insertions, 190 deletions
diff --git a/src/H5Abtree2.c b/src/H5Abtree2.c index 972fb0b..716ad4a 100644 --- a/src/H5Abtree2.c +++ b/src/H5Abtree2.c @@ -116,9 +116,7 @@ const H5B2_class_t H5A_BT2_NAME[1]={{ /* B-tree class information */ H5A__dense_btree2_name_compare, /* Record comparison callback */ H5A__dense_btree2_name_encode, /* Record encoding callback */ H5A__dense_btree2_name_decode, /* Record decoding callback */ - H5A__dense_btree2_name_debug, /* Record debugging callback */ - NULL, /* Create debugging context */ - NULL /* Destroy debugging context */ + H5A__dense_btree2_name_debug /* Record debugging callback */ }}; /* v2 B-tree class for indexing 'creation order' field of attributes */ @@ -132,9 +130,7 @@ const H5B2_class_t H5A_BT2_CORDER[1]={{ /* B-tree class information */ H5A__dense_btree2_corder_compare, /* Record comparison callback */ H5A__dense_btree2_corder_encode, /* Record encoding callback */ H5A__dense_btree2_corder_decode, /* Record decoding callback */ - H5A__dense_btree2_corder_debug, /* Record debugging callback */ - NULL, /* Create debugging context */ - NULL /* Destroy debugging context */ + H5A__dense_btree2_corder_debug /* Record debugging callback */ }}; @@ -86,6 +86,7 @@ extern const H5B2_class_t H5G_BT2_CORDER[1]; extern const H5B2_class_t H5SM_INDEX[1]; extern const H5B2_class_t H5A_BT2_NAME[1]; extern const H5B2_class_t H5A_BT2_CORDER[1]; +extern const H5B2_class_t H5B2_TEST2[1]; const H5B2_class_t *const H5B2_client_class_g[] = { H5B2_TEST, /* 0 - H5B2_TEST_ID */ @@ -98,6 +99,7 @@ const H5B2_class_t *const H5B2_client_class_g[] = { H5SM_INDEX, /* 7 - H5B2_SOHM_INDEX_ID */ H5A_BT2_NAME, /* 8 - H5B2_ATTR_DENSE_NAME_ID */ H5A_BT2_CORDER, /* 9 - H5B2_ATTR_DENSE_CORDER_ID */ + H5B2_TEST2, /* 10 - H5B2_TEST_ID */ }; @@ -282,36 +284,78 @@ H5B2_insert(H5B2_t *bt2, hid_t dxpl_id, void *udata) /* Get the v2 B-tree header */ hdr = bt2->hdr; + /* Insert the record */ + if(H5B2__insert_hdr(hdr, dxpl_id, udata) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into B-tree") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5B2_insert() */ + + +/*------------------------------------------------------------------------- + * Function: H5B2_update + * + * Purpose: Insert or modify a record to the B-tree. + * If the record exists already, it is modified as if H5B2_modify + * was called). If it doesn't exist, it is inserted as if + * H5B2_insert was called. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Dec 23 2015 + * + *------------------------------------------------------------------------- + */ +herr_t +H5B2_update(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_modify_t op, void *op_data) +{ + H5B2_hdr_t *hdr; /* Pointer to the B-tree header */ + H5B2_update_status_t status = H5B2_UPDATE_UNKNOWN; /* Whether the record was inserted/modified */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Check arguments. */ + HDassert(bt2); + HDassert(udata); + + /* Set the shared v2 B-tree header's file context for this operation */ + bt2->hdr->f = bt2->f; + + /* Get the v2 B-tree header */ + hdr = bt2->hdr; + /* Check if the root node is allocated yet */ if(!H5F_addr_defined(hdr->root.addr)) { /* Create root node as leaf node in B-tree */ if(H5B2__create_leaf(hdr, dxpl_id, &(hdr->root)) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create root node") } /* end if */ - /* Check if we need to split the root node (equiv. to a 1->2 node split) */ - else if(hdr->root.node_nrec == hdr->node_info[hdr->depth].split_nrec) { - /* Split root node */ - if(H5B2__split_root(hdr, dxpl_id) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to split root node") - } /* end if */ /* Attempt to insert record into B-tree */ if(hdr->depth > 0) { - if(H5B2__insert_internal(hdr, dxpl_id, hdr->depth, NULL, &hdr->root, H5B2_POS_ROOT, udata) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into B-tree internal node") + if(H5B2__update_internal(hdr, dxpl_id, hdr->depth, NULL, &hdr->root, &status, H5B2_POS_ROOT, udata, op, op_data) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to update record in B-tree internal node") } /* end if */ else { - if(H5B2__insert_leaf(hdr, dxpl_id, &hdr->root, H5B2_POS_ROOT, udata) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into B-tree leaf node") + if(H5B2__update_leaf(hdr, dxpl_id, &hdr->root, &status, H5B2_POS_ROOT, udata, op, op_data) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to update record in B-tree leaf node") } /* end else */ - /* Mark B-tree header as dirty */ - if(H5B2__hdr_dirty(hdr) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTMARKDIRTY, FAIL, "unable to mark B-tree header dirty") + /* Sanity check */ + HDassert(H5B2_UPDATE_UNKNOWN != status); + + /* Use insert algorithm if nodes to leaf full */ + if(H5B2_UPDATE_INSERT_CHILD_FULL == status) + if(H5B2__insert_hdr(hdr, dxpl_id, udata) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into B-tree") done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5B2_insert() */ +} /* H5B2_update() */ /*------------------------------------------------------------------------- @@ -1202,7 +1246,7 @@ H5B2_modify(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_modify_t op, /* Unlock current node */ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr.addr, leaf, leaf_flags) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node") - } + } /* end block */ done: FUNC_LEAVE_NOAPI(ret_value) diff --git a/src/H5B2dbg.c b/src/H5B2dbg.c index 73084d2..ddff9e9 100644 --- a/src/H5B2dbg.c +++ b/src/H5B2dbg.c @@ -92,7 +92,6 @@ H5B2__hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, const H5B2_class_t *type, haddr_t obj_addr) { H5B2_hdr_t *hdr = NULL; /* B-tree header info */ - void *dbg_ctx = NULL; /* v2 B-tree debugging context */ unsigned u; /* Local index variable */ char temp_str[128]; /* Temporary string, for formatting */ herr_t ret_value = SUCCEED; /* Return value */ @@ -109,17 +108,9 @@ H5B2__hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, HDassert(indent >= 0); HDassert(fwidth >= 0); HDassert(type); - HDassert((type->crt_dbg_ctx && type->dst_dbg_ctx) || - (NULL == type->crt_dbg_ctx && NULL == type->dst_dbg_ctx)); - - /* Check for debugging context callback available */ - if(type->crt_dbg_ctx) - /* Create debugging context */ - if(NULL == (dbg_ctx = (type->crt_dbg_ctx)(f, dxpl_id, obj_addr))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTGET, FAIL, "unable to create v2 B-tree debugging context") /* Load the B-tree header */ - if(NULL == (hdr = H5B2__hdr_protect(f, dxpl_id, addr, dbg_ctx, H5AC__READ_ONLY_FLAG))) + if(NULL == (hdr = H5B2__hdr_protect(f, dxpl_id, addr, f, H5AC__READ_ONLY_FLAG))) HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load B-tree header") /* Set file pointer for this B-tree operation */ @@ -171,8 +162,6 @@ H5B2__hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, } /* end for */ done: - if(dbg_ctx && (type->dst_dbg_ctx)(dbg_ctx) < 0) - HDONE_ERROR(H5E_BTREE, H5E_CANTRELEASE, FAIL, "unable to release v2 B-tree debugging context") if(hdr && H5B2__hdr_unprotect(hdr, dxpl_id, H5AC__NO_FLAGS_SET) < 0) HDONE_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release v2 B-tree header") @@ -199,7 +188,6 @@ H5B2__int_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, { H5B2_hdr_t *hdr = NULL; /* B-tree header */ H5B2_internal_t *internal = NULL; /* B-tree internal node */ - void *dbg_ctx = NULL; /* v2 B-tree debugging context */ unsigned u; /* Local index variable */ char temp_str[128]; /* Temporary string, for formatting */ herr_t ret_value=SUCCEED; /* Return value */ @@ -215,21 +203,12 @@ H5B2__int_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, HDassert(indent >= 0); HDassert(fwidth >= 0); HDassert(type); - HDassert((type->crt_dbg_ctx && type->dst_dbg_ctx) || - (NULL == type->crt_dbg_ctx && NULL == type->dst_dbg_ctx)); HDassert(H5F_addr_defined(hdr_addr)); HDassert(H5F_addr_defined(obj_addr)); HDassert(nrec > 0); - /* Check for debugging context callback available */ - if(type->crt_dbg_ctx) { - /* Create debugging context */ - if(NULL == (dbg_ctx = (type->crt_dbg_ctx)(f, dxpl_id, obj_addr))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTGET, FAIL, "unable to create v2 B-tree debugging context") - } /* end if */ - /* Load the B-tree header */ - if(NULL == (hdr = H5B2__hdr_protect(f, dxpl_id, hdr_addr, dbg_ctx, H5AC__READ_ONLY_FLAG))) + if(NULL == (hdr = H5B2__hdr_protect(f, dxpl_id, hdr_addr, f, H5AC__READ_ONLY_FLAG))) HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load v2 B-tree header") /* Set file pointer for this B-tree operation */ @@ -279,7 +258,7 @@ H5B2__int_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, HDfprintf(stream, "%*s%-*s\n", indent + 3, "", MAX(0, fwidth - 3), temp_str); HDassert(H5B2_INT_NREC(internal, hdr, u)); - (void)(type->debug)(stream, indent + 6, MAX (0, fwidth-6), H5B2_INT_NREC(internal, hdr, u), dbg_ctx); + (void)(type->debug)(stream, indent + 6, MAX (0, fwidth-6), H5B2_INT_NREC(internal, hdr, u), hdr->cb_ctx); } /* end for */ /* Print final node pointer */ @@ -291,8 +270,6 @@ H5B2__int_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, internal->node_ptrs[u].addr); done: - if(dbg_ctx && (type->dst_dbg_ctx)(dbg_ctx) < 0) - HDONE_ERROR(H5E_BTREE, H5E_CANTRELEASE, FAIL, "unable to release v2 B-tree debugging context") if(hdr && H5B2__hdr_unprotect(hdr, dxpl_id, H5AC__NO_FLAGS_SET) < 0) HDONE_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release v2 B-tree header") if(internal && H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, addr, internal, H5AC__NO_FLAGS_SET) < 0) @@ -321,7 +298,6 @@ H5B2__leaf_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent { H5B2_hdr_t *hdr = NULL; /* B-tree header */ H5B2_leaf_t *leaf = NULL; /* B-tree leaf node */ - void *dbg_ctx = NULL; /* v2 B-tree debugging context */ unsigned u; /* Local index variable */ char temp_str[128]; /* Temporary string, for formatting */ herr_t ret_value = SUCCEED; /* Return value */ @@ -337,20 +313,12 @@ H5B2__leaf_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent HDassert(indent >= 0); HDassert(fwidth >= 0); HDassert(type); - HDassert((type->crt_dbg_ctx && type->dst_dbg_ctx) || - (NULL == type->crt_dbg_ctx && NULL == type->dst_dbg_ctx)); HDassert(H5F_addr_defined(hdr_addr)); HDassert(H5F_addr_defined(obj_addr)); HDassert(nrec > 0); - /* Check for debugging context callback available */ - if(type->crt_dbg_ctx) - /* Create debugging context */ - if(NULL == (dbg_ctx = (type->crt_dbg_ctx)(f, dxpl_id, obj_addr))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTGET, FAIL, "unable to create v2 B-tree debugging context") - /* Load the B-tree header */ - if(NULL == (hdr = H5B2__hdr_protect(f, dxpl_id, hdr_addr, dbg_ctx, H5AC__READ_ONLY_FLAG))) + if(NULL == (hdr = H5B2__hdr_protect(f, dxpl_id, hdr_addr, f, H5AC__READ_ONLY_FLAG))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect v2 B-tree header") /* Set file pointer for this B-tree operation */ @@ -391,12 +359,10 @@ H5B2__leaf_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent HDfprintf(stream, "%*s%-*s\n", indent + 3, "", MAX(0, fwidth - 3), temp_str); HDassert(H5B2_LEAF_NREC(leaf, hdr, u)); - (void)(type->debug)(stream, indent + 6, MAX (0, fwidth-6), H5B2_LEAF_NREC(leaf, hdr, u), dbg_ctx); + (void)(type->debug)(stream, indent + 6, MAX (0, fwidth-6), H5B2_LEAF_NREC(leaf, hdr, u), hdr->cb_ctx); } /* end for */ done: - if(dbg_ctx && (type->dst_dbg_ctx)(dbg_ctx) < 0) - HDONE_ERROR(H5E_BTREE, H5E_CANTRELEASE, FAIL, "unable to release v2 B-tree debugging context") if(hdr && H5B2__hdr_unprotect(hdr, dxpl_id, H5AC__NO_FLAGS_SET) < 0) HDONE_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree header") if(leaf && H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, addr, leaf, H5AC__NO_FLAGS_SET) < 0) diff --git a/src/H5B2int.c b/src/H5B2int.c index b8c9634..363d903 100644 --- a/src/H5B2int.c +++ b/src/H5B2int.c @@ -1513,6 +1513,62 @@ done: /*------------------------------------------------------------------------- + * Function: H5B2__insert_hdr + * + * Purpose: Adds a new record to the B-tree. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Dec 23 2015 + * + *------------------------------------------------------------------------- + */ +herr_t +H5B2__insert_hdr(H5B2_hdr_t *hdr, hid_t dxpl_id, void *udata) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Check arguments. */ + HDassert(hdr); + HDassert(udata); + + /* Check if the root node is allocated yet */ + if(!H5F_addr_defined(hdr->root.addr)) { + /* Create root node as leaf node in B-tree */ + if(H5B2__create_leaf(hdr, dxpl_id, &(hdr->root)) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create root node") + } /* end if */ + /* Check if we need to split the root node (equiv. to a 1->2 node split) */ + else if(hdr->root.node_nrec == hdr->node_info[hdr->depth].split_nrec) { + /* Split root node */ + if(H5B2__split_root(hdr, dxpl_id) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to split root node") + } /* end if */ + + /* Attempt to insert record into B-tree */ + if(hdr->depth > 0) { + if(H5B2__insert_internal(hdr, dxpl_id, hdr->depth, NULL, &hdr->root, H5B2_POS_ROOT, udata) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into B-tree internal node") + } /* end if */ + else { + if(H5B2__insert_leaf(hdr, dxpl_id, &hdr->root, H5B2_POS_ROOT, udata) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into B-tree leaf node") + } /* end else */ + + /* Mark B-tree header as dirty */ + if(H5B2__hdr_dirty(hdr) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTMARKDIRTY, FAIL, "unable to mark B-tree header dirty") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5B2__insert_hdr() */ + + +/*------------------------------------------------------------------------- * Function: H5B2__insert_leaf * * Purpose: Adds a new record to a B-tree leaf node. @@ -1644,6 +1700,9 @@ H5B2__insert_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, curr_node_ptr->addr, curr_node_ptr->node_nrec, depth, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node") + /* Sanity check number of records */ + HDassert(internal->nrec == curr_node_ptr->node_nrec); + /* Split or redistribute child node pointers, if necessary */ { int cmp; /* Comparison value of records */ @@ -1755,6 +1814,348 @@ done: /*------------------------------------------------------------------------- + * Function: H5B2__update_leaf + * + * Purpose: Insert or modify a record in a B-tree leaf node. + * If the record exists already, it is modified as if H5B2_modify + * was called). If it doesn't exist, it is inserted as if + * H5B2_insert was called. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Dec 23 2015 + * + *------------------------------------------------------------------------- + */ +herr_t +H5B2__update_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *curr_node_ptr, + H5B2_update_status_t *status, H5B2_nodepos_t curr_pos, void *udata, + H5B2_modify_t op, void *op_data) +{ + H5B2_leaf_t *leaf; /* Pointer to leaf node */ + unsigned leaf_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting the leaf node */ + int cmp = -1; /* Comparison value of records */ + unsigned idx; /* Location of record which matches key */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Check arguments. */ + HDassert(hdr); + HDassert(curr_node_ptr); + HDassert(H5F_addr_defined(curr_node_ptr->addr)); + + /* Lock current B-tree node */ + if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, curr_node_ptr->addr, curr_node_ptr->node_nrec, H5AC__NO_FLAGS_SET))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node") + + /* 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 */ + cmp = H5B2__locate_record(hdr->cls, leaf->nrec, hdr->nat_off, leaf->leaf_native, udata, &idx); + + /* Check for inserting a record */ + if(0 != cmp) { + /* Check if the leaf node is full */ + if(curr_node_ptr->node_nrec == hdr->node_info[0].split_nrec) { + /* Indicate that the leaf is full, but we need to insert */ + *status = H5B2_UPDATE_INSERT_CHILD_FULL; + + /* Let calling routine handle insertion */ + HGOTO_DONE(SUCCEED) + } /* end if */ + + /* Adjust index to leave room for record to insert */ + if(cmp > 0) + idx++; + + /* Make room for new record */ + if(idx < leaf->nrec) + HDmemmove(H5B2_LEAF_NREC(leaf, hdr, idx + 1), H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size * (leaf->nrec - idx)); + } /* end if */ + } /* end else */ + + /* Check for modifying existing record */ + if(0 == cmp) { + hbool_t changed = FALSE; /* Whether the 'modify' callback changed the record */ + + /* Make callback for current record */ + if((op)(H5B2_LEAF_NREC(leaf, hdr, idx), op_data, &changed) < 0) { + /* Make certain that the callback didn't modify the value if it failed */ + HDassert(changed == FALSE); + + HGOTO_ERROR(H5E_BTREE, H5E_CANTMODIFY, FAIL, "'modify' callback failed for B-tree update operation") + } /* end if */ + + /* Mark the node as dirty if it changed */ + leaf_flags |= (changed ? H5AC__DIRTIED_FLAG : 0); + + /* Indicate that the record was modified */ + *status = H5B2_UPDATE_MODIFY_DONE; + } /* end if */ + else { + /* Must have a leaf node with enough space to insert a record now */ + HDassert(curr_node_ptr->node_nrec < hdr->node_info[0].max_nrec); + + /* Make callback to store record in native form */ + if((hdr->cls->store)(H5B2_LEAF_NREC(leaf, hdr, idx), udata) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into leaf node") + + /* Mark the node as dirty if it changed */ + leaf_flags |= H5AC__DIRTIED_FLAG; + + /* Indicate that the record was inserted */ + *status = H5B2_UPDATE_INSERT_DONE; + + /* 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++; + } /* end else */ + + /* Check for new record being the min or max for the tree */ + /* (Don't use 'else' for the idx check, to allow for root leaf node) */ + if(H5B2_POS_MIDDLE != curr_pos) { + if(idx == 0) { + if(H5B2_POS_LEFT == curr_pos || H5B2_POS_ROOT == curr_pos) { + if(hdr->min_native_rec == NULL) + if(NULL == (hdr->min_native_rec = (uint8_t *)HDmalloc(hdr->cls->nrec_size))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "memory allocation failed for v2 B-tree min record info") + HDmemcpy(hdr->min_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size); + } /* end if */ + } /* end if */ + if(idx == (unsigned)(leaf->nrec - 1)) { + if(H5B2_POS_RIGHT == curr_pos || H5B2_POS_ROOT == curr_pos) { + if(hdr->max_native_rec == NULL) + if(NULL == (hdr->max_native_rec = (uint8_t *)HDmalloc(hdr->cls->nrec_size))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "memory allocation failed for v2 B-tree max record info") + HDmemcpy(hdr->max_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size); + } /* end if */ + } /* end if */ + } /* end if */ + +done: + /* Release the B-tree leaf node */ + if(leaf && H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr->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__update_leaf() */ + + +/*------------------------------------------------------------------------- + * Function: H5B2__update_internal + * + * Purpose: Insert or modify a record in a B-tree leaf node. + * If the record exists already, it is modified as if H5B2_modify + * was called). If it doesn't exist, it is inserted as if + * H5B2_insert was called. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Dec 24 2015 + * + *------------------------------------------------------------------------- + */ +herr_t +H5B2__update_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, + unsigned *parent_cache_info_flags_ptr, H5B2_node_ptr_t *curr_node_ptr, + H5B2_update_status_t *status, H5B2_nodepos_t curr_pos, void *udata, + H5B2_modify_t op, void *op_data) +{ + H5B2_internal_t *internal = NULL; /* Pointer to internal node */ + unsigned internal_flags = H5AC__NO_FLAGS_SET; + int cmp; /* Comparison value of records */ + unsigned idx; /* Location of record which matches key */ + H5B2_nodepos_t next_pos = H5B2_POS_MIDDLE; /* Position of node */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Check arguments. */ + HDassert(hdr); + HDassert(depth > 0); + HDassert(curr_node_ptr); + HDassert(H5F_addr_defined(curr_node_ptr->addr)); + + /* Lock current B-tree node */ + if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, curr_node_ptr->addr, curr_node_ptr->node_nrec, depth, H5AC__NO_FLAGS_SET))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node") + + /* Sanity check number of records */ + HDassert(internal->nrec == curr_node_ptr->node_nrec); + + /* Locate node pointer for child */ + cmp = H5B2__locate_record(hdr->cls, internal->nrec, hdr->nat_off, internal->int_native, udata, &idx); + + /* Check for modifying existing record */ + if(0 == cmp) { + hbool_t changed = FALSE; /* Whether the 'modify' callback changed the record */ + + /* Make callback for current record */ + if((op)(H5B2_INT_NREC(internal, hdr, idx), op_data, &changed) < 0) { + /* Make certain that the callback didn't modify the value if it failed */ + HDassert(changed == FALSE); + + HGOTO_ERROR(H5E_BTREE, H5E_CANTMODIFY, FAIL, "'modify' callback failed for B-tree update operation") + } /* end if */ + + /* Mark the node as dirty if it changed */ + internal_flags |= (changed ? H5AC__DIRTIED_FLAG : 0); + + /* Indicate that the record was modified */ + *status = H5B2_UPDATE_MODIFY_DONE; + } /* end if */ + else { + /* Adjust index to leave room for node to insert */ + if(cmp > 0) + idx++; + + /* Check if this node is left/right-most */ + if(H5B2_POS_MIDDLE != curr_pos) { + if(idx == 0) { + if(H5B2_POS_LEFT == curr_pos || H5B2_POS_ROOT == curr_pos) + next_pos = H5B2_POS_LEFT; + } /* end if */ + else if(idx == internal->nrec) { + if(H5B2_POS_RIGHT == curr_pos || H5B2_POS_ROOT == curr_pos) + next_pos = H5B2_POS_RIGHT; + } /* end else */ + } /* end if */ + + /* Attempt to update record in child */ + if(depth > 1) { + if(H5B2__update_internal(hdr, dxpl_id, (uint16_t)(depth - 1), &internal_flags, &internal->node_ptrs[idx], status, next_pos, udata, op, op_data) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUPDATE, FAIL, "unable to update record in internal B-tree node") + } /* end if */ + else { + if(H5B2__update_leaf(hdr, dxpl_id, &internal->node_ptrs[idx], status, next_pos, udata, op, op_data) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUPDATE, FAIL, "unable to update record in leaf B-tree node") + } /* end else */ + + /* Take actions based on child's status report */ + switch(*status) { + case H5B2_UPDATE_MODIFY_DONE: + /* No action */ + break; + + case H5B2_UPDATE_INSERT_DONE: + /* Mark node as dirty */ + internal_flags |= H5AC__DIRTIED_FLAG; + + /* Update total record count for node pointer to current node */ + curr_node_ptr->all_nrec++; + break; + + case H5B2_UPDATE_INSERT_CHILD_FULL: + /* Split/redistribute this node */ + if(internal->nrec == hdr->node_info[depth].split_nrec) { + hbool_t could_split = FALSE; /* Whether the child node could split */ + +#ifdef QAK +HDfprintf(stderr, "%s: idx = %u, internal->nrec = %u\n", FUNC, idx, internal->nrec); +HDfprintf(stderr, "%s: hdr->node_info[%u].split_nrec = %u\n", FUNC, (unsigned)depth, (unsigned)hdr->node_info[depth].split_nrec); +HDfprintf(stderr, "%s: hdr->node_info[%u].split_nrec = %u\n", FUNC, (unsigned)(depth - 1), (unsigned)hdr->node_info[depth - 1].split_nrec); +#endif /* QAK */ + if(idx == 0) { /* Left-most child */ +#ifdef QAK +HDfprintf(stderr, "%s: Left-most child\n", FUNC); +HDfprintf(stderr, "%s: internal->node_ptrs[%u].node_nrec = %u\n", FUNC, (unsigned)idx, (unsigned)internal->node_ptrs[idx].node_nrec); +HDfprintf(stderr, "%s: internal->node_ptrs[%u].node_nrec = %u\n", FUNC, (unsigned)(idx + 1), (unsigned)internal->node_ptrs[idx + 1].node_nrec); +#endif /* QAK */ + /* Check for left-most child and its neighbor being close to full */ + if((internal->node_ptrs[idx].node_nrec + internal->node_ptrs[idx + 1].node_nrec) + >= ((hdr->node_info[depth - 1].split_nrec * 2) - 1)) + could_split = TRUE; + } /* end if */ + else if(idx == internal->nrec) { /* Right-most child */ +#ifdef QAK +HDfprintf(stderr, "%s: Right-most child\n", FUNC); +HDfprintf(stderr, "%s: internal->node_ptrs[%u].node_nrec = %u\n", FUNC, (unsigned)(idx - 1), (unsigned)internal->node_ptrs[idx - 1].node_nrec); +HDfprintf(stderr, "%s: internal->node_ptrs[%u].node_nrec = %u\n", FUNC, (unsigned)idx, (unsigned)internal->node_ptrs[idx].node_nrec); +#endif /* QAK */ + /* Check for right-most child and its neighbor being close to full */ + if((internal->node_ptrs[idx - 1].node_nrec + internal->node_ptrs[idx].node_nrec) + >= ((hdr->node_info[depth - 1].split_nrec * 2) - 1)) + could_split = TRUE; + } /* end else-if */ + else { /* Middle child */ +#ifdef QAK +HDfprintf(stderr, "%s: Middle child\n", FUNC); +HDfprintf(stderr, "%s: internal->node_ptrs[%u].node_nrec = %u\n", FUNC, (unsigned)(idx - 1), (unsigned)internal->node_ptrs[idx - 1].node_nrec); +HDfprintf(stderr, "%s: internal->node_ptrs[%u].node_nrec = %u\n", FUNC, (unsigned)idx, (unsigned)internal->node_ptrs[idx].node_nrec); +HDfprintf(stderr, "%s: internal->node_ptrs[%u].node_nrec = %u\n", FUNC, (unsigned)(idx + 1), (unsigned)internal->node_ptrs[idx + 1].node_nrec); +#endif /* QAK */ + /* Check for middle child and its left neighbor being close to full */ + if((internal->node_ptrs[idx - 1].node_nrec + internal->node_ptrs[idx].node_nrec) + >= ((hdr->node_info[depth - 1].split_nrec * 2) - 1)) + could_split = TRUE; + /* Check for middle child and its right neighbor being close to full */ + else if((internal->node_ptrs[idx].node_nrec + internal->node_ptrs[idx + 1].node_nrec) + >= ((hdr->node_info[depth - 1].split_nrec * 2) - 1)) + could_split = TRUE; + } /* end if */ + + /* If this node is full and the child node insertion could + * cause a split, punt back up to caller, leaving the + * "insert child full" status. + */ + if(could_split) { + /* Release the internal B-tree node */ + if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_INT, curr_node_ptr->addr, internal, internal_flags) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release internal B-tree node") + internal = NULL; + +#ifdef QAK +HDfprintf(stderr, "%s: Punting back to caller\n", FUNC); +#endif /* QAK */ + /* Punt back to caller */ + HGOTO_DONE(SUCCEED); + } /* end if */ + } /* end if */ + + /* Release the internal B-tree node */ + if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_INT, curr_node_ptr->addr, internal, internal_flags) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release internal B-tree node") + internal = NULL; + + /* Indicate that the record was inserted */ + *status = H5B2_UPDATE_INSERT_DONE; + + /* Dodge sideways into inserting a record into this node */ + if(H5B2__insert_internal(hdr, dxpl_id, depth, parent_cache_info_flags_ptr, curr_node_ptr, curr_pos, udata) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into internal B-tree node") + break; + + case H5B2_UPDATE_UNKNOWN: + default: + HDassert(0 && "Invalid update status"); + HGOTO_ERROR(H5E_BTREE, H5E_CANTUPDATE, FAIL, "invalid update status") + } /* end switch */ + } /* end else */ + +done: + /* Release the internal B-tree node */ + if(internal && H5AC_unprotect(hdr->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__update_internal() */ + + +/*------------------------------------------------------------------------- * Function: H5B2__create_leaf * * Purpose: Creates empty leaf node of a B-tree and update node pointer diff --git a/src/H5B2pkg.h b/src/H5B2pkg.h index f58850e..d6b6c04 100644 --- a/src/H5B2pkg.h +++ b/src/H5B2pkg.h @@ -228,6 +228,14 @@ typedef enum H5B2_nodepos_t { H5B2_POS_MIDDLE /* Node is neither right or left-most in tree */ } H5B2_nodepos_t; +/* Update status */ +typedef enum H5B2_update_status_t { + H5B2_UPDATE_UNKNOWN, /* Unknown update status (initial state) */ + H5B2_UPDATE_MODIFY_DONE, /* Update successfully modified existing record */ + H5B2_UPDATE_INSERT_DONE, /* Update inserted record successfully */ + H5B2_UPDATE_INSERT_CHILD_FULL /* Update will insert record, but child is full */ +} H5B2_update_status_t; + /* Callback info for loading a free space header into the cache */ typedef struct H5B2_hdr_cache_ud_t { H5F_t *f; /* File that v2 b-tree header is within */ @@ -252,7 +260,7 @@ typedef struct H5B2_leaf_cache_ud_t { #ifdef H5B2_TESTING /* Node information for testing */ -typedef struct { +typedef struct H5B2_node_info_test_t { unsigned depth; /* Depth of node */ unsigned nrec; /* Number of records in node */ } H5B2_node_info_test_t; @@ -281,6 +289,13 @@ H5FL_EXTERN(H5B2_leaf_t); /* Internal v2 B-tree testing class */ #ifdef H5B2_TESTING H5_DLLVAR const H5B2_class_t H5B2_TEST[1]; +H5_DLLVAR const H5B2_class_t H5B2_TEST2[1]; + +/* B-tree record for testing H5B2_TEST2 class */ +typedef struct H5B2_test_rec_t { + hsize_t key; /* Key for record */ + hsize_t val; /* Value for record */ +} H5B2_test_rec_t; #endif /* H5B2_TESTING */ /* Array of v2 B-tree client ID -> client class mappings */ @@ -327,12 +342,22 @@ H5_DLL herr_t H5B2__leaf_free(H5B2_leaf_t *l); H5_DLL herr_t H5B2__internal_free(H5B2_internal_t *i); /* Routines for inserting records */ +H5_DLL herr_t H5B2__insert_hdr(H5B2_hdr_t *hdr, hid_t dxpl_id, void *udata); H5_DLL herr_t H5B2__insert_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, unsigned *parent_cache_info_flags_ptr, H5B2_node_ptr_t *curr_node_ptr, H5B2_nodepos_t curr_pos, void *udata); H5_DLL herr_t H5B2__insert_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *curr_node_ptr, H5B2_nodepos_t curr_pos, void *udata); +/* Routines for update records */ +H5_DLL herr_t H5B2__update_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, + uint16_t depth, unsigned *parent_cache_info_flags_ptr, + H5B2_node_ptr_t *curr_node_ptr, H5B2_update_status_t *status, + H5B2_nodepos_t curr_pos, void *udata, H5B2_modify_t op, void *op_data); +H5_DLL herr_t H5B2__update_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, + H5B2_node_ptr_t *curr_node_ptr, H5B2_update_status_t *status, + H5B2_nodepos_t curr_pos, void *udata, H5B2_modify_t op, void *op_data); + /* Routines for iterating over nodes/records */ H5_DLL herr_t H5B2__iterate_node(H5B2_hdr_t *hdr, hid_t dxpl_id, uint16_t depth, const H5B2_node_ptr_t *curr_node, H5B2_operator_t op, void *op_data); diff --git a/src/H5B2private.h b/src/H5B2private.h index 9e3c2d7..ff94680 100644 --- a/src/H5B2private.h +++ b/src/H5B2private.h @@ -54,6 +54,7 @@ typedef enum H5B2_subid_t { H5B2_SOHM_INDEX_ID, /* B-tree is an index for shared object header messages */ H5B2_ATTR_DENSE_NAME_ID, /* B-tree is for indexing 'name' field for "dense" attribute storage on objects */ H5B2_ATTR_DENSE_CORDER_ID, /* B-tree is for indexing 'creation order' field for "dense" attribute storage on objects */ + H5B2_TEST2_ID, /* Another B-tree is for testing (do not use for actual data) */ H5B2_NUM_BTREE_ID /* Number of B-tree IDs (must be last) */ } H5B2_subid_t; @@ -94,8 +95,6 @@ struct H5B2_class_t { herr_t (*decode)(const uint8_t *raw, void *record, void *ctx); /* Decode record from disk storage form to native form */ herr_t (*debug)(FILE *stream, int indent, int fwidth, /* Print a record for debugging */ const void *record, const void *ctx); - void *(*crt_dbg_ctx)(H5F_t *f, hid_t dxpl_id, haddr_t obj_addr); /* Create debugging context */ - herr_t (*dst_dbg_ctx)(void *dbg_ctx); /* Destroy debugging context */ }; /* v2 B-tree creation parameters */ @@ -140,6 +139,8 @@ H5_DLL herr_t H5B2_neighbor(H5B2_t *bt2, hid_t dxpl_id, H5B2_compare_t range, void *udata, H5B2_found_t op, void *op_data); H5_DLL herr_t H5B2_modify(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_modify_t op, void *op_data); +H5_DLL herr_t H5B2_update(H5B2_t *bt2, hid_t dxpl_id, void *udata, + H5B2_modify_t op, void *op_data); H5_DLL herr_t H5B2_remove(H5B2_t *b2, hid_t dxpl_id, void *udata, H5B2_remove_t op, void *op_data); H5_DLL herr_t H5B2_remove_by_idx(H5B2_t *bt2, hid_t dxpl_id, diff --git a/src/H5B2test.c b/src/H5B2test.c index 87fddf7..e0c96fb 100644 --- a/src/H5B2test.c +++ b/src/H5B2test.c @@ -61,6 +61,7 @@ typedef struct H5B2_test_ctx_t { /* Local Prototypes */ /********************/ +/* v2 B-tree driver callbacks for 'test' B-trees */ static void *H5B2__test_crt_context(void *udata); static herr_t H5B2__test_dst_context(void *ctx); static herr_t H5B2__test_store(void *nrecord, const void *udata); @@ -69,13 +70,21 @@ static herr_t H5B2__test_encode(uint8_t *raw, const void *nrecord, void *ctx); static herr_t H5B2__test_decode(const uint8_t *raw, void *nrecord, void *ctx); static herr_t H5B2__test_debug(FILE *stream, int indent, int fwidth, const void *record, const void *_udata); -static void *H5B2__test_crt_dbg_context(H5F_t *f, hid_t dxpl_id, haddr_t addr); + +/* v2 B-tree driver callbacks for 'test2' B-trees */ +static herr_t H5B2__test2_store(void *nrecord, const void *udata); +static herr_t H5B2__test2_compare(const void *rec1, const void *rec2); +static herr_t H5B2__test2_encode(uint8_t *raw, const void *nrecord, void *ctx); +static herr_t H5B2__test2_decode(const uint8_t *raw, void *nrecord, void *ctx); +static herr_t H5B2__test2_debug(FILE *stream, int indent, int fwidth, + const void *record, const void *_udata); /*********************/ /* Package Variables */ /*********************/ +/* Class structure for testing simple B-tree records */ const H5B2_class_t H5B2_TEST[1]={{ /* B-tree class information */ H5B2_TEST_ID, /* Type of B-tree */ "H5B2_TEST_ID", /* Name of B-tree class */ @@ -86,9 +95,21 @@ const H5B2_class_t H5B2_TEST[1]={{ /* B-tree class information */ H5B2__test_compare, /* Record comparison callback */ H5B2__test_encode, /* Record encoding callback */ H5B2__test_decode, /* Record decoding callback */ - H5B2__test_debug, /* Record debugging callback */ - H5B2__test_crt_dbg_context, /* Create debugging context */ - H5B2__test_dst_context /* Destroy debugging context */ + H5B2__test_debug /* Record debugging callback */ +}}; + +/* Class structure for testing key/value B-tree records */ +const H5B2_class_t H5B2_TEST2[1]={{ /* B-tree class information */ + H5B2_TEST2_ID, /* Type of B-tree */ + "H5B2_TEST2_ID", /* Name of B-tree class */ + sizeof(H5B2_test_rec_t), /* Size of native record */ + H5B2__test_crt_context, /* Create client callback context */ + H5B2__test_dst_context, /* Destroy client callback context */ + H5B2__test2_store, /* Record storage callback */ + H5B2__test2_compare, /* Record comparison callback */ + H5B2__test2_encode, /* Record encoding callback */ + H5B2__test2_decode, /* Record decoding callback */ + H5B2__test2_debug /* Record debugging callback */ }}; @@ -310,42 +331,139 @@ H5B2__test_debug(FILE *stream, int indent, int fwidth, const void *record, /*------------------------------------------------------------------------- - * Function: H5B2__test_crt_dbg_context + * Function: H5B2__test2_store * - * Purpose: Create context for debugging callback + * Purpose: Store native information into record for B-tree * - * Return: Success: non-NULL - * Failure: NULL + * Return: Success: non-negative + * Failure: negative * * Programmer: Quincey Koziol - * Tuesday, December 1, 2009 + * Friday, December 25, 2015 * *------------------------------------------------------------------------- */ -static void * -H5B2__test_crt_dbg_context(H5F_t *f, hid_t H5_ATTR_UNUSED dxpl_id, haddr_t H5_ATTR_UNUSED addr) +static herr_t +H5B2__test2_store(void *nrecord, const void *udata) { - H5B2_test_ctx_t *ctx; /* Callback context structure */ - void *ret_value = NULL; /* Return value */ + FUNC_ENTER_STATIC_NOERR - FUNC_ENTER_STATIC + *(H5B2_test_rec_t *)nrecord = *(const H5B2_test_rec_t *)udata; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5B2__test2_store() */ + + +/*------------------------------------------------------------------------- + * Function: H5B2__test2_compare + * + * Purpose: Compare two native information records, according to some key + * + * Return: <0 if rec1 < rec2 + * =0 if rec1 == rec2 + * >0 if rec1 > rec2 + * + * Programmer: Quincey Koziol + * Friday, December 25, 2015 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5B2__test2_compare(const void *rec1, const void *rec2) +{ + FUNC_ENTER_STATIC_NOERR + + FUNC_LEAVE_NOAPI((herr_t)(((const H5B2_test_rec_t *)rec1)->key - ((const H5B2_test_rec_t *)rec2)->key)) +} /* H5B2__test2_compare() */ + + +/*------------------------------------------------------------------------- + * Function: H5B2__test2_encode + * + * Purpose: Encode native information into raw form for storing on disk + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * Friday, December 25, 2015 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5B2__test2_encode(uint8_t *raw, const void *nrecord, void *_ctx) +{ + H5B2_test_ctx_t *ctx = (H5B2_test_ctx_t *)_ctx; /* Callback context structure */ + + FUNC_ENTER_STATIC_NOERR /* Sanity check */ - HDassert(f); + HDassert(ctx); - /* Allocate callback context */ - if(NULL == (ctx = H5FL_MALLOC(H5B2_test_ctx_t))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, NULL, "can't allocate callback context") + H5F_ENCODE_LENGTH_LEN(raw, ((const H5B2_test_rec_t *)nrecord)->key, ctx->sizeof_size); + H5F_ENCODE_LENGTH_LEN(raw, ((const H5B2_test_rec_t *)nrecord)->val, ctx->sizeof_size); - /* Determine the size of addresses & lengths in the file */ - ctx->sizeof_size = H5F_SIZEOF_SIZE(f); + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5B2__test2_encode() */ - /* Set return value */ - ret_value = ctx; + +/*------------------------------------------------------------------------- + * Function: H5B2__test2_decode + * + * Purpose: Decode raw disk form of record into native form + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * Friday, December 25, 2015 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5B2__test2_decode(const uint8_t *raw, void *nrecord, void *_ctx) +{ + H5B2_test_ctx_t *ctx = (H5B2_test_ctx_t *)_ctx; /* Callback context structure */ -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5B2__test_crt_dbg_context() */ + FUNC_ENTER_STATIC_NOERR + + /* Sanity check */ + HDassert(ctx); + + H5F_DECODE_LENGTH_LEN(raw, ((H5B2_test_rec_t *)nrecord)->key, ctx->sizeof_size); + H5F_DECODE_LENGTH_LEN(raw, ((H5B2_test_rec_t *)nrecord)->val, ctx->sizeof_size); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5B2__test2_decode() */ + + +/*------------------------------------------------------------------------- + * Function: H5B2__test2_debug + * + * Purpose: Debug native form of record + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * Friday, December 25, 2015 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5B2__test2_debug(FILE *stream, int indent, int fwidth, const void *record, + const void H5_ATTR_UNUSED *_udata) +{ + FUNC_ENTER_STATIC_NOERR + + HDassert(record); + + HDfprintf(stream, "%*s%-*s (%Hu, %Hu)\n", indent, "", fwidth, "Record:", + ((const H5B2_test_rec_t *)record)->key, + ((const H5B2_test_rec_t *)record)->val); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5B2__test2_debug() */ /*------------------------------------------------------------------------- diff --git a/src/H5Gbtree2.c b/src/H5Gbtree2.c index b464930..1a99b12 100644 --- a/src/H5Gbtree2.c +++ b/src/H5Gbtree2.c @@ -114,9 +114,7 @@ const H5B2_class_t H5G_BT2_NAME[1]={{ /* B-tree class information */ H5G_dense_btree2_name_compare, /* Record comparison callback */ H5G_dense_btree2_name_encode, /* Record encoding callback */ H5G_dense_btree2_name_decode, /* Record decoding callback */ - H5G_dense_btree2_name_debug, /* Record debugging callback */ - NULL, /* Create debugging context */ - NULL /* Destroy debugging context */ + H5G_dense_btree2_name_debug /* Record debugging callback */ }}; /* v2 B-tree class for indexing 'creation order' field of links */ @@ -130,9 +128,7 @@ const H5B2_class_t H5G_BT2_CORDER[1]={{ /* B-tree class information */ H5G_dense_btree2_corder_compare, /* Record comparison callback */ H5G_dense_btree2_corder_encode, /* Record encoding callback */ H5G_dense_btree2_corder_decode, /* Record decoding callback */ - H5G_dense_btree2_corder_debug, /* Record debugging callback */ - NULL, /* Create debugging context */ - NULL /* Destroy debugging context */ + H5G_dense_btree2_corder_debug /* Record debugging callback */ }}; /*****************************/ diff --git a/src/H5HFbtree2.c b/src/H5HFbtree2.c index d82de93..a79bf58 100644 --- a/src/H5HFbtree2.c +++ b/src/H5HFbtree2.c @@ -71,7 +71,6 @@ typedef struct H5HF_huge_bt2_ctx_t { /* Common callbacks */ static void *H5HF__huge_bt2_crt_context(void *udata); static herr_t H5HF__huge_bt2_dst_context(void *ctx); -static void *H5HF__huge_bt2_crt_dbg_context(H5F_t *f, hid_t dxpl_id, haddr_t addr); /* Callbacks for indirect objects */ static herr_t H5HF__huge_bt2_indir_store(void *native, const void *udata); @@ -127,9 +126,7 @@ const H5B2_class_t H5HF_HUGE_BT2_INDIR[1]={{ /* B-tree class information */ H5HF__huge_bt2_indir_compare, /* Record comparison callback */ H5HF__huge_bt2_indir_encode, /* Record encoding callback */ H5HF__huge_bt2_indir_decode, /* Record decoding callback */ - H5HF__huge_bt2_indir_debug, /* Record debugging callback */ - H5HF__huge_bt2_crt_dbg_context, /* Create debugging context */ - H5HF__huge_bt2_dst_context /* Destroy debugging context */ + H5HF__huge_bt2_indir_debug /* Record debugging callback */ }}; /* v2 B-tree class for indirectly accessed, filtered 'huge' objects */ @@ -143,9 +140,7 @@ const H5B2_class_t H5HF_HUGE_BT2_FILT_INDIR[1]={{ /* B-tree class information */ H5HF__huge_bt2_filt_indir_compare, /* Record comparison callback */ H5HF__huge_bt2_filt_indir_encode, /* Record encoding callback */ H5HF__huge_bt2_filt_indir_decode, /* Record decoding callback */ - H5HF__huge_bt2_filt_indir_debug, /* Record debugging callback */ - H5HF__huge_bt2_crt_dbg_context, /* Create debugging context */ - H5HF__huge_bt2_dst_context /* Destroy debugging context */ + H5HF__huge_bt2_filt_indir_debug /* Record debugging callback */ }}; /* v2 B-tree class for directly accessed 'huge' objects */ @@ -159,9 +154,7 @@ const H5B2_class_t H5HF_HUGE_BT2_DIR[1]={{ /* B-tree class information */ H5HF__huge_bt2_dir_compare, /* Record comparison callback */ H5HF__huge_bt2_dir_encode, /* Record encoding callback */ H5HF__huge_bt2_dir_decode, /* Record decoding callback */ - H5HF__huge_bt2_dir_debug, /* Record debugging callback */ - H5HF__huge_bt2_crt_dbg_context, /* Create debugging context */ - H5HF__huge_bt2_dst_context /* Destroy debugging context */ + H5HF__huge_bt2_dir_debug /* Record debugging callback */ }}; /* v2 B-tree class for directly accessed, filtered 'huge' objects */ @@ -175,9 +168,7 @@ const H5B2_class_t H5HF_HUGE_BT2_FILT_DIR[1]={{ /* B-tree class information */ H5HF__huge_bt2_filt_dir_compare, /* Record comparison callback */ H5HF__huge_bt2_filt_dir_encode, /* Record encoding callback */ H5HF__huge_bt2_filt_dir_decode, /* Record decoding callback */ - H5HF__huge_bt2_filt_dir_debug, /* Record debugging callback */ - H5HF__huge_bt2_crt_dbg_context, /* Create debugging context */ - H5HF__huge_bt2_dst_context /* Destroy debugging context */ + H5HF__huge_bt2_filt_dir_debug /* Record debugging callback */ }}; /*****************************/ @@ -270,46 +261,6 @@ H5HF__huge_bt2_dst_context(void *_ctx) /*------------------------------------------------------------------------- - * Function: H5HF__huge_bt2_crt_dbg_context - * - * Purpose: Create context for debugging callback - * - * Return: Success: non-NULL - * Failure: NULL - * - * Programmer: Quincey Koziol - * Tuesday, December 1, 2009 - * - *------------------------------------------------------------------------- - */ -static void * -H5HF__huge_bt2_crt_dbg_context(H5F_t *f, hid_t H5_ATTR_UNUSED dxpl_id, haddr_t H5_ATTR_UNUSED addr) -{ - H5HF_huge_bt2_ctx_t *ctx; /* Callback context structure */ - void *ret_value = NULL; /* Return value */ - - FUNC_ENTER_STATIC - - /* Sanity check */ - HDassert(f); - - /* Allocate callback context */ - if(NULL == (ctx = H5FL_MALLOC(H5HF_huge_bt2_ctx_t))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "can't allocate callback context") - - /* Determine the size of addresses & lengths in the file */ - ctx->sizeof_addr = H5F_SIZEOF_ADDR(f); - ctx->sizeof_size = H5F_SIZEOF_SIZE(f); - - /* Set return value */ - ret_value = ctx; - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5HF__huge_bt2_crt_dbg_context() */ - - -/*------------------------------------------------------------------------- * Function: H5HF__huge_bt2_indir_found * * Purpose: Retrieve record for indirectly accessed 'huge' object, when diff --git a/src/H5SMbtree2.c b/src/H5SMbtree2.c index e533ae8..0110c1e 100644 --- a/src/H5SMbtree2.c +++ b/src/H5SMbtree2.c @@ -50,7 +50,6 @@ static herr_t H5SM__bt2_dst_context(void *ctx); static herr_t H5SM__bt2_store(void *native, const void *udata); static herr_t H5SM__bt2_debug(FILE *stream, int indent, int fwidth, const void *record, const void *_udata); -static void *H5SM__bt2_crt_dbg_context(H5F_t *f, hid_t dxpl_id, haddr_t addr); /*****************************/ @@ -67,9 +66,7 @@ const H5B2_class_t H5SM_INDEX[1]={{ /* B-tree class information */ H5SM__message_compare, /* Record comparison callback */ H5SM__message_encode, /* Record encoding callback */ H5SM__message_decode, /* Record decoding callback */ - H5SM__bt2_debug, /* Record debugging callback */ - H5SM__bt2_crt_dbg_context, /* Create debugging context */ - H5SM__bt2_dst_context /* Destroy debugging context */ + H5SM__bt2_debug /* Record debugging callback */ }}; @@ -218,45 +215,6 @@ H5SM__bt2_debug(FILE *stream, int indent, int fwidth, /*------------------------------------------------------------------------- - * Function: H5SM__bt2_crt_dbg_context - * - * Purpose: Create context for debugging callback - * - * Return: Success: non-NULL - * Failure: NULL - * - * Programmer: Quincey Koziol - * Tuesday, December 1, 2009 - * - *------------------------------------------------------------------------- - */ -static void * -H5SM__bt2_crt_dbg_context(H5F_t *f, hid_t H5_ATTR_UNUSED dxpl_id, haddr_t H5_ATTR_UNUSED addr) -{ - H5SM_bt2_ctx_t *ctx; /* Callback context structure */ - void *ret_value = NULL; /* Return value */ - - FUNC_ENTER_STATIC - - /* Sanity check */ - HDassert(f); - - /* Allocate callback context */ - if(NULL == (ctx = H5FL_MALLOC(H5SM_bt2_ctx_t))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "can't allocate callback context") - - /* Determine the size of addresses & lengths in the file */ - ctx->sizeof_addr = H5F_SIZEOF_ADDR(f); - - /* Set return value */ - ret_value = ctx; - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5SM__bt2_crt_dbg_context() */ - - -/*------------------------------------------------------------------------- * Function: H5SM_bt2_convert_to_list_op * * Purpose: An H5B2_remove_t callback function to convert a SOHM |