diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2006-06-19 10:06:10 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2006-06-19 10:06:10 (GMT) |
commit | 9db9e82cd1c4e35c6e64fbb2da5eb1db95a0fb55 (patch) | |
tree | df8aaa72b1094bcfacc740a8d33b255c84e1d34e /src/H5HFhdr.c | |
parent | 54e2de04d3b7a0359c80cc995f94b63123f4a4da (diff) | |
download | hdf5-9db9e82cd1c4e35c6e64fbb2da5eb1db95a0fb55.zip hdf5-9db9e82cd1c4e35c6e64fbb2da5eb1db95a0fb55.tar.gz hdf5-9db9e82cd1c4e35c6e64fbb2da5eb1db95a0fb55.tar.bz2 |
[svn-r12424] Purpose:
Code checkpoint
Description:
Add in more new features for the fractal heap code, mostly bringing in
more ability for deleting objects (which isn't completely working yet).
Also, checkpoint free space manager code, which is essentially complete
(although it needs some more work after the metadata cache has some additional
features)
Platforms tested:
FreeBSD 4.11 (sleipnir)
Linux 2.4 (chicago)
h5committest
Diffstat (limited to 'src/H5HFhdr.c')
-rw-r--r-- | src/H5HFhdr.c | 766 |
1 files changed, 744 insertions, 22 deletions
diff --git a/src/H5HFhdr.c b/src/H5HFhdr.c index 05d0a77..836d1e6 100644 --- a/src/H5HFhdr.c +++ b/src/H5HFhdr.c @@ -68,6 +68,10 @@ /* Local Prototypes */ /********************/ +/* Free space section routines */ +static herr_t H5HF_hdr_skip_ranges(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_indirect_t *iblock, unsigned start_entry, unsigned nentries); + /*********************/ /* Package Variables */ @@ -426,7 +430,7 @@ HDfprintf(stderr, "%s: Marking heap header as dirty\n", FUNC); HDassert(hdr); /* Mark header as dirty in cache */ - if(H5AC_mark_pinned_entry_dirty(hdr->f, hdr, FALSE, 0) < 0) + if(H5AC_mark_pinned_or_protected_entry_dirty(hdr->f, hdr) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, FAIL, "unable to mark fractal heap header as dirty") /* Set the dirty flags for the heap header */ @@ -482,9 +486,9 @@ done: /*------------------------------------------------------------------------- - * Function: H5HF_hdr_extend_heap + * Function: H5HF_hdr_adjust_heap * - * Purpose: Extend heap to cover more space + * Purpose: Adjust heap space * * Return: Non-negative on success/Negative on failure * @@ -495,25 +499,31 @@ done: *------------------------------------------------------------------------- */ herr_t -H5HF_hdr_extend_heap(H5HF_hdr_t *hdr, hsize_t new_size, hsize_t extra_free) +H5HF_hdr_adjust_heap(H5HF_hdr_t *hdr, hsize_t new_size, hssize_t extra_free) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_hdr_extend_heap) + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_adjust_heap) /* * Check arguments. */ HDassert(hdr); - HDassert(new_size >= hdr->total_size); /* Set the total space in heap */ hdr->total_size = new_size; hdr->man_size = new_size; - /* Increment the free space in direct blocks */ + /* Adjust the free space in direct blocks */ hdr->total_man_free += extra_free; - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5HF_hdr_extend_heap() */ + /* Mark heap header as modified */ + if(H5HF_hdr_dirty(hdr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark header as dirty") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_hdr_adjust_heap() */ /*------------------------------------------------------------------------- @@ -525,37 +535,752 @@ H5HF_hdr_extend_heap(H5HF_hdr_t *hdr, hsize_t new_size, hsize_t extra_free) * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu - * Apr 24 2006 + * May 23 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_hdr_inc_alloc(H5HF_hdr_t *hdr, size_t alloc_size) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_hdr_inc_alloc) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(alloc_size); + + /* Update the "allocated" size within the heap */ + hdr->man_alloc_size += alloc_size; +#ifdef QAK +HDfprintf(stderr, "%s: hdr->man_alloc_size = %Hu\n", "H5HF_hdr_inc_alloc", hdr->man_alloc_size); +#endif /* QAK */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_hdr_inc_alloc() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_start_iter + * + * Purpose: Start "next block" iterator at an offset/entry in the heap + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 30 2006 * *------------------------------------------------------------------------- */ herr_t -H5HF_hdr_inc_alloc(H5HF_hdr_t *hdr, hsize_t new_alloc_size, unsigned nentries) +H5HF_hdr_start_iter(H5HF_hdr_t *hdr, H5HF_indirect_t *iblock, hsize_t curr_off, unsigned curr_entry) { herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_inc_alloc) + FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_start_iter) /* * Check arguments. */ HDassert(hdr); - HDassert(new_alloc_size >= hdr->man_alloc_size); + HDassert(iblock); + + /* Set up "next block" iterator at correct location */ + if(H5HF_man_iter_start_entry(hdr, &hdr->next_block, iblock, curr_entry) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize block iterator") + + /* Set the offset of the iterator in the heap */ + hdr->man_iter_off = curr_off; - /* Advance the iterator for the current location with in the indirect block */ +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_hdr_start_iter() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_reset_iter + * + * Purpose: Reset "next block" iterator + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 31 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_hdr_reset_iter(H5HF_hdr_t *hdr, hsize_t curr_off) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_reset_iter) + + /* + * Check arguments. + */ + HDassert(hdr); + + /* Reset "next block" iterator */ + if(H5HF_man_iter_reset(&hdr->next_block) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't reset block iterator") + + /* Set the offset of the iterator in the heap */ + hdr->man_iter_off = curr_off; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_hdr_reset_iter() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_skip_blocks + * + * Purpose: Add skipped direct blocks to free space for heap + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Apr 3 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_hdr_skip_blocks(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_indirect_t *iblock, + unsigned start_entry, unsigned nentries) +{ + hsize_t sect_off; /* Offset of free section in heap */ + unsigned curr_row; /* Current row in indirect block */ + unsigned curr_col; /* Current column in indirect block */ + unsigned u; /* Local index variables */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_skip_blocks) +#ifdef QAK +HDfprintf(stderr, "%s: start_entry = %u, nentries = %u\n", FUNC, start_entry, nentries); +#endif /* QAK */ + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(iblock); + HDassert(nentries); + + /* Compute starting column & row */ + curr_row = start_entry / hdr->man_dtable.cparam.width; + curr_col = start_entry % hdr->man_dtable.cparam.width; + + /* Initialize information for rows skipped over */ + sect_off = iblock->block_off; + for(u = 0; u < curr_row; u++) + sect_off += hdr->man_dtable.row_block_size[u] * hdr->man_dtable.cparam.width; + sect_off += hdr->man_dtable.row_block_size[curr_row] * curr_col; +#ifdef QAK +HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off); +#endif /* QAK */ + + /* Loop over the blocks to skip */ + for(u = start_entry; u < (start_entry + nentries); /* u is advanced in loop */) { + unsigned row_entries; /* Number of entries in a particular row */ + + /* Compute number of entries in (possible partial) current row */ + row_entries = MIN(hdr->man_dtable.cparam.width - curr_col, (start_entry + nentries) - u); +#ifdef QAK +HDfprintf(stderr, "%s: u = %u\n", FUNC, u); +HDfprintf(stderr, "%s: curr_col = %u, curr_row = %u\n", FUNC, curr_col, curr_row); +HDfprintf(stderr, "%s: row_entries = %u, hdr->man_dtable.row_dblock_free[%u] = %Hu\n", FUNC, row_entries, curr_row, hdr->man_dtable.row_dblock_free[curr_row]); +#endif /* QAK */ + + /* Add 'range' section for blocks skipped in this row */ + if(H5HF_sect_range_add(hdr, dxpl_id, sect_off, hdr->man_dtable.row_dblock_free[curr_row], + iblock, curr_row, curr_col, row_entries) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create range section for indirect block's free space") + + /* Advance row & column position */ + sect_off += row_entries * hdr->man_dtable.row_block_size[curr_row]; + curr_row++; + curr_col = 0; /* (first partial row aligns this) */ + + /* Increment index variable */ + u += row_entries; + } /* end for */ +#ifdef QAK +HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off); +#endif /* QAK */ + + /* Advance the new block iterator */ + if(H5HF_hdr_inc_iter(hdr, (sect_off - hdr->man_iter_off), nentries) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't increase allocated heap size") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_hdr_skip_blocks() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_skip_ranges + * + * Purpose: Add skipped indirect ranges to free space for heap + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Apr 4 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_hdr_skip_ranges(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_indirect_t *iblock, + unsigned start_entry, unsigned nentries) +{ + hsize_t sect_off; /* Offset of free section in heap */ + size_t row_dblock_free_space; /* Size of free space for row of direct blocks in a row */ + size_t acc_row_dblock_free_space; /* Accumulated size of free space for row of direct blocks in a row */ + unsigned curr_row; /* Current row in indirect block */ + unsigned curr_col; /* Current column in indirect block */ + unsigned u, w; /* Local index variables */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_skip_ranges) +#ifdef QAK +HDfprintf(stderr, "%s: start_entry = %u, nentries = %u\n", FUNC, start_entry, nentries); +#endif /* QAK */ + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(iblock); + HDassert(nentries); + + /* Compute starting column & row */ + curr_row = start_entry / hdr->man_dtable.cparam.width; + curr_col = start_entry % hdr->man_dtable.cparam.width; +#ifdef QAK +HDfprintf(stderr, "%s: curr_col = %u, curr_row = %u\n", FUNC, curr_col, curr_row); +#endif /* QAK */ + + /* Initialize information for rows skipped over */ + sect_off = iblock->block_off; + for(u = 0; u < curr_row; u++) + sect_off += hdr->man_dtable.row_block_size[u] * hdr->man_dtable.cparam.width; + sect_off += hdr->man_dtable.row_block_size[curr_row] * curr_col; +#ifdef QAK +HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off); +#endif /* QAK */ + + /* Loop over the blocks to skip */ + for(u = start_entry; u < (start_entry + nentries); /* u is advanced in loop */) { + unsigned row_entries; /* Number of entries in a particular row */ + unsigned num_rows; /* Number of rows in indirect blocks referenced */ + + /* Compute number of rows in indirect blocks covered by entry */ + num_rows = (H5V_log2_of2((uint32_t)hdr->man_dtable.row_block_size[curr_row]) - + H5V_log2_of2(hdr->man_dtable.cparam.start_block_size)) - 1; + + /* Compute number of entries in (possible partial) current row */ + row_entries = MIN(hdr->man_dtable.cparam.width - curr_col, (start_entry + nentries) - u); +#ifdef QAK +HDfprintf(stderr, "%s: u = %u\n", FUNC, u); +HDfprintf(stderr, "%s: curr_col = %u, curr_row = %u\n", FUNC, curr_col, curr_row); +HDfprintf(stderr, "%s: row_entries = %u, num_rows = %u\n", FUNC, row_entries, num_rows); +#endif /* QAK */ + + /* Loop over rows in indirect blocks covered */ + acc_row_dblock_free_space = 0; + for(w = 0; w < num_rows; w++) { + + /* Compute free space in direct blocks for this row */ + row_dblock_free_space = hdr->man_dtable.cparam.width * hdr->man_dtable.row_dblock_free[w]; + acc_row_dblock_free_space += row_dblock_free_space; +#ifdef QAK +HDfprintf(stderr, "%s: w = %u\n", FUNC, w); +HDfprintf(stderr, "%s: hdr->man_dtable.row_dblock_free[%u] = %Zu\n", FUNC, w, hdr->man_dtable.row_dblock_free[w]); +#endif /* QAK */ + + /* Add "indirect" free space section for blocks in this row */ + + /* Create free list section node for blocks skipped over */ + if(H5HF_sect_indirect_add(hdr, dxpl_id, (sect_off + hdr->man_dtable.row_block_off[w]), + hdr->man_dtable.row_dblock_free[w], iblock, curr_row, curr_col, row_entries, w, num_rows) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section for indirect block's free space") + } /* end for */ +#ifdef QAK +HDfprintf(stderr, "%s: acc_row_dblock_free_space = %Zu\n", FUNC, acc_row_dblock_free_space); +#endif /* QAK */ + + /* Advance row & column position */ + sect_off += row_entries * hdr->man_dtable.row_block_size[curr_row]; + curr_row++; + curr_col = 0; /* (first partial row aligns this) */ + + /* Advance outer loop index */ + u += row_entries; + } /* end for */ +#ifdef QAK +HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off); +#endif /* QAK */ + + /* Advance the new block iterator */ + if(H5HF_hdr_inc_iter(hdr, (sect_off - hdr->man_iter_off), nentries) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't increase allocated heap size") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_hdr_skip_ranges() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_update_iter + * + * Purpose: Update state of heap to account for current iterator + * position. + * + * Note: Creates necessary indirect blocks + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 14 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_hdr_update_iter(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t min_dblock_size) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_update_iter) +#ifdef QAK +HDfprintf(stderr, "%s: min_dblock_size = %Zu\n", FUNC, min_dblock_size); +#endif /* QAK */ + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(min_dblock_size > 0); + + /* Check for creating first indirect block */ + if(hdr->man_dtable.curr_root_rows == 0) { + if(H5HF_man_iblock_root_create(hdr, dxpl_id, min_dblock_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "unable to create root indirect block") + } /* end if */ + else { + H5HF_indirect_t *iblock; /* Pointer to indirect block */ + hbool_t walked_up, walked_down; /* Condition variables for finding direct block location */ + unsigned next_row; /* Iterator's next block row */ + unsigned next_entry; /* Iterator's next block entry */ + unsigned min_dblock_row; /* Minimum row for direct block size request */ + +#ifdef QAK +HDfprintf(stderr, "%s: searching root indirect block\n", FUNC); +#endif /* QAK */ + /* Compute min. row for direct block requested */ + min_dblock_row = H5HF_dtable_size_to_row(&hdr->man_dtable, min_dblock_size); +#ifdef QAK +HDfprintf(stderr, "%s: min_dblock_size = %Zu, min_dblock_row = %u\n", FUNC, min_dblock_size, min_dblock_row); +#endif /* QAK */ + + /* Initialize block iterator, if necessary */ + if(!H5HF_man_iter_ready(&hdr->next_block)) { +#ifdef QAK +HDfprintf(stderr, "%s: hdr->man_iter_off = %Hu\n", FUNC, hdr->man_iter_off); +#endif /* QAK */ + /* Start iterator with previous offset of iterator */ + if(H5HF_man_iter_start_offset(hdr, dxpl_id, &hdr->next_block, hdr->man_iter_off) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to set block iterator location") + } /* end if */ + + /* Get information about current iterator location */ + if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL, &next_entry, &iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to retrieve current block iterator location") + +#ifdef QAK +HDfprintf(stderr, "%s: Check 1.0\n", FUNC); +HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock); +HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows); +HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row); +HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry); +#endif /* QAK */ + /* Check for skipping over blocks in the current block */ + if(min_dblock_row > next_row && next_row < iblock->nrows) { + unsigned min_entry; /* Min entry for direct block requested */ + unsigned skip_entries; /* Number of entries to skip in the current block */ + + /* Compute the number of entries to skip in the current block */ + min_entry = min_dblock_row * hdr->man_dtable.cparam.width; + if(min_dblock_row >= iblock->nrows) + skip_entries = (iblock->nrows * hdr->man_dtable.cparam.width) - next_entry; + else + skip_entries = min_entry - next_entry; +#ifdef QAK +HDfprintf(stderr, "%s: min_entry = %u, skip_entries = %u\n", FUNC, min_entry, skip_entries); +#endif /* QAK */ + + /* Add skipped direct blocks to heap's free space */ + if(H5HF_hdr_skip_blocks(hdr, dxpl_id, iblock, next_entry, skip_entries) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't add skipped blocks to heap's free space") + + /* Get information about new iterator location */ + if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL, &next_entry, &iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to retrieve current block iterator location") + } /* end if */ + + do { + /* Reset conditions for leaving loop */ + walked_up = walked_down = FALSE; + +#ifdef QAK +HDfprintf(stderr, "%s: Check 2.0\n", FUNC); +HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock); +HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows); +HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row); +HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry); +#endif /* QAK */ + + /* Check for walking off end of indirect block */ + /* (walk up iterator) */ + while(next_row >= iblock->nrows) { +#ifdef QAK +HDfprintf(stderr, "%s: Off the end of a block\n", FUNC); +#endif /* QAK */ + /* Check for needing to expand root indirect block */ + if(iblock->parent == NULL) { +#ifdef QAK +HDfprintf(stderr, "%s: Doubling root block\n", FUNC); +#endif /* QAK */ + if(H5HF_man_iblock_root_double(hdr, dxpl_id, min_dblock_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "unable to double root indirect block") + } /* end if */ + else { +#ifdef QAK +HDfprintf(stderr, "%s: Walking up a level\n", FUNC); +#endif /* QAK */ + /* Move iterator up one level */ + if(H5HF_man_iter_up(&hdr->next_block) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTNEXT, FAIL, "unable to advance current block iterator location") + + /* Increment location of next block at this level */ + if(H5HF_man_iter_next(hdr, &hdr->next_block, 1) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't advance fractal heap block location") + } /* end else */ + + /* Get information about new iterator location */ + if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL, &next_entry, &iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to retrieve current block iterator location") + + /* Indicate that we walked up */ + walked_up = TRUE; + } /* end while */ +#ifdef QAK +HDfprintf(stderr, "%s: Check 3.0\n", FUNC); +HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock); +HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows); +HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row); +HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry); +#endif /* QAK */ + + /* Check for walking into child indirect block */ + /* (walk down iterator) */ + if(next_row >= hdr->man_dtable.max_direct_rows) { + unsigned child_nrows; /* Number of rows in new indirect block */ + +#ifdef QAK +HDfprintf(stderr, "%s: Walking down into child indirect block\n", FUNC); +#endif /* QAK */ +#ifdef QAK +HDfprintf(stderr, "%s: Check 3.1\n", FUNC); +HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock); +HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows); +HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row); +HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry); +#endif /* QAK */ + HDassert(!H5F_addr_defined(iblock->ents[next_entry].addr)); + + /* Compute # of rows in next child indirect block to use */ + child_nrows = H5HF_dtable_size_to_rows(&hdr->man_dtable, hdr->man_dtable.row_block_size[next_row]); +#ifdef QAK +HDfprintf(stderr, "%s: child_nrows = %u\n", FUNC, child_nrows); +#endif /* QAK */ + + /* Check for skipping over indirect blocks */ + /* (that don't have direct blocks large enough to hold direct block size requested) */ + if(hdr->man_dtable.row_block_size[child_nrows - 1] < min_dblock_size) { + unsigned child_rows_needed; /* Number of rows needed to hold direct block */ + unsigned child_entry; /* Entry of child indirect block */ + +#ifdef QAK +HDfprintf(stderr, "%s: Skipping indirect block row that is too small\n", FUNC); +#endif /* QAK */ + /* Compute # of rows needed in child indirect block */ + child_rows_needed = (H5V_log2_of2(min_dblock_size) - H5V_log2_of2(hdr->man_dtable.cparam.start_block_size)) + 2; + HDassert(child_rows_needed > child_nrows); + child_entry = (next_row + (child_rows_needed - child_nrows)) * hdr->man_dtable.cparam.width; + if(child_entry > (iblock->nrows * hdr->man_dtable.cparam.width)) + child_entry = iblock->nrows * hdr->man_dtable.cparam.width; +#ifdef QAK +HDfprintf(stderr, "%s: child_rows_needed = %u\n", FUNC, child_rows_needed); +HDfprintf(stderr, "%s: child_entry = %u\n", FUNC, child_entry); +#endif /* QAK */ + + /* Add skipped indirect ranges to heap's free space */ + if(H5HF_hdr_skip_ranges(hdr, dxpl_id, iblock, next_entry, (child_entry - next_entry)) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't add skipped blocks to heap's free space") + } /* end if */ + else { + H5HF_indirect_t *new_iblock; /* Pointer to new indirect block */ + haddr_t new_iblock_addr; /* New indirect block's address */ + +#ifdef QAK +HDfprintf(stderr, "%s: Allocating new child indirect block\n", FUNC); +#endif /* QAK */ + /* Allocate new indirect block */ + if(H5HF_man_iblock_create(hdr, dxpl_id, iblock, next_entry, child_nrows, child_nrows, &new_iblock_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap indirect block") + + /* Lock new indirect block */ + if(NULL == (new_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, new_iblock_addr, child_nrows, iblock, next_entry, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") + + /* Move iterator down one level */ + if(H5HF_man_iter_down(&hdr->next_block, new_iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTNEXT, FAIL, "unable to advance current block iterator location") + + /* Check for skipping over rows and add free section for skipped rows */ + if(min_dblock_size > hdr->man_dtable.cparam.start_block_size) { + unsigned new_entry; /* Entry of direct block which is large enough */ + + /* Compute entry for direct block size requested */ + new_entry = hdr->man_dtable.cparam.width * min_dblock_row; +#ifdef QAK +HDfprintf(stderr, "%s: Skipping rows in new child indirect block - new_entry = %u\n", FUNC, new_entry); +#endif /* QAK */ + + /* Add skipped blocks to heap's free space */ + if(H5HF_hdr_skip_blocks(hdr, dxpl_id, new_iblock, 0, new_entry) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't add skipped blocks to heap's free space") + } /* end if */ + + /* Unprotect child indirect block */ + if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, new_iblock->addr, new_iblock, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + } /* end else */ + + /* Get information about new iterator location */ + if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL, &next_entry, &iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to retrieve current block iterator location") + + /* Indicate that we walked down */ + walked_down = TRUE; + } /* end if */ + } while(walked_down || walked_up); + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_hdr_update_iter() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_inc_iter + * + * Purpose: Advance "next block" iterator + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 23 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_hdr_inc_iter(H5HF_hdr_t *hdr, hsize_t adv_size, unsigned nentries) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_inc_iter) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(nentries); +#ifdef QAK +HDfprintf(stderr, "%s: hdr->man_iter_off = %Hu, adv_size = %Hu\n", FUNC, hdr->man_iter_off, adv_size); +#endif /* QAK */ + + /* Advance the iterator for the current location within the indirect block */ if(hdr->next_block.curr) if(H5HF_man_iter_next(hdr, &hdr->next_block, nentries) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTNEXT, FAIL, "unable to advance current block iterator location") - /* Update the "allocated" size within the heap */ - hdr->man_alloc_size = new_alloc_size; + /* Increment the offset of the iterator in the heap */ + hdr->man_iter_off += adv_size; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_hdr_inc_iter() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_reverse_iter + * + * Purpose: Walk "next block" iterator backwards until the correct + * location to allocate next block from is found + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 31 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_hdr_reverse_iter(H5HF_hdr_t *hdr, hid_t dxpl_id) +{ + H5HF_indirect_t *iblock; /* Indirect block where iterator is located */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_reverse_iter) + + /* + * Check arguments. + */ + HDassert(hdr); + + /* Initialize block iterator, if necessary */ + if(!H5HF_man_iter_ready(&hdr->next_block)) + /* Start iterator with previous offset of iterator */ + if(H5HF_man_iter_start_offset(hdr, dxpl_id, &hdr->next_block, hdr->man_iter_off) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to set block iterator location") + + /* Get information about current iterator location */ + if(H5HF_man_iter_curr(&hdr->next_block, NULL, NULL, NULL, &iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to retrieve current block iterator information") #ifdef QAK -HDfprintf(stderr, "%s: hdr->man_alloc_size = %Hu\n", FUNC, hdr->man_alloc_size); +HDfprintf(stderr, "%s: iblock->nchildren = %u\n", FUNC, iblock->nchildren); +HDfprintf(stderr, "%s: iblock->parent = %p\n", FUNC, iblock->parent); #endif /* QAK */ + /* Walk backwards through heap, looking for direct block to place iterator after */ + + /* Walk up the levels in the heap until we find an indirect block with children */ + while(iblock->nchildren == 0 && iblock->parent) { + /* Move iterator to parent of current block */ + if(H5HF_man_iter_up(&hdr->next_block) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTNEXT, FAIL, "unable to advance current block iterator location") + + /* Detach from parent indirect block */ + if(H5HF_man_iblock_detach(iblock->parent, dxpl_id, iblock->par_entry) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTATTACH, FAIL, "can't detach from parent indirect block") + iblock->parent = NULL; + iblock->par_entry = 0; + } /* end while */ + + /* If there's children in this indirect block, walk backwards to find last child */ + if(iblock->nchildren) { + unsigned curr_entry; /* Current entry for iterator */ + unsigned row; /* Row for entry */ + hbool_t walked_down; /* Loop flag */ + + /* Get information about current iterator location */ + if(H5HF_man_iter_curr(&hdr->next_block, NULL, NULL, &curr_entry, NULL) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to retrieve current block iterator information") +#ifdef QAK +HDfprintf(stderr, "%s: curr_entry = %u\n", FUNC, curr_entry); +#endif /* QAK */ + + /* Move current iterator position backwards once */ + curr_entry--; + + /* Search backwards for direct block to latch onto */ + do { + int tmp_entry; /* Temp. entry for iterator (use signed value to detect errors) */ + + /* Reset loop flag */ + walked_down = FALSE; + + /* Walk backwards through entries, until we find one that has a child */ + /* (Account for root indirect block shrinking) */ + tmp_entry = MIN(curr_entry, ((iblock->nrows * hdr->man_dtable.cparam.width) - 1)); +#ifdef QAK +HDfprintf(stderr, "%s: tmp_entry = %d\n", FUNC, tmp_entry); +HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows); +#endif /* QAK */ + while(!H5F_addr_defined(iblock->ents[tmp_entry].addr)) { + tmp_entry--; + HDassert(tmp_entry >= 0); + } /* end while */ +#ifdef QAK +HDfprintf(stderr, "%s: check 2.0 - tmp_entry = %d\n", FUNC, tmp_entry); +#endif /* QAK */ + curr_entry = tmp_entry; + + /* Check if entry is for a direct block */ + row = curr_entry / hdr->man_dtable.cparam.width; + if(row < hdr->man_dtable.max_direct_rows) { + /* Increment entry to empty location */ + curr_entry++; + + /* Set the current location of the iterator to next entry after the existing direct block */ + if(H5HF_man_iter_set_entry(hdr, &hdr->next_block, curr_entry) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSET, FAIL, "unable to set current block iterator location") + + /* Update iterator offset */ + hdr->man_iter_off = iblock->block_off; + hdr->man_iter_off += hdr->man_dtable.row_block_off[curr_entry / hdr->man_dtable.cparam.width]; + hdr->man_iter_off += hdr->man_dtable.row_block_size[curr_entry / hdr->man_dtable.cparam.width] * (curr_entry % hdr->man_dtable.cparam.width); + } /* end if */ + else { + H5HF_indirect_t *child_iblock; /* Pointer to child indirect block */ + unsigned child_nrows; /* # of rows in child block */ + + /* Compute # of rows in next child indirect block to use */ + child_nrows = H5HF_dtable_size_to_rows(&hdr->man_dtable, hdr->man_dtable.row_block_size[row]); + + /* Lock child indirect block */ + if(NULL == (child_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock->ents[curr_entry].addr, child_nrows, iblock, curr_entry, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") + + /* Set the current location of the iterator */ + if(H5HF_man_iter_set_entry(hdr, &hdr->next_block, curr_entry) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSET, FAIL, "unable to set current block iterator location") + + /* Walk down into child indirect block (pins child block) */ + if(H5HF_man_iter_down(&hdr->next_block, child_iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTNEXT, FAIL, "unable to advance current block iterator location") + + /* Update iterator location */ + iblock = child_iblock; + curr_entry = (child_iblock->nrows * hdr->man_dtable.cparam.width) - 1; + + /* Unprotect child indirect block */ + if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, child_iblock->addr, child_iblock, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + + /* Note that we walked down */ + walked_down = TRUE; + } /* end else */ + } while(walked_down); + } /* end if */ + else { + /* Reset header information back to "empty heap" state */ + if(H5HF_hdr_empty(hdr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't make heap empty") + } /* end else */ + done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_hdr_inc_alloc() */ +} /* end H5HF_hdr_reverse_iter() */ /*------------------------------------------------------------------------- @@ -584,13 +1309,10 @@ HDfprintf(stderr, "%s: Reseting heap header to empty\n", FUNC); /* Sanity check */ HDassert(hdr); - /* Reset root pointer information */ - hdr->man_dtable.curr_root_rows = 0; - hdr->man_dtable.table_addr = HADDR_UNDEF; - /* Shrink heap size */ hdr->total_size = hdr->std_size; hdr->man_size = 0; + hdr->man_alloc_size = 0; /* Reset the free space in direct blocks */ hdr->total_man_free = 0; |