diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2014-11-20 20:25:07 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2014-11-20 20:25:07 (GMT) |
commit | 5d23fe9d97efcf3fb900f9c387c00265908f5fd4 (patch) | |
tree | 42c34e941013768612c1b879389111bedf854b4e /src | |
parent | a0acf1329d983e47e29aa7b34c7c6bddc2b31a78 (diff) | |
download | hdf5-5d23fe9d97efcf3fb900f9c387c00265908f5fd4.zip hdf5-5d23fe9d97efcf3fb900f9c387c00265908f5fd4.tar.gz hdf5-5d23fe9d97efcf3fb900f9c387c00265908f5fd4.tar.bz2 |
[svn-r25828] Description:
Check in Vailin's performance improvements:
- Track min+max for v2 B-trees, so we can more quickly answer queries
- Refactor chunk index/hash value computation so that it doesn't have to be
updated on cached chunks every time the dataset's dimension sizes change.
Tested on:
Mac OSX/64 10.10.0 (amazon) w/gcc 4.9, FORTRAN, C++ & parallel
(h5committest not required on this branch)
Diffstat (limited to 'src')
-rw-r--r-- | src/H5B2.c | 120 | ||||
-rw-r--r-- | src/H5B2hdr.c | 10 | ||||
-rw-r--r-- | src/H5B2int.c | 138 | ||||
-rw-r--r-- | src/H5B2pkg.h | 30 | ||||
-rw-r--r-- | src/H5D.c | 6 | ||||
-rw-r--r-- | src/H5Dchunk.c | 436 | ||||
-rw-r--r-- | src/H5Dcompact.c | 15 | ||||
-rw-r--r-- | src/H5Dcontig.c | 13 | ||||
-rw-r--r-- | src/H5Ddeprec.c | 44 | ||||
-rw-r--r-- | src/H5Dearray.c | 12 | ||||
-rw-r--r-- | src/H5Defl.c | 13 | ||||
-rw-r--r-- | src/H5Dfarray.c | 6 | ||||
-rw-r--r-- | src/H5Dint.c | 109 | ||||
-rw-r--r-- | src/H5Dio.c | 19 | ||||
-rw-r--r-- | src/H5Dmpio.c | 8 | ||||
-rw-r--r-- | src/H5Dnone.c | 21 | ||||
-rw-r--r-- | src/H5Dpkg.h | 21 | ||||
-rw-r--r-- | src/H5VM.c | 126 | ||||
-rw-r--r-- | src/H5VMprivate.h | 31 |
19 files changed, 781 insertions, 397 deletions
@@ -306,11 +306,11 @@ H5B2_insert(H5B2_t *bt2, hid_t dxpl_id, void *udata) /* Attempt to insert record into B-tree */ if(hdr->depth > 0) { - if(H5B2_insert_internal(hdr, dxpl_id, hdr->depth, NULL, &hdr->root, hdr, udata) < 0) + if(H5B2_insert_internal(hdr, dxpl_id, hdr->depth, NULL, &hdr->root, H5B2_POS_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, hdr, udata) < 0) + if(H5B2_insert_leaf(hdr, dxpl_id, &hdr->root, H5B2_POS_ROOT, hdr, udata) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into B-tree leaf node") } /* end else */ @@ -433,6 +433,7 @@ H5B2_find(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_found_t op, unsigned depth; /* Current depth of the tree */ int cmp; /* Comparison value of records */ unsigned idx; /* Location of record which matches key */ + H5B2_nodepos_t curr_pos; /* Position of the current node */ htri_t ret_value = TRUE; /* Return value */ FUNC_ENTER_NOAPI(FALSE) @@ -453,6 +454,28 @@ H5B2_find(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_found_t op, if(curr_node_ptr.node_nrec == 0) HGOTO_DONE(FALSE) + /* Check record against min & max records in tree, to attempt to quickly + * find candidates or avoid further searching. + */ + if(hdr->min_native_rec != NULL) { + if((cmp = (hdr->cls->compare)(udata, hdr->min_native_rec)) < 0) + HGOTO_DONE(FALSE) /* Less than the least record--not found */ + else if(cmp == 0) { /* Record is found */ + if(op && (op)(hdr->min_native_rec, op_data) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "'found' callback failed for B-tree find operation") + HGOTO_DONE(TRUE) + } /* end if */ + } /* end if */ + if(hdr->max_native_rec != NULL) { + if((cmp = (hdr->cls->compare)(udata, hdr->max_native_rec)) > 0) + HGOTO_DONE(FALSE) /* Greater than the greatest record--not found */ + else if(cmp == 0) { /* Record is found */ + if(op && (op)(hdr->max_native_rec, op_data) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "'found' callback failed for B-tree find operation") + HGOTO_DONE(TRUE) + } /* end if */ + } /* end if */ + /* Current depth of the tree */ depth = hdr->depth; @@ -462,6 +485,7 @@ H5B2_find(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_found_t op, /* Walk down B-tree to find record or leaf node where record is located */ cmp = -1; + curr_pos = H5B2_POS_ROOT; 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 */ @@ -486,6 +510,24 @@ H5B2_find(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_found_t op, /* Get node pointer for next node to search */ next_node_ptr=internal->node_ptrs[idx]; + /* Set the position of the next node */ + if(H5B2_POS_MIDDLE != curr_pos) { + if(idx == 0) { + if(H5B2_POS_LEFT == curr_pos || H5B2_POS_ROOT == curr_pos) + curr_pos = H5B2_POS_LEFT; + else + curr_pos = H5B2_POS_MIDDLE; + } /* end if */ + else if(idx == internal->nrec) { + if(H5B2_POS_RIGHT == curr_pos || H5B2_POS_ROOT == curr_pos) + curr_pos = H5B2_POS_RIGHT; + else + curr_pos = H5B2_POS_MIDDLE; + } /* end if */ + else + curr_pos = H5B2_POS_MIDDLE; + } /* end if */ + /* Unlock current node */ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, (unsigned)(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") @@ -553,6 +595,27 @@ H5B2_find(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_found_t op, HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "'found' callback failed for B-tree find operation") } /* end if */ + + /* Check for record being the min or max for the tree */ + /* (Don't use 'else' for the idx check, to allow for root leaf node) */ + if(H5B2_POS_MIDDLE != curr_pos) { + if(idx == 0) { + if(H5B2_POS_LEFT == curr_pos || H5B2_POS_ROOT == curr_pos) { + if(hdr->min_native_rec == NULL) + if(NULL == (hdr->min_native_rec = (uint8_t *)HDmalloc(hdr->cls->nrec_size))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "memory allocation failed for v2 B-tree min record info") + HDmemcpy(hdr->min_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size); + } /* end if */ + } /* end if */ + if(idx == (unsigned)(leaf->nrec - 1)) { + if(H5B2_POS_RIGHT == curr_pos || H5B2_POS_ROOT == curr_pos) { + if(hdr->max_native_rec == NULL) + if(NULL == (hdr->max_native_rec = (uint8_t *)HDmalloc(hdr->cls->nrec_size))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "memory allocation failed for v2 B-tree max record info") + HDmemcpy(hdr->max_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size); + } /* end if */ + } /* end if */ + } /* end if */ } /* end else */ /* Unlock current node */ @@ -805,8 +868,8 @@ H5B2_remove(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_remove_t op, 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, NULL, - hdr->depth, &(hdr->cache_info), NULL, &hdr->root, udata, op, - op_data) < 0) + hdr->depth, &(hdr->cache_info), NULL, H5B2_POS_ROOT, &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 */ @@ -824,7 +887,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, hdr, udata, op, op_data) < 0) + if(H5B2_remove_leaf(hdr, dxpl_id, &hdr->root, H5B2_POS_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 */ @@ -894,8 +957,8 @@ H5B2_remove_by_idx(H5B2_t *bt2, hid_t dxpl_id, H5_iter_order_t order, 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, - NULL, hdr->depth, &(hdr->cache_info), NULL, &hdr->root, idx, - udata, op, op_data) < 0) + NULL, hdr->depth, &(hdr->cache_info), NULL, &hdr->root, + H5B2_POS_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 */ @@ -913,7 +976,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, hdr, (unsigned)idx, op, op_data) < 0) + if(H5B2_remove_leaf_by_idx(hdr, dxpl_id, &hdr->root, H5B2_POS_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 */ @@ -1048,6 +1111,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 */ + H5B2_nodepos_t curr_pos; /* Position of current node */ unsigned depth; /* Current depth of the tree */ int cmp; /* Comparison value of records */ unsigned idx; /* Location of record which matches key */ @@ -1081,6 +1145,7 @@ H5B2_modify(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_modify_t op, /* Walk down B-tree to find record or leaf node where record is located */ cmp = -1; + curr_pos = H5B2_POS_ROOT; while(depth > 0) { unsigned internal_flags = H5AC__NO_FLAGS_SET; H5B2_internal_t *internal; /* Pointer to internal node in B-tree */ @@ -1106,6 +1171,24 @@ H5B2_modify(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_modify_t op, /* Get node pointer for next node to search */ next_node_ptr = internal->node_ptrs[idx]; + /* Set the position of the next node */ + if(H5B2_POS_MIDDLE != curr_pos) { + if(idx == 0) { + if(H5B2_POS_LEFT == curr_pos || H5B2_POS_ROOT == curr_pos) + curr_pos = H5B2_POS_LEFT; + else + curr_pos = H5B2_POS_MIDDLE; + } /* end if */ + else if(idx == internal->nrec) { + if(H5B2_POS_RIGHT == curr_pos || H5B2_POS_ROOT == curr_pos) + curr_pos = H5B2_POS_RIGHT; + else + curr_pos = H5B2_POS_MIDDLE; + } /* end if */ + else + curr_pos = H5B2_POS_MIDDLE; + } /* end if */ + /* Unlock current node */ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, (unsigned)(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") @@ -1192,6 +1275,27 @@ H5B2_modify(H5B2_t *bt2, hid_t dxpl_id, void *udata, H5B2_modify_t op, HGOTO_ERROR(H5E_BTREE, H5E_CANTMODIFY, FAIL, "'modify' callback failed for B-tree find operation") } /* end if */ + + /* Check for modified record being the min or max for the tree */ + /* (Don't use 'else' for the idx check, to allow for root leaf node) */ + if(H5B2_POS_MIDDLE != curr_pos) { + if(idx == 0) { + if(H5B2_POS_LEFT == curr_pos || H5B2_POS_ROOT == curr_pos) { + if(hdr->min_native_rec == NULL) + if(NULL == (hdr->min_native_rec = (uint8_t *)HDmalloc(hdr->cls->nrec_size))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "memory allocation failed for v2 B-tree min record info") + HDmemcpy(hdr->min_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size); + } /* end if */ + } /* end if */ + if(idx == (unsigned)(leaf->nrec - 1)) { + if(H5B2_POS_RIGHT == curr_pos || H5B2_POS_ROOT == curr_pos) { + if(hdr->max_native_rec == NULL) + if(NULL == (hdr->max_native_rec = (uint8_t *)HDmalloc(hdr->cls->nrec_size))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "memory allocation failed for v2 B-tree max record info") + HDmemcpy(hdr->max_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size); + } /* end if */ + } /* end if */ + } /* end if */ } /* end else */ /* Mark the node as dirty if it changed */ diff --git a/src/H5B2hdr.c b/src/H5B2hdr.c index 702854b..5e00139 100644 --- a/src/H5B2hdr.c +++ b/src/H5B2hdr.c @@ -553,6 +553,16 @@ H5B2_hdr_free(H5B2_hdr_t *hdr) hdr->node_info = H5FL_SEQ_FREE(H5B2_node_info_t, hdr->node_info); } /* end if */ + /* Release the min & max record info, if set */ + if(hdr->min_native_rec) { + HDfree(hdr->min_native_rec); + hdr->min_native_rec = NULL; + } /* end if */ + if(hdr->max_native_rec) { + HDfree(hdr->max_native_rec); + hdr->max_native_rec = NULL; + } /* end if */ + /* Free B-tree header info */ hdr = H5FL_FREE(H5B2_hdr_t, hdr); diff --git a/src/H5B2int.c b/src/H5B2int.c index bf76d5c..b8c5c8c 100644 --- a/src/H5B2int.c +++ b/src/H5B2int.c @@ -2272,7 +2272,7 @@ done: */ herr_t H5B2_insert_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *curr_node_ptr, - void *parent, void *udata) + H5B2_nodepos_t curr_pos, void *parent, void *udata) { H5B2_leaf_t *leaf; /* Pointer to leaf node */ int cmp; /* Comparison value of records */ @@ -2328,6 +2328,27 @@ H5B2_insert_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *curr_node_ptr, /* Update record count for current node */ leaf->nrec++; + /* Check for new record being the min or max for the tree */ + /* (Don't use 'else' for the idx check, to allow for root leaf node) */ + if(H5B2_POS_MIDDLE != curr_pos) { + if(idx == 0) { + if(H5B2_POS_LEFT == curr_pos || H5B2_POS_ROOT == curr_pos) { + if(hdr->min_native_rec == NULL) + if(NULL == (hdr->min_native_rec = (uint8_t *)HDmalloc(hdr->cls->nrec_size))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "memory allocation failed for v2 B-tree min record info") + HDmemcpy(hdr->min_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size); + } /* end if */ + } /* end if */ + if(idx == (unsigned)(leaf->nrec - 1)) { + if(H5B2_POS_RIGHT == curr_pos || H5B2_POS_ROOT == curr_pos) { + if(hdr->max_native_rec == NULL) + if(NULL == (hdr->max_native_rec = (uint8_t *)HDmalloc(hdr->cls->nrec_size))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "memory allocation failed for v2 B-tree max record info") + HDmemcpy(hdr->max_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size); + } /* end if */ + } /* end if */ + } /* end if */ + done: /* Release the B-tree leaf node (marked as dirty) */ if(leaf && H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr->addr, leaf, H5AC__DIRTIED_FLAG) < 0) @@ -2353,11 +2374,12 @@ 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 *parent, void *udata) + H5B2_nodepos_t curr_pos, void *parent, void *udata) { H5B2_internal_t *internal = NULL; /* Pointer to internal node */ unsigned internal_flags = H5AC__NO_FLAGS_SET; unsigned idx; /* Location of record which matches key */ + H5B2_nodepos_t next_pos = H5B2_POS_MIDDLE; /* Position of node */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -2450,13 +2472,25 @@ H5B2_insert_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, unsigned depth, } /* end while */ } /* end block */ + /* Check if this node is left/right-most */ + if(H5B2_POS_MIDDLE != curr_pos) { + if(idx == 0) { + if(H5B2_POS_LEFT == curr_pos || H5B2_POS_ROOT == curr_pos) + next_pos = H5B2_POS_LEFT; + } /* end if */ + else if(idx == internal->nrec) { + if(H5B2_POS_RIGHT == curr_pos || H5B2_POS_ROOT == curr_pos) + next_pos = H5B2_POS_RIGHT; + } /* end else */ + } /* end if */ + /* Attempt to insert node */ if(depth > 1) { - if(H5B2_insert_internal(hdr, dxpl_id, (depth - 1), &internal_flags, &internal->node_ptrs[idx], internal, udata) < 0) + if(H5B2_insert_internal(hdr, dxpl_id, (depth - 1), &internal_flags, &internal->node_ptrs[idx], next_pos, 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], internal, udata) < 0) + if(H5B2_insert_leaf(hdr, dxpl_id, &internal->node_ptrs[idx], next_pos, internal, udata) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into B-tree leaf node") } /* end else */ @@ -2856,7 +2890,7 @@ done: */ 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) + H5B2_nodepos_t curr_pos, 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 */ @@ -2884,6 +2918,27 @@ H5B2_remove_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *curr_node_ptr, if(H5B2_locate_record(hdr->cls, leaf->nrec, hdr->nat_off, leaf->leaf_native, udata, &idx) != 0) HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "record is not in B-tree") + /* Check for invalidating the min/max record for the tree */ + if(H5B2_POS_MIDDLE != curr_pos) { + /* (Don't use 'else' for the idx check, to allow for root leaf node) */ + if(idx == 0) { + if(H5B2_POS_LEFT == curr_pos || H5B2_POS_ROOT == curr_pos) { + if(hdr->min_native_rec) { + HDfree(hdr->min_native_rec); + hdr->min_native_rec = NULL; + } /* end if */ + } /* end if */ + } /* end if */ + if(idx == (unsigned)(leaf->nrec - 1)) { + if(H5B2_POS_RIGHT == curr_pos || H5B2_POS_ROOT == curr_pos) { + if(hdr->max_native_rec) { + HDfree(hdr->max_native_rec); + hdr->max_native_rec = NULL; + } /* end if */ + } /* end if */ + } /* end if */ + } /* end if */ + /* Make 'remove' callback if there is one */ if(op) if((op)(H5B2_LEAF_NREC(leaf, hdr, idx), op_data) < 0) @@ -2945,8 +3000,8 @@ done: herr_t H5B2_remove_internal(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, - unsigned *parent_cache_info_flags_ptr, H5B2_node_ptr_t *curr_node_ptr, - void *udata, H5B2_remove_t op, void *op_data) + unsigned *parent_cache_info_flags_ptr, H5B2_nodepos_t curr_pos, + H5B2_node_ptr_t *curr_node_ptr, 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; @@ -2954,6 +3009,7 @@ H5B2_remove_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, hbool_t *depth_decreased, 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) */ + H5B2_nodepos_t next_pos = H5B2_POS_MIDDLE; /* Position of next node */ 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 */ @@ -3058,6 +3114,9 @@ H5B2_remove_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, hbool_t *depth_decreased, /* Set flag to indicate root was collapsed */ collapsed_root = TRUE; + + /* Indicate position of next node */ + next_pos = H5B2_POS_ROOT; } /* end if */ /* Merge or redistribute child node pointers, if necessary */ else { @@ -3165,16 +3224,28 @@ H5B2_remove_internal(H5B2_hdr_t *hdr, hid_t dxpl_id, hbool_t *depth_decreased, new_cache_info_flags_ptr = &internal_flags; new_cache_info = &internal->cache_info; new_node_ptr = &internal->node_ptrs[idx]; + + /* Indicate position of next node */ + if(H5B2_POS_MIDDLE != curr_pos) { + if(idx == 0) { + if(H5B2_POS_LEFT == curr_pos || H5B2_POS_ROOT == curr_pos) + next_pos = H5B2_POS_LEFT; + } /* end if */ + else if(idx == internal->nrec) { + if(H5B2_POS_RIGHT == curr_pos || H5B2_POS_ROOT == curr_pos) + next_pos = H5B2_POS_RIGHT; + } /* end if */ + } /* end if */ } /* end else */ /* Attempt to remove record from child node */ if(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) + new_cache_info, new_cache_info_flags_ptr, next_pos, 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, new_cache_info, udata, op, op_data) < 0) + if(H5B2_remove_leaf(hdr, dxpl_id, new_node_ptr, next_pos, 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 */ @@ -3222,8 +3293,8 @@ done: */ 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) + H5B2_node_ptr_t *curr_node_ptr, H5B2_nodepos_t curr_pos, 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 */ @@ -3247,6 +3318,27 @@ H5B2_remove_leaf_by_idx(H5B2_hdr_t *hdr, hid_t dxpl_id, HDassert(leaf->nrec == curr_node_ptr->node_nrec); HDassert(idx < leaf->nrec); + /* Check for invalidating the min/max record for the tree */ + if(H5B2_POS_MIDDLE != curr_pos) { + /* (Don't use 'else' for the idx check, to allow for root leaf node) */ + if(idx == 0) { + if(H5B2_POS_LEFT == curr_pos || H5B2_POS_ROOT == curr_pos) { + if(hdr->min_native_rec) { + HDfree(hdr->min_native_rec); + hdr->min_native_rec = NULL; + } /* end if */ + } /* end if */ + } /* end if */ + if(idx == (unsigned)(leaf->nrec - 1)) { + if(H5B2_POS_RIGHT == curr_pos || H5B2_POS_ROOT == curr_pos) { + if(hdr->max_native_rec) { + HDfree(hdr->max_native_rec); + hdr->max_native_rec = NULL; + } /* end if */ + } /* end if */ + } /* end if */ + } /* end if */ + /* Make 'remove' callback if there is one */ if(op) if((op)(H5B2_LEAF_NREC(leaf, hdr, idx), op_data) < 0) @@ -3310,8 +3402,8 @@ herr_t H5B2_remove_internal_by_idx(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, unsigned *parent_cache_info_flags_ptr, - H5B2_node_ptr_t *curr_node_ptr, hsize_t n, void *udata, H5B2_remove_t op, - void *op_data) + H5B2_node_ptr_t *curr_node_ptr, H5B2_nodepos_t curr_pos, 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; @@ -3319,6 +3411,7 @@ H5B2_remove_internal_by_idx(H5B2_hdr_t *hdr, hid_t dxpl_id, 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 */ + H5B2_nodepos_t next_pos = H5B2_POS_MIDDLE; /* Position of next node */ 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 */ @@ -3426,6 +3519,9 @@ H5B2_remove_internal_by_idx(H5B2_hdr_t *hdr, hid_t dxpl_id, /* Set flag to indicate root was collapsed */ collapsed_root = TRUE; + + /* Indicate position of next node */ + next_pos = H5B2_POS_ROOT; } /* end if */ /* Merge or redistribute child node pointers, if necessary */ else { @@ -3585,16 +3681,28 @@ H5B2_remove_internal_by_idx(H5B2_hdr_t *hdr, hid_t dxpl_id, new_cache_info_flags_ptr = &internal_flags; new_cache_info = &internal->cache_info; new_node_ptr = &internal->node_ptrs[idx]; + + /* Indicate position of next node */ + if(H5B2_POS_MIDDLE != curr_pos) { + if(idx == 0) { + if(H5B2_POS_LEFT == curr_pos || H5B2_POS_ROOT == curr_pos) + next_pos = H5B2_POS_LEFT; + } /* end if */ + else if(idx == internal->nrec) { + if(H5B2_POS_RIGHT == curr_pos || H5B2_POS_ROOT == curr_pos) + next_pos = H5B2_POS_RIGHT; + } /* end if */ + } /* end if */ } /* end else */ /* Attempt to remove record from child node */ if(depth > 1) { 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) + new_cache_info, new_cache_info_flags_ptr, new_node_ptr, next_pos, 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, new_cache_info, (unsigned)n, op, op_data) < 0) + if(H5B2_remove_leaf_by_idx(hdr, dxpl_id, new_node_ptr, next_pos, 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 */ diff --git a/src/H5B2pkg.h b/src/H5B2pkg.h index 29cde6f..55e00d9 100644 --- a/src/H5B2pkg.h +++ b/src/H5B2pkg.h @@ -176,6 +176,8 @@ typedef struct H5B2_hdr_t { 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 */ + uint8_t *min_native_rec; /* Pointer to minimum native record */ + uint8_t *max_native_rec; /* Pointer to maximum native record */ /* Client information (not stored) */ const H5B2_class_t *cls; /* Class of B-tree client */ @@ -218,6 +220,14 @@ struct H5B2_t { H5F_t *f; /* Pointer to file for v2 B-tree */ }; +/* Node position, for min/max determination */ +typedef enum H5B2_nodepos_t { + H5B2_POS_ROOT, /* Node is root (i.e. both right & left-most in tree) */ + H5B2_POS_RIGHT, /* Node is right-most in tree, at a given depth */ + H5B2_POS_LEFT, /* Node is left-most in tree, at a given depth */ + H5B2_POS_MIDDLE /* Node is neither right or left-most in tree */ +} H5B2_nodepos_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 */ @@ -323,9 +333,9 @@ 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 *parent, void *udata); + H5B2_node_ptr_t *curr_node_ptr, H5B2_nodepos_t curr_pos, 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 *parent, void *udata); + H5B2_node_ptr_t *curr_node_ptr, H5B2_nodepos_t curr_pos, 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, @@ -349,19 +359,19 @@ H5_DLL herr_t H5B2_neighbor_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, H5_DLL herr_t H5B2_remove_internal(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); + H5B2_nodepos_t curr_pos, 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); + H5B2_node_ptr_t *curr_node_ptr, H5B2_nodepos_t curr_pos, 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, 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); + H5B2_node_ptr_t *curr_node_ptr, H5B2_nodepos_t curr_pos, 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); + H5B2_node_ptr_t *curr_node_ptr, H5B2_nodepos_t curr_pos, 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, @@ -1040,8 +1040,8 @@ done: herr_t H5Drefresh(hid_t dset_id) { - H5D_t * dset = NULL; - hid_t ret_value = SUCCEED; /* return value */ + H5D_t *dset; /* Dataset to refresh */ + herr_t ret_value = SUCCEED; /* return value */ FUNC_ENTER_API(FAIL) H5TRACE1("e", "i", dset_id); @@ -1051,7 +1051,7 @@ H5Drefresh(hid_t dset_id) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") /* Call private function to refresh dataset object */ - if ((H5O_refresh_metadata(dset_id, dset->oloc, H5AC_dxpl_id)) < 0) + if((H5O_refresh_metadata(dset_id, dset->oloc, H5AC_dxpl_id)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTLOAD, FAIL, "unable to refresh dataset") done: diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c index 2557d1a..1311ba9 100644 --- a/src/H5Dchunk.c +++ b/src/H5Dchunk.c @@ -233,11 +233,11 @@ static herr_t H5D__chunk_file_cb(void *elem, hid_t type_id, unsigned ndims, const hsize_t *coords, void *fm); static herr_t H5D__chunk_mem_cb(void *elem, hid_t type_id, unsigned ndims, const hsize_t *coords, void *fm); +static size_t H5D__chunk_hash_val(const H5D_shared_t *shared, const hsize_t *scaled); static herr_t H5D__chunk_cache_evict(const H5D_t *dset, hid_t dxpl_id, const H5D_dxpl_cache_t *dxpl_cache, H5D_rdcc_ent_t *ent, hbool_t flush); -static htri_t H5D__chunk_is_partial_edge_chunk(const hsize_t offset[], - const H5D_t *dset, unsigned dset_ndims, const hsize_t *dset_dims, - const uint32_t *chunk_dims); +static hbool_t H5D__chunk_is_partial_edge_chunk(const hsize_t *chunk_offset, + unsigned dset_ndims, const hsize_t *dset_dims, const uint32_t *chunk_dims); static herr_t H5D__chunk_cache_prune(const H5D_t *dset, hid_t dxpl_id, const H5D_dxpl_cache_t *dxpl_cache, size_t size); static herr_t H5D__chunk_prune_fill(H5D_chunk_it_ud1_t *udata, hbool_t new_unfilt_chunk); @@ -323,15 +323,13 @@ H5D__chunk_direct_write(const H5D_t *dset, hid_t dxpl_id, uint32_t filters, hsiz uint32_t data_size, const void *buf) { const H5O_layout_t *layout = &(dset->shared->layout); /* Dataset layout */ - H5D_chunk_ud_t udata; /* User data for querying chunk info */ - hsize_t chunk_idx; + H5D_chunk_ud_t udata; /* User data for querying chunk info */ H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */ H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */ const H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /*raw data chunk cache */ - int space_ndims; /* Dataset's space rank */ - hsize_t space_dim[H5O_LAYOUT_NDIMS]; /* Dataset's dataspace dimensions */ H5D_chk_idx_info_t idx_info; /* Chunked index info */ - herr_t ret_value = SUCCEED; /* Return value */ + hsize_t scaled[H5S_MAX_RANK]; /* Scaled coordinates for this chunk */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC_TAG(dxpl_id, dset->oloc.addr, FAIL) @@ -342,18 +340,11 @@ H5D__chunk_direct_write(const H5D_t *dset, hid_t dxpl_id, uint32_t filters, hsiz HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize storage") } /* end if */ - - /* Retrieve the dataset dimensions */ - if((space_ndims = H5S_get_simple_extent_dims(dset->shared->space, space_dim, NULL)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to get simple dataspace info") - /* Calculate the index of this chunk */ - if(H5VM_chunk_index((unsigned)space_ndims, offset, - layout->u.chunk.dim, layout->u.chunk.down_chunks, &chunk_idx) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't get chunk index") + H5VM_chunk_scaled(dset->shared->ndims, offset, layout->u.chunk.dim, scaled); /* Find out the file address of the chunk */ - if(H5D__chunk_lookup(dset, dxpl_id, offset, chunk_idx, &udata) < 0) + if(H5D__chunk_lookup(dset, dxpl_id, offset, scaled, &udata) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address") udata.filter_mask = filters; @@ -473,24 +464,15 @@ done: herr_t H5D__chunk_set_info(const H5D_t *dset) { - hsize_t curr_dims[H5O_LAYOUT_NDIMS]; /* Curr. size of dataset dimensions */ - hsize_t max_dims[H5O_LAYOUT_NDIMS]; /* Max. size of dataset dimensions */ - int sndims; /* Rank of dataspace */ - unsigned ndims; /* Rank of dataspace */ - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* Sanity checks */ HDassert(dset); - /* Get the dim info for dataset */ - if((sndims = H5S_get_simple_extent_dims(dset->shared->space, curr_dims, max_dims)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataspace dimensions") - H5_ASSIGN_OVERFLOW(ndims, sndims, int, unsigned); - /* Set the base layout information */ - if(H5D__chunk_set_info_real(&dset->shared->layout.u.chunk, ndims, curr_dims, max_dims) < 0) + if(H5D__chunk_set_info_real(&dset->shared->layout.u.chunk, dset->shared->ndims, dset->shared->curr_dims, dset->shared->max_dims) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set layout's chunk info") /* Call the index's "resize" callback */ @@ -518,10 +500,7 @@ static herr_t H5D__chunk_construct(H5F_t UNUSED *f, H5D_t *dset) { const H5T_t *type = dset->shared->type; /* Convenience pointer to dataset's datatype */ - hsize_t max_dims[H5O_LAYOUT_NDIMS]; /* Maximum size of data in elements */ - hsize_t dims[H5O_LAYOUT_NDIMS]; /* Dimension size of data in elements */ uint64_t chunk_size; /* Size of chunk in bytes */ - int ndims; /* Rank of dataspace */ unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ @@ -536,9 +515,7 @@ H5D__chunk_construct(H5F_t UNUSED *f, H5D_t *dset) HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "no chunk information set?") /* Set up layout information */ - if((ndims = H5S_GET_EXTENT_NDIMS(dset->shared->space)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get rank") - if(dset->shared->layout.u.chunk.ndims != (unsigned)ndims) + if(dset->shared->layout.u.chunk.ndims != dset->shared->ndims) HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "dimensionality of chunks doesn't match the dataspace") /* Increment # of chunk dimensions, to account for datatype size as last element */ @@ -552,10 +529,6 @@ H5D__chunk_construct(H5F_t UNUSED *f, H5D_t *dset) /* Set the last dimension of the chunk size to the size of the datatype */ dset->shared->layout.u.chunk.dim[dset->shared->layout.u.chunk.ndims - 1] = (uint32_t)H5T_GET_SIZE(type); - /* Get local copy of dataset dimensions (for sanity checking) */ - if(H5S_get_simple_extent_dims(dset->shared->space, dims, max_dims) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to query maximum dimensions") - /* Sanity check dimensions */ for(u = 0; u < dset->shared->layout.u.chunk.ndims - 1; u++) { /* Don't allow zero-sized chunk dimensions */ @@ -567,7 +540,7 @@ H5D__chunk_construct(H5F_t UNUSED *f, H5D_t *dset) * the maximum dimension size. If any dimension size is zero, there * will be no such restriction. */ - if(dims[u] && max_dims[u] != H5S_UNLIMITED && max_dims[u] < dset->shared->layout.u.chunk.dim[u]) + if(dset->shared->curr_dims[u] && dset->shared->max_dims[u] != H5S_UNLIMITED && dset->shared->max_dims[u] < dset->shared->layout.u.chunk.dim[u]) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "chunk size must be <= maximum dimension size for fixed-sized dimensions") } /* end for */ @@ -1197,8 +1170,7 @@ H5D__create_chunk_map_single(H5D_chunk_map_t *fm, const H5D_io_info_t chunk_info->coords[fm->f_ndims] = 0; /* Calculate the index of this chunk */ - if(H5VM_chunk_index(fm->f_ndims, chunk_info->coords, fm->layout->u.chunk.dim, fm->layout->u.chunk.down_chunks, &chunk_info->index) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index") + chunk_info->index = H5VM_chunk_index_scaled(fm->f_ndims, chunk_info->coords, fm->layout->u.chunk.dim, fm->layout->u.chunk.down_chunks, chunk_info->scaled); /* Copy selection for file's dataspace into chunk dataspace */ if(H5S_select_copy(fm->single_space, fm->file_space, FALSE) < 0) @@ -1258,6 +1230,7 @@ H5D__create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t hsize_t coords[H5O_LAYOUT_NDIMS]; /* Current coordinates of chunk */ hsize_t end[H5O_LAYOUT_NDIMS]; /* Current coordinates of chunk */ hsize_t chunk_index; /* Index of chunk */ + hsize_t scaled[H5S_MAX_RANK]; /* Scaled coordinates for this chunk */ int curr_dim; /* Current dimension to increment */ unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ @@ -1282,8 +1255,7 @@ H5D__create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t } /* end for */ /* Calculate the index of this chunk */ - if(H5VM_chunk_index(fm->f_ndims, coords, fm->layout->u.chunk.dim, fm->layout->u.chunk.down_chunks, &chunk_index) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index") + chunk_index = H5VM_chunk_index_scaled(fm->f_ndims, coords, fm->layout->u.chunk.dim, fm->layout->u.chunk.down_chunks, scaled); /* Iterate through each chunk in the dataset */ while(sel_points) { @@ -1350,9 +1322,11 @@ H5D__create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t new_chunk_info->mspace_shared = FALSE; /* Copy the chunk's coordinates */ - for(u=0; u<fm->f_ndims; u++) - new_chunk_info->coords[u]=coords[u]; - new_chunk_info->coords[fm->f_ndims]=0; + HDmemcpy(new_chunk_info->coords, coords, sizeof(hsize_t) * fm->f_ndims); + new_chunk_info->coords[fm->f_ndims] = 0; + + /* Copy the chunk's scaled coordinates */ + HDmemcpy(new_chunk_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims); /* Insert the new chunk into the skip list */ if(H5SL_insert(fm->sel_chunks, new_chunk_info, &new_chunk_info->index) < 0) { @@ -1383,6 +1357,7 @@ H5D__create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t H5_CHECK_OVERFLOW(fm->chunk_dim[curr_dim],hsize_t,hssize_t); coords[curr_dim]+=fm->chunk_dim[curr_dim]; end[curr_dim]+=fm->chunk_dim[curr_dim]; + scaled[curr_dim]++; /* Bring chunk location back into bounds, if necessary */ if(coords[curr_dim] > sel_end[curr_dim]) { @@ -1400,8 +1375,8 @@ H5D__create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t } while(coords[curr_dim] > sel_end[curr_dim]); /* Re-calculate the index of this chunk */ - if(H5VM_chunk_index(fm->f_ndims, coords, fm->layout->u.chunk.dim, fm->layout->u.chunk.down_chunks, &chunk_index) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index") + /* (Technically, adjusting the scaled[] values could be moved inside loop above -QAK) */ + chunk_index = H5VM_chunk_index_scaled(fm->f_ndims, coords, fm->layout->u.chunk.dim, fm->layout->u.chunk.down_chunks, scaled); } /* end if */ } /* end while */ @@ -1541,16 +1516,16 @@ H5D__chunk_file_cb(void UNUSED *elem, hid_t UNUSED type_id, unsigned ndims, cons H5D_chunk_file_iter_ud_t *udata = (H5D_chunk_file_iter_ud_t *)_udata; /* User data for operation */ H5D_chunk_map_t *fm = udata->fm; /* File<->memory chunk mapping info */ H5D_chunk_info_t *chunk_info; /* Chunk information for current chunk */ - hsize_t coords_in_chunk[H5O_LAYOUT_NDIMS]; /* Coordinates of element in chunk */ + hsize_t coords_in_chunk[H5O_LAYOUT_NDIMS]; /* Coordinates of element in chunk */ hsize_t chunk_index; /* Chunk index */ + hsize_t scaled[H5S_MAX_RANK]; /* Scaled coordinates for this chunk */ unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC /* Calculate the index of this chunk */ - if(H5VM_chunk_index(ndims, coords, fm->layout->u.chunk.dim, fm->layout->u.chunk.down_chunks, &chunk_index) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index") + chunk_index = H5VM_chunk_index_scaled(ndims, coords, fm->layout->u.chunk.dim, fm->layout->u.chunk.down_chunks, scaled); /* Find correct chunk in file & memory skip list */ if(chunk_index==fm->last_index) { @@ -1603,9 +1578,10 @@ H5D__chunk_file_cb(void UNUSED *elem, hid_t UNUSED type_id, unsigned ndims, cons /* Compute the chunk's coordinates */ for(u = 0; u < fm->f_ndims; u++) { H5_CHECK_OVERFLOW(fm->layout->u.chunk.dim[u], hsize_t, hssize_t); - chunk_info->coords[u] = (coords[u] / (hssize_t)fm->layout->u.chunk.dim[u]) * (hssize_t)fm->layout->u.chunk.dim[u]; + chunk_info->coords[u] = scaled[u] * (hssize_t)fm->layout->u.chunk.dim[u]; } /* end for */ chunk_info->coords[fm->f_ndims] = 0; + HDmemcpy(chunk_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims); /* Insert the new chunk into the skip list */ if(H5SL_insert(fm->sel_chunks,chunk_info,&chunk_info->index) < 0) { @@ -1667,8 +1643,7 @@ H5D__chunk_mem_cb(void UNUSED *elem, hid_t UNUSED type_id, unsigned ndims, const FUNC_ENTER_STATIC /* Calculate the index of this chunk */ - if(H5VM_chunk_index(ndims, coords, fm->layout->u.chunk.dim, fm->layout->u.chunk.down_chunks, &chunk_index) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index") + chunk_index = H5VM_chunk_index(ndims, coords, fm->layout->u.chunk.dim, fm->layout->u.chunk.down_chunks); /* Find correct chunk in file & memory skip list */ if(chunk_index == fm->last_index) { @@ -1737,7 +1712,7 @@ htri_t H5D__chunk_cacheable(const H5D_io_info_t *io_info, haddr_t caddr, hbool_t write_op) { const H5D_t *dataset = io_info->dset; - htri_t no_filters = TRUE; + hbool_t no_filters = TRUE; htri_t ret_value = FAIL; FUNC_ENTER_PACKAGE @@ -1751,9 +1726,10 @@ H5D__chunk_cacheable(const H5D_io_info_t *io_info, haddr_t caddr, hbool_t write_ if(dataset->shared->dcpl_cache.pline.nused > 0) { if(dataset->shared->layout.u.chunk.flags & H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS) { - if((no_filters = H5D__chunk_is_partial_edge_chunk( - io_info->store->chunk.offset, io_info->dset, 0, NULL, NULL)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to determine if chunk is edge chunk") + no_filters = H5D__chunk_is_partial_edge_chunk( + io_info->store->chunk.offset, io_info->dset->shared->ndims, + io_info->dset->shared->curr_dims, + io_info->dset->shared->layout.u.chunk.dim); } /* end if */ else no_filters = FALSE; @@ -1896,7 +1872,7 @@ H5D__chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node); /* Get the info for the chunk in the file */ - if(H5D__chunk_lookup(io_info->dset, io_info->dxpl_id, chunk_info->coords, chunk_info->index, &udata) < 0) + if(H5D__chunk_lookup(io_info->dset, io_info->dxpl_id, chunk_info->coords, chunk_info->scaled, &udata) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address") /* Check for non-existant chunk & skip it if appropriate */ @@ -1911,8 +1887,6 @@ H5D__chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, if(cacheable) { /* Load the chunk into cache and lock it. */ - /* Pass in chunk's index. */ - io_info->store->chunk.index = chunk_info->index; /* Compute # of bytes accessed in chunk */ H5_CHECK_OVERFLOW(type_info->src_type_size, /*From:*/ size_t, /*To:*/ uint32_t); @@ -2029,7 +2003,7 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node); /* Look up the chunk */ - if(H5D__chunk_lookup(io_info->dset, io_info->dxpl_id, chunk_info->coords, chunk_info->index, &udata) < 0) + if(H5D__chunk_lookup(io_info->dset, io_info->dxpl_id, chunk_info->coords, chunk_info->scaled, &udata) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address") /* Pass in chunk's coordinates. */ @@ -2044,9 +2018,6 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, * simply allocate space instead of load the chunk. */ hbool_t entire_chunk = TRUE; /* Whether whole chunk is selected */ - /* Pass in chunk's index. */ - io_info->store->chunk.index = chunk_info->index; - /* Compute # of bytes accessed in chunk */ H5_CHECK_OVERFLOW(type_info->dst_type_size, /*From:*/ size_t, /*To:*/ uint32_t); dst_accessed_bytes = chunk_info->chunk_points * (uint32_t)type_info->dst_type_size; @@ -2313,8 +2284,6 @@ H5D__chunk_cinfo_cache_reset(H5D_chunk_cached_t *last) static herr_t H5D__chunk_cinfo_cache_update(H5D_chunk_cached_t *last, const H5D_chunk_ud_t *udata) { - unsigned u; /* Local index variable */ - FUNC_ENTER_STATIC_NOERR /* Sanity check */ @@ -2325,8 +2294,7 @@ H5D__chunk_cinfo_cache_update(H5D_chunk_cached_t *last, const H5D_chunk_ud_t *ud HDassert(udata->common.offset); /* Stored the information to cache */ - for(u = 0; u < udata->common.layout->ndims; u++) - last->offset[u] = udata->common.offset[u]; + HDmemcpy(last->offset, udata->common.offset, sizeof(hsize_t) * udata->common.layout->ndims); last->nbytes = udata->nbytes; last->chunk_idx = udata->chunk_idx; last->filter_mask = udata->filter_mask; @@ -2452,6 +2420,53 @@ done: /*------------------------------------------------------------------------- + * Function: H5D__chunk_hash_val + * + * Purpose: To calculate an index based on the dataset's scaled coordinates and + * sizes of the faster dimensions. + * + * Return: Hash value index + * + * Programmer: Vailin Choi; Nov 2014 + * + *------------------------------------------------------------------------- + */ +static size_t +H5D__chunk_hash_val(const H5D_shared_t *shared, const hsize_t *scaled) +{ + hsize_t val; /* Intermediate value */ + size_t ret; /* Value to return */ + unsigned ndims = shared->layout.u.chunk.ndims - 1; /* Rank of dataset */ + + FUNC_ENTER_STATIC_NOERR + + /* Sanity check */ + HDassert(shared); + HDassert(scaled); + + /* If the fastest changing dimension doesn't have enough entropy, use + * other dimensions too + */ + if(ndims > 1 && shared->curr_dims[ndims - 1] <= shared->cache.chunk.nslots) { + unsigned u; /* Local index variable */ + + val = scaled[0]; + for(u = 1; u < ndims; u++) { + val <<= H5VM_log2_gen(H5VM_power2up(shared->curr_dims[u])); + val ^= scaled[u]; + } /* end for */ + } /* end if */ + else + val = scaled[ndims - 1]; + + /* Modulo value against the number of array slots */ + ret = val % shared->cache.chunk.nslots; + + FUNC_LEAVE_NOAPI(ret) +} /* H5D__chunk_hash_val() */ + + +/*------------------------------------------------------------------------- * Function: H5D__chunk_lookup * * Purpose: Loops up a chunk in cache and on disk, and retrieves @@ -2466,7 +2481,7 @@ done: */ herr_t H5D__chunk_lookup(const H5D_t *dset, hid_t dxpl_id, const hsize_t *chunk_offset, - hsize_t chunk_idx, H5D_chunk_ud_t *udata) + const hsize_t *scaled, H5D_chunk_ud_t *udata) { H5D_rdcc_ent_t *ent = NULL; /* Cache entry */ hbool_t found = FALSE; /* In cache? */ @@ -2495,6 +2510,8 @@ H5D__chunk_lookup(const H5D_t *dset, hid_t dxpl_id, const hsize_t *chunk_offset, udata->common.storage = &(dset->shared->layout.storage.u.chunk); udata->common.offset = chunk_offset; udata->common.rdcc = &(dset->shared->cache.chunk); + udata->common.space_dim = dset->shared->curr_dims; + udata->common.scaled = scaled; /* Reset information about the chunk we are looking for */ udata->nbytes = 0; @@ -2506,7 +2523,7 @@ H5D__chunk_lookup(const H5D_t *dset, hid_t dxpl_id, const hsize_t *chunk_offset, /* Check for chunk in cache */ if(dset->shared->cache.chunk.nslots > 0) { - udata->idx_hint = H5D_CHUNK_HASH(dset->shared, chunk_idx); + udata->idx_hint = H5D__chunk_hash_val(dset->shared, scaled); ent = dset->shared->cache.chunk.slot[udata->idx_hint]; if(ent) @@ -2521,7 +2538,7 @@ H5D__chunk_lookup(const H5D_t *dset, hid_t dxpl_id, const hsize_t *chunk_offset, /* Find chunk addr */ if(found) { udata->addr = ent->chunk_addr; - udata->chunk_idx = chunk_idx; + udata->chunk_idx = ent->chunk_idx; } else { /* Invalidate idx_hint, to signal that the chunk is not in cache */ udata->idx_hint = UINT_MAX; @@ -2603,6 +2620,8 @@ H5D__chunk_flush_entry(const H5D_t *dset, hid_t dxpl_id, const H5D_dxpl_cache_t udata.common.storage = &dset->shared->layout.storage.u.chunk; udata.common.offset = ent->offset; udata.common.rdcc = &(dset->shared->cache.chunk); + udata.common.scaled = ent->scaled; + udata.filter_mask = 0; udata.nbytes = dset->shared->layout.u.chunk.size; udata.addr = ent->chunk_addr; @@ -2980,7 +2999,6 @@ H5D__chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata, H5D_rdcc_ent_t *ent = NULL; /*cache entry */ haddr_t chunk_addr = HADDR_UNDEF; /* Address of chunk on disk */ size_t chunk_size; /*size of a chunk */ - htri_t is_edge_chunk; /* Whether the chunk is an edge chunk */ hbool_t disable_filters = FALSE; /* Whether to disable filters (when adding to cache) */ void *chunk = NULL; /*the file chunk */ unsigned u; /*counters */ @@ -3104,11 +3122,9 @@ H5D__chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata, else if(layout->u.chunk.flags & H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS) { /* Check if this is an edge chunk */ - if((is_edge_chunk = H5D__chunk_is_partial_edge_chunk( - io_info->store->chunk.offset, io_info->dset, 0, NULL, layout->u.chunk.dim)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to determine if chunk is edge chunk") - - if(is_edge_chunk) { + if(H5D__chunk_is_partial_edge_chunk( + io_info->store->chunk.offset, io_info->dset->shared->ndims, + io_info->dset->shared->curr_dims, layout->u.chunk.dim)) { /* Disable the filters for both writing and reading */ disable_filters = TRUE; old_pline = NULL; @@ -3256,7 +3272,7 @@ H5D__chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata, } /* end if */ else if(rdcc->nslots > 0 && chunk_size <= rdcc->nbytes_max) { /* Calculate the index */ - udata->idx_hint = H5D_CHUNK_HASH(dset->shared, io_info->store->chunk.index); + udata->idx_hint = H5D__chunk_hash_val(io_info->dset->shared, udata->common.scaled); /* Add the chunk to the cache only if the slot is not already locked */ ent = rdcc->slot[udata->idx_hint]; @@ -3281,8 +3297,9 @@ H5D__chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata, ent->deleted = FALSE; ent->chunk_addr = chunk_addr; ent->chunk_idx = udata->chunk_idx; - for(u = 0; u < layout->u.chunk.ndims; u++) - ent->offset[u] = io_info->store->chunk.offset[u]; + HDmemcpy(ent->offset, io_info->store->chunk.offset, sizeof(hsize_t) * layout->u.chunk.ndims); + HDmemcpy(ent->scaled, udata->common.scaled, sizeof(hsize_t) * layout->u.chunk.ndims); + H5_ASSIGN_OVERFLOW(ent->rd_count, chunk_size, size_t, uint32_t); H5_ASSIGN_OVERFLOW(ent->wr_count, chunk_size, size_t, uint32_t); ent->chunk = (uint8_t *)chunk; @@ -3388,7 +3405,7 @@ H5D__chunk_unlock(const H5D_io_info_t *io_info, const H5D_chunk_ud_t *udata, * Note: we have to copy the layout and filter messages so we * don't discard the `const' qualifier. */ - htri_t is_unfiltered_edge_chunk = FALSE; /* Whether the chunk is an unfiltered edge chunk */ + hbool_t is_unfiltered_edge_chunk = FALSE; /* Whether the chunk is an unfiltered edge chunk */ /* Check if we should disable filters on this chunk */ if(udata->new_unfilt_chunk) { @@ -3400,9 +3417,9 @@ H5D__chunk_unlock(const H5D_io_info_t *io_info, const H5D_chunk_ud_t *udata, else if(layout->u.chunk.flags & H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS) { /* Check if the chunk is an edge chunk, and disable filters if so */ - if((is_unfiltered_edge_chunk = H5D__chunk_is_partial_edge_chunk( - io_info->store->chunk.offset, io_info->dset, 0, NULL, layout->u.chunk.dim)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to determine if chunk is edge chunk") + is_unfiltered_edge_chunk = H5D__chunk_is_partial_edge_chunk( + io_info->store->chunk.offset, io_info->dset->shared->ndims, + io_info->dset->shared->curr_dims, layout->u.chunk.dim); } /* end if */ if(dirty) { @@ -3415,6 +3432,7 @@ H5D__chunk_unlock(const H5D_io_info_t *io_info, const H5D_chunk_ud_t *udata, if(udata->new_unfilt_chunk) fake_ent.edge_chunk_state |= H5D_RDCC_NEWLY_DISABLED_FILTERS; HDmemcpy(fake_ent.offset, io_info->store->chunk.offset, layout->u.chunk.ndims * sizeof(fake_ent.offset[0])); + HDmemcpy(fake_ent.scaled, udata->common.scaled, sizeof(hsize_t) * layout->u.chunk.ndims); HDassert(layout->u.chunk.size > 0); fake_ent.chunk_idx = udata->chunk_idx; fake_ent.chunk_addr = udata->addr; @@ -3595,10 +3613,10 @@ H5D__chunk_allocate(const H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite, H5D_chunk_coll_info_t chunk_info; /* chunk address information for doing I/O */ #endif /* H5_HAVE_PARALLEL */ hbool_t carry; /* Flag to indicate that chunk increment carrys to higher dimension (sorta) */ - int space_ndims; /* Dataset's space rank */ - hsize_t space_dim[H5O_LAYOUT_NDIMS]; /* Dataset's dataspace dimensions */ + unsigned space_ndims; /* Dataset's space rank */ + const hsize_t *space_dim; /* Dataset's dataspace dimensions */ const uint32_t *chunk_dim = layout->u.chunk.dim; /* Convenience pointer to chunk dimensions */ - int op_dim; /* Current operationg dimension */ + unsigned op_dim; /* Current operationg dimension */ H5D_fill_buf_info_t fb_info; /* Dataset's fill buffer info */ hbool_t fb_info_init = FALSE; /* Whether the fill value buffer has been initialized */ hbool_t has_unfilt_edge_chunks = FALSE; /* Whether there are partial edge chunks with disabled filters */ @@ -3625,9 +3643,8 @@ H5D__chunk_allocate(const H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite, HDassert(TRUE == H5P_isa_class(dxpl_id, H5P_DATASET_XFER)); /* Retrieve the dataset dimensions */ - if((space_ndims = H5S_get_simple_extent_dims(dset->shared->space, space_dim, NULL)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to get simple dataspace info") - space_dim[space_ndims] = layout->u.chunk.dim[space_ndims]; + space_dim = dset->shared->curr_dims; + space_ndims = dset->shared->ndims; /* The last dimension in chunk_offset is always 0 */ chunk_offset[space_ndims] = (hsize_t)0; @@ -3772,6 +3789,7 @@ H5D__chunk_allocate(const H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite, chunk_size = orig_chunk_size; for(op_dim=0; op_dim<space_ndims; op_dim++) { H5D_chunk_ud_t udata; /* User data for querying chunk info */ + unsigned u; /* Local index variable */ int i; /* Local index variable */ /* Check if allocation along this dimension is really necessary */ @@ -3779,16 +3797,15 @@ H5D__chunk_allocate(const H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite, continue; else { /* Reset the chunk offset indices */ - HDmemset(chunk_offset, 0, ((unsigned)space_ndims - * sizeof(chunk_offset[0]))); + HDmemset(chunk_offset, 0, (space_ndims * sizeof(chunk_offset[0]))); chunk_offset[op_dim] = min_unalloc[op_dim]; if(has_unfilt_edge_chunks) { /* Initialize nunfilt_edge_chunk_dims */ nunfilt_edge_chunk_dims = 0; - for(i=0; i<space_ndims; i++) - if(unfilt_edge_chunk_dim[i] && chunk_offset[i] - == edge_chunk_offset[i]) + for(u = 0; u < space_ndims; u++) + if(unfilt_edge_chunk_dim[u] && chunk_offset[u] + == edge_chunk_offset[u]) nunfilt_edge_chunk_dims++; /* Initialize chunk_size and fill_buf */ @@ -3811,13 +3828,11 @@ H5D__chunk_allocate(const H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite, while(!carry) { /* None of the chunks should be allocated */ - hsize_t chunk_idx; + hsize_t scaled[H5O_LAYOUT_NDIMS]; /* Scaled coordinates for this chunk */ - /* Calculate the index of this chunk */ - if(H5VM_chunk_index((unsigned)space_ndims, chunk_offset, layout->u.chunk.dim, - layout->u.chunk.down_chunks, &chunk_idx) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't get chunk index") - if(H5D__chunk_lookup(dset, dxpl_id, chunk_offset, chunk_idx, &udata) < 0) + /* Look up this chunk */ + H5VM_chunk_scaled(space_ndims, chunk_offset, layout->u.chunk.dim, scaled); + if(H5D__chunk_lookup(dset, dxpl_id, chunk_offset, scaled, &udata) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address") #ifndef NDEBUG @@ -3828,9 +3843,9 @@ H5D__chunk_allocate(const H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite, * original dimensions */ { hbool_t outside_orig = FALSE; - for(i=0; i<space_ndims; i++) { - HDassert(chunk_offset[i] < space_dim[i]); - if(chunk_offset[i] >= old_dim[i]) + for(u = 0; u < space_ndims; u++) { + HDassert(chunk_offset[u] < space_dim[u]); + if(chunk_offset[u] >= old_dim[u]) outside_orig = TRUE; } /* end for */ HDassert(outside_orig); @@ -3941,10 +3956,10 @@ H5D__chunk_allocate(const H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite, /* Increment indices and adjust the edge chunk state */ carry = TRUE; - for(i = (space_ndims - 1); i >= 0; --i) { + for(i = ((int)space_ndims - 1); i >= 0; --i) { chunk_offset[i] += chunk_dim[i]; if(chunk_offset[i] > max_unalloc[i]) { - if(i == op_dim) + if((unsigned)i == op_dim) chunk_offset[i] = min_unalloc[i]; else chunk_offset[i] = 0; @@ -3957,7 +3972,7 @@ H5D__chunk_allocate(const H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite, if(should_fill && nunfilt_edge_chunk_dims == 0 && !fb_info.has_vlen_fill_type) { HDassert(!H5D__chunk_is_partial_edge_chunk( - chunk_offset, NULL, (unsigned)space_ndims, + chunk_offset, space_ndims, space_dim, chunk_dim)); fill_buf = &fb_info.fill_buf; chunk_size = orig_chunk_size; @@ -3973,7 +3988,7 @@ H5D__chunk_allocate(const H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite, if(should_fill && nunfilt_edge_chunk_dims == 1 && !fb_info.has_vlen_fill_type) { HDassert(H5D__chunk_is_partial_edge_chunk( - chunk_offset, NULL, (unsigned)space_ndims, + chunk_offset, space_ndims, space_dim, chunk_dim)); fill_buf = &unfilt_fill_buf; chunk_size = layout->u.chunk.size; @@ -4051,9 +4066,9 @@ H5D__chunk_update_old_edge_chunks(H5D_t *dset, hid_t dxpl_id, hsize_t old_dim[]) const H5O_pline_t *pline = &(dset->shared->dcpl_cache.pline); /* I/O pipeline info */ hsize_t chunk_offset[H5O_LAYOUT_NDIMS]; /* Offset of current chunk */ const uint32_t *chunk_dim = layout->u.chunk.dim; /* Convenience pointer to chunk dimensions */ - int space_ndims; /* Dataset's space rank */ - hsize_t space_dim[H5O_LAYOUT_NDIMS]; /* Dataset's dataspace dimensions */ - int op_dim; /* Current operationg dimension */ + unsigned space_ndims; /* Dataset's space rank */ + const hsize_t *space_dim; /* Dataset's dataspace dimensions */ + unsigned op_dim; /* Current operationg dimension */ H5D_io_info_t chk_io_info; /* Chunked I/O info object */ H5D_chunk_ud_t chk_udata; /* User data for locking chunk */ H5D_storage_t chk_store; /* Chunk storage information */ @@ -4084,9 +4099,8 @@ H5D__chunk_update_old_edge_chunks(H5D_t *dset, hid_t dxpl_id, hsize_t old_dim[]) & H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS); /* Retrieve the dataset dimensions */ - if((space_ndims = H5S_get_simple_extent_dims(dset->shared->space, space_dim, NULL)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to get simple dataspace info") - space_dim[space_ndims] = layout->u.chunk.dim[space_ndims]; + space_dim = dset->shared->curr_dims; + space_ndims = dset->shared->ndims; /* The last dimension in chunk_offset is always 0 */ chunk_offset[space_ndims] = (hsize_t)0; @@ -4145,37 +4159,32 @@ H5D__chunk_update_old_edge_chunks(H5D_t *dset, hid_t dxpl_id, hsize_t old_dim[]) /* Main loop: fix old edge chunks */ for(op_dim=0; op_dim<space_ndims; op_dim++) { - int i; /* Local index variable */ - /* Check if allocation along this dimension is really necessary */ if(!new_full_dim[op_dim]) continue; else { - HDassert((hsize_t) max_edge_chunk_off[op_dim] - == old_edge_chunk_off[op_dim]); + HDassert(max_edge_chunk_off[op_dim] == old_edge_chunk_off[op_dim]); /* Reset the chunk offset indices */ - HDmemset(chunk_offset, 0, ((unsigned)space_ndims - * sizeof(chunk_offset[0]))); + HDmemset(chunk_offset, 0, (space_ndims * sizeof(chunk_offset[0]))); chunk_offset[op_dim] = old_edge_chunk_off[op_dim]; carry = FALSE; } /* end if */ while(!carry) { + hsize_t scaled[H5O_LAYOUT_NDIMS]; /* Scaled coordinates for this chunk */ + int i; /* Local index variable */ + /* Make sure the chunk is really a former edge chunk */ - HDassert(H5D__chunk_is_partial_edge_chunk(chunk_offset, NULL, (unsigned)space_ndims, old_dim, chunk_dim) - && !H5D__chunk_is_partial_edge_chunk(chunk_offset, NULL, (unsigned)space_ndims, space_dim, chunk_dim)); + HDassert(H5D__chunk_is_partial_edge_chunk(chunk_offset, space_ndims, old_dim, chunk_dim) + && !H5D__chunk_is_partial_edge_chunk(chunk_offset, space_ndims, space_dim, chunk_dim)); - /* Calculate the index of this chunk */ - if(H5VM_chunk_index((unsigned)space_ndims, chunk_offset, chunk_dim, - layout->u.chunk.down_chunks, - &(chk_io_info.store->chunk.index)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't get chunk index") + /* Compute the scaled coordinates */ + H5VM_chunk_scaled(space_ndims, chunk_offset, chunk_dim, scaled); /* Lookup the chunk */ - if(H5D__chunk_lookup(dset, dxpl_id, chunk_offset, - chk_io_info.store->chunk.index, &chk_udata) < 0) + if(H5D__chunk_lookup(dset, dxpl_id, chunk_offset, scaled, &chk_udata) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address") /* If this chunk does not exist in cache or on disk, no need to do @@ -4194,8 +4203,8 @@ H5D__chunk_update_old_edge_chunks(H5D_t *dset, hid_t dxpl_id, hsize_t old_dim[]) /* Increment indices */ carry = TRUE; - for(i = (space_ndims - 1); i >= 0; --i) { - if(i != op_dim) { + for(i = ((int)space_ndims - 1); i >= 0; --i) { + if((unsigned)i != op_dim) { chunk_offset[i] += chunk_dim[i]; if(chunk_offset[i] > (hsize_t) max_edge_chunk_off[i]) chunk_offset[i] = 0; @@ -4420,7 +4429,7 @@ H5D__chunk_prune_fill(H5D_chunk_it_ud1_t *udata, hbool_t new_unfilt_chunk) H5_ASSIGN_OVERFLOW(chunk_size, layout->u.chunk.size, uint32_t, size_t); /* Get the info for the chunk in the file */ - if(H5D__chunk_lookup(dset, io_info->dxpl_id, chunk_offset, io_info->store->chunk.index, &chk_udata) < 0) + if(H5D__chunk_lookup(dset, io_info->dxpl_id, chunk_offset, udata->common.scaled, &chk_udata) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address") chk_udata.new_unfilt_chunk = new_unfilt_chunk; @@ -4623,14 +4632,13 @@ H5D__chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id, const hsize_t *old_dim) const H5O_layout_t *layout = &(dset->shared->layout); /* Dataset's layout */ const H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /*raw data chunk cache */ H5D_rdcc_ent_t *ent = NULL; /* Cache entry */ - int space_ndims; /* Dataset's space rank */ - hsize_t space_dim[H5O_LAYOUT_NDIMS]; /* Current dataspace dimensions */ - int op_dim; /* Current operationg dimension */ + unsigned space_ndims; /* Dataset's space rank */ + const hsize_t *space_dim; /* Current dataspace dimensions */ + unsigned op_dim; /* Current operationg dimension */ hbool_t shrunk_dim[H5O_LAYOUT_NDIMS]; /* Dimensions which have shrunk */ H5D_chunk_it_ud1_t udata; /* Chunk index iterator user data */ hbool_t udata_init = FALSE; /* Whether the chunk index iterator user data has been initialized */ H5D_chunk_common_ud_t idx_udata; /* User data for index removal routine */ - H5D_chunk_ud_t chk_udata; /* User data for getting chunk info */ H5S_t *chunk_space = NULL; /* Dataspace for a chunk */ hsize_t chunk_dim[H5O_LAYOUT_NDIMS]; /* Chunk dimensions */ hsize_t chunk_offset[H5O_LAYOUT_NDIMS]; /* Offset of current chunk */ @@ -4639,7 +4647,7 @@ H5D__chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id, const hsize_t *old_dim) hbool_t disable_edge_filters = FALSE; /* Whether to disable filters on partial edge chunks */ hbool_t new_unfilt_chunk = FALSE; /* Whether the chunk is newly unfiltered */ hbool_t carry; /* Flag to indicate that chunk increment carrys to higher dimension (sorta) */ - int i; /* Local index variable */ + unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE @@ -4664,10 +4672,8 @@ H5D__chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id, const hsize_t *old_dim) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache") /* Go get the rank & dimensions (including the element size) */ - if((space_ndims = H5S_get_simple_extent_dims(dset->shared->space, space_dim, - NULL)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataset dimensions") - space_dim[space_ndims] = layout->u.chunk.dim[space_ndims]; + space_dim = dset->shared->curr_dims; + space_ndims = dset->shared->ndims;; /* The last dimension in chunk_offset is always 0 */ chunk_offset[space_ndims] = (hsize_t)0; @@ -4686,15 +4692,14 @@ H5D__chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id, const hsize_t *old_dim) /* (also copy the chunk dimensions into 'hsize_t' array for creating dataspace) */ /* (also compute the dimensions which have been shrunk) */ elmts_per_chunk = 1; - for(i = 0; i < space_ndims; i++) { - elmts_per_chunk *= layout->u.chunk.dim[i]; - chunk_dim[i] = layout->u.chunk.dim[i]; - shrunk_dim[i] = space_dim[i] < old_dim[i]; + for(u = 0; u < space_ndims; u++) { + elmts_per_chunk *= layout->u.chunk.dim[u]; + chunk_dim[u] = layout->u.chunk.dim[u]; + shrunk_dim[u] = space_dim[u] < old_dim[u]; } /* end for */ /* Create a dataspace for a chunk & set the extent */ - if(NULL == (chunk_space = H5S_create_simple((unsigned)space_ndims, - chunk_dim, NULL))) + if(NULL == (chunk_space = H5S_create_simple(space_ndims, chunk_dim, NULL))) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace") /* Reset hyperslab start array */ @@ -4804,8 +4809,8 @@ H5D__chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id, const hsize_t *old_dim) if(has_fill) for(ent = rdcc->head; ent; ent = ent->next) /* Check for chunk offset outside of new dimensions */ - for(i = 0; i<space_ndims; i++) - if((hsize_t)ent->offset[i] >= space_dim[i]) { + for(u = 0; u < space_ndims; u++) + if((hsize_t)ent->offset[u] >= space_dim[u]) { /* Mark the entry as "deleted" */ ent->deleted = TRUE; break; @@ -4821,43 +4826,43 @@ H5D__chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id, const hsize_t *old_dim) >= min_mod_chunk_off[op_dim]); /* Reset the chunk offset indices */ - HDmemset(chunk_offset, 0, ((unsigned)space_ndims - * sizeof(chunk_offset[0]))); + HDmemset(chunk_offset, 0, (space_ndims * sizeof(chunk_offset[0]))); chunk_offset[op_dim] = min_mod_chunk_off[op_dim]; /* Initialize "dims_outside_fill" array */ ndims_outside_fill = 0; - for(i=0; i<space_ndims; i++) - if((hssize_t)chunk_offset[i] > max_fill_chunk_off[i]) { - dims_outside_fill[i] = TRUE; + for(u = 0; u < space_ndims; u++) + if((hssize_t)chunk_offset[u] > max_fill_chunk_off[u]) { + dims_outside_fill[u] = TRUE; ndims_outside_fill++; } /* end if */ else - dims_outside_fill[i] = FALSE; + dims_outside_fill[u] = FALSE; carry = FALSE; } /* end if */ while(!carry) { - /* Calculate the index of this chunk */ - if(H5VM_chunk_index((unsigned)space_ndims, chunk_offset, - layout->u.chunk.dim, layout->u.chunk.down_chunks, - &(chk_io_info.store->chunk.index)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't get chunk index") + hsize_t scaled[H5S_MAX_RANK]; /* Scaled coordinates for the current chunk */ + int i; /* Local index variable */ + + /* Compute the scaled coordinates */ + H5VM_chunk_scaled(space_ndims, chunk_offset, layout->u.chunk.dim, scaled); + udata.common.scaled = scaled; if(0 == ndims_outside_fill) { HDassert(fill_dim[op_dim]); HDassert(chunk_offset[op_dim] == min_mod_chunk_off[op_dim]); /* Make sure this is an edge chunk */ - HDassert(H5D__chunk_is_partial_edge_chunk(chunk_offset, NULL, - (unsigned)space_ndims, space_dim, layout->u.chunk.dim)); + HDassert(H5D__chunk_is_partial_edge_chunk(chunk_offset, + space_ndims, space_dim, layout->u.chunk.dim)); /* Determine if the chunk just became an unfiltered chunk */ if(new_unfilt_dim[op_dim]) { new_unfilt_chunk = TRUE; - for(i=0; i<space_ndims; i++) - if(chunk_offset[i] == min_partial_chunk_off[i]) { + for(u = 0; u < space_ndims; u++) + if(chunk_offset[u] == min_partial_chunk_off[u]) { new_unfilt_chunk = FALSE; break; } /* end if */ @@ -4866,8 +4871,8 @@ H5D__chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id, const hsize_t *old_dim) /* Make sure that, if we think this is a new unfiltered chunk, * it was previously not an edge chunk */ HDassert(!new_unfilt_dim[op_dim] || (!new_unfilt_chunk != - !H5D__chunk_is_partial_edge_chunk(chunk_offset, NULL, - (unsigned)space_ndims, old_dim, layout->u.chunk.dim))); + !H5D__chunk_is_partial_edge_chunk(chunk_offset, + space_ndims, old_dim, layout->u.chunk.dim))); HDassert(!new_unfilt_chunk || new_unfilt_dim[op_dim]); /* Fill the unused parts of the chunk */ @@ -4875,13 +4880,15 @@ H5D__chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id, const hsize_t *old_dim) HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to write fill value") } /* end if */ else { + H5D_chunk_ud_t chk_udata; /* User data for getting chunk info */ + #ifndef NDEBUG /* Make sure this chunk is really outside the new dimensions */ { hbool_t outside_dim = FALSE; - for(i=0; i<space_ndims; i++) - if(chunk_offset[i] >= space_dim[i]){ + for(u = 0; u < space_ndims; u++) + if(chunk_offset[u] >= space_dim[u]) { outside_dim = TRUE; break; } /* end if */ @@ -4890,7 +4897,7 @@ H5D__chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id, const hsize_t *old_dim) #endif /* NDEBUG */ /* Check if the chunk exists in cache or on disk */ - if(H5D__chunk_lookup(dset, dxpl_id, chunk_offset, chk_io_info.store->chunk.index, &chk_udata) < 0) + if(H5D__chunk_lookup(dset, dxpl_id, chunk_offset, udata.common.scaled, &chk_udata) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk") /* Evict the entry from the cache if present, but do not flush @@ -4905,10 +4912,10 @@ H5D__chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id, const hsize_t *old_dim) if(H5F_addr_defined(chk_udata.addr)) { /* Update the offset in idx_udata */ idx_udata.offset = chunk_offset; + idx_udata.scaled = udata.common.scaled; /* Remove the chunk from disk */ - if((layout->storage.u.chunk.ops->remove)(&idx_info, &idx_udata) - < 0) + if((layout->storage.u.chunk.ops->remove)(&idx_info, &idx_udata) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTDELETE, FAIL, "unable to remove chunk entry from index") } /* end if */ } /* end else */ @@ -4920,7 +4927,7 @@ H5D__chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id, const hsize_t *old_dim) if(chunk_offset[i] > (hsize_t) max_mod_chunk_off[i]) { /* Left maximum dimensions, "wrap around" and check if this * dimension is no longer outside the fill dimension */ - if(i == op_dim) { + if((unsigned)i == op_dim) { chunk_offset[i] = min_mod_chunk_off[i]; if(dims_outside_fill[i] && fill_dim[i]) { dims_outside_fill[i] = FALSE; @@ -5001,8 +5008,7 @@ H5D__chunk_addrmap_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata) FUNC_ENTER_STATIC /* Compute the index for this chunk */ - if(H5VM_chunk_index(rank, chunk_rec->offset, udata->common.layout->dim, udata->common.layout->down_chunks, &chunk_index) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, H5_ITER_ERROR, "can't get chunk index") + chunk_index = H5VM_chunk_index(rank, chunk_rec->offset, udata->common.layout->dim, udata->common.layout->down_chunks); /* Set it in the userdata to return */ udata->chunk_addr[chunk_index] = chunk_rec->chunk_addr; @@ -5184,7 +5190,7 @@ H5D__chunk_update_cache(H5D_t *dset, hid_t dxpl_id) H5D_rdcc_ent_t *tmp_tail; /* Tail pointer for temporary entry list */ H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */ H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */ - unsigned rank; /*current # of dimensions */ + unsigned rank; /* Current # of dimensions */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE @@ -5195,11 +5201,7 @@ H5D__chunk_update_cache(H5D_t *dset, hid_t dxpl_id) /* Get the rank */ rank = dset->shared->layout.u.chunk.ndims-1; - HDassert(rank > 0); - - /* 1-D dataset's chunks can't have their index change */ - if(rank == 1) - HGOTO_DONE(SUCCEED) + HDassert(rank > 1); /* Fill the DXPL cache values for later use */ if(H5D__get_dxpl_cache(dxpl_id, &dxpl_cache) < 0) @@ -5212,19 +5214,14 @@ H5D__chunk_update_cache(H5D_t *dset, hid_t dxpl_id) /* Recompute the index for each cached chunk that is in a dataset */ for(ent = rdcc->head; ent; ent = next) { - hsize_t idx; /* Chunk index */ unsigned old_idx; /* Previous index number */ /* Get the pointer to the next cache entry */ next = ent->next; - /* Calculate the index of this chunk */ - if(H5VM_chunk_index(rank, ent->offset, dset->shared->layout.u.chunk.dim, dset->shared->layout.u.chunk.down_chunks, &idx) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index") - /* Compute the index for the chunk entry */ old_idx = ent->idx; /* Save for later */ - ent->idx = H5D_CHUNK_HASH(dset->shared, idx); + ent->idx = H5D__chunk_hash_val(dset->shared, ent->scaled); if(old_idx != ent->idx) { /* Check if there is already a chunk at this chunk's new location */ @@ -5306,6 +5303,7 @@ H5D__chunk_copy_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata) { H5D_chunk_it_ud3_t *udata = (H5D_chunk_it_ud3_t *)_udata; /* User data for callback */ H5D_chunk_ud_t udata_dst; /* User data about new destination chunk */ + hsize_t scaled[H5S_MAX_RANK]; /* Scaled coordinates of chunk */ hbool_t is_vlen = FALSE; /* Whether datatype is variable-length */ hbool_t fix_ref = FALSE; /* Whether to fix up references in the dest. file */ @@ -5342,15 +5340,9 @@ H5D__chunk_copy_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata) /* Check if we should disable filters on this chunk */ if(udata->common.layout->flags & H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS) { - htri_t is_edge_chunk; /* Whether the chunk is an edge chunk */ - /* Check if the chunk is an edge chunk, and disable filters if so */ - if((is_edge_chunk = H5D__chunk_is_partial_edge_chunk( - chunk_rec->offset, NULL, udata->dset_ndims, - udata->dset_dims, udata->common.layout->dim)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, H5_ITER_ERROR, "unable to determine if chunk is edge chunk") - - if(!is_edge_chunk) + if(!H5D__chunk_is_partial_edge_chunk(chunk_rec->offset, udata->dset_ndims, + udata->dset_dims, udata->common.layout->dim)) must_filter = TRUE; } /* end if */ else @@ -5463,6 +5455,10 @@ H5D__chunk_copy_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata) udata->buf_size = buf_size; } /* end if */ + /* Compute the index and scaled coordinates for this chunk */ + udata_dst.chunk_idx = H5VM_chunk_index_scaled(udata_dst.common.layout->ndims - 1, chunk_rec->offset, udata_dst.common.layout->dim, udata_dst.common.layout->down_chunks, scaled); + udata_dst.common.scaled = scaled; + /* Insert chunk into the destination index */ if(H5D__idx_chunk_alloc(udata->idx_info_dst, &udata_dst) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert/resize chunk on chunk level") @@ -5475,10 +5471,6 @@ H5D__chunk_copy_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata) /* Set metadata tag in dxpl_id */ H5_BEGIN_TAG(udata->idx_info_dst->dxpl_id, H5AC__COPIED_TAG, H5_ITER_ERROR); - /* Compute the index for this chunk */ - if(H5VM_chunk_index(udata_dst.common.layout->ndims - 1, chunk_rec->offset, udata_dst.common.layout->dim, udata_dst.common.layout->down_chunks, &udata_dst.chunk_idx) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, H5_ITER_ERROR, "can't get chunk index") - if((udata_dst.need_insert || udata_dst.need_modify) && udata->idx_info_dst->storage->ops->insert_addr) { if((udata->idx_info_dst->storage->ops->insert_addr)(udata->idx_info_dst, &udata_dst) < 0) HGOTO_ERROR_TAG(H5E_DATASET, H5E_CANTINSERT, H5_ITER_ERROR, "unable to insert chunk addr into index") @@ -6198,42 +6190,25 @@ done: * *------------------------------------------------------------------------- */ -static htri_t -H5D__chunk_is_partial_edge_chunk(const hsize_t offset[], const H5D_t *dset, - unsigned dset_ndims, const hsize_t *dset_dims, const uint32_t *chunk_dims) +static hbool_t +H5D__chunk_is_partial_edge_chunk(const hsize_t offset[], unsigned dset_ndims, + const hsize_t *dset_dims, const uint32_t *chunk_dims) { - hsize_t _dset_dims[H5O_LAYOUT_NDIMS]; /* Dataset dimensions */ - unsigned i; /* Local index variables */ - htri_t ret_value = FALSE; /* Return value */ + unsigned u; /* Local index variable */ + hbool_t ret_value = FALSE; /* Return value */ - FUNC_ENTER_STATIC + FUNC_ENTER_STATIC_NOERR /* Check args */ HDassert(offset); - HDassert((chunk_dims && dset_dims) || dset); - - /* Get chunk dimensions if not specified */ - if(!chunk_dims) - chunk_dims = dset->shared->layout.u.chunk.dim; - - /* Get dataset dimensions if not specified */ - if(!dset_dims) { - int tmp_ndims; - if((tmp_ndims = H5S_get_simple_extent_dims(dset->shared->space, - _dset_dims, NULL)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, - "unable to get simple dataspace info") - - dset_dims = _dset_dims; - H5_ASSIGN_OVERFLOW(dset_ndims, tmp_ndims, int, unsigned); - } /* end if */ + HDassert(dset_ndims > 0); + HDassert(dset_dims); + HDassert(chunk_dims); /* check if this is a partial edge chunk */ - for(i=0; i<dset_ndims; i++) - if((offset[i] + chunk_dims[i]) > dset_dims[i]) { - ret_value = TRUE; - break; - } /* end if */ + for(u = 0; u < dset_ndims; u++) + if((offset[u] + chunk_dims[u]) > dset_dims[u]) + HGOTO_DONE(TRUE); done: FUNC_LEAVE_NOAPI(ret_value) @@ -6278,7 +6253,6 @@ H5D__idx_chunk_alloc(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata) if(idx_info->pline->nused > 0) { unsigned allow_chunk_size_len; /* Allowed size of encoded chunk size */ unsigned new_chunk_size_len; /* Size of encoded chunk size */ - hsize_t chunk_offset[H5O_LAYOUT_NDIMS]; H5D_chunk_ud_t found_udata; HDassert(idx_info->storage->idx_type != H5D_CHUNK_IDX_NONE); @@ -6301,8 +6275,8 @@ H5D__idx_chunk_alloc(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata) /* Initialize found_udata for ops->get_addr() */ HDmemset(&found_udata, 0, sizeof found_udata); - HDmemcpy(chunk_offset, udata->common.offset, idx_info->layout->ndims * sizeof(udata->common.offset[0])); - found_udata.common.offset = chunk_offset; + found_udata.common.offset = udata->common.offset; + found_udata.common.scaled = udata->common.scaled; found_udata.common.storage = udata->common.storage; found_udata.common.layout = udata->common.layout; found_udata.addr = HADDR_UNDEF; diff --git a/src/H5Dcompact.c b/src/H5Dcompact.c index 7d3f313..c053a68 100644 --- a/src/H5Dcompact.c +++ b/src/H5Dcompact.c @@ -174,11 +174,8 @@ H5D__compact_construct(H5F_t *f, H5D_t *dset) hssize_t stmp_size; /* Temporary holder for raw data size */ hsize_t tmp_size; /* Temporary holder for raw data size */ hsize_t max_comp_data_size; /* Max. allowed size of compact data */ - hsize_t dim[H5O_LAYOUT_NDIMS]; /* Current size of data in elements */ - hsize_t max_dim[H5O_LAYOUT_NDIMS]; /* Maximum size of data in elements */ - int ndims; /* Rank of dataspace */ - int i; /* Local index variable */ - herr_t ret_value = SUCCEED; /* Return value */ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC @@ -187,11 +184,9 @@ H5D__compact_construct(H5F_t *f, H5D_t *dset) HDassert(dset); /* Check for invalid dataset dimensions */ - if((ndims = H5S_get_simple_extent_dims(dset->shared->space, dim, max_dim)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataspace dimensions") - for(i = 0; i < ndims; i++) - if(max_dim[i] > dim[i]) - HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "extendible compact dataset") + for(u = 0; u < dset->shared->ndims; u++) + if(dset->shared->max_dims[u] > dset->shared->curr_dims[u]) + HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "extendible compact dataset not allowed") /* * Compact dataset is stored in dataset object header message of diff --git a/src/H5Dcontig.c b/src/H5Dcontig.c index 8d4cd02..11d6f60 100644 --- a/src/H5Dcontig.c +++ b/src/H5Dcontig.c @@ -396,10 +396,7 @@ H5D__contig_construct(H5F_t *f, H5D_t *dset) size_t dt_size; /* Size of datatype */ hsize_t tmp_size; /* Temporary holder for raw data size */ size_t tmp_sieve_buf_size; /* Temporary holder for sieve buffer size */ - hsize_t dim[H5O_LAYOUT_NDIMS]; /* Current size of data in elements */ - hsize_t max_dim[H5O_LAYOUT_NDIMS]; /* Maximum size of data in elements */ - int ndims; /* Rank of dataspace */ - int i; /* Local index variable */ + unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC @@ -415,11 +412,9 @@ H5D__contig_construct(H5F_t *f, H5D_t *dset) */ /* Check for invalid dataset dimensions */ - if((ndims = H5S_get_simple_extent_dims(dset->shared->space, dim, max_dim)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize contiguous storage") - for(i = 0; i < ndims; i++) - if(max_dim[i] > dim[i]) - HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "extendible contiguous non-external dataset") + for(u = 0; u < dset->shared->ndims; u++) + if(dset->shared->max_dims[u] > dset->shared->curr_dims[u]) + HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "extendible contiguous non-external dataset not allowed") /* Retrieve the number of elements in the dataspace */ if((snelmts = H5S_GET_EXTENT_NPOINTS(dset->shared->space)) < 0) diff --git a/src/H5Ddeprec.c b/src/H5Ddeprec.c index 04cf032..eb3f285 100644 --- a/src/H5Ddeprec.c +++ b/src/H5Ddeprec.c @@ -341,9 +341,7 @@ static herr_t H5D__extend(H5D_t *dataset, const hsize_t *size, hid_t dxpl_id) { htri_t changed; /* Flag to indicate that the dataspace was successfully extended */ - H5S_t *space; /* Dataset's dataspace */ - int rank; /* Dataspace # of dimensions */ - hsize_t curr_dims[H5O_LAYOUT_NDIMS];/* Current dimension sizes */ + hsize_t old_dims[H5S_MAX_RANK]; /* Current (i.e. old, if changed) dimension sizes */ H5O_fill_t *fill; /* Dataset's fill value */ herr_t ret_value = SUCCEED; /* Return value */ @@ -364,29 +362,53 @@ H5D__extend(H5D_t *dataset, const hsize_t *size, hid_t dxpl_id) */ /* Retrieve the current dimensions */ - space = dataset->shared->space; - if((rank = H5S_get_simple_extent_dims(space, curr_dims, NULL)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataset dimensions") + HDcompile_assert(sizeof(old_dims) == sizeof(dataset->shared->curr_dims)); + HDmemcpy(old_dims, dataset->shared->curr_dims, H5S_MAX_RANK * sizeof(old_dims[0])); /* Increase the size of the data space */ - if((changed = H5S_extend(space, size)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to increase size of data space") + if((changed = H5S_extend(dataset->shared->space, size)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to increase size of dataspace") /* Updated the dataset's info if the dataspace was successfully extended */ if(changed) { + /* Get the extended dimension sizes */ + /* (Need to retrieve this here, since the 'size' dimensions could + * extend one dimension but be smaller in a different dimension, + * and the dataspace's extent is the larger of the current and + * 'size' dimension values. - QAK) + */ + if(H5S_get_simple_extent_dims(dataset->shared->space, dataset->shared->curr_dims, NULL) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataset dimensions") + /* Update the index values for the cached chunks for this dataset */ if(H5D_CHUNKED == dataset->shared->layout.type) { + unsigned u; + + /* Update general information for chunks */ if(H5D__chunk_set_info(dataset) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to update # of chunks") - if(H5D__chunk_update_cache(dataset, dxpl_id) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update cached chunk indices") + + for(u = 1; u < dataset->shared->ndims; u++) { + hsize_t size_power2up; /* New size value, rounded to next power of 2 */ + + if((size_power2up = H5VM_power2up(dataset->shared->curr_dims[u])) != dataset->shared->curr_power2up[u]) { + /* Update the 'power2up' value for the current dimension */ + dataset->shared->curr_power2up[u] = size_power2up; + + /* Update the chunk cache indices */ + if(H5D__chunk_update_cache(dataset, dxpl_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update cached chunk indices") + break; + } /* end if */ + } /* end for */ + } /* end if */ /* Allocate space for the new parts of the dataset, if appropriate */ fill = &dataset->shared->dcpl_cache.fill; if(fill->alloc_time == H5D_ALLOC_TIME_EARLY) if(H5D__alloc_storage(dataset, dxpl_id, H5D_ALLOC_EXTEND, FALSE, - curr_dims) < 0) + old_dims) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize dataset with fill value") /* Mark the dataspace as dirty, for later writing to the file */ diff --git a/src/H5Dearray.c b/src/H5Dearray.c index 8df16de..fcb60aa 100644 --- a/src/H5Dearray.c +++ b/src/H5Dearray.c @@ -1166,13 +1166,11 @@ H5D_earray_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udat H5VM_swizzle_coords(hsize_t, swizzled_coords, idx_info->layout->u.earray.unlim_dim); /* Calculate the index of this chunk */ - if(H5VM_chunk_index(ndims, swizzled_coords, idx_info->layout->u.earray.swizzled_dim, idx_info->layout->u.earray.swizzled_down_chunks, &idx) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index") + idx = H5VM_chunk_index(ndims, swizzled_coords, idx_info->layout->u.earray.swizzled_dim, idx_info->layout->u.earray.swizzled_down_chunks); } /* end if */ else { /* Calculate the index of this chunk */ - if(H5VM_chunk_index((idx_info->layout->ndims - 1), udata->common.offset, idx_info->layout->dim, idx_info->layout->down_chunks, &idx) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index") + idx = H5VM_array_offset_pre((idx_info->layout->ndims - 1), idx_info->layout->down_chunks, udata->common.scaled); } /* end else */ udata->chunk_idx = idx; @@ -1415,13 +1413,11 @@ H5D_earray_idx_remove(const H5D_chk_idx_info_t *idx_info, H5D_chunk_common_ud_t H5VM_swizzle_coords(hsize_t, swizzled_coords, idx_info->layout->u.earray.unlim_dim); /* Calculate the index of this chunk */ - if(H5VM_chunk_index(ndims, swizzled_coords, idx_info->layout->u.earray.swizzled_dim, idx_info->layout->u.earray.swizzled_down_chunks, &idx) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index") + idx = H5VM_chunk_index(ndims, swizzled_coords, idx_info->layout->u.earray.swizzled_dim, idx_info->layout->u.earray.swizzled_down_chunks); } /* end if */ else { /* Calculate the index of this chunk */ - if(H5VM_chunk_index((idx_info->layout->ndims - 1), udata->offset, idx_info->layout->dim, idx_info->layout->down_chunks, &idx) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index") + idx = H5VM_array_offset_pre((idx_info->layout->ndims - 1), idx_info->layout->down_chunks, udata->scaled); } /* end else */ /* Check for filters on chunks */ diff --git a/src/H5Defl.c b/src/H5Defl.c index 38c8ccd..355492f 100644 --- a/src/H5Defl.c +++ b/src/H5Defl.c @@ -126,14 +126,11 @@ static herr_t H5D__efl_construct(H5F_t *f, H5D_t *dset) { size_t dt_size; /* Size of datatype */ - hsize_t dim[H5O_LAYOUT_NDIMS]; /* Current size of data in elements */ - hsize_t max_dim[H5O_LAYOUT_NDIMS]; /* Maximum size of data in elements */ hssize_t stmp_size; /* Temporary holder for raw data size */ hsize_t tmp_size; /* Temporary holder for raw data size */ hsize_t max_points; /* Maximum elements */ hsize_t max_storage; /* Maximum storage size */ - int ndims; /* Rank of dataspace */ - int i; /* Local index variable */ + unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC @@ -149,11 +146,9 @@ H5D__efl_construct(H5F_t *f, H5D_t *dset) */ /* Check for invalid dataset dimensions */ - if((ndims = H5S_get_simple_extent_dims(dset->shared->space, dim, max_dim)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize contiguous storage") - for(i = 1; i < ndims; i++) - if(max_dim[i] > dim[i]) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "only the first dimension can be extendible") + for(u = 1; u < dset->shared->ndims; u++) + if(dset->shared->max_dims[u] > dset->shared->curr_dims[u]) + HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "only the first dimension can be extendible") /* Retrieve the size of the dataset's datatype */ if(0 == (dt_size = H5T_get_size(dset->shared->type))) diff --git a/src/H5Dfarray.c b/src/H5Dfarray.c index 6423804..09476ab 100644 --- a/src/H5Dfarray.c +++ b/src/H5Dfarray.c @@ -1134,8 +1134,7 @@ H5D_farray_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udat fa = idx_info->storage->u.farray.fa; /* Calculate the index of this chunk */ - if(H5VM_chunk_index((idx_info->layout->ndims - 1), udata->common.offset, idx_info->layout->dim, idx_info->layout->max_down_chunks, &idx) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index") + idx = H5VM_array_offset_pre((idx_info->layout->ndims - 1), idx_info->layout->max_down_chunks, udata->common.scaled); udata->chunk_idx = idx; @@ -1355,8 +1354,7 @@ H5D_farray_idx_remove(const H5D_chk_idx_info_t *idx_info, H5D_chunk_common_ud_t fa = idx_info->storage->u.farray.fa; /* Calculate the index of this chunk */ - if(H5VM_chunk_index((idx_info->layout->ndims - 1), udata->offset, idx_info->layout->dim, idx_info->layout->max_down_chunks, &idx) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index") + idx = H5VM_array_offset_pre((idx_info->layout->ndims - 1), idx_info->layout->max_down_chunks, udata->scaled); /* Check for filters on chunks */ if(idx_info->pline->nused > 0) { diff --git a/src/H5Dint.c b/src/H5Dint.c index bddc017..c7a4704 100644 --- a/src/H5Dint.c +++ b/src/H5Dint.c @@ -62,6 +62,7 @@ static H5D_shared_t *H5D__new(hid_t dcpl_id, hbool_t creating, hbool_t vl_type); static herr_t H5D__init_type(H5F_t *file, const H5D_t *dset, hid_t type_id, const H5T_t *type); +static herr_t H5D__cache_dataspace_info(const H5D_t *dset); static herr_t H5D__init_space(H5F_t *file, const H5D_t *dset, const H5S_t *space); static herr_t H5D__swmr_setup(const H5D_t *dset, hid_t dxpl_id); static herr_t H5D__swmr_teardown(const H5D_t *dataset, hid_t dxpl_id); @@ -480,7 +481,6 @@ done: herr_t H5D__get_space_status(H5D_t *dset, H5D_space_status_t *allocation, hid_t dxpl_id) { - H5S_t *space; /* Dataset's dataspace */ hsize_t space_allocated; /* The number of bytes allocated for chunks */ hssize_t snelmts; /* Temporary holder for number of elements in dataspace */ hsize_t nelmts; /* Number of elements in dataspace */ @@ -493,11 +493,10 @@ H5D__get_space_status(H5D_t *dset, H5D_space_status_t *allocation, hid_t dxpl_id HDassert(dset); /* Get the dataset's dataspace */ - space = dset->shared->space; - HDassert(space); + HDassert(dset->shared->space); /* Get the total number of elements in dataset's dataspace */ - if((snelmts = H5S_GET_EXTENT_NPOINTS(space)) < 0) + if((snelmts = H5S_GET_EXTENT_NPOINTS(dset->shared->space)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve number of elements in dataspace") nelmts = (hsize_t)snelmts; @@ -669,6 +668,45 @@ done: /*------------------------------------------------------------------------- + * Function: H5D__cache_dataspace_info + * + * Purpose: Cache dataspace info for a dataset + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Wednesday, November 19, 2014 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D__cache_dataspace_info(const H5D_t *dset) +{ + int sndims; /* Signed number of dimensions of dataspace rank */ + unsigned u; /* Local index value */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Sanity checking */ + HDassert(dset); + + /* Cache info for dataset's dataspace */ + if((sndims = H5S_get_simple_extent_dims(dset->shared->space, dset->shared->curr_dims, dset->shared->max_dims)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't cache dataspace dimensions") + dset->shared->ndims = (unsigned)sndims; + + /* Compute the inital 'power2up' values */ + for(u = 0; u < dset->shared->ndims; u++) + dset->shared->curr_power2up[u] = H5VM_power2up(dset->shared->curr_dims[u]); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__cache_dataspace_info() */ + + +/*------------------------------------------------------------------------- * Function: H5D__init_space * * Purpose: Copy a dataspace for a dataset's use, performing all the @@ -702,6 +740,10 @@ H5D__init_space(H5F_t *file, const H5D_t *dset, const H5S_t *space) if(NULL == (dset->shared->space = H5S_copy(space, FALSE, TRUE))) HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "can't copy dataspace") + /* Cache the dataset's dataspace info */ + if(H5D__cache_dataspace_info(dset) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "can't cache dataspace info") + /* Set the latest format, if requested */ if(use_latest_format) if(H5S_set_latest_version(dset->shared->space) < 0) @@ -1365,6 +1407,10 @@ H5D__open_oid(H5D_t *dataset, hid_t dapl_id, hid_t dxpl_id) if(NULL == (dataset->shared->space = H5S_read(&(dataset->oloc), dxpl_id))) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to load dataspace info from dataset header") + /* Cache the dataset's dataspace info */ + if(H5D__cache_dataspace_info(dataset) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "can't cache dataspace info") + /* Get a datatype ID for the dataset's datatype */ if((dataset->shared->type_id = H5I_register(H5I_DATATYPE, dataset->shared->type, FALSE)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register type") @@ -2278,9 +2324,7 @@ done: herr_t H5D__set_extent(H5D_t *dset, const hsize_t *size, hid_t dxpl_id) { - H5S_t *space; /* Dataset's dataspace */ - int rank; /* Dataspace # of dimensions */ - hsize_t curr_dims[H5O_LAYOUT_NDIMS];/* Current dimension sizes */ + hsize_t curr_dims[H5S_MAX_RANK]; /* Current dimension sizes */ htri_t changed; /* Whether the dataspace changed size */ herr_t ret_value = SUCCEED; /* Return value */ @@ -2304,29 +2348,41 @@ H5D__set_extent(H5D_t *dset, const hsize_t *size, hid_t dxpl_id) if(H5D__check_filters(dset) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't apply filters") - /* Get the data space */ - space = dset->shared->space; - - /* Check if we are shrinking or expanding any of the dimensions */ - if((rank = H5S_get_simple_extent_dims(space, curr_dims, NULL)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataset dimensions") + /* Keep the current dataspace dimensions for later */ + HDcompile_assert(sizeof(curr_dims) == sizeof(dset->shared->curr_dims)); + HDmemcpy(curr_dims, dset->shared->curr_dims, H5S_MAX_RANK * sizeof(curr_dims[0])); - /* Modify the size of the data space */ - if((changed = H5S_set_extent(space, size)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to modify size of data space") + /* Modify the size of the dataspace */ + if((changed = H5S_set_extent(dset->shared->space, size)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to modify size of dataspace") /* Don't bother updating things, unless they've changed */ if(changed) { hbool_t shrink = FALSE; /* Flag to indicate a dimension has shrank */ hbool_t expand = FALSE; /* Flag to indicate a dimension has grown */ + hbool_t update_chunks = FALSE; /* Flag to indicate chunk cache update is needed */ unsigned u; /* Local index variable */ /* Determine if we are shrinking and/or expanding any dimensions */ - for(u = 0; u < (unsigned)rank; u++) { + for(u = 0; u < dset->shared->ndims; u++) { + hsize_t size_power2up; /* Size value, rounded to next power of 2 */ + + /* Check for various status changes */ if(size[u] < curr_dims[u]) shrink = TRUE; if(size[u] > curr_dims[u]) expand = TRUE; + if(dset->shared->curr_power2up[u] != (size_power2up = H5VM_power2up(size[u]))) { + /* Update the 'power2up' value for the current dimension */ + dset->shared->curr_power2up[u] = size_power2up; + + /* Only need to update the chunk indices if >1 dimension */ + if(u > 0) + update_chunks = TRUE; + } /* end if */ + + /* Update the cached copy of the dataset's dimensions */ + dset->shared->curr_dims[u] = size[u]; } /* end for */ /*------------------------------------------------------------------------- @@ -2335,10 +2391,15 @@ H5D__set_extent(H5D_t *dset, const hsize_t *size, hid_t dxpl_id) */ /* Update the index values for the cached chunks for this dataset */ if(H5D_CHUNKED == dset->shared->layout.type) { + /* Update the cached chunk info */ if(H5D__chunk_set_info(dset) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to update # of chunks") - if(H5D__chunk_update_cache(dset, dxpl_id) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update cached chunk indices") + + /* Check if updating the chunk cache indices is necessary */ + if(update_chunks) + /* Update the chunk cache indices */ + if(H5D__chunk_update_cache(dset, dxpl_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update cached chunk indices") } /* end if */ /* Allocate space for the new parts of the dataset, if appropriate */ @@ -2797,16 +2858,14 @@ H5D_get_space(H5D_t *dset) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to get data space") /* Create an atom */ - if((ret_value = H5I_register (H5I_DATASPACE, space, TRUE)) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register data space") + if((ret_value = H5I_register(H5I_DATASPACE, space, TRUE)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace") done: - if(ret_value < 0) { - if(space!=NULL) { + if(ret_value < 0) + if(space != NULL) if(H5S_close(space) < 0) HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataspace") - } /* end if */ - } /* end if */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5D_get_space() */ diff --git a/src/H5Dio.c b/src/H5Dio.c index 096a211..e9f6f10 100644 --- a/src/H5Dio.c +++ b/src/H5Dio.c @@ -302,10 +302,8 @@ H5D__pre_write(H5D_t *dset, hbool_t direct_write, hid_t mem_type_id, uint32_t direct_filters; hsize_t *direct_offset; uint32_t direct_datasize; - int ndims = 0; - hsize_t dims[H5O_LAYOUT_NDIMS]; hsize_t internal_offset[H5O_LAYOUT_NDIMS]; - int i; + unsigned u; /* Get the dataset transfer property list */ if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id))) @@ -322,25 +320,20 @@ H5D__pre_write(H5D_t *dset, hbool_t direct_write, hid_t mem_type_id, if(H5P_get(plist, H5D_XFER_DIRECT_CHUNK_WRITE_DATASIZE_NAME, &direct_datasize) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "error getting data size for direct chunk write") - /* The library's chunking code requires the offset terminates with a zero. So transfer the - * offset array to an internal offset array */ - if((ndims = H5S_get_simple_extent_dims(dset->shared->space, dims, NULL)) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't retrieve dataspace extent dims") - - for(i = 0; i < ndims; i++) { + for(u = 0; u < dset->shared->ndims; u++) { /* Make sure the offset doesn't exceed the dataset's dimensions */ - if(direct_offset[i] > dims[i]) + if(direct_offset[u] > dset->shared->curr_dims[u]) HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "offset exceeds dimensions of dataset") /* Make sure the offset fall right on a chunk's boundary */ - if(direct_offset[i] % dset->shared->layout.u.chunk.dim[i]) + if(direct_offset[u] % dset->shared->layout.u.chunk.dim[u]) HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "offset doesn't fall on chunks's boundary") - internal_offset[i] = direct_offset[i]; + internal_offset[u] = direct_offset[u]; } /* end for */ /* Terminate the offset with a zero */ - internal_offset[ndims] = 0; + internal_offset[dset->shared->ndims] = 0; /* write raw data */ if(H5D__chunk_direct_write(dset, dxpl_id, direct_filters, internal_offset, direct_datasize, buf) < 0) diff --git a/src/H5Dmpio.c b/src/H5Dmpio.c index 88c6075..11cb913 100644 --- a/src/H5Dmpio.c +++ b/src/H5Dmpio.c @@ -835,6 +835,7 @@ H5D__link_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *typ if(total_chunks == 1) { H5D_chunk_ud_t udata; /* User data for querying chunk info */ hsize_t coords[H5O_LAYOUT_NDIMS]; /* Coordinates of chunk in file dataset's dataspace */ + hsize_t scaled[H5O_LAYOUT_NDIMS]; /* Scaled coordinates for this chunk */ H5SL_node_t *chunk_node; /* Pointer to chunk node for selection */ H5S_t *fspace; /* Dataspace describing chunk & selection in it */ H5S_t *mspace; /* Dataspace describing selection in memory corresponding to this chunk */ @@ -842,10 +843,10 @@ H5D__link_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *typ /* Initialize the chunk coordinates */ /* (must be all zero, since there's only one chunk) */ HDmemset(coords, 0, sizeof(coords)); + HDmemset(scaled, 0, sizeof(scaled)); /* Look up address of chunk */ - if(H5D__chunk_lookup(io_info->dset, io_info->dxpl_id, coords, - io_info->store->chunk.index, &udata) < 0) + if(H5D__chunk_lookup(io_info->dset, io_info->dxpl_id, coords, scaled, &udata) < 0) HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't get chunk info from skipped list") ctg_store.contig.dset_addr = udata.addr; @@ -1204,7 +1205,6 @@ if(H5DEBUG(D)) /* Pass in chunk's coordinates in a union. */ store.chunk.offset = chunk_info->coords; - store.chunk.index = chunk_info->index; } /* end if */ /* Collective IO for this chunk, @@ -1592,7 +1592,7 @@ if(H5DEBUG(D)) /* Get address of chunk */ if(H5D__chunk_lookup(io_info->dset, io_info->dxpl_id, - chunk_info->coords, chunk_info->index, &udata) < 0) + chunk_info->coords, chunk_info->scaled, &udata) < 0) HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't get chunk info from skipped list") chunk_addr = udata.addr; } /* end if */ diff --git a/src/H5Dnone.c b/src/H5Dnone.c index 60194c3..c059066 100644 --- a/src/H5Dnone.c +++ b/src/H5Dnone.c @@ -192,10 +192,7 @@ H5D_none_is_space_alloc(const H5O_storage_chunk_t *storage) static herr_t H5D_none_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata) { - hsize_t idx; /* Array index of chunk */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_NOAPI_NOINIT_NOERR HDassert(idx_info); HDassert(idx_info->f); @@ -207,20 +204,16 @@ H5D_none_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata) HDassert(H5F_addr_defined(idx_info->storage->idx_addr)); /* Calculate the index of this chunk */ - if(H5VM_chunk_index((idx_info->layout->ndims - 1), udata->common.offset, idx_info->layout->dim, idx_info->layout->max_down_chunks, &idx) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index") - - udata->chunk_idx = idx; + udata->chunk_idx = H5VM_array_offset_pre((idx_info->layout->ndims - 1), idx_info->layout->max_down_chunks, udata->common.scaled); /* Calculate the address of the chunk */ - udata->addr = idx_info->storage->idx_addr + idx * idx_info->layout->size; + udata->addr = idx_info->storage->idx_addr + udata->chunk_idx * idx_info->layout->size; /* Update the other (constant) information for the chunk */ udata->nbytes = idx_info->layout->size; udata->filter_mask = 0; -done: - FUNC_LEAVE_NOAPI(ret_value) + FUNC_LEAVE_NOAPI(SUCCEED) } /* H5D_none_get_addr() */ @@ -248,7 +241,7 @@ H5D_none_iterate(const H5D_chk_idx_info_t *idx_info, hsize_t idx; /* Array index of chunk */ int ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_NOAPI_NOINIT_NOERR HDassert(idx_info); HDassert(idx_info->f); @@ -273,8 +266,7 @@ H5D_none_iterate(const H5D_chk_idx_info_t *idx_info, /* Iterate over all the chunks in the dataset's dataspace */ for(u = 0; u < idx_info->layout->nchunks; u++) { /* Calculate the index of this chunk */ - if(H5VM_chunk_index(ndims, chunk_rec.offset, idx_info->layout->dim, idx_info->layout->max_down_chunks, &idx) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index") + idx = H5VM_chunk_index(ndims, chunk_rec.offset, idx_info->layout->dim, idx_info->layout->max_down_chunks); /* Calculate the address of the chunk */ chunk_rec.chunk_addr = idx_info->storage->idx_addr + idx * idx_info->layout->size; @@ -302,7 +294,6 @@ H5D_none_iterate(const H5D_chk_idx_info_t *idx_info, } /* end while */ } /* end for */ -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5D_none_iterate() */ diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h index 10591d4..108ee03 100644 --- a/src/H5Dpkg.h +++ b/src/H5Dpkg.h @@ -61,8 +61,6 @@ (io_info)->op_type = H5D_IO_OP_READ; \ (io_info)->u.rbuf = buf -#define H5D_CHUNK_HASH(D, ADDR) H5F_addr_hash(ADDR, (D)->cache.chunk.nslots) - /* Flags for marking aspects of a dataset dirty */ #define H5D_MARK_SPACE 0x01 #define H5D_MARK_LAYOUT 0x02 @@ -186,7 +184,6 @@ typedef struct { } H5D_contig_storage_t; typedef struct { - hsize_t index; /* "Index" of chunk in dataset (must be first for TBBT routines) */ hsize_t *offset; /* Chunk's coordinates in elements */ } H5D_chunk_storage_t; @@ -276,6 +273,8 @@ typedef struct H5D_chunk_common_ud_t { const H5O_layout_chunk_t *layout; /* Chunk layout description */ const H5O_storage_chunk_t *storage; /* Chunk storage description */ const hsize_t *offset; /* Logical offset of chunk */ + const hsize_t *space_dim; /* Dataset dimension sizes */ + const hsize_t *scaled; /* Scaled coordinates for a chunk */ 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 */ @@ -351,6 +350,7 @@ typedef struct H5D_chunk_info_t { hsize_t index; /* "Index" of chunk in dataset */ uint32_t chunk_points; /* Number of elements selected in chunk */ hsize_t coords[H5O_LAYOUT_NDIMS]; /* Coordinates of chunk in file dataset's dataspace */ + hsize_t scaled[H5O_LAYOUT_NDIMS]; /* Scaled coordinates of chunk (in file dataset's dataspace) */ H5S_t *fspace; /* Dataspace describing chunk & selection in it */ unsigned fspace_shared; /* Indicate that the file space for a chunk is shared and shouldn't be freed */ H5S_t *mspace; /* Dataspace describing selection in memory corresponding to this chunk */ @@ -389,11 +389,11 @@ typedef struct H5D_chunk_map_t { } H5D_chunk_map_t; /* Cached information about a particular chunk */ -typedef struct H5D_chunk_cached_t{ +typedef struct H5D_chunk_cached_t { hbool_t valid; /*whether cache info is valid*/ hsize_t offset[H5O_LAYOUT_NDIMS]; /*logical offset to start*/ uint32_t nbytes; /*size of stored data */ - hsize_t chunk_idx; /*index of chunk in dataset */ + hsize_t chunk_idx; /*index of chunk in dataset */ unsigned filter_mask; /*excluded filters */ haddr_t addr; /*file address of chunk */ } H5D_chunk_cached_t; @@ -450,6 +450,12 @@ typedef struct H5D_shared_t { H5O_t *oh; /* Pointer to dataset's object header, pinned */ hbool_t is_swimming; /* TRUE if dataset has SWMR access enabled */ + /* Cached dataspace info */ + unsigned ndims; /* The dataset's dataspace rank */ + hsize_t curr_dims[H5S_MAX_RANK]; /* The curr. size of dataset dimensions */ + hsize_t curr_power2up[H5S_MAX_RANK]; /* The curr. dim sizes, rounded up to next power of 2 */ + hsize_t max_dims[H5S_MAX_RANK]; /* The max. size of dataset dimensions */ + /* Buffered/cached information for types of raw data storage*/ struct { H5D_rdcdc_t contig; /* Information about contiguous data */ @@ -531,10 +537,11 @@ typedef struct H5D_rdcc_ent_t { hbool_t deleted; /*chunk about to be deleted (do not flush) */ unsigned edge_chunk_state; /*states related to edge chunks (see above) */ hsize_t offset[H5O_LAYOUT_NDIMS]; /*chunk name */ + hsize_t scaled[H5O_LAYOUT_NDIMS]; /*scaled chunk 'name' (coordinates) */ uint32_t rd_count; /*bytes remaining to be read */ uint32_t wr_count; /*bytes remaining to be written */ haddr_t chunk_addr; /*address of chunk in file */ - hsize_t chunk_idx; /*index of chunk in dataset */ + hsize_t chunk_idx; /*index of chunk in dataset */ uint8_t *chunk; /*the unfiltered chunk data */ unsigned idx; /*index in hash table */ struct H5D_rdcc_ent_t *next;/*next item in doubly-linked list */ @@ -663,7 +670,7 @@ H5_DLL herr_t H5D__chunk_init(H5F_t *f, hid_t dxpl_id, const H5D_t *dset, hid_t dapl_id); H5_DLL hbool_t H5D__chunk_is_space_alloc(const H5O_storage_t *storage); H5_DLL herr_t H5D__chunk_lookup(const H5D_t *dset, hid_t dxpl_id, - const hsize_t *chunk_offset, hsize_t chunk_idx, H5D_chunk_ud_t *udata); + const hsize_t *chunk_offset, const hsize_t *scaled, H5D_chunk_ud_t *udata); H5_DLL void *H5D__chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata, hbool_t relax, hbool_t prev_unfilt_chunk); H5_DLL herr_t H5D__chunk_unlock(const H5D_io_info_t *io_info, @@ -1259,21 +1259,119 @@ done: * The chunk index is placed in the CHUNK_IDX location for return * from this function * - * Return: Non-negative on success/Negative on failure + * Return: Chunk index on success (can't fail) * * Programmer: Quincey Koziol * Monday, April 21, 2003 * - * Modifications: - * *------------------------------------------------------------------------- */ -herr_t +hsize_t H5VM_chunk_index(unsigned ndims, const hsize_t *coord, const uint32_t *chunk, - const hsize_t *down_nchunks, hsize_t *chunk_idx) + const hsize_t *down_nchunks) { - hsize_t scaled_coord[H5VM_HYPER_NDIMS]; /* Scaled, coordinates, in terms of chunks */ - unsigned u; /* Local index variable */ + hsize_t scaled_coord[H5VM_HYPER_NDIMS]; /* Scaled, coordinates, in terms of chunks */ + hsize_t chunk_idx; /* Chunk index computed */ + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + /* Sanity check */ + HDassert(ndims <= H5VM_HYPER_NDIMS); + HDassert(coord); + HDassert(chunk); + HDassert(down_nchunks); + + /* Defer to H5VM_chunk_index_scaled */ + chunk_idx = H5VM_chunk_index_scaled(ndims, coord, chunk, down_nchunks, scaled_coord); + + FUNC_LEAVE_NOAPI(chunk_idx) +} /* end H5VM_chunk_index() */ + + +/*------------------------------------------------------------------------- + * Function: H5VM_chunk_scaled + * + * Purpose: Compute the scaled coordinates for a chunk offset + * + * Return: <none> + * + * Programmer: Quincey Koziol + * Wednesday, November 19, 2014 + * + *------------------------------------------------------------------------- + */ +void +H5VM_chunk_scaled(unsigned ndims, const hsize_t *coord, const uint32_t *chunk, + hsize_t *scaled) +{ + unsigned u; /* Local index variable */ + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + /* Sanity check */ + HDassert(ndims <= H5VM_HYPER_NDIMS); + HDassert(coord); + HDassert(chunk); + HDassert(scaled); + + /* Compute the scaled coordinates for actual coordinates */ + /* (Note that the 'scaled' array is an 'OUT' parameter) */ + for(u = 0; u < ndims; u++) + scaled[u] = coord[u] / chunk[u]; + + FUNC_LEAVE_NOAPI_VOID +} /* end H5VM_chunk_scaled() */ + + +/*------------------------------------------------------------------------- + * Function: H5VM_chunk_index_scaled + * + * Purpose: Given a coordinate offset (COORD), the size of each chunk + * (CHUNK), the number of chunks in each dimension (NCHUNKS) + * and the number of dimensions of all of these (NDIMS), calculate + * a "chunk index" for the chunk that the coordinate offset is + * located in. + * + * The chunk index starts at 0 and increases according to the + * fastest changing dimension, then the next fastest, etc. + * + * For example, with a 3x5 chunk size and 6 chunks in the fastest + * changing dimension and 3 chunks in the slowest changing + * dimension, the chunk indices are as follows: + * + * +-----+-----+-----+-----+-----+-----+ + * | | | | | | | + * | 0 | 1 | 2 | 3 | 4 | 5 | + * | | | | | | | + * +-----+-----+-----+-----+-----+-----+ + * | | | | | | | + * | 6 | 7 | 8 | 9 | 10 | 11 | + * | | | | | | | + * +-----+-----+-----+-----+-----+-----+ + * | | | | | | | + * | 12 | 13 | 14 | 15 | 16 | 17 | + * | | | | | | | + * +-----+-----+-----+-----+-----+-----+ + * + * The chunk index is placed in the CHUNK_IDX location for return + * from this function + * + * Note: This routine is identical to H5VM_chunk_index(), except for + * caching the scaled information. Make changes in both places. + * + * Return: Chunk index on success (can't fail) + * + * Programmer: Quincey Koziol + * Monday, April 21, 2003 + * + *------------------------------------------------------------------------- + */ +hsize_t +H5VM_chunk_index_scaled(unsigned ndims, const hsize_t *coord, const uint32_t *chunk, + const hsize_t *down_nchunks, hsize_t *scaled) +{ + hsize_t chunk_idx; /* Computed chunk index */ + unsigned u; /* Local index variable */ FUNC_ENTER_NOAPI_NOINIT_NOERR @@ -1281,17 +1379,19 @@ H5VM_chunk_index(unsigned ndims, const hsize_t *coord, const uint32_t *chunk, HDassert(ndims <= H5VM_HYPER_NDIMS); HDassert(coord); HDassert(chunk); - HDassert(chunk_idx); + HDassert(down_nchunks); + HDassert(scaled); /* Compute the scaled coordinates for actual coordinates */ - for(u=0; u<ndims; u++) - scaled_coord[u]=coord[u]/chunk[u]; + /* (Note that the 'scaled' array is an 'OUT' parameter) */ + for(u = 0; u < ndims; u++) + scaled[u] = coord[u] / chunk[u]; /* Compute the chunk index */ - *chunk_idx=H5VM_array_offset_pre(ndims,down_nchunks,scaled_coord); /*lint !e772 scaled_coord will always be initialized */ + chunk_idx = H5VM_array_offset_pre(ndims, down_nchunks, scaled); /*lint !e772 scaled_coord will always be initialized */ - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5VM_chunk_index() */ + FUNC_LEAVE_NOAPI(chunk_idx) +} /* end H5VM_chunk_index_scaled() */ /*------------------------------------------------------------------------- diff --git a/src/H5VMprivate.h b/src/H5VMprivate.h index 9170b93..fe7baed 100644 --- a/src/H5VMprivate.h +++ b/src/H5VMprivate.h @@ -124,8 +124,12 @@ H5_DLL herr_t H5VM_array_calc_pre(hsize_t offset, unsigned n, const hsize_t *down, hsize_t *coords); H5_DLL herr_t H5VM_array_calc(hsize_t offset, unsigned n, const hsize_t *total_size, hsize_t *coords); -H5_DLL herr_t H5VM_chunk_index(unsigned ndims, const hsize_t *coord, - const uint32_t *chunk, const hsize_t *down_nchunks, hsize_t *chunk_idx); +H5_DLL hsize_t H5VM_chunk_index(unsigned ndims, const hsize_t *coord, + const uint32_t *chunk, const hsize_t *down_nchunks); +H5_DLL void H5VM_chunk_scaled(unsigned ndims, const hsize_t *coord, + const uint32_t *chunk, hsize_t *scaled); +H5_DLL hsize_t H5VM_chunk_index_scaled(unsigned ndims, const hsize_t *coord, + const uint32_t *chunk, const hsize_t *down_nchunks, hsize_t *scaled); H5_DLL ssize_t H5VM_opvv(size_t dst_max_nseq, size_t *dst_curr_seq, size_t dst_len_arr[], hsize_t dst_off_arr[], size_t src_max_nseq, size_t *src_curr_seq, size_t src_len_arr[], @@ -454,6 +458,29 @@ H5VM_log2_of2(uint32_t n) /*------------------------------------------------------------------------- + * Function: H5VM_power2up + * + * Purpose: Round up a number to the next power of 2 + * + * Return: Return the number which is a power of 2 + * + * Programmer: Vailin Choi; Nov 2014 + * + *------------------------------------------------------------------------- + */ +static H5_inline hsize_t UNUSED +H5VM_power2up(hsize_t n) +{ + hsize_t ret_value = 1; /* Return value */ + + while(ret_value < n) + ret_value <<= 1; + + return(ret_value); +} /* H5VM_power2up */ + + +/*------------------------------------------------------------------------- * Function: H5VM_limit_enc_size * * Purpose: Determine the # of bytes needed to encode values within a |