/*-------------------------------------------------------------------------
 * Function:	H5A_dense_build_table
 *
 * Purpose:     Builds a table containing a sorted list of attributes for
 *              an object
 *
 * Note:	Used for building table of attributes in non-native iteration
 *              order for an index.  Uses the "name" index to retrieve records,
 *		but the 'idx_type' index for sorting them.
 *
 * Return:	Success:        Non-negative
 *		Failure:	Negative
 *
 * Programmer:	Quincey Koziol
 *	        Dec 11, 2006
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5A_dense_build_table(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
    H5_index_t idx_type, H5_iter_order_t order, H5A_attr_table_t *atable)
{
    H5B2_t *bt2_name = NULL;            /* v2 B-tree handle for name index */
    hsize_t nrec;                       /* # of records in v2 B-tree */
    herr_t ret_value = SUCCEED;         /* Return value */

    FUNC_ENTER_NOAPI_NOINIT

    /* Sanity check */
    HDassert(f);
    HDassert(ainfo);
    HDassert(H5F_addr_defined(ainfo->fheap_addr));
    HDassert(H5F_addr_defined(ainfo->name_bt2_addr));
    HDassert(atable);

    /* Open the name index v2 B-tree */
    if(NULL == (bt2_name = H5B2_open(f, dxpl_id, ainfo->name_bt2_addr, NULL)))
        HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index")

    /* Retrieve # of records in "name" B-tree */
    /* (should be same # of records in all indices) */
    if(H5B2_get_nrec(bt2_name, &nrec) < 0)
        HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't retrieve # of records in index")

    /* Set size of table */
    H5_CHECK_OVERFLOW(nrec, /* From: */ hsize_t, /* To: */ size_t);
    atable->nattrs = (size_t)nrec;

    /* Allocate space for the table entries */
    if(atable->nattrs > 0) {
        H5A_dense_bt_ud_t udata;       /* User data for iteration callback */
        H5A_attr_iter_op_t attr_op;    /* Attribute operator */

        /* Allocate the table to store the attributes */
        if((atable->attrs = (H5A_t **)H5FL_SEQ_CALLOC(H5A_t_ptr, atable->nattrs)) == NULL)
            HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")

        /* Set up user data for iteration */
        udata.atable = atable;
        udata.curr_attr = 0;

        /* Build iterator operator */
        attr_op.op_type = H5A_ATTR_OP_LIB;
        attr_op.u.lib_op = H5A_dense_build_table_cb;

        /* Iterate over the links in the group, building a table of the link messages */
        if(H5A_dense_iterate(f, dxpl_id, (hid_t)0, ainfo, H5_INDEX_NAME,
                H5_ITER_NATIVE, (hsize_t)0, NULL, &attr_op, &udata) < 0)
            HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "error building attribute table")

        /* Sort attribute table in correct iteration order */
        if(H5A_attr_sort_table(atable, idx_type, order) < 0)
            HGOTO_ERROR(H5E_ATTR, H5E_CANTSORT, FAIL, "error sorting attribute table")
    } /* end if */
Example #2
0
/*-------------------------------------------------------------------------
 * Function:	H5FS_close
 *
 * Purpose:	Destroy & deallocate free list structure, serializing sections
 *              in the bins
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Quincey Koziol
 *              Tuesday, March  7, 2006
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace)
{
    herr_t ret_value = SUCCEED;         /* Return value */

    FUNC_ENTER_NOAPI_TAG(dxpl_id, H5AC__FREESPACE_TAG, FAIL)

    /* Check arguments. */
    HDassert(f);
    HDassert(fspace);
#ifdef H5FS_DEBUG
HDfprintf(stderr, "%s: Entering, fspace = %p, fspace->addr = %a, fspace->sinfo = %p\n", FUNC, fspace, fspace->addr, fspace->sinfo);
#endif /* H5FS_DEBUG */

    /* Check if section info is valid */
    /* (i.e. the header "owns" the section info and it's not in the cache) */
    if(fspace->sinfo) {
#ifdef H5FS_DEBUG
HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu, fspace->serial_sect_count = %Hu, fspace->sect_addr = %a, fspace->rc = %u\n", FUNC, fspace->tot_sect_count, fspace->serial_sect_count, fspace->sect_addr, fspace->rc);
HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n", FUNC, fspace->alloc_sect_size, fspace->sect_size);
#endif /* H5FS_DEBUG */
        /* If there are sections to serialize, update them */
        /* (if the free space manager is persistant) */
        if(fspace->serial_sect_count > 0 && H5F_addr_defined(fspace->addr)) {
#ifdef H5FS_DEBUG
HDfprintf(stderr, "%s: Real sections to store in file\n", FUNC);
#endif /* H5FS_DEBUG */
            if(fspace->sinfo->dirty) {
                /* Check if the section info is "floating" */
                if(!H5F_addr_defined(fspace->sect_addr)) {
                    /* Sanity check */
                    HDassert(fspace->sect_size > 0);

                    /* Allocate space for the section info in file */
                    if(H5F_USE_TMP_SPACE(f)) {
                        if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc_tmp(f, fspace->sect_size)))
                            HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
                    } /* end if */
                    else {
                        if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_size)))
                            HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
                    } /* end if */
                    fspace->alloc_sect_size = (size_t)fspace->sect_size;

                    /* Mark free space header as dirty */
                    if(H5AC_mark_entry_dirty(fspace) < 0)
                        HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty")
                } /* end if */
Example #3
0
/*-------------------------------------------------------------------------
 * Function:	H5D__single_idx_get_addr
 *
 * Purpose:	Get the file address of a chunk.
 *		Save the retrieved information in the udata supplied.
 *
 * Return:	Non-negative on success/Negative on failure
 *
 * Programmer:	Vailin Choi; July 2010
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5D__single_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata)
{
    FUNC_ENTER_STATIC_NOERR

    /* Sanity checks */
    HDassert(idx_info);
    HDassert(idx_info->f);
    HDassert(idx_info->pline);
    HDassert(idx_info->layout);
    HDassert(idx_info->storage);
    HDassert(idx_info->layout->nchunks == 1);
    HDassert(idx_info->layout->max_nchunks == 1);
    HDassert(udata);

    udata->chunk_block.offset = idx_info->storage->idx_addr;
    if(idx_info->layout->flags & H5O_LAYOUT_CHUNK_SINGLE_INDEX_WITH_FILTER) {
	udata->chunk_block.length = idx_info->storage->u.single.nbytes;
	udata->filter_mask = idx_info->storage->u.single.filter_mask;
    } /* end if */
    else {
	udata->chunk_block.length = idx_info->layout->size;
	udata->filter_mask = 0;
    } /* end else */
    if(!H5F_addr_defined(udata->chunk_block.offset))
        udata->chunk_block.length = 0;

    FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5D__single_idx_get_addr() */
Example #4
0
/*-------------------------------------------------------------------------
 * Function:	H5MF_alloc_open
 *
 * Purpose:	Open an existing free space manager of TYPE for file by
 *		creating a free-space structure
 *
 * Return:	Success:	non-negative
 *		Failure:	negative
 *
 * Programmer:	Quincey Koziol
 *		[email protected]
 *		Jan  8 2008
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5MF_alloc_open(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type)
{
    const H5FS_section_class_t *classes[] = { /* Free space section classes implemented for file */
        H5MF_FSPACE_SECT_CLS_SIMPLE};
    herr_t ret_value = SUCCEED;         /* Return value */

    FUNC_ENTER_NOAPI_NOINIT

    /*
     * Check arguments.
     */
    HDassert(f);
    HDassert(f->shared);
    HDassert(type != H5FD_MEM_NOLIST);
    HDassert(H5F_addr_defined(f->shared->fs_addr[type]));
    HDassert(f->shared->fs_state[type] == H5F_FS_STATE_CLOSED);

    /* Open an existing free space structure for the file */
    if(NULL == (f->shared->fs_man[type] = H5FS_open(f, dxpl_id, f->shared->fs_addr[type],
	    NELMTS(classes), classes, f, f->shared->alignment, f->shared->threshold)))
	HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space info")

    /* Set the state for the free space manager to "open", if it is now */
    if(f->shared->fs_man[type])
        f->shared->fs_state[type] = H5F_FS_STATE_OPEN;

