mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-03-31 17:10:47 +08:00
[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)
This commit is contained in:
parent
6d8b831b31
commit
b5504be6cc
@ -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 */
|
||||
}};
|
||||
|
||||
|
||||
|
74
src/H5B2.c
74
src/H5B2.c
@ -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)
|
||||
|
@ -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)
|
||||
|
401
src/H5B2int.c
401
src/H5B2int.c
@ -1511,6 +1511,62 @@ done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5B2__swap_leaf() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* 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
|
||||
@ -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 */
|
||||
@ -1753,6 +1812,348 @@ done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* H5B2__insert_internal() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* 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
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
168
src/H5B2test.c
168
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() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
|
@ -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 */
|
||||
}};
|
||||
|
||||
/*****************************/
|
||||
|
@ -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 */
|
||||
}};
|
||||
|
||||
/*****************************/
|
||||
@ -268,46 +259,6 @@ H5HF__huge_bt2_dst_context(void *_ctx)
|
||||
FUNC_LEAVE_NOAPI(SUCCEED)
|
||||
} /* H5HF__huge_bt2_dst_context() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* 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
|
||||
|
@ -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 */
|
||||
}};
|
||||
|
||||
|
||||
@ -216,45 +213,6 @@ H5SM__bt2_debug(FILE *stream, int indent, int fwidth,
|
||||
FUNC_LEAVE_NOAPI(SUCCEED)
|
||||
} /* end H5SM__bt2_debug */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* 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
|
||||
|
2626
test/btree2.c
2626
test/btree2.c
File diff suppressed because it is too large
Load Diff
@ -121,6 +121,10 @@ get_H5B2_class(const uint8_t *sig)
|
||||
cls = H5A_BT2_CORDER;
|
||||
break;
|
||||
|
||||
case H5B2_TEST2_ID:
|
||||
cls = H5B2_TEST2;
|
||||
break;
|
||||
|
||||
case H5B2_NUM_BTREE_ID:
|
||||
default:
|
||||
HDfprintf(stderr, "Unknown v2 B-tree subtype %u\n", (unsigned)(subtype));
|
||||
|
Loading…
x
Reference in New Issue
Block a user