summaryrefslogtreecommitdiffstats
path: root/src/H5FSsection.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5FSsection.c')
-rw-r--r--src/H5FSsection.c1202
1 files changed, 782 insertions, 420 deletions
diff --git a/src/H5FSsection.c b/src/H5FSsection.c
index 6aad881..42c0f86 100644
--- a/src/H5FSsection.c
+++ b/src/H5FSsection.c
@@ -40,6 +40,8 @@
/* Local Macros */
/****************/
+/* #define QAK */
+
/* Default starting size of section buffer */
#define H5FS_SINFO_SIZE_DEFAULT 64
@@ -67,27 +69,26 @@ typedef struct {
/********************/
/* Local Prototypes */
/********************/
-static herr_t H5FS_sect_increase(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
- const H5FS_section_class_t *cls, unsigned flags);
-static herr_t H5FS_sect_decrease(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
- const H5FS_section_class_t *cls);
+static herr_t H5FS_sect_increase(H5FS_t *fspace, const H5FS_section_class_t *cls,
+ unsigned flags);
+static herr_t H5FS_sect_decrease(H5FS_t *fspace, const H5FS_section_class_t *cls);
static herr_t H5FS_size_node_decr(H5FS_sinfo_t *sinfo, unsigned bin, H5FS_node_t *fspace_node,
const H5FS_section_class_t *cls);
static herr_t H5FS_sect_unlink_size(H5FS_sinfo_t *sinfo, const H5FS_section_class_t *cls,
H5FS_section_info_t *sect);
-static herr_t H5FS_sect_unlink_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
+static herr_t H5FS_sect_unlink_rest(H5FS_t *fspace,
const H5FS_section_class_t *cls, H5FS_section_info_t *sect);
+static herr_t H5FS_sect_remove_real(H5FS_t *fspace, H5FS_section_info_t *sect);
static herr_t H5FS_sect_link_size(H5FS_sinfo_t *sinfo, const H5FS_section_class_t *cls,
H5FS_section_info_t *sect);
-static herr_t H5FS_sect_link_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
- const H5FS_section_class_t *cls, H5FS_section_info_t *sect, unsigned flags);
-static herr_t H5FS_sect_link(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
+static herr_t H5FS_sect_link_rest(H5FS_t *fspace, const H5FS_section_class_t *cls,
H5FS_section_info_t *sect, unsigned flags);
-static herr_t H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
- H5FS_section_info_t **sect, void *op_data);
+static herr_t H5FS_sect_link(H5FS_t *fspace, H5FS_section_info_t *sect,
+ unsigned flags);
+static herr_t H5FS_sect_merge(H5FS_t *fspace, H5FS_section_info_t **sect,
+ void *op_data);
static htri_t H5FS_sect_find_node(H5FS_t *fspace, hsize_t request, H5FS_section_info_t **node);
-static herr_t H5FS_sect_serialize_size(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace);
-
+static herr_t H5FS_sect_serialize_size(H5FS_t *fspace);
/*********************/
/* Package Variables */
@@ -138,6 +139,9 @@ H5FS_sinfo_new(H5F_t *f, H5FS_t *fspace)
/* Check arguments. */
HDassert(f);
HDassert(fspace);
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: fspace->addr = %a\n", FUNC, fspace->addr);
+#endif /* H5FS_SINFO_DEBUG */
/* Allocate the free space header */
if(NULL == (sinfo = H5FL_CALLOC(H5FS_sinfo_t)))
@@ -148,113 +152,370 @@ H5FS_sinfo_new(H5F_t *f, H5FS_t *fspace)
sinfo->sect_prefix_size = H5FS_SINFO_PREFIX_SIZE(f);
sinfo->sect_off_size = (fspace->max_sect_addr + 7) / 8;
sinfo->sect_len_size = H5V_limit_enc_size((uint64_t)fspace->max_sect_size);
- sinfo->fspace = fspace;
-#ifdef QAK
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: fspace->max_sect_size = %Hu\n", FUNC, fspace->max_sect_size);
+HDfprintf(stderr, "%s: fspace->max_sect_addr = %u\n", FUNC, fspace->max_sect_addr);
HDfprintf(stderr, "%s: sinfo->nbins = %u\n", FUNC, sinfo->nbins);
HDfprintf(stderr, "%s: sinfo->sect_off_size = %u, sinfo->sect_len_size = %u\n", FUNC, sinfo->sect_off_size, sinfo->sect_len_size);
-#endif /* QAK */
+#endif /* H5FS_SINFO_DEBUG */
/* Allocate space for the section size bins */
if(NULL == (sinfo->bins = H5FL_SEQ_CALLOC(H5FS_bin_t, (size_t)sinfo->nbins)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for free space section bin array")
+ /* Increment the reference count on the free space manager header */
+ if(H5FS_incr(f, fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTINC, NULL, "unable to increment ref. count on free space header")
+ sinfo->fspace = fspace;
+
+ /* Link free space manager to section info */
+ /* (for deserializing sections) */
+ HDassert(fspace->sinfo == NULL);
+ fspace->sinfo = sinfo;
+
/* Set return value */
ret_value = sinfo;
done:
+ if(ret_value == NULL && sinfo) {
+ /* Release bins for skip lists */
+ if(sinfo->bins)
+ sinfo->bins = H5FL_SEQ_FREE(H5FS_bin_t, sinfo->bins);
+ /* Release free space section info */
+ H5FL_FREE(H5FS_sinfo_t, sinfo);
+ } /* end if */
+
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_sinfo_new() */
/*-------------------------------------------------------------------------
- * Function: H5FS_sinfo_pin
+ * Function: H5FS_sinfo_lock
*
- * Purpose: Pin the section info for the free space manager in memory
- * Either loads section info from disk, or creates new section info
+ * Purpose: Make certain the section info for the free space manager is
+ * in memory.
*
- * Return: Success: non-NULL, pointer to section info struct
- * Failure: NULL
+ * Either uses existing section info owned by the free space
+ * header, loads section info from disk, or creates new section
+ * info
+ *
+ * Return: Success: non-negative
+ * Failure: negative
*
* Programmer: Quincey Koziol
- * Monday, July 31, 2006
+ * Thursday, February 7, 2008
*
*-------------------------------------------------------------------------
*/
-static H5FS_sinfo_t *
-H5FS_sinfo_pin(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace)
+static herr_t
+H5FS_sinfo_lock(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5AC_protect_t accmode)
{
- H5FS_sinfo_t *sinfo; /* Section information struct created */
- H5FS_sinfo_t *ret_value; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5FS_sinfo_pin)
-#ifdef QAK
-HDfprintf(stderr, "%s: Called, fspace->sect_addr = %a\n", FUNC, fspace->sect_addr);
-#endif /* QAK */
+ FUNC_ENTER_NOAPI_NOINIT(H5FS_sinfo_lock)
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: Called, fspace->addr = %a, fspace->sinfo = %p, fspace->sect_addr = %a\n", FUNC, fspace->addr, fspace->sinfo, fspace->sect_addr);
+HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n", FUNC, fspace->alloc_sect_size, fspace->sect_size);
+#endif /* H5FS_SINFO_DEBUG */
/* Check arguments. */
HDassert(f);
HDassert(fspace);
- /* Create new section info, if it doesn't exist yet */
- if(!H5F_addr_defined(fspace->sect_addr)) {
-#ifdef QAK
-HDfprintf(stderr, "%s: Allocating new section info\n", FUNC);
-#endif /* QAK */
- /* Sanity check */
- HDassert(fspace->tot_sect_count == 0);
- HDassert(fspace->serial_sect_count == 0);
- HDassert(fspace->ghost_sect_count == 0);
+ /* If the free space header doesn't already "own" the section info, load
+ * section info or create it
+ */
+ if(fspace->sinfo) {
+ /* Check if the section info was protected & we want a different access mode */
+ if(fspace->sinfo_protected && accmode != fspace->sinfo_accmode) {
+ /* Check if we need to switch from read-only access to read-write */
+ if(H5AC_WRITE == accmode) {
+ /* Unprotect the read-only section info */
+ if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, fspace->sinfo, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPROTECT, FAIL, "unable to release free space section info")
+
+ /* Re-protect the section info with read-write access */
+ if(NULL == (fspace->sinfo = H5AC_protect(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, NULL, fspace, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, FAIL, "unable to load free space sections")
+
+ /* Switch the access mode we have */
+ fspace->sinfo_accmode = H5AC_WRITE;
+ } /* end if */
+ } /* end if */
+ } /* end if */
+ else {
+ /* If the section address is defined, load it from the file */
+ if(H5F_addr_defined(fspace->sect_addr)) {
+ /* Sanity check */
+ HDassert(fspace->sinfo_protected == FALSE);
+ HDassert(H5F_addr_defined(fspace->addr));
- /* Allocate and initialize free space section info */
- if(NULL == (sinfo = H5FS_sinfo_new(f, fspace)))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTCREATE, NULL, "can't create section info")
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: Reading in existing sections, fspace->sect_addr = %a\n", FUNC, fspace->sect_addr);
+#endif /* H5FS_SINFO_DEBUG */
+ /* Protect the free space sections */
+ if(NULL == (fspace->sinfo = H5AC_protect(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, NULL, fspace, accmode)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, FAIL, "unable to load free space sections")
+
+ /* Remember that we protected the section info & the access mode */
+ fspace->sinfo_protected = TRUE;
+ fspace->sinfo_accmode = accmode;
+ } /* end if */
+ else {
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: Creating new section info\n", FUNC);
+#endif /* H5FS_SINFO_DEBUG */
+ /* Sanity check */
+ HDassert(fspace->tot_sect_count == 0);
+ HDassert(fspace->serial_sect_count == 0);
+ HDassert(fspace->ghost_sect_count == 0);
+
+ /* Allocate and initialize free space section info */
+ if(NULL == (fspace->sinfo = H5FS_sinfo_new(f, fspace)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTCREATE, FAIL, "can't create section info")
+
+ /* Set initial size of section info to 0 */
+ fspace->sect_size = fspace->alloc_sect_size = 0;
+ } /* end if */
+ } /* end if */
+ HDassert(fspace->rc == 2);
- /* Allocate space for the section info */
- fspace->sect_size = H5FS_SINFO_SIZE_DEFAULT;
- fspace->alloc_sect_size = (size_t)fspace->sect_size;
- if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->alloc_sect_size)))
- HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, NULL, "file allocation failed for free space sections")
-#ifdef QAK
-HDfprintf(stderr, "%s: New section info, addr = %a, size = %Hu\n", FUNC, fspace->sect_addr, fspace->alloc_sect_size);
-#endif /* QAK */
+ /* Increment the section info lock count */
+ fspace->sinfo_lock_count++;
+
+done:
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: Leaving, fspace->addr = %a, fspace->sinfo = %p, fspace->sect_addr = %a\n", FUNC, fspace->addr, fspace->sinfo, fspace->sect_addr);
+HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n", FUNC, fspace->alloc_sect_size, fspace->sect_size);
+#endif /* H5FS_SINFO_DEBUG */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5FS_sinfo_lock() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS_sinfo_unlock
+ *
+ * Purpose: Release the section info, either giving ownership back to
+ * the cache or letting the free space header keep it.
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, February 7, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FS_sinfo_unlock(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, hbool_t modified)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5FS_sinfo_unlock)
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: Called, modified = %t, fspace->addr = %a, fspace->sect_addr = %a\n", FUNC, modified, fspace->addr, fspace->sect_addr);
+HDfprintf(stderr, "%s: fspace->sinfo_lock_count = %u, fspace->sinfo_modified = %t, fspace->sinfo_protected = %t\n", FUNC, fspace->sinfo_lock_count, fspace->sinfo_modified, fspace->sinfo_protected);
+HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n", FUNC, fspace->alloc_sect_size, fspace->sect_size);
+#endif /* H5FS_SINFO_DEBUG */
+
+ /* Check arguments. */
+ HDassert(f);
+ HDassert(fspace);
+ HDassert(fspace->rc == 2);
+ HDassert(fspace->sinfo);
+
+ /* Check if we modified any section */
+ if(modified) {
+ /* Check if the section info was protected with a different access mode */
+ if(fspace->sinfo_protected && fspace->sinfo_accmode != H5AC_WRITE)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTDIRTY, FAIL, "attempt to modify read-only section info")
- /* Cache the new free space section info (pinned) */
- if(H5AC_set(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, sinfo, H5AC__PIN_ENTRY_FLAG) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, NULL, "can't add free space sections to cache")
+ /* If we modified the section info, mark it dirty */
+ fspace->sinfo->dirty = TRUE;
- /* Mark free space header as dirty */
- if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, NULL, "unable to mark free space header as dirty")
+ /* Remember that the section info was modified while locked */
+ fspace->sinfo_modified = TRUE;
+
+ /* Assume that the modification will affect the statistics in the header
+ * and mark that dirty also
+ */
+ if(H5FS_dirty(f, fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty")
} /* end if */
- else {
+
+ /* Decrement the lock count on the section info */
+ fspace->sinfo_lock_count--;
+
+ /* Check if section info lock count dropped to zero */
+ if(fspace->sinfo_lock_count == 0) {
+ hbool_t release_sinfo_space = FALSE; /* Flag to indicate section info space in file should be released */
+
+ /* Check if we actually protected the section info */
+ if(fspace->sinfo_protected) {
+ unsigned cache_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting heap */
+
+ /* Sanity check */
+ HDassert(H5F_addr_defined(fspace->addr));
+
+ /* Check if we've made new changes to the section info while locked */
+ if(fspace->sinfo_modified) {
+ /* Note that we've modified the section info */
+ cache_flags |= H5AC__DIRTIED_FLAG;
+
+ /* Check if the section info size in the file has changed */
+ if(fspace->sect_size != fspace->alloc_sect_size)
+ cache_flags |= H5AC__SIZE_CHANGED_FLAG | H5AC__DELETED_FLAG | H5AC__TAKE_OWNERSHIP_FLAG;
+ } /* end if */
+
+ /* Sanity check */
+ HDassert(H5F_addr_defined(fspace->sect_addr));
+
+ /* Unprotect section info in cache */
+ /* (Possibly dirty) */
+ /* (Possibly taking ownership from the cache) */
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: Unprotecting section info, cache_flags = %u\n", FUNC, cache_flags);
+#endif /* H5FS_SINFO_DEBUG */
+ if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, fspace->sinfo, cache_flags) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPROTECT, FAIL, "unable to release free space section info")
+
+ /* Reset the protected flag on the section info */
+ fspace->sinfo_protected = FALSE;
+
+ /* Check if header is taking ownership of section info */
+ if((cache_flags & H5AC__TAKE_OWNERSHIP_FLAG)) {
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: Taking ownership of section info\n", FUNC);
+#endif /* H5FS_SINFO_DEBUG */
+ /* Set flag to release section info space in file */
+ release_sinfo_space = TRUE;
+ } /* end if */
+ else {
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: Relinquishing section info ownership\n", FUNC);
+#endif /* H5FS_SINFO_DEBUG */
+ /* Free space header relinquished ownership of section info */
+ fspace->sinfo = NULL;
+ } /* end else */
+ } /* end if */
+ else {
+ /* Check if the section info was modified */
+ if(fspace->sinfo_modified) {
+ /* Check if we need to release section info in the file */
+ if(H5F_addr_defined(fspace->sect_addr))
+ /* Set flag to release section info space in file */
+ release_sinfo_space = TRUE;
+ else
+ HDassert(fspace->alloc_sect_size == 0);
+ } /* end if */
+ else {
+ /* Sanity checks... */
+ if(H5F_addr_defined(fspace->sect_addr))
+ HDassert(fspace->alloc_sect_size == fspace->sect_size);
+ else
+ HDassert(fspace->alloc_sect_size == 0);
+ } /* end else */
+ } /* end else */
+
+ /* Reset the "section info modified" flag */
+ fspace->sinfo_modified = FALSE;
+
+ /* Check if header needs to release section info in the file */
+ if(release_sinfo_space) {
+ haddr_t old_sect_addr = fspace->sect_addr; /* Previous location of section info in file */
+ hsize_t old_alloc_sect_size = fspace->alloc_sect_size; /* Previous size of section info in file */
+
+ /* Sanity check */
+ HDassert(H5F_addr_defined(fspace->addr));
+
+ /* Reset section info in header */
+ fspace->sect_addr = HADDR_UNDEF;
+ fspace->alloc_sect_size = 0;
+
+ /* If we haven't already marked the header dirty, do so now */
+ if(!modified)
+ if(H5FS_dirty(f, fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty")
+
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: Freeing section info on disk, old_sect_addr = %a, old_alloc_sect_size = %Hu\n", FUNC, old_sect_addr, old_alloc_sect_size);
+#endif /* H5FS_SINFO_DEBUG */
+ /* Release space for section info in file */
+ if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, old_sect_addr, old_alloc_sect_size) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space sections")
+ } /* end if */
+ } /* end if */
+
+done:
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value);
+#endif /* H5FS_SINFO_DEBUG */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5FS_sinfo_unlock() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS_sect_serialize_size
+ *
+ * Purpose: Determine serialized size of all sections in free space manager
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Monday, May 8, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FS_sect_serialize_size(H5FS_t *fspace)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_sect_serialize_size)
+
+ /* Check arguments. */
+ HDassert(fspace);
#ifdef QAK
-HDfprintf(stderr, "%s: Reading in existing sections, fspace->sect_addr = %a\n", FUNC, fspace->sect_addr);
+HDfprintf(stderr, "%s: Check 1.0 - fspace->sect_size = %Hu\n", "H5FS_sect_serialize_size", fspace->sect_size);
+HDfprintf(stderr, "%s: fspace->serial_sect_count = %Zu\n", "H5FS_sect_serialize_size", fspace->serial_sect_count);
+HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu\n", "H5FS_sect_serialize_size", fspace->alloc_sect_size);
+HDfprintf(stderr, "%s: fspace->sinfo->serial_size_count = %Zu\n", "H5FS_sect_serialize_size", fspace->sinfo->serial_size_count);
#endif /* QAK */
- /* Protect the free space sections */
- if(NULL == (sinfo = (H5FS_sinfo_t *)H5AC_protect(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, NULL, fspace, H5AC_WRITE)))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, NULL, "unable to load free space sections")
- /* Pin them in the cache */
- if(H5AC_pin_protected_entry(f, sinfo) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTPIN, NULL, "unable to pin free space sections")
+ /* Compute the size of the buffer required to serialize all the sections */
+ if(fspace->serial_sect_count > 0) {
+ size_t sect_buf_size; /* Section buffer size */
- /* Unlock free space sections, now pinned */
- if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, sinfo, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPROTECT, NULL, "unable to release free space sections")
- } /* end else */
+ /* Serialized sections prefix */
+ sect_buf_size = fspace->sinfo->sect_prefix_size;
+
+ /* Count for each differently sized serializable section */
#ifdef QAK
-HDfprintf(stderr, "%s: sinfo->serial_size_count = %Zu\n", FUNC, sinfo->serial_size_count);
+HDfprintf(stderr, "%s: fspace->sinfo->serial_size_count = %Zu\n", "H5FS_sect_serialize_size", fspace->sinfo->serial_size_count);
+HDfprintf(stderr, "%s: fspace->serial_sect_count = %Hu\n", "H5FS_sect_serialize_size", fspace->serial_sect_count);
#endif /* QAK */
+ sect_buf_size += fspace->sinfo->serial_size_count * H5V_limit_enc_size((uint64_t)fspace->serial_sect_count);
- /* Update pointer to free space header for section info */
- sinfo->fspace = fspace;
+ /* Size for each differently sized serializable section */
+ sect_buf_size += fspace->sinfo->serial_size_count * fspace->sinfo->sect_len_size;
- /* Set return value */
- ret_value = sinfo;
+ /* Offsets of each section in address space */
+ sect_buf_size += fspace->serial_sect_count * fspace->sinfo->sect_off_size;
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5FS_sinfo_pin() */
+ /* Class of each section */
+ sect_buf_size += fspace->serial_sect_count * 1 /* byte */;
+
+ /* Extra space required to serialize each section */
+ sect_buf_size += fspace->sinfo->serial_size;
+
+ /* Update section size in header */
+ fspace->sect_size = sect_buf_size;
+ } /* end if */
+ else
+ /* Reset section size in header */
+ fspace->sect_size = fspace->sinfo->sect_prefix_size;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5FS_sect_serialize_size() */
/*-------------------------------------------------------------------------
@@ -264,7 +525,6 @@ done:
* on disk
*
* Return: Success: non-negative
- *
* Failure: negative
*
* Programmer: Quincey Koziol
@@ -273,8 +533,8 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_sect_increase(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
- const H5FS_section_class_t *cls, unsigned flags)
+H5FS_sect_increase(H5FS_t *fspace, const H5FS_section_class_t *cls,
+ unsigned flags)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -310,15 +570,11 @@ HDfprintf(stderr, "%s: cls->serial_size = %Zu\n", FUNC, cls->serial_size);
/* Update the free space sections' serialized size */
/* (if we're not deserializing the sections from disk) */
if(!(flags & H5FS_ADD_DESERIALIZING)) {
- if(H5FS_sect_serialize_size(f, dxpl_id, fspace) < 0)
+ if(H5FS_sect_serialize_size(fspace) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTCOMPUTE, FAIL, "can't adjust free space section size on disk")
} /* end if */
} /* end else */
- /* Mark free space header as dirty */
- if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty")
-
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_sect_increase() */
@@ -340,7 +596,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_sect_decrease(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, const H5FS_section_class_t *cls)
+H5FS_sect_decrease(H5FS_t *fspace, const H5FS_section_class_t *cls)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -374,14 +630,10 @@ HDfprintf(stderr, "%s: cls->serial_size = %Zu\n", FUNC, cls->serial_size);
fspace->sinfo->serial_size -= cls->serial_size;
/* Update the free space sections' serialized size */
- if(H5FS_sect_serialize_size(f, dxpl_id, fspace) < 0)
+ if(H5FS_sect_serialize_size(fspace) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTCOMPUTE, FAIL, "can't adjust free space section size on disk")
} /* end else */
- /* Mark free space header as dirty */
- if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty")
-
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_sect_decrease() */
@@ -547,15 +799,14 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_sect_unlink_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
- const H5FS_section_class_t *cls, H5FS_section_info_t *sect)
+H5FS_sect_unlink_rest(H5FS_t *fspace, const H5FS_section_class_t *cls,
+ H5FS_section_info_t *sect)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_unlink_rest)
/* Check arguments. */
- HDassert(f);
HDassert(fspace);
HDassert(fspace->sinfo);
HDassert(cls);
@@ -574,7 +825,7 @@ HDfprintf(stderr, "%s: removing object from merge list, sect->type = %u\n", FUNC
} /* end if */
/* Update section info & check if we need less room for the serialized free space sections */
- if(H5FS_sect_decrease(f, dxpl_id, fspace, cls) < 0)
+ if(H5FS_sect_decrease(fspace, cls) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't increase free space section size on disk")
/* Decrement amount of free space managed */
@@ -583,17 +834,13 @@ HDfprintf(stderr, "%s: fspace->tot_space = %Hu\n", FUNC, fspace->tot_space);
#endif /* QAK */
fspace->tot_space -= sect->size;
- /* Mark free space sections as changed */
- if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace->sinfo) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space sections as dirty")
-
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_sect_unlink_rest() */
/*-------------------------------------------------------------------------
- * Function: H5FS_sect_remove
+ * Function: H5FS_sect_remove_real
*
* Purpose: Remove a section from the free space manager
*
@@ -605,17 +852,15 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t
-H5FS_sect_remove(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
- H5FS_section_info_t *sect)
+static herr_t
+H5FS_sect_remove_real(H5FS_t *fspace, H5FS_section_info_t *sect)
{
const H5FS_section_class_t *cls; /* Class of section */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_remove)
+ FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_remove_real)
/* Check arguments. */
- HDassert(f);
HDassert(fspace);
HDassert(fspace->sinfo);
HDassert(sect);
@@ -628,11 +873,56 @@ H5FS_sect_remove(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't remove section from size tracking data structures")
/* Update rest of free space manager data structures for node removal */
- if(H5FS_sect_unlink_rest(f, dxpl_id, fspace, cls, sect) < 0)
+ if(H5FS_sect_unlink_rest(fspace, cls, sect) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't remove section from non-size tracking data structures")
done:
FUNC_LEAVE_NOAPI(ret_value)
+} /* H5FS_sect_remove_real() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS_sect_remove
+ *
+ * Purpose: Remove a section from the free space manager
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Wednesday, May 17, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FS_sect_remove(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
+ H5FS_section_info_t *sect)
+{
+ hbool_t sinfo_valid = FALSE; /* Whether the section info is valid */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_remove)
+
+ /* Check arguments. */
+ HDassert(f);
+ HDassert(fspace);
+ HDassert(sect);
+
+ /* Get a pointer to the section info */
+ 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;
+
+ /* Perform actual section removal */
+ if(H5FS_sect_remove_real(fspace, sect) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove section")
+
+done:
+ /* Release the section info */
+ if(sinfo_valid && H5FS_sinfo_unlock(f, dxpl_id, fspace, TRUE) < 0)
+ HDONE_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't release section info")
+
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_sect_remove() */
@@ -750,7 +1040,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_sect_link_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, const H5FS_section_class_t *cls,
+H5FS_sect_link_rest(H5FS_t *fspace, const H5FS_section_class_t *cls,
H5FS_section_info_t *sect, unsigned flags)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -758,7 +1048,6 @@ H5FS_sect_link_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, const H5FS_section_
FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_link_rest)
/* Check arguments. */
- HDassert(f);
HDassert(fspace);
HDassert(fspace->sinfo);
HDassert(sect);
@@ -776,7 +1065,7 @@ HDfprintf(stderr, "%s: inserting object into merge list, sect->type = %u\n", FUN
} /* end if */
/* Update section info & check if we need more room for the serialized free space sections */
- if(H5FS_sect_increase(f, dxpl_id, fspace, cls, flags) < 0)
+ if(H5FS_sect_increase(fspace, cls, flags) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't increase free space section size on disk")
/* Increment amount of free space managed */
@@ -802,8 +1091,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_sect_link(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
- H5FS_section_info_t *sect, unsigned flags)
+H5FS_sect_link(H5FS_t *fspace, H5FS_section_info_t *sect, unsigned flags)
{
const H5FS_section_class_t *cls; /* Class of section */
herr_t ret_value = SUCCEED; /* Return value */
@@ -811,7 +1099,6 @@ H5FS_sect_link(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_link)
/* Check arguments. */
- HDassert(f);
HDassert(fspace);
HDassert(fspace->sinfo);
HDassert(sect);
@@ -830,7 +1117,7 @@ HDfprintf(stderr, "%s: Check 1.0 - fspace->tot_space = %Hu\n", FUNC, fspace->tot
HDfprintf(stderr, "%s: Check 2.0 - fspace->tot_space = %Hu\n", FUNC, fspace->tot_space);
#endif /* QAK */
/* Update rest of free space manager data structures for section addition */
- if(H5FS_sect_link_rest(f, dxpl_id, fspace, cls, sect, flags) < 0)
+ if(H5FS_sect_link_rest(fspace, cls, sect, flags) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't add section to non-size tracking data structures")
#ifdef QAK
HDfprintf(stderr, "%s: Check 3.0 - fspace->tot_space = %Hu\n", FUNC, fspace->tot_space);
@@ -841,6 +1128,7 @@ done:
} /* H5FS_sect_link() */
+
/*-------------------------------------------------------------------------
* Function: H5FS_sect_merge
*
@@ -848,21 +1136,26 @@ done:
* free space.
*
* Return: Success: non-negative
- *
* Failure: negative
*
* Programmer: Quincey Koziol
* Wednesday, May 17, 2006
*
+ * Modifications: Vailin Choi; Sept 25th 2008
+ * Changes to the "shrinking" part--
+ * 1. Get last section node in merge-list instead of "less-than"
+ * node for further iteration
+ * 2. Remove "can-be-shrunk" section from free-space instead of
+ * "less-than" section
+ *
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
- H5FS_section_info_t **sect, void *op_data)
+H5FS_sect_merge(H5FS_t *fspace, H5FS_section_info_t **sect, void *op_data)
{
H5FS_section_class_t *sect_cls; /* Section's class */
- H5FS_section_info_t *tmp_sect_node; /* Temporary free space section */
hbool_t modified; /* Flag to indicate merge or shrink occurred */
+ hbool_t remove_sect = FALSE; /* Whether a section should be removed before shrinking */
htri_t status; /* Status value */
herr_t ret_value = SUCCEED; /* Return value */
@@ -877,43 +1170,54 @@ H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
/* Loop until no more merging */
if(fspace->sinfo->merge_list) {
do {
+ H5SL_node_t *less_sect_node; /* Skip list node for section less than new section */
+ H5SL_node_t *greater_sect_node; /* Skip list node for section greater than new section */
+ H5FS_section_info_t *tmp_sect; /* Temporary free space section */
H5FS_section_class_t *tmp_sect_cls; /* Temporary section's class */
+ hbool_t greater_sect_node_valid = FALSE; /* Indicate if 'greater than' section node is valid */
/* Reset 'modification occurred' flag */
modified = FALSE;
/* Look for neighboring section before new section */
- tmp_sect_node = (H5FS_section_info_t *)H5SL_less(fspace->sinfo->merge_list, &(*sect)->addr);
+ less_sect_node = H5SL_below(fspace->sinfo->merge_list, &(*sect)->addr);
/* Check for node before new node able to merge with new node */
- if(tmp_sect_node) {
+ if(less_sect_node) {
+ /* Check for node greater than section */
+ greater_sect_node = H5SL_next(less_sect_node);
+ greater_sect_node_valid = TRUE;
+
+ /* Get section for 'less than' skip list node */
+ tmp_sect = H5SL_item(less_sect_node);
+
/* Get classes for right & left sections */
- tmp_sect_cls = &fspace->sect_cls[tmp_sect_node->type];
+ tmp_sect_cls = &fspace->sect_cls[tmp_sect->type];
sect_cls = &fspace->sect_cls[(*sect)->type];
/* Check if sections of the left most class can merge with sections
* of another class & whether the sections are the same type,
* then check for 'can merge' callback
*/
- if((!(tmp_sect_cls->flags & H5FS_CLS_MERGE_SYM) || (tmp_sect_node->type == (*sect)->type))
+ if((!(tmp_sect_cls->flags & H5FS_CLS_MERGE_SYM) || (tmp_sect->type == (*sect)->type))
&& tmp_sect_cls->can_merge) {
/* Determine if the sections can merge */
- if((status = (*tmp_sect_cls->can_merge)(tmp_sect_node, *sect, op_data)) < 0)
+ if((status = (*tmp_sect_cls->can_merge)(tmp_sect, *sect, op_data)) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't check for merging sections")
if(status > 0) {
/* Sanity check */
HDassert(tmp_sect_cls->merge);
/* Remove 'less than' node from data structures */
- if(H5FS_sect_remove(f, dxpl_id, fspace, tmp_sect_node) < 0)
+ if(H5FS_sect_remove_real(fspace, tmp_sect) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures")
/* Merge the two sections together */
- if((*tmp_sect_cls->merge)(tmp_sect_node, *sect, op_data) < 0)
+ if((*tmp_sect_cls->merge)(tmp_sect, *sect, op_data) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't merge two sections")
/* Retarget section pointer to 'less than' node that was merged into */
- *sect = tmp_sect_node;
+ *sect = tmp_sect;
/* Indicate successful merge occurred */
modified = TRUE;
@@ -921,35 +1225,39 @@ H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
} /* end if */
} /* end if */
- /* Look for section after new (or merged) section */
- tmp_sect_node = (H5FS_section_info_t *)H5SL_greater(fspace->sinfo->merge_list, &(*sect)->addr);
+ /* Look for section after new (or merged) section, if not already determined */
+ if(!greater_sect_node_valid)
+ greater_sect_node = H5SL_above(fspace->sinfo->merge_list, &(*sect)->addr);
/* Check for node after new node able to merge with new node */
- if(tmp_sect_node) {
+ if(greater_sect_node) {
+ /* Get section for 'greater than' skip list node */
+ tmp_sect = H5SL_item(greater_sect_node);
+
/* Get classes for right & left sections */
sect_cls = &fspace->sect_cls[(*sect)->type];
- tmp_sect_cls = &fspace->sect_cls[tmp_sect_node->type];
+ tmp_sect_cls = &fspace->sect_cls[tmp_sect->type];
/* Check if sections of the left most class can merge with sections
* of another class & whether the sections are the same type,
* then check for 'can merge' callback
*/
- if((!(sect_cls->flags & H5FS_CLS_MERGE_SYM) || ((*sect)->type == tmp_sect_node->type))
+ if((!(sect_cls->flags & H5FS_CLS_MERGE_SYM) || ((*sect)->type == tmp_sect->type))
&& sect_cls->can_merge) {
/* Determine if the sections can merge */
- if((status = (*sect_cls->can_merge)(*sect, tmp_sect_node, op_data)) < 0)
+ if((status = (*sect_cls->can_merge)(*sect, tmp_sect, op_data)) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't check for merging sections")
if(status > 0) {
/* Sanity check */
HDassert(sect_cls->merge);
/* Remove 'greater than' node from data structures */
- if(H5FS_sect_remove(f, dxpl_id, fspace, tmp_sect_node) < 0)
+ if(H5FS_sect_remove_real(fspace, tmp_sect) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures")
/* Merge the two sections together */
- if((*sect_cls->merge)(*sect, tmp_sect_node, op_data) < 0)
+ if((*sect_cls->merge)(*sect, tmp_sect, op_data) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't merge two sections")
/* Indicate successful merge occurred */
@@ -957,7 +1265,7 @@ H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
} /* end if */
} /* end if */
} /* end if */
- } while(modified);
+ } while(modified);
} /* end if */
HDassert(*sect);
#ifdef QAK
@@ -978,15 +1286,14 @@ HDfprintf(stderr, "%s: Done merging, (*sect) = {%a, %Hu, %u, %s}\n", FUNC, (*sec
#ifdef QAK
HDfprintf(stderr, "%s: Can shrink!\n", FUNC);
#endif /* QAK */
- /* Look for neighboring section before new section */
- if(fspace->sinfo->merge_list) {
- tmp_sect_node = (H5FS_section_info_t *)H5SL_less(fspace->sinfo->merge_list, &(*sect)->addr);
- /* Make certain there isn't a section after the new section */
- HDassert(H5SL_greater(fspace->sinfo->merge_list, &(*sect)->addr) == NULL);
- } /* end if */
- else
- tmp_sect_node = NULL;
+ /* Remove SECT from free-space manager */
+ /* (only possible to happen on second+ pass through loop) */
+ if(remove_sect) {
+ if(H5FS_sect_remove_real(fspace, *sect) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures")
+ remove_sect = FALSE;
+ } /* end if */
/* Shrink the container */
/* (callback can indicate that it has discarded the section by setting *sect to NULL) */
@@ -994,20 +1301,34 @@ HDfprintf(stderr, "%s: Can shrink!\n", FUNC);
if((*sect_cls->shrink)(sect, op_data) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't shrink free space container")
- /* Check if the new section was removed */
- if(*sect == NULL && tmp_sect_node) {
- /* Remove 'less than' node from data structures */
- if(H5FS_sect_remove(f, dxpl_id, fspace, tmp_sect_node) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures")
-
- *sect = tmp_sect_node;
- } /* end if */
+ /* If this section was shrunk away, we may need to shrink another section */
+ if(*sect == NULL) {
+ /* Check for sections on merge list */
+ if(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))) {
+ /* Get the pointer to the last section, from the last node */
+ *sect = H5SL_item(last_node);
+ HDassert(*sect);
+
+ /* Indicate that this section needs to be removed if it causes a shrink */
+ remove_sect = TRUE;
+ } /* end if */
+ } /* end if */
+ } /* end if */
/* Indicate successful merge occurred */
modified = TRUE;
} /* end if */
} /* end if */
} while(modified && *sect);
+
+ /* Check for section that was shrunk away and next section not shrinking */
+ if(remove_sect && (*sect != NULL))
+ *sect = NULL;
+
#ifdef QAK
HDfprintf(stderr, "%s: Done shrinking\n", FUNC);
if(*sect)
@@ -1043,13 +1364,15 @@ H5FS_sect_add(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *sect
unsigned flags, void *op_data)
{
H5FS_section_class_t *cls; /* Section's class */
+ hbool_t sinfo_valid = FALSE; /* Whether the section info is valid */
+ hbool_t sinfo_modified = FALSE; /* Whether the section info was modified */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5FS_sect_add, FAIL)
-#ifdef QAK
+#ifdef H5FS_SINFO_DEBUG
HDfprintf(stderr, "%s: *sect = {%a, %Hu, %u, %s}\n", FUNC, sect->addr, sect->size, sect->type, (sect->state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED"));
-#endif /* QAK */
+#endif /* H5FS_SINFO_DEBUG */
/* Check arguments. */
HDassert(fspace);
@@ -1057,11 +1380,10 @@ HDfprintf(stderr, "%s: *sect = {%a, %Hu, %u, %s}\n", FUNC, sect->addr, sect->siz
HDassert(H5F_addr_defined(sect->addr));
HDassert(sect->size);
- /* Check if we need to go get the sections */
- if(fspace->sinfo == NULL) {
- if(NULL == (fspace->sinfo = H5FS_sinfo_pin(f, dxpl_id, fspace)))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTDECODE, FAIL, "can't pin sections")
- } /* end if */
+ /* Get a pointer to the section info */
+ 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;
/* Call "add" section class callback, if there is one */
cls = &fspace->sect_cls[sect->type];
@@ -1072,12 +1394,12 @@ HDfprintf(stderr, "%s: *sect = {%a, %Hu, %u, %s}\n", FUNC, sect->addr, sect->siz
/* Check for merging returned space with existing section node */
if(flags & H5FS_ADD_RETURNED_SPACE) {
-#ifdef QAK
+#ifdef H5FS_SINFO_DEBUG
HDfprintf(stderr, "%s: Returning space\n", FUNC);
-#endif /* QAK */
+#endif /* H5FS_SINFO_DEBUG */
/* Attempt to merge returned section with existing sections */
- if(H5FS_sect_merge(f, dxpl_id, fspace, &sect, op_data) < 0)
+ if(H5FS_sect_merge(fspace, &sect, op_data) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't merge sections")
} /* end if */
@@ -1086,29 +1408,157 @@ HDfprintf(stderr, "%s: Returning space\n", FUNC);
* be NULL at this point - QAK)
*/
if(sect)
- if(H5FS_sect_link(f, dxpl_id, fspace, sect, flags) < 0)
+ if(H5FS_sect_link(fspace, sect, flags) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space section into skip list")
-#ifdef QAK
-HDfprintf(stderr, "%s: fspace->hdr->tot_space = %Hu\n", FUNC, fspace->hdr->tot_space);
-#endif /* QAK */
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: fspace->tot_space = %Hu\n", FUNC, fspace->tot_space);
+#endif /* H5FS_SINFO_DEBUG */
/* Mark free space sections as changed */
/* (if adding sections while deserializing sections, don't set the flag) */
- if(!(flags & H5FS_ADD_DESERIALIZING)) {
- if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace->sinfo) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space sections as dirty")
- } /* end if */
+ if(!(flags & H5FS_ADD_DESERIALIZING))
+ sinfo_modified = TRUE;
done:
-#ifdef H5FS_DEBUG
+ /* Release the section info */
+ if(sinfo_valid && H5FS_sinfo_unlock(f, dxpl_id, fspace, sinfo_modified) < 0)
+ HDONE_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't release section info")
+
+#ifdef H5FS_DEBUG_ASSERT
if(!(flags & (H5FS_ADD_DESERIALIZING | H5FS_ADD_SKIP_VALID)))
H5FS_assert(fspace);
-#endif /* H5FS_DEBUG */
+#endif /* H5FS_DEBUG_ASSERT */
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value);
+#endif /* H5FS_SINFO_DEBUG */
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_sect_add() */
/*-------------------------------------------------------------------------
+ * Function: H5FS_sect_try_extend
+ *
+ * Purpose: Try to extend a block using space from a section on the free list
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, January 8, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5FS_sect_try_extend(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, haddr_t addr,
+ hsize_t size, hsize_t extra_requested)
+{
+ hbool_t sinfo_valid = FALSE; /* Whether the section info is valid */
+ hbool_t sinfo_modified = FALSE; /* Whether the section info was modified */
+ htri_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FS_sect_try_extend, FAIL)
+
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: addr = %a, size = %Hu, extra_requested = %hu\n", FUNC, addr, size, extra_requested);
+#endif /* H5FS_SINFO_DEBUG */
+
+ /* Check arguments. */
+ HDassert(f);
+ HDassert(fspace);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(size > 0);
+ HDassert(extra_requested > 0);
+
+ /* Check for any sections on free space list */
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu\n", FUNC, fspace->tot_sect_count);
+HDfprintf(stderr, "%s: fspace->serial_sect_count = %Hu\n", FUNC, fspace->serial_sect_count);
+HDfprintf(stderr, "%s: fspace->ghost_sect_count = %Hu\n", FUNC, fspace->ghost_sect_count);
+#endif /* H5FS_SINFO_DEBUG */
+ if(fspace->tot_sect_count > 0) {
+ H5FS_section_info_t *sect; /* Temporary free space section */
+
+ /* Get a pointer to the section info */
+ 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;
+
+
+/*
+
+Pseudo-code for algorithm:
+
+_section_ = <Get pointer to section with address > _region.addr_>
+if(_section_)
+ if(_section_ adjoins _region_ && _section.size_ >= _extra_requested_)
+ <remove section from data structures>
+ if(_section.size_ > _extra_requested_)
+ if(<can adjust _section_>)
+ <adjust _section_ by _extra_requested_>
+ <add adjusted section back to data structures>
+ else
+ <re-add UNadjusted section back to data structures>
+ <error>
+ <mark free space sections as changed in metadata cache>
+
+*/
+ /* Look for a section after block to extend */
+ if((sect = H5SL_greater(fspace->sinfo->merge_list, &addr))) {
+ /* Check if this section adjoins the block and is large enough to
+ * fulfill extension request.
+ *
+ * (Note: we assume that the section is fully merged with any
+ * possible neighboring nodes and is not at the end of the file
+ * (or it would have been eliminated), etc)
+ */
+ if(sect->size >= extra_requested && (addr + size) == sect->addr) {
+ /* Remove section from data structures */
+ if(H5FS_sect_remove_real(fspace, sect) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures")
+
+ /* Check for the section needing to be adjusted and re-added */
+ /* (Note: we should probably add a can_adjust/adjust callback
+ * to the section class structure, but we don't need it
+ * for the current usage, so I've deferred messing with
+ * it. - QAK - 2008/01/08)
+ */
+ if(sect->size > extra_requested) {
+ H5FS_section_class_t *cls; /* Section's class */
+
+ /* Get class for section */
+ cls = &fspace->sect_cls[sect->type];
+
+ /* Sanity check (for now) */
+ HDassert(cls->flags & H5FS_CLS_ADJUST_OK);
+
+ /* Adjust section by amount requested */
+ sect->addr += extra_requested;
+ sect->size -= extra_requested;
+
+ /* Re-add adjusted section to free sections data structures */
+ if(H5FS_sect_link(fspace, sect, 0) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space section into skip list")
+ } /* end if */
+
+ /* Note that we modified the section info */
+ sinfo_modified = TRUE;
+
+ /* Indicate success */
+ HGOTO_DONE(TRUE);
+ } /* end if */
+ } /* end if */
+ } /* end if */
+
+done:
+ /* Release the section info */
+ if(sinfo_valid && H5FS_sinfo_unlock(f, dxpl_id, fspace, sinfo_modified) < 0)
+ HDONE_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't release section info")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5FS_sect_try_extend() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5FS_sect_find_node
*
* Purpose: Locate a section of free space (in existing free space list
@@ -1121,6 +1571,11 @@ if(!(flags & (H5FS_ADD_DESERIALIZING | H5FS_ADD_SKIP_VALID)))
* Programmer: Quincey Koziol
* Monday, March 20, 2006
*
+ * Modifications:
+ * Vailin Choi, July 29th, 2008
+ * Modified to handle alignment by going through each bin to find
+ * a section that is big enough to fulfill "request+fragment for alignment"
+ *
*-------------------------------------------------------------------------
*/
static htri_t
@@ -1130,6 +1585,10 @@ H5FS_sect_find_node(H5FS_t *fspace, hsize_t request, H5FS_section_info_t **node)
unsigned bin; /* Bin to put the free space section in */
htri_t ret_value = FALSE; /* Return value */
+ H5SL_node_t *curr_size_node=NULL;
+ const H5FS_section_class_t *cls; /* Class of section */
+ hsize_t alignment;
+
FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_find_node)
/* Check arguments. */
@@ -1142,43 +1601,113 @@ H5FS_sect_find_node(H5FS_t *fspace, hsize_t request, H5FS_section_info_t **node)
/* Determine correct bin which holds items of at least the section's size */
bin = H5V_log2_gen(request);
HDassert(bin < fspace->sinfo->nbins);
- while(bin < fspace->sinfo->nbins && fspace->sinfo->bins[bin].bin_list == NULL)
- bin++;
-
- /* Find the first free space section that is large enough to fulfill request */
- /* (Since the bins use skip lists to track the sizes of the address-ordered
- * lists, this is actually a "best fit" algorithm)
- */
#ifdef QAK
HDfprintf(stderr, "%s: fspace->sinfo->nbins = %u\n", FUNC, fspace->sinfo->nbins);
HDfprintf(stderr, "%s: bin = %u\n", FUNC, bin);
#endif /* QAK */
- if(bin < fspace->sinfo->nbins)
- do {
- /* Look for large enough free space section in this bin */
- if(fspace->sinfo->bins[bin].bin_list)
- /* Check for large enough list of sections on list */
- if((fspace_node = (H5FS_node_t *)H5SL_greater(fspace->sinfo->bins[bin].bin_list, &request))) {
- const H5FS_section_class_t *cls; /* Class of section */
-
- /* Take first node off of the list (ie. node w/lowest address) */
- if(NULL == (*node = (H5FS_section_info_t *)H5SL_remove_first(fspace_node->sect_list)))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space node from skip list")
+ alignment = fspace->alignment;
+ if(!((alignment > 1) && (request >= fspace->threshold)))
+ alignment = 0; /* no alignment */
- /* Get section's class */
- cls = &fspace->sect_cls[(*node)->type];
+ do {
+ /* Check if there's any sections in this bin */
+ if(fspace->sinfo->bins[bin].bin_list) {
+
+ if (!alignment) { /* no alignment */
+ /* Find the first free space section that is large enough to fulfill request */
+ /* (Since the bins use skip lists to track the sizes of the address-ordered
+ * lists, this is actually a "best fit" algorithm)
+ */
+ /* Look for large enough free space section in this bin */
+ if((fspace_node = (H5FS_node_t *)H5SL_greater(fspace->sinfo->bins[bin].bin_list, &request))) {
+ /* Take first node off of the list (ie. node w/lowest address) */
+ if(NULL == (*node = (H5FS_section_info_t *)H5SL_remove_first(fspace_node->sect_list)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space node from skip list")
+
+ /* Get section's class */
+ cls = &fspace->sect_cls[(*node)->type];
+ /* Decrement # of sections in section size node */
+ if(H5FS_size_node_decr(fspace->sinfo, bin, fspace_node, cls) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space size node from skip list")
+ if(H5FS_sect_unlink_rest(fspace, cls, *node) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't remove section from non-size tracking data structures")
+ /* Indicate that we found a node for the request */
+ HGOTO_DONE(TRUE)
+ } /* end if */
+ } /* end if */
+ else { /* alignment is set */
+ /* get the first node of a certain size in this bin */
+ curr_size_node = H5SL_first(fspace->sinfo->bins[bin].bin_list);
+ while (curr_size_node != NULL) {
+ H5FS_node_t *curr_fspace_node=NULL;
+ H5SL_node_t *curr_sect_node=NULL;
+
+ /* Get the free space node for free space sections of the same size */
+ curr_fspace_node = H5SL_item(curr_size_node);
+
+ /* Get the Skip list which holds pointers to actual free list sections */
+ curr_sect_node = H5SL_first(curr_fspace_node->sect_list);
- /* Decrement # of sections in section size node */
- if(H5FS_size_node_decr(fspace->sinfo, bin, fspace_node, cls) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space size node from skip list")
+ while(curr_sect_node != NULL) {
+ H5FS_section_info_t *curr_sect=NULL;
+ hsize_t mis_align=0, frag_size=0;
+ H5FS_section_info_t *split_sect=NULL;
+
+ /* Get section node */
+ curr_sect = H5SL_item(curr_sect_node);
+
+ HDassert(H5F_addr_defined(curr_sect->addr));
+ HDassert(curr_fspace_node->sect_size == curr_sect->size);
+
+ cls = &fspace->sect_cls[curr_sect->type];
+
+ HDassert(alignment);
+ HDassert(cls);
+
+ if ((mis_align = curr_sect->addr % alignment))
+ frag_size = alignment - mis_align;
+
+ if ((curr_sect->size >= (request + frag_size)) && (cls->split)) {
+ /* remove the section with aligned address */
+ if(NULL == (*node = H5SL_remove(curr_fspace_node->sect_list, &curr_sect->addr)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space node from skip list")
+ /* Decrement # of sections in section size node */
+ if(H5FS_size_node_decr(fspace->sinfo, bin, curr_fspace_node, cls) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space size node from skip list")
+
+ if(H5FS_sect_unlink_rest(fspace, cls, *node) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't remove section from non-size tracking data structures")
+
+ /*
+ * The split() callback splits NODE into 2 sections:
+ * split_sect is the unused fragment for aligning NODE
+ * NODE's addr & size are updated to point to the remaining aligned section
+ * split_sect is re-added to free-space
+ */
+ if (mis_align) {
+ split_sect = cls->split(*node, frag_size);
+ if((H5FS_sect_link(fspace, split_sect, 0) < 0))
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space section into skip list")
+ /* sanity check */
+ HDassert(split_sect->addr < (*node)->addr);
+ HDassert(request <= (*node)->size);
+ }
+ /* Indicate that we found a node for the request */
+ HGOTO_DONE(TRUE)
+ }
- /* Indicate that we found a node for the request */
- HGOTO_DONE(TRUE)
- } /* end if */
+ /* Get the next section node in the list */
+ curr_sect_node = H5SL_next(curr_sect_node);
+ } /* end while of curr_sect_node */
- /* Advance to next larger bin */
- bin++;
- } while(bin < fspace->sinfo->nbins);
+ /* Get the next size node in the bin */
+ curr_size_node = H5SL_next(curr_size_node);
+ } /* end while of curr_size_node */
+ } /* else of alignment */
+ } /* if bin_list */
+ /* Advance to next larger bin */
+ bin++;
+ } while(bin < fspace->sinfo->nbins);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1198,12 +1727,18 @@ done:
* Programmer: Quincey Koziol
* Tuesday, March 7, 2006
*
+ * Modifications:
+ * Vailin Choi, July 29th 2008
+ * Move H5FS_sect_unlink_rest() to H5FS_sect_find_node()
+ *
*-------------------------------------------------------------------------
*/
htri_t
H5FS_sect_find(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, hsize_t request,
H5FS_section_info_t **node)
{
+ hbool_t sinfo_valid = FALSE; /* Whether the section info is valid */
+ hbool_t sinfo_modified = FALSE; /* Whether the section info was modified */
htri_t ret_value = FALSE; /* Return value */
FUNC_ENTER_NOAPI(H5FS_sect_find, FAIL)
@@ -1225,11 +1760,10 @@ HDfprintf(stderr, "%s: fspace->serial_sect_count = %Hu\n", FUNC, fspace->serial_
HDfprintf(stderr, "%s: fspace->ghost_sect_count = %Hu\n", FUNC, fspace->ghost_sect_count);
#endif /* QAK */
if(fspace->tot_sect_count > 0) {
- /* Check if we need to go get the sections */
- if(fspace->sinfo == NULL) {
- if(NULL == (fspace->sinfo = H5FS_sinfo_pin(f, dxpl_id, fspace)))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTDECODE, FAIL, "can't pin sections")
- } /* end if */
+ /* Get a pointer to the section info */
+ 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;
/* Look for node in bins */
if((ret_value = H5FS_sect_find_node(fspace, request, node)) < 0)
@@ -1237,209 +1771,27 @@ HDfprintf(stderr, "%s: fspace->ghost_sect_count = %Hu\n", FUNC, fspace->ghost_se
/* Decrement # of sections on free list, if we found an object */
if(ret_value > 0) {
- const H5FS_section_class_t *cls; /* Class of section */
-
- /* Get section's class */
- cls = &fspace->sect_cls[(*node)->type];
-
- /* Update rest of free space manager data structures for node removal */
- if(H5FS_sect_unlink_rest(f, dxpl_id, fspace, cls, *node) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't remove section from non-size tracking data structures")
+ /* Note that we've modified the section info */
+ sinfo_modified = TRUE;
#ifdef QAK
HDfprintf(stderr, "%s: (*node)->size = %Hu, (*node)->addr = %a, (*node)->type = %u\n", FUNC, (*node)->size, (*node)->addr, (*node)->type);
#endif /* QAK */
- } /* end if */
+ }
} /* end if */
done:
-#ifdef H5FS_DEBUG
+ /* Release the section info */
+ if(sinfo_valid && H5FS_sinfo_unlock(f, dxpl_id, fspace, sinfo_modified) < 0)
+ HDONE_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't release section info")
+
+#ifdef H5FS_DEBUG_ASSERT
H5FS_assert(fspace);
-#endif /* H5FS_DEBUG */
+#endif /* H5FS_DEBUG_ASSERT */
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_sect_find() */
/*-------------------------------------------------------------------------
- * Function: H5FS_sect_serialize_size
- *
- * Purpose: Determine serialized size of all sections in free space manager
- * And adjust space on disk for storing serialized sections
- *
- * Return: Success: non-negative
- * Failure: negative
- *
- * Programmer: Quincey Koziol
- * Monday, May 8, 2006
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5FS_sect_serialize_size(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_serialize_size)
-
- /* Check arguments. */
- HDassert(fspace);
-#ifdef QAK
-HDfprintf(stderr, "%s: Check 1.0 - fspace->sect_size = %Hu\n", FUNC, fspace->sect_size);
-HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu\n", FUNC, fspace->alloc_sect_size);
-HDfprintf(stderr, "%s: fspace->sinfo->serial_size_count = %Zu\n", FUNC, fspace->sinfo->serial_size_count);
-#endif /* QAK */
-
- /* Compute the size of the buffer required to serialize all the sections */
- if(fspace->serial_sect_count > 0) {
- size_t sect_buf_size; /* Section buffer size */
-
- /* Serialized sections prefix */
- sect_buf_size = fspace->sinfo->sect_prefix_size;
-
- /* Count for each differently sized serializable section */
-#ifdef QAK
-HDfprintf(stderr, "%s: fspace->sinfo->serial_size_count = %Zu\n", FUNC, fspace->sinfo->serial_size_count);
-HDfprintf(stderr, "%s: fspace->serial_sect_count = %Hu\n", FUNC, fspace->serial_sect_count);
-#endif /* QAK */
- sect_buf_size += fspace->sinfo->serial_size_count * H5V_limit_enc_size((uint64_t)fspace->serial_sect_count);
-
- /* Size for each differently sized serializable section */
- sect_buf_size += fspace->sinfo->serial_size_count * fspace->sinfo->sect_len_size;
-
- /* Offsets of each section in address space */
- sect_buf_size += fspace->serial_sect_count * fspace->sinfo->sect_off_size;
-
- /* Class of each section */
- sect_buf_size += fspace->serial_sect_count * 1;
-
- /* Extra space required to serialize each section */
- sect_buf_size += fspace->sinfo->serial_size;
-
- /* Update section size in header */
- fspace->sect_size = sect_buf_size;
- } /* end if */
- else
- /* Reset section size in header */
- fspace->sect_size = H5FS_SINFO_SIZE_DEFAULT;
-
-#ifdef QAK
-HDfprintf(stderr, "%s: Check 2.0 - fspace->sect_size = %Hu\n", FUNC, fspace->sect_size);
-HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu\n", FUNC, fspace->alloc_sect_size);
-#endif /* QAK */
- if(fspace->sect_size > fspace->alloc_sect_size) {
- size_t new_size; /* New size of space for serialized sections */
- haddr_t old_addr; /* Old address of serialized sections */
-
-/* Currently, the old block data is "thrown away" after the space is reallocated,
- * so avoid data copy in H5MF_realloc() call by just free'ing the space and
- * allocating new space.
- *
- * This also keeps the file smaller, by freeing the space and then
- * allocating new space, instead of vice versa (in H5MF_realloc).
- *
- * QAK - 5/ 8/2006
- */
- /* Free previous serialized sections disk space */
- old_addr = fspace->sect_addr;
- if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, old_addr, fspace->alloc_sect_size) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space sections")
-
- /* Compute new size */
- H5_ASSIGN_OVERFLOW(/* To: */ new_size, /* From: */ fspace->alloc_sect_size, /* From: */ hsize_t, /* To: */ size_t);
- while(new_size < fspace->sect_size)
- new_size *= (double)fspace->expand_percent / 100.0;
- fspace->alloc_sect_size = new_size;
-
- /* Allocate space for the new serialized sections on disk */
-#ifdef QAK
-HDfprintf(stderr, "%s: Allocating space for larger serialized sections, new_size = %Zu\n", FUNC, new_size);
-HDfprintf(stderr, "%s: fspace->sect_size = %Hu\n", FUNC, fspace->sect_size);
-#endif /* QAK */
- if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, (hsize_t)fspace->alloc_sect_size)))
- HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
-#ifdef QAK
-HDfprintf(stderr, "%s: old_addr = %a, fspace->sect_addr = %a\n", FUNC, old_addr, fspace->sect_addr);
-#endif /* QAK */
-
- /* Move object in cache, if it actually was relocated */
- if(H5F_addr_ne(fspace->sect_addr, old_addr)) {
- if(H5AC_rename(f, H5AC_FSPACE_SINFO, old_addr, fspace->sect_addr) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTRENAME, FAIL, "unable to move free space section info")
- } /* end if */
- else {
- /* Mark free space section as dirty */
- if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace->sinfo) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space section info as dirty")
- } /* end else */
-
- /* Mark free space header as dirty */
- if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty")
- } /* end if */
- else {
- size_t decrease_threshold; /* Size threshold for decreasing serialized section size */
- haddr_t old_addr; /* Old address of serialized sections */
-
- /* Compute the threshold for decreasing the sections' serialized size */
- decrease_threshold = (size_t)(((size_t)fspace->alloc_sect_size * (double)fspace->shrink_percent) / 100.0);
-
- if(fspace->alloc_sect_size > H5FS_SINFO_SIZE_DEFAULT &&
- fspace->sect_size < decrease_threshold) {
- size_t new_size = 0; /* New size of space for serialized sections */
-
-/* Currently, the old block data is "thrown away" after the space is reallocated,
- * so avoid data copy in H5MF_realloc() call by just free'ing the space and
- * allocating new space.
- *
- * This also keeps the file smaller, by freeing the space and then
- * allocating new space, instead of vice versa (in H5MF_realloc).
- *
- * QAK - 5/ 8/2006
- */
- /* Free previous serialized sections disk space */
- old_addr = fspace->sect_addr;
- if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, old_addr, fspace->alloc_sect_size) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space sections")
-
- /* Compute new size */
- while(fspace->sect_size < decrease_threshold) {
- new_size = decrease_threshold;
-
- decrease_threshold *= (double)fspace->shrink_percent / 100.0;
- } /* end while */
- if(new_size < H5FS_SINFO_SIZE_DEFAULT)
- new_size = H5FS_SINFO_SIZE_DEFAULT;
- fspace->alloc_sect_size = new_size;
-
- /* Allocate space for the new serialized sections on disk */
-#ifdef QAK
-HDfprintf(stderr, "%s: Allocating space for smaller serialized sections, new_size = %Zu\n", FUNC, new_size);
-#endif /* QAK */
- if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, (hsize_t)fspace->alloc_sect_size)))
- HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
-
- /* Move object in cache, if it actually was relocated */
- if(H5F_addr_ne(fspace->sect_addr, old_addr)) {
- if(H5AC_rename(f, H5AC_FSPACE_SINFO, old_addr, fspace->sect_addr) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTRENAME, FAIL, "unable to move free space section info")
- } /* end if */
- else {
- /* Mark free space section as dirty */
- if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace->sinfo) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space section info as dirty")
- } /* end else */
-
- /* Mark free space header as dirty */
- if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty")
- } /* end if */
- } /* end else */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5FS_sect_serialize_size() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5FS_iterate_sect_cb
*
* Purpose: Skip list iterator callback to iterate over free space sections
@@ -1533,7 +1885,8 @@ done:
herr_t
H5FS_sect_iterate(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_operator_t op, void *op_data)
{
- H5FS_iter_ud_t udata; /* User data for callbacks */
+ H5FS_iter_ud_t udata; /* User data for callbacks */
+ hbool_t sinfo_valid = FALSE; /* Whether the section info is valid */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_iterate)
@@ -1542,14 +1895,8 @@ H5FS_sect_iterate(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_operator_t op, v
HDassert(fspace);
HDassert(op);
- /* Check if we need to go get the sections */
- if(fspace->sinfo == NULL) {
- if(NULL == (fspace->sinfo = H5FS_sinfo_pin(f, dxpl_id, fspace)))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTDECODE, FAIL, "can't pin sections")
- } /* end if */
-
#ifdef QAK
-HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect_count);
+HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu\n", FUNC, fspace->tot_sect_count);
#endif /* QAK */
/* Set up user data for iterator */
@@ -1561,6 +1908,11 @@ HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect
if(fspace->tot_sect_count) {
unsigned bin; /* Current bin we are on */
+ /* Get a pointer to the section info */
+ if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC_READ) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't get section info")
+ sinfo_valid = TRUE;
+
/* Iterate over all the bins */
#ifdef QAK
HDfprintf(stderr, "%s: Iterate over section bins\n", FUNC);
@@ -1576,17 +1928,20 @@ HDfprintf(stderr, "%s: Iterate over section bins\n", FUNC);
} /* end if */
done:
+ /* Release the section info */
+ if(sinfo_valid && H5FS_sinfo_unlock(f, dxpl_id, fspace, FALSE) < 0)
+ HDONE_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't release section info")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_sect_iterate() */
/*-------------------------------------------------------------------------
- * Function: H5FS_get_sect_count
+ * Function: H5FS_sect_stats
*
- * Purpose: Retrieve the number of sections managed
+ * Purpose: Retrieve info about the sections managed
*
* Return: Success: non-negative
- *
* Failure: negative
*
* Programmer: Quincey Koziol
@@ -1595,19 +1950,21 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5FS_get_sect_count(const H5FS_t *fspace, hsize_t *nsects)
+H5FS_sect_stats(const H5FS_t *fspace, hsize_t *tot_space, hsize_t *nsects)
{
- FUNC_ENTER_NOAPI_NOFUNC(H5FS_get_sect_count)
+ FUNC_ENTER_NOAPI_NOFUNC(H5FS_sect_stats)
/* Check arguments. */
HDassert(fspace);
- HDassert(nsects);
- /* Get the section count */
- *nsects = fspace->tot_sect_count;
+ /* Get the stats desired */
+ if(tot_space)
+ *tot_space = fspace->tot_space;
+ if(nsects)
+ *nsects = fspace->tot_sect_count;
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5FS_get_sect_count() */
+} /* H5FS_sect_stats() */
/*-------------------------------------------------------------------------
@@ -1632,17 +1989,22 @@ H5FS_sect_change_class(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
const H5FS_section_class_t *old_cls; /* Old class of section */
const H5FS_section_class_t *new_cls; /* New class of section */
unsigned old_class; /* Old class ID of section */
+ hbool_t sinfo_valid = FALSE; /* Whether the section info is valid */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_change_class)
/* Check arguments. */
HDassert(fspace);
- HDassert(fspace->sinfo);
HDassert(sect);
HDassert(sect->type < fspace->nclasses);
HDassert(new_class < fspace->nclasses);
+ /* Get a pointer to the section info */
+ 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;
+
/* Get class info */
old_class = sect->type;
old_cls = &fspace->sect_cls[sect->type];
@@ -1764,18 +2126,18 @@ HDfprintf(stderr, "%s: removing object from merge list, sect->type = %u\n", FUNC
fspace->sinfo->serial_size += fspace->sect_cls[new_class].serial_size;
/* Update current space used for free space sections */
- if(H5FS_sect_serialize_size(f, dxpl_id, fspace) < 0)
+ if(H5FS_sect_serialize_size(fspace) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTCOMPUTE, FAIL, "can't adjust free space section size on disk")
- /* Mark free space sections as dirty */
- if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace->sinfo) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space sections as dirty")
-
done:
+ /* Release the section info */
+ if(sinfo_valid && H5FS_sinfo_unlock(f, dxpl_id, fspace, TRUE) < 0)
+ HDONE_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't release section info")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_sect_change_class() */
-#ifdef H5FS_DEBUG
+#ifdef H5FS_DEBUG_ASSERT
/*-------------------------------------------------------------------------
* Function: H5FS_sect_assert
@@ -1796,8 +2158,8 @@ H5FS_sect_assert(const H5FS_t *fspace)
hsize_t separate_obj; /* The number of separate objects managed */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_sect_assert)
-#ifdef QAK
-HDfprintf(stderr, "%s: fspace->hdr->tot_sect_count = %Hu\n", "H5FS_sect_assert", fspace->hdr->tot_sect_count);
+#ifndef QAK
+HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu\n", "H5FS_sect_assert", fspace->tot_sect_count);
#endif /* QAK */
/* Initialize state */
@@ -1925,5 +2287,5 @@ HDfprintf(stderr, "%s: sect->size = %Hu, sect->addr = %a, sect->type = %u\n", "H
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5FS_sect_assert() */
-#endif /* H5FS_DEBUG */
+#endif /* H5FS_DEBUG_ASSERT */