summaryrefslogtreecommitdiffstats
path: root/src/H5Oshared.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Oshared.c')
-rw-r--r--src/H5Oshared.c334
1 files changed, 279 insertions, 55 deletions
diff --git a/src/H5Oshared.c b/src/H5Oshared.c
index 367e001..7c69ab9 100644
--- a/src/H5Oshared.c
+++ b/src/H5Oshared.c
@@ -35,6 +35,8 @@
#include "H5Gprivate.h" /* Groups */
#include "H5MMprivate.h" /* Memory management */
#include "H5Opkg.h" /* Object headers */
+#include "H5HFprivate.h" /* Fractal heap */
+#include "H5SMprivate.h" /*JAMES: for H5SM_get_fheap_addr. Change this? */
static void *H5O_shared_decode (H5F_t*, hid_t dxpl_id, const uint8_t*);
static herr_t H5O_shared_encode (H5F_t*, uint8_t*, const void*);
@@ -44,8 +46,8 @@ static herr_t H5O_shared_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hboo
static herr_t H5O_shared_link(H5F_t *f, hid_t dxpl_id, const void *_mesg);
static herr_t H5O_shared_pre_copy_file(H5F_t *file_src, const H5O_msg_class_t *type,
void *mesg_src, hbool_t *deleted, const H5O_copy_t *cpy_info, void *_udata);
-static void *H5O_shared_copy_file(H5F_t *file_src, void *native_src,
- H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata);
+static void *H5O_shared_copy_file(H5F_t *file_src, const H5O_msg_class_t *mesg_type,
+ void *native_src, H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata);
static herr_t H5O_shared_debug (H5F_t*, hid_t dxpl_id, const void*, FILE*, int, int);
/* This message derives from H5O message class */
@@ -63,17 +65,22 @@ const H5O_msg_class_t H5O_MSG_SHARED[1] = {{
H5O_shared_link, /*link method */
NULL, /*get share method */
NULL, /*set share method */
+ NULL, /*is shared method */
H5O_shared_pre_copy_file, /* pre copy native value to file */
H5O_shared_copy_file, /* copy native value to file */
NULL, /* post copy native value to file */
H5O_shared_debug /*debug method */
}};
-/* Old version, with full symbol table entry as link for object header sharing */
+/* First version, with full symbol table entry as link for object header sharing */
#define H5O_SHARED_VERSION_1 1
-/* New version, with just address of object as link for object header sharing */
-#define H5O_SHARED_VERSION 2
+/* Older version, with just address of object as link for object header sharing */
+#define H5O_SHARED_VERSION_2 2
+
+/* Newest version, which recognizes messages that are stored in the heap */
+#define H5O_SHARED_VERSION_3 3
+#define H5O_SHARED_VERSION H5O_SHARED_VERSION_3
/*-------------------------------------------------------------------------
@@ -100,6 +107,10 @@ const H5O_msg_class_t H5O_MSG_SHARED[1] = {{
void *
H5O_shared_read(H5F_t *f, hid_t dxpl_id, H5O_shared_t *shared, const H5O_msg_class_t *type, void *mesg)
{
+ haddr_t fheap_addr;
+ H5HF_t *fheap = NULL;
+ unsigned char *buf=NULL; /* Pointer to raw message in heap */
+ void * native_mesg = NULL; /* Only used for messages shared in heap */
void *ret_value = NULL; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_shared_read)
@@ -109,12 +120,65 @@ H5O_shared_read(H5F_t *f, hid_t dxpl_id, H5O_shared_t *shared, const H5O_msg_cla
HDassert(shared);
HDassert(type);
- /* Get the shared message */
- ret_value = H5O_read_real(&(shared->oloc), type, 0, mesg, dxpl_id);
+ /* This message could have a heap ID (SOHM) or the address of an object
+ * header on disk (named datatype)
+ */
+ HDassert(shared->flags != H5O_NOT_SHARED);
+
+ if(shared->flags & H5O_SHARED_IN_HEAP_FLAG )
+ {
+ size_t buf_size;
+
+ if((fheap_addr = H5SM_get_fheap_addr(f, type->id, dxpl_id)) == HADDR_UNDEF)
+ HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, NULL, "can't get fheap address for shared messages")
+
+ if(NULL == (fheap =H5HF_open(f, dxpl_id, fheap_addr)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, NULL, "unable to open fractal heap")
+
+ if(H5HF_get_obj_len(fheap, dxpl_id, &(shared->u.heap_id), &buf_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, NULL, "can't get message size from fractal heap.")
+
+ /* Allocate buffer */
+ if(NULL == (buf = HDmalloc(buf_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+ if(H5HF_read(fheap, dxpl_id, &(shared->u.heap_id), buf) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "can't read message from fractal heap.")
+
+ /* Decode the message */
+ if(NULL == (native_mesg = H5O_decode(f, dxpl_id, buf, type->id)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "can't decode shared message.")
+
+ /* Make sure that this message is labeled as shared */
+ assert(type->set_share);
+ if(((type->set_share)(f, native_mesg, shared)) < 0)
+ HGOTO_ERROR (H5E_OHDR, H5E_CANTINIT, NULL, "unable to set sharing information")
+
+ ret_value = H5O_copy(type->id, native_mesg, mesg);
+ }
+ else
+ {
+ HDassert(shared->flags & H5O_COMMITTED_FLAG);
+ /* Get the shared message from an object header*/
+ if(NULL == (ret_value = H5O_read_real(&(shared->u.oloc), type, 0, mesg, dxpl_id)))
+ HGOTO_ERROR (H5E_OHDR, H5E_READERROR, NULL, "unable to read message")
+ }
+
+ /* Mark the message as shared */
if(type->set_share && (type->set_share)(f, ret_value, shared) < 0)
HGOTO_ERROR (H5E_OHDR, H5E_CANTINIT, NULL, "unable to set sharing information")
done:
+ if(buf)
+ HDfree(buf);
+
+ if(native_mesg)
+ H5O_free(type->id, native_mesg);
+
+ if(fheap)
+ if(H5HF_close(fheap, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "can't close fractal heap")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_shared_read() */
@@ -147,6 +211,9 @@ H5O_shared_link_adj(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *shared, int adj
/* check args */
HDassert(f);
HDassert(shared);
+ /* JAMES
+ * NEW THOUGHT: I should increment SOHM ref count here (or in a parallel function)
+ */
/*
* The shared message is stored in some other object header.
@@ -154,10 +221,18 @@ H5O_shared_link_adj(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *shared, int adj
* new object header. Adjust the reference count on that
* object header.
*/
- if(shared->oloc.file->shared != f->shared)
- HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "interfile hard links are not allowed")
- if((ret_value = H5O_link(&(shared->oloc), adjust, dxpl_id)) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared object link count")
+ if(shared->flags & H5O_COMMITTED_FLAG)
+ {
+ if(shared->u.oloc.file->shared != f->shared)
+ HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "interfile hard links are not allowed")
+ if((ret_value = H5O_link(&(shared->u.oloc), adjust, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared object link count")
+ }
+ else
+ {
+ HDassert(shared->flags & H5O_SHARED_IN_HEAP_FLAG);
+ ret_value = 1; /* JAMES temp refcount*/
+ }
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -185,7 +260,7 @@ static void *
H5O_shared_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *buf)
{
H5O_shared_t *mesg = NULL;
- unsigned flags, version;
+ unsigned version;
void *ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_shared_decode)
@@ -200,11 +275,21 @@ H5O_shared_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *buf)
/* Version */
version = *buf++;
- if(version != H5O_SHARED_VERSION_1 && version != H5O_SHARED_VERSION)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for shared object message")
-
- /* Get the shared information flags */
- flags = *buf++; /* Unused currently */
+ if(version < H5O_SHARED_VERSION_1 || version > H5O_SHARED_VERSION)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for shared object message")
+
+ /* Get the shared information flags
+ * Flags are unused before version 3.
+ */ /* JAMES: double-check that this is endian-portable */
+ if(version >= H5O_SHARED_VERSION_2)
+ {
+ mesg->flags = *buf++;
+ }
+ else
+ {
+ mesg->flags = H5O_COMMITTED_FLAG;
+ buf++;
+ }
/* Skip reserved bytes (for version 1) */
if(version == H5O_SHARED_VERSION_1)
@@ -212,12 +297,33 @@ H5O_shared_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *buf)
/* Body */
if(version == H5O_SHARED_VERSION_1)
- H5G_obj_ent_decode(f, &buf, &(mesg->oloc));
- else {
- HDassert(version == H5O_SHARED_VERSION);
- H5F_addr_decode(f, &buf, &(mesg->oloc.addr));
- mesg->oloc.file = f;
- } /* end else */
+ {
+ H5G_obj_ent_decode(f, &buf, &(mesg->u.oloc));
+ }
+ else if (version >= H5O_SHARED_VERSION_2)
+ {
+ /* If this message is in the heap, copy a heap ID.
+ * Otherwise, it is a named datatype, so copy an H5O_loc_t.
+ */
+ if(mesg->flags & H5O_SHARED_IN_HEAP_FLAG)
+ {
+ HDassert(version >= H5O_SHARED_VERSION_3 );
+ HDmemcpy(&(mesg->u.heap_id), buf, (size_t) H5SM_FHEAP_ID_LEN);
+ }
+ else
+ {
+ /* The H5O_COMMITTED_FLAG should be set if this message
+ * is from an older version before the flag existed.
+ */
+ if(version < H5O_SHARED_VERSION_3)
+ mesg->flags = H5O_COMMITTED_FLAG;
+
+ HDassert(mesg->flags & H5O_COMMITTED_FLAG);
+
+ H5F_addr_decode(f, &buf, &(mesg->u.oloc.addr));
+ mesg->u.oloc.file = f;
+ }
+ }
/* Set return value */
ret_value = mesg;
@@ -252,6 +358,7 @@ static herr_t
H5O_shared_encode (H5F_t *f, uint8_t *buf/*out*/, const void *_mesg)
{
const H5O_shared_t *mesg = (const H5O_shared_t *)_mesg;
+ unsigned version;
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_shared_encode)
@@ -260,10 +367,36 @@ H5O_shared_encode (H5F_t *f, uint8_t *buf/*out*/, const void *_mesg)
HDassert(buf);
HDassert(mesg);
+ /* JAMES: shouldn't be necessary. */
+ HDmemset(buf, 0, sizeof( H5O_shared_size(f, mesg)));
+
/* Encode */
- *buf++ = H5O_SHARED_VERSION;
- *buf++ = 0; /* No flags currently */
- H5F_addr_encode(f, &buf, mesg->oloc.addr);
+ /* If this message is shared in the heap, we need to use version 3 of the
+ * encoding and encode the SHARED_IN_HEAP flag.
+ */
+ /* JAMES: also use "use latest version" flag here */
+ if(mesg->flags & H5O_SHARED_IN_HEAP_FLAG) {
+ version = H5O_SHARED_VERSION;
+ }
+ else {
+ HDassert(mesg->flags & H5O_COMMITTED_FLAG);
+ version = H5O_SHARED_VERSION_2; /* version 1 is no longer used */
+ }
+
+ *buf++ = version;
+ *buf++ = (unsigned) mesg->flags;
+
+ /* Encode either the heap ID of the message or the address of the
+ * object header that holds it.
+ */
+ if(mesg->flags & H5O_SHARED_IN_HEAP_FLAG)
+ {
+ HDmemcpy(buf, &(mesg->u.heap_id), (size_t) H5SM_FHEAP_ID_LEN);
+ }
+ else
+ {
+ H5F_addr_encode(f, &buf, mesg->u.oloc.addr);
+ }
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_shared_encode() */
@@ -302,7 +435,19 @@ H5O_shared_copy(const void *_mesg, void *_dest, unsigned UNUSED update_flags)
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
/* copy */
- *dest = *mesg;
+ dest->flags = mesg->flags;
+ if(mesg->flags & H5O_COMMITTED_FLAG)
+ {
+ H5O_loc_copy(&(dest->u.oloc), &(mesg->u.oloc), H5_COPY_DEEP);
+ }
+ else if(mesg->flags & H5O_SHARED_IN_HEAP_FLAG)
+ {
+ dest->u.heap_id= mesg->u.heap_id;
+ } else
+ {
+ /* This message's sharing information is being reset */
+ HDassert(mesg->flags == H5O_NOT_SHARED);
+ }
/* Set return value */
ret_value=dest;
@@ -327,15 +472,26 @@ done:
*-------------------------------------------------------------------------
*/
static size_t
-H5O_shared_size (const H5F_t *f, const void UNUSED *_mesg)
+H5O_shared_size (const H5F_t *f, const void *_mesg)
{
+ const H5O_shared_t *shared = (const H5O_shared_t *) _mesg;
size_t ret_value;
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_shared_size);
- ret_value = 1 + /*version */
- 1 + /*the flags field */
- H5F_SIZEOF_ADDR(f); /*sharing by another obj hdr */
+ if(shared->flags & H5O_COMMITTED_FLAG)
+ {
+ ret_value = 1 + /*version */
+ 1 + /*the flags field */
+ H5F_SIZEOF_ADDR(f); /*sharing by another obj hdr */
+ }
+ else
+ {
+ HDassert(shared->flags & H5O_SHARED_IN_HEAP_FLAG);
+ ret_value = 1 + /*version */
+ 1 + /*the flags field */
+ H5SM_FHEAP_ID_LEN; /* Shared in the heap */
+ }
FUNC_LEAVE_NOAPI(ret_value);
}
@@ -367,11 +523,24 @@ H5O_shared_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link)
assert(f);
assert(shared);
+ /*
+ * Committed datatypes increment the OH of the original message when they
+ * are written (in H5O_shared_link) and decrement it here.
+ * SOHMs in the heap behave differently; their refcount is incremented
+ * during H5SM_share when they are going to be written (in H5O_append
+ * or H5O_modify). Their refcount in the SOHM indexes still needs to
+ * be decremented when they're deleted (in H5O_shared_link_adj).
+ */
+
/* Decrement the reference count on the shared object, if requested */
if(adj_link)
if(H5O_shared_link_adj(f, dxpl_id, shared, -1)<0)
HGOTO_ERROR (H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared object link count")
+ /* JAMES */
+/* JAMES if((shared->flags & H5O_SHARED_IN_HEAP_FLAG) > 0)
+ H5O_loc_free(&(shared->oloc));
+*/
done:
FUNC_LEAVE_NOAPI(ret_value);
} /* end H5O_shared_delete() */
@@ -392,6 +561,7 @@ done:
*
*-------------------------------------------------------------------------
*/
+/* JAMES: this is where shared messages increment their links */
static herr_t
H5O_shared_link(H5F_t *f, hid_t dxpl_id, const void *_mesg)
{
@@ -404,7 +574,11 @@ H5O_shared_link(H5F_t *f, hid_t dxpl_id, const void *_mesg)
assert(f);
assert(shared);
- /* Decrement the reference count on the shared object */
+ /* JAMES_HEAP: see comment in link_adj. Unneccessary except for shared attributes, I think,
+ * and they may yet take care of themselves.
+ */
+
+ /* Increment the reference count on the shared object */
if(H5O_shared_link_adj(f,dxpl_id,shared,1)<0)
HGOTO_ERROR (H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared object link count");
@@ -428,11 +602,15 @@ done:
*-------------------------------------------------------------------------
*/
static void *
-H5O_shared_copy_file(H5F_t UNUSED *file_src, void *native_src, H5F_t *file_dst,
- hid_t dxpl_id, H5O_copy_t *cpy_info, void UNUSED *udata)
+H5O_shared_copy_file(H5F_t *file_src, const H5O_msg_class_t *mesg_type,
+ void *native_src, H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info,
+ void *udata)
{
H5O_shared_t *shared_src = (H5O_shared_t *)native_src;
- H5O_shared_t *shared_dst = NULL;
+ H5O_shared_t *shared_dst = NULL; /* The destination message if
+ * it is a shared message */
+ void *dst_mesg = NULL; /* The destination message if
+ * it's an unshared message */
void *ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_shared_copy_file)
@@ -442,25 +620,57 @@ H5O_shared_copy_file(H5F_t UNUSED *file_src, void *native_src, H5F_t *file_dst,
HDassert(file_dst);
HDassert(cpy_info);
- /* Allocate space for the destination message */
- if(NULL == (shared_dst = H5MM_malloc(sizeof(H5O_shared_t))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
-
- /* Reset group entry for new object */
- H5O_loc_reset(&(shared_dst->oloc));
- shared_dst->oloc.file = file_dst;
- /* Copy the shared object from source to destination */
- if(H5O_copy_header_map(&(shared_src->oloc), &(shared_dst->oloc), dxpl_id, cpy_info, FALSE) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy object")
-
- /* Set return value */
- ret_value = shared_dst;
+ /* Committed shared messages create a shared message at the destination
+ * and also copy the committed object that they point to.
+ * SOHMs actually write a non-shared message at the destination.
+ */
+ if(shared_src->flags & H5O_COMMITTED_FLAG)
+ {
+ /* Allocate space for the destination message */
+ if(NULL == (shared_dst = H5MM_malloc(sizeof(H5O_shared_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+ /* Reset group entry for new object */
+ H5O_loc_reset(&(shared_dst->u.oloc));
+ shared_dst->u.oloc.file = file_dst;
+
+ /* Set flags for new shared object */
+ shared_dst->flags = shared_src->flags;
+
+ /* Copy the shared object from source to destination */
+ if(H5O_copy_header_map(&(shared_src->u.oloc), &(shared_dst->u.oloc), dxpl_id, cpy_info, FALSE) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy object")
+
+ /* Set return value */
+ ret_value = shared_dst;
+ }
+ else
+ {
+ HDassert(shared_src->flags & H5O_SHARED_IN_HEAP_FLAG);
+
+ /* Read the shared message to get the original message */
+ if(NULL == (dst_mesg = H5O_shared_read(file_src, dxpl_id, shared_src, mesg_type, NULL)))
+ HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, NULL, "unable to read shared message")
+
+ if(mesg_type->copy_file) {
+ /* Copy the original, un-shared message and return it */
+ ret_value = H5O_copy_mesg_file(mesg_type, mesg_type, file_src, dst_mesg, file_dst, dxpl_id, cpy_info, udata);
+ H5MM_xfree(dst_mesg);
+ }
+ else {
+ ret_value = dst_mesg;
+ }
+ }
done:
if(!ret_value)
+ {
if(shared_dst)
H5MM_xfree(shared_dst);
+ if(dst_mesg)
+ H5MM_xfree(dst_mesg);
+ }
FUNC_LEAVE_NOAPI(ret_value)
} /* H5O_shared_copy_file() */
@@ -498,7 +708,7 @@ H5O_shared_pre_copy_file(H5F_t *file_src, const H5O_msg_class_t *type,
if(type->pre_copy_file) {
/* Go get the actual shared message */
- if((mesg_native = H5O_read_real(&(shared_src->oloc), type, 0, NULL, H5AC_dxpl_id)) == NULL)
+ if(NULL == (mesg_native = H5O_shared_read(file_src, H5AC_dxpl_id, shared_src, type, NULL)))
HGOTO_ERROR(H5E_OHDR, H5E_READERROR, FAIL, "unable to load object header")
/* Perform "pre copy" operation on messge */
@@ -536,6 +746,8 @@ H5O_shared_debug (H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *_mesg,
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_shared_debug)
+ /* JAMES_HEAP: this oughta change, too, of course. */
+
/* Check args */
HDassert(f);
HDassert(mesg);
@@ -543,12 +755,24 @@ H5O_shared_debug (H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *_mesg,
HDassert(indent >= 0);
HDassert(fwidth >= 0);
- HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
- "Sharing method",
- "Obj Hdr");
- HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
- "Object address:",
- mesg->oloc.addr);
+ if(mesg->flags & H5O_COMMITTED_FLAG)
+ {
+ HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
+ "Sharing method",
+ "Obj Hdr");
+ HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
+ "Object address:",
+ mesg->u.oloc.addr);
+ }
+ else
+ {
+ HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
+ "Sharing method",
+ "SOHM Heap");
+ HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
+ "Heap ID:",
+ mesg->u.heap_id);
+ }
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_shared_debug() */