Esempio n. 1
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);
}
/*-------------------------------------------------------------------------
 * Function:	H5T__print_stats
 *
 * Purpose:	Print statistics about a conversion path.  Statistics are
 *		printed only if all the following conditions are true:
 *
 * 		1. The library was compiled with H5T_DEBUG defined.
 *		2. Data type debugging is turned on at run time.
 *		3. The path was called at least one time.
 *
 *		The optional NPRINT argument keeps track of the number of
 *		conversions paths for which statistics have been shown. If
 *		its value is zero then table headers are printed before the
 *		first line of output.
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *              Monday, December 14, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T__print_stats(H5T_path_t H5_ATTR_UNUSED * path, int H5_ATTR_UNUSED * nprint/*in,out*/)
{
#ifdef H5T_DEBUG
    hsize_t	nbytes;
    char	bandwidth[32];
#endif

    FUNC_ENTER_PACKAGE_NOERR

#ifdef H5T_DEBUG
    if(H5DEBUG(T) && path->stats.ncalls > 0) {
	if(nprint && 0 == (*nprint)++) {
	    HDfprintf(H5DEBUG(T), "H5T: type conversion statistics:\n");
	    HDfprintf(H5DEBUG(T), "   %-16s %10s %10s %8s %8s %8s %10s\n",
		       "Conversion", "Elmts", "Calls", "User",
		       "System", "Elapsed", "Bandwidth");
	    HDfprintf(H5DEBUG(T), "   %-16s %10s %10s %8s %8s %8s %10s\n",
		       "----------", "-----", "-----", "----",
		       "------", "-------", "---------");
	}
        if(path->src && path->dst)
            nbytes = MAX(H5T_get_size(path->src), H5T_get_size(path->dst));
        else if(path->src)
            nbytes = H5T_get_size(path->src);
        else if(path->dst)
            nbytes = H5T_get_size(path->dst);
        else
            nbytes = 0;
	nbytes *= path->stats.nelmts;
	H5_bandwidth(bandwidth, (double)nbytes, path->stats.timer.etime);
	HDfprintf(H5DEBUG(T), "   %-16s %10Hd %10d %8.2f %8.2f %8.2f %10s\n",
		   path->name,
		   path->stats.nelmts,
		   path->stats.ncalls,
		   path->stats.timer.utime,
		   path->stats.timer.stime,
		   path->stats.timer.etime,
		   bandwidth);
    }
#endif
    FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5T__print_stats() */
Esempio n. 3
0
/*-------------------------------------------------------------------------
 * Function:	H5S_mpio_hyper_type
 *
 * Purpose:	Translate an HDF5 hyperslab selection into an MPI type.
 *
 * Return:	non-negative on success, negative on failure.
 *
 * Outputs:	*new_type	  the MPI type corresponding to the selection
 *		*count		  how many objects of the new_type in selection
 *				  (useful if this is the buffer type for xfer)
 *		*extra_offset     Number of bytes of offset within dataset
 *		*is_derived_type  0 if MPI primitive type, 1 if derived
 *
 * Programmer:	rky 980813
 *
 * Modifications:  ppw 990401
 *		rky, ppw 2000-09-26 Freed old type after creating struct type.
 *		rky 2000-10-05 Changed displacements to be MPI_Aint.
 *		rky 2000-10-06 Added code for cases of empty hyperslab.
 *		akc, rky 2000-11-16 Replaced hard coded dimension size with
 *		    H5S_MAX_RANK.
 *
 *      	Quincey Koziol, June 18, 2002
 *      	Added 'extra_offset' parameter.  Also accomodate selection
 *      	offset in MPI type built.
 *
 *      	Albert Cheng, August 4, 2004
 *      	Reimplemented the algorithm of forming the outer_type by
 *      	defining it as (start, vector, extent) in one call.
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5S_mpio_hyper_type( const H5S_t *space, size_t elmt_size,
		     /* out: */
		     MPI_Datatype *new_type,
		     size_t *count,
		     hsize_t *extra_offset,
		     hbool_t *is_derived_type )
{
    H5S_sel_iter_t sel_iter;    /* Selection iteration info */
    hbool_t sel_iter_init=0;    /* Selection iteration info has been initialized */

    struct dim {	/* less hassle than malloc/free & ilk */
        hssize_t start;
        hsize_t strid;
        hsize_t block;
        hsize_t xtent;
        hsize_t count;
    } d[H5S_MAX_RANK];

    int			i;
    int			offset[H5S_MAX_RANK];
    int			max_xtent[H5S_MAX_RANK];
    H5S_hyper_dim_t	*diminfo;		/* [rank] */
    int		rank;
    int			block_length[3];
    MPI_Datatype	inner_type, outer_type, old_types[3];
    MPI_Aint            extent_len, displacement[3];
    int                 mpi_code;               /* MPI return code */
    herr_t		ret_value = SUCCEED;

    FUNC_ENTER_NOAPI_NOINIT(H5S_mpio_hyper_type);

    /* Check args */
    assert (space);
    assert(sizeof(MPI_Aint) >= sizeof(elmt_size));
    if (0==elmt_size)
        goto empty;

    /* Initialize selection iterator */
    if (H5S_select_iter_init(&sel_iter, space, elmt_size)<0)
        HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator");
    sel_iter_init=1;	/* Selection iteration info has been initialized */

    /* Abbreviate args */
    diminfo=sel_iter.u.hyp.diminfo;
    assert (diminfo);

    /* make a local copy of the dimension info so we can operate with them */

    /* Check if this is a "flattened" regular hyperslab selection */
    if(sel_iter.u.hyp.iter_rank!=0 && sel_iter.u.hyp.iter_rank<space->extent.rank) {
        /* Flattened selection */
        rank=sel_iter.u.hyp.iter_rank;
        assert (rank >= 0 && rank<=H5S_MAX_RANK);	/* within array bounds */
        if (0==rank)
            goto empty;
#ifdef H5S_DEBUG
  if(H5DEBUG(S))
            HDfprintf(H5DEBUG(S), "%s: Flattened selection\n",FUNC);
#endif
        for ( i=0; i<rank; ++i) {
            d[i].start = diminfo[i].start+sel_iter.u.hyp.sel_off[i];
            d[i].strid = diminfo[i].stride;
            d[i].block = diminfo[i].block;
            d[i].count = diminfo[i].count;
            d[i].xtent = sel_iter.u.hyp.size[i];
#ifdef H5S_DEBUG
       if(H5DEBUG(S)){
            HDfprintf(H5DEBUG(S), "%s: start=%Hd  stride=%Hu  count=%Hu  block=%Hu  xtent=%Hu",
                FUNC, d[i].start, d[i].strid, d[i].count, d[i].block, d[i].xtent );
            if (i==0)
                HDfprintf(H5DEBUG(S), "  rank=%d\n", rank );
            else
                HDfprintf(H5DEBUG(S), "\n" );
      }
#endif
            if (0==d[i].block)
                goto empty;
            if (0==d[i].count)
                goto empty;
            if (0==d[i].xtent)
                goto empty;
        }
    } /* end if */
    else {
        /* Non-flattened selection */
        rank = space->extent.rank;
        assert (rank >= 0 && rank<=H5S_MAX_RANK);	/* within array bounds */
        if (0==rank)
            goto empty;
#ifdef H5S_DEBUG
  if(H5DEBUG(S))
            HDfprintf(H5DEBUG(S),"%s: Non-flattened selection\n",FUNC); 
#endif
        for ( i=0; i<rank; ++i) {
            d[i].start = diminfo[i].start+space->select.offset[i];
            d[i].strid = diminfo[i].stride;
            d[i].block = diminfo[i].block;
            d[i].count = diminfo[i].count;
            d[i].xtent = space->extent.size[i];
#ifdef H5S_DEBUG
  if(H5DEBUG(S)){
    HDfprintf(H5DEBUG(S), "%s: start=%Hd  stride=%Hu  count=%Hu  block=%Hu  xtent=%Hu",
              FUNC, d[i].start, d[i].strid, d[i].count, d[i].block, d[i].xtent );
    if (i==0)
        HDfprintf(H5DEBUG(S), "  rank=%d\n", rank );
    else
        HDfprintf(H5DEBUG(S), "\n" );
  }
#endif
            if (0==d[i].block)
                goto empty;
            if (0==d[i].count)
                goto empty;
            if (0==d[i].xtent)
                goto empty;
        }
    } /* end else */

/**********************************************************************
    Compute array "offset[rank]" which gives the offsets for a multi-
    dimensional array with dimensions "d[i].xtent" (i=0,1,...,rank-1).
**********************************************************************/
    offset[rank-1] = 1;
    max_xtent[rank-1] = d[rank-1].xtent;
/*#ifdef H5Smpi_DEBUG   */ /* leave the old way */
#ifdef H5S_DEBUG
  if(H5DEBUG(S)){
     i=rank-1;
    HDfprintf(H5DEBUG(S), " offset[%2d]=%d; max_xtent[%2d]=%d\n",
                          i, offset[i], i, max_xtent[i]);
  }
#endif
    for (i=rank-2; i>=0; --i) {
        offset[i] = offset[i+1]*d[i+1].xtent;
        max_xtent[i] = max_xtent[i+1]*d[i].xtent;
#ifdef H5S_DEBUG
  if(H5DEBUG(S)){
    HDfprintf(H5DEBUG(S), " offset[%2d]=%d; max_xtent[%2d]=%d\n",
                          i, offset[i], i, max_xtent[i]);
  }
#endif

    }

    /*  Create a type covering the selected hyperslab.
     *  Multidimensional dataspaces are stored in row-major order.
     *  The type is built from the inside out, going from the
     *  fastest-changing (i.e., inner) dimension * to the slowest (outer). */

/*******************************************************
*  Construct contig type for inner contig dims:
*******************************************************/
#ifdef H5S_DEBUG
  if(H5DEBUG(S)) {
    HDfprintf(H5DEBUG(S), "%s: Making contig type %d MPI_BYTEs\n", FUNC,elmt_size );
    for (i=rank-1; i>=0; --i)
        HDfprintf(H5DEBUG(S), "d[%d].xtent=%Hu \n", i, d[i].xtent);
  }
#endif
    if (MPI_SUCCESS != (mpi_code= MPI_Type_contiguous( (int)elmt_size, MPI_BYTE, &inner_type )))
        HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code);

