diff options
-rw-r--r-- | src/H5Edefin.h | 2 | ||||
-rw-r--r-- | src/H5Einit.h | 10 | ||||
-rw-r--r-- | src/H5Epubgen.h | 4 | ||||
-rw-r--r-- | src/H5Eterm.h | 4 | ||||
-rw-r--r-- | src/H5FS.c | 379 | ||||
-rw-r--r-- | src/H5FSdbg.c | 39 | ||||
-rw-r--r-- | src/H5FSpkg.h | 28 | ||||
-rw-r--r-- | src/H5FSprivate.h | 43 | ||||
-rw-r--r-- | src/H5HF.c | 10 | ||||
-rw-r--r-- | src/H5HFcache.c | 45 | ||||
-rw-r--r-- | src/H5HFdbg.c | 20 | ||||
-rw-r--r-- | src/H5HFdblock.c | 184 | ||||
-rw-r--r-- | src/H5HFdtable.c | 39 | ||||
-rw-r--r-- | src/H5HFhdr.c | 766 | ||||
-rw-r--r-- | src/H5HFiblock.c | 1107 | ||||
-rw-r--r-- | src/H5HFint.c | 91 | ||||
-rw-r--r-- | src/H5HFiter.c | 113 | ||||
-rw-r--r-- | src/H5HFpkg.h | 101 | ||||
-rw-r--r-- | src/H5HFprivate.h | 14 | ||||
-rw-r--r-- | src/H5HFsection.c | 1126 | ||||
-rw-r--r-- | src/H5HFspace.c | 56 | ||||
-rw-r--r-- | src/H5HFstat.c | 4 | ||||
-rw-r--r-- | src/H5HFtest.c | 121 | ||||
-rw-r--r-- | src/H5err.txt | 2 | ||||
-rw-r--r-- | test/fheap.c | 5124 |
25 files changed, 6720 insertions, 2712 deletions
diff --git a/src/H5Edefin.h b/src/H5Edefin.h index d10ec5f..f297a50 100644 --- a/src/H5Edefin.h +++ b/src/H5Edefin.h @@ -74,6 +74,8 @@ hid_t H5E_CANTGETSIZE_g = FAIL; /* Unable to compute size */ hid_t H5E_CANTRESTORE_g = FAIL; /* Can't restore condition */ hid_t H5E_CANTCOMPUTE_g = FAIL; /* Can't compute value */ hid_t H5E_CANTEXTEND_g = FAIL; /* Can't extend heap's space */ +hid_t H5E_CANTATTACH_g = FAIL; /* Can't attach object */ +hid_t H5E_CANTUPDATE_g = FAIL; /* Can't update object */ /* Function entry/exit interface errors */ hid_t H5E_CANTINIT_g = FAIL; /* Unable to initialize object */ diff --git a/src/H5Einit.h b/src/H5Einit.h index c6909d2..aedbac3 100644 --- a/src/H5Einit.h +++ b/src/H5Einit.h @@ -264,6 +264,16 @@ if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't extend heap's space"))==NULL) HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") if((H5E_CANTEXTEND_g = H5I_register(H5I_ERROR_MSG, msg))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") +assert(H5E_CANTATTACH_g==(-1)); +if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't attach object"))==NULL) + HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") +if((H5E_CANTATTACH_g = H5I_register(H5I_ERROR_MSG, msg))<0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") +assert(H5E_CANTUPDATE_g==(-1)); +if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't update object"))==NULL) + HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") +if((H5E_CANTUPDATE_g = H5I_register(H5I_ERROR_MSG, msg))<0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") /* Function entry/exit interface errors */ assert(H5E_CANTINIT_g==(-1)); diff --git a/src/H5Epubgen.h b/src/H5Epubgen.h index 01ed436..b989db7 100644 --- a/src/H5Epubgen.h +++ b/src/H5Epubgen.h @@ -122,9 +122,13 @@ H5_DLLVAR hid_t H5E_CANTGETSIZE_g; /* Unable to compute size */ #define H5E_CANTRESTORE (H5OPEN H5E_CANTRESTORE_g) #define H5E_CANTCOMPUTE (H5OPEN H5E_CANTCOMPUTE_g) #define H5E_CANTEXTEND (H5OPEN H5E_CANTEXTEND_g) +#define H5E_CANTATTACH (H5OPEN H5E_CANTATTACH_g) +#define H5E_CANTUPDATE (H5OPEN H5E_CANTUPDATE_g) H5_DLLVAR hid_t H5E_CANTRESTORE_g; /* Can't restore condition */ H5_DLLVAR hid_t H5E_CANTCOMPUTE_g; /* Can't compute value */ H5_DLLVAR hid_t H5E_CANTEXTEND_g; /* Can't extend heap's space */ +H5_DLLVAR hid_t H5E_CANTATTACH_g; /* Can't attach object */ +H5_DLLVAR hid_t H5E_CANTUPDATE_g; /* Can't update object */ /* Function entry/exit interface errors */ #define H5E_CANTINIT (H5OPEN H5E_CANTINIT_g) diff --git a/src/H5Eterm.h b/src/H5Eterm.h index 1643db9..c2c206e 100644 --- a/src/H5Eterm.h +++ b/src/H5Eterm.h @@ -75,7 +75,9 @@ H5E_CANTGETSIZE_g= /* Heap errors */ H5E_CANTRESTORE_g= H5E_CANTCOMPUTE_g= -H5E_CANTEXTEND_g= +H5E_CANTEXTEND_g= +H5E_CANTATTACH_g= +H5E_CANTUPDATE_g= /* Function entry/exit interface errors */ H5E_CANTINIT_g= @@ -71,12 +71,6 @@ typedef struct H5FS_node_t { H5SL_t *sect_list; /* Skip list to hold pointers to actual free list section node */ } H5FS_node_t; -/* Free space section bin info */ -typedef struct H5FS_bin_t { - size_t sect_count; /* Total # of sections in this bin */ - H5SL_t *bin_list; /* Skip list of differently sized sections */ -} H5FS_bin_t; - /* User data for skip list iterator callback for syncing section info */ typedef struct { H5F_t *f; /* Pointer to the file */ @@ -102,28 +96,6 @@ typedef struct { /* Package Typedefs */ /********************/ -/* Main free space info */ -struct H5FS_t { - /* Stored values (from header) */ - H5FS_hdr_t *hdr; /* Pointer to header info */ - - /* Computed/cached values */ - haddr_t addr; /* Address of free space header on disk */ - unsigned nbins; /* Number of bins */ - size_t serial_size; /* Total serialized size of all section nodes */ - size_t size_count; /* Number of differently sized sections */ - unsigned sect_prefix_size; /* Size of the section serialization prefix (in bytes) */ - unsigned sect_off_size; /* Size of a section offset (in bytes) */ - unsigned sect_len_size; /* Size of a section length (in bytes) */ - hbool_t dirty; /* Space information is dirty */ - - /* Memory data structures (not stored directly) */ - H5FS_section_class_t *sect_cls; /* Array of section classes for this free list */ - H5FS_section_info_t *single; /* Section information when free list has only one free section */ - H5SL_t *merge_list; /* Skip list to hold sections for detecting merges */ - H5FS_bin_t *bins; /* Array of lists of lists of free sections */ -}; - /********************/ /* Local Prototypes */ @@ -133,9 +105,8 @@ static herr_t H5FS_open_remove(H5FS_t *fspace); static herr_t H5FS_init(H5FS_t *fspace); static herr_t H5FS_sect_free_cb(void *item, void *key, void *op_data); static herr_t H5FS_node_free_cb(void *item, void *key, void *op_data); -static herr_t H5FS_sect_increase(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace); -static herr_t H5FS_sect_decrease(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace); -static herr_t H5FS_add_bin_node(H5FS_t *fspace, H5FS_section_info_t *node); +static herr_t H5FS_sect_increase(H5FS_t *fspace); +static herr_t H5FS_sect_decrease(H5FS_t *fspace); static htri_t H5FS_find_bin_node(H5FS_t *fspace, hsize_t request, H5FS_section_info_t **node); static herr_t H5FS_serialize_sect_cb(void *_item, void UNUSED *key, void *_udata); static herr_t H5FS_serialize_node_cb(void *_item, void UNUSED *key, void *_udata); @@ -367,7 +338,7 @@ H5FS_init(H5FS_t *fspace) */ H5FS_t * H5FS_create(H5F_t *f, hid_t dxpl_id, haddr_t *fs_addr, const H5FS_create_t *fs_create, - size_t nclasses, H5FS_section_class_t *classes, const void *cls_init_udata) + size_t nclasses, const H5FS_section_class_t *classes[], const void *cls_init_udata) { H5FS_t *fspace = NULL; /* New free space structure */ H5FS_hdr_t *fs_hdr = NULL; /* New free space header */ @@ -390,10 +361,17 @@ H5FS_create(H5F_t *f, hid_t dxpl_id, haddr_t *fs_addr, const H5FS_create_t *fs_c HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for free space free list") /* Set immutable free list parameters */ - fspace->sect_cls = classes; + if(NULL == (fspace->sect_cls = H5FL_SEQ_MALLOC(H5FS_section_class_t, nclasses))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for free space section class array ") /* Initialize the section classes for this free space list */ for(u = 0; u < nclasses; u++) { + /* Make certain that section class type can be used as an array index into this array */ + HDassert(u == classes[u]->type); + + /* Copy the class information into the free space manager */ + HDmemcpy(&fspace->sect_cls[u], classes[u], sizeof(H5FS_section_class_t)); + /* Call the class initialization routine, if there is one */ if(fspace->sect_cls[u].init_cls) if((fspace->sect_cls[u].init_cls)(&fspace->sect_cls[u], cls_init_udata) < 0) @@ -495,7 +473,7 @@ done: */ H5FS_t * H5FS_open(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr, size_t nclasses, - H5FS_section_class_t *classes, const void *cls_init_udata) + const H5FS_section_class_t *classes[], const void *cls_init_udata) { H5FS_hdr_t *fs_hdr = NULL; /* Free space header loaded from file */ H5FS_t *fspace = NULL; /* New free space structure */ @@ -532,10 +510,17 @@ HDfprintf(stderr, "%s: Opening free space manager\n", FUNC); /* Set immutable free list parameters */ fspace->addr = fs_addr; HDassert(fspace->hdr->nclasses == nclasses); - fspace->sect_cls = classes; + if(NULL == (fspace->sect_cls = H5FL_SEQ_MALLOC(H5FS_section_class_t, nclasses))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for free space section class array ") /* Initialize the section classes for this free space list */ for(u = 0; u < nclasses; u++) { + /* Make certain that section class type can be used as an array index into this array */ + HDassert(u == classes[u]->type); + + /* Copy the class information into the free space manager */ + HDmemcpy(&fspace->sect_cls[u], classes[u], sizeof(H5FS_section_class_t)); + /* Call the class initialization routine, if there is one */ if(fspace->sect_cls[u].init_cls) if((fspace->sect_cls[u].init_cls)(&fspace->sect_cls[u], cls_init_udata) < 0) @@ -601,14 +586,11 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5FS_sect_increase(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace) +H5FS_sect_increase(H5FS_t *fspace) { - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_increase) + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_sect_increase) /* Check arguments. */ - HDassert(f); HDassert(fspace); HDassert(fspace->hdr); @@ -618,8 +600,7 @@ H5FS_sect_increase(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace) /* Update the free space sections' serialized size */ fspace->hdr->sect_size = H5FS_serialize_size(fspace); -done: - FUNC_LEAVE_NOAPI(ret_value) + FUNC_LEAVE_NOAPI(SUCCEED) } /* H5FS_sect_increase() */ @@ -639,14 +620,13 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5FS_sect_decrease(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace) +H5FS_sect_decrease(H5FS_t *fspace) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_decrease) /* Check arguments. */ - HDassert(f); HDassert(fspace); HDassert(fspace->hdr); @@ -884,14 +864,15 @@ H5FS_sect_unlink_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info HGOTO_ERROR(H5E_FSPACE, H5E_NOTFOUND, FAIL, "can't find section node on size list") /* Decrement amount of space required to serialize all sections */ - fspace->serial_size -= fspace->sect_cls[sect->cls->type].serial_size; + fspace->serial_size -= fspace->sect_cls[sect->type].serial_size; #ifdef QAK +HDfprintf(stderr, "%s: fspace->hdr->tot_space = %Hu\n", FUNC, fspace->hdr->tot_space); HDfprintf(stderr, "%s: fspace->serial_size = %Zu\n", FUNC, fspace->serial_size); -HDfprintf(stderr, "%s: fspace->sect_cls[(*node)->cls->type].serial_size = %Zu\n", FUNC, fspace->sect_cls[(*node)->cls->type].serial_size); +HDfprintf(stderr, "%s: fspace->sect_cls[%u].serial_size = %Zu\n", FUNC, sect->type, fspace->sect_cls[sect->type].serial_size); #endif /* QAK */ /* Update section info & check if we need less room for the serialized free space sections */ - if(H5FS_sect_decrease(f, dxpl_id, fspace) < 0) + if(H5FS_sect_decrease(fspace) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't increase free space section size on disk") /* Decrement amount of free space managed */ @@ -1121,10 +1102,9 @@ H5FS_sect_link_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t HDassert(sect); /* Add section to the address-ordered list of sections */ - if(fspace->merge_list == NULL) { + if(fspace->merge_list == NULL) if(NULL == (fspace->merge_list = H5SL_create(H5SL_TYPE_HADDR, 0.5, H5FS_DEFAULT_SKIPLIST_HEIGHT))) HGOTO_ERROR(H5E_FSPACE, H5E_CANTCREATE, FAIL, "can't create skip list for merging free space sections") - } /* end if */ if(H5SL_insert(fspace->merge_list, sect, §->addr) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space node into merging skip list") @@ -1133,10 +1113,10 @@ H5FS_sect_link_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t HDfprintf(stderr, "%s: fspace->serial_size = %Zu\n", FUNC, fspace->serial_size); HDfprintf(stderr, "%s: fspace->sect_cls[sect->cls->type].serial_size = %Zu\n", FUNC, fspace->sect_cls[sect->cls->type].serial_size); #endif /* QAK */ - fspace->serial_size += fspace->sect_cls[sect->cls->type].serial_size; + fspace->serial_size += fspace->sect_cls[sect->type].serial_size; /* Update section info & check if we need more room for the serialized free space sections */ - if(H5FS_sect_increase(f, dxpl_id, fspace) < 0) + if(H5FS_sect_increase(fspace) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't increase free space section size on disk") /* Increment amount of free space managed */ @@ -1173,13 +1153,22 @@ H5FS_sect_link(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *sec HDassert(fspace); HDassert(sect); - /* Add node to size tracked data structures */ + /* Add section to size tracked data structures */ +#ifdef QAK +HDfprintf(stderr, "%s: Check 1.0 - fspace->hdr->tot_space = %Hu\n", FUNC, fspace->hdr->tot_space); +#endif /* QAK */ if(H5FS_sect_link_size(fspace, sect) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't add section to size tracking data structures") +#ifdef QAK +HDfprintf(stderr, "%s: Check 2.0 - fspace->hdr->tot_space = %Hu\n", FUNC, fspace->hdr->tot_space); +#endif /* QAK */ /* Update rest of free space manager data structures for section addition */ if(H5FS_sect_link_rest(f, dxpl_id, fspace, sect) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't add section to non-size tracking data structures") +#ifdef QAK +HDfprintf(stderr, "%s: Check 3.0 - fspace->hdr->tot_space = %Hu\n", FUNC, fspace->hdr->tot_space); +#endif /* QAK */ done: FUNC_LEAVE_NOAPI(ret_value) @@ -1205,7 +1194,7 @@ static herr_t H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t **sect, void *op_data) { - H5FS_section_info_t *tmp_sect_node; /* Temporary free space section */ + H5FS_section_class_t *sect_cls = NULL; /* Section's class */ hbool_t merged; /* Flag to indicate merge occurred */ htri_t status; /* Status value */ herr_t ret_value = SUCCEED; /* Return value */ @@ -1221,6 +1210,9 @@ H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, /* Loop until no more merging */ do { + H5FS_section_class_t *tmp_sect_cls; /* Temporary section's class */ + H5FS_section_info_t *tmp_sect_node; /* Temporary free space section */ + /* Reset 'merge occurred' flag */ merged = FALSE; @@ -1228,27 +1220,32 @@ H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, tmp_sect_node = H5SL_less(fspace->merge_list, &(*sect)->addr); /* Check for node before new node able to merge with new node */ - if(tmp_sect_node && tmp_sect_node->cls->can_merge) { - /* Determine if the sections can merge */ - if((status = (*tmp_sect_node->cls->can_merge)(tmp_sect_node, *sect, op_data)) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't check for merging sections") - if(status > 0) { - /* Sanity check */ - HDassert((*sect)->cls->merge); - - /* Remove 'less than' node from data structures */ - if(H5FS_sect_unlink(f, dxpl_id, fspace, tmp_sect_node) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures") - - /* Merge the two sections together */ - if((*tmp_sect_node->cls->merge)(tmp_sect_node, *sect, op_data) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't merge two sections") - - /* Retarget section pointer to 'less than' node that was merged into */ - *sect = tmp_sect_node; - - /* Indicate successful merge occurred */ - merged = TRUE; + if(tmp_sect_node) { + tmp_sect_cls = &fspace->sect_cls[tmp_sect_node->type]; /* Use class for left-most section */ + if(tmp_sect_cls->can_merge) { + /* Determine if the sections can merge */ + if((status = (*tmp_sect_cls->can_merge)(tmp_sect_node, *sect, op_data)) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't check for merging sections") + if(status > 0) { + /* Sanity check */ + HDassert(tmp_sect_cls->merge); + + /* Remove 'less than' node from data structures */ + if(H5FS_sect_unlink(f, dxpl_id, fspace, tmp_sect_node) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures") + + /* Merge the two sections together */ + /* (rescan the class of the node, the 'can merge' callback can change it) */ + tmp_sect_cls = &fspace->sect_cls[tmp_sect_node->type]; /* Use class for left-most section */ + if((*tmp_sect_cls->merge)(tmp_sect_node, *sect, op_data) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't merge two sections") + + /* Retarget section pointer to 'less than' node that was merged into */ + *sect = tmp_sect_node; + + /* Indicate successful merge occurred */ + merged = TRUE; + } /* end if */ } /* end if */ } /* end if */ @@ -1256,31 +1253,38 @@ H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, tmp_sect_node = H5SL_greater(fspace->merge_list, &(*sect)->addr); /* Check for node after new node able to merge with new node */ - if(tmp_sect_node && tmp_sect_node->cls->can_merge) { - /* Determine if the sections can merge */ - if((status = (*tmp_sect_node->cls->can_merge)(*sect, tmp_sect_node, op_data)) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't check for merging sections") - if(status > 0) { - /* Sanity check */ - HDassert((*sect)->cls->merge); - - /* Remove 'greater than' node from data structures */ - if(H5FS_sect_unlink(f, dxpl_id, fspace, tmp_sect_node) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures") - - /* Merge the two sections together */ - if((*(*sect)->cls->merge)(*sect, tmp_sect_node, op_data) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't merge two sections") - - /* Indicate successful merge occurred */ - merged = TRUE; + if(tmp_sect_node) { + tmp_sect_cls = &fspace->sect_cls[(*sect)->type]; /* Use class for left-most section */ + if(tmp_sect_cls->can_merge) { + /* Determine if the sections can merge */ + if((status = (*tmp_sect_cls->can_merge)(*sect, tmp_sect_node, op_data)) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't check for merging sections") + if(status > 0) { + /* Sanity check */ + HDassert(tmp_sect_cls->merge); + + /* Remove 'greater than' node from data structures */ + if(H5FS_sect_unlink(f, dxpl_id, fspace, tmp_sect_node) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures") + + /* Merge the two sections together */ + /* (rescan the class of the node, the 'can merge' callback can change it) */ + tmp_sect_cls = &fspace->sect_cls[(*sect)->type]; /* Use class for left-most section */ + if((*tmp_sect_cls->merge)(*sect, tmp_sect_node, op_data) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't merge two sections") + + /* Indicate successful merge occurred */ + merged = TRUE; + } /* end if */ } /* end if */ } /* end if */ } while(merged); + HDassert(*sect); /* Check for (possibly merged) section able to shrink the size of the container */ - if((*sect)->cls->can_shrink) { - if((status = (*(*sect)->cls->can_shrink)(*sect, op_data)) < 0) + sect_cls = &fspace->sect_cls[(*sect)->type]; + if(sect_cls->can_shrink) { + if((status = (*sect_cls->can_shrink)(*sect, op_data)) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTSHRINK, FAIL, "can't check for shrinking container") if(status > 0) { #ifdef QAK @@ -1288,7 +1292,10 @@ HDfprintf(stderr, "%s: Can shrink!\n", FUNC); #endif /* QAK */ /* Shrink the container */ /* (callback can indicate that it has discarded the section by setting *sect to NULL) */ - if((*(*sect)->cls->shrink)(sect, op_data) < 0) + /* (rescan the class of the node, the 'can shrink' callback can change it) */ + sect_cls = &fspace->sect_cls[(*sect)->type]; + HDassert(sect_cls->shrink); + if((*sect_cls->shrink)(sect, op_data) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't shrink free space container") } /* end if */ } /* end if */ @@ -1321,7 +1328,7 @@ H5FS_add(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *sect, FUNC_ENTER_NOAPI(H5FS_add, FAIL) #ifdef QAK -HDfprintf(stderr, "%s: sect->size = %Hu, sect->addr = %a, sect->cls->type = %u\n", FUNC, sect->size, sect->addr, sect->cls->type); +HDfprintf(stderr, "%s: sect->size = %Hu, sect->addr = %a, sect->type = %u\n", FUNC, sect->size, sect->addr, sect->type); #endif /* QAK */ /* Check arguments. */ @@ -1341,11 +1348,17 @@ HDfprintf(stderr, "%s: Returning space\n", FUNC); HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't merge sections") } /* end if */ - /* Add new (possibly merged or even discarded) node to free sections */ + /* Add new (possibly merged) node to free sections data structures */ + /* (If section has been completely merged away or discarded, 'sect' will + * be NULL at this point - QAK) + */ if(sect) if(H5FS_sect_link(f, dxpl_id, fspace, sect) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space section into skip list") +#ifdef QAK +HDfprintf(stderr, "%s: fspace->hdr->tot_space = %Hu\n", FUNC, fspace->hdr->tot_space); +#endif /* QAK */ /* Mark free space sections as changed */ /* (if we're not deserializing all the sections) */ if(!(flags & H5FS_ADD_DESERIALIZING)) @@ -1517,16 +1530,18 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5FS_sect_free_cb(void *_sect, void UNUSED *key, void UNUSED *op_data) +H5FS_sect_free_cb(void *_sect, void UNUSED *key, void *op_data) { - H5FS_section_info_t *sect = (H5FS_section_info_t *)_sect; + H5FS_section_info_t *sect = (H5FS_section_info_t *)_sect; /* Section to free */ + const H5FS_t *fspace = (const H5FS_t *)op_data; /* Free space manager for section */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_sect_free_cb) HDassert(sect); + HDassert(fspace); /* Call the 'free' method for the section's class */ - (*sect->cls->free)(sect); + (*fspace->sect_cls[sect->type].free)(sect); FUNC_LEAVE_NOAPI(0) } /* H5FS_sect_free_cb() */ @@ -1547,16 +1562,17 @@ H5FS_sect_free_cb(void *_sect, void UNUSED *key, void UNUSED *op_data) *------------------------------------------------------------------------- */ static herr_t -H5FS_node_free_cb(void *item, void UNUSED *key, void UNUSED *op_data) +H5FS_node_free_cb(void *item, void UNUSED *key, void *op_data) { H5FS_node_t *fspace_node = (H5FS_node_t *)item; /* Temporary pointer to free space list node */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_node_free_cb) HDassert(fspace_node); + HDassert(op_data); /* Release the skip list for sections of this size */ - H5SL_destroy(fspace_node->sect_list, H5FS_sect_free_cb, NULL); + H5SL_destroy(fspace_node->sect_list, H5FS_sect_free_cb, op_data); /* Release free space list node */ H5FL_FREE(H5FS_node_t, fspace_node); @@ -1583,39 +1599,41 @@ H5FS_node_free_cb(void *item, void UNUSED *key, void UNUSED *op_data) static herr_t H5FS_serialize_sect_cb(void *_item, void UNUSED *key, void *_udata) { - H5FS_section_info_t *sect_info = (H5FS_section_info_t *)_item; /* Free space section to work on */ + H5FS_section_class_t *sect_cls; /* Class of section */ + H5FS_section_info_t *sect= (H5FS_section_info_t *)_item; /* Free space section to work on */ H5FS_iter_ud2_t *udata = (H5FS_iter_ud2_t *)_udata; /* Callback info */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5FS_serialize_sect_cb) /* Check arguments. */ - HDassert(sect_info); + HDassert(sect); HDassert(udata->fspace); HDassert(udata->p); /* The address of the section */ - UINT64ENCODE_VAR(*udata->p, sect_info->addr, udata->fspace->sect_off_size); + UINT64ENCODE_VAR(*udata->p, sect->addr, udata->fspace->sect_off_size); #ifdef QAK -HDfprintf(stderr, "%s: sect_info->addr = %a\n", FUNC, sect_info->addr); +HDfprintf(stderr, "%s: sect->addr = %a\n", FUNC, sect->addr); #endif /* QAK */ /* The type of this section */ - *(*udata->p)++ = (uint8_t)sect_info->cls->type; + *(*udata->p)++ = (uint8_t)sect->type; #ifdef QAK -HDfprintf(stderr, "%s: sect_info->cls->type = %u\n", FUNC, (unsigned)sect_info->cls->type); +HDfprintf(stderr, "%s: sect->type = %u\n", FUNC, (unsigned)sect->type); #endif /* QAK */ /* Call 'serialize' callback for this section */ - if(sect_info->cls->serialize) { - if((*sect_info->cls->serialize)(sect_info, *udata->p) < 0) + sect_cls = &udata->fspace->sect_cls[sect->type]; + if(sect_cls->serialize) { + if((*sect_cls->serialize)(sect, *udata->p) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTSERIALIZE, FAIL, "can't syncronize section") /* Update offset in serialization buffer */ - (*udata->p) += sect_info->cls->serial_size; + (*udata->p) += sect_cls->serial_size; } /* end if */ else - HDassert(sect_info->cls->serial_size == 0); + HDassert(sect_cls->serial_size == 0); done: FUNC_LEAVE_NOAPI(ret_value) @@ -1765,7 +1783,10 @@ HDfprintf(stderr, "%s: fspace->serial_size = %Zu\n", FUNC, fspace->serial_size); /* Check for existing serialized sections on disk to release */ if(H5F_addr_defined(fspace->hdr->sect_addr)) { /* Free previous serialized sections disk space */ - if(H5MF_xfree(f, H5FD_MEM_FSPACE_SECTS, dxpl_id, fspace->hdr->sect_addr, (hsize_t)fspace->hdr->alloc_sect_size)<0) +#ifdef QAK +HDfprintf(stderr, "%s: Releasing space for serialized sections\n", FUNC); +#endif /* QAK */ + if(H5MF_xfree(f, H5FD_MEM_FSPACE_SECTS, dxpl_id, fspace->hdr->sect_addr, fspace->hdr->alloc_sect_size)<0) HGOTO_ERROR(H5E_STORAGE, H5E_CANTFREE, FAIL, "unable to release free space sections") /* Reset address and size of serialized sections on disk */ @@ -1780,6 +1801,9 @@ HDfprintf(stderr, "%s: fspace->serial_size = %Zu\n", FUNC, fspace->serial_size); fspace->hdr->alloc_sect_size = (size_t)fspace->hdr->sect_size * (double)fspace->hdr->expand_percent / 100.0; /* Allocate space for the new serialized sections on disk */ +#ifdef QAK +HDfprintf(stderr, "%s: Allocating space for serialized sections\n", FUNC); +#endif /* QAK */ if(HADDR_UNDEF == (fspace->hdr->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SECTS, dxpl_id, (hsize_t)fspace->hdr->alloc_sect_size))) HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections") } /* end if */ @@ -1800,7 +1824,7 @@ HDfprintf(stderr, "%s: fspace->hdr->alloc_sect_size = %Hu\n", FUNC, fspace->hdr- * QAK - 5/ 8/2006 */ /* Free previous serialized sections disk space */ - if(H5MF_xfree(f, H5FD_MEM_FSPACE_SECTS, dxpl_id, fspace->hdr->sect_addr, (hsize_t)fspace->hdr->alloc_sect_size)<0) + if(H5MF_xfree(f, H5FD_MEM_FSPACE_SECTS, dxpl_id, fspace->hdr->sect_addr, fspace->hdr->alloc_sect_size)<0) HGOTO_ERROR(H5E_STORAGE, H5E_CANTFREE, FAIL, "unable to free free space sections") /* Compute new size */ @@ -1810,6 +1834,9 @@ HDfprintf(stderr, "%s: fspace->hdr->alloc_sect_size = %Hu\n", FUNC, fspace->hdr- fspace->hdr->alloc_sect_size = new_size; /* Allocate space for the new serialized sections on disk */ +#ifdef QAK +HDfprintf(stderr, "%s: Allocating space for larger serialized sections, fspace->hdr->sect_size = %Hu\n", FUNC, fspace->hdr->sect_size); +#endif /* QAK */ if(HADDR_UNDEF == (fspace->hdr->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SECTS, dxpl_id, (hsize_t)fspace->hdr->alloc_sect_size))) HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections") } /* end if */ @@ -1836,7 +1863,7 @@ HDfprintf(stderr, "%s: fspace->hdr->alloc_sect_size = %Hu\n", FUNC, fspace->hdr- * QAK - 5/ 8/2006 */ /* Free previous serialized sections disk space */ - if(H5MF_xfree(f, H5FD_MEM_FSPACE_SECTS, dxpl_id, fspace->hdr->sect_addr, (hsize_t)fspace->hdr->alloc_sect_size)<0) + if(H5MF_xfree(f, H5FD_MEM_FSPACE_SECTS, dxpl_id, fspace->hdr->sect_addr, fspace->hdr->alloc_sect_size)<0) HGOTO_ERROR(H5E_STORAGE, H5E_CANTFREE, FAIL, "unable to free free space sections") /* Compute new size */ @@ -1850,6 +1877,9 @@ HDfprintf(stderr, "%s: fspace->hdr->alloc_sect_size = %Hu\n", FUNC, fspace->hdr- fspace->hdr->alloc_sect_size = new_size; /* Allocate space for the new serialized sections on disk */ +#ifdef QAK +HDfprintf(stderr, "%s: Allocating space for smaller serialized sections\n", FUNC); +#endif /* QAK */ if(HADDR_UNDEF == (fspace->hdr->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SECTS, dxpl_id, (hsize_t)fspace->hdr->alloc_sect_size))) HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections") } /* end if */ @@ -1900,6 +1930,9 @@ HDfprintf(stderr, "%s: Serializing single section\n", FUNC); /* The size of the section */ UINT64ENCODE_VAR(p, fspace->single->size, fspace->sect_len_size); +#ifdef QAK +HDfprintf(stderr, "%s: fspace->single->size = %Hu\n", FUNC, fspace->single->size); +#endif /* QAK */ /* Serialize the single node */ if(H5FS_serialize_sect_cb(fspace->single, NULL, &udata) < 0) @@ -2020,8 +2053,9 @@ HDfprintf(stderr, "%s: fspace->hdr->sect_size = %Hu\n", FUNC, fspace->hdr->sect_ /* Check for any serialized sections */ if(fspace->hdr->sect_count > 0) { - hsize_t old_sect_count; /* Section count from header */ - unsigned sect_cnt_size; /* The size of the section size counts */ + hsize_t old_sect_count; /* Section count from header */ + hsize_t old_tot_space; /* Total space managed from header */ + unsigned sect_cnt_size; /* The size of the section size counts */ /* Compute the size of the section counts */ sect_cnt_size = MAX(1, (H5V_log2_gen(fspace->hdr->sect_count) + 7) / 8); @@ -2032,10 +2066,13 @@ HDfprintf(stderr, "%s: fspace->sect_len_size = %u\n", FUNC, fspace->sect_len_siz /* Reset the section count, the "add" routine will update it */ old_sect_count = fspace->hdr->sect_count; + old_tot_space = fspace->hdr->tot_space; #ifdef QAK HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect_count); +HDfprintf(stderr, "%s: fspace->hdr->tot_space = %Hu\n", FUNC, fspace->hdr->tot_space); #endif /* QAK */ fspace->hdr->sect_count = 0; + fspace->hdr->tot_space = 0; /* Walk through the buffer, deserializing sections */ do { @@ -2077,12 +2114,11 @@ HDfprintf(stderr, "%s: sect_type = %u\n", FUNC, sect_type); /* Call 'deserialize' callback for this section */ HDassert(fspace->sect_cls[sect_type].deserialize); - if((*fspace->sect_cls[sect_type].deserialize)(fspace->sect_cls, p, sect_addr, sect_size, &new_sect) < 0) + if(NULL == (new_sect = (*fspace->sect_cls[sect_type].deserialize)(p, sect_addr, sect_size))) HGOTO_ERROR(H5E_FSPACE, H5E_CANTDECODE, FAIL, "can't deserialize section") - HDassert(new_sect); /* Update offset in serialization buffer */ - p += new_sect->cls->serial_size; + p += fspace->sect_cls[sect_type].serial_size; /* Insert section in free space manager */ if(H5FS_add(f, dxpl_id, fspace, new_sect, H5FS_ADD_DESERIALIZING, NULL) < 0) @@ -2094,6 +2130,7 @@ HDfprintf(stderr, "%s: sect_type = %u\n", FUNC, sect_type); HDassert((size_t)(p - sect_buf) == old_sect_size); HDassert(old_sect_size == fspace->hdr->sect_size); HDassert(old_sect_count == fspace->hdr->sect_count); + HDassert(old_tot_space == fspace->hdr->tot_space); } /* end if */ done: @@ -2254,6 +2291,39 @@ done: /*------------------------------------------------------------------------- + * Function: H5FS_get_sect_count + * + * Purpose: Retrieve the number of sections managed + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Tuesday, May 30, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FS_get_sect_count(const H5FS_t *fspace, hsize_t *nsects) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FS_get_sect_count, FAIL) + + /* Check arguments. */ + HDassert(fspace); + HDassert(nsects); + + /* Get the section count */ + *nsects = fspace->hdr->sect_count; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_get_sect_count() */ + + +/*------------------------------------------------------------------------- * Function: H5FS_flush_cb * * Purpose: Skip list iterator callback to syncronize free space sections @@ -2333,6 +2403,64 @@ done: /*------------------------------------------------------------------------- + * Function: H5FS_delete + * + * Purpose: Delete a free space manager on disk + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Tuesday, May 30, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FS_delete(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr) +{ + H5FS_hdr_t *fs_hdr = NULL; /* Free space header loaded from file */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FS_delete, FAIL) +#ifdef QAK +HDfprintf(stderr, "%s: Deleting free space manager\n", FUNC); +#endif /* QAK */ + + /* Check arguments. */ + HDassert(f); + HDassert(H5F_addr_defined(fs_addr)); + + /* Protect the free space header */ + if(NULL == (fs_hdr = H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, NULL, NULL, H5AC_WRITE))) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, FAIL, "unable to protect free space header") + + /* Delete serialized section storage, if there are any */ +#ifdef QAK +HDfprintf(stderr, "%s: fs_hdr->sect_addr = %a\n", FUNC, fs_hdr->sect_addr); +#endif /* QAK */ + if(fs_hdr->sect_count > 0) { + HDassert(H5F_addr_defined(fs_hdr->sect_addr)); + HDassert(fs_hdr->sect_size > 0); + if(H5MF_xfree(f, H5FD_MEM_FSPACE_SECTS, dxpl_id, fs_hdr->sect_addr, fs_hdr->alloc_sect_size)<0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to release free space sections") + } /* end if */ + + /* Release header's disk space */ + if(H5MF_xfree(f, H5FD_MEM_FSPACE_HDR, dxpl_id, fs_addr, (hsize_t)H5FS_HEADER_SIZE(f))<0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to release free space header") + + /* Release the free space header */ + if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, fs_hdr, H5AC__DELETED_FLAG) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPROTECT, FAIL, "unable to release free space header") + fs_hdr = NULL; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_delete() */ + + +/*------------------------------------------------------------------------- * Function: H5FS_close * * Purpose: Destroy & deallocate free list structure, serializing sections @@ -2370,7 +2498,8 @@ H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace) /* Check for single section to free */ if(fspace->single) { - fspace->single->cls->free(fspace->single); + /* Call the 'free' callback for the section */ + (*fspace->sect_cls[fspace->single->type].free)(fspace->single); fspace->single = NULL; } /* end if */ HDassert(fspace->single == NULL); @@ -2380,7 +2509,7 @@ H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace) /* Clear out lists of nodes */ for(u = 0; u < fspace->nbins; u++) if(fspace->bins[u].bin_list) { - H5SL_destroy(fspace->bins[u].bin_list, H5FS_node_free_cb, NULL); + H5SL_destroy(fspace->bins[u].bin_list, H5FS_node_free_cb, fspace); fspace->bins[u].bin_list = NULL; } /* end if */ @@ -2388,15 +2517,17 @@ H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace) } /* end if */ /* Release skip list for merging sections */ - if(fspace->merge_list) { + if(fspace->merge_list) if(H5SL_close(fspace->merge_list) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTCLOSEOBJ, FAIL, "can't destroy section merging skip list") - } /* end if */ /* Unpin the free space header in the cache */ if(H5AC_unpin_entry(f, fspace->hdr) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin free space header") + /* Release the memory for the free space section classes */ + fspace->sect_cls = H5FL_SEQ_FREE(H5FS_section_class_t, fspace->sect_cls); + /* Free free space info */ H5FL_FREE(H5FS_t, fspace); diff --git a/src/H5FSdbg.c b/src/H5FSdbg.c index dcbc846..a946cf0 100644 --- a/src/H5FSdbg.c +++ b/src/H5FSdbg.c @@ -158,6 +158,45 @@ done: /*------------------------------------------------------------------------- + * Function: H5FS_sect_debug + * + * Purpose: Prints debugging info about a free space section. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 30 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FS_sect_debug(const H5FS_t *fspace, const H5FS_section_info_t *sect, FILE *stream, int indent, int fwidth) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FS_sect_debug, FAIL) + + /* + * Check arguments. + */ + HDassert(fspace); + HDassert(sect); + HDassert(stream); + HDassert(indent >= 0); + HDassert(fwidth >= 0); + + /* Call the section's debugging routine */ + if(fspace->sect_cls[sect->type].debug) + if((fspace->sect_cls[sect->type].debug)(sect, stream, indent, fwidth) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_BADITER, FAIL, "can't dump section's debugging info") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FS_sect_debug() */ + + +/*------------------------------------------------------------------------- * Function: H5FS_sects_debug * * Purpose: Prints debugging info about the free space sections. diff --git a/src/H5FSpkg.h b/src/H5FSpkg.h index 98a945e..0f9aaad 100644 --- a/src/H5FSpkg.h +++ b/src/H5FSpkg.h @@ -98,6 +98,34 @@ typedef struct H5FS_hdr_t { hsize_t alloc_sect_size; /* Allocated size of the section info in the file */ } H5FS_hdr_t; +/* Free space section bin info */ +typedef struct H5FS_bin_t { + size_t sect_count; /* Total # of sections in this bin */ + H5SL_t *bin_list; /* Skip list of differently sized sections */ +} H5FS_bin_t; + +/* Main free space info */ +struct H5FS_t { + /* Stored values (from header) */ + H5FS_hdr_t *hdr; /* Pointer to header info */ + + /* Computed/cached values */ + haddr_t addr; /* Address of free space header on disk */ + unsigned nbins; /* Number of bins */ + size_t serial_size; /* Total serialized size of all section nodes */ + size_t size_count; /* Number of differently sized sections */ + unsigned sect_prefix_size; /* Size of the section serialization prefix (in bytes) */ + unsigned sect_off_size; /* Size of a section offset (in bytes) */ + unsigned sect_len_size; /* Size of a section length (in bytes) */ + hbool_t dirty; /* Space information is dirty */ + + /* Memory data structures (not stored directly) */ + H5FS_section_class_t *sect_cls; /* Array of section classes for this free list */ + H5FS_section_info_t *single; /* Section information when free list has only one free section */ + H5SL_t *merge_list; /* Skip list to hold sections for detecting merges */ + H5FS_bin_t *bins; /* Array of lists of lists of free sections */ +}; + /*****************************/ /* Package Private Variables */ diff --git a/src/H5FSprivate.h b/src/H5FSprivate.h index 3b9311b..281bb57 100644 --- a/src/H5FSprivate.h +++ b/src/H5FSprivate.h @@ -54,7 +54,7 @@ /* Library Private Typedefs */ /****************************/ -/* Free space info (forward decl - defined in H5FS.c) */ +/* Free space info (forward decl - defined in H5FSpkg.h) */ typedef struct H5FS_t H5FS_t; /* Forward declaration free space section info */ @@ -71,28 +71,27 @@ typedef struct H5FS_section_class_t { /* Object methods */ herr_t (*serialize)(const H5FS_section_info_t *, uint8_t *); /* Routine to serialize a "live" section into a buffer */ - herr_t (*deserialize)(struct H5FS_section_class_t *cls, const uint8_t *, - haddr_t, hsize_t, H5FS_section_info_t **); /* Routine to deserialize a buffer into a "live" section */ - htri_t (*can_merge)(const H5FS_section_info_t *, const H5FS_section_info_t *, - void *); /* Routine to determine if two nodes are mergable */ + H5FS_section_info_t *(*deserialize)(const uint8_t *, haddr_t, hsize_t); /* Routine to deserialize a buffer into a "live" section */ + htri_t (*can_merge)(H5FS_section_info_t *, H5FS_section_info_t *, void *); /* Routine to determine if two nodes are mergable */ herr_t (*merge)(H5FS_section_info_t *, H5FS_section_info_t *, void *); /* Routine to merge two nodes */ - htri_t (*can_shrink)(H5FS_section_info_t *, void *); /* Routine to determine if node can shrink container */ + htri_t (*can_shrink)(H5FS_section_info_t *, void *); /* Routine to determine if node can shrink container */ herr_t (*shrink)(H5FS_section_info_t **, void *); /* Routine to shrink container */ - herr_t (*free)(H5FS_section_info_t *); /* Routine to free node */ - herr_t (*debug)(const H5FS_section_info_t *, FILE *, - int , int ); /* Routine to dump debugging information about a section */ + herr_t (*free)(H5FS_section_info_t *); /* Routine to free node */ + herr_t (*debug)(const H5FS_section_info_t *, FILE *, int , int ); /* Routine to dump debugging information about a section */ } H5FS_section_class_t; +/* State of section ("live" or "serialized") */ +typedef enum H5FS_section_state_t { + H5FS_SECT_LIVE, /* Section has "live" memory references */ + H5FS_SECT_SERIALIZED /* Section is in "serialized" form */ +} H5FS_section_state_t; + /* Free space section info */ struct H5FS_section_info_t { - haddr_t addr; /* Address of free space section in the address space */ - /* (Not actually used as address, used as unique ID for free space node) */ - hsize_t size; /* Size of free space section */ - H5FS_section_class_t *cls; /* Class of free space section */ - enum { - H5FS_SECT_LIVE, /* Section has "live" memory references */ - H5FS_SECT_SERIALIZED} /* Section is in "serialized" form */ - state; /* Whether the section is in "serialized" or "live" form */ + haddr_t addr; /* Address of free space section in the address space */ + hsize_t size; /* Size of free space section */ + unsigned type; /* Type of free space section (i.e. class) */ + H5FS_section_state_t state; /* Whether the section is in "serialized" or "live" form */ }; /* Free space client IDs for identifying user of free space */ @@ -128,16 +127,22 @@ H5FL_SEQ_EXTERN(H5FS_section_class_t); /***************************************/ H5_DLL H5FS_t *H5FS_create(H5F_t *f, hid_t dxpl_id, haddr_t *fs_addr, const H5FS_create_t *fs_create, size_t nclasses, - H5FS_section_class_t *classes, const void *cls_init_udata); + const H5FS_section_class_t *classes[], const void *cls_init_udata); H5_DLL H5FS_t *H5FS_open(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr, - size_t nclasses, H5FS_section_class_t *classes, const void *cls_init_udata); + size_t nclasses, const H5FS_section_class_t *classes[], const void *cls_init_udata); H5_DLL herr_t H5FS_add(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *node, unsigned flags, void *op_data); H5_DLL htri_t H5FS_find(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, hsize_t request, H5FS_section_info_t **node); H5_DLL herr_t H5FS_iterate(H5FS_t *fspace, H5FS_operator_t op, void *op_data); +H5_DLL herr_t H5FS_get_sect_count(const H5FS_t *fspace, hsize_t *nsects); H5_DLL herr_t H5FS_flush(H5F_t *f, hid_t dxpl_id, unsigned flags); +H5_DLL herr_t H5FS_delete(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr); H5_DLL herr_t H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace); +/* Debugging routines for dumping file structures */ +H5_DLL herr_t H5FS_sect_debug(const H5FS_t *fspace, const H5FS_section_info_t *sect, + FILE *stream, int indent, int fwidth); + #endif /* _H5FSprivate_H */ @@ -568,10 +568,20 @@ H5HF_close(H5HF_t *fh, hid_t dxpl_id) HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't remove group from list of open objects") /* 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 */ + /* (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_reset(&fh->hdr->next_block) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't reset block iterator") diff --git a/src/H5HFcache.c b/src/H5HFcache.c index 8b59876..d896a3e 100644 --- a/src/H5HFcache.c +++ b/src/H5HFcache.c @@ -328,6 +328,7 @@ HDfprintf(stderr, "%s: Load heap header, addr = %a\n", FUNC, addr); H5F_DECODE_LENGTH(f, p, hdr->total_size); H5F_DECODE_LENGTH(f, p, hdr->man_size); H5F_DECODE_LENGTH(f, p, hdr->man_alloc_size); + H5F_DECODE_LENGTH(f, p, hdr->man_iter_off); H5F_DECODE_LENGTH(f, p, hdr->std_size); H5F_DECODE_LENGTH(f, p, hdr->nobjs); @@ -435,6 +436,7 @@ HDfprintf(stderr, "%s: Flushing heap header, addr = %a, destroy = %u\n", FUNC, a H5F_ENCODE_LENGTH(f, p, hdr->total_size); H5F_ENCODE_LENGTH(f, p, hdr->man_size); H5F_ENCODE_LENGTH(f, p, hdr->man_alloc_size); + H5F_ENCODE_LENGTH(f, p, hdr->man_iter_off); H5F_ENCODE_LENGTH(f, p, hdr->std_size); H5F_ENCODE_LENGTH(f, p, hdr->nobjs); @@ -917,7 +919,7 @@ HDfprintf(stderr, "%s: Load indirect block, addr = %a\n", FUNC, addr); iblock->rc = 0; iblock->nrows = *nrows; iblock->addr = addr; - iblock->dirty = FALSE; + iblock->nchildren = 0; /* Compute size of indirect block */ iblock->size = H5HF_MAN_INDIRECT_SIZE(iblock->hdr, iblock); @@ -985,6 +987,12 @@ HDfprintf(stderr, "%s: Load indirect block, addr = %a\n", FUNC, addr); /* Decode child block address */ H5F_addr_decode(f, &p, &(iblock->ents[u].addr)); + /* Count child blocks */ + if(H5F_addr_defined(iblock->ents[u].addr)) { + iblock->nchildren++; + iblock->max_child = u; + } /* end if */ + #ifdef LATER /* Decode direct & indirect blocks differently (later, when direct blocks can be compressed) */ if(u < (iblock->hdr->man_dtable.max_direct_rows * iblock->hdr->man_dtable.cparam.width)) @@ -995,8 +1003,9 @@ HDfprintf(stderr, "%s: iblock->ents[%Zu] = {%a}\n", FUNC, u, iblock->ents[u].add #endif /* QAK */ } /* end for */ - /* Sanity check */ + /* Sanity checks */ HDassert((size_t)(p - buf) == iblock->size); + HDassert(iblock->nchildren); /* indirect blocks w/no children should have been deleted */ /* Set return value */ ret_value = iblock; @@ -1042,13 +1051,14 @@ HDfprintf(stderr, "%s: Flushing indirect block, addr = %a, destroy = %u\n", FUNC HDassert(iblock); if(iblock->cache_info.is_dirty) { - H5HF_hdr_t *hdr; /* Shared fractal heap information */ - uint8_t *buf = NULL; /* Temporary buffer */ - uint8_t *p; /* Pointer into raw data buffer */ - size_t u; /* Local index variable */ - - /* Sanity check */ - HDassert(iblock->dirty); + H5HF_hdr_t *hdr; /* Shared fractal heap information */ + uint8_t *buf = NULL; /* Temporary buffer */ + uint8_t *p; /* Pointer into raw data buffer */ +#ifndef NDEBUG + unsigned nchildren = 0; /* Track # of children */ + unsigned max_child = 0; /* Track max. child entry used */ +#endif /* NDEBUG */ + size_t u; /* Local index variable */ /* Get the pointer to the shared heap header */ hdr = iblock->hdr; @@ -1096,6 +1106,15 @@ HDfprintf(stderr, "%s: iblock->ents[%Zu] = {%a}\n", FUNC, u, iblock->ents[u].add /* Encode child block address */ H5F_addr_encode(f, &p, iblock->ents[u].addr); +#ifndef NDEBUG + /* Count child blocks */ + if(H5F_addr_defined(iblock->ents[u].addr)) { + nchildren++; + if(u > max_child) + max_child = u; + } /* end if */ +#endif /* NDEBUG */ + #ifdef LATER /* Encode direct & indirect blocks differently (when direct blocks can be compressed) */ if(u < (hdr->man_dtable.max_direct_rows * hdr->man_dtable.cparam.width)) @@ -1105,6 +1124,10 @@ HDfprintf(stderr, "%s: iblock->ents[%Zu] = {%a}\n", FUNC, u, iblock->ents[u].add /* Sanity check */ HDassert((size_t)(p - buf) == iblock->size); +#ifndef NDEBUG + HDassert(nchildren == iblock->nchildren); + HDassert(max_child == iblock->max_child); +#endif /* NDEBUG */ /* Write the indirect block */ if(H5F_block_write(f, H5FD_MEM_FHEAP_IBLOCK, addr, iblock->size, dxpl_id, buf) < 0) @@ -1114,7 +1137,6 @@ HDfprintf(stderr, "%s: iblock->ents[%Zu] = {%a}\n", FUNC, u, iblock->ents[u].add H5FL_BLK_FREE(indirect_block, buf); /* Reset dirty flags */ - iblock->dirty = FALSE; iblock->cache_info.is_dirty = FALSE; } /* end if */ @@ -1153,9 +1175,8 @@ H5HF_cache_iblock_dest(H5F_t UNUSED *f, H5HF_indirect_t *iblock) */ HDassert(iblock); HDassert(iblock->rc == 0); - HDassert(!iblock->dirty); #ifdef QAK -HDfprintf(stderr, "%s: Destroying indirect block\n", "H5HF_cache_iblock_dest"); +HDfprintf(stderr, "%s: Destroying indirect block\n", FUNC); #endif /* QAK */ /* Decrement reference count on shared info */ diff --git a/src/H5HFdbg.c b/src/H5HFdbg.c index 81faf1e..c8945fd 100644 --- a/src/H5HFdbg.c +++ b/src/H5HFdbg.c @@ -63,6 +63,7 @@ typedef struct { /* User data for free space section iterator callback */ typedef struct { + H5FS_t *fspace; /* Free space manager */ FILE *stream; /* Stream for output */ int indent; /* Indention amount */ int fwidth; /* Field width mount */ @@ -232,9 +233,12 @@ H5HF_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, "Total managed space data block size:", hdr->man_size); HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, - "Total managed space allocated data block size:", + "Total managed space allocated:", hdr->man_alloc_size); HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, + "Offset of managed space iterator:", + hdr->man_iter_off); + HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, "Total standalone space data block size:", hdr->std_size); HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, @@ -628,17 +632,16 @@ H5HF_sects_debug_cb(const H5FS_section_info_t *_sect, void *_udata) sect->sect_info.size); HDfprintf(udata->stream, "%*s%-*s %s\n", udata->indent, "", udata->fwidth, "Section type:", - (sect->sect_info.cls->type == H5FS_SECT_FHEAP_SINGLE ? "single" : - (sect->sect_info.cls->type == H5FS_SECT_FHEAP_RANGE ? "range" : - (sect->sect_info.cls->type == H5FS_SECT_FHEAP_INDIRECT ? "indirect" : "unknown")))); + (sect->sect_info.type == H5HF_FSPACE_SECT_SINGLE ? "single" : + (sect->sect_info.type == H5HF_FSPACE_SECT_RANGE ? "range" : + (sect->sect_info.type == H5HF_FSPACE_SECT_INDIRECT ? "indirect" : "unknown")))); HDfprintf(udata->stream, "%*s%-*s %s\n", udata->indent, "", udata->fwidth, "Section state:", (sect->sect_info.state == H5FS_SECT_LIVE ? "live" : "serialized")); - /* Call the section's debugging routine */ - if(sect->sect_info.cls->debug) - if((sect->sect_info.cls->debug)(_sect, udata->stream, udata->indent + 3, MAX(0, udata->fwidth - 3)) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't dump section's debugging info") + /* Dump section-specific debugging information */ + if(H5FS_sect_debug(udata->fspace, _sect, udata->stream, udata->indent + 3, MAX(0, udata->fwidth - 3)) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't dump section's debugging info") done: FUNC_LEAVE_NOAPI(ret_value) @@ -688,6 +691,7 @@ H5HF_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr, HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize heap free space") /* Prepare user data for section iteration callback */ + udata.fspace = hdr->fspace; udata.stream = stream; udata.indent = indent; udata.fwidth = fwidth; diff --git a/src/H5HFdblock.c b/src/H5HFdblock.c index 88c4e90..a4f1815 100644 --- a/src/H5HFdblock.c +++ b/src/H5HFdblock.c @@ -92,8 +92,7 @@ H5FL_DEFINE(H5HF_direct_t); */ herr_t H5HF_man_dblock_create(hid_t dxpl_id, H5HF_hdr_t *hdr, H5HF_indirect_t *par_iblock, - unsigned par_entry, size_t block_size, hsize_t block_off, haddr_t *addr_p, - H5HF_free_section_t **ret_sec_node) + unsigned par_entry, haddr_t *addr_p, H5HF_free_section_t **ret_sec_node) { H5HF_free_section_t *sec_node; /* Pointer to free space section for block */ H5HF_direct_t *dblock = NULL; /* Pointer to direct block */ @@ -106,7 +105,6 @@ H5HF_man_dblock_create(hid_t dxpl_id, H5HF_hdr_t *hdr, H5HF_indirect_t *par_iblo * Check arguments. */ HDassert(hdr); - HDassert(block_size > 0); HDassert(addr_p); /* @@ -124,49 +122,49 @@ H5HF_man_dblock_create(hid_t dxpl_id, H5HF_hdr_t *hdr, H5HF_indirect_t *par_iblo HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared heap header") /* Set info for direct block */ -#ifdef QAK -HDfprintf(stderr, "%s: size = %Zu, block_off = %Hu\n", FUNC, block_size, block_off); -#endif /* QAK */ - dblock->parent = par_iblock; - if(dblock->parent) { - if(H5HF_iblock_incr(par_iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") + if(par_iblock) { + unsigned par_row = par_entry / hdr->man_dtable.cparam.width; /* Row for block */ + + /* Compute offset & size, based on parent's information */ + dblock->block_off = par_iblock->block_off; + dblock->block_off += hdr->man_dtable.row_block_off[par_row]; + dblock->block_off += hdr->man_dtable.row_block_size[par_row] * (par_entry % hdr->man_dtable.cparam.width); + dblock->size = hdr->man_dtable.row_block_size[par_row]; } /* end if */ - dblock->par_entry = par_entry; - dblock->size = block_size; - dblock->block_off = block_off; - dblock->blk_off_size = H5HF_SIZEOF_OFFSET_LEN(block_size); - free_space = block_size - H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr); + else { + /* Must be the root direct block */ + dblock->block_off = 0; + dblock->size = hdr->man_dtable.cparam.start_block_size; + } /* end else */ + dblock->blk_off_size = H5HF_SIZEOF_OFFSET_LEN(dblock->size); + free_space = dblock->size - H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr); /* Allocate buffer for block */ /* XXX: Change to using free-list factories */ - if((dblock->blk = H5FL_BLK_MALLOC(direct_block, block_size)) == NULL) + if((dblock->blk = H5FL_BLK_MALLOC(direct_block, dblock->size)) == NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") #ifdef H5_USING_PURIFY HDmemset(dblock->blk, 0, dblock->size); #endif /* H5_USING_PURIFY */ /* Allocate space for the header on disk */ - if(HADDR_UNDEF == (*addr_p = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)block_size))) + if(HADDR_UNDEF == (*addr_p = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)dblock->size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block") +#ifdef QAK +HDfprintf(stderr, "%s: direct block address = %a\n", FUNC, *addr_p); +#endif /* QAK */ - /* Create free space section node */ - if(NULL == (sec_node = H5FL_MALLOC(H5HF_free_section_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") - - /* Set section's information */ - sec_node->sect_info.addr = block_off + H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr); - sec_node->sect_info.size = free_space; - sec_node->sect_info.cls = &hdr->sect_cls[H5FS_SECT_FHEAP_SINGLE]; - sec_node->sect_info.state = H5FS_SECT_LIVE; - sec_node->u.single.parent = dblock->parent; - if(dblock->parent) { - if(H5HF_iblock_incr(dblock->parent) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") - } /* end if */ - sec_node->u.single.par_entry = dblock->par_entry; - sec_node->u.single.dblock_addr = *addr_p; - sec_node->u.single.dblock_size = block_size; + /* Attach to parent indirect block, if there is one */ + dblock->parent = par_iblock; + if(dblock->parent) + if(H5HF_man_iblock_attach(dblock->parent, par_entry, *addr_p) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTATTACH, FAIL, "can't attach direct block to parent indirect block") + dblock->par_entry = par_entry; + + /* Create a new 'single' section for the free space in the block */ + if(NULL == (sec_node = H5HF_sect_single_new((dblock->block_off + H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr)), + free_space, dblock->parent, dblock->par_entry, *addr_p, dblock->size))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create section for new direct block's free space") /* Check what to do with section node */ if(ret_sec_node) @@ -182,6 +180,10 @@ HDmemset(dblock->blk, 0, dblock->size); if(H5AC_set(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, *addr_p, dblock, H5AC__NO_FLAGS_SET) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add fractal heap direct block to cache") + /* Increase the allocated heap size */ + if(H5HF_hdr_inc_alloc(hdr, dblock->size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't increase allocated heap size") + done: if(ret_value < 0) if(dblock) @@ -196,6 +198,10 @@ done: * * Purpose: Destroy a managed direct block * + * Note: This routine does _not_ insert a range section for the + * destroyed direct block, that must be handled by the + * caller. + * * Return: SUCCEED/FAIL * * Programmer: Quincey Koziol @@ -230,6 +236,10 @@ HDfprintf(stderr, "%s: root direct block\n", FUNC); /* Sanity check block iterator */ HDassert(!H5HF_man_iter_ready(&hdr->next_block)); + /* Reset root pointer information */ + hdr->man_dtable.curr_root_rows = 0; + hdr->man_dtable.table_addr = HADDR_UNDEF; + /* Reset header information back to "empty heap" state */ if(H5HF_hdr_empty(hdr) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't make heap empty") @@ -239,21 +249,51 @@ HDfprintf(stderr, "%s: root direct block\n", FUNC); HDfprintf(stderr, "%s: root indirect block\n", FUNC); #endif /* QAK */ -/* Remove from parent indirect block */ + /* Detach from parent indirect block */ + if(H5HF_man_iblock_detach(dblock->parent, dxpl_id, dblock->par_entry) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTATTACH, FAIL, "can't detach from parent indirect block") + dblock->parent = NULL; + dblock->par_entry = 0; -/* If this is the last block in the heap, move block iterator backwards */ + /* Adjust heap statistics */ + hdr->man_alloc_size -= dblock->size; -/* Detect the last direct block (of the starting block size) and make it the root direct block */ - -HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "destroying non-root direct block not supported yet") +#ifdef QAK +HDfprintf(stderr, "%s: dblock->block_off = %Hu\n", FUNC, dblock->block_off); +HDfprintf(stderr, "%s: hdr->man_iter_off = %Hu\n", FUNC, hdr->man_iter_off); +#endif /* QAK */ + /* Check for this direct block being the highest in the heap */ + if((dblock->block_off + dblock->size) == hdr->man_iter_off) { + /* Move 'next block' iterator backwards (may shrink heap) */ + if(H5HF_hdr_reverse_iter(hdr, dxpl_id) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't reverse 'next block' iterator") + } /* end if */ +#if 0 + else { + unsigned par_row, par_col; /* Row & column in parent indirect block */ + + /* Compute row & column in parent indirect block */ + par_row = dblock->par_entry / hdr->man_dtable.cparam.width; + par_col = dblock->par_entry % hdr->man_dtable.cparam.width; + + /* Add a 'range' section for the space in the destroyed block */ + if(H5HF_sect_range_add(hdr, dxpl_id, dblock->block_off, hdr->man_dtable.row_dblock_free[par_row], + dblock->parent, par_row, par_col, 1) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "can't create range section for direct block being destroyed") + } /* end else */ +#endif /* 0 */ } /* end else */ /* Release direct block's disk space */ +#ifdef QAK +HDfprintf(stderr, "%s: Before releasing direct block's space, dblock_addr = %a\n", FUNC, dblock_addr); +#endif /* QAK */ if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, dblock_addr, (hsize_t)dblock->size)<0) HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block") /* Remove direct block from metadata cache */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__DELETED_FLAG) < 0) + /* (direct block "destroy" callback will be called by cache) */ + if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block") dblock = NULL; @@ -277,11 +317,10 @@ done: *------------------------------------------------------------------------- */ herr_t -H5HF_man_dblock_new(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t request) +H5HF_man_dblock_new(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t request, + H5HF_free_section_t **ret_sec_node) { haddr_t dblock_addr; /* Address of new direct block */ - hsize_t dblock_off; /* Direct block offset in heap address space */ - size_t dblock_size; /* Size of new direct block */ size_t min_dblock_size; /* Min. size of direct block to allocate */ herr_t ret_value = SUCCEED; /* Return value */ @@ -319,13 +358,11 @@ HDfprintf(stderr, "%s: Check 2 - min_dblock_size = %Zu\n", FUNC, min_dblock_size if(!H5F_addr_defined(hdr->man_dtable.table_addr) && min_dblock_size == hdr->man_dtable.cparam.start_block_size) { /* Create new direct block at starting offset */ - dblock_size = hdr->man_dtable.cparam.start_block_size; - dblock_off = 0; - if(H5HF_man_dblock_create(dxpl_id, hdr, NULL, 0, dblock_size, dblock_off, &dblock_addr, NULL) < 0) + if(H5HF_man_dblock_create(dxpl_id, hdr, NULL, 0, &dblock_addr, ret_sec_node) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block") #ifdef QAK -HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr); +HDfprintf(stderr, "%s: root direct block, dblock_addr = %a\n", FUNC, dblock_addr); #endif /* QAK */ /* Point root at new direct block */ @@ -333,49 +370,50 @@ HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr); hdr->man_dtable.table_addr = dblock_addr; /* Extend heap to cover new direct block */ - if(H5HF_hdr_extend_heap(hdr, (hsize_t)dblock_size, hdr->man_dtable.row_dblock_free[0]) < 0) + if(H5HF_hdr_adjust_heap(hdr, (hsize_t)hdr->man_dtable.cparam.start_block_size, (hssize_t)hdr->man_dtable.row_dblock_free[0]) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "can't increase space to cover root direct block") } /* end if */ - /* Root entry already exists, go get indirect block for new direct block */ + /* Root entry already exists, allocate direct block from root indirect block */ else { H5HF_indirect_t *iblock; /* Pointer to indirect block to create */ - size_t dblock_entry; /* Direct entry for new direct block */ + unsigned next_row; /* Iterator's next block row */ + unsigned next_entry; /* Iterator's next block entry */ + size_t next_size; /* Size of next direct block to create */ + + /* Update iterator to reflect any previous increments as well as allow for requested direct block size */ + if(H5HF_hdr_update_iter(hdr, dxpl_id, min_dblock_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTUPDATE, FAIL, "unable to update block iterator") + + /* Retrieve information about current iterator position */ + if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL, &next_entry, &iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to retrieve current block iterator location") + HDassert(next_row < iblock->nrows); + next_size = hdr->man_dtable.row_block_size[next_row]; + + /* Check for skipping over blocks */ + if(min_dblock_size > next_size) { +HDfprintf(stderr, "%s: Skipping direct block sizes not supported, min_dblock_size = %Zu, next_size = %Zu\n", FUNC, min_dblock_size, next_size); +HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "skipping direct block sizes not supported yet") + } /* end if */ + + /* Advance "next block" iterator to next direct block entry */ + if(H5HF_hdr_inc_iter(hdr, (hsize_t)next_size, 1) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment 'next block' iterator") - /* Find indirect block with room for block of correct size */ - if(NULL == (iblock = H5HF_man_iblock_place_dblock(hdr, dxpl_id, min_dblock_size, &dblock_entry, &dblock_size))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to locate indirect block with space for direct block") #ifdef QAK HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock); HDfprintf(stderr, "%s: iblock->addr = %a\n", FUNC, iblock->addr); -HDfprintf(stderr, "%s: dblock_entry = %Zu\n", FUNC, dblock_entry); -HDfprintf(stderr, "%s: dblock_size = %Zu\n", FUNC, dblock_size); +HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry); #endif /* QAK */ - /* Compute the direct block's offset in the heap's address space */ - dblock_off = iblock->block_off; - dblock_off += hdr->man_dtable.row_block_off[dblock_entry / hdr->man_dtable.cparam.width]; - dblock_off += hdr->man_dtable.row_block_size[dblock_entry / hdr->man_dtable.cparam.width] * (dblock_entry % hdr->man_dtable.cparam.width); - /* Create new direct block at current location*/ - if(H5HF_man_dblock_create(dxpl_id, hdr, iblock, dblock_entry, dblock_size, dblock_off, &dblock_addr, NULL) < 0) + if(H5HF_man_dblock_create(dxpl_id, hdr, iblock, next_entry, &dblock_addr, ret_sec_node) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block") - #ifdef QAK HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr); #endif /* QAK */ - - /* Point indirect block at new direct block */ - iblock->ents[dblock_entry].addr = dblock_addr; - - /* Mark indirect block as modified */ - if(H5HF_iblock_dirty(iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty") } /* end else */ - /* Advance the allocated heap size/new block iterator */ - if(H5HF_hdr_inc_alloc(hdr, dblock_off + dblock_size, 1) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't increase allocated heap size") - done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_man_dblock_new() */ diff --git a/src/H5HFdtable.c b/src/H5HFdtable.c index e51b45b..1461cd7 100644 --- a/src/H5HFdtable.c +++ b/src/H5HFdtable.c @@ -103,11 +103,11 @@ H5HF_dtable_init(H5HF_dtable_t *dtable) HDassert(dtable); /* Compute/cache some values */ - dtable->first_row_bits = H5V_log2_of2(dtable->cparam.start_block_size) + - H5V_log2_of2(dtable->cparam.width); + dtable->start_bits = H5V_log2_of2(dtable->cparam.start_block_size); + dtable->first_row_bits = dtable->start_bits + H5V_log2_of2(dtable->cparam.width); dtable->max_root_rows = (dtable->cparam.max_index - dtable->first_row_bits) + 1; - dtable->max_direct_rows = (H5V_log2_of2(dtable->cparam.max_direct_size) - - H5V_log2_of2(dtable->cparam.start_block_size)) + 2; + dtable->max_direct_bits = H5V_log2_of2(dtable->cparam.max_direct_size); + dtable->max_direct_rows = (dtable->max_direct_bits - dtable->start_bits) + 2; dtable->num_id_first_row = dtable->cparam.start_block_size * dtable->cparam.width; dtable->max_dir_blk_off_size = H5HF_SIZEOF_OFFSET_LEN(dtable->cparam.max_direct_size); @@ -245,3 +245,34 @@ H5HF_dtable_size_to_row(H5HF_dtable_t *dtable, size_t block_size) FUNC_LEAVE_NOAPI(row) } /* end H5HF_dtable_size_to_row() */ + +/*------------------------------------------------------------------------- + * Function: H5HF_dtable_size_to_rows + * + * Purpose: Compute # of rows of indirect block of a given size + * + * Return: Non-negative on success (can't fail) + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 31 2006 + * + *------------------------------------------------------------------------- + */ +unsigned +H5HF_dtable_size_to_rows(H5HF_dtable_t *dtable, hsize_t size) +{ + unsigned rows; /* # of rows required for indirect block */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_dtable_size_to_rows) + + /* + * Check arguments. + */ + HDassert(dtable); + + rows = (H5V_log2_gen(size) - dtable->first_row_bits) + 1; + + FUNC_LEAVE_NOAPI(rows) +} /* end H5HF_dtable_size_to_rows() */ + diff --git a/src/H5HFhdr.c b/src/H5HFhdr.c index 05d0a77..836d1e6 100644 --- a/src/H5HFhdr.c +++ b/src/H5HFhdr.c @@ -68,6 +68,10 @@ /* Local Prototypes */ /********************/ +/* Free space section routines */ +static herr_t H5HF_hdr_skip_ranges(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_indirect_t *iblock, unsigned start_entry, unsigned nentries); + /*********************/ /* Package Variables */ @@ -426,7 +430,7 @@ HDfprintf(stderr, "%s: Marking heap header as dirty\n", FUNC); HDassert(hdr); /* Mark header as dirty in cache */ - if(H5AC_mark_pinned_entry_dirty(hdr->f, hdr, FALSE, 0) < 0) + if(H5AC_mark_pinned_or_protected_entry_dirty(hdr->f, hdr) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, FAIL, "unable to mark fractal heap header as dirty") /* Set the dirty flags for the heap header */ @@ -482,9 +486,9 @@ done: /*------------------------------------------------------------------------- - * Function: H5HF_hdr_extend_heap + * Function: H5HF_hdr_adjust_heap * - * Purpose: Extend heap to cover more space + * Purpose: Adjust heap space * * Return: Non-negative on success/Negative on failure * @@ -495,25 +499,31 @@ done: *------------------------------------------------------------------------- */ herr_t -H5HF_hdr_extend_heap(H5HF_hdr_t *hdr, hsize_t new_size, hsize_t extra_free) +H5HF_hdr_adjust_heap(H5HF_hdr_t *hdr, hsize_t new_size, hssize_t extra_free) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_hdr_extend_heap) + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_adjust_heap) /* * Check arguments. */ HDassert(hdr); - HDassert(new_size >= hdr->total_size); /* Set the total space in heap */ hdr->total_size = new_size; hdr->man_size = new_size; - /* Increment the free space in direct blocks */ + /* Adjust the free space in direct blocks */ hdr->total_man_free += extra_free; - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5HF_hdr_extend_heap() */ + /* Mark heap header as modified */ + if(H5HF_hdr_dirty(hdr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark header as dirty") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_hdr_adjust_heap() */ /*------------------------------------------------------------------------- @@ -525,37 +535,752 @@ H5HF_hdr_extend_heap(H5HF_hdr_t *hdr, hsize_t new_size, hsize_t extra_free) * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu - * Apr 24 2006 + * May 23 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_hdr_inc_alloc(H5HF_hdr_t *hdr, size_t alloc_size) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_hdr_inc_alloc) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(alloc_size); + + /* Update the "allocated" size within the heap */ + hdr->man_alloc_size += alloc_size; +#ifdef QAK +HDfprintf(stderr, "%s: hdr->man_alloc_size = %Hu\n", "H5HF_hdr_inc_alloc", hdr->man_alloc_size); +#endif /* QAK */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_hdr_inc_alloc() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_start_iter + * + * Purpose: Start "next block" iterator at an offset/entry in the heap + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 30 2006 * *------------------------------------------------------------------------- */ herr_t -H5HF_hdr_inc_alloc(H5HF_hdr_t *hdr, hsize_t new_alloc_size, unsigned nentries) +H5HF_hdr_start_iter(H5HF_hdr_t *hdr, H5HF_indirect_t *iblock, hsize_t curr_off, unsigned curr_entry) { herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_inc_alloc) + FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_start_iter) /* * Check arguments. */ HDassert(hdr); - HDassert(new_alloc_size >= hdr->man_alloc_size); + HDassert(iblock); + + /* Set up "next block" iterator at correct location */ + if(H5HF_man_iter_start_entry(hdr, &hdr->next_block, iblock, curr_entry) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize block iterator") + + /* Set the offset of the iterator in the heap */ + hdr->man_iter_off = curr_off; - /* Advance the iterator for the current location with in the indirect block */ +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_hdr_start_iter() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_reset_iter + * + * Purpose: Reset "next block" iterator + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 31 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_hdr_reset_iter(H5HF_hdr_t *hdr, hsize_t curr_off) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_reset_iter) + + /* + * Check arguments. + */ + HDassert(hdr); + + /* Reset "next block" iterator */ + if(H5HF_man_iter_reset(&hdr->next_block) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't reset block iterator") + + /* Set the offset of the iterator in the heap */ + hdr->man_iter_off = curr_off; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_hdr_reset_iter() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_skip_blocks + * + * Purpose: Add skipped direct blocks to free space for heap + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Apr 3 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_hdr_skip_blocks(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_indirect_t *iblock, + unsigned start_entry, unsigned nentries) +{ + hsize_t sect_off; /* Offset of free section in heap */ + unsigned curr_row; /* Current row in indirect block */ + unsigned curr_col; /* Current column in indirect block */ + unsigned u; /* Local index variables */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_skip_blocks) +#ifdef QAK +HDfprintf(stderr, "%s: start_entry = %u, nentries = %u\n", FUNC, start_entry, nentries); +#endif /* QAK */ + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(iblock); + HDassert(nentries); + + /* Compute starting column & row */ + curr_row = start_entry / hdr->man_dtable.cparam.width; + curr_col = start_entry % hdr->man_dtable.cparam.width; + + /* Initialize information for rows skipped over */ + sect_off = iblock->block_off; + for(u = 0; u < curr_row; u++) + sect_off += hdr->man_dtable.row_block_size[u] * hdr->man_dtable.cparam.width; + sect_off += hdr->man_dtable.row_block_size[curr_row] * curr_col; +#ifdef QAK +HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off); +#endif /* QAK */ + + /* Loop over the blocks to skip */ + for(u = start_entry; u < (start_entry + nentries); /* u is advanced in loop */) { + unsigned row_entries; /* Number of entries in a particular row */ + + /* Compute number of entries in (possible partial) current row */ + row_entries = MIN(hdr->man_dtable.cparam.width - curr_col, (start_entry + nentries) - u); +#ifdef QAK +HDfprintf(stderr, "%s: u = %u\n", FUNC, u); +HDfprintf(stderr, "%s: curr_col = %u, curr_row = %u\n", FUNC, curr_col, curr_row); +HDfprintf(stderr, "%s: row_entries = %u, hdr->man_dtable.row_dblock_free[%u] = %Hu\n", FUNC, row_entries, curr_row, hdr->man_dtable.row_dblock_free[curr_row]); +#endif /* QAK */ + + /* Add 'range' section for blocks skipped in this row */ + if(H5HF_sect_range_add(hdr, dxpl_id, sect_off, hdr->man_dtable.row_dblock_free[curr_row], + iblock, curr_row, curr_col, row_entries) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create range section for indirect block's free space") + + /* Advance row & column position */ + sect_off += row_entries * hdr->man_dtable.row_block_size[curr_row]; + curr_row++; + curr_col = 0; /* (first partial row aligns this) */ + + /* Increment index variable */ + u += row_entries; + } /* end for */ +#ifdef QAK +HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off); +#endif /* QAK */ + + /* Advance the new block iterator */ + if(H5HF_hdr_inc_iter(hdr, (sect_off - hdr->man_iter_off), nentries) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't increase allocated heap size") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_hdr_skip_blocks() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_skip_ranges + * + * Purpose: Add skipped indirect ranges to free space for heap + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Apr 4 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_hdr_skip_ranges(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_indirect_t *iblock, + unsigned start_entry, unsigned nentries) +{ + hsize_t sect_off; /* Offset of free section in heap */ + size_t row_dblock_free_space; /* Size of free space for row of direct blocks in a row */ + size_t acc_row_dblock_free_space; /* Accumulated size of free space for row of direct blocks in a row */ + unsigned curr_row; /* Current row in indirect block */ + unsigned curr_col; /* Current column in indirect block */ + unsigned u, w; /* Local index variables */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_skip_ranges) +#ifdef QAK +HDfprintf(stderr, "%s: start_entry = %u, nentries = %u\n", FUNC, start_entry, nentries); +#endif /* QAK */ + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(iblock); + HDassert(nentries); + + /* Compute starting column & row */ + curr_row = start_entry / hdr->man_dtable.cparam.width; + curr_col = start_entry % hdr->man_dtable.cparam.width; +#ifdef QAK +HDfprintf(stderr, "%s: curr_col = %u, curr_row = %u\n", FUNC, curr_col, curr_row); +#endif /* QAK */ + + /* Initialize information for rows skipped over */ + sect_off = iblock->block_off; + for(u = 0; u < curr_row; u++) + sect_off += hdr->man_dtable.row_block_size[u] * hdr->man_dtable.cparam.width; + sect_off += hdr->man_dtable.row_block_size[curr_row] * curr_col; +#ifdef QAK +HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off); +#endif /* QAK */ + + /* Loop over the blocks to skip */ + for(u = start_entry; u < (start_entry + nentries); /* u is advanced in loop */) { + unsigned row_entries; /* Number of entries in a particular row */ + unsigned num_rows; /* Number of rows in indirect blocks referenced */ + + /* Compute number of rows in indirect blocks covered by entry */ + num_rows = (H5V_log2_of2((uint32_t)hdr->man_dtable.row_block_size[curr_row]) - + H5V_log2_of2(hdr->man_dtable.cparam.start_block_size)) - 1; + + /* Compute number of entries in (possible partial) current row */ + row_entries = MIN(hdr->man_dtable.cparam.width - curr_col, (start_entry + nentries) - u); +#ifdef QAK +HDfprintf(stderr, "%s: u = %u\n", FUNC, u); +HDfprintf(stderr, "%s: curr_col = %u, curr_row = %u\n", FUNC, curr_col, curr_row); +HDfprintf(stderr, "%s: row_entries = %u, num_rows = %u\n", FUNC, row_entries, num_rows); +#endif /* QAK */ + + /* Loop over rows in indirect blocks covered */ + acc_row_dblock_free_space = 0; + for(w = 0; w < num_rows; w++) { + + /* Compute free space in direct blocks for this row */ + row_dblock_free_space = hdr->man_dtable.cparam.width * hdr->man_dtable.row_dblock_free[w]; + acc_row_dblock_free_space += row_dblock_free_space; +#ifdef QAK +HDfprintf(stderr, "%s: w = %u\n", FUNC, w); +HDfprintf(stderr, "%s: hdr->man_dtable.row_dblock_free[%u] = %Zu\n", FUNC, w, hdr->man_dtable.row_dblock_free[w]); +#endif /* QAK */ + + /* Add "indirect" free space section for blocks in this row */ + + /* Create free list section node for blocks skipped over */ + if(H5HF_sect_indirect_add(hdr, dxpl_id, (sect_off + hdr->man_dtable.row_block_off[w]), + hdr->man_dtable.row_dblock_free[w], iblock, curr_row, curr_col, row_entries, w, num_rows) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section for indirect block's free space") + } /* end for */ +#ifdef QAK +HDfprintf(stderr, "%s: acc_row_dblock_free_space = %Zu\n", FUNC, acc_row_dblock_free_space); +#endif /* QAK */ + + /* Advance row & column position */ + sect_off += row_entries * hdr->man_dtable.row_block_size[curr_row]; + curr_row++; + curr_col = 0; /* (first partial row aligns this) */ + + /* Advance outer loop index */ + u += row_entries; + } /* end for */ +#ifdef QAK +HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off); +#endif /* QAK */ + + /* Advance the new block iterator */ + if(H5HF_hdr_inc_iter(hdr, (sect_off - hdr->man_iter_off), nentries) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't increase allocated heap size") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_hdr_skip_ranges() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_update_iter + * + * Purpose: Update state of heap to account for current iterator + * position. + * + * Note: Creates necessary indirect blocks + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 14 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_hdr_update_iter(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t min_dblock_size) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_update_iter) +#ifdef QAK +HDfprintf(stderr, "%s: min_dblock_size = %Zu\n", FUNC, min_dblock_size); +#endif /* QAK */ + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(min_dblock_size > 0); + + /* Check for creating first indirect block */ + if(hdr->man_dtable.curr_root_rows == 0) { + if(H5HF_man_iblock_root_create(hdr, dxpl_id, min_dblock_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "unable to create root indirect block") + } /* end if */ + else { + H5HF_indirect_t *iblock; /* Pointer to indirect block */ + hbool_t walked_up, walked_down; /* Condition variables for finding direct block location */ + unsigned next_row; /* Iterator's next block row */ + unsigned next_entry; /* Iterator's next block entry */ + unsigned min_dblock_row; /* Minimum row for direct block size request */ + +#ifdef QAK +HDfprintf(stderr, "%s: searching root indirect block\n", FUNC); +#endif /* QAK */ + /* Compute min. row for direct block requested */ + min_dblock_row = H5HF_dtable_size_to_row(&hdr->man_dtable, min_dblock_size); +#ifdef QAK +HDfprintf(stderr, "%s: min_dblock_size = %Zu, min_dblock_row = %u\n", FUNC, min_dblock_size, min_dblock_row); +#endif /* QAK */ + + /* Initialize block iterator, if necessary */ + if(!H5HF_man_iter_ready(&hdr->next_block)) { +#ifdef QAK +HDfprintf(stderr, "%s: hdr->man_iter_off = %Hu\n", FUNC, hdr->man_iter_off); +#endif /* QAK */ + /* Start iterator with previous offset of iterator */ + if(H5HF_man_iter_start_offset(hdr, dxpl_id, &hdr->next_block, hdr->man_iter_off) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to set block iterator location") + } /* end if */ + + /* Get information about current iterator location */ + if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL, &next_entry, &iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to retrieve current block iterator location") + +#ifdef QAK +HDfprintf(stderr, "%s: Check 1.0\n", FUNC); +HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock); +HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows); +HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row); +HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry); +#endif /* QAK */ + /* Check for skipping over blocks in the current block */ + if(min_dblock_row > next_row && next_row < iblock->nrows) { + unsigned min_entry; /* Min entry for direct block requested */ + unsigned skip_entries; /* Number of entries to skip in the current block */ + + /* Compute the number of entries to skip in the current block */ + min_entry = min_dblock_row * hdr->man_dtable.cparam.width; + if(min_dblock_row >= iblock->nrows) + skip_entries = (iblock->nrows * hdr->man_dtable.cparam.width) - next_entry; + else + skip_entries = min_entry - next_entry; +#ifdef QAK +HDfprintf(stderr, "%s: min_entry = %u, skip_entries = %u\n", FUNC, min_entry, skip_entries); +#endif /* QAK */ + + /* Add skipped direct blocks to heap's free space */ + if(H5HF_hdr_skip_blocks(hdr, dxpl_id, iblock, next_entry, skip_entries) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't add skipped blocks to heap's free space") + + /* Get information about new iterator location */ + if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL, &next_entry, &iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to retrieve current block iterator location") + } /* end if */ + + do { + /* Reset conditions for leaving loop */ + walked_up = walked_down = FALSE; + +#ifdef QAK +HDfprintf(stderr, "%s: Check 2.0\n", FUNC); +HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock); +HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows); +HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row); +HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry); +#endif /* QAK */ + + /* Check for walking off end of indirect block */ + /* (walk up iterator) */ + while(next_row >= iblock->nrows) { +#ifdef QAK +HDfprintf(stderr, "%s: Off the end of a block\n", FUNC); +#endif /* QAK */ + /* Check for needing to expand root indirect block */ + if(iblock->parent == NULL) { +#ifdef QAK +HDfprintf(stderr, "%s: Doubling root block\n", FUNC); +#endif /* QAK */ + if(H5HF_man_iblock_root_double(hdr, dxpl_id, min_dblock_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "unable to double root indirect block") + } /* end if */ + else { +#ifdef QAK +HDfprintf(stderr, "%s: Walking up a level\n", FUNC); +#endif /* QAK */ + /* Move iterator up one level */ + if(H5HF_man_iter_up(&hdr->next_block) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTNEXT, FAIL, "unable to advance current block iterator location") + + /* Increment location of next block at this level */ + if(H5HF_man_iter_next(hdr, &hdr->next_block, 1) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't advance fractal heap block location") + } /* end else */ + + /* Get information about new iterator location */ + if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL, &next_entry, &iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to retrieve current block iterator location") + + /* Indicate that we walked up */ + walked_up = TRUE; + } /* end while */ +#ifdef QAK +HDfprintf(stderr, "%s: Check 3.0\n", FUNC); +HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock); +HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows); +HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row); +HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry); +#endif /* QAK */ + + /* Check for walking into child indirect block */ + /* (walk down iterator) */ + if(next_row >= hdr->man_dtable.max_direct_rows) { + unsigned child_nrows; /* Number of rows in new indirect block */ + +#ifdef QAK +HDfprintf(stderr, "%s: Walking down into child indirect block\n", FUNC); +#endif /* QAK */ +#ifdef QAK +HDfprintf(stderr, "%s: Check 3.1\n", FUNC); +HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock); +HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows); +HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row); +HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry); +#endif /* QAK */ + HDassert(!H5F_addr_defined(iblock->ents[next_entry].addr)); + + /* Compute # of rows in next child indirect block to use */ + child_nrows = H5HF_dtable_size_to_rows(&hdr->man_dtable, hdr->man_dtable.row_block_size[next_row]); +#ifdef QAK +HDfprintf(stderr, "%s: child_nrows = %u\n", FUNC, child_nrows); +#endif /* QAK */ + + /* Check for skipping over indirect blocks */ + /* (that don't have direct blocks large enough to hold direct block size requested) */ + if(hdr->man_dtable.row_block_size[child_nrows - 1] < min_dblock_size) { + unsigned child_rows_needed; /* Number of rows needed to hold direct block */ + unsigned child_entry; /* Entry of child indirect block */ + +#ifdef QAK +HDfprintf(stderr, "%s: Skipping indirect block row that is too small\n", FUNC); +#endif /* QAK */ + /* Compute # of rows needed in child indirect block */ + child_rows_needed = (H5V_log2_of2(min_dblock_size) - H5V_log2_of2(hdr->man_dtable.cparam.start_block_size)) + 2; + HDassert(child_rows_needed > child_nrows); + child_entry = (next_row + (child_rows_needed - child_nrows)) * hdr->man_dtable.cparam.width; + if(child_entry > (iblock->nrows * hdr->man_dtable.cparam.width)) + child_entry = iblock->nrows * hdr->man_dtable.cparam.width; +#ifdef QAK +HDfprintf(stderr, "%s: child_rows_needed = %u\n", FUNC, child_rows_needed); +HDfprintf(stderr, "%s: child_entry = %u\n", FUNC, child_entry); +#endif /* QAK */ + + /* Add skipped indirect ranges to heap's free space */ + if(H5HF_hdr_skip_ranges(hdr, dxpl_id, iblock, next_entry, (child_entry - next_entry)) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't add skipped blocks to heap's free space") + } /* end if */ + else { + H5HF_indirect_t *new_iblock; /* Pointer to new indirect block */ + haddr_t new_iblock_addr; /* New indirect block's address */ + +#ifdef QAK +HDfprintf(stderr, "%s: Allocating new child indirect block\n", FUNC); +#endif /* QAK */ + /* Allocate new indirect block */ + if(H5HF_man_iblock_create(hdr, dxpl_id, iblock, next_entry, child_nrows, child_nrows, &new_iblock_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap indirect block") + + /* Lock new indirect block */ + if(NULL == (new_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, new_iblock_addr, child_nrows, iblock, next_entry, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") + + /* Move iterator down one level */ + if(H5HF_man_iter_down(&hdr->next_block, new_iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTNEXT, FAIL, "unable to advance current block iterator location") + + /* Check for skipping over rows and add free section for skipped rows */ + if(min_dblock_size > hdr->man_dtable.cparam.start_block_size) { + unsigned new_entry; /* Entry of direct block which is large enough */ + + /* Compute entry for direct block size requested */ + new_entry = hdr->man_dtable.cparam.width * min_dblock_row; +#ifdef QAK +HDfprintf(stderr, "%s: Skipping rows in new child indirect block - new_entry = %u\n", FUNC, new_entry); +#endif /* QAK */ + + /* Add skipped blocks to heap's free space */ + if(H5HF_hdr_skip_blocks(hdr, dxpl_id, new_iblock, 0, new_entry) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't add skipped blocks to heap's free space") + } /* end if */ + + /* Unprotect child indirect block */ + if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, new_iblock->addr, new_iblock, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + } /* end else */ + + /* Get information about new iterator location */ + if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL, &next_entry, &iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to retrieve current block iterator location") + + /* Indicate that we walked down */ + walked_down = TRUE; + } /* end if */ + } while(walked_down || walked_up); + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_hdr_update_iter() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_inc_iter + * + * Purpose: Advance "next block" iterator + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 23 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_hdr_inc_iter(H5HF_hdr_t *hdr, hsize_t adv_size, unsigned nentries) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_inc_iter) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(nentries); +#ifdef QAK +HDfprintf(stderr, "%s: hdr->man_iter_off = %Hu, adv_size = %Hu\n", FUNC, hdr->man_iter_off, adv_size); +#endif /* QAK */ + + /* Advance the iterator for the current location within the indirect block */ if(hdr->next_block.curr) if(H5HF_man_iter_next(hdr, &hdr->next_block, nentries) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTNEXT, FAIL, "unable to advance current block iterator location") - /* Update the "allocated" size within the heap */ - hdr->man_alloc_size = new_alloc_size; + /* Increment the offset of the iterator in the heap */ + hdr->man_iter_off += adv_size; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_hdr_inc_iter() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_reverse_iter + * + * Purpose: Walk "next block" iterator backwards until the correct + * location to allocate next block from is found + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 31 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_hdr_reverse_iter(H5HF_hdr_t *hdr, hid_t dxpl_id) +{ + H5HF_indirect_t *iblock; /* Indirect block where iterator is located */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_reverse_iter) + + /* + * Check arguments. + */ + HDassert(hdr); + + /* Initialize block iterator, if necessary */ + if(!H5HF_man_iter_ready(&hdr->next_block)) + /* Start iterator with previous offset of iterator */ + if(H5HF_man_iter_start_offset(hdr, dxpl_id, &hdr->next_block, hdr->man_iter_off) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to set block iterator location") + + /* Get information about current iterator location */ + if(H5HF_man_iter_curr(&hdr->next_block, NULL, NULL, NULL, &iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to retrieve current block iterator information") #ifdef QAK -HDfprintf(stderr, "%s: hdr->man_alloc_size = %Hu\n", FUNC, hdr->man_alloc_size); +HDfprintf(stderr, "%s: iblock->nchildren = %u\n", FUNC, iblock->nchildren); +HDfprintf(stderr, "%s: iblock->parent = %p\n", FUNC, iblock->parent); #endif /* QAK */ + /* Walk backwards through heap, looking for direct block to place iterator after */ + + /* Walk up the levels in the heap until we find an indirect block with children */ + while(iblock->nchildren == 0 && iblock->parent) { + /* Move iterator to parent of current block */ + if(H5HF_man_iter_up(&hdr->next_block) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTNEXT, FAIL, "unable to advance current block iterator location") + + /* Detach from parent indirect block */ + if(H5HF_man_iblock_detach(iblock->parent, dxpl_id, iblock->par_entry) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTATTACH, FAIL, "can't detach from parent indirect block") + iblock->parent = NULL; + iblock->par_entry = 0; + } /* end while */ + + /* If there's children in this indirect block, walk backwards to find last child */ + if(iblock->nchildren) { + unsigned curr_entry; /* Current entry for iterator */ + unsigned row; /* Row for entry */ + hbool_t walked_down; /* Loop flag */ + + /* Get information about current iterator location */ + if(H5HF_man_iter_curr(&hdr->next_block, NULL, NULL, &curr_entry, NULL) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to retrieve current block iterator information") +#ifdef QAK +HDfprintf(stderr, "%s: curr_entry = %u\n", FUNC, curr_entry); +#endif /* QAK */ + + /* Move current iterator position backwards once */ + curr_entry--; + + /* Search backwards for direct block to latch onto */ + do { + int tmp_entry; /* Temp. entry for iterator (use signed value to detect errors) */ + + /* Reset loop flag */ + walked_down = FALSE; + + /* Walk backwards through entries, until we find one that has a child */ + /* (Account for root indirect block shrinking) */ + tmp_entry = MIN(curr_entry, ((iblock->nrows * hdr->man_dtable.cparam.width) - 1)); +#ifdef QAK +HDfprintf(stderr, "%s: tmp_entry = %d\n", FUNC, tmp_entry); +HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows); +#endif /* QAK */ + while(!H5F_addr_defined(iblock->ents[tmp_entry].addr)) { + tmp_entry--; + HDassert(tmp_entry >= 0); + } /* end while */ +#ifdef QAK +HDfprintf(stderr, "%s: check 2.0 - tmp_entry = %d\n", FUNC, tmp_entry); +#endif /* QAK */ + curr_entry = tmp_entry; + + /* Check if entry is for a direct block */ + row = curr_entry / hdr->man_dtable.cparam.width; + if(row < hdr->man_dtable.max_direct_rows) { + /* Increment entry to empty location */ + curr_entry++; + + /* Set the current location of the iterator to next entry after the existing direct block */ + if(H5HF_man_iter_set_entry(hdr, &hdr->next_block, curr_entry) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSET, FAIL, "unable to set current block iterator location") + + /* Update iterator offset */ + hdr->man_iter_off = iblock->block_off; + hdr->man_iter_off += hdr->man_dtable.row_block_off[curr_entry / hdr->man_dtable.cparam.width]; + hdr->man_iter_off += hdr->man_dtable.row_block_size[curr_entry / hdr->man_dtable.cparam.width] * (curr_entry % hdr->man_dtable.cparam.width); + } /* end if */ + else { + H5HF_indirect_t *child_iblock; /* Pointer to child indirect block */ + unsigned child_nrows; /* # of rows in child block */ + + /* Compute # of rows in next child indirect block to use */ + child_nrows = H5HF_dtable_size_to_rows(&hdr->man_dtable, hdr->man_dtable.row_block_size[row]); + + /* Lock child indirect block */ + if(NULL == (child_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock->ents[curr_entry].addr, child_nrows, iblock, curr_entry, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") + + /* Set the current location of the iterator */ + if(H5HF_man_iter_set_entry(hdr, &hdr->next_block, curr_entry) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSET, FAIL, "unable to set current block iterator location") + + /* Walk down into child indirect block (pins child block) */ + if(H5HF_man_iter_down(&hdr->next_block, child_iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTNEXT, FAIL, "unable to advance current block iterator location") + + /* Update iterator location */ + iblock = child_iblock; + curr_entry = (child_iblock->nrows * hdr->man_dtable.cparam.width) - 1; + + /* Unprotect child indirect block */ + if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, child_iblock->addr, child_iblock, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + + /* Note that we walked down */ + walked_down = TRUE; + } /* end else */ + } while(walked_down); + } /* end if */ + else { + /* Reset header information back to "empty heap" state */ + if(H5HF_hdr_empty(hdr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't make heap empty") + } /* end else */ + done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_hdr_inc_alloc() */ +} /* end H5HF_hdr_reverse_iter() */ /*------------------------------------------------------------------------- @@ -584,13 +1309,10 @@ HDfprintf(stderr, "%s: Reseting heap header to empty\n", FUNC); /* Sanity check */ HDassert(hdr); - /* Reset root pointer information */ - hdr->man_dtable.curr_root_rows = 0; - hdr->man_dtable.table_addr = HADDR_UNDEF; - /* Shrink heap size */ hdr->total_size = hdr->std_size; hdr->man_size = 0; + hdr->man_alloc_size = 0; /* Reset the free space in direct blocks */ hdr->total_man_free = 0; diff --git a/src/H5HFiblock.c b/src/H5HFiblock.c index f3d7029..652ae54 100644 --- a/src/H5HFiblock.c +++ b/src/H5HFiblock.c @@ -56,24 +56,9 @@ /********************/ /* Local Prototypes */ /********************/ +static herr_t H5HF_man_iblock_root_halve(H5HF_indirect_t *root_iblock, hid_t dxpl_id); +static herr_t H5HF_man_iblock_root_revert(H5HF_indirect_t *root_iblock, hid_t dxpl_id); -/* Free space section routines */ -static herr_t H5HF_man_iblock_skip_blocks(H5HF_hdr_t *hdr, hid_t dxpl_id, - H5HF_indirect_t *iblock, haddr_t iblock_addr, - unsigned start_entry, unsigned nentries); -static herr_t H5HF_man_iblock_skip_ranges(H5HF_hdr_t *hdr, hid_t dxpl_id, - H5HF_indirect_t *iblock, haddr_t iblock_addr, - unsigned start_entry, unsigned nentries); - -/* Root indirect block routines */ -static herr_t H5HF_man_iblock_root_create(H5HF_hdr_t *hdr, hid_t dxpl_id, - size_t min_dblock_size); -static herr_t H5HF_man_iblock_root_double(H5HF_hdr_t *hdr, hid_t dxpl_id, - size_t min_dblock_size); - -/* Misc. indirect block routines */ -static herr_t H5HF_man_iblock_create(H5HF_hdr_t *hdr, hid_t dxpl_id, - hsize_t block_off, unsigned nrows, unsigned max_rows, haddr_t *addr_p); /*********************/ /* Package Variables */ @@ -160,10 +145,40 @@ H5HF_iblock_decr(H5HF_indirect_t *iblock) iblock->rc--; /* Mark block as evictable again when no child blocks depend on it */ - if(iblock->rc == 0) + if(iblock->rc == 0) { + H5HF_indirect_t *tmp_iblock; /* Temporary pointer to indirect block */ + +#ifdef QAK +HDfprintf(stderr, "%s: indirect block ref. count at zero, iblock->addr = %a\n", FUNC, iblock->addr); +#endif /* QAK */ + /* Lock indirect block */ + if(iblock->nchildren == 0) { + if(NULL == (tmp_iblock = H5HF_man_iblock_protect(iblock->hdr, H5AC_dxpl_id, iblock->addr, iblock->nrows, NULL, 0, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") + HDassert(tmp_iblock == iblock); + } /* end if */ + if(H5AC_unpin_entry(iblock->hdr->f, iblock) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPIN, FAIL, "unable to unpin fractal heap indirect block") +/* XXX: If the indirect block has no children, delete indirect block's entry + * from cache. + */ + if(iblock->nchildren == 0) { + /* Check for deleting root indirect block (and no root direct block) */ + if(iblock->block_off == 0 && iblock->hdr->man_dtable.curr_root_rows > 0) { + /* Reset root pointer information */ + iblock->hdr->man_dtable.curr_root_rows = 0; + iblock->hdr->man_dtable.table_addr = HADDR_UNDEF; + } /* end if */ + + /* Unlock indirect block with delete flag */ + if(H5AC_unprotect(iblock->hdr->f, H5AC_dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, tmp_iblock, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + tmp_iblock = NULL; + } /* end if */ + } /* end if */ + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_iblock_decr() */ @@ -195,23 +210,9 @@ HDfprintf(stderr, "%s: Marking indirect block as dirty\n", FUNC); /* Sanity check */ HDassert(iblock); -/* XXX: Need to mark a protected block as dirty eventually also... */ -{ - unsigned entry_status; /* Indirect block entry status */ - - if(H5AC_get_entry_status(iblock->hdr->f, iblock->addr, &entry_status) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, FAIL, "unable to query fractal heap indirect block status") - HDassert(entry_status & H5AC_ES__IN_CACHE); - - if(!(entry_status & H5AC_ES__IS_PROTECTED)) { - /* Mark indirect block as dirty in cache */ - if(H5AC_mark_pinned_entry_dirty(iblock->hdr->f, iblock, FALSE, 0) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, FAIL, "unable to mark fractal heap indirect block as dirty") - } /* end if */ -} - - /* Set the dirty flag for the indirect block */ - iblock->dirty = TRUE; + /* Mark indirect block as dirty in cache */ + if(H5AC_mark_pinned_or_protected_entry_dirty(iblock->hdr->f, iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, FAIL, "unable to mark fractal heap indirect block as dirty") done: FUNC_LEAVE_NOAPI(ret_value) @@ -219,245 +220,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5HF_man_iblock_skip_blocks - * - * Purpose: Add skipped direct blocks to free space for heap - * - * Return: SUCCEED/FAIL - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Apr 3 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HF_man_iblock_skip_blocks(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_indirect_t *iblock, - haddr_t iblock_addr, unsigned start_entry, unsigned nentries) -{ - H5HF_free_section_t *sec_node; /* Pointer to free list section for range */ - hsize_t sect_off; /* Offset of free section in heap */ - unsigned curr_row; /* Current row in indirect block */ - unsigned curr_col; /* Current column in indirect block */ - unsigned u; /* Local index variables */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_skip_blocks) -#ifdef QAK -HDfprintf(stderr, "%s: start_entry = %u, nentries = %u\n", FUNC, start_entry, nentries); -#endif /* QAK */ - - /* - * Check arguments. - */ - HDassert(hdr); - HDassert(iblock); - HDassert(H5F_addr_defined(iblock_addr)); - - /* Compute starting column & row */ - curr_row = start_entry / hdr->man_dtable.cparam.width; - curr_col = start_entry % hdr->man_dtable.cparam.width; - - /* Initialize information for rows skipped over */ - sect_off = iblock->block_off; - for(u = 0; u < curr_row; u++) - sect_off += hdr->man_dtable.row_block_size[u] * hdr->man_dtable.cparam.width; - sect_off += hdr->man_dtable.row_block_size[curr_row] * curr_col; -#ifdef QAK -HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off); -#endif /* QAK */ - - /* Loop over the blocks to skip */ - for(u = start_entry; u < (start_entry + nentries); /* u is advanced in loop */) { - unsigned row_entries; /* Number of entries in a particular row */ - - /* Compute number of entries in (possible partial) current row */ - row_entries = MIN(hdr->man_dtable.cparam.width - curr_col, (start_entry + nentries) - u); -#ifdef QAK -HDfprintf(stderr, "%s: u = %u\n", FUNC, u); -HDfprintf(stderr, "%s: curr_col = %u, curr_row = %u\n", FUNC, curr_col, curr_row); -HDfprintf(stderr, "%s: row_entries = %u, hdr->man_dtable.row_dblock_free[%u] = %Hu\n", FUNC, row_entries, curr_row, hdr->man_dtable.row_dblock_free[curr_row]); -#endif /* QAK */ - - /* Add free space section for blocks in this row */ - - /* Create free list section node for blocks skipped over */ - if(NULL == (sec_node = H5FL_MALLOC(H5HF_free_section_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") - - /* Set section's information */ - sec_node->sect_info.addr = sect_off; - sec_node->sect_info.size = hdr->man_dtable.row_dblock_free[curr_row]; - sec_node->sect_info.cls = &hdr->sect_cls[H5FS_SECT_FHEAP_RANGE]; - sec_node->sect_info.state = H5FS_SECT_LIVE; - sec_node->u.range.iblock = iblock; - if(H5HF_iblock_incr(iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") - sec_node->u.range.row = curr_row; - sec_node->u.range.col = curr_col; - sec_node->u.range.num_entries = row_entries; - - /* Add new free space to the global list of space */ - if(H5HF_space_add(hdr, dxpl_id, sec_node) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list") - - /* Advance row & column position */ - sect_off += row_entries * hdr->man_dtable.row_block_size[curr_row]; - curr_row++; - curr_col = 0; /* (first partial row aligns this) */ - - /* Increment index variable */ - u += row_entries; - } /* end for */ -#ifdef QAK -HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off); -#endif /* QAK */ - - /* Advance the allocated heap size/new block iterator */ - if(H5HF_hdr_inc_alloc(hdr, sect_off, nentries) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't increase allocated heap size") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_man_iblock_skip_blocks() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_man_iblock_skip_ranges - * - * Purpose: Add skipped indirect ranges to free space for heap - * - * Return: SUCCEED/FAIL - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Apr 4 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HF_man_iblock_skip_ranges(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_indirect_t *iblock, - haddr_t iblock_addr, unsigned start_entry, unsigned nentries) -{ - H5HF_free_section_t *sec_node; /* Pointer to free list section for range */ - hsize_t sect_off; /* Offset of free section in heap */ - size_t row_dblock_free_space; /* Size of free space for row of direct blocks in a row */ - size_t acc_row_dblock_free_space; /* Accumulated size of free space for row of direct blocks in a row */ - unsigned curr_row; /* Current row in indirect block */ - unsigned curr_col; /* Current column in indirect block */ - unsigned u, w; /* Local index variables */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_skip_ranges) -#ifdef QAK -HDfprintf(stderr, "%s: start_entry = %u, nentries = %u\n", FUNC, start_entry, nentries); -#endif /* QAK */ - - /* - * Check arguments. - */ - HDassert(hdr); - HDassert(iblock); - HDassert(H5F_addr_defined(iblock_addr)); - - /* Compute starting column & row */ - curr_row = start_entry / hdr->man_dtable.cparam.width; - curr_col = start_entry % hdr->man_dtable.cparam.width; -#ifdef QAK -HDfprintf(stderr, "%s: curr_col = %u, curr_row = %u\n", FUNC, curr_col, curr_row); -#endif /* QAK */ - - /* Initialize information for rows skipped over */ - sect_off = iblock->block_off; - for(u = 0; u < curr_row; u++) - sect_off += hdr->man_dtable.row_block_size[u] * hdr->man_dtable.cparam.width; - sect_off += hdr->man_dtable.row_block_size[curr_row] * curr_col; -#ifdef QAK -HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off); -#endif /* QAK */ - - /* Loop over the blocks to skip */ - for(u = start_entry; u < (start_entry + nentries); /* u is advanced in loop */) { - unsigned row_entries; /* Number of entries in a particular row */ - unsigned num_rows; /* Number of rows in indirect blocks referenced */ - - /* Compute number of rows in indirect blocks covered by entry */ - num_rows = (H5V_log2_of2((uint32_t)hdr->man_dtable.row_block_size[curr_row]) - - H5V_log2_of2(hdr->man_dtable.cparam.start_block_size)) - 1; - - /* Compute number of entries in (possible partial) current row */ - row_entries = MIN(hdr->man_dtable.cparam.width - curr_col, (start_entry + nentries) - u); -#ifdef QAK -HDfprintf(stderr, "%s: u = %u\n", FUNC, u); -HDfprintf(stderr, "%s: curr_col = %u, curr_row = %u\n", FUNC, curr_col, curr_row); -HDfprintf(stderr, "%s: row_entries = %u, num_rows = %u\n", FUNC, row_entries, num_rows); -#endif /* QAK */ - - /* Loop over rows in indirect blocks covered */ - acc_row_dblock_free_space = 0; - for(w = 0; w < num_rows; w++) { - - /* Compute free space in direct blocks for this row */ - row_dblock_free_space = hdr->man_dtable.cparam.width * hdr->man_dtable.row_dblock_free[w]; - acc_row_dblock_free_space += row_dblock_free_space; -#ifdef QAK -HDfprintf(stderr, "%s: w = %u\n", FUNC, w); -HDfprintf(stderr, "%s: hdr->man_dtable.row_dblock_free[%u] = %Zu\n", FUNC, w, hdr->man_dtable.row_dblock_free[w]); -#endif /* QAK */ - - /* Add "indirect" free space section for blocks in this row */ - - /* Create free list section node for blocks skipped over */ - if(NULL == (sec_node = H5FL_MALLOC(H5HF_free_section_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") - - /* Set section's information */ - sec_node->sect_info.addr = sect_off + hdr->man_dtable.row_block_off[w]; -#ifdef QAK -HDfprintf(stderr, "%s: sec_node->sect_info.addr = %a\n", FUNC, sec_node->sect_info.addr); -#endif /* QAK */ - sec_node->sect_info.size = hdr->man_dtable.row_dblock_free[w]; - sec_node->sect_info.cls = &hdr->sect_cls[H5FS_SECT_FHEAP_INDIRECT]; - sec_node->sect_info.state = H5FS_SECT_LIVE; - sec_node->u.indirect.iblock = iblock; - if(H5HF_iblock_incr(iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") - sec_node->u.indirect.row = curr_row; - sec_node->u.indirect.col = curr_col; - sec_node->u.indirect.num_entries = row_entries; - sec_node->u.indirect.indir_row = w; - sec_node->u.indirect.indir_nrows = num_rows; - - /* Add new free space to the global list of space */ - if(H5HF_space_add(hdr, dxpl_id, sec_node) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list") - } /* end for */ -#ifdef QAK -HDfprintf(stderr, "%s: acc_row_dblock_free_space = %Zu\n", FUNC, acc_row_dblock_free_space); -#endif /* QAK */ - - /* Advance row & column position */ - sect_off += row_entries * hdr->man_dtable.row_block_size[curr_row]; - curr_row++; - curr_col = 0; /* (first partial row aligns this) */ - - /* Advance outer loop index */ - u += row_entries; - } /* end for */ -#ifdef QAK -HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off); -#endif /* QAK */ - - /* Advance the allocated heap size/new block iterator */ - if(H5HF_hdr_inc_alloc(hdr, sect_off, nentries) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't increase allocated heap size") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_man_iblock_skip_ranges() */ - - -/*------------------------------------------------------------------------- * Function: H5HF_man_iblock_root_create * * Purpose: Create root indirect block @@ -470,7 +232,7 @@ done: * *------------------------------------------------------------------------- */ -static herr_t +herr_t H5HF_man_iblock_root_create(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t min_dblock_size) { H5HF_indirect_t *iblock; /* Pointer to indirect block */ @@ -508,7 +270,7 @@ HDfprintf(stderr, "%s: nrows = %u\n", FUNC, nrows); #endif /* QAK */ /* Allocate root indirect block */ - if(H5HF_man_iblock_create(hdr, dxpl_id, (hsize_t)0, nrows, hdr->man_dtable.max_root_rows, &iblock_addr) < 0) + if(H5HF_man_iblock_create(hdr, dxpl_id, NULL, 0, nrows, hdr->man_dtable.max_root_rows, &iblock_addr) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap indirect block") #ifdef QAK HDfprintf(stderr, "%s: iblock_addr = %a\n", FUNC, iblock_addr); @@ -532,30 +294,27 @@ HDfprintf(stderr, "%s: have_direct_block = %u\n", FUNC, (unsigned)have_direct_bl if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, hdr->man_dtable.table_addr, hdr->man_dtable.cparam.start_block_size, iblock, 0, H5AC_WRITE))) HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block") - /* Point indirect block at direct block to add */ - iblock->ents[0].addr = hdr->man_dtable.table_addr; - - /* Make direct block share parent indirect block */ + /* Attach direct block to new root indirect block */ dblock->parent = iblock; dblock->par_entry = 0; - if(H5HF_iblock_incr(iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") + if(H5HF_man_iblock_attach(iblock, 0, hdr->man_dtable.table_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTATTACH, FAIL, "can't attach root direct block to parent indirect block") - /* Unlock first (root) direct block */ + /* Unlock first (previously the root) direct block */ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, hdr->man_dtable.table_addr, dblock, H5AC__NO_FLAGS_SET) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block") dblock = NULL; } /* end if */ - /* Set up iterator at correct location */ - if(H5HF_man_iter_start_entry(hdr, &hdr->next_block, iblock, have_direct_block) < 0) + /* Start iterator at correct location */ + if(H5HF_hdr_start_iter(hdr, iblock, (hsize_t)(have_direct_block ? hdr->man_dtable.cparam.start_block_size : 0), have_direct_block) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize block iterator") /* Check for skipping over direct blocks, in order to get to large enough block */ if(min_dblock_size > hdr->man_dtable.cparam.start_block_size) { /* Add skipped blocks to heap's free space */ - if(H5HF_man_iblock_skip_blocks(hdr, dxpl_id, iblock, iblock_addr, - have_direct_block, ((nrows - 1) * hdr->man_dtable.cparam.width) - have_direct_block) < 0) + if(H5HF_hdr_skip_blocks(hdr, dxpl_id, iblock, have_direct_block, + ((nrows - 1) * hdr->man_dtable.cparam.width) - have_direct_block) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't add skipped blocks to heap's free space") } /* end if */ @@ -582,13 +341,9 @@ HDfprintf(stderr, "%s: have_direct_block = %u\n", FUNC, (unsigned)have_direct_bl acc_dblock_free -= hdr->man_dtable.row_dblock_free[0]; /* Extend heap to cover new root indirect block */ - if(H5HF_hdr_extend_heap(hdr, hdr->man_dtable.row_block_off[nrows], acc_dblock_free) < 0) + if(H5HF_hdr_adjust_heap(hdr, hdr->man_dtable.row_block_off[nrows], (hssize_t)acc_dblock_free) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "can't increase space to cover root direct block") - /* Mark heap header as modified */ - if(H5HF_hdr_dirty(hdr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark header as dirty") - done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_man_iblock_root_create() */ @@ -607,7 +362,7 @@ done: * *------------------------------------------------------------------------- */ -static herr_t +herr_t H5HF_man_iblock_root_double(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t min_dblock_size) { H5HF_indirect_t *iblock; /* Pointer to root indirect block */ @@ -665,7 +420,7 @@ HDfprintf(stderr, "%s: new_next_entry = %u\n", FUNC, new_next_entry); #endif /* QAK */ /* Currently, the old block data is "thrown away" after the space is reallocated, -* so avoid data copy in H5MF_realloc() call by just free'ing the space and +* to avoid data copy in H5MF_realloc() call by just free'ing the space and * allocating new space. * * This also keeps the file smaller, by freeing the space and then @@ -674,8 +429,8 @@ HDfprintf(stderr, "%s: new_next_entry = %u\n", FUNC, new_next_entry); * QAK - 3/14/2006 */ /* Free previous indirect block disk space */ - if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, iblock->addr, (hsize_t)iblock->size)<0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block") + if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, iblock->addr, (hsize_t)iblock->size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block file space") /* Compute size of buffer needed for new indirect block */ iblock->nrows = new_nrows; @@ -695,8 +450,8 @@ HDfprintf(stderr, "%s: new_addr = %a\n", FUNC, new_addr); /* Check for skipping over rows and add free section for skipped rows */ if(skip_direct_rows) { /* Add skipped blocks to heap's free space */ - if(H5HF_man_iblock_skip_blocks(hdr, dxpl_id, iblock, new_addr, - next_entry, (new_next_entry - next_entry)) < 0) + if(H5HF_hdr_skip_blocks(hdr, dxpl_id, iblock, next_entry, + (new_next_entry - next_entry)) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't add skipped blocks to heap's free space") } /* end if */ @@ -714,9 +469,11 @@ HDfprintf(stderr, "%s: new_addr = %a\n", FUNC, new_addr); HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty") /* Move object in cache, if it actually was relocated */ - if(H5F_addr_ne(iblock->addr, new_addr)) + if(H5F_addr_ne(iblock->addr, new_addr)) { if(H5AC_rename(hdr->f, H5AC_FHEAP_IBLOCK, iblock->addr, new_addr) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTSPLIT, FAIL, "unable to move fractal heap root indirect block") + iblock->addr = new_addr; + } /* end if */ /* Update other shared header info */ hdr->man_dtable.curr_root_rows = new_nrows; @@ -728,363 +485,186 @@ HDfprintf(stderr, "%s: hdr->man_dtable.row_block_off[new_nrows - 1] = %Hu\n", FU HDfprintf(stderr, "%s: hdr->man_dtable.row_block_off[new_nrows] = %Hu\n", FUNC, hdr->man_dtable.row_block_off[new_nrows]); HDfprintf(stderr, "%s: acc_dblock_free = %Hu\n", FUNC, acc_dblock_free); #endif /* QAK */ - if(H5HF_hdr_extend_heap(hdr, 2 * hdr->man_dtable.row_block_off[new_nrows - 1], acc_dblock_free) < 0) + if(H5HF_hdr_adjust_heap(hdr, 2 * hdr->man_dtable.row_block_off[new_nrows - 1], (hssize_t)acc_dblock_free) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "can't increase space to cover root direct block") - /* Mark heap header as modified */ - if(H5HF_hdr_dirty(hdr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark header as dirty") - -/* XXX: Sanity check until can rename pinned entry in metadata cache */ -#ifndef NDEBUG -{ -H5HF_indirect_t *old_root_iblock = iblock; -#endif /* NDEBUG */ - - /* Lock root indirect block (again) */ - if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, new_addr, hdr->man_dtable.curr_root_rows, NULL, 0, H5AC_WRITE))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") - iblock->addr = new_addr; - -#ifndef NDEBUG - HDassert(old_root_iblock == iblock); -} -#endif /* NDEBUG */ - - /* Update the indirect block pointer in iterator */ - /* (pins the indirect block after it's in the new location) */ - if(H5HF_man_iter_update_iblock(&hdr->next_block, iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTMODIFY, FAIL, "unable to update indirect block for block iterator") - - /* Release the indirect block (marked as dirty) */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, iblock, H5AC__DIRTIED_FLAG) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") - done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_man_iblock_root_double() */ /*------------------------------------------------------------------------- - * Function: H5HF_man_iblock_place_dblock - * - * Purpose: Find indirect block with location for placing a direct block + * Function: H5HF_man_iblock_root_halve * - * Note: Creates necessary indirect blocks + * Purpose: Halve size of root indirect block * - * Return: Pointer to indirect block on success, NULL on failure + * Return: SUCCEED/FAIL * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu - * Mar 14 2006 + * Jun 12 2006 * *------------------------------------------------------------------------- */ -H5HF_indirect_t * -H5HF_man_iblock_place_dblock(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t min_dblock_size, - size_t *entry_p, size_t *dblock_size) +static herr_t +H5HF_man_iblock_root_halve(H5HF_indirect_t *iblock, hid_t dxpl_id) { - H5HF_indirect_t *ret_value; /* Return value */ + H5HF_hdr_t *hdr = iblock->hdr; /* Pointer to heap header */ + haddr_t new_addr; /* New address of indirect block */ + hsize_t acc_dblock_free; /* Accumulated free space in direct blocks */ + unsigned max_child_row; /* Row for max. child entry */ + unsigned new_nrows; /* New # of rows */ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_place_dblock) -#ifdef QAK -HDfprintf(stderr, "%s: min_dblock_size = %Zu\n", FUNC, min_dblock_size); -#endif /* QAK */ + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_root_halve) - /* - * Check arguments. - */ + /* Sanity check */ + HDassert(iblock); + HDassert(iblock->parent == NULL); HDassert(hdr); - HDassert(min_dblock_size > 0); - - /* Check for creating first indirect block */ - if(hdr->man_dtable.curr_root_rows == 0) { - if(H5HF_man_iblock_root_create(hdr, dxpl_id, min_dblock_size) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, NULL, "unable to create root indirect block") - } /* end if */ - else { - H5HF_indirect_t *iblock; /* Pointer to indirect block */ - hbool_t walked_up, walked_down; /* Condition variables for finding direct block location */ - unsigned next_row; /* Iterator's next block row */ - unsigned next_entry; /* Iterator's next block entry */ - unsigned min_dblock_row; /* Minimum row for direct block size request */ #ifdef QAK -HDfprintf(stderr, "%s: searching root indirect block\n", FUNC); +HDfprintf(stderr, "%s: Reducing root indirect block\n", FUNC); #endif /* QAK */ - /* Compute min. row for direct block requested */ - min_dblock_row = H5HF_dtable_size_to_row(&hdr->man_dtable, min_dblock_size); -#ifdef QAK -HDfprintf(stderr, "%s: min_dblock_size = %Zu, min_dblock_row = %u\n", FUNC, min_dblock_size, min_dblock_row); -#endif /* QAK */ - - /* Initialize block iterator, if necessary */ - if(!H5HF_man_iter_ready(&hdr->next_block)) { -#ifdef QAK -HDfprintf(stderr, "%s: hdr->man_alloc_size = %Hu\n", FUNC, hdr->man_alloc_size); -#endif /* QAK */ - /* Start iterator with offset of allocated space */ - if(H5HF_man_iter_start_offset(hdr, dxpl_id, &hdr->next_block, hdr->man_alloc_size) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "unable to set block iterator location") - } /* end if */ - /* Get information about current iterator location */ - if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL, - &next_entry, &iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, NULL, "unable to retrieve current block iterator location") + /* Compute maximum row used by child of indirect block */ + max_child_row = iblock->max_child / hdr->man_dtable.cparam.width; + /* Compute new # of rows in root indirect block */ + new_nrows = 1 << (1 + H5V_log2_gen((hsize_t)max_child_row)); #ifdef QAK -HDfprintf(stderr, "%s: Check 1.0\n", FUNC); -HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock); +HDfprintf(stderr, "%s: new_nrows = %u\n", FUNC, new_nrows); HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows); -HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row); -HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry); #endif /* QAK */ - /* Check for skipping over blocks in the current block */ - if(min_dblock_row > next_row && next_row < iblock->nrows) { - unsigned min_entry; /* Min entry for direct block requested */ - unsigned skip_entries; /* Number of entries to skip in the current block */ - - /* Compute the number of entries to skip in the current block */ - min_entry = min_dblock_row * hdr->man_dtable.cparam.width; - if(min_dblock_row >= iblock->nrows) - skip_entries = (iblock->nrows * hdr->man_dtable.cparam.width) - next_entry; - else - skip_entries = min_entry - next_entry; -#ifdef QAK -HDfprintf(stderr, "%s: min_entry = %u, skip_entries = %u\n", FUNC, min_entry, skip_entries); -#endif /* QAK */ - - /* Add skipped direct blocks to heap's free space */ - if(H5HF_man_iblock_skip_blocks(hdr, dxpl_id, iblock, iblock->addr, next_entry, skip_entries) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, NULL, "can't add skipped blocks to heap's free space") - /* Get information about new iterator location */ - if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL, - &next_entry, &iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, NULL, "unable to retrieve current block iterator location") - } /* end if */ +/* Currently, the old block data is "thrown away" after the space is reallocated, +* to avoid data copy in H5MF_realloc() call by just free'ing the space and +* allocating new space. +* +* This also keeps the file smaller, by freeing the space and then +* allocating new space, instead of vice versa (in H5MF_realloc). +* +* QAK - 6/12/2006 +*/ + /* Free previous indirect block disk space */ + if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, iblock->addr, (hsize_t)iblock->size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block file space") - do { - /* Reset conditions for leaving loop */ - walked_up = walked_down = FALSE; + /* Compute free space in rows to delete */ + acc_dblock_free = 0; + for(u = new_nrows; u < iblock->nrows; u++) + acc_dblock_free += hdr->man_dtable.row_dblock_free[u] * hdr->man_dtable.cparam.width; -#ifdef QAK -HDfprintf(stderr, "%s: Check 2.0\n", FUNC); -HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock); -HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows); -HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row); -HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry); -#endif /* QAK */ + /* Compute size of buffer needed for new indirect block */ + iblock->nrows = new_nrows; + iblock->size = H5HF_MAN_INDIRECT_SIZE(hdr, iblock); - /* Check for walking off end of indirect block */ - /* (walk up iterator) */ - while(next_row >= iblock->nrows) { -#ifdef QAK -HDfprintf(stderr, "%s: Off the end of a block\n", FUNC); -#endif /* QAK */ - /* Check for needing to expand root indirect block */ - if(iblock->parent == NULL) { -#ifdef QAK -HDfprintf(stderr, "%s: Doubling root block\n", FUNC); -#endif /* QAK */ - if(H5HF_man_iblock_root_double(hdr, dxpl_id, min_dblock_size) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, NULL, "unable to double root indirect block") - } /* end if */ - else { -#ifdef QAK -HDfprintf(stderr, "%s: Walking up a level\n", FUNC); -#endif /* QAK */ - /* Move iterator up one level */ - if(H5HF_man_iter_up(&hdr->next_block) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTNEXT, NULL, "unable to advance current block iterator location") - - /* Increment location of next block at this level */ - if(H5HF_man_iter_next(hdr, &hdr->next_block, 1) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't advance fractal heap block location") - } /* end else */ - - /* Get information about new iterator location */ - if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL, - &next_entry, &iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, NULL, "unable to retrieve current block iterator location") - - /* Indicate that we walked up */ - walked_up = TRUE; - } /* end while */ + /* Allocate space for the new indirect block on disk */ + if(HADDR_UNDEF == (new_addr = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, (hsize_t)iblock->size))) + HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap indirect block") #ifdef QAK -HDfprintf(stderr, "%s: Check 3.0\n", FUNC); -HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock); -HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows); -HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row); -HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry); +HDfprintf(stderr, "%s: new_addr = %a\n", FUNC, new_addr); #endif /* QAK */ - /* Check for walking into child indirect block */ - /* (walk down iterator) */ - if(next_row >= hdr->man_dtable.max_direct_rows) { - hsize_t next_size; /* Size of next direct block to create */ - unsigned child_nrows; /* Number of rows in new indirect block */ + /* Re-allocate direct block entry table */ + if(NULL == (iblock->ents = H5FL_SEQ_REALLOC(H5HF_indirect_ent_t, iblock->ents, (iblock->nrows * hdr->man_dtable.cparam.width)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct entries") -#ifdef QAK -HDfprintf(stderr, "%s: Walking down into child indirect block\n", FUNC); -#endif /* QAK */ -#ifdef QAK -HDfprintf(stderr, "%s: Check 3.1\n", FUNC); -HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock); -HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows); -HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row); -HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry); -#endif /* QAK */ - HDassert(!H5F_addr_defined(iblock->ents[next_entry].addr)); + /* Move object in cache, if it actually was relocated */ + if(H5F_addr_ne(iblock->addr, new_addr)) { + if(H5AC_rename(hdr->f, H5AC_FHEAP_IBLOCK, iblock->addr, new_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSPLIT, FAIL, "unable to move fractal heap root indirect block") + iblock->addr = new_addr; + } /* end if */ - /* Compute # of rows in next child indirect block to use */ - next_size = hdr->man_dtable.row_block_size[next_row]; - child_nrows = (H5V_log2_gen(next_size) - hdr->man_dtable.first_row_bits) + 1; -#ifdef QAK -HDfprintf(stderr, "%s: child_nrows = %u\n", FUNC, child_nrows); -#endif /* QAK */ + /* Mark indirect block as dirty */ + if(H5HF_iblock_dirty(iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty") - /* Check for skipping over indirect blocks */ - /* (that don't have direct blocks large enough to hold direct block size requested) */ - if(hdr->man_dtable.row_block_size[child_nrows - 1] < min_dblock_size) { - unsigned child_rows_needed; /* Number of rows needed to hold direct block */ - unsigned child_entry; /* Entry of child indirect block */ + /* Update other shared header info */ + hdr->man_dtable.curr_root_rows = new_nrows; + hdr->man_dtable.table_addr = new_addr; + /* Shrink heap to only cover new root indirect block */ #ifdef QAK -HDfprintf(stderr, "%s: Skipping indirect block row that is too small\n", FUNC); -#endif /* QAK */ - /* Compute # of rows needed in child indirect block */ - child_rows_needed = (H5V_log2_of2(min_dblock_size) - H5V_log2_of2(hdr->man_dtable.cparam.start_block_size)) + 2; - HDassert(child_rows_needed > child_nrows); - child_entry = (next_row + (child_rows_needed - child_nrows)) * hdr->man_dtable.cparam.width; - if(child_entry > (iblock->nrows * hdr->man_dtable.cparam.width)) - child_entry = iblock->nrows * hdr->man_dtable.cparam.width; -#ifdef QAK -HDfprintf(stderr, "%s: child_rows_needed = %u\n", FUNC, child_rows_needed); -HDfprintf(stderr, "%s: child_entry = %u\n", FUNC, child_entry); +HDfprintf(stderr, "%s: hdr->man_dtable.row_block_off[new_nrows - 1] = %Hu\n", FUNC, hdr->man_dtable.row_block_off[new_nrows - 1]); +HDfprintf(stderr, "%s: hdr->man_dtable.row_block_off[new_nrows] = %Hu\n", FUNC, hdr->man_dtable.row_block_off[new_nrows]); +HDfprintf(stderr, "%s: acc_dblock_free = %Hu\n", FUNC, acc_dblock_free); #endif /* QAK */ + if(H5HF_hdr_adjust_heap(hdr, 2 * hdr->man_dtable.row_block_off[new_nrows - 1], -(hssize_t)acc_dblock_free) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce space to cover root direct block") - /* Add skipped indirect ranges to heap's free space */ - if(H5HF_man_iblock_skip_ranges(hdr, dxpl_id, iblock, iblock->addr, next_entry, (child_entry - next_entry)) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, NULL, "can't add skipped blocks to heap's free space") - } /* end if */ - else { - H5HF_indirect_t *new_iblock; /* Pointer to new indirect block */ - hsize_t new_iblock_off; /* Direct block offset in heap address space */ - haddr_t new_iblock_addr; /* New indirect block's address */ +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_man_iblock_root_halve() */ -#ifdef QAK -HDfprintf(stderr, "%s: Allocating new child indirect block\n", FUNC); -#endif /* QAK */ - /* Compute the direct block's offset in the heap's address space */ - new_iblock_off = iblock->block_off; - new_iblock_off += hdr->man_dtable.row_block_off[next_entry / hdr->man_dtable.cparam.width]; - new_iblock_off += hdr->man_dtable.row_block_size[next_entry / hdr->man_dtable.cparam.width] * (next_entry % hdr->man_dtable.cparam.width); - - /* Allocate new indirect block */ - if(H5HF_man_iblock_create(hdr, dxpl_id, new_iblock_off, child_nrows, child_nrows, &new_iblock_addr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "can't allocate fractal heap indirect block") - - /* Lock new indirect block */ - if(NULL == (new_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, new_iblock_addr, child_nrows, iblock, next_entry, H5AC_WRITE))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block") - - /* Set parent information */ - HDassert(new_iblock->parent == NULL); - new_iblock->parent = iblock; - new_iblock->par_entry = next_entry; - if(H5HF_iblock_incr(iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block") - - /* Point current indirect block at new indirect block */ - iblock->ents[next_entry].addr = new_iblock_addr; - - /* Move iterator down one level */ - if(H5HF_man_iter_down(&hdr->next_block, new_iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTNEXT, NULL, "unable to advance current block iterator location") - - /* Get information about new iterator location */ - if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL, - &next_entry, NULL) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, NULL, "unable to retrieve current block iterator location") - next_size = hdr->man_dtable.row_block_size[next_row]; -#ifdef QAK -HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row); -HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry); -#endif /* QAK */ + +/*------------------------------------------------------------------------- + * Function: H5HF_man_iblock_root_revert + * + * Purpose: Revert root indirect block back to root direct block + * + * Note: Any sections left pointing to the old root indirect block + * will be cleaned up by the free space manager + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 31 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_man_iblock_root_revert(H5HF_indirect_t *root_iblock, hid_t dxpl_id) +{ + H5HF_hdr_t *hdr; /* Pointer to heap's header */ + H5HF_direct_t *dblock = NULL; /* Pointer to new root indirect block */ + haddr_t dblock_addr; /* Direct block's address in the file */ + size_t dblock_size; /* Direct block's size */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_root_revert) - /* Check for skipping over rows and add free section for skipped rows */ - if(min_dblock_size > next_size) { - unsigned new_entry; /* Entry of direct block which is large enough */ + /* + * Check arguments. + */ + HDassert(root_iblock); - /* Compute entry for direct block size requested */ - new_entry = hdr->man_dtable.cparam.width * min_dblock_row; #ifdef QAK -HDfprintf(stderr, "%s: Skipping rows in new child indirect block - new_entry = %u\n", FUNC, new_entry); +HDfprintf(stderr, "%s: Reverting root indirect block\n", FUNC); #endif /* QAK */ - /* Add skipped blocks to heap's free space */ - if(H5HF_man_iblock_skip_blocks(hdr, dxpl_id, new_iblock, new_iblock->addr, 0, new_entry) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, NULL, "can't add skipped blocks to heap's free space") - } /* end if */ - - /* Mark new indirect block as modified */ - if(H5HF_iblock_dirty(new_iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, NULL, "can't mark indirect block as dirty") + /* Set up local convenience variables */ + hdr = root_iblock->hdr; + dblock_addr = root_iblock->ents[0].addr; + dblock_size = hdr->man_dtable.cparam.start_block_size; - /* Mark current indirect block as modified */ - if(H5HF_iblock_dirty(iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, NULL, "can't mark indirect block as dirty") + /* Get pointer to last direct block */ + if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, root_iblock, 0, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block") - /* Unprotect child indirect block */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, new_iblock->addr, new_iblock, H5AC__DIRTIED_FLAG) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release fractal heap indirect block") - } /* end else */ + /* Detach direct block from parent */ + if(H5HF_man_iblock_detach(dblock->parent, dxpl_id, dblock->par_entry) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTATTACH, FAIL, "can't detach direct block from parent indirect block") + dblock->parent = NULL; + dblock->par_entry = 0; - /* Get information about new iterator location */ - if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL, - &next_entry, &iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, NULL, "unable to retrieve current block iterator location") + /* Point root at direct block */ + hdr->man_dtable.curr_root_rows = 0; + hdr->man_dtable.table_addr = dblock_addr; - /* Indicate that we walked down */ - walked_down = TRUE; - } /* end if */ - } while(walked_down || walked_up); - } /* end else */ - - /* Get information about iterator location */ -{ - H5HF_indirect_t *iblock; /* Pointer to indirect block */ - unsigned next_row; /* Iterator's next block row */ - unsigned next_entry; /* Iterator's next block entry */ - size_t next_size; /* Size of next direct block to create */ - - if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL, - &next_entry, &iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, NULL, "unable to retrieve current block iterator location") - HDassert(next_row < iblock->nrows); - next_size = hdr->man_dtable.row_block_size[next_row]; - - /* Check for skipping over blocks */ - if(min_dblock_size > next_size) { -HDfprintf(stderr, "%s: Skipping direct block sizes not supported, min_dblock_size = %Zu, next_size = %Zu\n", FUNC, min_dblock_size, next_size); -HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, NULL, "skipping direct block sizes not supported yet") - } /* end if */ - - /* Set entry for new direct block to use */ - *entry_p = next_entry; - - /* Set size of direct block to create */ - *dblock_size = next_size; - - /* Set return value */ - ret_value = iblock; -} + /* Reset 'next block' iterator */ + if(H5HF_hdr_reset_iter(hdr, (hsize_t)dblock_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't reset block iterator") done: + if(dblock && H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block") + FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_man_iblock_place_dblock() */ +} /* end H5HF_man_iblock_root_revert() */ /*------------------------------------------------------------------------- @@ -1132,12 +712,6 @@ H5HF_man_iblock_alloc_range(H5HF_hdr_t *hdr, hid_t dxpl_id, /* Compute info about range */ cur_entry = (old_sec_node->u.range.row * hdr->man_dtable.cparam.width) + old_sec_node->u.range.col; - /* Check for range covering indirect blocks */ - if(old_sec_node->u.range.row >= hdr->man_dtable.max_direct_rows) { -HDfprintf(stderr, "%s: Can't handle range sections over indirect blocks yet\n", FUNC); -HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "'range' free space sections over indirect blocks not supported yet") - } /* end if */ - /* Get a pointer to the indirect block covering the range */ iblock = old_sec_node->u.range.iblock; HDassert(iblock); @@ -1146,42 +720,13 @@ HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "'range' free space sections over i HDfprintf(stderr, "%s: cur_entry = %u\n", FUNC, cur_entry); HDfprintf(stderr, "%s: old_sec_node->u.range.num_entries = %u\n", FUNC, old_sec_node->u.range.num_entries); #endif /* QAK */ -#ifdef QAK -HDfprintf(stderr, "%s: hdr->man_dtable.row_block_size[old_sec_node->u.range.row] = %Hu\n", FUNC, hdr->man_dtable.row_block_size[old_sec_node->u.range.row]); -HDfprintf(stderr, "%s: old_sec_node->sect_addr = %a\n", FUNC, old_sec_node->sect_addr); -#endif /* QAK */ /* Create direct block of appropriate size */ - if(H5HF_man_dblock_create(dxpl_id, hdr, iblock, cur_entry, (size_t)hdr->man_dtable.row_block_size[old_sec_node->u.range.row], (hsize_t)old_sec_node->sect_info.addr, &dblock_addr, &dblock_sec_node) < 0) + if(H5HF_man_dblock_create(dxpl_id, hdr, iblock, cur_entry, &dblock_addr, &dblock_sec_node) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block") - /* Hook direct block up to indirect block */ - iblock->ents[cur_entry].addr = dblock_addr; - - /* Mark indirect block as dirty */ - if(H5HF_iblock_dirty(iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty") - - /* Check for only single block covered in range section */ - if(old_sec_node->u.range.num_entries == 1) { - /* Drop reference count on indirect block that free section is in */ - if(H5HF_iblock_decr(iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block") - - /* Free section structure */ - H5FL_FREE(H5HF_free_section_t, old_sec_node); - } /* end if */ - else { - /* Adjust section information */ - old_sec_node->sect_info.addr += hdr->man_dtable.row_block_size[old_sec_node->u.range.row]; - - /* Adjust range information */ - old_sec_node->u.range.col++; - old_sec_node->u.range.num_entries--; - - /* Add section back to free space list */ - if(H5HF_space_add(hdr, dxpl_id, old_sec_node) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list") - } /* end else */ + /* Reduce (& possibly re-add) 'range' section */ + if(H5HF_sect_range_reduce(hdr, dxpl_id, old_sec_node) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce indirect section node") /* Point 'sec_node' at new direct block section node */ *sec_node = dblock_sec_node; @@ -1217,7 +762,6 @@ H5HF_man_iblock_alloc_indirect(H5HF_hdr_t *hdr, hid_t dxpl_id, haddr_t child_iblock_addr; /* Address of child indirect block */ haddr_t dblock_addr; /* New direct block's address */ H5HF_free_section_t *dblock_sec_node = NULL; /* Pointer to direct block's section node */ - H5HF_free_section_t *range_sec_node = NULL; /* Pointer to new range section node */ H5HF_free_section_t *old_sec_node = *sec_node; /* Pointer to old indirect section node */ unsigned curr_entry; /* Current entry in indirect block */ unsigned dblock_entry; /* Entry of direct block in child indirect block */ @@ -1246,8 +790,10 @@ H5HF_man_iblock_alloc_indirect(H5HF_hdr_t *hdr, hid_t dxpl_id, #ifdef QAK HDfprintf(stderr, "%s: curr_entry = %u\n", FUNC, curr_entry); +HDfprintf(stderr, "%s: iblock->addr = %a\n", FUNC, iblock->addr); +HDfprintf(stderr, "%s: iblock->block_off = %Hu\n", FUNC, iblock->block_off); +HDfprintf(stderr, "%s: iblock->parent = %p\n", FUNC, iblock->parent); HDfprintf(stderr, "%s: iblock->ents[curr_entry].addr = %a\n", FUNC, iblock->ents[curr_entry].addr); -HDfprintf(stderr, "%s: iblock->ents[curr_entry].free_space = %Hu\n", FUNC, iblock->ents[curr_entry].free_space); HDfprintf(stderr, "%s: old_sec_node->u.indirect.indir_nrows = %u\n", FUNC, old_sec_node->u.indirect.indir_nrows); HDfprintf(stderr, "%s: old_sec_node->u.indirect.num_entries = %u\n", FUNC, old_sec_node->u.indirect.num_entries); #endif /* QAK */ @@ -1260,42 +806,16 @@ HDfprintf(stderr, "%s: old_sec_node->u.indirect.num_entries = %u\n", FUNC, old_s HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") } /* end if */ else { - hsize_t new_iblock_off; /* Offset of new indirect block */ - - /* Compute heap offset of new indirect block */ - new_iblock_off = iblock->block_off + - hdr->man_dtable.row_block_off[old_sec_node->u.indirect.row] + - (old_sec_node->u.indirect.col * - hdr->man_dtable.row_block_size[old_sec_node->u.indirect.row]); -#ifdef QAK -HDfprintf(stderr, "%s: iblock->block_off = %Hu\n", FUNC, iblock->block_off); -HDfprintf(stderr, "%s: new_iblock_off = %Hu\n", FUNC, new_iblock_off); -#endif /* QAK */ - /* Create child indirect block */ - if(H5HF_man_iblock_create(hdr, dxpl_id, new_iblock_off, old_sec_node->u.indirect.indir_nrows, old_sec_node->u.indirect.indir_nrows, &child_iblock_addr) < 0) + if(H5HF_man_iblock_create(hdr, dxpl_id, iblock, curr_entry, old_sec_node->u.indirect.indir_nrows, old_sec_node->u.indirect.indir_nrows, &child_iblock_addr) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap indirect block") /* Lock new child indirect block */ if(NULL == (child_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, child_iblock_addr, old_sec_node->u.indirect.indir_nrows, iblock, curr_entry, H5AC_WRITE))) HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") - - /* Set parent information */ - HDassert(child_iblock->parent == NULL); - child_iblock->parent = iblock; - child_iblock->par_entry = curr_entry; - if(H5HF_iblock_incr(iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") #ifdef QAK HDfprintf(stderr, "%s: child_iblock->child_free_space = %Hu\n", FUNC, child_iblock->child_free_space); #endif /* QAK */ - - /* Hook child up to parent indirect block */ - iblock->ents[curr_entry].addr = child_iblock_addr; - - /* Mark parent indirect block as modified */ - if(H5HF_iblock_dirty(iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty") } /* end else */ /* Compute entry for new direct block in child indirect block */ @@ -1308,64 +828,19 @@ HDfprintf(stderr, "%s: old_sec_node->u.indirect.indir_row = %u\n", FUNC, old_sec HDfprintf(stderr, "%s: hdr->man_dtable.row_block_size[old_sec_node->u.indirect.indir_row] = %Hu\n", FUNC, hdr->man_dtable.row_block_size[old_sec_node->u.indirect.indir_row]); HDfprintf(stderr, "%s: old_sec_node->sect_addr = %a\n", FUNC, old_sec_node->sect_addr); #endif /* QAK */ - if(H5HF_man_dblock_create(dxpl_id, hdr, child_iblock, dblock_entry, (size_t)hdr->man_dtable.row_block_size[old_sec_node->u.indirect.indir_row], (hsize_t)old_sec_node->sect_info.addr, &dblock_addr, &dblock_sec_node) < 0) + if(H5HF_man_dblock_create(dxpl_id, hdr, child_iblock, dblock_entry, &dblock_addr, &dblock_sec_node) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block") - /* Hook direct block up to child indirect block */ - child_iblock->ents[dblock_entry].addr = dblock_addr; - - /* Mark child indirect block as modified */ - if(H5HF_iblock_dirty(child_iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty") - - /* Create "range" section for other direct blocks in row of child indirect block */ + if(H5HF_sect_range_add(hdr, dxpl_id, (child_iblock->block_off + hdr->man_dtable.row_block_off[old_sec_node->u.indirect.indir_row] + + hdr->man_dtable.row_block_size[old_sec_node->u.indirect.indir_row]), + old_sec_node->sect_info.size, child_iblock, old_sec_node->u.indirect.indir_row, + 1, hdr->man_dtable.cparam.width - 1) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create range section for indirect block's free space") - /* Create free list section node for blocks skipped over */ - if(NULL == (range_sec_node = H5FL_MALLOC(H5HF_free_section_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") - - /* Set section's information */ - range_sec_node->sect_info.addr = child_iblock->block_off + hdr->man_dtable.row_block_off[old_sec_node->u.indirect.indir_row] - + hdr->man_dtable.row_block_size[old_sec_node->u.indirect.indir_row]; - range_sec_node->sect_info.size = old_sec_node->sect_info.size; - range_sec_node->sect_info.cls = &hdr->sect_cls[H5FS_SECT_FHEAP_RANGE]; - range_sec_node->sect_info.state = H5FS_SECT_LIVE; - range_sec_node->u.range.iblock = child_iblock; - if(H5HF_iblock_incr(child_iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") - range_sec_node->u.range.row = old_sec_node->u.indirect.indir_row; - range_sec_node->u.range.col = 1; - range_sec_node->u.range.num_entries = hdr->man_dtable.cparam.width - 1; - - /* Add new free space to the global list of space */ - if(H5HF_space_add(hdr, dxpl_id, range_sec_node) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list") - - - /* Reduce "indirect" section */ - - /* Check for only single block covered in range section */ - if(old_sec_node->u.indirect.num_entries == 1) { - /* Drop reference count on indirect block that free section is in */ - if(H5HF_iblock_decr(iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block") - - /* Free section structure */ - H5FL_FREE(H5HF_free_section_t, old_sec_node); - } /* end if */ - else { - /* Adjust section information */ - old_sec_node->sect_info.addr += hdr->man_dtable.row_block_size[old_sec_node->u.indirect.row]; - - /* Adjust range information */ - old_sec_node->u.indirect.col++; - old_sec_node->u.indirect.num_entries--; - - /* Add section back to free space list */ - if(H5HF_space_add(hdr, dxpl_id, old_sec_node) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list") - } /* end else */ + /* Reduce (& possibly re-add) 'indirect' section */ + if(H5HF_sect_indirect_reduce(hdr, dxpl_id, old_sec_node) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce indirect section node") /* Release the child indirect block (marked as dirty) */ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, child_iblock_addr, child_iblock, H5AC__DIRTIED_FLAG) < 0) @@ -1392,9 +867,9 @@ done: * *------------------------------------------------------------------------- */ -static herr_t -H5HF_man_iblock_create(H5HF_hdr_t *hdr, hid_t dxpl_id, - hsize_t block_off, unsigned nrows, unsigned max_rows, haddr_t *addr_p) +herr_t +H5HF_man_iblock_create(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_indirect_t *par_iblock, + unsigned par_entry, unsigned nrows, unsigned max_rows, haddr_t *addr_p) { H5HF_indirect_t *iblock = NULL; /* Pointer to indirect block */ size_t u; /* Local index variable */ @@ -1424,16 +899,12 @@ H5HF_man_iblock_create(H5HF_hdr_t *hdr, hid_t dxpl_id, HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared heap header") #ifdef QAK -HDfprintf(stderr, "%s: nrows = %u, max_nrows = %u\n", FUNC, nrows, max_nrows); +HDfprintf(stderr, "%s: nrows = %u, max_rows = %u\n", FUNC, nrows, max_rows); #endif /* QAK */ /* Set info for direct block */ iblock->rc = 0; - iblock->parent = NULL; /* Temporary, except for root indirect block */ - iblock->par_entry = 0; - iblock->block_off = block_off; iblock->nrows = nrows; iblock->max_rows = max_rows; - iblock->dirty = TRUE; /* Compute size of buffer needed for indirect block */ iblock->size = H5HF_MAN_INDIRECT_SIZE(hdr, iblock); @@ -1451,7 +922,26 @@ HDfprintf(stderr, "%s: nrows = %u, max_nrows = %u\n", FUNC, nrows, max_nrows); HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap indirect block") iblock->addr = *addr_p; -/* XXX: Update indirect statistics when they are added */ + /* Attach to parent indirect block, if there is one */ + iblock->parent = par_iblock; + iblock->par_entry = par_entry; + if(iblock->parent) { + /* Attach new block to parent */ + if(H5HF_man_iblock_attach(iblock->parent, par_entry, *addr_p) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTATTACH, FAIL, "can't attach indirect block to parent indirect block") + + /* Compute the indirect block's offset in the heap's address space */ + /* (based on parent's block offset) */ + iblock->block_off = par_iblock->block_off; + iblock->block_off += hdr->man_dtable.row_block_off[par_entry / hdr->man_dtable.cparam.width]; + iblock->block_off += hdr->man_dtable.row_block_size[par_entry / hdr->man_dtable.cparam.width] * (par_entry % hdr->man_dtable.cparam.width); + } /* end if */ + else + iblock->block_off = 0; /* Must be the root indirect block... */ + + /* Update indirect block's statistics */ + iblock->nchildren = 0; + iblock->max_child = 0; /* Cache the new fractal heap header */ if(H5AC_set(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, *addr_p, iblock, H5AC__NO_FLAGS_SET) < 0) @@ -1517,3 +1007,156 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_man_iblock_protect() */ + +/*------------------------------------------------------------------------- + * Function: H5HF_man_iblock_attach + * + * Purpose: Attach a block to an indirect block + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 30 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_man_iblock_attach(H5HF_indirect_t *iblock, unsigned entry, haddr_t child_addr) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_attach) +#ifdef QAK +HDfprintf(stderr, "%s: iblock = %p, entry = %u, child_addr = %a, iblock_nrows = %u\n", FUNC, iblock, entry, child_addr); +#endif /* QAK */ + + /* + * Check arguments. + */ + HDassert(iblock); + HDassert(H5F_addr_defined(child_addr)); + + /* Increment the reference count on this indirect block */ + if(H5HF_iblock_incr(iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") + + /* Point at the direct block */ + iblock->ents[entry].addr = child_addr; + + /* Check for max. entry used */ + if(entry > iblock->max_child) + iblock->max_child = entry; + + /* Increment the # of child blocks */ + iblock->nchildren++; + + /* Mark indirect block as modified */ + if(H5HF_iblock_dirty(iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_man_iblock_attach() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_man_iblock_detach + * + * Purpose: Detach a block from an indirect block + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 31 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_man_iblock_detach(H5HF_indirect_t *iblock, hid_t dxpl_id, unsigned entry) +{ + unsigned start_children; /* # of children of iblock when routine was entered */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_detach) +#ifdef QAK +HDfprintf(stderr, "%s: iblock = %p, entry = %u, dblock_addr = %a, iblock_nrows = %u\n", FUNC, iblock, entry, dblock_addr); +#endif /* QAK */ + + /* + * Check arguments. + */ + HDassert(iblock); + HDassert(iblock->nchildren); + + /* Reset address of entry */ + iblock->ents[entry].addr = HADDR_UNDEF; + + /* Decrement the # of child blocks */ + /* (If the number of children drop to 0, the indirect block will be + * removed from the heap when it's ref. count drops to zero and the + * metadata cache calls the indirect block destructor) + */ + /* (Track the initial # of children before the block gets modified, because + * this routine is called recursively) + */ + start_children = iblock->nchildren; + iblock->nchildren--; + + /* Reduce the max. entry used, if necessary */ + if(entry == iblock->max_child) { + if(iblock->nchildren > 0) + while(!H5F_addr_defined(iblock->ents[iblock->max_child].addr)) + iblock->max_child--; + else + iblock->max_child = 0; + } /* end if */ + + /* If this is the root indirect block handle some special cases */ + if(iblock->block_off == 0) { + /* If the number of children drops to 1, and that child is the first + * direct block in the heap, convert the heap back to using a root + * direct block + */ + if(iblock->nchildren == 1 && H5F_addr_defined(iblock->ents[0].addr)) + if(H5HF_man_iblock_root_revert(iblock, dxpl_id) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't convert root indirect block back to root direct block") + + /* Check for reducing size of root indirect block */ + if(iblock->nchildren > 0 && iblock->hdr->man_dtable.cparam.start_root_rows != 0 + && entry > iblock->max_child) { + unsigned max_child_row; /* Row for max. child entry */ + + /* Compute information needed for determining whether to reduce size of root indirect block */ + max_child_row = iblock->max_child / iblock->hdr->man_dtable.cparam.width; + + /* Check if the root indirect block should be reduced */ + if(iblock->nrows > 1 && max_child_row <= (iblock->nrows / 2)) + if(H5HF_man_iblock_root_halve(iblock, dxpl_id) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce size of root indirect block") + } /* end if */ + } /* end if */ + + /* Free indirect block disk space, if it has no children (i.e. it's been deleted) */ + if(start_children == 1) { + HDassert(iblock->nchildren == 0); + if(H5MF_xfree(iblock->hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, iblock->addr, (hsize_t)iblock->size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block disk space") + } /* end if */ + + /* Mark indirect block as modified */ + if(H5HF_iblock_dirty(iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty") + + /* Decrement the reference count on this indirect block */ + /* (should be last, so that potential 'unpin' on this indirect block + * doesn't invalidate the 'iblock' variable) + */ + if(H5HF_iblock_decr(iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't decrement reference count on shared indirect block") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_man_iblock_detach() */ + diff --git a/src/H5HFint.c b/src/H5HFint.c index 149eacc..c374098 100644 --- a/src/H5HFint.c +++ b/src/H5HFint.c @@ -231,25 +231,17 @@ HDfprintf(stderr, "%s: request = %Zu\n", FUNC, request); if((node_found = H5HF_space_find(hdr, dxpl_id, (hsize_t)request, sec_node)) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't locate free space in fractal heap") - /* If we didn't find a node, go make one big enough to hold the requested block */ - if(!node_found) { -#ifdef QAK -HDfprintf(stderr, "%s: Allocate new direct block\n", FUNC); -#endif /* QAK */ + /* If we didn't find a node, go create a direct block big enough to hold the requested block */ + if(!node_found) /* Allocate direct block big enough to hold requested size */ - if(H5HF_man_dblock_new(hdr, dxpl_id, request) < 0) + if(H5HF_man_dblock_new(hdr, dxpl_id, request, sec_node) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "can't create fractal heap direct block") - /* Request space from the free space */ - /* (Ought to be able to be filled, now) */ - if(H5HF_space_find(hdr, dxpl_id, (hsize_t)request, sec_node) <= 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't locate free space in fractal heap") - } /* end if */ HDassert(*sec_node); #ifdef QAK -HDfprintf(stderr, "%s: (*sec_node)->sect_addr = %a\n", FUNC, (*sec_node)->sect_addr); -HDfprintf(stderr, "%s: (*sec_node)->sect_size = %Zu\n", FUNC, (*sec_node)->sect_size); -HDfprintf(stderr, "%s: (*sec_node)->type = %u\n", FUNC, (unsigned)(*sec_node)->type); +HDfprintf(stderr, "%s: (*sec_node)->sect_info.addr = %a\n", FUNC, (*sec_node)->sect_info.addr); +HDfprintf(stderr, "%s: (*sec_node)->sect_info.size = %Hu\n", FUNC, (*sec_node)->sect_info.size); +HDfprintf(stderr, "%s: (*sec_node)->sect_info.type = %u\n", FUNC, (*sec_node)->sect_info.type); #endif /* QAK */ done: @@ -279,6 +271,9 @@ H5HF_man_insert(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sec_node, herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_insert) +#ifdef QAK +HDfprintf(stderr, "%s: obj_size = %Zu\n", FUNC, obj_size); +#endif /* QAK */ /* * Check arguments. @@ -289,7 +284,7 @@ H5HF_man_insert(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sec_node, HDassert(id); /* Check for indirect section */ - if(sec_node->sect_info.cls->type == H5FS_SECT_FHEAP_INDIRECT) { + if(sec_node->sect_info.type == H5HF_FSPACE_SECT_INDIRECT) { #ifdef QAK HDfprintf(stderr, "%s: sec_node->sect_info.addr = %a\n", FUNC, sec_node->sect_info.addr); HDfprintf(stderr, "%s: sec_node->sect_info.size = %Zu\n", FUNC, sec_node->sect_info.size); @@ -308,7 +303,7 @@ HDfprintf(stderr, "%s: sec_node->u.indirect.indir_nrows = %u\n", FUNC, sec_node- HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't break up indirect free section") } /* end if */ /* Check for range section */ - else if(sec_node->sect_info.cls->type == H5FS_SECT_FHEAP_RANGE) { + else if(sec_node->sect_info.type == H5HF_FSPACE_SECT_RANGE) { #ifdef QAK HDfprintf(stderr, "%s: sec_node->sect_info.addr = %a\n", FUNC, sec_node->sect_info.addr); HDfprintf(stderr, "%s: sec_node->sect_info.size = %Zu\n", FUNC, sec_node->sect_info.size); @@ -323,7 +318,7 @@ HDfprintf(stderr, "%s: sec_node->u.range.num_entries = %u\n", FUNC, sec_node->u. if(H5HF_man_iblock_alloc_range(hdr, dxpl_id, &sec_node) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't break up range free section") } /* end if */ - HDassert(sec_node->sect_info.cls->type == H5FS_SECT_FHEAP_SINGLE); + HDassert(sec_node->sect_info.type == H5HF_FSPACE_SECT_SINGLE); /* Check for serialized 'single' section */ if(sec_node->sect_info.state == H5FS_SECT_SERIALIZED) { @@ -334,8 +329,8 @@ HDfprintf(stderr, "%s: sec_node->u.range.num_entries = %u\n", FUNC, sec_node->u. /* Lock direct block */ #ifdef QAK -HDfprintf(stderr, "%s: sec_node->sect_addr = %a\n", FUNC, sec_node->sect_addr); -HDfprintf(stderr, "%s: sec_node->sect_size = %Zu\n", FUNC, sec_node->sect_size); +HDfprintf(stderr, "%s: sec_node->sect_info.addr = %a\n", FUNC, sec_node->sect_info.addr); +HDfprintf(stderr, "%s: sec_node->sect_info.size = %Hu\n", FUNC, sec_node->sect_info.size); HDfprintf(stderr, "%s: sec_node->u.single.parent = %p\n", FUNC, sec_node->u.single.parent); if(sec_node->u.single.parent) HDfprintf(stderr, "%s: sec_node->u.single.parent->addr = %a\n", FUNC, sec_node->u.single.parent->addr); @@ -365,29 +360,11 @@ HDfprintf(stderr, "%s: dblock->block_off = %Hu\n", FUNC, dblock->block_off); HDassert(sec_node->sect_info.size >= obj_size); #ifdef QAK -HDfprintf(stderr, "%s: sec_node->sect_info.size = %Zu\n", FUNC, sec_node->sect_info.size); +HDfprintf(stderr, "%s: sec_node->sect_info.size = %Hu\n", FUNC, sec_node->sect_info.size); #endif /* QAK */ - if(sec_node->sect_info.size == obj_size) { - /* Drop reference count on parent indirect block of direct block that free section is in */ - HDassert(dblock->parent == NULL || - sec_node->u.single.parent == NULL || - dblock->parent == sec_node->u.single.parent); - if(sec_node->u.single.parent) - if(H5HF_iblock_decr(sec_node->u.single.parent) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block") - - /* Release the memory for the free space section */ - H5FL_FREE(H5HF_free_section_t, sec_node); - } /* end if */ - else { - /* Adjust information for section node */ - sec_node->sect_info.addr += obj_size; - sec_node->sect_info.size -= obj_size; - - /* Re-insert section node into heap's free space */ - if(H5HF_space_add(hdr, dxpl_id, sec_node) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space") - } /* end else */ + /* Reduce (& possibly re-add) single section */ + if(H5HF_sect_single_reduce(hdr, dxpl_id, sec_node, obj_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce single section node") #ifdef QAK HDfprintf(stderr, "%s: blk_off = %Zu\n", FUNC, blk_off); @@ -564,9 +541,9 @@ HDfprintf(stderr, "%s: obj_off = %Hu, obj_len = %Zu\n", FUNC, obj_off, obj_len); HDassert(obj_len > 0); /* Check for bad offset or length */ - if(obj_off > hdr->man_alloc_size) + if(obj_off > hdr->man_size) HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "fractal heap object offset too large") - if(obj_len > hdr->man_dtable.cparam.start_block_size) + if(obj_len > hdr->man_dtable.cparam.max_direct_size) HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "fractal heap object size too large for direct block") if(obj_len > hdr->standalone_size) HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "fractal heap object should be standalone") @@ -623,22 +600,9 @@ HDfprintf(stderr, "%s: blk_off = %Zu\n", FUNC, blk_off); #endif /* QAK */ /* Create free space section node */ - if(NULL == (sec_node = H5FL_MALLOC(H5HF_free_section_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") - - /* Set section's information */ - sec_node->sect_info.addr = obj_off; - sec_node->sect_info.size = obj_len; - sec_node->sect_info.cls = &hdr->sect_cls[H5FS_SECT_FHEAP_SINGLE]; - sec_node->sect_info.state = H5FS_SECT_LIVE; - sec_node->u.single.parent = dblock->parent; - if(dblock->parent) { - if(H5HF_iblock_incr(dblock->parent) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") - } /* end if */ - sec_node->u.single.par_entry = dblock->par_entry; - sec_node->u.single.dblock_addr = dblock_addr; - sec_node->u.single.dblock_size = dblock_size; + if(NULL == (sec_node = H5HF_sect_single_new(obj_off, obj_len, + dblock->parent, dblock->par_entry, dblock_addr, dblock_size))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create section for direct block's free space") /* Unlock direct block */ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__NO_FLAGS_SET) < 0) @@ -647,16 +611,15 @@ HDfprintf(stderr, "%s: blk_off = %Zu\n", FUNC, blk_off); /* Update statistics about heap */ hdr->nobjs--; - hdr->total_man_free += obj_len; + + /* Reduce space available in heap */ + if(H5HF_hdr_adj_free(hdr, (ssize_t)obj_len) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't adjust free space for heap") /* Return free space to the heap's list of space */ if(H5HF_space_return(hdr, dxpl_id, sec_node) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list") - /* Mark heap header as modified */ - if(H5HF_hdr_dirty(hdr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty") - done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_man_remove() */ diff --git a/src/H5HFiter.c b/src/H5HFiter.c index abc592a..ef926e8 100644 --- a/src/H5HFiter.c +++ b/src/H5HFiter.c @@ -138,6 +138,9 @@ H5HF_man_iter_start_offset(H5HF_hdr_t *hdr, hid_t dxpl_id, herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iter_start_offset) +#ifdef QAK +HDfprintf(stderr, "%s: offset = %Hu\n", FUNC, offset); +#endif /* QAK */ /* * Check arguments. @@ -270,7 +273,39 @@ done: /*------------------------------------------------------------------------- - * Function: H5HF_man_iter_start + * Function: H5HF_man_iter_set_entry + * + * Purpose: Set the current entry for the iterator + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 31 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_man_iter_set_entry(const H5HF_hdr_t *hdr, H5HF_block_iter_t *biter, unsigned entry) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_man_iter_set_entry) + + /* + * Check arguments. + */ + HDassert(biter); + + /* Set location context */ + biter->curr->entry = entry; + biter->curr->row = entry / hdr->man_dtable.cparam.width; + biter->curr->col = entry % hdr->man_dtable.cparam.width; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_man_iter_set_entry() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_man_iter_start_entry * * Purpose: Initialize a block iterator to a particular location within * an indirect block @@ -411,32 +446,18 @@ H5HF_man_iter_next(H5HF_hdr_t *hdr, H5HF_block_iter_t *biter, unsigned nentries) HDassert(biter); HDassert(biter->curr); HDassert(biter->curr->context); - - /* Advance to next entry in current block */ HDassert(biter->curr->row < biter->curr->context->nrows); - if(nentries == 1) { - /* Increment block entry */ - biter->curr->entry++; - /* Increment column */ - biter->curr->col++; - - /* Check for walking off end of column */ - if(biter->curr->col == hdr->man_dtable.cparam.width) { - /* Reset column */ - biter->curr->col = 0; - - /* Increment row & block size */ - biter->curr->row++; - } /* end if */ - } /* end if */ - /* Advance multiple entries */ - else { - biter->curr->entry += nentries; - biter->curr->row = biter->curr->entry / hdr->man_dtable.cparam.width; - biter->curr->col = biter->curr->entry % hdr->man_dtable.cparam.width; - } /* end else */ + /* Advance entry in current block */ + biter->curr->entry += nentries; + biter->curr->row = biter->curr->entry / hdr->man_dtable.cparam.width; + biter->curr->col = biter->curr->entry % hdr->man_dtable.cparam.width; /* HDassert(biter->curr->row <= biter->curr->context->nrows); */ +#ifdef QAK +HDfprintf(stderr, "%s: biter->curr->entry = %u\n", "H5HF_man_iter_next", biter->curr->entry); +HDfprintf(stderr, "%s: biter->curr->row = %u\n", "H5HF_man_iter_next", biter->curr->row); +HDfprintf(stderr, "%s: biter->curr->col = %u\n", "H5HF_man_iter_next", biter->curr->col); +#endif /* QAK */ FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5HF_man_iter_next() */ @@ -543,50 +564,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5HF_man_iter_update_iblock - * - * Purpose: Update indirect block for current iterator location - * - * Return: SUCCEED/FAIL - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Apr 24 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5HF_man_iter_update_iblock(H5HF_block_iter_t *biter, H5HF_indirect_t *iblock) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iter_update_iblock) - - /* - * Check arguments. - */ - HDassert(biter); - HDassert(biter->ready); - HDassert(biter->curr); - HDassert(biter->curr->context); - - /* Release hold on current location's indirect block */ - if(H5HF_iblock_decr(biter->curr->context) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block") - - /* Update current location's indirect block */ - biter->curr->context = iblock; - - /* Add hold to current location's indirect block */ - if(H5HF_iblock_incr(biter->curr->context) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_man_iter_update_iblock() */ - - -/*------------------------------------------------------------------------- * Function: H5HF_man_iter_curr * * Purpose: Retrieve information about the current block iterator location diff --git a/src/H5HFpkg.h b/src/H5HFpkg.h index 1927445..f2bcfc4 100644 --- a/src/H5HFpkg.h +++ b/src/H5HFpkg.h @@ -80,6 +80,7 @@ + (h)->sizeof_addr /* File address of free section header */ \ + (h)->sizeof_size /* Total size of heap */ \ + (h)->sizeof_size /* Size of man. space in heap */ \ + + (h)->sizeof_size /* Size of man. space iterator offset in heap */ \ + (h)->sizeof_size /* Size of alloacted man. space in heap */ \ + (h)->sizeof_size /* Size of std. space in heap */ \ + (h)->sizeof_size /* Number of objects in heap */ \ @@ -125,9 +126,9 @@ /* Free space section types for fractal heap */ /* (values stored in free space data structures in file) */ -#define H5FS_SECT_FHEAP_SINGLE 0 /* Section is actual bytes in a direct block */ -#define H5FS_SECT_FHEAP_RANGE 1 /* Section is a range of direct blocks */ -#define H5FS_SECT_FHEAP_INDIRECT 2 /* Section is a range of _indirect_ blocks in an indirect block row */ +#define H5HF_FSPACE_SECT_SINGLE 0 /* Section is actual bytes in a direct block */ +#define H5HF_FSPACE_SECT_RANGE 1 /* Section is a range of direct blocks */ +#define H5HF_FSPACE_SECT_INDIRECT 2 /* Section is a range of _indirect_ blocks in an indirect block row */ /****************************/ /* Package Private Typedefs */ @@ -148,8 +149,10 @@ typedef struct H5HF_dtable_t { */ /* Computed information (not stored) */ - unsigned max_root_rows; /* Maximum # of rows in root indirect block */ - unsigned max_direct_rows; /* Maximum # of direct rows in any indirect block */ + unsigned max_root_rows; /* Maximum # of rows in root indirect block */ + unsigned max_direct_rows; /* Maximum # of direct rows in any indirect block */ + unsigned start_bits; /* # of bits for starting block size (i.e. log2(start_block_size)) */ + unsigned max_direct_bits; /* # of bits for max. direct block size (i.e. log2(max_direct_size)) */ unsigned max_dir_blk_off_size; /* Max. size of offsets in direct blocks */ unsigned first_row_bits; /* # of bits in address of first row */ hsize_t num_id_first_row; /* Number of IDs in first row of table */ @@ -199,7 +202,7 @@ typedef struct H5HF_free_section_t { haddr_t dblock_addr; /* Address of direct block for free section */ size_t dblock_size; /* Size of direct block */ - /* (Needed to retrieve direct block) */ + /* (Needed to retrieve root direct block) */ } single; struct { H5HF_indirect_t *iblock; /* Indirect block for free section */ @@ -235,6 +238,7 @@ typedef struct H5HF_hdr_t { hsize_t total_size; /* Total amount of space used by heap (managed & standalone) */ hsize_t man_size; /* Total amount of managed space in heap */ hsize_t man_alloc_size; /* Total amount of allocated managed space in heap */ + hsize_t man_iter_off; /* Offset of iterator in managed heap space */ hsize_t std_size; /* Total amount of standalone space in heap */ hsize_t nobjs; /* Number of objects in heap */ @@ -247,16 +251,12 @@ typedef struct H5HF_hdr_t { size_t sizeof_size; /* Size of file sizes */ size_t sizeof_addr; /* Size of file addresses */ size_t id_len; /* Size of heap IDs (in bytes) */ - size_t nsect_classes; /* Number of free space section classes */ - H5FS_section_class_t *sect_cls; /* Array of free space section classes */ H5FS_t *fspace; /* Free space list for objects in heap */ - hbool_t fspace_open; /* Whether free space is ready */ H5HF_block_iter_t next_block; /* Block iterator for searching for next block with space */ /* Doubling table information */ /* (Partially set by user, partially derived/updated internally) */ H5HF_dtable_t man_dtable; /* Doubling-table info for managed objects */ - H5HF_dtable_t std_dtable; /* Doubling-table info for standalone objects */ /* Information set by user */ H5HF_addrmap_t addrmap; /* Type of address mapping */ @@ -283,13 +283,14 @@ struct H5HF_indirect_t { /* Internal heap information (not stored) */ size_t rc; /* Reference count of child blocks */ - hbool_t dirty; /* Info is modified */ H5HF_hdr_t *hdr; /* Shared heap header info */ struct H5HF_indirect_t *parent; /* Shared parent indirect block info */ unsigned par_entry; /* Entry in parent's table */ haddr_t addr; /* Address of this indirect block on disk */ unsigned nrows; /* Total # of rows in indirect block */ unsigned max_rows; /* Max. # of rows in indirect block */ + unsigned nchildren; /* Number of child blocks */ + unsigned max_child; /* Max. offset used in child entries */ size_t size; /* Size of indirect block on disk */ /* Stored values */ @@ -320,15 +321,6 @@ struct H5HF_t { unsigned fo_count; /* Open object count for file */ }; -/* Fractal heap metadata statistics info */ -typedef struct H5HF_stat_t { - hsize_t total_size; /* Total size of heap allocated (man & std) */ - hsize_t man_size; /* Total size of managed space in heap */ - hsize_t std_size; /* Total size of standalone space in heap */ - hsize_t man_free_space; /* Free space within heap */ - hsize_t nobjs; /* Number of objects in heap */ -} H5HF_stat_t; - /* Fractal heap "parent info" (for loading a block) */ typedef struct H5HF_parent_t { H5HF_hdr_t *hdr; /* Pointer to heap header info */ @@ -357,13 +349,13 @@ H5_DLLVAR const H5AC_class_t H5AC_FHEAP_DBLOCK[1]; H5_DLLVAR const H5AC_class_t H5AC_FHEAP_IBLOCK[1]; /* H5HF single section inherits serializable properties from H5FS_section_class_t */ -H5_DLLVAR H5FS_section_class_t H5FS_SECT_CLS_FHEAP_SINGLE[1]; +H5_DLLVAR H5FS_section_class_t H5HF_FSPACE_SECT_CLS_SINGLE[1]; /* H5HF range section inherits serializable properties from H5FS_section_class_t */ -H5_DLLVAR H5FS_section_class_t H5FS_SECT_CLS_FHEAP_RANGE[1]; +H5_DLLVAR H5FS_section_class_t H5HF_FSPACE_SECT_CLS_RANGE[1]; /* H5HF indirect section inherits serializable properties from H5FS_section_class_t */ -H5_DLLVAR H5FS_section_class_t H5FS_SECT_CLS_FHEAP_INDIRECT[1]; +H5_DLLVAR H5FS_section_class_t H5HF_FSPACE_SECT_CLS_INDIRECT[1]; /* Declare a free list to manage the H5HF_hdr_t struct */ H5FL_EXTERN(H5HF_hdr_t); @@ -380,9 +372,6 @@ H5FL_EXTERN(H5HF_indirect_t); /* Declare a free list to manage the H5HF_indirect_ent_t sequence information */ H5FL_SEQ_EXTERN(H5HF_indirect_ent_t); -/* Declare a free list to manage the H5HF_free_section_t struct */ -H5FL_EXTERN(H5HF_free_section_t); - /******************************/ /* Package Private Prototypes */ @@ -399,37 +388,53 @@ H5_DLL herr_t H5HF_dtable_dest(H5HF_dtable_t *dtable); H5_DLL herr_t H5HF_dtable_lookup(const H5HF_dtable_t *dtable, hsize_t off, unsigned *row, unsigned *col); H5_DLL unsigned H5HF_dtable_size_to_row(H5HF_dtable_t *dtable, size_t block_size); +H5_DLL unsigned H5HF_dtable_size_to_rows(H5HF_dtable_t *dtable, hsize_t size); /* Heap header routines */ H5_DLL herr_t H5HF_hdr_incr(H5HF_hdr_t *hdr); H5_DLL herr_t H5HF_hdr_decr(H5HF_hdr_t *hdr); H5_DLL herr_t H5HF_hdr_dirty(H5HF_hdr_t *hdr); H5_DLL herr_t H5HF_hdr_adj_free(H5HF_hdr_t *hdr, ssize_t amt); -H5_DLL herr_t H5HF_hdr_extend_heap(H5HF_hdr_t *hdr, hsize_t new_size, hsize_t extra_free); -H5_DLL herr_t H5HF_hdr_inc_alloc(H5HF_hdr_t *hdr, hsize_t new_alloc_size, - unsigned nentries); +H5_DLL herr_t H5HF_hdr_adjust_heap(H5HF_hdr_t *hdr, hsize_t new_size, hssize_t extra_free); +H5_DLL herr_t H5HF_hdr_inc_alloc(H5HF_hdr_t *hdr, size_t alloc_size); +H5_DLL herr_t H5HF_hdr_start_iter(H5HF_hdr_t *hdr, H5HF_indirect_t *iblock, hsize_t curr_off, unsigned curr_entry); +H5_DLL herr_t H5HF_hdr_skip_blocks(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_indirect_t *iblock, unsigned start_entry, unsigned nentries); +H5_DLL herr_t H5HF_hdr_update_iter(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t min_dblock_size); +H5_DLL herr_t H5HF_hdr_inc_iter(H5HF_hdr_t *hdr, hsize_t adv_size, unsigned nentries); +H5_DLL herr_t H5HF_hdr_reverse_iter(H5HF_hdr_t *hdr, hid_t dxpl_id); +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); /* Indirect block routines */ H5_DLL herr_t H5HF_iblock_incr(H5HF_indirect_t *iblock); H5_DLL herr_t H5HF_iblock_decr(H5HF_indirect_t *iblock); H5_DLL herr_t H5HF_iblock_dirty(H5HF_indirect_t *iblock); -H5_DLL H5HF_indirect_t * H5HF_man_iblock_place_dblock(H5HF_hdr_t *fh, hid_t dxpl_id, - size_t min_dblock_size, size_t *entry_p, size_t *dblock_size); +H5_DLL herr_t H5HF_man_iblock_root_create(H5HF_hdr_t *hdr, hid_t dxpl_id, + size_t min_dblock_size); +H5_DLL herr_t H5HF_man_iblock_root_double(H5HF_hdr_t *hdr, hid_t dxpl_id, + size_t min_dblock_size); H5_DLL herr_t H5HF_man_iblock_alloc_range(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t **sec_node); H5_DLL herr_t H5HF_man_iblock_alloc_indirect(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t **sec_node); +H5_DLL herr_t H5HF_man_iblock_create(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_indirect_t *par_iblock, unsigned par_entry, unsigned nrows, + unsigned max_rows, haddr_t *addr_p); H5_DLL H5HF_indirect_t *H5HF_man_iblock_protect(H5HF_hdr_t *hdr, hid_t dxpl_id, haddr_t iblock_addr, unsigned iblock_nrows, H5HF_indirect_t *par_iblock, unsigned par_entry, H5AC_protect_t rw); +H5_DLL herr_t H5HF_man_iblock_attach(H5HF_indirect_t *iblock, unsigned entry, + haddr_t dblock_addr); +H5_DLL herr_t H5HF_man_iblock_detach(H5HF_indirect_t *iblock, hid_t dxpl_id, unsigned entry); /* Direct block routines */ -H5_DLL herr_t H5HF_man_dblock_new(H5HF_hdr_t *fh, hid_t dxpl_id, size_t request); +H5_DLL herr_t H5HF_man_dblock_new(H5HF_hdr_t *fh, hid_t dxpl_id, size_t request, + H5HF_free_section_t **ret_sec_node); H5_DLL herr_t H5HF_man_dblock_create(hid_t dxpl_id, H5HF_hdr_t *hdr, - H5HF_indirect_t *par_iblock, unsigned par_entry, size_t block_size, - hsize_t block_off, haddr_t *addr_p, H5HF_free_section_t **ret_sec_node); + H5HF_indirect_t *par_iblock, unsigned par_entry, haddr_t *addr_p, + H5HF_free_section_t **ret_sec_node); H5_DLL herr_t H5HF_man_dblock_destroy(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_direct_t *dblock, haddr_t dblock_addr); H5_DLL H5HF_direct_t *H5HF_man_dblock_protect(H5HF_hdr_t *hdr, hid_t dxpl_id, @@ -464,21 +469,19 @@ H5_DLL herr_t H5HF_dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, H5_DLL herr_t H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int fwidth, haddr_t hdr_addr, unsigned nrows); -/* Statistics routines */ -H5_DLL herr_t H5HF_stat_info(H5HF_t *fh, H5HF_stat_t *stats); - /* Block iteration routines */ H5_DLL herr_t H5HF_man_iter_init(H5HF_block_iter_t *biter); H5_DLL herr_t H5HF_man_iter_start_offset(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_block_iter_t *biter, hsize_t offset); H5_DLL herr_t H5HF_man_iter_start_entry(H5HF_hdr_t *hdr, H5HF_block_iter_t *biter, H5HF_indirect_t *iblock, unsigned start_entry); +H5_DLL herr_t H5HF_man_iter_set_entry(const H5HF_hdr_t *hdr, + H5HF_block_iter_t *biter, unsigned entry); H5_DLL herr_t H5HF_man_iter_next(H5HF_hdr_t *hdr, H5HF_block_iter_t *biter, unsigned nentries); H5_DLL herr_t H5HF_man_iter_up(H5HF_block_iter_t *biter); H5_DLL herr_t H5HF_man_iter_down(H5HF_block_iter_t *biter, H5HF_indirect_t *iblock); H5_DLL herr_t H5HF_man_iter_reset(H5HF_block_iter_t *biter); -H5_DLL herr_t H5HF_man_iter_update_iblock(H5HF_block_iter_t *biter, H5HF_indirect_t *iblock); H5_DLL herr_t H5HF_man_iter_curr(H5HF_block_iter_t *biter, unsigned *row, unsigned *col, unsigned *entry, H5HF_indirect_t **block); H5_DLL herr_t H5HF_man_iter_offset(H5HF_hdr_t *hdr, H5HF_block_iter_t *biter, @@ -494,19 +497,39 @@ H5_DLL herr_t H5HF_space_add(H5HF_hdr_t *hdr, hid_t dxpl_id, H5_DLL herr_t H5HF_space_return(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *node); H5_DLL herr_t H5HF_space_close(H5HF_hdr_t *hdr, hid_t dxpl_id); +H5_DLL herr_t H5HF_space_delete(H5HF_hdr_t *hdr, hid_t dxpl_id); /* Free space section routines */ +H5_DLL H5HF_free_section_t *H5HF_sect_single_new(hsize_t sect_off, + size_t sect_size, H5HF_indirect_t *parent, unsigned par_entry, + haddr_t dblock_addr, size_t dblock_size); H5_DLL herr_t H5HF_sect_single_revive(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect); +H5_DLL herr_t H5HF_sect_single_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_free_section_t *sect, size_t amt); +H5_DLL herr_t H5HF_sect_range_add(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t sect_off, + hsize_t sect_size, H5HF_indirect_t *iblock, + unsigned row, unsigned col, unsigned nentries); H5_DLL herr_t H5HF_sect_range_revive(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect); +H5_DLL herr_t H5HF_sect_range_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_free_section_t *sect); +H5_DLL herr_t H5HF_sect_indirect_add(H5HF_hdr_t *hdr, hid_t dxpl_id, + hsize_t sect_off, hsize_t sect_size, H5HF_indirect_t *iblock, + unsigned row, unsigned col, unsigned nentries, + unsigned indir_row, unsigned indir_nrows); H5_DLL herr_t H5HF_sect_indirect_revive(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect); +H5_DLL herr_t H5HF_sect_indirect_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_free_section_t *sect); /* Testing routines */ #ifdef H5HF_TESTING H5_DLL herr_t H5HF_get_cparam_test(const H5HF_t *fh, H5HF_create_t *cparam); -H5_DLL size_t H5HF_get_dblock_overhead(const H5HF_t *fh); +H5_DLL unsigned H5HF_get_max_root_rows(const H5HF_t *fh); +H5_DLL unsigned H5HF_get_dtable_width_test(const H5HF_t *fh); +H5_DLL unsigned H5HF_get_dtable_max_drows_test(const H5HF_t *fh); +H5_DLL unsigned H5HF_get_iblock_max_drows_test(const H5HF_t *fh, unsigned pos); H5_DLL hsize_t H5HF_get_dblock_size_test(const H5HF_t *fh, unsigned row); H5_DLL hsize_t H5HF_get_dblock_free_test(const H5HF_t *fh, unsigned row); H5_DLL herr_t H5HF_get_id_off_test(const H5HF_t *fh, const void *id, hsize_t *obj_off); diff --git a/src/H5HFprivate.h b/src/H5HFprivate.h index bb562de..b9ae0f4 100644 --- a/src/H5HFprivate.h +++ b/src/H5HFprivate.h @@ -67,6 +67,17 @@ typedef struct H5HF_create_t { /* (i.e. max. size of object to manage) */ } H5HF_create_t; +/* Fractal heap metadata statistics info */ +typedef struct H5HF_stat_t { + hsize_t total_size; /* Total size of heap allocated (man & std) */ + hsize_t nobjs; /* Number of objects in heap */ + hsize_t man_size; /* Total size of managed space in heap */ + hsize_t man_alloc_size; /* Total size of managed space allocated in heap */ + hsize_t man_iter_off; /* Offset of "new block" iterator in managed heap space */ + hsize_t man_free_space; /* Free space within managed heap */ + hsize_t std_size; /* Total size of standalone space in heap */ +} H5HF_stat_t; + /* Fractal heap info (forward decl - defined in H5HFpkg.h) */ typedef struct H5HF_t H5HF_t; @@ -90,6 +101,9 @@ H5_DLL herr_t H5HF_read(H5HF_t *fh, hid_t dxpl_id, const void *id, H5_DLL herr_t H5HF_remove(H5HF_t *fh, hid_t dxpl_id, const void *id); H5_DLL herr_t H5HF_close(H5HF_t *fh, hid_t dxpl_id); +/* Statistics routines */ +H5_DLL herr_t H5HF_stat_info(const H5HF_t *fh, H5HF_stat_t *stats); + /* Debugging routines */ #ifdef H5HF_DEBUGGING H5_DLL herr_t H5HF_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, diff --git a/src/H5HFsection.c b/src/H5HFsection.c index f164cdb..48e2ddb 100644 --- a/src/H5HFsection.c +++ b/src/H5HFsection.c @@ -52,30 +52,41 @@ /********************/ /* Shared routines */ -static herr_t H5HF_sect_node_alloc(H5FS_section_class_t *sect_cls, - unsigned sect_type, haddr_t sect_addr, hsize_t sect_size, - H5FS_section_info_t **sect); +static H5HF_free_section_t *H5HF_sect_node_new(unsigned sect_type, + haddr_t sect_addr, hsize_t sect_size, H5FS_section_state_t state); static herr_t H5HF_sect_node_free(H5HF_free_section_t *sect, H5HF_indirect_t *parent); +static herr_t H5HF_sect_revive(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_free_section_t *sect); /* 'single' section callbacks */ -static herr_t H5HF_sect_single_deserialize(H5FS_section_class_t *sect_cls, - const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size, - H5FS_section_info_t **sect); -static htri_t H5HF_sect_single_can_merge(const H5FS_section_info_t *sect1, - const H5FS_section_info_t *sect2, void *udata); +static H5FS_section_info_t *H5HF_sect_single_deserialize(const uint8_t *buf, + haddr_t sect_addr, hsize_t sect_size); +static htri_t H5HF_sect_single_can_merge(H5FS_section_info_t *sect1, + H5FS_section_info_t *sect2, void *udata); static herr_t H5HF_sect_single_merge(H5FS_section_info_t *sect1, H5FS_section_info_t *sect2, void *udata); -static htri_t H5HF_sect_single_can_shrink(H5FS_section_info_t *sect, void *udata); -static herr_t H5HF_sect_single_shrink(H5FS_section_info_t **sect, void *udata); +static htri_t H5HF_sect_single_can_shrink(H5FS_section_info_t *sect, + void *udata); static herr_t H5HF_sect_single_free(H5FS_section_info_t *sect); +/* 'range' section routines */ +static herr_t H5HF_sect_range_from_single(H5HF_hdr_t *hdr, + H5HF_free_section_t *sect, H5HF_direct_t *dblock); + /* 'range' section callbacks */ static herr_t H5HF_sect_range_init_cls(H5FS_section_class_t *cls, const void *udata); static herr_t H5HF_sect_range_serialize(const H5FS_section_info_t *sect, uint8_t *buf); -static herr_t H5HF_sect_range_deserialize(H5FS_section_class_t *sect_cls, - const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size, - H5FS_section_info_t **sect); +static H5FS_section_info_t *H5HF_sect_range_deserialize(const uint8_t *buf, + haddr_t sect_addr, hsize_t sect_size); +static htri_t H5HF_sect_range_can_merge(H5FS_section_info_t *sect1, + H5FS_section_info_t *sect2, void *udata); +static herr_t H5HF_sect_range_merge(H5FS_section_info_t *sect1, + H5FS_section_info_t *sect2, void *udata); +static htri_t H5HF_sect_range_can_shrink(H5FS_section_info_t *sect, + void *udata); +static herr_t H5HF_sect_range_shrink(H5FS_section_info_t **sect, + void *udata); static herr_t H5HF_sect_range_free(H5FS_section_info_t *sect); static herr_t H5HF_sect_range_debug(const H5FS_section_info_t *sect, FILE *stream, int indent, int fwidth); @@ -83,9 +94,8 @@ static herr_t H5HF_sect_range_debug(const H5FS_section_info_t *sect, /* 'indirect' section callbacks */ static herr_t H5HF_sect_indirect_init_cls(H5FS_section_class_t *cls, const void *udata); static herr_t H5HF_sect_indirect_serialize(const H5FS_section_info_t *sect, uint8_t *buf); -static herr_t H5HF_sect_indirect_deserialize(H5FS_section_class_t *sect_cls, - const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size, - H5FS_section_info_t **sect); +static H5FS_section_info_t *H5HF_sect_indirect_deserialize(const uint8_t *buf, + haddr_t sect_addr, hsize_t sect_size); static herr_t H5HF_sect_indirect_free(H5FS_section_info_t *sect); static herr_t H5HF_sect_indirect_debug(const H5FS_section_info_t *sect, FILE *stream, int indent, int fwidth); @@ -97,8 +107,8 @@ static herr_t H5HF_sect_indirect_debug(const H5FS_section_info_t *sect, /* Class info for "single" free space sections */ /* (No callbacks necessary) */ -H5FS_section_class_t H5FS_SECT_CLS_FHEAP_SINGLE[1] = {{ - H5FS_SECT_FHEAP_SINGLE, /* Section type */ +H5FS_section_class_t H5HF_FSPACE_SECT_CLS_SINGLE[1] = {{ + H5HF_FSPACE_SECT_SINGLE, /* Section type */ 0, /* Extra serialized size */ NULL, /* Initialize section class */ NULL, /* Serialize section */ @@ -106,29 +116,29 @@ H5FS_section_class_t H5FS_SECT_CLS_FHEAP_SINGLE[1] = {{ H5HF_sect_single_can_merge, /* Can sections merge? */ H5HF_sect_single_merge, /* Merge sections */ H5HF_sect_single_can_shrink, /* Can section shrink container?*/ - H5HF_sect_single_shrink, /* Shrink container w/section */ + NULL, /* Shrink container w/section */ H5HF_sect_single_free, /* Free section */ NULL, /* Dump debugging for section */ }}; /* Class info for "range" free space sections */ -H5FS_section_class_t H5FS_SECT_CLS_FHEAP_RANGE[1] = {{ - H5FS_SECT_FHEAP_RANGE, /* Section type */ +H5FS_section_class_t H5HF_FSPACE_SECT_CLS_RANGE[1] = {{ + H5HF_FSPACE_SECT_RANGE, /* Section type */ 0, /* Extra serialized size */ H5HF_sect_range_init_cls, /* Initialize section class */ H5HF_sect_range_serialize, /* Serialize section */ H5HF_sect_range_deserialize, /* Deserialize section */ - NULL, /* Can sections merge? */ - NULL, /* Merge sections */ - NULL, /* Can section shrink container?*/ - NULL, /* Shrink container w/section */ + H5HF_sect_range_can_merge, /* Can sections merge? */ + H5HF_sect_range_merge, /* Merge sections */ + H5HF_sect_range_can_shrink, /* Can section shrink container?*/ + H5HF_sect_range_shrink, /* Shrink container w/section */ H5HF_sect_range_free, /* Free section */ H5HF_sect_range_debug, /* Dump debugging for section */ }}; /* Class info for "indirect" free space sections */ -H5FS_section_class_t H5FS_SECT_CLS_FHEAP_INDIRECT[1] = {{ - H5FS_SECT_FHEAP_INDIRECT, /* Section type */ +H5FS_section_class_t H5HF_FSPACE_SECT_CLS_INDIRECT[1] = {{ + H5HF_FSPACE_SECT_INDIRECT, /* Section type */ 0, /* Extra serialized size */ H5HF_sect_indirect_init_cls, /* Initialize section class */ H5HF_sect_indirect_serialize, /* Serialize section */ @@ -157,7 +167,7 @@ H5FL_DEFINE(H5HF_free_section_t); /*------------------------------------------------------------------------- - * Function: H5HF_sect_node_alloc + * Function: H5HF_sect_node_new * * Purpose: Allocate a free space section node of a particular type * @@ -170,38 +180,37 @@ H5FL_DEFINE(H5HF_free_section_t); * *------------------------------------------------------------------------- */ -static herr_t -H5HF_sect_node_alloc(H5FS_section_class_t *sect_cls, unsigned sect_type, - haddr_t sect_addr, hsize_t sect_size, H5FS_section_info_t **sect) +static H5HF_free_section_t * +H5HF_sect_node_new(unsigned sect_type, haddr_t sect_addr, hsize_t sect_size, + H5FS_section_state_t sect_state) { H5HF_free_section_t *new_sect; /* New section */ - herr_t ret_value = SUCCEED; /* Return value */ + H5HF_free_section_t *ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_node_alloc) + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_node_new) /* Check arguments. */ HDassert(H5F_addr_defined(sect_addr)); HDassert(sect_size); - HDassert(sect); /* Create free list section node */ if(NULL == (new_sect = H5FL_MALLOC(H5HF_free_section_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for direct block free list section") /* Set the information passed in */ new_sect->sect_info.addr = sect_addr; new_sect->sect_info.size = sect_size; /* Set the section's class & state */ - new_sect->sect_info.cls = §_cls[sect_type]; - new_sect->sect_info.state = H5FS_SECT_SERIALIZED; + new_sect->sect_info.type = sect_type; + new_sect->sect_info.state = sect_state; - /* Update the return parameter */ - *sect = (H5FS_section_info_t *)new_sect; + /* Set return value */ + ret_value = new_sect; done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5HF_sect_node_alloc() */ +} /* H5HF_sect_node_new() */ /*------------------------------------------------------------------------- @@ -241,6 +250,121 @@ done: /*------------------------------------------------------------------------- + * Function: H5HF_sect_revive + * + * Purpose: Revive a section node + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, June 5, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_revive(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_revive) + + /* Sanity check */ + HDassert(hdr); + HDassert(sect); + + /* Call appropriate 'revive' routine */ + switch(sect->sect_info.type) { + case H5HF_FSPACE_SECT_INDIRECT: + if(H5HF_sect_indirect_revive(hdr, dxpl_id, sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive range free section") + break; + + case H5HF_FSPACE_SECT_RANGE: + if(H5HF_sect_range_revive(hdr, dxpl_id, sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive range free section") + break; + + case H5HF_FSPACE_SECT_SINGLE: + if(H5HF_sect_single_revive(hdr, dxpl_id, sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section") + break; + + default: + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "unknown section type") + } /* end switch */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HF_sect_revive() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_single_new + * + * Purpose: Create a new 'single' section and return it to the caller + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 30 2006 + * + *------------------------------------------------------------------------- + */ +H5HF_free_section_t * +H5HF_sect_single_new(hsize_t sect_off, size_t sect_size, + H5HF_indirect_t *parent, unsigned par_entry, + haddr_t dblock_addr, size_t dblock_size) +{ + H5HF_free_section_t *sect = NULL; /* 'Single' free space section to add */ + hbool_t par_incr = FALSE; /* Indicate that parent iblock has been incremented */ + H5HF_free_section_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_new) + + /* + * Check arguments. + */ + HDassert(sect_size); + + /* Create free space section node */ + if(NULL == (sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_SINGLE, sect_off, (hsize_t)sect_size, H5FS_SECT_LIVE))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for single section") + + /* Set the 'single' specific fields */ + sect->u.single.parent = parent; + if(sect->u.single.parent) { + if(H5HF_iblock_incr(sect->u.single.parent) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block") + par_incr = TRUE; + } /* end if */ + sect->u.single.par_entry = par_entry; + sect->u.single.dblock_addr = dblock_addr; + sect->u.single.dblock_size = dblock_size; + + /* Set return value */ + ret_value = sect; + +done: + if(!ret_value && sect) { + /* Check if we should decrement parent ref. count */ + if(par_incr) { + HDassert(sect->u.single.parent); + if(H5HF_iblock_decr(sect->u.single.parent) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTDEC, NULL, "can't decrement reference count on parent indirect block") + } /* end if */ + + /* Release the section */ + H5FL_FREE(H5HF_free_section_t, sect); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_sect_single_new() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_sect_single_revive * * Purpose: Update the memory information for a 'single' free section @@ -313,6 +437,58 @@ done: /*------------------------------------------------------------------------- + * Function: H5HF_sect_single_reduce + * + * Purpose: Reduce the size of a single section (possibly freeing it) + * and re-add it back to the free space manager for the heap + * (if it hasn't been freed) + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 31 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_sect_single_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_free_section_t *sect, size_t amt) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_reduce) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(sect); + HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_SINGLE); + HDassert(sect->sect_info.state == H5FS_SECT_LIVE); + + /* Check for eliminating the section */ + if(sect->sect_info.size == amt) { + /* Free single section */ + if(H5HF_sect_single_free((H5FS_section_info_t *)sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free single section node") + } /* end if */ + else { + /* Adjust information for section */ + sect->sect_info.addr += amt; + sect->sect_info.size -= amt; + + /* Re-insert section node into heap's free space */ + if(H5HF_space_add(hdr, dxpl_id, sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't re-add single section to free space manager") + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_sect_single_reduce() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_sect_single_deserialize * * Purpose: Deserialize a buffer into a "live" single section @@ -326,12 +502,12 @@ done: * *------------------------------------------------------------------------- */ -static herr_t -H5HF_sect_single_deserialize(H5FS_section_class_t *sect_cls, - const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size, - H5FS_section_info_t **sect) +static H5FS_section_info_t * +H5HF_sect_single_deserialize(const uint8_t *buf, haddr_t sect_addr, + hsize_t sect_size) { - herr_t ret_value = SUCCEED; /* Return value */ + H5HF_free_section_t *new_sect; /* New section */ + H5FS_section_info_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_deserialize) @@ -339,11 +515,13 @@ H5HF_sect_single_deserialize(H5FS_section_class_t *sect_cls, HDassert(buf); HDassert(H5F_addr_defined(sect_addr)); HDassert(sect_size); - HDassert(sect); /* Create free list section node */ - if(H5HF_sect_node_alloc(sect_cls, H5FS_SECT_FHEAP_SINGLE, sect_addr, sect_size, sect) < 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "allocation failed for direct block free list section") + if(NULL == (new_sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_SINGLE, sect_addr, sect_size, H5FS_SECT_SERIALIZED))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "allocation failed for direct block free list section") + + /* Set return value */ + ret_value = (H5FS_section_info_t *)new_sect; done: FUNC_LEAVE_NOAPI(ret_value) @@ -367,32 +545,87 @@ done: *------------------------------------------------------------------------- */ static htri_t -H5HF_sect_single_can_merge(const H5FS_section_info_t *sect1, - const H5FS_section_info_t *sect2, void UNUSED *udata) +H5HF_sect_single_can_merge(H5FS_section_info_t *_sect1, + H5FS_section_info_t *_sect2, void *_udata) { + H5HF_free_section_t *sect1 = (H5HF_free_section_t *)_sect1; /* Fractal heap free section */ + H5HF_free_section_t *sect2 = (H5HF_free_section_t *)_sect2; /* Fractal heap free section */ + H5HF_add_ud1_t *udata = (H5HF_add_ud1_t *)_udata; /* User callback data */ + H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */ + size_t dblock_size; /* Section's direct block's size */ + size_t dblock_overhead; /* Direct block's overhead */ + hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */ htri_t ret_value = FALSE; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_single_can_merge) + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_can_merge) /* Check arguments. */ HDassert(sect1); HDassert(sect2); - HDassert(H5F_addr_lt(sect1->addr, sect2->addr)); + HDassert(H5F_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr)); + +#ifdef QAK +HDfprintf(stderr, "%s: sect1->sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect1->sect_info.addr, sect1->sect_info.size, sect1->sect_info.type, (sect1->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED")); +HDfprintf(stderr, "%s: sect2->sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect2->sect_info.addr, sect2->sect_info.size, sect2->sect_info.type, (sect2->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED")); +#endif /* QAK */ + + /* Check to see if we should revive either section */ + if(sect1->sect_info.state != H5FS_SECT_LIVE) + if(H5HF_sect_single_revive(hdr, dxpl_id, sect1) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section") + if(sect2->sect_info.state != H5FS_SECT_LIVE) + if(H5HF_sect_revive(hdr, dxpl_id, sect2) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive free section") + /* Check for section occupying entire direct block */ + dblock_size = sect1->u.single.dblock_size; + dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr); #ifdef QAK -HDfprintf(stderr, "%s: sect1->size = %Hu, sect1->addr = %a\n", "H5HF_sect_single_can_merge", sect1->size, sect1->addr); -HDfprintf(stderr, "%s: sect2->size = %Hu, sect2->addr = %a\n", "H5HF_sect_single_can_merge", sect2->size, sect2->addr); +HDfprintf(stderr, "%s: dblock_size = %u\n", FUNC, dblock_size); #endif /* QAK */ + if((dblock_size - dblock_overhead) == sect1->sect_info.size) { + H5HF_direct_t *dblock; /* Pointer to direct block for section */ + haddr_t dblock_addr; /* Section's direct block's address */ + + /* Protect the direct block for the section */ + dblock_addr = sect1->u.single.dblock_addr; +#ifdef QAK +HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr); +#endif /* QAK */ + if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, sect1->u.single.parent, sect1->u.single.par_entry, H5AC_READ))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block") + HDassert(H5F_addr_eq(dblock->block_off + dblock_overhead, sect1->sect_info.addr)); + + /* Convert 'single' section into 'range' section */ + if(H5HF_sect_range_from_single(hdr, sect1, dblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTCONVERT, FAIL, "can't convert single section into range section") + + /* Destroy direct block */ + if(H5HF_man_dblock_destroy(hdr, dxpl_id, dblock, dblock_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release direct block") + dblock = NULL; + + /* Check if second section is a range section */ + if(sect2->sect_info.type == H5HF_FSPACE_SECT_RANGE) { + htri_t status; /* Status from range 'can merge' call */ + + /* Check if two sections can merge now */ + /* (i.e. assumes responsibility for passing along 'can merge' callback) */ + if((status = H5HF_sect_range_can_merge((H5FS_section_info_t *)sect1, (H5FS_section_info_t *)sect2, udata)) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTMERGE, FAIL, "can't check for merging sections") + HGOTO_DONE(status) + } /* end if */ + } /* end if */ /* Single section can only merge with other single sections */ - if(sect1->cls->type != sect2->cls->type) + if(sect1->sect_info.type != sect2->sect_info.type) HGOTO_DONE(FALSE) /* Check if second section adjoins first section */ /* (This can only occurs within a direct block, due to the direct block * overhead at the beginning of a block) */ - if(H5F_addr_eq(sect1->addr + sect1->size, sect2->addr)) + if(H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr)) HGOTO_DONE(TRUE) done: @@ -417,30 +650,40 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5HF_sect_single_merge(H5FS_section_info_t *sect1, H5FS_section_info_t *sect2, +H5HF_sect_single_merge(H5FS_section_info_t *_sect1, H5FS_section_info_t *_sect2, void UNUSED *udata) { + H5HF_free_section_t *sect1 = (H5HF_free_section_t *)_sect1; /* Fractal heap free section */ + H5HF_free_section_t *sect2 = (H5HF_free_section_t *)_sect2; /* Fractal heap free section */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_merge) /* Check arguments. */ HDassert(sect1); + HDassert(sect1->sect_info.state == H5FS_SECT_LIVE); HDassert(sect2); - HDassert(H5F_addr_eq(sect1->addr + sect1->size, sect2->addr)); + HDassert(sect2->sect_info.state == H5FS_SECT_LIVE); + HDassert(H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr)); #ifdef QAK -HDfprintf(stderr, "%s: sect1->size = %Hu, sect1->addr = %a\n", "H5HF_sect_single_merge", sect1->size, sect1->addr); -HDfprintf(stderr, "%s: sect2->size = %Hu, sect2->addr = %a\n", "H5HF_sect_single_merge", sect2->size, sect2->addr); +HDfprintf(stderr, "%s: sect1->sect_info.size = %Hu, sect1->sect_info.addr = %a\n", FUNC, sect1->sect_info.size, sect1->sect_info.addr); +HDfprintf(stderr, "%s: sect2->sect_info.size = %Hu, sect2->sect_info.addr = %a\n", FUNC, sect2->sect_info.size, sect2->sect_info.addr); #endif /* QAK */ /* Add second section's size to first section */ - sect1->size += sect2->size; + sect1->sect_info.size += sect2->sect_info.size; /* Get rid of second section */ - if(H5HF_sect_single_free(sect2) < 0) + if(H5HF_sect_single_free((H5FS_section_info_t *)sect2) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node") + /* Defer checking if 'single' section should be converted into 'range' section + * until next pass through the "can merge" callback, to make certain that + * removing a direct block in the root indirect block gives neighboring + * "range" sections a chance to deserialize. *ick* -QAK + */ + done: FUNC_LEAVE_NOAPI(ret_value) } /* H5HF_sect_single_merge() */ @@ -449,14 +692,18 @@ done: /*------------------------------------------------------------------------- * Function: H5HF_sect_single_can_shrink * - * Purpose: Can this section shrink the heap? + * Purpose: Can this section shrink the container? + * + * Note: This isn't actually shrinking the heap (since that's already + * been done) as much as it's cleaning up _after_ the heap + * shrink. * * Return: Success: non-negative (TRUE/FALSE) * * Failure: negative * * Programmer: Quincey Koziol - * Wednesday, May 17, 2006 + * Monday, June 5, 2006 * *------------------------------------------------------------------------- */ @@ -465,117 +712,66 @@ H5HF_sect_single_can_shrink(H5FS_section_info_t *_sect, void *_udata) { H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Fractal heap free section */ H5HF_add_ud1_t *udata = (H5HF_add_ud1_t *)_udata; /* User callback data */ - H5HF_hdr_t *hdr; /* Fractal heap header */ - H5HF_direct_t *dblock = NULL; /* Pointer to direct block for section */ - haddr_t dblock_addr; /* Section's direct block's address */ + H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */ size_t dblock_size; /* Section's direct block's size */ size_t dblock_overhead; /* Direct block's overhead */ - hid_t dxpl_id; /* DXPL ID for operation */ + hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */ htri_t ret_value = FALSE; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_can_shrink) /* Check arguments. */ HDassert(sect); - HDassert(udata); - HDassert(udata->hdr); + HDassert(sect->sect_info.state == H5FS_SECT_LIVE); #ifdef QAK -HDfprintf(stderr, "%s: sect->sect_info.size = %Hu, sect->sect_info.addr = %a\n", FUNC, sect->sect_info.size, sect->sect_info.addr); +HDfprintf(stderr, "%s: sect->sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect->sect_info.addr, sect->sect_info.size, sect->sect_info.type, (sect->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED")); #endif /* QAK */ - /* Initialize some local convenience variables */ - hdr = udata->hdr; - dxpl_id = udata->dxpl_id; - - /* Revive the section, if it's still serialized */ - if(sect->sect_info.state != H5FS_SECT_LIVE) { + /* Check to see if we should revive section */ + if(sect->sect_info.state != H5FS_SECT_LIVE) if(H5HF_sect_single_revive(hdr, dxpl_id, sect) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section") - } /* end if */ - /* Protect the direct block for the section */ - dblock_addr = sect->u.single.dblock_addr; + /* Check for section occupying entire direct block */ dblock_size = sect->u.single.dblock_size; + dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr); #ifdef QAK -HDfprintf(stderr, "%s: dblock_size = %u, dblock_addr = %a\n", FUNC, dblock_size, dblock_addr); +HDfprintf(stderr, "%s: dblock_size = %u\n", FUNC, dblock_size); #endif /* QAK */ - if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, sect->u.single.parent, sect->u.single.par_entry, H5AC_READ))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block") - - /* Check for section occupying entire direct block */ - dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr); - if(H5F_addr_eq(dblock->block_off + dblock_overhead, sect->sect_info.addr) && - (dblock_size - dblock_overhead) == sect->sect_info.size) { - /* Stash the direct block pointer away for the 'shrink' callback */ - udata->dblock = dblock; - - /* Indicate that the heap can be shrunk */ - HGOTO_DONE(TRUE) - } /* end if */ - -done: - /* Unprotect the direct block, if we aren't going to use it in the 'shrink' callback */ - if(ret_value != TRUE) - if(dblock && H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__NO_FLAGS_SET) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block") - - FUNC_LEAVE_NOAPI(ret_value) -} /* H5HF_sect_single_can_shrink() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_sect_single_shrink - * - * Purpose: Shrink heap w/section - * - * Return: Success: non-negative - * - * Failure: negative - * - * Programmer: Quincey Koziol - * Wednesday, May 17, 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HF_sect_single_shrink(H5FS_section_info_t **_sect, void *_udata) -{ - H5HF_free_section_t **sect = (H5HF_free_section_t **)_sect; /* Fractal heap free section */ - H5HF_add_ud1_t *udata = (H5HF_add_ud1_t *)_udata; /* User callback data */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_shrink) - - /* Check arguments. */ - HDassert(sect); - HDassert(*sect); - HDassert((*sect)->sect_info.state == H5FS_SECT_LIVE); - HDassert(udata); - HDassert(udata->hdr); - HDassert(udata->dblock); + if((dblock_size - dblock_overhead) == sect->sect_info.size) { + H5HF_direct_t *dblock; /* Pointer to direct block for section */ + haddr_t dblock_addr; /* Section's direct block's address */ + htri_t status; /* Status from range 'can shrink' call */ + /* Protect the direct block for the section */ + dblock_addr = sect->u.single.dblock_addr; #ifdef QAK -HDfprintf(stderr, "%s: (*sect)->sect_info.size = %Hu, (*sect)->sect_info.addr = %a\n", "H5HF_sect_single_shrink", (*sect)->sect_info.size, (*sect)->sect_info.addr); +HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr); #endif /* QAK */ - - /* Destroy direct block */ - if(H5HF_man_dblock_destroy(udata->hdr, udata->dxpl_id, udata->dblock, (*sect)->u.single.dblock_addr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release direct block") - - /* Mark section as "dead", since it's direct block is destroyed */ - (*sect)->sect_info.state = H5FS_SECT_SERIALIZED; - - /* Release section */ - if(H5HF_sect_single_free((H5FS_section_info_t *)*sect) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node") - - /* Set section pointer to NULL, to indicate that the section was released */ - *sect = NULL; + if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, sect->u.single.parent, sect->u.single.par_entry, H5AC_READ))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block") + HDassert(H5F_addr_eq(dblock->block_off + dblock_overhead, sect->sect_info.addr)); + + /* Convert 'single' section into 'range' section */ + if(H5HF_sect_range_from_single(hdr, sect, dblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTCONVERT, FAIL, "can't convert single section into range section") + + /* Destroy direct block */ + if(H5HF_man_dblock_destroy(hdr, dxpl_id, dblock, dblock_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release direct block") + dblock = NULL; + + /* Check if section can shrink container now */ + /* (i.e. assumes responsibility for passing along 'can shrink' callback) */ + if((status = H5HF_sect_range_can_shrink((H5FS_section_info_t *)sect, udata)) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't check for shrinking container") + HGOTO_DONE(status) + } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5HF_sect_single_shrink() */ +} /* H5HF_sect_single_can_shrink() */ /*------------------------------------------------------------------------- @@ -592,7 +788,7 @@ done: * *------------------------------------------------------------------------- */ -herr_t +static herr_t H5HF_sect_single_free(H5FS_section_info_t *_sect) { H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Pointer to section to free */ @@ -651,6 +847,72 @@ H5HF_sect_range_init_cls(H5FS_section_class_t *cls, const void UNUSED *udata) /*------------------------------------------------------------------------- + * Function: H5HF_sect_range_add + * + * Purpose: Add a new 'range' section to the free space manager for this + * heap + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 30 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_sect_range_add(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t sect_off, + hsize_t sect_size, H5HF_indirect_t *iblock, + unsigned row, unsigned col, unsigned nentries) +{ + H5HF_free_section_t *sect = NULL; /* 'Range' free space section to add */ + hbool_t iblock_incr = FALSE; /* Indicate that parent iblock has been incremented */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_add) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(iblock); + HDassert(sect_size); + HDassert(nentries); + HDassert(row < hdr->man_dtable.max_direct_rows); /* Can't handle ranges on indirect blocks */ + + /* Create free space section node */ + if(NULL == (sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_RANGE, sect_off, sect_size, H5FS_SECT_LIVE))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for range section") + + /* Set the 'range' specific fields */ + sect->u.range.iblock = iblock; + if(H5HF_iblock_incr(sect->u.range.iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") + iblock_incr = TRUE; + sect->u.range.row = row; + sect->u.range.col = col; + sect->u.range.num_entries = nentries; + + /* Add new free space to the free space manager for this heap */ + if(H5HF_space_add(hdr, dxpl_id, sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add range section to free space manager") + +done: + if(ret_value < 0 && sect) { + /* Check if we should decrement parent ref. count */ + if(iblock_incr) + if(H5HF_iblock_decr(sect->u.range.iblock) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block") + + /* Release the section */ + H5FL_FREE(H5HF_free_section_t, sect); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_sect_range_add() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_sect_range_revive * * Purpose: Update the memory information for a 'range' free section @@ -705,6 +967,104 @@ done: /*------------------------------------------------------------------------- + * Function: H5HF_sect_range_reduce + * + * Purpose: Reduce the size of a range section (possibly freeing it) + * and re-add it back to the free space manager for the heap + * (if it hasn't been freed) + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 31 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_sect_range_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_free_section_t *sect) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_reduce) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(sect); + HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_RANGE); + HDassert(sect->sect_info.state == H5FS_SECT_LIVE); + + /* Check for eliminating the section */ + if(sect->u.range.num_entries == 1) { + /* Free range section */ + if(H5HF_sect_range_free((H5FS_section_info_t *)sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free range section node") + } /* end if */ + else { + /* Adjust section information */ + sect->sect_info.addr += hdr->man_dtable.row_block_size[sect->u.range.row]; + + /* Adjust range information */ + sect->u.range.col++; + sect->u.range.num_entries--; + + /* Add section back to free space list */ + if(H5HF_space_add(hdr, dxpl_id, sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't re-add range section to free space manager") + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_sect_range_reduce() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_range_from_single + * + * Purpose: Convert a 'single' section into a 'range' section + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 31 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_range_from_single(H5HF_hdr_t *hdr, H5HF_free_section_t *sect, + H5HF_direct_t *dblock) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_range_from_single) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(sect); + HDassert(dblock); +#ifdef QAK +HDfprintf(stderr, "%s: sect.sect_info = {%a, %Hu, %u, %s}\n", "H5HF_sect_range_from_single", sect->sect_info.addr, sect->sect_info.size, sect->sect_info.type, (sect->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED")); +HDfprintf(stderr, "%s: dblock->parent = %p\n", "H5HF_sect_range_from_single", dblock->parent); +HDfprintf(stderr, "%s: hdr->man_dtable.curr_root_rows = %u\n", "H5HF_sect_range_from_single", hdr->man_dtable.curr_root_rows); +#endif /* QAK */ + + /* Update information for range block */ + sect->sect_info.addr = dblock->block_off; + sect->sect_info.type = H5HF_FSPACE_SECT_RANGE; + sect->u.range.iblock = dblock->parent; + sect->u.range.row = dblock->par_entry / hdr->man_dtable.cparam.width; + sect->u.range.col = dblock->par_entry % hdr->man_dtable.cparam.width; + sect->u.range.num_entries = 1; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_sect_range_from_single() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_sect_range_serialize * * Purpose: Serialize a "live" range section into a buffer @@ -756,12 +1116,12 @@ H5HF_sect_range_serialize(const H5FS_section_info_t *_sect, uint8_t *buf) * *------------------------------------------------------------------------- */ -static herr_t -H5HF_sect_range_deserialize(H5FS_section_class_t *sect_cls, - const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size, - H5FS_section_info_t **sect) +static H5FS_section_info_t * +H5HF_sect_range_deserialize(const uint8_t *buf, haddr_t sect_addr, + hsize_t sect_size) { - herr_t ret_value = SUCCEED; /* Return value */ + H5HF_free_section_t *new_sect; /* New section */ + H5FS_section_info_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_deserialize) @@ -769,20 +1129,22 @@ H5HF_sect_range_deserialize(H5FS_section_class_t *sect_cls, HDassert(buf); HDassert(H5F_addr_defined(sect_addr)); HDassert(sect_size); - HDassert(sect); /* Create free list section node */ - if(H5HF_sect_node_alloc(sect_cls, H5FS_SECT_FHEAP_RANGE, sect_addr, sect_size, sect) < 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "allocation failed for direct block free list section") + if(NULL == (new_sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_RANGE, sect_addr, sect_size, H5FS_SECT_SERIALIZED))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "allocation failed for direct block free list section") /* Range's row */ - UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.range.row); + UINT16DECODE(buf, new_sect->u.range.row); /* Range's column */ - UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.range.col); + UINT16DECODE(buf, new_sect->u.range.col); /* Range's # of entries */ - UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.range.num_entries); + UINT16DECODE(buf, new_sect->u.range.num_entries); + + /* Set return value */ + ret_value = (H5FS_section_info_t *)new_sect; done: FUNC_LEAVE_NOAPI(ret_value) @@ -790,6 +1152,289 @@ done: /*------------------------------------------------------------------------- + * Function: H5HF_sect_range_can_merge + * + * Purpose: Can two sections of this type merge? + * + * Note: Second section must be "after" first section + * + * Return: Success: non-negative (TRUE/FALSE) + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, June 5, 2006 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5HF_sect_range_can_merge(H5FS_section_info_t *_sect1, + H5FS_section_info_t *_sect2, void *_udata) +{ + H5HF_free_section_t *sect1 = (H5HF_free_section_t *)_sect1; /* Fractal heap free section */ + H5HF_free_section_t *sect2 = (H5HF_free_section_t *)_sect2; /* Fractal heap free section */ + H5HF_add_ud1_t *udata = (H5HF_add_ud1_t *)_udata; /* User callback data */ + H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */ + hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */ + hsize_t sect2_off; /* Offset of second section in heap */ + size_t dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr); /* Direct block's overhead */ + htri_t ret_value = FALSE; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_can_merge) + + /* Check arguments. */ + HDassert(sect1); + HDassert(sect2); + HDassert(H5F_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr)); + +#ifdef QAK +HDfprintf(stderr, "%s: sect1->sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect1->sect_info.addr, sect1->sect_info.size, sect1->sect_info.type, (sect1->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED")); +HDfprintf(stderr, "%s: sect2->sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect2->sect_info.addr, sect2->sect_info.size, sect2->sect_info.type, (sect2->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED")); +#endif /* QAK */ + /* Check to see if we should revive either section */ + if(sect1->sect_info.state != H5FS_SECT_LIVE) + if(H5HF_sect_range_revive(hdr, dxpl_id, sect1) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section") + if(sect2->sect_info.state != H5FS_SECT_LIVE) + if(H5HF_sect_revive(hdr, dxpl_id, sect2) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive free section") + + /* Check for special case of delayed conversion of 2nd section from + * single -> range section + */ + if(sect2->sect_info.type == H5HF_FSPACE_SECT_SINGLE) { + size_t dblock_size; /* Section's direct block's size */ + + /* Check for section occupying entire direct block */ + dblock_size = sect2->u.single.dblock_size; + if((dblock_size - dblock_overhead) == sect2->sect_info.size) { + H5HF_direct_t *dblock; /* Pointer to direct block for section */ + haddr_t dblock_addr; /* Section's direct block's address */ + + /* Protect the direct block for the section */ + dblock_addr = sect2->u.single.dblock_addr; +#ifdef QAK +HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr); +#endif /* QAK */ + if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, sect2->u.single.parent, sect2->u.single.par_entry, H5AC_READ))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block") + HDassert(H5F_addr_eq(dblock->block_off + dblock_overhead, sect2->sect_info.addr)); + + /* Convert 'single' section into 'range' section */ + if(H5HF_sect_range_from_single(hdr, sect2, dblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTCONVERT, FAIL, "can't convert single section into range section") + + /* Destroy direct block */ + if(H5HF_man_dblock_destroy(hdr, dxpl_id, dblock, dblock_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release direct block") + dblock = NULL; +#ifdef QAK +HDfprintf(stderr, "%s: hdr->man_iter_off = %Hu\n", FUNC, hdr->man_iter_off); +#endif /* QAK */ + } /* end if */ + } /* end if */ + +#ifdef QAK +HDfprintf(stderr, "%s: sect1.u.range = {%p, %u, %u, %u}\n", FUNC, sect1->u.range.iblock, sect1->u.range.row, sect1->u.range.col, sect1->u.range.num_entries); +#endif /* QAK */ + + /* Range section can only merge with other range sections */ + if(sect1->sect_info.type != sect2->sect_info.type) + HGOTO_DONE(FALSE) + +#ifdef QAK +HDfprintf(stderr, "%s: sect2.u.range = {%p, %u, %u, %u}\n", FUNC, sect2->u.range.iblock, sect2->u.range.row, sect2->u.range.col, sect2->u.range.num_entries); +HDfprintf(stderr, "%s: sect2.u.range.iblock->nchildren = %u\n", FUNC, sect2->u.range.iblock->nchildren); +#endif /* QAK */ + + /* Check if second section is in indirect block that's being deleted */ + if(sect2->u.range.iblock->nchildren == 0) + HGOTO_DONE(TRUE) + + /* Check if second section is past end of "next block" iterator */ + sect2_off = sect2->u.range.iblock->block_off; + sect2_off += hdr->man_dtable.row_block_off[sect2->u.range.row]; + sect2_off += hdr->man_dtable.row_block_size[sect2->u.range.row] * sect2->u.range.col; +#ifdef QAK +HDfprintf(stderr, "%s: hdr->man_iter_off = %Hu\n", FUNC, hdr->man_iter_off); +HDfprintf(stderr, "%s: sect2.u.range.iblock->block_off = %Hu\n", FUNC, sect2->u.range.iblock->block_off); +HDfprintf(stderr, "%s: hdr->man_dtable.row_block_off[%u] = %Hu\n", FUNC, sect2->u.range.row, hdr->man_dtable.row_block_off[sect2->u.range.row]); +HDfprintf(stderr, "%s: sect2_off = %Hu\n", FUNC, sect2_off); +#endif /* QAK */ + if(sect2_off > hdr->man_iter_off) + HGOTO_DONE(TRUE) + + /* Check if second section adjoins first section & is in the same row */ + if(H5F_addr_eq(sect1->sect_info.addr + (sect1->u.range.num_entries * (sect1->sect_info.size + dblock_overhead)), sect2->sect_info.addr) && + sect1->u.range.row == sect2->u.range.row) + HGOTO_DONE(TRUE) + +done: +#ifdef QAK +HDfprintf(stderr, "%s: ret_value = %t\n", FUNC, ret_value); +#endif /* QAK */ + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HF_sect_range_can_merge() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_range_merge + * + * Purpose: Merge two sections of this type + * + * Note: Second section always merges into first node + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, June 5, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_range_merge(H5FS_section_info_t *_sect1, H5FS_section_info_t *_sect2, + void *_udata) +{ + H5HF_free_section_t *sect1 = (H5HF_free_section_t *)_sect1; /* Fractal heap free section */ + H5HF_free_section_t *sect2 = (H5HF_free_section_t *)_sect2; /* Fractal heap free section */ + H5HF_add_ud1_t *udata = (H5HF_add_ud1_t *)_udata; /* User callback data */ + H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_merge) + + /* Check arguments. */ + HDassert(sect1); + HDassert(sect1->sect_info.state == H5FS_SECT_LIVE); + HDassert(sect1->sect_info.type == H5HF_FSPACE_SECT_RANGE); + HDassert(sect2); + HDassert(sect2->sect_info.state == H5FS_SECT_LIVE); + HDassert(sect2->sect_info.type == H5HF_FSPACE_SECT_RANGE); + +#ifdef QAK +HDfprintf(stderr, "%s: sect1.sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect1->sect_info.addr, sect1->sect_info.size, sect1->sect_info.type, (sect1->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED")); +HDfprintf(stderr, "%s: sect1.u.range = {%p, %u, %u, %u}\n", FUNC, sect1->u.range.iblock, sect1->u.range.row, sect1->u.range.col, sect1->u.range.num_entries); +HDfprintf(stderr, "%s: sect2.sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect2->sect_info.addr, sect2->sect_info.size, sect2->sect_info.type, (sect2->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED")); +HDfprintf(stderr, "%s: sect2.u.range = {%p, %u, %u, %u}\n", FUNC, sect2->u.range.iblock, sect2->u.range.row, sect2->u.range.col, sect2->u.range.num_entries); +#endif /* QAK */ + + /* Add second section's size to first section, if it's in the same row */ + if(sect1->u.range.row == sect2->u.range.row) + sect1->u.range.num_entries += sect2->u.range.num_entries; + + /* Get rid of second section */ + if(H5HF_sect_range_free((H5FS_section_info_t *)sect2) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node") + + /* Check if 'range' section should be converted into 'indirect' section (?) */ + if(sect1->u.range.num_entries == hdr->man_dtable.cparam.width && + sect1->u.range.row >= hdr->man_dtable.max_direct_rows) { +HDfprintf(stderr, "%s: converting range section to indirect section not supported yet!\n", FUNC); +HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "converting range section to indirect section not supported yet") + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HF_sect_range_merge() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_range_can_shrink + * + * Purpose: Can this section shrink the container? + * + * Note: This isn't actually shrinking the heap (since that's already + * been done) as much as it's cleaning up _after_ the heap + * shrink. + * + * Return: Success: non-negative (TRUE/FALSE) + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, June 5, 2006 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5HF_sect_range_can_shrink(H5FS_section_info_t *_sect, void UNUSED *_udata) +{ + const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Fractal heap free section */ + htri_t ret_value = FALSE; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_range_can_shrink) + + /* Check arguments. */ + HDassert(sect); + HDassert(sect->sect_info.state == H5FS_SECT_LIVE); + +#ifdef QAK +HDfprintf(stderr, "%s: sect->sect_info = {%a, %Hu, %u, %s}\n", "H5HF_sect_range_can_shrink", sect->sect_info.addr, sect->sect_info.size, sect->sect_info.type, (sect->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED")); +HDfprintf(stderr, "%s: sect->u.range = {%p, %u, %u, %u}\n", "H5HF_sect_range_can_shrink", sect->u.range.iblock, sect->u.range.row, sect->u.range.col, sect->u.range.num_entries); +if(sect->u.range.iblock != NULL) + HDfprintf(stderr, "%s: sect->u.range.iblock->nchildren = %u\n", "H5HF_sect_range_can_shrink", sect->u.range.iblock->nchildren); +#endif /* QAK */ + + /* If section has no parent, it should go away */ + if(sect->u.range.iblock == NULL) + HGOTO_DONE(TRUE) + + /* If section is in an indirect block with no children, it should go away */ + if(sect->u.range.iblock->nchildren == 0) + HGOTO_DONE(TRUE) + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HF_sect_range_can_shrink() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_range_shrink + * + * Purpose: Shrink container with section + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, June 5, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_range_shrink(H5FS_section_info_t **_sect, void UNUSED *_udata) +{ + H5HF_free_section_t **sect = (H5HF_free_section_t **)_sect; /* Fractal heap free section */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_shrink) + + /* Check arguments. */ + HDassert(sect); + HDassert(*sect); + HDassert((*sect)->sect_info.state == H5FS_SECT_LIVE); + +#ifdef QAK +HDfprintf(stderr, "%s: (*sect).sect_info = {%a, %Hu, %u}\n", FUNC, (*sect)->sect_info.addr, (*sect)->sect_info.size, (*sect)->sect_info.type); +HDfprintf(stderr, "%s: (*sect).u.range = {%p, %u, %u, %u}\n", FUNC, (*sect)->u.range.iblock, (*sect)->u.range.row, (*sect)->u.range.col, (*sect)->u.range.num_entries); +#endif /* QAK */ + + /* Get rid of section */ + if(H5HF_sect_range_free((H5FS_section_info_t *)*sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node") + + /* Indicate that the section has been released */ + *sect = NULL; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HF_sect_range_shrink() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_sect_range_free * * Purpose: Free a 'range' section node @@ -803,7 +1448,7 @@ done: * *------------------------------------------------------------------------- */ -herr_t +static herr_t H5HF_sect_range_free(H5FS_section_info_t *_sect) { H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Pointer to section to free */ @@ -904,6 +1549,74 @@ H5HF_sect_indirect_init_cls(H5FS_section_class_t *cls, const void UNUSED *udata) /*------------------------------------------------------------------------- + * Function: H5HF_sect_indirect_add + * + * Purpose: Add a new 'indirect' section to the free space manager for this + * heap + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 30 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_sect_indirect_add(H5HF_hdr_t *hdr, hid_t dxpl_id, + hsize_t sect_off, hsize_t sect_size, H5HF_indirect_t *iblock, + unsigned row, unsigned col, unsigned nentries, + unsigned indir_row, unsigned indir_nrows) +{ + H5HF_free_section_t *sect = NULL; /* 'Indirect' free space section to add */ + hbool_t iblock_incr = FALSE; /* Indicate that parent iblock has been incremented */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_add) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(iblock); + HDassert(sect_size); + HDassert(nentries); + + /* Create free space section node */ + if(NULL == (sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_INDIRECT, sect_off, sect_size, H5FS_SECT_LIVE))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for indirect section") + + /* Set the 'indirect' specific fields */ + sect->u.indirect.iblock = iblock; + if(H5HF_iblock_incr(sect->u.indirect.iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") + iblock_incr = TRUE; + sect->u.indirect.row = row; + sect->u.indirect.col = col; + sect->u.indirect.num_entries = nentries; + sect->u.indirect.indir_row = indir_row; + sect->u.indirect.indir_nrows = indir_nrows; + + /* Add new free space to the free space manager for the heap */ + if(H5HF_space_add(hdr, dxpl_id, sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect section to free space") + +done: + if(ret_value < 0 && sect) { + /* Check if we should decrement parent ref. count */ + if(iblock_incr) + if(H5HF_iblock_decr(sect->u.indirect.iblock) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block") + + /* Release the section */ + H5FL_FREE(H5HF_free_section_t, sect); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_sect_indirect_add() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_sect_indirect_revive * * Purpose: Update the memory information for a 'indirect' free section @@ -958,6 +1671,61 @@ done: /*------------------------------------------------------------------------- + * Function: H5HF_sect_indirect_reduce + * + * Purpose: Reduce the size of a indirect section (possibly freeing it) + * and re-add it back to the free space manager for the heap + * (if it hasn't been freed) + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 31 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_sect_indirect_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_free_section_t *sect) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_reduce) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(sect); + HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_INDIRECT); + HDassert(sect->sect_info.state == H5FS_SECT_LIVE); + + /* Check for eliminating the section */ + if(sect->u.indirect.num_entries == 1) { + /* Free indirect section */ + if(H5HF_sect_indirect_free((H5FS_section_info_t *)sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node") + } /* end if */ + else { + /* Adjust section information */ + sect->sect_info.addr += hdr->man_dtable.row_block_size[sect->u.indirect.row]; + + /* Adjust range information */ + sect->u.indirect.col++; + sect->u.indirect.num_entries--; + + /* Add 'indirect' section back to free space list */ + if(H5HF_space_add(hdr, dxpl_id, sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't re-add indirect section to free space manager") + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_sect_indirect_reduce() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_sect_indirect_serialize * * Purpose: Serialize a "live" indirect section into a buffer @@ -1015,12 +1783,12 @@ H5HF_sect_indirect_serialize(const H5FS_section_info_t *_sect, uint8_t *buf) * *------------------------------------------------------------------------- */ -static herr_t -H5HF_sect_indirect_deserialize(H5FS_section_class_t *sect_cls, - const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size, - H5FS_section_info_t **sect) +static H5FS_section_info_t * +H5HF_sect_indirect_deserialize(const uint8_t *buf, haddr_t sect_addr, + hsize_t sect_size) { - herr_t ret_value = SUCCEED; /* Return value */ + H5HF_free_section_t *new_sect; /* New section */ + H5FS_section_info_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_deserialize) @@ -1028,26 +1796,28 @@ H5HF_sect_indirect_deserialize(H5FS_section_class_t *sect_cls, HDassert(buf); HDassert(H5F_addr_defined(sect_addr)); HDassert(sect_size); - HDassert(sect); /* Create free list section node */ - if(H5HF_sect_node_alloc(sect_cls, H5FS_SECT_FHEAP_INDIRECT, sect_addr, sect_size, sect) < 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "allocation failed for direct block free list section") + if(NULL == (new_sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_INDIRECT, sect_addr, sect_size, H5FS_SECT_SERIALIZED))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "allocation failed for direct block free list section") /* Range's row */ - UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.indirect.row); + UINT16DECODE(buf, new_sect->u.indirect.row); /* Range's column */ - UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.indirect.col); + UINT16DECODE(buf, new_sect->u.indirect.col); /* Range's # of entries */ - UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.indirect.num_entries); + UINT16DECODE(buf, new_sect->u.indirect.num_entries); /* Range's indirect row */ - UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.indirect.indir_row); + UINT16DECODE(buf, new_sect->u.indirect.indir_row); /* Range's indirect # of rows */ - UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.indirect.indir_nrows); + UINT16DECODE(buf, new_sect->u.indirect.indir_nrows); + + /* Set return value */ + ret_value = (H5FS_section_info_t *)new_sect; done: FUNC_LEAVE_NOAPI(ret_value) @@ -1068,7 +1838,7 @@ done: * *------------------------------------------------------------------------- */ -herr_t +static herr_t H5HF_sect_indirect_free(H5FS_section_info_t *_sect) { H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Pointer to section to free */ diff --git a/src/H5HFspace.c b/src/H5HFspace.c index 91cc742..3519e91 100644 --- a/src/H5HFspace.c +++ b/src/H5HFspace.c @@ -96,10 +96,9 @@ herr_t H5HF_space_start(H5HF_hdr_t *hdr, hid_t dxpl_id) { const H5FS_section_class_t *classes[] = { /* Free space section classes implemented for fractal heap */ - H5FS_SECT_CLS_FHEAP_SINGLE, - H5FS_SECT_CLS_FHEAP_RANGE, - H5FS_SECT_CLS_FHEAP_INDIRECT}; - unsigned u; /* Local index variable */ + H5HF_FSPACE_SECT_CLS_SINGLE, + H5HF_FSPACE_SECT_CLS_RANGE, + H5HF_FSPACE_SECT_CLS_INDIRECT}; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_space_start) @@ -109,25 +108,11 @@ H5HF_space_start(H5HF_hdr_t *hdr, hid_t dxpl_id) */ HDassert(hdr); - /* Allocate space for the section classes for the free list management code to use */ - hdr->nsect_classes = NELMTS(classes); - if(NULL == (hdr->sect_cls = H5FL_SEQ_MALLOC(H5FS_section_class_t, hdr->nsect_classes))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for free space section class array ") - - /* Copy the section classes for this heap */ - /* (Initialization calls will be performed by the free list code) */ - for(u = 0; u < hdr->nsect_classes; u++) { - /* Make certain that section class type can be used as an array index into this array */ - HDassert(u == classes[u]->type); - - HDmemcpy(&hdr->sect_cls[u], classes[u], sizeof(H5FS_section_class_t)); - } /* end for */ - /* Check for creating free space info for the heap */ if(H5F_addr_defined(hdr->fs_addr)) { /* Open an existing free space structure for the heap */ if(NULL == (hdr->fspace = H5FS_open(hdr->f, dxpl_id, hdr->fs_addr, - hdr->nsect_classes, hdr->sect_cls, hdr))) + NELMTS(classes), classes, hdr))) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize free space info") } /* end if */ else { @@ -142,13 +127,10 @@ H5HF_space_start(H5HF_hdr_t *hdr, hid_t dxpl_id) /* Create the free space structure for the heap */ if(NULL == (hdr->fspace = H5FS_create(hdr->f, dxpl_id, &hdr->fs_addr, - &fs_create, hdr->nsect_classes, hdr->sect_cls, hdr))) + &fs_create, NELMTS(classes), classes, hdr))) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize free space info") } /* end else */ - /* Free space for heap is now open */ - hdr->fspace_open = TRUE; - done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_space_start() */ @@ -185,7 +167,7 @@ H5HF_space_find(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t request, H5HF_free_secti HDassert(node); /* Check if the free space for the heap has been initialized */ - if(!hdr->fspace_open) + if(!hdr->fspace) if(H5HF_space_start(hdr, dxpl_id) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize heap free space") @@ -228,7 +210,6 @@ H5HF_space_add(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *node) */ HDassert(hdr); HDassert(node); - HDassert(hdr->fspace_open); HDassert(hdr->fspace); /* Add to the free space for the heap */ @@ -270,7 +251,7 @@ H5HF_space_return(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *node) HDassert(node); /* Check if the free space for the heap has been initialized */ - if(!hdr->fspace_open) + if(!hdr->fspace) if(H5HF_space_start(hdr, dxpl_id) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize heap free space") @@ -316,20 +297,27 @@ H5HF_space_close(H5HF_hdr_t *hdr, hid_t dxpl_id) HDassert(hdr); /* Check if the free space was ever opened */ - if(hdr->fspace_open) { - /* Sanity check */ - HDassert(hdr->fspace); + if(hdr->fspace) { + hsize_t nsects; /* Number of sections for this heap */ + + /* Retrieve the number of sections for this heap */ + if(H5FS_get_sect_count(hdr->fspace, &nsects) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTCOUNT, FAIL, "can't query free space section count") +#ifdef QAK +HDfprintf(stderr, "%s: nsects = %Hu\n", FUNC, nsects); +#endif /* QAK */ /* Close the free space for the heap */ if(H5FS_close(hdr->f, dxpl_id, hdr->fspace) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release free space info") hdr->fspace = NULL; - /* Release the memory for the free space section classes */ - H5FL_SEQ_FREE(H5FS_section_class_t, hdr->sect_cls); - - /* Free space is now closed */ - hdr->fspace_open = FALSE; + /* Check if we can delete the free space manager for this heap */ + if(!nsects) { + if(H5FS_delete(hdr->f, dxpl_id, hdr->fs_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "can't delete free space info") + hdr->fs_addr = HADDR_UNDEF; + } /* end if */ } /* end if */ done: diff --git a/src/H5HFstat.c b/src/H5HFstat.c index 693a6fa..e0e762f 100644 --- a/src/H5HFstat.c +++ b/src/H5HFstat.c @@ -83,7 +83,7 @@ *------------------------------------------------------------------------- */ herr_t -H5HF_stat_info(H5HF_t *fh, H5HF_stat_t *stats) +H5HF_stat_info(const H5HF_t *fh, H5HF_stat_t *stats) { FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_stat_info) @@ -94,6 +94,8 @@ H5HF_stat_info(H5HF_t *fh, H5HF_stat_t *stats) /* Report statistics for fractal heap */ stats->total_size = fh->hdr->total_size; stats->man_size = fh->hdr->man_size; + stats->man_alloc_size = fh->hdr->man_alloc_size; + stats->man_iter_off = fh->hdr->man_iter_off; stats->std_size = fh->hdr->std_size; stats->man_free_space = fh->hdr->total_man_free; stats->nobjs = fh->hdr->nobjs; diff --git a/src/H5HFtest.c b/src/H5HFtest.c index a171acd..5e57af3 100644 --- a/src/H5HFtest.c +++ b/src/H5HFtest.c @@ -102,34 +102,133 @@ H5HF_get_cparam_test(const H5HF_t *fh, H5HF_create_t *cparam) /*------------------------------------------------------------------------- - * Function: H5HF_get_dblock_overhead + * Function: H5HF_get_max_root_rows * - * Purpose: Retrieve the size of direct block overhead + * Purpose: Retrieve the max. # of rows in the root indirect block * - * Return: Success: Size of direct block overhead + * Return: Success: Max. # of rows in root indirect block * * Failure: 0 * * Programmer: Quincey Koziol - * Tuesday, May 9, 2006 + * Monday, May 22, 2006 * *------------------------------------------------------------------------- */ -size_t -H5HF_get_dblock_overhead(const H5HF_t *fh) +unsigned +H5HF_get_max_root_rows(const H5HF_t *fh) { - size_t ret_value; /* Return value */ + unsigned ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_get_dblock_overhead) + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_get_max_root_rows) /* Check arguments. */ HDassert(fh); - /* Return direct block overhead */ - ret_value = H5HF_MAN_ABS_DIRECT_OVERHEAD(fh->hdr); + /* Return max. # of rows in root indirect block */ + ret_value = fh->hdr->man_dtable.max_root_rows; FUNC_LEAVE_NOAPI(ret_value) -} /* H5HF_get_dblock_overhead() */ +} /* H5HF_get_max_root_rows() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_get_dtable_width_test + * + * Purpose: Retrieve the width of the doubling table for a heap + * + * Return: Success: Width of the doubling table + * + * Failure: 0 + * + * Programmer: Quincey Koziol + * Monday, May 22, 2006 + * + *------------------------------------------------------------------------- + */ +unsigned +H5HF_get_dtable_width_test(const H5HF_t *fh) +{ + unsigned ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_get_dtable_width_test) + + /* Check arguments. */ + HDassert(fh); + + /* Return width of doubling table */ + ret_value = fh->hdr->man_dtable.cparam.width; + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HF_get_dtable_width_test() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_get_dtable_max_drows_test + * + * Purpose: Retrieve the max. # of direct block rows in any indirect block + * + * Return: Success: Max. # of direct block rows + * + * Failure: 0 + * + * Programmer: Quincey Koziol + * Monday, May 22, 2006 + * + *------------------------------------------------------------------------- + */ +unsigned +H5HF_get_dtable_max_drows_test(const H5HF_t *fh) +{ + unsigned ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_get_dtable_max_drows_test) + + /* Check arguments. */ + HDassert(fh); + + /* Return max. # of direct blocks in any indirect block */ + ret_value = fh->hdr->man_dtable.max_direct_rows; + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HF_get_dtable_max_drows_test() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_get_iblock_max_drows_test + * + * Purpose: Retrieve the max. # of direct block rows in an indirect block + * + * Note: POS is indexed from 1 and is only really working for the + * 2nd-level indirect blocks (i.e. indirect blocks with + * only direct block children) + * + * Return: Success: Max. # of direct block rows + * + * Failure: 0 + * + * Programmer: Quincey Koziol + * Monday, May 22, 2006 + * + *------------------------------------------------------------------------- + */ +unsigned +H5HF_get_iblock_max_drows_test(const H5HF_t *fh, unsigned pos) +{ + unsigned ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_get_iblock_max_drows_test) + + /* Check arguments. */ + HDassert(fh); + HDassert(pos); + + /* Return max. # of direct blocks in this indirect block row */ + ret_value = pos + (fh->hdr->man_dtable.max_direct_bits - + fh->hdr->man_dtable.first_row_bits) + 1; + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HF_get_iblock_max_drows_test() */ /*------------------------------------------------------------------------- diff --git a/src/H5err.txt b/src/H5err.txt index ca8f515..51807f8 100644 --- a/src/H5err.txt +++ b/src/H5err.txt @@ -218,6 +218,8 @@ MINOR, MPI, H5E_CANTRECV, Can't receive data MINOR, HEAP, H5E_CANTRESTORE, Can't restore condition MINOR, HEAP, H5E_CANTCOMPUTE, Can't compute value MINOR, HEAP, H5E_CANTEXTEND, Can't extend heap's space +MINOR, HEAP, H5E_CANTATTACH, Can't attach object +MINOR, HEAP, H5E_CANTUPDATE, Can't update object # Free space manager errors MINOR, FSPACE, H5E_CANTMERGE, Can't merge objects diff --git a/test/fheap.c b/test/fheap.c index 1f1a000..6cff879 100644 --- a/test/fheap.c +++ b/test/fheap.c @@ -47,21 +47,19 @@ /* #define ALL_INSERT_TESTS */ /* Heap metadata macros */ -#define DBLOCK_OVERHEAD(fh) H5HF_get_dblock_overhead(fh) /* # of bytes in direct block overhead */ -#define HEAP_ID_LEN 12 /* # of bytes to use for heap ID */ -#define DBLOCK_SIZE(fh, r) H5HF_get_dblock_size_test(fh, r) -#define DBLOCK_FREE(fh, r) H5HF_get_dblock_free_test(fh, r) +#define HEAP_ID_LEN 6 /* # of bytes to use for heap ID */ +#define HEAP_MAX_ROOT_ROWS(fh) H5HF_get_max_root_rows(fh) /* Max. # of rows in root indirect block */ +#define DTABLE_WIDTH(fh) H5HF_get_dtable_width_test(fh) /* Width of doubling table for heap */ +#define DTABLE_MAX_DROWS(fh) H5HF_get_dtable_max_drows_test(fh) /* Max. # of direct block rows in any indirect block */ +#define IBLOCK_MAX_DROWS(fh, pos) H5HF_get_iblock_max_drows_test(fh, pos) /* Max. # of direct block rows in a indirect block */ +#define DBLOCK_SIZE(fh, r) H5HF_get_dblock_size_test(fh, r) /* Size of a direct block in a given row */ +#define DBLOCK_FREE(fh, r) H5HF_get_dblock_free_test(fh, r) /* Free space in a direct block of a given row */ const char *FILENAME[] = { "fheap", NULL }; -/* Testing parameters */ -typedef struct fheap_test_param_t { - hbool_t reopen_heap; /* Whether to re-open the heap during the test */ -} fheap_test_param_t; - /* Types of tests to perform */ typedef enum { FHEAP_TEST_NORMAL, /* "Normal" test, with no testing parameters set */ @@ -69,12 +67,57 @@ typedef enum { FHEAP_TEST_NTESTS /* The number of test types, must be last */ } fheap_test_type_t; +/* Order to delete objects */ +typedef enum { + HEAP_DEL_FORWARD, /* Delete objects from 0 -> nobjs */ + HEAP_DEL_REVERSE, /* Delete objects from nobjs -> 0 */ + HEAP_DEL_NDIRS /* The number of different deletion orders, must be last */ +} fheap_test_del_dir_t; + +/* Order to delete objects */ +typedef enum { + HEAP_DEL_DRAIN_ALL, /* Don't drain half of objects first */ + HEAP_DEL_DRAIN_HALF, /* Don't drain half of objects first */ + HEAP_DEL_DRAIN_N /* The number of different ways to drain, must be last */ +} fheap_test_del_drain_t; + +/* Testing parameters */ +typedef struct fheap_test_param_t { + fheap_test_type_t reopen_heap; /* Whether to re-open the heap during the test */ + fheap_test_del_dir_t del_dir; /* Whether to delete objects forward or reverse */ + fheap_test_del_drain_t drain_half; /* Whether to drain half of the objects & refill, when deleting objects */ +} fheap_test_param_t; + +/* Heap state information */ +typedef struct fheap_heap_state_t { + hsize_t heap_size; /* Total size of heap (managed & standalone objects) */ + size_t nobjs; /* # of objects within heap */ + hsize_t man_size; /* Size of managed object heap */ + hsize_t man_alloc_size; /* Size of managed object heap allocated */ + hsize_t man_free_space; /* Managed object free space within heap */ +} fheap_heap_state_t; + +/* Heap IDs to retain */ +typedef struct fheap_heap_ids_t { + size_t num_ids; /* # of heap IDs in array */ + size_t alloc_ids; /* # of heap IDs allocated in array */ + unsigned char *ids; /* Array of object heap IDs */ + size_t *lens; /* Array of object lengths */ + size_t *offs; /* Array of object offsets (in global shared write buffer) */ +} fheap_heap_ids_t; + +/* Local variables */ +unsigned char *shared_wobj_g; /* Pointer to shared write buffer for objects */ +unsigned char *shared_robj_g; /* Pointer to shared read buffer for objects */ +size_t shared_obj_size_g; /* Size of shared objects */ +unsigned char *shared_ids_g = NULL; /* Array of shared object heap IDs */ +size_t *shared_lens_g = NULL; /* Array of shared object lengths */ +size_t *shared_offs_g = NULL; /* Array of shared object offsets */ +size_t shared_alloc_ids_g = 0; /* # of shared heap IDs allocated in array */ /* Local routines */ static int init_small_cparam(H5HF_create_t *cparam); -static int check_stats(H5HF_t *fh, hsize_t total_size, - hsize_t man_size, hsize_t std_size, hsize_t man_free_space, hsize_t nobjs); - +static int check_stats(const H5HF_t *fh, const fheap_heap_state_t *state); /*------------------------------------------------------------------------- @@ -128,32 +171,31 @@ init_small_cparam(H5HF_create_t *cparam) *------------------------------------------------------------------------- */ static int -check_stats(H5HF_t *fh, hsize_t total_size, - hsize_t man_size, hsize_t std_size, hsize_t man_free_space, hsize_t nobjs) +check_stats(const H5HF_t *fh, const fheap_heap_state_t *state) { H5HF_stat_t heap_stats; /* Statistics about the heap */ /* Get statistics for heap and verify they are correct */ if(H5HF_stat_info(fh, &heap_stats) < 0) FAIL_STACK_ERROR - if(heap_stats.total_size != total_size) { - HDfprintf(stdout, "heap_stats.total_size = %Hu, total_size = %Hu\n", heap_stats.total_size, total_size); + if(heap_stats.total_size != state->heap_size) { + HDfprintf(stdout, "heap_stats.total_size = %Hu, state->heap_size = %Hu\n", heap_stats.total_size, state->heap_size); FAIL_STACK_ERROR } /* end if */ - if(heap_stats.man_size != man_size) { - HDfprintf(stdout, "heap_stats.man_size = %Hu, man_size = %Hu\n", heap_stats.man_size, man_size); + if(heap_stats.nobjs != state->nobjs) { + HDfprintf(stdout, "heap_stats.nobjs = %Hu, state->nobjs = %Hu\n", heap_stats.nobjs, state->nobjs); FAIL_STACK_ERROR } /* end if */ - if(heap_stats.std_size != std_size) { - HDfprintf(stdout, "heap_stats.std_size = %Hu, std_size = %Hu\n", heap_stats.std_size, std_size); + if(heap_stats.man_size != state->man_size) { + HDfprintf(stdout, "heap_stats.man_size = %Hu, state->man_size = %Hu\n", heap_stats.man_size, state->man_size); FAIL_STACK_ERROR } /* end if */ - if(heap_stats.man_free_space != man_free_space) { - HDfprintf(stdout, "heap_stats.man_free_space = %Hu, man_free_space = %Hu\n", heap_stats.man_free_space, man_free_space); + if(heap_stats.man_alloc_size != state->man_alloc_size) { + HDfprintf(stdout, "heap_stats.man_alloc_size = %Hu, state->man_alloc_size = %Hu\n", heap_stats.man_alloc_size, state->man_alloc_size); FAIL_STACK_ERROR } /* end if */ - if(heap_stats.nobjs != nobjs) { - HDfprintf(stdout, "heap_stats.nobjs = %Hu, nobjs = %Hu\n", heap_stats.nobjs, nobjs); + if(heap_stats.man_free_space != state->man_free_space) { + HDfprintf(stdout, "heap_stats.man_free_space = %Hu, state->man_free_space = %Hu\n", heap_stats.man_free_space, state->man_free_space); FAIL_STACK_ERROR } /* end if */ @@ -170,6 +212,17 @@ error: * * Purpose: Add an object to heap * + * Note: The following fields in the 'state' structure are set to + * the values expected _after_ any block created for the object: + * heap_size + * man_size + * man_alloc_size + * man_free_space + * + * The following fields in the 'state' structure are set to + * the current state, before any block has been created: + * nobjs + * * Return: Success: 0 * * Failure: 1 @@ -180,207 +233,481 @@ error: *------------------------------------------------------------------------- */ static int -add_obj(H5HF_t *fh, hid_t dxpl, - hsize_t heap_size, hsize_t *free_space, unsigned *nobjs_ptr, - unsigned obj_init, size_t obj_size) +add_obj(H5HF_t *fh, hid_t dxpl, unsigned obj_off, size_t obj_size, + fheap_heap_state_t *state, fheap_heap_ids_t *keep_ids) { unsigned char heap_id[HEAP_ID_LEN]; /* Heap ID for object inserted */ - unsigned char *obj = NULL; /* Buffer for object to insert */ - unsigned char *robj = NULL; /* Buffer for reading object */ - size_t u; /* Local counting variable */ + unsigned char *obj; /* Buffer for object to insert */ /* Sanity check */ - HDassert(nobjs_ptr); - HDassert(free_space); + HDassert(fh); + HDassert(state); /* Initialize object buffer */ - obj = H5MM_malloc(obj_size); - HDassert(obj); - for(u = 0; u < obj_size; u++) - obj[u] = u + obj_init; + obj = &shared_wobj_g[obj_off]; /* Insert object */ HDmemset(heap_id, 0, sizeof(heap_id)); if(H5HF_insert(fh, dxpl, obj_size, obj, heap_id) < 0) FAIL_STACK_ERROR - /* Increment the number of objects */ - (*nobjs_ptr)++; + /* Adjust state of heap */ + state->nobjs++; + state->man_free_space -= obj_size; /* Check free space left in heap */ - *free_space -= obj_size; - if(check_stats(fh, heap_size, heap_size, (hsize_t)0, *free_space, (hsize_t)*nobjs_ptr)) + if(check_stats(fh, state)) FAIL_STACK_ERROR /* Read in object */ - robj = H5MM_malloc(obj_size); - if(H5HF_read(fh, dxpl, heap_id, robj) < 0) + if(H5HF_read(fh, dxpl, heap_id, shared_robj_g) < 0) FAIL_STACK_ERROR - if(HDmemcmp(obj, robj, obj_size)) + if(HDmemcmp(obj, shared_robj_g, obj_size)) FAIL_STACK_ERROR + /* If the heap IDs are to be retained, append them to the list */ + if(keep_ids) { + /* Check for needing to increase size of heap ID array */ + if(keep_ids->num_ids + 1 > keep_ids->alloc_ids) { + keep_ids->alloc_ids = MAX(1024, (keep_ids->alloc_ids * 2)); + if(NULL == (keep_ids->ids = H5MM_realloc(keep_ids->ids, HEAP_ID_LEN * keep_ids->alloc_ids))) + FAIL_STACK_ERROR + if(NULL == (keep_ids->lens = H5MM_realloc(keep_ids->lens, sizeof(size_t) * keep_ids->alloc_ids))) + FAIL_STACK_ERROR + if(NULL == (keep_ids->offs = H5MM_realloc(keep_ids->offs, sizeof(size_t) * keep_ids->alloc_ids))) + FAIL_STACK_ERROR + } /* end if */ + + /* Append the object info onto the array */ + HDmemcpy(&keep_ids->ids[keep_ids->num_ids * HEAP_ID_LEN], obj, HEAP_ID_LEN); + keep_ids->lens[keep_ids->num_ids] = obj_size; + keep_ids->offs[keep_ids->num_ids] = obj_off; + + /* Increment the number of IDs kept */ + keep_ids->num_ids++; + } /* end if */ + /* Operations succeeded */ - H5MM_xfree(obj); - H5MM_xfree(robj); return(0); error: - H5MM_xfree(obj); - H5MM_xfree(robj); return(1); } /* add_obj() */ /*------------------------------------------------------------------------- - * Function: fill_heap + * Function: get_del_string * - * Purpose: Insert (small) objects to fill up the free space in a heap block - * (Generally used to create & fill up a new direct block) + * Purpose: Return string describing the kind of deletion to perform * * Return: Success: 0 * * Failure: 1 * * Programmer: Quincey Koziol - * Tuesday, March 7, 2006 + * Monday, June 6, 2006 + * + *------------------------------------------------------------------------- + */ +static char * +get_del_string(fheap_test_param_t *tparam) +{ + char *str; + + /* Remove half of total objects from heap */ + if(tparam->del_dir == HEAP_DEL_FORWARD) + if(tparam->drain_half == HEAP_DEL_DRAIN_ALL) + str = HDstrdup("(all - forward)"); + else + str = HDstrdup("(half, refill, all - forward)"); + else + if(tparam->drain_half == HEAP_DEL_DRAIN_ALL) + str = HDstrdup("(all - reverse)"); + else + str = HDstrdup("(half, refill, all - reverse)"); + + return(str); +} /* get_del_string() */ + + +/*------------------------------------------------------------------------- + * Function: del_objs_half_refill + * + * Purpose: Remove half of objects from heap and refill + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, June 6, 2006 * *------------------------------------------------------------------------- */ static int -fill_heap(H5HF_t *fh, hid_t dxpl, const H5HF_create_t *cparam, - hsize_t heap_size, size_t block_size, - hsize_t extra_free, unsigned *nobjs_ptr) +del_objs_half_refill(H5F_t *f, hid_t dxpl, H5HF_t **fh, fheap_test_param_t *tparam, + fheap_heap_state_t *state, fheap_heap_ids_t *keep_ids) { - H5HF_stat_t heap_stats; /* Statistics about the heap */ - hsize_t free_space; /* Size of free space in heap */ - unsigned char obj[SMALL_OBJ_SIZE1]; /* Buffer for object to insert */ - unsigned char robj[SMALL_OBJ_SIZE1]; /* Buffer for reading object */ - size_t num_ids = 0; /* # of heap IDs in array */ - size_t alloc_ids = 0; /* # of heap IDs allocated in array */ - unsigned char *ids = NULL; /* Array of heap IDs */ - size_t data_size; /* Size of data portion of heap block */ - size_t last_obj_len; /* Size of last object inserted into heap */ - unsigned u, v; /* Local index variable */ + unsigned char *wobj; /* Buffer for object to insert */ + haddr_t fh_addr; /* Address of fractal heap */ + size_t half_nobjs; /* Half of total # of objects */ + size_t obj_idx; /* Index of the object to remove */ + size_t u; /* Local index variable */ /* Sanity check */ - HDassert(nobjs_ptr); + HDassert(fh); + HDassert(*fh); + HDassert(state); + HDassert(keep_ids); + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + if(H5HF_get_heap_addr(*fh, &fh_addr) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR + } /* end if */ - /* Initialize variables */ - data_size = block_size - DBLOCK_OVERHEAD(fh); + /* Remove half of total objects from heap */ + if(tparam->del_dir == HEAP_DEL_FORWARD) + obj_idx = 0; + else + obj_idx = state->nobjs - 1; + half_nobjs = state->nobjs / 2; + for(u = 0; u < half_nobjs; u++) { + /* Remove object from heap */ + if(H5HF_remove(*fh, dxpl, &keep_ids->ids[HEAP_ID_LEN * obj_idx]) < 0) + FAIL_STACK_ERROR - /* Initialize object buffer */ - for(u = 0; u < sizeof(obj); u++) - obj[u] = u; + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close (empty) heap */ + if(H5HF_close(*fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (*fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ - /* Increment object count */ - num_ids++; + /* Adjust index of object to delete next */ + if(tparam->del_dir == HEAP_DEL_FORWARD) + obj_idx++; + else + obj_idx--; + } /* end for */ - /* Check for needing to increase size of heap ID array */ - if(num_ids > alloc_ids) { - alloc_ids = MAX(1024, (alloc_ids * 2)); - if(NULL == (ids = H5MM_realloc(ids, HEAP_ID_LEN * alloc_ids))) + /* Re-insert half of total objects back into heap */ + if(tparam->del_dir == HEAP_DEL_FORWARD) + obj_idx = 0; + else + obj_idx = state->nobjs - 1; + for(u = 0; u < half_nobjs; u++) { + /* Re-insert object */ + wobj = &shared_wobj_g[keep_ids->offs[obj_idx]]; + if(H5HF_insert(*fh, dxpl, keep_ids->lens[obj_idx], wobj, &keep_ids->ids[HEAP_ID_LEN * obj_idx]) < 0) + FAIL_STACK_ERROR + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close (empty) heap */ + if(H5HF_close(*fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (*fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Adjust index of object to delete next */ + if(tparam->del_dir == HEAP_DEL_FORWARD) + obj_idx++; + else + obj_idx--; + } /* end for */ + + /* Operations succeeded */ + return(0); + +error: + return(1); +} /* del_objs_half_refill() */ + + +/*------------------------------------------------------------------------- + * Function: del_objs + * + * Purpose: Remove objects from heap + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, June 6, 2006 + * + *------------------------------------------------------------------------- + */ +static int +del_objs(H5F_t *f, hid_t dxpl, H5HF_t **fh, fheap_test_param_t *tparam, + fheap_heap_state_t *state, fheap_heap_ids_t *keep_ids) +{ + haddr_t fh_addr; /* Address of fractal heap */ + size_t obj_idx; /* Index of the object to remove */ + size_t u; /* Local index variable */ + + /* Sanity check */ + HDassert(fh); + HDassert(*fh); + HDassert(state); + HDassert(keep_ids); + + /* Check for first deleting half of objects & then re-inserting them */ + if(tparam->drain_half == HEAP_DEL_DRAIN_HALF) + if(del_objs_half_refill(f, dxpl, fh, tparam, state, keep_ids)) + FAIL_STACK_ERROR + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + if(H5HF_get_heap_addr(*fh, &fh_addr) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR } /* end if */ - /* Insert first object */ - if(H5HF_insert(fh, dxpl, sizeof(obj), obj, &ids[(num_ids - 1) * HEAP_ID_LEN]) < 0) - FAIL_STACK_ERROR + /* Remove all objects from heap */ + if(tparam->del_dir == HEAP_DEL_FORWARD) + obj_idx = 0; + else + obj_idx = state->nobjs - 1; + for(u = 0; u < state->nobjs; u++) { + /* Remove object from heap */ + if(H5HF_remove(*fh, dxpl, &keep_ids->ids[HEAP_ID_LEN * obj_idx]) < 0) + FAIL_STACK_ERROR - free_space = extra_free + (data_size - (num_ids * sizeof(obj))); -#ifdef QAK -HDfprintf(stderr, "extra_free = %Hu\n", extra_free); -HDfprintf(stderr, "free_space = %Hu\n", free_space); -#endif /* QAK */ - if(check_stats(fh, heap_size, heap_size, (hsize_t)0, free_space, (hsize_t)(*nobjs_ptr + num_ids))) - FAIL_STACK_ERROR + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close (empty) heap */ + if(H5HF_close(*fh, dxpl) < 0) + TEST_ERROR - /* Get statistics for heap */ - if(H5HF_stat_info(fh, &heap_stats) < 0) + /* Re-open heap */ + if(NULL == (*fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Adjust index of object to delete next */ + if(tparam->del_dir == HEAP_DEL_FORWARD) + obj_idx++; + else + obj_idx--; + } /* end for */ + + /* Check up on heap... */ + state->heap_size = 0; + state->man_size = 0; + state->man_alloc_size = 0; + state->man_free_space = 0; + state->nobjs = 0; + if(check_stats(*fh, state)) FAIL_STACK_ERROR - /* Loop over inserting objects into the root direct block, until there's no more space */ - while((heap_stats.man_free_space - extra_free) > sizeof(obj)) { - /* Initialize object buffer */ - for(u = 0; u < sizeof(obj); u++) - obj[u] = u + num_ids; + /* Operations succeeded */ + return(0); +error: + return(1); +} /* del_objs() */ + + +/*------------------------------------------------------------------------- + * Function: fill_heap + * + * Purpose: Insert (small) objects to fill up the free space in a heap block + * + * Note: The following fields in the 'state' structure are set to + * the values expected _after_ the block has been created: + * heap_size + * man_size + * man_alloc_size + * man_free_space + * + * The following fields in the 'state' structure are set to + * the current state, before the block has been created: + * nobjs + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Tuesday, March 7, 2006 + * + *------------------------------------------------------------------------- + */ +static int +fill_heap(H5HF_t *fh, hid_t dxpl, unsigned block_row, size_t obj_size, + fheap_heap_state_t *state, fheap_heap_ids_t *keep_ids) +{ + unsigned char *wobj; /* Buffer for object to insert */ + unsigned char *curr_id_ptr; /* Pointer into shared ID array */ + size_t *curr_len_ptr; /* Pointer into shared length array */ + size_t *curr_off_ptr; /* Pointer into shared offset array */ + size_t num_ids = 0; /* # of heap IDs in array */ + size_t data_size; /* Size of data portion of heap block */ + size_t last_obj_len; /* Size of last object inserted into heap */ + size_t obj_off; /* Offset of object in shared write buffer */ + unsigned u; /* Local index variable */ + + /* Sanity check */ + HDassert(fh); + HDassert(state); + HDassert(obj_size + 256 < shared_obj_size_g); + + /* Initialize starting information */ + data_size = DBLOCK_FREE(fh, block_row); + wobj = shared_wobj_g; + curr_id_ptr = shared_ids_g; + curr_len_ptr = shared_lens_g; + curr_off_ptr = shared_offs_g; + obj_off = 0; + + /* Loop over inserting objects into the root direct block, until there's no more space */ + while(data_size >= obj_size) { /* Increment object count */ num_ids++; /* Check for needing to increase size of heap ID array */ - if(num_ids > alloc_ids) { - alloc_ids = MAX(1024, (alloc_ids * 2)); - if(NULL == (ids = H5MM_realloc(ids, HEAP_ID_LEN * alloc_ids))) + if(num_ids > shared_alloc_ids_g) { + shared_alloc_ids_g = MAX(1024, (shared_alloc_ids_g * 2)); + if(NULL == (shared_ids_g = H5MM_realloc(shared_ids_g, HEAP_ID_LEN * shared_alloc_ids_g))) + FAIL_STACK_ERROR + if(NULL == (shared_lens_g = H5MM_realloc(shared_lens_g, sizeof(size_t) * shared_alloc_ids_g))) FAIL_STACK_ERROR + if(NULL == (shared_offs_g = H5MM_realloc(shared_offs_g, sizeof(size_t) * shared_alloc_ids_g))) + FAIL_STACK_ERROR + curr_id_ptr = &shared_ids_g[(num_ids - 1) * HEAP_ID_LEN]; + curr_len_ptr = &shared_lens_g[(num_ids - 1)]; + curr_off_ptr = &shared_offs_g[(num_ids - 1)]; } /* end if */ - if(H5HF_insert(fh, dxpl, sizeof(obj), obj, &ids[(num_ids - 1) * HEAP_ID_LEN]) < 0) + /* Insert object */ + if(H5HF_insert(fh, dxpl, obj_size, wobj, curr_id_ptr) < 0) FAIL_STACK_ERROR + *curr_len_ptr = obj_size; + *curr_off_ptr = obj_off; + + /* Adjust state of heap */ + state->nobjs++; + state->man_free_space -= obj_size; /* Check stats for heap */ - free_space = extra_free + (data_size - (num_ids * sizeof(obj))); -#ifdef QAK -HDfprintf(stderr, "free_space = %Hu\n", free_space); -#endif /* QAK */ - if(check_stats(fh, heap_size, heap_size, (hsize_t)0, free_space, (hsize_t)(num_ids + *nobjs_ptr))) + if(check_stats(fh, state)) FAIL_STACK_ERROR - /* Get statistics for heap */ - if(H5HF_stat_info(fh, &heap_stats) < 0) - FAIL_STACK_ERROR + /* Adjust object & ID pointers */ + wobj++; + obj_off++; + if(obj_off > 255) { + wobj = shared_wobj_g; + obj_off = 0; + } /* end if */ + curr_id_ptr += HEAP_ID_LEN; + curr_len_ptr++; + curr_off_ptr++; + + /* Decrement space left in block */ + data_size -= obj_size; } /* end while */ /* Check for adding smaller last object to heap block */ - if((heap_stats.man_free_space - extra_free) > 0) { - last_obj_len = (size_t)(heap_stats.man_free_space - extra_free); - - /* Initialize object buffer */ - for(u = 0; u < sizeof(obj); u++) - obj[u] = u + num_ids; + if(data_size > 0) { + /* Set size of last object in block */ + last_obj_len = data_size; /* Increment object count */ num_ids++; /* Check for needing to increase size of heap ID array */ - if(num_ids > alloc_ids) { - alloc_ids = MAX(1024, (alloc_ids * 2)); - if(NULL == (ids = H5MM_realloc(ids, HEAP_ID_LEN * alloc_ids))) + if(num_ids > shared_alloc_ids_g) { + shared_alloc_ids_g = MAX(1024, (shared_alloc_ids_g * 2)); + if(NULL == (shared_ids_g = H5MM_realloc(shared_ids_g, HEAP_ID_LEN * shared_alloc_ids_g))) + FAIL_STACK_ERROR + if(NULL == (shared_lens_g = H5MM_realloc(shared_lens_g, sizeof(size_t) * shared_alloc_ids_g))) + FAIL_STACK_ERROR + if(NULL == (shared_offs_g = H5MM_realloc(shared_offs_g, sizeof(size_t) * shared_alloc_ids_g))) FAIL_STACK_ERROR + curr_id_ptr = &shared_ids_g[(num_ids - 1) * HEAP_ID_LEN]; + curr_len_ptr = &shared_lens_g[(num_ids - 1)]; + curr_off_ptr = &shared_offs_g[(num_ids - 1)]; } /* end if */ /* Insert last object into the heap, using the remaining free space */ - if(H5HF_insert(fh, dxpl, last_obj_len, obj, &ids[(num_ids - 1) * HEAP_ID_LEN]) < 0) + if(H5HF_insert(fh, dxpl, last_obj_len, wobj, curr_id_ptr) < 0) FAIL_STACK_ERROR + *curr_len_ptr = last_obj_len; + *curr_off_ptr = obj_off; + + /* Adjust state of heap */ + state->nobjs++; + state->man_free_space -= last_obj_len; /* Verify that the heap is full */ - if(check_stats(fh, heap_size, heap_size, (hsize_t)0, extra_free, (hsize_t)(num_ids + *nobjs_ptr))) + if(check_stats(fh, state)) FAIL_STACK_ERROR } /* end if */ else - last_obj_len = sizeof(obj); /* Normal sized last object */ + last_obj_len = obj_size; /* Normal sized last object */ /* Verify reading the objects written out */ - for(v = 0; v < num_ids; v++) { - /* Initialize object buffer */ - for(u = 0; u < sizeof(obj); u++) - obj[u] = u + v; + /* Verify all the objects */ + wobj = shared_wobj_g; + curr_id_ptr = shared_ids_g; + curr_len_ptr = shared_lens_g; + curr_off_ptr = shared_offs_g; + for(u = 0; u < num_ids; u++) { /* Read in object */ - if(H5HF_read(fh, dxpl, &ids[v * HEAP_ID_LEN], robj) < 0) + if(H5HF_read(fh, dxpl, curr_id_ptr, shared_robj_g) < 0) FAIL_STACK_ERROR - if(HDmemcmp(obj, robj, (v == (num_ids - 1) ? last_obj_len : sizeof(obj)))) + + /* Check that object is correct */ + wobj = &shared_wobj_g[*curr_off_ptr]; + if(HDmemcmp(wobj, shared_robj_g, *curr_len_ptr)) FAIL_STACK_ERROR + + /* Adjust object & ID pointers */ + curr_id_ptr += HEAP_ID_LEN; + curr_len_ptr++; + curr_off_ptr++; } /* end for */ - /* Set the number of objects inserted */ - *nobjs_ptr += num_ids; + /* If the heap IDs are to be retained, append them to the list */ + if(keep_ids) { + /* Check for needing to increase size of heap ID array */ + if(keep_ids->num_ids + num_ids > keep_ids->alloc_ids) { + keep_ids->alloc_ids = MAX(1024, (keep_ids->alloc_ids * 2)); + if(NULL == (keep_ids->ids = H5MM_realloc(keep_ids->ids, HEAP_ID_LEN * keep_ids->alloc_ids))) + FAIL_STACK_ERROR + if(NULL == (keep_ids->lens = H5MM_realloc(keep_ids->lens, sizeof(size_t) * keep_ids->alloc_ids))) + FAIL_STACK_ERROR + if(NULL == (keep_ids->offs = H5MM_realloc(keep_ids->offs, sizeof(size_t) * keep_ids->alloc_ids))) + FAIL_STACK_ERROR + } /* end if */ + + /* Append the IDs onto the array */ + HDmemcpy(&keep_ids->ids[keep_ids->num_ids * HEAP_ID_LEN], shared_ids_g, (num_ids * HEAP_ID_LEN)); + HDmemcpy(&keep_ids->lens[keep_ids->num_ids], shared_lens_g, (num_ids * sizeof(size_t))); + HDmemcpy(&keep_ids->offs[keep_ids->num_ids], shared_offs_g, (num_ids * sizeof(size_t))); + + /* Increment the number of IDs kept */ + keep_ids->num_ids += num_ids; + } /* end if */ /* Operations succeeded */ - H5MM_xfree(ids); return(0); error: - H5MM_xfree(ids); return(1); } /* fill_heap() */ @@ -400,30 +727,27 @@ error: *------------------------------------------------------------------------- */ static int -fill_root_row(H5HF_t *fh, hid_t dxpl, const H5HF_create_t *cparam, - hsize_t *base_heap_size, hsize_t *base_free_space, unsigned row, - unsigned *nobjs_ptr) +fill_root_row(H5HF_t *fh, hid_t dxpl, unsigned row, size_t obj_size, + fheap_heap_state_t *state, fheap_heap_ids_t *keep_ids) { hsize_t first_free_space; /* Size of free space in heap after the first block */ hsize_t all_free_space; /* Size of free space in heap after all blocks */ - hsize_t free_space; /* Size of free space in heap */ hsize_t first_heap_size; /* Total size of the heap after the first block */ hsize_t all_heap_size; /* Total size of the heap after all blocks */ - hsize_t heap_size; /* Total size of the heap */ size_t block_size; /* Block size for row */ + size_t block_free; /* Free space in empty block of this row */ + unsigned width; /* Width of heap's doubling table */ unsigned expand_rows; /* # of rows to expand heap by */ unsigned u; /* Local index variable */ /* Sanity check */ - HDassert(nobjs_ptr); - HDassert(base_heap_size); - HDassert(base_free_space); + HDassert(fh); + HDassert(state); - /* Get the correct size for blocks in this row */ - if(row == 0) - block_size = cparam->managed.start_block_size; - else - block_size = cparam->managed.start_block_size * (1 << (row - 1)); + /* Get some information for the heap */ + block_size = DBLOCK_SIZE(fh, row); + block_free = DBLOCK_FREE(fh, row); + width = DTABLE_WIDTH(fh); /* Compute the number of rows to expand heap by */ if(row < 2) @@ -434,55 +758,51 @@ fill_root_row(H5HF_t *fh, hid_t dxpl, const H5HF_create_t *cparam, expand_rows = 0; /* Compute first block & all blocks heap size & free space */ - if(*base_heap_size == 0) { + if(state->heap_size == 0) { first_heap_size = block_size; - first_free_space = DBLOCK_FREE(fh, row); - all_heap_size = cparam->managed.width * block_size; - all_free_space = (cparam->managed.width - 1) * DBLOCK_FREE(fh, row); + first_free_space = block_free; + all_heap_size = width * block_size; + all_free_space = (width - 1) * block_free; } /* end if */ - else if(expand_rows ==0) { - all_heap_size = *base_heap_size; - all_free_space = *base_free_space; + else if(expand_rows == 0) { + all_heap_size = state->heap_size; + all_free_space = state->man_free_space; first_heap_size = all_heap_size; first_free_space = all_free_space; - all_free_space -= DBLOCK_FREE(fh, row); /* Account for shift from first free space */ + all_free_space -= block_free; /* Account for shift from first free space */ } /* end if */ else { - hsize_t block_mult; /* Base block size multiplier */ - - all_heap_size = *base_heap_size; + all_heap_size = state->heap_size; all_free_space = 0; - block_mult = 1; for(u = 0; u < expand_rows; u++) { - all_heap_size += cparam->managed.width * block_size * block_mult; - all_free_space += cparam->managed.width * DBLOCK_FREE(fh, row + u); - block_mult *= 2; + all_heap_size += width * DBLOCK_SIZE(fh, row + u); + all_free_space += width * DBLOCK_FREE(fh, row + u); } /* end for */ first_heap_size = all_heap_size; first_free_space = all_free_space; - all_free_space -= DBLOCK_FREE(fh, row); /* Account for shift from first free space */ + all_free_space -= block_free; /* Account for shift from first free space */ } /* end else */ - /* Loop over filling direct blocks, until first root indirect row is full */ - heap_size = first_heap_size; - free_space = first_free_space; - for(u = 0; u < cparam->managed.width; u++) { + /* Loop over filling direct blocks, until root indirect row is full */ + state->heap_size = first_heap_size; + state->man_size = first_heap_size; + state->man_free_space = first_free_space; + for(u = 0; u < width; u++) { /* Set heap's size & free space correctly */ if(u == 1) { - heap_size = all_heap_size; - free_space = all_free_space; + state->heap_size = all_heap_size; + state->man_size = all_heap_size; + state->man_free_space = all_free_space; } /* end if */ - free_space -= DBLOCK_FREE(fh, row); + + /* Account for new block added */ + state->man_alloc_size += block_size; /* Fill a direct heap block up */ - if(fill_heap(fh, dxpl, cparam, heap_size, block_size, free_space, nobjs_ptr)) + if(fill_heap(fh, dxpl, row, obj_size, state, keep_ids)) FAIL_STACK_ERROR } /* end for */ - /* Update heap size & free space */ - *base_heap_size = heap_size; - *base_free_space = free_space; - /* Operations succeeded */ return(0); @@ -506,29 +826,28 @@ error: *------------------------------------------------------------------------- */ static int -fill_row(H5HF_t *fh, hid_t dxpl, const H5HF_create_t *cparam, - hsize_t *heap_size, hsize_t *free_space, unsigned row, - unsigned *nobjs_ptr) +fill_row(H5HF_t *fh, hid_t dxpl, unsigned row, size_t obj_size, + fheap_heap_state_t *state, fheap_heap_ids_t *keep_ids) { - size_t block_size; /* Block size for row */ + size_t block_size; /* Size of direct block in this row */ + unsigned width; /* Width of heap's doubling table */ unsigned u; /* Local index variable */ /* Sanity check */ - HDassert(nobjs_ptr); - HDassert(heap_size); - HDassert(free_space); + HDassert(fh); + HDassert(state); - /* Get the correct size for blocks in this row */ - if(row == 0) - block_size = cparam->managed.start_block_size; - else - block_size = cparam->managed.start_block_size * (1 << (row - 1)); + /* Get some information for the heap */ + block_size = DBLOCK_SIZE(fh, row); + width = DTABLE_WIDTH(fh); /* Loop over filling direct blocks, until indirect row is full */ - for(u = 0; u < cparam->managed.width; u++) { + for(u = 0; u < width; u++) { + /* Adjust stats for new block */ + state->man_alloc_size += block_size; + /* Fill a direct heap block up */ - *free_space -= DBLOCK_FREE(fh, row); - if(fill_heap(fh, dxpl, cparam, *heap_size, block_size, *free_space, nobjs_ptr)) + if(fill_heap(fh, dxpl, row, obj_size, state, keep_ids)) FAIL_STACK_ERROR } /* end for */ @@ -558,27 +877,21 @@ error: *------------------------------------------------------------------------- */ static int -fill_root_direct(H5HF_t *fh, hid_t dxpl, const H5HF_create_t *cparam, - hsize_t *heap_size, hsize_t *free_space, unsigned *nobjs) +fill_root_direct(H5HF_t *fh, hid_t dxpl, size_t obj_size, + fheap_heap_state_t *state, fheap_heap_ids_t *keep_ids) { - size_t block_size; /* Size of block added */ - unsigned nrows; /* Number of rows inserted */ + unsigned max_dblock_rows; /* Max. # of direct block rows in indirect block */ + unsigned row; /* Row being created */ + + /* Get heap info */ + max_dblock_rows = DTABLE_MAX_DROWS(fh); + HDassert(max_dblock_rows); /* Loop over rows */ - block_size = cparam->managed.start_block_size; - nrows = 0; - while(block_size <= cparam->managed.max_direct_size) { - if(fill_root_row(fh, dxpl, cparam, heap_size, free_space, nrows, nobjs)) + for(row = 0; row < max_dblock_rows; row++) + if(fill_root_row(fh, dxpl, row, obj_size, state, keep_ids)) FAIL_STACK_ERROR - /* Adjust block size for row */ - if(nrows > 0) - block_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - /* Operations succeeded */ return(0); @@ -604,33 +917,20 @@ error: *------------------------------------------------------------------------- */ static int -fill_2nd_indirect(H5HF_t *fh, hid_t dxpl, const H5HF_create_t *cparam, - hsize_t *heap_size, hsize_t *free_space, unsigned *nobjs, - unsigned pos) +fill_2nd_indirect(H5HF_t *fh, hid_t dxpl, unsigned pos, size_t obj_size, + fheap_heap_state_t *state, fheap_heap_ids_t *keep_ids) { - size_t iblock_size; /* Indirect block's size */ - size_t max_dblock_size; /* Max. size of direct block to add */ - size_t dblock_size; /* Size of direct block added */ - unsigned nrows; /* Number of rows inserted */ + unsigned max_dblock_rows; /* Max. # of direct block rows in indirect block */ + unsigned row; /* Current row to create */ + + /* Get some information for the heap */ + max_dblock_rows = IBLOCK_MAX_DROWS(fh, pos); + HDassert(max_dblock_rows); /* Loop over rows */ - nrows = 0; - dblock_size = cparam->managed.start_block_size; - iblock_size = cparam->managed.max_direct_size * (1 << pos); - max_dblock_size = dblock_size * (1 << ((H5V_log2_of2(iblock_size / cparam->managed.width) - - (H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width))) + 1)); - while(dblock_size <= max_dblock_size) { - if(fill_row(fh, dxpl, cparam, heap_size, free_space, nrows, nobjs)) - FAIL_STACK_ERROR - - /* Adjust block size for row */ - if(nrows > 0) - dblock_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ + for(row = 0; row < max_dblock_rows; row++) + if(fill_row(fh, dxpl, row, obj_size, state, keep_ids)) + FAIL_STACK_ERROR /* Operations succeeded */ return(0); @@ -656,27 +956,21 @@ error: *------------------------------------------------------------------------- */ static int -fill_all_direct(H5HF_t *fh, hid_t dxpl, const H5HF_create_t *cparam, - hsize_t *heap_size, hsize_t *free_space, unsigned *nobjs) +fill_all_direct(H5HF_t *fh, hid_t dxpl, size_t obj_size, + fheap_heap_state_t *state, fheap_heap_ids_t *keep_ids) { - size_t dblock_size; /* Size of direct block added */ - unsigned nrows; /* Number of rows inserted */ + unsigned max_dblock_rows; /* Max. # of direct block rows in indirect block */ + unsigned row; /* Row being created */ + + /* Get heap info */ + max_dblock_rows = DTABLE_MAX_DROWS(fh); + HDassert(max_dblock_rows); /* Loop over rows */ - nrows = 0; - dblock_size = cparam->managed.start_block_size; - while(dblock_size <= cparam->managed.max_direct_size) { - if(fill_row(fh, dxpl, cparam, heap_size, free_space, nrows, nobjs)) + for(row = 0; row < max_dblock_rows; row++) + if(fill_row(fh, dxpl, row, obj_size, state, keep_ids)) FAIL_STACK_ERROR - /* Adjust block size for row */ - if(nrows > 0) - dblock_size *= 2; - - /* Increment row count */ - nrows++; - } /* end for */ - /* Operations succeeded */ return(0); @@ -702,15 +996,18 @@ error: *------------------------------------------------------------------------- */ static int -fill_2nd_indirect_row(H5HF_t *fh, hid_t dxpl, const H5HF_create_t *cparam, - hsize_t *heap_size, hsize_t *free_space, unsigned *nobjs, - unsigned pos) +fill_2nd_indirect_row(H5HF_t *fh, hid_t dxpl, unsigned pos, size_t obj_size, + fheap_heap_state_t *state, fheap_heap_ids_t *keep_ids) { + unsigned width; /* Width of heap's doubling table */ unsigned u; /* Local index variable */ + /* Get some information for the heap */ + width = DTABLE_WIDTH(fh); + /* Loop over row of indirect blocks */ - for(u = 0; u < cparam->managed.width; u++) - if(fill_2nd_indirect(fh, dxpl, cparam, heap_size, free_space, nobjs, pos)) + for(u = 0; u < width; u++) + if(fill_2nd_indirect(fh, dxpl, pos, obj_size, state, keep_ids)) FAIL_STACK_ERROR /* Operations succeeded */ @@ -738,14 +1035,18 @@ error: *------------------------------------------------------------------------- */ static int -fill_all_2nd_indirect_rows(H5HF_t *fh, hid_t dxpl, const H5HF_create_t *cparam, - hsize_t *heap_size, hsize_t *free_space, unsigned *nobjs) +fill_all_2nd_indirect_rows(H5HF_t *fh, hid_t dxpl, size_t obj_size, + fheap_heap_state_t *state, fheap_heap_ids_t *keep_ids) { + unsigned width; /* Width of heap's doubling table */ unsigned u; /* Local index variable */ + /* Get some information for the heap */ + width = DTABLE_WIDTH(fh); + /* Loop over rows of 2nd level deep indirect blocks */ - for(u = 0; u < (H5V_log2_of2(cparam->managed.width) + 1); u++) - if(fill_2nd_indirect_row(fh, dxpl, cparam, heap_size, free_space, nobjs, (u + 1))) + for(u = 0; u < (H5V_log2_of2(width) + 1); u++) + if(fill_2nd_indirect_row(fh, dxpl, (u + 1), obj_size, state, keep_ids)) FAIL_STACK_ERROR /* Operations succeeded */ @@ -773,19 +1074,18 @@ error: *------------------------------------------------------------------------- */ static int -fill_3rd_indirect(H5HF_t *fh, hid_t dxpl, const H5HF_create_t *cparam, - hsize_t *heap_size, hsize_t *free_space, unsigned *nobjs, - unsigned pos) +fill_3rd_indirect(H5HF_t *fh, hid_t dxpl, unsigned pos, size_t obj_size, + fheap_heap_state_t *state, fheap_heap_ids_t *keep_ids) { unsigned u; /* Local index variable */ /* Fill all direct block rows in third level indirect block */ - if(fill_all_direct(fh, dxpl, cparam, heap_size, free_space, nobjs)) + if(fill_all_direct(fh, dxpl, obj_size, state, keep_ids)) FAIL_STACK_ERROR /* Fill rows of recursive indirect blocks in third level indirect block */ for(u = 0; u < pos; u++) - if(fill_2nd_indirect_row(fh, dxpl, cparam, heap_size, free_space, nobjs, (u + 1))) + if(fill_2nd_indirect_row(fh, dxpl, (u + 1), obj_size, state, keep_ids)) FAIL_STACK_ERROR /* Operations succeeded */ @@ -813,16 +1113,19 @@ error: *------------------------------------------------------------------------- */ static int -fill_3rd_indirect_row(H5HF_t *fh, hid_t dxpl, const H5HF_create_t *cparam, - hsize_t *heap_size, hsize_t *free_space, unsigned *nobjs, - unsigned pos) +fill_3rd_indirect_row(H5HF_t *fh, hid_t dxpl, unsigned pos, size_t obj_size, + fheap_heap_state_t *state, fheap_heap_ids_t *keep_ids) { + unsigned width; /* Width of heap's doubling table */ unsigned u; /* Local index variable */ + /* Get some information for the heap */ + width = DTABLE_WIDTH(fh); + /* Loop over row of 3rd level indirect blocks */ - for(u = 0; u < cparam->managed.width; u++) + for(u = 0; u < width; u++) /* Fill third level indirect block */ - if(fill_3rd_indirect(fh, dxpl, cparam, heap_size, free_space, nobjs, pos)) + if(fill_3rd_indirect(fh, dxpl, pos, obj_size, state, keep_ids)) FAIL_STACK_ERROR /* Operations succeeded */ @@ -850,15 +1153,19 @@ error: *------------------------------------------------------------------------- */ static int -fill_all_3rd_indirect_rows(H5HF_t *fh, hid_t dxpl, const H5HF_create_t *cparam, - hsize_t *heap_size, hsize_t *free_space, unsigned *nobjs) +fill_all_3rd_indirect_rows(H5HF_t *fh, hid_t dxpl, size_t obj_size, + fheap_heap_state_t *state, fheap_heap_ids_t *keep_ids) { + unsigned width; /* Width of heap's doubling table */ unsigned u; /* Local index variable */ + /* Get some information for the heap */ + width = DTABLE_WIDTH(fh); + /* Loop over rows of 3rd level deep indirect blocks */ - for(u = 0; u < (H5V_log2_of2(cparam->managed.width) + 1); u++) + for(u = 0; u < (H5V_log2_of2(width) + 1); u++) /* Fill row of 3rd level indirect blocks */ - if(fill_3rd_indirect_row(fh, dxpl, cparam, heap_size, free_space, nobjs, u + 1)) + if(fill_3rd_indirect_row(fh, dxpl, (u + 1), obj_size, state, keep_ids)) FAIL_STACK_ERROR /* Operations succeeded */ @@ -886,25 +1193,28 @@ error: *------------------------------------------------------------------------- */ static int -fill_4th_indirect_row(H5HF_t *fh, hid_t dxpl, const H5HF_create_t *cparam, - hsize_t *heap_size, hsize_t *free_space, unsigned *nobjs, - unsigned pos) +fill_4th_indirect_row(H5HF_t *fh, hid_t dxpl, unsigned pos, size_t obj_size, + fheap_heap_state_t *state, fheap_heap_ids_t *keep_ids) { + unsigned width; /* Width of heap's doubling table */ unsigned u, v; /* Local index variables */ + /* Get some information for the heap */ + width = DTABLE_WIDTH(fh); + /* Loop over row of 4th level indirect blocks */ - for(u = 0; u < cparam->managed.width; u++) { + for(u = 0; u < width; u++) { /* Fill all direct block rows in fourth level indirect block */ - if(fill_all_direct(fh, dxpl, cparam, heap_size, free_space, nobjs)) + if(fill_all_direct(fh, dxpl, obj_size, state, keep_ids)) FAIL_STACK_ERROR /* Fill all rows of 2nd level deep indirect blocks in fourth level indirect block */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, heap_size, free_space, nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, obj_size, state, keep_ids)) FAIL_STACK_ERROR /* Fill rows of third level indirect blocks in fourth level indirect block */ for(v = 0; v < pos; v++) - if(fill_3rd_indirect_row(fh, dxpl, cparam, heap_size, free_space, nobjs, (v + 1))) + if(fill_3rd_indirect_row(fh, dxpl, (v + 1), obj_size, state, keep_ids)) FAIL_STACK_ERROR } /* end for */ @@ -933,39 +1243,37 @@ error: *------------------------------------------------------------------------- */ static int -fill_all_4th_indirect_rows(H5HF_t *fh, hid_t dxpl, const H5HF_create_t *cparam, - hsize_t *heap_size, hsize_t *free_space, unsigned *nobjs) +fill_all_4th_indirect_rows(H5HF_t *fh, hid_t dxpl, size_t obj_size, + fheap_heap_state_t *state, fheap_heap_ids_t *keep_ids) { + unsigned width; /* Width of heap's doubling table */ unsigned u; /* Local index variable */ + /* Get some information for the heap */ + width = DTABLE_WIDTH(fh); + /* Loop over rows of 4th level deep indirect blocks */ - for(u = 0; u < (H5V_log2_of2(cparam->managed.width) + 1); u++) { + for(u = 0; u < (H5V_log2_of2(width) + 1); u++) { /* Fill row of 4th level indirect blocks */ - if(fill_4th_indirect_row(fh, dxpl, cparam, heap_size, free_space, nobjs, (u + 1))) + if(fill_4th_indirect_row(fh, dxpl, (u + 1), obj_size, state, keep_ids)) FAIL_STACK_ERROR /* Account for root indirect block doubling # of rows again */ /* (From 16 rows to the max. # of rows: 22) */ + /* (Note: this is tied to the particular doubling table/heap creation parameters) */ if(u == 0) { - hsize_t block_size; /* Current block size */ - hsize_t max_block_size; /* Maximum size of blocks in heap */ + unsigned max_root_rows; /* Maximum # of rows in root indirect block */ unsigned row; /* Row in heap */ - /* Compute current & maximum block size in heap */ - block_size = cparam->managed.start_block_size * ((hsize_t)1 << 15); - max_block_size = (((hsize_t)1 << cparam->managed.max_index) / 2) / - cparam->managed.width; + /* Get some information for the heap */ + max_root_rows = HEAP_MAX_ROOT_ROWS(fh); /* Increase heap size & free space */ - row = 16; - while(block_size <= max_block_size) { - *heap_size += cparam->managed.width * block_size; - *free_space += cparam->managed.width * DBLOCK_FREE(fh, row); - - /* Advance to next row */ - block_size *= 2; - row++; - } /* end while */ + for(row = 16; row < max_root_rows; row++) { + state->heap_size += width * DBLOCK_SIZE(fh, row); + state->man_size += width * DBLOCK_SIZE(fh, row); + state->man_free_space += width * DBLOCK_FREE(fh, row); + } /* end for */ } /* end if */ } /* end for */ @@ -1000,6 +1308,7 @@ test_create(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t UNUSED *tparam H5HF_create_t test_cparam; /* Creation parameters for heap */ H5HF_t *fh = NULL; /* Fractal heap wrapper */ size_t id_len; /* Size of fractal heap IDs */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -1022,7 +1331,8 @@ test_create(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t UNUSED *tparam FAIL_STACK_ERROR if(id_len > HEAP_ID_LEN) FAIL_STACK_ERROR - if(check_stats(fh, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0)) + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); + if(check_stats(fh, &state)) FAIL_STACK_ERROR PASSED() @@ -1080,6 +1390,7 @@ test_reopen(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t UNUSED *tparam H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -1109,7 +1420,8 @@ test_reopen(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t UNUSED *tparam FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR - if(check_stats(fh, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0)) + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); + if(check_stats(fh, &state)) FAIL_STACK_ERROR /* Close the fractal heap */ @@ -1174,9 +1486,7 @@ test_abs_insert_first(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpa H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of the heap */ - unsigned nobjs = 0; /* Total number of objects inserted */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -1200,7 +1510,8 @@ test_abs_insert_first(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpa FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR - if(check_stats(fh, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0)) + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); + if(check_stats(fh, &state)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -1218,9 +1529,11 @@ test_abs_insert_first(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpa * Test inserting first (small) object into absolute heap */ TESTING("inserting first (small) object into absolute heap"); - free_space = DBLOCK_FREE(fh, 0); - heap_size = cparam->managed.start_block_size; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, SMALL_OBJ_SIZE1)) + state.heap_size = DBLOCK_SIZE(fh, 0); + state.man_size = DBLOCK_SIZE(fh, 0); + state.man_alloc_size = DBLOCK_SIZE(fh, 0); + state.man_free_space = DBLOCK_FREE(fh, 0); + if(add_obj(fh, dxpl, 10, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -1235,7 +1548,7 @@ test_abs_insert_first(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpa } /* end if */ /* Check for correctly sized heap */ - if(check_stats(fh, heap_size, heap_size, (hsize_t)0, free_space, (hsize_t)1)) + if(check_stats(fh, &state)) FAIL_STACK_ERROR PASSED() @@ -1285,8 +1598,7 @@ test_abs_insert_second(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tp H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - hsize_t free_space; /* Size of free space in heap */ - unsigned nobjs = 0; /* Total number of objects inserted */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -1310,13 +1622,17 @@ test_abs_insert_second(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tp FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting first (small) object into absolute heap */ TESTING("inserting two (small) objects into absolute heap"); - free_space = DBLOCK_FREE(fh, 0); - if(add_obj(fh, dxpl, (hsize_t)cparam->managed.start_block_size, &free_space, &nobjs, 10, SMALL_OBJ_SIZE1)) + state.heap_size = DBLOCK_SIZE(fh, 0); + state.man_size = DBLOCK_SIZE(fh, 0); + state.man_alloc_size = DBLOCK_SIZE(fh, 0); + state.man_free_space = DBLOCK_FREE(fh, 0); + if(add_obj(fh, dxpl, 10, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -1331,7 +1647,7 @@ test_abs_insert_second(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tp } /* end if */ /* Insert second object */ - if(add_obj(fh, dxpl, (hsize_t)cparam->managed.start_block_size, &free_space, &nobjs, 20, SMALL_OBJ_SIZE2)) + if(add_obj(fh, dxpl, 20, SMALL_OBJ_SIZE2, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -1382,7 +1698,7 @@ test_abs_insert_root_mult(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -1406,6 +1722,7 @@ test_abs_insert_root_mult(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting mult. (small) object into absolute heap @@ -1413,7 +1730,11 @@ test_abs_insert_root_mult(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t TESTING("inserting objects to fill absolute heap's root direct block"); /* Fill the heap up */ - if(fill_heap(fh, dxpl, cparam, (hsize_t)cparam->managed.start_block_size, cparam->managed.start_block_size, (hsize_t)0, &nobjs)) + state.heap_size = DBLOCK_SIZE(fh, 0); + state.man_size = DBLOCK_SIZE(fh, 0); + state.man_alloc_size = DBLOCK_SIZE(fh, 0); + state.man_free_space = DBLOCK_FREE(fh, 0); + if(fill_heap(fh, dxpl, 0, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -1476,9 +1797,7 @@ test_abs_insert_force_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_test_par H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of the heap */ - unsigned nobjs = 0; /* Number of objects inserted */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -1502,6 +1821,7 @@ test_abs_insert_force_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_test_par FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test forcing creation of indirect root block & second direct block @@ -1509,7 +1829,11 @@ test_abs_insert_force_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_test_par TESTING("inserting objects to create root indirect block"); /* Fill the heap up */ - if(fill_heap(fh, dxpl, cparam, (hsize_t)cparam->managed.start_block_size, cparam->managed.start_block_size, (hsize_t)0, &nobjs)) + state.heap_size = DBLOCK_SIZE(fh, 0); + state.man_size = DBLOCK_SIZE(fh, 0); + state.man_alloc_size = DBLOCK_SIZE(fh, 0); + state.man_free_space = DBLOCK_FREE(fh, 0); + if(fill_heap(fh, dxpl, 0, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -1524,9 +1848,11 @@ test_abs_insert_force_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_test_par } /* end if */ /* Insert one more object, to force root indirect block creation */ - free_space = (cparam->managed.width - 1) * DBLOCK_FREE(fh, 0); - heap_size = cparam->managed.width * cparam->managed.start_block_size; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, SMALL_OBJ_SIZE1)) + state.heap_size = cparam->managed.width * DBLOCK_SIZE(fh, 0); + state.man_size = cparam->managed.width * DBLOCK_SIZE(fh, 0); + state.man_alloc_size += DBLOCK_SIZE(fh, 0); + state.man_free_space = (cparam->managed.width - 1) * DBLOCK_FREE(fh, 0); + if(add_obj(fh, dxpl, 10, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -1578,9 +1904,7 @@ test_abs_insert_fill_second(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_ H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of the heap */ - unsigned nobjs = 0; /* Number of objects inserted */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -1604,6 +1928,7 @@ test_abs_insert_fill_second(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_ FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting mult. (small) objects to fill second direct block @@ -1611,7 +1936,11 @@ test_abs_insert_fill_second(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_ TESTING("inserting objects to fill second direct block"); /* Fill the first direct block heap up */ - if(fill_heap(fh, dxpl, cparam, (hsize_t)cparam->managed.start_block_size, cparam->managed.start_block_size, (hsize_t)0, &nobjs)) + state.heap_size = DBLOCK_SIZE(fh, 0); + state.man_size = DBLOCK_SIZE(fh, 0); + state.man_alloc_size = DBLOCK_SIZE(fh, 0); + state.man_free_space = DBLOCK_FREE(fh, 0); + if(fill_heap(fh, dxpl, 0, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -1626,9 +1955,11 @@ test_abs_insert_fill_second(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_ } /* end if */ /* Fill the second direct block heap up (also creates initial root indirect block) */ - free_space = (cparam->managed.width - 2) * DBLOCK_FREE(fh, 0); - heap_size = cparam->managed.width * cparam->managed.start_block_size; - if(fill_heap(fh, dxpl, cparam, heap_size, cparam->managed.start_block_size, free_space, &nobjs)) + state.heap_size = cparam->managed.width * DBLOCK_SIZE(fh, 0); + state.man_size = cparam->managed.width * DBLOCK_SIZE(fh, 0); + state.man_alloc_size += DBLOCK_SIZE(fh, 0); + state.man_free_space = (cparam->managed.width - 1) * DBLOCK_FREE(fh, 0); + if(fill_heap(fh, dxpl, 0, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -1681,9 +2012,7 @@ test_abs_insert_third_direct(hid_t fapl, H5HF_create_t *cparam, fheap_test_param H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of the heap */ - unsigned nobjs = 0; /* Number of objects inserted */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -1707,6 +2036,7 @@ test_abs_insert_third_direct(hid_t fapl, H5HF_create_t *cparam, fheap_test_param FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting mult. (small) objects to create third direct block @@ -1714,13 +2044,19 @@ test_abs_insert_third_direct(hid_t fapl, H5HF_create_t *cparam, fheap_test_param TESTING("inserting objects to create third direct block"); /* Fill the first direct block up */ - if(fill_heap(fh, dxpl, cparam, (hsize_t)cparam->managed.start_block_size, cparam->managed.start_block_size, (hsize_t)0, &nobjs)) + state.heap_size = DBLOCK_SIZE(fh, 0); + state.man_size = DBLOCK_SIZE(fh, 0); + state.man_alloc_size = DBLOCK_SIZE(fh, 0); + state.man_free_space = DBLOCK_FREE(fh, 0); + if(fill_heap(fh, dxpl, 0, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill the second direct block heap up (also creates initial root indirect block) */ - free_space = (cparam->managed.width - 2) * DBLOCK_FREE(fh, 0); - heap_size = cparam->managed.width * cparam->managed.start_block_size; - if(fill_heap(fh, dxpl, cparam, heap_size, cparam->managed.start_block_size, free_space, &nobjs)) + state.heap_size = cparam->managed.width * DBLOCK_SIZE(fh, 0); + state.man_size = cparam->managed.width * DBLOCK_SIZE(fh, 0); + state.man_alloc_size += DBLOCK_SIZE(fh, 0); + state.man_free_space = (cparam->managed.width - 1) * DBLOCK_FREE(fh, 0); + if(fill_heap(fh, dxpl, 0, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -1735,7 +2071,8 @@ test_abs_insert_third_direct(hid_t fapl, H5HF_create_t *cparam, fheap_test_param } /* end if */ /* Insert one more object, to force creation of third direct block */ - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, SMALL_OBJ_SIZE1)) + state.man_alloc_size += DBLOCK_SIZE(fh, 0); + if(add_obj(fh, dxpl, 10, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -1787,9 +2124,7 @@ test_abs_fill_first_row(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *t H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ - unsigned nobjs = 0; /* Total number of objects inserted */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -1813,6 +2148,7 @@ test_abs_fill_first_row(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *t FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting mult. (small) objects to fill first row in root indirect block @@ -1820,9 +2156,7 @@ test_abs_fill_first_row(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *t TESTING("inserting objects to fill first row of root indirect block"); /* Fill first row of [root] indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_row(fh, dxpl, cparam, &heap_size, &free_space, 0, &nobjs)) + if(fill_root_row(fh, dxpl, 0, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -1885,9 +2219,7 @@ test_abs_start_second_row(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of the heap */ - unsigned nobjs = 0; /* Number of objects inserted */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -1911,6 +2243,7 @@ test_abs_start_second_row(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting mult. (small) objects to start second row in root indirect block @@ -1918,9 +2251,7 @@ test_abs_start_second_row(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t TESTING("inserting objects to start second row of root indirect block"); /* Fill first root indirect row */ - heap_size = 0; - free_space = 0; - if(fill_root_row(fh, dxpl, cparam, &heap_size, &free_space, 0, &nobjs)) + if(fill_root_row(fh, dxpl, 0, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -1935,9 +2266,11 @@ test_abs_start_second_row(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t } /* end if */ /* Insert one more object, to force expanding root indirect block to two rows */ - heap_size += cparam->managed.width * cparam->managed.start_block_size; - free_space += cparam->managed.width * DBLOCK_FREE(fh, 1); - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, SMALL_OBJ_SIZE1)) + state.heap_size += cparam->managed.width * DBLOCK_SIZE(fh, 1); + state.man_size += cparam->managed.width * DBLOCK_SIZE(fh, 1); + state.man_alloc_size += DBLOCK_SIZE(fh, 1); + state.man_free_space = cparam->managed.width * DBLOCK_FREE(fh, 1); + if(add_obj(fh, dxpl, 10, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -1989,9 +2322,7 @@ test_abs_fill_second_row(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t * H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of the heap */ - unsigned nobjs = 0; /* Number of objects inserted */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -2015,6 +2346,7 @@ test_abs_fill_second_row(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t * FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting mult. (small) objects to start second row in root indirect block @@ -2022,9 +2354,7 @@ test_abs_fill_second_row(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t * TESTING("inserting objects to fill second row of root indirect block"); /* Fill first root indirect row */ - heap_size = 0; - free_space = 0; - if(fill_root_row(fh, dxpl, cparam, &heap_size, &free_space, 0, &nobjs)) + if(fill_root_row(fh, dxpl, 0, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -2039,7 +2369,7 @@ test_abs_fill_second_row(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t * } /* end if */ /* Fill second root indirect row */ - if(fill_root_row(fh, dxpl, cparam, &heap_size, &free_space, 1, &nobjs)) + if(fill_root_row(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -2092,9 +2422,7 @@ test_abs_start_third_row(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t * H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ - unsigned nobjs = 0; /* Number of objects inserted */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -2118,6 +2446,7 @@ test_abs_start_third_row(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t * FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting mult. (small) objects to start third row in root indirect block @@ -2125,13 +2454,11 @@ test_abs_start_third_row(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t * TESTING("inserting objects to start third row of root indirect block"); /* Fill first root indirect row */ - heap_size = 0; - free_space = 0; - if(fill_root_row(fh, dxpl, cparam, &heap_size, &free_space, 0, &nobjs)) + if(fill_root_row(fh, dxpl, 0, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill second root indirect row */ - if(fill_root_row(fh, dxpl, cparam, &heap_size, &free_space, 1, &nobjs)) + if(fill_root_row(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -2147,11 +2474,14 @@ test_abs_start_third_row(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t * /* Insert one more object, to force expanding root indirect block to four rows */ /* (Goes to four rows because it's doubling) */ - heap_size += cparam->managed.width * cparam->managed.start_block_size * 2; - heap_size += cparam->managed.width * cparam->managed.start_block_size * 4; - free_space += cparam->managed.width * DBLOCK_FREE(fh, 2); - free_space += cparam->managed.width * DBLOCK_FREE(fh, 3); - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, SMALL_OBJ_SIZE1)) + state.heap_size += cparam->managed.width * DBLOCK_SIZE(fh, 2); + state.heap_size += cparam->managed.width * DBLOCK_SIZE(fh, 3); + state.man_size += cparam->managed.width * DBLOCK_SIZE(fh, 2); + state.man_size += cparam->managed.width * DBLOCK_SIZE(fh, 3); + state.man_alloc_size += DBLOCK_SIZE(fh, 2); + state.man_free_space += cparam->managed.width * DBLOCK_FREE(fh, 2); + state.man_free_space += cparam->managed.width * DBLOCK_FREE(fh, 3); + if(add_obj(fh, dxpl, 10, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -2203,9 +2533,7 @@ test_abs_fill_fourth_row(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t * H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ unsigned u; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ @@ -2230,6 +2558,7 @@ test_abs_fill_fourth_row(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t * FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting mult. (small) objects to fill four rows in root indirect block @@ -2237,10 +2566,8 @@ test_abs_fill_fourth_row(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t * TESTING("inserting objects to fill four rows of root indirect block"); /* Loop over rows */ - heap_size = 0; - free_space = 0; for(u = 0; u < 4; u++) - if(fill_root_row(fh, dxpl, cparam, &heap_size, &free_space, u, &nobjs)) + if(fill_root_row(fh, dxpl, u, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -2303,9 +2630,7 @@ test_abs_fill_all_root_direct(hid_t fapl, H5HF_create_t *cparam, fheap_test_para H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -2329,6 +2654,7 @@ test_abs_fill_all_root_direct(hid_t fapl, H5HF_create_t *cparam, fheap_test_para FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting mult. (small) objects to fill all direct rows in root indirect block @@ -2336,9 +2662,7 @@ test_abs_fill_all_root_direct(hid_t fapl, H5HF_create_t *cparam, fheap_test_para TESTING("inserting objects to fill all direct rows of root indirect block"); /* Fill all direct blocks in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -2401,9 +2725,7 @@ test_abs_first_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_test_ H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -2427,6 +2749,7 @@ test_abs_first_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_test_ FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting mult. (small) objects to force creation of first recursive indirect block @@ -2434,9 +2757,7 @@ test_abs_first_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_test_ TESTING("inserting objects to create first recursive indirect block"); /* Fill direct blocks up */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -2451,7 +2772,8 @@ test_abs_first_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_test_ } /* end if */ /* Insert one more object, to force creation of first recursive indirect block */ - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, SMALL_OBJ_SIZE1)) + state.man_alloc_size += DBLOCK_SIZE(fh, 0); + if(add_obj(fh, dxpl, 10, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -2504,9 +2826,7 @@ test_abs_second_direct_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fhe H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -2530,6 +2850,7 @@ test_abs_second_direct_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fhe FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting mult. (small) objects to force creation of second direct @@ -2538,14 +2859,12 @@ test_abs_second_direct_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fhe TESTING("inserting objects to create second direct block in first recursive indirect block"); /* Fill direct blocks up */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill the first direct block in the recursive indirect block up */ - free_space -= DBLOCK_FREE(fh, 0); - if(fill_heap(fh, dxpl, cparam, heap_size, cparam->managed.start_block_size, free_space, &nobjs)) + state.man_alloc_size += DBLOCK_SIZE(fh, 0); + if(fill_heap(fh, dxpl, 0, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -2562,7 +2881,8 @@ test_abs_second_direct_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fhe /* Insert one more object, to force creation of second direct block in * first recursive indirect block */ - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, SMALL_OBJ_SIZE1)) + state.man_alloc_size += DBLOCK_SIZE(fh, 0); + if(add_obj(fh, dxpl, 10, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -2615,9 +2935,7 @@ test_abs_fill_first_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_ H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -2641,6 +2959,7 @@ test_abs_fill_first_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_ FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting mult. (small) objects to fill all direct @@ -2649,9 +2968,7 @@ test_abs_fill_first_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_ TESTING("inserting objects to fill all direct blocks in first recursive indirect block"); /* Fill direct blocks up in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -2666,7 +2983,7 @@ test_abs_fill_first_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_ } /* end if */ /* Fill first recursive indirect block */ - if(fill_2nd_indirect(fh, dxpl, cparam, &heap_size, &free_space, &nobjs, 1)) + if(fill_2nd_indirect(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -2720,9 +3037,7 @@ test_abs_second_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_test H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -2746,6 +3061,7 @@ test_abs_second_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_test FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting mult. (small) objects to fill all direct @@ -2754,13 +3070,11 @@ test_abs_second_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_test TESTING("inserting objects to start second recursive indirect block"); /* Fill direct blocks up in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill first recursive indirect block */ - if(fill_2nd_indirect(fh, dxpl, cparam, &heap_size, &free_space, &nobjs, 1)) + if(fill_2nd_indirect(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -2777,7 +3091,8 @@ test_abs_second_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_test /* Insert one more object, to force creation of second * recursive indirect block */ - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, SMALL_OBJ_SIZE1)) + state.man_alloc_size += DBLOCK_SIZE(fh, 0); + if(add_obj(fh, dxpl, 10, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -2832,9 +3147,7 @@ test_abs_fill_second_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -2858,6 +3171,7 @@ test_abs_fill_second_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting mult. (small) objects to fill all direct @@ -2866,13 +3180,11 @@ test_abs_fill_second_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap TESTING("inserting objects to fill all direct blocks in second recursive indirect block"); /* Fill direct blocks up in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill first recursive indirect block */ - if(fill_2nd_indirect(fh, dxpl, cparam, &heap_size, &free_space, &nobjs, 1)) + if(fill_2nd_indirect(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -2887,7 +3199,7 @@ test_abs_fill_second_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap } /* end if */ /* Fill 2nd recursive indirect block */ - if(fill_2nd_indirect(fh, dxpl, cparam, &heap_size, &free_space, &nobjs, 1)) + if(fill_2nd_indirect(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -2942,9 +3254,7 @@ test_abs_fill_recursive_indirect_row(hid_t fapl, H5HF_create_t *cparam, fheap_te H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -2968,6 +3278,7 @@ test_abs_fill_recursive_indirect_row(hid_t fapl, H5HF_create_t *cparam, fheap_te FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting mult. (small) objects to fill all direct @@ -2976,9 +3287,7 @@ test_abs_fill_recursive_indirect_row(hid_t fapl, H5HF_create_t *cparam, fheap_te TESTING("inserting objects to fill all direct blocks in first row of recursive indirect block"); /* Fill direct blocks in root indirect block up */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -2993,7 +3302,7 @@ test_abs_fill_recursive_indirect_row(hid_t fapl, H5HF_create_t *cparam, fheap_te } /* end if */ /* Fill row of recursive indirect blocks */ - if(fill_2nd_indirect_row(fh, dxpl, cparam, &heap_size, &free_space, &nobjs, 1)) + if(fill_2nd_indirect_row(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -3046,9 +3355,7 @@ test_abs_start_2nd_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_t H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -3072,6 +3379,7 @@ test_abs_start_2nd_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_t FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting mult. (small) objects to fill all direct @@ -3080,13 +3388,11 @@ test_abs_start_2nd_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_t TESTING("inserting objects to start second row of recursive indirect blocks"); /* Fill direct blocks in root indirect block up */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill row of recursive indirect blocks */ - if(fill_2nd_indirect_row(fh, dxpl, cparam, &heap_size, &free_space, &nobjs, 1)) + if(fill_2nd_indirect_row(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -3103,7 +3409,8 @@ test_abs_start_2nd_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_t /* Insert one more object, to force creation of second * recursive indirect block */ - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, SMALL_OBJ_SIZE1)) + state.man_alloc_size += DBLOCK_SIZE(fh, 0); + if(add_obj(fh, dxpl, 10, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -3156,9 +3463,7 @@ test_abs_recursive_indirect_two_deep(hid_t fapl, H5HF_create_t *cparam, fheap_te H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -3182,6 +3487,7 @@ test_abs_recursive_indirect_two_deep(hid_t fapl, H5HF_create_t *cparam, fheap_te FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting mult. (small) objects to fill all direct @@ -3190,9 +3496,7 @@ test_abs_recursive_indirect_two_deep(hid_t fapl, H5HF_create_t *cparam, fheap_te TESTING("inserting objects to fill recursive indirect blocks two levels deep"); /* Fill direct blocks up in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -3207,7 +3511,7 @@ test_abs_recursive_indirect_two_deep(hid_t fapl, H5HF_create_t *cparam, fheap_te } /* end if */ /* Fill all rows of 2nd level indirect blocks */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -3261,9 +3565,7 @@ test_abs_start_3rd_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_t H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -3287,6 +3589,7 @@ test_abs_start_3rd_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_t FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting mult. (small) objects to fill all direct @@ -3295,13 +3598,11 @@ test_abs_start_3rd_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_t TESTING("inserting objects to start recursive indirect blocks three levels deep"); /* Fill direct blocks up in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill all rows of 2nd level indirect blocks */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -3318,7 +3619,8 @@ test_abs_start_3rd_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_t /* Insert one more object, to force creation of third level deep * recursive indirect block */ - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, SMALL_OBJ_SIZE1)) + state.man_alloc_size += DBLOCK_SIZE(fh, 0); + if(add_obj(fh, dxpl, 10, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -3372,9 +3674,7 @@ test_abs_fill_first_3rd_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fh H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -3398,6 +3698,7 @@ test_abs_fill_first_3rd_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fh FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting mult. (small) objects to fill all direct @@ -3406,17 +3707,15 @@ test_abs_fill_first_3rd_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fh TESTING("inserting objects to fill first indirect block of recursive indirect blocks three levels deep"); /* Fill direct blocks up in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill all rows of 2nd level indirect blocks */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill all direct block rows in third level indirect block */ - if(fill_all_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -3431,7 +3730,7 @@ test_abs_fill_first_3rd_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fh } /* end if */ /* Fill row of recursive indirect blocks in third level indirect block */ - if(fill_2nd_indirect_row(fh, dxpl, cparam, &heap_size, &free_space, &nobjs, 1)) + if(fill_2nd_indirect_row(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -3485,9 +3784,7 @@ test_abs_fill_3rd_recursive_indirect_row(hid_t fapl, H5HF_create_t *cparam, fhea H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -3511,6 +3808,7 @@ test_abs_fill_3rd_recursive_indirect_row(hid_t fapl, H5HF_create_t *cparam, fhea FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting mult. (small) objects to fill all direct @@ -3519,13 +3817,11 @@ test_abs_fill_3rd_recursive_indirect_row(hid_t fapl, H5HF_create_t *cparam, fhea TESTING("inserting objects to fill row of indirect blocks in recursive indirect blocks three levels deep"); /* Fill direct blocks up in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill all rows of 2nd level indirect blocks */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -3540,7 +3836,7 @@ test_abs_fill_3rd_recursive_indirect_row(hid_t fapl, H5HF_create_t *cparam, fhea } /* end if */ /* Fill 1st row of 3rd level indirect blocks */ - if(fill_3rd_indirect_row(fh, dxpl, cparam, &heap_size, &free_space, &nobjs, 1)) + if(fill_3rd_indirect_row(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -3594,9 +3890,7 @@ test_abs_fill_all_3rd_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fhea H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -3620,6 +3914,7 @@ test_abs_fill_all_3rd_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fhea FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting mult. (small) objects to fill all direct @@ -3628,13 +3923,11 @@ test_abs_fill_all_3rd_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fhea TESTING("inserting objects to fill row of indirect blocks in recursive indirect blocks three levels deep"); /* Fill direct blocks up in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill all rows of 2nd level indirect blocks */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -3649,7 +3942,7 @@ test_abs_fill_all_3rd_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fhea } /* end if */ /* Fill all rows of 3rd level indirect blocks */ - if(fill_all_3rd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_3rd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -3704,9 +3997,7 @@ test_abs_start_4th_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_t H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -3730,6 +4021,7 @@ test_abs_start_4th_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_t FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting mult. (small) objects to fill all direct @@ -3738,17 +4030,15 @@ test_abs_start_4th_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_t TESTING("inserting objects to start first direct block in recursive indirect blocks four levels deep"); /* Fill direct blocks up in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill all rows of 2nd level indirect blocks */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill all rows of 3rd level indirect blocks */ - if(fill_all_3rd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_3rd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -3765,7 +4055,8 @@ test_abs_start_4th_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_t /* Insert one more object, to force creation of four level deep * recursive indirect block */ - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, SMALL_OBJ_SIZE1)) + state.man_alloc_size += DBLOCK_SIZE(fh, 0); + if(add_obj(fh, dxpl, 10, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -3820,9 +4111,7 @@ test_abs_fill_first_4th_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fh H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -3846,6 +4135,7 @@ test_abs_fill_first_4th_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fh FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting mult. (small) objects to fill all direct @@ -3854,25 +4144,23 @@ test_abs_fill_first_4th_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fh TESTING("inserting objects to fill first (3rd level) indirect block in recursive indirect block four levels deep"); /* Fill direct blocks up in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill all rows of 2nd level indirect blocks */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill all rows of 3rd level indirect blocks */ - if(fill_all_3rd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_3rd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill direct block rows in fourth level indirect block */ - if(fill_all_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill all rows of 2nd level deep indirect blocks in fourth level indirect block */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -3887,7 +4175,7 @@ test_abs_fill_first_4th_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fh } /* end if */ /* Fill first row of 3rd level deep indirect blocks in fourth level indirect block */ - if(fill_3rd_indirect_row(fh, dxpl, cparam, &heap_size, &free_space, &nobjs, 1)) + if(fill_3rd_indirect_row(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -3942,9 +4230,7 @@ test_abs_fill_4th_recursive_indirect_row(hid_t fapl, H5HF_create_t *cparam, fhea H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -3968,6 +4254,7 @@ test_abs_fill_4th_recursive_indirect_row(hid_t fapl, H5HF_create_t *cparam, fhea FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting mult. (small) objects to fill all direct @@ -3976,17 +4263,15 @@ test_abs_fill_4th_recursive_indirect_row(hid_t fapl, H5HF_create_t *cparam, fhea TESTING("inserting objects to fill first row of recursive indirect blocks four levels deep"); /* Fill direct blocks up in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill all rows of 2nd level indirect blocks */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill all rows of 3rd level indirect blocks */ - if(fill_all_3rd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_3rd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -4001,7 +4286,7 @@ test_abs_fill_4th_recursive_indirect_row(hid_t fapl, H5HF_create_t *cparam, fhea } /* end if */ /* Fill 1st row of 4th level indirect blocks */ - if(fill_4th_indirect_row(fh, dxpl, cparam, &heap_size, &free_space, &nobjs, 1)) + if(fill_4th_indirect_row(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -4056,9 +4341,7 @@ test_abs_fill_all_4th_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fhea H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -4082,6 +4365,7 @@ test_abs_fill_all_4th_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fhea FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting mult. (small) objects to fill all direct @@ -4090,17 +4374,15 @@ test_abs_fill_all_4th_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fhea TESTING("inserting objects to fill all rows of recursive indirect blocks four levels deep"); /* Fill direct blocks up in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill all rows of 2nd level indirect blocks */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill all rows of 3rd level indirect blocks */ - if(fill_all_3rd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_3rd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -4115,7 +4397,7 @@ test_abs_fill_all_4th_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fhea } /* end if */ /* Fill all rows of 4th level indirect blocks */ - if(fill_all_4th_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_4th_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -4173,9 +4455,7 @@ test_abs_start_5th_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_t H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -4199,6 +4479,7 @@ test_abs_start_5th_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_t FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting mult. (small) objects to fill all direct @@ -4208,9 +4489,7 @@ test_abs_start_5th_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_t TESTING("inserting objects to create first direct block in recursive indirect blocks five levels deep"); /* Fill direct blocks up in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -4225,7 +4504,7 @@ test_abs_start_5th_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_t } /* end if */ /* Fill all rows of 2nd level indirect blocks */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -4240,7 +4519,7 @@ test_abs_start_5th_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_t } /* end if */ /* Fill all rows of 3rd level indirect blocks */ - if(fill_all_3rd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_3rd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -4255,7 +4534,7 @@ test_abs_start_5th_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_t } /* end if */ /* Fill all rows of 4th level indirect blocks */ - if(fill_all_4th_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_4th_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -4272,7 +4551,8 @@ test_abs_start_5th_recursive_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_t /* Insert one more object, to force creation of five level deep * recursive indirect block */ - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, SMALL_OBJ_SIZE1)) + state.man_alloc_size += DBLOCK_SIZE(fh, 0); + if(add_obj(fh, dxpl, 10, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -4326,10 +4606,8 @@ test_abs_skip_start_block(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -4353,7 +4631,8 @@ test_abs_skip_start_block(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR - if(check_stats(fh, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0)) + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); + if(check_stats(fh, &state)) FAIL_STACK_ERROR /* @@ -4362,12 +4641,18 @@ test_abs_skip_start_block(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t */ TESTING("inserting object that is too large for starting block"); - obj_size = cparam->managed.start_block_size + 1; - free_space = 2 * cparam->managed.width * DBLOCK_FREE(fh, 0); - free_space += cparam->managed.width * DBLOCK_FREE(fh, 2); - heap_size = 2 * cparam->managed.width * cparam->managed.start_block_size; - heap_size += cparam->managed.width * (cparam->managed.start_block_size * 2); - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + obj_size = DBLOCK_SIZE(fh, 0) + 1; + state.heap_size = cparam->managed.width * DBLOCK_SIZE(fh, 0); + state.heap_size += cparam->managed.width * DBLOCK_SIZE(fh, 1); + state.heap_size += cparam->managed.width * DBLOCK_SIZE(fh, 2); + state.man_size = cparam->managed.width * DBLOCK_SIZE(fh, 0); + state.man_size += cparam->managed.width * DBLOCK_SIZE(fh, 1); + state.man_size += cparam->managed.width * DBLOCK_SIZE(fh, 2); + state.man_alloc_size = DBLOCK_SIZE(fh, 2); + state.man_free_space = cparam->managed.width * DBLOCK_FREE(fh, 0); + state.man_free_space += cparam->managed.width * DBLOCK_FREE(fh, 1); + state.man_free_space += cparam->managed.width * DBLOCK_FREE(fh, 2); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -4430,10 +4715,8 @@ test_abs_skip_start_block_add_back(hid_t fapl, H5HF_create_t *cparam, fheap_test H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -4457,7 +4740,8 @@ test_abs_skip_start_block_add_back(hid_t fapl, H5HF_create_t *cparam, fheap_test FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR - if(check_stats(fh, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0)) + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); + if(check_stats(fh, &state)) FAIL_STACK_ERROR /* @@ -4467,12 +4751,18 @@ test_abs_skip_start_block_add_back(hid_t fapl, H5HF_create_t *cparam, fheap_test TESTING("skipping starting block, then adding object back to first block"); /* Insert object too large for starting block size */ - obj_size = cparam->managed.start_block_size + 1; - free_space = 2 * cparam->managed.width * DBLOCK_FREE(fh, 0); - free_space += cparam->managed.width * DBLOCK_FREE(fh, 2); - heap_size = 2 * cparam->managed.width * cparam->managed.start_block_size; - heap_size += cparam->managed.width * (cparam->managed.start_block_size * 2); - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + obj_size = DBLOCK_SIZE(fh, 0) + 1; + state.heap_size = cparam->managed.width * DBLOCK_SIZE(fh, 0); + state.heap_size += cparam->managed.width * DBLOCK_SIZE(fh, 1); + state.heap_size += cparam->managed.width * DBLOCK_SIZE(fh, 2); + state.man_size = cparam->managed.width * DBLOCK_SIZE(fh, 0); + state.man_size += cparam->managed.width * DBLOCK_SIZE(fh, 1); + state.man_size += cparam->managed.width * DBLOCK_SIZE(fh, 2); + state.man_alloc_size = DBLOCK_SIZE(fh, 2); + state.man_free_space = cparam->managed.width * DBLOCK_FREE(fh, 0); + state.man_free_space += cparam->managed.width * DBLOCK_FREE(fh, 1); + state.man_free_space += cparam->managed.width * DBLOCK_FREE(fh, 2); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -4488,7 +4778,7 @@ test_abs_skip_start_block_add_back(hid_t fapl, H5HF_create_t *cparam, fheap_test /* Insert an object to fill up the heap block just created */ obj_size = DBLOCK_FREE(fh, 2) - obj_size; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -4503,7 +4793,8 @@ test_abs_skip_start_block_add_back(hid_t fapl, H5HF_create_t *cparam, fheap_test } /* end if */ /* Insert second "real" object, which should go in earlier direct block */ - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, SMALL_OBJ_SIZE2)) + state.man_alloc_size += DBLOCK_SIZE(fh, 0); + if(add_obj(fh, dxpl, 20, SMALL_OBJ_SIZE2, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -4556,10 +4847,8 @@ test_abs_skip_start_block_add_skipped(hid_t fapl, H5HF_create_t *cparam, fheap_t H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -4583,7 +4872,8 @@ test_abs_skip_start_block_add_skipped(hid_t fapl, H5HF_create_t *cparam, fheap_t FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR - if(check_stats(fh, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0)) + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); + if(check_stats(fh, &state)) FAIL_STACK_ERROR /* @@ -4593,12 +4883,18 @@ test_abs_skip_start_block_add_skipped(hid_t fapl, H5HF_create_t *cparam, fheap_t TESTING("skipping starting block, then adding objects to backfill and extend"); /* Insert object too large for starting block size */ - obj_size = cparam->managed.start_block_size + 1; - free_space = 2 * cparam->managed.width * DBLOCK_FREE(fh, 0); - free_space += cparam->managed.width * DBLOCK_FREE(fh, 2); - heap_size = 2 * cparam->managed.width * cparam->managed.start_block_size; - heap_size += cparam->managed.width * (cparam->managed.start_block_size * 2); - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + obj_size = DBLOCK_SIZE(fh, 0) + 1; + state.heap_size = cparam->managed.width * DBLOCK_SIZE(fh, 0); + state.heap_size += cparam->managed.width * DBLOCK_SIZE(fh, 1); + state.heap_size += cparam->managed.width * DBLOCK_SIZE(fh, 2); + state.man_size = cparam->managed.width * DBLOCK_SIZE(fh, 0); + state.man_size += cparam->managed.width * DBLOCK_SIZE(fh, 1); + state.man_size += cparam->managed.width * DBLOCK_SIZE(fh, 2); + state.man_alloc_size = DBLOCK_SIZE(fh, 2); + state.man_free_space = cparam->managed.width * DBLOCK_FREE(fh, 0); + state.man_free_space += cparam->managed.width * DBLOCK_FREE(fh, 1); + state.man_free_space += cparam->managed.width * DBLOCK_FREE(fh, 2); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -4614,7 +4910,7 @@ test_abs_skip_start_block_add_skipped(hid_t fapl, H5HF_create_t *cparam, fheap_t /* Insert an object to fill up the heap block just created */ obj_size = DBLOCK_FREE(fh, 2) - obj_size; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -4629,9 +4925,9 @@ test_abs_skip_start_block_add_skipped(hid_t fapl, H5HF_create_t *cparam, fheap_t } /* end if */ /* Add rows of blocks to "backfill" direct blocks that were skipped */ - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, 0, &nobjs)) + if(fill_row(fh, dxpl, 0, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, 1, &nobjs)) + if(fill_row(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -4645,8 +4941,9 @@ test_abs_skip_start_block_add_skipped(hid_t fapl, H5HF_create_t *cparam, fheap_t FAIL_STACK_ERROR } /* end if */ - /* Insert another object, which should go extend direct blocks, instead of backfill */ - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, SMALL_OBJ_SIZE2)) + /* Insert another object, which should extend direct blocks, instead of backfill */ + state.man_alloc_size += DBLOCK_SIZE(fh, 2); + if(add_obj(fh, dxpl, 20, SMALL_OBJ_SIZE2, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -4699,10 +4996,8 @@ test_abs_skip_2nd_block(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *t H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -4726,6 +5021,7 @@ test_abs_skip_2nd_block(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *t FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting first (small) object into absolute heap @@ -4733,10 +5029,11 @@ test_abs_skip_2nd_block(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *t TESTING("insert object to initial block, then add object too large for starting direct blocks"); /* Insert small object, to create root direct block */ - obj_size = SMALL_OBJ_SIZE1; - free_space = DBLOCK_FREE(fh, 0); - heap_size = cparam->managed.start_block_size; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.heap_size = DBLOCK_SIZE(fh, 0); + state.man_size = DBLOCK_SIZE(fh, 0); + state.man_alloc_size = DBLOCK_SIZE(fh, 0); + state.man_free_space = DBLOCK_FREE(fh, 0); + if(add_obj(fh, dxpl, 10, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -4753,14 +5050,18 @@ test_abs_skip_2nd_block(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *t /* Insert large object, to force creation of indirect block and * range of skipped blocks that are too small to hold the second object */ - obj_size = cparam->managed.start_block_size + 1; - free_space += (cparam->managed.width - 1 )* DBLOCK_FREE(fh, 0); - free_space += cparam->managed.width * DBLOCK_FREE(fh, 1); - free_space += cparam->managed.width * DBLOCK_FREE(fh, 2); - heap_size += (cparam->managed.width - 1) * cparam->managed.start_block_size; - heap_size += cparam->managed.width * cparam->managed.start_block_size; - heap_size += cparam->managed.width * cparam->managed.start_block_size * 2; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + obj_size = DBLOCK_SIZE(fh, 0) + 1; + state.heap_size += (cparam->managed.width - 1) * DBLOCK_SIZE(fh, 0); + state.heap_size += cparam->managed.width * DBLOCK_SIZE(fh, 1); + state.heap_size += cparam->managed.width * DBLOCK_SIZE(fh, 2); + state.man_size += (cparam->managed.width - 1) * DBLOCK_SIZE(fh, 0); + state.man_size += cparam->managed.width * DBLOCK_SIZE(fh, 1); + state.man_size += cparam->managed.width * DBLOCK_SIZE(fh, 2); + state.man_alloc_size += DBLOCK_SIZE(fh, 2); + state.man_free_space += (cparam->managed.width - 1 )* DBLOCK_FREE(fh, 0); + state.man_free_space += cparam->managed.width * DBLOCK_FREE(fh, 1); + state.man_free_space += cparam->managed.width * DBLOCK_FREE(fh, 2); + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -4827,11 +5128,9 @@ test_abs_skip_2nd_block_add_skipped(hid_t fapl, H5HF_create_t *cparam, fheap_tes H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ - unsigned u, v; /* Local index variables */ + fheap_heap_state_t state; /* State of fractal heap */ + unsigned v; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -4855,6 +5154,7 @@ test_abs_skip_2nd_block_add_skipped(hid_t fapl, H5HF_create_t *cparam, fheap_tes FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test inserting first (small) object into absolute heap @@ -4862,10 +5162,11 @@ test_abs_skip_2nd_block_add_skipped(hid_t fapl, H5HF_create_t *cparam, fheap_tes TESTING("insert object to initial block, then add object too large for starting direct blocks, then backfill and extend"); /* Insert small object, to create root direct block */ - obj_size = SMALL_OBJ_SIZE1; - free_space = DBLOCK_FREE(fh, 0); - heap_size = cparam->managed.start_block_size; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.heap_size = DBLOCK_SIZE(fh, 0); + state.man_size = DBLOCK_SIZE(fh, 0); + state.man_alloc_size = DBLOCK_SIZE(fh, 0); + state.man_free_space = DBLOCK_FREE(fh, 0); + if(add_obj(fh, dxpl, 10, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -4882,14 +5183,18 @@ test_abs_skip_2nd_block_add_skipped(hid_t fapl, H5HF_create_t *cparam, fheap_tes /* Insert large object, to force creation of indirect block and * range of skipped blocks that are too small to hold the second object */ - obj_size = cparam->managed.start_block_size + 1; - free_space += (cparam->managed.width - 1 )* DBLOCK_FREE(fh, 0); - free_space += cparam->managed.width * DBLOCK_FREE(fh, 1); - free_space += cparam->managed.width * DBLOCK_FREE(fh, 2); - heap_size += (cparam->managed.width - 1) * cparam->managed.start_block_size; - heap_size += cparam->managed.width * cparam->managed.start_block_size; - heap_size += cparam->managed.width * cparam->managed.start_block_size * 2; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + obj_size = DBLOCK_SIZE(fh, 0) + 1; + state.heap_size += (cparam->managed.width - 1) * DBLOCK_SIZE(fh, 0); + state.heap_size += cparam->managed.width * DBLOCK_SIZE(fh, 1); + state.heap_size += cparam->managed.width * DBLOCK_SIZE(fh, 2); + state.man_size += (cparam->managed.width - 1) * DBLOCK_SIZE(fh, 0); + state.man_size += cparam->managed.width * DBLOCK_SIZE(fh, 1); + state.man_size += cparam->managed.width * DBLOCK_SIZE(fh, 2); + state.man_alloc_size += DBLOCK_SIZE(fh, 2); + state.man_free_space += (cparam->managed.width - 1 )* DBLOCK_FREE(fh, 0); + state.man_free_space += cparam->managed.width * DBLOCK_FREE(fh, 1); + state.man_free_space += cparam->managed.width * DBLOCK_FREE(fh, 2); + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -4905,7 +5210,7 @@ test_abs_skip_2nd_block_add_skipped(hid_t fapl, H5HF_create_t *cparam, fheap_tes /* Insert an object to fill up the (smaller) heap block just created */ obj_size = DBLOCK_FREE(fh, 0) - SMALL_OBJ_SIZE1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -4920,8 +5225,8 @@ test_abs_skip_2nd_block_add_skipped(hid_t fapl, H5HF_create_t *cparam, fheap_tes } /* end if */ /* Fill remainder of 2 * start size block */ - obj_size = DBLOCK_FREE(fh, 2) - (cparam->managed.start_block_size + 1); - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + obj_size = DBLOCK_FREE(fh, 2) - (DBLOCK_SIZE(fh, 0) + 1); + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -4936,15 +5241,18 @@ test_abs_skip_2nd_block_add_skipped(hid_t fapl, H5HF_create_t *cparam, fheap_tes } /* end if */ /* Insert objects to fill remaining rows of the starting block size */ - for(u = 0; u < 2; u++) { - /* Fill a row of direct heap blocks up */ - for(v = 0; v < (cparam->managed.width - 1); v++) { - free_space -= DBLOCK_FREE(fh, u); - if(fill_heap(fh, dxpl, cparam, heap_size, cparam->managed.start_block_size, free_space, &nobjs)) - FAIL_STACK_ERROR - } /* end for */ + + /* Fill remainder of first row of direct heap blocks up */ + for(v = 0; v < (cparam->managed.width - 1); v++) { + state.man_alloc_size += DBLOCK_SIZE(fh, 0); + if(fill_heap(fh, dxpl, 0, SMALL_OBJ_SIZE1, &state, NULL)) + FAIL_STACK_ERROR } /* end for */ + /* Fill second row of direct blocks */ + if(fill_row(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) + FAIL_STACK_ERROR + /* Check for closing & re-opening the heap */ if(tparam->reopen_heap) { /* Close heap */ @@ -4957,8 +5265,8 @@ test_abs_skip_2nd_block_add_skipped(hid_t fapl, H5HF_create_t *cparam, fheap_tes } /* end if */ /* Insert one more object, to create new 2 * start size direct block */ - obj_size = SMALL_OBJ_SIZE1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, 2); + if(add_obj(fh, dxpl, 10, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -5016,10 +5324,8 @@ test_abs_fill_one_partial_skip_2nd_block_add_skipped(hid_t fapl, H5HF_create_t * H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ unsigned u; /* Local index variable */ /* Set the filename to use for this test (dependent on fapl) */ @@ -5044,6 +5350,7 @@ test_abs_fill_one_partial_skip_2nd_block_add_skipped(hid_t fapl, H5HF_create_t * FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test absolute heap @@ -5051,9 +5358,11 @@ test_abs_fill_one_partial_skip_2nd_block_add_skipped(hid_t fapl, H5HF_create_t * TESTING("skipping blocks with indirect root, then backfill and extend"); /* Fill initial direct block */ - heap_size = cparam->managed.start_block_size; - free_space = 0; - if(fill_heap(fh, dxpl, cparam, heap_size, cparam->managed.start_block_size, free_space, &nobjs)) + state.heap_size = DBLOCK_SIZE(fh, 0); + state.man_size = DBLOCK_SIZE(fh, 0); + state.man_alloc_size = DBLOCK_SIZE(fh, 0); + state.man_free_space = DBLOCK_FREE(fh, 0); + if(fill_heap(fh, dxpl, 0, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -5068,10 +5377,11 @@ test_abs_fill_one_partial_skip_2nd_block_add_skipped(hid_t fapl, H5HF_create_t * } /* end if */ /* Insert small object, to create root indirect block */ - obj_size = SMALL_OBJ_SIZE1; - heap_size += (cparam->managed.width - 1) * cparam->managed.start_block_size; - free_space += (cparam->managed.width - 1) * DBLOCK_FREE(fh, 0); - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.heap_size += (cparam->managed.width - 1) * DBLOCK_SIZE(fh, 0); + state.man_size += (cparam->managed.width - 1) * DBLOCK_SIZE(fh, 0); + state.man_alloc_size += DBLOCK_SIZE(fh, 0); + state.man_free_space += (cparam->managed.width - 1) * DBLOCK_FREE(fh, 0); + if(add_obj(fh, dxpl, 10, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -5088,14 +5398,18 @@ test_abs_fill_one_partial_skip_2nd_block_add_skipped(hid_t fapl, H5HF_create_t * /* Insert large object, to force creation of indirect block and * range of skipped blocks that are too small to hold the large object */ - obj_size = (2 * cparam->managed.start_block_size) + 1; - heap_size += cparam->managed.width * cparam->managed.start_block_size; - heap_size += cparam->managed.width * cparam->managed.start_block_size * 2; - heap_size += cparam->managed.width * cparam->managed.start_block_size * 4; - free_space += cparam->managed.width * DBLOCK_FREE(fh, 1); - free_space += cparam->managed.width * DBLOCK_FREE(fh, 2); - free_space += cparam->managed.width * DBLOCK_FREE(fh, 3); - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + obj_size = DBLOCK_SIZE(fh, 2) + 1; + state.heap_size += cparam->managed.width * DBLOCK_SIZE(fh, 1); + state.heap_size += cparam->managed.width * DBLOCK_SIZE(fh, 2); + state.heap_size += cparam->managed.width * DBLOCK_SIZE(fh, 3); + state.man_size += cparam->managed.width * DBLOCK_SIZE(fh, 1); + state.man_size += cparam->managed.width * DBLOCK_SIZE(fh, 2); + state.man_size += cparam->managed.width * DBLOCK_SIZE(fh, 3); + state.man_alloc_size += DBLOCK_SIZE(fh, 3); + state.man_free_space += cparam->managed.width * DBLOCK_FREE(fh, 1); + state.man_free_space += cparam->managed.width * DBLOCK_FREE(fh, 2); + state.man_free_space += cparam->managed.width * DBLOCK_FREE(fh, 3); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -5111,7 +5425,7 @@ test_abs_fill_one_partial_skip_2nd_block_add_skipped(hid_t fapl, H5HF_create_t * /* Insert an object to fill up the (smaller) heap block just created */ obj_size = DBLOCK_FREE(fh, 0) - SMALL_OBJ_SIZE1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -5126,8 +5440,8 @@ test_abs_fill_one_partial_skip_2nd_block_add_skipped(hid_t fapl, H5HF_create_t * } /* end if */ /* Insert object to fill remainder of 4 * start size block */ - obj_size = DBLOCK_FREE(fh, 3) - ((2 * cparam->managed.start_block_size) + 1); - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + obj_size = DBLOCK_FREE(fh, 3) - (DBLOCK_SIZE(fh, 2) + 1); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -5144,8 +5458,8 @@ test_abs_fill_one_partial_skip_2nd_block_add_skipped(hid_t fapl, H5HF_create_t * /* Insert objects to fill remaining heaps in first row */ for(u = 0; u < (cparam->managed.width - 2); u++) { /* Fill a direct heap block up */ - free_space -= DBLOCK_FREE(fh, 0); - if(fill_heap(fh, dxpl, cparam, heap_size, cparam->managed.start_block_size, free_space, &nobjs)) + state.man_alloc_size += DBLOCK_SIZE(fh, 0); + if(fill_heap(fh, dxpl, 0, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR } /* end for */ @@ -5161,7 +5475,7 @@ test_abs_fill_one_partial_skip_2nd_block_add_skipped(hid_t fapl, H5HF_create_t * } /* end if */ /* Insert objects to fill remaining heaps in second row */ - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, 1, &nobjs)) + if(fill_row(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -5176,7 +5490,7 @@ test_abs_fill_one_partial_skip_2nd_block_add_skipped(hid_t fapl, H5HF_create_t * } /* end if */ /* Insert objects to fill remaining heaps in third row */ - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, 2, &nobjs)) + if(fill_row(fh, dxpl, 2, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -5191,8 +5505,8 @@ test_abs_fill_one_partial_skip_2nd_block_add_skipped(hid_t fapl, H5HF_create_t * } /* end if */ /* Insert one more object, to create new 4 * start size direct block */ - obj_size = SMALL_OBJ_SIZE1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, 3); + if(add_obj(fh, dxpl, 10, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -5249,10 +5563,8 @@ test_abs_fill_row_skip_add_skipped(hid_t fapl, H5HF_create_t *cparam, fheap_test H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -5276,6 +5588,7 @@ test_abs_fill_row_skip_add_skipped(hid_t fapl, H5HF_create_t *cparam, fheap_test FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test absolute heap @@ -5283,9 +5596,7 @@ test_abs_fill_row_skip_add_skipped(hid_t fapl, H5HF_create_t *cparam, fheap_test TESTING("filling first row, then skipping rows, then backfill and extend"); /* Fill first row of direct blocks */ - heap_size = 0; - free_space = 0; - if(fill_root_row(fh, dxpl, cparam, &heap_size, &free_space, 0, &nobjs)) + if(fill_root_row(fh, dxpl, 0, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -5302,14 +5613,18 @@ test_abs_fill_row_skip_add_skipped(hid_t fapl, H5HF_create_t *cparam, fheap_test /* Insert large object, to force creation of indirect block and * range of skipped blocks that are too small to hold the large object */ - obj_size = (2 * cparam->managed.start_block_size) + 1; - heap_size += cparam->managed.width * DBLOCK_SIZE(fh, 1); - heap_size += cparam->managed.width * DBLOCK_SIZE(fh, 2); - heap_size += cparam->managed.width * DBLOCK_SIZE(fh, 3); - free_space += cparam->managed.width * DBLOCK_FREE(fh, 1); - free_space += cparam->managed.width * DBLOCK_FREE(fh, 2); - free_space += cparam->managed.width * DBLOCK_FREE(fh, 3); - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + obj_size = DBLOCK_SIZE(fh, 2) + 1; + state.heap_size += cparam->managed.width * DBLOCK_SIZE(fh, 1); + state.heap_size += cparam->managed.width * DBLOCK_SIZE(fh, 2); + state.heap_size += cparam->managed.width * DBLOCK_SIZE(fh, 3); + state.man_size += cparam->managed.width * DBLOCK_SIZE(fh, 1); + state.man_size += cparam->managed.width * DBLOCK_SIZE(fh, 2); + state.man_size += cparam->managed.width * DBLOCK_SIZE(fh, 3); + state.man_alloc_size += DBLOCK_SIZE(fh, 3); + state.man_free_space += cparam->managed.width * DBLOCK_FREE(fh, 1); + state.man_free_space += cparam->managed.width * DBLOCK_FREE(fh, 2); + state.man_free_space += cparam->managed.width * DBLOCK_FREE(fh, 3); + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -5325,7 +5640,7 @@ test_abs_fill_row_skip_add_skipped(hid_t fapl, H5HF_create_t *cparam, fheap_test /* Insert object to fill remainder of 4 * start size block */ obj_size = DBLOCK_FREE(fh, 3) - obj_size; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -5340,7 +5655,7 @@ test_abs_fill_row_skip_add_skipped(hid_t fapl, H5HF_create_t *cparam, fheap_test } /* end if */ /* Insert objects to fill remaining heaps in second row */ - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, 1, &nobjs)) + if(fill_row(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -5355,7 +5670,7 @@ test_abs_fill_row_skip_add_skipped(hid_t fapl, H5HF_create_t *cparam, fheap_test } /* end if */ /* Insert objects to fill remaining heaps in third row */ - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, 2, &nobjs)) + if(fill_row(fh, dxpl, 2, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -5370,8 +5685,8 @@ test_abs_fill_row_skip_add_skipped(hid_t fapl, H5HF_create_t *cparam, fheap_test } /* end if */ /* Insert one more object, to create new 4 * start size direct block */ - obj_size = SMALL_OBJ_SIZE1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, 3); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -5424,10 +5739,8 @@ test_abs_fill_direct_skip_indirect_start_block_add_skipped(hid_t fapl, H5HF_crea H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -5451,6 +5764,7 @@ test_abs_fill_direct_skip_indirect_start_block_add_skipped(hid_t fapl, H5HF_crea FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test absolute heap @@ -5458,9 +5772,7 @@ test_abs_fill_direct_skip_indirect_start_block_add_skipped(hid_t fapl, H5HF_crea TESTING("filling direct blocks and skipping blocks in non-root indirect block, then backfill and extend"); /* Fill direct blocks in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -5477,8 +5789,9 @@ test_abs_fill_direct_skip_indirect_start_block_add_skipped(hid_t fapl, H5HF_crea /* Insert large object, to force creation of indirect block and * range of skipped blocks that are too small to hold the large object */ - obj_size = (2 * cparam->managed.start_block_size) + 1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + obj_size = DBLOCK_SIZE(fh, 2) + 1; + state.man_alloc_size += DBLOCK_SIZE(fh, 3); + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -5493,9 +5806,9 @@ test_abs_fill_direct_skip_indirect_start_block_add_skipped(hid_t fapl, H5HF_crea } /* end if */ /* Add rows of blocks to "backfill" direct blocks that were skipped */ - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, 0, &nobjs)) + if(fill_row(fh, dxpl, 0, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, 1, &nobjs)) + if(fill_row(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -5510,8 +5823,8 @@ test_abs_fill_direct_skip_indirect_start_block_add_skipped(hid_t fapl, H5HF_crea } /* end if */ /* Insert an object to fill up the (biggest) heap block created */ - obj_size = DBLOCK_FREE(fh, 3) - ((2 * cparam->managed.start_block_size) + 1); - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + obj_size = DBLOCK_FREE(fh, 3) - obj_size; + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -5526,7 +5839,7 @@ test_abs_fill_direct_skip_indirect_start_block_add_skipped(hid_t fapl, H5HF_crea } /* end if */ /* Fill direct block heaps with 2 * initial block size in nested indirect block */ - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, 2, &nobjs)) + if(fill_row(fh, dxpl, 2, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -5542,7 +5855,8 @@ test_abs_fill_direct_skip_indirect_start_block_add_skipped(hid_t fapl, H5HF_crea /* Insert one more object, to create new 4 * start size direct block */ obj_size = SMALL_OBJ_SIZE1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, 3); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -5596,16 +5910,10 @@ test_abs_fill_direct_skip_2nd_indirect_start_block_add_skipped(hid_t fapl, H5HF_ H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned first_row_bits; /* Number of bits used bit addresses in first row */ - unsigned first_indirect_block_size; /* Range of addresses covered by each of the first indirect blocks */ unsigned num_first_indirect_rows; /* Number of rows (of direct blocks) in each of the first indirect blocks */ - size_t obj_block_size; /* Size of block to hold large object added */ - size_t block_size; /* Size of block added */ unsigned row; /* Current row in indirect block */ - unsigned nobjs = 0; /* Number of objects inserted */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ unsigned u; /* Local index variable */ /* Set the filename to use for this test (dependent on fapl) */ @@ -5630,18 +5938,12 @@ test_abs_fill_direct_skip_2nd_indirect_start_block_add_skipped(hid_t fapl, H5HF_ FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); - /* Compute # of bits used in first row */ - first_row_bits = H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width); - first_indirect_block_size = 2 * cparam->managed.max_direct_size; - num_first_indirect_rows = (H5V_log2_of2(first_indirect_block_size) - first_row_bits) + 1; - obj_block_size = 1 << ((num_first_indirect_rows + H5V_log2_of2(cparam->managed.start_block_size)) - 1); + /* Retrieve info about heap */ + num_first_indirect_rows = IBLOCK_MAX_DROWS(fh, 1); #ifdef QAK -HDfprintf(stderr, "first_row_bits = %u\n", first_row_bits); -HDfprintf(stderr, "first_indirect_block_size = %u\n", first_indirect_block_size); HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); -HDfprintf(stderr, "obj_block_size = %Zu\n", obj_block_size); #endif /* QAK */ /* @@ -5650,9 +5952,7 @@ HDfprintf(stderr, "obj_block_size = %Zu\n", obj_block_size); TESTING("filling direct blocks and skipping row of non-root indirect blocks, then backfill and extend"); /* Fill direct blocks in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -5670,11 +5970,12 @@ HDfprintf(stderr, "obj_block_size = %Zu\n", obj_block_size); * range of skipped (indirect) blocks that are too small to hold the large * object */ - obj_size = (1 << ((num_first_indirect_rows + H5V_log2_of2(cparam->managed.start_block_size)) - 2)) + 1; + obj_size = DBLOCK_SIZE(fh, num_first_indirect_rows - 1) + 1; #ifdef QAK HDfprintf(stderr, "obj_size = %Zu\n", obj_size); #endif /* QAK */ - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, num_first_indirect_rows); + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -5690,7 +5991,7 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); /* Insert object to fill space in (large) block created */ obj_size = DBLOCK_FREE(fh, num_first_indirect_rows) - obj_size; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -5705,23 +6006,16 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); } /* end if */ /* Fill all rows of direct blocks that are smaller than large object's block size */ - block_size = cparam->managed.start_block_size; - row = 0; - while(block_size < obj_block_size) { + for(row = 0; row < num_first_indirect_rows; row++) { /* Fill rows of direct blocks in skipped indirect blocks */ for(u = 0; u < cparam->managed.width; u++) - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, row, &nobjs)) + if(fill_row(fh, dxpl, row, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill row of direct blocks in largest (i.e. non-skipped) indirect block */ - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, row, &nobjs)) + if(fill_row(fh, dxpl, row, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR - - /* Advance position in blocks */ - if(row > 0) - block_size *= 2; - row++; - } /* end while */ + } /* end for */ /* Check for closing & re-opening the heap */ if(tparam->reopen_heap) { @@ -5736,7 +6030,8 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); /* Add one more object, to create another "large" block */ obj_size = SMALL_OBJ_SIZE1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, num_first_indirect_rows); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -5791,13 +6086,9 @@ test_abs_fill_2nd_direct_less_one_wrap_start_block_add_skipped(hid_t fapl, H5HF_ H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned first_row_bits; /* Number of bits used bit addresses in first row */ - unsigned first_indirect_block_size; /* Range of addresses covered by each of the first indirect blocks */ unsigned num_first_indirect_rows; /* Number of rows (of direct blocks) in each of the first indirect blocks */ - unsigned nobjs = 0; /* Number of objects inserted */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ unsigned u; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ @@ -5822,15 +6113,11 @@ test_abs_fill_2nd_direct_less_one_wrap_start_block_add_skipped(hid_t fapl, H5HF_ FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); - /* Compute # of bits used in first row */ - first_row_bits = H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width); - first_indirect_block_size = 2 * cparam->managed.max_direct_size; - num_first_indirect_rows = (H5V_log2_of2(first_indirect_block_size) - first_row_bits) + 1; + /* Retrieve info about heap */ + num_first_indirect_rows = IBLOCK_MAX_DROWS(fh, 1); #ifdef QAK -HDfprintf(stderr, "first_row_bits = %u\n", first_row_bits); -HDfprintf(stderr, "first_indirect_block_size = %u\n", first_indirect_block_size); HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); #endif /* QAK */ @@ -5840,9 +6127,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); TESTING("filling direct blocks, filling 2nd level indirect blocks, except last one, and insert object too large for 2nd level indirect blocks, then backfill and extend"); /* Fill direct blocks in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -5857,11 +6142,10 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill first row (except one) of 2nd level indirect blocks */ - for(u = 0; u < cparam->managed.width - 1; u++) { + for(u = 0; u < cparam->managed.width - 1; u++) /* Fill all rows of 2nd level indirect blocks in root block */ - if(fill_2nd_indirect(fh, dxpl, cparam, &heap_size, &free_space, &nobjs, 1)) + if(fill_2nd_indirect(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR - } /* end for */ /* Check for closing & re-opening the heap */ if(tparam->reopen_heap) { @@ -5878,11 +6162,12 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); * range of skipped (indirect) blocks that are too small to hold the large * object */ - obj_size = (1 << ((num_first_indirect_rows + H5V_log2_of2(cparam->managed.start_block_size)) - 2)) + 1; + obj_size = DBLOCK_SIZE(fh, num_first_indirect_rows - 1) + 1; #ifdef QAK HDfprintf(stderr, "obj_size = %Zu\n", obj_size); #endif /* QAK */ - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, num_first_indirect_rows); + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -5898,7 +6183,7 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); /* Insert object to fill space in (large) block created */ obj_size = DBLOCK_FREE(fh, num_first_indirect_rows) - obj_size; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -5917,11 +6202,11 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); */ for(u = 0; u < num_first_indirect_rows; u++) { /* Direct block rows in skipped 2nd level indirect block */ - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, u, &nobjs)) + if(fill_row(fh, dxpl, u, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Direct block row in current 2nd level indirect block */ - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, u, &nobjs)) + if(fill_row(fh, dxpl, u, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR } /* end for */ @@ -5938,7 +6223,8 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); /* Add one more object, to create another "large" block */ obj_size = SMALL_OBJ_SIZE1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, num_first_indirect_rows); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -5996,16 +6282,10 @@ test_abs_fill_direct_skip_2nd_indirect_skip_2nd_block_add_skipped(hid_t fapl, H5 H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned first_row_bits; /* Number of bits used bit addresses in first row */ - unsigned first_indirect_block_size; /* Range of addresses covered by each of the first indirect blocks */ unsigned num_first_indirect_rows; /* Number of rows (of direct blocks) in each of the first indirect blocks */ - size_t obj_block_size; /* Size of block to hold large object added */ - size_t block_size; /* Size of block added */ unsigned row; /* Current row in indirect block */ - unsigned nobjs = 0; /* Number of objects inserted */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ unsigned u; /* Local index variable */ /* Set the filename to use for this test (dependent on fapl) */ @@ -6030,18 +6310,12 @@ test_abs_fill_direct_skip_2nd_indirect_skip_2nd_block_add_skipped(hid_t fapl, H5 FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); - /* Compute # of bits used in first row */ - first_row_bits = H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width); - first_indirect_block_size = 2 * cparam->managed.max_direct_size; - num_first_indirect_rows = (H5V_log2_of2(first_indirect_block_size) - first_row_bits) + 1; - obj_block_size = 1 << ((num_first_indirect_rows + H5V_log2_of2(cparam->managed.start_block_size)) - 1); + /* Retrieve info about heap */ + num_first_indirect_rows = IBLOCK_MAX_DROWS(fh, 1); #ifdef QAK -HDfprintf(stderr, "first_row_bits = %u\n", first_row_bits); -HDfprintf(stderr, "first_indirect_block_size = %u\n", first_indirect_block_size); HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); -HDfprintf(stderr, "obj_block_size = %Zu\n", obj_block_size); #endif /* QAK */ /* @@ -6050,9 +6324,7 @@ HDfprintf(stderr, "obj_block_size = %Zu\n", obj_block_size); TESTING("filling direct blocks and skipping row of non-root indirect blocks, then skip row of direct blocks, then backfill and extend"); /* Fill direct blocks in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -6070,11 +6342,12 @@ HDfprintf(stderr, "obj_block_size = %Zu\n", obj_block_size); * range of skipped (indirect) blocks that are too small to hold the large * object */ - obj_size = (1 << ((num_first_indirect_rows + H5V_log2_of2(cparam->managed.start_block_size)) - 2)) + 1; + obj_size = DBLOCK_SIZE(fh, num_first_indirect_rows - 1) + 1; #ifdef QAK HDfprintf(stderr, "obj_size = %Zu\n", obj_size); #endif /* QAK */ - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, num_first_indirect_rows); + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -6090,7 +6363,7 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); /* Insert object to fill space in (large) block created */ obj_size = DBLOCK_FREE(fh, num_first_indirect_rows) - obj_size; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -6105,11 +6378,12 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); } /* end if */ /* Insert object too large for initial block size in skipped indirect blocks */ - obj_size = (cparam->managed.start_block_size * 4) + 1; + obj_size = DBLOCK_SIZE(fh, 3) + 1; #ifdef QAK HDfprintf(stderr, "obj_size = %Zu\n", obj_size); #endif /* QAK */ - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, 4); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -6128,7 +6402,7 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); #ifdef QAK HDfprintf(stderr, "obj_size = %Zu\n", obj_size); #endif /* QAK */ - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -6144,12 +6418,11 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); /* Finish off blocks in row of medium block size (just to make row filling easier below) */ obj_size = DBLOCK_FREE(fh, 4); - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) - FAIL_STACK_ERROR - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) - FAIL_STACK_ERROR - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) - FAIL_STACK_ERROR + for(u = 1; u < cparam->managed.width; u++) { + state.man_alloc_size += DBLOCK_SIZE(fh, 4); + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) + FAIL_STACK_ERROR + } /* end for */ /* Check for closing & re-opening the heap */ if(tparam->reopen_heap) { @@ -6163,24 +6436,17 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); } /* end if */ /* Fill all rows of direct blocks that are smaller than large object's block size */ - block_size = cparam->managed.start_block_size; - row = 0; - while(block_size < obj_block_size) { + for(row = 0; row < num_first_indirect_rows; row++) { /* Fill rows of direct blocks in skipped indirect blocks */ for(u = 0; u < cparam->managed.width; u++) - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, row, &nobjs)) + if(fill_row(fh, dxpl, row, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill row of direct blocks in largest (i.e. non-skipped) indirect block */ /* (Skip the row of blocks filled above) */ if(row != 4) - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, row, &nobjs)) + if(fill_row(fh, dxpl, row, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR - - /* Advance position in blocks */ - if(row > 0) - block_size *= 2; - row++; } /* end while */ /* Check for closing & re-opening the heap */ @@ -6196,7 +6462,8 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); /* Add one more object, to create another "large" block */ obj_size = SMALL_OBJ_SIZE1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, num_first_indirect_rows); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -6249,13 +6516,10 @@ test_abs_fill_direct_skip_indirect_two_rows_add_skipped(hid_t fapl, H5HF_create_ H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned first_row_bits; /* Number of bits used bit addresses in first row */ - unsigned first_indirect_block_size; /* Range of addresses covered by each of the first indirect blocks */ unsigned num_first_indirect_rows; /* Number of rows (of direct blocks) in each of the first indirect blocks */ - unsigned nobjs = 0; /* Number of objects inserted */ + unsigned max_dblock_rows; /* Max. # of rows (of direct blocks) in the root indirect block */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ unsigned u, v; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ @@ -6280,12 +6544,11 @@ test_abs_fill_direct_skip_indirect_two_rows_add_skipped(hid_t fapl, H5HF_create_ FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); - /* Compute # of bits used in first row */ - first_row_bits = H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width); - first_indirect_block_size = 2 * cparam->managed.max_direct_size; - num_first_indirect_rows = (H5V_log2_of2(first_indirect_block_size) - first_row_bits) + 1; + /* Retrieve info about heap */ + num_first_indirect_rows = IBLOCK_MAX_DROWS(fh, 1); + max_dblock_rows = DTABLE_MAX_DROWS(fh); /* * Test absolute heap @@ -6293,9 +6556,7 @@ test_abs_fill_direct_skip_indirect_two_rows_add_skipped(hid_t fapl, H5HF_create_ TESTING("filling direct blocks and skipping two rows of root indirect block, then backfill and extend"); /* Fill direct blocks in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -6312,8 +6573,9 @@ test_abs_fill_direct_skip_indirect_two_rows_add_skipped(hid_t fapl, H5HF_create_ /* Insert large object, to force creation of indirect block and * range of skipped blocks that are too small to hold the large object */ - obj_size = (cparam->managed.max_direct_size / 2) + 1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + obj_size = DBLOCK_SIZE(fh, max_dblock_rows - 2) + 1; + state.man_alloc_size += DBLOCK_SIZE(fh, max_dblock_rows - 1); + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -6328,8 +6590,8 @@ test_abs_fill_direct_skip_indirect_two_rows_add_skipped(hid_t fapl, H5HF_create_ } /* end if */ /* Insert an object to fill up the (biggest) heap block created */ - obj_size = DBLOCK_FREE(fh, num_first_indirect_rows + 1) - obj_size; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + obj_size = DBLOCK_FREE(fh, max_dblock_rows - 1) - obj_size; + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -6343,21 +6605,20 @@ test_abs_fill_direct_skip_indirect_two_rows_add_skipped(hid_t fapl, H5HF_create_ FAIL_STACK_ERROR } /* end if */ - /* Fill rows skipped over in indirect block's direct blocks - */ + /* Fill rows skipped over in indirect block's direct blocks */ for(u = 0; u < num_first_indirect_rows; u++) { /* Direct block rows in first row of skipped 2nd level indirect blocks */ for(v = 0; v < cparam->managed.width; v++) - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, u, &nobjs)) + if(fill_row(fh, dxpl, u, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Direct block rows in second row of skipped 2nd level indirect blocks */ for(v = 0; v < cparam->managed.width; v++) - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, u, &nobjs)) + if(fill_row(fh, dxpl, u, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Direct block row in used 2nd level indirect block */ - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, u, &nobjs)) + if(fill_row(fh, dxpl, u, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR } /* end for */ @@ -6376,7 +6637,7 @@ test_abs_fill_direct_skip_indirect_two_rows_add_skipped(hid_t fapl, H5HF_create_ /* Direct block rows in skipped 2nd level indirect blocks */ for(v = 0; v < cparam->managed.width; v++) - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, num_first_indirect_rows, &nobjs)) + if(fill_row(fh, dxpl, num_first_indirect_rows, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -6391,7 +6652,7 @@ test_abs_fill_direct_skip_indirect_two_rows_add_skipped(hid_t fapl, H5HF_create_ } /* end if */ /* Direct block row in used 2nd level indirect block */ - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, num_first_indirect_rows, &nobjs)) + if(fill_row(fh, dxpl, num_first_indirect_rows, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -6407,7 +6668,8 @@ test_abs_fill_direct_skip_indirect_two_rows_add_skipped(hid_t fapl, H5HF_create_ /* Add one more object, to create another "large" block */ obj_size = SMALL_OBJ_SIZE1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, max_dblock_rows - 1); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -6461,10 +6723,8 @@ test_abs_fill_2nd_direct_skip_start_block_add_skipped(hid_t fapl, H5HF_create_t H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -6488,6 +6748,7 @@ test_abs_fill_2nd_direct_skip_start_block_add_skipped(hid_t fapl, H5HF_create_t FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test absolute heap @@ -6495,9 +6756,7 @@ test_abs_fill_2nd_direct_skip_start_block_add_skipped(hid_t fapl, H5HF_create_t TESTING("filling direct blocks, filling 2nd level indirect blocks, and skip first rows of direct blocks of 3rd level indirect block, then backfill and extend"); /* Fill direct blocks in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -6512,7 +6771,7 @@ test_abs_fill_2nd_direct_skip_start_block_add_skipped(hid_t fapl, H5HF_create_t } /* end if */ /* Fill all rows of 2nd level indirect blocks */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -6530,8 +6789,9 @@ test_abs_fill_2nd_direct_skip_start_block_add_skipped(hid_t fapl, H5HF_create_t * range of skipped (indirect) blocks that are too small to hold the large * object */ - obj_size = (cparam->managed.start_block_size * 2) + 1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + obj_size = DBLOCK_SIZE(fh, 2) + 1; + state.man_alloc_size += DBLOCK_SIZE(fh, 3); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -6547,7 +6807,7 @@ test_abs_fill_2nd_direct_skip_start_block_add_skipped(hid_t fapl, H5HF_create_t /* Insert object to fill space in (large) block created */ obj_size = DBLOCK_FREE(fh, 3) - obj_size; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -6562,11 +6822,11 @@ test_abs_fill_2nd_direct_skip_start_block_add_skipped(hid_t fapl, H5HF_create_t } /* end if */ /* Fill rows skipped over in 3rd level indirect block's direct blocks */ - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, 0, &nobjs)) + if(fill_row(fh, dxpl, 0, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, 1, &nobjs)) + if(fill_row(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, 2, &nobjs)) + if(fill_row(fh, dxpl, 2, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -6582,7 +6842,8 @@ test_abs_fill_2nd_direct_skip_start_block_add_skipped(hid_t fapl, H5HF_create_t /* Add one more object, to create another "large" block */ obj_size = SMALL_OBJ_SIZE1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, 3); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -6638,10 +6899,8 @@ test_abs_fill_2nd_direct_skip_2nd_indirect_start_block_add_skipped(hid_t fapl, H H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ /* Set the filename to use for this test (dependent on fapl) */ h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); @@ -6665,6 +6924,7 @@ test_abs_fill_2nd_direct_skip_2nd_indirect_start_block_add_skipped(hid_t fapl, H FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test absolute heap @@ -6672,9 +6932,7 @@ test_abs_fill_2nd_direct_skip_2nd_indirect_start_block_add_skipped(hid_t fapl, H TESTING("filling direct blocks, filling 2nd level indirect blocks, filling 3rd level indirect block's direct blocks, and skip first rows of direct blocks of 3rd level indirect block's 2nd level indirect block, then backfill and extend"); /* Fill direct blocks in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -6689,7 +6947,7 @@ test_abs_fill_2nd_direct_skip_2nd_indirect_start_block_add_skipped(hid_t fapl, H } /* end if */ /* Fill all rows of 2nd level indirect blocks */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -6704,7 +6962,7 @@ test_abs_fill_2nd_direct_skip_2nd_indirect_start_block_add_skipped(hid_t fapl, H } /* end if */ /* Fill all direct block rows in third level indirect block */ - if(fill_all_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -6722,8 +6980,9 @@ test_abs_fill_2nd_direct_skip_2nd_indirect_start_block_add_skipped(hid_t fapl, H * range of skipped (indirect) blocks that are too small to hold the large * object */ - obj_size = (cparam->managed.start_block_size * 2) + 1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + obj_size = DBLOCK_SIZE(fh, 2) + 1; + state.man_alloc_size += DBLOCK_SIZE(fh, 3); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -6739,7 +6998,7 @@ test_abs_fill_2nd_direct_skip_2nd_indirect_start_block_add_skipped(hid_t fapl, H /* Insert object to fill space in (large) block created */ obj_size = DBLOCK_FREE(fh, 3) - obj_size; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -6756,11 +7015,11 @@ test_abs_fill_2nd_direct_skip_2nd_indirect_start_block_add_skipped(hid_t fapl, H /* Fill rows skipped over in (3rd level indirect block's) 2nd level * indirect block's direct blocks */ - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, 0, &nobjs)) + if(fill_row(fh, dxpl, 0, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, 1, &nobjs)) + if(fill_row(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, 2, &nobjs)) + if(fill_row(fh, dxpl, 2, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -6776,7 +7035,8 @@ test_abs_fill_2nd_direct_skip_2nd_indirect_start_block_add_skipped(hid_t fapl, H /* Add one more object, to create another "large" block */ obj_size = SMALL_OBJ_SIZE1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, 3); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -6831,13 +7091,9 @@ test_abs_fill_2nd_direct_fill_direct_skip_3rd_indirect_start_block_add_skipped(h H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned first_row_bits; /* Number of bits used bit addresses in first row */ - unsigned first_indirect_block_size; /* Range of addresses covered by each of the first indirect blocks */ unsigned num_first_indirect_rows; /* Number of rows (of direct blocks) in each of the first indirect blocks */ - unsigned nobjs = 0; /* Number of objects inserted */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ unsigned u, v; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ @@ -6862,15 +7118,11 @@ test_abs_fill_2nd_direct_fill_direct_skip_3rd_indirect_start_block_add_skipped(h FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); - /* Compute # of bits used in first row */ - first_row_bits = H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width); - first_indirect_block_size = 2 * cparam->managed.max_direct_size; - num_first_indirect_rows = (H5V_log2_of2(first_indirect_block_size) - first_row_bits) + 1; + /* Retrieve info about heap */ + num_first_indirect_rows = IBLOCK_MAX_DROWS(fh, 1); #ifdef QAK -HDfprintf(stderr, "first_row_bits = %u\n", first_row_bits); -HDfprintf(stderr, "first_indirect_block_size = %u\n", first_indirect_block_size); HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); #endif /* QAK */ @@ -6880,9 +7132,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); TESTING("filling direct blocks, filling 2nd level indirect blocks, filling 3rd level indirect block's direct blocks, and skip first row of indirect blocks of 3rd level indirect block, then backfill and extend"); /* Fill direct blocks in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -6897,7 +7147,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all rows of 2nd level indirect blocks */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -6912,7 +7162,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all direct block rows in third level indirect block */ - if(fill_all_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -6930,11 +7180,12 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); * range of skipped (indirect) blocks that are too small to hold the large * object */ - obj_size = (1 << ((num_first_indirect_rows + H5V_log2_of2(cparam->managed.start_block_size)) - 2)) + 1; + obj_size = DBLOCK_SIZE(fh, num_first_indirect_rows - 1) + 1; #ifdef QAK HDfprintf(stderr, "obj_size = %Zu\n", obj_size); #endif /* QAK */ - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, num_first_indirect_rows); + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -6950,7 +7201,7 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); /* Insert object to fill space in (large) block created */ obj_size = DBLOCK_FREE(fh, num_first_indirect_rows) - obj_size; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -6971,11 +7222,11 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); for(u = 0; u < num_first_indirect_rows; u++) { /* Direct block rows in 2nd level indirect blocks */ for(v = 0; v < cparam->managed.width; v++) - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, u, &nobjs)) + if(fill_row(fh, dxpl, u, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Direct block row in 3rd level indirect block */ - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, u, &nobjs)) + if(fill_row(fh, dxpl, u, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR } /* end for */ @@ -6992,7 +7243,8 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); /* Add one more object, to create another "large" block */ obj_size = SMALL_OBJ_SIZE1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, num_first_indirect_rows); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -7048,13 +7300,9 @@ test_abs_fill_2nd_direct_fill_direct_skip2_3rd_indirect_start_block_add_skipped( H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned first_row_bits; /* Number of bits used bit addresses in first row */ - unsigned first_indirect_block_size; /* Range of addresses covered by each of the first indirect blocks */ unsigned num_first_indirect_rows; /* Number of rows (of direct blocks) in each of the first indirect blocks */ - unsigned nobjs = 0; /* Number of objects inserted */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ unsigned u, v; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ @@ -7079,15 +7327,11 @@ test_abs_fill_2nd_direct_fill_direct_skip2_3rd_indirect_start_block_add_skipped( FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); - /* Compute # of bits used in first row */ - first_row_bits = H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width); - first_indirect_block_size = 2 * cparam->managed.max_direct_size; - num_first_indirect_rows = (H5V_log2_of2(first_indirect_block_size) - first_row_bits) + 1; + /* Retrieve info about heap */ + num_first_indirect_rows = IBLOCK_MAX_DROWS(fh, 1); #ifdef QAK -HDfprintf(stderr, "first_row_bits = %u\n", first_row_bits); -HDfprintf(stderr, "first_indirect_block_size = %u\n", first_indirect_block_size); HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); #endif /* QAK */ @@ -7097,9 +7341,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); TESTING("filling direct blocks, filling 2nd level indirect blocks, filling 3rd level indirect block's direct blocks, and skip first two rows of indirect blocks of 3rd level indirect block, then backfill and extend"); /* Fill direct blocks in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -7114,7 +7356,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all rows of 2nd level indirect blocks */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -7129,7 +7371,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all direct block rows in third level indirect block */ - if(fill_all_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -7147,11 +7389,12 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); * range of skipped (indirect) blocks that are too small to hold the large * object */ - obj_size = (1 << ((num_first_indirect_rows + H5V_log2_of2(cparam->managed.start_block_size)) - 1)) + 1; + obj_size = DBLOCK_SIZE(fh, num_first_indirect_rows) + 1; #ifdef QAK HDfprintf(stderr, "obj_size = %Zu\n", obj_size); #endif /* QAK */ - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, num_first_indirect_rows + 1); + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -7170,7 +7413,7 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); #ifdef QAK HDfprintf(stderr, "obj_size = %Zu\n", obj_size); #endif /* QAK */ - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -7191,14 +7434,18 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); for(u = 0; u < num_first_indirect_rows; u++) { /* Direct block rows in 2nd level indirect blocks */ for(v = 0; v < cparam->managed.width; v++) - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, u, &nobjs)) + if(fill_row(fh, dxpl, u, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Direct block row in 3rd level indirect block */ - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, u, &nobjs)) + if(fill_row(fh, dxpl, u, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR } /* end for */ + /* Fill row of direct blocks in second 3rd level indirect block */ + if(fill_row(fh, dxpl, num_first_indirect_rows, SMALL_OBJ_SIZE1, &state, NULL)) + FAIL_STACK_ERROR + /* Check for closing & re-opening the heap */ if(tparam->reopen_heap) { /* Close heap */ @@ -7212,7 +7459,8 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); /* Add one more object, to create another "large" block */ obj_size = SMALL_OBJ_SIZE1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, num_first_indirect_rows + 1); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -7244,7 +7492,7 @@ error: * Purpose: Test filling all direct blocks in root indirect block and all * direct blocks in 2nd level indirect blocks, all 3rd level * indirect blocks in first row except the last one, fill direct - * blocks in lasts 3rd level indirect block, then insert object + * blocks in last 3rd level indirect block, then insert object * insert object that is too large to hold in last 3rd level * indirect block's row of 2nd level indirect blocks (forcing the * use of the next row of 3rd level blocks), then backfill all @@ -7269,13 +7517,9 @@ test_abs_fill_3rd_direct_less_one_fill_direct_wrap_start_block_add_skipped(hid_t H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned first_row_bits; /* Number of bits used bit addresses in first row */ - unsigned first_indirect_block_size; /* Range of addresses covered by each of the first indirect blocks */ unsigned num_first_indirect_rows; /* Number of rows (of direct blocks) in each of the first indirect blocks */ - unsigned nobjs = 0; /* Number of objects inserted */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ unsigned u, v; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ @@ -7300,15 +7544,11 @@ test_abs_fill_3rd_direct_less_one_fill_direct_wrap_start_block_add_skipped(hid_t FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); - /* Compute # of bits used in first row */ - first_row_bits = H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width); - first_indirect_block_size = 2 * cparam->managed.max_direct_size; - num_first_indirect_rows = (H5V_log2_of2(first_indirect_block_size) - first_row_bits) + 1; + /* Retrieve info about heap */ + num_first_indirect_rows = IBLOCK_MAX_DROWS(fh, 1); #ifdef QAK -HDfprintf(stderr, "first_row_bits = %u\n", first_row_bits); -HDfprintf(stderr, "first_indirect_block_size = %u\n", first_indirect_block_size); HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); #endif /* QAK */ @@ -7318,9 +7558,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); TESTING("filling direct blocks, filling 2nd level indirect blocks, filling first row of 3rd level indirect blocks, except last one, fill all direct blocks in last 3rd level indirect block, and insert object too large for it's 2nd level indirect blocks, then backfill and extend"); /* Fill direct blocks in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -7334,8 +7572,8 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); FAIL_STACK_ERROR } /* end if */ - /* Fill all rows of 2nd level indirect blocks in 4th level indirect block */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + /* Fill all rows of 2nd level indirect blocks in root indirect block */ + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -7352,7 +7590,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); /* Fill first row (except one) of 3rd level indirect blocks */ for(u = 0; u < cparam->managed.width - 1; u++) /* Fill 3rd level indirect block */ - if(fill_3rd_indirect(fh, dxpl, cparam, &heap_size, &free_space, &nobjs, 1)) + if(fill_3rd_indirect(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -7367,7 +7605,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all direct block rows in last third level indirect block */ - if(fill_all_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -7385,11 +7623,12 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); * range of skipped (indirect) blocks that are too small to hold the large * object */ - obj_size = (1 << ((num_first_indirect_rows + H5V_log2_of2(cparam->managed.start_block_size)) - 2)) + 1; + obj_size = DBLOCK_SIZE(fh, num_first_indirect_rows - 1) + 1; #ifdef QAK HDfprintf(stderr, "obj_size = %Zu\n", obj_size); #endif /* QAK */ - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, num_first_indirect_rows); + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -7405,7 +7644,7 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); /* Insert object to fill space in (large) block created */ obj_size = DBLOCK_FREE(fh, num_first_indirect_rows) - obj_size; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -7425,11 +7664,11 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); for(u = 0; u < num_first_indirect_rows; u++) { /* Direct block rows in 2nd level indirect blocks */ for(v = 0; v < cparam->managed.width; v++) - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, u, &nobjs)) + if(fill_row(fh, dxpl, u, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR - /* Direct block row in current 2nd level indirect block */ - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, u, &nobjs)) + /* Direct block row in current 3rd level indirect block */ + if(fill_row(fh, dxpl, u, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR } /* end for */ @@ -7446,7 +7685,8 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); /* Add one more object, to create another "large" block */ obj_size = SMALL_OBJ_SIZE1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, num_first_indirect_rows); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -7504,13 +7744,9 @@ test_abs_fill_1st_row_3rd_direct_fill_2nd_direct_less_one_wrap_start_block_add_s H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned first_row_bits; /* Number of bits used bit addresses in first row */ - unsigned first_indirect_block_size; /* Range of addresses covered by each of the first indirect blocks */ unsigned num_first_indirect_rows; /* Number of rows (of direct blocks) in each of the first indirect blocks */ - unsigned nobjs = 0; /* Number of objects inserted */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ unsigned u; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ @@ -7535,15 +7771,11 @@ test_abs_fill_1st_row_3rd_direct_fill_2nd_direct_less_one_wrap_start_block_add_s FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); - /* Compute # of bits used in first row */ - first_row_bits = H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width); - first_indirect_block_size = 2 * cparam->managed.max_direct_size; - num_first_indirect_rows = (H5V_log2_of2(first_indirect_block_size) - first_row_bits) + 1; + /* Retrieve info about heap */ + num_first_indirect_rows = IBLOCK_MAX_DROWS(fh, 1); #ifdef QAK -HDfprintf(stderr, "first_row_bits = %u\n", first_row_bits); -HDfprintf(stderr, "first_indirect_block_size = %u\n", first_indirect_block_size); HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); #endif /* QAK */ @@ -7553,9 +7785,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); TESTING("filling direct blocks, filling 2nd level indirect blocks, filling first row of 3rd level indirect blocks, fill all direct blocks in next 3rd level indirect block, fill all 1st row of 2nd level indirect blocks, except last one, and insert object too large for 2nd level indirect block, then backfill and extend"); /* Fill direct blocks in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -7570,7 +7800,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all rows of 2nd level indirect blocks in 4th level indirect block */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -7585,7 +7815,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill first row of 3rd level indirect blocks */ - if(fill_3rd_indirect_row(fh, dxpl, cparam, &heap_size, &free_space, &nobjs, 1)) + if(fill_3rd_indirect_row(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -7600,7 +7830,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all direct block rows in 2nd row third level indirect block */ - if(fill_all_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -7615,10 +7845,9 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill first row (except one) of 2nd level indirect blocks */ - for(u = 0; u < cparam->managed.width - 1; u++) { - if(fill_2nd_indirect(fh, dxpl, cparam, &heap_size, &free_space, &nobjs, 1)) + for(u = 0; u < cparam->managed.width - 1; u++) + if(fill_2nd_indirect(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR - } /* end for */ /* Check for closing & re-opening the heap */ if(tparam->reopen_heap) { @@ -7635,11 +7864,12 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); * range of skipped (indirect) blocks that are too small to hold the large * object */ - obj_size = (1 << ((num_first_indirect_rows + H5V_log2_of2(cparam->managed.start_block_size)) - 2)) + 1; + obj_size = DBLOCK_SIZE(fh, num_first_indirect_rows - 1) + 1; #ifdef QAK HDfprintf(stderr, "obj_size = %Zu\n", obj_size); #endif /* QAK */ - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, num_first_indirect_rows); + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -7655,7 +7885,7 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); /* Insert object to fill space in (large) block created */ obj_size = DBLOCK_FREE(fh, num_first_indirect_rows) - obj_size; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -7674,11 +7904,11 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); */ for(u = 0; u < num_first_indirect_rows; u++) { /* Direct block rows in skipped 2nd level indirect block */ - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, u, &nobjs)) + if(fill_row(fh, dxpl, u, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Direct block row in current 2nd level indirect block */ - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, u, &nobjs)) + if(fill_row(fh, dxpl, u, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR } /* end for */ @@ -7695,7 +7925,8 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); /* Add one more object, to create another "large" block */ obj_size = SMALL_OBJ_SIZE1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, num_first_indirect_rows); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -7751,13 +7982,9 @@ test_abs_fill_3rd_direct_fill_direct_skip_start_block_add_skipped(hid_t fapl, H5 H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned first_row_bits; /* Number of bits used bit addresses in first row */ - unsigned first_indirect_block_size; /* Range of addresses covered by each of the first indirect blocks */ unsigned num_first_indirect_rows; /* Number of rows (of direct blocks) in each of the first indirect blocks */ - unsigned nobjs = 0; /* Number of objects inserted */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ unsigned u, v; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ @@ -7782,15 +8009,11 @@ test_abs_fill_3rd_direct_fill_direct_skip_start_block_add_skipped(hid_t fapl, H5 FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); - /* Compute # of bits used in first row */ - first_row_bits = H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width); - first_indirect_block_size = 2 * cparam->managed.max_direct_size; - num_first_indirect_rows = (H5V_log2_of2(first_indirect_block_size) - first_row_bits) + 1; + /* Retrieve info about heap */ + num_first_indirect_rows = IBLOCK_MAX_DROWS(fh, 1); #ifdef QAK -HDfprintf(stderr, "first_row_bits = %u\n", first_row_bits); -HDfprintf(stderr, "first_indirect_block_size = %u\n", first_indirect_block_size); HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); #endif /* QAK */ @@ -7800,9 +8023,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); TESTING("filling direct blocks, filling 2nd level indirect blocks, filling 3rd level indirect blocks, fill 4th level indirect block's direct blocks, and skip first row of 2nd indirect blocks of 4th level indirect block, then backfill and extend"); /* Fill direct blocks in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -7817,7 +8038,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all rows of 2nd level indirect blocks */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -7832,7 +8053,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all rows of 3rd level indirect blocks */ - if(fill_all_3rd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_3rd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -7847,7 +8068,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all direct block rows in fourth level indirect block */ - if(fill_all_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -7865,11 +8086,12 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); * range of skipped (indirect) blocks that are too small to hold the large * object */ - obj_size = (1 << ((num_first_indirect_rows + H5V_log2_of2(cparam->managed.start_block_size)) - 2)) + 1; + obj_size = DBLOCK_SIZE(fh, num_first_indirect_rows - 1) + 1; #ifdef QAK HDfprintf(stderr, "obj_size = %Zu\n", obj_size); #endif /* QAK */ - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, num_first_indirect_rows); + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -7885,7 +8107,7 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); /* Insert object to fill space in (large) block created */ obj_size = DBLOCK_FREE(fh, num_first_indirect_rows) - obj_size; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -7906,11 +8128,11 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); for(u = 0; u < num_first_indirect_rows; u++) { /* Direct block rows in 2nd level indirect blocks */ for(v = 0; v < cparam->managed.width; v++) - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, u, &nobjs)) + if(fill_row(fh, dxpl, u, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Direct block row in 2nd level indirect block */ - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, u, &nobjs)) + if(fill_row(fh, dxpl, u, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR } /* end for */ @@ -7927,7 +8149,8 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); /* Add one more object, to create another "large" block */ obj_size = SMALL_OBJ_SIZE1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, num_first_indirect_rows); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -7959,9 +8182,11 @@ error: * Purpose: Test filling all direct blocks in root indirect block and all * direct blocks in 2nd level indirect blocks, fill all direct * blocks and indirect blocks in 3rd level indirect block, then - * fill all direct blocks in 4th level indirect block, then + * fill all direct blocks and 2nd level indirect blocks in 4th + * level indirect block, then * insert object that is too large to hold in first row of 2nd - * level indirect blocks of 4th level indirect block, then + * level indirect blocks of 4th level indirect block's first + * 3rd level indirect block, then * backfill all skipped direct blocks & extend. * * Return: Success: 0 @@ -7983,13 +8208,9 @@ test_abs_fill_3rd_direct_fill_2nd_direct_fill_direct_skip_3rd_indirect_start_blo H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned first_row_bits; /* Number of bits used bit addresses in first row */ - unsigned first_indirect_block_size; /* Range of addresses covered by each of the first indirect blocks */ unsigned num_first_indirect_rows; /* Number of rows (of direct blocks) in each of the first indirect blocks */ - unsigned nobjs = 0; /* Number of objects inserted */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ unsigned u, v; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ @@ -8014,15 +8235,11 @@ test_abs_fill_3rd_direct_fill_2nd_direct_fill_direct_skip_3rd_indirect_start_blo FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); - /* Compute # of bits used in first row */ - first_row_bits = H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width); - first_indirect_block_size = 2 * cparam->managed.max_direct_size; - num_first_indirect_rows = (H5V_log2_of2(first_indirect_block_size) - first_row_bits) + 1; + /* Retrieve info about heap */ + num_first_indirect_rows = IBLOCK_MAX_DROWS(fh, 1); #ifdef QAK -HDfprintf(stderr, "first_row_bits = %u\n", first_row_bits); -HDfprintf(stderr, "first_indirect_block_size = %u\n", first_indirect_block_size); HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); #endif /* QAK */ @@ -8032,9 +8249,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); TESTING("filling direct blocks, filling 2nd level indirect blocks, filling 3rd level indirect blocks, fill 4th level indirect block's direct, 2nd level indirect blocks and 3rd level direct block, and skip first row of 2nd indirect blocks of 4th level indirect block's 3rd level indirect block, then backfill and extend"); /* Fill direct blocks in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8049,7 +8264,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all rows of 2nd level indirect blocks */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8064,7 +8279,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all rows of 3rd level indirect blocks */ - if(fill_all_3rd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_3rd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8079,7 +8294,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all direct block rows in fourth level indirect block */ - if(fill_all_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8094,7 +8309,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all rows of 2nd level indirect blocks in fourth level indirect block */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8109,7 +8324,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all direct block rows in fourth level indirect block's 3rd level indirect block */ - if(fill_all_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8127,11 +8342,12 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); * range of skipped (indirect) blocks that are too small to hold the large * object */ - obj_size = (1 << ((num_first_indirect_rows + H5V_log2_of2(cparam->managed.start_block_size)) - 2)) + 1; + obj_size = DBLOCK_SIZE(fh, num_first_indirect_rows - 1) + 1; #ifdef QAK HDfprintf(stderr, "obj_size = %Zu\n", obj_size); #endif /* QAK */ - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, num_first_indirect_rows); + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8147,7 +8363,7 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); /* Insert object to fill space in (large) block created */ obj_size = DBLOCK_FREE(fh, num_first_indirect_rows) - obj_size; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8168,11 +8384,11 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); for(u = 0; u < num_first_indirect_rows; u++) { /* Direct block rows in 2nd level indirect blocks */ for(v = 0; v < cparam->managed.width; v++) - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, u, &nobjs)) + if(fill_row(fh, dxpl, u, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Direct block row in 3rd level indirect block */ - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, u, &nobjs)) + if(fill_row(fh, dxpl, u, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR } /* end for */ @@ -8189,7 +8405,8 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); /* Add one more object, to create another "large" block */ obj_size = SMALL_OBJ_SIZE1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, num_first_indirect_rows); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -8249,13 +8466,9 @@ test_abs_fill_3rd_direct_fill_2nd_direct_fill_direct_skip_3rd_indirect_two_rows_ H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned first_row_bits; /* Number of bits used bit addresses in first row */ - unsigned first_indirect_block_size; /* Range of addresses covered by each of the first indirect blocks */ unsigned num_first_indirect_rows; /* Number of rows (of direct blocks) in each of the first indirect blocks */ - unsigned nobjs = 0; /* Number of objects inserted */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ unsigned u, v; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ @@ -8280,15 +8493,11 @@ test_abs_fill_3rd_direct_fill_2nd_direct_fill_direct_skip_3rd_indirect_two_rows_ FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); - /* Compute # of bits used in first row */ - first_row_bits = H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width); - first_indirect_block_size = 2 * cparam->managed.max_direct_size; - num_first_indirect_rows = (H5V_log2_of2(first_indirect_block_size) - first_row_bits) + 1; + /* Retrieve info about heap */ + num_first_indirect_rows = IBLOCK_MAX_DROWS(fh, 1); #ifdef QAK -HDfprintf(stderr, "first_row_bits = %u\n", first_row_bits); -HDfprintf(stderr, "first_indirect_block_size = %u\n", first_indirect_block_size); HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); #endif /* QAK */ @@ -8298,9 +8507,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); TESTING("filling direct blocks, filling 2nd level indirect blocks, filling 3rd level indirect blocks, fill first row of 4th level indirect blocks, fill 2nd row 4th level indirect block's direct, 2nd level indirect blocks, first row of 3rd level indirect blocks, 3rd level direct block in 2nd row, and skip first row of 2nd indirect blocks of 4th level indirect block's 3rd level indirect block, then backfill and extend"); /* Fill direct blocks in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8315,7 +8522,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all rows of 2nd level indirect blocks */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8330,7 +8537,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all rows of 3rd level indirect blocks */ - if(fill_all_3rd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_3rd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8345,31 +8552,25 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill first row of 4th level indirect blocks */ - if(fill_4th_indirect_row(fh, dxpl, cparam, &heap_size, &free_space, &nobjs, 1)) + if(fill_4th_indirect_row(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Account for root indirect block doubling # of rows again */ /* (From 16 rows to the max. # of rows: 22) */ + /* (Note: this is tied to the particular doubling table/heap creation parameters) */ { - hsize_t block_size; /* Current block size */ - hsize_t max_block_size; /* Maximum size of blocks in heap */ + unsigned max_root_rows; /* Maximum # of rows in root indirect block */ unsigned row; /* Row in heap */ - /* Compute current & maximum block size in heap */ - block_size = cparam->managed.start_block_size * ((hsize_t)1 << 15); - max_block_size = (((hsize_t)1 << cparam->managed.max_index) / 2) / - cparam->managed.width; + /* Get some information for the heap */ + max_root_rows = HEAP_MAX_ROOT_ROWS(fh); /* Increase heap size & free space */ - row = 16; - while(block_size <= max_block_size) { - heap_size += cparam->managed.width * block_size; - free_space += cparam->managed.width * DBLOCK_FREE(fh, row); - - /* Advance to next row */ - block_size *= 2; - row++; - } /* end while */ + for(row = 16; row < max_root_rows; row++) { + state.heap_size += cparam->managed.width * DBLOCK_SIZE(fh, row); + state.man_size += cparam->managed.width * DBLOCK_SIZE(fh, row); + state.man_free_space += cparam->managed.width * DBLOCK_FREE(fh, row); + } /* end for */ } /* end if */ /* Check for closing & re-opening the heap */ @@ -8384,7 +8585,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all direct block rows in 2nd row 4th level indirect block */ - if(fill_all_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8399,7 +8600,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all rows of 2nd level indirect blocks in 2nd row 4th level indirect block */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8414,7 +8615,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill first row of 3rd level indirect blocks in 2nd row 4th level indirect block */ - if(fill_3rd_indirect_row(fh, dxpl, cparam, &heap_size, &free_space, &nobjs, 1)) + if(fill_3rd_indirect_row(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8429,7 +8630,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all direct block rows in 4th level indirect block's 2nd row of 3rd level indirect block */ - if(fill_all_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8447,11 +8648,12 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); * range of skipped (indirect) blocks that are too small to hold the large * object */ - obj_size = (1 << ((num_first_indirect_rows + H5V_log2_of2(cparam->managed.start_block_size)) - 2)) + 1; + obj_size = DBLOCK_SIZE(fh, num_first_indirect_rows - 1) + 1; #ifdef QAK HDfprintf(stderr, "obj_size = %Zu\n", obj_size); #endif /* QAK */ - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, num_first_indirect_rows); + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8467,7 +8669,7 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); /* Insert object to fill space in (large) block created */ obj_size = DBLOCK_FREE(fh, num_first_indirect_rows) - obj_size; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8488,11 +8690,11 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); for(u = 0; u < num_first_indirect_rows; u++) { /* Direct block rows in 2nd level indirect blocks */ for(v = 0; v < cparam->managed.width; v++) - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, u, &nobjs)) + if(fill_row(fh, dxpl, u, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Direct block row in 3rd level indirect block */ - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, u, &nobjs)) + if(fill_row(fh, dxpl, u, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR } /* end for */ @@ -8509,7 +8711,8 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); /* Add one more object, to create another "large" block */ obj_size = SMALL_OBJ_SIZE1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, num_first_indirect_rows); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -8571,13 +8774,9 @@ test_abs_fill_3rd_direct_fill_2nd_direct_fill_direct_skip_3rd_indirect_wrap_star H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned first_row_bits; /* Number of bits used bit addresses in first row */ - unsigned first_indirect_block_size; /* Range of addresses covered by each of the first indirect blocks */ unsigned num_first_indirect_rows; /* Number of rows (of direct blocks) in each of the first indirect blocks */ - unsigned nobjs = 0; /* Number of objects inserted */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ unsigned u, v; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ @@ -8602,15 +8801,11 @@ test_abs_fill_3rd_direct_fill_2nd_direct_fill_direct_skip_3rd_indirect_wrap_star FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); - /* Compute # of bits used in first row */ - first_row_bits = H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width); - first_indirect_block_size = 2 * cparam->managed.max_direct_size; - num_first_indirect_rows = (H5V_log2_of2(first_indirect_block_size) - first_row_bits) + 1; + /* Retrieve info about heap */ + num_first_indirect_rows = IBLOCK_MAX_DROWS(fh, 1); #ifdef QAK -HDfprintf(stderr, "first_row_bits = %u\n", first_row_bits); -HDfprintf(stderr, "first_indirect_block_size = %u\n", first_indirect_block_size); HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); #endif /* QAK */ @@ -8620,9 +8815,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); TESTING("filling direct blocks, filling 2nd level indirect blocks, filling 3rd level indirect blocks, fill first row of 3rd level indirect blocks in 4th level indirect block except last 3rd level block, fill direct blocks in 3rd level block, and skip row of 2nd indirect blocks of 4th level indirect block's 3rd level indirect block, then backfill and extend"); /* Fill direct blocks in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8637,7 +8830,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all rows of 2nd level indirect blocks */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8652,7 +8845,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all rows of 3rd level indirect blocks */ - if(fill_all_3rd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_3rd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8667,7 +8860,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all direct block rows in 4th level indirect block */ - if(fill_all_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8682,7 +8875,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all rows of 2nd level indirect blocks in 4th level indirect block */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8699,11 +8892,11 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); /* Fill first row (except one) of 3rd level indirect blocks in 4th level indirect block */ for(u = 0; u < cparam->managed.width - 1; u++) { /* Fill all direct block rows in 3rd level indirect block */ - if(fill_all_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill row of 2nd level indirect blocks in 3rd level indirect block */ - if(fill_2nd_indirect_row(fh, dxpl, cparam, &heap_size, &free_space, &nobjs, 1)) + if(fill_2nd_indirect_row(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR } /* end for */ @@ -8719,7 +8912,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all direct block rows in 4th level indirect block's last 3rd level indirect block */ - if(fill_all_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8737,11 +8930,12 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); * range of skipped (indirect) blocks that are too small to hold the large * object */ - obj_size = (1 << ((num_first_indirect_rows + H5V_log2_of2(cparam->managed.start_block_size)) - 2)) + 1; + obj_size = DBLOCK_SIZE(fh, num_first_indirect_rows - 1) + 1; #ifdef QAK HDfprintf(stderr, "obj_size = %Zu\n", obj_size); #endif /* QAK */ - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, num_first_indirect_rows); + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8757,7 +8951,7 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); /* Insert object to fill space in (large) block created */ obj_size = DBLOCK_FREE(fh, num_first_indirect_rows) - obj_size; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8778,11 +8972,11 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); for(u = 0; u < num_first_indirect_rows; u++) { /* Direct block rows in 2nd level indirect blocks */ for(v = 0; v < cparam->managed.width; v++) - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, u, &nobjs)) + if(fill_row(fh, dxpl, u, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Direct block row in 4th level indirect block */ - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, u, &nobjs)) + if(fill_row(fh, dxpl, u, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR } /* end for */ @@ -8799,7 +8993,8 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); /* Add one more object, to create another "large" block */ obj_size = SMALL_OBJ_SIZE1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, num_first_indirect_rows); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -8861,13 +9056,9 @@ test_abs_fill_4th_direct_less_one_fill_2nd_direct_fill_direct_skip_3rd_indirect_ H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned first_row_bits; /* Number of bits used bit addresses in first row */ - unsigned first_indirect_block_size; /* Range of addresses covered by each of the first indirect blocks */ unsigned num_first_indirect_rows; /* Number of rows (of direct blocks) in each of the first indirect blocks */ - unsigned nobjs = 0; /* Number of objects inserted */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ unsigned u, v; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ @@ -8892,15 +9083,11 @@ test_abs_fill_4th_direct_less_one_fill_2nd_direct_fill_direct_skip_3rd_indirect_ FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); - /* Compute # of bits used in first row */ - first_row_bits = H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width); - first_indirect_block_size = 2 * cparam->managed.max_direct_size; - num_first_indirect_rows = (H5V_log2_of2(first_indirect_block_size) - first_row_bits) + 1; + /* Retrieve info about heap */ + num_first_indirect_rows = IBLOCK_MAX_DROWS(fh, 1); #ifdef QAK -HDfprintf(stderr, "first_row_bits = %u\n", first_row_bits); -HDfprintf(stderr, "first_indirect_block_size = %u\n", first_indirect_block_size); HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); #endif /* QAK */ @@ -8910,9 +9097,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); TESTING("filling direct blocks, filling 2nd level indirect blocks, filling 3rd level indirect blocks, fill first row of 4th level indirect blocks, except last one, fill first row of 3rd level indirect blocks in last 4th level indirect block except last 3rd level block, fill direct blocks in 3rd level block, and skip row of 2nd indirect blocks of 4th level indirect block's 3rd level indirect block, then backfill and extend"); /* Fill direct blocks in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8927,7 +9112,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all rows of 2nd level indirect blocks */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8942,7 +9127,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all rows of 3rd level indirect blocks */ - if(fill_all_3rd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_3rd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8959,15 +9144,15 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); /* Fill first row (except one) of 4th level indirect blocks */ for(u = 0; u < cparam->managed.width - 1; u++) { /* Fill all direct block rows in 4th level indirect block */ - if(fill_all_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill all rows of 2nd level indirect blocks in 4th level indirect block */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill row of 3rd level indirect blocks in 4th level indirect block */ - if(fill_3rd_indirect_row(fh, dxpl, cparam, &heap_size, &free_space, &nobjs, 1)) + if(fill_3rd_indirect_row(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR } /* end for */ @@ -8983,7 +9168,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all direct block rows in 4th level indirect block */ - if(fill_all_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -8998,7 +9183,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all rows of 2nd level indirect blocks in 4th level indirect block */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -9015,11 +9200,11 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); /* Fill row (except one) of 3rd level indirect blocks in 4th level indirect block */ for(u = 0; u < cparam->managed.width - 1; u++) { /* Fill all direct block rows in 3rd level indirect block */ - if(fill_all_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Fill row of 2nd level indirect blocks in 3rd level indirect block */ - if(fill_2nd_indirect_row(fh, dxpl, cparam, &heap_size, &free_space, &nobjs, 1)) + if(fill_2nd_indirect_row(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR } /* end for */ @@ -9035,31 +9220,25 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Fill all direct block rows in 4th level indirect block's last 3rd level indirect block */ - if(fill_all_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Account for root indirect block doubling # of rows again */ /* (From 16 rows to the max. # of rows: 22) */ + /* (Note: this is tied to the particular doubling table/heap creation parameters) */ { - hsize_t block_size; /* Current block size */ - hsize_t max_block_size; /* Maximum size of blocks in heap */ + unsigned max_root_rows; /* Maximum # of rows in root indirect block */ unsigned row; /* Row in heap */ - /* Compute current & maximum block size in heap */ - block_size = cparam->managed.start_block_size * ((hsize_t)1 << 15); - max_block_size = (((hsize_t)1 << cparam->managed.max_index) / 2) / - cparam->managed.width; + /* Get some information for the heap */ + max_root_rows = HEAP_MAX_ROOT_ROWS(fh); /* Increase heap size & free space */ - row = 16; - while(block_size <= max_block_size) { - heap_size += cparam->managed.width * block_size; - free_space += cparam->managed.width * DBLOCK_FREE(fh, row); - - /* Advance to next row */ - block_size *= 2; - row++; - } /* end while */ + for(row = 16; row < max_root_rows; row++) { + state.heap_size += cparam->managed.width * DBLOCK_SIZE(fh, row); + state.man_size += cparam->managed.width * DBLOCK_SIZE(fh, row); + state.man_free_space += cparam->managed.width * DBLOCK_FREE(fh, row); + } /* end for */ } /* end if */ /* Check for closing & re-opening the heap */ @@ -9077,11 +9256,12 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); * range of skipped (indirect) blocks that are too small to hold the large * object */ - obj_size = (1 << ((num_first_indirect_rows + H5V_log2_of2(cparam->managed.start_block_size)) - 2)) + 1; + obj_size = DBLOCK_SIZE(fh, num_first_indirect_rows - 1) + 1; #ifdef QAK HDfprintf(stderr, "obj_size = %Zu\n", obj_size); #endif /* QAK */ - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, num_first_indirect_rows); + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -9097,7 +9277,7 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); /* Insert object to fill space in (large) block created */ obj_size = DBLOCK_FREE(fh, num_first_indirect_rows) - obj_size; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -9118,11 +9298,11 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); for(u = 0; u < num_first_indirect_rows; u++) { /* Direct block rows in 2nd level indirect blocks */ for(v = 0; v < cparam->managed.width; v++) - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, u, &nobjs)) + if(fill_row(fh, dxpl, u, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Direct block row in 4th level indirect block */ - if(fill_row(fh, dxpl, cparam, &heap_size, &free_space, u, &nobjs)) + if(fill_row(fh, dxpl, u, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR } /* end for */ @@ -9139,7 +9319,8 @@ HDfprintf(stderr, "obj_size = %Zu\n", obj_size); /* Add one more object, to create another "large" block */ obj_size = SMALL_OBJ_SIZE1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, num_first_indirect_rows); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -9163,9 +9344,7 @@ error: } H5E_END_TRY; return(1); } /* test_abs_fill_4th_direct_less_one_fill_2nd_direct_fill_direct_skip_3rd_indirect_wrap_start_block_add_skipped() */ -#endif /* QAK */ -#ifndef QAK /*------------------------------------------------------------------------- * Function: test_abs_skip_direct_skip_indirect_two_rows_add_skipped @@ -9197,10 +9376,8 @@ test_abs_skip_direct_skip_indirect_two_rows_add_skipped(hid_t fapl, H5HF_create_ size_t id_len; /* Size of fractal heap IDs */ unsigned num_direct_rows; /* Number of rows (of direct blocks) in root indirect block */ unsigned row; /* Current row */ - unsigned nobjs = 0; /* Number of objects inserted */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ unsigned v; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ @@ -9225,10 +9402,10 @@ test_abs_skip_direct_skip_indirect_two_rows_add_skipped(hid_t fapl, H5HF_create_ FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* Compute # direct block rows in root indirect block */ - num_direct_rows = (H5V_log2_of2(cparam->managed.max_direct_size) - - H5V_log2_of2(cparam->managed.start_block_size)) + 3; + num_direct_rows = DTABLE_MAX_DROWS(fh); /* * Test absolute heap @@ -9236,25 +9413,26 @@ test_abs_skip_direct_skip_indirect_two_rows_add_skipped(hid_t fapl, H5HF_create_ TESTING("skipping direct blocks to last row and skipping two rows of root indirect block, then backfill and extend"); /* Compute heap size & free space when half direct blocks allocated */ - heap_size = 0; - free_space = 0; row = 0; do{ - heap_size += cparam->managed.width * DBLOCK_SIZE(fh, row); - free_space += cparam->managed.width * DBLOCK_FREE(fh, row); + state.heap_size += cparam->managed.width * DBLOCK_SIZE(fh, row); + state.man_size += cparam->managed.width * DBLOCK_SIZE(fh, row); + state.man_free_space += cparam->managed.width * DBLOCK_FREE(fh, row); row++; } while(row < (num_direct_rows / 2)); /* Insert object to extend root block to middle of root direct blocks */ - obj_size = (DBLOCK_SIZE(fh, row - 1) / 2) + 1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + obj_size = DBLOCK_SIZE(fh, row - 2) + 1; + state.man_alloc_size += DBLOCK_SIZE(fh, row -1); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Compute heap size & free space when all direct blocks allocated */ do{ - heap_size += cparam->managed.width * DBLOCK_SIZE(fh, row); - free_space += cparam->managed.width * DBLOCK_FREE(fh, row); + state.heap_size += cparam->managed.width * DBLOCK_SIZE(fh, row); + state.man_size += cparam->managed.width * DBLOCK_SIZE(fh, row); + state.man_free_space += cparam->managed.width * DBLOCK_FREE(fh, row); row++; } while(row < num_direct_rows); @@ -9262,10 +9440,12 @@ test_abs_skip_direct_skip_indirect_two_rows_add_skipped(hid_t fapl, H5HF_create_ * block, to force extension of root indirect block that covers the first * row of indirect blocks in root indirect block */ - obj_size = (cparam->managed.max_direct_size / 2) + 1; - for(v = 0; v < cparam->managed.width; v++) - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + obj_size = DBLOCK_SIZE(fh, num_direct_rows - 2) + 1; + for(v = 0; v < cparam->managed.width; v++) { + state.man_alloc_size += DBLOCK_SIZE(fh, num_direct_rows -1); + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR + } /* end for */ /* Check for closing & re-opening the heap */ if(tparam->reopen_heap) { @@ -9280,16 +9460,18 @@ test_abs_skip_direct_skip_indirect_two_rows_add_skipped(hid_t fapl, H5HF_create_ /* Compute heap size & free space when root indirect block doubles again */ do{ - heap_size += cparam->managed.width * DBLOCK_SIZE(fh, row); - free_space += cparam->managed.width * DBLOCK_FREE(fh, row); + state.heap_size += cparam->managed.width * DBLOCK_SIZE(fh, row); + state.man_size += cparam->managed.width * DBLOCK_SIZE(fh, row); + state.man_free_space += cparam->managed.width * DBLOCK_FREE(fh, row); row++; } while(row < (2 * num_direct_rows)); /* Insert large object, to force creation of indirect blocks with * range of skipped blocks that are too small to hold the large object */ - obj_size = (cparam->managed.max_direct_size / 2) + 1; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + obj_size = DBLOCK_SIZE(fh, num_direct_rows - 2) + 1; + state.man_alloc_size += DBLOCK_SIZE(fh, num_direct_rows -1); + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -9320,11 +9502,10 @@ error: /*------------------------------------------------------------------------- * Function: test_abs_frag_simple * - * Purpose: Test inserting small object to create root direct block, then - * insert objects small enough to fit into first row of direct - * blocks, but not to share a block with another object, until - * initial-block-size * 2 blocks are reached. Then, go back and - * fill in the space in the blocks skipped. + * Purpose: Test inserting objects small enough to fit into first row of + * direct blocks, but not to share a block with another object, + * until start-block-size * 2 blocks are reached. Then, go back + * and fill in the space in the blocks skipped. * * Return: Success: 0 * @@ -9345,10 +9526,8 @@ test_abs_frag_simple(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpar H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ unsigned u; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ @@ -9373,6 +9552,7 @@ test_abs_frag_simple(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpar FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* * Test absolute heap @@ -9383,22 +9563,28 @@ test_abs_frag_simple(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpar * share them with other objects of the same size, until the next larger * block size is reached. */ - obj_size = cparam->managed.start_block_size / 2; - heap_size = cparam->managed.start_block_size; - free_space = DBLOCK_FREE(fh, 0); + obj_size = DBLOCK_SIZE(fh, 0) / 2; + state.heap_size = DBLOCK_SIZE(fh, 0); + state.man_size = DBLOCK_SIZE(fh, 0); + state.man_free_space = DBLOCK_FREE(fh, 0); for(u = 0; u < cparam->managed.width; u++) { - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, 0); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR if(u == 0) { - heap_size = cparam->managed.start_block_size * cparam->managed.width; - free_space += DBLOCK_FREE(fh, 0) * (cparam->managed.width - 1); + state.heap_size = cparam->managed.width * DBLOCK_SIZE(fh, 0); + state.man_size = cparam->managed.width * DBLOCK_SIZE(fh, 0); + state.man_free_space += (cparam->managed.width - 1) * DBLOCK_FREE(fh, 0); } /* end if */ } /* end for */ - heap_size += cparam->managed.start_block_size * cparam->managed.width; - free_space += DBLOCK_FREE(fh, 1) * cparam->managed.width; - for(u = 0; u < cparam->managed.width; u++) - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.heap_size += DBLOCK_SIZE(fh, 1) * cparam->managed.width; + state.man_size += DBLOCK_SIZE(fh, 1) * cparam->managed.width; + state.man_free_space += DBLOCK_FREE(fh, 1) * cparam->managed.width; + for(u = 0; u < cparam->managed.width; u++) { + state.man_alloc_size += DBLOCK_SIZE(fh, 1); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR + } /* end for */ /* Check for closing & re-opening the heap */ if(tparam->reopen_heap) { @@ -9411,13 +9597,16 @@ test_abs_frag_simple(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpar FAIL_STACK_ERROR } /* end if */ + /* (Account for doubling root indirect block for rows 3-4 */ + for(u = 0; u < 2; u++) { + state.heap_size += DBLOCK_SIZE(fh, u + 2) * cparam->managed.width; + state.man_size += DBLOCK_SIZE(fh, u + 2) * cparam->managed.width; + state.man_free_space += DBLOCK_FREE(fh, u + 2) * cparam->managed.width; + } /* end for */ + /* Add one more object, to create a 2 * start_block_size block */ - /* (Account for doubling root indirect block in calc. below) */ - heap_size += (cparam->managed.start_block_size * 2) * cparam->managed.width; - heap_size += (cparam->managed.start_block_size * 4) * cparam->managed.width; - free_space += DBLOCK_FREE(fh, 2) * cparam->managed.width; - free_space += DBLOCK_FREE(fh, 3) * cparam->managed.width; - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, 2); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -9434,10 +9623,10 @@ test_abs_frag_simple(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpar /* Go back and fill in direct blocks of initial block size (which have large free space in them) */ obj_size = DBLOCK_FREE(fh, 0) - obj_size; for(u = 0; u < cparam->managed.width; u++) - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR for(u = 0; u < cparam->managed.width; u++) - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -9452,8 +9641,8 @@ test_abs_frag_simple(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpar } /* end if */ /* Fill in 2 * start_block_size block */ - obj_size = DBLOCK_FREE(fh, 2) - (cparam->managed.start_block_size / 2); - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 20, obj_size)) + obj_size = DBLOCK_FREE(fh, 2) - (DBLOCK_SIZE(fh, 0) / 2); + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR PASSED() @@ -9505,13 +9694,9 @@ test_abs_frag_direct(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpar H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - hsize_t block_mult; /* Base block size multiplier */ - unsigned base_row; /* Base row for adding new rows */ - unsigned nobjs = 0; /* Number of objects inserted */ unsigned root_direct_rows; /* Number of rows in root indirect block */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ unsigned u, v; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ @@ -9536,9 +9721,10 @@ test_abs_frag_direct(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpar FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); - /* Compute # of direct rows in root indirect block */ - root_direct_rows = (H5V_log2_of2(cparam->managed.max_direct_size) - H5V_log2_of2(cparam->managed.start_block_size)) + 2; + /* Retrieve # of direct rows in root indirect block */ + root_direct_rows = H5HF_get_dtable_max_drows_test(fh); /* * Test absolute heap @@ -9548,24 +9734,30 @@ test_abs_frag_direct(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpar /* Insert objects small enough to fit into each direct block, but not to * share them with other objects of the same size. */ - obj_size = cparam->managed.start_block_size / 2; - heap_size = cparam->managed.start_block_size; - free_space = DBLOCK_FREE(fh, 0); + obj_size = DBLOCK_SIZE(fh, 0) / 2; + state.heap_size = DBLOCK_SIZE(fh, 0); + state.man_size = DBLOCK_SIZE(fh, 0); + state.man_free_space = DBLOCK_FREE(fh, 0); /* First row */ for(u = 0; u < cparam->managed.width; u++) { - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + state.man_alloc_size += DBLOCK_SIZE(fh, 0); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR if(u == 0) { - heap_size = cparam->managed.start_block_size * cparam->managed.width; - free_space += DBLOCK_FREE(fh, 0) * (cparam->managed.width - 1); + state.heap_size = cparam->managed.width * DBLOCK_SIZE(fh, 0); + state.man_size = cparam->managed.width * DBLOCK_SIZE(fh, 0); + state.man_free_space += (cparam->managed.width - 1) * DBLOCK_FREE(fh, 0); } /* end if */ } /* end for */ - heap_size += cparam->managed.start_block_size * cparam->managed.width; - free_space += DBLOCK_FREE(fh, 1) * cparam->managed.width; + state.heap_size += DBLOCK_SIZE(fh, 1) * cparam->managed.width; + state.man_size += DBLOCK_SIZE(fh, 1) * cparam->managed.width; + state.man_free_space += DBLOCK_FREE(fh, 1) * cparam->managed.width; /* Second row */ - for(u = 0; u < cparam->managed.width; u++) - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + for(u = 0; u < cparam->managed.width; u++) { + state.man_alloc_size += DBLOCK_SIZE(fh, 1); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR + } /* end for */ /* Check for closing & re-opening the heap */ if(tparam->reopen_heap) { @@ -9579,22 +9771,20 @@ test_abs_frag_direct(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpar } /* end if */ /* (Account for doubling root indirect block for rows 3-4 */ - base_row = 2; - block_mult = 2; for(u = 0; u < 2; u++) { - heap_size += (cparam->managed.start_block_size * block_mult) * cparam->managed.width; - free_space += DBLOCK_FREE(fh, base_row + u) * cparam->managed.width; - block_mult *= 2; + state.heap_size += DBLOCK_SIZE(fh, u + 2) * cparam->managed.width; + state.man_size += DBLOCK_SIZE(fh, u + 2) * cparam->managed.width; + state.man_free_space += DBLOCK_FREE(fh, u + 2) * cparam->managed.width; } /* end for */ /* Rows 3-4 */ - block_mult = 2; for(u = 0; u < 2; u++) { - obj_size = (cparam->managed.start_block_size * block_mult) / 2; - for(v = 0; v < cparam->managed.width; v++) - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + obj_size = DBLOCK_SIZE(fh, u + 2) / 2; + for(v = 0; v < cparam->managed.width; v++) { + state.man_alloc_size += DBLOCK_SIZE(fh, u + 2); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR - block_mult *= 2; + } /* end for */ } /* end for */ /* Check for closing & re-opening the heap */ @@ -9609,22 +9799,20 @@ test_abs_frag_direct(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpar } /* end if */ /* (Account for doubling root indirect block for rows 5-8 */ - base_row = 4; - block_mult = 8; for(u = 0; u < 4; u++) { - heap_size += (cparam->managed.start_block_size * block_mult) * cparam->managed.width; - free_space += DBLOCK_FREE(fh, base_row + u) * cparam->managed.width; - block_mult *= 2; + state.heap_size += DBLOCK_SIZE(fh, u + 4) * cparam->managed.width; + state.man_size += DBLOCK_SIZE(fh, u + 4) * cparam->managed.width; + state.man_free_space += DBLOCK_FREE(fh, u + 4) * cparam->managed.width; } /* end for */ /* Rows 5-8 */ - block_mult = 8; for(u = 0; u < 4; u++) { - obj_size = (cparam->managed.start_block_size * block_mult) / 2; - for(v = 0; v < cparam->managed.width; v++) - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + obj_size = DBLOCK_SIZE(fh, u + 4) / 2; + for(v = 0; v < cparam->managed.width; v++) { + state.man_alloc_size += DBLOCK_SIZE(fh, u + 4); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR - block_mult *= 2; + } /* end for */ } /* end for */ /* Check for closing & re-opening the heap */ @@ -9639,20 +9827,19 @@ test_abs_frag_direct(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpar } /* end if */ /* (Account for doubling root indirect block for rows 9-16 */ - base_row = 8; - block_mult = 128; for(u = 0; u < 8; u++) { - heap_size += (cparam->managed.start_block_size * block_mult) * cparam->managed.width; - free_space += DBLOCK_FREE(fh, base_row + u) * cparam->managed.width; - block_mult *= 2; + state.heap_size += DBLOCK_SIZE(fh, u + 8) * cparam->managed.width; + state.man_size += DBLOCK_SIZE(fh, u + 8) * cparam->managed.width; + state.man_free_space += DBLOCK_FREE(fh, u + 8) * cparam->managed.width; } /* end for */ /* Row 9 (last direct block row) */ - block_mult = 128; - obj_size = (cparam->managed.start_block_size * block_mult) / 2; - for(v = 0; v < cparam->managed.width; v++) - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + obj_size = DBLOCK_SIZE(fh, 8) / 2; + for(v = 0; v < cparam->managed.width; v++) { + state.man_alloc_size += DBLOCK_SIZE(fh, 8); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR + } /* end for */ /* Check for closing & re-opening the heap */ if(tparam->reopen_heap) { @@ -9666,14 +9853,11 @@ test_abs_frag_direct(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpar } /* end if */ /* Go back and backfill all root block's direct blocks */ - block_mult = 1; for(u = 0; u < root_direct_rows; u++) { - obj_size = DBLOCK_FREE(fh, u) - ((cparam->managed.start_block_size * block_mult) / 2); + obj_size = DBLOCK_FREE(fh, u) - (DBLOCK_SIZE(fh, u) / 2); for(v = 0; v < cparam->managed.width; v++) - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR - if(u != 0) - block_mult *= 2; } /* end for */ PASSED() @@ -9727,14 +9911,9 @@ test_abs_frag_2nd_direct(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t * H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - hsize_t block_mult; /* Base block size multiplier */ - unsigned first_row_bits; /* Number of bits used bit addresses in first row */ - unsigned first_indirect_block_size; /* Range of addresses covered by each of the first indirect blocks */ unsigned num_first_indirect_rows; /* Number of rows (of direct blocks) in each of the first indirect blocks */ - unsigned nobjs = 0; /* Number of objects inserted */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ unsigned u, v; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ @@ -9759,15 +9938,11 @@ test_abs_frag_2nd_direct(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t * FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* Compute # of bits used in first row */ - first_row_bits = H5V_log2_of2(cparam->managed.start_block_size) + - H5V_log2_of2(cparam->managed.width); - first_indirect_block_size = 2 * cparam->managed.max_direct_size; - num_first_indirect_rows = (H5V_log2_of2(first_indirect_block_size) - first_row_bits) + 1; + num_first_indirect_rows = IBLOCK_MAX_DROWS(fh, 1); #ifdef QAK -HDfprintf(stderr, "first_row_bits = %u\n", first_row_bits); -HDfprintf(stderr, "first_indirect_block_size = %u\n", first_indirect_block_size); HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); #endif /* QAK */ @@ -9777,9 +9952,7 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); TESTING("fill root direct blocks, then fragment 2nd level indirect block's direct blocks, then backfill and extend"); /* Fill direct blocks in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -9796,14 +9969,13 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); /* Insert objects small enough to fit into each direct block, but not to * share them with other objects of the same size. */ - block_mult = 1; for(u = 0; u < num_first_indirect_rows; u++) { - obj_size = (cparam->managed.start_block_size * block_mult) / 2; - for(v = 0; v < cparam->managed.width; v++) - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + obj_size = DBLOCK_SIZE(fh, u) / 2; + for(v = 0; v < cparam->managed.width; v++) { + state.man_alloc_size += DBLOCK_SIZE(fh, u); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR - if(u != 0) - block_mult *= 2; + } /* end for */ } /* end for */ /* Check for closing & re-opening the heap */ @@ -9818,14 +9990,11 @@ HDfprintf(stderr, "num_first_indirect_rows = %u\n", num_first_indirect_rows); } /* end if */ /* Go back and backfill all 2nd level indirect block's direct blocks */ - block_mult = 1; for(u = 0; u < num_first_indirect_rows; u++) { - obj_size = DBLOCK_FREE(fh, u) - ((cparam->managed.start_block_size * block_mult) / 2); + obj_size = DBLOCK_FREE(fh, u) - (DBLOCK_SIZE(fh, u) / 2); for(v = 0; v < cparam->managed.width; v++) - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR - if(u != 0) - block_mult *= 2; } /* end for */ PASSED() @@ -9880,12 +10049,9 @@ test_abs_frag_3rd_direct(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t * H5HF_t *fh = NULL; /* Fractal heap wrapper */ haddr_t fh_addr; /* Address of fractal heap */ size_t id_len; /* Size of fractal heap IDs */ - hsize_t block_mult; /* Base block size multiplier */ unsigned root_direct_rows; /* Number of rows in root indirect block */ - unsigned nobjs = 0; /* Number of objects inserted */ size_t obj_size; /* Size of object */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + fheap_heap_state_t state; /* State of fractal heap */ unsigned u, v; /* Local index variables */ /* Set the filename to use for this test (dependent on fapl) */ @@ -9910,9 +10076,10 @@ test_abs_frag_3rd_direct(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t * FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); /* Compute # of direct rows in root indirect block */ - root_direct_rows = (H5V_log2_of2(cparam->managed.max_direct_size) - H5V_log2_of2(cparam->managed.start_block_size)) + 2; + root_direct_rows = DTABLE_MAX_DROWS(fh); /* * Test absolute heap @@ -9920,9 +10087,7 @@ test_abs_frag_3rd_direct(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t * TESTING("fill root direct blocks and 2nd level indirect blocks, then fragment 3rd level indirect block's direct blocks, then backfill and extend"); /* Fill direct blocks in root indirect block */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -9937,7 +10102,7 @@ test_abs_frag_3rd_direct(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t * } /* end if */ /* Fill all rows of 2nd level indirect blocks in root indirect block */ - if(fill_all_2nd_indirect_rows(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -9954,14 +10119,13 @@ test_abs_frag_3rd_direct(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t * /* Insert objects small enough to fit into each direct block, but not to * share them with other objects of the same size. */ - block_mult = 1; for(u = 0; u < root_direct_rows; u++) { - obj_size = (cparam->managed.start_block_size * block_mult) / 2; - for(v = 0; v < cparam->managed.width; v++) - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + obj_size = DBLOCK_SIZE(fh, u) / 2; + for(v = 0; v < cparam->managed.width; v++) { + state.man_alloc_size += DBLOCK_SIZE(fh, u); + if(add_obj(fh, dxpl, 10, obj_size, &state, NULL)) FAIL_STACK_ERROR - if(u != 0) - block_mult *= 2; + } /* end for */ } /* end for */ /* Check for closing & re-opening the heap */ @@ -9976,14 +10140,11 @@ test_abs_frag_3rd_direct(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t * } /* end if */ /* Go back and backfill all 3rd level indirect block's direct blocks */ - block_mult = 1; for(u = 0; u < root_direct_rows; u++) { - obj_size = DBLOCK_FREE(fh, u) - ((cparam->managed.start_block_size * block_mult) / 2); + obj_size = DBLOCK_FREE(fh, u) - (DBLOCK_SIZE(fh, u) / 2); for(v = 0; v < cparam->managed.width; v++) - if(add_obj(fh, dxpl, heap_size, &free_space, &nobjs, 10, obj_size)) + if(add_obj(fh, dxpl, 20, obj_size, &state, NULL)) FAIL_STACK_ERROR - if(u != 0) - block_mult *= 2; } /* end for */ PASSED() @@ -10039,8 +10200,6 @@ test_abs_random_managed(hsize_t size_limit, hid_t fapl, H5HF_create_t *cparam, f unsigned long seed; /* Random # seed */ size_t num_ids = 0; /* # of heap IDs in array */ size_t alloc_ids = 0; /* # of heap IDs allocated in array */ - unsigned char *obj = NULL; /* Buffer for object to insert */ - unsigned char *robj = NULL; /* Buffer for reading object */ hsize_t total_obj_added; /* Size of objects added */ size_t obj_size; /* Size of object */ size_t obj_loc; /* Location of object in buffer */ @@ -10085,11 +10244,6 @@ HDfprintf(stderr, "Random # seed was: %lu\n", seed); #endif /* QAK */ HDsrandom(seed); - /* Initialize the buffer for objects to insert */ - obj = H5MM_malloc(cparam->standalone_size); - for(u = 0; u < cparam->standalone_size; u++) - obj[u] = (unsigned char)u; - /* Loop over adding objects to the heap, until the size limit is reached */ total_obj_added = 0; while(total_obj_added < size_limit) { @@ -10111,7 +10265,7 @@ HDfprintf(stderr, "num_ids = %Zu, total_obj_added = %Hu, obj_size = %Zu\n", num_ /* Insert object */ obj_loc = cparam->standalone_size - obj_size; - if(H5HF_insert(fh, dxpl, obj_size, &obj[obj_loc], &ids[(num_ids - 1) * HEAP_ID_LEN]) < 0) + if(H5HF_insert(fh, dxpl, obj_size, &shared_wobj_g[obj_loc], &ids[(num_ids - 1) * HEAP_ID_LEN]) < 0) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -10129,9 +10283,6 @@ HDfprintf(stderr, "num_ids = %Zu, total_obj_added = %Hu, obj_size = %Zu\n", num_ total_obj_added += obj_size; } /* end while */ - /* Allocate buffer for reading objects */ - robj = H5MM_malloc(cparam->standalone_size); - /* Verify reading the objects written out */ for(u = 0; u < num_ids; u++) { /* Get object length */ @@ -10139,15 +10290,15 @@ HDfprintf(stderr, "num_ids = %Zu, total_obj_added = %Hu, obj_size = %Zu\n", num_ FAIL_STACK_ERROR /* Clear read buffer */ - HDmemset(robj, 0, obj_size); + HDmemset(shared_robj_g, 0, obj_size); /* Read in object */ - if(H5HF_read(fh, dxpl, &ids[u * HEAP_ID_LEN], robj) < 0) + if(H5HF_read(fh, dxpl, &ids[u * HEAP_ID_LEN], shared_robj_g) < 0) FAIL_STACK_ERROR /* Check for correct object */ obj_loc = cparam->standalone_size - obj_size; - if(HDmemcmp(&obj[obj_loc], robj, obj_size)) + if(HDmemcmp(&shared_wobj_g[obj_loc], shared_robj_g, obj_size)) FAIL_STACK_ERROR } /* end for */ @@ -10162,8 +10313,6 @@ HDfprintf(stderr, "num_ids = %Zu, total_obj_added = %Hu, obj_size = %Zu\n", num_ TEST_ERROR /* All tests passed */ - H5MM_xfree(obj); - H5MM_xfree(robj); H5MM_xfree(ids); return(0); @@ -10172,8 +10321,6 @@ error: if(fh) H5HF_close(fh, dxpl); H5Fclose(file); - H5MM_xfree(obj); - H5MM_xfree(robj); H5MM_xfree(ids); } H5E_END_TRY; HDfprintf(stderr, "Random # seed was: %lu\n", seed); @@ -10210,8 +10357,6 @@ test_abs_random_pow2_managed(hsize_t size_limit, hid_t fapl, H5HF_create_t *cpar unsigned long seed; /* Random # seed */ size_t num_ids = 0; /* # of heap IDs in array */ size_t alloc_ids = 0; /* # of heap IDs allocated in array */ - unsigned char *obj = NULL; /* Buffer for object to insert */ - unsigned char *robj = NULL; /* Buffer for reading object */ hsize_t total_obj_added; /* Size of objects added */ size_t obj_size; /* Size of object */ size_t obj_loc; /* Location of object in buffer */ @@ -10256,11 +10401,6 @@ HDfprintf(stderr, "Random # seed was: %lu\n", seed); #endif /* QAK */ HDsrandom(seed); - /* Initialize the buffer for objects to insert */ - obj = H5MM_malloc(cparam->standalone_size); - for(u = 0; u < cparam->standalone_size; u++) - obj[u] = (unsigned char)u; - /* Loop over adding objects to the heap, until the size limit is reached */ total_obj_added = 0; while(total_obj_added < size_limit) { @@ -10295,7 +10435,7 @@ if((num_ids % 100000) == 1) /* Insert object */ obj_loc = cparam->standalone_size - obj_size; - if(H5HF_insert(fh, dxpl, obj_size, &obj[obj_loc], &ids[(num_ids - 1) * HEAP_ID_LEN]) < 0) + if(H5HF_insert(fh, dxpl, obj_size, &shared_wobj_g[obj_loc], &ids[(num_ids - 1) * HEAP_ID_LEN]) < 0) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -10313,9 +10453,6 @@ if((num_ids % 100000) == 1) total_obj_added += obj_size; } /* end while */ - /* Allocate buffer for reading objects */ - robj = H5MM_malloc(cparam->standalone_size); - /* Verify reading the objects written out */ for(u = 0; u < num_ids; u++) { /* Get object length */ @@ -10323,15 +10460,15 @@ if((num_ids % 100000) == 1) FAIL_STACK_ERROR /* Clear read buffer */ - HDmemset(robj, 0, obj_size); + HDmemset(shared_robj_g, 0, obj_size); /* Read in object */ - if(H5HF_read(fh, dxpl, &ids[u * HEAP_ID_LEN], robj) < 0) + if(H5HF_read(fh, dxpl, &ids[u * HEAP_ID_LEN], shared_robj_g) < 0) FAIL_STACK_ERROR /* Check for correct object */ obj_loc = cparam->standalone_size - obj_size; - if(HDmemcmp(&obj[obj_loc], robj, obj_size)) + if(HDmemcmp(&shared_wobj_g[obj_loc], shared_robj_g, obj_size)) FAIL_STACK_ERROR } /* end for */ @@ -10346,8 +10483,6 @@ if((num_ids % 100000) == 1) TEST_ERROR /* All tests passed */ - H5MM_xfree(obj); - H5MM_xfree(robj); H5MM_xfree(ids); return(0); @@ -10356,8 +10491,6 @@ error: if(fh) H5HF_close(fh, dxpl); H5Fclose(file); - H5MM_xfree(obj); - H5MM_xfree(robj); H5MM_xfree(ids); } H5E_END_TRY; HDfprintf(stderr, "Random # seed was: %lu\n", seed); @@ -10392,10 +10525,8 @@ test_abs_remove_bogus(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpa haddr_t fh_addr; /* Address of fractal heap */ unsigned char heap_id[HEAP_ID_LEN]; /* Heap ID for object */ size_t id_len; /* Size of fractal heap IDs */ - unsigned nobjs = 0; /* Number of objects inserted */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ hsize_t obj_off; /* Offset of object in heap */ + fheap_heap_state_t state; /* State of fractal heap */ unsigned u; /* Local index variable */ herr_t ret; /* Generic return value */ @@ -10421,7 +10552,8 @@ test_abs_remove_bogus(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpa FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR - if(check_stats(fh, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0)) + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); + if(check_stats(fh, &state)) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -10452,9 +10584,7 @@ test_abs_remove_bogus(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpa FAIL_STACK_ERROR /* Fill root direct blocks */ - heap_size = 0; - free_space = 0; - if(fill_root_direct(fh, dxpl, cparam, &heap_size, &free_space, &nobjs)) + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, NULL)) FAIL_STACK_ERROR /* Get offset of random heap ID */ @@ -10462,7 +10592,7 @@ test_abs_remove_bogus(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpa FAIL_STACK_ERROR /* Make certain we can't accidentally use a valid heap ID */ - while(obj_off < heap_size) { + while(obj_off < state.heap_size) { /* Set heap ID to random (non-null) value */ for(u = 0; u < HEAP_ID_LEN; u++) heap_id[u] = HDrandom() + 1; @@ -10472,7 +10602,7 @@ test_abs_remove_bogus(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpa FAIL_STACK_ERROR } /* end while */ - /* Try removing bogus heap ID from empty heap */ + /* Try removing bogus heap ID from heap w/objects */ H5E_BEGIN_TRY { ret = H5HF_remove(fh, dxpl, heap_id); } H5E_END_TRY; @@ -10500,7 +10630,6 @@ error: } H5E_END_TRY; return(1); } /* test_abs_remove_bogus() */ -#endif /* QAK */ /*------------------------------------------------------------------------- @@ -10529,8 +10658,9 @@ test_abs_remove_one(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpara unsigned char heap_id[HEAP_ID_LEN]; /* Heap ID for object */ unsigned char obj[SMALL_OBJ_SIZE1]; /* Buffer for object to insert */ size_t id_len; /* Size of fractal heap IDs */ - hsize_t free_space; /* Size of free space in heap */ - hsize_t heap_size; /* Total size of heap */ + off_t empty_size; /* Size of a file with an empty heap */ + off_t file_size; /* Size of file currently */ + fheap_heap_state_t state; /* State of fractal heap */ unsigned u; /* Local index variable */ /* Set the filename to use for this test (dependent on fapl) */ @@ -10555,7 +10685,70 @@ test_abs_remove_one(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpara FAIL_STACK_ERROR if(!H5F_addr_defined(fh_addr)) FAIL_STACK_ERROR - if(check_stats(fh, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0)) + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Prepare for querying the size of a file with an empty heap */ + + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Close file */ + if(H5Fclose(file)<0) TEST_ERROR; + + /* Get the size of a file w/empty heap*/ + if((empty_size = h5_get_file_size(filename)) == 0) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + + /* + * Test removing first (small) object from absolute heap + */ + TESTING("removing single object from absolute heap"); + + /* Initialize the buffer for objects to insert */ + for(u = 0; u < sizeof(obj); u++) + obj[u] = u; + + /* Insert object into heap */ + if(H5HF_insert(fh, dxpl, sizeof(obj), obj, &heap_id) < 0) + FAIL_STACK_ERROR + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Check up on heap... */ + state.heap_size = DBLOCK_SIZE(fh, 0); + state.man_size = DBLOCK_SIZE(fh, 0); + state.man_alloc_size = DBLOCK_SIZE(fh, 0); + state.man_free_space = DBLOCK_FREE(fh, 0) - sizeof(obj); + state.nobjs = 1; + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Remove object from heap */ + if(H5HF_remove(fh, dxpl, heap_id) < 0) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -10569,17 +10762,354 @@ test_abs_remove_one(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpara FAIL_STACK_ERROR } /* end if */ + /* Check up on heap... */ + state.heap_size = 0; + state.man_size = 0; + state.man_alloc_size = 0; + state.man_free_space = 0; + state.nobjs = 0; + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Close the fractal heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Close the file */ + if(H5Fclose(file) < 0) + TEST_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) == 0) + TEST_ERROR + + /* Verify the file is correct size */ + if(file_size != empty_size) + TEST_ERROR + + PASSED() + + /* All tests passed */ + return(0); + +error: + H5E_BEGIN_TRY { + if(fh) + H5HF_close(fh, dxpl); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_abs_remove_one() */ + + +/*------------------------------------------------------------------------- + * Function: test_abs_remove_two + * + * Purpose: Test removing two objects from heap + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, May 22, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_abs_remove_two(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tparam) +{ + hid_t file = -1; /* File ID */ + hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */ + char filename[1024]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5HF_t *fh = NULL; /* Fractal heap wrapper */ + haddr_t fh_addr; /* Address of fractal heap */ + unsigned char heap_id1[HEAP_ID_LEN]; /* Heap ID for first object */ + unsigned char heap_id2[HEAP_ID_LEN]; /* Heap ID for second object */ + unsigned char obj[SMALL_OBJ_SIZE1]; /* Buffer for object to insert */ + size_t id_len; /* Size of fractal heap IDs */ + off_t empty_size; /* Size of a file with an empty heap */ + off_t file_size; /* Size of file currently */ + fheap_heap_state_t state; /* State of fractal heap */ + unsigned u; /* Local index variable */ + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Create absolute heap */ + if(NULL == (fh = H5HF_create(f, dxpl, cparam))) + FAIL_STACK_ERROR + if(H5HF_get_id_len(fh, &id_len) < 0) + FAIL_STACK_ERROR + if(id_len > HEAP_ID_LEN) + FAIL_STACK_ERROR + if(H5HF_get_heap_addr(fh, &fh_addr) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Prepare for querying the size of a file with an empty heap */ + + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Close file */ + if(H5Fclose(file)<0) TEST_ERROR; + + /* Get the size of a file w/empty heap*/ + if((empty_size = h5_get_file_size(filename)) == 0) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + /* - * Test removing first (small) object from absolute heap + * Test removing two (small) objects from absolute heap */ - TESTING("removing single object from absolute heap"); + TESTING("removing two objects from absolute heap"); /* Initialize the buffer for objects to insert */ for(u = 0; u < sizeof(obj); u++) obj[u] = u; + /* Insert first object into heap */ + if(H5HF_insert(fh, dxpl, sizeof(obj), obj, &heap_id1) < 0) + FAIL_STACK_ERROR + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Check up on heap... */ + state.heap_size = DBLOCK_SIZE(fh, 0); + state.man_size = DBLOCK_SIZE(fh, 0); + state.man_alloc_size = DBLOCK_SIZE(fh, 0); + state.man_free_space = DBLOCK_FREE(fh, 0) - sizeof(obj); + state.nobjs = 1; + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Insert second object into heap */ + if(H5HF_insert(fh, dxpl, sizeof(obj), obj, &heap_id2) < 0) + FAIL_STACK_ERROR + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Check up on heap... */ + state.man_free_space -= sizeof(obj); + state.nobjs++; + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Remove first object from heap */ + if(H5HF_remove(fh, dxpl, heap_id1) < 0) + FAIL_STACK_ERROR + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Check up on heap... */ + state.man_free_space += sizeof(obj); + state.nobjs--; + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Remove second object from heap */ + if(H5HF_remove(fh, dxpl, heap_id2) < 0) + FAIL_STACK_ERROR + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Check up on heap... */ + state.heap_size = 0; + state.man_size = 0; + state.man_alloc_size = 0; + state.man_free_space = 0; + state.nobjs = 0; + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Close the fractal heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Close the file */ + if(H5Fclose(file) < 0) + TEST_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) == 0) + TEST_ERROR + + /* Verify the file is correct size */ + if(file_size != empty_size) + TEST_ERROR + + PASSED() + + /* All tests passed */ + return(0); + +error: + H5E_BEGIN_TRY { + if(fh) + H5HF_close(fh, dxpl); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_abs_remove_two() */ + + +/*------------------------------------------------------------------------- + * Function: test_abs_remove_one_larger + * + * Purpose: Test removing single larger (but < standalone size) object + * from heap + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Tuesday, June 6, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_abs_remove_one_larger(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tparam) +{ + hid_t file = -1; /* File ID */ + hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */ + char filename[1024]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5HF_t *fh = NULL; /* Fractal heap wrapper */ + haddr_t fh_addr; /* Address of fractal heap */ + unsigned char heap_id[HEAP_ID_LEN]; /* Heap ID for object */ + unsigned char *obj; /* Buffer for object to insert */ + size_t obj_len; /* Length of object to insert */ + size_t id_len; /* Size of fractal heap IDs */ + off_t empty_size; /* Size of a file with an empty heap */ + off_t file_size; /* Size of file currently */ + fheap_heap_state_t state; /* State of fractal heap */ + unsigned u; /* Local index variable */ + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Create absolute heap */ + if(NULL == (fh = H5HF_create(f, dxpl, cparam))) + FAIL_STACK_ERROR + if(H5HF_get_id_len(fh, &id_len) < 0) + FAIL_STACK_ERROR + if(id_len > HEAP_ID_LEN) + FAIL_STACK_ERROR + if(H5HF_get_heap_addr(fh, &fh_addr) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Prepare for querying the size of a file with an empty heap */ + + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Close file */ + if(H5Fclose(file)<0) TEST_ERROR; + + /* Get the size of a file w/empty heap*/ + if((empty_size = h5_get_file_size(filename)) == 0) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + + /* + * Test removing one larger object from absolute heap + */ + TESTING("removing single larger object from absolute heap"); + + /* Set up object to insert */ + obj_len = DBLOCK_SIZE(fh, 2) + 1; + obj = shared_wobj_g; + /* Insert object into heap */ - if(H5HF_insert(fh, dxpl, sizeof(obj), obj, &heap_id) < 0) + if(H5HF_insert(fh, dxpl, obj_len, obj, &heap_id) < 0) FAIL_STACK_ERROR /* Check for closing & re-opening the heap */ @@ -10594,9 +11124,15 @@ test_abs_remove_one(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpara } /* end if */ /* Check up on heap... */ - heap_size = DBLOCK_SIZE(fh, 0); - free_space = DBLOCK_FREE(fh, 0) - sizeof(obj); - if(check_stats(fh, heap_size, heap_size, (hsize_t)0, free_space, (hsize_t)1)) + for(u = 0; u < 4; u++) { + state.heap_size += DBLOCK_SIZE(fh, u) * cparam->managed.width; + state.man_size += DBLOCK_SIZE(fh, u) * cparam->managed.width; + state.man_free_space += DBLOCK_FREE(fh, u) * cparam->managed.width; + } /* end for */ + state.man_alloc_size = DBLOCK_SIZE(fh, 3); + state.man_free_space -= obj_len; + state.nobjs = 1; + if(check_stats(fh, &state)) FAIL_STACK_ERROR /* Remove object from heap */ @@ -10615,11 +11151,283 @@ test_abs_remove_one(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpara } /* end if */ /* Check up on heap... */ - if(check_stats(fh, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0, (hsize_t)0)) + state.heap_size = 0; + state.man_size = 0; + state.man_alloc_size = 0; + state.man_free_space = 0; + state.nobjs = 0; + if(check_stats(fh, &state)) FAIL_STACK_ERROR + /* Close the fractal heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Close the file */ + if(H5Fclose(file) < 0) + TEST_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) == 0) + TEST_ERROR + + /* Verify the file is correct size */ + if(file_size != empty_size) + TEST_ERROR + PASSED() + /* All tests passed */ + return(0); + +error: + H5E_BEGIN_TRY { + if(fh) + H5HF_close(fh, dxpl); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_abs_remove_one_larger() */ + + +/*------------------------------------------------------------------------- + * Function: test_abs_remove_two_larger + * + * Purpose: Test removing two larger (but < standalone size) objects + * from heap + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Saturday, June 10, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_abs_remove_two_larger(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tparam) +{ + hid_t file = -1; /* File ID */ + hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */ + char filename[1024]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5HF_t *fh = NULL; /* Fractal heap wrapper */ + haddr_t fh_addr; /* Address of fractal heap */ + unsigned char heap_id1[HEAP_ID_LEN]; /* Heap ID for first object */ + unsigned char heap_id2[HEAP_ID_LEN]; /* Heap ID for second object */ + unsigned char *obj; /* Buffer for object to insert */ + size_t obj_len; /* Length of object to insert */ + size_t id_len; /* Size of fractal heap IDs */ + off_t empty_size; /* Size of a file with an empty heap */ + off_t file_size; /* Size of file currently */ + fheap_heap_state_t state; /* State of fractal heap */ + unsigned u; /* Local index variable */ + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Create absolute heap */ + if(NULL == (fh = H5HF_create(f, dxpl, cparam))) + FAIL_STACK_ERROR + if(H5HF_get_id_len(fh, &id_len) < 0) + FAIL_STACK_ERROR + if(id_len > HEAP_ID_LEN) + FAIL_STACK_ERROR + if(H5HF_get_heap_addr(fh, &fh_addr) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Prepare for querying the size of a file with an empty heap */ + + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Close file */ + if(H5Fclose(file)<0) TEST_ERROR; + + /* Get the size of a file w/empty heap*/ + if((empty_size = h5_get_file_size(filename)) == 0) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + + /* + * Test removing two larger objects from absolute heap + */ + if(tparam->del_dir == HEAP_DEL_FORWARD) + TESTING("removing two larger objects from absolute heap (forward)") + else + TESTING("removing two larger objects from absolute heap (reverse)") + + /* Set up first object to insert */ + obj_len = DBLOCK_SIZE(fh, 2) + 1; + obj = shared_wobj_g; + + /* Insert object into heap */ + if(H5HF_insert(fh, dxpl, obj_len, obj, &heap_id1) < 0) + FAIL_STACK_ERROR + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Check up on heap... */ + for(u = 0; u < 4; u++) { + state.heap_size += DBLOCK_SIZE(fh, u) * cparam->managed.width; + state.man_size += DBLOCK_SIZE(fh, u) * cparam->managed.width; + state.man_free_space += DBLOCK_FREE(fh, u) * cparam->managed.width; + } /* end for */ + state.man_alloc_size = DBLOCK_SIZE(fh, 3); + state.man_free_space -= obj_len; + state.nobjs = 1; + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Set up second object to insert */ + obj_len = DBLOCK_SIZE(fh, 4) + 1; + obj = shared_wobj_g; + + /* Insert object into heap */ + if(H5HF_insert(fh, dxpl, obj_len, obj, &heap_id2) < 0) + FAIL_STACK_ERROR + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Check up on heap... */ + /* (Goes to 8 rows because of doubling) */ + for(u = 4; u < 8; u++) { + state.heap_size += DBLOCK_SIZE(fh, u) * cparam->managed.width; + state.man_size += DBLOCK_SIZE(fh, u) * cparam->managed.width; + state.man_free_space += DBLOCK_FREE(fh, u) * cparam->managed.width; + } /* end for */ + state.man_alloc_size += DBLOCK_SIZE(fh, 5); + state.man_free_space -= obj_len; + state.nobjs = 2; + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Remove objects in different orders */ + if(tparam->del_dir == HEAP_DEL_FORWARD) { + /* Remove first object from heap */ + if(H5HF_remove(fh, dxpl, heap_id1) < 0) + FAIL_STACK_ERROR + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Check up on heap... */ + state.man_alloc_size -= DBLOCK_SIZE(fh, 3); + state.man_free_space += DBLOCK_SIZE(fh, 2) + 1; + state.nobjs = 1; + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Remove second object from heap */ + if(H5HF_remove(fh, dxpl, heap_id2) < 0) + FAIL_STACK_ERROR + } /* end if */ + else { + /* Remove second object from heap */ + if(H5HF_remove(fh, dxpl, heap_id2) < 0) + FAIL_STACK_ERROR + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Check up on heap... */ + /* (Goes to 4 rows because of halving) */ + for(u = 4; u < 8; u++) { + state.heap_size -= DBLOCK_SIZE(fh, u) * cparam->managed.width; + state.man_size -= DBLOCK_SIZE(fh, u) * cparam->managed.width; + state.man_free_space -= DBLOCK_FREE(fh, u) * cparam->managed.width; + } /* end for */ + state.man_alloc_size -= DBLOCK_SIZE(fh, 5); + state.man_free_space += DBLOCK_SIZE(fh, 4) + 1; + state.nobjs = 1; + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Remove first object from heap */ + if(H5HF_remove(fh, dxpl, heap_id1) < 0) + FAIL_STACK_ERROR + } /* end else */ + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Check up on heap... */ + state.heap_size = 0; + state.man_size = 0; + state.man_alloc_size = 0; + state.man_free_space = 0; + state.nobjs = 0; + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + /* Close the fractal heap */ if(H5HF_close(fh, dxpl) < 0) TEST_ERROR @@ -10628,6 +11436,20 @@ test_abs_remove_one(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tpara if(H5Fclose(file) < 0) TEST_ERROR + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) == 0) + TEST_ERROR + + /* Verify the file is correct size */ +#ifdef QAK +HDfprintf(stderr, "empty_size = %lu\n", (unsigned long)empty_size); +HDfprintf(stderr, "file_size = %lu\n", (unsigned long)file_size); +#endif /* QAK */ + if(file_size != empty_size) + TEST_ERROR + + PASSED() + /* All tests passed */ return(0); @@ -10638,7 +11460,1590 @@ error: H5Fclose(file); } H5E_END_TRY; return(1); -} /* test_abs_remove_one() */ +} /* test_abs_remove_two_larger() */ + + +/*------------------------------------------------------------------------- + * Function: test_abs_remove_three_larger + * + * Purpose: Test removing three larger (but < standalone size) objects + * from heap + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, June 12, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_abs_remove_three_larger(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tparam) +{ + hid_t file = -1; /* File ID */ + hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */ + char filename[1024]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5HF_t *fh = NULL; /* Fractal heap wrapper */ + haddr_t fh_addr; /* Address of fractal heap */ + unsigned char heap_id1[HEAP_ID_LEN]; /* Heap ID for first object */ + unsigned char heap_id2[HEAP_ID_LEN]; /* Heap ID for second object */ + unsigned char heap_id3[HEAP_ID_LEN]; /* Heap ID for third object */ + unsigned char *obj; /* Buffer for object to insert */ + size_t obj_len; /* Length of object to insert */ + size_t id_len; /* Size of fractal heap IDs */ + off_t empty_size; /* Size of a file with an empty heap */ + off_t file_size; /* Size of file currently */ + fheap_heap_state_t state; /* State of fractal heap */ + unsigned u; /* Local index variable */ + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Create absolute heap */ + if(NULL == (fh = H5HF_create(f, dxpl, cparam))) + FAIL_STACK_ERROR + if(H5HF_get_id_len(fh, &id_len) < 0) + FAIL_STACK_ERROR + if(id_len > HEAP_ID_LEN) + FAIL_STACK_ERROR + if(H5HF_get_heap_addr(fh, &fh_addr) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Prepare for querying the size of a file with an empty heap */ + + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Close file */ + if(H5Fclose(file)<0) TEST_ERROR; + + /* Get the size of a file w/empty heap*/ + if((empty_size = h5_get_file_size(filename)) == 0) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + + /* + * Test removing three larger objects from absolute heap + */ + if(tparam->del_dir == HEAP_DEL_FORWARD) + TESTING("removing three larger objects from absolute heap (forward)") + else + TESTING("removing three larger objects from absolute heap (reverse)") + + /* Set up first object to insert */ + obj_len = DBLOCK_SIZE(fh, 2) + 1; + obj = shared_wobj_g; + + /* Insert object into heap */ + if(H5HF_insert(fh, dxpl, obj_len, obj, &heap_id1) < 0) + FAIL_STACK_ERROR + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Check up on heap... */ + for(u = 0; u < 4; u++) { + state.heap_size += DBLOCK_SIZE(fh, u) * cparam->managed.width; + state.man_size += DBLOCK_SIZE(fh, u) * cparam->managed.width; + state.man_free_space += DBLOCK_FREE(fh, u) * cparam->managed.width; + } /* end for */ + state.man_alloc_size = DBLOCK_SIZE(fh, 3); + state.man_free_space -= obj_len; + state.nobjs = 1; + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Set up second object to insert */ + obj_len = DBLOCK_SIZE(fh, 4) + 1; + obj = shared_wobj_g; + + /* Insert object into heap */ + if(H5HF_insert(fh, dxpl, obj_len, obj, &heap_id2) < 0) + FAIL_STACK_ERROR + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Check up on heap... */ + /* (Goes to 8 rows because of doubling) */ + for(u = 4; u < 8; u++) { + state.heap_size += DBLOCK_SIZE(fh, u) * cparam->managed.width; + state.man_size += DBLOCK_SIZE(fh, u) * cparam->managed.width; + state.man_free_space += DBLOCK_FREE(fh, u) * cparam->managed.width; + } /* end for */ + state.man_alloc_size += DBLOCK_SIZE(fh, 5); + state.man_free_space -= obj_len; + state.nobjs = 2; + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Set up third object to insert */ + obj_len = DBLOCK_SIZE(fh, 7) + 1; + obj = shared_wobj_g; + + /* Insert object into heap */ + if(H5HF_insert(fh, dxpl, obj_len, obj, &heap_id3) < 0) + FAIL_STACK_ERROR + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Check up on heap... */ + /* (Goes to 16 rows because of doubling) */ + for(u = 8; u < 16; u++) { + state.heap_size += DBLOCK_SIZE(fh, u) * cparam->managed.width; + state.man_size += DBLOCK_SIZE(fh, u) * cparam->managed.width; + state.man_free_space += DBLOCK_FREE(fh, u) * cparam->managed.width; + } /* end for */ + state.man_alloc_size += DBLOCK_SIZE(fh, 8); + state.man_free_space -= obj_len; + state.nobjs = 3; + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Remove objects in different orders */ + if(tparam->del_dir == HEAP_DEL_FORWARD) { + /* Remove first object from heap */ + if(H5HF_remove(fh, dxpl, heap_id1) < 0) + FAIL_STACK_ERROR + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Check up on heap... */ + state.man_alloc_size -= DBLOCK_SIZE(fh, 3); + state.man_free_space += DBLOCK_SIZE(fh, 2) + 1; + state.nobjs = 2; + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Remove second object from heap */ + if(H5HF_remove(fh, dxpl, heap_id2) < 0) + FAIL_STACK_ERROR + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Check up on heap... */ + state.man_alloc_size -= DBLOCK_SIZE(fh, 5); + state.man_free_space += DBLOCK_SIZE(fh, 4) + 1; + state.nobjs = 1; + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Remove third object from heap */ + if(H5HF_remove(fh, dxpl, heap_id3) < 0) + FAIL_STACK_ERROR + } /* end if */ + else { + /* Remove third object from heap */ + if(H5HF_remove(fh, dxpl, heap_id3) < 0) + FAIL_STACK_ERROR + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Check up on heap... */ + /* (Goes to 8 rows because of halving) */ + for(u = 8; u < 16; u++) { + state.heap_size -= DBLOCK_SIZE(fh, u) * cparam->managed.width; + state.man_size -= DBLOCK_SIZE(fh, u) * cparam->managed.width; + state.man_free_space -= DBLOCK_FREE(fh, u) * cparam->managed.width; + } /* end for */ + state.man_alloc_size -= DBLOCK_SIZE(fh, 8); + state.man_free_space += DBLOCK_SIZE(fh, 7) + 1; + state.nobjs = 2; + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Remove second object from heap */ + if(H5HF_remove(fh, dxpl, heap_id2) < 0) + FAIL_STACK_ERROR + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Check up on heap... */ + /* (Goes to 4 rows because of halving) */ + for(u = 4; u < 8; u++) { + state.heap_size -= DBLOCK_SIZE(fh, u) * cparam->managed.width; + state.man_size -= DBLOCK_SIZE(fh, u) * cparam->managed.width; + state.man_free_space -= DBLOCK_FREE(fh, u) * cparam->managed.width; + } /* end for */ + state.man_alloc_size -= DBLOCK_SIZE(fh, 5); + state.man_free_space += DBLOCK_SIZE(fh, 4) + 1; + state.nobjs = 1; + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Remove first object from heap */ + if(H5HF_remove(fh, dxpl, heap_id1) < 0) + FAIL_STACK_ERROR + } /* end else */ + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Check up on heap... */ + state.heap_size = 0; + state.man_size = 0; + state.man_alloc_size = 0; + state.man_free_space = 0; + state.nobjs = 0; + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Close the fractal heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Close the file */ + if(H5Fclose(file) < 0) + TEST_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) == 0) + TEST_ERROR + + /* Verify the file is correct size */ +#ifdef QAK +HDfprintf(stderr, "empty_size = %lu\n", (unsigned long)empty_size); +HDfprintf(stderr, "file_size = %lu\n", (unsigned long)file_size); +#endif /* QAK */ + if(file_size != empty_size) + TEST_ERROR + + PASSED() + + /* All tests passed */ + return(0); + +error: + H5E_BEGIN_TRY { + if(fh) + H5HF_close(fh, dxpl); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_abs_remove_three_larger() */ +#endif /* QAK */ + +#ifndef QAK +#ifndef QAK2 + +/*------------------------------------------------------------------------- + * Function: test_abs_remove_root_direct + * + * Purpose: Test filling and removing all objects from root direct block in + * heap + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, May 22, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_abs_remove_root_direct(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tparam) +{ + hid_t file = -1; /* File ID */ + hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */ + char filename[1024]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5HF_t *fh = NULL; /* Fractal heap wrapper */ + haddr_t fh_addr; /* Address of fractal heap */ + fheap_heap_ids_t keep_ids; /* Structure to retain heap IDs */ + size_t id_len; /* Size of fractal heap IDs */ + off_t empty_size; /* Size of a file with an empty heap */ + off_t file_size; /* Size of file currently */ + fheap_heap_state_t state; /* State of fractal heap */ + const char *base_desc = "removing all objects from root direct block of absolute heap %s"; /* Test description */ + char *del_str = NULL; /* Deletion order description */ + char *test_desc = NULL; /* Test description */ + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Create absolute heap */ + if(NULL == (fh = H5HF_create(f, dxpl, cparam))) + FAIL_STACK_ERROR + if(H5HF_get_id_len(fh, &id_len) < 0) + FAIL_STACK_ERROR + if(id_len > HEAP_ID_LEN) + FAIL_STACK_ERROR + if(H5HF_get_heap_addr(fh, &fh_addr) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Prepare for querying the size of a file with an empty heap */ + + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Close file */ + if(H5Fclose(file)<0) TEST_ERROR; + + /* Get the size of a file w/empty heap*/ + if((empty_size = h5_get_file_size(filename)) == 0) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + + /* + * Test filling & removing all (small) objects from root direct block of absolute heap + */ + del_str = get_del_string(tparam); + HDassert(del_str); + test_desc = H5MM_malloc(HDstrlen(del_str) + HDstrlen(base_desc)); + sprintf(test_desc, base_desc, del_str); + TESTING(test_desc); + H5MM_xfree(del_str); + H5MM_xfree(test_desc); + + /* Initialize the heap ID structure */ + HDmemset(&keep_ids, 0, sizeof(fheap_heap_ids_t)); + + /* Fill the heap up */ + state.heap_size = DBLOCK_SIZE(fh, 0); + state.man_size = DBLOCK_SIZE(fh, 0); + state.man_alloc_size = DBLOCK_SIZE(fh, 0); + state.man_free_space = DBLOCK_FREE(fh, 0); + if(fill_heap(fh, dxpl, 0, SMALL_OBJ_SIZE1, &state, &keep_ids)) + FAIL_STACK_ERROR + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Check up on heap... */ + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Delete objects inserted (either forward or reverse order) */ + if(del_objs(f, dxpl, &fh, tparam, &state, &keep_ids)) + FAIL_STACK_ERROR + + /* Close the fractal heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Close the file */ + if(H5Fclose(file) < 0) + TEST_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) == 0) + TEST_ERROR + + /* Verify the file is correct size */ + if(file_size != empty_size) + TEST_ERROR + + /* Free resources */ + H5MM_xfree(keep_ids.ids); + H5MM_xfree(keep_ids.lens); + H5MM_xfree(keep_ids.offs); + + PASSED() + + /* All tests passed */ + return(0); + +error: + H5E_BEGIN_TRY { + H5MM_xfree(keep_ids.ids); + H5MM_xfree(keep_ids.lens); + H5MM_xfree(keep_ids.offs); + H5MM_xfree(del_str); + H5MM_xfree(test_desc); + if(fh) + H5HF_close(fh, dxpl); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_abs_remove_root_direct() */ + + +/*------------------------------------------------------------------------- + * Function: test_abs_remove_two_direct + * + * Purpose: Test filling and removing all objects from (first) two direct + * blocks in heap + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, May 22, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_abs_remove_two_direct(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tparam) +{ + hid_t file = -1; /* File ID */ + hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */ + char filename[1024]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5HF_t *fh = NULL; /* Fractal heap wrapper */ + haddr_t fh_addr; /* Address of fractal heap */ + fheap_heap_ids_t keep_ids; /* Structure to retain heap IDs */ + size_t id_len; /* Size of fractal heap IDs */ + off_t empty_size; /* Size of a file with an empty heap */ + off_t file_size; /* Size of file currently */ + fheap_heap_state_t state; /* State of fractal heap */ + const char *base_desc = "removing all objects from two direct blocks of absolute heap %s"; /* Test description */ + char *del_str = NULL; /* Deletion order description */ + char *test_desc = NULL; /* Test description */ + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Create absolute heap */ + if(NULL == (fh = H5HF_create(f, dxpl, cparam))) + FAIL_STACK_ERROR + if(H5HF_get_id_len(fh, &id_len) < 0) + FAIL_STACK_ERROR + if(id_len > HEAP_ID_LEN) + FAIL_STACK_ERROR + if(H5HF_get_heap_addr(fh, &fh_addr) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Prepare for querying the size of a file with an empty heap */ + + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Close file */ + if(H5Fclose(file)<0) TEST_ERROR; + + /* Get the size of a file w/empty heap*/ + if((empty_size = h5_get_file_size(filename)) == 0) + TEST_ERROR +#ifdef QAK +HDfprintf(stderr, "empty_size = %lu\n", (unsigned long)empty_size); +#endif /* QAK */ + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + + /* + * Test filling & removing all (small) objects from two direct blocks of absolute heap + */ + del_str = get_del_string(tparam); + HDassert(del_str); + test_desc = H5MM_malloc(HDstrlen(del_str) + HDstrlen(base_desc)); + sprintf(test_desc, base_desc, del_str); + TESTING(test_desc); + H5MM_xfree(del_str); + H5MM_xfree(test_desc); + + /* Initialize the heap ID structure */ + HDmemset(&keep_ids, 0, sizeof(fheap_heap_ids_t)); + + /* Fill the first block in heap */ + state.heap_size = DBLOCK_SIZE(fh, 0); + state.man_size = DBLOCK_SIZE(fh, 0); + state.man_alloc_size = DBLOCK_SIZE(fh, 0); + state.man_free_space = DBLOCK_FREE(fh, 0); + if(fill_heap(fh, dxpl, 0, SMALL_OBJ_SIZE1, &state, &keep_ids)) + FAIL_STACK_ERROR + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Check up on heap... */ + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Fill the second block in heap */ + state.heap_size = cparam->managed.width * DBLOCK_SIZE(fh, 0); + state.man_size = cparam->managed.width * DBLOCK_SIZE(fh, 0); + state.man_alloc_size += DBLOCK_SIZE(fh, 0); + state.man_free_space = (cparam->managed.width - 1) * DBLOCK_FREE(fh, 0); + if(fill_heap(fh, dxpl, 0, SMALL_OBJ_SIZE1, &state, &keep_ids)) + FAIL_STACK_ERROR + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Check up on heap... */ + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Delete objects inserted (either forward or reverse order) */ + if(del_objs(f, dxpl, &fh, tparam, &state, &keep_ids)) + FAIL_STACK_ERROR + + /* Close the fractal heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + fh = NULL; + + /* Close the file */ + if(H5Fclose(file) < 0) + TEST_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) == 0) + TEST_ERROR +#ifdef QAK +HDfprintf(stderr, "file_size = %lu\n", (unsigned long)file_size); +#endif /* QAK */ + + /* Verify the file is correct size */ + if(file_size != empty_size) + TEST_ERROR + + /* Free resources */ + H5MM_xfree(keep_ids.ids); + H5MM_xfree(keep_ids.lens); + H5MM_xfree(keep_ids.offs); + + PASSED() + + /* All tests passed */ + return(0); + +error: + H5E_BEGIN_TRY { + H5MM_xfree(keep_ids.ids); + H5MM_xfree(keep_ids.lens); + H5MM_xfree(keep_ids.offs); + H5MM_xfree(del_str); + H5MM_xfree(test_desc); + if(fh) + H5HF_close(fh, dxpl); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_abs_remove_two_direct() */ + + +/*------------------------------------------------------------------------- + * Function: test_abs_remove_first_row + * + * Purpose: Test filling and removing all objects from first row of direct + * blocks in heap + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, June 5, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_abs_remove_first_row(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tparam) +{ + hid_t file = -1; /* File ID */ + hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */ + char filename[1024]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5HF_t *fh = NULL; /* Fractal heap wrapper */ + haddr_t fh_addr; /* Address of fractal heap */ + fheap_heap_ids_t keep_ids; /* Structure to retain heap IDs */ + size_t id_len; /* Size of fractal heap IDs */ + off_t empty_size; /* Size of a file with an empty heap */ + off_t file_size; /* Size of file currently */ + fheap_heap_state_t state; /* State of fractal heap */ + const char *base_desc = "removing all objects from first row of direct blocks of absolute heap %s"; /* Test description */ + char *del_str = NULL; /* Deletion order description */ + char *test_desc = NULL; /* Test description */ + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Create absolute heap */ + if(NULL == (fh = H5HF_create(f, dxpl, cparam))) + FAIL_STACK_ERROR + if(H5HF_get_id_len(fh, &id_len) < 0) + FAIL_STACK_ERROR + if(id_len > HEAP_ID_LEN) + FAIL_STACK_ERROR + if(H5HF_get_heap_addr(fh, &fh_addr) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Prepare for querying the size of a file with an empty heap */ + + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Close file */ + if(H5Fclose(file)<0) TEST_ERROR; + + /* Get the size of a file w/empty heap*/ + if((empty_size = h5_get_file_size(filename)) == 0) + TEST_ERROR +#ifdef QAK +HDfprintf(stderr, "empty_size = %lu\n", (unsigned long)empty_size); +#endif /* QAK */ + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + + /* + * Test filling & removing all (small) objects from first row of direct blocks of absolute heap + */ + del_str = get_del_string(tparam); + HDassert(del_str); + test_desc = H5MM_malloc(HDstrlen(del_str) + HDstrlen(base_desc)); + sprintf(test_desc, base_desc, del_str); + TESTING(test_desc); + H5MM_xfree(del_str); + H5MM_xfree(test_desc); + + /* Initialize the heap ID structure */ + HDmemset(&keep_ids, 0, sizeof(fheap_heap_ids_t)); + + /* Fill first row of direct blocks */ + if(fill_root_row(fh, dxpl, 0, SMALL_OBJ_SIZE1, &state, &keep_ids)) + FAIL_STACK_ERROR + + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Check up on heap... */ + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Delete objects inserted (either forward or reverse order) */ + if(del_objs(f, dxpl, &fh, tparam, &state, &keep_ids)) + FAIL_STACK_ERROR + + /* Close the fractal heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + fh = NULL; + + /* Close the file */ + if(H5Fclose(file) < 0) + TEST_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) == 0) + TEST_ERROR +#ifdef QAK +HDfprintf(stderr, "file_size = %lu\n", (unsigned long)file_size); +#endif /* QAK */ + + /* Verify the file is correct size */ + if(file_size != empty_size) + TEST_ERROR + + /* Free resources */ + H5MM_xfree(keep_ids.ids); + H5MM_xfree(keep_ids.lens); + H5MM_xfree(keep_ids.offs); + + PASSED() + + /* All tests passed */ + return(0); + +error: + H5E_BEGIN_TRY { + H5MM_xfree(keep_ids.ids); + H5MM_xfree(keep_ids.lens); + H5MM_xfree(keep_ids.offs); + H5MM_xfree(del_str); + H5MM_xfree(test_desc); + if(fh) + H5HF_close(fh, dxpl); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_abs_remove_first_row() */ + + +/*------------------------------------------------------------------------- + * Function: test_abs_remove_first_two_rows + * + * Purpose: Test filling and removing all objects from first two rows of + * direct blocks in heap + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Monday, June 12, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_abs_remove_first_two_rows(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tparam) +{ + hid_t file = -1; /* File ID */ + hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */ + char filename[1024]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5HF_t *fh = NULL; /* Fractal heap wrapper */ + haddr_t fh_addr; /* Address of fractal heap */ + fheap_heap_ids_t keep_ids; /* Structure to retain heap IDs */ + size_t id_len; /* Size of fractal heap IDs */ + off_t empty_size; /* Size of a file with an empty heap */ + off_t file_size; /* Size of file currently */ + fheap_heap_state_t state; /* State of fractal heap */ + const char *base_desc = "removing all objects from first two rows of direct blocks of absolute heap %s"; /* Test description */ + char *del_str = NULL; /* Deletion order description */ + char *test_desc = NULL; /* Test description */ + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Create absolute heap */ + if(NULL == (fh = H5HF_create(f, dxpl, cparam))) + FAIL_STACK_ERROR + if(H5HF_get_id_len(fh, &id_len) < 0) + FAIL_STACK_ERROR + if(id_len > HEAP_ID_LEN) + FAIL_STACK_ERROR + if(H5HF_get_heap_addr(fh, &fh_addr) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Prepare for querying the size of a file with an empty heap */ + + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Close file */ + if(H5Fclose(file)<0) TEST_ERROR; + + /* Get the size of a file w/empty heap*/ + if((empty_size = h5_get_file_size(filename)) == 0) + TEST_ERROR +#ifdef QAK +HDfprintf(stderr, "empty_size = %lu\n", (unsigned long)empty_size); +#endif /* QAK */ + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + + /* + * Test filling & removing all (small) objects from first row of direct blocks of absolute heap + */ + del_str = get_del_string(tparam); + HDassert(del_str); + test_desc = H5MM_malloc(HDstrlen(del_str) + HDstrlen(base_desc)); + sprintf(test_desc, base_desc, del_str); + TESTING(test_desc); + H5MM_xfree(del_str); + H5MM_xfree(test_desc); + + /* Initialize the heap ID structure */ + HDmemset(&keep_ids, 0, sizeof(fheap_heap_ids_t)); + + /* Fill first two rows of direct blocks */ + if(fill_root_row(fh, dxpl, 0, SMALL_OBJ_SIZE1, &state, &keep_ids)) + FAIL_STACK_ERROR + if(fill_root_row(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, &keep_ids)) + FAIL_STACK_ERROR + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Check up on heap... */ + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Delete objects inserted (either forward or reverse order) */ + if(del_objs(f, dxpl, &fh, tparam, &state, &keep_ids)) + FAIL_STACK_ERROR + + /* Close the fractal heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + fh = NULL; + + /* Close the file */ + if(H5Fclose(file) < 0) + TEST_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) == 0) + TEST_ERROR +#ifdef QAK +HDfprintf(stderr, "file_size = %lu\n", (unsigned long)file_size); +#endif /* QAK */ + + /* Verify the file is correct size */ + if(file_size != empty_size) + TEST_ERROR + + /* Free resources */ + H5MM_xfree(keep_ids.ids); + H5MM_xfree(keep_ids.lens); + H5MM_xfree(keep_ids.offs); + + PASSED() + + /* All tests passed */ + return(0); + +error: + H5E_BEGIN_TRY { + H5MM_xfree(keep_ids.ids); + H5MM_xfree(keep_ids.lens); + H5MM_xfree(keep_ids.offs); + H5MM_xfree(del_str); + H5MM_xfree(test_desc); + if(fh) + H5HF_close(fh, dxpl); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_abs_remove_first_two_rows() */ + + +/*------------------------------------------------------------------------- + * Function: test_abs_remove_first_four_rows + * + * Purpose: Test filling and removing all objects from first four rows of + * direct blocks in heap + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Tuesday, June 13, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_abs_remove_first_four_rows(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tparam) +{ + hid_t file = -1; /* File ID */ + hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */ + char filename[1024]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5HF_t *fh = NULL; /* Fractal heap wrapper */ + haddr_t fh_addr; /* Address of fractal heap */ + fheap_heap_ids_t keep_ids; /* Structure to retain heap IDs */ + size_t id_len; /* Size of fractal heap IDs */ + off_t empty_size; /* Size of a file with an empty heap */ + off_t file_size; /* Size of file currently */ + fheap_heap_state_t state; /* State of fractal heap */ + const char *base_desc = "removing all objects from first four rows of direct blocks of absolute heap %s"; /* Test description */ + char *del_str = NULL; /* Deletion order description */ + char *test_desc = NULL; /* Test description */ + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Create absolute heap */ + if(NULL == (fh = H5HF_create(f, dxpl, cparam))) + FAIL_STACK_ERROR + if(H5HF_get_id_len(fh, &id_len) < 0) + FAIL_STACK_ERROR + if(id_len > HEAP_ID_LEN) + FAIL_STACK_ERROR + if(H5HF_get_heap_addr(fh, &fh_addr) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Prepare for querying the size of a file with an empty heap */ + + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Close file */ + if(H5Fclose(file)<0) TEST_ERROR; + + /* Get the size of a file w/empty heap*/ + if((empty_size = h5_get_file_size(filename)) == 0) + TEST_ERROR +#ifdef QAK +HDfprintf(stderr, "empty_size = %lu\n", (unsigned long)empty_size); +#endif /* QAK */ + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + + /* + * Test filling & removing all (small) objects from first row of direct blocks of absolute heap + */ + del_str = get_del_string(tparam); + HDassert(del_str); + test_desc = H5MM_malloc(HDstrlen(del_str) + HDstrlen(base_desc)); + sprintf(test_desc, base_desc, del_str); + TESTING(test_desc); + H5MM_xfree(del_str); + H5MM_xfree(test_desc); + + /* Initialize the heap ID structure */ + HDmemset(&keep_ids, 0, sizeof(fheap_heap_ids_t)); + + /* Fill first two rows of direct blocks */ + if(fill_root_row(fh, dxpl, 0, SMALL_OBJ_SIZE1, &state, &keep_ids)) + FAIL_STACK_ERROR + if(fill_root_row(fh, dxpl, 1, SMALL_OBJ_SIZE1, &state, &keep_ids)) + FAIL_STACK_ERROR + if(fill_root_row(fh, dxpl, 2, SMALL_OBJ_SIZE1, &state, &keep_ids)) + FAIL_STACK_ERROR + if(fill_root_row(fh, dxpl, 3, SMALL_OBJ_SIZE1, &state, &keep_ids)) + FAIL_STACK_ERROR + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Check up on heap... */ + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Delete objects inserted (either forward or reverse order) */ + if(del_objs(f, dxpl, &fh, tparam, &state, &keep_ids)) + FAIL_STACK_ERROR + + /* Close the fractal heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + fh = NULL; + + /* Close the file */ + if(H5Fclose(file) < 0) + TEST_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) == 0) + TEST_ERROR +#ifdef QAK +HDfprintf(stderr, "file_size = %lu\n", (unsigned long)file_size); +#endif /* QAK */ + + /* Verify the file is correct size */ + if(file_size != empty_size) + TEST_ERROR + + /* Free resources */ + H5MM_xfree(keep_ids.ids); + H5MM_xfree(keep_ids.lens); + H5MM_xfree(keep_ids.offs); + + PASSED() + + /* All tests passed */ + return(0); + +error: + H5E_BEGIN_TRY { + H5MM_xfree(keep_ids.ids); + H5MM_xfree(keep_ids.lens); + H5MM_xfree(keep_ids.offs); + H5MM_xfree(del_str); + H5MM_xfree(test_desc); + if(fh) + H5HF_close(fh, dxpl); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_abs_remove_first_four_rows() */ + + +/*------------------------------------------------------------------------- + * Function: test_abs_remove_all_root_direct + * + * Purpose: Test filling and removing all objects from all direct blocks + * in root indirect block of heap + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Tuesday, June 13, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_abs_remove_all_root_direct(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tparam) +{ + hid_t file = -1; /* File ID */ + hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */ + char filename[1024]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5HF_t *fh = NULL; /* Fractal heap wrapper */ + haddr_t fh_addr; /* Address of fractal heap */ + fheap_heap_ids_t keep_ids; /* Structure to retain heap IDs */ + size_t id_len; /* Size of fractal heap IDs */ + off_t empty_size; /* Size of a file with an empty heap */ + off_t file_size; /* Size of file currently */ + fheap_heap_state_t state; /* State of fractal heap */ + const char *base_desc = "removing all objects from all direct blocks of root group in absolute heap %s"; /* Test description */ + char *del_str = NULL; /* Deletion order description */ + char *test_desc = NULL; /* Test description */ + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Create absolute heap */ + if(NULL == (fh = H5HF_create(f, dxpl, cparam))) + FAIL_STACK_ERROR + if(H5HF_get_id_len(fh, &id_len) < 0) + FAIL_STACK_ERROR + if(id_len > HEAP_ID_LEN) + FAIL_STACK_ERROR + if(H5HF_get_heap_addr(fh, &fh_addr) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Prepare for querying the size of a file with an empty heap */ + + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Close file */ + if(H5Fclose(file)<0) TEST_ERROR; + + /* Get the size of a file w/empty heap*/ + if((empty_size = h5_get_file_size(filename)) == 0) + TEST_ERROR +#ifdef QAK +HDfprintf(stderr, "empty_size = %lu\n", (unsigned long)empty_size); +#endif /* QAK */ + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + + /* + * Test filling & removing all (small) objects from first row of direct blocks of absolute heap + */ + del_str = get_del_string(tparam); + HDassert(del_str); + test_desc = H5MM_malloc(HDstrlen(del_str) + HDstrlen(base_desc)); + sprintf(test_desc, base_desc, del_str); + TESTING(test_desc); + H5MM_xfree(del_str); + H5MM_xfree(test_desc); + + /* Initialize the heap ID structure */ + HDmemset(&keep_ids, 0, sizeof(fheap_heap_ids_t)); + + /* Fill direct blocks in root indirect block */ + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, &keep_ids)) + FAIL_STACK_ERROR + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Check up on heap... */ + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Delete objects inserted (either forward or reverse order) */ + if(del_objs(f, dxpl, &fh, tparam, &state, &keep_ids)) + FAIL_STACK_ERROR + + /* Close the fractal heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + fh = NULL; + + /* Close the file */ + if(H5Fclose(file) < 0) + TEST_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) == 0) + TEST_ERROR +#ifdef QAK +HDfprintf(stderr, "file_size = %lu\n", (unsigned long)file_size); +#endif /* QAK */ + + /* Verify the file is correct size */ + if(file_size != empty_size) + TEST_ERROR + + /* Free resources */ + H5MM_xfree(keep_ids.ids); + H5MM_xfree(keep_ids.lens); + H5MM_xfree(keep_ids.offs); + + PASSED() + + /* All tests passed */ + return(0); + +error: + H5E_BEGIN_TRY { + H5MM_xfree(keep_ids.ids); + H5MM_xfree(keep_ids.lens); + H5MM_xfree(keep_ids.offs); + H5MM_xfree(del_str); + H5MM_xfree(test_desc); + if(fh) + H5HF_close(fh, dxpl); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_abs_remove_all_root_direct() */ +#endif /* QAK2 */ + +#ifdef NOT_YET + +/*------------------------------------------------------------------------- + * Function: test_abs_remove_2nd_indirect + * + * Purpose: Test filling and removing all objects up to 2nd level indirect + * blocks of heap + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Tuesday, June 13, 2006 + * + *------------------------------------------------------------------------- + */ +static int +test_abs_remove_2nd_indirect(hid_t fapl, H5HF_create_t *cparam, fheap_test_param_t *tparam) +{ + hid_t file = -1; /* File ID */ + hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */ + char filename[1024]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5HF_t *fh = NULL; /* Fractal heap wrapper */ + haddr_t fh_addr; /* Address of fractal heap */ + fheap_heap_ids_t keep_ids; /* Structure to retain heap IDs */ + size_t id_len; /* Size of fractal heap IDs */ + off_t empty_size; /* Size of a file with an empty heap */ + off_t file_size; /* Size of file currently */ + fheap_heap_state_t state; /* State of fractal heap */ + const char *base_desc = "removing all objects from 2nd level indirect blocks of absolute heap %s"; /* Test description */ + char *del_str = NULL; /* Deletion order description */ + char *test_desc = NULL; /* Test description */ + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Create absolute heap */ + if(NULL == (fh = H5HF_create(f, dxpl, cparam))) + FAIL_STACK_ERROR + if(H5HF_get_id_len(fh, &id_len) < 0) + FAIL_STACK_ERROR + if(id_len > HEAP_ID_LEN) + FAIL_STACK_ERROR + if(H5HF_get_heap_addr(fh, &fh_addr) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + FAIL_STACK_ERROR + HDmemset(&state, 0, sizeof(fheap_heap_state_t)); + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Prepare for querying the size of a file with an empty heap */ + + /* Close (empty) heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Close file */ + if(H5Fclose(file)<0) TEST_ERROR; + + /* Get the size of a file w/empty heap*/ + if((empty_size = h5_get_file_size(filename)) == 0) + TEST_ERROR +#ifdef QAK +HDfprintf(stderr, "empty_size = %lu\n", (unsigned long)empty_size); +#endif /* QAK */ + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + STACK_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + + /* + * Test filling & removing all (small) objects from first row of direct blocks of absolute heap + */ + del_str = get_del_string(tparam); + HDassert(del_str); + test_desc = H5MM_malloc(HDstrlen(del_str) + HDstrlen(base_desc)); + sprintf(test_desc, base_desc, del_str); + TESTING(test_desc); + H5MM_xfree(del_str); + H5MM_xfree(test_desc); + + /* Initialize the heap ID structure */ + HDmemset(&keep_ids, 0, sizeof(fheap_heap_ids_t)); + + /* Fill direct blocks in root indirect block */ + if(fill_root_direct(fh, dxpl, SMALL_OBJ_SIZE1, &state, &keep_ids)) + FAIL_STACK_ERROR + + /* Fill all rows of 2nd level indirect blocks */ + if(fill_all_2nd_indirect_rows(fh, dxpl, SMALL_OBJ_SIZE1, &state, &keep_ids)) + FAIL_STACK_ERROR + + /* Check for closing & re-opening the heap */ + if(tparam->reopen_heap) { + /* Close heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + + /* Re-open heap */ + if(NULL == (fh = H5HF_open(f, dxpl, fh_addr))) + FAIL_STACK_ERROR + } /* end if */ + + /* Check up on heap... */ + if(check_stats(fh, &state)) + FAIL_STACK_ERROR + + /* Delete objects inserted (either forward or reverse order) */ + if(del_objs(f, dxpl, &fh, tparam, &state, &keep_ids)) + FAIL_STACK_ERROR + + /* Close the fractal heap */ + if(H5HF_close(fh, dxpl) < 0) + TEST_ERROR + fh = NULL; + + /* Close the file */ + if(H5Fclose(file) < 0) + TEST_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) == 0) + TEST_ERROR +#ifdef QAK +HDfprintf(stderr, "file_size = %lu\n", (unsigned long)file_size); +#endif /* QAK */ + + /* Verify the file is correct size */ + if(file_size != empty_size) + TEST_ERROR + + /* Free resources */ + H5MM_xfree(keep_ids.ids); + H5MM_xfree(keep_ids.lens); + H5MM_xfree(keep_ids.offs); + + PASSED() + + /* All tests passed */ + return(0); + +error: + H5E_BEGIN_TRY { + H5MM_xfree(keep_ids.ids); + H5MM_xfree(keep_ids.lens); + H5MM_xfree(keep_ids.offs); + H5MM_xfree(del_str); + H5MM_xfree(test_desc); + if(fh) + H5HF_close(fh, dxpl); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_abs_remove_2nd_indirect() */ +#endif /* NOT_YET */ +#endif /* QAK */ /*------------------------------------------------------------------------- @@ -10662,6 +13067,7 @@ main(void) H5HF_create_t cparam; /* Creation parameters for heap */ hid_t fapl = -1; /* File access property list for data files */ fheap_test_type_t curr_test; /* Current test being worked on */ + unsigned u; /* Local index variable */ unsigned nerrors = 0; /* Cumulative error count */ int ExpressMode; @@ -10670,18 +13076,27 @@ main(void) fapl = h5_fileaccess(); ExpressMode = GetTestExpress(); if (ExpressMode) - printf("***Express test mode on. Some tests maybe skipped\n"); + printf("***Express test mode on. Some tests may be skipped\n"); /* Initialize heap's creation parameters */ init_small_cparam(&cparam); + /* Allocate space for the shared objects */ + shared_obj_size_g = cparam.standalone_size + 256; + shared_wobj_g = H5MM_malloc(shared_obj_size_g); + shared_robj_g = H5MM_malloc(shared_obj_size_g); + + /* Initialize the shared write buffer for objects */ + for(u = 0; u < shared_obj_size_g; u++) + shared_wobj_g[u] = (unsigned char)u; + /* Iterate over the testing parameters */ #ifndef QAK for(curr_test = FHEAP_TEST_NORMAL; curr_test < FHEAP_TEST_NTESTS; curr_test++) { #else /* QAK */ HDfprintf(stderr, "Uncomment test loop!\n"); -curr_test = FHEAP_TEST_NORMAL; -/* curr_test = FHEAP_TEST_REOPEN; */ +/* curr_test = FHEAP_TEST_NORMAL; */ +curr_test = FHEAP_TEST_REOPEN; #endif /* QAK */ /* Clear the testing parameters */ HDmemset(&tparam, 0, sizeof(fheap_test_param_t)); @@ -10749,47 +13164,43 @@ curr_test = FHEAP_TEST_NORMAL; if (ExpressMode) printf("***Express test mode on. Some tests skipped\n"); else - nerrors += test_abs_start_5th_recursive_indirect(fapl, &cparam, &tparam); + nerrors += test_abs_start_5th_recursive_indirect(fapl, &cparam, &tparam); #else /* QAK */ HDfprintf(stderr, "Uncomment tests!\n"); #endif /* QAK */ #ifndef QAK + /* Skip blocks insertion */ if (ExpressMode) printf("***Express test mode on. Some tests skipped\n"); else { - /* Skip blocks insertion */ - nerrors += test_abs_skip_start_block(fapl, &cparam, &tparam); - nerrors += test_abs_skip_start_block_add_back(fapl, &cparam, &tparam); - nerrors += test_abs_skip_start_block_add_skipped(fapl, &cparam, &tparam); - nerrors += test_abs_skip_2nd_block(fapl, &cparam, &tparam); - nerrors += test_abs_skip_2nd_block_add_skipped(fapl, &cparam, &tparam); - nerrors += test_abs_fill_one_partial_skip_2nd_block_add_skipped(fapl, &cparam, &tparam); - nerrors += test_abs_fill_row_skip_add_skipped(fapl, &cparam, &tparam); - nerrors += test_abs_fill_direct_skip_indirect_start_block_add_skipped(fapl, &cparam, &tparam); - nerrors += test_abs_fill_direct_skip_2nd_indirect_start_block_add_skipped(fapl, &cparam, &tparam); - nerrors += test_abs_fill_2nd_direct_less_one_wrap_start_block_add_skipped(fapl, &cparam, &tparam); - nerrors += test_abs_fill_direct_skip_2nd_indirect_skip_2nd_block_add_skipped(fapl, &cparam, &tparam); - nerrors += test_abs_fill_direct_skip_indirect_two_rows_add_skipped(fapl, &cparam, &tparam); - nerrors += test_abs_fill_2nd_direct_skip_start_block_add_skipped(fapl, &cparam, &tparam); - nerrors += test_abs_fill_2nd_direct_skip_2nd_indirect_start_block_add_skipped(fapl, &cparam, &tparam); - nerrors += test_abs_fill_2nd_direct_fill_direct_skip_3rd_indirect_start_block_add_skipped(fapl, &cparam, &tparam); - nerrors += test_abs_fill_2nd_direct_fill_direct_skip2_3rd_indirect_start_block_add_skipped(fapl, &cparam, &tparam); - nerrors += test_abs_fill_3rd_direct_less_one_fill_direct_wrap_start_block_add_skipped(fapl, &cparam, &tparam); - nerrors += test_abs_fill_1st_row_3rd_direct_fill_2nd_direct_less_one_wrap_start_block_add_skipped(fapl, &cparam, &tparam); - nerrors += test_abs_fill_3rd_direct_fill_direct_skip_start_block_add_skipped(fapl, &cparam, &tparam); - nerrors += test_abs_fill_3rd_direct_fill_2nd_direct_fill_direct_skip_3rd_indirect_start_block_add_skipped(fapl, &cparam, &tparam); - nerrors += test_abs_fill_3rd_direct_fill_2nd_direct_fill_direct_skip_3rd_indirect_two_rows_start_block_add_skipped(fapl, &cparam, &tparam); - nerrors += test_abs_fill_3rd_direct_fill_2nd_direct_fill_direct_skip_3rd_indirect_wrap_start_block_add_skipped(fapl, &cparam, &tparam); - nerrors += test_abs_fill_4th_direct_less_one_fill_2nd_direct_fill_direct_skip_3rd_indirect_wrap_start_block_add_skipped(fapl, &cparam, &tparam); - } -#else /* QAK */ -HDfprintf(stderr, "Uncomment tests!\n"); -#endif /* QAK */ - - /* Additional skipped block insertion tests */ -#ifndef QAK - nerrors += test_abs_skip_direct_skip_indirect_two_rows_add_skipped(fapl, &cparam, &tparam); + nerrors += test_abs_skip_start_block(fapl, &cparam, &tparam); + nerrors += test_abs_skip_start_block_add_back(fapl, &cparam, &tparam); + nerrors += test_abs_skip_start_block_add_skipped(fapl, &cparam, &tparam); + nerrors += test_abs_skip_2nd_block(fapl, &cparam, &tparam); + nerrors += test_abs_skip_2nd_block_add_skipped(fapl, &cparam, &tparam); + nerrors += test_abs_fill_one_partial_skip_2nd_block_add_skipped(fapl, &cparam, &tparam); + nerrors += test_abs_fill_row_skip_add_skipped(fapl, &cparam, &tparam); + nerrors += test_abs_fill_direct_skip_indirect_start_block_add_skipped(fapl, &cparam, &tparam); + nerrors += test_abs_fill_direct_skip_2nd_indirect_start_block_add_skipped(fapl, &cparam, &tparam); + nerrors += test_abs_fill_2nd_direct_less_one_wrap_start_block_add_skipped(fapl, &cparam, &tparam); + nerrors += test_abs_fill_direct_skip_2nd_indirect_skip_2nd_block_add_skipped(fapl, &cparam, &tparam); + nerrors += test_abs_fill_direct_skip_indirect_two_rows_add_skipped(fapl, &cparam, &tparam); + nerrors += test_abs_fill_2nd_direct_skip_start_block_add_skipped(fapl, &cparam, &tparam); + nerrors += test_abs_fill_2nd_direct_skip_2nd_indirect_start_block_add_skipped(fapl, &cparam, &tparam); + nerrors += test_abs_fill_2nd_direct_fill_direct_skip_3rd_indirect_start_block_add_skipped(fapl, &cparam, &tparam); + nerrors += test_abs_fill_2nd_direct_fill_direct_skip2_3rd_indirect_start_block_add_skipped(fapl, &cparam, &tparam); + nerrors += test_abs_fill_3rd_direct_less_one_fill_direct_wrap_start_block_add_skipped(fapl, &cparam, &tparam); + nerrors += test_abs_fill_1st_row_3rd_direct_fill_2nd_direct_less_one_wrap_start_block_add_skipped(fapl, &cparam, &tparam); + nerrors += test_abs_fill_3rd_direct_fill_direct_skip_start_block_add_skipped(fapl, &cparam, &tparam); + nerrors += test_abs_fill_3rd_direct_fill_2nd_direct_fill_direct_skip_3rd_indirect_start_block_add_skipped(fapl, &cparam, &tparam); + nerrors += test_abs_fill_3rd_direct_fill_2nd_direct_fill_direct_skip_3rd_indirect_two_rows_start_block_add_skipped(fapl, &cparam, &tparam); + nerrors += test_abs_fill_3rd_direct_fill_2nd_direct_fill_direct_skip_3rd_indirect_wrap_start_block_add_skipped(fapl, &cparam, &tparam); + nerrors += test_abs_fill_4th_direct_less_one_fill_2nd_direct_fill_direct_skip_3rd_indirect_wrap_start_block_add_skipped(fapl, &cparam, &tparam); + + /* Additional skipped block insertion tests */ + nerrors += test_abs_skip_direct_skip_indirect_two_rows_add_skipped(fapl, &cparam, &tparam); + } /* end else */ #else /* QAK */ HDfprintf(stderr, "Uncomment tests!\n"); #endif /* QAK */ @@ -10809,9 +13220,9 @@ HDfprintf(stderr, "Uncomment tests!\n"); if (ExpressMode) printf("***Express test mode on. Some tests skipped\n"); else { - nerrors += test_abs_random_managed((hsize_t)(100*1000*1000), fapl, &cparam, &tparam); - nerrors += test_abs_random_pow2_managed((hsize_t)(100*1000*1000), fapl, &cparam, &tparam); - } + nerrors += test_abs_random_managed((hsize_t)(100*1000*1000), fapl, &cparam, &tparam); + nerrors += test_abs_random_pow2_managed((hsize_t)(100*1000*1000), fapl, &cparam, &tparam); + } /* end else */ #else /* QAK */ HDfprintf(stderr, "Uncomment tests!\n"); #endif /* QAK */ @@ -10822,10 +13233,64 @@ HDfprintf(stderr, "Uncomment tests!\n"); /* Simple removal */ #ifndef QAK nerrors += test_abs_remove_bogus(fapl, &cparam, &tparam); + nerrors += test_abs_remove_one(fapl, &cparam, &tparam); + nerrors += test_abs_remove_two(fapl, &cparam, &tparam); + nerrors += test_abs_remove_one_larger(fapl, &cparam, &tparam); + tparam.del_dir = HEAP_DEL_FORWARD; + nerrors += test_abs_remove_two_larger(fapl, &cparam, &tparam); + tparam.del_dir = HEAP_DEL_REVERSE; + nerrors += test_abs_remove_two_larger(fapl, &cparam, &tparam); + tparam.del_dir = HEAP_DEL_FORWARD; + nerrors += test_abs_remove_three_larger(fapl, &cparam, &tparam); + tparam.del_dir = HEAP_DEL_REVERSE; + nerrors += test_abs_remove_three_larger(fapl, &cparam, &tparam); +#else /* QAK */ +HDfprintf(stderr, "Uncomment tests!\n"); +#endif /* QAK */ + +#ifndef QAK +#ifndef QAK + { + fheap_test_del_dir_t del_dir; /* Deletion direction */ + fheap_test_del_drain_t drain_half; /* Deletion draining */ + + /* More complex removals */ + for(drain_half = HEAP_DEL_DRAIN_ALL; drain_half < HEAP_DEL_DRAIN_N; drain_half++) { + tparam.drain_half = drain_half; + for(del_dir = HEAP_DEL_FORWARD; del_dir < HEAP_DEL_NDIRS; del_dir++) { + tparam.del_dir = del_dir; +#else /* QAK */ +HDfprintf(stderr, "Uncomment test loops!\n"); +tparam.drain_half = HEAP_DEL_DRAIN_ALL; +/* tparam.drain_half = HEAP_DEL_DRAIN_HALF; */ +tparam.del_dir = HEAP_DEL_REVERSE; +#endif /* QAK */ + +#ifndef QAK +#ifndef QAK2 + nerrors += test_abs_remove_root_direct(fapl, &cparam, &tparam); + nerrors += test_abs_remove_two_direct(fapl, &cparam, &tparam); + nerrors += test_abs_remove_first_row(fapl, &cparam, &tparam); + nerrors += test_abs_remove_first_two_rows(fapl, &cparam, &tparam); + nerrors += test_abs_remove_first_four_rows(fapl, &cparam, &tparam); + nerrors += test_abs_remove_all_root_direct(fapl, &cparam, &tparam); +#else /* QAK2 */ +HDfprintf(stderr, "Uncomment tests!\n"); +#endif /* QAK2 */ +#ifdef NOT_YET + nerrors += test_abs_remove_2nd_indirect(fapl, &cparam, &tparam); +#endif /* NOT_YET */ +#else /* QAK */ +HDfprintf(stderr, "Uncomment tests!\n"); +#endif /* QAK */ +#ifndef QAK + } /* end for */ + } /* end for */ + } /* end block */ +#endif /* QAK */ #else /* QAK */ HDfprintf(stderr, "Uncomment tests!\n"); #endif /* QAK */ - nerrors += test_abs_remove_one(fapl, &cparam, &tparam); #ifndef QAK } /* end for */ #endif /* QAK */ @@ -10833,16 +13298,31 @@ HDfprintf(stderr, "Uncomment tests!\n"); if(nerrors) goto error; puts("All fractal heap tests passed."); + + /* Release space for the shared objects */ + H5MM_xfree(shared_wobj_g); + H5MM_xfree(shared_robj_g); + H5MM_xfree(shared_ids_g); + H5MM_xfree(shared_lens_g); + H5MM_xfree(shared_offs_g); + + /* Clean up file used */ #ifndef QAK h5_cleanup(FILENAME, fapl); #else /* QAK */ HDfprintf(stderr, "Uncomment cleanup!\n"); #endif /* QAK */ + return 0; error: puts("*** TESTS FAILED ***"); H5E_BEGIN_TRY { + H5MM_xfree(shared_wobj_g); + H5MM_xfree(shared_robj_g); + H5MM_xfree(shared_ids_g); + H5MM_xfree(shared_lens_g); + H5MM_xfree(shared_offs_g); H5Pclose(fapl); } H5E_END_TRY; return 1; |