done:
    FUNC_LEAVE_NOAPI(ret_value)
} /* end H5MF_alloc_open() */
Example #5
0
/*-------------------------------------------------------------------------
 * Function:	H5D__single_idx_remove
 *
 * Purpose:	Remove the single chunk
 *
 * Return:	Non-negative on success/Negative on failure
 *
 * Programmer:	Vailin Choi; July 2011
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5D__single_idx_remove(const H5D_chk_idx_info_t *idx_info, H5D_chunk_common_ud_t H5_ATTR_UNUSED *udata)
{
    hsize_t nbytes;                 /* Size of all chunks */
    herr_t ret_value = SUCCEED;     /* Return value */

    FUNC_ENTER_STATIC

    /* Sanity checks */
    HDassert(idx_info);
    HDassert(idx_info->f);
    HDassert(idx_info->pline);
    HDassert(idx_info->layout);
    HDassert(idx_info->storage);
    HDassert(H5F_addr_defined(idx_info->storage->idx_addr));

    if(idx_info->layout->flags & H5O_LAYOUT_CHUNK_SINGLE_INDEX_WITH_FILTER)
	nbytes = idx_info->storage->u.single.nbytes;
    else
	nbytes = idx_info->layout->size;

    if(H5MF_xfree(idx_info->f, H5FD_MEM_DRAW, idx_info->dxpl_id, idx_info->storage->idx_addr, nbytes) < 0)
        HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, H5_ITER_ERROR, "unable to free dataset chunks")

    idx_info->storage->idx_addr = HADDR_UNDEF;

done:
    FUNC_LEAVE_NOAPI(ret_value)
} /* H5D__single_idx_remove() */
/*-------------------------------------------------------------------------
 * Function:	H5F__drvrinfo_prefix_decode
 *
 * Purpose:	Decode a driver info prefix
 *
 * Return:      Non-negative on success/Negative on failure
 *
 * Programmer:  Quincey Koziol
 *              December 15, 2016
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5F__drvrinfo_prefix_decode(H5O_drvinfo_t *drvrinfo, char *drv_name,
    const uint8_t **image_ref, H5F_drvrinfo_cache_ud_t *udata,
    hbool_t extend_eoa)
{
    const uint8_t	*image = (const uint8_t *)*image_ref;   /* Pointer into raw data buffer */
    unsigned            drv_vers;       /* Version of driver info block */
    herr_t ret_value = SUCCEED;         /* Return value */

    FUNC_ENTER_STATIC

    /* Sanity check */
    HDassert(drvrinfo);
    HDassert(image_ref);
    HDassert(image);
    HDassert(udata);
    HDassert(udata->f);

    /* Version number */
    drv_vers = *image++;
    if(drv_vers != HDF5_DRIVERINFO_VERSION_0)
        HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad driver information block version number")

    image += 3; /* reserved bytes */

    /* Driver info size */
    UINT32DECODE(image, drvrinfo->len);

    /* Driver name and/or version */
    if(drv_name) { 
        HDmemcpy(drv_name, (const char *)image, (size_t)8);
        drv_name[8] = '\0';
        image += 8; /* advance past name/version */
    } /* end if */

    /* Extend the EOA if required so that we can read the complete driver info block */
    if(extend_eoa) {
        haddr_t eoa;                /* Current EOA for the file */
        haddr_t min_eoa;            /* Minimum EOA needed for reading the driver info */

        /* Get current EOA... */
        eoa = H5FD_get_eoa(udata->f->shared->lf, H5FD_MEM_SUPER);
        if(!H5F_addr_defined(eoa))
            HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "driver get_eoa request failed")

        /* ... if it is too small, extend it. */
        min_eoa = udata->driver_addr + H5F_DRVINFOBLOCK_HDR_SIZE + drvrinfo->len;

        /* If it grew, set it */
        if(H5F_addr_gt(min_eoa, eoa))
            if(H5FD_set_eoa(udata->f->shared->lf, H5FD_MEM_SUPER, min_eoa) < 0)
                HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "set end of space allocation request failed")
    } /* end if */

    /* Update the image buffer pointer */
    *image_ref = image;

done:
    FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F__drvrinfo_prefix_decode() */
Example #7
0
/*-------------------------------------------------------------------------
 * Function:	H5D__single_idx_copy_setup
 *
 * Purpose:	Set up any necessary information for copying the single chunk
 *
 * Return:	Non-negative on success/Negative on failure
 *
 * Programmer:	Vailin Choi; Sept 2011
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5D__single_idx_copy_setup(const H5D_chk_idx_info_t *idx_info_src,
    const H5D_chk_idx_info_t *idx_info_dst)
{
    herr_t      ret_value = SUCCEED;    /* Return value */

    FUNC_ENTER_STATIC

    /* Check args */
    HDassert(idx_info_src);
    HDassert(idx_info_src->f);
    HDassert(idx_info_src->pline);
    HDassert(idx_info_src->layout);
    HDassert(idx_info_src->storage);
    HDassert(H5F_addr_defined(idx_info_src->storage->idx_addr));

    HDassert(idx_info_dst);
    HDassert(idx_info_dst->f);
    HDassert(idx_info_dst->pline);
    HDassert(idx_info_dst->layout);
    HDassert(idx_info_dst->storage);

    /* Set copied metadata tag */
    H5_BEGIN_TAG(idx_info_dst->dxpl_id, H5AC__COPIED_TAG, FAIL);

    /* Set up information at the destination file */
    if(H5D__single_idx_create(idx_info_dst) < 0)
        HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize chunked storage")

    /* Reset metadata tag */
    H5_END_TAG(FAIL);

done:
    FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__single_idx_copy_setup() */
Example #8
0
/*-------------------------------------------------------------------------
 * Function:    H5MF_xfree
 *
 * Purpose:     Frees part of a file, making that part of the file
 *              available for reuse.
 *
 * Return:      Non-negative on success/Negative on failure
 *
 * Programmer:  Robb Matzke
 *              [email protected]
 *              Jul 17 1997
 *
 * Modifications:
 *		Robb Matzke, 1999-07-28
 *		The ADDR argument is passed by value
 *
 * 		Robb Matzke, 1999-08-03
 *		Modified to use the virtual file layer.
 *-------------------------------------------------------------------------
 */
herr_t
H5MF_xfree(H5F_t *f, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t size)
{
    herr_t      ret_value=SUCCEED;       /* Return value */

    FUNC_ENTER_NOAPI_NOFUNC(H5MF_xfree);

    /* check arguments */
    assert(f);
    if (!H5F_addr_defined(addr) || 0 == size)
        HGOTO_DONE(SUCCEED);
    assert(addr!=0);

    /* Convert relative address to absolute address */
    addr += f->shared->base_addr;

    /* Allow virtual file layer to free block */
    if (H5FD_free(f->shared->lf, type, dxpl_id, addr, size)<0) {
#ifdef H5MF_DEBUG
	if (H5DEBUG(MF)) {
	    fprintf(H5DEBUG(MF),
		    "H5MF_free: lost %lu bytes of file storage\n",
		    (unsigned long)size);
	}
#endif
    }

done:
    FUNC_LEAVE_NOAPI(ret_value);
}
Example #9
0
/*-------------------------------------------------------------------------
 * Function:	H5HF_space_start
 *
 * Purpose:	"Start up" free space for heap - open existing free space
 *              structure if one exists, otherwise create a new free space
 *              structure
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Quincey Koziol
 *		[email protected]
 *		May  2 2006
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5HF_space_start(H5HF_hdr_t *hdr, hid_t dxpl_id, hbool_t may_create)
{
    const H5FS_section_class_t *classes[] = { /* Free space section classes implemented for fractal heap */
        H5HF_FSPACE_SECT_CLS_SINGLE,
        H5HF_FSPACE_SECT_CLS_FIRST_ROW,
        H5HF_FSPACE_SECT_CLS_NORMAL_ROW,
        H5HF_FSPACE_SECT_CLS_INDIRECT};
    herr_t ret_value = SUCCEED;         /* Return value */

    FUNC_ENTER_NOAPI_NOINIT(H5HF_space_start)

    /*
     * Check arguments.
     */
    HDassert(hdr);

    /* Check for creating free space info for the heap */
    if(H5F_addr_defined(hdr->fs_addr)) {
        /* Open an existing free space structure for the heap */
        if(NULL == (hdr->fspace = H5FS_open(hdr->f, dxpl_id, hdr->fs_addr,
                NELMTS(classes), classes, hdr)))
            HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize free space info")
    } /* end if */
    else {
        /* Check if we are allowed to create the free space manager */
        if(may_create) {
Example #10
0
/*-------------------------------------------------------------------------
 * Function:    H5SM_get_mesg_count_test
 *
 * Purpose:     Retrieve the number of messages tracked of a certain type
 *
 * Return:      Non-negative on success/Negative on failure
 *
 * Programmer:  Quincey Koziol
 *              Wednesday, January  3, 2007
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5SM_get_mesg_count_test(H5F_t *f, hid_t dxpl_id, unsigned type_id,
    size_t *mesg_count)
{
    H5SM_master_table_t *table = NULL;  /* SOHM master table */
    herr_t ret_value = SUCCEED;         /* Return value */

    FUNC_ENTER_NOAPI_NOINIT(H5SM_get_mesg_count_test)

    /* Sanity check */
    HDassert(f);
    HDassert(mesg_count);

    /* Check for shared messages being enabled */
    if(H5F_addr_defined(f->shared->sohm_addr)) {
        H5SM_index_header_t *header;        /* Index header for message type */
        H5SM_table_cache_ud_t cache_udata;  /* User-data for callback */
        ssize_t index_num;                  /* Table index for message type */

        /* Set up user data for callback */
        cache_udata.f = f;

        /* Look up the master SOHM table */
        if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, f->shared->sohm_addr, &cache_udata, H5AC_READ)))
            HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table")

        /* Find the correct index for this message type */
        if((index_num = H5SM_get_index(table, type_id)) < 0)
            HGOTO_ERROR(H5E_SOHM, H5E_NOTFOUND, FAIL, "unable to find correct SOHM index")
        header = &(table->indexes[index_num]);

        /* Set the message count for the type */
        *mesg_count = header->num_messages;
    } /* end if */