/*******************************************************
*  Construct the type by walking the hyperslab dims
*  from the inside out:
*******************************************************/
    for ( i=rank-1; i>=0; --i) {
#ifdef H5S_DEBUG
     if(H5DEBUG(S)) {
        HDfprintf(H5DEBUG(S), "%s: Dimension i=%d \n"
            "start=%Hd count=%Hu block=%Hu stride=%Hu, xtent=%Hu max_xtent=%d\n",
            FUNC, i, d[i].start, d[i].count, d[i].block, d[i].strid, d[i].xtent, max_xtent[i]);
     }
#endif

#ifdef H5S_DEBUG
  if(H5DEBUG(S))
            HDfprintf(H5DEBUG(S), "%s: i=%d  Making vector-type \n", FUNC,i);
#endif
       /****************************************
       *  Build vector type of the selection.
       ****************************************/
	mpi_code =MPI_Type_vector((int)(d[i].count),        /* count */
				  (int)(d[i].block),        /* blocklength */
				  (int)(d[i].strid),   	    /* stride */
				  inner_type,	            /* old type */
				  &outer_type);            /* new type */

        MPI_Type_free( &inner_type );
        if (mpi_code!=MPI_SUCCESS)
            HMPI_GOTO_ERROR(FAIL, "couldn't create MPI vector type", mpi_code);

       /****************************************
       *  Then build the dimension type as (start, vector type, xtent).
       ****************************************/
       /* calculate start and extent values of this dimension */
	displacement[1] = d[i].start * offset[i] * elmt_size;
        displacement[2] = (MPI_Aint)elmt_size * max_xtent[i];
        if(MPI_SUCCESS != (mpi_code = MPI_Type_extent(outer_type, &extent_len)))
            HMPI_GOTO_ERROR(FAIL, "MPI_Type_extent failed", mpi_code);

       /*************************************************
       *  Restructure this datatype ("outer_type")
       *  so that it still starts at 0, but its extent
       *  is the full extent in this dimension.
       *************************************************/
        if (displacement[1] > 0 || (int)extent_len < displacement[2]) {

            block_length[0] = 1;
            block_length[1] = 1;
            block_length[2] = 1;

            displacement[0] = 0;

            old_types[0] = MPI_LB;
            old_types[1] = outer_type;
            old_types[2] = MPI_UB;
#ifdef H5S_DEBUG
       if(H5DEBUG(S)){
            HDfprintf(H5DEBUG(S), "%s: i=%d Extending struct type\n"
                "***displacements: %d, %d, %d\n",
		FUNC, i, displacement[0], displacement[1], displacement[2]);
       }
#endif

            mpi_code = MPI_Type_struct ( 3,               /* count */
                                    block_length,    /* blocklengths */
                                    displacement,    /* displacements */
                                    old_types,       /* old types */
                                    &inner_type);    /* new type */

            MPI_Type_free (&outer_type);
    	    if (mpi_code!=MPI_SUCCESS)
                HMPI_GOTO_ERROR(FAIL, "couldn't resize MPI vector type", mpi_code);
        }
        else {
            inner_type = outer_type;
        }
    } /* end for */
