summaryrefslogtreecommitdiffstats
path: root/src/H5HFhuge.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2006-08-17 15:59:14 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2006-08-17 15:59:14 (GMT)
commit49d1901fdde7e3c4ebb2db7f13214793832cba42 (patch)
tree218114d6911d2b046b3b66656556bc0784942618 /src/H5HFhuge.c
parent0de233508859e5d2c029a4079c2e7569078412c2 (diff)
downloadhdf5-49d1901fdde7e3c4ebb2db7f13214793832cba42.zip
hdf5-49d1901fdde7e3c4ebb2db7f13214793832cba42.tar.gz
hdf5-49d1901fdde7e3c4ebb2db7f13214793832cba42.tar.bz2
[svn-r12592] Description:
Several changes, all mooshed together: - Add support for "tiny" objects - which can be stored in the heap ID itself, instead of in the heap data blocks. - Flesh out support for compressed direct blocks, but comment it out until John's got some metadata cache changes in place to support it. - Add support for applying I/O pipeline filters to 'huge' objects - Refactor 'huge' object code to store information for 'huge' objects directly in the heap ID, when there are I/O pipeline filters applied to the heap (and the heap ID is large enough to hold the information) - Update h5debug tool to correctly handle 'huge' & 'tiny' objects. - Misc. other code cleanups, etc. Tested on: FreeBSD/32 4.11 (sleipnir) Linux/64 2.4 (mir) Solaris/64 2.9 (shanti)
Diffstat (limited to 'src/H5HFhuge.c')
-rw-r--r--src/H5HFhuge.c559
1 files changed, 443 insertions, 116 deletions
diff --git a/src/H5HFhuge.c b/src/H5HFhuge.c
index 7a47dba..cc5b824 100644
--- a/src/H5HFhuge.c
+++ b/src/H5HFhuge.c
@@ -37,6 +37,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5HFpkg.h" /* Fractal heaps */
#include "H5MFprivate.h" /* File memory management */
+#include "H5MMprivate.h" /* Memory management */
/****************/
@@ -63,20 +64,25 @@
/* Local Prototypes */
/********************/
-/* local v2 B-tree operations */
+/* Local v2 B-tree operations */
static herr_t H5HF_huge_bt2_create(H5HF_hdr_t *hdr, hid_t dxpl_id);
/* v2 B-tree function callbacks (in H5HFbtree2.c) */
-herr_t H5HF_huge_bt2_found(const void *nrecord, void *op_data);
-herr_t H5HF_huge_bt2_remove(const void *nrecord, void *op_data);
+herr_t H5HF_huge_bt2_indir_found(const void *nrecord, void *op_data);
+herr_t H5HF_huge_bt2_indir_remove(const void *nrecord, void *op_data);
+herr_t H5HF_huge_bt2_filt_indir_found(const void *nrecord, void *op_data);
+herr_t H5HF_huge_bt2_filt_indir_remove(const void *nrecord, void *op_data);
+herr_t H5HF_huge_bt2_dir_remove(const void *nrecord, void *op_data);
+herr_t H5HF_huge_bt2_filt_dir_found(const void *nrecord, void *op_data);
+herr_t H5HF_huge_bt2_filt_dir_remove(const void *nrecord, void *op_data);
+
+/* Local 'huge' object support routines */
+static hsize_t H5HF_huge_new_id(H5HF_hdr_t *hdr);
/*********************/
/* Package Variables */
/*********************/
-/* The v2 B-tree class for tracking huge objects */
-H5_DLLVAR const H5B2_class_t H5HF_BTREE2[1];
-
/*****************************/
/* Library Private Variables */
@@ -104,6 +110,7 @@ H5_DLLVAR const H5B2_class_t H5HF_BTREE2[1];
static herr_t
H5HF_huge_bt2_create(H5HF_hdr_t *hdr, hid_t dxpl_id)
{
+ const H5B2_class_t *bt2_class; /* v2 B-tree class to use */
size_t rrec_size; /* Size of 'raw' records on disk */
herr_t ret_value = SUCCEED; /* Return value */
@@ -115,13 +122,45 @@ H5HF_huge_bt2_create(H5HF_hdr_t *hdr, hid_t dxpl_id)
HDassert(hdr);
/* Compute the size of 'raw' records on disk */
- if(hdr->huge_ids_direct)
- rrec_size = hdr->sizeof_addr + hdr->sizeof_size;
- else
- rrec_size = hdr->sizeof_addr + hdr->sizeof_size + hdr->huge_id_size;
+ /* (Note: the size for huge IDs could be set to 'huge_id_size', instead
+ * of 'sizeof_size', but that would make the v2 B-tree callback routines
+ * depend on the heap header, which makes the v2 B-tree flush routines
+ * difficult to write. "Waste" an extra byte or for small heaps (where
+ * the 'huge_id_size' is < 'sizeof_size' in order to make this easier -QAK)
+ */
+ if(hdr->huge_ids_direct) {
+ if(hdr->filter_len > 0) {
+ rrec_size = hdr->sizeof_addr /* Address of object */
+ + hdr->sizeof_size /* Length of object */
+ + 4 /* Filter mask for filtered object */
+ + hdr->sizeof_size; /* Size of de-filtered object in memory */
+ bt2_class = H5HF_BT2_FILT_DIR;
+ } /* end if */
+ else {
+ rrec_size = hdr->sizeof_addr /* Address of object */
+ + hdr->sizeof_size; /* Length of object */
+ bt2_class = H5HF_BT2_DIR;
+ } /* end else */
+ } /* end if */
+ else {
+ if (hdr->filter_len > 0) {
+ rrec_size = hdr->sizeof_addr /* Address of filtered object */
+ + hdr->sizeof_size /* Length of filtered object */
+ + 4 /* Filter mask for filtered object */
+ + hdr->sizeof_size /* Size of de-filtered object in memory */
+ + hdr->sizeof_size; /* Unique ID for object */
+ bt2_class = H5HF_BT2_FILT_INDIR;
+ } /* end if */
+ else {
+ rrec_size = hdr->sizeof_addr /* Address of object */
+ + hdr->sizeof_size /* Length of object */
+ + hdr->sizeof_size; /* Unique ID for object */
+ bt2_class = H5HF_BT2_INDIR;
+ } /* end else */
+ } /* end else */
/* Create v2 B-tree for tracking 'huge' objects */
- if(H5B2_create(hdr->f, dxpl_id, &hdr->huge_bt2_class, (size_t)H5HF_HUGE_BT2_NODE_SIZE, rrec_size,
+ if(H5B2_create(hdr->f, dxpl_id, bt2_class, (size_t)H5HF_HUGE_BT2_NODE_SIZE, rrec_size,
H5HF_HUGE_BT2_SPLIT_PERC, H5HF_HUGE_BT2_MERGE_PERC, &hdr->huge_bt2_addr/*out*/) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "can't create v2 B-tree for tracking 'huge' heap objects")
@@ -156,22 +195,38 @@ H5HF_huge_init(H5HF_hdr_t *hdr)
/* Compute information about 'huge' objects for the heap */
/* Check if we can completely hold the 'huge' object's offset & length in
- * the file in the heap ID (which will speed up accessing it)
+ * the file in the heap ID (which will speed up accessing it) and we don't
+ * have any I/O pipeline filters.
*/
#ifdef QAK
HDfprintf(stderr, "%s: hdr->id_len = %u\n", "H5HF_huge_init", (unsigned)hdr->id_len);
+HDfprintf(stderr, "%s: hdr->filter_len = %u\n", "H5HF_huge_init", (unsigned)hdr->filter_len);
#endif /* QAK */
- if((hdr->sizeof_addr + hdr->sizeof_size) <= (hdr->id_len - 1)) {
- /* Indicate that v2 B-tree doesn't have to be used to locate object */
- hdr->huge_ids_direct = TRUE;
-
- /* Set the size of 'huge' object IDs */
- hdr->huge_id_size = hdr->sizeof_addr + hdr->sizeof_size;
+ if(hdr->filter_len > 0) {
+ if((hdr->id_len - 1) >= (hdr->sizeof_addr + hdr->sizeof_size + 4 + hdr->sizeof_size)) {
+ /* Indicate that v2 B-tree doesn't have to be used to locate object */
+ hdr->huge_ids_direct = TRUE;
+
+ /* Set the size of 'huge' object IDs */
+ hdr->huge_id_size = hdr->sizeof_addr + hdr->sizeof_size + hdr->sizeof_size;
+ } /* end if */
+ else
+ /* Indicate that v2 B-tree must be used to access object */
+ hdr->huge_ids_direct = FALSE;
} /* end if */
else {
- /* Indicate that v2 B-tree must be used to locate object */
- hdr->huge_ids_direct = FALSE;
-
+ if((hdr->sizeof_addr + hdr->sizeof_size) <= (hdr->id_len - 1)) {
+ /* Indicate that v2 B-tree doesn't have to be used to locate object */
+ hdr->huge_ids_direct = TRUE;
+
+ /* Set the size of 'huge' object IDs */
+ hdr->huge_id_size = hdr->sizeof_addr + hdr->sizeof_size;
+ } /* end if */
+ else
+ /* Indicate that v2 B-tree must be used to locate object */
+ hdr->huge_ids_direct = FALSE;
+ } /* end else */
+ if(!hdr->huge_ids_direct) {
/* Set the size and maximum value of 'huge' object ID */
if((hdr->id_len - 1) < sizeof(hsize_t)) {
hdr->huge_id_size = hdr->id_len - 1;
@@ -181,28 +236,65 @@ HDfprintf(stderr, "%s: hdr->id_len = %u\n", "H5HF_huge_init", (unsigned)hdr->id_
hdr->huge_id_size = sizeof(hsize_t);
hdr->huge_max_id = HSIZET_MAX;
} /* end else */
- } /* end else */
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HF_huge_init() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_huge_new_id
+ *
+ * Purpose: Determine a new ID for an indirectly accessed 'huge' object
+ * (either filtered or not)
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Aug 15 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static hsize_t
+H5HF_huge_new_id(H5HF_hdr_t *hdr)
+{
+ hsize_t new_id; /* New object's ID */
+ hsize_t ret_value; /* Return value */
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_huge_new_id)
- /* Set up the v2 B-tree for tracking 'huge' objects in the heap */
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
- /* Copy the standard v2 B-tree class */
- HDmemcpy(&hdr->huge_bt2_class, H5HF_BTREE2, sizeof(H5B2_class_t));
+ /* Check for wrapping around 'huge' object ID space */
+ if(hdr->huge_ids_wrapped)
+ /* Fail for now - eventually should iterate through v2 B-tree, looking for available ID */
+ HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, 0, "wrapping 'huge' object IDs not supported yet")
+ else {
+ /* Get new 'huge' object ID to use for object */
+ /* (avoids using ID 0) */
+ new_id = ++hdr->huge_next_id;
- /* Set the native record size for the v2 B-tree */
- hdr->huge_bt2_class.nrec_size = sizeof(H5HF_huge_bt2_rec_t);
+ /* Check for wrapping 'huge' object IDs around */
+ if(hdr->huge_next_id == hdr->huge_max_id)
+ hdr->huge_ids_wrapped = TRUE;
+ } /* end else */
- /* Set v2 B-tree class's "class private" pointer to the heap header */
- hdr->huge_bt2_class.cls_private = hdr;
+ /* Set return value */
+ ret_value = new_id;
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5HF_huge_init() */
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_huge_new_id() */
/*-------------------------------------------------------------------------
* Function: H5HF_huge_insert
*
- * Purpose: Insert a huge object into the file and track it
+ * Purpose: Insert a 'huge' object into the file and track it
*
* Return: SUCCEED/FAIL
*
@@ -213,12 +305,14 @@ HDfprintf(stderr, "%s: hdr->id_len = %u\n", "H5HF_huge_init", (unsigned)hdr->id_
*-------------------------------------------------------------------------
*/
herr_t
-H5HF_huge_insert(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t obj_size, const void *obj,
+H5HF_huge_insert(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t obj_size, void *obj,
void *_id)
{
- H5HF_huge_bt2_rec_t obj_rec; /* Record for tracking object */
uint8_t *id = (uint8_t *)_id; /* Pointer to ID buffer */
haddr_t obj_addr; /* Address of object in the file */
+ void *write_buf; /* Pointer to buffer to write */
+ size_t write_size; /* Size of [possibly filtered] object written to file */
+ unsigned filter_mask = 0; /* Filter mask for object (only used for filtered objects) */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_huge_insert)
@@ -239,54 +333,142 @@ HDfprintf(stderr, "%s: obj_size = %Zu\n", FUNC, obj_size);
if(H5HF_huge_bt2_create(hdr, dxpl_id) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "can't create v2 B-tree for tracking 'huge' heap objects")
+ /* Check for I/O pipeline filter on heap */
+ if(hdr->filter_len > 0) {
+ H5Z_cb_t filter_cb = {NULL, NULL}; /* Filter callback structure */
+ size_t nbytes; /* Number of bytes used */
+
+ /* Allocate buffer to perform I/O filtering on */
+ write_size = obj_size;
+ if(NULL == (write_buf = H5MM_malloc(write_size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "memory allocation failed for pipeline buffer")
+ HDmemcpy(write_buf, obj, write_size);
+
+ /* Push direct block data through I/O filter pipeline */
+ nbytes = write_size;
+ if(H5Z_pipeline(&(hdr->pline), 0, &filter_mask, H5Z_NO_EDC,
+ filter_cb, &nbytes, &write_size, &write_buf) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFILTER, FAIL, "output pipeline failed")
+#ifdef QAK
+HDfprintf(stderr, "%s: nbytes = %Zu, write_size = %Zu, write_buf = %p\n", FUNC, nbytes, write_size, write_buf);
+HDfprintf(stderr, "%s: obj_size = %Zu, obj = %p\n", FUNC, obj_size, obj);
+#endif /* QAK */
+
+ /* Update size of object on disk */
+ write_size = nbytes;
+ } /* end if */
+ else {
+ write_buf = obj;
+ write_size = obj_size;
+ } /* end else */
+
/* Allocate space in the file for storing the 'huge' object */
- if(HADDR_UNDEF == (obj_addr = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_HUGE_OBJ, dxpl_id, (hsize_t)obj_size)))
+ if(HADDR_UNDEF == (obj_addr = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_HUGE_OBJ, dxpl_id, (hsize_t)write_size)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap huge object")
/* Write the object's data to disk */
- if(H5F_block_write(hdr->f, H5FD_MEM_FHEAP_HUGE_OBJ, obj_addr, obj_size, dxpl_id, obj) < 0)
+ if(H5F_block_write(hdr->f, H5FD_MEM_FHEAP_HUGE_OBJ, obj_addr, write_size, dxpl_id, write_buf) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "writing 'huge' object to file failed")
- /* Initialize shared part of record for tracking object in v2 B-tree */
- obj_rec.addr = obj_addr;
- obj_rec.len = obj_size;
+ /* Release buffer for writing, if we had one */
+ if(write_buf != obj) {
+ HDassert(hdr->filter_len > 0);
+ H5MM_xfree(write_buf);
+ } /* end if */
+
+ /* Perform different actions for directly & indirectly accessed 'huge' objects */
+ if(hdr->huge_ids_direct) {
+ if(hdr->filter_len > 0) {
+ H5HF_huge_bt2_filt_dir_rec_t obj_rec; /* Record for tracking object */
+
+ /* Initialize record for tracking object in v2 B-tree */
+ obj_rec.addr = obj_addr;
+ obj_rec.len = write_size;
+ obj_rec.filter_mask = filter_mask;
+ obj_rec.obj_size = obj_size;
+#ifdef QAK
+HDfprintf(stderr, "%s: obj_rec = {%a, %Hu, %x, %Hu}\n", FUNC, obj_rec.addr, obj_rec.len, obj_rec.filter_mask, obj_rec.obj_size);
+#endif /* QAK */
- /* If the 'huge' object will be indirectly accessed, through the v2 B-tree,
- * create an ID for it, otherwise put a zero in for ID
- */
- if(hdr->huge_ids_direct)
- obj_rec.id = 0;
- else {
- /* Check for wrapping around 'huge' object ID space */
- if(hdr->huge_ids_wrapped)
- /* Fail for now - eventually should iterate through v2 B-tree, looking for available ID */
- HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "wrapping 'huge' object IDs not supported yet")
+ /* Insert record for object in v2 B-tree */
+ if(H5B2_insert(hdr->f, dxpl_id, H5HF_BT2_FILT_DIR, hdr->huge_bt2_addr, &obj_rec) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "couldn't insert object tracking record in v2 B-tree")
+
+ /* Encode ID for user */
+ *id++ = H5HF_ID_VERS_CURR | H5HF_ID_TYPE_HUGE;
+ H5F_addr_encode(hdr->f, &id, obj_addr);
+ H5F_ENCODE_LENGTH(hdr->f, id, (hsize_t)write_size);
+ UINT32ENCODE(id, filter_mask);
+ H5F_ENCODE_LENGTH(hdr->f, id, (hsize_t)obj_size);
+ } /* end if */
else {
- /* Get new 'huge' object ID to use for object */
- /* (avoid using ID 0) */
- obj_rec.id = ++hdr->huge_next_id;
+ H5HF_huge_bt2_dir_rec_t obj_rec; /* Record for tracking object */
- /* Check for wrapping 'huge' object IDs around */
- if(hdr->huge_next_id == hdr->huge_max_id)
- hdr->huge_ids_wrapped = TRUE;
- } /* end else */
- } /* end else */
+ /* Initialize record for tracking object in v2 B-tree */
+ obj_rec.addr = obj_addr;
+ obj_rec.len = write_size;
#ifdef QAK
-HDfprintf(stderr, "%s: obj_rec = {%a, %Hu, %Hu}\n", FUNC, obj_rec.addr, obj_rec.len, obj_rec.id);
+HDfprintf(stderr, "%s: obj_rec = {%a, %Hu}\n", FUNC, obj_rec.addr, obj_rec.len);
#endif /* QAK */
- /* Insert record for object in v2 B-tree */
- if(H5B2_insert(hdr->f, dxpl_id, &hdr->huge_bt2_class, hdr->huge_bt2_addr, &obj_rec) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "couldn't insert object tracking record in v2 B-tree")
+ /* Insert record for object in v2 B-tree */
+ if(H5B2_insert(hdr->f, dxpl_id, H5HF_BT2_DIR, hdr->huge_bt2_addr, &obj_rec) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "couldn't insert object tracking record in v2 B-tree")
- /* Encode ID for user */
- *id++ = H5HF_ID_VERS_CURR | H5HF_ID_TYPE_HUGE;
- if(hdr->huge_ids_direct) {
- H5F_addr_encode(hdr->f, &id, obj_addr);
- H5F_ENCODE_LENGTH(hdr->f, id, (hsize_t)obj_size);
+ /* Encode ID for user */
+ *id++ = H5HF_ID_VERS_CURR | H5HF_ID_TYPE_HUGE;
+ H5F_addr_encode(hdr->f, &id, obj_addr);
+ H5F_ENCODE_LENGTH(hdr->f, id, (hsize_t)write_size);
+ } /* end if */
} /* end if */
- else
- UINT64ENCODE_VAR(id, obj_rec.id, hdr->huge_id_size)
+ else {
+ H5HF_huge_bt2_filt_indir_rec_t filt_indir_rec; /* Record for tracking filtered object */
+ H5HF_huge_bt2_indir_rec_t indir_rec; /* Record for tracking non-filtered object */
+ const H5B2_class_t *bt2_class; /* v2 B-tree class to use */
+ void *ins_rec; /* Pointer to record to insert */
+ hsize_t new_id; /* New ID for object */
+
+ /* Get new ID for object */
+ if(0 == (new_id = H5HF_huge_new_id(hdr)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't generate new ID for object")
+
+ if(hdr->filter_len > 0) {
+ /* Initialize record for object in v2 B-tree */
+ filt_indir_rec.addr = obj_addr;
+ filt_indir_rec.len = write_size;
+ filt_indir_rec.filter_mask = filter_mask;
+ filt_indir_rec.obj_size = obj_size;
+ filt_indir_rec.id = new_id;
+#ifdef QAK
+HDfprintf(stderr, "%s: filt_indir_rec = {%a, %Hu, %x, %Hu, %Hu}\n", FUNC, filt_indir_rec.addr, filt_indir_rec.len, filt_indir_rec.filter_mask, filt_indir_rec.obj_size, filt_indir_rec.id);
+#endif /* QAK */
+
+ /* Set pointer to record to insert */
+ ins_rec = &filt_indir_rec;
+ bt2_class = H5HF_BT2_FILT_INDIR;
+ } /* end if */
+ else {
+ /* Initialize record for object in v2 B-tree */
+ indir_rec.addr = obj_addr;
+ indir_rec.len = write_size;
+ indir_rec.id = new_id;
+#ifdef QAK
+HDfprintf(stderr, "%s: indir_rec = {%a, %Hu, %Hu}\n", FUNC, indir_rec.addr, indir_rec.len, indir_rec.id);
+#endif /* QAK */
+
+ /* Set pointer to record to insert */
+ ins_rec = &indir_rec;
+ bt2_class = H5HF_BT2_INDIR;
+ } /* end else */
+
+ /* Insert record for tracking object in v2 B-tree */
+ if(H5B2_insert(hdr->f, dxpl_id, bt2_class, hdr->huge_bt2_addr, ins_rec) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "couldn't insert object tracking record in v2 B-tree")
+
+ /* Encode ID for user */
+ *id++ = H5HF_ID_VERS_CURR | H5HF_ID_TYPE_HUGE;
+ UINT64ENCODE_VAR(id, new_id, hdr->huge_id_size)
+ } /* end else */
/* Update statistics about heap */
hdr->huge_size += obj_size;
@@ -320,7 +502,7 @@ H5HF_huge_get_obj_len(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
{
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5HF_huge_get_obj_len, FAIL)
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_huge_get_obj_len)
/*
* Check arguments.
@@ -330,28 +512,57 @@ H5HF_huge_get_obj_len(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
HDassert(id);
HDassert(obj_len_p);
+ /* Skip over the flag byte */
+ id++;
+
/* Check if 'huge' object ID encodes address & length directly */
if(hdr->huge_ids_direct) {
- /* Skip over object offset in file */
- id += hdr->sizeof_addr;
+ if(hdr->filter_len > 0) {
+ /* Skip over filtered object info */
+ id += hdr->sizeof_addr + hdr->sizeof_size + 4;
+
+ /* Retrieve the object's length */
+ H5F_DECODE_LENGTH(hdr->f, id, *obj_len_p);
+ } /* end if */
+ else {
+ /* Skip over object offset in file */
+ id += hdr->sizeof_addr;
- /* Retrieve the object's length */
- H5F_DECODE_LENGTH(hdr->f, id, *obj_len_p);
+ /* Retrieve the object's length */
+ H5F_DECODE_LENGTH(hdr->f, id, *obj_len_p);
+ } /* end else */
} /* end if */
else {
- H5HF_huge_bt2_rec_t found_rec; /* Record found from tracking object */
- H5HF_huge_bt2_rec_t search_rec; /* Record for searching for object */
+ if(hdr->filter_len > 0) {
+ H5HF_huge_bt2_filt_indir_rec_t found_rec; /* Record found from tracking object */
+ H5HF_huge_bt2_filt_indir_rec_t search_rec; /* Record for searching for object */
+
+ /* Get ID for looking up 'huge' object in v2 B-tree */
+ UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size)
+
+ /* Look up object in v2 B-tree */
+ if(H5B2_find(hdr->f, dxpl_id, H5HF_BT2_FILT_INDIR, hdr->huge_bt2_addr,
+ &search_rec, H5HF_huge_bt2_filt_indir_found, &found_rec) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree")
+
+ /* Retrieve the object's length */
+ *obj_len_p = (size_t)found_rec.obj_size;
+ } /* end if */
+ else {
+ H5HF_huge_bt2_indir_rec_t found_rec; /* Record found from tracking object */
+ H5HF_huge_bt2_indir_rec_t search_rec; /* Record for searching for object */
- /* Get ID for looking up 'huge' object in v2 B-tree */
- UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size)
+ /* Get ID for looking up 'huge' object in v2 B-tree */
+ UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size)
- /* Look up object in v2 B-tree */
- if(H5B2_find(hdr->f, dxpl_id, &hdr->huge_bt2_class, hdr->huge_bt2_addr,
- &search_rec, H5HF_huge_bt2_found, &found_rec) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree")
+ /* Look up object in v2 B-tree */
+ if(H5B2_find(hdr->f, dxpl_id, H5HF_BT2_INDIR, hdr->huge_bt2_addr,
+ &search_rec, H5HF_huge_bt2_indir_found, &found_rec) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree")
- /* Retrieve the object's length */
- *obj_len_p = (size_t)found_rec.len;
+ /* Retrieve the object's length */
+ *obj_len_p = (size_t)found_rec.len;
+ } /* end else */
} /* end else */
done:
@@ -375,8 +586,10 @@ done:
herr_t
H5HF_huge_read(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id, void *obj)
{
+ void *read_buf; /* Pointer to buffer for reading */
haddr_t obj_addr; /* Object's address in the file */
hsize_t obj_size = 0; /* Object's size in the file */
+ unsigned filter_mask = 0; /* Filter mask for object (only used for filtered objects) */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_huge_read)
@@ -388,33 +601,85 @@ H5HF_huge_read(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id, void *obj)
HDassert(id);
HDassert(obj);
+ /* Skip over the flag byte */
+ id++;
+
/* Check for 'huge' object ID that encodes address & length directly */
if(hdr->huge_ids_direct) {
- /* Retrieve the object's address and length */
+ /* Retrieve the object's address and length (common) */
H5F_addr_decode(hdr->f, &id, &obj_addr);
H5F_DECODE_LENGTH(hdr->f, id, obj_size);
+
+ /* Retrieve extra information needed for filtered objects */
+ if(hdr->filter_len > 0)
+ UINT32DECODE(id, filter_mask);
} /* end if */
else {
- H5HF_huge_bt2_rec_t found_rec; /* Record found from tracking object */
- H5HF_huge_bt2_rec_t search_rec; /* Record for searching for object */
+ if(hdr->filter_len > 0) {
+ H5HF_huge_bt2_filt_indir_rec_t found_rec; /* Record found from tracking object */
+ H5HF_huge_bt2_filt_indir_rec_t search_rec; /* Record for searching for object */
+
+ /* Get ID for looking up 'huge' object in v2 B-tree */
+ UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size)
+
+ /* Look up object in v2 B-tree */
+ if(H5B2_find(hdr->f, dxpl_id, H5HF_BT2_FILT_INDIR, hdr->huge_bt2_addr,
+ &search_rec, H5HF_huge_bt2_filt_indir_found, &found_rec) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree")
+
+ /* Retrieve the object's address & length */
+ obj_addr = found_rec.addr;
+ obj_size = found_rec.len;
+ filter_mask = found_rec.filter_mask;
+ } /* end if */
+ else {
+ H5HF_huge_bt2_indir_rec_t found_rec; /* Record found from tracking object */
+ H5HF_huge_bt2_indir_rec_t search_rec; /* Record for searching for object */
- /* Get ID for looking up 'huge' object in v2 B-tree */
- UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size)
+ /* Get ID for looking up 'huge' object in v2 B-tree */
+ UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size)
- /* Look up object in v2 B-tree */
- if(H5B2_find(hdr->f, dxpl_id, &hdr->huge_bt2_class, hdr->huge_bt2_addr,
- &search_rec, H5HF_huge_bt2_found, &found_rec) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree")
+ /* Look up object in v2 B-tree */
+ if(H5B2_find(hdr->f, dxpl_id, H5HF_BT2_INDIR, hdr->huge_bt2_addr,
+ &search_rec, H5HF_huge_bt2_indir_found, &found_rec) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree")
- /* Retrieve the object's address & length */
- obj_addr = found_rec.addr;
- obj_size = found_rec.len;
+ /* Retrieve the object's address & length */
+ obj_addr = found_rec.addr;
+ obj_size = found_rec.len;
+ } /* end else */
} /* end else */
- /* Read the object's data from the file */
- if (H5F_block_read(hdr->f, H5FD_MEM_FHEAP_HUGE_OBJ, obj_addr, (size_t)obj_size, dxpl_id, obj) < 0)
+ /* Set up buffer for reading */
+ if(hdr->filter_len > 0) {
+ if(NULL == (read_buf = H5MM_malloc((size_t)obj_size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "memory allocation failed for pipeline buffer")
+ } /* end if */
+ else
+ read_buf = obj;
+
+ /* Read the object's (possibly filtered) data from the file */
+ if(H5F_block_read(hdr->f, H5FD_MEM_FHEAP_HUGE_OBJ, obj_addr, (size_t)obj_size, dxpl_id, read_buf) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_READERROR, FAIL, "can't read 'huge' object's data from the file")
+ /* Check for I/O pipeline filter on heap */
+ if(hdr->filter_len > 0) {
+ H5Z_cb_t filter_cb = {NULL, NULL}; /* Filter callback structure */
+ size_t read_size; /* Object's size in the file */
+ size_t nbytes; /* Number of bytes used */
+
+ /* De-filter the object */
+ read_size = nbytes = obj_size;
+ if(H5Z_pipeline(&(hdr->pline), H5Z_FLAG_REVERSE, &filter_mask, H5Z_NO_EDC, filter_cb, &nbytes, &read_size, &read_buf) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFILTER, FAIL, "input filter failed")
+
+ /* Copy object to user's buffer */
+ HDmemcpy(obj, read_buf, nbytes);
+
+ /* Release read buffer */
+ H5MM_xfree(read_buf);
+ } /* end if */
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_huge_read() */
@@ -436,7 +701,6 @@ done:
herr_t
H5HF_huge_remove(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id)
{
- H5HF_huge_bt2_rec_t search_rec; /* Record for searching for object */
H5HF_huge_remove_ud1_t udata; /* User callback data for v2 B-tree remove call */
herr_t ret_value = SUCCEED; /* Return value */
@@ -448,26 +712,70 @@ H5HF_huge_remove(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id)
HDassert(hdr);
HDassert(id);
+ /* Skip over the flag byte */
+ id++;
+
+ /* Set up the common callback info */
+ udata.hdr = hdr;
+ udata.dxpl_id = dxpl_id;
+
/* Check for 'huge' object ID that encodes address & length directly */
if(hdr->huge_ids_direct) {
- /* Retrieve the object's address and length */
- /* (used as key in v2 B-tree record) */
- H5F_addr_decode(hdr->f, &id, &search_rec.addr);
- H5F_DECODE_LENGTH(hdr->f, id, search_rec.len);
+ if(hdr->filter_len > 0) {
+ H5HF_huge_bt2_filt_dir_rec_t search_rec; /* Record for searching for object */
+
+ /* Retrieve the object's address and length */
+ /* (used as key in v2 B-tree record) */
+ H5F_addr_decode(hdr->f, &id, &search_rec.addr);
+ H5F_DECODE_LENGTH(hdr->f, id, search_rec.len);
+
+ /* Remove the record for tracking the 'huge' object from the v2 B-tree */
+ /* (space in the file for the object is freed in the 'remove' callback) */
+ if(H5B2_remove(hdr->f, dxpl_id, H5HF_BT2_FILT_DIR, hdr->huge_bt2_addr,
+ &search_rec, H5HF_huge_bt2_filt_dir_remove, &udata) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "can't remove object from B-tree")
+ } /* end if */
+ else {
+ H5HF_huge_bt2_dir_rec_t search_rec; /* Record for searching for object */
+
+ /* Retrieve the object's address and length */
+ /* (used as key in v2 B-tree record) */
+ H5F_addr_decode(hdr->f, &id, &search_rec.addr);
+ H5F_DECODE_LENGTH(hdr->f, id, search_rec.len);
+
+ /* Remove the record for tracking the 'huge' object from the v2 B-tree */
+ /* (space in the file for the object is freed in the 'remove' callback) */
+ if(H5B2_remove(hdr->f, dxpl_id, H5HF_BT2_DIR, hdr->huge_bt2_addr,
+ &search_rec, H5HF_huge_bt2_dir_remove, &udata) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "can't remove object from B-tree")
+ } /* end else */
} /* end if */
- else
- /* Get ID for looking up 'huge' object in v2 B-tree */
- UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size)
+ else {
+ if(hdr->filter_len > 0) {
+ H5HF_huge_bt2_filt_indir_rec_t search_rec; /* Record for searching for object */
+
+ /* Get ID for looking up 'huge' object in v2 B-tree */
+ UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size)
+
+ /* Remove the record for tracking the 'huge' object from the v2 B-tree */
+ /* (space in the file for the object is freed in the 'remove' callback) */
+ if(H5B2_remove(hdr->f, dxpl_id, H5HF_BT2_FILT_INDIR, hdr->huge_bt2_addr,
+ &search_rec, H5HF_huge_bt2_filt_indir_remove, &udata) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "can't remove object from B-tree")
+ } /* end if */
+ else {
+ H5HF_huge_bt2_indir_rec_t search_rec; /* Record for searching for object */
- /* Set up the callback info */
- udata.hdr = hdr;
- udata.dxpl_id = dxpl_id;
+ /* Get ID for looking up 'huge' object in v2 B-tree */
+ UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size)
- /* Remove the record for tracking the 'huge' object from the v2 B-tree */
- /* (space in the file for the object is freed in the 'remove' callback) */
- if(H5B2_remove(hdr->f, dxpl_id, &hdr->huge_bt2_class, hdr->huge_bt2_addr,
- &search_rec, H5HF_huge_bt2_remove, &udata) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "can't remove object from B-tree")
+ /* Remove the record for tracking the 'huge' object from the v2 B-tree */
+ /* (space in the file for the object is freed in the 'remove' callback) */
+ if(H5B2_remove(hdr->f, dxpl_id, H5HF_BT2_INDIR, hdr->huge_bt2_addr,
+ &search_rec, H5HF_huge_bt2_indir_remove, &udata) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "can't remove object from B-tree")
+ } /* end else */
+ } /* end else */
/* Update statistics about heap */
hdr->huge_size -= udata.obj_len;
@@ -515,7 +823,8 @@ H5HF_huge_term(H5HF_hdr_t *hdr, hid_t dxpl_id)
HDassert(hdr->huge_size == 0);
/* Delete the v2 B-tree */
- if(H5B2_delete(hdr->f, dxpl_id, &hdr->huge_bt2_class, hdr->huge_bt2_addr, NULL, NULL) < 0)
+ /* (any v2 B-tree class will work here) */
+ if(H5B2_delete(hdr->f, dxpl_id, H5HF_BT2_INDIR, hdr->huge_bt2_addr, NULL, NULL) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "can't delete v2 B-tree")
/* Reset the information about 'huge' objects in the file */
@@ -568,8 +877,26 @@ H5HF_huge_delete(H5HF_hdr_t *hdr, hid_t dxpl_id)
udata.dxpl_id = dxpl_id;
/* Delete the v2 B-tree */
- if(H5B2_delete(hdr->f, dxpl_id, &hdr->huge_bt2_class, hdr->huge_bt2_addr, H5HF_huge_bt2_remove, &udata) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "can't delete v2 B-tree")
+ if(hdr->huge_ids_direct) {
+ if(hdr->filter_len > 0) {
+ if(H5B2_delete(hdr->f, dxpl_id, H5HF_BT2_FILT_DIR, hdr->huge_bt2_addr, H5HF_huge_bt2_filt_dir_remove, &udata) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "can't delete v2 B-tree")
+ } /* end if */
+ else {
+ if(H5B2_delete(hdr->f, dxpl_id, H5HF_BT2_DIR, hdr->huge_bt2_addr, H5HF_huge_bt2_dir_remove, &udata) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "can't delete v2 B-tree")
+ } /* end else */
+ } /* end if */
+ else {
+ if(hdr->filter_len > 0) {
+ if(H5B2_delete(hdr->f, dxpl_id, H5HF_BT2_FILT_INDIR, hdr->huge_bt2_addr, H5HF_huge_bt2_filt_indir_remove, &udata) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "can't delete v2 B-tree")
+ } /* end if */
+ else {
+ if(H5B2_delete(hdr->f, dxpl_id, H5HF_BT2_INDIR, hdr->huge_bt2_addr, H5HF_huge_bt2_indir_remove, &udata) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "can't delete v2 B-tree")
+ } /* end else */
+ } /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)