summaryrefslogtreecommitdiffstats
path: root/src/H5HF.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5HF.c')
-rw-r--r--src/H5HF.c325
1 files changed, 271 insertions, 54 deletions
diff --git a/src/H5HF.c b/src/H5HF.c
index f6a8707..4e26927 100644
--- a/src/H5HF.c
+++ b/src/H5HF.c
@@ -39,6 +39,7 @@
/***********/
#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 */
@@ -66,8 +67,8 @@
/* Package Variables */
/*********************/
-/* Declare a free list to manage the H5HF_t struct */
-H5FL_DEFINE(H5HF_t);
+/* Declare a free list to manage the H5HF_hdr_t struct */
+H5FL_DEFINE(H5HF_hdr_t);
/*****************************/
@@ -79,6 +80,9 @@ H5FL_DEFINE(H5HF_t);
/* Local Variables */
/*******************/
+/* Declare a free list to manage the H5HF_t struct */
+H5FL_DEFINE_STATIC(H5HF_t);
+
/*-------------------------------------------------------------------------
@@ -86,8 +90,8 @@ H5FL_DEFINE(H5HF_t);
*
* Purpose: Creates a new empty fractal heap in the file.
*
- * Return: Non-negative on success (with address of new fractal heap
- * filled in), negative on failure
+ * Return: Pointer to heap wrapper on success
+ * NULL on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
@@ -95,48 +99,79 @@ H5FL_DEFINE(H5HF_t);
*
*-------------------------------------------------------------------------
*/
-herr_t
-H5HF_create(H5F_t *f, hid_t dxpl_id, H5HF_create_t *cparam, haddr_t *addr_p,
- size_t *id_len_p)
+H5HF_t *
+H5HF_create(H5F_t *f, hid_t dxpl_id, H5HF_create_t *cparam)
{
- H5HF_t *hdr = NULL; /* The new fractal heap header information */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5HF_t *fh = NULL; /* Pointer to new fractal heap */
+ H5HF_hdr_t *hdr = NULL; /* The new fractal heap header information */
+ haddr_t hdr_addr; /* Heap header address */
+ H5HF_t *ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5HF_create, FAIL)
+ FUNC_ENTER_NOAPI(H5HF_create, NULL)
/*
* Check arguments.
*/
HDassert(f);
HDassert(cparam);
- HDassert(addr_p);
- HDassert(id_len_p);
/* Allocate & basic initialization for the shared header */
if(NULL == (hdr = H5HF_hdr_alloc(f)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate space for shared heap info")
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate space for shared heap info")
/* Allocate space for the header on disk */
- if(HADDR_UNDEF == (*addr_p = H5MF_alloc(f, H5FD_MEM_FHEAP_HDR, dxpl_id, (hsize_t)H5HF_HEADER_SIZE(hdr))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap header")
+ if(HADDR_UNDEF == (hdr_addr = H5MF_alloc(f, H5FD_MEM_FHEAP_HDR, dxpl_id, (hsize_t)H5HF_HEADER_SIZE(hdr))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "file allocation failed for fractal heap header")
/* Initialize shared fractal heap header */
- if(H5HF_hdr_init(hdr, *addr_p, cparam) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't initialize shared fractal heap header")
+ /* (This routine is only called for newly created heaps) */
+ if(H5HF_hdr_init(hdr, hdr_addr, cparam) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't initialize shared fractal heap header")
- /* Set the length of heap IDs */
- *id_len_p = hdr->id_len;
#ifdef QAK
HDfprintf(stderr, "%s: hdr->id_len = %Zu\n", FUNC, hdr->id_len);
#endif /* QAK */
/* Cache the new fractal heap header */
- if(H5AC_set(f, dxpl_id, H5AC_FHEAP_HDR, *addr_p, hdr, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add fractal heap header to cache")
+ if(H5AC_set(f, dxpl_id, H5AC_FHEAP_HDR, hdr_addr, hdr, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't add fractal heap header to cache")
+
+ /* Create fractal heap wrapper */
+ if(NULL == (fh = H5FL_MALLOC(H5HF_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fractal heap info")
+
+ /* Lock the heap header into memory */
+#ifdef QAK
+HDfprintf(stderr, "%s: fh_addr = %a\n", FUNC, fh_addr);
+#endif /* QAK */
+ if(NULL == (hdr = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, hdr_addr, NULL, NULL, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to load fractal heap header")
+
+ /* 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")
+
+ /* Unlock heap header, now pinned */
+ if(H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, hdr_addr, hdr, H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release fractal heap header")
+ hdr = NULL;
+
+ /* Add heap to list of open objects in file */
+ if(H5FO_insert(f, fh->hdr->heap_addr, fh) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, NULL, "can't insert heap into list of open objects")
+
+ /* Set open object count */
+ fh->fo_count = 1;
+
+ /* Set the return value */
+ ret_value = fh;
done:
- if(ret_value < 0) {
- if(hdr)
+ if(!ret_value) {
+ if(fh)
+ (void)H5HF_close(fh);
+ else if(hdr)
(void)H5HF_cache_hdr_dest(f, hdr);
} /* end if */
@@ -145,6 +180,149 @@ done:
/*-------------------------------------------------------------------------
+ * 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 new fractal heap header information */
+ H5HF_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5HF_open, NULL)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(H5F_addr_defined(fh_addr));
+
+ /* Check if group was already open */
+ if((fh = H5FO_opened(f, fh_addr)) == NULL) {
+
+ /* Clear any errors from H5FO_opened() */
+ H5E_clear_stack(NULL);
+
+ /* Load the heap header into memory */
+#ifdef QAK
+HDfprintf(stderr, "%s: fh_addr = %a\n", FUNC, fh_addr);
+#endif /* QAK */
+ if(NULL == (hdr = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, fh_addr, NULL, NULL, H5AC_READ)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to load fractal heap header")
+#ifdef QAK
+HDfprintf(stderr, "%s: hdr->rc = %u\n", FUNC, hdr->rc);
+#endif /* QAK */
+
+ /* Create fractal heap info */
+ if(NULL == (fh = H5FL_MALLOC(H5HF_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 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")
+
+ /* Add heap to list of open objects in file */
+ if(H5FO_insert(f, fh->hdr->heap_addr, fh) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, NULL, "can't insert heap into list of open objects")
+
+ /* Set open object count */
+ fh->fo_count = 1;
+ } /* end if */
+ else {
+ /* Increment shared reference count */
+ fh->fo_count++;
+ } /* end else */
+
+ /* 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_PROTECT, NULL, "unable to release fractal heap header")
+ if(!ret_value) {
+ if(fh)
+ (void)H5HF_close(fh);
+ } /* end if */
+
+ 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_NOFUNC(H5HF_get_id_len)
+
+ /*
+ * 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(H5HF_t *fh, haddr_t *heap_addr_p)
+{
+ FUNC_ENTER_NOAPI_NOFUNC(H5HF_get_heap_addr)
+
+ /*
+ * 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.
@@ -159,11 +337,10 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5HF_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t size,
- const void *obj, void *id/*out*/)
+H5HF_insert(H5HF_t *fh, hid_t dxpl_id, size_t size, const void *obj,
+ void *id/*out*/)
{
- H5HF_t *hdr = NULL; /* The fractal heap header information */
- unsigned hdr_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for header */
+ H5HF_hdr_t *hdr = NULL; /* The fractal heap header information */
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5HF_insert, FAIL)
@@ -174,17 +351,13 @@ HDfprintf(stderr, "%s: size = %Zu\n", FUNC, size);
/*
* Check arguments.
*/
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ HDassert(fh);
HDassert(size > 0);
HDassert(obj);
HDassert(id);
- /*
- * Load the fractal heap header.
- */
- if(NULL == (hdr = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, addr, NULL, NULL, H5AC_WRITE)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap header")
+ /* Get the fractal heap header */
+ hdr = fh->hdr;
/* Check if object is large enough to be standalone */
if(size >= hdr->standalone_size) {
@@ -208,14 +381,7 @@ HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "'write once' managed blocks not su
} /* end else */
} /* end else */
- /* Check for making header dirty */
- if(hdr->dirty)
- hdr_flags |= H5AC__DIRTIED_FLAG;
-
done:
- if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, addr, hdr, hdr_flags) < 0)
- HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap header")
-
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_insert() */
@@ -234,10 +400,9 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5HF_read(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_id,
- void *obj/*out*/)
+H5HF_read(H5HF_t *fh, hid_t dxpl_id, const void *_id, void *obj/*out*/)
{
- H5HF_t *hdr = NULL; /* The fractal heap header information */
+ H5HF_hdr_t *hdr = NULL; /* The fractal heap header information */
const uint8_t *id = (const uint8_t *)_id; /* Object ID */
hsize_t obj_off; /* Object's offset in heap */
size_t obj_len; /* Object's length in heap */
@@ -248,16 +413,12 @@ H5HF_read(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_id,
/*
* Check arguments.
*/
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ HDassert(fh);
HDassert(id);
HDassert(obj);
- /*
- * Load the fractal heap header.
- */
- if(NULL == (hdr = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, addr, NULL, NULL, H5AC_READ)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap header")
+ /* Get the fractal heap header */
+ hdr = fh->hdr;
/* Decode the object offset within the heap & it's length */
UINT64DECODE_VAR(id, obj_off, hdr->heap_off_size);
@@ -277,9 +438,65 @@ HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "standalone blocks not supported ye
} /* end else */
done:
- if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, addr, hdr, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap header")
-
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_read() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_close
+ *
+ * Purpose: Close a fractal heap wrapper
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Apr 17 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_close(H5HF_t *fh)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(H5HF_close, FAIL)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(fh);
+
+ /* Decrement shared object count */
+ --fh->fo_count;
+
+ /* Check if this is the last reference to the shared heap wrapper */
+ if(0 == fh->fo_count) {
+ /* Remove the heap from the list of opened objects in the file */
+ if(H5FO_delete(fh->hdr->f, H5AC_dxpl_id, fh->hdr->heap_addr) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't remove group from list of open objects")
+
+ /* Reset the free list information */
+ /* (Bump the "generation" counter in case this heap header is still
+ * in the cache when the heap is re-opened -QAK)
+ */
+ H5HF_flist_reset(fh->hdr->flist);
+ fh->hdr->fl_gen++;
+ fh->hdr->freelist_sync = FALSE;
+
+ /* Reset the block iterator */
+ if(H5HF_man_iter_reset(&fh->hdr->next_block) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't reset block iterator")
+
+ /* Decrement the reference count on the heap header */
+ if(H5HF_hdr_decr(fh->hdr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared heap header")
+
+ /* Release the fractal heap wrapper */
+ H5FL_FREE(H5HF_t, fh);
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_close() */
+