summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2008-01-03 18:24:01 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2008-01-03 18:24:01 (GMT)
commit04d73e7a0c69839922cf78adcb04e2617fc0f5b9 (patch)
treee5fa979c46410c6b81cb5709d47381672becdd3e
parent35694d44ae9aedaeed71850222ce014606ed3572 (diff)
downloadhdf5-04d73e7a0c69839922cf78adcb04e2617fc0f5b9.zip
hdf5-04d73e7a0c69839922cf78adcb04e2617fc0f5b9.tar.gz
hdf5-04d73e7a0c69839922cf78adcb04e2617fc0f5b9.tar.bz2
[svn-r14363] Description:
Refactor file space allocation routines into separate source module. Tested on: FreeBSD/32 6.2 (duty) in debug mode Mac OS X/32 10.4.10 (amazon) in debug mode
-rw-r--r--MANIFEST2
-rw-r--r--src/H5FD.c1724
-rw-r--r--src/H5FDpkg.h67
-rw-r--r--src/H5FDspace.c1738
-rwxr-xr-xsrc/Makefile.am2
-rw-r--r--src/Makefile.in5
6 files changed, 1879 insertions, 1659 deletions
diff --git a/MANIFEST b/MANIFEST
index 7473603..0706d36 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -503,10 +503,12 @@
./src/H5FDmpiposix.h
./src/H5FDmulti.c
./src/H5FDmulti.h
+./src/H5FDpkg.h
./src/H5FDprivate.h
./src/H5FDpublic.h
./src/H5FDsec2.c
./src/H5FDsec2.h
+./src/H5FDspace.c
./src/H5FDstdio.c
./src/H5FDstdio.h
./src/H5FDwindows.c
diff --git a/src/H5FD.c b/src/H5FD.c
index eec94fa..06398f0 100644
--- a/src/H5FD.c
+++ b/src/H5FD.c
@@ -24,18 +24,25 @@
* file driver layer.
*/
+/****************/
+/* Module Setup */
+/****************/
+
#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+#define H5FD_PACKAGE /*suppress error about including H5FDpkg */
/* Interface initialization */
#define H5_INTERFACE_INIT_FUNC H5FD_init_interface
-/* Packages needed by this file */
+/***********/
+/* Headers */
+/***********/
#include "H5private.h" /* Generic Functions */
#include "H5Dprivate.h" /* Datasets */
#include "H5Eprivate.h" /* Error handling */
#include "H5Fpkg.h" /* File access */
-#include "H5FDprivate.h" /* File drivers */
+#include "H5FDpkg.h" /* File Drivers */
#include "H5FDcore.h" /* Files stored entirely in memory */
#include "H5FDfamily.h" /* File families */
#include "H5FDlog.h" /* sec2 driver with I/O logging (for debugging) */
@@ -47,46 +54,50 @@
#include "H5FDwindows.h" /* Windows buffered I/O */
#endif
#include "H5FDdirect.h" /* Direct file I/O */
-#include "H5FLprivate.h" /* Free lists */
#include "H5Iprivate.h" /* IDs */
#include "H5MMprivate.h" /* Memory management */
#include "H5Pprivate.h" /* Property lists */
-/* static prototypes */
+/****************/
+/* Local Macros */
+/****************/
+
+/* Metadata accumulator controls */
+#define H5FD_ACCUM_THROTTLE 8
+#define H5FD_ACCUM_THRESHOLD 2048
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
static herr_t H5FD_pl_copy(void *(*copy_func)(const void *), size_t pl_size,
const void *old_pl, void **copied_pl);
static herr_t H5FD_pl_close(hid_t driver_id, herr_t (*free_func)(void *),
void *pl);
static herr_t H5FD_free_cls(H5FD_class_t *cls);
-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 herr_t H5FD_free_freelist(H5FD_t *file);
-static haddr_t H5FD_update_eoa(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size);
-
-/* 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_STATIC(meta_accum);
-
-/* Local macro definitions */
-#define H5FD_ACCUM_THROTTLE 8
-#define H5FD_ACCUM_THRESHOLD 2048
-/* Define this to display information about file allocations */
-/* #define H5FD_ALLOC_DEBUG */
+/*********************/
+/* Package Variables */
+/*********************/
+
-/* Static local variables */
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
/*
* Global count of the number of H5FD_t's handed out. This is used as a
@@ -104,6 +115,32 @@ static unsigned long file_serial_no;
/*-------------------------------------------------------------------------
+ * Function: H5FD_init
+ *
+ * Purpose: Initialize the interface from some other package.
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, January 3, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_init(void)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FD_init, FAIL)
+ /* FUNC_ENTER() does all the work */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_init() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5FD_init_interface
*
* Purpose: Initialize the virtual file layer.
@@ -1189,73 +1226,6 @@ done:
/*-------------------------------------------------------------------------
- * 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
- * Modifications:
- *-------------------------------------------------------------------------
- */
-static 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;
- 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: H5FDcmp
*
* Purpose: Compare the keys of two files using the file driver callback
@@ -1487,905 +1457,6 @@ done:
/*-------------------------------------------------------------------------
- * 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
- * Modifications:
- * Albert Cheng, 2001/05/01
- * Implement the allocation by alignment/threshold.
- *
- * Bill Wendling, 2002/12/02
- * Split apart into subfunctions for each separate task.
- *
- * Bill Wendling, 2003/02/19
- * Added support for FPHDF5.
- *
- * John Mainzer, 2004/04/13
- * Moved much of the FPHDF5 specific code into H5FP_client_alloc(),
- * and re-worked it to get rid of a race condition on the eoa.
- *
- *-------------------------------------------------------------------------
- */
-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
- * Purpose: Try to allocate SIZE bytes of memory from the free list
- * if possible.
- *
- * This is split from H5FD_alloc().
- * Return: Success: The format address of the new file memory.
- * Failure: The undefined address HADDR_UNDEF
- * Programmer: Bill Wendling
- * 02. December, 2002
- * Modifications:
- *-------------------------------------------------------------------------
- */
-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;
-
- 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;
-
- 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 */
- 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
- * Programmer: Bill Wendling
- * 2. December, 2002
- *
- *-------------------------------------------------------------------------
- */
-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)
-{
- 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 */
-
- /* 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(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;
-
- /* 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 */
- } /* end if */
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5FD_aggr_adjoin() */
-
-
-/*-------------------------------------------------------------------------
- * 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 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) {
- /* 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 */
-
-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() */
-
-
-/*-------------------------------------------------------------------------
- * 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
- *
- *-------------------------------------------------------------------------
- */
-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: Double private version of H5FDalloc() :-)
- *
- * Return: Success: The format address of the new file memory.
- *
- * Failure: The undefined address HADDR_UNDEF
- *
- * Programmer: Quincey Koziol
- * Friday, August 25, 2000
- *
- * Modifications:
- * Albert Cheng, 2001/05/01
- * Implement the allocation by alignment/threshold.
- *
- *-------------------------------------------------------------------------
- */
-static haddr_t
-H5FD_real_alloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size)
-{
- haddr_t ret_value = HADDR_UNDEF;
-
- FUNC_ENTER_NOAPI_NOINIT(H5FD_real_alloc)
-#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);
-
- /*
- * 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)
- HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "driver eoa update request failed")
- }
-
-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
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-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() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5FDfree
*
* Purpose: Frees format addresses starting with ADDR and continuing for
@@ -2435,271 +1506,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5FD_free
- *
- * Purpose: Private version of H5FDfree()
- *
- * Return: Success: Non-negative
- * Failure: Negative
- *
- * Programmer: Robb Matzke
- * Wednesday, August 4, 1999
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5FD_free(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t size)
-{
- H5FD_mem_t mapped_type;
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5FD_free, FAIL)
-
- /* Check args */
- HDassert(file);
- HDassert(file->cls);
- HDassert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES);
-
-#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 */
- 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;
-
- /* 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;
-
- /* Check for eliminating the block before the 'current' one */
- if(last == prev)
- prev = last_prev;
-
- /* Free the memory for the merged block */
- 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 */
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: mapped_type = %u, last = {%a, %Hu}\n", FUNC, (unsigned)mapped_type, last->addr, last->size);
-#endif /* H5FD_ALLOC_DEBUG */
-
- /* 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);
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: eoa = %a\n", FUNC, eoa);
-#endif /* H5FD_ALLOC_DEBUG */
- if(eoa == (last->addr + last->size)) {
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: Reducing file size to = %a\n", FUNC, last->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*/
- H5FL_FREE(H5FD_free_t, last);
- } /* end if */
- } /* 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 {
- /* leak memory */
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: LEAKED MEMORY!!! type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)type, addr, size);
-#endif /* H5FD_ALLOC_DEBUG */
- } /* end else */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_free() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5FDrealloc
*
* Purpose: Changes the size of an allocated chunk of memory, possibly
@@ -2742,306 +1548,6 @@ 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
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-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 = 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
- *
- * Purpose: Check if a block in the file can be extended.
- *
- * Return: Success: TRUE(1)/FALSE(0)
- *
- * Failure: FAIL
- *
- * Programmer: Quincey Koziol
- * Friday, June 11, 2004
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-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
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-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 */
- 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: H5FDget_eoa
*
* Purpose: Returns the address of the first byte after the last
@@ -4027,97 +2533,3 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD_get_vfd_handle() */
-
-/*-------------------------------------------------------------------------
- * 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
- *
- * Modifications:
- * Raymond Lu
- * 5 January 2007
- * Due to the complexity EOA for Multi driver, this function
- * is made failed for now.
- *
- *-------------------------------------------------------------------------
- */
-hssize_t
-H5FD_get_freespace(const H5FD_t *file)
-{
- 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 */
-
- FUNC_ENTER_NOAPI(H5FD_get_freespace, FAIL)
-
- /* check args */
- HDassert(file);
- HDassert(file->cls);
-
- /* 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);
-
- /* 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 */
-
- /* 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 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;
- } /* end if */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_get_freespace() */
-
diff --git a/src/H5FDpkg.h b/src/H5FDpkg.h
new file mode 100644
index 0000000..700ec1d
--- /dev/null
+++ b/src/H5FDpkg.h
@@ -0,0 +1,67 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Programmer: Quincey Koziol <koziol@hdfgroup.org>
+ * Thursday, January 3, 2008
+ *
+ * Purpose: This file contains declarations which are visible only within
+ * the H5FD package. Source files outside the H5FD package should
+ * include H5FDprivate.h instead.
+ */
+#ifndef H5FD_PACKAGE
+#error "Do not include this file outside the H5FD package!"
+#endif
+
+#ifndef _H5FDpkg_H
+#define _H5FDpkg_H
+
+/* Get package's private header */
+#include "H5FDprivate.h" /* File drivers */
+
+/* Other private headers needed by this file */
+#include "H5FLprivate.h" /* Free lists */
+
+/**************************/
+/* Package Private Macros */
+/**************************/
+
+
+/****************************/
+/* Package Private Typedefs */
+/****************************/
+
+
+/*****************************/
+/* Package Private Variables */
+/*****************************/
+
+/* Declare a PQ free list to manage the metadata accumulator buffer */
+H5FL_BLK_EXTERN(meta_accum);
+
+
+/******************************/
+/* Package Private Prototypes */
+/******************************/
+H5_DLL herr_t H5FD_init(void);
+H5_DLL herr_t H5FD_free_freelist(H5FD_t *file);
+
+
+/* Testing routines */
+#ifdef H5FD_TESTING
+#endif /* H5FD_TESTING */
+
+#endif /* _H5FDpkg_H */
+
diff --git a/src/H5FDspace.c b/src/H5FDspace.c
new file mode 100644
index 0000000..7bd72cc
--- /dev/null
+++ b/src/H5FDspace.c
@@ -0,0 +1,1738 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5FDspace.c
+ * Jan 3 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Space allocation routines for the file.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5FD_PACKAGE /*suppress error about including H5FDpkg */
+
+/* Interface initialization */
+#define H5_INTERFACE_INIT_FUNC H5FD_space_init_interface
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fprivate.h" /* File access */
+#include "H5FDpkg.h" /* File Drivers */
+#include "H5FDmulti.h" /* Usage-partitioned file family */
+#include "H5MMprivate.h" /* Memory management */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+/* Define this to display information about file allocations */
+/* #define H5FD_ALLOC_DEBUG */
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* 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);
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* 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);
+
+
+
+/*--------------------------------------------------------------------------
+NAME
+ H5FD_space_init_interface -- Initialize interface-specific information
+USAGE
+ herr_t H5FD_space_init_interface()
+
+RETURNS
+ Non-negative on success/Negative on failure
+DESCRIPTION
+ Initializes any interface-specific data or routines. (Just calls
+ H5FD_init_iterface currently).
+
+--------------------------------------------------------------------------*/
+static herr_t
+H5FD_space_init_interface(void)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_space_init_interface)
+
+ FUNC_LEAVE_NOAPI(H5FD_init())
+} /* H5FD_space_init_interface() */
+
+
+/*-------------------------------------------------------------------------
+ * 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;
+ 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
+ *
+ * Purpose: Try to allocate SIZE bytes of memory from the free list
+ * if possible.
+ *
+ * This is split from H5FD_alloc().
+ *
+ * Return: Success: The format address of the new file memory.
+ * 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;
+
+ 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;
+
+ 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 */
+ 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
+ *
+ * Programmer: Bill Wendling
+ * 2. December, 2002
+ *
+ *-------------------------------------------------------------------------
+ */
+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)
+{
+ 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 */
+
+ /* 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(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;
+
+ /* 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 */
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5FD_aggr_adjoin() */
+
+
+/*-------------------------------------------------------------------------
+ * 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 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) {
+ /* 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 */
+
+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() */
+
+
+/*-------------------------------------------------------------------------
+ * 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
+ *
+ *-------------------------------------------------------------------------
+ */
+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: Double private version of H5FDalloc() :-)
+ *
+ * Return: Success: The format address of the new file memory.
+ * Failure: The undefined address HADDR_UNDEF
+ *
+ * Programmer: Quincey Koziol
+ * Friday, August 25, 2000
+ *
+ *-------------------------------------------------------------------------
+ */
+static haddr_t
+H5FD_real_alloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size)
+{
+ haddr_t ret_value = HADDR_UNDEF;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5FD_real_alloc)
+#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);
+
+ /*
+ * 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)
+ HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "driver eoa update request failed")
+ }
+
+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() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_free
+ *
+ * Purpose: Private version of H5FDfree()
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, August 4, 1999
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_free(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t size)
+{
+ H5FD_mem_t mapped_type;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FD_free, FAIL)
+
+ /* Check args */
+ HDassert(file);
+ HDassert(file->cls);
+ HDassert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES);
+
+#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 */
+ 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;
+
+ /* 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;
+
+ /* Check for eliminating the block before the 'current' one */
+ if(last == prev)
+ prev = last_prev;
+
+ /* Free the memory for the merged block */
+ 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 */
+#ifdef H5FD_ALLOC_DEBUG
+HDfprintf(stderr, "%s: mapped_type = %u, last = {%a, %Hu}\n", FUNC, (unsigned)mapped_type, last->addr, last->size);
+#endif /* H5FD_ALLOC_DEBUG */
+
+ /* 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);
+#ifdef H5FD_ALLOC_DEBUG
+HDfprintf(stderr, "%s: eoa = %a\n", FUNC, eoa);
+#endif /* H5FD_ALLOC_DEBUG */
+ if(eoa == (last->addr + last->size)) {
+#ifdef H5FD_ALLOC_DEBUG
+HDfprintf(stderr, "%s: Reducing file size to = %a\n", FUNC, last->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*/
+ H5FL_FREE(H5FD_free_t, last);
+ } /* end if */
+ } /* 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 {
+ /* leak memory */
+#ifdef H5FD_ALLOC_DEBUG
+HDfprintf(stderr, "%s: LEAKED MEMORY!!! type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)type, addr, size);
+#endif /* H5FD_ALLOC_DEBUG */
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_free() */
+
+
+/*-------------------------------------------------------------------------
+ * 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 = 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
+ *
+ * Purpose: Check if a block in the file can be extended.
+ *
+ * Return: Success: TRUE(1)/FALSE(0)
+ * 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 */
+ 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
+ *
+ * Note:
+ * Raymond Lu
+ * 5 January 2007
+ * Due to the complexity EOA for Multi driver, this function
+ * is made failed for now.
+ *
+ *-------------------------------------------------------------------------
+ */
+hssize_t
+H5FD_get_freespace(const H5FD_t *file)
+{
+ 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 */
+
+ FUNC_ENTER_NOAPI(H5FD_get_freespace, FAIL)
+
+ /* check args */
+ HDassert(file);
+ HDassert(file->cls);
+
+ /* 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);
+
+ /* 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 */
+
+ /* 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 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;
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_get_freespace() */
+
diff --git a/src/Makefile.am b/src/Makefile.am
index d742282..0e5030b 100755
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -54,7 +54,7 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5F.c H5Fdbg.c H5Ffake.c H5Fmount.c H5Fsfile.c H5Fsuper.c H5Ftest.c \
H5FD.c H5FDcore.c \
H5FDdirect.c H5FDfamily.c H5FDlog.c H5FDmpi.c H5FDmpio.c \
- H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDstdio.c \
+ H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDspace.c H5FDstdio.c \
H5FL.c H5FO.c H5FS.c H5FScache.c H5FSdbg.c H5FSsection.c \
H5G.c H5Gbtree2.c H5Gcompact.c H5Gdense.c H5Gdeprec.c H5Gent.c \
H5Gint.c H5Glink.c \
diff --git a/src/Makefile.in b/src/Makefile.in
index 1dbf810..decae9b 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -88,7 +88,7 @@ am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \
H5E.lo H5Edeprec.lo H5Eint.lo H5F.lo H5Fdbg.lo H5Ffake.lo \
H5Fmount.lo H5Fsfile.lo H5Fsuper.lo H5Ftest.lo H5FD.lo \
H5FDcore.lo H5FDdirect.lo H5FDfamily.lo H5FDlog.lo H5FDmpi.lo \
- H5FDmpio.lo H5FDmpiposix.lo H5FDmulti.lo H5FDsec2.lo \
+ H5FDmpio.lo H5FDmpiposix.lo H5FDmulti.lo H5FDsec2.lo H5FDspace.lo \
H5FDstdio.lo H5FL.lo H5FO.lo H5FS.lo H5FScache.lo H5FSdbg.lo \
H5FSsection.lo H5G.lo H5Gbtree2.lo H5Gcompact.lo H5Gdense.lo \
H5Gdeprec.lo H5Gent.lo H5Gint.lo H5Glink.lo H5Gloc.lo \
@@ -411,7 +411,7 @@ libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5F.c H5Fdbg.c H5Ffake.c H5Fmount.c H5Fsfile.c H5Fsuper.c H5Ftest.c \
H5FD.c H5FDcore.c \
H5FDdirect.c H5FDfamily.c H5FDlog.c H5FDmpi.c H5FDmpio.c \
- H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDstdio.c \
+ H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDspace.c H5FDstdio.c \
H5FL.c H5FO.c H5FS.c H5FScache.c H5FSdbg.c H5FSsection.c \
H5G.c H5Gbtree2.c H5Gcompact.c H5Gdense.c H5Gdeprec.c H5Gent.c \
H5Gint.c H5Glink.c \
@@ -628,6 +628,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDmpiposix.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDmulti.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDsec2.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDspace.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDstdio.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FL.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FO.Plo@am__quote@