diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2006-08-17 15:59:14 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2006-08-17 15:59:14 (GMT) |
commit | 49d1901fdde7e3c4ebb2db7f13214793832cba42 (patch) | |
tree | 218114d6911d2b046b3b66656556bc0784942618 /src/H5HFhuge.c | |
parent | 0de233508859e5d2c029a4079c2e7569078412c2 (diff) | |
download | hdf5-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.c | 559 |
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) |