/*------------------------------------------------------------------------- * Function: H5B2__update_leaf * * Purpose: Insert or modify a record in a B-tree leaf node. * If the record exists already, it is modified as if H5B2_modify * was called). If it doesn't exist, it is inserted as if * H5B2_insert was called. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * [email protected] * Dec 23 2015 * *------------------------------------------------------------------------- */ herr_t H5B2__update_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *curr_node_ptr, H5B2_update_status_t *status, H5B2_nodepos_t curr_pos, void *parent, void *udata, H5B2_modify_t op, void *op_data) { H5B2_leaf_t *leaf; /* Pointer to leaf node */ unsigned leaf_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting the leaf node */ int cmp = -1; /* Comparison value of records */ unsigned idx = 0; /* Location of record which matches key */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* Check arguments. */ HDassert(hdr); HDassert(curr_node_ptr); HDassert(H5F_addr_defined(curr_node_ptr->addr)); /* Lock current B-tree node */ if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, parent, curr_node_ptr, FALSE, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node") /* Sanity check number of records */ HDassert(curr_node_ptr->all_nrec == curr_node_ptr->node_nrec); HDassert(leaf->nrec == curr_node_ptr->node_nrec); /* Check for inserting into empty leaf */ if(leaf->nrec == 0) idx = 0; else { /* Find correct location to insert this record */ if(H5B2__locate_record(hdr->cls, leaf->nrec, hdr->nat_off, leaf->leaf_native, udata, &idx, &cmp) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTCOMPARE, FAIL, "can't compare btree2 records") /* Check for inserting a record */ if(0 != cmp) { /* Check if the leaf node is full */ if(curr_node_ptr->node_nrec == hdr->node_info[0].split_nrec) { /* Indicate that the leaf is full, but we need to insert */ *status = H5B2_UPDATE_INSERT_CHILD_FULL; /* Let calling routine handle insertion */ HGOTO_DONE(SUCCEED) } /* end if */ /* Adjust index to leave room for record to insert */ if(cmp > 0) idx++; /* Make room for new record */ if(idx < leaf->nrec) HDmemmove(H5B2_LEAF_NREC(leaf, hdr, idx + 1), H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size * (leaf->nrec - idx)); } /* end if */ } /* end else */
/*------------------------------------------------------------------------- * Function: H5F_cwfs_add * * Purpose: Add a global heap collection to the CWFS for a file. * * Return: Success: Non-negative * Failure: Negative * * Programmer: Quincey Koziol * Tuesday, July 19, 2011 * *------------------------------------------------------------------------- */ herr_t H5F_cwfs_add(H5F_t *f, H5HG_heap_t *heap) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) /* Check args */ HDassert(f); HDassert(f->shared); HDassert(heap); /* * Add the new heap to the CWFS list, removing some other entry if * necessary to make room. We remove the right-most entry that has less * free space than this heap. */ if(NULL == f->shared->cwfs) { if(NULL == (f->shared->cwfs = (H5HG_heap_t **)H5MM_malloc(H5F_NCWFS * sizeof(H5HG_heap_t *)))) HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't allocate CWFS for file") f->shared->cwfs[0] = heap; f->shared->ncwfs = 1; } else if(H5F_NCWFS == f->shared->ncwfs) { int i; /* Local index variable */ for(i = H5F_NCWFS - 1; i >= 0; --i) if(H5HG_FREE_SIZE(f->shared->cwfs[i]) < H5HG_FREE_SIZE(heap)) { HDmemmove(f->shared->cwfs + 1, f->shared->cwfs, (size_t)i * sizeof(H5HG_heap_t *)); f->shared->cwfs[0] = heap; break; } /* end if */ } else { HDmemmove(f->shared->cwfs + 1, f->shared->cwfs, f->shared->ncwfs * sizeof(H5HG_heap_t *)); f->shared->cwfs[0] = heap; f->shared->ncwfs += 1; } /* end else */ done: FUNC_LEAVE_NOAPI(ret_value) } /* H5F_cwfs_add() */
/*------------------------------------------------------------------------- * Function: H5F_accum_read * * Purpose: Attempts to read some data from the metadata accumulator for * a file into a buffer. * * Note: We can't change (or add to) the metadata accumulator, because * this might be a speculative read and could possibly read raw * data into the metadata accumulator. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * [email protected] * Jan 10 2008 * *------------------------------------------------------------------------- */ herr_t H5F_accum_read(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr, size_t size, void *buf/*out*/) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) HDassert(f); HDassert(f->shared); HDassert(buf); /* Check if this information is in the metadata accumulator */ if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && type != H5FD_MEM_DRAW) { if(size < H5F_ACCUM_MAX_SIZE) { /* Sanity check */ HDassert(!f->shared->accum.buf || (f->shared->accum.alloc_size >= f->shared->accum.size)); /* Current read adjoins or overlaps with metadata accumulator */ if(H5F_addr_overlap(addr, size, f->shared->accum.loc, f->shared->accum.size) || ((addr + size) == f->shared->accum.loc) || (f->shared->accum.loc + f->shared->accum.size) == addr) { size_t amount_before; /* Amount to read before current accumulator */ haddr_t new_addr; /* New address of the accumulator buffer */ size_t new_size; /* New size of the accumulator buffer */ /* Compute new values for accumulator */ new_addr = MIN(addr, f->shared->accum.loc); new_size = (size_t)(MAX((addr + size), (f->shared->accum.loc + f->shared->accum.size)) - new_addr); /* Check if we need more buffer space */ if(new_size > f->shared->accum.alloc_size) { size_t new_alloc_size; /* New size of accumulator */ /* Adjust the buffer size to be a power of 2 that is large enough to hold data */ new_alloc_size = (size_t)1 << (1 + H5V_log2_gen((uint64_t)(new_size - 1))); /* Reallocate the metadata accumulator buffer */ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, new_alloc_size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer") /* Note the new buffer size */ f->shared->accum.alloc_size = new_alloc_size; #ifdef H5_CLEAR_MEMORY HDmemset(f->shared->accum.buf + f->shared->accum.size, 0, (f->shared->accum.alloc_size - f->shared->accum.size)); #endif /* H5_CLEAR_MEMORY */ } /* end if */ /* Read the part before the metadata accumulator */ if(addr < f->shared->accum.loc) { /* Set the amount to read */ H5_ASSIGN_OVERFLOW(amount_before, (f->shared->accum.loc - addr), hsize_t, size_t); /* Make room for the metadata to read in */ HDmemmove(f->shared->accum.buf + amount_before, f->shared->accum.buf, f->shared->accum.size); /* Adjust dirty region tracking info, if present */ if(f->shared->accum.dirty) f->shared->accum.dirty_off += amount_before; /* Dispatch to driver */ if(H5FD_read(f->shared->lf, dxpl_id, type, addr, amount_before, f->shared->accum.buf) < 0) HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed") } /* end if */ else
/*------------------------------------------------------------------------- * Function: H5F__accum_read * * Purpose: Attempts to read some data from the metadata accumulator for * a file into a buffer. * * Note: We can't change (or add to) the metadata accumulator, because * this might be a speculative read and could possibly read raw * data into the metadata accumulator. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * [email protected] * Jan 10 2008 * *------------------------------------------------------------------------- */ herr_t H5F__accum_read(H5F_t *f, H5FD_mem_t map_type, haddr_t addr, size_t size, void *buf/*out*/) { H5FD_t *file; /* File driver pointer */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* Sanity checks */ HDassert(f); HDassert(buf); /* Translate to file driver I/O info object */ file = f->shared->lf; /* Check if this information is in the metadata accumulator */ if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && map_type != H5FD_MEM_DRAW) { H5F_meta_accum_t *accum; /* Alias for file's metadata accumulator */ /* Set up alias for file's metadata accumulator info */ accum = &f->shared->accum; if(size < H5F_ACCUM_MAX_SIZE) { /* Sanity check */ HDassert(!accum->buf || (accum->alloc_size >= accum->size)); /* Current read adjoins or overlaps with metadata accumulator */ if(H5F_addr_overlap(addr, size, accum->loc, accum->size) || ((addr + size) == accum->loc) || (accum->loc + accum->size) == addr) { size_t amount_before; /* Amount to read before current accumulator */ haddr_t new_addr; /* New address of the accumulator buffer */ size_t new_size; /* New size of the accumulator buffer */ /* Compute new values for accumulator */ new_addr = MIN(addr, accum->loc); new_size = (size_t)(MAX((addr + size), (accum->loc + accum->size)) - new_addr); /* Check if we need more buffer space */ if(new_size > accum->alloc_size) { size_t new_alloc_size; /* New size of accumulator */ /* Adjust the buffer size to be a power of 2 that is large enough to hold data */ new_alloc_size = (size_t)1 << (1 + H5VM_log2_gen((uint64_t)(new_size - 1))); /* Reallocate the metadata accumulator buffer */ if(NULL == (accum->buf = H5FL_BLK_REALLOC(meta_accum, accum->buf, new_alloc_size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer") /* Note the new buffer size */ accum->alloc_size = new_alloc_size; /* Clear the memory */ HDmemset(accum->buf + accum->size, 0, (accum->alloc_size - accum->size)); } /* end if */ /* Read the part before the metadata accumulator */ if(addr < accum->loc) { /* Set the amount to read */ H5_CHECKED_ASSIGN(amount_before, size_t, (accum->loc - addr), hsize_t); /* Make room for the metadata to read in */ HDmemmove(accum->buf + amount_before, accum->buf, accum->size); /* Adjust dirty region tracking info, if present */ if(accum->dirty) accum->dirty_off += amount_before; /* Dispatch to driver */ if(H5FD_read(file, map_type, addr, amount_before, accum->buf) < 0) HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed") } /* end if */
/*------------------------------------------------------------------------- * Function: H5B2__insert_leaf * * Purpose: Adds a new record to a B-tree leaf node. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * [email protected] * Mar 3 2005 * *------------------------------------------------------------------------- */ herr_t H5B2__insert_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *curr_node_ptr, H5B2_nodepos_t curr_pos, void *parent, void *udata) { H5B2_leaf_t *leaf; /* Pointer to leaf node */ unsigned leaf_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting the leaf node */ int cmp; /* Comparison value of records */ unsigned idx = 0; /* Location of record which matches key */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* Check arguments. */ HDassert(hdr); HDassert(curr_node_ptr); HDassert(H5F_addr_defined(curr_node_ptr->addr)); /* Lock current B-tree node */ if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, parent, curr_node_ptr, FALSE, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node") /* Must have a leaf node with enough space to insert a record now */ HDassert(curr_node_ptr->node_nrec < hdr->node_info[0].max_nrec); /* Sanity check number of records */ HDassert(curr_node_ptr->all_nrec == curr_node_ptr->node_nrec); HDassert(leaf->nrec == curr_node_ptr->node_nrec); /* Check for inserting into empty leaf */ if(leaf->nrec == 0) idx = 0; else { /* Find correct location to insert this record */ if(H5B2__locate_record(hdr->cls, leaf->nrec, hdr->nat_off, leaf->leaf_native, udata, &idx, &cmp) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTCOMPARE, FAIL, "can't compare btree2 records") if(cmp == 0) HGOTO_ERROR(H5E_BTREE, H5E_EXISTS, FAIL, "record is already in B-tree") if(cmp > 0) idx++; /* Make room for new record */ if(idx < leaf->nrec) HDmemmove(H5B2_LEAF_NREC(leaf, hdr, idx + 1), H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size * (leaf->nrec - idx)); } /* end else */ /* Make callback to store record in native form */ if((hdr->cls->store)(H5B2_LEAF_NREC(leaf, hdr, idx), udata) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into leaf node") /* Mark the node as dirty */ leaf_flags |= H5AC__DIRTIED_FLAG; /* Update record count for node pointer to current node */ curr_node_ptr->all_nrec++; curr_node_ptr->node_nrec++; /* Update record count for current node */ leaf->nrec++; /* 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 = H5MM_malloc(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 = H5MM_malloc(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) { /* Shadow the node if doing SWMR writes */ if(hdr->swmr_write && (leaf_flags & H5AC__DIRTIED_FLAG)) if(H5B2__shadow_leaf(leaf, dxpl_id, curr_node_ptr) < 0) HDONE_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow leaf B-tree node") /* Unprotect leaf node */ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr->addr, leaf, leaf_flags) < 0) HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release leaf B-tree node") } /* end if */ FUNC_LEAVE_NOAPI(ret_value) } /* H5B2__insert_leaf() */