From 051ffe9d61c067549bc1dab94f9de7ea330e64db Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Sat, 10 Mar 2007 19:34:24 -0500 Subject: [svn-r13492] Description: Fix mis-calculation of chunk #0 size encoding and also catch a few more places which adjust the size of chunk and have them adjust the encode flags also. Add some assertions to object header sanity checking routine. Tested on: FreeBSD/32 6.2 (duty) --- src/H5O.c | 35 ++++++++++++----------------------- src/H5Oalloc.c | 41 +++++++++++++++++++++++++++++++++++++---- src/H5Ocache.c | 8 +++++--- src/H5Ocopy.c | 23 ++++++++++++++++++++--- src/H5Odbg.c | 14 ++++++++++++++ 5 files changed, 88 insertions(+), 33 deletions(-) diff --git a/src/H5O.c b/src/H5O.c index 775ee4d..789a6ab 100644 --- a/src/H5O.c +++ b/src/H5O.c @@ -677,7 +677,7 @@ H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, hid_t ocpl_id, /* Initialize version-specific fields */ if(oh->version > H5O_VERSION_1) { - size_t tent_oh_size; /* Tentative size of object header */ + uint64_t tent_oh_size; /* Tentative size of object header */ /* Initialize all time fields with current time, if we are storing them */ if(oh->flags & H5O_HDR_STORE_TIMES) @@ -702,28 +702,12 @@ H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, hid_t ocpl_id, oh->flags |= H5O_HDR_ATTR_STORE_PHASE_CHANGE; /* Determine correct value for chunk #0 size bits */ - - /* See if only 1 byte is enough */ - tent_oh_size = H5O_SIZEOF_HDR(oh) + size_hint; - if(tent_oh_size > 255) { - uint8_t old_oh_flags = oh->flags; /* Temporary object header flags */ - - /* Need more than 1 byte, see if 2 bytes is enough */ + if(size_hint > 4294967295) + oh->flags |= H5O_HDR_CHUNK0_8; + else if(size_hint > 65535) + oh->flags |= H5O_HDR_CHUNK0_4; + else if(size_hint > 255) oh->flags |= H5O_HDR_CHUNK0_2; - tent_oh_size = H5O_SIZEOF_HDR(oh) + size_hint; - if(tent_oh_size > 65535) { - /* Need more than 2 bytes, see if 4 bytes is enough */ - oh->flags = old_oh_flags; - oh->flags |= H5O_HDR_CHUNK0_4; - tent_oh_size = H5O_SIZEOF_HDR(oh) + size_hint; - if(tent_oh_size > 4294967295) { - /* Use 8 bytes */ - /* (Should probably have check for using more than 8 bytes... :-) */ - oh->flags = old_oh_flags; - oh->flags |= H5O_HDR_CHUNK0_8; - } /* end if */ - } /* end if */ - } /* end if */ } /* end if */ else { /* Reset unused time fields */ @@ -2011,14 +1995,19 @@ H5O_get_create_plist(const H5O_loc_t *oloc, hid_t dxpl_id, H5P_genplist_t *oc_pl /* Set property values, if they were used for the object */ if(oh->version > H5O_VERSION_1) { + uint8_t ohdr_flags; /* "User-visible" object header status flags */ + /* Set attribute storage values */ if(H5P_set(oc_plist, H5O_CRT_ATTR_MAX_COMPACT_NAME, &oh->max_compact) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set max. # of compact attributes in property list") if(H5P_set(oc_plist, H5O_CRT_ATTR_MIN_DENSE_NAME, &oh->min_dense) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set min. # of dense attributes in property list") + /* Mask off non-"user visible" flags */ + ohdr_flags = oh->flags & (H5O_HDR_ATTR_CRT_ORDER_TRACKED | H5O_HDR_ATTR_CRT_ORDER_INDEXED | H5O_HDR_STORE_TIMES); + /* Set object header flags */ - if(H5P_set(oc_plist, H5O_CRT_OHDR_FLAGS_NAME, &oh->flags) < 0) + if(H5P_set(oc_plist, H5O_CRT_OHDR_FLAGS_NAME, &ohdr_flags) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set object header flags") } /* end if */ diff --git a/src/H5Oalloc.c b/src/H5Oalloc.c index 957de77..b03a774 100644 --- a/src/H5Oalloc.c +++ b/src/H5Oalloc.c @@ -468,6 +468,9 @@ H5O_alloc_extend_chunk(H5F_t *f, size_t old_size; /* Old size of chunk */ htri_t tri_result; /* Result from checking if chunk can be extended */ int extend_msg = -1;/* Index of null message to extend */ + uint8_t new_size_flags = 0; /* New chunk #0 size flags */ + hbool_t adjust_size_flags = FALSE; /* Whether to adjust the chunk #0 size flags */ + size_t extra_prfx_size = 0; /* Extra bytes added to object header prefix */ unsigned u; /* Local index variable */ htri_t ret_value = TRUE; /* return value */ @@ -506,18 +509,48 @@ H5O_alloc_extend_chunk(H5F_t *f, delta = (aligned_size + H5O_SIZEOF_MSGHDR_OH(oh)) - oh->chunk[chunkno].gap; delta = H5O_ALIGN_OH(oh, delta); + /* Check for changing the chunk #0 data size enough to need adjusting the flags */ + if(oh->version > H5O_VERSION_1 && chunkno == 0) { + uint64_t chunk0_size = oh->chunk[0].size - H5O_SIZEOF_HDR(oh); /* Size of chunk 0's data */ + + /* Check for moving from a 1-byte to a 2-byte size encoding */ + if(chunk0_size <= 255 && (chunk0_size + delta) > 255) { + extra_prfx_size = 1; + new_size_flags = H5O_HDR_CHUNK0_2; + adjust_size_flags = TRUE; + } /* end if */ + /* Check for moving from a 2-byte to a 4-byte size encoding */ + else if(chunk0_size <= 65535 && (chunk0_size + delta) > 65535) { + extra_prfx_size = 2; + new_size_flags = H5O_HDR_CHUNK0_4; + adjust_size_flags = TRUE; + } /* end if */ + /* Check for moving from a 4-byte to a 8-byte size encoding */ + else if(chunk0_size <= 4294967295 && (chunk0_size + delta) > 4294967295) { + extra_prfx_size = 4; + new_size_flags = H5O_HDR_CHUNK0_8; + adjust_size_flags = TRUE; + } /* end if */ + } /* end if */ + /* Determine whether the chunk can be extended */ tri_result = H5MF_can_extend(f, H5FD_MEM_OHDR, oh->chunk[chunkno].addr, - (hsize_t)(oh->chunk[chunkno].size), (hsize_t)delta); + (hsize_t)(oh->chunk[chunkno].size), (hsize_t)(delta + extra_prfx_size)); if(tri_result == FALSE) /* can't extend -- we are done */ HGOTO_DONE(FALSE) else if(tri_result < 0) /* error */ HGOTO_ERROR(H5E_RESOURCE, H5E_SYSTEM, FAIL, "can't tell if we can extend chunk") /* If we get this far, we should be able to extend the chunk */ - if(H5MF_extend(f, H5FD_MEM_OHDR, oh->chunk[chunkno].addr, (hsize_t)(oh->chunk[chunkno].size), (hsize_t)delta) < 0 ) + if(H5MF_extend(f, H5FD_MEM_OHDR, oh->chunk[chunkno].addr, (hsize_t)(oh->chunk[chunkno].size), (hsize_t)(delta + extra_prfx_size)) < 0 ) HGOTO_ERROR(H5E_RESOURCE, H5E_SYSTEM, FAIL, "can't extend chunk") + /* Adjust object header prefix flags */ + if(adjust_size_flags) { + oh->flags &= ~H5O_HDR_CHUNK0_SIZE; + oh->flags |= new_size_flags; + } /* end if */ + /* If we can extend an existing null message, take care of that */ if(extend_msg >= 0) { /* Adjust message size of existing null message */ @@ -548,7 +581,7 @@ H5O_alloc_extend_chunk(H5F_t *f, /* Allocate more memory space for chunk's image */ old_image = oh->chunk[chunkno].image; old_size = oh->chunk[chunkno].size; - oh->chunk[chunkno].size += delta; + oh->chunk[chunkno].size += delta + extra_prfx_size; oh->chunk[chunkno].image = H5FL_BLK_REALLOC(chunk_image, old_image, oh->chunk[chunkno].size); oh->chunk[chunkno].gap = 0; oh->chunk[chunkno].dirty = TRUE; @@ -562,7 +595,7 @@ H5O_alloc_extend_chunk(H5F_t *f, for(u = 0; u < oh->nmesgs; u++) { /* Adjust raw addresses for messages in this chunk to reflect new 'image' address */ if(oh->mesg[u].chunkno == chunkno) - oh->mesg[u].raw = oh->chunk[chunkno].image + (oh->mesg[u].raw - old_image); + oh->mesg[u].raw = oh->chunk[chunkno].image + extra_prfx_size + (oh->mesg[u].raw - old_image); /* Find continuation message which points to this chunk and adjust chunk's size */ /* (Chunk 0 doesn't have a continuation message that points to it and diff --git a/src/H5Ocache.c b/src/H5Ocache.c index 16e6278..142d23f 100644 --- a/src/H5Ocache.c +++ b/src/H5Ocache.c @@ -357,11 +357,10 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1, /* First chunk size */ UINT32DECODE(p, chunk_size); - } /* end else */ - /* Reserved, in version 1 */ - if(H5O_VERSION_1 == oh->version) + /* Reserved, in version 1 */ p += 4; + } /* end else */ /* Determine object header prefix length */ prefix_size = (size_t)(p - read_buf); @@ -702,14 +701,17 @@ H5O_assert(oh); /* First chunk size */ switch(oh->flags & H5O_HDR_CHUNK0_SIZE) { case 0: /* 1 byte size */ + HDassert(chunk0_size < 256); *p++ = chunk0_size; break; case 1: /* 2 byte size */ + HDassert(chunk0_size < 65536); UINT16ENCODE(p, chunk0_size); break; case 2: /* 4 byte size */ + HDassert(chunk0_size < 4294967296); UINT32ENCODE(p, chunk0_size); break; diff --git a/src/H5Ocopy.c b/src/H5Ocopy.c index 55ba9bf..ee2a63e 100644 --- a/src/H5Ocopy.c +++ b/src/H5Ocopy.c @@ -513,14 +513,31 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, /* Calculate how big the destination object header will be on disk. * This isn't necessarily the same size as the original. */ - dst_oh_size = H5O_SIZEOF_HDR(oh_dst); - /* Add space for messages. */ + /* Compute space for messages. */ + dst_oh_size = 0; for(mesgno = 0; mesgno < oh_dst->nmesgs; mesgno++) { dst_oh_size += H5O_SIZEOF_MSGHDR_OH(oh_dst); dst_oh_size += oh_dst->mesg[mesgno].raw_size; } /* end for */ + /* Check if we need to determine correct value for chunk #0 size bits */ + if(oh_dst->version > H5O_VERSION_1) { + /* Reset destination object header's "chunk 0 size" flags */ + oh_dst->flags &= ~H5O_HDR_CHUNK0_SIZE; + + /* Determine correct value for chunk #0 size bits */ + if(dst_oh_size > 4294967295) + oh_dst->flags |= H5O_HDR_CHUNK0_8; + else if(dst_oh_size > 65535) + oh_dst->flags |= H5O_HDR_CHUNK0_4; + else if(dst_oh_size > 255) + oh_dst->flags |= H5O_HDR_CHUNK0_2; + } /* end if */ + + /* Add in destination's object header size now */ + dst_oh_size += H5O_SIZEOF_HDR(oh_dst); + /* Allocate space for chunk in destination file */ if(HADDR_UNDEF == (oh_dst->chunk[0].addr = H5MF_alloc(oloc_dst->file, H5FD_MEM_OHDR, dxpl_id, (hsize_t)dst_oh_size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for object header") @@ -539,7 +556,6 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, * treatment. This has to happen after the destination header has been * allocated. */ - HDassert(H5O_SIZEOF_HDR(oh_src) == H5O_SIZEOF_HDR(oh_dst)); HDassert(H5O_SIZEOF_MSGHDR_OH(oh_src) == H5O_SIZEOF_MSGHDR_OH(oh_dst)); msghdr_size = H5O_SIZEOF_MSGHDR_OH(oh_src); @@ -585,6 +601,7 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, HDassert(H5F_addr_defined(addr_new)); oloc_dst->addr = addr_new; + /* Allocate space for the address mapping of the object copied */ if(NULL == (addr_map = H5FL_MALLOC(H5O_addr_map_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") diff --git a/src/H5Odbg.c b/src/H5Odbg.c index a5428c1..b4d642b 100644 --- a/src/H5Odbg.c +++ b/src/H5Odbg.c @@ -136,6 +136,20 @@ H5O_assert(const H5O_t *oh) HDassert(oh->chunk[u].gap == 0); } /* end for */ + /* Check for correct chunk #0 size flags */ + if(oh->version > H5O_VERSION_1) { + uint64_t chunk0_size = oh->chunk[0].size - H5O_SIZEOF_HDR(oh); + + if(chunk0_size <= 255) + HDassert((oh->flags & H5O_HDR_CHUNK0_SIZE) == H5O_HDR_CHUNK0_1); + else if(chunk0_size <= 65535) + HDassert((oh->flags & H5O_HDR_CHUNK0_SIZE) == H5O_HDR_CHUNK0_2); + else if(chunk0_size <= 4294967295) + HDassert((oh->flags & H5O_HDR_CHUNK0_SIZE) == H5O_HDR_CHUNK0_4); + else + HDassert((oh->flags & H5O_HDR_CHUNK0_SIZE) == H5O_HDR_CHUNK0_8); + } /* end if */ + /* Loop over all messages in object header */ for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) { /* Accumulate information, based on the type of message */ -- cgit v0.12