Example #11
0
/*-------------------------------------------------------------------------
 * Function:	H5D__single_idx_is_space_alloc
 *
 * Purpose:	Query if space is allocated for the single chunk
 *
 * Return:	Non-negative on success/Negative on failure
 *
 * Programmer:	Vailin Choi; July 2011
 *
 *-------------------------------------------------------------------------
 */
static hbool_t
H5D__single_idx_is_space_alloc(const H5O_storage_chunk_t *storage)
{
    FUNC_ENTER_STATIC_NOERR

    /* Check args */
    HDassert(storage);

    FUNC_LEAVE_NOAPI((hbool_t)H5F_addr_defined(storage->idx_addr))
} /* end H5D__single_idx_is_space_alloc() */
/*-------------------------------------------------------------------------
 * Function:	H5HG_load
 *
 * Purpose:	Loads a global heap collection from disk.
 *
 * Return:	Success:	Ptr to a global heap collection.
 *
 *		Failure:	NULL
 *
 * Programmer:	Robb Matzke
 *              Friday, March 27, 1998
 *
 *-------------------------------------------------------------------------
 */
static H5HG_heap_t *
H5HG_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1,
	   void UNUSED * udata2)
{
    H5HG_heap_t	*heap = NULL;
    uint8_t	*p = NULL;
    size_t	nalloc, need;
    size_t      max_idx = 0;            /* The maximum index seen */
    H5HG_heap_t	*ret_value = NULL;      /* Return value */

    FUNC_ENTER_NOAPI(H5HG_load, NULL)

    /* check arguments */
    HDassert(f);
    HDassert(H5F_addr_defined(addr));
    HDassert(!udata1);
    HDassert(!udata2);

    /* Read the initial 4k page */
    if(NULL == (heap = H5FL_CALLOC(H5HG_heap_t)))
	HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
    heap->addr = addr;
    if(NULL == (heap->chunk = H5FL_BLK_MALLOC(gheap_chunk, (size_t)H5HG_MINSIZE)))
	HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
    if(H5F_block_read(f, H5FD_MEM_GHEAP, addr, (size_t)H5HG_MINSIZE, dxpl_id, heap->chunk) < 0)
	HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read global heap collection")

    /* Magic number */
    if(HDmemcmp(heap->chunk, H5HG_MAGIC, (size_t)H5_SIZEOF_MAGIC))
	HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad global heap collection signature")
    p = heap->chunk + H5_SIZEOF_MAGIC;

    /* Version */
    if(H5HG_VERSION != *p++)
	HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong version number in global heap")

    /* Reserved */
    p += 3;

    /* Size */
    H5F_DECODE_LENGTH(f, p, heap->size);
    HDassert(heap->size >= H5HG_MINSIZE);

    /*
     * If we didn't read enough in the first try, then read the rest of the
     * collection now.
     */
    if(heap->size > H5HG_MINSIZE) {
	haddr_t next_addr = addr + (hsize_t)H5HG_MINSIZE;

	if(NULL == (heap->chunk = H5FL_BLK_REALLOC(gheap_chunk, heap->chunk, heap->size)))
	    HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
	if(H5F_block_read(f, H5FD_MEM_GHEAP, next_addr, (heap->size - H5HG_MINSIZE), dxpl_id, heap->chunk + H5HG_MINSIZE) < 0)
	    HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read global heap collection")
    } /* end if */
Example #13
0
/*-------------------------------------------------------------------------
 * Function:	H5FS_open
 *
 * Purpose:	Open an existing file free space info structure on disk
 *
 * Return:	Success:	Pointer to free space structure
 *
 *		Failure:	NULL
 *
 * Programmer:	Quincey Koziol
 *              Tuesday, May  2, 2006
 *
 * Modfications:
 *
 *	Vailin Choi, July 29th, 2008
 *	  Add two more parameters for handling alignment: alignment & threshhold
 *
 *-------------------------------------------------------------------------
 */
H5FS_t *
H5FS_open(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr, size_t nclasses,
    const H5FS_section_class_t *classes[], void *cls_init_udata, hsize_t alignment, hsize_t threshold)
{
    H5FS_t *fspace = NULL;      /* New free space structure */
    H5FS_hdr_cache_ud_t cache_udata; /* User-data for metadata cache callback */
    H5FS_t *ret_value;          /* Return value */

    FUNC_ENTER_NOAPI_TAG(dxpl_id, H5AC__FREESPACE_TAG, NULL)
#ifdef H5FS_DEBUG
HDfprintf(stderr, "%s: Opening free space manager, fs_addr = %a, nclasses = %Zu\n", FUNC, fs_addr, nclasses);
#endif /* H5FS_DEBUG */

    /* Check arguments. */
    HDassert(H5F_addr_defined(fs_addr));
    HDassert(nclasses);
    HDassert(classes);

    /* Initialize user data for protecting the free space manager */
    cache_udata.f = f;
    cache_udata.nclasses = nclasses;
    cache_udata.classes = classes;
    cache_udata.cls_init_udata = cls_init_udata;
    cache_udata.addr = fs_addr;

    /* Protect the free space header */
    if(NULL == (fspace = (H5FS_t *)H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, &cache_udata, H5AC_READ)))
        HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, NULL, "unable to load free space header")
#ifdef H5FS_DEBUG
HDfprintf(stderr, "%s: fspace->sect_addr = %a\n", FUNC, fspace->sect_addr);
HDfprintf(stderr, "%s: fspace->sect_size = %Hu\n", FUNC, fspace->sect_size);
HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu\n", FUNC, fspace->alloc_sect_size);
HDfprintf(stderr, "%s: fspace->sinfo = %p\n", FUNC, fspace->sinfo);
HDfprintf(stderr, "%s: fspace->rc = %u\n", FUNC, fspace->rc);
#endif /* H5FS_DEBUG */

    /* Increment the reference count on the free space manager header */
    HDassert(fspace->rc <= 1);
    if(H5FS_incr(fspace) < 0)
        HGOTO_ERROR(H5E_FSPACE, H5E_CANTINC, NULL, "unable to increment ref. count on free space header")

    fspace->alignment = alignment;
    fspace->threshold = threshold;

    /* Unlock free space header */
    if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, fspace, H5AC__NO_FLAGS_SET) < 0)
        HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPROTECT, NULL, "unable to release free space header")

    /* Set return value */
    ret_value = fspace;