/***************************
*  End of loop, walking
*  thru dimensions.
***************************/


    /* At this point inner_type is actually the outermost type, even for 0-trip loop */

    *new_type = inner_type;
    if (MPI_SUCCESS != (mpi_code= MPI_Type_commit( new_type )))
        HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code);

    /* fill in the remaining return values */
    *count = 1;			/* only have to move one of these suckers! */
    *extra_offset = 0;
    *is_derived_type = 1;
    HGOTO_DONE(SUCCEED);

empty:
    /* special case: empty hyperslab */
    *new_type = MPI_BYTE;
    *count = 0;
    *extra_offset = 0;
    *is_derived_type = 0;

done:
    /* Release selection iterator */
    if(sel_iter_init) {
        if (H5S_SELECT_ITER_RELEASE(&sel_iter)<0)
            HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator");
    } /* end if */

#ifdef H5S_DEBUG
  if(H5DEBUG(S)){
    HDfprintf(H5DEBUG(S), "Leave %s, count=%ld  is_derived_type=%d\n",
		FUNC, *count, *is_derived_type );
  }
#endif
    FUNC_LEAVE_NOAPI(ret_value);
}
Esempio n. 4
0
/*-------------------------------------------------------------------------
 * Function:  H5I_clear_group
 *
 * Purpose:  Removes all objects from the group, calling the free
 *    function for each object regardless of the reference count.
 *
 * Return:  Success:  Non-negative
 *
 *    Failure:  negative
 *
 * Programmer:  Robb Matzke
 *              Wednesday, March 24, 1999
 *
 * Modifications:
 *     Robb Matzke, 1999-04-27
 *    If FORCE is zero then any item for which the free callback
 *    failed is not removed.  This function returns failure if
 *    items could not be removed.
 *
 *     Robb Matzke, 1999-08-17
 *    If the object reference count is larger than one then it must
 *    be because the library is using the object internally. This
 *    happens for instance for file driver ID's which are stored in
 *    things like property lists, files, etc.  Objects that have a
 *    reference count larger than one are not affected unless FORCE
 *    is non-zero.
 *-------------------------------------------------------------------------
 */
