summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2008-10-07 04:17:35 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2008-10-07 04:17:35 (GMT)
commit9f60f016ab71cf8ce39c859fd9eb61c6fca35d63 (patch)
tree0ddbcb2f8707b578af22c62748420b9e3c19177b /src
parent504c67846e6a4cc5706403bf21a9ae4f07aae7b4 (diff)
downloadhdf5-9f60f016ab71cf8ce39c859fd9eb61c6fca35d63.zip
hdf5-9f60f016ab71cf8ce39c859fd9eb61c6fca35d63.tar.gz
hdf5-9f60f016ab71cf8ce39c859fd9eb61c6fca35d63.tar.bz2
[svn-r15800] Description:
Bring file free space branch changes through r15795 into trunk, which includes a fair bit of code cleanup & rearrangement along with a couple of bug fixes also. Tested on: Mac OS X/32 10.5.5 (amazon) in debug mode Mac OS X/32 10.5.5 (amazon) w/C++ & FORTRAN, w/threadsafe, in production mode FreeBSD/32 6.3 (duty) in debug mode FreeBSD/64 6.3 (liberty) w/C++ & FORTRAN, in debug mode Linux/32 2.6 (kagiso) w/PGI compilers, w/C++ & FORTRAN, w/threadsafe, in debug mode Linux/64-amd64 2.6 (smirom) w/Intel compilers w/default API=1.6.x, w/C++ & FORTRAN, in production mode Solaris/32 2.10 (linew) w/deprecated symbols disabled, w/C++ & FORTRAN, w/szip filter, in production mode Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN, in production mode Linux/64-ia64 2.4 (tg-login3) w/parallel, w/FORTRAN, in production mode Linux/64-amd64 2.6 (abe) w/parallel, w/FORTRAN, in production mode
Diffstat (limited to 'src')
-rw-r--r--src/H5AC.c16
-rw-r--r--src/H5ACprivate.h5
-rw-r--r--src/H5Adense.c20
-rw-r--r--src/H5B.c105
-rw-r--r--src/H5B2.c32
-rw-r--r--src/H5B2cache.c65
-rw-r--r--src/H5B2int.c41
-rw-r--r--src/H5B2private.h2
-rw-r--r--src/H5Bcache.c30
-rw-r--r--src/H5Bprivate.h2
-rw-r--r--src/H5C.c82
-rw-r--r--src/H5Cprivate.h17
-rw-r--r--src/H5Dchunk.c93
-rw-r--r--src/H5Dcontig.c22
-rw-r--r--src/H5Dint.c45
-rw-r--r--src/H5Distore.c40
-rw-r--r--src/H5Dmpio.c32
-rw-r--r--src/H5Dpkg.h4
-rw-r--r--src/H5EAcache.c76
-rw-r--r--src/H5EAdblock.c6
-rw-r--r--src/H5EAhdr.c6
-rw-r--r--src/H5EAiblock.c6
-rw-r--r--src/H5EAsblock.c6
-rw-r--r--src/H5F.c961
-rw-r--r--src/H5FD.c864
-rw-r--r--src/H5FDcore.c2
-rw-r--r--src/H5FDdirect.c20
-rw-r--r--src/H5FDfamily.c89
-rw-r--r--src/H5FDint.c297
-rw-r--r--src/H5FDlog.c21
-rw-r--r--src/H5FDmpi.h1
-rw-r--r--src/H5FDmpio.c116
-rw-r--r--src/H5FDmpio.h2
-rw-r--r--src/H5FDmpiposix.c34
-rw-r--r--src/H5FDmpiposix.h3
-rw-r--r--src/H5FDmulti.c64
-rw-r--r--src/H5FDpkg.h4
-rw-r--r--src/H5FDprivate.h26
-rw-r--r--src/H5FDpublic.h41
-rw-r--r--src/H5FDsec2.c57
-rw-r--r--src/H5FDspace.c1611
-rw-r--r--src/H5FDstdio.c88
-rw-r--r--src/H5FDwindows.c158
-rw-r--r--src/H5FS.c462
-rw-r--r--src/H5FScache.c118
-rw-r--r--src/H5FSdbg.c21
-rw-r--r--src/H5FSpkg.h31
-rw-r--r--src/H5FSprivate.h32
-rw-r--r--src/H5FSsection.c1202
-rw-r--r--src/H5FSstat.c101
-rw-r--r--src/H5FStest.c154
-rw-r--r--src/H5Faccum.c655
-rw-r--r--src/H5Fdbg.c4
-rw-r--r--src/H5Fio.c165
-rw-r--r--src/H5Fmpi.c181
-rw-r--r--src/H5Fpkg.h56
-rw-r--r--src/H5Fprivate.h79
-rw-r--r--src/H5Fquery.c663
-rw-r--r--src/H5Fsuper.c93
-rw-r--r--src/H5G.c29
-rw-r--r--src/H5Gcache.c470
-rw-r--r--src/H5Gcompact.c11
-rw-r--r--src/H5Gdense.c8
-rw-r--r--src/H5Gdeprec.c8
-rw-r--r--src/H5Gnode.c460
-rw-r--r--src/H5Gobj.c106
-rw-r--r--src/H5Gpkg.h24
-rw-r--r--src/H5Gstab.c8
-rw-r--r--src/H5Gtest.c6
-rw-r--r--src/H5Gtraverse.c60
-rw-r--r--src/H5HFcache.c52
-rw-r--r--src/H5HFdblock.c32
-rw-r--r--src/H5HFhdr.c15
-rw-r--r--src/H5HFhuge.c10
-rw-r--r--src/H5HFiblock.c21
-rw-r--r--src/H5HFpkg.h1
-rw-r--r--src/H5HFsection.c4
-rw-r--r--src/H5HFspace.c14
-rw-r--r--src/H5HG.c707
-rw-r--r--src/H5HGcache.c442
-rw-r--r--src/H5HGpkg.h56
-rw-r--r--src/H5HL.c669
-rw-r--r--src/H5HLcache.c478
-rw-r--r--src/H5HLpkg.h19
-rw-r--r--src/H5MF.c797
-rw-r--r--src/H5MFaggr.c571
-rw-r--r--src/H5MFdbg.c217
-rw-r--r--src/H5MFpkg.h175
-rw-r--r--src/H5MFprivate.h48
-rw-r--r--src/H5MFsection.c526
-rw-r--r--src/H5O.c10
-rw-r--r--src/H5Oalloc.c23
-rw-r--r--src/H5Ocache.c42
-rw-r--r--src/H5Omessage.c2
-rw-r--r--src/H5Oprivate.h2
-rw-r--r--src/H5Plapl.c2
-rw-r--r--src/H5SL.c181
-rw-r--r--src/H5SLprivate.h2
-rwxr-xr-xsrc/H5SM.c40
-rw-r--r--src/H5SMcache.c25
-rw-r--r--src/H5Spoint.c4
-rwxr-xr-xsrc/Makefile.am17
-rw-r--r--src/Makefile.in103
103 files changed, 9465 insertions, 6261 deletions
diff --git a/src/H5AC.c b/src/H5AC.c
index 751f877..193afb6 100644
--- a/src/H5AC.c
+++ b/src/H5AC.c
@@ -835,7 +835,9 @@ done:
*
* Modifications:
*
- * None.
+ * Added 'flags' paramater, to allow freeing file space
+ *
+ * QAK - 2/5/08
*
*-------------------------------------------------------------------------
*/
@@ -843,15 +845,16 @@ herr_t
H5AC_expunge_entry(H5F_t *f,
hid_t dxpl_id,
const H5AC_class_t *type,
- haddr_t addr)
+ haddr_t addr,
+ unsigned flags)
{
herr_t result;
- herr_t ret_value=SUCCEED; /* Return value */
H5AC_t * cache_ptr = NULL;
#if H5AC__TRACE_FILE_ENABLED
char trace[128] = "";
FILE * trace_file_ptr = NULL;
#endif /* H5AC__TRACE_FILE_ENABLED */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5AC_expunge_entry, FAIL)
@@ -885,7 +888,8 @@ H5AC_expunge_entry(H5F_t *f,
H5AC_noblock_dxpl_id,
cache_ptr,
type,
- addr);
+ addr,
+ flags);
if ( result < 0 ) {
@@ -1284,6 +1288,10 @@ H5AC_set(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr, void *
HDassert(H5F_addr_defined(addr));
HDassert(thing);
+ /* Check for invalid access request */
+ if(0 == (f->intent & H5F_ACC_RDWR))
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "no write intent on file")
+
#if H5AC__TRACE_FILE_ENABLED
/* For the insert, only the addr, size, type id and flags are really
* necessary in the trace file. Write the result to catch occult
diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h
index fc30a78..9a479e0 100644
--- a/src/H5ACprivate.h
+++ b/src/H5ACprivate.h
@@ -253,6 +253,8 @@ extern hid_t H5AC_ind_dxpl_id;
#define H5AC__FLUSH_CLEAR_ONLY_FLAG H5C__FLUSH_CLEAR_ONLY_FLAG
#define H5AC__FLUSH_MARKED_ENTRIES_FLAG H5C__FLUSH_MARKED_ENTRIES_FLAG
#define H5AC__FLUSH_IGNORE_PROTECTED_FLAG H5C__FLUSH_IGNORE_PROTECTED_FLAG
+#define H5AC__FREE_FILE_SPACE_FLAG H5C__FREE_FILE_SPACE_FLAG
+#define H5AC__TAKE_OWNERSHIP_FLAG H5C__TAKE_OWNERSHIP_FLAG
/* #defines of flags used to report entry status in the
@@ -298,7 +300,8 @@ H5_DLL herr_t H5AC_rename(H5F_t *f, const H5AC_class_t *type,
H5_DLL herr_t H5AC_dest(H5F_t *f, hid_t dxpl_id);
H5_DLL herr_t H5AC_expunge_entry(H5F_t *f, hid_t dxpl_id,
- const H5AC_class_t *type, haddr_t addr);
+ const H5AC_class_t *type, haddr_t addr,
+ unsigned flags);
H5_DLL herr_t H5AC_set_write_done_callback(H5C_t * cache_ptr,
void (* write_done)(void));
diff --git a/src/H5Adense.c b/src/H5Adense.c
index 4f9dcce..76ab95d 100644
--- a/src/H5Adense.c
+++ b/src/H5Adense.c
@@ -327,6 +327,7 @@ H5A_dense_open(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *na
H5HF_t *fheap = NULL; /* Fractal heap handle */
H5HF_t *shared_fheap = NULL; /* Fractal heap handle for shared header messages */
htri_t attr_sharable; /* Flag indicating attributes are sharable */
+ htri_t attr_exists; /* Attribute exists in v2 B-tree */
H5A_t *ret_value = NULL; /* Return value */
FUNC_ENTER_NOAPI(H5A_dense_open, NULL)
@@ -375,7 +376,9 @@ H5A_dense_open(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *na
udata.found_op_data = &ret_value;
/* Find & copy the attribute in the 'name' index */
- if(H5B2_find(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, &udata, NULL, NULL) < 0)
+ if((attr_exists = H5B2_find(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, &udata, NULL, NULL)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "can't search for attribute in name index")
+ else if(attr_exists == FALSE)
HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "can't locate attribute in name index")
done:
@@ -841,6 +844,7 @@ H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *
H5A_t *attr_copy = NULL; /* Copy of attribute to rename */
htri_t attr_sharable; /* Flag indicating attributes are sharable */
htri_t shared_mesg; /* Should this message be stored in the Shared Message table? */
+ htri_t attr_exists; /* Attribute exists in v2 B-tree */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5A_dense_rename, FAIL)
@@ -890,8 +894,10 @@ H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *
udata.found_op_data = &attr_copy;
/* Get copy of attribute through 'name' tracking v2 B-tree */
- if(H5B2_find(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, &udata, NULL, NULL) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to find record in v2 B-tree")
+ if((attr_exists = H5B2_find(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, &udata, NULL, NULL)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't search for attribute in name index")
+ else if(attr_exists == FALSE)
+ HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't locate attribute in name index")
HDassert(attr_copy);
/* Check if message is already shared */
@@ -1656,12 +1662,8 @@ H5A_dense_exists(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *
udata.found_op_data = NULL;
/* Find the attribute in the 'name' index */
- if(H5B2_find(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, &udata, NULL, NULL) < 0) {
- /* Assume that the failure was just not finding the attribute & clear stack */
- H5E_clear_stack(NULL);
-
- ret_value = FALSE;
- } /* end if */
+ if((ret_value = H5B2_find(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, &udata, NULL, NULL)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't search for attribute in name index")
done:
/* Release resources */
diff --git a/src/H5B.c b/src/H5B.c
index c442632..d049ee7 100644
--- a/src/H5B.c
+++ b/src/H5B.c
@@ -294,9 +294,9 @@ done:
* pointers since it assumes that all nodes can be reached
* from the parent node.
*
- * Return: Non-negative on success (if found, values returned through the
- * UDATA argument). Negative on failure (if not found, UDATA is
- * undefined).
+ * Return: Non-negative (TRUE/FALSE) on success (if found, values returned
+ * through the UDATA argument). Negative on failure (if not found,
+ * UDATA is undefined).
*
* Programmer: Robb Matzke
* matzke@llnl.gov
@@ -307,90 +307,65 @@ done:
* The ADDR argument is passed by value.
*-------------------------------------------------------------------------
*/
-herr_t
+htri_t
H5B_find(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t addr, void *udata)
{
H5B_t *bt = NULL;
- H5B_shared_t *shared; /* Pointer to shared B-tree info */
- unsigned idx=0, lt = 0, rt; /* Final, left & right key indices */
+ H5B_shared_t *shared; /* Pointer to shared B-tree info */
+ unsigned idx = 0, lt = 0, rt; /* Final, left & right key indices */
int cmp = 1; /* Key comparison value */
- int ret_value = SUCCEED; /* Return value */
+ htri_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5B_find, FAIL)
/*
* Check arguments.
*/
- assert(f);
- assert(type);
- assert(type->decode);
- assert(type->cmp3);
- assert(type->found);
- assert(H5F_addr_defined(addr));
+ HDassert(f);
+ HDassert(type);
+ HDassert(type->decode);
+ HDassert(type->cmp3);
+ HDassert(type->found);
+ HDassert(H5F_addr_defined(addr));
/*
* Perform a binary search to locate the child which contains
* the thing for which we're searching.
*/
- if (NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, type, udata, H5AC_READ)))
+ if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, type, udata, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load B-tree node")
- shared=(H5B_shared_t *)H5RC_GET_OBJ(bt->rc_shared);
+ shared = (H5B_shared_t *)H5RC_GET_OBJ(bt->rc_shared);
HDassert(shared);
- rt = bt->nchildren;
- while (lt < rt && cmp) {
+ rt = bt->nchildren;
+ while(lt < rt && cmp) {
idx = (lt + rt) / 2;
/* compare */
- if ((cmp = (type->cmp3) (f, dxpl_id, H5B_NKEY(bt,shared,idx), udata,
- H5B_NKEY(bt,shared,idx+1))) < 0) {
+ if((cmp = (type->cmp3)(f, dxpl_id, H5B_NKEY(bt, shared, idx), udata, H5B_NKEY(bt, shared, (idx + 1)))) < 0)
rt = idx;
- } else {
- lt = idx+1;
- }
- }
- if (cmp)
- /* Note: don't push error on stack, leave that to next higher level,
- * since many times the B-tree is searched in order to determine
- * if an object exists in the B-tree or not. -QAK
- */
-#ifdef OLD_WAY
- HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "B-tree key not found")
-#else /* OLD_WAY */
- HGOTO_DONE(FAIL)
-#endif /* OLD_WAY */
+ else
+ lt = idx + 1;
+ } /* end while */
+ /* Check if not found */
+ if(cmp)
+ HGOTO_DONE(FALSE)
/*
* Follow the link to the subtree or to the data node.
*/
assert(idx < bt->nchildren);
- if (bt->level > 0) {
- if (H5B_find(f, dxpl_id, type, bt->child[idx], udata) < 0)
- /* Note: don't push error on stack, leave that to next higher level,
- * since many times the B-tree is searched in order to determine
- * if an object exists in the B-tree or not. -QAK
- */
-#ifdef OLD_WAY
- HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "key not found in subtree")
-#else /* OLD_WAY */
- HGOTO_DONE(FAIL)
-#endif /* OLD_WAY */
- } else {
- if ((type->found) (f, dxpl_id, bt->child[idx], H5B_NKEY(bt,shared,idx), udata) < 0)
- /* Note: don't push error on stack, leave that to next higher level,
- * since many times the B-tree is searched in order to determine
- * if an object exists in the B-tree or not. -QAK
- */
-#ifdef OLD_WAY
- HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "key not found in leaf node")
-#else /* OLD_WAY */
- HGOTO_DONE(FAIL)
-#endif /* OLD_WAY */
- }
+ if(bt->level > 0) {
+ if((ret_value = H5B_find(f, dxpl_id, type, bt->child[idx], udata)) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "can't lookup key in subtree")
+ } /* end if */
+ else {
+ if((ret_value = (type->found)(f, dxpl_id, bt->child[idx], H5B_NKEY(bt, shared, idx), udata)) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "can't lookup key in leaf node")
+ } /* end else */
done:
- if (bt && H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__NO_FLAGS_SET)
- < 0)
+ if(bt && H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release node")
FUNC_LEAVE_NOAPI(ret_value)
@@ -1533,16 +1508,14 @@ H5B_remove_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type
bt->left = HADDR_UNDEF;
bt->right = HADDR_UNDEF;
H5_CHECK_OVERFLOW(shared->sizeof_rnode,size_t,hsize_t);
- if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, addr, (hsize_t)shared->sizeof_rnode)<0
- || H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, bt_flags | H5C__DELETED_FLAG)<0) {
+ if(H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, bt_flags | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0) {
bt = NULL;
bt_flags = H5AC__NO_FLAGS_SET;
HGOTO_ERROR(H5E_BTREE, H5E_PROTECT, H5B_INS_ERROR, "unable to free B-tree node")
- }
+ } /* end if */
bt = NULL;
bt_flags = H5AC__NO_FLAGS_SET;
- }
-
+ } /* end if */
} else if (H5B_INS_REMOVE==ret_value && 0==idx) {
/*
* The subtree is the left-most child of this node. We discard the
@@ -1766,12 +1739,8 @@ H5B_delete(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t addr, void
} /* end if */
} /* end else */
- /* Delete this node from disk */
- if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, addr, (hsize_t)shared->sizeof_rnode)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree node")
-
done:
- if (bt && H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5C__DELETED_FLAG)<0)
+ if(bt && H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG)<0)
HDONE_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree node in cache")
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5B2.c b/src/H5B2.c
index 1efc000..45bfff0 100644
--- a/src/H5B2.c
+++ b/src/H5B2.c
@@ -314,10 +314,10 @@ done:
* OP_DATA pointer, to allow caller to return information about
* the record.
*
- * If 'OP' is NULL, then this routine just returns "SUCCEED" when
+ * If 'OP' is NULL, then this routine just returns "TRUE" when
* a record is present in the B-tree.
*
- * Return: Non-negative on success, negative on failure.
+ * Return: Non-negative (TRUE/FALSE) on success, negative on failure.
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
@@ -325,7 +325,7 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t
+htri_t
H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr,
void *udata, H5B2_found_t op, void *op_data)
{
@@ -337,7 +337,7 @@ H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr,
unsigned depth; /* Current depth of the tree */
int cmp; /* Comparison value of records */
unsigned idx; /* Location of record which matches key */
- herr_t ret_value = SUCCEED;
+ htri_t ret_value = TRUE /* Return value */;
FUNC_ENTER_NOAPI(H5B2_find, FAIL)
@@ -372,7 +372,7 @@ H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr,
/* Check for empty tree */
if(curr_node_ptr.node_nrec == 0)
- HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "B-tree has no records")
+ HGOTO_DONE(FALSE)
/* Walk down B-tree to find record or leaf node where record is located */
cmp = -1;
@@ -404,7 +404,7 @@ H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr,
/* Make callback for current record */
if(op && (op)(H5B2_INT_NREC(internal, shared, idx), op_data) < 0) {
/* Unlock current node */
- if (H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__NO_FLAGS_SET) < 0)
+ if(H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "'found' callback failed for B-tree find operation")
@@ -414,7 +414,8 @@ H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr,
if(H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
- HGOTO_DONE(SUCCEED);
+ /* Indicate record found */
+ HGOTO_DONE(TRUE)
} /* end else */
/* Decrement depth we're at in B-tree */
@@ -436,15 +437,8 @@ H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr,
if(H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr.addr, leaf, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
- /* Note: don't push error on stack, leave that to next higher level,
- * since many times the B-tree is searched in order to determine
- * if an object exists in the B-tree or not. -QAK
- */
-#ifdef OLD_WAY
- HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "key not found in leaf node")
-#else /* OLD_WAY */
- HGOTO_DONE(FAIL)
-#endif /* OLD_WAY */
+ /* Record not found */
+ HGOTO_DONE(FALSE)
} /* end if */
else {
/* Make callback for current record */
@@ -992,13 +986,9 @@ H5B2_delete(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr,
if(H5B2_delete_node(f, dxpl_id, bt2->shared, shared->depth, &bt2->root, op, op_data) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to delete B-tree nodes")
- /* Release space for B-tree node on disk */
- if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, addr, (hsize_t)H5B2_HEADER_SIZE(f))<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree header info")
-
done:
/* Release the B-tree header info */
- if(bt2 && H5AC_unprotect(f, dxpl_id, H5AC_BT2_HDR, addr, bt2, H5AC__DELETED_FLAG) < 0)
+ if(bt2 && H5AC_unprotect(f, dxpl_id, H5AC_BT2_HDR, addr, bt2, H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to delete B-tree header info")
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5B2cache.c b/src/H5B2cache.c
index 9a5736f..903b4f3 100644
--- a/src/H5B2cache.c
+++ b/src/H5B2cache.c
@@ -30,12 +30,14 @@
#define H5B2_PACKAGE /*suppress error about including H5B2pkg */
+
/***********/
/* Headers */
/***********/
#include "H5private.h" /* Generic Functions */
#include "H5B2pkg.h" /* v2 B-trees */
#include "H5Eprivate.h" /* Error handling */
+#include "H5MFprivate.h" /* File memory management */
#include "H5WBprivate.h" /* Wrapped Buffers */
@@ -80,6 +82,7 @@ static herr_t H5B2_cache_leaf_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, ha
static herr_t H5B2_cache_leaf_clear(H5F_t *f, H5B2_leaf_t *l, hbool_t destroy);
static herr_t H5B2_cache_leaf_size(const H5F_t *f, const H5B2_leaf_t *l, size_t *size_ptr);
+
/*********************/
/* Package Variables */
/*********************/
@@ -114,6 +117,7 @@ const H5AC_class_t H5AC_BT2_LEAF[1] = {{
(H5AC_size_func_t)H5B2_cache_leaf_size,
}};
+
/*****************************/
/* Library Private Variables */
/*****************************/
@@ -376,17 +380,29 @@ done:
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
herr_t
-H5B2_cache_hdr_dest(H5F_t UNUSED *f, H5B2_t *bt2)
+H5B2_cache_hdr_dest(H5F_t *f, H5B2_t *bt2)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B2_cache_hdr_dest)
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_cache_hdr_dest)
/*
* Check arguments.
*/
HDassert(bt2);
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!bt2->cache_info.free_file_space_on_destroy || H5F_addr_defined(bt2->cache_info.addr));
+
+ /* Check for freeing file space for B-tree header */
+ if(bt2->cache_info.free_file_space_on_destroy) {
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_BTREE, H5AC_dxpl_id, bt2->cache_info.addr, (hsize_t)H5B2_HEADER_SIZE(f)) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free v2 B-tree header")
+ } /* end if */
+
/* Decrement reference count on shared B-tree info */
if(bt2->shared)
H5RC_DEC(bt2->shared);
@@ -394,7 +410,8 @@ H5B2_cache_hdr_dest(H5F_t UNUSED *f, H5B2_t *bt2)
/* Free B-tree header info */
(void)H5FL_FREE(H5B2_t, bt2);
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5B2_cache_hdr_dest() */
@@ -712,23 +729,34 @@ done:
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
herr_t
-H5B2_cache_internal_dest(H5F_t UNUSED *f, H5B2_internal_t *internal)
+H5B2_cache_internal_dest(H5F_t *f, H5B2_internal_t *internal)
{
H5B2_shared_t *shared; /* Shared B-tree information */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B2_cache_internal_dest)
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_cache_internal_dest)
/*
* Check arguments.
*/
HDassert(internal);
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!internal->cache_info.free_file_space_on_destroy || H5F_addr_defined(internal->cache_info.addr));
+
/* Get the pointer to the shared B-tree info */
shared = (H5B2_shared_t *)H5RC_GET_OBJ(internal->shared);
HDassert(shared);
+ /* Check for freeing file space for B-tree internal node */
+ if(internal->cache_info.free_file_space_on_destroy) {
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_BTREE, H5AC_dxpl_id, internal->cache_info.addr, (hsize_t)shared->node_size) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free v2 B-tree internal node")
+ } /* end if */
+
/* Release internal node's native key buffer */
if(internal->int_native)
H5FL_FAC_FREE(shared->node_info[internal->depth].nat_rec_fac, internal->int_native);
@@ -744,7 +772,8 @@ H5B2_cache_internal_dest(H5F_t UNUSED *f, H5B2_internal_t *internal)
/* Free B-tree internal node info */
(void)H5FL_FREE(H5B2_internal_t, internal);
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5B2_cache_internal_dest() */
@@ -1035,23 +1064,34 @@ done:
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
herr_t
-H5B2_cache_leaf_dest(H5F_t UNUSED *f, H5B2_leaf_t *leaf)
+H5B2_cache_leaf_dest(H5F_t *f, H5B2_leaf_t *leaf)
{
H5B2_shared_t *shared; /* Shared B-tree information */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B2_cache_leaf_dest)
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_cache_leaf_dest)
/*
* Check arguments.
*/
HDassert(leaf);
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!leaf->cache_info.free_file_space_on_destroy || H5F_addr_defined(leaf->cache_info.addr));
+
/* Get the pointer to the shared B-tree info */
shared = (H5B2_shared_t *)H5RC_GET_OBJ(leaf->shared);
HDassert(shared);
+ /* Check for freeing file space for B-tree leaf node */
+ if(leaf->cache_info.free_file_space_on_destroy) {
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_BTREE, H5AC_dxpl_id, leaf->cache_info.addr, (hsize_t)shared->node_size) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free v2 B-tree leaf node")
+ } /* end if */
+
/* Release leaf's native key buffer */
if(leaf->leaf_native)
H5FL_FAC_FREE(shared->node_info[0].nat_rec_fac, leaf->leaf_native);
@@ -1063,7 +1103,8 @@ H5B2_cache_leaf_dest(H5F_t UNUSED *f, H5B2_leaf_t *leaf)
/* Free B-tree leaf node info */
(void)H5FL_FREE(H5B2_leaf_t, leaf);
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5B2_cache_leaf_dest() */
diff --git a/src/H5B2int.c b/src/H5B2int.c
index d1def45..a6d53a5 100644
--- a/src/H5B2int.c
+++ b/src/H5B2int.c
@@ -1360,9 +1360,7 @@ H5B2_merge2(H5F_t *f, hid_t dxpl_id, unsigned depth,
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
/* Delete right node & remove from cache (marked as dirty) */
- if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, right_addr, (hsize_t)shared->node_size) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node")
- if(H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0)
+ if(H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
done:
@@ -1584,9 +1582,7 @@ H5B2_merge3(H5F_t *f, hid_t dxpl_id, unsigned depth,
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
/* Delete right node & remove from cache (marked as dirty) */
- if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, right_addr, (hsize_t)shared->node_size) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node")
- if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0)
+ if(H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
done:
@@ -2290,12 +2286,8 @@ H5B2_remove_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
HDmemmove(H5B2_LEAF_NREC(leaf, shared, idx), H5B2_LEAF_NREC(leaf, shared, (idx + 1)), shared->type->nrec_size * (leaf->nrec-idx));
} /* end if */
else {
- /* Release space for B-tree node on disk */
- if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, leaf_addr, (hsize_t)shared->node_size) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node")
-
/* Let the cache know that the object is deleted */
- leaf_flags |= H5AC__DELETED_FLAG;
+ leaf_flags |= H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
/* Reset address of parent node pointer */
curr_node_ptr->addr = HADDR_UNDEF;
@@ -2377,12 +2369,8 @@ H5B2_remove_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
parent_cache_info_flags_ptr, internal, &internal_flags, 0) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node")
- /* Release space for root B-tree node on disk */
- if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, internal_addr, (hsize_t)shared->node_size) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node")
-
/* Let the cache know that the object is deleted */
- internal_flags |= H5AC__DELETED_FLAG;
+ internal_flags |= H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
/* Reset information in header's root node pointer */
curr_node_ptr->addr = internal->node_ptrs[0].addr;
@@ -2590,12 +2578,8 @@ H5B2_remove_leaf_by_idx(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
HDmemmove(H5B2_LEAF_NREC(leaf, shared, idx), H5B2_LEAF_NREC(leaf, shared, (idx + 1)), shared->type->nrec_size * (leaf->nrec-idx));
} /* end if */
else {
- /* Release space for B-tree node on disk */
- if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, leaf_addr, (hsize_t)shared->node_size) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node")
-
/* Let the cache know that the object is deleted */
- leaf_flags |= H5AC__DELETED_FLAG;
+ leaf_flags |= H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
/* Reset address of parent node pointer */
curr_node_ptr->addr = HADDR_UNDEF;
@@ -2681,12 +2665,8 @@ H5B2_remove_internal_by_idx(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
parent_cache_info_flags_ptr, internal, &internal_flags, 0) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node")
- /* Release space for root B-tree node on disk */
- if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, internal_addr, (hsize_t)shared->node_size) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node")
-
/* Let the cache know that the object is deleted */
- internal_flags |= H5AC__DELETED_FLAG;
+ internal_flags |= H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
/* Reset information in header's root node pointer */
curr_node_ptr->addr = internal->node_ptrs[0].addr;
@@ -3144,15 +3124,10 @@ H5B2_delete_node(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, unsigned depth,
} /* end for */
} /* end if */
- /* Release space for current B-tree node on disk */
- if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, curr_node->addr, (hsize_t)shared->node_size) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree node")
-
done:
/* Unlock & delete current node */
- if(node)
- if(H5AC_unprotect(f, dxpl_id, curr_node_class, curr_node->addr, node, H5AC__DELETED_FLAG) < 0)
- HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ if(node && H5AC_unprotect(f, dxpl_id, curr_node_class, curr_node->addr, node, H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5B2_delete_node() */
diff --git a/src/H5B2private.h b/src/H5B2private.h
index 6d8172c..0a18604 100644
--- a/src/H5B2private.h
+++ b/src/H5B2private.h
@@ -124,7 +124,7 @@ H5_DLL herr_t H5B2_iterate(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type,
haddr_t addr, H5B2_operator_t op, void *op_data);
H5_DLL herr_t H5B2_iterate_size(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type,
haddr_t addr, hsize_t *op_data);
-H5_DLL herr_t H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type,
+H5_DLL htri_t H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type,
haddr_t addr, void *udata, H5B2_found_t op, void *op_data);
H5_DLL herr_t H5B2_index(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type,
haddr_t addr, H5_iter_order_t order, hsize_t idx, H5B2_found_t op,
diff --git a/src/H5Bcache.c b/src/H5Bcache.c
index d3b2a35..9765552 100644
--- a/src/H5Bcache.c
+++ b/src/H5Bcache.c
@@ -37,6 +37,7 @@
#include "H5private.h" /* Generic Functions */
#include "H5Bpkg.h" /* B-link trees */
#include "H5Eprivate.h" /* Error handling */
+#include "H5MFprivate.h" /* File memory management */
/****************/
/* Local Macros */
@@ -321,24 +322,45 @@ done:
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
herr_t
-H5B_dest(H5F_t UNUSED *f, H5B_t *bt)
+H5B_dest(H5F_t *f, H5B_t *bt)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B_dest)
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5B_dest)
/*
* Check arguments.
*/
+ HDassert(f);
HDassert(bt);
HDassert(bt->rc_shared);
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!bt->cache_info.free_file_space_on_destroy || H5F_addr_defined(bt->cache_info.addr));
+
+ /* Check for freeing file space for B-tree node */
+ if(bt->cache_info.free_file_space_on_destroy) {
+ H5B_shared_t *shared; /* Pointer to shared B-tree info */
+
+ /* Get the pointer to the shared B-tree info */
+ shared = (H5B_shared_t *)H5RC_GET_OBJ(bt->rc_shared);
+ HDassert(shared);
+
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_BTREE, H5AC_dxpl_id, bt->cache_info.addr, (hsize_t)shared->sizeof_rnode) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree node")
+ } /* end if */
+
+ /* Release resources for B-tree node */
H5FL_SEQ_FREE(haddr_t, bt->child);
(void)H5FL_BLK_FREE(native_block, bt->native);
H5RC_DEC(bt->rc_shared);
(void)H5FL_FREE(H5B_t, bt);
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5B_dest() */
diff --git a/src/H5Bprivate.h b/src/H5Bprivate.h
index dc8648e..c11d02c 100644
--- a/src/H5Bprivate.h
+++ b/src/H5Bprivate.h
@@ -103,7 +103,7 @@ typedef struct H5B_class_t {
herr_t (*new_node)(H5F_t*, hid_t, H5B_ins_t, void*, void*, void*, haddr_t*);
int (*cmp2)(H5F_t*, hid_t, void*, void*, void*); /*compare 2 keys */
int (*cmp3)(H5F_t*, hid_t, void*, void*, void*); /*compare 3 keys */
- herr_t (*found)(H5F_t*, hid_t, haddr_t, const void*, void*);
+ htri_t (*found)(H5F_t*, hid_t, haddr_t, const void*, void*);
/* insert new data */
H5B_ins_t (*insert)(H5F_t*, hid_t, haddr_t, void*, hbool_t*, void*, void*,
diff --git a/src/H5C.c b/src/H5C.c
index 382f104..a6a6240 100644
--- a/src/H5C.c
+++ b/src/H5C.c
@@ -3412,15 +3412,19 @@ H5C_expunge_entry(H5F_t * f,
hid_t secondary_dxpl_id,
H5C_t * cache_ptr,
const H5C_class_t * type,
- haddr_t addr)
+ haddr_t addr,
+ unsigned flags)
{
herr_t result;
- herr_t ret_value = SUCCEED; /* Return value */
hbool_t first_flush = TRUE;
+ hbool_t free_file_space;
H5C_cache_entry_t * entry_ptr = NULL;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5C_expunge_entry, FAIL)
+ free_file_space = ( (flags & H5C__FREE_FILE_SPACE_FLAG) != 0 );
+
HDassert( H5F_addr_defined(addr) );
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
@@ -3459,6 +3463,11 @@ H5C_expunge_entry(H5F_t * f,
"Target entry is pinned.")
}
+ /* Pass along 'free file space' flag to cache client */
+
+ entry_ptr->free_file_space_on_destroy = free_file_space;
+
+
/* If we get this far, call H5C_flush_single_entry() with the
* H5C__FLUSH_INVALIDATE_FLAG and the H5C__FLUSH_CLEAR_ONLY_FLAG.
* This will clear the entry, and then delete it from the cache.
@@ -4611,6 +4620,10 @@ done:
* JRM -- 12/31/07
* Added code supporting flash cache size increases.
*
+ * QAK -- 1/31/08
+ * Added initialization for the new free_file_space_on_destroy
+ * field.
+ *
*-------------------------------------------------------------------------
*/
@@ -4692,6 +4705,7 @@ H5C_insert_entry(H5F_t * f,
entry_ptr->flush_in_progress = FALSE;
entry_ptr->destroy_in_progress = FALSE;
+ entry_ptr->free_file_space_on_destroy = FALSE;
entry_ptr->ht_next = NULL;
entry_ptr->ht_prev = NULL;
@@ -7413,7 +7427,15 @@ done:
* ro_ref_count parameters.
*
* JRM -- 12/31/07
- * Modified funtion to support flash cache resizes.
+ * Modified function to support flash cache resizes.
+ *
+ * QAK -- 1/31/08
+ * Modified function to support freeing file space in client's
+ * 'dest' callback routine.
+ *
+ * QAK -- 2/07/08
+ * Separated "destroy entry" concept from "remove entry from
+ * cache" concept, by adding the 'take_ownership' flag.
*
*-------------------------------------------------------------------------
*/
@@ -7435,6 +7457,8 @@ H5C_unprotect(H5F_t * f,
hbool_t size_changed;
hbool_t pin_entry;
hbool_t unpin_entry;
+ hbool_t free_file_space;
+ hbool_t take_ownership;
#ifdef H5_HAVE_PARALLEL
hbool_t clear_entry = FALSE;
#endif /* H5_HAVE_PARALLEL */
@@ -7452,6 +7476,8 @@ H5C_unprotect(H5F_t * f,
size_changed = ( (flags & H5C__SIZE_CHANGED_FLAG) != 0 );
pin_entry = ( (flags & H5C__PIN_ENTRY_FLAG) != 0 );
unpin_entry = ( (flags & H5C__UNPIN_ENTRY_FLAG) != 0 );
+ free_file_space = ( (flags & H5C__FREE_FILE_SPACE_FLAG) != 0 );
+ take_ownership = ( (flags & H5C__TAKE_OWNERSHIP_FLAG) != 0 );
/* Changing the size of an entry dirties it. Thus, set the
* dirtied flag if the size_changed flag is set.
@@ -7471,6 +7497,9 @@ H5C_unprotect(H5F_t * f,
HDassert( ( ! size_changed ) || ( dirtied ) );
HDassert( ( ! size_changed ) || ( new_size > 0 ) );
HDassert( ! ( pin_entry && unpin_entry ) );
+ HDassert( ( ! free_file_space ) || ( deleted ) ); /* deleted flag must accompany free_file_space */
+ HDassert( ( ! take_ownership ) || ( deleted ) ); /* deleted flag must accompany take_ownership */
+ HDassert( ! ( free_file_space && take_ownership ) ); /* can't have both free_file_space & take_ownership */
entry_ptr = (H5C_cache_entry_t *)thing;
@@ -7696,7 +7725,9 @@ H5C_unprotect(H5F_t * f,
* H5C__FLUSH_CLEAR_ONLY_FLAG and H5C__FLUSH_INVALIDATE_FLAG flags.
* However, it is needed for the function call.
*/
- hbool_t dummy_first_flush = TRUE;
+ hbool_t dummy_first_flush = TRUE;
+ unsigned flush_flags = (H5C__FLUSH_CLEAR_ONLY_FLAG |
+ H5C__FLUSH_INVALIDATE_FLAG);
/* we can't delete a pinned entry */
HDassert ( ! (entry_ptr->is_pinned ) );
@@ -7716,14 +7747,23 @@ H5C_unprotect(H5F_t * f,
"hash table contains multiple entries for addr?!?.")
}
+ /* Pass along 'free file space' flag to cache client */
+
+ entry_ptr->free_file_space_on_destroy = free_file_space;
+
+ /* Set the "take ownership" flag for the flush, if needed */
+ if ( take_ownership) {
+
+ flush_flags |= H5C__TAKE_OWNERSHIP_FLAG;
+ }
+
if ( H5C_flush_single_entry(f,
primary_dxpl_id,
secondary_dxpl_id,
cache_ptr,
type,
addr,
- (H5C__FLUSH_CLEAR_ONLY_FLAG |
- H5C__FLUSH_INVALIDATE_FLAG),
+ flush_flags,
&dummy_first_flush,
TRUE) < 0 ) {
@@ -10004,11 +10044,15 @@ done:
* in which the target entry is resized during flush, and
* update the caches data structures accordingly.
*
- *
* JRM -- 3/29/07
* Added sanity checks on the new is_read_only and
* ro_ref_count fields.
*
+ * QAK -- 2/07/08
+ * Separated "destroy entry" concept from "remove entry from
+ * cache" concept, by adding the 'take_ownership' flag and
+ * the "destroy_entry" variable.
+ *
*-------------------------------------------------------------------------
*/
static herr_t
@@ -10024,12 +10068,14 @@ H5C_flush_single_entry(H5F_t * f,
{
hbool_t destroy;
hbool_t clear_only;
+ hbool_t take_ownership;
hbool_t was_dirty;
- herr_t ret_value = SUCCEED; /* Return value */
+ hbool_t destroy_entry;
herr_t status;
int type_id;
unsigned flush_flags = H5C_CALLBACK__NO_FLAGS_SET;
H5C_cache_entry_t * entry_ptr = NULL;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5C_flush_single_entry)
@@ -10042,6 +10088,15 @@ H5C_flush_single_entry(H5F_t * f,
destroy = ( (flags & H5C__FLUSH_INVALIDATE_FLAG) != 0 );
clear_only = ( (flags & H5C__FLUSH_CLEAR_ONLY_FLAG) != 0);
+ take_ownership = ( (flags & H5C__TAKE_OWNERSHIP_FLAG) != 0);
+
+ /* Set the flag for destroying the entry, based on the 'take ownership'
+ * and 'destroy' flags
+ */
+ if(take_ownership)
+ destroy_entry = FALSE;
+ else
+ destroy_entry = destroy;
/* attempt to find the target entry in the hash table */
H5C__SEARCH_INDEX(cache_ptr, addr, entry_ptr, FAIL)
@@ -10308,7 +10363,7 @@ H5C_flush_single_entry(H5F_t * f,
}
#endif /* NDEBUG */
/* Call the callback routine to clear all dirty flags for object */
- if ( (entry_ptr->type->clear)(f, entry_ptr, destroy) < 0 ) {
+ if ( (entry_ptr->type->clear)(f, entry_ptr, destroy_entry) < 0 ) {
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "can't clear entry")
}
@@ -10341,7 +10396,7 @@ H5C_flush_single_entry(H5F_t * f,
if ( *first_flush_ptr && entry_ptr->is_dirty ) {
- status = (entry_ptr->type->flush)(f, primary_dxpl_id, destroy,
+ status = (entry_ptr->type->flush)(f, primary_dxpl_id, destroy_entry,
entry_ptr->addr, entry_ptr,
&flush_flags);
*first_flush_ptr = FALSE;
@@ -10349,7 +10404,7 @@ H5C_flush_single_entry(H5F_t * f,
} else {
status = (entry_ptr->type->flush)(f, secondary_dxpl_id,
- destroy, entry_ptr->addr,
+ destroy_entry, entry_ptr->addr,
entry_ptr, &flush_flags);
}
@@ -10534,6 +10589,10 @@ done:
* Added initialization for the new is_read_only and
* ro_ref_count fields.
*
+ * QAK -- 1/31/08
+ * Added initialization for the new free_file_space_on_destroy
+ * field.
+ *
*-------------------------------------------------------------------------
*/
@@ -10609,6 +10668,7 @@ H5C_load_entry(H5F_t * f,
#endif /* H5_HAVE_PARALLEL */
entry_ptr->flush_in_progress = FALSE;
entry_ptr->destroy_in_progress = FALSE;
+ entry_ptr->free_file_space_on_destroy = FALSE;
if ( (type->size)(f, thing, &(entry_ptr->size)) < 0 ) {
diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h
index b50227b..4ce321c 100644
--- a/src/H5Cprivate.h
+++ b/src/H5Cprivate.h
@@ -364,6 +364,11 @@ typedef herr_t (*H5C_log_flush_func_t)(H5C_t * cache_ptr,
* destroy_in_progress: Boolean flag that is set to true iff the entry
* is in the process of being flushed and destroyed.
*
+ * free_file_space_on_destroy: Boolean flag that is set to true iff the entry
+ * is in the process of being flushed and destroyed and the file
+ * space used by the object should be freed by the cache client's
+ * 'dest' callback routine.
+ *
*
* Fields supporting the hash table:
*
@@ -489,6 +494,7 @@ typedef struct H5C_cache_entry_t
#endif /* H5_HAVE_PARALLEL */
hbool_t flush_in_progress;
hbool_t destroy_in_progress;
+ hbool_t free_file_space_on_destroy;
/* fields supporting the hash table: */
@@ -893,7 +899,12 @@ typedef struct H5C_auto_size_ctl_t
* H5C__SIZE_CHANGED_FLAG
* H5C__PIN_ENTRY_FLAG
* H5C__UNPIN_ENTRY_FLAG
+ * H5C__FREE_FILE_SPACE_FLAG
+ * H5C__TAKE_OWNERSHIP_FLAG
+ *
+ * These flags apply to H5C_expunge_entry():
*
+ * H5C__FREE_FILE_SPACE_FLAG
*
* These flags apply to H5C_flush_cache():
*
@@ -908,6 +919,7 @@ typedef struct H5C_auto_size_ctl_t
* H5C__FLUSH_INVALIDATE_FLAG
* H5C__FLUSH_CLEAR_ONLY_FLAG
* H5C__FLUSH_MARKED_ENTRIES_FLAG
+ * H5C__TAKE_OWNERSHIP_FLAG
*/
#define H5C__NO_FLAGS_SET 0x0000
@@ -922,6 +934,8 @@ typedef struct H5C_auto_size_ctl_t
#define H5C__FLUSH_MARKED_ENTRIES_FLAG 0x0100
#define H5C__FLUSH_IGNORE_PROTECTED_FLAG 0x0200
#define H5C__READ_ONLY_FLAG 0x0400
+#define H5C__FREE_FILE_SPACE_FLAG 0x0800
+#define H5C__TAKE_OWNERSHIP_FLAG 0x1000
H5_DLL H5C_t * H5C_create(size_t max_cache_size,
@@ -954,7 +968,8 @@ H5_DLL herr_t H5C_expunge_entry(H5F_t * f,
hid_t secondary_dxpl_id,
H5C_t * cache_ptr,
const H5C_class_t * type,
- haddr_t addr);
+ haddr_t addr,
+ unsigned flags);
H5_DLL herr_t H5C_flush_cache(H5F_t * f,
hid_t primary_dxpl_id,
diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c
index 0692774..202da75 100644
--- a/src/H5Dchunk.c
+++ b/src/H5Dchunk.c
@@ -1484,17 +1484,17 @@ H5D_chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
H5D_chunk_info_t *chunk_info; /* Chunk information */
H5D_io_info_t *chk_io_info; /* Pointer to I/O info object for this chunk */
void *chunk; /* Pointer to locked chunk buffer */
- haddr_t chunk_addr; /* Chunk address on disk */
H5D_chunk_ud_t udata; /* B-tree pass-through */
/* Get the actual chunk information from the skip list node */
chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node);
- /* Get the address of the chunk in the file */
- chunk_addr = H5D_chunk_get_addr(io_info->dset, io_info->dxpl_id, chunk_info->coords, &udata);
+ /* Get the info for the chunk in the file */
+ if(H5D_chunk_get_info(io_info->dset, io_info->dxpl_id, chunk_info->coords, &udata) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
/* Check for non-existant chunk & skip it if appropriate */
- if(!H5F_addr_defined(chunk_addr) && !H5D_chunk_in_cache(io_info->dset, chunk_info->coords, chunk_info->index)
+ if(!H5F_addr_defined(udata.addr) && !H5D_chunk_in_cache(io_info->dset, chunk_info->coords, chunk_info->index)
&& skip_missing_chunks) {
/* No chunk cached */
chunk = NULL;
@@ -1504,7 +1504,7 @@ H5D_chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
} /* end if */
else {
/* Load the chunk into cache and lock it. */
- if(H5D_chunk_cacheable(io_info, chunk_addr)) {
+ if(H5D_chunk_cacheable(io_info, udata.addr)) {
/* Pass in chunk's coordinates in a union. */
io_info->store->chunk.offset = chunk_info->coords;
io_info->store->chunk.index = chunk_info->index;
@@ -1524,10 +1524,10 @@ H5D_chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
} /* end if */
else {
/* Sanity check */
- HDassert(H5F_addr_defined(chunk_addr));
+ HDassert(H5F_addr_defined(udata.addr));
/* Set up the storage address information for this chunk */
- ctg_store.contig.dset_addr = chunk_addr;
+ ctg_store.contig.dset_addr = udata.addr;
/* No chunk cached */
chunk = NULL;
@@ -1612,7 +1612,6 @@ H5D_chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
H5D_chunk_info_t *chunk_info; /* Chunk information */
H5D_io_info_t *chk_io_info; /* Pointer to I/O info object for this chunk */
void *chunk; /* Pointer to locked chunk buffer */
- haddr_t chunk_addr; /* Chunk address on disk */
H5D_chunk_ud_t udata; /* B-tree pass-through */
/* Get the actual chunk information from the skip list node */
@@ -1620,8 +1619,9 @@ H5D_chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
/* Load the chunk into cache. But if the whole chunk is written,
* simply allocate space instead of load the chunk. */
- chunk_addr = H5D_chunk_get_addr(io_info->dset, io_info->dxpl_id, chunk_info->coords, &udata);
- if(H5D_chunk_cacheable(io_info, chunk_addr)) {
+ if(H5D_chunk_get_info(io_info->dset, io_info->dxpl_id, chunk_info->coords, &udata) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
+ if(H5D_chunk_cacheable(io_info, udata.addr)) {
hbool_t entire_chunk = TRUE; /* Whether whole chunk is selected */
/* Pass in chunk's coordinates in a union. */
@@ -1648,10 +1648,10 @@ H5D_chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
} /* end if */
else {
/* Sanity check */
- HDassert(H5F_addr_defined(chunk_addr));
+ HDassert(H5F_addr_defined(udata.addr));
/* Set up the storage address information for this chunk */
- ctg_store.contig.dset_addr = chunk_addr;
+ ctg_store.contig.dset_addr = udata.addr;
/* No chunk cached */
chunk = NULL;
@@ -1945,9 +1945,9 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5D_chunk_get_addr
+ * Function: H5D_chunk_get_info
*
- * Purpose: Get the file address of a chunk if file space has been
+ * Purpose: Get the info about a chunk if file space has been
* assigned. Save the retrieved information in the udata
* supplied.
*
@@ -1958,26 +1958,24 @@ done:
*
*-------------------------------------------------------------------------
*/
-haddr_t
-H5D_chunk_get_addr(const H5D_t *dset, hid_t dxpl_id, const hsize_t *chunk_offset,
- H5D_chunk_ud_t *_udata)
+herr_t
+H5D_chunk_get_info(const H5D_t *dset, hid_t dxpl_id, const hsize_t *chunk_offset,
+ H5D_chunk_ud_t *udata)
{
- H5D_chunk_ud_t tmp_udata; /* Information about a chunk */
- H5D_chunk_ud_t *udata; /* Pointer to information about a chunk */
- haddr_t ret_value; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_chunk_get_addr)
+ FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_get_info)
HDassert(dset);
HDassert(dset->shared->layout.u.chunk.ndims > 0);
HDassert(chunk_offset);
+ HDassert(udata);
- /* Check for udata struct to return */
- udata = (_udata != NULL ? _udata : &tmp_udata);
-
- /* Initialize the information about the chunk we are looking for */
+ /* Initialize the query information about the chunk we are looking for */
udata->common.mesg = &(dset->shared->layout);
udata->common.offset = chunk_offset;
+
+ /* Reset information about the chunk we are looking for */
udata->nbytes = 0;
udata->filter_mask = 0;
udata->addr = HADDR_UNDEF;
@@ -1992,24 +1990,16 @@ H5D_chunk_get_addr(const H5D_t *dset, hid_t dxpl_id, const hsize_t *chunk_offset
idx_info.layout = &dset->shared->layout;
/* Go get the chunk information */
- if(!H5F_addr_defined((dset->shared->layout.u.chunk.ops->get_addr)(&idx_info, udata))) {
- /* Cache the fact that the chunk is not in the B-tree */
- H5D_chunk_cinfo_cache_update(&dset->shared->cache.chunk.last, udata);
-
- HGOTO_DONE(HADDR_UNDEF)
- } /* end if */
+ if((dset->shared->layout.u.chunk.ops->get_addr)(&idx_info, udata) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't query chunk address")
/* Cache the information retrieved */
- HDassert(H5F_addr_defined(udata->addr));
H5D_chunk_cinfo_cache_update(&dset->shared->cache.chunk.last, udata);
} /* end if */
- /* Success! Set the return value */
- ret_value = udata->addr;
-
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5D_chunk_get_addr() */
+} /* H5D_chunk_get_info() */
/*-------------------------------------------------------------------------
@@ -2381,9 +2371,10 @@ H5D_chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata,
FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_lock)
HDassert(io_info);
- HDassert(dset);
HDassert(io_info->dxpl_cache);
HDassert(io_info->store);
+ HDassert(udata);
+ HDassert(dset);
HDassert(TRUE == H5P_isa_class(io_info->dxpl_id, H5P_DATASET_XFER));
/* Get the chunk's size */
@@ -2426,20 +2417,13 @@ H5D_chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata,
HDmemset(chunk, 0, chunk_size);
} /* end if */
else {
- H5D_chunk_ud_t tmp_udata; /*B-tree pass-through */
-
- if(udata != NULL)
- chunk_addr = udata->addr;
- else {
- /* Point at temporary storage for B-tree pass through */
- udata = &tmp_udata;
+ /*
+ * Not in the cache. Count this as a miss if it's in the file
+ * or an init if it isn't.
+ */
- /*
- * Not in the cache. Read it from the file and count this as a miss
- * if it's in the file or an init if it isn't.
- */
- chunk_addr = H5D_chunk_get_addr(io_info->dset, io_info->dxpl_id, io_info->store->chunk.offset, udata);
- } /* end else */
+ /* Save the chunk address */
+ chunk_addr = udata->addr;
/* Check if the chunk exists on disk */
if(H5F_addr_defined(chunk_addr)) {
@@ -2972,14 +2956,15 @@ H5D_chunk_allocate(H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite)
/* Loop over all chunks */
carry = FALSE;
while(!carry) {
- haddr_t chunk_addr; /* Address of chunk */
+ H5D_chunk_ud_t udata; /* User data for querying chunk info */
int i; /* Local index variable */
- /* Get the chunk's address */
- chunk_addr = H5D_chunk_get_addr(dset, dxpl_id, chunk_offset, NULL);
+ /* Get the chunk's info */
+ if(H5D_chunk_get_info(dset, dxpl_id, chunk_offset, &udata) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "error looking up chunk address")
/* Check if the chunk exists yet on disk */
- if(!H5F_addr_defined(chunk_addr)) {
+ if(!H5F_addr_defined(udata.addr)) {
const H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /* Raw data chunk cache */
H5D_rdcc_ent_t *ent; /* Cache entry */
hbool_t chunk_exists; /* Flag to indicate whether a chunk exists already */
diff --git a/src/H5Dcontig.c b/src/H5Dcontig.c
index 88ffdc6..01ee5e2 100644
--- a/src/H5Dcontig.c
+++ b/src/H5Dcontig.c
@@ -608,7 +608,6 @@ for(u = 0; u < mem_max_nseq; u++)
haddr_t sieve_start = HADDR_UNDEF, sieve_end = HADDR_UNDEF; /* Start & end locations of sieve buffer */
haddr_t contig_end; /* End locations of block to write */
size_t sieve_size = (size_t)-1; /* size of sieve buffer */
- haddr_t abs_eoa; /* Absolute end of file address */
haddr_t rel_eoa; /* Relative end of file address */
hsize_t max_data; /* Actual maximum size of data to cache */
@@ -653,12 +652,9 @@ for(u = 0; u < mem_max_nseq; u++)
dset_contig->sieve_loc=addr;
/* Make certain we don't read off the end of the file */
- if (HADDR_UNDEF==(abs_eoa=H5F_get_eoa(file)))
+ if(HADDR_UNDEF == (rel_eoa = H5F_get_eoa(file, H5FD_MEM_DRAW)))
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size")
- /* Adjust absolute EOA address to relative EOA address */
- rel_eoa = abs_eoa - H5F_get_base_addr(file);
-
/* Set up the buffer parameters */
max_data = store_contig->dset_size-dset_offset_arr[u];
@@ -730,12 +726,9 @@ for(u = 0; u < mem_max_nseq; u++)
dset_contig->sieve_loc=addr;
/* Make certain we don't read off the end of the file */
- if (HADDR_UNDEF==(abs_eoa=H5F_get_eoa(file)))
+ if(HADDR_UNDEF == (rel_eoa = H5F_get_eoa(file, H5FD_MEM_DRAW)))
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size")
- /* Adjust absolute EOA address to relative EOA address */
- rel_eoa=abs_eoa-H5F_get_base_addr(file);
-
/* Only need this when resizing sieve buffer */
max_data=store_contig->dset_size-dset_offset_arr[u];
@@ -872,7 +865,6 @@ H5D_contig_writevv(const H5D_io_info_t *io_info,
haddr_t sieve_start=HADDR_UNDEF, sieve_end=HADDR_UNDEF; /* Start & end locations of sieve buffer */
haddr_t contig_end; /* End locations of block to write */
size_t sieve_size=(size_t)-1; /* size of sieve buffer */
- haddr_t abs_eoa; /* Absolute end of file address */
haddr_t rel_eoa; /* Relative end of file address */
hsize_t max_data; /* Actual maximum size of data to cache */
@@ -921,12 +913,9 @@ if(dset_contig->sieve_size > size)
dset_contig->sieve_loc=addr;
/* Make certain we don't read off the end of the file */
- if (HADDR_UNDEF==(abs_eoa=H5F_get_eoa(file)))
+ if(HADDR_UNDEF == (rel_eoa = H5F_get_eoa(file, H5FD_MEM_DRAW)))
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size")
- /* Adjust absolute EOA address to relative EOA address */
- rel_eoa=abs_eoa-H5F_get_base_addr(file);
-
/* Set up the buffer parameters */
max_data=store_contig->dset_size-dset_offset_arr[u];
@@ -1040,12 +1029,9 @@ if(dset_contig->sieve_size > size)
dset_contig->sieve_loc=addr;
/* Make certain we don't read off the end of the file */
- if (HADDR_UNDEF==(abs_eoa=H5F_get_eoa(file)))
+ if(HADDR_UNDEF == (rel_eoa = H5F_get_eoa(file, H5FD_MEM_DRAW)))
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size")
- /* Adjust absolute EOA address to relative EOA address */
- rel_eoa=abs_eoa-H5F_get_base_addr(file);
-
/* Only need this when resizing sieve buffer */
max_data=store_contig->dset_size-dset_offset_arr[u];
diff --git a/src/H5Dint.c b/src/H5Dint.c
index bab3038..aa91db5 100644
--- a/src/H5Dint.c
+++ b/src/H5Dint.c
@@ -1484,7 +1484,7 @@ H5D_open_oid(H5D_t *dataset, hid_t dxpl_id)
* This is important only for parallel I/O where the space must
* be fully allocated before I/O can happen.
*/
- if((H5F_get_intent(dataset->oloc.file) & H5F_ACC_RDWR)
+ if((H5F_INTENT(dataset->oloc.file) & H5F_ACC_RDWR)
&& ((dataset->shared->layout.type == H5D_CONTIGUOUS && !H5F_addr_defined(dataset->shared->layout.u.contig.addr))
|| (dataset->shared->layout.type == H5D_CHUNKED && !H5F_addr_defined(dataset->shared->layout.u.chunk.addr)))
&& IS_H5FD_MPI(dataset->oloc.file)) {
@@ -1730,33 +1730,6 @@ H5D_typeof(const H5D_t *dset)
/*-------------------------------------------------------------------------
- * Function: H5D_get_file
- *
- * Purpose: Returns the dataset's file pointer.
- *
- * Return: Success: Ptr to the dataset's file pointer.
- *
- * Failure: NULL
- *
- * Programmer: Quincey Koziol
- * Thursday, October 22, 1998
- *
- *-------------------------------------------------------------------------
- */
-static H5F_t *
-H5D_get_file(const H5D_t *dset)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_get_file)
-
- HDassert(dset);
- HDassert(dset->oloc.file);
-
- FUNC_LEAVE_NOAPI(dset->oloc.file)
-} /* end H5D_get_file() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5D_alloc_storage
*
* Purpose: Allocate storage for the raw data of a dataset.
@@ -2036,8 +2009,6 @@ done:
haddr_t
H5D_get_offset(const H5D_t *dset)
{
- haddr_t base_addr;
- H5F_t *f;
haddr_t ret_value = HADDR_UNDEF;
FUNC_ENTER_NOAPI_NOINIT(H5D_get_offset)
@@ -2052,15 +2023,9 @@ H5D_get_offset(const H5D_t *dset)
case H5D_CONTIGUOUS:
/* If dataspace hasn't been allocated or dataset is stored in
* an external file, the value will be HADDR_UNDEF. */
- f = H5D_get_file(dset);
- base_addr = H5F_get_base_addr(f);
-
- /* If there's user block in file, returns the absolute dataset offset
- * from the beginning of file. */
- if(base_addr != HADDR_UNDEF)
- ret_value = dset->shared->layout.u.contig.addr + base_addr;
- else
- ret_value = dset->shared->layout.u.contig.addr;
+ if(dset->shared->dcpl_cache.efl.nused == 0 || H5F_addr_defined(dset->shared->layout.u.contig.addr))
+ /* Return the absolute dataset offset from the beginning of file. */
+ ret_value = dset->shared->layout.u.contig.addr + H5F_BASE_ADDR(dset->oloc.file);
break;
default:
@@ -2325,7 +2290,7 @@ H5D_set_extent(H5D_t *dset, const hsize_t *size, hid_t dxpl_id)
HDassert(size);
/* Check if we are allowed to modify this file */
- if(0 == (H5F_get_intent(dset->oloc.file) & H5F_ACC_RDWR))
+ if(0 == (H5F_INTENT(dset->oloc.file) & H5F_ACC_RDWR))
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "no write intent on file")
/* Check if the filters in the DCPL will need to encode, and if so, can they? */
diff --git a/src/H5Distore.c b/src/H5Distore.c
index a217a41..5d24d63 100644
--- a/src/H5Distore.c
+++ b/src/H5Distore.c
@@ -139,7 +139,7 @@ static int H5D_istore_cmp2(H5F_t *f, hid_t dxpl_id, void *_lt_key, void *_udata,
void *_rt_key);
static int H5D_istore_cmp3(H5F_t *f, hid_t dxpl_id, void *_lt_key, void *_udata,
void *_rt_key);
-static herr_t H5D_istore_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_lt_key,
+static htri_t H5D_istore_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_lt_key,
void *_udata);
static H5B_ins_t H5D_istore_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key,
hbool_t *lt_key_changed, void *_md_key,
@@ -162,7 +162,7 @@ static herr_t H5D_istore_idx_init(const H5D_chk_idx_info_t *idx_info);
static herr_t H5D_istore_idx_create(const H5D_chk_idx_info_t *idx_info);
static herr_t H5D_istore_idx_insert(const H5D_chk_idx_info_t *idx_info,
H5D_chunk_ud_t *udata);
-static haddr_t H5D_istore_idx_get_addr(const H5D_chk_idx_info_t *idx_info,
+static herr_t H5D_istore_idx_get_addr(const H5D_chk_idx_info_t *idx_info,
H5D_chunk_ud_t *udata);
static int H5D_istore_idx_iterate(const H5D_chk_idx_info_t *idx_info,
H5D_chunk_cb_func_t chunk_cb, void *chunk_udata);
@@ -583,8 +583,8 @@ done:
* called with the maximum stored chunk indices less than the
* requested chunk indices.
*
- * Return: Non-negative on success with information about the chunk
- * returned through the UDATA argument. Negative on failure.
+ * Return: Non-negative (TRUE/FALSE) on success with information about the
+ * chunk returned through the UDATA argument. Negative on failure.
*
* Programmer: Robb Matzke
* Thursday, October 9, 1997
@@ -592,14 +592,14 @@ done:
*-------------------------------------------------------------------------
*/
/* ARGSUSED */
-static herr_t
+static htri_t
H5D_istore_found(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, haddr_t addr, const void *_lt_key,
void *_udata)
{
H5D_chunk_ud_t *udata = (H5D_chunk_ud_t *) _udata;
const H5D_istore_key_t *lt_key = (const H5D_istore_key_t *) _lt_key;
unsigned u;
- herr_t ret_value = SUCCEED; /* Return value */
+ htri_t ret_value = TRUE; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_found)
@@ -612,7 +612,7 @@ H5D_istore_found(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, haddr_t addr, const void
/* Is this *really* the requested chunk? */
for(u = 0; u < udata->common.mesg->u.chunk.ndims; u++)
if(udata->common.offset[u] >= lt_key->offset[u] + udata->common.mesg->u.chunk.dim[u])
- HGOTO_DONE(FAIL)
+ HGOTO_DONE(FALSE)
/* Initialize return values */
HDassert(lt_key->nbytes > 0);
@@ -971,12 +971,12 @@ done:
*
*-------------------------------------------------------------------------
*/
-static haddr_t
+static herr_t
H5D_istore_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata)
{
- haddr_t ret_value; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_idx_get_addr)
+ FUNC_ENTER_NOAPI_NOINIT(H5D_istore_idx_get_addr)
HDassert(idx_info);
HDassert(idx_info->f);
@@ -984,23 +984,9 @@ H5D_istore_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udat
HDassert(idx_info->layout->u.chunk.ndims > 0);
HDassert(udata);
- /* Go get the chunk information */
- if(H5B_find(idx_info->f, idx_info->dxpl_id, H5B_ISTORE, idx_info->layout->u.chunk.addr, udata) < 0) {
- /* Note: don't push error on stack, leave that to next higher level,
- * since many times the B-tree is searched in order to determine
- * if a chunk exists in the B-tree or not. -QAK
- */
-#ifdef OLD_WAY
- H5E_clear_stack(NULL);
-
- HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, HADDR_UNDEF, "Can't locate chunk info")
-#else /* OLD_WAY */
- HGOTO_DONE(HADDR_UNDEF)
-#endif /* OLD_WAY */
- } /* end if */
-
- /* Success! Set the return value */
- ret_value = udata->addr;
+ /* Go get the chunk information from the B-tree */
+ if(H5B_find(idx_info->f, idx_info->dxpl_id, H5B_ISTORE, idx_info->layout->u.chunk.addr, udata) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk info")
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Dmpio.c b/src/H5Dmpio.c
index 04be442..99ad001 100644
--- a/src/H5Dmpio.c
+++ b/src/H5Dmpio.c
@@ -640,7 +640,7 @@ H5D_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info
if(io_option == H5D_ONE_LINK_CHUNK_IO) {
io_option = H5D_MULTI_CHUNK_IO; /* We can not do this with one chunk IO. */
#ifdef H5_HAVE_INSTRUMENTED_LIBRARY
- { int new_value;
+ { int new_value;
htri_t check_prop;
check_prop = H5Pexist(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_LINK_TO_MULTI);
if(check_prop > 0) {
@@ -664,7 +664,7 @@ H5D_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info
HGOTO_ERROR(H5E_IO, H5E_CANTSET, FAIL, "unable to set property value")
}
- }/* add this property because the library changes the option from one link to multiple chunks.*/
+ }/* add this property because the library changes the option from one link to multiple chunks.*/
#endif
}
#endif
@@ -848,6 +848,7 @@ H5D_link_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type
* equivalent of compressed contiguous datasets - QAK]
*/
if(total_chunks == 1) {
+ H5D_chunk_ud_t udata; /* User data for querying chunk info */
hsize_t coords[H5O_LAYOUT_NDIMS]; /* Coordinates of chunk in file dataset's dataspace */
H5SL_node_t *chunk_node; /* Pointer to chunk node for selection */
H5S_t *fspace; /* Dataspace describing chunk & selection in it */
@@ -858,8 +859,9 @@ H5D_link_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type
HDmemset(coords, 0, sizeof(coords));
/* Look up address of chunk */
- if(HADDR_UNDEF == (ctg_store.contig.dset_addr = H5D_chunk_get_addr(io_info->dset, io_info->dxpl_id, coords, NULL)))
+ if(H5D_chunk_get_info(io_info->dset, io_info->dxpl_id, coords, &udata) < 0)
HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't get chunk info from skipped list")
+ ctg_store.contig.dset_addr = udata.addr;
/* Check for this process having selection in this chunk */
chunk_node = H5SL_first(fm->sel_chunks);
@@ -1207,7 +1209,6 @@ if(H5DEBUG(D))
void *chunk; /* Pointer to the data chunk in cache */
uint32_t accessed_bytes; /* Total accessed size in a chunk */
unsigned idx_hint = 0; /* Cache index hint */
- haddr_t caddr; /* Address of the cached chunk */
/* Switch to independent I/O */
if(last_xfer_mode != H5FD_MPIO_INDEPENDENT) {
@@ -1219,11 +1220,11 @@ if(H5DEBUG(D))
/* Load the chunk into cache. But if the whole chunk is written,
* simply allocate space instead of load the chunk.
*/
- if(HADDR_UNDEF == (caddr = H5D_chunk_get_addr(io_info->dset, io_info->dxpl_id, chunk_info->coords, &udata)))
+ if(H5D_chunk_get_info(io_info->dset, io_info->dxpl_id, chunk_info->coords, &udata) < 0)
HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't get chunk info from skipped list")
/* Load the chunk into cache and lock it. */
- if(H5D_chunk_cacheable(io_info, caddr)) {
+ if(H5D_chunk_cacheable(io_info, udata.addr)) {
hbool_t entire_chunk = TRUE; /* Whether whole chunk is selected */
/* Compute # of bytes accessed in chunk */
@@ -1246,7 +1247,7 @@ if(H5DEBUG(D))
} /* end if */
else {
/* Set up the storage address information for this chunk */
- ctg_store.contig.dset_addr = caddr;
+ ctg_store.contig.dset_addr = udata.addr;
/* No chunk cached */
chunk = NULL;
@@ -1396,7 +1397,6 @@ if(H5DEBUG(D)) {
/* Iterate through chunks to be operated on */
while(chunk_node) {
H5D_chunk_info_t *chunk_info; /* chunk information */
- haddr_t chunk_addr; /* Address of chunk in file */
H5D_chunk_ud_t udata; /* B-tree pass-through */
hbool_t make_ind, make_coll; /* Flags to indicate that the MPI mode should change */
@@ -1434,8 +1434,8 @@ if(H5DEBUG(D)) {
#endif /* H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS */
/* Retrieve the chunk's address */
- if(HADDR_UNDEF == (chunk_addr = H5D_chunk_get_addr(io_info->dset, io_info->dxpl_id, chunk_info->coords, &udata)))
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk info from skipped list")
+ if(H5D_chunk_get_info(io_info->dset, io_info->dxpl_id, chunk_info->coords, &udata) < 0)
+ HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't get chunk info from skipped list")
/* Independent I/O */
if(make_ind) {
@@ -1449,7 +1449,7 @@ if(H5DEBUG(D)) {
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to independent I/O")
/* Load the chunk into cache and lock it. */
- if(H5D_chunk_cacheable(io_info, chunk_addr)) {
+ if(H5D_chunk_cacheable(io_info, udata.addr)) {
hbool_t entire_chunk = TRUE; /* Whether whole chunk is selected */
/* Compute # of bytes accessed in chunk */
@@ -1472,7 +1472,7 @@ if(H5DEBUG(D)) {
} /* end if */
else {
/* Set up the storage address information for this chunk */
- ctg_store.contig.dset_addr = chunk_addr;
+ ctg_store.contig.dset_addr = udata.addr;
/* No chunk cached */
chunk = NULL;
@@ -1499,7 +1499,7 @@ if(H5DEBUG(D)) {
} /* end if */
else { /*collective I/O */
/* Set up the storage address information for this chunk */
- ctg_store.contig.dset_addr = chunk_addr;
+ ctg_store.contig.dset_addr = udata.addr;
if(H5D_inter_collective_io(&ctg_io_info, type_info, chunk_info->fspace, chunk_info->mspace) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,"couldn't finish shared collective MPI-IO")
@@ -1743,8 +1743,12 @@ if(H5DEBUG(D))
HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk info from skipped list")
if(many_chunk_opt == H5D_OBTAIN_ONE_CHUNK_ADDR_IND) {
- if(HADDR_UNDEF == (chunk_addr = H5D_chunk_get_addr(io_info->dset, io_info->dxpl_id, chunk_info->coords, NULL)))
+ H5D_chunk_ud_t udata; /* User data for querying chunk info */
+
+ /* Get address of chunk */
+ if(H5D_chunk_get_info(io_info->dset, io_info->dxpl_id, chunk_info->coords, &udata) < 0)
HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't get chunk info from skipped list")
+ chunk_addr = udata.addr;
} /* end if */
else
chunk_addr = total_chunk_addr_array[chunk_info->index];
diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h
index f6732ff..09a3c2c 100644
--- a/src/H5Dpkg.h
+++ b/src/H5Dpkg.h
@@ -264,7 +264,7 @@ typedef herr_t (*H5D_chunk_init_func_t)(const H5D_chk_idx_info_t *idx_info);
typedef herr_t (*H5D_chunk_create_func_t)(const H5D_chk_idx_info_t *idx_info);
typedef herr_t (*H5D_chunk_insert_func_t)(const H5D_chk_idx_info_t *idx_info,
H5D_chunk_ud_t *udata);
-typedef haddr_t (*H5D_chunk_get_addr_func_t)(const H5D_chk_idx_info_t *idx_info,
+typedef herr_t (*H5D_chunk_get_addr_func_t)(const H5D_chk_idx_info_t *idx_info,
H5D_chunk_ud_t *udata);
typedef int (*H5D_chunk_iterate_func_t)(const H5D_chk_idx_info_t *idx_info,
H5D_chunk_cb_func_t chunk_cb, void *chunk_udata);
@@ -564,7 +564,7 @@ H5_DLL hbool_t H5D_chunk_cacheable(const H5D_io_info_t *io_info, haddr_t caddr);
H5_DLL herr_t H5D_chunk_cinfo_cache_reset(H5D_chunk_cached_t *last);
H5_DLL herr_t H5D_chunk_create(H5D_t *dset /*in,out*/, hid_t dxpl_id);
H5_DLL herr_t H5D_chunk_init(H5F_t *f, hid_t dxpl_id, const H5D_t *dset);
-H5_DLL haddr_t H5D_chunk_get_addr(const H5D_t *dset, hid_t dxpl_id,
+H5_DLL herr_t H5D_chunk_get_info(const H5D_t *dset, hid_t dxpl_id,
const hsize_t *chunk_offset, H5D_chunk_ud_t *udata);
H5_DLL void *H5D_chunk_lock(const H5D_io_info_t *io_info,
H5D_chunk_ud_t *udata, hbool_t relax, unsigned *idx_hint/*in,out*/);
diff --git a/src/H5EAcache.c b/src/H5EAcache.c
index 35a6916..fe64d05 100644
--- a/src/H5EAcache.c
+++ b/src/H5EAcache.c
@@ -458,11 +458,29 @@ END_FUNC(STATIC) /* end H5EA__cache_hdr_size() */
/* ARGSUSED */
BEGIN_FUNC(STATIC, ERR,
herr_t, SUCCEED, FAIL,
-H5EA__cache_hdr_dest(H5F_t UNUSED *f, H5EA_hdr_t *hdr))
+H5EA__cache_hdr_dest(H5F_t *f, H5EA_hdr_t *hdr))
/* Check arguments */
+ HDassert(f);
HDassert(hdr);
+ /* Verify that header is clean */
+ HDassert(hdr->cache_info.is_dirty == FALSE);
+
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!hdr->cache_info.free_file_space_on_destroy || H5F_addr_defined(hdr->cache_info.addr));
+
+ /* Check for freeing file space for extensible array header */
+ if(hdr->cache_info.free_file_space_on_destroy) {
+ /* Sanity check address */
+ HDassert(H5F_addr_eq(hdr->addr, hdr->cache_info.addr));
+
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_EARRAY_HDR, H5AC_dxpl_id, hdr->cache_info.addr, (hsize_t)hdr->size) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to free extensible array header")
+ } /* end if */
+
/* Release the extensible array header */
if(H5EA__hdr_dest(hdr) < 0)
H5E_THROW(H5E_CANTFREE, "can't free extensible array header")
@@ -803,8 +821,26 @@ herr_t, SUCCEED, FAIL,
H5EA__cache_iblock_dest(H5F_t *f, H5EA_iblock_t *iblock))
/* Sanity check */
+ HDassert(f);
HDassert(iblock);
+ /* Verify that index block is clean */
+ HDassert(iblock->cache_info.is_dirty == FALSE);
+
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!iblock->cache_info.free_file_space_on_destroy || H5F_addr_defined(iblock->cache_info.addr));
+
+ /* Check for freeing file space for extensible array index block */
+ if(iblock->cache_info.free_file_space_on_destroy) {
+ /* Sanity check address */
+ HDassert(H5F_addr_eq(iblock->addr, iblock->cache_info.addr));
+
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_EARRAY_IBLOCK, H5AC_dxpl_id, iblock->cache_info.addr, (hsize_t)iblock->size) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to free extensible array index block")
+ } /* end if */
+
/* Release the index block */
if(H5EA__iblock_dest(f, iblock) < 0)
H5E_THROW(H5E_CANTFREE, "can't free extensible array index block")
@@ -1112,8 +1148,26 @@ herr_t, SUCCEED, FAIL,
H5EA__cache_sblock_dest(H5F_t *f, H5EA_sblock_t *sblock))
/* Sanity check */
+ HDassert(f);
HDassert(sblock);
+ /* Verify that super block is clean */
+ HDassert(sblock->cache_info.is_dirty == FALSE);
+
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!sblock->cache_info.free_file_space_on_destroy || H5F_addr_defined(sblock->cache_info.addr));
+
+ /* Check for freeing file space for extensible array super block */
+ if(sblock->cache_info.free_file_space_on_destroy) {
+ /* Sanity check address */
+ HDassert(H5F_addr_eq(sblock->addr, sblock->cache_info.addr));
+
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_EARRAY_SBLOCK, H5AC_dxpl_id, sblock->cache_info.addr, (hsize_t)sblock->size) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to free extensible array super block")
+ } /* end if */
+
/* Release the super block */
if(H5EA__sblock_dest(f, sblock) < 0)
H5E_THROW(H5E_CANTFREE, "can't free extensible array super block")
@@ -1314,7 +1368,7 @@ H5EA__cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
/* Metadata checksum */
UINT32ENCODE(p, metadata_chksum);
- /* Write the index block */
+ /* Write the data block */
HDassert((size_t)(p - buf) == size);
if(H5F_block_write(f, H5FD_MEM_EARRAY_DBLOCK, addr, size, dxpl_id, buf) < 0)
H5E_THROW(H5E_WRITEERROR, "unable to save extensible array data block to disk")
@@ -1418,8 +1472,26 @@ herr_t, SUCCEED, FAIL,
H5EA__cache_dblock_dest(H5F_t *f, H5EA_dblock_t *dblock))
/* Sanity check */
+ HDassert(f);
HDassert(dblock);
+ /* Verify that data block is clean */
+ HDassert(dblock->cache_info.is_dirty == FALSE);
+
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!dblock->cache_info.free_file_space_on_destroy || H5F_addr_defined(dblock->cache_info.addr));
+
+ /* Check for freeing file space for extensible array data block */
+ if(dblock->cache_info.free_file_space_on_destroy) {
+ /* Sanity check address */
+ HDassert(H5F_addr_eq(dblock->addr, dblock->cache_info.addr));
+
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_EARRAY_DBLOCK, H5AC_dxpl_id, dblock->cache_info.addr, (hsize_t)dblock->size) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to free extensible array data block")
+ } /* end if */
+
/* Release the data block */
if(H5EA__dblock_dest(f, dblock) < 0)
H5E_THROW(H5E_CANTFREE, "can't free extensible array data block")
diff --git a/src/H5EAdblock.c b/src/H5EAdblock.c
index 0c29741..2d0d241 100644
--- a/src/H5EAdblock.c
+++ b/src/H5EAdblock.c
@@ -363,13 +363,9 @@ HDfprintf(stderr, "%s: Called\n", FUNC);
if(NULL == (dblock = H5EA__dblock_protect(hdr, dxpl_id, dblk_addr, dblk_nelmts, H5AC_WRITE)))
H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array data block, address = %llu", (unsigned long_long)dblk_addr)
- /* Release data block's disk space */
- if(H5MF_xfree(hdr->f, H5FD_MEM_EARRAY_DBLOCK, dxpl_id, dblk_addr, (hsize_t)dblock->size) < 0)
- H5E_THROW(H5E_CANTFREE, "unable to free extensible array data block")
-
CATCH
/* Finished deleting data block in metadata cache */
- if(dblock && H5EA__dblock_unprotect(dblock, dxpl_id, H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG) < 0)
+ if(dblock && H5EA__dblock_unprotect(dblock, dxpl_id, H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array data block")
END_FUNC(PKG) /* end H5EA__dblock_delete() */
diff --git a/src/H5EAhdr.c b/src/H5EAhdr.c
index f11fc70..9fb3c73 100644
--- a/src/H5EAhdr.c
+++ b/src/H5EAhdr.c
@@ -614,12 +614,8 @@ HDfprintf(stderr, "%s: hdr->idx_blk_addr = %a\n", FUNC, hdr->idx_blk_addr);
H5E_THROW(H5E_CANTDELETE, "unable to delete extensible array index block")
} /* end if */
- /* Release header's disk space */
- if(H5MF_xfree(hdr->f, H5FD_MEM_EARRAY_HDR, dxpl_id, hdr->addr, (hsize_t)hdr->size) < 0)
- H5E_THROW(H5E_CANTFREE, "unable to release extensible array header")
-
/* Finished deleting header */
- if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_EARRAY_HDR, hdr->addr, hdr, H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG) < 0)
+ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_EARRAY_HDR, hdr->addr, hdr, H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array header")
hdr = NULL;
diff --git a/src/H5EAiblock.c b/src/H5EAiblock.c
index 152d438..4928c28 100644
--- a/src/H5EAiblock.c
+++ b/src/H5EAiblock.c
@@ -395,13 +395,9 @@ HDfprintf(stderr, "%s: Called\n", FUNC);
} /* end for */
} /* end if */
- /* Release index block's disk space */
- if(H5MF_xfree(hdr->f, H5FD_MEM_EARRAY_IBLOCK, dxpl_id, hdr->idx_blk_addr, (hsize_t)iblock->size) < 0)
- H5E_THROW(H5E_CANTFREE, "unable to free extensible array index block")
-
CATCH
/* Finished deleting index block in metadata cache */
- if(iblock && H5EA__iblock_unprotect(iblock, dxpl_id, H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG) < 0)
+ if(iblock && H5EA__iblock_unprotect(iblock, dxpl_id, H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array index block")
END_FUNC(PKG) /* end H5EA__iblock_delete() */
diff --git a/src/H5EAsblock.c b/src/H5EAsblock.c
index 89f4d4a..b774812 100644
--- a/src/H5EAsblock.c
+++ b/src/H5EAsblock.c
@@ -340,13 +340,9 @@ HDfprintf(stderr, "%s: Called\n", FUNC);
} /* end for */
} /* end if */
- /* Release super block's disk space */
- if(H5MF_xfree(hdr->f, H5FD_MEM_EARRAY_SBLOCK, dxpl_id, sblk_addr, (hsize_t)sblock->size) < 0)
- H5E_THROW(H5E_CANTFREE, "unable to free extensible array super block")
-
CATCH
/* Finished deleting super block in metadata cache */
- if(sblock && H5EA__sblock_unprotect(sblock, dxpl_id, H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG) < 0)
+ if(sblock && H5EA__sblock_unprotect(sblock, dxpl_id, H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array super block")
END_FUNC(PKG) /* end H5EA__sblock_delete() */
diff --git a/src/H5F.c b/src/H5F.c
index 02687eb..f7c0022 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -29,6 +29,7 @@
#include "H5FDprivate.h" /* File drivers */
#include "H5Gprivate.h" /* Groups */
#include "H5Iprivate.h" /* IDs */
+#include "H5MFprivate.h" /* File memory management */
#include "H5MMprivate.h" /* Memory management */
#include "H5Pprivate.h" /* Property lists */
#include "H5SMprivate.h" /* Shared Object Header Messages */
@@ -321,11 +322,11 @@ H5F_get_access_plist(H5F_t *f, hbool_t app_ref)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set alignment")
if(H5P_set(new_plist, H5F_ACS_GARBG_COLCT_REF_NAME, &(f->shared->gc_ref)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set garbage collect reference")
- if(H5P_set(new_plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(f->shared->lf->meta_aggr.alloc_size)) < 0)
+ if(H5P_set(new_plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(f->shared->meta_aggr.alloc_size)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set metadata cache size")
if(H5P_set(new_plist, H5F_ACS_SIEVE_BUF_SIZE_NAME, &(f->shared->sieve_buf_size)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't sieve buffer size")
- if(H5P_set(new_plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(f->shared->lf->sdata_aggr.alloc_size)) < 0)
+ if(H5P_set(new_plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(f->shared->sdata_aggr.alloc_size)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set 'small data' cache size")
if(H5P_set(new_plist, H5F_ACS_LATEST_FORMAT_NAME, &(f->shared->latest_format)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set 'latest format' flag")
@@ -797,31 +798,31 @@ done:
htri_t
H5Fis_hdf5(const char *name)
{
- H5FD_t *file = NULL;
- htri_t ret_value;
+ H5FD_t *file = NULL; /* Low-level file struct */
+ htri_t ret_value; /* Return value */
FUNC_ENTER_API(H5Fis_hdf5, FAIL)
H5TRACE1("t", "*s", name);
/* Check args and all the boring stuff. */
- if (!name || !*name)
+ if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "no file name specified")
/* Open the file at the virtual file layer */
- if (NULL==(file=H5FD_open(name, H5F_ACC_RDONLY, H5P_FILE_ACCESS_DEFAULT, HADDR_UNDEF)))
+ if(NULL == (file = H5FD_open(name, H5F_ACC_RDONLY, H5P_FILE_ACCESS_DEFAULT, HADDR_UNDEF)))
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to open file")
/* The file is an hdf5 file if the hdf5 file signature can be found */
- ret_value = (HADDR_UNDEF!=H5F_locate_signature(file, H5AC_ind_dxpl_id));
+ ret_value = (HADDR_UNDEF != H5F_locate_signature(file, H5AC_ind_dxpl_id));
done:
/* Close the file */
- if (file)
- if(H5FD_close(file) < 0 && ret_value>=0)
+ if(file)
+ if(H5FD_close(file) < 0 && ret_value >= 0)
HDONE_ERROR(H5E_IO, H5E_CANTCLOSEFILE, FAIL, "unable to close file")
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Fis_hdf5() */
/*-------------------------------------------------------------------------
@@ -879,17 +880,20 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf)
} /* end if */
else {
unsigned super_vers = HDF5_SUPERBLOCK_VERSION_DEF; /* Superblock version for file */
- H5P_genplist_t *plist; /* Property list */
+ H5P_genplist_t *plist; /* Property list */
+ size_t u; /* Local index variable */
HDassert(lf != NULL);
if(NULL == (f->shared = H5FL_CALLOC(H5F_file_t)))
HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate shared file structure")
- f->shared->super_addr = HADDR_UNDEF;
f->shared->base_addr = HADDR_UNDEF;
f->shared->extension_addr = HADDR_UNDEF;
f->shared->sohm_addr = HADDR_UNDEF;
f->shared->sohm_vers = HDF5_SHAREDHEADER_VERSION;
+ for(u = 0; u < NELMTS(f->shared->fs_addr); u++)
+ f->shared->fs_addr[u] = HADDR_UNDEF;
f->shared->driver_addr = HADDR_UNDEF;
+ f->shared->accum.loc = HADDR_UNDEF;
f->shared->lf = lf;
/*
@@ -935,11 +939,23 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get sieve buffer size")
if(H5P_get(plist, H5F_ACS_LATEST_FORMAT_NAME, &(f->shared->latest_format)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'latest format' flag")
+ if(H5P_get(plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(f->shared->meta_aggr.alloc_size)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get metadata cache size")
+ f->shared->meta_aggr.feature_flag = H5FD_FEAT_AGGREGATE_METADATA;
+ if(H5P_get(plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(f->shared->sdata_aggr.alloc_size)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'small data' cache size")
+ f->shared->sdata_aggr.feature_flag = H5FD_FEAT_AGGREGATE_SMALLDATA;
/* Get the VFD values to cache */
f->shared->maxaddr = H5FD_get_maxaddr(lf);
if(!H5F_addr_defined(f->shared->maxaddr))
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad maximum address from VFD")
+ if(H5FD_get_feature_flags(lf, &f->shared->feature_flags) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get feature flags from VFD")
+ if(H5FD_get_fs_type_map(lf, f->shared->fs_type_map) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get free space type mapping from VFD")
+ if(H5MF_init_merge_flags(f) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "problem initializing free space merge flags")
/* Bump superblock version if we are to use the latest version of the format */
if(f->shared->latest_format)
@@ -1073,6 +1089,9 @@ H5F_dest(H5F_t *f, hid_t dxpl_id)
if(H5AC_dest(f, dxpl_id))
/* Push error, but keep going*/
HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
+ if(H5F_accum_reset(f) < 0)
+ /* Push error, but keep going*/
+ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
if(H5FO_dest(f) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
@@ -1765,6 +1784,18 @@ H5F_flush(H5F_t *f, hid_t dxpl_id, H5F_scope_t scope, unsigned flags)
if(H5D_flush(f, dxpl_id, flags) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush dataset cache")
+ /* If we will be closing the file, we should release the free space
+ * information now (needs to happen before truncating the file and
+ * before the metadata cache is shut down, since the free space manager is
+ * holding some data structures in memory and also because releasing free
+ * space can shrink the file's 'eoa' value)
+ */
+ if(flags & H5F_FLUSH_CLOSING) {
+ /* Shutdown file free space manager(s) */
+ if(H5MF_close(f, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release file free space info")
+ } /* end if */
+
/* flush (and invalidate, if requested) the entire metadata cache */
H5AC_flags = 0;
if((flags & H5F_FLUSH_INVALIDATE) != 0 )
@@ -1772,23 +1803,21 @@ H5F_flush(H5F_t *f, hid_t dxpl_id, H5F_scope_t scope, unsigned flags)
if(H5AC_flush(f, dxpl_id, H5AC_flags) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush metadata cache")
- /*
- * If we are invalidating everything (which only happens just before
- * the file closes), release the unused portion of the metadata and
- * "small data" blocks back to the free lists in the file.
+ /* Truncate the file to the current allocated size */
+ /* (needs to happen before superblock write, since the 'eoa' value is
+ * written in superblock -QAK)
*/
- if(flags & H5F_FLUSH_INVALIDATE) {
- if(H5FD_aggr_reset(f->shared->lf, &(f->shared->lf->meta_aggr), dxpl_id) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "can't reset metadata block")
-
- if(H5FD_aggr_reset(f->shared->lf, &(f->shared->lf->sdata_aggr), dxpl_id) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "can't reset 'small data' block")
- } /* end if */
+ if(H5FD_truncate(f->shared->lf, dxpl_id, (unsigned)((flags & H5F_FLUSH_CLOSING) > 0)) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "low level truncate failed")
/* Write the superblock to disk */
if(H5F_super_write(f, dxpl_id) != SUCCEED)
HGOTO_ERROR(H5E_CACHE, H5E_WRITEERROR, FAIL, "unable to write superblock to file")
+ /* Flush out the metadata accumulator */
+ if(H5F_accum_flush(f, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to flush metadata accumulator")
+
/* Flush file buffers to disk. */
if(H5FD_flush(f->shared->lf, dxpl_id, (unsigned)((flags & H5F_FLUSH_CLOSING) > 0)) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "low level flush failed")
@@ -2004,7 +2033,7 @@ H5F_try_close(H5F_t *f)
*/
if(f->intent&H5F_ACC_RDWR) {
/* Flush and destroy all caches */
- if(H5F_flush(f, H5AC_dxpl_id, H5F_SCOPE_LOCAL, H5C__NO_FLAGS_SET) < 0)
+ if(H5F_flush(f, H5AC_dxpl_id, H5F_SCOPE_LOCAL, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache")
} /* end if */
@@ -2138,410 +2167,37 @@ done:
* Programmer: James Laird
* August 23, 2006
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
herr_t
H5Fget_intent(hid_t file_id, unsigned *intent_flags)
{
- H5F_t * file = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_API(H5Fget_intent, FAIL)
H5TRACE2("e", "i*Iu", file_id, intent_flags);
- if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
-
/* If no intent flags were passed in, exit quietly */
- if(!intent_flags)
- HGOTO_DONE(SUCCEED)
+ if(intent_flags) {
+ H5F_t * file; /* Pointer to file structure */
- *intent_flags = H5F_get_intent(file);
+ /* Get the internal file structure */
+ if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
- /* HDF5 uses some flags internally that users don't know about.
- * Simplify things for them so that they get one of H5F_ACC_RDWR
- * or H5F_ACC_RDONLY.
- */
- if(*intent_flags & H5F_ACC_RDWR)
- *intent_flags = H5F_ACC_RDWR;
- else
- *intent_flags = H5F_ACC_RDONLY;
+ /* HDF5 uses some flags internally that users don't know about.
+ * Simplify things for them so that they only get either H5F_ACC_RDWR
+ * or H5F_ACC_RDONLY.
+ */
+ if(H5F_INTENT(file) & H5F_ACC_RDWR)
+ *intent_flags = H5F_ACC_RDWR;
+ else
+ *intent_flags = H5F_ACC_RDONLY;
+ } /* end if */
done:
FUNC_LEAVE_API(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_get_intent
- *
- * Purpose: Quick and dirty routine to retrieve the file's 'intent' flags
- * (Mainly added to stop non-file routines from poking about in the
- * H5F_t data structure)
- *
- * Return: 'intent' on success/abort on failure (shouldn't fail)
- *
- * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
- * September 29, 2000
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-unsigned
-H5F_get_intent(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_intent)
-
- HDassert(f);
-
- FUNC_LEAVE_NOAPI(f->intent)
-} /* end H5F_get_intent() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_get_extpath
- *
- * Purpose: Retrieve the file's 'extpath' flags
- * This is used by H5L_extern_traverse() to retrieve the main file's location
- * when searching the target file.
- *
- * Return: 'extpath' on success/abort on failure (shouldn't fail)
- *
- * Programmer: Vailin Choi, April 2, 2008
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-char *
-H5F_get_extpath(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_extpath)
-
- HDassert(f);
-
- FUNC_LEAVE_NOAPI(f->extpath)
-} /* end H5F_get_extpath() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_sizeof_addr
- *
- * Purpose: Quick and dirty routine to retrieve the size of the file's size_t
- * (Mainly added to stop non-file routines from poking about in the
- * H5F_t data structure)
- *
- * Return: 'sizeof_addr' on success/abort on failure (shouldn't fail)
- *
- * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
- * September 29, 2000
- *
- * Modifications:
- *
- * Raymond Lu, Oct 14, 2001
- * Changed to generic property list.
- *
- *-------------------------------------------------------------------------
- */
-size_t
-H5F_sizeof_addr(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sizeof_addr)
-
- assert(f);
- assert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->sizeof_addr)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_sizeof_size
- *
- * Purpose: Quick and dirty routine to retrieve the size of the file's off_t
- * (Mainly added to stop non-file routines from poking about in the
- * H5F_t data structure)
- *
- * Return: 'sizeof_size' on success/abort on failure (shouldn't fail)
- *
- * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
- * September 29, 2000
- *
- *-------------------------------------------------------------------------
- */
-size_t
-H5F_sizeof_size(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sizeof_size)
-
- assert(f);
- assert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->sizeof_size)
-} /* H5F_sizeof_size() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_sym_leaf_k
- *
- * Purpose: Replaced a macro to retrieve the symbol table leaf size,
- * now that the generic properties are being used to store
- * the values.
- *
- * Return: Success: Non-negative, and the symbol table leaf size is
- * returned.
- *
- * Failure: Negative (should not happen)
- *
- * Programmer: Raymond Lu
- * slu@ncsa.uiuc.edu
- * Oct 14 2001
- *
- *-------------------------------------------------------------------------
- */
-unsigned
-H5F_sym_leaf_k(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sym_leaf_k)
-
- assert(f);
- assert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->sym_leaf_k)
-} /* end H5F_sym_leaf_k() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_Kvalue
- *
- * Purpose: Replaced a macro to retrieve a B-tree key value for a certain
- * type, now that the generic properties are being used to store
- * the B-tree values.
- *
- * Return: Success: Non-negative, and the B-tree key value is
- * returned.
- *
- * Failure: Negative (should not happen)
- *
- * Programmer: Raymond Lu
- * slu@ncsa.uiuc.edu
- * Oct 14 2001
- *
- *-------------------------------------------------------------------------
- */
-unsigned
-H5F_Kvalue(const H5F_t *f, const H5B_class_t *type)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_Kvalue)
-
- assert(f);
- assert(f->shared);
- assert(type);
-
- FUNC_LEAVE_NOAPI(f->shared->btree_k[type->id])
-} /* end H5F_Kvalue() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_rdcc_nelmts
- *
- * Purpose: Replaced a macro to retrieve the raw data cache number of elments,
- * now that the generic properties are being used to store
- * the values.
- *
- * Return: Success: Non-negative, and the raw data cache number of
- * of elemnts is returned.
- *
- * Failure: Negative (should not happen)
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Jun 1 2004
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-size_t
-H5F_rdcc_nelmts(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_rdcc_nelmts)
-
- assert(f);
- assert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->rdcc_nelmts)
-} /* end H5F_rdcc_nelmts() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_rdcc_nbytes
- *
- * Purpose: Replaced a macro to retrieve the raw data cache number of bytes,
- * now that the generic properties are being used to store
- * the values.
- *
- * Return: Success: Non-negative, and the raw data cache number of
- * of bytes is returned.
- *
- * Failure: Negative (should not happen)
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Jun 1 2004
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-size_t
-H5F_rdcc_nbytes(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_rdcc_nbytes)
-
- assert(f);
- assert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->rdcc_nbytes)
-} /* end H5F_rdcc_nbytes() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_rdcc_w0
- *
- * Purpose: Replaced a macro to retrieve the raw data cache 'w0' value
- * now that the generic properties are being used to store
- * the values.
- *
- * Return: Success: Non-negative, and the raw data cache 'w0' value
- * is returned.
- *
- * Failure: Negative (should not happen)
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Jun 2 2004
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-double
-H5F_rdcc_w0(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_rdcc_w0)
-
- assert(f);
- assert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->rdcc_w0)
-} /* end H5F_rdcc_w0() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_has_feature
- *
- * Purpose: Check if a file has a particular feature enabled
- *
- * Return: Success: Non-negative - TRUE or FALSE
- * Failure: Negative (should not happen)
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * May 31 2004
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-hbool_t
-H5F_has_feature(const H5F_t *f, unsigned feature)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_has_feature)
-
- assert(f);
- assert(f->shared);
-
- FUNC_LEAVE_NOAPI((hbool_t)(f->shared->lf->feature_flags&feature))
-} /* end H5F_has_feature() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_get_driver_id
- *
- * Purpose: Quick and dirty routine to retrieve the file's 'driver_id' value
- * (Mainly added to stop non-file routines from poking about in the
- * H5F_t data structure)
- *
- * Return: 'driver_id' on success/abort on failure (shouldn't fail)
- *
- * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
- * October 10, 2000
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-hid_t
-H5F_get_driver_id(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_driver_id)
-
- assert(f);
- assert(f->shared);
- assert(f->shared->lf);
-
- FUNC_LEAVE_NOAPI(f->shared->lf->driver_id)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_get_fileno
- *
- * Purpose: Quick and dirty routine to retrieve the file's 'fileno' value
- * (Mainly added to stop non-file routines from poking about in the
- * H5F_t data structure)
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
- * March 27, 2002
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5F_get_fileno(const H5F_t *f, unsigned long *filenum)
-{
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(H5F_get_fileno, FAIL)
-
- HDassert(f);
- HDassert(f->shared);
- HDassert(f->shared->lf);
- HDassert(filenum);
-
- /* Retrieve the file's serial number */
- if(H5FD_get_fileno(f->shared->lf, filenum) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, FAIL, "can't retrieve fileno")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_get_fileno() */
+} /* end H5Fget_intent() */
/*-------------------------------------------------------------------------
@@ -2584,35 +2240,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5F_get_base_addr
- *
- * Purpose: Quick and dirty routine to retrieve the file's 'base_addr' value
- * (Mainly added to stop non-file routines from poking about in the
- * H5F_t data structure)
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Raymond Lu <slu@ncsa.uiuc.edu>
- * December 20, 2002
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-haddr_t
-H5F_get_base_addr(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_base_addr)
-
- assert(f);
- assert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->base_addr)
-} /* end H5F_get_base_addr() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5F_get_eoa
*
* Purpose: Quick and dirty routine to retrieve the file's 'eoa' value
@@ -2622,314 +2249,26 @@ H5F_get_base_addr(const H5F_t *f)
* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
* June 1, 2004
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
haddr_t
-H5F_get_eoa(const H5F_t *f)
+H5F_get_eoa(const H5F_t *f, H5FD_mem_t type)
{
haddr_t ret_value;
FUNC_ENTER_NOAPI(H5F_get_eoa, HADDR_UNDEF)
- assert(f);
- assert(f->shared);
+ HDassert(f);
+ HDassert(f->shared);
/* Dispatch to driver */
- if (HADDR_UNDEF==(ret_value=H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT)))
+ if(HADDR_UNDEF == (ret_value = H5FD_get_eoa(f->shared->lf, type)))
HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "driver get_eoa request failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_get_eoa() */
-#ifdef H5_HAVE_PARALLEL
-
-/*-------------------------------------------------------------------------
- * Function: H5F_mpi_get_rank
- *
- * Purpose: Retrieves the rank of an MPI process.
- *
- * Return: Success: The rank (non-negative)
- *
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * Friday, January 30, 2004
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-int
-H5F_mpi_get_rank(const H5F_t *f)
-{
- int ret_value;
-
- FUNC_ENTER_NOAPI(H5F_mpi_get_rank, FAIL)
-
- assert(f && f->shared);
-
- /* Dispatch to driver */
- if ((ret_value=H5FD_mpi_get_rank(f->shared->lf)) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "driver get_rank request failed")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_mpi_get_rank() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_mpi_get_comm
- *
- * Purpose: Retrieves the file's communicator
- *
- * Return: Success: The communicator (non-negative)
- *
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * Friday, January 30, 2004
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-MPI_Comm
-H5F_mpi_get_comm(const H5F_t *f)
-{
- MPI_Comm ret_value;
-
- FUNC_ENTER_NOAPI(H5F_mpi_get_comm, MPI_COMM_NULL)
-
- assert(f && f->shared);
-
- /* Dispatch to driver */
- if ((ret_value=H5FD_mpi_get_comm(f->shared->lf))==MPI_COMM_NULL)
- HGOTO_ERROR(H5E_VFL, H5E_CANTGET, MPI_COMM_NULL, "driver get_comm request failed")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_mpi_get_comm() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_mpi_get_size
- *
- * Purpose: Retrieves the size of an MPI process.
- *
- * Return: Success: The size (positive)
- *
- * Failure: Negative
- *
- * Programmer: John Mainzer
- * Friday, May 6, 2005
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-int
-H5F_mpi_get_size(const H5F_t *f)
-{
- int ret_value;
-
- FUNC_ENTER_NOAPI(H5F_mpi_get_size, FAIL)
-
- assert(f && f->shared);
-
- /* Dispatch to driver */
- if ((ret_value=H5FD_mpi_get_size(f->shared->lf)) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "driver get_size request failed")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_mpi_get_size() */
-#endif /* H5_HAVE_PARALLEL */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_grp_btree_shared
- *
- * Purpose: Replaced a macro to retrieve the shared B-tree node info
- * now that the generic properties are being used to store
- * the values.
- *
- * Return: Success: Non-void, and the shared B-tree node info
- * is returned.
- *
- * Failure: void (should not happen)
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Jul 5 2004
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-H5RC_t *
-H5F_grp_btree_shared(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_grp_btree_shared)
-
- assert(f);
- assert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->grp_btree_shared)
-} /* end H5F_grp_btree_shared() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_sieve_buf_size
- *
- * Purpose: Replaced a macro to retrieve the dataset sieve buffer size
- * now that the generic properties are being used to store
- * the values.
- *
- * Return: Success: Non-void, and the dataset sieve buffer size
- * is returned.
- *
- * Failure: void (should not happen)
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Jul 8 2005
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-size_t
-H5F_sieve_buf_size(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sieve_buf_size)
-
- assert(f);
- assert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->sieve_buf_size)
-} /* end H5F_sieve_buf_size() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_gc_ref
- *
- * Purpose: Replaced a macro to retrieve the "garbage collect
- * references flag" now that the generic properties are being used
- * to store the values.
- *
- * Return: Success: The "garbage collect references flag"
- * is returned.
- *
- * Failure: (should not happen)
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Jul 8 2005
- *
- *-------------------------------------------------------------------------
- */
-unsigned
-H5F_gc_ref(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_gc_ref)
-
- HDassert(f);
- HDassert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->gc_ref)
-} /* end H5F_gc_ref() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_get_fcpl
- *
- * Purpose: Retrieve the value of a file's FCPL.
- *
- * Return: Success: The FCPL for the file.
- *
- * Failure: ? (should not happen)
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * May 25 2005
- *
- *-------------------------------------------------------------------------
- */
-hid_t
-H5F_get_fcpl(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_fcpl)
-
- assert(f);
- assert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->fcpl_id)
-} /* end H5F_get_fcpl() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_use_latest_format
- *
- * Purpose: Retrieve the 'use the latest version of the format' flag for
- * the file.
- *
- * Return: Success: Non-negative, the 'use the latest format' flag
- *
- * Failure: (can't happen)
- *
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Oct 2 2006
- *
- *-------------------------------------------------------------------------
- */
-hbool_t
-H5F_use_latest_format(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_use_latest_format)
-
- HDassert(f);
- HDassert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->latest_format)
-} /* end H5F_use_latest_format() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_get_fc_degree
- *
- * Purpose: Retrieve the 'file close degree' for the file.
- *
- * Return: Success: Non-negative, the 'file close degree'
- *
- * Failure: (can't happen)
- *
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Mar 5 2007
- *
- *-------------------------------------------------------------------------
- */
-H5F_close_degree_t
-H5F_get_fc_degree(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_fc_degree)
-
- HDassert(f);
- HDassert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->fc_degree)
-} /* end H5F_get_fc_degree() */
-
/*-------------------------------------------------------------------------
* Function: H5F_incr_nopen_objs
@@ -2986,148 +2325,6 @@ H5F_decr_nopen_objs(H5F_t *f)
/*-------------------------------------------------------------------------
- * Function: H5F_store_msg_crt_idx
- *
- * Purpose: Retrieve the 'store message creation index' flag for the file.
- *
- * Return: Success: Non-negative, the 'store message creation index' flag
- *
- * Failure: (can't happen)
- *
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Mar 6 2007
- *
- *-------------------------------------------------------------------------
- */
-hbool_t
-H5F_store_msg_crt_idx(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_store_msg_crt_idx)
-
- HDassert(f);
- HDassert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->store_msg_crt_idx)
-} /* end H5F_store_msg_crt_idx() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_block_read
- *
- * Purpose: Reads some data from a file/server/etc into a buffer.
- * The data is contiguous. The address is relative to the base
- * address for the file.
- *
- * Errors:
- * IO READERROR Low-level read failed.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Jul 10 1997
- *
- * Modifications:
- * Albert Cheng, 1998-06-02
- * Added XFER_MODE argument
- *
- * Robb Matzke, 1999-07-28
- * The ADDR argument is passed by value.
- *
- * Robb Matzke, 1999-08-02
- * Modified to use the virtual file layer. The data transfer
- * property list is passed in by object ID since that's how the
- * virtual file layer needs it.
- *-------------------------------------------------------------------------
- */
-herr_t
-H5F_block_read(const H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size, hid_t dxpl_id,
- void *buf/*out*/)
-{
- haddr_t abs_addr;
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5F_block_read, FAIL)
-
- assert (f);
- assert (f->shared);
- assert(size<SIZET_MAX);
- assert (buf);
-
- /* convert the relative address to an absolute address */
- abs_addr = f->shared->base_addr + addr;
-
- /* Read the data */
- if(H5FD_read(f->shared->lf, type, dxpl_id, abs_addr, size, buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file read failed")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_block_write
- *
- * Purpose: Writes some data from memory to a file/server/etc. The
- * data is contiguous. The address is relative to the base
- * address.
- *
- * Errors:
- * IO WRITEERROR Low-level write failed.
- * IO WRITEERROR No write intent.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Jul 10 1997
- *
- * Modifications:
- * Albert Cheng, 1998-06-02
- * Added XFER_MODE argument
- *
- * Robb Matzke, 1999-07-28
- * The ADDR argument is passed by value.
- *
- * Robb Matzke, 1999-08-02
- * Modified to use the virtual file layer. The data transfer
- * property list is passed in by object ID since that's how the
- * virtual file layer needs it.
- *-------------------------------------------------------------------------
- */
-herr_t
-H5F_block_write(const H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
- hid_t dxpl_id, const void *buf)
-{
- haddr_t abs_addr;
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5F_block_write, FAIL)
-
- assert (f);
- assert (f->shared);
- assert (size<SIZET_MAX);
- assert (buf);
-
- if (0==(f->intent & H5F_ACC_RDWR))
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "no write intent")
-
- /* Convert the relative address to an absolute address */
- abs_addr = f->shared->base_addr + addr;
-
- /* Write the data */
- if (H5FD_write(f->shared->lf, type, dxpl_id, abs_addr, size, buf))
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
* Function: H5F_addr_encode
*
* Purpose: Encodes an address into the buffer pointed to by *PP and
@@ -3234,7 +2431,7 @@ H5F_addr_decode(const H5F_t *f, const uint8_t **pp/*in,out*/, haddr_t *addr_p/*o
hssize_t
H5Fget_freespace(hid_t file_id)
{
- H5F_t *file=NULL; /* File object for file ID */
+ H5F_t *file; /* File object for file ID */
hssize_t ret_value; /* Return value */
FUNC_ENTER_API(H5Fget_freespace, FAIL)
@@ -3245,7 +2442,7 @@ H5Fget_freespace(hid_t file_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
/* Go get the actual amount of free space in the file */
- if((ret_value = H5FD_get_freespace(file->shared->lf)) < 0)
+ if((ret_value = H5MF_get_freespace(file, H5AC_ind_dxpl_id)) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to check free space for file")
done:
@@ -3275,19 +2472,19 @@ herr_t
H5Fget_filesize(hid_t file_id, hsize_t *size)
{
H5F_t *file; /* File object for file ID */
- haddr_t eof;
- herr_t ret_value = SUCCEED; /* Return value */
+ haddr_t eof; /* End of file address */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Fget_filesize, FAIL)
H5TRACE2("e", "i*h", file_id, size);
/* Check args */
if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
/* Go get the actual file size */
- if((eof = H5FDget_eof(file->shared->lf)) == HADDR_UNDEF)
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file size")
+ if(HADDR_UNDEF == (eof = H5FDget_eof(file->shared->lf)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file size")
*size = (hsize_t)eof;
diff --git a/src/H5FD.c b/src/H5FD.c
index 3973037..9eacd3e 100644
--- a/src/H5FD.c
+++ b/src/H5FD.c
@@ -62,9 +62,6 @@
/* Local Macros */
/****************/
-/* Metadata accumulator controls */
-#define H5FD_ACCUM_THROTTLE 8
-#define H5FD_ACCUM_THRESHOLD 2048
/******************/
/* Local Typedefs */
@@ -1053,23 +1050,23 @@ done:
H5FD_t *
H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
{
- H5FD_class_t *driver;
- H5FD_t *file = NULL;
- hid_t driver_id = -1;
- hsize_t meta_block_size = 0;
- hsize_t sdata_block_size = 0;
- H5P_genplist_t *plist; /* Property list pointer */
- H5FD_t *ret_value;
+ H5FD_class_t *driver; /* VFD for file */
+ H5FD_t *file = NULL; /* VFD file struct */
+ hid_t driver_id = -1; /* VFD ID */
+ H5P_genplist_t *plist; /* Property list pointer */
+ H5FD_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5FD_open, NULL)
- /* Get file access property list */
- if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list")
-
+ /* Sanity check */
if(0 == maxaddr)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "zero format address range")
+ /* Get file access property list */
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list");
+
+ /* Get the VFD to open the file with */
if(H5P_get(plist, H5F_ACS_FILE_DRV_ID_NAME, &driver_id) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get driver ID")
@@ -1094,16 +1091,6 @@ H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
HGOTO_ERROR(H5E_VFL, H5E_CANTINC, NULL, "unable to increment ref count on VFL driver")
file->cls = driver;
file->maxaddr = maxaddr;
- HDmemset(file->fl, 0, sizeof(file->fl));
- if(H5P_get(plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(meta_block_size)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get meta data block size")
- file->meta_aggr.feature_flag = H5FD_FEAT_AGGREGATE_METADATA;
- file->meta_aggr.alloc_size = meta_block_size;
- if(H5P_get(plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(sdata_block_size)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'small data' block size")
- file->sdata_aggr.feature_flag = H5FD_FEAT_AGGREGATE_SMALLDATA;
- file->sdata_aggr.alloc_size = sdata_block_size;
- file->accum_loc = HADDR_UNDEF;
if(H5P_get(plist, H5F_ACS_ALIGN_THRHD_NAME, &(file->threshold)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get alignment threshold")
if(H5P_get(plist, H5F_ACS_ALIGN_NAME, &(file->alignment)) < 0)
@@ -1120,6 +1107,10 @@ H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
} /* end if */
file->fileno = file_serial_no;
+ /* Start with base address set to 0 */
+ /* (This will be changed later, when the superblock is located) */
+ file->base_addr = 0;
+
/* Set return value */
ret_value = file;
@@ -1203,10 +1194,6 @@ H5FD_close(H5FD_t *file)
/* check args */
HDassert(file && file->cls);
- /* Free the freelist */
- if(H5FD_free_freelist(file) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "can't release file space free list")
-
/* Prepare to close file by clearing all public fields */
driver = file->cls;
if(H5I_dec_ref(file->driver_id, FALSE) < 0)
@@ -1423,6 +1410,8 @@ done:
* Tuesday, July 27, 1999
*
* Modifications:
+ * Vailin Choi, 29th July 2008
+ * Two more parameters were added to H5FD_alloc() for handling alignment
*
*-------------------------------------------------------------------------
*/
@@ -1448,12 +1437,15 @@ H5FDalloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, HADDR_UNDEF, "not a data transfer property list")
/* Do the real work */
- if(HADDR_UNDEF == (ret_value = H5FD_alloc(file, type, dxpl_id, size)))
+ if(HADDR_UNDEF == (ret_value = H5FD_alloc(file, dxpl_id, type, size, NULL, NULL)))
HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "unable to allocate file memory")
+ /* (Note compensating for base address subtraction in internal routine) */
+ ret_value += file->base_addr;
+
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5FDalloc() */
/*-------------------------------------------------------------------------
@@ -1497,7 +1489,8 @@ H5FDfree(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t siz
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list")
/* Do the real work */
- if(H5FD_free(file, type, dxpl_id, addr, size) < 0)
+ /* (Note compensating for base address addition in internal routine) */
+ if(H5FD_free(file, dxpl_id, type, addr - file->base_addr, size) < 0)
HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "file deallocation request failed")
done:
@@ -1506,65 +1499,17 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5FDrealloc
- *
- * Purpose: Changes the size of an allocated chunk of memory, possibly
- * also changing its location in the file.
- *
- * Return: Success: New address of the block of memory, not
- * necessarily the same as the original address.
- *
- * Failure: HADDR_UNDEF
- *
- * Programmer: Robb Matzke
- * Tuesday, August 3, 1999
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-haddr_t
-H5FDrealloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t old_addr, hsize_t old_size,
- hsize_t new_size)
-{
- haddr_t ret_value = HADDR_UNDEF;
-
- FUNC_ENTER_API(H5FDrealloc, HADDR_UNDEF)
- H5TRACE6("a", "*xMtiahh", file, type, dxpl_id, old_addr, old_size, new_size);
-
- /* Check args */
- if(H5P_DEFAULT == dxpl_id)
- dxpl_id = H5P_DATASET_XFER_DEFAULT;
- else
- if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, HADDR_UNDEF, "not a data transfer property list")
-
- if(HADDR_UNDEF == (ret_value = H5FD_realloc(file, type, dxpl_id, old_addr, old_size, new_size)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "file reallocation request failed")
-
-done:
- FUNC_LEAVE_API(ret_value)
-} /* end H5FDrealloc() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5FDget_eoa
*
* Purpose: Returns the address of the first byte after the last
* allocated memory in the file.
*
* Return: Success: First byte after allocated memory.
- *
* Failure: HADDR_UNDEF
*
* Programmer: Robb Matzke
* Friday, July 30, 1999
*
- * Modifications:
- * Raymond Lu
- * 21 Dec. 2006
- * Added the parameter TYPE. It's only used for MULTI driver.
- *
*-------------------------------------------------------------------------
*/
haddr_t
@@ -1578,52 +1523,19 @@ H5FDget_eoa(H5FD_t *file, H5FD_mem_t type)
/* Check args */
if(!file || !file->cls)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, HADDR_UNDEF, "invalid file pointer")
- if(type<H5FD_MEM_DEFAULT || type >= H5FD_MEM_NTYPES)
+ if(type < H5FD_MEM_DEFAULT || type >= H5FD_MEM_NTYPES)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, HADDR_UNDEF, "invalid file type")
/* The real work */
- if(HADDR_UNDEF==(ret_value=H5FD_get_eoa(file, type)))
+ if(HADDR_UNDEF == (ret_value = H5FD_get_eoa(file, type)))
HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "file get eoa request failed")
-done:
- FUNC_LEAVE_API(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_get_eoa
- *
- * Purpose: Private version of H5FDget_eoa()
- *
- * Return: Success: First byte after allocated memory.
- *
- * Failure: HADDR_UNDEF
- *
- * Programmer: Robb Matzke
- * Wednesday, August 4, 1999
- *
- * Modifications:
- * Raymond Lu
- * 21 Dec. 2006
- * Added the parameter TYPE. It's only used for MULTI driver.
- *
- *-------------------------------------------------------------------------
- */
-haddr_t
-H5FD_get_eoa(const H5FD_t *file, H5FD_mem_t type)
-{
- haddr_t ret_value;
-
- FUNC_ENTER_NOAPI(H5FD_get_eoa, HADDR_UNDEF)
- assert(file && file->cls);
-
- /* Dispatch to driver */
- if(HADDR_UNDEF==(ret_value=(file->cls->get_eoa)(file, type)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "driver get_eoa request failed")
+ /* (Note compensating for base address subtraction in internal routine) */
+ ret_value += file->base_addr;
done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
+ FUNC_LEAVE_API(ret_value)
+} /* end H5FDget_eoa() */
/*-------------------------------------------------------------------------
@@ -1643,23 +1555,17 @@ done:
* and the driver didn't supply an allocation callback.
*
* Return: Success: Non-negative
- *
* Failure: Negative, no side effect
*
* Programmer: Robb Matzke
* Friday, July 30, 1999
*
- * Modifications:
- * Raymond Lu
- * 21 Dec. 2006
- * Added the parameter TYPE. It's only used for MULTI driver.
- *
*-------------------------------------------------------------------------
*/
herr_t
H5FDset_eoa(H5FD_t *file, H5FD_mem_t type, haddr_t addr)
{
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5FDset_eoa, FAIL)
H5TRACE3("e", "*xMta", file, type, addr);
@@ -1667,57 +1573,19 @@ H5FDset_eoa(H5FD_t *file, H5FD_mem_t type, haddr_t addr)
/* Check args */
if(!file || !file->cls)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer")
- if(type<H5FD_MEM_DEFAULT || type >= H5FD_MEM_NTYPES)
+ if(type < H5FD_MEM_DEFAULT || type >= H5FD_MEM_NTYPES)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file type")
-
- if(!H5F_addr_defined(addr) || addr>file->maxaddr)
+ if(!H5F_addr_defined(addr) || addr > file->maxaddr)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid end-of-address value")
/* The real work */
- if(H5FD_set_eoa(file, type, addr) < 0)
+ /* (Note compensating for base address addition in internal routine) */
+ if(H5FD_set_eoa(file, type, addr - file->base_addr) < 0)
HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "file set eoa request failed")
done:
FUNC_LEAVE_API(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_set_eoa
- *
- * Purpose: Private version of H5FDset_eoa()
- *
- * Return: Success: Non-negative
- *
- * Failure: Negative, no side effect
- *
- * Programmer: Robb Matzke
- * Wednesday, August 4, 1999
- *
- * Modifications:
- * Raymond Lu
- * 21 Dec. 2006
- * Added the parameter TYPE. It's only used for MULTI driver.
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5FD_set_eoa(H5FD_t *file, H5FD_mem_t UNUSED type, haddr_t addr)
-{
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5FD_set_eoa, FAIL)
-
- assert(file && file->cls);
- assert(H5F_addr_defined(addr) && addr<=file->maxaddr);
-
- /* Dispatch to driver */
- if((file->cls->set_eoa)(file, type, addr) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver set_eoa request failed")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FDset_eoa() */
/*-------------------------------------------------------------------------
@@ -1759,80 +1627,101 @@ H5FDget_eof(H5FD_t *file)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, HADDR_UNDEF, "invalid file pointer")
/* The real work */
- if(HADDR_UNDEF==(ret_value=H5FD_get_eof(file)))
+ if(HADDR_UNDEF == (ret_value = H5FD_get_eof(file)))
HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "file get eof request failed")
+ /* (Note compensating for base address subtraction in internal routine) */
+ ret_value += file->base_addr;
+
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5FDget_eof() */
/*-------------------------------------------------------------------------
- * Function: H5FD_get_eof
+ * Function: H5FD_get_maxaddr
*
* Purpose: Private version of H5FDget_eof()
*
- * Return: Success: The EOF address.
- *
+ * Return: Success: The maximum address allowed in the file.
* Failure: HADDR_UNDEF
*
- * Programmer: Robb Matzke
- * Wednesday, August 4, 1999
- *
- * Modifications:
+ * Programmer: Quincey Koziol
+ * Thursday, January 3, 2008
*
*-------------------------------------------------------------------------
*/
haddr_t
-H5FD_get_eof(const H5FD_t *file)
+H5FD_get_maxaddr(const H5FD_t *file)
{
- haddr_t ret_value;
+ haddr_t ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5FD_get_eof, HADDR_UNDEF)
+ FUNC_ENTER_NOAPI(H5FD_get_maxaddr, HADDR_UNDEF)
- assert(file && file->cls);
+ HDassert(file);
- /* Dispatch to driver */
- if(file->cls->get_eof) {
- if(HADDR_UNDEF==(ret_value=(file->cls->get_eof)(file)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "driver get_eof request failed")
- } else {
- ret_value = file->maxaddr;
- }
+ /* Set return value */
+ ret_value = file->maxaddr;
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_get_maxaddr() */
/*-------------------------------------------------------------------------
- * Function: H5FD_get_maxaddr
+ * Function: H5FD_get_feature_flags
*
- * Purpose: Private version of H5FDget_eof()
+ * Purpose: Retrieve the feature flags for the VFD
*
- * Return: Success: The maximum address allowed in the file.
- * Failure: HADDR_UNDEF
+ * Return: Success: Non-negative
+ * Failure: Negative
*
* Programmer: Quincey Koziol
- * Thursday, January 3, 2008
+ * Tuesday, January 8, 2008
*
*-------------------------------------------------------------------------
*/
-haddr_t
-H5FD_get_maxaddr(const H5FD_t *file)
+herr_t
+H5FD_get_feature_flags(const H5FD_t *file, unsigned long *feature_flags)
{
- haddr_t ret_value; /* Return value */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_get_feature_flags)
- FUNC_ENTER_NOAPI(H5FD_get_maxaddr, HADDR_UNDEF)
+ HDassert(file);
+ HDassert(feature_flags);
+
+ /* Set feature flags to return */
+ *feature_flags = file->feature_flags;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5FD_get_feature_flags() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_get_fs_type_map
+ *
+ * Purpose: Retrieve the free space type mapping for the VFD
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, January 17, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_get_fs_type_map(const H5FD_t *file, H5FD_mem_t *type_map)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_get_fs_type_map)
HDassert(file);
+ HDassert(type_map);
- /* Set return value */
- ret_value = file->maxaddr;
+ /* Copy free space type mapping */
+ HDmemcpy(type_map, file->cls->fl_map, sizeof(file->cls->fl_map));
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_get_maxaddr() */
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5FD_get_fs_type_map() */
/*-------------------------------------------------------------------------
@@ -1860,7 +1749,7 @@ herr_t
H5FDread(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size,
void *buf/*out*/)
{
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5FDread, FAIL)
H5TRACE6("e", "*xMtiazx", file, type, dxpl_id, addr, size, buf);
@@ -1873,206 +1762,76 @@ H5FDread(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size
if(H5P_DEFAULT == dxpl_id)
dxpl_id= H5P_DATASET_XFER_DEFAULT;
else
- if(TRUE!=H5P_isa_class(dxpl_id,H5P_DATASET_XFER))
+ if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list")
if(!buf)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null result buffer")
/* Do the real work */
- if(H5FD_read(file, type, dxpl_id, addr, size, buf) < 0)
+ /* (Note compensating for base address addition in internal routine) */
+ if(H5FD_read(file, dxpl_id, type, addr - file->base_addr, size, buf) < 0)
HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "file read request failed")
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5FDread() */
/*-------------------------------------------------------------------------
- * Function: H5FD_read
+ * Function: H5FDwrite
*
- * Purpose: Private version of H5FDread()
+ * Purpose: Writes SIZE bytes to FILE beginning at address ADDR according
+ * to the data transfer property list DXPL_ID (which may be the
+ * constant H5P_DEFAULT). The bytes to be written come from the
+ * buffer BUF.
*
* Return: Success: Non-negative
*
* Failure: Negative
*
* Programmer: Robb Matzke
- * Wednesday, August 4, 1999
+ * Thursday, July 29, 1999
*
* Modifications:
- * Albert Cheng, 2000-11-21
- * Disable the code that does early return when size==0 for
- * Parallel mode since a collective call would require the process
- * to continue on with "nothing" to transfer.
*
*-------------------------------------------------------------------------
*/
herr_t
-H5FD_read(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size,
- void *buf/*out*/)
+H5FDwrite(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size,
+ const void *buf)
{
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5FD_read, FAIL)
-
- assert(file && file->cls);
- assert(H5I_GENPROP_LST==H5I_get_type(dxpl_id));
- assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER));
- assert(buf);
-
-#ifndef H5_HAVE_PARALLEL
- /* Do not return early for Parallel mode since the I/O could be a */
- /* collective transfer. */
- /* The no-op case */
- if(0==size)
- HGOTO_DONE(SUCCEED)
-#endif /* H5_HAVE_PARALLEL */
-
- /* Check if this information is in the metadata accumulator */
- if((file->feature_flags&H5FD_FEAT_ACCUMULATE_METADATA) && type!=H5FD_MEM_DRAW) {
- /* Current read overlaps with metadata accumulator */
- if(H5F_addr_overlap(addr,size,file->accum_loc,file->accum_size)) {
- unsigned char *read_buf=(unsigned char *)buf; /* Pointer to the buffer being read in */
- size_t amount_read; /* Amount to read at a time */
-#ifndef NDEBUG
- hsize_t tempamount_read; /* Amount to read at a time */
-#endif /* NDEBUG */
- hsize_t read_off; /* Offset to read from */
-
- /* Double check that we aren't reading raw data */
- assert(type!=H5FD_MEM_DRAW);
-
- /* Read the part before the metadata accumulator */
- if(addr<file->accum_loc) {
- /* Set the amount to read */
- H5_ASSIGN_OVERFLOW(amount_read,file->accum_loc-addr,hsize_t,size_t);
-
- /* Dispatch to driver */
- if((file->cls->read)(file, type, dxpl_id, addr, amount_read, read_buf) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read request failed")
-
- /* Adjust the buffer, address & size */
- read_buf+=amount_read;
- addr+=amount_read;
- size-=amount_read;
- } /* end if */
-
- /* Copy the part overlapping the metadata accumulator */
- if(size>0 && (addr>=file->accum_loc && addr<(file->accum_loc+file->accum_size))) {
- /* Set the offset to "read" from */
- read_off=addr-file->accum_loc;
-
- /* Set the amount to "read" */
-#ifndef NDEBUG
- tempamount_read = file->accum_size-read_off;
- H5_CHECK_OVERFLOW(tempamount_read,hsize_t,size_t);
- amount_read = MIN(size, (size_t)tempamount_read);
-#else /* NDEBUG */
- amount_read = MIN(size, (size_t)(file->accum_size-read_off));
-#endif /* NDEBUG */
-
- /* Copy the data out of the buffer */
- HDmemcpy(read_buf,file->meta_accum+read_off,amount_read);
-
- /* Adjust the buffer, address & size */
- read_buf+=amount_read;
- addr+=amount_read;
- size-=amount_read;
- } /* end if */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Read the part after the metadata accumulator */
- if(size>0 && addr>=(file->accum_loc+file->accum_size)) {
- /* Dispatch to driver */
- if((file->cls->read)(file, type, dxpl_id, addr, size, read_buf) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read request failed")
+ FUNC_ENTER_API(H5FDwrite, FAIL)
+ H5TRACE6("e", "*xMtiaz*x", file, type, dxpl_id, addr, size, buf);
- /* Adjust the buffer, address & size */
- read_buf+=size;
- addr+=size;
- size-=size;
- } /* end if */
+ /* Check args */
+ if(!file || !file->cls)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer")
+ /* Get the default dataset transfer property list if the user didn't provide one */
+ if(H5P_DEFAULT == dxpl_id)
+ dxpl_id = H5P_DATASET_XFER_DEFAULT;
+ else
+ if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list")
+ if(!buf)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null buffer")
- /* Make certain we've read it all */
- assert(size==0);
- } /* end if */
- /* Current read doesn't overlap with metadata accumulator, read it into accumulator */
- else {
- /* Only update the metadata accumulator if it is not dirty or if
- * we are allowed to write the accumulator out during reads (when
- * it is dirty)
- */
- if(file->feature_flags&H5FD_FEAT_ACCUMULATE_METADATA_READ || !file->accum_dirty) {
- /* Flush current contents, if dirty */
- if(file->accum_dirty) {
- if((file->cls->write)(file, H5FD_MEM_DEFAULT, dxpl_id, file->accum_loc, file->accum_size, file->meta_accum) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "driver write request failed")
-
- /* Reset accumulator dirty flag */
- file->accum_dirty=FALSE;
- } /* end if */
-
- /* Cache the new piece of metadata */
- /* Check if we need to resize the buffer */
- if(size>file->accum_buf_size) {
- /* Grow the metadata accumulator buffer */
- if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
-
- /* Note the new buffer size */
- file->accum_buf_size=size;
- } /* end if */
- else {
- /* Check if we should shrink the accumulator buffer */
- if(size<(file->accum_buf_size/H5FD_ACCUM_THROTTLE) &&
- file->accum_buf_size>H5FD_ACCUM_THRESHOLD) {
- size_t new_size=(file->accum_buf_size/H5FD_ACCUM_THROTTLE); /* New size of accumulator buffer */
-
- /* Shrink the accumulator buffer */
- if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,new_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
-
- /* Note the new buffer size */
- file->accum_buf_size=new_size;
- } /* end if */
- } /* end else */
-
- /* Update accumulator information */
- file->accum_loc=addr;
- file->accum_size=size;
- file->accum_dirty=FALSE;
-
- /* Read into accumulator */
- if((file->cls->read)(file, H5FD_MEM_DEFAULT, dxpl_id, file->accum_loc, file->accum_size, file->meta_accum) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read request failed")
-
- /* Copy into buffer */
- HDmemcpy(buf,file->meta_accum,size);
- } /* end if */
- else {
- /* Dispatch to driver */
- if((file->cls->read)(file, type, dxpl_id, addr, size, buf) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read request failed")
- } /* end else */
- } /* end else */
- } /* end if */
- else {
- /* Dispatch to driver */
- if((file->cls->read)(file, type, dxpl_id, addr, size, buf) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read request failed")
- } /* end else */
+ /* The real work */
+ /* (Note compensating for base address addition in internal routine) */
+ if(H5FD_write(file, dxpl_id, type, addr - file->base_addr, size, buf) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "file write request failed")
done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
+ FUNC_LEAVE_API(ret_value)
+} /* end H5FDwrite() */
/*-------------------------------------------------------------------------
- * Function: H5FDwrite
+ * Function: H5FDflush
*
- * Purpose: Writes SIZE bytes to FILE beginning at address ADDR according
- * to the data transfer property list DXPL_ID (which may be the
- * constant H5P_DEFAULT). The bytes to be written come from the
- * buffer BUF.
+ * Purpose: Notify driver to flush all cached data. If the driver has no
+ * flush method then nothing happens.
*
* Return: Success: Non-negative
*
@@ -2082,33 +1841,31 @@ done:
* Thursday, July 29, 1999
*
* Modifications:
+ * Quincey Koziol, May 20, 2002
+ * Added 'closing' parameter
*
*-------------------------------------------------------------------------
*/
herr_t
-H5FDwrite(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size,
- const void *buf)
+H5FDflush(H5FD_t *file, hid_t dxpl_id, unsigned closing)
{
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_API(H5FDwrite, FAIL)
- H5TRACE6("e", "*xMtiaz*x", file, type, dxpl_id, addr, size, buf);
+ FUNC_ENTER_API(H5FDflush, FAIL)
+ H5TRACE3("e", "*xiIu", file, dxpl_id, closing);
/* Check args */
if(!file || !file->cls)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer")
- /* Get the default dataset transfer property list if the user didn't provide one */
if(H5P_DEFAULT == dxpl_id)
- dxpl_id= H5P_DATASET_XFER_DEFAULT;
+ dxpl_id = H5P_DATASET_XFER_DEFAULT;
else
- if(TRUE!=H5P_isa_class(dxpl_id,H5P_DATASET_XFER))
+ if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list")
- if(!buf)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null buffer")
- /* The real work */
- if(H5FD_write(file, type, dxpl_id, addr, size, buf) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "file write request failed")
+ /* Do the real work */
+ if(H5FD_flush(file, dxpl_id, closing) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTFLUSH, FAIL, "file flush request failed")
done:
FUNC_LEAVE_API(ret_value)
@@ -2116,303 +1873,68 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5FD_write
+ * Function: H5FD_flush
*
- * Purpose: Private version of H5FDwrite()
+ * Purpose: Private version of H5FDflush()
*
* Return: Success: Non-negative
- *
* Failure: Negative
*
* Programmer: Robb Matzke
* Wednesday, August 4, 1999
*
- * Modifications:
- * Albert Cheng, 2000-11-21
- * Disable the code that does early return when size==0 for
- * Parallel mode since a collective call would require the process
- * to continue on with "nothing" to transfer.
- *
*-------------------------------------------------------------------------
*/
herr_t
-H5FD_write(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size,
- const void *buf)
+H5FD_flush(H5FD_t *file, hid_t dxpl_id, unsigned closing)
{
- size_t new_size; /* New size of the accumulator buffer */
- size_t old_offset; /* Offset of old data within the accumulator buffer */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5FD_write, FAIL)
-
- assert(file && file->cls);
- assert(H5I_GENPROP_LST==H5I_get_type(dxpl_id));
- assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER));
- assert(buf);
-
-#ifndef H5_HAVE_PARALLEL
- /* Do not return early for Parallel mode since the I/O could be a */
- /* collective transfer. */
- /* The no-op case */
- if(0==size)
- HGOTO_DONE(SUCCEED)
-#endif /* H5_HAVE_PARALLEL */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Check for accumulating metadata */
- if((file->feature_flags&H5FD_FEAT_ACCUMULATE_METADATA) && type!=H5FD_MEM_DRAW) {
- /* Check if there is already metadata in the accumulator */
- if(file->accum_size>0) {
- /* Check if the piece of metadata being written adjoins or is inside the metadata accumulator */
- if((addr>=file->accum_loc && addr<=(file->accum_loc+file->accum_size))
- || ((addr+size)>file->accum_loc && (addr+size)<=(file->accum_loc+file->accum_size))
- || (addr<file->accum_loc && (addr+size)>=file->accum_loc)) {
-
- /* Check if the new metadata adjoins the beginning of the current accumulator */
- if((addr+size)==file->accum_loc) {
- /* Check if we need more buffer space */
- if((size+file->accum_size)>file->accum_buf_size) {
- /* Adjust the buffer size, by doubling it */
- file->accum_buf_size = MAX(file->accum_buf_size*2,size+file->accum_size);
-
- /* Reallocate the metadata accumulator buffer */
- if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,file->accum_buf_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
-#ifdef H5_CLEAR_MEMORY
-HDmemset(file->meta_accum + file->accum_size, 0, (file->accum_buf_size - (file->accum_size + size)));
-#endif /* H5_CLEAR_MEMORY */
- } /* end if */
-
- /* Move the existing metadata to the proper location */
- HDmemmove(file->meta_accum+size,file->meta_accum,file->accum_size);
-
- /* Copy the new metadata at the front */
- HDmemcpy(file->meta_accum,buf,size);
-
- /* Set the new size & location of the metadata accumulator */
- file->accum_loc=addr;
- file->accum_size=file->accum_size+size;
-
- /* Mark it as written to */
- file->accum_dirty=TRUE;
- } /* end if */
- /* Check if the new metadata adjoins the end of the current accumulator */
- else if(addr==(file->accum_loc+file->accum_size)) {
- /* Check if we need more buffer space */
- if((size+file->accum_size)>file->accum_buf_size) {
- /* Adjust the buffer size, by doubling it */
- file->accum_buf_size = MAX(file->accum_buf_size*2,size+file->accum_size);
-
- /* Reallocate the metadata accumulator buffer */
- if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,file->accum_buf_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
-#ifdef H5_CLEAR_MEMORY
-HDmemset(file->meta_accum + file->accum_size + size, 0, (file->accum_buf_size - (file->accum_size + size)));
-#endif /* H5_CLEAR_MEMORY */
- } /* end if */
-
- /* Copy the new metadata to the end */
- HDmemcpy(file->meta_accum+file->accum_size,buf,size);
-
- /* Set the new size of the metadata accumulator */
- file->accum_size=file->accum_size+size;
-
- /* Mark it as written to */
- file->accum_dirty=TRUE;
- } /* end if */
- /* Check if the new metadata is entirely within the current accumulator */
- else if(addr>=file->accum_loc && (addr+size)<=(file->accum_loc+file->accum_size)) {
- /* Copy the new metadata to the proper location within the accumulator */
- HDmemcpy(file->meta_accum+(addr-file->accum_loc),buf,size);
-
- /* Mark it as written to */
- file->accum_dirty=TRUE;
- } /* end if */
- /* Check if the new metadata overlaps the beginning of the current accumulator */
- else if(addr<file->accum_loc && (addr+size)<=(file->accum_loc+file->accum_size)) {
- /* Calculate the new accumulator size, based on the amount of overlap */
- H5_ASSIGN_OVERFLOW(new_size,(file->accum_loc-addr)+file->accum_size,hsize_t,size_t);
-
- /* Check if we need more buffer space */
- if(new_size>file->accum_buf_size) {
- /* Adjust the buffer size, by doubling it */
- file->accum_buf_size = MAX(file->accum_buf_size*2,new_size);
-
- /* Reallocate the metadata accumulator buffer */
- if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,file->accum_buf_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
-#ifdef H5_CLEAR_MEMORY
-HDmemset(file->meta_accum + file->accum_size, 0, (file->accum_buf_size - file->accum_size));
-#endif /* H5_CLEAR_MEMORY */
- } /* end if */
-
- /* Calculate the proper offset of the existing metadata */
- H5_ASSIGN_OVERFLOW(old_offset,(addr+size)-file->accum_loc,hsize_t,size_t);
-
- /* Move the existing metadata to the proper location */
- HDmemmove(file->meta_accum+size,file->meta_accum+old_offset,(file->accum_size-old_offset));
-
- /* Copy the new metadata at the front */
- HDmemcpy(file->meta_accum,buf,size);
-
- /* Set the new size & location of the metadata accumulator */
- file->accum_loc=addr;
- file->accum_size=new_size;
-
- /* Mark it as written to */
- file->accum_dirty=TRUE;
- } /* end if */
- /* Check if the new metadata overlaps the end of the current accumulator */
- else if(addr>=file->accum_loc && (addr+size)>(file->accum_loc+file->accum_size)) {
- /* Calculate the new accumulator size, based on the amount of overlap */
- H5_ASSIGN_OVERFLOW(new_size,(addr-file->accum_loc)+size,hsize_t,size_t);
-
- /* Check if we need more buffer space */
- if(new_size>file->accum_buf_size) {
- /* Adjust the buffer size, by doubling it */
- file->accum_buf_size = MAX(file->accum_buf_size*2,new_size);
-
- /* Reallocate the metadata accumulator buffer */
- if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,file->accum_buf_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
-#ifdef H5_CLEAR_MEMORY
-HDmemset(file->meta_accum + file->accum_size, 0, (file->accum_buf_size - file->accum_size));
-#endif /* H5_CLEAR_MEMORY */
- } /* end if */
-
- /* Copy the new metadata to the end */
- HDmemcpy(file->meta_accum+(addr-file->accum_loc),buf,size);
-
- /* Set the new size & location of the metadata accumulator */
- file->accum_size=new_size;
-
- /* Mark it as written to */
- file->accum_dirty=TRUE;
- } /* end if */
- else {
- assert(0 && "New metadata overlapped both beginning and end of existing metadata accumulator!");
- } /* end else */
- } /* end if */
- /* New piece of metadata doesn't adjoin or overlap the existing accumulator */
- else {
- /* Write out the existing metadata accumulator, with dispatch to driver */
- if(file->accum_dirty) {
- if((file->cls->write)(file, H5FD_MEM_DEFAULT, dxpl_id, file->accum_loc, file->accum_size, file->meta_accum) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "driver write request failed")
- /* Reset accumulator dirty flag */
- file->accum_dirty=FALSE;
- } /* end if */
-
- /* Cache the new piece of metadata */
- /* Check if we need to resize the buffer */
- if(size>file->accum_buf_size) {
- /* Grow the metadata accumulator buffer */
- if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
-
- /* Note the new buffer size */
- file->accum_buf_size=size;
-#ifdef H5_CLEAR_MEMORY
-{
-size_t clear_size = MAX(file->accum_size, size);
-HDmemset(file->meta_accum + clear_size, 0, (file->accum_buf_size - clear_size));
-}
-#endif /* H5_CLEAR_MEMORY */
- } /* end if */
- else {
- /* Check if we should shrink the accumulator buffer */
- if(size<(file->accum_buf_size/H5FD_ACCUM_THROTTLE) &&
- file->accum_buf_size>H5FD_ACCUM_THRESHOLD) {
- size_t tmp_size=(file->accum_buf_size/H5FD_ACCUM_THROTTLE); /* New size of accumulator buffer */
-
- /* Shrink the accumulator buffer */
- if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,tmp_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
-
- /* Note the new buffer size */
- file->accum_buf_size=tmp_size;
- } /* end if */
- } /* end else */
-
- /* Update the metadata accumulator information */
- file->accum_loc=addr;
- file->accum_size=size;
- file->accum_dirty=TRUE;
-
- /* Store the piece of metadata in the accumulator */
- HDmemcpy(file->meta_accum,buf,size);
- } /* end else */
- } /* end if */
- /* No metadata in the accumulator, grab this piece and keep it */
- else {
- /* Check if we need to reallocate the buffer */
- if(size>file->accum_buf_size) {
- /* Reallocate the metadata accumulator buffer */
- if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
-
- /* Note the new buffer size */
- file->accum_buf_size=size;
- } /* end if */
+ FUNC_ENTER_NOAPI(H5FD_flush, FAIL)
- /* Update the metadata accumulator information */
- file->accum_loc=addr;
- file->accum_size=size;
- file->accum_dirty=TRUE;
+ HDassert(file && file->cls);
- /* Store the piece of metadata in the accumulator */
- HDmemcpy(file->meta_accum,buf,size);
- } /* end else */
- } /* end if */
- else {
- /* Dispatch to driver */
- if((file->cls->write)(file, type, dxpl_id, addr, size, buf) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "driver write request failed")
- } /* end else */
+ if(file->cls->flush && (file->cls->flush)(file, dxpl_id, closing) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver flush request failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_flush() */
/*-------------------------------------------------------------------------
- * Function: H5FDflush
+ * Function: H5FDtruncate
*
- * Purpose: Notify driver to flush all cached data. If the driver has no
- * flush method then nothing happens.
+ * Purpose: Notify driver to truncate the file back to the allocated size.
*
* Return: Success: Non-negative
- *
* Failure: Negative
*
- * Programmer: Robb Matzke
- * Thursday, July 29, 1999
- *
- * Modifications:
- * Quincey Koziol, May 20, 2002
- * Added 'closing' parameter
+ * Programmer: Quincey Koziol
+ * Thursday, January 31, 2008
*
*-------------------------------------------------------------------------
*/
herr_t
-H5FDflush(H5FD_t *file, hid_t dxpl_id, unsigned closing)
+H5FDtruncate(H5FD_t *file, hid_t dxpl_id, unsigned closing)
{
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_API(H5FDflush, FAIL)
+ FUNC_ENTER_API(H5FDtruncate, FAIL)
H5TRACE3("e", "*xiIu", file, dxpl_id, closing);
/* Check args */
if(!file || !file->cls)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer")
if(H5P_DEFAULT == dxpl_id)
- dxpl_id= H5P_DATASET_XFER_DEFAULT;
+ dxpl_id = H5P_DATASET_XFER_DEFAULT;
else
- if(TRUE!=H5P_isa_class(dxpl_id,H5P_DATASET_XFER))
+ if(TRUE != H5P_isa_class(dxpl_id,H5P_DATASET_XFER))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list")
/* Do the real work */
- if(H5FD_flush(file,dxpl_id,closing) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "file flush request failed")
+ if(H5FD_truncate(file, dxpl_id, closing) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTUPDATE, FAIL, "file flush request failed")
done:
FUNC_LEAVE_API(ret_value)
@@ -2420,49 +1942,33 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5FD_flush
+ * Function: H5FD_truncate
*
- * Purpose: Private version of H5FDflush()
+ * Purpose: Private version of H5FDtruncate()
*
* Return: Success: Non-negative
- *
* Failure: Negative
*
- * Programmer: Robb Matzke
- * Wednesday, August 4, 1999
- *
- * Modifications:
- * Quincey Koziol, May 20, 2002
- * Added 'closing' parameter
+ * Programmer: Quincey Koziol
+ * Thursday, January 31, 2008
*
*-------------------------------------------------------------------------
*/
herr_t
-H5FD_flush(H5FD_t *file, hid_t dxpl_id, unsigned closing)
+H5FD_truncate(H5FD_t *file, hid_t dxpl_id, unsigned closing)
{
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5FD_flush, FAIL)
-
- assert(file && file->cls);
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Check if we need to flush out the metadata accumulator */
- if((file->feature_flags&H5FD_FEAT_ACCUMULATE_METADATA) && file->accum_dirty && file->accum_size>0) {
- /* Flush the metadata contents */
- /* Not certain if the type and dxpl should be the way they are... -QAK */
- if((file->cls->write)(file, H5FD_MEM_DEFAULT, dxpl_id, file->accum_loc, file->accum_size, file->meta_accum) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver write request failed")
+ FUNC_ENTER_NOAPI(H5FD_truncate, FAIL)
- /* Reset the dirty flag */
- file->accum_dirty=FALSE;
- } /* end if */
+ HDassert(file && file->cls);
- if(file->cls->flush && (file->cls->flush)(file,dxpl_id,closing) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver flush request failed")
+ if(file->cls->truncate && (file->cls->truncate)(file, dxpl_id, closing) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTUPDATE, FAIL, "driver truncate request failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_truncate() */
/*-------------------------------------------------------------------------
@@ -2563,3 +2069,33 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD_get_vfd_handle() */
+
+/*--------------------------------------------------------------------------
+ * Function: H5FD_set_base_addr
+ *
+ * Purpose: Set the base address for the file
+ *
+ * Return: Non-negative if succeed; negative if fails.
+ *
+ * Programmer: Quincey Koziol
+ * Jan. 17, 2008
+ *
+ *--------------------------------------------------------------------------
+ */
+herr_t
+H5FD_set_base_addr(H5FD_t *file, haddr_t base_addr)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(H5FD_set_base_addr, FAIL)
+
+ HDassert(file);
+ HDassert(H5F_addr_defined(base_addr));
+
+ /* Set the file's base address */
+ file->base_addr = base_addr;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_set_base_addr() */
+
diff --git a/src/H5FDcore.c b/src/H5FDcore.c
index deef3ed..de49e9e 100644
--- a/src/H5FDcore.c
+++ b/src/H5FDcore.c
@@ -128,6 +128,7 @@ static const H5FD_class_t H5FD_core_g = {
H5FD_core_read, /*read */
H5FD_core_write, /*write */
H5FD_core_flush, /*flush */
+ NULL, /*truncate */
NULL, /*lock */
NULL, /*unlock */
H5FD_FLMAP_SINGLE /*fl_map */
@@ -898,3 +899,4 @@ H5FD_core_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing)
done:
FUNC_LEAVE_NOAPI(ret_value)
}
+
diff --git a/src/H5FDdirect.c b/src/H5FDdirect.c
index 980b16f..88a2af0 100644
--- a/src/H5FDdirect.c
+++ b/src/H5FDdirect.c
@@ -163,14 +163,14 @@ static herr_t H5FD_direct_close(H5FD_t *_file);
static int H5FD_direct_cmp(const H5FD_t *_f1, const H5FD_t *_f2);
static herr_t H5FD_direct_query(const H5FD_t *_f1, unsigned long *flags);
static haddr_t H5FD_direct_get_eoa(const H5FD_t *_file, H5FD_mem_t type);
-static herr_t H5FD_direct_set_eoa(H5FD_t *_file, H5FD_mem_t UNUSED type, haddr_t addr);
+static herr_t H5FD_direct_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr);
static haddr_t H5FD_direct_get_eof(const H5FD_t *_file);
static herr_t H5FD_direct_get_handle(H5FD_t *_file, hid_t fapl, void** file_handle);
static herr_t H5FD_direct_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr,
size_t size, void *buf);
static herr_t H5FD_direct_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr,
size_t size, const void *buf);
-static herr_t H5FD_direct_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
+static herr_t H5FD_direct_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
static const H5FD_class_t H5FD_direct_g = {
"direct", /*name */
@@ -198,7 +198,8 @@ static const H5FD_class_t H5FD_direct_g = {
H5FD_direct_get_handle, /*get_handle */
H5FD_direct_read, /*read */
H5FD_direct_write, /*write */
- H5FD_direct_flush, /*flush */
+ NULL, /*flush */
+ H5FD_direct_truncate, /*truncate */
NULL, /*lock */
NULL, /*unlock */
H5FD_FLMAP_SINGLE /*fl_map */
@@ -1238,7 +1239,7 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5FD_direct_flush
+ * Function: H5FD_direct_truncate
*
* Purpose: Makes sure that the true file size is the same (or larger)
* than the end-of-address.
@@ -1250,17 +1251,15 @@ done:
* Programmer: Raymond Lu
* Thursday, 21 September 2006
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static herr_t
-H5FD_direct_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing)
+H5FD_direct_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing)
{
H5FD_direct_t *file = (H5FD_direct_t*)_file;
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5FD_direct_flush, FAIL)
+ FUNC_ENTER_NOAPI(H5FD_direct_truncate, FAIL)
assert(file);
@@ -1301,5 +1300,6 @@ H5FD_direct_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing)
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_direct_truncate() */
#endif /* H5_HAVE_DIRECT */
+
diff --git a/src/H5FDfamily.c b/src/H5FDfamily.c
index c70bfdb..5451cc0 100644
--- a/src/H5FDfamily.c
+++ b/src/H5FDfamily.c
@@ -107,6 +107,7 @@ static herr_t H5FD_family_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, ha
static herr_t H5FD_family_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
size_t size, const void *_buf);
static herr_t H5FD_family_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
+static herr_t H5FD_family_truncate(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
/* The class struct */
static const H5FD_class_t H5FD_family_g = {
@@ -136,6 +137,7 @@ static const H5FD_class_t H5FD_family_g = {
H5FD_family_read, /*read */
H5FD_family_write, /*write */
H5FD_family_flush, /*flush */
+ H5FD_family_truncate, /*truncate */
NULL, /*lock */
NULL, /*unlock */
H5FD_FLMAP_SINGLE /*fl_map */
@@ -1051,13 +1053,13 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FD_family_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t eoa)
+H5FD_family_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t abs_eoa)
{
H5FD_family_t *file = (H5FD_family_t*)_file;
- haddr_t addr=eoa;
+ haddr_t addr = abs_eoa;
char memb_name[4096];
- unsigned u; /* Local index variable */
- herr_t ret_value=SUCCEED; /* Return value */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5FD_family_set_eoa, FAIL)
@@ -1076,32 +1078,34 @@ H5FD_family_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t eoa)
} /* end if */
/* Create another file if necessary */
- if (u>=file->nmembs || !file->memb[u]) {
+ if(u >= file->nmembs || !file->memb[u]) {
file->nmembs = MAX(file->nmembs, u+1);
sprintf(memb_name, file->name, u);
H5E_BEGIN_TRY {
- H5_CHECK_OVERFLOW(file->memb_size,hsize_t,haddr_t);
- file->memb[u] = H5FDopen(memb_name, file->flags|H5F_ACC_CREAT,
+ H5_CHECK_OVERFLOW(file->memb_size, hsize_t, haddr_t);
+ file->memb[u] = H5FDopen(memb_name, file->flags | H5F_ACC_CREAT,
file->memb_fapl_id, (haddr_t)file->memb_size);
} H5E_END_TRY;
- if (NULL==file->memb[u])
+ if(NULL == file->memb[u])
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to open member file")
- }
+ } /* end if */
/* Set the EOA marker for the member */
- H5_CHECK_OVERFLOW(file->memb_size,hsize_t,haddr_t);
- if (addr>(haddr_t)file->memb_size) {
- if(H5FD_set_eoa(file->memb[u], type, (haddr_t)file->memb_size)<0)
+ /* (Note compensating for base address addition in internal routine) */
+ H5_CHECK_OVERFLOW(file->memb_size, hsize_t, haddr_t);
+ if(addr > (haddr_t)file->memb_size) {
+ if(H5FD_set_eoa(file->memb[u], type, ((haddr_t)file->memb_size - file->pub.base_addr)) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to set file eoa")
addr -= file->memb_size;
- } else {
- if(H5FD_set_eoa(file->memb[u], type, addr)<0)
+ } /* end if */
+ else {
+ if(H5FD_set_eoa(file->memb[u], type, (addr - file->pub.base_addr)) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to set file eoa")
addr = 0;
- }
- }
+ } /* end else */
+ } /* end for */
- file->eoa = eoa;
+ file->eoa = abs_eoa;
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1142,13 +1146,16 @@ H5FD_family_get_eof(const H5FD_t *_file)
* with `i' equal to that member. If all members have zero EOF then exit
* loop with i==0.
*/
- assert(file->nmembs>0);
- for (i=(int)file->nmembs-1; i>=0; --i) {
- if ((eof=H5FD_get_eof(file->memb[i]))!=0)
+ HDassert(file->nmembs > 0);
+ for(i = (int)file->nmembs - 1; i >= 0; --i) {
+ if((eof = H5FD_get_eof(file->memb[i])) != 0)
break;
- if (0==i)
+ if(0 == i)
break;
- }
+ } /* end for */
+
+ /* Adjust for base address for file */
+ eof += file->pub.base_addr;
/*
* The file size is the number of members before the i'th member plus the
@@ -1157,7 +1164,7 @@ H5FD_family_get_eof(const H5FD_t *_file)
eof += ((unsigned)i)*file->memb_size;
/* Set return value */
- ret_value=MAX(eof, file->eoa);
+ ret_value = MAX(eof, file->eoa);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1396,3 +1403,39 @@ H5FD_family_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing)
done:
FUNC_LEAVE_NOAPI(ret_value)
}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_family_truncate
+ *
+ * Purpose: Truncates all family members.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1, as many files truncated as possible.
+ *
+ * Programmer: Quincey Koziol
+ * Saturday, February 23, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_family_truncate(H5FD_t *_file, hid_t dxpl_id, unsigned closing)
+{
+ H5FD_family_t *file = (H5FD_family_t*)_file;
+ unsigned u, nerrors = 0;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FD_family_truncate, FAIL)
+
+ for(u = 0; u < file->nmembs; u++)
+ if(file->memb[u] && H5FD_truncate(file->memb[u], dxpl_id, closing) < 0)
+ nerrors++;
+
+ if(nerrors)
+ HGOTO_ERROR(H5E_IO, H5E_BADVALUE, FAIL, "unable to flush member files")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_family_truncate() */
+
diff --git a/src/H5FDint.c b/src/H5FDint.c
new file mode 100644
index 0000000..aa375e2
--- /dev/null
+++ b/src/H5FDint.c
@@ -0,0 +1,297 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5FDint.c
+ * Jan 17 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Internal routine for VFD operations
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5FD_PACKAGE /*suppress error about including H5FDpkg */
+
+/* Interface initialization */
+#define H5_INTERFACE_INIT_FUNC H5FD_int_init_interface
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fprivate.h" /* File access */
+#include "H5FDpkg.h" /* File Drivers */
+#include "H5Iprivate.h" /* IDs */
+#include "H5Pprivate.h" /* Property lists */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+
+/*--------------------------------------------------------------------------
+NAME
+ H5FD_int_init_interface -- Initialize interface-specific information
+USAGE
+ herr_t H5FD_int_init_interface()
+
+RETURNS
+ Non-negative on success/Negative on failure
+DESCRIPTION
+ Initializes any interface-specific data or routines. (Just calls
+ H5FD_init_iterface currently).
+
+--------------------------------------------------------------------------*/
+static herr_t
+H5FD_int_init_interface(void)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_int_init_interface)
+
+ FUNC_LEAVE_NOAPI(H5FD_init())
+} /* H5FD_int_init_interface() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_read
+ *
+ * Purpose: Private version of H5FDread()
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, August 4, 1999
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_read(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr,
+ size_t size, void *buf/*out*/)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FD_read, FAIL)
+
+ HDassert(file && file->cls);
+ HDassert(H5I_GENPROP_LST == H5I_get_type(dxpl_id));
+ HDassert(TRUE == H5P_isa_class(dxpl_id, H5P_DATASET_XFER));
+ HDassert(buf);
+
+#ifndef H5_HAVE_PARALLEL
+ /* Do not return early for Parallel mode since the I/O could be a */
+ /* collective transfer. */
+ /* The no-op case */
+ if(0 == size)
+ HGOTO_DONE(SUCCEED)
+#endif /* H5_HAVE_PARALLEL */
+
+ /* Dispatch to driver */
+ if((file->cls->read)(file, type, dxpl_id, addr + file->base_addr, size, buf) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read request failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_write
+ *
+ * Purpose: Private version of H5FDwrite()
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, August 4, 1999
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_write(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr,
+ size_t size, const void *buf)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FD_write, FAIL)
+
+ HDassert(file && file->cls);
+ HDassert(H5I_GENPROP_LST == H5I_get_type(dxpl_id));
+ HDassert(TRUE == H5P_isa_class(dxpl_id, H5P_DATASET_XFER));
+ HDassert(buf);
+
+#ifndef H5_HAVE_PARALLEL
+ /* Do not return early for Parallel mode since the I/O could be a */
+ /* collective transfer. */
+ /* The no-op case */
+ if(0 == size)
+ HGOTO_DONE(SUCCEED)
+#endif /* H5_HAVE_PARALLEL */
+
+ /* Dispatch to driver */
+ if((file->cls->write)(file, type, dxpl_id, addr + file->base_addr, size, buf) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "driver write request failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_write() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_set_eoa
+ *
+ * Purpose: Private version of H5FDset_eoa()
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative, no side effect
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, August 4, 1999
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_set_eoa(H5FD_t *file, H5FD_mem_t type, haddr_t addr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FD_set_eoa, FAIL)
+
+ HDassert(file && file->cls);
+ HDassert(H5F_addr_defined(addr) && addr <= file->maxaddr);
+
+ /* Dispatch to driver */
+ if((file->cls->set_eoa)(file, type, addr + file->base_addr) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver set_eoa request failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_set_eoa() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_get_eoa
+ *
+ * Purpose: Private version of H5FDget_eoa()
+ *
+ * Return: Success: First byte after allocated memory.
+ * Failure: HADDR_UNDEF
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, August 4, 1999
+ *
+ *-------------------------------------------------------------------------
+ */
+haddr_t
+H5FD_get_eoa(const H5FD_t *file, H5FD_mem_t type)
+{
+ haddr_t ret_value;
+
+ FUNC_ENTER_NOAPI(H5FD_get_eoa, HADDR_UNDEF)
+
+ HDassert(file && file->cls);
+
+ /* Dispatch to driver */
+ if(HADDR_UNDEF == (ret_value = (file->cls->get_eoa)(file, type)))
+ HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "driver get_eoa request failed")
+
+ /* Adjust for base address in file */
+ ret_value -= file->base_addr;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_get_eoa() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_get_eof
+ *
+ * Purpose: Private version of H5FDget_eof()
+ *
+ * Return: Success: The EOF address.
+ *
+ * Failure: HADDR_UNDEF
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, August 4, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+haddr_t
+H5FD_get_eof(const H5FD_t *file)
+{
+ haddr_t ret_value;
+
+ FUNC_ENTER_NOAPI(H5FD_get_eof, HADDR_UNDEF)
+
+ HDassert(file && file->cls);
+
+ /* Dispatch to driver */
+ if(file->cls->get_eof) {
+ if(HADDR_UNDEF == (ret_value = (file->cls->get_eof)(file)))
+ HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "driver get_eof request failed")
+ } /* end if */
+ else
+ ret_value = file->maxaddr;
+
+ /* Adjust for base address in file */
+ ret_value -= file->base_addr;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_get_eof() */
+
diff --git a/src/H5FDlog.c b/src/H5FDlog.c
index 9a34a45..2a4dae6 100644
--- a/src/H5FDlog.c
+++ b/src/H5FDlog.c
@@ -190,7 +190,7 @@ static herr_t H5FD_log_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr
size_t size, void *buf);
static herr_t H5FD_log_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr,
size_t size, const void *buf);
-static herr_t H5FD_log_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
+static herr_t H5FD_log_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
#ifdef OLD_WAY
/*
@@ -233,14 +233,11 @@ static const H5FD_class_t H5FD_log_g = {
H5FD_log_get_handle, /*get_handle */
H5FD_log_read, /*read */
H5FD_log_write, /*write */
- H5FD_log_flush, /*flush */
+ NULL, /*flush */
+ H5FD_log_truncate, /*truncate */
NULL, /*lock */
NULL, /*unlock */
-#ifdef OLD_WAY
- H5FD_FLMAP_NOLIST /*fl_map */
-#else /* OLD_WAY */
H5FD_FLMAP_SINGLE /*fl_map */
-#endif /* OLD_WAY */
};
@@ -1306,30 +1303,27 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5FD_log_flush
+ * Function: H5FD_log_truncate
*
* Purpose: Makes sure that the true file size is the same (or larger)
* than the end-of-address.
*
* Return: Success: Non-negative
- *
* Failure: Negative
*
* Programmer: Robb Matzke
* Wednesday, August 4, 1999
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
/* ARGSUSED */
static herr_t
-H5FD_log_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing)
+H5FD_log_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing)
{
H5FD_log_t *file = (H5FD_log_t*)_file;
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5FD_log_flush, FAIL)
+ FUNC_ENTER_NOAPI(H5FD_log_truncate, FAIL)
if(file->eoa>file->eof) {
if(-1 == file_seek(file->fd, (file_offset_t)(file->eoa - 1), SEEK_SET))
@@ -1343,4 +1337,5 @@ H5FD_log_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing)
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_log_truncate() */
+
diff --git a/src/H5FDmpi.h b/src/H5FDmpi.h
index 885e844..b9998dd 100644
--- a/src/H5FDmpi.h
+++ b/src/H5FDmpi.h
@@ -120,3 +120,4 @@ H5_DLL MPI_Comm H5FD_mpi_get_comm(const H5FD_t *_file);
#endif /* H5_HAVE_PARALLEL */
#endif /* H5FDmpi_H */
+
diff --git a/src/H5FDmpio.c b/src/H5FDmpio.c
index 2bc0754..ea5a768 100644
--- a/src/H5FDmpio.c
+++ b/src/H5FDmpio.c
@@ -82,6 +82,7 @@ static herr_t H5FD_mpio_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, hadd
static herr_t H5FD_mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
size_t size, const void *buf);
static herr_t H5FD_mpio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
+static herr_t H5FD_mpio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
static int H5FD_mpio_mpi_rank(const H5FD_t *_file);
static int H5FD_mpio_mpi_size(const H5FD_t *_file);
static MPI_Comm H5FD_mpio_communicator(const H5FD_t *_file);
@@ -121,6 +122,7 @@ static const H5FD_class_mpi_t H5FD_mpio_g = {
H5FD_mpio_read, /*read */
H5FD_mpio_write, /*write */
H5FD_mpio_flush, /*flush */
+ H5FD_mpio_truncate, /*truncate */
NULL, /*lock */
NULL, /*unlock */
H5FD_FLMAP_SINGLE /*fl_map */
@@ -1859,68 +1861,106 @@ done:
*
* Failure: Negative
*
- * Programmer: Unknown
+ * Programmer: Robb Matzke
* January 30, 1998
*
- * Modifications:
- * Robb Matzke, 1998-02-18
- * Added the ACCESS_PARMS argument.
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_mpio_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned closing)
+{
+ H5FD_mpio_t *file = (H5FD_mpio_t*)_file;
+ int mpi_code; /* mpi return code */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(H5FD_mpio_flush, FAIL)
+
+#ifdef H5FDmpio_DEBUG
+ if(H5FD_mpio_Debug[(int)'t'])
+ HDfprintf(stdout, "Entering %s\n", FUNC);
+#endif
+ HDassert(file);
+ HDassert(H5FD_MPIO == file->pub.driver_id);
+
+ /* Only sync the file if we are not going to immediately close it */
+ if(!closing) {
+ if(MPI_SUCCESS != (mpi_code = MPI_File_sync(file->f)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_File_sync failed", mpi_code)
+ } /* end if */
+
+done:
+#ifdef H5FDmpio_DEBUG
+ if(H5FD_mpio_Debug[(int)'t'])
+ HDfprintf(stdout, "Leaving %s\n", FUNC);
+#endif
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_mpio_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_mpio_truncate
*
- * Robb Matzke, 1999-08-06
- * Modified to work with the virtual file layer.
+ * Purpose: Make certain the file's size matches it's allocated size
*
- * Robb Matzke, 2000-12-29
- * Make sure file size is at least as large as the last
- * allocated byte.
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Quincey Koziol, 2002-06-??
- * Changed file extension method to use MPI_File_set_size instead
- * read->write method.
+ * Programmer: Quincey Koziol
+ * January 31, 2008
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5FD_mpio_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned closing)
+H5FD_mpio_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t closing)
{
H5FD_mpio_t *file = (H5FD_mpio_t*)_file;
- int mpi_code; /* mpi return code */
- MPI_Offset mpi_off;
- herr_t ret_value=SUCCEED;
+ herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI(H5FD_mpio_flush, FAIL)
+ FUNC_ENTER_NOAPI(H5FD_mpio_truncate, FAIL)
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "Entering H5FD_mpio_flush\n" );
+ if(H5FD_mpio_Debug[(int)'t'])
+ HDfprintf(stdout, "Entering %s\n", FUNC);
#endif
- assert(file);
- assert(H5FD_MPIO==file->pub.driver_id);
+ HDassert(file);
+ HDassert(H5FD_MPIO == file->pub.driver_id);
/* Extend the file to make sure it's large enough, then sync.
* Unfortunately, keeping track of EOF is an expensive operation, so
* we can't just check whether EOF<EOA like with other drivers.
* Therefore we'll just read the byte at EOA-1 and then write it back. */
- if(file->eoa>file->last_eoa) {
+ if(file->eoa > file->last_eoa) {
+ int mpi_code; /* mpi return code */
+ MPI_Offset mpi_off;
+
#ifdef H5_MPI_FILE_SET_SIZE_BIG
- if (H5FD_mpi_haddr_to_MPIOff(file->eoa, &mpi_off)<0)
+ if(H5FD_mpi_haddr_to_MPIOff(file->eoa, &mpi_off) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "cannot convert from haddr_t to MPI_Offset")
/* Extend the file's size */
- if (MPI_SUCCESS != (mpi_code=MPI_File_set_size(file->f, mpi_off)))
+ if(MPI_SUCCESS != (mpi_code = MPI_File_set_size(file->f, mpi_off)))
HMPI_GOTO_ERROR(FAIL, "MPI_File_set_size failed", mpi_code)
#else /* H5_MPI_FILE_SET_SIZE_BIG */
- if (0==file->mpi_rank) {
- uint8_t byte=0;
+ /* Wait until all processes are here before reading/writing the byte at
+ * process 0's end of address space. The window for corruption is
+ * probably tiny, but does exist...
+ */
+ if(MPI_SUCCESS != (mpi_code = MPI_Barrier(file->comm)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed", mpi_code)
+
+ if(0 == file->mpi_rank) {
+ uint8_t byte = 0;
MPI_Status mpi_stat;
/* Portably initialize MPI status variable */
- HDmemset(&mpi_stat,0,sizeof(MPI_Status));
+ HDmemset(&mpi_stat, 0, sizeof(MPI_Status));
- if (H5FD_mpi_haddr_to_MPIOff(file->eoa-1, &mpi_off)<0)
+ if(H5FD_mpi_haddr_to_MPIOff(file->eoa-1, &mpi_off) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "cannot convert from haddr_t to MPI_Offset")
- if (MPI_SUCCESS != (mpi_code=MPI_File_read_at(file->f, mpi_off, &byte, 1, MPI_BYTE, &mpi_stat)))
+ if(MPI_SUCCESS != (mpi_code = MPI_File_read_at(file->f, mpi_off, &byte, 1, MPI_BYTE, &mpi_stat)))
HMPI_GOTO_ERROR(FAIL, "MPI_File_read_at failed", mpi_code)
- if (MPI_SUCCESS != (mpi_code=MPI_File_write_at(file->f, mpi_off, &byte, 1, MPI_BYTE, &mpi_stat)))
+ if(MPI_SUCCESS != (mpi_code = MPI_File_write_at(file->f, mpi_off, &byte, 1, MPI_BYTE, &mpi_stat)))
HMPI_GOTO_ERROR(FAIL, "MPI_File_write_at failed", mpi_code)
} /* end if */
#endif /* H5_MPI_FILE_SET_SIZE_BIG */
@@ -1931,27 +1971,21 @@ H5FD_mpio_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned closing)
* it the shorter length, potentially truncating the file and dropping
* the new data written)
*/
- if (MPI_SUCCESS!= (mpi_code=MPI_Barrier(file->comm)))
+ if(MPI_SUCCESS != (mpi_code = MPI_Barrier(file->comm)))
HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed", mpi_code)
/* Update the 'last' eoa value */
- file->last_eoa=file->eoa;
- } /* end if */
-
- /* Only sync the file if we are not going to immediately close it */
- if(!closing) {
- if (MPI_SUCCESS != (mpi_code=MPI_File_sync(file->f)))
- HMPI_GOTO_ERROR(FAIL, "MPI_File_sync failed", mpi_code)
+ file->last_eoa = file->eoa;
} /* end if */
done:
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "Leaving H5FD_mpio_flush\n" );
+ if(H5FD_mpio_Debug[(int)'t'])
+ HDfprintf(stdout, "Leaving %s\n", FUNC);
#endif
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_mpio_truncate() */
/*-------------------------------------------------------------------------
diff --git a/src/H5FDmpio.h b/src/H5FDmpio.h
index 8fa1be5..41baf8d 100644
--- a/src/H5FDmpio.h
+++ b/src/H5FDmpio.h
@@ -31,7 +31,7 @@
/* Macros */
#define IS_H5FD_MPIO(f) /* (H5F_t *f) */ \
- (H5FD_MPIO==H5F_get_driver_id(f))
+ (H5FD_MPIO==H5F_DRIVER_ID(f))
#ifdef H5_HAVE_PARALLEL
/*Turn on H5FDmpio_debug if H5F_DEBUG is on */
diff --git a/src/H5FDmpiposix.c b/src/H5FDmpiposix.c
index 9683e27..03e8cb3 100644
--- a/src/H5FDmpiposix.c
+++ b/src/H5FDmpiposix.c
@@ -190,7 +190,7 @@ static herr_t H5FD_mpiposix_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id,
size_t size, void *buf);
static herr_t H5FD_mpiposix_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr,
size_t size, const void *buf);
-static herr_t H5FD_mpiposix_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
+static herr_t H5FD_mpiposix_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
static int H5FD_mpiposix_mpi_rank(const H5FD_t *_file);
static int H5FD_mpiposix_mpi_size(const H5FD_t *_file);
static MPI_Comm H5FD_mpiposix_communicator(const H5FD_t *_file);
@@ -229,7 +229,8 @@ static const H5FD_class_mpi_t H5FD_mpiposix_g = {
H5FD_mpiposix_get_handle, /*get_handle */
H5FD_mpiposix_read, /*read */
H5FD_mpiposix_write, /*write */
- H5FD_mpiposix_flush, /*flush */
+ NULL, /*flush */
+ H5FD_mpiposix_truncate, /*truncate */
NULL, /*lock */
NULL, /*unlock */
H5FD_FLMAP_SINGLE /*fl_map */
@@ -1365,9 +1366,10 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5FD_mpiposix_flush
+ * Function: H5FD_mpiposix_truncate
*
- * Purpose: Makes sure that all data is on disk. This is collective.
+ * Purpose: Makes sure that the true file size is the same (or larger)
+ * than the end-of-address.
*
* Return: Success: Non-negative
* Failure: Negative
@@ -1375,12 +1377,10 @@ done:
* Programmer: Quincey Koziol
* Thursday, July 11, 2002
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static herr_t
-H5FD_mpiposix_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing)
+H5FD_mpiposix_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing)
{
H5FD_mpiposix_t *file = (H5FD_mpiposix_t*)_file;
#ifdef _WIN32
@@ -1388,15 +1388,15 @@ H5FD_mpiposix_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing
LARGE_INTEGER li; /* 64-bit integer for SetFilePointer() call */
#endif /* _WIN32 */
int mpi_code; /* MPI return code */
- herr_t ret_value=SUCCEED;
+ herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI(H5FD_mpiposix_flush, FAIL)
+ FUNC_ENTER_NOAPI(H5FD_mpiposix_truncate, FAIL)
- assert(file);
- assert(H5FD_MPIPOSIX==file->pub.driver_id);
+ HDassert(file);
+ HDassert(H5FD_MPIPOSIX == file->pub.driver_id);
/* Extend the file to make sure it's large enough */
- if(file->eoa>file->last_eoa) {
+ if(file->eoa > file->last_eoa) {
/* Use the round-robin process to truncate (extend) the file */
if(file->mpi_rank == H5_PAR_META_WRITE) {
#ifdef _WIN32
@@ -1406,8 +1406,8 @@ H5FD_mpiposix_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing
/* Translate 64-bit integers into form Windows wants */
/* [This algorithm is from the Windows documentation for SetFilePointer()] */
li.QuadPart = file->eoa;
- SetFilePointer((HANDLE)filehandle,li.LowPart,&li.HighPart,FILE_BEGIN);
- if(SetEndOfFile((HANDLE)filehandle)==0)
+ SetFilePointer((HANDLE)filehandle, li.LowPart, &li.HighPart, FILE_BEGIN);
+ if(SetEndOfFile((HANDLE)filehandle) == 0)
HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
#else /* _WIN32 */
if(-1==file_truncate(file->fd, (file_offset_t)file->eoa))
@@ -1421,11 +1421,11 @@ H5FD_mpiposix_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing
* it the shorter length, potentially truncating the file and dropping
* the new data written)
*/
- if (MPI_SUCCESS!= (mpi_code=MPI_Barrier(file->comm)))
+ if(MPI_SUCCESS != (mpi_code = MPI_Barrier(file->comm)))
HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed", mpi_code)
/* Update the 'last' eoa and eof values */
- file->last_eoa=file->eoa;
+ file->last_eoa = file->eoa;
file->eof = file->eoa;
/* Reset last file I/O information */
@@ -1435,7 +1435,7 @@ H5FD_mpiposix_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_mpiposix_flush() */
+} /* end H5FD_mpiposix_truncate() */
/*-------------------------------------------------------------------------
diff --git a/src/H5FDmpiposix.h b/src/H5FDmpiposix.h
index 70e632a..832839e 100644
--- a/src/H5FDmpiposix.h
+++ b/src/H5FDmpiposix.h
@@ -32,7 +32,7 @@
/* Macros */
#define IS_H5FD_MPIPOSIX(f) /* (H5F_t *f) */ \
- (H5FD_MPIPOSIX==H5F_get_driver_id(f))
+ (H5FD_MPIPOSIX==H5F_DRIVER_ID(f))
#ifdef H5_HAVE_PARALLEL
@@ -54,4 +54,3 @@ H5_DLL herr_t H5Pget_fapl_mpiposix(hid_t fapl_id, MPI_Comm *comm/*out*/, hbool_t
#endif /* __H5FDmpiposix_H */
-
diff --git a/src/H5FDmulti.c b/src/H5FDmulti.c
index 27a7cac..6b53d9e 100644
--- a/src/H5FDmulti.c
+++ b/src/H5FDmulti.c
@@ -152,6 +152,7 @@ static herr_t H5FD_multi_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, had
static herr_t H5FD_multi_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
size_t size, const void *_buf);
static herr_t H5FD_multi_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
+static herr_t H5FD_multi_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
/* The class struct */
static const H5FD_class_t H5FD_multi_g = {
@@ -181,6 +182,7 @@ static const H5FD_class_t H5FD_multi_g = {
H5FD_multi_read, /*read */
H5FD_multi_write, /*write */
H5FD_multi_flush, /*flush */
+ H5FD_multi_truncate, /*truncate */
NULL, /*lock */
NULL, /*unlock */
H5FD_FLMAP_DEFAULT /*fl_map */
@@ -1461,7 +1463,7 @@ H5FD_multi_get_eoa(const H5FD_t *_file, H5FD_mem_t type)
const H5FD_multi_t *file = (const H5FD_multi_t*)_file;
haddr_t eoa = 0;
haddr_t memb_eoa = 0;
- static const char *func="H5FD_multi_eof"; /* Function Name for error reporting */
+ static const char *func="H5FD_multi_eoa"; /* Function Name for error reporting */
/* Clear the error stack */
H5Eclear2(H5E_DEFAULT);
@@ -1470,7 +1472,7 @@ H5FD_multi_get_eoa(const H5FD_t *_file, H5FD_mem_t type)
* taken out because it makes little sense for MULTI files.
* However, the library sometimes queries it through H5F_get_eoa.
* Here the code finds the biggest EOA for individual file if
- * the query is from H5F_get_eoa (TYPE is H5FD_MEM_DEFAULT).
+ * the query is for TYPE == H5FD_MEM_DEFAULT.
*/
if(H5FD_MEM_DEFAULT == type) {
UNIQUE_MEMBERS(file->fa.memb_map, mt) {
@@ -1507,6 +1509,7 @@ H5FD_multi_get_eoa(const H5FD_t *_file, H5FD_mem_t type)
if (HADDR_UNDEF==eoa)
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "member file has unknown eoa", HADDR_UNDEF)
+ if (eoa>0) eoa += file->fa.memb_addr[mmt];
} else if (file->fa.relax) {
/*
* The member is not open yet (maybe it doesn't exist). Make the
@@ -1551,14 +1554,22 @@ static herr_t
H5FD_multi_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t eoa)
{
H5FD_multi_t *file = (H5FD_multi_t*)_file;
+ H5FD_mem_t mmt;
herr_t status;
static const char *func="H5FD_multi_set_eoa"; /* Function Name for error reporting */
/* Clear the error stack */
H5Eclear2(H5E_DEFAULT);
+ mmt = file->fa.memb_map[type];
+ if(H5FD_MEM_DEFAULT == mmt)
+ mmt = type;
+
+ assert(eoa >= file->fa.memb_addr[mmt]);
+ assert(eoa < file->memb_next[mmt]);
+
H5E_BEGIN_TRY {
- status = H5FDset_eoa(file->memb[type], type, eoa);
+ status = H5FDset_eoa(file->memb[mmt], mmt, (eoa - file->fa.memb_addr[mmt]));
} H5E_END_TRY;
if (status<0)
H5Epush_ret(func, H5E_ERR_CLS, H5E_FILE, H5E_BADVALUE, "member H5FDset_eoa failed", -1)
@@ -1596,7 +1607,7 @@ H5FD_multi_get_eof(const H5FD_t *_file)
const H5FD_multi_t *file = (const H5FD_multi_t*)_file;
haddr_t eof=0, tmp_eof;
haddr_t eoa=0, tmp_eoa;
- static const char *func="H5FD_multi_eof"; /* Function Name for error reporting */
+ static const char *func="H5FD_multi_get_eof"; /* Function Name for error reporting */
/* Clear the error stack */
H5Eclear2(H5E_DEFAULT);
@@ -1619,6 +1630,7 @@ H5FD_multi_get_eof(const H5FD_t *_file)
if (HADDR_UNDEF==tmp_eoa)
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "member file has unknown eoa", HADDR_UNDEF)
+ if (tmp_eoa>0) tmp_eoa += file->fa.memb_addr[mt];
} else if (file->fa.relax) {
/*
* The member is not open yet (maybe it doesn't exist). Make the
@@ -1701,7 +1713,7 @@ H5FD_multi_alloc(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size)
mmt = file->fa.memb_map[type];
if (H5FD_MEM_DEFAULT==mmt) mmt = type;
- if (HADDR_UNDEF==(addr=H5FDalloc(file->memb[mmt], type, dxpl_id, size)))
+ if (HADDR_UNDEF==(addr=H5FDalloc(file->memb[mmt], mmt, dxpl_id, size)))
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "member file can't alloc", HADDR_UNDEF)
addr += file->fa.memb_addr[mmt];
@@ -1753,7 +1765,7 @@ H5FD_multi_free(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsi
assert(addr>=file->fa.memb_addr[mmt]);
assert(addr+size<=file->memb_next[mmt]);
- return H5FDfree(file->memb[mmt], type, dxpl_id, addr-file->fa.memb_addr[mmt], size);
+ return H5FDfree(file->memb[mmt], mmt, dxpl_id, addr-file->fa.memb_addr[mmt], size);
}
@@ -1943,6 +1955,46 @@ H5FD_multi_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing)
/*-------------------------------------------------------------------------
+ * Function: H5FD_multi_truncate
+ *
+ * Purpose: Truncates all multi members.
+ *
+ * Return: Success: 0
+ * Failure: -1, as many files truncated as possible.
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, January 31, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_multi_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing)
+{
+ H5FD_multi_t *file = (H5FD_multi_t*)_file;
+ H5FD_mem_t mt;
+ int nerrors=0;
+ static const char *func="H5FD_multi_truncate"; /* Function Name for error reporting */
+
+ /* Clear the error stack */
+ H5Eclear2(H5E_DEFAULT);
+
+ /* Truncate each file */
+ for(mt = H5FD_MEM_SUPER; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) {
+ if(file->memb[mt]) {
+ H5E_BEGIN_TRY {
+ if(H5FDtruncate(file->memb[mt], dxpl_id, closing) < 0)
+ nerrors++;
+ } H5E_END_TRY;
+ }
+ }
+ if(nerrors)
+ H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "error truncating member files", -1)
+
+ return 0;
+} /* end H5FD_multi_truncate() */
+
+
+/*-------------------------------------------------------------------------
* Function: compute_next
*
* Purpose: Compute the memb_next[] values of the file based on the
diff --git a/src/H5FDpkg.h b/src/H5FDpkg.h
index 700ec1d..9401b52 100644
--- a/src/H5FDpkg.h
+++ b/src/H5FDpkg.h
@@ -48,15 +48,11 @@
/* Package Private Variables */
/*****************************/
-/* Declare a PQ free list to manage the metadata accumulator buffer */
-H5FL_BLK_EXTERN(meta_accum);
-
/******************************/
/* Package Private Prototypes */
/******************************/
H5_DLL herr_t H5FD_init(void);
-H5_DLL herr_t H5FD_free_freelist(H5FD_t *file);
/* Testing routines */
diff --git a/src/H5FDprivate.h b/src/H5FDprivate.h
index f4797bb..25b2f24 100644
--- a/src/H5FDprivate.h
+++ b/src/H5FDprivate.h
@@ -55,27 +55,25 @@ H5_DLL H5FD_t *H5FD_open(const char *name, unsigned flags, hid_t fapl_id,
H5_DLL herr_t H5FD_close(H5FD_t *file);
H5_DLL int H5FD_cmp(const H5FD_t *f1, const H5FD_t *f2);
H5_DLL int H5FD_query(const H5FD_t *f, unsigned long *flags/*out*/);
-H5_DLL haddr_t H5FD_alloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size);
-H5_DLL herr_t H5FD_free(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t size);
-H5_DLL haddr_t H5FD_realloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t old_addr,
- hsize_t old_size, hsize_t new_size);
+H5_DLL haddr_t H5FD_alloc(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, hsize_t size, haddr_t *align_addr, hsize_t *align_size);
+H5_DLL herr_t H5FD_free(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr, hsize_t size);
+H5_DLL htri_t H5FD_try_extend(H5FD_t *file, H5FD_mem_t type, haddr_t blk_end,
+ hsize_t extra_requested);
H5_DLL haddr_t H5FD_get_eoa(const H5FD_t *file, H5FD_mem_t type);
H5_DLL herr_t H5FD_set_eoa(H5FD_t *file, H5FD_mem_t type, haddr_t addr);
H5_DLL haddr_t H5FD_get_eof(const H5FD_t *file);
H5_DLL haddr_t H5FD_get_maxaddr(const H5FD_t *file);
-H5_DLL herr_t H5FD_read(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size,
- void *buf/*out*/);
-H5_DLL herr_t H5FD_write(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size,
- const void *buf);
+H5_DLL herr_t H5FD_get_feature_flags(const H5FD_t *file, unsigned long *feature_flags);
+H5_DLL herr_t H5FD_get_fs_type_map(const H5FD_t *file, H5FD_mem_t *type_map);
+H5_DLL herr_t H5FD_read(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type,
+ haddr_t addr, size_t size, void *buf/*out*/);
+H5_DLL herr_t H5FD_write(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type,
+ haddr_t addr, size_t size, const void *buf);
H5_DLL herr_t H5FD_flush(H5FD_t *file, hid_t dxpl_id, unsigned closing);
+H5_DLL herr_t H5FD_truncate(H5FD_t *file, hid_t dxpl_id, hbool_t closing);
H5_DLL herr_t H5FD_get_fileno(const H5FD_t *file, unsigned long *filenum);
H5_DLL herr_t H5FD_get_vfd_handle(H5FD_t *file, hid_t fapl, void** file_handle);
-H5_DLL hssize_t H5FD_get_freespace(const H5FD_t *file);
-H5_DLL htri_t H5FD_can_extend(const H5FD_t *file, H5FD_mem_t type, haddr_t addr,
- hsize_t size, hsize_t extra_requested);
-H5_DLL herr_t H5FD_extend(H5FD_t *file, H5FD_mem_t type, haddr_t addr,
- hsize_t size, hsize_t extra_requested);
-H5_DLL herr_t H5FD_aggr_reset(H5FD_t *file, H5FD_blk_aggr_t *aggr, hid_t dxpl_id);
+H5_DLL herr_t H5FD_set_base_addr(H5FD_t *file, haddr_t base_addr);
#endif /* !_H5FDprivate_H */
diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h
index ef48edd..f960a1c 100644
--- a/src/H5FDpublic.h
+++ b/src/H5FDpublic.h
@@ -230,6 +230,7 @@ typedef struct H5FD_class_t {
herr_t (*write)(H5FD_t *file, H5FD_mem_t type, hid_t dxpl,
haddr_t addr, size_t size, const void *buffer);
herr_t (*flush)(H5FD_t *file, hid_t dxpl_id, unsigned closing);
+ herr_t (*truncate)(H5FD_t *file, hid_t dxpl_id, hbool_t closing);
herr_t (*lock)(H5FD_t *file, unsigned char *oid, unsigned lock_type, hbool_t last);
herr_t (*unlock)(H5FD_t *file, unsigned char *oid, hbool_t last);
H5FD_mem_t fl_map[H5FD_MEM_NTYPES];
@@ -242,15 +243,6 @@ typedef struct H5FD_free_t {
struct H5FD_free_t *next;
} H5FD_free_t;
-/* Structure for metadata & "small [raw] data" block aggregation fields */
-typedef struct H5FD_blk_aggr_t {
- unsigned long feature_flag; /* Feature flag type */
- hsize_t alloc_size; /* Size for allocating new blocks */
- hsize_t tot_size; /* Total amount of bytes aggregated into block */
- hsize_t size; /* Current size of block left */
- haddr_t addr; /* Location of block left */
-} H5FD_blk_aggr_t;
-
/*
* The main datatype for each driver. Public fields common to all drivers
* are declared here and the driver appends private fields in memory.
@@ -258,32 +250,14 @@ typedef struct H5FD_blk_aggr_t {
struct H5FD_t {
hid_t driver_id; /*driver ID for this file */
const H5FD_class_t *cls; /*constant class info */
- unsigned long fileno; /* File serial number */
+ unsigned long fileno; /* File 'serial' number */
unsigned long feature_flags; /* VFL Driver feature Flags */
+ haddr_t maxaddr; /* For this file, overrides class */
+ haddr_t base_addr; /* Base address for HDF5 data w/in file */
+
+ /* Space allocation management fields */
hsize_t threshold; /* Threshold for alignment */
hsize_t alignment; /* Allocation alignment */
-
- /* Block aggregation info */
- H5FD_blk_aggr_t meta_aggr; /* Metadata aggregation info */
- /* (if aggregating metadata allocations) */
- H5FD_blk_aggr_t sdata_aggr; /* "Small data" aggregation info */
- /* (if aggregating "small data" allocations) */
-
- /* Metadata accumulator fields */
- unsigned char *meta_accum; /* Buffer to hold the accumulated metadata */
- haddr_t accum_loc; /* File location (offset) of the
- * accumulated metadata */
- size_t accum_size; /* Size of the accumulated
- * metadata buffer used (in
- * bytes) */
- size_t accum_buf_size; /* Size of the accumulated
- * metadata buffer allocated (in
- * bytes) */
- unsigned accum_dirty; /* Flag to indicate that the
- * accumulated metadata is dirty */
- haddr_t maxaddr; /* For this file, overrides class */
- H5FD_free_t *fl[H5FD_MEM_NTYPES]; /* Freelist per allocation type */
- hsize_t maxsize; /* Largest object on FL, or zero */
};
#ifdef __cplusplus
@@ -301,8 +275,6 @@ H5_DLL int H5FDquery(const H5FD_t *f, unsigned long *flags);
H5_DLL haddr_t H5FDalloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size);
H5_DLL herr_t H5FDfree(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id,
haddr_t addr, hsize_t size);
-H5_DLL haddr_t H5FDrealloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id,
- haddr_t addr, hsize_t old_size, hsize_t new_size);
H5_DLL haddr_t H5FDget_eoa(H5FD_t *file, H5FD_mem_t type);
H5_DLL herr_t H5FDset_eoa(H5FD_t *file, H5FD_mem_t type, haddr_t eoa);
H5_DLL haddr_t H5FDget_eof(H5FD_t *file);
@@ -312,6 +284,7 @@ H5_DLL herr_t H5FDread(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id,
H5_DLL herr_t H5FDwrite(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id,
haddr_t addr, size_t size, const void *buf);
H5_DLL herr_t H5FDflush(H5FD_t *file, hid_t dxpl_id, unsigned closing);
+H5_DLL herr_t H5FDtruncate(H5FD_t *file, hid_t dxpl_id, hbool_t closing);
#ifdef __cplusplus
}
diff --git a/src/H5FDsec2.c b/src/H5FDsec2.c
index 1073a87..cace117 100644
--- a/src/H5FDsec2.c
+++ b/src/H5FDsec2.c
@@ -158,7 +158,7 @@ static herr_t H5FD_sec2_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, hadd
size_t size, void *buf);
static herr_t H5FD_sec2_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr,
size_t size, const void *buf);
-static herr_t H5FD_sec2_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
+static herr_t H5FD_sec2_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
static const H5FD_class_t H5FD_sec2_g = {
"sec2", /*name */
@@ -186,7 +186,8 @@ static const H5FD_class_t H5FD_sec2_g = {
H5FD_sec2_get_handle, /*get_handle */
H5FD_sec2_read, /*read */
H5FD_sec2_write, /*write */
- H5FD_sec2_flush, /*flush */
+ NULL, /*flush */
+ H5FD_sec2_truncate, /*truncate */
NULL, /*lock */
NULL, /*unlock */
H5FD_FLMAP_SINGLE /*fl_map */
@@ -419,22 +420,28 @@ done:
* Programmer: Robb Matzke
* Thursday, July 29, 1999
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static herr_t
H5FD_sec2_close(H5FD_t *_file)
{
H5FD_sec2_t *file = (H5FD_sec2_t*)_file;
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5FD_sec2_close, FAIL)
+#ifdef QAK
+HDfprintf(stderr, "%s: file->eof = %a, file->eoa = %a\n", FUNC, file->eof, file->eoa);
+#endif /* QAK */
+
+ /* Sanity check */
+ HDassert(file);
- if (HDclose(file->fd)<0)
+ /* Close the underlying file */
+ if(HDclose(file->fd) < 0)
HSYS_GOTO_ERROR(H5E_IO, H5E_CANTCLOSEFILE, FAIL, "unable to close file")
- (void)H5FL_FREE(H5FD_sec2_t,file);
+ /* Release the file info */
+ (void)H5FL_FREE(H5FD_sec2_t, file);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -612,7 +619,7 @@ H5FD_sec2_set_eoa(H5FD_t *_file, H5FD_mem_t UNUSED type, haddr_t addr)
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_sec2_set_eoa() */
/*-------------------------------------------------------------------------
@@ -765,7 +772,7 @@ done:
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_sec2_read() */
/*-------------------------------------------------------------------------
@@ -846,11 +853,11 @@ done:
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_sec2_write() */
/*-------------------------------------------------------------------------
- * Function: H5FD_sec2_flush
+ * Function: H5FD_sec2_truncate
*
* Purpose: Makes sure that the true file size is the same (or larger)
* than the end-of-address.
@@ -862,23 +869,24 @@ done:
* Programmer: Robb Matzke
* Wednesday, August 4, 1999
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
/* ARGSUSED */
static herr_t
-H5FD_sec2_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing)
+H5FD_sec2_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing)
{
- H5FD_sec2_t *file = (H5FD_sec2_t*)_file;
- herr_t ret_value=SUCCEED; /* Return value */
+ H5FD_sec2_t *file = (H5FD_sec2_t*)_file;
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5FD_sec2_flush, FAIL)
+ FUNC_ENTER_NOAPI(H5FD_sec2_truncate, FAIL)
+#ifdef QAK
+HDfprintf(stderr, "%s: file->eof = %a, file->eoa = %a\n", FUNC, file->eof, file->eoa);
+#endif /* QAK */
- assert(file);
+ HDassert(file);
/* Extend the file to make sure it's large enough */
- if (file->eoa!=file->eof) {
+ if(!H5F_addr_eq(file->eoa, file->eof)) {
#ifdef _WIN32
HFILE filehandle; /* Windows file handle */
LARGE_INTEGER li; /* 64-bit integer for SetFilePointer() call */
@@ -889,11 +897,11 @@ H5FD_sec2_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing)
/* Translate 64-bit integers into form Windows wants */
/* [This algorithm is from the Windows documentation for SetFilePointer()] */
li.QuadPart = (LONGLONG)file->eoa;
- (void)SetFilePointer((HANDLE)filehandle,li.LowPart,&li.HighPart,FILE_BEGIN);
- if(SetEndOfFile((HANDLE)filehandle)==0)
+ (void)SetFilePointer((HANDLE)filehandle, li.LowPart, &li.HighPart, FILE_BEGIN);
+ if(SetEndOfFile((HANDLE)filehandle) == 0)
HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
#else /* _WIN32 */
- if (-1==file_truncate(file->fd, (file_offset_t)file->eoa))
+ if(-1 == file_truncate(file->fd, (file_offset_t)file->eoa))
HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
#endif /* _WIN32 */
@@ -903,8 +911,9 @@ H5FD_sec2_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing)
/* Reset last file I/O information */
file->pos = HADDR_UNDEF;
file->op = OP_UNKNOWN;
- }
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_sec2_truncate() */
+
diff --git a/src/H5FDspace.c b/src/H5FDspace.c
index 0bbf160..0fadc1e 100644
--- a/src/H5FDspace.c
+++ b/src/H5FDspace.c
@@ -66,19 +66,6 @@
/********************/
/* Local Prototypes */
/********************/
-static haddr_t H5FD_alloc_from_free_list(H5FD_t *file, H5FD_mem_t type,
- hsize_t size);
-static haddr_t H5FD_aggr_alloc(H5FD_t *file, H5FD_blk_aggr_t *aggr,
- H5FD_blk_aggr_t *other_aggr, H5FD_mem_t type, hid_t dxpl_id, hsize_t size);
-static herr_t H5FD_aggr_adjoin(const H5FD_t *file, H5FD_blk_aggr_t *aggr,
- H5FD_free_t *last);
-static htri_t H5FD_aggr_can_extend(const H5FD_t *file, const H5FD_blk_aggr_t *aggr,
- haddr_t eoa, haddr_t end);
-static herr_t H5FD_aggr_shift(H5FD_blk_aggr_t *aggr, hsize_t extra);
-static herr_t H5FD_aggr_query(const H5FD_t *file, const H5FD_blk_aggr_t *aggr,
- haddr_t *addr, hsize_t *size);
-static haddr_t H5FD_real_alloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size);
-static haddr_t H5FD_update_eoa(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size);
/*********************/
@@ -98,9 +85,6 @@ static haddr_t H5FD_update_eoa(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsi
/* Declare a free list to manage the H5FD_free_t struct */
H5FL_DEFINE(H5FD_free_t);
-/* Declare a PQ free list to manage the metadata accumulator buffer */
-H5FL_BLK_DEFINE(meta_accum);
-
/*--------------------------------------------------------------------------
@@ -126,965 +110,127 @@ H5FD_space_init_interface(void)
/*-------------------------------------------------------------------------
- * Function: H5FD_free_freelist
- *
- * Purpose: Split off from H5FD_close(). Free the elements in the
- * free list for this file driver.
- *
- * Return: Success: SUCCEED
- * Failure: Never fails
- *
- * Programmer: Bill Wendling
- * 17. February 2003
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5FD_free_freelist(H5FD_t *file)
-{
- H5FD_mem_t i;
-#ifdef H5FD_ALLOC_DEBUG
- unsigned nblocks = 0;
- hsize_t nbytes = 0;
-#endif /* H5FD_ALLOC_DEBUG */
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_free_freelist)
-
- /* check args */
- HDassert(file && file->cls);
-
- /*
- * Free all free-lists, leaking any memory thus described. Also leaks
- * file space allocated but not used when metadata aggregation is
- * turned on.
- */
- for(i = H5FD_MEM_DEFAULT; i < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, i)) {
- H5FD_free_t *cur, *next;
-
- for( cur = file->fl[i]; cur; cur = next) {
-#ifdef H5FD_ALLOC_DEBUG
- ++nblocks;
- nbytes += cur->size;
-#endif /* H5FD_ALLOC_DEBUG */
- next = cur->next;
- (void)H5FL_FREE(H5FD_free_t, cur);
- } /* end for */
-
- file->fl[i] = NULL;
- } /* end for */
-
-#ifdef H5FD_ALLOC_DEBUG
- if(nblocks)
- HDfprintf(stderr, "%s: leaked %Hu bytes of file memory in %u blocks\n",
- "H5FD_free_freelist", nbytes, nblocks);
-#endif /* H5FD_ALLOC_DEBUG */
-
- /* Check if we need to reset the metadata accumulator information */
- if(file->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) {
- /* Free the buffer */
- if(file->meta_accum)
- file->meta_accum = H5FL_BLK_FREE(meta_accum, file->meta_accum);
-
- /* Reset the buffer sizes & location */
- file->accum_buf_size = file->accum_size = 0;
- file->accum_loc = HADDR_UNDEF;
- file->accum_dirty = 0;
- } /* end if */
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5FD_free_freelist() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_alloc
- *
- * Purpose: Private version of H5FDalloc().
- *
- * Return: Success: The format address of the new file memory.
- * Failure: The undefined address HADDR_UNDEF
- *
- * Programmer: Robb Matzke
- * Wednesday, August 4, 1999
- *
- *-------------------------------------------------------------------------
- */
-haddr_t
-H5FD_alloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size)
-{
- haddr_t ret_value = HADDR_UNDEF;
-
- FUNC_ENTER_NOAPI(H5FD_alloc, HADDR_UNDEF)
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size);
-#endif /* H5FD_ALLOC_DEBUG */
-
- /* check args */
- assert(file);
- assert(file->cls);
- assert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES);
- assert(size > 0);
-
-#ifdef H5F_DEBUG
- if(H5DEBUG(F))
- HDfprintf(H5DEBUG(F), "%s: alignment=%Hd, threshold=%Hd, size=%Hd\n",
- FUNC, file->alignment, file->threshold, size);
-#endif /* H5F_DEBUG */
-
- /* Try to allocate from the free list first */
- if((ret_value = H5FD_alloc_from_free_list(file, type, size)) != HADDR_UNDEF)
- HGOTO_DONE(ret_value)
-
-#ifdef H5F_DEBUG
- if(H5DEBUG(F))
- HDfprintf(H5DEBUG(F), "%s: Could not allocate from freelists\n", FUNC);
-#endif /* H5F_DEBUG */
-
- if(type != H5FD_MEM_DRAW) {
- /* Handle metadata differently from "raw" data */
- if(HADDR_UNDEF == (ret_value = H5FD_aggr_alloc(file, &(file->meta_aggr), &(file->sdata_aggr), type, dxpl_id, size)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate metadata")
- } /* end if */
- else {
- /* Allocate "raw" data */
- if(HADDR_UNDEF == (ret_value = H5FD_aggr_alloc(file, &(file->sdata_aggr), &(file->meta_aggr), type, dxpl_id, size)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate raw data")
- } /* end else */
-
-done:
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value);
-#endif /* H5FD_ALLOC_DEBUG */
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_alloc() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_alloc_from_free_list
+ * Function: H5FD_extend
*
- * Purpose: Try to allocate SIZE bytes of memory from the free list
- * if possible.
+ * Purpose: Extend the EOA space of a file.
*
- * This is split from H5FD_alloc().
+ * NOTE: Returns absolute file offset
*
- * Return: Success: The format address of the new file memory.
+ * Return: Success: The address of the previous EOA.
* Failure: The undefined address HADDR_UNDEF
*
* Programmer: Bill Wendling
- * 02. December, 2002
- *
- *-------------------------------------------------------------------------
- */
-static haddr_t
-H5FD_alloc_from_free_list(H5FD_t *file, H5FD_mem_t type, hsize_t size)
-{
- H5FD_mem_t mapped_type;
- haddr_t ret_value = HADDR_UNDEF;
-
- FUNC_ENTER_NOAPI(H5FD_alloc_from_free_list, HADDR_UNDEF)
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size);
-#endif /* H5FD_ALLOC_DEBUG */
-
- assert(file);
- assert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES);
- assert(size > 0);
-
- /* Map the allocation request to a free list */
- if(H5FD_MEM_DEFAULT == file->cls->fl_map[type])
- mapped_type = type;
- else
- mapped_type = file->cls->fl_map[type];
-
- /*
- * Try to satisfy the request from the free list. Only perform the
- * search if the free list has the potential of satisfying the
- * request.
- *
- * Here, aligned requests are requests that are >= threshold and
- * alignment > 1.
- *
- * For non-aligned request, first try to find an exact match,
- * otherwise use the best match which is the smallest size that meets
- * the requested size.
- *
- * For aligned address request, find a block in the following order
- * of preferences:
- *
- * 1. block address is aligned and exact match in size;
- * 2. block address is aligned with smallest size > requested size;
- * 3. block address is not aligned with smallest size >= requested size.
- */
- if(mapped_type >= H5FD_MEM_DEFAULT && (file->maxsize == 0 || size <= file->maxsize)) {
- H5FD_free_t *prev = NULL, *best = NULL;
- H5FD_free_t *cur = file->fl[mapped_type];
- hbool_t found_aligned = FALSE;
- hbool_t need_aligned;
- hsize_t head;
-
- need_aligned = file->alignment > 1 && size >= file->threshold;
-
- while(cur) {
- if(cur->size > file->maxsize)
- file->maxsize = cur->size;
-
- if(need_aligned) {
- if((head = cur->addr % file->alignment) == 0) {
- /*
- * Aligned address
- */
- if(cur->size >= size) {
- if(cur->size == size) {
- /* exact match */
- ret_value = cur->addr;
-
- /*
- * Make certain we don't hand out a block of raw data
- * from the free list which overlaps with the metadata
- * aggregation buffer (if it's turned on)
- */
- if(type == H5FD_MEM_DRAW &&
- (file->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) &&
- H5F_addr_overlap(ret_value, size,
- file->accum_loc, file->accum_size)) {
- ret_value = HADDR_UNDEF;
- } else {
- if(prev)
- prev->next = cur->next;
- else
- file->fl[mapped_type] = cur->next;
-
- (void)H5FL_FREE(H5FD_free_t, cur);
-
- if(size == file->maxsize)
- file->maxsize = 0; /*unknown*/
-
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: Exact size match (aligned)\n", FUNC);
-#endif /* H5FD_ALLOC_DEBUG */
- HGOTO_DONE(ret_value)
- }
- }
- else
- /* Favor smallest block, that's closest to the beginning of the file */
- if(!best || !found_aligned || cur->size < best->size ||
- (cur->size == best->size && H5F_addr_lt(cur->addr, best->addr))) {
- best = cur;
- found_aligned = TRUE;
- }
- } /* end if */
- } else {
- /*
- * Non-aligned address
- *
- * Check to see if this block is big enough to skip
- * to the next aligned address and is still big
- * enough for the requested size. The extra
- * (cur->size > head) is for preventing unsigned
- * underflow. (This could be improved by checking for
- * an exact match after excluding the head. Such
- * match is as good as the found_aligned case above.)
- */
- head = file->alignment - head; /* actual head size */
-
- if(!found_aligned && cur->size > head && cur->size-head >= size) {
- /* Favor smallest block, that's closest to the beginning of the file */
- if(!best || cur->size < best->size ||
- (cur->size == best->size && H5F_addr_lt(cur->addr, best->addr)))
- best = cur;
- } /* end if */
- } /* end else */
- } else {
- /* !need_aligned */
- if(cur->size >= size) {
- if(cur->size == size) {
- /* exact match */
- ret_value = cur->addr;
-
- /*
- * Make certain we don't hand out a block of raw data
- * from the free list which overlaps with the metadata
- * aggregation buffer (if it's turned on)
- */
- if(type == H5FD_MEM_DRAW &&
- (file->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) &&
- H5F_addr_overlap(ret_value, size, file->accum_loc,
- file->accum_size)) {
- ret_value = HADDR_UNDEF;
- } else {
- if(prev)
- prev->next = cur->next;
- else
- file->fl[mapped_type] = cur->next;
-
- (void)H5FL_FREE(H5FD_free_t, cur);
-
- if(size == file->maxsize)
- file->maxsize = 0; /*unknown*/
-
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: Exact size match (unaligned)\n", FUNC);
-#endif /* H5FD_ALLOC_DEBUG */
- HGOTO_DONE(ret_value)
- }
- } /* end if */
- else {
- /* Favor smallest block, that's closest to the beginning of the file */
- if(!best || cur->size < best->size ||
- (cur->size == best->size && H5F_addr_lt(cur->addr, best->addr)))
- best = cur;
- } /* end else */
- } /* end if */
- } /* end else */
-
- prev = cur;
- cur = cur->next;
- } /* end while */
-
- /* Couldn't find exact match, use best fitting piece found */
- if(best) {
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: Splitting %Hu byte sized block\n", FUNC, best->size);
-#endif /* H5FD_ALLOC_DEBUG */
- if(best->size == file->maxsize)
- file->maxsize = 0; /*unknown*/
-
- if(!need_aligned || found_aligned) {
- /* free only tail */
- ret_value = best->addr;
-
- /*
- * Make certain we don't hand out a block of raw data
- * from the free list which overlaps with the metadata
- * aggregation buffer (if it's turned on)
- */
- if(type == H5FD_MEM_DRAW &&
- (file->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) &&
- H5F_addr_overlap(ret_value, size, file->accum_loc,
- file->accum_size)) {
- ret_value = HADDR_UNDEF;
- } else {
- best->addr += size; /* Reduce size of block on free list */
- best->size -= size;
- HGOTO_DONE(ret_value)
- }
- } else {
- /*
- * Split into 3 pieces. Keep the the head and tail in the
- * freelist.
- */
- H5FD_free_t *tmp = NULL;
-
- head = file->alignment - (best->addr % file->alignment);
- ret_value = best->addr + head;
-
- /*
- * Make certain we don't hand out a block of raw data
- * from the free list which overlaps with the metadata
- * aggregation buffer (if it's turned on)
- */
- if(type == H5FD_MEM_DRAW &&
- (file->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) &&
- H5F_addr_overlap(ret_value, size, file->accum_loc, file->accum_size)) {
- ret_value = HADDR_UNDEF;
- } else {
- /* Attempt to allocate memory for temporary node */
- if((tmp = H5FL_MALLOC(H5FD_free_t))==NULL)
- HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "free block allocation failed")
-
- if((tmp->size = (best->size - (head + size)))!=0) {
- tmp->addr = best->addr + (head + size);
- tmp->next = best->next;
- best->next = tmp;
- } else {
- /* no tail piece */
- (void)H5FL_FREE(H5FD_free_t,tmp);
- }
-
- best->size = head;
- HGOTO_DONE(ret_value)
- } /* end else */
- } /* end else */
- } /* end if */
- } /* end if */
-
-done:
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value);
-#endif /* H5FD_ALLOC_DEBUG */
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_alloc_from_free_list() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_aggr_alloc
- *
- * Purpose: Try to allocate SIZE bytes of memory from an aggregator
- * block if possible.
- *
- * This is split from H5FD_alloc().
- *
- * Return: Success: The format address of the new file memory.
- * Failure: The undefined address HADDR_UNDEF
+ * Wednesday, 04. December, 2002
*
- * Programmer: Bill Wendling
- * 2. December, 2002
+ * Modifications:
+ * Vailin Choi, 29th July 2008
+ * Add 2 more parameters for handling alignment: address and size of the fragment
*
*-------------------------------------------------------------------------
*/
static haddr_t
-H5FD_aggr_alloc(H5FD_t *file, H5FD_blk_aggr_t *aggr, H5FD_blk_aggr_t *other_aggr,
- H5FD_mem_t type, hid_t dxpl_id, hsize_t size)
+H5FD_extend(H5FD_t *file, H5FD_mem_t type, hbool_t new_block, hsize_t size, haddr_t *frag_addr, hsize_t *frag_size)
{
+ haddr_t eoa; /* Address of end-of-allocated space */
+ hsize_t extra; /* Extra space to allocate, to align request */
haddr_t ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5FD_aggr_alloc)
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size);
-#endif /* H5FD_ALLOC_DEBUG */
+ FUNC_ENTER_NOAPI_NOINIT(H5FD_extend)
/* check args */
HDassert(file);
- HDassert(aggr);
- HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA);
- HDassert(other_aggr);
- HDassert(other_aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || other_aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA);
- HDassert(other_aggr->feature_flag != aggr->feature_flag);
+ HDassert(file->cls);
HDassert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES);
HDassert(size > 0);
- /*
- * If the aggregation feature is enabled for this VFL
- * driver, allocate "generic" space and sub-allocate out of
- * that, if possible. Otherwise just allocate through
- * H5FD_real_alloc()
- */
- if(file->feature_flags & aggr->feature_flag) {
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: aggr = {%a, %Hu, %Hu}\n", FUNC, aggr->addr, aggr->tot_size, aggr->size);
-#endif /* H5FD_ALLOC_DEBUG */
- /* Check if the space requested is larger than the space left in the block */
- if(size > aggr->size) {
- haddr_t new_space; /* Address for newly allocated space */
-
- /* Check if the block asked for is too large for 'normal' aggregator block */
- if(size >= aggr->alloc_size) {
- /* Allocate more room for this new block the regular way */
- if(HADDR_UNDEF == (new_space = H5FD_real_alloc(file, type, dxpl_id, size)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate aggregation block")
-
- /* Check if the new space is at the end of the current block */
- if((aggr->addr + aggr->size) == new_space) {
- /*
- * Treat the allocation request as if the current block
- * grew by the amount allocated and just update the address.
- *
- * Don't bother updating the block's size since it will
- * just grow and shrink by the same amount.
- *
- * _Do_ add to the total size aggregated.
- *
- */
- ret_value = aggr->addr;
- aggr->addr += size;
- aggr->tot_size += size;
- } /* end if */
- else {
- /* Check if the new space is at the end of the _other_ block */
- if(other_aggr->size > 0 && (other_aggr->addr + other_aggr->size) == new_space) {
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: New block is at end of 'other' block: other_aggr = {%a, %Hu, %Hu}\n", FUNC, other_aggr->addr, other_aggr->tot_size, other_aggr->size);
-#endif /* H5FD_ALLOC_DEBUG */
- /* If the other block has used at least the
- * 'allocation' amount for that block, shift the
- * newly allocated space down over the remainder
- * in the 'other block', shift the 'other block'
- * up by the same amount and free it. (Which
- * should amount to "bubbling" the remainder in
- * the 'other block' to the end of the file and
- * then "popping" the bubble by shrinking the
- * file)
- */
- if((other_aggr->tot_size - other_aggr->size) >= other_aggr->alloc_size) {
- H5FD_mem_t alloc_type = (other_aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA ? H5FD_MEM_DEFAULT : H5FD_MEM_DRAW); /* Type of file memory to work with */
- haddr_t free_addr = (new_space + size) - other_aggr->size; /* Address of free space in 'other block' shifted toward end of the file */
- hsize_t free_size = other_aggr->size; /* Size of the free space in 'other block' */
-
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: Freeing 'other' block\n", FUNC);
-#endif /* H5FD_ALLOC_DEBUG */
- /* Reset 'other' block's info */
- other_aggr->addr = 0;
- other_aggr->tot_size = 0;
- other_aggr->size = 0;
-
- /* Shift newly allocated space down */
- new_space -= free_size;
-
- /* Return the unused portion of the 'other' block to a free list */
- if(H5FD_free(file, alloc_type, dxpl_id, free_addr, free_size) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation block")
- } /* end if */
- } /* end if */
-
- /* Use the new space allocated, leaving the old block */
- ret_value = new_space;
- } /* end else */
- } /* end if */
- else {
- H5FD_mem_t alloc_type = (aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA ? H5FD_MEM_DEFAULT : H5FD_MEM_DRAW); /* Type of file memory to work with */
-
- /* Allocate another block */
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: Allocating block\n", FUNC);
-#endif /* H5FD_ALLOC_DEBUG */
- if(HADDR_UNDEF == (new_space = H5FD_real_alloc(file, alloc_type, dxpl_id, aggr->alloc_size)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate aggregation block")
-
- /* Check if the new space is at the end of the current block */
- if(aggr->addr + aggr->size == new_space) {
- aggr->size += aggr->alloc_size;
- aggr->tot_size += aggr->alloc_size;
- } /* end if */
- else {
- hsize_t new_size; /* Size of new aggregator block */
-
- /* Return the unused portion of the block to a free list */
- if(aggr->size > 0)
- if(H5FD_free(file, alloc_type, dxpl_id, aggr->addr, aggr->size) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation block")
-
- /* Check if the new space is at the end of the _other_ block */
- if(other_aggr->size > 0 && (other_aggr->addr + other_aggr->size) == new_space) {
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: New block is at end of 'other' block: other_aggr = {%a, %Hu, %Hu}\n", FUNC, other_aggr->addr, other_aggr->tot_size, other_aggr->size);
-#endif /* H5FD_ALLOC_DEBUG */
-#ifdef QAK
- /* If the other block has used at least the
- * 'allocation' amount for that block, give the
- * remaining free space in the 'other' block to
- * the new space allocated for 'this' block.
- */
- if((other_aggr->tot_size - other_aggr->size) >= other_aggr->alloc_size) {
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: Absorbing 'other' block\n", FUNC);
-#endif /* H5FD_ALLOC_DEBUG */
- /* Absorb the remaining free space into newly allocated block */
- new_space -= other_aggr->size;
- new_size = aggr->alloc_size + other_aggr->size;
-
- /* Reset the info for the 'other' block */
- other_aggr->addr = 0;
- other_aggr->tot_size = 0;
- other_aggr->size = 0;
- } /* end if */
- else
- new_size = aggr->alloc_size;
-#else /* QAK */
- /* If the other block has used at least the
- * 'allocation' amount for that block, shift the
- * newly allocated space down over the remainder
- * in the 'other block', shift the 'other block'
- * up by the same amount and free it. (Which
- * should amount to "bubbling" the remainder in
- * the 'other block' to the end of the file and
- * then "popping" the bubble by shrinking the
- * file)
- */
- if((other_aggr->tot_size - other_aggr->size) >= other_aggr->alloc_size) {
- H5FD_mem_t other_type = (other_aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA ? H5FD_MEM_DEFAULT : H5FD_MEM_DRAW); /* Type of file memory to work with */
- haddr_t free_addr = (new_space + aggr->alloc_size) - other_aggr->size; /* Address of free space in 'other block' shifted toward end of the file */
- hsize_t free_size = other_aggr->size; /* Size of the free space in 'other block' */
-
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: Freeing 'other' block\n", FUNC);
-#endif /* H5FD_ALLOC_DEBUG */
- /* Reset 'other' block's info */
- other_aggr->addr = 0;
- other_aggr->tot_size = 0;
- other_aggr->size = 0;
-
- /* Shift newly allocated space down */
- new_space -= free_size;
-
- /* Return the unused portion of the 'other' block to a free list */
- if(H5FD_free(file, other_type, dxpl_id, free_addr, free_size) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation block")
- } /* end if */
- new_size = aggr->alloc_size;
-#endif /* QAK */
- } /* end if */
- else
- new_size = aggr->alloc_size;
-
- /* Point the aggregator at the newly allocated block */
- aggr->addr = new_space;
- aggr->size = new_size;
- aggr->tot_size = new_size;
- } /* end else */
-
- /* Allocate space out of the metadata block */
- ret_value = aggr->addr;
- aggr->size -= size;
- aggr->addr += size;
- } /* end else */
- } /* end if */
- else {
- /* Allocate space out of the block */
- ret_value = aggr->addr;
- aggr->size -= size;
- aggr->addr += size;
- }
- } /* end if */
- else {
- /* Allocate data the regular way */
- if(HADDR_UNDEF == (ret_value = H5FD_real_alloc(file, type, dxpl_id, size)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate file space")
- } /* end else */
-
-done:
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value);
-#endif /* H5FD_ALLOC_DEBUG */
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_aggr_alloc() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_aggr_adjoin
- *
- * Purpose: Check if a newly freed block of space in the file adjoins an
- * aggregator block
- *
- * Return: Success: Non-negative
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * Thursday, December 13, 2007
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5FD_aggr_adjoin(const H5FD_t *file, H5FD_blk_aggr_t *aggr, H5FD_free_t *last)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_aggr_adjoin)
-
- /* Check args */
- HDassert(file);
- HDassert(file->cls);
- HDassert(aggr);
- HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA);
- HDassert(last);
-
- /* Check if this free block adjoins the aggregator */
- if((file->feature_flags & aggr->feature_flag) && aggr->size > 0) {
- hbool_t adjoins = FALSE; /* Whether the block adjoined the aggregator */
-
- /* Does the newly freed space adjoin the end of the aggregator */
- if((aggr->addr + aggr->size) == last->addr) {
- last->addr = aggr->addr;
- adjoins = TRUE;
- } /* end if */
- /* Does the newly freed space adjoin the beginning of the aggregator */
- else if((last->addr + last->size) == aggr->addr)
- adjoins = TRUE;
+ /* Get current end-of-allocated space address */
+ eoa = file->cls->get_eoa(file, type);
- /* Reset aggregator information, if adjoined */
- if(adjoins) {
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: Adjoined flag = %lx aggregator\n", "H5FD_aggr_adjoin", aggr->feature_flag);
-#endif /* H5FD_ALLOC_DEBUG */
- last->size += aggr->size;
- aggr->addr = 0;
- aggr->size = 0;
- } /* end if */
+ /* Compute extra space to allocate, if this is a new block and should be aligned */
+ extra = 0;
+ if(new_block && file->alignment > 1 && size >= file->threshold) {
+ hsize_t mis_align; /* Amount EOA is misaligned */
+
+ /* Check for EOA already aligned */
+ if((mis_align = (eoa % file->alignment)) > 0) {
+ extra = file->alignment - mis_align;
+ if (frag_addr) *frag_addr = eoa;
+ if (frag_size) *frag_size = extra;
+ }
} /* end if */
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5FD_aggr_adjoin() */
+ /* Add in extra allocation amount */
+ size += extra;
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_aggr_can_extend
- *
- * Purpose: Check is an aggregator block can be extended
- *
- * Return: Success: Non-negative
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * Thursday, December 13, 2007
- *
- *-------------------------------------------------------------------------
- */
-static htri_t
-H5FD_aggr_can_extend(const H5FD_t *file, const H5FD_blk_aggr_t *aggr, haddr_t eoa,
- haddr_t end)
-{
- htri_t ret_value = FALSE;
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_aggr_can_extend)
+ /* Check for overflow when extending */
+ if(H5F_addr_overflow(eoa, size) || (eoa + size) > file->maxaddr)
+ HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed")
- /* Check args */
- HDassert(file);
- HDassert(aggr);
- HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA);
+ /* Set the [possibly aligned] address to return */
+ ret_value = eoa + extra;
- /* Check if this aggregator is active */
- if(file->feature_flags & aggr->feature_flag) {
- /* If the aggregator block is at the end of the file, and the block to
- * test adjoins the beginning of the aggregator block, then it's
- * extendable
- */
- if((aggr->addr + aggr->size) == eoa && end == aggr->addr)
- HGOTO_DONE(TRUE)
- } /* end if */
+ /* Extend the end-of-allocated space address */
+ eoa += size;
+ if(file->cls->set_eoa(file, type, eoa) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_aggr_can_extend() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_aggr_extend
- *
- * Purpose: Shift an aggregator block in the file
- *
- * Return: Success: Non-negative
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * Thursday, December 13, 2007
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5FD_aggr_shift(H5FD_blk_aggr_t *aggr, hsize_t extra)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_aggr_shift)
-
- /* Check args */
- HDassert(aggr);
- HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA);
-
- /* Shift the aggregator block by the extra amount */
- aggr->addr += extra;
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5FD_aggr_shift() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_aggr_query
- *
- * Purpose: Query a block aggregator's current address & size info
- *
- * Return: Success: Non-negative
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * Thursday, December 13, 2007
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5FD_aggr_query(const H5FD_t *file, const H5FD_blk_aggr_t *aggr, haddr_t *addr,
- hsize_t *size)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_aggr_query)
-
- /* Check args */
- HDassert(file);
- HDassert(aggr);
- HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA);
-
- /* Check if this aggregator is active */
- if(file->feature_flags & aggr->feature_flag) {
- *addr = aggr->addr;
- *size = aggr->size;
- } /* end if */
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5FD_aggr_query() */
+} /* end H5FD_extend() */
/*-------------------------------------------------------------------------
- * Function: H5FD_aggr_reset
- *
- * Purpose: Reset a block aggregator, returning any space back to file
- *
- * Return: Success: Non-negative
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * Thursday, December 13, 2007
+ * Function: H5FD_alloc
*
- *-------------------------------------------------------------------------
- */
-herr_t
-H5FD_aggr_reset(H5FD_t *file, H5FD_blk_aggr_t *aggr, hid_t dxpl_id)
-{
- H5FD_mem_t alloc_type; /* Type of file memory to work with */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5FD_aggr_reset, FAIL)
-
- /* Check args */
- HDassert(file);
- HDassert(aggr);
- HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA);
-
- /* Set the type of memory in the file */
- alloc_type = (aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA ? H5FD_MEM_DEFAULT : H5FD_MEM_DRAW); /* Type of file memory to work with */
-
- /* Check if this aggregator is active */
- if(file->feature_flags & aggr->feature_flag) {
- /* Return the unused portion of the metadata block to a free list */
- if(aggr->size > 0)
- if(H5FD_free(file, alloc_type, dxpl_id, aggr->addr, aggr->size) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "can't free aggregator block")
-
- /* Reset aggregator block information */
- aggr->tot_size = 0;
- aggr->addr = 0;
- aggr->size = 0;
- } /* end if */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_aggr_reset() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_real_alloc
+ * Purpose: Private version of H5FDalloc().
*
- * Purpose: Double private version of H5FDalloc() :-)
+ * Return: Success: The format address of the new file memory.
+ * Failure: The undefined address HADDR_UNDEF
*
- * Return: Success: The format address of the new file memory.
- * Failure: The undefined address HADDR_UNDEF
+ * Programmer: Robb Matzke
+ * Wednesday, August 4, 1999
*
- * Programmer: Quincey Koziol
- * Friday, August 25, 2000
+ * Modification:
+ * Vailin Choi, 29th July 2008
+ * Add two more parameters () for handling alignment: address & size of the fragment
*
*-------------------------------------------------------------------------
*/
-static haddr_t
-H5FD_real_alloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size)
+haddr_t
+H5FD_alloc(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, hsize_t size, haddr_t *frag_addr, hsize_t *frag_size)
{
- haddr_t ret_value = HADDR_UNDEF;
+ haddr_t ret_value = HADDR_UNDEF;
- FUNC_ENTER_NOAPI_NOINIT(H5FD_real_alloc)
+ FUNC_ENTER_NOAPI(H5FD_alloc, HADDR_UNDEF)
#ifdef H5FD_ALLOC_DEBUG
HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size);
#endif /* H5FD_ALLOC_DEBUG */
/* check args */
- assert(file);
- assert(file->cls);
- assert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES);
- assert(size > 0);
+ HDassert(file);
+ HDassert(file->cls);
+ HDassert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES);
+ HDassert(size > 0);
- /*
- * Dispatch to driver `alloc' callback or extend the end-of-address
- * marker
- */
+ /* Dispatch to driver `alloc' callback or extend the end-of-address marker */
if(file->cls->alloc) {
if((ret_value = (file->cls->alloc)(file, type, dxpl_id, size)) == HADDR_UNDEF)
HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "driver allocation request failed")
- } else {
- if((ret_value = H5FD_update_eoa(file, type, dxpl_id, size)) == HADDR_UNDEF)
+ } /* end if */
+ else {
+ if((ret_value = H5FD_extend(file, type, TRUE, size, frag_addr, frag_size)) == HADDR_UNDEF)
HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "driver eoa update request failed")
- }
+ } /* end else */
+
+ /* Convert absolute file offset to relative address */
+ ret_value -= file->base_addr;
done:
#ifdef H5FD_ALLOC_DEBUG
HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value);
#endif /* H5FD_ALLOC_DEBUG */
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_real_alloc() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_update_eoa
- *
- * Purpose: Update the EOA field of the file's memory.
- *
- * This was split off from the H5FD_real_alloc function to
- * make life easier for all.
- *
- * Return: Success: The format address of the new file memory.
- * Failure: The undefined address HADDR_UNDEF
- *
- * Programmer: Bill Wendling
- * Wednesday, 04. December, 2002
- *
- *-------------------------------------------------------------------------
- */
-static haddr_t
-H5FD_update_eoa(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size)
-{
- haddr_t eoa, oldeoa = 0;
- hsize_t wasted;
- haddr_t ret_value = HADDR_UNDEF;
-
- FUNC_ENTER_NOAPI_NOINIT(H5FD_update_eoa)
-
- /* check args */
- assert(file);
- assert(file->cls);
- assert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES);
- assert(size > 0);
-
- eoa = file->cls->get_eoa(file, type);
-
-#ifdef H5F_DEBUG
- if(file->alignment * file->threshold != 1 && H5DEBUG(F))
- HDfprintf(H5DEBUG(F),
- "%s: alignment=%Hd, threshold=%Hd, size=%Hd, Begin eoa=%a\n",
- FUNC, file->alignment, file->threshold, size, eoa);
-#endif /* H5F_DEBUG */
-
- /* Wasted is 0 if not exceeding threshold or eoa happens to be aligned */
- wasted = (size >= file->threshold) ? (eoa % file->alignment) : 0;
- if(wasted) {
- wasted = file->alignment - wasted; /* actual waste */
- oldeoa = eoa; /* save it for later freeing */
-
- /* Advance eoa to the next alignment by allocating the wasted */
- if(H5F_addr_overflow(eoa, size) || (eoa + wasted) > file->maxaddr)
- HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed")
-
- eoa += wasted;
-
- if(file->cls->set_eoa(file, type, eoa) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed")
- } /* end if */
-
- /* allocate the aligned memory */
- if(H5F_addr_overflow(eoa, size) || eoa + size > file->maxaddr)
- HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed")
-
- ret_value = eoa;
- eoa += size;
-
- if(file->cls->set_eoa(file, type, eoa) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed")
-
- /* Free the wasted memory */
- if(wasted) {
- if(H5FD_free(file, type, dxpl_id, oldeoa, wasted) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "file deallocation request failed")
- } /* end if */
-
-#ifdef H5F_DEBUG
- if(file->alignment * file->threshold != 1 && H5DEBUG(F))
- HDfprintf(H5DEBUG(F),
- "%s: ret_value=%a, wasted=%Hd, Ended eoa=%a\n",
- FUNC, ret_value, wasted, eoa);
-#endif /* H5F_DEBUG */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_update_eoa() */
+} /* end H5FD_alloc() */
/*-------------------------------------------------------------------------
@@ -1101,9 +247,8 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5FD_free(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t size)
+H5FD_free(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr, hsize_t size)
{
- H5FD_mem_t mapped_type;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5FD_free, FAIL)
@@ -1112,235 +257,50 @@ H5FD_free(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t si
HDassert(file);
HDassert(file->cls);
HDassert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES);
+ HDassert(size > 0);
#ifdef H5FD_ALLOC_DEBUG
HDfprintf(stderr, "%s: type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)type, addr, size);
#endif /* H5FD_ALLOC_DEBUG */
- if(!H5F_addr_defined(addr) || addr > file->maxaddr ||
- H5F_addr_overflow(addr, size) || (addr + size) > file->maxaddr)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid region")
-
- /* Allow 0-sized free's to occur without penalty */
- if(0 == size)
- HGOTO_DONE(SUCCEED)
-
- /* Map request type to free list */
- if(H5FD_MEM_DEFAULT==file->cls->fl_map[type])
- mapped_type = type;
- else
- mapped_type = file->cls->fl_map[type];
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: mapped_type = %u\n", FUNC, (unsigned)mapped_type);
-#endif /* H5FD_ALLOC_DEBUG */
-
- /*
- * If the request maps to a free list then add memory to the free list
- * without ever telling the driver that it was freed. Otherwise let the
- * driver deallocate the memory.
- */
- if(mapped_type >= H5FD_MEM_DEFAULT) {
- H5FD_free_t *last; /* Last merged node */
- H5FD_free_t *last_prev = NULL;/* Pointer to node before merged node */
- H5FD_free_t *curr; /* Current free block being inspected */
- H5FD_free_t *prev; /* Previous free block being inspected */
-
- /* Adjust the metadata accumulator to remove the freed block, if it overlaps */
- if((file->feature_flags&H5FD_FEAT_ACCUMULATE_METADATA)
- && H5F_addr_overlap(addr, size, file->accum_loc, file->accum_size)) {
- size_t overlap_size; /* Size of overlap with accumulator */
-
- /* Check for overlapping the beginning of the accumulator */
- if(H5F_addr_le(addr, file->accum_loc)) {
- /* Check for completely overlapping the accumulator */
- if(H5F_addr_ge(addr + size, file->accum_loc + file->accum_size)) {
- /* Reset the entire accumulator */
- file->accum_loc=HADDR_UNDEF;
- file->accum_size=FALSE;
- file->accum_dirty=FALSE;
- } /* end if */
- /* Block to free must end within the accumulator */
- else {
- size_t new_accum_size; /* Size of new accumulator buffer */
-
- /* Calculate the size of the overlap with the accumulator, etc. */
- H5_ASSIGN_OVERFLOW(overlap_size,(addr+size)-file->accum_loc,haddr_t,size_t);
- new_accum_size=file->accum_size-overlap_size;
-
- /* Move the accumulator buffer information to eliminate the freed block */
- HDmemmove(file->meta_accum,file->meta_accum+overlap_size,new_accum_size);
-
- /* Adjust the accumulator information */
- file->accum_loc+=overlap_size;
- file->accum_size=new_accum_size;
- } /* end else */
- } /* end if */
- /* Block to free must start within the accumulator */
- else {
- /* Calculate the size of the overlap with the accumulator */
- H5_ASSIGN_OVERFLOW(overlap_size,(file->accum_loc+file->accum_size)-addr,haddr_t,size_t);
-
- /* Block to free is in the middle of the accumulator */
- if(H5F_addr_lt((addr + size), file->accum_loc + file->accum_size)) {
- haddr_t tail_addr;
- size_t tail_size;
-
- /* Calculate the address & size of the tail to write */
- tail_addr=addr+size;
- H5_ASSIGN_OVERFLOW(tail_size,(file->accum_loc+file->accum_size)-tail_addr,haddr_t,size_t);
-
- /* Write out the part of the accumulator after the block to free */
- /* (Use the driver's write call directly - to avoid looping back and writing to metadata accumulator) */
- if((file->cls->write)(file, H5FD_MEM_DEFAULT, dxpl_id, tail_addr, tail_size, file->meta_accum+(tail_addr-file->accum_loc)) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "file write request failed")
- } /* end if */
-
- /* Adjust the accumulator information */
- file->accum_size=file->accum_size-overlap_size;
- } /* end else */
- } /* end if */
-
- /* Scan through the existing blocks for the mapped type to see if we can extend one */
- curr = file->fl[mapped_type];
- last = prev = NULL;
- while(curr != NULL) {
- /* Check if the block to free adjoins the start of the current block */
- if((addr + size) == curr->addr) {
- /* If we previously found & merged a node, eliminate it from the list & free it */
- if(last != NULL) {
- /* Check if there was a previous block in the list */
- if(last_prev != NULL)
- /* Eliminate the merged block from the list */
- last_prev->next = last->next;
- /* No previous block, this must be the head of the list */
- else
- /* Eliminate the merged block from the list */
- file->fl[mapped_type] = last->next;
-
- /* Check for eliminating the block before the 'current' one */
- if(last == prev)
- prev = last_prev;
-
- /* Free the memory for the merged block */
- (void)H5FL_FREE(H5FD_free_t, last);
- } /* end if */
-
- /* Adjust the address and size of the block found */
- curr->addr = addr;
- curr->size += size;
-
- /* Adjust the information about to memory block to include the merged block */
- addr = curr->addr;
- size = curr->size;
+ /* Sanity checking */
+ if(!H5F_addr_defined(addr))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file offset")
- /* Update the information about the merged node */
- last = curr;
- last_prev = prev;
- } /* end if */
- else {
- /* Check if the block to free adjoins the end of the current block */
- if((curr->addr + curr->size) == addr) {
- /* If we previously found & merged a node, eliminate it from the list & free it */
- if(last != NULL) {
- /* Check if there was a previous block in the list */
- if(last_prev != NULL)
- /* Eliminate the merged block from the list */
- last_prev->next = last->next;
- /* No previous block, this must be the head of the list */
- else
- /* Eliminate the merged block from the list */
- file->fl[mapped_type] = last->next;
+ /* Convert address to absolute file offset */
+ addr += file->base_addr;
- /* Check for eliminating the block before the 'current' one */
- if(last == prev)
- prev = last_prev;
+ /* More sanity checking */
+ if(addr > file->maxaddr || H5F_addr_overflow(addr, size) || (addr + size) > file->maxaddr)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file free space region to free")
- /* Free the memory for the merged block */
- (void)H5FL_FREE(H5FD_free_t, last);
- } /* end if */
-
- /* Adjust the size of the block found */
- curr->size += size;
-
- /* Adjust the information about to memory block to include the merged block */
- addr = curr->addr;
- size = curr->size;
-
- /* Update the information about the merged node */
- last = curr;
- last_prev = prev;
- } /* end if */
- } /* end else */
-
- /* Advance to next node in list */
- prev = curr;
- curr = curr->next;
- } /* end while */
-
- /* Check if we adjusted an existing block */
- if(last != NULL) {
- /* Move the node found to the front, if it wasn't already there */
- if(last_prev != NULL) {
- last_prev->next = last->next;
- last->next = file->fl[mapped_type];
- file->fl[mapped_type] = last;
- } /* end if */
- } /* end if */
- else {
- /* Allocate a new node to hold the free block's information */
- if(NULL == (last = H5FL_MALLOC(H5FD_free_t)))
- HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate node for free space info")
-
- last->addr = addr;
- last->size = size;
- last->next = file->fl[mapped_type];
- file->fl[mapped_type] = last;
- } /* end else */
+ /* Check for file driver 'free' callback and call it if available */
+ if(file->cls->free) {
#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: mapped_type = %u, last = {%a, %Hu}\n", FUNC, (unsigned)mapped_type, last->addr, last->size);
+HDfprintf(stderr, "%s: Letting VFD free space\n", FUNC);
#endif /* H5FD_ALLOC_DEBUG */
+ if((file->cls->free)(file, type, dxpl_id, addr, size) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "driver free request failed")
+ } /* end if */
+ /* Check if this free block is at the end of file allocated space.
+ * Truncate it if this is true.
+ */
+ else if(file->cls->get_eoa) {
+ haddr_t eoa;
- /* Check if we increased the size of the largest block on the list */
- file->maxsize = MAX(file->maxsize, last->size);
-
- /* Check if this free block adjoins the "metadata aggregator" */
- if(H5FD_aggr_adjoin(file, &(file->meta_aggr), last) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "aggregator deallocation request failed")
-
- /* Check if this free block adjoins the "small data aggregator" */
- if(H5FD_aggr_adjoin(file, &(file->sdata_aggr), last) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "aggregator deallocation request failed")
-
- /* Check if this free block is at the end of file allocated space.
- * Truncate it if this is true. */
- if(file->cls->get_eoa) {
- haddr_t eoa;
-
- eoa = file->cls->get_eoa(file, type);
+ eoa = file->cls->get_eoa(file, type);
#ifdef H5FD_ALLOC_DEBUG
HDfprintf(stderr, "%s: eoa = %a\n", FUNC, eoa);
#endif /* H5FD_ALLOC_DEBUG */
- if(eoa == (last->addr + last->size)) {
+ if(eoa == (addr + size)) {
#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: Reducing file size to = %a\n", FUNC, last->addr);
+HDfprintf(stderr, "%s: Reducing file size to = %a\n", FUNC, addr);
#endif /* H5FD_ALLOC_DEBUG */
- if(file->cls->set_eoa(file, type, last->addr) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "set end of space allocation request failed")
-
- /* Remove this free block from the list */
- file->fl[mapped_type] = last->next;
- if(file->maxsize == last->size)
- file->maxsize = 0; /*unknown*/
- (void)H5FL_FREE(H5FD_free_t, last);
- } /* end if */
+ if(file->cls->set_eoa(file, type, addr) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "set end of space allocation request failed")
} /* end if */
- } else if(file->cls->free) {
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: Letting VFD free space\n", FUNC);
-#endif /* H5FD_ALLOC_DEBUG */
- if((file->cls->free)(file, type, dxpl_id, addr, size) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver free request failed")
- } else {
+ } /* end else-if */
+ else {
/* leak memory */
#ifdef H5FD_ALLOC_DEBUG
HDfprintf(stderr, "%s: LEAKED MEMORY!!! type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)type, addr, size);
@@ -1353,386 +313,55 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5FD_realloc
- *
- * Purpose: Private version of H5FDrealloc()
- *
- * Return: Success: New address of the block of memory, not
- * necessarily the same as the original address.
- * Failure: HADDR_UNDEF
- *
- * Programmer: Robb Matzke
- * Wednesday, August 4, 1999
- *
- *-------------------------------------------------------------------------
- */
-haddr_t
-H5FD_realloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t old_addr, hsize_t old_size,
- hsize_t new_size)
-{
- haddr_t new_addr=old_addr;
- uint8_t _buf[8192];
- uint8_t *buf=_buf;
- haddr_t ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI(H5FD_realloc, HADDR_UNDEF)
-
- if(new_size == old_size) {
- /*nothing to do*/
- } else if(0 == old_size) {
- /* allocate memory */
- HDassert(!H5F_addr_defined(old_addr));
- if(HADDR_UNDEF == (new_addr = H5FD_alloc(file, type, dxpl_id, new_size)))
- HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, HADDR_UNDEF, "file allocation failed")
- } else if(0==new_size) {
- /* free memory */
- HDassert(H5F_addr_defined(old_addr));
- if(H5FD_free(file, type, dxpl_id, old_addr, old_size) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "file deallocation request failed")
- new_addr = HADDR_UNDEF;
- } else if(new_size<old_size) {
- /* free the end of the block */
- if(H5FD_free(file, type, dxpl_id, old_addr+old_size, old_size-new_size) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "file deallocation request failed")
- } else {
- /* move memory to new location */
- /* Note! This may fail if sizeof(hsize_t)>sizeof(size_t) and the
- * object on disk is too large to read into a memory buffer all at one
- * time. This chunk of code would have to be re-written using a loop
- * to move pieces of the realloced data through a fixed size buffer, etc.
- * -QAK, 6/20/01
- */
- if(HADDR_UNDEF == (new_addr = H5FD_alloc(file, type, dxpl_id, new_size)))
- HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, HADDR_UNDEF, "file allocation failed")
- H5_CHECK_OVERFLOW(old_size,hsize_t,size_t);
- if(old_size > sizeof(_buf) && NULL == (buf = (uint8_t *)H5MM_malloc((size_t)old_size))) {
- (void)H5FD_free(file, type, dxpl_id, new_addr, new_size);
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, "memory allocation failed")
- } /* end if */
- if(H5FD_read(file, type, dxpl_id, old_addr, (size_t)old_size, buf) < 0 ||
- H5FD_write(file, type, dxpl_id, new_addr, (size_t)old_size, buf) < 0) {
- (void)H5FD_free(file, type, dxpl_id, new_addr, new_size);
- if(buf != _buf)
- H5MM_xfree(buf);
- HGOTO_ERROR(H5E_FILE, H5E_READERROR, HADDR_UNDEF, "unable to move file block")
- } /* end if */
-
- if(buf != _buf)
- H5MM_xfree(buf);
- if(H5FD_free(file, type, dxpl_id, old_addr, old_size) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "file deallocation request failed")
- } /* end else */
-
- /* Set return value */
- ret_value = new_addr;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_realloc() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_can_extend
+ * Function: H5FD_try_extend
*
- * Purpose: Check if a block in the file can be extended.
+ * Purpose: Extend a block at the end of the file, if possible.
*
- * Return: Success: TRUE(1)/FALSE(0)
+ * Return: Success: TRUE(1) - Block was extended
+ * FALSE(0) - Block could not be extended
* Failure: FAIL
*
- * Programmer: Quincey Koziol
- * Friday, June 11, 2004
- *
- *-------------------------------------------------------------------------
- */
-htri_t
-H5FD_can_extend(const H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size, hsize_t extra_requested)
-{
- haddr_t end; /* End of block in file */
- haddr_t eoa; /* End of address space in the file */
- htri_t ret_value = FALSE; /* Return value */
-
- FUNC_ENTER_NOAPI(H5FD_can_extend, FAIL)
-
- /* Retrieve the end of the address space */
- if(HADDR_UNDEF == (eoa = H5FD_get_eoa(file, type)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver get_eoa request failed")
-
- /* Compute end of block */
- end = addr + size;
-
- /* Check if the block is exactly at the end of the file */
- if(end == eoa)
- HGOTO_DONE(TRUE)
- else {
- H5FD_free_t *curr; /* Current free block being inspected */
- H5FD_mem_t mapped_type; /* Memory type, after mapping */
-
- /* Map request type to free list */
- if(H5FD_MEM_DEFAULT==file->cls->fl_map[type])
- mapped_type = type;
- else
- mapped_type = file->cls->fl_map[type];
-
- /* Check if block is inside the metadata or small data aggregator */
- if(mapped_type!=H5FD_MEM_DRAW) {
- /* Check for test block able to extend metadata aggregation block */
- if((ret_value = H5FD_aggr_can_extend(file, &(file->meta_aggr), eoa, end)) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "can't determine if metadata aggregation block can be extended")
- else if(ret_value > 0)
- HGOTO_DONE(TRUE)
- } /* end if */
- else {
- /* Check for test block able to extend metadata aggregation block */
- if((ret_value = H5FD_aggr_can_extend(file, &(file->sdata_aggr), eoa, end)) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "can't determine if 'small data' aggregation block can be extended")
- else if(ret_value > 0)
- HGOTO_DONE(TRUE)
- } /* end else */
-
- /* Scan through the existing blocks for the mapped type to see if we can extend one */
- if(mapped_type >= H5FD_MEM_DEFAULT) {
- curr = file->fl[mapped_type];
- while(curr != NULL) {
- if(end == curr->addr) {
- if(extra_requested <= curr->size)
- HGOTO_DONE(TRUE)
- else
- HGOTO_DONE(FALSE)
- } /* end if */
-
- /* Advance to next node in list */
- curr=curr->next;
- } /* end while */
- } /* end if */
- } /* end else */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_can_extend() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_extend
- *
- * Purpose: Extend a block in the file.
- *
- * Return: Success: Non-negative
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * Saturday, June 12, 2004
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5FD_extend(H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size, hsize_t extra_requested)
-{
- haddr_t eoa; /* End of address space in the file */
- haddr_t end; /* End of block in file */
- hbool_t update_eoma=FALSE; /* Whether we need to update the eoma */
- hbool_t update_eosda=FALSE; /* Whether we need to update the eosda */
- hbool_t at_end=FALSE; /* Block is at end of file */
- H5FD_mem_t mapped_type; /* Memory type, after mapping */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5FD_extend, FAIL)
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: type = %u, addr = %a, size = %Hu, extra_requested = %Hu\n", FUNC, (unsigned)type, addr, size, extra_requested);
-#endif /* H5FD_ALLOC_DEBUG */
-
- /* Retrieve the end of the address space */
- if(HADDR_UNDEF==(eoa=H5FD_get_eoa(file, type)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver get_eoa request failed")
-
- /* Map request type to free list */
- if(H5FD_MEM_DEFAULT==file->cls->fl_map[type])
- mapped_type = type;
- else
- mapped_type = file->cls->fl_map[type];
-
- /* Compute end of block */
- end = addr + size;
-
- /* Check if the block is exactly at the end of the file */
- if(end == eoa)
- at_end = TRUE;
- else {
- /* (Check if block is inside the metadata or small data accumulator) */
- if(mapped_type!=H5FD_MEM_DRAW) {
- /* Check for test block able to extend metadata aggregation block */
- if((ret_value = H5FD_aggr_can_extend(file, &(file->meta_aggr), eoa, end)) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "can't determine if metadata aggregation block can be extended")
- else if(ret_value > 0)
- update_eoma = TRUE;
- } /* end if */
- else {
- /* Check for test block able to extend metadata aggregation block */
- if((ret_value = H5FD_aggr_can_extend(file, &(file->sdata_aggr), eoa, end)) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "can't determine if metadata aggregation block can be extended")
- else if(ret_value > 0)
- update_eosda = TRUE;
- } /* end else */
- } /* end else */
-
- /* Block is at end of file, we are extending the eoma or eosda */
- if(update_eoma || update_eosda || at_end) {
- /* Check for overflowing the file */
- if(H5F_addr_overflow(eoa, extra_requested) || eoa + extra_requested > file->maxaddr)
- HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, FAIL, "file allocation request failed")
-
- /* Extend the file */
- eoa += extra_requested;
- if(file->cls->set_eoa(file, type, eoa) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, FAIL, "file allocation request failed")
-
- /* Update the metadata and/or small data block */
- HDassert(!(update_eoma && update_eosda));
- if(update_eoma)
- H5FD_aggr_shift(&(file->meta_aggr), extra_requested);
- if(update_eosda)
- H5FD_aggr_shift(&(file->sdata_aggr), extra_requested);
- } /* end if */
- /* If the block we are extending isn't at the end of the file, find a free block to extend into */
- else {
- H5FD_free_t *curr; /* Current free block being inspected */
- H5FD_free_t *prev; /* Current free block being inspected */
-
- /* Walk through free list, looking for block to merge with */
- curr = file->fl[mapped_type];
- prev = NULL;
- while(curr!=NULL) {
- /* Found block that ajoins end of block to extend */
- if(end == curr->addr) {
- /* Check if free space is large enough */
- if(extra_requested <= curr->size) {
- /* Check for exact match */
- if(extra_requested == curr->size) {
- /* Unlink node from free list */
- if(prev == NULL)
- file->fl[mapped_type] = curr->next;
- else
- prev->next = curr->next;
-
- /* Free the memory for the used block */
- (void)H5FL_FREE(H5FD_free_t, curr);
- } /* end if */
- else {
- curr->addr += extra_requested;
- curr->size -= extra_requested;
- } /* end else */
-
- /* Leave now */
- break;
- } /* end if */
- else
- HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, FAIL, "can't extend block")
- } /* end if */
-
- /* Advance to next node in list */
- prev = curr;
- curr = curr->next;
- } /* end while */
-
- /* Couldn't find block to extend */
- if(curr == NULL)
- HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, FAIL, "can't extend block")
- } /* end else */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_extend() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_get_freespace
- *
- * Purpose: Retrieve the amount of free space in a file.
- *
- * Return: Success: Amount of free space in file
- * Failure: Negative
- *
* Programmer: Quincey Koziol
- * Monday, October 6, 2003
+ * Thursday, 17. January, 2008
*
- * Note:
- * Raymond Lu
- * 5 January 2007
- * Due to the complexity EOA for Multi driver, this function
- * is made failed for now.
+ * Modification:
+ * Vailin Choi, 29th July 2008
+ * Two more parameters were added to FD_extend() for handling alignment
*
*-------------------------------------------------------------------------
*/
-hssize_t
-H5FD_get_freespace(const H5FD_t *file)
+htri_t
+H5FD_try_extend(H5FD_t *file, H5FD_mem_t type, haddr_t blk_end, hsize_t extra_requested)
{
- H5FD_free_t *free_node; /* Pointer to node on free list */
- H5FD_mem_t type; /* Type of memory */
- haddr_t ma_addr = HADDR_UNDEF; /* Base "metadata aggregator" address */
- hsize_t ma_size = 0; /* Size of "metadata aggregator" */
- haddr_t sda_addr = HADDR_UNDEF; /* Base "small data aggregator" address */
- hsize_t sda_size = 0; /* Size of "small data aggregator" */
- haddr_t eoa = 0; /* End of allocated space in the file */
- hssize_t ret_value = 0; /* Return value */
+ haddr_t eoa; /* End of allocated space in file */
+ htri_t ret_value = FALSE; /* Return value */
- FUNC_ENTER_NOAPI(H5FD_get_freespace, FAIL)
+ FUNC_ENTER_NOAPI(H5FD_try_extend, FAIL)
/* check args */
HDassert(file);
HDassert(file->cls);
+ HDassert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES);
+ HDassert(extra_requested > 0);
- /* Multi driver doesn't support this function because of the complexity.
- * It doesn't have eoa for the whole file. */
- if(file->driver_id == H5FD_MULTI)
- HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "Multi driver doesn't support this function")
-
- /* Retrieve the 'eoa' for the file */
- eoa = file->cls->get_eoa(file, H5FD_MEM_DEFAULT);
-
- /* Retrieve metadata aggregator info, if available */
- H5FD_aggr_query(file, &(file->meta_aggr), &ma_addr, &ma_size);
-
- /* Retrieve 'small data' aggregator info, if available */
- H5FD_aggr_query(file, &(file->sdata_aggr), &sda_addr, &sda_size);
+ /* Retrieve the end of the address space */
+ if(HADDR_UNDEF == (eoa = file->cls->get_eoa(file, type)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed")
- /* Iterate over all the types of memory, to retrieve amount of free space for each */
- for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t,type)) {
- /* Iterate through the free list, accumulating the amount of free space for this type */
- free_node = file->fl[type];
- while(free_node) {
- /* Check for current node adjoining the metadata & small data aggregators */
- if(H5F_addr_eq(free_node->addr + free_node->size, ma_addr)) {
- ma_addr -= free_node->size;
- ma_size += free_node->size;
- } else if(H5F_addr_eq(free_node->addr + free_node->size, sda_addr)) {
- sda_addr -= free_node->size;
- sda_size += free_node->size;
- } else if(H5F_addr_eq(ma_addr + ma_size, free_node->addr))
- ma_size += free_node->size;
- else if(H5F_addr_eq(sda_addr + sda_size, free_node->addr))
- sda_size += free_node->size;
- else
- ret_value += (hssize_t)free_node->size;
- free_node = free_node->next;
- } /* end while */
- } /* end for */
+ /* Adjust block end by base address of the file, to create absolute address */
+ blk_end += file->base_addr;
- /* Check for aggregating metadata allocations */
- if(ma_size > 0) {
- /* Add in the reserved space for metadata to the available free space */
- /* (if it's not at the tail of the file) */
- if(H5F_addr_ne(ma_addr + ma_size, eoa))
- ret_value += ma_size;
- } /* end if */
+ /* Check if the block is exactly at the end of the file */
+ if(H5F_addr_eq(blk_end, eoa)) {
+ /* Extend the object by extending the underlying file */
+ if(HADDR_UNDEF == H5FD_extend(file, type, FALSE, extra_requested, NULL, NULL))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, "driver extend request failed")
- /* Check for aggregating small data allocations */
- if(sda_size > 0) {
- /* Add in the reserved space for metadata to the available free space */
- /* (if it's not at the tail of the file) */
- if(H5F_addr_ne(sda_addr + sda_size, eoa))
- ret_value += sda_size;
+ /* Indicate success */
+ HGOTO_DONE(TRUE)
} /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_get_freespace() */
+} /* end H5FD_try_extend() */
diff --git a/src/H5FDstdio.c b/src/H5FDstdio.c
index 46c8e81..59056c9 100644
--- a/src/H5FDstdio.c
+++ b/src/H5FDstdio.c
@@ -166,6 +166,7 @@ static herr_t H5FD_stdio_read(H5FD_t *lf, H5FD_mem_t type, hid_t fapl_id, haddr_
static herr_t H5FD_stdio_write(H5FD_t *lf, H5FD_mem_t type, hid_t fapl_id, haddr_t addr,
size_t size, const void *buf);
static herr_t H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
+static herr_t H5FD_stdio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
static const H5FD_class_t H5FD_stdio_g = {
"stdio", /*name */
@@ -194,6 +195,7 @@ static const H5FD_class_t H5FD_stdio_g = {
H5FD_stdio_read, /*read */
H5FD_stdio_write, /*write */
H5FD_stdio_flush, /*flush */
+ H5FD_stdio_truncate, /*truncate */
NULL, /*lock */
NULL, /*unlock */
H5FD_FLMAP_SINGLE /*fl_map */
@@ -943,19 +945,63 @@ H5FD_stdio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
* Programmer: Robb Matzke
* Wednesday, October 22, 1997
*
- * Modifications:
- * Ported to VFL/H5FD layer - QAK, 10/18/99
- *
*-------------------------------------------------------------------------
*/
static herr_t
H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing)
{
H5FD_stdio_t *file = (H5FD_stdio_t*)_file;
- static const char *func="H5FD_stdio_flush"; /* Function Name for error reporting */
+ static const char *func = "H5FD_stdio_flush"; /* Function Name for error reporting */
/* Shut compiler up */
- dxpl_id=dxpl_id;
+ dxpl_id = dxpl_id;
+
+ /* Clear the error stack */
+ H5Eclear2(H5E_DEFAULT);
+
+ /* Only try to flush the file if we have write access */
+ if(file->write_access) {
+ /* Flush */
+ if(!closing) {
+ if(fflush(file->fp) < 0)
+ H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_WRITEERROR, "fflush failed", -1)
+
+ /* Reset last file I/O information */
+ file->pos = HADDR_UNDEF;
+ file->op = H5FD_STDIO_OP_UNKNOWN;
+ } /* end if */
+ } /* end if */
+
+ return(0);
+} /* end H5FD_stdio_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_stdio_truncate
+ *
+ * Purpose: Makes sure that the true file size is the same (or larger)
+ * than the end-of-address.
+ *
+ * Errors:
+ * IO SEEKERROR fseek failed.
+ * IO WRITEERROR fflush or fwrite failed.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, January 31, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_stdio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing)
+{
+ H5FD_stdio_t *file = (H5FD_stdio_t*)_file;
+ static const char *func = "H5FD_stdio_truncate"; /* Function Name for error reporting */
+
+ /* Shut compiler up */
+ dxpl_id = dxpl_id;
+ closing = closing;
/* Clear the error stack */
H5Eclear2(H5E_DEFAULT);
@@ -963,9 +1009,10 @@ H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing)
/* Only try to flush the file if we have write access */
if(file->write_access) {
/* Makes sure that the true file size is the same as the end-of-address. */
- if (file->eoa!=file->eof) {
+ if(file->eoa != file->eof) {
+ int fd = fileno(file->fp); /* File descriptor for HDF5 file */
+
#ifdef _WIN32
- int fd=_fileno(file->fp); /* File descriptor for HDF5 file */
HFILE filehandle; /* Windows file handle */
LARGE_INTEGER li; /* 64-bit integer for SetFilePointer() call */
@@ -975,14 +1022,16 @@ H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing)
/* Translate 64-bit integers into form Windows wants */
/* [This algorithm is from the Windows documentation for SetFilePointer()] */
li.QuadPart = (LONGLONG)file->eoa;
- (void)SetFilePointer((HANDLE)filehandle,li.LowPart,&li.HighPart,FILE_BEGIN);
- if(SetEndOfFile((HANDLE)filehandle)==0)
- H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_SEEKERROR, "unable to extend file properly", -1)
+ (void)SetFilePointer((HANDLE)filehandle, li.LowPart, &li.HighPart, FILE_BEGIN);
+ if(SetEndOfFile((HANDLE)filehandle) == 0)
+ H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_SEEKERROR, "unable to truncate/extend file properly", -1)
#else /* _WIN32 */
- int fd=fileno(file->fp); /* File descriptor for HDF5 file */
+ /* Reset seek offset to beginning of file, so that file isn't re-extended later */
+ rewind(file->fp);
- if (-1==file_truncate(fd, (file_offset_t)file->eoa))
- H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_SEEKERROR, "unable to extend file properly", -1)
+ /* Truncate file to proper length */
+ if(-1 == file_truncate(fd, (file_offset_t)file->eoa))
+ H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_SEEKERROR, "unable to truncate/extend file properly", -1)
#endif /* _WIN32 */
/* Update the eof value */
@@ -992,23 +1041,15 @@ H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing)
file->pos = HADDR_UNDEF;
file->op = H5FD_STDIO_OP_UNKNOWN;
} /* end if */
-
- /*
- * Flush
- */
- if(!closing) {
- if (fflush(file->fp) < 0)
- H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_WRITEERROR, "fflush failed", -1)
- } /* end if */
} /* end if */
else {
/* Double-check for problems */
- if (file->eoa>file->eof)
+ if(file->eoa > file->eof)
H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_TRUNCATED, "eoa>eof!", -1)
} /* end else */
return(0);
-}
+} /* end H5FD_stdio_truncate() */
#ifdef _H5private_H
@@ -1019,3 +1060,4 @@ H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing)
*/
#error "Do not use HDF5 private definitions"
#endif
+
diff --git a/src/H5FDwindows.c b/src/H5FDwindows.c
index bbae92c..912c721 100644
--- a/src/H5FDwindows.c
+++ b/src/H5FDwindows.c
@@ -139,11 +139,12 @@ static herr_t H5FD_windows_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, h
static herr_t H5FD_windows_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr,
size_t size, const void *buf);
static herr_t H5FD_windows_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
+static herr_t H5FD_windows_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
static const H5FD_class_t H5FD_windows_g = {
- "windows", /*name */
- MAXADDR, /*maxaddr */
- H5F_CLOSE_WEAK, /* fc_degree */
+ "windows", /*name */
+ MAXADDR, /*maxaddr */
+ H5F_CLOSE_WEAK, /* fc_degree */
NULL, /*sb_size */
NULL, /*sb_encode */
NULL, /*sb_decode */
@@ -154,22 +155,23 @@ static const H5FD_class_t H5FD_windows_g = {
0, /*dxpl_size */
NULL, /*dxpl_copy */
NULL, /*dxpl_free */
- H5FD_windows_open, /*open */
- H5FD_windows_close, /*close */
- H5FD_windows_cmp, /*cmp */
- H5FD_windows_query, /*query */
+ H5FD_windows_open, /*open */
+ H5FD_windows_close, /*close */
+ H5FD_windows_cmp, /*cmp */
+ H5FD_windows_query, /*query */
NULL, /*alloc */
NULL, /*free */
- H5FD_windows_get_eoa, /*get_eoa */
- H5FD_windows_set_eoa, /*set_eoa */
- H5FD_windows_get_eof, /*get_eof */
- H5FD_windows_get_handle,/*get_handle */
- H5FD_windows_read, /*read */
- H5FD_windows_write, /*write */
- H5FD_windows_flush, /*flush */
- NULL, /*lock */
- NULL, /*unlock */
- H5FD_FLMAP_SINGLE /*fl_map */
+ H5FD_windows_get_eoa, /*get_eoa */
+ H5FD_windows_set_eoa, /*set_eoa */
+ H5FD_windows_get_eof, /*get_eof */
+ H5FD_windows_get_handle, /*get_handle */
+ H5FD_windows_read, /*read */
+ H5FD_windows_write, /*write */
+ H5FD_windows_flush, /*flush */
+ H5FD_windows_truncate, /*truncate */
+ NULL, /*lock */
+ NULL, /*unlock */
+ H5FD_FLMAP_SINGLE /*fl_map */
};
/* Declare a free list to manage the H5FD_windows_t struct */
@@ -941,22 +943,20 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
}
+
/*-------------------------------------------------------------------------
* Function: H5FD_windows_flush
*
* Purpose: Makes sure that the true file size is the same (or larger)
- * than the end-of-address.
+ * than the end-of-address.
*
* Return: Success: Non-negative
- *
- * Failure: Negative
+ * Failure: Negative
*
* Programmer: Scott Wegner
- * Based on code by Robb Matzke
+ * Based on code by Robb Matzke
* Thursday, May 24 2007
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
/* ARGSUSED */
@@ -964,58 +964,96 @@ static herr_t
H5FD_windows_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned closing)
{
H5FD_windows_t *file = (H5FD_windows_t*)_file;
- herr_t ret_value=SUCCEED; /* Return value */
-#ifndef WINDOWS_USE_STDIO
- LARGE_INTEGER li;
- HANDLE filehandle;
-#else
- int fd;
-#endif /* WINDOWS_USE_STDIO */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5FD_windows_flush, FAIL)
- assert(file);
+ HDassert(file);
+
+ /* Only try to flush if we have write access */
+ if(file->write_access) {
+ /* Flush */
+ if(!closing) {
+#ifdef WINDOWS_USE_STDIO
+ if(fflush(file->fp) == EOF)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "fflush failed")
+#endif /* WINDOWS_USE_STDIO */
+
+ /* Reset last file I/O information */
+ file->pos = HADDR_UNDEF;
+ file->op = OP_UNKNOWN;
+ } /* end if */
+ } /* end if */
- if (file->eoa != file->eof) {
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_windows_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_windows_truncate
+ *
+ * Purpose: Makes sure that the true file size is the same (or larger)
+ * than the end-of-address.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Scott Wegner
+ * Based on code by Robb Matzke
+ * Thursday, May 24 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static herr_t
+H5FD_windows_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t closing)
+{
+ H5FD_windows_t *file = (H5FD_windows_t*)_file;
#ifndef WINDOWS_USE_STDIO
+ LARGE_INTEGER li;
+ HANDLE filehandle;
+#else
+ int fd;
+#endif /* WINDOWS_USE_STDIO */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Extend the file to make sure it's large enough */
- if( (filehandle = (HANDLE)_get_osfhandle(file->fd)) == INVALID_HANDLE_VALUE)
- HGOTO_ERROR(H5E_FILE, H5E_FILEOPEN, FAIL, "unable to get file handle for file")
+ FUNC_ENTER_NOAPI(H5FD_windows_truncate, FAIL)
- li.QuadPart = (__int64)file->eoa;
- (void)SetFilePointer((HANDLE)filehandle,li.LowPart,&li.HighPart,FILE_BEGIN);
- if(SetEndOfFile(filehandle) == 0)
- HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
+ HDassert(file);
+ if(file->eoa != file->eof) {
+#ifndef WINDOWS_USE_STDIO
+ /* Extend the file to make sure it's large enough */
+ if((filehandle = (HANDLE)_get_osfhandle(file->fd)) == INVALID_HANDLE_VALUE)
+ HGOTO_ERROR(H5E_FILE, H5E_FILEOPEN, FAIL, "unable to get file handle for file")
+
+ li.QuadPart = (__int64)file->eoa;
+ (void)SetFilePointer((HANDLE)filehandle, li.LowPart, &li.HighPart, FILE_BEGIN);
+ if(SetEndOfFile(filehandle) == 0)
+ HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
#else /* WINDOWS_USE_STDIO */
- /* Only try to flush if we have write access */
- if(!file->write_access)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot flush without write access")
-
- if((fd = _fileno(file->fp)) == -1)
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to get file descriptor for file")
- if(_chsize_s(fd, file->eoa))
- HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
-
- /* Flush */
- if(!closing)
- if (fflush(file->fp) == EOF)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "fflush failed")
+ /* Only try to flush if we have write access */
+ if(!file->write_access)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot flush without write access")
+
+ if((fd = _fileno(file->fp)) == -1)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to get file descriptor for file")
+ if(_chsize_s(fd, file->eoa))
+ HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
#endif /* WINDOWS_USE_STDIO */
- /* Update the eof value */
- file->eof = file->eoa;
-
- /* Reset last file I/O information */
- file->pos = HADDR_UNDEF;
- file->op = OP_UNKNOWN;
+ /* Update the eof value */
+ file->eof = file->eoa;
- }
+ /* Reset last file I/O information */
+ file->pos = HADDR_UNDEF;
+ file->op = OP_UNKNOWN;
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_windows_truncate() */
#endif /* H5_HAVE_WINDOWS */
diff --git a/src/H5FS.c b/src/H5FS.c
index 47ac7ef..4282200 100644
--- a/src/H5FS.c
+++ b/src/H5FS.c
@@ -91,22 +91,25 @@ H5FL_DEFINE(H5FS_t);
* Programmer: Quincey Koziol
* Tuesday, March 7, 2006
*
+ * Modifications:
+ * Vailin Choi, July 29th, 2008
+ * Add two more parameters for handling alignment: alignment & threshhold
+ *
*-------------------------------------------------------------------------
*/
H5FS_t *
H5FS_create(H5F_t *f, hid_t dxpl_id, haddr_t *fs_addr, const H5FS_create_t *fs_create,
- size_t nclasses, const H5FS_section_class_t *classes[], void *cls_init_udata)
+ size_t nclasses, const H5FS_section_class_t *classes[], void *cls_init_udata, hsize_t alignment, hsize_t threshold)
{
H5FS_t *fspace = NULL; /* New free space structure */
H5FS_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5FS_create, NULL)
-#ifdef QAK
+#ifdef H5FS_DEBUG
HDfprintf(stderr, "%s: Creating free space manager, nclasses = %Zu\n", FUNC, nclasses);
-#endif /* QAK */
+#endif /* H5FS_DEBUG */
/* Check arguments. */
- HDassert(fs_addr);
HDassert(fs_create->shrink_percent);
HDassert(fs_create->shrink_percent < fs_create->expand_percent);
HDassert(fs_create->max_sect_size);
@@ -118,11 +121,6 @@ HDfprintf(stderr, "%s: Creating free space manager, nclasses = %Zu\n", FUNC, ncl
if(NULL == (fspace = H5FS_new(nclasses, classes, cls_init_udata)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for free space free list")
- /* Allocate space for the free space header */
- if(HADDR_UNDEF == (fspace->addr = H5MF_alloc(f, H5FD_MEM_FSPACE_HDR, dxpl_id, (hsize_t)H5FS_HEADER_SIZE(f))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "file allocation failed for free space header")
- *fs_addr = fspace->addr;
-
/* Initialize creation information for free space manager */
fspace->client = fs_create->client;
fspace->shrink_percent = fs_create->shrink_percent;
@@ -130,17 +128,39 @@ HDfprintf(stderr, "%s: Creating free space manager, nclasses = %Zu\n", FUNC, ncl
fspace->max_sect_addr = fs_create->max_sect_addr;
fspace->max_sect_size = fs_create->max_sect_size;
- /* Cache the new free space header (pinned) */
- if(H5AC_set(f, dxpl_id, H5AC_FSPACE_HDR, fspace->addr, fspace, H5AC__PIN_ENTRY_FLAG) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, NULL, "can't add free space header to cache")
+ fspace->alignment = alignment;
+ fspace->threshold = threshold;
+
+ /* Check if the free space tracker is supposed to be persistant */
+ if(fs_addr) {
+ /* Allocate space for the free space header */
+ if(HADDR_UNDEF == (fspace->addr = H5MF_alloc(f, H5FD_MEM_FSPACE_HDR, dxpl_id, (hsize_t)H5FS_HEADER_SIZE(f))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "file allocation failed for free space header")
+
+ /* Cache the new free space header (pinned) */
+ if(H5AC_set(f, dxpl_id, H5AC_FSPACE_HDR, fspace->addr, fspace, H5AC__PIN_ENTRY_FLAG) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, NULL, "can't add free space header to cache")
+
+ /* Return free space header address to caller, if desired */
+ *fs_addr = fspace->addr;
+ } /* end if */
+
+ /* Set the reference count to 1, since we inserted the entry in the cache pinned */
+ fspace->rc = 1;
/* Set the return value */
ret_value = fspace;
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: fspace = %p, fspace->addr = %a\n", FUNC, fspace, fspace->addr);
+#endif /* H5FS_DEBUG */
done:
if(!ret_value && fspace)
(void)H5FS_cache_hdr_dest(f, fspace);
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value);
+#endif /* H5FS_DEBUG */
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_create() */
@@ -157,21 +177,25 @@ done:
* Programmer: Quincey Koziol
* Tuesday, May 2, 2006
*
+ * Modfications:
+ *
+ * Vailin Choi, July 29th, 2008
+ * Add two more parameters for handling alignment: alignment & threshhold
+ *
*-------------------------------------------------------------------------
*/
H5FS_t *
H5FS_open(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr, size_t nclasses,
- const H5FS_section_class_t *classes[], void *cls_init_udata)
+ const H5FS_section_class_t *classes[], void *cls_init_udata, hsize_t alignment, hsize_t threshold)
{
H5FS_t *fspace = NULL; /* New free space structure */
H5FS_prot_t fs_prot; /* Information for protecting free space manager */
- unsigned fspace_status = 0; /* Free space header's status in the metadata cache */
H5FS_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5FS_open, NULL)
-#ifdef QAK
-HDfprintf(stderr, "%s: Opening free space manager, nclasses = %Zu\n", FUNC, nclasses);
-#endif /* QAK */
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Opening free space manager, fs_addr = %a, nclasses = %Zu\n", FUNC, fs_addr, nclasses);
+#endif /* H5FS_DEBUG */
/* Check arguments. */
HDassert(H5F_addr_defined(fs_addr));
@@ -186,26 +210,23 @@ HDfprintf(stderr, "%s: Opening free space manager, nclasses = %Zu\n", FUNC, ncla
/* Protect the free space header */
if(NULL == (fspace = (H5FS_t *)H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, &fs_prot, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, NULL, "unable to load free space header")
-#ifdef QAK
+#ifdef H5FS_DEBUG
HDfprintf(stderr, "%s: fspace->sect_addr = %a\n", FUNC, fspace->sect_addr);
HDfprintf(stderr, "%s: 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 = %p\n", FUNC, fspace->sinfo);
-#endif /* QAK */
+HDfprintf(stderr, "%s: fspace->rc = %u\n", FUNC, fspace->rc);
+#endif /* H5FS_DEBUG */
- /* Check the free space header's status in the metadata cache */
- if(H5AC_get_entry_status(f, fs_addr, &fspace_status) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, NULL, "unable to check metadata cache status for free space header")
+ /* Increment the reference count on the free space manager header */
+ HDassert(fspace->rc <= 1);
+ if(H5FS_incr(f, fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTINC, NULL, "unable to increment ref. count on free space header")
- /* If the free space header isn't already pinned, pin it now */
- /* (could still be pinned from it's section info still hanging around in the cache) */
- if(!(fspace_status & H5AC_ES__IS_PINNED)) {
- /* Pin free space header in the cache */
- if(H5AC_pin_protected_entry(f, fspace) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTPIN, NULL, "unable to pin free space header")
- } /* end if */
+ fspace->alignment = alignment;
+ fspace->threshold = threshold;
- /* Unlock free space header, now pinned */
+ /* Unlock free space header */
if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, fspace, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPROTECT, NULL, "unable to release free space header")
@@ -239,9 +260,9 @@ H5FS_delete(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr)
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5FS_delete, FAIL)
-#ifdef QAK
-HDfprintf(stderr, "%s: Deleting free space manager\n", FUNC);
-#endif /* QAK */
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Deleting free space manager, fs_addr = %a\n", FUNC, fs_addr);
+#endif /* H5FS_DEBUG */
/* Check arguments. */
HDassert(f);
@@ -257,16 +278,19 @@ HDfprintf(stderr, "%s: Deleting free space manager\n", FUNC);
if(NULL == (fspace = (H5FS_t *)H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, &fs_prot, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, FAIL, "unable to protect free space header")
+ /* Sanity check */
+ HDassert(fspace->sinfo == NULL);
+
/* Delete serialized section storage, if there are any */
-#ifdef QAK
+#ifdef H5FS_DEBUG
HDfprintf(stderr, "%s: fspace->sect_addr = %a\n", FUNC, fspace->sect_addr);
-#endif /* QAK */
+#endif /* H5FS_DEBUG */
if(fspace->serial_sect_count > 0) {
unsigned sinfo_status = 0; /* Free space section info's status in the metadata cache */
/* Sanity check */
HDassert(H5F_addr_defined(fspace->sect_addr));
- HDassert(fspace->sect_size > 0);
+ HDassert(fspace->alloc_sect_size > 0);
/* Check the free space section info's status in the metadata cache */
if(H5AC_get_entry_status(f, fspace->sect_addr, &sinfo_status) < 0)
@@ -278,32 +302,28 @@ HDfprintf(stderr, "%s: fspace->sect_addr = %a\n", FUNC, fspace->sect_addr);
HDassert(!(sinfo_status & H5AC_ES__IS_PINNED));
HDassert(!(sinfo_status & H5AC_ES__IS_PROTECTED));
-#ifdef QAK
+#ifdef H5FS_DEBUG
HDfprintf(stderr, "%s: Expunging free space section info from cache\n", FUNC);
-#endif /* QAK */
+#endif /* H5FS_DEBUG */
/* Evict the free space section info from the metadata cache */
- if(H5AC_expunge_entry(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr) < 0)
+ /* (Free file space) */
+ if(H5AC_expunge_entry(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, H5AC__FREE_FILE_SPACE_FLAG) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "unable to remove free space section info from cache")
-#ifdef QAK
+#ifdef H5FS_DEBUG
HDfprintf(stderr, "%s: Done expunging free space section info from cache\n", FUNC);
-#endif /* QAK */
+#endif /* H5FS_DEBUG */
} /* end if */
-
- /* Release the space in the file */
- if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_addr, fspace->alloc_sect_size) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to release free space sections")
+ else {
+ /* Release the space in the file */
+ if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_addr, fspace->alloc_sect_size) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to release free space sections")
+ } /* end else */
} /* end if */
- /* Release header's disk space */
- if(H5MF_xfree(f, H5FD_MEM_FSPACE_HDR, dxpl_id, fs_addr, (hsize_t)H5FS_HEADER_SIZE(f))<0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to release free space header")
-
- /* Release the free space header */
- if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, fspace, H5AC__DELETED_FLAG) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPROTECT, FAIL, "unable to release free space header")
- fspace = NULL;
-
done:
+ if(fspace && H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, fspace, H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
+ HDONE_ERROR(H5E_FSPACE, H5E_CANTUNPROTECT, FAIL, "unable to release free space header")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_delete() */
@@ -333,72 +353,143 @@ H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace)
/* Check arguments. */
HDassert(f);
HDassert(fspace);
-#ifdef QAK
-HDfprintf(stderr, "%s: Entering, fspace = %p, fspace->sinfo = %p\n", FUNC, fspace, fspace->sinfo);
-#endif /* QAK */
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Entering, fspace = %p, fspace->addr = %a, fspace->sinfo = %p\n", FUNC, fspace, fspace->addr, fspace->sinfo);
+#endif /* H5FS_DEBUG */
/* Check if section info is valid */
+ /* (i.e. the header "owns" the section info and it's not in the cache) */
if(fspace->sinfo) {
- HDassert(H5F_addr_defined(fspace->sect_addr));
-
- /* Unpin the free space section info in the cache */
- if(H5AC_unpin_entry(f, fspace->sinfo) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin free space section info")
-
- /* If there aren't any sections being managed, free the space for the sections */
-#ifdef QAK
-HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu\n", FUNC, fspace->tot_sect_count);
-#endif /* QAK */
- if(fspace->tot_sect_count == 0) {
- haddr_t old_addr; /* Old section info address */
-
- HDassert(fspace->serial_sect_count == 0);
- HDassert(fspace->ghost_sect_count == 0);
-
- /* 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 release free space sections")
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu, fspace->serial_sect_count = %Hu, fspace->sect_addr = %a, fspace->rc = %u\n", FUNC, fspace->tot_sect_count, fspace->serial_sect_count, fspace->sect_addr, fspace->rc);
+HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n", FUNC, fspace->alloc_sect_size, fspace->sect_size);
+#endif /* H5FS_DEBUG */
+ /* If there are sections to serialize, update them */
+ /* (if the free space manager is persistant) */
+ if(fspace->serial_sect_count > 0 && H5F_addr_defined(fspace->addr)) {
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Real sections to store in file\n", FUNC);
+#endif /* H5FS_DEBUG */
+ if(fspace->sinfo->dirty) {
+ /* Check if the section info is "floating" */
+ if(!H5F_addr_defined(fspace->sect_addr)) {
+ /* Sanity check */
+ HDassert(fspace->sect_size > 0);
+
+ /* Allocate space for the section info in file */
+ if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_size)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
+ fspace->alloc_sect_size = (size_t)fspace->sect_size;
+
+ /* 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 if */
+ else
+ /* Sanity check that section info has address */
+ HDassert(H5F_addr_defined(fspace->sect_addr));
+
+ /* Cache the free space section info */
+ if(H5AC_set(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, fspace->sinfo, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, FAIL, "can't add free space sections to cache")
+ } /* end if */
+ else {
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: NOT storing section info in file\n", FUNC);
+#endif /* H5FS_DEBUG */
+ /* Check if space for the section info is allocated */
+ if(H5F_addr_defined(fspace->sect_addr)) {
+ /* Sanity check */
+ /* (section info should only be in the file if the header is */
+ HDassert(H5F_addr_defined(fspace->addr));
- /* Reset section info */
- fspace->sect_addr = HADDR_UNDEF;
- fspace->alloc_sect_size = fspace->sect_size = 0;
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Section info allocated though\n", FUNC);
+#endif /* H5FS_DEBUG */
+ /* Check if the section info is for the free space in the file */
+ /* (NOTE: This is the "bootstrapping" special case for the
+ * free space manager, to avoid freeing the space for the
+ * section info and re-creating it as a section in the
+ * manager. -QAK)
+ */
+ if(fspace->client == H5FS_CLIENT_FILE_ID) {
+ htri_t status; /* "can absorb" status for section into */
- /* 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")
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Section info is for file free space\n", FUNC);
+#endif /* H5FS_DEBUG */
+ /* Try to shrink the file or absorb the section info into a block aggregator */
+ if((status = H5MF_try_shrink(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_addr, fspace->alloc_sect_size)) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't check for absorbing section info")
+ else if(status == FALSE) {
+ /* Section info can't "go away", but it's free. Allow
+ * header to record it
+ */
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Section info can't 'go away', header will own it\n", FUNC);
+#endif /* H5FS_DEBUG */
+ } /* end if */
+ else {
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Section info went 'go away'\n", FUNC);
+#endif /* H5FS_DEBUG */
+ /* Reset section info in header */
+ fspace->sect_addr = HADDR_UNDEF;
+ fspace->alloc_sect_size = 0;
+
+ /* 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 else */
+ } /* end if */
+ else {
+ 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 */
- /* Evict the section info from the metadata cache */
- if(H5AC_expunge_entry(f, dxpl_id, H5AC_FSPACE_SINFO, old_addr) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "unable to remove free space section info from cache")
- } /* end if */
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Section info is NOT for file free space\n", FUNC);
+#endif /* H5FS_DEBUG */
+ /* Reset section info in header */
+ fspace->sect_addr = HADDR_UNDEF;
+ fspace->alloc_sect_size = 0;
+
+ /* 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")
+
+ /* Free previous serialized sections disk space */
+ 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 else */
+
+ /* Destroy section info */
+ if(H5FS_cache_sinfo_dest(f, fspace->sinfo) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTCLOSEOBJ, FAIL, "unable to destroy free space section info")
+ } /* end else */
+
+ /* Reset the header's pointer to the section info */
+ fspace->sinfo = NULL;
} /* end if */
else {
- unsigned sect_status = 0; /* Free space section's status in the metadata cache */
-
- /* Check if we've allocated any section info in the file & if it's still in the cache */
- if(H5F_addr_defined(fspace->sect_addr) && H5AC_get_entry_status(f, fspace->sect_addr, &sect_status) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "unable to check metadata cache status for free space header")
-
- /* If this free list header's section info exists and is still in the
- * cache, don't unpin the header - let the section info do it,
- * when the section info is evicted from the cache. -QAK
- */
- if(!(sect_status & H5AC_ES__IN_CACHE)) {
- /* Unpin the free space header in the cache */
- /* (the section info destructor would unpin it if the section info existed) */
- if(H5AC_unpin_entry(f, fspace) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin free space header")
- } /* end if */
+ /* Just sanity checks... */
+ if(fspace->serial_sect_count > 0)
+ /* Sanity check that section info has address */
+ HDassert(H5F_addr_defined(fspace->sect_addr));
+ else
+ /* Sanity check that section info doesn't have address */
+ HDassert(!H5F_addr_defined(fspace->sect_addr));
} /* end else */
- /* Reset the header's pointer to the section info, so it will get pinned again
- * if the free space header is still in the metadata cache when the free
- * space manager is re-opened.
- */
- fspace->sinfo = NULL;
+ /* Decrement the reference count on the free space manager header */
+ if(H5FS_decr(f, fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTDEC, FAIL, "unable to decrement ref. count on free space header")
done:
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Leaving, ret_value = %d, fspace->rc = %u\n", FUNC, ret_value, fspace->rc);
+#endif /* H5FS_DEBUG */
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_close() */
@@ -453,6 +544,10 @@ H5FS_new(size_t nclasses, const H5FS_section_class_t *classes[],
if(fspace->sect_cls[u].init_cls)
if((fspace->sect_cls[u].init_cls)(&fspace->sect_cls[u], cls_init_udata) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, NULL, "unable to initialize section class")
+
+ /* Determine maximum class-specific serialization size for each section */
+ if(fspace->sect_cls[u].serial_size > fspace->max_cls_serial_size)
+ fspace->max_cls_serial_size = fspace->sect_cls[u].serial_size;
} /* end for */
} /* end if */
@@ -494,12 +589,141 @@ H5FS_size(const H5F_t *f, const H5FS_t *fspace, hsize_t *meta_size)
HDassert(meta_size);
/* Get the free space size info */
- *meta_size += H5FS_HEADER_SIZE(f) + fspace->alloc_sect_size;
+ *meta_size += H5FS_HEADER_SIZE(f) + (fspace->sinfo ? fspace->sect_size : fspace->alloc_sect_size);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5FS_size() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS_incr
+ *
+ * Purpose: Increment reference count on free space header
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * February 7, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FS_incr(H5F_t *f, H5FS_t *fspace)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FS_incr, FAIL)
#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Entering, fpace->addr = %a, fspace->rc = %u\n", FUNC, fspace->addr, fspace->rc);
+#endif /* H5FS_DEBUG */
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(fspace);
+
+ /* Check if we should pin the header in the cache */
+ if(fspace->rc == 0 && H5F_addr_defined(fspace->addr))
+ if(H5AC_pin_protected_entry(f, fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTPIN, FAIL, "unable to pin free space header")
+
+ /* Increment reference count on header */
+ fspace->rc++;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FS_incr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS_decr
+ *
+ * Purpose: Decrement reference count on free space header
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * February 7, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FS_decr(H5F_t *f, H5FS_t *fspace)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FS_decr, FAIL)
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Entering, fpace->addr = %a, fspace->rc = %u\n", FUNC, fspace->addr, fspace->rc);
+#endif /* H5FS_DEBUG */
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(fspace);
+
+ /* Decrement reference count on header */
+ fspace->rc--;
+
+ /* Check if we should unpin the header in the cache */
+ if(fspace->rc == 0) {
+ if(H5F_addr_defined(fspace->addr)) {
+ if(H5AC_unpin_entry(f, fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin free space header")
+ } /* end if */
+ else {
+ if(H5FS_cache_hdr_dest(f, fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTCLOSEOBJ, FAIL, "unable to destroy free space header")
+ } /* end else */
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FS_decr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS_dirty
+ *
+ * Purpose: Mark free space header as dirty
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Feb 14 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FS_dirty(H5F_t *f, H5FS_t *fspace)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5FS_dirty)
+#ifdef QAK
+HDfprintf(stderr, "%s: Marking free space header as dirty\n", FUNC);
+#endif /* QAK */
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(fspace);
+
+ /* Check if the free space manager is persistant */
+ if(H5F_addr_defined(fspace->addr))
+ /* Mark header as dirty in cache */
+ 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)
+} /* end H5FS_dirty() */
+
+#ifdef H5FS_DEBUG_ASSERT
/*-------------------------------------------------------------------------
* Function: H5FS_assert
@@ -518,16 +742,19 @@ herr_t
H5FS_assert(const H5FS_t *fspace)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_assert)
-#ifdef QAK
-HDfprintf(stderr, "%s: fspace->hdr->tot_sect_count = %Hu\n", "H5FS_assert", fspace->hdr->tot_sect_count);
+#ifndef QAK
+HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu\n", "H5FS_assert", fspace->tot_sect_count);
#endif /* QAK */
- /* Sanity check sections */
- H5FS_sect_assert(fspace);
+ /* Checks for section info, if it's available */
+ if(fspace->sinfo) {
+ /* Sanity check sections */
+ H5FS_sect_assert(fspace);
- /* General assumptions about the section size counts */
- HDassert(fspace->sinfo->tot_size_count >= fspace->sinfo->serial_size_count);
- HDassert(fspace->sinfo->tot_size_count >= fspace->sinfo->ghost_size_count);
+ /* General assumptions about the section size counts */
+ HDassert(fspace->sinfo->tot_size_count >= fspace->sinfo->serial_size_count);
+ HDassert(fspace->sinfo->tot_size_count >= fspace->sinfo->ghost_size_count);
+ } /* end if */
/* General assumptions about the section counts */
HDassert(fspace->tot_sect_count >= fspace->serial_sect_count);
@@ -539,5 +766,4 @@ HDfprintf(stderr, "%s: fspace->hdr->tot_sect_count = %Hu\n", "H5FS_assert", fspa
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5FS_assert() */
-#endif /* H5FS_DEBUG */
-
+#endif /* H5FS_DEBUG_ASSERT */
diff --git a/src/H5FScache.c b/src/H5FScache.c
index edf045a..a7af72b 100644
--- a/src/H5FScache.c
+++ b/src/H5FScache.c
@@ -36,6 +36,7 @@
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5FSpkg.h" /* File free space */
+#include "H5MFprivate.h" /* File memory management */
#include "H5Vprivate.h" /* Vectors and arrays */
#include "H5WBprivate.h" /* Wrapped Buffers */
@@ -299,12 +300,68 @@ H5FS_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5F
FUNC_ENTER_NOAPI_NOINIT(H5FS_cache_hdr_flush)
#ifdef QAK
HDfprintf(stderr, "%s: Flushing free space header, addr = %a, destroy = %u\n", FUNC, addr, (unsigned)destroy);
+HDfprintf(stderr, "%s: fspace->sect_addr = %a, fspace->sinfo = %p\n", FUNC, fspace->sect_addr, fspace->sinfo);
+HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n", FUNC, fspace->alloc_sect_size, fspace->sect_size);
#endif /* QAK */
/* check arguments */
HDassert(f);
HDassert(H5F_addr_defined(addr));
HDassert(fspace);
+ HDassert(H5F_addr_defined(fspace->addr));
+
+ /* Check if the header "owns" the section info */
+ if(fspace->sinfo) {
+ /* Sanity check - should not be trying to destroy header if it still
+ * "owns" section info
+ */
+ HDassert(!destroy);
+
+ /* Check if the section info is dirty */
+ if(fspace->sinfo->dirty) {
+ if(fspace->serial_sect_count > 0) {
+ /* Check if we need to allocate space for section info */
+ if(!H5F_addr_defined(fspace->sect_addr)) {
+ /* Sanity check */
+ HDassert(fspace->sect_size > 0);
+
+ /* Allocate space for the section info in file */
+ if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_size)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
+ fspace->alloc_sect_size = (size_t)fspace->sect_size;
+
+ /* Mark header dirty */
+ /* (don't use cache API, since we're in a callback) */
+ fspace->cache_info.is_dirty = TRUE;
+ } /* end if */
+
+ /* Write section info to file */
+ if(H5FS_cache_sinfo_flush(f, dxpl_id, FALSE, fspace->sect_addr, fspace->sinfo, NULL) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTFLUSH, FAIL, "unable to save free space section info to disk")
+ } /* end if */
+ else {
+ /* Sanity check that section info doesn't have address */
+ HDassert(!H5F_addr_defined(fspace->sect_addr));
+ } /* end else */
+#ifdef QAK
+HDfprintf(stderr, "%s: Check 2.0\n", FUNC);
+HDfprintf(stderr, "%s: fspace->sect_addr = %a, fspace->sinfo = %p\n", FUNC, fspace->sect_addr, fspace->sinfo);
+HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n", FUNC, fspace->alloc_sect_size, fspace->sect_size);
+#endif /* QAK */
+
+ /* Mark section info clean */
+ fspace->sinfo->dirty = FALSE;
+ } /* end if */
+ } /* end if */
+ else {
+ /* Just sanity checks... */
+ if(fspace->serial_sect_count > 0)
+ /* Sanity check that section info has address */
+ HDassert(H5F_addr_defined(fspace->sect_addr));
+ else
+ /* Sanity check that section info doesn't have address */
+ HDassert(!H5F_addr_defined(fspace->sect_addr));
+ } /* end else */
if(fspace->cache_info.is_dirty) {
uint8_t *hdr; /* Pointer to header buffer */
@@ -412,9 +469,8 @@ done:
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
herr_t
-H5FS_cache_hdr_dest(H5F_t UNUSED *f, H5FS_t *fspace)
+H5FS_cache_hdr_dest(H5F_t *f, H5FS_t *fspace)
{
unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
@@ -426,6 +482,12 @@ H5FS_cache_hdr_dest(H5F_t UNUSED *f, H5FS_t *fspace)
*/
HDassert(fspace);
+ /* We should not still be holding on to the free space section info */
+ HDassert(!fspace->sinfo);
+
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!fspace->cache_info.free_file_space_on_destroy || H5F_addr_defined(fspace->cache_info.addr));
+
/* Terminate the section classes for this free space list */
for(u = 0; u < fspace->nclasses ; u++) {
/* Call the class termination routine, if there is one */
@@ -434,6 +496,17 @@ H5FS_cache_hdr_dest(H5F_t UNUSED *f, H5FS_t *fspace)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "unable to finalize section class")
} /* end for */
+ /* Check for freeing file space for free space header */
+ if(fspace->cache_info.free_file_space_on_destroy) {
+ /* Sanity check */
+ HDassert(H5F_addr_defined(fspace->addr));
+
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_FSPACE_HDR, H5AC_dxpl_id, fspace->cache_info.addr, (hsize_t)H5FS_HEADER_SIZE(f)) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space header")
+ } /* end if */
+
/* Release the memory for the free space section classes */
if(fspace->sect_cls)
fspace->sect_cls = (H5FS_section_class_t *)H5FL_SEQ_FREE(H5FS_section_class_t, fspace->sect_cls);
@@ -556,11 +629,6 @@ HDfprintf(stderr, "%s: Load free space sections, addr = %a\n", FUNC, addr);
if(NULL == (sinfo = H5FS_sinfo_new(f, fspace)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- /* Link free space manager to section info */
- /* (for deserializing sections) */
- HDassert(fspace->sinfo == NULL);
- fspace->sinfo = sinfo;
-
/* Sanity check address */
if(H5F_addr_ne(addr, fspace->sect_addr))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "incorrect address for free space sections")
@@ -872,7 +940,7 @@ HDfprintf(stderr, "%s: Flushing free space header, addr = %a, destroy = %u\n", F
HDassert(sinfo->fspace);
HDassert(sinfo->fspace->sect_cls);
- if(sinfo->cache_info.is_dirty) {
+ if(sinfo->cache_info.is_dirty || sinfo->dirty) {
H5FS_iter_ud_t udata; /* User data for callbacks */
uint8_t *buf = NULL; /* Temporary raw data buffer */
uint8_t *p; /* Pointer into raw data buffer */
@@ -944,6 +1012,7 @@ HDfprintf(stderr, "%s: sinfo->fspace->alloc_sect_size = %Hu\n", FUNC, sinfo->fsp
(void)H5FL_BLK_FREE(sect_block, buf);
sinfo->cache_info.is_dirty = FALSE;
+ sinfo->dirty = FALSE;
} /* end if */
if(destroy)
@@ -966,6 +1035,10 @@ done:
* Programmer: Quincey Koziol
* Saturday, March 11, 2006
*
+ * Modifications:
+ * Vailin Choi, July 29th, 2008
+ * Add HDassert() to make sure "free" method exists before calling
+ *
*-------------------------------------------------------------------------
*/
static herr_t
@@ -978,6 +1051,7 @@ H5FS_sinfo_free_sect_cb(void *_sect, void UNUSED *key, void *op_data)
HDassert(sect);
HDassert(sinfo);
+ HDassert(sinfo->fspace->sect_cls[sect->type].free);
/* Call the section's class 'free' method on the section */
(*sinfo->fspace->sect_cls[sect->type].free)(sect);
@@ -1033,7 +1107,6 @@ H5FS_sinfo_free_node_cb(void *item, void UNUSED *key, void *op_data)
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
herr_t
H5FS_cache_sinfo_dest(H5F_t *f, H5FS_sinfo_t *sinfo)
{
@@ -1041,6 +1114,9 @@ H5FS_cache_sinfo_dest(H5F_t *f, H5FS_sinfo_t *sinfo)
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5FS_cache_sinfo_dest)
+#ifdef QAK
+HDfprintf(stderr, "%s: Destroying section info, sinfo->fspace->addr = %a\n", FUNC, sinfo->fspace->addr);
+#endif /* QAK */
/*
* Check arguments.
@@ -1049,6 +1125,20 @@ H5FS_cache_sinfo_dest(H5F_t *f, H5FS_sinfo_t *sinfo)
HDassert(sinfo->fspace);
HDassert(sinfo->bins);
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!sinfo->cache_info.free_file_space_on_destroy || H5F_addr_defined(sinfo->cache_info.addr));
+
+ /* Check for freeing file space for free space section info */
+ if(sinfo->cache_info.free_file_space_on_destroy) {
+ /* Sanity check */
+ HDassert(sinfo->fspace->alloc_sect_size > 0);
+
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, H5AC_dxpl_id, sinfo->cache_info.addr, (hsize_t)sinfo->fspace->alloc_sect_size) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space section info")
+ } /* end if */
+
/* Clear out lists of nodes */
for(u = 0; u < sinfo->nbins; u++)
if(sinfo->bins[u].bin_list) {
@@ -1064,12 +1154,14 @@ H5FS_cache_sinfo_dest(H5F_t *f, H5FS_sinfo_t *sinfo)
if(H5SL_close(sinfo->merge_list) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTCLOSEOBJ, FAIL, "can't destroy section merging skip list")
- /* Unpin the free space header in the cache */
+ /* Decrement the reference count on free space header */
/* (make certain this is last action with section info, to allow for header
* disappearing immediately)
*/
- if(H5AC_unpin_entry(f, sinfo->fspace) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin free space header")
+ sinfo->fspace->sinfo = NULL;
+ if(H5FS_decr(f, sinfo->fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTDEC, FAIL, "unable to decrement ref. count on free space header")
+ sinfo->fspace = NULL;
/* Release free space section info */
(void)H5FL_FREE(H5FS_sinfo_t, sinfo);
@@ -1141,7 +1233,7 @@ H5FS_cache_sinfo_size(const H5F_t UNUSED *f, const H5FS_sinfo_t *sinfo, size_t *
HDassert(size_ptr);
/* Set size value */
- H5_ASSIGN_OVERFLOW(/* To: */ *size_ptr, /* From: */ sinfo->fspace->sect_size, /* From: */ hsize_t, /* To: */ size_t);
+ H5_ASSIGN_OVERFLOW(/* To: */ *size_ptr, /* From: */ sinfo->fspace->alloc_sect_size, /* From: */ hsize_t, /* To: */ size_t);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5FS_cache_sinfo_size() */
diff --git a/src/H5FSdbg.c b/src/H5FSdbg.c
index b5d2a6f..cf165ca 100644
--- a/src/H5FSdbg.c
+++ b/src/H5FSdbg.c
@@ -30,6 +30,7 @@
#define H5FS_PACKAGE /*suppress error about including H5FSpkg */
#define H5HF_DEBUGGING /* Need access to fractal heap debugging routines */
+#define H5MF_DEBUGGING /* Need access to file space debugging routines */
/***********/
/* Headers */
@@ -38,6 +39,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5FSpkg.h" /* File free space */
#include "H5HFprivate.h" /* Fractal heaps */
+#include "H5MFprivate.h" /* File memory management */
/****************/
/* Local Macros */
@@ -85,6 +87,10 @@
* koziol@ncsa.uiuc.edu
* May 9 2006
*
+ * Modifications:
+ * Vailin Choi, July 29th, 2008
+ * Add H5FS_CLIENT_FILE_ID for File Memory Management
+ *
*-------------------------------------------------------------------------
*/
herr_t
@@ -124,7 +130,8 @@ H5FS_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int
*/
HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
"Free space client:",
- (fspace->client == H5FS_CLIENT_FHEAP_ID ? "Fractal heap" : "Unknown"));
+ (fspace->client == H5FS_CLIENT_FHEAP_ID ? "Fractal heap" :
+ (fspace->client == H5FS_CLIENT_FILE_ID ? "File Memory Management" : "Unknown")));
HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
"Total free space tracked:",
fspace->tot_space);
@@ -259,7 +266,10 @@ H5FS_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t UNUSED addr, FILE *stream, int
client = fspace->client;
/* Release the free space header */
- if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, fspace, H5AC__NO_FLAGS_SET) < 0)
+ /* (set the "deleted" flag for the unprotect, so the cache entry is removed
+ * and reloaded later, with the correct client information -QAK)
+ */
+ if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, fspace, H5AC__DELETED_FLAG) < 0)
HDONE_ERROR(H5E_FSPACE, H5E_PROTECT, FAIL, "unable to release free space header")
fspace = NULL;
@@ -275,6 +285,13 @@ H5FS_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t UNUSED addr, FILE *stream, int
HGOTO_ERROR(H5E_FSPACE, H5E_SYSTEM, FAIL, "unable to dump fractal heap free space sections")
break;
+ case H5FS_CLIENT_FILE_ID:
+#ifdef NOT_YET
+ if(H5MF_sects_debug(f, dxpl_id, client_addr, stream, indent + 3, MAX(0, fwidth - 3)) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_SYSTEM, FAIL, "unable to dump file free space sections")
+#endif /* NOT_YET */
+ break;
+
default:
HDfprintf(stream, "Unknown client!\n");
break;
diff --git a/src/H5FSpkg.h b/src/H5FSpkg.h
index 9f3409f..1786b44 100644
--- a/src/H5FSpkg.h
+++ b/src/H5FSpkg.h
@@ -28,9 +28,15 @@
#ifndef _H5FSpkg_H
#define _H5FSpkg_H
-/* Uncomment this macro to enable extra sanity checking */
+/* Uncomment this macro to enable debugging output for free space manager */
/* #define H5FS_DEBUG */
+/* Uncomment this macro to enable debugging output for free space sections */
+/* #define H5FS_SINFO_DEBUG */
+
+/* Uncomment this macro to enable extra sanity checking */
+/* #define H5FS_DEBUG_ASSERT */
+
/* Get package's private header */
#include "H5FSprivate.h" /* File free space */
@@ -110,7 +116,7 @@ typedef struct H5FS_node_t {
H5SL_t *sect_list; /* Skip list to hold pointers to actual free list section node */
} H5FS_node_t;
-/* Information about sections managed */
+/* Free space section info */
typedef struct H5FS_sinfo_t {
/* Information for H5AC cache functions, _must_ be first field in structure */
H5AC_info_t cache_info;
@@ -119,6 +125,7 @@ typedef struct H5FS_sinfo_t {
H5FS_bin_t *bins; /* Array of lists of lists of free sections */
/* Computed/cached values */
+ hbool_t dirty; /* Whether this info in memory is out of sync w/info in file */
unsigned nbins; /* Number of bins */
size_t serial_size; /* Total size of all serializable sections */
size_t tot_size_count; /* Total number of differently sized sections */
@@ -133,7 +140,7 @@ typedef struct H5FS_sinfo_t {
H5SL_t *merge_list; /* Skip list to hold sections for detecting merges */
} H5FS_sinfo_t;
-/* Main free space info */
+/* Free space header info */
struct H5FS_t {
/* Information for H5AC cache functions, _must_ be first field in structure */
H5AC_info_t cache_info;
@@ -159,8 +166,17 @@ struct H5FS_t {
hsize_t alloc_sect_size; /* Allocated size of the section info in the file */
/* Computed/cached values */
+ unsigned rc; /* Count of outstanding references to struct */
haddr_t addr; /* Address of free space header on disk */
H5FS_sinfo_t *sinfo; /* Section information */
+ unsigned sinfo_lock_count; /* # of times the section info has been locked */
+ hbool_t sinfo_protected; /* Whether the section info was protected when locked */
+ hbool_t sinfo_modified; /* Whether the section info has been modified while locked */
+ H5AC_protect_t sinfo_accmode; /* Access mode for protecting the section info */
+ size_t max_cls_serial_size; /* Max. additional size of serialized form of section */
+ hsize_t threshold; /* Threshold for alignment */
+ hsize_t alignment; /* Alignment */
+
/* Memory data structures (not stored directly) */
H5FS_section_class_t *sect_cls; /* Array of section classes for this free list */
@@ -197,6 +213,9 @@ H5FL_EXTERN(H5FS_t);
/* Free space manager header routines */
H5_DLL H5FS_t *H5FS_new(size_t nclasses, const H5FS_section_class_t *classes[],
void *cls_init_udata);
+H5_DLL herr_t H5FS_incr(H5F_t *f, H5FS_t *fspace);
+H5_DLL herr_t H5FS_decr(H5F_t *f, H5FS_t *fspace);
+H5_DLL herr_t H5FS_dirty(H5F_t *f, H5FS_t *fspace);
/* Free space section routines */
H5_DLL H5FS_sinfo_t *H5FS_sinfo_new(H5F_t *f, H5FS_t *fspace);
@@ -211,5 +230,11 @@ H5_DLL herr_t H5FS_assert(const H5FS_t *fspace);
H5_DLL herr_t H5FS_sect_assert(const H5FS_t *fspace);
#endif /* H5FS_DEBUG */
+/* Testing routines */
+#ifdef H5FS_TESTING
+H5_DLL herr_t H5FS_get_cparam_test(const H5FS_t *fh, H5FS_create_t *cparam);
+H5_DLL int H5FS_cmp_cparam_test(const H5FS_create_t *cparam1, const H5FS_create_t *cparam2);
+#endif /* H5FS_TESTING */
+
#endif /* _H5FSpkg_H */
diff --git a/src/H5FSprivate.h b/src/H5FSprivate.h
index ff8ecfd..6f73b93 100644
--- a/src/H5FSprivate.h
+++ b/src/H5FSprivate.h
@@ -43,10 +43,14 @@
* serialized to the file.
*/
#define H5FS_CLS_SEPAR_OBJ 0x02 /* Objects in this class shouldn't
- * participate in merge operations
+ * participate in merge operations.
*/
#define H5FS_CLS_MERGE_SYM 0x04 /* Objects in this class only merge
- * with other objects in this class
+ * with other objects in this class.
+ */
+#define H5FS_CLS_ADJUST_OK 0x08 /* Objects in this class can be merged
+ * without requiring a can_adjust/adjust
+ * callback pair.
*/
/* Flags for H5FS_add() */
@@ -103,6 +107,7 @@ typedef struct H5FS_section_class_t {
herr_t (*shrink)(H5FS_section_info_t **, void *); /* Routine to shrink container */
herr_t (*free)(H5FS_section_info_t *); /* Routine to free node */
herr_t (*valid)(const struct H5FS_section_class_t *, const H5FS_section_info_t *); /* Routine to check if a section is valid */
+ H5FS_section_info_t *(*split)(H5FS_section_info_t *, hsize_t); /* Routine to create the split section */
herr_t (*debug)(const H5FS_section_info_t *, FILE *, int , int ); /* Routine to dump debugging information about a section */
} H5FS_section_class_t;
@@ -123,6 +128,7 @@ struct H5FS_section_info_t {
/* Free space client IDs for identifying user of free space */
typedef enum H5FS_client_t {
H5FS_CLIENT_FHEAP_ID = 0, /* Free space is used by fractal heap */
+ H5FS_CLIENT_FILE_ID, /* Free space is used by file */
H5FS_NUM_CLIENT_ID /* Number of free space client IDs (must be last) */
} H5FS_client_t;
@@ -135,6 +141,15 @@ typedef struct H5FS_create_t {
hsize_t max_sect_size; /* Maximum size of section to track */
} H5FS_create_t;
+/* Free space statistics info */
+typedef struct H5FS_stat_t {
+ hsize_t tot_space; /* Total amount of space tracked */
+ hsize_t tot_sect_count; /* Total # of sections tracked */
+ hsize_t serial_sect_count; /* # of serializable sections tracked */
+ hsize_t ghost_sect_count; /* # of un-serializable sections tracked */
+} H5FS_stat_t;
+
+
/* Typedef for iteration operations */
typedef herr_t (*H5FS_operator_t)(const H5FS_section_info_t *sect,
void *operator_data/*in,out*/);
@@ -155,9 +170,9 @@ H5FL_SEQ_EXTERN(H5FS_section_class_t);
/* Free space manager routines */
H5_DLL H5FS_t *H5FS_create(H5F_t *f, hid_t dxpl_id, haddr_t *fs_addr,
const H5FS_create_t *fs_create, size_t nclasses,
- const H5FS_section_class_t *classes[], void *cls_init_udata);
+ const H5FS_section_class_t *classes[], void *cls_init_udata, hsize_t alignment, hsize_t threshold);
H5_DLL H5FS_t *H5FS_open(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr,
- size_t nclasses, const H5FS_section_class_t *classes[], void *cls_init_udata);
+ size_t nclasses, const H5FS_section_class_t *classes[], void *cls_init_udata, hsize_t alignment, hsize_t threshold);
H5_DLL herr_t H5FS_size(const H5F_t *f, const H5FS_t *fspace, hsize_t *meta_size);
H5_DLL herr_t H5FS_delete(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr);
H5_DLL herr_t H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace);
@@ -165,15 +180,22 @@ H5_DLL herr_t H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace);
/* Free space section routines */
H5_DLL herr_t H5FS_sect_add(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
H5FS_section_info_t *node, unsigned flags, void *op_data);
+H5_DLL herr_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);
H5_DLL herr_t H5FS_sect_remove(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
H5FS_section_info_t *node);
H5_DLL htri_t H5FS_sect_find(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
hsize_t request, H5FS_section_info_t **node);
H5_DLL herr_t H5FS_sect_iterate(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_operator_t op, void *op_data);
-H5_DLL herr_t H5FS_get_sect_count(const H5FS_t *fspace, hsize_t *nsects);
+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);
+/* Statistics routine */
+H5_DLL herr_t H5FS_stat_info(const H5FS_t *fh, H5FS_stat_t *stats);
+
+
/* Debugging routines for dumping file structures */
H5_DLL herr_t H5FS_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr,
FILE *stream, int indent, int fwidth);
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 */
diff --git a/src/H5FSstat.c b/src/H5FSstat.c
new file mode 100644
index 0000000..7b2cb0d
--- /dev/null
+++ b/src/H5FSstat.c
@@ -0,0 +1,101 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: Free-space metadata statistics functions.
+ *
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5FS_PACKAGE /*suppress error about including H5FSpkg */
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5FSpkg.h" /* Free-space manager */
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS_stat_info
+ *
+ * Purpose: Retrieve metadata statistics for the free-space manager
+ *
+ * Return: Success: non-negative
+ *
+ * Failure: does not fail
+ *
+ * Programmer: Vailin Choi
+ * August 25th, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FS_stat_info(const H5FS_t *frsp, H5FS_stat_t *stats)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_stat_info)
+
+ /* Check arguments. */
+ HDassert(frsp);
+ HDassert(stats);
+
+ /* Report statistics for free space */
+ stats->tot_space = frsp->tot_space;
+ stats->tot_sect_count = frsp->tot_sect_count;
+ stats->serial_sect_count = frsp->serial_sect_count;
+ stats->ghost_sect_count = frsp->ghost_sect_count;
+ /* can add more metadata statistics for the free-space manager */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5FS_stat_info() */
diff --git a/src/H5FStest.c b/src/H5FStest.c
new file mode 100644
index 0000000..719e553
--- /dev/null
+++ b/src/H5FStest.c
@@ -0,0 +1,154 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: Free-space manager testing functions.
+ *
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5FS_PACKAGE /*suppress error about including H5FSpkg */
+#define H5FS_TESTING /*suppress warning about H5FS testing funcs */
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5FSpkg.h" /* Free-space manager */
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_get_cparam_test
+ *
+ * Purpose: Retrieve the parameters used to create the free-space manager
+ *
+ * Return: Success: non-negative
+ *
+ * Failure: negative
+ *
+ * Programmer: similar to H5HF_get_cparam_test()
+ * Vailin Choi; August 25th, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FS_get_cparam_test(const H5FS_t *frsp, H5FS_create_t *cparam)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_get_cparam_test)
+
+ /* Check arguments. */
+ HDassert(frsp);
+ HDassert(cparam);
+
+ cparam->client = frsp->client;
+ cparam->shrink_percent = frsp->shrink_percent;
+ cparam->expand_percent = frsp->expand_percent;
+ cparam->max_sect_addr = frsp->max_sect_addr;
+ cparam->max_sect_size = frsp->max_sect_size;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5FS_get_cparam_test() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_cmp_cparam_test
+ *
+ * Purpose: Compare the parameters used to create the fractal heap
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: similar to H5HF_cmp_cparam_test()
+ * Vailin Choi; August 25th, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+H5FS_cmp_cparam_test(const H5FS_create_t *cparam1, const H5FS_create_t *cparam2)
+{
+ int ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_cmp_cparam_test)
+
+ /* Check arguments. */
+ HDassert(cparam1);
+ HDassert(cparam2);
+
+ if(cparam1->client < cparam2->client)
+ HGOTO_DONE(-1)
+ else if(cparam1->client > cparam2->client)
+ HGOTO_DONE(1)
+
+ if(cparam1->shrink_percent < cparam2->shrink_percent)
+ HGOTO_DONE(-1)
+ else if(cparam1->shrink_percent > cparam2->shrink_percent)
+ HGOTO_DONE(1)
+
+ if(cparam1->expand_percent < cparam2->expand_percent)
+ HGOTO_DONE(-1)
+ else if(cparam1->expand_percent > cparam2->expand_percent)
+ HGOTO_DONE(1)
+
+ if(cparam1->max_sect_size < cparam2->max_sect_size)
+ HGOTO_DONE(-1)
+ else if(cparam1->max_sect_size > cparam2->max_sect_size)
+ HGOTO_DONE(1)
+
+ if(cparam1->max_sect_addr < cparam2->max_sect_addr)
+ HGOTO_DONE(-1)
+ else if(cparam1->max_sect_addr > cparam2->max_sect_addr)
+ HGOTO_DONE(1)
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5FS_cmp_cparam_test */
diff --git a/src/H5Faccum.c b/src/H5Faccum.c
new file mode 100644
index 0000000..b9fe3e1
--- /dev/null
+++ b/src/H5Faccum.c
@@ -0,0 +1,655 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5Faccum.c
+ * Jan 10 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: File metadata "accumulator" routines. (Used to
+ * cache small metadata I/Os and group them into a
+ * single larger I/O)
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* File access */
+#include "H5FDprivate.h" /* File drivers */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+/* Metadata accumulator controls */
+#define H5F_ACCUM_THROTTLE 8
+#define H5F_ACCUM_THRESHOLD 2048
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Declare a PQ free list to manage the metadata accumulator buffer */
+H5FL_BLK_DEFINE_STATIC(meta_accum);
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_accum_read
+ *
+ * Purpose: Attempts to read some data from the metadata accumulator for
+ * a file into a buffer.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jan 10 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5F_accum_read(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr,
+ size_t size, void *buf/*out*/)
+{
+ htri_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5F_accum_read, FAIL)
+
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(buf);
+
+ /* Check if this information is in the metadata accumulator */
+ if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && type != H5FD_MEM_DRAW) {
+ /* Current read overlaps with metadata accumulator */
+ if(H5F_addr_overlap(addr, size, f->shared->accum.loc, f->shared->accum.size)) {
+ unsigned char *read_buf = (unsigned char *)buf; /* Pointer to the buffer being read in */
+ size_t amount_read; /* Amount to read at a time */
+ hsize_t read_off; /* Offset to read from */
+
+ /* Read the part before the metadata accumulator */
+ if(addr < f->shared->accum.loc) {
+ /* Set the amount to read */
+ H5_ASSIGN_OVERFLOW(amount_read, (f->shared->accum.loc - addr), hsize_t, size_t);
+
+ /* Dispatch to driver */
+ if(H5FD_read(f->shared->lf, dxpl_id, type, addr, amount_read, read_buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed")
+
+ /* Adjust the buffer, address & size */
+ read_buf += amount_read;
+ addr += amount_read;
+ size -= amount_read;
+ } /* end if */
+
+ /* Copy the part overlapping the metadata accumulator */
+ if(size > 0 && (addr >= f->shared->accum.loc && addr < (f->shared->accum.loc + f->shared->accum.size))) {
+ /* Set the offset to "read" from */
+ read_off = addr - f->shared->accum.loc;
+
+ /* Set the amount to "read" */
+#ifndef NDEBUG
+{
+ hsize_t tempamount_read; /* Amount to read at a time */
+
+ tempamount_read = f->shared->accum.size - read_off;
+ H5_CHECK_OVERFLOW(tempamount_read, hsize_t, size_t);
+ amount_read = MIN(size, (size_t)tempamount_read);
+}
+#else /* NDEBUG */
+ amount_read = MIN(size, (size_t)(f->shared->accum.size - read_off));
+#endif /* NDEBUG */
+
+ /* Copy the data out of the buffer */
+ HDmemcpy(read_buf, f->shared->accum.buf + read_off, amount_read);
+
+ /* Adjust the buffer, address & size */
+ read_buf += amount_read;
+ addr += amount_read;
+ size -= amount_read;
+ } /* end if */
+
+ /* Read the part after the metadata accumulator */
+ if(size > 0 && addr >= (f->shared->accum.loc + f->shared->accum.size)) {
+ /* Dispatch to driver */
+ if(H5FD_read(f->shared->lf, dxpl_id, type, addr, size, read_buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed")
+
+ /* Adjust the buffer, address & size */
+ read_buf += size;
+ addr += size;
+ size -= size;
+ } /* end if */
+
+ /* Make certain we've read it all */
+ HDassert(size == 0);
+ } /* end if */
+ /* Current read doesn't overlap with metadata accumulator, read it into accumulator */
+ else {
+ /* Only update the metadata accumulator if it is not dirty or if
+ * we are allowed to write the accumulator out during reads (when
+ * it is dirty)
+ */
+ if(f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA_READ || !f->shared->accum.dirty) {
+ /* Flush current contents, if dirty */
+ if(f->shared->accum.dirty) {
+ if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, f->shared->accum.loc, f->shared->accum.size, f->shared->accum.buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "driver write request failed")
+
+ /* Reset accumulator dirty flag */
+ f->shared->accum.dirty = FALSE;
+ } /* end if */
+
+ /* Cache the new piece of metadata */
+ /* Check if we need to resize the buffer */
+ if(size > f->shared->accum.alloc_size) {
+ /* Grow the metadata accumulator buffer */
+ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
+
+ /* Note the new buffer size */
+ f->shared->accum.alloc_size = size;
+ } /* end if */
+ else {
+ /* Check if we should shrink the accumulator buffer */
+ if(size < (f->shared->accum.alloc_size / H5F_ACCUM_THROTTLE) &&
+ f->shared->accum.alloc_size > H5F_ACCUM_THRESHOLD) {
+ size_t new_size = (f->shared->accum.alloc_size / H5F_ACCUM_THROTTLE); /* New size of accumulator buffer */
+
+ /* Shrink the accumulator buffer */
+ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, new_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
+
+ /* Note the new buffer size */
+ f->shared->accum.alloc_size = new_size;
+ } /* end if */
+ } /* end else */
+
+ /* Update accumulator information */
+ f->shared->accum.loc = addr;
+ f->shared->accum.size = size;
+ f->shared->accum.dirty = FALSE;
+
+ /* Read into accumulator */
+ if(H5FD_read(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, f->shared->accum.loc, f->shared->accum.size, f->shared->accum.buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed")
+
+ /* Copy into buffer */
+ HDmemcpy(buf, f->shared->accum.buf, size);
+ } /* end if */
+ else {
+ /* Dispatch to driver */
+ if(H5FD_read(f->shared->lf, dxpl_id, type, addr, size, buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed")
+ } /* end else */
+ } /* end else */
+
+ /* Indicate success */
+ HGOTO_DONE(TRUE);
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_accum_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_accum_write
+ *
+ * Purpose: Attempts to read some data from the metadata accumulator for
+ * a file into a buffer.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jan 10 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5F_accum_write(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr,
+ size_t size, const void *buf)
+{
+ htri_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5F_accum_write, FAIL)
+
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->intent & H5F_ACC_RDWR);
+ HDassert(buf);
+
+ /* Check for accumulating metadata */
+ if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && type != H5FD_MEM_DRAW) {
+ /* Check if there is already metadata in the accumulator */
+ if(f->shared->accum.size > 0) {
+ /* Check if the piece of metadata being written adjoins or is inside the metadata accumulator */
+ if(H5F_addr_overlap(addr, size, f->shared->accum.loc, f->shared->accum.size)) {
+ size_t new_size; /* New size of the accumulator buffer */
+ size_t old_offset; /* Offset of old data within the accumulator buffer */
+
+ /* Check if the new metadata adjoins the beginning of the current accumulator */
+ if((addr + size) == f->shared->accum.loc) {
+ /* Check if we need more buffer space */
+ if((size + f->shared->accum.size) > f->shared->accum.alloc_size) {
+ /* Adjust the buffer size, by doubling it */
+ f->shared->accum.alloc_size = MAX(f->shared->accum.alloc_size * 2, size + f->shared->accum.size);
+
+ /* Reallocate the metadata accumulator buffer */
+ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, f->shared->accum.alloc_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
+#ifdef H5_CLEAR_MEMORY
+HDmemset(f->shared->accum.buf + f->shared->accum.size, 0, (f->shared->accum.alloc_size - (f->shared->accum.size + size)));
+#endif /* H5_CLEAR_MEMORY */
+ } /* end if */
+
+ /* Move the existing metadata to the proper location */
+ HDmemmove(f->shared->accum.buf + size, f->shared->accum.buf, f->shared->accum.size);
+
+ /* Copy the new metadata at the front */
+ HDmemcpy(f->shared->accum.buf, buf, size);
+
+ /* Set the new size & location of the metadata accumulator */
+ f->shared->accum.loc = addr;
+ f->shared->accum.size += size;
+
+ /* Mark it as written to */
+ f->shared->accum.dirty = TRUE;
+ } /* end if */
+ /* Check if the new metadata adjoins the end of the current accumulator */
+ else if(addr == (f->shared->accum.loc + f->shared->accum.size)) {
+ /* Check if we need more buffer space */
+ if((size + f->shared->accum.size) > f->shared->accum.alloc_size) {
+ /* Adjust the buffer size, by doubling it */
+ f->shared->accum.alloc_size = MAX(f->shared->accum.alloc_size * 2, size + f->shared->accum.size);
+
+ /* Reallocate the metadata accumulator buffer */
+ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, f->shared->accum.alloc_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
+#ifdef H5_CLEAR_MEMORY
+HDmemset(f->shared->accum.buf + f->shared->accum.size + size, 0, (f->shared->accum.alloc_size - (f->shared->accum.size + size)));
+#endif /* H5_CLEAR_MEMORY */
+ } /* end if */
+
+ /* Copy the new metadata to the end */
+ HDmemcpy(f->shared->accum.buf + f->shared->accum.size, buf, size);
+
+ /* Set the new size of the metadata accumulator */
+ f->shared->accum.size += size;
+
+ /* Mark it as written to */
+ f->shared->accum.dirty = TRUE;
+ } /* end if */
+ /* Check if the new metadata is entirely within the current accumulator */
+ else if(addr >= f->shared->accum.loc && (addr + size) <= (f->shared->accum.loc + f->shared->accum.size)) {
+ /* Copy the new metadata to the proper location within the accumulator */
+ HDmemcpy(f->shared->accum.buf + (addr - f->shared->accum.loc), buf, size);
+
+ /* Mark it as written to */
+ f->shared->accum.dirty = TRUE;
+ } /* end if */
+ /* Check if the new metadata overlaps the beginning of the current accumulator */
+ else if(addr < f->shared->accum.loc && (addr + size) <= (f->shared->accum.loc + f->shared->accum.size)) {
+ /* Calculate the new accumulator size, based on the amount of overlap */
+ H5_ASSIGN_OVERFLOW(new_size, (f->shared->accum.loc - addr) + f->shared->accum.size, hsize_t, size_t);
+
+ /* Check if we need more buffer space */
+ if(new_size > f->shared->accum.alloc_size) {
+ /* Adjust the buffer size, by doubling it */
+ f->shared->accum.alloc_size = MAX(f->shared->accum.alloc_size + 2, new_size);
+
+ /* Reallocate the metadata accumulator buffer */
+ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, f->shared->accum.alloc_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
+#ifdef H5_CLEAR_MEMORY
+HDmemset(f->shared->accum.buf + f->shared->accum.size, 0, (f->shared->accum.alloc_size - f->shared->accum.size));
+#endif /* H5_CLEAR_MEMORY */
+ } /* end if */
+
+ /* Calculate the proper offset of the existing metadata */
+ H5_ASSIGN_OVERFLOW(old_offset, (addr + size) - f->shared->accum.loc, hsize_t, size_t);
+
+ /* Move the existing metadata to the proper location */
+ HDmemmove(f->shared->accum.buf + size, f->shared->accum.buf + old_offset, (f->shared->accum.size - old_offset));
+
+ /* Copy the new metadata at the front */
+ HDmemcpy(f->shared->accum.buf, buf, size);
+
+ /* Set the new size & location of the metadata accumulator */
+ f->shared->accum.loc = addr;
+ f->shared->accum.size = new_size;
+
+ /* Mark it as written to */
+ f->shared->accum.dirty = TRUE;
+ } /* end if */
+ /* Check if the new metadata overlaps the end of the current accumulator */
+ else if(addr >= f->shared->accum.loc && (addr + size) > (f->shared->accum.loc + f->shared->accum.size)) {
+ /* Calculate the new accumulator size, based on the amount of overlap */
+ H5_ASSIGN_OVERFLOW(new_size, (addr - f->shared->accum.loc) + size, hsize_t, size_t);
+
+ /* Check if we need more buffer space */
+ if(new_size > f->shared->accum.alloc_size) {
+ /* Adjust the buffer size, by doubling it */
+ f->shared->accum.alloc_size = MAX(f->shared->accum.alloc_size * 2, new_size);
+
+ /* Reallocate the metadata accumulator buffer */
+ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, f->shared->accum.alloc_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
+#ifdef H5_CLEAR_MEMORY
+HDmemset(f->shared->accum.buf + f->shared->accum.size, 0, (f->shared->accum.alloc_size - f->shared->accum.size));
+#endif /* H5_CLEAR_MEMORY */
+ } /* end if */
+
+ /* Copy the new metadata to the end */
+ HDmemcpy(f->shared->accum.buf + (addr - f->shared->accum.loc), buf, size);
+
+ /* Set the new size & location of the metadata accumulator */
+ f->shared->accum.size = new_size;
+
+ /* Mark it as written to */
+ f->shared->accum.dirty = TRUE;
+ } /* end if */
+ else {
+ HDassert(0 && "New metadata overlapped both beginning and end of existing metadata accumulator!");
+ } /* end else */
+ } /* end if */
+ /* New piece of metadata doesn't adjoin or overlap the existing accumulator */
+ else {
+ /* Write out the existing metadata accumulator, with dispatch to driver */
+ if(f->shared->accum.dirty) {
+ if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, f->shared->accum.loc, f->shared->accum.size, f->shared->accum.buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
+
+ /* Reset accumulator dirty flag */
+ f->shared->accum.dirty = FALSE;
+ } /* end if */
+
+ /* Cache the new piece of metadata */
+ /* Check if we need to resize the buffer */
+ if(size > f->shared->accum.alloc_size) {
+ /* Grow the metadata accumulator buffer */
+ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
+
+ /* Note the new buffer size */
+ f->shared->accum.alloc_size = size;
+#ifdef H5_CLEAR_MEMORY
+{
+size_t clear_size = MAX(f->shared->accum.size, size);
+HDmemset(f->shared->accum.buf + clear_size, 0, (f->shared->accum.alloc_size - clear_size));
+}
+#endif /* H5_CLEAR_MEMORY */
+ } /* end if */
+ else {
+ /* Check if we should shrink the accumulator buffer */
+ if(size < (f->shared->accum.alloc_size / H5F_ACCUM_THROTTLE) &&
+ f->shared->accum.alloc_size > H5F_ACCUM_THRESHOLD) {
+ size_t tmp_size = (f->shared->accum.alloc_size / H5F_ACCUM_THROTTLE); /* New size of accumulator buffer */
+
+ /* Shrink the accumulator buffer */
+ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, tmp_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
+
+ /* Note the new buffer size */
+ f->shared->accum.alloc_size = tmp_size;
+ } /* end if */
+ } /* end else */
+
+ /* Update the metadata accumulator information */
+ f->shared->accum.loc = addr;
+ f->shared->accum.size = size;
+ f->shared->accum.dirty = TRUE;
+
+ /* Store the piece of metadata in the accumulator */
+ HDmemcpy(f->shared->accum.buf, buf, size);
+ } /* end else */
+ } /* end if */
+ /* No metadata in the accumulator, grab this piece and keep it */
+ else {
+ /* Check if we need to reallocate the buffer */
+ if(size > f->shared->accum.alloc_size) {
+ /* Reallocate the metadata accumulator buffer */
+ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
+
+ /* Note the new buffer size */
+ f->shared->accum.alloc_size = size;
+ } /* end if */
+
+ /* Update the metadata accumulator information */
+ f->shared->accum.loc = addr;
+ f->shared->accum.size = size;
+ f->shared->accum.dirty = TRUE;
+
+ /* Store the piece of metadata in the accumulator */
+ HDmemcpy(f->shared->accum.buf, buf, size);
+ } /* end else */
+
+ /* Indicate success */
+ HGOTO_DONE(TRUE);
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_accum_write() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_accum_free
+ *
+ * Purpose: Check for free space invalidating [part of] a metadata
+ * accumulator.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jan 10 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_accum_free(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr,
+ hsize_t size)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5F_accum_free, FAIL)
+
+ /* check arguments */
+ HDassert(f);
+
+ /* Adjust the metadata accumulator to remove the freed block, if it overlaps */
+ if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA)
+ && H5F_addr_overlap(addr, size, f->shared->accum.loc, f->shared->accum.size)) {
+ size_t overlap_size; /* Size of overlap with accumulator */
+
+ /* Sanity check */
+ /* (The metadata accumulator should not intersect w/raw data */
+ HDassert(H5FD_MEM_DRAW != type);
+
+ /* Check for overlapping the beginning of the accumulator */
+ if(H5F_addr_le(addr, f->shared->accum.loc)) {
+ /* Check for completely overlapping the accumulator */
+ if(H5F_addr_ge(addr + size, f->shared->accum.loc + f->shared->accum.size)) {
+ /* Reset the accumulator, but don't free buffer */
+ f->shared->accum.loc = HADDR_UNDEF;
+ f->shared->accum.size = 0;
+ f->shared->accum.dirty = FALSE;
+ } /* end if */
+ /* Block to free must end within the accumulator */
+ else {
+ size_t new_accum_size; /* Size of new accumulator buffer */
+
+ /* Calculate the size of the overlap with the accumulator, etc. */
+ H5_ASSIGN_OVERFLOW(overlap_size, (addr + size) - f->shared->accum.loc, haddr_t, size_t);
+ new_accum_size = f->shared->accum.size - overlap_size;
+
+ /* Move the accumulator buffer information to eliminate the freed block */
+ HDmemmove(f->shared->accum.buf, f->shared->accum.buf + overlap_size, new_accum_size);
+
+ /* Adjust the accumulator information */
+ f->shared->accum.loc += overlap_size;
+ f->shared->accum.size = new_accum_size;
+ } /* end else */
+ } /* end if */
+ /* Block to free must start within the accumulator */
+ else {
+ /* Calculate the size of the overlap with the accumulator */
+ H5_ASSIGN_OVERFLOW(overlap_size, (f->shared->accum.loc + f->shared->accum.size) - addr, haddr_t, size_t);
+
+ /* Block to free is in the middle of the accumulator */
+ if(H5F_addr_lt((addr + size), f->shared->accum.loc + f->shared->accum.size)) {
+ haddr_t tail_addr;
+ size_t tail_size;
+
+ /* Calculate the address & size of the tail to write */
+ tail_addr = addr + size;
+ H5_ASSIGN_OVERFLOW(tail_size, (f->shared->accum.loc + f->shared->accum.size) - tail_addr, haddr_t, size_t);
+
+ /* Write out the part of the accumulator after the block to free */
+ if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, tail_addr, tail_size, f->shared->accum.buf + (tail_addr - f->shared->accum.loc)) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
+ } /* end if */
+
+ /* Adjust the accumulator information */
+ f->shared->accum.size = f->shared->accum.size - overlap_size;
+ } /* end else */
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_accum_free() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_accum_flush
+ *
+ * Purpose: Flush the metadata accumulator to the file
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jan 10 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_accum_flush(H5F_t *f, hid_t dxpl_id)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5F_accum_flush, FAIL)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ /* Check if we need to flush out the metadata accumulator */
+ if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && f->shared->accum.dirty && f->shared->accum.size > 0) {
+ /* Flush the metadata contents */
+ if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, f->shared->accum.loc, f->shared->accum.size, f->shared->accum.buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
+
+ /* Reset the dirty flag */
+ f->shared->accum.dirty = FALSE;
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_accum_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_accum_reset
+ *
+ * Purpose: Reset the metadata accumulator for the file
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jan 10 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_accum_reset(H5F_t *f)
+{
+ FUNC_ENTER_NOAPI_NOFUNC(H5F_accum_reset)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ /* Check if we need to reset the metadata accumulator information */
+ if(f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) {
+ /* Sanity check */
+ HDassert(!f->closing || FALSE == f->shared->accum.dirty);
+
+ /* Free the buffer */
+ if(f->shared->accum.buf)
+ f->shared->accum.buf = H5FL_BLK_FREE(meta_accum, f->shared->accum.buf);
+
+ /* Reset the buffer sizes & location */
+ f->shared->accum.alloc_size = f->shared->accum.size = 0;
+ f->shared->accum.loc = HADDR_UNDEF;
+ f->shared->accum.dirty = FALSE;
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5F_accum_reset() */
+
+
diff --git a/src/H5Fdbg.c b/src/H5Fdbg.c
index 9d4e6e9..e05c32a 100644
--- a/src/H5Fdbg.c
+++ b/src/H5Fdbg.c
@@ -82,7 +82,7 @@ H5F_debug(H5F_t *f, FILE *stream, int indent, int fwidth)
HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
"File open reference count:", f->shared->nrefs);
HDfprintf(stream, "%*s%-*s %a (abs)\n", indent, "", fwidth,
- "Address of super block:", f->shared->super_addr);
+ "Address of super block:", f->shared->base_addr);
HDfprintf(stream, "%*s%-*s %Hu bytes\n", indent, "", fwidth,
"Size of userblock:", userblock_size);
@@ -107,8 +107,6 @@ H5F_debug(H5F_t *f, FILE *stream, int indent, int fwidth)
"Symbol table internal node 1/2 rank:", f->shared->btree_k[H5B_SNODE_ID]);
HDfprintf(stream, "%*s%-*s 0x%02x\n", indent, "", fwidth,
"File status flags:", (unsigned)(f->shared->status_flags));
- HDfprintf(stream, "%*s%-*s %a (abs)\n", indent, "", fwidth,
- "Base address:", f->shared->base_addr);
HDfprintf(stream, "%*s%-*s %a (rel)\n", indent, "", fwidth,
"Superblock extension address:", f->shared->extension_addr);
HDfprintf(stream, "%*s%-*s %a (rel)\n", indent, "", fwidth,
diff --git a/src/H5Fio.c b/src/H5Fio.c
new file mode 100644
index 0000000..1081a27
--- /dev/null
+++ b/src/H5Fio.c
@@ -0,0 +1,165 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5Fio.c
+ * Jan 10 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: File I/O routines.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* File access */
+#include "H5FDprivate.h" /* File drivers */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_block_read
+ *
+ * Purpose: Reads some data from a file/server/etc into a buffer.
+ * The data is contiguous. The address is relative to the base
+ * address for the file.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jul 10 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_block_read(const H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
+ hid_t dxpl_id, void *buf/*out*/)
+{
+ htri_t accumulated; /* Whether the data was accepted by the metadata accumulator */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5F_block_read, FAIL)
+
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(buf);
+
+ /* Check if this I/O can be satisfied by the metadata accumulator */
+ if((accumulated = H5F_accum_read(f, dxpl_id, type, addr, size, buf)) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "read from metadata accumulator failed")
+ else if(accumulated == FALSE) {
+ /* Read the data */
+ if(H5FD_read(f->shared->lf, dxpl_id, type, addr, size, buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed")
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_block_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_block_write
+ *
+ * Purpose: Writes some data from memory to a file/server/etc. The
+ * data is contiguous. The address is relative to the base
+ * address.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jul 10 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_block_write(const H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
+ hid_t dxpl_id, const void *buf)
+{
+ htri_t accumulated; /* Whether the data was accepted by the metadata accumulator */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5F_block_write, FAIL)
+#ifdef QAK
+HDfprintf(stderr, "%s: write to addr = %a, size = %Zu\n", FUNC, addr, size);
+#endif /* QAK */
+
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->intent & H5F_ACC_RDWR);
+ HDassert(buf);
+
+ /* Check for accumulating metadata */
+ if((accumulated = H5F_accum_write(f, dxpl_id, type, addr, size, buf)) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "write to metadata accumulator failed")
+ else if(accumulated == FALSE) {
+ /* Write the data */
+ if(H5FD_write(f->shared->lf, dxpl_id, type, addr, size, buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_block_write() */
+
diff --git a/src/H5Fmpi.c b/src/H5Fmpi.c
new file mode 100644
index 0000000..c90ad7c
--- /dev/null
+++ b/src/H5Fmpi.c
@@ -0,0 +1,181 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5Fmpi.c
+ * Jan 10 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: MPI-related routines.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* File access */
+#include "H5FDmpi.h" /* MPI-based file drivers */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+#ifdef H5_HAVE_PARALLEL
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_mpi_get_rank
+ *
+ * Purpose: Retrieves the rank of an MPI process.
+ *
+ * Return: Success: The rank (non-negative)
+ *
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Friday, January 30, 2004
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+H5F_mpi_get_rank(const H5F_t *f)
+{
+ int ret_value;
+
+ FUNC_ENTER_NOAPI(H5F_mpi_get_rank, FAIL)
+
+ assert(f && f->shared);
+
+ /* Dispatch to driver */
+ if ((ret_value=H5FD_mpi_get_rank(f->shared->lf)) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "driver get_rank request failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_mpi_get_rank() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_mpi_get_comm
+ *
+ * Purpose: Retrieves the file's communicator
+ *
+ * Return: Success: The communicator (non-negative)
+ *
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Friday, January 30, 2004
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+MPI_Comm
+H5F_mpi_get_comm(const H5F_t *f)
+{
+ MPI_Comm ret_value;
+
+ FUNC_ENTER_NOAPI(H5F_mpi_get_comm, MPI_COMM_NULL)
+
+ assert(f && f->shared);
+
+ /* Dispatch to driver */
+ if ((ret_value=H5FD_mpi_get_comm(f->shared->lf))==MPI_COMM_NULL)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTGET, MPI_COMM_NULL, "driver get_comm request failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_mpi_get_comm() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_mpi_get_size
+ *
+ * Purpose: Retrieves the size of an MPI process.
+ *
+ * Return: Success: The size (positive)
+ *
+ * Failure: Negative
+ *
+ * Programmer: John Mainzer
+ * Friday, May 6, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+H5F_mpi_get_size(const H5F_t *f)
+{
+ int ret_value;
+
+ FUNC_ENTER_NOAPI(H5F_mpi_get_size, FAIL)
+
+ assert(f && f->shared);
+
+ /* Dispatch to driver */
+ if ((ret_value=H5FD_mpi_get_size(f->shared->lf)) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "driver get_size request failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_mpi_get_size() */
+#endif /* H5_HAVE_PARALLEL */
+
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index 594ed50..428b58d 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -38,6 +38,7 @@
#include "H5private.h" /* Generic Functions */
#include "H5FLprivate.h" /* Free Lists */
#include "H5FOprivate.h" /* File objects */
+#include "H5FSprivate.h" /* File free space */
#include "H5Gprivate.h" /* Groups */
#include "H5Oprivate.h" /* Object header messages */
#include "H5RCprivate.h" /* Reference counted object functions */
@@ -62,6 +63,35 @@
/* Mask for removing private file access flags */
#define H5F_ACC_PUBLIC_FLAGS 0x00ffu
+/* Free space section+aggregator merge flags */
+#define H5F_FS_MERGE_METADATA 0x01 /* Section can merge with metadata aggregator */
+#define H5F_FS_MERGE_RAWDATA 0x02 /* Section can merge with small 'raw' data aggregator */
+
+/* Structure for metadata & "small [raw] data" block aggregation fields */
+struct H5F_blk_aggr_t {
+ unsigned long feature_flag; /* Feature flag type */
+ hsize_t alloc_size; /* Size for allocating new blocks */
+ hsize_t tot_size; /* Total amount of bytes aggregated into block */
+ hsize_t size; /* Current size of block left */
+ haddr_t addr; /* Location of block left */
+};
+
+/* Structure for metadata accumulator fields */
+typedef struct H5F_meta_accum_t {
+ unsigned char *buf; /* Buffer to hold the accumulated metadata */
+ haddr_t loc; /* File location (offset) of the accumulated metadata */
+ size_t size; /* Size of the accumulated metadata buffer used (in bytes) */
+ size_t alloc_size; /* Size of the accumulated metadata buffer allocated (in bytes) */
+ hbool_t dirty; /* Flag to indicate that the accumulated metadata is dirty */
+} H5F_meta_accum_t;
+
+/* Enum for free space manager state */
+typedef enum H5F_fs_state_t {
+ H5F_FS_STATE_CLOSED, /* Free space manager is closed */
+ H5F_FS_STATE_OPEN, /* Free space manager has been opened */
+ H5F_FS_STATE_DELETING /* Free space manager is being deleted */
+} H5F_fs_state_t;
+
/* A record of the mount table */
typedef struct H5F_mount_t {
struct H5G_t *group; /* Mount point group held open */
@@ -97,13 +127,14 @@ typedef struct H5F_file_t {
unsigned btree_k[H5B_NUM_BTREE_ID]; /* B-tree key values for each type */
size_t sizeof_addr; /* Size of addresses in file */
size_t sizeof_size; /* Size of offsets in file */
- haddr_t super_addr; /* Absolute address of super block */
haddr_t base_addr; /* Absolute base address for rel.addrs. */
+ /* (superblock for file is at this offset) */
haddr_t extension_addr; /* Relative address of superblock extension */
haddr_t sohm_addr; /* Relative address of shared object header message table */
unsigned sohm_vers; /* Version of shared message table on disk */
unsigned sohm_nindexes; /* Number of shared messages indexes in the table */
haddr_t driver_addr; /* File driver information block address*/
+ unsigned long feature_flags; /* VFL Driver feature Flags */
haddr_t maxaddr; /* Maximum address for file */
H5AC_t *cache; /* The object cache */
@@ -129,6 +160,20 @@ typedef struct H5F_file_t {
struct H5G_t *root_grp; /* Open root group */
H5FO_t *open_objs; /* Open objects in file */
H5RC_t *grp_btree_shared; /* Ref-counted group B-tree node info */
+
+ /* File space allocation information */
+ unsigned fs_aggr_merge[H5FD_MEM_NTYPES]; /* Flags for whether free space can merge with aggregator(s) */
+ H5F_fs_state_t fs_state[H5FD_MEM_NTYPES]; /* State of free space manager for each type */
+ haddr_t fs_addr[H5FD_MEM_NTYPES]; /* Address of free space manager info for each type */
+ H5FS_t *fs_man[H5FD_MEM_NTYPES]; /* Free space manager for each file space type */
+ H5FD_mem_t fs_type_map[H5FD_MEM_NTYPES]; /* Mapping of "real" file space type into tracked type */
+ H5F_blk_aggr_t meta_aggr; /* Metadata aggregation info */
+ /* (if aggregating metadata allocations) */
+ H5F_blk_aggr_t sdata_aggr; /* "Small data" aggregation info */
+ /* (if aggregating "small data" allocations) */
+
+ /* Metadata accumulator information */
+ H5F_meta_accum_t accum; /* Metadata accumulator info */
} H5F_file_t;
/*
@@ -182,6 +227,15 @@ H5_DLL herr_t H5F_super_write(H5F_t *f, hid_t dxpl_id);
H5_DLL herr_t H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc);
H5_DLL herr_t H5F_super_ext_size(H5F_t *f, hid_t dxpl_id, hsize_t *super_ext_info);
+/* Metadata accumulator routines */
+H5_DLL htri_t H5F_accum_read(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type,
+ haddr_t addr, size_t size, void *buf);
+H5_DLL htri_t H5F_accum_write(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type,
+ haddr_t addr, size_t size, const void *buf);
+H5_DLL herr_t H5F_accum_free(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type,
+ haddr_t addr, hsize_t size);
+H5_DLL herr_t H5F_accum_flush(H5F_t *f, hid_t dxpl_id);
+H5_DLL herr_t H5F_accum_reset(H5F_t *f);
/* Shared file list related routines */
H5_DLL herr_t H5F_sfile_add(H5F_file_t *shared);
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index d975167..7791296 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -35,6 +35,9 @@
/* Main file structure */
typedef struct H5F_t H5F_t;
+/* Block aggregation structure */
+typedef struct H5F_blk_aggr_t H5F_blk_aggr_t;
+
/*===----------------------------------------------------------------------===
* Flush Flags
*===----------------------------------------------------------------------===
@@ -214,7 +217,7 @@ typedef struct H5F_t H5F_t;
HADDR_UNDEF==(X)+(haddr_t)(Z) || \
(X)+(haddr_t)(Z)<(X))
#define H5F_addr_hash(X,M) ((unsigned)((X)%(M)))
-#define H5F_addr_defined(X) (X!=HADDR_UNDEF)
+#define H5F_addr_defined(X) ((X)!=HADDR_UNDEF)
/* The H5F_addr_eq() macro guarantees that Y is not HADDR_UNDEF by making
* certain that X is not HADDR_UNDEF and then checking that X equals Y
*/
@@ -233,43 +236,36 @@ typedef struct H5F_t H5F_t;
#define H5F_addr_ge(X,Y) ((X)!=HADDR_UNDEF && \
(Y)!=HADDR_UNDEF && \
(X)>=(Y))
-#define H5F_addr_cmp(X,Y) (H5F_addr_eq(X,Y)?0: \
- (H5F_addr_lt(X, Y)?-1:1))
+#define H5F_addr_cmp(X,Y) (H5F_addr_eq((X), (Y)) ? 0 : \
+ (H5F_addr_lt((X), (Y)) ? -1 : 1))
#define H5F_addr_pow2(N) ((haddr_t)1<<(N))
-#define H5F_addr_overlap(O1,L1,O2,L2) ((O1<O2 && (O1+L1)>O2) || \
- (O1>=O2 && O1<(O2+L2)))
+#define H5F_addr_overlap(O1,L1,O2,L2) (((O1) < (O2) && ((O1) + (L1)) > (O2)) || \
+ ((O1) >= (O2) && (O1) < ((O2) + (L2))))
/* If the module using this macro is allowed access to the private variables, access them directly */
#ifdef H5F_PACKAGE
-/* The FCPL itself */
+#define H5F_INTENT(F) ((F)->intent)
#define H5F_FCPL(F) ((F)->shared->fcpl_id)
-/* size of size_t and off_t as they exist on disk */
#define H5F_SIZEOF_ADDR(F) ((F)->shared->sizeof_addr)
#define H5F_SIZEOF_SIZE(F) ((F)->shared->sizeof_size)
-/* Size of symbol table leafs */
#define H5F_SYM_LEAF_K(F) ((F)->shared->sym_leaf_k)
-/* B-tree key value size */
#define H5F_KVALUE(F,T) ((F)->shared->btree_k[(T)->id])
-/* Raw data cache values */
#define H5F_RDCC_NELMTS(F) ((F)->shared->rdcc_nelmts)
#define H5F_RDCC_NBYTES(F) ((F)->shared->rdcc_nbytes)
#define H5F_RDCC_W0(F) ((F)->shared->rdcc_w0)
-/* Check for file driver feature enabled */
-#define H5F_HAS_FEATURE(F,FL) ((F)->shared->lf->feature_flags & (FL))
-/* B-tree node raw page */
-#define H5F_GRP_BTREE_SHARED(F) ((F)->shared->grp_btree_shared)
-/* Base address of file */
#define H5F_BASE_ADDR(F) ((F)->shared->base_addr)
-/* Sieve buffer size for datasets */
+#define H5F_GRP_BTREE_SHARED(F) ((F)->shared->grp_btree_shared)
#define H5F_SIEVE_BUF_SIZE(F) ((F)->shared->sieve_buf_size)
#define H5F_GC_REF(F) ((F)->shared->gc_ref)
#define H5F_USE_LATEST_FORMAT(F) ((F)->shared->latest_format)
-#define H5F_INTENT(F) ((F)->intent)
#define H5F_EXTPATH(F) ((F)->extpath)
#define H5F_GET_FC_DEGREE(F) ((F)->shared->fc_degree)
#define H5F_STORE_MSG_CRT_IDX(F) ((F)->shared->store_msg_crt_idx)
+#define H5F_HAS_FEATURE(F,FL) ((F)->shared->lf->feature_flags & (FL))
+#define H5F_DRIVER_ID(F) ((F)->shared->lf->driver_id)
#define H5F_GET_FILENO(F,FILENUM) ((FILENUM) = (F)->shared->lf->fileno)
#else /* H5F_PACKAGE */
+#define H5F_INTENT(F) (H5F_get_intent(F))
#define H5F_FCPL(F) (H5F_get_fcpl(F))
#define H5F_SIZEOF_ADDR(F) (H5F_sizeof_addr(F))
#define H5F_SIZEOF_SIZE(F) (H5F_sizeof_size(F))
@@ -278,17 +274,17 @@ typedef struct H5F_t H5F_t;
#define H5F_RDCC_NELMTS(F) (H5F_rdcc_nelmts(F))
#define H5F_RDCC_NBYTES(F) (H5F_rdcc_nbytes(F))
#define H5F_RDCC_W0(F) (H5F_rdcc_w0(F))
-#define H5F_HAS_FEATURE(F,FL) (H5F_has_feature(F,FL))
-#define H5F_GRP_BTREE_SHARED(F) (H5F_grp_btree_shared(F))
#define H5F_BASE_ADDR(F) (H5F_get_base_addr(F))
+#define H5F_GRP_BTREE_SHARED(F) (H5F_grp_btree_shared(F))
#define H5F_SIEVE_BUF_SIZE(F) (H5F_sieve_buf_size(F))
#define H5F_GC_REF(F) (H5F_gc_ref(F))
#define H5F_USE_LATEST_FORMAT(F) (H5F_use_latest_format(F))
-#define H5F_INTENT(F) (H5F_get_intent(F))
#define H5F_EXTPATH(F) (H5F_get_extpath(F))
#define H5F_GET_FC_DEGREE(F) (H5F_get_fc_degree(F))
-#define H5F_STORE_MSG_CRT_IDX(F) (H5F_store_msg_crt_idx(F))
-#define H5F_GET_FILENO(F,FILENUM) (H5F_get_filenum((F), &(FILENUM)))
+#define H5F_STORE_MSG_CRT_IDX(F) (H5F_store_msg_crt_idx(F))
+#define H5F_HAS_FEATURE(F,FL) (H5F_has_feature(F,FL))
+#define H5F_DRIVER_ID(F) (H5F_get_driver_id(F))
+#define H5F_GET_FILENO(F,FILENUM) (H5F_get_fileno((F), &(FILENUM)))
#endif /* H5F_PACKAGE */
@@ -463,39 +459,27 @@ struct H5RC_t;
H5_DLL H5F_t *H5F_open(const char *name, unsigned flags, hid_t fcpl_id,
hid_t fapl_id, hid_t dxpl_id);
H5_DLL herr_t H5F_try_close(H5F_t *f);
+H5_DLL unsigned H5F_incr_nopen_objs(H5F_t *f);
+H5_DLL unsigned H5F_decr_nopen_objs(H5F_t *f);
/* Functions than retrieve values from the file struct */
-H5_DLL hid_t H5F_get_driver_id(const H5F_t *f);
-H5_DLL hid_t H5F_get_access_plist(H5F_t *f, hbool_t app_ref);
H5_DLL unsigned H5F_get_intent(const H5F_t *f);
+H5_DLL hid_t H5F_get_access_plist(H5F_t *f, hbool_t app_ref);
H5_DLL char *H5F_get_extpath(const H5F_t *f);
-H5_DLL herr_t H5F_get_fileno(const H5F_t *f, unsigned long *filenum);
H5_DLL hid_t H5F_get_id(H5F_t *file, hbool_t app_ref);
H5_DLL size_t H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref);
H5_DLL size_t H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *obj_id_list, hbool_t app_ref);
-H5_DLL haddr_t H5F_get_base_addr(const H5F_t *f);
-H5_DLL haddr_t H5F_get_eoa(const H5F_t *f);
-#ifdef H5_HAVE_PARALLEL
-H5_DLL int H5F_mpi_get_rank(const H5F_t *f);
-H5_DLL MPI_Comm H5F_mpi_get_comm(const H5F_t *f);
-H5_DLL int H5F_mpi_get_size(const H5F_t *f);
-#endif /* H5_HAVE_PARALLEL */
-H5_DLL unsigned H5F_incr_nopen_objs(H5F_t *f);
-H5_DLL unsigned H5F_decr_nopen_objs(H5F_t *f);
-/* Functions than check file mounting information */
-H5_DLL hbool_t H5F_is_mount(const H5F_t *file);
-
-/* Functions than retrieve values set from the FCPL */
+/* Functions than retrieve values set/cached from the superblock/FCPL */
H5_DLL hid_t H5F_get_fcpl(const H5F_t *f);
H5_DLL size_t H5F_sizeof_addr(const H5F_t *f);
H5_DLL size_t H5F_sizeof_size(const H5F_t *f);
H5_DLL unsigned H5F_sym_leaf_k(const H5F_t *f);
H5_DLL unsigned H5F_Kvalue(const H5F_t *f, const struct H5B_class_t *type);
-H5_DLL hbool_t H5F_has_feature(const H5F_t *f, unsigned feature);
H5_DLL size_t H5F_rdcc_nbytes(const H5F_t *f);
H5_DLL size_t H5F_rdcc_nelmts(const H5F_t *f);
H5_DLL double H5F_rdcc_w0(const H5F_t *f);
+H5_DLL haddr_t H5F_get_base_addr(const H5F_t *f);
H5_DLL struct H5RC_t *H5F_grp_btree_shared(const H5F_t *f);
H5_DLL size_t H5F_sieve_buf_size(const H5F_t *f);
H5_DLL unsigned H5F_gc_ref(const H5F_t *f);
@@ -503,6 +487,16 @@ H5_DLL hbool_t H5F_use_latest_format(const H5F_t *f);
H5_DLL H5F_close_degree_t H5F_get_fc_degree(const H5F_t *f);
H5_DLL hbool_t H5F_store_msg_crt_idx(const H5F_t *f);
+/* Functions that retrieve values from VFD layer */
+H5_DLL hbool_t H5F_has_feature(const H5F_t *f, unsigned feature);
+H5_DLL hid_t H5F_get_driver_id(const H5F_t *f);
+H5_DLL herr_t H5F_get_fileno(const H5F_t *f, unsigned long *filenum);
+H5_DLL haddr_t H5F_get_eoa(const H5F_t *f, H5FD_mem_t type);
+
+/* Functions than check file mounting information */
+H5_DLL hbool_t H5F_is_mount(const H5F_t *file);
+H5_DLL hbool_t H5F_has_mount(const H5F_t *file);
+
/* Functions that operate on blocks of bytes wrt super block */
H5_DLL herr_t H5F_block_read(const H5F_t *f, H5FD_mem_t type, haddr_t addr,
size_t size, hid_t dxpl_id, void *buf/*out*/);
@@ -524,6 +518,13 @@ H5_DLL herr_t H5F_sfile_assert_num(unsigned n);
H5_DLL H5F_t *H5F_fake_alloc(size_t sizeof_size);
H5_DLL herr_t H5F_fake_free(H5F_t *f);
+/* Parallel I/O (i.e. MPI) related routines */
+#ifdef H5_HAVE_PARALLEL
+H5_DLL int H5F_mpi_get_rank(const H5F_t *f);
+H5_DLL MPI_Comm H5F_mpi_get_comm(const H5F_t *f);
+H5_DLL int H5F_mpi_get_size(const H5F_t *f);
+#endif /* H5_HAVE_PARALLEL */
+
/* Debugging functions */
H5_DLL herr_t H5F_debug(H5F_t *f, FILE * stream, int indent, int fwidth);
diff --git a/src/H5Fquery.c b/src/H5Fquery.c
new file mode 100644
index 0000000..3b93fb5
--- /dev/null
+++ b/src/H5Fquery.c
@@ -0,0 +1,663 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5Fquery.c
+ * Jan 10 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: File structure query routines.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* File access */
+#include "H5FDprivate.h" /* File drivers */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_get_intent
+ *
+ * Purpose: Quick and dirty routine to retrieve the file's 'intent' flags
+ * (Mainly added to stop non-file routines from poking about in the
+ * H5F_t data structure)
+ *
+ * Return: 'intent' on success/abort on failure (shouldn't fail)
+ *
+ * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
+ * September 29, 2000
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+H5F_get_intent(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_intent)
+
+ HDassert(f);
+
+ FUNC_LEAVE_NOAPI(f->intent)
+} /* end H5F_get_intent() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_get_extpath
+ *
+ * Purpose: Retrieve the file's 'extpath' flags
+ * This is used by H5L_extern_traverse() to retrieve the main file's location
+ * when searching the target file.
+ *
+ * Return: 'extpath' on success/abort on failure (shouldn't fail)
+ *
+ * Programmer: Vailin Choi, April 2, 2008
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+char *
+H5F_get_extpath(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_extpath)
+
+ HDassert(f);
+
+ FUNC_LEAVE_NOAPI(f->extpath)
+} /* end H5F_get_extpath() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_get_fcpl
+ *
+ * Purpose: Retrieve the value of a file's FCPL.
+ *
+ * Return: Success: The FCPL for the file.
+ *
+ * Failure: ? (should not happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 25 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5F_get_fcpl(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_fcpl)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->fcpl_id)
+} /* end H5F_get_fcpl() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_sizeof_addr
+ *
+ * Purpose: Quick and dirty routine to retrieve the size of the file's size_t
+ * (Mainly added to stop non-file routines from poking about in the
+ * H5F_t data structure)
+ *
+ * Return: 'sizeof_addr' on success/abort on failure (shouldn't fail)
+ *
+ * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
+ * September 29, 2000
+ *
+ *-------------------------------------------------------------------------
+ */
+size_t
+H5F_sizeof_addr(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sizeof_addr)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->sizeof_addr)
+} /* end H5F_sizeof_addr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_sizeof_size
+ *
+ * Purpose: Quick and dirty routine to retrieve the size of the file's off_t
+ * (Mainly added to stop non-file routines from poking about in the
+ * H5F_t data structure)
+ *
+ * Return: 'sizeof_size' on success/abort on failure (shouldn't fail)
+ *
+ * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
+ * September 29, 2000
+ *
+ *-------------------------------------------------------------------------
+ */
+size_t
+H5F_sizeof_size(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sizeof_size)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->sizeof_size)
+} /* H5F_sizeof_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_sym_leaf_k
+ *
+ * Purpose: Replaced a macro to retrieve the symbol table leaf size,
+ * now that the generic properties are being used to store
+ * the values.
+ *
+ * Return: Success: Non-negative, and the symbol table leaf size is
+ * returned.
+ *
+ * Failure: Negative (should not happen)
+ *
+ * Programmer: Raymond Lu
+ * slu@ncsa.uiuc.edu
+ * Oct 14 2001
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+H5F_sym_leaf_k(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sym_leaf_k)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->sym_leaf_k)
+} /* end H5F_sym_leaf_k() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_Kvalue
+ *
+ * Purpose: Replaced a macro to retrieve a B-tree key value for a certain
+ * type, now that the generic properties are being used to store
+ * the B-tree values.
+ *
+ * Return: Success: Non-negative, and the B-tree key value is
+ * returned.
+ *
+ * Failure: Negative (should not happen)
+ *
+ * Programmer: Raymond Lu
+ * slu@ncsa.uiuc.edu
+ * Oct 14 2001
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+H5F_Kvalue(const H5F_t *f, const H5B_class_t *type)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_Kvalue)
+
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(type);
+
+ FUNC_LEAVE_NOAPI(f->shared->btree_k[type->id])
+} /* end H5F_Kvalue() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_rdcc_nelmts
+ *
+ * Purpose: Replaced a macro to retrieve the raw data cache number of elments,
+ * now that the generic properties are being used to store
+ * the values.
+ *
+ * Return: Success: Non-negative, and the raw data cache number of
+ * of elemnts is returned.
+ *
+ * Failure: Negative (should not happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Jun 1 2004
+ *
+ *-------------------------------------------------------------------------
+ */
+size_t
+H5F_rdcc_nelmts(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_rdcc_nelmts)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->rdcc_nelmts)
+} /* end H5F_rdcc_nelmts() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_rdcc_nbytes
+ *
+ * Purpose: Replaced a macro to retrieve the raw data cache number of bytes,
+ * now that the generic properties are being used to store
+ * the values.
+ *
+ * Return: Success: Non-negative, and the raw data cache number of
+ * of bytes is returned.
+ *
+ * Failure: Negative (should not happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Jun 1 2004
+ *
+ *-------------------------------------------------------------------------
+ */
+size_t
+H5F_rdcc_nbytes(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_rdcc_nbytes)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->rdcc_nbytes)
+} /* end H5F_rdcc_nbytes() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_rdcc_w0
+ *
+ * Purpose: Replaced a macro to retrieve the raw data cache 'w0' value
+ * now that the generic properties are being used to store
+ * the values.
+ *
+ * Return: Success: Non-negative, and the raw data cache 'w0' value
+ * is returned.
+ *
+ * Failure: Negative (should not happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Jun 2 2004
+ *
+ *-------------------------------------------------------------------------
+ */
+double
+H5F_rdcc_w0(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_rdcc_w0)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->rdcc_w0)
+} /* end H5F_rdcc_w0() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_get_base_addr
+ *
+ * Purpose: Quick and dirty routine to retrieve the file's 'base_addr' value
+ * (Mainly added to stop non-file routines from poking about in the
+ * H5F_t data structure)
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Raymond Lu <slu@ncsa.uiuc.edu>
+ * December 20, 2002
+ *
+ *-------------------------------------------------------------------------
+ */
+haddr_t
+H5F_get_base_addr(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_base_addr)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->base_addr)
+} /* end H5F_get_base_addr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_grp_btree_shared
+ *
+ * Purpose: Replaced a macro to retrieve the shared B-tree node info
+ * now that the generic properties are being used to store
+ * the values.
+ *
+ * Return: Success: Non-void, and the shared B-tree node info
+ * is returned.
+ *
+ * Failure: void (should not happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Jul 5 2004
+ *
+ *-------------------------------------------------------------------------
+ */
+H5RC_t *
+H5F_grp_btree_shared(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_grp_btree_shared)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->grp_btree_shared)
+} /* end H5F_grp_btree_shared() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_sieve_buf_size
+ *
+ * Purpose: Replaced a macro to retrieve the dataset sieve buffer size
+ * now that the generic properties are being used to store
+ * the values.
+ *
+ * Return: Success: Non-void, and the dataset sieve buffer size
+ * is returned.
+ *
+ * Failure: void (should not happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Jul 8 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+size_t
+H5F_sieve_buf_size(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sieve_buf_size)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->sieve_buf_size)
+} /* end H5F_sieve_buf_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_gc_ref
+ *
+ * Purpose: Replaced a macro to retrieve the "garbage collect
+ * references flag" now that the generic properties are being used
+ * to store the values.
+ *
+ * Return: Success: The "garbage collect references flag"
+ * is returned.
+ *
+ * Failure: (should not happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Jul 8 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+H5F_gc_ref(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_gc_ref)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->gc_ref)
+} /* end H5F_gc_ref() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_use_latest_format
+ *
+ * Purpose: Retrieve the 'use the latest version of the format' flag for
+ * the file.
+ *
+ * Return: Success: Non-negative, the 'use the latest format' flag
+ *
+ * Failure: (can't happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Oct 2 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+hbool_t
+H5F_use_latest_format(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_use_latest_format)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->latest_format)
+} /* end H5F_use_latest_format() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_get_fc_degree
+ *
+ * Purpose: Retrieve the 'file close degree' for the file.
+ *
+ * Return: Success: Non-negative, the 'file close degree'
+ *
+ * Failure: (can't happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Mar 5 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+H5F_close_degree_t
+H5F_get_fc_degree(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_fc_degree)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->fc_degree)
+} /* end H5F_get_fc_degree() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_store_msg_crt_idx
+ *
+ * Purpose: Retrieve the 'store message creation index' flag for the file.
+ *
+ * Return: Success: Non-negative, the 'store message creation index' flag
+ *
+ * Failure: (can't happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Mar 6 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+hbool_t
+H5F_store_msg_crt_idx(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_store_msg_crt_idx)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->store_msg_crt_idx)
+} /* end H5F_store_msg_crt_idx() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_has_feature
+ *
+ * Purpose: Check if a file has a particular feature enabled
+ *
+ * Return: Success: Non-negative - TRUE or FALSE
+ * Failure: Negative (should not happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 31 2004
+ *
+ *-------------------------------------------------------------------------
+ */
+hbool_t
+H5F_has_feature(const H5F_t *f, unsigned feature)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_has_feature)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI((hbool_t)(f->shared->lf->feature_flags&feature))
+} /* end H5F_has_feature() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_get_driver_id
+ *
+ * Purpose: Quick and dirty routine to retrieve the file's 'driver_id' value
+ * (Mainly added to stop non-file routines from poking about in the
+ * H5F_t data structure)
+ *
+ * Return: 'driver_id' on success/abort on failure (shouldn't fail)
+ *
+ * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
+ * October 10, 2000
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5F_get_driver_id(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_driver_id)
+
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->lf);
+
+ FUNC_LEAVE_NOAPI(f->shared->lf->driver_id)
+} /* end H5F_get_driver_id() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_get_fileno
+ *
+ * Purpose: Quick and dirty routine to retrieve the file's 'fileno' value
+ * (Mainly added to stop non-file routines from poking about in the
+ * H5F_t data structure)
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
+ * March 27, 2002
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_get_fileno(const H5F_t *f, unsigned long *filenum)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(H5F_get_fileno, FAIL)
+
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->lf);
+ HDassert(filenum);
+
+ /* Retrieve the file's serial number */
+ if(H5FD_get_fileno(f->shared->lf, filenum) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, FAIL, "can't retrieve fileno")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_get_fileno() */
+
diff --git a/src/H5Fsuper.c b/src/H5Fsuper.c
index 5036a4f..6196557 100644
--- a/src/H5Fsuper.c
+++ b/src/H5Fsuper.c
@@ -31,6 +31,7 @@
#include "H5Fpkg.h" /* File access */
#include "H5FDprivate.h" /* File drivers */
#include "H5Iprivate.h" /* IDs */
+#include "H5MFprivate.h" /* File memory management */
#include "H5Pprivate.h" /* Property lists */
#include "H5SMprivate.h" /* Shared Object Header Messages */
@@ -186,9 +187,9 @@ H5F_locate_signature(H5FD_t *file, hid_t dxpl_id)
*/
for(n = 8; n < maxpow; n++) {
addr = (8 == n) ? 0 : (haddr_t)1 << n;
- if(H5FD_set_eoa(file, H5FD_MEM_SUPER, addr+H5F_SIGNATURE_LEN) < 0)
+ if(H5FD_set_eoa(file, H5FD_MEM_SUPER, addr + H5F_SIGNATURE_LEN) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, HADDR_UNDEF, "unable to set EOA value for file signature")
- if(H5FD_read(file, H5FD_MEM_SUPER, dxpl_id, addr, (size_t)H5F_SIGNATURE_LEN, buf) < 0)
+ if(H5FD_read(file, dxpl_id, H5FD_MEM_SUPER, addr, (size_t)H5F_SIGNATURE_LEN, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, HADDR_UNDEF, "unable to read file signature")
if(!HDmemcmp(buf, H5F_SIGNATURE, (size_t)H5F_SIGNATURE_LEN))
break;
@@ -235,6 +236,7 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
H5P_genplist_t *c_plist; /* File creation property list */
H5F_file_t *shared; /* shared part of `file' */
H5FD_t *lf; /* file driver part of `shared' */
+ haddr_t abs_super_addr; /* Absolute offset of superblock in file */
haddr_t stored_eoa; /*relative end-of-addr in file */
haddr_t eof; /*end of file address */
size_t sizeof_addr; /* Size of offsets in the file (in bytes) */
@@ -256,14 +258,14 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list")
/* Find the superblock */
- if(HADDR_UNDEF == (shared->super_addr = H5F_locate_signature(lf, dxpl_id)))
+ if(HADDR_UNDEF == (abs_super_addr = H5F_locate_signature(lf, dxpl_id)))
HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "unable to find file signature")
/* Read fixed-size portion of the superblock */
p = sbuf;
- if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, shared->super_addr + fixed_size) < 0)
+ if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, abs_super_addr + fixed_size) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "set end of space allocation request failed")
- if(H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, shared->super_addr, fixed_size, p) < 0)
+ if(H5FD_read(lf, dxpl_id, H5FD_MEM_SUPER, abs_super_addr, fixed_size, p) < 0)
HGOTO_ERROR(H5E_FILE, H5E_READERROR, FAIL, "unable to read superblock")
/* Skip over signature (already checked when locating the superblock) */
@@ -285,9 +287,9 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
HDassert(fixed_size + variable_size <= sizeof(sbuf));
/* Read in variable-sized portion of superblock */
- if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, shared->super_addr + fixed_size + variable_size) < 0)
+ if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, abs_super_addr + fixed_size + variable_size) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "set end of space allocation request failed")
- if(H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, shared->super_addr + fixed_size, variable_size, p) < 0)
+ if(H5FD_read(lf, dxpl_id, H5FD_MEM_SUPER, abs_super_addr + fixed_size, variable_size, p) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read superblock")
/* Check for older version of superblock format */
@@ -388,17 +390,23 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
* Check if superblock address is different from base address and
* adjust base address and "end of address" address if so.
*/
- if(!H5F_addr_eq(shared->super_addr, shared->base_addr)) {
+ if(!H5F_addr_eq(abs_super_addr, shared->base_addr)) {
/* Check if the superblock moved earlier in the file */
- if(H5F_addr_lt(shared->super_addr, shared->base_addr))
- stored_eoa -= (shared->base_addr - shared->super_addr);
+ if(H5F_addr_lt(abs_super_addr, shared->base_addr))
+ stored_eoa -= (shared->base_addr - abs_super_addr);
else
/* The superblock moved later in the file */
- stored_eoa += (shared->super_addr - shared->base_addr);
+ stored_eoa += (abs_super_addr - shared->base_addr);
- shared->base_addr = shared->super_addr;
+ shared->base_addr = abs_super_addr;
} /* end if */
+ /* Set the base address for the file in the VFD now, after adjusting
+ * space for possible offsets of the HDF5 data in the file.
+ */
+ if(H5FD_set_base_addr(lf, shared->base_addr) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "failed to set base address for file driver")
+
/* This step is for h5repart tool only. If user wants to change file driver
* from family to sec2 while using h5repart, set the driver address to
* undefined to let the library ignore the family driver information saved
@@ -412,14 +420,13 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
uint8_t dbuf[H5F_MAX_DRVINFOBLOCK_SIZE]; /* Buffer for driver info block */
char drv_name[9]; /* Name of driver */
unsigned drv_vers; /* Version of driver info block */
- haddr_t drv_addr = shared->base_addr + shared->driver_addr;
size_t drv_variable_size; /* Size of variable-length portion of driver info block, in bytes */
/* Read in fixed-sized portion of driver info block */
p = dbuf;
- if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, drv_addr + H5F_DRVINFOBLOCK_HDR_SIZE) < 0)
+ if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, shared->driver_addr + H5F_DRVINFOBLOCK_HDR_SIZE) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "set end of space allocation request failed")
- if(H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, drv_addr, (size_t)H5F_DRVINFOBLOCK_HDR_SIZE, p) < 0)
+ if(H5FD_read(lf, dxpl_id, H5FD_MEM_SUPER, shared->driver_addr, (size_t)H5F_DRVINFOBLOCK_HDR_SIZE, p) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read driver information block")
/* Version number */
@@ -449,9 +456,9 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "multi driver should be used")
/* Read in variable-sized portion of driver info block */
- if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, drv_addr + H5F_DRVINFOBLOCK_HDR_SIZE + drv_variable_size) < 0)
+ if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, shared->driver_addr + H5F_DRVINFOBLOCK_HDR_SIZE + drv_variable_size) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "set end of space allocation request failed")
- if(H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, drv_addr + H5F_DRVINFOBLOCK_HDR_SIZE, drv_variable_size, p) < 0)
+ if(H5FD_read(lf, dxpl_id, H5FD_MEM_SUPER, shared->driver_addr + H5F_DRVINFOBLOCK_HDR_SIZE, drv_variable_size, p) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read file driver information")
/* Decode driver information */
@@ -512,16 +519,22 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
* Check if superblock address is different from base address and
* adjust base address and "end of address" address if so.
*/
- if(!H5F_addr_eq(shared->super_addr, shared->base_addr)) {
+ if(!H5F_addr_eq(abs_super_addr, shared->base_addr)) {
/* Check if the superblock moved earlier in the file */
- if(H5F_addr_lt(shared->super_addr, shared->base_addr))
- stored_eoa -= (shared->base_addr - shared->super_addr);
+ if(H5F_addr_lt(abs_super_addr, shared->base_addr))
+ stored_eoa -= (shared->base_addr - abs_super_addr);
else
/* The superblock moved later in the file */
- stored_eoa += (shared->super_addr - shared->base_addr);
+ stored_eoa += (abs_super_addr - shared->base_addr);
- shared->base_addr = shared->super_addr;
+ shared->base_addr = abs_super_addr;
} /* end if */
+
+ /* Set the base address for the file in the VFD now, after adjusting
+ * space for possible offsets of the HDF5 data in the file.
+ */
+ if(H5FD_set_base_addr(lf, shared->base_addr) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "failed to set base address for file driver")
} /* end else */
/*
@@ -538,7 +551,8 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
*/
if(HADDR_UNDEF == (eof = H5FD_get_eof(lf)))
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size")
- if(eof < stored_eoa)
+ /* (Account for the stored EOA being absolute offset -QAK) */
+ if((eof + H5F_BASE_ADDR(f)) < stored_eoa)
HGOTO_ERROR(H5E_FILE, H5E_TRUNCATED, FAIL, "truncated file")
/*
@@ -652,9 +666,8 @@ H5F_super_init(H5F_t *f, hid_t dxpl_id)
{
H5P_genplist_t *plist; /* File creation property list */
hsize_t userblock_size; /* Size of userblock, in bytes */
- size_t superblock_size; /* Size of superblock, in bytes */
+ hsize_t superblock_size; /* Size of superblock, in bytes */
size_t driver_size; /* Size of driver info block (bytes) */
- hsize_t alloc_size; /* Size to allocate on disk */
unsigned super_vers; /* Superblock version */
haddr_t super_addr; /* Address of superblock */
hbool_t need_ext; /* Whether the superblock extension is needed */
@@ -674,10 +687,19 @@ H5F_super_init(H5F_t *f, hid_t dxpl_id)
*/
if(H5P_get(plist, H5F_CRT_USER_BLOCK_NAME, &userblock_size) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get userblock size")
- f->shared->super_addr = userblock_size;
- f->shared->base_addr = f->shared->super_addr;
+ f->shared->base_addr = userblock_size;
f->shared->status_flags = 0;
+ /* Reserve space for the userblock */
+ if(H5FD_set_eoa(f->shared->lf, H5FD_MEM_SUPER, userblock_size) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to set EOA value for userblock")
+
+ /* Set the base address for the file in the VFD now, after allocating
+ * space for userblock.
+ */
+ if(H5FD_set_base_addr(f->shared->lf, f->shared->base_addr) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "failed to set base address for file driver")
+
/* Grab superblock version from property list */
if(H5P_get(plist, H5F_CRT_SUPER_VERS_NAME, &super_vers) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get superblock version")
@@ -703,11 +725,9 @@ H5F_super_init(H5F_t *f, hid_t dxpl_id)
* superblock need to be at the beginning of the file and only the first
* allocation request is required to return memory at format address zero.
*/
- H5_CHECK_OVERFLOW(f->shared->base_addr, haddr_t, hsize_t);
- alloc_size = (hsize_t)f->shared->base_addr + superblock_size;
if(super_vers < HDF5_SUPERBLOCK_VERSION_2)
- alloc_size += driver_size;
- super_addr = H5FD_alloc(f->shared->lf, H5FD_MEM_SUPER, dxpl_id, alloc_size);
+ superblock_size += driver_size;
+ super_addr = H5MF_alloc(f, H5FD_MEM_SUPER, dxpl_id, superblock_size);
if(HADDR_UNDEF == super_addr)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to allocate file space for userblock and/or superblock")
if(0 != super_addr)
@@ -836,6 +856,7 @@ H5F_super_write(H5F_t *f, hid_t dxpl_id)
H5P_genplist_t *plist; /* File creation property list */
uint8_t buf[H5F_MAX_SUPERBLOCK_SIZE + H5F_MAX_DRVINFOBLOCK_SIZE]; /* Superblock & driver info blockencoding buffer */
uint8_t *p; /* Ptr into encoding buffer */
+ haddr_t rel_eoa; /* Relative EOA for file */
size_t superblock_size; /* Size of superblock, in bytes */
size_t driver_size; /* Size of driver info block (bytes)*/
unsigned super_vers; /* Superblock version */
@@ -886,7 +907,8 @@ H5F_super_write(H5F_t *f, hid_t dxpl_id)
H5F_addr_encode(f, &p, f->shared->base_addr);
H5F_addr_encode(f, &p, f->shared->extension_addr);
- H5F_addr_encode(f, &p, H5FD_get_eoa(f->shared->lf, H5FD_MEM_SUPER));
+ rel_eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_SUPER);
+ H5F_addr_encode(f, &p, (rel_eoa + f->shared->base_addr));
H5F_addr_encode(f, &p, f->shared->driver_addr);
if(H5G_obj_ent_encode(f, &p, H5G_oloc(f->shared->root_grp)) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to encode root group information")
@@ -932,7 +954,8 @@ H5F_super_write(H5F_t *f, hid_t dxpl_id)
/* Base, superblock extension & end of file addresses */
H5F_addr_encode(f, &p, f->shared->base_addr);
H5F_addr_encode(f, &p, f->shared->extension_addr);
- H5F_addr_encode(f, &p, H5FD_get_eoa(f->shared->lf, H5FD_MEM_SUPER));
+ rel_eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_SUPER);
+ H5F_addr_encode(f, &p, (rel_eoa + f->shared->base_addr));
/* Retrieve information for root group */
if(NULL == (root_oloc = H5G_oloc(f->shared->root_grp)))
@@ -957,8 +980,8 @@ H5F_super_write(H5F_t *f, hid_t dxpl_id)
/* Double check we didn't overrun the block (unlikely) */
HDassert(superblock_size <= sizeof(buf));
- /* Write superblock */
- if(H5FD_write(f->shared->lf, H5FD_MEM_SUPER, dxpl_id, f->shared->super_addr, superblock_size, buf) < 0)
+ /* Write superblock (always at relative offset 0) */
+ if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_SUPER, (haddr_t)0, superblock_size, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write superblock")
done:
diff --git a/src/H5G.c b/src/H5G.c
index 4a49663..6a7e505 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -429,8 +429,9 @@ done:
hid_t
H5Gget_create_plist(hid_t group_id)
{
- htri_t ginfo_exists = 0;
- htri_t linfo_exists = 0;
+ H5O_linfo_t linfo; /* Link info message */
+ htri_t ginfo_exists;
+ htri_t linfo_exists;
H5G_t *grp = NULL;
H5P_genplist_t *gcpl_plist;
H5P_genplist_t *new_plist;
@@ -472,15 +473,9 @@ H5Gget_create_plist(hid_t group_id)
} /* end if */
/* Check for the group having a link info message */
- if((linfo_exists = H5O_msg_exists(&(grp->oloc), H5O_LINFO_ID, H5AC_ind_dxpl_id)) < 0)
+ if((linfo_exists = H5G_obj_get_linfo(&(grp->oloc), &linfo, H5AC_ind_dxpl_id)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to read object header")
if(linfo_exists) {
- H5O_linfo_t linfo; /* Link info message */
-
- /* Read the link info */
- if(NULL == H5G_obj_get_linfo(&(grp->oloc), &linfo, H5AC_ind_dxpl_id))
- HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get link info")
-
/* Set the link info for the property list */
if(H5P_set(new_plist, H5G_CRT_LINK_INFO_NAME, &linfo) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set link info")
@@ -1828,6 +1823,7 @@ H5G_visit_cb(const H5O_link_t *lnk, void *_udata)
H5G_loc_t *old_loc = udata->curr_loc; /* Pointer to previous group location info */
H5_index_t idx_type = udata->idx_type; /* Type of index to use */
H5O_linfo_t linfo; /* Link info message */
+ htri_t linfo_exists; /* Whether the link info message exists */
/* Add the path separator to the current path */
HDassert(udata->path[udata->curr_path_len] == '\0');
@@ -1835,7 +1831,9 @@ H5G_visit_cb(const H5O_link_t *lnk, void *_udata)
udata->curr_path_len++;
/* Attempt to get the link info for this group */
- if(H5G_obj_get_linfo(&obj_oloc, &linfo, udata->dxpl_id)) {
+ if((linfo_exists = H5G_obj_get_linfo(&obj_oloc, &linfo, udata->dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "can't check for link info message")
+ if(linfo_exists) {
/* Check for creation order tracking, if creation order index lookup requested */
if(idx_type == H5_INDEX_CRT_ORDER) {
/* Check if creation order is tracked */
@@ -1847,9 +1845,6 @@ H5G_visit_cb(const H5O_link_t *lnk, void *_udata)
HDassert(idx_type == H5_INDEX_NAME);
} /* end if */
else {
- /* Clear error stack from not finding the link info message */
- H5E_clear_stack(NULL);
-
/* Can only perform name lookups on groups with symbol tables */
if(idx_type != H5_INDEX_NAME)
/* Switch to name order for this group */
@@ -1918,6 +1913,7 @@ H5G_visit(hid_t loc_id, const char *group_name, H5_index_t idx_type,
{
H5G_iter_visit_ud_t udata; /* User data for callback */
H5O_linfo_t linfo; /* Link info message */
+ htri_t linfo_exists; /* Whether the link info message exists */
hid_t gid = (-1); /* Group ID */
H5G_t *grp = NULL; /* Group opened */
H5G_loc_t loc; /* Location of group passed in */
@@ -1987,7 +1983,9 @@ H5G_visit(hid_t loc_id, const char *group_name, H5_index_t idx_type,
} /* end if */
/* Attempt to get the link info for this group */
- if(H5G_obj_get_linfo(&(grp->oloc), &linfo, dxpl_id)) {
+ if((linfo_exists = H5G_obj_get_linfo(&(grp->oloc), &linfo, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message")
+ if(linfo_exists) {
/* Check for creation order tracking, if creation order index lookup requested */
if(idx_type == H5_INDEX_CRT_ORDER) {
/* Check if creation order is tracked */
@@ -1999,9 +1997,6 @@ H5G_visit(hid_t loc_id, const char *group_name, H5_index_t idx_type,
HDassert(idx_type == H5_INDEX_NAME);
} /* end if */
else {
- /* Clear error stack from not finding the link info message */
- H5E_clear_stack(NULL);
-
/* Can only perform name lookups on groups with symbol tables */
if(idx_type != H5_INDEX_NAME)
/* Switch to name order for this group */
diff --git a/src/H5Gcache.c b/src/H5Gcache.c
new file mode 100644
index 0000000..0e2a699
--- /dev/null
+++ b/src/H5Gcache.c
@@ -0,0 +1,470 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5Gcache.c
+ * Feb 5 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Implement group metadata cache methods.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5G_PACKAGE /*suppress error about including H5Gpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Gpkg.h" /* Groups */
+#include "H5MFprivate.h" /* File memory management */
+#include "H5WBprivate.h" /* Wrapped Buffers */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+#define H5G_NODE_VERS 1 /* Symbol table node version number */
+#define H5G_NODE_BUF_SIZE 512 /* Size of stack buffer for serialized nodes */
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+/* Metadata cache (H5AC) callbacks */
+static H5G_node_t *H5G_node_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_udata1,
+ void *_udata2);
+static herr_t H5G_node_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
+ H5G_node_t *sym, unsigned UNUSED * flags_ptr);
+static herr_t H5G_node_dest(H5F_t *f, H5G_node_t *sym);
+static herr_t H5G_node_clear(H5F_t *f, H5G_node_t *sym, hbool_t destroy);
+static herr_t H5G_node_size(const H5F_t *f, const H5G_node_t *sym, size_t *size_ptr);
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Symbol table nodes inherit cache-like properties from H5AC */
+const H5AC_class_t H5AC_SNODE[1] = {{
+ H5AC_SNODE_ID,
+ (H5AC_load_func_t)H5G_node_load,
+ (H5AC_flush_func_t)H5G_node_flush,
+ (H5AC_dest_func_t)H5G_node_dest,
+ (H5AC_clear_func_t)H5G_node_clear,
+ (H5AC_size_func_t)H5G_node_size,
+}};
+
+
+/* Declare extern the free list to manage the H5G_node_t struct */
+H5FL_EXTERN(H5G_node_t);
+
+/* Declare extern the free list to manage sequences of H5G_entry_t's */
+H5FL_SEQ_EXTERN(H5G_entry_t);
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_node_load
+ *
+ * Purpose: Loads a symbol table node from the file.
+ *
+ * Return: Success: Ptr to the new table.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jun 23 1997
+ *
+ * Modifications:
+ * Robb Matzke, 1999-07-28
+ * The ADDR argument is passed by value.
+ *
+ * Quincey Koziol, 2002-7-180
+ * Added dxpl parameter to allow more control over I/O from metadata
+ * cache.
+ *-------------------------------------------------------------------------
+ */
+static H5G_node_t *
+H5G_node_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *_udata1,
+ void UNUSED * _udata2)
+{
+ H5G_node_t *sym = NULL;
+ size_t size;
+ H5WB_t *wb = NULL; /* Wrapped buffer for node data */
+ uint8_t node_buf[H5G_NODE_BUF_SIZE]; /* Buffer for node */
+ uint8_t *node; /* Pointer to node buffer */
+ const uint8_t *p;
+ H5G_node_t *ret_value; /*for error handling */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5G_node_load)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(!_udata1);
+ HDassert(NULL == _udata2);
+
+ /*
+ * Initialize variables.
+ */
+
+ /* Wrap the local buffer for serialized node info */
+ if(NULL == (wb = H5WB_wrap(node_buf, sizeof(node_buf))))
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "can't wrap buffer")
+
+ /* Compute the size of the serialized symbol table node on disk */
+ size = H5G_node_size_real(f);
+
+ /* Get a pointer to a buffer that's large enough for node */
+ if(NULL == (node = (uint8_t *)H5WB_actual(wb, size)))
+ HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, NULL, "can't get actual buffer")
+
+ /* Read the serialized symbol table node. */
+ if(H5F_block_read(f, H5FD_MEM_BTREE, addr, size, dxpl_id, node) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_READERROR, NULL, "unable to read symbol table node")
+
+ /* Get temporary pointer to serialized node */
+ p = node;
+
+ /* magic */
+ if(HDmemcmp(p, H5G_NODE_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, NULL, "bad symbol table node signature")
+ p += 4;
+
+ /* version */
+ if(H5G_NODE_VERS != *p++)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, NULL, "bad symbol table node version")
+
+ /* reserved */
+ p++;
+
+ /* Allocate symbol table data structures */
+ if(NULL == (sym = H5FL_CALLOC(H5G_node_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ if(NULL == (sym->entry = H5FL_SEQ_CALLOC(H5G_entry_t, (size_t)(2 * H5F_SYM_LEAF_K(f)))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+ /* number of symbols */
+ UINT16DECODE(p, sym->nsyms);
+
+ /* entries */
+ if(H5G_ent_decode_vec(f, &p, sym->entry, sym->nsyms) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, NULL, "unable to decode symbol table entries")
+
+ /* Set return value */
+ ret_value = sym;
+
+done:
+ /* Release resources */
+ if(wb && H5WB_unwrap(wb) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, NULL, "can't close wrapped buffer")
+ if(!ret_value)
+ if(sym && H5G_node_dest(f, sym) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CANTFREE, NULL, "unable to destroy symbol table node")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_node_load() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_node_flush
+ *
+ * Purpose: Flush a symbol table node to disk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jun 23 1997
+ *
+ * Modifications:
+ * rky, 1998-08-28
+ * Only p0 writes metadata to disk.
+ *
+ * Robb Matzke, 1999-07-28
+ * The ADDR argument is passed by value.
+ *
+ * Quincey Koziol, 2002-7-180
+ * Added dxpl parameter to allow more control over I/O from metadata
+ * cache.
+ *
+ * Pedro Vicente, <pvn@ncsa.uiuc.edu> 18 Sep 2002
+ * Added `id to name' support.
+ *
+ * JRM -- 8/21/06
+ * Added the flags_ptr parameter. This parameter exists to
+ * allow the flush routine to report to the cache if the
+ * entry is resized or renamed as a result of the flush.
+ * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry.
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5G_node_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5G_node_t *sym, unsigned UNUSED * flags_ptr)
+{
+ H5WB_t *wb = NULL; /* Wrapped buffer for node data */
+ uint8_t node_buf[H5G_NODE_BUF_SIZE]; /* Buffer for node */
+ unsigned u;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5G_node_flush)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(sym);
+
+ /*
+ * Look for dirty entries and set the node dirty flag.
+ */
+ for(u = 0; u < sym->nsyms; u++)
+ if(sym->entry[u].dirty) {
+ /* Set the node's dirty flag */
+ sym->cache_info.is_dirty = TRUE;
+
+ /* Reset the entry's dirty flag */
+ sym->entry[u].dirty = FALSE;
+ } /* end if */
+
+ /*
+ * Write the symbol node to disk.
+ */
+ if(sym->cache_info.is_dirty) {
+ uint8_t *node; /* Pointer to node buffer */
+ uint8_t *p; /* Pointer into raw data buffer */
+ size_t size;
+
+ /* Wrap the local buffer for serialized node info */
+ if(NULL == (wb = H5WB_wrap(node_buf, sizeof(node_buf))))
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't wrap buffer")
+
+ /* Compute the size of the serialized symbol table node on disk */
+ size = H5G_node_size_real(f);
+
+ /* Get a pointer to a buffer that's large enough for node */
+ if(NULL == (node = (uint8_t *)H5WB_actual(wb, size)))
+ HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't get actual buffer")
+
+ /* Get temporary pointer to serialized symbol table node */
+ p = node;
+
+ /* magic number */
+ HDmemcpy(p, H5G_NODE_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ p += 4;
+
+ /* version number */
+ *p++ = H5G_NODE_VERS;
+
+ /* reserved */
+ *p++ = 0;
+
+ /* number of symbols */
+ UINT16ENCODE(p, sym->nsyms);
+
+ /* entries */
+ if(H5G_ent_encode_vec(f, &p, sym->entry, sym->nsyms) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTENCODE, FAIL, "can't serialize")
+ HDmemset(p, 0, size - (p - node));
+
+ /* Write the serialized symbol table node. */
+ if(H5F_block_write(f, H5FD_MEM_BTREE, addr, size, dxpl_id, node) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_WRITEERROR, FAIL, "unable to write symbol table node to the file")
+
+ /* Reset the node's dirty flag */
+ sym->cache_info.is_dirty = FALSE;
+ } /* end if */
+
+ /*
+ * Destroy the symbol node? This might happen if the node is being
+ * preempted from the cache.
+ */
+ if(destroy)
+ if(H5G_node_dest(f, sym) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to destroy symbol table node")
+
+done:
+ /* Release resources */
+ if(wb && H5WB_unwrap(wb) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_node_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_node_dest
+ *
+ * Purpose: Destroy a symbol table node in memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Jan 15 2003
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_node_dest(H5F_t *f, H5G_node_t *sym)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5G_node_dest)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(sym);
+
+ /* Verify that node is clean */
+ HDassert(sym->cache_info.is_dirty == FALSE);
+
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!sym->cache_info.free_file_space_on_destroy || H5F_addr_defined(sym->cache_info.addr));
+
+ /* Check for freeing file space for symbol table node */
+ if(sym->cache_info.free_file_space_on_destroy) {
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_BTREE, H5AC_dxpl_id, sym->cache_info.addr, (hsize_t)H5G_node_size_real(f)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to free symbol table node")
+ } /* end if */
+
+ /* Release resources */
+ if(sym->entry)
+ sym->entry = (H5G_entry_t *)H5FL_SEQ_FREE(H5G_entry_t, sym->entry);
+ (void)H5FL_FREE(H5G_node_t, sym);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_node_dest() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_node_clear
+ *
+ * Purpose: Mark a symbol table node in memory as non-dirty.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Mar 20 2003
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5G_node_clear(H5F_t *f, H5G_node_t *sym, hbool_t destroy)
+{
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5G_node_clear);
+
+ /*
+ * Check arguments.
+ */
+ assert(sym);
+
+ /* Look for dirty entries and reset their dirty flag. */
+ for(u = 0; u < sym->nsyms; u++)
+ sym->entry[u].dirty=FALSE;
+ sym->cache_info.is_dirty = FALSE;
+
+ /*
+ * Destroy the symbol node? This might happen if the node is being
+ * preempted from the cache.
+ */
+ if (destroy)
+ if (H5G_node_dest(f, sym) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to destroy symbol table node");
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5G_node_clear() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_node_size
+ *
+ * Purpose: Compute the size in bytes of the specified instance of
+ * H5G_node_t on disk, and return it in *size_ptr. On failure
+ * the value of size_ptr is undefined.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 5/13/04
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5G_node_size(const H5F_t *f, const H5G_node_t UNUSED *sym, size_t *size_ptr)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_node_size);
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(size_ptr);
+
+ *size_ptr = H5G_node_size_real(f);
+
+ FUNC_LEAVE_NOAPI(SUCCEED);
+} /* H5G_node_size() */
+
diff --git a/src/H5Gcompact.c b/src/H5Gcompact.c
index 6b41007..9ecd6c1 100644
--- a/src/H5Gcompact.c
+++ b/src/H5Gcompact.c
@@ -489,7 +489,7 @@ done:
*
* Purpose: Look up an object relative to a group, using link messages.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative (TRUE/FALSE) on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
@@ -497,13 +497,13 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t
+htri_t
H5G_compact_lookup(H5O_loc_t *oloc, const char *name, H5O_link_t *lnk,
hid_t dxpl_id)
{
H5G_iter_lkp_t udata; /* User data for iteration callback */
H5O_mesg_operator_t op; /* Message operator */
- herr_t ret_value = SUCCEED; /* Return value */
+ htri_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5G_compact_lookup, FAIL)
@@ -522,9 +522,8 @@ H5G_compact_lookup(H5O_loc_t *oloc, const char *name, H5O_link_t *lnk,
if(H5O_msg_iterate(oloc, H5O_LINK_ID, &op, &udata, dxpl_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "error iterating over link messages")
- /* Check if we found the link we were looking for */
- if(!udata.found)
- HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found")
+ /* Determine if we found the link we were looking for */
+ ret_value = udata.found;
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Gdense.c b/src/H5Gdense.c
index a15d961..6c3a171 100644
--- a/src/H5Gdense.c
+++ b/src/H5Gdense.c
@@ -490,7 +490,7 @@ done:
*
* Purpose: Look up a link within a group that uses dense link storage
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative (TRUE/FALSE) on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@hdfgroup.org
@@ -498,13 +498,13 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t
+htri_t
H5G_dense_lookup(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
const char *name, H5O_link_t *lnk)
{
H5G_bt2_ud_common_t udata; /* User data for v2 B-tree link lookup */
H5HF_t *fheap = NULL; /* Fractal heap handle */
- herr_t ret_value = SUCCEED; /* Return value */
+ htri_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5G_dense_lookup, FAIL)
@@ -530,7 +530,7 @@ H5G_dense_lookup(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
udata.found_op_data = lnk;
/* Find & copy the named link in the 'name' index */
- if(H5B2_find(f, dxpl_id, H5G_BT2_NAME, linfo->name_bt2_addr, &udata, NULL, NULL) < 0)
+ if((ret_value = H5B2_find(f, dxpl_id, H5G_BT2_NAME, linfo->name_bt2_addr, &udata, NULL, NULL)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to locate link in name index")
done:
diff --git a/src/H5Gdeprec.c b/src/H5Gdeprec.c
index 6a4310f..ddb5dfe 100644
--- a/src/H5Gdeprec.c
+++ b/src/H5Gdeprec.c
@@ -1136,6 +1136,7 @@ static H5G_obj_t
H5G_obj_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx, hid_t dxpl_id)
{
H5O_linfo_t linfo; /* Link info message */
+ htri_t linfo_exists; /* Whether the link info message exists */
H5G_obj_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5G_obj_get_type_by_idx, H5G_UNKNOWN)
@@ -1144,7 +1145,9 @@ H5G_obj_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx, hid_t dxpl_id)
HDassert(oloc);
/* Attempt to get the link info for this group */
- if(H5G_obj_get_linfo(oloc, &linfo, dxpl_id)) {
+ if((linfo_exists = H5G_obj_get_linfo(oloc, &linfo, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5G_UNKNOWN, "can't check for link info message")
+ if(linfo_exists) {
if(H5F_addr_defined(linfo.fheap_addr)) {
/* Get the object's name from the dense link storage */
if((ret_value = H5G_dense_get_type_by_idx(oloc->file, dxpl_id, &linfo, idx)) < 0)
@@ -1157,9 +1160,6 @@ H5G_obj_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx, hid_t dxpl_id)
} /* end else */
} /* end if */
else {
- /* Clear error stack from not finding the link info message */
- H5E_clear_stack(NULL);
-
/* Get the object's type from the symbol table */
if((ret_value = H5G_stab_get_type_by_idx(oloc, idx, dxpl_id)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5G_UNKNOWN, "can't locate type")
diff --git a/src/H5Gnode.c b/src/H5Gnode.c
index cefed5b..9468302 100644
--- a/src/H5Gnode.c
+++ b/src/H5Gnode.c
@@ -39,7 +39,6 @@
#include "H5HLprivate.h" /* Local Heaps */
#include "H5MFprivate.h" /* File memory management */
#include "H5MMprivate.h" /* Memory management */
-#include "H5WBprivate.h" /* Wrapped Buffers */
/* Private typedefs */
@@ -51,38 +50,11 @@ typedef struct H5G_node_key_t {
size_t offset; /*offset into heap for name */
} H5G_node_key_t;
-/*
- * A symbol table node is a collection of symbol table entries. It can
- * be thought of as the lowest level of the B-link tree that points to
- * a collection of symbol table entries that belong to a specific symbol
- * table or group.
- */
-typedef struct H5G_node_t {
- H5AC_info_t cache_info; /* Information for H5AC cache functions, _must_ be */
- /* first field in structure */
- unsigned nsyms; /*number of symbols */
- H5G_entry_t *entry; /*array of symbol table entries */
-} H5G_node_t;
-
/* Private macros */
-#define H5G_NODE_VERS 1 /*symbol table node version number */
-#define H5G_NODE_SIZEOF_HDR(F) (H5_SIZEOF_MAGIC + 4)
-/* Size of stack buffer for serialized nodes */
-#define H5G_NODE_BUF_SIZE 512
+#define H5G_NODE_SIZEOF_HDR(F) (H5_SIZEOF_MAGIC + 4)
/* PRIVATE PROTOTYPES */
-static herr_t H5G_node_serialize(H5F_t *f, H5G_node_t *sym, size_t size, uint8_t *buf);
-static size_t H5G_node_size_real(const H5F_t *f);
-
-/* Metadata cache callbacks */
-static H5G_node_t *H5G_node_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_udata1,
- void *_udata2);
-static herr_t H5G_node_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
- H5G_node_t *sym, unsigned UNUSED * flags_ptr);
-static herr_t H5G_node_dest(H5F_t *f, H5G_node_t *sym);
-static herr_t H5G_node_clear(H5F_t *f, H5G_node_t *sym, hbool_t destroy);
-static herr_t H5G_node_size(const H5F_t *f, const H5G_node_t *sym, size_t *size_ptr);
/* B-tree callbacks */
static H5RC_t *H5G_node_get_shared(const H5F_t *f, const void *_udata);
@@ -93,7 +65,7 @@ static int H5G_node_cmp2(H5F_t *f, hid_t dxpl_id, void *_lt_key, void *_udata,
void *_rt_key);
static int H5G_node_cmp3(H5F_t *f, hid_t dxpl_id, void *_lt_key, void *_udata,
void *_rt_key);
-static herr_t H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_lt_key,
+static htri_t H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_lt_key,
void *_udata);
static H5B_ins_t H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key,
hbool_t *lt_key_changed, void *_md_key,
@@ -111,16 +83,6 @@ static herr_t H5G_node_debug_key(FILE *stream, H5F_t *f, hid_t dxpl_id,
int indent, int fwidth, const void *key,
const void *udata);
-/* H5G inherits cache-like properties from H5AC */
-const H5AC_class_t H5AC_SNODE[1] = {{
- H5AC_SNODE_ID,
- (H5AC_load_func_t)H5G_node_load,
- (H5AC_flush_func_t)H5G_node_flush,
- (H5AC_dest_func_t)H5G_node_dest,
- (H5AC_clear_func_t)H5G_node_clear,
- (H5AC_size_func_t)H5G_node_size,
-}};
-
/* H5G inherits B-tree like properties from H5B */
H5B_class_t H5B_SNODE[1] = {{
H5B_SNODE_ID, /*id */
@@ -140,10 +102,10 @@ H5B_class_t H5B_SNODE[1] = {{
}};
/* Declare a free list to manage the H5G_node_t struct */
-H5FL_DEFINE_STATIC(H5G_node_t);
+H5FL_DEFINE(H5G_node_t);
/* Declare a free list to manage sequences of H5G_entry_t's */
-H5FL_SEQ_DEFINE_STATIC(H5G_entry_t);
+H5FL_SEQ_DEFINE(H5G_entry_t);
/*-------------------------------------------------------------------------
@@ -303,7 +265,7 @@ H5G_node_debug_key(FILE *stream, H5F_t *f, hid_t UNUSED dxpl_id, int indent,
*
*-------------------------------------------------------------------------
*/
-static size_t
+size_t
H5G_node_size_real(const H5F_t *f)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_node_size_real);
@@ -314,389 +276,6 @@ H5G_node_size_real(const H5F_t *f)
/*-------------------------------------------------------------------------
- * Function: H5G_node_load
- *
- * Purpose: Loads a symbol table node from the file.
- *
- * Return: Success: Ptr to the new table.
- *
- * Failure: NULL
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Jun 23 1997
- *
- * Modifications:
- * Robb Matzke, 1999-07-28
- * The ADDR argument is passed by value.
- *
- * Quincey Koziol, 2002-7-180
- * Added dxpl parameter to allow more control over I/O from metadata
- * cache.
- *-------------------------------------------------------------------------
- */
-static H5G_node_t *
-H5G_node_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *_udata1,
- void UNUSED * _udata2)
-{
- H5G_node_t *sym = NULL;
- size_t size;
- H5WB_t *wb = NULL; /* Wrapped buffer for node data */
- uint8_t node_buf[H5G_NODE_BUF_SIZE]; /* Buffer for node */
- uint8_t *node; /* Pointer to node buffer */
- const uint8_t *p;
- H5G_node_t *ret_value; /*for error handling */
-
- FUNC_ENTER_NOAPI_NOINIT(H5G_node_load)
-
- /*
- * Check arguments.
- */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
- HDassert(!_udata1);
- HDassert(NULL == _udata2);
-
- /*
- * Initialize variables.
- */
-
- /* Wrap the local buffer for serialized node info */
- if(NULL == (wb = H5WB_wrap(node_buf, sizeof(node_buf))))
- HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "can't wrap buffer")
-
- /* Compute the size of the serialized symbol table node on disk */
- size = H5G_node_size_real(f);
-
- /* Get a pointer to a buffer that's large enough for node */
- if(NULL == (node = (uint8_t *)H5WB_actual(wb, size)))
- HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, NULL, "can't get actual buffer")
-
- /* Read the serialized symbol table node. */
- if(H5F_block_read(f, H5FD_MEM_BTREE, addr, size, dxpl_id, node) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_READERROR, NULL, "unable to read symbol table node")
-
- /* Get temporary pointer to serialized node */
- p = node;
-
- /* magic */
- if(HDmemcmp(p, H5G_NODE_MAGIC, (size_t)H5_SIZEOF_MAGIC))
- HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, NULL, "bad symbol table node signature")
- p += H5_SIZEOF_MAGIC;
-
- /* version */
- if(H5G_NODE_VERS != *p++)
- HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, NULL, "bad symbol table node version")
-
- /* reserved */
- p++;
-
- /* Allocate symbol table data structures */
- if(NULL == (sym = H5FL_CALLOC(H5G_node_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- if(NULL == (sym->entry = H5FL_SEQ_CALLOC(H5G_entry_t, (size_t)(2 * H5F_SYM_LEAF_K(f)))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
-
- /* number of symbols */
- UINT16DECODE(p, sym->nsyms);
-
- /* entries */
- if(H5G_ent_decode_vec(f, &p, sym->entry, sym->nsyms) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, NULL, "unable to decode symbol table entries")
-
- /* Set return value */
- ret_value = sym;
-
-done:
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, NULL, "can't close wrapped buffer")
- if(!ret_value)
- if(sym && H5G_node_dest(f, sym) < 0)
- HDONE_ERROR(H5E_SYM, H5E_CANTFREE, NULL, "unable to destroy symbol table node")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5G_node_load() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5G_node_flush
- *
- * Purpose: Flush a symbol table node to disk.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Jun 23 1997
- *
- * Modifications:
- * rky, 1998-08-28
- * Only p0 writes metadata to disk.
- *
- * Robb Matzke, 1999-07-28
- * The ADDR argument is passed by value.
- *
- * Quincey Koziol, 2002-7-180
- * Added dxpl parameter to allow more control over I/O from metadata
- * cache.
- *
- * Pedro Vicente, <pvn@ncsa.uiuc.edu> 18 Sep 2002
- * Added `id to name' support.
- *
- * JRM -- 8/21/06
- * Added the flags_ptr parameter. This parameter exists to
- * allow the flush routine to report to the cache if the
- * entry is resized or renamed as a result of the flush.
- * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry.
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5G_node_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5G_node_t *sym, unsigned UNUSED * flags_ptr)
-{
- H5WB_t *wb = NULL; /* Wrapped buffer for node data */
- uint8_t node_buf[H5G_NODE_BUF_SIZE]; /* Buffer for node */
- unsigned u;
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5G_node_flush)
-
- /*
- * Check arguments.
- */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
- HDassert(sym);
-
- /*
- * Look for dirty entries and set the node dirty flag.
- */
- for(u = 0; u < sym->nsyms; u++)
- if(sym->entry[u].dirty) {
- /* Set the node's dirty flag */
- sym->cache_info.is_dirty = TRUE;
-
- /* Reset the entry's dirty flag */
- sym->entry[u].dirty = FALSE;
- } /* end if */
-
- /*
- * Write the symbol node to disk.
- */
- if(sym->cache_info.is_dirty) {
- uint8_t *node; /* Pointer to node buffer */
- size_t size;
-
- /* Wrap the local buffer for serialized node info */
- if(NULL == (wb = H5WB_wrap(node_buf, sizeof(node_buf))))
- HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't wrap buffer")
-
- /* Compute the size of the serialized symbol table node on disk */
- size = H5G_node_size_real(f);
-
- /* Get a pointer to a buffer that's large enough for node */
- if(NULL == (node = (uint8_t *)H5WB_actual(wb, size)))
- HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't get actual buffer")
-
- /* Serialize symbol table node into buffer */
- if(H5G_node_serialize(f, sym, size, node) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTSERIALIZE, FAIL, "node serialization failed")
-
- /* Write the serialized symbol table node. */
- if(H5F_block_write(f, H5FD_MEM_BTREE, addr, size, dxpl_id, node) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_WRITEERROR, FAIL, "unable to write symbol table node to the file")
-
- /* Reset the node's dirty flag */
- sym->cache_info.is_dirty = FALSE;
- } /* end if */
-
- /*
- * Destroy the symbol node? This might happen if the node is being
- * preempted from the cache.
- */
- if(destroy)
- if(H5G_node_dest(f, sym) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to destroy symbol table node")
-
-done:
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5G_node_flush() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5G_node_serialize
- *
- * Purpose: Serialize the symbol table node
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Bill Wendling
- * wendling@ncsa.uiuc.edu
- * Sept. 16, 2003
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5G_node_serialize(H5F_t *f, H5G_node_t *sym, size_t size, uint8_t *buf)
-{
- uint8_t *p;
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT(H5G_node_serialize);
-
- /* check args */
- assert(f);
- assert(sym);
- assert(buf);
-
- p = buf;
-
- /* magic number */
- HDmemcpy(p, H5G_NODE_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += H5_SIZEOF_MAGIC;
-
- /* version number */
- *p++ = H5G_NODE_VERS;
-
- /* reserved */
- *p++ = 0;
-
- /* number of symbols */
- UINT16ENCODE(p, sym->nsyms);
-
- /* entries */
- if (H5G_ent_encode_vec(f, &p, sym->entry, sym->nsyms) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTENCODE, FAIL, "can't serialize")
- HDmemset(p, 0, size - (p - buf));
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5G_node_dest
- *
- * Purpose: Destroy a symbol table node in memory.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Jan 15 2003
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5G_node_dest(H5F_t UNUSED *f, H5G_node_t *sym)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_node_dest)
-
- /*
- * Check arguments.
- */
- HDassert(sym);
-
- /* Verify that node is clean */
- HDassert(sym->cache_info.is_dirty == FALSE);
-
- if(sym->entry)
- sym->entry = (H5G_entry_t *)H5FL_SEQ_FREE(H5G_entry_t, sym->entry);
- (void)H5FL_FREE(H5G_node_t, sym);
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5G_node_dest() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5G_node_clear
- *
- * Purpose: Mark a symbol table node in memory as non-dirty.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 20 2003
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5G_node_clear(H5F_t *f, H5G_node_t *sym, hbool_t destroy)
-{
- unsigned u; /* Local index variable */
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT(H5G_node_clear);
-
- /*
- * Check arguments.
- */
- assert(sym);
-
- /* Look for dirty entries and reset their dirty flag. */
- for(u = 0; u < sym->nsyms; u++)
- sym->entry[u].dirty=FALSE;
- sym->cache_info.is_dirty = FALSE;
-
- /*
- * Destroy the symbol node? This might happen if the node is being
- * preempted from the cache.
- */
- if (destroy)
- if (H5G_node_dest(f, sym) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to destroy symbol table node");
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5G_node_clear() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5G_node_size
- *
- * Purpose: Compute the size in bytes of the specified instance of
- * H5G_node_t on disk, and return it in *size_ptr. On failure
- * the value of size_ptr is undefined.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: John Mainzer
- * 5/13/04
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5G_node_size(const H5F_t *f, const H5G_node_t UNUSED *sym, size_t *size_ptr)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_node_size);
-
- /*
- * Check arguments.
- */
- HDassert(f);
- HDassert(size_ptr);
-
- *size_ptr = H5G_node_size_real(f);
-
- FUNC_LEAVE_NOAPI(SUCCEED);
-} /* H5G_node_size() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5G_node_create
*
* Purpose: Creates a new empty symbol table node. This function is
@@ -903,8 +482,8 @@ H5G_node_cmp3(H5F_t *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_udata,
* entry field. Otherwise the entry is copied from the
* UDATA entry field to the symbol table.
*
- * Return: Success: Non-negative if found and data returned through
- * the UDATA pointer.
+ * Return: Success: Non-negative (TRUE/FALSE) if found and data
+ * returned through the UDATA pointer.
*
* Failure: Negative if not found.
*
@@ -914,7 +493,7 @@ H5G_node_cmp3(H5F_t *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_udata,
*
*-------------------------------------------------------------------------
*/
-static herr_t
+static htri_t
H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *_lt_key,
void *_udata)
{
@@ -923,8 +502,8 @@ H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *_lt_key
unsigned lt = 0, idx = 0, rt;
int cmp = 1;
const char *s;
- const char *base; /* Base of heap */
- herr_t ret_value = SUCCEED; /* Return value */
+ const char *base; /* Base of heap */
+ htri_t ret_value = TRUE; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5G_node_found)
@@ -961,7 +540,7 @@ H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *_lt_key
} /* end while */
if(cmp)
- HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "not found")
+ HGOTO_DONE(FALSE)
/* Call user's callback operator */
if((udata->op)(&sn->entry[idx], udata->op_data) < 0)
@@ -1292,14 +871,8 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/,
*rt_key = *lt_key;
*rt_key_changed = TRUE;
sn->nsyms = 0;
- if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, addr, (hsize_t)H5G_node_size_real(f)) < 0
- || H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, H5AC__DIRTIED_FLAG | H5C__DELETED_FLAG) < 0) {
- sn = NULL;
- HGOTO_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to free symbol table node")
- } /* end if */
- sn = NULL;
+ sn_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
ret_value = H5B_INS_REMOVE;
-
} else if(0 == idx) {
/*
* We are about to remove the left-most entry from the symbol table
@@ -1311,7 +884,6 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/,
HDmemmove(sn->entry + idx, sn->entry + idx + 1,
(sn->nsyms-idx) * sizeof(H5G_entry_t));
ret_value = H5B_INS_NOOP;
-
} else if (idx + 1 == sn->nsyms) {
/*
* We are about to remove the right-most entry from the symbol table
@@ -1323,7 +895,6 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/,
rt_key->offset = sn->entry[sn->nsyms - 1].name_off;
*rt_key_changed = TRUE;
ret_value = H5B_INS_NOOP;
-
} else {
/*
* We are about to remove an entry from the middle of a symbol table
@@ -1364,12 +935,7 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/,
*rt_key = *lt_key;
*rt_key_changed = TRUE;
sn->nsyms = 0;
- if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, addr, (hsize_t)H5G_node_size_real(f)) < 0
- || H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, H5AC__DIRTIED_FLAG | H5C__DELETED_FLAG) < 0) {
- sn = NULL;
- HGOTO_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to free symbol table node")
- } /* end if */
- sn = NULL;
+ sn_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
ret_value = H5B_INS_REMOVE;
} /* end else */
diff --git a/src/H5Gobj.c b/src/H5Gobj.c
index a9d6e1a..e0d5434 100644
--- a/src/H5Gobj.c
+++ b/src/H5Gobj.c
@@ -141,6 +141,10 @@ H5G_obj_create(H5F_t *f, hid_t dxpl_id, const H5O_ginfo_t *ginfo,
HDassert(ginfo);
HDassert(oloc);
+ /* Check for invalid access request */
+ if(0 == (f->intent & H5F_ACC_RDWR))
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "no write intent on file")
+
/* Check for using the latest version of the group format */
/* (add more checks for creating "new format" groups when needed) */
if(H5F_USE_LATEST_FORMAT(f) || linfo->track_corder)
@@ -322,36 +326,41 @@ H5G_obj_ent_encode(const H5F_t *f, uint8_t **pp, const H5O_loc_t *oloc)
*
*-------------------------------------------------------------------------
*/
-H5O_linfo_t *
+htri_t
H5G_obj_get_linfo(const H5O_loc_t *grp_oloc, H5O_linfo_t *linfo, hid_t dxpl_id)
{
- H5O_linfo_t *ret_value; /* Return value */
+ htri_t ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5G_obj_get_linfo, NULL)
+ FUNC_ENTER_NOAPI(H5G_obj_get_linfo, FAIL)
/* check arguments */
HDassert(grp_oloc);
+ HDassert(linfo);
+
+ /* Check for the group having a link info message */
+ if((ret_value = H5O_msg_exists(grp_oloc, H5O_LINFO_ID, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to read object header")
+ if(ret_value) {
+ /* Retrieve the "link info" structure */
+ if(NULL == H5O_msg_read(grp_oloc, H5O_LINFO_ID, linfo, dxpl_id))
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "link info message not present")
- /* Retrieve the "link info" structure */
- if((ret_value = (H5O_linfo_t *)H5O_msg_read(grp_oloc, H5O_LINFO_ID, linfo, dxpl_id))) {
/* Check if we don't know how many links there are */
- if(ret_value->nlinks == HSIZET_MAX) {
+ if(linfo->nlinks == HSIZET_MAX) {
/* Check if we are using "dense" link storage */
- if(H5F_addr_defined(ret_value->fheap_addr)) {
+ if(H5F_addr_defined(linfo->fheap_addr)) {
/* Retrieve # of records in "name" B-tree */
/* (should be same # of records in all indices) */
- if(H5B2_get_nrec(grp_oloc->file, dxpl_id, H5G_BT2_NAME, ret_value->name_bt2_addr, &ret_value->nlinks) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTGET, NULL, "can't retrieve # of records in index")
+ if(H5B2_get_nrec(grp_oloc->file, dxpl_id, H5G_BT2_NAME, linfo->name_bt2_addr, &linfo->nlinks) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve # of records in index")
} /* end if */
else {
/* Retrieve # of links from object header */
- if(H5O_get_nlinks(grp_oloc, dxpl_id, &ret_value->nlinks) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTGET, NULL, "can't retrieve # of links for object")
+ if(H5O_get_nlinks(grp_oloc, dxpl_id, &linfo->nlinks) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve # of links for object")
} /* end if */
} /* end if */
} /* end if */
- else
- HGOTO_ERROR(H5E_SYM, H5E_CANTGET, NULL, "link info message not present")
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -452,6 +461,7 @@ H5G_obj_insert(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *obj_lnk,
hbool_t adj_link, hid_t dxpl_id)
{
H5O_linfo_t linfo; /* Link info message */
+ htri_t linfo_exists; /* Whether the link info message exists */
hbool_t use_old_format; /* Whether to use 'old format' (symbol table) for insertions or not */
hbool_t use_new_dense = FALSE; /* Whether to use "dense" form of 'new format' group */
herr_t ret_value = SUCCEED; /* Return value */
@@ -465,7 +475,9 @@ H5G_obj_insert(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *obj_lnk,
/* Check if we have information about the number of objects in this group */
/* (by attempting to get the link info message for this group) */
- if(H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) {
+ if((linfo_exists = H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message")
+ if(linfo_exists) {
H5O_ginfo_t ginfo; /* Group info message */
size_t link_msg_size; /* Size of new link message in the file */
@@ -525,9 +537,6 @@ H5G_obj_insert(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *obj_lnk,
} /* end else */
} /* end if */
else {
- /* Clear error stack from not finding the link info message */
- H5E_clear_stack(NULL);
-
/* Check for new-style link information */
if(obj_lnk->cset != H5T_CSET_ASCII || obj_lnk->type > H5L_TYPE_BUILTIN_MAX) {
H5O_linfo_t new_linfo = H5G_CRT_LINK_INFO_DEF; /* Link information */
@@ -636,6 +645,7 @@ H5G_obj_iterate(const H5O_loc_t *grp_oloc,
H5G_lib_iterate_t op, void *op_data, hid_t dxpl_id)
{
H5O_linfo_t linfo; /* Link info message */
+ htri_t linfo_exists; /* Whether the link info message exists */
herr_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5G_obj_iterate, FAIL)
@@ -645,7 +655,9 @@ H5G_obj_iterate(const H5O_loc_t *grp_oloc,
HDassert(op);
/* Attempt to get the link info for this group */
- if(H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) {
+ if((linfo_exists = H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message")
+ if(linfo_exists) {
/* Check for going out of bounds */
if(skip > 0 && (size_t)skip >= linfo.nlinks)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "index out of bound")
@@ -669,9 +681,6 @@ H5G_obj_iterate(const H5O_loc_t *grp_oloc,
} /* end else */
} /* end if */
else {
- /* Clear error stack from not finding the link info message */
- H5E_clear_stack(NULL);
-
/* Can only perform name lookups on groups with symbol tables */
if(idx_type != H5_INDEX_NAME)
HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "no creation order index to query")
@@ -707,6 +716,7 @@ H5G_obj_info(H5O_loc_t *oloc, H5G_info_t *grp_info, hid_t dxpl_id)
H5G_name_t grp_path; /* Group hier. path */
H5O_loc_t grp_oloc; /* Group object location */
H5O_linfo_t linfo; /* Link info message */
+ htri_t linfo_exists; /* Whether the link info message exists */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5G_obj_info, FAIL)
@@ -732,7 +742,9 @@ H5G_obj_info(H5O_loc_t *oloc, H5G_info_t *grp_info, hid_t dxpl_id)
grp_info->mounted = H5G_MOUNTED(grp);
/* Attempt to get the link info for this group */
- if(H5G_obj_get_linfo(oloc, &linfo, dxpl_id)) {
+ if((linfo_exists = H5G_obj_get_linfo(oloc, &linfo, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message")
+ if(linfo_exists) {
/* Retrieve the information about the links */
grp_info->nlinks = linfo.nlinks;
grp_info->max_corder = linfo.max_corder;
@@ -744,9 +756,6 @@ H5G_obj_info(H5O_loc_t *oloc, H5G_info_t *grp_info, hid_t dxpl_id)
grp_info->storage_type = H5G_STORAGE_TYPE_COMPACT;
} /* end if */
else {
- /* Clear error stack from not finding the link info message */
- H5E_clear_stack(NULL);
-
/* Get the number of objects in this group by iterating over symbol table */
if(H5G_stab_count(oloc, &grp_info->nlinks, dxpl_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTCOUNT, FAIL, "can't count objects")
@@ -783,6 +792,7 @@ H5G_obj_get_name_by_idx(H5O_loc_t *oloc, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n, char* name, size_t size, hid_t dxpl_id)
{
H5O_linfo_t linfo; /* Link info message */
+ htri_t linfo_exists; /* Whether the link info message exists */
ssize_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5G_obj_get_name_by_idx, FAIL)
@@ -791,7 +801,9 @@ H5G_obj_get_name_by_idx(H5O_loc_t *oloc, H5_index_t idx_type,
HDassert(oloc && oloc->file);
/* Attempt to get the link info for this group */
- if(H5G_obj_get_linfo(oloc, &linfo, dxpl_id)) {
+ if((linfo_exists = H5G_obj_get_linfo(oloc, &linfo, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message")
+ if(linfo_exists) {
/* Check for creation order tracking, if creation order index lookup requested */
if(idx_type == H5_INDEX_CRT_ORDER) {
/* Check if creation order is tracked */
@@ -812,9 +824,6 @@ H5G_obj_get_name_by_idx(H5O_loc_t *oloc, H5_index_t idx_type,
} /* end else */
} /* end if */
else {
- /* Clear error stack from not finding the link info message */
- H5E_clear_stack(NULL);
-
/* Can only perform name lookups on groups with symbol tables */
if(idx_type != H5_INDEX_NAME)
HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "no creation order index to query")
@@ -955,6 +964,7 @@ herr_t
H5G_obj_remove(H5O_loc_t *oloc, H5RS_str_t *grp_full_path_r, const char *name, hid_t dxpl_id)
{
H5O_linfo_t linfo; /* Link info message */
+ htri_t linfo_exists; /* Whether the link info message exists */
hbool_t use_old_format; /* Whether to use 'old format' (symbol table) for deletion or not */
herr_t ret_value = SUCCEED; /* Return value */
@@ -965,7 +975,9 @@ H5G_obj_remove(H5O_loc_t *oloc, H5RS_str_t *grp_full_path_r, const char *name, h
HDassert(name && *name);
/* Attempt to get the link info for this group */
- if(H5G_obj_get_linfo(oloc, &linfo, dxpl_id)) {
+ if((linfo_exists = H5G_obj_get_linfo(oloc, &linfo, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message")
+ if(linfo_exists) {
/* Using the new format for groups */
use_old_format = FALSE;
@@ -982,9 +994,6 @@ H5G_obj_remove(H5O_loc_t *oloc, H5RS_str_t *grp_full_path_r, const char *name, h
} /* end else */
} /* end if */
else {
- /* Clear error stack from not finding the link info message */
- H5E_clear_stack(NULL);
-
/* Using the old format for groups */
use_old_format = TRUE;
@@ -1021,6 +1030,7 @@ H5G_obj_remove_by_idx(H5O_loc_t *grp_oloc, H5RS_str_t *grp_full_path_r,
H5_index_t idx_type, H5_iter_order_t order, hsize_t n, hid_t dxpl_id)
{
H5O_linfo_t linfo; /* Link info message */
+ htri_t linfo_exists; /* Whether the link info message exists */
hbool_t use_old_format; /* Whether to use 'old format' (symbol table) for deletion or not */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1030,7 +1040,9 @@ H5G_obj_remove_by_idx(H5O_loc_t *grp_oloc, H5RS_str_t *grp_full_path_r,
HDassert(grp_oloc && grp_oloc->file);
/* Attempt to get the link info for this group */
- if(H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) {
+ if((linfo_exists = H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message")
+ if(linfo_exists) {
/* Check for creation order tracking, if creation order index lookup requested */
if(idx_type == H5_INDEX_CRT_ORDER) {
/* Check if creation order is tracked */
@@ -1093,12 +1105,13 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t
+htri_t
H5G_obj_lookup(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk,
hid_t dxpl_id)
{
H5O_linfo_t linfo; /* Link info message */
- herr_t ret_value = SUCCEED; /* Return value */
+ htri_t linfo_exists; /* Whether the link info message exists */
+ htri_t ret_value = FALSE; /* Return value */
FUNC_ENTER_NOAPI(H5G_obj_lookup, FAIL)
@@ -1107,25 +1120,24 @@ H5G_obj_lookup(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk,
HDassert(name && *name);
/* Attempt to get the link info message for this group */
- if(H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) {
+ if((linfo_exists = H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message")
+ if(linfo_exists) {
/* Check for dense link storage */
if(H5F_addr_defined(linfo.fheap_addr)) {
/* Get the object's info from the dense link storage */
- if(H5G_dense_lookup(grp_oloc->file, dxpl_id, &linfo, name, lnk) < 0)
+ if((ret_value = H5G_dense_lookup(grp_oloc->file, dxpl_id, &linfo, name, lnk)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate object")
} /* end if */
else {
/* Get the object's info from the link messages */
- if(H5G_compact_lookup(grp_oloc, name, lnk, dxpl_id) < 0)
+ if((ret_value = H5G_compact_lookup(grp_oloc, name, lnk, dxpl_id)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate object")
} /* end else */
} /* end if */
else {
- /* Clear error stack from not finding the link info message */
- H5E_clear_stack(NULL);
-
/* Get the object's info from the symbol table */
- if(H5G_stab_lookup(grp_oloc, name, lnk, dxpl_id) < 0)
+ if((ret_value = H5G_stab_lookup(grp_oloc, name, lnk, dxpl_id)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate object")
} /* end else */
@@ -1153,6 +1165,7 @@ H5G_obj_lookup_by_idx(H5O_loc_t *grp_oloc, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n, H5O_link_t *lnk, hid_t dxpl_id)
{
H5O_linfo_t linfo; /* Link info message */
+ htri_t linfo_exists; /* Whether the link info message exists */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5G_obj_lookup_by_idx, FAIL)
@@ -1161,7 +1174,9 @@ H5G_obj_lookup_by_idx(H5O_loc_t *grp_oloc, H5_index_t idx_type,
HDassert(grp_oloc && grp_oloc->file);
/* Attempt to get the link info message for this group */
- if(H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) {
+ if((linfo_exists = H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message")
+ if(linfo_exists) {
/* Check for creation order tracking, if creation order index lookup requested */
if(idx_type == H5_INDEX_CRT_ORDER) {
/* Check if creation order is tracked */
@@ -1182,9 +1197,6 @@ H5G_obj_lookup_by_idx(H5O_loc_t *grp_oloc, H5_index_t idx_type,
} /* end else */
} /* end if */
else {
- /* Clear error stack from not finding the link info message */
- H5E_clear_stack(NULL);
-
/* Can only perform name lookups on groups with symbol tables */
if(idx_type != H5_INDEX_NAME)
HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "no creation order index to query")
diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h
index b2cef28..31e5713 100644
--- a/src/H5Gpkg.h
+++ b/src/H5Gpkg.h
@@ -110,6 +110,19 @@ typedef struct H5G_entry_t {
} H5G_entry_t;
/*
+ * A symbol table node is a collection of symbol table entries. It can
+ * be thought of as the lowest level of the B-link tree that points to
+ * a collection of symbol table entries that belong to a specific symbol
+ * table or group.
+ */
+typedef struct H5G_node_t {
+ H5AC_info_t cache_info; /* Information for H5AC cache functions, _must_ be */
+ /* first field in structure */
+ unsigned nsyms; /*number of symbols */
+ H5G_entry_t *entry; /*array of symbol table entries */
+} H5G_node_t;
+
+/*
* Shared information for all open group objects
*/
struct H5G_shared_t {
@@ -412,6 +425,7 @@ H5_DLL herr_t H5G_ent_debug(H5F_t *f, const H5G_entry_t *ent,
/* Functions that understand symbol table nodes */
H5_DLL herr_t H5G_node_init(H5F_t *f);
+H5_DLL size_t H5G_node_size_real(const H5F_t *f);
H5_DLL int H5G_node_iterate(H5F_t *f, hid_t dxpl_id, const void *_lt_key, haddr_t addr,
const void *_rt_key, void *_udata);
H5_DLL int H5G_node_sumup(H5F_t *f, hid_t dxpl_id, const void *_lt_key, haddr_t addr,
@@ -462,7 +476,7 @@ H5_DLL herr_t H5G_compact_remove_by_idx(const H5O_loc_t *oloc, hid_t dxpl_id,
H5_DLL herr_t H5G_compact_iterate(const H5O_loc_t *oloc, hid_t dxpl_id,
const H5O_linfo_t *linfo, H5_index_t idx_type, H5_iter_order_t order,
hsize_t skip, hsize_t *last_lnk, H5G_lib_iterate_t op, void *op_data);
-H5_DLL herr_t H5G_compact_lookup(H5O_loc_t *grp_oloc, const char *name,
+H5_DLL htri_t H5G_compact_lookup(H5O_loc_t *grp_oloc, const char *name,
H5O_link_t *lnk, hid_t dxpl_id);
H5_DLL herr_t H5G_compact_lookup_by_idx(H5O_loc_t *oloc, hid_t dxpl_id,
const H5O_linfo_t *linfo, H5_index_t idx_type, H5_iter_order_t order,
@@ -478,7 +492,7 @@ H5_DLL herr_t H5G_dense_build_table(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *
H5_DLL herr_t H5G_dense_create(H5F_t *f, hid_t dxpl_id, H5O_linfo_t *linfo);
H5_DLL herr_t H5G_dense_insert(H5F_t *f, hid_t dxpl_id,
const H5O_linfo_t *linfo, const H5O_link_t *lnk);
-H5_DLL herr_t H5G_dense_lookup(H5F_t *f, hid_t dxpl_id,
+H5_DLL htri_t H5G_dense_lookup(H5F_t *f, hid_t dxpl_id,
const H5O_linfo_t *linfo, const char *name, H5O_link_t *lnk);
H5_DLL herr_t H5G_dense_lookup_by_idx(H5F_t *f, hid_t dxpl_id,
const H5O_linfo_t *linfo, H5_index_t idx_type, H5_iter_order_t order,
@@ -504,8 +518,8 @@ H5_DLL H5G_obj_t H5G_dense_get_type_by_idx(H5F_t *f, hid_t dxpl_id,
/* Functions that understand group objects */
H5_DLL herr_t H5G_obj_create(H5F_t *f, hid_t dxpl_id, const H5O_ginfo_t *ginfo,
const H5O_linfo_t *linfo, hid_t gcpl_id, H5O_loc_t *oloc/*out*/);
-H5_DLL H5O_linfo_t * H5G_obj_get_linfo(const H5O_loc_t *grp_oloc,
- H5O_linfo_t *linfo, hid_t dxpl_id);
+H5_DLL htri_t H5G_obj_get_linfo(const H5O_loc_t *grp_oloc, H5O_linfo_t *linfo,
+ hid_t dxpl_id);
H5_DLL herr_t H5G_obj_insert(const H5O_loc_t *grp_oloc, const char *name,
H5O_link_t *obj_lnk, hbool_t adj_link, hid_t dxpl_id);
H5_DLL herr_t H5G_obj_iterate(const H5O_loc_t *grp_oloc,
@@ -518,7 +532,7 @@ H5_DLL herr_t H5G_obj_remove(H5O_loc_t *oloc, H5RS_str_t *grp_full_path_r,
const char *name, hid_t dxpl_id);
H5_DLL herr_t H5G_obj_remove_by_idx(H5O_loc_t *grp_oloc, H5RS_str_t *grp_full_path_r,
H5_index_t idx_type, H5_iter_order_t order, hsize_t n, hid_t dxpl_id);
-H5_DLL herr_t H5G_obj_lookup(H5O_loc_t *grp_oloc, const char *name,
+H5_DLL htri_t H5G_obj_lookup(H5O_loc_t *grp_oloc, const char *name,
H5O_link_t *lnk, hid_t dxpl_id);
H5_DLL herr_t H5G_obj_lookup_by_idx(H5O_loc_t *grp_oloc, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n, H5O_link_t *lnk, hid_t dxpl_id);
diff --git a/src/H5Gstab.c b/src/H5Gstab.c
index 8ab9deb..f79d78b 100644
--- a/src/H5Gstab.c
+++ b/src/H5Gstab.c
@@ -810,7 +810,7 @@ done:
*
* Purpose: Look up an object relative to a group, using symbol table
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative (TRUE/FALSE) on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
@@ -818,7 +818,7 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t
+htri_t
H5G_stab_lookup(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk,
hid_t dxpl_id)
{
@@ -826,7 +826,7 @@ H5G_stab_lookup(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk,
H5G_bt_lkp_t bt_udata; /* Data to pass through B-tree */
H5G_stab_fnd_ud_t udata; /* 'User data' to give to callback */
H5O_stab_t stab; /* Symbol table message */
- herr_t ret_value = SUCCEED; /* Return value */
+ htri_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5G_stab_lookup, FAIL)
@@ -856,7 +856,7 @@ H5G_stab_lookup(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk,
bt_udata.op_data = &udata;
/* Search the B-tree */
- if(H5B_find(grp_oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, &bt_udata) < 0)
+ if((ret_value = H5B_find(grp_oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, &bt_udata)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "not found")
done:
diff --git a/src/H5Gtest.c b/src/H5Gtest.c
index be9ab14..d7f102f 100644
--- a/src/H5Gtest.c
+++ b/src/H5Gtest.c
@@ -133,7 +133,7 @@ H5G_is_empty_test(hid_t gid)
HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "both symbol table and link info messages found")
/* Get the link info */
- if(NULL == H5G_obj_get_linfo(&(grp->oloc), &linfo, H5AC_dxpl_id))
+ if(H5G_obj_get_linfo(&(grp->oloc), &linfo, H5AC_dxpl_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get link info")
/* Check for 'dense' link storage file addresses being defined */
@@ -343,7 +343,7 @@ H5G_is_new_dense_test(hid_t gid)
H5O_linfo_t linfo; /* Link info message */
/* Get the link info */
- if(NULL == H5G_obj_get_linfo(&(grp->oloc), &linfo, H5AC_dxpl_id))
+ if(H5G_obj_get_linfo(&(grp->oloc), &linfo, H5AC_dxpl_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get link info")
/* Check for 'dense' link storage file addresses being defined */
@@ -393,7 +393,7 @@ H5G_new_dense_info_test(hid_t gid, hsize_t *name_count, hsize_t *corder_count)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group")
/* Get the link info */
- if(NULL == H5G_obj_get_linfo(&(grp->oloc), &linfo, H5AC_dxpl_id))
+ if(H5G_obj_get_linfo(&(grp->oloc), &linfo, H5AC_dxpl_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get link info")
/* Check for 'dense' link storage file addresses being defined */
diff --git a/src/H5Gtraverse.c b/src/H5Gtraverse.c
index 7693343..87ebc74 100644
--- a/src/H5Gtraverse.c
+++ b/src/H5Gtraverse.c
@@ -633,7 +633,7 @@ H5G_traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target,
/* Traverse the path */
while((name = H5G_component(name, &nchars)) && *name) {
const char *s; /* Temporary string pointer */
- herr_t lookup_status; /* Status from object lookup */
+ htri_t lookup_status; /* Status from object lookup */
/*
* Copy the component name into a null-terminated buffer so
@@ -661,11 +661,11 @@ H5G_traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target,
} /* end if */
/* Get information for object in current group */
- /* (Defer issuing error for bad lookup until later) */
- lookup_status = H5G_obj_lookup(grp_loc.oloc, H5G_comp_g, &lnk/*out*/, dxpl_id);
+ if((lookup_status = H5G_obj_lookup(grp_loc.oloc, H5G_comp_g, &lnk/*out*/, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't look up component")
/* If the lookup was OK, build object location and traverse special links, etc. */
- if(lookup_status >= 0) {
+ if(lookup_status) {
/* Sanity check link and indicate it's valid */
HDassert(lnk.type >= H5L_TYPE_HARD);
HDassert(!HDstrcmp(H5G_comp_g, lnk.name));
@@ -688,14 +688,14 @@ H5G_traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target,
H5G_loc_t *cb_loc; /* Pointer to object location for callback */
/* Set callback parameters appropriately, based on link being found */
- if(lookup_status < 0) {
+ if(lookup_status) {
+ cb_lnk = &lnk;
+ cb_loc = &obj_loc;
+ } /* end if */
+ else {
HDassert(!obj_loc_valid);
cb_lnk = NULL;
cb_loc = NULL;
- } /* end if */
- else {
- cb_lnk = &lnk;
- cb_loc = &obj_loc;
} /* end else */
/* Call 'operator' routine */
@@ -706,7 +706,7 @@ H5G_traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target,
} /* end if */
/* Handle lookup failures now */
- if(lookup_status < 0) {
+ if(!lookup_status) {
/* If an intermediate group doesn't exist & flag is set, create the group */
if(target & H5G_CRT_INTMD_GROUP) {
const H5O_ginfo_t def_ginfo = H5G_CRT_GROUP_INFO_DEF; /* Default group info settings */
@@ -714,31 +714,32 @@ H5G_traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target,
H5O_ginfo_t par_ginfo; /* Group info settings for parent group */
H5O_linfo_t par_linfo; /* Link info settings for parent group */
H5O_linfo_t tmp_linfo; /* Temporary link info settings */
+ htri_t exists; /* Whether a group or link info message exists */
const H5O_ginfo_t *ginfo; /* Group info settings for new group */
const H5O_linfo_t *linfo; /* Link info settings for new group */
- /* Get the group info for parent group */
+ /* Check for the parent group having a group info message */
/* (OK if not found) */
- if(NULL == H5O_msg_read(grp_loc.oloc, H5O_GINFO_ID, &par_ginfo, dxpl_id)) {
- /* Clear error stack from not finding the group info message */
- H5E_clear_stack(NULL);
-
- /* Use default group info settings */
- ginfo = &def_ginfo;
+ if((exists = H5O_msg_exists(grp_loc.oloc, H5O_GINFO_ID, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to read object header")
+ if(exists) {
+ /* Get the group info for parent group */
+ if(NULL == H5O_msg_read(grp_loc.oloc, H5O_GINFO_ID, &par_ginfo, dxpl_id))
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "group info message not present")
+
+ /* Use parent group info settings */
+ ginfo = &par_ginfo;
} /* end if */
else
- ginfo = &par_ginfo;
+ /* Use default group info settings */
+ ginfo = &def_ginfo;
- /* Get the link info for parent group */
+ /* Check for the parent group having a link info message */
/* (OK if not found) */
- if(NULL == H5G_obj_get_linfo(grp_loc.oloc, &par_linfo, dxpl_id)) {
- /* Clear error stack from not finding the link info message */
- H5E_clear_stack(NULL);
-
- /* Use default link info settings */
- linfo = &def_linfo;
- } /* end if */
- else {
+ /* Get the link info for parent group */
+ if((exists = H5G_obj_get_linfo(grp_loc.oloc, &par_linfo, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to read object header")
+ if(exists) {
/* Only keep the creation order information from the parent
* group's link info
*/
@@ -746,7 +747,10 @@ H5G_traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target,
tmp_linfo.track_corder = par_linfo.track_corder;
tmp_linfo.index_corder = par_linfo.index_corder;
linfo = &tmp_linfo;
- } /* end else */
+ } /* end if */
+ else
+ /* Use default link info settings */
+ linfo = &def_linfo;
/* Create the intermediate group */
/* XXX: Should we allow user to control the group creation params here? -QAK */
diff --git a/src/H5HFcache.c b/src/H5HFcache.c
index f057c7c..8b29bc7 100644
--- a/src/H5HFcache.c
+++ b/src/H5HFcache.c
@@ -30,6 +30,7 @@
#define H5HF_PACKAGE /*suppress error about including H5HFpkg */
+
/***********/
/* Headers */
/***********/
@@ -41,6 +42,7 @@
#include "H5Vprivate.h" /* Vectors and arrays */
#include "H5WBprivate.h" /* Wrapped Buffers */
+
/****************/
/* Local Macros */
/****************/
@@ -89,6 +91,7 @@ static herr_t H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy,
static herr_t H5HF_cache_dblock_clear(H5F_t *f, H5HF_direct_t *dblock, hbool_t destroy);
static herr_t H5HF_cache_dblock_size(const H5F_t *f, const H5HF_direct_t *dblock, size_t *size_ptr);
+
/*********************/
/* Package Variables */
/*********************/
@@ -593,11 +596,12 @@ done:
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
herr_t
-H5HF_cache_hdr_dest(H5F_t UNUSED *f, H5HF_hdr_t *hdr)
+H5HF_cache_hdr_dest(H5F_t *f, H5HF_hdr_t *hdr)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_cache_hdr_dest)
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_cache_hdr_dest)
/*
* Check arguments.
@@ -605,6 +609,17 @@ H5HF_cache_hdr_dest(H5F_t UNUSED *f, H5HF_hdr_t *hdr)
HDassert(hdr);
HDassert(hdr->rc == 0);
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!hdr->cache_info.free_file_space_on_destroy || H5F_addr_defined(hdr->cache_info.addr));
+
+ /* Check for freeing file space for heap header */
+ if(hdr->cache_info.free_file_space_on_destroy) {
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_FHEAP_HDR, H5AC_dxpl_id, hdr->cache_info.addr, (hsize_t)hdr->heap_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap header")
+ } /* end if */
+
/* Free the block size lookup table for the doubling table */
H5HF_dtable_dest(&hdr->man_dtable);
@@ -615,7 +630,8 @@ H5HF_cache_hdr_dest(H5F_t UNUSED *f, H5HF_hdr_t *hdr)
/* Free the shared info itself */
(void)H5FL_FREE(H5HF_hdr_t, hdr);
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_cache_hdr_dest() */
@@ -1071,7 +1087,6 @@ done:
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
herr_t
H5HF_cache_iblock_dest(H5F_t *f, H5HF_indirect_t *iblock)
{
@@ -1089,6 +1104,17 @@ H5HF_cache_iblock_dest(H5F_t *f, H5HF_indirect_t *iblock)
HDfprintf(stderr, "%s: Destroying indirect block\n", FUNC);
#endif /* QAK */
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!iblock->cache_info.free_file_space_on_destroy || H5F_addr_defined(iblock->cache_info.addr));
+
+ /* Check for freeing file space for indirect block */
+ if(iblock->cache_info.free_file_space_on_destroy) {
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_FHEAP_IBLOCK, H5AC_dxpl_id, iblock->cache_info.addr, (hsize_t)iblock->size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block")
+ } /* end if */
+
/* Set the shared heap header's file context for this operation */
iblock->hdr->f = f;
@@ -1234,6 +1260,7 @@ H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_size,
/* Set block's internal information */
dblock->size = *size;
+ dblock->file_size = 0;
dblock->blk_off_size = H5HF_SIZEOF_OFFSET_LEN(dblock->size);
/* Allocate block buffer */
@@ -1622,7 +1649,6 @@ done:
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
herr_t
H5HF_cache_dblock_dest(H5F_t *f, H5HF_direct_t *dblock)
{
@@ -1638,6 +1664,20 @@ H5HF_cache_dblock_dest(H5F_t *f, H5HF_direct_t *dblock)
HDfprintf(stderr, "%s: Destroying direct block, dblock = %p\n", FUNC, dblock);
#endif /* QAK */
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!dblock->cache_info.free_file_space_on_destroy || H5F_addr_defined(dblock->cache_info.addr));
+
+ /* Check for freeing file space for direct block */
+ if(dblock->cache_info.free_file_space_on_destroy) {
+ /* Sanity check */
+ HDassert(dblock->file_size > 0);
+
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, H5AC_dxpl_id, dblock->cache_info.addr, dblock->file_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block")
+ } /* end if */
+
/* Set the shared heap header's file context for this operation */
dblock->hdr->f = f;
diff --git a/src/H5HFdblock.c b/src/H5HFdblock.c
index 9bc5b20..a4ce8b2 100644
--- a/src/H5HFdblock.c
+++ b/src/H5HFdblock.c
@@ -137,6 +137,7 @@ H5HF_man_dblock_create(hid_t dxpl_id, H5HF_hdr_t *hdr, H5HF_indirect_t *par_iblo
dblock->block_off = 0;
dblock->size = hdr->man_dtable.cparam.start_block_size;
} /* end else */
+ dblock->file_size = 0;
dblock->blk_off_size = H5HF_SIZEOF_OFFSET_LEN(dblock->size);
free_space = dblock->size - H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr);
@@ -220,6 +221,7 @@ H5HF_man_dblock_destroy(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_direct_t *dblock,
haddr_t dblock_addr)
{
hsize_t dblock_size; /* Size of direct block on disk */
+ unsigned cache_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting indirect block */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_destroy)
@@ -325,16 +327,15 @@ HDfprintf(stderr, "%s: Reversing iterator\n", FUNC);
HDfprintf(stderr, "%s: Before releasing direct block's space, dblock_addr = %a, dblock_size = %Hu\n", FUNC, dblock_addr, dblock_size);
#endif /* QAK */
- /* Release direct block's disk space */
- if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, dblock_addr, dblock_size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block")
-
- /* Remove direct block from metadata cache */
- if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block")
- dblock = NULL;
+ /* Indicate that the indirect block should be deleted & file space freed */
+ dblock->file_size = dblock_size;
+ cache_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
done:
+ /* Unprotect the indirect block, with appropriate flags */
+ if(dblock && H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, cache_flags) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_man_dblock_destroy() */
@@ -688,7 +689,7 @@ HDfprintf(stderr, "%s: dblock_addr = %a, dblock_size = %Hu\n", FUNC, dblock_addr
HDfprintf(stderr, "%s: Expunging direct block from cache\n", FUNC);
#endif /* QAK */
/* Evict the direct block from the metadata cache */
- if(H5AC_expunge_entry(f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr) < 0)
+ if(H5AC_expunge_entry(f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "unable to remove direct block from cache")
#ifdef QAK
HDfprintf(stderr, "%s: Done expunging direct block from cache\n", FUNC);
@@ -696,6 +697,19 @@ HDfprintf(stderr, "%s: Done expunging direct block from cache\n", FUNC);
} /* end if */
/* Release direct block's disk space */
+ /* (XXX: Under the best of circumstances, this block's space in the file
+ * would be freed in the H5AC_expunge_entry() call above (and the
+ * H5AC__FREE_FILE_SPACE_FLAG used there), but since the direct
+ * block structure might have a different size on disk than in
+ * the heap's 'abstract' address space, we would need to set the
+ * "file_size" field for the direct block structure. In order to
+ * do that, we'd have to protect/unprotect the direct block and
+ * that would add a bunch of unnecessary overhead to the process,
+ * so we just release the file space here, directly. When the
+ * revised metadata cache is operating, it will "know" the file
+ * size of each entry in the cache and we can the the
+ * H5AC_expunge_entry() method. -QAK)
+ */
if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, dblock_addr, dblock_size) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block")
diff --git a/src/H5HFhdr.c b/src/H5HFhdr.c
index ffd90e8..4fd527d 100644
--- a/src/H5HFhdr.c
+++ b/src/H5HFhdr.c
@@ -1505,6 +1505,7 @@ done:
herr_t
H5HF_hdr_delete(H5HF_hdr_t *hdr, hid_t dxpl_id)
{
+ unsigned cache_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting heap header */
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5HF_hdr_delete, FAIL)
@@ -1585,18 +1586,12 @@ HDfprintf(stderr, "%s: hdr->huge_bt2_addr = %a\n", FUNC, hdr->huge_bt2_addr);
HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to release fractal heap 'huge' objects and tracker")
} /* end if */
- /* Release header's disk space */
- if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_HDR, dxpl_id, hdr->heap_addr, (hsize_t)hdr->heap_size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to release fractal heap header")
-
- /* Finished deleting header */
- if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_HDR, hdr->heap_addr, hdr, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap header")
- hdr = NULL;
+ /* Indicate that the heap header should be deleted & file space freed */
+ cache_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
done:
- /* Unprotect the header, if an error occurred */
- if(hdr && H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_HDR, hdr->heap_addr, hdr, H5AC__NO_FLAGS_SET) < 0)
+ /* Unprotect the header with appropriate flags */
+ if(hdr && H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_HDR, hdr->heap_addr, hdr, cache_flags) < 0)
HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap header")
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5HFhuge.c b/src/H5HFhuge.c
index 198ef62..db9f7a1 100644
--- a/src/H5HFhuge.c
+++ b/src/H5HFhuge.c
@@ -545,7 +545,7 @@ H5HF_huge_get_obj_len(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
/* Look up object in v2 B-tree */
if(H5B2_find(hdr->f, dxpl_id, H5HF_BT2_FILT_INDIR, hdr->huge_bt2_addr,
- &search_rec, H5HF_huge_bt2_filt_indir_found, &found_rec) < 0)
+ &search_rec, H5HF_huge_bt2_filt_indir_found, &found_rec) != TRUE)
HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree")
/* Retrieve the object's length */
@@ -560,7 +560,7 @@ H5HF_huge_get_obj_len(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
/* Look up object in v2 B-tree */
if(H5B2_find(hdr->f, dxpl_id, H5HF_BT2_INDIR, hdr->huge_bt2_addr,
- &search_rec, H5HF_huge_bt2_indir_found, &found_rec) < 0)
+ &search_rec, H5HF_huge_bt2_indir_found, &found_rec) != TRUE)
HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree")
/* Retrieve the object's length */
@@ -628,7 +628,7 @@ H5HF_huge_op_real(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
/* Look up object in v2 B-tree */
if(H5B2_find(hdr->f, dxpl_id, H5HF_BT2_FILT_INDIR, hdr->huge_bt2_addr,
- &search_rec, H5HF_huge_bt2_filt_indir_found, &found_rec) < 0)
+ &search_rec, H5HF_huge_bt2_filt_indir_found, &found_rec) != TRUE)
HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree")
/* Retrieve the object's address & length */
@@ -645,7 +645,7 @@ H5HF_huge_op_real(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
/* Look up object in v2 B-tree */
if(H5B2_find(hdr->f, dxpl_id, H5HF_BT2_INDIR, hdr->huge_bt2_addr,
- &search_rec, H5HF_huge_bt2_indir_found, &found_rec) < 0)
+ &search_rec, H5HF_huge_bt2_indir_found, &found_rec) != TRUE)
HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree")
/* Retrieve the object's address & length */
@@ -764,7 +764,7 @@ H5HF_huge_write(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
/* Look up object in v2 B-tree */
if(H5B2_find(hdr->f, dxpl_id, H5HF_BT2_INDIR, hdr->huge_bt2_addr,
- &search_rec, H5HF_huge_bt2_indir_found, &found_rec) < 0)
+ &search_rec, H5HF_huge_bt2_indir_found, &found_rec) != TRUE)
HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree")
/* Retrieve the object's address & length */
diff --git a/src/H5HFiblock.c b/src/H5HFiblock.c
index 6eb288f..8f9eb24 100644
--- a/src/H5HFiblock.c
+++ b/src/H5HFiblock.c
@@ -310,12 +310,8 @@ HDfprintf(stderr, "%s: Removing indirect block from cache, iblock->addr = %a\n",
iblock->par_entry = 0;
} /* end if */
- /* Release space for indirect block on disk */
- if(H5MF_xfree(iblock->hdr->f, H5FD_MEM_FHEAP_IBLOCK, H5AC_dxpl_id, iblock->addr, (hsize_t)iblock->size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block disk space")
-
/* Evict the indirect block from the metadata cache */
- if(H5AC_expunge_entry(iblock->hdr->f, H5AC_dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr) < 0)
+ if(H5AC_expunge_entry(iblock->hdr->f, H5AC_dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, H5AC__FREE_FILE_SPACE_FLAG) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "unable to remove indirect block from cache")
} /* end if */
} /* end if */
@@ -1489,6 +1485,7 @@ H5HF_man_iblock_delete(H5HF_hdr_t *hdr, hid_t dxpl_id, haddr_t iblock_addr,
H5HF_indirect_t *iblock; /* Pointer to indirect block */
unsigned row, col; /* Current row & column in indirect block */
unsigned entry; /* Current entry in row */
+ unsigned cache_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting indirect block */
hbool_t did_protect; /* Whether we protected the indirect block or not */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1550,10 +1547,6 @@ HDfprintf(stderr, "%s: iblock_addr = %a, iblock_nrows = %u\n", FUNC, iblock_addr
} /* end for */
} /* end row */
- /* Release indirect block's disk space */
- if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, iblock_addr, (hsize_t)iblock->size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block")
-
#ifndef NDEBUG
{
unsigned iblock_status = 0; /* Indirect block's status in the metadata cache */
@@ -1567,12 +1560,14 @@ HDfprintf(stderr, "%s: iblock_addr = %a, iblock_nrows = %u\n", FUNC, iblock_addr
}
#endif /* NDEBUG */
- /* Finished deleting indirect block in metadata cache */
- if(H5HF_man_iblock_unprotect(iblock, dxpl_id, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG, did_protect) < 0)
- HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
- iblock = NULL;
+ /* Indicate that the indirect block should be deleted & file space freed */
+ cache_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
done:
+ /* Unprotect the indirect block, with appropriate flags */
+ if(iblock && H5HF_man_iblock_unprotect(iblock, dxpl_id, cache_flags, did_protect) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_man_iblock_delete() */
diff --git a/src/H5HFpkg.h b/src/H5HFpkg.h
index 71691c9..bf80164 100644
--- a/src/H5HFpkg.h
+++ b/src/H5HFpkg.h
@@ -403,6 +403,7 @@ typedef struct H5HF_direct_t {
H5HF_indirect_t *parent; /* Shared parent indirect block info */
unsigned par_entry; /* Entry in parent's table */
size_t size; /* Size of direct block */
+ hsize_t file_size; /* Size of direct block in file (only valid when block's space is being freed) */
unsigned blk_off_size; /* Size of offsets in the block */
uint8_t *blk; /* Pointer to buffer containing block data */
diff --git a/src/H5HFsection.c b/src/H5HFsection.c
index 091ec79..81b353f 100644
--- a/src/H5HFsection.c
+++ b/src/H5HFsection.c
@@ -206,6 +206,7 @@ H5FS_section_class_t H5HF_FSPACE_SECT_CLS_SINGLE[1] = {{
H5HF_sect_single_shrink, /* Shrink container w/section */
H5HF_sect_single_free, /* Free section */
H5HF_sect_single_valid, /* Check validity of section */
+ NULL, /* Split section node for alignment */
NULL, /* Dump debugging for section */
}};
@@ -234,6 +235,7 @@ H5FS_section_class_t H5HF_FSPACE_SECT_CLS_FIRST_ROW[1] = {{
H5HF_sect_row_shrink, /* Shrink container w/section */
H5HF_sect_row_free, /* Free section */
H5HF_sect_row_valid, /* Check validity of section */
+ NULL, /* Split section node for alignment */
H5HF_sect_row_debug, /* Dump debugging for section */
}};
@@ -259,6 +261,7 @@ H5FS_section_class_t H5HF_FSPACE_SECT_CLS_NORMAL_ROW[1] = {{
NULL, /* Shrink container w/section */
H5HF_sect_row_free, /* Free section */
H5HF_sect_row_valid, /* Check validity of section */
+ NULL, /* Split section node for alignment */
H5HF_sect_row_debug, /* Dump debugging for section */
}};
@@ -287,6 +290,7 @@ H5FS_section_class_t H5HF_FSPACE_SECT_CLS_INDIRECT[1] = {{
NULL, /* Shrink container w/section */
NULL, /* Free section */
NULL, /* Check validity of section */
+ NULL, /* Split section node for alignment */
NULL, /* Dump debugging for section */
}};
diff --git a/src/H5HFspace.c b/src/H5HFspace.c
index 77d8b1b..7978a96 100644
--- a/src/H5HFspace.c
+++ b/src/H5HFspace.c
@@ -44,6 +44,8 @@
#define H5HF_FSPACE_SHRINK 80 /* Percent of "normal" size to shrink serialized free space size */
#define H5HF_FSPACE_EXPAND 120 /* Percent of "normal" size to expand serialized free space size */
+#define H5HF_FSPACE_THRHD_DEF 1 /* Default: no alignment threshold */
+#define H5HF_FSPACE_ALIGN_DEF 1 /* Default: no alignment */
/******************/
/* Local Typedefs */
@@ -91,6 +93,11 @@
* koziol@ncsa.uiuc.edu
* May 2 2006
*
+ * Modifications:
+ * Vailin Choi, July 29th, 2008
+ * Pass values of alignment and threshold to FS_create() and FS_open()
+ * for handling alignment.
+ *
*-------------------------------------------------------------------------
*/
herr_t
@@ -114,7 +121,7 @@ H5HF_space_start(H5HF_hdr_t *hdr, hid_t dxpl_id, hbool_t may_create)
if(H5F_addr_defined(hdr->fs_addr)) {
/* Open an existing free space structure for the heap */
if(NULL == (hdr->fspace = H5FS_open(hdr->f, dxpl_id, hdr->fs_addr,
- NELMTS(classes), classes, hdr)))
+ NELMTS(classes), classes, hdr, H5HF_FSPACE_THRHD_DEF, H5HF_FSPACE_ALIGN_DEF)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize free space info")
} /* end if */
else {
@@ -131,8 +138,9 @@ H5HF_space_start(H5HF_hdr_t *hdr, hid_t dxpl_id, hbool_t may_create)
/* Create the free space structure for the heap */
if(NULL == (hdr->fspace = H5FS_create(hdr->f, dxpl_id, &hdr->fs_addr,
- &fs_create, NELMTS(classes), classes, hdr)))
+ &fs_create, NELMTS(classes), classes, hdr, H5HF_FSPACE_THRHD_DEF, H5HF_FSPACE_ALIGN_DEF)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize free space info")
+ HDassert(H5F_addr_defined(hdr->fs_addr));
} /* end if */
} /* end else */
@@ -351,7 +359,7 @@ H5HF_space_close(H5HF_hdr_t *hdr, hid_t dxpl_id)
hsize_t nsects; /* Number of sections for this heap */
/* Retrieve the number of sections for this heap */
- if(H5FS_get_sect_count(hdr->fspace, &nsects) < 0)
+ if(H5FS_sect_stats(hdr->fspace, NULL, &nsects) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTCOUNT, FAIL, "can't query free space section count")
#ifdef QAK
HDfprintf(stderr, "%s: nsects = %Hu\n", FUNC, nsects);
diff --git a/src/H5HG.c b/src/H5HG.c
index f867147..b5f8988 100644
--- a/src/H5HG.c
+++ b/src/H5HG.c
@@ -37,33 +37,28 @@
* in the collection, and temporal locality.
*/
+/****************/
+/* Module Setup */
+/****************/
+
#define H5F_PACKAGE /*suppress error about including H5Fpkg */
#define H5HG_PACKAGE /*suppress error about including H5HGpkg */
+/***********/
+/* Headers */
+/***********/
#include "H5private.h" /* Generic Functions */
-#include "H5ACprivate.h" /* Metadata cache */
#include "H5Eprivate.h" /* Error handling */
#include "H5Fpkg.h" /* File access */
-#include "H5FLprivate.h" /* Free lists */
#include "H5HGpkg.h" /* Global heaps */
#include "H5MFprivate.h" /* File memory management */
#include "H5MMprivate.h" /* Memory management */
-/* Private macros */
-/*
- * Global heap collection version.
- */
-#define H5HG_VERSION 1
-
-/*
- * All global heap collections are at least this big. This allows us to read
- * most collections with a single read() since we don't have to read a few
- * bytes of header to figure out the size. If the heap is larger than this
- * then a second read gets the rest after we've decoded the header.
- */
-#define H5HG_MINSIZE 4096
+/****************/
+/* Local Macros */
+/****************/
/*
* Limit global heap collections to the some reasonable size. This is
@@ -73,12 +68,6 @@
#define H5HG_MAXSIZE 65536
/*
- * Maximum length of the CWFS list, the list of remembered collections that
- * have free space.
- */
-#define H5HG_NCWFS 16
-
-/*
* The maximum number of links allowed to a global heap object.
*/
#define H5HG_MAXLINK 65535
@@ -88,63 +77,47 @@
*/
#define H5HG_MAXIDX 65535
-/*
- * The size of the collection header, always a multiple of the alignment so
- * that the stuff that follows the header is aligned.
- */
-#define H5HG_SIZEOF_HDR(f) \
- H5HG_ALIGN(4 + /*magic number */ \
- 1 + /*version number */ \
- 3 + /*reserved */ \
- H5F_SIZEOF_SIZE(f)) /*collection size */
-/*
- * The initial guess for the number of messages in a collection. We assume
- * that all objects in that collection are zero length, giving the maximum
- * possible number of objects in the collection. The collection itself has
- * some overhead and each message has some overhead. The `+2' accounts for
- * rounding and for the free space object.
- */
-#define H5HG_NOBJS(f,z) (int)((((z)-H5HG_SIZEOF_HDR(f))/ \
- H5HG_SIZEOF_OBJHDR(f)+2))
+/******************/
+/* Local Typedefs */
+/******************/
+
-/* Private typedefs */
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
-/* PRIVATE PROTOTYPES */
static haddr_t H5HG_create(H5F_t *f, hid_t dxpl_id, size_t size);
-#ifdef NOT_YET
-static void *H5HG_peek(H5F_t *f, hid_t dxpl_id, H5HG_t *hobj);
-#endif /* NOT_YET */
-
-/* Metadata cache callbacks */
-static H5HG_heap_t *H5HG_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1,
- void *udata2);
-static herr_t H5HG_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr,
- H5HG_heap_t *heap, unsigned UNUSED * flags_ptr);
-static herr_t H5HG_dest(H5F_t *f, H5HG_heap_t *heap);
-static herr_t H5HG_clear(H5F_t *f, H5HG_heap_t *heap, hbool_t destroy);
-static herr_t H5HG_compute_size(const H5F_t *f, const H5HG_heap_t *heap, size_t *size_ptr);
-/*
- * H5HG inherits cache-like properties from H5AC
- */
-const H5AC_class_t H5AC_GHEAP[1] = {{
- H5AC_GHEAP_ID,
- (H5AC_load_func_t)H5HG_load,
- (H5AC_flush_func_t)H5HG_flush,
- (H5AC_dest_func_t)H5HG_dest,
- (H5AC_clear_func_t)H5HG_clear,
- (H5AC_size_func_t)H5HG_compute_size,
-}};
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
/* Declare a free list to manage the H5HG_t struct */
-H5FL_DEFINE_STATIC(H5HG_heap_t);
+H5FL_DEFINE(H5HG_heap_t);
/* Declare a free list to manage sequences of H5HG_obj_t's */
-H5FL_SEQ_DEFINE_STATIC(H5HG_obj_t);
+H5FL_SEQ_DEFINE(H5HG_obj_t);
/* Declare a PQ free list to manage heap chunks */
-H5FL_BLK_DEFINE_STATIC(heap_chunk);
+H5FL_BLK_DEFINE(gheap_chunk);
+
/*-------------------------------------------------------------------------
@@ -213,7 +186,7 @@ H5HG_create (H5F_t *f, hid_t dxpl_id, size_t size)
heap->addr = addr;
heap->size = size;
- if (NULL==(heap->chunk = H5FL_BLK_MALLOC (heap_chunk,size)))
+ if (NULL==(heap->chunk = H5FL_BLK_MALLOC (gheap_chunk,size)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, \
"memory allocation failed");
#ifdef H5_CLEAR_MEMORY
@@ -294,361 +267,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5HG_load
- *
- * Purpose: Loads a global heap collection from disk.
- *
- * Return: Success: Ptr to a global heap collection.
- *
- * Failure: NULL
- *
- * Programmer: Robb Matzke
- * Friday, March 27, 1998
- *
- * Modifications:
- * Robb Matzke, 1999-07-28
- * The ADDR argument is passed by value.
- *
- * Quincey Koziol, 2002-7-180
- * Added dxpl parameter to allow more control over I/O from metadata
- * cache.
- *-------------------------------------------------------------------------
- */
-static H5HG_heap_t *
-H5HG_load (H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1,
- void UNUSED * udata2)
-{
- H5HG_heap_t *heap = NULL;
- uint8_t *p = NULL;
- int i;
- size_t nalloc, need;
- size_t max_idx=0; /* The maximum index seen */
- H5HG_heap_t *ret_value = NULL; /* Return value */
-
- FUNC_ENTER_NOAPI(H5HG_load, NULL);
-
- /* check arguments */
- assert (f);
- assert (H5F_addr_defined (addr));
- assert (!udata1);
- assert (!udata2);
-
- /* Read the initial 4k page */
- if(NULL == (heap = H5FL_CALLOC (H5HG_heap_t)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
- heap->addr = addr;
- if(NULL == (heap->chunk = H5FL_BLK_MALLOC(heap_chunk, (size_t)H5HG_MINSIZE)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
- if(H5F_block_read(f, H5FD_MEM_GHEAP, addr, (size_t)H5HG_MINSIZE, dxpl_id, heap->chunk)<0)
- HGOTO_ERROR (H5E_HEAP, H5E_READERROR, NULL, "unable to read global heap collection");
-
- /* Magic number */
- if(HDmemcmp(heap->chunk, H5HG_MAGIC, (size_t)H5_SIZEOF_MAGIC))
- HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL, "bad global heap collection signature");
- p = heap->chunk + H5_SIZEOF_MAGIC;
-
- /* Version */
- if (H5HG_VERSION!=*p++)
- HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL, "wrong version number in global heap");
-
- /* Reserved */
- p += 3;
-
- /* Size */
- H5F_DECODE_LENGTH (f, p, heap->size);
- assert (heap->size>=H5HG_MINSIZE);
-
- /*
- * If we didn't read enough in the first try, then read the rest of the
- * collection now.
- */
- if (heap->size > H5HG_MINSIZE) {
- haddr_t next_addr = addr + (hsize_t)H5HG_MINSIZE;
- if (NULL==(heap->chunk = H5FL_BLK_REALLOC (heap_chunk, heap->chunk, heap->size)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
- if (H5F_block_read (f, H5FD_MEM_GHEAP, next_addr, (heap->size-H5HG_MINSIZE), dxpl_id, heap->chunk+H5HG_MINSIZE)<0)
- HGOTO_ERROR (H5E_HEAP, H5E_READERROR, NULL, "unable to read global heap collection");
- }
-
- /* Decode each object */
- p = heap->chunk + H5HG_SIZEOF_HDR (f);
- nalloc = H5HG_NOBJS (f, heap->size);
- if (NULL==(heap->obj = H5FL_SEQ_MALLOC (H5HG_obj_t,nalloc)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
- heap->obj[0].size=heap->obj[0].nrefs=0;
- heap->obj[0].begin=NULL;
-
- heap->nalloc = nalloc;
- while (p<heap->chunk+heap->size) {
- if (p+H5HG_SIZEOF_OBJHDR(f)>heap->chunk+heap->size) {
- /*
- * The last bit of space is too tiny for an object header, so we
- * assume that it's free space.
- */
- assert (NULL==heap->obj[0].begin);
- heap->obj[0].size = (heap->chunk+heap->size) - p;
- heap->obj[0].begin = p;
- p += heap->obj[0].size;
- } else {
- unsigned idx;
- uint8_t *begin = p;
-
- UINT16DECODE (p, idx);
-
- /* Check if we need more room to store heap objects */
- if(idx>=heap->nalloc) {
- size_t new_alloc; /* New allocation number */
- H5HG_obj_t *new_obj; /* New array of object descriptions */
-
- /* Determine the new number of objects to index */
- new_alloc=MAX(heap->nalloc*2,(idx+1));
-
- /* Reallocate array of objects */
- if (NULL==(new_obj = H5FL_SEQ_REALLOC (H5HG_obj_t, heap->obj, new_alloc)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
-
- /* Update heap information */
- heap->nalloc=new_alloc;
- heap->obj=new_obj;
- } /* end if */
-
- UINT16DECODE (p, heap->obj[idx].nrefs);
- p += 4; /*reserved*/
- H5F_DECODE_LENGTH (f, p, heap->obj[idx].size);
- heap->obj[idx].begin = begin;
- /*
- * The total storage size includes the size of the object header
- * and is zero padded so the next object header is properly
- * aligned. The last bit of space is the free space object whose
- * size is never padded and already includes the object header.
- */
- if (idx>0) {
- need = H5HG_SIZEOF_OBJHDR(f) + H5HG_ALIGN(heap->obj[idx].size);
-
- /* Check for "gap" in index numbers (caused by deletions) and fill in heap object values */
- if(idx>(max_idx+1))
- HDmemset(&heap->obj[max_idx+1],0,sizeof(H5HG_obj_t)*(idx-(max_idx+1)));
- max_idx=idx;
- } else {
- need = heap->obj[idx].size;
- }
- p = begin + need;
- }
- }
- assert(p==heap->chunk+heap->size);
- assert(H5HG_ISALIGNED(heap->obj[0].size));
-
- /* Set the next index value to use */
- if(max_idx>0)
- heap->nused=max_idx+1;
- else
- heap->nused=1;
-
- /*
- * Add the new heap to the CWFS list, removing some other entry if
- * necessary to make room. We remove the right-most entry that has less
- * free space than this heap.
- */
- if (!f->shared->cwfs) {
- f->shared->cwfs = (H5HG_heap_t **)H5MM_malloc(H5HG_NCWFS * sizeof(H5HG_heap_t *));
- if(NULL == f->shared->cwfs)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- f->shared->ncwfs = 1;
- f->shared->cwfs[0] = heap;
- } else if(H5HG_NCWFS == f->shared->ncwfs) {
- for(i = H5HG_NCWFS - 1; i >= 0; --i) {
- if(f->shared->cwfs[i]->obj[0].size < heap->obj[0].size) {
- HDmemmove(f->shared->cwfs + 1, f->shared->cwfs, i * sizeof(H5HG_heap_t *));
- f->shared->cwfs[0] = heap;
- break;
- } /* end if */
- } /* end for */
- } else {
- HDmemmove(f->shared->cwfs + 1, f->shared->cwfs, f->shared->ncwfs * sizeof(H5HG_heap_t *));
- f->shared->ncwfs += 1;
- f->shared->cwfs[0] = heap;
- } /* end else */
-
- ret_value = heap;
-
-done:
- if (!ret_value && heap) {
- if(H5HG_dest(f,heap)<0)
- HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "unable to destroy global heap collection");
- }
- FUNC_LEAVE_NOAPI(ret_value);
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HG_flush
- *
- * Purpose: Flushes a global heap collection from memory to disk if it's
- * dirty. Optionally deletes teh heap from memory.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * Friday, March 27, 1998
- *
- * Modifications:
- * Robb Matzke, 1999-07-28
- * The ADDR argument is passed by value.
- *
- * Quincey Koziol, 2002-7-180
- * Added dxpl parameter to allow more control over I/O from metadata
- * cache.
- *
- * JRM -- 8/21/06
- * Added the flags_ptr parameter. This parameter exists to
- * allow the flush routine to report to the cache if the
- * entry is resized or renamed as a result of the flush.
- * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry.
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HG_flush (H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HG_heap_t *heap, unsigned UNUSED * flags_ptr)
-{
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5HG_flush, FAIL);
-
- /* Check arguments */
- assert (f);
- assert (H5F_addr_defined (addr));
- assert (H5F_addr_eq (addr, heap->addr));
- assert (heap);
-
- if (heap->cache_info.is_dirty) {
- if (H5F_block_write (f, H5FD_MEM_GHEAP, addr, heap->size, dxpl_id, heap->chunk)<0)
- HGOTO_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write global heap collection to file");
- heap->cache_info.is_dirty = FALSE;
- }
-
- if (destroy) {
- if(H5HG_dest(f,heap)<0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy global heap collection");
- }
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HG_dest
- *
- * Purpose: Destroys a global heap collection in memory
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Wednesday, January 15, 2003
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HG_dest (H5F_t *f, H5HG_heap_t *heap)
-{
- int i;
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HG_dest)
-
- /* Check arguments */
- HDassert(heap);
-
- /* Verify that node is clean */
- HDassert(heap->cache_info.is_dirty == FALSE);
-
- for(i = 0; i < f->shared->ncwfs; i++) {
- if(f->shared->cwfs[i] == heap) {
- f->shared->ncwfs -= 1;
- HDmemmove(f->shared->cwfs + i, f->shared->cwfs + i + 1, (f->shared->ncwfs - i) * sizeof(H5HG_heap_t *));
- break;
- } /* end if */
- } /* end for */
-
- if(heap->chunk)
- heap->chunk = H5FL_BLK_FREE(heap_chunk, heap->chunk);
- if(heap->obj)
- heap->obj = (H5HG_obj_t *)H5FL_SEQ_FREE(H5HG_obj_t, heap->obj);
- (void)H5FL_FREE(H5HG_heap_t, heap);
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5HG_dest() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HG_clear
- *
- * Purpose: Mark a global heap in memory as non-dirty.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Thursday, March 20, 2003
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HG_clear(H5F_t *f, H5HG_heap_t *heap, hbool_t destroy)
-{
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT(H5HG_clear);
-
- /* Check arguments */
- assert (heap);
-
- /* Mark heap as clean */
- heap->cache_info.is_dirty = FALSE;
-
- if (destroy)
- if (H5HG_dest(f, heap) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy global heap collection");
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* H5HG_clear() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HG_compute_size
- *
- * Purpose: Compute the size in bytes of the specified instance of
- * H5HG_heap_t on disk, and return it in *len_ptr. On failure,
- * the value of *len_ptr is undefined.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: John Mainzer
- * 5/13/04
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HG_compute_size(const H5F_t UNUSED *f, const H5HG_heap_t *heap, size_t *size_ptr)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HG_compute_size);
-
- /* Check arguments */
- HDassert(heap);
- HDassert(size_ptr);
-
- *size_ptr = heap->size;
-
- FUNC_LEAVE_NOAPI(SUCCEED);
-} /* H5HG_compute_size() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5HG_alloc
*
* Purpose: Given a heap with enough free space, this function will split
@@ -714,7 +332,7 @@ H5HG_alloc (H5F_t *f, H5HG_heap_t *heap, size_t size, unsigned * heap_flags_ptr)
/* Reallocate array of objects */
if (NULL==(new_obj = H5FL_SEQ_REALLOC (H5HG_obj_t, heap->obj, new_alloc)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, 0, "memory allocation failed");
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "memory allocation failed")
/* Update heap information */
heap->nalloc=new_alloc;
@@ -803,75 +421,60 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5HG_extend (H5F_t *f, H5HG_heap_t *heap, size_t size, unsigned * heap_flags_ptr)
+H5HG_extend(H5F_t *f, H5HG_heap_t *heap, size_t need, unsigned *heap_flags_ptr)
{
- size_t need; /* Actual space needed to store object */
size_t old_size; /* Previous size of the heap's chunk */
- uint8_t *new_chunk=NULL; /* Pointer to new chunk information */
+ uint8_t *new_chunk = NULL; /* Pointer to new chunk information */
uint8_t *p = NULL; /* Pointer to raw heap info */
unsigned u; /* Local index variable */
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5HG_extend);
+ FUNC_ENTER_NOAPI_NOINIT(H5HG_extend)
/* Check args */
- assert (f);
- assert (heap);
- assert (heap_flags_ptr);
-
- /* Compute total space need to add to this heap */
- need = H5HG_SIZEOF_OBJHDR(f) + H5HG_ALIGN(size);
-
- /* Decrement the amount needed in the heap by the amount of free space available */
- assert(need>heap->obj[0].size);
- need -= heap->obj[0].size;
-
- /* Don't do anything less than double the size of the heap */
- need = MAX(heap->size,need);
-
- /* Extend the space allocated for this heap on disk */
- if(H5MF_extend(f,H5FD_MEM_GHEAP,heap->addr,(hsize_t)heap->size,(hsize_t)need)<0)
- HGOTO_ERROR (H5E_HEAP, H5E_NOSPACE, FAIL, "can't extend heap on disk");
+ HDassert(f);
+ HDassert(heap);
+ HDassert(heap_flags_ptr);
/* Re-allocate the heap information in memory */
- if (NULL==(new_chunk = H5FL_BLK_REALLOC (heap_chunk, heap->chunk, heap->size+need)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "new heap allocation failed");
+ if(NULL == (new_chunk = H5FL_BLK_REALLOC(gheap_chunk, heap->chunk, (heap->size + need))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "new heap allocation failed")
#ifdef H5_CLEAR_MEMORY
HDmemset(new_chunk + heap->size, 0, need);
#endif /* H5_CLEAR_MEMORY */
/* Adjust the size of the heap */
- old_size=heap->size;
- heap->size+=need;
+ old_size = heap->size;
+ heap->size += need;
/* Encode the new size of the heap */
p = new_chunk + H5_SIZEOF_MAGIC + 1 /* version */ + 3 /* reserved */;
- H5F_ENCODE_LENGTH (f, p, heap->size);
+ H5F_ENCODE_LENGTH(f, p, heap->size);
/* Move the pointers to the existing objects to their new locations */
- for (u=0; u<heap->nused; u++)
+ for(u = 0; u < heap->nused; u++)
if(heap->obj[u].begin)
heap->obj[u].begin = new_chunk + (heap->obj[u].begin - heap->chunk);
/* Update the heap chunk pointer now */
- heap->chunk=new_chunk;
+ heap->chunk = new_chunk;
/* Update the free space information for the heap */
- heap->obj[0].size+=need;
- if(heap->obj[0].begin==NULL)
- heap->obj[0].begin=heap->chunk+old_size;
+ heap->obj[0].size += need;
+ if(heap->obj[0].begin == NULL)
+ heap->obj[0].begin = heap->chunk+old_size;
p = heap->obj[0].begin;
UINT16ENCODE(p, 0); /*id*/
UINT16ENCODE(p, 0); /*nrefs*/
UINT32ENCODE(p, 0); /*reserved*/
- H5F_ENCODE_LENGTH (f, p, heap->obj[0].size);
+ H5F_ENCODE_LENGTH(f, p, heap->obj[0].size);
assert(H5HG_ISALIGNED(heap->obj[0].size));
/* Mark the heap as dirty */
*heap_flags_ptr |= H5AC__DIRTIED_FLAG;
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HG_extend() */
@@ -922,26 +525,26 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5HG_insert (H5F_t *f, hid_t dxpl_id, size_t size, void *obj, H5HG_t *hobj/*out*/)
+H5HG_insert(H5F_t *f, hid_t dxpl_id, size_t size, void *obj, H5HG_t *hobj/*out*/)
{
size_t need; /*total space needed for object */
- int cwfsno;
+ int cwfsno;
size_t idx;
haddr_t addr = HADDR_UNDEF;
H5HG_heap_t *heap = NULL;
unsigned heap_flags = H5AC__NO_FLAGS_SET;
- hbool_t found=0; /* Flag to indicate a heap with enough space was found */
- herr_t ret_value=SUCCEED; /* Return value */
+ hbool_t found = FALSE; /* Flag to indicate a heap with enough space was found */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5HG_insert, FAIL);
+ FUNC_ENTER_NOAPI(H5HG_insert, FAIL)
/* Check args */
- assert (f);
- assert (0==size || obj);
- assert (hobj);
+ HDassert(f);
+ HDassert(0 == size || obj);
+ HDassert(hobj);
- if (0==(f->intent & H5F_ACC_RDWR))
- HGOTO_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file");
+ if(0 == (f->intent & H5F_ACC_RDWR))
+ HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file")
/* Find a large enough collection on the CWFS list */
need = H5HG_SIZEOF_OBJHDR(f) + H5HG_ALIGN(size);
@@ -970,20 +573,18 @@ H5HG_insert (H5F_t *f, hid_t dxpl_id, size_t size, void *obj, H5HG_t *hobj/*out*
* take any of it as gospel.
* JRM - 5/24/04
*/
-
- for (cwfsno=0; cwfsno<f->shared->ncwfs; cwfsno++) {
- if (f->shared->cwfs[cwfsno]->obj[0].size>=need) {
+ for(cwfsno = 0; cwfsno < f->shared->ncwfs; cwfsno++)
+ if(f->shared->cwfs[cwfsno]->obj[0].size >= need) {
addr = f->shared->cwfs[cwfsno]->addr;
- found=1;
+ found = TRUE;
break;
} /* end if */
- } /* end for */
/*
* If we didn't find any collection with enough free space the check if
* we can extend any of the collections to make enough room.
*/
- if (!found) {
+ if(!found) {
size_t new_need;
for (cwfsno=0; cwfsno<f->shared->ncwfs; cwfsno++) {
@@ -991,12 +592,19 @@ H5HG_insert (H5F_t *f, hid_t dxpl_id, size_t size, void *obj, H5HG_t *hobj/*out*
new_need -= f->shared->cwfs[cwfsno]->obj[0].size;
new_need = MAX(f->shared->cwfs[cwfsno]->size, new_need);
- if((f->shared->cwfs[cwfsno]->size+new_need)<=H5HG_MAXSIZE && H5MF_can_extend(f,H5FD_MEM_GHEAP,f->shared->cwfs[cwfsno]->addr,(hsize_t)f->shared->cwfs[cwfsno]->size,(hsize_t)new_need)) {
- if(H5HG_extend(f,f->shared->cwfs[cwfsno],size, &heap_flags)<0)
- HGOTO_ERROR (H5E_HEAP, H5E_CANTINIT, FAIL, "unable to extend global heap collection");
- addr = f->shared->cwfs[cwfsno]->addr;
- found=1;
- break;
+ if((f->shared->cwfs[cwfsno]->size + new_need) <= H5HG_MAXSIZE) {
+ htri_t extended; /* Whether the heap was extended */
+
+ extended = H5MF_try_extend(f, dxpl_id, H5FD_MEM_GHEAP, f->shared->cwfs[cwfsno]->addr, (hsize_t)f->shared->cwfs[cwfsno]->size, (hsize_t)new_need);
+ if(extended < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "error trying to extend heap")
+ else if(extended == TRUE) {
+ if(H5HG_extend(f, f->shared->cwfs[cwfsno], new_need, &heap_flags) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to extend global heap collection")
+ addr = f->shared->cwfs[cwfsno]->addr;
+ found = TRUE;
+ break;
+ } /* end if */
} /* end if */
} /* end for */
} /* end if */
@@ -1005,43 +613,40 @@ H5HG_insert (H5F_t *f, hid_t dxpl_id, size_t size, void *obj, H5HG_t *hobj/*out*
* If we didn't find any collection with enough free space then allocate a
* new collection large enough for the message plus the collection header.
*/
- if (!found) {
-
+ if(!found) {
addr = H5HG_create(f, dxpl_id, need+H5HG_SIZEOF_HDR (f));
- if ( ! H5F_addr_defined(addr) )
- HGOTO_ERROR (H5E_HEAP, H5E_CANTINIT, FAIL, \
- "unable to allocate a global heap collection");
+ if(!H5F_addr_defined(addr))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to allocate a global heap collection")
cwfsno = 0;
} /* end if */
else {
-
/* Move the collection forward in the CWFS list, if it's not
* already at the front
*/
- if (cwfsno>0) {
+ if(cwfsno > 0) {
H5HG_heap_t *tmp = f->shared->cwfs[cwfsno];
- f->shared->cwfs[cwfsno] = f->shared->cwfs[cwfsno-1];
- f->shared->cwfs[cwfsno-1] = tmp;
+
+ f->shared->cwfs[cwfsno] = f->shared->cwfs[cwfsno - 1];
+ f->shared->cwfs[cwfsno - 1] = tmp;
--cwfsno;
} /* end if */
} /* end else */
HDassert(H5F_addr_defined(addr));
-
- if(NULL == (heap = (H5HG_heap_t *)H5AC_protect(f, dxpl_id, H5AC_GHEAP, addr, NULL, NULL, H5AC_WRITE)) )
- HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap");
+ if(NULL == (heap = (H5HG_heap_t *)H5AC_protect(f, dxpl_id, H5AC_GHEAP, addr, NULL, NULL, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap")
/* Split the free space to make room for the new object */
- idx = H5HG_alloc (f, heap, size, &heap_flags);
+ idx = H5HG_alloc(f, heap, size, &heap_flags);
/* Copy data into the heap */
- if(size>0) {
- HDmemcpy(heap->obj[idx].begin+H5HG_SIZEOF_OBJHDR(f), obj, size);
+ if(size > 0) {
+ HDmemcpy(heap->obj[idx].begin + H5HG_SIZEOF_OBJHDR(f), obj, size);
#ifdef OLD_WAY
/* Don't bother zeroing out the rest of the info in the heap -QAK */
- HDmemset(heap->obj[idx].begin+H5HG_SIZEOF_OBJHDR(f)+size, 0,
- need-(H5HG_SIZEOF_OBJHDR(f)+size));
+ HDmemset(heap->obj[idx].begin + H5HG_SIZEOF_OBJHDR(f) + size, 0,
+ need - (H5HG_SIZEOF_OBJHDR(f) + size));
#endif /* OLD_WAY */
} /* end if */
heap_flags |= H5AC__DIRTIED_FLAG;
@@ -1051,10 +656,10 @@ H5HG_insert (H5F_t *f, hid_t dxpl_id, size_t size, void *obj, H5HG_t *hobj/*out*
hobj->idx = idx;
done:
- if ( heap && H5AC_unprotect(f, dxpl_id, H5AC_GHEAP, heap->addr, heap, heap_flags) < 0 )
- HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to unprotect heap.");
+ if(heap && H5AC_unprotect(f, dxpl_id, H5AC_GHEAP, heap->addr, heap, heap_flags) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to unprotect heap.")
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5HG_insert() */
@@ -1180,19 +785,19 @@ H5HG_link (H5F_t *f, hid_t dxpl_id, const H5HG_t *hobj, int adjust)
assert (f);
assert (hobj);
if (0==(f->intent & H5F_ACC_RDWR))
- HGOTO_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file");
+ HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file")
if(adjust!=0) {
/* Load the heap */
if (NULL == (heap = (H5HG_heap_t *)H5AC_protect(f, dxpl_id, H5AC_GHEAP, hobj->addr, NULL, NULL, H5AC_WRITE)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap");
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap")
assert (hobj->idx<heap->nused);
assert (heap->obj[hobj->idx].begin);
if (heap->obj[hobj->idx].nrefs+adjust<0)
- HGOTO_ERROR (H5E_HEAP, H5E_BADRANGE, FAIL, "new link count would be out of range");
+ HGOTO_ERROR (H5E_HEAP, H5E_BADRANGE, FAIL, "new link count would be out of range")
if (heap->obj[hobj->idx].nrefs+adjust>H5HG_MAXLINK)
- HGOTO_ERROR (H5E_HEAP, H5E_BADVALUE, FAIL, "new link count would be out of range");
+ HGOTO_ERROR (H5E_HEAP, H5E_BADVALUE, FAIL, "new link count would be out of range")
heap->obj[hobj->idx].nrefs += adjust;
heap_flags |= H5AC__DIRTIED_FLAG;
} /* end if */
@@ -1202,7 +807,7 @@ H5HG_link (H5F_t *f, hid_t dxpl_id, const H5HG_t *hobj, int adjust)
done:
if (heap && H5AC_unprotect(f, dxpl_id, H5AC_GHEAP, hobj->addr, heap, heap_flags)<0)
- HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release object header");
+ HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value);
}
@@ -1230,88 +835,88 @@ done:
herr_t
H5HG_remove (H5F_t *f, hid_t dxpl_id, H5HG_t *hobj)
{
- uint8_t *p=NULL, *obj_start=NULL;
H5HG_heap_t *heap = NULL;
+ uint8_t *p = NULL, *obj_start = NULL;
size_t need;
- int i;
unsigned u;
- unsigned flags=H5AC__NO_FLAGS_SET;/* Whether the heap gets deleted */
- herr_t ret_value=SUCCEED; /* Return value */
+ unsigned flags = H5AC__NO_FLAGS_SET;/* Whether the heap gets deleted */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5HG_remove, FAIL);
/* Check args */
- assert (f);
- assert (hobj);
- if (0==(f->intent & H5F_ACC_RDWR))
- HGOTO_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file");
+ HDassert(f);
+ HDassert(hobj);
+ if(0 == (f->intent & H5F_ACC_RDWR))
+ HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file")
/* Load the heap */
- if (NULL == (heap = (H5HG_heap_t *)H5AC_protect(f, dxpl_id, H5AC_GHEAP, hobj->addr, NULL, NULL, H5AC_WRITE)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap");
+ if(NULL == (heap = (H5HG_heap_t *)H5AC_protect(f, dxpl_id, H5AC_GHEAP, hobj->addr, NULL, NULL, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap")
- assert (hobj->idx<heap->nused);
- assert (heap->obj[hobj->idx].begin);
+ HDassert(hobj->idx < heap->nused);
+ HDassert(heap->obj[hobj->idx].begin);
obj_start = heap->obj[hobj->idx].begin;
/* Include object header size */
- need = H5HG_ALIGN(heap->obj[hobj->idx].size)+H5HG_SIZEOF_OBJHDR(f);
+ need = H5HG_ALIGN(heap->obj[hobj->idx].size) + H5HG_SIZEOF_OBJHDR(f);
/* Move the new free space to the end of the heap */
- for (u=0; u<heap->nused; u++) {
- if (heap->obj[u].begin > heap->obj[hobj->idx].begin)
+ for(u = 0; u < heap->nused; u++)
+ if(heap->obj[u].begin > heap->obj[hobj->idx].begin)
heap->obj[u].begin -= need;
- }
- if (NULL==heap->obj[0].begin) {
- heap->obj[0].begin = heap->chunk + (heap->size-need);
+ if(NULL == heap->obj[0].begin) {
+ heap->obj[0].begin = heap->chunk + (heap->size - need);
heap->obj[0].size = need;
heap->obj[0].nrefs = 0;
- } else {
+ } /* end if */
+ else
heap->obj[0].size += need;
- }
- HDmemmove (obj_start, obj_start+need,
- heap->size-((obj_start+need)-heap->chunk));
- if (heap->obj[0].size>=H5HG_SIZEOF_OBJHDR (f)) {
+ HDmemmove(obj_start, obj_start + need,
+ heap->size - ((obj_start + need) - heap->chunk));
+ if(heap->obj[0].size >= H5HG_SIZEOF_OBJHDR(f)) {
p = heap->obj[0].begin;
UINT16ENCODE(p, 0); /*id*/
UINT16ENCODE(p, 0); /*nrefs*/
UINT32ENCODE(p, 0); /*reserved*/
H5F_ENCODE_LENGTH (f, p, heap->obj[0].size);
- }
- HDmemset (heap->obj+hobj->idx, 0, sizeof(H5HG_obj_t));
+ } /* end if */
+ HDmemset(heap->obj + hobj->idx, 0, sizeof(H5HG_obj_t));
flags |= H5AC__DIRTIED_FLAG;
- if (heap->obj[0].size+H5HG_SIZEOF_HDR(f)==heap->size) {
+ if((heap->obj[0].size + H5HG_SIZEOF_HDR(f)) == heap->size) {
/*
* The collection is empty. Remove it from the CWFS list and return it
* to the file free list.
*/
- H5_CHECK_OVERFLOW(heap->size,size_t,hsize_t);
- H5MF_xfree(f, H5FD_MEM_GHEAP, dxpl_id, heap->addr, (hsize_t)heap->size);
- flags |= H5C__DELETED_FLAG; /* Indicate that the object was deleted, for the unprotect call */
- } else {
+ H5_CHECK_OVERFLOW(heap->size, size_t, hsize_t);
+ flags |= H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG; /* Indicate that the object was deleted, for the unprotect call */
+ } /* end if */
+ else {
+ int i; /* Local index variable */
+
/*
* If the heap is in the CWFS list then advance it one position. The
* H5AC_protect() might have done that too, but that's okay. If the
* heap isn't on the CWFS list then add it to the end.
*/
- for (i=0; i<f->shared->ncwfs; i++) {
- if (f->shared->cwfs[i]==heap) {
- if (i) {
- f->shared->cwfs[i] = f->shared->cwfs[i-1];
- f->shared->cwfs[i-1] = heap;
- }
+ for(i = 0; i < f->shared->ncwfs; i++)
+ if(f->shared->cwfs[i] == heap) {
+ if(i) {
+ f->shared->cwfs[i] = f->shared->cwfs[i - 1];
+ f->shared->cwfs[i - 1] = heap;
+ } /* end if */
break;
- }
- }
- if (i>=f->shared->ncwfs) {
- f->shared->ncwfs = MIN (f->shared->ncwfs+1, H5HG_NCWFS);
- f->shared->cwfs[f->shared->ncwfs-1] = heap;
- }
- }
+ } /* end if */
+ if(i >= f->shared->ncwfs) {
+ f->shared->ncwfs = MIN(f->shared->ncwfs + 1, H5HG_NCWFS);
+ f->shared->cwfs[f->shared->ncwfs - 1] = heap;
+ } /* end if */
+ } /* end else */
done:
- if (heap && H5AC_unprotect(f, dxpl_id, H5AC_GHEAP, hobj->addr, heap, flags) != SUCCEED)
- HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release object header");
+ if(heap && H5AC_unprotect(f, dxpl_id, H5AC_GHEAP, hobj->addr, heap, flags) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value);
-}
+} /* end H5HG_remove() */
+
diff --git a/src/H5HGcache.c b/src/H5HGcache.c
new file mode 100644
index 0000000..1a9e92c
--- /dev/null
+++ b/src/H5HGcache.c
@@ -0,0 +1,442 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5HGcache.c
+ * Feb 5 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Implement global heap metadata cache methods.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+#define H5HG_PACKAGE /*suppress error about including H5HGpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* File access */
+#include "H5HGpkg.h" /* Global heaps */
+#include "H5MFprivate.h" /* File memory management */
+#include "H5MMprivate.h" /* Memory management */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+/* Metadata cache callbacks */
+static H5HG_heap_t *H5HG_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1,
+ void *udata2);
+static herr_t H5HG_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr,
+ H5HG_heap_t *heap, unsigned UNUSED * flags_ptr);
+static herr_t H5HG_clear(H5F_t *f, H5HG_heap_t *heap, hbool_t destroy);
+static herr_t H5HG_size(const H5F_t *f, const H5HG_heap_t *heap, size_t *size_ptr);
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* H5HG inherits cache-like properties from H5AC */
+const H5AC_class_t H5AC_GHEAP[1] = {{
+ H5AC_GHEAP_ID,
+ (H5AC_load_func_t)H5HG_load,
+ (H5AC_flush_func_t)H5HG_flush,
+ (H5AC_dest_func_t)H5HG_dest,
+ (H5AC_clear_func_t)H5HG_clear,
+ (H5AC_size_func_t)H5HG_size,
+}};
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HG_load
+ *
+ * Purpose: Loads a global heap collection from disk.
+ *
+ * Return: Success: Ptr to a global heap collection.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Friday, March 27, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5HG_heap_t *
+H5HG_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1,
+ void UNUSED * udata2)
+{
+ H5HG_heap_t *heap = NULL;
+ uint8_t *p = NULL;
+ size_t nalloc, need;
+ size_t max_idx = 0; /* The maximum index seen */
+ H5HG_heap_t *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5HG_load, NULL)
+
+ /* check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(!udata1);
+ HDassert(!udata2);
+
+ /* Read the initial 4k page */
+ if(NULL == (heap = H5FL_CALLOC(H5HG_heap_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ heap->addr = addr;
+ if(NULL == (heap->chunk = H5FL_BLK_MALLOC(gheap_chunk, (size_t)H5HG_MINSIZE)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ if(H5F_block_read(f, H5FD_MEM_GHEAP, addr, (size_t)H5HG_MINSIZE, dxpl_id, heap->chunk) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read global heap collection")
+
+ /* Magic number */
+ if(HDmemcmp(heap->chunk, H5HG_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad global heap collection signature")
+ p = heap->chunk + H5_SIZEOF_MAGIC;
+
+ /* Version */
+ if(H5HG_VERSION != *p++)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong version number in global heap")
+
+ /* Reserved */
+ p += 3;
+
+ /* Size */
+ H5F_DECODE_LENGTH(f, p, heap->size);
+ HDassert(heap->size >= H5HG_MINSIZE);
+
+ /*
+ * If we didn't read enough in the first try, then read the rest of the
+ * collection now.
+ */
+ if(heap->size > H5HG_MINSIZE) {
+ haddr_t next_addr = addr + (hsize_t)H5HG_MINSIZE;
+
+ if(NULL == (heap->chunk = H5FL_BLK_REALLOC(gheap_chunk, heap->chunk, heap->size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ if(H5F_block_read(f, H5FD_MEM_GHEAP, next_addr, (heap->size - H5HG_MINSIZE), dxpl_id, heap->chunk + H5HG_MINSIZE) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read global heap collection")
+ } /* end if */
+
+ /* Decode each object */
+ p = heap->chunk + H5HG_SIZEOF_HDR(f);
+ nalloc = H5HG_NOBJS(f, heap->size);
+ if(NULL == (heap->obj = H5FL_SEQ_MALLOC(H5HG_obj_t, nalloc)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ heap->obj[0].size = heap->obj[0].nrefs = 0;
+ heap->obj[0].begin = NULL;
+
+ heap->nalloc = nalloc;
+ while(p < (heap->chunk + heap->size)) {
+ if((p + H5HG_SIZEOF_OBJHDR(f)) > (heap->chunk + heap->size)) {
+ /*
+ * The last bit of space is too tiny for an object header, so we
+ * assume that it's free space.
+ */
+ HDassert(NULL == heap->obj[0].begin);
+ heap->obj[0].size = (heap->chunk + heap->size) - p;
+ heap->obj[0].begin = p;
+ p += heap->obj[0].size;
+ } /* end if */
+ else {
+ unsigned idx;
+ uint8_t *begin = p;
+
+ UINT16DECODE(p, idx);
+
+ /* Check if we need more room to store heap objects */
+ if(idx >= heap->nalloc) {
+ size_t new_alloc; /* New allocation number */
+ H5HG_obj_t *new_obj; /* New array of object descriptions */
+
+ /* Determine the new number of objects to index */
+ new_alloc = MAX(heap->nalloc * 2, (idx + 1));
+
+ /* Reallocate array of objects */
+ if(NULL == (new_obj = H5FL_SEQ_REALLOC(H5HG_obj_t, heap->obj, new_alloc)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+ /* Update heap information */
+ heap->nalloc = new_alloc;
+ heap->obj = new_obj;
+ } /* end if */
+
+ UINT16DECODE(p, heap->obj[idx].nrefs);
+ p += 4; /*reserved*/
+ H5F_DECODE_LENGTH(f, p, heap->obj[idx].size);
+ heap->obj[idx].begin = begin;
+
+ /*
+ * The total storage size includes the size of the object header
+ * and is zero padded so the next object header is properly
+ * aligned. The last bit of space is the free space object whose
+ * size is never padded and already includes the object header.
+ */
+ if(idx > 0) {
+ need = H5HG_SIZEOF_OBJHDR(f) + H5HG_ALIGN(heap->obj[idx].size);
+
+ /* Check for "gap" in index numbers (caused by deletions) and fill in heap object values */
+ if(idx > (max_idx + 1))
+ HDmemset(&heap->obj[max_idx + 1], 0, sizeof(H5HG_obj_t) * (idx - (max_idx + 1)));
+ max_idx = idx;
+ } /* end if */
+ else
+ need = heap->obj[idx].size;
+ p = begin + need;
+ } /* end else */
+ } /* end while */
+ HDassert(p == heap->chunk + heap->size);
+ HDassert(H5HG_ISALIGNED(heap->obj[0].size));
+
+ /* Set the next index value to use */
+ if(max_idx > 0)
+ heap->nused = max_idx + 1;
+ else
+ heap->nused = 1;
+
+ /*
+ * Add the new heap to the CWFS list, removing some other entry if
+ * necessary to make room. We remove the right-most entry that has less
+ * free space than this heap.
+ */
+ if(!f->shared->cwfs) {
+ f->shared->cwfs = (H5HG_heap_t **)H5MM_malloc(H5HG_NCWFS * sizeof(H5HG_heap_t *));
+ if(NULL == f->shared->cwfs)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ f->shared->ncwfs = 1;
+ f->shared->cwfs[0] = heap;
+ } else if(H5HG_NCWFS == f->shared->ncwfs) {
+ int i; /* Local index variable */
+
+ for(i = H5HG_NCWFS - 1; i >= 0; --i)
+ if(f->shared->cwfs[i]->obj[0].size < heap->obj[0].size) {
+ HDmemmove(f->shared->cwfs + 1, f->shared->cwfs, i * sizeof(H5HG_heap_t *));
+ f->shared->cwfs[0] = heap;
+ break;
+ } /* end if */
+ } else {
+ HDmemmove(f->shared->cwfs + 1, f->shared->cwfs, f->shared->ncwfs * sizeof(H5HG_heap_t *));
+ f->shared->ncwfs += 1;
+ f->shared->cwfs[0] = heap;
+ } /* end else */
+
+ ret_value = heap;
+
+done:
+ if(!ret_value && heap)
+ if(H5HG_dest(f, heap) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "unable to destroy global heap collection")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HG_load() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HG_flush
+ *
+ * Purpose: Flushes a global heap collection from memory to disk if it's
+ * dirty. Optionally deletes teh heap from memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Friday, March 27, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HG_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HG_heap_t *heap, unsigned UNUSED * flags_ptr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5HG_flush, FAIL)
+
+ /* Check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(H5F_addr_eq(addr, heap->addr));
+ HDassert(heap);
+
+ if(heap->cache_info.is_dirty) {
+ if(H5F_block_write(f, H5FD_MEM_GHEAP, addr, heap->size, dxpl_id, heap->chunk) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write global heap collection to file")
+ heap->cache_info.is_dirty = FALSE;
+ } /* end if */
+
+ if(destroy)
+ if(H5HG_dest(f, heap) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy global heap collection")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HG_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HG_dest
+ *
+ * Purpose: Destroys a global heap collection in memory
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Wednesday, January 15, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HG_dest(H5F_t *f, H5HG_heap_t *heap)
+{
+ int i; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HG_dest)
+
+ /* Check arguments */
+ HDassert(heap);
+
+ /* Verify that node is clean */
+ HDassert(heap->cache_info.is_dirty == FALSE);
+
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!heap->cache_info.free_file_space_on_destroy || H5F_addr_defined(heap->cache_info.addr));
+
+ /* Check for freeing file space for globalheap */
+ if(heap->cache_info.free_file_space_on_destroy) {
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_GHEAP, H5AC_dxpl_id, heap->cache_info.addr, (hsize_t)heap->size) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free global heap")
+ } /* end if */
+
+ /* Remove heap from NCWFS array, if it's present */
+ for(i = 0; i < f->shared->ncwfs; i++)
+ if(f->shared->cwfs[i] == heap) {
+ f->shared->ncwfs -= 1;
+ HDmemmove(f->shared->cwfs + i, f->shared->cwfs + i + 1, (f->shared->ncwfs - i) * sizeof(H5HG_heap_t *));
+ break;
+ } /* end if */
+
+ /* Release resources */
+ if(heap->chunk)
+ heap->chunk = H5FL_BLK_FREE(gheap_chunk, heap->chunk);
+ if(heap->obj)
+ heap->obj = H5FL_SEQ_FREE(H5HG_obj_t, heap->obj);
+ (void)H5FL_FREE(H5HG_heap_t, heap);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5HG_dest() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HG_clear
+ *
+ * Purpose: Mark a global heap in memory as non-dirty.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, March 20, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HG_clear(H5F_t *f, H5HG_heap_t *heap, hbool_t destroy)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HG_clear)
+
+ /* Check arguments */
+ HDassert(heap);
+
+ /* Mark heap as clean */
+ heap->cache_info.is_dirty = FALSE;
+
+ if(destroy)
+ if(H5HG_dest(f, heap) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy global heap collection")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5HG_clear() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HG_size
+ *
+ * Purpose: Compute the size in bytes of the specified instance of
+ * H5HG_heap_t on disk, and return it in *len_ptr. On failure,
+ * the value of *len_ptr is undefined.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 5/13/04
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HG_size(const H5F_t UNUSED *f, const H5HG_heap_t *heap, size_t *size_ptr)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HG_size)
+
+ /* Check arguments */
+ HDassert(heap);
+ HDassert(size_ptr);
+
+ *size_ptr = heap->size;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5HG_size() */
+
diff --git a/src/H5HGpkg.h b/src/H5HGpkg.h
index e814367..96be009 100644
--- a/src/H5HGpkg.h
+++ b/src/H5HGpkg.h
@@ -32,6 +32,9 @@
#include "H5HGprivate.h"
/* Other private headers needed by this file */
+#include "H5ACprivate.h" /* Metadata cache */
+#include "H5FLprivate.h" /* Free lists */
+
/*****************************/
/* Package Private Variables */
@@ -40,11 +43,40 @@
/* The cache subclass */
H5_DLLVAR const H5AC_class_t H5AC_GHEAP[1];
+/* Declare extern the free list to manage the H5HG_t struct */
+H5FL_EXTERN(H5HG_heap_t);
+
+/* Declare extern the free list to manage sequences of H5HG_obj_t's */
+H5FL_SEQ_EXTERN(H5HG_obj_t);
+
+/* Declare extern the PQ free list to manage heap chunks */
+H5FL_BLK_EXTERN(gheap_chunk);
+
+
/**************************/
/* Package Private Macros */
/**************************/
/*
+ * Global heap collection version.
+ */
+#define H5HG_VERSION 1
+
+/*
+ * All global heap collections are at least this big. This allows us to read
+ * most collections with a single read() since we don't have to read a few
+ * bytes of header to figure out the size. If the heap is larger than this
+ * then a second read gets the rest after we've decoded the header.
+ */
+#define H5HG_MINSIZE 4096
+
+/*
+ * Maximum length of the CWFS list, the list of remembered collections that
+ * have free space.
+ */
+#define H5HG_NCWFS 16
+
+/*
* Pad all global heap messages to a multiple of eight bytes so we can load
* the entire collection into memory and operate on it there. Eight should
* be sufficient for machines that have alignment constraints because our
@@ -56,6 +88,16 @@ H5_DLLVAR const H5AC_class_t H5AC_GHEAP[1];
#define H5HG_ISALIGNED(X) ((X)==H5HG_ALIGN(X))
/*
+ * The size of the collection header, always a multiple of the alignment so
+ * that the stuff that follows the header is aligned.
+ */
+#define H5HG_SIZEOF_HDR(f) \
+ H5HG_ALIGN(4 + /*magic number */ \
+ 1 + /*version number */ \
+ 3 + /*reserved */ \
+ H5F_SIZEOF_SIZE(f)) /*collection size */
+
+/*
* The overhead associated with each object in the heap, always a multiple of
* the alignment so that the stuff that follows the header is aligned.
*/
@@ -65,6 +107,17 @@ H5_DLLVAR const H5AC_class_t H5AC_GHEAP[1];
4 + /*reserved */ \
H5F_SIZEOF_SIZE(f)) /*object data size */
+/*
+ * The initial guess for the number of messages in a collection. We assume
+ * that all objects in that collection are zero length, giving the maximum
+ * possible number of objects in the collection. The collection itself has
+ * some overhead and each message has some overhead. The `+2' accounts for
+ * rounding and for the free space object.
+ */
+#define H5HG_NOBJS(f,z) (int)((((z)-H5HG_SIZEOF_HDR(f))/ \
+ H5HG_SIZEOF_OBJHDR(f)+2))
+
+
/****************************/
/* Package Private Typedefs */
/****************************/
@@ -92,6 +145,7 @@ struct H5HG_heap_t {
/******************************/
/* Package Private Prototypes */
/******************************/
+H5_DLL herr_t H5HG_dest(H5F_t *f, H5HG_heap_t *heap);
-#endif
+#endif /* _H5HGpkg_H */
diff --git a/src/H5HL.c b/src/H5HL.c
index 3b3a740..a69eb16 100644
--- a/src/H5HL.c
+++ b/src/H5HL.c
@@ -22,69 +22,75 @@
* Purpose: Heap functions for the local heaps used by symbol
* tables to store names (among other things).
*
- * Modifications:
- *
- * Robb Matzke, 5 Aug 1997
- * Added calls to H5E.
- *
*-------------------------------------------------------------------------
*/
+
+/****************/
+/* Module Setup */
+/****************/
+
#define H5F_PACKAGE /* Suppress error about including H5Fpkg */
#define H5HL_PACKAGE /* Suppress error about including H5HLpkg */
+/***********/
+/* Headers */
+/***********/
#include "H5private.h" /* Generic Functions */
-#include "H5ACprivate.h" /* Metadata cache */
#include "H5Eprivate.h" /* Error handling */
#include "H5Fpkg.h" /* File access */
-#include "H5FLprivate.h" /* Free lists */
#include "H5HLpkg.h" /* Local Heaps */
#include "H5MFprivate.h" /* File memory management */
-/* Private macros */
-#define H5HL_FREE_NULL 1 /*end of free list on disk */
+
+/****************/
+/* Local Macros */
+/****************/
+
#define H5HL_MIN_HEAP 128 /* Minimum size to reduce heap buffer to */
-/*
- * Local heap collection version.
- */
-#define H5HL_VERSION 0
-/* Private typedefs */
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
-/* PRIVATE PROTOTYPES */
-static herr_t H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf);
static H5HL_free_t *H5HL_remove_free(H5HL_t *heap, H5HL_free_t *fl);
static herr_t H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap);
-/* Metadata cache callbacks */
-static H5HL_t *H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1,
- void *udata2);
-static herr_t H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, H5HL_t *heap, unsigned UNUSED * flags_ptr);
-static herr_t H5HL_dest(H5F_t *f, H5HL_t *heap);
-static herr_t H5HL_clear(H5F_t *f, H5HL_t *heap, hbool_t destroy);
-static herr_t H5HL_size(const H5F_t *f, const H5HL_t *heap, size_t *size_ptr);
-/*
- * H5HL inherits cache-like properties from H5AC
- */
-const H5AC_class_t H5AC_LHEAP[1] = {{
- H5AC_LHEAP_ID,
- (H5AC_load_func_t)H5HL_load,
- (H5AC_flush_func_t)H5HL_flush,
- (H5AC_dest_func_t)H5HL_dest,
- (H5AC_clear_func_t)H5HL_clear,
- (H5AC_size_func_t)H5HL_size,
-}};
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
/* Declare a free list to manage the H5HL_free_t struct */
-H5FL_DEFINE_STATIC(H5HL_free_t);
+H5FL_DEFINE(H5HL_free_t);
/* Declare a free list to manage the H5HL_t struct */
-H5FL_DEFINE_STATIC(H5HL_t);
+H5FL_DEFINE(H5HL_t);
/* Declare a PQ free list to manage the heap chunk information */
-H5FL_BLK_DEFINE_STATIC(heap_chunk);
+H5FL_BLK_DEFINE(lheap_chunk);
+
/*-------------------------------------------------------------------------
@@ -106,15 +112,6 @@ H5FL_BLK_DEFINE_STATIC(heap_chunk);
* matzke@llnl.gov
* Jul 16 1997
*
- * Modifications:
- *
- * Robb Matzke, 5 Aug 1997
- * Takes a flag that determines the type of heap that is
- * created.
- *
- * John Mainzer, 6/7/05
- * Removed code modifying the is_dirty field of the cache info.
- *
*-------------------------------------------------------------------------
*/
herr_t
@@ -125,179 +122,58 @@ H5HL_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, haddr_t *addr_p/*out*/)
size_t sizeof_hdr; /* Cache H5HL header size for file */
herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI(H5HL_create, FAIL);
+ FUNC_ENTER_NOAPI(H5HL_create, FAIL)
/* check arguments */
- assert(f);
- assert(addr_p);
+ HDassert(f);
+ HDassert(addr_p);
- if (size_hint && size_hint < H5HL_SIZEOF_FREE(f))
+ if(size_hint && size_hint < H5HL_SIZEOF_FREE(f))
size_hint = H5HL_SIZEOF_FREE(f);
size_hint = H5HL_ALIGN(size_hint);
/* Cache this for later */
- sizeof_hdr= H5HL_SIZEOF_HDR(f);
+ sizeof_hdr = H5HL_SIZEOF_HDR(f);
/* allocate file version */
total_size = sizeof_hdr + size_hint;
- if (HADDR_UNDEF==(*addr_p=H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, total_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate file memory");
+ if(HADDR_UNDEF == (*addr_p = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, total_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate file memory")
/* allocate memory version */
- if (NULL==(heap = H5FL_CALLOC(H5HL_t)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
+ if(NULL == (heap = H5FL_CALLOC(H5HL_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
heap->addr = *addr_p + (hsize_t)sizeof_hdr;
heap->heap_alloc = size_hint;
- if (NULL==(heap->chunk = H5FL_BLK_CALLOC(heap_chunk,(sizeof_hdr + size_hint))))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
+ if(NULL == (heap->chunk = H5FL_BLK_CALLOC(lheap_chunk, (sizeof_hdr + size_hint))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* free list */
- if (size_hint) {
- if (NULL==(heap->freelist = H5FL_MALLOC(H5HL_free_t)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
+ if(size_hint) {
+ if(NULL == (heap->freelist = H5FL_MALLOC(H5HL_free_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
heap->freelist->offset = 0;
heap->freelist->size = size_hint;
heap->freelist->prev = heap->freelist->next = NULL;
- } else {
+ } /* end if */
+ else
heap->freelist = NULL;
- }
/* add to cache */
- if (H5AC_set(f, dxpl_id, H5AC_LHEAP, *addr_p, heap, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to cache heap");
+ if(H5AC_set(f, dxpl_id, H5AC_LHEAP, *addr_p, heap, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to cache heap")
done:
- if (ret_value<0) {
- if (H5F_addr_defined(*addr_p))
+ if(ret_value < 0) {
+ if(H5F_addr_defined(*addr_p))
H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, *addr_p, total_size);
- if (heap) {
- if(H5HL_dest(f,heap)<0)
- HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection");
- }
- }
- FUNC_LEAVE_NOAPI(ret_value);
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HL_load
- *
- * Purpose: Loads a heap from disk.
- *
- * Return: Success: Ptr to a local heap memory data structure.
- *
- * Failure: NULL
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Jul 17 1997
- *
- * Modifications:
- * Robb Matzke, 1999-07-28
- * The ADDR argument is passed by value.
- *
- * Quincey Koziol, 2002-7-180
- * Added dxpl parameter to allow more control over I/O from metadata
- * cache.
- *-------------------------------------------------------------------------
- */
-static H5HL_t *
-H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1,
- void UNUSED * udata2)
-{
- uint8_t hdr[52];
- size_t sizeof_hdr; /* Cache H5HL header size for file */
- const uint8_t *p = NULL;
- H5HL_t *heap = NULL;
- H5HL_free_t *fl = NULL, *tail = NULL;
- size_t free_block = H5HL_FREE_NULL;
- H5HL_t *ret_value;
-
- FUNC_ENTER_NOAPI(H5HL_load, NULL)
-
- /* check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
- HDassert(!udata1);
- HDassert(!udata2);
-
- /* Cache this for later */
- sizeof_hdr = H5HL_SIZEOF_HDR(f);
- HDassert(sizeof_hdr <= sizeof(hdr));
-
- /* Get the local heap's header */
- if(H5F_block_read(f, H5FD_MEM_LHEAP, addr, sizeof_hdr, dxpl_id, hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read heap header")
- p = hdr;
-
- /* Check magic number */
- if(HDmemcmp(hdr, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap signature")
- p += H5_SIZEOF_MAGIC;
-
- /* Version */
- if(H5HL_VERSION != *p++)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong version number in global heap")
-
- /* Reserved */
- p += 3;
-
- /* Allocate space in memory for the heap */
- if(NULL == (heap = H5FL_CALLOC(H5HL_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
-
- /* heap data size */
- H5F_DECODE_LENGTH(f, p, heap->heap_alloc);
-
- /* free list head */
- H5F_DECODE_LENGTH(f, p, free_block);
- if(free_block != H5HL_FREE_NULL && free_block >= heap->heap_alloc)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list")
-
- /* data */
- H5F_addr_decode(f, &p, &(heap->addr));
- if(NULL == (heap->chunk = H5FL_BLK_CALLOC(heap_chunk, (sizeof_hdr + heap->heap_alloc))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- if(heap->heap_alloc &&
- H5F_block_read(f, H5FD_MEM_LHEAP, heap->addr, heap->heap_alloc, dxpl_id, heap->chunk + sizeof_hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to read heap data")
-
- /* Build free list */
- while(H5HL_FREE_NULL != free_block) {
- if(free_block >= heap->heap_alloc)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list")
- if(NULL == (fl = H5FL_MALLOC(H5HL_free_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- fl->offset = free_block;
- fl->prev = tail;
- fl->next = NULL;
- if(tail)
- tail->next = fl;
- tail = fl;
- if(!heap->freelist)
- heap->freelist = fl;
-
- p = heap->chunk + sizeof_hdr + free_block;
-
- H5F_DECODE_LENGTH(f, p, free_block);
- if(free_block == 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "free block size is zero?")
-
- H5F_DECODE_LENGTH(f, p, fl->size);
- if (fl->offset + fl->size > heap->heap_alloc)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list")
- } /* end while */
-
- /* Set return value */
- ret_value = heap;
-
-done:
- if(!ret_value && heap)
- if(H5HL_dest(f,heap) < 0)
- HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "unable to destroy local heap collection")
+ if(heap)
+ if(H5HL_dest(f,heap) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection")
+ } /* end if */
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HL_load() */
+} /* end H5HL_create() */
/*-------------------------------------------------------------------------
@@ -313,22 +189,6 @@ done:
* wendling@ncsa.uiuc.edu
* Sept. 16, 2003
*
- * Modifications:
- *
- * John Mainzer, 8/10/05
- * Reworked this function for a different role.
- *
- * It used to be called during cache eviction, where it
- * attempted to size the disk space allocation for the
- * actual size of the heap. However, this causes problems
- * in the parallel case, as the reuslting disk allocations
- * may not be synchronized.
- *
- * It is now called from H5HL_remove(), where it is used to
- * reduce heap size in response to an entry deletion. This
- * means that the function should either do nothing, or
- * reduce the size of the disk allocation.
- *
*-------------------------------------------------------------------------
*/
static herr_t
@@ -429,15 +289,15 @@ H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap)
HDassert(new_heap_size < heap->heap_alloc);
/* Resize the memory buffer */
- heap->chunk = H5FL_BLK_REALLOC(heap_chunk, heap->chunk, (sizeof_hdr + new_heap_size));
+ heap->chunk = H5FL_BLK_REALLOC(lheap_chunk, heap->chunk, (sizeof_hdr + new_heap_size));
if(!heap->chunk)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Release old space on disk */
/* (Should be safe to free old heap space first, since it's shrinking -QAK) */
H5_CHECK_OVERFLOW(heap->heap_alloc, size_t, hsize_t);
- H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, old_addr, (hsize_t)heap->heap_alloc);
- H5E_clear_stack(NULL); /* don't really care if the free failed */
+ if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, old_addr, (hsize_t)heap->heap_alloc) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap")
/* Allocate new space on disk */
H5_CHECK_OVERFLOW(new_heap_size, size_t, hsize_t);
@@ -455,268 +315,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5HL_serialize
- *
- * Purpose: Serialize the heap. This function will eliminate free
- * blocks at the tail of the heap and also split the block
- * if it needs to be split for the file. This is so that we
- * can serialize it correctly.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Bill Wendling
- * wendling@ncsa.uiuc.edu
- * Sept. 16, 2003
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf)
-{
- H5HL_free_t *fl;
- uint8_t *p;
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_serialize)
-
- /* check args */
- assert(buf);
- assert(heap);
-
- /* serialize the header */
- p = buf;
- fl = heap->freelist;
- HDmemcpy(p, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC);
- p += H5_SIZEOF_MAGIC;
- *p++ = H5HL_VERSION;
- *p++ = 0; /*reserved*/
- *p++ = 0; /*reserved*/
- *p++ = 0; /*reserved*/
- H5F_ENCODE_LENGTH(f, p, heap->heap_alloc);
- H5F_ENCODE_LENGTH(f, p, fl ? fl->offset : H5HL_FREE_NULL);
- H5F_addr_encode(f, &p, heap->addr);
-
- /* serialize the free list */
- for (; fl; fl = fl->next) {
- assert (fl->offset == H5HL_ALIGN (fl->offset));
- p = heap->chunk + H5HL_SIZEOF_HDR(f) + fl->offset;
-
- if (fl->next) {
- H5F_ENCODE_LENGTH(f, p, fl->next->offset);
- } else {
- H5F_ENCODE_LENGTH(f, p, H5HL_FREE_NULL);
- }
-
- H5F_ENCODE_LENGTH(f, p, fl->size);
- }
-
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HL_flush
- *
- * Purpose: Flushes a heap from memory to disk if it's dirty. Optionally
- * deletes the heap from memory.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Jul 17 1997
- *
- * Modifications:
- * rky, 1998-08-28
- * Only p0 writes metadata to disk.
- *
- * Robb Matzke, 1999-07-28
- * The ADDR argument is passed by value.
- *
- * Quincey Koziol, 2002-7-180
- * Added dxpl parameter to allow more control over I/O from metadata
- * cache.
- *
- * Bill Wendling, 2003-09-16
- * Separated out the bit that serializes the heap.
- *
- * John Mainzer, 2005-08-10
- * Removed call to H5HL_minimize_heap_space(). It does disk space
- * allocation, which can cause problems if done at flush time.
- * Instead, disk space allocation/deallocation is now done at
- * insert/remove time.
- *
- * John Mainzer, 2006-08-21
- * Added the flags_ptr parameter. This parameter exists to
- * allow the flush routine to report to the cache if the
- * entry is resized or renamed as a result of the flush.
- * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry.
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HL_t *heap, unsigned UNUSED * flags_ptr)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5HL_flush, FAIL);
-
- /* check arguments */
- HDassert( f );
- HDassert( H5F_addr_defined(addr) );
- HDassert( heap );
-
- if (heap->cache_info.is_dirty) {
- haddr_t hdr_end_addr;
- size_t sizeof_hdr = H5HL_SIZEOF_HDR(f); /* cache H5HL header size for file */
-
- /* Write the header */
- if (H5HL_serialize(f, heap, heap->chunk) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTSERIALIZE, FAIL, "unable to serialize local heap")
-
- /* Copy buffer to disk */
- hdr_end_addr = addr + (hsize_t)sizeof_hdr;
-
- if (H5F_addr_eq(heap->addr, hdr_end_addr)) {
- /* The header and data are contiguous */
- if (H5F_block_write(f, H5FD_MEM_LHEAP, addr, (sizeof_hdr + heap->heap_alloc),
- dxpl_id, heap->chunk) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header and data to file")
- } else {
- if (H5F_block_write(f, H5FD_MEM_LHEAP, addr, sizeof_hdr, dxpl_id, heap->chunk) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header to file")
-
- if (H5F_block_write(f, H5FD_MEM_LHEAP, heap->addr, heap->heap_alloc,
- dxpl_id, heap->chunk + sizeof_hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap data to file")
- }
-
- heap->cache_info.is_dirty = FALSE;
- }
-
- /* Should we destroy the memory version? */
- if (destroy) {
- if (H5HL_dest(f,heap) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection")
- }
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HL_dest
- *
- * Purpose: Destroys a heap in memory.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Jan 15 2003
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HL_dest(H5F_t UNUSED *f, H5HL_t *heap)
-{
- H5HL_free_t *fl;
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_dest)
-
- /* check arguments */
- HDassert(heap);
-
- /* Verify that node is clean */
- HDassert(heap->cache_info.is_dirty == FALSE);
-
- if(heap->chunk)
- heap->chunk = H5FL_BLK_FREE(heap_chunk, heap->chunk);
- while(heap->freelist) {
- fl = heap->freelist;
- heap->freelist = fl->next;
- (void)H5FL_FREE(H5HL_free_t, fl);
- } /* end while */
- (void)H5FL_FREE(H5HL_t, heap);
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5HL_dest() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HL_clear
- *
- * Purpose: Mark a local heap in memory as non-dirty.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 20 2003
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HL_clear(H5F_t *f, H5HL_t *heap, hbool_t destroy)
-{
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT(H5HL_clear);
-
- /* check arguments */
- assert(heap);
-
- /* Mark heap as clean */
- heap->cache_info.is_dirty = FALSE;
-
- if (destroy)
- if (H5HL_dest(f, heap) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection");
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5HL_clear() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HL_size
- *
- * Purpose: Compute the size in bytes of the specified instance of
- * H5HL_t on disk, and return it in *len_ptr. On failure,
- * the value of *len_ptr is undefined.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: John Mainzer
- * 5/13/04
- *
- * Modifications:
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HL_size(const H5F_t *f, const H5HL_t *heap, size_t *size_ptr)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_size);
-
- /* check arguments */
- HDassert(f);
- HDassert(heap);
- HDassert(size_ptr);
-
- *size_ptr = H5HL_SIZEOF_HDR(f) + heap->heap_alloc;
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5HL_size() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5HL_protect
*
* Purpose: This function is a wrapper for the H5AC_protect call. The
@@ -779,8 +377,6 @@ done:
* wendling@ncsa.uiuc.edu
* Sept. 17, 2003
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
void *
@@ -791,11 +387,13 @@ H5HL_offset_into(H5F_t *f, const H5HL_t *heap, size_t offset)
* valid heap pointer. So, this can remain "FUNC_ENTER_NOAPI_NOINIT"
*/
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_offset_into)
- assert(f);
- assert(heap);
- assert(offset < heap->heap_alloc);
+
+ HDassert(f);
+ HDassert(heap);
+ HDassert(offset < heap->heap_alloc);
+
FUNC_LEAVE_NOAPI(heap->chunk + H5HL_SIZEOF_HDR(f) + offset)
-}
+} /* end H5HL_offset_into() */
/*-------------------------------------------------------------------------
@@ -849,7 +447,7 @@ done:
static H5HL_free_t *
H5HL_remove_free(H5HL_t *heap, H5HL_free_t *fl)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_remove_free);
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_remove_free)
if(fl->prev)
fl->prev->next = fl->next;
@@ -859,7 +457,7 @@ H5HL_remove_free(H5HL_t *heap, H5HL_free_t *fl)
if(!fl->prev)
heap->freelist = fl->next;
- FUNC_LEAVE_NOAPI((H5HL_free_t *)H5FL_FREE(H5HL_free_t, fl));
+ FUNC_LEAVE_NOAPI((H5HL_free_t *)H5FL_FREE(H5HL_free_t, fl))
} /* end H5HL_remove_free() */
@@ -949,9 +547,9 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void *
* free chunk. If the heap must expand, we double its size.
*/
if(found == FALSE) {
- size_t need_more; /* How much more space we need */
- size_t new_heap_alloc; /* Final size of space allocated for heap */
- htri_t can_extend; /* Whether the local heap's data segment on disk can be extended */
+ size_t need_more; /* How much more space we need */
+ size_t new_heap_alloc; /* Final size of space allocated for heap */
+ htri_t extended; /* Whether the local heap's data segment on disk was extended */
/* At least double the heap's size, making certain there's enough room
* for the new object */
@@ -1011,34 +609,21 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void *
H5_CHECK_OVERFLOW(heap->heap_alloc, size_t, hsize_t);
H5_CHECK_OVERFLOW(new_heap_alloc, size_t, hsize_t);
- /* Check if current heap is extendible */
- can_extend = H5MF_can_extend(f, H5FD_MEM_LHEAP, heap->addr, (hsize_t)(heap->heap_alloc), (hsize_t)need_more);
- if(can_extend < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "unable to check whether heap can be extended")
+ /* Extend current heap if possible */
+ extended = H5MF_try_extend(f, dxpl_id, H5FD_MEM_LHEAP, heap->addr, (hsize_t)(heap->heap_alloc), (hsize_t)need_more);
+ if(extended < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, (size_t)(-1), "error trying to extend heap")
- /* extend the current heap if we can... */
- if(can_extend == TRUE) {
- if(H5MF_extend(f, H5FD_MEM_LHEAP, heap->addr, (hsize_t)(heap->heap_alloc), (hsize_t)need_more) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "can't extend heap on disk")
- } /* end if */
- else { /* ...if we can't, allocate a new chunk & release the old */
- haddr_t new_addr;
-
- /* The new allocation may fail -- to avoid the possiblity of
- * file corruption, allocate the new heap first, and then
- * deallocate the old.
- */
+ /* If we couldn't extend the heap, release old chunk and allocate a new one */
+ if(extended == FALSE) {
+ /* Release old space on disk */
+ if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->addr, (hsize_t)heap->heap_alloc) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, (size_t)(-1), "unable to free local heap")
/* allocate new disk space for the heap */
- if((new_addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, (hsize_t)new_heap_alloc)) == HADDR_UNDEF)
+ if((heap->addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, (hsize_t)new_heap_alloc)) == HADDR_UNDEF)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "unable to allocate file space for heap")
-
- /* Release old space on disk */
- H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->addr, (hsize_t)heap->heap_alloc);
- H5E_clear_stack(NULL); /* don't really care if the free failed */
-
- heap->addr = new_addr;
- } /* end else */
+ } /* end if */
/* If the last free list in the heap is at the end of the heap, extend it */
if(last_fl && last_fl->offset + last_fl->size == heap->heap_alloc) {
@@ -1096,7 +681,7 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void *
}
#endif
heap->heap_alloc = new_heap_alloc;
- heap->chunk = H5FL_BLK_REALLOC(heap_chunk, heap->chunk, (sizeof_hdr + heap->heap_alloc));
+ heap->chunk = H5FL_BLK_REALLOC(lheap_chunk, heap->chunk, (sizeof_hdr + heap->heap_alloc));
if(NULL == heap->chunk)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "memory allocation failed")
@@ -1148,7 +733,7 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size)
H5HL_free_t *fl = NULL;
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5HL_remove, FAIL);
+ FUNC_ENTER_NOAPI(H5HL_remove, FAIL)
/* check arguments */
HDassert(f);
@@ -1272,7 +857,7 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size)
} /* end if */
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HL_remove() */
@@ -1287,67 +872,33 @@ done:
* koziol@ncsa.uiuc.edu
* Mar 22 2003
*
- * Modifications:
- *
- * John Mainzer - 6/17/05
- * Modified function to use the new dirtied parmeter of
- * H5AC_unprotect(), which allows management of the is_dirty
- * field of the cache info to be moved into the cache code.
- *
*-------------------------------------------------------------------------
*/
herr_t
H5HL_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr)
{
- H5HL_t *heap = NULL;
- size_t sizeof_hdr; /* Cache H5HL header size for file */
- herr_t ret_value=SUCCEED; /* Return value */
+ H5HL_t *heap = NULL; /* Local heap to delete */
+ unsigned cache_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting heap */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5HL_delete, FAIL);
+ FUNC_ENTER_NOAPI(H5HL_delete, FAIL)
/* check arguments */
- assert(f);
- assert(H5F_addr_defined(addr));
-
- /* Cache this for later */
- sizeof_hdr= H5HL_SIZEOF_HDR(f);
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
/* Get heap pointer */
- if (NULL == (heap = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_WRITE)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap");
-
- /* Check if the heap is contiguous on disk */
- assert(!H5F_addr_overflow(addr,sizeof_hdr));
- if(H5F_addr_eq(heap->addr,addr+sizeof_hdr)) {
- /* Free the contiguous local heap in one call */
- H5_CHECK_OVERFLOW(sizeof_hdr+heap->heap_alloc,size_t,hsize_t);
- if (H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, addr, (hsize_t)(sizeof_hdr+heap->heap_alloc))<0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free contiguous local heap");
- } /* end if */
- else {
- /* Free the local heap's header */
- H5_CHECK_OVERFLOW(sizeof_hdr,size_t,hsize_t);
- if (H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, addr, (hsize_t)sizeof_hdr)<0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap header");
-
- /* Free the local heap's data */
- H5_CHECK_OVERFLOW(heap->heap_alloc,size_t,hsize_t);
- if (H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->addr, (hsize_t)heap->heap_alloc)<0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap data");
- } /* end else */
-
- /* Release the local heap metadata from the cache */
- if (H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, H5AC__DIRTIED_FLAG | H5C__DELETED_FLAG)<0) {
- heap = NULL;
- HGOTO_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release local heap");
- }
- heap = NULL;
+ if(NULL == (heap = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap")
+
+ /* Set the cache flags to delete the heap & free its file space */
+ cache_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
done:
- if (heap && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, H5AC__NO_FLAGS_SET)<0)
- HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release local heap");
+ if(heap && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, cache_flags) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release local heap")
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HL_delete() */
diff --git a/src/H5HLcache.c b/src/H5HLcache.c
new file mode 100644
index 0000000..449e166
--- /dev/null
+++ b/src/H5HLcache.c
@@ -0,0 +1,478 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5HLcache.c
+ * Feb 5 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Implement local heap metadata cache methods.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5HL_PACKAGE /* Suppress error about including H5HLpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5HLpkg.h" /* Local Heaps */
+#include "H5MFprivate.h" /* File memory management */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+#define H5HL_VERSION 0 /* Local heap collection version */
+#define H5HL_FREE_NULL 1 /* End of free list on disk */
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+/* Local encode/decode routines */
+static herr_t H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf);
+
+/* Metadata cache callbacks */
+static H5HL_t *H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1,
+ void *udata2);
+static herr_t H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, H5HL_t *heap, unsigned UNUSED * flags_ptr);
+static herr_t H5HL_clear(H5F_t *f, H5HL_t *heap, hbool_t destroy);
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* H5HL inherits cache-like properties from H5AC */
+const H5AC_class_t H5AC_LHEAP[1] = {{
+ H5AC_LHEAP_ID,
+ (H5AC_load_func_t)H5HL_load,
+ (H5AC_flush_func_t)H5HL_flush,
+ (H5AC_dest_func_t)H5HL_dest,
+ (H5AC_clear_func_t)H5HL_clear,
+ (H5AC_size_func_t)H5HL_size,
+}};
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_serialize
+ *
+ * Purpose: Serialize the heap. This function will eliminate free
+ * blocks at the tail of the heap and also split the block
+ * if it needs to be split for the file. This is so that we
+ * can serialize it correctly.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Bill Wendling
+ * wendling@ncsa.uiuc.edu
+ * Sept. 16, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf)
+{
+ H5HL_free_t *fl;
+ uint8_t *p;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_serialize)
+
+ /* check args */
+ assert(buf);
+ assert(heap);
+
+ /* serialize the header */
+ p = buf;
+ fl = heap->freelist;
+ HDmemcpy(p, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ p += H5_SIZEOF_MAGIC;
+ *p++ = H5HL_VERSION;
+ *p++ = 0; /*reserved*/
+ *p++ = 0; /*reserved*/
+ *p++ = 0; /*reserved*/
+ H5F_ENCODE_LENGTH(f, p, heap->heap_alloc);
+ H5F_ENCODE_LENGTH(f, p, fl ? fl->offset : H5HL_FREE_NULL);
+ H5F_addr_encode(f, &p, heap->addr);
+
+ /* serialize the free list */
+ for (; fl; fl = fl->next) {
+ assert (fl->offset == H5HL_ALIGN (fl->offset));
+ p = heap->chunk + H5HL_SIZEOF_HDR(f) + fl->offset;
+
+ if (fl->next) {
+ H5F_ENCODE_LENGTH(f, p, fl->next->offset);
+ } else {
+ H5F_ENCODE_LENGTH(f, p, H5HL_FREE_NULL);
+ }
+
+ H5F_ENCODE_LENGTH(f, p, fl->size);
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL_serialize() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_load
+ *
+ * Purpose: Loads a heap from disk.
+ *
+ * Return: Success: Ptr to a local heap memory data structure.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jul 17 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5HL_t *
+H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1,
+ void UNUSED * udata2)
+{
+ uint8_t hdr[52];
+ size_t sizeof_hdr; /* Cache H5HL header size for file */
+ const uint8_t *p = NULL;
+ H5HL_t *heap = NULL;
+ H5HL_free_t *fl = NULL, *tail = NULL;
+ size_t free_block = H5HL_FREE_NULL;
+ H5HL_t *ret_value;
+
+ FUNC_ENTER_NOAPI(H5HL_load, NULL)
+
+ /* check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(!udata1);
+ HDassert(!udata2);
+
+ /* Cache this for later */
+ sizeof_hdr = H5HL_SIZEOF_HDR(f);
+ HDassert(sizeof_hdr <= sizeof(hdr));
+
+ /* Get the local heap's header */
+ if(H5F_block_read(f, H5FD_MEM_LHEAP, addr, sizeof_hdr, dxpl_id, hdr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read heap header")
+ p = hdr;
+
+ /* Check magic number */
+ if(HDmemcmp(hdr, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap signature")
+ p += H5_SIZEOF_MAGIC;
+
+ /* Version */
+ if(H5HL_VERSION != *p++)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong version number in global heap")
+
+ /* Reserved */
+ p += 3;
+
+ /* Allocate space in memory for the heap */
+ if(NULL == (heap = H5FL_CALLOC(H5HL_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+ /* heap data size */
+ H5F_DECODE_LENGTH(f, p, heap->heap_alloc);
+
+ /* free list head */
+ H5F_DECODE_LENGTH(f, p, free_block);
+ if(free_block != H5HL_FREE_NULL && free_block >= heap->heap_alloc)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list")
+
+ /* data */
+ H5F_addr_decode(f, &p, &(heap->addr));
+ if(NULL == (heap->chunk = H5FL_BLK_CALLOC(lheap_chunk, (sizeof_hdr + heap->heap_alloc))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ if(heap->heap_alloc &&
+ H5F_block_read(f, H5FD_MEM_LHEAP, heap->addr, heap->heap_alloc, dxpl_id, heap->chunk + sizeof_hdr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to read heap data")
+
+ /* Build free list */
+ while(H5HL_FREE_NULL != free_block) {
+ if(free_block >= heap->heap_alloc)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list")
+ if(NULL == (fl = H5FL_MALLOC(H5HL_free_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ fl->offset = free_block;
+ fl->prev = tail;
+ fl->next = NULL;
+ if(tail)
+ tail->next = fl;
+ tail = fl;
+ if(!heap->freelist)
+ heap->freelist = fl;
+
+ p = heap->chunk + sizeof_hdr + free_block;
+
+ H5F_DECODE_LENGTH(f, p, free_block);
+ if(free_block == 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "free block size is zero?")
+
+ H5F_DECODE_LENGTH(f, p, fl->size);
+ if(fl->offset + fl->size > heap->heap_alloc)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list")
+ } /* end while */
+
+ /* Set return value */
+ ret_value = heap;
+
+done:
+ if(!ret_value && heap)
+ if(H5HL_dest(f,heap) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "unable to destroy local heap collection")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL_load() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_flush
+ *
+ * Purpose: Flushes a heap from memory to disk if it's dirty. Optionally
+ * deletes the heap from memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jul 17 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HL_t *heap, unsigned UNUSED * flags_ptr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5HL_flush, FAIL)
+
+ /* check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(heap);
+
+ if(heap->cache_info.is_dirty) {
+ haddr_t hdr_end_addr;
+ size_t sizeof_hdr = H5HL_SIZEOF_HDR(f); /* cache H5HL header size for file */
+
+ /* Write the header */
+ if(H5HL_serialize(f, heap, heap->chunk) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSERIALIZE, FAIL, "unable to serialize local heap")
+
+ /* Copy buffer to disk */
+ hdr_end_addr = addr + (hsize_t)sizeof_hdr;
+
+ if(H5F_addr_eq(heap->addr, hdr_end_addr)) {
+ /* The header and data are contiguous */
+ if(H5F_block_write(f, H5FD_MEM_LHEAP, addr, (sizeof_hdr + heap->heap_alloc), dxpl_id, heap->chunk) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header and data to file")
+ } /* end if */
+ else {
+ if(H5F_block_write(f, H5FD_MEM_LHEAP, addr, sizeof_hdr, dxpl_id, heap->chunk) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header to file")
+
+ if(H5F_block_write(f, H5FD_MEM_LHEAP, heap->addr, heap->heap_alloc, dxpl_id, heap->chunk + sizeof_hdr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap data to file")
+ } /* end else */
+
+ heap->cache_info.is_dirty = FALSE;
+ } /* end if */
+
+ /* Should we destroy the memory version? */
+ if(destroy)
+ if(H5HL_dest(f, heap) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_dest
+ *
+ * Purpose: Destroys a heap in memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Jan 15 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HL_dest(H5F_t *f, H5HL_t *heap)
+{
+ H5HL_free_t *fl; /* Heap object free list */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HL_dest)
+
+ /* check arguments */
+ HDassert(heap);
+
+ /* Verify that node is clean */
+ HDassert(heap->cache_info.is_dirty == FALSE);
+
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!heap->cache_info.free_file_space_on_destroy || H5F_addr_defined(heap->cache_info.addr));
+
+ /* Check for freeing file space for local heap */
+ if(heap->cache_info.free_file_space_on_destroy) {
+ size_t sizeof_hdr; /* H5HL header size for file */
+ haddr_t hdr_addr; /* Address of heap header in file */
+
+ /* Compute this for later */
+ sizeof_hdr = H5HL_SIZEOF_HDR(f);
+ hdr_addr = heap->cache_info.addr;
+
+ /* Check if the heap is contiguous on disk */
+ HDassert(!H5F_addr_overflow(hdr_addr, sizeof_hdr));
+ if(H5F_addr_eq(heap->addr, hdr_addr + sizeof_hdr)) {
+ /* Free the contiguous local heap in one call */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ H5_CHECK_OVERFLOW(sizeof_hdr + heap->heap_alloc, size_t, hsize_t);
+ if(H5MF_xfree(f, H5FD_MEM_LHEAP, H5AC_dxpl_id, hdr_addr, (hsize_t)(sizeof_hdr + heap->heap_alloc)) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free contiguous local heap")
+ } /* end if */
+ else {
+ /* Free the local heap's header */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ H5_CHECK_OVERFLOW(sizeof_hdr, size_t, hsize_t);
+ if(H5MF_xfree(f, H5FD_MEM_LHEAP, H5AC_dxpl_id, hdr_addr, (hsize_t)sizeof_hdr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap header")
+
+ /* Free the local heap's data */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ H5_CHECK_OVERFLOW(heap->heap_alloc, size_t, hsize_t);
+ if(H5MF_xfree(f, H5FD_MEM_LHEAP, H5AC_dxpl_id, heap->addr, (hsize_t)heap->heap_alloc) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap data")
+ } /* end else */
+ } /* end if */
+
+ /* Release resources */
+ if(heap->chunk)
+ heap->chunk = H5FL_BLK_FREE(lheap_chunk, heap->chunk);
+ while(heap->freelist) {
+ fl = heap->freelist;
+ heap->freelist = fl->next;
+ (void)H5FL_FREE(H5HL_free_t, fl);
+ } /* end while */
+ (void)H5FL_FREE(H5HL_t, heap);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL_dest() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_clear
+ *
+ * Purpose: Mark a local heap in memory as non-dirty.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Mar 20 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HL_clear(H5F_t *f, H5HL_t *heap, hbool_t destroy)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HL_clear)
+
+ /* check arguments */
+ HDassert(heap);
+
+ /* Mark heap as clean */
+ heap->cache_info.is_dirty = FALSE;
+
+ if(destroy)
+ if(H5HL_dest(f, heap) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL_clear() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_size
+ *
+ * Purpose: Compute the size in bytes of the specified instance of
+ * H5HL_t on disk, and return it in *len_ptr. On failure,
+ * the value of *len_ptr is undefined.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 5/13/04
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HL_size(const H5F_t *f, const H5HL_t *heap, size_t *size_ptr)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_size)
+
+ /* check arguments */
+ HDassert(f);
+ HDassert(heap);
+ HDassert(size_ptr);
+
+ *size_ptr = H5HL_SIZEOF_HDR(f) + heap->heap_alloc;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5HL_size() */
+
diff --git a/src/H5HLpkg.h b/src/H5HLpkg.h
index 48781e3..1e34a48 100644
--- a/src/H5HLpkg.h
+++ b/src/H5HLpkg.h
@@ -32,6 +32,9 @@
#include "H5HLprivate.h"
/* Other private headers needed by this file */
+#include "H5ACprivate.h" /* Metadata cache */
+#include "H5FLprivate.h" /* Free lists */
+
/*****************************/
/* Package Private Variables */
@@ -40,6 +43,16 @@
/* The cache subclass */
H5_DLLVAR const H5AC_class_t H5AC_LHEAP[1];
+/* Declare extern the free list to manage the H5HL_free_t struct */
+H5FL_EXTERN(H5HL_free_t);
+
+/* Declare extern the free list to manage the H5HL_t struct */
+H5FL_EXTERN(H5HL_t);
+
+/* Declare extern the PQ free list to manage the heap chunk information */
+H5FL_BLK_EXTERN(lheap_chunk);
+
+
/**************************/
/* Package Private Macros */
/**************************/
@@ -51,6 +64,7 @@ H5_DLLVAR const H5AC_class_t H5AC_LHEAP[1];
H5F_SIZEOF_SIZE (F) + /*free list head */ \
H5F_SIZEOF_ADDR (F)) /*data address */
+
/****************************/
/* Package Private Typedefs */
/****************************/
@@ -71,10 +85,13 @@ struct H5HL_t {
H5HL_free_t *freelist; /*the free list */
};
+
/******************************/
/* Package Private Prototypes */
/******************************/
-#endif
+H5_DLL herr_t H5HL_dest(H5F_t *f, H5HL_t *heap);
+H5_DLL herr_t H5HL_size(const H5F_t *f, const H5HL_t *heap, size_t *size_ptr);
+#endif /* _H5HLpkg_H */
diff --git a/src/H5MF.c b/src/H5MF.c
index b9a5e7f..d7bbd21 100644
--- a/src/H5MF.c
+++ b/src/H5MF.c
@@ -29,6 +29,7 @@
/****************/
#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+#define H5MF_PACKAGE /*suppress error about including H5MFpkg */
/***********/
@@ -37,18 +38,33 @@
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5Fpkg.h" /* File access */
-#include "H5MFprivate.h" /* File memory management */
+#include "H5MFpkg.h" /* File memory management */
+#include "H5Vprivate.h" /* Vectors and arrays */
/****************/
/* Local Macros */
/****************/
+#define H5MF_FSPACE_SHRINK 80 /* Percent of "normal" size to shrink serialized free space size */
+#define H5MF_FSPACE_EXPAND 120 /* Percent of "normal" size to expand serialized free space size */
+
+/* Map an allocation request type to a free list */
+#define H5MF_ALLOC_TO_FS_TYPE(F, T) ((H5FD_MEM_DEFAULT == (F)->shared->fs_type_map[T]) \
+ ? (T) : (F)->shared->fs_type_map[T])
+
/******************/
/* Local Typedefs */
/******************/
+/* Enum for kind of free space section+aggregator merging allowed for a file */
+typedef enum {
+ H5MF_AGGR_MERGE_SEPARATE, /* Everything in separate free list */
+ H5MF_AGGR_MERGE_DICHOTOMY, /* Metadata in one free list and raw data in another */
+ H5MF_AGGR_MERGE_TOGETHER /* Metadata & raw data in one free list */
+} H5MF_aggr_merge_t;
+
/********************/
/* Package Typedefs */
@@ -58,7 +74,6 @@
/********************/
/* Local Prototypes */
/********************/
-static hbool_t H5MF_alloc_overflow(H5F_t *f, hsize_t size);
/*********************/
@@ -77,6 +92,177 @@ static hbool_t H5MF_alloc_overflow(H5F_t *f, hsize_t size);
/*-------------------------------------------------------------------------
+ * Function: H5MF_init_merge_flags
+ *
+ * Purpose: Initialize the free space section+aggregator merge flags
+ * for the file.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Friday, February 1, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5MF_init_merge_flags(H5F_t *f)
+{
+ H5MF_aggr_merge_t mapping_type; /* Type of free list mapping */
+ H5FD_mem_t type; /* Memory type for iteration */
+ hbool_t all_same; /* Whether all the types map to the same value */
+
+ FUNC_ENTER_NOAPI_NOFUNC(H5MF_init_merge_flags)
+
+ /* check args */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->lf);
+
+ /* Iterate over all the free space types to determine if sections of that type
+ * can merge with the metadata or small 'raw' data aggregator
+ */
+ all_same = TRUE;
+ for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type))
+ /* Check for any different type mappings */
+ if(f->shared->fs_type_map[type] != f->shared->fs_type_map[H5FD_MEM_DEFAULT]) {
+ all_same = FALSE;
+ break;
+ } /* end if */
+
+ /* Check for all allocation types mapping to the same free list type */
+ if(all_same) {
+ if(f->shared->fs_type_map[H5FD_MEM_DEFAULT] == H5FD_MEM_DEFAULT)
+ mapping_type = H5MF_AGGR_MERGE_SEPARATE;
+ else
+ mapping_type = H5MF_AGGR_MERGE_TOGETHER;
+ } /* end if */
+ else {
+ /* Check for raw data mapping into same list as metadata */
+ if(f->shared->fs_type_map[H5FD_MEM_DRAW] == f->shared->fs_type_map[H5FD_MEM_SUPER])
+ mapping_type = H5MF_AGGR_MERGE_SEPARATE;
+ else {
+ hbool_t all_metadata_same; /* Whether all metadata go in same free list */
+
+ /* One or more allocation type don't map to the same free list type */
+ /* Check if all the metadata allocation types map to the same type */
+ all_metadata_same = TRUE;
+ for(type = H5FD_MEM_SUPER; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type))
+ /* Skip checking raw data free list mapping */
+ if(type != H5FD_MEM_DRAW) {
+ /* Check for any different type mappings */
+ if(f->shared->fs_type_map[type] != f->shared->fs_type_map[H5FD_MEM_SUPER]) {
+ all_metadata_same = FALSE;
+ break;
+ } /* end if */
+ } /* end if */
+
+ /* Check for all metadata on same free list */
+ if(all_metadata_same)
+ mapping_type = H5MF_AGGR_MERGE_DICHOTOMY;
+ else
+ mapping_type = H5MF_AGGR_MERGE_SEPARATE;
+ } /* end else */
+ } /* end else */
+
+ /* Based on mapping type, initialize merging flags for each free list type */
+ switch(mapping_type) {
+ case H5MF_AGGR_MERGE_SEPARATE:
+ HDmemset(f->shared->fs_aggr_merge, 0, sizeof(f->shared->fs_aggr_merge));
+ break;
+
+ case H5MF_AGGR_MERGE_DICHOTOMY:
+ HDmemset(f->shared->fs_aggr_merge, H5F_FS_MERGE_METADATA, sizeof(f->shared->fs_aggr_merge));
+ f->shared->fs_aggr_merge[H5FD_MEM_DRAW] = H5F_FS_MERGE_RAWDATA;
+ break;
+
+ case H5MF_AGGR_MERGE_TOGETHER:
+ HDmemset(f->shared->fs_aggr_merge, (H5F_FS_MERGE_METADATA | H5F_FS_MERGE_RAWDATA), sizeof(f->shared->fs_aggr_merge));
+ break;
+ } /* end switch */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5MF_init_merge_flags() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_alloc_start
+ *
+ * Purpose: "Start up" free space for file - open existing free space
+ * structure if one exists, otherwise create a new free space
+ * structure
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jan 8 2008
+ *
+ * Modifications:
+ * Vailin Choi, July 29th, 2008
+ * Pass values of alignment and threshold to FS_create() for handling alignment
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5MF_alloc_start(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, hbool_t may_create)
+{
+ const H5FS_section_class_t *classes[] = { /* Free space section classes implemented for file */
+ H5MF_FSPACE_SECT_CLS_SIMPLE};
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5MF_alloc_start)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(f->shared);
+
+ /* Check for creating free space info for the file */
+ if(H5F_addr_defined(f->shared->fs_addr[type])) {
+ /* Open an existing free space structure for the file */
+ HDassert(f->shared->fs_state[type] == H5F_FS_STATE_CLOSED);
+ if(NULL == (f->shared->fs_man[type] = H5FS_open(f, dxpl_id, f->shared->fs_addr[type],
+ NELMTS(classes), classes, f, f->shared->alignment, f->shared->threshold)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space info")
+ } /* end if */
+ else {
+ /* Check if we are allowed to create the free space manager */
+ if(may_create) {
+ H5FS_create_t fs_create; /* Free space creation parameters */
+
+ /* Set the free space creation parameters */
+ fs_create.client = H5FS_CLIENT_FILE_ID;
+ fs_create.shrink_percent = H5MF_FSPACE_SHRINK;
+ fs_create.expand_percent = H5MF_FSPACE_EXPAND;
+ fs_create.max_sect_addr = 1 + H5V_log2_gen((uint64_t)f->shared->maxaddr);
+ fs_create.max_sect_size = f->shared->maxaddr;
+
+ /* Create the free space structure for the heap */
+ HDassert(f->shared->fs_state[type] == H5F_FS_STATE_CLOSED);
+#ifdef LATER
+ if(NULL == (f->shared->fs_man[type] = H5FS_create(f, dxpl_id, &f->shared->fs_addr[type],
+ &fs_create, NELMTS(classes), classes, f, f->shared->alignment, f->shared->threshold)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space info")
+#else /* LATER */
+ if(NULL == (f->shared->fs_man[type] = H5FS_create(f, dxpl_id, NULL,
+ &fs_create, NELMTS(classes), classes, f, f->shared->alignment, f->shared->threshold)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space info")
+#endif /* LATER */
+ } /* end if */
+ } /* end else */
+
+ /* Set the state for the free space manager to "open", if it is now */
+ if(f->shared->fs_man[type])
+ f->shared->fs_state[type] = H5F_FS_STATE_OPEN;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MF_alloc_start() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5MF_alloc
*
* Purpose: Allocate SIZE bytes of file memory and return the relative
@@ -94,31 +280,105 @@ static hbool_t H5MF_alloc_overflow(H5F_t *f, hsize_t size);
*-------------------------------------------------------------------------
*/
haddr_t
-H5MF_alloc(H5F_t *f, H5FD_mem_t type, hid_t dxpl_id, hsize_t size)
+H5MF_alloc(H5F_t *f, H5FD_mem_t alloc_type, hid_t dxpl_id, hsize_t size)
{
- haddr_t ret_value;
+ H5FD_mem_t fs_type; /* Free space type (mapped from allocation type) */
+ haddr_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5MF_alloc, HADDR_UNDEF)
+#ifdef H5MF_ALLOC_DEBUG
+HDfprintf(stderr, "%s: alloc_type = %u, size = %Hu\n", FUNC, (unsigned)alloc_type, size);
+#endif /* H5MF_ALLOC_DEBUG */
/* check arguments */
HDassert(f);
HDassert(size > 0);
- /* Fail if we don't have write access */
- if(0 == (f->intent & H5F_ACC_RDWR))
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, HADDR_UNDEF, "file is read-only")
-
- /* Allocate space from the virtual file layer */
- if(HADDR_UNDEF == (ret_value = H5FD_alloc(f->shared->lf, type, dxpl_id, size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, "file allocation failed")
-
- /* Convert absolute file address to relative file address */
- HDassert(ret_value >= f->shared->base_addr);
-
- /* Set return value */
- ret_value -= f->shared->base_addr;
+ /* Get free space type from allocation type */
+ fs_type = H5MF_ALLOC_TO_FS_TYPE(f, alloc_type);
+
+ /* Check if the free space manager for the file has been initialized */
+ if(!f->shared->fs_man[fs_type])
+ if(H5MF_alloc_start(f, dxpl_id, fs_type, FALSE) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, HADDR_UNDEF, "can't initialize file free space")
+
+ /* Search for large enough space in the free space manager */
+ if(f->shared->fs_man[fs_type]) {
+ H5MF_free_section_t *node; /* Free space section pointer */
+ htri_t node_found = FALSE; /* Whether an existing free list node was found */
+
+ /* Try to get a section from the free space manager */
+ if((node_found = H5FS_sect_find(f, dxpl_id, f->shared->fs_man[fs_type], size, (H5FS_section_info_t **)&node)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "error locating free space in file")
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: Check 1.5, node_found = %t\n", FUNC, node_found);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+
+ /* Check for actually finding section */
+ if(node_found) {
+ /* Sanity check */
+ HDassert(node);
+
+ /* Retrieve return value */
+ ret_value = node->sect_info.addr;
+
+ /* Check for eliminating the section */
+ if(node->sect_info.size == size) {
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: Check 1.6, freeing node\n", FUNC);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+ /* Free section node */
+ if(H5MF_sect_simple_free((H5FS_section_info_t *)node) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, HADDR_UNDEF, "can't free simple section node")
+ } /* end if */
+ else {
+ H5MF_sect_ud_t udata; /* User data for callback */
+
+ /* Adjust information for section */
+ node->sect_info.addr += size;
+ node->sect_info.size -= size;
+
+ /* Construct user data for callbacks */
+ udata.f = f;
+ udata.dxpl_id = dxpl_id;
+ udata.alloc_type = alloc_type;
+ udata.allow_sect_absorb = TRUE;
+
+#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);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+ /* Re-insert section node into file's free space */
+ if(H5FS_sect_add(f, dxpl_id, f->shared->fs_man[fs_type], (H5FS_section_info_t *)node, H5FS_ADD_RETURNED_SPACE, &udata) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINSERT, HADDR_UNDEF, "can't re-add section to file free space")
+ } /* end else */
+
+ /* Leave now */
+ HGOTO_DONE(ret_value)
+ } /* end if */
+ } /* end if */
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: Check 2.0\n", FUNC);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+
+ /* Couldn't find anything from the free space manager, go allocate some */
+ if(alloc_type != H5FD_MEM_DRAW) {
+ /* Handle metadata differently from "raw" data */
+ if(HADDR_UNDEF == (ret_value = H5MF_aggr_alloc(f, dxpl_id, &(f->shared->meta_aggr), &(f->shared->sdata_aggr), alloc_type, size)))
+ HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate metadata")
+ } /* end if */
+ else {
+ /* Allocate "raw" data */
+ if(HADDR_UNDEF == (ret_value = H5MF_aggr_alloc(f, dxpl_id, &(f->shared->sdata_aggr), &(f->shared->meta_aggr), alloc_type, size)))
+ HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate raw data")
+ } /* end else */
done:
+#ifdef H5MF_ALLOC_DEBUG
+HDfprintf(stderr, "%s: Leaving: ret_value = %a, size = %Hu\n", FUNC, ret_value, size);
+#endif /* H5MF_ALLOC_DEBUG */
+#ifdef H5MF_ALLOC_DEBUG_DUMP
+H5MF_sects_dump(f, dxpl_id, stderr);
+#endif /* H5MF_ALLOC_DEBUG_DUMP */
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5MF_alloc() */
@@ -138,193 +398,458 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5MF_xfree(H5F_t *f, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t size)
+H5MF_xfree(H5F_t *f, H5FD_mem_t alloc_type, hid_t dxpl_id, haddr_t addr,
+ hsize_t size)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5MF_free_section_t *node = NULL; /* Free space section pointer */
+ H5MF_sect_ud_t udata; /* User data for callback */
+ H5FD_mem_t fs_type; /* Free space type (mapped from allocation type) */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOFUNC(H5MF_xfree)
+ FUNC_ENTER_NOAPI(H5MF_xfree, FAIL)
+#ifdef H5MF_ALLOC_DEBUG
+HDfprintf(stderr, "%s: Entering - alloc_type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)alloc_type, addr, size);
+#endif /* H5MF_ALLOC_DEBUG */
/* check arguments */
HDassert(f);
if(!H5F_addr_defined(addr) || 0 == size)
HGOTO_DONE(SUCCEED);
- HDassert(addr != 0);
-
- /* Convert relative address to absolute address */
- addr += f->shared->base_addr;
-
- /* Allow virtual file layer to free block */
- if(H5FD_free(f->shared->lf, type, dxpl_id, addr, size) < 0) {
-#ifdef H5MF_DEBUG
- if(H5DEBUG(MF))
- fprintf(H5DEBUG(MF), "H5MF_free: lost %lu bytes of file storage\n", (unsigned long)size);
-#endif
+ HDassert(addr != 0); /* Can't deallocate the superblock :-) */
+
+ /* Check if the space to free intersects with the file's metadata accumulator */
+ if(H5F_accum_free(f, dxpl_id, alloc_type, addr, size) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "can't check free space intersection w/metadata accumulator")
+
+ /* Get free space type from allocation type */
+ fs_type = H5MF_ALLOC_TO_FS_TYPE(f, alloc_type);
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: fs_type = %u\n", FUNC, (unsigned)fs_type);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+
+ /* Check if the free space manager for the file has been initialized */
+ if(!f->shared->fs_man[fs_type]) {
+ /* If there's no free space manager for objects of this type,
+ * see if we can avoid creating one by checking if the freed
+ * space is at the end of the file
+ */
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: f->shared->fs_addr[%u] = %a\n", FUNC, (unsigned)fs_type, f->shared->fs_addr[fs_type]);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+ if(!H5F_addr_defined(f->shared->fs_addr[fs_type])) {
+ htri_t status; /* "can absorb" status for section into */
+
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: Trying to avoid starting up free space manager\n", FUNC);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+ /* Try to shrink the file or absorb the block into a block aggregator */
+ if((status = H5MF_try_shrink(f, alloc_type, dxpl_id, addr, size)) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't check for absorbing block")
+ else if(status > 0)
+ /* Indicate success */
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+
+ /* If we are deleting the free space manager, leave now, to avoid
+ * [re-]starting it.
+ *
+ * Note: this drops the space to free on the floor...
+ *
+ */
+ if(f->shared->fs_state[fs_type] == H5F_FS_STATE_DELETING)
+{
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: dropping addr = %a, size = %Hu, on the floor!\n", FUNC, addr, size);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+ HGOTO_DONE(SUCCEED)
+}
+
+ /* There's either already a free space manager, or the freed
+ * space isn't at the end of the file, so start up (or create)
+ * the file space manager
+ */
+ if(H5MF_alloc_start(f, dxpl_id, fs_type, TRUE) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space")
} /* end if */
+ HDassert(f->shared->fs_man[fs_type]);
+
+ /* Create free space section for block */
+ if(NULL == (node = H5MF_sect_simple_new(addr, size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space section")
+
+ /* Construct user data for callbacks */
+ udata.f = f;
+ udata.dxpl_id = dxpl_id;
+ udata.alloc_type = alloc_type;
+ udata.allow_sect_absorb = TRUE;
+
+ /* Add to the free space for the file */
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: Before H5FS_sect_add()\n", FUNC);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+ if(H5FS_sect_add(f, dxpl_id, f->shared->fs_man[fs_type], (H5FS_section_info_t *)node, H5FS_ADD_RETURNED_SPACE, &udata) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINSERT, FAIL, "can't add section to file free space")
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: After H5FS_sect_add()\n", FUNC);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+ node = NULL;
done:
+ if(ret_value < 0 && node)
+ /* On error, free section node allocated */
+ if(H5MF_sect_simple_free((H5FS_section_info_t *)node) < 0)
+ HDONE_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free simple section node")
+
+#ifdef H5MF_ALLOC_DEBUG
+HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value);
+#endif /* H5MF_ALLOC_DEBUG */
+#ifdef H5MF_ALLOC_DEBUG_DUMP
+H5MF_sects_dump(f, dxpl_id, stderr);
+#endif /* H5MF_ALLOC_DEBUG_DUMP */
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5MF_xfree() */
/*-------------------------------------------------------------------------
- * Function: H5MF_realloc
+ * Function: H5MF_try_extend
*
- * Purpose: Changes the size of an allocated chunk, possibly moving it to
- * a new address. The chunk to change is at address OLD_ADDR
- * and is exactly OLD_SIZE bytes (if these are H5F_ADDR_UNDEF
- * and zero then this function acts like H5MF_alloc). The new
- * size will be NEW_SIZE and its address is the return value (if
- * NEW_SIZE is zero then this function acts like H5MF_free and
- * an undefined address is returned).
+ * Purpose: Extend a block in the file if possible.
*
- * If the new size is less than the old size then the new
- * address will be the same as the old address (except for the
- * special case where the new size is zero).
- *
- * If the new size is more than the old size then most likely a
- * new address will be returned. However, under certain
- * circumstances the library may return the same address.
- *
- * Return: Success: The relative file address of the new block.
- * Failure: HADDR_UNDEF
+ * Return: Success: TRUE(1) - Block was extended
+ * FALSE(0) - Block could not be extended
+ * Failure: FAIL
*
- * Programmer: Robb Matzke
- * Thursday, April 16, 1998
+ * Programmer: Quincey Koziol
+ * Friday, June 11, 2004
*
*-------------------------------------------------------------------------
*/
-haddr_t
-H5MF_realloc(H5F_t *f, H5FD_mem_t type, hid_t dxpl_id, haddr_t old_addr, hsize_t old_size,
- hsize_t new_size)
+htri_t
+H5MF_try_extend(H5F_t *f, hid_t dxpl_id, H5FD_mem_t alloc_type, haddr_t addr,
+ hsize_t size, hsize_t extra_requested)
{
- haddr_t ret_value;
-
- FUNC_ENTER_NOAPI(H5MF_realloc, HADDR_UNDEF)
-
- /* Convert old relative address to absolute address */
- old_addr += f->shared->base_addr;
-
- /* Reallocate memory from the virtual file layer */
- ret_value = H5FD_realloc(f->shared->lf, type, dxpl_id, old_addr, old_size, new_size);
- if(HADDR_UNDEF == ret_value)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, "unable to allocate new file memory")
-
- /* Convert return value to relative address */
- HDassert(ret_value >= f->shared->base_addr);
+ haddr_t end; /* End of block to extend */
+ htri_t ret_value; /* Return value */
- /* Set return value */
- ret_value -= f->shared->base_addr;
+ FUNC_ENTER_NOAPI(H5MF_try_extend, FAIL)
+#ifdef H5MF_ALLOC_DEBUG
+HDfprintf(stderr, "%s: Entering: alloc_type = %u, addr = %a, size = %Hu, extra_requested = %Hu\n", FUNC, (unsigned)alloc_type, addr, size, extra_requested);
+#endif /* H5MF_ALLOC_DEBUG */
+
+ /* Compute end of block to extend */
+ end = addr + size;
+
+ /* Check if the block is exactly at the end of the file */
+ if((ret_value = H5FD_try_extend(f->shared->lf, alloc_type, end, extra_requested)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, "error extending file")
+ else if(ret_value == FALSE) {
+ H5F_blk_aggr_t *aggr; /* Aggregator to use */
+
+ /* Check for test block able to extend aggregation block */
+ aggr = (alloc_type == H5FD_MEM_DRAW) ? &(f->shared->sdata_aggr) : &(f->shared->meta_aggr);
+ if((ret_value = H5MF_aggr_try_extend(f, aggr, alloc_type, end, extra_requested)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, "error extending aggregation block")
+ else if(ret_value == FALSE) {
+ H5FD_mem_t fs_type; /* Free space type (mapped from allocation type) */
+
+ /* Get free space type from allocation type */
+ fs_type = H5MF_ALLOC_TO_FS_TYPE(f, alloc_type);
+
+ /* Check if the free space for the file has been initialized */
+ if(!f->shared->fs_man[fs_type])
+ if(H5MF_alloc_start(f, dxpl_id, fs_type, FALSE) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space")
+
+ /* Check for test block able to block in free space manager */
+ if(f->shared->fs_man[fs_type])
+ if((ret_value = H5FS_sect_try_extend(f, dxpl_id, f->shared->fs_man[fs_type], addr, size, extra_requested)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, "error extending block in free space manager")
+ } /* end if */
+ } /* end if */
done:
+#ifdef H5MF_ALLOC_DEBUG
+HDfprintf(stderr, "%s: Leaving: ret_value = %t\n", FUNC, ret_value);
+#endif /* H5MF_ALLOC_DEBUG */
+#ifdef H5MF_ALLOC_DEBUG_DUMP
+H5MF_sects_dump(f, dxpl_id, stderr);
+#endif /* H5MF_ALLOC_DEBUG_DUMP */
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5MF_realloc() */
+} /* end H5MF_try_extend() */
/*-------------------------------------------------------------------------
- * Function: H5MF_alloc_overflow
+ * Function: H5MF_get_freespace
*
- * Purpose: Checks if an allocation of file space would cause an overflow.
- * F is the file whose space is being allocated, SIZE is the amount
- * of space needed.
+ * Purpose: Retrieve the amount of free space in a file.
*
- * Return: FALSE if no overflow would result
- * TRUE if overflow would result (the allocation should not be allowed)
+ * Return: Success: Amount of free space in file
+ * Failure: Negative
*
- * Programmer: James Laird
- * Nat Furrer
- * Tuesday, June 1, 2004
+ * Programmer: Quincey Koziol
+ * Monday, October 6, 2003
*
*-------------------------------------------------------------------------
*/
-static hbool_t
-H5MF_alloc_overflow(H5F_t *f, hsize_t size)
+hssize_t
+H5MF_get_freespace(H5F_t *f, hid_t dxpl_id)
{
- haddr_t eoa; /* End-of-allocation in the file */
- haddr_t space_avail; /* Unallocated space still available in file */
- hbool_t ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5MF_alloc_overflow)
-
- /* Start with the current end of the file's address. */
- eoa = H5F_get_eoa(f);
- HDassert(H5F_addr_defined(eoa));
-
- /* Subtract EOA from the file's maximum address to get the actual amount of
- * addressable space left in the file.
- */
- HDassert(f->shared->maxaddr >= eoa);
- space_avail = (hsize_t)(f->shared->maxaddr - eoa);
+ haddr_t eoa; /* End of allocated space in the file */
+ haddr_t ma_addr = HADDR_UNDEF; /* Base "metadata aggregator" address */
+ hsize_t ma_size = 0; /* Size of "metadata aggregator" */
+ haddr_t sda_addr = HADDR_UNDEF; /* Base "small data aggregator" address */
+ hsize_t sda_size = 0; /* Size of "small data aggregator" */
+ hsize_t tot_fs_size = 0; /* Amount of all free space managed */
+ H5FD_mem_t type; /* Memory type for iteration */
+ hssize_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5MF_get_freespace, FAIL)
+
+ /* check args */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->lf);
+
+ /* Retrieve the 'eoa' for the file */
+ if(HADDR_UNDEF == (eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed")
+
+ /* Retrieve metadata aggregator info, if available */
+ H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size);
+
+ /* Retrieve 'small data' aggregator info, if available */
+ H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sda_addr, &sda_size);
+
+ /* 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)) {
+ hsize_t type_fs_size = 0; /* Amount of free space managed for each type */
+
+ /* Check if the free space for the file has been initialized */
+ if(!f->shared->fs_man[type])
+ if(H5MF_alloc_start(f, dxpl_id, type, FALSE) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space")
+
+ /* Retrieve free space size from free space manager */
+ if(f->shared->fs_man[type])
+ if((ret_value = H5FS_sect_stats(f->shared->fs_man[type], &type_fs_size, NULL)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't query free space stats")
+
+ /* Increment total free space for types */
+ tot_fs_size += type_fs_size;
+ } /* end for */
+
+ /* Start computing value to return */
+ ret_value = tot_fs_size;
+
+ /* Check for aggregating metadata allocations */
+ if(ma_size > 0) {
+ /* Add in the reserved space for metadata to the available free space */
+ /* (if it's not at the tail of the file) */
+ if(H5F_addr_ne(ma_addr + ma_size, eoa))
+ ret_value += ma_size;
+ } /* end if */
- /* Ensure that there's enough room left in the file for something of this size */
- if(size > space_avail)
- ret_value = TRUE;
- else
- ret_value = FALSE;
+ /* Check for aggregating small data allocations */
+ if(sda_size > 0) {
+ /* Add in the reserved space for metadata to the available free space */
+ /* (if it's not at the tail of the file) */
+ if(H5F_addr_ne(sda_addr + sda_size, eoa))
+ ret_value += sda_size;
+ } /* end if */
+done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5MF_alloc_overflow() */
+} /* end H5MF_get_freespace() */
/*-------------------------------------------------------------------------
- * Function: H5MF_can_extend
+ * Function: H5MF_can_shrink
*
- * Purpose: Check if a block in the file can be extended.
+ * Purpose: Try to shrink the size of a file with a block or absorb it
+ * into a block aggregator.
*
- * Return: Success: TRUE(1)/FALSE(0)
- * Failure: FAIL
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Quincey Koziol
- * Friday, June 11, 2004
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Feb 14 2008
*
*-------------------------------------------------------------------------
*/
htri_t
-H5MF_can_extend(H5F_t *f, H5FD_mem_t type, haddr_t addr, hsize_t size, hsize_t extra_requested)
+H5MF_try_shrink(H5F_t *f, H5FD_mem_t alloc_type, hid_t dxpl_id, haddr_t addr,
+ hsize_t size)
{
- htri_t ret_value; /* Return value */
+ H5MF_free_section_t *node = NULL; /* Free space section pointer */
+ H5MF_sect_ud_t udata; /* User data for callback */
+ htri_t ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5MF_can_extend, FAIL)
+ FUNC_ENTER_NOAPI(H5MF_try_shrink, FAIL)
+#ifdef H5MF_ALLOC_DEBUG
+HDfprintf(stderr, "%s: Entering - alloc_type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)alloc_type, addr, size);
+#endif /* H5MF_ALLOC_DEBUG */
- /* Convert old relative address to absolute address */
- addr += H5F_BASE_ADDR(f);
+ /* check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(size > 0);
- /* Pass the request down to the virtual file layer */
- if((ret_value = H5FD_can_extend(f->shared->lf, type, addr, size, extra_requested)) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate new file memory");
+ /* Create free space section for block */
+ if(NULL == (node = H5MF_sect_simple_new(addr, size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space section")
+
+ /* Construct user data for callbacks */
+ udata.f = f;
+ udata.dxpl_id = dxpl_id;
+ udata.alloc_type = alloc_type;
+ udata.allow_sect_absorb = FALSE; /* Force section to be absorbed into aggregator */
+
+ /* Call the "can shrink" callback for the section */
+ if((ret_value = H5MF_sect_simple_can_shrink((const H5FS_section_info_t *)node, &udata)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTMERGE, FAIL, "can't check if section can shrink container")
+ else if(ret_value > 0) {
+ /* Shrink or absorb the section */
+ if(H5MF_sect_simple_shrink((H5FS_section_info_t **)&node, &udata) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't shrink container")
+ } /* end if */
done:
+ /* Free section node allocated */
+ if(node && H5MF_sect_simple_free((H5FS_section_info_t *)node) < 0)
+ HDONE_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free simple section node")
+
+#ifdef H5MF_ALLOC_DEBUG
+HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value);
+#endif /* H5MF_ALLOC_DEBUG */
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5MF_can_extend() */
+} /* end H5MF_try_shrink() */
/*-------------------------------------------------------------------------
- * Function: H5MF_extend
+ * Function: H5MF_close
*
- * Purpose: Extend a block in the file.
+ * Purpose: Close the free space tracker(s) for a file
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: SUCCEED/FAIL
*
- * Programmer: Quincey Koziol
- * Saturday, June 12, 2004
+ * Programmer: Quincey Koziol
+ * Tuesday, January 22, 2008
*
*-------------------------------------------------------------------------
*/
herr_t
-H5MF_extend(H5F_t *f, H5FD_mem_t type, haddr_t addr, hsize_t size, hsize_t extra_requested)
+H5MF_close(H5F_t *f, hid_t dxpl_id)
{
- herr_t ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI(H5MF_extend, FAIL)
-
- /* Convert relative address to absolute address */
- addr += H5F_BASE_ADDR(f);
-
- /* Pass the request down to the virtual file layer */
- if((ret_value = H5FD_extend(f->shared->lf, type, addr, size, extra_requested)) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate new file memory")
+ H5FD_mem_t type; /* Memory type for iteration */
+ H5F_blk_aggr_t *first_aggr; /* First aggregator to reset */
+ H5F_blk_aggr_t *second_aggr; /* Second aggregator to reset */
+ haddr_t ma_addr = HADDR_UNDEF; /* Base "metadata aggregator" address */
+ hsize_t ma_size = 0; /* Size of "metadata aggregator" */
+ haddr_t sda_addr = HADDR_UNDEF; /* Base "small data aggregator" address */
+ hsize_t sda_size = 0; /* Size of "small data aggregator" */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5MF_close, FAIL)
+#ifdef H5MF_ALLOC_DEBUG
+HDfprintf(stderr, "%s: Entering\n", FUNC);
+#endif /* H5MF_ALLOC_DEBUG */
+
+ /* check args */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->lf);
+
+ /* 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)) {
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: Check 1.0 - f->shared->fs_man[%u] = %p, f->shared->fs_addr[%u] = %a\n", FUNC, (unsigned)type, f->shared->fs_man[type], (unsigned)type, f->shared->fs_addr[type]);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+ /* If the free space manager for this type is open, close it */
+ if(f->shared->fs_man[type]) {
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: Before closing free space manager\n", FUNC);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+ if(H5FS_close(f, dxpl_id, f->shared->fs_man[type]) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release free space info")
+ f->shared->fs_man[type] = NULL;
+ f->shared->fs_state[type] = H5F_FS_STATE_CLOSED;
+ } /* end if */
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: Check 2.0 - f->shared->fs_man[%u] = %p, f->shared->fs_addr[%u] = %a\n", FUNC, (unsigned)type, f->shared->fs_man[type], (unsigned)type, f->shared->fs_addr[type]);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+
+ /* If there is free space manager info for this type, delete it */
+ /* (XXX: Make this optional when free space for a file can be persistant) */
+ if(H5F_addr_defined(f->shared->fs_addr[type])) {
+ haddr_t tmp_fs_addr; /* Temporary holder for free space manager address */
+
+ /* Put address into temporary variable and reset it */
+ /* (Avoids loopback in file space freeing routine) */
+ tmp_fs_addr = f->shared->fs_addr[type];
+ f->shared->fs_addr[type] = HADDR_UNDEF;
+
+ /* Shift to "deleting" state, to make certain we don't track any
+ * file space freed as a result of deleting the free space manager.
+ */
+ f->shared->fs_state[type] = H5F_FS_STATE_DELETING;
+
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: Before deleting free space manager\n", FUNC);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+ /* Delete free space manager for this type */
+ if(H5FS_delete(f, dxpl_id, tmp_fs_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "can't delete free space manager")
+
+ /* Shift [back] to closed state */
+ HDassert(f->shared->fs_state[type] == H5F_FS_STATE_DELETING);
+ f->shared->fs_state[type] = H5F_FS_STATE_CLOSED;
+
+ /* Sanity check that the free space manager for this type wasn't started up again */
+ HDassert(!H5F_addr_defined(f->shared->fs_addr[type]));
+ } /* end if */
+ } /* end for */
+
+ /* Retrieve metadata aggregator info, if available */
+ H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size);
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: ma_addr = %a, ma_size = %Hu, end of ma = %a\n", FUNC, ma_addr, ma_size, (haddr_t)((ma_addr + ma_size) - 1));
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+
+ /* Retrieve 'small data' aggregator info, if available */
+ H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sda_addr, &sda_size);
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: sda_addr = %a, sda_size = %Hu, end of sda = %a\n", FUNC, sda_addr, sda_size, (haddr_t)((sda_addr + sda_size) - 1));
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+
+ /* Make certain we release the aggregator that's later in the file first */
+ /* (so the file shrinks properly) */
+ if(H5F_addr_defined(ma_addr) && H5F_addr_defined(sda_addr)) {
+ if(H5F_addr_lt(ma_addr, sda_addr)) {
+ first_aggr = &(f->shared->sdata_aggr);
+ second_aggr = &(f->shared->meta_aggr);
+ } /* end if */
+ else {
+ first_aggr = &(f->shared->meta_aggr);
+ second_aggr = &(f->shared->sdata_aggr);
+ } /* end else */
+ } /* end if */
+ else {
+ first_aggr = &(f->shared->meta_aggr);
+ second_aggr = &(f->shared->sdata_aggr);
+ } /* end else */
+
+ /* Release the unused portion of the metadata and "small data" blocks back
+ * to the free lists in the file.
+ */
+ if(H5MF_aggr_reset(f, dxpl_id, first_aggr) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "can't reset metadata block")
+ if(H5MF_aggr_reset(f, dxpl_id, second_aggr) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "can't reset 'small data' block")
done:
+#ifdef H5MF_ALLOC_DEBUG
+HDfprintf(stderr, "%s: Leaving\n", FUNC);
+#endif /* H5MF_ALLOC_DEBUG */
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5MF_extend() */
+} /* end H5MF_close() */
diff --git a/src/H5MFaggr.c b/src/H5MFaggr.c
new file mode 100644
index 0000000..dda1968
--- /dev/null
+++ b/src/H5MFaggr.c
@@ -0,0 +1,571 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Programmer: Quincey Koziol <koziol@hdfgroup.org>
+ * Tuesday, January 8, 2008
+ *
+ * Purpose: Routines for aggregating free space allocations
+ *
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+#define H5MF_PACKAGE /*suppress error about including H5MFpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* File access */
+#include "H5MFpkg.h" /* File memory management */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_aggr_alloc
+ *
+ * Purpose: Try to allocate SIZE bytes of memory from an aggregator
+ * block if possible.
+ *
+ * Return: Success: The format address of the new file memory.
+ * Failure: The undefined address HADDR_UNDEF
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, December 13, 2007
+ *
+ * Modifications:
+ * Vailin Choi, July 29th, 2008
+ * The whole routine is modified to handle alignment
+ *
+ *-------------------------------------------------------------------------
+ */
+haddr_t
+H5MF_aggr_alloc(H5F_t *f, hid_t dxpl_id, H5F_blk_aggr_t *aggr,
+ H5F_blk_aggr_t *other_aggr, H5FD_mem_t type, hsize_t size)
+{
+ haddr_t ret_value;
+ hsize_t alignment = 0, mis_align = 0;
+ haddr_t frag_addr = 0, eoa_frag_addr = 0;
+ hsize_t frag_size = 0, eoa_frag_size = 0;
+ haddr_t eoa = 0, new_space = 0;
+ htri_t extended = 0;
+ H5FD_mem_t alloc_type, other_alloc_type;
+
+ FUNC_ENTER_NOAPI(H5MF_aggr_alloc, HADDR_UNDEF)
+#ifdef H5MF_AGGR_DEBUG
+HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size);
+#endif /* H5MF_AGGR_DEBUG */
+
+ /* check args */
+ HDassert(f);
+ HDassert(aggr);
+ HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA);
+ HDassert(other_aggr);
+ HDassert(other_aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || other_aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA);
+ HDassert(other_aggr->feature_flag != aggr->feature_flag);
+ HDassert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES);
+ HDassert(size > 0);
+
+ /*
+ * If the aggregation feature is enabled for this file, allocate "generic"
+ * space and sub-allocate out of that, if possible. Otherwise just allocate
+ * through H5FD_alloc()
+ */
+ if(f->shared->feature_flags & aggr->feature_flag) {
+#ifdef H5MF_AGGR_DEBUG
+HDfprintf(stderr, "%s: aggr = {%a, %Hu, %Hu}\n", FUNC, aggr->addr, aggr->tot_size, aggr->size);
+#endif /* H5MF_AGGR_DEBUG */
+
+ alignment = f->shared->alignment;
+ if (!((alignment > 1) && (size >= f->shared->threshold)))
+ alignment = 0; /* no alignment */
+
+ if (alignment && aggr->addr > 0 && aggr->size > 0 && (mis_align = aggr->addr % alignment)) {
+ frag_addr = aggr->addr;
+ frag_size = alignment - mis_align;
+ }
+
+ if (HADDR_UNDEF == (eoa = H5F_get_eoa(f, type)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "Unable to get eoa")
+
+ alloc_type = aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA ? H5FD_MEM_DEFAULT : H5FD_MEM_DRAW;
+ other_alloc_type = other_aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA ? H5FD_MEM_DEFAULT : H5FD_MEM_DRAW;
+
+ /* Check if the space requested is larger than the space left in the block */
+ if((size + frag_size) > aggr->size) {
+
+ /* Check if the block asked for is too large for 'normal' aggregator block */
+ if(size >= aggr->alloc_size) {
+
+ hsize_t ext_size = size + frag_size;
+
+ if ((aggr->addr > 0) && (extended=H5FD_try_extend(f->shared->lf, alloc_type, aggr->addr + aggr->size, ext_size)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "can't extending space")
+ else if (extended) {
+ /* aggr->size is unchanged */
+ ret_value = aggr->addr + frag_size;
+ aggr->addr += ext_size;
+ aggr->tot_size += ext_size;
+ } else {
+ 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, other_aggr->addr, other_aggr->size) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation block")
+
+ other_aggr->addr = 0;
+ other_aggr->tot_size = 0;
+ other_aggr->size = 0;
+ }
+
+ if(HADDR_UNDEF == (new_space = H5FD_alloc(f->shared->lf, dxpl_id, type, size, &eoa_frag_addr, &eoa_frag_size)))
+ HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate aggregation block")
+
+ /* Use the new space allocated, leaving the old block */
+ ret_value = new_space;
+ } /* end else */
+ } /* end if */
+ else {
+ hsize_t ext_size = aggr->alloc_size;
+
+ /* Allocate another block */
+#ifdef H5MF_AGGR_DEBUG
+HDfprintf(stderr, "%s: Allocating block\n", FUNC);
+#endif /* H5MF_AGGR_DEBUG */
+
+ if (frag_size > (ext_size - size))
+ ext_size += (frag_size - (ext_size - size));
+
+ if ((aggr->addr > 0) && (extended = H5FD_try_extend(f->shared->lf, alloc_type, aggr->addr + aggr->size, ext_size)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "can't extending space")
+ else if (extended) {
+ aggr->addr += frag_size;
+ aggr->size += (ext_size - frag_size);
+ aggr->tot_size += ext_size;
+ } else {
+ haddr_t unused_addr = HADDR_UNDEF; /* Address of unused portion */
+ hsize_t unused_size = 0; /* Size of unused portion */
+
+ 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, other_aggr->addr, other_aggr->size) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation block")
+ other_aggr->addr = 0;
+ other_aggr->tot_size = 0;
+ other_aggr->size = 0;
+ }
+
+ if(HADDR_UNDEF == (new_space = H5FD_alloc(f->shared->lf, dxpl_id, alloc_type, aggr->alloc_size, &eoa_frag_addr, &eoa_frag_size)))
+ HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate aggregation block")
+
+ /* Return the unused portion of the block to a free list */
+ if(aggr->size > 0)
+ if(H5MF_xfree(f, alloc_type, dxpl_id, aggr->addr, aggr->size) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation block")
+
+ /* Point the aggregator at the newly allocated block */
+ aggr->addr = new_space;
+ aggr->size = aggr->alloc_size;
+ aggr->tot_size = aggr->alloc_size;
+
+ } /* end else */
+
+ /* Allocate space out of the metadata block */
+ ret_value = aggr->addr;
+ aggr->size -= size;
+ aggr->addr += size;
+ } /* end else */
+
+ /* freeing any possible fragment due to file allocation */
+ if (eoa_frag_size)
+ if(H5MF_xfree(f, type, dxpl_id, eoa_frag_addr, eoa_frag_size) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free eoa fragment")
+
+ /* freeing any possible fragment due to alignment in the block after extension */
+ if (extended && frag_size)
+ if(H5MF_xfree(f, type, dxpl_id, frag_addr, frag_size) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation fragment")
+ } /* end if */
+ else {
+ /* Allocate space out of the block */
+ ret_value = aggr->addr + frag_size;
+ aggr->size -= (size + frag_size);
+ aggr->addr += (size + frag_size);
+
+ /* free any possible fragment */
+ if (frag_size)
+ if(H5MF_xfree(f, type, dxpl_id, frag_addr, frag_size) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation fragment")
+ }
+ } /* end if */
+ else {
+ /* Allocate data from the file */
+ if(HADDR_UNDEF == (ret_value = H5FD_alloc(f->shared->lf, dxpl_id, type, size, &eoa_frag_addr, &eoa_frag_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate file space")
+ if (eoa_frag_size)
+ if(H5MF_xfree(f, type, dxpl_id, eoa_frag_addr, eoa_frag_size) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free eoa fragment")
+ } /* end else */
+
+done:
+#ifdef H5MF_AGGR_DEBUG
+HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value);
+#endif /* H5MF_AGGR_DEBUG */
+ if (alignment)
+ HDassert(!(ret_value % alignment));
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MF_aggr_alloc() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_aggr_try_extend
+ *
+ * Purpose: Check if a block is inside an aggregator block and extend it
+ * if possible.
+ *
+ * Return: Success: TRUE(1) - Block was extended
+ * FALSE(0) - Block could not be extended
+ * Failure: FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, December 13, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5MF_aggr_try_extend(const H5F_t *f, H5F_blk_aggr_t *aggr, H5FD_mem_t type,
+ haddr_t blk_end, hsize_t extra_requested)
+{
+ htri_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5MF_aggr_try_extend, FAIL)
+
+ /* Check args */
+ HDassert(f);
+ HDassert(aggr);
+ HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA);
+
+ /* Check if this aggregator is active */
+ if(f->shared->feature_flags & aggr->feature_flag) {
+ /* If the block being tested adjoins the beginning of the aggregator
+ * block, check if the aggregator can accomodate the extension.
+ */
+ if(H5F_addr_eq(blk_end, aggr->addr)) {
+ /* If the aggregator block is at the end of the file, extend the
+ * file and "bubble" the aggregator up
+ */
+ if((ret_value = H5FD_try_extend(f->shared->lf, type, (aggr->addr + aggr->size), extra_requested)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, "error extending file")
+ else if(ret_value == TRUE) {
+ /* Shift the aggregator block by the extra requested */
+ aggr->addr += extra_requested;
+
+ /* Add extra requested to the aggregator block's total amount allocated */
+ aggr->tot_size += extra_requested;
+ } /* end if */
+ else {
+ /* Check if the aggregator block has enough internal space to satisfy
+ * extending the block.
+ */
+ if(aggr->size >= extra_requested) {
+ /* Extend block into aggregator */
+ aggr->size -= extra_requested;
+ aggr->addr += extra_requested;
+
+ /* Indicate success */
+ HGOTO_DONE(TRUE);
+ } /* end if */
+ } /* end else */
+ } /* end if */
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MF_aggr_try_extend() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_aggr_can_absorb
+ *
+ * Purpose: Check if a section adjoins an aggregator block and one can
+ * absorb the other.
+ *
+ * Return: Success: TRUE(1) - Section or aggregator can be absorbed
+ * FALSE(0) - Section and aggregator can not be absorbed
+ * Failure: FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Friday, February 1, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5MF_aggr_can_absorb(const H5F_t *f, const H5F_blk_aggr_t *aggr,
+ const H5MF_free_section_t *sect, H5MF_shrink_type_t *shrink)
+{
+ htri_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOFUNC(H5MF_aggr_can_absorb)
+
+ /* Check args */
+ HDassert(f);
+ HDassert(aggr);
+ HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA);
+ HDassert(sect);
+ HDassert(shrink);
+
+ /* Check if this aggregator is active */
+ if(f->shared->feature_flags & aggr->feature_flag) {
+ /* Check if the block adjoins the beginning or end of the aggregator */
+ if(H5F_addr_eq((sect->sect_info.addr + sect->sect_info.size), aggr->addr)
+ || H5F_addr_eq((aggr->addr + aggr->size), sect->sect_info.addr)) {
+#ifdef H5MF_AGGR_DEBUG
+HDfprintf(stderr, "%s: section {%a, %Hu} adjoins aggr = {%a, %Hu}\n", "H5MF_aggr_can_absorb", sect->sect_info.addr, sect->sect_info.size, aggr->addr, aggr->size);
+#endif /* H5MF_AGGR_DBEUG */
+ /* Check if aggregator would get too large and should be absorbed into section */
+ if((aggr->size + sect->sect_info.size) >= aggr->alloc_size)
+ *shrink = H5MF_SHRINK_SECT_ABSORB_AGGR;
+ else
+ *shrink = H5MF_SHRINK_AGGR_ABSORB_SECT;
+
+ /* Indicate success */
+ HGOTO_DONE(TRUE)
+ } /* end if */
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MF_aggr_can_absorb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_aggr_absorb
+ *
+ * Purpose: Absorb a free space section into an aggregator block or
+ * vice versa.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Friday, February 1, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5MF_aggr_absorb(const H5F_t *f, H5F_blk_aggr_t *aggr, H5MF_free_section_t *sect,
+ hbool_t allow_sect_absorb)
+{
+ FUNC_ENTER_NOAPI_NOFUNC(H5MF_aggr_absorb)
+
+ /* Check args */
+ HDassert(f);
+ HDassert(aggr);
+ HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA);
+ HDassert(f->shared->feature_flags & aggr->feature_flag);
+ HDassert(sect);
+
+ /* Check if aggregator would get too large and should be absorbed into section */
+ if((aggr->size + sect->sect_info.size) >= aggr->alloc_size && allow_sect_absorb) {
+ /* Check if the section adjoins the beginning or end of the aggregator */
+ if(H5F_addr_eq((sect->sect_info.addr + sect->sect_info.size), aggr->addr)) {
+#ifdef H5MF_AGGR_DBEUG
+HDfprintf(stderr, "%s: aggr {%a, %Hu} adjoins front of section = {%a, %Hu}\n", "H5MF_aggr_absorb", aggr->addr, aggr->size, sect->sect_info.addr, sect->sect_info.size);
+#endif /* H5MF_AGGR_DBEUG */
+ /* Absorb aggregator onto end of section */
+ sect->sect_info.size += aggr->size;
+ } /* end if */
+ else {
+ /* Sanity check */
+ HDassert(H5F_addr_eq((aggr->addr + aggr->size), sect->sect_info.addr));
+
+#ifdef H5MF_AGGR_DBEUG
+HDfprintf(stderr, "%s: aggr {%a, %Hu} adjoins end of section = {%a, %Hu}\n", "H5MF_aggr_absorb", aggr->addr, aggr->size, sect->sect_info.addr, sect->sect_info.size);
+#endif /* H5MF_AGGR_DBEUG */
+ /* Absorb aggregator onto beginning of section */
+ sect->sect_info.addr -= aggr->size;
+ sect->sect_info.size += aggr->size;
+ } /* end if */
+
+ /* Reset aggregator */
+ aggr->tot_size = 0;
+ aggr->addr = 0;
+ aggr->size = 0;
+ } /* end if */
+ else {
+ /* Check if the section adjoins the beginning or end of the aggregator */
+ if(H5F_addr_eq((sect->sect_info.addr + sect->sect_info.size), aggr->addr)) {
+#ifdef H5MF_AGGR_DBEUG
+HDfprintf(stderr, "%s: section {%a, %Hu} adjoins front of aggr = {%a, %Hu}\n", "H5MF_aggr_absorb", sect->sect_info.addr, sect->sect_info.size, aggr->addr, aggr->size);
+#endif /* H5MF_AGGR_DBEUG */
+ /* Absorb section onto front of aggregator */
+ aggr->addr -= sect->sect_info.size;
+ aggr->size += sect->sect_info.size;
+
+ /* Sections absorbed onto front of aggregator count against the total
+ * amount of space aggregated together.
+ */
+ aggr->tot_size -= MIN(aggr->tot_size, sect->sect_info.size);
+ } /* end if */
+ else {
+ /* Sanity check */
+ HDassert(H5F_addr_eq((aggr->addr + aggr->size), sect->sect_info.addr));
+
+#ifdef H5MF_AGGR_DBEUG
+HDfprintf(stderr, "%s: section {%a, %Hu} adjoins end of aggr = {%a, %Hu}\n", "H5MF_aggr_absorb", sect->sect_info.addr, sect->sect_info.size, aggr->addr, aggr->size);
+#endif /* H5MF_AGGR_DBEUG */
+ /* Absorb section onto end of aggregator */
+ aggr->size += sect->sect_info.size;
+ } /* end if */
+ /* Sanity check */
+ HDassert(!allow_sect_absorb || (aggr->size < aggr->alloc_size));
+ } /* end else */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5MF_aggr_absorb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_aggr_query
+ *
+ * Purpose: Query a block aggregator's current address & size info
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, December 13, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5MF_aggr_query(const H5F_t *f, const H5F_blk_aggr_t *aggr, haddr_t *addr,
+ hsize_t *size)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5MF_aggr_query)
+
+ /* Check args */
+ HDassert(f);
+ HDassert(aggr);
+ HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA);
+
+ /* Check if this aggregator is active */
+ if(f->shared->feature_flags & aggr->feature_flag) {
+ *addr = aggr->addr;
+ *size = aggr->size;
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5MF_aggr_query() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_aggr_reset
+ *
+ * Purpose: Reset a block aggregator, returning any space back to file
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, December 13, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5MF_aggr_reset(H5F_t *f, hid_t dxpl_id, H5F_blk_aggr_t *aggr)
+{
+ H5FD_mem_t alloc_type; /* Type of file memory to work with */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5MF_aggr_reset, FAIL)
+
+ /* Check args */
+ HDassert(f);
+ HDassert(aggr);
+ HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA);
+
+ /* Set the type of memory in the file */
+ alloc_type = (aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA ? H5FD_MEM_DEFAULT : H5FD_MEM_DRAW); /* Type of file memory to work with */
+
+ /* Check if this aggregator is active */
+ if(f->shared->feature_flags & aggr->feature_flag) {
+ haddr_t tmp_addr; /* Temporary holder for aggregator address */
+ hsize_t tmp_size; /* Temporary holder for aggregator size */
+
+ /* Retain aggregator info */
+ tmp_addr = aggr->addr;
+ tmp_size = aggr->size;
+#ifdef H5MF_AGGR_DBEUG
+HDfprintf(stderr, "%s: tmp_addr = %a, tmp_size = %Hu\n", FUNC, tmp_addr, tmp_size);
+#endif /* H5MF_AGGR_DBEUG */
+
+ /* Reset aggregator block information */
+ aggr->tot_size = 0;
+ aggr->addr = 0;
+ aggr->size = 0;
+
+ /* Return the unused portion of the metadata block to the file */
+ if(tmp_size > 0)
+ if(H5FD_free(f->shared->lf, dxpl_id, alloc_type, tmp_addr, tmp_size) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "can't free space")
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MF_aggr_reset() */
+
diff --git a/src/H5MFdbg.c b/src/H5MFdbg.c
new file mode 100644
index 0000000..ca83b5a
--- /dev/null
+++ b/src/H5MFdbg.c
@@ -0,0 +1,217 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5MFdbg.c
+ * Jan 31 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: File memory management debugging functions.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+#define H5MF_PACKAGE /*suppress error about including H5MFpkg */
+#define H5MF_DEBUGGING /* Need access to file space debugging routines */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* File access */
+#include "H5MFpkg.h" /* File memory management */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+/* User data for free space section iterator callback */
+typedef struct {
+ H5FS_t *fspace; /* Free space manager */
+ FILE *stream; /* Stream for output */
+ int indent; /* Indention amount */
+ int fwidth; /* Field width amount */
+} H5MF_debug_iter_ud_t;
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_sects_debug_cb
+ *
+ * Purpose: Prints debugging info about a free space section for a file
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * January 31 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5MF_sects_debug_cb(const H5FS_section_info_t *_sect, void *_udata)
+{
+ const H5MF_free_section_t *sect = (const H5MF_free_section_t *)_sect; /* Section to dump info */
+ H5MF_debug_iter_ud_t *udata = (H5MF_debug_iter_ud_t *)_udata; /* User data for callbacks */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5MF_sects_debug_cb)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(sect);
+ HDassert(udata);
+
+ /* Print generic section information */
+ HDfprintf(udata->stream, "%*s%-*s %s\n", udata->indent, "", udata->fwidth,
+ "Section type:",
+ (sect->sect_info.type == H5MF_FSPACE_SECT_SIMPLE ? "simple" : "unknown"));
+ HDfprintf(udata->stream, "%*s%-*s %a\n", udata->indent, "", udata->fwidth,
+ "Section address:",
+ sect->sect_info.addr);
+ HDfprintf(udata->stream, "%*s%-*s %Hu\n", udata->indent, "", udata->fwidth,
+ "Section size:",
+ sect->sect_info.size);
+ HDfprintf(udata->stream, "%*s%-*s %Hu\n", udata->indent, "", udata->fwidth,
+ "End of section:",
+ (haddr_t)((sect->sect_info.addr + sect->sect_info.size) - 1));
+ HDfprintf(udata->stream, "%*s%-*s %s\n", udata->indent, "", udata->fwidth,
+ "Section state:",
+ (sect->sect_info.state == H5FS_SECT_LIVE ? "live" : "serialized"));
+
+ /* Dump section-specific debugging information */
+ if(H5FS_sect_debug(udata->fspace, _sect, udata->stream, udata->indent + 3, MAX(0, udata->fwidth - 3)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_BADITER, FAIL, "can't dump section's debugging info")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MF_sects_debug_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_sects_dump
+ *
+ * Purpose: Prints debugging info about free space sections for a file.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jan 31 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5MF_sects_dump(H5F_t *f, hid_t dxpl_id, FILE *stream)
+{
+ haddr_t eoa; /* End of allocated space in the file */
+ haddr_t ma_addr = HADDR_UNDEF; /* Base "metadata aggregator" address */
+ hsize_t ma_size = 0; /* Size of "metadata aggregator" */
+ haddr_t sda_addr = HADDR_UNDEF; /* Base "small data aggregator" address */
+ hsize_t sda_size = 0; /* Size of "small data aggregator" */
+ H5FD_mem_t type; /* Memory type for iteration */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5MF_sects_dump, FAIL)
+HDfprintf(stderr, "%s: Dumping file free space sections\n", FUNC);
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(stream);
+
+ /* Retrieve the 'eoa' for the file */
+ if(HADDR_UNDEF == (eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed")
+HDfprintf(stderr, "%s: eoa = %a\n", FUNC, eoa);
+
+ /* Retrieve metadata aggregator info, if available */
+ H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size);
+HDfprintf(stderr, "%s: ma_addr = %a, ma_size = %Hu, end of ma = %a\n", FUNC, ma_addr, ma_size, (haddr_t)((ma_addr + ma_size) - 1));
+
+ /* Retrieve 'small data' aggregator info, if available */
+ H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sda_addr, &sda_size);
+HDfprintf(stderr, "%s: sda_addr = %a, sda_size = %Hu, end of sda = %a\n", FUNC, sda_addr, sda_size, (haddr_t)((sda_addr + sda_size) - 1));
+
+ /* Iterate over all the free space types that have managers and dump each free list's space */
+ for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type)) {
+#ifdef QAK
+ /* Check if the free space for the file has been initialized */
+ if(!f->shared->fs_man[type])
+ if(H5MF_alloc_start(f, dxpl_id, type, FALSE) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space")
+#endif /* QAK */
+
+ /* If there is a free space manager for this type, iterate over them */
+ if(f->shared->fs_man[type]) {
+ H5MF_debug_iter_ud_t udata; /* User data for callbacks */
+
+ /* Prepare user data for section iteration callback */
+ udata.fspace = f->shared->fs_man[type];
+ udata.stream = stream;
+ udata.indent = 0;
+ udata.fwidth = 3;
+
+ /* Iterate over all the free space sections */
+ if(H5FS_sect_iterate(f, dxpl_id, f->shared->fs_man[type], H5MF_sects_debug_cb, &udata) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't iterate over heap's free space")
+ } /* end if */
+ } /* end for */
+
+done:
+HDfprintf(stderr, "%s: Done dumping file free space sections\n", FUNC);
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MF_sects_dump() */
+
diff --git a/src/H5MFpkg.h b/src/H5MFpkg.h
new file mode 100644
index 0000000..0e69fd0
--- /dev/null
+++ b/src/H5MFpkg.h
@@ -0,0 +1,175 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Programmer: Quincey Koziol <koziol@hdfgroup.org>
+ * Tuesday, January 8, 2008
+ *
+ * Purpose: This file contains declarations which are visible only within
+ * the H5MF package. Source files outside the H5MF package should
+ * include H5MFprivate.h instead.
+ */
+#ifndef H5MF_PACKAGE
+#error "Do not include this file outside the H5MF package!"
+#endif
+
+#ifndef _H5MFpkg_H
+#define _H5MFpkg_H
+
+/* Get package's private header */
+#include "H5MFprivate.h"
+
+/* Other private headers needed by this file */
+#include "H5FSprivate.h" /* File free space */
+
+
+/**************************/
+/* Package Private Macros */
+/**************************/
+
+/* Define this to display information about file allocations */
+/* #define H5MF_ALLOC_DEBUG */
+
+/* Define this to display more information about file allocations */
+/* #define H5MF_ALLOC_DEBUG_MORE */
+
+/* Define this to display more information about block aggregator actions */
+/* #define H5MF_AGGR_DEBUG */
+
+/* Define this to dump free space tracker contents after they've been modified */
+/* #define H5MF_ALLOC_DEBUG_DUMP */
+
+/* Free space section types for file */
+/* (values stored in free space data structures in file) */
+#define H5MF_FSPACE_SECT_SIMPLE 0 /* Section is a range of actual bytes in file */
+
+
+/****************************/
+/* Package Private Typedefs */
+/****************************/
+
+/* File free space section info */
+typedef struct H5MF_free_section_t {
+ H5FS_section_info_t sect_info; /* Free space section information (must be first in struct) */
+#ifdef NOT_YET
+ union {
+ struct {
+ H5HF_indirect_t *parent; /* Indirect block parent for free section's direct block */
+ unsigned par_entry; /* Entry of free section's direct block in parent indirect block */
+ } single;
+ struct {
+ struct H5HF_free_section_t *under; /* Pointer to indirect block underlying row section */
+ unsigned row; /* Row for range of blocks */
+ unsigned col; /* Column for range of blocks */
+ unsigned num_entries; /* Number of entries covered */
+
+ /* Fields that aren't stored */
+ hbool_t checked_out; /* Flag to indicate that a row section is temporarily out of the free space manager */
+ } row;
+ struct {
+ /* Holds either a pointer to an indirect block (if its "live") or
+ * the block offset of it's indirect block (if its "serialized")
+ * (This allows the indirect block that the section is within to
+ * be compared with other sections, whether it's serialized
+ * or not)
+ */
+ union {
+ H5HF_indirect_t *iblock; /* Indirect block for free section */
+ hsize_t iblock_off; /* Indirect block offset in "heap space" */
+ } u;
+ unsigned row; /* Row for range of blocks */
+ unsigned col; /* Column for range of blocks */
+ unsigned num_entries; /* Number of entries covered */
+
+ /* Fields that aren't stored */
+ struct H5HF_free_section_t *parent; /* Pointer to "parent" indirect section */
+ unsigned par_entry; /* Entry within parent indirect section */
+ hsize_t span_size; /* Size of space tracked, in "heap space" */
+ unsigned iblock_entries; /* Number of entries in indirect block where section is located */
+ unsigned rc; /* Reference count of outstanding row & child indirect sections */
+ unsigned dir_nrows; /* Number of direct rows in section */
+ struct H5HF_free_section_t **dir_rows; /* Array of pointers to outstanding row sections */
+ unsigned indir_nents; /* Number of indirect entries in section */
+ struct H5HF_free_section_t **indir_ents; /* Array of pointers to outstanding child indirect sections */
+ } indirect;
+ } u;
+#endif /* NOT_YET */
+} H5MF_free_section_t;
+
+/* Type of "container shrink" operation to perform */
+typedef enum {
+ H5MF_SHRINK_EOA, /* Section should shrink the EOA value */
+ H5MF_SHRINK_AGGR_ABSORB_SECT, /* Section should merge into the aggregator block */
+ H5MF_SHRINK_SECT_ABSORB_AGGR /* Aggregator block should merge into the section */
+} H5MF_shrink_type_t;
+
+/* User data for free space manager section callbacks */
+typedef struct H5MF_sect_ud_t {
+ /* Down */
+ H5F_t *f; /* Pointer to file to operate on */
+ 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 */
+
+ /* Up */
+ H5MF_shrink_type_t shrink; /* Type of shrink operation to perform */
+ H5F_blk_aggr_t *aggr; /* Aggregator block to operate on */
+} H5MF_sect_ud_t;
+
+
+/*****************************/
+/* Package Private Variables */
+/*****************************/
+
+/* H5MF single section inherits serializable properties from H5FS_section_class_t */
+H5_DLLVAR H5FS_section_class_t H5MF_FSPACE_SECT_CLS_SIMPLE[1];
+
+
+/******************************/
+/* Package Private Prototypes */
+/******************************/
+
+/* Allocator routines */
+H5_DLL herr_t H5MF_alloc_start(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type,
+ hbool_t may_create);
+H5_DLL herr_t H5MF_sects_dump(H5F_t *f, hid_t dxpl_id, FILE *stream);
+
+/* 'simple' section routines */
+H5_DLL H5MF_free_section_t *H5MF_sect_simple_new(haddr_t sect_off,
+ hsize_t sect_size);
+H5_DLL htri_t H5MF_sect_simple_can_shrink(const H5FS_section_info_t *_sect,
+ void *udata);
+H5_DLL herr_t H5MF_sect_simple_shrink(H5FS_section_info_t **_sect,
+ void *udata);
+H5_DLL herr_t H5MF_sect_simple_free(H5FS_section_info_t *sect);
+
+/* Block aggregator routines */
+H5_DLL haddr_t H5MF_aggr_alloc(H5F_t *f, hid_t dxpl_id, H5F_blk_aggr_t *aggr,
+ H5F_blk_aggr_t *other_aggr, H5FD_mem_t type, hsize_t size);
+H5_DLL htri_t H5MF_aggr_try_extend(const H5F_t *f, H5F_blk_aggr_t *aggr,
+ H5FD_mem_t type, haddr_t abs_blk_end, hsize_t extra_requested);
+H5_DLL htri_t H5MF_aggr_can_absorb(const H5F_t *f, const H5F_blk_aggr_t *aggr,
+ const H5MF_free_section_t *sect, H5MF_shrink_type_t *shrink);
+H5_DLL herr_t H5MF_aggr_absorb(const H5F_t *f, H5F_blk_aggr_t *aggr,
+ H5MF_free_section_t *sect, hbool_t allow_sect_absorb);
+H5_DLL herr_t H5MF_aggr_query(const H5F_t *f, const H5F_blk_aggr_t *aggr,
+ haddr_t *addr, hsize_t *size);
+
+/* Testing routines */
+#ifdef H5MF_TESTING
+#endif /* H5MF_TESTING */
+
+#endif /* _H5MFpkg_H */
+
diff --git a/src/H5MFprivate.h b/src/H5MFprivate.h
index b2e0126..0d1da8a 100644
--- a/src/H5MFprivate.h
+++ b/src/H5MFprivate.h
@@ -32,6 +32,10 @@
#include "H5Fprivate.h" /* File access */
#include "H5FDprivate.h" /* File Drivers */
+/**************************/
+/* Library Private Macros */
+/**************************/
+
/*
* Feature: Define H5MF_DEBUG on the compiler command line if you want to
* see diagnostics from this layer.
@@ -40,18 +44,44 @@
# undef H5MF_DEBUG
#endif
-/*
- * Library prototypes...
- */
+/****************************/
+/* Library Private Typedefs */
+/****************************/
+
+
+/*****************************/
+/* Library-private Variables */
+/*****************************/
+
+
+/***************************************/
+/* Library-private Function Prototypes */
+/***************************************/
+
+/* File space manager routines */
+H5_DLL herr_t H5MF_init_merge_flags(H5F_t *f);
+H5_DLL hssize_t H5MF_get_freespace(H5F_t *f, hid_t dxpl_id);
+H5_DLL herr_t H5MF_close(H5F_t *f, hid_t dxpl_id);
+
+/* File space allocation routines */
H5_DLL haddr_t H5MF_alloc(H5F_t *f, H5FD_mem_t type, hid_t dxpl_id, hsize_t size);
H5_DLL herr_t H5MF_xfree(H5F_t *f, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
hsize_t size);
-H5_DLL haddr_t H5MF_realloc(H5F_t *f, H5FD_mem_t type, hid_t dxpl_id, haddr_t old_addr,
- hsize_t old_size, hsize_t new_size);
-H5_DLL htri_t H5MF_can_extend(H5F_t *f, H5FD_mem_t type, haddr_t addr,
- hsize_t size, hsize_t extra_requested);
-H5_DLL herr_t H5MF_extend(H5F_t *f, H5FD_mem_t type, haddr_t addr, hsize_t size,
- hsize_t extra_requested);
+H5_DLL herr_t H5MF_try_extend(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type,
+ haddr_t addr, hsize_t size, hsize_t extra_requested);
+H5_DLL htri_t H5MF_try_shrink(H5F_t *f, H5FD_mem_t alloc_type, hid_t dxpl_id,
+ haddr_t addr, hsize_t size);
+
+/* 'block aggregator' routines */
+H5_DLL herr_t H5MF_aggr_reset(H5F_t *file, hid_t dxpl_id, H5F_blk_aggr_t *aggr);
+
+/* Debugging routines */
+#ifdef H5MF_DEBUGGING
+#ifdef NOT_YET
+H5_DLL herr_t H5MF_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr,
+ FILE *stream, int indent, int fwidth);
+#endif /* NOT_YET */
+#endif /* H5MF_DEBUGGING */
#endif /* end _H5MFprivate_H */
diff --git a/src/H5MFsection.c b/src/H5MFsection.c
new file mode 100644
index 0000000..b01590e
--- /dev/null
+++ b/src/H5MFsection.c
@@ -0,0 +1,526 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Programmer: Quincey Koziol <koziol@hdfgroup.org>
+ * Tuesday, January 8, 2008
+ *
+ * Purpose: Free space section callbacks for file.
+ *
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+#define H5MF_PACKAGE /*suppress error about including H5MFpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* File access */
+#include "H5MFpkg.h" /* File memory management */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+/* 'simple' section callbacks */
+static H5FS_section_info_t *H5MF_sect_simple_deserialize(const H5FS_section_class_t *cls,
+ hid_t dxpl_id, const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size,
+ unsigned *des_flags);
+static htri_t H5MF_sect_simple_can_merge(const H5FS_section_info_t *sect1,
+ const H5FS_section_info_t *sect2, void *udata);
+static herr_t H5MF_sect_simple_merge(H5FS_section_info_t *sect1,
+ H5FS_section_info_t *sect2, void *udata);
+static herr_t H5MF_sect_simple_valid(const H5FS_section_class_t *cls,
+ const H5FS_section_info_t *sect);
+static H5FS_section_info_t *H5MF_sect_simple_split(H5FS_section_info_t *sect,
+ hsize_t frag_size);
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+/* Class info for "simple" free space sections */
+H5FS_section_class_t H5MF_FSPACE_SECT_CLS_SIMPLE[1] = {{
+ /* Class variables */
+ H5MF_FSPACE_SECT_SIMPLE, /* Section type */
+ 0, /* Extra serialized size */
+ H5FS_CLS_MERGE_SYM | H5FS_CLS_ADJUST_OK, /* Class flags */
+ NULL, /* Class private info */
+
+ /* Class methods */
+ NULL, /* Initialize section class */
+ NULL, /* Terminate section class */
+
+ /* Object methods */
+ NULL, /* Add section */
+ NULL, /* Serialize section */
+ H5MF_sect_simple_deserialize, /* Deserialize section */
+ H5MF_sect_simple_can_merge, /* Can sections merge? */
+ H5MF_sect_simple_merge, /* Merge sections */
+ H5MF_sect_simple_can_shrink, /* Can section shrink container?*/
+ H5MF_sect_simple_shrink, /* Shrink container w/section */
+ H5MF_sect_simple_free, /* Free section */
+ H5MF_sect_simple_valid, /* Check validity of section */
+ H5MF_sect_simple_split, /* Split section node for alignment */
+ NULL, /* Dump debugging for section */
+}};
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Declare a free list to manage the H5MF_free_section_t struct */
+H5FL_DEFINE(H5MF_free_section_t);
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_sect_simple_new
+ *
+ * Purpose: Create a new 'simple' section and return it to the caller
+ *
+ * Return: Pointer to new section on success/NULL on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * January 8 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+H5MF_free_section_t *
+H5MF_sect_simple_new(haddr_t sect_off, hsize_t sect_size)
+{
+ H5MF_free_section_t *sect = NULL; /* 'Simple' free space section to add */
+ H5MF_free_section_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5MF_sect_simple_new)
+
+ /* Check arguments. */
+ HDassert(sect_size);
+
+ /* Create free space section node */
+ if(NULL == (sect = H5FL_MALLOC(H5MF_free_section_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for direct block free list section")
+
+ /* Set the information passed in */
+ sect->sect_info.addr = sect_off;
+ sect->sect_info.size = sect_size;
+
+ /* Set the section's class & state */
+ sect->sect_info.type = H5MF_FSPACE_SECT_SIMPLE;
+ sect->sect_info.state = H5FS_SECT_LIVE;
+
+ /* Set return value */
+ ret_value = sect;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MF_sect_simple_new() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_sect_simple_deserialize
+ *
+ * Purpose: Deserialize a buffer into a "live" single section
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, January 8, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5FS_section_info_t *
+H5MF_sect_simple_deserialize(const H5FS_section_class_t UNUSED *cls,
+ hid_t UNUSED dxpl_id, const uint8_t UNUSED *buf, haddr_t sect_addr,
+ hsize_t sect_size, unsigned UNUSED *des_flags)
+{
+ H5MF_free_section_t *sect; /* New section */
+ H5FS_section_info_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5MF_sect_simple_deserialize)
+
+ /* Check arguments. */
+ HDassert(H5F_addr_defined(sect_addr));
+ HDassert(sect_size);
+
+ /* Create free space section for block */
+ if(NULL == (sect = H5MF_sect_simple_new(sect_addr, sect_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, NULL, "can't initialize free space section")
+
+ /* Set return value */
+ ret_value = (H5FS_section_info_t *)sect;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5MF_sect_simple_deserialize() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_sect_simple_can_merge
+ *
+ * Purpose: Can two sections of this type merge?
+ *
+ * Note: Second section must be "after" first section
+ *
+ * Return: Success: non-negative (TRUE/FALSE)
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, January 8, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static htri_t
+H5MF_sect_simple_can_merge(const H5FS_section_info_t *_sect1,
+ const H5FS_section_info_t *_sect2, void UNUSED *_udata)
+{
+ const H5MF_free_section_t *sect1 = (const H5MF_free_section_t *)_sect1; /* File free section */
+ const H5MF_free_section_t *sect2 = (const H5MF_free_section_t *)_sect2; /* File free section */
+ htri_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5MF_sect_simple_can_merge)
+
+ /* Check arguments. */
+ HDassert(sect1);
+ HDassert(sect2);
+ HDassert(sect1->sect_info.type == sect2->sect_info.type); /* Checks "MERGE_SYM" flag */
+ HDassert(H5F_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr));
+
+ /* Check if second section adjoins first section */
+ ret_value = H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5MF_sect_simple_can_merge() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_sect_simple_merge
+ *
+ * Purpose: Merge two sections of this type
+ *
+ * Note: Second section always merges into first node
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, January 8, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5MF_sect_simple_merge(H5FS_section_info_t *_sect1, H5FS_section_info_t *_sect2,
+ void UNUSED *_udata)
+{
+ H5MF_free_section_t *sect1 = (H5MF_free_section_t *)_sect1; /* File free section */
+ H5MF_free_section_t *sect2 = (H5MF_free_section_t *)_sect2; /* File free section */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5MF_sect_simple_merge)
+
+ /* Check arguments. */
+ HDassert(sect1);
+ HDassert(sect1->sect_info.type == H5MF_FSPACE_SECT_SIMPLE);
+ HDassert(sect2);
+ HDassert(sect2->sect_info.type == H5MF_FSPACE_SECT_SIMPLE);
+ HDassert(H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr));
+
+ /* Add second section's size to first section */
+ sect1->sect_info.size += sect2->sect_info.size;
+
+ /* Get rid of second section */
+ if(H5MF_sect_simple_free((H5FS_section_info_t *)sect2) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free section node")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5MF_sect_simple_merge() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_sect_simple_can_shrink
+ *
+ * Purpose: Can this section shrink the container?
+ *
+ * Return: Success: non-negative (TRUE/FALSE)
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, January 8, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5MF_sect_simple_can_shrink(const H5FS_section_info_t *_sect, void *_udata)
+{
+ const H5MF_free_section_t *sect = (const H5MF_free_section_t *)_sect; /* File free section */
+ H5MF_sect_ud_t *udata = (H5MF_sect_ud_t *)_udata; /* User data for callback */
+ haddr_t eoa; /* End of address space in the file */
+ haddr_t end; /* End of section to extend */
+ htri_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5MF_sect_simple_can_shrink)
+
+ /* Check arguments. */
+ HDassert(sect);
+ HDassert(udata);
+ HDassert(udata->f);
+
+ /* Retrieve the end of the file's address space */
+ if(HADDR_UNDEF == (eoa = H5FD_get_eoa(udata->f->shared->lf, H5FD_MEM_DEFAULT)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed")
+
+ /* Compute address of end of section to check */
+ end = sect->sect_info.addr + sect->sect_info.size;
+
+ /* Check if the section is exactly at the end of the allocated space in the file */
+ if(H5F_addr_eq(end, eoa)) {
+ /* Set the shrinking type */
+ udata->shrink = H5MF_SHRINK_EOA;
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: section {%a, %Hu}, shrinks file, eoa = %a\n", FUNC, sect->sect_info.addr, sect->sect_info.size, eoa);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+
+ /* Indicate shrinking can occur */
+ HGOTO_DONE(TRUE)
+ } /* end if */
+ else {
+ /* 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 */
+
+ /* See if section can absorb the aggregator & vice versa */
+ if((status = H5MF_aggr_can_absorb(udata->f, &(udata->f->shared->meta_aggr), sect, &(udata->shrink))) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTMERGE, FAIL, "error merging section with aggregation block")
+ else if(status > 0) {
+ /* Set the aggregator to operate on */
+ udata->aggr = &(udata->f->shared->meta_aggr);
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: section {%a, %Hu}, adjoins metadata aggregator\n", FUNC, sect->sect_info.addr, sect->sect_info.size);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+
+ /* Indicate shrinking can occur */
+ HGOTO_DONE(TRUE)
+ } /* end if */
+ } /* end if */
+
+ /* Check if this section is allowed to merge with small 'raw' aggregation block */
+ if(udata->f->shared->fs_aggr_merge[udata->alloc_type] & H5F_FS_MERGE_RAWDATA) {
+ htri_t status; /* Status from aggregator adjoin */
+
+ /* See if section can absorb the aggregator & vice versa */
+ if((status = H5MF_aggr_can_absorb(udata->f, &(udata->f->shared->sdata_aggr), sect, &(udata->shrink))) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTMERGE, FAIL, "error merging section with aggregation block")
+ else if(status > 0) {
+ /* Set the aggregator to operate on */
+ udata->aggr = &(udata->f->shared->sdata_aggr);
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: section {%a, %Hu}, adjoins small data aggregator\n", FUNC, sect->sect_info.addr, sect->sect_info.size);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+
+ /* Indicate shrinking can occur */
+ HGOTO_DONE(TRUE)
+ } /* end if */
+ } /* end if */
+ } /* end else */
+
+ /* Set return value */
+ ret_value = FALSE;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5MF_sect_simple_can_shrink() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_sect_simple_shrink
+ *
+ * Purpose: Shrink container with section
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, January 8, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5MF_sect_simple_shrink(H5FS_section_info_t **_sect, void *_udata)
+{
+ H5MF_free_section_t **sect = (H5MF_free_section_t **)_sect; /* File free section */
+ H5MF_sect_ud_t *udata = (H5MF_sect_ud_t *)_udata; /* User data for callback */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5MF_sect_simple_shrink)
+
+ /* Check arguments. */
+ HDassert(sect);
+ HDassert(udata);
+ HDassert(udata->f);
+
+ /* Check for shrinking file */
+ if(H5MF_SHRINK_EOA == udata->shrink) {
+ /* Release section's space at EOA with file driver */
+ if(H5FD_free(udata->f->shared->lf, udata->dxpl_id, H5FD_MEM_DEFAULT, (*sect)->sect_info.addr, (*sect)->sect_info.size) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "driver free request failed")
+ } /* end if */
+ else {
+ /* Sanity check */
+ HDassert(udata->aggr);
+
+ /* Absorb the section into the aggregator or vice versa */
+ if(H5MF_aggr_absorb(udata->f, udata->aggr, *sect, udata->allow_sect_absorb) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTMERGE, FAIL, "can't absorb section into aggregator or vice versa")
+ } /* end else */
+
+ /* Check for freeing section */
+ if(udata->shrink != H5MF_SHRINK_SECT_ABSORB_AGGR) {
+ /* Free section */
+ if(H5MF_sect_simple_free((H5FS_section_info_t *)*sect) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free simple section node")
+
+ /* Mark section as freed, for free space manager */
+ *sect = NULL;
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5MF_sect_simple_shrink() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_sect_simple_free
+ *
+ * Purpose: Free a 'single' section node
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, January 8, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5MF_sect_simple_free(H5FS_section_info_t *_sect)
+{
+ H5MF_free_section_t *sect = (H5MF_free_section_t *)_sect; /* File free section */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5MF_sect_simple_free)
+
+ /* Check arguments. */
+ HDassert(sect);
+
+ /* Release the section */
+ H5FL_FREE(H5MF_free_section_t, sect);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5MF_sect_simple_free() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_sect_simple_valid
+ *
+ * Purpose: Check the validity of a section
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, January 8, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5MF_sect_simple_valid(const H5FS_section_class_t UNUSED *cls,
+ const H5FS_section_info_t *_sect)
+{
+ const H5MF_free_section_t *sect = (const H5MF_free_section_t *)_sect; /* File free section */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5MF_sect_simple_valid)
+
+ /* Check arguments. */
+ HDassert(sect);
+
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5MF_sect_simple_valid() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_sect_simple_split
+ *
+ * Purpose: Split SECT into 2 sections: fragment for alignment & the aligned section
+ * SECT's addr and size are updated to point to the aligned section
+ *
+ * Return: Success: the fragment for aligning sect
+ * Failure: null
+ *
+ * Programmer: Vailin Choi, July 29, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5FS_section_info_t *
+H5MF_sect_simple_split(H5FS_section_info_t *sect, hsize_t frag_size)
+{
+ H5MF_free_section_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5MF_sect_simple_split)
+
+ /* Allocate space for new section */
+ if(NULL == (ret_value = H5MF_sect_simple_new(sect->addr, frag_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, NULL, "can't initialize free space section")
+
+ /* Set new section's info */
+ sect->addr += frag_size;
+ sect->size -= frag_size;
+
+done:
+ FUNC_LEAVE_NOAPI((H5FS_section_info_t *)ret_value)
+} /* end H5MF_sect_simple_split() */
+
+
diff --git a/src/H5O.c b/src/H5O.c
index a706f86..bf12c3f 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -1062,9 +1062,11 @@ H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, hid_t ocpl_id,
/* check args */
HDassert(f);
+ HDassert(f->intent & H5F_ACC_RDWR);
HDassert(loc);
HDassert(TRUE == H5P_isa_class(ocpl_id, H5P_OBJECT_CREATE));
+
/* Make certain we allocate at least a reasonable size for the object header */
size_hint = H5O_ALIGN_F(f, MAX(H5O_MIN_SIZE, size_hint));
@@ -1448,7 +1450,7 @@ H5O_link(const H5O_loc_t *loc, int adjust, hid_t dxpl_id)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file")
/* Mark the object header as deleted */
- oh_flags = H5C__DELETED_FLAG;
+ oh_flags = H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
} /* end else */
} /* end if */
} else {
@@ -1833,7 +1835,7 @@ H5O_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file")
done:
- if(oh && H5AC_unprotect(f, dxpl_id, H5AC_OHDR, addr, oh, H5AC__DIRTIED_FLAG | H5C__DELETED_FLAG) < 0)
+ if(oh && H5AC_unprotect(f, dxpl_id, H5AC_OHDR, addr, oh, H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
@@ -1879,10 +1881,6 @@ H5O_delete_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message")
} /* end for */
- /* Free main (first) object header "chunk" */
- if(H5MF_xfree(f, H5FD_MEM_OHDR, dxpl_id, oh->chunk[0].addr, (hsize_t)oh->chunk[0].size) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free object header")
-
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_delete_oh() */
diff --git a/src/H5Oalloc.c b/src/H5Oalloc.c
index f9e06ad..3234d82 100644
--- a/src/H5Oalloc.c
+++ b/src/H5Oalloc.c
@@ -64,8 +64,8 @@ static herr_t H5O_eliminate_gap(H5O_t *oh, H5O_mesg_t *mesg,
uint8_t *new_gap_loc, size_t new_gap_size);
static herr_t H5O_alloc_null(H5O_t *oh, unsigned null_idx,
const H5O_msg_class_t *new_type, void *new_native, size_t new_size);
-static htri_t H5O_alloc_extend_chunk(H5F_t *f, H5O_t *oh, unsigned chunkno,
- size_t size, unsigned * msg_idx);
+static htri_t H5O_alloc_extend_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
+ unsigned chunkno, size_t size, unsigned * msg_idx);
static unsigned H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
size_t size);
static htri_t H5O_move_msgs_forward(H5O_t *oh);
@@ -457,6 +457,7 @@ done:
*/
static htri_t
H5O_alloc_extend_chunk(H5F_t *f,
+ hid_t dxpl_id,
H5O_t *oh,
unsigned chunkno,
size_t size,
@@ -466,7 +467,7 @@ H5O_alloc_extend_chunk(H5F_t *f,
size_t aligned_size = H5O_ALIGN_OH(oh, size);
uint8_t *old_image; /* Old address of chunk's image in memory */
size_t old_size; /* Old size of chunk */
- htri_t tri_result; /* Result from checking if chunk can be extended */
+ htri_t extended; /* If chunk can be extended */
int extend_msg = -1;/* Index of null message to extend */
uint8_t new_size_flags = 0; /* New chunk #0 size flags */
hbool_t adjust_size_flags = FALSE; /* Whether to adjust the chunk #0 size flags */
@@ -534,16 +535,12 @@ H5O_alloc_extend_chunk(H5F_t *f,
} /* end if */
/* Determine whether the chunk can be extended */
- tri_result = H5MF_can_extend(f, H5FD_MEM_OHDR, oh->chunk[chunkno].addr,
+ extended = H5MF_try_extend(f, dxpl_id, H5FD_MEM_OHDR, oh->chunk[chunkno].addr,
(hsize_t)(oh->chunk[chunkno].size), (hsize_t)(delta + extra_prfx_size));
- if(tri_result == FALSE) /* can't extend -- we are done */
+ if(extended < 0) /* error */
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTEXTEND, FAIL, "can't tell if we can extend chunk")
+ else if(extended == FALSE) /* can't extend -- we are done */
HGOTO_DONE(FALSE)
- else if(tri_result < 0) /* error */
- HGOTO_ERROR(H5E_RESOURCE, H5E_SYSTEM, FAIL, "can't tell if we can extend chunk")
-
- /* If we get this far, we should be able to extend the chunk */
- if(H5MF_extend(f, H5FD_MEM_OHDR, oh->chunk[chunkno].addr, (hsize_t)(oh->chunk[chunkno].size), (hsize_t)(delta + extra_prfx_size)) < 0 )
- HGOTO_ERROR(H5E_RESOURCE, H5E_SYSTEM, FAIL, "can't extend chunk")
/* Adjust object header prefix flags */
if(adjust_size_flags) {
@@ -994,13 +991,13 @@ H5O_alloc(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_msg_class_t *type,
HDassert(H5F_addr_defined(oh->chunk[chunkno].addr));
- tri_result = H5O_alloc_extend_chunk(f, oh, chunkno, raw_size, &idx);
+ tri_result = H5O_alloc_extend_chunk(f, dxpl_id, oh, chunkno, raw_size, &idx);
if(tri_result == TRUE)
break;
else if(tri_result == FALSE)
idx = UFAIL;
else
- HGOTO_ERROR(H5E_OHDR, H5E_SYSTEM, UFAIL, "H5O_alloc_extend_chunk failed unexpectedly")
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTEXTEND, UFAIL, "H5O_alloc_extend_chunk failed unexpectedly")
} /* end for */
/* If idx is still UFAIL, we were not able to extend a chunk,
diff --git a/src/H5Ocache.c b/src/H5Ocache.c
index 35b4e07..c50f557 100644
--- a/src/H5Ocache.c
+++ b/src/H5Ocache.c
@@ -37,6 +37,7 @@
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free lists */
+#include "H5MFprivate.h" /* File memory management */
#include "H5Opkg.h" /* Object headers */
@@ -130,8 +131,7 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
unsigned merged_null_msgs = 0; /* Number of null messages merged together */
haddr_t chunk_addr; /* Address of first chunk */
size_t chunk_size; /* Size of first chunk */
- haddr_t abs_eoa; /* Absolute end of file address */
- haddr_t rel_eoa; /* Relative end of file address */
+ haddr_t eoa; /* Relative end of file address */
H5O_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5O_load, NULL)
@@ -143,14 +143,11 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
HDassert(!_udata2);
/* Make certain we don't speculatively read off the end of the file */
- if(HADDR_UNDEF == (abs_eoa = H5F_get_eoa(f)))
+ if(HADDR_UNDEF == (eoa = H5F_get_eoa(f, H5FD_MEM_OHDR)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to determine file size")
- /* Adjust absolute EOA address to relative EOA address */
- rel_eoa = abs_eoa - H5F_get_base_addr(f);
-
/* Compute the size of the speculative object header buffer */
- H5_ASSIGN_OVERFLOW(spec_read_size, MIN(rel_eoa - addr, H5O_SPEC_READ_SIZE), /* From: */ hsize_t, /* To: */ size_t);
+ H5_ASSIGN_OVERFLOW(spec_read_size, MIN(eoa - addr, H5O_SPEC_READ_SIZE), /* From: */ hsize_t, /* To: */ size_t);
/* Attempt to speculatively read both object header prefix and first chunk */
if(H5F_block_read(f, H5FD_MEM_OHDR, addr, spec_read_size, dxpl_id, read_buf) < 0)
@@ -415,7 +412,7 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
#endif /* NDEBUG */
/* Check for combining two adjacent 'null' messages */
- if((H5F_get_intent(f) & H5F_ACC_RDWR) &&
+ if((H5F_INTENT(f) & H5F_ACC_RDWR) &&
H5O_NULL_ID == id && oh->nmesgs > 0 &&
H5O_NULL_ID == oh->mesg[oh->nmesgs - 1].type->id &&
oh->mesg[oh->nmesgs - 1].chunkno == chunkno) {
@@ -468,7 +465,7 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
/* Check for "mark if unknown" message flag, etc. */
else if((flags & H5O_MSG_FLAG_MARK_IF_UNKNOWN) &&
!(flags & H5O_MSG_FLAG_WAS_UNKNOWN) &&
- (H5F_get_intent(f) & H5F_ACC_RDWR)) {
+ (H5F_INTENT(f) & H5F_ACC_RDWR)) {
/* Mark the message as "unknown" */
/* This is a bit aggressive, since the application may
@@ -838,20 +835,37 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5O_dest(H5F_t UNUSED *f, H5O_t *oh)
+H5O_dest(H5F_t *f, H5O_t *oh)
{
unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_dest)
+ FUNC_ENTER_NOAPI_NOINIT(H5O_dest)
+#ifdef QAK
+HDfprintf(stderr, "%s: oh->cache_info.addr = %a\n", FUNC, oh->cache_info.addr);
+HDfprintf(stderr, "%s: oh->cache_info.free_file_space_on_destroy = %t\n", FUNC, oh->cache_info.free_file_space_on_destroy);
+#endif /* QAK */
/* check args */
HDassert(oh);
/* Verify that node is clean */
- HDassert(oh->cache_info.is_dirty == FALSE);
+ HDassert(!oh->cache_info.is_dirty);
+
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!oh->cache_info.free_file_space_on_destroy || H5F_addr_defined(oh->cache_info.addr));
/* destroy chunks */
if(oh->chunk) {
+ /* Check for releasing file space for object header */
+ if(oh->cache_info.free_file_space_on_destroy) {
+ /* Free main (first) object header "chunk" */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_OHDR, H5AC_dxpl_id, oh->chunk[0].addr, (hsize_t)oh->chunk[0].size) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free object header")
+ } /* end if */
+
+ /* Release buffer for each chunk */
for(u = 0; u < oh->nchunks; u++) {
/* Verify that chunk is clean */
HDassert(oh->chunk[u].dirty == 0);
@@ -859,6 +873,7 @@ H5O_dest(H5F_t UNUSED *f, H5O_t *oh)
oh->chunk[u].image = H5FL_BLK_FREE(chunk_image, oh->chunk[u].image);
} /* end for */
+ /* Release array of chunk info */
oh->chunk = (H5O_chunk_t *)H5FL_SEQ_FREE(H5O_chunk_t, oh->chunk);
} /* end if */
@@ -877,7 +892,8 @@ H5O_dest(H5F_t UNUSED *f, H5O_t *oh)
/* destroy object header */
(void)H5FL_FREE(H5O_t, oh);
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_dest() */
diff --git a/src/H5Omessage.c b/src/H5Omessage.c
index bfe40f8..1682117 100644
--- a/src/H5Omessage.c
+++ b/src/H5Omessage.c
@@ -879,7 +879,7 @@ H5O_msg_count_real(const H5O_t *oh, const H5O_msg_class_t *type)
*-------------------------------------------------------------------------
*/
htri_t
-H5O_msg_exists(H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id)
+H5O_msg_exists(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id)
{
H5O_t *oh = NULL; /* Object header for location */
htri_t ret_value; /* Return value */
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index 09b9b02..f65b15d 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -580,7 +580,7 @@ H5_DLL herr_t H5O_msg_reset(unsigned type_id, void *native);
H5_DLL void *H5O_msg_free(unsigned type_id, void *mesg);
H5_DLL void *H5O_msg_copy(unsigned type_id, const void *mesg, void *dst);
H5_DLL int H5O_msg_count(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id);
-H5_DLL htri_t H5O_msg_exists(H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id);
+H5_DLL htri_t H5O_msg_exists(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id);
H5_DLL herr_t H5O_msg_remove(const H5O_loc_t *loc, unsigned type_id, int sequence,
hbool_t adj_link, hid_t dxpl_id);
H5_DLL herr_t H5O_msg_remove_op(const H5O_loc_t *loc, unsigned type_id, int sequence,
diff --git a/src/H5Plapl.c b/src/H5Plapl.c
index 2b16be2..a572df3 100644
--- a/src/H5Plapl.c
+++ b/src/H5Plapl.c
@@ -563,7 +563,7 @@ H5Pset_elink_fapl(hid_t lapl_id, hid_t fapl_id)
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Pset_elink_fapl, FAIL)
- H5TRACE2("e", "i*s", lapl_id, fapl_id);
+ H5TRACE2("e", "ii", lapl_id, fapl_id);
/* Check arguments */
if(NULL == (plist = H5P_object_verify(lapl_id, H5P_LINK_ACCESS)))
diff --git a/src/H5SL.c b/src/H5SL.c
index ac1296c..fe810d1 100644
--- a/src/H5SL.c
+++ b/src/H5SL.c
@@ -1290,6 +1290,187 @@ done:
/*--------------------------------------------------------------------------
NAME
+ H5SL_below
+ PURPOSE
+ Search for _node_ in a skip list whose object is less than or equal to 'key'
+ USAGE
+ H5SL_node_t *H5SL_below(slist, key)
+ H5SL_t *slist; IN/OUT: Pointer to skip list
+ void *key; IN: Key for item to search for
+
+ RETURNS
+ Returns pointer to _node_ who key is less than or equal to 'key' on success,
+ NULL on failure
+ DESCRIPTION
+ Search for a node with an object in a skip list, according to it's key,
+ returning the node itself (for an exact match), or the node with the next
+ highest key that is less than 'key'
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+H5SL_node_t *
+H5SL_below(H5SL_t *slist, const void *key)
+{
+ H5SL_node_t *x; /* Current node to examine */
+ uint32_t hashval = 0; /* Hash value for key */
+ H5SL_node_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_below)
+
+ /* Check args */
+ HDassert(slist);
+ HDassert(key);
+
+ /* Check internal consistency */
+ /* (Pre-condition) */
+
+ /* Insert item into skip list */
+
+ /* Work through the forward pointers for a node, finding the node at each
+ * level that is before the location to insert
+ */
+ x = slist->header;
+ switch(slist->type) {
+ case H5SL_TYPE_INT:
+ H5SL_FIND(SCALAR, slist, x, -, const int, key, -)
+ break;
+
+ case H5SL_TYPE_HADDR:
+ H5SL_FIND(SCALAR, slist, x, -, const haddr_t, key, -)
+ break;
+
+ case H5SL_TYPE_STR:
+ H5SL_FIND(STRING, slist, x, -, char *, key, hashval)
+ break;
+
+ case H5SL_TYPE_HSIZE:
+ H5SL_FIND(SCALAR, slist, x, -, const hsize_t, key, -)
+ break;
+
+ case H5SL_TYPE_UNSIGNED:
+ H5SL_FIND(SCALAR, slist, x, -, const unsigned, key, -)
+ break;
+
+ case H5SL_TYPE_SIZE:
+ H5SL_FIND(SCALAR, slist, x, -, const size_t, key, -)
+ break;
+
+ case H5SL_TYPE_OBJ:
+ H5SL_FIND(OBJ, slist, x, -, const H5_obj_t, key, -)
+ break;
+ } /* end switch */
+
+ /* An exact match for 'key' must not have been found in list, if we get here */
+ /* Check for a node with a key that is less than the given 'key' */
+ if(NULL == x) {
+ /* Check for walking off the list */
+ if(slist->last != slist->header)
+ ret_value = slist->last;
+ else
+ ret_value = NULL;
+ } /* end if */
+ else {
+ if(x->backward != slist->header)
+ ret_value = x->backward;
+ else
+ ret_value = NULL;
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5SL_below() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5SL_above
+ PURPOSE
+ Search for _node_ in a skip list whose object is greater than or equal to 'key'
+ USAGE
+ H5SL_node_t *H5SL_above(slist, key)
+ H5SL_t *slist; IN/OUT: Pointer to skip list
+ void *key; IN: Key for item to search for
+
+ RETURNS
+ Returns pointer to _node_ with object that has a key is greater than or
+ equal to 'key' on success, NULL on failure
+ DESCRIPTION
+ Search for a node with an object in a skip list, according to it's key,
+ returning the node itself (for an exact match), or the node with the next
+ lowest key that is greater than 'key'
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+H5SL_node_t *
+H5SL_above(H5SL_t *slist, const void *key)
+{
+ H5SL_node_t *x; /* Current node to examine */
+ uint32_t hashval = 0; /* Hash value for key */
+ H5SL_node_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_above)
+
+ /* Check args */
+ HDassert(slist);
+ HDassert(key);
+
+ /* Check internal consistency */
+ /* (Pre-condition) */
+
+ /* Insert item into skip list */
+
+ /* Work through the forward pointers for a node, finding the node at each
+ * level that is before the location to insert
+ */
+ x = slist->header;
+ switch(slist->type) {
+ case H5SL_TYPE_INT:
+ H5SL_FIND(SCALAR, slist, x, -, const int, key, -)
+ break;
+
+ case H5SL_TYPE_HADDR:
+ H5SL_FIND(SCALAR, slist, x, -, const haddr_t, key, -)
+ break;
+
+ case H5SL_TYPE_STR:
+ H5SL_FIND(STRING, slist, x, -, char *, key, hashval)
+ break;
+
+ case H5SL_TYPE_HSIZE:
+ H5SL_FIND(SCALAR, slist, x, -, const hsize_t, key, -)
+ break;
+
+ case H5SL_TYPE_UNSIGNED:
+ H5SL_FIND(SCALAR, slist, x, -, const unsigned, key, -)
+ break;
+
+ case H5SL_TYPE_SIZE:
+ H5SL_FIND(SCALAR, slist, x, -, const size_t, key, -)
+ break;
+
+ case H5SL_TYPE_OBJ:
+ H5SL_FIND(OBJ, slist, x, -, const H5_obj_t, key, -)
+ break;
+ } /* end switch */
+
+ /* An exact match for 'key' must not have been found in list, if we get here */
+ /* ('x' must be the next node with a key greater than the 'key', or NULL) */
+ if(x)
+ ret_value = x;
+ else
+ ret_value = NULL;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5SL_above() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5SL_first
PURPOSE
Gets a pointer to the first node in a skip list
diff --git a/src/H5SLprivate.h b/src/H5SLprivate.h
index 9f73893..27bb4d1 100644
--- a/src/H5SLprivate.h
+++ b/src/H5SLprivate.h
@@ -72,6 +72,8 @@ H5_DLL void *H5SL_search(H5SL_t *slist, const void *key);
H5_DLL void *H5SL_less(H5SL_t *slist, const void *key);
H5_DLL void *H5SL_greater(H5SL_t *slist, const void *key);
H5_DLL H5SL_node_t *H5SL_find(H5SL_t *slist, const void *key);
+H5_DLL H5SL_node_t *H5SL_below(H5SL_t *slist, const void *key);
+H5_DLL H5SL_node_t *H5SL_above(H5SL_t *slist, const void *key);
H5_DLL H5SL_node_t *H5SL_first(H5SL_t *slist);
H5_DLL H5SL_node_t *H5SL_next(H5SL_node_t *slist_node);
H5_DLL H5SL_node_t *H5SL_prev(H5SL_node_t *slist_node);
diff --git a/src/H5SM.c b/src/H5SM.c
index 4de5810..f782e68 100755
--- a/src/H5SM.c
+++ b/src/H5SM.c
@@ -529,23 +529,31 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5SM_delete_index(H5F_t *f, H5SM_index_header_t *header, hid_t dxpl_id, hbool_t delete_heap)
+H5SM_delete_index(H5F_t *f, H5SM_index_header_t *header, hid_t dxpl_id,
+ hbool_t delete_heap)
{
- hsize_t list_size; /* Size of list on disk */
- herr_t ret_value = SUCCEED;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5SM_delete_index)
/* Determine whether index is a list or a B-tree. */
if(header->index_type == H5SM_LIST) {
- /* Eject entry from cache */
- if(H5AC_expunge_entry(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "unable to remove list index from cache")
-
- /* Free the file space used */
- list_size = H5SM_LIST_SIZE(f, header->list_max);
- if(H5MF_xfree(f, H5FD_MEM_SOHM_INDEX, dxpl_id, header->index_addr, list_size) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to free shared message list")
+ unsigned index_status = 0; /* Index list's status in the metadata cache */
+
+ /* Check the index list's status in the metadata cache */
+ if(H5AC_get_entry_status(f, header->index_addr, &index_status) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to check metadata cache status for direct block")
+
+ /* If the index list is in the cache, expunge it now */
+ if(index_status & H5AC_ES__IN_CACHE) {
+ /* Sanity checks on index list */
+ HDassert(!(index_status & H5AC_ES__IS_PINNED));
+ HDassert(!(index_status & H5AC_ES__IS_PROTECTED));
+
+ /* Evict the index list from the metadata cache */
+ if(H5AC_expunge_entry(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, H5AC__FREE_FILE_SPACE_FLAG) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "unable to remove list index from cache")
+ } /* end if */
} /* end if */
else {
HDassert(header->index_type == H5SM_BTREE);
@@ -727,7 +735,7 @@ H5SM_convert_list_to_btree(H5F_t *f, H5SM_index_header_t *header,
} /* end for */
/* Unprotect list in cache and release heap */
- if(H5AC_unprotect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, list, H5AC__DELETED_FLAG) < 0)
+ if(H5AC_unprotect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, list, H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "unable to release SOHM list")
*_list = list = NULL;
@@ -1691,7 +1699,7 @@ H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
if(header->num_messages == 0) {
/* Unprotect cache and release heap */
- if(list && H5AC_unprotect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, list, H5AC__DELETED_FLAG) < 0)
+ if(list && H5AC_unprotect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, list, H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "unable to release SOHM list")
list = NULL;
@@ -2064,11 +2072,15 @@ H5SM_get_refcount(H5F_t *f, hid_t dxpl_id, unsigned type_id,
message = list->messages[list_pos];
} /* end if */
else {
+ htri_t msg_exists; /* Whether the message exists in the v2 B-tree */
+
/* Index is a B-tree */
HDassert(header->index_type == H5SM_BTREE);
/* Look up the message in the v2 B-tree */
- if(H5B2_find(f, dxpl_id, H5SM_INDEX, header->index_addr, &key, H5SM_get_refcount_bt2_cb, &message) < 0)
+ if((msg_exists = H5B2_find(f, dxpl_id, H5SM_INDEX, header->index_addr, &key, H5SM_get_refcount_bt2_cb, &message)) < 0)
+ HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, FAIL, "error finding message in index")
+ if(!msg_exists)
HGOTO_ERROR(H5E_SOHM, H5E_NOTFOUND, FAIL, "message not in index")
} /* end else */
diff --git a/src/H5SMcache.c b/src/H5SMcache.c
index 021b43f..91478c5 100644
--- a/src/H5SMcache.c
+++ b/src/H5SMcache.c
@@ -27,6 +27,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5Fpkg.h" /* File access */
#include "H5FLprivate.h" /* Free Lists */
+#include "H5MFprivate.h" /* File memory management */
#include "H5MMprivate.h" /* Memory management */
#include "H5SMpkg.h" /* Shared object header messages */
#include "H5WBprivate.h" /* Wrapped Buffers */
@@ -652,18 +653,34 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5SM_list_dest(H5F_t UNUSED *f, H5SM_list_t* list)
+H5SM_list_dest(H5F_t *f, H5SM_list_t* list)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_list_dest)
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5SM_list_dest)
+ /* Sanity check */
HDassert(list);
+ HDassert(list->header);
HDassert(list->messages);
- H5FL_ARR_FREE(H5SM_sohm_t, list->messages);
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!list->cache_info.free_file_space_on_destroy || H5F_addr_defined(list->cache_info.addr));
+
+ /* Check for freeing file space for shared message index list */
+ if(list->cache_info.free_file_space_on_destroy) {
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_SOHM_INDEX, H5AC_dxpl_id, list->cache_info.addr, (hsize_t)H5SM_LIST_SIZE(f, list->header->list_max)) < 0)
+ HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, FAIL, "unable to free shared message list")
+ } /* end if */
+ /* Release resources */
+ H5FL_ARR_FREE(H5SM_sohm_t, list->messages);
(void)H5FL_FREE(H5SM_list_t, list);
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5SM_list_dest() */
diff --git a/src/H5Spoint.c b/src/H5Spoint.c
index a93e274..74d72d9 100644
--- a/src/H5Spoint.c
+++ b/src/H5Spoint.c
@@ -878,8 +878,8 @@ H5S_point_deserialize (H5S_t *space, const uint8_t *buf)
UINT32DECODE(buf, *tcoord);
/* Select points */
- if(H5S_select_elements(space,op,num_elem,(const hsize_t *)coord) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection");
+ if(H5S_select_elements(space, op, num_elem, (const hsize_t *)coord) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
done:
/* Free the coordinate array if necessary */
diff --git a/src/Makefile.am b/src/Makefile.am
index 9a9673b..3f6c1bb 100755
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -53,20 +53,25 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5E.c H5Edeprec.c H5Eint.c \
H5EA.c H5EAcache.c H5EAdbg.c H5EAdblock.c H5EAhdr.c H5EAiblock.c \
H5EAint.c H5EAsblock.c H5EAstat.c H5EAtest.c \
- H5F.c H5Fdbg.c H5Ffake.c H5Fmount.c H5Fsfile.c H5Fsuper.c H5Ftest.c \
+ H5F.c H5Faccum.c H5Fdbg.c H5Ffake.c H5Fio.c H5Fmount.c H5Fmpi.c H5Fquery.c \
+ H5Fsfile.c H5Fsuper.c H5Ftest.c \
H5FD.c H5FDcore.c \
- H5FDdirect.c H5FDfamily.c H5FDlog.c H5FDmpi.c H5FDmpio.c \
+ H5FDdirect.c H5FDfamily.c H5FDint.c H5FDlog.c H5FDmpi.c H5FDmpio.c \
H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDspace.c H5FDstdio.c \
- H5FL.c H5FO.c H5FS.c H5FScache.c H5FSdbg.c H5FSsection.c \
- H5G.c H5Gbtree2.c H5Gcompact.c H5Gdense.c H5Gdeprec.c H5Gent.c \
+ H5FL.c H5FO.c H5FS.c H5FScache.c H5FSdbg.c H5FSsection.c H5FSstat.c H5FStest.c \
+ H5G.c H5Gbtree2.c H5Gcache.c \
+ H5Gcompact.c H5Gdense.c H5Gdeprec.c H5Gent.c \
H5Gint.c H5Glink.c \
H5Gloc.c H5Gname.c H5Gnode.c H5Gobj.c H5Goh.c H5Gstab.c H5Gtest.c \
H5Gtraverse.c \
H5HF.c H5HFbtree2.c H5HFcache.c H5HFdbg.c H5HFdblock.c H5HFdtable.c \
H5HFhdr.c H5HFhuge.c H5HFiblock.c H5HFiter.c H5HFman.c H5HFsection.c \
H5HFspace.c H5HFstat.c H5HFtest.c H5HFtiny.c \
- H5HG.c H5HGdbg.c H5HL.c H5HLdbg.c H5HP.c H5I.c H5L.c H5Lexternal.c \
- H5MF.c H5MM.c H5MP.c H5MPtest.c \
+ H5HG.c H5HGcache.c H5HGdbg.c \
+ H5HL.c H5HLcache.c H5HLdbg.c \
+ H5HP.c H5I.c H5L.c H5Lexternal.c \
+ H5MF.c H5MFaggr.c H5MFdbg.c H5MFsection.c \
+ H5MM.c H5MP.c H5MPtest.c \
H5O.c H5Oainfo.c H5Oalloc.c H5Oattr.c \
H5Oattribute.c H5Obogus.c H5Obtreek.c H5Ocache.c \
H5Ocont.c H5Ocopy.c H5Odbg.c H5Odrvinfo.c H5Odtype.c H5Oefl.c \
diff --git a/src/Makefile.in b/src/Makefile.in
index aff05cd..d6385b6 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -87,41 +87,44 @@ am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \
H5Dint.lo H5Dio.lo H5Distore.lo H5Dmpio.lo H5Doh.lo \
H5Dscatgath.lo H5Dselect.lo H5Dtest.lo H5E.lo H5Edeprec.lo \
H5Eint.lo H5EA.lo H5EAcache.lo H5EAdbg.lo H5EAdblock.lo \
- H5EAhdr.lo H5EAiblock.lo H5EAint.lo H5EAsblock.lo H5EAstat.lo H5EAtest.lo \
- H5F.lo H5Fdbg.lo H5Ffake.lo H5Fmount.lo H5Fsfile.lo \
- H5Fsuper.lo H5Ftest.lo H5FD.lo H5FDcore.lo H5FDdirect.lo \
- H5FDfamily.lo H5FDlog.lo H5FDmpi.lo H5FDmpio.lo \
- H5FDmpiposix.lo H5FDmulti.lo H5FDsec2.lo H5FDspace.lo \
- H5FDstdio.lo H5FL.lo H5FO.lo H5FS.lo H5FScache.lo H5FSdbg.lo \
- H5FSsection.lo H5G.lo H5Gbtree2.lo H5Gcompact.lo H5Gdense.lo \
- H5Gdeprec.lo H5Gent.lo H5Gint.lo H5Glink.lo H5Gloc.lo \
- H5Gname.lo H5Gnode.lo H5Gobj.lo H5Goh.lo H5Gstab.lo H5Gtest.lo \
- H5Gtraverse.lo H5HF.lo H5HFbtree2.lo H5HFcache.lo H5HFdbg.lo \
- H5HFdblock.lo H5HFdtable.lo H5HFhdr.lo H5HFhuge.lo \
- H5HFiblock.lo H5HFiter.lo H5HFman.lo H5HFsection.lo \
- H5HFspace.lo H5HFstat.lo H5HFtest.lo H5HFtiny.lo H5HG.lo \
- H5HGdbg.lo H5HL.lo H5HLdbg.lo H5HP.lo H5I.lo H5L.lo \
- H5Lexternal.lo H5MF.lo H5MM.lo H5MP.lo H5MPtest.lo H5O.lo \
- H5Oainfo.lo H5Oalloc.lo H5Oattr.lo H5Oattribute.lo H5Obogus.lo \
- H5Obtreek.lo H5Ocache.lo H5Ocont.lo H5Ocopy.lo H5Odbg.lo \
- H5Odrvinfo.lo H5Odtype.lo H5Oefl.lo H5Ofill.lo H5Oginfo.lo \
- H5Olayout.lo H5Olinfo.lo H5Olink.lo H5Omessage.lo H5Omtime.lo \
- H5Oname.lo H5Onull.lo H5Opline.lo H5Orefcount.lo H5Osdspace.lo \
- H5Oshared.lo H5Ostab.lo H5Oshmesg.lo H5Otest.lo H5Ounknown.lo \
- H5P.lo H5Pacpl.lo H5Pdcpl.lo H5Pdeprec.lo H5Pdxpl.lo \
- H5Pfapl.lo H5Pfcpl.lo H5Pfmpl.lo H5Pgcpl.lo H5Pint.lo \
- H5Plapl.lo H5Plcpl.lo H5Pocpl.lo H5Pocpypl.lo H5Pstrcpl.lo \
- H5Ptest.lo H5R.lo H5Rdeprec.lo H5RC.lo H5RS.lo H5S.lo \
- H5Sall.lo H5Sdbg.lo H5Shyper.lo H5Smpio.lo H5Snone.lo \
- H5Spoint.lo H5Sselect.lo H5Stest.lo H5SL.lo H5SM.lo \
- H5SMbtree2.lo H5SMcache.lo H5SMtest.lo H5ST.lo H5T.lo \
- H5Tarray.lo H5Tbit.lo H5Tcommit.lo H5Tcompound.lo H5Tconv.lo \
- H5Tcset.lo H5Tdbg.lo H5Tdeprec.lo H5Tenum.lo H5Tfields.lo \
- H5Tfixed.lo H5Tfloat.lo H5Tinit.lo H5Tnative.lo H5Toffset.lo \
- H5Toh.lo H5Topaque.lo H5Torder.lo H5Tpad.lo H5Tprecis.lo \
- H5Tstrpad.lo H5Tvisit.lo H5Tvlen.lo H5TS.lo H5V.lo H5WB.lo \
- H5Z.lo H5Zdeflate.lo H5Zfletcher32.lo H5Znbit.lo H5Zshuffle.lo \
- H5Zszip.lo H5Zscaleoffset.lo H5Ztrans.lo
+ H5EAhdr.lo H5EAiblock.lo H5EAint.lo H5EAsblock.lo H5EAstat.lo \
+ H5EAtest.lo H5F.lo H5Faccum.lo H5Fdbg.lo H5Ffake.lo H5Fio.lo \
+ H5Fmount.lo H5Fmpi.lo H5Fquery.lo H5Fsfile.lo H5Fsuper.lo \
+ H5Ftest.lo H5FD.lo H5FDcore.lo H5FDdirect.lo H5FDfamily.lo \
+ H5FDint.lo H5FDlog.lo H5FDmpi.lo H5FDmpio.lo H5FDmpiposix.lo \
+ H5FDmulti.lo H5FDsec2.lo H5FDspace.lo H5FDstdio.lo H5FL.lo \
+ H5FO.lo H5FS.lo H5FScache.lo H5FSdbg.lo H5FSsection.lo \
+ H5FSstat.lo H5FStest.lo H5G.lo H5Gbtree2.lo H5Gcache.lo \
+ H5Gcompact.lo H5Gdense.lo H5Gdeprec.lo H5Gent.lo H5Gint.lo \
+ H5Glink.lo H5Gloc.lo H5Gname.lo H5Gnode.lo H5Gobj.lo H5Goh.lo \
+ H5Gstab.lo H5Gtest.lo H5Gtraverse.lo H5HF.lo H5HFbtree2.lo \
+ H5HFcache.lo H5HFdbg.lo H5HFdblock.lo H5HFdtable.lo H5HFhdr.lo \
+ H5HFhuge.lo H5HFiblock.lo H5HFiter.lo H5HFman.lo \
+ H5HFsection.lo H5HFspace.lo H5HFstat.lo H5HFtest.lo \
+ H5HFtiny.lo H5HG.lo H5HGcache.lo H5HGdbg.lo H5HL.lo \
+ H5HLcache.lo H5HLdbg.lo H5HP.lo H5I.lo H5L.lo H5Lexternal.lo \
+ H5MF.lo H5MFaggr.lo H5MFdbg.lo H5MFsection.lo H5MM.lo H5MP.lo \
+ H5MPtest.lo H5O.lo H5Oainfo.lo H5Oalloc.lo H5Oattr.lo \
+ H5Oattribute.lo H5Obogus.lo H5Obtreek.lo H5Ocache.lo \
+ H5Ocont.lo H5Ocopy.lo H5Odbg.lo H5Odrvinfo.lo H5Odtype.lo \
+ H5Oefl.lo H5Ofill.lo H5Oginfo.lo H5Olayout.lo H5Olinfo.lo \
+ H5Olink.lo H5Omessage.lo H5Omtime.lo H5Oname.lo H5Onull.lo \
+ H5Opline.lo H5Orefcount.lo H5Osdspace.lo H5Oshared.lo \
+ H5Ostab.lo H5Oshmesg.lo H5Otest.lo H5Ounknown.lo H5P.lo \
+ H5Pacpl.lo H5Pdcpl.lo H5Pdeprec.lo H5Pdxpl.lo H5Pfapl.lo \
+ H5Pfcpl.lo H5Pfmpl.lo H5Pgcpl.lo H5Pint.lo H5Plapl.lo \
+ H5Plcpl.lo H5Pocpl.lo H5Pocpypl.lo H5Pstrcpl.lo H5Ptest.lo \
+ H5R.lo H5Rdeprec.lo H5RC.lo H5RS.lo H5S.lo H5Sall.lo H5Sdbg.lo \
+ H5Shyper.lo H5Smpio.lo H5Snone.lo H5Spoint.lo H5Sselect.lo \
+ H5Stest.lo H5SL.lo H5SM.lo H5SMbtree2.lo H5SMcache.lo \
+ H5SMtest.lo H5ST.lo H5T.lo H5Tarray.lo H5Tbit.lo H5Tcommit.lo \
+ H5Tcompound.lo H5Tconv.lo H5Tcset.lo H5Tdbg.lo H5Tdeprec.lo \
+ H5Tenum.lo H5Tfields.lo H5Tfixed.lo H5Tfloat.lo H5Tinit.lo \
+ H5Tnative.lo H5Toffset.lo H5Toh.lo H5Topaque.lo H5Torder.lo \
+ H5Tpad.lo H5Tprecis.lo H5Tstrpad.lo H5Tvisit.lo H5Tvlen.lo \
+ H5TS.lo H5V.lo H5WB.lo H5Z.lo H5Zdeflate.lo H5Zfletcher32.lo \
+ H5Znbit.lo H5Zshuffle.lo H5Zszip.lo H5Zscaleoffset.lo \
+ H5Ztrans.lo
libhdf5_la_OBJECTS = $(am_libhdf5_la_OBJECTS)
libhdf5_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
@@ -433,20 +436,25 @@ libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5E.c H5Edeprec.c H5Eint.c \
H5EA.c H5EAcache.c H5EAdbg.c H5EAdblock.c H5EAhdr.c H5EAiblock.c \
H5EAint.c H5EAsblock.c H5EAstat.c H5EAtest.c \
- H5F.c H5Fdbg.c H5Ffake.c H5Fmount.c H5Fsfile.c H5Fsuper.c H5Ftest.c \
+ H5F.c H5Faccum.c H5Fdbg.c H5Ffake.c H5Fio.c H5Fmount.c H5Fmpi.c H5Fquery.c \
+ H5Fsfile.c H5Fsuper.c H5Ftest.c \
H5FD.c H5FDcore.c \
- H5FDdirect.c H5FDfamily.c H5FDlog.c H5FDmpi.c H5FDmpio.c \
+ H5FDdirect.c H5FDfamily.c H5FDint.c H5FDlog.c H5FDmpi.c H5FDmpio.c \
H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDspace.c H5FDstdio.c \
- H5FL.c H5FO.c H5FS.c H5FScache.c H5FSdbg.c H5FSsection.c \
- H5G.c H5Gbtree2.c H5Gcompact.c H5Gdense.c H5Gdeprec.c H5Gent.c \
+ H5FL.c H5FO.c H5FS.c H5FScache.c H5FSdbg.c H5FSsection.c H5FSstat.c H5FStest.c \
+ H5G.c H5Gbtree2.c H5Gcache.c \
+ H5Gcompact.c H5Gdense.c H5Gdeprec.c H5Gent.c \
H5Gint.c H5Glink.c \
H5Gloc.c H5Gname.c H5Gnode.c H5Gobj.c H5Goh.c H5Gstab.c H5Gtest.c \
H5Gtraverse.c \
H5HF.c H5HFbtree2.c H5HFcache.c H5HFdbg.c H5HFdblock.c H5HFdtable.c \
H5HFhdr.c H5HFhuge.c H5HFiblock.c H5HFiter.c H5HFman.c H5HFsection.c \
H5HFspace.c H5HFstat.c H5HFtest.c H5HFtiny.c \
- H5HG.c H5HGdbg.c H5HL.c H5HLdbg.c H5HP.c H5I.c H5L.c H5Lexternal.c \
- H5MF.c H5MM.c H5MP.c H5MPtest.c \
+ H5HG.c H5HGcache.c H5HGdbg.c \
+ H5HL.c H5HLcache.c H5HLdbg.c \
+ H5HP.c H5I.c H5L.c H5Lexternal.c \
+ H5MF.c H5MFaggr.c H5MFdbg.c H5MFsection.c \
+ H5MM.c H5MP.c H5MPtest.c \
H5O.c H5Oainfo.c H5Oalloc.c H5Oattr.c \
H5Oattribute.c H5Obogus.c H5Obtreek.c H5Ocache.c \
H5Ocont.c H5Ocopy.c H5Odbg.c H5Odrvinfo.c H5Odtype.c H5Oefl.c \
@@ -659,6 +667,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDcore.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDdirect.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDfamily.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDint.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDlog.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDmpi.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDmpio.Plo@am__quote@
@@ -673,14 +682,21 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FScache.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FSdbg.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FSsection.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FSstat.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FStest.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Faccum.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fdbg.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ffake.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fio.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fmount.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fmpi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fquery.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fsfile.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fsuper.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ftest.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5G.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gbtree2.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gcache.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gcompact.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gdense.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gdeprec.Plo@am__quote@
@@ -712,14 +728,19 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFtest.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFtiny.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HG.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HGcache.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HGdbg.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HL.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HLcache.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HLdbg.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HP.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5I.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5L.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Lexternal.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MF.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MFaggr.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MFdbg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MFsection.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MM.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MP.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MPtest.Plo@am__quote@