done:
    FUNC_LEAVE_NOAPI_TAG(ret_value, NULL)
} /* H5FS_open() */
Example #14
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 */
Example #15
0
/*-------------------------------------------------------------------------
 *
 * Function:    H5C__tag_entry
 *
 * Purpose:     Tags an entry with the provided tag (contained in the API context).
 *              If sanity checking is enabled, this function will perform 
 *              validation that a proper tag is contained within the provided 
 *              data access property list id before application.
 *
 * Return:      FAIL if error is detected, SUCCEED otherwise.
 *
 * Programmer:  Mike McGreevy
 *              January 14, 2010
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5C__tag_entry(H5C_t *cache, H5C_cache_entry_t *entry)
{
    H5C_tag_info_t *tag_info;	/* Points to a tag info struct */
    haddr_t tag;                /* Tag value */
    herr_t ret_value = SUCCEED;  /* Return value */

    FUNC_ENTER_PACKAGE

    /* Assertions */
    HDassert(cache != NULL);
    HDassert(entry != NULL);
    HDassert(cache->magic == H5C__H5C_T_MAGIC);

    /* Get the tag */
    tag = H5CX_get_tag();

    if(cache->ignore_tags) {
        /* if we're ignoring tags, it's because we're running
           tests on internal functions and may not have inserted a tag 
           value into a given API context before creating some metadata. Thus,
           in this case only, if a tag value has not been set, we can
           arbitrarily set it to something for the sake of passing the tests. 
           If the tag value is set, then we'll just let it get assigned without
           additional checking for correctness. */
        if(!H5F_addr_defined(tag))
            tag = H5AC__IGNORE_TAG;
    } /* end if */
#if H5C_DO_TAGGING_SANITY_CHECKS
    else {
        /* Perform some sanity checks to ensure that a correct tag is being applied */
        if(H5C_verify_tag(entry->type->id, tag) < 0)
            HGOTO_ERROR(H5E_CACHE, H5E_CANTTAG, FAIL, "tag verification failed")
    } /* end else */
#endif

    /* Search the list of tagged object addresses in the cache */
    tag_info = (H5C_tag_info_t *)H5SL_search(cache->tag_list, &tag);

    /* Check if this is the first entry for this tagged object */
    if(NULL == tag_info) {
        /* Allocate new tag info struct */
        if(NULL == (tag_info = H5FL_CALLOC(H5C_tag_info_t)))
            HGOTO_ERROR(H5E_CACHE, H5E_CANTALLOC, FAIL, "can't allocate tag info for cache entry")

        /* Set the tag for all entries */
        tag_info->tag = tag;

        /* Insert tag info into skip list */
        if(H5SL_insert(cache->tag_list, tag_info, &(tag_info->tag)) < 0 )
            HGOTO_ERROR(H5E_CACHE, H5E_CANTINSERT, FAIL, "can't insert tag info in skip list")
    } /* end if */
    else
Example #16
0
/*-------------------------------------------------------------------------
 * Function:	H5D__single_idx_delete
 *
 * Purpose:	Delete raw data storage for entire dataset (i.e. the only chunk)
 *
 * Return:	Success:	Non-negative
 *		Failure:	negative
 *
 * Programmer:	Vailin Choi; Sept 2011
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5D__single_idx_delete(const H5D_chk_idx_info_t *idx_info)
{
    herr_t ret_value = SUCCEED;     /* Return value */

    FUNC_ENTER_STATIC_NOERR

    /* Sanity checks */
    HDassert(idx_info);
    HDassert(idx_info->f);
    HDassert(idx_info->pline);
    HDassert(idx_info->layout);
    HDassert(idx_info->storage);

    if(H5F_addr_defined(idx_info->storage->idx_addr))
	ret_value = H5D__single_idx_remove(idx_info, NULL);
    else
	HDassert(!H5F_addr_defined(idx_info->storage->idx_addr));

    FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__single_idx_delete() */
Example #17
0
/*-------------------------------------------------------------------------
 * Function:	H5B2__neighbor_leaf
 *
 * Purpose:	Locate a record relative to the specified information in a
 *              B-tree leaf node and return that information by filling in
 *              fields of the
 *              caller-supplied UDATA pointer depending on the type of leaf node
 *		requested.  The UDATA can point to additional data passed
 *		to the key comparison function.
 *
 *              The 'OP' routine is called with the record found and the
 *              OP_DATA pointer, to allow caller to return information about
 *              the record.
 *
 *              The RANGE indicates whether to search for records less than or
 *              equal to, or greater than or equal to the information passed
 *              in with UDATA.
 *
 * Return:	Non-negative on success, negative on failure.
 *
 * Programmer:	Quincey Koziol
 *		[email protected]
 *		Mar  9 2005
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5B2__neighbor_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *curr_node_ptr,
    void *neighbor_loc, H5B2_compare_t comp, void *parent, void *udata, H5B2_found_t op,
    void *op_data)
{
    H5B2_leaf_t *leaf;                  /* Pointer to leaf node */
    unsigned    idx = 0;                /* Location of record which matches key */
    int         cmp = 0;                /* Comparison value of records */
    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));
    HDassert(op);

    /* Lock current B-tree node */
    if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, parent, curr_node_ptr, FALSE, H5AC__READ_ONLY_FLAG)))
        HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")

    /* Locate node pointer for child */
    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)
        idx++;
    else
        if(cmp == 0 && comp == H5B2_COMPARE_GREATER)
            idx++;

    /* Set the neighbor location, if appropriate */
    if(comp == H5B2_COMPARE_LESS) {
        if(idx > 0)
            neighbor_loc = H5B2_LEAF_NREC(leaf, hdr, idx - 1);
    } /* end if */
    else {
        HDassert(comp == H5B2_COMPARE_GREATER);

        if(idx < leaf->nrec)
            neighbor_loc = H5B2_LEAF_NREC(leaf, hdr, idx);
    } /* end else */

    /* Make callback if neighbor record has been found */
    if(neighbor_loc) {
        /* Make callback for current record */
        if((op)(neighbor_loc, op_data) < 0)
            HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "'found' callback failed for B-tree neighbor operation")
    } /* end if */
    else
Example #18
0
/*-------------------------------------------------------------------------
 * Function:    H5O_ainfo_copy_file
 *
 * Purpose:     Copies a message from _MESG to _DEST in file
 *
 * Return:      Success:        Ptr to _DEST
 *              Failure:        NULL
 *
 * Programmer:  Peter Cao
 *              July 18, 2007
 *
 *-------------------------------------------------------------------------
 */
static void *
H5O_ainfo_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst,
    hbool_t H5_ATTR_UNUSED *recompute_size, unsigned H5_ATTR_UNUSED *mesg_flags,
    H5O_copy_t *cpy_info, void H5_ATTR_UNUSED *udata, hid_t dxpl_id)
{
    H5O_ainfo_t *ainfo_src = (H5O_ainfo_t *)mesg_src;
    H5O_ainfo_t *ainfo_dst = NULL;
    void *ret_value = NULL;     /* Return value */

    FUNC_ENTER_NOAPI_NOINIT

    /* check args */
    HDassert(file_src);
    HDassert(ainfo_src);
    HDassert(file_dst);
    HDassert(cpy_info);
    HDassert(!cpy_info->copy_without_attr);

    /* Allocate space for the destination message */
    if(NULL == (ainfo_dst = H5FL_MALLOC(H5O_ainfo_t)))
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")

    /* Copy the top level of the information */
    *ainfo_dst = *ainfo_src;

    if(H5F_addr_defined(ainfo_src->fheap_addr)) {
        /* Prepare to copy dense attributes - actual copy in post_copy */

        /* Set copied metadata tag */
        H5_BEGIN_TAG(dxpl_id, H5AC__COPIED_TAG, NULL);

        if(H5A_dense_create(file_dst, dxpl_id, ainfo_dst) < 0)
            HGOTO_ERROR_TAG(H5E_OHDR, H5E_CANTINIT, NULL, "unable to create dense storage for attributes")

        /* Reset metadata tag */
        H5_END_TAG(NULL);
    } /* end if */

    /* Set return value */
    ret_value = ainfo_dst;

done:
    /* Release destination attribute information on failure */
    if(!ret_value && ainfo_dst)
        ainfo_dst = H5FL_FREE(H5O_ainfo_t, ainfo_dst);

    FUNC_LEAVE_NOAPI(ret_value)
} /* H5O_ainfo_copy_file() */
Example #19
0
/*-------------------------------------------------------------------------
 * Function:	H5MF_alloc_overflow
 *
 * Purpose:	Checks if an allocation of file space would cause an overflow.
 *          F is the file whose space is being allocated, SIZE is the amount
 *          of space needed.
 *
 * Return:	0 if no overflow would result
 *          1 if overflow would result (the allocation should not be allowed)
 *
 * Programmer:	James Laird
 *				Nat Furrer
 *              Tuesday, June 1, 2004
 *
 * Modifications:
 *-------------------------------------------------------------------------
 */
