summaryrefslogtreecommitdiffstats
path: root/src/H5Ocache.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Ocache.c')
-rw-r--r--src/H5Ocache.c2000
1 files changed, 1112 insertions, 888 deletions
diff --git a/src/H5Ocache.c b/src/H5Ocache.c
index b3dea03..0851493 100644
--- a/src/H5Ocache.c
+++ b/src/H5Ocache.c
@@ -1,23 +1,20 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* 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. *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://www.hdfgroup.org/licenses. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*-------------------------------------------------------------------------
*
* Created: H5Ocache.c
* Sep 28 2005
- * Quincey Koziol <koziol@ncsa.uiuc.edu>
+ * Quincey Koziol
*
* Purpose: Object header metadata cache virtual functions.
*
@@ -28,70 +25,64 @@
/* Module Setup */
/****************/
-#define H5O_PACKAGE /*suppress error about including H5Opkg */
-
+#include "H5Omodule.h" /* This source code file is part of the H5O module */
/***********/
/* Headers */
/***********/
-#include "H5private.h" /* Generic Functions */
-#include "H5Eprivate.h" /* Error handling */
-#include "H5FLprivate.h" /* Free lists */
-#include "H5MFprivate.h" /* File memory management */
-#include "H5Opkg.h" /* Object headers */
-#include "H5WBprivate.h" /* Wrapped Buffers */
-
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5FLprivate.h" /* Free lists */
+#include "H5MFprivate.h" /* File memory management */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5Opkg.h" /* Object headers */
+#include "H5WBprivate.h" /* Wrapped Buffers */
/****************/
/* Local Macros */
/****************/
-/* 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 largest object type's default object header
- * size to save the extra I/O operations) */
-#define H5O_SPEC_READ_SIZE 512
-
-
/******************/
/* Local Typedefs */
/******************/
-
/********************/
/* Package Typedefs */
/********************/
-
/********************/
/* Local Prototypes */
/********************/
/* Metadata cache callbacks */
-static H5O_t *H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_t *oh, unsigned UNUSED * flags_ptr);
-static herr_t H5O_dest(H5F_t *f, H5O_t *oh);
-static herr_t H5O_clear(H5F_t *f, H5O_t *oh, hbool_t destroy);
-static herr_t H5O_size(const H5F_t *f, const H5O_t *oh, size_t *size_ptr);
-
-static H5O_chunk_proxy_t *H5O_cache_chk_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5O_cache_chk_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_chunk_proxy_t *chk_proxy, unsigned UNUSED * flags_ptr);
-static herr_t H5O_cache_chk_dest(H5F_t *f, H5O_chunk_proxy_t *chk_proxy);
-static herr_t H5O_cache_chk_clear(H5F_t *f, H5O_chunk_proxy_t *chk_proxy, hbool_t destroy);
-static herr_t H5O_cache_chk_size(const H5F_t *f, const H5O_chunk_proxy_t *chk_proxy, size_t *size_ptr);
-
-/* Chunk proxy routines */
-static herr_t H5O_chunk_proxy_dest(H5O_chunk_proxy_t *chunk_proxy);
+static herr_t H5O__cache_get_initial_load_size(void *udata, size_t *image_len);
+static herr_t H5O__cache_get_final_load_size(const void *image_ptr, size_t image_len, void *udata,
+ size_t *actual_len);
+static htri_t H5O__cache_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
+static void *H5O__cache_deserialize(const void *image, size_t len, void *udata, hbool_t *dirty);
+static herr_t H5O__cache_image_len(const void *thing, size_t *image_len);
+static herr_t H5O__cache_serialize(const H5F_t *f, void *image, size_t len, void *thing);
+static herr_t H5O__cache_notify(H5AC_notify_action_t action, void *_thing);
+static herr_t H5O__cache_free_icr(void *thing);
+
+static herr_t H5O__cache_chk_get_initial_load_size(void *udata, size_t *image_len);
+static htri_t H5O__cache_chk_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
+static void *H5O__cache_chk_deserialize(const void *image, size_t len, void *udata, hbool_t *dirty);
+static herr_t H5O__cache_chk_image_len(const void *thing, size_t *image_len);
+static herr_t H5O__cache_chk_serialize(const H5F_t *f, void *image, size_t len, void *thing);
+static herr_t H5O__cache_chk_notify(H5AC_notify_action_t action, void *_thing);
+static herr_t H5O__cache_chk_free_icr(void *thing);
+
+/* Prefix routines */
+static herr_t H5O__prefix_deserialize(const uint8_t *image, H5O_cache_ud_t *udata);
/* Chunk routines */
-static herr_t H5O_chunk_deserialize(H5O_t *oh, haddr_t addr, size_t len,
- const uint8_t *image, H5O_common_cache_ud_t *udata, hbool_t *dirty);
-static herr_t H5O_chunk_serialize(const H5F_t *f, H5O_t *oh, unsigned chunkno);
+static herr_t H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t chunk_size, const uint8_t *image,
+ size_t len, H5O_common_cache_ud_t *udata, hbool_t *dirty);
+static herr_t H5O__chunk_serialize(const H5F_t *f, H5O_t *oh, unsigned chunkno);
/* Misc. routines */
-static herr_t H5O_add_cont_msg(H5O_cont_msgs_t *cont_msg_info,
- const H5O_cont_t *cont);
-
+static herr_t H5O__add_cont_msg(H5O_cont_msgs_t *cont_msg_info, const H5O_cont_t *cont);
/*********************/
/* Package Variables */
@@ -99,24 +90,38 @@ static herr_t H5O_add_cont_msg(H5O_cont_msgs_t *cont_msg_info,
/* H5O object header prefix inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_OHDR[1] = {{
- H5AC_OHDR_ID,
- (H5AC_load_func_t)H5O_load,
- (H5AC_flush_func_t)H5O_flush,
- (H5AC_dest_func_t)H5O_dest,
- (H5AC_clear_func_t)H5O_clear,
- (H5AC_notify_func_t)NULL,
- (H5AC_size_func_t)H5O_size,
+ H5AC_OHDR_ID, /* Metadata client ID */
+ "object header", /* Metadata client name (for debugging) */
+ H5FD_MEM_OHDR, /* File space memory type for client */
+ H5AC__CLASS_SPECULATIVE_LOAD_FLAG, /* Client class behavior flags */
+ H5O__cache_get_initial_load_size, /* 'get_initial_load_size' callback */
+ H5O__cache_get_final_load_size, /* 'get_final_load_size' callback */
+ H5O__cache_verify_chksum, /* 'verify_chksum' callback */
+ H5O__cache_deserialize, /* 'deserialize' callback */
+ H5O__cache_image_len, /* 'image_len' callback */
+ NULL, /* 'pre_serialize' callback */
+ H5O__cache_serialize, /* 'serialize' callback */
+ H5O__cache_notify, /* 'notify' callback */
+ H5O__cache_free_icr, /* 'free_icr' callback */
+ NULL, /* 'fsf_size' callback */
}};
/* H5O object header chunk inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_OHDR_CHK[1] = {{
- H5AC_OHDR_CHK_ID,
- (H5AC_load_func_t)H5O_cache_chk_load,
- (H5AC_flush_func_t)H5O_cache_chk_flush,
- (H5AC_dest_func_t)H5O_cache_chk_dest,
- (H5AC_clear_func_t)H5O_cache_chk_clear,
- (H5AC_notify_func_t)NULL,
- (H5AC_size_func_t)H5O_cache_chk_size,
+ H5AC_OHDR_CHK_ID, /* Metadata client ID */
+ "object header continuation chunk", /* Metadata client name (for debugging) */
+ H5FD_MEM_OHDR, /* File space memory type for client */
+ H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */
+ H5O__cache_chk_get_initial_load_size, /* 'get_initial_load_size' callback */
+ NULL, /* 'get_final_load_size' callback */
+ H5O__cache_chk_verify_chksum, /* 'verify_chksum' callback */
+ H5O__cache_chk_deserialize, /* 'deserialize' callback */
+ H5O__cache_chk_image_len, /* 'image_len' callback */
+ NULL, /* 'pre_serialize' callback */
+ H5O__cache_chk_serialize, /* 'serialize' callback */
+ H5O__cache_chk_notify, /* 'notify' callback */
+ H5O__cache_chk_free_icr, /* 'free_icr' callback */
+ NULL, /* 'fsf_size' callback */
}};
/* Declare external the free list for H5O_unknown_t's */
@@ -128,212 +133,207 @@ H5FL_EXTERN(H5O_chunk_proxy_t);
/* Declare the free list for H5O_cont_t sequences */
H5FL_SEQ_DEFINE(H5O_cont_t);
-
/*****************************/
/* Library Private Variables */
/*****************************/
-
/*******************/
/* Local Variables */
/*******************/
-
-
/*-------------------------------------------------------------------------
- * Function: H5O_load
+ * Function: H5O__cache_get_initial_load_size()
*
- * Purpose: Loads an object header from disk.
+ * Purpose: Tell the metadata cache how much data to read from file in
+ * the first speculative read for the object header.
*
- * Return: Success: Pointer to the new object header.
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Failure: NULL
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Aug 5 1997
+ * Programmer: John Mainzer
+ * 7/28/14
*
*-------------------------------------------------------------------------
*/
-static H5O_t *
-H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
+static herr_t
+H5O__cache_get_initial_load_size(void H5_ATTR_UNUSED *_udata, size_t *image_len)
{
- H5O_t *oh = NULL; /* Object header read in */
- H5O_cache_ud_t *udata = (H5O_cache_ud_t *)_udata; /* User data for callback */
- H5WB_t *wb = NULL; /* Wrapped buffer for prefix data */
- uint8_t read_buf[H5O_SPEC_READ_SIZE]; /* Buffer for speculative read */
- const uint8_t *p; /* Pointer into buffer to decode */
- uint8_t *buf; /* Buffer to decode */
- size_t spec_read_size; /* Size of buffer to speculatively read in */
- size_t prefix_size; /* Size of object header prefix */
- size_t buf_size; /* Size of prefix+chunk #0 buffer */
- haddr_t eoa; /* Relative end of file address */
- H5O_t *ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_PACKAGE_NOERR
/* Check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
- HDassert(udata);
- HDassert(udata->common.f);
- HDassert(udata->common.cont_msg_info);
-
- /* Make certain we don't speculatively read off the end of the file */
- if(HADDR_UNDEF == (eoa = H5F_get_eoa(f, H5FD_MEM_OHDR)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to determine file size")
-
- /* Compute the size of the speculative object header buffer */
- H5_ASSIGN_OVERFLOW(spec_read_size, MIN(eoa - addr, H5O_SPEC_READ_SIZE), /* From: */ hsize_t, /* To: */ size_t);
-
- /* Attempt to speculatively read both object header prefix and first chunk */
- if(H5F_block_read(f, H5FD_MEM_OHDR, addr, spec_read_size, dxpl_id, read_buf) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header")
- p = read_buf;
+ HDassert(image_len);
- /* Allocate space for the object header data structure */
- if(NULL == (oh = H5FL_CALLOC(H5O_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ /* Set the image length size */
+ *image_len = H5O_SPEC_READ_SIZE;
- /* File-specific, non-stored information */
- oh->sizeof_size = H5F_SIZEOF_SIZE(udata->common.f);
- oh->sizeof_addr = H5F_SIZEOF_ADDR(udata->common.f);
-
- /* Check for presence of magic number */
- /* (indicates version 2 or later) */
- if(!HDmemcmp(p, H5O_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC)) {
- /* Magic number */
- p += H5_SIZEOF_MAGIC;
-
- /* Version */
- oh->version = *p++;
- if(H5O_VERSION_2 != oh->version)
- HGOTO_ERROR(H5E_OHDR, H5E_VERSION, NULL, "bad object header version number")
-
- /* Flags */
- oh->flags = *p++;
- if(oh->flags & ~H5O_HDR_ALL_FLAGS)
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "unknown object header status flag(s)")
-
- /* Number of links to object (unless overridden by refcount message) */
- oh->nlink = 1;
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O__cache_get_initial_load_size() */
- /* Time fields */
- if(oh->flags & H5O_HDR_STORE_TIMES) {
- uint32_t tmp; /* Temporary value */
+/*-------------------------------------------------------------------------
+ * Function: H5O__cache_get_final_load_size()
+ *
+ * Purpose: Tell the metadata cache the final size of an object header.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Quincey Koziol
+ * November 18, 2016
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O__cache_get_final_load_size(const void *image, size_t H5_ATTR_NDEBUG_UNUSED image_len, void *_udata,
+ size_t *actual_len)
+{
+ H5O_cache_ud_t *udata = (H5O_cache_ud_t *)_udata; /* User data for callback */
+ herr_t ret_value = SUCCEED; /* Return value */
- UINT32DECODE(p, tmp);
- oh->atime = (time_t)tmp;
- UINT32DECODE(p, tmp);
- oh->mtime = (time_t)tmp;
- UINT32DECODE(p, tmp);
- oh->ctime = (time_t)tmp;
- UINT32DECODE(p, tmp);
- oh->btime = (time_t)tmp;
- } /* end if */
- else
- oh->atime = oh->mtime = oh->ctime = oh->btime = 0;
+ FUNC_ENTER_PACKAGE
- /* Attribute fields */
- if(oh->flags & H5O_HDR_ATTR_STORE_PHASE_CHANGE) {
- UINT16DECODE(p, oh->max_compact);
- UINT16DECODE(p, oh->min_dense);
- if(oh->max_compact < oh->min_dense)
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "bad object header attribute phase change values")
- } /* end if */
- else {
- oh->max_compact = H5O_CRT_ATTR_MAX_COMPACT_DEF;
- oh->min_dense = H5O_CRT_ATTR_MIN_DENSE_DEF;
- } /* end else */
+ /* Check arguments */
+ HDassert(image);
+ HDassert(udata);
+ HDassert(actual_len);
+ HDassert(*actual_len == image_len);
- /* First chunk size */
- switch(oh->flags & H5O_HDR_CHUNK0_SIZE) {
- case 0: /* 1 byte size */
- oh->chunk0_size = *p++;
- break;
+ /* Deserialize the object header prefix */
+ if (H5O__prefix_deserialize((const uint8_t *)image, udata) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "can't deserialize object header prefix")
- case 1: /* 2 byte size */
- UINT16DECODE(p, oh->chunk0_size);
- break;
+ /* Sanity check */
+ HDassert(udata->oh);
- case 2: /* 4 byte size */
- UINT32DECODE(p, oh->chunk0_size);
- break;
+ /* Set the final size for the cache image */
+ *actual_len = udata->chunk0_size + (size_t)H5O_SIZEOF_HDR(udata->oh);
- case 3: /* 8 byte size */
- UINT64DECODE(p, oh->chunk0_size);
- break;
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O__cache_get_final_load_size() */
- default:
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "bad size for chunk 0")
- } /* end switch */
- if(oh->chunk0_size > 0 && oh->chunk0_size < H5O_SIZEOF_MSGHDR_OH(oh))
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "bad object header chunk size")
- } /* 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")
+/*-------------------------------------------------------------------------
+ * Function: H5O__cache_verify_chksum
+ *
+ * Purpose: Verify the computed checksum of the data structure is the
+ * same as the stored chksum.
+ *
+ * Return: Success: TRUE/FALSE
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi
+ * Aug 2015
+ *
+ *-------------------------------------------------------------------------
+ */
+static htri_t
+H5O__cache_verify_chksum(const void *_image, size_t len, void *_udata)
+{
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5O_cache_ud_t *udata = (H5O_cache_ud_t *)_udata; /* User data for callback */
+ htri_t ret_value = TRUE; /* Return value */
- /* Flags */
- oh->flags = H5O_CRT_OHDR_FLAGS_DEF;
+ FUNC_ENTER_PACKAGE_NOERR
- /* Reserved */
- p++;
+ /* Check arguments */
+ HDassert(image);
+ HDassert(udata);
+ HDassert(udata->oh);
- /* Number of messages */
- UINT16DECODE(p, udata->v1_pfx_nmesgs);
+ /* There is no checksum for version 1 */
+ if (udata->oh->version != H5O_VERSION_1) {
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
- /* Link count */
- UINT32DECODE(p, oh->nlink);
+ /* Get stored and computed checksums */
+ H5F_get_checksums(image, len, &stored_chksum, &computed_chksum);
- /* Reset unused time fields */
- oh->atime = oh->mtime = oh->ctime = oh->btime = 0;
+ if (stored_chksum != computed_chksum) {
+ /* These fields are not deserialized yet in H5O__prefix_deserialize() */
+ HDassert(udata->oh->chunk == NULL);
+ HDassert(udata->oh->mesg == NULL);
+ HDassert(udata->oh->proxy == NULL);
- /* Reset unused attribute fields */
- oh->max_compact = 0;
- oh->min_dense = 0;
+ /* Indicate that udata->oh is to be freed later
+ in H5O__prefix_deserialize() */
+ udata->free_oh = TRUE;
+ ret_value = FALSE;
+ } /* end if */
+ } /* end if */
+ else
+ HDassert(!(udata->common.file_intent & H5F_ACC_SWMR_WRITE));
- /* First chunk size */
- UINT32DECODE(p, oh->chunk0_size);
- if((udata->v1_pfx_nmesgs > 0 && oh->chunk0_size < H5O_SIZEOF_MSGHDR_OH(oh)) ||
- (udata->v1_pfx_nmesgs == 0 && oh->chunk0_size > 0))
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "bad object header chunk size")
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O__cache_verify_chksum() */
- /* Reserved, in version 1 (for 8-byte alignment padding) */
- p += 4;
- } /* end else */
+/*-------------------------------------------------------------------------
+ * Function: H5O__cache_deserialize
+ *
+ * Purpose: Attempt to deserialize the object header contained in the
+ * supplied buffer, load the data into an instance of H5O_t, and
+ * return a pointer to the new instance.
+ *
+ * Note that the object header is read with with a speculative read.
+ * If the initial read is too small, make note of this fact and return
+ * without error. H5C__load_entry() will note the size discrepancy
+ * and retry the deserialize operation with the correct size read.
+ *
+ * Return: Success: Pointer to in core representation
+ * Failure: NULL
+ *
+ * Programmer: John Mainzer
+ * 7/28/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5O__cache_deserialize(const void *image, size_t len, void *_udata, hbool_t *dirty)
+{
+ H5O_t *oh = NULL; /* Object header read in */
+ H5O_cache_ud_t *udata = (H5O_cache_ud_t *)_udata; /* User data for callback */
+ void *ret_value = NULL; /* Return value */
- /* Determine object header prefix length */
- prefix_size = (size_t)(p - (const uint8_t *)read_buf);
- HDassert((size_t)prefix_size == (size_t)(H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh)));
+ FUNC_ENTER_PACKAGE
- /* Compute the size of the buffer used */
- buf_size = oh->chunk0_size + (size_t)H5O_SIZEOF_HDR(oh);
+ /* Check arguments */
+ HDassert(image);
+ HDassert(len > 0);
+ HDassert(udata);
+ HDassert(udata->common.f);
+ HDassert(udata->common.cont_msg_info);
+ HDassert(dirty);
+
+ /* Check for partially deserialized object header */
+ /* (Object header prefix will be deserialized if the object header came
+ * through the 'get_final_load_size' callback and not deserialized if
+ * the object header is coming from a cache image - QAK, 2016/12/14)
+ */
+ if (NULL == udata->oh) {
+ /* Deserialize the object header prefix */
+ if (H5O__prefix_deserialize((const uint8_t *)image, udata) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "can't deserialize object header prefix")
- /* Check if the speculative read was large enough to parse the first chunk */
- if(spec_read_size < buf_size) {
- /* Wrap the local buffer for serialized header info */
- if(NULL == (wb = H5WB_wrap(read_buf, sizeof(read_buf))))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't wrap buffer")
+ /* Sanity check */
+ HDassert(udata->oh);
+ } /* end if */
- /* Get a pointer to a buffer that's large enough for serialized header */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, buf_size)))
- HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "can't get actual buffer")
+ /* Retrieve partially deserialized object header from user data */
+ oh = udata->oh;
- /* Copy existing raw data into new buffer */
- HDmemcpy(buf, read_buf, spec_read_size);
+ /* Set SWMR flag, if appropriate */
+ oh->swmr_write = !!(H5F_INTENT(udata->common.f) & H5F_ACC_SWMR_WRITE);
- /* Read rest of the raw data */
- if(H5F_block_read(f, H5FD_MEM_OHDR, (addr + spec_read_size), (buf_size - spec_read_size), dxpl_id, (buf + spec_read_size)) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header data")
+ /* Create object header proxy if doing SWMR writes */
+ if (oh->swmr_write) {
+ /* Create virtual entry, for use as proxy */
+ if (NULL == (oh->proxy = H5AC_proxy_entry_create()))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, NULL, "can't create object header proxy")
} /* end if */
else
- buf = read_buf;
+ oh->proxy = NULL;
/* Parse the first chunk */
- if(H5O_chunk_deserialize(oh, udata->common.addr, oh->chunk0_size, buf, &(udata->common), &oh->cache_info.is_dirty) < 0)
+ if (H5O__chunk_deserialize(oh, udata->common.addr, udata->chunk0_size, (const uint8_t *)image, len,
+ &(udata->common), dirty) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't deserialize first object header chunk")
/* Note that we've loaded the object header from the file */
@@ -343,630 +343,707 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
ret_value = oh;
done:
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_CLOSEERROR, NULL, "can't close wrapped buffer")
-
/* Release the [possibly partially initialized] object header on errors */
- if(!ret_value && oh)
- if(H5O_free(oh) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, NULL, "unable to destroy object header data")
+ if (!ret_value && oh)
+ if (H5O__free(oh, FALSE) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, NULL, "unable to destroy object header data")
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_load() */
+} /* end H5O__cache_deserialize() */
-
/*-------------------------------------------------------------------------
- * Function: H5O_flush
+ * Function: H5O__cache_image_len
*
- * Purpose: Flushes (and destroys) an object header.
+ * Purpose: Compute the size in bytes of the specified instance of
+ * H5O_t on disk, and return it in *image_len. On failure,
+ * the value of *image_len is undefined.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Aug 5 1997
+ * Programmer: John Mainzer
+ * 7/28/14
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t UNUSED addr, H5O_t *oh, unsigned UNUSED * flags_ptr)
+H5O__cache_image_len(const void *_thing, size_t *image_len)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ const H5O_t *oh = (const H5O_t *)_thing; /* Object header to query */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_PACKAGE_NOERR
/* Check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
HDassert(oh);
+ HDassert(oh->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(oh->cache_info.type == H5AC_OHDR);
+ HDassert(image_len);
- /* flush */
- if(oh->cache_info.is_dirty) {
- uint8_t *p; /* Pointer to object header prefix buffer */
+ /* Report the object header's prefix+first chunk length */
+ *image_len = oh->chunk[0].size;
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O__cache_image_len() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5O__cache_serialize
+ *
+ * Purpose: Serialize the contents of the supplied object header, and
+ * load this data into the supplied buffer.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 7/28/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O__cache_serialize(const H5F_t *f, void *image, size_t len, void *_thing)
+{
+ H5O_t *oh = (H5O_t *)_thing; /* Object header to encode */
+ uint8_t *chunk_image; /* Pointer to object header prefix buffer */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Check arguments */
+ HDassert(f);
+ HDassert(image);
+ HDassert(oh);
+ HDassert(oh->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(oh->cache_info.type == H5AC_OHDR);
+ HDassert(oh->chunk[0].size == len);
#ifdef H5O_DEBUG
-H5O_assert(oh);
+ H5O__assert(oh);
#endif /* H5O_DEBUG */
- /* Point to raw data 'image' for first chunk, which has room for the prefix */
- p = oh->chunk[0].image;
+ /* Point to raw data 'image' for first chunk, which
+ * has room for the prefix
+ */
+ chunk_image = 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) {
- uint64_t chunk0_size; /* Size of chunk 0's data */
+ /* 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) {
+ uint64_t chunk0_size; /* Size of chunk 0's data */
- HDassert(oh->chunk[0].size >= (size_t)H5O_SIZEOF_HDR(oh));
- chunk0_size = oh->chunk[0].size - (size_t)H5O_SIZEOF_HDR(oh);
+ HDassert(oh->chunk[0].size >= (size_t)H5O_SIZEOF_HDR(oh));
+ chunk0_size = oh->chunk[0].size - (size_t)H5O_SIZEOF_HDR(oh);
- /* Verify magic number */
- HDassert(!HDmemcmp(p, H5O_HDR_MAGIC, H5_SIZEOF_MAGIC));
- p += H5_SIZEOF_MAGIC;
+ /* Verify magic number */
+ HDassert(!HDmemcmp(chunk_image, H5O_HDR_MAGIC, H5_SIZEOF_MAGIC));
+ chunk_image += H5_SIZEOF_MAGIC;
- /* Version */
- *p++ = oh->version;
-
- /* Flags */
- *p++ = oh->flags;
+ /* Version */
+ *chunk_image++ = oh->version;
- /* Time fields */
- if(oh->flags & H5O_HDR_STORE_TIMES) {
- UINT32ENCODE(p, oh->atime);
- UINT32ENCODE(p, oh->mtime);
- UINT32ENCODE(p, oh->ctime);
- UINT32ENCODE(p, oh->btime);
- } /* end if */
+ /* Flags */
+ *chunk_image++ = oh->flags;
- /* Attribute fields */
- if(oh->flags & H5O_HDR_ATTR_STORE_PHASE_CHANGE) {
- UINT16ENCODE(p, oh->max_compact);
- UINT16ENCODE(p, oh->min_dense);
- } /* end if */
+ /* Time fields */
+ if (oh->flags & H5O_HDR_STORE_TIMES) {
+ UINT32ENCODE(chunk_image, oh->atime);
+ UINT32ENCODE(chunk_image, oh->mtime);
+ UINT32ENCODE(chunk_image, oh->ctime);
+ UINT32ENCODE(chunk_image, oh->btime);
+ } /* end if */
- /* First chunk size */
- switch(oh->flags & H5O_HDR_CHUNK0_SIZE) {
- case 0: /* 1 byte size */
- HDassert(chunk0_size < 256);
- *p++ = (uint8_t)chunk0_size;
- break;
-
- case 1: /* 2 byte size */
- HDassert(chunk0_size < 65536);
- UINT16ENCODE(p, chunk0_size);
- break;
-
- case 2: /* 4 byte size */
- /* use <= 2**32 -1 to stay within 4 bytes integer range */
- HDassert(chunk0_size <= 4294967295UL);
- UINT32ENCODE(p, chunk0_size);
- break;
-
- case 3: /* 8 byte size */
- UINT64ENCODE(p, chunk0_size);
- break;
-
- default:
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad size for chunk 0")
- } /* end switch */
+ /* Attribute fields */
+ if (oh->flags & H5O_HDR_ATTR_STORE_PHASE_CHANGE) {
+ UINT16ENCODE(chunk_image, oh->max_compact);
+ UINT16ENCODE(chunk_image, oh->min_dense);
} /* end if */
- else {
- /* Version */
- *p++ = oh->version;
- /* Reserved */
- *p++ = 0;
+ /* First chunk size */
+ switch (oh->flags & H5O_HDR_CHUNK0_SIZE) {
+ case 0: /* 1 byte size */
+ HDassert(chunk0_size < 256);
+ *chunk_image++ = (uint8_t)chunk0_size;
+ break;
+
+ case 1: /* 2 byte size */
+ HDassert(chunk0_size < 65536);
+ UINT16ENCODE(chunk_image, chunk0_size);
+ break;
+
+ case 2: /* 4 byte size */
+ /* use <= 2**32 -1 to stay within 4 bytes integer range */
+ HDassert(chunk0_size <= 4294967295UL);
+ UINT32ENCODE(chunk_image, chunk0_size);
+ break;
+
+ case 3: /* 8 byte size */
+ UINT64ENCODE(chunk_image, chunk0_size);
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad size for chunk 0")
+ } /* end switch */
+ } /* end if */
+ else {
+ /* Version */
+ *chunk_image++ = oh->version;
+
+ /* Reserved */
+ *chunk_image++ = 0;
- /* Number of messages */
+ /* Number of messages */
#ifdef H5O_ENABLE_BAD_MESG_COUNT
- if(oh->store_bad_mesg_count)
- UINT16ENCODE(p, (oh->nmesgs - 1))
- else
+ if (oh->store_bad_mesg_count)
+ UINT16ENCODE(chunk_image, (oh->nmesgs - 1))
+ else
#endif /* H5O_ENABLE_BAD_MESG_COUNT */
- UINT16ENCODE(p, oh->nmesgs);
-
- /* Link count */
- UINT32ENCODE(p, oh->nlink);
+ UINT16ENCODE(chunk_image, oh->nmesgs);
- /* First chunk size */
- UINT32ENCODE(p, (oh->chunk[0].size - (size_t)H5O_SIZEOF_HDR(oh)));
+ /* Link count */
+ UINT32ENCODE(chunk_image, oh->nlink);
- /* Zero to alignment */
- HDmemset(p, 0, (size_t)(H5O_SIZEOF_HDR(oh) - 12));
- p += (size_t)(H5O_SIZEOF_HDR(oh) - 12);
- } /* end else */
- HDassert((size_t)(p - oh->chunk[0].image) == (size_t)(H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh)));
+ /* First chunk size */
+ UINT32ENCODE(chunk_image, (oh->chunk[0].size - (size_t)H5O_SIZEOF_HDR(oh)));
- /* Serialize messages for this chunk */
- if(H5O_chunk_serialize(f, oh, (unsigned)0) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL, "unable to serialize first object header chunk")
+ /* Zero to alignment */
+ HDmemset(chunk_image, 0, (size_t)(H5O_SIZEOF_HDR(oh) - 12));
+ chunk_image += (size_t)(H5O_SIZEOF_HDR(oh) - 12);
+ } /* end else */
- /* Write the chunk out */
- HDassert(H5F_addr_defined(oh->chunk[0].addr));
- if(H5F_block_write(f, H5FD_MEM_OHDR, oh->chunk[0].addr, oh->chunk[0].size, dxpl_id, oh->chunk[0].image) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header chunk to disk")
+ HDassert((size_t)(chunk_image - oh->chunk[0].image) ==
+ (size_t)(H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh)));
- /* Mark object header as clean now */
- oh->cache_info.is_dirty = FALSE;
- } /* end if */
+ /* Serialize messages for this chunk */
+ if (H5O__chunk_serialize(f, oh, (unsigned)0) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL, "unable to serialize first object header chunk")
- /* 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")
+ /* copy the chunk into the image -- this is potentially expensive.
+ * Can we rework things so that the object header and the cache
+ * share a buffer?
+ */
+ H5MM_memcpy(image, oh->chunk[0].image, len);
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_flush() */
+} /* end H5O__cache_serialize() */
-
/*-------------------------------------------------------------------------
- * Function: H5O_dest
+ * Function: H5O__cache_notify
*
- * Purpose: Destroys an object header.
+ * Purpose: Handle cache action notifications
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Jan 15 2003
+ * Programmer: Quincey Koziol
+ * Jul 23 2016
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_dest(H5F_t *f, H5O_t *oh)
+H5O__cache_notify(H5AC_notify_action_t action, void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5O_t *oh = (H5O_t *)_thing;
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_PACKAGE
- /* check args */
+ /*
+ * Check arguments.
+ */
HDassert(oh);
- HDassert(oh->rc == 0);
- /* Verify that node is clean */
- HDassert(!oh->cache_info.is_dirty);
+ switch (action) {
+ case H5AC_NOTIFY_ACTION_AFTER_INSERT:
+ case H5AC_NOTIFY_ACTION_AFTER_LOAD:
+ if (oh->swmr_write) {
+ /* Sanity check */
+ HDassert(oh->proxy);
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!oh->cache_info.free_file_space_on_destroy || H5F_addr_defined(oh->cache_info.addr));
+ /* Register the object header as a parent of the virtual entry */
+ if (H5AC_proxy_entry_add_parent(oh->proxy, oh) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't add object header as parent of proxy")
+ } /* end if */
+ break;
- /* Check for releasing file space for object header */
- if(oh->chunk && oh->cache_info.free_file_space_on_destroy) {
- /* Free main (first) object header "chunk" */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_OHDR, H5AC_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")
- } /* end if */
+ case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
+ case H5AC_NOTIFY_ACTION_ENTRY_DIRTIED:
+ /* do nothing */
+ break;
- /* Destroy object header */
- if(H5O_free(oh) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't destroy object header")
+ case H5AC_NOTIFY_ACTION_ENTRY_CLEANED: {
+ unsigned u; /* Local index variable */
+
+ /* Mark messages stored with the object header (i.e. messages in chunk 0) as clean */
+ for (u = 0; u < oh->nmesgs; u++)
+ if (oh->mesg[u].chunkno == 0)
+ oh->mesg[u].dirty = FALSE;
+#ifndef NDEBUG
+ /* Reset the number of messages dirtied by decoding */
+ oh->ndecode_dirtied = 0;
+#endif /* NDEBUG */
+ } break;
+
+ case H5AC_NOTIFY_ACTION_CHILD_DIRTIED:
+ case H5AC_NOTIFY_ACTION_CHILD_CLEANED:
+ case H5AC_NOTIFY_ACTION_CHILD_UNSERIALIZED:
+ case H5AC_NOTIFY_ACTION_CHILD_SERIALIZED:
+ /* do nothing */
+ break;
+
+ case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
+ if (oh->swmr_write) {
+ /* Unregister the object header as a parent of the virtual entry */
+ if (H5AC_proxy_entry_remove_parent(oh->proxy, oh) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't remove object header as parent of proxy")
+ } /* end if */
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unknown action from metadata cache")
+ } /* end switch */
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_dest() */
+} /* end H5O__cache_notify() */
-
/*-------------------------------------------------------------------------
- * Function: H5O_clear
- *
- * Purpose: Mark a object header in memory as non-dirty.
+ * Function: H5O__cache_free_icr
*
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 20 2003
+ * Purpose: Free the in core representation of the supplied object header.
*
- * Changes: In the parallel case, there is the possibility that the
- * the object header may be flushed by different processes
- * over the life of the computation. Thus we must ensure
- * that the chunk images are up to date before we mark the
- * messages clean -- as otherwise we may overwrite valid
- * data with a blank section of a chunk image.
+ * Note: The metadata cache sets the object's cache_info.magic to
+ * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr
+ * callback (checked in assert).
*
- * To deal with this, I have added code to call
- * H5O_chunk_serialize() for all chunks before we
- * mark all messages as clean if we are not destroying the
- * object. Do this in the parallel case only, as the problem
- * can only occur in this context.
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * JRM -- 10/12/10
+ * Programmer: John Mainzer
+ * 7/28/14
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_clear(H5F_t *f, H5O_t *oh, hbool_t destroy)
+H5O__cache_free_icr(void *_thing)
{
- unsigned u; /* Local index variable */
- herr_t ret_value = SUCCEED;
+ H5O_t *oh = (H5O_t *)_thing; /* Object header to destroy */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_PACKAGE
- /* check args */
+ /* Check arguments */
HDassert(oh);
+ HDassert(oh->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
+ HDassert(oh->cache_info.type == H5AC_OHDR);
-#ifdef H5_HAVE_PARALLEL
- if ( ( oh->cache_info.is_dirty ) && ( ! destroy ) ) {
-
- size_t i;
-
- /* scan through all chunks associated with the object header,
- * and cause them to update their images for all entries currently
- * marked dirty. Must do this in the parallel case, as it is possible
- * that this processor may clear this object header several times
- * before flushing it -- thus causing undefined sections of the image
- * to be written to disk overwriting valid data.
- */
-
- for ( i = 0; i < oh->nchunks; i++ ) {
-
- if ( H5O_chunk_serialize(f, oh, i) < 0 ) {
+ /* Destroy object header */
+ if (H5O__free(oh, FALSE) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't destroy object header")
- HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL,
- "unable to serialize object header chunk")
- }
- }
- }
-#endif /* H5_HAVE_PARALLEL */
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O__cache_free_icr() */
- /* Mark messages as clean */
- for(u = 0; u < oh->nmesgs; u++)
- oh->mesg[u].dirty = FALSE;
+/*-------------------------------------------------------------------------
+ * Function: H5O__cache_chk_get_initial_load_size()
+ *
+ * Purpose: Tell the metadata cache how large the on disk image of the
+ * chunk proxy is, so it can load the image into a buffer for the
+ * deserialize call.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 7/28/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O__cache_chk_get_initial_load_size(void *_udata, size_t *image_len)
+{
+ const H5O_chk_cache_ud_t *udata = (const H5O_chk_cache_ud_t *)_udata; /* User data for callback */
-#ifndef NDEBUG
- /* Reset the number of messages dirtied by decoding */
- oh->ndecode_dirtied = 0;
-#endif /* NDEBUG */
+ FUNC_ENTER_PACKAGE_NOERR
- /* Mark whole header as clean */
- oh->cache_info.is_dirty = FALSE;
+ /* Check arguments */
+ HDassert(udata);
+ HDassert(udata->oh);
+ HDassert(image_len);
- if(destroy)
- if(H5O_dest(f, oh) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header data")
+ /* Set the image length size */
+ *image_len = udata->size;
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_clear() */
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O__cache_chk_get_initial_load_size() */
-
/*-------------------------------------------------------------------------
- * Function: H5O_size
+ * Function: H5B2__cache_chk_verify_chksum
*
- * Purpose: Compute the size in bytes of the specified instance of
- * H5O_t on disk, and return it in *len_ptr. On failure,
- * the value of *len_ptr is undefined.
+ * Purpose: Verify the computed checksum of the data structure is the
+ * same as the stored chksum.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: TRUE/FALSE
+ * Failure: Negative
*
- * Programmer: John Mainzer
- * 5/13/04
+ * Programmer: Vailin Choi
+ * Aug 2015
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5O_size(const H5F_t UNUSED *f, const H5O_t *oh, size_t *size_ptr)
+static htri_t
+H5O__cache_chk_verify_chksum(const void *_image, size_t len, void *_udata)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5O_chk_cache_ud_t *udata = (H5O_chk_cache_ud_t *)_udata; /* User data for callback */
+ htri_t ret_value = TRUE; /* Return value */
- /* check args */
- HDassert(oh);
- HDassert(size_ptr);
+ FUNC_ENTER_PACKAGE_NOERR
- /* Report the object header's prefix+first chunk length */
- if(oh->chunk0_size)
- *size_ptr = (size_t)H5O_SIZEOF_HDR(oh) + oh->chunk0_size;
- else
- *size_ptr = oh->chunk[0].size;
+ /* Check arguments */
+ HDassert(image);
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5O_size() */
+ /* There is no checksum for version 1 */
+ if (udata->oh->version != H5O_VERSION_1) {
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
+
+ /* Get stored and computed checksums */
+ H5F_get_checksums(image, len, &stored_chksum, &computed_chksum);
+
+ if (stored_chksum != computed_chksum)
+ ret_value = FALSE;
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O__cache_chk_verify_chksum() */
-
/*-------------------------------------------------------------------------
- * Function: H5O_cache_chk_load
+ * Function: H5O__cache_chk_deserialize
*
- * Purpose: Loads an object header continuation chunk from disk.
+ * Purpose: Attempt to deserialize the object header continuation chunk
+ * contained in the supplied buffer, load the data into an instance
+ * of H5O_chunk_proxy_t, and return a pointer to the new instance.
*
- * Return: Success: Pointer to the new object header chunk proxy.
- * Failure: NULL
+ * Return: Success: Pointer to in core representation
+ * Failure: NULL
*
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Jul 12 2008
+ * Programmer: John Mainzer
+ * 7/28/14
*
*-------------------------------------------------------------------------
*/
-static H5O_chunk_proxy_t *
-H5O_cache_chk_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
+static void *
+H5O__cache_chk_deserialize(const void *image, size_t len, void *_udata, hbool_t *dirty)
{
- H5O_chunk_proxy_t *chk_proxy = NULL; /* Chunk proxy object */
- H5O_chk_cache_ud_t *udata = (H5O_chk_cache_ud_t *)_udata; /* User data for callback */
- H5WB_t *wb = NULL; /* Wrapped buffer for prefix data */
- uint8_t chunk_buf[H5O_SPEC_READ_SIZE]; /* Buffer for speculative read */
- uint8_t *buf; /* Buffer to decode */
- H5O_chunk_proxy_t *ret_value; /* Return value */
+ H5O_chunk_proxy_t *chk_proxy = NULL; /* Chunk proxy object */
+ H5O_chk_cache_ud_t *udata = (H5O_chk_cache_ud_t *)_udata; /* User data for callback */
+ void *ret_value = NULL; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_PACKAGE
/* Check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ HDassert(image);
+ HDassert(len > 0);
HDassert(udata);
HDassert(udata->oh);
+ HDassert(dirty);
/* Allocate space for the object header data structure */
- if(NULL == (chk_proxy = H5FL_CALLOC(H5O_chunk_proxy_t)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "memory allocation failed")
-
- /* Wrap the local buffer for serialized header info */
- if(NULL == (wb = H5WB_wrap(chunk_buf, sizeof(chunk_buf))))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't wrap buffer")
-
- /* Get a pointer to a buffer that's large enough for serialized header */
- if(NULL == (buf = (uint8_t *)H5WB_actual(wb, udata->size)))
- HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "can't get actual buffer")
-
- /* Read rest of the raw data */
- if(H5F_block_read(f, H5FD_MEM_OHDR, addr, udata->size, dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header continuation chunk")
+ if (NULL == (chk_proxy = H5FL_CALLOC(H5O_chunk_proxy_t)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "memory allocation failed")
/* Check if we are still decoding the object header */
/* (as opposed to bringing a piece of it back from the file) */
- if(udata->decoding) {
+ if (udata->decoding) {
/* Sanity check */
HDassert(udata->common.f);
HDassert(udata->common.cont_msg_info);
/* Parse the chunk */
- if(H5O_chunk_deserialize(udata->oh, udata->common.addr, udata->size, buf, &(udata->common), &chk_proxy->cache_info.is_dirty) < 0)
+ if (H5O__chunk_deserialize(udata->oh, udata->common.addr, udata->size, (const uint8_t *)image, len,
+ &(udata->common), dirty) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't deserialize object header chunk")
- /* Set the fields for the chunk proxy */
- chk_proxy->oh = udata->oh;
- chk_proxy->chunkno = udata->oh->nchunks - 1;
+ /* Set the chunk number for the chunk proxy */
+ H5_CHECKED_ASSIGN(chk_proxy->chunkno, unsigned, udata->oh->nchunks - 1, size_t);
} /* end if */
else {
/* Sanity check */
HDassert(udata->chunkno < udata->oh->nchunks);
- /* Set the fields for the chunk proxy */
- chk_proxy->oh = udata->oh;
+ /* Set the chunk number for the chunk proxy */
chk_proxy->chunkno = udata->chunkno;
- /* Sanity check that the chunk representation we have in memory is the same
- * as the one being brought in from disk.
+ /* Sanity check that the chunk representation we have in memory is
+ * the same as the one being brought in from disk.
*/
- HDassert(0 == HDmemcmp(buf, chk_proxy->oh->chunk[chk_proxy->chunkno].image, chk_proxy->oh->chunk[chk_proxy->chunkno].size));
+ HDassert(0 == HDmemcmp(image, udata->oh->chunk[chk_proxy->chunkno].image,
+ udata->oh->chunk[chk_proxy->chunkno].size));
} /* end else */
/* Increment reference count of object header */
- if(H5O_inc_rc(udata->oh) < 0)
+ if (H5O__inc_rc(udata->oh) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINC, NULL, "can't increment reference count on object header")
+ chk_proxy->oh = udata->oh;
/* Set return value */
ret_value = chk_proxy;
done:
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_CLOSEERROR, NULL, "can't close wrapped buffer")
-
- /* Release the [possibly partially initialized] object header on errors */
- if(!ret_value && chk_proxy)
- if(H5O_chunk_proxy_dest(chk_proxy) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, NULL, "unable to destroy object header chunk proxy")
+ if (NULL == ret_value)
+ if (chk_proxy && H5O__chunk_dest(chk_proxy) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, NULL, "unable to destroy object header chunk")
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_cache_chk_load() */
+} /* end H5O__cache_chk_deserialize() */
-
/*-------------------------------------------------------------------------
- * Function: H5O_cache_chk_flush
+ * Function: H5O__cache_chk_image_len
*
- * Purpose: Flushes (and destroys) an object header continuation chunk.
+ * Purpose: Return the on disk image size of a object header chunk to the
+ * metadata cache via the image_len.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Jul 12 2008
+ * Programmer: John Mainzer
+ * 7/28/14
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_cache_chk_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
- H5O_chunk_proxy_t *chk_proxy, unsigned UNUSED * flags_ptr)
+H5O__cache_chk_image_len(const void *_thing, size_t *image_len)
{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
+ const H5O_chunk_proxy_t *chk_proxy = (const H5O_chunk_proxy_t *)_thing; /* Chunk proxy to query */
- /* flush */
- if(chk_proxy->cache_info.is_dirty) {
- /* Serialize messages for this chunk */
- if(H5O_chunk_serialize(f, chk_proxy->oh, chk_proxy->chunkno) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL, "unable to serialize object header continuation chunk")
+ FUNC_ENTER_PACKAGE_NOERR
- /* Write the chunk out */
- HDassert(H5F_addr_defined(chk_proxy->oh->chunk[chk_proxy->chunkno].addr));
- HDassert(H5F_addr_eq(addr, chk_proxy->oh->chunk[chk_proxy->chunkno].addr));
- if(H5F_block_write(f, H5FD_MEM_OHDR, addr, chk_proxy->oh->chunk[chk_proxy->chunkno].size, dxpl_id, chk_proxy->oh->chunk[chk_proxy->chunkno].image) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header continuation chunk to disk")
-
- /* Mark object header as clean now */
- chk_proxy->cache_info.is_dirty = FALSE;
- } /* end if */
+ /* Check arguments */
+ HDassert(chk_proxy);
+ HDassert(chk_proxy->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(chk_proxy->cache_info.type == H5AC_OHDR_CHK);
+ HDassert(chk_proxy->oh);
+ HDassert(image_len);
- /* Destroy the object header, if requested */
- if(destroy)
- if(H5O_cache_chk_dest(f, chk_proxy) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header continuation chunk data")
+ *image_len = chk_proxy->oh->chunk[chk_proxy->chunkno].size;
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_cache_chk_flush() */
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O__cache_chk_image_len() */
-
/*-------------------------------------------------------------------------
- * Function: H5O_cache_chk_dest
+ * Function: H5O__cache_chk_serialize
*
- * Purpose: Destroys an object header continuation chunk.
+ * Purpose: Given a pointer to an instance of an object header chunk and an
+ * appropriately sized buffer, serialize the contents of the
+ * instance for writing to disk, and copy the serialized data
+ * into the buffer.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * July 12, 2008
+ * Programmer: John Mainzer
+ * 7/28/14
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_cache_chk_dest(H5F_t *f, H5O_chunk_proxy_t *chk_proxy)
+H5O__cache_chk_serialize(const H5F_t *f, void *image, size_t len, void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5O_chunk_proxy_t *chk_proxy = (H5O_chunk_proxy_t *)_thing; /* Object header chunk to serialize */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_PACKAGE
/* Check arguments */
+ HDassert(f);
+ HDassert(image);
HDassert(chk_proxy);
- HDassert(chk_proxy->chunkno > 0);
+ HDassert(chk_proxy->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(chk_proxy->cache_info.type == H5AC_OHDR_CHK);
+ HDassert(chk_proxy->oh);
+ HDassert(chk_proxy->oh->chunk[chk_proxy->chunkno].size == len);
- /* Verify that node is clean */
- HDassert(chk_proxy->cache_info.is_dirty == FALSE);
+ /* Serialize messages for this chunk */
+ if (H5O__chunk_serialize(f, chk_proxy->oh, chk_proxy->chunkno) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL, "unable to serialize object header continuation chunk")
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!chk_proxy->cache_info.free_file_space_on_destroy || H5F_addr_defined(chk_proxy->cache_info.addr));
-
- /* Check for releasing file space for object header */
- if(chk_proxy->cache_info.free_file_space_on_destroy) {
- /* Release the space on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_OHDR, H5AC_dxpl_id, chk_proxy->oh->chunk[chk_proxy->chunkno].addr, (hsize_t)chk_proxy->oh->chunk[chk_proxy->chunkno].size) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free object header continuation chunk")
- } /* end if */
-
- /* Destroy object header chunk proxy */
- if(H5O_chunk_proxy_dest(chk_proxy) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to destroy object header chunk proxy")
+ /* copy the chunk into the image -- this is potentially expensive.
+ * Can we rework things so that the chunk and the cache share a buffer?
+ */
+ H5MM_memcpy(image, chk_proxy->oh->chunk[chk_proxy->chunkno].image, len);
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_cache_chk_dest() */
+} /* end H5O__cache_chk_serialize() */
-
/*-------------------------------------------------------------------------
- * Function: H5O_cache_chk_clear
- *
- * Purpose: Mark a object header continuation chunk in memory as non-dirty.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * July 12, 2008
- *
- * Changes: In the parallel case, there is the possibility that the
- * the object header chunk may be flushed by different
- * processes over the life of the computation. Thus we must
- * ensure that the chunk image is up to date before we mark its
- * messages clean -- as otherwise we may overwrite valid
- * data with a blank section of a chunk image.
- *
- * To deal with this, I have added code to call
- * H5O_chunk_serialize() for this chunk before we
- * mark all messages as clean if we are not destroying the
- * chunk.
+ * Function: H5O__cache_chk_notify
*
- * Do this in the parallel case only, as the problem
- * can only occur in this context.
+ * Purpose: Handle cache action notifications
*
- * Note that at present at least, it seems that this fix
- * is not necessary, as we don't seem to be able to
- * generate a dirty chunk without creating a dirty object
- * header. However, the object header code will be changing
- * a lot in the near future, so I'll leave this fix in
- * for now, unless Quincey requests otherwise.
+ * Return: Non-negative on success/Negative on failure
*
- * JRM -- 10/12/10
+ * Programmer: Neil Fortner
+ * Mar 20 2012
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_cache_chk_clear(H5F_t *f, H5O_chunk_proxy_t *chk_proxy, hbool_t destroy)
+H5O__cache_chk_notify(H5AC_notify_action_t action, void *_thing)
{
- unsigned u; /* Local index variable */
- herr_t ret_value = SUCCEED;
+ H5O_chunk_proxy_t *chk_proxy = (H5O_chunk_proxy_t *)_thing;
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_PACKAGE
- /* check args */
+ /*
+ * Check arguments.
+ */
HDassert(chk_proxy);
+ HDassert(chk_proxy->oh);
+
+ switch (action) {
+ case H5AC_NOTIFY_ACTION_AFTER_INSERT:
+ case H5AC_NOTIFY_ACTION_AFTER_LOAD:
+ if (chk_proxy->oh->swmr_write) {
+ /* Add flush dependency on chunk with continuation, if one exists */
+ if (chk_proxy->fd_parent) {
+ /* Sanity checks */
+ HDassert(((H5C_cache_entry_t *)(chk_proxy->fd_parent))->magic ==
+ H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(((H5C_cache_entry_t *)(chk_proxy->fd_parent))->type);
+ HDassert((((H5C_cache_entry_t *)(chk_proxy->fd_parent))->type->id == H5AC_OHDR_ID) ||
+ (((H5C_cache_entry_t *)(chk_proxy->fd_parent))->type->id == H5AC_OHDR_CHK_ID));
+
+ /* Add flush dependency from chunk containing the continuation message
+ * that points to this chunk (either oh or another chunk proxy object)
+ */
+ if (H5AC_create_flush_dependency(chk_proxy->fd_parent, chk_proxy) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
+ } /* end if */
-#ifdef H5_HAVE_PARALLEL
- if ( ( chk_proxy->oh->cache_info.is_dirty ) && ( ! destroy ) ) {
+ /* Add flush dependency on object header */
+ {
+ if (H5AC_create_flush_dependency(chk_proxy->oh, chk_proxy) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
+ } /* end if */
- if ( H5O_chunk_serialize(f, chk_proxy->oh, chk_proxy->chunkno) < 0 ) {
+ /* Add flush dependency on object header proxy, if proxy exists */
+ {
+ /* Sanity check */
+ HDassert(chk_proxy->oh->proxy);
- HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL,
- "unable to serialize object header chunk")
- }
- }
-#endif /* H5_HAVE_PARALLEL */
+ /* Register the object header chunk as a parent of the virtual entry */
+ if (H5AC_proxy_entry_add_parent(chk_proxy->oh->proxy, chk_proxy) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL,
+ "can't add object header chunk as parent of proxy")
+ }
+ } /* end if */
+ break;
+
+ case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
+ case H5AC_NOTIFY_ACTION_ENTRY_DIRTIED:
+ /* do nothing */
+ break;
+
+ case H5AC_NOTIFY_ACTION_ENTRY_CLEANED: {
+ unsigned u; /* Local index variable */
+
+ /* Mark messages in chunk as clean */
+ for (u = 0; u < chk_proxy->oh->nmesgs; u++)
+ if (chk_proxy->oh->mesg[u].chunkno == chk_proxy->chunkno)
+ chk_proxy->oh->mesg[u].dirty = FALSE;
+ } break;
+
+ case H5AC_NOTIFY_ACTION_CHILD_DIRTIED:
+ case H5AC_NOTIFY_ACTION_CHILD_CLEANED:
+ case H5AC_NOTIFY_ACTION_CHILD_UNSERIALIZED:
+ case H5AC_NOTIFY_ACTION_CHILD_SERIALIZED:
+ /* do nothing */
+ break;
+
+ case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
+ if (chk_proxy->oh->swmr_write) {
+ /* Remove flush dependency on parent object header chunk, if one is set */
+ if (chk_proxy->fd_parent) {
+ /* Sanity checks */
+ HDassert(((H5C_cache_entry_t *)(chk_proxy->fd_parent))->magic ==
+ H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(((H5C_cache_entry_t *)(chk_proxy->fd_parent))->type);
+ HDassert((((H5C_cache_entry_t *)(chk_proxy->fd_parent))->type->id == H5AC_OHDR_ID) ||
+ (((H5C_cache_entry_t *)(chk_proxy->fd_parent))->type->id == H5AC_OHDR_CHK_ID));
+
+ if (H5AC_destroy_flush_dependency(chk_proxy->fd_parent, chk_proxy) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency")
+ chk_proxy->fd_parent = NULL;
+ } /* end if */
- /* Mark messages in chunk as clean */
- for(u = 0; u < chk_proxy->oh->nmesgs; u++)
- if(chk_proxy->oh->mesg[u].chunkno == chk_proxy->chunkno)
- chk_proxy->oh->mesg[u].dirty = FALSE;
+ /* Unregister the object header as a parent of the virtual entry */
+ if (H5AC_destroy_flush_dependency(chk_proxy->oh, chk_proxy) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency")
- /* Mark as clean */
- chk_proxy->cache_info.is_dirty = FALSE;
+ /* Unregister the object header chunk as a parent of the virtual entry */
+ if (H5AC_proxy_entry_remove_parent(chk_proxy->oh->proxy, chk_proxy) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL,
+ "can't remove object header chunk as parent of proxy")
+ } /* end if */
+ break;
- if(destroy)
- if(H5O_cache_chk_dest(f, chk_proxy) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header continuation chunk data")
+ default:
+#ifdef NDEBUG
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unknown action from metadata cache")
+#else /* NDEBUG */
+ HDassert(0 && "Unknown action?!?");
+#endif /* NDEBUG */
+ } /* end switch */
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_cache_chk_clear() */
+} /* end H5O__cache_chk_notify() */
-
/*-------------------------------------------------------------------------
- * Function: H5O_cache_chk_size
+ * Function: H5O__cache_chk_free_icr
*
- * Purpose: Compute the size in bytes of the specified instance of
- * an object header continuation chunk on disk, and return it in
- * *len_ptr. On failure, the value of *len_ptr is undefined.
+ * Purpose: Free the in core memory associated with the supplied object
+ * header continuation chunk.
*
- * Return: Non-negative on success/Negative on failure
+ * Note: The metadata cache sets the object's cache_info.magic to
+ * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr
+ * callback (checked in assert).
*
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * July 12, 2008
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 7/28/14
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_cache_chk_size(const H5F_t UNUSED *f, const H5O_chunk_proxy_t *chk_proxy, size_t *size_ptr)
+H5O__cache_chk_free_icr(void *_thing)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ H5O_chunk_proxy_t *chk_proxy = (H5O_chunk_proxy_t *)_thing; /* Object header chunk proxy to release */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
- /* check args */
+ /* Check arguments */
HDassert(chk_proxy);
- HDassert(size_ptr);
+ HDassert(chk_proxy->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
+ HDassert(chk_proxy->cache_info.type == H5AC_OHDR_CHK);
- /* Report the object header continuation chunk's length */
- *size_ptr = chk_proxy->oh->chunk[chk_proxy->chunkno].size;
+ /* Destroy object header chunk proxy */
+ if (H5O__chunk_dest(chk_proxy) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to destroy object header chunk proxy")
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5O_cache_chk_size() */
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O__cache_chk_free_icr() */
-
/*-------------------------------------------------------------------------
- * Function: H5O_add_cont_msg
+ * Function: H5O__add_cont_msg
*
* Purpose: Add information from a continuation message to the list of
* continuation messages in the object header
@@ -975,47 +1052,216 @@ H5O_cache_chk_size(const H5F_t UNUSED *f, const H5O_chunk_proxy_t *chk_proxy, si
* Failure: FAIL
*
* Programmer: Quincey Koziol
- * koziol@hdfgroup.org
* July 12, 2008
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_add_cont_msg(H5O_cont_msgs_t *cont_msg_info, const H5O_cont_t *cont)
+H5O__add_cont_msg(H5O_cont_msgs_t *cont_msg_info, const H5O_cont_t *cont)
{
size_t contno; /* Continuation message index */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_PACKAGE
/* Check arguments */
HDassert(cont_msg_info);
HDassert(cont);
/* Increase chunk array size, if necessary */
- if(cont_msg_info->nmsgs >= cont_msg_info->alloc_nmsgs) {
- size_t na = MAX(H5O_NCHUNKS, cont_msg_info->alloc_nmsgs * 2); /* Double # of messages allocated */
+ if (cont_msg_info->nmsgs >= cont_msg_info->alloc_nmsgs) {
+ size_t na = MAX(H5O_NCHUNKS, cont_msg_info->alloc_nmsgs * 2); /* Double # of messages allocated */
H5O_cont_t *x;
- if(NULL == (x = H5FL_SEQ_REALLOC(H5O_cont_t, cont_msg_info->msgs, na)))
+ if (NULL == (x = H5FL_SEQ_REALLOC(H5O_cont_t, cont_msg_info->msgs, na)))
HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, FAIL, "memory allocation failed")
cont_msg_info->alloc_nmsgs = na;
- cont_msg_info->msgs = x;
+ cont_msg_info->msgs = x;
} /* end if */
/* Init the continuation message info */
- contno = cont_msg_info->nmsgs++;
- cont_msg_info->msgs[contno].addr = cont->addr;
- cont_msg_info->msgs[contno].size = cont->size;
+ contno = cont_msg_info->nmsgs++;
+ cont_msg_info->msgs[contno].addr = cont->addr;
+ cont_msg_info->msgs[contno].size = cont->size;
cont_msg_info->msgs[contno].chunkno = cont->chunkno;
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5O_add_cont_msg() */
+} /* H5O__add_cont_msg() */
-
/*-------------------------------------------------------------------------
- * Function: H5O_chunk_deserialize
+ * Function: H5O__prefix_deserialize()
+ *
+ * Purpose: Deserialize an object header prefix
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Quincey Koziol
+ * December 14, 2016
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O__prefix_deserialize(const uint8_t *_image, H5O_cache_ud_t *udata)
+{
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ H5O_t *oh = NULL; /* Object header read in */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Check arguments */
+ HDassert(image);
+ HDassert(udata);
+
+ /* Allocate space for the new object header data structure */
+ if (NULL == (oh = H5FL_CALLOC(H5O_t)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, FAIL, "memory allocation failed")
+
+ /* File-specific, non-stored information */
+ oh->sizeof_size = H5F_SIZEOF_SIZE(udata->common.f);
+ oh->sizeof_addr = H5F_SIZEOF_ADDR(udata->common.f);
+
+ /* Check for presence of magic number */
+ /* (indicates version 2 or later) */
+ if (!HDmemcmp(image, H5O_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC)) {
+ /* Magic number */
+ image += H5_SIZEOF_MAGIC;
+
+ /* Version */
+ oh->version = *image++;
+ if (H5O_VERSION_2 != oh->version)
+ HGOTO_ERROR(H5E_OHDR, H5E_VERSION, FAIL, "bad object header version number")
+
+ /* Flags */
+ oh->flags = *image++;
+ if (oh->flags & ~H5O_HDR_ALL_FLAGS)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unknown object header status flag(s)")
+
+ /* Number of links to object (unless overridden by refcount message) */
+ oh->nlink = 1;
+
+ /* Time fields */
+ if (oh->flags & H5O_HDR_STORE_TIMES) {
+ uint32_t tmp; /* Temporary value */
+
+ UINT32DECODE(image, tmp);
+ oh->atime = (time_t)tmp;
+ UINT32DECODE(image, tmp);
+ oh->mtime = (time_t)tmp;
+ UINT32DECODE(image, tmp);
+ oh->ctime = (time_t)tmp;
+ UINT32DECODE(image, tmp);
+ oh->btime = (time_t)tmp;
+ } /* end if */
+ else
+ oh->atime = oh->mtime = oh->ctime = oh->btime = 0;
+
+ /* Attribute fields */
+ if (oh->flags & H5O_HDR_ATTR_STORE_PHASE_CHANGE) {
+ UINT16DECODE(image, oh->max_compact);
+ UINT16DECODE(image, oh->min_dense);
+ if (oh->max_compact < oh->min_dense)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad object header attribute phase change values")
+ } /* end if */
+ else {
+ oh->max_compact = H5O_CRT_ATTR_MAX_COMPACT_DEF;
+ oh->min_dense = H5O_CRT_ATTR_MIN_DENSE_DEF;
+ } /* end else */
+
+ /* First chunk size */
+ switch (oh->flags & H5O_HDR_CHUNK0_SIZE) {
+ case 0: /* 1 byte size */
+ udata->chunk0_size = *image++;
+ break;
+
+ case 1: /* 2 byte size */
+ UINT16DECODE(image, udata->chunk0_size);
+ break;
+
+ case 2: /* 4 byte size */
+ UINT32DECODE(image, udata->chunk0_size);
+ break;
+
+ case 3: /* 8 byte size */
+ UINT64DECODE(image, udata->chunk0_size);
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad size for chunk 0")
+ } /* end switch */
+ if (udata->chunk0_size > 0 && udata->chunk0_size < H5O_SIZEOF_MSGHDR_OH(oh))
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad object header chunk size")
+ } /* end if */
+ else {
+ /* Version */
+ oh->version = *image++;
+ if (H5O_VERSION_1 != oh->version)
+ HGOTO_ERROR(H5E_OHDR, H5E_VERSION, FAIL, "bad object header version number")
+
+ /* Flags */
+ oh->flags = H5O_CRT_OHDR_FLAGS_DEF;
+
+ /* Reserved */
+ image++;
+
+ /* Number of messages */
+ UINT16DECODE(image, udata->v1_pfx_nmesgs);
+
+ /* Link count */
+ UINT32DECODE(image, oh->nlink);
+
+ /* Reset unused time fields */
+ oh->atime = oh->mtime = oh->ctime = oh->btime = 0;
+
+ /* Reset unused attribute fields */
+ oh->max_compact = 0;
+ oh->min_dense = 0;
+
+ /* First chunk size */
+ UINT32DECODE(image, udata->chunk0_size);
+ if ((udata->v1_pfx_nmesgs > 0 && udata->chunk0_size < H5O_SIZEOF_MSGHDR_OH(oh)) ||
+ (udata->v1_pfx_nmesgs == 0 && udata->chunk0_size > 0))
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad object header chunk size")
+
+ /* Reserved, in version 1 (for 8-byte alignment padding) */
+ image += 4;
+ } /* end else */
+
+ /* Verify object header prefix length */
+ HDassert((size_t)(image - _image) == (size_t)(H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh)));
+
+ /* If udata->oh is to be freed (see H5O__cache_verify_chksum),
+ save the pointer to udata->oh and free it later after setting
+ udata->oh with the new object header */
+ if (udata->free_oh) {
+ H5O_t *saved_oh = udata->oh;
+ HDassert(udata->oh);
+
+ /* Save the object header for later use in 'deserialize' callback */
+ udata->oh = oh;
+ if (H5O__free(saved_oh, FALSE) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't destroy object header")
+ udata->free_oh = FALSE;
+ }
+ else
+ /* Save the object header for later use in 'deserialize' callback */
+ udata->oh = oh;
+
+ oh = NULL;
+
+done:
+ /* Release the [possibly partially initialized] object header on errors */
+ if (ret_value < 0 && oh)
+ if (H5O__free(oh, FALSE) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to destroy object header data")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O__prefix_deserialize() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5O__chunk_deserialize
*
* Purpose: Deserialize a chunk for an object header
*
@@ -1023,198 +1269,208 @@ done:
* Failure: FAIL
*
* Programmer: Quincey Koziol
- * koziol@hdfgroup.org
* July 12, 2008
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_chunk_deserialize(H5O_t *oh, haddr_t addr, size_t len, const uint8_t *image,
- H5O_common_cache_ud_t *udata, hbool_t *dirty)
+H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t chunk_size, const uint8_t *image, size_t len,
+ H5O_common_cache_ud_t *udata, hbool_t *dirty)
{
- const uint8_t *p; /* Pointer into buffer to decode */
- uint8_t *eom_ptr; /* Pointer to end of messages for a chunk */
- size_t curmesg; /* Current message being decoded in object header */
- unsigned merged_null_msgs = 0; /* Number of null messages merged together */
- unsigned chunkno; /* Current chunk's index */
+ const uint8_t *chunk_image; /* Pointer into buffer to decode */
+ uint8_t *eom_ptr; /* Pointer to end of messages for a chunk */
+ unsigned merged_null_msgs = 0; /* Number of null messages merged together */
+ unsigned chunkno; /* Current chunk's index */
#ifndef NDEBUG
- unsigned nullcnt; /* Count of null messages (for sanity checking gaps in chunks) */
-#endif /* NDEBUG */
+ unsigned nullcnt; /* Count of null messages (for sanity checking gaps in chunks) */
+#endif /* NDEBUG */
+ hbool_t mesgs_modified =
+ FALSE; /* Whether any messages were modified when the object header was deserialized */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_PACKAGE
/* Check arguments */
HDassert(oh);
HDassert(H5F_addr_defined(addr));
HDassert(image);
+ HDassert(len);
HDassert(udata->f);
HDassert(udata->cont_msg_info);
/* Increase chunk array size, if necessary */
- if(oh->nchunks >= oh->alloc_nchunks) {
- size_t na = MAX(H5O_NCHUNKS, oh->alloc_nchunks * 2); /* Double # of chunks allocated */
+ if (oh->nchunks >= oh->alloc_nchunks) {
+ size_t na = MAX(H5O_NCHUNKS, oh->alloc_nchunks * 2); /* Double # of chunks allocated */
H5O_chunk_t *x;
- if(NULL == (x = H5FL_SEQ_REALLOC(H5O_chunk_t, oh->chunk, na)))
+ if (NULL == (x = H5FL_SEQ_REALLOC(H5O_chunk_t, oh->chunk, na)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, FAIL, "memory allocation failed")
oh->alloc_nchunks = na;
- oh->chunk = x;
+ oh->chunk = x;
} /* end if */
/* Init the chunk data info */
- chunkno = oh->nchunks++;
- oh->chunk[chunkno].gap = 0;
- if(chunkno == 0) {
+ chunkno = (unsigned)oh->nchunks++;
+ oh->chunk[chunkno].gap = 0;
+ oh->chunk[chunkno].addr = addr;
+ if (chunkno == 0)
/* First chunk's 'image' includes room for the object header prefix */
- oh->chunk[0].addr = addr;
- oh->chunk[0].size = len + (size_t)H5O_SIZEOF_HDR(oh);
- } /* end if */
- else {
- oh->chunk[chunkno].addr = addr;
- oh->chunk[chunkno].size = len;
- } /* end else */
- if(NULL == (oh->chunk[chunkno].image = H5FL_BLK_MALLOC(chunk_image, oh->chunk[chunkno].size)))
+ oh->chunk[0].size = chunk_size + (size_t)H5O_SIZEOF_HDR(oh);
+ else
+ oh->chunk[chunkno].size = chunk_size;
+ if (NULL == (oh->chunk[chunkno].image = H5FL_BLK_MALLOC(chunk_image, oh->chunk[chunkno].size)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, FAIL, "memory allocation failed")
+ oh->chunk[chunkno].chunk_proxy = NULL;
/* Copy disk image into chunk's image */
- HDmemcpy(oh->chunk[chunkno].image, image, oh->chunk[chunkno].size);
+ if (len < oh->chunk[chunkno].size)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "attempted to copy too many disk image bytes into buffer")
+ H5MM_memcpy(oh->chunk[chunkno].image, image, oh->chunk[chunkno].size);
/* Point into chunk image to decode */
- p = oh->chunk[chunkno].image;
+ chunk_image = oh->chunk[chunkno].image;
/* Handle chunk 0 as special case */
- if(chunkno == 0)
+ if (chunkno == 0)
/* Skip over [already decoded] prefix */
- p += (size_t)(H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh));
+ chunk_image += (size_t)(H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh));
/* Check for magic # on chunks > 0 in later versions of the format */
- else if(chunkno > 0 && oh->version > H5O_VERSION_1) {
+ else if (chunkno > 0 && oh->version > H5O_VERSION_1) {
/* Magic number */
- if(HDmemcmp(p, H5O_CHK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ if (HDmemcmp(chunk_image, H5O_CHK_MAGIC, (size_t)H5_SIZEOF_MAGIC) != 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "wrong object header chunk signature")
- p += H5_SIZEOF_MAGIC;
+ chunk_image += H5_SIZEOF_MAGIC;
} /* end if */
- /* Save # of messages already inspected */
- curmesg = oh->nmesgs;
-
/* Decode messages from this chunk */
eom_ptr = oh->chunk[chunkno].image + (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM_OH(oh));
#ifndef NDEBUG
nullcnt = 0;
#endif /* NDEBUG */
- while(p < eom_ptr) {
- size_t 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 */
- H5O_msg_crt_idx_t crt_idx = 0; /* Creation index for current message */
+ while (chunk_image < eom_ptr) {
+ size_t mesg_size; /* Size of message read in */
+ unsigned id; /* ID (type) of current message */
+ uint8_t flags; /* Flags for current message */
+ H5O_msg_crt_idx_t crt_idx = 0; /* Creation index for current message */
/* Decode message prefix info */
/* Version # */
- if(oh->version == H5O_VERSION_1)
- UINT16DECODE(p, id)
+ if (oh->version == H5O_VERSION_1)
+ UINT16DECODE(chunk_image, id)
else
- id = *p++;
-
- /* Check for unknown message ID getting encoded in file */
- if(id == H5O_UNKNOWN_ID)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "'unknown' message ID encoded in file?!?")
+ id = *chunk_image++;
/* Message size */
- UINT16DECODE(p, mesg_size);
- HDassert(mesg_size == H5O_ALIGN_OH(oh, mesg_size));
+ UINT16DECODE(chunk_image, mesg_size);
+ if (mesg_size != H5O_ALIGN_OH(oh, mesg_size))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "message not aligned")
/* Message flags */
- flags = *p++;
- if(flags & ~H5O_MSG_FLAG_BITS)
+ flags = *chunk_image++;
+ if (flags & ~H5O_MSG_FLAG_BITS)
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unknown flag for message")
- if((flags & H5O_MSG_FLAG_SHARED) && (flags & H5O_MSG_FLAG_DONTSHARE))
+ if ((flags & H5O_MSG_FLAG_SHARED) && (flags & H5O_MSG_FLAG_DONTSHARE))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "bad flag combination for message")
- if((flags & H5O_MSG_FLAG_WAS_UNKNOWN) && (flags & H5O_MSG_FLAG_FAIL_IF_UNKNOWN_AND_OPEN_FOR_WRITE))
+ if ((flags & H5O_MSG_FLAG_WAS_UNKNOWN) && (flags & H5O_MSG_FLAG_FAIL_IF_UNKNOWN_AND_OPEN_FOR_WRITE))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "bad flag combination for message")
- if((flags & H5O_MSG_FLAG_WAS_UNKNOWN) && !(flags & H5O_MSG_FLAG_MARK_IF_UNKNOWN))
+ if ((flags & H5O_MSG_FLAG_WAS_UNKNOWN) && !(flags & H5O_MSG_FLAG_MARK_IF_UNKNOWN))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "bad flag combination for message")
+ /* Delay checking the "shareable" flag until we've made sure id
+ * references a valid message class that this version of the library
+ * knows about */
/* Reserved bytes/creation index */
- if(oh->version == H5O_VERSION_1)
- p += 3; /*reserved*/
+ if (oh->version == H5O_VERSION_1)
+ chunk_image += 3; /*reserved*/
else {
/* Only decode creation index if they are being tracked */
- if(oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED)
- UINT16DECODE(p, crt_idx);
+ if (oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED)
+ UINT16DECODE(chunk_image, crt_idx);
} /* end else */
/* Try to detect invalidly formatted object header message that
* extends past end of chunk.
*/
- if(p + mesg_size > eom_ptr)
+ if (chunk_image + mesg_size > eom_ptr)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "corrupt object header")
#ifndef NDEBUG
/* Increment count of null messages */
- if(H5O_NULL_ID == id)
+ if (H5O_NULL_ID == id)
nullcnt++;
#endif /* NDEBUG */
/* Check for combining two adjacent 'null' messages */
- if((udata->file_intent & 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) {
+ if ((udata->file_intent & 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) {
+
+ size_t mesgno; /* Current message to operate on */
/* Combine adjacent null messages */
mesgno = oh->nmesgs - 1;
oh->mesg[mesgno].raw_size += (size_t)H5O_SIZEOF_MSGHDR_OH(oh) + mesg_size;
oh->mesg[mesgno].dirty = TRUE;
merged_null_msgs++;
- udata->merged_null_msgs++;
} /* end if */
else {
+ H5O_mesg_t *mesg; /* Pointer to new message */
+ unsigned ioflags = 0; /* Flags for decode routine */
+
/* Check if we need to extend message table to hold the new message */
- if(oh->nmesgs >= oh->alloc_nmesgs)
- if(H5O_alloc_msgs(oh, (size_t)1) < 0)
+ if (oh->nmesgs >= oh->alloc_nmesgs)
+ if (H5O__alloc_msgs(oh, (size_t)1) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, FAIL, "can't allocate more space for messages")
- /* Get index for message */
- mesgno = oh->nmesgs++;
+ /* Get pointer to message to set up */
+ mesg = &oh->mesg[oh->nmesgs];
+
+ /* Increment # of messages */
+ oh->nmesgs++;
/* Initialize information about message */
- oh->mesg[mesgno].dirty = FALSE;
- oh->mesg[mesgno].flags = flags;
- oh->mesg[mesgno].crt_idx = crt_idx;
- oh->mesg[mesgno].native = NULL;
- oh->mesg[mesgno].raw = (uint8_t *)p; /* Casting away const OK - QAK */
- oh->mesg[mesgno].raw_size = mesg_size;
- oh->mesg[mesgno].chunkno = chunkno;
+ mesg->dirty = FALSE;
+ mesg->flags = flags;
+ mesg->crt_idx = crt_idx;
+ mesg->native = NULL;
+ H5_GCC_CLANG_DIAG_OFF("cast-qual")
+ mesg->raw = (uint8_t *)chunk_image;
+ H5_GCC_CLANG_DIAG_ON("cast-qual")
+ mesg->raw_size = mesg_size;
+ mesg->chunkno = chunkno;
/* Point unknown messages at 'unknown' message class */
/* (Usually from future versions of the library) */
- if(id >= NELMTS(H5O_msg_class_g) || NULL == H5O_msg_class_g[id]) {
- H5O_unknown_t *unknown; /* Pointer to "unknown" message info */
+ if (id >= H5O_UNKNOWN_ID ||
+#ifdef H5O_ENABLE_BOGUS
+ id == H5O_BOGUS_VALID_ID ||
+#endif
+ NULL == H5O_msg_class_g[id]) {
+
+ H5O_unknown_t *unknown; /* Pointer to "unknown" message info */
/* Allocate "unknown" message info */
- if(NULL == (unknown = H5FL_MALLOC(H5O_unknown_t)))
+ if (NULL == (unknown = H5FL_MALLOC(H5O_unknown_t)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, FAIL, "memory allocation failed")
/* Save the original message type ID */
*unknown = id;
/* Save 'native' form of unknown message */
- oh->mesg[mesgno].native = unknown;
+ mesg->native = unknown;
/* Set message to "unknown" class */
- oh->mesg[mesgno].type = H5O_msg_class_g[H5O_UNKNOWN_ID];
-
- /* Check for "fail if unknown" message flag */
- if((udata->file_intent & H5F_ACC_RDWR) &&
- (flags & H5O_MSG_FLAG_FAIL_IF_UNKNOWN_AND_OPEN_FOR_WRITE))
- HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "unknown message with 'fail if unknown' flag found")
+ mesg->type = H5O_msg_class_g[H5O_UNKNOWN_ID];
+
+ /* Check for "fail if unknown" message flags */
+ if (((udata->file_intent & H5F_ACC_RDWR) &&
+ (flags & H5O_MSG_FLAG_FAIL_IF_UNKNOWN_AND_OPEN_FOR_WRITE)) ||
+ (flags & H5O_MSG_FLAG_FAIL_IF_UNKNOWN_ALWAYS))
+ HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL,
+ "unknown message with 'fail if unknown' flag found")
/* Check for "mark if unknown" message flag, etc. */
- else if((flags & H5O_MSG_FLAG_MARK_IF_UNKNOWN) &&
- !(flags & H5O_MSG_FLAG_WAS_UNKNOWN) &&
- (udata->file_intent & H5F_ACC_RDWR)) {
+ else if ((flags & H5O_MSG_FLAG_MARK_IF_UNKNOWN) && !(flags & H5O_MSG_FLAG_WAS_UNKNOWN) &&
+ (udata->file_intent & H5F_ACC_RDWR)) {
/* Mark the message as "unknown" */
/* This is a bit aggressive, since the application may
@@ -1227,24 +1483,88 @@ H5O_chunk_deserialize(H5O_t *oh, haddr_t addr, size_t len, const uint8_t *image,
* the metadata cache in some other "weird" way, like
* using H5Ocopy() - QAK
*/
- oh->mesg[mesgno].flags |= H5O_MSG_FLAG_WAS_UNKNOWN;
+ mesg->flags |= H5O_MSG_FLAG_WAS_UNKNOWN;
/* Mark the message and chunk as dirty */
- oh->mesg[mesgno].dirty = TRUE;
- udata->mesgs_modified = TRUE;
- *dirty = TRUE;
+ mesg->dirty = TRUE;
+ mesgs_modified = TRUE;
} /* end if */
- } /* end if */
- else
+ } /* end if */
+ else {
+ /* Check for message of unshareable class marked as "shareable"
+ */
+ if ((flags & H5O_MSG_FLAG_SHAREABLE) && H5O_msg_class_g[id] &&
+ !(H5O_msg_class_g[id]->share_flags & H5O_SHARE_IS_SHARABLE))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL,
+ "message of unshareable class flagged as shareable")
+
/* Set message class for "known" messages */
- oh->mesg[mesgno].type = H5O_msg_class_g[id];
- } /* end else */
+ mesg->type = H5O_msg_class_g[id];
+ } /* end else */
+
+ /* Do some inspection/interpretation of new messages from this chunk */
+ /* (detect continuation messages, ref. count messages, etc.) */
+
+ /* Check if message is a continuation message */
+ if (H5O_CONT_ID == id) {
+ H5O_cont_t *cont;
+
+ /* Decode continuation message */
+ cont = (H5O_cont_t *)(H5O_MSG_CONT->decode)(udata->f, NULL, 0, &ioflags, mesg->raw_size,
+ mesg->raw);
+ H5_CHECKED_ASSIGN(cont->chunkno, unsigned, udata->cont_msg_info->nmsgs + 1,
+ size_t); /* the next continuation message/chunk */
+
+ /* Save 'native' form of continuation message */
+ mesg->native = cont;
+
+ /* Add to continuation messages left to interpret */
+ if (H5O__add_cont_msg(udata->cont_msg_info, cont) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't add continuation message")
+ } /* end if */
+ /* Check if message is a ref. count message */
+ else if (H5O_REFCOUNT_ID == id) {
+ H5O_refcount_t *refcount;
+
+ /* Decode ref. count message */
+ if (oh->version <= H5O_VERSION_1)
+ HGOTO_ERROR(H5E_OHDR, H5E_VERSION, FAIL,
+ "object header version does not support reference count message")
+ refcount = (H5O_refcount_t *)(H5O_MSG_REFCOUNT->decode)(udata->f, NULL, 0, &ioflags,
+ mesg->raw_size, mesg->raw);
+
+ /* Save 'native' form of ref. count message */
+ mesg->native = refcount;
+
+ /* Set object header values */
+ oh->has_refcount_msg = TRUE;
+ if (!refcount)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't decode refcount")
+ oh->nlink = *refcount;
+ } /* end if */
+ /* Check if message is a link message */
+ else if (H5O_LINK_ID == id) {
+ /* Increment the count of link messages */
+ oh->link_msgs_seen++;
+ } /* end if */
+ /* Check if message is an attribute message */
+ else if (H5O_ATTR_ID == id) {
+ /* Increment the count of attribute messages */
+ oh->attr_msgs_seen++;
+ } /* end if */
+
+ /* Mark the message & chunk as dirty if the message was changed by decoding */
+ if ((ioflags & H5O_DECODEIO_DIRTY) && (udata->file_intent & H5F_ACC_RDWR)) {
+ mesg->dirty = TRUE;
+ mesgs_modified = TRUE;
+ } /* end if */
+ } /* end else */
/* Advance decode pointer past message */
- p += mesg_size;
+ chunk_image += mesg_size;
/* Check for 'gap' at end of chunk */
- if((eom_ptr - p) > 0 && (eom_ptr - p) < H5O_SIZEOF_MSGHDR_OH(oh)) {
+ if ((eom_ptr - chunk_image) > 0 && (eom_ptr - chunk_image) < H5O_SIZEOF_MSGHDR_OH(oh)) {
/* Gaps can only occur in later versions of the format */
HDassert(oh->version > H5O_VERSION_1);
@@ -1252,109 +1572,46 @@ H5O_chunk_deserialize(H5O_t *oh, haddr_t addr, size_t len, const uint8_t *image,
HDassert(nullcnt == 0);
/* Set gap information for chunk */
- oh->chunk[chunkno].gap = (size_t)(eom_ptr - p);
+ oh->chunk[chunkno].gap = (size_t)(eom_ptr - chunk_image);
/* Increment location in chunk */
- p += oh->chunk[chunkno].gap;
+ chunk_image += oh->chunk[chunkno].gap;
} /* end if */
- } /* end while */
+ } /* 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);
+ if (oh->version > H5O_VERSION_1) {
+ uint32_t stored_chksum; /* Checksum from file */
- /* Compute checksum on chunk */
- computed_chksum = H5_checksum_metadata(oh->chunk[chunkno].image, (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM), 0);
+ /* checksum verification already done in verify_chksum cb */
- /* Verify checksum */
- if(stored_chksum != computed_chksum)
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "incorrect metadata checksum for object header chunk")
+ /* Metadata checksum */
+ UINT32DECODE(chunk_image, stored_chksum);
} /* end if */
/* Sanity check */
- HDassert(p == oh->chunk[chunkno].image + oh->chunk[chunkno].size);
-
- /* Do some inspection/interpretation of new messages from this chunk */
- /* (detect continuation messages, ref. count messages, etc.) */
- while(curmesg < oh->nmesgs) {
- /* Check if next message to examine is a continuation message */
- if(H5O_CONT_ID == oh->mesg[curmesg].type->id) {
- H5O_cont_t *cont;
- unsigned ioflags = 0; /* Flags for decode routine */
-
- /* Decode continuation message */
- cont = (H5O_cont_t *)(H5O_MSG_CONT->decode)(udata->f, udata->dxpl_id, NULL, 0, &ioflags, oh->mesg[curmesg].raw);
- cont->chunkno = udata->cont_msg_info->nmsgs + 1; /*the next continuation message/chunk */
-
- /* Save 'native' form of continuation message */
- oh->mesg[curmesg].native = cont;
-
- /* Add to continuation messages left to interpret */
- if(H5O_add_cont_msg(udata->cont_msg_info, cont) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't add continuation message")
-
- /* Mark the message & chunk as dirty if the message was changed by decoding */
- if((ioflags & H5O_DECODEIO_DIRTY) && (udata->file_intent & H5F_ACC_RDWR)) {
- oh->mesg[curmesg].dirty = TRUE;
- udata->mesgs_modified = TRUE;
- *dirty = TRUE;
- } /* end if */
- } /* 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;
- unsigned ioflags = 0; /* Flags for decode routine */
-
- /* Decode ref. count message */
- HDassert(oh->version > H5O_VERSION_1);
- refcount = (H5O_refcount_t *)(H5O_MSG_REFCOUNT->decode)(udata->f, udata->dxpl_id, NULL, 0, &ioflags, 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;
-
- /* Mark the message & chunk as dirty if the message was changed by decoding */
- if((ioflags & H5O_DECODEIO_DIRTY) && (udata->file_intent & H5F_ACC_RDWR)) {
- oh->mesg[curmesg].dirty = TRUE;
- udata->mesgs_modified = TRUE;
- *dirty = TRUE;
- } /* end if */
- } /* end if */
- /* Check if next message to examine is a link message */
- else if(H5O_LINK_ID == oh->mesg[curmesg].type->id) {
- /* Increment the count of link messages */
- oh->link_msgs_seen++;
- } /* end if */
- /* Check if next message to examine is an attribute message */
- else if(H5O_ATTR_ID == oh->mesg[curmesg].type->id) {
- /* Increment the count of attribute messages */
- oh->attr_msgs_seen++;
- } /* end if */
+ HDassert(chunk_image == oh->chunk[chunkno].image + oh->chunk[chunkno].size);
- /* Advance to next message */
- curmesg++;
- } /* end while */
+ /* Mark the chunk dirty if we've modified messages */
+ if (mesgs_modified)
+ *dirty = TRUE;
/* Mark the chunk dirty if we've merged null messages */
- if(merged_null_msgs) {
- udata->mesgs_modified = TRUE;
- *dirty = TRUE;
+ if (merged_null_msgs > 0) {
+ udata->merged_null_msgs += merged_null_msgs;
+ *dirty = TRUE;
} /* end if */
done:
+ if (ret_value < 0 && udata->cont_msg_info->msgs) {
+ udata->cont_msg_info->msgs = H5FL_SEQ_FREE(H5O_cont_t, udata->cont_msg_info->msgs);
+ udata->cont_msg_info->alloc_nmsgs = 0;
+ }
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5O_chunk_deserialize() */
+} /* H5O__chunk_deserialize() */
-
/*-------------------------------------------------------------------------
- * Function: H5O_chunk_serialize
+ * Function: H5O__chunk_serialize
*
* Purpose: Serialize a chunk for an object header
*
@@ -1362,94 +1619,61 @@ done:
* Failure: FAIL
*
* Programmer: Quincey Koziol
- * koziol@hdfgroup.org
* July 12, 2008
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_chunk_serialize(const H5F_t *f, H5O_t *oh, unsigned chunkno)
+H5O__chunk_serialize(const H5F_t *f, H5O_t *oh, unsigned chunkno)
{
- H5O_mesg_t *curr_msg; /* Pointer to current message being operated on */
- unsigned u; /* Local index variable */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5O_mesg_t *curr_msg; /* Pointer to current message being operated on */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_PACKAGE
/* Check arguments */
HDassert(f);
HDassert(oh);
/* Encode any dirty messages in this chunk */
- for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++)
- if(curr_msg->dirty && curr_msg->chunkno == chunkno)
- /* Casting away const OK -QAK */
- if(H5O_msg_flush((H5F_t *)f, oh, curr_msg) < 0)
+ for (u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++)
+ if (curr_msg->dirty && curr_msg->chunkno == chunkno) {
+ H5_GCC_CLANG_DIAG_OFF("cast-qual")
+ if (H5O_msg_flush((H5F_t *)f, oh, curr_msg) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "unable to encode object header message")
+ H5_GCC_CLANG_DIAG_ON("cast-qual")
+ }
/* Sanity checks */
- if(oh->version > H5O_VERSION_1)
+ if (oh->version > H5O_VERSION_1)
/* Make certain the magic # is present */
- HDassert(!HDmemcmp(oh->chunk[chunkno].image, (chunkno == 0 ? H5O_HDR_MAGIC : H5O_CHK_MAGIC), H5_SIZEOF_MAGIC));
+ HDassert(!HDmemcmp(oh->chunk[chunkno].image, (chunkno == 0 ? H5O_HDR_MAGIC : H5O_CHK_MAGIC),
+ H5_SIZEOF_MAGIC));
else
/* Gaps should never occur in version 1 of the format */
HDassert(oh->chunk[chunkno].gap == 0);
/* Extra work, for later versions of the format */
- if(oh->version > H5O_VERSION_1) {
- uint32_t metadata_chksum; /* Computed metadata checksum value */
- uint8_t *p; /* Pointer into object header chunk */
+ if (oh->version > H5O_VERSION_1) {
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
+ uint8_t *chunk_image; /* Pointer into object header chunk */
/* Check for gap in chunk & zero it out */
- if(oh->chunk[chunkno].gap)
+ if (oh->chunk[chunkno].gap)
HDmemset((oh->chunk[chunkno].image + oh->chunk[chunkno].size) -
- (H5O_SIZEOF_CHKSUM + oh->chunk[chunkno].gap), 0, oh->chunk[chunkno].gap);
+ (H5O_SIZEOF_CHKSUM + oh->chunk[chunkno].gap),
+ 0, oh->chunk[chunkno].gap);
/* Compute metadata checksum */
- metadata_chksum = H5_checksum_metadata(oh->chunk[chunkno].image, (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM), 0);
+ metadata_chksum =
+ H5_checksum_metadata(oh->chunk[chunkno].image, (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM), 0);
/* Metadata checksum */
- p = oh->chunk[chunkno].image + (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM);
- UINT32ENCODE(p, metadata_chksum);
+ chunk_image = oh->chunk[chunkno].image + (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM);
+ UINT32ENCODE(chunk_image, metadata_chksum);
} /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5O_chunk_serialize() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5O_chunk_proxy_dest
- *
- * Purpose: Destroy a chunk proxy object
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * July 13, 2008
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5O_chunk_proxy_dest(H5O_chunk_proxy_t *chk_proxy)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- /* Check arguments */
- HDassert(chk_proxy);
-
- /* Decrement reference count of object header */
- if(chk_proxy->oh && H5O_dec_rc(chk_proxy->oh) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "can't decrement reference count on object header")
-
- /* Release the chunk proxy object */
- chk_proxy = H5FL_FREE(H5O_chunk_proxy_t, chk_proxy);
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5O_chunk_proxy_dest() */
-
+} /* H5O__chunk_serialize() */