/*------------------------------------------------------------------------- * Function: H5HF_man_iter_start_offset * * Purpose: Initialize a block iterator to a particular location, given * an offset in the heap * * Return: SUCCEED/FAIL * * Programmer: Quincey Koziol * [email protected] * Apr 24 2006 * *------------------------------------------------------------------------- */ herr_t H5HF_man_iter_start_offset(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_block_iter_t *biter, hsize_t offset) { H5HF_indirect_t *iblock; /* Indirect block for location context */ haddr_t iblock_addr; /* Address of indirect block */ unsigned iblock_nrows; /* # of rows in indirect block */ H5HF_indirect_t *iblock_parent; /* Parent indirect block of location context */ unsigned iblock_par_entry; /* Entry within parent indirect block */ hsize_t curr_offset; /* Current offset, as adjusted */ unsigned row; /* Current row we are on */ unsigned col; /* Column in row */ hbool_t root_block = TRUE; /* Flag to indicate the current block is the root indirect block */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iter_start_offset) /* * Check arguments. */ HDassert(biter); HDassert(!biter->ready); /* Check for empty heap */ HDassert(offset >= hdr->man_dtable.cparam.start_block_size); /* Allocate level structure */ if(NULL == (biter->curr = H5FL_MALLOC(H5HF_block_loc_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") /* 1: <Scan down block offsets for dtable rows until find a row >= offset> <Set current location's row, col, entry & size> <If row < max_direct_rows> <Done> <Else - row > max_direct_rows> <Create new block level> <Link new block level into iterator> <Adjust offset for block offset for row> <Make new block level the current context> <Goto 1> */ do { hbool_t did_protect; /* Whether we protected the indirect block or not */ /* Walk down the rows in the doubling table until we've found the correct row for the next block */ for(row = 0; row < hdr->man_dtable.max_root_rows; row++) if((offset >= hdr->man_dtable.row_block_off[row]) && (offset < hdr->man_dtable.row_block_off[row] + (hdr->man_dtable.cparam.width * hdr->man_dtable.row_block_size[row]))) break; /* Adjust offset by row offset */ curr_offset = offset - hdr->man_dtable.row_block_off[row]; /* Compute column */ H5_CHECK_OVERFLOW((curr_offset / hdr->man_dtable.row_block_size[row]), hsize_t, unsigned); col = (unsigned)(curr_offset / hdr->man_dtable.row_block_size[row]); /* Set the current level's context */ biter->curr->row = row; biter->curr->col = col; biter->curr->entry = (row * hdr->man_dtable.cparam.width) + col; /* Get the context indirect block's information */ if(root_block) { iblock_addr = hdr->man_dtable.table_addr; iblock_nrows = hdr->man_dtable.curr_root_rows; iblock_parent = NULL; iblock_par_entry = 0; /* The root block can't go up further... */ biter->curr->up = NULL; /* Next time through the loop will not be with the root indirect block */ root_block = FALSE; } /* end if */ else { hsize_t child_size; /* Size of new indirect block to create */ /* Retrieve the parent information from the previous context location */ iblock_parent = biter->curr->up->context; iblock_par_entry = biter->curr->up->entry; /* Look up the address of context indirect block */ iblock_addr = iblock_parent->ents[iblock_par_entry].addr; /* Compute # of rows in context indirect block */ child_size = hdr->man_dtable.row_block_size[biter->curr->up->row]; iblock_nrows = (H5V_log2_gen(child_size) - hdr->man_dtable.first_row_bits) + 1; } /* end else */ /* Load indirect block for this context location */ if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, iblock_nrows, iblock_parent, iblock_par_entry, FALSE, H5AC_WRITE, &did_protect))) HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") /* Make indirect block the context for the current location */ biter->curr->context = iblock; /* Hold the indirect block with the location */ if(H5HF_iblock_incr(biter->curr->context) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") /* Release the current indirect block */ if(H5HF_man_iblock_unprotect(iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") iblock = NULL; /* See if the location falls in a direct block row */ /* Or, if the offset has just filled up a direct or indirect block */ if(curr_offset == (col * hdr->man_dtable.row_block_size[row]) || row < hdr->man_dtable.max_direct_rows) { HDassert(curr_offset - (col * hdr->man_dtable.row_block_size[row]) == 0); break; /* Done now */ } /* end if */ /* Indirect block row */ else { H5HF_block_loc_t *new_loc; /* Pointer to new block location */ /* Allocate level structure */ if(NULL == (new_loc = H5FL_MALLOC(H5HF_block_loc_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") /* Link new level into iterator */ new_loc->up = biter->curr; /* Adjust offset for new level */ offset = curr_offset - (col * hdr->man_dtable.row_block_size[row]); /* Make new block the current context */ biter->curr = new_loc; } /* end else */ } while(1); /* Breaks out in middle */ /* Set flag to indicate block iterator finished initializing */ biter->ready = TRUE; done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_man_iter_start_offset() */
/*------------------------------------------------------------------------- * Function: H5F_accum_read * * Purpose: Attempts to read some data from the metadata accumulator for * a file into a buffer. * * Note: We can't change (or add to) the metadata accumulator, because * this might be a speculative read and could possibly read raw * data into the metadata accumulator. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * [email protected] * Jan 10 2008 * *------------------------------------------------------------------------- */ herr_t H5F_accum_read(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr, size_t size, void *buf/*out*/) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) HDassert(f); HDassert(f->shared); HDassert(buf); /* Check if this information is in the metadata accumulator */ if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && type != H5FD_MEM_DRAW) { if(size < H5F_ACCUM_MAX_SIZE) { /* Sanity check */ HDassert(!f->shared->accum.buf || (f->shared->accum.alloc_size >= f->shared->accum.size)); /* Current read adjoins or overlaps with metadata accumulator */ if(H5F_addr_overlap(addr, size, f->shared->accum.loc, f->shared->accum.size) || ((addr + size) == f->shared->accum.loc) || (f->shared->accum.loc + f->shared->accum.size) == addr) { size_t amount_before; /* Amount to read before current accumulator */ haddr_t new_addr; /* New address of the accumulator buffer */ size_t new_size; /* New size of the accumulator buffer */ /* Compute new values for accumulator */ new_addr = MIN(addr, f->shared->accum.loc); new_size = (size_t)(MAX((addr + size), (f->shared->accum.loc + f->shared->accum.size)) - new_addr); /* Check if we need more buffer space */ if(new_size > f->shared->accum.alloc_size) { size_t new_alloc_size; /* New size of accumulator */ /* Adjust the buffer size to be a power of 2 that is large enough to hold data */ new_alloc_size = (size_t)1 << (1 + H5V_log2_gen((uint64_t)(new_size - 1))); /* Reallocate the metadata accumulator buffer */ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, new_alloc_size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer") /* Note the new buffer size */ f->shared->accum.alloc_size = new_alloc_size; #ifdef H5_CLEAR_MEMORY HDmemset(f->shared->accum.buf + f->shared->accum.size, 0, (f->shared->accum.alloc_size - f->shared->accum.size)); #endif /* H5_CLEAR_MEMORY */ } /* end if */ /* Read the part before the metadata accumulator */ if(addr < f->shared->accum.loc) { /* Set the amount to read */ H5_ASSIGN_OVERFLOW(amount_before, (f->shared->accum.loc - addr), hsize_t, size_t); /* Make room for the metadata to read in */ HDmemmove(f->shared->accum.buf + amount_before, f->shared->accum.buf, f->shared->accum.size); /* Adjust dirty region tracking info, if present */ if(f->shared->accum.dirty) f->shared->accum.dirty_off += amount_before; /* Dispatch to driver */ if(H5FD_read(f->shared->lf, dxpl_id, type, addr, amount_before, f->shared->accum.buf) < 0) HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed") } /* end if */ else