437 lines
14 KiB
C
437 lines
14 KiB
C
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||
* Copyright by The HDF Group. *
|
||
* Copyright by the Board of Trustees of the University of Illinois. *
|
||
* All rights reserved. *
|
||
* *
|
||
* This file is part of HDF5. The full HDF5 copyright notice, including *
|
||
* terms governing use, modification, and redistribution, is contained in *
|
||
* the COPYING file, which can be found at the root of the source code *
|
||
* distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
|
||
* If you do not have access to either file, you may request a copy from *
|
||
* help@hdfgroup.org. *
|
||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||
|
||
/*-------------------------------------------------------------------------
|
||
*
|
||
* Created: H5Ochunk.c
|
||
* Jul 13 2008
|
||
* Quincey Koziol
|
||
*
|
||
* Purpose: Object header chunk routines.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
|
||
/****************/
|
||
/* Module Setup */
|
||
/****************/
|
||
|
||
#include "H5Omodule.h" /* This source code file is part of the H5O module */
|
||
|
||
|
||
/***********/
|
||
/* Headers */
|
||
/***********/
|
||
#include "H5private.h" /* Generic Functions */
|
||
#include "H5Eprivate.h" /* Error handling */
|
||
#include "H5Opkg.h" /* Object headers */
|
||
|
||
|
||
/****************/
|
||
/* Local Macros */
|
||
/****************/
|
||
|
||
|
||
/******************/
|
||
/* Local Typedefs */
|
||
/******************/
|
||
|
||
|
||
/********************/
|
||
/* Package Typedefs */
|
||
/********************/
|
||
|
||
|
||
/********************/
|
||
/* Local Prototypes */
|
||
/********************/
|
||
|
||
|
||
/*********************/
|
||
/* Package Variables */
|
||
/*********************/
|
||
|
||
/* Declare the free list for H5O_chunk_proxy_t's */
|
||
H5FL_DEFINE(H5O_chunk_proxy_t);
|
||
|
||
|
||
/*****************************/
|
||
/* Library Private Variables */
|
||
/*****************************/
|
||
|
||
|
||
/*******************/
|
||
/* Local Variables */
|
||
/*******************/
|
||
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O__chunk_add
|
||
*
|
||
* Purpose: Add new chunk for object header to metadata cache
|
||
*
|
||
* Return: SUCCEED/FAIL
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Jul 13 2008
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O__chunk_add(H5F_t *f, H5O_t *oh, unsigned idx, unsigned cont_chunkno)
|
||
{
|
||
H5O_chunk_proxy_t *chk_proxy = NULL; /* Proxy for chunk, to mark it dirty in the cache */
|
||
H5O_chunk_proxy_t *cont_chk_proxy = NULL; /* Proxy for chunk containing continuation message that points to this chunk, if not chunk 0 */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_PACKAGE_TAG(oh->cache_info.addr)
|
||
|
||
/* check args */
|
||
HDassert(f);
|
||
HDassert(oh);
|
||
HDassert(idx < oh->nchunks);
|
||
HDassert(idx > 0);
|
||
|
||
/* Allocate space for the object header data structure */
|
||
if(NULL == (chk_proxy = H5FL_CALLOC(H5O_chunk_proxy_t)))
|
||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
|
||
|
||
/* Increment reference count on object header */
|
||
if(H5O__inc_rc(oh) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTINC, FAIL, "can't increment reference count on object header")
|
||
|
||
/* Set the values in the chunk proxy */
|
||
chk_proxy->f = f;
|
||
chk_proxy->oh = oh;
|
||
chk_proxy->chunkno = idx;
|
||
|
||
/* Determine the parent of the chunk */
|
||
if(cont_chunkno != 0) {
|
||
if(NULL == (cont_chk_proxy = H5O__chunk_protect(f, oh, cont_chunkno)))
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
|
||
chk_proxy->fd_parent = cont_chk_proxy;
|
||
} /* end else */
|
||
|
||
/* Insert the chunk proxy into the cache */
|
||
if(H5AC_insert_entry(f, H5AC_OHDR_CHK, oh->chunk[idx].addr, chk_proxy, H5AC__NO_FLAGS_SET) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "unable to cache object header chunk")
|
||
|
||
chk_proxy = NULL;
|
||
|
||
done:
|
||
/* Cleanup on failure */
|
||
if(ret_value < 0)
|
||
if(chk_proxy && H5O__chunk_dest(chk_proxy) < 0)
|
||
HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to destroy object header chunk")
|
||
|
||
/* Release resources */
|
||
if(cont_chk_proxy)
|
||
if(H5O__chunk_unprotect(f, cont_chk_proxy, FALSE) < 0)
|
||
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
|
||
|
||
FUNC_LEAVE_NOAPI_TAG(ret_value)
|
||
} /* end H5O__chunk_add() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O__chunk_protect
|
||
*
|
||
* Purpose: Protect an object header chunk for modifications
|
||
*
|
||
* Return: SUCCEED/FAIL
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Jul 17 2008
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
H5O_chunk_proxy_t *
|
||
H5O__chunk_protect(H5F_t *f, H5O_t *oh, unsigned idx)
|
||
{
|
||
H5O_chunk_proxy_t *chk_proxy = NULL; /* Proxy for protected chunk */
|
||
H5O_chunk_proxy_t *ret_value = NULL; /* Return value */
|
||
|
||
FUNC_ENTER_PACKAGE_TAG(oh->cache_info.addr)
|
||
|
||
/* check args */
|
||
HDassert(f);
|
||
HDassert(oh);
|
||
HDassert(idx < oh->nchunks);
|
||
|
||
/* Check for protecting first chunk */
|
||
if(0 == idx) {
|
||
/* Create new "fake" chunk proxy for first chunk */
|
||
/* (since the first chunk is already handled by the H5O_t object) */
|
||
if(NULL == (chk_proxy = H5FL_CALLOC(H5O_chunk_proxy_t)))
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "memory allocation failed")
|
||
|
||
/* Increment reference count on object header */
|
||
if(H5O__inc_rc(oh) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTINC, NULL, "can't increment reference count on object header")
|
||
|
||
/* Set chunk proxy fields */
|
||
chk_proxy->f = f;
|
||
chk_proxy->oh = oh;
|
||
chk_proxy->chunkno = idx;
|
||
} /* end if */
|
||
else {
|
||
H5O_chk_cache_ud_t chk_udata; /* User data for loading chunk */
|
||
|
||
/* Construct the user data for protecting chunk proxy */
|
||
/* (and _not_ decoding it) */
|
||
HDmemset(&chk_udata, 0, sizeof(chk_udata));
|
||
chk_udata.oh = oh;
|
||
chk_udata.chunkno = idx;
|
||
chk_udata.size = oh->chunk[idx].size;
|
||
|
||
/* Get the chunk proxy */
|
||
if(NULL == (chk_proxy = (H5O_chunk_proxy_t *)H5AC_protect(f, H5AC_OHDR_CHK, oh->chunk[idx].addr, &chk_udata, H5AC__NO_FLAGS_SET)))
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to load object header chunk")
|
||
|
||
/* Sanity check */
|
||
HDassert(chk_proxy->oh == oh);
|
||
HDassert(chk_proxy->chunkno == idx);
|
||
} /* end else */
|
||
|
||
/* Set return value */
|
||
ret_value = chk_proxy;
|
||
|
||
done:
|
||
/* Cleanup on error */
|
||
if(!ret_value)
|
||
if(0 == idx && chk_proxy && H5O__chunk_dest(chk_proxy) < 0)
|
||
HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, NULL, "unable to destroy object header chunk")
|
||
|
||
FUNC_LEAVE_NOAPI_TAG(ret_value)
|
||
} /* end H5O__chunk_protect() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O__chunk_unprotect
|
||
*
|
||
* Purpose: Unprotect an object header chunk after modifications
|
||
*
|
||
* Return: SUCCEED/FAIL
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Jul 17 2008
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O__chunk_unprotect(H5F_t *f, H5O_chunk_proxy_t *chk_proxy, hbool_t dirtied)
|
||
{
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_PACKAGE
|
||
|
||
/* check args */
|
||
HDassert(f);
|
||
HDassert(chk_proxy);
|
||
|
||
/* Check for releasing first chunk */
|
||
if(0 == chk_proxy->chunkno) {
|
||
/* Check for dirtying the first chunk */
|
||
if(dirtied) {
|
||
/* Mark object header as dirty in cache */
|
||
if(H5AC_mark_entry_dirty(chk_proxy->oh) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, FAIL, "unable to mark object header as dirty")
|
||
} /* end else/if */
|
||
|
||
/* Decrement reference count of object header */
|
||
if(H5O__dec_rc(chk_proxy->oh) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "can't decrement reference count on object header")
|
||
|
||
/* Free fake chunk proxy */
|
||
chk_proxy = H5FL_FREE(H5O_chunk_proxy_t, chk_proxy);
|
||
} /* end if */
|
||
else {
|
||
/* Release the chunk proxy from the cache, possibly marking it dirty */
|
||
if(H5AC_unprotect(f, H5AC_OHDR_CHK, chk_proxy->oh->chunk[chk_proxy->chunkno].addr, chk_proxy, (dirtied ? H5AC__DIRTIED_FLAG : H5AC__NO_FLAGS_SET)) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header chunk")
|
||
} /* end else */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O__chunk_unprotect() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O__chunk_resize
|
||
*
|
||
* Purpose: Resize an object header chunk
|
||
*
|
||
* Return: SUCCEED/FAIL
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* May 6 2010
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O__chunk_resize(H5O_t *oh, H5O_chunk_proxy_t *chk_proxy)
|
||
{
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_PACKAGE
|
||
|
||
/* check args */
|
||
HDassert(oh);
|
||
HDassert(chk_proxy);
|
||
|
||
/* Check for resizing first chunk */
|
||
if(0 == chk_proxy->chunkno) {
|
||
/* Resize object header in cache */
|
||
if(H5AC_resize_entry(oh, oh->chunk[0].size) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTRESIZE, FAIL, "unable to resize chunk in cache")
|
||
} /* end if */
|
||
else {
|
||
/* Resize chunk in cache */
|
||
if(H5AC_resize_entry(chk_proxy, oh->chunk[chk_proxy->chunkno].size) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTRESIZE, FAIL, "unable to resize chunk in cache")
|
||
} /* end else */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O__chunk_resize() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O__chunk_update_idx
|
||
*
|
||
* Purpose: Update the chunk index for a chunk proxy
|
||
*
|
||
* Return: SUCCEED/FAIL
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Jul 13 2008
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O__chunk_update_idx(H5F_t *f, H5O_t *oh, unsigned idx)
|
||
{
|
||
H5O_chunk_proxy_t *chk_proxy = NULL;/* Proxy for chunk, to mark it dirty in the cache */
|
||
H5O_chk_cache_ud_t chk_udata; /* User data for loading chunk */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_PACKAGE_TAG(oh->cache_info.addr)
|
||
|
||
/* check args */
|
||
HDassert(f);
|
||
HDassert(oh);
|
||
HDassert(idx < oh->nchunks);
|
||
HDassert(idx > 0);
|
||
|
||
/* Construct the user data for protecting chunk proxy */
|
||
/* (and _not_ decoding it) */
|
||
HDmemset(&chk_udata, 0, sizeof(chk_udata));
|
||
chk_udata.oh = oh;
|
||
chk_udata.chunkno = idx;
|
||
chk_udata.size = oh->chunk[idx].size;
|
||
|
||
/* Get the chunk proxy */
|
||
if(NULL == (chk_proxy = (H5O_chunk_proxy_t *)H5AC_protect(f, H5AC_OHDR_CHK, oh->chunk[idx].addr, &chk_udata, H5AC__NO_FLAGS_SET)))
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
|
||
|
||
/* Update index for chunk proxy in cache */
|
||
chk_proxy->chunkno = idx;
|
||
|
||
/* Release the chunk proxy from the cache, marking it deleted */
|
||
if(H5AC_unprotect(f, H5AC_OHDR_CHK, oh->chunk[idx].addr, chk_proxy, H5AC__DIRTIED_FLAG) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header chunk")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI_TAG(ret_value)
|
||
} /* end H5O__chunk_update_idx() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O__chunk_delete
|
||
*
|
||
* Purpose: Notify metadata cache that a chunk has been deleted
|
||
*
|
||
* Return: SUCCEED/FAIL
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Jul 13 2008
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O__chunk_delete(H5F_t *f, H5O_t *oh, unsigned idx)
|
||
{
|
||
H5O_chunk_proxy_t *chk_proxy = NULL;/* Proxy for chunk, to mark it dirty in the cache */
|
||
unsigned cache_flags = H5AC__DELETED_FLAG; /* Flags for unprotecting proxy */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_PACKAGE_TAG(oh->cache_info.addr)
|
||
|
||
/* check args */
|
||
HDassert(f);
|
||
HDassert(oh);
|
||
HDassert(idx < oh->nchunks);
|
||
HDassert(idx > 0);
|
||
|
||
/* Get the chunk proxy */
|
||
if(NULL == (chk_proxy = H5O__chunk_protect(f, oh, idx)))
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
|
||
|
||
/* Only free file space if not doing SWMR writes */
|
||
if(!oh->swmr_write)
|
||
cache_flags |= H5AC__DIRTIED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
|
||
|
||
done:
|
||
/* Release the chunk proxy from the cache, marking it deleted */
|
||
if(chk_proxy && H5AC_unprotect(f, H5AC_OHDR_CHK, oh->chunk[idx].addr, chk_proxy, cache_flags) < 0)
|
||
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header chunk")
|
||
|
||
FUNC_LEAVE_NOAPI_TAG(ret_value)
|
||
} /* end H5O__chunk_delete() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O__chunk_dest
|
||
*
|
||
* Purpose: Destroy a chunk proxy object
|
||
*
|
||
* Return: SUCCEED/FAIL
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* July 13, 2008
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O__chunk_dest(H5O_chunk_proxy_t *chk_proxy)
|
||
{
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_PACKAGE
|
||
|
||
/* Check arguments */
|
||
HDassert(chk_proxy);
|
||
|
||
/* Decrement reference count of object header */
|
||
if(chk_proxy->oh && H5O__dec_rc(chk_proxy->oh) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "can't decrement reference count on object header")
|
||
|
||
/* Release the chunk proxy object */
|
||
chk_proxy = H5FL_FREE(H5O_chunk_proxy_t, chk_proxy);
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5O__chunk_dest() */
|
||
|