summaryrefslogtreecommitdiffstats
path: root/src/H5Rint.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Rint.c')
-rw-r--r--src/H5Rint.c1856
1 files changed, 1414 insertions, 442 deletions
diff --git a/src/H5Rint.c b/src/H5Rint.c
index 07efae2..e33eecb 100644
--- a/src/H5Rint.c
+++ b/src/H5Rint.c
@@ -35,11 +35,73 @@
#include "H5Sprivate.h" /* Dataspaces */
#include "H5Tprivate.h" /* Datatypes */
-
/****************/
/* Local Macros */
/****************/
+#define H5R_MAX_STRING_LEN (1 << 16) /* Max encoded string length */
+
+/* Encode macro */
+#define H5R_ENCODE(func, val, buf, buf_size, actual, m) do {\
+ size_t __nalloc = buf_size; \
+ if(func(val, buf, &__nalloc) < 0) \
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTENCODE, FAIL, m) \
+ if(buf && buf_size >= __nalloc) { \
+ buf += __nalloc; \
+ buf_size -= __nalloc; \
+ } \
+ actual += __nalloc; \
+} while(0)
+
+#define H5R_ENCODE_VAR(func, var, size, buf, buf_size, actual, m) do { \
+ size_t __nalloc = buf_size; \
+ if(func(var, size, buf, &__nalloc) < 0) \
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTENCODE, FAIL, m) \
+ if(buf && buf_size >= __nalloc) { \
+ p += __nalloc; \
+ buf_size -= __nalloc; \
+ } \
+ actual += __nalloc; \
+} while(0)
+
+/* Decode macro */
+#define H5R_DECODE(func, val, buf, buf_size, actual, m) do {\
+ size_t __nbytes = buf_size; \
+ if(func(buf, &__nbytes, val) < 0) \
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, m) \
+ buf += __nbytes; \
+ buf_size -= __nbytes; \
+ actual += __nbytes; \
+} while(0)
+
+#define H5R_DECODE_VAR(func, var, size, buf, buf_size, actual, m) do { \
+ size_t __nbytes = buf_size; \
+ if(func(buf, &__nbytes, var, size) < 0) \
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, m) \
+ p += __nbytes; \
+ buf_size -= __nbytes; \
+ actual += __nbytes; \
+} while(0)
+
+/* Debug */
+//#define H5R_DEBUG
+#ifdef H5R_DEBUG
+#define H5R_LOG_DEBUG(...) do { \
+ HDfprintf(stdout, " # %s(): ", __func__); \
+ HDfprintf(stdout, __VA_ARGS__); \
+ HDfprintf(stdout, "\n"); \
+ HDfflush(stdout); \
+ } while (0)
+static const char *
+H5R__print_token(const H5VL_token_t token) {
+ static char string[64];
+ HDsnprintf(string, 64, "%zu", *(haddr_t *)token);
+ return string;
+}
+#else
+#define H5R_LOG_DEBUG(...) do { } while (0)
+#endif
+
/******************/
/* Local Typedefs */
/******************/
@@ -48,6 +110,13 @@
/* Local Prototypes */
/********************/
+static herr_t H5R__encode_obj_token(const H5VL_token_t *obj_token, size_t token_size, unsigned char *buf, size_t *nalloc);
+static herr_t H5R__decode_obj_token(const unsigned char *buf, size_t *nbytes, H5VL_token_t *obj_token, uint8_t *token_size);
+static herr_t H5R__encode_region(H5S_t *space, unsigned char *buf, size_t *nalloc);
+static herr_t H5R__decode_region(const unsigned char *buf, size_t *nbytes, H5S_t **space_ptr);
+static herr_t H5R__encode_string(const char *string, unsigned char *buf, size_t *nalloc);
+static herr_t H5R__decode_string(const unsigned char *buf, size_t *nbytes, char **string_ptr);
+
/*********************/
/* Package Variables */
/*********************/
@@ -82,14 +151,15 @@ DESCRIPTION
herr_t
H5R__init_package(void)
{
- herr_t ret_value = SUCCEED; /* Return value */
-
FUNC_ENTER_NOAPI_NOINIT_NOERR
/* Mark "top" of interface as initialized */
H5R_top_package_initialize_s = TRUE;
- FUNC_LEAVE_NOAPI(ret_value)
+ /* Sanity check, if assert fails, H5R_REF_BUF_SIZE must be increased */
+ HDcompile_assert(sizeof(H5R_ref_priv_t) <= H5R_REF_BUF_SIZE);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5R__init_package() */
@@ -167,571 +237,1473 @@ H5R_term_package(void)
} /* end H5R_term_package() */
-/*--------------------------------------------------------------------------
- NAME
- H5R__create
- PURPOSE
- Creates a particular kind of reference for the user
- USAGE
- herr_t H5R__create(ref, loc, name, ref_type, space)
- void *ref; OUT: Reference created
- H5G_loc_t *loc; IN: File location used to locate object pointed to
- const char *name; IN: Name of object at location LOC_ID of object
- pointed to
- H5R_type_t ref_type; IN: Type of reference to create
- H5S_t *space; IN: Dataspace ID with selection, used for Dataset
- Region references.
+/*-------------------------------------------------------------------------
+ * Function: H5R__create_object
+ *
+ * Purpose: Creates an object reference.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__create_object(const H5VL_token_t *obj_token, size_t token_size,
+ H5R_ref_priv_t *ref)
+{
+ size_t encode_size;
+ herr_t ret_value = SUCCEED; /* Return value */
- RETURNS
- Non-negative on success/Negative on failure
- DESCRIPTION
- Creates a particular type of reference specified with REF_TYPE, in the
- space pointed to by REF. The LOC_ID and NAME are used to locate the object
- pointed to and the SPACE_ID is used to choose the region pointed to (for
- Dataset Region references).
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
+ FUNC_ENTER_PACKAGE
+
+ HDassert(ref);
+
+ /* Create new reference */
+ H5MM_memcpy(ref->ref.obj.token, obj_token, token_size);
+ ref->ref.obj.filename = NULL;
+ ref->loc_id = H5I_INVALID_HID;
+ ref->type = (uint8_t)H5R_OBJECT2;
+ ref->token_size = (uint8_t)token_size;
+
+ /* Cache encoding size (assume no external reference) */
+ if(H5R__encode(NULL, ref, NULL, &encode_size, 0) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTENCODE, FAIL, "unable to determine encoding size")
+ ref->encode_size = (uint32_t)encode_size;
+
+ H5R_LOG_DEBUG("Created object reference, %d, filename=%s, obj_addr=%s, encode size=%u",
+ (int)sizeof(H5R_ref_priv_t), ref->ref.obj.filename, H5R__print_token(ref->ref.obj.token),
+ ref->encode_size);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__create_object() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__create_region
+ *
+ * Purpose: Creates a region reference.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
herr_t
-H5R__create(void *_ref, H5G_loc_t *loc, const char *name, H5R_type_t ref_type, H5S_t *space)
+H5R__create_region(const H5VL_token_t *obj_token, size_t token_size,
+ H5S_t *space, H5R_ref_priv_t *ref)
{
- H5G_loc_t obj_loc; /* Group hier. location of object */
- H5G_name_t path; /* Object group hier. path */
- H5O_loc_t oloc; /* Object object location */
- hbool_t obj_found = FALSE; /* Object location found */
- herr_t ret_value = SUCCEED; /* Return value */
+ size_t encode_size;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
- HDassert(_ref);
- HDassert(loc);
- HDassert(name);
- HDassert(ref_type > H5R_BADTYPE && ref_type < H5R_MAXTYPE);
+ HDassert(space);
+ HDassert(ref);
- /* Set up object location to fill in */
- obj_loc.oloc = &oloc;
- obj_loc.path = &path;
- H5G_loc_reset(&obj_loc);
+ /* Create new reference */
+ H5MM_memcpy(ref->ref.obj.token, obj_token, token_size);
+ ref->ref.obj.filename = NULL;
+ if(NULL == (ref->ref.reg.space = H5S_copy(space, FALSE, TRUE)))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOPY, FAIL, "unable to copy dataspace")
- /* Set the FAPL for the API context */
- H5CX_set_libver_bounds(loc->oloc->file);
+ ref->loc_id = H5I_INVALID_HID;
+ ref->type = (uint8_t)H5R_DATASET_REGION2;
+ ref->token_size = (uint8_t)token_size;
- /* Find the object */
- if(H5G_loc_find(loc, name, &obj_loc) < 0)
- HGOTO_ERROR(H5E_REFERENCE, H5E_NOTFOUND, FAIL, "object not found")
- obj_found = TRUE;
+ /* Cache encoding size (assume no external reference) */
+ if(H5R__encode(NULL, ref, NULL, &encode_size, 0) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTENCODE, FAIL, "unable to determine encoding size")
+ ref->encode_size = (uint32_t)encode_size;
- switch (ref_type) {
- case H5R_OBJECT:
- {
- hobj_ref_t *ref = (hobj_ref_t *)_ref; /* Get pointer to correct type of reference struct */
+ H5R_LOG_DEBUG("Created region reference, %d, filename=%s, obj_addr=%s, encode size=%u",
+ (int)sizeof(H5R_ref_priv_t), ref->ref.obj.filename, H5R__print_token(ref->ref.obj.token),
+ ref->encode_size);
- *ref = obj_loc.oloc->addr;
- break;
+done:
+ if(ret_value < 0) {
+ if(ref->ref.reg.space) {
+ H5S_close(ref->ref.reg.space);
+ ref->ref.reg.space = NULL;
}
+ }
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5R__create_region */
- case H5R_DATASET_REGION:
- {
- H5HG_t hobjid; /* Heap object ID */
- hdset_reg_ref_t *ref = (hdset_reg_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 */
- uint8_t *buf; /* Buffer to store serialized selection in */
- unsigned heapid_found; /* Flag for non-zero heap ID found */
- unsigned u; /* local index */
-
- /* Set up information for dataset region */
-
- /* Return any previous heap block to the free list if we are
- * garbage collecting
- */
- if (H5F_GC_REF(loc->oloc->file)) {
- /* Check for an existing heap ID in the reference */
- for (u = 0, heapid_found = 0, p = (uint8_t *)ref; u < H5R_DSET_REG_REF_BUF_SIZE; u++)
- if (p[u] != 0) {
- heapid_found = 1;
- break;
- }
-
- if (heapid_found != 0) {
- /* Return heap block to free list */
- }
- }
-
- /* Zero the heap ID out, may leak heap space if user is re-using
- * reference and doesn't have garbage collection turned on
- */
- HDmemset(ref, 0, H5R_DSET_REG_REF_BUF_SIZE);
-
- /* 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 (NULL == (buf = (uint8_t *)H5MM_malloc((size_t)buf_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
-
- /* Serialize information for dataset OID into heap buffer */
- p = (uint8_t *)buf;
- H5F_addr_encode(loc->oloc->file, &p, obj_loc.oloc->addr);
-
- /* Serialize the selection into heap buffer */
- if (H5S_SELECT_SERIALIZE(space, &p) < 0)
- HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOPY, FAIL, "Unable to serialize selection")
-
- /* Save the serialized buffer for later */
- H5_CHECK_OVERFLOW(buf_size, hssize_t, size_t);
- if(H5HG_insert(loc->oloc->file, (size_t)buf_size, buf, &hobjid) < 0)
- HGOTO_ERROR(H5E_REFERENCE, H5E_WRITEERROR, FAIL, "Unable to serialize selection")
-
- /* Serialize the heap ID and index for storage in the file */
- p = (uint8_t *)ref;
- H5F_addr_encode(loc->oloc->file, &p, hobjid.addr);
- UINT32ENCODE(p, hobjid.idx);
-
- /* Free the buffer we serialized data in */
- H5MM_xfree(buf);
- break;
- } /* end case H5R_DATASET_REGION */
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__create_attr
+ *
+ * Purpose: Creates an attribute reference.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__create_attr(const H5VL_token_t *obj_token, size_t token_size,
+ const char *attr_name, H5R_ref_priv_t *ref)
+{
+ size_t encode_size;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ HDassert(attr_name);
+ HDassert(ref);
+
+ /* Make sure that attribute name is not longer than supported encode size */
+ if(HDstrlen(attr_name) > H5R_MAX_STRING_LEN)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_ARGS, FAIL, "attribute name too long (%d > %d)", (int)HDstrlen(attr_name), H5R_MAX_STRING_LEN)
+
+ /* Create new reference */
+ H5MM_memcpy(ref->ref.obj.token, obj_token, token_size);
+ ref->ref.obj.filename = NULL;
+ if(NULL == (ref->ref.attr.name = HDstrdup(attr_name)))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOPY, FAIL, "Cannot copy attribute name")
+
+ ref->loc_id = H5I_INVALID_HID;
+ ref->type = (uint8_t)H5R_ATTR;
+ ref->token_size = (uint8_t)token_size;
+
+ /* Cache encoding size (assume no external reference) */
+ if(H5R__encode(NULL, ref, NULL, &encode_size, 0) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTENCODE, FAIL, "unable to determine encoding size")
+ ref->encode_size = (uint32_t)encode_size;
+
+ H5R_LOG_DEBUG("Created attribute reference, %d, filename=%s, obj_addr=%s, attr name=%s, encode size=%u",
+ (int)sizeof(H5R_ref_priv_t), ref->ref.obj.filename, H5R__print_token(ref->ref.obj.token),
+ ref->ref.attr.name, ref->encode_size);
+done:
+ if(ret_value < 0)
+ ref->ref.attr.name = H5MM_xfree(ref->ref.attr.name);
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5R__create_attr */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__destroy
+ *
+ * Purpose: Destroy reference.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__destroy(H5R_ref_priv_t *ref)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ HDassert(ref != NULL);
+
+ ref->ref.obj.filename = H5MM_xfree(ref->ref.obj.filename);
+
+ switch(ref->type) {
+ case H5R_OBJECT2:
+ break;
+ case H5R_DATASET_REGION2:
+ if(H5S_close(ref->ref.reg.space) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTFREE, FAIL, "Cannot close dataspace")
+ ref->ref.reg.space = NULL;
+ break;
+ case H5R_ATTR:
+ ref->ref.attr.name = H5MM_xfree(ref->ref.attr.name);
+ break;
+ case H5R_OBJECT1:
+ case H5R_DATASET_REGION1:
case H5R_BADTYPE:
case H5R_MAXTYPE:
+ HDassert("invalid reference type" && 0);
+ HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (invalid reference type)")
default:
HDassert("unknown reference type" && 0);
HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (unknown reference type)")
} /* end switch */
-done:
- if (obj_found)
- H5G_loc_free(&obj_loc);
+ /* Decrement refcount of attached loc_id */
+ if((ref->loc_id != H5I_INVALID_HID) && (H5I_dec_ref(ref->loc_id) < 0))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDEC, FAIL, "decrementing location ID failed")
+done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5R__create() */
+} /* end H5R__destroy() */
-/*--------------------------------------------------------------------------
- NAME
- H5R__dereference
- PURPOSE
- Opens the HDF5 object referenced.
- USAGE
- hid_t H5R__dereference(ref, oapl_id, ref_type, ref)
- H5F_t *file; IN: File the object being dereferenced is within
- hid_t oapl_id; IN: Object access property list ID
- H5R_type_t ref_type; IN: Type of reference
- void *ref; IN: Reference to open.
+/*-------------------------------------------------------------------------
+ * Function: H5R__set_loc_id
+ *
+ * Purpose: Attach location ID to reference and increment location refcount.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__set_loc_id(H5R_ref_priv_t *ref, hid_t id, hbool_t inc_ref)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
- RETURNS
- Valid ID on success, Negative on failure
- DESCRIPTION
- Given a reference to some object, open that object and return an ID for
- that object.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- Currently only set up to work with references to datasets
- EXAMPLES
- REVISION LOG
- Raymond Lu
- 13 July 2011
- I added the OAPL_ID parameter for the object being referenced. It only
- supports dataset access property list currently.
-
- M. Scot Breitenfeld
- 3 March 2015
- Added a check for undefined reference pointer.
---------------------------------------------------------------------------*/
+ FUNC_ENTER_PACKAGE
+
+ HDassert(ref != NULL);
+ HDassert(id != H5I_INVALID_HID);
+
+ /* If a location ID was previously assigned, decrement refcount and assign new one */
+ if((ref->loc_id != H5I_INVALID_HID) && (H5I_dec_ref(ref->loc_id) < 0))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDEC, FAIL, "decrementing location ID failed")
+ ref->loc_id = id;
+
+ /* Prevent location ID from being freed until reference is destroyed */
+ if(inc_ref && H5I_inc_ref(ref->loc_id, FALSE) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTINC, FAIL, "incrementing location ID failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__set_loc_id() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__get_loc_id
+ *
+ * Purpose: Retrieve location ID attached to existing reference.
+ *
+ * Return: Valid ID on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
hid_t
-H5R__dereference(H5F_t *file, hid_t oapl_id, H5R_type_t ref_type, const void *_ref)
+H5R__get_loc_id(const H5R_ref_priv_t *ref)
{
- H5O_loc_t oloc; /* Object location */
- H5G_name_t path; /* Path of object */
- H5G_loc_t loc; /* Group location */
- unsigned rc; /* Reference count of object */
- H5O_type_t obj_type; /* Type of object */
hid_t ret_value = H5I_INVALID_HID; /* Return value */
+ FUNC_ENTER_PACKAGE_NOERR
+
+ HDassert(ref != NULL);
+
+ ret_value = ref->loc_id;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__get_loc_id() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__reopen_file
+ *
+ * Purpose: Re-open referenced file using file access property list.
+ *
+ * Return: Valid ID on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5R__reopen_file(H5R_ref_priv_t *ref, hid_t fapl_id)
+{
+ void *new_file = NULL;
+ H5VL_connector_prop_t connector_prop;
+ unsigned flags = H5F_ACC_RDWR; /* Must open file read-write to allow for object modifications */
+ H5P_genplist_t *plist;
+ hid_t ret_value = H5I_INVALID_HID;
+
FUNC_ENTER_PACKAGE
- HDassert(_ref);
- HDassert(ref_type > H5R_BADTYPE && ref_type < H5R_MAXTYPE);
- HDassert(file);
+ /* TODO add search path */
- /* Initialize the object location */
- H5O_loc_reset(&oloc);
- oloc.file = file;
+ /* Verify access property list and set up collective metadata if appropriate */
+ if(H5CX_set_apl(&fapl_id, H5P_CLS_FACC, H5I_INVALID_HID, TRUE) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
- switch (ref_type) {
- case H5R_OBJECT:
- {
- oloc.addr = *(const hobj_ref_t *)_ref; /* Only object references currently supported */
- if (!H5F_addr_defined(oloc.addr) || oloc.addr == 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "Undefined reference pointer")
- break;
- }
+ /* Get the VOL info from the fapl */
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a file access property list")
+ if(H5P_peek(plist, H5F_ACS_VOL_CONN_NAME, &connector_prop) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5I_INVALID_HID, "can't get VOL connector info")
- case H5R_DATASET_REGION:
- {
- H5HG_t hobjid; /* Heap object ID */
- uint8_t *buf; /* Buffer to store serialized selection in */
- const uint8_t *p; /* Pointer to OID to store */
+ /* Stash a copy of the "top-level" connector property, before any pass-through
+ * connectors modify or unwrap it.
+ */
+ if(H5CX_set_vol_connector_prop(&connector_prop) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set VOL connector info in API context")
- /* 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);
+ /* Open the file */
+ if(NULL == (new_file = H5VL_file_open(&connector_prop, H5R_REF_FILENAME(ref), flags, fapl_id, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, H5I_INVALID_HID, "unable to open file")
- if (!H5F_addr_defined(hobjid.addr) || hobjid.addr == 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "Undefined reference pointer")
+ /* Get an ID for the file */
+ if((ret_value = H5VL_register_using_vol_id(H5I_FILE, new_file, connector_prop.connector_id, TRUE)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize file handle")
- /* Get the dataset region from the heap (allocate inside routine) */
- if(NULL == (buf = (uint8_t *)H5HG_read(oloc.file, &hobjid, NULL, NULL)))
- HGOTO_ERROR(H5E_REFERENCE, H5E_READERROR, H5I_INVALID_HID, "Unable to read dataset region information")
+ /* Attach loc_id to reference */
+ if(H5R__set_loc_id((H5R_ref_priv_t *)ref, ret_value, FALSE) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTSET, H5I_INVALID_HID, "unable to attach location id to reference")
- /* Get the object oid for the dataset */
- p = buf;
- H5F_addr_decode(oloc.file, &p, &(oloc.addr));
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__reopen_file() */
- /* Free the buffer allocated in H5HG_read() */
- H5MM_xfree(buf);
- break;
- } /* end case H5R_DATASET_REGION */
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__get_type
+ *
+ * Purpose: Given a reference to some object, return the type of that reference.
+ *
+ * Return: Type of the reference
+ *
+ *-------------------------------------------------------------------------
+ */
+H5R_type_t
+H5R__get_type(const H5R_ref_priv_t *ref)
+{
+ H5R_type_t ret_value = H5R_BADTYPE;
+
+ FUNC_ENTER_PACKAGE_NOERR
+
+ HDassert(ref != NULL);
+ ret_value = ref->type;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__get_type() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__equal
+ *
+ * Purpose: Compare two references
+ *
+ * Return: TRUE if equal, FALSE if unequal, FAIL if error
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5R__equal(const H5R_ref_priv_t *ref1, const H5R_ref_priv_t *ref2)
+{
+ htri_t ret_value = TRUE;
+
+ FUNC_ENTER_PACKAGE
+ HDassert(ref1 != NULL);
+ HDassert(ref2 != NULL);
+
+ /* Compare reference types */
+ if(ref1->type != ref2->type)
+ HGOTO_DONE(FALSE);
+
+ /* Compare object addresses */
+ if(ref1->token_size != ref2->token_size)
+ HGOTO_DONE(FALSE);
+ if(0 != HDmemcmp(ref1->ref.obj.token, ref2->ref.obj.token, ref1->token_size))
+ HGOTO_DONE(FALSE);
+
+ /* Compare filenames */
+ if((ref1->ref.obj.filename && (NULL == ref2->ref.obj.filename))
+ || ((NULL == ref1->ref.obj.filename) && ref2->ref.obj.filename))
+ HGOTO_DONE(FALSE);
+ if(ref1->ref.obj.filename && ref1->ref.obj.filename
+ && (0 != HDstrcmp(ref1->ref.obj.filename, ref2->ref.obj.filename)))
+ HGOTO_DONE(FALSE);
+
+ switch(ref1->type) {
+ case H5R_OBJECT2:
+ break;
+ case H5R_DATASET_REGION2:
+ if((ret_value = H5S_extent_equal(ref1->ref.reg.space, ref2->ref.reg.space)) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOMPARE, FAIL, "cannot compare dataspace extents")
+ break;
+ case H5R_ATTR:
+ HDassert(ref1->ref.attr.name && ref2->ref.attr.name);
+ if(0 != HDstrcmp(ref1->ref.attr.name, ref2->ref.attr.name))
+ HGOTO_DONE(FALSE);
+ break;
+ case H5R_OBJECT1:
+ case H5R_DATASET_REGION1:
case H5R_BADTYPE:
case H5R_MAXTYPE:
+ HDassert("invalid reference type" && 0);
+ HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (invalid reference type)")
default:
HDassert("unknown reference type" && 0);
- HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, H5I_INVALID_HID, "internal error (unknown reference type)")
+ HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (unknown reference type)")
} /* end switch */
- /* Get the # of links for object, and its type
- * (To check to make certain that this object hasn't been deleted
- * since the reference was created)
- */
- if(H5O_get_rc_and_type(&oloc, &rc, &obj_type) < 0 || 0 == rc)
- HGOTO_ERROR(H5E_REFERENCE, H5E_LINKCOUNT, H5I_INVALID_HID, "dereferencing deleted object")
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__equal() */
- /* Construct a group location for opening the object */
- H5G_name_reset(&path);
- loc.oloc = &oloc;
- loc.path = &path;
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__copy
+ *
+ * Purpose: Copy a reference
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__copy(const H5R_ref_priv_t *src_ref, H5R_ref_priv_t *dst_ref)
+{
+ herr_t ret_value = SUCCEED;
- /* Open the object */
- switch (obj_type) {
- case H5O_TYPE_GROUP:
- {
- H5G_t *group; /* Pointer to group to open */
+ FUNC_ENTER_PACKAGE
- if(NULL == (group = H5G_open(&loc)))
- HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5I_INVALID_HID, "not found")
+ HDassert((src_ref != NULL) && (dst_ref != NULL));
- /* Create an atom for the group */
- if((ret_value = H5I_register(H5I_GROUP, group, TRUE)) < 0) {
- H5G_close(group);
- HGOTO_ERROR(H5E_SYM, H5E_CANTREGISTER, H5I_INVALID_HID, "can't register group")
- }
+ H5MM_memcpy(dst_ref->ref.obj.token, src_ref->ref.obj.token, src_ref->token_size);
+ dst_ref->encode_size = src_ref->encode_size;
+ dst_ref->type = src_ref->type;
+ dst_ref->token_size = src_ref->token_size;
+ switch(src_ref->type) {
+ case H5R_OBJECT2:
break;
- }
-
- case H5O_TYPE_NAMED_DATATYPE:
- {
- H5T_t *type; /* Pointer to datatype to open */
-
- if(NULL == (type = H5T_open(&loc)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, H5I_INVALID_HID, "not found")
+ case H5R_DATASET_REGION2:
+ if(NULL == (dst_ref->ref.reg.space = H5S_copy(src_ref->ref.reg.space, FALSE, TRUE)))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOPY, FAIL, "unable to copy dataspace")
+ break;
+ case H5R_ATTR:
+ if(NULL == (dst_ref->ref.attr.name = HDstrdup(src_ref->ref.attr.name)))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOPY, FAIL, "Cannot copy attribute name")
+ break;
+ case H5R_OBJECT1:
+ case H5R_DATASET_REGION1:
+ HDassert("invalid reference type" && 0);
+ HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (invalid reference type)")
+ case H5R_BADTYPE:
+ case H5R_MAXTYPE:
+ default:
+ HDassert("unknown reference type" && 0);
+ HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (unknown reference type)")
+ } /* end switch */
- /* Create an atom for the datatype */
- if((ret_value = H5I_register(H5I_DATATYPE, type, TRUE)) < 0) {
- H5T_close(type);
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, H5I_INVALID_HID, "can't register datatype")
- }
+ /* We only need to keep a copy of the filename if we don't have the loc_id */
+ if(src_ref->loc_id == H5I_INVALID_HID) {
+ HDassert(src_ref->ref.obj.filename);
- break;
- }
+ if(NULL == (dst_ref->ref.obj.filename = HDstrdup(src_ref->ref.obj.filename)))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOPY, FAIL, "Cannot copy filename")
+ dst_ref->loc_id = H5I_INVALID_HID;
+ } else {
+ dst_ref->ref.obj.filename = NULL;
- case H5O_TYPE_DATASET:
- {
- H5D_t *dset; /* Pointer to dataset to open */
+ /* Set location ID and hold reference to it */
+ if(H5R__set_loc_id(dst_ref, src_ref->loc_id, TRUE) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTSET, FAIL, "cannot set reference location ID")
+ }
- /* Open the dataset */
- if(NULL == (dset = H5D_open(&loc, oapl_id)))
- HGOTO_ERROR(H5E_DATASET, H5E_NOTFOUND, H5I_INVALID_HID, "not found")
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__copy() */
- /* Create an atom for the dataset */
- if((ret_value = H5I_register(H5I_DATASET, dset, TRUE)) < 0) {
- H5D_close(dset);
- HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, H5I_INVALID_HID, "can't register dataset")
- }
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__get_obj_token
+ *
+ * Purpose: Given a reference to some object, get the encoded object addr.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__get_obj_token(const H5R_ref_priv_t *ref, H5VL_token_t *obj_token,
+ size_t *token_size)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
- break;
- }
+ FUNC_ENTER_PACKAGE
- case H5O_TYPE_MAP:
- HGOTO_ERROR(H5E_REFERENCE, H5E_BADTYPE, H5I_INVALID_HID, "maps not supported in native VOL connector")
+ HDassert(ref != NULL);
+ HDassert(ref->token_size <= H5VL_MAX_TOKEN_SIZE);
- case H5O_TYPE_UNKNOWN:
- case H5O_TYPE_NTYPES:
- default:
- HGOTO_ERROR(H5E_REFERENCE, H5E_BADTYPE, H5I_INVALID_HID, "can't identify type of object referenced")
- } /* end switch */
+ if(obj_token) {
+ if(0 == ref->token_size)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOPY, FAIL, "NULL token size")
+ H5MM_memcpy(obj_token, ref->ref.obj.token, ref->token_size);
+ }
+ if(token_size)
+ *token_size = ref->token_size;
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5R__dereference() */
+} /* end H5R__get_obj_token() */
-/*--------------------------------------------------------------------------
- NAME
- H5R__get_region
- PURPOSE
- Retrieves a dataspace with the region pointed to selected.
- USAGE
- H5S_t *H5R__get_region(file, ref)
- H5F_t *file; IN: File the object being dereferenced is within
- void *ref; IN: Reference to open.
+/*-------------------------------------------------------------------------
+ * Function: H5R__set_obj_token
+ *
+ * Purpose: Given a reference to some object, set the encoded object addr.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__set_obj_token(H5R_ref_priv_t *ref, const H5VL_token_t *obj_token,
+ size_t token_size)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
- RETURNS
- Pointer to the dataspace on success, NULL on failure
- DESCRIPTION
- Given a reference to some object, creates a copy of the dataset pointed
- to's dataspace and defines a selection in the copy which is the region
- pointed to.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-H5S_t *
-H5R__get_region(H5F_t *file, const void *_ref)
+ FUNC_ENTER_PACKAGE_NOERR
+
+ HDassert(ref != NULL);
+ HDassert(obj_token);
+ HDassert(token_size);
+ HDassert(token_size <= H5VL_MAX_TOKEN_SIZE);
+
+ H5MM_memcpy(ref->ref.obj.token, obj_token, ref->token_size);
+ ref->token_size = token_size;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__set_obj_token() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__get_region
+ *
+ * Purpose: Given a reference to some object, creates a copy of the dataset
+ * pointed to's dataspace and defines a selection in the copy which is the
+ * region pointed to.
+ *
+ * Return: Pointer to the dataspace on success/NULL on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__get_region(const H5R_ref_priv_t *ref, H5S_t *space)
{
- H5O_loc_t oloc; /* Object location */
- const uint8_t *p; /* Pointer to OID to store */
- H5HG_t hobjid; /* Heap object ID */
- uint8_t *buf = NULL; /* Buffer to store serialized selection in */
- H5S_t *ret_value; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
- HDassert(_ref);
- HDassert(file);
+ HDassert(ref != NULL);
+ HDassert(ref->type == H5R_DATASET_REGION2);
+ HDassert(space);
- /* Initialize the object location */
- H5O_loc_reset(&oloc);
- oloc.file = file;
+ /* Copy reference selection to destination */
+ if(H5S_select_copy(space, ref->ref.reg.space, FALSE) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOPY, FAIL, "unable to copy selection")
- /* 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);
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__get_region() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__get_file_name
+ *
+ * Purpose: Given a reference to some object, determine a file name of the
+ * object located into.
+ *
+ * Return: Non-negative length of the path on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+ssize_t
+H5R__get_file_name(const H5R_ref_priv_t *ref, char *buf, size_t size)
+{
+ size_t copy_len;
+ ssize_t ret_value = -1; /* Return value */
- /* Get the dataset region from the heap (allocate inside routine) */
- if(NULL == (buf = (uint8_t *)H5HG_read(oloc.file, &hobjid, NULL, NULL)))
- HGOTO_ERROR(H5E_REFERENCE, H5E_READERROR, NULL, "Unable to read dataset region information")
+ FUNC_ENTER_PACKAGE
- /* Get the object oid for the dataset */
- p = buf;
- H5F_addr_decode(oloc.file, &p, &(oloc.addr));
+ /* Check args */
+ HDassert(ref != NULL);
- /* Open and copy the dataset's dataspace */
- if(NULL == (ret_value = H5S_read(&oloc)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_NOTFOUND, NULL, "not found")
+ /* Return if that reference has no filename set */
+ if(!ref->ref.obj.filename)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_ARGS, (-1), "no filename available for that reference")
- /* Unserialize the selection */
- if(H5S_SELECT_DESERIALIZE(&ret_value, &p) < 0)
- HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, NULL, "can't deserialize selection")
+ /* Get the file name length */
+ copy_len = HDstrlen(ref->ref.obj.filename);
+ HDassert(copy_len <= H5R_MAX_STRING_LEN);
-done:
- /* Free the buffer allocated in H5HG_read() */
- if(buf)
- H5MM_xfree(buf);
+ /* Copy the file name */
+ if(buf) {
+ copy_len = MIN(copy_len, size - 1);
+ H5MM_memcpy(buf, ref->ref.obj.filename, copy_len);
+ buf[copy_len] = '\0';
+ }
+ ret_value = (ssize_t)(copy_len + 1);
+done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5R__get_region() */
+} /* end H5R__get_file_name() */
-/*--------------------------------------------------------------------------
- NAME
- H5R__get_obj_type
- PURPOSE
- Retrieves the type of object that an object reference points to
- USAGE
- H5O_type_t H5R__get_obj_type(file, ref_type, ref)
- H5F_t *file; IN: File the object being dereferenced is within
- H5R_type_t ref_type; IN: Type of reference to query
- void *ref; IN: Reference to query.
- H5O_type_t *obj_type; OUT: The type of the object, set on success
+/*-------------------------------------------------------------------------
+ * Function: H5R__get_attr_name
+ *
+ * Purpose: Given a reference to some attribute, determine its name.
+ *
+ * Return: Non-negative length of the path on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+ssize_t
+H5R__get_attr_name(const H5R_ref_priv_t *ref, char *buf, size_t size)
+{
+ ssize_t ret_value = -1; /* Return value */
+ size_t attr_name_len; /* Length of the attribute name */
- RETURNS
- Non-negative on success/Negative on failure
- DESCRIPTION
- Given a reference to some object, this function returns the type of object
- pointed to.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
+ FUNC_ENTER_PACKAGE_NOERR
+
+ /* Check args */
+ HDassert(ref != NULL);
+ HDassert(ref->type == H5R_ATTR);
+
+ /* Get the attribute name length */
+ attr_name_len = HDstrlen(ref->ref.attr.name);
+ HDassert(attr_name_len <= H5R_MAX_STRING_LEN);
+
+ /* Get the attribute name */
+ if(buf) {
+ size_t copy_len = MIN(attr_name_len, size - 1);
+ H5MM_memcpy(buf, ref->ref.attr.name, copy_len);
+ buf[copy_len] = '\0';
+ }
+
+ ret_value = (ssize_t)(attr_name_len + 1);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__get_attr_name() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__encode
+ *
+ * Purpose: Private function for H5Rencode.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
herr_t
-H5R__get_obj_type(H5F_t *file, H5R_type_t ref_type, const void *_ref,
- H5O_type_t *obj_type)
+H5R__encode(const char *filename, const H5R_ref_priv_t *ref, unsigned char *buf,
+ size_t *nalloc, unsigned flags)
{
- H5O_loc_t oloc; /* Object location */
- unsigned rc; /* Reference count of object */
- herr_t ret_value = SUCCEED; /* Return value */
+ uint8_t *p = (uint8_t *)buf;
+ size_t buf_size = 0, encode_size = 0;
+ herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
- HDassert(file);
- HDassert(_ref);
+ HDassert(ref);
+ HDassert(nalloc);
+
+ /**
+ * Encoding format:
+ * | Reference type (8 bits) | Flags (8 bits) | Token (token size)
+ * | |
+ * | |----> H5R_IS_EXTERNAL: File info
+ * |
+ * |----> H5R_DATASET_REGION2: Serialized selection
+ * |
+ * |----> H5R_ATTR: Attribute name len + name
+ *
+ */
+
+ /* Don't encode if buffer size isn't big enough or buffer is empty */
+ if(buf && *nalloc >= H5R_ENCODE_HEADER_SIZE) {
+ /* Encode the type of the reference */
+ *p++ = (uint8_t)ref->type;
+
+ /* Encode the flags */
+ *p++ = (uint8_t)flags;
- /* Initialize the symbol table entry */
- H5O_loc_reset(&oloc);
- oloc.file = file;
+ buf_size = *nalloc - H5R_ENCODE_HEADER_SIZE;
+ }
+ encode_size += H5R_ENCODE_HEADER_SIZE;
+
+ /* Encode object token */
+ H5R_ENCODE_VAR(H5R__encode_obj_token, &ref->ref.obj.token, ref->token_size,
+ p, buf_size, encode_size, "Cannot encode object address");
+
+ /**
+ * TODO Encode VOL info
+ * When we have a better way of storing blobs, we should add
+ * support for referencing files in external VOLs.
+ * There are currently multiple limitations:
+ * - avoid duplicating VOL info on each reference
+ * - must query terminal VOL connector to avoid passthrough confusion
+ */
+ if(flags & H5R_IS_EXTERNAL) {
+ /* Encode file name */
+ H5R_ENCODE(H5R__encode_string, filename, p, buf_size, encode_size,
+ "Cannot encode filename");
+ }
- switch (ref_type) {
- case H5R_OBJECT:
- {
- /* Get the object oid */
- oloc.addr = *(const hobj_ref_t *)_ref; /* Only object references currently supported */
+ switch(ref->type) {
+ case H5R_OBJECT2:
break;
- }
+ case H5R_DATASET_REGION2:
+ /* Encode dataspace */
+ H5R_ENCODE(H5R__encode_region, ref->ref.reg.space, p, buf_size,
+ encode_size, "Cannot encode region");
+ break;
+ case H5R_ATTR:
+ /* Encode attribute name */
+ H5R_ENCODE(H5R__encode_string, ref->ref.attr.name, p, buf_size,
+ encode_size, "Cannot encode attribute name");
+ break;
+ case H5R_OBJECT1:
+ case H5R_DATASET_REGION1:
+ case H5R_BADTYPE:
+ case H5R_MAXTYPE:
+ HDassert("invalid reference type" && 0);
+ HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (invalid reference type)")
+ default:
+ HDassert("unknown reference type" && 0);
+ HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (unknown reference type)")
+ } /* end switch */
+
+ *nalloc = encode_size;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__encode() */
- case H5R_DATASET_REGION:
- {
- H5HG_t hobjid; /* Heap object ID */
- const uint8_t *p; /* Pointer to reference to decode */
- uint8_t *buf; /* Buffer to store serialized selection in */
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__decode
+ *
+ * Purpose: Private function for H5Rdecode.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__decode(const unsigned char *buf, size_t *nbytes, H5R_ref_priv_t *ref)
+{
+ const uint8_t *p = (const uint8_t *)buf;
+ size_t buf_size = 0, decode_size = 0;
+ uint8_t flags;
+ herr_t ret_value = SUCCEED;
- /* 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);
+ FUNC_ENTER_PACKAGE
- /* Get the dataset region from the heap (allocate inside routine) */
- if(NULL == (buf = (uint8_t *)H5HG_read(oloc.file, &hobjid, NULL, NULL)))
- HGOTO_ERROR(H5E_REFERENCE, H5E_READERROR, FAIL, "Unable to read dataset region information")
+ HDassert(buf);
+ HDassert(nbytes);
+ HDassert(ref);
+ buf_size = *nbytes;
- /* Get the object oid for the dataset */
- p = buf;
- H5F_addr_decode(oloc.file, &p, &(oloc.addr));
+ /* Don't decode if buffer size isn't big enough */
+ if(buf_size < H5R_ENCODE_HEADER_SIZE)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "Buffer size is too small")
- /* Free the buffer allocated in H5HG_read() */
- H5MM_xfree(buf);
+ /* Set new reference */
+ ref->type = (H5R_type_t)*p++;
+ if(ref->type <= H5R_BADTYPE || ref->type >= H5R_MAXTYPE)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference type")
- break;
- }
+ /* Set flags */
+ flags = *p++;
+
+ buf_size -= H5R_ENCODE_HEADER_SIZE;
+ decode_size += H5R_ENCODE_HEADER_SIZE;
+ /* Decode object token */
+ H5R_DECODE_VAR(H5R__decode_obj_token, &ref->ref.obj.token, &ref->token_size,
+ p, buf_size, decode_size, "Cannot decode object address");
+
+ /* We do not need to store the filename if the reference is internal */
+ if(flags & H5R_IS_EXTERNAL) {
+ /* Decode file name */
+ H5R_DECODE(H5R__decode_string, &ref->ref.obj.filename, p, buf_size,
+ decode_size, "Cannot decode filename");
+ } else
+ ref->ref.obj.filename = NULL;
+
+ switch(ref->type) {
+ case H5R_OBJECT2:
+ break;
+ case H5R_DATASET_REGION2:
+ /* Decode dataspace */
+ H5R_DECODE(H5R__decode_region, &ref->ref.reg.space, p, buf_size,
+ decode_size, "Cannot decode region");
+ break;
+ case H5R_ATTR:
+ /* Decode attribute name */
+ H5R_DECODE(H5R__decode_string, &ref->ref.attr.name, p, buf_size,
+ decode_size, "Cannot decode attribute name");
+ break;
+ case H5R_OBJECT1:
+ case H5R_DATASET_REGION1:
case H5R_BADTYPE:
case H5R_MAXTYPE:
+ HDassert("invalid reference type" && 0);
+ HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (invalid reference type)")
default:
HDassert("unknown reference type" && 0);
HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (unknown reference type)")
} /* end switch */
- /* Get the # of links for object, and its type */
- /* (To check to make certain that this object hasn't been deleted since the reference was created) */
- if(H5O_get_rc_and_type(&oloc, &rc, obj_type) < 0 || 0 == rc)
- HGOTO_ERROR(H5E_REFERENCE, H5E_LINKCOUNT, FAIL, "dereferencing deleted object")
+ /* Set loc ID to invalid */
+ ref->loc_id = H5I_INVALID_HID;
+
+ /* Set encoding size */
+ ref->encode_size = decode_size;
+
+ H5R_LOG_DEBUG("Decoded reference, filename=%s, obj_addr=%s, encode size=%u",
+ ref->ref.obj.filename, H5R__print_token(ref->ref.obj.token),
+ ref->encode_size);
+
+ *nbytes = decode_size;
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5R__get_obj_type() */
+} /* end H5R__decode() */
-/*--------------------------------------------------------------------------
- NAME
- H5R__get_name
- PURPOSE
- Internal routine to determine a name for the object referenced
- USAGE
- ssize_t H5R__get_name(f, ref_type, ref, name, size)
- H5F_t *f; IN: Pointer to the file that the reference is pointing
- into
- hid_t lapl_id; IN: LAPL to use for operation
- hid_t id; IN: Location ID given for reference
- H5R_type_t ref_type; IN: Type of reference
- void *_ref; IN: Reference to query.
- char *name; OUT: Buffer to place name of object referenced
- size_t size; IN: Size of name buffer
+/*-------------------------------------------------------------------------
+ * Function: H5R__encode_obj_token
+ *
+ * Purpose: Encode an object address.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5R__encode_obj_token(const H5VL_token_t *obj_token, size_t token_size,
+ unsigned char *buf, size_t *nalloc)
+{
+ herr_t ret_value = SUCCEED;
- RETURNS
- Non-negative length of the path on success, -1 on failure
- DESCRIPTION
- Given a reference to some object, determine a path to the object
- referenced in the file.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- This may not be the only path to that object.
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-ssize_t
-H5R__get_name(H5F_t *f, H5R_type_t ref_type, const void *_ref,
- char *name, size_t size)
+ FUNC_ENTER_STATIC_NOERR
+
+ HDassert(nalloc);
+
+ /* Don't encode if buffer size isn't big enough or buffer is empty */
+ if(buf && *nalloc >= token_size) {
+ uint8_t *p = (uint8_t *)buf;
+
+ /* Encode token size */
+ *p++ = (uint8_t)(token_size & 0xff);
+
+ /* Encode token */
+ H5MM_memcpy(p, obj_token, token_size);
+ }
+ *nalloc = token_size + H5_SIZEOF_UINT8_T;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__encode_obj_token() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__decode_obj_token
+ *
+ * Purpose: Decode an object address.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5R__decode_obj_token(const unsigned char *buf, size_t *nbytes,
+ H5VL_token_t *obj_token, uint8_t *token_size)
{
- H5O_loc_t oloc; /* Object location describing object for reference */
- ssize_t ret_value = -1; /* Return value */
+ const uint8_t *p = (const uint8_t *)buf;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ HDassert(buf);
+ HDassert(nbytes);
+ HDassert(obj_token);
+ HDassert(token_size);
+
+ /* Don't decode if buffer size isn't big enough */
+ if(*nbytes < H5_SIZEOF_UINT8_T)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "Buffer size is too small")
+
+ /* Get token size */
+ *token_size = *p++;
+ if(*token_size > sizeof(H5VL_token_t))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "Invalid token size (%u)", *token_size)
+
+ /* Decode token */
+ H5MM_memcpy(obj_token, p, *token_size);
+
+ *nbytes = *token_size + H5_SIZEOF_UINT8_T;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__decode_obj_token() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__encode_region
+ *
+ * Purpose: Encode a selection.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5R__encode_region(H5S_t *space, unsigned char *buf, size_t *nalloc)
+{
+ uint8_t *p = NULL; /* Pointer to data to store */
+ hssize_t buf_size = 0;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ HDassert(space);
+ HDassert(nalloc);
+
+ /* Get the amount of space required to serialize the selection */
+ if((buf_size = H5S_SELECT_SERIAL_SIZE(space)) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTENCODE, FAIL, "Cannot determine amount of space needed for serializing selection")
+
+ /* Don't encode if buffer size isn't big enough or buffer is empty */
+ if(buf && *nalloc >= ((size_t)buf_size + 2 * H5_SIZEOF_UINT32_T)) {
+ p = (uint8_t *)buf;
+ int rank;
+
+ /* Encode the size for safety check */
+ UINT32ENCODE(p, (uint32_t)buf_size);
+
+ /* Encode the extent rank */
+ if((rank = H5S_get_simple_extent_ndims(space)) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't get extent rank for selection")
+ UINT32ENCODE(p, (uint32_t)rank);
+
+ /* Serialize the selection */
+ if(H5S_SELECT_SERIALIZE(space, (unsigned char **)&p) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTENCODE, FAIL, "can't serialize selection")
+ }
+ *nalloc = (size_t)buf_size + 2 * H5_SIZEOF_UINT32_T;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__encode_region() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__decode_region
+ *
+ * Purpose: Decode a selection.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5R__decode_region(const unsigned char *buf, size_t *nbytes, H5S_t **space_ptr)
+{
+ const uint8_t *p = (const uint8_t *)buf;
+ size_t buf_size = 0;
+ unsigned rank;
+ H5S_t *space;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ HDassert(buf);
+ HDassert(nbytes);
+ HDassert(space_ptr);
+
+ /* Don't decode if buffer size isn't big enough */
+ if(*nbytes < (2 * H5_SIZEOF_UINT32_T))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "Buffer size is too small")
+
+ /* Decode the selection size */
+ UINT32DECODE(p, buf_size);
+ buf_size += H5_SIZEOF_UINT32_T;
+
+ /* Decode the extent rank */
+ UINT32DECODE(p, rank);
+ buf_size += H5_SIZEOF_UINT32_T;
+
+ /* Don't decode if buffer size isn't big enough */
+ if(*nbytes < buf_size)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "Buffer size is too small")
+
+ /* Deserialize the selection (dataspaces need the extent rank information) */
+ if(NULL == (space = H5S_create(H5S_SIMPLE)))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "Buffer size is too small")
+ if(H5S_set_extent_simple(space, rank, NULL, NULL) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTSET, FAIL, "can't set extent rank for selection")
+ if(H5S_SELECT_DESERIALIZE(&space, &p) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "can't deserialize selection")
+
+ *nbytes = buf_size;
+ *space_ptr = space;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__decode_region() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__encode_string
+ *
+ * Purpose: Encode a string.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5R__encode_string(const char *string, unsigned char *buf, size_t *nalloc)
+{
+ size_t string_len, buf_size;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ HDassert(string);
+ HDassert(nalloc);
+
+ /* Get the amount of space required to serialize the string */
+ string_len = HDstrlen(string);
+ if(string_len > H5R_MAX_STRING_LEN)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_ARGS, FAIL, "string too long")
+
+ /* Compute buffer size, allow for the attribute name length and object address */
+ buf_size = string_len + sizeof(uint16_t);
+
+ if(buf && *nalloc >= buf_size) {
+ uint8_t *p = (uint8_t *)buf;
+ /* Serialize information for string length into the buffer */
+ UINT16ENCODE(p, string_len);
+ /* Copy the string into the buffer */
+ H5MM_memcpy(p, string, string_len);
+ }
+ *nalloc = buf_size;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__encode_string() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__decode_string
+ *
+ * Purpose: Decode a string.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5R__decode_string(const unsigned char *buf, size_t *nbytes, char **string_ptr)
+{
+ const uint8_t *p = (const uint8_t *)buf;
+ size_t string_len;
+ char *string = NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ HDassert(buf);
+ HDassert(nbytes);
+ HDassert(string_ptr);
+
+ /* Don't decode if buffer size isn't big enough */
+ if(*nbytes < sizeof(uint16_t))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "Buffer size is too small")
+
+ /* Get the string length */
+ UINT16DECODE(p, string_len);
+ HDassert(string_len <= H5R_MAX_STRING_LEN);
+
+ /* Allocate the string */
+ if(NULL == (string = H5MM_malloc(string_len + 1)))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTALLOC, FAIL, "Cannot allocate string")
+
+ /* Copy the string */
+ H5MM_memcpy(string, p, string_len);
+ string[string_len] = '\0';
+
+ *string_ptr = string;
+ *nbytes = sizeof(uint16_t) + string_len;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__decode_string() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__encode_heap
+ *
+ * Purpose: Encode data and insert into heap (native only).
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__encode_heap(H5F_t *f, unsigned char *buf, size_t *nalloc,
+ const unsigned char *data, size_t data_size)
+{
+ size_t buf_size;
+ herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
- /* Check args */
HDassert(f);
- HDassert(_ref);
+ HDassert(nalloc);
- /* Initialize the object location */
- H5O_loc_reset(&oloc);
- oloc.file = f;
+ buf_size = H5HG_HEAP_ID_SIZE(f);
+ if(buf && *nalloc >= buf_size) {
+ H5HG_t hobjid;
+ uint8_t *p = (uint8_t *)buf;
- /* Get address for reference */
- switch (ref_type) {
- case H5R_OBJECT:
- {
- oloc.addr = *(const hobj_ref_t *)_ref;
- break;
- }
+ /* Write the reference information to disk (allocates space also) */
+ if(H5HG_insert(f, data_size, (void *)data, &hobjid) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "Unable to write reference information")
- case H5R_DATASET_REGION:
- {
- H5HG_t hobjid; /* Heap object ID */
- uint8_t *buf; /* Buffer to store serialized selection in */
- const uint8_t *p; /* Pointer to OID to store */
+ /* Encode the heap information */
+ H5F_addr_encode(f, &p, hobjid.addr);
+ UINT32ENCODE(p, hobjid.idx);
+ }
+ *nalloc = buf_size;
- /* 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);
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__encode_heap() */
- /* Get the dataset region from the heap (allocate inside routine) */
- if((buf = (uint8_t *)H5HG_read(oloc.file, &hobjid, NULL, NULL)) == NULL)
- HGOTO_ERROR(H5E_REFERENCE, H5E_READERROR, (-1), "Unable to read dataset region information")
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__decode_heap
+ *
+ * Purpose: Decode data inserted into heap (native only).
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__decode_heap(H5F_t *f, const unsigned char *buf, size_t *nbytes,
+ unsigned char **data_ptr, size_t *data_size)
+{
+ const uint8_t *p = (const uint8_t *)buf;
+ H5HG_t hobjid;
+ size_t buf_size;
+ herr_t ret_value = SUCCEED;
- /* Get the object oid for the dataset */
- p = buf;
- H5F_addr_decode(oloc.file, &p, &(oloc.addr));
+ FUNC_ENTER_PACKAGE
- /* Free the buffer allocated in H5HG_read() */
- H5MM_xfree(buf);
+ HDassert(f);
+ HDassert(buf);
+ HDassert(nbytes);
+ HDassert(data_ptr);
+
+ buf_size = H5HG_HEAP_ID_SIZE(f);
+ /* Don't decode if buffer size isn't big enough */
+ if(*nbytes < buf_size)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "Buffer size is too small")
+
+ /* Get the heap information */
+ H5F_addr_decode(f, &p, &(hobjid.addr));
+ if(!H5F_addr_defined(hobjid.addr) || hobjid.addr == 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Undefined reference pointer")
+ UINT32DECODE(p, hobjid.idx);
- break;
- }
+ /* Read the information from disk */
+ if(NULL == (*data_ptr = (unsigned char *)H5HG_read(f, &hobjid, (void *)*data_ptr, data_size)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_READERROR, FAIL, "Unable to read reference data")
- case H5R_BADTYPE:
- case H5R_MAXTYPE:
- default:
- HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, (-1), "internal error (unknown reference type)")
- } /* end switch */
+ *nbytes = buf_size;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__decode_heap() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__free_heap
+ *
+ * Purpose: Remove data previously inserted into heap (native only).
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__free_heap(H5F_t *f, const unsigned char *buf, size_t nbytes)
+{
+ H5HG_t hobjid;
+ const uint8_t *p = (const uint8_t *)buf;
+ size_t buf_size;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE
+
+ HDassert(f);
+ HDassert(buf);
+
+ buf_size = H5HG_HEAP_ID_SIZE(f);
+ /* Don't decode if buffer size isn't big enough */
+ if(nbytes < buf_size)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "Buffer size is too small")
+
+ /* Get the heap information */
+ H5F_addr_decode(f, &p, &(hobjid.addr));
+ if(!H5F_addr_defined(hobjid.addr) || hobjid.addr == 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Undefined reference pointer")
+ UINT32DECODE(p, hobjid.idx);
+
+ /* Free heap object */
+ if(hobjid.addr > 0) {
+ /* Free heap object */
+ if(H5HG_remove(f, &hobjid) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "Unable to remove heap object")
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__free_heap() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__decode_addr_compat
+ *
+ * Purpose: Decode an object address. (native only)
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__decode_addr_compat(hid_t id, H5I_type_t type, H5R_type_t ref_type,
+ const unsigned char *buf, haddr_t *addr_ptr)
+{
+ hid_t file_id = H5I_INVALID_HID; /* File ID for region reference */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE
+
+ if(ref_type == H5R_OBJECT1) {
+ size_t buf_size = H5R_OBJ_REF_BUF_SIZE;
+
+ /* Get object address */
+ if(H5R__decode_addr_obj_compat(buf, &buf_size, addr_ptr) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "unable to get object address")
+ } else {
+ void *vol_obj_file = NULL;
+ H5F_t *f = NULL;
+ size_t buf_size = H5R_DSET_REG_REF_BUF_SIZE;
+
+ /* Get the file for the object */
+ if((file_id = H5F_get_file_id(id, type, FALSE)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
+
+ /* Retrieve VOL object */
+ if(NULL == (vol_obj_file = H5VL_vol_object(file_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Retrieve file from VOL object */
+ if(NULL == (f = (H5F_t *)H5VL_object_data(vol_obj_file)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid VOL object")
+
+ /* Get object address */
+ if(H5R__decode_addr_region_compat(f, buf, &buf_size, addr_ptr, NULL) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "unable to get object address")
+ }
+
+done:
+ if(file_id != H5I_INVALID_HID && H5I_dec_ref(file_id) < 0)
+ HDONE_ERROR(H5E_REFERENCE, H5E_CANTDEC, FAIL, "unable to decrement refcount on file")
+ FUNC_LEAVE_NOAPI(ret_value)
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__encode_addr_obj_compat
+ *
+ * Purpose: Encode an object address. (native only)
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__encode_addr_obj_compat(haddr_t addr, unsigned char *buf, size_t *nalloc)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE_NOERR
+
+ HDassert(nalloc);
+
+ /* Don't encode if buffer size isn't big enough or buffer is empty */
+ if(buf && *nalloc >= sizeof(addr))
+ H5MM_memcpy(buf, &addr, sizeof(addr));
+ *nalloc = sizeof(addr);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__encode_addr_obj_compat() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__decode_addr_obj_compat
+ *
+ * Purpose: Decode an object address. (native only)
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__decode_addr_obj_compat(const unsigned char *buf, size_t *nbytes,
+ haddr_t *addr_ptr)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE
+
+ HDassert(buf);
+ HDassert(nbytes);
+ HDassert(addr_ptr);
+
+ /* Don't decode if buffer size isn't big enough */
+ if(*nbytes < sizeof(*addr_ptr))
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "Buffer size is too small")
- /* Get name, length, etc. */
- if((ret_value = H5G_get_name_by_addr(f, &oloc, name, size)) < 0)
- HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, (-1), "can't determine name")
+ H5MM_memcpy(addr_ptr, buf, sizeof(*addr_ptr));
+
+ *nbytes = sizeof(*addr_ptr);
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5R__get_name() */
+} /* H5R__decode_addr_obj_compat() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__encode_addr_region_compat
+ *
+ * Purpose: Encode dataset selection and insert data into heap (native only).
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__encode_addr_region_compat(H5F_t *f, haddr_t obj_addr, H5S_t *space,
+ unsigned char *buf, size_t *nalloc)
+{
+ size_t buf_size;
+ unsigned char *data = NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE
+
+ HDassert(f);
+ HDassert(space);
+ HDassert(nalloc);
+
+ /* Get required buffer size */
+ if(H5R__encode_heap(f, NULL, &buf_size, NULL, (size_t)0) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ if(buf && *nalloc >= buf_size) {
+ ssize_t data_size;
+ uint8_t *p;
+
+ /* Pass the correct encoding version for the selection depending on the
+ * file libver bounds, this is later retrieved in H5S hyper encode */
+ H5CX_set_libver_bounds(f);
+
+ /* Zero the heap ID out, may leak heap space if user is re-using
+ * reference and doesn't have garbage collection turned on
+ */
+ HDmemset(buf, 0, buf_size);
+
+ /* Get the amount of space required to serialize the selection */
+ if((data_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 */
+ data_size += (hssize_t)sizeof(haddr_t);
+
+ /* Allocate the space to store the serialized information */
+ H5_CHECK_OVERFLOW(data_size, hssize_t, size_t);
+ if(NULL == (data = (uint8_t *)H5MM_malloc((size_t)data_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Serialize information for dataset OID into heap buffer */
+ p = (uint8_t *)data;
+ H5F_addr_encode(f, &p, obj_addr);
+
+ /* Serialize the selection into heap buffer */
+ if(H5S_SELECT_SERIALIZE(space, &p) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOPY, FAIL, "Unable to serialize selection")
+
+ /* Write to heap */
+ if(H5R__encode_heap(f, buf, nalloc, data, (size_t)data_size) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+ }
+ *nalloc = buf_size;
+
+done:
+ H5MM_free(data);
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5R__encode_addr_region_compat() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5R__decode_obj_addr_compat
+ *
+ * Purpose: Decode dataset selection from data inserted into heap (native only).
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5R__decode_addr_region_compat(H5F_t *f, const unsigned char *buf,
+ size_t *nbytes, haddr_t *obj_addr_ptr, H5S_t **space_ptr)
+{
+ unsigned char *data = NULL;
+ size_t data_size;
+ haddr_t obj_addr;
+ const uint8_t *p;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE
+
+ HDassert(f);
+ HDassert(buf);
+ HDassert(nbytes);
+
+ /* Read from heap */
+ if(H5R__decode_heap(f, buf, nbytes, &data, &data_size) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
+
+ /* Get object address */
+ p = (const uint8_t *)data;
+ H5F_addr_decode(f, &p, &obj_addr);
+ if(!H5F_addr_defined(obj_addr) || obj_addr == 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Undefined reference pointer")
+
+ if(space_ptr) {
+ H5O_loc_t oloc; /* Object location */
+ H5S_t *space = NULL;
+
+ /* Initialize the object location */
+ H5O_loc_reset(&oloc);
+ oloc.file = f;
+ oloc.addr = obj_addr;
+
+ /* Open and copy the dataset's dataspace */
+ if(NULL == (space = H5S_read(&oloc)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_NOTFOUND, FAIL, "not found")
+
+ /* Unserialize the selection */
+ if(H5S_SELECT_DESERIALIZE(&space, &p) < 0)
+ HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, FAIL, "can't deserialize selection")
+
+ *space_ptr = space;
+ }
+ if(obj_addr_ptr)
+ *obj_addr_ptr = obj_addr;
+
+done:
+ H5MM_free(data);
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5R__decode_addr_region_compat() */