diff options
Diffstat (limited to 'src/H5FScache.c')
-rw-r--r-- | src/H5FScache.c | 139 |
1 files changed, 105 insertions, 34 deletions
diff --git a/src/H5FScache.c b/src/H5FScache.c index 8ace571..8a345fe 100644 --- a/src/H5FScache.c +++ b/src/H5FScache.c @@ -36,6 +36,7 @@ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ #include "H5FSpkg.h" /* File free space */ +#include "H5MFprivate.h" /* File memory management */ #include "H5Vprivate.h" /* Vectors and arrays */ #include "H5WBprivate.h" /* Wrapped Buffers */ @@ -100,6 +101,7 @@ const H5AC_class_t H5AC_FSPACE_HDR[1] = {{ (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, }}; @@ -110,6 +112,7 @@ const H5AC_class_t H5AC_FSPACE_SINFO[1] = {{ (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, }}; @@ -179,7 +182,7 @@ H5FS_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_fs_prot, size = H5FS_HEADER_SIZE(f); /* Get a pointer to a buffer that's large enough for header */ - if(NULL == (hdr = H5WB_actual(wb, size))) + if(NULL == (hdr = (uint8_t *)H5WB_actual(wb, size))) HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, NULL, "can't get actual buffer") /* Read header from disk */ @@ -189,16 +192,16 @@ H5FS_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_fs_prot, p = hdr; /* Magic number */ - if(HDmemcmp(p, H5FS_HDR_MAGIC, (size_t)H5FS_SIZEOF_MAGIC)) + if(HDmemcmp(p, H5FS_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC)) HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "wrong free space header signature") - p += H5FS_SIZEOF_MAGIC; + p += H5_SIZEOF_MAGIC; /* Version */ if(*p++ != H5FS_HDR_VERSION) HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "wrong free space header version") /* Client ID */ - fspace->client = *p++; + fspace->client = (H5FS_client_t)*p++; if(fspace->client >= H5FS_NUM_CLIENT_ID) HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "unknown client ID in free space header") @@ -293,6 +296,45 @@ H5FS_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5F HDassert(f); HDassert(H5F_addr_defined(addr)); HDassert(fspace); + HDassert(H5F_addr_defined(fspace->addr)); + + /* 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 + */ + 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_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") + } /* end if */ + + /* Mark section info clean */ + fspace->sinfo->dirty = FALSE; + } /* end if */ + } /* end if */ + else if(fspace->serial_sect_count > 0) + /* Sanity check that section info has address */ + HDassert(H5F_addr_defined(fspace->sect_addr)); if(fspace->cache_info.is_dirty) { uint8_t *hdr; /* Pointer to header buffer */ @@ -308,15 +350,15 @@ H5FS_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5F size = H5FS_HEADER_SIZE(f); /* Get a pointer to a buffer that's large enough for header */ - if(NULL == (hdr = H5WB_actual(wb, size))) + if(NULL == (hdr = (uint8_t *)H5WB_actual(wb, size))) HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "can't get actual buffer") /* Get temporary pointer to header */ p = hdr; /* Magic number */ - HDmemcpy(p, H5FS_HDR_MAGIC, (size_t)H5FS_SIZEOF_MAGIC); - p += H5FS_SIZEOF_MAGIC; + HDmemcpy(p, H5FS_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC); + p += H5_SIZEOF_MAGIC; /* Version # */ *p++ = H5FS_HDR_VERSION; @@ -400,9 +442,8 @@ done: * *------------------------------------------------------------------------- */ -/* ARGSUSED */ herr_t -H5FS_cache_hdr_dest(H5F_t UNUSED *f, H5FS_t *fspace) +H5FS_cache_hdr_dest(H5F_t *f, H5FS_t *fspace) { unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ @@ -414,6 +455,12 @@ H5FS_cache_hdr_dest(H5F_t UNUSED *f, H5FS_t *fspace) */ HDassert(fspace); + /* 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)); + /* Terminate the section classes for this free space list */ for(u = 0; u < fspace->nclasses ; u++) { /* Call the class termination routine, if there is one */ @@ -422,12 +469,23 @@ H5FS_cache_hdr_dest(H5F_t UNUSED *f, H5FS_t *fspace) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "unable to finalize section class") } /* end for */ + /* 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)H5FS_HEADER_SIZE(f)) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space header") + } /* end if */ + /* Release the memory for the free space section classes */ if(fspace->sect_cls) - fspace->sect_cls = H5FL_SEQ_FREE(H5FS_section_class_t, fspace->sect_cls); + fspace->sect_cls = (H5FS_section_class_t *)H5FL_SEQ_FREE(H5FS_section_class_t, fspace->sect_cls); /* Free free space info */ - H5FL_FREE(H5FS_t, fspace); + (void)H5FL_FREE(H5FS_t, fspace); done: FUNC_LEAVE_NOAPI(ret_value) @@ -531,9 +589,6 @@ H5FS_cache_sinfo_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * H5FS_sinfo_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5FS_cache_sinfo_load) -#ifdef QAK -HDfprintf(stderr, "%s: Load free space sections, addr = %a\n", FUNC, addr); -#endif /* QAK */ /* Check arguments */ HDassert(f); @@ -543,11 +598,6 @@ HDfprintf(stderr, "%s: Load free space sections, addr = %a\n", FUNC, addr); /* Allocate a new free space section info */ if(NULL == (sinfo = H5FS_sinfo_new(f, fspace))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - - /* Link free space manager to section info */ - /* (for deserializing sections) */ - HDassert(fspace->sinfo == NULL); - fspace->sinfo = sinfo; /* Sanity check address */ if(H5F_addr_ne(addr, fspace->sect_addr)) @@ -566,9 +616,9 @@ HDfprintf(stderr, "%s: Load free space sections, addr = %a\n", FUNC, addr); p = buf; /* Magic number */ - if(HDmemcmp(p, H5FS_SINFO_MAGIC, (size_t)H5FS_SIZEOF_MAGIC)) + if(HDmemcmp(p, H5FS_SINFO_MAGIC, (size_t)H5_SIZEOF_MAGIC)) HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "wrong free space sections signature") - p += H5FS_SIZEOF_MAGIC; + p += H5_SIZEOF_MAGIC; /* Version */ if(*p++ != H5FS_SINFO_VERSION) @@ -670,7 +720,7 @@ HDfprintf(stderr, "%s: Load free space sections, addr = %a\n", FUNC, addr); done: if(buf) - H5FL_BLK_FREE(sect_block, buf); + (void)H5FL_BLK_FREE(sect_block, buf); if(!ret_value && sinfo) (void)H5FS_cache_sinfo_dest(f, sinfo); @@ -807,7 +857,7 @@ H5FS_cache_sinfo_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H HDassert(sinfo->fspace); HDassert(sinfo->fspace->sect_cls); - if(sinfo->cache_info.is_dirty) { + 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 */ @@ -825,8 +875,8 @@ H5FS_cache_sinfo_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H p = buf; /* Magic number */ - HDmemcpy(p, H5FS_SINFO_MAGIC, (size_t)H5FS_SIZEOF_MAGIC); - p += H5FS_SIZEOF_MAGIC; + HDmemcpy(p, H5FS_SINFO_MAGIC, (size_t)H5_SIZEOF_MAGIC); + p += H5_SIZEOF_MAGIC; /* Version # */ *p++ = H5FS_SINFO_VERSION; @@ -863,9 +913,10 @@ H5FS_cache_sinfo_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H 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") - H5FL_BLK_FREE(sect_block, buf); + (void)H5FL_BLK_FREE(sect_block, buf); sinfo->cache_info.is_dirty = FALSE; + sinfo->dirty = FALSE; } /* end if */ if(destroy) @@ -888,6 +939,10 @@ done: * Programmer: Quincey Koziol * Saturday, March 11, 2006 * + * Modifications: + * Vailin Choi, July 29th, 2008 + * Add HDassert() to make sure "free" method exists before calling + * *------------------------------------------------------------------------- */ static herr_t @@ -900,6 +955,7 @@ H5FS_sinfo_free_sect_cb(void *_sect, void UNUSED *key, void *op_data) HDassert(sect); HDassert(sinfo); + HDassert(sinfo->fspace->sect_cls[sect->type].free); /* Call the section's class 'free' method on the section */ (*sinfo->fspace->sect_cls[sect->type].free)(sect); @@ -936,7 +992,7 @@ H5FS_sinfo_free_node_cb(void *item, void UNUSED *key, void *op_data) H5SL_destroy(fspace_node->sect_list, H5FS_sinfo_free_sect_cb, op_data); /* Release free space list node */ - H5FL_FREE(H5FS_node_t, fspace_node); + (void)H5FL_FREE(H5FS_node_t, fspace_node); FUNC_LEAVE_NOAPI(0) } /* H5FS_sinfo_free_node_cb() */ @@ -955,7 +1011,6 @@ H5FS_sinfo_free_node_cb(void *item, void UNUSED *key, void *op_data) * *------------------------------------------------------------------------- */ -/* ARGSUSED */ herr_t H5FS_cache_sinfo_dest(H5F_t *f, H5FS_sinfo_t *sinfo) { @@ -971,6 +1026,20 @@ H5FS_cache_sinfo_dest(H5F_t *f, H5FS_sinfo_t *sinfo) HDassert(sinfo->fspace); HDassert(sinfo->bins); + /* 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(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 */ + /* Clear out lists of nodes */ for(u = 0; u < sinfo->nbins; u++) if(sinfo->bins[u].bin_list) { @@ -979,22 +1048,24 @@ H5FS_cache_sinfo_dest(H5F_t *f, H5FS_sinfo_t *sinfo) } /* end if */ /* Release bins for skip lists */ - sinfo->bins = H5FL_SEQ_FREE(H5FS_bin_t, sinfo->bins); + sinfo->bins = (H5FS_bin_t *)H5FL_SEQ_FREE(H5FS_bin_t, sinfo->bins); /* Release skip list for merging sections */ if(sinfo->merge_list) if(H5SL_close(sinfo->merge_list) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTCLOSEOBJ, FAIL, "can't destroy section merging skip list") - /* Unpin the free space header in the cache */ + /* Decrement the reference count on free space header */ /* (make certain this is last action with section info, to allow for header * disappearing immediately) */ - if(H5AC_unpin_entry(f, sinfo->fspace) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin free space header") + sinfo->fspace->sinfo = NULL; + if(H5FS_decr(f, sinfo->fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTDEC, FAIL, "unable to decrement ref. count on free space header") + sinfo->fspace = NULL; /* Release free space section info */ - H5FL_FREE(H5FS_sinfo_t, sinfo); + (void)H5FL_FREE(H5FS_sinfo_t, sinfo); done: FUNC_LEAVE_NOAPI(ret_value) @@ -1063,7 +1134,7 @@ H5FS_cache_sinfo_size(const H5F_t UNUSED *f, const H5FS_sinfo_t *sinfo, size_t * HDassert(size_ptr); /* Set size value */ - H5_ASSIGN_OVERFLOW(/* To: */ *size_ptr, /* From: */ sinfo->fspace->sect_size, /* From: */ hsize_t, /* To: */ size_t); + H5_ASSIGN_OVERFLOW(/* To: */ *size_ptr, /* From: */ sinfo->fspace->alloc_sect_size, /* From: */ hsize_t, /* To: */ size_t); FUNC_LEAVE_NOAPI(SUCCEED) } /* H5FS_cache_sinfo_size() */ |