diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/H5FS.c | 897 | ||||
-rw-r--r-- | src/H5FScache.c | 20 | ||||
-rw-r--r-- | src/H5FSdbg.c | 10 | ||||
-rw-r--r-- | src/H5FSpkg.h | 19 | ||||
-rw-r--r-- | src/H5FSprivate.h | 35 | ||||
-rw-r--r-- | src/H5Gdeprec.c | 1 | ||||
-rw-r--r-- | src/H5HFdbg.c | 10 | ||||
-rw-r--r-- | src/H5HFdblock.c | 23 | ||||
-rw-r--r-- | src/H5HFdtable.c | 13 | ||||
-rw-r--r-- | src/H5HFhdr.c | 203 | ||||
-rw-r--r-- | src/H5HFiblock.c | 228 | ||||
-rw-r--r-- | src/H5HFint.c | 53 | ||||
-rw-r--r-- | src/H5HFpkg.h | 87 | ||||
-rw-r--r-- | src/H5HFsection.c | 3442 | ||||
-rw-r--r-- | src/H5HFspace.c | 90 | ||||
-rw-r--r-- | src/H5HFtest.c | 2 |
16 files changed, 3871 insertions, 1262 deletions
@@ -12,7 +12,8 @@ * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> +/* + * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> * Tuesday, May 2, 2006 * * Purpose: Free space tracking functions. @@ -61,6 +62,9 @@ + H5F_SIZEOF_ADDR(f) /* Address of free space header for these sections */ \ ) +/* Uncomment this macro to enable extra sanity checking */ +/* #define H5FS_DEBUG */ + /******************/ /* Local Typedefs */ /******************/ @@ -68,6 +72,8 @@ /* Free space node for free space sections of the same size */ typedef struct H5FS_node_t { hsize_t sect_size; /* Size of all sections on list */ + size_t serial_count; /* # of serializable sections on list */ + size_t ghost_count; /* # of un-serializable sections on list */ H5SL_t *sect_list; /* Skip list to hold pointers to actual free list section node */ } H5FS_node_t; @@ -105,8 +111,24 @@ 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(H5FS_t *fspace); -static herr_t H5FS_sect_decrease(H5FS_t *fspace); +static herr_t H5FS_sect_increase(H5FS_t *fspace, const H5FS_section_class_t *cls); +static herr_t H5FS_sect_decrease(H5FS_t *fspace, const H5FS_section_class_t *cls); +static herr_t H5FS_size_node_decr(H5FS_t *fspace, unsigned bin, H5FS_node_t *fspace_node, + const H5FS_section_class_t *cls); +static herr_t H5FS_sect_unlink_size(H5FS_t *fspace, const H5FS_section_class_t *cls, + H5FS_section_info_t *sect); +static herr_t H5FS_sect_unlink_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, + const H5FS_section_class_t *cls, H5FS_section_info_t *sect); +static herr_t H5FS_sect_unlink(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, + H5FS_section_info_t *sect); +static herr_t H5FS_sect_link_size_bin(H5FS_t *fspace, const H5FS_section_class_t *cls, + H5FS_section_info_t *sect); +static herr_t H5FS_sect_link_size(H5FS_t *fspace, const H5FS_section_class_t *cls, + H5FS_section_info_t *sect); +static herr_t H5FS_sect_link_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, + const H5FS_section_class_t *cls, H5FS_section_info_t *sect); +static herr_t H5FS_sect_link(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, + H5FS_section_info_t *sect); 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); @@ -114,6 +136,9 @@ static size_t H5FS_serialize_size(H5FS_t *fspace); static herr_t H5FS_serialize_bins(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace); static herr_t H5FS_deserialize_bins(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace); static herr_t H5FS_flush_cb(void *_item, void *key, void *_udata); +#ifdef H5FS_DEBUG +herr_t H5FS_assert(const H5FS_t *fspace); +#endif /* H5FS_DEBUG */ /*********************/ @@ -316,7 +341,7 @@ H5FS_init(H5FS_t *fspace) fspace->bins = NULL; fspace->merge_list = NULL; fspace->serial_size = 0; - fspace->size_count = 0; + fspace->tot_size_count = fspace->serial_size_count = fspace->ghost_size_count = 0; FUNC_LEAVE_NOAPI(SUCCEED) } /* H5FS_init() */ @@ -338,7 +363,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, const H5FS_section_class_t *classes[], const void *cls_init_udata) + size_t nclasses, const H5FS_section_class_t *classes[], void *cls_init_udata) { H5FS_t *fspace = NULL; /* New free space structure */ H5FS_hdr_t *fs_hdr = NULL; /* New free space header */ @@ -390,7 +415,7 @@ H5FS_create(H5F_t *f, hid_t dxpl_id, haddr_t *fs_addr, const H5FS_create_t *fs_c /* Initialize information for header */ fs_hdr->tot_space = 0; - fs_hdr->sect_count = 0; + fs_hdr->tot_sect_count = fs_hdr->serial_sect_count = fs_hdr->ghost_sect_count = 0; fs_hdr->nclasses = nclasses; fs_hdr->client = fs_create->client; fs_hdr->shrink_percent = fs_create->shrink_percent; @@ -439,6 +464,9 @@ HDfprintf(stderr, "%s: fspace->hdr->sect_size = %Hu\n", FUNC, fspace->hdr->sect_ /* Flag the free space as dirty */ fspace->dirty = TRUE; + /* Reset flag for deserializing the sections */ + fspace->must_deserialize = FALSE; + /* Add the free space manager to the list of open free space managers */ if(H5FS_open_add(fspace) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, NULL, "can't add free space header to open list") @@ -473,7 +501,7 @@ done: */ H5FS_t * H5FS_open(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr, size_t nclasses, - const H5FS_section_class_t *classes[], const void *cls_init_udata) + const H5FS_section_class_t *classes[], void *cls_init_udata) { H5FS_hdr_t *fs_hdr = NULL; /* Free space header loaded from file */ H5FS_t *fspace = NULL; /* New free space structure */ @@ -499,6 +527,11 @@ HDfprintf(stderr, "%s: Opening free space manager\n", FUNC); /* Point free space wrapper at header and pin it in the cache */ fspace->hdr = fs_hdr; +#ifdef QAK +HDfprintf(stderr, "%s: fspace->hdr->tot_sect_count = %Hu\n", FUNC, fspace->hdr->tot_sect_count); +HDfprintf(stderr, "%s: fspace->hdr->serial_sect_count = %Hu\n", FUNC, fspace->hdr->serial_sect_count); +HDfprintf(stderr, "%s: fspace->hdr->ghost_sect_count = %Hu\n", FUNC, fspace->hdr->ghost_sect_count); +#endif /* QAK */ if(H5AC_pin_protected_entry(f, fs_hdr) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTPIN, NULL, "unable to pin free space header") @@ -541,16 +574,17 @@ HDfprintf(stderr, "%s: fspace->sect_off_size = %u, fspace->sect_len_size = %u\n" /* The free space is clean, currently */ fspace->dirty = FALSE; - /* Go get all the sections, if there are any */ + /* Set flag for delayed deserialization appropriately */ #ifdef QAK HDfprintf(stderr, "%s: fspace->hdr->sect_addr = %a\n", FUNC, fspace->hdr->sect_addr); #endif /* QAK */ - if(fspace->hdr->sect_count > 0) { + if(fspace->hdr->serial_sect_count > 0) { HDassert(H5F_addr_defined(fspace->hdr->sect_addr)); HDassert(fspace->hdr->sect_size > 0); - if(H5FS_deserialize_bins(f, dxpl_id, fspace) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTDECODE, NULL, "can't deserialize sections") + fspace->must_deserialize = TRUE; } /* end if */ + else + fspace->must_deserialize = FALSE; /* Add the free space manager to the list of open free space managers */ if(H5FS_open_add(fspace) < 0) @@ -586,19 +620,27 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5FS_sect_increase(H5FS_t *fspace) +H5FS_sect_increase(H5FS_t *fspace, const H5FS_section_class_t *cls) { FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_sect_increase) /* Check arguments. */ HDassert(fspace); HDassert(fspace->hdr); + HDassert(cls); - /* Increment # of sections on free space list */ - fspace->hdr->sect_count++; + /* Increment total # of sections on free space list */ + fspace->hdr->tot_sect_count++; - /* Update the free space sections' serialized size */ - fspace->hdr->sect_size = H5FS_serialize_size(fspace); + /* Check for serializable or 'ghost' section */ + if(cls->flags & H5FS_CLS_GHOST_OBJ) + fspace->hdr->ghost_sect_count++; + else { + fspace->hdr->serial_sect_count++; + + /* Update the free space sections' serialized size */ + fspace->hdr->sect_size = H5FS_serialize_size(fspace); + } /* end else */ FUNC_LEAVE_NOAPI(SUCCEED) } /* H5FS_sect_increase() */ @@ -620,7 +662,7 @@ H5FS_sect_increase(H5FS_t *fspace) *------------------------------------------------------------------------- */ static herr_t -H5FS_sect_decrease(H5FS_t *fspace) +H5FS_sect_decrease(H5FS_t *fspace, const H5FS_section_class_t *cls) { herr_t ret_value = SUCCEED; /* Return value */ @@ -629,67 +671,82 @@ H5FS_sect_decrease(H5FS_t *fspace) /* Check arguments. */ HDassert(fspace); HDassert(fspace->hdr); + HDassert(cls); /* Decrement total # of sections in free space manager */ - fspace->hdr->sect_count--; - - /* Drop back to using a "single" node when there's only one section */ - if(fspace->hdr->sect_count == 1) { - H5FS_node_t *fspace_node; /* Free list size node */ - H5FS_section_info_t *sect; /* Section to move to 'single' info */ - unsigned bin; /* Bin with node */ - unsigned u; /* Local index variable */ - - /* Sanity check */ - HDassert(fspace->single == NULL); - HDassert(fspace->size_count == 1); - - /* Search for the bin with the node */ - for(u = 0; u < fspace->nbins; u++) - if(fspace->bins[u].sect_count) { - HDassert(fspace->bins[u].sect_count == 1); - bin = u; - break; - } /* end if */ - + fspace->hdr->tot_sect_count--; + if(cls->flags & H5FS_CLS_GHOST_OBJ) + fspace->hdr->ghost_sect_count--; + else + fspace->hdr->serial_sect_count--; + + /* Check for sections to manage */ + if(fspace->hdr->tot_sect_count > 0) { + /* Drop back to using a "single" node when there's only one section */ + if(fspace->hdr->tot_sect_count == 1) { + H5FS_node_t *fspace_node; /* Free list size node */ + H5FS_section_info_t *sect; /* Section to move to 'single' info */ + unsigned bin; /* Bin with node */ + unsigned u; /* Local index variable */ + + /* Sanity check */ + HDassert(fspace->single == NULL); + HDassert(fspace->tot_size_count == 1); + + /* Search for the bin with the node */ + for(u = 0; u < fspace->nbins; u++) + if(fspace->bins[u].tot_sect_count) { + /* Sanity check section size count for bin */ + HDassert(H5SL_count(fspace->bins[u].bin_list) == 1); + HDassert(fspace->bins[u].tot_sect_count == 1); + HDassert((fspace->bins[u].serial_sect_count + + fspace->bins[u].ghost_sect_count) == 1); + + /* Save bin index & get out */ + bin = u; + break; + } /* end if */ #ifndef NDEBUG - /* Sanity check rest of bins */ - for(u++ ; u < fspace->nbins; u++) - HDassert(fspace->bins[u].sect_count == 0); + /* Sanity check rest of bins */ + for(u++; u < fspace->nbins; u++) { + HDassert(fspace->bins[u].tot_sect_count == 0); + HDassert(fspace->bins[u].serial_sect_count == 0); + HDassert(fspace->bins[u].ghost_sect_count == 0); + } /* end for */ #endif /* NDEBUG */ - /* Sanity check section size count for bin */ - HDassert(H5SL_count(fspace->bins[bin].bin_list) == 1); - HDassert(fspace->bins[bin].sect_count == 1); + /* Remove the free space section size node from the bin list */ + if(NULL == (fspace_node = H5SL_remove_first(fspace->bins[bin].bin_list))) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space section size node from skip list") - /* Remove the free space section size node from the bin list */ - if(NULL == (fspace_node = H5SL_remove_first(fspace->bins[bin].bin_list))) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space section size node from skip list") + /* Decrement # of section sizes in bin */ + fspace->bins[bin].tot_sect_count = 0; + fspace->bins[bin].serial_sect_count = 0; + fspace->bins[bin].ghost_sect_count = 0; - /* Decrement # of section sizes in bin */ - fspace->bins[bin].sect_count = 0; + /* Make certain there's only one section of this size */ + HDassert(H5SL_count(fspace_node->sect_list) == 1); + HDassert((fspace_node->serial_count + fspace_node->ghost_count) == 1); - /* Make certain there's only one section of this size */ - HDassert(H5SL_count(fspace_node->sect_list) == 1); + /* Remove the free space section from the section size list */ + if(NULL == (sect = H5SL_remove_first(fspace_node->sect_list))) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space section from skip list") - /* Remove the free space section from the section size list */ - if(NULL == (sect = H5SL_remove_first(fspace_node->sect_list))) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space section from skip list") + /* Destroy skip list for size tracking node */ + if(H5SL_close(fspace_node->sect_list) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTCLOSEOBJ, FAIL, "can't destroy size tracking node's skip list") - /* Destroy skip list for size tracking node */ - if(H5SL_close(fspace_node->sect_list) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTCLOSEOBJ, FAIL, "can't destroy size tracking node's skip list") + /* Release free space list node */ + H5FL_FREE(H5FS_node_t, fspace_node); - /* Release free space list node */ - H5FL_FREE(H5FS_node_t, fspace_node); + /* Capture single section's information */ + fspace->single = sect; + } /* end if */ - /* Capture single section's information */ - fspace->single = sect; + /* Update the free space sections' serialized size */ + if(!(cls->flags & H5FS_CLS_GHOST_OBJ)) + fspace->hdr->sect_size = H5FS_serialize_size(fspace); } /* end if */ - - /* Update the free space sections' serialized size */ - if(fspace->hdr->sect_count > 0) - fspace->hdr->sect_size = H5FS_serialize_size(fspace); else fspace->hdr->sect_size = 0; @@ -714,7 +771,8 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5FS_size_node_decr(H5FS_t *fspace, H5FS_node_t *fspace_node, unsigned bin) +H5FS_size_node_decr(H5FS_t *fspace, unsigned bin, H5FS_node_t *fspace_node, + const H5FS_section_class_t *cls) { herr_t ret_value = SUCCEED; /* Return value */ @@ -723,11 +781,49 @@ H5FS_size_node_decr(H5FS_t *fspace, H5FS_node_t *fspace_node, unsigned bin) /* Check arguments. */ HDassert(fspace); HDassert(fspace_node); + HDassert(cls); + + /* Decrement the # of sections in this bin */ + /* (Different from the # of items in the bin's skiplist, since each node on + * the bin's skiplist is also a skiplist...) + */ + fspace->bins[bin].tot_sect_count--; +#ifdef QAK +HDfprintf(stderr, "%s: fspace->bins[%u].sect_count = %Zu\n", FUNC, bin, fspace->bins[bin].sect_count); +#endif /* QAK */ + + /* Check for 'ghost' or 'serializable' section */ + if(cls->flags & H5FS_CLS_GHOST_OBJ) { + /* Decrement node's ghost section count */ + fspace_node->ghost_count--; + + /* Decrement bin's ghost section count */ + fspace->bins[bin].ghost_sect_count--; + + /* If the node has no more ghost sections, decrement number of ghost section sizes managed */ + if(fspace_node->ghost_count == 0) + fspace->ghost_size_count--; + } /* end if */ + else { + /* Decrement node's serializable section count */ + fspace_node->serial_count--; + + /* Decrement bin's serializable section count */ + fspace->bins[bin].serial_sect_count--; + + /* If the node has no more serializable sections, decrement number of serializable section sizes managed */ + if(fspace_node->serial_count == 0) + fspace->serial_size_count--; + } /* end else */ /* Check for no more nodes on list of that size */ if(H5SL_count(fspace_node->sect_list) == 0) { H5FS_node_t *tmp_fspace_node; /* Free space list size node */ + /* Sanity checks */ + HDassert(fspace_node->ghost_count == 0); + HDassert(fspace_node->serial_count == 0); + /* Remove size tracking list from bin */ tmp_fspace_node = H5SL_remove(fspace->bins[bin].bin_list, &fspace_node->sect_size); if(tmp_fspace_node == NULL || tmp_fspace_node != fspace_node) @@ -740,19 +836,10 @@ H5FS_size_node_decr(H5FS_t *fspace, H5FS_node_t *fspace_node, unsigned bin) /* Release free space list node */ H5FL_FREE(H5FS_node_t, fspace_node); - /* Decrement number of section sizes */ - fspace->size_count--; + /* Decrement total number of section sizes managed */ + fspace->tot_size_count--; } /* end if */ - /* Decrement the # of sections in this bin */ - /* (Different from the # of items in the bin's skiplist, since each node on - * the bin's skiplist is also a skiplist...) - */ - fspace->bins[bin].sect_count--; -#ifdef QAK -HDfprintf(stderr, "%s: fspace->bins[%u].sect_count = %Zu\n", FUNC, bin, fspace->bins[bin].sect_count); -#endif /* QAK */ - done: FUNC_LEAVE_NOAPI(ret_value) } /* H5FS_size_node_decr() */ @@ -774,7 +861,8 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5FS_sect_unlink_size(H5FS_t *fspace, H5FS_section_info_t *sect) +H5FS_sect_unlink_size(H5FS_t *fspace, const H5FS_section_class_t *cls, + H5FS_section_info_t *sect) { herr_t ret_value = SUCCEED; /* Return value */ @@ -783,6 +871,7 @@ H5FS_sect_unlink_size(H5FS_t *fspace, H5FS_section_info_t *sect) /* Check arguments. */ HDassert(fspace); HDassert(sect); + HDassert(cls); /* Check for only a single section */ if(fspace->single) { @@ -793,8 +882,8 @@ H5FS_sect_unlink_size(H5FS_t *fspace, H5FS_section_info_t *sect) /* Reset 'single' section pointer */ fspace->single = NULL; - /* Decrement number of section sizes */ - fspace->size_count--; + /* Reset number of section sizes */ + fspace->tot_size_count = fspace->serial_size_count = fspace->ghost_size_count = 0; } /* end if */ else { H5FS_node_t *fspace_node; /* Free list size node */ @@ -820,7 +909,7 @@ H5FS_sect_unlink_size(H5FS_t *fspace, H5FS_section_info_t *sect) HGOTO_ERROR(H5E_FSPACE, H5E_NOTFOUND, FAIL, "can't find section node on size list") /* Decrement # of sections in section size node */ - if(H5FS_size_node_decr(fspace, fspace_node, bin) < 0) + if(H5FS_size_node_decr(fspace, bin, fspace_node, cls) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space size node from skip list") } /* end else */ @@ -846,7 +935,8 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5FS_sect_unlink_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *sect) +H5FS_sect_unlink_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, + const H5FS_section_class_t *cls, H5FS_section_info_t *sect) { H5FS_section_info_t *tmp_sect_node; /* Temporary section node */ herr_t ret_value = SUCCEED; /* Return value */ @@ -856,6 +946,7 @@ H5FS_sect_unlink_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info /* Check arguments. */ HDassert(f); HDassert(fspace); + HDassert(cls); HDassert(sect); /* Remove node from merge list */ @@ -872,7 +963,7 @@ HDfprintf(stderr, "%s: fspace->sect_cls[%u].serial_size = %Zu\n", FUNC, sect->ty #endif /* QAK */ /* Update section info & check if we need less room for the serialized free space sections */ - if(H5FS_sect_decrease(fspace) < 0) + if(H5FS_sect_decrease(fspace, cls) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't increase free space section size on disk") /* Decrement amount of free space managed */ @@ -903,6 +994,7 @@ done: static herr_t H5FS_sect_unlink(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *sect) { + const H5FS_section_class_t *cls; /* Class of section */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_unlink) @@ -912,12 +1004,15 @@ H5FS_sect_unlink(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *s HDassert(fspace); HDassert(sect); + /* Get section's class */ + cls = &fspace->sect_cls[sect->type]; + /* Remove node from size tracked data structures */ - if(H5FS_sect_unlink_size(fspace, sect) < 0) + if(H5FS_sect_unlink_size(fspace, cls, sect) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't remove section from size tracking data structures") /* Update rest of free space manager data structures for node removal */ - if(H5FS_sect_unlink_rest(f, dxpl_id, fspace, sect) < 0) + if(H5FS_sect_unlink_rest(f, dxpl_id, fspace, cls, sect) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't remove section from non-size tracking data structures") done: @@ -940,7 +1035,8 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5FS_sect_link_size_bin(H5FS_t *fspace, H5FS_section_info_t *sect) +H5FS_sect_link_size_bin(H5FS_t *fspace, const H5FS_section_class_t *cls, + H5FS_section_info_t *sect) { H5FS_node_t *fspace_node = NULL; /* Pointer to free space node of the correct size */ unsigned bin; /* Bin to put the free space section in */ @@ -977,6 +1073,7 @@ HDfprintf(stderr, "%s: sect->size = %Hu, sect->addr = %a\n", FUNC, sect->size, s /* Initialize the free list size node */ fspace_node->sect_size = sect->size; + fspace_node->serial_count = fspace_node->ghost_count = 0; if(NULL == (fspace_node->sect_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 free space nodes") @@ -985,7 +1082,7 @@ HDfprintf(stderr, "%s: sect->size = %Hu, sect->addr = %a\n", FUNC, sect->size, s HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space node into skip list") /* Increment number of section sizes */ - fspace->size_count++; + fspace->tot_size_count++; } /* end if */ /* Increment # of section in bin */ @@ -995,7 +1092,23 @@ HDfprintf(stderr, "%s: sect->size = %Hu, sect->addr = %a\n", FUNC, sect->size, s #ifdef QAK HDfprintf(stderr, "%s: fspace->bins[%u].sect_count = %Zu\n", FUNC, bin, fspace->bins[bin].sect_count); #endif /* QAK */ - fspace->bins[bin].sect_count++; + fspace->bins[bin].tot_sect_count++; + if(cls->flags & H5FS_CLS_GHOST_OBJ) { + fspace->bins[bin].ghost_sect_count++; + fspace_node->ghost_count++; + + /* Check for first ghost section in node */ + if(fspace_node->ghost_count == 1) + fspace->ghost_size_count++; + } /* end if */ + else { + fspace->bins[bin].serial_sect_count++; + fspace_node->serial_count++; + + /* Check for first serializable section in node */ + if(fspace_node->serial_count == 1) + fspace->serial_size_count++; + } /* end else */ /* Insert free space node into correct skip list */ if(H5SL_insert(fspace_node->sect_list, sect, §->addr) < 0) @@ -1021,7 +1134,8 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5FS_sect_link_size(H5FS_t *fspace, H5FS_section_info_t *sect) +H5FS_sect_link_size(H5FS_t *fspace, const H5FS_section_class_t *cls, + H5FS_section_info_t *sect) { herr_t ret_value = SUCCEED; /* Return value */ @@ -1033,43 +1147,73 @@ H5FS_sect_link_size(H5FS_t *fspace, H5FS_section_info_t *sect) /* Check for special cases of # of sections on free list */ #ifdef QAK -HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect_count); +HDfprintf(stderr, "%s: fspace->tot_size_count = %Zu\n", FUNC, fspace->tot_size_count); +HDfprintf(stderr, "%s: fspace->serial_size_count = %Zu\n", FUNC, fspace->serial_size_count); +HDfprintf(stderr, "%s: fspace->ghost_size_count = %Zu\n", FUNC, fspace->ghost_size_count); #endif /* QAK */ - if(fspace->hdr->sect_count == 0) { + if(fspace->hdr->tot_sect_count == 0) { HDassert(fspace->single == NULL); /* Capture single section's information */ fspace->single = sect; /* Increment number of section sizes */ - fspace->size_count++; + HDassert(fspace->tot_size_count == 0); + HDassert(fspace->serial_size_count == 0); + HDassert(fspace->ghost_size_count == 0); + fspace->tot_size_count = 1; + if(cls->flags & H5FS_CLS_GHOST_OBJ) + fspace->ghost_size_count = 1; + else + fspace->serial_size_count = 1; } /* end if */ else { /* Have a single section, put it into the bins */ if(fspace->single) { + const H5FS_section_class_t *single_cls; /* Single section's class */ + /* Check if we should allocate the bins */ if(fspace->bins == NULL) /* Allocate the bins for free space sizes */ if(NULL == (fspace->bins = H5FL_SEQ_CALLOC(H5FS_bin_t, fspace->nbins))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for free space bins") + /* Get single section's class */ + single_cls = &fspace->sect_cls[fspace->single->type]; + /* Insert the current single section into the bins */ - if(H5FS_sect_link_size_bin(fspace, fspace->single) < 0) + if(H5FS_sect_link_size_bin(fspace, single_cls, fspace->single) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space node into skip list") fspace->single = NULL; /* Decrement number of section sizes */ /* (from increment in H5FS_sect_link_size_bin for inserting the single section) */ - fspace->size_count--; + fspace->tot_size_count--; + if(single_cls->flags & H5FS_CLS_GHOST_OBJ) + fspace->ghost_size_count--; + else + fspace->serial_size_count--; +#ifdef QAK +HDfprintf(stderr, "%s: After adjusting single section\n", FUNC); +HDfprintf(stderr, "%s: fspace->tot_size_count = %Zu\n", FUNC, fspace->tot_size_count); +HDfprintf(stderr, "%s: fspace->serial_size_count = %Zu\n", FUNC, fspace->serial_size_count); +HDfprintf(stderr, "%s: fspace->ghost_size_count = %Zu\n", FUNC, fspace->ghost_size_count); +#endif /* QAK */ } /* end if */ HDassert(fspace->single == NULL); /* Put new section into bins */ - if(H5FS_sect_link_size_bin(fspace, sect) < 0) + if(H5FS_sect_link_size_bin(fspace, cls, sect) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space node into skip list") } /* end else */ done: +#ifdef QAK +HDfprintf(stderr, "%s: Leaving\n", FUNC); +HDfprintf(stderr, "%s: fspace->tot_size_count = %Zu\n", FUNC, fspace->tot_size_count); +HDfprintf(stderr, "%s: fspace->serial_size_count = %Zu\n", FUNC, fspace->serial_size_count); +HDfprintf(stderr, "%s: fspace->ghost_size_count = %Zu\n", FUNC, fspace->ghost_size_count); +#endif /* QAK */ FUNC_LEAVE_NOAPI(ret_value) } /* H5FS_sect_link_size() */ @@ -1090,7 +1234,8 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5FS_sect_link_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *sect) +H5FS_sect_link_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, const H5FS_section_class_t *cls, + H5FS_section_info_t *sect) { herr_t ret_value = SUCCEED; /* Return value */ @@ -1111,12 +1256,12 @@ H5FS_sect_link_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t /* Increment amount of space required to serialize all sections */ #ifdef QAK 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); +HDfprintf(stderr, "%s: cls->serial_size = %Zu\n", FUNC, cls->serial_size); #endif /* QAK */ - fspace->serial_size += fspace->sect_cls[sect->type].serial_size; + fspace->serial_size += cls->serial_size; /* Update section info & check if we need more room for the serialized free space sections */ - if(H5FS_sect_increase(fspace) < 0) + if(H5FS_sect_increase(fspace, cls) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't increase free space section size on disk") /* Increment amount of free space managed */ @@ -1142,8 +1287,10 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5FS_sect_link(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *sect) +H5FS_sect_link(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, + H5FS_section_info_t *sect) { + const H5FS_section_class_t *cls; /* Class of section */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_link) @@ -1153,18 +1300,21 @@ H5FS_sect_link(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *sec HDassert(fspace); HDassert(sect); + /* Get section's class */ + cls = &fspace->sect_cls[sect->type]; + /* 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) + if(H5FS_sect_link_size(fspace, cls, 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) + if(H5FS_sect_link_rest(f, dxpl_id, fspace, cls, 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); @@ -1280,6 +1430,9 @@ H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, } /* end if */ } while(merged); HDassert(*sect); +#ifdef QAK +HDfprintf(stderr, "%s: Done merging, (*sect) = {%a, %Hu, %u, %s}\n", FUNC, (*sect)->addr, (*sect)->size, (*sect)->type, ((*sect)->state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED")); +#endif /* QAK */ /* Check for (possibly merged) section able to shrink the size of the container */ sect_cls = &fspace->sect_cls[(*sect)->type]; @@ -1301,6 +1454,9 @@ HDfprintf(stderr, "%s: Can shrink!\n", FUNC); } /* end if */ done: +#ifdef QAK +HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value); +#endif /* QAK */ FUNC_LEAVE_NOAPI(ret_value) } /* H5FS_sect_merge() */ @@ -1337,8 +1493,15 @@ HDfprintf(stderr, "%s: sect->size = %Hu, sect->addr = %a, sect->type = %u\n", FU HDassert(H5F_addr_defined(sect->addr)); HDassert(sect->size); + /* Check if we need to go deserialize the sections */ + if(fspace->must_deserialize) { + fspace->must_deserialize = FALSE; + if(H5FS_deserialize_bins(f, dxpl_id, fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTDECODE, FAIL, "can't deserialize sections") + } /* end if */ + /* Check for merging returned space with existing section node */ - if(flags & H5FS_ADD_RETURNED_SPACE && fspace->hdr->sect_count > 0) { + if((flags & H5FS_ADD_RETURNED_SPACE) && fspace->hdr->tot_sect_count > 0) { #ifdef QAK HDfprintf(stderr, "%s: Returning space\n", FUNC); #endif /* QAK */ @@ -1365,6 +1528,10 @@ HDfprintf(stderr, "%s: fspace->hdr->tot_space = %Hu\n", FUNC, fspace->hdr->tot_s fspace->dirty = TRUE; done: +#ifdef H5FS_DEBUG +if(!(flags & H5FS_ADD_DESERIALIZING)) + H5FS_assert(fspace); +#endif /* H5FS_DEBUG */ FUNC_LEAVE_NOAPI(ret_value) } /* H5FS_add() */ @@ -1419,12 +1586,17 @@ HDfprintf(stderr, "%s: bin = %u\n", FUNC, bin); if(fspace->bins[bin].bin_list) /* Check for large enough list of sections on list */ if((fspace_node = H5SL_greater(fspace->bins[bin].bin_list, &request))) { + const H5FS_section_class_t *cls; /* Class of section */ + /* Take first node off of the list (ie. node w/lowest address) */ if(NULL == (*node = H5SL_remove_first(fspace_node->sect_list))) HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space node from skip list") + /* Get section's class */ + cls = &fspace->sect_cls[(*node)->type]; + /* Decrement # of sections in section size node */ - if(H5FS_size_node_decr(fspace, fspace_node, bin) < 0) + if(H5FS_size_node_decr(fspace, bin, fspace_node, cls) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space size node from skip list") /* Indicate that we found a node for the request */ @@ -1471,11 +1643,20 @@ HDfprintf(stderr, "%s: request = %Hu\n", FUNC, request); HDassert(request); HDassert(node); + /* Check if we need to go deserialize the sections */ + if(fspace->must_deserialize) { + fspace->must_deserialize = FALSE; + if(H5FS_deserialize_bins(f, dxpl_id, fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTDECODE, FAIL, "can't deserialize sections") + } /* end if */ + /* Check for any sections on free space list */ #ifdef QAK -HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect_count); +HDfprintf(stderr, "%s: fspace->hdr->tot_sect_count = %Hu\n", FUNC, fspace->hdr->tot_sect_count); +HDfprintf(stderr, "%s: fspace->hdr->serial_sect_count = %Hu\n", FUNC, fspace->hdr->serial_sect_count); +HDfprintf(stderr, "%s: fspace->hdr->ghost_sect_count = %Hu\n", FUNC, fspace->hdr->ghost_sect_count); #endif /* QAK */ - if(fspace->hdr->sect_count > 0) { + if(fspace->hdr->tot_sect_count > 0) { /* Check for single section */ if(fspace->single) { /* See if single section is large enough */ @@ -1485,7 +1666,8 @@ HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect fspace->single = NULL; /* Decrement number of section sizes */ - fspace->size_count--; + fspace->tot_size_count = 0; + fspace->serial_size_count = fspace->ghost_size_count = 0; /* Found a good section */ ret_value = TRUE; @@ -1501,16 +1683,24 @@ HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect /* Decrement # of sections on free list, if we found an object */ if(ret_value > 0) { + const H5FS_section_class_t *cls; /* Class of section */ + + /* Get section's class */ + cls = &fspace->sect_cls[(*node)->type]; + /* Update rest of free space manager data structures for node removal */ - if(H5FS_sect_unlink_rest(f, dxpl_id, fspace, *node) < 0) + if(H5FS_sect_unlink_rest(f, dxpl_id, fspace, cls, *node) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't remove section from non-size tracking data structures") #ifdef QAK -HDfprintf(stderr, "%s: (*node)->size = %Hu, (*node)->addr = %a, (*node)->cls->type = %u\n", FUNC, (*node)->size, (*node)->addr, (*node)->cls->type); +HDfprintf(stderr, "%s: (*node)->size = %Hu, (*node)->addr = %a, (*node)->type = %u\n", FUNC, (*node)->size, (*node)->addr, (*node)->type); #endif /* QAK */ } /* end if */ } /* end if */ done: +#ifdef H5FS_DEBUG + H5FS_assert(fspace); +#endif /* H5FS_DEBUG */ FUNC_LEAVE_NOAPI(ret_value) } /* H5FS_find() */ @@ -1611,29 +1801,34 @@ H5FS_serialize_sect_cb(void *_item, void UNUSED *key, void *_udata) HDassert(udata->fspace); HDassert(udata->p); - /* The address of the section */ - UINT64ENCODE_VAR(*udata->p, sect->addr, udata->fspace->sect_off_size); + /* Get section's class */ + sect_cls = &udata->fspace->sect_cls[sect->type]; + + /* Check if this section should be serialized (i.e. is not a ghost section) */ + if(!(sect_cls->flags & H5FS_CLS_GHOST_OBJ)) { + /* The address of the section */ + UINT64ENCODE_VAR(*udata->p, sect->addr, udata->fspace->sect_off_size); #ifdef QAK HDfprintf(stderr, "%s: sect->addr = %a\n", FUNC, sect->addr); #endif /* QAK */ - /* The type of this section */ - *(*udata->p)++ = (uint8_t)sect->type; + /* The type of this section */ + *(*udata->p)++ = (uint8_t)sect->type; #ifdef QAK HDfprintf(stderr, "%s: sect->type = %u\n", FUNC, (unsigned)sect->type); #endif /* QAK */ - /* Call 'serialize' callback for this section */ - 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") + /* Call 'serialize' callback for this section */ + if(sect_cls->serialize) { + if((*sect_cls->serialize)(sect_cls, sect, *udata->p) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTSERIALIZE, FAIL, "can't syncronize section") - /* Update offset in serialization buffer */ - (*udata->p) += sect_cls->serial_size; + /* Update offset in serialization buffer */ + (*udata->p) += sect_cls->serial_size; + } /* end if */ + else + HDassert(sect_cls->serial_size == 0); } /* end if */ - else - HDassert(sect_cls->serial_size == 0); done: FUNC_LEAVE_NOAPI(ret_value) @@ -1660,7 +1855,6 @@ H5FS_serialize_node_cb(void *_item, void UNUSED *key, void *_udata) { H5FS_node_t *fspace_node = (H5FS_node_t *)_item; /* Free space size node to work on */ H5FS_iter_ud2_t *udata = (H5FS_iter_ud2_t *)_udata; /* Callback info */ - size_t node_count; /* Number of sections of this size */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5FS_serialize_node_cb) @@ -1670,24 +1864,25 @@ H5FS_serialize_node_cb(void *_item, void UNUSED *key, void *_udata) HDassert(udata->fspace); HDassert(udata->p); - /* The number of sections of this node's size */ - node_count = H5SL_count(fspace_node->sect_list); - HDassert(node_count); - UINT64ENCODE_VAR(*udata->p, node_count, udata->sect_cnt_size); + /* Check if this node has any serializable sections */ + if(fspace_node->serial_count > 0) { + /* The number of serializable sections of this node's size */ + UINT64ENCODE_VAR(*udata->p, fspace_node->serial_count, udata->sect_cnt_size); #ifdef QAK -HDfprintf(stderr, "%s: node_count = %Zu\n", FUNC, node_count); +HDfprintf(stderr, "%s: fspace_node->serial_count = %Zu\n", FUNC, fspace_node->serial_count); #endif /* QAK */ - /* The size of the sections for this node */ - UINT64ENCODE_VAR(*udata->p, fspace_node->sect_size, udata->fspace->sect_len_size); + /* The size of the sections for this node */ + UINT64ENCODE_VAR(*udata->p, fspace_node->sect_size, udata->fspace->sect_len_size); #ifdef QAK HDfprintf(stderr, "%s: sect_size = %Hu\n", FUNC, fspace_node->sect_size); #endif /* QAK */ - /* Iterate through all the sections of this size */ - HDassert(fspace_node->sect_list); - if(H5SL_iterate(fspace_node->sect_list, H5FS_serialize_sect_cb, udata) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_BADITER, FAIL, "can't iterate over section nodes") + /* Iterate through all the sections of this size */ + HDassert(fspace_node->sect_list); + if(H5SL_iterate(fspace_node->sect_list, H5FS_serialize_sect_cb, udata) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_BADITER, FAIL, "can't iterate over section nodes") + } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) @@ -1723,17 +1918,21 @@ H5FS_serialize_size(H5FS_t *fspace) /* Serialized sections prefix */ sect_buf_size = fspace->sect_prefix_size; - /* Count for each differently sized section */ - sect_buf_size += fspace->size_count * MAX(1, ((H5V_log2_gen(fspace->hdr->sect_count) + 7) / 8)); + /* Count for each differently sized serializable section */ +#ifdef QAK +HDfprintf(stderr, "%s: fspace->serial_size_count = %Zu\n", "H5FS_serialize_size", fspace->serial_size_count); +HDfprintf(stderr, "%s: fspace->hdr->serial_sect_count = %Hu\n", "H5FS_serialize_size", fspace->hdr->serial_sect_count); +#endif /* QAK */ + sect_buf_size += fspace->serial_size_count * MAX(1, ((H5V_log2_gen(fspace->hdr->serial_sect_count) + 7) / 8)); - /* Size for each differently sized section */ - sect_buf_size += fspace->size_count * fspace->sect_len_size; + /* Size for each differently sized serializable section */ + sect_buf_size += fspace->serial_size_count * fspace->sect_len_size; /* Offsets of each section in address space */ - sect_buf_size += fspace->hdr->sect_count * fspace->sect_off_size; + sect_buf_size += fspace->hdr->serial_sect_count * fspace->sect_off_size; /* Class of each section */ - sect_buf_size += fspace->hdr->sect_count * 1; + sect_buf_size += fspace->hdr->serial_sect_count * 1; /* Extra space required to serialize each section */ sect_buf_size += fspace->serial_size; @@ -1774,12 +1973,17 @@ H5FS_serialize_bins(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace) #ifdef QAK HDfprintf(stderr, "%s: fspace->hdr->sect_addr = %a\n", FUNC, fspace->hdr->sect_addr); HDfprintf(stderr, "%s: fspace->hdr->sect_size = %Hu\n", FUNC, fspace->hdr->sect_size); -HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect_count); +HDfprintf(stderr, "%s: fspace->hdr->tot_sect_count = %Hu\n", FUNC, fspace->hdr->tot_sect_count); +HDfprintf(stderr, "%s: fspace->hdr->serial_sect_count = %Hu\n", FUNC, fspace->hdr->serial_sect_count); +HDfprintf(stderr, "%s: fspace->hdr->ghost_sect_count = %Hu\n", FUNC, fspace->hdr->ghost_sect_count); HDfprintf(stderr, "%s: fspace->serial_size = %Zu\n", FUNC, fspace->serial_size); +HDfprintf(stderr, "%s: fspace->single = %p\n", FUNC, fspace->single); +if(fspace->single) + HDfprintf(stderr, "%s: fspace->single = {%a, %Hu, %u, %s}\n", FUNC, fspace->single->addr, fspace->single->size, fspace->single->type, (fspace->single->state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED")); #endif /* QAK */ /* Check for no free sections */ - if(fspace->hdr->sect_count == 0) { + if(fspace->hdr->serial_sect_count == 0) { /* Check for existing serialized sections on disk to release */ if(H5F_addr_defined(fspace->hdr->sect_addr)) { /* Free previous serialized sections disk space */ @@ -1802,9 +2006,9 @@ HDfprintf(stderr, "%s: Releasing space for serialized sections\n", FUNC); /* Allocate space for the new serialized sections on disk */ #ifdef QAK -HDfprintf(stderr, "%s: Allocating space for serialized sections\n", FUNC); +HDfprintf(stderr, "%s: Allocating space for serialized sections, fspace->hdr->alloc_sect_size = %Hu\n", FUNC, fspace->hdr->alloc_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))) + if(HADDR_UNDEF == (fspace->hdr->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SECTS, dxpl_id, fspace->hdr->alloc_sect_size))) HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections") } /* end if */ else { @@ -1901,11 +2105,11 @@ HDfprintf(stderr, "%s: Allocating space for smaller serialized sections\n", FUNC *p++ = H5FS_SECTS_VERSION; /* Metadata status flags */ - /* XXX: Set this? */ +/* XXX: Set this? */ *p++ = 0; /* Metadata checksum */ - /* XXX: Set this! (After all the metadata is in the buffer) */ +/* XXX: Set this! (After all the metadata is in the buffer) */ HDmemset(p, 0, 4); p += 4; @@ -1915,7 +2119,7 @@ HDfprintf(stderr, "%s: Allocating space for smaller serialized sections\n", FUNC /* Set up user data for iterator */ udata.fspace = fspace; udata.p = &p; - udata.sect_cnt_size = MAX(1, (H5V_log2_gen(fspace->hdr->sect_count) + 7) / 8); + udata.sect_cnt_size = MAX(1, (H5V_log2_gen(fspace->hdr->serial_sect_count) + 7) / 8); #ifdef QAK HDfprintf(stderr, "%s: udata.sect_cnt_size = %u\n", FUNC, udata.sect_cnt_size); #endif /* QAK */ @@ -2052,26 +2256,34 @@ HDfprintf(stderr, "%s: fspace->hdr->sect_size = %Hu\n", FUNC, fspace->hdr->sect_ HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, FAIL, "incorrect header address for free space sections") /* Check for any serialized sections */ - if(fspace->hdr->sect_count > 0) { - hsize_t old_sect_count; /* Section count from header */ + if(fspace->hdr->serial_sect_count > 0) { + hsize_t old_tot_sect_count; /* Total section count from header */ + hsize_t old_serial_sect_count; /* Total serializable section count from header */ + hsize_t old_ghost_sect_count; /* Total ghost 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); + sect_cnt_size = MAX(1, (H5V_log2_gen(fspace->hdr->serial_sect_count) + 7) / 8); #ifdef QAK HDfprintf(stderr, "%s: sect_cnt_size = %u\n", FUNC, sect_cnt_size); HDfprintf(stderr, "%s: fspace->sect_len_size = %u\n", FUNC, fspace->sect_len_size); #endif /* QAK */ /* Reset the section count, the "add" routine will update it */ - old_sect_count = fspace->hdr->sect_count; + old_tot_sect_count = fspace->hdr->tot_sect_count; + old_serial_sect_count = fspace->hdr->serial_sect_count; + old_ghost_sect_count = fspace->hdr->ghost_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_sect_count = %Hu\n", FUNC, fspace->hdr->tot_sect_count); +HDfprintf(stderr, "%s: fspace->hdr->serial_sect_count = %Hu\n", FUNC, fspace->hdr->serial_sect_count); +HDfprintf(stderr, "%s: fspace->hdr->ghost_sect_count = %Hu\n", FUNC, fspace->hdr->ghost_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_sect_count = 0; + fspace->hdr->serial_sect_count = 0; + fspace->hdr->ghost_sect_count = 0; fspace->hdr->tot_space = 0; /* Walk through the buffer, deserializing sections */ @@ -2099,6 +2311,7 @@ HDfprintf(stderr, "%s: sect_size = %Hu\n", FUNC, sect_size); H5FS_section_info_t *new_sect; /* Section that was deserialized */ haddr_t sect_addr; /* Address of free space section in the address space */ unsigned sect_type; /* Type of free space section */ + unsigned des_flags; /* Flags from deserialize callback */ /* The address of the section */ UINT64DECODE_VAR(p, sect_addr, fspace->sect_off_size); @@ -2113,23 +2326,30 @@ HDfprintf(stderr, "%s: sect_type = %u\n", FUNC, sect_type); #endif /* QAK */ /* Call 'deserialize' callback for this section */ + des_flags = 0; HDassert(fspace->sect_cls[sect_type].deserialize); - if(NULL == (new_sect = (*fspace->sect_cls[sect_type].deserialize)(p, sect_addr, sect_size))) + if(NULL == (new_sect = (*fspace->sect_cls[sect_type].deserialize)(&fspace->sect_cls[sect_type], dxpl_id, p, sect_addr, sect_size, &des_flags))) HGOTO_ERROR(H5E_FSPACE, H5E_CANTDECODE, FAIL, "can't deserialize section") /* Update offset in serialization buffer */ p += fspace->sect_cls[sect_type].serial_size; +#ifdef QAK +HDfprintf(stderr, "%s: fspace->sect_cls[%u].serial_size = %Zu\n", FUNC, sect_type, fspace->sect_cls[sect_type].serial_size); +#endif /* QAK */ - /* Insert section in free space manager */ - if(H5FS_add(f, dxpl_id, fspace, new_sect, H5FS_ADD_DESERIALIZING, NULL) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't add section to free space manager") + /* Insert section in free space manager, unless requested not to */ + if(!(des_flags & H5FS_DESERIALIZE_NO_ADD)) + if(H5FS_add(f, dxpl_id, fspace, new_sect, H5FS_ADD_DESERIALIZING, NULL) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't add section to free space manager") } /* end for */ } while(p < (sect_buf + old_sect_size)); /* Sanity check */ 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_sect_count == fspace->hdr->tot_sect_count); + HDassert(old_serial_sect_count == fspace->hdr->serial_sect_count); + HDassert(old_ghost_sect_count == fspace->hdr->ghost_sect_count); HDassert(old_tot_space == fspace->hdr->tot_space); } /* end if */ @@ -2236,7 +2456,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5FS_iterate(H5FS_t *fspace, H5FS_operator_t op, void *op_data) +H5FS_iterate(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_operator_t op, void *op_data) { H5FS_iter_ud3_t udata; /* User data for callbacks */ herr_t ret_value = SUCCEED; /* Return value */ @@ -2247,6 +2467,13 @@ H5FS_iterate(H5FS_t *fspace, H5FS_operator_t op, void *op_data) HDassert(fspace); HDassert(op); + /* Check if we need to go deserialize the sections */ + if(fspace->must_deserialize) { + fspace->must_deserialize = FALSE; + if(H5FS_deserialize_bins(f, dxpl_id, fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTDECODE, FAIL, "can't deserialize sections") + } /* end if */ + #ifdef QAK HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect_count); #endif /* QAK */ @@ -2257,7 +2484,7 @@ HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect udata.op_data = op_data; /* Iterate over sections, if there are any */ - if(fspace->hdr->sect_count) { + if(fspace->hdr->tot_sect_count) { /* Check for whether to iterate over a single section */ if(fspace->single) { #ifdef QAK @@ -2316,7 +2543,7 @@ H5FS_get_sect_count(const H5FS_t *fspace, hsize_t *nsects) HDassert(nsects); /* Get the section count */ - *nsects = fspace->hdr->sect_count; + *nsects = fspace->hdr->tot_sect_count; done: FUNC_LEAVE_NOAPI(ret_value) @@ -2324,6 +2551,152 @@ done: /*------------------------------------------------------------------------- + * Function: H5FS_sect_change_class + * + * Purpose: Make appropriate adjustments to internal data structures when + * a section changes class + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, July 10, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FS_sect_change_class(H5FS_t *fspace, H5FS_section_info_t *sect, unsigned new_class) +{ + const H5FS_section_class_t *old_cls; /* Old class of section */ + const H5FS_section_class_t *new_cls; /* New class of section */ + unsigned old_class; /* Old class ID of section */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_sect_change_class) + + /* Check arguments. */ + HDassert(fspace); + HDassert(fspace->must_deserialize == FALSE); + HDassert(sect); + HDassert(sect->type < fspace->hdr->nclasses); + HDassert(new_class < fspace->hdr->nclasses); +#ifdef QAK +HDfprintf(stderr, "%s: Called\n", "H5FS_sect_change_class"); +#endif /* QAK */ + + /* Get class info */ + old_class = sect->type; + old_cls = &fspace->sect_cls[sect->type]; + new_cls = &fspace->sect_cls[new_class]; + + /* Check if the section's class change will affect the # of serializable or ghost sections */ + if((old_cls->flags & H5FS_CLS_GHOST_OBJ) != (new_cls->flags & H5FS_CLS_GHOST_OBJ)) { + hbool_t to_ghost; /* Flag if the section is changing to a ghost section */ + + /* Determine if this section is becoming a ghost or is becoming serializable */ + if(old_cls->flags & H5FS_CLS_GHOST_OBJ) + to_ghost = FALSE; + else + to_ghost = TRUE; +#ifdef QAK +HDfprintf(stderr, "%s: to_ghost = %u\n", "H5FS_sect_change_class", to_ghost); +#endif /* QAK */ + + /* Check for single vs. multiple sections managed */ + if(fspace->single) { + /* Adjust serializable/ghost counts */ + if(to_ghost) { + fspace->serial_size_count = 0; + fspace->ghost_size_count = 1; + fspace->hdr->serial_sect_count = 0; + fspace->hdr->ghost_sect_count = 1; + } /* end if */ + else { + fspace->serial_size_count = 1; + fspace->ghost_size_count = 0; + fspace->hdr->serial_sect_count = 1; + fspace->hdr->ghost_sect_count = 0; + } /* end else */ + } /* end if */ + else { + H5FS_node_t *fspace_node; /* Free list size node */ + unsigned bin; /* Bin to put the free space section in */ + + /* Sanity check */ + HDassert(fspace->bins); + + /* Determine correct bin which holds items of at least the section's size */ + bin = H5V_log2_gen(sect->size); + HDassert(bin < fspace->nbins); + HDassert(fspace->bins[bin].bin_list); + + /* Get space node for section's size */ + fspace_node = H5SL_search(fspace->bins[bin].bin_list, §->size); + HDassert(fspace_node); + + /* Adjust serializable/ghost counts */ + if(to_ghost) { + /* Adjust global section count totals */ + fspace->hdr->serial_sect_count--; + fspace->hdr->ghost_sect_count++; + + /* Adjust bin's section count totals */ + fspace->bins[bin].serial_sect_count--; + fspace->bins[bin].ghost_sect_count++; + + /* Adjust section size node's section count totals */ + fspace_node->serial_count--; + fspace_node->ghost_count++; + + /* Check if we switched a section size node's status */ + if(fspace_node->serial_count == 0) + fspace->serial_size_count--; + if(fspace_node->ghost_count == 1) + fspace->ghost_size_count++; + } /* end if */ + else { + /* Adjust global section count totals */ + fspace->hdr->serial_sect_count++; + fspace->hdr->ghost_sect_count--; + + /* Adjust bin's section count totals */ + fspace->bins[bin].serial_sect_count++; + fspace->bins[bin].ghost_sect_count--; + + /* Adjust section size node's section count totals */ + fspace_node->serial_count++; + fspace_node->ghost_count--; + + /* Check if we switched a section size node's status */ + if(fspace_node->serial_count == 1) + fspace->serial_size_count++; + if(fspace_node->ghost_count == 0) + fspace->ghost_size_count--; + } /* end else */ + } /* end else */ + } /* end if */ + + /* Change the section's class */ + sect->type = new_class; + + /* Change the serialized size of sections */ + fspace->serial_size -= fspace->sect_cls[old_class].serial_size; + fspace->serial_size += fspace->sect_cls[new_class].serial_size; + + /* Update current space used for free space sections */ + fspace->hdr->sect_size = H5FS_serialize_size(fspace); + + /* Mark free space as dirty also */ + fspace->dirty = TRUE; + +#ifdef H5FS_DEBUG + H5FS_assert(fspace); +#endif /* H5FS_DEBUG */ + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5FS_sect_change_class() */ + + +/*------------------------------------------------------------------------- * Function: H5FS_flush_cb * * Purpose: Skip list iterator callback to syncronize free space sections @@ -2353,9 +2726,11 @@ H5FS_flush_cb(void *_item, void UNUSED *key, void *_udata) HDassert(udata->f); /* Serialize the bins for this free space manager, if they are dirty */ - if(fspace->dirty) + if(fspace->dirty) { + HDassert(fspace->must_deserialize == FALSE); if(H5FS_serialize_bins(udata->f, udata->dxpl_id, fspace) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTSERIALIZE, FAIL, "can't syncronize bins") + } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) @@ -2439,7 +2814,7 @@ HDfprintf(stderr, "%s: Deleting free space manager\n", FUNC); #ifdef QAK HDfprintf(stderr, "%s: fs_hdr->sect_addr = %a\n", FUNC, fs_hdr->sect_addr); #endif /* QAK */ - if(fs_hdr->sect_count > 0) { + if(fs_hdr->serial_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) @@ -2486,16 +2861,24 @@ H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace) /* Check arguments. */ HDassert(f); HDassert(fspace); +#ifdef QAK +HDfprintf(stderr, "%s: Entering\n", FUNC); +#endif /* QAK */ /* Remove the free space manager from the list of open free space managers */ if(H5FS_open_remove(fspace) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove free space header from open list") /* Serialize the sections in the bins, if necessary */ - if(fspace->dirty) + if(fspace->dirty) { + HDassert(fspace->must_deserialize == FALSE); if(H5FS_serialize_bins(f, dxpl_id, fspace) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTSERIALIZE, FAIL, "can't syncronize bins") + } /* end if */ +#ifdef QAK +HDfprintf(stderr, "%s: fspace->hdr->tot_sect_count = %Hu\n", FUNC, fspace->hdr->tot_sect_count); +#endif /* QAK */ /* Check for single section to free */ if(fspace->single) { /* Call the 'free' callback for the section */ @@ -2525,6 +2908,14 @@ H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace) if(H5AC_unpin_entry(f, fspace->hdr) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin free space header") + /* Terminate the section classes for this free space list */ + for(u = 0; u < fspace->hdr->nclasses ; u++) { + /* Call the class termination routine, if there is one */ + if(fspace->sect_cls[u].term_cls) + if((fspace->sect_cls[u].term_cls)(&fspace->sect_cls[u]) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "unable to finalize section class") + } /* end for */ + /* Release the memory for the free space section classes */ fspace->sect_cls = H5FL_SEQ_FREE(H5FS_section_class_t, fspace->sect_cls); @@ -2556,3 +2947,181 @@ H5FS_debug_test(const H5FS_t *fspace) FUNC_LEAVE_NOAPI(SUCCEED) } +#ifdef H5FS_DEBUG + +/*------------------------------------------------------------------------- + * Function: H5FS_assert + * + * Purpose: Verify that the sections managed are mostly sane + * + * Return: Non-negative on success, negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Jul 17 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FS_assert(const H5FS_t *fspace) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_assert) +#ifdef QAK +HDfprintf(stderr, "%s: fspace->hdr->tot_sect_count = %Hu\n", "H5FS_assert", fspace->hdr->tot_sect_count); +#endif /* QAK */ + + /* Check for single vs. multiple sections managed */ + if(fspace->single) { + const H5FS_section_class_t *cls; /* Class of section */ + + HDassert(fspace->tot_size_count == 1); + HDassert(fspace->hdr->tot_sect_count == 1); + + /* Get section's class */ + cls = &fspace->sect_cls[fspace->single->type]; +#ifdef QAK +HDfprintf(stderr, "%s: fspace->single->size = %Hu, fspace->single->addr = %a, fspace->single->type = %u\n", "H5FS_assert", fspace->single->size, fspace->single->addr, fspace->single->type); +#endif /* QAK */ + + /* Sanity checks on counts */ + if(cls->flags & H5FS_CLS_GHOST_OBJ) { + HDassert(fspace->serial_size_count == 0); + HDassert(fspace->ghost_size_count == 1); + HDassert(fspace->hdr->serial_sect_count == 0); + HDassert(fspace->hdr->ghost_sect_count == 1); + } /* end if */ + else { + HDassert(fspace->serial_size_count == 1); + HDassert(fspace->ghost_size_count == 0); + HDassert(fspace->hdr->serial_sect_count == 1); + HDassert(fspace->hdr->ghost_sect_count == 0); + } /* end else */ + } /* end if */ + else if(fspace->bins) { + hsize_t acc_tot_sect_count; /* Accumulated total section count from bins */ + hsize_t acc_serial_sect_count; /* Accumulated serializable section count from bins */ + hsize_t acc_ghost_sect_count; /* Accumulated ghost section count from bins */ + size_t acc_tot_size_count; /* Accumulated total section size count from bins */ + size_t acc_serial_size_count; /* Accumulated serializable section size count from bins */ + size_t acc_ghost_size_count; /* Accumulated ghost section size count from bins */ + unsigned u; /* Local index variable */ + + /* Walk through all sections in bins */ + acc_tot_sect_count = 0; + acc_serial_sect_count = 0; + acc_ghost_sect_count = 0; + acc_tot_size_count = 0; + acc_serial_size_count = 0; + acc_ghost_size_count = 0; + for(u = 0; u < fspace->nbins; u++) { + acc_tot_sect_count += fspace->bins[u].tot_sect_count; + acc_serial_sect_count += fspace->bins[u].serial_sect_count; + acc_ghost_sect_count += fspace->bins[u].ghost_sect_count; + if(fspace->bins[u].bin_list) { + H5SL_node_t *curr_size_node; /* Current section size node in skip list */ + size_t bin_serial_count; /* # of serializable sections in this bin */ + size_t bin_ghost_count; /* # of ghost sections in this bin */ + + acc_tot_size_count += H5SL_count(fspace->bins[u].bin_list); + + /* Walk through the sections in this bin */ + curr_size_node = H5SL_first(fspace->bins[u].bin_list); + bin_serial_count = 0; + bin_ghost_count = 0; + while(curr_size_node != NULL) { + H5FS_node_t *fspace_node; /* Section size node */ + H5SL_node_t *curr_sect_node; /* Current section node in skip list */ + size_t size_serial_count; /* # of serializable sections of this size */ + size_t size_ghost_count; /* # of ghost sections of this size */ + + /* Get section size node */ + fspace_node = H5SL_item(curr_size_node); + + /* Check sections on list */ + curr_sect_node = H5SL_first(fspace_node->sect_list); + size_serial_count = 0; + size_ghost_count = 0; + while(curr_sect_node != NULL) { + H5FS_section_class_t *cls; /* Class of section */ + H5FS_section_info_t *sect; /* Section */ + + /* Get section node & it's class */ + sect = H5SL_item(curr_sect_node); + cls = &fspace->sect_cls[sect->type]; +#ifdef QAK +HDfprintf(stderr, "%s: sect->size = %Hu, sect->addr = %a, sect->type = %u\n", "H5FS_assert", sect->size, sect->addr, sect->type); +#endif /* QAK */ + + /* Sanity check section */ + HDassert(H5F_addr_defined(sect->addr)); + HDassert(fspace_node->sect_size == sect->size); + if(cls->valid) + (*cls->valid)(cls, sect); + + /* Add to correct count */ + if(cls->flags & H5FS_CLS_GHOST_OBJ) + size_ghost_count++; + else + size_serial_count++; + + /* Get the next section node in the list */ + curr_sect_node = H5SL_next(curr_sect_node); + } /* end while */ + + /* Check the number of serializable & ghost sections of this size */ + HDassert(fspace_node->serial_count == size_serial_count); + HDassert(fspace_node->ghost_count == size_ghost_count); + + /* Add to global count of serializable & ghost section sizes */ + if(fspace_node->serial_count > 0) + acc_serial_size_count++; + if(fspace_node->ghost_count > 0) + acc_ghost_size_count++; + + /* Add to bin's serializable & ghost counts */ + bin_serial_count += size_serial_count; + bin_ghost_count += size_ghost_count; + + /* Get the next section size node in the list */ + curr_size_node = H5SL_next(curr_size_node); + } /* end while */ + + /* Check the number of serializable & ghost sections in this bin */ + HDassert(fspace->bins[u].tot_sect_count == (bin_serial_count + bin_ghost_count)); + HDassert(fspace->bins[u].serial_sect_count == bin_serial_count); + HDassert(fspace->bins[u].ghost_sect_count == bin_ghost_count); + } /* end if */ + } /* end for */ + + /* Check counts from bins vs. global counts */ + HDassert(fspace->tot_size_count == acc_tot_size_count); + HDassert(fspace->serial_size_count == acc_serial_size_count); + HDassert(fspace->ghost_size_count == acc_ghost_size_count); + HDassert(fspace->hdr->tot_sect_count == acc_tot_sect_count); + HDassert(fspace->hdr->serial_sect_count == acc_serial_sect_count); + HDassert(fspace->hdr->ghost_sect_count == acc_ghost_sect_count); + } /* end else */ + else { + /* Check counts are zero */ + HDassert(fspace->hdr->tot_sect_count == 0); + HDassert(fspace->hdr->serial_sect_count == 0); + HDassert(fspace->hdr->ghost_sect_count == 0); + } /* end else */ + + /* General assumptions about the section size counts */ + HDassert(fspace->tot_size_count >= fspace->serial_size_count); + HDassert(fspace->tot_size_count >= fspace->ghost_size_count); + + /* General assumptions about the section counts */ + HDassert(fspace->hdr->tot_sect_count >= fspace->hdr->serial_sect_count); + HDassert(fspace->hdr->tot_sect_count >= fspace->hdr->ghost_sect_count); + HDassert(fspace->hdr->tot_sect_count == (fspace->hdr->serial_sect_count + fspace->hdr->ghost_sect_count)); + + /* Make certain that the number of sections on the address list is correct */ + if(fspace->merge_list) + HDassert(fspace->hdr->tot_sect_count == H5SL_count(fspace->merge_list)); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5FS_assert() */ +#endif /* H5FS_DEBUG */ + diff --git a/src/H5FScache.c b/src/H5FScache.c index c87cdc0..c6fd297 100644 --- a/src/H5FScache.c +++ b/src/H5FScache.c @@ -173,8 +173,14 @@ HDfprintf(stderr, "%s: Load free space header, addr = %a\n", FUNC, addr); /* Total space tracked */ H5F_DECODE_LENGTH(f, p, hdr->tot_space); - /* # of free space sections tracked */ - H5F_DECODE_LENGTH(f, p, hdr->sect_count); + /* Total # of free space sections tracked */ + H5F_DECODE_LENGTH(f, p, hdr->tot_sect_count); + + /* # of serializable free space sections tracked */ + H5F_DECODE_LENGTH(f, p, hdr->serial_sect_count); + + /* # of ghost free space sections tracked */ + H5F_DECODE_LENGTH(f, p, hdr->ghost_sect_count); /* # of section classes */ UINT16DECODE(p, hdr->nclasses); @@ -279,8 +285,14 @@ HDfprintf(stderr, "%s: Flushing free space header, addr = %a, destroy = %u\n", F /* Total space tracked */ H5F_ENCODE_LENGTH(f, p, hdr->tot_space); - /* # of free space sections tracked */ - H5F_ENCODE_LENGTH(f, p, hdr->sect_count); + /* Total # of free space sections tracked */ + H5F_ENCODE_LENGTH(f, p, hdr->tot_sect_count); + + /* # of serializable free space sections tracked */ + H5F_ENCODE_LENGTH(f, p, hdr->serial_sect_count); + + /* # of ghost free space sections tracked */ + H5F_ENCODE_LENGTH(f, p, hdr->ghost_sect_count); /* # of section classes */ UINT16ENCODE(p, hdr->nclasses); diff --git a/src/H5FSdbg.c b/src/H5FSdbg.c index a946cf0..69c0f80 100644 --- a/src/H5FSdbg.c +++ b/src/H5FSdbg.c @@ -122,8 +122,14 @@ H5FS_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, "Total free space tracked:", hdr->tot_space); HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, - "Number of free space sections tracked:", - hdr->sect_count); + "Total number of free space sections tracked:", + hdr->tot_sect_count); + HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, + "Number of serializable free space sections tracked:", + hdr->serial_sect_count); + HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, + "Number of ghost free space sections tracked:", + hdr->ghost_sect_count); HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, "Number of free space section classes:", hdr->nclasses); diff --git a/src/H5FSpkg.h b/src/H5FSpkg.h index 0f9aaad..c3d9f1c 100644 --- a/src/H5FSpkg.h +++ b/src/H5FSpkg.h @@ -60,7 +60,9 @@ /* Free space header specific fields */ \ + 1 /* Client ID */ \ + H5F_SIZEOF_SIZE(f) /* Total free space tracked */ \ - + H5F_SIZEOF_SIZE(f) /* # of sections tracked */ \ + + H5F_SIZEOF_SIZE(f) /* Total # of sections tracked */ \ + + H5F_SIZEOF_SIZE(f) /* # of serializable sections tracked */ \ + + H5F_SIZEOF_SIZE(f) /* # of ghost sections tracked */ \ + 2 /* Number of section classes */ \ + 2 /* Shrink percent */ \ + 2 /* Expand percent */ \ @@ -82,7 +84,9 @@ typedef struct H5FS_hdr_t { /* Statistics */ hsize_t tot_space; /* Total amount of space tracked */ - hsize_t sect_count; /* # of sections tracked */ + hsize_t tot_sect_count; /* Total # of sections tracked */ + hsize_t serial_sect_count; /* # of serializable sections tracked */ + hsize_t ghost_sect_count; /* # of un-serializable sections tracked */ /* Creation information */ H5FS_client_t client; /* Type of user of this free space manager */ @@ -100,7 +104,9 @@ typedef struct H5FS_hdr_t { /* Free space section bin info */ typedef struct H5FS_bin_t { - size_t sect_count; /* Total # of sections in this bin */ + size_t tot_sect_count; /* Total # of sections in this bin */ + size_t serial_sect_count; /* # of serializable sections in this bin */ + size_t ghost_sect_count; /* # of un-serializable sections in this bin */ H5SL_t *bin_list; /* Skip list of differently sized sections */ } H5FS_bin_t; @@ -112,11 +118,14 @@ struct H5FS_t { /* 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 */ + size_t serial_size; /* Total size of all serializable sections */ + size_t tot_size_count; /* Total number of differently sized sections */ + size_t serial_size_count; /* Total number of differently sized serializable sections */ + size_t ghost_size_count; /* Total number of differently sized un-serializable 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 must_deserialize; /* Sections must be deserialized */ hbool_t dirty; /* Space information is dirty */ /* Memory data structures (not stored directly) */ diff --git a/src/H5FSprivate.h b/src/H5FSprivate.h index ada35e0..25383cc 100644 --- a/src/H5FSprivate.h +++ b/src/H5FSprivate.h @@ -38,9 +38,13 @@ /* Library Private Macros */ /**************************/ +/* Flags for H5FS_section_class_t 'flags' field */ +#define H5FS_CLS_GHOST_OBJ 0x01 /* Objects in this class shouldn't be + * serialized to the file. + */ + /* Flags for H5FS_add() */ #define H5FS_ADD_DESERIALIZING 0x01 /* Free space is being deserialized - * (for package use only) */ #define H5FS_ADD_RETURNED_SPACE 0x02 /* Section was previously allocated * and is being returned to the @@ -49,6 +53,13 @@ * object) */ +/* Flags for deserialize callback */ +#define H5FS_DESERIALIZE_NO_ADD 0x01 /* Don't add section to free space + * manager after it's deserialized + * (its only here for it's side- + * effects). + */ + /****************************/ /* Library Private Typedefs */ @@ -63,20 +74,24 @@ typedef struct H5FS_section_info_t H5FS_section_info_t; /* Free space section class info */ typedef struct H5FS_section_class_t { /* Class variables */ - const unsigned type; /* Type of free space section */ - size_t serial_size; /* Size of serialized form of section */ + const unsigned type; /* Type of free space section */ + size_t serial_size; /* Size of serialized form of section */ + unsigned flags; /* Class flags */ + void *cls_private; /* Class private information */ /* Class methods */ - herr_t (*init_cls)(struct H5FS_section_class_t *, const void *); /* Routine to initialize class-specific settings */ + herr_t (*init_cls)(struct H5FS_section_class_t *, void *); /* Routine to initialize class-specific settings */ + herr_t (*term_cls)(struct H5FS_section_class_t *); /* Routine to terminate class-specific settings */ /* Object methods */ - herr_t (*serialize)(const H5FS_section_info_t *, uint8_t *); /* Routine to serialize a "live" section into a buffer */ - H5FS_section_info_t *(*deserialize)(const uint8_t *, haddr_t, hsize_t); /* Routine to deserialize a buffer into a "live" section */ + herr_t (*serialize)(const struct H5FS_section_class_t *, const H5FS_section_info_t *, uint8_t *); /* Routine to serialize a "live" section into a buffer */ + H5FS_section_info_t *(*deserialize)(const struct H5FS_section_class_t *, hid_t dxpl_id, const uint8_t *, haddr_t, hsize_t, unsigned *); /* 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 */ 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 (*valid)(const struct H5FS_section_class_t *, const H5FS_section_info_t *); /* Routine to check if a section is valid */ herr_t (*debug)(const H5FS_section_info_t *, FILE *, int , int ); /* Routine to dump debugging information about a section */ } H5FS_section_class_t; @@ -127,15 +142,17 @@ 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, - const H5FS_section_class_t *classes[], const void *cls_init_udata); + const H5FS_section_class_t *classes[], void *cls_init_udata); H5_DLL H5FS_t *H5FS_open(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr, - size_t nclasses, const H5FS_section_class_t *classes[], const void *cls_init_udata); + size_t nclasses, const H5FS_section_class_t *classes[], 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_iterate(H5F_t *f, hid_t dxpl_id, 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_sect_change_class(H5FS_t *fspace, H5FS_section_info_t *sect, + unsigned new_class); 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); diff --git a/src/H5Gdeprec.c b/src/H5Gdeprec.c index 98d2cf8..4f2b837 100644 --- a/src/H5Gdeprec.c +++ b/src/H5Gdeprec.c @@ -83,6 +83,7 @@ H5Glink2(hid_t cur_loc_id, const char *cur_name, H5L_link_t type, herr_t ret_value; FUNC_ENTER_API(H5Glink2, FAIL) + H5TRACE5("e","isLlis",cur_loc_id,cur_name,type,new_loc_id,new_name); if(type == H5L_LINK_HARD) { if((ret_value = H5Lcreate_hard(cur_loc_id, cur_name, new_loc_id, new_name, H5P_DEFAULT)) < 0) diff --git a/src/H5HFdbg.c b/src/H5HFdbg.c index c8945fd..2d878f9 100644 --- a/src/H5HFdbg.c +++ b/src/H5HFdbg.c @@ -435,7 +435,7 @@ H5HF_dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, HDfprintf(stream, "%*sFree Blocks (offset, size):\n", indent, ""); /* Iterate over the free space sections, to detect overlaps with this block */ - if(H5FS_iterate(hdr->fspace, H5HF_dblock_debug_cb, &udata) < 0) + if(H5FS_iterate(f, dxpl_id, hdr->fspace, H5HF_dblock_debug_cb, &udata) < 0) HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't iterate over heap's free space") /* Close the free space information */ @@ -488,7 +488,6 @@ H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, { H5HF_hdr_t *hdr = NULL; /* Fractal heap header info */ H5HF_indirect_t *iblock = NULL; /* Fractal heap direct block info */ - size_t dblock_size; /* Current direct block size */ char temp_str[64]; /* Temporary string, for formatting */ size_t u, v; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ @@ -557,7 +556,6 @@ H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, temp_str, iblock->ents[off].addr); } /* end for */ - dblock_size *= 2; } /* end for */ HDfprintf(stream, "%*sIndirect Block Entries:\n", indent, ""); if(iblock->nrows > hdr->man_dtable.max_direct_rows) { @@ -633,8 +631,8 @@ H5HF_sects_debug_cb(const H5FS_section_info_t *_sect, void *_udata) HDfprintf(udata->stream, "%*s%-*s %s\n", udata->indent, "", udata->fwidth, "Section type:", (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")))); + (sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ? "first row" : + (sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ? "normal row" : "unknown")))); HDfprintf(udata->stream, "%*s%-*s %s\n", udata->indent, "", udata->fwidth, "Section state:", (sect->sect_info.state == H5FS_SECT_LIVE ? "live" : "serialized")); @@ -697,7 +695,7 @@ H5HF_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr, udata.fwidth = fwidth; /* Iterate over all the free space sections */ - if(H5FS_iterate(hdr->fspace, H5HF_sects_debug_cb, &udata) < 0) + if(H5FS_iterate(f, dxpl_id, hdr->fspace, H5HF_sects_debug_cb, &udata) < 0) HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't iterate over heap's free space") /* Close the free space information */ diff --git a/src/H5HFdblock.c b/src/H5HFdblock.c index c8abfd4..590d8f3 100644 --- a/src/H5HFdblock.c +++ b/src/H5HFdblock.c @@ -96,6 +96,7 @@ H5HF_man_dblock_create(hid_t dxpl_id, H5HF_hdr_t *hdr, H5HF_indirect_t *par_iblo { H5HF_free_section_t *sec_node; /* Pointer to free space section for block */ H5HF_direct_t *dblock = NULL; /* Pointer to direct block */ + haddr_t dblock_addr; /* Direct block's address */ size_t free_space; /* Free space in new block */ herr_t ret_value = SUCCEED; /* Return value */ @@ -105,7 +106,6 @@ H5HF_man_dblock_create(hid_t dxpl_id, H5HF_hdr_t *hdr, H5HF_indirect_t *par_iblo * Check arguments. */ HDassert(hdr); - HDassert(addr_p); /* * Allocate file and memory data structures. @@ -148,22 +148,22 @@ 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)dblock->size))) + if(HADDR_UNDEF == (dblock_addr = 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); +HDfprintf(stderr, "%s: direct block address = %a\n", FUNC, dblock_addr); #endif /* QAK */ /* 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) + if(H5HF_man_iblock_attach(dblock->parent, par_entry, dblock_addr) < 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))) + free_space, dblock->parent, dblock->par_entry, dblock_addr, 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 */ @@ -172,18 +172,22 @@ HDfprintf(stderr, "%s: direct block address = %a\n", FUNC, *addr_p); *ret_sec_node = sec_node; else { /* Add new free space to the heap's list of space */ - if(H5HF_space_add(hdr, dxpl_id, sec_node) < 0) + if(H5HF_space_add(hdr, dxpl_id, sec_node, 0) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list") } /* end else */ /* Cache the new fractal heap direct block */ - if(H5AC_set(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, *addr_p, dblock, H5AC__NO_FLAGS_SET) < 0) + if(H5AC_set(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, 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") + /* Set the address of of direct block, if requested */ + if(addr_p) + *addr_p = dblock_addr; + done: if(ret_value < 0) if(dblock) @@ -242,7 +246,6 @@ HDfprintf(stderr, "%s: root direct block\n", FUNC); 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 */ @@ -282,7 +285,7 @@ HDfprintf(stderr, "%s: Reversing iterator\n", FUNC); 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], + if(H5HF_sect_range_add(hdr, dxpl_id, dblock->block_off, hdr->man_dtable.row_tot_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 */ @@ -380,7 +383,7 @@ HDfprintf(stderr, "%s: root direct block, dblock_addr = %a\n", FUNC, dblock_addr hdr->man_dtable.table_addr = dblock_addr; /* Extend heap to cover new direct block */ - 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) + if(H5HF_hdr_adjust_heap(hdr, (hsize_t)hdr->man_dtable.cparam.start_block_size, (hssize_t)hdr->man_dtable.row_tot_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, allocate direct block from root indirect block */ diff --git a/src/H5HFdtable.c b/src/H5HFdtable.c index 1461cd7..4c41805 100644 --- a/src/H5HFdtable.c +++ b/src/H5HFdtable.c @@ -116,8 +116,10 @@ H5HF_dtable_init(H5HF_dtable_t *dtable) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create doubling table block size table") if(NULL == (dtable->row_block_off = H5MM_malloc(dtable->max_root_rows * sizeof(hsize_t)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create doubling table block offset table") - if(NULL == (dtable->row_dblock_free = H5MM_malloc(dtable->max_root_rows * sizeof(hsize_t)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create doubling table direct block free space table") + if(NULL == (dtable->row_tot_dblock_free = H5MM_malloc(dtable->max_root_rows * sizeof(hsize_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create doubling table total direct block free space table") + if(NULL == (dtable->row_max_dblock_free = H5MM_malloc(dtable->max_root_rows * sizeof(size_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create doubling table max. direct block free space table") tmp_block_size = dtable->cparam.start_block_size; acc_block_off = dtable->cparam.start_block_size * dtable->cparam.width; dtable->row_block_size[0] = dtable->cparam.start_block_size; @@ -205,8 +207,11 @@ H5HF_dtable_dest(H5HF_dtable_t *dtable) /* Free the block offset lookup table for the doubling table */ H5MM_xfree(dtable->row_block_off); - /* Free the direct block free space lookup table for the doubling table */ - H5MM_xfree(dtable->row_dblock_free); + /* Free the total direct block free space lookup table for the doubling table */ + H5MM_xfree(dtable->row_tot_dblock_free); + + /* Free the max. direct block free space lookup table for the doubling table */ + H5MM_xfree(dtable->row_max_dblock_free); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5HF_dtable_dest() */ diff --git a/src/H5HFhdr.c b/src/H5HFhdr.c index d5af3fe..fc67aed 100644 --- a/src/H5HFhdr.c +++ b/src/H5HFhdr.c @@ -68,10 +68,6 @@ /* 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 */ @@ -153,13 +149,15 @@ done: * *------------------------------------------------------------------------- */ -static hsize_t -H5HF_hdr_compute_free_space(H5HF_hdr_t *hdr, hsize_t iblock_size) +static herr_t +H5HF_hdr_compute_free_space(H5HF_hdr_t *hdr, unsigned iblock_row) { hsize_t acc_heap_size; /* Accumumated heap space */ + hsize_t iblock_size; /* Size of indirect block to calculate for */ hsize_t acc_dblock_free; /* Accumumated direct block free space */ + size_t max_dblock_free; /* Max. direct block free space */ unsigned curr_row; /* Current row in block */ - hsize_t ret_value; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_hdr_compute_free_space) @@ -167,22 +165,27 @@ H5HF_hdr_compute_free_space(H5HF_hdr_t *hdr, hsize_t iblock_size) * Check arguments. */ HDassert(hdr); - HDassert(iblock_size > hdr->man_dtable.cparam.max_direct_size); + HDassert(iblock_row >= hdr->man_dtable.max_direct_rows); /* Set the free space in direct blocks */ acc_heap_size = 0; acc_dblock_free = 0; + max_dblock_free = 0; + iblock_size = hdr->man_dtable.row_block_size[iblock_row]; curr_row = 0; while(acc_heap_size < iblock_size) { acc_heap_size += hdr->man_dtable.row_block_size[curr_row] * hdr->man_dtable.cparam.width; - acc_dblock_free += hdr->man_dtable.row_dblock_free[curr_row] * + acc_dblock_free += hdr->man_dtable.row_tot_dblock_free[curr_row] * hdr->man_dtable.cparam.width; + if(hdr->man_dtable.row_max_dblock_free[curr_row] > max_dblock_free) + max_dblock_free = hdr->man_dtable.row_max_dblock_free[curr_row]; curr_row++; } /* end while */ - /* Set return value */ - ret_value = acc_dblock_free; + /* Set direct block free space values for indirect block */ + hdr->man_dtable.row_tot_dblock_free[iblock_row] = acc_dblock_free; + hdr->man_dtable.row_max_dblock_free[iblock_row] = max_dblock_free; FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_hdr_compute_free_space() */ @@ -226,15 +229,19 @@ H5HF_hdr_finish_init(H5HF_hdr_t *hdr) /* Set the free space in direct blocks */ for(u = 0; u < hdr->man_dtable.max_root_rows; u++) { - if(u < hdr->man_dtable.max_direct_rows) - hdr->man_dtable.row_dblock_free[u] = hdr->man_dtable.row_block_size[u] - + if(u < hdr->man_dtable.max_direct_rows) { + hdr->man_dtable.row_tot_dblock_free[u] = hdr->man_dtable.row_block_size[u] - H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr); + hdr->man_dtable.row_max_dblock_free[u] = hdr->man_dtable.row_tot_dblock_free[u]; + } /* end if */ else - hdr->man_dtable.row_dblock_free[u] = H5HF_hdr_compute_free_space(hdr, hdr->man_dtable.row_block_size[u]); + if(H5HF_hdr_compute_free_space(hdr, u) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize direct block free space for indirect block") #ifdef QAK HDfprintf(stderr, "%s: row_block_size[%Zu] = %Hu\n", FUNC, u, hdr->man_dtable.row_block_size[u]); HDfprintf(stderr, "%s: row_block_off[%Zu] = %Hu\n", FUNC, u, hdr->man_dtable.row_block_off[u]); -HDfprintf(stderr, "%s: row_dblock_free[%Zu] = %Hu\n", FUNC, u, hdr->man_dtable.row_dblock_free[u]); +HDfprintf(stderr, "%s: row_tot_dblock_free[%Zu] = %Hu\n", FUNC, u, hdr->man_dtable.row_tot_dblock_free[u]); +HDfprintf(stderr, "%s: row_max_dblock_free[%Zu] = %Zu\n", FUNC, u, hdr->man_dtable.row_max_dblock_free[u]); #endif /* QAK */ } /* end for */ @@ -652,10 +659,7 @@ 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 */ + hsize_t sect_off; /* Offset of section in heap space */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_skip_blocks) @@ -670,46 +674,11 @@ HDfprintf(stderr, "%s: start_entry = %u, nentries = %u\n", FUNC, start_entry, ne 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); + /* Add 'indirect' section for blocks skipped in this row */ + if(H5HF_sect_indirect_add(hdr, dxpl_id, iblock, start_entry, nentries, §_off) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section for indirect block's free space") #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); +HDfprintf(stderr, "%s: sect_off = %Hu\n", FUNC, sect_off); #endif /* QAK */ /* Advance the new block iterator */ @@ -722,120 +691,6 @@ done: /*------------------------------------------------------------------------- - * 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 @@ -1036,8 +891,8 @@ 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) + /* Add skipped indirect blocks to heap's free space */ + if(H5HF_hdr_skip_blocks(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 { diff --git a/src/H5HFiblock.c b/src/H5HFiblock.c index 1fa7c35..f48b4c2 100644 --- a/src/H5HFiblock.c +++ b/src/H5HFiblock.c @@ -112,6 +112,10 @@ H5HF_iblock_incr(H5HF_indirect_t *iblock) /* Increment reference count on shared indirect block */ iblock->rc++; +#ifdef QAK +HDfprintf(stderr, "%s: iblock->addr = %a, iblock->rc = %Zu\n", FUNC, iblock->addr, iblock->rc); +HDfprintf(stderr, "%s: iblock->block_off = %Hu\n", FUNC, iblock->block_off); +#endif /* QAK */ done: FUNC_LEAVE_NOAPI(ret_value) @@ -143,6 +147,10 @@ H5HF_iblock_decr(H5HF_indirect_t *iblock) /* Decrement reference count on shared indirect block */ iblock->rc--; +#ifdef QAK +HDfprintf(stderr, "%s: iblock->addr = %a, iblock->rc = %Zu\n", FUNC, iblock->addr, iblock->rc); +HDfprintf(stderr, "%s: iblock->block_off = %Hu\n", FUNC, iblock->block_off); +#endif /* QAK */ /* Mark block as evictable again when no child blocks depend on it */ if(iblock->rc == 0) { @@ -350,11 +358,11 @@ HDfprintf(stderr, "%s: have_direct_block = %u\n", FUNC, (unsigned)have_direct_bl /* Compute free space in direct blocks referenced from entries in root indirect block */ acc_dblock_free = 0; for(u = 0; u < nrows; u++) - acc_dblock_free += hdr->man_dtable.row_dblock_free[u] * hdr->man_dtable.cparam.width; + acc_dblock_free += hdr->man_dtable.row_tot_dblock_free[u] * hdr->man_dtable.cparam.width; /* Account for potential initial direct block */ if(have_direct_block) - acc_dblock_free -= hdr->man_dtable.row_dblock_free[0]; + acc_dblock_free -= hdr->man_dtable.row_tot_dblock_free[0]; /* Extend heap to cover new root indirect block */ if(H5HF_hdr_adjust_heap(hdr, hdr->man_dtable.row_block_off[nrows], (hssize_t)acc_dblock_free) < 0) @@ -487,7 +495,7 @@ HDfprintf(stderr, "%s: new_addr = %a\n", FUNC, new_addr); unsigned row = u / hdr->man_dtable.cparam.width; /* Row for current entry */ iblock->ents[u].addr = HADDR_UNDEF; - acc_dblock_free += hdr->man_dtable.row_dblock_free[row]; + acc_dblock_free += hdr->man_dtable.row_tot_dblock_free[row]; } /* end for */ /* Mark indirect block as dirty */ @@ -580,7 +588,7 @@ HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows); /* 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; + acc_dblock_free += hdr->man_dtable.row_tot_dblock_free[u] * hdr->man_dtable.cparam.width; /* Compute size of buffer needed for new indirect block */ iblock->nrows = new_nrows; @@ -686,7 +694,7 @@ HDfprintf(stderr, "%s: Reverting root indirect block\n", FUNC); HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't reset block iterator") /* Extend heap to just cover first direct block */ - 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) + if(H5HF_hdr_adjust_heap(hdr, (hsize_t)hdr->man_dtable.cparam.start_block_size, (hssize_t)hdr->man_dtable.row_tot_dblock_free[0]) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "can't increase space to cover root direct block") done: @@ -698,80 +706,10 @@ done: /*------------------------------------------------------------------------- - * Function: H5HF_man_iblock_alloc_range - * - * Purpose: Allocate a "single" section for an object, out of a "range" - * section - * - * Note: Creates necessary direct & indirect blocks - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 28 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5HF_man_iblock_alloc_range(H5HF_hdr_t *hdr, hid_t dxpl_id, - H5HF_free_section_t **sec_node) -{ - H5HF_indirect_t *iblock = NULL; /* Pointer to indirect block */ - haddr_t dblock_addr; /* Direct block's address */ - H5HF_free_section_t *dblock_sec_node = NULL; /* Pointer to direct block's section node */ - H5HF_free_section_t *old_sec_node = *sec_node; /* Pointer to old section node */ - unsigned cur_entry; /* Current entry in indirect block */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_alloc_range) - - /* - * Check arguments. - */ - HDassert(hdr); - HDassert(sec_node && *sec_node); - - /* Check for serialized section */ - if(old_sec_node->sect_info.state == H5FS_SECT_SERIALIZED) { - /* Revive range section */ - if(H5HF_sect_range_revive(hdr, dxpl_id, old_sec_node) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTREVIVE, FAIL, "can't revive range section") - } /* end if */ - - /* Compute info about range */ - cur_entry = (old_sec_node->u.range.row * hdr->man_dtable.cparam.width) + old_sec_node->u.range.col; - - /* Get a pointer to the indirect block covering the range */ - iblock = old_sec_node->u.range.iblock; - HDassert(iblock); - -#ifdef QAK -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 */ - /* Create direct block of appropriate size */ - 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") - - /* 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; - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_man_iblock_alloc_range() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_man_iblock_alloc_indirect + * Function: H5HF_man_iblock_alloc_indirect2 * - * Purpose: Allocate a "single" section for an object, out of an - * "indirect" section, possibly creating "range" section as a - * byproduct. + * Purpose: Allocate a "single" section for an object, out of a + * "row" section. * * Note: Creates necessary direct & indirect blocks * @@ -779,110 +717,70 @@ done: * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu - * Apr 4 2006 + * July 6 2006 * *------------------------------------------------------------------------- */ herr_t -H5HF_man_iblock_alloc_indirect(H5HF_hdr_t *hdr, hid_t dxpl_id, - H5HF_free_section_t **sec_node) +H5HF_man_iblock_alloc_row(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t **sec_node) { H5HF_indirect_t *iblock; /* Pointer to indirect block */ - H5HF_indirect_t *child_iblock; /* Pointer to child indirect block */ - 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 *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 */ + unsigned dblock_entry; /* Entry for direct block */ + hbool_t iblock_held = FALSE; /* Flag to indicate that indirect block is held */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_alloc_indirect) + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_alloc_row) /* * Check arguments. */ HDassert(hdr); - HDassert(sec_node && *sec_node); + HDassert(sec_node && old_sec_node); + HDassert(old_sec_node->u.row.row < hdr->man_dtable.max_direct_rows); /* Check for serialized section */ if(old_sec_node->sect_info.state == H5FS_SECT_SERIALIZED) { /* Revive indirect section */ - if(H5HF_sect_indirect_revive(hdr, dxpl_id, old_sec_node) < 0) + if(H5HF_sect_row_revive(hdr, dxpl_id, old_sec_node) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTREVIVE, FAIL, "can't revive indirect section") } /* end if */ - /* Compute info about range */ - curr_entry = (old_sec_node->u.indirect.row * hdr->man_dtable.cparam.width) + old_sec_node->u.indirect.col; - /* Get a pointer to the indirect block covering the section */ - iblock = old_sec_node->u.indirect.iblock; + if(NULL == (iblock = H5HF_sect_row_get_iblock(old_sec_node))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't retrieve indirect block for row section") #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: 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); +HDfprintf(stderr, "%s: iblock->rc = %Zu\n", FUNC, iblock->rc); #endif /* QAK */ - /* Check if indirect block for this indirect section has already been created */ - if(H5F_addr_defined(iblock->ents[curr_entry].addr)) { - /* Look up existing child indirect block */ - child_iblock_addr = iblock->ents[curr_entry].addr; - 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") - } /* end if */ - else { - /* Create child indirect block */ - 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") -#ifdef QAK -HDfprintf(stderr, "%s: child_iblock->child_free_space = %Hu\n", FUNC, child_iblock->child_free_space); -#endif /* QAK */ - } /* end else */ + /* Hold indirect block in memory, until direct block can point to it */ + if(H5HF_iblock_incr(iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") + iblock_held = TRUE; - /* Compute entry for new direct block in child indirect block */ - dblock_entry = old_sec_node->u.indirect.indir_row * hdr->man_dtable.cparam.width; + /* Reduce (& possibly re-add) 'row' section */ + if(H5HF_sect_row_reduce(hdr, dxpl_id, old_sec_node, &dblock_entry) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce row section node") - /* Create direct block of correct size */ - /* (creates a 'single' free space section also) */ + /* Create direct block & single section */ #ifdef QAK -HDfprintf(stderr, "%s: old_sec_node->u.indirect.indir_row = %u\n", FUNC, old_sec_node->u.indirect.indir_row); -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_info.addr = %a\n", FUNC, old_sec_node->sect_info.addr); -HDfprintf(stderr, "%s: dblock_entry = %u\n", FUNC, dblock_entry); +HDfprintf(stderr, "%s: Allocating direct block, dblock_entry = %u\n", FUNC, dblock_entry); #endif /* QAK */ - if(H5HF_man_dblock_create(dxpl_id, hdr, child_iblock, dblock_entry, &dblock_addr, &dblock_sec_node) < 0) + if(H5HF_man_dblock_create(dxpl_id, hdr, iblock, dblock_entry, NULL, sec_node) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block") - /* 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") - - /* 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) - HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") - - /* Point 'sec_node' at new direct block section node */ - *sec_node = dblock_sec_node; - done: + /* Release hold on indirect block */ + if(iblock_held) + if(H5HF_iblock_decr(iblock) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't decrement reference count on shared indirect block") + FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_man_iblock_alloc_indirect() */ +} /* end H5HF_man_iblock_alloc_row() */ /*------------------------------------------------------------------------- @@ -1109,9 +1007,6 @@ done: herr_t H5HF_man_iblock_detach(H5HF_indirect_t *iblock, hid_t dxpl_id, unsigned entry) { -#ifdef OLD_WAY - unsigned start_children; /* # of children of iblock when routine was entered */ -#endif /* OLD_WAY */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_detach) @@ -1134,12 +1029,6 @@ HDfprintf(stderr, "%s: iblock->block_off = %Hu, iblock->nchildren = %u\n", FUNC, * 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) - */ -#ifdef OLD_WAY - start_children = iblock->nchildren; -#endif /* OLD_WAY */ iblock->nchildren--; /* Reduce the max. entry used, if necessary */ @@ -1195,3 +1084,34 @@ HDfprintf(stderr, "%s: iblock->block_off = %Hu, iblock->nchildren = %u\n", FUNC, FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_man_iblock_detach() */ + +/*------------------------------------------------------------------------- + * Function: H5HF_man_iblock_entry_addr + * + * Purpose: Retrieve the address of an indirect block's child + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * July 10 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_man_iblock_entry_addr(H5HF_indirect_t *iblock, unsigned entry, haddr_t *child_addr) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_man_iblock_entry_addr) + + /* + * Check arguments. + */ + HDassert(iblock); + HDassert(child_addr); + + /* Reset address of entry */ + *child_addr = iblock->ents[entry].addr; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_man_iblock_entry_addr() */ + diff --git a/src/H5HFint.c b/src/H5HFint.c index 833bc0f..e9fe631 100644 --- a/src/H5HFint.c +++ b/src/H5HFint.c @@ -115,11 +115,11 @@ HDfprintf(stderr, "%s: obj_off = %Hu\n", FUNC, obj_off); /* Set up target bottom & top rows */ if(locate_indirect) { bot_row = hdr->man_dtable.max_direct_rows; - top_row = hdr->man_dtable.max_direct_rows + (H5V_log2_of2(hdr->man_dtable.cparam.width) + 1); + top_row = hdr->man_dtable.max_direct_rows + H5V_log2_of2(hdr->man_dtable.cparam.width); } /* end if */ else { bot_row = 0; - top_row = hdr->man_dtable.max_direct_rows; + top_row = hdr->man_dtable.max_direct_rows - 1; } /* end else */ #ifdef QAK HDfprintf(stderr, "%s: bot_row = %u, top_row = %u\n", FUNC, bot_row, top_row); @@ -143,7 +143,7 @@ HDfprintf(stderr, "%s: iblock_addr = %a\n", FUNC, iblock_addr); HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") /* Check for indirect block row */ - while(row < bot_row || row >= top_row) { + while(row < bot_row || row > top_row) { haddr_t new_iblock_addr; /* New indirect block's address */ H5HF_indirect_t *new_iblock; /* Pointer to new indirect block */ unsigned nrows; /* Number of rows in new indirect block */ @@ -196,7 +196,8 @@ HDfprintf(stderr, "%s: row = %u, col = %u\n", FUNC, row, col); } /* end while */ /* Set return parameters */ - *ret_entry = (row * hdr->man_dtable.cparam.width) + col; + if(ret_entry) + *ret_entry = (row * hdr->man_dtable.cparam.width) + col; *ret_iblock = iblock; done: @@ -296,40 +297,22 @@ HDfprintf(stderr, "%s: obj_size = %Zu\n", FUNC, obj_size); HDassert(obj); HDassert(id); - /* Check for indirect section */ - if(sec_node->sect_info.type == H5HF_FSPACE_SECT_INDIRECT) { + /* Check for row section */ + if(sec_node->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW || + sec_node->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW) { #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); -HDfprintf(stderr, "%s: sec_node->u.indirect.iblock = %p\n", FUNC, sec_node->u.indirect.iblock); -if(sec_node->sect_info.state == H5FS_SECT_LIVE && sec_node->u.indirect.iblock) - HDfprintf(stderr, "%s: sec_node->u.indirect.iblock->addr = %a\n", FUNC, sec_node->u.indirect.iblock->addr); -HDfprintf(stderr, "%s: sec_node->u.indirect.row = %u\n", FUNC, sec_node->u.indirect.row); -HDfprintf(stderr, "%s: sec_node->u.indirect.col = %u\n", FUNC, sec_node->u.indirect.col); -HDfprintf(stderr, "%s: sec_node->u.indirect.num_entries = %u\n", FUNC, sec_node->u.indirect.num_entries); -HDfprintf(stderr, "%s: sec_node->u.indirect.indir_row = %u\n", FUNC, sec_node->u.indirect.indir_row); -HDfprintf(stderr, "%s: sec_node->u.indirect.indir_nrows = %u\n", FUNC, sec_node->u.indirect.indir_nrows); +HDfprintf(stderr, "%s: sec_node->sect_info.size = %Hu\n", FUNC, sec_node->sect_info.size); +HDfprintf(stderr, "%s: sec_node->sect_info.type = %s\n", FUNC, (sec_node->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ? "H5HF_FSPACE_SECT_FIRST_ROW" : "H5HF_FSPACE_SECT_NORMAL_ROW")); +HDfprintf(stderr, "%s: sec_node->u.row.under = %p\n", FUNC, sec_node->u.row.under); +HDfprintf(stderr, "%s: sec_node->u.row.row = %u\n", FUNC, sec_node->u.row.row); +HDfprintf(stderr, "%s: sec_node->u.row.col = %u\n", FUNC, sec_node->u.row.col); +HDfprintf(stderr, "%s: sec_node->u.row.num_entries = %u\n", FUNC, sec_node->u.row.num_entries); #endif /* QAK */ - /* Allocate 'single' selection out of 'indirect' selection */ - if(H5HF_man_iblock_alloc_indirect(hdr, dxpl_id, &sec_node) < 0) - 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.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); -HDfprintf(stderr, "%s: sec_node->u.range.iblock = %p\n", FUNC, sec_node->u.range.iblock); -if(sec_node->sect_info.state == H5FS_SECT_LIVE && sec_node->u.range.iblock) - HDfprintf(stderr, "%s: sec_node->u.range.iblock->addr = %a\n", FUNC, sec_node->u.range.iblock->addr); -HDfprintf(stderr, "%s: sec_node->u.range.row = %u\n", FUNC, sec_node->u.range.row); -HDfprintf(stderr, "%s: sec_node->u.range.col = %u\n", FUNC, sec_node->u.range.col); -HDfprintf(stderr, "%s: sec_node->u.range.num_entries = %u\n", FUNC, sec_node->u.range.num_entries); -#endif /* QAK */ - /* Allocate 'single' selection out of 'range' selection */ - 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") + /* Allocate 'single' selection out of 'row' selection */ + if(H5HF_man_iblock_alloc_row(hdr, dxpl_id, &sec_node) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't break up row section") } /* end if */ HDassert(sec_node->sect_info.type == H5HF_FSPACE_SECT_SINGLE); @@ -630,7 +613,7 @@ HDfprintf(stderr, "%s: blk_off = %Zu\n", FUNC, blk_off); 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) + if(H5HF_space_add(hdr, dxpl_id, sec_node, H5FS_ADD_RETURNED_SPACE) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list") done: diff --git a/src/H5HFpkg.h b/src/H5HFpkg.h index d5b4da0..15f0665 100644 --- a/src/H5HFpkg.h +++ b/src/H5HFpkg.h @@ -126,9 +126,10 @@ /* Free space section types for fractal heap */ /* (values stored in free space data structures in file) */ -#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 */ +#define H5HF_FSPACE_SECT_SINGLE 0 /* Section is a range of actual bytes in a direct block */ +#define H5HF_FSPACE_SECT_FIRST_ROW 1 /* Section is first range of blocks in an indirect block row */ +#define H5HF_FSPACE_SECT_NORMAL_ROW 2 /* Section is a range of blocks in an indirect block row */ +#define H5HF_FSPACE_SECT_INDIRECT 3 /* Section is a span of blocks in an indirect block */ /****************************/ /* Package Private Typedefs */ @@ -158,10 +159,15 @@ typedef struct H5HF_dtable_t { hsize_t num_id_first_row; /* Number of IDs in first row of table */ hsize_t *row_block_size; /* Block size per row of indirect block */ hsize_t *row_block_off; /* Cumulative offset per row of indirect block */ - hsize_t *row_dblock_free; /* Free space in dblocks for this row */ + hsize_t *row_tot_dblock_free; /* Total free space in dblocks for this row */ /* (For indirect block rows, it's the total * free space in all direct blocks referenced - * from the indirect block + * from the indirect block) + */ + size_t *row_max_dblock_free; /* Max. free space in dblocks for this row */ + /* (For indirect block rows, it's the maximum + * free space in a direct block referenced + * from the indirect block) */ } H5HF_dtable_t; @@ -205,18 +211,39 @@ typedef struct H5HF_free_section_t { /* (Needed to retrieve root direct block) */ } single; struct { - H5HF_indirect_t *iblock; /* Indirect block for free section */ + struct H5HF_free_section_t *under; /* Pointer to indirect block underlying row section */ unsigned row; /* Row for range of blocks */ unsigned col; /* Column for range of blocks */ unsigned num_entries; /* Number of entries covered */ - } range; + + /* Fields that aren't stored */ + hbool_t checked_out; /* Flag to indicate that a row section is temporarily out of the free space manager */ + } row; struct { - H5HF_indirect_t *iblock; /* Indirect block for free section */ + /* Holds either a pointer to an indirect block (if its "live") or + * the block offset of it's indirect block (if its "serialized") + * (This allows the indirect block that the section is within to + * be compared with other sections, whether its serialized + * or not) + */ + union { + H5HF_indirect_t *iblock; /* Indirect block for free section */ + hsize_t iblock_off; /* Indirect block offset in "heap space" */ + } u; unsigned row; /* Row for range of blocks */ unsigned col; /* Column for range of blocks */ unsigned num_entries; /* Number of entries covered */ - unsigned indir_row; /* Row for indirect range of blocks */ - unsigned indir_nrows; /* Number of rows in indirect blocks */ + + /* Fields that aren't stored */ + struct H5HF_free_section_t *parent; /* Pointer to "parent" indirect section */ + unsigned par_entry; /* Entry within parent indirect section */ + hsize_t span_size; /* Size of space tracked, in "heap space" */ + unsigned iblock_entries; /* Number of entries in indirect block where section is located */ + unsigned rc; /* Reference count of outstanding row & child indirect sections */ + unsigned dir_nrows; /* Number of direct rows in section */ + struct H5HF_free_section_t **dir_rows; /* Array of pointers to outstanding row sections */ + unsigned indir_nents; /* Number of indirect entries in section */ + struct H5HF_free_section_t **indir_ents; /* Array of pointers to outstanding child indirect sections */ } indirect; } u; } H5HF_free_section_t; @@ -332,7 +359,7 @@ typedef struct H5HF_parent_t { typedef struct { H5HF_hdr_t *hdr; /* Fractal heap header */ hid_t dxpl_id; /* DXPL ID for operation */ - H5HF_direct_t *dblock; /* Direct block */ + hbool_t adjoin; /* Whether two spans of blocks adjoin each other */ } H5HF_add_ud1_t; /*****************************/ @@ -351,8 +378,11 @@ 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 H5HF_FSPACE_SECT_CLS_SINGLE[1]; -/* H5HF range section inherits serializable properties from H5FS_section_class_t */ -H5_DLLVAR H5FS_section_class_t H5HF_FSPACE_SECT_CLS_RANGE[1]; +/* H5HF 'first' row section inherits serializable properties from H5FS_section_class_t */ +H5_DLLVAR H5FS_section_class_t H5HF_FSPACE_SECT_CLS_FIRST_ROW[1]; + +/* H5HF 'normal' row section inherits serializable properties from H5FS_section_class_t */ +H5_DLLVAR H5FS_section_class_t H5HF_FSPACE_SECT_CLS_NORMAL_ROW[1]; /* H5HF indirect section inherits serializable properties from H5FS_section_class_t */ H5_DLLVAR H5FS_section_class_t H5HF_FSPACE_SECT_CLS_INDIRECT[1]; @@ -415,9 +445,7 @@ 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, +H5_DLL herr_t H5HF_man_iblock_alloc_row(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, @@ -429,6 +457,8 @@ H5_DLL H5HF_indirect_t *H5HF_man_iblock_protect(H5HF_hdr_t *hdr, hid_t dxpl_id, 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); +H5_DLL herr_t H5HF_man_iblock_entry_addr(H5HF_indirect_t *iblock, unsigned entry, + haddr_t *child_addr); /* Direct block routines */ H5_DLL herr_t H5HF_man_dblock_new(H5HF_hdr_t *fh, hid_t dxpl_id, size_t request, @@ -494,11 +524,11 @@ H5_DLL herr_t H5HF_space_start(H5HF_hdr_t *hdr, hid_t dxpl_id); H5_DLL htri_t H5HF_space_find(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t request, H5HF_free_section_t **node); H5_DLL herr_t H5HF_space_add(H5HF_hdr_t *hdr, hid_t dxpl_id, - H5HF_free_section_t *node); -H5_DLL herr_t H5HF_space_return(H5HF_hdr_t *hdr, hid_t dxpl_id, - H5HF_free_section_t *node); + H5HF_free_section_t *node, unsigned flags); 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); +H5_DLL herr_t H5HF_space_sect_change_class(H5HF_hdr_t *hdr, H5HF_free_section_t *sect, + unsigned new_class); /* Free space section routines */ H5_DLL H5HF_free_section_t *H5HF_sect_single_new(hsize_t sect_off, @@ -508,21 +538,14 @@ 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, +H5_DLL herr_t H5HF_sect_row_revive(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect); +H5_DLL herr_t H5HF_sect_row_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_free_section_t *sect, unsigned *entry_p); +H5_DLL H5HF_indirect_t *H5HF_sect_row_get_iblock(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); + H5HF_indirect_t *iblock, unsigned start_entry, unsigned nentries, + hsize_t *sect_off); /* Testing routines */ #ifdef H5HF_TESTING diff --git a/src/H5HFsection.c b/src/H5HFsection.c index 7fe557b..b12fc2b 100644 --- a/src/H5HFsection.c +++ b/src/H5HFsection.c @@ -12,7 +12,8 @@ * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> +/* + * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> * Monday, May 1, 2006 * * Purpose: Free space section routines for fractal heaps. @@ -31,6 +32,8 @@ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ #include "H5HFpkg.h" /* Fractal heaps */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Vprivate.h" /* Vectors and arrays */ /****************/ /* Local Macros */ @@ -41,6 +44,11 @@ /* Local Typedefs */ /******************/ +/* Typedef for "class private" information for indirect sections */ +typedef struct { + H5HF_hdr_t *hdr; /* Pointer to fractal heap header */ +} H5HF_sect_indirect_private_t; + /********************/ /* Package Typedefs */ @@ -56,47 +64,96 @@ 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 H5FS_section_info_t *H5HF_sect_single_deserialize(const uint8_t *buf, - haddr_t sect_addr, hsize_t sect_size); +static H5FS_section_info_t *H5HF_sect_single_deserialize(const H5FS_section_class_t *cls, + hid_t dxpl_id, const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size, + unsigned *des_flags); 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 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, +static herr_t H5HF_sect_single_valid(const H5FS_section_class_t *cls, + const H5FS_section_info_t *sect); + +/* 'row' section routines */ +static H5HF_free_section_t *H5HF_sect_row_create(haddr_t sect_off, + hsize_t sect_size, hbool_t is_first, unsigned row, unsigned col, + unsigned nentries, H5HF_free_section_t *under_sect); +static herr_t H5HF_sect_row_first(H5HF_hdr_t *hdr, H5HF_free_section_t *sect); +static herr_t H5HF_sect_row_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 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, +static herr_t H5HF_sect_row_iblock_same(const H5HF_free_section_t *sect1, + const H5HF_free_section_t *sect2); + +/* 'row' section callbacks */ +static herr_t H5HF_sect_row_init_cls(H5FS_section_class_t *cls, void *udata); +static herr_t H5HF_sect_row_term_cls(H5FS_section_class_t *cls); +static herr_t H5HF_sect_row_serialize(const H5FS_section_class_t *cls, + const H5FS_section_info_t *sect, uint8_t *buf); +static H5FS_section_info_t *H5HF_sect_row_deserialize(const H5FS_section_class_t *cls, + hid_t dxpl_id, const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size, + unsigned *des_flags); +static htri_t H5HF_sect_row_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, +static herr_t H5HF_sect_row_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, +static htri_t H5HF_sect_row_can_shrink(H5FS_section_info_t *sect, void *udata); -static herr_t H5HF_sect_range_shrink(H5FS_section_info_t **sect, +static herr_t H5HF_sect_row_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); +static herr_t H5HF_sect_row_free(H5FS_section_info_t *sect); +static herr_t H5HF_sect_row_valid(const H5FS_section_class_t *cls, + const H5FS_section_info_t *sect); + +/* 'indirect' section routines */ +static H5HF_free_section_t *H5HF_sect_indirect_new(haddr_t sect_off, + hsize_t sect_size, H5HF_indirect_t *iblock, hsize_t iblock_off, + unsigned row, unsigned col, unsigned nentries); +static herr_t H5HF_sect_indirect_init_rows(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_free_section_t *sect, hbool_t first_child, unsigned space_flags, + unsigned start_row, unsigned start_col, unsigned end_row, unsigned end_col); +static H5HF_free_section_t *H5HF_sect_indirect_for_row(H5HF_hdr_t *hdr, + H5HF_indirect_t *iblock, H5HF_free_section_t *row_sect); +static herr_t H5HF_sect_indirect_decr(H5HF_free_section_t *sect); +static herr_t H5HF_sect_indirect_revive_row(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_free_section_t *sect); +static herr_t H5HF_sect_indirect_revive(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_free_section_t *sect, H5HF_indirect_t *sect_iblock); +static herr_t H5HF_sect_indirect_reduce_row(H5HF_hdr_t *hdr, + H5HF_free_section_t *row_sect, hbool_t *alloc_from_start); +static herr_t H5HF_sect_indirect_reduce(H5HF_hdr_t *hdr, + H5HF_free_section_t *sect, unsigned child_entry); +static herr_t H5HF_sect_indirect_first(H5HF_hdr_t *hdr, H5HF_free_section_t *sect); +static hbool_t H5HF_sect_indirect_is_first(H5HF_free_section_t *sect); +static H5HF_indirect_t * H5HF_sect_indirect_get_iblock(H5HF_free_section_t *sect); +static herr_t H5HF_sect_indirect_span_size(H5HF_hdr_t *hdr, + H5HF_free_section_t *sect); +static herr_t H5HF_sect_indirect_iblock_entries(H5HF_hdr_t *hdr, + H5HF_free_section_t *sect); +static herr_t H5HF_sect_indirect_iblock_same(const H5HF_free_section_t *sect1, + const H5HF_free_section_t *sect2); +static hbool_t H5HF_sect_indirect_is_last_row(const H5HF_free_section_t *row_sect); +static herr_t H5HF_sect_indirect_merge_row(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_free_section_t *sect1, H5HF_free_section_t *sect2); +static herr_t H5HF_sect_indirect_shrink_row(H5HF_free_section_t *row_sect); +static herr_t H5HF_sect_indirect_serialize(H5HF_hdr_t *hdr, + const H5HF_free_section_t *sect, uint8_t *buf); +static H5FS_section_info_t *H5HF_sect_indirect_deserialize(H5HF_hdr_t *hdr, + hid_t dxpl_id, const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size, + unsigned *des_flags); +static herr_t H5HF_sect_indirect_free(H5HF_free_section_t *sect); +static herr_t H5HF_sect_indirect_valid(const H5FS_section_class_t *row_cls, + const H5HF_free_section_t *row_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 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_init_cls(H5FS_section_class_t *cls, void *udata); +static herr_t H5HF_sect_indirect_term_cls(H5FS_section_class_t *cls); static herr_t H5HF_sect_indirect_debug(const H5FS_section_info_t *sect, FILE *stream, int indent, int fwidth); @@ -106,48 +163,104 @@ 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 H5HF_FSPACE_SECT_CLS_SINGLE[1] = {{ + /* Class variables */ H5HF_FSPACE_SECT_SINGLE, /* Section type */ 0, /* Extra serialized size */ + 0, /* Class flags */ + NULL, /* Class private info */ + + /* Class methods */ NULL, /* Initialize section class */ + NULL, /* Terminate section class */ + + /* Object methods */ NULL, /* Serialize section */ H5HF_sect_single_deserialize, /* Deserialize section */ H5HF_sect_single_can_merge, /* Can sections merge? */ H5HF_sect_single_merge, /* Merge sections */ H5HF_sect_single_can_shrink, /* Can section shrink container?*/ - NULL, /* Shrink container w/section */ + H5HF_sect_single_shrink, /* Shrink container w/section */ H5HF_sect_single_free, /* Free section */ + H5HF_sect_single_valid, /* Check validity of section */ NULL, /* Dump debugging for section */ }}; -/* Class info for "range" free space sections */ -H5FS_section_class_t H5HF_FSPACE_SECT_CLS_RANGE[1] = {{ - H5HF_FSPACE_SECT_RANGE, /* Section type */ +/* Class info for "first row" free space sections */ +/* (Same as "normal" row sections, except they also act as a proxy for the + * underlying indirect section + */ +H5FS_section_class_t H5HF_FSPACE_SECT_CLS_FIRST_ROW[1] = {{ + /* Class variables */ + H5HF_FSPACE_SECT_FIRST_ROW, /* 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 */ - 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 */ + 0, /* Class flags */ + NULL, /* Class private info */ + + /* Class methods */ + H5HF_sect_row_init_cls, /* Initialize section class */ + H5HF_sect_row_term_cls, /* Terminate section class */ + + /* Object methods */ + H5HF_sect_row_serialize, /* Serialize section */ + H5HF_sect_row_deserialize, /* Deserialize section */ + H5HF_sect_row_can_merge, /* Can sections merge? */ + H5HF_sect_row_merge, /* Merge sections */ + H5HF_sect_row_can_shrink, /* Can section shrink container?*/ + H5HF_sect_row_shrink, /* Shrink container w/section */ + H5HF_sect_row_free, /* Free section */ + H5HF_sect_row_valid, /* Check validity of section */ + NULL, /* Dump debugging for section */ +}}; + +/* Class info for "normal row" free space sections */ +H5FS_section_class_t H5HF_FSPACE_SECT_CLS_NORMAL_ROW[1] = {{ + /* Class variables */ + H5HF_FSPACE_SECT_NORMAL_ROW, /* Section type */ + 0, /* Extra serialized size */ + H5FS_CLS_GHOST_OBJ, /* Class flags */ + NULL, /* Class private info */ + + /* Class methods */ + NULL, /* Initialize section class */ + NULL, /* Terminate section class */ + + /* Object methods */ + NULL, /* Serialize section */ + NULL, /* Deserialize section */ + H5HF_sect_row_can_merge, /* Can sections merge? */ + H5HF_sect_row_merge, /* Merge sections */ + H5HF_sect_row_can_shrink, /* Can section shrink container?*/ + H5HF_sect_row_shrink, /* Shrink container w/section */ + H5HF_sect_row_free, /* Free section */ + H5HF_sect_row_valid, /* Check validity of section */ + NULL, /* Dump debugging for section */ }}; /* Class info for "indirect" free space sections */ +/* (No object callbacks necessary - objects of this class should never be in + * section manager) + */ H5FS_section_class_t H5HF_FSPACE_SECT_CLS_INDIRECT[1] = {{ + /* Class variables */ H5HF_FSPACE_SECT_INDIRECT, /* Section type */ 0, /* Extra serialized size */ + H5FS_CLS_GHOST_OBJ, /* Class flags */ + NULL, /* Class private info */ + + /* Class methods */ H5HF_sect_indirect_init_cls, /* Initialize section class */ - H5HF_sect_indirect_serialize, /* Serialize section */ - H5HF_sect_indirect_deserialize, /* Deserialize section */ + H5HF_sect_indirect_term_cls, /* Terminate section class */ + + /* Object methods */ + NULL, /* Serialize section */ + NULL, /* Deserialize section */ NULL, /* Can sections merge? */ NULL, /* Merge sections */ NULL, /* Can section shrink container?*/ NULL, /* Shrink container w/section */ - H5HF_sect_indirect_free, /* Free section */ + NULL, /* Free section */ + NULL, /* Check validity of section */ H5HF_sect_indirect_debug, /* Dump debugging for section */ }}; @@ -191,7 +304,6 @@ H5HF_sect_node_new(unsigned sect_type, haddr_t sect_addr, hsize_t sect_size, /* Check arguments. */ HDassert(H5F_addr_defined(sect_addr)); - HDassert(sect_size); /* Create free list section node */ if(NULL == (new_sect = H5FL_MALLOC(H5HF_free_section_t))) @@ -228,7 +340,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5HF_sect_node_free(H5HF_free_section_t *sect, H5HF_indirect_t *parent) +H5HF_sect_node_free(H5HF_free_section_t *sect, H5HF_indirect_t *iblock) { herr_t ret_value = SUCCEED; /* Return value */ @@ -237,9 +349,9 @@ H5HF_sect_node_free(H5HF_free_section_t *sect, H5HF_indirect_t *parent) HDassert(sect); /* Release indirect block, if there was one */ - if(parent) - if(H5HF_iblock_decr(parent) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on parent indirect block") + if(iblock) + if(H5HF_iblock_decr(iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on section's indirect block") /* Release the section */ H5FL_FREE(H5HF_free_section_t, sect); @@ -250,57 +362,6 @@ 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 @@ -479,7 +540,7 @@ H5HF_sect_single_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id, sect->sect_info.size -= amt; /* Re-insert section node into heap's free space */ - if(H5HF_space_add(hdr, dxpl_id, sect) < 0) + if(H5HF_space_add(hdr, dxpl_id, sect, 0) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't re-add single section to free space manager") } /* end else */ @@ -503,8 +564,9 @@ done: *------------------------------------------------------------------------- */ static H5FS_section_info_t * -H5HF_sect_single_deserialize(const uint8_t *buf, haddr_t sect_addr, - hsize_t sect_size) +H5HF_sect_single_deserialize(const H5FS_section_class_t UNUSED *cls, + hid_t UNUSED dxpl_id, const uint8_t *buf, haddr_t sect_addr, + hsize_t sect_size, unsigned UNUSED *des_flags) { H5HF_free_section_t *new_sect; /* New section */ H5FS_section_info_t *ret_value; /* Return value */ @@ -546,18 +608,13 @@ done: */ static htri_t H5HF_sect_single_can_merge(H5FS_section_info_t *_sect1, - H5FS_section_info_t *_sect2, void *_udata) + 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 */ - 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(H5HF_sect_single_can_merge) + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_single_can_merge) /* Check arguments. */ HDassert(sect1); @@ -565,70 +622,18 @@ H5HF_sect_single_can_merge(H5FS_section_info_t *_sect1, 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: 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); +HDfprintf(stderr, "%s: sect1->sect_info = {%a, %Hu, %u, %s}\n", "H5HF_sect_single_can_merge", 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", "H5HF_sect_single_can_merge", 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 */ - 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") - -#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 */ - - /* 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->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) + /* (This can only occur within a direct block, due to the direct block + * overhead at the beginning of a block, so no need to check if sections + * are actually within the same direct block) */ if(H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr)) HGOTO_DONE(TRUE) @@ -656,24 +661,27 @@ done: */ static herr_t H5HF_sect_single_merge(H5FS_section_info_t *_sect1, H5FS_section_info_t *_sect2, - void UNUSED *udata) + 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 */ 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(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->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); +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 */ /* Add second section's size to first section */ @@ -683,11 +691,48 @@ HDfprintf(stderr, "%s: sect2->sect_info.size = %Hu, sect2->sect_info.addr = %a\n 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 - */ + /* Check to see if we should revive first 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") + + /* Check for section occupying entire direct block */ + /* (and not the root direct block) */ + dblock_size = sect1->u.single.dblock_size; + dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr); +#ifdef QAK +HDfprintf(stderr, "%s: dblock_size = %u\n", FUNC, dblock_size); +HDfprintf(stderr, "%s: dblock_overhead = %Zu\n", FUNC, dblock_overhead); +HDfprintf(stderr, "%s: hdr->man_iter_off = %Hu\n", FUNC, hdr->man_iter_off); +#endif /* QAK */ + if((dblock_size - dblock_overhead) == sect1->sect_info.size && + hdr->man_dtable.curr_root_rows > 0) { + 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 'row' section */ + if(H5HF_sect_row_from_single(hdr, sect1, dblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTCONVERT, FAIL, "can't convert single section into row section") + +#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.row = {%p, %u, %u, %u, %t}\n", FUNC, sect1->u.row.under, sect1->u.row.row, sect1->u.row.col, sect1->u.row.num_entries, sect1->u.row.checked_out); +#endif /* QAK */ + + /* 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; + } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) @@ -716,14 +761,15 @@ static htri_t 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 */ +#ifndef NDEBUG H5HF_add_ud1_t *udata = (H5HF_add_ud1_t *)_udata; /* User callback data */ H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */ +#endif /* NDEBUG */ 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(H5HF_sect_single_can_shrink) + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_single_can_shrink) /* Check arguments. */ HDassert(sect); @@ -733,50 +779,101 @@ H5HF_sect_single_can_shrink(H5FS_section_info_t *_sect, void *_udata) 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 */ - /* 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") - /* 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\n", FUNC, dblock_size); +HDfprintf(stderr, "%s: dblock_size = %Zu\n", FUNC, dblock_size); +HDfprintf(stderr, "%s: dblock_overhead = %Zu\n", FUNC, dblock_overhead); #endif /* QAK */ 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 */ + /* We shouldn't ever have a single section that occupies an entire + * direct block, unless it's in the root direct block (and + * therefore there's no parent indirect block to hook into) + */ + HDassert(hdr->man_dtable.curr_root_rows == 0); + HGOTO_DONE(TRUE) + } /* end if */ + else { + /* We shouldn't have a situation where the 'next block' iterator + * is moved before a direct block that still has objects within it. + */ + HDassert(hdr->man_dtable.curr_root_rows == 0 || hdr->man_iter_off > sect->sect_info.addr); + HGOTO_DONE(FALSE) + } /* end else */ - /* Protect the direct block for the section */ - dblock_addr = sect->u.single.dblock_addr; +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HF_sect_single_can_shrink() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_single_shrink + * + * Purpose: Shrink container with section + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, July 17, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_single_shrink(H5FS_section_info_t **_sect, void UNUSED *_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 = udata->hdr; /* Fractal heap header */ + hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */ + H5HF_direct_t *dblock; /* Pointer to direct block for section */ + haddr_t dblock_addr; /* Section's direct block's address */ + 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.type == H5HF_FSPACE_SECT_SINGLE); + +#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); +#endif /* QAK */ + + /* Check to see if we should revive either 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") + + /* Protect the direct block for the section */ + dblock_addr = (*sect)->u.single.dblock_addr; + HDassert(dblock_addr == hdr->man_dtable.table_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, 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)); + if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, + (*sect)->u.single.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 + (*sect)->u.single.dblock_size, (*sect)->sect_info.addr + (*sect)->sect_info.size)); - /* 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; - /* 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; + /* Get rid of section */ + if(H5HF_sect_single_free((H5FS_section_info_t *)*sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node") - /* 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 */ + /* Indicate that the section has been released */ + *sect = NULL; done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5HF_sect_single_can_shrink() */ +} /* H5HF_sect_single_shrink() */ /*------------------------------------------------------------------------- @@ -821,160 +918,248 @@ done: /*------------------------------------------------------------------------- - * Function: H5HF_sect_range_init_cls + * Function: H5HF_sect_single_valid * - * Purpose: Initialize the "range" class structure + * Purpose: Check the validity of a section * * Return: Success: non-negative - * * Failure: negative * * Programmer: Quincey Koziol - * Monday, May 1, 2006 + * Friday, July 21, 2006 * *------------------------------------------------------------------------- */ static herr_t -H5HF_sect_range_init_cls(H5FS_section_class_t *cls, const void UNUSED *udata) +H5HF_sect_single_valid(const H5FS_section_class_t *cls, const H5FS_section_info_t *_sect) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_range_init_cls) + const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Pointer to section to check */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_single_valid) - /* Check arguments. */ HDassert(cls); + HDassert(sect); - /* Set the size of all serialized objects of this class of sections */ - cls->serial_size = 2 /* Row */ - + 2 /* Column */ - + 2; /* # of entries */ +#ifdef QAK +HDfprintf(stderr, "%s: sect->sect_info = {%a, %Hu, %u, %s}\n", "H5HF_sect_single_valid", 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 */ + if(sect->sect_info.state == H5FS_SECT_LIVE) { + /* Check if this section is not in a direct block that is the root direct block */ + /* (not enough information to check on a single section in a root direct block) */ + if(sect->u.single.parent != NULL) { + H5HF_indirect_t *iblock; /* Indirect block that section's direct block resides in */ + H5HF_direct_t *dblock; /* Direct block for section */ + herr_t status; /* Generic status value */ + +#ifdef QAK +HDfprintf(stderr, "%s: sect->u.single = {%p, %u, %a, %Zu}\n", "H5HF_sect_single_valid", sect->u.single.parent, sect->u.single.par_entry, sect->u.single.dblock_addr, sect->u.single.dblock_size); +#endif /* QAK */ + /* Sanity check settings for section's direct block's parent */ + iblock = sect->u.single.parent; + HDassert(H5F_addr_defined(iblock->ents[sect->u.single.par_entry].addr)); + HDassert(H5F_addr_eq(iblock->ents[sect->u.single.par_entry].addr, + sect->u.single.dblock_addr)); + + /* Protect the direct block for the section */ + dblock = H5HF_man_dblock_protect(iblock->hdr, H5AC_dxpl_id, sect->u.single.dblock_addr, sect->u.single.dblock_size, iblock, sect->u.single.par_entry, H5AC_READ); + HDassert(dblock); + + /* Sanity check settings for section */ + HDassert(sect->u.single.dblock_size > 0); + HDassert(sect->u.single.dblock_size == dblock->size); + HDassert(dblock->size > sect->sect_info.size); + HDassert(H5F_addr_lt(dblock->block_off, sect->sect_info.addr)); + HDassert(H5F_addr_ge((dblock->block_off + dblock->size), + (sect->sect_info.addr + sect->sect_info.size))); + + /* Release direct block */ + status = H5AC_unprotect(iblock->hdr->f, H5AC_dxpl_id, H5AC_FHEAP_DBLOCK, sect->u.single.dblock_addr, dblock, H5AC__NO_FLAGS_SET); + HDassert(status >= 0); + } /* end if */ + } /* end if */ FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5HF_sect_range_init_cls() */ +} /* H5HF_sect_single_valid() */ /*------------------------------------------------------------------------- - * Function: H5HF_sect_range_add + * Function: H5HF_sect_row_create * - * Purpose: Add a new 'range' section to the free space manager for this - * heap + * Purpose: Create a new 'row' section + * + * Return: Success: pointer to new section + * + * Failure: NULL + * + * Programmer: Quincey Koziol + * Thursday, July 6, 2006 + * + *------------------------------------------------------------------------- + */ +static H5HF_free_section_t * +H5HF_sect_row_create(haddr_t sect_off, hsize_t sect_size, hbool_t is_first, + unsigned row, unsigned col, unsigned nentries, H5HF_free_section_t *under_sect) +{ + H5HF_free_section_t *sect = NULL; /* 'Row' section created */ + H5HF_free_section_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_row_create) + + /* Check arguments. */ + HDassert(sect_size); + HDassert(nentries); + HDassert(under_sect); + + /* Create 'row' free space section node */ + /* ("inherits" underlying indirect section's state) */ + if(NULL == (sect = H5HF_sect_node_new((unsigned)(is_first ? H5HF_FSPACE_SECT_FIRST_ROW : H5HF_FSPACE_SECT_NORMAL_ROW), sect_off, sect_size, under_sect->sect_info.state))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for row section") + + /* Set the 'row' specific fields */ + sect->u.row.under = under_sect; + sect->u.row.row = row; + sect->u.row.col = col; + sect->u.row.num_entries = nentries; + sect->u.row.checked_out = FALSE; + + /* Set return value */ + ret_value = sect; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HF_sect_row_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_row_from_single + * + * Purpose: Convert a 'single' section into a 'row' section * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu - * May 30 2006 + * July 6 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) +static herr_t +H5HF_sect_row_from_single(H5HF_hdr_t *hdr, H5HF_free_section_t *sect, + H5HF_direct_t *dblock) { - 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) + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_row_from_single) /* * 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 */ + HDassert(sect); + HDassert(dblock); +#ifdef QAK +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")); +HDfprintf(stderr, "%s: dblock->parent = %p\n", FUNC, dblock->parent); +HDfprintf(stderr, "%s: hdr->man_dtable.curr_root_rows = %u\n", FUNC, hdr->man_dtable.curr_root_rows); +#endif /* QAK */ - /* 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") + /* Convert 'single' section information to 'row' section info */ + sect->sect_info.addr = dblock->block_off; + sect->sect_info.type = H5HF_FSPACE_SECT_FIRST_ROW; + sect->u.row.row = dblock->par_entry / hdr->man_dtable.cparam.width; + sect->u.row.col = dblock->par_entry % hdr->man_dtable.cparam.width; + sect->u.row.num_entries = 1; + sect->u.row.checked_out = FALSE; + + /* Create indirect section that underlies the row section */ + if(NULL == (sect->u.row.under = H5HF_sect_indirect_for_row(hdr, dblock->parent, sect))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "serializing row section not supported yet") + + /* Release single section's hold on underlying indirect block */ + if(H5HF_iblock_decr(dblock->parent) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block") 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") + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_sect_row_from_single() */ - /* Release the section */ - H5FL_FREE(H5HF_free_section_t, sect); - } /* end if */ + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_row_iblock_same + * + * Purpose: Check if two row sections are located in the same indirect block + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * July 6 2006 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5HF_sect_row_iblock_same(const H5HF_free_section_t *row_sect1, + const H5HF_free_section_t *row_sect2) +{ + htri_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_row_iblock_same) + + /* + * Check arguments. + */ + HDassert(row_sect1); + HDassert(row_sect2); + + /* Compare the underlying indirect sections */ + ret_value = H5HF_sect_indirect_iblock_same(row_sect1->u.row.under, row_sect2->u.row.under); FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_sect_range_add() */ +} /* end H5HF_sect_row_iblock_same() */ /*------------------------------------------------------------------------- - * Function: H5HF_sect_range_revive + * Function: H5HF_sect_row_revive * - * Purpose: Update the memory information for a 'range' free section + * Purpose: Update the memory information for a 'row' free section * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu - * May 8 2006 + * July 6 2006 * *------------------------------------------------------------------------- */ herr_t -H5HF_sect_range_revive(H5HF_hdr_t *hdr, hid_t dxpl_id, - H5HF_free_section_t *sect) +H5HF_sect_row_revive(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect) { - H5HF_indirect_t *sec_iblock; /* Pointer to section indirect block */ - unsigned sec_entry; /* Entry within section indirect block */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_revive) + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_row_revive) /* * Check arguments. */ HDassert(hdr); HDassert(sect); + HDassert(sect->u.row.under); HDassert(sect->sect_info.state == H5FS_SECT_SERIALIZED); - /* Look up indirect block containing direct blocks for range */ - if(H5HF_man_locate_block(hdr, dxpl_id, sect->sect_info.addr, FALSE, &sec_iblock, &sec_entry, H5AC_READ) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of section") - - /* Increment reference count on indirect block that free section is in */ - if(H5HF_iblock_incr(sec_iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block") - - /* Set the pointer to the section's indirect block */ - sect->u.range.iblock = sec_iblock; - - /* Unlock indirect block */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, sec_iblock->addr, sec_iblock, H5AC__NO_FLAGS_SET) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") - sec_iblock = NULL; - - /* Section is "live" now */ - sect->sect_info.state = H5FS_SECT_LIVE; + /* Pass along "revive" request to underlying indirect section */ + /* (which will mark this section as "live") */ + if(H5HF_sect_indirect_revive_row(hdr, dxpl_id, sect->u.row.under) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTREVIVE, FAIL, "can't revive indirect section") done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_sect_range_revive() */ +} /* end H5HF_sect_row_revive() */ /*------------------------------------------------------------------------- - * Function: H5HF_sect_range_reduce + * Function: H5HF_sect_row_reduce * - * Purpose: Reduce the size of a range section (possibly freeing it) + * Purpose: Reduce the size of a row section (possibly freeing it) * and re-add it back to the free space manager for the heap * (if it hasn't been freed) * @@ -982,186 +1167,316 @@ done: * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu - * May 31 2006 + * July 6 2006 * *------------------------------------------------------------------------- */ herr_t -H5HF_sect_range_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id, - H5HF_free_section_t *sect) +H5HF_sect_row_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect, + unsigned *entry_p) { + hbool_t alloc_from_start; /* Whether to allocate from the end of the row */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_reduce) + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_row_reduce) /* * Check arguments. */ HDassert(hdr); HDassert(sect); - HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_RANGE); + HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW || + sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW); HDassert(sect->sect_info.state == H5FS_SECT_LIVE); + HDassert(entry_p); +#ifdef QAK +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")); +HDfprintf(stderr, "%s: sect->u.row = {%p, %u, %u, %u, %t}\n", FUNC, sect->u.row.under, sect->u.row.row, sect->u.row.col, sect->u.row.num_entries, sect->u.row.checked_out); +#endif /* QAK */ + + /* Mark the row as checked out from the free space manager */ + HDassert(sect->u.row.checked_out == FALSE); + sect->u.row.checked_out = TRUE; + + /* Forward row section to indirect routines, to handle reducing underlying indirect section */ + alloc_from_start = FALSE; + if(H5HF_sect_indirect_reduce_row(hdr, sect, &alloc_from_start) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce underlying section") + + /* Determine entry allocated */ + *entry_p = (sect->u.row.row * hdr->man_dtable.cparam.width) + sect->u.row.col; + if(!alloc_from_start) + *entry_p += (sect->u.row.num_entries - 1); /* 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") + if(sect->u.row.num_entries == 1) { +#ifdef QAK +HDfprintf(stderr, "%s: Freeing row section\n", FUNC); +#endif /* QAK */ + /* Free row section */ + if(H5HF_sect_row_free((H5FS_section_info_t *)sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free row section node") } /* end if */ else { - /* Adjust section information */ - sect->sect_info.addr += hdr->man_dtable.row_block_size[sect->u.range.row]; + /* Check whether to allocate from the beginning or end of the row */ + if(alloc_from_start) { + /* Adjust section start */ + sect->sect_info.addr += hdr->man_dtable.row_block_size[sect->u.row.row]; + sect->u.row.col++; + } /* end else */ - /* Adjust range information */ - sect->u.range.col++; - sect->u.range.num_entries--; + /* Adjust span of blocks covered */ + sect->u.row.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") + /* Check the row back in */ + sect->u.row.checked_out = FALSE; + + /* Add 'row' section back to free space list */ + if(H5HF_space_add(hdr, dxpl_id, sect, 0) < 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_range_reduce() */ +} /* end H5HF_sect_row_reduce() */ /*------------------------------------------------------------------------- - * Function: H5HF_sect_range_from_single + * Function: H5HF_sect_row_first * - * Purpose: Convert a 'single' section into a 'range' section + * Purpose: Make row a "first row" * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu - * May 31 2006 + * July 10 2006 * *------------------------------------------------------------------------- */ static herr_t -H5HF_sect_range_from_single(H5HF_hdr_t *hdr, H5HF_free_section_t *sect, - H5HF_direct_t *dblock) +H5HF_sect_row_first(H5HF_hdr_t *hdr, H5HF_free_section_t *sect) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_range_from_single) + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_row_first) + + /* Sanity check */ + HDassert(hdr); + HDassert(sect); + HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW); + + /* If the row is already checked out from the free space manager, just + * change it's class directly and the free space manager will adjust when + * it is checked back in. + */ + if(sect->u.row.checked_out) + sect->sect_info.type = H5HF_FSPACE_SECT_FIRST_ROW; + else { + /* Change row section to be the "first row" */ + if(H5HF_space_sect_change_class(hdr, sect, H5HF_FSPACE_SECT_FIRST_ROW) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSET, FAIL, "can't set row section to be first row") + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_sect_row_first() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_row_get_iblock + * + * Purpose: Retrieve the indirect block for a row section + * + * Return: Pointer to indirect block on success/NULL on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * July 9 2006 + * + *------------------------------------------------------------------------- + */ +H5HF_indirect_t * +H5HF_sect_row_get_iblock(H5HF_free_section_t *sect) +{ + H5HF_indirect_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_row_get_iblock) /* * 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 */ + HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW || + sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW); + HDassert(sect->sect_info.state == H5FS_SECT_LIVE); - /* 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; + ret_value = H5HF_sect_indirect_get_iblock(sect->u.row.under); - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5HF_sect_range_from_single() */ + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_sect_row_get_iblock() */ /*------------------------------------------------------------------------- - * Function: H5HF_sect_range_serialize + * Function: H5HF_sect_row_init_cls * - * Purpose: Serialize a "live" range section into a buffer + * Purpose: Initialize the "row" section class structure + * + * Note: Since 'row' sections are proxies for 'indirect' sections, this + * routine forwards call to 'indirect' class initialization * * Return: Success: non-negative * * Failure: negative * * Programmer: Quincey Koziol - * Monday, May 1, 2006 + * Monday, July 6, 2006 * *------------------------------------------------------------------------- */ static herr_t -H5HF_sect_range_serialize(const H5FS_section_info_t *_sect, uint8_t *buf) +H5HF_sect_row_init_cls(H5FS_section_class_t *cls, void *_udata) { - const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_range_serialize) + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_row_init_cls) /* Check arguments. */ - HDassert(buf); - HDassert(sect); + HDassert(cls); + HDassert(!cls->cls_private); + + /* Forward call to indirect class initialization */ + if(H5HF_sect_indirect_init_cls(cls, _udata) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize row section class") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HF_sect_row_init_cls() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_row_term_cls + * + * Purpose: Terminate the "row" section class structure + * + * Note: Since 'row' sections are proxies for 'indirect' sections, this + * routine forwards call to 'indirect' class termination + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, July 6, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_row_term_cls(H5FS_section_class_t *cls) +{ + herr_t ret_value = SUCCEED; /* Return value */ - /* Range's row */ - UINT16ENCODE(buf, sect->u.range.row); + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_row_term_cls) - /* Range's column */ - UINT16ENCODE(buf, sect->u.range.col); + /* Check arguments. */ + HDassert(cls); - /* Range's # of entries */ - UINT16ENCODE(buf, sect->u.range.num_entries); + /* Forward call to indirect class termination */ + if(H5HF_sect_indirect_term_cls(cls) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't terminate row section class") - FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5HF_sect_range_serialize() */ +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HF_sect_row_term_cls() */ /*------------------------------------------------------------------------- - * Function: H5HF_sect_range_deserialize + * Function: H5HF_sect_row_serialize * - * Purpose: Deserialize a buffer into a "live" range section + * Purpose: Serialize a "live" row section into a buffer * * Return: Success: non-negative * * Failure: negative * * Programmer: Quincey Koziol - * Monday, May 1, 2006 + * Thursday, July 6, 2006 * *------------------------------------------------------------------------- */ -static H5FS_section_info_t * -H5HF_sect_range_deserialize(const uint8_t *buf, haddr_t sect_addr, - hsize_t sect_size) +static herr_t +H5HF_sect_row_serialize(const H5FS_section_class_t *cls, + const H5FS_section_info_t *_sect, uint8_t *buf) { - H5HF_free_section_t *new_sect; /* New section */ - H5FS_section_info_t *ret_value; /* Return value */ + H5HF_hdr_t *hdr; /* Fractal heap header */ + const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_deserialize) + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_row_serialize) /* Check arguments. */ + HDassert(cls); HDassert(buf); - HDassert(H5F_addr_defined(sect_addr)); - HDassert(sect_size); + HDassert(sect); + HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW); + HDassert(sect->sect_info.addr == sect->u.row.under->sect_info.addr); - /* Create free list section node */ - 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") + /* Forward to indirect routine to serialize underlying section */ + hdr = ((H5HF_sect_indirect_private_t *)(cls->cls_private))->hdr; + if(H5HF_sect_indirect_serialize(hdr, sect->u.row.under, buf) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSERIALIZE, FAIL, "can't serialize row section's underlying indirect section") - /* Range's indirect block */ - /* (Section needs to be "revived" before this is correct) */ - new_sect->u.range.iblock = NULL; +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HF_sect_row_serialize() */ - /* Range's row */ - UINT16DECODE(buf, new_sect->u.range.row); + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_row_deserialize + * + * Purpose: Deserialize a buffer into a "live" row section + * + * Note: Actually this routine just forwards to the 'indirect' + * deserialize routine, which creates the row section. + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Saturday, July 15, 2006 + * + *------------------------------------------------------------------------- + */ +static H5FS_section_info_t * +H5HF_sect_row_deserialize(const H5FS_section_class_t *cls, hid_t dxpl_id, + const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size, + unsigned *des_flags) +{ + H5HF_hdr_t *hdr; /* Fractal heap header */ + H5FS_section_info_t *ret_value; /* Return value */ - /* Range's column */ - UINT16DECODE(buf, new_sect->u.range.col); + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_row_deserialize) - /* Range's # of entries */ - UINT16DECODE(buf, new_sect->u.range.num_entries); + /* Check arguments. */ + HDassert(cls); + HDassert(buf); + HDassert(H5F_addr_defined(sect_addr)); + HDassert(sect_size); - /* Set return value */ - ret_value = (H5FS_section_info_t *)new_sect; + /* Forward to indirect routine to deserialize underlying section */ + hdr = ((H5HF_sect_indirect_private_t *)(cls->cls_private))->hdr; + if(NULL == (ret_value = H5HF_sect_indirect_deserialize(hdr, dxpl_id, buf, + sect_addr, sect_size, des_flags))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDECODE, NULL, "can't deserialize row section's underlying indirect section") done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5HF_sect_range_deserialize() */ +} /* H5HF_sect_row_deserialize() */ /*------------------------------------------------------------------------- - * Function: H5HF_sect_range_can_merge + * Function: H5HF_sect_row_can_merge * * Purpose: Can two sections of this type merge? * @@ -1172,23 +1487,21 @@ done: * Failure: negative * * Programmer: Quincey Koziol - * Monday, June 5, 2006 + * Thursday, July 6, 2006 * *------------------------------------------------------------------------- */ static htri_t -H5HF_sect_range_can_merge(H5FS_section_info_t *_sect1, +H5HF_sect_row_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 */ - 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) + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_row_can_merge) /* Check arguments. */ HDassert(sect1); @@ -1196,80 +1509,65 @@ H5HF_sect_range_can_merge(H5FS_section_info_t *_sect1, 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")); +HDfprintf(stderr, "%s: sect1->sect_info = {%a, %Hu, %u, %s}\n", "H5HF_sect_row_can_merge", 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", "H5HF_sect_row_can_merge", 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 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 to see if we should revive the 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 = 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); +HDfprintf(stderr, "%s: sect1->u.row = {%p, %u, %u, %u, %t}\n", "H5HF_sect_row_can_merge", sect1->u.row.under, sect1->u.row.row, sect1->u.row.col, sect1->u.row.num_entries, sect1->u.row.checked_out); +if(sect2->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW || + sect2->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW) + HDfprintf(stderr, "%s: sect2->u.row = {%p, %u, %u, %u, %t}\n", "H5HF_sect_row_can_merge", sect2->u.row.under, sect2->u.row.row, sect2->u.row.col, sect2->u.row.num_entries, sect2->u.row.checked_out); #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 */ + /* Row section can only merge with other row sections */ + if(!((sect1->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW || + sect1->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW) + && (sect2->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW || + sect2->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW))) + HGOTO_DONE(FALSE) #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); -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: hdr->man_iter_off = %Hu\n", "H5HF_sect_row_can_merge", hdr->man_iter_off); #endif /* QAK */ + /* If second section is after current 'next block' iterator and it's the + * last row in the underlying indirect section, it should go away + */ + if(sect2->sect_info.addr >= hdr->man_iter_off && H5HF_sect_indirect_is_last_row(sect2)) + HGOTO_DONE(TRUE) - /* Range section can only merge with other range sections */ - if(sect1->sect_info.type != sect2->sect_info.type) - HGOTO_DONE(FALSE) + /* Check if second section shares the same underlying indirect block as + * the first section, but doesn't already have same underlying indirect + * section. + */ + if(H5HF_sect_row_iblock_same(sect1, sect2)) { + HDassert((sect1->u.row.row != sect2->u.row.row) || + (((sect1->u.row.col + sect1->u.row.num_entries) - 1) + < sect2->u.row.col)); + if(sect1->u.row.under != sect2->u.row.under) { + size_t dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr); /* Direct block's overhead */ #ifdef QAK -HDfprintf(stderr, "%s: hdr->man_iter_off = %Hu\n", FUNC, hdr->man_iter_off); +HDfprintf(stderr, "%s: dblock_overhead = %Zu\n", "H5HF_sect_row_can_merge", dblock_overhead); #endif /* QAK */ - if(sect2->sect_info.addr >= 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) + /* Check if second section adjoins first section */ + if(H5F_addr_eq(sect1->sect_info.addr + (sect1->u.row.num_entries * (sect1->sect_info.size + dblock_overhead)), sect2->sect_info.addr)) { + udata->adjoin = TRUE; + HGOTO_DONE(TRUE) + } /* end if */ + } /* end if */ + } /* end if */ done: #ifdef QAK -HDfprintf(stderr, "%s: ret_value = %t\n", FUNC, ret_value); +HDfprintf(stderr, "%s: ret_value = %t\n", "H5HF_sect_row_can_merge", ret_value); #endif /* QAK */ FUNC_LEAVE_NOAPI(ret_value) -} /* H5HF_sect_range_can_merge() */ +} /* H5HF_sect_row_can_merge() */ /*------------------------------------------------------------------------- - * Function: H5HF_sect_range_merge + * Function: H5HF_sect_row_merge * * Purpose: Merge two sections of this type * @@ -1280,57 +1578,85 @@ HDfprintf(stderr, "%s: ret_value = %t\n", FUNC, ret_value); * Failure: negative * * Programmer: Quincey Koziol - * Monday, June 5, 2006 + * Thursday, July 6, 2006 * *------------------------------------------------------------------------- */ static herr_t -H5HF_sect_range_merge(H5FS_section_info_t *_sect1, H5FS_section_info_t *_sect2, +H5HF_sect_row_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 */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_merge) + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_row_merge) /* Check arguments. */ HDassert(sect1); - HDassert(sect1->sect_info.type == H5HF_FSPACE_SECT_RANGE); + HDassert(sect1->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW || + sect1->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW); HDassert(sect2); - HDassert(sect2->sect_info.type == H5HF_FSPACE_SECT_RANGE); + HDassert(sect2->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW || + sect2->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW); #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); +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 */ - /* 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; + /* Check to see if we should revive second section */ + if(sect2->sect_info.state != H5FS_SECT_LIVE) + if(H5HF_sect_row_revive(hdr, dxpl_id, sect2) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section") +#ifdef QAK +HDfprintf(stderr, "%s: sect2->u.row = {%p, %u, %u, %u}\n", FUNC, sect2->u.row.under, sect2->u.row.row, sect2->u.row.col, sect2->u.row.num_entries); +#endif /* QAK */ - /* 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 rows adjoin each other */ + /* (as opposed to second row just being after the end of the heap and + * needed to be pruned away) + */ + if(udata->adjoin) { +#ifdef QAK +HDfprintf(stderr, "%s: Merging underlying indirect blocks\n", FUNC); +#endif /* QAK */ + /* Check to see if we should revive first section */ + if(sect1->sect_info.state != H5FS_SECT_LIVE) + if(H5HF_sect_row_revive(hdr, dxpl_id, sect1) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section") +#ifdef QAK +HDfprintf(stderr, "%s: sect1->u.row = {%p, %u, %u, %u}\n", FUNC, sect1->u.row.under, sect1->u.row.row, sect1->u.row.col, sect1->u.row.num_entries); +#endif /* QAK */ - /* 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") + /* Merge rows' underlying indirect sections together */ + if(H5HF_sect_indirect_merge_row(hdr, dxpl_id, sect1, sect2) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTMERGE, FAIL, "can't merge underlying indirect sections") } /* end if */ + else { +#ifdef QAK +HDfprintf(stderr, "%s: Shrinking away second section\n", FUNC); +#endif /* QAK */ + /* Shrink size of underlying indirect section */ + if(H5HF_sect_indirect_shrink_row(sect2) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't shrink underlying indirect section") + + /* Get rid of second section */ + if(H5HF_sect_row_free((H5FS_section_info_t *)sect2) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node") + sect2 = NULL; + } /* end else */ done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5HF_sect_range_merge() */ +} /* H5HF_sect_row_merge() */ /*------------------------------------------------------------------------- - * Function: H5HF_sect_range_can_shrink + * Function: H5HF_sect_row_can_shrink * * Purpose: Can this section shrink the container? * @@ -1343,43 +1669,44 @@ done: * Failure: negative * * Programmer: Quincey Koziol - * Monday, June 5, 2006 + * Thursday, July 6, 2006 * *------------------------------------------------------------------------- */ static htri_t -H5HF_sect_range_can_shrink(H5FS_section_info_t *_sect, void UNUSED *_udata) +H5HF_sect_row_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 */ H5HF_add_ud1_t *udata = (H5HF_add_ud1_t *)_udata; /* User callback data */ H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */ htri_t ret_value = FALSE; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_range_can_shrink) + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_row_can_shrink) /* Check arguments. */ HDassert(sect); - HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_RANGE); + HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW || + sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW); #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); +HDfprintf(stderr, "%s: sect->sect_info = {%a, %Hu, %u, %s}\n", "H5HF_sect_row_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.row = {%p, %u, %u, %u}\n", "H5HF_sect_row_can_shrink", sect->u.row.under, sect->u.row.row, sect->u.row.col, sect->u.row.num_entries); #endif /* QAK */ /* Check if section is past end of "next block" iterator */ #ifdef QAK -HDfprintf(stderr, "%s: hdr->man_iter_off = %Hu\n", "H5HF_sect_range_can_shrink", hdr->man_iter_off); +HDfprintf(stderr, "%s: hdr->man_iter_off = %Hu\n", "H5HF_sect_row_can_shrink", hdr->man_iter_off); #endif /* QAK */ - if(sect->sect_info.addr >= hdr->man_iter_off) + if(sect->sect_info.addr >= hdr->man_iter_off && H5HF_sect_indirect_is_last_row(sect)) HGOTO_DONE(TRUE) done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5HF_sect_range_can_shrink() */ +} /* H5HF_sect_row_can_shrink() */ /*------------------------------------------------------------------------- - * Function: H5HF_sect_range_shrink + * Function: H5HF_sect_row_shrink * * Purpose: Shrink container with section * @@ -1388,30 +1715,35 @@ done: * Failure: negative * * Programmer: Quincey Koziol - * Monday, June 5, 2006 + * Thursday, July 6, 2006 * *------------------------------------------------------------------------- */ static herr_t -H5HF_sect_range_shrink(H5FS_section_info_t **_sect, void UNUSED *_udata) +H5HF_sect_row_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) + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_row_shrink) /* Check arguments. */ HDassert(sect); HDassert(*sect); - HDassert((*sect)->sect_info.type == H5HF_FSPACE_SECT_RANGE); + HDassert((*sect)->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW || + (*sect)->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW); #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); +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")); +HDfprintf(stderr, "%s: (*sect)->u.row = {%p, %u, %u, %u}\n", FUNC, (*sect)->u.row.under, (*sect)->u.row.row, (*sect)->u.row.col, (*sect)->u.row.num_entries); #endif /* QAK */ + /* Shrink size of underlying indirect section */ + if(H5HF_sect_indirect_shrink_row(*sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't shrink underlying indirect section") + /* Get rid of section */ - if(H5HF_sect_range_free((H5FS_section_info_t *)*sect) < 0) + if(H5HF_sect_row_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 */ @@ -1419,88 +1751,344 @@ HDfprintf(stderr, "%s: (*sect).u.range = {%p, %u, %u, %u}\n", FUNC, (*sect)->u.r done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5HF_sect_range_shrink() */ +} /* H5HF_sect_row_shrink() */ /*------------------------------------------------------------------------- - * Function: H5HF_sect_range_free + * Function: H5HF_sect_row_free * - * Purpose: Free a 'range' section node + * Purpose: Free a 'row' section node * * Return: Success: non-negative * * Failure: negative * * Programmer: Quincey Koziol - * Wednesday, May 17, 2006 + * Thursday, July 6, 2006 * *------------------------------------------------------------------------- */ static herr_t -H5HF_sect_range_free(H5FS_section_info_t *_sect) +H5HF_sect_row_free(H5FS_section_info_t *_sect) { H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Pointer to section to free */ - H5HF_indirect_t *parent = NULL; /* Parent indirect block for section */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_free) + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_row_free) HDassert(sect); + HDassert(sect->u.row.under); - /* Check for live reference to an indirect block */ - if(sect->sect_info.state == H5FS_SECT_LIVE) { - /* Get parent indirect block, if there was one */ - if(sect->u.range.iblock) - parent = sect->u.range.iblock; - } /* end if */ + /* Decrement the ref. count on the row section's underlying indirect section */ + if(H5HF_sect_indirect_decr(sect->u.row.under) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't detach section node") /* Release the section */ - if(H5HF_sect_node_free(sect, parent) < 0) + if(H5HF_sect_node_free(sect, NULL) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node") done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5HF_sect_range_free() */ +} /* H5HF_sect_row_free() */ /*------------------------------------------------------------------------- - * Function: H5HF_sect_range_debug + * Function: H5HF_sect_row_valid * - * Purpose: Dump debugging information about an range free space section + * Purpose: Check the validity of a section * * Return: Success: non-negative - * * Failure: negative * * Programmer: Quincey Koziol - * Saturday, May 13, 2006 + * Friday, July 21, 2006 * *------------------------------------------------------------------------- */ static herr_t -H5HF_sect_range_debug(const H5FS_section_info_t *_sect, - FILE *stream, int indent, int fwidth) +H5HF_sect_row_valid(const H5FS_section_class_t *cls, const H5FS_section_info_t *_sect) { - const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Section to dump info */ + const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Pointer to section to check */ + const H5HF_free_section_t *indir_sect; /* Pointer to underlying indirect section */ + unsigned indir_idx; /* Index of row in underlying indirect section's row array */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_range_debug) + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_row_valid) - /* Check arguments. */ + HDassert(cls); HDassert(sect); - /* Print range section information */ - HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, - "Row:", - sect->u.range.row); - HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, - "Column:", - sect->u.range.col); - HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, - "Number of entries:", - sect->u.range.num_entries); +#ifdef QAK +HDfprintf(stderr, "%s: sect->sect_info = {%a, %Hu, %u, %s}\n", "H5HF_sect_row_valid", 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.row = {%p, %u, %u, %u, %t}\n", "H5HF_sect_row_valid", sect->u.row.under, sect->u.row.row, sect->u.row.col, sect->u.row.num_entries, sect->u.row.checked_out); +#endif /* QAK */ + /* Sanity checking on the row */ + HDassert(sect->u.row.under); + HDassert(sect->u.row.num_entries); + HDassert(sect->u.row.checked_out == FALSE); + indir_sect = sect->u.row.under; + indir_idx = sect->u.row.row - indir_sect->u.indirect.row; +#ifdef QAK +HDfprintf(stderr, "%s: indir_idx = %u\n", "H5HF_sect_row_valid", indir_idx); +#endif /* QAK */ + HDassert(indir_sect->u.indirect.dir_rows[indir_idx] == sect); + + /* Different checking for different kinds of rows */ + if(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW) { + /* Some extra sanity checks on the row */ + HDassert(sect->u.row.row == indir_sect->u.indirect.row); + + /* Check that the row's underlying indirect section is valid */ + H5HF_sect_indirect_valid(cls, sect); + } /* end if */ FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5HF_sect_range_debug() */ +} /* H5HF_sect_row_valid() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_indirect_span_size + * + * Purpose: Compute the span size covered by an indirect section + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * July 3 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_indirect_span_size(H5HF_hdr_t *hdr, H5HF_free_section_t *sect) +{ + unsigned start_row; /* Row for first block covered */ + unsigned start_col; /* Column for first block covered */ + unsigned start_entry; /* Entry for first block covered */ + unsigned end_row; /* Row for last block covered */ + unsigned end_col; /* Column for last block covered */ + unsigned end_entry; /* Entry for last block covered */ + hsize_t acc_span_size; /* Accumulated span size */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_span_size) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(sect); + HDassert(sect->u.indirect.num_entries > 0); + + /* Compute starting entry, column & row */ + start_row = sect->u.indirect.row; + start_col = sect->u.indirect.col; + start_entry = (start_row * hdr->man_dtable.cparam.width) + start_col; + + /* Compute ending entry, column & row */ + end_entry = (start_entry + sect->u.indirect.num_entries) - 1; + end_row = end_entry / hdr->man_dtable.cparam.width; + end_col = end_entry % hdr->man_dtable.cparam.width; +#ifdef QAK +HDfprintf(stderr, "%s: start_row = %u, start_col = %u, start_entry = %u\n", "H5HF_sect_indirect_span_size", start_row, start_col, start_entry); +HDfprintf(stderr, "%s: end_row = %u, end_col = %u, end_entry = %u\n", "H5HF_sect_indirect_span_size", end_row, end_col, end_entry); +#endif /* QAK */ + + /* Initialize accumulated span size */ + acc_span_size = 0; + + /* Compute span size covered */ + + /* Check for multi-row span */ + if(start_row != end_row) { + /* Accomodate partial starting row */ + if(start_col > 0) { + acc_span_size = hdr->man_dtable.row_block_size[start_row] * + (hdr->man_dtable.cparam.width - start_col); + start_row++; + } /* end if */ + + /* Accumulate full rows */ + while(start_row < end_row) { + acc_span_size += hdr->man_dtable.row_block_size[start_row] * + hdr->man_dtable.cparam.width; + start_row++; + } /* end while */ + + /* Accomodate partial ending row */ + acc_span_size += hdr->man_dtable.row_block_size[start_row] * + (end_col + 1); + } /* end if */ + else { + /* Span is in same row */ + acc_span_size = hdr->man_dtable.row_block_size[start_row] * + ((end_col - start_col) + 1); + } /* end else */ + + /* Set the span size for the indirect section */ +#ifdef QAK +HDfprintf(stderr, "%s: acc_span_size = %Hu\n", "H5HF_sect_indirect_span_size", acc_span_size); +#endif /* QAK */ + sect->u.indirect.span_size = acc_span_size; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_sect_indirect_span_size() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_indirect_iblock_entries + * + * Purpose: Compute the number of entries for the iblock that an + * indirect section is located in + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * July 3 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_indirect_iblock_entries(H5HF_hdr_t *hdr, H5HF_free_section_t *sect) +{ + unsigned nrows; /* Number of rows in target indirect block */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_iblock_entries) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(sect); + + /* If the section is 'live', just use it's indirect block */ + if(sect->sect_info.state == H5FS_SECT_LIVE) { + HDassert(sect->u.indirect.u.iblock); + nrows = sect->u.indirect.u.iblock->nrows; + } /* end if */ + else { + hsize_t curr_off; /* Current search offset */ + hsize_t iblock_off; /* Temporary copy of indirect block's offset */ + unsigned curr_row, curr_col; /* Current search row & column */ + + /* Set starting offset for search */ + iblock_off = sect->u.indirect.u.iblock_off; + + curr_off = 0; + do { + /* Compute block's new offset */ + iblock_off -= curr_off; + + /* Look up row & column in new indirect block for object */ + if(H5HF_dtable_lookup(&hdr->man_dtable, iblock_off, &curr_row, &curr_col) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of object") + HDassert(curr_row >= hdr->man_dtable.max_direct_rows); + + /* Compute offset of block indicated */ + curr_off = hdr->man_dtable.row_block_off[curr_row] + + hdr->man_dtable.row_block_size[curr_row] * curr_col; + } while(curr_off != iblock_off); + + /* Compute # of rows in indirect block */ + nrows = (H5V_log2_gen(hdr->man_dtable.row_block_size[curr_row]) - hdr->man_dtable.first_row_bits) + 1; +#ifdef QAK +HDfprintf(stderr, "%s: nrows = %u\n", FUNC, nrows); +#endif /* QAK */ + } /* end else */ + HDassert(nrows); + + /* Compute number of entries in indirect block */ + sect->u.indirect.iblock_entries = hdr->man_dtable.cparam.width * nrows; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_sect_indirect_iblock_entries() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_indirect_iblock_same + * + * Purpose: Check if two indirect sections are located in the same indirect block + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * July 6 2006 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5HF_sect_indirect_iblock_same(const H5HF_free_section_t *sect1, + const H5HF_free_section_t *sect2) +{ + htri_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_iblock_same) + + /* + * Check arguments. + */ + HDassert(sect1); + HDassert(sect2); + + ret_value = ((sect1->sect_info.state == H5FS_SECT_LIVE ? sect1->u.indirect.u.iblock->block_off : sect1->u.indirect.u.iblock_off) + == (sect2->sect_info.state == H5FS_SECT_LIVE ? sect2->u.indirect.u.iblock->block_off : sect2->u.indirect.u.iblock_off)); + +#ifdef QAK +HDfprintf(stderr, "%s: Leaving, ret_value = %t\n", "H5HF_sect_indirect_iblock_same", ret_value); +#endif /* QAK */ + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_sect_indirect_iblock_same() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_indirect_is_last_row + * + * Purpose: Check if a row is the last row in an indirect section + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * July 18 2006 + * + *------------------------------------------------------------------------- + */ +static hbool_t +H5HF_sect_indirect_is_last_row(const H5HF_free_section_t *row_sect) +{ + const H5HF_free_section_t *sect; /* Underlying indirect section */ + hbool_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_is_last_row) + + /* + * Check arguments. + */ + HDassert(row_sect); + + /* Check for any child indirect sections or if this row is not the last row */ + sect = row_sect->u.row.under; +#ifdef QAK +HDfprintf(stderr, "%s: sect->u.indirect.indir_nents = %u\n", "H5HF_sect_indirect_is_last_row", sect->u.indirect.indir_nents); +HDfprintf(stderr, "%s: sect->u.indirect.row = %u\n", "H5HF_sect_indirect_is_last_row", sect->u.indirect.row); +HDfprintf(stderr, "%s: sect->u.indirect.dir_nrows = %u\n", "H5HF_sect_indirect_is_last_row", sect->u.indirect.dir_nrows); +HDfprintf(stderr, "%s: row_sect->u.row.row = %u\n", "H5HF_sect_indirect_is_last_row", row_sect->u.row.row); +#endif /* QAK */ + if(sect->u.indirect.indir_nents > 0) + ret_value = FALSE; + else if(((sect->u.indirect.row + sect->u.indirect.dir_nrows) - 1) == + row_sect->u.row.row) + ret_value = TRUE; + else + ret_value = FALSE; + +#ifdef QAK +HDfprintf(stderr, "%s: ret_value = %t\n", "H5HF_sect_indirect_is_last_row", ret_value); +#endif /* QAK */ + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_sect_indirect_is_last_row() */ /*------------------------------------------------------------------------- @@ -1513,99 +2101,595 @@ H5HF_sect_range_debug(const H5FS_section_info_t *_sect, * Failure: negative * * Programmer: Quincey Koziol - * Monday, May 1, 2006 + * Monday, July 3, 2006 * *------------------------------------------------------------------------- */ static herr_t -H5HF_sect_indirect_init_cls(H5FS_section_class_t *cls, const void UNUSED *udata) +H5HF_sect_indirect_init_cls(H5FS_section_class_t *cls, void *_udata) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_init_cls) + H5HF_hdr_t *hdr = (H5HF_hdr_t *)_udata; /* Fractal heap header */ + H5HF_sect_indirect_private_t *cls_prvt; /* Pointer to class private info */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_init_cls) /* Check arguments. */ HDassert(cls); + HDassert(!cls->cls_private); + + /* Allocate & initialize the class-private (i.e. private shared) information + * for this type of section + */ + if(NULL == (cls_prvt = H5MM_malloc(sizeof(H5HF_sect_indirect_private_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + cls_prvt->hdr = hdr; + cls->cls_private = cls_prvt; /* Set the size of all serialized objects of this class of sections */ - cls->serial_size = 2 /* Row */ + cls->serial_size = hdr->heap_off_size /* Indirect block's offset in "heap space" */ + + 2 /* Row */ + 2 /* Column */ - + 2 /* # of entries */ - + 2 /* Indirect row */ - + 2; /* Indirect # of rows */ + + 2; /* # of entries */ - FUNC_LEAVE_NOAPI(SUCCEED) +done: + FUNC_LEAVE_NOAPI(ret_value) } /* H5HF_sect_indirect_init_cls() */ /*------------------------------------------------------------------------- - * Function: H5HF_sect_indirect_add + * Function: H5HF_sect_indirect_term_cls * - * Purpose: Add a new 'indirect' section to the free space manager for this - * heap + * Purpose: Terminate the "indirect" class structure + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, July 3, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_indirect_term_cls(H5FS_section_class_t *cls) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_term_cls) + + /* Check arguments. */ + HDassert(cls); + + /* Free the class private information */ + cls->cls_private = H5MM_xfree(cls->cls_private); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5HF_sect_indirect_term_cls() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_indirect_new + * + * Purpose: Create a new 'indirect' section for other routines to finish + * initializing. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu - * May 30 2006 + * July 6 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) +static H5HF_free_section_t * +H5HF_sect_indirect_new(haddr_t sect_off, hsize_t sect_size, + H5HF_indirect_t *iblock, hsize_t iblock_off, unsigned row, unsigned col, + unsigned nentries) { 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 */ + H5HF_free_section_t *ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_add) + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_new) /* * 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") + if(NULL == (sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_INDIRECT, sect_off, + sect_size, (iblock ? H5FS_SECT_LIVE : H5FS_SECT_SERIALIZED)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "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; + if(iblock) { + sect->u.indirect.u.iblock = iblock; + if(H5HF_iblock_incr(sect->u.indirect.u.iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block") + iblock_incr = TRUE; + } /* end if */ + else + sect->u.indirect.u.iblock_off = iblock_off; 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") + /* Reset the non-stored fields, they are computed later, on demand */ + sect->u.indirect.span_size = 0; + sect->u.indirect.iblock_entries = 0; + + /* This indirect section doesn't (currently) have a parent */ + sect->u.indirect.parent = NULL; + sect->u.indirect.par_entry = 0; + + /* Set return value */ + ret_value = sect; done: - if(ret_value < 0 && sect) { + if(!ret_value && 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") + if(H5HF_iblock_decr(sect->u.indirect.u.iblock) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTDEC, NULL, "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_new() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_indirect_row + * + * Purpose: Create the underlying indirect section for a new row section + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * July 6 2006 + * + *------------------------------------------------------------------------- + */ +static H5HF_free_section_t * +H5HF_sect_indirect_for_row(H5HF_hdr_t *hdr, H5HF_indirect_t *iblock, + H5HF_free_section_t *row_sect) +{ + H5HF_free_section_t *sect = NULL; /* 'Indirect' free space section to add */ + H5HF_free_section_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_for_row) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(iblock); + HDassert(row_sect); + HDassert(row_sect->u.row.row < hdr->man_dtable.max_direct_rows); +#ifdef QAK +HDfprintf(stderr, "%s: Entering\n", FUNC); +#endif /* QAK */ + + /* Create free space section node */ + if(NULL == (sect = H5HF_sect_indirect_new(row_sect->sect_info.addr, + row_sect->sect_info.size, iblock, iblock->block_off, + row_sect->u.row.row, row_sect->u.row.col, row_sect->u.row.num_entries))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't create indirect section") + + /* Set # of direct rows covered */ + sect->u.indirect.dir_nrows = 1; + + /* Allocate space for the derived row sections */ + if(NULL == (sect->u.indirect.dir_rows = H5MM_malloc(sizeof(H5HF_free_section_t *)))) + HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "allocation failed for row section pointer array") + + /* Atatch the new row section to indirect section */ + sect->u.indirect.dir_rows[0] = row_sect; + sect->u.indirect.rc = 1; + + /* No indirect rows in current section */ + sect->u.indirect.indir_nents = 0; + sect->u.indirect.indir_ents = NULL; + + /* Set return value */ + ret_value = sect; + +done: + if(!ret_value && sect) + if(H5HF_sect_indirect_free(sect) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, NULL, "can't free indirect section node") + +#ifdef QAK +HDfprintf(stderr, "%s: Leaving\n", FUNC); +#endif /* QAK */ + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_sect_indirect_for_row() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_indirect_init_rows + * + * Purpose: Initialize the derived row sections for a newly created + * indirect section + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * July 6 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_indirect_init_rows(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_free_section_t *sect, hbool_t first_child, unsigned space_flags, + unsigned start_row, unsigned start_col, + unsigned end_row, unsigned end_col) +{ + hsize_t curr_off; /* Offset of new section in "heap space" */ + size_t dblock_overhead; /* Direct block's overhead */ + unsigned row_entries; /* # of entries in row */ + unsigned row_col; /* Column within current row */ + unsigned curr_entry; /* Current entry within indirect section */ + unsigned curr_indir_entry; /* Current indirect entry within indirect section */ + unsigned curr_row; /* Current row within indirect section */ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_init_rows) +#ifdef QAK +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")); +HDfprintf(stderr, "%s: first_child = %t\n", FUNC, first_child); +HDfprintf(stderr, "%s: start_row = %u, start_col = %u\n", FUNC, start_row, start_col); +HDfprintf(stderr, "%s: end_row = %u, end_col = %u\n", FUNC, end_row, end_col); +#endif /* QAK */ + + /* + * Check arguments. + */ + HDassert(sect); + + /* Reset reference count for indirect section */ + sect->u.indirect.rc = 0; + + /* Set up direct block information, if necessary */ + if(start_row < hdr->man_dtable.max_direct_rows) { + unsigned max_direct_row; /* Max. direct row covered */ + + /* Compute max. direct row covered by indirect section */ + max_direct_row = MIN(end_row, (hdr->man_dtable.max_direct_rows - 1)); + + /* Compute # of direct rows covered */ + sect->u.indirect.dir_nrows = (max_direct_row - start_row) + 1; + + /* Allocate space for the derived row sections */ + if(NULL == (sect->u.indirect.dir_rows = H5MM_malloc(sizeof(H5HF_free_section_t *) * sect->u.indirect.dir_nrows))) + HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for row section pointer array") + } /* end if */ + else { + /* No rows of direct blocks covered, reset direct row information */ + sect->u.indirect.dir_nrows = 0; + sect->u.indirect.dir_rows = NULL; + } /* end else */ + + /* Set up indirect block information, if necessary */ + if(end_row >= hdr->man_dtable.max_direct_rows) { + unsigned indirect_start_row; /* Row to start indirect entries on */ + unsigned indirect_start_col; /* Column to start indirect entries on */ + unsigned indirect_start_entry; /* Index of starting indirect entry */ + unsigned indirect_end_entry; /* Index of ending indirect entry */ + + /* Compute starting indirect entry */ + if(start_row < hdr->man_dtable.max_direct_rows) { + indirect_start_row = hdr->man_dtable.max_direct_rows; + indirect_start_col = 0; + } /* end if */ + else { + indirect_start_row = start_row; + indirect_start_col = start_col; + } /* end else */ + indirect_start_entry = (indirect_start_row * hdr->man_dtable.cparam.width) + + indirect_start_col; + + /* Compute ending indirect entry */ + indirect_end_entry = (end_row * hdr->man_dtable.cparam.width) + + end_col; + + /* Compute # of indirect entries covered */ + sect->u.indirect.indir_nents = (indirect_end_entry - indirect_start_entry) + 1; + + /* Allocate space for the child indirect sections */ + if(NULL == (sect->u.indirect.indir_ents = H5MM_malloc(sizeof(H5HF_free_section_t *) * sect->u.indirect.indir_nents))) + HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for indirect section pointer array") + } /* end if */ + else { + /* No indirect block entries covered, reset indirect row information */ + sect->u.indirect.indir_nents = 0; + sect->u.indirect.indir_ents = NULL; + } /* end else */ + + /* Set up initial row information */ + if(start_row == end_row) + row_entries = (end_col - start_col) + 1; + else + row_entries = hdr->man_dtable.cparam.width - start_col; + row_col = start_col; + + /* Loop over creating the sections covered by this indirect section */ + curr_off = sect->sect_info.addr; + curr_entry = (start_row * hdr->man_dtable.cparam.width) + start_col; + curr_row = 0; + curr_indir_entry = 0; + dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr); + for(u = start_row; u <= end_row; u++, curr_row++) { + if(u < hdr->man_dtable.max_direct_rows) { + H5HF_free_section_t *row_sect = NULL; /* 'Row' free space section to add */ + +#ifdef QAK +HDfprintf(stderr, "%s: Creating direct row, row_col = %u, row_entries = %u\n", FUNC, row_col, row_entries); +#endif /* QAK */ + /* Create 'row' free space section node */ + if(NULL == (row_sect = H5HF_sect_row_create(curr_off, + (hdr->man_dtable.row_block_size[u] - dblock_overhead), first_child, u, row_col, + row_entries, sect))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "creation failed for child row section") + + /* Add new row section to array for indirect section */ + sect->u.indirect.dir_rows[curr_row] = row_sect; + + /* Add new row section to free space manager for the heap */ + if(H5HF_space_add(hdr, dxpl_id, row_sect, space_flags) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add row section to free space") + + /* Add new row section to array for indirect section */ + sect->u.indirect.rc++; + + /* Advance the offset to the next section */ + curr_off += row_entries * hdr->man_dtable.row_block_size[u]; + + /* Advance the current entry to the next row*/ + curr_entry += row_entries; + + /* Reset the 'first child' flag */ + first_child = FALSE; + } /* end if */ + else { + H5HF_indirect_t *child_iblock; /* Child indirect block */ + H5HF_free_section_t *child_sect; /* Child 'indirect' section to add */ + unsigned child_nrows; /* Number of child rows in indirect blocks for this row */ + unsigned child_nentries; /* Number of child entries in indirect blocks for this row */ + unsigned v; /* Local index variable */ + + /* Compute info about row's indirect blocks for child section */ + child_nrows = H5HF_dtable_size_to_rows(&hdr->man_dtable, hdr->man_dtable.row_block_size[u]); + child_nentries = child_nrows * hdr->man_dtable.cparam.width; +#ifdef QAK +HDfprintf(stderr, "%s: child_nrows = %u\n", FUNC, child_nrows); +HDfprintf(stderr, "%s: child_nentries = %u\n", FUNC, child_nentries); +HDfprintf(stderr, "%s: row_entries = %u\n", FUNC, row_entries); +#endif /* QAK */ + + /* Add an indirect section for each indirect block in the row */ + for(v = 0; v < row_entries; v++) { + /* Try to get the child section's indirect block, if it's available */ + if(sect->sect_info.state == H5FS_SECT_LIVE) { + haddr_t child_iblock_addr; /* Child indirect block's address on disk */ + + /* Get the address of the child indirect block */ + if(H5HF_man_iblock_entry_addr(sect->u.indirect.u.iblock, curr_entry, &child_iblock_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to retrieve child indirect block's address") +#ifdef QAK +HDfprintf(stderr, "%s: child_iblock_addr = %a\n", FUNC, child_iblock_addr); +#endif /* QAK */ + + /* If the child indirect block's address is defined, protect it */ + if(H5F_addr_defined(child_iblock_addr)) { + if(NULL == (child_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, child_iblock_addr, child_nrows, NULL, 0, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") + } /* end if */ + else + child_iblock = NULL; + } /* end if */ + else + child_iblock = NULL; + + /* Create free space section node */ + if(NULL == (child_sect = H5HF_sect_indirect_new(curr_off, (hsize_t)0, + child_iblock, curr_off, 0, 0, child_nentries))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section") + + /* Initialize rows for new indirect section */ + if(H5HF_sect_indirect_init_rows(hdr, dxpl_id, child_sect, + first_child, space_flags, 0, 0, (child_nrows - 1), + (hdr->man_dtable.cparam.width - 1)) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize indirect section") + + /* If we have a valid child indirect block, release it now */ + if(child_iblock) + 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") + + /* Attach child section to this section */ + child_sect->u.indirect.parent = sect; + child_sect->u.indirect.par_entry = curr_entry; + sect->u.indirect.indir_ents[curr_indir_entry] = child_sect; + sect->u.indirect.rc++; + + /* Advance the offset for the next section */ + curr_off += hdr->man_dtable.row_block_size[u]; + + /* Advance to the next entry */ + curr_entry++; + curr_indir_entry++; + + /* Reset the 'first child' flag */ + first_child = FALSE; + } /* end for */ + } /* end else */ + + /* Compute the # of entries for the next row */ + if(u < (end_row - 1)) + row_entries = hdr->man_dtable.cparam.width; + else + row_entries = end_col + 1; + + /* Reset column for all other rows */ + row_col = 0; + } /* end for */ + /* Make certain we've tracked the section's dependents correctly */ + HDassert(sect->u.indirect.rc == + (sect->u.indirect.indir_nents + sect->u.indirect.dir_nrows)); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_sect_indirect_init_rows() */ + + +/*------------------------------------------------------------------------- + * 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 + * July 3 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_sect_indirect_add(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_indirect_t *iblock, unsigned start_entry, unsigned nentries, + hsize_t *end_off /*out*/) +{ + H5HF_free_section_t *sect = NULL; /* 'Indirect3' free space section to add */ + hsize_t sect_off; /* Offset of section in heap space */ + unsigned start_row; /* Start row in indirect block */ + unsigned start_col; /* Start column in indirect block */ + unsigned end_entry; /* End entry in indirect block */ + unsigned end_row; /* End row in indirect block */ + unsigned end_col; /* End column in indirect block */ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_add) +#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 */ + start_row = start_entry / hdr->man_dtable.cparam.width; + start_col = start_entry % hdr->man_dtable.cparam.width; + + /* Compute end column & row */ + end_entry = (start_entry + nentries) - 1; + end_row = end_entry / hdr->man_dtable.cparam.width; + end_col = end_entry % hdr->man_dtable.cparam.width; + + /* Initialize information for rows skipped over */ + sect_off = iblock->block_off; + for(u = 0; u < start_row; u++) + sect_off += hdr->man_dtable.row_block_size[u] * hdr->man_dtable.cparam.width; + sect_off += hdr->man_dtable.row_block_size[start_row] * start_col; +#ifdef QAK +HDfprintf(stderr, "%s: sect_off = %Hu\n", FUNC, sect_off); +#endif /* QAK */ + + /* Create free space section node */ + if(NULL == (sect = H5HF_sect_indirect_new(sect_off, (hsize_t)0, iblock, + iblock->block_off, start_row, start_col, nentries))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section") + + /* Initialize rows for new indirect section */ + if(H5HF_sect_indirect_init_rows(hdr, dxpl_id, sect, TRUE, 0, start_row, + start_col, end_row, end_col) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize indirect section") + + /* Get end of section offset to return, if requested */ + if(end_off) { + /* Set the span size of the new section */ + if(H5HF_sect_indirect_span_size(hdr, sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute span size of section") + + /* Compute the end of the section */ + *end_off = sect_off + sect->u.indirect.span_size; +#ifdef QAK +HDfprintf(stderr, "%s: *end_off = %Hu\n", FUNC, *end_off); +#endif /* QAK */ + } /* end if */ + +done: + if(ret_value < 0 && sect) + if(H5HF_sect_indirect_free(sect) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node") + + FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_sect_indirect_add() */ /*------------------------------------------------------------------------- - * Function: H5HF_sect_indirect_revive + * Function: H5HF_sect_indirect_decr + * + * Purpose: Decrement ref. count on indirect section + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * July 6 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_indirect_decr(H5HF_free_section_t *sect) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_decr) + + /* + * Check arguments. + */ + HDassert(sect); + HDassert(sect->u.indirect.rc); +#ifdef QAK +HDfprintf(stderr, "%s: sect->u.indirect.rc = %u\n", FUNC, sect->u.indirect.rc); +#endif /* QAK */ + + /* Decrement ref. count for indirect section */ + sect->u.indirect.rc--; + + /* If the indirect section's ref. count drops to zero, free the section */ + if(sect->u.indirect.rc == 0) { + /* Decrement ref. count on indirect section's parent */ + if(sect->u.indirect.parent) + if(H5HF_sect_indirect_decr(sect->u.indirect.parent) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't decrement ref. count on parent indirect section") + + /* Free indirect section */ + if(H5HF_sect_indirect_free(sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node") + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_sect_indirect_decr() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_indirect_revive_row * * Purpose: Update the memory information for a 'indirect' free section * @@ -1613,19 +2697,18 @@ done: * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu - * May 8 2006 + * July 3 2006 * *------------------------------------------------------------------------- */ -herr_t -H5HF_sect_indirect_revive(H5HF_hdr_t *hdr, hid_t dxpl_id, - H5HF_free_section_t *sect) +static herr_t +H5HF_sect_indirect_revive_row(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect) { H5HF_indirect_t *sec_iblock; /* Pointer to section indirect block */ - unsigned sec_entry; /* Entry within section indirect block */ + unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_revive) + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_revive_row) /* * Check arguments. @@ -1635,7 +2718,11 @@ H5HF_sect_indirect_revive(H5HF_hdr_t *hdr, hid_t dxpl_id, HDassert(sect->sect_info.state == H5FS_SECT_SERIALIZED); /* Look up indirect block containing indirect blocks for section */ - if(H5HF_man_locate_block(hdr, dxpl_id, sect->sect_info.addr, TRUE, &sec_iblock, &sec_entry, H5AC_READ) < 0) +#ifdef QAK +HDfprintf(stderr, "%s: sect->sect_info.addr = %a\n", FUNC, sect->sect_info.addr); +HDfprintf(stderr, "%s: sect->u.indirect.u.iblock_off = %Hu\n", FUNC, sect->u.indirect.u.iblock_off); +#endif /* QAK */ + if(H5HF_man_locate_block(hdr, dxpl_id, sect->sect_info.addr, FALSE, &sec_iblock, NULL, H5AC_READ) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of section") /* Increment reference count on indirect block that free section is in */ @@ -1643,7 +2730,7 @@ H5HF_sect_indirect_revive(H5HF_hdr_t *hdr, hid_t dxpl_id, HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block") /* Set the pointer to the section's indirect block */ - sect->u.indirect.iblock = sec_iblock; + sect->u.indirect.u.iblock = sec_iblock; /* Unlock indirect block */ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, sec_iblock->addr, sec_iblock, H5AC__NO_FLAGS_SET) < 0) @@ -1653,12 +2740,369 @@ H5HF_sect_indirect_revive(H5HF_hdr_t *hdr, hid_t dxpl_id, /* Section is "live" now */ sect->sect_info.state = H5FS_SECT_LIVE; + /* Loop over derived row sections and mark them all as 'live' now */ + for(u = 0; u < sect->u.indirect.dir_nrows; u++) + sect->u.indirect.dir_rows[u]->sect_info.state = H5FS_SECT_LIVE; + + /* Revive parent indirect section, if there is one */ + if(sect->u.indirect.parent && sect->u.indirect.parent->sect_info.state == H5FS_SECT_SERIALIZED) + if(H5HF_sect_indirect_revive(hdr, dxpl_id, sect->u.indirect.parent, sect->u.indirect.u.iblock->parent) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTREVIVE, FAIL, "can't revive indirect section") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_sect_indirect_revive_row() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_indirect_revive + * + * Purpose: Update the memory information for a 'indirect' free section + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * July 10 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_indirect_revive(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_free_section_t *sect, H5HF_indirect_t *sect_iblock) +{ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_revive) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(sect); + HDassert(sect->sect_info.state == H5FS_SECT_SERIALIZED); + HDassert(sect_iblock); + +#ifdef QAK +HDfprintf(stderr, "%s: sect->sect_info.addr = %a\n", FUNC, sect->sect_info.addr); +HDfprintf(stderr, "%s: sect->u.indirect.u.iblock_off = %Hu\n", FUNC, sect->u.indirect.u.iblock_off); +#endif /* QAK */ + /* Increment reference count on indirect block that free section is in */ + if(H5HF_iblock_incr(sect_iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block") + + /* Set the pointer to the section's indirect block */ + sect->u.indirect.u.iblock = sect_iblock; + + /* Section is "live" now */ + sect->sect_info.state = H5FS_SECT_LIVE; + + /* Loop over derived row sections and mark them all as 'live' now */ + for(u = 0; u < sect->u.indirect.dir_nrows; u++) + sect->u.indirect.dir_rows[u]->sect_info.state = H5FS_SECT_LIVE; + + /* Revive parent indirect section, if there is one */ + if(sect->u.indirect.parent && sect->u.indirect.parent->sect_info.state == H5FS_SECT_SERIALIZED) + if(H5HF_sect_indirect_revive(hdr, dxpl_id, sect->u.indirect.parent, sect->u.indirect.u.iblock->parent) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTREVIVE, FAIL, "can't revive indirect section") + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_sect_indirect_revive() */ /*------------------------------------------------------------------------- + * Function: H5HF_sect_indirect_reduce_row + * + * Purpose: Remove a block from an 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 + * July 10 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_indirect_reduce_row(H5HF_hdr_t *hdr, H5HF_free_section_t *row_sect, + hbool_t *alloc_from_start) +{ + H5HF_free_section_t *sect; /* Indirect3 section underlying row section */ + unsigned row_start_entry; /* Entry for first block covered in row section */ + unsigned row_end_entry; /* Entry for last block covered in row section */ + unsigned row_entry; /* Entry to allocate in row section */ + unsigned start_entry; /* Entry for first block covered */ + unsigned start_row; /* Start row in indirect block */ + unsigned start_col; /* Start column in indirect block */ + unsigned end_entry; /* Entry for last block covered */ + unsigned end_row; /* End row in indirect block */ + unsigned end_col; /* End column in indirect block */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_reduce_row) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(row_sect); + + /* Compute starting & ending information for row section */ + row_start_entry = (row_sect->u.row.row * hdr->man_dtable.cparam.width) + row_sect->u.row.col; + row_end_entry = (row_start_entry + row_sect->u.row.num_entries) - 1; +#ifdef QAK +HDfprintf(stderr, "%s: row_sect->sect_info = {%a, %Hu, %u, %s}\n", FUNC, row_sect->sect_info.addr, row_sect->sect_info.size, row_sect->sect_info.type, (row_sect->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED")); +HDfprintf(stderr, "%s: row_sect->u.row.row = %u, row_sect->u.row.col = %u, row_sect->u.row.num_entries = %u\n", FUNC, row_sect->u.row.row, row_sect->u.row.col, row_sect->u.row.num_entries); +HDfprintf(stderr, "%s: row_start_entry = %u, row_end_entry = %u\n", FUNC, row_start_entry, row_end_entry); +#endif /* QAK */ + + /* Compute starting & ending information for indirect section */ + sect = row_sect->u.row.under; + start_row = sect->u.indirect.row; + start_col = sect->u.indirect.col; + start_entry = (start_row * hdr->man_dtable.cparam.width) + start_col; + end_entry = (start_entry + sect->u.indirect.num_entries) - 1; + end_row = end_entry / hdr->man_dtable.cparam.width; + end_col = end_entry % hdr->man_dtable.cparam.width; + + /* Additional sanity check */ + HDassert(sect->u.indirect.dir_rows); + HDassert(sect->u.indirect.dir_rows[(row_sect->u.row.row - start_row)] == row_sect); +#ifdef QAK +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")); +HDfprintf(stderr, "%s: sect->u.indirect.parent = %p, sect->u.indirect.par_entry = %u\n", FUNC, sect->u.indirect.parent, sect->u.indirect.par_entry); +HDfprintf(stderr, "%s: start_entry = %u, start_row = %u, start_col = %u\n", FUNC, start_entry, start_row, start_col); +HDfprintf(stderr, "%s: end_entry = %u, end_row = %u, end_col = %u\n", FUNC, end_entry, end_row, end_col); +#endif /* QAK */ + + /* Check if we should allocate from end of indirect section */ + if(row_end_entry == end_entry && start_row != end_row) { + *alloc_from_start = FALSE; + row_entry = row_end_entry; +#ifdef QAK +HDfprintf(stderr, "%s: Row is at end of indirect section\n", FUNC); +#endif /* QAK */ + } /* end if */ + else { + *alloc_from_start = TRUE; + row_entry = row_start_entry; +#ifdef QAK +HDfprintf(stderr, "%s: Row is NOT at end of indirect section\n", FUNC); +#endif /* QAK */ + } /* end else */ +#ifdef QAK +HDfprintf(stderr, "%s: row_entry = %u\n", FUNC, row_entry); +#endif /* QAK */ + + /* Check if we have a parent section to be detached from */ + if(sect->u.indirect.parent) { + hbool_t is_first; /* Flag to indicate that this section is the first section in hierarchy */ + + /* Check if this section is the first section */ + is_first = H5HF_sect_indirect_is_first(sect); + + /* Remove this indirect section from parent indirect section */ + if(H5HF_sect_indirect_reduce(hdr, sect->u.indirect.parent, sect->u.indirect.par_entry) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce parent indirect section") + sect->u.indirect.parent = NULL; + sect->u.indirect.par_entry = 0; + + /* If we weren't the first section, set "first row" for this indirect section */ + if(!is_first) + if(H5HF_sect_indirect_first(hdr, sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for indirect section") + } /* end if */ + + /* Adjust indirect section's span size, if it's set */ + if(sect->u.indirect.span_size > 0) + sect->u.indirect.span_size -= row_sect->sect_info.size; + + /* Check how to adjust section for allocated entry */ + if(sect->u.indirect.num_entries > 1) { + if(row_entry == start_entry) { +#ifdef QAK +HDfprintf(stderr, "%s: Entry is at start of indirect section\n", FUNC); +#endif /* QAK */ + /* Adjust section start */ + sect->sect_info.addr += hdr->man_dtable.row_block_size[sect->u.indirect.row]; + + /* Adjust block coordinates of span */ + sect->u.indirect.col++; + if(sect->u.indirect.col == hdr->man_dtable.cparam.width) { + HDassert(row_sect->u.row.num_entries == 1); + + /* Adjust direct row information */ + sect->u.indirect.dir_nrows--; +#ifdef QAK +HDfprintf(stderr, "%s: sect->u.indirect.dir_nrows = %u\n", FUNC, sect->u.indirect.dir_nrows); +#endif /* QAK */ + + /* Adjust direct row sections for indirect section */ + if(sect->u.indirect.dir_nrows > 0) { + HDmemmove(§->u.indirect.dir_rows[0], + §->u.indirect.dir_rows[1], + sect->u.indirect.dir_nrows * sizeof(H5HF_free_section_t *)); + HDassert(sect->u.indirect.dir_rows[0]); + + /* Make new "first row" in indirect section */ + if(row_sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW) + if(H5HF_sect_row_first(hdr, sect->u.indirect.dir_rows[0]) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for indirect section") + } /* end if */ + else { + /* Sanity check */ + HDassert(sect->u.indirect.indir_ents); + + /* Eliminate direct rows for this section */ + sect->u.indirect.dir_rows = H5MM_xfree(sect->u.indirect.dir_rows); + + /* Make new "first row" in indirect section */ + if(row_sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW) + if(H5HF_sect_indirect_first(hdr, sect->u.indirect.indir_ents[0]) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for child indirect section") + } /* end else */ + + sect->u.indirect.row++; + sect->u.indirect.col = 0; + } /* end if */ + + /* Adjust number of entries covered */ + sect->u.indirect.num_entries--; + } /* end if */ + else if(row_entry == end_entry) { + unsigned new_end_row; /* New end row for entries */ + +#ifdef QAK +HDfprintf(stderr, "%s: Entry is at end of indirect section\n", FUNC); +#endif /* QAK */ + /* Sanity check */ + HDassert(sect->u.indirect.indir_ents == NULL); + + /* Adjust number of entries covered */ + sect->u.indirect.num_entries--; + + /* Check for eliminating a direct row */ + new_end_row = ((start_entry + sect->u.indirect.num_entries) - 1) / hdr->man_dtable.cparam.width; + HDassert(new_end_row <= end_row); + if(new_end_row < end_row) { + HDassert(new_end_row == (end_row - 1)); + sect->u.indirect.dir_nrows--; + } /* end if */ + } /* end if */ + else { + H5HF_free_section_t *peer_sect; /* Peer indirect section */ + H5HF_indirect_t *iblock; /* Pointer to indirect block for this section */ + hsize_t iblock_off; /* Section's indirect block's offset in "heap space" */ + unsigned peer_nentries; /* Number of entries in new peer indirect section */ + unsigned peer_dir_nrows; /* Number of direct rows in new peer indirect section */ + unsigned new_start_row; /* New starting row for current indirect section */ + unsigned u; /* Local index variable */ + +#ifdef QAK +HDfprintf(stderr, "%s: Entry is in middle of indirect section\n", FUNC); +#endif /* QAK */ + /* Sanity checks */ + HDassert(row_sect->u.row.col == 0); + HDassert(row_sect->u.row.row > 0); + HDassert(row_sect->u.row.row < hdr->man_dtable.max_direct_rows); + HDassert(row_sect->u.row.num_entries == hdr->man_dtable.cparam.width); + HDassert(row_sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW); + + /* Compute basic information about peer & current indirect sections */ + new_start_row = row_sect->u.row.row; + peer_nentries = row_entry - start_entry; + peer_dir_nrows = new_start_row - start_row; +#ifdef QAK +HDfprintf(stderr, "%s: peer_nentries = %u, peer_dir_nrows = %u\n", FUNC, peer_nentries, peer_dir_nrows); +HDfprintf(stderr, "%s: new_start_row = %u\n", FUNC, new_start_row); +#endif /* QAK */ + + /* Get indirect block information for peer */ + if(sect->sect_info.state == H5FS_SECT_LIVE) { + iblock = sect->u.indirect.u.iblock; + iblock_off = sect->u.indirect.u.iblock->block_off; + } /* end if */ + else { + iblock = NULL; + iblock_off = sect->u.indirect.u.iblock_off; + } /* end else */ +#ifdef QAK +HDfprintf(stderr, "%s: iblock = %p, iblock_off = %Hu\n", FUNC, iblock, iblock_off); +#endif /* QAK */ + + /* Create peer indirect section */ + if(NULL == (peer_sect = H5HF_sect_indirect_new(sect->sect_info.addr, + sect->sect_info.size, iblock, iblock_off, start_row, start_col, + peer_nentries))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section") + + /* Set up direct row & indirect entry information for peer section */ + peer_sect->u.indirect.dir_nrows = peer_dir_nrows; + if(NULL == (peer_sect->u.indirect.dir_rows = H5MM_malloc(sizeof(H5HF_free_section_t *) * peer_dir_nrows))) + HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for row section pointer array") + peer_sect->u.indirect.indir_nents = 0; + peer_sect->u.indirect.indir_ents = NULL; + + /* Transfer row sections between current & peer sections */ + HDmemcpy(&peer_sect->u.indirect.dir_rows[0], + §->u.indirect.dir_rows[0], + (sizeof(H5HF_free_section_t *) * peer_dir_nrows)); + HDmemmove(§->u.indirect.dir_rows[0], + §->u.indirect.dir_rows[peer_dir_nrows], + (sizeof(H5HF_free_section_t *) * (sect->u.indirect.dir_nrows - peer_dir_nrows))); + sect->u.indirect.dir_nrows -= peer_dir_nrows; + HDassert(row_sect == sect->u.indirect.dir_rows[0]); + + /* Re-target transferred row sections to point to new underlying indirect section */ + for(u = 0; u < peer_dir_nrows; u++) + peer_sect->u.indirect.dir_rows[u]->u.row.under = peer_sect; + + /* Change first row section in indirect section to be the "first row" */ + /* (But we don't have to tell the free space manager about it, + * because the row section is "checked out" from the free space + * manager currently. + */ + row_sect->sect_info.type = H5HF_FSPACE_SECT_FIRST_ROW; + + /* Adjust reference counts for current & peer sections */ + peer_sect->u.indirect.rc = peer_dir_nrows; + sect->u.indirect.rc -= peer_dir_nrows; + + /* Transfer/update cached information about indirect block */ + peer_sect->u.indirect.iblock_entries = sect->u.indirect.iblock_entries; + peer_sect->u.indirect.span_size = row_sect->sect_info.addr - peer_sect->sect_info.addr; + if(sect->u.indirect.span_size > 0) + /* (span for row section has already been removed) */ + sect->u.indirect.span_size -= peer_sect->u.indirect.span_size; + + /* Update information for current section */ + sect->sect_info.addr = row_sect->sect_info.addr + hdr->man_dtable.row_block_size[new_start_row]; + sect->u.indirect.row = new_start_row; + sect->u.indirect.col = row_sect->u.row.col + 1; + sect->u.indirect.num_entries -= (peer_nentries + 1); /* Transferred entries, plus the entry allocated out of the row */ + + /* Make certain we've tracked the sections' dependents correctly */ + HDassert(sect->u.indirect.rc == + (sect->u.indirect.indir_nents + sect->u.indirect.dir_nrows)); + HDassert(peer_sect->u.indirect.rc == + (peer_sect->u.indirect.indir_nents + peer_sect->u.indirect.dir_nrows)); + } /* end else */ + } /* end if */ + else { + sect->u.indirect.num_entries--; + sect->u.indirect.dir_nrows--; + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_sect_indirect_reduce_row() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_sect_indirect_reduce * * Purpose: Reduce the size of a indirect section (possibly freeing it) @@ -1669,14 +3113,20 @@ done: * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu - * May 31 2006 + * July 10 2006 * *------------------------------------------------------------------------- */ -herr_t -H5HF_sect_indirect_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id, - H5HF_free_section_t *sect) +static herr_t +H5HF_sect_indirect_reduce(H5HF_hdr_t *hdr, H5HF_free_section_t *sect, + unsigned child_entry) { + unsigned start_entry; /* Entry for first block covered */ + unsigned start_row; /* Start row in indirect block */ + unsigned start_col; /* Start column in indirect block */ + unsigned end_entry; /* Entry for last block covered */ + unsigned end_row; /* End row in indirect block */ + unsigned end_col; /* End column in indirect block */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_reduce) @@ -1686,34 +3136,624 @@ H5HF_sect_indirect_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id, */ HDassert(hdr); HDassert(sect); - HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_INDIRECT); - HDassert(sect->sect_info.state == H5FS_SECT_LIVE); +#ifdef QAK +HDfprintf(stderr, "%s: child_entry = %u\n", FUNC, child_entry); +#endif /* QAK */ - /* 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") + /* Compute starting & ending information for indirect section */ + start_row = sect->u.indirect.row; + start_col = sect->u.indirect.col; + start_entry = (start_row * hdr->man_dtable.cparam.width) + start_col; + end_entry = (start_entry + sect->u.indirect.num_entries) - 1; + end_row = end_entry / hdr->man_dtable.cparam.width; + end_col = end_entry % hdr->man_dtable.cparam.width; +#ifdef QAK +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")); +HDfprintf(stderr, "%s: sect->u.indirect.parent = %p, sect->u.indirect.par_entry = %u\n", FUNC, sect->u.indirect.parent, sect->u.indirect.par_entry); +HDfprintf(stderr, "%s: start_entry = %u, start_row = %u, start_col = %u\n", FUNC, start_entry, start_row, start_col); +HDfprintf(stderr, "%s: end_entry = %u, end_row = %u, end_col = %u\n", FUNC, end_entry, end_row, end_col); +#endif /* QAK */ + + /* Check how to adjust section for allocated entry */ + if(sect->u.indirect.num_entries > 1) { + /* Check if we have a parent section to be detached from */ + if(sect->u.indirect.parent) { + hbool_t is_first; /* Flag to indicate that this section is the first section in hierarchy */ + + /* Check if this section is the first section */ + is_first = H5HF_sect_indirect_is_first(sect); + + /* Reduce parent indirect section */ + if(H5HF_sect_indirect_reduce(hdr, sect->u.indirect.parent, sect->u.indirect.par_entry) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce parent indirect section") + sect->u.indirect.parent = NULL; + sect->u.indirect.par_entry = 0; + + /* If we weren't the first section, set "first row" for this indirect section */ + if(!is_first) + if(H5HF_sect_indirect_first(hdr, sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for indirect section") + } /* end if */ + + /* Check if we can allocate from start of indirect section */ + if(child_entry == start_entry) { +#ifdef QAK +HDfprintf(stderr, "%s: Child is at start of indirect section\n", FUNC); +#endif /* QAK */ + /* Sanity check */ + HDassert(sect->u.indirect.dir_rows == NULL); + HDassert(sect->u.indirect.indir_ents); + + /* Adjust section start */ + sect->sect_info.addr += hdr->man_dtable.row_block_size[start_row]; + + /* Adjust span of blocks covered */ + sect->u.indirect.col++; + if(sect->u.indirect.col == hdr->man_dtable.cparam.width) { + sect->u.indirect.row++; + sect->u.indirect.col = 0; + } /* end if */ + sect->u.indirect.num_entries--; + if(sect->u.indirect.span_size > 0) + sect->u.indirect.span_size -= hdr->man_dtable.row_block_size[start_row]; + + /* Adjust indirect entry information */ + sect->u.indirect.indir_nents--; + HDmemmove(§->u.indirect.indir_ents[0], + §->u.indirect.indir_ents[1], + sect->u.indirect.indir_nents * sizeof(H5HF_free_section_t *)); + HDassert(sect->u.indirect.indir_ents[0]); + + /* Make new "first row" in new first indirect child section */ + if(H5HF_sect_indirect_first(hdr, sect->u.indirect.indir_ents[0]) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for child indirect section") + } /* end if */ + else if(child_entry == end_entry) { +#ifdef QAK +HDfprintf(stderr, "%s: Child is at end of indirect section\n", FUNC); +#endif /* QAK */ + /* Sanity check */ + HDassert(sect->u.indirect.indir_ents); + + /* Adjust span of blocks covered */ + sect->u.indirect.num_entries--; + if(sect->u.indirect.span_size > 0) + sect->u.indirect.span_size -= hdr->man_dtable.row_block_size[end_row]; + + /* Adjust indirect entry information */ + sect->u.indirect.indir_nents--; + if(sect->u.indirect.indir_nents == 0) + sect->u.indirect.indir_ents = H5MM_xfree(sect->u.indirect.indir_ents); + } /* end if */ + else { + H5HF_free_section_t *peer_sect; /* Peer indirect section */ + H5HF_indirect_t *iblock; /* Pointer to indirect block for this section */ + hsize_t iblock_off; /* Section's indirect block's offset in "heap space" */ + haddr_t peer_sect_addr; /* Address of new peer section in "heap space" */ + unsigned peer_nentries; /* Number of entries in new peer indirect section */ + unsigned peer_start_row; /* Starting row for new peer indirect section */ + unsigned peer_start_col; /* Starting column for new peer indirect section */ + unsigned child_row; /* Row where child entry is located */ + unsigned new_nentries; /* New number of entries for current indirect section */ + unsigned old_nentries; /* Old number of entries for current indirect section */ + unsigned u; /* Local index variable */ + +#ifdef QAK +HDfprintf(stderr, "%s: Child is in middle of indirect section\n", FUNC); +#endif /* QAK */ + /* Sanity check */ + HDassert(sect->u.indirect.indir_ents); + + /* Compute basic information about peer & current indirect sections */ + peer_nentries = end_entry - child_entry; + peer_start_row = (child_entry + 1) / hdr->man_dtable.cparam.width; + peer_start_col = (child_entry + 1) % hdr->man_dtable.cparam.width; + child_row = child_entry / hdr->man_dtable.cparam.width; + new_nentries = sect->u.indirect.num_entries - (peer_nentries + 1); + old_nentries = sect->u.indirect.num_entries; +#ifdef QAK +HDfprintf(stderr, "%s: peer_nentries = %u, peer_start_row = %u, peer_start_col = %u\n", FUNC, peer_nentries, peer_start_row, peer_start_col); +HDfprintf(stderr, "%s: new_nentries = %u\n", FUNC, new_nentries); +#endif /* QAK */ + + /* Get indirect block information for peer */ + if(sect->sect_info.state == H5FS_SECT_LIVE) { + iblock = sect->u.indirect.u.iblock; + iblock_off = sect->u.indirect.u.iblock->block_off; + } /* end if */ + else { + iblock = NULL; + iblock_off = sect->u.indirect.u.iblock_off; + } /* end else */ +#ifdef QAK +HDfprintf(stderr, "%s: iblock = %p, iblock_off = %Hu\n", FUNC, iblock, iblock_off); +#endif /* QAK */ + + /* Update the number of entries in current section & calculate it's span size */ + /* (Will use this to compute the section address for th peer section */ + sect->u.indirect.num_entries = new_nentries; + if(H5HF_sect_indirect_span_size(hdr, sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute span size of section") +#ifdef QAK +HDfprintf(stderr, "%s: sect->u.indirect.span_size = %Hu\n", FUNC, sect->u.indirect.span_size); +#endif /* QAK */ + + /* Compute address of peer indirect section */ + peer_sect_addr = sect->sect_info.addr; + peer_sect_addr += sect->u.indirect.span_size; + peer_sect_addr += hdr->man_dtable.row_block_size[child_row]; +#ifdef QAK +HDfprintf(stderr, "%s: peer_sect_addr = %a\n", FUNC, peer_sect_addr); +#endif /* QAK */ + + /* Create peer indirect section */ + if(NULL == (peer_sect = H5HF_sect_indirect_new(peer_sect_addr, + sect->sect_info.size, iblock, iblock_off, peer_start_row, + peer_start_col, peer_nentries))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section") + + /* Set up direct row & indirect entry information for peer section */ + peer_sect->u.indirect.dir_nrows = 0; + peer_sect->u.indirect.dir_rows = NULL; + peer_sect->u.indirect.indir_nents = peer_nentries; + if(NULL == (peer_sect->u.indirect.indir_ents = H5MM_malloc(sizeof(H5HF_free_section_t *) * peer_nentries))) + HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for indirect section pointer array") + + /* Transfer child indirect sections between current & peer sections */ + HDmemcpy(&peer_sect->u.indirect.indir_ents[0], + §->u.indirect.indir_ents[old_nentries - peer_nentries], + (sizeof(H5HF_free_section_t *) * peer_nentries)); + sect->u.indirect.indir_nents -= (peer_nentries + 1); /* Transferred blocks, plus child entry */ +#ifdef QAK +HDfprintf(stderr, "%s: sect->u.indirect.indir_nents = %u, old_nentries = %u\n", FUNC, sect->u.indirect.indir_nents, old_nentries); +#endif /* QAK */ + + /* Re-target transferred row sections to point to new underlying indirect section */ + for(u = 0; u < peer_nentries; u++) + peer_sect->u.indirect.indir_ents[u]->u.indirect.parent = peer_sect; + + /* Make new "first row" in peer section */ + if(H5HF_sect_indirect_first(hdr, peer_sect->u.indirect.indir_ents[0]) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for peer indirect section") + + /* Adjust reference counts for current & peer sections */ + peer_sect->u.indirect.rc = peer_nentries; + sect->u.indirect.rc -= peer_nentries; +#ifdef QAK +HDfprintf(stderr, "%s: sect->u.indirect.rc = %u\n", FUNC, sect->u.indirect.rc); +HDfprintf(stderr, "%s: peer_sect->u.indirect.rc = %u\n", FUNC, peer_sect->u.indirect.rc); +#endif /* QAK */ + + /* Transfer cached information about indirect block */ + peer_sect->u.indirect.iblock_entries = sect->u.indirect.iblock_entries; + + /* Make certain we've tracked the sections' dependents correctly */ + /* (Note modified on current section's ref. count, since we haven't + * detached the child section yet) + */ + HDassert((sect->u.indirect.rc - 1) == + (sect->u.indirect.indir_nents + sect->u.indirect.dir_nrows)); + HDassert(peer_sect->u.indirect.rc == + (peer_sect->u.indirect.indir_nents + peer_sect->u.indirect.dir_nrows)); + } /* end else */ } /* 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") + sect->u.indirect.indir_nents--; } /* end else */ + /* Decrement # of sections which depend on this row */ + /* (Must be last as section can be freed) */ + if(H5HF_sect_indirect_decr(sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't decrement section's ref. count ") + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_sect_indirect_reduce() */ /*------------------------------------------------------------------------- + * Function: H5HF_sect_indirect_is_first + * + * Purpose: Check if indirect section is first in all parents + * + * Return: Non-negative (TRUE/FALSE) on success/<can't fail> + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * July 17 2006 + * + *------------------------------------------------------------------------- + */ +static hbool_t +H5HF_sect_indirect_is_first(H5HF_free_section_t *sect) +{ + hbool_t ret_value = FALSE; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_is_first) + + /* Sanity check */ + HDassert(sect); + + /* Recurse to parent */ + if(sect->u.indirect.parent) { + if(sect->sect_info.addr == sect->u.indirect.parent->sect_info.addr) + ret_value = H5HF_sect_indirect_is_first(sect->u.indirect.parent); + } /* end if */ + else + ret_value = TRUE; + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_sect_indirect_first() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_indirect_first + * + * Purpose: Make new 'first row' for indirect section + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * July 10 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_indirect_first(H5HF_hdr_t *hdr, H5HF_free_section_t *sect) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_first) + + /* Sanity check */ + HDassert(hdr); + HDassert(sect); + + /* Check if this indirect section has direct block rows */ + if(sect->u.indirect.dir_nrows > 0) { + /* Sanity checks */ + HDassert(sect->u.indirect.row == 0); + HDassert(sect->u.indirect.col == 0); + HDassert(sect->u.indirect.dir_rows[0]); + + /* Change first row section in indirect section to be the "first row" */ + if(H5HF_sect_row_first(hdr, sect->u.indirect.dir_rows[0]) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSET, FAIL, "can't set row section to be first row") + } /* end if */ + else { + /* Sanity checks */ + HDassert(sect->u.indirect.indir_nents > 0); + HDassert(sect->u.indirect.indir_ents[0]); + + /* Forward to first child indirect section */ + if(H5HF_sect_indirect_first(hdr, sect->u.indirect.indir_ents[0]) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSET, FAIL, "can't set child indirect section to be first row") + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_sect_indirect_first() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_indirect_get_iblock + * + * Purpose: Retrieve the indirect block for a indirect section + * + * Return: Pointer to indirect block on success/NULL on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * July 9 2006 + * + *------------------------------------------------------------------------- + */ +static H5HF_indirect_t * +H5HF_sect_indirect_get_iblock(H5HF_free_section_t *sect) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_get_iblock) + + /* + * Check arguments. + */ + HDassert(sect); + HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_INDIRECT); + HDassert(sect->sect_info.state == H5FS_SECT_LIVE); + + FUNC_LEAVE_NOAPI(sect->u.indirect.u.iblock) +} /* end H5HF_sect_indirect_get_iblock() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_indirect_merge_row + * + * Purpose: Merge two sections of this type + * + * Note: Second section always merges into first node + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Tuesday, July 18, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_indirect_merge_row(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_free_section_t *row_sect1, H5HF_free_section_t *row_sect2) +{ + H5HF_free_section_t *sect1, *sect2; /* Indirect sections underlying row sections */ + hsize_t iblock_off1, iblock_off2; /* The offset of the indirect blocks for the indirect sections (in "heap space") */ + unsigned start_entry1; /* Start entry for section #1 */ + unsigned start_row1, start_col1; /* Starting row & column for section #1 */ + unsigned end_entry1; /* End entry for section #1 */ + unsigned end_row1, end_col1; /* Ending row & column for section #1 */ + unsigned start_entry2; /* Start entry for section #2 */ + unsigned start_row2, start_col2; /* Starting row & column for section #2 */ + unsigned end_row2, end_col2; /* Ending row & column for section #2 */ + unsigned end_entry2; /* End entry for section #2 */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_merge_row) + + /* Sanity check parameters */ + HDassert(hdr); + HDassert(row_sect1); + HDassert(row_sect1->u.row.under); + HDassert(row_sect1->sect_info.state == H5FS_SECT_LIVE); + HDassert(row_sect2); + HDassert(row_sect2->u.row.under); + HDassert(row_sect2->sect_info.state == H5FS_SECT_LIVE); + HDassert(row_sect2->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW); + + /* Set up indirect section information */ + sect1 = row_sect1->u.row.under; + sect2 = row_sect2->u.row.under; +#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 */ + + /* Sanity check some assumptions about the indirect sections */ + HDassert(sect1->u.indirect.dir_nrows > 0); + HDassert(sect1->u.indirect.dir_rows); + HDassert(sect1->u.indirect.indir_nents == 0); + HDassert(sect1->u.indirect.indir_ents == NULL); + HDassert(sect2->u.indirect.dir_nrows > 0); + HDassert(sect2->u.indirect.dir_rows); + + /* Set up span information */ + start_row1 = sect1->u.indirect.row; + start_col1 = sect1->u.indirect.col; + start_entry1 = (start_row1 * hdr->man_dtable.cparam.width) + start_col1; + end_entry1 = (start_entry1 + sect1->u.indirect.num_entries) - 1; + end_row1 = end_entry1 / hdr->man_dtable.cparam.width; + end_col1 = end_entry1 % hdr->man_dtable.cparam.width; + HDassert(end_row1 == row_sect1->u.row.row); +#ifdef QAK +HDfprintf(stderr, "%s: start_row1 = %u, start_col1 = %u, start_entry1 = %u\n", FUNC, start_row1, start_col1, start_entry1); +HDfprintf(stderr, "%s: sect1->u.indirect.num_entries = %u\n", FUNC, sect1->u.indirect.num_entries); +HDfprintf(stderr, "%s: end_row1 = %u, end_col1 = %u, end_entry1 = %u\n", FUNC, end_row1, end_col1, end_entry1); +#endif /* QAK */ + start_row2 = sect2->u.indirect.row; + start_col2 = sect2->u.indirect.col; + start_entry2 = (start_row2 * hdr->man_dtable.cparam.width) + start_col2; + end_entry2 = (start_entry2 + sect2->u.indirect.num_entries) - 1; + end_row2 = end_entry2 / hdr->man_dtable.cparam.width; + end_col2 = end_entry2 % hdr->man_dtable.cparam.width; + HDassert(start_row2 == row_sect2->u.row.row); +#ifdef QAK +HDfprintf(stderr, "%s: start_row2 = %u, start_col2 = %u, start_entry2 = %u\n", FUNC, start_row2, start_col2, start_entry2); +HDfprintf(stderr, "%s: sect2->u.indirect.num_entries = %u\n", FUNC, sect2->u.indirect.num_entries); +HDfprintf(stderr, "%s: end_row2 = %u, end_col2 = %u, end_entry2 = %u\n", FUNC, end_row2, end_col2, end_entry2); +#endif /* QAK */ + if(sect1->sect_info.state == H5FS_SECT_LIVE) + iblock_off1 = sect1->u.indirect.u.iblock->block_off; + else + iblock_off1 = sect1->u.indirect.u.iblock_off; + if(sect2->sect_info.state == H5FS_SECT_LIVE) + iblock_off2 = sect2->u.indirect.u.iblock->block_off; + else + iblock_off2 = sect2->u.indirect.u.iblock_off; +#ifdef QAK +HDfprintf(stderr, "%s: iblock_off1 = %Hu\n", FUNC, iblock_off1); +HDfprintf(stderr, "%s: iblock_off2 = %Hu\n", FUNC, iblock_off2); +#endif /* QAK */ + + /* Determine if the two indirect sections are in the same indirect block */ + if(iblock_off1 == iblock_off2) { + unsigned src_row2; /* Source row for copying from second section */ + unsigned new_dir_nrows; /* New value for number of direct rows in first section */ + unsigned nrows_moved; /* Number of rows to move from second section to first */ + unsigned u; /* Local index variable */ + +#ifdef QAK +HDfprintf(stderr, "%s: sect1->u.indirect.dir_nrows = %u\n", FUNC, sect1->u.indirect.dir_nrows); +HDfprintf(stderr, "%s: sect2->u.indirect.dir_nrows = %u\n", FUNC, sect2->u.indirect.dir_nrows); +#endif /* QAK */ + + /* Check for sections sharing a row */ + if(end_row1 == start_row2) { +#ifdef QAK +HDfprintf(stderr, "%s: Sections share a row\n", FUNC); +#endif /* QAK */ + + /* Adjust info for first row section, to absorb second row section */ + HDassert((row_sect1->u.row.col + row_sect1->u.row.num_entries) == row_sect2->u.row.col); + row_sect1->u.row.num_entries += row_sect2->u.row.num_entries; + + /* Set up parameters for transfer of rows */ + src_row2 = 1; + nrows_moved = sect2->u.indirect.dir_nrows - 1; + new_dir_nrows = (sect1->u.indirect.dir_nrows + sect2->u.indirect.dir_nrows) - 1; + } /* end if */ + else { +#ifdef QAK +HDfprintf(stderr, "%s: Sections don't share a row\n", FUNC); +#endif /* QAK */ + + /* Set up parameters for transfer of rows */ + src_row2 = 0; + nrows_moved = sect2->u.indirect.dir_nrows; + new_dir_nrows = sect1->u.indirect.dir_nrows + sect2->u.indirect.dir_nrows; + } /* end else */ +#ifdef QAK +HDfprintf(stderr, "%s: src_row2 = %u\n", FUNC, src_row2); +HDfprintf(stderr, "%s: nrows_moved = %u\n", FUNC, nrows_moved); +HDfprintf(stderr, "%s: new_dir_nrows = %u\n", FUNC, new_dir_nrows); +#endif /* QAK */ + + /* Check if we need to move additional rows */ + if(nrows_moved > 0) { + /* Extend the first section's row array */ + if(NULL == (sect1->u.indirect.dir_rows = H5MM_realloc(sect1->u.indirect.dir_rows, sizeof(H5HF_free_section_t *) * new_dir_nrows))) + HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for row section pointer array") + + /* Transfer the second section's rows to first section */ + HDmemcpy(§1->u.indirect.dir_rows[sect1->u.indirect.dir_nrows], + §2->u.indirect.dir_rows[src_row2], + (sizeof(H5HF_free_section_t *) * nrows_moved)); + + /* Re-target the row sections moved from second section */ + for(u = sect1->u.indirect.dir_nrows; u < new_dir_nrows; u++) + sect1->u.indirect.dir_rows[u]->u.row.under = sect1; + + /* Adjust reference counts to account for transferred rows */ + sect1->u.indirect.rc += nrows_moved; + sect2->u.indirect.rc -= nrows_moved; + } /* end if */ + + /* Check for indirect sections in second section */ + if(sect2->u.indirect.indir_nents > 0) { + HDassert(sect2->u.indirect.rc > 0); + HDassert(sect2->u.indirect.indir_ents); + + /* Copy over any child indirect sections in second section */ + + /* Re-target the child indirect sections moved from second section */ + + /* Adjust reference counts for transferred child indirect sections */ + +HDfprintf(stderr, "%s: moving child indirect sections between indirect sections not supported yet!\n", FUNC); +HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "moving child indirect sections between two indirect sections not supported yet") + } /* end if */ + + /* Update information for first section */ + sect1->u.indirect.dir_nrows = new_dir_nrows; + sect1->u.indirect.num_entries += sect2->u.indirect.num_entries; + if(sect1->u.indirect.span_size) { + if(sect2->u.indirect.span_size) + sect1->u.indirect.span_size += sect2->u.indirect.span_size; + else + sect1->u.indirect.span_size = 0; + } /* end if */ + if(sect1->u.indirect.iblock_entries == 0) + sect1->u.indirect.iblock_entries = sect2->u.indirect.iblock_entries; + + /* Make certain we've tracked the first section's dependents correctly */ + HDassert(sect1->u.indirect.rc == + (sect1->u.indirect.indir_nents + sect1->u.indirect.dir_nrows)); + + /* Wrap up, for indirect sections not sharing a row */ + /* (want this to be after the first indirection section is consistent again) */ + if(end_row1 == start_row2) { +#ifdef QAK +HDfprintf(stderr, "%s: Finishing sections share a row\n", FUNC); +#endif /* QAK */ + /* Release second row section */ + /* (also releases second indirect section, since all of it's other + * dependents are gone) + */ + HDassert(sect2->u.indirect.rc == 1); + if(H5HF_sect_row_free((H5FS_section_info_t *)row_sect2) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free row section") + } /* end if */ + else { +#ifdef QAK +HDfprintf(stderr, "%s: Finishing sections don't share a row\n", FUNC); +#endif /* QAK */ + /* Decrement ref. count on second indirect section's parent */ + HDassert(sect2->u.indirect.rc == 0); + if(sect2->u.indirect.parent) + if(H5HF_sect_indirect_decr(sect2->u.indirect.parent) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't decrement ref. count on parent indirect section") + + /* Free second indirect section */ + if(H5HF_sect_indirect_free(sect2) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node") + + /* Re-add the second section's first row */ + /* (it's already been added to first section, but it's been removed + * from the free space manager and needs to be re-added) + */ +#ifdef QAK +HDfprintf(stderr, "%s: Re-inserting second row section\n", FUNC); +#endif /* QAK */ + row_sect2->sect_info.type = H5HF_FSPACE_SECT_NORMAL_ROW; + HDassert(row_sect2->u.row.under == sect1); + if(H5HF_space_add(hdr, dxpl_id, row_sect2, H5FS_ADD_RETURNED_SPACE) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't re-add second row section to free space") +#ifdef QAK +HDfprintf(stderr, "%s: Done re-inserting second row section\n", FUNC); +#endif /* QAK */ + } /* end else */ + } /* end if */ + else { +HDfprintf(stderr, "%s: merging two indirect sections in different indirect blocks not supported yet!\n", FUNC); +HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "merging two indirect sections in different indirect blocks not supported yet") + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_sect_indirect_merge_row() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_indirect_shrink_row + * + * Purpose: "Shrink" an indirect by eliminating it's last row + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * Tuesday, July 18, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_indirect_shrink_row(H5HF_free_section_t *row_sect) +{ + H5HF_free_section_t *sect; /* Indirect section underlying row section */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_shrink_row) + + /* Sanity check parameters */ + HDassert(row_sect); + HDassert(row_sect->u.row.under); + + /* Set up indirect section information */ + sect = row_sect->u.row.under; + + /* Sanity check some assumptions about the indirect section */ + HDassert(sect->u.indirect.dir_nrows > 0); + HDassert(sect->u.indirect.dir_rows); + HDassert(sect->u.indirect.indir_nents == 0); + HDassert(sect->u.indirect.indir_ents == NULL); + + /* Decrement the number of rows */ + /* (other cleanup will be taken care of when the section is freed) */ + sect->u.indirect.dir_nrows--; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_sect_indirect_shrink_row() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_sect_indirect_serialize * * Purpose: Serialize a "live" indirect section into a buffer @@ -1723,37 +3763,70 @@ done: * Failure: negative * * Programmer: Quincey Koziol - * Monday, May 1, 2006 + * Monday, July 3, 2006 * *------------------------------------------------------------------------- */ static herr_t -H5HF_sect_indirect_serialize(const H5FS_section_info_t *_sect, uint8_t *buf) +H5HF_sect_indirect_serialize(H5HF_hdr_t *hdr, const H5HF_free_section_t *sect, + uint8_t *buf) { - const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_serialize) + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_serialize) /* Check arguments. */ + HDassert(hdr); + HDassert(sect); HDassert(buf); - HDassert(_sect); - - /* Range's row */ - UINT16ENCODE(buf, sect->u.indirect.row); +#ifdef QAK +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 */ - /* Range's column */ - UINT16ENCODE(buf, sect->u.indirect.col); + /* Check if this indirect section has a parent & forward if this section is first */ + if(sect->u.indirect.parent) { + if(sect->sect_info.addr == sect->u.indirect.parent->sect_info.addr) + if(H5HF_sect_indirect_serialize(hdr, sect->u.indirect.parent, buf) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSERIALIZE, FAIL, "can't serialize indirect section's parent indirect section") + } /* end if */ + else { + /* Indirect range's indirect block's block offset */ + if(sect->sect_info.state == H5FS_SECT_LIVE) { + HDassert(sect->u.indirect.u.iblock); + UINT64ENCODE_VAR(buf, sect->u.indirect.u.iblock->block_off, hdr->heap_off_size); +#ifdef QAK +HDfprintf(stderr, "%s: sect->u.indirect.u.iblock->block_off = %Hu\n", FUNC, sect->u.indirect.u.iblock->block_off); +#endif /* QAK */ + } /* end if */ + else +{ + UINT64ENCODE_VAR(buf, sect->u.indirect.u.iblock_off, hdr->heap_off_size); +#ifdef QAK +HDfprintf(stderr, "%s: sect->u.indirect.u.iblock_off = %Hu\n", FUNC, sect->u.indirect.u.iblock_off); +#endif /* QAK */ +} - /* Range's # of entries */ - UINT16ENCODE(buf, sect->u.indirect.num_entries); + /* Indirect range's row */ + UINT16ENCODE(buf, sect->u.indirect.row); +#ifdef QAK +HDfprintf(stderr, "%s: sect->u.indirect.row = %u\n", FUNC, sect->u.indirect.row); +#endif /* QAK */ - /* Range's indirect row */ - UINT16ENCODE(buf, sect->u.indirect.indir_row); + /* Indirect range's column */ + UINT16ENCODE(buf, sect->u.indirect.col); +#ifdef QAK +HDfprintf(stderr, "%s: sect->u.indirect.col = %u\n", FUNC, sect->u.indirect.col); +#endif /* QAK */ - /* Range's indirect # of rows */ - UINT16ENCODE(buf, sect->u.indirect.indir_nrows); + /* Indirect range's # of entries */ + UINT16ENCODE(buf, sect->u.indirect.num_entries); +#ifdef QAK +HDfprintf(stderr, "%s: sect->u.indirect.num_entries = %u\n", FUNC, sect->u.indirect.num_entries); +#endif /* QAK */ + } /* end else */ - FUNC_LEAVE_NOAPI(SUCCEED) +done: + FUNC_LEAVE_NOAPI(ret_value) } /* H5HF_sect_indirect_serialize() */ @@ -1767,42 +3840,81 @@ H5HF_sect_indirect_serialize(const H5FS_section_info_t *_sect, uint8_t *buf) * Failure: negative * * Programmer: Quincey Koziol - * Monday, May 1, 2006 + * Monday, July 3, 2006 * *------------------------------------------------------------------------- */ static H5FS_section_info_t * -H5HF_sect_indirect_deserialize(const uint8_t *buf, haddr_t sect_addr, - hsize_t sect_size) +H5HF_sect_indirect_deserialize(H5HF_hdr_t *hdr, hid_t dxpl_id, + const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size, + unsigned *des_flags) { - H5HF_free_section_t *new_sect; /* New section */ + H5HF_free_section_t *new_sect; /* New indirect section */ + hsize_t iblock_off; /* Indirect block's offset */ + unsigned start_row; /* Indirect3 section's start row */ + unsigned start_col; /* Indirect3 section's start column */ + unsigned nentries; /* Indirect3 section's number of entries */ + unsigned start_entry; /* Start entry in indirect block */ + unsigned end_entry; /* End entry in indirect block */ + unsigned end_row; /* End row in indirect block */ + unsigned end_col; /* End column in indirect block */ H5FS_section_info_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_deserialize) /* Check arguments. */ + HDassert(hdr); HDassert(buf); HDassert(H5F_addr_defined(sect_addr)); HDassert(sect_size); +#ifdef QAK +HDfprintf(stderr, "%s: sect_addr = %a, sect_size = %Hu\n", FUNC, sect_addr, sect_size); +#endif /* QAK */ - /* Create free list section node */ - 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") + /* Indirect range's indirect block's block offset */ + UINT64DECODE_VAR(buf, iblock_off, hdr->heap_off_size); +#ifdef QAK +HDfprintf(stderr, "%s: iblock_off = %Hu\n", FUNC, iblock_off); +#endif /* QAK */ + + /* Indirect3 section's row */ + UINT16DECODE(buf, start_row); +#ifdef QAK +HDfprintf(stderr, "%s: start_row = %u\n", FUNC, start_row); +#endif /* QAK */ + + /* Indirect3 section's column */ + UINT16DECODE(buf, start_col); +#ifdef QAK +HDfprintf(stderr, "%s: start_col = %u\n", FUNC, start_col); +#endif /* QAK */ + + /* Indirect3 section's # of entries */ + UINT16DECODE(buf, nentries); +#ifdef QAK +HDfprintf(stderr, "%s: nentries = %u\n", FUNC, nentries); +#endif /* QAK */ - /* Range's row */ - UINT16DECODE(buf, new_sect->u.indirect.row); + /* Create free space section node */ + if(NULL == (new_sect = H5HF_sect_indirect_new(sect_addr, sect_size, NULL, + iblock_off, start_row, start_col, nentries))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't create indirect section") - /* Range's column */ - UINT16DECODE(buf, new_sect->u.indirect.col); + /* Compute start entry */ + start_entry = (start_row * hdr->man_dtable.cparam.width) + start_col; - /* Range's # of entries */ - UINT16DECODE(buf, new_sect->u.indirect.num_entries); + /* Compute end column & row */ + end_entry = (start_entry + nentries) - 1; + end_row = end_entry / hdr->man_dtable.cparam.width; + end_col = end_entry % hdr->man_dtable.cparam.width; - /* Range's indirect row */ - UINT16DECODE(buf, new_sect->u.indirect.indir_row); + /* Initialize rows for new indirect section */ + if(H5HF_sect_indirect_init_rows(hdr, dxpl_id, new_sect, TRUE, H5FS_ADD_DESERIALIZING, + new_sect->u.indirect.row, new_sect->u.indirect.col, end_row, end_col) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't initialize indirect section") - /* Range's indirect # of rows */ - UINT16DECODE(buf, new_sect->u.indirect.indir_nrows); + /* Indicate that this section shouldn't be added to free space manager's list */ + *des_flags |= H5FS_DESERIALIZE_NO_ADD; /* Set return value */ ret_value = (H5FS_section_info_t *)new_sect; @@ -1822,30 +3934,35 @@ done: * Failure: negative * * Programmer: Quincey Koziol - * Wednesday, May 17, 2006 + * Monday, July 3, 2006 * *------------------------------------------------------------------------- */ static herr_t -H5HF_sect_indirect_free(H5FS_section_info_t *_sect) +H5HF_sect_indirect_free(H5HF_free_section_t *sect) { - H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Pointer to section to free */ - H5HF_indirect_t *parent = NULL; /* Parent indirect block for section */ - herr_t ret_value = SUCCEED; /* Return value */ + H5HF_indirect_t *iblock = NULL; /* Indirect block for section */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_free) HDassert(sect); + /* Release the memory for tracking direct rows */ + sect->u.indirect.dir_rows = H5MM_xfree(sect->u.indirect.dir_rows); + + /* Release the memory for tracking indirect entries */ + sect->u.indirect.indir_ents = H5MM_xfree(sect->u.indirect.indir_ents); + /* Check for live reference to an indirect block */ if(sect->sect_info.state == H5FS_SECT_LIVE) { - /* Get parent indirect block, if there was one */ - if(sect->u.indirect.iblock) - parent = sect->u.indirect.iblock; + /* Get indirect block, if there was one */ + if(sect->u.indirect.u.iblock) + iblock = sect->u.indirect.u.iblock; } /* end if */ /* Release the sections */ - if(H5HF_sect_node_free(sect, parent) < 0) + if(H5HF_sect_node_free(sect, iblock) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node") done: @@ -1854,6 +3971,101 @@ done: /*------------------------------------------------------------------------- + * Function: H5HF_sect_indirect_valid + * + * Purpose: Check the validity of a section + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * Friday, July 21, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_indirect_valid(const H5FS_section_class_t *row_cls, const H5HF_free_section_t *row_sect) +{ + const H5HF_free_section_t *sect; /* Pointer to underlying indirect section */ + H5HF_sect_indirect_private_t *cls_prvt; /* Pointer to class private info */ + const H5HF_hdr_t *hdr; /* Fractal heap header */ + hsize_t iblock_off; /* Indirect block's offset in "heap space" */ + unsigned start_row; /* Row for first block covered */ + unsigned start_col; /* Column for first block covered */ + unsigned start_entry; /* Entry for first block covered */ + unsigned end_row; /* Row for last block covered */ + unsigned end_col; /* Column for last block covered */ + unsigned end_entry; /* Entry for last block covered */ + unsigned dir_nrows; /* Number of direct rows in section */ + unsigned u; /* Local index variable */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_valid) + + /* Sanity check arguments */ + HDassert(row_cls); + HDassert(row_sect); + + /* Set up indirect section */ + sect = row_sect->u.row.under; + cls_prvt = row_cls->cls_private; + hdr = cls_prvt->hdr; + HDassert(sect); + HDassert(hdr); +#ifdef QAK +HDfprintf(stderr, "%s: sect->sect_info = {%a, %Hu, %u, %s}\n", "H5HF_sect_indirect_valid", 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")); +if(sect->sect_info.state == H5FS_SECT_LIVE) + HDfprintf(stderr, "%s: sect->u.indirect = {%p, ", "H5HF_sect_indirect_valid", sect->u.indirect.u.iblock); +else + HDfprintf(stderr, "%s: sect->u.indirect = {%Hu, ", "H5HF_sect_indirect_valid", sect->u.indirect.u.iblock_off); +HDfprintf(stderr, "%u, %u, %u}\n", sect->u.indirect.row, sect->u.indirect.col, sect->u.indirect.num_entries); +#endif /* QAK */ + + /* Retrieve the indirect block's offset */ + if(sect->sect_info.state == H5FS_SECT_LIVE) + iblock_off = sect->u.indirect.u.iblock->block_off; + else + iblock_off = sect->u.indirect.u.iblock_off; + +#ifdef QAK +HDfprintf(stderr, "%s: iblock_off = %Hu\n", "H5HF_sect_indirect_valid", iblock_off); +#endif /* QAK */ + + /* Compute starting entry, column & row */ + start_row = sect->u.indirect.row; + start_col = sect->u.indirect.col; + start_entry = (start_row * hdr->man_dtable.cparam.width) + start_col; + + /* Compute ending entry, column & row */ + end_entry = (start_entry + sect->u.indirect.num_entries) - 1; + end_row = end_entry / hdr->man_dtable.cparam.width; + end_col = end_entry % hdr->man_dtable.cparam.width; +#ifdef QAK +HDfprintf(stderr, "%s: start_row = %u, start_col = %u, start_entry = %u\n", "H5HF_sect_indirect_valid", start_row, start_col, start_entry); +HDfprintf(stderr, "%s: end_row = %u, end_col = %u, end_entry = %u\n", "H5HF_sect_indirect_valid", end_row, end_col, end_entry); +#endif /* QAK */ + + /* Iterate over direct rows, checking pointer references */ + dir_nrows = (end_row - start_row) + 1; + HDassert(dir_nrows == sect->u.indirect.dir_nrows); + for(u = 0; u < dir_nrows; u++) { + const H5HF_free_section_t *tmp_row_sect; /* Pointer to row section */ + + tmp_row_sect = sect->u.indirect.dir_rows[u]; + HDassert(tmp_row_sect->u.row.under == sect); + HDassert(tmp_row_sect->u.row.row == (start_row + u)); + if(u < (dir_nrows - 1)) { + const H5HF_free_section_t *tmp2_row_sect; /* Pointer to row section */ + + tmp2_row_sect = sect->u.indirect.dir_rows[u + 1]; + HDassert(tmp_row_sect->u.row.row != tmp2_row_sect->u.row.row); + } /* end if */ + } /* end for */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5HF_sect_indirect_valid() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_sect_indirect_debug * * Purpose: Dump debugging information about an indirect free space section @@ -1863,7 +4075,7 @@ done: * Failure: negative * * Programmer: Quincey Koziol - * Saturday, May 13, 2006 + * Monday, July 3, 2006 * *------------------------------------------------------------------------- */ @@ -1888,12 +4100,6 @@ H5HF_sect_indirect_debug(const H5FS_section_info_t *_sect, HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, "Number of entries:", sect->u.indirect.num_entries); - HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, - "Indirect row:", - sect->u.indirect.indir_row); - HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, - "Indirect number of rows:", - sect->u.indirect.indir_nrows); FUNC_LEAVE_NOAPI(SUCCEED) } /* H5HF_sect_indirect_debug() */ diff --git a/src/H5HFspace.c b/src/H5HFspace.c index 3519e91..4634e49 100644 --- a/src/H5HFspace.c +++ b/src/H5HFspace.c @@ -97,7 +97,8 @@ 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 */ H5HF_FSPACE_SECT_CLS_SINGLE, - H5HF_FSPACE_SECT_CLS_RANGE, + H5HF_FSPACE_SECT_CLS_FIRST_ROW, + H5HF_FSPACE_SECT_CLS_NORMAL_ROW, H5HF_FSPACE_SECT_CLS_INDIRECT}; herr_t ret_value = SUCCEED; /* Return value */ @@ -194,55 +195,18 @@ done: * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu - * May 2 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5HF_space_add(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *node) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_space_add) - - /* - * Check arguments. - */ - HDassert(hdr); - HDassert(node); - HDassert(hdr->fspace); - - /* Add to the free space for the heap */ - if(H5FS_add(hdr->f, dxpl_id, hdr->fspace, (H5FS_section_info_t *)node, 0, NULL) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "can't add section to heap free space") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_space_add() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_space_return - * - * Purpose: Return a freedsection to the free space for the heap - * - * Return: Success: non-negative - * - * Failure: negative - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu * May 15 2006 * *------------------------------------------------------------------------- */ herr_t -H5HF_space_return(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *node) +H5HF_space_add(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *node, + unsigned flags) { H5HF_add_ud1_t udata; /* User data for free space manager 'add' */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5HF_space_return) + FUNC_ENTER_NOAPI_NOINIT(H5HF_space_add) /* * Check arguments. @@ -258,15 +222,15 @@ H5HF_space_return(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *node) /* Construct user data */ udata.hdr = hdr; udata.dxpl_id = dxpl_id; - udata.dblock = NULL; + udata.adjoin = 0; /* Add to the free space for the heap */ - if(H5FS_add(hdr->f, dxpl_id, hdr->fspace, (H5FS_section_info_t *)node, H5FS_ADD_RETURNED_SPACE, &udata) < 0) + if(H5FS_add(hdr->f, dxpl_id, hdr->fspace, (H5FS_section_info_t *)node, flags, &udata) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "can't add section to heap free space") done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_space_return() */ +} /* end H5HF_space_add() */ /*------------------------------------------------------------------------- @@ -324,3 +288,41 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_space_close() */ + +/*------------------------------------------------------------------------- + * Function: H5HF_space_change_sect_class + * + * Purpose: Change a section's class + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * July 10 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_space_sect_change_class(H5HF_hdr_t *hdr, H5HF_free_section_t *sect, unsigned new_class) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_space_sect_change_class) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(hdr->fspace); + HDassert(sect); + + /* Notify the free space manager that a section has changed class */ + if(H5FS_sect_change_class(hdr->fspace, (H5FS_section_info_t *)sect, new_class) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTMODIFY, FAIL, "can't modify class of free space section") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_space_sect_change_class() */ + diff --git a/src/H5HFtest.c b/src/H5HFtest.c index a3b524b..d34f1f6 100644 --- a/src/H5HFtest.c +++ b/src/H5HFtest.c @@ -288,7 +288,7 @@ H5HF_get_dblock_free_test(const H5HF_t *fh, unsigned row) HDassert(fh); /* Return direct block free space */ - ret_value = fh->hdr->man_dtable.row_dblock_free[row]; + ret_value = fh->hdr->man_dtable.row_tot_dblock_free[row]; FUNC_LEAVE_NOAPI(ret_value) } /* H5HF_get_dblock_free_test() */ |