diff options
-rw-r--r-- | src/H5FS.c | 231 | ||||
-rw-r--r-- | src/H5FSprivate.h | 12 | ||||
-rw-r--r-- | src/H5HFpkg.h | 7 | ||||
-rw-r--r-- | src/H5HFsection.c | 994 | ||||
-rw-r--r-- | src/H5HFspace.c | 83 | ||||
-rw-r--r-- | src/H5SL.c | 2 | ||||
-rw-r--r-- | test/fheap.c | 14 |
7 files changed, 772 insertions, 571 deletions
@@ -119,8 +119,6 @@ static herr_t H5FS_sect_unlink_size(H5FS_t *fspace, const H5FS_section_class_t * 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, @@ -727,6 +725,7 @@ H5FS_sect_decrease(H5FS_t *fspace, const H5FS_section_class_t *cls) /* 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); + HDassert((fspace->hdr->serial_sect_count + fspace->hdr->ghost_sect_count) == 1); /* Remove the free space section from the section size list */ if(NULL == (sect = H5SL_remove_first(fspace_node->sect_list))) @@ -938,7 +937,6 @@ 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) { - H5FS_section_info_t *tmp_sect_node; /* Temporary section node */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_unlink_rest) @@ -949,10 +947,17 @@ H5FS_sect_unlink_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, HDassert(cls); HDassert(sect); - /* Remove node from merge list */ - tmp_sect_node = H5SL_remove(fspace->merge_list, §->addr); - if(tmp_sect_node == NULL || tmp_sect_node != sect) - HGOTO_ERROR(H5E_FSPACE, H5E_NOTFOUND, FAIL, "can't find section node on size list") + /* Remove node from merge list, if it was entered there */ + if(!(cls->flags & H5FS_CLS_SEPAR_OBJ)) { + H5FS_section_info_t *tmp_sect_node; /* Temporary section node */ + +#ifdef QAK +HDfprintf(stderr, "%s: removing object from merge list, sect->type = %u\n", FUNC, (unsigned)sect->type); +#endif /* QAK */ + tmp_sect_node = H5SL_remove(fspace->merge_list, §->addr); + if(tmp_sect_node == NULL || tmp_sect_node != sect) + HGOTO_ERROR(H5E_FSPACE, H5E_NOTFOUND, FAIL, "can't find section node on size list") + } /* end if */ /* Decrement amount of space required to serialize all sections */ fspace->serial_size -= fspace->sect_cls[sect->type].serial_size; @@ -978,12 +983,11 @@ done: /*------------------------------------------------------------------------- - * Function: H5FS_sect_unlink + * Function: H5FS_remove * - * Purpose: Unlink a section from the internal data structures + * Purpose: Remove a section from the free space manager * * Return: Success: non-negative - * * Failure: negative * * Programmer: Quincey Koziol @@ -991,13 +995,13 @@ done: * *------------------------------------------------------------------------- */ -static herr_t -H5FS_sect_unlink(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *sect) +herr_t +H5FS_remove(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) + FUNC_ENTER_NOAPI_NOINIT(H5FS_remove) /* Check arguments. */ HDassert(f); @@ -1017,7 +1021,7 @@ H5FS_sect_unlink(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *s done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5FS_sect_unlink() */ +} /* H5FS_remove() */ /*------------------------------------------------------------------------- @@ -1246,12 +1250,17 @@ H5FS_sect_link_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, const H5FS_section_ HDassert(fspace); HDassert(sect); - /* Add section to the address-ordered list of sections */ - if(fspace->merge_list == NULL) - if(NULL == (fspace->merge_list = H5SL_create(H5SL_TYPE_HADDR, 0.5, H5FS_DEFAULT_SKIPLIST_HEIGHT))) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTCREATE, FAIL, "can't create skip list for merging free space sections") - if(H5SL_insert(fspace->merge_list, sect, §->addr) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space node into merging skip list") + /* Add section to the address-ordered list of sections, if allowed */ + if(!(cls->flags & H5FS_CLS_SEPAR_OBJ)) { +#ifdef QAK +HDfprintf(stderr, "%s: inserting object into merge list, sect->type = %u\n", FUNC, (unsigned)sect->type); +#endif /* QAK */ + if(fspace->merge_list == NULL) + if(NULL == (fspace->merge_list = H5SL_create(H5SL_TYPE_HADDR, 0.5, H5FS_DEFAULT_SKIPLIST_HEIGHT))) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTCREATE, FAIL, "can't create skip list for merging free space sections") + if(H5SL_insert(fspace->merge_list, sect, §->addr) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space node into merging skip list") + } /* end if */ /* Increment amount of space required to serialize all sections */ #ifdef QAK @@ -1344,8 +1353,9 @@ static herr_t H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t **sect, void *op_data) { - H5FS_section_class_t *sect_cls = NULL; /* Section's class */ - hbool_t merged; /* Flag to indicate merge occurred */ + H5FS_section_class_t *sect_cls; /* Section's class */ + H5FS_section_info_t *tmp_sect_node; /* Temporary free space section */ + hbool_t modified; /* Flag to indicate merge or shrink occurred */ htri_t status; /* Status value */ herr_t ret_value = SUCCEED; /* Return value */ @@ -1361,18 +1371,25 @@ H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, /* Loop until no more merging */ do { H5FS_section_class_t *tmp_sect_cls; /* Temporary section's class */ - H5FS_section_info_t *tmp_sect_node; /* Temporary free space section */ - /* Reset 'merge occurred' flag */ - merged = FALSE; + /* Reset 'modification occurred' flag */ + modified = FALSE; /* Look for neighboring section before new section */ tmp_sect_node = H5SL_less(fspace->merge_list, &(*sect)->addr); /* Check for node before new node able to merge with new node */ if(tmp_sect_node) { - tmp_sect_cls = &fspace->sect_cls[tmp_sect_node->type]; /* Use class for left-most section */ - if(tmp_sect_cls->can_merge) { + /* Get classes for right & left sections */ + tmp_sect_cls = &fspace->sect_cls[tmp_sect_node->type]; + sect_cls = &fspace->sect_cls[(*sect)->type]; + + /* Check if sections of the left most class can merge with sections + * of another class & whether the sections are the same type, + * then check for 'can merge' callback + */ + if((!(tmp_sect_cls->flags & H5FS_CLS_MERGE_SYM) || (tmp_sect_node->type == (*sect)->type)) + && tmp_sect_cls->can_merge) { /* Determine if the sections can merge */ if((status = (*tmp_sect_cls->can_merge)(tmp_sect_node, *sect, op_data)) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't check for merging sections") @@ -1381,12 +1398,10 @@ H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, HDassert(tmp_sect_cls->merge); /* Remove 'less than' node from data structures */ - if(H5FS_sect_unlink(f, dxpl_id, fspace, tmp_sect_node) < 0) + if(H5FS_remove(f, dxpl_id, fspace, tmp_sect_node) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures") /* Merge the two sections together */ - /* (rescan the class of the node, the 'can merge' callback can change it) */ - tmp_sect_cls = &fspace->sect_cls[tmp_sect_node->type]; /* Use class for left-most section */ if((*tmp_sect_cls->merge)(tmp_sect_node, *sect, op_data) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't merge two sections") @@ -1394,7 +1409,7 @@ H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, *sect = tmp_sect_node; /* Indicate successful merge occurred */ - merged = TRUE; + modified = TRUE; } /* end if */ } /* end if */ } /* end if */ @@ -1404,54 +1419,87 @@ H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, /* Check for node after new node able to merge with new node */ if(tmp_sect_node) { - tmp_sect_cls = &fspace->sect_cls[(*sect)->type]; /* Use class for left-most section */ - if(tmp_sect_cls->can_merge) { + /* Get classes for right & left sections */ + sect_cls = &fspace->sect_cls[(*sect)->type]; + tmp_sect_cls = &fspace->sect_cls[tmp_sect_node->type]; + + /* Check if sections of the left most class can merge with sections + * of another class & whether the sections are the same type, + * then check for 'can merge' callback + */ + if((!(sect_cls->flags & H5FS_CLS_MERGE_SYM) || ((*sect)->type == tmp_sect_node->type)) + && sect_cls->can_merge) { + /* Determine if the sections can merge */ - if((status = (*tmp_sect_cls->can_merge)(*sect, tmp_sect_node, op_data)) < 0) + if((status = (*sect_cls->can_merge)(*sect, tmp_sect_node, op_data)) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't check for merging sections") if(status > 0) { /* Sanity check */ - HDassert(tmp_sect_cls->merge); + HDassert(sect_cls->merge); /* Remove 'greater than' node from data structures */ - if(H5FS_sect_unlink(f, dxpl_id, fspace, tmp_sect_node) < 0) + if(H5FS_remove(f, dxpl_id, fspace, tmp_sect_node) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures") /* Merge the two sections together */ - /* (rescan the class of the node, the 'can merge' callback can change it) */ - tmp_sect_cls = &fspace->sect_cls[(*sect)->type]; /* Use class for left-most section */ - if((*tmp_sect_cls->merge)(*sect, tmp_sect_node, op_data) < 0) + if((*sect_cls->merge)(*sect, tmp_sect_node, op_data) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't merge two sections") /* Indicate successful merge occurred */ - merged = TRUE; + modified = TRUE; } /* end if */ } /* end if */ } /* end if */ - } while(merged); + } while(modified); 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]; - if(sect_cls->can_shrink) { - if((status = (*sect_cls->can_shrink)(*sect, op_data)) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTSHRINK, FAIL, "can't check for shrinking container") - if(status > 0) { + /* Loop until no more shrinking */ + do { + /* Reset 'modification occurred' flag */ + modified = FALSE; + + /* Check for (possibly merged) section able to shrink the size of the container */ + sect_cls = &fspace->sect_cls[(*sect)->type]; + if(sect_cls->can_shrink) { + if((status = (*sect_cls->can_shrink)(*sect, op_data)) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTSHRINK, FAIL, "can't check for shrinking container") + if(status > 0) { #ifdef QAK HDfprintf(stderr, "%s: Can shrink!\n", FUNC); #endif /* QAK */ - /* Shrink the container */ - /* (callback can indicate that it has discarded the section by setting *sect to NULL) */ - /* (rescan the class of the node, the 'can shrink' callback can change it) */ - sect_cls = &fspace->sect_cls[(*sect)->type]; - HDassert(sect_cls->shrink); - if((*sect_cls->shrink)(sect, op_data) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't shrink free space container") + /* Look for neighboring section before new section */ + tmp_sect_node = H5SL_less(fspace->merge_list, &(*sect)->addr); + + /* Shrink the container */ + /* (callback can indicate that it has discarded the section by setting *sect to NULL) */ + HDassert(sect_cls->shrink); + if((*sect_cls->shrink)(sect, op_data) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't shrink free space container") + + /* Check if the new section was removed */ + if(*sect == NULL && tmp_sect_node) { + /* Remove 'less than' node from data structures */ + if(H5FS_remove(f, dxpl_id, fspace, tmp_sect_node) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures") + + *sect = tmp_sect_node; + } /* end if */ + + /* Indicate successful merge occurred */ + modified = TRUE; + } /* end if */ } /* end if */ - } /* end if */ + } while(modified && *sect); +#ifdef QAK +HDfprintf(stderr, "%s: Done shrinking\n", FUNC); +if(*sect) + HDfprintf(stderr, "%s: (*sect) = {%a, %Hu, %u, %s}\n", FUNC, (*sect)->addr, (*sect)->size, (*sect)->type, ((*sect)->state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED")); +else + HDfprintf(stderr, "%s: *sect = %p\n", FUNC, *sect); +#endif /* QAK */ done: #ifdef QAK @@ -2568,11 +2616,12 @@ done: 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 */ + 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 */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_sect_change_class) + FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_change_class) /* Check arguments. */ HDassert(fspace); @@ -2580,14 +2629,15 @@ H5FS_sect_change_class(H5FS_t *fspace, H5FS_section_info_t *sect, unsigned new_c 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]; +#ifdef QAK +HDfprintf(stderr, "%s: old_cls->flags = %x\n", FUNC, old_cls->flags); +HDfprintf(stderr, "%s: new_cls->flags = %x\n", FUNC, new_cls->flags); +#endif /* QAK */ /* 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)) { @@ -2599,7 +2649,7 @@ HDfprintf(stderr, "%s: Called\n", "H5FS_sect_change_class"); else to_ghost = TRUE; #ifdef QAK -HDfprintf(stderr, "%s: to_ghost = %u\n", "H5FS_sect_change_class", to_ghost); +HDfprintf(stderr, "%s: to_ghost = %u\n", FUNC, to_ghost); #endif /* QAK */ /* Check for single vs. multiple sections managed */ @@ -2676,6 +2726,42 @@ HDfprintf(stderr, "%s: to_ghost = %u\n", "H5FS_sect_change_class", to_ghost); } /* end else */ } /* end if */ + /* Check if the section's class change will affect the mergable list */ + if((old_cls->flags & H5FS_CLS_SEPAR_OBJ) != (new_cls->flags & H5FS_CLS_SEPAR_OBJ)) { + hbool_t to_mergable; /* Flag if the section is changing to a mergable section */ + + /* Determine if this section is becoming mergable or is becoming separate */ + if(old_cls->flags & H5FS_CLS_SEPAR_OBJ) + to_mergable = TRUE; + else + to_mergable = FALSE; +#ifdef QAK +HDfprintf(stderr, "%s: to_mergable = %u\n", FUNC, to_mergable); +#endif /* QAK */ + + /* Add or remove section from merge list, as appropriate */ + if(to_mergable) { +#ifdef QAK +HDfprintf(stderr, "%s: inserting object into merge list, sect->type = %u\n", FUNC, (unsigned)sect->type); +#endif /* QAK */ + if(fspace->merge_list == NULL) + if(NULL == (fspace->merge_list = H5SL_create(H5SL_TYPE_HADDR, 0.5, H5FS_DEFAULT_SKIPLIST_HEIGHT))) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTCREATE, FAIL, "can't create skip list for merging free space sections") + if(H5SL_insert(fspace->merge_list, sect, §->addr) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space node into merging skip list") + } /* end if */ + else { + H5FS_section_info_t *tmp_sect_node; /* Temporary section node */ + +#ifdef QAK +HDfprintf(stderr, "%s: removing object from merge list, sect->type = %u\n", FUNC, (unsigned)sect->type); +#endif /* QAK */ + tmp_sect_node = H5SL_remove(fspace->merge_list, §->addr); + if(tmp_sect_node == NULL || tmp_sect_node != sect) + HGOTO_ERROR(H5E_FSPACE, H5E_NOTFOUND, FAIL, "can't find section node on size list") + } /* end else */ + } /* end if */ + /* Change the section's class */ sect->type = new_class; @@ -2689,10 +2775,11 @@ HDfprintf(stderr, "%s: to_ghost = %u\n", "H5FS_sect_change_class", to_ghost); /* Mark free space as dirty also */ fspace->dirty = TRUE; +done: #ifdef H5FS_DEBUG H5FS_assert(fspace); #endif /* H5FS_DEBUG */ - FUNC_LEAVE_NOAPI(SUCCEED) + FUNC_LEAVE_NOAPI(ret_value) } /* H5FS_sect_change_class() */ @@ -2965,11 +3052,16 @@ H5FS_debug_test(const H5FS_t *fspace) herr_t H5FS_assert(const H5FS_t *fspace) { + hsize_t separate_obj; /* The number of separate objects managed */ + 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 */ + /* Initialize state */ + separate_obj = 0; + /* Check for single vs. multiple sections managed */ if(fspace->single) { const H5FS_section_class_t *cls; /* Class of section */ @@ -2996,6 +3088,10 @@ HDfprintf(stderr, "%s: fspace->single->size = %Hu, fspace->single->addr = %a, fs HDassert(fspace->hdr->serial_sect_count == 1); HDassert(fspace->hdr->ghost_sect_count == 0); } /* end else */ + + /* Count node, if separate */ + if(cls->flags & H5FS_CLS_SEPAR_OBJ) + separate_obj++; } /* end if */ else if(fspace->bins) { hsize_t acc_tot_sect_count; /* Accumulated total section count from bins */ @@ -3064,6 +3160,10 @@ HDfprintf(stderr, "%s: sect->size = %Hu, sect->addr = %a, sect->type = %u\n", "H else size_serial_count++; + /* Count node, if separate */ + if(cls->flags & H5FS_CLS_SEPAR_OBJ) + separate_obj++; + /* Get the next section node in the list */ curr_sect_node = H5SL_next(curr_sect_node); } /* end while */ @@ -3116,10 +3216,11 @@ HDfprintf(stderr, "%s: sect->size = %Hu, sect->addr = %a, sect->type = %u\n", "H 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)); + HDassert(fspace->hdr->serial_sect_count > 0 || fspace->hdr->ghost_sect_count == 0); /* 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)); + HDassert(fspace->hdr->tot_sect_count == (separate_obj + H5SL_count(fspace->merge_list))); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5FS_assert() */ diff --git a/src/H5FSprivate.h b/src/H5FSprivate.h index 25383cc..2b840bd 100644 --- a/src/H5FSprivate.h +++ b/src/H5FSprivate.h @@ -42,6 +42,12 @@ #define H5FS_CLS_GHOST_OBJ 0x01 /* Objects in this class shouldn't be * serialized to the file. */ +#define H5FS_CLS_SEPAR_OBJ 0x02 /* Objects in this class shouldn't + * participate in merge operations + */ +#define H5FS_CLS_MERGE_SYM 0x04 /* Objects in this class only merge + * with other objects in this class + */ /* Flags for H5FS_add() */ #define H5FS_ADD_DESERIALIZING 0x01 /* Free space is being deserialized @@ -86,9 +92,9 @@ typedef struct H5FS_section_class_t { /* Object methods */ 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 */ + htri_t (*can_merge)(const H5FS_section_info_t *, const H5FS_section_info_t *, void *); /* Routine to determine if two nodes are mergable */ herr_t (*merge)(H5FS_section_info_t *, H5FS_section_info_t *, void *); /* Routine to merge two nodes */ - htri_t (*can_shrink)(H5FS_section_info_t *, void *); /* Routine to determine if node can shrink container */ + htri_t (*can_shrink)(const 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 */ @@ -147,6 +153,8 @@ 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[], 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 herr_t H5FS_remove(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, + H5FS_section_info_t *node); 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(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_operator_t op, void *op_data); diff --git a/src/H5HFpkg.h b/src/H5HFpkg.h index 15f0665..aa7c3bf 100644 --- a/src/H5HFpkg.h +++ b/src/H5HFpkg.h @@ -359,7 +359,6 @@ typedef struct H5HF_parent_t { typedef struct { H5HF_hdr_t *hdr; /* Fractal heap header */ hid_t dxpl_id; /* DXPL ID for operation */ - hbool_t adjoin; /* Whether two spans of blocks adjoin each other */ } H5HF_add_ud1_t; /*****************************/ @@ -521,10 +520,12 @@ H5_DLL hbool_t H5HF_man_iter_ready(H5HF_block_iter_t *biter); /* Free space manipulation routines */ 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, unsigned flags); +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_remove(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_free_section_t *node); H5_DLL herr_t H5HF_space_close(H5HF_hdr_t *hdr, hid_t dxpl_id); H5_DLL herr_t H5HF_space_delete(H5HF_hdr_t *hdr, hid_t dxpl_id); H5_DLL herr_t H5HF_space_sect_change_class(H5HF_hdr_t *hdr, H5HF_free_section_t *sect, diff --git a/src/H5HFsection.c b/src/H5HFsection.c index 623d547..8888d06 100644 --- a/src/H5HFsection.c +++ b/src/H5HFsection.c @@ -69,11 +69,11 @@ static herr_t H5HF_sect_node_free(H5HF_free_section_t *sect, 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 htri_t H5HF_sect_single_can_merge(const H5FS_section_info_t *sect1, + const 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, +static htri_t H5HF_sect_single_can_shrink(const H5FS_section_info_t *sect, void *udata); static herr_t H5HF_sect_single_shrink(H5FS_section_info_t **_sect, void *udata); @@ -88,8 +88,7 @@ static H5HF_free_section_t *H5HF_sect_row_create(haddr_t sect_off, 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); -static herr_t H5HF_sect_row_iblock_same(const H5HF_free_section_t *sect1, - const H5HF_free_section_t *sect2); +static herr_t H5HF_sect_row_free_real(H5HF_free_section_t *sect); /* 'row' section callbacks */ static herr_t H5HF_sect_row_init_cls(H5FS_section_class_t *cls, void *udata); @@ -99,11 +98,11 @@ static herr_t H5HF_sect_row_serialize(const H5FS_section_class_t *cls, 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 htri_t H5HF_sect_row_can_merge(const H5FS_section_info_t *sect1, + const H5FS_section_info_t *sect2, void *udata); static herr_t H5HF_sect_row_merge(H5FS_section_info_t *sect1, H5FS_section_info_t *sect2, void *udata); -static htri_t H5HF_sect_row_can_shrink(H5FS_section_info_t *sect, +static htri_t H5HF_sect_row_can_shrink(const H5FS_section_info_t *sect, void *udata); static herr_t H5HF_sect_row_shrink(H5FS_section_info_t **sect, void *udata); @@ -112,8 +111,9 @@ 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, +static H5HF_free_section_t *H5HF_sect_indirect_new(H5HF_hdr_t *hdr, + 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, @@ -134,14 +134,13 @@ 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 hsize_t H5HF_sect_indirect_iblock_off(const H5HF_free_section_t *sect); +static H5HF_free_section_t * H5HF_sect_indirect_top(H5HF_free_section_t *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_build_parent(H5HF_hdr_t *hdr, H5HF_free_section_t *sect); +static herr_t H5HF_sect_indirect_shrink(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_free_section_t *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, @@ -167,7 +166,7 @@ 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 */ + H5FS_CLS_MERGE_SYM, /* Class flags */ NULL, /* Class private info */ /* Class methods */ @@ -194,7 +193,7 @@ H5FS_section_class_t H5HF_FSPACE_SECT_CLS_FIRST_ROW[1] = {{ /* Class variables */ H5HF_FSPACE_SECT_FIRST_ROW, /* Section type */ 0, /* Extra serialized size */ - 0, /* Class flags */ + H5FS_CLS_MERGE_SYM, /* Class flags */ NULL, /* Class private info */ /* Class methods */ @@ -218,7 +217,7 @@ 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 */ + H5FS_CLS_MERGE_SYM|H5FS_CLS_SEPAR_OBJ|H5FS_CLS_GHOST_OBJ, /* Class flags */ NULL, /* Class private info */ /* Class methods */ @@ -228,10 +227,10 @@ H5FS_section_class_t H5HF_FSPACE_SECT_CLS_NORMAL_ROW[1] = {{ /* 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 */ + NULL, /* Can sections merge? */ + NULL, /* Merge sections */ + NULL, /* Can section shrink container?*/ + NULL, /* Shrink container w/section */ H5HF_sect_row_free, /* Free section */ H5HF_sect_row_valid, /* Check validity of section */ NULL, /* Dump debugging for section */ @@ -245,7 +244,7 @@ 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 */ + H5FS_CLS_MERGE_SYM|H5FS_CLS_GHOST_OBJ, /* Class flags */ NULL, /* Class private info */ /* Class methods */ @@ -607,11 +606,11 @@ done: *------------------------------------------------------------------------- */ static htri_t -H5HF_sect_single_can_merge(H5FS_section_info_t *_sect1, - H5FS_section_info_t *_sect2, void UNUSED *_udata) +H5HF_sect_single_can_merge(const H5FS_section_info_t *_sect1, + const 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 */ + const H5HF_free_section_t *sect1 = (const H5HF_free_section_t *)_sect1; /* Fractal heap free section */ + const H5HF_free_section_t *sect2 = (const H5HF_free_section_t *)_sect2; /* Fractal heap free section */ htri_t ret_value = FALSE; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_single_can_merge) @@ -619,6 +618,7 @@ H5HF_sect_single_can_merge(H5FS_section_info_t *_sect1, /* Check arguments. */ HDassert(sect1); HDassert(sect2); + HDassert(sect1->sect_info.type == sect2->sect_info.type); /* Checks "MERGE_SYM" flag */ HDassert(H5F_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr)); #ifdef QAK @@ -626,10 +626,6 @@ HDfprintf(stderr, "%s: sect1->sect_info = {%a, %Hu, %u, %s}\n", "H5HF_sect_singl 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 */ - /* 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 occur within a direct block, due to the direct block * overhead at the beginning of a block, so no need to check if sections @@ -676,7 +672,9 @@ H5HF_sect_single_merge(H5FS_section_info_t *_sect1, H5FS_section_info_t *_sect2, /* Check arguments. */ HDassert(sect1); + HDassert(sect1->sect_info.type == H5HF_FSPACE_SECT_SINGLE); HDassert(sect2); + HDassert(sect2->sect_info.type == H5HF_FSPACE_SECT_SINGLE); HDassert(H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr)); #ifdef QAK @@ -758,45 +756,46 @@ done: *------------------------------------------------------------------------- */ static htri_t -H5HF_sect_single_can_shrink(H5FS_section_info_t *_sect, void *_udata) +H5HF_sect_single_can_shrink(const H5FS_section_info_t *_sect, void *_udata) { - H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Fractal heap free section */ + 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 */ - size_t dblock_size; /* Section's direct block's size */ - size_t dblock_overhead; /* Direct block's overhead */ htri_t ret_value = FALSE; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_single_can_shrink) /* Check arguments. */ HDassert(sect); - HDassert(sect->sect_info.state == H5FS_SECT_LIVE); #ifdef QAK -HDfprintf(stderr, "%s: sect->sect_info = {%a, %Hu, %u, %s}\n", 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->sect_info = {%a, %Hu, %u, %s}\n", "H5HF_sect_single_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")); #endif /* QAK */ - /* Check for section occupying entire direct block */ - dblock_size = sect->u.single.dblock_size; - dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr); + /* Check for section occupying entire root direct block */ + /* (We shouldn't ever have a single section that occupies an entire + * direct block, unless it's in the root direct block (because it + * would have been converted into a row section, if there was an + * indirect block that covered it) + */ + if(hdr->man_dtable.curr_root_rows == 0) { + size_t dblock_size; /* Section's direct block's size */ + size_t dblock_overhead; /* Direct block's overhead */ + + dblock_size = hdr->man_dtable.cparam.start_block_size; + dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr); #ifdef QAK -HDfprintf(stderr, "%s: dblock_size = %Zu\n", FUNC, dblock_size); -HDfprintf(stderr, "%s: dblock_overhead = %Zu\n", FUNC, dblock_overhead); +HDfprintf(stderr, "%s: dblock_size = %Zu\n", "H5HF_sect_single_can_shrink", dblock_size); +HDfprintf(stderr, "%s: dblock_overhead = %Zu\n", "H5HF_sect_single_can_shrink", dblock_overhead); #endif /* QAK */ - if((dblock_size - dblock_overhead) == sect->sect_info.size) { - /* 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) + if((dblock_size - dblock_overhead) == sect->sect_info.size) + 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); + HDassert(hdr->man_iter_off > sect->sect_info.addr); HGOTO_DONE(FALSE) } /* end else */ @@ -841,12 +840,13 @@ H5HF_sect_single_shrink(H5FS_section_info_t **_sect, void UNUSED *_udata) 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 */ + /* 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") /* Protect the direct block for the section */ + /* (should be a root direct block) */ dblock_addr = (*sect)->u.single.dblock_addr; HDassert(dblock_addr == hdr->man_dtable.table_addr); #ifdef QAK @@ -946,7 +946,7 @@ HDfprintf(stderr, "%s: sect->sect_info = {%a, %Hu, %u, %s}\n", "H5HF_sect_single /* (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 */ + unsigned dblock_status = 0; /* Direct block's status in the metadata cache */ herr_t status; /* Generic status value */ #ifdef QAK @@ -958,21 +958,33 @@ HDfprintf(stderr, "%s: sect->u.single = {%p, %u, %a, %Zu}\n", "H5HF_sect_single_ 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); + /* Check the direct block's status in the metadata cache */ + status = H5AC_get_entry_status(iblock->hdr->f, sect->u.single.dblock_addr, &dblock_status); HDassert(status >= 0); + + /* If the direct block for the section isn't already protected, + * protect it here in order to check single section's sanity + * against it. + */ + if(!(dblock_status & H5AC_ES__IS_PROTECTED)) { + H5HF_direct_t *dblock; /* Direct block for section */ + + /* 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 */ } /* end if */ @@ -1083,40 +1095,6 @@ done: /*------------------------------------------------------------------------- - * 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_row_iblock_same() */ - - -/*------------------------------------------------------------------------- * Function: H5HF_sect_row_revive * * Purpose: Update the memory information for a 'row' free section @@ -1490,20 +1468,21 @@ done: *------------------------------------------------------------------------- */ static htri_t -H5HF_sect_row_can_merge(H5FS_section_info_t *_sect1, - H5FS_section_info_t *_sect2, void *_udata) +H5HF_sect_row_can_merge(const H5FS_section_info_t *_sect1, + const 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 */ + const H5HF_free_section_t *sect1 = (const H5HF_free_section_t *)_sect1; /* Fractal heap free section */ + const H5HF_free_section_t *sect2 = (const H5HF_free_section_t *)_sect2; /* Fractal heap free section */ + H5HF_free_section_t *top_indir_sect1, *top_indir_sect2; /* Top indirect section for each row */ htri_t ret_value = FALSE; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_row_can_merge) /* Check arguments. */ HDassert(sect1); + HDassert(sect1->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW); HDassert(sect2); + HDassert(sect1->sect_info.type == sect2->sect_info.type); /* Checks "MERGE_SYM" flag */ HDassert(H5F_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr)); #ifdef QAK @@ -1513,46 +1492,29 @@ HDfprintf(stderr, "%s: sect2->sect_info = {%a, %Hu, %u, %s}\n", "H5HF_sect_row_c #ifdef QAK 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); +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 */ - /* 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: 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) + /* Get the top indirect section underlying each row */ + top_indir_sect1 = H5HF_sect_indirect_top(sect1->u.row.under); + HDassert(top_indir_sect1); + top_indir_sect2 = H5HF_sect_indirect_top(sect2->u.row.under); + HDassert(top_indir_sect2); /* 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 */ - + if(top_indir_sect1 != top_indir_sect2) { + if(H5HF_sect_indirect_iblock_off(top_indir_sect1) == H5HF_sect_indirect_iblock_off(top_indir_sect2)) { #ifdef QAK -HDfprintf(stderr, "%s: dblock_overhead = %Zu\n", "H5HF_sect_row_can_merge", dblock_overhead); +HDfprintf(stderr, "%s: top_indir_sect1->sect_info.addr = %a\n", "H5HF_sect_row_can_merge", top_indir_sect1->sect_info.addr); +HDfprintf(stderr, "%s: top_indir_sect1->u.indirect.span_size = %Hu\n", "H5HF_sect_row_can_merge", top_indir_sect1->u.indirect.span_size); +HDfprintf(stderr, "%s: top_indir_sect2->sect_info.addr = %a\n", "H5HF_sect_row_can_merge", top_indir_sect2->sect_info.addr); #endif /* QAK */ /* 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; + if(H5F_addr_eq((top_indir_sect1->sect_info.addr + top_indir_sect1->u.indirect.span_size), top_indir_sect2->sect_info.addr)) HGOTO_DONE(TRUE) - } /* end if */ } /* end if */ } /* end if */ @@ -1595,58 +1557,32 @@ H5HF_sect_row_merge(H5FS_section_info_t *_sect1, H5FS_section_info_t *_sect2, /* Check arguments. */ HDassert(sect1); - HDassert(sect1->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW || - sect1->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW); + HDassert(sect1->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW); HDassert(sect2); - HDassert(sect2->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW || - sect2->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW); + HDassert(sect2->sect_info.type == H5HF_FSPACE_SECT_FIRST_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: 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 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") + /* 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 */ - - /* 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); +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); +HDfprintf(stderr, "%s: sect2->u.row = {%p, %u, %u, %u, %t}\n", FUNC, sect2->u.row.under, sect2->u.row.row, sect2->u.row.col, sect2->u.row.num_entries, sect2->u.row.checked_out); #endif /* QAK */ - /* 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 */ + /* 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") done: FUNC_LEAVE_NOAPI(ret_value) @@ -1672,7 +1608,7 @@ done: *------------------------------------------------------------------------- */ static htri_t -H5HF_sect_row_can_shrink(H5FS_section_info_t *_sect, void UNUSED *_udata) +H5HF_sect_row_can_shrink(const 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 */ @@ -1683,19 +1619,18 @@ H5HF_sect_row_can_shrink(H5FS_section_info_t *_sect, void UNUSED *_udata) /* Check arguments. */ HDassert(sect); - HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW || - sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW); + HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW); #ifdef QAK 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); +HDfprintf(stderr, "%s: sect->u.row = {%p, %u, %u, %u, %t}\n", "H5HF_sect_row_can_shrink", sect->u.row.under, sect->u.row.row, sect->u.row.col, sect->u.row.num_entries, sect->u.row.checked_out); #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_row_can_shrink", hdr->man_iter_off); #endif /* QAK */ - if(sect->sect_info.addr >= hdr->man_iter_off && H5HF_sect_indirect_is_last_row(sect)) + if(sect->sect_info.addr >= hdr->man_iter_off) HGOTO_DONE(TRUE) done: @@ -1718,9 +1653,13 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5HF_sect_row_shrink(H5FS_section_info_t **_sect, void UNUSED *_udata) +H5HF_sect_row_shrink(H5FS_section_info_t **_sect, void *_udata) { H5HF_free_section_t **sect = (H5HF_free_section_t **)_sect; /* Fractal heap free section */ + H5HF_free_section_t *top_indir_sect; /* Top indirect section for row */ + 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_row_shrink) @@ -1728,22 +1667,20 @@ H5HF_sect_row_shrink(H5FS_section_info_t **_sect, void UNUSED *_udata) /* Check arguments. */ HDassert(sect); HDassert(*sect); - HDassert((*sect)->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW || - (*sect)->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW); + HDassert((*sect)->sect_info.type == H5HF_FSPACE_SECT_FIRST_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")); 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 */ + /* Get the top indirect section underlying each row */ + top_indir_sect = H5HF_sect_indirect_top((*sect)->u.row.under); + /* Shrink size of underlying indirect section */ - if(H5HF_sect_indirect_shrink_row(*sect) < 0) + if(H5HF_sect_indirect_shrink(hdr, dxpl_id, top_indir_sect) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't shrink underlying indirect section") - /* Get rid of section */ - 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 */ *sect = NULL; @@ -1753,6 +1690,38 @@ done: /*------------------------------------------------------------------------- + * Function: H5HF_sect_row_free_real + * + * Purpose: Free a 'row' section node + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Thursday, July 6, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_row_free_real(H5HF_free_section_t *sect) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_row_free_real) + + HDassert(sect); + + /* Release the section */ + 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_row_free_real() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_sect_row_free * * Purpose: Free a 'row' section node @@ -1782,7 +1751,7 @@ H5HF_sect_row_free(H5FS_section_info_t *_sect) HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't detach section node") /* Release the section */ - if(H5HF_sect_node_free(sect, NULL) < 0) + if(H5HF_sect_row_free_real(sect) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node") done: @@ -1932,83 +1901,45 @@ HDfprintf(stderr, "%s: acc_span_size = %Hu\n", "H5HF_sect_indirect_span_size", a /*------------------------------------------------------------------------- - * Function: H5HF_sect_indirect_iblock_entries + * Function: H5HF_sect_indirect_iblock_off * - * Purpose: Compute the number of entries for the iblock that an - * indirect section is located in + * Purpose: Get the offset of the indirect block for the section * - * Return: Non-negative on success/Negative on failure + * Return: Offset of indirect block in "heap space" (can't fail) * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu - * July 3 2006 + * July 6 2006 * *------------------------------------------------------------------------- */ -static herr_t -H5HF_sect_indirect_iblock_entries(H5HF_hdr_t *hdr, H5HF_free_section_t *sect) +static hsize_t +H5HF_sect_indirect_iblock_off(const H5HF_free_section_t *sect) { - unsigned nrows; /* Number of rows in target indirect block */ - herr_t ret_value = SUCCEED; /* Return value */ + hsize_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_iblock_entries) + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_iblock_off) /* * 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; + ret_value = sect->sect_info.state == H5FS_SECT_LIVE ? sect->u.indirect.u.iblock->block_off : sect->u.indirect.u.iblock_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); +HDfprintf(stderr, "%s: Leaving, ret_value = %Hu\n", "H5HF_sect_indirect_iblock_off", ret_value); #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() */ +} /* end H5HF_sect_indirect_iblock_off() */ /*------------------------------------------------------------------------- - * Function: H5HF_sect_indirect_iblock_same + * Function: H5HF_sect_indirect_top * - * Purpose: Check if two indirect sections are located in the same indirect block + * Purpose: Get the "top" indirect section * - * Return: Non-negative on success/Negative on failure + * Return: Pointer to the top indirect sectin (can't fail) * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu @@ -2016,77 +1947,31 @@ done: * *------------------------------------------------------------------------- */ -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) +static H5HF_free_section_t * +H5HF_sect_indirect_top(H5HF_free_section_t *sect) { - const H5HF_free_section_t *sect; /* Underlying indirect section */ - hbool_t ret_value; /* Return value */ + H5HF_free_section_t *ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_is_last_row) + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_top) /* * Check arguments. */ - HDassert(row_sect); + HDassert(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); +HDfprintf(stderr, "%s: sect1->u.indirect.parent = %p\n", "H5HF_sect_indirect_top", sect->u.indirect.parent); #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; + if(sect->u.indirect.parent) + ret_value = H5HF_sect_indirect_top(sect->u.indirect.parent); else - ret_value = FALSE; + ret_value = sect; #ifdef QAK -HDfprintf(stderr, "%s: ret_value = %t\n", "H5HF_sect_indirect_is_last_row", ret_value); +HDfprintf(stderr, "%s: Leaving, ret_value = %p\n", "H5HF_sect_indirect_top", ret_value); #endif /* QAK */ FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_sect_indirect_is_last_row() */ +} /* end H5HF_sect_indirect_top() */ /*------------------------------------------------------------------------- @@ -2179,7 +2064,7 @@ H5HF_sect_indirect_term_cls(H5FS_section_class_t *cls) *------------------------------------------------------------------------- */ static H5HF_free_section_t * -H5HF_sect_indirect_new(haddr_t sect_off, hsize_t sect_size, +H5HF_sect_indirect_new(H5HF_hdr_t *hdr, haddr_t sect_off, hsize_t sect_size, H5HF_indirect_t *iblock, hsize_t iblock_off, unsigned row, unsigned col, unsigned nentries) { @@ -2192,6 +2077,7 @@ H5HF_sect_indirect_new(haddr_t sect_off, hsize_t sect_size, /* * Check arguments. */ + HDassert(hdr); HDassert(nentries); /* Create free space section node */ @@ -2202,19 +2088,23 @@ H5HF_sect_indirect_new(haddr_t sect_off, hsize_t sect_size, /* Set the 'indirect' specific fields */ if(iblock) { sect->u.indirect.u.iblock = iblock; + sect->u.indirect.iblock_entries = hdr->man_dtable.cparam.width * + sect->u.indirect.u.iblock->max_rows; 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 + else { sect->u.indirect.u.iblock_off = iblock_off; + sect->u.indirect.iblock_entries = 0; + } /* end else */ sect->u.indirect.row = row; sect->u.indirect.col = col; sect->u.indirect.num_entries = nentries; - /* Reset the non-stored fields, they are computed later, on demand */ - sect->u.indirect.span_size = 0; - sect->u.indirect.iblock_entries = 0; + /* Compute span size of indirect section */ + if(H5HF_sect_indirect_span_size(hdr, sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, NULL, "can't compute span size of section") /* This indirect section doesn't (currently) have a parent */ sect->u.indirect.parent = NULL; @@ -2272,7 +2162,7 @@ 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, + if(NULL == (sect = H5HF_sect_indirect_new(hdr, 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") @@ -2349,6 +2239,7 @@ HDfprintf(stderr, "%s: end_row = %u, end_col = %u\n", FUNC, end_row, end_col); * Check arguments. */ HDassert(sect); + HDassert(sect->u.indirect.span_size > 0); /* Reset reference count for indirect section */ sect->u.indirect.rc = 0; @@ -2495,7 +2386,7 @@ HDfprintf(stderr, "%s: child_iblock_addr = %a\n", FUNC, child_iblock_addr); child_iblock = NULL; /* Create free space section node */ - if(NULL == (child_sect = H5HF_sect_indirect_new(curr_off, (hsize_t)0, + if(NULL == (child_sect = H5HF_sect_indirect_new(hdr, 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") @@ -2606,7 +2497,7 @@ 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, + if(NULL == (sect = H5HF_sect_indirect_new(hdr, 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") @@ -2617,10 +2508,6 @@ HDfprintf(stderr, "%s: sect_off = %Hu\n", FUNC, sect_off); /* 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 @@ -2730,6 +2617,10 @@ HDfprintf(stderr, "%s: sect->u.indirect.u.iblock_off = %Hu\n", FUNC, sect->u.ind /* Set the pointer to the section's indirect block */ sect->u.indirect.u.iblock = sec_iblock; + /* Set the number of entries in the indirect block */ + sect->u.indirect.iblock_entries = hdr->man_dtable.cparam.width * + sect->u.indirect.u.iblock->max_rows; + /* 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") @@ -2793,6 +2684,10 @@ HDfprintf(stderr, "%s: sect->u.indirect.u.iblock_off = %Hu\n", FUNC, sect->u.ind /* Set the pointer to the section's indirect block */ sect->u.indirect.u.iblock = sect_iblock; + /* Set the number of entries in the indirect block */ + sect->u.indirect.iblock_entries = hdr->man_dtable.cparam.width * + sect->u.indirect.u.iblock->max_rows; + /* Section is "live" now */ sect->sect_info.state = H5FS_SECT_LIVE; @@ -2868,6 +2763,8 @@ HDfprintf(stderr, "%s: row_start_entry = %u, row_end_entry = %u\n", FUNC, row_st end_col = end_entry % hdr->man_dtable.cparam.width; /* Additional sanity check */ + HDassert(sect->u.indirect.span_size > 0); + HDassert(sect->u.indirect.iblock_entries > 0); HDassert(sect->u.indirect.dir_rows); HDassert(sect->u.indirect.dir_rows[(row_sect->u.row.row - start_row)] == row_sect); #ifdef QAK @@ -2915,9 +2812,8 @@ HDfprintf(stderr, "%s: row_entry = %u\n", FUNC, row_entry); 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; + /* Adjust indirect section's span size */ + 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) { @@ -3033,7 +2929,7 @@ HDfprintf(stderr, "%s: iblock = %p, iblock_off = %Hu\n", FUNC, iblock, iblock_of #endif /* QAK */ /* Create peer indirect section */ - if(NULL == (peer_sect = H5HF_sect_indirect_new(sect->sect_info.addr, + if(NULL == (peer_sect = H5HF_sect_indirect_new(hdr, 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") @@ -3073,12 +2969,10 @@ HDfprintf(stderr, "%s: iblock = %p, iblock_off = %Hu\n", FUNC, iblock, iblock_of /* 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.span_size -= peer_sect->u.indirect.span_size; /* (span for row section has already been removed) */ 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 */ @@ -3134,6 +3028,8 @@ H5HF_sect_indirect_reduce(H5HF_hdr_t *hdr, H5HF_free_section_t *sect, */ HDassert(hdr); HDassert(sect); + HDassert(sect->u.indirect.span_size > 0); + HDassert(sect->u.indirect.iblock_entries > 0); #ifdef QAK HDfprintf(stderr, "%s: child_entry = %u\n", FUNC, child_entry); #endif /* QAK */ @@ -3192,8 +3088,7 @@ HDfprintf(stderr, "%s: Child is at start of indirect section\n", FUNC); 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]; + sect->u.indirect.span_size -= hdr->man_dtable.row_block_size[start_row]; /* Adjust indirect entry information */ sect->u.indirect.indir_nents--; @@ -3215,8 +3110,7 @@ HDfprintf(stderr, "%s: Child is at end of indirect section\n", FUNC); /* 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]; + sect->u.indirect.span_size -= hdr->man_dtable.row_block_size[end_row]; /* Adjust indirect entry information */ sect->u.indirect.indir_nents--; @@ -3233,7 +3127,6 @@ HDfprintf(stderr, "%s: Child is at end of indirect section\n", FUNC); 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 @@ -3248,11 +3141,11 @@ HDfprintf(stderr, "%s: Child is in middle of indirect section\n", FUNC); 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 */ + HDassert(child_row >= hdr->man_dtable.max_direct_rows); /* Get indirect block information for peer */ if(sect->sect_info.state == H5FS_SECT_LIVE) { @@ -3268,7 +3161,7 @@ HDfprintf(stderr, "%s: iblock = %p, iblock_off = %Hu\n", FUNC, iblock, iblock_of #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 */ + /* (Will use this to compute the section address for the 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") @@ -3285,7 +3178,7 @@ 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, + if(NULL == (peer_sect = H5HF_sect_indirect_new(hdr, 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") @@ -3299,11 +3192,11 @@ HDfprintf(stderr, "%s: peer_sect_addr = %a\n", FUNC, peer_sect_addr); /* Transfer child indirect sections between current & peer sections */ HDmemcpy(&peer_sect->u.indirect.indir_ents[0], - §->u.indirect.indir_ents[old_nentries - peer_nentries], + §->u.indirect.indir_ents[sect->u.indirect.indir_nents - 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); +HDfprintf(stderr, "%s: sect->u.indirect.indir_nents = %u\n", FUNC, sect->u.indirect.indir_nents); #endif /* QAK */ /* Re-target transferred row sections to point to new underlying indirect section */ @@ -3485,7 +3378,6 @@ 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 */ @@ -3494,6 +3386,8 @@ H5HF_sect_indirect_merge_row(H5HF_hdr_t *hdr, hid_t dxpl_id, 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 */ + hbool_t merged_rows; /* Flag to indicate that rows was merged together */ + unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_merge_row) @@ -3509,20 +3403,23 @@ H5HF_sect_indirect_merge_row(H5HF_hdr_t *hdr, hid_t dxpl_id, 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; + sect1 = H5HF_sect_indirect_top(row_sect1->u.row.under); + HDassert(sect1); + sect2 = H5HF_sect_indirect_top(row_sect2->u.row.under); + HDassert(sect2); #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); + HDassert(sect1->sect_info.state == H5FS_SECT_LIVE); + HDassert(sect1->u.indirect.span_size > 0); + HDassert(sect1->u.indirect.iblock_entries > 0); + HDassert(sect2->sect_info.state == H5FS_SECT_LIVE); + HDassert(sect2->u.indirect.span_size > 0); + HDassert(sect2->u.indirect.iblock_entries > 0); + HDassert(sect1->u.indirect.iblock_entries == sect2->u.indirect.iblock_entries); /* Set up span information */ start_row1 = sect1->u.indirect.row; @@ -3531,8 +3428,8 @@ HDfprintf(stderr, "%s: sect2->sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect2->sec 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: sect1->u.indirect.dir_nrows = %u\n", FUNC, sect1->u.indirect.dir_nrows); 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); @@ -3543,51 +3440,58 @@ HDfprintf(stderr, "%s: end_row1 = %u, end_col1 = %u, end_entry1 = %u\n", FUNC, e 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: sect2->u.indirect.dir_nrows = %u\n", FUNC, sect2->u.indirect.dir_nrows); 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 direct sections in second section */ + /* (second indirect section can be parent of indirect section for second + * row, and thus have no row sections of it's own) + */ + if(sect2->u.indirect.dir_nrows > 0) { + unsigned new_dir_nrows1; /* New value for number of direct rows in first section */ + unsigned src_row2; /* Source row for copying from second section */ + unsigned nrows_moved2; /* Number of rows to move from second section to first */ + + /* Sanity check child row assumptions */ + /* (second indirect section should be at top of equal or deeper + * hier. of row/indirect sections, so if second indirect section + * has child row sections, first indirect section _must_ have + * them also) + */ + HDassert(sect1->u.indirect.dir_nrows > 0); + HDassert(sect1->u.indirect.dir_rows); - /* Check for sections sharing a row */ - if(end_row1 == start_row2) { + /* Check for sections sharing a row in the same underlying indirect block */ + if(row_sect1->u.row.under->u.indirect.u.iblock->block_off == row_sect2->u.row.under->u.indirect.u.iblock->block_off + && end_row1 == start_row2) { + H5HF_free_section_t *last_row_sect1; /* Last row in first indirect section */ #ifdef QAK HDfprintf(stderr, "%s: Sections share a row\n", FUNC); #endif /* QAK */ + /* Locate the last row section in first indirect section, if we don't already have it */ + if(row_sect1->u.row.row != end_row1) + last_row_sect1 = sect1->u.indirect.dir_rows[sect1->u.indirect.dir_nrows - 1]; + else + last_row_sect1 = row_sect1; + HDassert(last_row_sect1); + HDassert(last_row_sect1->u.row.row == end_row1); + /* 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; + HDassert((last_row_sect1->u.row.col + last_row_sect1->u.row.num_entries) == row_sect2->u.row.col); + last_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; + nrows_moved2 = sect2->u.indirect.dir_nrows - 1; + new_dir_nrows1 = (sect1->u.indirect.dir_nrows + sect2->u.indirect.dir_nrows) - 1; + + /* Indicate that the rows were merged */ + merged_rows = TRUE; } /* end if */ else { #ifdef QAK @@ -3596,159 +3500,292 @@ HDfprintf(stderr, "%s: Sections don't share a row\n", FUNC); /* 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; + nrows_moved2 = sect2->u.indirect.dir_nrows; + new_dir_nrows1 = sect1->u.indirect.dir_nrows + sect2->u.indirect.dir_nrows; + + /* Indicate that the rows were _not_ merged */ + merged_rows = FALSE; } /* end else */ #ifdef QAK +HDfprintf(stderr, "%s: new_dir_nrows1 = %u\n", FUNC, new_dir_nrows1); 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); +HDfprintf(stderr, "%s: nrows_moved2 = %u\n", FUNC, nrows_moved2); #endif /* QAK */ /* Check if we need to move additional rows */ - if(nrows_moved > 0) { + if(nrows_moved2 > 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))) + if(NULL == (sect1->u.indirect.dir_rows = H5MM_realloc(sect1->u.indirect.dir_rows, sizeof(H5HF_free_section_t *) * new_dir_nrows1))) 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)); + (sizeof(H5HF_free_section_t *) * nrows_moved2)); /* Re-target the row sections moved from second section */ - for(u = sect1->u.indirect.dir_nrows; u < new_dir_nrows; u++) + for(u = sect1->u.indirect.dir_nrows; u < new_dir_nrows1; 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 */ + sect1->u.indirect.rc += nrows_moved2; + sect2->u.indirect.rc -= nrows_moved2; - /* 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); + /* Update information for first section */ + sect1->u.indirect.dir_nrows = new_dir_nrows1; + } /* end if */ + } /* end if */ + else + /* Indicate that the rows were _not_ merged */ + merged_rows = FALSE; - /* Copy over any child indirect sections in second section */ + /* Check for indirect sections in second section */ + if(sect2->u.indirect.indir_nents > 0) { + unsigned new_indir_nents1; /* New value for number of indirect entries in first section */ - /* Re-target the child indirect sections moved from second section */ + /* Some sanity checks on second indirect section */ + HDassert(sect2->u.indirect.rc > 0); + HDassert(sect2->u.indirect.indir_ents); - /* Adjust reference counts for transferred child indirect sections */ + /* Set up parameters for transfer of entries */ + new_indir_nents1 = sect1->u.indirect.indir_nents + sect2->u.indirect.indir_nents; -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") + /* Check if first section can just take over second section's memory buffer */ + if(sect1->u.indirect.indir_ents == NULL) { + sect1->u.indirect.indir_ents = sect2->u.indirect.indir_ents; + sect2->u.indirect.indir_ents = NULL; } /* end if */ + else { + /* Extend the first section's entry array */ + if(NULL == (sect1->u.indirect.indir_ents = H5MM_realloc(sect1->u.indirect.indir_ents, sizeof(H5HF_free_section_t *) * new_indir_nents1))) + HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for row section pointer array") + + /* Transfer the second section's entries to first section */ + HDmemcpy(§1->u.indirect.indir_ents[sect1->u.indirect.indir_nents], + §2->u.indirect.indir_ents[0], + (sizeof(H5HF_free_section_t *) * sect2->u.indirect.indir_nents)); + } /* end else */ + + /* Re-target the child indirect sections moved from second section */ + for(u = sect1->u.indirect.indir_nents; u < new_indir_nents1; u++) + sect1->u.indirect.indir_ents[u]->u.indirect.parent = sect1; + + /* Adjust reference counts for transferred child indirect sections */ + sect1->u.indirect.rc += sect2->u.indirect.indir_nents; + sect2->u.indirect.rc -= sect2->u.indirect.indir_nents; /* 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; + sect1->u.indirect.indir_nents = new_indir_nents1; + } /* end if */ + + /* Update information for first section */ + sect1->u.indirect.num_entries += sect2->u.indirect.num_entries; + sect1->u.indirect.span_size += sect2->u.indirect.span_size; - /* 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)); + /* 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) { + /* Wrap up, freeing or re-inserting second row section */ + /* (want this to be after the first indirection section is consistent again) */ + if(merged_rows) { #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 { + /* Release second row section */ + /* (indirectly 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) - */ + /* 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 indirect 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") + row_sect2->sect_info.type = H5HF_FSPACE_SECT_NORMAL_ROW; + if(H5HF_space_add(hdr, dxpl_id, row_sect2, 0) < 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 */ +#ifdef QAK +HDfprintf(stderr, "%s: sect1->u.indirect.iblock_entries = %u\n", FUNC, sect1->u.indirect.iblock_entries); +HDfprintf(stderr, "%s: sect1->u.indirect.num_entries = %u\n", FUNC, sect1->u.indirect.num_entries); +#endif /* QAK */ + /* Check if we can create parent indirect section for first section */ + /* (i.e. merged indirect sections cover an entire indirect block) */ + if(sect1->u.indirect.iblock_entries == sect1->u.indirect.num_entries) { +#ifdef QAK +HDfprintf(stderr, "%s: creating parent indirect section\n", FUNC); +#endif /* QAK */ + /* Build parent section for fully populated indirect section */ + HDassert(sect1->u.indirect.parent == NULL); + if(H5HF_sect_indirect_build_parent(hdr, sect1) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "can't create parent for full indirect section") + } /* end if */ + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_sect_indirect_merge_row() */ /*------------------------------------------------------------------------- - * Function: H5HF_sect_indirect_shrink_row + * Function: H5HF_sect_indirect_build_parent * - * Purpose: "Shrink" an indirect by eliminating it's last row + * Purpose: Build a parent indirect section for a full indirect section * * Return: Success: non-negative * Failure: negative * * Programmer: Quincey Koziol - * Tuesday, July 18, 2006 + * Friday, July 21, 2006 * *------------------------------------------------------------------------- */ static herr_t -H5HF_sect_indirect_shrink_row(H5HF_free_section_t *row_sect) +H5HF_sect_indirect_build_parent(H5HF_hdr_t *hdr, H5HF_free_section_t *sect) { - H5HF_free_section_t *sect; /* Indirect section underlying row section */ + H5HF_indirect_t *par_iblock; /* Indirect block for parent section */ + H5HF_free_section_t *par_sect; /* Parent indirect section */ + unsigned par_row, par_col; /* Row & column in parent indirect section */ + unsigned par_entry; /* Entry within parent indirect section */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_shrink_row) + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_build_parent) +#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 */ /* Sanity check parameters */ - HDassert(row_sect); - HDassert(row_sect->u.row.under); + HDassert(hdr); + HDassert(sect); + HDassert(sect->u.indirect.span_size > 0); + HDassert(sect->u.indirect.iblock_entries > 0); + HDassert(sect->u.indirect.iblock_entries == sect->u.indirect.num_entries); + HDassert(sect->u.indirect.u.iblock); + HDassert(sect->u.indirect.parent == NULL); +#ifdef QAK +HDfprintf(stderr, "%s: sect->u.indirect = {%p, %u, %u, %u}\n", FUNC, sect->u.indirect.u.iblock, sect->u.indirect.row, sect->u.indirect.col, sect->u.indirect.num_entries); +#endif /* QAK */ - /* Set up indirect section information */ - sect = row_sect->u.row.under; + /* Get information for creating parent indirect section */ + par_entry = sect->u.indirect.u.iblock->par_entry; + par_row = par_entry / hdr->man_dtable.cparam.width; + par_col = par_entry % hdr->man_dtable.cparam.width; + HDassert(par_row >= hdr->man_dtable.max_direct_rows); +#ifdef QAK +HDfprintf(stderr, "%s: par_entry = %u, par_row = %u, par_col = %u\n", FUNC, par_entry, par_row, par_col); +#endif /* QAK */ + par_iblock = sect->u.indirect.u.iblock->parent; + HDassert(par_iblock); + + /* Create parent indirect section */ + if(NULL == (par_sect = H5HF_sect_indirect_new(hdr, sect->sect_info.addr, + sect->sect_info.size, par_iblock, par_iblock->block_off, + par_row, par_col, 1))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section") + + /* No rows of direct blocks covered in parent, reset direct row information */ + par_sect->u.indirect.dir_nrows = 0; + par_sect->u.indirect.dir_rows = NULL; + + /* Allocate space for the child indirect sections */ + par_sect->u.indirect.indir_nents = 1; + if(NULL == (par_sect->u.indirect.indir_ents = H5MM_malloc(sizeof(H5HF_free_section_t *)))) + HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for indirect section pointer array") + + /* Attach sections together */ + sect->u.indirect.parent = par_sect; + sect->u.indirect.par_entry = par_entry; + par_sect->u.indirect.indir_ents[0] = sect; + par_sect->u.indirect.rc = 1; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_sect_indirect_build_parent() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_indirect_shrink + * + * Purpose: "Shrink" container w/section + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, July 24, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_indirect_shrink(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect) +{ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_shrink) + + /* Sanity check parameters */ + HDassert(hdr); + HDassert(sect); /* 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); + HDassert(sect->u.indirect.dir_nrows > 0 || sect->u.indirect.indir_nents > 0); +#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 = {%p, %u, %u, %u}\n", FUNC, sect->u.indirect.u.iblock, sect->u.indirect.row, sect->u.indirect.col, sect->u.indirect.num_entries); +HDfprintf(stderr, "%s: sect->u.indirect.span_size = %Hu\n", FUNC, sect->u.indirect.span_size); +HDfprintf(stderr, "%s: sect->u.indirect.parent = %p\n", FUNC, sect->u.indirect.parent); +#endif /* QAK */ - /* Decrement the number of rows */ - /* (other cleanup will be taken care of when the section is freed) */ - sect->u.indirect.dir_nrows--; + /* Walk through direct rows, freeing them */ + for(u = 0; u < sect->u.indirect.dir_nrows; u++) { + /* Remove the normal rows from free space manager */ + if(sect->u.indirect.dir_rows[u]->sect_info.type != H5HF_FSPACE_SECT_FIRST_ROW) { + HDassert(sect->u.indirect.dir_rows[u]->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW); + if(H5HF_space_remove(hdr, dxpl_id, sect->u.indirect.dir_rows[u]) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "can't remove section from heap free space") + } /* end if */ - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5HF_sect_indirect_shrink_row() */ + /* Release the row section */ + if(H5HF_sect_row_free_real(sect->u.indirect.dir_rows[u]) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free child section node") + } /* end for */ + + /* Walk through indirect entries, freeing them (recursively) */ + for(u = 0; u < sect->u.indirect.indir_nents; u++) + if(H5HF_sect_indirect_shrink(hdr, dxpl_id, sect->u.indirect.indir_ents[u]) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free child section node") + + /* Free the indirect section itself */ + if(H5HF_sect_indirect_free(sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_sect_indirect_shrink() */ /*------------------------------------------------------------------------- @@ -3894,8 +3931,8 @@ HDfprintf(stderr, "%s: nentries = %u\n", FUNC, nentries); #endif /* QAK */ /* 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))) + if(NULL == (new_sect = H5HF_sect_indirect_new(hdr, sect_addr, sect_size, + NULL, iblock_off, start_row, start_col, nentries))) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't create indirect section") /* Compute start entry */ @@ -3994,7 +4031,6 @@ H5HF_sect_indirect_valid(const H5FS_section_class_t *row_cls, const H5HF_free_se 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) @@ -4042,22 +4078,38 @@ HDfprintf(stderr, "%s: start_row = %u, start_col = %u, start_entry = %u\n", "H5H 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 */ + /* Sanity check any direct rows */ + if(sect->u.indirect.dir_nrows > 0) { + unsigned dir_nrows; /* Number of direct rows in section */ + unsigned max_dir_row; /* Maximum direct row in 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 */ + /* Check for indirect rows in section */ + if(end_row >= hdr->man_dtable.max_direct_rows) + max_dir_row = hdr->man_dtable.max_direct_rows - 1; + else + max_dir_row = end_row; + + /* Iterate over direct rows, checking pointer references */ + dir_nrows = (max_dir_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->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW + || tmp_row_sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW); + 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 *tmp_row_sect2; /* Pointer to row section */ + + tmp_row_sect2 = sect->u.indirect.dir_rows[u + 1]; + HDassert(tmp_row_sect->u.row.row < tmp_row_sect2->u.row.row); + HDassert(H5F_addr_lt(tmp_row_sect->sect_info.addr, tmp_row_sect2->sect_info.addr)); + HDassert(tmp_row_sect->sect_info.size <= tmp_row_sect2->sect_info.size); + } /* end if */ + } /* end for */ + } /* end if */ FUNC_LEAVE_NOAPI(SUCCEED) } /* H5HF_sect_indirect_valid() */ diff --git a/src/H5HFspace.c b/src/H5HFspace.c index 4634e49..646f07e 100644 --- a/src/H5HFspace.c +++ b/src/H5HFspace.c @@ -138,6 +138,54 @@ done: /*------------------------------------------------------------------------- + * Function: H5HF_space_add + * + * Purpose: Add a section 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_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_add) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(node); + + /* Check if the free space for the heap has been initialized */ + if(!hdr->fspace) + if(H5HF_space_start(hdr, dxpl_id) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize heap free space") + + /* Construct user data */ + udata.hdr = hdr; + udata.dxpl_id = dxpl_id; + + /* Add to the free space for the heap */ + 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_add() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_space_find * * Purpose: Attempt to find space in a fractal heap @@ -185,52 +233,40 @@ done: /*------------------------------------------------------------------------- - * Function: H5HF_space_add + * Function: H5HF_space_remove * - * Purpose: Add a section to the free space for the heap + * Purpose: Remove a section from the free space for the heap * * Return: Success: non-negative - * * Failure: negative * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu - * May 15 2006 + * July 24 2006 * *------------------------------------------------------------------------- */ herr_t -H5HF_space_add(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *node, - unsigned flags) +H5HF_space_remove(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *node) { - 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_add) + FUNC_ENTER_NOAPI_NOINIT(H5HF_space_remove) /* * Check arguments. */ HDassert(hdr); + HDassert(hdr->fspace); HDassert(node); - /* Check if the free space for the heap has been initialized */ - if(!hdr->fspace) - if(H5HF_space_start(hdr, dxpl_id) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize heap free space") - - /* Construct user data */ - udata.hdr = hdr; - udata.dxpl_id = dxpl_id; - 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, flags, &udata) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "can't add section to heap free space") + /* Remove from the free space for the heap */ + if(H5FS_remove(hdr->f, dxpl_id, hdr->fspace, (H5FS_section_info_t *)node) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "can't remove section from heap free space") done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_space_add() */ +} /* end H5HF_space_remove() */ /*------------------------------------------------------------------------- @@ -310,6 +346,9 @@ H5HF_space_sect_change_class(H5HF_hdr_t *hdr, H5HF_free_section_t *sect, unsigne herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_space_sect_change_class) +#ifdef QAK +HDfprintf(stderr, "%s: Called\n", FUNC); +#endif /* QAK */ /* * Check arguments. @@ -1324,7 +1324,7 @@ H5SL_prev(H5SL_node_t *slist_node) NAME H5SL_last PURPOSE - Gets a pointer to the lsat node in a skip list + Gets a pointer to the last node in a skip list USAGE H5SL_node_t *H5SL_last(slist) H5SL_t *slist; IN: Pointer to skip list diff --git a/test/fheap.c b/test/fheap.c index 5fef553..be72650 100644 --- a/test/fheap.c +++ b/test/fheap.c @@ -13535,7 +13535,7 @@ HDfprintf(stderr, "Uncomment tests!\n"); #endif /* QAK */ #ifndef QAK -#ifndef QAK +#ifndef QAK2 { fheap_test_del_dir_t del_dir; /* Deletion direction */ fheap_test_del_drain_t drain_half; /* Deletion draining */ @@ -13545,13 +13545,13 @@ HDfprintf(stderr, "Uncomment tests!\n"); tparam.drain_half = drain_half; for(del_dir = HEAP_DEL_FORWARD; del_dir < HEAP_DEL_NDIRS; del_dir++) { tparam.del_dir = del_dir; -#else /* QAK */ +#else /* QAK2 */ HDfprintf(stderr, "Uncomment test loops!\n"); /* tparam.drain_half = HEAP_DEL_DRAIN_ALL; */ tparam.drain_half = HEAP_DEL_DRAIN_HALF; -tparam.del_dir = HEAP_DEL_FORWARD; -/* tparam.del_dir = HEAP_DEL_REVERSE; */ -#endif /* QAK */ +/* tparam.del_dir = HEAP_DEL_FORWARD; */ +tparam.del_dir = HEAP_DEL_REVERSE; +#endif /* QAK2 */ #ifndef QAK #ifndef QAK2 @@ -13568,11 +13568,11 @@ HDfprintf(stderr, "Uncomment tests!\n"); #else /* QAK */ HDfprintf(stderr, "Uncomment tests!\n"); #endif /* QAK */ -#ifndef QAK +#ifndef QAK2 } /* end for */ } /* end for */ } /* end block */ -#endif /* QAK */ +#endif /* QAK2 */ #else /* QAK */ HDfprintf(stderr, "Uncomment tests!\n"); #endif /* QAK */ |