summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/H5FDcore.c2
-rw-r--r--src/H5FDdirect.c2
-rw-r--r--src/H5FDfamily.c2
-rw-r--r--src/H5FDlog.c2
-rw-r--r--src/H5FDmpio.c2
-rw-r--r--src/H5FDmpiposix.c2
-rw-r--r--src/H5FDsec2.c2
-rw-r--r--src/H5FDstdio.c2
-rw-r--r--src/H5FSprivate.h2
-rw-r--r--src/H5FSsection.c111
-rw-r--r--src/H5MF.c150
-rw-r--r--src/H5MFaggr.c161
-rw-r--r--src/H5MFpkg.h1
-rw-r--r--src/H5MFprivate.h1
-rw-r--r--src/H5MFsection.c4
15 files changed, 402 insertions, 44 deletions
diff --git a/src/H5FDcore.c b/src/H5FDcore.c
index 8e2cf2a..932e2af 100644
--- a/src/H5FDcore.c
+++ b/src/H5FDcore.c
@@ -184,7 +184,7 @@ static const H5FD_class_t H5FD_core_g = {
H5FD_core_truncate, /*truncate */
NULL, /*lock */
NULL, /*unlock */
- H5FD_FLMAP_SINGLE /*fl_map */
+ H5FD_FLMAP_DICHOTOMY /*fl_map */
};
diff --git a/src/H5FDdirect.c b/src/H5FDdirect.c
index 218a1dd..4721a44 100644
--- a/src/H5FDdirect.c
+++ b/src/H5FDdirect.c
@@ -205,7 +205,7 @@ static const H5FD_class_t H5FD_direct_g = {
H5FD_direct_truncate, /*truncate */
NULL, /*lock */
NULL, /*unlock */
- H5FD_FLMAP_SINGLE /*fl_map */
+ H5FD_FLMAP_DICHOTOMY /*fl_map */
};
/* Declare a free list to manage the H5FD_direct_t struct */
diff --git a/src/H5FDfamily.c b/src/H5FDfamily.c
index 6f6d757..68f856a 100644
--- a/src/H5FDfamily.c
+++ b/src/H5FDfamily.c
@@ -148,7 +148,7 @@ static const H5FD_class_t H5FD_family_g = {
H5FD_family_truncate, /*truncate */
NULL, /*lock */
NULL, /*unlock */
- H5FD_FLMAP_SINGLE /*fl_map */
+ H5FD_FLMAP_DICHOTOMY /*fl_map */
};
diff --git a/src/H5FDlog.c b/src/H5FDlog.c
index b2c6398..6a2425c 100644
--- a/src/H5FDlog.c
+++ b/src/H5FDlog.c
@@ -233,7 +233,7 @@ static const H5FD_class_t H5FD_log_g = {
H5FD_log_truncate, /*truncate */
NULL, /*lock */
NULL, /*unlock */
- H5FD_FLMAP_SINGLE /*fl_map */
+ H5FD_FLMAP_DICHOTOMY /*fl_map */
};
/* Declare a free list to manage the H5FD_log_t struct */
diff --git a/src/H5FDmpio.c b/src/H5FDmpio.c
index 6dbe831..42e28b1 100644
--- a/src/H5FDmpio.c
+++ b/src/H5FDmpio.c
@@ -127,7 +127,7 @@ static const H5FD_class_mpi_t H5FD_mpio_g = {
H5FD_mpio_truncate, /*truncate */
NULL, /*lock */
NULL, /*unlock */
- H5FD_FLMAP_SINGLE /*fl_map */
+ H5FD_FLMAP_DICHOTOMY /*fl_map */
}, /* End of superclass information */
H5FD_mpio_mpi_rank, /*get_rank */
H5FD_mpio_mpi_size, /*get_size */
diff --git a/src/H5FDmpiposix.c b/src/H5FDmpiposix.c
index 0ad39a9..4ed3a4d 100644
--- a/src/H5FDmpiposix.c
+++ b/src/H5FDmpiposix.c
@@ -236,7 +236,7 @@ static const H5FD_class_mpi_t H5FD_mpiposix_g = {
H5FD_mpiposix_truncate, /*truncate */
NULL, /*lock */
NULL, /*unlock */
- H5FD_FLMAP_SINGLE /*fl_map */
+ H5FD_FLMAP_DICHOTOMY /*fl_map */
}, /* End of superclass information */
H5FD_mpiposix_mpi_rank, /*get_rank */
H5FD_mpiposix_mpi_size, /*get_size */
diff --git a/src/H5FDsec2.c b/src/H5FDsec2.c
index 4201e07..241609d 100644
--- a/src/H5FDsec2.c
+++ b/src/H5FDsec2.c
@@ -191,7 +191,7 @@ static const H5FD_class_t H5FD_sec2_g = {
H5FD_sec2_truncate, /*truncate */
NULL, /*lock */
NULL, /*unlock */
- H5FD_FLMAP_SINGLE /*fl_map */
+ H5FD_FLMAP_DICHOTOMY /*fl_map */
};
/* Declare a free list to manage the H5FD_sec2_t struct */
diff --git a/src/H5FDstdio.c b/src/H5FDstdio.c
index 4733eba..43bf6b9 100644
--- a/src/H5FDstdio.c
+++ b/src/H5FDstdio.c
@@ -226,7 +226,7 @@ static const H5FD_class_t H5FD_stdio_g = {
H5FD_stdio_truncate, /* truncate */
NULL, /* lock */
NULL, /* unlock */
- H5FD_FLMAP_SINGLE /* fl_map */
+ H5FD_FLMAP_DICHOTOMY /* fl_map */
};
diff --git a/src/H5FSprivate.h b/src/H5FSprivate.h
index f6a0034..8cb3f95 100644
--- a/src/H5FSprivate.h
+++ b/src/H5FSprivate.h
@@ -200,6 +200,8 @@ H5_DLL herr_t H5FS_sect_stats(const H5FS_t *fspace, hsize_t *tot_space,
hsize_t *nsects);
H5_DLL herr_t H5FS_sect_change_class(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
H5FS_section_info_t *sect, unsigned new_class);
+H5_DLL htri_t H5FS_sect_try_shrink_eoa(const H5F_t *f, hid_t dxpl_id, const H5FS_t *fspace, void *op_data);
+H5_DLL herr_t H5FS_sect_query_last_sect(const H5FS_t *fspace, haddr_t *sect_addr, hsize_t *sect_size);
/* Statistics routine */
H5_DLL herr_t H5FS_stat_info(const H5F_t *f, const H5FS_t *frsp, H5FS_stat_t *stats);
diff --git a/src/H5FSsection.c b/src/H5FSsection.c
index 581d3dc..fa24f85 100644
--- a/src/H5FSsection.c
+++ b/src/H5FSsection.c
@@ -2377,3 +2377,114 @@ HDfprintf(stderr, "%s: sect->size = %Hu, sect->addr = %a, sect->type = %u\n", "H
} /* end H5FS_sect_assert() */
#endif /* H5FS_DEBUG_ASSERT */
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS_sect_try_shrink_eoa
+ *
+ * Purpose: To shrink the last section on the merge list if the section
+ * is at EOF.
+ *
+ * Return: Success: non-negative (TRUE/FALSE)
+ * Failure: negative
+ *
+ * Programmer: Vailin Choi
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5FS_sect_try_shrink_eoa(const H5F_t *f, hid_t dxpl_id, const H5FS_t *fspace, void *op_data)
+{
+ hbool_t sinfo_valid = FALSE; /* Whether the section info is valid */
+ hbool_t section_removed = FALSE; /* Whether a section was removed */
+ htri_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check arguments. */
+ HDassert(fspace);
+
+ if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC_WRITE) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't get section info")
+ sinfo_valid = TRUE;
+
+ if(fspace->sinfo && fspace->sinfo->merge_list) {
+ H5SL_node_t *last_node; /* Last node in merge list */
+
+ /* Check for last node in the merge list */
+ if(NULL != (last_node = H5SL_last(fspace->sinfo->merge_list))) {
+ H5FS_section_info_t *tmp_sect; /* Temporary free space section */
+ H5FS_section_class_t *tmp_sect_cls; /* Temporary section's class */
+
+ /* Get the pointer to the last section, from the last node */
+ tmp_sect = (H5FS_section_info_t *)H5SL_item(last_node);
+ HDassert(tmp_sect);
+ tmp_sect_cls = &fspace->sect_cls[tmp_sect->type];
+ if(tmp_sect_cls->can_shrink) {
+ /* Check if the section can be shrunk away */
+ if((ret_value = (*tmp_sect_cls->can_shrink)(tmp_sect, op_data)) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTSHRINK, FAIL, "can't check for shrinking container")
+ if(ret_value > 0) {
+ HDassert(tmp_sect_cls->shrink);
+
+ /* Remove section from free space manager */
+ if(H5FS_sect_remove_real(fspace, tmp_sect) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures")
+ section_removed = TRUE;
+
+ /* Shrink away section */
+ if((*tmp_sect_cls->shrink)(&tmp_sect, op_data) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't shrink free space container")
+ } /* end if */
+ } /* end if */
+ } /* end if */
+ } /* end if */
+
+done:
+ /* Release the section info */
+ if(sinfo_valid && H5FS_sinfo_unlock(f, dxpl_id, fspace, section_removed) < 0)
+ HDONE_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't release section info")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5FS_sect_try_shrink_eoa() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS_sect_query_last_sect
+ *
+ * Purpose: Retrieve info about the last section on the merge list
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Vailin Choi
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FS_sect_query_last_sect(const H5FS_t *fspace, haddr_t *sect_addr, hsize_t *sect_size)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* Check arguments. */
+ HDassert(fspace);
+
+ if(fspace->sinfo && fspace->sinfo->merge_list) {
+ H5SL_node_t *last_node; /* Last node in merge list */
+
+ /* Check for last node in the merge list */
+ if(NULL != (last_node = H5SL_last(fspace->sinfo->merge_list))) {
+ H5FS_section_info_t *tmp_sect; /* Temporary free space section */
+
+ /* Get the pointer to the last section, from the last node */
+ tmp_sect = (H5FS_section_info_t *)H5SL_item(last_node);
+ HDassert(tmp_sect);
+ if(sect_addr)
+ *sect_addr = tmp_sect->addr;
+ if(sect_size)
+ *sect_size = tmp_sect->size;
+ } /* end if */
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5FS_sect_query_last_sect() */
+
diff --git a/src/H5MF.c b/src/H5MF.c
index e708ab8..4b0668f 100644
--- a/src/H5MF.c
+++ b/src/H5MF.c
@@ -487,6 +487,7 @@ HDfprintf(stderr, "%s: Check 1.6, freeing node\n", FUNC);
udata.dxpl_id = dxpl_id;
udata.alloc_type = alloc_type;
udata.allow_sect_absorb = TRUE;
+ udata.allow_eoa_shrink_only = FALSE;
#ifdef H5MF_ALLOC_DEBUG_MORE
HDfprintf(stderr, "%s: Check 1.7, re-adding node, node->sect_info.size = %Hu\n", FUNC, node->sect_info.size);
@@ -692,6 +693,7 @@ HDfprintf(stderr, "%s: dropping addr = %a, size = %Hu, on the floor!\n", FUNC, a
udata.dxpl_id = dxpl_id;
udata.alloc_type = alloc_type;
udata.allow_sect_absorb = TRUE;
+ udata.allow_eoa_shrink_only = FALSE;
/* If size of section freed is larger than threshold, add it to the free space manager */
if(size >= f->shared->fs_threshold) {
@@ -823,6 +825,11 @@ H5MF_sects_dump(f, dxpl_id, stderr);
* Programmer: Quincey Koziol
* Monday, October 6, 2003
*
+ * Modifications:
+ * Vailin Choi; July 2012
+ * As the default free-list mapping is changed to H5FD_FLMAP_DICHOTOMY,
+ * checks are added to account for the last section of each free-space manager
+ * and the remaining space in the two aggregators are at EOF.
*-------------------------------------------------------------------------
*/
herr_t
@@ -836,6 +843,8 @@ H5MF_get_freespace(H5F_t *f, hid_t dxpl_id, hsize_t *tot_space, hsize_t *meta_si
hsize_t tot_fs_size = 0; /* Amount of all free space managed */
hsize_t tot_meta_size = 0; /* Amount of metadata for free space managers */
H5FD_mem_t type; /* Memory type for iteration */
+ H5FD_mem_t fs_started[H5FD_MEM_NTYPES]; /* Indicate whether the free-space manager has been started */
+ hbool_t eoa_shrank; /* Whether an EOA shrink occurs */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -859,14 +868,15 @@ H5MF_get_freespace(H5F_t *f, hid_t dxpl_id, hsize_t *tot_space, hsize_t *meta_si
/* Iterate over all the free space types that have managers and get each free list's space */
for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type)) {
- hbool_t fs_started = FALSE;
+
+ fs_started[type] = FALSE;
/* Check if the free space for the file has been initialized */
if(!f->shared->fs_man[type] && H5F_addr_defined(f->shared->fs_addr[type])) {
if(H5MF_alloc_open(f, dxpl_id, type) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space")
HDassert(f->shared->fs_man[type]);
- fs_started = TRUE;
+ fs_started[type] = TRUE;
} /* end if */
/* Check if there's free space of this type */
@@ -884,32 +894,54 @@ H5MF_get_freespace(H5F_t *f, hid_t dxpl_id, hsize_t *tot_space, hsize_t *meta_si
tot_fs_size += type_fs_size;
tot_meta_size += type_meta_size;
} /* end if */
+ } /* end for */
- /* Close the free space manager, if we opened it here */
- if(fs_started)
+ /* Iterate until no more EOA shrink occurs */
+ do {
+ eoa_shrank = FALSE;
+
+ /* Check the last section of each free-space manager */
+ for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type)) {
+ haddr_t sect_addr = HADDR_UNDEF;
+ hsize_t sect_size = 0;
+
+ if(f->shared->fs_man[type]) {
+ if(H5FS_sect_query_last_sect(f->shared->fs_man[type], &sect_addr, &sect_size) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't query last section on merge list")
+
+ /* Deduct space from previous accumulation if the section is at EOA */
+ if(H5F_addr_eq(sect_addr + sect_size, eoa)) {
+ eoa = sect_addr;
+ eoa_shrank = TRUE;
+ tot_fs_size -= sect_size;
+ } /* end if */
+ } /* end if */
+ } /* end for */
+
+ /* Check the metadata and raw data aggregators */
+ if(ma_size > 0 && H5F_addr_eq(ma_addr + ma_size, eoa)) {
+ eoa = ma_addr;
+ eoa_shrank = TRUE;
+ ma_size = 0;
+ } /* end if */
+ if(sda_size > 0 && H5F_addr_eq(sda_addr + sda_size, eoa)) {
+ eoa = sda_addr;
+ eoa_shrank = TRUE;
+ sda_size = 0;
+ } /* end if */
+ } while(eoa_shrank);
+
+ /* Close the free-space managers if they were opened earlier in this routine */
+ for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type)) {
+ if(fs_started[type])
if(H5MF_alloc_close(f, dxpl_id, type) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't close file free space")
} /* 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))
- tot_fs_size += 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))
- tot_fs_size += sda_size;
- } /* end if */
-
/* Set the value(s) to return */
+ /* (The metadata & small data aggregators count as free space now, since they aren't at EOA) */
if(tot_space)
- *tot_space = tot_fs_size;
+ *tot_space = tot_fs_size + ma_size + sda_size;
if(meta_size)
*meta_size = tot_meta_size;
@@ -961,6 +993,7 @@ HDfprintf(stderr, "%s: Entering - alloc_type = %u, addr = %a, size = %Hu\n", FUN
udata.dxpl_id = dxpl_id;
udata.alloc_type = alloc_type;
udata.allow_sect_absorb = FALSE; /* Force section to be absorbed into aggregator */
+ udata.allow_eoa_shrink_only = FALSE;
/* Call the "can shrink" callback for the section */
if((ret_value = H5MF_sect_simple_can_shrink((const H5FS_section_info_t *)node, &udata)) < 0)
@@ -984,6 +1017,66 @@ HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value);
/*-------------------------------------------------------------------------
+ * Function: H5MF_close_shrink_eoa
+ *
+ * Purpose: Shrink the EOA while closing
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Saturday, July 7, 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5MF_close_shrink_eoa(H5F_t *f, hid_t dxpl_id)
+{
+ H5FD_mem_t type; /* Memory type for iteration */
+ hbool_t eoa_shrank; /* Whether an EOA shrink occurs */
+ htri_t status; /* Status value */
+ H5MF_sect_ud_t udata; /* User data for callback */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* check args */
+ HDassert(f);
+ HDassert(f->shared);
+
+ /* Construct user data for callbacks */
+ udata.f = f;
+ udata.dxpl_id = dxpl_id;
+ udata.allow_sect_absorb = FALSE;
+ udata.allow_eoa_shrink_only = TRUE;
+
+ /* Iterate until no more EOA shrinking occurs */
+ do {
+ eoa_shrank = FALSE;
+
+ /* Check the last section of each free-space manager */
+ for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type)) {
+ if(f->shared->fs_man[type]) {
+ udata.alloc_type = type;
+ if((status = H5FS_sect_try_shrink_eoa(f, dxpl_id, f->shared->fs_man[type], &udata)) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTSHRINK, FAIL, "can't check for shrinking eoa")
+ else if(status > 0)
+ eoa_shrank = TRUE;
+ } /* end if */
+ } /* end for */
+
+ /* check the two aggregators */
+ if((status = H5MF_aggrs_try_shrink_eoa(f, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't check for shrinking eoa")
+ else if(status > 0)
+ eoa_shrank = TRUE;
+ } while(eoa_shrank);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MF_close_shrink_eoa() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5MF_close
*
* Purpose: Close the free space tracker(s) for a file
@@ -993,6 +1086,12 @@ HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value);
* Programmer: Quincey Koziol
* Tuesday, January 22, 2008
*
+ * Modifications:
+ * Vailin Choi; July 2012
+ * As the default free-list mapping is changed to H5FD_FLMAP_DICHOTOMY,
+ * modifications are needed to shrink EOA if the last section of each free-space manager
+ * and the remaining space in the two aggregators are at EOA.
+
*-------------------------------------------------------------------------
*/
herr_t
@@ -1017,6 +1116,10 @@ HDfprintf(stderr, "%s: Entering\n", FUNC);
if(H5MF_free_aggrs(f, dxpl_id) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "can't free aggregators")
+ /* Trying shrinking the EOA for the file */
+ if(H5MF_close_shrink_eoa(f, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't shrink eoa")
+
/* Making free-space managers persistent for superblock version >= 2 */
if(f->shared->sblock->super_vers >= HDF5_SUPERBLOCK_VERSION_2
&& f->shared->fs_strategy == H5F_FILE_SPACE_ALL_PERSIST) {
@@ -1164,6 +1267,11 @@ HDfprintf(stderr, "%s: Before deleting free space manager\n", FUNC);
if(H5MF_free_aggrs(f, dxpl_id) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "can't free aggregators")
+ /* Trying shrinking the EOA for the file */
+ /* (in case any free space is now at the EOA) */
+ if(H5MF_close_shrink_eoa(f, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't shrink eoa")
+
done:
#ifdef H5MF_ALLOC_DEBUG
HDfprintf(stderr, "%s: Leaving\n", FUNC);
diff --git a/src/H5MFaggr.c b/src/H5MFaggr.c
index 6f68fd7..f015b19 100644
--- a/src/H5MFaggr.c
+++ b/src/H5MFaggr.c
@@ -57,6 +57,8 @@
/********************/
/* Local Prototypes */
/********************/
+static herr_t H5MF_aggr_free(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type,
+ H5F_blk_aggr_t *aggr);
/*********************/
@@ -231,15 +233,14 @@ HDfprintf(stderr, "%s: aggr = {%a, %Hu, %Hu}\n", FUNC, aggr->addr, aggr->tot_siz
if(H5F_addr_gt((eoa + size), f->shared->tmp_addr))
HGOTO_ERROR(H5E_RESOURCE, H5E_BADRANGE, HADDR_UNDEF, "'normal' file space allocation request will overlap into 'temporary' file space")
+ /* Release "other" aggregator, if it exists, is at the end of the allocated space,
+ * has allocated more than one block and the unallocated space is greater than its
+ * allocation block size.
+ */
if ((other_aggr->size > 0) && (H5F_addr_eq((other_aggr->addr + other_aggr->size), eoa)) &&
- ((other_aggr->tot_size - other_aggr->size) >= other_aggr->alloc_size)) {
-
- if(H5FD_free(f->shared->lf, dxpl_id, other_alloc_type, f, other_aggr->addr, other_aggr->size) < 0)
+ (other_aggr->tot_size > other_aggr->size) && ((other_aggr->tot_size - other_aggr->size) >= other_aggr->alloc_size)) {
+ if(H5MF_aggr_free(f, dxpl_id, other_alloc_type, other_aggr) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation block")
-
- other_aggr->addr = 0;
- other_aggr->tot_size = 0;
- other_aggr->size = 0;
} /* end if */
/* Allocate space from the VFD (i.e. at the end of the file) */
@@ -275,14 +276,14 @@ HDfprintf(stderr, "%s: Allocating block\n", FUNC);
if(H5F_addr_gt((eoa + aggr->alloc_size), f->shared->tmp_addr))
HGOTO_ERROR(H5E_RESOURCE, H5E_BADRANGE, HADDR_UNDEF, "'normal' file space allocation request will overlap into 'temporary' file space")
+ /* Release "other" aggregator, if it exists, is at the end of the allocated space,
+ * has allocated more than one block and the unallocated space is greater than its
+ * allocation block size.
+ */
if((other_aggr->size > 0) && (H5F_addr_eq((other_aggr->addr + other_aggr->size), eoa)) &&
- ((other_aggr->tot_size - other_aggr->size) >= other_aggr->alloc_size)) {
-
- if(H5FD_free(f->shared->lf, dxpl_id, other_alloc_type, f, other_aggr->addr, other_aggr->size) < 0)
+ (other_aggr->tot_size > other_aggr->size) && ((other_aggr->tot_size - other_aggr->size) >= other_aggr->alloc_size)) {
+ if(H5MF_aggr_free(f, dxpl_id, other_alloc_type, other_aggr) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation block")
- other_aggr->addr = 0;
- other_aggr->tot_size = 0;
- other_aggr->size = 0;
} /* end if */
/* Allocate space from the VFD (i.e. at the end of the file) */
@@ -633,8 +634,10 @@ H5MF_aggr_query(const H5F_t *f, const H5F_blk_aggr_t *aggr, haddr_t *addr,
/* Check if this aggregator is active */
if(f->shared->feature_flags & aggr->feature_flag) {
- *addr = aggr->addr;
- *size = aggr->size;
+ if(addr)
+ *addr = aggr->addr;
+ if(size)
+ *size = aggr->size;
} /* end if */
FUNC_LEAVE_NOAPI(SUCCEED)
@@ -766,3 +769,131 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5MF_free_aggrs() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_aggr_can_shrink_eoa
+ *
+ * Purpose: Check if the remaining space in the aggregator is at EOA
+ *
+ * Return: Success: non-negative (TRUE/FALSE)
+ * Failure: negative
+ *
+ * Programmer: Vailin Choi
+ *
+ *-------------------------------------------------------------------------
+ */
+static htri_t
+H5MF_aggr_can_shrink_eoa(H5F_t *f, H5FD_mem_t type, H5F_blk_aggr_t *aggr)
+{
+ haddr_t eoa = HADDR_UNDEF; /* EOA for the file */
+ htri_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(aggr);
+ HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA);
+
+ /* Get the EOA for the file */
+ if(HADDR_UNDEF == (eoa = H5F_get_eoa(f, type)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "Unable to get eoa")
+
+ /* Check if the aggregator is at EOA */
+ if(aggr->size > 0 && H5F_addr_defined(aggr->addr))
+ ret_value = H5F_addr_eq(eoa, aggr->addr + aggr->size);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5MF_aggr_can_shrink_eoa() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_aggr_free
+ *
+ * Purpose: Free the aggregator's space in the file.
+ *
+ * Note: Does _not_ put the space on a free list
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5MF_aggr_free(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, H5F_blk_aggr_t *aggr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(f->shared->lf);
+ HDassert(aggr);
+ HDassert(H5F_addr_defined(aggr->addr));
+ HDassert(aggr->size > 0);
+ HDassert(H5F_INTENT(f) & H5F_ACC_RDWR);
+ HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA);
+ HDassert(f->shared->feature_flags & aggr->feature_flag);
+
+ /* Free the remaining space at EOA in the aggregator */
+ if(H5FD_free(f->shared->lf, dxpl_id, type, f, aggr->addr, aggr->size) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "can't free aggregation block")
+
+ /* Reset the aggregator */
+ aggr->tot_size = 0;
+ aggr->addr = HADDR_UNDEF;
+ aggr->size = 0;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5MF_aggr_free() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_aggrs_try_shrink_eoa
+ *
+ * Purpose: Check the metadata & small block aggregators to see if
+ * EOA shrink is possible; if so, shrink each aggregator
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5MF_aggrs_try_shrink_eoa(H5F_t *f, hid_t dxpl_id)
+{
+ htri_t ma_status; /* Whether the metadata aggregator can shrink the EOA */
+ htri_t sda_status; /* Whether the small data aggregator can shrink the EOA */
+ htri_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check args */
+ HDassert(f);
+ HDassert(f->shared);
+
+ if((ma_status = H5MF_aggr_can_shrink_eoa(f, H5FD_MEM_DEFAULT, &(f->shared->meta_aggr))) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't query metadata aggregator stats")
+ if(ma_status > 0)
+ if(H5MF_aggr_free(f, dxpl_id, H5FD_MEM_DEFAULT, &(f->shared->meta_aggr)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't check for shrinking eoa")
+
+ if((sda_status = H5MF_aggr_can_shrink_eoa(f, H5FD_MEM_DRAW, &(f->shared->sdata_aggr))) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't query small data aggregator stats")
+ if(sda_status > 0)
+ if(H5MF_aggr_free(f, dxpl_id, H5FD_MEM_DRAW, &(f->shared->sdata_aggr)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't check for shrinking eoa")
+
+ ret_value = (ma_status || sda_status);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MF_aggrs_try_shrink_eoa() */
+
diff --git a/src/H5MFpkg.h b/src/H5MFpkg.h
index 25785ae..2071a0a 100644
--- a/src/H5MFpkg.h
+++ b/src/H5MFpkg.h
@@ -122,6 +122,7 @@ typedef struct H5MF_sect_ud_t {
hid_t dxpl_id; /* DXPL for VFD operations */
H5FD_mem_t alloc_type; /* Type of memory being allocated */
hbool_t allow_sect_absorb; /* Whether sections are allowed to absorb a block aggregator */
+ hbool_t allow_eoa_shrink_only; /* Whether shrinking eoa is allowed only for the section */
/* Up */
H5MF_shrink_type_t shrink; /* Type of shrink operation to perform */
diff --git a/src/H5MFprivate.h b/src/H5MFprivate.h
index b471aa3..ad5e385 100644
--- a/src/H5MFprivate.h
+++ b/src/H5MFprivate.h
@@ -81,6 +81,7 @@ H5_DLL haddr_t H5MF_alloc_tmp(H5F_t *f, hsize_t size);
/* 'block aggregator' routines */
H5_DLL herr_t H5MF_free_aggrs(H5F_t *f, hid_t dxpl_id);
+H5_DLL htri_t H5MF_aggrs_try_shrink_eoa(H5F_t *f, hid_t dxpl_id);
/* Debugging routines */
#ifdef H5MF_DEBUGGING
diff --git a/src/H5MFsection.c b/src/H5MFsection.c
index 89b2219..0572def 100644
--- a/src/H5MFsection.c
+++ b/src/H5MFsection.c
@@ -328,6 +328,10 @@ HDfprintf(stderr, "%s: section {%a, %Hu}, shrinks file, eoa = %a\n", FUNC, sect-
HGOTO_DONE(TRUE)
} /* end if */
else {
+ /* Shrinking can't occur if the 'eoa_shrink_only' flag is set and we're not shrinking the EOA */
+ if(udata->allow_eoa_shrink_only)
+ HGOTO_DONE(FALSE)
+
/* Check if this section is allowed to merge with metadata aggregation block */
if(udata->f->shared->fs_aggr_merge[udata->alloc_type] & H5F_FS_MERGE_METADATA) {
htri_t status; /* Status from aggregator adjoin */