summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJerome Soumagne <jsoumagne@hdfgroup.org>2015-09-24 23:52:08 (GMT)
committerJerome Soumagne <jsoumagne@hdfgroup.org>2016-11-29 23:42:31 (GMT)
commit6ce8e4ba64133f8175fd6ec4fe039793a16751ed (patch)
treed46b3b5435cb02de89a4990e25d2939bcb752f82 /src
parentcbec0173a20b62d44abbf0a5d60bc927e4cb81a8 (diff)
downloadhdf5-6ce8e4ba64133f8175fd6ec4fe039793a16751ed.zip
hdf5-6ce8e4ba64133f8175fd6ec4fe039793a16751ed.tar.gz
hdf5-6ce8e4ba64133f8175fd6ec4fe039793a16751ed.tar.bz2
Add H5R_REGION reference type
Add type/conversion routines to write/read H5R_REGION type H5Rcreate on H5R_REGION type no longer stores variable length type in global heap. The type is only stored in the heap if it is written to disk.
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/H5R.c98
-rw-r--r--src/H5Rpublic.h9
-rw-r--r--src/H5T.c39
-rw-r--r--src/H5Tconv.c129
-rw-r--r--src/H5Tnative.c18
-rw-r--r--src/H5Tpkg.h23
-rw-r--r--src/H5Tpublic.h2
-rw-r--r--src/H5Tref.c374
-rw-r--r--src/H5detect.c4
-rw-r--r--src/Makefile.am1
11 files changed, 675 insertions, 23 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 478680a..388ff28 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -588,6 +588,7 @@ set (H5T_SRCS
${HDF5_SRC_DIR}/H5Torder.c
${HDF5_SRC_DIR}/H5Tpad.c
${HDF5_SRC_DIR}/H5Tprecis.c
+ ${HDF5_SRC_DIR}/H5Tref.c
${HDF5_SRC_DIR}/H5Tstrpad.c
${HDF5_SRC_DIR}/H5Tvisit.c
${HDF5_SRC_DIR}/H5Tvlen.c
diff --git a/src/H5R.c b/src/H5R.c
index b8339a4..fbed9f1 100644
--- a/src/H5R.c
+++ b/src/H5R.c
@@ -51,7 +51,7 @@
/* Local Prototypes */
/********************/
-static H5S_t * H5R_get_region(H5F_t *file, hid_t dxpl_id, const void *_ref);
+static H5S_t * H5R_get_region(H5F_t *file, hid_t dxpl_id, H5R_type_t ref_type, const void *_ref);
static ssize_t H5R_get_name(H5F_t *file, hid_t lapl_id, hid_t dxpl_id, hid_t id,
H5R_type_t ref_type, const void *_ref, char *name, size_t size);
@@ -360,6 +360,56 @@ H5R_create(void *_ref, H5R_type_t ref_type, ...)
break;
}
+ case H5R_REGION:
+ {
+ H5G_loc_t *loc;
+ const char *name;
+ hid_t dxpl_id;
+ hreg_ref_t *ref = (hreg_ref_t *)_ref; /* Get pointer to correct type of reference struct */
+ hssize_t buf_size; /* Size of buffer needed to serialize selection */
+ uint8_t *p; /* Pointer to OID to store */
+ H5S_t *space;
+
+ /* Get arguments */
+ loc = va_arg(ap, H5G_loc_t *);
+ name = va_arg(ap, const char *);
+ dxpl_id = va_arg(ap, hid_t);
+ space = va_arg(ap, H5S_t *);
+
+ HDassert(ref);
+ HDassert(loc);
+ HDassert(name);
+ HDassert(space);
+
+ /* Find the object */
+ if(H5G_loc_find(loc, name, &obj_loc, H5P_DEFAULT, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_NOTFOUND, FAIL, "object not found")
+ obj_found = TRUE;
+
+ /* Get the amount of space required to serialize the selection */
+ if((buf_size = H5S_SELECT_SERIAL_SIZE(space)) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTINIT, FAIL, "Invalid amount of space for serializing selection")
+
+ /* Increase buffer size to allow for the dataset OID */
+ buf_size += (hssize_t)sizeof(haddr_t);
+
+ /* Allocate the space to store the serialized information */
+ H5_CHECK_OVERFLOW(buf_size, hssize_t, size_t);
+
+ if(!ref->buf || ref->buf_size < (size_t) buf_size) {
+ ref->buf_size = (size_t)buf_size;
+ } else {
+ /* Serialize information for dataset OID into buffer */
+ p = (uint8_t *)ref->buf;
+ H5F_addr_encode(loc->oloc->file, &p, obj_loc.oloc->addr);
+
+ /* Serialize the selection into buffer */
+ if(H5S_SELECT_SERIALIZE(space, &p) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOPY, FAIL, "Unable to serialize selection")
+ }
+ }
+ break;
+
case H5R_ATTR:
{
H5G_loc_t *loc;
@@ -531,6 +581,7 @@ H5Rcreate(void *ref, H5R_type_t ref_type, ...)
HGOTO_ERROR(H5E_REFERENCE, H5E_CANTINIT, FAIL, "unable to create reference")
}
break;
+ case H5R_REGION:
case H5R_DATASET_REGION:
{
hid_t loc_id;
@@ -715,6 +766,17 @@ H5R_dereference(H5F_t *file, hid_t oapl_id, hid_t dxpl_id, H5R_type_t ref_type,
} /* end case */
break;
+ case H5R_REGION:
+ {
+ const hreg_ref_t *ref = (const hreg_ref_t *)_ref; /* Get pointer to correct type of reference struct */
+ const uint8_t *p; /* Pointer to OID to store */
+
+ /* Get the object oid for the dataset */
+ p = (const uint8_t *)ref->buf;
+ H5F_addr_decode(oloc.file, &p, &(oloc.addr));
+ } /* end case */
+ break;
+
case H5R_BADTYPE:
case H5R_MAXTYPE:
default:
@@ -881,9 +943,10 @@ done:
PURPOSE
Retrieves a dataspace with the region pointed to selected.
USAGE
- H5S_t *H5R_get_region(file, dxpl_id, ref)
+ H5S_t *H5R_get_region(file, dxpl_id, ref_type, ref)
H5F_t *file; IN: File the object being dereferenced is within
hid_t dxpl_id; IN: Property list ID
+ H5R_type_t ref_type; IN: Type of reference to get region of
void *ref; IN: Reference to open.
RETURNS
@@ -898,7 +961,7 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static H5S_t *
-H5R_get_region(H5F_t *file, hid_t dxpl_id, const void *_ref)
+H5R_get_region(H5F_t *file, hid_t dxpl_id, H5R_type_t ref_type, const void *_ref)
{
H5O_loc_t oloc; /* Object location */
const uint8_t *p; /* Pointer to OID to store */
@@ -915,17 +978,26 @@ H5R_get_region(H5F_t *file, hid_t dxpl_id, const void *_ref)
H5O_loc_reset(&oloc);
oloc.file = file;
- /* Get the heap ID for the dataset region */
- p = (const uint8_t *)_ref;
- H5F_addr_decode(oloc.file, &p, &(hobjid.addr));
- UINT32DECODE(p, hobjid.idx);
+ if (ref_type == H5R_DATASET_REGION) {
+ /* Get the heap ID for the dataset region */
+ p = (const uint8_t *)_ref;
+ H5F_addr_decode(oloc.file, &p, &(hobjid.addr));
+ UINT32DECODE(p, hobjid.idx);
+
+ /* Get the dataset region from the heap (allocate inside routine) */
+ if((buf = (uint8_t *)H5HG_read(oloc.file, dxpl_id, &hobjid, NULL, NULL)) == NULL)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_READERROR, NULL, "Unable to read dataset region information")
- /* Get the dataset region from the heap (allocate inside routine) */
- if((buf = (uint8_t *)H5HG_read(oloc.file, dxpl_id, &hobjid, NULL, NULL)) == NULL)
- HGOTO_ERROR(H5E_REFERENCE, H5E_READERROR, NULL, "Unable to read dataset region information")
+ /* Point to heap buffer now */
+ p = buf;
+ } else {
+ const hreg_ref_t *ref = (const hreg_ref_t *)_ref; /* Get pointer to correct type of reference struct */
+
+ /* Point to reference buffer now */
+ p = (const uint8_t *)ref->buf;
+ }
/* Get the object oid for the dataset */
- p = buf;
H5F_addr_decode(oloc.file, &p, &(oloc.addr));
/* Open and copy the dataset's dataspace */
@@ -980,13 +1052,13 @@ H5Rget_region(hid_t id, H5R_type_t ref_type, const void *ref)
/* Check args */
if(H5G_loc(id, &loc) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
- if(ref_type != H5R_DATASET_REGION)
+ if(ref_type != H5R_DATASET_REGION && ref_type != H5R_REGION)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference type")
if(ref == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference pointer")
/* Get the dataspace with the correct region selected */
- if((space = H5R_get_region(loc.oloc->file, H5AC_ind_dxpl_id, ref)) == NULL)
+ if((space = H5R_get_region(loc.oloc->file, H5AC_ind_dxpl_id, ref_type, ref)) == NULL)
HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCREATE, FAIL, "unable to create dataspace")
/* Atomize */
diff --git a/src/H5Rpublic.h b/src/H5Rpublic.h
index 303059e..2ee47cf 100644
--- a/src/H5Rpublic.h
+++ b/src/H5Rpublic.h
@@ -31,6 +31,7 @@ typedef enum {
H5R_BADTYPE = (-1), /*invalid Reference Type */
H5R_OBJECT, /*Object reference */
H5R_DATASET_REGION, /*Dataset Region Reference */
+ H5R_REGION, /*Revised Dataset Region Reference */
H5R_ATTR, /*Attribute Reference */
H5R_MAXTYPE /*highest type (Invalid as true type) */
} H5R_type_t;
@@ -52,6 +53,14 @@ typedef haddr_t hobj_ref_t; /* Needs to be large enough to store largest haddr_t
typedef unsigned char hdset_reg_ref_t[H5R_DSET_REG_REF_BUF_SIZE];/* Buffer to store heap ID and index */
/* Needs to be large enough to store largest haddr_t in a worst case machine (ie. 8 bytes currently) plus an int */
+/* Variable length region reference struct in memory */
+typedef struct hreg_ref_t {
+ size_t buf_size;/* Size of serialized region reference */
+ void *buf; /* Pointer to serialized region reference */
+} hreg_ref_t;
+
+#define H5R_REG_REF_INITIALIZER { 0, NULL }
+
#define H5R_ATTR_REF_BUF_SIZE (2 * (sizeof(haddr_t) + 4))
/* Attribute reference structure for user's code */
typedef unsigned char hattr_ref_t[H5R_ATTR_REF_BUF_SIZE];/* Buffer to store two heap IDs and indices */
diff --git a/src/H5T.c b/src/H5T.c
index abdc5d6..54c3974 100644
--- a/src/H5T.c
+++ b/src/H5T.c
@@ -227,11 +227,18 @@
dt->shared->u.atomic.u.r.loc = H5T_LOC_MEMORY; \
}
-#define H5T_INIT_TYPE_REGREF_CORE { \
+#define H5T_INIT_TYPE_DSET_REGREF_CORE { \
H5T_INIT_TYPE_REF_COMMON \
dt->shared->u.atomic.u.r.rtype = H5R_DATASET_REGION; \
}
+#define H5T_INIT_TYPE_REGREF_CORE { \
+ H5T_INIT_TYPE_REF_COMMON \
+ dt->shared->force_conv = TRUE; \
+ dt->shared->u.atomic.u.r.rtype = H5R_REGION; \
+ dt->shared->u.atomic.u.r.loc = H5T_LOC_BADLOC; \
+}
+
#define H5T_INIT_TYPE_ATTRREF_CORE { \
H5T_INIT_TYPE_REF_COMMON \
dt->shared->u.atomic.u.r.rtype = H5R_ATTR; \
@@ -349,6 +356,7 @@ hid_t H5T_STD_B64BE_g = FAIL;
hid_t H5T_STD_B64LE_g = FAIL;
hid_t H5T_STD_REF_OBJ_g = FAIL;
hid_t H5T_STD_REF_DSETREG_g = FAIL;
+hid_t H5T_STD_REF_REG_g = FAIL;
hid_t H5T_STD_REF_ATTR_g = FAIL;
hid_t H5T_UNIX_D32BE_g = FAIL;
@@ -440,6 +448,7 @@ size_t H5T_POINTER_COMP_ALIGN_g = 0;
size_t H5T_HVL_COMP_ALIGN_g = 0;
size_t H5T_HOBJREF_COMP_ALIGN_g = 0;
size_t H5T_HDSETREGREF_COMP_ALIGN_g = 0;
+size_t H5T_HREGREF_COMP_ALIGN_g = 0;
size_t H5T_HATTRREF_COMP_ALIGN_g = 0;
/*
@@ -726,6 +735,7 @@ H5T__init_package(void)
H5T_t *vlen=NULL; /* Datatype structure for vlen objects */
H5T_t *array=NULL; /* Datatype structure for array objects */
H5T_t *objref=NULL; /* Datatype structure for object reference objects */
+ H5T_t *regref=NULL; /* Datatype structure for region reference objects */
hsize_t dim[1]={1}; /* Dimension info for array datatype */
herr_t status;
unsigned copied_dtype=1; /* Flag to indicate whether datatype was copied or allocated (for error cleanup) */
@@ -982,7 +992,14 @@ H5T__init_package(void)
objref = dt; /* Keep type for later */
/* Dataset Region reference (i.e. selection inside a dataset) */
- H5T_INIT_TYPE(REGREF, H5T_STD_REF_DSETREG_g, ALLOC, -, SET, H5R_DSET_REG_REF_BUF_SIZE)
+ H5T_INIT_TYPE(DSET_REGREF, H5T_STD_REF_DSETREG_g, ALLOC, -, SET, H5R_DSET_REG_REF_BUF_SIZE)
+
+ /* Dataset Region reference (i.e. selection inside a dataset) */
+ H5T_INIT_TYPE(REGREF, H5T_STD_REF_REG_g, ALLOC, -, NOSET, -)
+ /* TODO put that in the macro */
+ if(H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "invalid datatype location")
+ regref = dt; /* Keep type for later */
/* Attribute reference (i.e. object and attribute names in file) */
H5T_INIT_TYPE(ATTRREF, H5T_STD_REF_ATTR_g, ALLOC, -, SET, H5R_ATTR_REF_BUF_SIZE)
@@ -1021,6 +1038,7 @@ H5T__init_package(void)
status |= H5T_register(H5T_PERS_SOFT, "vlen", vlen, vlen, H5T__conv_vlen, H5AC_ind_dxpl_id, FALSE);
status |= H5T_register(H5T_PERS_SOFT, "array", array, array, H5T__conv_array, H5AC_ind_dxpl_id, FALSE);
status |= H5T_register(H5T_PERS_SOFT, "objref", objref, objref, H5T__conv_order_opt, H5AC_ind_dxpl_id, FALSE);
+ status |= H5T_register(H5T_PERS_SOFT, "regref", regref, regref, H5T__conv_ref, H5AC_ind_dxpl_id, FALSE);
/*
* Native conversions should be listed last since we can use hardware to
@@ -1451,6 +1469,7 @@ H5T_top_term_package(void)
H5T_STD_B64LE_g = FAIL;
H5T_STD_REF_OBJ_g = FAIL;
H5T_STD_REF_DSETREG_g = FAIL;
+ H5T_STD_REF_REG_g = FAIL;
H5T_STD_REF_ATTR_g = FAIL;
H5T_UNIX_D32BE_g = FAIL;
@@ -4335,7 +4354,12 @@ H5T_cmp(const H5T_t *dt1, const H5T_t *dt2, hbool_t superset)
/*void */
break;
- case H5R_ATTR:
+ case H5R_REGION:
+ /* Does this need more to distinguish it? -QAK 8/25/15 */
+ /*void */
+ break;
+
+ case H5R_ATTR:
/* Does this need more to distinguish it? -QAK 8/25/15 */
/*void */
break;
@@ -5131,7 +5155,7 @@ done:
htri_t H5T_set_loc(dt,f,loc)
H5T_t *dt; IN/OUT: Pointer to the datatype to mark
H5F_t *f; IN: Pointer to the file the datatype is in
- H5T_vlen_type_t loc IN: location of type
+ H5T_loc_t loc IN: location of type
RETURNS
One of two values on success:
@@ -5265,6 +5289,13 @@ H5T_set_loc(H5T_t *dt, H5F_t *f, H5T_loc_t loc)
ret_value=TRUE;
} /* end if */
} /* end if */
+ if(dt->shared->u.atomic.u.r.rtype == H5R_REGION) {
+ /* Mark this reference */
+ if((changed = H5T__ref_set_loc(dt, f, loc)) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "Unable to set reference location");
+ if(changed > 0)
+ ret_value = changed;
+ }
break;
case H5T_NO_CLASS:
diff --git a/src/H5Tconv.c b/src/H5Tconv.c
index 8b96d22..622d7a8 100644
--- a/src/H5Tconv.c
+++ b/src/H5Tconv.c
@@ -1025,6 +1025,9 @@ H5FL_BLK_DEFINE_STATIC(vlen_seq);
/* Declare a free list to manage pieces of array data */
H5FL_BLK_DEFINE_STATIC(array_seq);
+/* Declare a free list to manage pieces of reference data */
+H5FL_BLK_DEFINE_STATIC(ref_seq);
+
/*-------------------------------------------------------------------------
* Function: H5T__conv_noop
@@ -3560,6 +3563,132 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T__conv_array() */
+/*-------------------------------------------------------------------------
+ * Function: H5T__conv_ref
+ *
+ * Purpose: Converts between region reference datatypes in memory and on disk.
+ * This is a soft conversion function.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5T__conv_ref(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
+ size_t buf_stride, size_t bkg_stride, void *buf, void *bkg, hid_t dxpl_id)
+{
+ H5T_t *src = NULL; /* source datatype */
+ H5T_t *dst = NULL; /* destination datatype */
+ uint8_t *s = NULL; /* source buffer */
+ uint8_t *d = NULL; /* destination buffer */
+ uint8_t *b = NULL; /* background buffer */
+ ssize_t s_stride, d_stride; /* src and dst strides */
+ ssize_t b_stride; /* bkg stride */
+ void *conv_buf = NULL; /* temporary conversion buffer */
+ size_t conv_buf_size = 0; /* size of conversion buffer in bytes */
+ size_t elmtno; /* element number counter */
+ herr_t ret_value = SUCCEED; /* return value */
+
+ FUNC_ENTER_PACKAGE
+
+ switch(cdata->command) {
+ case H5T_CONV_INIT:
+ /*
+ * First, determine if this conversion function applies to the
+ * conversion path SRC_ID-->DST_ID. If not, return failure;
+ * otherwise initialize the `priv' field of `cdata' with
+ * information that remains (almost) constant for this
+ * conversion path.
+ */
+ if(NULL == (src = (H5T_t *)H5I_object(src_id)) || NULL == (dst = (H5T_t *)H5I_object(dst_id)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not a datatype")
+ if(H5T_REFERENCE != src->shared->type)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not a H5T_REFERENCE datatype")
+ if(H5T_REFERENCE != dst->shared->type)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not a H5T_REFERENCE datatype")
+
+ /* Reference types don't need a background buffer */
+ cdata->need_bkg = H5T_BKG_NO;
+ break;
+
+ case H5T_CONV_FREE:
+ break;
+
+ case H5T_CONV_CONV:
+ {
+ /*
+ * Conversion.
+ */
+ if(NULL == (src = (H5T_t *)H5I_object(src_id)) || NULL == (dst = (H5T_t *)H5I_object(dst_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
+
+ /* Initialize source & destination strides */
+ if(buf_stride) {
+ HDassert(buf_stride >= src->shared->size);
+ HDassert(buf_stride >= dst->shared->size);
+ H5_CHECK_OVERFLOW(buf_stride, size_t, ssize_t);
+ s_stride = d_stride = (ssize_t)buf_stride;
+ } /* end if */
+ else {
+ H5_CHECK_OVERFLOW(src->shared->size, size_t, ssize_t);
+ H5_CHECK_OVERFLOW(dst->shared->size, size_t, ssize_t);
+ s_stride = (ssize_t)src->shared->size;
+ d_stride = (ssize_t)dst->shared->size;
+ } /* end else */
+ if(bkg) {
+ if(bkg_stride)
+ b_stride = (ssize_t)bkg_stride;
+ else
+ b_stride = d_stride;
+ } /* end if */
+ else
+ b_stride = 0;
+
+ /* Single forward pass over all data */
+ s = d = (uint8_t *)buf;
+ b = (uint8_t *)bkg;
+
+ for(elmtno = 0; elmtno < nelmts; elmtno++) {
+ size_t buf_size;
+
+ /* Get size of references */
+ if(0 == (buf_size = (*(src->shared->u.atomic.u.r.getsize))(s)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "incorrect length")
+
+ /* Check if conversion buffer is large enough, resize if necessary. */
+ conv_buf_size = buf_size;
+ if(NULL == (conv_buf = H5FL_BLK_REALLOC(ref_seq, conv_buf, conv_buf_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion")
+ HDmemset(conv_buf, 0, conv_buf_size);
+
+ /* Read reference */
+ if((*(src->shared->u.atomic.u.r.read))(src->shared->u.atomic.u.r.f, dxpl_id, s, conv_buf, buf_size) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_READERROR, FAIL, "can't read reference data")
+
+ /* Write reference to destination location */
+ if((*(dst->shared->u.atomic.u.r.write))(dst->shared->u.atomic.u.r.f, dxpl_id, d, conv_buf, b, buf_size) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "can't write reference data")
+
+ /* Advance pointers */
+ s += s_stride;
+ d += d_stride;
+ b += b_stride;
+ } /* end for */
+ } /* end case */
+ break;
+
+ default: /* Some other command we don't know about yet.*/
+ HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command")
+ } /* end switch */
+
+done:
+ /* Release the conversion buffer (always allocated, except on errors) */
+ if(conv_buf)
+ conv_buf = H5FL_BLK_FREE(ref_seq, conv_buf);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T__conv_ref() */
+
/*-------------------------------------------------------------------------
* Function: H5T__conv_i_i
diff --git a/src/H5Tnative.c b/src/H5Tnative.c
index 7860eca..7f536cf 100644
--- a/src/H5Tnative.c
+++ b/src/H5Tnative.c
@@ -234,7 +234,7 @@ H5T_get_native_type(H5T_t *dtype, H5T_direction_t direction, size_t *struct_alig
ref_size = sizeof(hobj_ref_t);
} /* end if */
else {
- /* Decide if the datatype is a dataset region or attribute reference. */
+ /* Decide if the datatype is a dataset region reference. */
if(NULL == (dt = (H5T_t *)H5I_object(H5T_STD_REF_DSETREG_g)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a datatype")
not_equal = H5T_cmp(ret_value, dt, FALSE);
@@ -245,8 +245,20 @@ H5T_get_native_type(H5T_t *dtype, H5T_direction_t direction, size_t *struct_alig
ref_size = sizeof(hdset_reg_ref_t);
} /* end if */
else {
- align = H5T_HATTRREF_COMP_ALIGN_g;
- ref_size = sizeof(hattr_ref_t);
+ /* Decide if the datatype is a dataset region reference. */
+ if(NULL == (dt = (H5T_t *)H5I_object(H5T_STD_REF_REG_g)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a datatype")
+ not_equal = H5T_cmp(ret_value, dt, FALSE);
+
+ /* Update size, offset and compound alignment for parent. */
+ if(!not_equal) {
+ align = H5T_HREGREF_COMP_ALIGN_g;
+ ref_size = sizeof(hreg_ref_t);
+ } /* end if */
+ else {
+ align = H5T_HATTRREF_COMP_ALIGN_g;
+ ref_size = sizeof(hattr_ref_t);
+ } /* end else */
} /* end else */
} /* end else */
diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h
index eb2f1e2..fdc3dd7 100644
--- a/src/H5Tpkg.h
+++ b/src/H5Tpkg.h
@@ -164,6 +164,13 @@ struct H5T_path_t {
H5T_cdata_t cdata; /*data for this function */
};
+/* Reference function pointers */
+typedef size_t (*H5T_ref_getsizefunc_t)(const void *_ref);
+typedef herr_t (*H5T_ref_readfunc_t)(H5F_t *f, hid_t dxpl_id, void *_ref,
+ void *buf, size_t buf_size);
+typedef herr_t (*H5T_ref_writefunc_t)(H5F_t *f, hid_t dxpl_id, void *_ref,
+ void *buf, void *_bg, size_t buf_size);
+
typedef struct H5T_atomic_t {
H5T_order_t order; /*byte order */
size_t prec; /*precision in bits */
@@ -192,8 +199,12 @@ typedef struct H5T_atomic_t {
} s; /*string types */
struct {
- H5R_type_t rtype; /*type of reference stored */
- H5T_loc_t loc; /* Location of data in buffer */
+ H5R_type_t rtype; /*type of reference stored */
+ H5T_loc_t loc; /*location of data in buffer */
+ H5F_t *f; /*file ID (if data is on disk) */
+ H5T_ref_getsizefunc_t getsize; /*function to get reference size (bytes) */
+ H5T_ref_readfunc_t read; /*function to read reference into buffer */
+ H5T_ref_writefunc_t write; /*function to write reference from buffer */
} r; /*reference types */
} u;
} H5T_atomic_t;
@@ -356,6 +367,7 @@ H5_DLLVAR size_t H5T_POINTER_COMP_ALIGN_g;
H5_DLLVAR size_t H5T_HVL_COMP_ALIGN_g;
H5_DLLVAR size_t H5T_HOBJREF_COMP_ALIGN_g;
H5_DLLVAR size_t H5T_HDSETREGREF_COMP_ALIGN_g;
+H5_DLLVAR size_t H5T_HREGREF_COMP_ALIGN_g;
H5_DLLVAR size_t H5T_HATTRREF_COMP_ALIGN_g;
/*
@@ -474,6 +486,10 @@ H5_DLL herr_t H5T__conv_array(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
size_t nelmts, size_t buf_stride,
size_t bkg_stride, void *buf, void *bkg,
hid_t dset_xfer_plist);
+H5_DLL herr_t H5T__conv_ref(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
+ size_t nelmts, size_t buf_stride,
+ size_t bkg_stride, void *buf, void *bkg,
+ hid_t dset_xfer_plist);
H5_DLL herr_t H5T__conv_i_i(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
size_t nelmts, size_t buf_stride,
size_t bkg_stride, void *_buf, void *bkg,
@@ -1302,6 +1318,9 @@ H5_DLL H5T_t *H5T__array_create(H5T_t *base, unsigned ndims, const hsize_t dim[/
H5_DLL int H5T__get_array_ndims(const H5T_t *dt);
H5_DLL int H5T__get_array_dims(const H5T_t *dt, hsize_t dims[]);
+/* Reference functions */
+H5_DLL htri_t H5T__ref_set_loc(const H5T_t *dt, H5F_t *f, H5T_loc_t loc);
+
/* Compound functions */
H5_DLL herr_t H5T__insert(H5T_t *parent, const char *name, size_t offset,
const H5T_t *member);
diff --git a/src/H5Tpublic.h b/src/H5Tpublic.h
index 0fe7fcf..f27025c 100644
--- a/src/H5Tpublic.h
+++ b/src/H5Tpublic.h
@@ -266,6 +266,7 @@ H5_DLLVAR hid_t H5T_IEEE_F64LE_g;
#define H5T_STD_B64LE (H5OPEN H5T_STD_B64LE_g)
#define H5T_STD_REF_OBJ (H5OPEN H5T_STD_REF_OBJ_g)
#define H5T_STD_REF_DSETREG (H5OPEN H5T_STD_REF_DSETREG_g)
+#define H5T_STD_REF_REG (H5OPEN H5T_STD_REF_REG_g)
#define H5T_STD_REF_ATTR (H5OPEN H5T_STD_REF_ATTR_g)
H5_DLLVAR hid_t H5T_STD_I8BE_g;
H5_DLLVAR hid_t H5T_STD_I8LE_g;
@@ -293,6 +294,7 @@ H5_DLLVAR hid_t H5T_STD_B64BE_g;
H5_DLLVAR hid_t H5T_STD_B64LE_g;
H5_DLLVAR hid_t H5T_STD_REF_OBJ_g;
H5_DLLVAR hid_t H5T_STD_REF_DSETREG_g;
+H5_DLLVAR hid_t H5T_STD_REF_REG_g;
H5_DLLVAR hid_t H5T_STD_REF_ATTR_g;
/*
diff --git a/src/H5Tref.c b/src/H5Tref.c
new file mode 100644
index 0000000..def5cb1
--- /dev/null
+++ b/src/H5Tref.c
@@ -0,0 +1,374 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Module Info: This module contains the functionality for reference
+ * datatypes in the H5T interface.
+ */
+
+#include "H5Tmodule.h" /* This source code file is part of the H5T module */
+
+
+#include "H5private.h" /* Generic Functions */
+#include "H5Dprivate.h" /* Dataset functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5HGprivate.h" /* Global Heaps */
+#include "H5Iprivate.h" /* IDs */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5Pprivate.h" /* Property lists */
+#include "H5Tpkg.h" /* Datatypes */
+
+/* Local functions */
+static size_t H5T__ref_reg_mem_getsize(const void *_ref);
+static herr_t H5T__ref_reg_mem_read(H5F_t *f, hid_t dxpl_id, void *_ref, void *_buf, size_t buf_size);
+static herr_t H5T__ref_reg_mem_write(H5F_t *f, hid_t dxpl_id, void *_ref, void *_buf, void *_bg, size_t buf_size);
+
+static size_t H5T__ref_disk_getsize(const void *_ref);
+static herr_t H5T__ref_disk_read(H5F_t *f, hid_t dxpl_id, void *_ref, void *_buf, size_t buf_size);
+static herr_t H5T__ref_disk_write(H5F_t *f, hid_t dxpl_id, void *_ref, void *_buf, void *_bg, size_t buf_size);
+
+/* Local variables */
+
+/*-------------------------------------------------------------------------
+ * Function: H5T__ref_set_loc
+ *
+ * Purpose: Sets the location of a reference datatype to be either on disk
+ * or in memory
+ *
+ * Return:
+ * One of two values on success:
+ * TRUE - If the location of any reference types changed
+ * FALSE - If the location of any reference types is the same
+ * Negative value is returned on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5T__ref_set_loc(const H5T_t *dt, H5F_t *f, H5T_loc_t loc)
+{
+ htri_t ret_value = FALSE; /* Indicate success, but no location change */
+
+ FUNC_ENTER_PACKAGE
+
+ /* check parameters */
+ HDassert(dt);
+ HDassert(loc >= H5T_LOC_BADLOC && loc < H5T_LOC_MAXLOC);
+
+ /* Only change the location if it's different */
+ if(loc != dt->shared->u.atomic.u.r.loc || f != dt->shared->u.atomic.u.r.f) {
+ switch(loc) {
+ case H5T_LOC_MEMORY: /* Memory based reference datatype */
+ HDassert(NULL == f);
+
+ /* Mark this type as being stored in memory */
+ dt->shared->u.atomic.u.r.loc = H5T_LOC_MEMORY;
+
+ if(dt->shared->u.atomic.u.r.rtype == H5R_REGION) {
+ /* size in memory, disk size is different */
+ dt->shared->size = sizeof(hreg_ref_t);
+
+ /* Set up the function pointers to access the region
+ * reference in memory */
+ dt->shared->u.atomic.u.r.getsize = H5T__ref_reg_mem_getsize;
+ dt->shared->u.atomic.u.r.read = H5T__ref_reg_mem_read;
+ dt->shared->u.atomic.u.r.write = H5T__ref_reg_mem_write;
+ } else {
+ HDassert(0 && "Invalid reference type");
+ }
+
+ /* Reset file ID (since this reference is in memory) */
+ dt->shared->u.atomic.u.r.f = NULL;
+ break;
+
+ case H5T_LOC_DISK: /* Disk based reference datatype */
+ HDassert(f);
+
+ /* Mark this type as being stored on disk */
+ dt->shared->u.atomic.u.r.loc = H5T_LOC_DISK;
+
+ /*
+ * Size of element on disk is 4 bytes for the length, plus the size
+ * of an address in this file, plus 4 bytes for the size of a heap
+ * ID. Memory size is different
+ */
+ dt->shared->size = (size_t) (2 * H5_SIZEOF_UINT32_T) + H5F_SIZEOF_ADDR(f);
+
+ /*
+ * Set up the function pointers to access the information on
+ * disk. Region and attribute references are stored identically
+ * on disk, so use the same functions
+ */
+ dt->shared->u.atomic.u.r.getsize = H5T__ref_disk_getsize;
+ dt->shared->u.atomic.u.r.read = H5T__ref_disk_read;
+ dt->shared->u.atomic.u.r.write = H5T__ref_disk_write;
+
+ /* Set file ID (since this reference is on disk) */
+ dt->shared->u.atomic.u.r.f = f;
+ break;
+
+ case H5T_LOC_BADLOC:
+ case H5T_LOC_MAXLOC:
+ default:
+ HGOTO_ERROR(H5E_DATATYPE, H5E_BADRANGE, FAIL, "invalid reference datatype location")
+ } /* end switch */
+
+ /* Indicate that the location changed */
+ ret_value = TRUE;
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T__ref_set_loc() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5T__ref_reg_mem_getsize
+ *
+ * Purpose: Retrieves the size of a memory based region reference.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+H5T__ref_reg_mem_getsize(const void *_ref)
+{
+#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
+ const hreg_ref_t *ref = (const hreg_ref_t *)_ref;
+#else
+ hreg_ref_t ref;
+#endif
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* check parameters, return result */
+#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
+ HDassert(ref);
+
+ FUNC_LEAVE_NOAPI(ref->buf_size)
+#else
+ HDassert(_ref);
+ HDmemcpy(&ref, _ref, sizeof(hreg_ref_t));
+
+ FUNC_LEAVE_NOAPI(ref.buf_size)
+#endif
+} /* end H5T__ref_reg_mem_getsize() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5T__ref_reg_mem_read
+ *
+ * Purpose: "Reads" the memory based region reference into a buffer
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5T__ref_reg_mem_read(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id,
+ void *_ref, void *buf, size_t buf_size)
+{
+#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
+ const hreg_ref_t *ref = (const hreg_ref_t *)_ref;
+#else
+ hreg_ref_t ref;
+#endif
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* check parameters, copy data */
+ HDassert(buf);
+#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
+ HDassert(ref && ref->buf);
+
+ HDmemcpy(buf, ref->buf, buf_size);
+#else
+ HDassert(_ref);
+ HDmemcpy(&ref, _ref, sizeof(hreg_ref_t));
+ HDassert(ref.buf);
+
+ HDmemcpy(buf, ref.buf, buf_size);
+#endif
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5T__ref_reg_mem_read() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5T__ref_reg_mem_write
+ *
+ * Purpose: "Writes" the memory region reference from a buffer
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5T__ref_reg_mem_write(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id,
+ void *_ref, void *buf, void H5_ATTR_UNUSED *_bg, size_t buf_size)
+{
+ hreg_ref_t ref;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* check parameters */
+ HDassert(_ref);
+ HDassert(buf);
+
+ if (buf_size != 0) {
+ if (NULL == (ref.buf = H5MM_malloc(buf_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for reference data")
+
+ /* Copy the data into the newly allocated buffer */
+ HDmemcpy(ref.buf, buf, buf_size);
+ } /* end if */
+ else
+ ref.buf = NULL;
+
+ /* Set the size */
+ ref.buf_size = buf_size;
+
+ /* Set pointer in user's buffer with memcpy, to avoid alignment issues */
+ HDmemcpy(_ref, &ref, sizeof(hreg_ref_t));
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T__ref_reg_mem_write() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5T__ref_disk_getsize
+ *
+ * Purpose: Retrieves the length of a disk based reference element.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+H5T__ref_disk_getsize(const void *_ref)
+{
+ const uint8_t *ref = (const uint8_t *)_ref; /* Pointer to the disk reference information */
+ size_t buf_size = 0;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* check parameters */
+ HDassert(ref);
+
+ UINT32DECODE(ref, buf_size);
+
+ FUNC_LEAVE_NOAPI(buf_size)
+} /* end H5T__ref_disk_getsize() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5T__ref_disk_read
+ *
+ * Purpose: Reads the disk based region element into a buffer
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5T__ref_disk_read(H5F_t *f, hid_t dxpl_id, void *_ref, void *buf,
+ size_t H5_ATTR_UNUSED buf_size)
+{
+ const uint8_t *ref = (const uint8_t *)_ref;
+ H5HG_t hobjid;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* check parameters */
+ HDassert(ref);
+ HDassert(buf);
+ HDassert(f);
+
+ /* Skip the length of the sequence */
+ ref += 4;
+
+ /* Get the heap information */
+ H5F_addr_decode(f, (const uint8_t **)&ref, &(hobjid.addr));
+ UINT32DECODE(ref, hobjid.idx);
+
+ /* Check if this sequence actually has any data */
+ if(hobjid.addr > 0) {
+ /* Read the VL information from disk */
+ if(H5HG_read(f, dxpl_id, &hobjid, buf, NULL) == NULL)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_READERROR, FAIL, "Unable to read reference information")
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T__ref_disk_read() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5T__ref_disk_write
+ *
+ * Purpose: Writes the disk based region element from a buffer
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5T__ref_disk_write(H5F_t *f, hid_t dxpl_id, void *_ref, void *buf, void *_bg,
+ size_t buf_size)
+{
+ uint8_t *ref = (uint8_t *)_ref; /* Pointer to the user's information */
+ const uint8_t *bg = (const uint8_t *)_bg; /* Pointer to the old data */
+ H5HG_t hobjid; /* New reference's heap ID */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* check parameters */
+ HDassert(ref);
+ HDassert(buf_size == 0 || buf);
+ HDassert(f);
+
+ /* TODO not sure if we need that but oh well... */
+ /* Free heap object for old data. */
+ if(bg != NULL) {
+ H5HG_t bg_hobjid; /* "Background" reference's ID info */
+
+ /* Skip the length of the reference and heap object ID from background data. */
+ bg += 4;
+
+ /* Get heap information */
+ H5F_addr_decode(f, (const uint8_t **)&bg, &(bg_hobjid.addr));
+ UINT32DECODE(bg, bg_hobjid.idx);
+
+ /* Free heap object for old data */
+ if(bg_hobjid.addr > 0) {
+ /* Free heap object */
+ if(H5HG_remove(f, dxpl_id, &bg_hobjid) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "Unable to remove heap object")
+ } /* end if */
+ } /* end if */
+
+ /* Set the size */
+ UINT32ENCODE(ref, buf_size);
+
+ /* Write the reference information to disk (allocates space also) */
+ if(H5HG_insert(f, dxpl_id, buf_size, buf, &hobjid) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "Unable to write reference information")
+
+ /* Encode the heap information */
+ H5F_addr_encode(f, &ref, hobjid.addr);
+ UINT32ENCODE(ref, hobjid.idx);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T__ref_disk_write() */
+
diff --git a/src/H5detect.c b/src/H5detect.c
index 454118e..ad0205b 100644
--- a/src/H5detect.c
+++ b/src/H5detect.c
@@ -1653,11 +1653,13 @@ detect_C99_floats(void)
static void
detect_alignments(void)
{
- /* Detect structure alignment for pointers, hvl_t, hobj_ref_t, hdset_reg_ref_t, hattr_ref_t */
+ /* Detect structure alignment for pointers, hvl_t, hobj_ref_t,
+ * hdset_reg_ref_t, hattr_ref_t, hreg_ref_t */
DETECT_M(void *, POINTER, m_g[na_g]); na_g++;
DETECT_M(hvl_t, HVL, m_g[na_g]); na_g++;
DETECT_M(hobj_ref_t, HOBJREF, m_g[na_g]); na_g++;
DETECT_M(hdset_reg_ref_t, HDSETREGREF, m_g[na_g]); na_g++;
+ DETECT_M(hreg_ref_t, HREGREF, m_g[na_g]); na_g++;
DETECT_M(hattr_ref_t, HATTRREF, m_g[na_g]); na_g++;
}
diff --git a/src/Makefile.am b/src/Makefile.am
index 49fca61..09047fc 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -108,6 +108,7 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5Tfloat.c H5Tinit.c H5Tnative.c H5Toffset.c H5Toh.c \
H5Topaque.c \
H5Torder.c \
+ H5Tref.c \
H5Tpad.c H5Tprecis.c H5Tstrpad.c H5Tvisit.c H5Tvlen.c H5TS.c H5VM.c H5WB.c H5Z.c \
H5X.c H5Xdummy.c H5Xalacrity.c H5Xfastbit.c \
H5Zdeflate.c H5Zfletcher32.c H5Znbit.c H5Zshuffle.c \