hbool_t
H5MF_alloc_overflow(H5F_t *f, hsize_t size)
{
    hsize_t space_needed;       /* Accumulator variable */
    size_t c;                   /* Local index variable */
    hbool_t ret_value;           /* Return value */

    FUNC_ENTER_NOAPI_NOFUNC(H5MF_alloc_overflow)

    /* Start with the current end of the file's address. */
    space_needed = (hsize_t)H5F_get_eoa(f);
    HDassert(H5F_addr_defined(space_needed));

    /* Subtract the file's base address to get the actual amount of
     * space being used:
     * (end of allocated space - beginning of allocated space)
     */
    HDassert(H5F_BASE_ADDR(f) < space_needed);
    space_needed -= (hsize_t)H5F_BASE_ADDR(f);

    /* Add the amount of space requested for this allocation */
    space_needed += size;

    /* Also add space that is "reserved" for data to be flushed
     * to disk (e.g., for object headers and the heap).
     * This is the total amount of file space that will be
     * allocated.
     */
    space_needed += f->shared->lf->reserved_alloc;

    /* Ensure that this final number is less than the file's
     * address space.  We do this by shifting in multiples
     * of 16 bits because some systems will do nothing if
     * we shift by the size of a long long (64 bits) all at
     * once (<cough> Linux <cough>).  Thus, we break one shift
     * into several smaller shifts.
     */
    for(c=0; c < H5F_SIZEOF_ADDR(f); c += 2)
        space_needed = space_needed >> 16;

    if(space_needed != 0)
        ret_value=TRUE;
    else
        ret_value=FALSE;

    FUNC_LEAVE_NOAPI(ret_value)
}
Example #20
0
/*-------------------------------------------------------------------------
 * Function:	H5O_efl_encode
 *
 * Purpose:	Encodes a message.
 *
 * Return:	Non-negative on success/Negative on failure
 *
 * Programmer:	Robb Matzke
 *		Tuesday, November 25, 1997
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5O_efl_encode(H5F_t *f, hbool_t UNUSED disable_shared, uint8_t *p, const void *_mesg)
{
    const H5O_efl_t	*mesg = (const H5O_efl_t *)_mesg;
    size_t		u;      /* Local index variable */

    FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_efl_encode)

    /* check args */
    HDassert(f);
    HDassert(mesg);
    HDassert(p);

    /* Version */
    *p++ = H5O_EFL_VERSION;

    /* Reserved */
    *p++ = 0;
    *p++ = 0;
    *p++ = 0;

    /* Number of slots */
    HDassert(mesg->nalloc > 0);
    UINT16ENCODE(p, mesg->nused); /*yes, twice*/
    HDassert(mesg->nused > 0 && mesg->nused <= mesg->nalloc);
    UINT16ENCODE(p, mesg->nused);

    /* Heap address */
    HDassert(H5F_addr_defined(mesg->heap_addr));
    H5F_addr_encode(f, &p, mesg->heap_addr);

    /* Encode file list */
    for(u = 0; u < mesg->nused; u++) {
	/*
	 * The name should have been added to the heap when the dataset was
	 * created.
	 */
	HDassert(mesg->slot[u].name_offset);
	H5F_ENCODE_LENGTH(f, p, mesg->slot[u].name_offset);
	H5F_ENCODE_LENGTH(f, p, mesg->slot[u].offset);
	H5F_ENCODE_LENGTH(f, p, mesg->slot[u].size);
    } /* end for */

    FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_efl_encode() */
Example #21
0
/*-------------------------------------------------------------------------
 * Function:    H5O_ainfo_post_copy_file
 *
 * Purpose:     Finish copying a message from between files.
 *              We have to copy the values of a reference attribute in the
 *              post copy because H5O_post_copy_file() fails in the case that
 *              an object may have a reference attribute that points to the
 *              object itself.
 *
 * Return:      Non-negative on success/Negative on failure
 *
 * Programmer:  Peter Cao
 *              July 25, 2007
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5O_ainfo_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src,
    H5O_loc_t *dst_oloc, void *mesg_dst, unsigned H5_ATTR_UNUSED *mesg_flags,
    hid_t dxpl_id, H5O_copy_t *cpy_info)
{
    const H5O_ainfo_t *ainfo_src = (const H5O_ainfo_t *)mesg_src;
    herr_t ret_value = SUCCEED;   /* Return value */

    FUNC_ENTER_NOAPI_NOINIT

    HDassert(ainfo_src);

    if(H5F_addr_defined(ainfo_src->fheap_addr)) {
        if(H5A_dense_post_copy_file_all(src_oloc, ainfo_src, dst_oloc,
                (H5O_ainfo_t *)mesg_dst, dxpl_id, cpy_info) < 0)
        HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "can't copy attribute")
    } /* end if */

done:
    FUNC_LEAVE_NOAPI(ret_value)
} /* H5O_ainfo_post_copy_file() */
Example #22
0
/*-------------------------------------------------------------------------
 * Function:    H5O_ainfo_encode
 *
 * Purpose:     Encodes a message.
 *
 * Return:      Non-negative on success/Negative on failure
 *
 * Programmer:  Quincey Koziol
 *              [email protected]
 *              Mar  6 2007
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5O_ainfo_encode(H5F_t *f, hbool_t H5_ATTR_UNUSED disable_shared, uint8_t *p, const void *_mesg)
{
    const H5O_ainfo_t   *ainfo = (const H5O_ainfo_t *)_mesg;
    unsigned char       flags;          /* Flags for encoding attribute info */

    FUNC_ENTER_NOAPI_NOINIT_NOERR

    /* check args */
    HDassert(f);
    HDassert(p);
    HDassert(ainfo);

    /* Message version */
    *p++ = H5O_AINFO_VERSION;

    /* The flags for the attribute indices */
    flags = ainfo->track_corder ? H5O_AINFO_TRACK_CORDER : 0;
    flags = (unsigned char)(flags | (ainfo->index_corder ? H5O_AINFO_INDEX_CORDER : 0));
    *p++ = flags;

    /* Max. creation order value for the object */
    if(ainfo->track_corder)
        UINT16ENCODE(p, ainfo->max_crt_idx);

    /* Address of fractal heap to store "dense" attributes */
    H5F_addr_encode(f, &p, ainfo->fheap_addr);

    /* Address of v2 B-tree to index names of attributes */
    H5F_addr_encode(f, &p, ainfo->name_bt2_addr);

    /* Address of v2 B-tree to index creation order of attributes, if they are indexed */
    if(ainfo->index_corder)
        H5F_addr_encode(f, &p, ainfo->corder_bt2_addr);
    else
        HDassert(!H5F_addr_defined(ainfo->corder_bt2_addr));

    FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_ainfo_encode() */
Example #23
0
/*-------------------------------------------------------------------------
 * Function:	H5D__single_idx_create
 *
 * Purpose:	Set up Single Chunk Index: filtered or non-filtered
 *		
 * Return:	Non-negative on success 
 *		Negative on failure.
 *
 * Programmer:	Vailin Choi; July 2011
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5D__single_idx_create(const H5D_chk_idx_info_t *idx_info)
{
    FUNC_ENTER_STATIC_NOERR

    /* Check args */
    HDassert(idx_info);
    HDassert(idx_info->f);
    HDassert(idx_info->pline);
    HDassert(idx_info->layout);
    HDassert(idx_info->storage);
    HDassert(idx_info->layout->max_nchunks == idx_info->layout->nchunks);
    HDassert(idx_info->layout->nchunks == 1);
    HDassert(!H5F_addr_defined(idx_info->storage->idx_addr));

    if(idx_info->pline->nused)
	HDassert(idx_info->layout->flags & H5O_LAYOUT_CHUNK_SINGLE_INDEX_WITH_FILTER);
    else
	HDassert(!(idx_info->layout->flags & H5O_LAYOUT_CHUNK_SINGLE_INDEX_WITH_FILTER));

    FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5D__single_idx_create() */
