diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 1999-07-03 10:31:26 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 1999-07-03 10:31:26 (GMT) |
commit | 650e29cff6b23b99318f70699af08cfdb57ea924 (patch) | |
tree | e37bc1ece43cbbad2504adbea63a5ef9241d2453 /src/H5Tvlen.c | |
parent | 1b20703c2048cf176df2d5c792de56da92ae03e2 (diff) | |
download | hdf5-650e29cff6b23b99318f70699af08cfdb57ea924.zip hdf5-650e29cff6b23b99318f70699af08cfdb57ea924.tar.gz hdf5-650e29cff6b23b99318f70699af08cfdb57ea924.tar.bz2 |
[svn-r1418] Modified H5Tconvert to require a dataset transfer property list ID as the
final parameter (so that VL datatypes have a way to pass in the custom memory
allocation routines).
Fixed a conversion bug when VL fields were part of a compound datatype that
was causing the no-op conversion routine to be used instead of the vlen routine.
Added the H5Pset_vlen_mem_manager and H5Pget_vlen_mem_manager routines to
allow users to provide their own custom memory allocation routines for VL data
read in from the file and reclaimed with H5Dvlen_reclaim.
Finished coding on H5Dvlen_reclaim so it works now.
Diffstat (limited to 'src/H5Tvlen.c')
-rw-r--r-- | src/H5Tvlen.c | 232 |
1 files changed, 226 insertions, 6 deletions
diff --git a/src/H5Tvlen.c b/src/H5Tvlen.c index 4530361..1a70aa8 100644 --- a/src/H5Tvlen.c +++ b/src/H5Tvlen.c @@ -21,6 +21,7 @@ static char RcsId[] = "@(#)$Revision$"; #include <H5private.h> /* Generic Functions */ #include <H5Eprivate.h> /* Errors */ #include <H5HGprivate.h> /* Global Heaps */ +#include <H5Iprivate.h> /* IDs */ #include <H5MMprivate.h> /* Memory Allocation */ #include <H5Tpkg.h> /* Datatypes */ @@ -30,6 +31,9 @@ static char RcsId[] = "@(#)$Revision$"; static intn interface_initialize_g = 0; #define INTERFACE_INIT NULL +/* Local functions */ +static herr_t H5T_vlen_reclaim_recurse(void *elem, H5T_t *dt, H5MM_free_t free_func, void *free_info); + /*------------------------------------------------------------------------- * Function: H5T_vlen_set_loc @@ -45,7 +49,8 @@ static intn interface_initialize_g = 0; * *------------------------------------------------------------------------- */ -herr_t H5T_vlen_set_loc(H5T_t *dt, H5F_t *f, H5T_vlen_type_t loc) +static herr_t +H5T_vlen_set_loc(H5T_t *dt, H5F_t *f, H5T_vlen_type_t loc) { FUNC_ENTER (H5T_vlen_set_loc, FAIL); @@ -100,7 +105,7 @@ herr_t H5T_vlen_set_loc(H5T_t *dt, H5F_t *f, H5T_vlen_type_t loc) } /* end switch */ FUNC_LEAVE (SUCCEED); -} /* end H5T_vlen_disk_write() */ +} /* end H5T_vlen_set_loc() */ /*------------------------------------------------------------------------- @@ -177,7 +182,7 @@ herr_t H5T_vlen_mem_read(H5F_t UNUSED *f, void *vl_addr, void *buf, size_t len) * *------------------------------------------------------------------------- */ -herr_t H5T_vlen_mem_alloc(H5F_t UNUSED *f, void *vl_addr, hsize_t seq_len, hsize_t base_size) +herr_t H5T_vlen_mem_alloc(const H5F_xfer_t *xfer_parms, void *vl_addr, hsize_t seq_len, hsize_t base_size) { hvl_t *vl=(hvl_t *)vl_addr; /* Pointer to the user's hvl_t information */ @@ -186,8 +191,15 @@ herr_t H5T_vlen_mem_alloc(H5F_t UNUSED *f, void *vl_addr, hsize_t seq_len, hsize /* check parameters */ assert(vl); - if(NULL==(vl->p=H5MM_malloc(seq_len*base_size))) - HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for VL data"); + /* Use the user's memory allocation routine is one is defined */ + if(xfer_parms->vlen_alloc!=NULL) { + if(NULL==(vl->p=(xfer_parms->vlen_alloc)(seq_len*base_size,xfer_parms->alloc_info))) + HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for VL data"); + } /* end if */ + else { /* Default to system malloc */ + if(NULL==(vl->p=H5MM_malloc(seq_len*base_size))) + HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for VL data"); + } /* end else */ vl->len=seq_len; FUNC_LEAVE (SUCCEED); @@ -312,7 +324,7 @@ herr_t H5T_vlen_disk_read(H5F_t *f, void *vl_addr, void *buf, size_t UNUSED len) * *------------------------------------------------------------------------- */ -herr_t H5T_vlen_disk_alloc(H5F_t UNUSED *f, void UNUSED *vl_addr, hsize_t UNUSED seq_len, hsize_t UNUSED base_size) +herr_t H5T_vlen_disk_alloc(const H5F_xfer_t UNUSED *f, void UNUSED *vl_addr, hsize_t UNUSED seq_len, hsize_t UNUSED base_size) { FUNC_ENTER (H5T_vlen_disk_alloc, FAIL); @@ -363,3 +375,211 @@ herr_t H5T_vlen_disk_write(H5F_t *f, void *vl_addr, void *buf, size_t len) FUNC_LEAVE (SUCCEED); } /* end H5T_vlen_disk_write() */ + +/*-------------------------------------------------------------------------- + NAME + H5T_vlen_reclaim_recurse + PURPOSE + Internal recursive routine to free VL datatypes + USAGE + herr_t H5T_vlen_reclaim(elem,dt) + void *elem; IN/OUT: Pointer to the dataset element + H5T_t *dt; IN: Datatype of dataset element + + RETURNS + SUCCEED/FAIL + DESCRIPTION + Frees any dynamic memory used by VL datatypes in the current dataset + element. Performs a recursive depth-first traversal of all compound + datatypes to free all VL datatype information allocated by any field. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5T_vlen_reclaim_recurse(void *elem, H5T_t *dt, H5MM_free_t free_func, void *free_info) +{ + intn i,j; /* local counting variable */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER(H5T_vlen_reclaim_recurse, FAIL); + + assert(elem); + assert(dt); + + /* Check the datatype of this element */ + switch(dt->type) { + /* Check each field and recurse on VL and compound ones */ + case H5T_COMPOUND: + for (i=0; i<dt->u.compnd.nmembs; i++) { + /* Recurse if it's VL or compound */ + if(dt->u.compnd.memb[i].type->type==H5T_COMPOUND || dt->u.compnd.memb[i].type->type==H5T_VLEN) { + uintn nelem=1; /* Number of array elements in field */ + void *off; /* offset of field */ + + /* Compute the number of array elements in field */ + for(j=0; j<dt->u.compnd.memb[i].ndims; j++) + nelem *= dt->u.compnd.memb[i].dim[j]; + + /* Calculate the offset of each array element and recurse on it */ + while(nelem>0) { + off=((uint8_t *)elem)+dt->u.compnd.memb[i].offset+(nelem-1)*dt->u.compnd.memb[i].type->size; + if(H5T_vlen_reclaim_recurse(off,dt->u.compnd.memb[i].type,free_func,free_info)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "Unable to free compound field"); + nelem--; + } /* end while */ + } /* end if */ + } /* end for */ + break; + + /* Recurse on the VL information if it's VL or compound, then free VL sequence */ + case H5T_VLEN: + { + hvl_t *vl=(hvl_t *)elem; /* Temp. ptr to the vl info */ + + /* Recurse if it's VL or compound */ + if(dt->parent->type==H5T_COMPOUND || dt->parent->type==H5T_VLEN) { + void *off; /* offset of field */ + + /* Calculate the offset of each array element and recurse on it */ + while(vl->len>0) { + off=((uint8_t *)vl->p)+(vl->len-1)*dt->parent->size; + if(H5T_vlen_reclaim_recurse(off,dt->parent,free_func,free_info)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "Unable to free VL element"); + vl->len--; + } /* end while */ + } /* end if */ + + /* Free the VL sequence */ + if(free_func!=NULL) + (*free_func)(vl->p,free_info); + else + H5MM_xfree(vl->p); + } /* end case */ + break; + + default: + break; + } /* end switch */ + +done: + FUNC_LEAVE(ret_value); +} /* end H5T_vlen_reclaim_recurse() */ + + +/*-------------------------------------------------------------------------- + NAME + H5T_vlen_reclaim + PURPOSE + Default method to reclaim any VL data for a buffer element + USAGE + herr_t H5T_vlen_reclaim(elem,type_id,ndim,point,op_data) + void *elem; IN/OUT: Pointer to the dataset element + hid_t type_id; IN: Datatype of dataset element + hsize_t ndim; IN: Number of dimensions in dataspace + hssize_t *point; IN: Coordinate location of element in dataspace + void *op_data IN: Operator data + + RETURNS + SUCCEED/FAIL + DESCRIPTION + Frees any dynamic memory used by VL datatypes in the current dataset + element. Recursively descends compound datatypes to free all VL datatype + information allocated by any field. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5T_vlen_reclaim(void *elem, hid_t type_id, hsize_t UNUSED ndim, hssize_t UNUSED *point, void *op_data) +{ + H5F_xfer_t *xfer_parms = (H5F_xfer_t *)op_data; /* Dataset transfer plist from iterator */ + H5T_t *dt = NULL; + herr_t ret_value = FAIL; + + FUNC_ENTER(H5T_vlen_reclaim, FAIL); + + assert(elem); + assert(H5I_DATATYPE == H5I_get_type(type_id)); + + /* Check args */ + if (H5I_DATATYPE!=H5I_get_type(type_id) || NULL==(dt=H5I_object(type_id))) + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + + /* Pull the free function and free info pointer out of the op_data and call the recurse datatype free function */ + ret_value=H5T_vlen_reclaim_recurse(elem,dt,xfer_parms->vlen_free,xfer_parms->free_info); + +#ifdef LATER +done: +#endif /* LATER */ + FUNC_LEAVE(ret_value); +} /* end H5T_vlen_reclaim() */ + + +/*-------------------------------------------------------------------------- + NAME + H5T_vlen_mark + PURPOSE + Recursively mark any VL datatypes as on disk/in memory + USAGE + herr_t H5T_vlen_mark(dt,f,loc) + H5T_t *dt; IN/OUT: Pointer to the datatype to mark + H5F_t *dt; IN: Pointer to the file the datatype is in + H5T_vlen_type_t loc IN: location of VL type + + RETURNS + SUCCEED/FAIL + DESCRIPTION + Recursively descends any VL or compound datatypes to mark all VL datatypes + as either on disk or in memory. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5T_vlen_mark(H5T_t *dt, H5F_t *f, H5T_vlen_type_t loc) +{ + intn i; /* local counting variable */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER(H5T_vlen_mark, FAIL); + + assert(dt); + assert(loc>H5T_VLEN_BADTYPE && loc<H5T_VLEN_MAXTYPE); + + /* Check the datatype of this element */ + switch(dt->type) { + /* Check each field and recurse on VL and compound ones */ + case H5T_COMPOUND: + for (i=0; i<dt->u.compnd.nmembs; i++) { + /* Recurse if it's VL or compound */ + if(dt->u.compnd.memb[i].type->type==H5T_COMPOUND || dt->u.compnd.memb[i].type->type==H5T_VLEN) { + if(H5T_vlen_mark(dt->u.compnd.memb[i].type,f,loc)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "Unable to set VL location"); + } /* end if */ + } /* end for */ + break; + + /* Recurse on the VL information if it's VL or compound, then free VL sequence */ + case H5T_VLEN: + /* Recurse if it's VL or compound */ + if(dt->parent->type==H5T_COMPOUND || dt->parent->type==H5T_VLEN) { + if(H5T_vlen_mark(dt->parent,f,loc)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "Unable to set VL location"); + } /* end if */ + + /* Mark this VL sequence */ + if(H5T_vlen_set_loc(dt,f,loc)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "Unable to set VL location"); + break; + + default: + break; + } /* end switch */ + +done: + FUNC_LEAVE(ret_value); +} /* end H5T_vlen_mark() */ |