summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2007-03-11 00:34:24 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2007-03-11 00:34:24 (GMT)
commit051ffe9d61c067549bc1dab94f9de7ea330e64db (patch)
tree36112639e4dd5b15b4a5a0f6d1faf50f6f7f1c34 /src
parent1eb19fc8959e2f4580e7d48633f42a350ca229c3 (diff)
downloadhdf5-051ffe9d61c067549bc1dab94f9de7ea330e64db.zip
hdf5-051ffe9d61c067549bc1dab94f9de7ea330e64db.tar.gz
hdf5-051ffe9d61c067549bc1dab94f9de7ea330e64db.tar.bz2
[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)
Diffstat (limited to 'src')
-rw-r--r--src/H5O.c35
-rw-r--r--src/H5Oalloc.c41
-rw-r--r--src/H5Ocache.c8
-rw-r--r--src/H5Ocopy.c23
-rw-r--r--src/H5Odbg.c14
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 */