herr_t
H5I_clear_group(H5I_type_t grp, hbool_t force)
{
    H5I_id_group_t  *grp_ptr = NULL;    /* ptr to the atomic group */
    H5I_id_info_t   *cur=NULL;          /* Current node being worked with */
    H5I_id_info_t   *next=NULL;         /* Next node in list */
    H5I_id_info_t   *last=NULL;         /* Last node seen */
    H5I_id_info_t   *tmp=NULL;          /* Temporary node ptr */
    int    ret_value = SUCCEED;
    unsigned    delete_node;            /* Flag to indicate node should be removed from linked list */
    unsigned  i;

    FUNC_ENTER_NOAPI(H5I_clear_group, FAIL);

    if (grp <= H5I_BADID || grp >= H5I_NGROUPS)
  HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid group number");

    grp_ptr = H5I_id_group_list_g[grp];
    if (grp_ptr == NULL || grp_ptr->count <= 0)
  HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid group");

    /*
     * Call free method for all objects in group regardless of their reference
     * counts. Ignore the return value from from the free method and remove
     * object from group regardless if FORCE is non-zero.
     */
    for (i=0; i<grp_ptr->hash_size; i++) {
        for (cur=grp_ptr->id_list[i]; cur; cur=next) {
            /*
             * Do nothing to the object if the reference count is larger than
             * one and forcing is off.
             */
            if (!force && cur->count>1) {
                next=cur->next;
                continue;
            } /* end if */

            /* Check for a 'free' function and call it, if it exists */
            if (grp_ptr->free_func && (grp_ptr->free_func)(cur->obj_ptr)<0) {
                if (force) {
#ifdef H5I_DEBUG
                    if (H5DEBUG(I)) {
                        fprintf(H5DEBUG(I), "H5I: free grp=%d obj=0x%08lx "
                            "failure ignored\n", (int)grp,
                            (unsigned long)(cur->obj_ptr));
                    } /* end if */
#endif /*H5I_DEBUG*/

                    /* Indicate node should be removed from list */
                    delete_node=1;
                } /* end if */
                else {
                    /* Indicate node should _NOT_ be remove from list */
                    delete_node=0;
                } /* end else */
            } /* end if */
            else {
                /* Indicate node should be removed from list */
                delete_node=1;
            } /* end else */

            /* Check if we should delete this node or not */
            if(delete_node) {
                /* Decrement the number of IDs in the group */
                (grp_ptr->ids)--;

                /* Advance to next node */
                next = cur->next;

                /* Re-scan the list of nodes and remove the node from the list */
                /* (can't maintain static pointers to the previous node in the */
                /*      list, because the node's 'free' callback could have */
                /*      make an H5I call, which could potentially change the */
                /*      order of the nodes on the list - QAK) */
                last=NULL;
                tmp=grp_ptr->id_list[i];
                while(tmp!=cur) {
                    assert(tmp!=NULL);
                    last=tmp;
                    tmp=tmp->next;
                } /* end while */

                /* Delete the node from the list */
                if(last==NULL) {
                    /* Node at head of list, just advance the list head to next node */
                    assert(grp_ptr->id_list[i]==cur);
                    grp_ptr->id_list[i] = next;
                } /* end if */
                else {
                    /* Node in middle of list, jump over it */
                    assert(last->next==cur);
                    last->next=next;
                } /* end else */

                /* Free the node */
                H5FL_FREE(H5I_id_info_t,cur);
            } /* end if */
            else {
                /* Advance to next node */
                next = cur->next;
            } /* end else */
        } /* end for */
    } /* end for */

done:
    FUNC_LEAVE_NOAPI(ret_value);
}