Ejemplo n.º 1
0
/*-------------------------------------------------------------------------
 * 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 */
Ejemplo n.º 2
0
/*-------------------------------------------------------------------------
 * 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
Ejemplo n.º 4
0
/*-------------------------------------------------------------------------
 * 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 */
Ejemplo n.º 5
0
/*-------------------------------------------------------------------------
 * 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() */