diff options
Diffstat (limited to 'src/H5Dbtree.c')
-rw-r--r-- | src/H5Dbtree.c | 386 |
1 files changed, 364 insertions, 22 deletions
diff --git a/src/H5Dbtree.c b/src/H5Dbtree.c index e61811d..f511d90 100644 --- a/src/H5Dbtree.c +++ b/src/H5Dbtree.c @@ -124,6 +124,10 @@ static herr_t H5D_btree_encode_key(const H5B_shared_t *shared, uint8_t *raw, const void *_key); static herr_t H5D_btree_debug_key(FILE *stream, int indent, int fwidth, const void *key, const void *udata); +static herr_t H5D_btree_create_flush_dep(void *_key, void *_udata, + void *parent); +static herr_t H5D_btree_update_flush_dep(void *_key, void *_udata, + void *old_parent, void *new_parent); /* Chunked layout indexing callbacks */ static herr_t H5D_btree_idx_init(const H5D_chk_idx_info_t *idx_info, @@ -146,6 +150,10 @@ static herr_t H5D_btree_idx_copy_shutdown(H5O_storage_chunk_t *storage_src, static herr_t H5D_btree_idx_size(const H5D_chk_idx_info_t *idx_info, hsize_t *size); static herr_t H5D_btree_idx_reset(H5O_storage_chunk_t *storage, hbool_t reset_addr); +static herr_t H5D_btree_idx_support(const H5D_chk_idx_info_t *idx_info, + H5D_chunk_ud_t *udata, H5AC_info_t *child_entry); +static herr_t H5D_btree_idx_unsupport(const H5D_chk_idx_info_t *idx_info, + H5D_chunk_common_ud_t *udata, H5AC_info_t *child_entry); static herr_t H5D_btree_idx_dump(const H5O_storage_chunk_t *storage, FILE *stream); static herr_t H5D_btree_idx_dest(const H5D_chk_idx_info_t *idx_info); @@ -157,7 +165,7 @@ static herr_t H5D_btree_idx_dest(const H5D_chk_idx_info_t *idx_info); /* v1 B-tree indexed chunk I/O ops */ const H5D_chunk_ops_t H5D_COPS_BTREE[1] = {{ - FALSE, /* v1 B-tree indices don't support SWMR access */ + TRUE, /* v1 B-tree indices do support SWMR access */ H5D_btree_idx_init, H5D_btree_idx_create, H5D_btree_idx_is_space_alloc, @@ -171,8 +179,8 @@ const H5D_chunk_ops_t H5D_COPS_BTREE[1] = {{ H5D_btree_idx_copy_shutdown, H5D_btree_idx_size, H5D_btree_idx_reset, - NULL, - NULL, + H5D_btree_idx_support, + H5D_btree_idx_unsupport, H5D_btree_idx_dump, H5D_btree_idx_dest }}; @@ -199,6 +207,8 @@ H5B_class_t H5B_BTREE[1] = {{ H5D_btree_decode_key, /*decode */ H5D_btree_encode_key, /*encode */ H5D_btree_debug_key, /*debug */ + H5D_btree_create_flush_dep, /*create_flush_dep */ + H5D_btree_update_flush_dep, /*update_flush_dep */ }}; @@ -561,13 +571,20 @@ H5D_btree_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key, * QAK - 11/19/2002 */ #ifdef OLD_WAY + /* Note that this does not take SWMR writes into account! Fix this + * if we ever want to go back to this code. -NAF 8/2/11 */ if(HADDR_UNDEF == (*new_node_p = H5MF_realloc(f, H5FD_MEM_DRAW, addr, (hsize_t)lt_key->nbytes, (hsize_t)udata->nbytes))) HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, H5B_INS_ERROR, "unable to reallocate chunk storage") #else /* OLD_WAY */ - H5_CHECK_OVERFLOW(lt_key->nbytes, uint32_t, hsize_t); - if(H5MF_xfree(f, H5FD_MEM_DRAW, dxpl_id, addr, (hsize_t)lt_key->nbytes) < 0) - HGOTO_ERROR(H5E_STORAGE, H5E_CANTFREE, H5B_INS_ERROR, "unable to free chunk") + /* Only free the old location if not doing SWMR writes - otherwise + * we must keep the old chunk around in case a reader has an + * outdated version of the b-tree node */ + if(!(H5F_INTENT(f) & H5F_ACC_SWMR_WRITE)) { + H5_CHECK_OVERFLOW(lt_key->nbytes, uint32_t, hsize_t); + if(H5MF_xfree(f, H5FD_MEM_DRAW, dxpl_id, addr, (hsize_t)lt_key->nbytes) < 0) + HGOTO_ERROR(H5E_STORAGE, H5E_CANTFREE, H5B_INS_ERROR, "unable to free chunk") + } /* end if */ H5_CHECK_OVERFLOW(udata->nbytes, uint32_t, hsize_t); if(HADDR_UNDEF == (*new_node_p = H5MF_alloc(f, H5FD_MEM_DRAW, dxpl_id, (hsize_t)udata->nbytes))) HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, H5B_INS_ERROR, "unable to reallocate chunk") @@ -644,9 +661,11 @@ H5D_btree_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key /*in,out * FUNC_ENTER_NOAPI_NOINIT(H5D_btree_remove) /* Remove raw data chunk from file */ - H5_CHECK_OVERFLOW(lt_key->nbytes, uint32_t, hsize_t); - if(H5MF_xfree(f, H5FD_MEM_DRAW, dxpl_id, addr, (hsize_t)lt_key->nbytes) < 0) - HGOTO_ERROR(H5E_STORAGE, H5E_CANTFREE, H5B_INS_ERROR, "unable to free chunk") + if(!(H5F_INTENT(f) & H5F_ACC_SWMR_WRITE)) { + H5_CHECK_OVERFLOW(lt_key->nbytes, uint32_t, hsize_t); + if(H5MF_xfree(f, H5FD_MEM_DRAW, dxpl_id, addr, (hsize_t)lt_key->nbytes) < 0) + HGOTO_ERROR(H5E_STORAGE, H5E_CANTFREE, H5B_INS_ERROR, "unable to free chunk") + } /* end if */ /* Mark keys as unchanged */ *lt_key_changed = FALSE; @@ -801,7 +820,7 @@ H5D_btree_shared_create(const H5F_t *f, H5O_storage_chunk_t *store, unsigned ndi /* Set up the "local" information for this dataset's chunks */ /* <none> */ - +HDassert(!store->u.btree.shared); /* Make shared B-tree info reference counted */ if(NULL == (store->u.btree.shared = H5RC_create(shared, H5B_shared_free))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create ref-count wrapper for shared B-tree info") @@ -812,6 +831,91 @@ done: /*------------------------------------------------------------------------- + * Function: H5D_btree_create_flush_dep + * + * Purpose: Creates a flush dependency between the specified chunk + * (child) and parent. + * + * Return: Success: 0 + * Failure: FAIL + * + * Programmer: Neil Fortner + * Tuesday, September 21, 2010 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D_btree_create_flush_dep(void *_key, void *_udata, void *parent) +{ + H5D_btree_key_t *key = (H5D_btree_key_t *)_key; + H5D_chunk_common_ud_t *udata = (H5D_chunk_common_ud_t *) _udata; + int ret_value; + + FUNC_ENTER_NOAPI_NOINIT(H5D_btree_create_flush_dep) + + HDassert(key); + 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, key->offset, + parent) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTDEPEND, FAIL, "unable to create flush dependency") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D_btree_create_flush_dep() */ + + +/*------------------------------------------------------------------------- + * Function: H5D_btree_update_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, August 31, 2010 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D_btree_update_flush_dep(void *_key, void *_udata, void *old_parent, + void *new_parent) +{ + H5D_btree_key_t *key = (H5D_btree_key_t *)_key; + H5D_chunk_common_ud_t *udata = (H5D_chunk_common_ud_t *) _udata; + int ret_value; + + FUNC_ENTER_NOAPI_NOINIT(H5D_btree_update_flush_dep) + + HDassert(key); + 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, key->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_update_flush_dep() */ + + +/*------------------------------------------------------------------------- * Function: H5D_btree_idx_init * * Purpose: Initialize the indexing information for a dataset. @@ -871,7 +975,9 @@ done: static herr_t H5D_btree_idx_create(const H5D_chk_idx_info_t *idx_info) { - H5D_chunk_common_ud_t udata; /* User data for B-tree callback */ + H5D_chunk_common_ud_t udata; /* User data for B-tree callback */ + 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(H5D_btree_idx_create) @@ -888,11 +994,26 @@ H5D_btree_idx_create(const H5D_chk_idx_info_t *idx_info) udata.layout = idx_info->layout; udata.storage = idx_info->storage; + /* 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 */ + 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 v1 B-tree for the chunk index */ - if(H5B_create(idx_info->f, idx_info->dxpl_id, H5B_BTREE, &udata, &(idx_info->storage->idx_addr)/*out*/) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't create B-tree") + if(H5B_create(idx_info->f, idx_info->dxpl_id, H5B_BTREE, &udata, oh, &(idx_info->storage->idx_addr)/*out*/) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't create B-tree") 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_btree_idx_create() */ @@ -942,7 +1063,9 @@ H5D_btree_idx_is_space_alloc(const H5O_storage_chunk_t *storage) static herr_t H5D_btree_idx_insert(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata) { - herr_t ret_value = SUCCEED; /* Return value */ + 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(H5D_btree_idx_insert) @@ -954,14 +1077,30 @@ H5D_btree_idx_insert(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata) HDassert(H5F_addr_defined(idx_info->storage->idx_addr)); HDassert(udata); + /* Check for SWMR writes to the file. If so we must pin the dataset object + * header so it can be set as a flush dependency parent. */ + 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 */ + 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 chunk it if it doesn't exist, or reallocate the chunk if * its size changed. */ - if(H5B_insert(idx_info->f, idx_info->dxpl_id, H5B_BTREE, idx_info->storage->idx_addr, udata) < 0) + if(H5B_insert(idx_info->f, idx_info->dxpl_id, H5B_BTREE, idx_info->storage->idx_addr, udata, oh) < 0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to allocate chunk") 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) } /* H5D_btree_idx_insert() */ @@ -983,6 +1122,8 @@ done: static herr_t H5D_btree_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata) { + 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(H5D_btree_idx_get_addr) @@ -996,11 +1137,27 @@ H5D_btree_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata HDassert(H5F_addr_defined(idx_info->storage->idx_addr)); HDassert(udata); + /* Check for SWMR writes to the file. If so we must pin the dataset object + * header so it can be set as a flush dependency parent. */ + 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 */ + 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 */ + /* Go get the chunk information from the B-tree */ - if(H5B_find(idx_info->f, idx_info->dxpl_id, H5B_BTREE, idx_info->storage->idx_addr, udata) < 0) + if(H5B_find(idx_info->f, idx_info->dxpl_id, H5B_BTREE, idx_info->storage->idx_addr, udata, oh) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk info") 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) } /* H5D_btree_idx_get_addr() */ @@ -1071,9 +1228,11 @@ H5D_btree_idx_iterate(const H5D_chk_idx_info_t *idx_info, H5D_chunk_cb_func_t chunk_cb, void *chunk_udata) { H5D_btree_it_ud_t udata; /* User data for B-tree iterator callback */ + H5O_loc_t oloc; /* Temporary object header location for dataset */ + H5O_t *oh = NULL; /* Dataset's object header */ int ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR(H5D_btree_idx_iterate) + FUNC_ENTER_NOAPI_NOINIT(H5D_btree_idx_iterate) HDassert(idx_info); HDassert(idx_info->f); @@ -1084,6 +1243,19 @@ H5D_btree_idx_iterate(const H5D_chk_idx_info_t *idx_info, HDassert(chunk_cb); HDassert(chunk_udata); + /* Check for SWMR writes to the file. If so we must pin the dataset object + * header so it can be set as a flush dependency parent. */ + 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 */ + 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 */ + /* Initialize userdata */ HDmemset(&udata, 0, sizeof udata); udata.common.layout = idx_info->layout; @@ -1092,9 +1264,13 @@ H5D_btree_idx_iterate(const H5D_chk_idx_info_t *idx_info, udata.udata = chunk_udata; /* Iterate over existing chunks */ - if((ret_value = H5B_iterate(idx_info->f, idx_info->dxpl_id, H5B_BTREE, idx_info->storage->idx_addr, H5D_btree_idx_iterate_cb, &udata)) < 0) + if((ret_value = H5B_iterate(idx_info->f, idx_info->dxpl_id, H5B_BTREE, idx_info->storage->idx_addr, H5D_btree_idx_iterate_cb, &udata, oh)) < 0) HERROR(H5E_DATASET, H5E_BADITER, "unable to iterate over chunk B-tree"); +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_btree_idx_iterate() */ @@ -1114,6 +1290,8 @@ H5D_btree_idx_iterate(const H5D_chk_idx_info_t *idx_info, static herr_t H5D_btree_idx_remove(const H5D_chk_idx_info_t *idx_info, H5D_chunk_common_ud_t *udata) { + 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(H5D_btree_idx_remove) @@ -1126,13 +1304,29 @@ H5D_btree_idx_remove(const H5D_chk_idx_info_t *idx_info, H5D_chunk_common_ud_t * HDassert(H5F_addr_defined(idx_info->storage->idx_addr)); HDassert(udata); + /* Check for SWMR writes to the file. If so we must pin the dataset object + * header so it can be set as a flush dependency parent. */ + 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 */ + 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 */ + /* Remove the chunk from the v1 B-tree index and release the space for the * chunk (in the B-tree callback). */ - if(H5B_remove(idx_info->f, idx_info->dxpl_id, H5B_BTREE, idx_info->storage->idx_addr, udata) < 0) + if(H5B_remove(idx_info->f, idx_info->dxpl_id, H5B_BTREE, idx_info->storage->idx_addr, udata, oh) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTDELETE, FAIL, "unable to remove chunk entry") 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) } /* H5D_btree_idx_remove() */ @@ -1154,7 +1348,9 @@ done: static herr_t H5D_btree_idx_delete(const H5D_chk_idx_info_t *idx_info) { - herr_t ret_value = SUCCEED; /* Return value */ + 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(H5D_btree_idx_delete) @@ -1170,6 +1366,19 @@ H5D_btree_idx_delete(const H5D_chk_idx_info_t *idx_info) H5O_storage_chunk_t tmp_storage; /* Local copy of storage info */ H5D_chunk_common_ud_t udata; /* User data for B-tree operations */ + /* Check for SWMR writes to the file. If so we must pin the dataset object + * header so it can be set as a flush dependency parent. */ + 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 */ + 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 */ + /* Set up temporary chunked storage info */ tmp_storage = *idx_info->storage; @@ -1183,7 +1392,7 @@ H5D_btree_idx_delete(const H5D_chk_idx_info_t *idx_info) udata.storage = &tmp_storage; /* Delete entire B-tree */ - if(H5B_delete(idx_info->f, idx_info->dxpl_id, H5B_BTREE, tmp_storage.idx_addr, &udata) < 0) + if(H5B_delete(idx_info->f, idx_info->dxpl_id, H5B_BTREE, tmp_storage.idx_addr, &udata, oh) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTDELETE, FAIL, "unable to delete chunk B-tree") /* Release the shared B-tree page */ @@ -1194,6 +1403,9 @@ H5D_btree_idx_delete(const H5D_chk_idx_info_t *idx_info) } /* 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_btree_idx_delete() */ @@ -1300,6 +1512,8 @@ H5D_btree_idx_size(const H5D_chk_idx_info_t *idx_info, hsize_t *index_size) H5D_chunk_common_ud_t udata; /* User-data for loading B-tree nodes */ H5B_info_t bt_info; /* B-tree info */ hbool_t shared_init = FALSE; /* Whether shared B-tree info is initialized */ + 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(H5D_btree_idx_size, FAIL) @@ -1312,6 +1526,19 @@ H5D_btree_idx_size(const H5D_chk_idx_info_t *idx_info, hsize_t *index_size) HDassert(idx_info->storage); HDassert(index_size); + /* Check for SWMR writes to the file. If so we must pin the dataset object + * header so it can be set as a flush dependency parent. */ + 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 */ + 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 */ + /* Initialize the shared info for the B-tree traversal */ if(H5D_btree_shared_create(idx_info->f, idx_info->storage, idx_info->layout->ndims) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create wrapper for shared B-tree info") @@ -1323,13 +1550,16 @@ H5D_btree_idx_size(const H5D_chk_idx_info_t *idx_info, hsize_t *index_size) udata.storage = idx_info->storage; /* Get metadata information for B-tree */ - if(H5B_get_info(idx_info->f, idx_info->dxpl_id, H5B_BTREE, idx_info->storage->idx_addr, &bt_info, NULL, &udata) < 0) + if(H5B_get_info(idx_info->f, idx_info->dxpl_id, H5B_BTREE, idx_info->storage->idx_addr, &bt_info, NULL, &udata, oh) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to iterate over chunk B-tree") /* Set the size of the B-tree */ *index_size = bt_info.size; done: + if(oh && H5O_unpin(oh) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CANTUNPIN, FAIL, "unable to unpin dataset object header") + if(shared_init) { if(NULL == idx_info->storage->u.btree.shared) HDONE_ERROR(H5E_IO, H5E_CANTFREE, FAIL, "ref-counted page nil") @@ -1370,6 +1600,118 @@ H5D_btree_idx_reset(H5O_storage_chunk_t *storage, hbool_t reset_addr) /*------------------------------------------------------------------------- + * Function: H5D_btree_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 + * Friday, Jun 24, 2011 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5D_btree_idx_support(const H5D_chk_idx_info_t *idx_info, + H5D_chunk_ud_t *udata, H5AC_info_t *child_entry) +{ + H5O_loc_t oloc; /* Temporary object header location for dataset */ + H5O_t *oh = NULL; /* Dataset's object header */ + herr_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5D_btree_idx_support) + + /* 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); + + /* 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 */ + if(NULL == (oh = H5O_pin(&oloc, idx_info->dxpl_id))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTPIN, FAIL, "unable to pin dataset object header") + + /* Add the flush dependency on the chunk */ + if((ret_value = H5B_support(idx_info->f, idx_info->dxpl_id, H5B_BTREE, idx_info->storage->idx_addr, + udata, oh, child_entry)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTDEPEND, FAIL, "unable to create flush dependency on b-tree array metadata") + +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_btree_idx_support() */ + + +/*------------------------------------------------------------------------- + * Function: H5D_btree_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 + * Wednesday, Jul 6, 2011 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D_btree_idx_unsupport(const H5D_chk_idx_info_t *idx_info, + H5D_chunk_common_ud_t *udata, H5AC_info_t *child_entry) +{ + 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(H5D_btree_idx_unsupport) + + /* 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); + + /* 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 */ + if(NULL == (oh = H5O_pin(&oloc, idx_info->dxpl_id))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTPIN, FAIL, "unable to pin dataset object header") + + /* Add the flush dependency on the chunk */ + if((ret_value = H5B_unsupport(idx_info->f, idx_info->dxpl_id, H5B_BTREE, idx_info->storage->idx_addr, + udata, oh, child_entry)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency on b-tree array metadata") + +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_btree_idx_unsupport() */ + + +/*------------------------------------------------------------------------- * Function: H5D_btree_idx_dump * * Purpose: Dump indexing information to a stream. |