Example #24
0
/*-------------------------------------------------------------------------
 * Function:	H5MF_alloc_create
 *
 * Purpose:	Create free space manager of TYPE for the file by creating
 *		a free-space structure
 *
 * Return:	Success:	non-negative
 *		Failure:	negative
 *
 * Programmer:	Quincey Koziol
 *		[email protected]
 *		Jan  8 2008
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5MF_alloc_create(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type)
{
    const H5FS_section_class_t *classes[] = { /* Free space section classes implemented for file */
        H5MF_FSPACE_SECT_CLS_SIMPLE};
    herr_t ret_value = SUCCEED;         /* Return value */
    H5FS_create_t fs_create; 		/* Free space creation parameters */

    FUNC_ENTER_NOAPI_NOINIT

    /*
     * Check arguments.
     */
    HDassert(f);
    HDassert(f->shared);
    HDassert(type != H5FD_MEM_NOLIST);
    HDassert(!H5F_addr_defined(f->shared->fs_addr[type]));
    HDassert(f->shared->fs_state[type] == H5F_FS_STATE_CLOSED);

    /* Set the free space creation parameters */
    fs_create.client = H5FS_CLIENT_FILE_ID;
    fs_create.shrink_percent = H5MF_FSPACE_SHRINK;
    fs_create.expand_percent = H5MF_FSPACE_EXPAND;
    fs_create.max_sect_addr = 1 + H5VM_log2_gen((uint64_t)f->shared->maxaddr);
    fs_create.max_sect_size = f->shared->maxaddr;

    if(NULL == (f->shared->fs_man[type] = H5FS_create(f, dxpl_id, NULL,
	    &fs_create, NELMTS(classes), classes, f, f->shared->alignment, f->shared->threshold)))
	HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space info")


    /* Set the state for the free space manager to "open", if it is now */
    if(f->shared->fs_man[type])
        f->shared->fs_state[type] = H5F_FS_STATE_OPEN;

done:
    FUNC_LEAVE_NOAPI(ret_value)
} /* end H5MF_alloc_create() */
Example #25
0
/*-------------------------------------------------------------------------
 * Function:	H5D__single_idx_insert
 *
 * Purpose:	Allocate space for the single chunk
 *
 * Return:	Non-negative on success/Negative on failure
 *
 * Programmer:	Vailin Choi; July 2011
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5D__single_idx_insert(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata,
    const H5D_t *dset)
{
    herr_t	ret_value = SUCCEED;	/* Return value */

    FUNC_ENTER_STATIC

    /* Sanity checks */
    HDassert(idx_info);
    HDassert(idx_info->f);
    HDassert(idx_info->pline);
    HDassert(idx_info->layout);
    HDassert(idx_info->storage);
    HDassert(idx_info->layout->nchunks == 1);
    HDassert(idx_info->layout->max_nchunks == 1);
    HDassert(udata);

    /* Set the address for the chunk */
    HDassert(H5F_addr_defined(udata->chunk_block.offset));
    idx_info->storage->idx_addr = udata->chunk_block.offset;

    if(idx_info->pline->nused > 0) {
        H5_CHECKED_ASSIGN(idx_info->storage->u.single.nbytes, uint32_t, udata->chunk_block.length, hsize_t);
	idx_info->storage->u.single.filter_mask = udata->filter_mask;
    } /* end if */

    if(dset) {
	if(dset->shared->dcpl_cache.fill.alloc_time != H5D_ALLOC_TIME_EARLY || idx_info->pline->nused > 0) {
	    /* Mark the layout dirty so that the address of the single chunk will be flushed later */
	    if(H5D__mark(dset, idx_info->dxpl_id, H5D_MARK_LAYOUT) < 0)
		HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to mark layout as dirty")
	} /* end if */
    } /* end if */

done:
    FUNC_LEAVE_NOAPI(ret_value)
} /* H5D__single_idx_insert() */
Example #26
0
/*-------------------------------------------------------------------------
 * Function:	H5D__single_idx_iterate
 *
 * Purpose:	Make callback for the single chunk
 *
 * Return:	Non-negative on success/Negative on failure
 *
 * Programmer:	Vailin Choi; July 2010
 *
 *-------------------------------------------------------------------------
 */
