From e6b818134e24b1d4d99a612218e0a50ffa08bd28 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Sun, 11 Mar 2007 18:15:03 -0500 Subject: [svn-r13497] Description: Move ref. count of # of links to an object out of the object header's prefix and make it a header message instead (since it's a "rare" occurence), eliminating some more space for each object in the file. Inserting this "ref. count" message exposed a flaw in the library's mechanism for locating a message to promote to another chunk and replace with a continuation message, which required some additional work to fix. It's still not completely robust, but it's working for more cases now and detects failures robustly. Reduced the minimum size of an object header chunk to just enough to contain a header message prefix and continuation message. Tested on: FreeBSD/32 6.2 (duty) --- MANIFEST | 1 + src/H5O.c | 34 ++- src/H5Oalloc.c | 209 +++++++++++------ src/H5Ocache.c | 61 +++-- src/H5Ocopy.c | 68 +++++- src/H5Opkg.h | 9 +- src/H5Oprivate.h | 8 + src/H5Orefcount.c | 324 ++++++++++++++++++++++++++ src/Makefile.am | 3 +- src/Makefile.in | 5 +- test/objcopy.c | 4 +- test/stab.c | 8 +- test/tattr.c | 88 +++---- test/tfile.c | 2 +- tools/testfiles/h5copytst.out.ls | 68 +++--- tools/testfiles/h5mkgrp_nested.ls | 4 +- tools/testfiles/h5mkgrp_nested_latest.ls | 4 +- tools/testfiles/h5mkgrp_nested_mult.ls | 8 +- tools/testfiles/h5mkgrp_nested_mult_latest.ls | 8 +- tools/testfiles/h5mkgrp_several.ls | 4 +- tools/testfiles/h5mkgrp_several_latest.ls | 4 +- tools/testfiles/h5mkgrp_single.ls | 2 +- tools/testfiles/h5mkgrp_single_latest.ls | 2 +- 23 files changed, 710 insertions(+), 218 deletions(-) create mode 100644 src/H5Orefcount.c diff --git a/MANIFEST b/MANIFEST index 806dd35..d457145 100644 --- a/MANIFEST +++ b/MANIFEST @@ -608,6 +608,7 @@ ./src/H5Opline.c ./src/H5Oprivate.h ./src/H5Opublic.h +./src/H5Orefcount.c ./src/H5Osdspace.c ./src/H5Oshared.c ./src/H5Oshared.h diff --git a/src/H5O.c b/src/H5O.c index d2ff41d..5f3e507 100644 --- a/src/H5O.c +++ b/src/H5O.c @@ -103,6 +103,7 @@ const H5O_msg_class_t *const H5O_msg_class_g[] = { H5O_MSG_BTREEK, /*0x0013 Non-default v1 B-tree 'K' values */ H5O_MSG_DRVINFO, /*0x0014 Driver info settings */ H5O_MSG_AINFO, /*0x0015 Attribute information */ + H5O_MSG_REFCOUNT, /*0x0016 Object's ref. count */ }; /* Header object ID to class mapping */ @@ -989,8 +990,7 @@ H5O_link(const H5O_loc_t *loc, int adjust, hid_t dxpl_id) HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "no write intent on file") /* get header */ - if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, - NULL, NULL, H5AC_WRITE))) + if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE))) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header") /* adjust link count */ @@ -1033,6 +1033,36 @@ H5O_link(const H5O_loc_t *loc, int adjust, hid_t dxpl_id) oh_flags |= H5AC__DIRTIED_FLAG; } /* end if */ + /* Check for operations on refcount message */ + if(oh->version > H5O_VERSION_1) { + /* Check if the object has a refcount message already */ + if(oh->has_refcount_msg) { + /* Check for removing refcount message */ + if(oh->nlink <= 1) { + if(H5O_msg_remove_real(loc->file, oh, H5O_MSG_REFCOUNT, H5O_ALL, NULL, NULL, TRUE, dxpl_id) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete refcount message") + oh->has_refcount_msg = FALSE; + } /* end if */ + /* Update refcount message with new link count */ + else { + H5O_refcount_t refcount = oh->nlink; + + if(H5O_msg_write_real(loc->file, dxpl_id, oh, H5O_MSG_REFCOUNT, H5O_MSG_FLAG_DONTSHARE, 0, &refcount) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update refcount message") + } /* end else */ + } /* end if */ + else { + /* Check for adding refcount message to object */ + if(oh->nlink > 1) { + H5O_refcount_t refcount = oh->nlink; + + if(H5O_msg_append_real(loc->file, dxpl_id, oh, H5O_MSG_REFCOUNT, H5O_MSG_FLAG_DONTSHARE, 0, &refcount) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to create new refcount message") + oh->has_refcount_msg = TRUE; + } /* end if */ + } /* end else */ + } /* end if */ + /* Set return value */ ret_value = oh->nlink; diff --git a/src/H5Oalloc.c b/src/H5Oalloc.c index b03a774..ce20a27 100644 --- a/src/H5Oalloc.c +++ b/src/H5Oalloc.c @@ -632,6 +632,15 @@ done: * * SIZE need not be aligned. * + * Note: The algorithm for finding a message to replace with a + * continuation message is still fairly limited. It's possible + * that two (or more) messages smaller than a continuation message + * might occupy a chunk and need to be moved in order to make + * room for the continuation message. + * + * Also, we aren't checking for NULL messages in front of another + * message right now... + * * Return: Success: Index number of the null message for the * new chunk. The null message will be at * least SIZE bytes not counting the message @@ -651,11 +660,20 @@ H5O_alloc_new_chunk(H5F_t *f, H5O_t *oh, size_t size) { + /* Struct for storing information about "best" messages to allocate from */ + typedef struct { + int msgno; /* Index in message array */ + size_t gap_size; /* Size of any "gap" in the chunk immediately after message */ + size_t null_size; /* Size of any null message in the chunk immediately after message */ + size_t total_size; /* Total size of "available" space around message */ + unsigned null_msgno; /* Message index of null message immediately after message */ + } alloc_info; + + H5O_mesg_t *curr_msg; /* Pointer to current message to operate on */ size_t cont_size; /*continuation message size */ - int found_null = (-1); /*best fit null message */ - int found_attr = (-1); /*best fit attribute message */ - int found_link = (-1); /*best fit link message */ - int found_other = (-1); /*best fit other message */ + int found_null = (-1); /* Best fit null message */ + alloc_info found_attr = {-1, 0, 0, 0, 0}; /* Best fit attribute message */ + alloc_info found_other = {-1, 0, 0, 0, 0}; /* Best fit other message */ unsigned idx; /*message number */ uint8_t *p = NULL; /*ptr into new chunk */ H5O_cont_t *cont = NULL; /*native continuation message */ @@ -677,81 +695,114 @@ 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!). * */ cont_size = H5O_ALIGN_OH(oh, H5F_SIZEOF_ADDR(f) + H5F_SIZEOF_SIZE(f)); - for(u = 0; u < oh->nmesgs; u++) { - int msg_id = oh->mesg[u].type->id; /* Temp. copy of message type ID */ + for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) { + if(curr_msg->type->id == H5O_NULL_ID) { + if(cont_size == curr_msg->raw_size) { + found_null = u; + break; + } /* end if */ + else if(curr_msg->raw_size > cont_size && + (found_null < 0 || curr_msg->raw_size < oh->mesg[found_null].raw_size)) + found_null = u; + } /* end if */ + else if(curr_msg->type->id == H5O_CONT_ID) { + /* Don't consider continuation messages (for now) */ + } /* end if */ + else { + unsigned msg_chunkno = curr_msg->chunkno; /* Chunk that the message is in */ + uint8_t *end_chunk_data = (oh->chunk[msg_chunkno].image + oh->chunk[msg_chunkno].size) - (H5O_SIZEOF_CHKSUM_OH(oh) + oh->chunk[msg_chunkno].gap); /* End of message data in chunk */ + uint8_t *end_msg = curr_msg->raw + curr_msg->raw_size; /* End of current message */ + size_t gap_size = 0; /* Size of gap after current message */ + size_t null_size = 0; /* Size of NULL message after current message */ + unsigned null_msgno; /* Index of NULL message after current message */ + size_t total_size; /* Total size of available space "around" current message */ + + /* Check if the message is the last one in the chunk */ + if(end_msg == end_chunk_data) + gap_size = oh->chunk[msg_chunkno].gap; + else { + H5O_mesg_t *tmp_msg; /* Temp. pointer to message to operate on */ + unsigned v; /* Local index variable */ + + /* Check for null message after this message, in same chunk */ + for(v = 0, tmp_msg = &oh->mesg[0]; v < oh->nmesgs; v++, tmp_msg++) { + if(tmp_msg->type->id == H5O_NULL_ID && (tmp_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh)) == end_msg) { + null_msgno = v; + null_size = H5O_SIZEOF_MSGHDR_OH(oh) + tmp_msg->raw_size; + break; + } /* end if */ - if(H5O_NULL_ID == msg_id) { - if(cont_size == oh->mesg[u].raw_size) { - found_null = u; - break; - } else if(oh->mesg[u].raw_size >= cont_size && - (found_null < 0 || - oh->mesg[u].raw_size < oh->mesg[found_null].raw_size)) { - found_null = u; - } - } else if(H5O_CONT_ID == msg_id) { - /*don't consider continuation messages */ - } else if(H5O_ATTR_ID == msg_id) { - if(oh->mesg[u].raw_size >= cont_size && - (found_attr < 0 || - oh->mesg[u].raw_size < oh->mesg[found_attr].raw_size)) - found_attr = u; - } else if(H5O_LINK_ID == msg_id) { - if(oh->mesg[u].raw_size >= cont_size && - (found_link < 0 || - oh->mesg[u].raw_size < oh->mesg[found_link].raw_size)) - found_link = u; - } else { - if(oh->mesg[u].raw_size >= cont_size && - (found_other < 0 || - oh->mesg[u].raw_size < oh->mesg[found_other].raw_size)) - found_other = u; - } /* end else */ + /* XXX: Should also check for NULL message in front of current message... */ + + } /* end for */ + } /* end else */ + + /* Add up current message's total available space */ + total_size = curr_msg->raw_size + gap_size + null_size; + + /* Check if message is large enough to hold continuation info */ + if(total_size >= cont_size) { + if(curr_msg->type->id == H5O_ATTR_ID) { + if(found_attr.msgno < 0 || total_size < found_attr.total_size) { + found_attr.msgno = u; + found_attr.gap_size = gap_size; + found_attr.null_size = null_size; + found_attr.total_size = total_size; + found_attr.null_msgno = null_msgno; + } /* end if */ + } /* end if */ + else { + if(found_other.msgno < 0 || total_size < found_other.total_size) { + found_other.msgno = u; + found_other.gap_size = gap_size; + found_other.null_size = null_size; + found_other.total_size = total_size; + found_other.null_msgno = null_msgno; + } /* end if */ + } /* end else */ + } /* end if */ + } /* end else */ } /* end for */ - HDassert(found_null >= 0 || found_attr >= 0 || found_link >= 0 || found_other >= 0); + if(found_null < 0 && found_attr.msgno < 0 && found_other.msgno < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, "unable to locate message to move") /* * If we must move some other message to make room for the null * message, then make sure the new chunk has enough room for that * other message. * - * Move link messages first, then other messages, and attributes - * only as a last resort. + * Move other messages first, and attributes only as a last resort. * */ if(found_null < 0) { - if(found_link >= 0) - found_other = found_link; - - if(found_other < 0) + if(found_other.msgno < 0) found_other = found_attr; - HDassert(found_other >= 0); - size += H5O_SIZEOF_MSGHDR_OH(oh) + oh->mesg[found_other].raw_size; + HDassert(found_other.msgno >= 0); + size += H5O_SIZEOF_MSGHDR_OH(oh) + oh->mesg[found_other.msgno].raw_size; } /* end if */ /* + * The total chunk size must include the requested space plus enough + * for the message header. This must be at least some minimum and + * aligned propertly. + */ + size = MAX(H5O_MIN_SIZE, size + H5O_SIZEOF_MSGHDR_OH(oh)); + HDassert(size == H5O_ALIGN_OH(oh, size)); + + /* * The total chunk size must include enough space for the checksum * on the chunk and the continuation chunk magic #. (which are only present * in later versions of the object header) */ size += H5O_SIZEOF_CHKHDR_OH(oh); - /* - * The total chunk size must include the requested space plus enough - * for the message header. This must be at least some minimum and a - * multiple of the alignment size. - */ - size = MAX(H5O_MIN_SIZE, size + H5O_SIZEOF_MSGHDR_OH(oh)); - HDassert(size == H5O_ALIGN_OH(oh, size)); - /* allocate space in file to hold the new chunk */ new_chunk_addr = H5MF_alloc(f, H5FD_MEM_OHDR, dxpl_id, (hsize_t)size); if(HADDR_UNDEF == new_chunk_addr) @@ -806,22 +857,51 @@ H5O_alloc_new_chunk(H5F_t *f, null_msg->type = H5O_MSG_NULL; null_msg->dirty = TRUE; null_msg->native = NULL; - null_msg->raw = oh->mesg[found_other].raw; - null_msg->raw_size = oh->mesg[found_other].raw_size; - null_msg->chunkno = oh->mesg[found_other].chunkno; + null_msg->raw = oh->mesg[found_other.msgno].raw; + null_msg->raw_size = oh->mesg[found_other.msgno].raw_size; + null_msg->chunkno = oh->mesg[found_other.msgno].chunkno; - /* Copy the message to move to its new location */ + /* Copy the message to move (& its prefix) to its new location */ /* (Chunk is already dirty, no need to mark it) */ - HDmemcpy(p, oh->mesg[found_other].raw - H5O_SIZEOF_MSGHDR_OH(oh), - oh->mesg[found_other].raw_size + H5O_SIZEOF_MSGHDR_OH(oh)); + HDmemcpy(p, oh->mesg[found_other.msgno].raw - H5O_SIZEOF_MSGHDR_OH(oh), + oh->mesg[found_other.msgno].raw_size + H5O_SIZEOF_MSGHDR_OH(oh)); - /* Switch message to point to new location */ - oh->mesg[found_other].raw = p + H5O_SIZEOF_MSGHDR_OH(oh); - oh->mesg[found_other].chunkno = chunkno; + /* Switch moved message to point to new location */ + oh->mesg[found_other.msgno].raw = p + H5O_SIZEOF_MSGHDR_OH(oh); + oh->mesg[found_other.msgno].chunkno = chunkno; /* Account for copied message in new chunk */ - p += H5O_SIZEOF_MSGHDR_OH(oh) + oh->mesg[found_other].raw_size; - size -= H5O_SIZEOF_MSGHDR_OH(oh) + oh->mesg[found_other].raw_size; + p += H5O_SIZEOF_MSGHDR_OH(oh) + oh->mesg[found_other.msgno].raw_size; + size -= H5O_SIZEOF_MSGHDR_OH(oh) + oh->mesg[found_other.msgno].raw_size; + + /* Add any available space after the message to move to the new null message */ + if(found_other.gap_size > 0) { + /* Absorb a gap after the moved message */ + HDassert(oh->chunk[null_msg->chunkno].gap == found_other.gap_size); + null_msg->raw_size += found_other.gap_size; + oh->chunk[null_msg->chunkno].gap = 0; + } /* end if */ + else if(found_other.null_size > 0) { + H5O_mesg_t *old_null_msg = &oh->mesg[found_other.null_msgno]; /* Pointer to NULL message to eliminate */ + + /* Absorb a null message after the moved message */ + HDassert((null_msg->raw + null_msg->raw_size) == (old_null_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh))); + null_msg->raw_size += found_other.null_size; + + /* Release any information/memory for message */ + H5O_msg_free_mesg(old_null_msg); + + /* Remove null message from list of messages */ + if(found_other.null_msgno < (oh->nmesgs - 1)) + HDmemmove(old_null_msg, old_null_msg + 1, ((oh->nmesgs - 1) - found_other.null_msgno) * sizeof(H5O_mesg_t)); + + /* Decrement # of messages */ + /* (Don't bother reducing size of message array for now -QAK) */ + oh->nmesgs--; + + /* Adjust message index for new NULL message */ + found_null--; + } /* end if */ } /* end if */ HDassert(found_null >= 0); @@ -832,8 +912,7 @@ H5O_alloc_new_chunk(H5F_t *f, oh->mesg[idx].dirty = TRUE; oh->mesg[idx].native = NULL; oh->mesg[idx].raw = p + H5O_SIZEOF_MSGHDR_OH(oh); - oh->mesg[idx].raw_size = size - - (H5O_SIZEOF_CHKHDR_OH(oh) + H5O_SIZEOF_MSGHDR_OH(oh)); + oh->mesg[idx].raw_size = size - (H5O_SIZEOF_CHKHDR_OH(oh) + H5O_SIZEOF_MSGHDR_OH(oh)); oh->mesg[idx].chunkno = chunkno; /* Initialize the continuation information */ diff --git a/src/H5Ocache.c b/src/H5Ocache.c index 142d23f..2a76526 100644 --- a/src/H5Ocache.c +++ b/src/H5Ocache.c @@ -44,8 +44,8 @@ /* Set the object header size to speculatively read in */ /* (needs to be more than the object header prefix size to work at all and - * should be larger than the default dataset object header to save the - * extra I/O operations) */ + * should be larger than the largest object type's default object header + * size to save the extra I/O operations) */ #define H5O_SPEC_READ_SIZE 512 @@ -283,28 +283,10 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1, /* Number of messages (to allocate initially) */ nmesgs = 1; - } /* end if */ - else { - /* Version */ - oh->version = *p++; - if(H5O_VERSION_1 != oh->version) - HGOTO_ERROR(H5E_OHDR, H5E_VERSION, NULL, "bad object header version number") - - /* Flags */ - oh->flags = H5O_CRT_OHDR_FLAGS_DEF; - - /* Reserved */ - p++; - - /* Number of messages */ - UINT16DECODE(p, nmesgs); - } /* end else */ - /* Link count */ - UINT32DECODE(p, oh->nlink); + /* Number of links to object (unless overridden by refcount message) */ + oh->nlink = 1; - /* Version-specific fields */ - if(oh->version > H5O_VERSION_1) { /* Time fields */ if(oh->flags & H5O_HDR_STORE_TIMES) { UINT32DECODE(p, oh->atime); @@ -348,6 +330,23 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1, } /* end switch */ } /* end if */ else { + /* Version */ + oh->version = *p++; + if(H5O_VERSION_1 != oh->version) + HGOTO_ERROR(H5E_OHDR, H5E_VERSION, NULL, "bad object header version number") + + /* Flags */ + oh->flags = H5O_CRT_OHDR_FLAGS_DEF; + + /* Reserved */ + p++; + + /* Number of messages */ + UINT16DECODE(p, nmesgs); + + /* Link count */ + UINT32DECODE(p, oh->nlink); + /* Reset unused time fields */ oh->atime = oh->mtime = oh->ctime = oh->btime = 0; @@ -592,6 +591,21 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1, chunk_addr = cont->addr; chunk_size = cont->size; } /* end if */ + /* Check if next message to examine is a ref. count message */ + else if(H5O_REFCOUNT_ID == oh->mesg[curmesg].type->id) { + H5O_refcount_t *refcount; + + /* Decode ref. count message */ + HDassert(oh->version > H5O_VERSION_1); + refcount = (H5O_refcount_t *)(H5O_MSG_REFCOUNT->decode)(f, dxpl_id, 0, oh->mesg[curmesg].raw); + + /* Save 'native' form of ref. count message */ + oh->mesg[curmesg].native = refcount; + + /* Set object header values */ + oh->has_refcount_msg = TRUE; + oh->nlink = *refcount; + } /* end if */ } /* end for */ } /* end while */ @@ -681,9 +695,6 @@ H5O_assert(oh); /* Flags */ *p++ = oh->flags; - /* Link count */ - UINT32ENCODE(p, oh->nlink); - /* Time fields */ if(oh->flags & H5O_HDR_STORE_TIMES) { UINT32ENCODE(p, oh->atime); diff --git a/src/H5Ocopy.c b/src/H5Ocopy.c index ee2a63e..ec51f00 100644 --- a/src/H5Ocopy.c +++ b/src/H5Ocopy.c @@ -295,12 +295,15 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, 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 */ + size_t orig_dst_msgs; /* Original # of messages in dest. object */ 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 */ size_t dst_oh_size; /* Total size of the destination OH */ + size_t dst_oh_null; /* Size of the null message to add to destination OH */ + unsigned dst_oh_gap; /* Size of the gap in chunk #0 of destination OH */ uint8_t *current_pos; /* Current position in destination image */ size_t msghdr_size; hbool_t shared; /* Whether copy_file callback created a shared message */ @@ -535,6 +538,27 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, oh_dst->flags |= H5O_HDR_CHUNK0_2; } /* end if */ + /* Check if the chunk's data portion is too small */ + dst_oh_gap = dst_oh_null = 0; + if(dst_oh_size < H5O_MIN_SIZE) { + size_t delta = (H5O_MIN_SIZE - dst_oh_size); /* Delta in chunk size needed */ + + /* Sanity check */ + HDassert((oh_dst->flags & H5O_HDR_CHUNK0_SIZE) == H5O_HDR_CHUNK0_1); + + /* Determine whether to create gap or NULL message */ + if(delta < H5O_SIZEOF_MSGHDR_OH(oh_dst)) + dst_oh_gap = delta; + else + dst_oh_null = delta; + + /* Increase destination object header size */ + dst_oh_size += delta; + + /* Sanity check */ + HDassert(dst_oh_size <= 255); + } /* end if */ + /* Add in destination's object header size now */ dst_oh_size += H5O_SIZEOF_HDR(oh_dst); @@ -550,7 +574,7 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, /* Set dest. chunk information */ oh_dst->chunk[0].dirty = TRUE; oh_dst->chunk[0].size = dst_oh_size; - oh_dst->chunk[0].gap = 0; + oh_dst->chunk[0].gap = dst_oh_gap; /* Set up raw pointers and copy messages that didn't need special * treatment. This has to happen after the destination header has been @@ -568,7 +592,7 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, HDmemcpy(current_pos, H5O_HDR_MAGIC, (size_t)H5O_SIZEOF_MAGIC); current_pos += H5O_SIZEOF_HDR(oh_dst) - H5O_SIZEOF_CHKSUM_OH(oh_dst); - /* Copy each message that wasn't dirtied above */ + /* Loop through destination messages, updating their "raw" info */ null_msgs = 0; for(mesgno = 0; mesgno < oh_dst->nmesgs; mesgno++) { /* Skip any deleted or NULL messages in the source unless the @@ -585,17 +609,43 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, mesg_src = &(oh_src->mesg[mesgno + null_msgs]); mesg_dst = &(oh_dst->mesg[mesgno]); - if(!mesg_dst->dirty) { + /* Copy each message that wasn't dirtied above */ + 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); - } /* end if */ + HDmemcpy(current_pos, mesg_src->raw - msghdr_size, msghdr_size + mesg_src->raw_size); + + /* Set message's raw pointer to destination chunk's new "image" */ mesg_dst->raw = current_pos + msghdr_size; + + /* Move to location where next message should go */ current_pos += mesg_dst->raw_size + msghdr_size; } /* end for */ + /* Save this in case more messages are added during NULL message checking */ + orig_dst_msgs = oh_dst->nmesgs; + + /* Check if we need to add a NULL message to this header */ + if(dst_oh_null > 0) { + unsigned null_idx; /* Index of new NULL message */ + + /* Make sure we have enough space for new NULL message */ + if(oh_dst->nmesgs + 1 > oh_dst->alloc_nmesgs) + if(H5O_alloc_msgs(oh_dst, (size_t)1) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate more space for messages") + + /* Create null message for [rest of] space in new chunk */ + /* (account for chunk's magic # & checksum) */ + null_idx = oh_dst->nmesgs++; + oh_dst->mesg[null_idx].type = H5O_MSG_NULL; + oh_dst->mesg[null_idx].dirty = TRUE; + oh_dst->mesg[null_idx].native = NULL; + oh_dst->mesg[null_idx].raw = current_pos + msghdr_size; + oh_dst->mesg[null_idx].raw_size = dst_oh_null - msghdr_size; + oh_dst->mesg[null_idx].chunkno = 0; + } /* end if */ + /* 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); + HDassert(current_pos + dst_oh_gap + dst_oh_null + 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)); @@ -620,7 +670,7 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, * object header for destination object */ null_msgs = 0; - for(mesgno = 0; mesgno < oh_dst->nmesgs; mesgno++) { + for(mesgno = 0; mesgno < orig_dst_msgs; mesgno++) { /* Skip any deleted or NULL messages in the source unless the * preserve_null flag is set */ @@ -657,7 +707,7 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, /* Indicate that the destination address will no longer be locked */ addr_map->is_locked = FALSE; - /* Increment object header's reference count, if any descendents have created links to link to this object */ + /* Increment object header's reference count, if any descendents have created links to this object */ if(addr_map->inc_ref_count) { H5_CHECK_OVERFLOW(addr_map->inc_ref_count, hsize_t, unsigned); oh_dst->nlink += (unsigned)addr_map->inc_ref_count; diff --git a/src/H5Opkg.h b/src/H5Opkg.h index 0eed076..68a286d 100644 --- a/src/H5Opkg.h +++ b/src/H5Opkg.h @@ -29,8 +29,8 @@ /* Object header macros */ #define H5O_NMESGS 8 /*initial number of messages */ #define H5O_NCHUNKS 2 /*initial number of chunks */ -#define H5O_MIN_SIZE 32 /*min obj header data size */ -#define H5O_MSG_TYPES 22 /* # of types of messages */ +#define H5O_MIN_SIZE 22 /* Min. obj header data size (must be big enough for a message prefix and a continuation message) */ +#define H5O_MSG_TYPES 23 /* # of types of messages */ #define H5O_MAX_CRT_ORDER_IDX 65535 /* Max. creation order index value */ /* Versions of object header structure */ @@ -109,7 +109,6 @@ (H5O_SIZEOF_MAGIC + /*magic number */ \ 1 + /*version number */ \ 1 + /*flags */ \ - 4 + /*reference count */ \ (((O)->flags & H5O_HDR_STORE_TIMES) ? ( \ 4 + /*access time */ \ 4 + /*modification time */ \ @@ -247,6 +246,7 @@ struct H5O_t { size_t sizeof_addr; /* Size of file addresses */ /* Object information (stored) */ + hbool_t has_refcount_msg; /* Whether the object has a ref. count message */ unsigned nlink; /*link count */ uint8_t version; /*version number */ uint8_t flags; /*flags */ @@ -434,6 +434,9 @@ H5_DLLVAR const H5O_msg_class_t H5O_MSG_DRVINFO[1]; /* Attribute Information Message. (0x0015) */ H5_DLLVAR const H5O_msg_class_t H5O_MSG_AINFO[1]; +/* Reference Count Message. (0x0016) */ +H5_DLLVAR const H5O_msg_class_t H5O_MSG_REFCOUNT[1]; + /* * Object header "object" types diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index eca29e2..60d7a1d 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -135,6 +135,7 @@ typedef struct H5O_copy_t { #define H5O_BTREEK_ID 0x0013 /* v1 B-tree 'K' values message. */ #define H5O_DRVINFO_ID 0x0014 /* Driver info message. */ #define H5O_AINFO_ID 0x0015 /* Attribute info message. */ +#define H5O_REFCOUNT_ID 0x0016 /* Reference count message. */ /* Shared object message flags. @@ -429,6 +430,13 @@ typedef struct H5O_ainfo_t { haddr_t name_bt2_addr; /* Address of v2 B-tree for indexing names of "dense" attributes */ } H5O_ainfo_t; +/* + * Reference Count Message. + * (Contains # of links to object, if >1) + * (Data structure in memory) + */ +typedef uint32_t H5O_refcount_t; + /* Typedef for iteration operations */ typedef herr_t (*H5O_operator_t)(const void *mesg/*in*/, unsigned idx, diff --git a/src/H5Orefcount.c b/src/H5Orefcount.c new file mode 100644 index 0000000..8f49b8c --- /dev/null +++ b/src/H5Orefcount.c @@ -0,0 +1,324 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5Orefcount.c + * Mar 10 2007 + * Quincey Koziol + * + * Purpose: Object ref. count messages. + * + *------------------------------------------------------------------------- + */ + +#define H5O_PACKAGE /*suppress error about including H5Opkg */ + +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5FLprivate.h" /* Free lists */ +#include "H5Opkg.h" /* Object headers */ + + +/* PRIVATE PROTOTYPES */ +static void *H5O_refcount_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p); +static herr_t H5O_refcount_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg); +static void *H5O_refcount_copy(const void *_mesg, void *_dest); +static size_t H5O_refcount_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg); +static herr_t H5O_refcount_free(void *_mesg); +static herr_t H5O_refcount_pre_copy_file(H5F_t *file_src, const void *mesg_src, + hbool_t *deleted, const H5O_copy_t *cpy_info, void *udata); +static herr_t H5O_refcount_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, + FILE * stream, int indent, int fwidth); + +/* This message derives from H5O message class */ +const H5O_msg_class_t H5O_MSG_REFCOUNT[1] = {{ + H5O_REFCOUNT_ID, /*message id number */ + "refcount", /*message name for debugging */ + sizeof(H5O_refcount_t), /*native message size */ + FALSE, /* messages are sharable? */ + H5O_refcount_decode, /*decode message */ + H5O_refcount_encode, /*encode message */ + H5O_refcount_copy, /*copy the native value */ + H5O_refcount_size, /*size of symbol table entry */ + NULL, /*default reset method */ + H5O_refcount_free, /* free method */ + NULL, /* file delete method */ + NULL, /* link method */ + NULL, /*set share method */ + NULL, /*can share method */ + H5O_refcount_pre_copy_file, /* pre copy native value to file */ + NULL, /* copy native value to file */ + NULL, /* post copy native value to file */ + NULL, /* get creation index */ + NULL, /* set creation index */ + H5O_refcount_debug /*debug the message */ +}}; + +/* Current version of ref. count information */ +#define H5O_REFCOUNT_VERSION 0 + +/* Declare a free list to manage the H5O_refcount_t struct */ +H5FL_DEFINE_STATIC(H5O_refcount_t); + + +/*------------------------------------------------------------------------- + * Function: H5O_refcount_decode + * + * Purpose: Decode a message and return a pointer to a newly allocated one. + * + * Return: Success: Ptr to new message in native form. + * Failure: NULL + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Mar 10 2007 + * + *------------------------------------------------------------------------- + */ +static void * +H5O_refcount_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags, + const uint8_t *p) +{ + H5O_refcount_t *refcount = NULL; /* Reference count */ + void *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_refcount_decode) + + /* check args */ + HDassert(f); + HDassert(p); + + /* Version of message */ + if(*p++ != H5O_REFCOUNT_VERSION) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for message") + + /* Allocate space for message */ + if(NULL == (refcount = H5FL_MALLOC(H5O_refcount_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* Get ref. count for object */ + UINT32DECODE(p, *refcount) + + /* Set return value */ + ret_value = refcount; + +done: + if(ret_value == NULL && refcount != NULL) + H5FL_FREE(H5O_refcount_t, refcount); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_refcount_decode() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_refcount_encode + * + * Purpose: Encodes a message. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Mar 10 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_refcount_encode(H5F_t *f, hbool_t UNUSED disable_shared, uint8_t *p, const void *_mesg) +{ + const H5O_refcount_t *refcount = (const H5O_refcount_t *)_mesg; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_refcount_encode) + + /* check args */ + HDassert(f); + HDassert(p); + HDassert(refcount); + + /* Message version */ + *p++ = H5O_REFCOUNT_VERSION; + + /* Object's ref. count */ + UINT32ENCODE(p, *refcount); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_refcount_encode() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_refcount_copy + * + * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if + * necessary. + * + * Return: Success: Ptr to _DEST + * Failure: NULL + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Mar 10 2007 + * + *------------------------------------------------------------------------- + */ +static void * +H5O_refcount_copy(const void *_mesg, void *_dest) +{ + const H5O_refcount_t *refcount = (const H5O_refcount_t *)_mesg; + H5O_refcount_t *dest = (H5O_refcount_t *) _dest; + void *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_refcount_copy) + + /* check args */ + HDassert(refcount); + if(!dest && NULL == (dest = H5FL_MALLOC(H5O_refcount_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* copy */ + *dest = *refcount; + + /* Set return value */ + ret_value = dest; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_refcount_copy() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_refcount_size + * + * Purpose: Returns the size of the raw message in bytes not counting + * the message type or size fields, but only the data fields. + * This function doesn't take into account alignment. + * + * Return: Success: Message data size in bytes without alignment. + * Failure: zero + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Mar 10 2007 + * + *------------------------------------------------------------------------- + */ +static size_t +H5O_refcount_size(const H5F_t *f, hbool_t UNUSED disable_shared, const void *_mesg) +{ + const H5O_refcount_t *refcount = (const H5O_refcount_t *)_mesg; + size_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_refcount_size) + + /* Set return value */ + ret_value = 1 /* Version */ + + 4; /* Ref. count */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_refcount_size() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_refcount_free + * + * Purpose: Free's the message + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, March 10, 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_refcount_free(void *mesg) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_refcount_free) + + HDassert(mesg); + + H5FL_FREE(H5O_refcount_t, mesg); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_refcount_free() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_refcount_pre_copy_file + * + * Purpose: Perform any necessary actions before copying message between + * files. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Saturday, March 10, 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_refcount_pre_copy_file(H5F_t UNUSED *file_src, const void UNUSED *native_src, + hbool_t *deleted, const H5O_copy_t *cpy_info, void UNUSED *udata) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_refcount_pre_copy_file) + + /* check args */ + HDassert(deleted); + HDassert(cpy_info); + + /* Always delete this message when copying objects between files. Let + * the copy routine set the correct ref. count. + */ + *deleted = TRUE; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_refcount_pre_copy_file() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_refcount_debug + * + * Purpose: Prints debugging info for a message. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Mar 6 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_refcount_debug(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *_mesg, FILE * stream, + int indent, int fwidth) +{ + const H5O_refcount_t *refcount = (const H5O_refcount_t *) _mesg; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_refcount_debug) + + /* check args */ + HDassert(f); + HDassert(refcount); + HDassert(stream); + HDassert(indent >= 0); + HDassert(fwidth >= 0); + + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "Number of links:", (unsigned)*refcount); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_refcount_debug() */ + diff --git a/src/Makefile.am b/src/Makefile.am index 8375f3a1..ced4713 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -67,7 +67,8 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5Ofill.c H5Oginfo.c \ H5Olayout.c \ H5Olinfo.c H5Olink.c H5Omessage.c H5Omtime.c \ - H5Oname.c H5Onull.c H5Opline.c H5Osdspace.c H5Oshared.c H5Ostab.c \ + H5Oname.c H5Onull.c H5Opline.c H5Orefcount.c \ + H5Osdspace.c H5Oshared.c H5Ostab.c \ H5Oshmesg.c H5Otest.c \ H5P.c H5Pacpl.c H5Pdcpl.c H5Pdxpl.c H5Pfapl.c H5Pfcpl.c H5Pfmpl.c \ H5Pgcpl.c \ diff --git a/src/Makefile.in b/src/Makefile.in index bc614d6..1c1bb6e 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -105,7 +105,7 @@ am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \ H5Obtreek.lo H5Ocache.lo H5Ocont.lo H5Ocopy.lo H5Odbg.lo \ H5Odrvinfo.lo H5Odtype.lo H5Oefl.lo H5Ofill.lo H5Oginfo.lo \ H5Olayout.lo H5Olinfo.lo H5Olink.lo H5Omessage.lo H5Omtime.lo \ - H5Oname.lo H5Onull.lo H5Opline.lo H5Osdspace.lo H5Oshared.lo \ + H5Oname.lo H5Onull.lo H5Opline.lo H5Orefcount.lo H5Osdspace.lo H5Oshared.lo \ H5Ostab.lo H5Oshmesg.lo H5Otest.lo H5P.lo H5Pacpl.lo \ H5Pdcpl.lo H5Pdxpl.lo H5Pfapl.lo H5Pfcpl.lo H5Pfmpl.lo \ H5Pgcpl.lo H5Plapl.lo H5Plcpl.lo H5Pocpl.lo H5Pocpypl.lo \ @@ -426,7 +426,7 @@ libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5Ofill.c H5Oginfo.c \ H5Olayout.c \ H5Olinfo.c H5Olink.c H5Omessage.c H5Omtime.c \ - H5Oname.c H5Onull.c H5Opline.c H5Osdspace.c H5Oshared.c H5Ostab.c \ + H5Oname.c H5Onull.c H5Opline.c H5Orefcount.c H5Osdspace.c H5Oshared.c H5Ostab.c \ H5Oshmesg.c H5Otest.c \ H5P.c H5Pacpl.c H5Pdcpl.c H5Pdxpl.c H5Pfapl.c H5Pfcpl.c H5Pfmpl.c \ H5Pgcpl.c \ @@ -694,6 +694,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Oname.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Onull.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Opline.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Orefcount.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Osdspace.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Oshared.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Oshmesg.Plo@am__quote@ diff --git a/test/objcopy.c b/test/objcopy.c index 71cd247..8cc1027 100755 --- a/test/objcopy.c +++ b/test/objcopy.c @@ -1255,11 +1255,11 @@ compare_groups(hid_t gid, hid_t gid2, hid_t pid, int depth, unsigned copy_flags) * of messages hasn't increased. */ if(H5O_COPY_PRESERVE_NULL_FLAG & copy_flags) { - if(objstat.ohdr.nmesgs != objstat2.ohdr.nmesgs); + if(objstat.ohdr.nmesgs != objstat2.ohdr.nmesgs) + ; else if(objstat.ohdr.nmesgs < objstat2.ohdr.nmesgs) TEST_ERROR } - if(1 != objstat2.ohdr.nchunks) TEST_ERROR } /* end if */ /* Get link info */ diff --git a/test/stab.c b/test/stab.c index adf9803..73e1645 100644 --- a/test/stab.c +++ b/test/stab.c @@ -427,9 +427,9 @@ lifecycle(hid_t fapl) /* Check that the object header is only one chunk and the space has been allocated correctly */ if(H5Gget_objinfo(gid, ".", FALSE, &obj_stat) < 0) TEST_ERROR #ifdef H5_HAVE_LARGE_HSIZET - if(obj_stat.ohdr.size != 163) TEST_ERROR + if(obj_stat.ohdr.size != 159) TEST_ERROR #else /* H5_HAVE_LARGE_HSIZET */ - if(obj_stat.ohdr.size != 143) TEST_ERROR + if(obj_stat.ohdr.size != 139) TEST_ERROR #endif /* H5_HAVE_LARGE_HSIZET */ if(obj_stat.ohdr.free != 0) TEST_ERROR if(obj_stat.ohdr.nmesgs != 6) TEST_ERROR @@ -453,9 +453,9 @@ lifecycle(hid_t fapl) /* Check that the object header is still one chunk and the space has been allocated correctly */ if(H5Gget_objinfo(gid, ".", FALSE, &obj_stat) < 0) TEST_ERROR #ifdef H5_HAVE_LARGE_HSIZET - if(obj_stat.ohdr.size != 163) TEST_ERROR + if(obj_stat.ohdr.size != 159) TEST_ERROR #else /* H5_HAVE_LARGE_HSIZET */ - if(obj_stat.ohdr.size != 143) TEST_ERROR + if(obj_stat.ohdr.size != 139) TEST_ERROR #endif /* H5_HAVE_LARGE_HSIZET */ if(obj_stat.ohdr.free != 92) TEST_ERROR if(obj_stat.ohdr.nmesgs != 3) TEST_ERROR diff --git a/test/tattr.c b/test/tattr.c index 897b713..d9ce186 100644 --- a/test/tattr.c +++ b/test/tattr.c @@ -6259,16 +6259,6 @@ test_attr_shared_write(hid_t fcpl, hid_t fapl) ret = H5Pclose(my_fcpl); CHECK(ret, FAIL, "H5Pclose"); - /* Commit datatype to file */ - if(test_shared == 2) { - ret = H5Tcommit(fid, TYPE1_NAME, attr_tid); - CHECK(ret, FAIL, "H5Tcommit"); - - /* Close attribute's datatype */ - ret = H5Tclose(attr_tid); - CHECK(ret, FAIL, "H5Tclose"); - } /* end switch */ - /* Close file */ ret = H5Fclose(fid); CHECK(ret, FAIL, "H5Fclose"); @@ -6283,10 +6273,10 @@ test_attr_shared_write(hid_t fcpl, hid_t fapl) fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl); CHECK(fid, FAIL, "H5Fopen"); - /* Re-open attribute datatype as necessary */ + /* Commit datatype to file */ if(test_shared == 2) { - attr_tid = H5Topen(fid, TYPE1_NAME); - CHECK(attr_tid, FAIL, "H5Topen"); + ret = H5Tcommit(fid, TYPE1_NAME, attr_tid); + CHECK(ret, FAIL, "H5Tcommit"); } /* end if */ /* Set up to query the object creation properties */ @@ -6466,6 +6456,12 @@ test_attr_shared_write(hid_t fcpl, hid_t fapl) ret = H5Gunlink(fid, DSET2_NAME); CHECK(ret, FAIL, "H5Gunlink"); + /* Unlink committed datatype */ + if(test_shared == 2) { + ret = H5Gunlink(fid, TYPE1_NAME); + CHECK(ret, FAIL, "H5Gunlink"); + } /* end if */ + /* Check on attribute storage status */ ret = H5F_get_sohm_mesg_count_test(fid, H5O_ATTR_ID, &mesg_count); CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test"); @@ -6588,16 +6584,6 @@ test_attr_shared_rename(hid_t fcpl, hid_t fapl) ret = H5Pclose(my_fcpl); CHECK(ret, FAIL, "H5Pclose"); - /* Commit datatype to file */ - if(test_shared == 2) { - ret = H5Tcommit(fid, TYPE1_NAME, attr_tid); - CHECK(ret, FAIL, "H5Tcommit"); - - /* Close attribute's datatype */ - ret = H5Tclose(attr_tid); - CHECK(ret, FAIL, "H5Tclose"); - } /* end switch */ - /* Close file */ ret = H5Fclose(fid); CHECK(ret, FAIL, "H5Fclose"); @@ -6612,10 +6598,10 @@ test_attr_shared_rename(hid_t fcpl, hid_t fapl) fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl); CHECK(fid, FAIL, "H5Fopen"); - /* Re-open attribute datatype as necessary */ + /* Commit datatype to file */ if(test_shared == 2) { - attr_tid = H5Topen(fid, TYPE1_NAME); - CHECK(attr_tid, FAIL, "H5Topen"); + ret = H5Tcommit(fid, TYPE1_NAME, attr_tid); + CHECK(ret, FAIL, "H5Tcommit"); } /* end if */ /* Set up to query the object creation properties */ @@ -6911,6 +6897,12 @@ test_attr_shared_rename(hid_t fcpl, hid_t fapl) ret = H5Gunlink(fid, DSET2_NAME); CHECK(ret, FAIL, "H5Gunlink"); + /* Unlink committed datatype */ + if(test_shared == 2) { + ret = H5Gunlink(fid, TYPE1_NAME); + CHECK(ret, FAIL, "H5Gunlink"); + } /* end if */ + /* Check on attribute storage status */ ret = H5F_get_sohm_mesg_count_test(fid, H5O_ATTR_ID, &mesg_count); CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test"); @@ -7032,16 +7024,6 @@ test_attr_shared_delete(hid_t fcpl, hid_t fapl) ret = H5Pclose(my_fcpl); CHECK(ret, FAIL, "H5Pclose"); - /* Commit datatype to file */ - if(test_shared == 2) { - ret = H5Tcommit(fid, TYPE1_NAME, attr_tid); - CHECK(ret, FAIL, "H5Tcommit"); - - /* Close attribute's datatype */ - ret = H5Tclose(attr_tid); - CHECK(ret, FAIL, "H5Tclose"); - } /* end switch */ - /* Close file */ ret = H5Fclose(fid); CHECK(ret, FAIL, "H5Fclose"); @@ -7056,10 +7038,10 @@ test_attr_shared_delete(hid_t fcpl, hid_t fapl) fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl); CHECK(fid, FAIL, "H5Fopen"); - /* Re-open attribute datatype as necessary */ + /* Commit datatype to file */ if(test_shared == 2) { - attr_tid = H5Topen(fid, TYPE1_NAME); - CHECK(attr_tid, FAIL, "H5Topen"); + ret = H5Tcommit(fid, TYPE1_NAME, attr_tid); + CHECK(ret, FAIL, "H5Tcommit"); } /* end if */ /* Set up to query the object creation properties */ @@ -7278,6 +7260,12 @@ test_attr_shared_delete(hid_t fcpl, hid_t fapl) ret = H5Gunlink(fid, DSET2_NAME); CHECK(ret, FAIL, "H5Gunlink"); + /* Unlink committed datatype */ + if(test_shared == 2) { + ret = H5Gunlink(fid, TYPE1_NAME); + CHECK(ret, FAIL, "H5Gunlink"); + } /* end if */ + /* Check on attribute storage status */ ret = H5F_get_sohm_mesg_count_test(fid, H5O_ATTR_ID, &mesg_count); CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test"); @@ -7399,16 +7387,6 @@ test_attr_shared_unlink(hid_t fcpl, hid_t fapl) ret = H5Pclose(my_fcpl); CHECK(ret, FAIL, "H5Pclose"); - /* Commit datatype to file */ - if(test_shared == 2) { - ret = H5Tcommit(fid, TYPE1_NAME, attr_tid); - CHECK(ret, FAIL, "H5Tcommit"); - - /* Close attribute's datatype */ - ret = H5Tclose(attr_tid); - CHECK(ret, FAIL, "H5Tclose"); - } /* end switch */ - /* Close file */ ret = H5Fclose(fid); CHECK(ret, FAIL, "H5Fclose"); @@ -7423,10 +7401,10 @@ test_attr_shared_unlink(hid_t fcpl, hid_t fapl) fid = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl); CHECK(fid, FAIL, "H5Fopen"); - /* Re-open attribute datatype as necessary */ + /* Commit datatype to file */ if(test_shared == 2) { - attr_tid = H5Topen(fid, TYPE1_NAME); - CHECK(attr_tid, FAIL, "H5Topen"); + ret = H5Tcommit(fid, TYPE1_NAME, attr_tid); + CHECK(ret, FAIL, "H5Tcommit"); } /* end if */ /* Set up to query the object creation properties */ @@ -7631,6 +7609,12 @@ test_attr_shared_unlink(hid_t fcpl, hid_t fapl) ret = H5Gunlink(fid, DSET1_NAME); CHECK(ret, FAIL, "H5Gunlink"); + /* Unlink committed datatype */ + if(test_shared == 2) { + ret = H5Gunlink(fid, TYPE1_NAME); + CHECK(ret, FAIL, "H5Gunlink"); + } /* end if */ + /* Check on attribute storage status */ ret = H5F_get_sohm_mesg_count_test(fid, H5O_ATTR_ID, &mesg_count); CHECK(ret, FAIL, "H5F_get_sohm_mesg_count_test"); diff --git a/test/tfile.c b/test/tfile.c index 34a304b..91cfa58 100644 --- a/test/tfile.c +++ b/test/tfile.c @@ -1247,7 +1247,7 @@ test_file_freespace(void) free_space = H5Fget_freespace(file); CHECK(free_space, FAIL, "H5Fget_freespace"); #ifdef H5_HAVE_LARGE_HSIZET - VERIFY(free_space, 2368, "H5Fget_freespace"); + VERIFY(free_space, 2376, "H5Fget_freespace"); #else /* H5_HAVE_LARGE_HSIZET */ VERIFY(free_space, 588, "H5Fget_freespace"); /* XXX: fix me */ #endif /* H5_HAVE_LARGE_HSIZET */ diff --git a/tools/testfiles/h5copytst.out.ls b/tools/testfiles/h5copytst.out.ls index 1e8cd16..378aa0f 100644 --- a/tools/testfiles/h5copytst.out.ls +++ b/tools/testfiles/h5copytst.out.ls @@ -6,7 +6,7 @@ Opened "../testfiles/h5copytst.out.h5" with sec2 driver. Location: 1:90344 Links: 1 /A/B1 Group - Location: 1:91056 + Location: 1:91048 Links: 1 /A/B1/simple Dataset {6/6} Location: 1:90216 @@ -15,50 +15,50 @@ Opened "../testfiles/h5copytst.out.h5" with sec2 driver. Storage:
Type: 32-bit little-endian integer /A/B2 Group - Location: 1:94600 + Location: 1:94584 Links: 1 /A/B2/simple2 Dataset {6/6} - Location: 1:94472 + Location: 1:94456 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX Storage:
Type: 32-bit little-endian integer /C Group - Location: 1:97816 + Location: 1:97792 Links: 1 /C/D Group - Location: 1:98528 + Location: 1:98496 Links: 1 /C/D/simple Dataset {6/6} - Location: 1:97688 + Location: 1:97664 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX Storage:
Type: 32-bit little-endian integer /E Group - Location: 1:103960 + Location: 1:103920 Links: 1 /E/F Group - Location: 1:113216 + Location: 1:103960 Links: 1 /E/F/grp_dsets Group - Location: 1:100648 + Location: 1:100608 Links: 1 /E/F/grp_dsets/chunk Dataset {6/6} - Location: 1:102784 + Location: 1:102744 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX Chunks: {2} 8 bytes Storage:
Type: 32-bit little-endian integer /E/F/grp_dsets/compact Dataset {6/6} - Location: 1:103240 + Location: 1:103200 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX Storage:
Type: 32-bit little-endian integer /E/F/grp_dsets/compound Dataset {2/2} - Location: 1:103376 + Location: 1:103336 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX Storage:
@@ -67,7 +67,7 @@ Opened "../testfiles/h5copytst.out.h5" with sec2 driver. "str2" +20 20-byte null-terminated ASCII string } 40 bytes /E/F/grp_dsets/compressed Dataset {6/6} - Location: 1:103592 + Location: 1:103552 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX Chunks: {2} 8 bytes @@ -75,14 +75,14 @@ Opened "../testfiles/h5copytst.out.h5" with sec2 driver. Filter-0: deflate-1 OPT {1} Type: 32-bit little-endian integer /E/F/grp_dsets/named_vl Dataset {2/2} - Location: 1:103808 + Location: 1:103768 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX Storage:
- Type: shared-1:103760 variable length of + Type: shared-1:103720 variable length of 32-bit little-endian integer /E/F/grp_dsets/nested_vl Dataset {2/2} - Location: 1:112280 + Location: 1:112240 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX Storage:
@@ -90,43 +90,43 @@ Opened "../testfiles/h5copytst.out.h5" with sec2 driver. variable length of 32-bit little-endian integer /E/F/grp_dsets/simple Dataset {6/6} - Location: 1:112424 + Location: 1:112384 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX Storage:
Type: 32-bit little-endian integer /E/F/grp_dsets/vl Type - Location: 1:103760 + Location: 1:103720 Links: 2 - Type: shared-1:103760 variable length of + Type: shared-1:103720 variable length of 32-bit little-endian integer /G Group - Location: 1:128264 + Location: 1:128176 Links: 1 /G/H Group - Location: 1:128976 + Location: 1:128880 Links: 1 /G/H/grp_nested Group - Location: 1:115248 + Location: 1:115160 Links: 1 /G/H/grp_nested/grp_dsets Group - Location: 1:116040 + Location: 1:115952 Links: 1 /G/H/grp_nested/grp_dsets/chunk Dataset {6/6} - Location: 1:118176 + Location: 1:118088 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX Chunks: {2} 8 bytes Storage:
Type: 32-bit little-endian integer /G/H/grp_nested/grp_dsets/compact Dataset {6/6} - Location: 1:120776 + Location: 1:120688 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX Storage:
Type: 32-bit little-endian integer /G/H/grp_nested/grp_dsets/compound Dataset {2/2} - Location: 1:120912 + Location: 1:120824 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX Storage:
@@ -135,7 +135,7 @@ Opened "../testfiles/h5copytst.out.h5" with sec2 driver. "str2" +20 20-byte null-terminated ASCII string } 40 bytes /G/H/grp_nested/grp_dsets/compressed Dataset {6/6} - Location: 1:123224 + Location: 1:123136 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX Chunks: {2} 8 bytes @@ -143,14 +143,14 @@ Opened "../testfiles/h5copytst.out.h5" with sec2 driver. Filter-0: deflate-1 OPT {1} Type: 32-bit little-endian integer /G/H/grp_nested/grp_dsets/named_vl Dataset {2/2} - Location: 1:127536 + Location: 1:127448 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX Storage:
- Type: shared-1:123392 variable length of + Type: shared-1:123304 variable length of 32-bit little-endian integer /G/H/grp_nested/grp_dsets/nested_vl Dataset {2/2} - Location: 1:127664 + Location: 1:127576 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX Storage:
@@ -158,15 +158,15 @@ Opened "../testfiles/h5copytst.out.h5" with sec2 driver. variable length of 32-bit little-endian integer /G/H/grp_nested/grp_dsets/simple Dataset {6/6} - Location: 1:127808 + Location: 1:127720 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX Storage:
Type: 32-bit little-endian integer /G/H/grp_nested/grp_dsets/vl Type - Location: 1:123392 + Location: 1:123304 Links: 2 - Type: shared-1:123392 variable length of + Type: shared-1:123304 variable length of 32-bit little-endian integer /chunk Dataset {6/6} Location: 1:6216 @@ -471,7 +471,7 @@ Opened "../testfiles/h5copytst.out.h5" with sec2 driver. "str2" +20 20-byte null-terminated ASCII string } 40 bytes /simple Dataset {6/6} - Location: 1:808 + Location: 1:800 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX Storage:
diff --git a/tools/testfiles/h5mkgrp_nested.ls b/tools/testfiles/h5mkgrp_nested.ls index acc3aba..5f3d479 100644 --- a/tools/testfiles/h5mkgrp_nested.ls +++ b/tools/testfiles/h5mkgrp_nested.ls @@ -3,8 +3,8 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_nested.h5' ############################# Opened "../testfiles/h5mkgrp_nested.h5" with sec2 driver. /one Group - Location: 1:1520 + Location: 1:1504 Links: 1 /one/two Group - Location: 1:808 + Location: 1:800 Links: 1 diff --git a/tools/testfiles/h5mkgrp_nested_latest.ls b/tools/testfiles/h5mkgrp_nested_latest.ls index 320e19d..93364de 100644 --- a/tools/testfiles/h5mkgrp_nested_latest.ls +++ b/tools/testfiles/h5mkgrp_nested_latest.ls @@ -3,10 +3,10 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_nested_latest.h5' ############################# Opened "../testfiles/h5mkgrp_nested_latest.h5" with sec2 driver. /one Group - Location: 1:366 + Location: 1:358 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX /one/two Group - Location: 1:207 + Location: 1:203 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX diff --git a/tools/testfiles/h5mkgrp_nested_mult.ls b/tools/testfiles/h5mkgrp_nested_mult.ls index 162da0c..99082b6 100644 --- a/tools/testfiles/h5mkgrp_nested_mult.ls +++ b/tools/testfiles/h5mkgrp_nested_mult.ls @@ -3,14 +3,14 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_nested_mult.h5' ############################# Opened "../testfiles/h5mkgrp_nested_mult.h5" with sec2 driver. /one Group - Location: 1:1520 + Location: 1:1504 Links: 1 /one/two Group - Location: 1:808 + Location: 1:800 Links: 1 /three Group - Location: 1:3600 + Location: 1:3568 Links: 1 /three/four Group - Location: 1:2888 + Location: 1:2864 Links: 1 diff --git a/tools/testfiles/h5mkgrp_nested_mult_latest.ls b/tools/testfiles/h5mkgrp_nested_mult_latest.ls index c3a4cf1..98edd64 100644 --- a/tools/testfiles/h5mkgrp_nested_mult_latest.ls +++ b/tools/testfiles/h5mkgrp_nested_mult_latest.ls @@ -3,18 +3,18 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_nested_mult_latest.h5' ############################# Opened "../testfiles/h5mkgrp_nested_mult_latest.h5" with sec2 driver. /one Group - Location: 1:366 + Location: 1:358 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX /one/two Group - Location: 1:207 + Location: 1:203 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX /three Group - Location: 1:684 + Location: 1:668 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX /three/four Group - Location: 1:525 + Location: 1:513 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX diff --git a/tools/testfiles/h5mkgrp_several.ls b/tools/testfiles/h5mkgrp_several.ls index e71e7a5..dcbe3eb 100644 --- a/tools/testfiles/h5mkgrp_several.ls +++ b/tools/testfiles/h5mkgrp_several.ls @@ -3,8 +3,8 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_several.h5' ############################# Opened "../testfiles/h5mkgrp_several.h5" with sec2 driver. /one Group - Location: 1:808 + Location: 1:800 Links: 1 /two Group - Location: 1:1848 + Location: 1:1832 Links: 1 diff --git a/tools/testfiles/h5mkgrp_several_latest.ls b/tools/testfiles/h5mkgrp_several_latest.ls index f43e6c2..91eff51 100644 --- a/tools/testfiles/h5mkgrp_several_latest.ls +++ b/tools/testfiles/h5mkgrp_several_latest.ls @@ -3,10 +3,10 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_several_latest.h5' ############################# Opened "../testfiles/h5mkgrp_several_latest.h5" with sec2 driver. /one Group - Location: 1:207 + Location: 1:203 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX /two Group - Location: 1:366 + Location: 1:358 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX diff --git a/tools/testfiles/h5mkgrp_single.ls b/tools/testfiles/h5mkgrp_single.ls index 800b002..1f7e828 100644 --- a/tools/testfiles/h5mkgrp_single.ls +++ b/tools/testfiles/h5mkgrp_single.ls @@ -3,5 +3,5 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_single.h5' ############################# Opened "../testfiles/h5mkgrp_single.h5" with sec2 driver. /single Group - Location: 1:808 + Location: 1:800 Links: 1 diff --git a/tools/testfiles/h5mkgrp_single_latest.ls b/tools/testfiles/h5mkgrp_single_latest.ls index 72901cf..294db66 100644 --- a/tools/testfiles/h5mkgrp_single_latest.ls +++ b/tools/testfiles/h5mkgrp_single_latest.ls @@ -3,6 +3,6 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_single_latest.h5' ############################# Opened "../testfiles/h5mkgrp_single_latest.h5" with sec2 driver. /latest Group - Location: 1:207 + Location: 1:203 Links: 1 Modified: XXXX-XX-XX XX:XX:XX XXX -- cgit v0.12