diff options
39 files changed, 2898 insertions, 432 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); @@ -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 */ @@ -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 */ diff --git a/test/btree2.c b/test/btree2.c index d8abc84..f9a8982 100644 --- a/test/btree2.c +++ b/test/btree2.c @@ -138,7 +138,7 @@ create_btree(H5F_t *f, hid_t dxpl, const H5B2_create_t *cparam, H5B2_t **bt2, haddr_t *bt2_addr) { /* Create the v2 B-tree & get its address */ - if(NULL == (*bt2 = H5B2_create(f, dxpl, cparam, f))) + if(NULL == (*bt2 = H5B2_create(f, dxpl, cparam, f, NULL))) FAIL_STACK_ERROR if(H5B2_get_addr(*bt2, bt2_addr/*out*/) < 0) FAIL_STACK_ERROR @@ -177,7 +177,7 @@ reopen_btree(H5F_t *f, hid_t dxpl, H5B2_t **bt2, haddr_t bt2_addr, FAIL_STACK_ERROR /* Re-open v2 B-tree */ - if(NULL == (*bt2 = H5B2_open(f, dxpl, bt2_addr, f))) + if(NULL == (*bt2 = H5B2_open(f, dxpl, bt2_addr, f, NULL))) FAIL_STACK_ERROR } /* end if */ @@ -2854,7 +2854,7 @@ HDfprintf(stderr,"curr_time=%lu\n",(unsigned long)curr_time); } /* Re-open v2 B-tree */ - if(NULL == (bt2 = H5B2_open(f, dxpl, bt2_addr, f))) + if(NULL == (bt2 = H5B2_open(f, dxpl, bt2_addr, f, NULL))) FAIL_STACK_ERROR /* Check up on B-tree after re-open */ @@ -6551,7 +6551,7 @@ HDfprintf(stderr, "curr_time = %lu\n", (unsigned long)curr_time); } /* end for */ /* Re-open v2 B-tree */ - if(NULL == (bt2 = H5B2_open(f, dxpl, bt2_addr, f))) + if(NULL == (bt2 = H5B2_open(f, dxpl, bt2_addr, f, NULL))) FAIL_STACK_ERROR /* Remove all records */ @@ -6636,7 +6636,7 @@ HDfprintf(stderr, "curr_time = %lu\n", (unsigned long)curr_time); } /* Re-open v2 B-tree */ - if(NULL == (bt2 = H5B2_open(f, dxpl, bt2_addr, f))) + if(NULL == (bt2 = H5B2_open(f, dxpl, bt2_addr, f, NULL))) FAIL_STACK_ERROR /* Remove all records */ @@ -6646,7 +6646,7 @@ HDfprintf(stderr, "curr_time = %lu\n", (unsigned long)curr_time); rrecord = HSIZET_MAX; /* Remove random record */ - if(H5B2_remove_by_idx(bt2, dxpl, H5_ITER_INC, (hsize_t)rem_idx, remove_cb, &rrecord) < 0) + if(H5B2_remove_by_idx(bt2, dxpl, H5_ITER_INC, (hsize_t)rem_idx, NULL, remove_cb, &rrecord) < 0) FAIL_STACK_ERROR /* Make certain that the record value is correct */ @@ -6725,14 +6725,14 @@ HDfprintf(stderr, "curr_time = %lu\n", (unsigned long)curr_time); } /* Re-open v2 B-tree */ - if(NULL == (bt2 = H5B2_open(f, dxpl, bt2_addr, f))) + if(NULL == (bt2 = H5B2_open(f, dxpl, bt2_addr, f, NULL))) FAIL_STACK_ERROR /* Remove all records */ for(u = 0; u < INSERT_MANY; u++) { /* Remove first record */ rrecord = HSIZET_MAX; - if(H5B2_remove_by_idx(bt2, dxpl, H5_ITER_INC, (hsize_t)0, remove_cb, &rrecord) < 0) + if(H5B2_remove_by_idx(bt2, dxpl, H5_ITER_INC, (hsize_t)0, NULL, remove_cb, &rrecord) < 0) FAIL_STACK_ERROR /* Make certain that the record value is correct */ @@ -6811,14 +6811,14 @@ HDfprintf(stderr, "curr_time = %lu\n", (unsigned long)curr_time); } /* Re-open v2 B-tree */ - if(NULL == (bt2 = H5B2_open(f, dxpl, bt2_addr, f))) + if(NULL == (bt2 = H5B2_open(f, dxpl, bt2_addr, f, NULL))) FAIL_STACK_ERROR /* Remove all records */ for(u = 0; u < INSERT_MANY; u++) { /* Remove last record */ rrecord = HSIZET_MAX; - if(H5B2_remove_by_idx(bt2, dxpl, H5_ITER_DEC, (hsize_t)0, remove_cb, &rrecord) < 0) + if(H5B2_remove_by_idx(bt2, dxpl, H5_ITER_DEC, (hsize_t)0, NULL, remove_cb, &rrecord) < 0) FAIL_STACK_ERROR /* Make certain that the record value is correct */ @@ -7173,7 +7173,7 @@ test_delete(hid_t fapl, const H5B2_create_t *cparam) /* * Delete v2 B-tree */ - if(H5B2_delete(f, dxpl, bt2_addr, f, NULL, NULL) < 0) + if(H5B2_delete(f, dxpl, bt2_addr, f, NULL, NULL, NULL) < 0) FAIL_STACK_ERROR /* Close the file */ @@ -7231,7 +7231,7 @@ test_delete(hid_t fapl, const H5B2_create_t *cparam) /* * Delete v2 B-tree */ - if(H5B2_delete(f, H5P_DATASET_XFER_DEFAULT, bt2_addr, f, NULL, NULL) < 0) + if(H5B2_delete(f, H5P_DATASET_XFER_DEFAULT, bt2_addr, f, NULL, NULL, NULL) < 0) FAIL_STACK_ERROR /* Close file */ @@ -7289,7 +7289,7 @@ test_delete(hid_t fapl, const H5B2_create_t *cparam) /* * Delete v2 B-tree */ - if(H5B2_delete(f, dxpl, bt2_addr, f, NULL, NULL) < 0) + if(H5B2_delete(f, dxpl, bt2_addr, f, NULL, NULL, NULL) < 0) FAIL_STACK_ERROR /* Close file */ @@ -7347,7 +7347,7 @@ test_delete(hid_t fapl, const H5B2_create_t *cparam) /* * Delete v2 B-tree */ - if(H5B2_delete(f, dxpl, bt2_addr, f, NULL, NULL) < 0) + if(H5B2_delete(f, dxpl, bt2_addr, f, NULL, NULL, NULL) < 0) FAIL_STACK_ERROR /* Close file */ diff --git a/test/swmr_addrem_writer.c b/test/swmr_addrem_writer.c index ddfcd5c..24c485f 100644 --- a/test/swmr_addrem_writer.c +++ b/test/swmr_addrem_writer.c @@ -8,7 +8,7 @@ open_skeleton(const char *filename, unsigned verbose) hid_t fid; /* File ID for new HDF5 file */
hid_t fapl; /* File access property list */
hid_t sid; /* Dataspace ID */
- hsize_t dim; /* Dataspace dimension */
+ hsize_t dim[2]; /* Dataspace dimension */
unsigned u, v; /* Local index variable */
/* Create file access property list */
@@ -54,11 +54,11 @@ printf("mdc_config.epoch_length = %lu\n", (unsigned long)mdc_config.epoch_length return(-1);
if((sid = H5Dget_space(symbol_info[u][v].dsid)) < 0)
return -1;
- if(1 != H5Sget_simple_extent_ndims(sid))
+ if(2 != H5Sget_simple_extent_ndims(sid))
return -1;
- if(H5Sget_simple_extent_dims(sid, &dim, NULL) < 0)
+ if(H5Sget_simple_extent_dims(sid, dim, NULL) < 0)
return -1;
- symbol_info[u][v].nrecords = (hsize_t)dim;
+ symbol_info[u][v].nrecords = dim[1];
} /* end for */
return(fid);
@@ -69,7 +69,8 @@ addrem_records(hid_t fid, unsigned verbose, unsigned long nops, unsigned long fl {
hid_t tid; /* Datatype ID for records */
hid_t mem_sid; /* Memory dataspace ID */
- hsize_t start, count; /* Hyperslab selection values */
+ hsize_t start[2] = {0, 0}, count[2] = {1, 1}; /* Hyperslab selection values */
+ hsize_t dim[2] = {1, 0}; /* Dataspace dimensions */
symbol_t buf[MAX_SIZE_CHANGE]; /* Write buffer */
H5AC_cache_config_t mdc_config_orig; /* Original metadata cache configuration */
H5AC_cache_config_t mdc_config_cork; /* Corked metadata cache configuration */
@@ -80,8 +81,7 @@ addrem_records(hid_t fid, unsigned verbose, unsigned long nops, unsigned long fl memset(&buf, 0, sizeof(buf));
/* Create a dataspace for the record to add */
- count = 1;
- if((mem_sid = H5Screate_simple(1, &count, NULL)) < 0)
+ if((mem_sid = H5Screate_simple(2, count, NULL)) < 0)
return(-1);
/* Create datatype for appending records */
@@ -110,22 +110,22 @@ addrem_records(hid_t fid, unsigned verbose, unsigned long nops, unsigned long fl symbol = choose_dataset();
/* Decide whether to shrink or expand, and by how much */
- count = (hsize_t)random() % (MAX_SIZE_CHANGE * 2) + 1;
+ count[1] = (hsize_t)random() % (MAX_SIZE_CHANGE * 2) + 1;
- if(count > MAX_SIZE_CHANGE) {
+ if(count[1] > MAX_SIZE_CHANGE) {
/* Add records */
- count -= MAX_SIZE_CHANGE;
+ count[1] -= MAX_SIZE_CHANGE;
/* Set the buffer's IDs (equal to its position) */
- for(v=0; v<count; v++)
+ for(v=0; v<count[1]; v++)
buf[v].rec_id = (uint64_t)symbol->nrecords + (uint64_t)v;
/* Set the memory space to the correct size */
- if(H5Sset_extent_simple(mem_sid, 1, &count, NULL) < 0)
+ if(H5Sset_extent_simple(mem_sid, 2, count, NULL) < 0)
return(-1);
/* Get the coordinates to write */
- start = symbol->nrecords;
+ start[1] = symbol->nrecords;
/* Cork the metadata cache, to prevent the object header from being
* flushed before the data has been written */
@@ -133,8 +133,9 @@ addrem_records(hid_t fid, unsigned verbose, unsigned long nops, unsigned long fl return(-1);*/
/* Extend the dataset's dataspace to hold the new record */
- symbol->nrecords+= count;
- if(H5Dset_extent(symbol->dsid, &symbol->nrecords) < 0)
+ symbol->nrecords+= count[1];
+ dim[1] = symbol->nrecords;
+ if(H5Dset_extent(symbol->dsid, dim) < 0)
return(-1);
/* Get the dataset's dataspace */
@@ -142,7 +143,7 @@ addrem_records(hid_t fid, unsigned verbose, unsigned long nops, unsigned long fl return(-1);
/* Choose the last record in the dataset */
- if(H5Sselect_hyperslab(file_sid, H5S_SELECT_SET, &start, NULL, &count, NULL) < 0)
+ if(H5Sselect_hyperslab(file_sid, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
return(-1);
/* Write record to the dataset */
@@ -159,11 +160,12 @@ addrem_records(hid_t fid, unsigned verbose, unsigned long nops, unsigned long fl } /* end if */
else {
/* Shrink the dataset's dataspace */
- if(count > symbol->nrecords)
+ if(count[1] > symbol->nrecords)
symbol->nrecords = 0;
else
- symbol->nrecords -= count;
- if(H5Dset_extent(symbol->dsid, &symbol->nrecords) < 0)
+ symbol->nrecords -= count[1];
+ dim[1] = symbol->nrecords;
+ if(H5Dset_extent(symbol->dsid, dim) < 0)
return(-1);
} /* end else */
@@ -267,7 +269,7 @@ int main(int argc, const char *argv[]) /* Create randomized set of numbers */
curr_time = time(NULL);
- srandom((unsigned)curr_time);
+ //srandom((unsigned)curr_time);
/* Emit informational message */
if(verbose)
diff --git a/test/swmr_generator.c b/test/swmr_generator.c index a19f70f..35cd5c6 100644 --- a/test/swmr_generator.c +++ b/test/swmr_generator.c @@ -13,9 +13,9 @@ gen_skeleton(const char *filename, unsigned verbose, int comp_level, hid_t tid; /* Datatype for dataset elements */
hid_t sid; /* Dataspace ID */
hid_t aid; /* Attribute ID */
- hsize_t dims = 0; /* Dataset starting dimensions */
- hsize_t max_dims = H5S_UNLIMITED; /* Dataset maximum dimensions */
- hsize_t chunk_dims = CHUNK_SIZE; /* Chunk dimensions */
+ hsize_t dims[2] = {1, 0}; /* Dataset starting dimensions */
+ hsize_t max_dims[2] = {1, H5S_UNLIMITED}; /* Dataset maximum dimensions */
+ hsize_t chunk_dims[2] = {1, CHUNK_SIZE}; /* Chunk dimensions */
#ifdef FILLVAL_WORKS
symbol_t fillval; /* Dataset fill value */
#endif /* FILLVAL_WORKS */
@@ -30,6 +30,8 @@ gen_skeleton(const char *filename, unsigned verbose, int comp_level, if(strcmp(index_type, "b1"))
if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
return(-1);
+ if(!strcmp(index_type, "b2"))
+ max_dims[0] = H5S_UNLIMITED;
#ifdef QAK
/* Increase the initial size of the metadata cache */
@@ -95,13 +97,13 @@ printf("mdc_config.epoch_length = %lu\n", (unsigned long)mdc_config.epoch_length return(-1);
/* Create dataspace for creating datasets */
- if((sid = H5Screate_simple(1, &dims, &max_dims)) < 0)
+ if((sid = H5Screate_simple(2, dims, max_dims)) < 0)
return(-1);
/* Create dataset creation property list */
if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
return(-1);
- if(H5Pset_chunk(dcpl, 1, &chunk_dims) < 0)
+ if(H5Pset_chunk(dcpl, 2, chunk_dims) < 0)
return(-1);
if(comp_level >= 0) {
if(H5Pset_deflate(dcpl, (unsigned)comp_level) < 0)
@@ -158,7 +160,7 @@ usage(void) printf("Usage error!\n");
printf("Usage: swmr_generator [-q] [-c <deflate compression level>] [-i <index type>]\n");
printf("<deflate compression level> should be -1 (for no compression) or 0-9\n");
- printf("<index type> should be b1, b2, fa, or ea (fa and b2 not yet implemented)\n");
+ printf("<index type> should be b1, b2, fa, or ea (fa not yet implemented)\n");
printf("Defaults to verbose (no '-q' given), no compression ('-c -1') and v1 b-tree\n");
printf(" (-i b1)");
exit(1);
@@ -189,7 +191,8 @@ int main(int argc, const char *argv[]) case 'i':
index_type = argv[u + 1];
if(strcmp(index_type, "b1")
- && strcmp(index_type, "ea"))
+ && strcmp(index_type, "ea")
+ && strcmp(index_type, "b2"))
usage();
u += 2;
break;
diff --git a/test/swmr_reader.c b/test/swmr_reader.c index 48cf4bd..cdfc1f9 100644 --- a/test/swmr_reader.c +++ b/test/swmr_reader.c @@ -10,7 +10,7 @@ check_dataset(hid_t fid, unsigned verbose, const char *sym_name, symbol_t *recor hid_t dsid; /* Dataset ID */
hid_t file_sid; /* Dataset's space ID */
hssize_t snpoints; /* Number of elements in dataset */
- hsize_t start, count = 1; /* Hyperslab selection values */
+ hsize_t start[2] = {0, 0}, count[2] = {1, 1}; /* Hyperslab selection values */
/* Open dataset for symbol */
if((dsid = H5Dopen2(fid, sym_name, H5P_DEFAULT)) < 0)
@@ -31,8 +31,8 @@ check_dataset(hid_t fid, unsigned verbose, const char *sym_name, symbol_t *recor /* Check if there are records for symbol */
if(snpoints > 0) {
/* Choose the last record in the dataset */
- start = (hsize_t)(snpoints - 1);
- if(H5Sselect_hyperslab(file_sid, H5S_SELECT_SET, &start, NULL, &count, NULL) < 0)
+ start[1] = (hsize_t)(snpoints - 1);
+ if(H5Sselect_hyperslab(file_sid, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
return(-1);
/* Read record from dataset */
@@ -41,7 +41,7 @@ check_dataset(hid_t fid, unsigned verbose, const char *sym_name, symbol_t *recor return(-1);
/* Verify record value */
- if(record->rec_id != start) {
+ if(record->rec_id != start[1]) {
printf("Incorrect record value!\n");
printf("Symbol = '%s', # of records = %lld, record->rec_id = %llu\n", sym_name, (long long)snpoints, (unsigned long long)record->rec_id);
return(-1);
diff --git a/test/swmr_remove_reader.c b/test/swmr_remove_reader.c index 61d5aab..518ea4e 100644 --- a/test/swmr_remove_reader.c +++ b/test/swmr_remove_reader.c @@ -10,7 +10,7 @@ check_dataset(hid_t fid, unsigned verbose, const char *sym_name, symbol_t *recor hid_t dsid; /* Dataset ID */
hid_t file_sid; /* Dataset's space ID */
hssize_t snpoints; /* Number of elements in dataset */
- hsize_t start, count = 1; /* Hyperslab selection values */
+ hsize_t start[2] = {0, 0}, count[2] = {1, 1}; /* Hyperslab selection values */
/* Open dataset for symbol */
if((dsid = H5Dopen2(fid, sym_name, H5P_DEFAULT)) < 0)
@@ -32,10 +32,10 @@ check_dataset(hid_t fid, unsigned verbose, const char *sym_name, symbol_t *recor if(snpoints > 0) {
/* Choose a random record in the dataset, choosing the last record half
* the time */
- start = (hsize_t)(random() % (snpoints * 2));
- if(start > (hsize_t)(snpoints - 1))
- start = (hsize_t)(snpoints - 1);
- if(H5Sselect_hyperslab(file_sid, H5S_SELECT_SET, &start, NULL, &count, NULL) < 0)
+ start[1] = (hsize_t)(random() % (snpoints * 2));
+ if(start[1] > (hsize_t)(snpoints - 1))
+ start[1] = (hsize_t)(snpoints - 1);
+ if(H5Sselect_hyperslab(file_sid, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
return(-1);
/* Read record from dataset */
@@ -54,7 +54,7 @@ check_dataset(hid_t fid, unsigned verbose, const char *sym_name, symbol_t *recor /* Verify record value - note that it may be the fill value, because the
* chunk may be deleted before the object header has the updated
* dimensions */
- if(record->rec_id != start && record->rec_id != (uint64_t)0) {
+ if(record->rec_id != start[1] && record->rec_id != (uint64_t)0) {
printf("Incorrect record value!\n");
printf("Symbol = '%s', # of records = %lld, record->rec_id = %llx\n", sym_name, (long long)snpoints, (unsigned long long)record->rec_id);
return(-1);
diff --git a/test/swmr_remove_writer.c b/test/swmr_remove_writer.c index 576fae8..1570438 100644 --- a/test/swmr_remove_writer.c +++ b/test/swmr_remove_writer.c @@ -8,7 +8,7 @@ open_skeleton(const char *filename, unsigned verbose) hid_t fid; /* File ID for new HDF5 file */
hid_t fapl; /* File access property list */
hid_t sid; /* Dataspace ID */
- hsize_t dim; /* Dataspace dimension */
+ hsize_t dim[2]; /* Dataspace dimensions */
unsigned u, v; /* Local index variable */
/* Create file access property list */
@@ -54,11 +54,11 @@ printf("mdc_config.epoch_length = %lu\n", (unsigned long)mdc_config.epoch_length return(-1);
if((sid = H5Dget_space(symbol_info[u][v].dsid)) < 0)
return -1;
- if(1 != H5Sget_simple_extent_ndims(sid))
+ if(2 != H5Sget_simple_extent_ndims(sid))
return -1;
- if(H5Sget_simple_extent_dims(sid, &dim, NULL) < 0)
+ if(H5Sget_simple_extent_dims(sid, dim, NULL) < 0)
return -1;
- symbol_info[u][v].nrecords = (hsize_t)dim;
+ symbol_info[u][v].nrecords = dim[1];
} /* end for */
return(fid);
@@ -68,6 +68,7 @@ static int remove_records(hid_t fid, unsigned verbose, unsigned long nshrinks, unsigned long flush_count)
{
unsigned long shrink_to_flush; /* # of removals before flush */
+ hsize_t dim[2] = {1,0}; /* Dataspace dimensions */
unsigned long u, v; /* Local index variables */
/* Remove records from random datasets, according to frequency distribution */
@@ -85,7 +86,8 @@ remove_records(hid_t fid, unsigned verbose, unsigned long nshrinks, unsigned lon symbol->nrecords = 0;
else
symbol->nrecords -= remove_size;
- if(H5Dset_extent(symbol->dsid, &symbol->nrecords) < 0)
+ dim[1] = symbol->nrecords;
+ if(H5Dset_extent(symbol->dsid, dim) < 0)
return(-1);
/* Check for flushing file */
diff --git a/test/swmr_sparse_reader.c b/test/swmr_sparse_reader.c index dfed4dc..eff199b 100644 --- a/test/swmr_sparse_reader.c +++ b/test/swmr_sparse_reader.c @@ -11,7 +11,7 @@ check_dataset(hid_t fid, unsigned verbose, const symbol_info_t *symbol, symbol_t {
hid_t dsid; /* Dataset ID */
hid_t file_sid; /* Dataset's space ID */
- hsize_t start, count = 1; /* Hyperslab selection values */
+ hsize_t start[2] = {0, 0}, count[2] = {1, 1}; /* Hyperslab selection values */
/* Open dataset for symbol */
if((dsid = H5Dopen2(fid, symbol->name, H5P_DEFAULT)) < 0)
@@ -23,8 +23,8 @@ check_dataset(hid_t fid, unsigned verbose, const symbol_info_t *symbol, symbol_t /* Choose the random record in the dataset (will be the same as chosen by
* the writer) */
- start = (hsize_t)random() % symbol->nrecords;;
- if(H5Sselect_hyperslab(file_sid, H5S_SELECT_SET, &start, NULL, &count, NULL) < 0)
+ start[1] = (hsize_t)random() % symbol->nrecords;
+ if(H5Sselect_hyperslab(file_sid, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
return(-1);
/* Emit informational message */
@@ -39,14 +39,14 @@ check_dataset(hid_t fid, unsigned verbose, const symbol_info_t *symbol, symbol_t * header chunk afer the first. Until this is fixed, just allow the read
* value to be 0. */
record->rec_id = (uint64_t)ULLONG_MAX;
-#else /* FILLVAL_WORKS */
+#else /* OHDR_DEPS_WORK */
record->rec_id = (uint64_t)0;
-#endif /* FILLVAL_WORKS */
+#endif /* OHDR_DEPS_WORK */
if(H5Dread(dsid, symbol_tid, rec_sid, file_sid, H5P_DEFAULT, record) < 0)
return(-1);
/* Verify record value */
- if(record->rec_id != start
+ if(record->rec_id != start[1]
#ifndef OHDR_DEPS_WORK
&& record->rec_id != (uint64_t)0
#endif
diff --git a/test/swmr_sparse_writer.c b/test/swmr_sparse_writer.c index 211bec9..8afb538 100644 --- a/test/swmr_sparse_writer.c +++ b/test/swmr_sparse_writer.c @@ -72,12 +72,13 @@ add_records(hid_t fid, unsigned verbose, unsigned long nrecords, unsigned long f {
hid_t tid; /* Datatype ID for records */
hid_t mem_sid; /* Memory dataspace ID */
- hsize_t start, count = 1; /* Hyperslab selection values */
+ hsize_t start[2] = {0, 0}, count[2] = {1, 1}; /* Hyperslab selection values */
symbol_t record; /* The record to add to the dataset */
H5AC_cache_config_t mdc_config_orig; /* Original metadata cache configuration */
H5AC_cache_config_t mdc_config_cork; /* Corked metadata cache configuration */
unsigned long rec_to_flush; /* # of records left to write before flush */
volatile int dummy; /* Dummy varialbe for busy sleep */
+ hsize_t dim[2] = {1,0}; /* Dataspace dimensions */
unsigned long u, v; /* Local index variables */
/* Reset the record */
@@ -122,8 +123,9 @@ add_records(hid_t fid, unsigned verbose, unsigned long nrecords, unsigned long f * add the sequence attribute */
if(symbol->nrecords == 0) {
symbol->nrecords = nrecords / 5;
+ dim[1] = symbol->nrecords;
- if(H5Dset_extent(symbol->dsid, &symbol->nrecords) < 0)
+ if(H5Dset_extent(symbol->dsid, dim) < 0)
return(-1);
if((file_sid = H5Screate(H5S_SCALAR)) < 0)
@@ -137,17 +139,17 @@ add_records(hid_t fid, unsigned verbose, unsigned long nrecords, unsigned long f return(-1);
/* Get the coordinate to write */
- start = (hsize_t)random() % symbol->nrecords;
+ start[1] = (hsize_t)random() % symbol->nrecords;
/* Set the record's ID (equal to its position) */
- record.rec_id = start;
+ record.rec_id = start[1];
/* Get the dataset's dataspace */
if((file_sid = H5Dget_space(symbol->dsid)) < 0)
return(-1);
/* Choose a random record in the dataset */
- if(H5Sselect_hyperslab(file_sid, H5S_SELECT_SET, &start, NULL, &count, NULL) < 0)
+ if(H5Sselect_hyperslab(file_sid, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
return(-1);
/* Write record to the dataset */
diff --git a/test/swmr_writer.c b/test/swmr_writer.c index c584f60..d465d70 100644 --- a/test/swmr_writer.c +++ b/test/swmr_writer.c @@ -59,7 +59,8 @@ add_records(hid_t fid, unsigned verbose, unsigned long nrecords, unsigned long f {
hid_t tid; /* Datatype ID for records */
hid_t mem_sid; /* Memory dataspace ID */
- hsize_t start, count = 1; /* Hyperslab selection values */
+ hsize_t start[2] = {0, 0}, count[2] = {1, 1}; /* Hyperslab selection values */
+ hsize_t dim[2] = {1, 0}; /* Dataspace dimensions */
symbol_t record; /* The record to add to the dataset */
H5AC_cache_config_t mdc_config_orig; /* Original metadata cache configuration */
H5AC_cache_config_t mdc_config_cork; /* Corked metadata cache configuration */
@@ -102,7 +103,7 @@ add_records(hid_t fid, unsigned verbose, unsigned long nrecords, unsigned long f record.rec_id = symbol->nrecords;
/* Get the coordinate to write */
- start = symbol->nrecords;
+ start[1] = symbol->nrecords;
/* Cork the metadata cache, to prevent the object header from being
* flushed before the data has been written */
@@ -111,7 +112,8 @@ add_records(hid_t fid, unsigned verbose, unsigned long nrecords, unsigned long f /* Extend the dataset's dataspace to hold the new record */
symbol->nrecords++;
- if(H5Dset_extent(symbol->dsid, &symbol->nrecords) < 0)
+ dim[1] = symbol->nrecords;
+ if(H5Dset_extent(symbol->dsid, dim) < 0)
return(-1);
/* Get the dataset's dataspace */
@@ -119,7 +121,7 @@ add_records(hid_t fid, unsigned verbose, unsigned long nrecords, unsigned long f return(-1);
/* Choose the last record in the dataset */
- if(H5Sselect_hyperslab(file_sid, H5S_SELECT_SET, &start, NULL, &count, NULL) < 0)
+ if(H5Sselect_hyperslab(file_sid, H5S_SELECT_SET, start, NULL, count, NULL) < 0)
return(-1);
/* Write record to the dataset */
@@ -242,7 +244,7 @@ int main(int argc, const char *argv[]) /* Create randomized set of numbers */
curr_time = time(NULL);
- srandom((unsigned)curr_time);
+ srandom(15);//srandom((unsigned)curr_time);
/* Emit informational message */
if(verbose)
diff --git a/test/testswmr.sh b/test/testswmr.sh index 090a131..9ca1e97 100755 --- a/test/testswmr.sh +++ b/test/testswmr.sh @@ -69,7 +69,7 @@ while [ $# -gt 0 ]; do done # Loop over index types -for index_type in "-i b1" "-i ea" +for index_type in "-i b1" "-i ea" "-i b2" do # Try with and without compression for compress in "" "-c 1" |