summaryrefslogtreecommitdiffstats
path: root/src/H5O.c
diff options
context:
space:
mode:
authorJames Laird <jlaird@hdfgroup.org>2006-11-13 20:41:36 (GMT)
committerJames Laird <jlaird@hdfgroup.org>2006-11-13 20:41:36 (GMT)
commitb6c317f27cd150aa7bfc4e9cf275629570c9a319 (patch)
tree3413a54aec3bbebb821088a473f6ff425c3d39be /src/H5O.c
parent77c265f26746359cf348437702c93c162f7022f6 (diff)
downloadhdf5-b6c317f27cd150aa7bfc4e9cf275629570c9a319.zip
hdf5-b6c317f27cd150aa7bfc4e9cf275629570c9a319.tar.gz
hdf5-b6c317f27cd150aa7bfc4e9cf275629570c9a319.tar.bz2
[svn-r12902] Checkin of Shared Object Header Message work.
This feature is still in progress; Shared Object Header Messages are not complete as a feature and are not thoroughly tested. There are still "TODO" comments in the code (comments with the word "JAMES" in them, so as not to be confused with other TODO comments). Hopefully this checkin will reduce the liklihood of conflicts as I finish implementing this feature. All current tests pass on juniper, copper (parallel), heping, kagiso, and mir.
Diffstat (limited to 'src/H5O.c')
-rw-r--r--src/H5O.c713
1 files changed, 593 insertions, 120 deletions
diff --git a/src/H5O.c b/src/H5O.c
index 23fee02..89194b5 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -41,6 +41,8 @@
#include "H5MFprivate.h" /* File memory management */
#include "H5MMprivate.h" /* Memory management */
#include "H5Opkg.h" /* Object headers */
+#include "H5Tprivate.h"
+#include "H5SMprivate.h" /* Shared object header messages */
#ifdef H5_HAVE_GETTIMEOFDAY
#include <sys/time.h>
@@ -70,6 +72,7 @@
HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, ERR, "unable to decode message") \
} /* end if */
+/* Private typedefs */
/******************/
/* Local Typedefs */
@@ -170,8 +173,6 @@ static herr_t H5O_iterate_real(const H5O_loc_t *loc, const H5O_msg_class_t *type
static const H5O_obj_class_t *H5O_obj_class(H5O_loc_t *loc, hid_t dxpl_id);
static H5G_obj_t H5O_obj_type_real(H5O_t *oh);
static const H5O_obj_class_t *H5O_obj_class_real(H5O_t *oh);
-static void * H5O_copy_mesg_file(const H5O_msg_class_t *type, H5F_t *file_src, void *mesg_src,
- H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata);
static herr_t H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
hid_t dxpl_id, H5O_copy_t *cpy_info);
static herr_t H5O_copy_free_addrmap_cb(void *item, void *key, void *op_data);
@@ -249,7 +250,6 @@ H5FL_EXTERN(H5O_cont_t);
/* Declare a free list to manage the H5O_addr_map_t struct */
H5FL_EXTERN(H5O_addr_map_t);
-
/*-------------------------------------------------------------------------
* Function: H5Oopen
@@ -1607,11 +1607,14 @@ done:
*
*-------------------------------------------------------------------------
*/
+/* JAMES: this will probably get put through its paces when extending shared
+ * dataspaces */
int
H5O_modify(H5O_loc_t *loc, unsigned type_id, int overwrite,
- unsigned flags, unsigned update_flags, const void *mesg, hid_t dxpl_id)
+ unsigned flags, unsigned update_flags, void *mesg, hid_t dxpl_id)
{
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
+ htri_t shared_mess;
int ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5O_modify, FAIL)
@@ -1626,6 +1629,15 @@ H5O_modify(H5O_loc_t *loc, unsigned type_id, int overwrite,
HDassert(mesg);
HDassert(0 == (flags & ~H5O_FLAG_BITS));
+ /* Should this message be written as a SOHM? */
+ if((shared_mess = H5SM_try_share(loc->file, dxpl_id, type_id, mesg)) >0)
+ {
+ /* Mark the message as shared */
+ flags |= H5O_FLAG_SHARED;
+
+ } else if(shared_mess < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "error while trying to share message");
+
/* Call the "real" modify routine */
if((ret_value = H5O_modify_real(loc, type, overwrite, flags, update_flags, mesg, dxpl_id)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header message")
@@ -1679,6 +1691,8 @@ H5O_modify_real(H5O_loc_t *loc, const H5O_msg_class_t *type, int overwrite,
unsigned idx; /* Index of message to modify */
H5O_mesg_t *idx_msg; /* Pointer to message to modify */
H5O_shared_t sh_mesg;
+ const H5O_msg_class_t *write_type = type; /* Type of message to be written */
+ const void *write_mesg = mesg; /* Actual message being written */
int ret_value;
FUNC_ENTER_NOAPI_NOINIT(H5O_modify_real)
@@ -1709,7 +1723,7 @@ H5O_modify_real(H5O_loc_t *loc, const H5O_msg_class_t *type, int overwrite,
/* Was the right message found? */
if(overwrite >= 0 && (idx >= oh->nmesgs || sequence != overwrite)) {
- /* But can we insert a new one with this sequence number? */
+ /* No, but can we insert a new one with this sequence number? */
if(overwrite == sequence + 1)
overwrite = -1;
else
@@ -1719,6 +1733,7 @@ H5O_modify_real(H5O_loc_t *loc, const H5O_msg_class_t *type, int overwrite,
/* Check for creating new message */
if(overwrite < 0) {
/* Create a new message */
+ /* JAMES: why is sh_mesg passed in here? Is it ever used? */
if((idx = H5O_new_mesg(loc->file, oh, &flags, type, mesg, &sh_mesg, &type, &mesg, dxpl_id, &oh_flags)) == UFAIL)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to create new message")
@@ -1728,11 +1743,41 @@ H5O_modify_real(H5O_loc_t *loc, const H5O_msg_class_t *type, int overwrite,
} else if(oh->mesg[idx].flags & H5O_FLAG_CONSTANT) {
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to modify constant message")
} else if(oh->mesg[idx].flags & H5O_FLAG_SHARED) {
- HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to modify shared (constant) message")
+ /* This message is shared, but it's being modified. This is valid if
+ * it's shared in the heap .
+ * First, make sure it's not a committed message; these can't ever
+ * be modified.
+ */
+ if(((H5O_shared_t*) oh->mesg[idx].native)->flags & H5O_COMMITTED_FLAG)
+ HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to modify committed message")
+
+ /* Remove the old message from the SOHM index */
+ if(H5SM_try_delete(loc->file, dxpl_id, oh->mesg[idx].type->id, oh->mesg[idx].native) < 0)
+ HGOTO_ERROR (H5E_OHDR, H5E_CANTFREE, FAIL, "unable to delete message from SOHM table")
+
+ /* Now this message is no longer shared and we can safely overwrite
+ * it.
+ * We need to make sure that the message we're writing is shared,
+ * though, and that the library doesn't try to reset the current
+ * message like it would in a normal overwrite (this message is
+ * realy a shared pointer, not a real
+ * message).
+ * JAMES: will this break if a shared message is overwritten with a larger
+ * non-shared message?
+ */
+ HDassert(H5O_is_shared(type->id, mesg) > 0); /* JAMES: this should work with
+ * replacement messages that aren't shared, too. */
+
+ if(H5O_get_share(type->id, loc->file, mesg, &sh_mesg)<0)
+ HGOTO_ERROR (H5E_OHDR, H5E_BADMESG, FAIL, "can't get shared message")
+
+ /* Instead of writing the original message, write a shared message */
+ write_type = H5O_msg_class_g[H5O_SHARED_ID];
+ write_mesg = &sh_mesg;
}
/* Write the information to the message */
- if(H5O_write_mesg(oh, idx, type, mesg, flags, update_flags, &oh_flags) < 0)
+ if(H5O_write_mesg(oh, idx, write_type, write_mesg, flags, update_flags, &oh_flags) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to write message")
/* Update the modification time message if any */
@@ -1854,9 +1899,10 @@ done:
*/
int
H5O_append(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id, unsigned flags,
- const void *mesg, unsigned * oh_flags_ptr)
+ void *mesg, unsigned * oh_flags_ptr)
{
- const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
+ const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
+ htri_t shared_mess; /* Should this message be stored in the Shared Message table? */
int ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5O_append, FAIL)
@@ -1871,7 +1917,15 @@ H5O_append(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id, unsigned flags,
HDassert(mesg);
HDassert(oh_flags_ptr);
- /* Call the "real" append routine */
+ /* Should this message be written as a SOHM? */
+ if((shared_mess = H5SM_try_share(f, dxpl_id, type_id, mesg)) >0)
+ {
+ /* Mark the message as shared */
+ flags |= H5O_FLAG_SHARED;
+ }
+ else if(shared_mess < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "error determining if message should be shared");
+
if((ret_value = H5O_append_real( f, dxpl_id, oh, type, flags, mesg, oh_flags_ptr)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to append to object header")
@@ -1953,6 +2007,7 @@ H5O_new_mesg(H5F_t *f, H5O_t *oh, unsigned *flags, const H5O_msg_class_t *orig_t
const void **new_mesg, hid_t dxpl_id, unsigned * oh_flags_ptr)
{
size_t size; /* Size of space allocated for object header */
+ htri_t is_shared; /* Is this a shared message? */
unsigned ret_value = UFAIL; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_new_mesg)
@@ -1972,20 +2027,25 @@ H5O_new_mesg(H5F_t *f, H5O_t *oh, unsigned *flags, const H5O_msg_class_t *orig_t
if(*flags & H5O_FLAG_SHARED) {
HDmemset(sh_mesg, 0, sizeof(H5O_shared_t));
- if(NULL == orig_type->get_share)
- HGOTO_ERROR(H5E_OHDR, H5E_UNSUPPORTED, UFAIL, "message class is not sharable")
- if((orig_type->get_share)(f, orig_mesg, sh_mesg/*out*/) < 0) {
+ if ((NULL == orig_type->is_shared) || (NULL == orig_type->get_share))
+ HGOTO_ERROR(H5E_OHDR, H5E_UNSUPPORTED, UFAIL, "message class is not sharable");
+ if ((is_shared = (orig_type->is_shared)(orig_mesg)) == FALSE) {
/*
* If the message isn't shared then turn off the shared bit
* and treat it as an unshared message.
*/
- H5E_clear_stack(NULL);
*flags &= ~H5O_FLAG_SHARED;
- } else {
- /* Change type & message to use shared information */
+ } else if(is_shared > 0) {
+ /* Message is shared. Get shared message, change message type,
+ * and use shared information */
+ if ((orig_type->get_share)(f, orig_mesg, sh_mesg/*out*/) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, UFAIL, "can't get shared message")
+
*new_type = H5O_MSG_SHARED;
*new_mesg = sh_mesg;
- } /* end else */
+ } else {
+ HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, UFAIL, "can't determine if message is shared")
+ }/* end else */
} /* end if */
else {
*new_type = orig_type;
@@ -1996,7 +2056,7 @@ H5O_new_mesg(H5F_t *f, H5O_t *oh, unsigned *flags, const H5O_msg_class_t *orig_t
if((size = ((*new_type)->raw_size)(f, *new_mesg)) >= H5O_MESG_MAX_SIZE)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, UFAIL, "object header message is too large")
- /* Allocate space in the object headed for the message */
+ /* Allocate space in the object header for the message */
if((ret_value = H5O_alloc(f, dxpl_id, oh, orig_type, size, oh_flags_ptr)) == UFAIL)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, UFAIL, "unable to allocate space for message")
@@ -3455,9 +3515,11 @@ H5O_alloc_new_chunk(H5F_t *f,
* that could be moved to make room for the continuation message.
*
* Don't ever move continuation message from one chunk to another.
+ * Prioritize link messages moving to later chunks, instead of
+ * more "important" messages.
+ * Avoid moving attributes when possible to preserve their
+ * ordering (although ordering is *not* guaranteed!).
*
- * Prioritize moving attribute and link messages to later chunks,
- * instead of more "important" messages.
*/
cont_size = H5O_ALIGN_OH(oh, H5F_SIZEOF_ADDR(f) + H5F_SIZEOF_SIZE(f));
for(u = 0; u < oh->nmesgs; u++) {
@@ -3498,15 +3560,17 @@ H5O_alloc_new_chunk(H5F_t *f,
* message, then make sure the new chunk has enough room for that
* other message.
*
- * Move attributes first, then link messages, then other messages.
+ * Move link messages first, then other messages, and attributes
+ * only as a last resort.
*
*/
if(found_null < 0) {
- if(found_attr >= 0)
- found_other = found_attr;
- else if(found_link >= 0)
+ if(found_link >= 0)
found_other = found_link;
+ if(found_other < 0)
+ found_other = found_attr;
+
HDassert(found_other >= 0);
size += H5O_SIZEOF_MSGHDR_OH(oh) + oh->mesg[found_other].raw_size;
} /* end if */
@@ -4030,7 +4094,7 @@ H5O_get_share(unsigned type_id, H5F_t *f, const void *mesg, H5O_shared_t *share)
HDassert(mesg);
HDassert(share);
- /* Compute the raw data size for the mesg */
+ /* Get shared data for the mesg */
if((ret_value = (type->get_share)(f, mesg, share)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to retrieve shared message information")
@@ -4039,6 +4103,143 @@ done:
} /* end H5O_get_share() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_is_shared
+ *
+ * Purpose: Call the 'is_shared' method for a
+ * particular class of object header.
+ *
+ * Return: Object is shared: TRUE
+ * Object is not shared: FALSE
+ *
+ * Programmer: James Laird
+ * jlaird@ncsa.uiuc.edu
+ * April 5 2006
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5O_is_shared(unsigned type_id, const void *mesg)
+{
+ const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
+ htri_t ret_value;
+
+ FUNC_ENTER_NOAPI_NOFUNC(H5O_is_shared)
+
+ /* Check args */
+ HDassert(type_id < NELMTS(H5O_msg_class_g));
+ type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
+ HDassert(type);
+ HDassert(mesg);
+
+ HDassert(type_id != H5O_SHARED_ID); /* JAMES: check for this mistake elsewhere, too */
+
+ /* If there is no is_shared function, then obviously it's not a shared message! */
+ if( !(type->is_shared))
+ ret_value = FALSE;
+ else
+ ret_value = (type->is_shared)(mesg);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_is_shared() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_set_share
+ *
+ * Purpose: Set the shared information for an object header message.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: James Laird
+ * jlaird@hdfgroup.org
+ * November 1 2006
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_set_share(H5F_t *f, hid_t dxpl_id, H5O_shared_t *share,
+ unsigned type_id, void *mesg)
+{
+ const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
+ herr_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5O_set_share,FAIL)
+
+ /* Check args */
+ HDassert(f);
+ HDassert(share);
+ HDassert(type_id < NELMTS(H5O_msg_class_g));
+ type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
+ HDassert(type);
+ HDassert(type->set_share);
+ HDassert(mesg);
+ HDassert(share->flags != H5O_NOT_SHARED);
+
+ /* Set this message as the shared message for the message, wiping out
+ * any information that was there before
+ */
+ if((ret_value = (type->set_share)(f, mesg, share)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to set shared message information")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_set_share() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_reset_share
+ *
+ * Purpose: Reset the shared information for an object header message.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: James Laird
+ * jlaird@hdfgroup.org
+ * Oct 17 2006
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_reset_share(H5F_t *f, unsigned type_id, void *mesg)
+{
+ const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
+ H5O_shared_t sh_mesg; /* Shared message */
+ herr_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5O_reset_share,FAIL)
+
+ /* Check args */
+ HDassert(type_id < NELMTS(H5O_msg_class_g));
+ type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
+ HDassert(type);
+ HDassert(type->set_share);
+ HDassert(mesg);
+
+ /* Initialize the shared message to zero. */
+ HDmemset(&sh_mesg, 0, sizeof(H5O_shared_t));
+
+ /* Set this message as the shared message for the message, wiping out
+ * any information that was there before
+ */
+ if((ret_value = (type->set_share)(f, mesg, &sh_mesg)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to reset shared message information")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_reset_share() */
+
+
+
/*-------------------------------------------------------------------------
* Function: H5O_delete
*
@@ -4160,7 +4361,9 @@ H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_mesg_t *mesg, hbool_t adj_link)
/* Get the message to free's type */
if(mesg->flags & H5O_FLAG_SHARED)
+ {
type = H5O_MSG_SHARED;
+ }
else
type = mesg->type;
@@ -4176,6 +4379,22 @@ H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_mesg_t *mesg, hbool_t adj_link)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to decode message")
} /* end if */
+ /* Check if this message needs to be removed from the SOHM table */
+ /* JAMES: there should be a callback, maybe in H5O_shared_delete, to fiddle w/ the ref. count.
+ * We shouldn't need to do a search in the SOHM table on delete. */
+ if(type == H5O_MSG_SHARED)
+ {
+ /* JAMES ugly! And not quite correct. */
+ void * mesg_orig;
+ if(NULL == (mesg_orig = H5O_shared_read(f, dxpl_id, mesg->native, mesg->type, NULL)))
+ HGOTO_ERROR (H5E_OHDR, H5E_BADMESG, FAIL, "unable to read shared message")
+
+ if(H5SM_try_delete(f, dxpl_id, mesg->type->id, mesg->native) < 0)
+ HGOTO_ERROR (H5E_OHDR, H5E_CANTFREE, FAIL, "unable to delete message from SOHM table")
+
+ H5O_free(mesg->type->id, mesg_orig);
+ }
+
if((type->del)(f, dxpl_id, mesg->native, adj_link) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message")
} /* end if */
@@ -4444,12 +4663,23 @@ H5O_iterate_real(const H5O_loc_t *loc, const H5O_msg_class_t *type, H5AC_protect
/* Iterate over messages */
for(sequence = 0, idx = 0, idx_msg = &oh->mesg[0]; idx < oh->nmesgs && !ret_value; idx++, idx_msg++) {
if(type->id == idx_msg->type->id) {
+ void * unshared_mesg; /* JAMES */
+
/*
* Decode the message if necessary. If the message is shared then decode
* a shared message, ignoring the message type.
*/
LOAD_NATIVE(loc->file, dxpl_id, idx_msg, FAIL)
+ /* JAMES: test */
+ if(idx_msg->flags & H5O_FLAG_SHARED)
+ {
+ if(NULL == (unshared_mesg = H5O_shared_read(loc->file, dxpl_id, idx_msg->native, idx_msg->type, NULL)))
+ HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "unable to read shared message");
+ }
+ else
+ unshared_mesg = idx_msg->native;
+
/* Check for making an "internal" (i.e. within the H5O package) callback */
if(internal) {
/* Call the "internal" iterator callback */
@@ -4458,10 +4688,19 @@ H5O_iterate_real(const H5O_loc_t *loc, const H5O_msg_class_t *type, H5AC_protect
} /* end if */
else {
/* Call the iterator callback */
- if((ret_value = (op.app_op)(idx_msg->native, sequence, op_data)) != 0)
+/* JAMES if((ret_value = (op.app_op)(idx_msg->native, sequence, op_data)) != 0)
+ break;
+*/
+ if((ret_value = (op.app_op)(unshared_mesg, sequence, op_data)) != 0)
break;
} /* end else */
+ /* JAMES again */
+ if(idx_msg->flags & H5O_FLAG_SHARED)
+ {
+ H5O_free_real(idx_msg->type, unshared_mesg);
+ }
+
/* Check for error from iterator */
if(ret_value < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "iterator function failed")
@@ -4820,8 +5059,8 @@ done:
*
*-------------------------------------------------------------------------
*/
-static void *
-H5O_copy_mesg_file(const H5O_msg_class_t *type, H5F_t *file_src, void *native_src,
+void *
+H5O_copy_mesg_file(const H5O_msg_class_t *copy_type, const H5O_msg_class_t *mesg_type, H5F_t *file_src, void *native_src,
H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata)
{
void *ret_value;
@@ -4829,14 +5068,15 @@ H5O_copy_mesg_file(const H5O_msg_class_t *type, H5F_t *file_src, void *native_sr
FUNC_ENTER_NOAPI_NOINIT(H5O_copy_mesg_file)
/* check args */
- HDassert(type);
- HDassert(type->copy_file);
+ HDassert(copy_type);
+ HDassert(mesg_type);
+ HDassert(copy_type->copy_file);
HDassert(file_src);
HDassert(native_src);
HDassert(file_dst);
HDassert(cpy_info);
- if(NULL == (ret_value = (type->copy_file)(file_src, native_src, file_dst, dxpl_id, cpy_info, udata)))
+ if(NULL == (ret_value = (copy_type->copy_file)(file_src, mesg_type, native_src, file_dst, dxpl_id, cpy_info, udata)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to copy object header message to file")
done:
@@ -4847,7 +5087,15 @@ done:
/*-------------------------------------------------------------------------
* Function: H5O_copy_header_real
*
- * Purpose: copy header object from one location to another.
+ * Purpose: Copy header object from one location to another using
+ * pre-copy, copy, and post-copy callbacks for each message
+ * type.
+ *
+ * The source header object is compressed into a single chunk
+ * (since we know how big it is) and any continuation messages
+ * are converted into NULL messages.
+ *
+ * By default, NULL messages are not copied.
*
* Return: Non-negative on success/Negative on failure
*
@@ -4865,11 +5113,17 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
H5O_t *oh_dst = NULL; /* Object header for destination object */
unsigned chunkno = 0, mesgno = 0;
haddr_t addr_new = HADDR_UNDEF;
+ hbool_t *deleted = NULL; /* Array of flags indicating whether messages should be copied */
+ size_t null_msgs; /* Number of NULL messages found in each loop */
H5O_mesg_t *mesg_src; /* Message in source object header */
H5O_mesg_t *mesg_dst; /* Message in source object header */
const H5O_msg_class_t *copy_type; /* Type of message to use for copying */
const H5O_obj_class_t *obj_class = NULL; /* Type of object we are copying */
- void *udata = NULL; /* User data for passing to message callbacks */
+ void *udata = NULL; /* User data for passing to message
+ callbacks */
+ size_t dst_oh_size; /* Total size of the destination OH */
+ uint8_t *current_pos; /* Current position in destination image */
+ size_t msghdr_size;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT(H5O_copy_header_real)
@@ -4905,57 +5159,27 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
oh_dst->version = oh_src->version;
oh_dst->nlink = 0;
- /* Initialize size of chunk array */
- oh_dst->alloc_nchunks = oh_dst->nchunks = oh_src->nchunks;
+ /* Initialize size of chunk array. The destination always has only one
+ * chunk.
+ */
+ oh_dst->alloc_nchunks = oh_dst->nchunks = 1;
/* Allocate memory for the chunk array */
if(NULL == (oh_dst->chunk = H5FL_SEQ_MALLOC(H5O_chunk_t, oh_dst->alloc_nchunks)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
- /* need to allocate all the chunks for the destination before copy the chunk message
- because continuation chunk message will need to know the chunk address of address of
- continuation block.
+ /* Allocate memory for "deleted" array. This array marks the message in
+ * the source that shouldn't be copied to the destination.
*/
- for(chunkno = 0; chunkno < oh_src->nchunks; chunkno++) {
- size_t chunk_size = oh_src->chunk[chunkno].size;
-
- /* Allocate space for chunk in destination file */
- if(HADDR_UNDEF == (oh_dst->chunk[chunkno].addr = H5MF_alloc(oloc_dst->file, H5FD_MEM_OHDR, dxpl_id, (hsize_t)chunk_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for object header")
- if(chunkno == 0)
- addr_new = oh_dst->chunk[chunkno].addr;
-
- /* Create memory image for the new chunk */
- if(NULL == (oh_dst->chunk[chunkno].image = H5FL_BLK_MALLOC(chunk_image, chunk_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
-
- /* Copy the chunk image from source to destination in memory */
- /* (This copies over all the messages which don't require special
- * callbacks to fix them up.)
- */
- HDmemcpy(oh_dst->chunk[chunkno].image, oh_src->chunk[chunkno].image, chunk_size);
-
- /* Set dest. chunk information */
- oh_dst->chunk[chunkno].dirty = TRUE;
- oh_dst->chunk[chunkno].size = chunk_size;
- oh_dst->chunk[chunkno].gap = oh_src->chunk[chunkno].gap;
- } /* end for */
-
-
- /* Initialize size of message list */
- oh_dst->alloc_nmesgs = oh_dst->nmesgs = oh_src->nmesgs;
-
- /* Allocate memory for message array */
- if(NULL == (oh_dst->mesg = H5FL_SEQ_CALLOC(H5O_mesg_t, oh_dst->alloc_nmesgs)))
+ if(NULL == (deleted = HDmalloc(sizeof(hbool_t) * oh_src->nmesgs)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ HDmemset(deleted, FALSE, sizeof(hbool_t) * oh_src->nmesgs);
- /* Copy basic information about messages */
- HDmemcpy(oh_dst->mesg, oh_src->mesg, oh_dst->alloc_nmesgs * sizeof(H5O_mesg_t));
-
- /* Set up destination message raw image pointer information */
- /* (must be done before "pre copy" pass, so that if a message is deleted,
- * the raw message information in a chunk can be moved around safely)
+ /* "pre copy" pass over messages, to gather information for actual message copy operation
+ * (for messages which depend on information from other messages)
+ * Keep track of how many NULL or deleted messages we find (or create)
*/
+ null_msgs = 0;
for(mesgno = 0; mesgno < oh_src->nmesgs; mesgno++) {
/* Set up convenience variables */
mesg_src = &(oh_src->mesg[mesgno]);
@@ -4964,28 +5188,23 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
/* Sanity check */
HDassert(!mesg_src->dirty); /* Should be cleared by earlier call to flush messages */
- /* Fix up destination message pointers */
- mesg_dst->raw = oh_dst->chunk[mesg_dst->chunkno].image + (mesg_src->raw - oh_src->chunk[mesg_src->chunkno].image);
- mesg_dst->native = NULL;
- } /* end for */
-
- /* "pre copy" pass over messages, to gather information for actual message copy operation */
- /* (for messages which depend on information from other messages) */
- for(mesgno = 0; mesgno < oh_src->nmesgs; mesgno++) {
- /* Set up convenience variables */
- mesg_src = &(oh_src->mesg[mesgno]);
- mesg_dst = &(oh_dst->mesg[mesgno]);
-
/* Check for shared message to operate on */
if(mesg_src->flags & H5O_FLAG_SHARED)
copy_type = H5O_MSG_SHARED;
else
copy_type = mesg_src->type;
- HDassert(copy_type);
- if(copy_type->pre_copy_file) {
- hbool_t deleted = FALSE; /* Flag to indicate that the message should be deleted from the destination */
+ /* Check for continuation message; these are converted to NULL
+ * messages because the destination OH will have only one chunk
+ */
+ if(H5O_CONT_ID == mesg_src->type->id || H5O_NULL_ID == mesg_src->type->id) {
+ deleted[mesgno] = TRUE;
+ ++null_msgs;
+ copy_type = H5O_MSG_NULL;
+ }
+ HDassert(copy_type);
+ if(copy_type->pre_copy_file ) {
/*
* Decode the message if necessary. If the message is shared then do
* a shared message, ignoring the message type.
@@ -4998,28 +5217,68 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
} /* end if (NULL == mesg_src->native) */
/* Perform "pre copy" operation on message */
- if((copy_type->pre_copy_file)(oloc_src->file, mesg_src->type, mesg_src->native, &deleted, cpy_info, udata) < 0)
+ if((copy_type->pre_copy_file)(oloc_src->file, mesg_src->type, mesg_src->native, &(deleted[mesgno]), cpy_info, udata) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to perform 'pre copy' operation on message")
/* Check if the message should be deleted in the destination */
- if(deleted) {
- /* Convert message into a null message */
- if(H5O_release_mesg(oloc_dst->file, dxpl_id, oh_dst, mesg_dst, FALSE, FALSE) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to convert into null message")
- } /* end if */
- } /* end if */
+ if(deleted[mesgno]) {
+ /* Mark message as deleted */
+ ++null_msgs;
+ } /* end if(deleted) */
+ } /* end if(copy_type->pre_copy_file) */
} /* end for */
+ /* Initialize size of message list. It may or may not include the NULL messages
+ * detected above.
+ */
+ if(cpy_info->preserve_null)
+ oh_dst->alloc_nmesgs = oh_dst->nmesgs = oh_src->nmesgs;
+ else
+ oh_dst->alloc_nmesgs = oh_dst->nmesgs = (oh_src->nmesgs - null_msgs);
+
+ /* Allocate memory for destination message array */
+ if(oh_dst->alloc_nmesgs > 0) {
+ if(NULL == (oh_dst->mesg = H5FL_SEQ_CALLOC(H5O_mesg_t, oh_dst->alloc_nmesgs)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ }
+
/* "copy" pass over messages, to perform main message copying */
- for(mesgno = 0; mesgno < oh_src->nmesgs; mesgno++) {
+ null_msgs = 0;
+ for(mesgno = 0; mesgno < oh_dst->nmesgs; mesgno++) {
+ /* Skip any deleted or NULL messages in the source unless the
+ * preserve_null flag is set
+ */
+ if(FALSE == cpy_info->preserve_null) {
+ while(deleted[mesgno + null_msgs]) {
+ ++null_msgs;
+ HDassert(mesgno + null_msgs < oh_src->nmesgs);
+ }
+ }
+
/* Set up convenience variables */
- mesg_src = &(oh_src->mesg[mesgno]);
+ mesg_src = &(oh_src->mesg[mesgno + null_msgs]);
mesg_dst = &(oh_dst->mesg[mesgno]);
+ /* Initialize on destination message */
+ mesg_dst->chunkno = 0;
+ mesg_dst->dirty = FALSE;
+ mesg_dst->flags = mesg_src->flags;
+ mesg_dst->native = NULL;
+ mesg_dst->raw = NULL;
+ mesg_dst->raw_size = mesg_src->raw_size;
+ mesg_dst->type = mesg_src->type;
+
+ /* If we're preserving deleted messages, set their types to 'NULL'
+ * in the destination.
+ */
+ if(cpy_info->preserve_null && deleted[mesgno]) {
+ mesg_dst->type = H5O_MSG_NULL;
+ }
+
/* Check for shared message to operate on */
/* (Use destination message, in case the message has been removed (i.e
- * converted to a nil message) in the destination -QAK)
- */
+ * converted to a nil message) in the destination -QAK)
+ */
if(mesg_dst->flags & H5O_FLAG_SHARED)
copy_type = H5O_MSG_SHARED;
else
@@ -5029,9 +5288,9 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
/* copy this message into destination file */
if(copy_type->copy_file) {
/*
- * Decode the message if necessary. If the message is shared then do
- * a shared message, ignoring the message type.
- */
+ * Decode the message if necessary. If the message is shared then do
+ * a shared message, ignoring the message type.
+ */
if(NULL == mesg_src->native) {
/* Decode the message if necessary */
HDassert(copy_type->decode);
@@ -5040,16 +5299,10 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
} /* end if (NULL == mesg_src->native) */
/* Copy the source message */
- if(H5O_CONT_ID == mesg_src->type->id) {
- if((mesg_dst->native = H5O_copy_mesg_file(copy_type, oloc_src->file, mesg_src->native,
- oloc_dst->file, dxpl_id, cpy_info, oh_dst->chunk)) == NULL)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object header message")
- } /* end if */
- else {
- if((mesg_dst->native = H5O_copy_mesg_file(copy_type, oloc_src->file, mesg_src->native,
- oloc_dst->file, dxpl_id, cpy_info, udata)) == NULL)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object header message")
- } /* end else */
+ if((mesg_dst->native = H5O_copy_mesg_file(copy_type, mesg_dst->type,
+ oloc_src->file, mesg_src->native, oloc_dst->file, dxpl_id,
+ cpy_info, udata)) == NULL)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object header message")
/* Mark the message in the destination as dirty, so it'll get encoded when the object header is flushed */
mesg_dst->dirty = TRUE;
@@ -5057,6 +5310,86 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
} /* end of mesgno loop */
+ /* Allocate the destination header and copy any messages that didn't have
+ * copy callbacks. They get copied directly from the source image to the
+ * destination image.
+ */
+
+ /* Calculate how big the destination object header will be on disk.
+ * This isn't necessarily the same size as the original.
+ */
+ dst_oh_size = H5O_SIZEOF_HDR_OH(oh_dst);
+
+ /* Add space for messages. */
+ for(mesgno = 0; mesgno < oh_dst->nmesgs; mesgno++) {
+ dst_oh_size += H5O_SIZEOF_MSGHDR_OH(oh_dst);
+ dst_oh_size += H5O_ALIGN_OH(oh_dst, oh_dst->mesg[mesgno].raw_size);
+ }
+
+ /* Allocate space for chunk in destination file */
+ if(HADDR_UNDEF == (oh_dst->chunk[0].addr = H5MF_alloc(oloc_dst->file, H5FD_MEM_OHDR, dxpl_id, (hsize_t)dst_oh_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for object header")
+ addr_new = oh_dst->chunk[0].addr;
+
+ /* Create memory image for the new chunk */
+ if(NULL == (oh_dst->chunk[0].image = H5FL_BLK_MALLOC(chunk_image, dst_oh_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Set dest. chunk information */
+ oh_dst->chunk[0].dirty = TRUE;
+ oh_dst->chunk[0].size = dst_oh_size;
+ oh_dst->chunk[0].gap = 0;
+
+ /* Set up raw pointers and copy messages that didn't need special
+ * treatment. This has to happen after the destination header has been
+ * allocated.
+ */
+ HDassert(H5O_SIZEOF_HDR_OH(oh_src) == H5O_SIZEOF_HDR_OH(oh_dst));
+ HDassert(H5O_SIZEOF_MSGHDR_OH(oh_src) == H5O_SIZEOF_MSGHDR_OH(oh_dst));
+ msghdr_size = H5O_SIZEOF_MSGHDR_OH(oh_src);
+
+ current_pos = oh_dst->chunk[0].image;
+
+ /* Copy the message header. Most of this will be overwritten when
+ * the header is flushed to disk, but later versions have a
+ * magic number that isn't.
+ */
+ HDmemcpy(current_pos, oh_src->chunk[0].image,
+ H5O_SIZEOF_HDR_OH(oh_dst) - H5O_SIZEOF_CHKSUM_OH(oh_dst));
+ current_pos += H5O_SIZEOF_HDR_OH(oh_dst) - H5O_SIZEOF_CHKSUM_OH(oh_dst);
+
+ /* JAMES: include this in loop above? Doesn't take deleted messages
+ * into account
+ */
+ /* Copy each message that wasn't dirtied above */
+ null_msgs = 0;
+ for(mesgno = 0; mesgno < oh_dst->nmesgs; mesgno++) {
+ /* Skip any deleted or NULL messages in the source unless the
+ * preserve_null flag is set
+ */
+ if(FALSE == cpy_info->preserve_null) {
+ while(deleted[mesgno + null_msgs]) {
+ ++null_msgs;
+ HDassert(mesgno + null_msgs < oh_src->nmesgs);
+ }
+ }
+
+ /* Set up convenience variables */
+ mesg_src = &(oh_src->mesg[mesgno + null_msgs]);
+ mesg_dst = &(oh_dst->mesg[mesgno]);
+
+ if(! mesg_dst->dirty) {
+ /* Copy the message header plus the message's raw data. */
+ HDmemcpy(current_pos, mesg_src->raw - msghdr_size,
+ msghdr_size + mesg_src->raw_size);
+ }
+ mesg_dst->raw = current_pos + msghdr_size;
+ current_pos += mesg_dst->raw_size + msghdr_size;
+ }
+
+ /* Make sure we filled the chunk, except for room at the end for a checksum */
+ HDassert(current_pos + H5O_SIZEOF_CHKSUM_OH(oh_dst) == dst_oh_size + oh_dst->chunk[0].image);
+
/* Set the dest. object location to the first chunk address */
HDassert(H5F_addr_defined(addr_new));
oloc_dst->addr = addr_new;
@@ -5078,9 +5411,20 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
/* "post copy" loop over messages, to fix up any messages which require a complete
* object header for destination object
*/
- for(mesgno = 0; mesgno < oh_src->nmesgs; mesgno++) {
+ null_msgs = 0;
+ for(mesgno = 0; mesgno < oh_dst->nmesgs; mesgno++) {
+ /* Skip any deleted or NULL messages in the source unless the
+ * preserve_null flag is set
+ */
+ if(FALSE == cpy_info->preserve_null) {
+ while(deleted[mesgno + null_msgs]) {
+ ++null_msgs;
+ HDassert(mesgno + null_msgs < oh_src->nmesgs);
+ }
+ }
+
/* Set up convenience variables */
- mesg_src = &(oh_src->mesg[mesgno]);
+ mesg_src = &(oh_src->mesg[mesgno + null_msgs]);
mesg_dst = &(oh_dst->mesg[mesgno]);
/* Check for shared message to operate on */
@@ -5119,7 +5463,12 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to cache object header")
done:
- /* Release pointer to source object header and it's derived objects */
+ /* Free deleted array */
+ if(deleted) {
+ HDfree(deleted);
+ }
+
+ /* Release pointer to source object header and its derived objects */
if(oh_src != NULL) {
/* Unprotect the source object header */
if(H5AC_unprotect(oloc_src->file, dxpl_id, H5AC_OHDR, oloc_src->addr, oh_src, H5AC__NO_FLAGS_SET) < 0)
@@ -5180,7 +5529,7 @@ H5O_copy_header_map(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
/* Copy object for the first time */
/* Check for incrementing the depth of copy */
- /* (Can't do this for all copies, since shared datatypes should always be copied) */
+ /* (Can't do this for all copies, since committed datatypes should always be copied) */
if(inc_depth)
cpy_info->curr_depth++;
@@ -5199,7 +5548,7 @@ H5O_copy_header_map(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
ret_value++;
} /* end if */
else {
- /* Object has already been copied, set it's address in destination file */
+ /* Object has already been copied, set its address in destination file */
oloc_dst->addr = addr_map->dst_addr;
/* If the object is locked currently (because we are copying a group
@@ -5301,6 +5650,8 @@ H5O_copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
cpy_info.expand_ref = TRUE;
if((cpy_option & H5O_COPY_WITHOUT_ATTR_FLAG) > 0)
cpy_info.copy_without_attr = TRUE;
+ if((cpy_option & H5O_COPY_PRESERVE_NULL_FLAG) > 0)
+ cpy_info.preserve_null = TRUE;
/* Create a skip list to keep track of which objects are copied */
if((cpy_info.map_list = H5SL_create(H5SL_TYPE_HADDR, 0.5, (size_t)16)) == NULL)
@@ -5317,6 +5668,128 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_copy_header() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_mesg_hash
+ *
+ * Purpose: Returns a hash value for an object header message.
+ *
+ * Return: Non-H5O_HASH_UNDEF hash value on success
+ * H5O_HASH_UNDEF on failure
+ *
+ * Programmer: James Laird
+ * April 13 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+uint32_t
+H5O_mesg_hash(unsigned type_id, H5F_t *f, const void *mesg)
+{
+ size_t buf_size;
+ unsigned char * buf = NULL; /* Buffer to be hashed */
+ uint32_t hash;
+ uint32_t ret_value;
+
+ FUNC_ENTER_NOAPI(H5O_mesg_hash, FAIL)
+
+ /* Check args */
+ HDassert(type_id < NELMTS(H5O_msg_class_g));
+ HDassert(mesg);
+ HDassert(f);
+
+ /* Find out the size of buffer needed */
+ if((buf_size = H5O_raw_size(type_id, f, mesg)) <= 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADSIZE, FAIL, "can't find message size");
+
+ /* JAMES: revisit this! Some messages don't use as much space as they say
+ * they need. Quincey may have fixed this.
+ */
+ if((buf = HDmalloc(buf_size)) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate buffer for message");
+ HDmemset(buf, 0, buf_size);
+
+ if(H5O_encode(f, buf, mesg, type_id) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "can't encode OH message");
+
+ /*
+ * Compute the hash value for this message. type_id is used here to
+ * initialize the hash algorithm, and affects the resulting value.
+ */
+ hash = H5_checksum_lookup3(buf, buf_size, type_id);
+
+ /* JAMES: this is a pretty good hash function. Do we need to version it?
+ * If so, we'd do so here. */
+
+ /* A hash value of H5O_HASH_UNDEF indicates failure. If we naturally
+ * generated this value, reset it to some valid value. */
+ if(hash == H5O_HASH_UNDEF)
+ hash = (uint32_t) 1;
+
+ ret_value = hash;
+done:
+ if(buf)
+ HDfree(buf);
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_mesg_hash() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_copy_obj_by_ref
+ *
+ * Purpose: Copy the object pointed by _src_ref.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Peter Cao
+ * Aug 7 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_copy_obj_by_ref(H5O_loc_t *src_oloc, hid_t dxpl_id, H5O_loc_t *dst_oloc,
+ H5G_loc_t *dst_root_loc, H5O_copy_t *cpy_info)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(H5O_copy_obj_by_ref, FAIL)
+
+ HDassert(src_oloc);
+ HDassert(dst_oloc);
+
+ /* Perform the copy, or look up existing copy */
+ if((ret_value = H5O_copy_header_map(src_oloc, dst_oloc, dxpl_id, cpy_info, FALSE)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object")
+
+ /* Check if a new valid object is copied to the destination */
+ if(H5F_addr_defined(dst_oloc->addr) && (ret_value > SUCCEED)) {
+ char tmp_obj_name[80];
+ H5G_name_t new_path;
+ H5O_loc_t new_oloc;
+ H5G_loc_t new_loc;
+
+ /* Set up group location for new object */
+ new_loc.oloc = &new_oloc;
+ new_loc.path = &new_path;
+ H5G_loc_reset(&new_loc);
+ new_oloc.file = dst_oloc->file;
+ new_oloc.addr = dst_oloc->addr;
+
+ /* Pick a default name for the new object */
+ sprintf(tmp_obj_name, "~obj_pointed_by_%llu", (unsigned long_long)dst_oloc->addr);
+
+ /* Create a link to the newly copied object */
+ if(H5L_link(dst_root_loc, tmp_obj_name, &new_loc, H5P_DEFAULT, H5P_DEFAULT, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to insert link")
+
+ H5G_loc_free(&new_loc);
+ } /* if (H5F_addr_defined(dst_oloc.addr)) */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_copy_obj_by_ref() */
+
+
+
#ifdef H5O_DEBUG
/*-------------------------------------------------------------------------
@@ -5603,7 +6076,7 @@ H5O_debug_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, haddr_t addr, FILE *stream, i
H5O_shared_t *shared = (H5O_shared_t*)(oh->mesg[i].native);
void *mesg;
- mesg = H5O_read_real(&(shared->oloc), oh->mesg[i].type, 0, NULL, dxpl_id);
+ mesg = H5O_shared_read(f, dxpl_id, shared, oh->mesg[i].type, NULL);
if(oh->mesg[i].type->debug)
(oh->mesg[i].type->debug)(f, dxpl_id, mesg, stream, indent + 3, MAX (0, fwidth - 3));
H5O_free_real(oh->mesg[i].type, mesg);