summaryrefslogtreecommitdiffstats
path: root/src/H5FScache.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5FScache.c')
-rw-r--r--src/H5FScache.c1397
1 files changed, 834 insertions, 563 deletions
diff --git a/src/H5FScache.c b/src/H5FScache.c
index 461af99..25a9c5e 100644
--- a/src/H5FScache.c
+++ b/src/H5FScache.c
@@ -49,9 +49,6 @@
#define H5FS_HDR_VERSION 0 /* Header */
#define H5FS_SINFO_VERSION 0 /* Serialized sections */
-/* Size of stack buffer for serialized headers */
-#define H5FS_HDR_BUF_SIZE 256
-
/******************/
/* Local Typedefs */
@@ -60,7 +57,7 @@
/* User data for skip list iterator callback for iterating over section size nodes when syncing */
typedef struct {
H5FS_sinfo_t *sinfo; /* Free space section info */
- uint8_t **p; /* Pointer to address of buffer pointer to serialize with */
+ uint8_t **image; /* Pointer to address of buffer pointer to serialize with */
unsigned sect_cnt_size; /* # of bytes to encode section size counts in */
} H5FS_iter_ud_t;
@@ -75,20 +72,35 @@ typedef struct {
/********************/
/* Section info routines */
-static herr_t H5FS_sinfo_serialize_sect_cb(void *_item, void H5_ATTR_UNUSED *key, void *_udata);
-static herr_t H5FS_sinfo_serialize_node_cb(void *_item, void H5_ATTR_UNUSED *key, void *_udata);
+static herr_t H5FS__sinfo_serialize_sect_cb(void *_item, void H5_ATTR_UNUSED *key, void *_udata);
+static herr_t H5FS__sinfo_serialize_node_cb(void *_item, void H5_ATTR_UNUSED *key, void *_udata);
/* Metadata cache callbacks */
-static H5FS_t *H5FS_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5FS_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5FS_t *fspace, unsigned H5_ATTR_UNUSED * flags_ptr);
-static herr_t H5FS_cache_hdr_dest(H5F_t *f, H5FS_t *fspace);
-static herr_t H5FS_cache_hdr_clear(H5F_t *f, H5FS_t *fspace, hbool_t destroy);
-static herr_t H5FS_cache_hdr_size(const H5F_t *f, const H5FS_t *fspace, size_t *size_ptr);
-static H5FS_sinfo_t *H5FS_cache_sinfo_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
-static herr_t H5FS_cache_sinfo_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5FS_sinfo_t *sinfo, unsigned H5_ATTR_UNUSED * flags_ptr);
-static herr_t H5FS_cache_sinfo_dest(H5F_t *f, H5FS_sinfo_t *sinfo);
-static herr_t H5FS_cache_sinfo_clear(H5F_t *f, H5FS_sinfo_t *sinfo, hbool_t destroy);
-static herr_t H5FS_cache_sinfo_size(const H5F_t *f, const H5FS_sinfo_t *sinfo, size_t *size_ptr);
+static herr_t H5FS__cache_hdr_get_load_size(const void *udata, size_t *image_len);
+static void *H5FS__cache_hdr_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5FS__cache_hdr_image_len(const void *thing, size_t *image_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static herr_t H5FS__cache_hdr_pre_serialize(const H5F_t *f, hid_t dxpl_id,
+ void *thing, haddr_t addr, size_t len, size_t compressed_len,
+ haddr_t *new_addr, size_t *new_len, size_t *new_compressed_len,
+ unsigned *flags);
+static herr_t H5FS__cache_hdr_serialize(const H5F_t *f, void *image,
+ size_t len, void *thing);
+static herr_t H5FS__cache_hdr_free_icr(void *thing);
+
+static herr_t H5FS__cache_sinfo_get_load_size(const void *udata, size_t *image_len);
+static void *H5FS__cache_sinfo_deserialize(const void *image, size_t len,
+ void *udata, hbool_t *dirty);
+static herr_t H5FS__cache_sinfo_image_len(const void *thing, size_t *image_len,
+ hbool_t *compressed_ptr, size_t *compressed_image_len_ptr);
+static herr_t H5FS__cache_sinfo_pre_serialize(const H5F_t *f, hid_t dxpl_id,
+ void *thing, haddr_t addr, size_t len, size_t compressed_len,
+ haddr_t *new_addr, size_t *new_len, size_t *new_compressed_len,
+ unsigned *flags);
+static herr_t H5FS__cache_sinfo_serialize(const H5F_t *f, void *image,
+ size_t len, void *thing);
+static herr_t H5FS__cache_sinfo_free_icr(void *thing);
/*********************/
@@ -97,24 +109,36 @@ static herr_t H5FS_cache_sinfo_size(const H5F_t *f, const H5FS_sinfo_t *sinfo, s
/* H5FS header inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_FSPACE_HDR[1] = {{
- H5AC_FSPACE_HDR_ID,
- (H5AC_load_func_t)H5FS_cache_hdr_load,
- (H5AC_flush_func_t)H5FS_cache_hdr_flush,
- (H5AC_dest_func_t)H5FS_cache_hdr_dest,
- (H5AC_clear_func_t)H5FS_cache_hdr_clear,
- (H5AC_notify_func_t)NULL,
- (H5AC_size_func_t)H5FS_cache_hdr_size,
+ H5AC_FSPACE_HDR_ID, /* Metadata client ID */
+ "Free Space Header", /* Metadata client name (for debugging) */
+ H5FD_MEM_FSPACE_HDR, /* File space memory type for client */
+ H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */
+ H5FS__cache_hdr_get_load_size, /* 'get_load_size' callback */
+ H5FS__cache_hdr_deserialize, /* 'deserialize' callback */
+ H5FS__cache_hdr_image_len, /* 'image_len' callback */
+ H5FS__cache_hdr_pre_serialize, /* 'pre_serialize' callback */
+ H5FS__cache_hdr_serialize, /* 'serialize' callback */
+ NULL, /* 'notify' callback */
+ H5FS__cache_hdr_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
-/* H5FS serialized sections inherit cache-like properties from H5AC */
+/* H5FS section info inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_FSPACE_SINFO[1] = {{
- H5AC_FSPACE_SINFO_ID,
- (H5AC_load_func_t)H5FS_cache_sinfo_load,
- (H5AC_flush_func_t)H5FS_cache_sinfo_flush,
- (H5AC_dest_func_t)H5FS_cache_sinfo_dest,
- (H5AC_clear_func_t)H5FS_cache_sinfo_clear,
- (H5AC_notify_func_t)NULL,
- (H5AC_size_func_t)H5FS_cache_sinfo_size,
+ H5AC_FSPACE_SINFO_ID, /* Metadata client ID */
+ "Free Space Section Info", /* Metadata client name (for debugging) */
+ H5FD_MEM_FSPACE_SINFO, /* File space memory type for client */
+ H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */
+ H5FS__cache_sinfo_get_load_size, /* 'get_load_size' callback */
+ H5FS__cache_sinfo_deserialize, /* 'deserialize' callback */
+ H5FS__cache_sinfo_image_len, /* 'image_len' callback */
+ H5FS__cache_sinfo_pre_serialize, /* 'pre_serialize' callback */
+ H5FS__cache_sinfo_serialize, /* 'serialize' callback */
+ NULL, /* 'notify' callback */
+ H5FS__cache_sinfo_free_icr, /* 'free_icr' callback */
+ NULL, /* 'clear' callback */
+ NULL, /* 'fsf_size' callback */
}};
@@ -127,44 +151,73 @@ const H5AC_class_t H5AC_FSPACE_SINFO[1] = {{
/* Local Variables */
/*******************/
-/* Declare a free list to manage free space section data to/from disk */
-H5FL_BLK_DEFINE_STATIC(sect_block);
-
/*-------------------------------------------------------------------------
- * Function: H5FS_cache_hdr_load
+ * Function: H5FS__cache_hdr_get_load_size
*
- * Purpose: Loads a free space manager header from the disk.
+ * Purpose: Compute the size of the data structure on disk.
*
- * Return: Success: Pointer to a new free space header
- * Failure: NULL
+ * Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * May 2 2006
+ * koziol@hdfgroup.org
+ * August 14, 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FS__cache_hdr_get_load_size(const void *_udata, size_t *image_len)
+{
+ const H5FS_hdr_cache_ud_t *udata = (const H5FS_hdr_cache_ud_t *)_udata; /* User-data for metadata cache callback */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments */
+ HDassert(image_len);
+
+ /* Set the image length size */
+ *image_len = (size_t)H5FS_HEADER_SIZE(udata->f);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5FS__cache_hdr_get_load_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS__cache_hdr_deserialize
+ *
+ * Purpose: Given a buffer containing the on disk image of the free space
+ * manager section info, allocate an instance of H5FS_t, load
+ * it with the data contained in the image, and return a pointer
+ * to the new instance.
+ *
+ * Return: Success: Pointer to new object
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * August 18 2013
*
*-------------------------------------------------------------------------
*/
-static H5FS_t *
-H5FS_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
+static void *
+H5FS__cache_hdr_deserialize(const void *_image, size_t len, void *_udata,
+ hbool_t H5_ATTR_UNUSED *dirty)
{
H5FS_t *fspace = NULL; /* Free space header info */
- H5FS_hdr_cache_ud_t *udata = (H5FS_hdr_cache_ud_t *)_udata; /* user data for callback */
- H5WB_t *wb = NULL; /* Wrapped buffer for header data */
- uint8_t hdr_buf[H5FS_HDR_BUF_SIZE]; /* Buffer for header */
- uint8_t *hdr; /* Pointer to header buffer */
- const uint8_t *p; /* Pointer into raw data buffer */
+ H5FS_hdr_cache_ud_t *udata = (H5FS_hdr_cache_ud_t *)_udata; /* User data for callback */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
uint32_t stored_chksum; /* Stored metadata checksum value */
uint32_t computed_chksum; /* Computed metadata checksum value */
unsigned nclasses; /* Number of section classes */
H5FS_t *ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
/* Check arguments */
- HDassert(f);
+ HDassert(image);
HDassert(udata);
+ HDassert(udata->f);
/* Allocate a new free space manager */
if(NULL == (fspace = H5FS__new(udata->f, udata->nclasses, udata->classes, udata->cls_init_udata)))
@@ -173,80 +226,69 @@ H5FS_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
/* Set free space manager's internal information */
fspace->addr = udata->addr;
- /* Wrap the local buffer for serialized header info */
- if(NULL == (wb = H5WB_wrap(hdr_buf, sizeof(hdr_buf))))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, NULL, "can't wrap buffer")
-
- /* Get a pointer to a buffer that's large enough for header */
- if(NULL == (hdr = (uint8_t *)H5WB_actual(wb, fspace->hdr_size)))
- HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, NULL, "can't get actual buffer")
-
- /* Read header from disk */
- if(H5F_block_read(f, H5FD_MEM_FSPACE_HDR, addr, fspace->hdr_size, dxpl_id, hdr) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_READERROR, NULL, "can't read free space header")
-
- p = hdr;
-
/* Magic number */
- if(HDmemcmp(p, H5FS_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ if(HDmemcmp(image, H5FS_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "wrong free space header signature")
- p += H5_SIZEOF_MAGIC;
+ image += H5_SIZEOF_MAGIC;
/* Version */
- if(*p++ != H5FS_HDR_VERSION)
+ if(*image++ != H5FS_HDR_VERSION)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "wrong free space header version")
/* Client ID */
- fspace->client = (H5FS_client_t)*p++;
+ fspace->client = (H5FS_client_t)*image++;
if(fspace->client >= H5FS_NUM_CLIENT_ID)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "unknown client ID in free space header")
/* Total space tracked */
- H5F_DECODE_LENGTH(udata->f, p, fspace->tot_space);
+ H5F_DECODE_LENGTH(udata->f, image, fspace->tot_space);
/* Total # of free space sections tracked */
- H5F_DECODE_LENGTH(udata->f, p, fspace->tot_sect_count);
+ H5F_DECODE_LENGTH(udata->f, image, fspace->tot_sect_count);
/* # of serializable free space sections tracked */
- H5F_DECODE_LENGTH(udata->f, p, fspace->serial_sect_count);
+ H5F_DECODE_LENGTH(udata->f, image, fspace->serial_sect_count);
/* # of ghost free space sections tracked */
- H5F_DECODE_LENGTH(udata->f, p, fspace->ghost_sect_count);
+ H5F_DECODE_LENGTH(udata->f, image, fspace->ghost_sect_count);
/* # of section classes */
/* (only check if we actually have some classes) */
- UINT16DECODE(p, nclasses);
+ UINT16DECODE(image, nclasses);
if(fspace->nclasses > 0 && fspace->nclasses != nclasses)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "section class count mismatch")
/* Shrink percent */
- UINT16DECODE(p, fspace->shrink_percent);
+ UINT16DECODE(image, fspace->shrink_percent);
/* Expand percent */
- UINT16DECODE(p, fspace->expand_percent);
+ UINT16DECODE(image, fspace->expand_percent);
- /* Size of address space free space sections are within (log2 of actual value) */
- UINT16DECODE(p, fspace->max_sect_addr);
+ /* Size of address space free space sections are within
+ * (log2 of actual value)
+ */
+ UINT16DECODE(image, fspace->max_sect_addr);
/* Max. size of section to track */
- H5F_DECODE_LENGTH(udata->f, p, fspace->max_sect_size);
+ H5F_DECODE_LENGTH(udata->f, image, fspace->max_sect_size);
/* Address of serialized free space sections */
- H5F_addr_decode(udata->f, &p, &fspace->sect_addr);
+ H5F_addr_decode(udata->f, &image, &fspace->sect_addr);
/* Size of serialized free space sections */
- H5F_DECODE_LENGTH(udata->f, p, fspace->sect_size);
+ H5F_DECODE_LENGTH(udata->f, image, fspace->sect_size);
/* Allocated size of serialized free space sections */
- H5F_DECODE_LENGTH(udata->f, p, fspace->alloc_sect_size);
+ H5F_DECODE_LENGTH(udata->f, image, fspace->alloc_sect_size);
/* Compute checksum on indirect block */
- computed_chksum = H5_checksum_metadata(hdr, (size_t)(p - (const uint8_t *)hdr), 0);
+ computed_chksum = H5_checksum_metadata(_image, (size_t)(image - (const uint8_t *)_image), 0);
/* Metadata checksum */
- UINT32DECODE(p, stored_chksum);
+ UINT32DECODE(image, stored_chksum);
- HDassert((size_t)(p - (const uint8_t *)hdr) == fspace->hdr_size);
+ /* Sanity check */
+ HDassert((size_t)(image - (const uint8_t *)_image) <= len);
/* Verify checksum */
if(stored_chksum != computed_chksum)
@@ -257,177 +299,432 @@ H5FS_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
done:
/* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_FSPACE, H5E_CLOSEERROR, NULL, "can't close wrapped buffer")
if(!ret_value && fspace)
if(H5FS__hdr_dest(fspace) < 0)
HDONE_ERROR(H5E_FSPACE, H5E_CANTFREE, NULL, "unable to destroy free space header")
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FS_cache_hdr_load() */ /*lint !e818 Can't make udata a pointer to const */
+} /* end H5FS__cache_hdr_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5FS_cache_hdr_flush
+ * Function: H5FS__cache_hdr_image_len
*
- * Purpose: Flushes a dirty free space header to disk.
+ * Purpose: Compute the size of the data structure on disk and return
+ * it in *image_len.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * May 2 2006
+ * koziol@hdfgroup.org
+ * August 14, 2013
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5FS_t *fspace, unsigned H5_ATTR_UNUSED * flags_ptr)
+H5FS__cache_hdr_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
- H5WB_t *wb = NULL; /* Wrapped buffer for header data */
- uint8_t hdr_buf[H5FS_HDR_BUF_SIZE]; /* Buffer for header */
- herr_t ret_value = SUCCEED; /* Return value */
+ const H5FS_t *fspace = (const H5FS_t *)_thing; /* Pointer to the object */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments */
+ HDassert(fspace);
+ HDassert(fspace->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(fspace->cache_info.type == H5AC_FSPACE_HDR);
+ HDassert(image_len);
+
+ /* Set the image length size */
+ *image_len = fspace->hdr_size;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5FS__cache_hdr_image_len() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS__cache_hdf_pre_serialize
+ *
+ * Purpose: The free space manager header contains the address, size, and
+ * allocation size of the free space manager section info. However,
+ * since it is possible for the section info to either not be allocated
+ * at all, or be allocated in temporary (AKA imaginary) files space,
+ * it is possible for the above mentioned fields to contain giberish
+ * when the free space manager header is serialized.
+ *
+ * This function exists to prevent this problem. It does so by
+ * forcing allocation of real file space for the section information.
+ *
+ * Note that in the Version 2 cache, this problem was dealt with by
+ * simply flushing the section info before flushing the header. This
+ * was possible, since the clients handled file I/O directly. As
+ * this responsibility has moved to the cache in Version 3, this
+ * solution is no longer directly applicable.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FS__cache_hdr_pre_serialize(const H5F_t *f, hid_t dxpl_id, void *_thing,
+ haddr_t addr, size_t H5_ATTR_UNUSED len, size_t H5_ATTR_UNUSED compressed_len,
+ haddr_t *new_addr, size_t *new_len, size_t H5_ATTR_UNUSED *new_compressed_len,
+ unsigned *flags)
+{
+ H5FS_t *fspace = (H5FS_t *)_thing; /* Pointer to the object */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC_TAG(dxpl_id, H5AC__FREESPACE_TAG, FAIL)
- /* check arguments */
+ /* Sanity check */
HDassert(f);
- HDassert(H5F_addr_defined(addr));
HDassert(fspace);
- HDassert(H5F_addr_defined(fspace->addr));
+ HDassert(fspace->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(fspace->cache_info.type == H5AC_FSPACE_HDR);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(new_addr);
+ HDassert(new_len);
+ HDassert(flags);
- /* Check if the header "owns" the section info */
if(fspace->sinfo) {
- /* Sanity check - should not be trying to destroy header if it still
- * "owns" section info
+ /* This implies that the header "owns" the section info.
+ *
+ * Unfortunately, the comments in the code are not clear as to
+ * what this means, but from reviewing the code (most particularly
+ * H5FS_close(), H5FS_sinfo_lock, and H5FS_sinfo_unlock()), I
+ * gather that it means that the header is maintaining a pointer to
+ * an instance of H5FS_sinfo_t in which free space data is
+ * maintained, and either:
+ *
+ * 1) The instance of H5FS_sinfo_t is not in the metadata cache.
+ *
+ * This will be TRUE iff H5F_addr_defined(fspace->sect_addr)
+ * is FALSE, and fspace->sinfo is not NULL. This is sometimes
+ * referred to as "floating" section info in the comments.
+ *
+ * If the section info structure contains free space data
+ * that must be placed on disk eventually, then
+ *
+ * fspace->serial_sect_count > 0
+ *
+ * and
+ *
+ * H5F_addr_defined(fspace->addr)
+ *
+ * will both be TRUE. If this contition does not hold, then
+ * either the free space info is not persistant
+ * (!H5F_addr_defined(fspace->addr)???) or the section info
+ * contains no free space data that must be written to file
+ * ( fspace->serial_sect_count == 0 ).
+ *
+ * 2) The instance of H5FS_sinfo_t is in the metadata cache with
+ * address in temporary file space (AKA imaginary file space).
+ * The entry may or may not be protected, and if protected, it
+ * may be protected either RW or RO (as indicated by
+ * fspace->sinfo_protected and fspace->sinfo_accmod).
+ *
+ * 3) The instance of H5FS_sinfo_t is in the metadata cache with
+ * address in real file space. As in case 2) above, the entry
+ * may or may not be protected, and if protected, it
+ * may be protected either RW or RO (as indicated by
+ * fspace->sinfo_protected and fspace->sinfo_accmod).
+ *
+ * Observe that fspace->serial_sect_count > 0 must be TRUE in
+ * cases 2) and 3), as the section info should not be stored on
+ * disk if it doesn't exist. Similarly, since the section info
+ * will not be stored to disk unless the header is,
+ * H5F_addr_defined(fspace->addr) must hold as well.
+ *
+ * As the objective is to touch up the free space manager header
+ * so that it contains sensical data on the size and location of
+ * the section information, we have to handle each of the above
+ * cases differently.
+ *
+ * Case 1) If either fspace->serial_sect_count == 0 or
+ * ! H5F_addr_defined(fspace->addr) do nothing as either
+ * the free space manager data is not persistant, or the
+ * section info is empty.
+ *
+ * Otherwise, allocate space for the section info in real
+ * file space, insert the section info at this location, and
+ * set fspace->sect_addr, fspace->sect_size, and
+ * fspace->alloc_sect_size to reflect the new location
+ * of the section info. Note that it is not necessary to
+ * force a write of the section info.
+ *
+ * Case 2) Allocate space for the section info in real file space,
+ * and tell the metadata cache to relocate the entry.
+ * Update fspace->sect_addr, fspace->sect_size, and
+ * fspace->alloc_sect_size to reflect the new location.
+ *
+ * Case 3) Nothing to be done in this case, although it is useful
+ * to perform sanity checks.
+ *
+ * Note that while we may alter the contents of the free space
+ * header in cases 1) and 2), there is no need to mark the header
+ * as dirty, as the metadata cache would not be attempting to
+ * serialize the header if it though it was clean.
*/
- HDassert(!destroy);
-
- /* Check if the section info is dirty */
- if(fspace->sinfo->dirty) {
- if(fspace->serial_sect_count > 0) {
- /* Check if we need to allocate space for section info */
- if(H5F_IS_TMP_ADDR(f, fspace->sect_addr) || !H5F_addr_defined(fspace->sect_addr)) {
- /* Sanity check */
- HDassert(fspace->sect_size > 0);
-
- /* Allocate space for the section info in file */
- if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_size)))
- HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
- fspace->alloc_sect_size = (size_t)fspace->sect_size;
-
- /* Mark header dirty */
- /* (don't use cache API, since we're in a callback) */
- fspace->cache_info.is_dirty = TRUE;
- } /* end if */
-
- /* Write section info to file */
- if(H5FS_cache_sinfo_flush(f, dxpl_id, FALSE, fspace->sect_addr, fspace->sinfo, NULL) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFLUSH, FAIL, "unable to save free space section info to disk")
+ if(fspace->serial_sect_count > 0 && H5F_addr_defined(fspace->addr)) {
+ /* Sanity check */
+ HDassert(fspace->sect_size > 0);
+
+ if(!H5F_addr_defined(fspace->sect_addr)) { /* case 1 */
+ /* allocate file space for the section info, and insert it
+ * into the metadata cache.
+ */
+ if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_size)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
+
+ fspace->alloc_sect_size = (size_t)fspace->sect_size;
+ if(H5AC_insert_entry((H5F_t *)f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, fspace->sinfo, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, FAIL, "can't add free space sections to cache")
+
+ HDassert(fspace->sinfo->cache_info.size == fspace->alloc_sect_size);
+
+ /* the metadata cache is now managing the section info,
+ * so set fspace->sinfo to NULL.
+ */
+ fspace->sinfo = NULL;
} /* end if */
-
- /* Mark section info clean */
- fspace->sinfo->dirty = FALSE;
- } /* end if */
+ else if(H5F_IS_TMP_ADDR(f, fspace->sect_addr)) { /* case 2 */
+ haddr_t new_sect_addr;
+
+ /* move the section info from temporary (AKA imaginary) file
+ * space to real file space.
+ */
+
+ /* if my reading of the code is correct, this should always
+ * be the case. If not, we will have to add code to resize
+ * file space allocation for section info as well as moving it.
+ */
+ HDassert(fspace->sect_size > 0);
+ HDassert(fspace->alloc_sect_size == (size_t)fspace->sect_size);
+
+ /* Allocate space for the section info in file */
+ if(HADDR_UNDEF == (new_sect_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_size)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
+
+ fspace->alloc_sect_size = (size_t)fspace->sect_size;
+ HDassert(fspace->sinfo->cache_info.size == fspace->alloc_sect_size);
+
+ /* Let the metadata cache know the section info moved */
+ if(H5AC_move_entry((H5F_t *)f, H5AC_FSPACE_SINFO, fspace->sect_addr, new_sect_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTMOVE, FAIL, "unable to move section info")
+
+ fspace->sect_addr = new_sect_addr;
+ } /* end else-if */
+ else { /* case 3 -- nothing to do but sanity checking */
+ /* if my reading of the code is correct, this should always
+ * be the case. If not, we will have to add code to resize
+ * file space allocation for section info.
+ */
+ HDassert(fspace->sect_size > 0);
+ HDassert(fspace->alloc_sect_size == (size_t)fspace->sect_size);
+ } /* end else */
+ } /* end else */
+ else {
+ /* for one reason or another (see comment above) there should
+ * not be any file space allocated for the section info.
+ */
+ HDassert(!H5F_addr_defined(fspace->sect_addr));
+ } /* end else */
} /* end if */
- else if(fspace->serial_sect_count > 0)
- /* Sanity check that section info has address */
- HDassert(H5F_addr_defined(fspace->sect_addr));
+ else if(H5F_addr_defined(fspace->sect_addr)) {
+ /* Here the metadata cache is managing the section info.
+ *
+ * Do some sanity checks, and then test to see if the section
+ * info is in real file space. If it isn't relocate it into
+ * real file space lest the header be written to file with
+ * a nonsense section info address.
+ */
+ HDassert(fspace->serial_sect_count > 0);
+ HDassert(fspace->sect_size > 0);
+ HDassert(fspace->alloc_sect_size == (size_t)fspace->sect_size);
+
+ if(H5F_IS_TMP_ADDR(f, fspace->sect_addr)) {
+ unsigned sect_status = 0;
+ haddr_t new_sect_addr;
+
+ /* we have work to do -- must relocate section info into
+ * real file space.
+ *
+ * Since the section info address is in temporary space (AKA
+ * imaginary space), it follows that the entry must be in
+ * cache. Further, since fspace->sinfo is NULL, it must be
+ * unprotected and un-pinned. Start by verifying this.
+ */
+ if(H5AC_get_entry_status(f, fspace->sect_addr, &sect_status) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't get section info status")
+
+ HDassert(sect_status & H5AC_ES__IN_CACHE);
+ HDassert((sect_status & H5AC_ES__IS_PROTECTED) == 0);
+ HDassert((sect_status & H5AC_ES__IS_PINNED) == 0);
- if(fspace->cache_info.is_dirty) {
- uint8_t *hdr; /* Pointer to header buffer */
- uint8_t *p; /* Pointer into raw data buffer */
- uint32_t metadata_chksum; /* Computed metadata checksum value */
+ /* Allocate space for the section info in file */
+ if(HADDR_UNDEF == (new_sect_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_size)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
- /* Wrap the local buffer for serialized header info */
- if(NULL == (wb = H5WB_wrap(hdr_buf, sizeof(hdr_buf))))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, FAIL, "can't wrap buffer")
+ fspace->alloc_sect_size = (size_t)fspace->sect_size;
- /* Get a pointer to a buffer that's large enough for header */
- if(NULL == (hdr = (uint8_t *)H5WB_actual(wb, fspace->hdr_size)))
- HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "can't get actual buffer")
+ /* Sanity check */
+ HDassert(!H5F_addr_eq(fspace->sect_addr, new_sect_addr));
- /* Get temporary pointer to header */
- p = hdr;
+ /* Let the metadata cache know the section info moved */
+ if(H5AC_move_entry((H5F_t *)f, H5AC_FSPACE_SINFO, fspace->sect_addr, new_sect_addr) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTMOVE, FAIL, "unable to move section info")
- /* Magic number */
- HDmemcpy(p, H5FS_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += H5_SIZEOF_MAGIC;
+ /* Update the internal address for the section info */
+ fspace->sect_addr = new_sect_addr;
- /* Version # */
- *p++ = H5FS_HDR_VERSION;
+ /* No need to mark the header dirty, as we are about to
+ * serialize it.
+ */
+ } /* end if */
+ } /* end else-if */
+ else { /* there is no section info at present */
+ /* do some sanity checks */
+ HDassert(fspace->serial_sect_count == 0);
+ HDassert(fspace->tot_sect_count == fspace->ghost_sect_count);
+ } /* end else */
- /* Client ID */
- *p++ = fspace->client;
+ /* what ever happened above, set *flags to 0 */
+ *flags = 0;
- /* Total space tracked */
- H5F_ENCODE_LENGTH(f, p, fspace->tot_space);
+done:
+ FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
+} /* end H5FS__cache_hdr_pre_serialize() */
- /* Total # of free space sections tracked */
- H5F_ENCODE_LENGTH(f, p, fspace->tot_sect_count);
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS__cache_hdr_serialize
+ *
+ * Purpose: Given an instance of H5FS_t and a suitably sized buffer,
+ * serialize the contents of the instance of H5FS_t and write
+ * its contents to the buffer. This buffer will be used to
+ * write the image of the instance to file.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FS__cache_hdr_serialize(const H5F_t *f, void *_image, size_t len,
+ void *_thing)
+{
+ H5FS_t *fspace = (H5FS_t *)_thing; /* Pointer to the object */
+ uint8_t *image = (uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* # of serializable free space sections tracked */
- H5F_ENCODE_LENGTH(f, p, fspace->serial_sect_count);
+ FUNC_ENTER_STATIC_NOERR
- /* # of ghost free space sections tracked */
- H5F_ENCODE_LENGTH(f, p, fspace->ghost_sect_count);
+ /* Check arguments */
+ HDassert(f);
+ HDassert(image);
+ HDassert(fspace);
+ HDassert(fspace->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(fspace->cache_info.type == H5AC_FSPACE_HDR);
+ HDassert(fspace->hdr_size == len);
+
+ /* The section information does not always exits, and if it does,
+ * it is not always in the cache. To make matters more interesting,
+ * even if it is in the cache, it may not be in real file space.
+ *
+ * The pre-serialize function should have moved the section info
+ * into real file space if necessary before this function was called.
+ * The following asserts are a cursory check on this.
+ */
+ HDassert((! H5F_addr_defined(fspace->sect_addr)) || (! H5F_IS_TMP_ADDR(f, fspace->sect_addr)));
+ HDassert((! H5F_addr_defined(fspace->sect_addr)) ||
+ ((fspace->serial_sect_count > 0) &&
+ (fspace->sect_size > 0) &&
+ (fspace->alloc_sect_size == (size_t)fspace->sect_size)));
- /* # of section classes */
- UINT16ENCODE(p, fspace->nclasses);
+ /* Magic number */
+ HDmemcpy(image, H5FS_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ image += H5_SIZEOF_MAGIC;
- /* Shrink percent */
- UINT16ENCODE(p, fspace->shrink_percent);
+ /* Version # */
+ *image++ = H5FS_HDR_VERSION;
- /* Expand percent */
- UINT16ENCODE(p, fspace->expand_percent);
+ /* Client ID */
+ *image++ = fspace->client;
- /* Size of address space free space sections are within (log2 of actual value) */
- UINT16ENCODE(p, fspace->max_sect_addr);
+ /* Total space tracked */
+ H5F_ENCODE_LENGTH(f, image, fspace->tot_space);
- /* Max. size of section to track */
- H5F_ENCODE_LENGTH(f, p, fspace->max_sect_size);
+ /* Total # of free space sections tracked */
+ H5F_ENCODE_LENGTH(f, image, fspace->tot_sect_count);
- /* Address of serialized free space sections */
- H5F_addr_encode(f, &p, fspace->sect_addr);
+ /* # of serializable free space sections tracked */
+ H5F_ENCODE_LENGTH(f, image, fspace->serial_sect_count);
- /* Size of serialized free space sections */
- H5F_ENCODE_LENGTH(f, p, fspace->sect_size);
+ /* # of ghost free space sections tracked */
+ H5F_ENCODE_LENGTH(f, image, fspace->ghost_sect_count);
- /* Allocated size of serialized free space sections */
- H5F_ENCODE_LENGTH(f, p, fspace->alloc_sect_size);
+ /* # of section classes */
+ UINT16ENCODE(image, fspace->nclasses);
- /* Compute checksum */
- metadata_chksum = H5_checksum_metadata(hdr, (size_t)(p - (uint8_t *)hdr), 0);
+ /* Shrink percent */
+ UINT16ENCODE(image, fspace->shrink_percent);
- /* Metadata checksum */
- UINT32ENCODE(p, metadata_chksum);
+ /* Expand percent */
+ UINT16ENCODE(image, fspace->expand_percent);
- /* Write the free space header. */
- HDassert((size_t)(p - hdr) == fspace->hdr_size);
- if(H5F_block_write(f, H5FD_MEM_FSPACE_HDR, addr, fspace->hdr_size, dxpl_id, hdr) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFLUSH, FAIL, "unable to save free space header to disk")
+ /* Size of address space free space sections are within (log2 of
+ * actual value)
+ */
+ UINT16ENCODE(image, fspace->max_sect_addr);
- fspace->cache_info.is_dirty = FALSE;
- } /* end if */
+ /* Max. size of section to track */
+ H5F_ENCODE_LENGTH(f, image, fspace->max_sect_size);
- if(destroy)
- if(H5FS_cache_hdr_dest(f, fspace) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to destroy free space header")
+ /* Address of serialized free space sections */
+ H5F_addr_encode(f, &image, fspace->sect_addr);
-done:
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_FSPACE, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer")
+ /* Size of serialized free space sections */
+ H5F_ENCODE_LENGTH(f, image, fspace->sect_size);
+
+ /* Allocated size of serialized free space sections */
+ H5F_ENCODE_LENGTH(f, image, fspace->alloc_sect_size);
+
+ /* Compute checksum */
+ metadata_chksum = H5_checksum_metadata((uint8_t *)_image, (size_t)(image - (uint8_t *)_image), 0);
+
+ /* Metadata checksum */
+ UINT32ENCODE(image, metadata_chksum);
+
+ /* sanity checks */
+ HDassert((size_t)(image - (uint8_t *)_image) == fspace->hdr_size);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5FS_cache_hdr_flush() */
+} /* H5FS__cache_hdr_serialize() */
+
+/***************************************/
+/* no H5FS__cache_hdr_notify() function */
+/***************************************/
/*-------------------------------------------------------------------------
- * Function: H5FS_cache_hdr_dest
+ * Function: H5FS__cache_hdr_free_icr
*
* Purpose: Destroys a free space header in memory.
*
- * 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).
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
@@ -436,175 +733,133 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_cache_hdr_dest(H5F_t *f, H5FS_t *fspace)
+H5FS__cache_hdr_free_icr(void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5FS_t *fspace = (H5FS_t *)_thing; /* Pointer to the object */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /* Check arguments */
+ /* Sanity checks */
HDassert(fspace);
+ HDassert(fspace->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
+ HDassert(fspace->cache_info.type == H5AC_FSPACE_HDR);
/* We should not still be holding on to the free space section info */
HDassert(!fspace->sinfo);
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!fspace->cache_info.free_file_space_on_destroy || H5F_addr_defined(fspace->cache_info.addr));
-
- /* Check for freeing file space for free space header */
- if(fspace->cache_info.free_file_space_on_destroy) {
- /* Sanity check */
- HDassert(H5F_addr_defined(fspace->addr));
-
- /* Release the space on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(H5MF_xfree(f, H5FD_MEM_FSPACE_HDR, H5AC_dxpl_id, fspace->cache_info.addr, (hsize_t)fspace->hdr_size) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space header")
- } /* end if */
-
/* Destroy free space header */
if(H5FS__hdr_dest(fspace) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to destroy free space header")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FS_cache_hdr_dest() */
+} /* end H5FS__cache_hdr_free_icr() */
-
-/*-------------------------------------------------------------------------
- * Function: H5FS_cache_hdr_clear
- *
- * Purpose: Mark a free space header in memory as non-dirty.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * May 2 2006
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5FS_cache_hdr_clear(H5F_t *f, H5FS_t *fspace, hbool_t destroy)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- /*
- * Check arguments.
- */
- HDassert(fspace);
-
- /* Reset the dirty flag. */
- fspace->cache_info.is_dirty = FALSE;
-
- if(destroy)
- if(H5FS_cache_hdr_dest(f, fspace) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to destroy free space header")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FS_cache_hdr_clear() */
+/********************************************************/
+/* metadata cache callback definitions for section info */
+/********************************************************/
/*-------------------------------------------------------------------------
- * Function: H5FS_cache_hdr_size
+ * Function: H5FS__cache_sinfo_get_load_size()
*
- * Purpose: Compute the size in bytes of a free space header
- * on disk, and return it in *size_ptr. On failure,
- * the value of *size_ptr is undefined.
+ * Purpose: Compute the size of the on disk image of the free space
+ * manager section info, and place this value in *image_len.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * May 2 2006
+ * Programmer: John Mainzer
+ * 7/7/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5FS_cache_hdr_size(const H5F_t H5_ATTR_UNUSED *f, const H5FS_t *fspace, size_t *size_ptr)
+static herr_t
+H5FS__cache_sinfo_get_load_size(const void *_udata, size_t *image_len)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ const H5FS_t *fspace; /* free space manager */
+ const H5FS_sinfo_cache_ud_t *udata = (const H5FS_sinfo_cache_ud_t *)_udata; /* User data for callback */
- /* check arguments */
- HDassert(f);
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Sanity checks */
+ HDassert(udata);
+ fspace = udata->fspace;
HDassert(fspace);
- HDassert(size_ptr);
+ HDassert(fspace->sect_size > 0);
+ HDassert(image_len);
- /* Set size value */
- *size_ptr = fspace->hdr_size;
+ *image_len = (size_t)(fspace->sect_size);
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5FS_cache_hdr_size() */
+} /* end H5FS__cache_sinfo_get_load_size() */
/*-------------------------------------------------------------------------
- * Function: H5FS_cache_sinfo_load
+ * Function: H5FS__cache_sinfo_deserialize
*
- * Purpose: Loads free space sections from the disk.
+ * Purpose: Given a buffer containing the on disk image of the free space
+ * manager section info, allocate an instance of H5FS_sinfo_t, load
+ * it with the data contained in the image, and return a pointer to
+ * the new instance.
*
- * Return: Success: Pointer to a new free space section info
- * Failure: NULL
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * July 31 2006
+ * Return: Success: Pointer to in core representation
+ * Failure: NULL
+ *
+ * Programmer: John Mainzer
+ * 7/7/14
*
*-------------------------------------------------------------------------
*/
-static H5FS_sinfo_t *
-H5FS_cache_sinfo_load(H5F_t *f, hid_t dxpl_id, haddr_t H5_ATTR_UNUSED addr, void *_udata)
+static void *
+H5FS__cache_sinfo_deserialize(const void *_image, size_t len, void *_udata,
+ hbool_t *dirty)
{
- H5FS_sinfo_t *sinfo = NULL; /* Free space section info */
- H5FS_sinfo_cache_ud_t *udata = (H5FS_sinfo_cache_ud_t *)_udata; /* user data for callback */
- haddr_t fs_addr; /* Free space header address */
- size_t old_sect_size; /* Old section size */
- uint8_t *buf = NULL; /* Temporary buffer */
- const uint8_t *p; /* Pointer into raw data buffer */
- uint32_t stored_chksum; /* Stored metadata checksum value */
- uint32_t computed_chksum; /* Computed metadata checksum value */
- H5FS_sinfo_t *ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- /* Check arguments */
- HDassert(f);
+ H5FS_sinfo_cache_ud_t *udata = (H5FS_sinfo_cache_ud_t *)_udata; /* User data for callback */
+ H5FS_t *fspace; /* free space manager */
+ H5FS_sinfo_t *sinfo = NULL; /* Free space section info */
+ haddr_t fs_addr; /* Free space header address */
+ size_t old_sect_size; /* Old section size */
+ const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum */
+ uint32_t computed_chksum; /* Computed metadata checksum */
+ void * ret_value; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity checks */
+ HDassert(image);
HDassert(udata);
+ fspace = udata->fspace;
+ HDassert(fspace);
+ HDassert(fspace->sect_size == len);
+ HDassert(dirty);
/* Allocate a new free space section info */
- if(NULL == (sinfo = H5FS_sinfo_new(udata->f, udata->fspace)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
-
- /* Allocate space for the buffer to serialize the sections into */
- H5_CHECKED_ASSIGN(old_sect_size, size_t, udata->fspace->sect_size, hsize_t);
- if(NULL == (buf = H5FL_BLK_MALLOC(sect_block, (size_t)udata->fspace->sect_size)))
+ if(NULL == (sinfo = H5FS_sinfo_new(udata->f, fspace)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- /* Read buffer from disk */
- if(H5F_block_read(f, H5FD_MEM_FSPACE_SINFO, udata->fspace->sect_addr, (size_t)udata->fspace->sect_size, dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_READERROR, NULL, "can't read free space sections")
-
- /* Deserialize free sections from buffer available */
- p = buf;
+ /* initialize old_sect_size */
+ H5_CHECKED_ASSIGN(old_sect_size, size_t, udata->fspace->sect_size, hsize_t);
/* Magic number */
- if(HDmemcmp(p, H5FS_SINFO_MAGIC, (size_t)H5_SIZEOF_MAGIC))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "wrong free space sections signature")
- p += H5_SIZEOF_MAGIC;
+ if(HDmemcmp(image, H5FS_SINFO_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "wrong free space sections signature")
+ image += H5_SIZEOF_MAGIC;
/* Version */
- if(*p++ != H5FS_SINFO_VERSION)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "wrong free space sections version")
+ if(*image++ != H5FS_SINFO_VERSION)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "wrong free space sections version")
/* Address of free space header for these sections */
- H5F_addr_decode(udata->f, &p, &fs_addr);
+ H5F_addr_decode(udata->f, &image, &fs_addr);
if(H5F_addr_ne(fs_addr, udata->fspace->addr))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "incorrect header address for free space sections")
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "incorrect header address for free space sections")
/* Check for any serialized sections */
- if(udata->fspace->serial_sect_count > 0) {
+ if(fspace->serial_sect_count > 0) {
hsize_t old_tot_sect_count; /* Total section count from header */
hsize_t old_serial_sect_count; /* Total serializable section count from header */
hsize_t old_ghost_sect_count; /* Total ghost section count from header */
@@ -615,27 +870,27 @@ H5FS_cache_sinfo_load(H5F_t *f, hid_t dxpl_id, haddr_t H5_ATTR_UNUSED addr, void
sect_cnt_size = H5VM_limit_enc_size((uint64_t)udata->fspace->serial_sect_count);
/* Reset the section count, the "add" routine will update it */
- old_tot_sect_count = udata->fspace->tot_sect_count;
- old_serial_sect_count = udata->fspace->serial_sect_count;
- old_ghost_sect_count = udata->fspace->ghost_sect_count;
- old_tot_space = udata->fspace->tot_space;
- udata->fspace->tot_sect_count = 0;
- udata->fspace->serial_sect_count = 0;
- udata->fspace->ghost_sect_count = 0;
- udata->fspace->tot_space = 0;
-
- /* Walk through the buffer, deserializing sections */
+ old_tot_sect_count = fspace->tot_sect_count;
+ old_serial_sect_count = fspace->serial_sect_count;
+ old_ghost_sect_count = fspace->ghost_sect_count;
+ old_tot_space = fspace->tot_space;
+ fspace->tot_sect_count = 0;
+ fspace->serial_sect_count = 0;
+ fspace->ghost_sect_count = 0;
+ fspace->tot_space = 0;
+
+ /* Walk through the image, deserializing sections */
do {
hsize_t sect_size; /* Current section size */
size_t node_count; /* # of sections of this size */
size_t u; /* Local index variable */
/* The number of sections of this node's size */
- UINT64DECODE_VAR(p, node_count, sect_cnt_size);
+ UINT64DECODE_VAR(image, node_count, sect_cnt_size);
HDassert(node_count);
/* The size of the sections for this node */
- UINT64DECODE_VAR(p, sect_size, sinfo->sect_len_size);
+ UINT64DECODE_VAR(image, sect_size, sinfo->sect_len_size);
HDassert(sect_size);
/* Loop over nodes of this size */
@@ -646,324 +901,306 @@ H5FS_cache_sinfo_load(H5F_t *f, hid_t dxpl_id, haddr_t H5_ATTR_UNUSED addr, void
unsigned des_flags; /* Flags from deserialize callback */
/* The address of the section */
- UINT64DECODE_VAR(p, sect_addr, sinfo->sect_off_size);
+ UINT64DECODE_VAR(image, sect_addr, sinfo->sect_off_size);
/* The type of this section */
- sect_type = *p++;
+ sect_type = *image++;
/* Call 'deserialize' callback for this section */
des_flags = 0;
HDassert(udata->fspace->sect_cls[sect_type].deserialize);
- if(NULL == (new_sect = (*udata->fspace->sect_cls[sect_type].deserialize)(&udata->fspace->sect_cls[sect_type], udata->dxpl_id, p, sect_addr, sect_size, &des_flags)))
+ if(NULL == (new_sect = (*fspace->sect_cls[sect_type].deserialize) (&fspace->sect_cls[sect_type], udata->dxpl_id, image, sect_addr, sect_size, &des_flags)))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTDECODE, NULL, "can't deserialize section")
- /* Update offset in serialization buffer */
- p += udata->fspace->sect_cls[sect_type].serial_size;
+ /* Update offset in serialization image */
+ image += udata->fspace->sect_cls[sect_type].serial_size;
/* Insert section in free space manager, unless requested not to */
if(!(des_flags & H5FS_DESERIALIZE_NO_ADD))
if(H5FS_sect_add(udata->f, udata->dxpl_id, udata->fspace, new_sect, H5FS_ADD_DESERIALIZING, NULL) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, NULL, "can't add section to free space manager")
} /* end for */
- } while(p < ((buf + old_sect_size) - H5FS_SIZEOF_CHKSUM));
+ } while(image < (((const uint8_t *)_image + old_sect_size) - H5FS_SIZEOF_CHKSUM));
/* Sanity check */
- HDassert((size_t)(p - buf) == (old_sect_size - H5FS_SIZEOF_CHKSUM));
- HDassert(old_sect_size == udata->fspace->sect_size);
- HDassert(old_tot_sect_count == udata->fspace->tot_sect_count);
- HDassert(old_serial_sect_count == udata->fspace->serial_sect_count);
- HDassert(old_ghost_sect_count == udata->fspace->ghost_sect_count);
- HDassert(old_tot_space == udata->fspace->tot_space);
+ HDassert((size_t)(image - (const uint8_t *)_image) == (old_sect_size - H5FS_SIZEOF_CHKSUM));
+ HDassert(old_sect_size == fspace->sect_size);
+ HDassert(old_tot_sect_count == fspace->tot_sect_count);
+ HDassert(old_serial_sect_count == fspace->serial_sect_count);
+ HDassert(old_ghost_sect_count == fspace->ghost_sect_count);
+ HDassert(old_tot_space == fspace->tot_space);
} /* end if */
/* Compute checksum on indirect block */
- computed_chksum = H5_checksum_metadata(buf, (size_t)(p - (const uint8_t *)buf), 0);
+ computed_chksum = H5_checksum_metadata((const uint8_t *)_image, (size_t)(image - (const uint8_t *)_image), 0);
/* Metadata checksum */
- UINT32DECODE(p, stored_chksum);
+ UINT32DECODE(image, stored_chksum);
/* Verify checksum */
if(stored_chksum != computed_chksum)
- HGOTO_ERROR(H5E_FSPACE, H5E_BADVALUE, NULL, "incorrect metadata checksum for fractal heap indirect block")
+ HGOTO_ERROR(H5E_FSPACE, H5E_BADVALUE, NULL, "incorrect metadata checksum for fractal heap indirect block")
/* Sanity check */
- HDassert((size_t)(p - (const uint8_t *)buf) == old_sect_size);
+ HDassert((size_t)(image - (const uint8_t *)_image) == old_sect_size);
/* Set return value */
ret_value = sinfo;
done:
- if(buf)
- buf = H5FL_BLK_FREE(sect_block, buf);
if(!ret_value && sinfo)
if(H5FS_sinfo_dest(sinfo) < 0)
HDONE_ERROR(H5E_FSPACE, H5E_CANTFREE, NULL, "unable to destroy free space info")
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FS_cache_sinfo_load() */ /*lint !e818 Can't make udata a pointer to const */
+} /* end H5FS__cache_sinfo_deserialize() */
/*-------------------------------------------------------------------------
- * Function: H5FS_sinfo_serialize_sect_cb
+ * Function: H5FS__cache_sinfo_image_len
*
- * Purpose: Skip list iterator callback to serialize free space sections
- * of a particular size
+ * Purpose: Compute the size of the data structure on disk and return
+ * it in *image_len.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * Monday, May 8, 2006
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * August 14, 2013
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_sinfo_serialize_sect_cb(void *_item, void H5_ATTR_UNUSED *key, void *_udata)
+H5FS__cache_sinfo_image_len(const void *_thing, size_t *image_len,
+ hbool_t H5_ATTR_UNUSED *compressed_ptr, size_t H5_ATTR_UNUSED *compressed_image_len_ptr)
{
- H5FS_section_class_t *sect_cls; /* Class of section */
- H5FS_section_info_t *sect= (H5FS_section_info_t *)_item; /* Free space section to work on */
- H5FS_iter_ud_t *udata = (H5FS_iter_ud_t *)_udata; /* Callback info */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- /* Check arguments. */
- HDassert(sect);
- HDassert(udata->sinfo);
- HDassert(udata->p);
+ const H5FS_sinfo_t *sinfo = (const H5FS_sinfo_t *)_thing; /* Pointer to the object */
+ const H5FS_t *fspace; /* Free space header */
- /* Get section's class */
- sect_cls = &udata->sinfo->fspace->sect_cls[sect->type];
-
- /* Check if this section should be serialized (i.e. is not a ghost section) */
- if(!(sect_cls->flags & H5FS_CLS_GHOST_OBJ)) {
- /* The address of the section */
- UINT64ENCODE_VAR(*udata->p, sect->addr, udata->sinfo->sect_off_size);
-
- /* The type of this section */
- *(*udata->p)++ = (uint8_t)sect->type;
+ FUNC_ENTER_STATIC_NOERR
- /* Call 'serialize' callback for this section */
- if(sect_cls->serialize) {
- if((*sect_cls->serialize)(sect_cls, sect, *udata->p) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTSERIALIZE, FAIL, "can't syncronize section")
+ /* Sanity checks */
+ HDassert(sinfo);
+ HDassert(sinfo->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(sinfo->cache_info.type == H5AC_FSPACE_SINFO);
+ fspace = sinfo->fspace;
+ HDassert(fspace);
+ HDassert(fspace->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(fspace->cache_info.type == H5AC_FSPACE_HDR);
+ HDassert(image_len);
- /* Update offset in serialization buffer */
- (*udata->p) += sect_cls->serial_size;
- } /* end if */
- else
- HDassert(sect_cls->serial_size == 0);
- } /* end if */
+ /* Set the image length size */
+ H5_CHECKED_ASSIGN(*image_len, size_t, sinfo->fspace->alloc_sect_size, hsize_t);
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5FS_sinfo_serialize_sect_cb() */
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5FS__cache_sinfo_image_len() */
/*-------------------------------------------------------------------------
- * Function: H5FS_sinfo_serialize_node_cb
+ * Function: H5FS__cache_sinfo_pre_serialize
*
- * Purpose: Skip list iterator callback to serialize free space sections
- * in a bin
+ * Purpose: The objective of this function is to test to see if file space
+ * for the section info is located in temporary (AKA imaginary) file
+ * space. If it is, relocate file space for the section info to
+ * regular file space.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Quincey Koziol
- * Monday, May 8, 2006
+ * Programmer: John Mainzer
+ * 7/7/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5FS_sinfo_serialize_node_cb(void *_item, void H5_ATTR_UNUSED *key, void *_udata)
+static herr_t
+H5FS__cache_sinfo_pre_serialize(const H5F_t *f, hid_t dxpl_id, void *_thing,
+ haddr_t addr, size_t len, size_t H5_ATTR_UNUSED compressed_len, haddr_t *new_addr,
+ size_t *new_len, size_t H5_ATTR_UNUSED *new_compressed_len, unsigned *flags)
{
- H5FS_node_t *fspace_node = (H5FS_node_t *)_item; /* Free space size node to work on */
- H5FS_iter_ud_t *udata = (H5FS_iter_ud_t *)_udata; /* Callback info */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5FS_sinfo_t *sinfo = (H5FS_sinfo_t *)_thing; /* Pointer to the object */
+ H5FS_t *fspace; /* Free space header */
+ haddr_t sinfo_addr; /* Address for section info */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /* Check arguments. */
- HDassert(fspace_node);
- HDassert(udata->sinfo);
- HDassert(udata->p);
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(sinfo);
+ HDassert(sinfo->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(sinfo->cache_info.type == H5AC_FSPACE_SINFO);
+ fspace = sinfo->fspace;
+ HDassert(fspace->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(fspace->cache_info.type == H5AC_FSPACE_HDR);
+ HDassert(fspace->cache_info.is_pinned);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(H5F_addr_eq(fspace->sect_addr, addr));
+ HDassert(fspace->sect_size == len);
+ HDassert(new_addr);
+ HDassert(new_len);
+ HDassert(flags);
- /* Check if this node has any serializable sections */
- if(fspace_node->serial_count > 0) {
- /* The number of serializable sections of this node's size */
- UINT64ENCODE_VAR(*udata->p, fspace_node->serial_count, udata->sect_cnt_size);
+ /* we shouldn't be called if the section info is empty */
+ HDassert(fspace->serial_sect_count > 0);
- /* The size of the sections for this node */
- UINT64ENCODE_VAR(*udata->p, fspace_node->sect_size, udata->sinfo->sect_len_size);
+ sinfo_addr = addr; /* this will change if we relocate the section data */
- /* Iterate through all the sections of this size */
- HDassert(fspace_node->sect_list);
- if(H5SL_iterate(fspace_node->sect_list, H5FS_sinfo_serialize_sect_cb, udata) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_BADITER, FAIL, "can't iterate over section nodes")
+ /* Check for section info at temporary address */
+ if(H5F_IS_TMP_ADDR(f, fspace->sect_addr)) {
+ /* Sanity check */
+ HDassert(fspace->sect_size > 0);
+ HDassert(H5F_addr_eq(fspace->sect_addr, addr));
+
+ /* Allocate space for the section info in file */
+ if(HADDR_UNDEF == (sinfo_addr = H5MF_alloc((H5F_t *)f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_size)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
+
+ fspace->alloc_sect_size = (size_t)fspace->sect_size;
+
+ /* Sanity check */
+ HDassert(!H5F_addr_eq(sinfo->fspace->sect_addr, sinfo_addr));
+
+ /* Let the metadata cache know the section info moved */
+ if(H5AC_move_entry((H5F_t *)f, H5AC_FSPACE_SINFO, sinfo->fspace->sect_addr, sinfo_addr) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTMOVE, FAIL, "unable to move section info")
+
+ /* Update the internal address for the section info */
+ sinfo->fspace->sect_addr = sinfo_addr;
+
+ /* Mark free space header as dirty */
+ if(H5AC_mark_entry_dirty(fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty")
+ } /* end if */
+
+ if(!H5F_addr_eq(addr, sinfo_addr)) {
+ *new_addr = sinfo_addr;
+ *flags = H5C__SERIALIZE_MOVED_FLAG;
} /* end if */
+ else
+ *flags = 0;
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5FS_sinfo_serialize_node_cb() */
+} /* end H5FS__cache_sinfo_pre_serialize() */
/*-------------------------------------------------------------------------
- * Function: H5FS_cache_sinfo_flush
+ * Function: H5FS__cache_sinfo_serialize
*
- * Purpose: Flushes a dirty free space section info to disk.
+ * Purpose: Given an instance of H5FS_sinfo_t and a suitably sized buffer,
+ * serialize the contents of the instance of H5FS_sinfo_t and write
+ * its contents to the buffer. This buffer will be used to write
+ * the image of the instance to file.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * July 31 2006
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5FS_cache_sinfo_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5FS_sinfo_t *sinfo, unsigned H5_ATTR_UNUSED * flags_ptr)
+static herr_t
+H5FS__cache_sinfo_serialize(const H5F_t *f, void *_image, size_t len,
+ void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5FS_sinfo_t *sinfo = (H5FS_sinfo_t *)_thing; /* Pointer to the object */
+ H5FS_t *fspace; /* Free space header */
+ H5FS_iter_ud_t udata; /* User data for callbacks */
+ uint8_t *image = (uint8_t *)_image; /* Pointer into raw data buffer */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
+ unsigned bin; /* Current bin we are on */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /* check arguments */
+ /* Sanity checks */
HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ HDassert(image);
HDassert(sinfo);
- HDassert(sinfo->fspace);
- HDassert(sinfo->fspace->sect_cls);
-
- if(sinfo->cache_info.is_dirty || sinfo->dirty) {
- H5FS_iter_ud_t udata; /* User data for callbacks */
- uint8_t *buf = NULL; /* Temporary raw data buffer */
- uint8_t *p; /* Pointer into raw data buffer */
- uint32_t metadata_chksum; /* Computed metadata checksum value */
- unsigned bin; /* Current bin we are on */
-
- /* Sanity check address */
- if(H5F_addr_ne(addr, sinfo->fspace->sect_addr))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, FAIL, "incorrect address for free space sections")
+ HDassert(sinfo->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(sinfo->cache_info.type == H5AC_FSPACE_SINFO);
+ fspace = sinfo->fspace;
+ HDassert(fspace->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(fspace->cache_info.type == H5AC_FSPACE_HDR);
+ HDassert(fspace->cache_info.is_pinned);
+ HDassert(fspace->sect_size == len);
+ HDassert(fspace->sect_cls);
- /* Allocate temporary buffer */
- if((buf = H5FL_BLK_MALLOC(sect_block, (size_t)sinfo->fspace->sect_size)) == NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
-
- p = buf;
-
- /* Magic number */
- HDmemcpy(p, H5FS_SINFO_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += H5_SIZEOF_MAGIC;
-
- /* Version # */
- *p++ = H5FS_SINFO_VERSION;
-
- /* Address of free space header for these sections */
- H5F_addr_encode(f, &p, sinfo->fspace->addr);
-
- /* Set up user data for iterator */
- udata.sinfo = sinfo;
- udata.p = &p;
- udata.sect_cnt_size = H5VM_limit_enc_size((uint64_t)sinfo->fspace->serial_sect_count);
-
- /* Iterate over all the bins */
- for(bin = 0; bin < sinfo->nbins; bin++)
- /* Check if there are any sections in this bin */
- if(sinfo->bins[bin].bin_list)
- /* Iterate over list of section size nodes for bin */
- if(H5SL_iterate(sinfo->bins[bin].bin_list, H5FS_sinfo_serialize_node_cb, &udata) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_BADITER, FAIL, "can't iterate over section size nodes")
-
- /* Compute checksum */
- metadata_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
-
- /* Metadata checksum */
- UINT32ENCODE(p, metadata_chksum);
-
- /* Sanity check */
- HDassert((size_t)(p - buf) == sinfo->fspace->sect_size);
- HDassert(sinfo->fspace->sect_size <= sinfo->fspace->alloc_sect_size);
-
- /* Check for section info at temporary address */
- if(H5F_IS_TMP_ADDR(f, sinfo->fspace->sect_addr)) {
- /* Sanity check */
- HDassert(sinfo->fspace->sect_size > 0);
- HDassert(H5F_addr_eq(sinfo->fspace->sect_addr, addr));
-
- /* Allocate space for the section info in file */
- if(HADDR_UNDEF == (addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, sinfo->fspace->sect_size)))
- HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
- sinfo->fspace->alloc_sect_size = (size_t)sinfo->fspace->sect_size;
+ /* Magic number */
+ HDmemcpy(image, H5FS_SINFO_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ image += H5_SIZEOF_MAGIC;
- /* Sanity check */
- HDassert(!H5F_addr_eq(sinfo->fspace->sect_addr, addr));
+ /* Version # */
+ *image++ = H5FS_SINFO_VERSION;
- /* Let the metadata cache know the section info moved */
- if(H5AC_move_entry(f, H5AC_FSPACE_SINFO, sinfo->fspace->sect_addr, addr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTMOVE, FAIL, "unable to move indirect block")
+ /* Address of free space header for these sections */
+ H5F_addr_encode(f, &image, sinfo->fspace->addr);
- /* Update the internal address for the section info */
- sinfo->fspace->sect_addr = addr;
+ /* Set up user data for iterator */
+ udata.sinfo = sinfo;
+ udata.image = &image;
+ udata.sect_cnt_size = H5VM_limit_enc_size((uint64_t)sinfo->fspace->serial_sect_count);
- /* Mark free space header as dirty */
- if(H5AC_mark_entry_dirty(sinfo->fspace) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty")
- } /* end if */
+ /* Iterate over all the bins */
+ for(bin = 0; bin < sinfo->nbins; bin++)
+ /* Check if there are any sections in this bin */
+ if(sinfo->bins[bin].bin_list)
+ /* Iterate over list of section size nodes for bin */
+ if(H5SL_iterate(sinfo->bins[bin].bin_list, H5FS__sinfo_serialize_node_cb, &udata) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_BADITER, FAIL, "can't iterate over section size nodes")
- /* Write buffer to disk */
- if(H5F_block_write(f, H5FD_MEM_FSPACE_SINFO, sinfo->fspace->sect_addr, (size_t)sinfo->fspace->sect_size, dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFLUSH, FAIL, "unable to save free space sections to disk")
- buf = H5FL_BLK_FREE(sect_block, buf);
+ /* Compute checksum */
+ metadata_chksum = H5_checksum_metadata(_image, (size_t)(image - (uint8_t *)_image), 0);
- sinfo->cache_info.is_dirty = FALSE;
- sinfo->dirty = FALSE;
- } /* end if */
+ /* Metadata checksum */
+ UINT32ENCODE(image, metadata_chksum);
- if(destroy)
- if(H5FS_cache_sinfo_dest(f, sinfo) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to destroy free space section info")
+ /* Sanity check */
+ HDassert((size_t)(image - (uint8_t *)_image) == sinfo->fspace->sect_size);
+ HDassert(sinfo->fspace->sect_size <= sinfo->fspace->alloc_sect_size);
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5FS_cache_sinfo_flush() */
+} /* end H5FS__cache_sinfo_serialize() */
/*-------------------------------------------------------------------------
- * Function: H5FS_cache_sinfo_dest
+ * Function: H5FS__cache_sinfo_free_icr
*
- * Purpose: Destroys a free space section info in memory.
+ * Purpose: Free the memory used for the in core representation of the
+ * free space manager section info.
*
- * 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@ncsa.uiuc.edu
- * July 31 2006
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: John Mainzer
+ * 6/21/14
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5FS_cache_sinfo_dest(H5F_t *f, H5FS_sinfo_t *sinfo)
+static herr_t
+H5FS__cache_sinfo_free_icr(void *_thing)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5FS_sinfo_t *sinfo = (H5FS_sinfo_t *)_thing; /* Pointer to the object */
+ H5FS_t *fspace; /* Free space header */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /* Check arguments */
+ /* Sanity checks */
HDassert(sinfo);
-
- /* If we're going to free the space on disk, the address must be valid */
- HDassert(!sinfo->cache_info.free_file_space_on_destroy || H5F_addr_defined(sinfo->cache_info.addr));
-
- /* Check for freeing file space for free space section info */
- if(sinfo->cache_info.free_file_space_on_destroy) {
- /* Sanity check */
- HDassert(sinfo->fspace->alloc_sect_size > 0);
-
- /* Release the space on disk */
- /* (XXX: Nasty usage of internal DXPL value! -QAK) */
- if(!H5F_IS_TMP_ADDR(f, sinfo->cache_info.addr))
- if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, H5AC_dxpl_id, sinfo->cache_info.addr, (hsize_t)sinfo->fspace->alloc_sect_size) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space section info")
- } /* end if */
+ HDassert(sinfo->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC);
+ HDassert(sinfo->cache_info.type == H5AC_FSPACE_SINFO);
+ fspace = sinfo->fspace;
+ HDassert(fspace->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC);
+ HDassert(fspace->cache_info.type == H5AC_FSPACE_HDR);
+ HDassert(fspace->cache_info.is_pinned);
/* Destroy free space info */
if(H5FS_sinfo_dest(sinfo) < 0)
@@ -971,73 +1208,107 @@ H5FS_cache_sinfo_dest(H5F_t *f, H5FS_sinfo_t *sinfo)
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FS_cache_sinfo_dest() */
+} /* end H5FS__cache_sinfo_free_icr() */
/*-------------------------------------------------------------------------
- * Function: H5FS_cache_sinfo_clear
+ * Function: H5FS__sinfo_serialize_sect_cb
*
- * Purpose: Mark a free space section info in memory as non-dirty.
+ * Purpose: Skip list iterator callback to serialize free space sections
+ * of a particular size
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * July 31 2006
+ * Monday, May 8, 2006
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_cache_sinfo_clear(H5F_t *f, H5FS_sinfo_t *sinfo, hbool_t destroy)
+H5FS__sinfo_serialize_sect_cb(void *_item, void H5_ATTR_UNUSED *key, void *_udata)
{
+ H5FS_section_class_t *sect_cls; /* Class of section */
+ H5FS_section_info_t *sect= (H5FS_section_info_t *)_item; /* Free space section to work on */
+ H5FS_iter_ud_t *udata = (H5FS_iter_ud_t *)_udata; /* Callback info */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_STATIC
- /*
- * Check arguments.
- */
- HDassert(sinfo);
+ /* Check arguments. */
+ HDassert(sect);
+ HDassert(udata->sinfo);
+ HDassert(udata->image);
- /* Reset the dirty flag. */
- sinfo->cache_info.is_dirty = FALSE;
+ /* Get section's class */
+ sect_cls = &udata->sinfo->fspace->sect_cls[sect->type];
- if(destroy)
- if(H5FS_cache_sinfo_dest(f, sinfo) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to destroy free space section info")
+ /* Check if this section should be serialized (i.e. is not a ghost section) */
+ if(!(sect_cls->flags & H5FS_CLS_GHOST_OBJ)) {
+ /* The address of the section */
+ UINT64ENCODE_VAR(*udata->image, sect->addr, udata->sinfo->sect_off_size);
+
+ /* The type of this section */
+ *(*udata->image)++ = (uint8_t)sect->type;
+
+ /* Call 'serialize' callback for this section */
+ if(sect_cls->serialize) {
+ if((*sect_cls->serialize)(sect_cls, sect, *udata->image) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTSERIALIZE, FAIL, "can't syncronize section")
+
+ /* Update offset in serialization buffer */
+ (*udata->image) += sect_cls->serial_size;
+ } /* end if */
+ else
+ HDassert(sect_cls->serial_size == 0);
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FS_cache_sinfo_clear() */
+} /* H5FS__sinfo_serialize_sect_cb() */
/*-------------------------------------------------------------------------
- * Function: H5FS_cache_sinfo_size
+ * Function: H5FS__sinfo_serialize_node_cb
*
- * Purpose: Compute the size in bytes of a free space section info
- * on disk, and return it in *size_ptr. On failure,
- * the value of *size_ptr is undefined.
+ * Purpose: Skip list iterator callback to serialize free space sections
+ * in a bin
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * July 31 2006
+ * Monday, May 8, 2006
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_cache_sinfo_size(const H5F_t H5_ATTR_UNUSED *f, const H5FS_sinfo_t *sinfo, size_t *size_ptr)
+H5FS__sinfo_serialize_node_cb(void *_item, void H5_ATTR_UNUSED *key, void *_udata)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ H5FS_node_t *fspace_node = (H5FS_node_t *)_item; /* Free space size node to work on */
+ H5FS_iter_ud_t *udata = (H5FS_iter_ud_t *)_udata; /* Callback info */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* check arguments */
- HDassert(sinfo);
- HDassert(size_ptr);
+ FUNC_ENTER_STATIC
+
+ /* Check arguments. */
+ HDassert(fspace_node);
+ HDassert(udata->sinfo);
+ HDassert(udata->image);
- /* Set size value */
- H5_CHECKED_ASSIGN(*size_ptr, size_t, sinfo->fspace->alloc_sect_size, hsize_t);
+ /* Check if this node has any serializable sections */
+ if(fspace_node->serial_count > 0) {
+ /* The number of serializable sections of this node's size */
+ UINT64ENCODE_VAR(*udata->image, fspace_node->serial_count, udata->sect_cnt_size);
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5FS_cache_sinfo_size() */
+ /* The size of the sections for this node */
+ UINT64ENCODE_VAR(*udata->image, fspace_node->sect_size, udata->sinfo->sect_len_size);
+
+ /* Iterate through all the sections of this size */
+ HDassert(fspace_node->sect_list);
+ if(H5SL_iterate(fspace_node->sect_list, H5FS__sinfo_serialize_sect_cb, udata) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_BADITER, FAIL, "can't iterate over section nodes")
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5FS__sinfo_serialize_node_cb() */