static int
H5D__single_idx_iterate(const H5D_chk_idx_info_t *idx_info,
    H5D_chunk_cb_func_t chunk_cb, void *chunk_udata)
{
    H5D_chunk_rec_t chunk_rec;		/* generic chunk record  */
    int ret_value = -1;    		/* Return value */

    FUNC_ENTER_STATIC_NOERR

    /* Sanity checks */
    HDassert(idx_info);
    HDassert(idx_info->f);
    HDassert(idx_info->pline);
    HDassert(idx_info->layout);
    HDassert(idx_info->storage);
    HDassert(chunk_cb);
    HDassert(chunk_udata);
    HDassert(H5F_addr_defined(idx_info->storage->idx_addr));

    /* Initialize generic chunk record */
    HDmemset(&chunk_rec, 0, sizeof(chunk_rec));
    chunk_rec.chunk_addr = idx_info->storage->idx_addr;

    if(idx_info->layout->flags & H5O_LAYOUT_CHUNK_SINGLE_INDEX_WITH_FILTER) {
	chunk_rec.nbytes = idx_info->storage->u.single.nbytes;
	chunk_rec.filter_mask = idx_info->storage->u.single.filter_mask;
    } /* end if */
    else {
	chunk_rec.nbytes = idx_info->layout->size;
	chunk_rec.filter_mask = 0;
    } /* end else */

    /* Make "generic chunk" callback */
    if((ret_value = (*chunk_cb)(&chunk_rec, chunk_udata)) < 0)
	HERROR(H5E_DATASET, H5E_CALLBACK, "failure in generic chunk iterator callback");

    FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__single_idx_iterate() */
Example #27
0
/*-------------------------------------------------------------------------
 * Function:    H5O_ainfo_delete
 *
 * Purpose:     Free file space referenced by message.  Note that open_oh
 *              *must* be non-NULL - this means that calls to
 *              H5O_msg_delete must include an oh if the type is ainfo.
 *
 * Return:      Non-negative on success/Negative on failure
 *
 * Programmer:  Quincey Koziol
 *              Tuesday, March  6, 2007
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5O_ainfo_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, void *_mesg)
{
    H5O_ainfo_t *ainfo = (H5O_ainfo_t *)_mesg;
    herr_t ret_value = SUCCEED;   /* Return value */

    FUNC_ENTER_NOAPI_NOINIT

    /* check args */
    HDassert(f);
    HDassert(ainfo);
    HDassert(open_oh);

    /* If the object is using "dense" attribute storage, delete it */
    if(H5F_addr_defined(ainfo->fheap_addr)) {
        /* Delete the attribute */
        if(H5A_dense_delete(f, dxpl_id, ainfo) < 0)
            HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free dense attribute storage")
    } /* end if */

done:
    FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_ainfo_delete() */
Example #28
0
/*-------------------------------------------------------------------------
 * Function:	H5MF_alloc_start
 *
 * Purpose:	Open or create a free space manager of a given type
 *
 * Return:	Success:	non-negative
 *		Failure:	negative
 *
 * Programmer:	Quincey Koziol
 *		[email protected]
 *		Jan  8 2008
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5MF_alloc_start(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type)
{
    herr_t ret_value = SUCCEED;         /* Return value */

    FUNC_ENTER_NOAPI_NOINIT

    /*
     * Check arguments.
     */
    HDassert(f);
    HDassert(f->shared);
    HDassert(type != H5FD_MEM_NOLIST);

    /* Check if the free space manager exists already */
    if(H5F_addr_defined(f->shared->fs_addr[type])) {
        /* Open existing free space manager */
        if(H5MF_alloc_open(f, dxpl_id, type) < 0)
            HGOTO_ERROR(H5E_RESOURCE, H5E_CANTOPENOBJ, FAIL, "can't initialize file free space")
    } /* end if */
    else {
        /* Create new free space manager */
        if(H5MF_alloc_create(f, dxpl_id, type) < 0)
Example #29
0
/*-------------------------------------------------------------------------
 * Function:    H5C_apply_candidate_list
 *
 * Purpose:     Apply the supplied candidate list.
 *
 *		We used to do this by simply having each process write 
 *		every mpi_size-th entry in the candidate list, starting 
 *		at index mpi_rank, and mark all the others clean.  
 *
 *		However, this can cause unnecessary contention in a file 
 *		system by increasing the number of processes writing to 
 *		adjacent locations in the HDF5 file.
 *
 *		To attempt to minimize this, we now arange matters such 
 *		that each process writes n adjacent entries in the 
 *		candidate list, and marks all others clean.  We must do
 *		this in such a fashion as to guarantee that each entry 
 *		on the candidate list is written by exactly one process, 
 *		and marked clean by all others.  
 *
 *		To do this, first construct a table mapping mpi_rank
 *		to the index of the first entry in the candidate list to
 *		be written by the process of that mpi_rank, and then use
 *		the table to control which entries are written and which
 *		are marked as clean as a function of the mpi_rank.
 *
 *		Note that the table must be identical on all processes, as
 *		all see the same candidate list, mpi_size, and mpi_rank --
 *		the inputs used to construct the table.  
 *
 *		We construct the table as follows.  Let:
 *
 *			n = num_candidates / mpi_size;
 *
 *			m = num_candidates % mpi_size;
 *
 *		Now allocate an array of integers of length mpi_size + 1, 
 *		and call this array candidate_assignment_table. 
 *
 *		Conceptually, if the number of candidates is a multiple
 *		of the mpi_size, we simply pass through the candidate list
 *		and assign n entries to each process to flush, with the 
 *		index of the first entry to flush in the location in 
 *		the candidate_assignment_table indicated by the mpi_rank
 *		of the process.  
 *
 *		In the more common case in which the candidate list isn't 
 *		isn't a multiple of the mpi_size, we pretend it is, and 
 *		give num_candidates % mpi_size processes one extra entry
 *		each to make things work out.
 *
 *		Once the table is constructed, we determine the first and
 *		last entry this process is to flush as follows:
 *
 *	 	first_entry_to_flush = candidate_assignment_table[mpi_rank]
 *
 *		last_entry_to_flush = 
 *			candidate_assignment_table[mpi_rank + 1] - 1;
 *		
 *		With these values determined, we simply scan through the 
 *		candidate list, marking all entries in the range 
 *		[first_entry_to_flush, last_entry_to_flush] for flush,
 *		and all others to be cleaned.
 *
 *		Finally, we scan the LRU from tail to head, flushing 
 *		or marking clean the candidate entries as indicated.
 *		If necessary, we scan the pinned list as well.
 *
 *		Note that this function will fail if any protected or 
 *		clean entries appear on the candidate list.
 *
 *		This function is used in managing sync points, and 
 *		shouldn't be used elsewhere.
 *
 * Return:      Success:        SUCCEED
 *
 *              Failure:        FAIL
 *
 * Programmer:  John Mainzer
 *              3/17/10
 *
 * Changes:     Ported code to detect next entry status changes as the 
 *              the result of a flush from the serial code in the scan of 
 *              the LRU.  Also added code to detect and adapt to the 
 *              removal from the cache of the next entry in the scan of 
 *		the LRU.
 *
 *		Note that at present, all of these changes should not 
 *		be required as the operations on entries as they are 
 *		flushed that can cause these condiditions are not premitted
 *		in the parallel case.  However, Quincey indicates that 
 *		this may change, and thus has requested the modification.
 *
 *		Note the assert(FALSE) in the if statement whose body 
 *		restarts the scan of the LRU.  As the body of the if 
 *		statement should be unreachable, it should never be 
 *		triggered until the constraints on the parallel case 
 *		are relaxed.  Please remove the assertion at that time.
 *
 *		Also added warning on the Pinned Entry List scan, as it
 *		is potentially subject to the same issue.  As there is 
 *		no cognate of this scan in the serial code, I don't have
 *		a fix to port to it.
 *
 *						JRM -- 4/10/19
 *		
 *-------------------------------------------------------------------------
 */
herr_t
H5C_apply_candidate_list(H5F_t * f,
                         hid_t dxpl_id,
                         H5C_t * cache_ptr,
                         int num_candidates,
                         haddr_t * candidates_list_ptr,
                         int mpi_rank,
                         int mpi_size)
{
    hbool_t		restart_scan;
    hbool_t		prev_is_dirty;
    int                 i;
    int			m;
    int			n;
    int			first_entry_to_flush;
    int			last_entry_to_flush;
    int			entries_to_clear = 0;
    int			entries_to_flush = 0;
    int			entries_to_flush_or_clear_last = 0;
    int			entries_to_flush_collectively = 0;
    int			entries_cleared = 0;
    int			entries_flushed = 0;
    int			entries_delayed = 0;
    int			entries_flushed_or_cleared_last = 0;
    int			entries_flushed_collectively = 0;
    int			entries_examined = 0;
    int			initial_list_len;
    int               * candidate_assignment_table = NULL;
    haddr_t		addr;
    H5C_cache_entry_t *	clear_ptr = NULL;
    H5C_cache_entry_t *	next_ptr = NULL;
    H5C_cache_entry_t *	entry_ptr = NULL;
    H5C_cache_entry_t *	flush_ptr = NULL;
    H5C_cache_entry_t * delayed_ptr = NULL;
#if H5C_DO_SANITY_CHECKS
    haddr_t		last_addr;
#endif /* H5C_DO_SANITY_CHECKS */
#if H5C_APPLY_CANDIDATE_LIST__DEBUG
    char		tbl_buf[1024];
#endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */
    herr_t              ret_value = SUCCEED;      /* Return value */

    FUNC_ENTER_NOAPI(FAIL)

    HDassert( cache_ptr != NULL );
    HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
    HDassert( num_candidates > 0 );
    HDassert( num_candidates <= cache_ptr->slist_len );
    HDassert( candidates_list_ptr != NULL );
    HDassert( 0 <= mpi_rank );
    HDassert( mpi_rank < mpi_size );

#if H5C_APPLY_CANDIDATE_LIST__DEBUG
    HDfprintf(stdout, "%s:%d: setting up candidate assignment table.\n", 
              FUNC, mpi_rank);
    for ( i = 0; i < 1024; i++ ) tbl_buf[i] = '\0';
    sprintf(&(tbl_buf[0]), "candidate list = ");
    for ( i = 0; i < num_candidates; i++ )
    {
        sprintf(&(tbl_buf[HDstrlen(tbl_buf)]), " 0x%llx", 
                (long long)(*(candidates_list_ptr + i)));
    }
    sprintf(&(tbl_buf[HDstrlen(tbl_buf)]), "\n");
    HDfprintf(stdout, "%s", tbl_buf);
#endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */

    n = num_candidates / mpi_size;
    m = num_candidates % mpi_size;
    HDassert(n >= 0);

    if(NULL == (candidate_assignment_table = (int *)H5MM_malloc(sizeof(int) * (size_t)(mpi_size + 1))))
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for candidate assignment table")

    candidate_assignment_table[0] = 0;
    candidate_assignment_table[mpi_size] = num_candidates;

    if(m == 0) { /* mpi_size is an even divisor of num_candidates */
        HDassert(n > 0);
        for(i = 1; i < mpi_size; i++)
            candidate_assignment_table[i] = candidate_assignment_table[i - 1] + n;
    } /* end if */
    else { 
        for(i = 1; i <= m; i++)
            candidate_assignment_table[i] = candidate_assignment_table[i - 1] + n + 1;

        if(num_candidates < mpi_size) {
            for(i = m + 1; i < mpi_size; i++)
                candidate_assignment_table[i] = num_candidates;
        } /* end if */
        else {
            for(i = m + 1; i < mpi_size; i++)
                candidate_assignment_table[i] = candidate_assignment_table[i - 1] + n;
        } /* end else */
    } /* end else */
    HDassert((candidate_assignment_table[mpi_size - 1] + n) == num_candidates);

#if H5C_DO_SANITY_CHECKS
    /* verify that the candidate assignment table has the expected form */
    for ( i = 1; i < mpi_size - 1; i++ ) 
    {
        int a, b;

        a = candidate_assignment_table[i] - candidate_assignment_table[i - 1];
        b = candidate_assignment_table[i + 1] - candidate_assignment_table[i];

        HDassert( n + 1 >= a );
        HDassert( a >= b );
        HDassert( b >= n );
    }
#endif /* H5C_DO_SANITY_CHECKS */

    first_entry_to_flush = candidate_assignment_table[mpi_rank];
    last_entry_to_flush = candidate_assignment_table[mpi_rank + 1] - 1;

#if H5C_APPLY_CANDIDATE_LIST__DEBUG
    for ( i = 0; i < 1024; i++ )
        tbl_buf[i] = '\0';
    sprintf(&(tbl_buf[0]), "candidate assignment table = ");
    for(i = 0; i <= mpi_size; i++)
        sprintf(&(tbl_buf[HDstrlen(tbl_buf)]), " %d", candidate_assignment_table[i]);
    sprintf(&(tbl_buf[HDstrlen(tbl_buf)]), "\n");
    HDfprintf(stdout, "%s", tbl_buf);

    HDfprintf(stdout, "%s:%d: flush entries [%d, %d].\n", 
              FUNC, mpi_rank, first_entry_to_flush, last_entry_to_flush);

    HDfprintf(stdout, "%s:%d: marking entries.\n", FUNC, mpi_rank);
#endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */

    for(i = 0; i < num_candidates; i++) {
        addr = candidates_list_ptr[i];
        HDassert( H5F_addr_defined(addr) );

#if H5C_DO_SANITY_CHECKS
        if ( i > 0 ) {
            if ( last_addr == addr ) {
                HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Duplicate entry in cleaned list.\n")
            } else if ( last_addr > addr ) {
                HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "candidate list not sorted.\n")
            }
        }

        last_addr = addr;
#endif /* H5C_DO_SANITY_CHECKS */

        H5C__SEARCH_INDEX(cache_ptr, addr, entry_ptr, FAIL)
        if(entry_ptr == NULL) {
            HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Listed candidate entry not in cache?!?!?.")
        } else if(!entry_ptr->is_dirty) {
            HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Listed entry not dirty?!?!?.")
        } else if ( entry_ptr->is_protected ) {
            /* For now at least, we can't deal with protected entries.
             * If we encounter one, scream and die.  If it becomes an
             * issue, we should be able to work around this. 
             */
            HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Listed entry is protected?!?!?.")
        } else {
            /* determine whether the entry is to be cleared or flushed,
             * and mark it accordingly.  We will scan the protected and 
             * pinned list shortly, and clear or flush according to these
             * markings.  
             */
            if((i >= first_entry_to_flush) && (i <= last_entry_to_flush)) {
                entries_to_flush++;
                entry_ptr->flush_immediately = TRUE;
            } /* end if */
            else {
                entries_to_clear++;
                entry_ptr->clear_on_unprotect = TRUE;
            } /* end else */
        } /* end else */
    } /* end for */

#if H5C_APPLY_CANDIDATE_LIST__DEBUG
    HDfprintf(stdout, "%s:%d: num candidates/to clear/to flush = %d/%d/%d.\n", 
              FUNC, mpi_rank, (int)num_candidates, (int)entries_to_clear,
              (int)entries_to_flush);
#endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */


    /* We have now marked all the entries on the candidate list for 
     * either flush or clear -- now scan the LRU and the pinned list
     * for these entries and do the deed.
     *
     * Note that we are doing things in this round about manner so as
     * to preserve the order of the LRU list to the best of our ability.
     * If we don't do this, my experiments indicate that we will have a
     * noticably poorer hit ratio as a result.
     */

#if H5C_APPLY_CANDIDATE_LIST__DEBUG
    HDfprintf(stdout, "%s:%d: scanning LRU list. len = %d.\n", FUNC, mpi_rank,
              (int)(cache_ptr->LRU_list_len));
#endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */

    /* ===================================================================== *
     * Now scan the LRU and PEL lists, flushing or clearing entries as
     * needed.
     *
     * The flush_me_last and flush_me_collectively flags may dictate how or
     * when some entries can be flushed, and should be addressed here.
     * However, in their initial implementation, these flags only apply to the
     * superblock, so there's only a relatively small change to this function
     * to account for this one case where they come into play. If these flags
     * are ever expanded upon, this function and the following flushing steps
     * should be reworked to account for additional cases.
     * ===================================================================== */

    HDassert(entries_to_flush >= 0);

    restart_scan = FALSE;
    entries_examined = 0;
    initial_list_len = cache_ptr->LRU_list_len;
    entry_ptr = cache_ptr->LRU_tail_ptr;

    /* Examine each entry in the LRU list */
    while ( ( entry_ptr != NULL ) 
            && 
            ( entries_examined <= (entries_to_flush + 1) * initial_list_len ) 
            &&
            ( (entries_cleared + entries_flushed) < num_candidates ) ) {

        if ( entry_ptr->prev != NULL )
            prev_is_dirty = entry_ptr->prev->is_dirty;

        /* If this process needs to clear this entry. */
        if(entry_ptr->clear_on_unprotect) {

            HDassert(entry_ptr->is_dirty);

            next_ptr = entry_ptr->next; 
            entry_ptr->clear_on_unprotect = FALSE;
            clear_ptr = entry_ptr;
            entry_ptr = entry_ptr->prev;
            entries_cleared++;

#if ( H5C_APPLY_CANDIDATE_LIST__DEBUG > 1 )
    HDfprintf(stdout, "%s:%d: clearing 0x%llx.\n", FUNC, mpi_rank,
              (long long)clear_ptr->addr);
#endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */

	    /* No need to check for the next entry in the scan being 
             * removed from the cache, as this call to H5C__flush_single_entry()
             * will not call either the pre_serialize or serialize callbacks.
             */

            if(H5C__flush_single_entry(f, dxpl_id, clear_ptr, H5C__FLUSH_CLEAR_ONLY_FLAG | H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG, NULL) < 0)
                HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't clear entry.")
        } /* end if */

        /* Else, if this process needs to flush this entry. */
        else if (entry_ptr->flush_immediately) {
Example #30
0
/*-------------------------------------------------------------------------
 * Function:	H5O_efl_decode
 *
 * Purpose:	Decode an external file list message and return a pointer to
 *		the message (and some other data).
 *
 * Return:	Success:	Ptr to a new message struct.
 *
 *		Failure:	NULL
 *
 * Programmer:	Robb Matzke
 *		Tuesday, November 25, 1997
 *
 *-------------------------------------------------------------------------
 */
static void *
H5O_efl_decode(H5F_t *f, hid_t dxpl_id, H5O_t UNUSED *open_oh,
    unsigned UNUSED mesg_flags, unsigned UNUSED *ioflags, const uint8_t *p)
{
    H5O_efl_t		*mesg = NULL;
    int			version;
    const char		*s = NULL;
    H5HL_t              *heap;
    size_t		u;      /* Local index variable */
    void *ret_value;            /* Return value */

    FUNC_ENTER_NOAPI_NOINIT(H5O_efl_decode)

    /* Check args */
    HDassert(f);
    HDassert(p);

    if(NULL == (mesg = (H5O_efl_t *)H5MM_calloc(sizeof(H5O_efl_t))))
	HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")

    /* Version */
    version = *p++;
    if(version != H5O_EFL_VERSION)
	HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for external file list message")

    /* Reserved */
    p += 3;

    /* Number of slots */
    UINT16DECODE(p, mesg->nalloc);
    assert(mesg->nalloc>0);
    UINT16DECODE(p, mesg->nused);
    assert(mesg->nused <= mesg->nalloc);

    /* Heap address */
    H5F_addr_decode(f, &p, &(mesg->heap_addr));

#ifndef NDEBUG
    HDassert(H5F_addr_defined(mesg->heap_addr));

    if(NULL == (heap = H5HL_protect(f, dxpl_id, mesg->heap_addr, H5AC_READ)))
        HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "unable to read protect link value")

    s = (const char *)H5HL_offset_into(f, heap, 0);

    HDassert(s && !*s);

    if(H5HL_unprotect(f, dxpl_id, heap, mesg->heap_addr) < 0)
        HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "unable to read unprotect link value")
    heap = NULL;
#endif

    /* Decode the file list */
    mesg->slot = (H5O_efl_entry_t *)H5MM_calloc(mesg->nalloc * sizeof(H5O_efl_entry_t));
    if(NULL == mesg->slot)
	HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")

    if(NULL == (heap = H5HL_protect(f, dxpl_id, mesg->heap_addr, H5AC_READ)))
        HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "unable to read protect link value")
    for(u = 0; u < mesg->nused; u++) {
	/* Name */
	H5F_DECODE_LENGTH (f, p, mesg->slot[u].name_offset);

        s = (const char *)H5HL_offset_into(f, heap, mesg->slot[u].name_offset);
	HDassert(s && *s);
	mesg->slot[u].name = H5MM_xstrdup (s);
        HDassert(mesg->slot[u].name);

	/* File offset */
	H5F_DECODE_LENGTH (f, p, mesg->slot[u].offset);

	/* Size */
	H5F_DECODE_LENGTH (f, p, mesg->slot[u].size);
	HDassert(mesg->slot[u].size > 0);
    } /* end for */

    if(H5HL_unprotect(f, dxpl_id, heap, mesg->heap_addr) < 0)
        HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "unable to read unprotect link value")
    heap = NULL;

    /* Set return value */
    ret_value = mesg;

done:
    if(ret_value == NULL)
        if(mesg != NULL)
            H5MM_xfree(mesg);

    FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_efl_decode() */