summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/H5O.c178
-rw-r--r--src/H5Ocache.c488
-rw-r--r--src/H5Opkg.h67
3 files changed, 359 insertions, 374 deletions
diff --git a/src/H5O.c b/src/H5O.c
index 39548fb..80b963f 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -130,7 +130,7 @@ typedef struct H5O_addr_map_t {
static hid_t H5O_open_by_loc(H5G_loc_t *obj_loc, hid_t dxpl_id);
static H5O_loc_t * H5O_get_oloc(hid_t id);
-static herr_t H5O_new(H5F_t *f, hid_t dxpl_id, size_t size_hint,
+static herr_t H5O_new(H5F_t *f, hid_t dxpl_id, size_t chunk_size,
H5O_loc_t *loc/*out*/, haddr_t header);
static herr_t H5O_reset_real(const H5O_msg_class_t *type, void *native);
static void * H5O_copy_real(const H5O_msg_class_t *type, const void *mesg,
@@ -713,7 +713,7 @@ done:
* write access and should eventually be closed by calling
* H5O_close().
*
- * Return: Success: SUCCEED, the ENT argument contains
+ * Return: Success: SUCCEED, the LOC argument contains
* information about the object header,
* including its address.
* Failure: FAIL
@@ -724,10 +724,11 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_new(H5F_t *f, hid_t dxpl_id, size_t size_hint, H5O_loc_t *loc/*out*/,
+H5O_new(H5F_t *f, hid_t dxpl_id, size_t chunk_size, H5O_loc_t *loc/*out*/,
haddr_t header)
{
H5O_t *oh = NULL;
+ size_t oh_size; /* Size of initial object header */
herr_t ret_value = SUCCEED; /* return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_new)
@@ -736,49 +737,61 @@ H5O_new(H5F_t *f, hid_t dxpl_id, size_t size_hint, H5O_loc_t *loc/*out*/,
HDassert(f);
HDassert(loc);
+ /* Set up object location */
loc->file = f;
loc->addr = header;
- /* allocate the object header and fill in header fields */
+ /* Allocate the object header and fill in header fields */
if(NULL == (oh = H5FL_MALLOC(H5O_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ /* Initialize rudimentary information object object header */
oh->version = H5O_VERSION_1;
oh->nlink = 0;
- /* create the chunk list and initialize the first chunk */
+ /* Compute total size of initial object header */
+ /* (i.e. object header prefix and first chunk) */
+ oh_size = H5O_SIZEOF_HDR_OH(oh) + chunk_size;
+
+ /* Create the chunk list */
oh->nchunks = 1;
oh->alloc_nchunks = H5O_NCHUNKS;
-
if(NULL == (oh->chunk = H5FL_SEQ_MALLOC(H5O_chunk_t, (size_t)oh->alloc_nchunks)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ /* Initialize the first chunk */
oh->chunk[0].dirty = TRUE;
- oh->chunk[0].addr = loc->addr + (hsize_t)H5O_SIZEOF_HDR_OH(oh);
- oh->chunk[0].size = size_hint;
+ oh->chunk[0].addr = loc->addr;
+ oh->chunk[0].size = oh_size;
- if(NULL == (oh->chunk[0].image = H5FL_BLK_CALLOC(chunk_image, size_hint)))
+ /* Allocate enough space for the first chunk */
+ /* (including space for serializing the object header prefix */
+ if(NULL == (oh->chunk[0].image = H5FL_BLK_CALLOC(chunk_image, oh_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
- /* create the message list and initialize the first message */
+ /* Put magic # for object header in first chunk */
+ if(oh->version > H5O_VERSION_1)
+ HDmemcpy(oh->chunk[0].image, H5O_HDR_MAGIC, (size_t)H5O_SIZEOF_MAGIC);
+
+ /* Create the message list */
oh->nmesgs = 1;
oh->alloc_nmesgs = H5O_NMESGS;
-
- if(NULL == (oh->mesg = H5FL_SEQ_CALLOC(H5O_mesg_t, (size_t)oh->alloc_nmesgs)))
+ if(NULL == (oh->mesg = H5FL_SEQ_CALLOC(H5O_mesg_t, oh->alloc_nmesgs)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ /* Initialize the first message */
oh->mesg[0].type = H5O_MSG_NULL;
oh->mesg[0].dirty = TRUE;
oh->mesg[0].native = NULL;
- oh->mesg[0].raw = oh->chunk[0].image + H5O_SIZEOF_MSGHDR_OH(oh);
- oh->mesg[0].raw_size = size_hint - H5O_SIZEOF_MSGHDR_OH(oh);
+ oh->mesg[0].raw = oh->chunk[0].image + (H5O_SIZEOF_HDR_OH(oh) - H5O_SIZEOF_CHKSUM_OH(oh)) + H5O_SIZEOF_MSGHDR_OH(oh);
+ oh->mesg[0].raw_size = chunk_size - H5O_SIZEOF_MSGHDR_OH(oh);
oh->mesg[0].chunkno = 0;
- /* cache it */
+ /* Cache object header */
if(H5AC_set(f, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to cache object header")
- /* open it */
+ /* Open it */
if(H5O_open(loc) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open object header")
@@ -1819,9 +1832,11 @@ H5O_protect(H5O_loc_t *loc, hid_t dxpl_id)
HDassert(loc->file);
HDassert(H5F_addr_defined(loc->addr));
+ /* Check for write access on the file */
if(0 == (loc->file->intent & H5F_ACC_RDWR))
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, NULL, "no write intent on file")
+ /* Lock the object header into the cache */
if(NULL == (ret_value = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "unable to load object header")
@@ -1860,6 +1875,7 @@ H5O_unprotect(H5O_loc_t *loc, H5O_t *oh, hid_t dxpl_id, unsigned oh_flags)
HDassert(H5F_addr_defined(loc->addr));
HDassert(oh);
+ /* Release the object header from the cache */
if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
@@ -2153,7 +2169,7 @@ H5O_touch_oh(H5F_t *f,
} /* end if */
/* Update the message */
- *((time_t*)(oh->mesg[idx].native)) = now;
+ *((time_t *)(oh->mesg[idx].native)) = now;
/* Mark the message & object header as dirty */
oh->mesg[idx].dirty = TRUE;
@@ -2581,7 +2597,7 @@ H5O_alloc_msgs(H5O_t *oh, size_t min_alloc)
/* Initialize number of messages information */
old_alloc = oh->alloc_nmesgs;
- na = oh->alloc_nmesgs + MAX (H5O_NMESGS, min_alloc);
+ na = oh->alloc_nmesgs + MAX(oh->alloc_nmesgs, min_alloc);
/* Attempt to allocate more memory */
if(NULL == (new_mesg = H5FL_SEQ_REALLOC(H5O_mesg_t, oh->mesg, na)))
@@ -2626,8 +2642,8 @@ H5O_move_msgs_forward(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
HDassert(oh);
/* Loop until no messages packed */
- /* (Double loop is not very efficient, but it would be some extra work to add
- * a list of messages to each chunk -QAK)
+ /* (Double loop is not very efficient, but it would be some extra work to
+ * add a list of messages to each chunk -QAK)
*/
do {
H5O_mesg_t *curr_msg; /* Pointer to current message to operate on */
@@ -2643,7 +2659,7 @@ H5O_move_msgs_forward(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
/* Check if null message is not last in chunk */
chunk = &(oh->chunk[curr_msg->chunkno]);
- if((curr_msg->raw + curr_msg->raw_size) != (chunk->image + chunk->size)) {
+ if((curr_msg->raw + curr_msg->raw_size + H5O_SIZEOF_CHKSUM_OH(oh)) != (chunk->image + chunk->size)) {
H5O_mesg_t *nonnull_msg; /* Pointer to current message to operate on */
unsigned v; /* Local index variable */
@@ -2939,7 +2955,7 @@ H5O_remove_empty_chunks(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
* its not the "base" chunk), delete that chunk from object header
*/
if(H5O_NULL_ID == null_msg->type->id && null_msg->chunkno > 0 &&
- (H5O_SIZEOF_MSGHDR_OH(oh) + null_msg->raw_size) == oh->chunk[null_msg->chunkno].size) {
+ (H5O_SIZEOF_MSGHDR_OH(oh) + null_msg->raw_size + H5O_SIZEOF_CHKHDR_OH(oh)) == oh->chunk[null_msg->chunkno].size) {
H5O_mesg_t *curr_msg; /* Pointer to current message to operate on */
unsigned null_msg_no; /* Message # for null message */
unsigned deleted_chunkno; /* Chunk # to delete */
@@ -3152,17 +3168,16 @@ H5O_alloc_extend_chunk(H5F_t *f,
HDassert(chunkno < oh->nchunks);
HDassert(size > 0);
HDassert(msg_idx != NULL);
-
- if(!H5F_addr_defined(oh->chunk[chunkno].addr))
- HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, FAIL, "chunk isn't on disk")
+ HDassert(H5F_addr_defined(oh->chunk[chunkno].addr));
/* Test to see if the specified chunk ends with a null messages.
* If successful, set the index of the the null message in extend_msg.
*/
for(u = 0; u < oh->nmesgs; u++) {
/* Check for null message at end of proper chunk */
+ /* (account for possible checksum at end of chunk) */
if(oh->mesg[u].chunkno == chunkno && H5O_NULL_ID == oh->mesg[u].type->id &&
- (oh->mesg[u].raw + oh->mesg[u].raw_size == oh->chunk[chunkno].image + oh->chunk[chunkno].size)) {
+ ((oh->mesg[u].raw + oh->mesg[u].raw_size + H5O_SIZEOF_CHKSUM_OH(oh)) == oh->chunk[chunkno].image + oh->chunk[chunkno].size)) {
extend_msg = u;
break;
@@ -3370,6 +3385,13 @@ H5O_alloc_new_chunk(H5F_t *f,
} /* end if */
/*
+ * 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.
@@ -3386,8 +3408,8 @@ H5O_alloc_new_chunk(H5F_t *f,
* Create the new chunk giving it a file address.
*/
if(oh->nchunks >= oh->alloc_nchunks) {
- unsigned na = oh->alloc_nchunks + H5O_NCHUNKS;
- H5O_chunk_t *x = H5FL_SEQ_REALLOC (H5O_chunk_t, oh->chunk, (size_t)na);
+ unsigned na = MAX(H5O_NCHUNKS, oh->alloc_nchunks * 2); /* Double # of chunks allocated */
+ H5O_chunk_t *x = H5FL_SEQ_REALLOC(H5O_chunk_t, oh->chunk, (size_t)na);
if(!x)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, "memory allocation failed")
@@ -3402,6 +3424,14 @@ H5O_alloc_new_chunk(H5F_t *f,
if(NULL == (oh->chunk[chunkno].image = p = H5FL_BLK_CALLOC(chunk_image, size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, "memory allocation failed")
+ /* If this is a later version of the object header format, put the magic
+ * # at the beginning of the chunk
+ */
+ if(oh->version > H5O_VERSION_1) {
+ HDmemcpy(p, H5O_CHK_MAGIC, (size_t)H5O_SIZEOF_MAGIC);
+ p += H5O_SIZEOF_MAGIC;
+ } /* end if */
+
/*
* Make sure we have enough space for all possible new messages
* that could be generated below.
@@ -3410,10 +3440,11 @@ H5O_alloc_new_chunk(H5F_t *f,
if(H5O_alloc_msgs(oh, (size_t)3) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, "can't allocate more space for messages")
- /*
- * Describe the messages of the new chunk.
+ /* Move message (that will be replaced with continuation message)
+ * to new chunk, if necessary.
*/
if(found_null < 0) {
+ /* Create null message for space that message to copy currently occupies */
found_null = u = oh->nmesgs++;
oh->mesg[u].type = H5O_MSG_NULL;
oh->mesg[u].dirty = TRUE;
@@ -3422,22 +3453,28 @@ H5O_alloc_new_chunk(H5F_t *f,
oh->mesg[u].raw_size = oh->mesg[found_other].raw_size;
oh->mesg[u].chunkno = oh->mesg[found_other].chunkno;
- oh->mesg[found_other].dirty = TRUE;
/* Copy the message to the new location */
HDmemcpy(p + H5O_SIZEOF_MSGHDR_OH(oh),
oh->mesg[found_other].raw,
oh->mesg[found_other].raw_size);
oh->mesg[found_other].raw = p + H5O_SIZEOF_MSGHDR_OH(oh);
oh->mesg[found_other].chunkno = chunkno;
+ oh->mesg[found_other].dirty = TRUE;
+
+ /* 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;
} /* end if */
+
+ /* Create null message for [rest of] space in new chunk */
+ /* (except for chunk's magic # & checksum) */
idx = oh->nmesgs++;
oh->mesg[idx].type = H5O_MSG_NULL;
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_MSGHDR_OH(oh);
+ oh->mesg[idx].raw_size = size -
+ (H5O_SIZEOF_CHKHDR_OH(oh) + H5O_SIZEOF_MSGHDR_OH(oh));
oh->mesg[idx].chunkno = chunkno;
/*
@@ -3460,9 +3497,7 @@ H5O_alloc_new_chunk(H5F_t *f,
oh->mesg[found_null].raw_size = cont_size;
} /* end if */
- /*
- * Initialize the continuation message.
- */
+ /* Initialize the continuation message */
oh->mesg[found_null].type = H5O_MSG_CONT;
oh->mesg[found_null].dirty = TRUE;
if(NULL == (cont = H5FL_MALLOC(H5O_cont_t)))
@@ -3815,7 +3850,7 @@ H5O_delete_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
} /* end for */
/* Free main (first) object header "chunk" */
- if(H5MF_xfree(f, H5FD_MEM_OHDR, dxpl_id, (oh->chunk[0].addr - H5O_SIZEOF_HDR_OH(oh)), (hsize_t)(oh->chunk[0].size + H5O_SIZEOF_HDR_OH(oh))) < 0)
+ if(H5MF_xfree(f, H5FD_MEM_OHDR, dxpl_id, oh->chunk[0].addr, (hsize_t)oh->chunk[0].size) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free object header")
done:
@@ -3919,7 +3954,7 @@ H5O_get_info(H5O_loc_t *loc, H5O_stat_t *ostat, hid_t dxpl_id)
/* Check for this message being free space */
if(H5O_NULL_ID == curr_msg->type->id)
- free_space+= H5O_SIZEOF_MSGHDR_OH(oh) + curr_msg->raw_size;
+ free_space += H5O_SIZEOF_MSGHDR_OH(oh) + curr_msg->raw_size;
} /* end for */
/* Set the information for this object header */
@@ -4581,24 +4616,11 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
for(chunkno = 0; chunkno < oh_src->nchunks; chunkno++) {
size_t chunk_size = oh_src->chunk[chunkno].size;
- /* '0th' chunk is preceded by object header prefix */
- if(0 == chunkno) {
- size_t hdr_size;
-
- /* get the size of the file header of the destination file */
- hdr_size = H5O_SIZEOF_HDR_OH(oh_dst);
-
- /* Allocate file space for the first chunk & object header prefix */
- if(HADDR_UNDEF == (addr_new = H5MF_alloc(oloc_dst->file, H5FD_MEM_OHDR, dxpl_id, (hsize_t)hdr_size + chunk_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for object header")
-
- /* Set first chunk's address */
- oh_dst->chunk[0].addr = addr_new + (hsize_t)hdr_size;
- } /* end if */
- else {
- if(HADDR_UNDEF == (oh_dst->chunk[chunkno].addr = H5MF_alloc(oloc_dst->file, H5FD_MEM_OHDR, dxpl_id, (hsize_t)chunk_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for object header")
- } /* end else */
+ /* Allocate space for chunk in destination file */
+ if(HADDR_UNDEF == (oh_dst->chunk[chunkno].addr = H5MF_alloc(oloc_dst->file, H5FD_MEM_OHDR, dxpl_id, (hsize_t)chunk_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for object header")
+ if(chunkno == 0)
+ addr_new = oh_dst->chunk[chunkno].addr;
/* Create memory image for the new chunk */
if(NULL == (oh_dst->chunk[chunkno].image = H5FL_BLK_MALLOC(chunk_image, chunk_size)))
@@ -5234,7 +5256,6 @@ H5O_debug_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, haddr_t addr, FILE *stream, i
unsigned i, chunkno;
size_t mesg_total = 0, chunk_total = 0;
int *sequence;
- haddr_t tmp_addr;
void *(*decode)(H5F_t*, hid_t, const uint8_t*);
herr_t (*debug)(H5F_t*, hid_t, const void*, FILE*, int, int)=NULL;
herr_t ret_value = SUCCEED;
@@ -5252,15 +5273,15 @@ H5O_debug_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, haddr_t addr, FILE *stream, i
/* debug */
HDfprintf(stream, "%*sObject Header...\n", indent, "");
- HDfprintf(stream, "%*s%-*s %d\n", indent, "", fwidth,
+ HDfprintf(stream, "%*s%-*s %t\n", indent, "", fwidth,
"Dirty:",
- (int) (oh->cache_info.is_dirty));
+ oh->cache_info.is_dirty);
HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
"Version:",
oh->version);
HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
"Header size (in bytes):",
- (unsigned) H5O_SIZEOF_HDR_OH(oh));
+ (unsigned)H5O_SIZEOF_HDR_OH(oh));
HDfprintf(stream, "%*s%-*s %d\n", indent, "", fwidth,
"Number of links:",
oh->nlink);
@@ -5273,22 +5294,29 @@ H5O_debug_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, haddr_t addr, FILE *stream, i
/* debug each chunk */
for(i = 0, chunk_total = 0; i < oh->nchunks; i++) {
+ size_t chunk_size;
+
chunk_total += oh->chunk[i].size;
HDfprintf(stream, "%*sChunk %d...\n", indent, "", i);
- HDfprintf(stream, "%*s%-*s %d\n", indent + 3, "", MAX(0, fwidth - 3),
+ HDfprintf(stream, "%*s%-*s %t\n", indent + 3, "", MAX(0, fwidth - 3),
"Dirty:",
- (int) (oh->chunk[i].dirty));
+ oh->chunk[i].dirty);
HDfprintf(stream, "%*s%-*s %a\n", indent + 3, "", MAX(0, fwidth - 3),
- "Address:", oh->chunk[i].addr);
+ "Address:",
+ oh->chunk[i].addr);
- tmp_addr = addr + (hsize_t)H5O_SIZEOF_HDR_OH(oh);
- if(0 == i && H5F_addr_ne(oh->chunk[i].addr, tmp_addr))
- HDfprintf(stream, "*** WRONG ADDRESS!\n");
- HDfprintf(stream, "%*s%-*s %lu\n", indent + 3, "", MAX(0, fwidth - 3),
+ if(0 == i) {
+ if(H5F_addr_ne(oh->chunk[i].addr, addr))
+ HDfprintf(stream, "*** WRONG ADDRESS!\n");
+ chunk_size = oh->chunk[i].size - H5O_SIZEOF_HDR_OH(oh);
+ } /* end if */
+ else
+ chunk_size = oh->chunk[i].size;
+ HDfprintf(stream, "%*s%-*s %Zu\n", indent + 3, "", MAX(0, fwidth - 3),
"Size in bytes:",
- (unsigned long) (oh->chunk[i].size));
+ chunk_size);
} /* end for */
/* debug each message */
@@ -5312,9 +5340,9 @@ H5O_debug_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, haddr_t addr, FILE *stream, i
(unsigned) (oh->mesg[i].type->id),
oh->mesg[i].type->name,
sequence[oh->mesg[i].type->id]++);
- HDfprintf (stream, "%*s%-*s %d\n", indent+3, "", MAX (0, fwidth-3),
+ HDfprintf (stream, "%*s%-*s %t\n", indent+3, "", MAX (0, fwidth-3),
"Dirty:",
- (int)(oh->mesg[i].dirty));
+ oh->mesg[i].dirty);
HDfprintf (stream, "%*s%-*s %s\n", indent+3, "", MAX (0, fwidth-3),
"Shared:",
(oh->mesg[i].flags & H5O_FLAG_SHARED) ? "Yes" : "No");
@@ -5326,18 +5354,18 @@ H5O_debug_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, haddr_t addr, FILE *stream, i
"*** ADDITIONAL UNKNOWN FLAGS --->",
oh->mesg[i].flags & ~H5O_FLAG_BITS);
} /* end if */
- HDfprintf(stream, "%*s%-*s %lu bytes\n", indent+3, "", MAX(0,fwidth-3),
+ HDfprintf(stream, "%*s%-*s %Zu bytes\n", indent+3, "", MAX(0,fwidth-3),
"Raw size in obj header:",
- (unsigned long) (oh->mesg[i].raw_size));
- HDfprintf(stream, "%*s%-*s %d\n", indent + 3, "", MAX(0, fwidth - 3),
+ oh->mesg[i].raw_size);
+ HDfprintf(stream, "%*s%-*s %u\n", indent + 3, "", MAX(0, fwidth - 3),
"Chunk number:",
- (int) (oh->mesg[i].chunkno));
+ oh->mesg[i].chunkno);
chunkno = oh->mesg[i].chunkno;
if(chunkno >= oh->nchunks)
HDfprintf(stream, "*** BAD CHUNK NUMBER\n");
- HDfprintf(stream, "%*s%-*s %u\n", indent + 3, "", MAX(0, fwidth - 3),
+ HDfprintf(stream, "%*s%-*s %Zu\n", indent + 3, "", MAX(0, fwidth - 3),
"Raw data offset in chunk:",
- (unsigned) (oh->mesg[i].raw - oh->chunk[chunkno].image));
+ (size_t)(oh->mesg[i].raw - oh->chunk[chunkno].image));
/* check the size */
if((oh->mesg[i].raw + oh->mesg[i].raw_size >
diff --git a/src/H5Ocache.c b/src/H5Ocache.c
index e3ce6ac..d4e00a3 100644
--- a/src/H5Ocache.c
+++ b/src/H5Ocache.c
@@ -109,10 +109,7 @@ const H5AC_class_t H5AC_OHDR[1] = {{
herr_t
H5O_flush_msgs(H5F_t *f, H5O_t *oh)
{
- uint8_t *p; /* Temporary pointer to encode with */
- int id; /* ID of message to encode */
H5O_mesg_t *curr_msg; /* Pointer to current message being operated on */
- herr_t (*encode)(H5F_t*, uint8_t*, const void*) = NULL;
unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
@@ -125,29 +122,29 @@ H5O_flush_msgs(H5F_t *f, H5O_t *oh)
/* Encode any dirty messages */
for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) {
if(curr_msg->dirty) {
+ uint8_t *p; /* Temporary pointer to encode with */
+
+ /* Point into message's chunk's image */
p = curr_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh);
/* Encode the message prefix */
- id = curr_msg->type->id;
- UINT16ENCODE(p, id);
+ UINT16ENCODE(p, curr_msg->type->id);
HDassert(curr_msg->raw_size < H5O_MESG_MAX_SIZE);
UINT16ENCODE(p, curr_msg->raw_size);
*p++ = curr_msg->flags;
- *p++ = 0; /*reserved*/
- *p++ = 0; /*reserved*/
- *p++ = 0; /*reserved*/
+
+ /* Only encode reserved bytes for version 1 of format */
+ if(oh->version == H5O_VERSION_1) {
+ *p++ = 0; /*reserved*/
+ *p++ = 0; /*reserved*/
+ *p++ = 0; /*reserved*/
+ } /* end for */
/* Encode the message itself */
if(curr_msg->native) {
- HDassert(curr_msg->type->encode);
+ herr_t (*encode)(H5F_t*, uint8_t*, const void*);
- /* allocate file space for chunks that have none yet */
- if(H5O_CONT_ID == id && !H5F_addr_defined(((H5O_cont_t *)(curr_msg->native))->addr))
- /* We now allocate disk space on insertion, instead
- * of on flush from the cache, so this case is now an
- * error. -- JRM
- */
- HGOTO_ERROR(H5E_OHDR, H5E_SYSTEM, FAIL, "File space for message not allocated!?!")
+ HDassert(curr_msg->type->encode);
/*
* Encode the message. If the message is shared then we
@@ -178,186 +175,6 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_flush_msgs() */
-#ifdef OLD_WAY
-
-/*-------------------------------------------------------------------------
- * Function: H5O_load
- *
- * Purpose: Loads an object header from disk.
- *
- * Return: Success: Pointer to the new object header.
- *
- * Failure: NULL
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Aug 5 1997
- *
- *-------------------------------------------------------------------------
- */
-static H5O_t *
-H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
- void UNUSED * _udata2)
-{
- H5O_t *oh = NULL;
- H5O_t *ret_value;
- uint8_t buf[16], *p;
- size_t mesg_size;
- size_t hdr_size;
- unsigned id;
- int mesgno;
- unsigned curmesg = 0, nmesgs;
- unsigned chunkno;
- unsigned skipped_msgs = 0; /* Number of unknown messages skipped */
- unsigned merged_null_msgs = 0; /* Number of null messages merged together */
- haddr_t chunk_addr;
- size_t chunk_size;
- uint8_t flags;
-
- FUNC_ENTER_NOAPI(H5O_load, NULL)
-
- /* check args */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
- HDassert(!_udata1);
- HDassert(!_udata2);
-
- /* allocate ohdr and init chunk list */
- if (NULL==(oh = H5FL_CALLOC(H5O_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
-
- /* read fixed-length part of object header */
- hdr_size = H5O_SIZEOF_HDR(f);
- assert(hdr_size<=sizeof(buf));
- if (H5F_block_read(f, H5FD_MEM_OHDR, addr, hdr_size, dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header")
- p = buf;
-
- /* decode version */
- oh->version = *p++;
- if (H5O_VERSION != oh->version)
- HGOTO_ERROR(H5E_OHDR, H5E_VERSION, NULL, "bad object header version number")
-
- /* reserved */
- p++;
-
- /* decode number of messages */
- UINT16DECODE(p, nmesgs);
-
- /* decode link count */
- UINT32DECODE(p, oh->nlink);
-
- /* decode first chunk info */
- chunk_addr = addr + (hsize_t)hdr_size;
- UINT32DECODE(p, chunk_size);
-
- /* build the message array */
- oh->alloc_nmesgs = nmesgs;
- if (NULL==(oh->mesg=H5FL_SEQ_MALLOC(H5O_mesg_t,(size_t)oh->alloc_nmesgs)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
-
- /* read each chunk from disk */
- while(H5F_addr_defined(chunk_addr)) {
- /* increase chunk array size */
- if(oh->nchunks >= oh->alloc_nchunks) {
- unsigned na = oh->alloc_nchunks + H5O_NCHUNKS;
- H5O_chunk_t *x = H5FL_SEQ_REALLOC (H5O_chunk_t, oh->chunk, (size_t)na);
-
- if(!x)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- oh->alloc_nchunks = na;
- oh->chunk = x;
- } /* end if */
-
- /* read the chunk raw data */
- chunkno = oh->nchunks++;
- oh->chunk[chunkno].dirty = FALSE;
- oh->chunk[chunkno].addr = chunk_addr;
- oh->chunk[chunkno].size = chunk_size;
- if(NULL==(oh->chunk[chunkno].image = H5FL_BLK_MALLOC(chunk_image, chunk_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- if(H5F_block_read(f, H5FD_MEM_OHDR, chunk_addr, chunk_size, dxpl_id, oh->chunk[chunkno].image) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header data")
-
- /* load messages from this chunk */
- for(p = oh->chunk[chunkno].image; p < oh->chunk[chunkno].image + chunk_size; p += mesg_size) {
- UINT16DECODE(p, id);
- UINT16DECODE(p, mesg_size);
- HDassert(mesg_size == H5O_ALIGN_OH(mesg_size));
- flags = *p++;
- p += 3; /*reserved*/
-
- /* Try to detect invalidly formatted object header messages */
- if(p + mesg_size > oh->chunk[chunkno].image + chunk_size)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "corrupt object header")
-
- /* Skip header messages we don't know about */
- /* (Usually from future versions of the library */
- if(id >= NELMTS(H5O_msg_class_g) || NULL == H5O_msg_class_g[id]) {
- skipped_msgs++;
- continue;
- } /* end if */
-
- if((H5F_get_intent(f) & H5F_ACC_RDWR) &&
- H5O_NULL_ID == id && oh->nmesgs > 0 &&
- H5O_NULL_ID == oh->mesg[oh->nmesgs - 1].type->id &&
- oh->mesg[oh->nmesgs - 1].chunkno == chunkno) {
- /* combine adjacent null messages */
- mesgno = oh->nmesgs - 1;
- oh->mesg[mesgno].raw_size += H5O_SIZEOF_MSGHDR(f) + mesg_size;
- oh->mesg[mesgno].dirty = TRUE;
- merged_null_msgs++;
- } else {
- /* new message */
- if (oh->nmesgs >= nmesgs)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "corrupt object header - too many messages")
- mesgno = oh->nmesgs++;
- oh->mesg[mesgno].type = H5O_msg_class_g[id];
- oh->mesg[mesgno].dirty = FALSE;
- oh->mesg[mesgno].flags = flags;
- oh->mesg[mesgno].native = NULL;
- oh->mesg[mesgno].raw = p;
- oh->mesg[mesgno].raw_size = mesg_size;
- oh->mesg[mesgno].chunkno = chunkno;
- } /* end else */
- } /* end for */
-
- HDassert(p == oh->chunk[chunkno].image + chunk_size);
-
- /* decode next object header continuation message */
- for(chunk_addr = HADDR_UNDEF; !H5F_addr_defined(chunk_addr) && curmesg < oh->nmesgs; ++curmesg) {
- if(H5O_CONT_ID == oh->mesg[curmesg].type->id) {
- H5O_cont_t *cont;
-
- cont = (H5O_MSG_CONT->decode) (f, dxpl_id, oh->mesg[curmesg].raw);
- oh->mesg[curmesg].native = cont;
- chunk_addr = cont->addr;
- chunk_size = cont->size;
- cont->chunkno = oh->nchunks; /*the next chunk to allocate */
- } /* end if */
- } /* end for */
- } /* end while */
-
- /* Mark the object header dirty if we've merged a message */
- if(merged_null_msgs)
- oh->cache_info.is_dirty = TRUE;
-
- /* Sanity check for the correct # of messages in object header */
- if((oh->nmesgs + skipped_msgs + merged_null_msgs) != nmesgs)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "corrupt object header - too few messages")
-
- /* Set return value */
- ret_value = oh;
-
-done:
- if(!ret_value && oh) {
- if(H5O_dest(f,oh) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, NULL, "unable to destroy object header data")
- } /* end if */
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_load() */
-#else /* OLD_WAY */
/*-------------------------------------------------------------------------
* Function: H5O_load
@@ -389,8 +206,9 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
unsigned merged_null_msgs = 0; /* Number of null messages merged together */
haddr_t chunk_addr; /* Address of first chunk */
size_t chunk_size; /* Size of first chunk */
- haddr_t abs_eoa; /* Absolute end of file address */
- haddr_t rel_eoa; /* Relative end of file address */
+ haddr_t abs_eoa; /* Absolute end of file address */
+ haddr_t rel_eoa; /* Relative end of file address */
+ uint32_t prefix_chksum = 0; /* Checksum of object header prefix */
H5O_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5O_load, NULL)
@@ -420,13 +238,26 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
if(NULL == (oh = H5FL_CALLOC(H5O_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- /* Version */
- oh->version = *p++;
- if(H5O_VERSION_1 != oh->version)
- HGOTO_ERROR(H5E_OHDR, H5E_VERSION, NULL, "bad object header version number")
+ /* Check for magic number */
+ /* (indicates version 2 or later) */
+ if(!HDmemcmp(p, H5O_HDR_MAGIC, (size_t)H5O_SIZEOF_MAGIC)) {
+ /* Magic number */
+ p += H5O_SIZEOF_MAGIC;
- /* Reserved */
- p++;
+ /* Version */
+ oh->version = *p++;
+ if(H5O_VERSION_2 != oh->version)
+ HGOTO_ERROR(H5E_OHDR, H5E_VERSION, NULL, "bad object header version number")
+ } /* 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")
+
+ /* Reserved */
+ p++;
+ } /* end else */
/* Number of messages */
UINT16DECODE(p, nmesgs);
@@ -437,11 +268,18 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
/* First chunk size */
UINT32DECODE(p, chunk_size);
- /* Reserved */
- p += 4;
+ /* Reserved, in version 1 */
+ if(H5O_VERSION_1 == oh->version)
+ p += 4;
- /* Compute first chunk address */
+ /* Determine object header prefix length */
prefix_size = (size_t)(p - read_buf);
+
+ /* Compute partial checksum, for later versions of the format */
+ if(oh->version > H5O_VERSION_1)
+ prefix_chksum = H5_checksum_lookup3(read_buf, prefix_size, 0);
+
+ /* Compute first chunk address */
chunk_addr = addr + (hsize_t)prefix_size;
/* Allocate the message array */
@@ -452,11 +290,10 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
/* Read each chunk from disk */
while(H5F_addr_defined(chunk_addr)) {
unsigned chunkno; /* Current chunk's index */
- size_t mesg_size; /* Size of message read in */
/* Increase chunk array size, if necessary */
if(oh->nchunks >= oh->alloc_nchunks) {
- unsigned na = oh->alloc_nchunks + H5O_NCHUNKS;
+ unsigned na = MAX(H5O_NCHUNKS, oh->alloc_nchunks * 2); /* Double # of chunks allocated */
H5O_chunk_t *x = H5FL_SEQ_REALLOC(H5O_chunk_t, oh->chunk, (size_t)na);
if(!x)
@@ -465,43 +302,86 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
oh->chunk = x;
} /* end if */
- /* Init the chunk raw data info */
+ /* Init the chunk data info */
chunkno = oh->nchunks++;
oh->chunk[chunkno].dirty = FALSE;
- oh->chunk[chunkno].addr = chunk_addr;
- oh->chunk[chunkno].size = chunk_size;
- if(NULL == (oh->chunk[chunkno].image = H5FL_BLK_MALLOC(chunk_image, chunk_size)))
+ if(chunkno == 0) {
+ /* First chunk's 'image' includes room for the object header prefix */
+ oh->chunk[0].addr = addr;
+ oh->chunk[0].size = chunk_size + H5O_SIZEOF_HDR_OH(oh);
+ } /* end if */
+ else {
+ oh->chunk[chunkno].addr = chunk_addr;
+ oh->chunk[chunkno].size = chunk_size;
+ } /* end else */
+ if(NULL == (oh->chunk[chunkno].image = H5FL_BLK_MALLOC(chunk_image, oh->chunk[chunkno].size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- /* Check for speculative read of first chunk containing all the data needed */
- if(chunkno == 0 && (spec_read_size - prefix_size) >= chunk_size)
- HDmemcpy(oh->chunk[chunkno].image, p, chunk_size);
+ /* Handle chunk 0 as special case */
+ if(chunkno == 0) {
+ /* Check for speculative read of first chunk containing all the data needed */
+ if(spec_read_size >= oh->chunk[0].size)
+ HDmemcpy(oh->chunk[0].image, read_buf, oh->chunk[0].size);
+ else {
+ /* Copy the object header prefix into chunk 0's image */
+ HDmemcpy(oh->chunk[0].image, read_buf, prefix_size);
+
+ /* Read the chunk raw data */
+ if(H5F_block_read(f, H5FD_MEM_OHDR, chunk_addr, (oh->chunk[0].size - prefix_size),
+ dxpl_id, (oh->chunk[0].image + prefix_size)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header data")
+ } /* end else */
+
+ /* Point into chunk image to decode */
+ p = oh->chunk[0].image + prefix_size;
+ } /* end if */
else {
/* Read the chunk raw data */
- if(H5F_block_read(f, H5FD_MEM_OHDR, chunk_addr, chunk_size, dxpl_id, oh->chunk[chunkno].image) < 0)
+ if(H5F_block_read(f, H5FD_MEM_OHDR, chunk_addr, chunk_size,
+ dxpl_id, oh->chunk[chunkno].image) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header data")
+
+ /* Point into chunk image to decode */
+ p = oh->chunk[chunkno].image;
} /* end else */
- /* Load messages from this chunk */
- for(p = oh->chunk[chunkno].image; p < oh->chunk[chunkno].image + chunk_size; p += mesg_size) {
+ /* Check for magic # on chunks > 0 in later versions of the format */
+ if(chunkno > 0 && oh->version > H5O_VERSION_1) {
+ /* Magic number */
+ if(!HDmemcmp(p, H5O_CHK_MAGIC, (size_t)H5O_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "wrong object header chunk signature")
+ p += H5O_SIZEOF_MAGIC;
+ } /* end if */
+
+ /* Decode messages from this chunk */
+ while(p < (oh->chunk[chunkno].image + (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM_OH(oh)))) {
unsigned mesgno; /* Current message to operate on */
+ size_t mesg_size; /* Size of message read in */
unsigned id; /* ID (type) of current message */
uint8_t flags; /* Flags for current message */
+ /* Decode message prefix info */
UINT16DECODE(p, id);
UINT16DECODE(p, mesg_size);
HDassert(mesg_size == H5O_ALIGN_OH(oh, mesg_size));
flags = *p++;
- p += 3; /*reserved*/
+ if(oh->version == H5O_VERSION_1)
+ p += 3; /*reserved*/
/* Try to detect invalidly formatted object header messages */
- if(p + mesg_size > oh->chunk[chunkno].image + chunk_size)
+ if(p + mesg_size > oh->chunk[chunkno].image + (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM_OH(oh)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "corrupt object header")
/* Skip header messages we don't know about */
/* (Usually from future versions of the library) */
if(id >= NELMTS(H5O_msg_class_g) || NULL == H5O_msg_class_g[id]) {
+ /* Increment skipped messages counter */
skipped_msgs++;
+
+ /* Advance decode pointer past message */
+ p += mesg_size;
+
+ /* Go get next message */
continue;
} /* end if */
@@ -530,9 +410,32 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
oh->mesg[mesgno].raw_size = mesg_size;
oh->mesg[mesgno].chunkno = chunkno;
} /* end else */
- } /* end for */
- HDassert(p == oh->chunk[chunkno].image + chunk_size);
+ /* Advance decode pointer past message */
+ p += mesg_size;
+ } /* end while */
+
+ /* Check for correct checksum on chunks, in later versions of the format */
+ if(oh->version > H5O_VERSION_1) {
+ uint32_t stored_chksum; /* Checksum from file */
+ uint32_t computed_chksum; /* Checksum computed in memory */
+
+ /* Metadata checksum */
+ UINT32DECODE(p, stored_chksum);
+
+ /* Compute checksum on entire header */
+ if(chunkno == 0)
+ computed_chksum = H5_checksum_metadata(oh->chunk[chunkno].image + prefix_size, chunk_size, prefix_chksum);
+ else
+ computed_chksum = H5_checksum_metadata(oh->chunk[chunkno].image, (chunk_size - H5O_SIZEOF_CHKSUM), 0);
+
+ /* Verify checksum */
+ if(stored_chksum != computed_chksum)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "incorrect metadata checksum for object header chunk")
+ } /* end if */
+
+ /* Sanity check */
+ HDassert(p == oh->chunk[chunkno].image + oh->chunk[chunkno].size);
/* Check for another chunk to read in & parse */
for(chunk_addr = HADDR_UNDEF; !H5F_addr_defined(chunk_addr) && curmesg < oh->nmesgs; ++curmesg) {
@@ -574,7 +477,6 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_load() */
-#endif /* OLD_WAY */
/*-------------------------------------------------------------------------
@@ -591,11 +493,8 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_t *oh)
+H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t UNUSED addr, H5O_t *oh)
{
- uint8_t buf[16], *p;
- hbool_t combine = FALSE; /* Whether to combine the object header prefix & the first chunk */
- unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5O_flush, FAIL)
@@ -607,69 +506,112 @@ H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_t *oh)
/* flush */
if(oh->cache_info.is_dirty) {
+ uint8_t *p; /* Pointer to object header prefix buffer */
+ unsigned u; /* Local index variable */
+
/* Encode any dirty messages */
if(H5O_flush_msgs(f, oh) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "unable to flush object header messages")
- /* Encode header prefix */
- p = buf;
+ /* Point to raw data 'image' for first chunk, which has room for the prefix */
+ p = oh->chunk[0].image;
+
+ /* Later versions of object header prefix have different format and
+ * also require that chunk 0 always be updated, since the checksum
+ * on the entire block of memory needs to be updated if anything is
+ * modified */
+ if(oh->version > H5O_VERSION_1) {
+ size_t prefix_size; /* Length of object header prefix */
+ uint32_t prefix_chksum; /* Prefix checksum value */
+ uint32_t full_chksum; /* Full checksum value */
+ size_t raw_size; /* Size of raw data in first chunk */
- /* encode version */
- *p++ = oh->version;
+ /* Verify magic number */
+ HDassert(!HDmemcmp(oh->chunk[u].image, H5O_HDR_MAGIC, H5O_SIZEOF_MAGIC));
+ p += H5O_SIZEOF_MAGIC;
- /* reserved */
- *p++ = 0;
+ /* Version */
+ *p++ = oh->version;
- /* encode number of messages */
- UINT16ENCODE(p, oh->nmesgs);
+ /* Number of messages */
+ UINT16ENCODE(p, oh->nmesgs);
- /* encode link count */
- UINT32ENCODE(p, oh->nlink);
+ /* Link count */
+ UINT32ENCODE(p, oh->nlink);
- /* encode body size */
- UINT32ENCODE(p, oh->chunk[0].size);
+ /* Chunk size */
+ UINT32ENCODE(p, (oh->chunk[0].size - H5O_SIZEOF_HDR_OH(oh)));
- /* zero to alignment */
- HDmemset(p, 0, (size_t)(H5O_SIZEOF_HDR_OH(oh) - 12));
+ /* Determine object header prefix length */
+ prefix_size = (size_t)(p - oh->chunk[0].image);
- /* write the object header prefix */
+ /* Compute partial checksum for later */
+ /* (checksum performed in this odd way in order to accomodate
+ * reading in the header & first chunk in reasonable way)
+ */
+ prefix_chksum = H5_checksum_lookup3(oh->chunk[0].image, prefix_size, 0);
- /* Check if we can combine the object header prefix & the first chunk into one I/O operation */
- if(oh->chunk[0].dirty && (addr + H5O_SIZEOF_HDR_OH(oh)) == oh->chunk[0].addr)
- combine = TRUE;
+ /* Finish full checksum, over chunk data */
+ raw_size = oh->chunk[0].size - H5O_SIZEOF_HDR_OH(oh);
+ full_chksum = H5_checksum_metadata(p, raw_size, prefix_chksum);
+ p += raw_size;
+
+ /* Metadata checksum */
+ UINT32ENCODE(p, full_chksum);
+ HDassert((size_t)(p - oh->chunk[0].image) == oh->chunk[0].size);
+ } /* end if */
else {
- if(H5F_block_write(f, H5FD_MEM_OHDR, addr, (size_t)H5O_SIZEOF_HDR_OH(oh), dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header hdr to disk")
+ /* Version */
+ *p++ = oh->version;
+
+ /* Reserved */
+ *p++ = 0;
+
+ /* Number of messages */
+ UINT16ENCODE(p, oh->nmesgs);
+
+ /* Link count */
+ UINT32ENCODE(p, oh->nlink);
+
+ /* First chunk size */
+ UINT32ENCODE(p, (oh->chunk[0].size - H5O_SIZEOF_HDR_OH(oh)));
+
+ /* Zero to alignment */
+ HDmemset(p, 0, (size_t)(H5O_SIZEOF_HDR_OH(oh) - 12));
} /* end else */
- /* write each chunk to disk */
- for(u = 0; u < oh->nchunks; u++) {
- if(oh->chunk[u].dirty) {
- HDassert(H5F_addr_defined(oh->chunk[u].addr));
- if(u == 0 && combine) {
- /* Allocate space for the combined prefix and first chunk */
- if((p = H5FL_BLK_MALLOC(chunk_image, (H5O_SIZEOF_HDR_OH(oh) + oh->chunk[u].size))) == NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ /* Mark chunk 0 as dirty, since the object header prefix has been updated */
+ /* (this could be more sophisticated and track whether any prefix fields
+ * have been changed, which could save I/O accesses - QAK)
+ */
+ HDassert(H5F_addr_eq(addr, oh->chunk[0].addr));
+ oh->chunk[0].dirty = TRUE;
- /* Copy in the prefix */
- HDmemcpy(p, buf, (size_t)H5O_SIZEOF_HDR_OH(oh));
+ /* Write each chunk to disk, if it's dirty */
+ for(u = 0; u < oh->nchunks; u++) {
+ /* Sanity check - make certain the magic # is present */
+ if(oh->version > H5O_VERSION_1)
+ HDassert(!HDmemcmp(oh->chunk[u].image, (u == 0 ? H5O_HDR_MAGIC : H5O_CHK_MAGIC), H5O_SIZEOF_MAGIC));
- /* Copy in the first chunk */
- HDmemcpy(p + H5O_SIZEOF_HDR_OH(oh), oh->chunk[u].image, oh->chunk[u].size);
+ /* Write out chunk, if it's dirty */
+ if(oh->chunk[u].dirty) {
+ /* Compute checksum, for chunks > 0 & later versions of format */
+ if(u > 0 && oh->version > H5O_VERSION_1) {
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
- /* Write the combined prefix/chunk out */
- if(H5F_block_write(f, H5FD_MEM_OHDR, addr,
- (H5O_SIZEOF_HDR_OH(oh) + oh->chunk[u].size), dxpl_id, p) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header data to disk")
+ /* Compute metadata checksum */
+ metadata_chksum = H5_checksum_metadata(oh->chunk[u].image, (oh->chunk[u].size - H5O_SIZEOF_CHKSUM), 0);
- /* Release the memory for the combined prefix/chunk */
- p = H5FL_BLK_FREE(chunk_image, p);
+ /* Metadata checksum */
+ p = oh->chunk[u].image + (oh->chunk[u].size - H5O_SIZEOF_CHKSUM);
+ UINT32ENCODE(p, metadata_chksum);
} /* end if */
- else {
- if(H5F_block_write(f, H5FD_MEM_OHDR, oh->chunk[u].addr,
- (oh->chunk[u].size), dxpl_id, oh->chunk[u].image) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header data to disk")
- } /* end else */
+
+ /* Write the chunk out */
+ HDassert(H5F_addr_defined(oh->chunk[u].addr));
+ if(H5F_block_write(f, H5FD_MEM_OHDR, oh->chunk[u].addr,
+ oh->chunk[u].size, dxpl_id, oh->chunk[u].image) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header chunk to disk")
/* Mark chunk as clean now */
oh->chunk[u].dirty = FALSE;
@@ -680,10 +622,10 @@ H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_t *oh)
oh->cache_info.is_dirty = FALSE;
} /* end if */
- if(destroy) {
+ /* Destroy the object header, if requested */
+ if(destroy)
if(H5O_dest(f,oh) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header data")
- } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Opkg.h b/src/H5Opkg.h
index 49a0cf9..4886153 100644
--- a/src/H5Opkg.h
+++ b/src/H5Opkg.h
@@ -48,13 +48,9 @@
* object header chunks directly into memory and operate on them there, even
* on 64-bit architectures. This allows us to reduce the number of disk I/O
* requests with a minimum amount of mem-to-mem copies.
+ *
+ * Note: We no longer attempt to do this. - QAK, 10/16/06
*/
-/*
- * Note: We no longer attempt to do this.
- */
-#ifdef OLD_WAY
-#define H5O_ALIGN(X) (8 * (((X) + 7) / 8))
-#else /* OLD_WAY */
#define H5O_ALIGN_OLD(X) (8 * (((X) + 7) / 8))
#define H5O_ALIGN_VERS(V, X) \
(((V) == H5O_VERSION_1) ? \
@@ -66,19 +62,20 @@
H5O_ALIGN_VERS((O)->version, X)
#define H5O_ALIGN_F(F, X) \
H5O_ALIGN_VERS((H5F_USE_LATEST_FORMAT(F) ? H5O_VERSION_LATEST : H5O_VERSION_1), X)
-#endif /* OLD_WAY */
+
+/* Size of signature information (on disk) */
+#define H5O_SIZEOF_MAGIC 4
+
+/* Object header signatures */
+#define H5O_HDR_MAGIC "OHDR" /* Header */
+#define H5O_CHK_MAGIC "OCHK" /* Continuation chunk */
+
+/* Size of checksum (on disk) */
+#define H5O_SIZEOF_CHKSUM 4
/*
* Size of object header prefix.
*/
-#ifdef OLD_WAY
-#define H5O_SIZEOF_HDR(F) \
- H5O_ALIGN(1 + /*version number */ \
- 1 + /*reserved */ \
- 2 + /*number of messages */ \
- 4 + /*reference count */ \
- 4) /*header data size */
-#else /* OLD_WAY */
#define H5O_SIZEOF_HDR_VERS(V) \
(((V) == H5O_VERSION_1) ? \
H5O_ALIGN_OLD(1 + /*version number */ \
@@ -87,28 +84,21 @@
4 + /*reference count */ \
4) /*header data size */ \
: \
- (4 + /*magic number */ \
+ (H5O_SIZEOF_MAGIC + /*magic number */ \
1 + /*version number */ \
2 + /*number of messages */ \
4 + /*reference count */ \
- 4) /*header data size */ \
+ 4 + /*header data size */ \
+ H5O_SIZEOF_CHKSUM) /*checksum size */ \
)
#define H5O_SIZEOF_HDR_OH(O) \
H5O_SIZEOF_HDR_VERS((O)->version)
#define H5O_SIZEOF_HDR_F(F) \
H5O_SIZEOF_HDR_VERS(H5F_USE_LATEST_FORMAT(F) ? H5O_VERSION_LATEST : H5O_VERSION_1)
-#endif /* OLD_WAY */
/*
* Size of object header message prefix
*/
-#ifdef OLD_WAY
-#define H5O_SIZEOF_MSGHDR(F) \
- H5O_ALIGN(2 + /*message type */ \
- 2 + /*sizeof message data */ \
- 1 + /*flags */ \
- 3) /*reserved */
-#else /* OLD_WAY */
#define H5O_SIZEOF_MSGHDR_VERS(V) \
(((V) == H5O_VERSION_1) ? \
H5O_ALIGN_OLD(2 + /*message type */ \
@@ -123,7 +113,32 @@
H5O_SIZEOF_MSGHDR_VERS((O)->version)
#define H5O_SIZEOF_MSGHDR_F(F) \
H5O_SIZEOF_MSGHDR_VERS(H5F_USE_LATEST_FORMAT(F) ? H5O_VERSION_LATEST : H5O_VERSION_1)
-#endif /* OLD_WAY */
+
+/*
+ * Size of chunk "header" for each chunk
+ */
+#define H5O_SIZEOF_CHKHDR_VERS(V) \
+ (((V) == H5O_VERSION_1) ? \
+ 0 + /*no magic # */ \
+ 0 /*no checksum */ \
+ : \
+ H5O_SIZEOF_MAGIC + /*magic # */ \
+ H5O_SIZEOF_CHKSUM /*checksum */ \
+ )
+#define H5O_SIZEOF_CHKHDR_OH(O) \
+ H5O_SIZEOF_CHKHDR_VERS((O)->version)
+
+/*
+ * Size of checksum for each chunk
+ */
+#define H5O_SIZEOF_CHKSUM_VERS(V) \
+ (((V) == H5O_VERSION_1) ? \
+ 0 /*no checksum */ \
+ : \
+ H5O_SIZEOF_CHKSUM /*checksum */ \
+ )
+#define H5O_SIZEOF_CHKSUM_OH(O) \
+ H5O_SIZEOF_CHKSUM_VERS((O)->version)
struct H5O_msg_class_t {
unsigned id; /*message type ID on disk */