summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNeil Fortner <nfortne2@hdfgroup.org>2012-05-30 22:01:00 (GMT)
committerNeil Fortner <nfortne2@hdfgroup.org>2012-05-30 22:01:00 (GMT)
commit9786c0e5cb563c362c9b6f5b9bd0730b9ddcadf6 (patch)
tree006f9f714a95e349ae313fd76afdae9a45910c19 /src
parent1f6cb6f84a0fdeec79938624ef874d4147d52d87 (diff)
downloadhdf5-9786c0e5cb563c362c9b6f5b9bd0730b9ddcadf6.zip
hdf5-9786c0e5cb563c362c9b6f5b9bd0730b9ddcadf6.tar.gz
hdf5-9786c0e5cb563c362c9b6f5b9bd0730b9ddcadf6.tar.bz2
[svn-r22422] Purpose: Add support for SWMR with v2 b-trees
Description: Adds SWMR support to the v2 b-trees when used as a chunk index. Because each node keeps track of the total number of records reachable through each of its children, nodes must be shadowed every time a descendent record is inserted or removed. This implementation prevents this from happening, however, if the node has already been shadowed since the last time the v2 b-tree header was flushed. Also modified SWMR test to include v2 b-trees. Tested: jam, koala, ostrich (h5committest), durandal Note: There is a preexisting failure in the ph5diff (-v) test
Diffstat (limited to 'src')
-rw-r--r--src/H5Abtree2.c4
-rw-r--r--src/H5Adense.c103
-rw-r--r--src/H5Aint.c12
-rw-r--r--src/H5Apkg.h25
-rw-r--r--src/H5B2.c471
-rw-r--r--src/H5B2cache.c195
-rw-r--r--src/H5B2dbg.c7
-rw-r--r--src/H5B2hdr.c15
-rw-r--r--src/H5B2int.c1595
-rw-r--r--src/H5B2pkg.h62
-rw-r--r--src/H5B2private.h16
-rw-r--r--src/H5B2stat.c2
-rw-r--r--src/H5B2test.c37
-rw-r--r--src/H5Bprivate.h4
-rw-r--r--src/H5Dbtree2.c469
-rw-r--r--src/H5Gbtree2.c4
-rw-r--r--src/H5Gdense.c32
-rw-r--r--src/H5Gobj.c2
-rw-r--r--src/H5Goh.c4
-rw-r--r--src/H5Gtest.c4
-rw-r--r--src/H5HFbtree2.c8
-rw-r--r--src/H5HFhuge.c16
-rw-r--r--src/H5HFstat.c2
-rw-r--r--src/H5Oainfo.c13
-rw-r--r--src/H5Oattribute.c32
-rw-r--r--src/H5Oprivate.h3
-rw-r--r--src/H5Otest.c14
-rw-r--r--src/H5SM.c20
-rw-r--r--src/H5SMbtree2.c2
29 files changed, 2814 insertions, 359 deletions
diff --git a/src/H5Abtree2.c b/src/H5Abtree2.c
index 5a15c20..afaab84 100644
--- a/src/H5Abtree2.c
+++ b/src/H5Abtree2.c
@@ -116,6 +116,8 @@ 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 */
+ NULL, /* Create flush dependency *//*!FIXME write me -NAF */
+ NULL, /* Update flush dependency *//*!FIXME write me -NAF */
H5A_dense_btree2_name_debug, /* Record debugging callback */
NULL, /* Create debugging context */
NULL /* Destroy debugging context */
@@ -132,6 +134,8 @@ 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 */
+ NULL, /* Create flush dependency *//*!FIXME write me -NAF */
+ NULL, /* Update flush dependency *//*!FIXME write me -NAF */
H5A_dense_btree2_corder_debug, /* Record debugging callback */
NULL, /* Create debugging context */
NULL /* Destroy debugging context */
diff --git a/src/H5Adense.c b/src/H5Adense.c
index 4c10255..3005749 100644
--- a/src/H5Adense.c
+++ b/src/H5Adense.c
@@ -126,6 +126,7 @@ typedef struct H5A_bt2_ud_rm_t {
/* downward */
H5A_bt2_ud_common_t common; /* Common info for B-tree user data (must be first) */
haddr_t corder_bt2_addr; /* v2 B-tree address of creation order index */
+ void *parent; /* Flush dependency parent */
} H5A_bt2_ud_rm_t;
/*
@@ -140,6 +141,7 @@ typedef struct H5A_bt2_ud_rmbi_t {
H5HF_t *shared_fheap; /* Fractal heap handle for shared messages */
H5_index_t idx_type; /* Index type for operation */
haddr_t other_bt2_addr; /* v2 B-tree address of "other" index */
+ void *parent; /* Flush dependency parent */
} H5A_bt2_ud_rmbi_t;
@@ -183,7 +185,7 @@ typedef struct H5A_bt2_ud_rmbi_t {
*-------------------------------------------------------------------------
*/
herr_t
-H5A_dense_create(H5F_t *f, hid_t dxpl_id, H5O_ainfo_t *ainfo)
+H5A_dense_create(H5F_t *f, hid_t dxpl_id, H5O_ainfo_t *ainfo, void *parent)
{
H5HF_create_t fheap_cparam; /* Fractal heap creation parameters */
H5B2_create_t bt2_cparam; /* v2 B-tree creation parameters */
@@ -246,7 +248,7 @@ HDfprintf(stderr, "%s: fheap_id_len = %Zu\n", FUNC, fheap_id_len);
H5O_FHEAP_ID_LEN; /* Fractal heap ID */
bt2_cparam.split_percent = H5A_NAME_BT2_SPLIT_PERC;
bt2_cparam.merge_percent = H5A_NAME_BT2_MERGE_PERC;
- if(NULL == (bt2_name = H5B2_create(f, dxpl_id, &bt2_cparam, NULL)))
+ if(NULL == (bt2_name = H5B2_create(f, dxpl_id, &bt2_cparam, NULL, parent)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to create v2 B-tree for name index")
/* Retrieve the v2 B-tree's address in the file */
@@ -267,7 +269,7 @@ HDfprintf(stderr, "%s: ainfo->name_bt2_addr = %a\n", FUNC, ainfo->name_bt2_addr)
H5O_FHEAP_ID_LEN; /* Fractal heap ID */
bt2_cparam.split_percent = H5A_CORDER_BT2_SPLIT_PERC;
bt2_cparam.merge_percent = H5A_CORDER_BT2_MERGE_PERC;
- if(NULL == (bt2_corder = H5B2_create(f, dxpl_id, &bt2_cparam, NULL)))
+ if(NULL == (bt2_corder = H5B2_create(f, dxpl_id, &bt2_cparam, NULL, parent)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to create v2 B-tree for creation order index")
/* Retrieve the v2 B-tree's address in the file */
@@ -339,7 +341,8 @@ H5A_dense_fnd_cb(const H5A_t *attr, hbool_t *took_ownership, void *_user_attr)
*-------------------------------------------------------------------------
*/
H5A_t *
-H5A_dense_open(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *name)
+H5A_dense_open(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
+ const char *name, void *parent)
{
H5A_bt2_ud_common_t udata; /* User data for v2 B-tree modify */
H5HF_t *fheap = NULL; /* Fractal heap handle */
@@ -383,7 +386,7 @@ H5A_dense_open(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *na
} /* end if */
/* Open the name index v2 B-tree */
- if(NULL == (bt2_name = H5B2_open(f, dxpl_id, ainfo->name_bt2_addr, NULL)))
+ if(NULL == (bt2_name = H5B2_open(f, dxpl_id, ainfo->name_bt2_addr, NULL, parent)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to open v2 B-tree for name index")
/* Create the "udata" information for v2 B-tree record find */
@@ -442,6 +445,7 @@ H5A_dense_insert(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, H5A_t *attr)
uint8_t attr_buf[H5A_ATTR_BUF_SIZE]; /* Buffer for serializing message */
unsigned mesg_flags = 0; /* Flags for storing message */
htri_t attr_sharable; /* Flag indicating attributes are sharable */
+ H5O_t *oh = NULL; /* Attribute's object header */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -527,8 +531,15 @@ H5A_dense_insert(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, H5A_t *attr)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to insert attribute into fractal heap")
} /* end else */
+ /* Check for SWMR writes to the file */
+ if(H5F_INTENT(f) & H5F_ACC_SWMR_WRITE)
+ /* Pin the attribute's object header */
+ /*!FIXME change to use ohdr proxy once those changes are merged -NAF */
+ if(NULL == (oh = H5O_pin(&attr->oloc, dxpl_id)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTPIN, FAIL, "unable to pin attribute object header")
+
/* Open the name index v2 B-tree */
- if(NULL == (bt2_name = H5B2_open(f, dxpl_id, ainfo->name_bt2_addr, NULL)))
+ if(NULL == (bt2_name = H5B2_open(f, dxpl_id, ainfo->name_bt2_addr, NULL, oh)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index")
/* Create the callback information for v2 B-tree record insertion */
@@ -551,8 +562,9 @@ H5A_dense_insert(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, H5A_t *attr)
/* Check if we should create a creation order index v2 B-tree record */
if(ainfo->index_corder) {
/* Open the creation order index v2 B-tree */
+ /*!FIXME use ohdr proxy -NAF */
HDassert(H5F_addr_defined(ainfo->corder_bt2_addr));
- if(NULL == (bt2_corder = H5B2_open(f, dxpl_id, ainfo->corder_bt2_addr, NULL)))
+ if(NULL == (bt2_corder = H5B2_open(f, dxpl_id, ainfo->corder_bt2_addr, NULL, oh)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for creation order index")
/* Insert the record into the creation order index v2 B-tree */
@@ -562,6 +574,8 @@ H5A_dense_insert(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, H5A_t *attr)
done:
/* Release resources */
+ if(oh && H5O_unpin(oh) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTUNPIN, FAIL, "unable to unpin attribute object header")
if(shared_fheap && H5HF_close(shared_fheap, dxpl_id) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
if(fheap && H5HF_close(fheap, dxpl_id) < 0)
@@ -636,6 +650,7 @@ H5A_dense_write_bt2_cb(void *_record, void *_op_data, hbool_t *changed)
H5B2_t *bt2_corder = NULL; /* v2 B-tree handle for creation order index */
H5WB_t *wb = NULL; /* Wrapped buffer for attribute data */
uint8_t attr_buf[H5A_ATTR_BUF_SIZE]; /* Buffer for serializing attribute */
+ H5O_t *oh = NULL; /* Attribute's object header */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -659,8 +674,16 @@ H5A_dense_write_bt2_cb(void *_record, void *_op_data, hbool_t *changed)
if(H5F_addr_defined(op_data->corder_bt2_addr)) {
H5A_bt2_ud_common_t udata; /* User data for v2 B-tree modify */
+ /* Check for SWMR writes to the file */
+ if(H5F_INTENT(op_data->f) & H5F_ACC_SWMR_WRITE)
+ /* Pin the attribute's object header */
+ /*!FIXME change to use ohdr proxy once those changes are merged -NAF */
+ if(NULL == (oh = H5O_pin(&op_data->attr->oloc, op_data->dxpl_id)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTPIN, FAIL, "unable to pin attribute object header")
+
/* Open the creation order index v2 B-tree */
- if(NULL == (bt2_corder = H5B2_open(op_data->f, op_data->dxpl_id, op_data->corder_bt2_addr, NULL)))
+ /*!FIXME use ohdr proxy -NAF */
+ if(NULL == (bt2_corder = H5B2_open(op_data->f, op_data->dxpl_id, op_data->corder_bt2_addr, NULL, oh)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for creation order index")
/* Create the "udata" information for v2 B-tree record modify */
@@ -721,6 +744,8 @@ H5A_dense_write_bt2_cb(void *_record, void *_op_data, hbool_t *changed)
done:
/* Release resources */
+ if(oh && H5O_unpin(oh) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTUNPIN, FAIL, "unable to unpin attribute object header")
if(bt2_corder && H5B2_close(bt2_corder, op_data->dxpl_id) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for creation order index")
if(wb && H5WB_unwrap(wb) < 0)
@@ -752,6 +777,7 @@ H5A_dense_write(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, H5A_t *attr)
H5HF_t *shared_fheap = NULL; /* Fractal heap handle for shared header messages */
H5B2_t *bt2_name = NULL; /* v2 B-tree handle for name index */
htri_t attr_sharable; /* Flag indicating attributes are sharable */
+ H5O_t *oh = NULL; /* Attribute's object header */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -789,8 +815,16 @@ H5A_dense_write(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, H5A_t *attr)
if(NULL == (fheap = H5HF_open(f, dxpl_id, ainfo->fheap_addr)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
+ /* Check for SWMR writes to the file */
+ if(H5F_INTENT(f) & H5F_ACC_SWMR_WRITE)
+ /* Pin the attribute's object header */
+ /*!FIXME change to use ohdr proxy once those changes are merged -NAF */
+ if(NULL == (oh = H5O_pin(&attr->oloc, dxpl_id)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTPIN, FAIL, "unable to pin attribute object header")
+
/* Open the name index v2 B-tree */
- if(NULL == (bt2_name = H5B2_open(f, dxpl_id, ainfo->name_bt2_addr, NULL)))
+ /*!FIXME use ohdr proxy -NAF */
+ if(NULL == (bt2_name = H5B2_open(f, dxpl_id, ainfo->name_bt2_addr, NULL, oh)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index")
/* Create the "udata" information for v2 B-tree record modify */
@@ -819,6 +853,8 @@ H5A_dense_write(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, H5A_t *attr)
done:
/* Release resources */
+ if(oh && H5O_unpin(oh) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTUNPIN, FAIL, "unable to unpin attribute object header")
if(shared_fheap && H5HF_close(shared_fheap, dxpl_id) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
if(fheap && H5HF_close(fheap, dxpl_id) < 0)
@@ -888,8 +924,8 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *old_name,
- const char *new_name)
+H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
+ const char *old_name, const char *new_name, void *parent)
{
H5A_bt2_ud_common_t udata; /* User data for v2 B-tree modify */
H5HF_t *fheap = NULL; /* Fractal heap handle */
@@ -936,7 +972,7 @@ H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
/* Open the name index v2 B-tree */
- if(NULL == (bt2_name = H5B2_open(f, dxpl_id, ainfo->name_bt2_addr, NULL)))
+ if(NULL == (bt2_name = H5B2_open(f, dxpl_id, ainfo->name_bt2_addr, NULL, parent)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index")
/* Create the "udata" information for v2 B-tree record modify */
@@ -1011,7 +1047,7 @@ H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *
HGOTO_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL, "error determining if message should be shared")
/* Delete old attribute from dense storage */
- if(H5A_dense_remove(f, dxpl_id, ainfo, old_name) < 0)
+ if(H5A_dense_remove(f, dxpl_id, ainfo, old_name, parent) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute in dense storage")
done:
@@ -1140,8 +1176,9 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5A_dense_iterate(H5F_t *f, hid_t dxpl_id, hid_t loc_id, const H5O_ainfo_t *ainfo,
- H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_attr,
+H5A_dense_iterate(H5F_t *f, hid_t dxpl_id, hid_t loc_id,
+ const H5O_ainfo_t *ainfo, H5_index_t idx_type, H5_iter_order_t order,
+ hsize_t skip, void *parent, hsize_t *last_attr,
const H5A_attr_iter_op_t *attr_op, void *op_data)
{
H5HF_t *fheap = NULL; /* Fractal heap handle */
@@ -1215,7 +1252,7 @@ H5A_dense_iterate(H5F_t *f, hid_t dxpl_id, hid_t loc_id, const H5O_ainfo_t *ainf
} /* end if */
/* Open the index v2 B-tree */
- if(NULL == (bt2 = H5B2_open(f, dxpl_id, bt2_addr, NULL)))
+ if(NULL == (bt2 = H5B2_open(f, dxpl_id, bt2_addr, NULL, parent)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for index")
/* Construct the user data for v2 B-tree iterator callback */
@@ -1241,7 +1278,7 @@ H5A_dense_iterate(H5F_t *f, hid_t dxpl_id, hid_t loc_id, const H5O_ainfo_t *ainf
else {
/* Build the table of attributes for this object */
/* (build table using the name index, but sort according to idx_type) */
- if(H5A_dense_build_table(f, dxpl_id, ainfo, idx_type, order, &atable) < 0)
+ if(H5A_dense_build_table(f, dxpl_id, ainfo, idx_type, order, parent, &atable) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "error building table of attributes")
/* Iterate over attributes in table */
@@ -1291,7 +1328,7 @@ H5A_dense_remove_bt2_cb(const void *_record, void *_udata)
/* Check for removing the link from the creation order index */
if(H5F_addr_defined(udata->corder_bt2_addr)) {
/* Open the creation order index v2 B-tree */
- if(NULL == (bt2_corder = H5B2_open(udata->common.f, udata->common.dxpl_id, udata->corder_bt2_addr, NULL)))
+ if(NULL == (bt2_corder = H5B2_open(udata->common.f, udata->common.dxpl_id, udata->corder_bt2_addr, NULL, udata->parent)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for creation order index")
/* Set up the user data for the v2 B-tree 'record remove' callback */
@@ -1342,7 +1379,8 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5A_dense_remove(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *name)
+H5A_dense_remove(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
+ const char *name, void *parent)
{
H5A_bt2_ud_rm_t udata; /* User data for v2 B-tree record removal */
H5HF_t *fheap = NULL; /* Fractal heap handle */
@@ -1386,7 +1424,7 @@ H5A_dense_remove(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *
} /* end if */
/* Open the name index v2 B-tree */
- if(NULL == (bt2_name = H5B2_open(f, dxpl_id, ainfo->name_bt2_addr, NULL)))
+ if(NULL == (bt2_name = H5B2_open(f, dxpl_id, ainfo->name_bt2_addr, NULL, parent)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index")
/* Set up the user data for the v2 B-tree 'record remove' callback */
@@ -1399,6 +1437,7 @@ H5A_dense_remove(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *
udata.common.found_op = H5A_dense_fnd_cb; /* v2 B-tree comparison callback */
udata.common.found_op_data = &attr_copy;
udata.corder_bt2_addr = ainfo->corder_bt2_addr;
+ udata.parent = parent;
/* Remove the record from the name index v2 B-tree */
if(H5B2_remove(bt2_name, dxpl_id, &udata, H5A_dense_remove_bt2_cb, &udata) < 0)
@@ -1500,7 +1539,7 @@ H5A_dense_remove_by_idx_bt2_cb(const void *_record, void *_bt2_udata)
} /* end else */
/* Open the index v2 B-tree */
- if(NULL == (bt2 = H5B2_open(bt2_udata->f, bt2_udata->dxpl_id, bt2_udata->other_bt2_addr, NULL)))
+ if(NULL == (bt2 = H5B2_open(bt2_udata->f, bt2_udata->dxpl_id, bt2_udata->other_bt2_addr, NULL, bt2_udata->parent)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for index")
/* Set the common information for the v2 B-tree remove operation */
@@ -1562,7 +1601,7 @@ done:
*/
herr_t
H5A_dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
- H5_index_t idx_type, H5_iter_order_t order, hsize_t n)
+ H5_index_t idx_type, H5_iter_order_t order, hsize_t n, void *parent)
{
H5HF_t *fheap = NULL; /* Fractal heap handle */
H5HF_t *shared_fheap = NULL; /* Fractal heap handle for shared header messages */
@@ -1632,7 +1671,7 @@ H5A_dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
} /* end if */
/* Open the index v2 B-tree */
- if(NULL == (bt2 = H5B2_open(f, dxpl_id, bt2_addr, NULL)))
+ if(NULL == (bt2 = H5B2_open(f, dxpl_id, bt2_addr, NULL, parent)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for index")
/* Set up the user data for the v2 B-tree 'record remove' callback */
@@ -1642,15 +1681,16 @@ H5A_dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
udata.shared_fheap = shared_fheap;
udata.idx_type = idx_type;
udata.other_bt2_addr = idx_type == H5_INDEX_NAME ? ainfo->corder_bt2_addr : ainfo->name_bt2_addr;
+ udata.parent = parent;
/* Remove the record from the name index v2 B-tree */
- if(H5B2_remove_by_idx(bt2, dxpl_id, order, n, H5A_dense_remove_by_idx_bt2_cb, &udata) < 0)
+ if(H5B2_remove_by_idx(bt2, dxpl_id, order, n, NULL, H5A_dense_remove_by_idx_bt2_cb, &udata) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTREMOVE, FAIL, "unable to remove attribute from v2 B-tree index")
} /* end if */
else {
/* Build the table of attributes for this object */
/* (build table using the name index, but sort according to idx_type) */
- if(H5A_dense_build_table(f, dxpl_id, ainfo, idx_type, order, &atable) < 0)
+ if(H5A_dense_build_table(f, dxpl_id, ainfo, idx_type, order, parent, &atable) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "error building table of attributes")
/* Check for skipping too many attributes */
@@ -1658,7 +1698,7 @@ H5A_dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified")
/* Delete appropriate attribute from dense storage */
- if(H5A_dense_remove(f, dxpl_id, ainfo, ((atable.attrs[n])->shared)->name) < 0)
+ if(H5A_dense_remove(f, dxpl_id, ainfo, ((atable.attrs[n])->shared)->name, parent) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute in dense storage")
} /* end else */
@@ -1692,7 +1732,8 @@ done:
*-------------------------------------------------------------------------
*/
htri_t
-H5A_dense_exists(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *name)
+H5A_dense_exists(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
+ const char *name, void *parent)
{
H5A_bt2_ud_common_t udata; /* User data for v2 B-tree modify */
H5HF_t *fheap = NULL; /* Fractal heap handle */
@@ -1735,7 +1776,7 @@ H5A_dense_exists(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *
} /* end if */
/* Open the name index v2 B-tree */
- if(NULL == (bt2_name = H5B2_open(f, dxpl_id, ainfo->name_bt2_addr, NULL)))
+ if(NULL == (bt2_name = H5B2_open(f, dxpl_id, ainfo->name_bt2_addr, NULL, parent)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index")
/* Create the "udata" information for v2 B-tree record 'find' */
@@ -1846,7 +1887,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5A_dense_delete(H5F_t *f, hid_t dxpl_id, H5O_ainfo_t *ainfo)
+H5A_dense_delete(H5F_t *f, hid_t dxpl_id, H5O_ainfo_t *ainfo, void *parent)
{
H5A_bt2_ud_common_t udata; /* v2 B-tree user data for deleting attributes */
H5HF_t *fheap = NULL; /* Fractal heap handle */
@@ -1876,7 +1917,7 @@ H5A_dense_delete(H5F_t *f, hid_t dxpl_id, H5O_ainfo_t *ainfo)
udata.found_op_data = NULL;
/* Delete name index v2 B-tree */
- if(H5B2_delete(f, dxpl_id, ainfo->name_bt2_addr, NULL, H5A_dense_delete_bt2_cb, &udata) < 0)
+ if(H5B2_delete(f, dxpl_id, ainfo->name_bt2_addr, NULL, parent, H5A_dense_delete_bt2_cb, &udata) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete v2 B-tree for name index")
ainfo->name_bt2_addr = HADDR_UNDEF;
@@ -1888,7 +1929,7 @@ H5A_dense_delete(H5F_t *f, hid_t dxpl_id, H5O_ainfo_t *ainfo)
/* Check if we should delete the creation order index v2 B-tree */
if(H5F_addr_defined(ainfo->corder_bt2_addr)) {
/* Delete the creation order index, without adjusting the ref. count on the attributes */
- if(H5B2_delete(f, dxpl_id, ainfo->corder_bt2_addr, NULL, NULL, NULL) < 0)
+ if(H5B2_delete(f, dxpl_id, ainfo->corder_bt2_addr, NULL, parent, NULL, NULL) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete v2 B-tree for creation order index")
ainfo->corder_bt2_addr = HADDR_UNDEF;
} /* end if */
diff --git a/src/H5Aint.c b/src/H5Aint.c
index 74c5590..14c2c65 100644
--- a/src/H5Aint.c
+++ b/src/H5Aint.c
@@ -308,7 +308,8 @@ done:
*/
herr_t
H5A_dense_build_table(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
- H5_index_t idx_type, H5_iter_order_t order, H5A_attr_table_t *atable)
+ H5_index_t idx_type, H5_iter_order_t order, void *parent,
+ H5A_attr_table_t *atable)
{
H5B2_t *bt2_name = NULL; /* v2 B-tree handle for name index */
hsize_t nrec; /* # of records in v2 B-tree */
@@ -324,7 +325,7 @@ H5A_dense_build_table(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
HDassert(atable);
/* Open the name index v2 B-tree */
- if(NULL == (bt2_name = H5B2_open(f, dxpl_id, ainfo->name_bt2_addr, NULL)))
+ if(NULL == (bt2_name = H5B2_open(f, dxpl_id, ainfo->name_bt2_addr, NULL, parent)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index")
/* Retrieve # of records in "name" B-tree */
@@ -355,7 +356,7 @@ H5A_dense_build_table(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
/* Iterate over the links in the group, building a table of the link messages */
if(H5A_dense_iterate(f, dxpl_id, (hid_t)0, ainfo, H5_INDEX_NAME,
- H5_ITER_NATIVE, (hsize_t)0, NULL, &attr_op, &udata) < 0)
+ H5_ITER_NATIVE, (hsize_t)0, parent, NULL, &attr_op, &udata) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "error building attribute table")
/* Sort attribute table in correct iteration order */
@@ -711,7 +712,8 @@ H5A_get_ainfo(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5O_ainfo_t *ainfo)
/* Check if we are using "dense" attribute storage */
if(H5F_addr_defined(ainfo->fheap_addr)) {
/* Open the name index v2 B-tree */
- if(NULL == (bt2_name = H5B2_open(f, dxpl_id, ainfo->name_bt2_addr, NULL)))
+ /*!FIXME use ohdr proxy -NAF */
+ if(NULL == (bt2_name = H5B2_open(f, dxpl_id, ainfo->name_bt2_addr, NULL, oh)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index")
/* Retrieve # of records in "name" B-tree */
@@ -1252,7 +1254,7 @@ H5A_dense_post_copy_file_all(const H5O_loc_t *src_oloc, const H5O_ainfo_t *ainfo
if(H5A_dense_iterate(src_oloc->file, dxpl_id, (hid_t)0, ainfo_src, H5_INDEX_NAME,
- H5_ITER_NATIVE, (hsize_t)0, NULL, &attr_op, &udata) < 0)
+ H5_ITER_NATIVE, (hsize_t)0, NULL, NULL, &attr_op, &udata) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "error building attribute table")
done:
diff --git a/src/H5Apkg.h b/src/H5Apkg.h
index 26c8dff..c1d0c90 100644
--- a/src/H5Apkg.h
+++ b/src/H5Apkg.h
@@ -200,26 +200,29 @@ H5_DLL htri_t H5A_get_ainfo(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5O_ainfo_t *ain
H5_DLL herr_t H5A_set_version(const H5F_t *f, H5A_t *attr);
/* Attribute "dense" storage routines */
-H5_DLL herr_t H5A_dense_create(H5F_t *f, hid_t dxpl_id, H5O_ainfo_t *ainfo);
+H5_DLL herr_t H5A_dense_create(H5F_t *f, hid_t dxpl_id, H5O_ainfo_t *ainfo,
+ void *parent);
H5_DLL H5A_t *H5A_dense_open(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
- const char *name);
+ const char *name, void *parent);
H5_DLL herr_t H5A_dense_insert(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
H5A_t *attr);
H5_DLL herr_t H5A_dense_write(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
H5A_t *attr);
H5_DLL herr_t H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
- const char *old_name, const char *new_name);
+ const char *old_name, const char *new_name, void *parent);
H5_DLL herr_t H5A_dense_iterate(H5F_t *f, hid_t dxpl_id, hid_t loc_id,
const H5O_ainfo_t *ainfo, H5_index_t idx_type, H5_iter_order_t order,
- hsize_t skip, hsize_t *last_attr, const H5A_attr_iter_op_t *attr_op,
+ hsize_t skip, void *parent, hsize_t *last_attr, const H5A_attr_iter_op_t *attr_op,
void *op_data);
-H5_DLL herr_t H5A_dense_remove(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
- const char *name);
-H5_DLL herr_t H5A_dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
- H5_index_t idx_type, H5_iter_order_t order, hsize_t n);
+H5_DLL herr_t H5A_dense_remove(H5F_t *f, hid_t dxpl_id,
+ const H5O_ainfo_t *ainfo, const char *name, void *parent);
+H5_DLL herr_t H5A_dense_remove_by_idx(H5F_t *f, hid_t dxpl_id,
+ const H5O_ainfo_t *ainfo, H5_index_t idx_type, H5_iter_order_t order,
+ hsize_t n, void *parent);
H5_DLL htri_t H5A_dense_exists(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
- const char *name);
-H5_DLL herr_t H5A_dense_delete(H5F_t *f, hid_t dxpl_id, H5O_ainfo_t *ainfo);
+ const char *name, void *parent);
+H5_DLL herr_t H5A_dense_delete(H5F_t *f, hid_t dxpl_id, H5O_ainfo_t *ainfo,
+ void *parent);
/* Attribute table operations */
@@ -227,7 +230,7 @@ H5_DLL herr_t H5A_compact_build_table(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
H5_index_t idx_type, H5_iter_order_t order, H5A_attr_table_t *atable);
H5_DLL herr_t H5A_dense_build_table(H5F_t *f, hid_t dxpl_id,
const H5O_ainfo_t *ainfo, H5_index_t idx_type, H5_iter_order_t order,
- H5A_attr_table_t *atable);
+ void *parent, H5A_attr_table_t *atable);
H5_DLL herr_t H5A_attr_iterate_table(const H5A_attr_table_t *atable,
hsize_t skip, hsize_t *last_attr, hid_t loc_id,
const H5A_attr_iter_op_t *attr_op, void *op_data);
diff --git a/src/H5B2.c b/src/H5B2.c
index 003f83e..5a77c30 100644
--- a/src/H5B2.c
+++ b/src/H5B2.c
@@ -130,7 +130,8 @@ H5FL_DEFINE_STATIC(H5B2_t);
*-------------------------------------------------------------------------
*/
H5B2_t *
-H5B2_create(H5F_t *f, hid_t dxpl_id, const H5B2_create_t *cparam, void *ctx_udata)
+H5B2_create(H5F_t *f, hid_t dxpl_id, const H5B2_create_t *cparam,
+ void *ctx_udata, void *parent)
{
H5B2_t *bt2 = NULL; /* Pointer to the B-tree */
H5B2_hdr_t *hdr = NULL; /* Pointer to the B-tree header */
@@ -150,7 +151,7 @@ H5B2_create(H5F_t *f, hid_t dxpl_id, const H5B2_create_t *cparam, void *ctx_udat
HDcompile_assert(H5B2_NUM_BTREE_ID == NELMTS(H5B2_client_class_g));
/* Create shared v2 B-tree header */
- if(HADDR_UNDEF == (hdr_addr = H5B2_hdr_create(f, dxpl_id, cparam, ctx_udata)))
+ if(HADDR_UNDEF == (hdr_addr = H5B2_hdr_create(f, dxpl_id, cparam, ctx_udata, parent)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, NULL, "can't create v2 B-tree header")
/* Create v2 B-tree wrapper */
@@ -159,6 +160,7 @@ H5B2_create(H5F_t *f, hid_t dxpl_id, const H5B2_create_t *cparam, void *ctx_udat
/* Look up the B-tree header */
cache_udata.f = f;
+ cache_udata.parent = parent;
cache_udata.ctx_udata = ctx_udata;
if(NULL == (hdr = (H5B2_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, hdr_addr, &cache_udata, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, NULL, "unable to load B-tree header")
@@ -204,7 +206,7 @@ done:
*-------------------------------------------------------------------------
*/
H5B2_t *
-H5B2_open(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *ctx_udata)
+H5B2_open(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *ctx_udata, void *parent)
{
H5B2_t *bt2 = NULL; /* Pointer to the B-tree */
H5B2_hdr_t *hdr = NULL; /* Pointer to the B-tree header */
@@ -219,6 +221,7 @@ H5B2_open(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *ctx_udata)
/* Look up the B-tree header */
cache_udata.f = f;
+ cache_udata.parent = parent;
cache_udata.ctx_udata = ctx_udata;
if(NULL == (hdr = (H5B2_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, addr, &cache_udata, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, NULL, "unable to load B-tree header")
@@ -291,23 +294,23 @@ H5B2_insert(H5B2_t *bt2, hid_t dxpl_id, void *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)
+ if(H5B2_create_leaf(hdr, dxpl_id, hdr, &(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)
+ if(H5B2_split_root(hdr, dxpl_id, udata) < 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, udata) < 0)
+ if(H5B2_insert_internal(hdr, dxpl_id, hdr->depth, NULL, &hdr->root, hdr, 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, udata) < 0)
+ if(H5B2_insert_leaf(hdr, dxpl_id, &hdr->root, hdr, udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into B-tree leaf node")
} /* end else */
@@ -389,7 +392,7 @@ H5B2_iterate(H5B2_t *bt2, hid_t dxpl_id, H5B2_operator_t op, void *op_data)
/* Iterate through records */
if(hdr->root.node_nrec > 0) {
/* Iterate through nodes */
- if((ret_value = H5B2_iterate_node(hdr, dxpl_id, hdr->depth, &hdr->root, op, op_data)) < 0)
+ if((ret_value = H5B2_iterate_node(hdr, dxpl_id, hdr->depth, &hdr->root, hdr, op, op_data)) < 0)
HERROR(H5E_BTREE, H5E_CANTLIST, "node iteration failed");
} /* end if */
@@ -426,6 +429,7 @@ H5B2_find(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_found_t op,
{
H5B2_hdr_t *hdr; /* Pointer to the B-tree header */
H5B2_node_ptr_t curr_node_ptr; /* Node pointer info for current node */
+ void *parent = NULL; /* Parent of current node */
unsigned depth; /* Current depth of the tree */
int cmp; /* Comparison value of records */
unsigned idx; /* Location of record which matches key */
@@ -445,23 +449,34 @@ H5B2_find(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_found_t op,
/* Make copy of the root node pointer to start search with */
curr_node_ptr = hdr->root;
- /* Current depth of the tree */
- depth = hdr->depth;
-
/* Check for empty tree */
if(curr_node_ptr.node_nrec == 0)
HGOTO_DONE(FALSE)
+ /* Current depth of the tree */
+ depth = hdr->depth;
+
+ /* Set initial parent, if doing swmr writes */
+ if(hdr->swmr_write)
+ parent = hdr;
+
/* Walk down B-tree to find record or leaf node where record is located */
cmp = -1;
- while(depth > 0 && cmp != 0) {
+ while(depth > 0) {
H5B2_internal_t *internal; /* Pointer to internal node in B-tree */
H5B2_node_ptr_t next_node_ptr; /* Node pointer info for next node */
/* Lock B-tree current node */
- if(NULL == (internal = H5B2_protect_internal(hdr, dxpl_id, curr_node_ptr.addr, curr_node_ptr.node_nrec, depth, H5AC_READ)))
+ if(NULL == (internal = H5B2_protect_internal(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, depth, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+ /* Unpin parent if necessary */
+ if(parent) {
+ if(parent != hdr && H5AC_unpin_entry(parent) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "unable to unpin parent entry")
+ parent = NULL;
+ } /* end if */
+
/* Locate node pointer for child */
cmp = H5B2_locate_record(hdr->cls, internal->nrec, hdr->nat_off, internal->int_native, udata, &idx);
if(cmp > 0)
@@ -472,9 +487,13 @@ H5B2_find(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_found_t op,
next_node_ptr=internal->node_ptrs[idx];
/* Unlock current node */
- if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__NO_FLAGS_SET) < 0)
+ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, hdr->swmr_write ? H5AC__PIN_ENTRY_FLAG : H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ /* Keep track of parent if necessary */
+ if(hdr->swmr_write)
+ parent = internal;
+
/* Set pointer to next node to load */
curr_node_ptr = next_node_ptr;
} /* end if */
@@ -504,9 +523,16 @@ H5B2_find(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_found_t op,
H5B2_leaf_t *leaf; /* Pointer to leaf node in B-tree */
/* Lock B-tree leaf node */
- if(NULL == (leaf = H5B2_protect_leaf(hdr, dxpl_id, curr_node_ptr.addr, curr_node_ptr.node_nrec, H5AC_READ)))
+ if(NULL == (leaf = H5B2_protect_leaf(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
+ /* Unpin parent if necessary */
+ if(parent) {
+ if(parent != hdr && H5AC_unpin_entry(parent) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "unable to unpin parent entry")
+ parent = NULL;
+ } /* end if */
+
/* Locate record */
cmp = H5B2_locate_record(hdr->cls, leaf->nrec, hdr->nat_off, leaf->leaf_native, udata, &idx);
@@ -535,6 +561,12 @@ H5B2_find(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_found_t op,
} /* end block */
done:
+ if(parent) {
+ HDassert(ret_value < 0);
+ if(parent != hdr && H5AC_unpin_entry(parent) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "unable to unpin parent entry")
+ } /* end if */
+
FUNC_LEAVE_NOAPI(ret_value)
} /* H5B2_find() */
@@ -563,6 +595,7 @@ H5B2_index(H5B2_t *bt2, hid_t dxpl_id, H5_iter_order_t order, hsize_t idx,
{
H5B2_hdr_t *hdr; /* Pointer to the B-tree header */
H5B2_node_ptr_t curr_node_ptr; /* Node pointer info for current node */
+ void *parent = NULL; /* Parent of current node */
unsigned depth; /* Current depth of the tree */
herr_t ret_value = SUCCEED; /* Return value */
@@ -581,9 +614,6 @@ H5B2_index(H5B2_t *bt2, hid_t dxpl_id, H5_iter_order_t order, hsize_t idx,
/* Make copy of the root node pointer to start search with */
curr_node_ptr = hdr->root;
- /* Current depth of the tree */
- depth = hdr->depth;
-
/* Check for empty tree */
if(curr_node_ptr.node_nrec == 0)
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "B-tree has no records")
@@ -592,6 +622,13 @@ H5B2_index(H5B2_t *bt2, hid_t dxpl_id, H5_iter_order_t order, hsize_t idx,
if(idx >= curr_node_ptr.all_nrec)
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "B-tree doesn't have that many records")
+ /* Current depth of the tree */
+ depth = hdr->depth;
+
+ /* Set initial parent, if doing swmr writes */
+ if(hdr->swmr_write)
+ parent = hdr;
+
/* Check for reverse indexing and map requested index to appropriate forward index */
if(order == H5_ITER_DEC)
idx = curr_node_ptr.all_nrec - (idx + 1);
@@ -603,9 +640,16 @@ H5B2_index(H5B2_t *bt2, hid_t dxpl_id, H5_iter_order_t order, hsize_t idx,
unsigned u; /* Local index variable */
/* Lock B-tree current node */
- if(NULL == (internal = H5B2_protect_internal(hdr, dxpl_id, curr_node_ptr.addr, curr_node_ptr.node_nrec, depth, H5AC_READ)))
+ if(NULL == (internal = H5B2_protect_internal(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, depth, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+ /* Unpin parent if necessary */
+ if(parent) {
+ if(parent != hdr && H5AC_unpin_entry(parent) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "unable to unpin parent entry")
+ parent = NULL;
+ } /* end if */
+
/* Search for record with correct index */
for(u = 0; u < internal->nrec; u++) {
/* Check if record is in child node */
@@ -614,9 +658,13 @@ H5B2_index(H5B2_t *bt2, hid_t dxpl_id, H5_iter_order_t order, hsize_t idx,
next_node_ptr = internal->node_ptrs[u];
/* Unlock current node */
- if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__NO_FLAGS_SET) < 0)
+ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, hdr->swmr_write ? H5AC__PIN_ENTRY_FLAG : H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ /* Keep track of parent if necessary */
+ if(hdr->swmr_write)
+ parent = internal;
+
/* Set pointer to next node to load */
curr_node_ptr = next_node_ptr;
@@ -656,9 +704,13 @@ H5B2_index(H5B2_t *bt2, hid_t dxpl_id, H5_iter_order_t order, hsize_t idx,
next_node_ptr = internal->node_ptrs[u];
/* Unlock current node */
- if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__NO_FLAGS_SET) < 0)
+ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, hdr->swmr_write ? H5AC__PIN_ENTRY_FLAG : H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ /* Keep track of parent if necessary */
+ if(hdr->swmr_write)
+ parent = internal;
+
/* Set pointer to next node to load */
curr_node_ptr = next_node_ptr;
} /* end if */
@@ -675,9 +727,16 @@ H5B2_index(H5B2_t *bt2, hid_t dxpl_id, H5_iter_order_t order, hsize_t idx,
H5B2_leaf_t *leaf; /* Pointer to leaf node in B-tree */
/* Lock B-tree leaf node */
- if(NULL == (leaf = H5B2_protect_leaf(hdr, dxpl_id, curr_node_ptr.addr, curr_node_ptr.node_nrec, H5AC_READ)))
+ if(NULL == (leaf = H5B2_protect_leaf(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
+ /* Unpin parent if necessary */
+ if(parent) {
+ if(parent != hdr && H5AC_unpin_entry(parent) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "unable to unpin parent entry")
+ parent = NULL;
+ } /* end if */
+
/* Sanity check index */
HDassert(idx < leaf->nrec);
@@ -696,6 +755,12 @@ H5B2_index(H5B2_t *bt2, hid_t dxpl_id, H5_iter_order_t order, hsize_t idx,
} /* end block */
done:
+ if(parent) {
+ HDassert(ret_value < 0);
+ if(parent != hdr && H5AC_unpin_entry(parent) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "unable to unpin parent entry")
+ } /* end if */
+
FUNC_LEAVE_NOAPI(ret_value)
} /* H5B2_index() */
@@ -739,8 +804,9 @@ H5B2_remove(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_remove_t op,
if(hdr->depth > 0) {
hbool_t depth_decreased = FALSE; /* Flag to indicate whether the depth of the B-tree decreased */
- if(H5B2_remove_internal(hdr, dxpl_id, &depth_decreased, NULL, hdr->depth,
- &(hdr->cache_info), NULL, &hdr->root, udata, op, op_data) < 0)
+ if(H5B2_remove_internal(hdr, dxpl_id, &depth_decreased, NULL, NULL,
+ hdr->depth, &(hdr->cache_info), NULL, &hdr->root, udata, op,
+ op_data) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record from B-tree internal node")
/* Check for decreasing the depth of the B-tree */
@@ -758,7 +824,7 @@ H5B2_remove(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_remove_t op,
} /* end for */
} /* end if */
else {
- if(H5B2_remove_leaf(hdr, dxpl_id, &hdr->root, udata, op, op_data) < 0)
+ if(H5B2_remove_leaf(hdr, dxpl_id, &hdr->root, hdr, udata, op, op_data) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record from B-tree leaf node")
} /* end else */
@@ -779,6 +845,12 @@ done:
*
* Purpose: Removes the n'th record from a B-tree.
*
+ * The 'udata' parameter is only used to pass through to the
+ * crt_flush_dep and upd_flush_dep callbacks, so it only
+ * needs to contain enough information for those (if any - it
+ * can be NULL). Specifically, it does not need to identify
+ * the specific record to search for.
+ *
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
@@ -789,7 +861,7 @@ done:
*/
herr_t
H5B2_remove_by_idx(H5B2_t *bt2, hid_t dxpl_id, H5_iter_order_t order,
- hsize_t idx, H5B2_remove_t op, void *op_data)
+ hsize_t idx, void *udata, H5B2_remove_t op, void *op_data)
{
H5B2_hdr_t *hdr; /* Pointer to the B-tree header */
herr_t ret_value = SUCCEED; /* Return value */
@@ -821,8 +893,9 @@ H5B2_remove_by_idx(H5B2_t *bt2, hid_t dxpl_id, H5_iter_order_t order,
if(hdr->depth > 0) {
hbool_t depth_decreased = FALSE; /* Flag to indicate whether the depth of the B-tree decreased */
- if(H5B2_remove_internal_by_idx(hdr, dxpl_id, &depth_decreased, NULL, hdr->depth,
- &(hdr->cache_info), NULL, &hdr->root, idx, op, op_data) < 0)
+ if(H5B2_remove_internal_by_idx(hdr, dxpl_id, &depth_decreased, NULL,
+ NULL, hdr->depth, &(hdr->cache_info), NULL, &hdr->root, idx,
+ udata, op, op_data) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record from B-tree internal node")
/* Check for decreasing the depth of the B-tree */
@@ -840,7 +913,7 @@ H5B2_remove_by_idx(H5B2_t *bt2, hid_t dxpl_id, H5_iter_order_t order,
} /* end for */
} /* end if */
else {
- if(H5B2_remove_leaf_by_idx(hdr, dxpl_id, &hdr->root, (unsigned)idx, op, op_data) < 0)
+ if(H5B2_remove_leaf_by_idx(hdr, dxpl_id, &hdr->root, hdr, (unsigned)idx, op, op_data) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record from B-tree leaf node")
} /* end else */
@@ -935,11 +1008,11 @@ H5B2_neighbor(H5B2_t *bt2, hid_t dxpl_id, H5B2_compare_t range, void *udata,
/* Attempt to find neighbor record in B-tree */
if(hdr->depth > 0) {
- if(H5B2_neighbor_internal(hdr, dxpl_id, hdr->depth, &hdr->root, NULL, range, udata, op, op_data) < 0)
+ if(H5B2_neighbor_internal(hdr, dxpl_id, hdr->depth, &hdr->root, NULL, range, hdr, udata, op, op_data) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "unable to find neighbor record in B-tree internal node")
} /* end if */
else {
- if(H5B2_neighbor_leaf(hdr, dxpl_id, &hdr->root, NULL, range, udata, op, op_data) < 0)
+ if(H5B2_neighbor_leaf(hdr, dxpl_id, &hdr->root, NULL, range, hdr, udata, op, op_data) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "unable to find neighbor record in B-tree leaf node")
} /* end else */
@@ -974,6 +1047,7 @@ H5B2_modify(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_modify_t op,
{
H5B2_hdr_t *hdr; /* Pointer to the B-tree header */
H5B2_node_ptr_t curr_node_ptr; /* Node pointer info for current node */
+ void *parent = NULL; /* Parent of current node */
unsigned depth; /* Current depth of the tree */
int cmp; /* Comparison value of records */
unsigned idx; /* Location of record which matches key */
@@ -994,24 +1068,35 @@ H5B2_modify(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_modify_t op,
/* Make copy of the root node pointer to start search with */
curr_node_ptr = hdr->root;
- /* Current depth of the tree */
- depth = hdr->depth;
-
/* Check for empty tree */
if(0 == curr_node_ptr.node_nrec)
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "B-tree has no records")
+ /* Current depth of the tree */
+ depth = hdr->depth;
+
+ /* Set initial parent, if doing swmr writes */
+ if(hdr->swmr_write)
+ parent = hdr;
+
/* Walk down B-tree to find record or leaf node where record is located */
cmp = -1;
- while(depth > 0 && cmp != 0) {
+ while(depth > 0) {
unsigned internal_flags = H5AC__NO_FLAGS_SET;
H5B2_internal_t *internal; /* Pointer to internal node in B-tree */
H5B2_node_ptr_t next_node_ptr; /* Node pointer info for next node */
/* Lock B-tree current node */
- if(NULL == (internal = H5B2_protect_internal(hdr, dxpl_id, curr_node_ptr.addr, curr_node_ptr.node_nrec, depth, H5AC_WRITE)))
+ if(NULL == (internal = H5B2_protect_internal(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, depth, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+ /* Unpin parent if necessary */
+ if(parent) {
+ if(parent != hdr && H5AC_unpin_entry(parent) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "unable to unpin parent entry")
+ parent = NULL;
+ } /* end if */
+
/* Locate node pointer for child */
cmp = H5B2_locate_record(hdr->cls, internal->nrec, hdr->nat_off, internal->int_native, udata, &idx);
if(cmp > 0)
@@ -1022,9 +1107,13 @@ H5B2_modify(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_modify_t op,
next_node_ptr = internal->node_ptrs[idx];
/* Unlock current node */
- if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__NO_FLAGS_SET) < 0)
+ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, hdr->swmr_write ? H5AC__PIN_ENTRY_FLAG : H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ /* Keep track of parent if necessary */
+ if(hdr->swmr_write)
+ parent = internal;
+
/* Set pointer to next node to load */
curr_node_ptr = next_node_ptr;
} /* end if */
@@ -1063,9 +1152,16 @@ H5B2_modify(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_modify_t op,
hbool_t changed = FALSE;/* Whether the 'modify' callback changed the record */
/* Lock B-tree leaf node */
- if(NULL == (leaf = H5B2_protect_leaf(hdr, dxpl_id, curr_node_ptr.addr, curr_node_ptr.node_nrec, H5AC_WRITE)))
+ if(NULL == (leaf = H5B2_protect_leaf(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
+ /* Unpin parent if necessary */
+ if(parent) {
+ if(parent != hdr && H5AC_unpin_entry(parent) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "unable to unpin parent entry")
+ parent = NULL;
+ } /* end if */
+
/* Locate record */
cmp = H5B2_locate_record(hdr->cls, leaf->nrec, hdr->nat_off, leaf->leaf_native, udata, &idx);
@@ -1107,6 +1203,12 @@ H5B2_modify(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_modify_t op,
}
done:
+ if(parent) {
+ HDassert(ret_value < 0);
+ if(parent != hdr && H5AC_unpin_entry(parent) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "unable to unpin parent entry")
+ } /* end if */
+
FUNC_LEAVE_NOAPI(ret_value)
} /* H5B2_modify() */
@@ -1235,7 +1337,7 @@ done:
*/
herr_t
H5B2_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *ctx_udata,
- H5B2_remove_t op, void *op_data)
+ void *parent, H5B2_remove_t op, void *op_data)
{
H5B2_hdr_t *hdr = NULL; /* Pointer to the B-tree header */
H5B2_hdr_cache_ud_t cache_udata; /* User-data for callback */
@@ -1252,6 +1354,7 @@ H5B2_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *ctx_udata,
HDfprintf(stderr, "%s: addr = %a\n", FUNC, addr);
#endif /* QAK */
cache_udata.f = f;
+ cache_udata.parent = parent;
cache_udata.ctx_udata = ctx_udata;
if(NULL == (hdr = (H5B2_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, addr, &cache_udata, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect v2 B-tree header")
@@ -1281,3 +1384,293 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5B2_delete() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_support
+ *
+ * Purpose: Add a flush dependency between the b-tree child object (as
+ * the flush dependency child) and the b-tree node containing
+ * the address of that child. If the child has not yet been
+ * inserted, does nothing.
+ *
+ * Return: TRUE if flush dependency created
+ * FALSE if child is not in b-tree
+ * Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * May 11 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5B2_support(H5B2_t *bt2, hid_t dxpl_id, void *udata, void *child)
+{
+ H5B2_hdr_t *hdr; /* Pointer to the B-tree header */
+ H5B2_node_ptr_t curr_node_ptr; /* Node pointer info for current node */
+ void *parent = NULL; /* Parent of current node */
+ unsigned depth; /* Current depth of the tree */
+ int cmp; /* Comparison value of records */
+ unsigned idx; /* Location of record which matches key */
+ htri_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check arguments. */
+ HDassert(bt2);
+ HDassert(child);
+
+ /* 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;
+
+ /* Make copy of the root node pointer to start search with */
+ curr_node_ptr = hdr->root;
+
+ /* Check for empty tree */
+ if(curr_node_ptr.node_nrec == 0)
+ HGOTO_DONE(FALSE)
+
+ /* Current depth of the tree */
+ depth = hdr->depth;
+
+ /* This should only be called if swmr_write is on */
+ HDassert(hdr->swmr_write);
+
+ /* Set initial parent */
+ parent = hdr;
+
+ /* Walk down B-tree to find record or leaf node where record is located */
+ while(depth > 0) {
+ H5B2_internal_t *internal; /* Pointer to internal node in B-tree */
+ H5B2_node_ptr_t next_node_ptr; /* Node pointer info for next node */
+
+ /* Lock B-tree current node */
+ if(NULL == (internal = H5B2_protect_internal(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, depth, H5AC_READ)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+
+ /* Unpin parent if necessary */
+ if(parent != hdr && H5AC_unpin_entry(parent) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "unable to unpin parent entry")
+ parent = NULL;
+
+ /* Locate node pointer for child */
+ cmp = H5B2_locate_record(hdr->cls, internal->nrec, hdr->nat_off, internal->int_native, udata, &idx);
+ if(cmp > 0)
+ idx++;
+
+ if(cmp != 0) {
+ /* Get node pointer for next node to search */
+ next_node_ptr=internal->node_ptrs[idx];
+
+ /* Unlock current node */
+ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__PIN_ENTRY_FLAG) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+
+ /* Keep track of parent */
+ parent = internal;
+
+ /* Set pointer to next node to load */
+ curr_node_ptr = next_node_ptr;
+ } /* end if */
+ else {
+ /* Add flush dependency on child */
+ if(H5AC_create_flush_dependency(internal, child) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
+
+ /* Unlock current node */
+ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+
+ /* Indicate record supported */
+ HGOTO_DONE(TRUE)
+ } /* end else */
+
+ /* Decrement depth we're at in B-tree */
+ depth--;
+ } /* end while */
+
+ {
+ H5B2_leaf_t *leaf; /* Pointer to leaf node in B-tree */
+
+ /* Lock B-tree leaf node */
+ if(NULL == (leaf = H5B2_protect_leaf(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, H5AC_READ)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
+
+ /* Unpin parent if necessary */
+ if(parent != hdr && H5AC_unpin_entry(parent) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "unable to unpin parent entry")
+ parent = NULL;
+
+ /* Locate record */
+ cmp = H5B2_locate_record(hdr->cls, leaf->nrec, hdr->nat_off, leaf->leaf_native, udata, &idx);
+
+ if(cmp == 0) {
+ /* Add flush dependency on child */
+ if(H5AC_create_flush_dependency(leaf, child) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
+
+ /* Indicate child was supported */
+ ret_value = TRUE;
+ } /* end if */
+
+ /* Unlock current node */
+ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr.addr, leaf, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ } /* end block */
+
+done:
+ if(parent) {
+ HDassert(ret_value < 0);
+ if(parent != hdr && H5AC_unpin_entry(parent) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "unable to unpin parent entry")
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5B2_support() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_unsupport
+ *
+ * Purpose: Destroy a flush dependency between the b-tree child object
+ * and the b-tree node containing the address of that child.
+ * This dependency *must* have been created earlier either by
+ * a call to H5B_support() or by the client (presumably via
+ * the create_flush_dep() callback on insertion).
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * May 14 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5B2_unsupport(H5B2_t *bt2, hid_t dxpl_id, void *udata, void *child)
+{
+ H5B2_hdr_t *hdr; /* Pointer to the B-tree header */
+ H5B2_node_ptr_t curr_node_ptr; /* Node pointer info for current node */
+ void *parent = NULL; /* Parent of current node */
+ unsigned depth; /* Current depth of the tree */
+ int cmp; /* Comparison value of records */
+ unsigned idx; /* Location of record which matches key */
+ htri_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check arguments. */
+ HDassert(bt2);
+ HDassert(child);
+
+ /* 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;
+
+ /* Make copy of the root node pointer to start search with */
+ curr_node_ptr = hdr->root;
+
+ /* Check for empty tree */
+ if(curr_node_ptr.node_nrec == 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "B-tree is empty")
+
+ /* Current depth of the tree */
+ depth = hdr->depth;
+
+ /* This should only be called if swmr_write is on */
+ HDassert(hdr->swmr_write);
+
+ /* Set initial parent */
+ parent = hdr;
+
+ /* Walk down B-tree to find record or leaf node where record is located */
+ while(depth > 0) {
+ H5B2_internal_t *internal; /* Pointer to internal node in B-tree */
+ H5B2_node_ptr_t next_node_ptr; /* Node pointer info for next node */
+
+ /* Lock B-tree current node */
+ if(NULL == (internal = H5B2_protect_internal(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, depth, H5AC_READ)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+
+ /* Unpin parent if necessary */
+ if(parent != hdr && H5AC_unpin_entry(parent) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "unable to unpin parent entry")
+ parent = NULL;
+
+ /* Locate node pointer for child */
+ cmp = H5B2_locate_record(hdr->cls, internal->nrec, hdr->nat_off, internal->int_native, udata, &idx);
+ if(cmp > 0)
+ idx++;
+
+ if(cmp != 0) {
+ /* Get node pointer for next node to search */
+ next_node_ptr=internal->node_ptrs[idx];
+
+ /* Unlock current node */
+ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__PIN_ENTRY_FLAG) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+
+ /* Keep track of parent */
+ parent = internal;
+
+ /* Set pointer to next node to load */
+ curr_node_ptr = next_node_ptr;
+ } /* end if */
+ else {
+ /* Remove flush dependency on child */
+ if(H5AC_destroy_flush_dependency(internal, child) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
+
+ /* Unlock current node */
+ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+
+ /* No need to continue */
+ HGOTO_DONE(SUCCEED)
+ } /* end else */
+
+ /* Decrement depth we're at in B-tree */
+ depth--;
+ } /* end while */
+
+ {
+ H5B2_leaf_t *leaf; /* Pointer to leaf node in B-tree */
+
+ /* Lock B-tree leaf node */
+ if(NULL == (leaf = H5B2_protect_leaf(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, H5AC_READ)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
+
+ /* Unpin parent if necessary */
+ if(parent != hdr && H5AC_unpin_entry(parent) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "unable to unpin parent entry")
+ parent = NULL;
+
+ /* Locate record */
+ cmp = H5B2_locate_record(hdr->cls, leaf->nrec, hdr->nat_off, leaf->leaf_native, udata, &idx);
+
+ if(cmp == 0) {
+ /* Add flush dependency on child */
+ if(H5AC_destroy_flush_dependency(leaf, child) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
+ } /* end if */
+ else
+ HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "node not found in B-tree")
+
+ /* Unlock current node */
+ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr.addr, leaf, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ } /* end block */
+
+done:
+ if(parent) {
+ HDassert(ret_value < 0);
+ if(parent != hdr && H5AC_unpin_entry(parent) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "unable to unpin parent entry")
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5B2_unsupport() */
+
diff --git a/src/H5B2cache.c b/src/H5B2cache.c
index 2ee4ef7..96faa13 100644
--- a/src/H5B2cache.c
+++ b/src/H5B2cache.c
@@ -73,16 +73,19 @@ static H5B2_hdr_t *H5B2_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, vo
static herr_t H5B2_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_hdr_t *hdr, unsigned UNUSED * flags_ptr);
static herr_t H5B2_cache_hdr_dest(H5F_t *f, H5B2_hdr_t *hdr);
static herr_t H5B2_cache_hdr_clear(H5F_t *f, H5B2_hdr_t *hdr, hbool_t destroy);
+static herr_t H5B2_cache_hdr_notify(H5AC_notify_action_t action, H5B2_hdr_t *hdr);
static herr_t H5B2_cache_hdr_size(const H5F_t *f, const H5B2_hdr_t *hdr, size_t *size_ptr);
static H5B2_internal_t *H5B2_cache_internal_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
static herr_t H5B2_cache_internal_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_internal_t *i, unsigned UNUSED * flags_ptr);
static herr_t H5B2_cache_internal_dest(H5F_t *f, H5B2_internal_t *internal);
static herr_t H5B2_cache_internal_clear(H5F_t *f, H5B2_internal_t *i, hbool_t destroy);
+static herr_t H5B2_cache_internal_notify(H5AC_notify_action_t action, H5B2_internal_t *internal);
static herr_t H5B2_cache_internal_size(const H5F_t *f, const H5B2_internal_t *i, size_t *size_ptr);
static H5B2_leaf_t *H5B2_cache_leaf_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
static herr_t H5B2_cache_leaf_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_leaf_t *l, unsigned UNUSED * flags_ptr);
static herr_t H5B2_cache_leaf_dest(H5F_t *f, H5B2_leaf_t *leaf);
static herr_t H5B2_cache_leaf_clear(H5F_t *f, H5B2_leaf_t *l, hbool_t destroy);
+static herr_t H5B2_cache_leaf_notify(H5AC_notify_action_t action, H5B2_leaf_t *leaf);
static herr_t H5B2_cache_leaf_size(const H5F_t *f, const H5B2_leaf_t *l, size_t *size_ptr);
@@ -97,7 +100,7 @@ const H5AC_class_t H5AC_BT2_HDR[1] = {{
(H5AC_flush_func_t)H5B2_cache_hdr_flush,
(H5AC_dest_func_t)H5B2_cache_hdr_dest,
(H5AC_clear_func_t)H5B2_cache_hdr_clear,
- (H5AC_notify_func_t)NULL,
+ (H5AC_notify_func_t)H5B2_cache_hdr_notify,
(H5AC_size_func_t)H5B2_cache_hdr_size,
}};
@@ -108,7 +111,7 @@ const H5AC_class_t H5AC_BT2_INT[1] = {{
(H5AC_flush_func_t)H5B2_cache_internal_flush,
(H5AC_dest_func_t)H5B2_cache_internal_dest,
(H5AC_clear_func_t)H5B2_cache_internal_clear,
- (H5AC_notify_func_t)NULL,
+ (H5AC_notify_func_t)H5B2_cache_internal_notify,
(H5AC_size_func_t)H5B2_cache_internal_size,
}};
@@ -119,7 +122,7 @@ const H5AC_class_t H5AC_BT2_LEAF[1] = {{
(H5AC_flush_func_t)H5B2_cache_leaf_flush,
(H5AC_dest_func_t)H5B2_cache_leaf_dest,
(H5AC_clear_func_t)H5B2_cache_leaf_clear,
- (H5AC_notify_func_t)NULL,
+ (H5AC_notify_func_t)H5B2_cache_leaf_notify,
(H5AC_size_func_t)H5B2_cache_leaf_size,
}};
@@ -238,7 +241,7 @@ H5B2_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
/* Initialize B-tree header info */
cparam.cls = H5B2_client_class_g[id];
- if(H5B2_hdr_init(hdr, &cparam, udata->ctx_udata, depth) < 0)
+ if(H5B2_hdr_init(hdr, &cparam, udata->ctx_udata, udata->parent, depth) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, NULL, "can't initialize B-tree header info")
/* Set the B-tree header's address */
@@ -348,6 +351,23 @@ H5B2_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
HGOTO_ERROR(H5E_BTREE, H5E_CANTFLUSH, FAIL, "unable to save B-tree header to disk")
hdr->cache_info.is_dirty = FALSE;
+
+ /* Clear shadowed node lists, as the header has been flushed and all
+ * nodes must be shadowed again (if doing SWMR writes). Note that this
+ * algorithm does one extra iteration at the end, as the last node's
+ * shadowed_next pointer points to itself. */
+ while(hdr->shadowed_internal) {
+ H5B2_internal_t *next = hdr->shadowed_internal->shadowed_next;
+
+ hdr->shadowed_internal->shadowed_next = NULL;
+ hdr->shadowed_internal = next;
+ } /* end while */
+ while(hdr->shadowed_leaf) {
+ H5B2_leaf_t *next = hdr->shadowed_leaf->shadowed_next;
+
+ hdr->shadowed_leaf->shadowed_next = NULL;
+ hdr->shadowed_leaf = next;
+ } /* end while */
} /* end if */
if(destroy)
@@ -445,6 +465,61 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5B2_cache_hdr_notify
+ *
+ * Purpose: Handle cache action notifications
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * nfortne2@hdfgroup.org
+ * Apr 24 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_cache_hdr_notify(H5AC_notify_action_t action, H5B2_hdr_t *hdr)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+
+ /* Check if the file was opened with SWMR-write access */
+ if(hdr->swmr_write) {
+ HDassert(hdr->parent);
+ switch(action) {
+ case H5AC_NOTIFY_ACTION_AFTER_INSERT:
+ /* Create flush dependency on parent */
+ if(H5AC_create_flush_dependency(hdr->parent, hdr) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
+ break;
+
+ case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
+ /* Destroy flush dependency on parent */
+ if(H5AC_destroy_flush_dependency(hdr->parent, hdr) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency")
+ break;
+
+ default:
+#ifdef NDEBUG
+ HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, FAIL, "unknown action from metadata cache")
+#else /* NDEBUG */
+ HDassert(0 && "Unknown action?!?");
+#endif /* NDEBUG */
+ } /* end switch */
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5B2_cache_hdr_notify() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5B2_cache_hdr_size
*
* Purpose: Compute the size in bytes of a B-tree header
@@ -523,6 +598,7 @@ H5B2_cache_internal_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
/* Share B-tree information */
internal->hdr = udata->hdr;
+ internal->parent = udata->parent;
/* Read header from disk */
if(H5F_block_read(f, H5FD_MEM_BTREE, addr, udata->hdr->node_size, dxpl_id, udata->hdr->page) < 0)
@@ -787,6 +863,61 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5B2_cache_internal_notify
+ *
+ * Purpose: Handle cache action notifications
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * nfortne2@hdfgroup.org
+ * Apr 25 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_cache_internal_notify(H5AC_notify_action_t action, H5B2_internal_t *internal)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /*
+ * Check arguments.
+ */
+ HDassert(internal);
+
+ /* Check if the file was opened with SWMR-write access */
+ if(internal->hdr->swmr_write) {
+ HDassert(internal->parent);
+ switch(action) {
+ case H5AC_NOTIFY_ACTION_AFTER_INSERT:
+ /* Create flush dependency on parent */
+ if(H5AC_create_flush_dependency(internal->parent, internal) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
+ break;
+
+ case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
+ /* Destroy flush dependency on parent */
+ if(H5AC_destroy_flush_dependency(internal->parent, internal) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency")
+ break;
+
+ default:
+#ifdef NDEBUG
+ HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, FAIL, "unknown action from metadata cache")
+#else /* NDEBUG */
+ HDassert(0 && "Unknown action?!?");
+#endif /* NDEBUG */
+ } /* end switch */
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5B2_cache_internal_notify() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5B2_cache_internal_size
*
* Purpose: Compute the size in bytes of a B-tree internal node
@@ -865,6 +996,7 @@ H5B2_cache_leaf_load(H5F_t UNUSED *f, hid_t dxpl_id, haddr_t addr, void *_udata)
/* Share B-tree header information */
leaf->hdr = udata->hdr;
+ leaf->parent = udata->parent;
/* Read header from disk */
if(H5F_block_read(udata->f, H5FD_MEM_BTREE, addr, udata->hdr->node_size, dxpl_id, udata->hdr->page) < 0)
@@ -1095,6 +1227,61 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5B2_cache_leaf_notify
+ *
+ * Purpose: Handle cache action notifications
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * nfortne2@hdfgroup.org
+ * Apr 25 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_cache_leaf_notify(H5AC_notify_action_t action, H5B2_leaf_t *leaf)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /*
+ * Check arguments.
+ */
+ HDassert(leaf);
+
+ /* Check if the file was opened with SWMR-write access */
+ if(leaf->hdr->swmr_write) {
+ HDassert(leaf->parent);
+ switch(action) {
+ case H5AC_NOTIFY_ACTION_AFTER_INSERT:
+ /* Create flush dependency on parent */
+ if(H5AC_create_flush_dependency(leaf->parent, leaf) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
+ break;
+
+ case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
+ /* Destroy flush dependency on parent */
+ if(H5AC_destroy_flush_dependency(leaf->parent, leaf) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency")
+ break;
+
+ default:
+#ifdef NDEBUG
+ HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, FAIL, "unknown action from metadata cache")
+#else /* NDEBUG */
+ HDassert(0 && "Unknown action?!?");
+#endif /* NDEBUG */
+ } /* end switch */
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5B2_cache_leaf_notify() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5B2_cache_leaf_size
*
* Purpose: Compute the size in bytes of a B-tree leaf node
diff --git a/src/H5B2dbg.c b/src/H5B2dbg.c
index 3e5d55a..06c1195 100644
--- a/src/H5B2dbg.c
+++ b/src/H5B2dbg.c
@@ -124,6 +124,7 @@ H5B2_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent,
*/
cache_udata.f = f;
cache_udata.ctx_udata = dbg_ctx;
+ cache_udata.parent = NULL;
if(NULL == (hdr = (H5B2_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, addr, &cache_udata, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load B-tree header")
@@ -242,6 +243,7 @@ H5B2_int_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent,
*/
cache_udata.f = f;
cache_udata.ctx_udata = dbg_ctx;
+ cache_udata.parent = NULL;
if(NULL == (hdr = (H5B2_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, hdr_addr, &cache_udata, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load B-tree header")
@@ -251,7 +253,7 @@ H5B2_int_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent,
/*
* Load the B-tree internal node
*/
- if(NULL == (internal = H5B2_protect_internal(hdr, dxpl_id, addr, nrec, depth, H5AC_READ)))
+ if(NULL == (internal = H5B2_protect_internal(hdr, dxpl_id, addr, NULL, nrec, depth, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load B-tree internal node")
/* Print opening message */
@@ -374,6 +376,7 @@ H5B2_leaf_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent,
*/
cache_udata.f = f;
cache_udata.ctx_udata = dbg_ctx;
+ cache_udata.parent = NULL;
if(NULL == (hdr = (H5B2_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, hdr_addr, &cache_udata, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree header")
@@ -383,7 +386,7 @@ H5B2_leaf_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent,
/*
* Load the B-tree leaf node
*/
- if(NULL == (leaf = H5B2_protect_leaf(hdr, dxpl_id, addr, nrec, H5AC_READ)))
+ if(NULL == (leaf = H5B2_protect_leaf(hdr, dxpl_id, addr, NULL, nrec, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
/* Print opening message */
diff --git a/src/H5B2hdr.c b/src/H5B2hdr.c
index b73c29a..54842ff 100644
--- a/src/H5B2hdr.c
+++ b/src/H5B2hdr.c
@@ -108,7 +108,7 @@ H5FL_SEQ_DEFINE(H5B2_node_info_t);
*/
herr_t
H5B2_hdr_init(H5B2_hdr_t *hdr, const H5B2_create_t *cparam, void *ctx_udata,
- uint16_t depth)
+ void *parent, uint16_t depth)
{
size_t sz_max_nrec; /* Temporary variable for range checking */
unsigned u_max_nrec_size; /* Temporary variable for range checking */
@@ -132,6 +132,7 @@ H5B2_hdr_init(H5B2_hdr_t *hdr, const H5B2_create_t *cparam, void *ctx_udata,
HDassert(cparam->merge_percent < (cparam->split_percent / 2));
/* Initialize basic information */
+ hdr->parent = parent;
hdr->rc = 0;
hdr->pending_delete = FALSE;
@@ -207,6 +208,12 @@ HDmemset(hdr->page, 0, hdr->node_size);
} /* end for */
} /* end if */
+ /* Determine if we are doing SWMR writes. Only enable for data chunks for
+ * now. */
+ hdr->swmr_write = (H5F_INTENT(hdr->f) & H5F_ACC_SWMR_WRITE) > 0
+ && (hdr->cls->id == H5B2_CDSET_ID
+ || hdr->cls->id == H5B2_CDSET_FILT_ID);
+
/* Create the callback context, if the callback exists */
if(hdr->cls->crt_context) {
if(NULL == (hdr->cb_ctx = (*hdr->cls->crt_context)(ctx_udata)))
@@ -283,7 +290,7 @@ done:
*/
haddr_t
H5B2_hdr_create(H5F_t *f, hid_t dxpl_id, const H5B2_create_t *cparam,
- void *ctx_udata)
+ void *ctx_udata, void *parent)
{
H5B2_hdr_t *hdr = NULL; /* The new v2 B-tree header information */
haddr_t ret_value; /* Return value */
@@ -301,7 +308,7 @@ H5B2_hdr_create(H5F_t *f, hid_t dxpl_id, const H5B2_create_t *cparam,
HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, HADDR_UNDEF, "allocation failed for B-tree header")
/* Initialize shared B-tree info */
- if(H5B2_hdr_init(hdr, cparam, ctx_udata, (uint16_t)0) < 0)
+ if(H5B2_hdr_init(hdr, cparam, ctx_udata, parent, (uint16_t)0) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, HADDR_UNDEF, "can't create shared B-tree info")
/* Allocate space for the header on disk */
@@ -590,7 +597,7 @@ H5B2_hdr_delete(H5B2_hdr_t *hdr, hid_t dxpl_id)
/* Delete all nodes in B-tree */
if(H5F_addr_defined(hdr->root.addr))
- if(H5B2_delete_node(hdr, dxpl_id, hdr->depth, &hdr->root, hdr->remove_op, hdr->remove_op_data) < 0)
+ if(H5B2_delete_node(hdr, dxpl_id, hdr->depth, &hdr->root, hdr, hdr->remove_op, hdr->remove_op_data) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to delete B-tree nodes")
/* Indicate that the heap header should be deleted & file space freed */
diff --git a/src/H5B2int.c b/src/H5B2int.c
index 4355174..e6d359a 100644
--- a/src/H5B2int.c
+++ b/src/H5B2int.c
@@ -61,24 +61,32 @@
/********************/
/* Helper functions */
-static herr_t H5B2_create_internal(H5B2_hdr_t *hdr, hid_t dxpl_id,
+static herr_t H5B2_create_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, void *parent,
H5B2_node_ptr_t *node_ptr, unsigned depth);
static herr_t H5B2_split1(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags_ptr,
- H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx);
+ H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx,
+ void *udata);
static herr_t H5B2_redistribute2(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
- H5B2_internal_t *internal, unsigned idx);
+ H5B2_internal_t *internal, unsigned idx, void *udata);
static herr_t H5B2_redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
- H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx);
+ H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx,
+ void *udata);
static herr_t H5B2_merge2(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags_ptr,
- H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx);
+ H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx,
+ void *udata);
static herr_t H5B2_merge3(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags_ptr,
- H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx);
+ H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx,
+ void *udata);
static herr_t H5B2_swap_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
- H5B2_internal_t *internal, unsigned *internal_flags_ptr,
- unsigned idx, void *swap_loc);
+ H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx,
+ void *swap_loc, void *swap_parent, void *udata);
+static herr_t H5B2_shadow_internal(H5B2_hdr_t *hdr, hid_t dxpl_id,
+ unsigned depth, H5B2_node_ptr_t *curr_node_ptr, H5B2_internal_t **internal);
+static herr_t H5B2_shadow_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id,
+ H5B2_node_ptr_t *curr_node_ptr, H5B2_leaf_t **leaf);
#ifdef H5B2_DEBUG
static herr_t H5B2_assert_leaf(const H5B2_hdr_t *hdr, const H5B2_leaf_t *leaf);
static herr_t H5B2_assert_leaf2(const H5B2_hdr_t *hdr, const H5B2_leaf_t *leaf, const H5B2_leaf_t *leaf2);
@@ -172,19 +180,24 @@ H5B2_locate_record(const H5B2_class_t *type, unsigned nrec, size_t *rec_off,
*-------------------------------------------------------------------------
*/
static herr_t
-H5B2_split1(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth, H5B2_node_ptr_t *curr_node_ptr,
- unsigned *parent_cache_info_flags_ptr, H5B2_internal_t *internal,
- unsigned *internal_flags_ptr, unsigned idx)
+H5B2_split1(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
+ H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags_ptr,
+ H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx,
+ void *udata)
{
const H5AC_class_t *child_class; /* Pointer to child node's class info */
haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */
void *left_child = NULL, *right_child = NULL; /* Pointers to child nodes */
+ const H5AC_class_t *grandchild_class; /* Pointer to grandchild node's class info */
+ haddr_t grandchild_addr; /* Grandchild address */
+ void *grandchild = NULL; /* Pointer to grandchild node */
uint16_t *left_nrec, *right_nrec; /* Pointers to child # of records */
uint8_t *left_native, *right_native;/* Pointers to childs' native records */
H5B2_node_ptr_t *left_node_ptrs = NULL, *right_node_ptrs = NULL;/* Pointers to childs' node pointer info */
uint16_t mid_record; /* Index of "middle" record in current node */
uint16_t old_node_nrec; /* Number of records in internal node split */
unsigned left_child_flags = H5AC__NO_FLAGS_SET, right_child_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting child nodes */
+ unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -206,7 +219,7 @@ H5B2_split1(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth, H5B2_node_ptr_t *cur
/* Create new internal node */
internal->node_ptrs[idx + 1].all_nrec = internal->node_ptrs[idx + 1].node_nrec = 0;
- if(H5B2_create_internal(hdr, dxpl_id, &(internal->node_ptrs[idx + 1]), (depth - 1)) < 0)
+ if(H5B2_create_internal(hdr, dxpl_id, internal, &(internal->node_ptrs[idx + 1]), (depth - 1)) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new internal node")
/* Setup information for unlocking child nodes */
@@ -214,12 +227,19 @@ H5B2_split1(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth, H5B2_node_ptr_t *cur
left_addr = internal->node_ptrs[idx].addr;
right_addr = internal->node_ptrs[idx + 1].addr;
- /* Protect both leafs */
- if(NULL == (left_int = H5B2_protect_internal(hdr, dxpl_id, left_addr, internal->node_ptrs[idx].node_nrec, (depth - 1), H5AC_WRITE)))
+ /* Protect both leaves */
+ if(NULL == (left_int = H5B2_protect_internal(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx].node_nrec, (depth - 1), H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
- if(NULL == (right_int = H5B2_protect_internal(hdr, dxpl_id, right_addr, internal->node_ptrs[idx + 1].node_nrec, (depth - 1), H5AC_WRITE)))
+ if(NULL == (right_int = H5B2_protect_internal(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, (depth - 1), H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
+ /* Shadow the left node if doing SWMR writes */
+ if(hdr->swmr_write) {
+ if(H5B2_shadow_internal(hdr, dxpl_id, (depth - 1), &(internal->node_ptrs[idx]), &left_int) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow internal node")
+ left_addr = internal->node_ptrs[idx].addr;
+ } /* end if */
+
/* More setup for child nodes */
left_child = left_int;
right_child = right_int;
@@ -235,7 +255,7 @@ H5B2_split1(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth, H5B2_node_ptr_t *cur
/* Create new leaf node */
internal->node_ptrs[idx + 1].all_nrec = internal->node_ptrs[idx + 1].node_nrec = 0;
- if(H5B2_create_leaf(hdr, dxpl_id, &(internal->node_ptrs[idx + 1])) < 0)
+ if(H5B2_create_leaf(hdr, dxpl_id, internal, &(internal->node_ptrs[idx + 1])) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new leaf node")
/* Setup information for unlocking child nodes */
@@ -243,12 +263,19 @@ H5B2_split1(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth, H5B2_node_ptr_t *cur
left_addr = internal->node_ptrs[idx].addr;
right_addr = internal->node_ptrs[idx + 1].addr;
- /* Protect both leafs */
- if(NULL == (left_leaf = H5B2_protect_leaf(hdr, dxpl_id, left_addr, internal->node_ptrs[idx].node_nrec, H5AC_WRITE)))
+ /* Protect both leaves */
+ if(NULL == (left_leaf = H5B2_protect_leaf(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx].node_nrec, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
- if(NULL == (right_leaf = H5B2_protect_leaf(hdr, dxpl_id, right_addr, internal->node_ptrs[idx + 1].node_nrec, H5AC_WRITE)))
+ if(NULL == (right_leaf = H5B2_protect_leaf(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
+ /* Shadow the left node if doing SWMR writes */
+ if(hdr->swmr_write) {
+ if(H5B2_shadow_leaf(hdr, dxpl_id, &(internal->node_ptrs[idx]), &left_leaf) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow internal node")
+ left_addr = internal->node_ptrs[idx].addr;
+ } /* end if */
+
/* More setup for child nodes */
left_child = left_leaf;
right_child = right_leaf;
@@ -287,7 +314,6 @@ H5B2_split1(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth, H5B2_node_ptr_t *cur
/* Determine total number of records in new child nodes */
if(depth > 1) {
- unsigned u; /* Local index variable */
hsize_t new_left_all_nrec; /* New total number of records in left child */
hsize_t new_right_all_nrec; /* New total number of records in right child */
@@ -321,6 +347,76 @@ H5B2_split1(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth, H5B2_node_ptr_t *cur
if(parent_cache_info_flags_ptr)
*parent_cache_info_flags_ptr |= H5AC__DIRTIED_FLAG;
+ /* Update flush dependencies */
+ if(hdr->swmr_write) {
+ /* Update dependencies on records */
+ if(hdr->cls->upd_flush_dep) {
+ /* Update right child's records */
+ for(u = 0; u < *right_nrec; u++)
+ if(hdr->cls->upd_flush_dep(H5B2_NAT_NREC(right_native, hdr, u), udata, left_child, right_child) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+
+ /* Update the middle record */
+ if(hdr->cls->upd_flush_dep(H5B2_INT_NREC(internal, hdr, idx), udata, left_child, internal) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+ } /* end if */
+
+ /* Update node pointers */
+ if(depth > 1) {
+ /* Loop over grandchildren */
+ for(u = 0; u < (*right_nrec + (unsigned)1); u++) {
+ hbool_t update_deps = FALSE; /* Whether to update flush dependencies */
+
+ grandchild_addr = right_node_ptrs[u].addr;
+ if(depth > 2) {
+ H5B2_internal_t *grandchild_int = NULL;
+
+ /* Protect grandchild */
+ if(NULL == (grandchild_int = H5B2_protect_internal(hdr, dxpl_id, grandchild_addr, right_child, right_node_ptrs[u].node_nrec, (depth - 2), H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
+ grandchild_class = H5AC_BT2_INT;
+ grandchild = grandchild_int;
+
+ if(grandchild_int->parent == left_child) {
+ grandchild_int->parent = right_child;
+ update_deps = TRUE;
+ } /* end if */
+ else
+ HDassert(grandchild_int->parent == right_child);
+ } /* end if */
+ else {
+ H5B2_leaf_t *grandchild_leaf = NULL;
+
+ /* Protect grandchild */
+ if(NULL == (grandchild_leaf = H5B2_protect_leaf(hdr, dxpl_id, grandchild_addr, right_child, right_node_ptrs[u].node_nrec, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
+ grandchild_class = H5AC_BT2_LEAF;
+ grandchild = grandchild_leaf;
+
+ if(grandchild_leaf->parent == left_child) {
+ grandchild_leaf->parent = right_child;
+ update_deps = TRUE;
+ } /* end if */
+ else
+ HDassert(grandchild_leaf->parent == right_child);
+ } /* end else */
+
+ /* Update flush dependencies if necessary */
+ if(update_deps) {
+ if(H5AC_destroy_flush_dependency(left_child, grandchild) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency")
+ if(H5AC_create_flush_dependency(right_child, grandchild) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
+ } /* end if */
+
+ /* Unprotect the grandchild */
+ if(H5AC_unprotect(hdr->f, dxpl_id, grandchild_class, right_node_ptrs[u].addr, grandchild, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ grandchild = NULL;
+ } /* end for */
+ } /* end if */
+ } /* end if */
+
#ifdef H5B2_DEBUG
H5B2_assert_internal((hsize_t)0, hdr, internal);
if(depth > 1) {
@@ -340,6 +436,17 @@ done:
if(right_child && H5AC_unprotect(hdr->f, dxpl_id, child_class, right_addr, right_child, right_child_flags) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree leaf node")
+ /* Release grandchild node if protected (only on error) */
+ if(grandchild && H5AC_unprotect(hdr->f, dxpl_id, grandchild_class, left_node_ptrs[u].addr, grandchild, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+
+ /* Unprotect the grandchild on error */
+ if(grandchild) {
+ HDassert(ret_value < 0);
+ if(H5AC_unprotect(hdr->f, dxpl_id, grandchild_class, grandchild_addr, grandchild, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ } /* end if */
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5B2_split1 */
@@ -359,7 +466,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5B2_split_root(H5B2_hdr_t *hdr, hid_t dxpl_id)
+H5B2_split_root(H5B2_hdr_t *hdr, hid_t dxpl_id, void *udata)
{
H5B2_internal_t *new_root = NULL; /* Pointer to new root node */
unsigned new_root_flags = H5AC__NO_FLAGS_SET; /* Cache flags for new root node */
@@ -399,18 +506,18 @@ H5B2_split_root(H5B2_hdr_t *hdr, hid_t dxpl_id)
/* Create new internal node to use as root */
hdr->root.node_nrec = 0;
- if(H5B2_create_internal(hdr, dxpl_id, &(hdr->root), hdr->depth) < 0)
+ if(H5B2_create_internal(hdr, dxpl_id, hdr, &(hdr->root), hdr->depth) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create new internal node")
/* Protect new root node */
- if(NULL == (new_root = H5B2_protect_internal(hdr, dxpl_id, hdr->root.addr, hdr->root.node_nrec, hdr->depth, H5AC_WRITE)))
+ if(NULL == (new_root = H5B2_protect_internal(hdr, dxpl_id, hdr->root.addr, hdr, hdr->root.node_nrec, hdr->depth, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
/* Set first node pointer in root node to old root node pointer info */
new_root->node_ptrs[0] = old_root_ptr;
/* Split original root node */
- if(H5B2_split1(hdr, dxpl_id, hdr->depth, &(hdr->root), NULL, new_root, &new_root_flags, 0) < 0)
+ if(H5B2_split1(hdr, dxpl_id, hdr->depth, &(hdr->root), NULL, new_root, &new_root_flags, 0, udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to split old root node")
done:
@@ -438,16 +545,20 @@ done:
*/
static herr_t
H5B2_redistribute2(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
- H5B2_internal_t *internal, unsigned idx)
+ H5B2_internal_t *internal, unsigned idx, void *udata)
{
const H5AC_class_t *child_class; /* Pointer to child node's class info */
haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */
void *left_child = NULL, *right_child = NULL; /* Pointers to child nodes */
+ const H5AC_class_t *grandchild_class; /* Pointer to grandchild node's class info */
+ haddr_t grandchild_addr; /* Grandchild address */
+ void *grandchild = NULL; /* Pointer to grandchild node */
uint16_t *left_nrec, *right_nrec; /* Pointers to child # of records */
uint8_t *left_native, *right_native; /* Pointers to childs' native records */
H5B2_node_ptr_t *left_node_ptrs = NULL, *right_node_ptrs = NULL;/* Pointers to childs' node pointer info */
hssize_t left_moved_nrec = 0, right_moved_nrec = 0; /* Number of records moved, for internal redistrib */
unsigned left_child_flags = H5AC__NO_FLAGS_SET, right_child_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting child nodes */
+ unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -467,11 +578,21 @@ H5B2_redistribute2(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
right_addr = internal->node_ptrs[idx + 1].addr;
/* Lock left & right B-tree child nodes */
- if(NULL == (left_internal = H5B2_protect_internal(hdr, dxpl_id, left_addr, internal->node_ptrs[idx].node_nrec, (depth - 1), H5AC_WRITE)))
+ if(NULL == (left_internal = H5B2_protect_internal(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx].node_nrec, (depth - 1), H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
- if(NULL == (right_internal = H5B2_protect_internal(hdr, dxpl_id, right_addr, internal->node_ptrs[idx + 1].node_nrec, (depth - 1), H5AC_WRITE)))
+ if(NULL == (right_internal = H5B2_protect_internal(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, (depth - 1), H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
+ /* Shadow both nodes if doing SWMR writes */
+ if(hdr->swmr_write) {
+ if(H5B2_shadow_internal(hdr, dxpl_id, (depth - 1), &(internal->node_ptrs[idx]), &left_internal) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow internal node")
+ if(H5B2_shadow_internal(hdr, dxpl_id, (depth - 1), &(internal->node_ptrs[idx + 1]), &right_internal) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow internal node")
+ left_addr = internal->node_ptrs[idx].addr;
+ right_addr = internal->node_ptrs[idx + 1].addr;
+ } /* end if */
+
/* More setup for child nodes */
left_child = left_internal;
right_child = right_internal;
@@ -492,11 +613,21 @@ H5B2_redistribute2(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
right_addr = internal->node_ptrs[idx + 1].addr;
/* Lock left & right B-tree child nodes */
- if(NULL == (left_leaf = H5B2_protect_leaf(hdr, dxpl_id, left_addr, internal->node_ptrs[idx].node_nrec, H5AC_WRITE)))
+ if(NULL == (left_leaf = H5B2_protect_leaf(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx].node_nrec, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
- if(NULL == (right_leaf = H5B2_protect_leaf(hdr, dxpl_id, right_addr, internal->node_ptrs[idx + 1].node_nrec, H5AC_WRITE)))
+ if(NULL == (right_leaf = H5B2_protect_leaf(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
+ /* Shadow both nodes if doing SWMR writes */
+ if(hdr->swmr_write) {
+ if(H5B2_shadow_leaf(hdr, dxpl_id, &(internal->node_ptrs[idx]), &left_leaf) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow leaf node")
+ if(H5B2_shadow_leaf(hdr, dxpl_id, &(internal->node_ptrs[idx + 1]), &right_leaf) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow leaf node")
+ left_addr = internal->node_ptrs[idx].addr;
+ right_addr = internal->node_ptrs[idx + 1].addr;
+ } /* end if */
+
/* More setup for child nodes */
left_child = left_leaf;
right_child = right_leaf;
@@ -541,7 +672,6 @@ H5B2_redistribute2(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
/* Handle node pointers, if we have an internal node */
if(depth > 1) {
hsize_t moved_nrec = move_nrec; /* Total number of records moved, for internal redistrib */
- unsigned u; /* Local index variable */
/* Count the number of records being moved */
for(u = 0; u < move_nrec; u++)
@@ -556,6 +686,80 @@ H5B2_redistribute2(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
HDmemmove(&(right_node_ptrs[0]), &(right_node_ptrs[move_nrec]), sizeof(H5B2_node_ptr_t) * (new_right_nrec + (unsigned)1));
} /* end if */
+ /* Update flush dependencies */
+ if(hdr->swmr_write) {
+ /* Update dependencies on records */
+ if(hdr->cls->upd_flush_dep) {
+ /* Update the old middle record */
+ if(hdr->cls->upd_flush_dep(H5B2_NAT_NREC(left_native, hdr, *left_nrec), udata, internal, left_child) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+
+ /* Update left child's records moved from right child */
+ for(u = (*left_nrec + (unsigned)1); u < *left_nrec + move_nrec; u++)
+ if(hdr->cls->upd_flush_dep(H5B2_NAT_NREC(left_native, hdr, u), udata, right_child, left_child) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+
+ /* Update the new middle record */
+ if(hdr->cls->upd_flush_dep(H5B2_INT_NREC(internal, hdr, idx), udata, right_child, internal) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+ } /* end if */
+
+ /* Update node pointers */
+ if(depth > 1) {
+ /* Loop over grandchildren */
+ for(u = (*left_nrec + (unsigned)1); u < (*left_nrec + (unsigned)move_nrec + (unsigned)1); u++) {
+ hbool_t update_deps = FALSE; /* Whether to update flush dependencies */
+
+ grandchild_addr = left_node_ptrs[u].addr;
+ if(depth > 2) {
+ H5B2_internal_t *grandchild_int = NULL;
+
+ /* Protect grandchild */
+ if(NULL == (grandchild_int = H5B2_protect_internal(hdr, dxpl_id, grandchild_addr, left_child, left_node_ptrs[u].node_nrec, (depth - 2), H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
+ grandchild_class = H5AC_BT2_INT;
+ grandchild = grandchild_int;
+
+ if(grandchild_int->parent == right_child) {
+ grandchild_int->parent = left_child;
+ update_deps = TRUE;
+ } /* end if */
+ else
+ HDassert(grandchild_int->parent == left_child);
+ } /* end if */
+ else {
+ H5B2_leaf_t *grandchild_leaf = NULL;
+
+ /* Protect grandchild */
+ if(NULL == (grandchild_leaf = H5B2_protect_leaf(hdr, dxpl_id, grandchild_addr, left_child, left_node_ptrs[u].node_nrec, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
+ grandchild_class = H5AC_BT2_LEAF;
+ grandchild = grandchild_leaf;
+
+ if(grandchild_leaf->parent == right_child) {
+ grandchild_leaf->parent = left_child;
+ update_deps = TRUE;
+ } /* end if */
+ else
+ HDassert(grandchild_leaf->parent == left_child);
+ } /* end else */
+
+ /* Update flush dependencies if necessary */
+ if(update_deps) {
+ if(H5AC_destroy_flush_dependency(right_child, grandchild) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency")
+ if(H5AC_create_flush_dependency(left_child, grandchild) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
+ } /* end if */
+
+ /* Unprotect the grandchild */
+ if(H5AC_unprotect(hdr->f, dxpl_id, grandchild_class, left_node_ptrs[u].addr, grandchild, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ grandchild = NULL;
+ } /* end for */
+ } /* end if */
+ } /* end if */
+
/* Update number of records in child nodes */
*left_nrec = (uint16_t)(*left_nrec + move_nrec);
*right_nrec = new_right_nrec;
@@ -570,6 +774,8 @@ H5B2_redistribute2(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
uint16_t new_left_nrec = (uint16_t)(*left_nrec + *right_nrec) / 2; /* New number of records for left child */
uint16_t move_nrec = (uint16_t)(*left_nrec - new_left_nrec); /* Number of records to move from left node to right */
+ HDassert(*left_nrec > *right_nrec);
+
/* Slide records in right node up */
HDmemmove(H5B2_NAT_NREC(right_native, hdr, move_nrec),
H5B2_NAT_NREC(right_native, hdr, 0),
@@ -588,7 +794,6 @@ H5B2_redistribute2(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
/* Handle node pointers, if we have an internal node */
if(depth > 1) {
hsize_t moved_nrec = move_nrec; /* Total number of records moved, for internal redistrib */
- unsigned u; /* Local index variable */
/* Slide node pointers in right node up */
HDmemmove(&(right_node_ptrs[move_nrec]), &(right_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * (size_t)(*right_nrec + 1));
@@ -603,6 +808,80 @@ H5B2_redistribute2(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
H5_ASSIGN_OVERFLOW(/* To: */ right_moved_nrec, /* From: */ moved_nrec, /* From: */ hsize_t, /* To: */ hssize_t)
} /* end if */
+ /* Update flush dependencies */
+ if(hdr->swmr_write) {
+ /* Update dependencies on records */
+ if(hdr->cls->upd_flush_dep) {
+ /* Update the old middle record */
+ if(hdr->cls->upd_flush_dep(H5B2_NAT_NREC(right_native, hdr, (move_nrec - 1)), udata, internal, right_child) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+
+ /* Update right child's records moved from left child */
+ for(u = 0; u < (unsigned)(move_nrec - 1); u++)
+ if(hdr->cls->upd_flush_dep(H5B2_NAT_NREC(right_native, hdr, u), udata, left_child, right_child) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+
+ /* Update the new middle record */
+ if(hdr->cls->upd_flush_dep(H5B2_INT_NREC(internal, hdr, idx), udata, left_child, internal) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+ } /* end if */
+
+ /* Update node pointers */
+ if(depth > 1) {
+ /* Loop over grandchildren */
+ for(u = 0; u < move_nrec; u++) {
+ hbool_t update_deps = FALSE; /* Whether to update flush dependencies */
+
+ grandchild_addr = right_node_ptrs[u].addr;
+ if(depth > 2) {
+ H5B2_internal_t *grandchild_int = NULL;
+
+ /* Protect grandchild */
+ if(NULL == (grandchild_int = H5B2_protect_internal(hdr, dxpl_id, grandchild_addr, right_child, right_node_ptrs[u].node_nrec, (depth - 2), H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
+ grandchild_class = H5AC_BT2_INT;
+ grandchild = grandchild_int;
+
+ if(grandchild_int->parent == left_child) {
+ grandchild_int->parent = right_child;
+ update_deps = TRUE;
+ } /* end if */
+ else
+ HDassert(grandchild_int->parent == right_child);
+ } /* end if */
+ else {
+ H5B2_leaf_t *grandchild_leaf = NULL;
+
+ /* Protect grandchild */
+ if(NULL == (grandchild_leaf = H5B2_protect_leaf(hdr, dxpl_id, grandchild_addr, right_child, right_node_ptrs[u].node_nrec, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
+ grandchild_class = H5AC_BT2_LEAF;
+ grandchild = grandchild_leaf;
+
+ if(grandchild_leaf->parent == left_child) {
+ grandchild_leaf->parent = right_child;
+ update_deps = TRUE;
+ } /* end if */
+ else
+ HDassert(grandchild_leaf->parent == right_child);
+ } /* end else */
+
+ /* Update flush dependencies if necessary */
+ if(update_deps) {
+ if(H5AC_destroy_flush_dependency(left_child, grandchild) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency")
+ if(H5AC_create_flush_dependency(right_child, grandchild) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
+ } /* end if */
+
+ /* Unprotect the grandchild */
+ if(H5AC_unprotect(hdr->f, dxpl_id, grandchild_class, right_node_ptrs[u].addr, grandchild, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ grandchild = NULL;
+ } /* end for */
+ } /* end if */
+ } /* end if */
+
/* Update number of records in child nodes */
*left_nrec = new_left_nrec;
*right_nrec = (uint16_t)(*right_nrec + move_nrec);
@@ -645,6 +924,17 @@ done:
if(right_child && H5AC_unprotect(hdr->f, dxpl_id, child_class, right_addr, right_child, right_child_flags) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
+ /* Release grandchild node if protected (only on error) */
+ if(grandchild && H5AC_unprotect(hdr->f, dxpl_id, grandchild_class, left_node_ptrs[u].addr, grandchild, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+
+ /* Unprotect the grandchild on error */
+ if(grandchild) {
+ HDassert(ret_value < 0);
+ if(H5AC_unprotect(hdr->f, dxpl_id, grandchild_class, grandchild_addr, grandchild, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ } /* end if */
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5B2_redistribute2 */
@@ -665,7 +955,8 @@ done:
*/
static herr_t
H5B2_redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
- H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx)
+ H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx,
+ void *udata)
{
H5B2_node_ptr_t *left_node_ptrs = NULL, *right_node_ptrs = NULL; /* Pointers to childs' node pointer info */
H5B2_node_ptr_t *middle_node_ptrs = NULL; /* Pointers to childs' node pointer info */
@@ -674,6 +965,9 @@ H5B2_redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
haddr_t middle_addr; /* Address of middle child node */
void *left_child = NULL, *right_child = NULL; /* Pointers to child nodes */
void *middle_child = NULL; /* Pointers to middle child node */
+ const H5AC_class_t *grandchild_class; /* Pointer to grandchild node's class info */
+ haddr_t grandchild_addr; /* Grandchild address */
+ void *grandchild = NULL; /* Pointer to grandchild node */
uint16_t *left_nrec, *right_nrec; /* Pointers to child # of records */
uint16_t *middle_nrec; /* Pointers to middle child # of records */
uint8_t *left_native, *right_native; /* Pointers to childs' native records */
@@ -682,6 +976,7 @@ H5B2_redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
hssize_t middle_moved_nrec = 0; /* Number of records moved, for internal split */
unsigned left_child_flags = H5AC__NO_FLAGS_SET, right_child_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting child nodes */
unsigned middle_child_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting child nodes */
+ unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -704,13 +999,26 @@ H5B2_redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
right_addr = internal->node_ptrs[idx + 1].addr;
/* Lock B-tree child nodes */
- if(NULL == (left_internal = H5B2_protect_internal(hdr, dxpl_id, left_addr, internal->node_ptrs[idx - 1].node_nrec, (depth - 1), H5AC_WRITE)))
+ if(NULL == (left_internal = H5B2_protect_internal(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx - 1].node_nrec, (depth - 1), H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
- if(NULL == (middle_internal = H5B2_protect_internal(hdr, dxpl_id, middle_addr, internal->node_ptrs[idx].node_nrec, (depth - 1), H5AC_WRITE)))
+ if(NULL == (middle_internal = H5B2_protect_internal(hdr, dxpl_id, middle_addr, internal, internal->node_ptrs[idx].node_nrec, (depth - 1), H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
- if(NULL == (right_internal = H5B2_protect_internal(hdr, dxpl_id, right_addr, internal->node_ptrs[idx + 1].node_nrec, (depth - 1), H5AC_WRITE)))
+ if(NULL == (right_internal = H5B2_protect_internal(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, (depth - 1), H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
+ /* Shadow all nodes if doing SWMR writes */
+ if(hdr->swmr_write) {
+ if(H5B2_shadow_internal(hdr, dxpl_id, (depth - 1), &(internal->node_ptrs[idx - 1]), &left_internal) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow internal node")
+ if(H5B2_shadow_internal(hdr, dxpl_id, (depth - 1), &(internal->node_ptrs[idx]), &middle_internal) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow internal node")
+ if(H5B2_shadow_internal(hdr, dxpl_id, (depth - 1), &(internal->node_ptrs[idx + 1]), &right_internal) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow internal node")
+ left_addr = internal->node_ptrs[idx - 1].addr;
+ middle_addr = internal->node_ptrs[idx].addr;
+ right_addr = internal->node_ptrs[idx + 1].addr;
+ } /* end if */
+
/* More setup for child nodes */
left_child = left_internal;
middle_child = middle_internal;
@@ -737,13 +1045,26 @@ H5B2_redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
right_addr = internal->node_ptrs[idx + 1].addr;
/* Lock B-tree child nodes */
- if(NULL == (left_leaf = H5B2_protect_leaf(hdr, dxpl_id, left_addr, internal->node_ptrs[idx - 1].node_nrec, H5AC_WRITE)))
+ if(NULL == (left_leaf = H5B2_protect_leaf(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx - 1].node_nrec, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
- if(NULL == (middle_leaf = H5B2_protect_leaf(hdr, dxpl_id, middle_addr, internal->node_ptrs[idx].node_nrec, H5AC_WRITE)))
+ if(NULL == (middle_leaf = H5B2_protect_leaf(hdr, dxpl_id, middle_addr, internal, internal->node_ptrs[idx].node_nrec, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
- if(NULL == (right_leaf = H5B2_protect_leaf(hdr, dxpl_id, right_addr, internal->node_ptrs[idx + 1].node_nrec, H5AC_WRITE)))
+ if(NULL == (right_leaf = H5B2_protect_leaf(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
+ /* Shadow all nodes if doing SWMR writes */
+ if(hdr->swmr_write) {
+ if(H5B2_shadow_leaf(hdr, dxpl_id, &(internal->node_ptrs[idx - 1]), &left_leaf) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow leaf node")
+ if(H5B2_shadow_leaf(hdr, dxpl_id, &(internal->node_ptrs[idx]), &middle_leaf) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow leaf node")
+ if(H5B2_shadow_leaf(hdr, dxpl_id, &(internal->node_ptrs[idx + 1]), &right_leaf) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow leaf node")
+ left_addr = internal->node_ptrs[idx - 1].addr;
+ middle_addr = internal->node_ptrs[idx].addr;
+ right_addr = internal->node_ptrs[idx + 1].addr;
+ } /* end if */
+
/* More setup for child nodes */
left_child = left_leaf;
middle_child = middle_leaf;
@@ -793,7 +1114,6 @@ H5B2_redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
if(depth > 1) {
hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */
unsigned move_nptrs; /* Number of node pointers to move */
- unsigned u; /* Local index variable */
/* Move middle node pointers into left node */
move_nptrs = (unsigned)(new_left_nrec - *left_nrec);
@@ -809,6 +1129,80 @@ H5B2_redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
HDmemmove(&(middle_node_ptrs[0]), &(middle_node_ptrs[move_nptrs]), sizeof(H5B2_node_ptr_t) * ((*middle_nrec - move_nptrs) + 1));
} /* end if */
+ /* Update flush dependencies */
+ if(hdr->swmr_write) {
+ /* Update dependencies on records */
+ if(hdr->cls->upd_flush_dep) {
+ /* Update the old parent record */
+ if(hdr->cls->upd_flush_dep(H5B2_NAT_NREC(left_native, hdr, *left_nrec), udata, internal, left_child) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+
+ /* Update left child's records moved from middle child */
+ for(u = (*left_nrec + (unsigned)1); u < *left_nrec + (unsigned)moved_middle_nrec; u++)
+ if(hdr->cls->upd_flush_dep(H5B2_NAT_NREC(left_native, hdr, u), udata, middle_child, left_child) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+
+ /* Update the new parent record */
+ if(hdr->cls->upd_flush_dep(H5B2_INT_NREC(internal, hdr, idx - 1), udata, middle_child, internal) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+ } /* end if */
+
+ /* Update node pointers */
+ if(depth > 1) {
+ /* Loop over grandchildren */
+ for(u = (*left_nrec + (unsigned)1); u < (*left_nrec + (unsigned)moved_middle_nrec + 1); u++) {
+ hbool_t update_deps = FALSE; /* Whether to update flush dependencies */
+
+ grandchild_addr = left_node_ptrs[u].addr;
+ if(depth > 2) {
+ H5B2_internal_t *grandchild_int = NULL;
+
+ /* Protect grandchild */
+ if(NULL == (grandchild_int = H5B2_protect_internal(hdr, dxpl_id, grandchild_addr, left_child, left_node_ptrs[u].node_nrec, (depth - 2), H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
+ grandchild_class = H5AC_BT2_INT;
+ grandchild = grandchild_int;
+
+ if(grandchild_int->parent == middle_child) {
+ grandchild_int->parent = left_child;
+ update_deps = TRUE;
+ } /* end if */
+ else
+ HDassert(grandchild_int->parent == left_child);
+ } /* end if */
+ else {
+ H5B2_leaf_t *grandchild_leaf = NULL;
+
+ /* Protect grandchild */
+ if(NULL == (grandchild_leaf = H5B2_protect_leaf(hdr, dxpl_id, grandchild_addr, left_child, left_node_ptrs[u].node_nrec, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
+ grandchild_class = H5AC_BT2_LEAF;
+ grandchild = grandchild_leaf;
+
+ if(grandchild_leaf->parent == middle_child) {
+ grandchild_leaf->parent = left_child;
+ update_deps = TRUE;
+ } /* end if */
+ else
+ HDassert(grandchild_leaf->parent == left_child);
+ } /* end else */
+
+ /* Update flush dependencies if necessary */
+ if(update_deps) {
+ if(H5AC_destroy_flush_dependency(middle_child, grandchild) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency")
+ if(H5AC_create_flush_dependency(left_child, grandchild) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
+ } /* end if */
+
+ /* Unprotect the grandchild */
+ if(H5AC_unprotect(hdr->f, dxpl_id, grandchild_class, left_node_ptrs[u].addr, grandchild, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ grandchild = NULL;
+ } /* end for */
+ } /* end if */
+ } /* end if */
+
/* Update the current number of records in middle node */
curr_middle_nrec = (uint16_t)(curr_middle_nrec - moved_middle_nrec);
@@ -837,7 +1231,6 @@ H5B2_redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
/* Move node pointers also if this is an internal node */
if(depth > 1) {
hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */
- unsigned u; /* Local index variable */
/* Slide the node pointers in right node up */
HDmemmove(&(right_node_ptrs[right_nrec_move]), &(right_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * (size_t)(*right_nrec + 1));
@@ -852,6 +1245,80 @@ H5B2_redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
middle_moved_nrec -= (hssize_t)(moved_nrec + right_nrec_move);
} /* end if */
+ /* Update flush dependencies */
+ if(hdr->swmr_write) {
+ /* Update dependencies on records */
+ if(hdr->cls->upd_flush_dep) {
+ /* Update the old parent record */
+ if(hdr->cls->upd_flush_dep(H5B2_NAT_NREC(right_native, hdr, (right_nrec_move - 1)), udata, internal, right_child) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+
+ /* Update right child's records moved from middle child */
+ for(u = 0; u < (right_nrec_move - 1); u++)
+ if(hdr->cls->upd_flush_dep(H5B2_NAT_NREC(right_native, hdr, u), udata, middle_child, right_child) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+
+ /* Update the new parent record */
+ if(hdr->cls->upd_flush_dep(H5B2_INT_NREC(internal, hdr, idx), udata, middle_child, internal) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+ } /* end if */
+
+ /* Update node pointers */
+ if(depth > 1) {
+ /* Loop over grandchildren */
+ for(u = 0; u < right_nrec_move; u++) {
+ hbool_t update_deps = FALSE; /* Whether to update flush dependencies */
+
+ grandchild_addr = right_node_ptrs[u].addr;
+ if(depth > 2) {
+ H5B2_internal_t *grandchild_int = NULL;
+
+ /* Protect grandchild */
+ if(NULL == (grandchild_int = H5B2_protect_internal(hdr, dxpl_id, grandchild_addr, right_child, right_node_ptrs[u].node_nrec, (depth - 2), H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
+ grandchild_class = H5AC_BT2_INT;
+ grandchild = grandchild_int;
+
+ if(grandchild_int->parent == middle_child) {
+ grandchild_int->parent = right_child;
+ update_deps = TRUE;
+ } /* end if */
+ else
+ HDassert(grandchild_int->parent == right_child);
+ } /* end if */
+ else {
+ H5B2_leaf_t *grandchild_leaf = NULL;
+
+ /* Protect grandchild */
+ if(NULL == (grandchild_leaf = H5B2_protect_leaf(hdr, dxpl_id, grandchild_addr, right_child, right_node_ptrs[u].node_nrec, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
+ grandchild_class = H5AC_BT2_LEAF;
+ grandchild = grandchild_leaf;
+
+ if(grandchild_leaf->parent == middle_child) {
+ grandchild_leaf->parent = right_child;
+ update_deps = TRUE;
+ } /* end if */
+ else
+ HDassert(grandchild_leaf->parent == right_child);
+ } /* end else */
+
+ /* Update flush dependencies if necessary */
+ if(update_deps) {
+ if(H5AC_destroy_flush_dependency(middle_child, grandchild) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency")
+ if(H5AC_create_flush_dependency(right_child, grandchild) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
+ } /* end if */
+
+ /* Unprotect the grandchild */
+ if(H5AC_unprotect(hdr->f, dxpl_id, grandchild_class, right_node_ptrs[u].addr, grandchild, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ grandchild = NULL;
+ } /* end for */
+ } /* end if */
+ } /* end if */
+
/* Update the current number of records in middle node */
curr_middle_nrec = (uint16_t)(curr_middle_nrec - right_nrec_move);
@@ -880,7 +1347,6 @@ H5B2_redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
/* Move node pointers also if this is an internal node */
if(depth > 1) {
hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */
- unsigned u; /* Local index variable */
/* Slide the node pointers in middle node up */
HDmemmove(&(middle_node_ptrs[left_nrec_move]), &(middle_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * (size_t)(curr_middle_nrec + 1));
@@ -895,6 +1361,80 @@ H5B2_redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
middle_moved_nrec += (hssize_t)(moved_nrec + left_nrec_move);
} /* end if */
+ /* Update flush dependencies */
+ if(hdr->swmr_write) {
+ /* Update dependencies on records */
+ if(hdr->cls->upd_flush_dep) {
+ /* Update the old parent record */
+ if(hdr->cls->upd_flush_dep(H5B2_NAT_NREC(middle_native, hdr, (left_nrec_move - 1)), udata, internal, middle_child) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+
+ /* Update middle child's records moved from left child */
+ for(u = 0; u < (left_nrec_move - 1); u++)
+ if(hdr->cls->upd_flush_dep(H5B2_NAT_NREC(middle_native, hdr, u), udata, left_child, middle_child) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+
+ /* Update the new parent record */
+ if(hdr->cls->upd_flush_dep(H5B2_INT_NREC(internal, hdr, idx - 1), udata, left_child, internal) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+ } /* end if */
+
+ /* Update node pointers */
+ if(depth > 1) {
+ /* Loop over grandchildren */
+ for(u = 0; u < left_nrec_move; u++) {
+ hbool_t update_deps = FALSE; /* Whether to update flush dependencies */
+
+ grandchild_addr = middle_node_ptrs[u].addr;
+ if(depth > 2) {
+ H5B2_internal_t *grandchild_int = NULL;
+
+ /* Protect grandchild */
+ if(NULL == (grandchild_int = H5B2_protect_internal(hdr, dxpl_id, grandchild_addr, middle_child, middle_node_ptrs[u].node_nrec, (depth - 2), H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
+ grandchild_class = H5AC_BT2_INT;
+ grandchild = grandchild_int;
+
+ if(grandchild_int->parent == left_child) {
+ grandchild_int->parent = middle_child;
+ update_deps = TRUE;
+ } /* end if */
+ else
+ HDassert(grandchild_int->parent == middle_child);
+ } /* end if */
+ else {
+ H5B2_leaf_t *grandchild_leaf = NULL;
+
+ /* Protect grandchild */
+ if(NULL == (grandchild_leaf = H5B2_protect_leaf(hdr, dxpl_id, grandchild_addr, middle_child, middle_node_ptrs[u].node_nrec, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
+ grandchild_class = H5AC_BT2_LEAF;
+ grandchild = grandchild_leaf;
+
+ if(grandchild_leaf->parent == left_child) {
+ grandchild_leaf->parent = middle_child;
+ update_deps = TRUE;
+ } /* end if */
+ else
+ HDassert(grandchild_leaf->parent == middle_child);
+ } /* end for */
+
+ /* Update flush dependencies if necessary */
+ if(update_deps) {
+ if(H5AC_destroy_flush_dependency(left_child, grandchild) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency")
+ if(H5AC_create_flush_dependency(middle_child, grandchild) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
+ } /* end else */
+
+ /* Unprotect the grandchild */
+ if(H5AC_unprotect(hdr->f, dxpl_id, grandchild_class, middle_node_ptrs[u].addr, grandchild, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ grandchild = NULL;
+ } /* end for */
+ } /* end if */
+ } /* end if */
+
/* Update the current number of records in middle node */
curr_middle_nrec = (uint16_t)(curr_middle_nrec + left_nrec_move);
@@ -922,7 +1462,6 @@ H5B2_redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
/* Move node pointers also if this is an internal node */
if(depth > 1) {
hsize_t moved_nrec; /* Total number of records moved, for internal redistrib */
- unsigned u; /* Local index variable */
/* Move right node pointers into middle node */
HDmemcpy(&(middle_node_ptrs[curr_middle_nrec + 1]), &(right_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * right_nrec_move);
@@ -937,6 +1476,80 @@ H5B2_redistribute3(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
HDmemmove(&(right_node_ptrs[0]), &(right_node_ptrs[right_nrec_move]), sizeof(H5B2_node_ptr_t) * (size_t)(new_right_nrec + 1));
} /* end if */
+ /* Update flush dependencies */
+ if(hdr->swmr_write) {
+ /* Update dependencies on records */
+ if(hdr->cls->upd_flush_dep) {
+ /* Update the old parent record */
+ if(hdr->cls->upd_flush_dep(H5B2_NAT_NREC(middle_native, hdr, curr_middle_nrec), udata, internal, middle_child) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+
+ /* Update middle child's records moved from right child */
+ for(u = (curr_middle_nrec + (unsigned)1); u < curr_middle_nrec + right_nrec_move; u++)
+ if(hdr->cls->upd_flush_dep(H5B2_NAT_NREC(middle_native, hdr, u), udata, right_child, middle_child) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+
+ /* Update the new parent record */
+ if(hdr->cls->upd_flush_dep(H5B2_INT_NREC(internal, hdr, idx), udata, right_child, internal) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+ } /* end if */
+
+ /* Update node pointers */
+ if(depth > 1) {
+ /* Loop over grandchildren */
+ for(u = (curr_middle_nrec + (unsigned)1); u < (curr_middle_nrec + right_nrec_move + 1); u++) {
+ hbool_t update_deps = FALSE; /* Whether to update flush dependencies */
+
+ grandchild_addr = middle_node_ptrs[u].addr;
+ if(depth > 2) {
+ H5B2_internal_t *grandchild_int = NULL;
+
+ /* Protect grandchild */
+ if(NULL == (grandchild_int = H5B2_protect_internal(hdr, dxpl_id, grandchild_addr, middle_child, middle_node_ptrs[u].node_nrec, (depth - 2), H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
+ grandchild_class = H5AC_BT2_INT;
+ grandchild = grandchild_int;
+
+ if(grandchild_int->parent == right_child) {
+ grandchild_int->parent = middle_child;
+ update_deps = TRUE;
+ } /* end if */
+ else
+ HDassert(grandchild_int->parent == middle_child);
+ } /* end if */
+ else {
+ H5B2_leaf_t *grandchild_leaf = NULL;
+
+ /* Protect grandchild */
+ if(NULL == (grandchild_leaf = H5B2_protect_leaf(hdr, dxpl_id, grandchild_addr, middle_child, middle_node_ptrs[u].node_nrec, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
+ grandchild_class = H5AC_BT2_LEAF;
+ grandchild = grandchild_leaf;
+
+ if(grandchild_leaf->parent == right_child) {
+ grandchild_leaf->parent = middle_child;
+ update_deps = TRUE;
+ } /* end if */
+ else
+ HDassert(grandchild_leaf->parent == middle_child);
+ } /* end else */
+
+ /* Update flush dependencies if necessary */
+ if(update_deps) {
+ if(H5AC_destroy_flush_dependency(right_child, grandchild) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency")
+ if(H5AC_create_flush_dependency(middle_child, grandchild) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
+ } /* end if */
+
+ /* Unprotect the grandchild */
+ if(H5AC_unprotect(hdr->f, dxpl_id, grandchild_class, middle_node_ptrs[u].addr, grandchild, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ grandchild = NULL;
+ } /* end for */
+ } /* end if */
+ } /* end if */
+
/* Mark nodes as dirty */
middle_child_flags |= H5AC__DIRTIED_FLAG;
right_child_flags |= H5AC__DIRTIED_FLAG;
@@ -1032,6 +1645,13 @@ done:
if(right_child && H5AC_unprotect(hdr->f, dxpl_id, child_class, right_addr, right_child, right_child_flags) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
+ /* Unprotect the grandchild on error */
+ if(grandchild) {
+ HDassert(ret_value < 0);
+ if(H5AC_unprotect(hdr->f, dxpl_id, grandchild_class, grandchild_addr, grandchild, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ } /* end if */
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5B2_redistribute3 */
@@ -1054,15 +1674,20 @@ done:
static herr_t
H5B2_merge2(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags_ptr,
- H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx)
+ H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx,
+ void *udata)
{
const H5AC_class_t *child_class; /* Pointer to child node's class info */
haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */
void *left_child = NULL, *right_child = NULL; /* Pointers to left & right child nodes */
+ const H5AC_class_t *grandchild_class; /* Pointer to grandchild node's class info */
+ haddr_t grandchild_addr; /* Grandchild address */
+ void *grandchild = NULL; /* Pointer to grandchild node */
uint16_t *left_nrec, *right_nrec; /* Pointers to left & right child # of records */
uint8_t *left_native, *right_native; /* Pointers to left & right children's native records */
H5B2_node_ptr_t *left_node_ptrs = NULL, *right_node_ptrs = NULL;/* Pointers to childs' node pointer info */
unsigned left_child_flags = H5AC__NO_FLAGS_SET, right_child_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting child nodes */
+ unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -1084,11 +1709,18 @@ H5B2_merge2(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
right_addr = internal->node_ptrs[idx + 1].addr;
/* Lock left & right B-tree child nodes */
- if(NULL == (left_internal = H5B2_protect_internal(hdr, dxpl_id, left_addr, internal->node_ptrs[idx].node_nrec, (depth - 1), H5AC_WRITE)))
+ if(NULL == (left_internal = H5B2_protect_internal(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx].node_nrec, (depth - 1), H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
- if(NULL == (right_internal = H5B2_protect_internal(hdr, dxpl_id, right_addr, internal->node_ptrs[idx + 1].node_nrec, (depth - 1), H5AC_WRITE)))
+ if(NULL == (right_internal = H5B2_protect_internal(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, (depth - 1), H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
+ /* Shadow the left node if doing SWMR writes */
+ if(hdr->swmr_write) {
+ if(H5B2_shadow_internal(hdr, dxpl_id, (depth - 1), &(internal->node_ptrs[idx]), &left_internal) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow internal node")
+ left_addr = internal->node_ptrs[idx].addr;
+ } /* end if */
+
/* More setup for accessing child node information */
left_child = left_internal;
right_child = right_internal;
@@ -1109,11 +1741,18 @@ H5B2_merge2(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
right_addr = internal->node_ptrs[idx + 1].addr;
/* Lock left & right B-tree child nodes */
- if(NULL == (left_leaf = H5B2_protect_leaf(hdr, dxpl_id, left_addr, internal->node_ptrs[idx].node_nrec, H5AC_WRITE)))
+ if(NULL == (left_leaf = H5B2_protect_leaf(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx].node_nrec, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
- if(NULL == (right_leaf = H5B2_protect_leaf(hdr, dxpl_id, right_addr, internal->node_ptrs[idx + 1].node_nrec, H5AC_WRITE)))
+ if(NULL == (right_leaf = H5B2_protect_leaf(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
+ /* Shadow the left node if doing SWMR writes */
+ if(hdr->swmr_write) {
+ if(H5B2_shadow_leaf(hdr, dxpl_id, &(internal->node_ptrs[idx]), &left_leaf) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow leaf node")
+ left_addr = internal->node_ptrs[idx].addr;
+ } /* end if */
+
/* More setup for accessing child node information */
left_child = left_leaf;
right_child = right_leaf;
@@ -1135,12 +1774,84 @@ H5B2_merge2(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
if(depth > 1)
HDmemcpy(&(left_node_ptrs[*left_nrec + 1]), &(right_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * (size_t)(*right_nrec + 1));
+ /* Update flush dependencies */
+ if(hdr->swmr_write) {
+ /* Update dependencies on records */
+ if(hdr->cls->upd_flush_dep) {
+ /* Update the old parent record */
+ if(hdr->cls->upd_flush_dep(H5B2_NAT_NREC(left_native, hdr, *left_nrec), udata, internal, left_child) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+
+ /* Update records moved from right child */
+ for(u = (*left_nrec + (unsigned)1); u < (*left_nrec + (unsigned)*right_nrec + (unsigned)1); u++)
+ if(hdr->cls->upd_flush_dep(H5B2_NAT_NREC(left_native, hdr, u), udata, right_child, left_child) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+ } /* end if */
+
+ /* Update node pointers */
+ if(depth > 1) {
+ /* Loop over grandchildren */
+ for(u = (*left_nrec + (unsigned)1); u < (*left_nrec + (unsigned)*right_nrec + (unsigned)2); u++) {
+ hbool_t update_deps = FALSE; /* Whether to update flush dependencies */
+
+ grandchild_addr = left_node_ptrs[u].addr;
+ if(depth > 2) {
+ H5B2_internal_t *grandchild_int = NULL;
+
+ /* Protect grandchild */
+ if(NULL == (grandchild_int = H5B2_protect_internal(hdr, dxpl_id, grandchild_addr, left_child, left_node_ptrs[u].node_nrec, (depth - 2), H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
+ grandchild_class = H5AC_BT2_INT;
+ grandchild = grandchild_int;
+
+ if(grandchild_int->parent == right_child) {
+ grandchild_int->parent = left_child;
+ update_deps = TRUE;
+ } /* end if */
+ else
+ HDassert(grandchild_int->parent == left_child);
+ } /* end if */
+ else {
+ H5B2_leaf_t *grandchild_leaf = NULL;
+
+ /* Protect grandchild */
+ if(NULL == (grandchild_leaf = H5B2_protect_leaf(hdr, dxpl_id, grandchild_addr, left_child, left_node_ptrs[u].node_nrec, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
+ grandchild_class = H5AC_BT2_LEAF;
+ grandchild = grandchild_leaf;
+
+ if(grandchild_leaf->parent == right_child) {
+ grandchild_leaf->parent = left_child;
+ update_deps = TRUE;
+ } /* end if */
+ else
+ HDassert(grandchild_leaf->parent == left_child);
+ } /* end else */
+
+ /* Update flush dependencies if necessary */
+ if(update_deps) {
+ if(H5AC_destroy_flush_dependency(right_child, grandchild) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency")
+ if(H5AC_create_flush_dependency(left_child, grandchild) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
+ } /* end if */
+
+ /* Unprotect the grandchild */
+ if(H5AC_unprotect(hdr->f, dxpl_id, grandchild_class, left_node_ptrs[u].addr, grandchild, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ grandchild = NULL;
+ } /* end for */
+ } /* end if */
+ } /* end if */
+
/* Update # of records in left node */
*left_nrec = (uint16_t)(*left_nrec + *right_nrec + 1);
/* Mark nodes as dirty */
left_child_flags |= H5AC__DIRTIED_FLAG;
- right_child_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
+ right_child_flags |= H5AC__DELETED_FLAG;
+ if(!(hdr->swmr_write))
+ right_child_flags |= H5AC__DIRTIED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
} /* end block */
/* Update # of records in child nodes */
@@ -1185,6 +1896,13 @@ done:
if(right_child && H5AC_unprotect(hdr->f, dxpl_id, child_class, right_addr, right_child, right_child_flags) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
+ /* Unprotect the grandchild on error */
+ if(grandchild) {
+ HDassert(ret_value < 0);
+ if(H5AC_unprotect(hdr->f, dxpl_id, grandchild_class, grandchild_addr, grandchild, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ } /* end if */
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5B2_merge2() */
@@ -1207,13 +1925,17 @@ done:
static herr_t
H5B2_merge3(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
H5B2_node_ptr_t *curr_node_ptr, unsigned *parent_cache_info_flags_ptr,
- H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx)
+ H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx,
+ void *udata)
{
const H5AC_class_t *child_class; /* Pointer to child node's class info */
haddr_t left_addr, right_addr; /* Addresses of left & right child nodes */
haddr_t middle_addr; /* Address of middle child node */
void *left_child = NULL, *right_child = NULL; /* Pointers to left & right child nodes */
void *middle_child = NULL; /* Pointer to middle child node */
+ const H5AC_class_t *grandchild_class; /* Pointer to grandchild node's class info */
+ haddr_t grandchild_addr; /* Grandchild address */
+ void *grandchild = NULL; /* Pointer to grandchild node */
uint16_t *left_nrec, *right_nrec; /* Pointers to left & right child # of records */
uint16_t *middle_nrec; /* Pointer to middle child # of records */
uint8_t *left_native, *right_native; /* Pointers to left & right children's native records */
@@ -1223,6 +1945,7 @@ H5B2_merge3(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
hsize_t middle_moved_nrec; /* Number of records moved, for internal split */
unsigned left_child_flags = H5AC__NO_FLAGS_SET, right_child_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting child nodes */
unsigned middle_child_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting child nodes */
+ unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -1246,13 +1969,23 @@ H5B2_merge3(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
right_addr = internal->node_ptrs[idx + 1].addr;
/* Lock B-tree child nodes */
- if(NULL == (left_internal = H5B2_protect_internal(hdr, dxpl_id, left_addr, internal->node_ptrs[idx - 1].node_nrec, (depth - 1), H5AC_WRITE)))
+ if(NULL == (left_internal = H5B2_protect_internal(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx - 1].node_nrec, (depth - 1), H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
- if(NULL == (middle_internal = H5B2_protect_internal(hdr, dxpl_id, middle_addr, internal->node_ptrs[idx].node_nrec, (depth - 1), H5AC_WRITE)))
+ if(NULL == (middle_internal = H5B2_protect_internal(hdr, dxpl_id, middle_addr, internal, internal->node_ptrs[idx].node_nrec, (depth - 1), H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
- if(NULL == (right_internal = H5B2_protect_internal(hdr, dxpl_id, right_addr, internal->node_ptrs[idx + 1].node_nrec, (depth - 1), H5AC_WRITE)))
+ if(NULL == (right_internal = H5B2_protect_internal(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, (depth - 1), H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
+ /* Shadow left and middle nodes if doing SWMR writes */
+ if(hdr->swmr_write) {
+ if(H5B2_shadow_internal(hdr, dxpl_id, (depth - 1), &(internal->node_ptrs[idx - 1]), &left_internal) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow internal node")
+ if(H5B2_shadow_internal(hdr, dxpl_id, (depth - 1), &(internal->node_ptrs[idx]), &middle_internal) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow internal node")
+ left_addr = internal->node_ptrs[idx - 1].addr;
+ middle_addr = internal->node_ptrs[idx].addr;
+ } /* end if */
+
/* More setup for accessing child node information */
left_child = left_internal;
middle_child = middle_internal;
@@ -1279,13 +2012,23 @@ H5B2_merge3(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
right_addr = internal->node_ptrs[idx + 1].addr;
/* Lock B-tree child nodes */
- if(NULL == (left_leaf = H5B2_protect_leaf(hdr, dxpl_id, left_addr, internal->node_ptrs[idx - 1].node_nrec, H5AC_WRITE)))
+ if(NULL == (left_leaf = H5B2_protect_leaf(hdr, dxpl_id, left_addr, internal, internal->node_ptrs[idx - 1].node_nrec, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
- if(NULL == (middle_leaf = H5B2_protect_leaf(hdr, dxpl_id, middle_addr, internal->node_ptrs[idx].node_nrec, H5AC_WRITE)))
+ if(NULL == (middle_leaf = H5B2_protect_leaf(hdr, dxpl_id, middle_addr, internal, internal->node_ptrs[idx].node_nrec, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
- if(NULL == (right_leaf = H5B2_protect_leaf(hdr, dxpl_id, right_addr, internal->node_ptrs[idx + 1].node_nrec, H5AC_WRITE)))
+ if(NULL == (right_leaf = H5B2_protect_leaf(hdr, dxpl_id, right_addr, internal, internal->node_ptrs[idx + 1].node_nrec, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
+ /* Shadow left and middle nodes if doing SWMR writes */
+ if(hdr->swmr_write) {
+ if(H5B2_shadow_leaf(hdr, dxpl_id, &(internal->node_ptrs[idx - 1]), &left_leaf) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow leaf node")
+ if(H5B2_shadow_leaf(hdr, dxpl_id, &(internal->node_ptrs[idx]), &middle_leaf) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow leaf node")
+ left_addr = internal->node_ptrs[idx - 1].addr;
+ middle_addr = internal->node_ptrs[idx].addr;
+ } /* end if */
+
/* More setup for accessing child node information */
left_child = left_leaf;
middle_child = middle_leaf;
@@ -1320,7 +2063,6 @@ H5B2_merge3(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
/* Move node pointers also if this is an internal node */
if(depth > 1) {
- unsigned u; /* Local index variable */
/* Copy node pointers from middle node into left node */
HDmemcpy(&(left_node_ptrs[*left_nrec + 1]), &(middle_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * middle_nrec_move);
@@ -1333,6 +2075,80 @@ H5B2_merge3(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
HDmemmove(&(middle_node_ptrs[0]), &(middle_node_ptrs[middle_nrec_move]), sizeof(H5B2_node_ptr_t) * (size_t)((unsigned)(*middle_nrec + 1) - middle_nrec_move));
} /* end if */
+ /* Update flush dependencies */
+ if(hdr->swmr_write) {
+ /* Update dependencies on records */
+ if(hdr->cls->upd_flush_dep) {
+ /* Update the old parent record */
+ if(hdr->cls->upd_flush_dep(H5B2_NAT_NREC(left_native, hdr, *left_nrec), udata, internal, left_child) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+
+ /* Update records moved from middle child */
+ for(u = (*left_nrec + (unsigned)1); u < (*left_nrec + (unsigned)middle_nrec_move); u++)
+ if(hdr->cls->upd_flush_dep(H5B2_NAT_NREC(left_native, hdr, u), udata, middle_child, left_child) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+
+ /* Update the new parent record */
+ if(hdr->cls->upd_flush_dep(H5B2_INT_NREC(internal, hdr, idx), udata, middle_child, internal) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+ } /* end if */
+
+ /* Update node pointers */
+ if(depth > 1) {
+ /* Loop over grandchildren */
+ for(u = (*left_nrec + (unsigned)1); u < (*left_nrec + (unsigned)middle_nrec_move + (unsigned)1); u++) {
+ hbool_t update_deps = FALSE; /* Whether to update flush dependencies */
+
+ grandchild_addr = left_node_ptrs[u].addr;
+ if(depth > 2) {
+ H5B2_internal_t *grandchild_int = NULL;
+
+ /* Protect grandchild */
+ if(NULL == (grandchild_int = H5B2_protect_internal(hdr, dxpl_id, grandchild_addr, left_child, left_node_ptrs[u].node_nrec, (depth - 2), H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
+ grandchild_class = H5AC_BT2_INT;
+ grandchild = grandchild_int;
+
+ if(grandchild_int->parent == middle_child) {
+ grandchild_int->parent = left_child;
+ update_deps = TRUE;
+ } /* end if */
+ else
+ HDassert(grandchild_int->parent == left_child);
+ } /* end if */
+ else {
+ H5B2_leaf_t *grandchild_leaf = NULL;
+
+ /* Protect grandchild */
+ if(NULL == (grandchild_leaf = H5B2_protect_leaf(hdr, dxpl_id, grandchild_addr, left_child, left_node_ptrs[u].node_nrec, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
+ grandchild_class = H5AC_BT2_LEAF;
+ grandchild = grandchild_leaf;
+
+ if(grandchild_leaf->parent == middle_child) {
+ grandchild_leaf->parent = left_child;
+ update_deps = TRUE;
+ } /* end if */
+ else
+ HDassert(grandchild_leaf->parent == left_child);
+ } /* end else */
+
+ /* Update flush dependencies if necessary */
+ if(update_deps) {
+ if(H5AC_destroy_flush_dependency(middle_child, grandchild) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency")
+ if(H5AC_create_flush_dependency(left_child, grandchild) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
+ } /* end if */
+
+ /* Unprotect the grandchild */
+ if(H5AC_unprotect(hdr->f, dxpl_id, grandchild_class, left_node_ptrs[u].addr, grandchild, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ grandchild = NULL;
+ } /* end for */
+ } /* end if */
+ } /* end if */
+
/* Update # of records in left & middle nodes */
*left_nrec = (uint16_t)(*left_nrec + middle_nrec_move);
*middle_nrec = (uint16_t)(*middle_nrec - middle_nrec_move);
@@ -1355,12 +2171,84 @@ H5B2_merge3(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
/* Copy node pointers from right node into middle node */
HDmemcpy(&(middle_node_ptrs[*middle_nrec + 1]), &(right_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * (size_t)(*right_nrec + 1));
+ /* Update flush dependencies */
+ if(hdr->swmr_write) {
+ /* Update dependencies on records */
+ if(hdr->cls->upd_flush_dep) {
+ /* Update the old parent record */
+ if(hdr->cls->upd_flush_dep(H5B2_NAT_NREC(middle_native, hdr, *middle_nrec), udata, internal, middle_child) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+
+ /* Update records moved from right child */
+ for(u = (*middle_nrec + (unsigned)1); u < (*middle_nrec + (unsigned)*right_nrec + (unsigned)1); u++)
+ if(hdr->cls->upd_flush_dep(H5B2_NAT_NREC(left_native, hdr, u), udata, right_child, middle_child) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+ } /* end if */
+
+ /* Update node pointers */
+ if(depth > 1) {
+ /* Loop over grandchildren */
+ for(u = (*middle_nrec + (unsigned)1); u < (*middle_nrec + (unsigned)*right_nrec + (unsigned)2); u++) {
+ hbool_t update_deps = FALSE; /* Whether to update flush dependencies */
+
+ grandchild_addr = middle_node_ptrs[u].addr;
+ if(depth > 2) {
+ H5B2_internal_t *grandchild_int = NULL;
+
+ /* Protect grandchild */
+ if(NULL == (grandchild_int = H5B2_protect_internal(hdr, dxpl_id, grandchild_addr, middle_child, middle_node_ptrs[u].node_nrec, (depth - 2), H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
+ grandchild_class = H5AC_BT2_INT;
+ grandchild = grandchild_int;
+
+ if(grandchild_int->parent == right_child) {
+ grandchild_int->parent = middle_child;
+ update_deps = TRUE;
+ } /* end if */
+ else
+ HDassert(grandchild_int->parent == middle_child);
+ } /* end if */
+ else {
+ H5B2_leaf_t *grandchild_leaf = NULL;
+
+ /* Protect grandchild */
+ if(NULL == (grandchild_leaf = H5B2_protect_leaf(hdr, dxpl_id, grandchild_addr, middle_child, middle_node_ptrs[u].node_nrec, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
+ grandchild_class = H5AC_BT2_LEAF;
+ grandchild = grandchild_leaf;
+
+ if(grandchild_leaf->parent == right_child) {
+ grandchild_leaf->parent = middle_child;
+ update_deps = TRUE;
+ } /* end if */
+ else
+ HDassert(grandchild_leaf->parent == middle_child);
+ } /* end else */
+
+ /* Update flush dependencies if necessary */
+ if(update_deps) {
+ if(H5AC_destroy_flush_dependency(right_child, grandchild) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency")
+ if(H5AC_create_flush_dependency(middle_child, grandchild) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
+ } /* end if */
+
+ /* Unprotect the grandchild */
+ if(H5AC_unprotect(hdr->f, dxpl_id, grandchild_class, middle_node_ptrs[u].addr, grandchild, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ grandchild = NULL;
+ } /* end for */
+ } /* end if */
+ } /* end if */
+
/* Update # of records in middle node */
*middle_nrec = (uint16_t)(*middle_nrec + (*right_nrec + 1));
/* Mark nodes as dirty */
middle_child_flags |= H5AC__DIRTIED_FLAG;
- right_child_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
+ right_child_flags |= H5AC__DELETED_FLAG;
+ if(!(hdr->swmr_write))
+ right_child_flags |= H5AC__DIRTIED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
} /* end block */
/* Update # of records in child nodes */
@@ -1413,6 +2301,13 @@ done:
if(right_child && H5AC_unprotect(hdr->f, dxpl_id, child_class, right_addr, right_child, right_child_flags) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
+ /* Unprotect the grandchild on error */
+ if(grandchild) {
+ HDassert(ret_value < 0);
+ if(H5AC_unprotect(hdr->f, dxpl_id, grandchild_class, grandchild_addr, grandchild, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ } /* end if */
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5B2_merge3() */
@@ -1435,7 +2330,7 @@ done:
static herr_t
H5B2_swap_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
H5B2_internal_t *internal, unsigned *internal_flags_ptr,
- unsigned idx, void *swap_loc)
+ unsigned idx, void *swap_loc, void *swap_parent, void *udata)
{
const H5AC_class_t *child_class; /* Pointer to child node's class info */
haddr_t child_addr; /* Address of child node */
@@ -1460,7 +2355,7 @@ H5B2_swap_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
child_addr = internal->node_ptrs[idx].addr;
/* Lock B-tree child nodes */
- if(NULL == (child_internal = H5B2_protect_internal(hdr, dxpl_id, child_addr, internal->node_ptrs[idx].node_nrec, (depth - 1), H5AC_WRITE)))
+ if(NULL == (child_internal = H5B2_protect_internal(hdr, dxpl_id, child_addr, internal, internal->node_ptrs[idx].node_nrec, (depth - 1), H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
/* More setup for accessing child node information */
@@ -1475,7 +2370,7 @@ H5B2_swap_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
child_addr = internal->node_ptrs[idx].addr;
/* Lock B-tree child node */
- if(NULL == (child_leaf = H5B2_protect_leaf(hdr, dxpl_id, child_addr, internal->node_ptrs[idx].node_nrec, H5AC_WRITE)))
+ if(NULL == (child_leaf = H5B2_protect_leaf(hdr, dxpl_id, child_addr, internal, internal->node_ptrs[idx].node_nrec, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
/* More setup for accessing child node information */
@@ -1488,6 +2383,14 @@ H5B2_swap_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
HDmemcpy(H5B2_NAT_NREC(child_native, hdr, 0), swap_loc, hdr->cls->nrec_size);
HDmemcpy(swap_loc, hdr->page, hdr->cls->nrec_size);
+ /* Update flush dependencies */
+ if(hdr->swmr_write && hdr->cls->upd_flush_dep) {
+ if(hdr->cls->upd_flush_dep(H5B2_NAT_NREC(child_native, hdr, 0), udata, swap_parent, child) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+ if(hdr->cls->upd_flush_dep(swap_loc, udata, child, swap_parent) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+ } /* end if */
+
/* Mark parent as dirty */
*internal_flags_ptr |= H5AC__DIRTIED_FLAG;
@@ -1523,7 +2426,7 @@ done:
*/
herr_t
H5B2_insert_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *curr_node_ptr,
- void *udata)
+ void *parent, void *udata)
{
H5B2_leaf_t *leaf; /* Pointer to leaf node */
int cmp; /* Comparison value of records */
@@ -1538,9 +2441,14 @@ H5B2_insert_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *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_WRITE)))
+ if(NULL == (leaf = H5B2_protect_leaf(hdr, dxpl_id, curr_node_ptr->addr, parent, curr_node_ptr->node_nrec, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
+ /* Shadow the node if doing SWMR writes */
+ if(hdr->swmr_write)
+ if(H5B2_shadow_leaf(hdr, dxpl_id, curr_node_ptr, &leaf) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow leaf node")
+
/* 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);
@@ -1567,6 +2475,11 @@ H5B2_insert_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *curr_node_ptr,
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")
+ /* Set up flush dependency on child client object, if appropriate */
+ if(hdr->swmr_write && hdr->cls->crt_flush_dep)
+ if((hdr->cls->crt_flush_dep)(H5B2_LEAF_NREC(leaf, hdr, idx), udata, leaf) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
+
/* Update record count for node pointer to current node */
curr_node_ptr->all_nrec++;
curr_node_ptr->node_nrec++;
@@ -1577,7 +2490,7 @@ H5B2_insert_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *curr_node_ptr,
done:
/* Release the B-tree leaf node (marked as dirty) */
if(leaf && H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr->addr, leaf, H5AC__DIRTIED_FLAG) < 0)
- HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release leaf B-tree node")
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release leaf B-tree node")\
FUNC_LEAVE_NOAPI(ret_value)
} /* H5B2_insert_leaf() */
@@ -1599,9 +2512,9 @@ done:
herr_t
H5B2_insert_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
unsigned *parent_cache_info_flags_ptr, H5B2_node_ptr_t *curr_node_ptr,
- void *udata)
+ void *parent, void *udata)
{
- H5B2_internal_t *internal; /* Pointer to internal node */
+ H5B2_internal_t *internal = NULL; /* Pointer to internal node */
unsigned internal_flags = H5AC__NO_FLAGS_SET;
unsigned idx; /* Location of record which matches key */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1615,10 +2528,15 @@ H5B2_insert_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
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_WRITE)))
+ if(NULL == (internal = H5B2_protect_internal(hdr, dxpl_id, curr_node_ptr->addr, parent, curr_node_ptr->node_nrec, depth, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
-/* Split or redistribute child node pointers, if necessary */
+ /* Shadow the node if doing SWMR writes */
+ if(hdr->swmr_write)
+ if(H5B2_shadow_internal(hdr, dxpl_id, depth, curr_node_ptr, &internal) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow internal node")
+
+ /* Split or redistribute child node pointers, if necessary */
{
int cmp; /* Comparison value of records */
unsigned retries; /* Number of times to attempt redistribution */
@@ -1646,35 +2564,35 @@ H5B2_insert_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
/* Attempt to redistribute records among children */
if(idx == 0) { /* Left-most child */
if(retries > 0 && (internal->node_ptrs[idx + 1].node_nrec < split_nrec)) {
- if(H5B2_redistribute2(hdr, dxpl_id, depth, internal, idx) < 0)
+ if(H5B2_redistribute2(hdr, dxpl_id, depth, internal, idx, udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
} /* end if */
else {
if(H5B2_split1(hdr, dxpl_id, depth, curr_node_ptr,
- parent_cache_info_flags_ptr, internal, &internal_flags, idx) < 0)
+ parent_cache_info_flags_ptr, internal, &internal_flags, idx, udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to split child node")
} /* end else */
} /* end if */
else if(idx == internal->nrec) { /* Right-most child */
if(retries > 0 && (internal->node_ptrs[idx - 1].node_nrec < split_nrec)) {
- if(H5B2_redistribute2(hdr, dxpl_id, depth, internal, (idx - 1)) < 0)
+ if(H5B2_redistribute2(hdr, dxpl_id, depth, internal, (idx - 1), udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
} /* end if */
else {
if(H5B2_split1(hdr, dxpl_id, depth, curr_node_ptr,
- parent_cache_info_flags_ptr, internal, &internal_flags, idx) < 0)
+ parent_cache_info_flags_ptr, internal, &internal_flags, idx, udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to split child node")
} /* end else */
} /* end if */
else { /* Middle child */
if(retries > 0 && ((internal->node_ptrs[idx + 1].node_nrec < split_nrec) ||
(internal->node_ptrs[idx - 1].node_nrec < split_nrec))) {
- if(H5B2_redistribute3(hdr, dxpl_id, depth, internal, &internal_flags, idx) < 0)
+ if(H5B2_redistribute3(hdr, dxpl_id, depth, internal, &internal_flags, idx, udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
} /* end if */
else {
if(H5B2_split1(hdr, dxpl_id, depth, curr_node_ptr,
- parent_cache_info_flags_ptr, internal, &internal_flags, idx) < 0)
+ parent_cache_info_flags_ptr, internal, &internal_flags, idx, udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to split child node")
} /* end else */
} /* end else */
@@ -1693,11 +2611,11 @@ H5B2_insert_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
/* Attempt to insert node */
if(depth > 1) {
- if(H5B2_insert_internal(hdr, dxpl_id, (depth - 1), &internal_flags, &internal->node_ptrs[idx], udata) < 0)
+ if(H5B2_insert_internal(hdr, dxpl_id, (depth - 1), &internal_flags, &internal->node_ptrs[idx], internal, 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, &internal->node_ptrs[idx], udata) < 0)
+ if(H5B2_insert_leaf(hdr, dxpl_id, &internal->node_ptrs[idx], internal, udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into B-tree leaf node")
} /* end else */
@@ -1731,7 +2649,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5B2_create_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *node_ptr)
+H5B2_create_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, void *parent, H5B2_node_ptr_t *node_ptr)
{
H5B2_leaf_t *leaf = NULL; /* Pointer to new leaf node created */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1766,6 +2684,12 @@ HDmemset(leaf->leaf_native, 0, hdr->cls->nrec_size * hdr->node_info[0].max_nrec)
/* Set number of records */
leaf->nrec = 0;
+ /* Set parent */
+ leaf->parent = parent;
+
+ /* Set shadowed list next pointer */
+ leaf->shadowed_next = NULL;
+
/* Allocate space on disk for the leaf */
if(HADDR_UNDEF == (node_ptr->addr = H5MF_alloc(hdr->f, H5FD_MEM_BTREE, dxpl_id, (hsize_t)hdr->node_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for B-tree leaf node")
@@ -1799,8 +2723,8 @@ done:
*-------------------------------------------------------------------------
*/
H5B2_leaf_t *
-H5B2_protect_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, haddr_t addr, unsigned nrec,
- H5AC_protect_t rw)
+H5B2_protect_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, haddr_t addr, void *parent,
+ unsigned nrec, H5AC_protect_t rw)
{
H5B2_leaf_cache_ud_t udata; /* User-data for callback */
H5B2_leaf_t *ret_value; /* Return value */
@@ -1814,6 +2738,7 @@ H5B2_protect_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, haddr_t addr, unsigned nrec,
/* Set up user data for callback */
udata.f = hdr->f;
udata.hdr = hdr;
+ udata.parent = parent;
H5_ASSIGN_OVERFLOW(/* To: */ udata.nrec, /* From: */ nrec, /* From: */ unsigned, /* To: */ uint16_t)
/* Protect the leaf node */
@@ -1840,8 +2765,8 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5B2_create_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *node_ptr,
- unsigned depth)
+H5B2_create_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, void *parent,
+ H5B2_node_ptr_t *node_ptr, unsigned depth)
{
H5B2_internal_t *internal = NULL; /* Pointer to new internal node created */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1885,6 +2810,12 @@ HDmemset(internal->node_ptrs, 0, sizeof(H5B2_node_ptr_t) * (hdr->node_info[depth
internal->nrec = 0;
internal->depth = (uint16_t)depth;
+ /* Set parent */
+ internal->parent = parent;
+
+ /* Set shadowed list next pointer */
+ internal->shadowed_next = NULL;
+
/* Allocate space on disk for the internal node */
if(HADDR_UNDEF == (node_ptr->addr = H5MF_alloc(hdr->f, H5FD_MEM_BTREE, dxpl_id, (hsize_t)hdr->node_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for B-tree internal node")
@@ -1919,7 +2850,7 @@ done:
*/
H5B2_internal_t *
H5B2_protect_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, haddr_t addr,
- unsigned nrec, unsigned depth, H5AC_protect_t rw)
+ void *parent, unsigned nrec, unsigned depth, H5AC_protect_t rw)
{
H5B2_internal_cache_ud_t udata; /* User data to pass through to cache 'deserialize' callback */
H5B2_internal_t *ret_value; /* Return value */
@@ -1934,6 +2865,7 @@ H5B2_protect_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, haddr_t addr,
/* Set up user data for callback */
udata.f = hdr->f;
udata.hdr = hdr;
+ udata.parent = parent;
H5_ASSIGN_OVERFLOW(/* To: */ udata.nrec, /* From: */ nrec, /* From: */ unsigned, /* To: */ uint16_t)
H5_ASSIGN_OVERFLOW(/* To: */ udata.depth, /* From: */ depth, /* From: */ unsigned, /* To: */ uint16_t)
@@ -1965,13 +2897,15 @@ done:
*/
herr_t
H5B2_iterate_node(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
- const H5B2_node_ptr_t *curr_node, H5B2_operator_t op, void *op_data)
+ const H5B2_node_ptr_t *curr_node, void *parent, H5B2_operator_t op,
+ void *op_data)
{
const H5AC_class_t *curr_node_class = NULL; /* Pointer to current node's class info */
void *node = NULL; /* Pointers to current node */
uint8_t *node_native; /* Pointers to node's native records */
uint8_t *native = NULL; /* Pointers to copy of node's native records */
H5B2_node_ptr_t *node_ptrs = NULL; /* Pointers to node's node pointers */
+ hbool_t node_pinned = FALSE; /* Whether node is pinned */
unsigned u; /* Local index */
herr_t ret_value = H5_ITER_CONT; /* Iterator return value */
@@ -1987,7 +2921,7 @@ H5B2_iterate_node(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
H5B2_internal_t *internal; /* Pointer to internal node */
/* Lock the current B-tree node */
- if(NULL == (internal = H5B2_protect_internal(hdr, dxpl_id, curr_node->addr, curr_node->node_nrec, depth, H5AC_READ)))
+ if(NULL == (internal = H5B2_protect_internal(hdr, dxpl_id, curr_node->addr, parent, curr_node->node_nrec, depth, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
/* Set up information about current node */
@@ -2006,7 +2940,7 @@ H5B2_iterate_node(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
H5B2_leaf_t *leaf; /* Pointer to leaf node */
/* Lock the current B-tree node */
- if(NULL == (leaf = H5B2_protect_leaf(hdr, dxpl_id, curr_node->addr, curr_node->node_nrec, H5AC_READ)))
+ if(NULL == (leaf = H5B2_protect_leaf(hdr, dxpl_id, curr_node->addr, parent, curr_node->node_nrec, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
/* Set up information about current node */
@@ -2023,15 +2957,18 @@ H5B2_iterate_node(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
HDmemcpy(native, node_native, (hdr->cls->nrec_size * curr_node->node_nrec));
/* Unlock the node */
- if(H5AC_unprotect(hdr->f, dxpl_id, curr_node_class, curr_node->addr, node, H5AC__NO_FLAGS_SET) < 0)
+ if(H5AC_unprotect(hdr->f, dxpl_id, curr_node_class, curr_node->addr, node, hdr->swmr_write ? H5AC__PIN_ENTRY_FLAG : H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
- node = NULL;
+ if(hdr->swmr_write)
+ node_pinned = TRUE;
+ else
+ node = NULL;
/* Iterate through records, in order */
for(u = 0; u < curr_node->node_nrec && !ret_value; u++) {
/* Descend into child node, if current node is an internal node */
if(depth > 0) {
- if((ret_value = H5B2_iterate_node(hdr, dxpl_id, (depth - 1), &(node_ptrs[u]), op, op_data)) < 0)
+ if((ret_value = H5B2_iterate_node(hdr, dxpl_id, (depth - 1), &(node_ptrs[u]), node, op, op_data)) < 0)
HERROR(H5E_BTREE, H5E_CANTLIST, "node iteration failed");
} /* end if */
@@ -2044,11 +2981,15 @@ H5B2_iterate_node(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
/* Descend into last child node, if current node is an internal node */
if(!ret_value && depth > 0) {
- if((ret_value = H5B2_iterate_node(hdr, dxpl_id, (depth - 1), &(node_ptrs[u]), op, op_data)) < 0)
+ if((ret_value = H5B2_iterate_node(hdr, dxpl_id, (depth - 1), &(node_ptrs[u]), node, op, op_data)) < 0)
HERROR(H5E_BTREE, H5E_CANTLIST, "node iteration failed");
} /* end if */
done:
+ /* Unpin the node if it was pinned */
+ if(node_pinned && H5AC_unpin_entry(node) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "can't unpin node")
+
/* Release the node pointers & native records, if they were copied */
if(node_ptrs)
node_ptrs = (H5B2_node_ptr_t *)H5FL_FAC_FREE(hdr->node_info[depth].node_ptr_fac, node_ptrs);
@@ -2074,7 +3015,7 @@ done:
*/
herr_t
H5B2_remove_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *curr_node_ptr,
- void *udata, H5B2_remove_t op, void *op_data)
+ void *parent, void *udata, H5B2_remove_t op, void *op_data)
{
H5B2_leaf_t *leaf; /* Pointer to leaf node */
haddr_t leaf_addr = HADDR_UNDEF; /* Leaf address on disk */
@@ -2091,7 +3032,7 @@ H5B2_remove_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *curr_node_ptr,
/* Lock current B-tree node */
leaf_addr = curr_node_ptr->addr;
- if(NULL == (leaf = H5B2_protect_leaf(hdr, dxpl_id, leaf_addr, curr_node_ptr->node_nrec, H5AC_WRITE)))
+ if(NULL == (leaf = H5B2_protect_leaf(hdr, dxpl_id, leaf_addr, parent, curr_node_ptr->node_nrec, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
/* Sanity check number of records */
@@ -2110,17 +3051,26 @@ H5B2_remove_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *curr_node_ptr,
/* Update number of records in node */
leaf->nrec--;
- /* Mark leaf node as dirty also */
- leaf_flags |= H5AC__DIRTIED_FLAG;
-
if(leaf->nrec > 0) {
+ /* Shadow the node if doing SWMR writes */
+ if(hdr->swmr_write) {
+ if(H5B2_shadow_leaf(hdr, dxpl_id, curr_node_ptr, &leaf) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow leaf node")
+ leaf_addr = curr_node_ptr->addr;
+ } /* end if */
+
/* Pack record out of leaf */
if(idx < leaf->nrec)
HDmemmove(H5B2_LEAF_NREC(leaf, hdr, idx), H5B2_LEAF_NREC(leaf, hdr, (idx + 1)), hdr->cls->nrec_size * (leaf->nrec - idx));
+
+ /* Mark leaf node as dirty also */
+ leaf_flags |= H5AC__DIRTIED_FLAG;
} /* end if */
else {
/* Let the cache know that the object is deleted */
- leaf_flags |= H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
+ leaf_flags |= H5AC__DELETED_FLAG;
+ if(!hdr->swmr_write)
+ leaf_flags |= H5AC__DIRTIED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
/* Reset address of parent node pointer */
curr_node_ptr->addr = HADDR_UNDEF;
@@ -2153,7 +3103,7 @@ done:
*/
herr_t
H5B2_remove_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, hbool_t *depth_decreased,
- void *swap_loc, unsigned depth, H5AC_info_t *parent_cache_info,
+ void *swap_loc, void *swap_parent, unsigned depth, H5AC_info_t *parent_cache_info,
unsigned *parent_cache_info_flags_ptr, H5B2_node_ptr_t *curr_node_ptr,
void *udata, H5B2_remove_t op, void *op_data)
{
@@ -2161,6 +3111,8 @@ H5B2_remove_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, hbool_t *depth_decreased,
unsigned *new_cache_info_flags_ptr = NULL;
H5B2_node_ptr_t *new_node_ptr; /* Pointer to new node pointer */
H5B2_internal_t *internal; /* Pointer to internal node */
+ const H5AC_class_t *new_root_class; /* Pointer to new root node's class info */
+ void *new_root = NULL; /* Pointer to new root node (if old root collapsed) */
unsigned internal_flags = H5AC__NO_FLAGS_SET;
haddr_t internal_addr; /* Address of internal node */
size_t merge_nrec; /* Number of records to merge node at */
@@ -2178,7 +3130,7 @@ H5B2_remove_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, hbool_t *depth_decreased,
/* Lock current B-tree node */
internal_addr = curr_node_ptr->addr;
- if(NULL == (internal = H5B2_protect_internal(hdr, dxpl_id, internal_addr, curr_node_ptr->node_nrec, depth, H5AC_WRITE)))
+ if(NULL == (internal = H5B2_protect_internal(hdr, dxpl_id, internal_addr, parent_cache_info, curr_node_ptr->node_nrec, depth, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
/* Determine the correct number of records to merge at */
@@ -2191,16 +3143,71 @@ H5B2_remove_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, hbool_t *depth_decreased,
/* Merge children of root node */
if(H5B2_merge2(hdr, dxpl_id, depth, curr_node_ptr,
- parent_cache_info_flags_ptr, internal, &internal_flags, 0) < 0)
+ parent_cache_info_flags_ptr, internal, &internal_flags, 0,
+ udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node")
/* Let the cache know that the object is deleted */
- internal_flags |= H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
+ internal_flags |= H5AC__DELETED_FLAG;
+ if(!hdr->swmr_write)
+ internal_flags |= H5AC__FREE_FILE_SPACE_FLAG;
/* Reset information in header's root node pointer */
curr_node_ptr->addr = internal->node_ptrs[0].addr;
curr_node_ptr->node_nrec = internal->node_ptrs[0].node_nrec;
+ /* Update flush dependencies */
+ if(hdr->swmr_write) {
+ hbool_t update_dep = FALSE; /* Whether to update root flush dependency */
+
+ /* Update hdr to root dependency */
+ if(depth > 1) {
+ H5B2_internal_t *new_root_int = NULL;
+
+ /* Protect new root */
+ if(NULL == (new_root_int = H5B2_protect_internal(hdr, dxpl_id, curr_node_ptr->addr, hdr, curr_node_ptr->node_nrec, (depth - 1), H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
+ new_root_class = H5AC_BT2_INT;
+ new_root = new_root_int;
+
+ if(new_root_int->parent == internal) {
+ new_root_int->parent = hdr;
+ update_dep = TRUE;
+ } /* end if */
+ else
+ HDassert(new_root_int->parent == hdr);
+ } /* end if */
+ else {
+ H5B2_leaf_t *new_root_leaf = NULL;
+
+ /* Protect new root */
+ if(NULL == (new_root_leaf = H5B2_protect_leaf(hdr, dxpl_id, curr_node_ptr->addr, hdr, curr_node_ptr->node_nrec, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
+ new_root_class = H5AC_BT2_LEAF;
+ new_root = new_root_leaf;
+
+ if(new_root_leaf->parent == internal) {
+ new_root_leaf->parent = hdr;
+ update_dep = TRUE;
+ } /* end if */
+ else
+ HDassert(new_root_leaf->parent == hdr);
+ } /* end else */
+
+ /* Update flush dependency if necessary */
+ if(update_dep) {
+ if(H5AC_destroy_flush_dependency(internal, new_root) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency")
+ if(H5AC_create_flush_dependency(hdr, new_root) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
+ } /* end if */
+
+ /* Unprotect the new root */
+ if(H5AC_unprotect(hdr->f, dxpl_id, new_root_class, curr_node_ptr->addr, new_root, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ new_root = NULL;
+ } /* end if */
+
/* Indicate that the level of the B-tree decreased */
*depth_decreased = TRUE;
@@ -2218,6 +3225,13 @@ H5B2_remove_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, hbool_t *depth_decreased,
int cmp = 0; /* Comparison value of records */
unsigned retries; /* Number of times to attempt redistribution */
+ /* Shadow the node if doing SWMR writes */
+ if(hdr->swmr_write) {
+ if(H5B2_shadow_internal(hdr, dxpl_id, depth, curr_node_ptr, &internal) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow internal node")
+ internal_addr = curr_node_ptr->addr;
+ } /* end if */
+
/* Locate node pointer for child */
if(swap_loc)
idx = 0;
@@ -2246,35 +3260,38 @@ H5B2_remove_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, hbool_t *depth_decreased,
*/
if(idx == 0) { /* Left-most child */
if(retries > 0 && (internal->node_ptrs[idx + 1].node_nrec > merge_nrec)) {
- if(H5B2_redistribute2(hdr, dxpl_id, depth, internal, idx) < 0)
+ if(H5B2_redistribute2(hdr, dxpl_id, depth, internal, idx, udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
} /* end if */
else {
if(H5B2_merge2(hdr, dxpl_id, depth, curr_node_ptr,
- parent_cache_info_flags_ptr, internal, &internal_flags, idx) < 0)
+ parent_cache_info_flags_ptr, internal,
+ &internal_flags, idx, udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node")
} /* end else */
} /* end if */
else if(idx == internal->nrec) { /* Right-most child */
if(retries > 0 && (internal->node_ptrs[idx - 1].node_nrec > merge_nrec)) {
- if(H5B2_redistribute2(hdr, dxpl_id, depth, internal, (idx - 1)) < 0)
+ if(H5B2_redistribute2(hdr, dxpl_id, depth, internal, (idx - 1), udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
} /* end if */
else {
if(H5B2_merge2(hdr, dxpl_id, depth, curr_node_ptr,
- parent_cache_info_flags_ptr, internal, &internal_flags, (idx - 1)) < 0)
+ parent_cache_info_flags_ptr, internal,
+ &internal_flags, (idx - 1), udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node")
} /* end else */
} /* end if */
else { /* Middle child */
if(retries > 0 && ((internal->node_ptrs[idx + 1].node_nrec > merge_nrec) ||
(internal->node_ptrs[idx - 1].node_nrec > merge_nrec))) {
- if(H5B2_redistribute3(hdr, dxpl_id, depth, internal, &internal_flags, idx) < 0)
+ if(H5B2_redistribute3(hdr, dxpl_id, depth, internal, &internal_flags, idx, udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
} /* end if */
else {
if(H5B2_merge3(hdr, dxpl_id, depth, curr_node_ptr,
- parent_cache_info_flags_ptr, internal, &internal_flags, idx) < 0)
+ parent_cache_info_flags_ptr, internal,
+ &internal_flags, idx, udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node")
} /* end else */
} /* end else */
@@ -2294,12 +3311,14 @@ H5B2_remove_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, hbool_t *depth_decreased,
} /* end while */
/* Handle deleting a record from an internal node */
- if(!swap_loc && cmp == 0)
+ if(!swap_loc && cmp == 0) {
swap_loc = H5B2_INT_NREC(internal, hdr, idx - 1);
+ swap_parent = internal;
+ }
/* Swap record to delete with record from leaf, if we are the last internal node */
if(swap_loc && depth == 1)
- if(H5B2_swap_leaf(hdr, dxpl_id, depth, internal, &internal_flags, idx, swap_loc) < 0)
+ if(H5B2_swap_leaf(hdr, dxpl_id, depth, internal, &internal_flags, idx, swap_loc, swap_parent, udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTSWAP, FAIL, "Can't swap records in B-tree")
/* Set pointers for advancing to child node */
@@ -2310,12 +3329,12 @@ H5B2_remove_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, hbool_t *depth_decreased,
/* Attempt to remove record from child node */
if(depth > 1) {
- if(H5B2_remove_internal(hdr, dxpl_id, depth_decreased, swap_loc, depth - 1,
+ if(H5B2_remove_internal(hdr, dxpl_id, depth_decreased, swap_loc, swap_parent, depth - 1,
new_cache_info, new_cache_info_flags_ptr, new_node_ptr, udata, op, op_data) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record from B-tree internal node")
} /* end if */
else {
- if(H5B2_remove_leaf(hdr, dxpl_id, new_node_ptr, udata, op, op_data) < 0)
+ if(H5B2_remove_leaf(hdr, dxpl_id, new_node_ptr, new_cache_info, udata, op, op_data) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record from B-tree leaf node")
} /* end else */
@@ -2324,7 +3343,8 @@ H5B2_remove_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, hbool_t *depth_decreased,
new_node_ptr->all_nrec--;
/* Mark node as dirty */
- internal_flags |= H5AC__DIRTIED_FLAG;
+ if(!(hdr->swmr_write && collapsed_root))
+ internal_flags |= H5AC__DIRTIED_FLAG;
#ifdef H5B2_DEBUG
H5B2_assert_internal((!collapsed_root ? (curr_node_ptr->all_nrec - 1) : new_node_ptr->all_nrec), hdr, internal);
@@ -2335,6 +3355,13 @@ done:
if(internal && H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_INT, internal_addr, internal, internal_flags) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release internal B-tree node")
+ /* Release the new root's child on error */
+ if(new_root) {
+ HDassert(ret_value < 0);
+ if(H5AC_unprotect(hdr->f, dxpl_id, new_root_class, curr_node_ptr->addr, new_root, H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ } /* end if */
+
FUNC_LEAVE_NOAPI(ret_value)
} /* H5B2_remove_internal() */
@@ -2355,8 +3382,8 @@ done:
*/
herr_t
H5B2_remove_leaf_by_idx(H5B2_hdr_t *hdr, hid_t dxpl_id,
- H5B2_node_ptr_t *curr_node_ptr, unsigned idx, H5B2_remove_t op,
- void *op_data)
+ H5B2_node_ptr_t *curr_node_ptr, void *parent, unsigned idx,
+ H5B2_remove_t op, void *op_data)
{
H5B2_leaf_t *leaf; /* Pointer to leaf node */
haddr_t leaf_addr = HADDR_UNDEF; /* Leaf address on disk */
@@ -2372,7 +3399,7 @@ H5B2_remove_leaf_by_idx(H5B2_hdr_t *hdr, hid_t dxpl_id,
/* Lock B-tree leaf node */
leaf_addr = curr_node_ptr->addr;
- if(NULL == (leaf = H5B2_protect_leaf(hdr, dxpl_id, leaf_addr, curr_node_ptr->node_nrec, H5AC_WRITE)))
+ if(NULL == (leaf = H5B2_protect_leaf(hdr, dxpl_id, leaf_addr, parent, curr_node_ptr->node_nrec, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
/* Sanity check number of records */
@@ -2388,17 +3415,26 @@ H5B2_remove_leaf_by_idx(H5B2_hdr_t *hdr, hid_t dxpl_id,
/* Update number of records in node */
leaf->nrec--;
- /* Mark leaf node as dirty also */
- leaf_flags |= H5AC__DIRTIED_FLAG;
-
if(leaf->nrec > 0) {
+ /* Shadow the node if doing SWMR writes */
+ if(hdr->swmr_write) {
+ if(H5B2_shadow_leaf(hdr, dxpl_id, curr_node_ptr, &leaf) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow leaf node")
+ leaf_addr = curr_node_ptr->addr;
+ } /* end if */
+
/* Pack record out of leaf */
if(idx < leaf->nrec)
HDmemmove(H5B2_LEAF_NREC(leaf, hdr, idx), H5B2_LEAF_NREC(leaf, hdr, (idx + 1)), hdr->cls->nrec_size * (leaf->nrec - idx));
+
+ /* Mark leaf node as dirty also */
+ leaf_flags |= H5AC__DIRTIED_FLAG;
} /* end if */
else {
/* Let the cache know that the object is deleted */
- leaf_flags |= H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
+ leaf_flags |= H5AC__DELETED_FLAG;
+ if(!hdr->swmr_write)
+ leaf_flags |= H5AC__DIRTIED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
/* Reset address of parent node pointer */
curr_node_ptr->addr = HADDR_UNDEF;
@@ -2432,14 +3468,16 @@ done:
*/
herr_t
H5B2_remove_internal_by_idx(H5B2_hdr_t *hdr, hid_t dxpl_id,
- hbool_t *depth_decreased, void *swap_loc, unsigned depth,
+ hbool_t *depth_decreased, void *swap_loc, void *swap_parent, unsigned depth,
H5AC_info_t *parent_cache_info, unsigned *parent_cache_info_flags_ptr,
- H5B2_node_ptr_t *curr_node_ptr, hsize_t n, H5B2_remove_t op,
+ H5B2_node_ptr_t *curr_node_ptr, hsize_t n, void *udata, H5B2_remove_t op,
void *op_data)
{
H5AC_info_t *new_cache_info; /* Pointer to new cache info */
unsigned *new_cache_info_flags_ptr = NULL;
H5B2_node_ptr_t *new_node_ptr; /* Pointer to new node pointer */
+ const H5AC_class_t *new_root_class; /* Pointer to new root node's class info */
+ void *new_root = NULL; /* Pointer to new root node (if old root collapsed) */
H5B2_internal_t *internal; /* Pointer to internal node */
unsigned internal_flags = H5AC__NO_FLAGS_SET;
haddr_t internal_addr; /* Address of internal node */
@@ -2458,7 +3496,7 @@ H5B2_remove_internal_by_idx(H5B2_hdr_t *hdr, hid_t dxpl_id,
/* Lock current B-tree node */
internal_addr = curr_node_ptr->addr;
- if(NULL == (internal = H5B2_protect_internal(hdr, dxpl_id, internal_addr, curr_node_ptr->node_nrec, depth, H5AC_WRITE)))
+ if(NULL == (internal = H5B2_protect_internal(hdr, dxpl_id, internal_addr, parent_cache_info, curr_node_ptr->node_nrec, depth, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
HDassert(internal->nrec == curr_node_ptr->node_nrec);
HDassert(depth == hdr->depth || internal->nrec > 1);
@@ -2474,16 +3512,71 @@ H5B2_remove_internal_by_idx(H5B2_hdr_t *hdr, hid_t dxpl_id,
/* Merge children of root node */
if(H5B2_merge2(hdr, dxpl_id, depth, curr_node_ptr,
- parent_cache_info_flags_ptr, internal, &internal_flags, 0) < 0)
+ parent_cache_info_flags_ptr, internal, &internal_flags, 0,
+ udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node")
/* Let the cache know that the object is deleted */
- internal_flags |= H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
+ internal_flags |= H5AC__DELETED_FLAG;
+ if(!hdr->swmr_write)
+ internal_flags |= H5AC__FREE_FILE_SPACE_FLAG;
/* Reset information in header's root node pointer */
curr_node_ptr->addr = internal->node_ptrs[0].addr;
curr_node_ptr->node_nrec = internal->node_ptrs[0].node_nrec;
+ /* Update flush dependencies */
+ if(hdr->swmr_write) {
+ hbool_t update_dep = FALSE; /* Whether to update root flush dependency */
+
+ /* Update hdr to root dependency */
+ if(depth > 1) {
+ H5B2_internal_t *new_root_int = NULL;
+
+ /* Protect new root */
+ if(NULL == (new_root_int = H5B2_protect_internal(hdr, dxpl_id, curr_node_ptr->addr, hdr, curr_node_ptr->node_nrec, (depth - 1), H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
+ new_root_class = H5AC_BT2_INT;
+ new_root = new_root_int;
+
+ if(new_root_int->parent == internal) {
+ new_root_int->parent = hdr;
+ update_dep = TRUE;
+ } /* end if */
+ else
+ HDassert(new_root_int->parent == hdr);
+ } /* end if */
+ else {
+ H5B2_leaf_t *new_root_leaf = NULL;
+
+ /* Protect new root */
+ if(NULL == (new_root_leaf = H5B2_protect_leaf(hdr, dxpl_id, curr_node_ptr->addr, hdr, curr_node_ptr->node_nrec, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
+ new_root_class = H5AC_BT2_LEAF;
+ new_root = new_root_leaf;
+
+ if(new_root_leaf->parent == internal) {
+ new_root_leaf->parent = hdr;
+ update_dep = TRUE;
+ } /* end if */
+ else
+ HDassert(new_root_leaf->parent == hdr);
+ } /* end else */
+
+ /* Update flush dependency if necessary */
+ if(update_dep) {
+ if(H5AC_destroy_flush_dependency(internal, new_root) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency")
+ if(H5AC_create_flush_dependency(hdr, new_root) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
+ } /* end if */
+
+ /* Unprotect the new root */
+ if(H5AC_unprotect(hdr->f, dxpl_id, new_root_class, curr_node_ptr->addr, new_root, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ new_root = NULL;
+ } /* end if */
+
/* Indicate that the level of the B-tree decreased */
*depth_decreased = TRUE;
@@ -2502,6 +3595,13 @@ H5B2_remove_internal_by_idx(H5B2_hdr_t *hdr, hid_t dxpl_id,
hbool_t found = FALSE; /* Comparison value of records */
unsigned retries; /* Number of times to attempt redistribution */
+ /* Shadow the node if doing SWMR writes */
+ if(hdr->swmr_write && !collapsed_root) {
+ if(H5B2_shadow_internal(hdr, dxpl_id, depth, curr_node_ptr, &internal) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow internal node")
+ internal_addr = curr_node_ptr->addr;
+ } /* end if */
+
/* Locate node pointer for child */
if(swap_loc)
idx = 0;
@@ -2552,35 +3652,38 @@ H5B2_remove_internal_by_idx(H5B2_hdr_t *hdr, hid_t dxpl_id,
*/
if(idx == 0) { /* Left-most child */
if(retries > 0 && (internal->node_ptrs[idx + 1].node_nrec > merge_nrec)) {
- if(H5B2_redistribute2(hdr, dxpl_id, depth, internal, idx) < 0)
+ if(H5B2_redistribute2(hdr, dxpl_id, depth, internal, idx, udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
} /* end if */
else {
if(H5B2_merge2(hdr, dxpl_id, depth, curr_node_ptr,
- parent_cache_info_flags_ptr, internal, &internal_flags, idx) < 0)
+ parent_cache_info_flags_ptr, internal,
+ &internal_flags, idx, udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node")
} /* end else */
} /* end if */
else if(idx == internal->nrec) { /* Right-most child */
if(retries > 0 && (internal->node_ptrs[idx - 1].node_nrec > merge_nrec)) {
- if(H5B2_redistribute2(hdr, dxpl_id, depth, internal, (idx - 1)) < 0)
+ if(H5B2_redistribute2(hdr, dxpl_id, depth, internal, (idx - 1), udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
} /* end if */
else {
if(H5B2_merge2(hdr, dxpl_id, depth, curr_node_ptr,
- parent_cache_info_flags_ptr, internal, &internal_flags, (idx - 1)) < 0)
+ parent_cache_info_flags_ptr, internal,
+ &internal_flags, (idx - 1), udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node")
} /* end else */
} /* end if */
else { /* Middle child */
if(retries > 0 && ((internal->node_ptrs[idx + 1].node_nrec > merge_nrec) ||
(internal->node_ptrs[idx - 1].node_nrec > merge_nrec))) {
- if(H5B2_redistribute3(hdr, dxpl_id, depth, internal, &internal_flags, idx) < 0)
+ if(H5B2_redistribute3(hdr, dxpl_id, depth, internal, &internal_flags, idx, udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTREDISTRIBUTE, FAIL, "unable to redistribute child node records")
} /* end if */
else {
if(H5B2_merge3(hdr, dxpl_id, depth, curr_node_ptr,
- parent_cache_info_flags_ptr, internal, &internal_flags, idx) < 0)
+ parent_cache_info_flags_ptr, internal,
+ &internal_flags, idx, udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node")
} /* end else */
} /* end else */
@@ -2629,12 +3732,14 @@ H5B2_remove_internal_by_idx(H5B2_hdr_t *hdr, hid_t dxpl_id,
} /* end while */
/* Handle deleting a record from an internal node */
- if(!swap_loc && found)
+ if(!swap_loc && found) {
swap_loc = H5B2_INT_NREC(internal, hdr, idx - 1);
+ swap_parent = internal;
+ }
/* Swap record to delete with record from leaf, if we are the last internal node */
if(swap_loc && depth == 1)
- if(H5B2_swap_leaf(hdr, dxpl_id, depth, internal, &internal_flags, idx, swap_loc) < 0)
+ if(H5B2_swap_leaf(hdr, dxpl_id, depth, internal, &internal_flags, idx, swap_loc, swap_parent, udata) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTSWAP, FAIL, "can't swap records in B-tree")
/* Set pointers for advancing to child node */
@@ -2645,12 +3750,12 @@ H5B2_remove_internal_by_idx(H5B2_hdr_t *hdr, hid_t dxpl_id,
/* Attempt to remove record from child node */
if(depth > 1) {
- if(H5B2_remove_internal_by_idx(hdr, dxpl_id, depth_decreased, swap_loc, depth - 1,
- new_cache_info, new_cache_info_flags_ptr, new_node_ptr, n, op, op_data) < 0)
+ if(H5B2_remove_internal_by_idx(hdr, dxpl_id, depth_decreased, swap_loc, swap_parent, depth - 1,
+ new_cache_info, new_cache_info_flags_ptr, new_node_ptr, n, udata, op, op_data) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record from B-tree internal node")
} /* end if */
else {
- if(H5B2_remove_leaf_by_idx(hdr, dxpl_id, new_node_ptr, (unsigned)n, op, op_data) < 0)
+ if(H5B2_remove_leaf_by_idx(hdr, dxpl_id, new_node_ptr, new_cache_info, (unsigned)n, op, op_data) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record from B-tree leaf node")
} /* end else */
@@ -2659,7 +3764,8 @@ H5B2_remove_internal_by_idx(H5B2_hdr_t *hdr, hid_t dxpl_id,
new_node_ptr->all_nrec--;
/* Mark node as dirty */
- internal_flags |= H5AC__DIRTIED_FLAG;
+ if(!(hdr->swmr_write && collapsed_root))
+ internal_flags |= H5AC__DIRTIED_FLAG;
#ifdef H5B2_DEBUG
H5B2_assert_internal((!collapsed_root ? (curr_node_ptr->all_nrec - 1) : new_node_ptr->all_nrec), hdr, internal);
@@ -2670,6 +3776,13 @@ done:
if(internal && H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_INT, internal_addr, internal, internal_flags) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release internal B-tree node")
+ /* Release the new root's child on error */
+ if(new_root) {
+ HDassert(ret_value < 0);
+ if(H5AC_unprotect(hdr->f, dxpl_id, new_root_class, curr_node_ptr->addr, new_root, H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ } /* end if */
+
FUNC_LEAVE_NOAPI(ret_value)
} /* H5B2_remove_internal_by_idx() */
@@ -2702,7 +3815,7 @@ done:
*/
herr_t
H5B2_neighbor_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *curr_node_ptr,
- void *neighbor_loc, H5B2_compare_t comp, void *udata, H5B2_found_t op,
+ void *neighbor_loc, H5B2_compare_t comp, void *parent, void *udata, H5B2_found_t op,
void *op_data)
{
H5B2_leaf_t *leaf; /* Pointer to leaf node */
@@ -2719,7 +3832,7 @@ H5B2_neighbor_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *curr_node_pt
HDassert(op);
/* Lock current B-tree node */
- if(NULL == (leaf = H5B2_protect_leaf(hdr, dxpl_id, curr_node_ptr->addr, curr_node_ptr->node_nrec, H5AC_READ)))
+ if(NULL == (leaf = H5B2_protect_leaf(hdr, dxpl_id, curr_node_ptr->addr, parent, curr_node_ptr->node_nrec, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
/* Locate node pointer for child */
@@ -2789,7 +3902,7 @@ done:
herr_t
H5B2_neighbor_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
H5B2_node_ptr_t *curr_node_ptr, void *neighbor_loc, H5B2_compare_t comp,
- void *udata, H5B2_found_t op, void *op_data)
+ void *parent, void *udata, H5B2_found_t op, void *op_data)
{
H5B2_internal_t *internal; /* Pointer to internal node */
unsigned idx; /* Location of record which matches key */
@@ -2806,7 +3919,7 @@ H5B2_neighbor_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
HDassert(op);
/* 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_READ)))
+ if(NULL == (internal = H5B2_protect_internal(hdr, dxpl_id, curr_node_ptr->addr, parent, curr_node_ptr->node_nrec, depth, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
/* Locate node pointer for child */
@@ -2828,11 +3941,11 @@ H5B2_neighbor_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
/* Attempt to find neighboring record */
if(depth > 1) {
- if(H5B2_neighbor_internal(hdr, dxpl_id, depth - 1, &internal->node_ptrs[idx], neighbor_loc, comp, udata, op, op_data) < 0)
+ if(H5B2_neighbor_internal(hdr, dxpl_id, depth - 1, &internal->node_ptrs[idx], neighbor_loc, comp, internal, udata, op, op_data) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "unable to find neighbor record in B-tree internal node")
} /* end if */
else {
- if(H5B2_neighbor_leaf(hdr, dxpl_id, &internal->node_ptrs[idx], neighbor_loc, comp, udata, op, op_data) < 0)
+ if(H5B2_neighbor_leaf(hdr, dxpl_id, &internal->node_ptrs[idx], neighbor_loc, comp, internal, udata, op, op_data) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "unable to find neighbor record in B-tree leaf node")
} /* end else */
@@ -2861,7 +3974,8 @@ done:
*/
herr_t
H5B2_delete_node(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
- const H5B2_node_ptr_t *curr_node, H5B2_remove_t op, void *op_data)
+ const H5B2_node_ptr_t *curr_node, void *parent, H5B2_remove_t op,
+ void *op_data)
{
const H5AC_class_t *curr_node_class = NULL; /* Pointer to current node's class info */
void *node = NULL; /* Pointers to current node */
@@ -2879,7 +3993,7 @@ H5B2_delete_node(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
unsigned u; /* Local index */
/* Lock the current B-tree node */
- if(NULL == (internal = H5B2_protect_internal(hdr, dxpl_id, curr_node->addr, curr_node->node_nrec, depth, H5AC_WRITE)))
+ if(NULL == (internal = H5B2_protect_internal(hdr, dxpl_id, curr_node->addr, parent, curr_node->node_nrec, depth, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
/* Set up information about current node */
@@ -2889,14 +4003,14 @@ H5B2_delete_node(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
/* Descend into children */
for(u = 0; u < internal->nrec + (unsigned)1; u++)
- if(H5B2_delete_node(hdr, dxpl_id, (depth - 1), &(internal->node_ptrs[u]), op, op_data) < 0)
+ if(H5B2_delete_node(hdr, dxpl_id, (depth - 1), &(internal->node_ptrs[u]), internal, op, op_data) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "node descent failed")
} /* end if */
else {
H5B2_leaf_t *leaf; /* Pointer to leaf node */
/* Lock the current B-tree node */
- if(NULL == (leaf = H5B2_protect_leaf(hdr, dxpl_id, curr_node->addr, curr_node->node_nrec, H5AC_WRITE)))
+ if(NULL == (leaf = H5B2_protect_leaf(hdr, dxpl_id, curr_node->addr, parent, curr_node->node_nrec, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
/* Set up information about current node */
@@ -2919,7 +4033,7 @@ H5B2_delete_node(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
done:
/* Unlock & delete current node */
- if(node && H5AC_unprotect(hdr->f, dxpl_id, curr_node_class, curr_node->addr, node, H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
+ if(node && H5AC_unprotect(hdr->f, dxpl_id, curr_node_class, curr_node->addr, node, H5AC__DELETED_FLAG | (hdr->swmr_write ? 0 : H5AC__FREE_FILE_SPACE_FLAG)) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
FUNC_LEAVE_NOAPI(ret_value)
@@ -2941,7 +4055,7 @@ done:
*/
herr_t
H5B2_node_size(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
- const H5B2_node_ptr_t *curr_node, hsize_t *btree_size)
+ const H5B2_node_ptr_t *curr_node, void *parent, hsize_t *btree_size)
{
H5B2_internal_t *internal = NULL; /* Pointer to internal node */
herr_t ret_value = SUCCEED; /* Iterator return value */
@@ -2955,7 +4069,7 @@ H5B2_node_size(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
HDassert(depth > 0);
/* Lock the current B-tree node */
- if(NULL == (internal = H5B2_protect_internal(hdr, dxpl_id, curr_node->addr, curr_node->node_nrec, depth, H5AC_READ)))
+ if(NULL == (internal = H5B2_protect_internal(hdr, dxpl_id, curr_node->addr, parent, curr_node->node_nrec, depth, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
/* Recursively descend into child nodes, if we are above the "twig" level in the B-tree */
@@ -2964,7 +4078,7 @@ H5B2_node_size(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
/* Descend into children */
for(u = 0; u < internal->nrec + (unsigned)1; u++)
- if(H5B2_node_size(hdr, dxpl_id, (depth - 1), &(internal->node_ptrs[u]), btree_size) < 0)
+ if(H5B2_node_size(hdr, dxpl_id, (depth - 1), &(internal->node_ptrs[u]), internal, btree_size) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "node iteration failed")
} /* end if */
else /* depth is 1: count all the leaf nodes from this node */
@@ -3066,6 +4180,193 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5B2_leaf_free() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_shadow_internal
+ *
+ * Purpose: fnord
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * Apr 27 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_shadow_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
+ H5B2_node_ptr_t *curr_node_ptr, H5B2_internal_t **internal)
+{
+ hbool_t node_pinned = FALSE;
+ hbool_t node_protected = TRUE;
+ haddr_t new_node_addr; /* Address to move node to */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(depth > 0);
+ HDassert(curr_node_ptr);
+ HDassert(H5F_addr_defined(curr_node_ptr->addr));
+ HDassert(internal);
+ HDassert(*internal);
+ HDassert(hdr->swmr_write);
+
+ /* We only need to shadow the node if it has not been shadowed since the
+ * last time the header was flushed, as otherwise it will be unreachable by
+ * the readers so there will be no need to shadow. To check if it has been
+ * shadowed, check if it is on the shadowed node list. shadowed_next will
+ * be equal to internal if this node is at the head, so it can be used to
+ * determine if this node is in the list. */
+ if(!(*internal)->shadowed_next) {
+ /*
+ * We must clone the old node so readers with an out-of-date version of
+ * the parent can still see the correct number of children, via the
+ * shadowed node. Remove it from cache but do not mark it free on disk.
+ */
+ /* Allocate space for the cloned node */
+ if(HADDR_UNDEF == (new_node_addr = H5MF_alloc(hdr->f, H5FD_MEM_BTREE, dxpl_id, (hsize_t)hdr->node_size)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "unable to allocate file space to move B-tree node")
+
+ /* Pin old entry so it is not flushed when we unprotect */
+ if(H5AC_pin_protected_entry(*internal) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPIN, FAIL, "unable to pin old B-tree node")
+ node_pinned = TRUE;
+
+ /* Unprotect node so we can move it. Do not mark it dirty yet so it is
+ * not flushed to the old location (however unlikely). */
+ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_INT, curr_node_ptr->addr, *internal, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release old B-tree node")
+ node_protected = FALSE;
+
+ /* Move the location of the old child on the disk */
+ if(H5AC_move_entry(hdr->f, H5AC_BT2_INT, curr_node_ptr->addr, new_node_addr) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTMOVE, FAIL, "unable to move B-tree node")
+ curr_node_ptr->addr = new_node_addr;
+
+ /* Re-protect node at new address. Should have the same location in
+ * memory. */
+ if(*internal != H5B2_protect_internal(hdr, dxpl_id, curr_node_ptr->addr, (*internal)->parent, curr_node_ptr->node_nrec, depth, H5AC_WRITE))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
+ node_protected = TRUE;
+
+ /* Add node to shadowed node list */
+ if(hdr->shadowed_internal)
+ (*internal)->shadowed_next = hdr->shadowed_internal;
+ else
+ (*internal)->shadowed_next = *internal;
+ hdr->shadowed_internal = *internal;
+ } /* end if */
+
+done:
+ if(node_pinned)
+ if(H5AC_unpin_entry(*internal) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "unable to unpin internal B-tree node")
+
+ if(!node_protected) {
+ HDassert(ret_value < 0);
+ *internal = NULL;
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5B2_shadow_internal() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B2_shadow_leaf
+ *
+ * Purpose: fnord
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * Apr 27 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B2_shadow_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id,
+ H5B2_node_ptr_t *curr_node_ptr, H5B2_leaf_t **leaf)
+{
+ hbool_t node_pinned = FALSE;
+ hbool_t node_protected = TRUE;
+ haddr_t new_node_addr; /* Address to move node to */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(curr_node_ptr);
+ HDassert(H5F_addr_defined(curr_node_ptr->addr));
+ HDassert(leaf);
+ HDassert(*leaf);
+ HDassert(hdr->swmr_write);
+
+ /* We only need to shadow the node if it has not been shadowed since the
+ * last time the header was flushed, as otherwise it will be unreachable by
+ * the readers so there will be no need to shadow. To check if it has been
+ * shadowed, check if it is on the shadowed node list. shadowed_next will
+ * be equal to leaf if this node is at the head, so it can be used to
+ * determine if this node is in the list. */
+ if(!(*leaf)->shadowed_next) {
+ /*
+ * We must clone the old node so readers with an out-of-date version of
+ * the parent can still see the correct number of children, via the
+ * shadowed node. Remove it from cache but do not mark it free on disk.
+ */
+ /* Allocate space for the cloned node */
+ if(HADDR_UNDEF == (new_node_addr = H5MF_alloc(hdr->f, H5FD_MEM_BTREE, dxpl_id, (hsize_t)hdr->node_size)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "unable to allocate file space to move B-tree node")
+
+ /* Pin old entry so it is not flushed when we unprotect */
+ if(H5AC_pin_protected_entry(*leaf) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPIN, FAIL, "unable to pin old B-tree node")
+ node_pinned = TRUE;
+
+ /* Unprotect node so we can move it. Do not mark it dirty yet so it is
+ * not flushed to the old location (however unlikely). */
+ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr->addr, *leaf, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release old B-tree node")
+ node_protected = FALSE;
+
+ /* Move the location of the old child on the disk */
+ if(H5AC_move_entry(hdr->f, H5AC_BT2_LEAF, curr_node_ptr->addr, new_node_addr) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTMOVE, FAIL, "unable to move B-tree node")
+ curr_node_ptr->addr = new_node_addr;
+
+ /* Re-protect node at new address. Should have the same location in
+ * memory. */
+ if(*leaf != H5B2_protect_leaf(hdr, dxpl_id, curr_node_ptr->addr, (*leaf)->parent, curr_node_ptr->node_nrec, H5AC_WRITE))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
+ node_protected = TRUE;
+
+ /* Add node to shadowed node list */
+ if(hdr->shadowed_leaf)
+ (*leaf)->shadowed_next = hdr->shadowed_leaf;
+ else
+ (*leaf)->shadowed_next = *leaf;
+ hdr->shadowed_leaf = *leaf;
+ } /* end if */
+
+done:
+ if(node_pinned)
+ if(H5AC_unpin_entry(*leaf) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "unable to unpin leaf B-tree node")
+
+ if(!node_protected) {
+ HDassert(ret_value < 0);
+ *leaf = NULL;
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5B2_shadow_leaf() */
+
#ifdef H5B2_DEBUG
/*-------------------------------------------------------------------------
diff --git a/src/H5B2pkg.h b/src/H5B2pkg.h
index b820853..96ef54f 100644
--- a/src/H5B2pkg.h
+++ b/src/H5B2pkg.h
@@ -160,6 +160,7 @@ typedef struct H5B2_hdr_t {
/* Shared internal data structures (not stored) */
H5F_t *f; /* Pointer to the file that the B-tree is in */
+ void *parent; /* Flush dependency parent */
haddr_t addr; /* Address of B-tree header in the file */
size_t hdr_size; /* Size of the B-tree header on disk */
size_t rc; /* Reference count of nodes using this header */
@@ -172,6 +173,9 @@ typedef struct H5B2_hdr_t {
uint8_t *page; /* Common disk page for I/O */
size_t *nat_off; /* Array of offsets of native records */
H5B2_node_info_t *node_info; /* Table of node info structs for current depth of B-tree */
+ hbool_t swmr_write; /* Whether we are doing SWMR writes */
+ struct H5B2_leaf_t *shadowed_leaf; /* Linked list of shadowed leaf nodes */
+ struct H5B2_internal_t *shadowed_internal; /* Linked list of shadowed internal nodes */
/* Client information (not stored) */
const H5B2_class_t *cls; /* Class of B-tree client */
@@ -185,8 +189,10 @@ typedef struct H5B2_leaf_t {
/* Internal B-tree information */
H5B2_hdr_t *hdr; /* Pointer to the [pinned] v2 B-tree header */
+ void *parent; /* Flush dependency parent */
uint8_t *leaf_native; /* Pointer to native records */
uint16_t nrec; /* Number of records in node */
+ struct H5B2_leaf_t *shadowed_next; /* Next node in shadowed list */
} H5B2_leaf_t;
/* B-tree internal node information */
@@ -196,10 +202,12 @@ typedef struct H5B2_internal_t {
/* Internal B-tree information */
H5B2_hdr_t *hdr; /* Pointer to the [pinned] v2 B-tree header */
+ void *parent; /* Flush dependency parent */
uint8_t *int_native; /* Pointer to native records */
H5B2_node_ptr_t *node_ptrs; /* Pointer to node pointers */
uint16_t nrec; /* Number of records in node */
uint16_t depth; /* Depth of this node in the B-tree */
+ struct H5B2_internal_t *shadowed_next; /* Next node in shadowed list */
} H5B2_internal_t;
/* v2 B-tree */
@@ -211,6 +219,7 @@ struct H5B2_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 */
+ void *parent; /* Flush dependency parent */
void *ctx_udata; /* User-data for protecting */
} H5B2_hdr_cache_ud_t;
@@ -218,6 +227,7 @@ typedef struct H5B2_hdr_cache_ud_t {
typedef struct H5B2_internal_cache_ud_t {
H5F_t *f; /* File that v2 b-tree header is within */
H5B2_hdr_t *hdr; /* v2 B-tree header */
+ void *parent; /* Flush dependency parent */
unsigned nrec; /* Number of records in node to load */
unsigned depth; /* Depth of node to load */
} H5B2_internal_cache_ud_t;
@@ -226,6 +236,7 @@ typedef struct H5B2_internal_cache_ud_t {
typedef struct H5B2_leaf_cache_ud_t {
H5F_t *f; /* File that v2 b-tree header is within */
H5B2_hdr_t *hdr; /* v2 B-tree header */
+ void *parent; /* Flush dependency parent */
unsigned nrec; /* Number of records in node to load */
} H5B2_leaf_cache_ud_t;
@@ -273,9 +284,9 @@ extern const H5B2_class_t *const H5B2_client_class_g[H5B2_NUM_BTREE_ID];
/* Routines for managing B-tree header info */
H5_DLL H5B2_hdr_t *H5B2_hdr_alloc(H5F_t *f);
H5_DLL haddr_t H5B2_hdr_create(H5F_t *f, hid_t dxpl_id,
- const H5B2_create_t *cparam, void *ctx_udata);
+ const H5B2_create_t *cparam, void *ctx_udata, void *parent);
H5_DLL herr_t H5B2_hdr_init(H5B2_hdr_t *hdr, const H5B2_create_t *cparam,
- void *ctx_udata, uint16_t depth);
+ void *ctx_udata, void *parent, uint16_t depth);
H5_DLL herr_t H5B2_hdr_incr(H5B2_hdr_t *hdr);
H5_DLL herr_t H5B2_hdr_decr(H5B2_hdr_t *hdr);
H5_DLL herr_t H5B2_hdr_fuse_incr(H5B2_hdr_t *hdr);
@@ -285,15 +296,15 @@ H5_DLL herr_t H5B2_hdr_delete(H5B2_hdr_t *hdr, hid_t dxpl_id);
/* Routines for operating on leaf nodes */
H5B2_leaf_t *H5B2_protect_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, haddr_t addr,
- unsigned nrec, H5AC_protect_t rw);
+ void *parent, unsigned nrec, H5AC_protect_t rw);
/* Routines for operating on internal nodes */
H5_DLL H5B2_internal_t *H5B2_protect_internal(H5B2_hdr_t *hdr, hid_t dxpl_id,
- haddr_t addr, unsigned nrec, unsigned depth, H5AC_protect_t rw);
+ haddr_t addr, void *parent, unsigned nrec, unsigned depth, H5AC_protect_t rw);
/* Routines for allocating nodes */
-H5_DLL herr_t H5B2_split_root(H5B2_hdr_t *hdr, hid_t dxpl_id);
-H5_DLL herr_t H5B2_create_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id,
+H5_DLL herr_t H5B2_split_root(H5B2_hdr_t *hdr, hid_t dxpl_id, void *udata);
+H5_DLL herr_t H5B2_create_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, void *parent,
H5B2_node_ptr_t *node_ptr);
/* Routines for releasing structures */
@@ -304,45 +315,50 @@ H5_DLL herr_t H5B2_internal_free(H5B2_internal_t *i);
/* Routines for inserting records */
H5_DLL herr_t H5B2_insert_internal(H5B2_hdr_t *hdr, hid_t dxpl_id,
unsigned depth, unsigned *parent_cache_info_flags_ptr,
- H5B2_node_ptr_t *curr_node_ptr, void *udata);
+ H5B2_node_ptr_t *curr_node_ptr, void *parent, void *udata);
H5_DLL herr_t H5B2_insert_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id,
- H5B2_node_ptr_t *curr_node_ptr, void *udata);
+ H5B2_node_ptr_t *curr_node_ptr, void *parent, void *udata);
/* Routines for iterating over nodes/records */
H5_DLL herr_t H5B2_iterate_node(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
- const H5B2_node_ptr_t *curr_node, H5B2_operator_t op, void *op_data);
+ const H5B2_node_ptr_t *curr_node, void *parent, H5B2_operator_t op, void *op_data);
H5_DLL herr_t H5B2_node_size(H5B2_hdr_t *hdr, hid_t dxpl_id,
- unsigned depth, const H5B2_node_ptr_t *curr_node, hsize_t *op_data);
+ unsigned depth, const H5B2_node_ptr_t *curr_node, void *parent,
+ hsize_t *op_data);
/* Routines for locating records */
H5_DLL int H5B2_locate_record(const H5B2_class_t *type, unsigned nrec,
size_t *rec_off, const uint8_t *native, const void *udata, unsigned *idx);
H5_DLL herr_t H5B2_neighbor_internal(H5B2_hdr_t *hdr, hid_t dxpl_id,
unsigned depth, H5B2_node_ptr_t *curr_node_ptr, void *neighbor_loc,
- H5B2_compare_t comp, void *udata, H5B2_found_t op, void *op_data);
+ H5B2_compare_t comp, void *parent, void *udata, H5B2_found_t op,
+ void *op_data);
H5_DLL herr_t H5B2_neighbor_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id,
- H5B2_node_ptr_t *curr_node_ptr, void *neighbor_loc,
- H5B2_compare_t comp, void *udata, H5B2_found_t op, void *op_data);
+ H5B2_node_ptr_t *curr_node_ptr, void *neighbor_loc, H5B2_compare_t comp,
+ void *parent, void *udata, H5B2_found_t op, void *op_data);
/* Routines for removing records */
H5_DLL herr_t H5B2_remove_internal(H5B2_hdr_t *hdr, hid_t dxpl_id,
- hbool_t *depth_decreased, void *swap_loc, unsigned depth, H5AC_info_t *parent_cache_info,
- hbool_t * parent_cache_info_dirtied_ptr, H5B2_node_ptr_t *curr_node_ptr, void *udata,
- H5B2_remove_t op, void *op_data);
-H5_DLL herr_t H5B2_remove_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id,
+ hbool_t *depth_decreased, void *swap_loc, void *swap_parent, unsigned depth,
+ H5AC_info_t *parent_cache_info, hbool_t * parent_cache_info_dirtied_ptr,
H5B2_node_ptr_t *curr_node_ptr, void *udata, H5B2_remove_t op,
void *op_data);
+H5_DLL herr_t H5B2_remove_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id,
+ H5B2_node_ptr_t *curr_node_ptr, void *parent, void *udata, H5B2_remove_t op,
+ void *op_data);
H5_DLL herr_t H5B2_remove_internal_by_idx(H5B2_hdr_t *hdr, hid_t dxpl_id,
- hbool_t *depth_decreased, void *swap_loc, unsigned depth, H5AC_info_t *parent_cache_info,
- hbool_t * parent_cache_info_dirtied_ptr, H5B2_node_ptr_t *curr_node_ptr, hsize_t idx,
- H5B2_remove_t op, void *op_data);
-H5_DLL herr_t H5B2_remove_leaf_by_idx(H5B2_hdr_t *hdr, hid_t dxpl_id,
- H5B2_node_ptr_t *curr_node_ptr, unsigned idx, H5B2_remove_t op,
+ hbool_t *depth_decreased, void *swap_loc, void *swap_parent, unsigned depth,
+ H5AC_info_t *parent_cache_info, hbool_t * parent_cache_info_dirtied_ptr,
+ H5B2_node_ptr_t *curr_node_ptr, hsize_t idx, void *udata, H5B2_remove_t op,
void *op_data);
+H5_DLL herr_t H5B2_remove_leaf_by_idx(H5B2_hdr_t *hdr, hid_t dxpl_id,
+ H5B2_node_ptr_t *curr_node_ptr, void *parent, unsigned idx,
+ H5B2_remove_t op, void *op_data);
/* Routines for deleting nodes */
H5_DLL herr_t H5B2_delete_node(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth,
- const H5B2_node_ptr_t *curr_node, H5B2_remove_t op, void *op_data);
+ const H5B2_node_ptr_t *curr_node, void *parent, H5B2_remove_t op,
+ void *op_data);
/* Debugging routines for dumping file structures */
H5_DLL herr_t H5B2_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr,
diff --git a/src/H5B2private.h b/src/H5B2private.h
index 8ec9954..7ec0019 100644
--- a/src/H5B2private.h
+++ b/src/H5B2private.h
@@ -94,6 +94,8 @@ struct H5B2_class_t {
herr_t (*compare)(const void *rec1, const void *rec2); /* Compare two native records */
herr_t (*encode)(uint8_t *raw, const void *record, void *ctx); /* Encode record from native form to disk storage form */
herr_t (*decode)(const uint8_t *raw, void *record, void *ctx); /* Decode record from disk storage form to native form */
+ herr_t (*crt_flush_dep)(void *record, void *udata, void *parent); /* Create a flush dependency with record as child */
+ herr_t (*upd_flush_dep)(void *record, void *udata, void *old_parent, void *new_parent); /* Update a flush dependency with record as child */
herr_t (*debug)(FILE *stream, const H5F_t *f, hid_t dxpl_id, /* Print a record for debugging */
int indent, int fwidth, const void *record, const void *ctx);
void *(*crt_dbg_ctx)(H5F_t *f, hid_t dxpl_id, haddr_t obj_addr); /* Create debugging context */
@@ -128,8 +130,9 @@ typedef struct H5B2_t H5B2_t;
/* Library-private Function Prototypes */
/***************************************/
H5_DLL H5B2_t *H5B2_create(H5F_t *f, hid_t dxpl_id, const H5B2_create_t *cparam,
- void *ctx_udata);
-H5_DLL H5B2_t *H5B2_open(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *ctx_udata);
+ void *ctx_udata, void *parent);
+H5_DLL H5B2_t *H5B2_open(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *ctx_udata,
+ void *parent);
H5_DLL herr_t H5B2_get_addr(const H5B2_t *bt2, haddr_t *addr/*out*/);
H5_DLL herr_t H5B2_insert(H5B2_t *bt2, hid_t dxpl_id, void *udata);
H5_DLL herr_t H5B2_iterate(H5B2_t *bt2, hid_t dxpl_id, H5B2_operator_t op,
@@ -145,13 +148,18 @@ H5_DLL herr_t H5B2_modify(H5B2_t *bt2, hid_t dxpl_id, void *udata,
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,
- H5_iter_order_t order, hsize_t idx, H5B2_remove_t op, void *op_data);
+ H5_iter_order_t order, hsize_t idx, void *udata, H5B2_remove_t op,
+ void *op_data);
H5_DLL herr_t H5B2_get_nrec(const H5B2_t *bt2, hsize_t *nrec);
H5_DLL herr_t H5B2_size(H5B2_t *bt2, hid_t dxpl_id,
hsize_t *btree_size);
H5_DLL herr_t H5B2_close(H5B2_t *bt2, hid_t dxpl_id);
H5_DLL herr_t H5B2_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr,
- void *ctx_udata, H5B2_remove_t op, void *op_data);
+ void *ctx_udata, void *parent, H5B2_remove_t op, void *op_data);
+H5_DLL htri_t H5B2_support(H5B2_t *bt2, hid_t dxpl_id, void *udata,
+ void *child);
+H5_DLL herr_t H5B2_unsupport(H5B2_t *bt2, hid_t dxpl_id, void *udata,
+ void *child);
/* Statistics routines */
H5_DLL herr_t H5B2_stat_info(H5B2_t *bt2, H5B2_stat_t *info);
diff --git a/src/H5B2stat.c b/src/H5B2stat.c
index a8f1fbd..05e81ed 100644
--- a/src/H5B2stat.c
+++ b/src/H5B2stat.c
@@ -140,7 +140,7 @@ H5B2_size(H5B2_t *bt2, hid_t dxpl_id, hsize_t *btree_size)
*btree_size += hdr->node_size;
else
/* Iterate through nodes */
- if(H5B2_node_size(hdr, dxpl_id, hdr->depth, &hdr->root, btree_size) < 0)
+ if(H5B2_node_size(hdr, dxpl_id, hdr->depth, &hdr->root, hdr, btree_size) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "node iteration failed")
} /* end if */
diff --git a/src/H5B2test.c b/src/H5B2test.c
index 8507d6e..06736e7 100644
--- a/src/H5B2test.c
+++ b/src/H5B2test.c
@@ -86,6 +86,8 @@ 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 */
+ NULL, /* Create flush dependency */
+ NULL, /* Update flush dependency */
H5B2_test_debug, /* Record debugging callback */
H5B2_test_crt_dbg_context, /* Create debugging context */
H5B2_test_dst_context /* Destroy debugging context */
@@ -397,6 +399,7 @@ H5B2_get_node_info_test(H5B2_t *bt2, hid_t dxpl_id, void *udata,
{
H5B2_hdr_t *hdr; /* Pointer to the B-tree header */
H5B2_node_ptr_t curr_node_ptr; /* Node pointer info for current node */
+ void *parent = NULL; /* Parent of current node */
unsigned depth; /* Current depth of the tree */
int cmp; /* Comparison value of records */
unsigned idx; /* Location of record which matches key */
@@ -416,6 +419,10 @@ H5B2_get_node_info_test(H5B2_t *bt2, hid_t dxpl_id, void *udata,
/* Make copy of the root node pointer to start search with */
curr_node_ptr = hdr->root;
+ /* Set initial parent, if doing swmr writes */
+ if(hdr->swmr_write)
+ parent = hdr;
+
/* Current depth of the tree */
depth = hdr->depth;
@@ -430,9 +437,16 @@ H5B2_get_node_info_test(H5B2_t *bt2, hid_t dxpl_id, void *udata,
H5B2_node_ptr_t next_node_ptr; /* Node pointer info for next node */
/* Lock B-tree current node */
- if(NULL == (internal = H5B2_protect_internal(hdr, dxpl_id, curr_node_ptr.addr, curr_node_ptr.node_nrec, depth, H5AC_READ)))
+ if(NULL == (internal = H5B2_protect_internal(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, depth, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
+ /* Unpin parent if necessary */
+ if(parent) {
+ if(parent != hdr && H5AC_unpin_entry(parent) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "unable to unpin parent entry")
+ parent = NULL;
+ } /* end if */
+
/* Locate node pointer for child */
cmp = H5B2_locate_record(hdr->cls, internal->nrec, hdr->nat_off, internal->int_native, udata, &idx);
if(cmp > 0)
@@ -443,9 +457,13 @@ H5B2_get_node_info_test(H5B2_t *bt2, hid_t dxpl_id, void *udata,
next_node_ptr = internal->node_ptrs[idx];
/* Unlock current node */
- if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__NO_FLAGS_SET) < 0)
+ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, hdr->swmr_write ? H5AC__PIN_ENTRY_FLAG : H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ /* Keep track of parent if necessary */
+ if(hdr->swmr_write)
+ parent = internal;
+
/* Set pointer to next node to load */
curr_node_ptr = next_node_ptr;
} /* end if */
@@ -470,9 +488,16 @@ H5B2_get_node_info_test(H5B2_t *bt2, hid_t dxpl_id, void *udata,
H5B2_leaf_t *leaf; /* Pointer to leaf node in B-tree */
/* Lock B-tree leaf node */
- if(NULL == (leaf = H5B2_protect_leaf(hdr, dxpl_id, curr_node_ptr.addr, curr_node_ptr.node_nrec, H5AC_READ)))
+ if(NULL == (leaf = H5B2_protect_leaf(hdr, dxpl_id, curr_node_ptr.addr, parent, curr_node_ptr.node_nrec, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
+ /* Unpin parent if necessary */
+ if(parent) {
+ if(parent != hdr && H5AC_unpin_entry(parent) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "unable to unpin parent entry")
+ parent = NULL;
+ } /* end if */
+
/* Locate record */
cmp = H5B2_locate_record(hdr->cls, leaf->nrec, hdr->nat_off, leaf->leaf_native, udata, &idx);
@@ -490,6 +515,12 @@ H5B2_get_node_info_test(H5B2_t *bt2, hid_t dxpl_id, void *udata,
ninfo->nrec = curr_node_ptr.node_nrec;
done:
+ if(parent) {
+ HDassert(ret_value < 0);
+ if(parent != hdr && H5AC_unpin_entry(parent) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "unable to unpin parent entry")
+ } /* end if */
+
FUNC_LEAVE_NOAPI(ret_value)
} /* H5B2_get_node_info_test() */
diff --git a/src/H5Bprivate.h b/src/H5Bprivate.h
index a7b303d..1d371a3 100644
--- a/src/H5Bprivate.h
+++ b/src/H5Bprivate.h
@@ -141,8 +141,8 @@ typedef struct H5B_class_t {
herr_t (*debug_key)(FILE*, int, int, const void*, const void*);
/* flush dependency functions */
- herr_t (*create_flush_dep)(void*, void *, void *);
- herr_t (*update_flush_dep)(void*, void *, void *, void*);
+ herr_t (*create_flush_dep)(void*, void*, void*);
+ herr_t (*update_flush_dep)(void*, void*, void*, void*);
} H5B_class_t;
/* Information about B-tree */
diff --git a/src/H5Dbtree2.c b/src/H5Dbtree2.c
index e2a5ca1..27119fc 100644
--- a/src/H5Dbtree2.c
+++ b/src/H5Dbtree2.c
@@ -94,6 +94,10 @@ typedef struct H5D_bt2_it_ud_t {
typedef struct H5D_bt2_find_ud_t {
void *rec; /* The record to search for */
unsigned ndims; /* Number of dimensions for the chunked dataset */
+ const H5O_layout_chunk_t *layout; /* Chunk layout description */
+ const struct H5D_rdcc_t *rdcc; /* Chunk cache. Only necessary if the index
+ * may be modified, and if any chunks in the
+ * dset may be cached */
} H5D_bt2_find_ud_t;
@@ -112,6 +116,9 @@ static herr_t H5D_bt2_store(void *native, const void *udata);
static herr_t H5D_bt2_compare(const void *rec1, const void *rec2);
static herr_t H5D_bt2_encode(uint8_t *raw, const void *native, void *ctx);
static herr_t H5D_bt2_decode(const uint8_t *raw, void *native, void *ctx);
+static herr_t H5D_bt2_crt_flush_dep(void *_record, void *_udata, void *parent);
+static herr_t H5D_bt2_upd_flush_dep(void *_record, void *_udata,
+ void *old_parent, void *new_parent);
static herr_t H5D_bt2_debug(FILE *stream, const H5F_t *f, hid_t dxpl_id,
int indent, int fwidth, const void *record, const void *u_ctx);
@@ -120,6 +127,10 @@ static herr_t H5D_bt2_filt_store(void *native, const void *udata);
static herr_t H5D_bt2_filt_compare(const void *rec1, const void *rec2);
static herr_t H5D_bt2_filt_encode(uint8_t *raw, const void *native, void *ctx);
static herr_t H5D_bt2_filt_decode(const uint8_t *raw, void *native, void *ctx);
+static herr_t H5D_bt2_filt_crt_flush_dep(void *_record, void *_udata,
+ void *parent);
+static herr_t H5D_bt2_filt_upd_flush_dep(void *_record, void *_udata,
+ void *old_parent, void *new_parent);
static herr_t H5D_bt2_filt_debug(FILE *stream, const H5F_t *f, hid_t dxpl_id,
int indent, int fwidth, const void *record, const void *u_ctx);
@@ -144,6 +155,8 @@ static herr_t H5D_bt2_filt_remove_cb(const void *nrecord, void *_udata);
static herr_t H5D_bt2_mod_filt_cb(void *_record, void *_op_data, hbool_t *changed);
/* Chunked layout indexing callbacks for v2 B-tree indexing */
+static herr_t H5D_bt2_idx_init(const H5D_chk_idx_info_t *idx_info,
+ const H5S_t *space, haddr_t dset_ohdr_addr);
static herr_t H5D_bt2_idx_create(const H5D_chk_idx_info_t *idx_info);
static hbool_t H5D_bt2_idx_is_space_alloc(const H5O_storage_chunk_t *storage);
static herr_t H5D_bt2_idx_insert(const H5D_chk_idx_info_t *idx_info,
@@ -161,6 +174,10 @@ static herr_t H5D_bt2_idx_copy_shutdown(H5O_storage_chunk_t *storage_src,
H5O_storage_chunk_t *storage_dst, hid_t dxpl_id);
static herr_t H5D_bt2_idx_size(const H5D_chk_idx_info_t *idx_info, hsize_t *size);
static herr_t H5D_bt2_idx_reset(H5O_storage_chunk_t *storage, hbool_t reset_addr);
+static htri_t H5D_bt2_idx_support(const H5D_chk_idx_info_t *idx_info,
+ H5D_chunk_ud_t *udata, H5AC_info_t *child_entry);
+static herr_t H5D_bt2_idx_unsupport(const H5D_chk_idx_info_t *idx_info,
+ H5D_chunk_ud_t *udata, H5AC_info_t *child_entry);
static herr_t H5D_bt2_idx_dump(const H5O_storage_chunk_t *storage,
FILE *stream);
static herr_t H5D_bt2_idx_dest(const H5D_chk_idx_info_t *idx_info);
@@ -172,8 +189,8 @@ static herr_t H5D_bt2_idx_dest(const H5D_chk_idx_info_t *idx_info);
/* Chunked dataset I/O ops for v2 B-tree indexing */
const H5D_chunk_ops_t H5D_COPS_BT2[1] = {{
- FALSE,
- NULL,
+ TRUE,
+ H5D_bt2_idx_init,
H5D_bt2_idx_create,
H5D_bt2_idx_is_space_alloc,
H5D_bt2_idx_insert,
@@ -186,8 +203,8 @@ const H5D_chunk_ops_t H5D_COPS_BT2[1] = {{
H5D_bt2_idx_copy_shutdown,
H5D_bt2_idx_size,
H5D_bt2_idx_reset,
- NULL,
- NULL,
+ H5D_bt2_idx_support,
+ H5D_bt2_idx_unsupport,
H5D_bt2_idx_dump,
H5D_bt2_idx_dest
}};
@@ -208,6 +225,8 @@ const H5B2_class_t H5D_BT2[1] = {{ /* B-tree class information */
H5D_bt2_compare, /* Record comparison callback */
H5D_bt2_encode, /* Record encoding callback */
H5D_bt2_decode, /* Record decoding callback */
+ H5D_bt2_crt_flush_dep, /* Create flush dependency */
+ H5D_bt2_upd_flush_dep, /* Update flush dependency */
H5D_bt2_debug, /* Record debugging callback */
H5D_bt2_crt_dbg_context, /* Create debugging context */
H5D_bt2_dst_dbg_context /* Destroy debugging context */
@@ -224,6 +243,8 @@ const H5B2_class_t H5D_BT2_FILT[1] = {{ /* B-tree class information */
H5D_bt2_filt_compare, /* Record comparison callback */
H5D_bt2_filt_encode, /* Record encoding callback */
H5D_bt2_filt_decode, /* Record decoding callback */
+ H5D_bt2_filt_crt_flush_dep, /* Create flush dependency */
+ H5D_bt2_filt_upd_flush_dep, /* Update flush dependency */
H5D_bt2_filt_debug, /* Record debugging callback */
H5D_bt2_crt_dbg_context, /* Create debugging context */
H5D_bt2_dst_dbg_context /* Destroy debugging context */
@@ -450,6 +471,89 @@ H5D_bt2_decode(const uint8_t *raw, void *_record, void *_ctx)
/*-------------------------------------------------------------------------
+ * Function: H5D_bt2_crt_flush_dep
+ *
+ * Purpose: Creates a flush dependency between the specified chunk
+ * (child) and parent.
+ *
+ * Return: Success: 0
+ * Failure: FAIL
+ *
+ * Programmer: Neil Fortner
+ * Tuesday, May 1, 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_bt2_crt_flush_dep(void *_record, void *_udata, void *parent)
+{
+ H5D_bt2_rec_t *record = (H5D_bt2_rec_t *)_record; /* The native record */
+ const H5D_bt2_find_ud_t *udata = (const H5D_bt2_find_ud_t *)_udata; /* User data */
+ int ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ HDassert(record);
+ HDassert(udata);
+ HDassert(udata->layout->ndims > 0 && udata->layout->ndims <= H5O_LAYOUT_NDIMS);
+ HDassert(parent);
+
+ /* If there is no rdcc, then there are no cached chunks to create
+ * dependencies on. This should only happen when copying */
+ if(udata->rdcc)
+ /* Delegate to chunk routine */
+ if(H5D_chunk_create_flush_dep(udata->rdcc, udata->layout, record->offset, parent) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_bt2_crt_flush_dep() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_bt2_upd_flush_dep
+ *
+ * Purpose: Updates the flush dependency of the specified chunk from
+ * old_parent to new_parent, but only if the current parent
+ * is cached. If the chunk is not cached, does nothing.
+ *
+ * Return: Success: 0
+ * Failure: FAIL
+ *
+ * Programmer: Neil Fortner
+ * Tuesday, May 1, 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_bt2_upd_flush_dep(void *_record, void *_udata, void *old_parent,
+ void *new_parent)
+{
+ H5D_bt2_rec_t *record = (H5D_bt2_rec_t *)_record; /* The native record */
+ const H5D_bt2_find_ud_t *udata = (const H5D_bt2_find_ud_t *)_udata; /* User data */
+ int ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ HDassert(record);
+ HDassert(udata);
+ HDassert(udata->layout->ndims > 0 && udata->layout->ndims <= H5O_LAYOUT_NDIMS);
+ HDassert(old_parent);
+ HDassert(new_parent);
+
+ /* If there is no rdcc, then there are no cached chunks to update
+ * dependencies. This should only happen when copying */
+ if(udata->rdcc)
+ /* Delegate to chunk routine */
+ if(H5D_chunk_update_flush_dep(udata->rdcc, udata->layout, record->offset, old_parent, new_parent) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_bt2_upd_flush_dep() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5D_bt2_debug
*
* Purpose: Debug native form of record (non-filtered)
@@ -617,6 +721,89 @@ H5D_bt2_filt_decode(const uint8_t *raw, void *_record, void *_ctx)
/*-------------------------------------------------------------------------
+ * Function: H5D_bt2_filt_crt_flush_dep
+ *
+ * Purpose: Creates a flush dependency between the specified chunk
+ * (child) and parent.
+ *
+ * Return: Success: 0
+ * Failure: FAIL
+ *
+ * Programmer: Neil Fortner
+ * Tuesday, May 1, 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_bt2_filt_crt_flush_dep(void *_record, void *_udata, void *parent)
+{
+ H5D_bt2_filt_rec_t *record = (H5D_bt2_filt_rec_t *)_record; /* The native record */
+ const H5D_bt2_find_ud_t *udata = (const H5D_bt2_find_ud_t *)_udata; /* User data */
+ int ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ HDassert(record);
+ HDassert(udata);
+ HDassert(udata->layout->ndims > 0 && udata->layout->ndims <= H5O_LAYOUT_NDIMS);
+ HDassert(parent);
+
+ /* If there is no rdcc, then there are no cached chunks to create
+ * dependencies on. This should only happen when copying */
+ if(udata->rdcc)
+ /* Delegate to chunk routine */
+ if(H5D_chunk_create_flush_dep(udata->rdcc, udata->layout, record->offset, parent) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_bt2_filt_crt_flush_dep() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_bt2_filt_upd_flush_dep
+ *
+ * Purpose: Updates the flush dependency of the specified chunk from
+ * old_parent to new_parent, but only if the current parent
+ * is cached. If the chunk is not cached, does nothing.
+ *
+ * Return: Success: 0
+ * Failure: FAIL
+ *
+ * Programmer: Neil Fortner
+ * Tuesday, May 1, 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_bt2_filt_upd_flush_dep(void *_record, void *_udata, void *old_parent,
+ void *new_parent)
+{
+ H5D_bt2_filt_rec_t *record = (H5D_bt2_filt_rec_t *)_record; /* The native record */
+ const H5D_bt2_find_ud_t *udata = (const H5D_bt2_find_ud_t *)_udata; /* User data */
+ int ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ HDassert(record);
+ HDassert(udata);
+ HDassert(udata->layout->ndims > 0 && udata->layout->ndims <= H5O_LAYOUT_NDIMS);
+ HDassert(old_parent);
+ HDassert(new_parent);
+
+ /* If there is no rdcc, then there are no cached chunks to update
+ * dependencies. This should only happen when copying */
+ if(udata->rdcc)
+ /* Delegate to chunk routine */
+ if(H5D_chunk_update_flush_dep(udata->rdcc, udata->layout, record->offset, old_parent, new_parent) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_btree_filt_upd_flush_dep() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5D_bt2_filt_debug
*
* Purpose: Debug native form of record (filterd)
@@ -758,6 +945,33 @@ H5D_bt2_dst_dbg_context(void *_u_ctx)
/*-------------------------------------------------------------------------
+ * Function: H5D_bt2_idx_init
+ *
+ * Purpose: Initialize the indexing information for a dataset.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * Wednensday, May 23, 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_bt2_idx_init(const H5D_chk_idx_info_t UNUSED *idx_info,
+ const H5S_t UNUSED *space, haddr_t dset_ohdr_addr)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* Check args */
+ HDassert(H5F_addr_defined(dset_ohdr_addr));
+
+ idx_info->storage->u.btree2.dset_ohdr_addr = dset_ohdr_addr;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D_bt2_idx_init() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5D_bt2_idx_open()
*
* Purpose: Opens an existing v2 B-tree.
@@ -778,6 +992,8 @@ static herr_t
H5D_bt2_idx_open(const H5D_chk_idx_info_t *idx_info)
{
H5D_bt2_ctx_ud_t u_ctx; /* user data for creating context */
+ H5O_loc_t oloc; /* Temporary object header location for dataset */
+ H5O_t *oh = NULL; /* Dataset's object header */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -797,11 +1013,27 @@ H5D_bt2_idx_open(const H5D_chk_idx_info_t *idx_info)
u_ctx.ndims = idx_info->layout->ndims - 1;
u_ctx.chunk_size = idx_info->layout->size;
+ /* Check for SWMR writes to the file */
+ if(H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE) {
+ /* Set up object header location for dataset */
+ H5O_loc_reset(&oloc);
+ oloc.file = idx_info->f;
+ oloc.addr = idx_info->storage->u.btree.dset_ohdr_addr;
+
+ /* Pin the dataset's object header */
+ /*!FIXME change to use ohdr proxy once those changes are merged -NAF */
+ if(NULL == (oh = H5O_pin(&oloc, idx_info->dxpl_id)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTPIN, FAIL, "unable to pin dataset object header")
+ } /* end if */
+
/* Open v2 B-tree for the chunk index */
- if(NULL == (idx_info->storage->u.btree2.bt2 = H5B2_open(idx_info->f, idx_info->dxpl_id, idx_info->storage->idx_addr , &u_ctx)))
+ if(NULL == (idx_info->storage->u.btree2.bt2 = H5B2_open(idx_info->f, idx_info->dxpl_id, idx_info->storage->idx_addr , &u_ctx, oh)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't open v2 B-tree for tracking chunked dataset")
done:
+ if(oh && H5O_unpin(oh) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTUNPIN, FAIL, "unable to unpin dataset object header")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_bt2_idx_open() */
@@ -822,6 +1054,8 @@ H5D_bt2_idx_create(const H5D_chk_idx_info_t *idx_info)
{
H5B2_create_t bt2_cparam; /* v2 B-tree creation parameters */
H5D_bt2_ctx_ud_t u_ctx; /* data for context call */
+ H5O_loc_t oloc; /* Temporary object header location for dataset */
+ H5O_t *oh = NULL; /* Dataset's object header */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -833,7 +1067,7 @@ H5D_bt2_idx_create(const H5D_chk_idx_info_t *idx_info)
HDassert(idx_info->layout);
HDassert(idx_info->storage);
HDassert(!H5F_addr_defined(idx_info->storage->idx_addr));
-
+
bt2_cparam.rrec_size = H5F_SIZEOF_ADDR(idx_info->f) /* Address of chunk */
+ (idx_info->layout->ndims - 1) * 8; /* # of dimensions x 64-bit chunk offsets */
@@ -863,8 +1097,21 @@ H5D_bt2_idx_create(const H5D_chk_idx_info_t *idx_info)
u_ctx.ndims = idx_info->layout->ndims - 1;
u_ctx.chunk_size = idx_info->layout->size;
+ /* Check for SWMR writes to the file */
+ if(H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE) {
+ /* Set up object header location for dataset */
+ H5O_loc_reset(&oloc);
+ oloc.file = idx_info->f;
+ oloc.addr = idx_info->storage->u.btree.dset_ohdr_addr;
+
+ /* Pin the dataset's object header */
+ /*!FIXME change to use ohdr proxy once those changes are merged -NAF */
+ if(NULL == (oh = H5O_pin(&oloc, idx_info->dxpl_id)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTPIN, FAIL, "unable to pin dataset object header")
+ } /* end if */
+
/* Create the v2 B-tree for the chunked dataset */
- if(NULL == (idx_info->storage->u.btree2.bt2 = H5B2_create(idx_info->f, idx_info->dxpl_id, &bt2_cparam, &u_ctx)))
+ if(NULL == (idx_info->storage->u.btree2.bt2 = H5B2_create(idx_info->f, idx_info->dxpl_id, &bt2_cparam, &u_ctx, oh)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, FAIL, "can't create v2 B-tree for tracking chunked dataset")
/* Retrieve the v2 B-tree's address in the file */
@@ -872,6 +1119,9 @@ H5D_bt2_idx_create(const H5D_chk_idx_info_t *idx_info)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get v2 B-tree address for tracking chunked dataset")
done:
+ if(oh && H5O_unpin(oh) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTUNPIN, FAIL, "unable to unpin dataset object header")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_bt2_idx_create() */
@@ -1015,6 +1265,8 @@ H5D_bt2_idx_insert(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata)
/* Prepare user data for compare callback */
bt2_udata.rec = &rec;
bt2_udata.ndims = idx_info->layout->ndims - 1;
+ bt2_udata.layout = idx_info->layout;
+ bt2_udata.rdcc = udata->common.rdcc;
/* Try to find the chunked record */
if(H5B2_find(bt2, idx_info->dxpl_id, &bt2_udata, H5D_bt2_filt_found_cb, &found_rec) < 0)
@@ -1027,10 +1279,12 @@ H5D_bt2_idx_insert(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata)
/* Check for chunk being same size */
if(udata->nbytes != found_rec.nbytes) {
- /* Free the original chunk */
- H5_CHECK_OVERFLOW(found_rec.nbytes, uint32_t, hsize_t);
- if(H5MF_xfree(idx_info->f, H5FD_MEM_DRAW, idx_info->dxpl_id, found_rec.addr, (hsize_t)found_rec.nbytes) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to free chunk")
+ /* Free the original chunk if not doing SWMR writes */
+ if(!(H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE)) {
+ H5_CHECK_OVERFLOW(found_rec.nbytes, uint32_t, hsize_t);
+ if(H5MF_xfree(idx_info->f, H5FD_MEM_DRAW, idx_info->dxpl_id, found_rec.addr, (hsize_t)found_rec.nbytes) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to free chunk")
+ } /* end if */
/* Allocate a new chunk */
H5_CHECK_OVERFLOW(udata->nbytes, uint32_t, hsize_t);
@@ -1071,6 +1325,8 @@ H5D_bt2_idx_insert(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata)
/* Prepare user data for compare callback */
bt2_udata.rec = &rec;
bt2_udata.ndims = idx_info->layout->ndims - 1;
+ bt2_udata.layout = idx_info->layout;
+ bt2_udata.rdcc = udata->common.rdcc;
for(u = 0; u < (idx_info->layout->ndims - 1); u++)
rec.offset[u] = udata->common.offset[u];
@@ -1203,6 +1459,8 @@ H5D_bt2_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata)
/* Prepare user data for compare callback */
bt2_udata.rec = &search_rec;
bt2_udata.ndims = idx_info->layout->ndims - 1;
+ bt2_udata.layout = idx_info->layout;
+ bt2_udata.rdcc = udata->common.rdcc;
/* Go get chunk information from v2 B-tree */
if(H5B2_find(bt2, idx_info->dxpl_id, &bt2_udata, H5D_bt2_filt_found_cb, &found_rec) < 0)
@@ -1227,6 +1485,8 @@ H5D_bt2_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata)
/* Prepare user data for compare callback */
bt2_udata.rec = &search_rec;
bt2_udata.ndims = idx_info->layout->ndims - 1;
+ bt2_udata.layout = idx_info->layout;
+ bt2_udata.rdcc = udata->common.rdcc;
/* Go get chunk information from v2 B-tree */
if(H5B2_find(bt2, idx_info->dxpl_id, &bt2_udata, H5D_bt2_found_cb, &found_rec) < 0)
@@ -1481,8 +1741,10 @@ H5D_bt2_idx_remove(const H5D_chk_idx_info_t *idx_info, H5D_chunk_common_ud_t *ud
bt2_udata.rec = &search_rec;
bt2_udata.ndims = idx_info->layout->ndims - 1;
+ bt2_udata.layout = idx_info->layout;
+ bt2_udata.rdcc = udata->rdcc;
- if(H5B2_remove(bt2, idx_info->dxpl_id, &bt2_udata, H5D_bt2_filt_remove_cb, &remove_udata) < 0)
+ if(H5B2_remove(bt2, idx_info->dxpl_id, &bt2_udata, (H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE) ? NULL : H5D_bt2_filt_remove_cb, &remove_udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTREMOVE, FAIL, "can't remove object from B-tree")
} /* end if */
else { /* non-filtered chunk */
@@ -1496,8 +1758,10 @@ H5D_bt2_idx_remove(const H5D_chk_idx_info_t *idx_info, H5D_chunk_common_ud_t *ud
bt2_udata.rec = &search_rec;
bt2_udata.ndims = idx_info->layout->ndims - 1;
+ bt2_udata.layout = idx_info->layout;
+ bt2_udata.rdcc = udata->rdcc;
- if(H5B2_remove(bt2, idx_info->dxpl_id, &bt2_udata, H5D_bt2_remove_cb, &remove_udata) < 0)
+ if(H5B2_remove(bt2, idx_info->dxpl_id, &bt2_udata, (H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE) ? NULL : H5D_bt2_remove_cb, &remove_udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTREMOVE, FAIL, "can't remove object from B-tree")
} /* end else */
@@ -1532,6 +1796,8 @@ H5D_bt2_idx_delete(const H5D_chk_idx_info_t *idx_info)
H5D_bt2_remove_ud_t remove_udata; /* User data for removal callback */
H5B2_remove_t remove_op; /* The removal callback */
H5D_bt2_ctx_ud_t u_ctx; /* data for context call */
+ H5O_loc_t oloc; /* Temporary object header location for dataset */
+ H5O_t *oh = NULL; /* Dataset's object header */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -1554,22 +1820,43 @@ H5D_bt2_idx_delete(const H5D_chk_idx_info_t *idx_info)
remove_udata.f = idx_info->f;
remove_udata.dxpl_id = idx_info->dxpl_id;
- if(idx_info->pline->nused > 0) /* filtered */
- remove_op = H5D_bt2_filt_remove_cb;
- else { /* non-filtered */
- remove_op = H5D_bt2_remove_cb;
- remove_udata.unfilt_size = idx_info->layout->size;
- }
+ /* Set remove operation. Do not remove chunks in SWMR_WRITE mode */
+ if(H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE)
+ remove_op = NULL;
+ else {
+ if(idx_info->pline->nused > 0) /* filtered */
+ remove_op = H5D_bt2_filt_remove_cb;
+ else { /* non-filtered */
+ remove_op = H5D_bt2_remove_cb;
+ remove_udata.unfilt_size = idx_info->layout->size;
+ } /* end else */
+ } /* end else */
+
+ /* Check for SWMR writes to the file */
+ if(H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE) {
+ /* Set up object header location for dataset */
+ H5O_loc_reset(&oloc);
+ oloc.file = idx_info->f;
+ oloc.addr = idx_info->storage->u.btree.dset_ohdr_addr;
+
+ /* Pin the dataset's object header */
+ /*!FIXME change to use ohdr proxy once those changes are merged -NAF */
+ if(NULL == (oh = H5O_pin(&oloc, idx_info->dxpl_id)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTPIN, FAIL, "unable to pin dataset object header")
+ } /* end if */
/* Delete the v2 B-tree */
/*(space in the file for each object is freed in the 'remove' callback) */
- if(H5B2_delete(idx_info->f, idx_info->dxpl_id, idx_info->storage->idx_addr, &u_ctx, remove_op, &remove_udata) < 0)
+ if(H5B2_delete(idx_info->f, idx_info->dxpl_id, idx_info->storage->idx_addr, &u_ctx, oh, remove_op, &remove_udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTDELETE, FAIL, "can't delete v2 B-tree")
idx_info->storage->idx_addr = HADDR_UNDEF;
} /* end if */
done:
+ if(oh && H5O_unpin(oh) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTUNPIN, FAIL, "unable to unpin dataset object header")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_bt2_idx_delete() */
@@ -1621,7 +1908,7 @@ H5D_bt2_idx_copy_setup(const H5D_chk_idx_info_t *idx_info_src,
if(H5D_bt2_idx_create(idx_info_dst) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize chunked storage")
HDassert(H5F_addr_defined(idx_info_dst->storage->idx_addr));
-
+
/* Reset metadata tag */
H5_END_TAG(FAIL);
@@ -1747,6 +2034,146 @@ H5D_bt2_idx_reset(H5O_storage_chunk_t *storage, hbool_t reset_addr)
/*-------------------------------------------------------------------------
+ * Function: H5D_bt2_idx_support
+ *
+ * Purpose: Create a dependency between a chunk [proxy] and the index
+ * metadata that contains the record for the chunk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * Monday, May 14, 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+static htri_t
+H5D_bt2_idx_support(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata,
+ H5AC_info_t *child_entry)
+{
+ H5D_bt2_find_ud_t bt2_udata; /* User data for v2 B-tree calls */
+ unsigned u; /* Local index variable */
+ htri_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Check args */
+ HDassert(idx_info);
+ HDassert(idx_info->f);
+ HDassert(idx_info->pline);
+ HDassert(idx_info->layout);
+ HDassert(idx_info->storage);
+ HDassert(H5F_addr_defined(idx_info->storage->idx_addr));
+ HDassert(udata);
+ HDassert(child_entry);
+ HDassert(H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE);
+
+ if(idx_info->pline->nused > 0) { /* filtered chunk */
+ H5D_bt2_filt_rec_t search_rec; /* Record for searching for object */
+
+ /* Set the chunk offset to be searched for */
+ for(u = 0; u < (idx_info->layout->ndims - 1); u++)
+ search_rec.offset[u] = udata->common.offset[u];
+
+ /* Prepare user data for support callback */
+ bt2_udata.rec = &search_rec;
+ bt2_udata.ndims = idx_info->layout->ndims - 1;
+ bt2_udata.layout = idx_info->layout;
+ bt2_udata.rdcc = udata->common.rdcc;
+ } /* end if */
+ else { /* non-filtered chunk */
+ H5D_bt2_rec_t search_rec; /* Record for searching for object */
+
+ /* Set the chunk offset to be searched for */
+ for(u = 0; u < (idx_info->layout->ndims - 1); u++)
+ search_rec.offset[u] = udata->common.offset[u];
+
+ /* Prepare user data for support callback */
+ bt2_udata.rec = &search_rec;
+ bt2_udata.ndims = idx_info->layout->ndims - 1;
+ bt2_udata.layout = idx_info->layout;
+ bt2_udata.rdcc = udata->common.rdcc;
+ } /* end else */
+
+ /* Add the flush dependency on the chunk */
+ if((ret_value = H5B2_support(idx_info->storage->u.btree2.bt2, idx_info->dxpl_id, &bt2_udata, child_entry)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTDEPEND, FAIL, "unable to create flush dependency on b-tree array metadata")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_bt2_idx_support() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_bt2_idx_unsupport
+ *
+ * Purpose: Destroy a dependency between a chunk [proxy] and the index
+ * metadata that contains the record for the chunk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * Monday, May 14, 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_bt2_idx_unsupport(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata,
+ H5AC_info_t *child_entry)
+{
+ H5D_bt2_find_ud_t bt2_udata; /* User data for v2 B-tree calls */
+ unsigned u; /* Local index variable */
+ herr_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Check args */
+ HDassert(idx_info);
+ HDassert(idx_info->f);
+ HDassert(idx_info->pline);
+ HDassert(idx_info->layout);
+ HDassert(idx_info->storage);
+ HDassert(H5F_addr_defined(idx_info->storage->idx_addr));
+ HDassert(udata);
+ HDassert(child_entry);
+ HDassert(H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE);
+
+ if(idx_info->pline->nused > 0) { /* filtered chunk */
+ H5D_bt2_filt_rec_t search_rec; /* Record for searching for object */
+
+ /* Set the chunk offset to be searched for */
+ for(u = 0; u < (idx_info->layout->ndims - 1); u++)
+ search_rec.offset[u] = udata->common.offset[u];
+
+ /* Prepare user data for support callback */
+ bt2_udata.rec = &search_rec;
+ bt2_udata.ndims = idx_info->layout->ndims - 1;
+ bt2_udata.layout = idx_info->layout;
+ bt2_udata.rdcc = udata->common.rdcc;
+ } /* end if */
+ else { /* non-filtered chunk */
+ H5D_bt2_rec_t search_rec; /* Record for searching for object */
+
+ /* Set the chunk offset to be searched for */
+ for(u = 0; u < (idx_info->layout->ndims - 1); u++)
+ search_rec.offset[u] = udata->common.offset[u];
+
+ /* Prepare user data for support callback */
+ bt2_udata.rec = &search_rec;
+ bt2_udata.ndims = idx_info->layout->ndims - 1;
+ bt2_udata.layout = idx_info->layout;
+ bt2_udata.rdcc = udata->common.rdcc;
+ } /* end else */
+
+ /* Add the flush dependency on the chunk */
+ if((ret_value = H5B2_unsupport(idx_info->storage->u.btree2.bt2, idx_info->dxpl_id, &bt2_udata, child_entry)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency on b-tree array metadata")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_bt2_idx_unsupport() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5D_bt2_idx_dump
*
* Purpose: Dump indexing information to a stream.
diff --git a/src/H5Gbtree2.c b/src/H5Gbtree2.c
index a917eb4..5a0fd80 100644
--- a/src/H5Gbtree2.c
+++ b/src/H5Gbtree2.c
@@ -114,6 +114,8 @@ 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 */
+ NULL, /* Create flush dependency */
+ NULL, /* Update flush dependency */
H5G_dense_btree2_name_debug, /* Record debugging callback */
NULL, /* Create debugging context */
NULL /* Destroy debugging context */
@@ -130,6 +132,8 @@ 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 */
+ NULL, /* Create flush dependency */
+ NULL, /* Update flush dependency */
H5G_dense_btree2_corder_debug, /* Record debugging callback */
NULL, /* Create debugging context */
NULL /* Destroy debugging context */
diff --git a/src/H5Gdense.c b/src/H5Gdense.c
index 841b4d3..e919507 100644
--- a/src/H5Gdense.c
+++ b/src/H5Gdense.c
@@ -326,7 +326,7 @@ HDfprintf(stderr, "%s: fheap_id_len = %Zu\n", FUNC, fheap_id_len);
fheap_id_len; /* Fractal heap ID */
bt2_cparam.split_percent = H5G_NAME_BT2_SPLIT_PERC;
bt2_cparam.merge_percent = H5G_NAME_BT2_MERGE_PERC;
- if(NULL == (bt2_name = H5B2_create(f, dxpl_id, &bt2_cparam, NULL)))
+ if(NULL == (bt2_name = H5B2_create(f, dxpl_id, &bt2_cparam, NULL, NULL)))
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create v2 B-tree for name index")
/* Retrieve the v2 B-tree's address in the file */
@@ -346,7 +346,7 @@ HDfprintf(stderr, "%s: linfo->name_bt2_addr = %a\n", FUNC, linfo->name_bt2_addr)
fheap_id_len; /* Fractal heap ID */
bt2_cparam.split_percent = H5G_CORDER_BT2_SPLIT_PERC;
bt2_cparam.merge_percent = H5G_CORDER_BT2_MERGE_PERC;
- if(NULL == (bt2_corder = H5B2_create(f, dxpl_id, &bt2_cparam, NULL)))
+ if(NULL == (bt2_corder = H5B2_create(f, dxpl_id, &bt2_cparam, NULL, NULL)))
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create v2 B-tree for creation order index")
/* Retrieve the v2 B-tree's address in the file */
@@ -438,7 +438,7 @@ HDfprintf(stderr, "%s: HDstrlen(lnk->name) = %Zu, link_size = %Zu\n", FUNC, HDst
HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert link into fractal heap")
/* Open the name index v2 B-tree */
- if(NULL == (bt2_name = H5B2_open(f, dxpl_id, linfo->name_bt2_addr, NULL)))
+ if(NULL == (bt2_name = H5B2_open(f, dxpl_id, linfo->name_bt2_addr, NULL, NULL)))
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index")
/* Create the callback information for v2 B-tree record insertion */
@@ -460,7 +460,7 @@ HDfprintf(stderr, "%s: HDstrlen(lnk->name) = %Zu, link_size = %Zu\n", FUNC, HDst
if(linfo->index_corder) {
/* Open the creation order index v2 B-tree */
HDassert(H5F_addr_defined(linfo->corder_bt2_addr));
- if(NULL == (bt2_corder = H5B2_open(f, dxpl_id, linfo->corder_bt2_addr, NULL)))
+ if(NULL == (bt2_corder = H5B2_open(f, dxpl_id, linfo->corder_bt2_addr, NULL, NULL)))
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for creation order index")
/* Insert the record into the creation order index v2 B-tree */
@@ -557,7 +557,7 @@ H5G__dense_lookup(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
/* Open the name index v2 B-tree */
- if(NULL == (bt2_name = H5B2_open(f, dxpl_id, linfo->name_bt2_addr, NULL)))
+ if(NULL == (bt2_name = H5B2_open(f, dxpl_id, linfo->name_bt2_addr, NULL, NULL)))
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index")
/* Construct the user data for v2 B-tree callback */
@@ -733,7 +733,7 @@ H5G__dense_lookup_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
/* Open the index v2 B-tree */
- if(NULL == (bt2 = H5B2_open(f, dxpl_id, bt2_addr, NULL)))
+ if(NULL == (bt2 = H5B2_open(f, dxpl_id, bt2_addr, NULL, NULL)))
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for index")
/* Construct the user data for v2 B-tree callback */
@@ -1042,7 +1042,7 @@ H5G__dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
/* Open the index v2 B-tree */
- if(NULL == (bt2 = H5B2_open(f, dxpl_id, bt2_addr, NULL)))
+ if(NULL == (bt2 = H5B2_open(f, dxpl_id, bt2_addr, NULL, NULL)))
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for index")
/* Construct the user data for v2 B-tree iterator callback */
@@ -1244,7 +1244,7 @@ H5G__dense_get_name_by_idx(H5F_t *f, hid_t dxpl_id, H5O_linfo_t *linfo,
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
/* Open the index v2 B-tree */
- if(NULL == (bt2 = H5B2_open(f, dxpl_id, bt2_addr, NULL)))
+ if(NULL == (bt2 = H5B2_open(f, dxpl_id, bt2_addr, NULL, NULL)))
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for index")
/* Set up the user data for the v2 B-tree 'record remove' callback */
@@ -1326,7 +1326,7 @@ H5G_dense_remove_fh_cb(const void *obj, size_t UNUSED obj_len, void *_udata)
H5G_bt2_ud_common_t bt2_udata; /* Info for B-tree callbacks */
/* Open the creation order index v2 B-tree */
- if(NULL == (bt2 = H5B2_open(udata->f, udata->dxpl_id, udata->corder_bt2_addr, NULL)))
+ if(NULL == (bt2 = H5B2_open(udata->f, udata->dxpl_id, udata->corder_bt2_addr, NULL, NULL)))
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for creation order index")
/* Set up the user data for the v2 B-tree 'record remove' callback */
@@ -1440,7 +1440,7 @@ H5G__dense_remove(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
/* Open the name index v2 B-tree */
- if(NULL == (bt2 = H5B2_open(f, dxpl_id, linfo->name_bt2_addr, NULL)))
+ if(NULL == (bt2 = H5B2_open(f, dxpl_id, linfo->name_bt2_addr, NULL, NULL)))
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index")
/* Set up the user data for the v2 B-tree 'record remove' callback */
@@ -1577,7 +1577,7 @@ H5G_dense_remove_by_idx_bt2_cb(const void *_record, void *_bt2_udata)
} /* end else */
/* Open the index v2 B-tree */
- if(NULL == (bt2 = H5B2_open(bt2_udata->f, bt2_udata->dxpl_id, bt2_udata->other_bt2_addr, NULL)))
+ if(NULL == (bt2 = H5B2_open(bt2_udata->f, bt2_udata->dxpl_id, bt2_udata->other_bt2_addr, NULL, NULL)))
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for 'other' index")
/* Set the common information for the v2 B-tree remove operation */
@@ -1682,7 +1682,7 @@ H5G__dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
/* Open the index v2 B-tree */
- if(NULL == (bt2 = H5B2_open(f, dxpl_id, bt2_addr, NULL)))
+ if(NULL == (bt2 = H5B2_open(f, dxpl_id, bt2_addr, NULL, NULL)))
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for index")
/* Set up the user data for the v2 B-tree 'remove by index' callback */
@@ -1694,7 +1694,7 @@ H5G__dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
udata.grp_full_path_r = grp_full_path_r;
/* Remove the record from the name index v2 B-tree */
- if(H5B2_remove_by_idx(bt2, dxpl_id, order, n, H5G_dense_remove_by_idx_bt2_cb, &udata) < 0)
+ if(H5B2_remove_by_idx(bt2, dxpl_id, order, n, NULL, H5G_dense_remove_by_idx_bt2_cb, &udata) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTREMOVE, FAIL, "unable to remove link from indexed v2 B-tree")
} /* end if */
else { /* Otherwise, we need to build a table of the links and sort it */
@@ -1776,7 +1776,7 @@ H5G__dense_delete(H5F_t *f, hid_t dxpl_id, H5O_linfo_t *linfo, hbool_t adj_link)
udata.replace_names = FALSE;
/* Delete the name index, adjusting the ref. count on links removed */
- if(H5B2_delete(f, dxpl_id, linfo->name_bt2_addr, NULL, H5G_dense_remove_bt2_cb, &udata) < 0)
+ if(H5B2_delete(f, dxpl_id, linfo->name_bt2_addr, NULL, NULL, H5G_dense_remove_bt2_cb, &udata) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete v2 B-tree for name index")
/* Close the fractal heap */
@@ -1785,7 +1785,7 @@ H5G__dense_delete(H5F_t *f, hid_t dxpl_id, H5O_linfo_t *linfo, hbool_t adj_link)
} /* end if */
else {
/* Delete the name index, without adjusting the ref. count on the links */
- if(H5B2_delete(f, dxpl_id, linfo->name_bt2_addr, NULL, NULL, NULL) < 0)
+ if(H5B2_delete(f, dxpl_id, linfo->name_bt2_addr, NULL, NULL, NULL, NULL) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete v2 B-tree for name index")
} /* end else */
linfo->name_bt2_addr = HADDR_UNDEF;
@@ -1794,7 +1794,7 @@ H5G__dense_delete(H5F_t *f, hid_t dxpl_id, H5O_linfo_t *linfo, hbool_t adj_link)
if(linfo->index_corder) {
/* Delete the creation order index, without adjusting the ref. count on the links */
HDassert(H5F_addr_defined(linfo->corder_bt2_addr));
- if(H5B2_delete(f, dxpl_id, linfo->corder_bt2_addr, NULL, NULL, NULL) < 0)
+ if(H5B2_delete(f, dxpl_id, linfo->corder_bt2_addr, NULL, NULL, NULL, NULL) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete v2 B-tree for creation order index")
linfo->corder_bt2_addr = HADDR_UNDEF;
} /* end if */
diff --git a/src/H5Gobj.c b/src/H5Gobj.c
index 021f4e1..08091a3 100644
--- a/src/H5Gobj.c
+++ b/src/H5Gobj.c
@@ -342,7 +342,7 @@ H5G__obj_get_linfo(const H5O_loc_t *grp_oloc, H5O_linfo_t *linfo, hid_t dxpl_id)
/* Check if we are using "dense" link storage */
if(H5F_addr_defined(linfo->fheap_addr)) {
/* Open the name index v2 B-tree */
- if(NULL == (bt2_name = H5B2_open(grp_oloc->file, dxpl_id, linfo->name_bt2_addr, NULL)))
+ if(NULL == (bt2_name = H5B2_open(grp_oloc->file, dxpl_id, linfo->name_bt2_addr, NULL, NULL)))
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index")
/* Retrieve # of records in "name" B-tree */
diff --git a/src/H5Goh.c b/src/H5Goh.c
index c6115db..9e8d496 100644
--- a/src/H5Goh.c
+++ b/src/H5Goh.c
@@ -361,7 +361,7 @@ H5O_group_bh_info(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5_ih_info_t *bh_info)
/* Check if name index available */
if(H5F_addr_defined(linfo.name_bt2_addr)) {
/* Open the name index v2 B-tree */
- if(NULL == (bt2_name = H5B2_open(f, dxpl_id, linfo.name_bt2_addr, NULL)))
+ if(NULL == (bt2_name = H5B2_open(f, dxpl_id, linfo.name_bt2_addr, NULL, NULL)))
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index")
/* Get name index B-tree size */
@@ -372,7 +372,7 @@ H5O_group_bh_info(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5_ih_info_t *bh_info)
/* Check if creation order index available */
if(H5F_addr_defined(linfo.corder_bt2_addr)) {
/* Open the creation order index v2 B-tree */
- if(NULL == (bt2_corder = H5B2_open(f, dxpl_id, linfo.corder_bt2_addr, NULL)))
+ if(NULL == (bt2_corder = H5B2_open(f, dxpl_id, linfo.corder_bt2_addr, NULL, NULL)))
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for creation order index")
/* Get creation order index B-tree size */
diff --git a/src/H5Gtest.c b/src/H5Gtest.c
index dfdefda..4d41409 100644
--- a/src/H5Gtest.c
+++ b/src/H5Gtest.c
@@ -408,7 +408,7 @@ H5G__new_dense_info_test(hid_t gid, hsize_t *name_count, hsize_t *corder_count)
HGOTO_DONE(FAIL)
/* Open the name index v2 B-tree */
- if(NULL == (bt2_name = H5B2_open(grp->oloc.file, H5AC_dxpl_id, linfo.name_bt2_addr, NULL)))
+ if(NULL == (bt2_name = H5B2_open(grp->oloc.file, H5AC_dxpl_id, linfo.name_bt2_addr, NULL, NULL)))
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index")
/* Retrieve # of records in name index */
@@ -418,7 +418,7 @@ H5G__new_dense_info_test(hid_t gid, hsize_t *name_count, hsize_t *corder_count)
/* Check if there is a creation order index */
if(H5F_addr_defined(linfo.corder_bt2_addr)) {
/* Open the creation order index v2 B-tree */
- if(NULL == (bt2_corder = H5B2_open(grp->oloc.file, H5AC_dxpl_id, linfo.corder_bt2_addr, NULL)))
+ if(NULL == (bt2_corder = H5B2_open(grp->oloc.file, H5AC_dxpl_id, linfo.corder_bt2_addr, NULL, NULL)))
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for creation order index")
/* Retrieve # of records in creation order index */
diff --git a/src/H5HFbtree2.c b/src/H5HFbtree2.c
index 34b74d7..345412f 100644
--- a/src/H5HFbtree2.c
+++ b/src/H5HFbtree2.c
@@ -122,6 +122,8 @@ 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 */
+ NULL, /* Create flush dependency */
+ NULL, /* Update flush dependency */
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 */
@@ -138,6 +140,8 @@ 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 */
+ NULL, /* Create flush dependency */
+ NULL, /* Update flush dependency */
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 */
@@ -154,6 +158,8 @@ 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 */
+ NULL, /* Create flush dependency */
+ NULL, /* Update flush dependency */
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 */
@@ -170,6 +176,8 @@ 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 */
+ NULL, /* Create flush dependency */
+ NULL, /* Update flush dependency */
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 */
diff --git a/src/H5HFhuge.c b/src/H5HFhuge.c
index 6f0b48e..786c850 100644
--- a/src/H5HFhuge.c
+++ b/src/H5HFhuge.c
@@ -157,7 +157,7 @@ H5HF_huge_bt2_create(H5HF_hdr_t *hdr, hid_t dxpl_id)
bt2_cparam.merge_percent = H5HF_HUGE_BT2_MERGE_PERC;
/* Create v2 B-tree for tracking 'huge' objects */
- if(NULL == (hdr->huge_bt2 = H5B2_create(hdr->f, dxpl_id, &bt2_cparam, hdr->f)))
+ if(NULL == (hdr->huge_bt2 = H5B2_create(hdr->f, dxpl_id, &bt2_cparam, hdr->f, NULL)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "can't create v2 B-tree for tracking 'huge' heap objects")
/* Retrieve the v2 B-tree's address in the file */
@@ -339,7 +339,7 @@ HDfprintf(stderr, "%s: obj_size = %Zu\n", FUNC, obj_size);
/* Check if v2 B-tree is open yet */
if(NULL == hdr->huge_bt2) {
/* Open existing v2 B-tree */
- if(NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, dxpl_id, hdr->huge_bt2_addr, hdr->f)))
+ if(NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, dxpl_id, hdr->huge_bt2_addr, hdr->f, NULL)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for tracking 'huge' heap objects")
} /* end if */
} /* end else */
@@ -545,7 +545,7 @@ H5HF_huge_get_obj_len(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
/* Check if v2 B-tree is open yet */
if(NULL == hdr->huge_bt2) {
/* Open existing v2 B-tree */
- if(NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, dxpl_id, hdr->huge_bt2_addr, hdr->f)))
+ if(NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, dxpl_id, hdr->huge_bt2_addr, hdr->f, NULL)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for tracking 'huge' heap objects")
} /* end if */
@@ -636,7 +636,7 @@ H5HF_huge_op_real(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
/* Check if v2 B-tree is open yet */
if(NULL == hdr->huge_bt2) {
/* Open existing v2 B-tree */
- if(NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, dxpl_id, hdr->huge_bt2_addr, hdr->f)))
+ if(NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, dxpl_id, hdr->huge_bt2_addr, hdr->f, NULL)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for tracking 'huge' heap objects")
} /* end if */
@@ -784,7 +784,7 @@ H5HF_huge_write(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
/* Check if v2 B-tree is open yet */
if(NULL == hdr->huge_bt2) {
/* Open existing v2 B-tree */
- if(NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, dxpl_id, hdr->huge_bt2_addr, hdr->f)))
+ if(NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, dxpl_id, hdr->huge_bt2_addr, hdr->f, NULL)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for tracking 'huge' heap objects")
} /* end if */
@@ -914,7 +914,7 @@ H5HF_huge_remove(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id)
/* Check if v2 B-tree is open yet */
if(NULL == hdr->huge_bt2) {
/* Open existing v2 B-tree */
- if(NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, dxpl_id, hdr->huge_bt2_addr, hdr->f)))
+ if(NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, dxpl_id, hdr->huge_bt2_addr, hdr->f, NULL)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for tracking 'huge' heap objects")
} /* end if */
@@ -1037,7 +1037,7 @@ H5HF_huge_term(H5HF_hdr_t *hdr, hid_t dxpl_id)
/* Delete the v2 B-tree */
/* (any v2 B-tree class will work here) */
- if(H5B2_delete(hdr->f, dxpl_id, hdr->huge_bt2_addr, hdr->f, NULL, NULL) < 0)
+ if(H5B2_delete(hdr->f, dxpl_id, hdr->huge_bt2_addr, hdr->f, NULL, NULL, NULL) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "can't delete v2 B-tree")
/* Reset the information about 'huge' objects in the file */
@@ -1105,7 +1105,7 @@ H5HF_huge_delete(H5HF_hdr_t *hdr, hid_t dxpl_id)
} /* end else */
/* Delete the v2 B-tree */
- if(H5B2_delete(hdr->f, dxpl_id, hdr->huge_bt2_addr, hdr->f, op, &udata) < 0)
+ if(H5B2_delete(hdr->f, dxpl_id, hdr->huge_bt2_addr, hdr->f, NULL, op, &udata) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "can't delete v2 B-tree")
done:
diff --git a/src/H5HFstat.c b/src/H5HFstat.c
index b0e1987..802a332 100644
--- a/src/H5HFstat.c
+++ b/src/H5HFstat.c
@@ -155,7 +155,7 @@ H5HF_size(const H5HF_t *fh, hid_t dxpl_id, hsize_t *heap_size)
/* Check for B-tree storage of huge objects in fractal heap */
if(H5F_addr_defined(hdr->huge_bt2_addr)) {
/* Open the huge object index v2 B-tree */
- if(NULL == (bt2 = H5B2_open(hdr->f, dxpl_id, hdr->huge_bt2_addr, hdr->f)))
+ if(NULL == (bt2 = H5B2_open(hdr->f, dxpl_id, hdr->huge_bt2_addr, hdr->f, NULL)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for tracking 'huge' objects")
/* Get the B-tree storage */
diff --git a/src/H5Oainfo.c b/src/H5Oainfo.c
index b207ea2..b6aa4fc 100644
--- a/src/H5Oainfo.c
+++ b/src/H5Oainfo.c
@@ -333,7 +333,7 @@ H5O_ainfo_free(void *mesg)
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_ainfo_delete(H5F_t *f, hid_t dxpl_id, H5O_t UNUSED *open_oh, void *_mesg)
+H5O_ainfo_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, void *_mesg)
{
H5O_ainfo_t *ainfo = (H5O_ainfo_t *)_mesg;
herr_t ret_value = SUCCEED; /* Return value */
@@ -346,7 +346,8 @@ H5O_ainfo_delete(H5F_t *f, hid_t dxpl_id, H5O_t UNUSED *open_oh, void *_mesg)
/* If the object is using "dense" attribute storage, delete it */
if(H5F_addr_defined(ainfo->fheap_addr))
- if(H5A_dense_delete(f, dxpl_id, ainfo) < 0)
+ /*!FIXME use ohdr proxy -NAF */
+ if(H5A_dense_delete(f, dxpl_id, ainfo, open_oh) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free dense attribute storage")
done:
@@ -427,12 +428,14 @@ H5O_ainfo_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst,
*ainfo_dst = *ainfo_src;
if(H5F_addr_defined(ainfo_src->fheap_addr)) {
- /* copy dense attribute */
-
+ /* Prepare to copy dense attributes - actual copy in post_copy */
+
/* Set copied metadata tag */
H5_BEGIN_TAG(dxpl_id, H5AC__COPIED_TAG, NULL);
- if(H5A_dense_create(file_dst, dxpl_id, ainfo_dst) < 0)
+ /*!FIXME Must pass something for the parent, once we have a way to
+ * depend on an object being copied (ohdr proxy?) -NAF */
+ if(H5A_dense_create(file_dst, dxpl_id, ainfo_dst, NULL) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to create dense storage for attributes")
/* Reset metadata tag */
diff --git a/src/H5Oattribute.c b/src/H5Oattribute.c
index 30ec732..9370aa9 100644
--- a/src/H5Oattribute.c
+++ b/src/H5Oattribute.c
@@ -280,7 +280,8 @@ H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
H5O_mesg_operator_t op; /* Wrapper for operator */
/* Create dense storage for attributes */
- if(H5A_dense_create(loc->file, dxpl_id, &ainfo) < 0)
+ /*!FIXME use ohdr proxy -NAF */
+ if(H5A_dense_create(loc->file, dxpl_id, &ainfo, oh) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to create dense storage for attributes")
/* Set up user data for callback */
@@ -507,7 +508,8 @@ H5O_attr_open_by_name(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
/* Check for attributes in dense storage */
if(H5F_addr_defined(ainfo.fheap_addr)) {
/* Open attribute with dense storage */
- if(NULL == (opened_attr = H5A_dense_open(loc->file, dxpl_id, &ainfo, name)))
+ /*!FIXME use ohdr proxy -NAF */
+ if(NULL == (opened_attr = H5A_dense_open(loc->file, dxpl_id, &ainfo, name, oh)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "can't open attribute")
} /* end if */
else {
@@ -1205,7 +1207,7 @@ H5O_attr_rename(const H5O_loc_t *loc, hid_t dxpl_id, const char *old_name,
/* Check for attributes stored densely */
if(H5F_addr_defined(ainfo.fheap_addr)) {
/* Rename the attribute data in dense storage */
- if(H5A_dense_rename(loc->file, dxpl_id, &ainfo, old_name, new_name) < 0)
+ if(H5A_dense_rename(loc->file, dxpl_id, &ainfo, old_name, new_name, oh) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "error updating attribute")
} /* end if */
else {
@@ -1306,7 +1308,8 @@ H5O_attr_iterate_real(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id,
oh = NULL;
/* Iterate over attributes in dense storage */
- if((ret_value = H5A_dense_iterate(loc->file, dxpl_id, loc_id, &ainfo, idx_type, order, skip, last_attr, attr_op, op_data)) < 0)
+ /*!FIXME use ohdr proxy -NAF */
+ if((ret_value = H5A_dense_iterate(loc->file, dxpl_id, loc_id, &ainfo, idx_type, order, skip, oh, last_attr, attr_op, op_data)) < 0)
HERROR(H5E_ATTR, H5E_BADITER, "error iterating over attributes");
} /* end if */
else {
@@ -1420,7 +1423,8 @@ H5O_attr_remove_update(const H5O_loc_t *loc, H5O_t *oh, H5O_ainfo_t *ainfo,
size_t u; /* Local index */
/* Build the table of attributes for this object */
- if(H5A_dense_build_table(loc->file, dxpl_id, ainfo, H5_INDEX_NAME, H5_ITER_NATIVE, &atable) < 0)
+ /*!FIXME use ohdr proxy -NAF */
+ if(H5A_dense_build_table(loc->file, dxpl_id, ainfo, H5_INDEX_NAME, H5_ITER_NATIVE, oh, &atable) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "error building attribute table")
/* Inspect attributes in table for ones that can't be converted back
@@ -1475,7 +1479,8 @@ H5O_attr_remove_update(const H5O_loc_t *loc, H5O_t *oh, H5O_ainfo_t *ainfo,
} /* end for */
/* Remove the dense storage */
- if(H5A_dense_delete(loc->file, dxpl_id, ainfo) < 0)
+ /*!FIXME use ohdr proxy -NAF */
+ if(H5A_dense_delete(loc->file, dxpl_id, ainfo, oh) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete dense attribute storage")
} /* end if */
} /* end if */
@@ -1591,7 +1596,8 @@ H5O_attr_remove(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
/* Check for attributes stored densely */
if(H5F_addr_defined(ainfo.fheap_addr)) {
/* Delete attribute from dense storage */
- if(H5A_dense_remove(loc->file, dxpl_id, &ainfo, name) < 0)
+ /*!FIXME use ohdr proxy -NAF */
+ if(H5A_dense_remove(loc->file, dxpl_id, &ainfo, name, oh) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute in dense storage")
} /* end if */
else {
@@ -1675,7 +1681,8 @@ H5O_attr_remove_by_idx(const H5O_loc_t *loc, H5_index_t idx_type,
/* Check for attributes stored densely */
if(H5F_addr_defined(ainfo.fheap_addr)) {
/* Delete attribute from dense storage */
- if(H5A_dense_remove_by_idx(loc->file, dxpl_id, &ainfo, idx_type, order, n) < 0)
+ /*!FIXME use ohdr proxy -NAF */
+ if(H5A_dense_remove_by_idx(loc->file, dxpl_id, &ainfo, idx_type, order, n, oh) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute in dense storage")
} /* end if */
else {
@@ -1860,7 +1867,8 @@ H5O_attr_exists(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
/* Check for attributes stored densely */
if(H5F_addr_defined(ainfo.fheap_addr)) {
/* Check if attribute exists in dense storage */
- if((ret_value = H5A_dense_exists(loc->file, dxpl_id, &ainfo, name)) < 0)
+ /*!FIXME use ohdr proxy -NAF */
+ if((ret_value = H5A_dense_exists(loc->file, dxpl_id, &ainfo, name, oh)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_BADITER, FAIL, "error checking for existence of attribute")
} /* end if */
else {
@@ -1928,8 +1936,9 @@ H5O_attr_bh_info(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5_ih_info_t *bh_info)
else if(ainfo_exists > 0) {
/* Check if name index available */
if(H5F_addr_defined(ainfo.name_bt2_addr)) {
+ /*!FIXME use ohdr proxy -NAF */
/* Open the name index v2 B-tree */
- if(NULL == (bt2_name = H5B2_open(f, dxpl_id, ainfo.name_bt2_addr, NULL)))
+ if(NULL == (bt2_name = H5B2_open(f, dxpl_id, ainfo.name_bt2_addr, NULL, oh)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index")
/* Get name index B-tree size */
@@ -1939,8 +1948,9 @@ H5O_attr_bh_info(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5_ih_info_t *bh_info)
/* Check if creation order index available */
if(H5F_addr_defined(ainfo.corder_bt2_addr)) {
+ /*!FIXME use ohdr proxy -NAF */
/* Open the creation order index v2 B-tree */
- if(NULL == (bt2_corder = H5B2_open(f, dxpl_id, ainfo.corder_bt2_addr, NULL)))
+ if(NULL == (bt2_corder = H5B2_open(f, dxpl_id, ainfo.corder_bt2_addr, NULL, oh)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for creation order index")
/* Get creation order index B-tree size */
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index 36ba8a4..66744f3 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -437,7 +437,8 @@ typedef struct H5O_storage_chunk_earray_t {
struct H5B2_t; /* Defined in H5B2pkg.h */
typedef struct H5O_storage_chunk_bt2_t {
- struct H5B2_t *bt2;
+ haddr_t dset_ohdr_addr; /* File address dataset's object header */
+ struct H5B2_t *bt2; /* Pointer to b-tree 2 struct */
} H5O_storage_chunk_bt2_t;
typedef struct H5O_storage_chunk_t {
diff --git a/src/H5Otest.c b/src/H5Otest.c
index ca1b426..a056068 100644
--- a/src/H5Otest.c
+++ b/src/H5Otest.c
@@ -193,12 +193,13 @@ H5O_is_attr_empty_test(hid_t oid)
if(H5F_addr_defined(ainfo.fheap_addr)) {
/* Check for any messages in object header */
HDassert(nattrs == 0);
-
+
/* Set metadata tag in dxpl_id */
H5_BEGIN_TAG(H5AC_ind_dxpl_id, loc->addr, FAIL);
/* Open the name index v2 B-tree */
- if(NULL == (bt2_name = H5B2_open(loc->file, H5AC_ind_dxpl_id, ainfo.name_bt2_addr, NULL)))
+ /*!FIXME use ohdr proxy -NAF */
+ if(NULL == (bt2_name = H5B2_open(loc->file, H5AC_ind_dxpl_id, ainfo.name_bt2_addr, NULL, oh)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index")
/* Reset metadata tag in dxpl_id */
@@ -291,7 +292,8 @@ H5O_num_attrs_test(hid_t oid, hsize_t *nattrs)
H5_BEGIN_TAG(H5AC_ind_dxpl_id, loc->addr, FAIL);
/* Open the name index v2 B-tree */
- if(NULL == (bt2_name = H5B2_open(loc->file, H5AC_ind_dxpl_id, ainfo.name_bt2_addr, NULL)))
+ /*!FIXME use ohdr proxy -NAF */
+ if(NULL == (bt2_name = H5B2_open(loc->file, H5AC_ind_dxpl_id, ainfo.name_bt2_addr, NULL, oh)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index")
/* Reset metadata tag in dxpl_id */
@@ -379,7 +381,8 @@ H5O_attr_dense_info_test(hid_t oid, hsize_t *name_count, hsize_t *corder_count)
HGOTO_DONE(FAIL)
/* Open the name index v2 B-tree */
- if(NULL == (bt2_name = H5B2_open(loc->file, H5AC_ind_dxpl_id, ainfo.name_bt2_addr, NULL)))
+ /*!FIXME use ohdr proxy -NAF */
+ if(NULL == (bt2_name = H5B2_open(loc->file, H5AC_ind_dxpl_id, ainfo.name_bt2_addr, NULL, oh)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index")
/* Retrieve # of records in name index */
@@ -389,7 +392,8 @@ H5O_attr_dense_info_test(hid_t oid, hsize_t *name_count, hsize_t *corder_count)
/* Check if there is a creation order index */
if(H5F_addr_defined(ainfo.corder_bt2_addr)) {
/* Open the creation order index v2 B-tree */
- if(NULL == (bt2_corder = H5B2_open(loc->file, H5AC_ind_dxpl_id, ainfo.corder_bt2_addr, NULL)))
+ /*!FIXME use ohdr proxy -NAF */
+ if(NULL == (bt2_corder = H5B2_open(loc->file, H5AC_ind_dxpl_id, ainfo.corder_bt2_addr, NULL, oh)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for creation order index")
/* Retrieve # of records in creation order index */
diff --git a/src/H5SM.c b/src/H5SM.c
index 62efb50..c71d6e5 100644
--- a/src/H5SM.c
+++ b/src/H5SM.c
@@ -481,7 +481,7 @@ H5SM_create_index(H5F_t *f, H5SM_index_header_t *header, hid_t dxpl_id)
bt2_cparam.rrec_size = (uint32_t)H5SM_SOHM_ENTRY_SIZE(f);
bt2_cparam.split_percent = H5SM_B2_SPLIT_PERCENT;
bt2_cparam.merge_percent = H5SM_B2_MERGE_PERCENT;
- if(NULL == (bt2 = H5B2_create(f, dxpl_id, &bt2_cparam, f)))
+ if(NULL == (bt2 = H5B2_create(f, dxpl_id, &bt2_cparam, f, NULL)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTCREATE, FAIL, "B-tree creation failed for SOHM index")
/* Retrieve the v2 B-tree's address in the file */
@@ -581,7 +581,7 @@ H5SM_delete_index(H5F_t *f, H5SM_index_header_t *header, hid_t dxpl_id,
HDassert(header->index_type == H5SM_BTREE);
/* Delete the B-tree. */
- if(H5B2_delete(f, dxpl_id, header->index_addr, f, NULL, NULL) < 0)
+ if(H5B2_delete(f, dxpl_id, header->index_addr, f, NULL, NULL, NULL) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "unable to delete B-tree")
/* Revert to list unless B-trees can have zero records */
@@ -724,7 +724,7 @@ H5SM_convert_list_to_btree(H5F_t *f, H5SM_index_header_t *header,
bt2_cparam.rrec_size = (uint32_t)H5SM_SOHM_ENTRY_SIZE(f);
bt2_cparam.split_percent = H5SM_B2_SPLIT_PERCENT;
bt2_cparam.merge_percent = H5SM_B2_MERGE_PERCENT;
- if(NULL == (bt2 = H5B2_create(f, dxpl_id, &bt2_cparam, f)))
+ if(NULL == (bt2 = H5B2_create(f, dxpl_id, &bt2_cparam, f, NULL)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTCREATE, FAIL, "B-tree creation failed for SOHM index")
/* Retrieve the v2 B-tree's address in the file */
@@ -837,7 +837,7 @@ H5SM_convert_btree_to_list(H5F_t * f, H5SM_index_header_t * header, hid_t dxpl_i
/* Delete the B-tree and have messages copy themselves to the
* list as they're deleted
*/
- if(H5B2_delete(f, dxpl_id, btree_addr, f, H5SM_bt2_convert_to_list_op, list) < 0)
+ if(H5B2_delete(f, dxpl_id, btree_addr, f, NULL, H5SM_bt2_convert_to_list_op, list) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "unable to delete B-tree")
done:
@@ -1320,7 +1320,7 @@ H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
HDassert(header->index_type == H5SM_BTREE);
/* Open the index v2 B-tree */
- if(NULL == (bt2 = H5B2_open(f, dxpl_id, header->index_addr, f)))
+ if(NULL == (bt2 = H5B2_open(f, dxpl_id, header->index_addr, f, NULL)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for SOHM index")
if(defer) {
@@ -1448,7 +1448,7 @@ H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
/* Open the index v2 B-tree, if it isn't already */
if(NULL == bt2) {
- if(NULL == (bt2 = H5B2_open(f, dxpl_id, header->index_addr, f)))
+ if(NULL == (bt2 = H5B2_open(f, dxpl_id, header->index_addr, f, NULL)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for SOHM index")
} /* end if */
@@ -1817,7 +1817,7 @@ H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
HDassert(header->index_type == H5SM_BTREE);
/* Open the index v2 B-tree */
- if(NULL == (bt2 = H5B2_open(f, dxpl_id, header->index_addr, f)))
+ if(NULL == (bt2 = H5B2_open(f, dxpl_id, header->index_addr, f, NULL)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for SOHM index")
/* If this returns failure, it means that the message wasn't found.
@@ -1847,7 +1847,7 @@ H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
else {
/* Open the index v2 B-tree, if it isn't already */
if(NULL == bt2) {
- if(NULL == (bt2 = H5B2_open(f, dxpl_id, header->index_addr, f)))
+ if(NULL == (bt2 = H5B2_open(f, dxpl_id, header->index_addr, f, NULL)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for SOHM index")
} /* end if */
@@ -2189,7 +2189,7 @@ H5SM_get_refcount(H5F_t *f, hid_t dxpl_id, unsigned type_id,
HDassert(header->index_type == H5SM_BTREE);
/* Open the index v2 B-tree */
- if(NULL == (bt2 = H5B2_open(f, dxpl_id, header->index_addr, f)))
+ if(NULL == (bt2 = H5B2_open(f, dxpl_id, header->index_addr, f, NULL)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for SOHM index")
/* Look up the message in the v2 B-tree */
@@ -2705,7 +2705,7 @@ H5SM_ih_size(H5F_t *f, hid_t dxpl_id, hsize_t *hdr_size, H5_ih_info_t *ih_info)
if(table->indexes[u].index_type == H5SM_BTREE) {
if(H5F_addr_defined(table->indexes[u].index_addr)) {
/* Open the index v2 B-tree */
- if(NULL == (bt2 = H5B2_open(f, dxpl_id, table->indexes[u].index_addr, f)))
+ if(NULL == (bt2 = H5B2_open(f, dxpl_id, table->indexes[u].index_addr, f, NULL)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for SOHM index")
if(H5B2_size(bt2, dxpl_id, &(ih_info->index_size)) < 0)
diff --git a/src/H5SMbtree2.c b/src/H5SMbtree2.c
index daa1e4f..62b45f0 100644
--- a/src/H5SMbtree2.c
+++ b/src/H5SMbtree2.c
@@ -67,6 +67,8 @@ 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 */
+ NULL, /* Create flush dependency */
+ NULL, /* Update flush dependency */
H5SM_bt2_debug, /* Record debugging callback */
H5SM_bt2_crt_dbg_context, /* Create debugging context */
H5SM_bt2_dst_context /* Destroy debugging context */