diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2006-07-31 09:54:09 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2006-07-31 09:54:09 (GMT) |
commit | 87449d081d1c99312034d917502f2b6aca2ee60c (patch) | |
tree | d21839e74c6602b9a60ce383207001675b4b5ebd /src | |
parent | ce859f41bb12e07ecb8dff6a783ca21e782ad6fe (diff) | |
download | hdf5-87449d081d1c99312034d917502f2b6aca2ee60c.zip hdf5-87449d081d1c99312034d917502f2b6aca2ee60c.tar.gz hdf5-87449d081d1c99312034d917502f2b6aca2ee60c.tar.bz2 |
[svn-r12517] Description:
Fix the last scattered bunch of problems with the object deletion code,
which appears to be completely working now (for objects that are stored
within heap blocks - standalone objects aren't implemented yet).
Also, re-work the regression test to speed up some of the existing tests
and add in 100-200 more combinations of tests - overall, its probably even
slower than it was... :-/
Tested:
FreeBSD 4.11 (sleipnir)
Linux 2.4 (chicago)
Mac OS X (amazon)
Diffstat (limited to 'src')
-rw-r--r-- | src/H5FS.c | 187 | ||||
-rw-r--r-- | src/H5FSprivate.h | 5 | ||||
-rw-r--r-- | src/H5HF.c | 17 | ||||
-rw-r--r-- | src/H5HFdbg.c | 12 | ||||
-rw-r--r-- | src/H5HFdblock.c | 4 | ||||
-rw-r--r-- | src/H5HFdtable.c | 85 | ||||
-rw-r--r-- | src/H5HFhdr.c | 58 | ||||
-rw-r--r-- | src/H5HFiblock.c | 4 | ||||
-rw-r--r-- | src/H5HFint.c | 5 | ||||
-rw-r--r-- | src/H5HFpkg.h | 9 | ||||
-rw-r--r-- | src/H5HFsection.c | 725 |
11 files changed, 760 insertions, 351 deletions
@@ -127,6 +127,8 @@ static herr_t H5FS_sect_link_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, const H5FS_section_class_t *cls, H5FS_section_info_t *sect); static herr_t H5FS_sect_link(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *sect); +static herr_t H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, + H5FS_section_info_t **sect, void *op_data); static htri_t H5FS_find_bin_node(H5FS_t *fspace, hsize_t request, H5FS_section_info_t **node); static herr_t H5FS_serialize_sect_cb(void *_item, void UNUSED *key, void *_udata); static herr_t H5FS_serialize_node_cb(void *_item, void UNUSED *key, void *_udata); @@ -1363,94 +1365,95 @@ H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, /* Check arguments. */ HDassert(fspace); - HDassert(fspace->merge_list); HDassert(*sect); HDassert(H5F_addr_defined((*sect)->addr)); HDassert((*sect)->size); /* Loop until no more merging */ - do { - H5FS_section_class_t *tmp_sect_cls; /* Temporary section's class */ - - /* 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) { - /* 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") - if(status > 0) { - /* Sanity check */ - HDassert(tmp_sect_cls->merge); - - /* 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") - - /* Merge the two sections together */ - if((*tmp_sect_cls->merge)(tmp_sect_node, *sect, op_data) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't merge two sections") - - /* Retarget section pointer to 'less than' node that was merged into */ - *sect = tmp_sect_node; - - /* Indicate successful merge occurred */ - modified = TRUE; + if(fspace->merge_list) { + do { + H5FS_section_class_t *tmp_sect_cls; /* Temporary section's class */ + + /* 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) { + /* 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") + if(status > 0) { + /* Sanity check */ + HDassert(tmp_sect_cls->merge); + + /* 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") + + /* Merge the two sections together */ + if((*tmp_sect_cls->merge)(tmp_sect_node, *sect, op_data) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't merge two sections") + + /* Retarget section pointer to 'less than' node that was merged into */ + *sect = tmp_sect_node; + + /* Indicate successful merge occurred */ + modified = TRUE; + } /* end if */ } /* end if */ } /* end if */ - } /* end if */ - /* Look for section after new (or merged) section */ - tmp_sect_node = H5SL_greater(fspace->merge_list, &(*sect)->addr); - - /* Check for node after new node able to merge with new node */ - if(tmp_sect_node) { - /* 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 = (*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(sect_cls->merge); - - /* Remove 'greater 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") - - /* Merge the two sections together */ - if((*sect_cls->merge)(*sect, tmp_sect_node, op_data) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't merge two sections") - - /* Indicate successful merge occurred */ - modified = TRUE; + /* Look for section after new (or merged) section */ + tmp_sect_node = H5SL_greater(fspace->merge_list, &(*sect)->addr); + + /* Check for node after new node able to merge with new node */ + if(tmp_sect_node) { + /* 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 = (*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(sect_cls->merge); + + /* Remove 'greater 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") + + /* Merge the two sections together */ + if((*sect_cls->merge)(*sect, tmp_sect_node, op_data) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't merge two sections") + + /* Indicate successful merge occurred */ + modified = TRUE; + } /* end if */ } /* end if */ } /* end if */ - } /* end if */ - } while(modified); + } while(modified); + } /* end if */ 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")); @@ -1471,7 +1474,14 @@ HDfprintf(stderr, "%s: Done merging, (*sect) = {%a, %Hu, %u, %s}\n", FUNC, (*sec HDfprintf(stderr, "%s: Can shrink!\n", FUNC); #endif /* QAK */ /* Look for neighboring section before new section */ - tmp_sect_node = H5SL_less(fspace->merge_list, &(*sect)->addr); + if(fspace->merge_list) { + tmp_sect_node = H5SL_less(fspace->merge_list, &(*sect)->addr); + + /* Make certain there isn't a section after the new section */ + HDassert(H5SL_greater(fspace->merge_list, &(*sect)->addr) == NULL); + } /* end if */ + else + tmp_sect_node = NULL; /* Shrink the container */ /* (callback can indicate that it has discarded the section by setting *sect to NULL) */ @@ -1527,12 +1537,13 @@ herr_t H5FS_add(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *sect, unsigned flags, void *op_data) { + H5FS_section_class_t *cls; /* Section's class */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5FS_add, FAIL) #ifdef QAK -HDfprintf(stderr, "%s: sect->size = %Hu, sect->addr = %a, sect->type = %u\n", FUNC, sect->size, sect->addr, sect->type); +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")); #endif /* QAK */ /* Check arguments. */ @@ -1548,8 +1559,15 @@ HDfprintf(stderr, "%s: sect->size = %Hu, sect->addr = %a, sect->type = %u\n", FU HGOTO_ERROR(H5E_FSPACE, H5E_CANTDECODE, FAIL, "can't deserialize sections") } /* end if */ + /* Call "add" section class callback, if there is one */ + cls = &fspace->sect_cls[sect->type]; + if(cls->add) { + if((*cls->add)(sect, &flags, op_data) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "'add' section class callback failed") + } /* end if */ + /* Check for merging returned space with existing section node */ - if((flags & H5FS_ADD_RETURNED_SPACE) && fspace->hdr->tot_sect_count > 0) { + if(flags & H5FS_ADD_RETURNED_SPACE) { #ifdef QAK HDfprintf(stderr, "%s: Returning space\n", FUNC); #endif /* QAK */ @@ -1577,7 +1595,7 @@ HDfprintf(stderr, "%s: fspace->hdr->tot_space = %Hu\n", FUNC, fspace->hdr->tot_s done: #ifdef H5FS_DEBUG -if(!(flags & H5FS_ADD_DESERIALIZING)) +if(!(flags & (H5FS_ADD_DESERIALIZING | H5FS_ADD_SKIP_VALID))) H5FS_assert(fspace); #endif /* H5FS_DEBUG */ FUNC_LEAVE_NOAPI(ret_value) @@ -2776,9 +2794,6 @@ HDfprintf(stderr, "%s: removing object from merge list, sect->type = %u\n", FUNC fspace->dirty = TRUE; done: -#ifdef H5FS_DEBUG - H5FS_assert(fspace); -#endif /* H5FS_DEBUG */ FUNC_LEAVE_NOAPI(ret_value) } /* H5FS_sect_change_class() */ @@ -3216,7 +3231,9 @@ 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)); +#ifdef QAK HDassert(fspace->hdr->serial_sect_count > 0 || fspace->hdr->ghost_sect_count == 0); +#endif /* QAK */ /* Make certain that the number of sections on the address list is correct */ if(fspace->merge_list) diff --git a/src/H5FSprivate.h b/src/H5FSprivate.h index 2b840bd..dfbefa7 100644 --- a/src/H5FSprivate.h +++ b/src/H5FSprivate.h @@ -58,6 +58,10 @@ * as a result of freeing an * object) */ +#define H5FS_ADD_SKIP_VALID 0x04 /* Don't check validity after adding + * this section. (state of the + * managed sections is in flux) + */ /* Flags for deserialize callback */ #define H5FS_DESERIALIZE_NO_ADD 0x01 /* Don't add section to free space @@ -90,6 +94,7 @@ typedef struct H5FS_section_class_t { herr_t (*term_cls)(struct H5FS_section_class_t *); /* Routine to terminate class-specific settings */ /* Object methods */ + herr_t (*add)(H5FS_section_info_t *, unsigned *, void *); /* Routine called when section is about to be added to manager */ 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)(const H5FS_section_info_t *, const H5FS_section_info_t *, void *); /* Routine to determine if two nodes are mergable */ @@ -354,7 +354,7 @@ HDfprintf(stderr, "%s: size = %Zu\n", FUNC, size); hdr = fh->hdr; /* Check if object is large enough to be standalone */ - if(size >= hdr->standalone_size) { + if(size > hdr->standalone_size) { HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "standalone blocks not supported yet") } /* end if */ else { @@ -582,8 +582,19 @@ H5HF_close(H5HF_t *fh, hid_t dxpl_id) * a reference loop and the objects couldn't be removed from * the metadata cache - QAK) */ - if(H5HF_man_iter_reset(&fh->hdr->next_block) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't reset block iterator") +#ifdef QAK +HDfprintf(stderr, "%s; fh->hdr->man_iter_off = %Hu\n", FUNC, fh->hdr->man_iter_off); +HDfprintf(stderr, "%s; fh->hdr->man_size = %Hu\n", FUNC, fh->hdr->man_size); +HDfprintf(stderr, "%s; fh->hdr->rc = %Zu\n", FUNC, fh->hdr->rc); +#endif /* QAK */ + /* Reset block iterator, if necessary */ + if(H5HF_man_iter_ready(&fh->hdr->next_block)) { + if(H5HF_man_iter_reset(&fh->hdr->next_block) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't reset block iterator") + } /* end if */ +#ifdef QAK +HDfprintf(stderr, "%s; After iterator reset fh->hdr->rc = %Zu\n", FUNC, fh->hdr->rc); +#endif /* QAK */ /* Decrement the reference count on the heap header */ if(H5HF_hdr_decr(fh->hdr) < 0) diff --git a/src/H5HFdbg.c b/src/H5HFdbg.c index 2d878f9..52227a6 100644 --- a/src/H5HFdbg.c +++ b/src/H5HFdbg.c @@ -622,20 +622,22 @@ H5HF_sects_debug_cb(const H5FS_section_info_t *_sect, void *_udata) HDassert(udata); /* Print generic section information */ + HDfprintf(udata->stream, "%*s%-*s %s\n", udata->indent, "", udata->fwidth, + "Section type:", + (sect->sect_info.type == H5HF_FSPACE_SECT_SINGLE ? "single" : + (sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ? "first row" : + (sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW ? "normal row" : "unknown")))); HDfprintf(udata->stream, "%*s%-*s %a\n", udata->indent, "", udata->fwidth, "Section address:", sect->sect_info.addr); HDfprintf(udata->stream, "%*s%-*s %Hu\n", udata->indent, "", udata->fwidth, "Section size:", sect->sect_info.size); - HDfprintf(udata->stream, "%*s%-*s %s\n", udata->indent, "", udata->fwidth, - "Section type:", - (sect->sect_info.type == H5HF_FSPACE_SECT_SINGLE ? "single" : - (sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ? "first row" : - (sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ? "normal row" : "unknown")))); +#ifdef QAK HDfprintf(udata->stream, "%*s%-*s %s\n", udata->indent, "", udata->fwidth, "Section state:", (sect->sect_info.state == H5FS_SECT_LIVE ? "live" : "serialized")); +#endif /* QAK */ /* Dump section-specific debugging information */ if(H5FS_sect_debug(udata->fspace, _sect, udata->stream, udata->indent + 3, MAX(0, udata->fwidth - 3)) < 0) diff --git a/src/H5HFdblock.c b/src/H5HFdblock.c index 590d8f3..00821e9 100644 --- a/src/H5HFdblock.c +++ b/src/H5HFdblock.c @@ -394,14 +394,14 @@ HDfprintf(stderr, "%s: root direct block, dblock_addr = %a\n", FUNC, dblock_addr size_t next_size; /* Size of next direct block to create */ #ifdef QAK -HDfprintf(stderr, "%s: before updating iterator\n", FUNC); +HDfprintf(stderr, "%s: before updating iterator, hdr->man_iter_off = %Hu, hdr->man_size = %Hu\n", FUNC, hdr->man_iter_off, hdr->man_size); #endif /* QAK */ /* Update iterator to reflect any previous increments as well as allow for requested direct block size */ if(H5HF_hdr_update_iter(hdr, dxpl_id, min_dblock_size) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTUPDATE, FAIL, "unable to update block iterator") #ifdef QAK -HDfprintf(stderr, "%s: after updating iterator\n", FUNC); +HDfprintf(stderr, "%s: after updating iterator, hdr->man_iter_off = %Hu\n", FUNC, hdr->man_iter_off); #endif /* QAK */ /* Retrieve information about current iterator position */ if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL, &next_entry, &iblock) < 0) diff --git a/src/H5HFdtable.c b/src/H5HFdtable.c index 4c41805..e0e2ff9 100644 --- a/src/H5HFdtable.c +++ b/src/H5HFdtable.c @@ -231,7 +231,7 @@ H5HF_dtable_dest(H5HF_dtable_t *dtable) *------------------------------------------------------------------------- */ unsigned -H5HF_dtable_size_to_row(H5HF_dtable_t *dtable, size_t block_size) +H5HF_dtable_size_to_row(const H5HF_dtable_t *dtable, size_t block_size) { unsigned row; /* Row where block will fit */ @@ -265,7 +265,7 @@ H5HF_dtable_size_to_row(H5HF_dtable_t *dtable, size_t block_size) *------------------------------------------------------------------------- */ unsigned -H5HF_dtable_size_to_rows(H5HF_dtable_t *dtable, hsize_t size) +H5HF_dtable_size_to_rows(const H5HF_dtable_t *dtable, hsize_t size) { unsigned rows; /* # of rows required for indirect block */ @@ -281,3 +281,84 @@ H5HF_dtable_size_to_rows(H5HF_dtable_t *dtable, hsize_t size) FUNC_LEAVE_NOAPI(rows) } /* end H5HF_dtable_size_to_rows() */ + +/*------------------------------------------------------------------------- + * Function: H5HF_dtable_span_size + * + * Purpose: Compute the size covered by a span of entries + * + * Return: Non-zero span size on success/zero on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * July 25 2006 + * + *------------------------------------------------------------------------- + */ +hsize_t +H5HF_dtable_span_size(const H5HF_dtable_t *dtable, unsigned start_row, + unsigned start_col, unsigned num_entries) +{ + unsigned start_entry; /* Entry for first block covered */ + unsigned end_row; /* Row for last block covered */ + unsigned end_col; /* Column for last block covered */ + unsigned end_entry; /* Entry for last block covered */ + hsize_t acc_span_size; /* Accumulated span size */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_dtable_span_size) + + /* + * Check arguments. + */ + HDassert(dtable); + HDassert(num_entries > 0); + + /* Compute starting entry */ + start_entry = (start_row * dtable->cparam.width) + start_col; + + /* Compute ending entry, column & row */ + end_entry = (start_entry + num_entries) - 1; + end_row = end_entry / dtable->cparam.width; + end_col = end_entry % dtable->cparam.width; +#ifdef QAK +HDfprintf(stderr, "%s: start_row = %u, start_col = %u, start_entry = %u\n", "H5HF_sect_indirect_span_size", start_row, start_col, start_entry); +HDfprintf(stderr, "%s: end_row = %u, end_col = %u, end_entry = %u\n", "H5HF_sect_indirect_span_size", end_row, end_col, end_entry); +#endif /* QAK */ + + /* Initialize accumulated span size */ + acc_span_size = 0; + + /* Compute span size covered */ + + /* Check for multi-row span */ + if(start_row != end_row) { + /* Accomodate partial starting row */ + if(start_col > 0) { + acc_span_size = dtable->row_block_size[start_row] * + (dtable->cparam.width - start_col); + start_row++; + } /* end if */ + + /* Accumulate full rows */ + while(start_row < end_row) { + acc_span_size += dtable->row_block_size[start_row] * + dtable->cparam.width; + start_row++; + } /* end while */ + + /* Accomodate partial ending row */ + acc_span_size += dtable->row_block_size[start_row] * + (end_col + 1); + } /* end if */ + else { + /* Span is in same row */ + acc_span_size = dtable->row_block_size[start_row] * + ((end_col - start_col) + 1); + } /* end else */ + +#ifdef QAK +HDfprintf(stderr, "%s: acc_span_size = %Hu\n", "H5HF_dtable_span_size", acc_span_size); +#endif /* QAK */ + FUNC_LEAVE_NOAPI(acc_span_size) +} /* end H5HF_sect_indirect_span_size() */ + diff --git a/src/H5HFhdr.c b/src/H5HFhdr.c index fc67aed..69efdbc 100644 --- a/src/H5HFhdr.c +++ b/src/H5HFhdr.c @@ -270,6 +270,7 @@ done: herr_t H5HF_hdr_init(H5HF_hdr_t *hdr, haddr_t fh_addr, H5HF_create_t *cparam) { + size_t dblock_overhead; /* Direct block's overhead */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_init) @@ -325,6 +326,12 @@ H5HF_hdr_init(H5HF_hdr_t *hdr, haddr_t fh_addr, H5HF_create_t *cparam) if(H5HF_hdr_finish_init(hdr) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create ref-count wrapper for shared fractal heap header") + /* Extra checking for possible gap between max. direct block size minus + * overhead and standalone object size */ + dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr); + if((cparam->managed.max_direct_size - dblock_overhead) < cparam->standalone_size) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "max. direct block size not large enough to hold all managed blocks") + done: if(ret_value < 0) if(hdr) @@ -516,6 +523,12 @@ H5HF_hdr_adjust_heap(H5HF_hdr_t *hdr, hsize_t new_size, hssize_t extra_free) * Check arguments. */ HDassert(hdr); +#ifdef QAK +HDfprintf(stderr, "%s; new_size = %Hu, extra_free = %Hd\n", FUNC, new_size, extra_free); +HDfprintf(stderr, "%s; hdr->total_size = %Hu\n", FUNC, hdr->total_size); +HDfprintf(stderr, "%s; hdr->man_size = %Hu\n", FUNC, hdr->man_size); +HDfprintf(stderr, "%s; hdr->total_man_free = %Hu\n", FUNC, hdr->total_man_free); +#endif /* QAK */ /* Set the total space in heap */ hdr->total_size = new_size; @@ -635,6 +648,9 @@ H5HF_hdr_reset_iter(H5HF_hdr_t *hdr, hsize_t curr_off) HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't reset block iterator") /* Set the offset of the iterator in the heap */ +#ifdef QAK +HDfprintf(stderr, "%s: hdr->man_iter_off = %Hu, curr_off = %Hu\n", FUNC, hdr->man_iter_off, curr_off); +#endif /* QAK */ hdr->man_iter_off = curr_off; done: @@ -659,7 +675,8 @@ herr_t H5HF_hdr_skip_blocks(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_indirect_t *iblock, unsigned start_entry, unsigned nentries) { - hsize_t sect_off; /* Offset of section in heap space */ + unsigned row, col; /* Row & column of entry */ + hsize_t sect_size; /* Size of section in heap space */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_skip_blocks) @@ -674,16 +691,25 @@ HDfprintf(stderr, "%s: start_entry = %u, nentries = %u\n", FUNC, start_entry, ne HDassert(iblock); HDassert(nentries); - /* Add 'indirect' section for blocks skipped in this row */ - if(H5HF_sect_indirect_add(hdr, dxpl_id, iblock, start_entry, nentries, §_off) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section for indirect block's free space") + /* Compute the span within the heap to skip */ + row = start_entry / hdr->man_dtable.cparam.width; + col = start_entry % hdr->man_dtable.cparam.width; + sect_size = H5HF_dtable_span_size(&hdr->man_dtable, row, col, nentries); #ifdef QAK -HDfprintf(stderr, "%s: sect_off = %Hu\n", FUNC, sect_off); +HDfprintf(stderr, "%s: Check 1.0 - hdr->man_iter_off = %Hu, sect_size = %Hu\n", FUNC, hdr->man_iter_off, sect_size); #endif /* QAK */ + HDassert(sect_size > 0); /* Advance the new block iterator */ - if(H5HF_hdr_inc_iter(hdr, (sect_off - hdr->man_iter_off), nentries) < 0) + if(H5HF_hdr_inc_iter(hdr, sect_size, nentries) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't increase allocated heap size") +#ifdef QAK +HDfprintf(stderr, "%s: Check 2.0 - hdr->man_iter_off = %Hu\n", FUNC, hdr->man_iter_off); +#endif /* QAK */ + + /* Add 'indirect' section for blocks skipped in this row */ + if(H5HF_sect_indirect_add(hdr, dxpl_id, iblock, start_entry, nentries) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section for indirect block's free space") done: FUNC_LEAVE_NOAPI(ret_value) @@ -1092,9 +1118,12 @@ HDfprintf(stderr, "%s: curr_entry = %u\n", FUNC, curr_entry); #ifdef QAK HDfprintf(stderr, "%s: Heap empty\n", FUNC); #endif /* QAK */ - /* Reset header information back to "empty heap" state */ - if(H5HF_hdr_empty(hdr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't make heap empty") + /* Reset iterator offset */ + hdr->man_iter_off = 0; + + /* Reset 'next block' iterator */ + if(H5HF_man_iter_reset(&hdr->next_block) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't reset block iterator") } /* end else */ } /* end if */ else { @@ -1194,12 +1223,21 @@ H5HF_hdr_empty(H5HF_hdr_t *hdr) FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_empty) #ifdef QAK -HDfprintf(stderr, "%s: Reseting heap header to empty\n", FUNC); +HDfprintf(stderr, "%s: Resetting heap header to empty\n", FUNC); #endif /* QAK */ /* Sanity check */ HDassert(hdr); + /* Reset block iterator, if necessary */ + if(H5HF_man_iter_ready(&hdr->next_block)) { +#ifdef QAK +HDfprintf(stderr, "%s: 'next block' iterator is ready\n", FUNC); +#endif /* QAK */ + if(H5HF_man_iter_reset(&hdr->next_block) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't reset block iterator") + } /* end if */ + /* Shrink heap size */ hdr->total_size = hdr->std_size; hdr->man_size = 0; diff --git a/src/H5HFiblock.c b/src/H5HFiblock.c index f48b4c2..3970a7e 100644 --- a/src/H5HFiblock.c +++ b/src/H5HFiblock.c @@ -181,6 +181,10 @@ HDfprintf(stderr, "%s: Removing indirect block from cache, iblock->addr = %a\n", /* Reset root pointer information */ iblock->hdr->man_dtable.curr_root_rows = 0; iblock->hdr->man_dtable.table_addr = HADDR_UNDEF; + + /* Reset header information back to "empty heap" state */ + if(H5HF_hdr_empty(iblock->hdr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't make heap empty") } /* end if */ /* Detach from parent indirect block */ diff --git a/src/H5HFint.c b/src/H5HFint.c index e9fe631..8964c29 100644 --- a/src/H5HFint.c +++ b/src/H5HFint.c @@ -281,7 +281,7 @@ H5HF_man_insert(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sec_node, size_t obj_size, const void *obj, void *id) { H5HF_direct_t *dblock = NULL; /* Pointer to direct block to modify */ - haddr_t dblock_addr; /* Direct block address */ + haddr_t dblock_addr = HADDR_UNDEF; /* Direct block address */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_insert) @@ -386,6 +386,9 @@ HDfprintf(stderr, "%s: blk_off = %Zu\n", FUNC, blk_off); HDfprintf(stderr, "%s: dblock->block_off = %Hu\n", FUNC, dblock->block_off); #endif /* QAK */ H5HF_ID_ENCODE(id, hdr, (dblock->block_off + blk_off), obj_size); +#ifdef QAK +HDfprintf(stderr, "%s: obj_off = %Hu, obj_len = %Zu\n", FUNC, (dblock->block_off + blk_off), obj_size); +#endif /* QAK */ } /* end if */ else { HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "inserting within mapped managed blocks not supported yet") diff --git a/src/H5HFpkg.h b/src/H5HFpkg.h index aa7c3bf..725e5bb 100644 --- a/src/H5HFpkg.h +++ b/src/H5HFpkg.h @@ -416,8 +416,10 @@ H5_DLL herr_t H5HF_dtable_init(H5HF_dtable_t *dtable); H5_DLL herr_t H5HF_dtable_dest(H5HF_dtable_t *dtable); H5_DLL herr_t H5HF_dtable_lookup(const H5HF_dtable_t *dtable, hsize_t off, unsigned *row, unsigned *col); -H5_DLL unsigned H5HF_dtable_size_to_row(H5HF_dtable_t *dtable, size_t block_size); -H5_DLL unsigned H5HF_dtable_size_to_rows(H5HF_dtable_t *dtable, hsize_t size); +H5_DLL unsigned H5HF_dtable_size_to_row(const H5HF_dtable_t *dtable, size_t block_size); +H5_DLL unsigned H5HF_dtable_size_to_rows(const H5HF_dtable_t *dtable, hsize_t size); +H5_DLL hsize_t H5HF_dtable_span_size(const H5HF_dtable_t *dtable, unsigned start_row, + unsigned start_col, unsigned num_entries); /* Heap header routines */ H5_DLL herr_t H5HF_hdr_incr(H5HF_hdr_t *hdr); @@ -545,8 +547,7 @@ H5_DLL herr_t H5HF_sect_row_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect, unsigned *entry_p); H5_DLL H5HF_indirect_t *H5HF_sect_row_get_iblock(H5HF_free_section_t *sect); H5_DLL herr_t H5HF_sect_indirect_add(H5HF_hdr_t *hdr, hid_t dxpl_id, - H5HF_indirect_t *iblock, unsigned start_entry, unsigned nentries, - hsize_t *sect_off); + H5HF_indirect_t *iblock, unsigned start_entry, unsigned nentries); /* Testing routines */ #ifdef H5HF_TESTING diff --git a/src/H5HFsection.c b/src/H5HFsection.c index 8888d06..fbc514b 100644 --- a/src/H5HFsection.c +++ b/src/H5HFsection.c @@ -39,15 +39,23 @@ /* Local Macros */ /****************/ +/* Size of serialized indirect section information */ +#define H5HF_SECT_INDIRECT_SERIAL_SIZE(h) ( \ + (h)->heap_off_size /* Indirect block's offset in "heap space" */ \ + + 2 /* Row */ \ + + 2 /* Column */ \ + + 2 /* # of entries */ \ + ) + /******************/ /* Local Typedefs */ /******************/ -/* Typedef for "class private" information for indirect sections */ +/* Typedef for "class private" information for sections */ typedef struct { H5HF_hdr_t *hdr; /* Pointer to fractal heap header */ -} H5HF_sect_indirect_private_t; +} H5HF_sect_private_t; /********************/ @@ -60,12 +68,21 @@ typedef struct { /********************/ /* Shared routines */ +static herr_t H5HF_sect_init_cls(H5FS_section_class_t *cls, + H5HF_hdr_t *hdr); +static herr_t H5HF_sect_term_cls(H5FS_section_class_t *cls); static H5HF_free_section_t *H5HF_sect_node_new(unsigned sect_type, haddr_t sect_addr, hsize_t sect_size, H5FS_section_state_t state); static herr_t H5HF_sect_node_free(H5HF_free_section_t *sect, H5HF_indirect_t *parent); +/* 'single' section routines */ +static herr_t H5HF_sect_single_full_dblock(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_free_section_t *sect); + /* 'single' section callbacks */ +static herr_t H5HF_sect_single_add(H5FS_section_info_t *sect, unsigned *flags, + void *udata); 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); @@ -109,6 +126,8 @@ static herr_t H5HF_sect_row_shrink(H5FS_section_info_t **sect, static herr_t H5HF_sect_row_free(H5FS_section_info_t *sect); static herr_t H5HF_sect_row_valid(const H5FS_section_class_t *cls, const H5FS_section_info_t *sect); +static herr_t H5HF_sect_row_debug(const H5FS_section_info_t *sect, + FILE *stream, int indent, int fwidth); /* 'indirect' section routines */ static H5HF_free_section_t *H5HF_sect_indirect_new(H5HF_hdr_t *hdr, @@ -116,8 +135,9 @@ static H5HF_free_section_t *H5HF_sect_indirect_new(H5HF_hdr_t *hdr, H5HF_indirect_t *iblock, hsize_t iblock_off, unsigned row, unsigned col, unsigned nentries); static herr_t H5HF_sect_indirect_init_rows(H5HF_hdr_t *hdr, hid_t dxpl_id, - H5HF_free_section_t *sect, hbool_t first_child, unsigned space_flags, - unsigned start_row, unsigned start_col, unsigned end_row, unsigned end_col); + H5HF_free_section_t *sect, hbool_t first_child, H5HF_free_section_t **first_row_sect, + unsigned space_flags, unsigned start_row, unsigned start_col, + unsigned end_row, unsigned end_col); static H5HF_free_section_t *H5HF_sect_indirect_for_row(H5HF_hdr_t *hdr, H5HF_indirect_t *iblock, H5HF_free_section_t *row_sect); static herr_t H5HF_sect_indirect_decr(H5HF_free_section_t *sect); @@ -132,8 +152,6 @@ static herr_t H5HF_sect_indirect_reduce(H5HF_hdr_t *hdr, static herr_t H5HF_sect_indirect_first(H5HF_hdr_t *hdr, H5HF_free_section_t *sect); static hbool_t H5HF_sect_indirect_is_first(H5HF_free_section_t *sect); static H5HF_indirect_t * H5HF_sect_indirect_get_iblock(H5HF_free_section_t *sect); -static herr_t H5HF_sect_indirect_span_size(H5HF_hdr_t *hdr, - H5HF_free_section_t *sect); static 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, @@ -147,14 +165,14 @@ static H5FS_section_info_t *H5HF_sect_indirect_deserialize(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size, unsigned *des_flags); static herr_t H5HF_sect_indirect_free(H5HF_free_section_t *sect); -static herr_t H5HF_sect_indirect_valid(const H5FS_section_class_t *row_cls, - const H5HF_free_section_t *row_sect); +static herr_t H5HF_sect_indirect_valid(const H5HF_hdr_t *hdr, + const H5HF_free_section_t *sect); +static herr_t H5HF_sect_indirect_debug(const H5HF_free_section_t *sect, + FILE *stream, int indent, int fwidth); /* 'indirect' section callbacks */ static herr_t H5HF_sect_indirect_init_cls(H5FS_section_class_t *cls, void *udata); static herr_t H5HF_sect_indirect_term_cls(H5FS_section_class_t *cls); -static herr_t H5HF_sect_indirect_debug(const H5FS_section_info_t *sect, - FILE *stream, int indent, int fwidth); /*********************/ @@ -174,6 +192,7 @@ H5FS_section_class_t H5HF_FSPACE_SECT_CLS_SINGLE[1] = {{ NULL, /* Terminate section class */ /* Object methods */ + H5HF_sect_single_add, /* Add section */ NULL, /* Serialize section */ H5HF_sect_single_deserialize, /* Deserialize section */ H5HF_sect_single_can_merge, /* Can sections merge? */ @@ -201,6 +220,7 @@ H5FS_section_class_t H5HF_FSPACE_SECT_CLS_FIRST_ROW[1] = {{ H5HF_sect_row_term_cls, /* Terminate section class */ /* Object methods */ + NULL, /* Add section */ H5HF_sect_row_serialize, /* Serialize section */ H5HF_sect_row_deserialize, /* Deserialize section */ H5HF_sect_row_can_merge, /* Can sections merge? */ @@ -209,7 +229,7 @@ H5FS_section_class_t H5HF_FSPACE_SECT_CLS_FIRST_ROW[1] = {{ H5HF_sect_row_shrink, /* Shrink container w/section */ H5HF_sect_row_free, /* Free section */ H5HF_sect_row_valid, /* Check validity of section */ - NULL, /* Dump debugging for section */ + H5HF_sect_row_debug, /* Dump debugging for section */ }}; /* Class info for "normal row" free space sections */ @@ -221,10 +241,11 @@ H5FS_section_class_t H5HF_FSPACE_SECT_CLS_NORMAL_ROW[1] = {{ NULL, /* Class private info */ /* Class methods */ - NULL, /* Initialize section class */ - NULL, /* Terminate section class */ + H5HF_sect_row_init_cls, /* Initialize section class */ + H5HF_sect_row_term_cls, /* Terminate section class */ /* Object methods */ + NULL, /* Add section */ NULL, /* Serialize section */ NULL, /* Deserialize section */ NULL, /* Can sections merge? */ @@ -233,7 +254,7 @@ H5FS_section_class_t H5HF_FSPACE_SECT_CLS_NORMAL_ROW[1] = {{ NULL, /* Shrink container w/section */ H5HF_sect_row_free, /* Free section */ H5HF_sect_row_valid, /* Check validity of section */ - NULL, /* Dump debugging for section */ + H5HF_sect_row_debug, /* Dump debugging for section */ }}; /* Class info for "indirect" free space sections */ @@ -252,6 +273,7 @@ H5FS_section_class_t H5HF_FSPACE_SECT_CLS_INDIRECT[1] = {{ H5HF_sect_indirect_term_cls, /* Terminate section class */ /* Object methods */ + NULL, /* Add section */ NULL, /* Serialize section */ NULL, /* Deserialize section */ NULL, /* Can sections merge? */ @@ -260,7 +282,7 @@ H5FS_section_class_t H5HF_FSPACE_SECT_CLS_INDIRECT[1] = {{ NULL, /* Shrink container w/section */ NULL, /* Free section */ NULL, /* Check validity of section */ - H5HF_sect_indirect_debug, /* Dump debugging for section */ + NULL, /* Dump debugging for section */ }}; /* Declare a free list to manage the H5HF_free_section_t struct */ @@ -279,6 +301,72 @@ H5FL_DEFINE(H5HF_free_section_t); /*------------------------------------------------------------------------- + * Function: H5HF_sect_init_cls + * + * Purpose: Initialize the common class structure + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * Tuesday, July 25, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_init_cls(H5FS_section_class_t *cls, H5HF_hdr_t *hdr) +{ + H5HF_sect_private_t *cls_prvt; /* Pointer to class private info */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_init_cls) + + /* Check arguments. */ + HDassert(cls); + HDassert(!cls->cls_private); + + /* Allocate & initialize the class-private (i.e. private shared) information + * for this type of section + */ + if(NULL == (cls_prvt = H5MM_malloc(sizeof(H5HF_sect_private_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + cls_prvt->hdr = hdr; + cls->cls_private = cls_prvt; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HF_sect_init_cls() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_term_cls + * + * Purpose: Terminate the common class structure + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * Tuesday, July 25, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_term_cls(H5FS_section_class_t *cls) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_term_cls) + + /* Check arguments. */ + HDassert(cls); + + /* Free the class private information */ + cls->cls_private = H5MM_xfree(cls->cls_private); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5HF_sect_term_cls() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_sect_node_new * * Purpose: Allocate a free space section node of a particular type @@ -365,7 +453,7 @@ done: * * Purpose: Create a new 'single' section and return it to the caller * - * Return: Non-negative on success/Negative on failure + * Return: Pointer to new section on success/NULL on failure * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu @@ -549,12 +637,146 @@ done: /*------------------------------------------------------------------------- + * Function: H5HF_sect_single_full_dblock + * + * Purpose: Checks if a single section covers the entire direct block + * that it resides in, and converts it to a row section if so + * + * Note: Does not convert a single section to a row section if the + * single section is for a root direct block + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * Thursday, July 27, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_single_full_dblock(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_free_section_t *sect) +{ + size_t dblock_size; /* Section's direct block's size */ + size_t dblock_overhead; /* Direct block's overhead */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_full_dblock) + + /* Check arguments. */ + HDassert(sect); + HDassert(sect->sect_info.state == H5FS_SECT_LIVE); + HDassert(hdr); + +#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 */ + + /* Check for section occupying entire direct block */ + /* (and not the root direct block) */ + dblock_size = sect->u.single.dblock_size; + dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr); +#ifdef QAK +HDfprintf(stderr, "%s: dblock_size = %u\n", FUNC, dblock_size); +HDfprintf(stderr, "%s: dblock_overhead = %Zu\n", FUNC, dblock_overhead); +HDfprintf(stderr, "%s: hdr->man_dtable.curr_root_rows = %u\n", FUNC, hdr->man_dtable.curr_root_rows); +#endif /* QAK */ + if((dblock_size - dblock_overhead) == sect->sect_info.size && + hdr->man_dtable.curr_root_rows > 0) { + H5HF_direct_t *dblock; /* Pointer to direct block for section */ + haddr_t dblock_addr; /* Section's direct block's address */ + + /* Protect the direct block for the section */ + dblock_addr = sect->u.single.dblock_addr; +#ifdef QAK +HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr); +#endif /* QAK */ + if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, sect->u.single.parent, sect->u.single.par_entry, H5AC_READ))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block") + HDassert(H5F_addr_eq(dblock->block_off + dblock_overhead, sect->sect_info.addr)); + + /* Convert 'single' section into 'row' section */ + if(H5HF_sect_row_from_single(hdr, sect, dblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTCONVERT, FAIL, "can't convert single section into row section") + +#ifdef QAK +HDfprintf(stderr, "%s: sect->sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect->sect_info.addr, sect->sect_info.size, sect->sect_info.type, (sect->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED")); +HDfprintf(stderr, "%s: sect->u.row = {%p, %u, %u, %u, %t}\n", FUNC, sect->u.row.under, sect->u.row.row, sect->u.row.col, sect->u.row.num_entries, sect->u.row.checked_out); +#endif /* QAK */ + + /* Destroy direct block */ + if(H5HF_man_dblock_destroy(hdr, dxpl_id, dblock, dblock_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release direct block") + dblock = NULL; + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HF_sect_single_full_dblock() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_single_add + * + * Purpose: Perform any actions on section as it is added to free space + * manager + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * Thursday, July 27, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_single_add(H5FS_section_info_t *_sect, unsigned *flags, void *_udata) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_add) + + /* Don't need to check section if we are deserializing, because it should + * have already been checked when it was first added + */ + if(!(*flags & H5FS_ADD_DESERIALIZING)) { + H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Fractal heap free section */ + H5HF_add_ud1_t *udata = (H5HF_add_ud1_t *)_udata; /* User callback data */ + H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */ + hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */ + + /* Sanity check */ + HDassert(sect); + HDassert(hdr); + +#ifdef QAK +HDfprintf(stderr, "%s: sect->sect_info = {%a, %Hu, %u, %s}\n", "H5HF_sect_single_add", 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 if single section covers entire direct block it's in */ + /* (converts to row section possibly) */ + if(H5HF_sect_single_full_dblock(hdr, dxpl_id, sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTCONVERT, FAIL, "can't check/convert single section") + + /* Set the "returned space" flag if the single section was changed + * into a row section, so the "merging & shrinking" algorithm + * gets executed in the free space manager + */ + if(sect->sect_info.type != H5HF_FSPACE_SECT_SINGLE) + *flags |= H5FS_ADD_RETURNED_SPACE; + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HF_sect_single_add() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_sect_single_deserialize * * Purpose: Deserialize a buffer into a "live" single section * * Return: Success: non-negative - * * Failure: negative * * Programmer: Quincey Koziol @@ -663,8 +885,6 @@ H5HF_sect_single_merge(H5FS_section_info_t *_sect1, H5FS_section_info_t *_sect2, H5HF_free_section_t *sect2 = (H5HF_free_section_t *)_sect2; /* Fractal heap free section */ H5HF_add_ud1_t *udata = (H5HF_add_ud1_t *)_udata; /* User callback data */ H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */ - size_t dblock_size; /* Section's direct block's size */ - size_t dblock_overhead; /* Direct block's overhead */ hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */ herr_t ret_value = SUCCEED; /* Return value */ @@ -694,43 +914,10 @@ HDfprintf(stderr, "%s: sect2->sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect2->sec if(H5HF_sect_single_revive(hdr, dxpl_id, sect1) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section") - /* Check for section occupying entire direct block */ - /* (and not the root direct block) */ - dblock_size = sect1->u.single.dblock_size; - dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr); -#ifdef QAK -HDfprintf(stderr, "%s: dblock_size = %u\n", FUNC, dblock_size); -HDfprintf(stderr, "%s: dblock_overhead = %Zu\n", FUNC, dblock_overhead); -HDfprintf(stderr, "%s: hdr->man_iter_off = %Hu\n", FUNC, hdr->man_iter_off); -#endif /* QAK */ - if((dblock_size - dblock_overhead) == sect1->sect_info.size && - hdr->man_dtable.curr_root_rows > 0) { - H5HF_direct_t *dblock; /* Pointer to direct block for section */ - haddr_t dblock_addr; /* Section's direct block's address */ - - /* Protect the direct block for the section */ - dblock_addr = sect1->u.single.dblock_addr; -#ifdef QAK -HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr); -#endif /* QAK */ - if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, sect1->u.single.parent, sect1->u.single.par_entry, H5AC_READ))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block") - HDassert(H5F_addr_eq(dblock->block_off + dblock_overhead, sect1->sect_info.addr)); - - /* Convert 'single' section into 'row' section */ - if(H5HF_sect_row_from_single(hdr, sect1, dblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTCONVERT, FAIL, "can't convert single section into row section") - -#ifdef QAK -HDfprintf(stderr, "%s: sect1->sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect1->sect_info.addr, sect1->sect_info.size, sect1->sect_info.type, (sect1->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED")); -HDfprintf(stderr, "%s: sect1->u.row = {%p, %u, %u, %u, %t}\n", FUNC, sect1->u.row.under, sect1->u.row.row, sect1->u.row.col, sect1->u.row.num_entries, sect1->u.row.checked_out); -#endif /* QAK */ - - /* Destroy direct block */ - if(H5HF_man_dblock_destroy(hdr, dxpl_id, dblock, dblock_addr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release direct block") - dblock = NULL; - } /* end if */ + /* Check if single section covers entire direct block it's in */ + /* (converts to row section possibly) */ + if(H5HF_sect_single_full_dblock(hdr, dxpl_id, sect1) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTCONVERT, FAIL, "can't check/convert single section") done: FUNC_LEAVE_NOAPI(ret_value) @@ -770,6 +957,7 @@ H5HF_sect_single_can_shrink(const H5FS_section_info_t *_sect, void *_udata) #ifdef QAK 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")); +HDfprintf(stderr, "%s: hdr->man_dtable.curr_root_rows = %u\n", "H5HF_sect_single_can_shrink", hdr->man_dtable.curr_root_rows); #endif /* QAK */ /* Check for section occupying entire root direct block */ @@ -946,6 +1134,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 */ + size_t dblock_overhead; /* Direct block's overhead */ unsigned dblock_status = 0; /* Direct block's status in the metadata cache */ herr_t status; /* Generic status value */ @@ -958,6 +1147,13 @@ 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)); + /* Check if the section is actually within the heap */ + HDassert(sect->sect_info.addr < iblock->hdr->man_iter_off); + + /* Check that the direct block has been merged correctly */ + dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(iblock->hdr); + HDassert((sect->sect_info.size + dblock_overhead) < sect->u.single.dblock_size); + /* 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); @@ -1313,17 +1509,24 @@ H5HF_sect_row_get_iblock(H5HF_free_section_t *sect) static herr_t H5HF_sect_row_init_cls(H5FS_section_class_t *cls, void *_udata) { + H5HF_hdr_t *hdr = (H5HF_hdr_t *)_udata; /* Fractal heap header */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_row_init_cls) /* Check arguments. */ HDassert(cls); - HDassert(!cls->cls_private); + HDassert(hdr); - /* Forward call to indirect class initialization */ - if(H5HF_sect_indirect_init_cls(cls, _udata) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize row section class") + /* Call common class initialization */ + if(H5HF_sect_init_cls(cls, hdr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize common section class") + + /* First row sections actually are proxies for indirection sections on disk */ + if(cls->type == H5HF_FSPACE_SECT_FIRST_ROW) + cls->serial_size = H5HF_SECT_INDIRECT_SERIAL_SIZE(hdr); + else + cls->serial_size = 0; done: FUNC_LEAVE_NOAPI(ret_value) @@ -1357,9 +1560,9 @@ H5HF_sect_row_term_cls(H5FS_section_class_t *cls) /* Check arguments. */ HDassert(cls); - /* Forward call to indirect class termination */ - if(H5HF_sect_indirect_term_cls(cls) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't terminate row section class") + /* Call common class termination */ + if(H5HF_sect_term_cls(cls) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't terminate common section class") done: FUNC_LEAVE_NOAPI(ret_value) @@ -1398,7 +1601,7 @@ H5HF_sect_row_serialize(const H5FS_section_class_t *cls, HDassert(sect->sect_info.addr == sect->u.row.under->sect_info.addr); /* Forward to indirect routine to serialize underlying section */ - hdr = ((H5HF_sect_indirect_private_t *)(cls->cls_private))->hdr; + hdr = ((H5HF_sect_private_t *)(cls->cls_private))->hdr; if(H5HF_sect_indirect_serialize(hdr, sect->u.row.under, buf) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTSERIALIZE, FAIL, "can't serialize row section's underlying indirect section") @@ -1441,7 +1644,7 @@ H5HF_sect_row_deserialize(const H5FS_section_class_t *cls, hid_t dxpl_id, HDassert(sect_size); /* Forward to indirect routine to deserialize underlying section */ - hdr = ((H5HF_sect_indirect_private_t *)(cls->cls_private))->hdr; + hdr = ((H5HF_sect_private_t *)(cls->cls_private))->hdr; if(NULL == (ret_value = H5HF_sect_indirect_deserialize(hdr, dxpl_id, buf, sect_addr, sect_size, des_flags))) HGOTO_ERROR(H5E_HEAP, H5E_CANTDECODE, NULL, "can't deserialize row section's underlying indirect section") @@ -1566,23 +1769,39 @@ HDfprintf(stderr, "%s: sect1->sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect1->sec 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 if second 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(sect2->sect_info.addr >= hdr->man_iter_off) { + H5HF_free_section_t *top_indir_sect; /* Top indirect section for row */ - /* 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") + /* Get the top indirect section underlying second row section */ + top_indir_sect = H5HF_sect_indirect_top(sect2->u.row.under); + + /* Shrink away underlying indirect section */ + 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") + } /* end if */ + else { + /* 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: 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") + /* 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 else */ done: FUNC_LEAVE_NOAPI(ret_value) @@ -1677,7 +1896,7 @@ HDfprintf(stderr, "%s: (*sect)->u.row = {%p, %u, %u, %u}\n", FUNC, (*sect)->u.ro /* 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 */ + /* Shrink away underlying indirect section */ 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") @@ -1775,15 +1994,22 @@ done: static herr_t H5HF_sect_row_valid(const H5FS_section_class_t *cls, const H5FS_section_info_t *_sect) { + H5HF_sect_private_t *cls_prvt; /* Pointer to class private info */ + const H5HF_hdr_t *hdr; /* Fractal heap header */ const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Pointer to section to check */ const H5HF_free_section_t *indir_sect; /* Pointer to underlying indirect section */ unsigned indir_idx; /* Index of row in underlying indirect section's row array */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_row_valid) + /* Basic sanity check */ HDassert(cls); HDassert(sect); + /* Retrieve class private information */ + cls_prvt = cls->cls_private; + hdr = cls_prvt->hdr; + #ifdef QAK HDfprintf(stderr, "%s: sect->sect_info = {%a, %Hu, %u, %s}\n", "H5HF_sect_row_valid", sect->sect_info.addr, sect->sect_info.size, sect->sect_info.type, (sect->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED")); HDfprintf(stderr, "%s: sect->u.row = {%p, %u, %u, %u, %t}\n", "H5HF_sect_row_valid", sect->u.row.under, sect->u.row.row, sect->u.row.col, sect->u.row.num_entries, sect->u.row.checked_out); @@ -1799,13 +2025,21 @@ HDfprintf(stderr, "%s: indir_idx = %u\n", "H5HF_sect_row_valid", indir_idx); #endif /* QAK */ HDassert(indir_sect->u.indirect.dir_rows[indir_idx] == sect); + /* Check if the section is actually within the heap */ + HDassert(sect->sect_info.addr < hdr->man_iter_off); + /* Different checking for different kinds of rows */ if(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW) { + H5HF_free_section_t *top_indir_sect; /* Top indirect section for row */ + /* Some extra sanity checks on the row */ HDassert(sect->u.row.row == indir_sect->u.indirect.row); + /* Get the top indirect section underlying row */ + top_indir_sect = H5HF_sect_indirect_top(sect->u.row.under); + /* Check that the row's underlying indirect section is valid */ - H5HF_sect_indirect_valid(cls, sect); + H5HF_sect_indirect_valid(hdr, top_indir_sect); } /* end if */ FUNC_LEAVE_NOAPI(SUCCEED) @@ -1813,91 +2047,51 @@ HDfprintf(stderr, "%s: indir_idx = %u\n", "H5HF_sect_row_valid", indir_idx); /*------------------------------------------------------------------------- - * Function: H5HF_sect_indirect_span_size + * Function: H5HF_sect_row_debug * - * Purpose: Compute the span size covered by an indirect section + * Purpose: Dump debugging information about an row free space section * - * Return: Non-negative on success/Negative on failure + * Return: Success: non-negative + * Failure: negative * * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * July 3 2006 + * Tuesday, July 25, 2006 * *------------------------------------------------------------------------- */ static herr_t -H5HF_sect_indirect_span_size(H5HF_hdr_t *hdr, H5HF_free_section_t *sect) +H5HF_sect_row_debug(const H5FS_section_info_t *_sect, + FILE *stream, int indent, int fwidth) { - unsigned start_row; /* Row for first block covered */ - unsigned start_col; /* Column for first block covered */ - unsigned start_entry; /* Entry for first block covered */ - unsigned end_row; /* Row for last block covered */ - unsigned end_col; /* Column for last block covered */ - unsigned end_entry; /* Entry for last block covered */ - hsize_t acc_span_size; /* Accumulated span size */ + const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Section to dump info */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_span_size) + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_row_debug) - /* - * Check arguments. - */ - HDassert(hdr); + /* Check arguments. */ HDassert(sect); - HDassert(sect->u.indirect.num_entries > 0); - /* Compute starting entry, column & row */ - start_row = sect->u.indirect.row; - start_col = sect->u.indirect.col; - start_entry = (start_row * hdr->man_dtable.cparam.width) + start_col; - - /* Compute ending entry, column & row */ - end_entry = (start_entry + sect->u.indirect.num_entries) - 1; - end_row = end_entry / hdr->man_dtable.cparam.width; - end_col = end_entry % hdr->man_dtable.cparam.width; -#ifdef QAK -HDfprintf(stderr, "%s: start_row = %u, start_col = %u, start_entry = %u\n", "H5HF_sect_indirect_span_size", start_row, start_col, start_entry); -HDfprintf(stderr, "%s: end_row = %u, end_col = %u, end_entry = %u\n", "H5HF_sect_indirect_span_size", end_row, end_col, end_entry); -#endif /* QAK */ - - /* Initialize accumulated span size */ - acc_span_size = 0; - - /* Compute span size covered */ - - /* Check for multi-row span */ - if(start_row != end_row) { - /* Accomodate partial starting row */ - if(start_col > 0) { - acc_span_size = hdr->man_dtable.row_block_size[start_row] * - (hdr->man_dtable.cparam.width - start_col); - start_row++; - } /* end if */ + /* Print indirect section information */ + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "Row:", + sect->u.row.row); + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "Column:", + sect->u.row.col); + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "Number of entries:", + sect->u.row.num_entries); - /* Accumulate full rows */ - while(start_row < end_row) { - acc_span_size += hdr->man_dtable.row_block_size[start_row] * - hdr->man_dtable.cparam.width; - start_row++; - } /* end while */ + /* If this is a first row section display information about underlying indirect section */ + if(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW) { + /* Print indirect section header */ + HDfprintf(stream, "%*s%-*s\n", indent, "", fwidth, + "Underlying indirect section:"); - /* Accomodate partial ending row */ - acc_span_size += hdr->man_dtable.row_block_size[start_row] * - (end_col + 1); + H5HF_sect_indirect_debug(sect->u.row.under, stream, indent + 3, MAX(0, fwidth - 3)); } /* end if */ - else { - /* Span is in same row */ - acc_span_size = hdr->man_dtable.row_block_size[start_row] * - ((end_col - start_col) + 1); - } /* end else */ - - /* Set the span size for the indirect section */ -#ifdef QAK -HDfprintf(stderr, "%s: acc_span_size = %Hu\n", "H5HF_sect_indirect_span_size", acc_span_size); -#endif /* QAK */ - sect->u.indirect.span_size = acc_span_size; FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5HF_sect_indirect_span_size() */ +} /* H5HF_sect_row_debug() */ /*------------------------------------------------------------------------- @@ -1992,28 +2186,20 @@ static herr_t H5HF_sect_indirect_init_cls(H5FS_section_class_t *cls, void *_udata) { H5HF_hdr_t *hdr = (H5HF_hdr_t *)_udata; /* Fractal heap header */ - H5HF_sect_indirect_private_t *cls_prvt; /* Pointer to class private info */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_init_cls) /* Check arguments. */ HDassert(cls); - HDassert(!cls->cls_private); + HDassert(hdr); - /* Allocate & initialize the class-private (i.e. private shared) information - * for this type of section - */ - if(NULL == (cls_prvt = H5MM_malloc(sizeof(H5HF_sect_indirect_private_t)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - cls_prvt->hdr = hdr; - cls->cls_private = cls_prvt; + /* Call to common class initialization */ + if(H5HF_sect_init_cls(cls, hdr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize common section class") /* Set the size of all serialized objects of this class of sections */ - cls->serial_size = hdr->heap_off_size /* Indirect block's offset in "heap space" */ - + 2 /* Row */ - + 2 /* Column */ - + 2; /* # of entries */ + cls->serial_size = H5HF_SECT_INDIRECT_SERIAL_SIZE(hdr); done: FUNC_LEAVE_NOAPI(ret_value) @@ -2037,15 +2223,19 @@ done: static herr_t H5HF_sect_indirect_term_cls(H5FS_section_class_t *cls) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_term_cls) + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_term_cls) /* Check arguments. */ HDassert(cls); - /* Free the class private information */ - cls->cls_private = H5MM_xfree(cls->cls_private); + /* Call common class termination */ + if(H5HF_sect_term_cls(cls) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't terminate common section class") - FUNC_LEAVE_NOAPI(SUCCEED) +done: + FUNC_LEAVE_NOAPI(ret_value) } /* H5HF_sect_indirect_term_cls() */ @@ -2103,8 +2293,9 @@ H5HF_sect_indirect_new(H5HF_hdr_t *hdr, haddr_t sect_off, hsize_t sect_size, sect->u.indirect.num_entries = nentries; /* 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") + sect->u.indirect.span_size = H5HF_dtable_span_size(&hdr->man_dtable, + row, col, nentries); + HDassert(sect->u.indirect.span_size > 0); /* This indirect section doesn't (currently) have a parent */ sect->u.indirect.parent = NULL; @@ -2213,8 +2404,8 @@ HDfprintf(stderr, "%s: Leaving\n", FUNC); */ static herr_t H5HF_sect_indirect_init_rows(H5HF_hdr_t *hdr, hid_t dxpl_id, - H5HF_free_section_t *sect, hbool_t first_child, unsigned space_flags, - unsigned start_row, unsigned start_col, + H5HF_free_section_t *sect, hbool_t first_child, H5HF_free_section_t **first_row_sect, + unsigned space_flags, unsigned start_row, unsigned start_col, unsigned end_row, unsigned end_col) { hsize_t curr_off; /* Offset of new section in "heap space" */ @@ -2224,6 +2415,7 @@ H5HF_sect_indirect_init_rows(H5HF_hdr_t *hdr, hid_t dxpl_id, unsigned curr_entry; /* Current entry within indirect section */ unsigned curr_indir_entry; /* Current indirect entry within indirect section */ unsigned curr_row; /* Current row within indirect section */ + unsigned dir_nrows; /* # of direct rows in indirect section */ unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ @@ -2252,14 +2444,21 @@ HDfprintf(stderr, "%s: end_row = %u, end_col = %u\n", FUNC, end_row, end_col); max_direct_row = MIN(end_row, (hdr->man_dtable.max_direct_rows - 1)); /* Compute # of direct rows covered */ - sect->u.indirect.dir_nrows = (max_direct_row - start_row) + 1; + dir_nrows = (max_direct_row - start_row) + 1; + + /* Don't set the of direct rows in section yet, so sanity + * checking works (enabled in free section manager, with H5FS_DEBUG + * macro) correctly. + */ + sect->u.indirect.dir_nrows = 0; /* Allocate space for the derived row sections */ - if(NULL == (sect->u.indirect.dir_rows = H5MM_malloc(sizeof(H5HF_free_section_t *) * sect->u.indirect.dir_nrows))) + if(NULL == (sect->u.indirect.dir_rows = H5MM_malloc(sizeof(H5HF_free_section_t *) * dir_nrows))) HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for row section pointer array") } /* end if */ else { /* No rows of direct blocks covered, reset direct row information */ + dir_nrows = 0; sect->u.indirect.dir_nrows = 0; sect->u.indirect.dir_rows = NULL; } /* end else */ @@ -2329,11 +2528,16 @@ HDfprintf(stderr, "%s: Creating direct row, row_col = %u, row_entries = %u\n", F /* Add new row section to array for indirect section */ sect->u.indirect.dir_rows[curr_row] = row_sect; - /* Add new row section to free space manager for the heap */ - if(H5HF_space_add(hdr, dxpl_id, row_sect, space_flags) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add row section to free space") + /* Check to see if we should grab the first row section instead of adding it immediately */ + if(first_row_sect) + *first_row_sect = row_sect; + else { + /* Add new row section to free space manager for the heap */ + if(H5HF_space_add(hdr, dxpl_id, row_sect, space_flags) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add row section to free space") + } /* end else */ - /* Add new row section to array for indirect section */ + /* Increment reference count for underlying indirect section */ sect->u.indirect.rc++; /* Advance the offset to the next section */ @@ -2342,8 +2546,9 @@ HDfprintf(stderr, "%s: Creating direct row, row_col = %u, row_entries = %u\n", F /* Advance the current entry to the next row*/ curr_entry += row_entries; - /* Reset the 'first child' flag */ + /* Reset the 'first child' parameters */ first_child = FALSE; + first_row_sect = NULL; } /* end if */ else { H5HF_indirect_t *child_iblock; /* Child indirect block */ @@ -2392,8 +2597,8 @@ HDfprintf(stderr, "%s: child_iblock_addr = %a\n", FUNC, child_iblock_addr); /* Initialize rows for new indirect section */ if(H5HF_sect_indirect_init_rows(hdr, dxpl_id, child_sect, - first_child, space_flags, 0, 0, (child_nrows - 1), - (hdr->man_dtable.cparam.width - 1)) < 0) + first_child, first_row_sect, space_flags, 0, 0, + (child_nrows - 1), (hdr->man_dtable.cparam.width - 1)) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize indirect section") /* If we have a valid child indirect block, release it now */ @@ -2414,8 +2619,9 @@ HDfprintf(stderr, "%s: child_iblock_addr = %a\n", FUNC, child_iblock_addr); curr_entry++; curr_indir_entry++; - /* Reset the 'first child' flag */ + /* Reset the 'first child' parameters */ first_child = FALSE; + first_row_sect = NULL; } /* end for */ } /* end else */ @@ -2428,6 +2634,10 @@ HDfprintf(stderr, "%s: child_iblock_addr = %a\n", FUNC, child_iblock_addr); /* Reset column for all other rows */ row_col = 0; } /* end for */ + + /* Set the final # of direct rows in section */ + sect->u.indirect.dir_nrows = dir_nrows; + /* Make certain we've tracked the section's dependents correctly */ HDassert(sect->u.indirect.rc == (sect->u.indirect.indir_nents + sect->u.indirect.dir_nrows)); @@ -2453,10 +2663,10 @@ done: */ herr_t H5HF_sect_indirect_add(H5HF_hdr_t *hdr, hid_t dxpl_id, - H5HF_indirect_t *iblock, unsigned start_entry, unsigned nentries, - hsize_t *end_off /*out*/) + H5HF_indirect_t *iblock, unsigned start_entry, unsigned nentries) { - H5HF_free_section_t *sect = NULL; /* 'Indirect3' free space section to add */ + H5HF_free_section_t *sect = NULL; /* 'Indirect' free space section to add */ + H5HF_free_section_t *first_row_sect = NULL; /* First row section in new indirect section */ hsize_t sect_off; /* Offset of section in heap space */ unsigned start_row; /* Start row in indirect block */ unsigned start_col; /* Start column in indirect block */ @@ -2502,18 +2712,16 @@ HDfprintf(stderr, "%s: sect_off = %Hu\n", FUNC, sect_off); HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section") /* Initialize rows for new indirect section */ - if(H5HF_sect_indirect_init_rows(hdr, dxpl_id, sect, TRUE, 0, start_row, - start_col, end_row, end_col) < 0) + if(H5HF_sect_indirect_init_rows(hdr, dxpl_id, sect, TRUE, &first_row_sect, + H5FS_ADD_SKIP_VALID, start_row, start_col, end_row, end_col) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize indirect section") + HDassert(first_row_sect); - /* Get end of section offset to return, if requested */ - if(end_off) { - /* Compute the end of the section */ - *end_off = sect_off + sect->u.indirect.span_size; -#ifdef QAK -HDfprintf(stderr, "%s: *end_off = %Hu\n", FUNC, *end_off); -#endif /* QAK */ - } /* end if */ + /* Now that underlying indirect section is consistent, add first row + * section to free space manager for the heap + */ + if(H5HF_space_add(hdr, dxpl_id, first_row_sect, H5FS_ADD_RETURNED_SPACE) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add row section to free space") done: if(ret_value < 0 && sect) @@ -2558,14 +2766,19 @@ HDfprintf(stderr, "%s: sect->u.indirect.rc = %u\n", FUNC, sect->u.indirect.rc); /* If the indirect section's ref. count drops to zero, free the section */ if(sect->u.indirect.rc == 0) { - /* Decrement ref. count on indirect section's parent */ - if(sect->u.indirect.parent) - if(H5HF_sect_indirect_decr(sect->u.indirect.parent) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't decrement ref. count on parent indirect section") + H5HF_free_section_t *par_sect; /* Parent indirect section */ + + /* Preserve pointer to parent indirect section when freeing this section */ + par_sect = sect->u.indirect.parent; /* Free indirect section */ if(H5HF_sect_indirect_free(sect) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node") + + /* Decrement ref. count on indirect section's parent */ + if(par_sect) + if(H5HF_sect_indirect_decr(par_sect) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't decrement ref. count on parent indirect section") } /* end if */ done: @@ -2724,7 +2937,7 @@ static herr_t H5HF_sect_indirect_reduce_row(H5HF_hdr_t *hdr, H5HF_free_section_t *row_sect, hbool_t *alloc_from_start) { - H5HF_free_section_t *sect; /* Indirect3 section underlying row section */ + H5HF_free_section_t *sect; /* Indirect section underlying row section */ unsigned row_start_entry; /* Entry for first block covered in row section */ unsigned row_end_entry; /* Entry for last block covered in row section */ unsigned row_entry; /* Entry to allocate in row section */ @@ -2765,6 +2978,7 @@ HDfprintf(stderr, "%s: row_start_entry = %u, row_end_entry = %u\n", FUNC, row_st /* Additional sanity check */ HDassert(sect->u.indirect.span_size > 0); HDassert(sect->u.indirect.iblock_entries > 0); + HDassert(sect->u.indirect.dir_nrows > 0); HDassert(sect->u.indirect.dir_rows); HDassert(sect->u.indirect.dir_rows[(row_sect->u.row.row - start_row)] == row_sect); #ifdef QAK @@ -2829,6 +3043,10 @@ HDfprintf(stderr, "%s: Entry is at start of indirect section\n", FUNC); if(sect->u.indirect.col == hdr->man_dtable.cparam.width) { HDassert(row_sect->u.row.num_entries == 1); + /* Adjust section's span information */ + sect->u.indirect.row++; + sect->u.indirect.col = 0; + /* Adjust direct row information */ sect->u.indirect.dir_nrows--; #ifdef QAK @@ -2837,6 +3055,7 @@ HDfprintf(stderr, "%s: sect->u.indirect.dir_nrows = %u\n", FUNC, sect->u.indirec /* Adjust direct row sections for indirect section */ if(sect->u.indirect.dir_nrows > 0) { + HDassert(sect->u.indirect.dir_rows); HDmemmove(§->u.indirect.dir_rows[0], §->u.indirect.dir_rows[1], sect->u.indirect.dir_nrows * sizeof(H5HF_free_section_t *)); @@ -2849,6 +3068,7 @@ HDfprintf(stderr, "%s: sect->u.indirect.dir_nrows = %u\n", FUNC, sect->u.indirec } /* end if */ else { /* Sanity check */ + HDassert(sect->u.indirect.indir_nents > 0); HDassert(sect->u.indirect.indir_ents); /* Eliminate direct rows for this section */ @@ -2859,9 +3079,6 @@ HDfprintf(stderr, "%s: sect->u.indirect.dir_nrows = %u\n", FUNC, sect->u.indirec if(H5HF_sect_indirect_first(hdr, sect->u.indirect.indir_ents[0]) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for child indirect section") } /* end else */ - - sect->u.indirect.row++; - sect->u.indirect.col = 0; } /* end if */ /* Adjust number of entries covered */ @@ -2874,6 +3091,7 @@ HDfprintf(stderr, "%s: sect->u.indirect.dir_nrows = %u\n", FUNC, sect->u.indirec HDfprintf(stderr, "%s: Entry is at end of indirect section\n", FUNC); #endif /* QAK */ /* Sanity check */ + HDassert(sect->u.indirect.indir_nents == 0); HDassert(sect->u.indirect.indir_ents == NULL); /* Adjust number of entries covered */ @@ -2985,8 +3203,13 @@ HDfprintf(stderr, "%s: iblock = %p, iblock_off = %Hu\n", FUNC, iblock, iblock_of } /* end else */ } /* end if */ else { + /* Decrement count of entries & rows */ sect->u.indirect.num_entries--; sect->u.indirect.dir_nrows--; + HDassert(sect->u.indirect.dir_nrows == 0); + + /* Eliminate direct rows for this section */ + sect->u.indirect.dir_rows = H5MM_xfree(sect->u.indirect.dir_rows); } /* end else */ done: @@ -3075,7 +3298,9 @@ HDfprintf(stderr, "%s: end_entry = %u, end_row = %u, end_col = %u\n", FUNC, end_ HDfprintf(stderr, "%s: Child is at start of indirect section\n", FUNC); #endif /* QAK */ /* Sanity check */ + HDassert(sect->u.indirect.dir_nrows == 0); HDassert(sect->u.indirect.dir_rows == NULL); + HDassert(sect->u.indirect.indir_nents > 0); HDassert(sect->u.indirect.indir_ents); /* Adjust section start */ @@ -3106,6 +3331,7 @@ HDfprintf(stderr, "%s: Child is at start of indirect section\n", FUNC); HDfprintf(stderr, "%s: Child is at end of indirect section\n", FUNC); #endif /* QAK */ /* Sanity check */ + HDassert(sect->u.indirect.indir_nents > 0); HDassert(sect->u.indirect.indir_ents); /* Adjust span of blocks covered */ @@ -3133,6 +3359,7 @@ HDfprintf(stderr, "%s: Child is at end of indirect section\n", FUNC); HDfprintf(stderr, "%s: Child is in middle of indirect section\n", FUNC); #endif /* QAK */ /* Sanity check */ + HDassert(sect->u.indirect.indir_nents > 0); HDassert(sect->u.indirect.indir_ents); /* Compute basic information about peer & current indirect sections */ @@ -3163,11 +3390,12 @@ HDfprintf(stderr, "%s: iblock = %p, iblock_off = %Hu\n", FUNC, iblock, iblock_of /* Update the number of entries in current section & calculate it's span size */ /* (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") + sect->u.indirect.span_size = H5HF_dtable_span_size(&hdr->man_dtable, + sect->u.indirect.row, sect->u.indirect.col, new_nentries); #ifdef QAK HDfprintf(stderr, "%s: sect->u.indirect.span_size = %Hu\n", FUNC, sect->u.indirect.span_size); #endif /* QAK */ + HDassert(sect->u.indirect.span_size > 0); /* Compute address of peer indirect section */ peer_sect_addr = sect->sect_info.addr; @@ -3195,6 +3423,10 @@ HDfprintf(stderr, "%s: peer_sect_addr = %a\n", FUNC, peer_sect_addr); §->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 */ + + /* Eliminate indirect entries for this section, if appropriate */ + if(sect->u.indirect.indir_nents == 0) + sect->u.indirect.indir_ents = H5MM_xfree(sect->u.indirect.indir_ents); #ifdef QAK HDfprintf(stderr, "%s: sect->u.indirect.indir_nents = %u\n", FUNC, sect->u.indirect.indir_nents); #endif /* QAK */ @@ -3229,8 +3461,13 @@ HDfprintf(stderr, "%s: peer_sect->u.indirect.rc = %u\n", FUNC, peer_sect->u.indi } /* end else */ } /* end if */ else { + /* Decrement count of entries & indirect entries */ sect->u.indirect.num_entries--; sect->u.indirect.indir_nents--; + HDassert(sect->u.indirect.indir_nents == 0); + + /* Eliminate indirect entries for this section */ + sect->u.indirect.indir_ents = H5MM_xfree(sect->u.indirect.indir_ents); } /* end else */ /* Decrement # of sections which depend on this row */ @@ -3307,6 +3544,7 @@ H5HF_sect_indirect_first(H5HF_hdr_t *hdr, H5HF_free_section_t *sect) /* Sanity checks */ HDassert(sect->u.indirect.row == 0); HDassert(sect->u.indirect.col == 0); + HDassert(sect->u.indirect.dir_rows); HDassert(sect->u.indirect.dir_rows[0]); /* Change first row section in indirect section to be the "first row" */ @@ -3316,6 +3554,7 @@ H5HF_sect_indirect_first(H5HF_hdr_t *hdr, H5HF_free_section_t *sect) else { /* Sanity checks */ HDassert(sect->u.indirect.indir_nents > 0); + HDassert(sect->u.indirect.indir_ents); HDassert(sect->u.indirect.indir_ents[0]); /* Forward to first child indirect section */ @@ -3545,6 +3784,7 @@ HDfprintf(stderr, "%s: nrows_moved2 = %u\n", FUNC, nrows_moved2); /* Some sanity checks on second indirect section */ HDassert(sect2->u.indirect.rc > 0); + HDassert(sect2->u.indirect.indir_nents > 0); HDassert(sect2->u.indirect.indir_ents); /* Set up parameters for transfer of entries */ @@ -3622,7 +3862,7 @@ HDfprintf(stderr, "%s: Finishing sections don't share a row\n", FUNC); HDfprintf(stderr, "%s: Re-inserting second row section\n", FUNC); #endif /* QAK */ row_sect2->sect_info.type = H5HF_FSPACE_SECT_NORMAL_ROW; - if(H5HF_space_add(hdr, dxpl_id, row_sect2, 0) < 0) + if(H5HF_space_add(hdr, dxpl_id, row_sect2, H5FS_ADD_SKIP_VALID) < 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); @@ -3886,9 +4126,9 @@ H5HF_sect_indirect_deserialize(H5HF_hdr_t *hdr, hid_t dxpl_id, { H5HF_free_section_t *new_sect; /* New indirect section */ hsize_t iblock_off; /* Indirect block's offset */ - unsigned start_row; /* Indirect3 section's start row */ - unsigned start_col; /* Indirect3 section's start column */ - unsigned nentries; /* Indirect3 section's number of entries */ + unsigned start_row; /* Indirect section's start row */ + unsigned start_col; /* Indirect section's start column */ + unsigned nentries; /* Indirect section's number of entries */ unsigned start_entry; /* Start entry in indirect block */ unsigned end_entry; /* End entry in indirect block */ unsigned end_row; /* End row in indirect block */ @@ -3912,19 +4152,19 @@ HDfprintf(stderr, "%s: sect_addr = %a, sect_size = %Hu\n", FUNC, sect_addr, sect HDfprintf(stderr, "%s: iblock_off = %Hu\n", FUNC, iblock_off); #endif /* QAK */ - /* Indirect3 section's row */ + /* Indirect section's row */ UINT16DECODE(buf, start_row); #ifdef QAK HDfprintf(stderr, "%s: start_row = %u\n", FUNC, start_row); #endif /* QAK */ - /* Indirect3 section's column */ + /* Indirect section's column */ UINT16DECODE(buf, start_col); #ifdef QAK HDfprintf(stderr, "%s: start_col = %u\n", FUNC, start_col); #endif /* QAK */ - /* Indirect3 section's # of entries */ + /* Indirect section's # of entries */ UINT16DECODE(buf, nentries); #ifdef QAK HDfprintf(stderr, "%s: nentries = %u\n", FUNC, nentries); @@ -3944,8 +4184,9 @@ HDfprintf(stderr, "%s: nentries = %u\n", FUNC, nentries); end_col = end_entry % hdr->man_dtable.cparam.width; /* Initialize rows for new indirect section */ - if(H5HF_sect_indirect_init_rows(hdr, dxpl_id, new_sect, TRUE, H5FS_ADD_DESERIALIZING, - new_sect->u.indirect.row, new_sect->u.indirect.col, end_row, end_col) < 0) + if(H5HF_sect_indirect_init_rows(hdr, dxpl_id, new_sect, TRUE, NULL, + H5FS_ADD_DESERIALIZING, new_sect->u.indirect.row, new_sect->u.indirect.col, + end_row, end_col) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't initialize indirect section") /* Indicate that this section shouldn't be added to free space manager's list */ @@ -4019,12 +4260,8 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5HF_sect_indirect_valid(const H5FS_section_class_t *row_cls, const H5HF_free_section_t *row_sect) +H5HF_sect_indirect_valid(const H5HF_hdr_t *hdr, const H5HF_free_section_t *sect) { - const H5HF_free_section_t *sect; /* Pointer to underlying indirect section */ - H5HF_sect_indirect_private_t *cls_prvt; /* Pointer to class private info */ - const H5HF_hdr_t *hdr; /* Fractal heap header */ - hsize_t iblock_off; /* Indirect block's offset in "heap space" */ unsigned start_row; /* Row for first block covered */ unsigned start_col; /* Column for first block covered */ unsigned start_entry; /* Entry for first block covered */ @@ -4036,15 +4273,9 @@ H5HF_sect_indirect_valid(const H5FS_section_class_t *row_cls, const H5HF_free_se FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_valid) /* Sanity check arguments */ - HDassert(row_cls); - HDassert(row_sect); - - /* Set up indirect section */ - sect = row_sect->u.row.under; - cls_prvt = row_cls->cls_private; - hdr = cls_prvt->hdr; - HDassert(sect); HDassert(hdr); + HDassert(sect); + #ifdef QAK HDfprintf(stderr, "%s: sect->sect_info = {%a, %Hu, %u, %s}\n", "H5HF_sect_indirect_valid", sect->sect_info.addr, sect->sect_info.size, sect->sect_info.type, (sect->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED")); if(sect->sect_info.state == H5FS_SECT_LIVE) @@ -4054,16 +4285,6 @@ else HDfprintf(stderr, "%u, %u, %u}\n", sect->u.indirect.row, sect->u.indirect.col, sect->u.indirect.num_entries); #endif /* QAK */ - /* Retrieve the indirect block's offset */ - if(sect->sect_info.state == H5FS_SECT_LIVE) - iblock_off = sect->u.indirect.u.iblock->block_off; - else - iblock_off = sect->u.indirect.u.iblock_off; - -#ifdef QAK -HDfprintf(stderr, "%s: iblock_off = %Hu\n", "H5HF_sect_indirect_valid", iblock_off); -#endif /* QAK */ - /* Compute starting entry, column & row */ start_row = sect->u.indirect.row; start_col = sect->u.indirect.col; @@ -4100,14 +4321,42 @@ HDfprintf(stderr, "%s: end_row = %u, end_col = %u, end_entry = %u\n", "H5HF_sect || 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)) { + if(u > 0) { 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); + tmp_row_sect2 = sect->u.indirect.dir_rows[u - 1]; + HDassert(tmp_row_sect2->u.row.row < tmp_row_sect->u.row.row); + HDassert(H5F_addr_lt(tmp_row_sect2->sect_info.addr, tmp_row_sect->sect_info.addr)); + HDassert(tmp_row_sect2->sect_info.size <= tmp_row_sect->sect_info.size); + } /* end if */ + } /* end for */ + } /* end if */ + + /* Sanity check any indirect entries */ + if(sect->u.indirect.indir_nents > 0) { + /* Basic sanity checks */ + if(sect->sect_info.state == H5FS_SECT_LIVE) { + HDassert(sect->u.indirect.iblock_entries); + HDassert(sect->u.indirect.indir_nents <= sect->u.indirect.iblock_entries); + } /* end if */ + HDassert(sect->u.indirect.indir_ents); + + /* Sanity check each child indirect section */ + for(u = 0; u < sect->u.indirect.indir_nents; u++) { + const H5HF_free_section_t *tmp_child_sect; /* Pointer to child indirect section */ + + tmp_child_sect = sect->u.indirect.indir_ents[u]; + HDassert(tmp_child_sect->sect_info.type == H5HF_FSPACE_SECT_INDIRECT); + HDassert(tmp_child_sect->u.indirect.parent == sect); + if(u > 0) { + const H5HF_free_section_t *tmp_child_sect2; /* Pointer to child indirect section */ + + tmp_child_sect2 = sect->u.indirect.indir_ents[u - 1]; + HDassert(H5F_addr_lt(tmp_child_sect2->sect_info.addr, tmp_child_sect->sect_info.addr)); } /* end if */ + + /* Recursively check child indirect section */ + H5HF_sect_indirect_valid(hdr, tmp_child_sect); } /* end for */ } /* end if */ @@ -4130,11 +4379,9 @@ HDfprintf(stderr, "%s: end_row = %u, end_col = %u, end_entry = %u\n", "H5HF_sect *------------------------------------------------------------------------- */ static herr_t -H5HF_sect_indirect_debug(const H5FS_section_info_t *_sect, +H5HF_sect_indirect_debug(const H5HF_free_section_t *sect, FILE *stream, int indent, int fwidth) { - const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Section to dump info */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_debug) /* Check arguments. */ |