summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/H5HF.c102
-rw-r--r--src/H5HFcache.c2
-rw-r--r--src/H5HFhdr.c114
-rw-r--r--src/H5HFpkg.h6
4 files changed, 157 insertions, 67 deletions
diff --git a/src/H5HF.c b/src/H5HF.c
index e53a793..7e9a06b 100644
--- a/src/H5HF.c
+++ b/src/H5HF.c
@@ -240,6 +240,10 @@ HDfprintf(stderr, "%s: fh_addr = %a\n", FUNC, fh_addr);
HDfprintf(stderr, "%s: hdr->rc = %u, hdr->fspace = %p\n", FUNC, hdr->rc, hdr->fspace);
#endif /* QAK */
+ /* 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_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fractal heap info")
@@ -771,6 +775,8 @@ done:
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;
FUNC_ENTER_NOAPI(H5HF_close, FAIL)
@@ -819,12 +825,37 @@ HDfprintf(stderr, "%s; After iterator reset fh->hdr->rc = %Zu\n", FUNC, fh->hdr-
*/
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 */
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 = H5AC_protect(fh->f, dxpl_id, H5AC_FHEAP_HDR, heap_addr, NULL, NULL, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap header")
+
+ /* Set the shared heap header's file context for this operation */
+ hdr->f = fh->f;
+
+ /* 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 */
+
/* Release the fractal heap wrapper */
H5FL_FREE(H5HF_t, fh);
@@ -869,73 +900,14 @@ HDfprintf(stderr, "%s: fh_addr = %a\n", FUNC, fh_addr);
/* Check for files using shared heap header */
if(hdr->file_rc)
- HGOTO_ERROR(H5E_HEAP, H5E_OBJOPEN, FAIL, "heap still open")
-
- /* Check for free space manager for heap */
- /* (must occur before attempting to delete the heap, so indirect blocks
- * will get unpinned)
- */
- if(H5F_addr_defined(hdr->fs_addr)) {
-#ifdef QAK
-HDfprintf(stderr, "%s: hdr->fs_addr = %a\n", FUNC, hdr->fs_addr);
-#endif /* QAK */
- /* Delete free space manager for heap */
- if(H5HF_space_delete(hdr, dxpl_id) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to release fractal heap free space manager")
- } /* end if */
-
- /* Check for root direct/indirect block */
- if(H5F_addr_defined(hdr->man_dtable.table_addr)) {
-#ifdef QAK
-HDfprintf(stderr, "%s: hdr->man_dtable.table_addr = %a\n", FUNC, hdr->man_dtable.table_addr);
-#endif /* QAK */
- if(hdr->man_dtable.curr_root_rows == 0) {
- hsize_t dblock_size; /* Size of direct block */
-
- /* Check for I/O filters on this heap */
- if(hdr->filter_len > 0) {
- dblock_size = (hsize_t)hdr->pline_root_direct_size;
-#ifdef QAK
-HDfprintf(stderr, "%s: hdr->pline_root_direct_size = %Zu\n", FUNC, hdr->pline_root_direct_size);
-#endif /* QAK */
-
- /* Reset the header's pipeline information */
- hdr->pline_root_direct_size = 0;
- hdr->pline_root_direct_filter_mask = 0;
- } /* end else */
- else
- dblock_size = (hsize_t)hdr->man_dtable.cparam.start_block_size;
-
- /* Delete root direct block */
- if(H5HF_man_dblock_delete(f, dxpl_id, hdr->man_dtable.table_addr, dblock_size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to release fractal heap root direct block")
- } /* end if */
- else {
- /* Delete root indirect block */
- if(H5HF_man_iblock_delete(hdr, dxpl_id, hdr->man_dtable.table_addr, hdr->man_dtable.curr_root_rows, NULL, 0) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to release fractal heap root indirect block")
- } /* end else */
- } /* end if */
-
- /* Check for 'huge' objects in heap */
- if(H5F_addr_defined(hdr->huge_bt2_addr)) {
-#ifdef QAK
-HDfprintf(stderr, "%s: hdr->huge_bt2_addr = %a\n", FUNC, hdr->huge_bt2_addr);
-#endif /* QAK */
- /* Delete huge objects in heap and their tracker */
- if(H5HF_huge_delete(hdr, dxpl_id) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to release fractal heap 'huge' objects and tracker")
+ 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 */
- /* Release header's disk space */
- if(H5MF_xfree(f, H5FD_MEM_FHEAP_HDR, dxpl_id, fh_addr, (hsize_t)hdr->heap_size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to release fractal heap header")
-
- /* Finished deleting header */
- if(H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, fh_addr, hdr, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0)
- HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap header")
- hdr = NULL;
-
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)
diff --git a/src/H5HFcache.c b/src/H5HFcache.c
index 880c36d..0fbafba 100644
--- a/src/H5HFcache.c
+++ b/src/H5HFcache.c
@@ -307,6 +307,7 @@ HDfprintf(stderr, "%s: Load heap header, addr = %a\n", FUNC, addr);
/* Heap status flags */
/* (bit 0: "huge" object IDs have wrapped) */
+ /* (bit 1: checksum direct blocks) */
heap_flags = *p++;
hdr->huge_ids_wrapped = heap_flags & H5HF_HDR_FLAGS_HUGE_ID_WRAPPED;
hdr->checksum_dblocks = heap_flags & H5HF_HDR_FLAGS_CHECKSUM_DBLOCKS;
@@ -491,6 +492,7 @@ HDfprintf(stderr, "%s: Flushing heap header, addr = %a, destroy = %u\n", FUNC, a
/* Heap status flags */
/* (bit 0: "huge" object IDs have wrapped) */
+ /* (bit 1: checksum direct blocks) */
heap_flags = 0;
heap_flags |= (hdr->huge_ids_wrapped ? H5HF_HDR_FLAGS_HUGE_ID_WRAPPED : 0);
heap_flags |= (hdr->checksum_dblocks ? H5HF_HDR_FLAGS_CHECKSUM_DBLOCKS : 0);
diff --git a/src/H5HFhdr.c b/src/H5HFhdr.c
index 4b61063..6267e76 100644
--- a/src/H5HFhdr.c
+++ b/src/H5HFhdr.c
@@ -1481,3 +1481,117 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_hdr_empty() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_hdr_delete
+ *
+ * Purpose: Delete a fractal heap, starting with the header
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jan 5 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_hdr_delete(H5HF_hdr_t *hdr, hid_t dxpl_id)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(H5HF_hdr_delete, FAIL)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(!hdr->file_rc);
+
+#ifndef NDEBUG
+{
+ unsigned hdr_status = 0; /* Heap header's status in the metadata cache */
+
+ /* Check the heap header's status in the metadata cache */
+ if(H5AC_get_entry_status(hdr->f, hdr->heap_addr, &hdr_status) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to check metadata cache status for heap header")
+
+ /* Sanity checks on heap header */
+ HDassert(hdr_status & H5AC_ES__IN_CACHE);
+ HDassert(hdr_status & H5AC_ES__IS_PROTECTED);
+} /* end block */
+#endif /* NDEBUG */
+
+ /* Check for free space manager for heap */
+ /* (must occur before attempting to delete the heap, so indirect blocks
+ * will get unpinned)
+ */
+ if(H5F_addr_defined(hdr->fs_addr)) {
+#ifdef QAK
+HDfprintf(stderr, "%s: hdr->fs_addr = %a\n", FUNC, hdr->fs_addr);
+#endif /* QAK */
+ /* Delete free space manager for heap */
+ if(H5HF_space_delete(hdr, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to release fractal heap free space manager")
+ } /* end if */
+
+ /* Check for root direct/indirect block */
+ if(H5F_addr_defined(hdr->man_dtable.table_addr)) {
+#ifdef QAK
+HDfprintf(stderr, "%s: hdr->man_dtable.table_addr = %a\n", FUNC, hdr->man_dtable.table_addr);
+#endif /* QAK */
+ if(hdr->man_dtable.curr_root_rows == 0) {
+ hsize_t dblock_size; /* Size of direct block */
+
+ /* Check for I/O filters on this heap */
+ if(hdr->filter_len > 0) {
+ dblock_size = (hsize_t)hdr->pline_root_direct_size;
+#ifdef QAK
+HDfprintf(stderr, "%s: hdr->pline_root_direct_size = %Zu\n", FUNC, hdr->pline_root_direct_size);
+#endif /* QAK */
+
+ /* Reset the header's pipeline information */
+ hdr->pline_root_direct_size = 0;
+ hdr->pline_root_direct_filter_mask = 0;
+ } /* end else */
+ else
+ dblock_size = (hsize_t)hdr->man_dtable.cparam.start_block_size;
+
+ /* Delete root direct block */
+ if(H5HF_man_dblock_delete(hdr->f, dxpl_id, hdr->man_dtable.table_addr, dblock_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to release fractal heap root direct block")
+ } /* end if */
+ else {
+ /* Delete root indirect block */
+ if(H5HF_man_iblock_delete(hdr, dxpl_id, hdr->man_dtable.table_addr, hdr->man_dtable.curr_root_rows, NULL, 0) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to release fractal heap root indirect block")
+ } /* end else */
+ } /* end if */
+
+ /* Check for 'huge' objects in heap */
+ if(H5F_addr_defined(hdr->huge_bt2_addr)) {
+#ifdef QAK
+HDfprintf(stderr, "%s: hdr->huge_bt2_addr = %a\n", FUNC, hdr->huge_bt2_addr);
+#endif /* QAK */
+ /* Delete huge objects in heap and their tracker */
+ if(H5HF_huge_delete(hdr, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to release fractal heap 'huge' objects and tracker")
+ } /* end if */
+
+ /* Release header's disk space */
+ if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_HDR, dxpl_id, hdr->heap_addr, (hsize_t)hdr->heap_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to release fractal heap header")
+
+ /* Finished deleting header */
+ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_HDR, hdr->heap_addr, hdr, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap header")
+ hdr = NULL;
+
+done:
+ /* Unprotect the header, if an error occurred */
+ if(hdr && H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_HDR, hdr->heap_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_hdr_delete() */
+
diff --git a/src/H5HFpkg.h b/src/H5HFpkg.h
index 676a63e..6e6951d 100644
--- a/src/H5HFpkg.h
+++ b/src/H5HFpkg.h
@@ -71,8 +71,8 @@
)
/* Flags for status byte */
-#define H5HF_HDR_FLAGS_HUGE_ID_WRAPPED 0x01
-#define H5HF_HDR_FLAGS_CHECKSUM_DBLOCKS 0x02
+#define H5HF_HDR_FLAGS_HUGE_ID_WRAPPED 0x01 /* "huge" object IDs have wrapped */
+#define H5HF_HDR_FLAGS_CHECKSUM_DBLOCKS 0x02 /* checksum direct blocks */
/* Size of the fractal heap header on disk */
/* (this is the fixed-len portion, the variable-len I/O filter information
@@ -348,6 +348,7 @@ typedef struct H5HF_hdr_t {
H5AC_protect_t mode; /* Access mode for heap */
H5F_t *f; /* Pointer to file for heap */
size_t file_rc; /* Reference count of files using heap header */
+ hbool_t pending_delete; /* Heap is pending deletion */
size_t sizeof_size; /* Size of file sizes */
size_t sizeof_addr; /* Size of file addresses */
struct H5HF_indirect_t *root_iblock; /* Pointer to pinned root indirect block */
@@ -569,6 +570,7 @@ H5_DLL herr_t H5HF_hdr_reverse_iter(H5HF_hdr_t *hdr, hid_t dxpl_id,
haddr_t dblock_addr);
H5_DLL herr_t H5HF_hdr_reset_iter(H5HF_hdr_t *hdr, hsize_t curr_off);
H5_DLL herr_t H5HF_hdr_empty(H5HF_hdr_t *hdr);
+H5_DLL herr_t H5HF_hdr_delete(H5HF_hdr_t *hdr, hid_t dxpl_id);
/* Indirect block routines */
H5_DLL herr_t H5HF_iblock_incr(H5HF_indirect_t *iblock);