hdf5/src/H5HF.c
Dana Robinson d8f67a62cc [svn-r22700] Description:
Minor refactoring to extract managed object length determination.
    This makes the tiny, managed, and huge code work alike.

Tested on:
    jam (very minor change, no need for full commit test)
2012-08-20 13:44:14 -05:00

889 lines
29 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* Copyright by the Board of Trustees of the University of Illinois. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the files COPYING and Copyright.html. COPYING can be found at the root *
* of the source code distribution tree; Copyright.html can be found at the *
* root level of an installed copy of the electronic HDF5 document set and *
* is linked from the top-level documents page. It can also be found at *
* http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
* access to either file, you may request a copy from help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*-------------------------------------------------------------------------
*
* Created: H5HF.c
* Feb 24 2006
* Quincey Koziol <koziol@ncsa.uiuc.edu>
*
* Purpose: Implements a "fractal heap" for storing variable-
* length objects in a file.
*
* Please see the documentation in:
* doc/html/TechNotes/FractalHeap.html for a full description
* of how they work, etc.
*
*-------------------------------------------------------------------------
*/
/****************/
/* Module Setup */
/****************/
#define H5HF_PACKAGE /*suppress error about including H5HFpkg */
/***********/
/* Headers */
/***********/
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5FOprivate.h" /* File objects */
#include "H5HFpkg.h" /* Fractal heaps */
#include "H5MFprivate.h" /* File memory management */
/****************/
/* Local Macros */
/****************/
/******************/
/* Local Typedefs */
/******************/
/********************/
/* Package Typedefs */
/********************/
/********************/
/* Local Prototypes */
/********************/
/*********************/
/* Package Variables */
/*********************/
/*****************************/
/* Library Private Variables */
/*****************************/
/*******************/
/* Local Variables */
/*******************/
/* Declare a free list to manage the H5HF_t struct */
H5FL_DEFINE_STATIC(H5HF_t);
/*-------------------------------------------------------------------------
* Function: H5HF_op_read
*
* Purpose: Performs a 'read' operation for a heap 'op' callback
*
* Return: SUCCEED/FAIL
*
* Programmer: Quincey Koziol
* koziol@hdfgroup.org
* Sep 11 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5HF_op_read(const void *obj, size_t obj_len, void *op_data)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
/* Perform "read", using memcpy() */
HDmemcpy(op_data, obj, obj_len);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5HF_op_read() */
/*-------------------------------------------------------------------------
* Function: H5HF_op_write
*
* Purpose: Performs a 'write' operation for a heap 'op' callback
*
* Return: SUCCEED/FAIL
*
* Programmer: Quincey Koziol
* koziol@hdfgroup.org
* Dec 18 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5HF_op_write(const void *obj, size_t obj_len, void *op_data)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
/* Perform "write", using memcpy() */
HDmemcpy((void *)obj, op_data, obj_len); /* Casting away const OK -QAK */
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5HF_op_write() */
/*-------------------------------------------------------------------------
* Function: H5HF_create
*
* Purpose: Creates a new empty fractal heap in the file.
*
* Return: Pointer to heap wrapper on success
* NULL on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Feb 24 2006
*
*-------------------------------------------------------------------------
*/
H5HF_t *
H5HF_create(H5F_t *f, hid_t dxpl_id, const H5HF_create_t *cparam)
{
H5HF_t *fh = NULL; /* Pointer to new fractal heap */
H5HF_hdr_t *hdr = NULL; /* The fractal heap header information */
haddr_t fh_addr; /* Heap header address */
H5HF_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI(NULL)
/*
* Check arguments.
*/
HDassert(f);
HDassert(cparam);
/* Create shared fractal heap header */
if(HADDR_UNDEF == (fh_addr = H5HF_hdr_create(f, dxpl_id, cparam)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't create fractal heap header")
/* Allocate fractal heap wrapper */
if(NULL == (fh = H5FL_MALLOC(H5HF_t)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "memory allocation failed for fractal heap info")
/* Lock the heap header into memory */
if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, fh_addr, H5AC_WRITE)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap header")
/* Point fractal heap wrapper at header and bump it's ref count */
fh->hdr = hdr;
if(H5HF_hdr_incr(fh->hdr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared heap header")
/* Increment # of files using this heap header */
if(H5HF_hdr_fuse_incr(fh->hdr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment file reference count on shared heap header")
/* Set file pointer for this heap open context */
fh->f = f;
/* Set the return value */
ret_value = fh;
done:
if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, fh_addr, hdr, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release fractal heap header")
if(!ret_value && fh)
if(H5HF_close(fh, dxpl_id) < 0)
HDONE_ERROR(H5E_HEAP, H5E_CANTCLOSEOBJ, NULL, "unable to close fractal heap")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_create() */
/*-------------------------------------------------------------------------
* Function: H5HF_open
*
* Purpose: Opens an existing fractal heap in the file.
*
* Return: Pointer to heap wrapper on success
* NULL on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Apr 18 2006
*
*-------------------------------------------------------------------------
*/
H5HF_t *
H5HF_open(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr)
{
H5HF_t *fh = NULL; /* Pointer to new fractal heap */
H5HF_hdr_t *hdr = NULL; /* The fractal heap header information */
H5HF_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI(NULL)
/*
* Check arguments.
*/
HDassert(f);
HDassert(H5F_addr_defined(fh_addr));
/* Load the heap header into memory */
if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, fh_addr, H5AC_READ)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap header")
/* Check for pending heap deletion */
if(hdr->pending_delete)
HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, NULL, "can't open fractal heap pending deletion")
/* Create fractal heap info */
if(NULL == (fh = H5FL_MALLOC(H5HF_t)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "memory allocation failed for fractal heap info")
/* Point fractal heap wrapper at header */
fh->hdr = hdr;
if(H5HF_hdr_incr(fh->hdr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared heap header")
/* Increment # of files using this heap header */
if(H5HF_hdr_fuse_incr(fh->hdr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment file reference count on shared heap header")
/* Set file pointer for this heap open context */
fh->f = f;
/* Set the return value */
ret_value = fh;
done:
if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, fh_addr, hdr, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release fractal heap header")
if(!ret_value && fh)
if(H5HF_close(fh, dxpl_id) < 0)
HDONE_ERROR(H5E_HEAP, H5E_CANTCLOSEOBJ, NULL, "unable to close fractal heap")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_open() */
/*-------------------------------------------------------------------------
* Function: H5HF_get_id_len
*
* Purpose: Get the size of IDs for entries in a fractal heap
*
* Return: SUCCEED/FAIL
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Apr 17 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5HF_get_id_len(H5HF_t *fh, size_t *id_len_p)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
/*
* Check arguments.
*/
HDassert(fh);
HDassert(id_len_p);
/* Retrieve the ID length for entries in this heap */
*id_len_p = fh->hdr->id_len;
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5HF_get_id_len() */
/*-------------------------------------------------------------------------
* Function: H5HF_get_heap_addr
*
* Purpose: Get the address of a fractal heap
*
* Return: SUCCEED/FAIL
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Apr 18 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5HF_get_heap_addr(const H5HF_t *fh, haddr_t *heap_addr_p)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
/*
* Check arguments.
*/
HDassert(fh);
HDassert(heap_addr_p);
/* Retrieve the heap header address for this heap */
*heap_addr_p = fh->hdr->heap_addr;
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5HF_get_heap_addr() */
/*-------------------------------------------------------------------------
* Function: H5HF_insert
*
* Purpose: Insert a new object into a fractal heap.
*
* Return: Non-negative on success (with heap ID of new object
* filled in), negative on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Feb 24 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5HF_insert(H5HF_t *fh, hid_t dxpl_id, size_t size, const void *obj,
void *id/*out*/)
{
H5HF_hdr_t *hdr = NULL; /* The fractal heap header information */
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
/* Sanity check */
HDassert(fh);
HDassert(obj);
HDassert(id);
/* Check arguments */
if(size == 0)
HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "can't insert 0-sized objects")
/* Set the shared heap header's file context for this operation */
fh->hdr->f = fh->f;
/* Get the fractal heap header */
hdr = fh->hdr;
/* Check for 'huge' object */
if(size > hdr->max_man_size) {
/* Store 'huge' object in heap */
/* (Casting away const OK - QAK) */
if(H5HF_huge_insert(hdr, dxpl_id, size, (void *)obj, id) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "can't store 'huge' object in fractal heap")
} /* end if */
/* Check for 'tiny' object */
else if(size <= hdr->tiny_max_len) {
/* Store 'tiny' object in heap */
if(H5HF_tiny_insert(hdr, size, obj, id) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "can't store 'tiny' object in fractal heap")
} /* end if */
else {
/* Check if we are in "append only" mode, or if there's enough room for the object */
if(hdr->write_once) {
HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "'write once' managed blocks not supported yet")
} /* end if */
else {
/* Allocate space for object in 'managed' heap */
if(H5HF_man_insert(hdr, dxpl_id, size, obj, id) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "can't store 'managed' object in fractal heap")
} /* end else */
} /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_insert() */
/*-------------------------------------------------------------------------
* Function: H5HF_get_obj_len
*
* Purpose: Get the size of an entry in a fractal heap
*
* Return: SUCCEED/FAIL
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* May 9 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5HF_get_obj_len(H5HF_t *fh, hid_t dxpl_id, const void *_id, size_t *obj_len_p)
{
const uint8_t *id = (const uint8_t *)_id; /* Object ID */
uint8_t id_flags; /* Heap ID flag bits */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/*
* Check arguments.
*/
HDassert(fh);
HDassert(id);
HDassert(obj_len_p);
/* Get the ID flags */
id_flags = *id;
/* Check for correct heap ID version */
if((id_flags & H5HF_ID_VERS_MASK) != H5HF_ID_VERS_CURR)
HGOTO_ERROR(H5E_HEAP, H5E_VERSION, FAIL, "incorrect heap ID version")
/* Set the shared heap header's file context for this operation */
fh->hdr->f = fh->f;
/* Check type of object in heap */
if((id_flags & H5HF_ID_TYPE_MASK) == H5HF_ID_TYPE_MAN) {
if(H5HF_man_get_obj_len(fh->hdr, id, obj_len_p) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get 'managed' object's length")
} /* end if */
else if((id_flags & H5HF_ID_TYPE_MASK) == H5HF_ID_TYPE_HUGE) {
if(H5HF_huge_get_obj_len(fh->hdr, dxpl_id, id, obj_len_p) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get 'huge' object's length")
} /* end if */
else if((id_flags & H5HF_ID_TYPE_MASK) == H5HF_ID_TYPE_TINY) {
if(H5HF_tiny_get_obj_len(fh->hdr, id, obj_len_p) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get 'tiny' object's length")
} /* end if */
else {
HDfprintf(stderr, "%s: Heap ID type not supported yet!\n", FUNC);
HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "heap ID type not supported yet")
} /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_get_obj_len() */
/*-------------------------------------------------------------------------
* Function: H5HF_read
*
* Purpose: Read an object from a fractal heap into a buffer
*
* Return: SUCCEED/FAIL
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Mar 18 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5HF_read(H5HF_t *fh, hid_t dxpl_id, const void *_id, void *obj/*out*/)
{
const uint8_t *id = (const uint8_t *)_id; /* Object ID */
uint8_t id_flags; /* Heap ID flag bits */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/*
* Check arguments.
*/
HDassert(fh);
HDassert(id);
HDassert(obj);
/* Get the ID flags */
id_flags = *id;
/* Check for correct heap ID version */
if((id_flags & H5HF_ID_VERS_MASK) != H5HF_ID_VERS_CURR)
HGOTO_ERROR(H5E_HEAP, H5E_VERSION, FAIL, "incorrect heap ID version")
/* Set the shared heap header's file context for this operation */
fh->hdr->f = fh->f;
/* Check type of object in heap */
if((id_flags & H5HF_ID_TYPE_MASK) == H5HF_ID_TYPE_MAN) {
/* Read object from managed heap blocks */
if(H5HF_man_read(fh->hdr, dxpl_id, id, obj) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't read object from fractal heap")
} /* end if */
else if((id_flags & H5HF_ID_TYPE_MASK) == H5HF_ID_TYPE_HUGE) {
/* Read 'huge' object from file */
if(H5HF_huge_read(fh->hdr, dxpl_id, id, obj) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't read 'huge' object from fractal heap")
} /* end if */
else if((id_flags & H5HF_ID_TYPE_MASK) == H5HF_ID_TYPE_TINY) {
/* Read 'tiny' object from file */
if(H5HF_tiny_read(fh->hdr, id, obj) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't read 'tiny' object from fractal heap")
} /* end if */
else {
HDfprintf(stderr, "%s: Heap ID type not supported yet!\n", FUNC);
HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "heap ID type not supported yet")
} /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_read() */
/*-------------------------------------------------------------------------
* Function: H5HF_write
*
* Purpose: Write an object from a buffer into a fractal heap
*
* Notes: Writing objects in "managed" heap blocks is only storage
* method currently supported. (Which could be expanded to
* 'huge' and 'tiny' objects, with some work)
*
* Also, assumes that the 'op' routine modifies the data, and
* marks data to be written back to disk, even if 'op' routine
* didn't actually change anything. (Which could be modified
* to pass "did_modify" flag to callback, if necessary)
*
* Also, assumes that object to write is same size as object in
* heap.
*
* Return: SUCCEED/FAIL
*
* Programmer: Quincey Koziol
* koziol@hdfgroup.org
* Dec 18 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5HF_write(H5HF_t *fh, hid_t dxpl_id, void *_id, hbool_t UNUSED *id_changed,
const void *obj)
{
uint8_t *id = (uint8_t *)_id; /* Object ID */
uint8_t id_flags; /* Heap ID flag bits */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/*
* Check arguments.
*/
HDassert(fh);
HDassert(id);
HDassert(obj);
/* Get the ID flags */
id_flags = *id;
/* Check for correct heap ID version */
if((id_flags & H5HF_ID_VERS_MASK) != H5HF_ID_VERS_CURR)
HGOTO_ERROR(H5E_HEAP, H5E_VERSION, FAIL, "incorrect heap ID version")
/* Set the shared heap header's file context for this operation */
fh->hdr->f = fh->f;
/* Check type of object in heap */
if((id_flags & H5HF_ID_TYPE_MASK) == H5HF_ID_TYPE_MAN) {
/* Operate on object from managed heap blocks */
/* (ID can't change and modifying object is "easy" to manage) */
if(H5HF_man_write(fh->hdr, dxpl_id, id, obj) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "can't write to 'managed' heap object")
} /* end if */
else if((id_flags & H5HF_ID_TYPE_MASK) == H5HF_ID_TYPE_HUGE) {
/* Operate on "huge" object */
if(H5HF_huge_write(fh->hdr, dxpl_id, id, obj) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "can't write to 'huge' heap object")
} /* end if */
else if((id_flags & H5HF_ID_TYPE_MASK) == H5HF_ID_TYPE_TINY) {
/* Check for writing a 'tiny' object */
/* (which isn't supported yet - ID will change) */
HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "modifying 'tiny' object not supported yet")
} /* end if */
else {
HDfprintf(stderr, "%s: Heap ID type not supported yet!\n", FUNC);
HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "heap ID type not supported yet")
} /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_write() */
/*-------------------------------------------------------------------------
* Function: H5HF_op
*
* Purpose: Perform an operation directly on a heap object
*
* Note: The library routines currently assume that the 'op' callback
* won't modify the object. This can easily be changed later for
* "managed" heap objects, and, with some difficulty, for 'huge'
* and 'tiny' heap objects.
*
* Return: SUCCEED/FAIL
*
* Programmer: Quincey Koziol
* koziol@hdfgroup.org
* Sept 11 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5HF_op(H5HF_t *fh, hid_t dxpl_id, const void *_id, H5HF_operator_t op,
void *op_data)
{
const uint8_t *id = (const uint8_t *)_id; /* Object ID */
uint8_t id_flags; /* Heap ID flag bits */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/*
* Check arguments.
*/
HDassert(fh);
HDassert(id);
HDassert(op);
/* Get the ID flags */
id_flags = *id;
/* Check for correct heap ID version */
if((id_flags & H5HF_ID_VERS_MASK) != H5HF_ID_VERS_CURR)
HGOTO_ERROR(H5E_HEAP, H5E_VERSION, FAIL, "incorrect heap ID version")
/* Set the shared heap header's file context for this operation */
fh->hdr->f = fh->f;
/* Check type of object in heap */
if((id_flags & H5HF_ID_TYPE_MASK) == H5HF_ID_TYPE_MAN) {
/* Operate on object from managed heap blocks */
if(H5HF_man_op(fh->hdr, dxpl_id, id, op, op_data) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "can't operate on object from fractal heap")
} /* end if */
else if((id_flags & H5HF_ID_TYPE_MASK) == H5HF_ID_TYPE_HUGE) {
/* Operate on 'huge' object from file */
if(H5HF_huge_op(fh->hdr, dxpl_id, id, op, op_data) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "can't operate on 'huge' object from fractal heap")
} /* end if */
else if((id_flags & H5HF_ID_TYPE_MASK) == H5HF_ID_TYPE_TINY) {
/* Operate on 'tiny' object from file */
if(H5HF_tiny_op(fh->hdr, id, op, op_data) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "can't operate on 'tiny' object from fractal heap")
} /* end if */
else {
HDfprintf(stderr, "%s: Heap ID type not supported yet!\n", FUNC);
HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "heap ID type not supported yet")
} /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_op() */
/*-------------------------------------------------------------------------
* Function: H5HF_remove
*
* Purpose: Remove an object from a fractal heap
*
* Return: SUCCEED/FAIL
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* May 15 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5HF_remove(H5HF_t *fh, hid_t dxpl_id, const void *_id)
{
const uint8_t *id = (const uint8_t *)_id; /* Object ID */
uint8_t id_flags; /* Heap ID flag bits */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/*
* Check arguments.
*/
HDassert(fh);
HDassert(fh->hdr);
HDassert(id);
/* Get the ID flags */
id_flags = *id;
/* Check for correct heap ID version */
if((id_flags & H5HF_ID_VERS_MASK) != H5HF_ID_VERS_CURR)
HGOTO_ERROR(H5E_HEAP, H5E_VERSION, FAIL, "incorrect heap ID version")
/* Set the shared heap header's file context for this operation */
fh->hdr->f = fh->f;
/* Check type of object in heap */
if((id_flags & H5HF_ID_TYPE_MASK) == H5HF_ID_TYPE_MAN) {
/* Remove object from managed heap blocks */
if(H5HF_man_remove(fh->hdr, dxpl_id, id) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "can't remove object from fractal heap")
} /* end if */
else if((id_flags & H5HF_ID_TYPE_MASK) == H5HF_ID_TYPE_HUGE) {
/* Remove 'huge' object from file & v2 B-tree tracker */
if(H5HF_huge_remove(fh->hdr, dxpl_id, id) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "can't remove 'huge' object from fractal heap")
} /* end if */
else if((id_flags & H5HF_ID_TYPE_MASK) == H5HF_ID_TYPE_TINY) {
/* Remove 'tiny' object from heap statistics */
if(H5HF_tiny_remove(fh->hdr, id) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "can't remove 'tiny' object from fractal heap")
} /* end if */
else {
HDfprintf(stderr, "%s: Heap ID type not supported yet!\n", FUNC);
HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "heap ID type not supported yet")
} /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_remove() */
/*-------------------------------------------------------------------------
* Function: H5HF_close
*
* Purpose: Close a fractal heap
*
* Return: SUCCEED/FAIL
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Apr 17 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5HF_close(H5HF_t *fh, hid_t dxpl_id)
{
hbool_t pending_delete = FALSE; /* Whether the heap is pending deletion */
haddr_t heap_addr = HADDR_UNDEF; /* Address of heap (for deletion) */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/*
* Check arguments.
*/
HDassert(fh);
/* Decrement file reference & check if this is the last open fractal heap using the shared heap header */
if(0 == H5HF_hdr_fuse_decr(fh->hdr)) {
/* Set the shared heap header's file context for this operation */
fh->hdr->f = fh->f;
/* Close the free space information */
/* (Can't put this in header "destroy" routine, because it has
* pointers to indirect blocks in the heap, which would create
* a reference loop and the objects couldn't be removed from
* the metadata cache - QAK)
*/
if(H5HF_space_close(fh->hdr, dxpl_id) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release free space info")
/* Reset the block iterator, if necessary */
/* (Can't put this in header "destroy" routine, because it has
* pointers to indirect blocks in the heap, which would create
* a reference loop and the objects couldn't be removed from
* the metadata cache - QAK)
*/
if(H5HF_man_iter_ready(&fh->hdr->next_block))
if(H5HF_man_iter_reset(&fh->hdr->next_block) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't reset block iterator")
/* Shut down the huge object information */
/* (Can't put this in header "destroy" routine, because it has
* has the address of an object in the file, which might be
* modified by the shutdown routine - QAK)
*/
if(H5HF_huge_term(fh->hdr, dxpl_id) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release 'huge' object info")
/* Check for pending heap deletion */
if(fh->hdr->pending_delete) {
/* Set local info, so heap deletion can occur after decrementing the
* header's ref count
*/
pending_delete = TRUE;
heap_addr = fh->hdr->heap_addr;
} /* end if */
} /* end if */
/* Decrement the reference count on the heap header */
/* (don't put in H5HF_hdr_fuse_decr() as the heap header may be evicted
* immediately -QAK)
*/
if(H5HF_hdr_decr(fh->hdr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared heap header")
/* Check for pending heap deletion */
if(pending_delete) {
H5HF_hdr_t *hdr; /* Another pointer to fractal heap header */
/* Lock the heap header into memory */
if(NULL == (hdr = H5HF_hdr_protect(fh->f, dxpl_id, heap_addr, H5AC_WRITE)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap header")
/* Delete heap, starting with header (unprotects header) */
if(H5HF_hdr_delete(hdr, dxpl_id) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "unable to delete fractal heap")
} /* end if */
done:
/* Release the fractal heap wrapper */
fh = H5FL_FREE(H5HF_t, fh);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_close() */
/*-------------------------------------------------------------------------
* Function: H5HF_delete
*
* Purpose: Delete a fractal heap
*
* Return: SUCCEED/FAIL
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Aug 4 2006
*
*-------------------------------------------------------------------------
*/
herr_t
H5HF_delete(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr)
{
H5HF_hdr_t *hdr = NULL; /* The fractal heap header information */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
/*
* Check arguments.
*/
HDassert(f);
HDassert(H5F_addr_defined(fh_addr));
/* Lock the heap header into memory */
if(NULL == (hdr = H5HF_hdr_protect(f, dxpl_id, fh_addr, H5AC_WRITE)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap header")
/* Check for files using shared heap header */
if(hdr->file_rc)
hdr->pending_delete = TRUE;
else {
/* Delete heap now, starting with header (unprotects header) */
if(H5HF_hdr_delete(hdr, dxpl_id) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "unable to delete fractal heap")
hdr = NULL;
} /* end if */
done:
/* Unprotect the header, if an error occurred */
if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, fh_addr, hdr, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap header")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_delete() */