diff options
author | James Laird <jlaird@hdfgroup.org> | 2006-11-13 20:41:36 (GMT) |
---|---|---|
committer | James Laird <jlaird@hdfgroup.org> | 2006-11-13 20:41:36 (GMT) |
commit | b6c317f27cd150aa7bfc4e9cf275629570c9a319 (patch) | |
tree | 3413a54aec3bbebb821088a473f6ff425c3d39be /src/H5Oshared.c | |
parent | 77c265f26746359cf348437702c93c162f7022f6 (diff) | |
download | hdf5-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/H5Oshared.c')
-rw-r--r-- | src/H5Oshared.c | 334 |
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() */ |