diff options
author | Dana Robinson <derobins@hdfgroup.org> | 2015-08-14 19:58:54 (GMT) |
---|---|---|
committer | Dana Robinson <derobins@hdfgroup.org> | 2015-08-14 19:58:54 (GMT) |
commit | c27d1808480a4ffae4af5ff5384993f63ea6b5d4 (patch) | |
tree | 251081393f02ad4fb6767af9d23be50971761d79 /src/H5FScache.c | |
parent | 37b14fd3ed8aae8f3b83df03ca29f82178c25f8f (diff) | |
parent | d3e931c772a1fea1d8d0676dd6dd3fe95b000d9e (diff) | |
download | hdf5-c27d1808480a4ffae4af5ff5384993f63ea6b5d4.zip hdf5-c27d1808480a4ffae4af5ff5384993f63ea6b5d4.tar.gz hdf5-c27d1808480a4ffae4af5ff5384993f63ea6b5d4.tar.bz2 |
[svn-r27507] Merge of r27237-27500 from the trunk.
Tested w/ h5committest
NOTES: - The manifest may still be messed up.
- Cmake fails since the dual binary work needs to be merged with
this repo's CMake externals.
Diffstat (limited to 'src/H5FScache.c')
-rw-r--r-- | src/H5FScache.c | 1397 |
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, §_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 = ℑ + 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() */ |