diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2008-10-07 04:17:35 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2008-10-07 04:17:35 (GMT) |
commit | 9f60f016ab71cf8ce39c859fd9eb61c6fca35d63 (patch) | |
tree | 0ddbcb2f8707b578af22c62748420b9e3c19177b /src/H5FDspace.c | |
parent | 504c67846e6a4cc5706403bf21a9ae4f07aae7b4 (diff) | |
download | hdf5-9f60f016ab71cf8ce39c859fd9eb61c6fca35d63.zip hdf5-9f60f016ab71cf8ce39c859fd9eb61c6fca35d63.tar.gz hdf5-9f60f016ab71cf8ce39c859fd9eb61c6fca35d63.tar.bz2 |
[svn-r15800] Description:
Bring file free space branch changes through r15795 into trunk, which
includes a fair bit of code cleanup & rearrangement along with a couple of
bug fixes also.
Tested on:
Mac OS X/32 10.5.5 (amazon) in debug mode
Mac OS X/32 10.5.5 (amazon) w/C++ & FORTRAN, w/threadsafe,
in production mode
FreeBSD/32 6.3 (duty) in debug mode
FreeBSD/64 6.3 (liberty) w/C++ & FORTRAN, in debug mode
Linux/32 2.6 (kagiso) w/PGI compilers, w/C++ & FORTRAN, w/threadsafe,
in debug mode
Linux/64-amd64 2.6 (smirom) w/Intel compilers w/default API=1.6.x,
w/C++ & FORTRAN, in production mode
Solaris/32 2.10 (linew) w/deprecated symbols disabled, w/C++ & FORTRAN,
w/szip filter, in production mode
Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN,
in production mode
Linux/64-ia64 2.4 (tg-login3) w/parallel, w/FORTRAN, in production mode
Linux/64-amd64 2.6 (abe) w/parallel, w/FORTRAN, in production mode
Diffstat (limited to 'src/H5FDspace.c')
-rw-r--r-- | src/H5FDspace.c | 1611 |
1 files changed, 120 insertions, 1491 deletions
diff --git a/src/H5FDspace.c b/src/H5FDspace.c index 0bbf160..0fadc1e 100644 --- a/src/H5FDspace.c +++ b/src/H5FDspace.c @@ -66,19 +66,6 @@ /********************/ /* Local Prototypes */ /********************/ -static haddr_t H5FD_alloc_from_free_list(H5FD_t *file, H5FD_mem_t type, - hsize_t size); -static haddr_t H5FD_aggr_alloc(H5FD_t *file, H5FD_blk_aggr_t *aggr, - H5FD_blk_aggr_t *other_aggr, H5FD_mem_t type, hid_t dxpl_id, hsize_t size); -static herr_t H5FD_aggr_adjoin(const H5FD_t *file, H5FD_blk_aggr_t *aggr, - H5FD_free_t *last); -static htri_t H5FD_aggr_can_extend(const H5FD_t *file, const H5FD_blk_aggr_t *aggr, - haddr_t eoa, haddr_t end); -static herr_t H5FD_aggr_shift(H5FD_blk_aggr_t *aggr, hsize_t extra); -static herr_t H5FD_aggr_query(const H5FD_t *file, const H5FD_blk_aggr_t *aggr, - haddr_t *addr, hsize_t *size); -static haddr_t H5FD_real_alloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size); -static haddr_t H5FD_update_eoa(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size); /*********************/ @@ -98,9 +85,6 @@ static haddr_t H5FD_update_eoa(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsi /* Declare a free list to manage the H5FD_free_t struct */ H5FL_DEFINE(H5FD_free_t); -/* Declare a PQ free list to manage the metadata accumulator buffer */ -H5FL_BLK_DEFINE(meta_accum); - /*-------------------------------------------------------------------------- @@ -126,965 +110,127 @@ H5FD_space_init_interface(void) /*------------------------------------------------------------------------- - * Function: H5FD_free_freelist - * - * Purpose: Split off from H5FD_close(). Free the elements in the - * free list for this file driver. - * - * Return: Success: SUCCEED - * Failure: Never fails - * - * Programmer: Bill Wendling - * 17. February 2003 - * - *------------------------------------------------------------------------- - */ -herr_t -H5FD_free_freelist(H5FD_t *file) -{ - H5FD_mem_t i; -#ifdef H5FD_ALLOC_DEBUG - unsigned nblocks = 0; - hsize_t nbytes = 0; -#endif /* H5FD_ALLOC_DEBUG */ - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_free_freelist) - - /* check args */ - HDassert(file && file->cls); - - /* - * Free all free-lists, leaking any memory thus described. Also leaks - * file space allocated but not used when metadata aggregation is - * turned on. - */ - for(i = H5FD_MEM_DEFAULT; i < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, i)) { - H5FD_free_t *cur, *next; - - for( cur = file->fl[i]; cur; cur = next) { -#ifdef H5FD_ALLOC_DEBUG - ++nblocks; - nbytes += cur->size; -#endif /* H5FD_ALLOC_DEBUG */ - next = cur->next; - (void)H5FL_FREE(H5FD_free_t, cur); - } /* end for */ - - file->fl[i] = NULL; - } /* end for */ - -#ifdef H5FD_ALLOC_DEBUG - if(nblocks) - HDfprintf(stderr, "%s: leaked %Hu bytes of file memory in %u blocks\n", - "H5FD_free_freelist", nbytes, nblocks); -#endif /* H5FD_ALLOC_DEBUG */ - - /* Check if we need to reset the metadata accumulator information */ - if(file->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) { - /* Free the buffer */ - if(file->meta_accum) - file->meta_accum = H5FL_BLK_FREE(meta_accum, file->meta_accum); - - /* Reset the buffer sizes & location */ - file->accum_buf_size = file->accum_size = 0; - file->accum_loc = HADDR_UNDEF; - file->accum_dirty = 0; - } /* end if */ - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5FD_free_freelist() */ - - -/*------------------------------------------------------------------------- - * Function: H5FD_alloc - * - * Purpose: Private version of H5FDalloc(). - * - * Return: Success: The format address of the new file memory. - * Failure: The undefined address HADDR_UNDEF - * - * Programmer: Robb Matzke - * Wednesday, August 4, 1999 - * - *------------------------------------------------------------------------- - */ -haddr_t -H5FD_alloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size) -{ - haddr_t ret_value = HADDR_UNDEF; - - FUNC_ENTER_NOAPI(H5FD_alloc, HADDR_UNDEF) -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size); -#endif /* H5FD_ALLOC_DEBUG */ - - /* check args */ - assert(file); - assert(file->cls); - assert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); - assert(size > 0); - -#ifdef H5F_DEBUG - if(H5DEBUG(F)) - HDfprintf(H5DEBUG(F), "%s: alignment=%Hd, threshold=%Hd, size=%Hd\n", - FUNC, file->alignment, file->threshold, size); -#endif /* H5F_DEBUG */ - - /* Try to allocate from the free list first */ - if((ret_value = H5FD_alloc_from_free_list(file, type, size)) != HADDR_UNDEF) - HGOTO_DONE(ret_value) - -#ifdef H5F_DEBUG - if(H5DEBUG(F)) - HDfprintf(H5DEBUG(F), "%s: Could not allocate from freelists\n", FUNC); -#endif /* H5F_DEBUG */ - - if(type != H5FD_MEM_DRAW) { - /* Handle metadata differently from "raw" data */ - if(HADDR_UNDEF == (ret_value = H5FD_aggr_alloc(file, &(file->meta_aggr), &(file->sdata_aggr), type, dxpl_id, size))) - HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate metadata") - } /* end if */ - else { - /* Allocate "raw" data */ - if(HADDR_UNDEF == (ret_value = H5FD_aggr_alloc(file, &(file->sdata_aggr), &(file->meta_aggr), type, dxpl_id, size))) - HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate raw data") - } /* end else */ - -done: -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value); -#endif /* H5FD_ALLOC_DEBUG */ - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_alloc() */ - - -/*------------------------------------------------------------------------- - * Function: H5FD_alloc_from_free_list + * Function: H5FD_extend * - * Purpose: Try to allocate SIZE bytes of memory from the free list - * if possible. + * Purpose: Extend the EOA space of a file. * - * This is split from H5FD_alloc(). + * NOTE: Returns absolute file offset * - * Return: Success: The format address of the new file memory. + * Return: Success: The address of the previous EOA. * Failure: The undefined address HADDR_UNDEF * * Programmer: Bill Wendling - * 02. December, 2002 - * - *------------------------------------------------------------------------- - */ -static haddr_t -H5FD_alloc_from_free_list(H5FD_t *file, H5FD_mem_t type, hsize_t size) -{ - H5FD_mem_t mapped_type; - haddr_t ret_value = HADDR_UNDEF; - - FUNC_ENTER_NOAPI(H5FD_alloc_from_free_list, HADDR_UNDEF) -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size); -#endif /* H5FD_ALLOC_DEBUG */ - - assert(file); - assert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); - assert(size > 0); - - /* Map the allocation request to a free list */ - if(H5FD_MEM_DEFAULT == file->cls->fl_map[type]) - mapped_type = type; - else - mapped_type = file->cls->fl_map[type]; - - /* - * Try to satisfy the request from the free list. Only perform the - * search if the free list has the potential of satisfying the - * request. - * - * Here, aligned requests are requests that are >= threshold and - * alignment > 1. - * - * For non-aligned request, first try to find an exact match, - * otherwise use the best match which is the smallest size that meets - * the requested size. - * - * For aligned address request, find a block in the following order - * of preferences: - * - * 1. block address is aligned and exact match in size; - * 2. block address is aligned with smallest size > requested size; - * 3. block address is not aligned with smallest size >= requested size. - */ - if(mapped_type >= H5FD_MEM_DEFAULT && (file->maxsize == 0 || size <= file->maxsize)) { - H5FD_free_t *prev = NULL, *best = NULL; - H5FD_free_t *cur = file->fl[mapped_type]; - hbool_t found_aligned = FALSE; - hbool_t need_aligned; - hsize_t head; - - need_aligned = file->alignment > 1 && size >= file->threshold; - - while(cur) { - if(cur->size > file->maxsize) - file->maxsize = cur->size; - - if(need_aligned) { - if((head = cur->addr % file->alignment) == 0) { - /* - * Aligned address - */ - if(cur->size >= size) { - if(cur->size == size) { - /* exact match */ - ret_value = cur->addr; - - /* - * Make certain we don't hand out a block of raw data - * from the free list which overlaps with the metadata - * aggregation buffer (if it's turned on) - */ - if(type == H5FD_MEM_DRAW && - (file->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && - H5F_addr_overlap(ret_value, size, - file->accum_loc, file->accum_size)) { - ret_value = HADDR_UNDEF; - } else { - if(prev) - prev->next = cur->next; - else - file->fl[mapped_type] = cur->next; - - (void)H5FL_FREE(H5FD_free_t, cur); - - if(size == file->maxsize) - file->maxsize = 0; /*unknown*/ - -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: Exact size match (aligned)\n", FUNC); -#endif /* H5FD_ALLOC_DEBUG */ - HGOTO_DONE(ret_value) - } - } - else - /* Favor smallest block, that's closest to the beginning of the file */ - if(!best || !found_aligned || cur->size < best->size || - (cur->size == best->size && H5F_addr_lt(cur->addr, best->addr))) { - best = cur; - found_aligned = TRUE; - } - } /* end if */ - } else { - /* - * Non-aligned address - * - * Check to see if this block is big enough to skip - * to the next aligned address and is still big - * enough for the requested size. The extra - * (cur->size > head) is for preventing unsigned - * underflow. (This could be improved by checking for - * an exact match after excluding the head. Such - * match is as good as the found_aligned case above.) - */ - head = file->alignment - head; /* actual head size */ - - if(!found_aligned && cur->size > head && cur->size-head >= size) { - /* Favor smallest block, that's closest to the beginning of the file */ - if(!best || cur->size < best->size || - (cur->size == best->size && H5F_addr_lt(cur->addr, best->addr))) - best = cur; - } /* end if */ - } /* end else */ - } else { - /* !need_aligned */ - if(cur->size >= size) { - if(cur->size == size) { - /* exact match */ - ret_value = cur->addr; - - /* - * Make certain we don't hand out a block of raw data - * from the free list which overlaps with the metadata - * aggregation buffer (if it's turned on) - */ - if(type == H5FD_MEM_DRAW && - (file->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && - H5F_addr_overlap(ret_value, size, file->accum_loc, - file->accum_size)) { - ret_value = HADDR_UNDEF; - } else { - if(prev) - prev->next = cur->next; - else - file->fl[mapped_type] = cur->next; - - (void)H5FL_FREE(H5FD_free_t, cur); - - if(size == file->maxsize) - file->maxsize = 0; /*unknown*/ - -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: Exact size match (unaligned)\n", FUNC); -#endif /* H5FD_ALLOC_DEBUG */ - HGOTO_DONE(ret_value) - } - } /* end if */ - else { - /* Favor smallest block, that's closest to the beginning of the file */ - if(!best || cur->size < best->size || - (cur->size == best->size && H5F_addr_lt(cur->addr, best->addr))) - best = cur; - } /* end else */ - } /* end if */ - } /* end else */ - - prev = cur; - cur = cur->next; - } /* end while */ - - /* Couldn't find exact match, use best fitting piece found */ - if(best) { -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: Splitting %Hu byte sized block\n", FUNC, best->size); -#endif /* H5FD_ALLOC_DEBUG */ - if(best->size == file->maxsize) - file->maxsize = 0; /*unknown*/ - - if(!need_aligned || found_aligned) { - /* free only tail */ - ret_value = best->addr; - - /* - * Make certain we don't hand out a block of raw data - * from the free list which overlaps with the metadata - * aggregation buffer (if it's turned on) - */ - if(type == H5FD_MEM_DRAW && - (file->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && - H5F_addr_overlap(ret_value, size, file->accum_loc, - file->accum_size)) { - ret_value = HADDR_UNDEF; - } else { - best->addr += size; /* Reduce size of block on free list */ - best->size -= size; - HGOTO_DONE(ret_value) - } - } else { - /* - * Split into 3 pieces. Keep the the head and tail in the - * freelist. - */ - H5FD_free_t *tmp = NULL; - - head = file->alignment - (best->addr % file->alignment); - ret_value = best->addr + head; - - /* - * Make certain we don't hand out a block of raw data - * from the free list which overlaps with the metadata - * aggregation buffer (if it's turned on) - */ - if(type == H5FD_MEM_DRAW && - (file->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && - H5F_addr_overlap(ret_value, size, file->accum_loc, file->accum_size)) { - ret_value = HADDR_UNDEF; - } else { - /* Attempt to allocate memory for temporary node */ - if((tmp = H5FL_MALLOC(H5FD_free_t))==NULL) - HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "free block allocation failed") - - if((tmp->size = (best->size - (head + size)))!=0) { - tmp->addr = best->addr + (head + size); - tmp->next = best->next; - best->next = tmp; - } else { - /* no tail piece */ - (void)H5FL_FREE(H5FD_free_t,tmp); - } - - best->size = head; - HGOTO_DONE(ret_value) - } /* end else */ - } /* end else */ - } /* end if */ - } /* end if */ - -done: -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value); -#endif /* H5FD_ALLOC_DEBUG */ - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_alloc_from_free_list() */ - - -/*------------------------------------------------------------------------- - * Function: H5FD_aggr_alloc - * - * Purpose: Try to allocate SIZE bytes of memory from an aggregator - * block if possible. - * - * This is split from H5FD_alloc(). - * - * Return: Success: The format address of the new file memory. - * Failure: The undefined address HADDR_UNDEF + * Wednesday, 04. December, 2002 * - * Programmer: Bill Wendling - * 2. December, 2002 + * Modifications: + * Vailin Choi, 29th July 2008 + * Add 2 more parameters for handling alignment: address and size of the fragment * *------------------------------------------------------------------------- */ static haddr_t -H5FD_aggr_alloc(H5FD_t *file, H5FD_blk_aggr_t *aggr, H5FD_blk_aggr_t *other_aggr, - H5FD_mem_t type, hid_t dxpl_id, hsize_t size) +H5FD_extend(H5FD_t *file, H5FD_mem_t type, hbool_t new_block, hsize_t size, haddr_t *frag_addr, hsize_t *frag_size) { + haddr_t eoa; /* Address of end-of-allocated space */ + hsize_t extra; /* Extra space to allocate, to align request */ haddr_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5FD_aggr_alloc) -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size); -#endif /* H5FD_ALLOC_DEBUG */ + FUNC_ENTER_NOAPI_NOINIT(H5FD_extend) /* check args */ HDassert(file); - HDassert(aggr); - HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA); - HDassert(other_aggr); - HDassert(other_aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || other_aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA); - HDassert(other_aggr->feature_flag != aggr->feature_flag); + HDassert(file->cls); HDassert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); HDassert(size > 0); - /* - * If the aggregation feature is enabled for this VFL - * driver, allocate "generic" space and sub-allocate out of - * that, if possible. Otherwise just allocate through - * H5FD_real_alloc() - */ - if(file->feature_flags & aggr->feature_flag) { -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: aggr = {%a, %Hu, %Hu}\n", FUNC, aggr->addr, aggr->tot_size, aggr->size); -#endif /* H5FD_ALLOC_DEBUG */ - /* Check if the space requested is larger than the space left in the block */ - if(size > aggr->size) { - haddr_t new_space; /* Address for newly allocated space */ - - /* Check if the block asked for is too large for 'normal' aggregator block */ - if(size >= aggr->alloc_size) { - /* Allocate more room for this new block the regular way */ - if(HADDR_UNDEF == (new_space = H5FD_real_alloc(file, type, dxpl_id, size))) - HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate aggregation block") - - /* Check if the new space is at the end of the current block */ - if((aggr->addr + aggr->size) == new_space) { - /* - * Treat the allocation request as if the current block - * grew by the amount allocated and just update the address. - * - * Don't bother updating the block's size since it will - * just grow and shrink by the same amount. - * - * _Do_ add to the total size aggregated. - * - */ - ret_value = aggr->addr; - aggr->addr += size; - aggr->tot_size += size; - } /* end if */ - else { - /* Check if the new space is at the end of the _other_ block */ - if(other_aggr->size > 0 && (other_aggr->addr + other_aggr->size) == new_space) { -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: New block is at end of 'other' block: other_aggr = {%a, %Hu, %Hu}\n", FUNC, other_aggr->addr, other_aggr->tot_size, other_aggr->size); -#endif /* H5FD_ALLOC_DEBUG */ - /* If the other block has used at least the - * 'allocation' amount for that block, shift the - * newly allocated space down over the remainder - * in the 'other block', shift the 'other block' - * up by the same amount and free it. (Which - * should amount to "bubbling" the remainder in - * the 'other block' to the end of the file and - * then "popping" the bubble by shrinking the - * file) - */ - if((other_aggr->tot_size - other_aggr->size) >= other_aggr->alloc_size) { - H5FD_mem_t alloc_type = (other_aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA ? H5FD_MEM_DEFAULT : H5FD_MEM_DRAW); /* Type of file memory to work with */ - haddr_t free_addr = (new_space + size) - other_aggr->size; /* Address of free space in 'other block' shifted toward end of the file */ - hsize_t free_size = other_aggr->size; /* Size of the free space in 'other block' */ - -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: Freeing 'other' block\n", FUNC); -#endif /* H5FD_ALLOC_DEBUG */ - /* Reset 'other' block's info */ - other_aggr->addr = 0; - other_aggr->tot_size = 0; - other_aggr->size = 0; - - /* Shift newly allocated space down */ - new_space -= free_size; - - /* Return the unused portion of the 'other' block to a free list */ - if(H5FD_free(file, alloc_type, dxpl_id, free_addr, free_size) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation block") - } /* end if */ - } /* end if */ - - /* Use the new space allocated, leaving the old block */ - ret_value = new_space; - } /* end else */ - } /* end if */ - else { - H5FD_mem_t alloc_type = (aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA ? H5FD_MEM_DEFAULT : H5FD_MEM_DRAW); /* Type of file memory to work with */ - - /* Allocate another block */ -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: Allocating block\n", FUNC); -#endif /* H5FD_ALLOC_DEBUG */ - if(HADDR_UNDEF == (new_space = H5FD_real_alloc(file, alloc_type, dxpl_id, aggr->alloc_size))) - HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate aggregation block") - - /* Check if the new space is at the end of the current block */ - if(aggr->addr + aggr->size == new_space) { - aggr->size += aggr->alloc_size; - aggr->tot_size += aggr->alloc_size; - } /* end if */ - else { - hsize_t new_size; /* Size of new aggregator block */ - - /* Return the unused portion of the block to a free list */ - if(aggr->size > 0) - if(H5FD_free(file, alloc_type, dxpl_id, aggr->addr, aggr->size) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation block") - - /* Check if the new space is at the end of the _other_ block */ - if(other_aggr->size > 0 && (other_aggr->addr + other_aggr->size) == new_space) { -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: New block is at end of 'other' block: other_aggr = {%a, %Hu, %Hu}\n", FUNC, other_aggr->addr, other_aggr->tot_size, other_aggr->size); -#endif /* H5FD_ALLOC_DEBUG */ -#ifdef QAK - /* If the other block has used at least the - * 'allocation' amount for that block, give the - * remaining free space in the 'other' block to - * the new space allocated for 'this' block. - */ - if((other_aggr->tot_size - other_aggr->size) >= other_aggr->alloc_size) { -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: Absorbing 'other' block\n", FUNC); -#endif /* H5FD_ALLOC_DEBUG */ - /* Absorb the remaining free space into newly allocated block */ - new_space -= other_aggr->size; - new_size = aggr->alloc_size + other_aggr->size; - - /* Reset the info for the 'other' block */ - other_aggr->addr = 0; - other_aggr->tot_size = 0; - other_aggr->size = 0; - } /* end if */ - else - new_size = aggr->alloc_size; -#else /* QAK */ - /* If the other block has used at least the - * 'allocation' amount for that block, shift the - * newly allocated space down over the remainder - * in the 'other block', shift the 'other block' - * up by the same amount and free it. (Which - * should amount to "bubbling" the remainder in - * the 'other block' to the end of the file and - * then "popping" the bubble by shrinking the - * file) - */ - if((other_aggr->tot_size - other_aggr->size) >= other_aggr->alloc_size) { - H5FD_mem_t other_type = (other_aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA ? H5FD_MEM_DEFAULT : H5FD_MEM_DRAW); /* Type of file memory to work with */ - haddr_t free_addr = (new_space + aggr->alloc_size) - other_aggr->size; /* Address of free space in 'other block' shifted toward end of the file */ - hsize_t free_size = other_aggr->size; /* Size of the free space in 'other block' */ - -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: Freeing 'other' block\n", FUNC); -#endif /* H5FD_ALLOC_DEBUG */ - /* Reset 'other' block's info */ - other_aggr->addr = 0; - other_aggr->tot_size = 0; - other_aggr->size = 0; - - /* Shift newly allocated space down */ - new_space -= free_size; - - /* Return the unused portion of the 'other' block to a free list */ - if(H5FD_free(file, other_type, dxpl_id, free_addr, free_size) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation block") - } /* end if */ - new_size = aggr->alloc_size; -#endif /* QAK */ - } /* end if */ - else - new_size = aggr->alloc_size; - - /* Point the aggregator at the newly allocated block */ - aggr->addr = new_space; - aggr->size = new_size; - aggr->tot_size = new_size; - } /* end else */ - - /* Allocate space out of the metadata block */ - ret_value = aggr->addr; - aggr->size -= size; - aggr->addr += size; - } /* end else */ - } /* end if */ - else { - /* Allocate space out of the block */ - ret_value = aggr->addr; - aggr->size -= size; - aggr->addr += size; - } - } /* end if */ - else { - /* Allocate data the regular way */ - if(HADDR_UNDEF == (ret_value = H5FD_real_alloc(file, type, dxpl_id, size))) - HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate file space") - } /* end else */ - -done: -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value); -#endif /* H5FD_ALLOC_DEBUG */ - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_aggr_alloc() */ - - -/*------------------------------------------------------------------------- - * Function: H5FD_aggr_adjoin - * - * Purpose: Check if a newly freed block of space in the file adjoins an - * aggregator block - * - * Return: Success: Non-negative - * Failure: Negative - * - * Programmer: Quincey Koziol - * Thursday, December 13, 2007 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5FD_aggr_adjoin(const H5FD_t *file, H5FD_blk_aggr_t *aggr, H5FD_free_t *last) -{ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_aggr_adjoin) - - /* Check args */ - HDassert(file); - HDassert(file->cls); - HDassert(aggr); - HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA); - HDassert(last); - - /* Check if this free block adjoins the aggregator */ - if((file->feature_flags & aggr->feature_flag) && aggr->size > 0) { - hbool_t adjoins = FALSE; /* Whether the block adjoined the aggregator */ - - /* Does the newly freed space adjoin the end of the aggregator */ - if((aggr->addr + aggr->size) == last->addr) { - last->addr = aggr->addr; - adjoins = TRUE; - } /* end if */ - /* Does the newly freed space adjoin the beginning of the aggregator */ - else if((last->addr + last->size) == aggr->addr) - adjoins = TRUE; + /* Get current end-of-allocated space address */ + eoa = file->cls->get_eoa(file, type); - /* Reset aggregator information, if adjoined */ - if(adjoins) { -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: Adjoined flag = %lx aggregator\n", "H5FD_aggr_adjoin", aggr->feature_flag); -#endif /* H5FD_ALLOC_DEBUG */ - last->size += aggr->size; - aggr->addr = 0; - aggr->size = 0; - } /* end if */ + /* Compute extra space to allocate, if this is a new block and should be aligned */ + extra = 0; + if(new_block && file->alignment > 1 && size >= file->threshold) { + hsize_t mis_align; /* Amount EOA is misaligned */ + + /* Check for EOA already aligned */ + if((mis_align = (eoa % file->alignment)) > 0) { + extra = file->alignment - mis_align; + if (frag_addr) *frag_addr = eoa; + if (frag_size) *frag_size = extra; + } } /* end if */ - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5FD_aggr_adjoin() */ + /* Add in extra allocation amount */ + size += extra; - -/*------------------------------------------------------------------------- - * Function: H5FD_aggr_can_extend - * - * Purpose: Check is an aggregator block can be extended - * - * Return: Success: Non-negative - * Failure: Negative - * - * Programmer: Quincey Koziol - * Thursday, December 13, 2007 - * - *------------------------------------------------------------------------- - */ -static htri_t -H5FD_aggr_can_extend(const H5FD_t *file, const H5FD_blk_aggr_t *aggr, haddr_t eoa, - haddr_t end) -{ - htri_t ret_value = FALSE; - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_aggr_can_extend) + /* Check for overflow when extending */ + if(H5F_addr_overflow(eoa, size) || (eoa + size) > file->maxaddr) + HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed") - /* Check args */ - HDassert(file); - HDassert(aggr); - HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA); + /* Set the [possibly aligned] address to return */ + ret_value = eoa + extra; - /* Check if this aggregator is active */ - if(file->feature_flags & aggr->feature_flag) { - /* If the aggregator block is at the end of the file, and the block to - * test adjoins the beginning of the aggregator block, then it's - * extendable - */ - if((aggr->addr + aggr->size) == eoa && end == aggr->addr) - HGOTO_DONE(TRUE) - } /* end if */ + /* Extend the end-of-allocated space address */ + eoa += size; + if(file->cls->set_eoa(file, type, eoa) < 0) + HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed") done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_aggr_can_extend() */ - - -/*------------------------------------------------------------------------- - * Function: H5FD_aggr_extend - * - * Purpose: Shift an aggregator block in the file - * - * Return: Success: Non-negative - * Failure: Negative - * - * Programmer: Quincey Koziol - * Thursday, December 13, 2007 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5FD_aggr_shift(H5FD_blk_aggr_t *aggr, hsize_t extra) -{ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_aggr_shift) - - /* Check args */ - HDassert(aggr); - HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA); - - /* Shift the aggregator block by the extra amount */ - aggr->addr += extra; - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5FD_aggr_shift() */ - - -/*------------------------------------------------------------------------- - * Function: H5FD_aggr_query - * - * Purpose: Query a block aggregator's current address & size info - * - * Return: Success: Non-negative - * Failure: Negative - * - * Programmer: Quincey Koziol - * Thursday, December 13, 2007 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5FD_aggr_query(const H5FD_t *file, const H5FD_blk_aggr_t *aggr, haddr_t *addr, - hsize_t *size) -{ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_aggr_query) - - /* Check args */ - HDassert(file); - HDassert(aggr); - HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA); - - /* Check if this aggregator is active */ - if(file->feature_flags & aggr->feature_flag) { - *addr = aggr->addr; - *size = aggr->size; - } /* end if */ - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5FD_aggr_query() */ +} /* end H5FD_extend() */ /*------------------------------------------------------------------------- - * Function: H5FD_aggr_reset - * - * Purpose: Reset a block aggregator, returning any space back to file - * - * Return: Success: Non-negative - * Failure: Negative - * - * Programmer: Quincey Koziol - * Thursday, December 13, 2007 + * Function: H5FD_alloc * - *------------------------------------------------------------------------- - */ -herr_t -H5FD_aggr_reset(H5FD_t *file, H5FD_blk_aggr_t *aggr, hid_t dxpl_id) -{ - H5FD_mem_t alloc_type; /* Type of file memory to work with */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5FD_aggr_reset, FAIL) - - /* Check args */ - HDassert(file); - HDassert(aggr); - HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA); - - /* Set the type of memory in the file */ - alloc_type = (aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA ? H5FD_MEM_DEFAULT : H5FD_MEM_DRAW); /* Type of file memory to work with */ - - /* Check if this aggregator is active */ - if(file->feature_flags & aggr->feature_flag) { - /* Return the unused portion of the metadata block to a free list */ - if(aggr->size > 0) - if(H5FD_free(file, alloc_type, dxpl_id, aggr->addr, aggr->size) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "can't free aggregator block") - - /* Reset aggregator block information */ - aggr->tot_size = 0; - aggr->addr = 0; - aggr->size = 0; - } /* end if */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_aggr_reset() */ - - -/*------------------------------------------------------------------------- - * Function: H5FD_real_alloc + * Purpose: Private version of H5FDalloc(). * - * Purpose: Double private version of H5FDalloc() :-) + * Return: Success: The format address of the new file memory. + * Failure: The undefined address HADDR_UNDEF * - * Return: Success: The format address of the new file memory. - * Failure: The undefined address HADDR_UNDEF + * Programmer: Robb Matzke + * Wednesday, August 4, 1999 * - * Programmer: Quincey Koziol - * Friday, August 25, 2000 + * Modification: + * Vailin Choi, 29th July 2008 + * Add two more parameters () for handling alignment: address & size of the fragment * *------------------------------------------------------------------------- */ -static haddr_t -H5FD_real_alloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size) +haddr_t +H5FD_alloc(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, hsize_t size, haddr_t *frag_addr, hsize_t *frag_size) { - haddr_t ret_value = HADDR_UNDEF; + haddr_t ret_value = HADDR_UNDEF; - FUNC_ENTER_NOAPI_NOINIT(H5FD_real_alloc) + FUNC_ENTER_NOAPI(H5FD_alloc, HADDR_UNDEF) #ifdef H5FD_ALLOC_DEBUG HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size); #endif /* H5FD_ALLOC_DEBUG */ /* check args */ - assert(file); - assert(file->cls); - assert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); - assert(size > 0); + HDassert(file); + HDassert(file->cls); + HDassert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); + HDassert(size > 0); - /* - * Dispatch to driver `alloc' callback or extend the end-of-address - * marker - */ + /* Dispatch to driver `alloc' callback or extend the end-of-address marker */ if(file->cls->alloc) { if((ret_value = (file->cls->alloc)(file, type, dxpl_id, size)) == HADDR_UNDEF) HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "driver allocation request failed") - } else { - if((ret_value = H5FD_update_eoa(file, type, dxpl_id, size)) == HADDR_UNDEF) + } /* end if */ + else { + if((ret_value = H5FD_extend(file, type, TRUE, size, frag_addr, frag_size)) == HADDR_UNDEF) HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "driver eoa update request failed") - } + } /* end else */ + + /* Convert absolute file offset to relative address */ + ret_value -= file->base_addr; done: #ifdef H5FD_ALLOC_DEBUG HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value); #endif /* H5FD_ALLOC_DEBUG */ FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_real_alloc() */ - - -/*------------------------------------------------------------------------- - * Function: H5FD_update_eoa - * - * Purpose: Update the EOA field of the file's memory. - * - * This was split off from the H5FD_real_alloc function to - * make life easier for all. - * - * Return: Success: The format address of the new file memory. - * Failure: The undefined address HADDR_UNDEF - * - * Programmer: Bill Wendling - * Wednesday, 04. December, 2002 - * - *------------------------------------------------------------------------- - */ -static haddr_t -H5FD_update_eoa(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size) -{ - haddr_t eoa, oldeoa = 0; - hsize_t wasted; - haddr_t ret_value = HADDR_UNDEF; - - FUNC_ENTER_NOAPI_NOINIT(H5FD_update_eoa) - - /* check args */ - assert(file); - assert(file->cls); - assert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); - assert(size > 0); - - eoa = file->cls->get_eoa(file, type); - -#ifdef H5F_DEBUG - if(file->alignment * file->threshold != 1 && H5DEBUG(F)) - HDfprintf(H5DEBUG(F), - "%s: alignment=%Hd, threshold=%Hd, size=%Hd, Begin eoa=%a\n", - FUNC, file->alignment, file->threshold, size, eoa); -#endif /* H5F_DEBUG */ - - /* Wasted is 0 if not exceeding threshold or eoa happens to be aligned */ - wasted = (size >= file->threshold) ? (eoa % file->alignment) : 0; - if(wasted) { - wasted = file->alignment - wasted; /* actual waste */ - oldeoa = eoa; /* save it for later freeing */ - - /* Advance eoa to the next alignment by allocating the wasted */ - if(H5F_addr_overflow(eoa, size) || (eoa + wasted) > file->maxaddr) - HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed") - - eoa += wasted; - - if(file->cls->set_eoa(file, type, eoa) < 0) - HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed") - } /* end if */ - - /* allocate the aligned memory */ - if(H5F_addr_overflow(eoa, size) || eoa + size > file->maxaddr) - HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed") - - ret_value = eoa; - eoa += size; - - if(file->cls->set_eoa(file, type, eoa) < 0) - HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed") - - /* Free the wasted memory */ - if(wasted) { - if(H5FD_free(file, type, dxpl_id, oldeoa, wasted) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "file deallocation request failed") - } /* end if */ - -#ifdef H5F_DEBUG - if(file->alignment * file->threshold != 1 && H5DEBUG(F)) - HDfprintf(H5DEBUG(F), - "%s: ret_value=%a, wasted=%Hd, Ended eoa=%a\n", - FUNC, ret_value, wasted, eoa); -#endif /* H5F_DEBUG */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_update_eoa() */ +} /* end H5FD_alloc() */ /*------------------------------------------------------------------------- @@ -1101,9 +247,8 @@ done: *------------------------------------------------------------------------- */ herr_t -H5FD_free(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t size) +H5FD_free(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr, hsize_t size) { - H5FD_mem_t mapped_type; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5FD_free, FAIL) @@ -1112,235 +257,50 @@ H5FD_free(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t si HDassert(file); HDassert(file->cls); HDassert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); + HDassert(size > 0); #ifdef H5FD_ALLOC_DEBUG HDfprintf(stderr, "%s: type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)type, addr, size); #endif /* H5FD_ALLOC_DEBUG */ - if(!H5F_addr_defined(addr) || addr > file->maxaddr || - H5F_addr_overflow(addr, size) || (addr + size) > file->maxaddr) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid region") - - /* Allow 0-sized free's to occur without penalty */ - if(0 == size) - HGOTO_DONE(SUCCEED) - - /* Map request type to free list */ - if(H5FD_MEM_DEFAULT==file->cls->fl_map[type]) - mapped_type = type; - else - mapped_type = file->cls->fl_map[type]; -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: mapped_type = %u\n", FUNC, (unsigned)mapped_type); -#endif /* H5FD_ALLOC_DEBUG */ - - /* - * If the request maps to a free list then add memory to the free list - * without ever telling the driver that it was freed. Otherwise let the - * driver deallocate the memory. - */ - if(mapped_type >= H5FD_MEM_DEFAULT) { - H5FD_free_t *last; /* Last merged node */ - H5FD_free_t *last_prev = NULL;/* Pointer to node before merged node */ - H5FD_free_t *curr; /* Current free block being inspected */ - H5FD_free_t *prev; /* Previous free block being inspected */ - - /* Adjust the metadata accumulator to remove the freed block, if it overlaps */ - if((file->feature_flags&H5FD_FEAT_ACCUMULATE_METADATA) - && H5F_addr_overlap(addr, size, file->accum_loc, file->accum_size)) { - size_t overlap_size; /* Size of overlap with accumulator */ - - /* Check for overlapping the beginning of the accumulator */ - if(H5F_addr_le(addr, file->accum_loc)) { - /* Check for completely overlapping the accumulator */ - if(H5F_addr_ge(addr + size, file->accum_loc + file->accum_size)) { - /* Reset the entire accumulator */ - file->accum_loc=HADDR_UNDEF; - file->accum_size=FALSE; - file->accum_dirty=FALSE; - } /* end if */ - /* Block to free must end within the accumulator */ - else { - size_t new_accum_size; /* Size of new accumulator buffer */ - - /* Calculate the size of the overlap with the accumulator, etc. */ - H5_ASSIGN_OVERFLOW(overlap_size,(addr+size)-file->accum_loc,haddr_t,size_t); - new_accum_size=file->accum_size-overlap_size; - - /* Move the accumulator buffer information to eliminate the freed block */ - HDmemmove(file->meta_accum,file->meta_accum+overlap_size,new_accum_size); - - /* Adjust the accumulator information */ - file->accum_loc+=overlap_size; - file->accum_size=new_accum_size; - } /* end else */ - } /* end if */ - /* Block to free must start within the accumulator */ - else { - /* Calculate the size of the overlap with the accumulator */ - H5_ASSIGN_OVERFLOW(overlap_size,(file->accum_loc+file->accum_size)-addr,haddr_t,size_t); - - /* Block to free is in the middle of the accumulator */ - if(H5F_addr_lt((addr + size), file->accum_loc + file->accum_size)) { - haddr_t tail_addr; - size_t tail_size; - - /* Calculate the address & size of the tail to write */ - tail_addr=addr+size; - H5_ASSIGN_OVERFLOW(tail_size,(file->accum_loc+file->accum_size)-tail_addr,haddr_t,size_t); - - /* Write out the part of the accumulator after the block to free */ - /* (Use the driver's write call directly - to avoid looping back and writing to metadata accumulator) */ - if((file->cls->write)(file, H5FD_MEM_DEFAULT, dxpl_id, tail_addr, tail_size, file->meta_accum+(tail_addr-file->accum_loc)) < 0) - HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "file write request failed") - } /* end if */ - - /* Adjust the accumulator information */ - file->accum_size=file->accum_size-overlap_size; - } /* end else */ - } /* end if */ - - /* Scan through the existing blocks for the mapped type to see if we can extend one */ - curr = file->fl[mapped_type]; - last = prev = NULL; - while(curr != NULL) { - /* Check if the block to free adjoins the start of the current block */ - if((addr + size) == curr->addr) { - /* If we previously found & merged a node, eliminate it from the list & free it */ - if(last != NULL) { - /* Check if there was a previous block in the list */ - if(last_prev != NULL) - /* Eliminate the merged block from the list */ - last_prev->next = last->next; - /* No previous block, this must be the head of the list */ - else - /* Eliminate the merged block from the list */ - file->fl[mapped_type] = last->next; - - /* Check for eliminating the block before the 'current' one */ - if(last == prev) - prev = last_prev; - - /* Free the memory for the merged block */ - (void)H5FL_FREE(H5FD_free_t, last); - } /* end if */ - - /* Adjust the address and size of the block found */ - curr->addr = addr; - curr->size += size; - - /* Adjust the information about to memory block to include the merged block */ - addr = curr->addr; - size = curr->size; + /* Sanity checking */ + if(!H5F_addr_defined(addr)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file offset") - /* Update the information about the merged node */ - last = curr; - last_prev = prev; - } /* end if */ - else { - /* Check if the block to free adjoins the end of the current block */ - if((curr->addr + curr->size) == addr) { - /* If we previously found & merged a node, eliminate it from the list & free it */ - if(last != NULL) { - /* Check if there was a previous block in the list */ - if(last_prev != NULL) - /* Eliminate the merged block from the list */ - last_prev->next = last->next; - /* No previous block, this must be the head of the list */ - else - /* Eliminate the merged block from the list */ - file->fl[mapped_type] = last->next; + /* Convert address to absolute file offset */ + addr += file->base_addr; - /* Check for eliminating the block before the 'current' one */ - if(last == prev) - prev = last_prev; + /* More sanity checking */ + if(addr > file->maxaddr || H5F_addr_overflow(addr, size) || (addr + size) > file->maxaddr) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file free space region to free") - /* Free the memory for the merged block */ - (void)H5FL_FREE(H5FD_free_t, last); - } /* end if */ - - /* Adjust the size of the block found */ - curr->size += size; - - /* Adjust the information about to memory block to include the merged block */ - addr = curr->addr; - size = curr->size; - - /* Update the information about the merged node */ - last = curr; - last_prev = prev; - } /* end if */ - } /* end else */ - - /* Advance to next node in list */ - prev = curr; - curr = curr->next; - } /* end while */ - - /* Check if we adjusted an existing block */ - if(last != NULL) { - /* Move the node found to the front, if it wasn't already there */ - if(last_prev != NULL) { - last_prev->next = last->next; - last->next = file->fl[mapped_type]; - file->fl[mapped_type] = last; - } /* end if */ - } /* end if */ - else { - /* Allocate a new node to hold the free block's information */ - if(NULL == (last = H5FL_MALLOC(H5FD_free_t))) - HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate node for free space info") - - last->addr = addr; - last->size = size; - last->next = file->fl[mapped_type]; - file->fl[mapped_type] = last; - } /* end else */ + /* Check for file driver 'free' callback and call it if available */ + if(file->cls->free) { #ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: mapped_type = %u, last = {%a, %Hu}\n", FUNC, (unsigned)mapped_type, last->addr, last->size); +HDfprintf(stderr, "%s: Letting VFD free space\n", FUNC); #endif /* H5FD_ALLOC_DEBUG */ + if((file->cls->free)(file, type, dxpl_id, addr, size) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "driver free request failed") + } /* end if */ + /* Check if this free block is at the end of file allocated space. + * Truncate it if this is true. + */ + else if(file->cls->get_eoa) { + haddr_t eoa; - /* Check if we increased the size of the largest block on the list */ - file->maxsize = MAX(file->maxsize, last->size); - - /* Check if this free block adjoins the "metadata aggregator" */ - if(H5FD_aggr_adjoin(file, &(file->meta_aggr), last) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "aggregator deallocation request failed") - - /* Check if this free block adjoins the "small data aggregator" */ - if(H5FD_aggr_adjoin(file, &(file->sdata_aggr), last) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "aggregator deallocation request failed") - - /* Check if this free block is at the end of file allocated space. - * Truncate it if this is true. */ - if(file->cls->get_eoa) { - haddr_t eoa; - - eoa = file->cls->get_eoa(file, type); + eoa = file->cls->get_eoa(file, type); #ifdef H5FD_ALLOC_DEBUG HDfprintf(stderr, "%s: eoa = %a\n", FUNC, eoa); #endif /* H5FD_ALLOC_DEBUG */ - if(eoa == (last->addr + last->size)) { + if(eoa == (addr + size)) { #ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: Reducing file size to = %a\n", FUNC, last->addr); +HDfprintf(stderr, "%s: Reducing file size to = %a\n", FUNC, addr); #endif /* H5FD_ALLOC_DEBUG */ - if(file->cls->set_eoa(file, type, last->addr) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "set end of space allocation request failed") - - /* Remove this free block from the list */ - file->fl[mapped_type] = last->next; - if(file->maxsize == last->size) - file->maxsize = 0; /*unknown*/ - (void)H5FL_FREE(H5FD_free_t, last); - } /* end if */ + if(file->cls->set_eoa(file, type, addr) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "set end of space allocation request failed") } /* end if */ - } else if(file->cls->free) { -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: Letting VFD free space\n", FUNC); -#endif /* H5FD_ALLOC_DEBUG */ - if((file->cls->free)(file, type, dxpl_id, addr, size) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver free request failed") - } else { + } /* end else-if */ + else { /* leak memory */ #ifdef H5FD_ALLOC_DEBUG HDfprintf(stderr, "%s: LEAKED MEMORY!!! type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)type, addr, size); @@ -1353,386 +313,55 @@ done: /*------------------------------------------------------------------------- - * Function: H5FD_realloc - * - * Purpose: Private version of H5FDrealloc() - * - * Return: Success: New address of the block of memory, not - * necessarily the same as the original address. - * Failure: HADDR_UNDEF - * - * Programmer: Robb Matzke - * Wednesday, August 4, 1999 - * - *------------------------------------------------------------------------- - */ -haddr_t -H5FD_realloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t old_addr, hsize_t old_size, - hsize_t new_size) -{ - haddr_t new_addr=old_addr; - uint8_t _buf[8192]; - uint8_t *buf=_buf; - haddr_t ret_value; /* Return value */ - - FUNC_ENTER_NOAPI(H5FD_realloc, HADDR_UNDEF) - - if(new_size == old_size) { - /*nothing to do*/ - } else if(0 == old_size) { - /* allocate memory */ - HDassert(!H5F_addr_defined(old_addr)); - if(HADDR_UNDEF == (new_addr = H5FD_alloc(file, type, dxpl_id, new_size))) - HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, HADDR_UNDEF, "file allocation failed") - } else if(0==new_size) { - /* free memory */ - HDassert(H5F_addr_defined(old_addr)); - if(H5FD_free(file, type, dxpl_id, old_addr, old_size) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "file deallocation request failed") - new_addr = HADDR_UNDEF; - } else if(new_size<old_size) { - /* free the end of the block */ - if(H5FD_free(file, type, dxpl_id, old_addr+old_size, old_size-new_size) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "file deallocation request failed") - } else { - /* move memory to new location */ - /* Note! This may fail if sizeof(hsize_t)>sizeof(size_t) and the - * object on disk is too large to read into a memory buffer all at one - * time. This chunk of code would have to be re-written using a loop - * to move pieces of the realloced data through a fixed size buffer, etc. - * -QAK, 6/20/01 - */ - if(HADDR_UNDEF == (new_addr = H5FD_alloc(file, type, dxpl_id, new_size))) - HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, HADDR_UNDEF, "file allocation failed") - H5_CHECK_OVERFLOW(old_size,hsize_t,size_t); - if(old_size > sizeof(_buf) && NULL == (buf = (uint8_t *)H5MM_malloc((size_t)old_size))) { - (void)H5FD_free(file, type, dxpl_id, new_addr, new_size); - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, "memory allocation failed") - } /* end if */ - if(H5FD_read(file, type, dxpl_id, old_addr, (size_t)old_size, buf) < 0 || - H5FD_write(file, type, dxpl_id, new_addr, (size_t)old_size, buf) < 0) { - (void)H5FD_free(file, type, dxpl_id, new_addr, new_size); - if(buf != _buf) - H5MM_xfree(buf); - HGOTO_ERROR(H5E_FILE, H5E_READERROR, HADDR_UNDEF, "unable to move file block") - } /* end if */ - - if(buf != _buf) - H5MM_xfree(buf); - if(H5FD_free(file, type, dxpl_id, old_addr, old_size) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "file deallocation request failed") - } /* end else */ - - /* Set return value */ - ret_value = new_addr; - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_realloc() */ - - -/*------------------------------------------------------------------------- - * Function: H5FD_can_extend + * Function: H5FD_try_extend * - * Purpose: Check if a block in the file can be extended. + * Purpose: Extend a block at the end of the file, if possible. * - * Return: Success: TRUE(1)/FALSE(0) + * Return: Success: TRUE(1) - Block was extended + * FALSE(0) - Block could not be extended * Failure: FAIL * - * Programmer: Quincey Koziol - * Friday, June 11, 2004 - * - *------------------------------------------------------------------------- - */ -htri_t -H5FD_can_extend(const H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size, hsize_t extra_requested) -{ - haddr_t end; /* End of block in file */ - haddr_t eoa; /* End of address space in the file */ - htri_t ret_value = FALSE; /* Return value */ - - FUNC_ENTER_NOAPI(H5FD_can_extend, FAIL) - - /* Retrieve the end of the address space */ - if(HADDR_UNDEF == (eoa = H5FD_get_eoa(file, type))) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver get_eoa request failed") - - /* Compute end of block */ - end = addr + size; - - /* Check if the block is exactly at the end of the file */ - if(end == eoa) - HGOTO_DONE(TRUE) - else { - H5FD_free_t *curr; /* Current free block being inspected */ - H5FD_mem_t mapped_type; /* Memory type, after mapping */ - - /* Map request type to free list */ - if(H5FD_MEM_DEFAULT==file->cls->fl_map[type]) - mapped_type = type; - else - mapped_type = file->cls->fl_map[type]; - - /* Check if block is inside the metadata or small data aggregator */ - if(mapped_type!=H5FD_MEM_DRAW) { - /* Check for test block able to extend metadata aggregation block */ - if((ret_value = H5FD_aggr_can_extend(file, &(file->meta_aggr), eoa, end)) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "can't determine if metadata aggregation block can be extended") - else if(ret_value > 0) - HGOTO_DONE(TRUE) - } /* end if */ - else { - /* Check for test block able to extend metadata aggregation block */ - if((ret_value = H5FD_aggr_can_extend(file, &(file->sdata_aggr), eoa, end)) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "can't determine if 'small data' aggregation block can be extended") - else if(ret_value > 0) - HGOTO_DONE(TRUE) - } /* end else */ - - /* Scan through the existing blocks for the mapped type to see if we can extend one */ - if(mapped_type >= H5FD_MEM_DEFAULT) { - curr = file->fl[mapped_type]; - while(curr != NULL) { - if(end == curr->addr) { - if(extra_requested <= curr->size) - HGOTO_DONE(TRUE) - else - HGOTO_DONE(FALSE) - } /* end if */ - - /* Advance to next node in list */ - curr=curr->next; - } /* end while */ - } /* end if */ - } /* end else */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_can_extend() */ - - -/*------------------------------------------------------------------------- - * Function: H5FD_extend - * - * Purpose: Extend a block in the file. - * - * Return: Success: Non-negative - * Failure: Negative - * - * Programmer: Quincey Koziol - * Saturday, June 12, 2004 - * - *------------------------------------------------------------------------- - */ -herr_t -H5FD_extend(H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size, hsize_t extra_requested) -{ - haddr_t eoa; /* End of address space in the file */ - haddr_t end; /* End of block in file */ - hbool_t update_eoma=FALSE; /* Whether we need to update the eoma */ - hbool_t update_eosda=FALSE; /* Whether we need to update the eosda */ - hbool_t at_end=FALSE; /* Block is at end of file */ - H5FD_mem_t mapped_type; /* Memory type, after mapping */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5FD_extend, FAIL) -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: type = %u, addr = %a, size = %Hu, extra_requested = %Hu\n", FUNC, (unsigned)type, addr, size, extra_requested); -#endif /* H5FD_ALLOC_DEBUG */ - - /* Retrieve the end of the address space */ - if(HADDR_UNDEF==(eoa=H5FD_get_eoa(file, type))) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver get_eoa request failed") - - /* Map request type to free list */ - if(H5FD_MEM_DEFAULT==file->cls->fl_map[type]) - mapped_type = type; - else - mapped_type = file->cls->fl_map[type]; - - /* Compute end of block */ - end = addr + size; - - /* Check if the block is exactly at the end of the file */ - if(end == eoa) - at_end = TRUE; - else { - /* (Check if block is inside the metadata or small data accumulator) */ - if(mapped_type!=H5FD_MEM_DRAW) { - /* Check for test block able to extend metadata aggregation block */ - if((ret_value = H5FD_aggr_can_extend(file, &(file->meta_aggr), eoa, end)) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "can't determine if metadata aggregation block can be extended") - else if(ret_value > 0) - update_eoma = TRUE; - } /* end if */ - else { - /* Check for test block able to extend metadata aggregation block */ - if((ret_value = H5FD_aggr_can_extend(file, &(file->sdata_aggr), eoa, end)) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "can't determine if metadata aggregation block can be extended") - else if(ret_value > 0) - update_eosda = TRUE; - } /* end else */ - } /* end else */ - - /* Block is at end of file, we are extending the eoma or eosda */ - if(update_eoma || update_eosda || at_end) { - /* Check for overflowing the file */ - if(H5F_addr_overflow(eoa, extra_requested) || eoa + extra_requested > file->maxaddr) - HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, FAIL, "file allocation request failed") - - /* Extend the file */ - eoa += extra_requested; - if(file->cls->set_eoa(file, type, eoa) < 0) - HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, FAIL, "file allocation request failed") - - /* Update the metadata and/or small data block */ - HDassert(!(update_eoma && update_eosda)); - if(update_eoma) - H5FD_aggr_shift(&(file->meta_aggr), extra_requested); - if(update_eosda) - H5FD_aggr_shift(&(file->sdata_aggr), extra_requested); - } /* end if */ - /* If the block we are extending isn't at the end of the file, find a free block to extend into */ - else { - H5FD_free_t *curr; /* Current free block being inspected */ - H5FD_free_t *prev; /* Current free block being inspected */ - - /* Walk through free list, looking for block to merge with */ - curr = file->fl[mapped_type]; - prev = NULL; - while(curr!=NULL) { - /* Found block that ajoins end of block to extend */ - if(end == curr->addr) { - /* Check if free space is large enough */ - if(extra_requested <= curr->size) { - /* Check for exact match */ - if(extra_requested == curr->size) { - /* Unlink node from free list */ - if(prev == NULL) - file->fl[mapped_type] = curr->next; - else - prev->next = curr->next; - - /* Free the memory for the used block */ - (void)H5FL_FREE(H5FD_free_t, curr); - } /* end if */ - else { - curr->addr += extra_requested; - curr->size -= extra_requested; - } /* end else */ - - /* Leave now */ - break; - } /* end if */ - else - HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, FAIL, "can't extend block") - } /* end if */ - - /* Advance to next node in list */ - prev = curr; - curr = curr->next; - } /* end while */ - - /* Couldn't find block to extend */ - if(curr == NULL) - HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, FAIL, "can't extend block") - } /* end else */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_extend() */ - - -/*------------------------------------------------------------------------- - * Function: H5FD_get_freespace - * - * Purpose: Retrieve the amount of free space in a file. - * - * Return: Success: Amount of free space in file - * Failure: Negative - * * Programmer: Quincey Koziol - * Monday, October 6, 2003 + * Thursday, 17. January, 2008 * - * Note: - * Raymond Lu - * 5 January 2007 - * Due to the complexity EOA for Multi driver, this function - * is made failed for now. + * Modification: + * Vailin Choi, 29th July 2008 + * Two more parameters were added to FD_extend() for handling alignment * *------------------------------------------------------------------------- */ -hssize_t -H5FD_get_freespace(const H5FD_t *file) +htri_t +H5FD_try_extend(H5FD_t *file, H5FD_mem_t type, haddr_t blk_end, hsize_t extra_requested) { - H5FD_free_t *free_node; /* Pointer to node on free list */ - H5FD_mem_t type; /* Type of memory */ - haddr_t ma_addr = HADDR_UNDEF; /* Base "metadata aggregator" address */ - hsize_t ma_size = 0; /* Size of "metadata aggregator" */ - haddr_t sda_addr = HADDR_UNDEF; /* Base "small data aggregator" address */ - hsize_t sda_size = 0; /* Size of "small data aggregator" */ - haddr_t eoa = 0; /* End of allocated space in the file */ - hssize_t ret_value = 0; /* Return value */ + haddr_t eoa; /* End of allocated space in file */ + htri_t ret_value = FALSE; /* Return value */ - FUNC_ENTER_NOAPI(H5FD_get_freespace, FAIL) + FUNC_ENTER_NOAPI(H5FD_try_extend, FAIL) /* check args */ HDassert(file); HDassert(file->cls); + HDassert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); + HDassert(extra_requested > 0); - /* Multi driver doesn't support this function because of the complexity. - * It doesn't have eoa for the whole file. */ - if(file->driver_id == H5FD_MULTI) - HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "Multi driver doesn't support this function") - - /* Retrieve the 'eoa' for the file */ - eoa = file->cls->get_eoa(file, H5FD_MEM_DEFAULT); - - /* Retrieve metadata aggregator info, if available */ - H5FD_aggr_query(file, &(file->meta_aggr), &ma_addr, &ma_size); - - /* Retrieve 'small data' aggregator info, if available */ - H5FD_aggr_query(file, &(file->sdata_aggr), &sda_addr, &sda_size); + /* Retrieve the end of the address space */ + if(HADDR_UNDEF == (eoa = file->cls->get_eoa(file, type))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed") - /* Iterate over all the types of memory, to retrieve amount of free space for each */ - for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t,type)) { - /* Iterate through the free list, accumulating the amount of free space for this type */ - free_node = file->fl[type]; - while(free_node) { - /* Check for current node adjoining the metadata & small data aggregators */ - if(H5F_addr_eq(free_node->addr + free_node->size, ma_addr)) { - ma_addr -= free_node->size; - ma_size += free_node->size; - } else if(H5F_addr_eq(free_node->addr + free_node->size, sda_addr)) { - sda_addr -= free_node->size; - sda_size += free_node->size; - } else if(H5F_addr_eq(ma_addr + ma_size, free_node->addr)) - ma_size += free_node->size; - else if(H5F_addr_eq(sda_addr + sda_size, free_node->addr)) - sda_size += free_node->size; - else - ret_value += (hssize_t)free_node->size; - free_node = free_node->next; - } /* end while */ - } /* end for */ + /* Adjust block end by base address of the file, to create absolute address */ + blk_end += file->base_addr; - /* Check for aggregating metadata allocations */ - if(ma_size > 0) { - /* Add in the reserved space for metadata to the available free space */ - /* (if it's not at the tail of the file) */ - if(H5F_addr_ne(ma_addr + ma_size, eoa)) - ret_value += ma_size; - } /* end if */ + /* Check if the block is exactly at the end of the file */ + if(H5F_addr_eq(blk_end, eoa)) { + /* Extend the object by extending the underlying file */ + if(HADDR_UNDEF == H5FD_extend(file, type, FALSE, extra_requested, NULL, NULL)) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, "driver extend request failed") - /* Check for aggregating small data allocations */ - if(sda_size > 0) { - /* Add in the reserved space for metadata to the available free space */ - /* (if it's not at the tail of the file) */ - if(H5F_addr_ne(sda_addr + sda_size, eoa)) - ret_value += sda_size; + /* Indicate success */ + HGOTO_DONE(TRUE) } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_get_freespace() */ +} /* end H5FD_try_extend() */ |