summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2010-10-19 19:11:23 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2010-10-19 19:11:23 (GMT)
commit63ebb100e4aa4d2cc1117ca7ebc67a2f071119d1 (patch)
tree1a4395f0c53513b3b824b861ca4b27ac74d5db16 /src
parent3c470c9db63424d8a07c1fb789ee8e8c513dd2a6 (diff)
downloadhdf5-63ebb100e4aa4d2cc1117ca7ebc67a2f071119d1.zip
hdf5-63ebb100e4aa4d2cc1117ca7ebc67a2f071119d1.tar.gz
hdf5-63ebb100e4aa4d2cc1117ca7ebc67a2f071119d1.tar.bz2
[svn-r19641] Description:
Bring r19542:19639 from trunk to revise_chunks branch. Tested on: FreeBSD/32 6.3 (duty) in debug mode FreeBSD/64 6.3 (liberty) w/C++ & FORTRAN, in debug mode Linux/32 2.6 (jam) w/PGI compilers, w/default API=1.8.x, w/C++ & FORTRAN, w/threadsafe, in debug mode Linux/64-amd64 2.6 (amani) 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, w/threadsafe, in production mode Linux/PPC 2.6 (heiwa) w/C++ & FORTRAN, w/threadsafe, in debug mode Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN, in production mode Linux/64-amd64 2.6 (abe) w/parallel, w/FORTRAN, in debug mode Mac OS X/32 10.6.4 (amazon) in debug mode Mac OS X/32 10.6.4 (amazon) w/C++ & FORTRAN, w/threadsafe, in production mode Mac OS X/32 10.6.4 (amazon) w/parallel, in debug mode
Diffstat (limited to 'src')
-rw-r--r--src/H5AC.c34
-rw-r--r--src/H5ACprivate.h2
-rw-r--r--src/H5B.c373
-rw-r--r--src/H5C.c133
-rw-r--r--src/H5Cprivate.h3
-rw-r--r--src/H5D.c14
-rw-r--r--src/H5Dbtree.c4
-rw-r--r--src/H5Dchunk.c22
-rw-r--r--src/H5Dint.c4
-rw-r--r--src/H5Dpkg.h3
-rw-r--r--src/H5E.c52
-rw-r--r--src/H5Edeprec.c26
-rw-r--r--src/H5Eint.c18
-rw-r--r--src/H5Epkg.h19
-rw-r--r--src/H5F.c2
-rw-r--r--src/H5Faccum.c736
-rw-r--r--src/H5Fio.c24
-rw-r--r--src/H5Fpkg.h11
-rw-r--r--src/H5Fsuper.c61
-rw-r--r--src/H5Fsuper_cache.c4
-rw-r--r--src/H5G.c16
-rw-r--r--src/H5Gobj.c5
-rw-r--r--src/H5Groot.c4
-rw-r--r--src/H5Gtraverse.c10
-rw-r--r--src/H5L.c22
-rw-r--r--src/H5O.c57
-rw-r--r--src/H5Ocache.c74
-rw-r--r--src/H5Opkg.h1
-rw-r--r--src/H5Oprivate.h4
-rw-r--r--src/H5Otest.c49
-rw-r--r--src/H5Tcommit.c17
-rw-r--r--src/H5public.h4
-rw-r--r--src/Makefile.in2
33 files changed, 1236 insertions, 574 deletions
diff --git a/src/H5AC.c b/src/H5AC.c
index 1c92833..f2a728f 100644
--- a/src/H5AC.c
+++ b/src/H5AC.c
@@ -1825,6 +1825,40 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5AC_dump_cache
+ *
+ * Purpose: Dumps a summary of the contents of the metadata cache
+ * to stdout.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * Sunday, October 10, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5AC_dump_cache(const H5F_t *f)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5AC_dump_cache, FAIL)
+
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->cache);
+
+ if ( H5C_dump_cache(f->shared->cache, H5F_OPEN_NAME(f)) < 0 ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5C_dump_cache() failed.")
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5AC_dump_cache() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5AC_get_cache_auto_resize_config
*
* Purpose: Wrapper function for H5C_get_cache_auto_resize_config().
diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h
index 6780b72..2a817a0 100644
--- a/src/H5ACprivate.h
+++ b/src/H5ACprivate.h
@@ -373,6 +373,8 @@ H5_DLL herr_t H5AC_set_write_done_callback(H5C_t * cache_ptr,
void (* write_done)(void));
H5_DLL herr_t H5AC_stats(const H5F_t *f);
+H5_DLL herr_t H5AC_dump_cache(const H5F_t *f);
+
H5_DLL herr_t H5AC_get_cache_auto_resize_config(const H5AC_t * cache_ptr,
H5AC_cache_config_t *config_ptr);
diff --git a/src/H5B.c b/src/H5B.c
index f15eedb..389dbb5 100644
--- a/src/H5B.c
+++ b/src/H5B.c
@@ -120,6 +120,8 @@
4 + /*type, level, num entries */ \
2*H5F_SIZEOF_ADDR(F)) /*left and right sibling addresses */
+/* Default initializer for H5B_ins_ud_t */
+#define H5B_INS_UD_T_NULL {NULL, HADDR_UNDEF, H5AC__NO_FLAGS_SET}
/******************/
/* Local Typedefs */
@@ -131,24 +133,32 @@ typedef struct H5B_iter_ud_t {
void *udata; /* Node type's 'udata' for loading & iterator callback */
} H5B_info_ud_t;
+/* Convenience struct for the arguments needed to unprotect a b-tree after a
+ * call to H5B_iterate_helper() or H5B_split() */
+typedef struct H5B_ins_ud_t {
+ H5B_t *bt; /* B-tree */
+ haddr_t addr; /* B-tree address */
+ unsigned cache_flags; /* Cache flags for H5AC_unprotect() */
+} H5B_ins_ud_t;
+
/********************/
/* Local Prototypes */
/********************/
-static H5B_ins_t H5B_insert_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr,
+static H5B_ins_t H5B_insert_helper(H5F_t *f, hid_t dxpl_id, H5B_ins_ud_t *bt_ud,
const H5B_class_t *type,
uint8_t *lt_key,
hbool_t *lt_key_changed,
uint8_t *md_key, void *udata,
uint8_t *rt_key,
hbool_t *rt_key_changed,
- haddr_t *retval);
+ H5B_ins_ud_t *split_bt_ud/*out*/);
static herr_t H5B_insert_child(H5B_t *bt, unsigned *bt_flags,
unsigned idx, haddr_t child,
H5B_ins_t anchor, const void *md_key);
-static herr_t H5B_split(H5F_t *f, hid_t dxpl_id, H5B_t *old_bt,
- unsigned *old_bt_flags, haddr_t old_addr,
- unsigned idx, void *udata, haddr_t *new_addr/*out*/);
+static herr_t H5B_split(H5F_t *f, hid_t dxpl_id, H5B_ins_ud_t *bt_ud,
+ unsigned idx, void *udata,
+ H5B_ins_ud_t *split_bt_ud/*out*/);
static H5B_t * H5B_copy(const H5B_t *old_bt);
@@ -374,7 +384,7 @@ done:
* The UDATA pointer is passed to the sizeof_rkey() method but is
* otherwise unused.
*
- * The OLD_BT argument is a pointer to a protected B-tree
+ * The BT_UD argument is a pointer to a protected B-tree
* node.
*
* Return: Non-negative on success (The address of the new node is
@@ -387,14 +397,12 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5B_split(H5F_t *f, hid_t dxpl_id, H5B_t *old_bt, unsigned *old_bt_flags,
- haddr_t old_addr, unsigned idx, void *udata, haddr_t *new_addr_p/*out*/)
+H5B_split(H5F_t *f, hid_t dxpl_id, H5B_ins_ud_t *bt_ud, unsigned idx,
+ void *udata, H5B_ins_ud_t *split_bt_ud/*out*/)
{
H5P_genplist_t *dx_plist; /* Data transfer property list */
- H5B_shared_t *shared; /* Pointer to shared B-tree info */
+ H5B_shared_t *shared; /* Pointer to shared B-tree info */
H5B_cache_ud_t cache_udata; /* User-data for metadata cache callback */
- unsigned new_bt_flags = H5AC__NO_FLAGS_SET;
- H5B_t *new_bt = NULL;
unsigned nleft, nright; /* Number of keys in left & right halves */
double split_ratios[3]; /* B-tree split ratios */
herr_t ret_value = SUCCEED; /* Return value */
@@ -405,16 +413,18 @@ H5B_split(H5F_t *f, hid_t dxpl_id, H5B_t *old_bt, unsigned *old_bt_flags,
* Check arguments.
*/
HDassert(f);
- HDassert(old_bt);
- HDassert(old_bt_flags);
- HDassert(H5F_addr_defined(old_addr));
+ HDassert(bt_ud);
+ HDassert(bt_ud->bt);
+ HDassert(H5F_addr_defined(bt_ud->addr));
+ HDassert(split_bt_ud);
+ HDassert(!split_bt_ud->bt);
/*
* Initialize variables.
*/
- shared = (H5B_shared_t *)H5RC_GET_OBJ(old_bt->rc_shared);
+ shared = (H5B_shared_t *)H5RC_GET_OBJ(bt_ud->bt->rc_shared);
HDassert(shared);
- HDassert(old_bt->nchildren == shared->two_k);
+ HDassert(bt_ud->bt->nchildren == shared->two_k);
/* Get the dataset transfer property list */
if(NULL == (dx_plist = (H5P_genplist_t *)H5I_object(dxpl_id)))
@@ -428,11 +438,11 @@ H5B_split(H5F_t *f, hid_t dxpl_id, H5B_t *old_bt, unsigned *old_bt_flags,
if(H5DEBUG(B)) {
const char *side;
- if(!H5F_addr_defined(old_bt->left) && !H5F_addr_defined(old_bt->right))
+ if(!H5F_addr_defined(bt_ud->bt->left) && !H5F_addr_defined(bt_ud->bt->right))
side = "ONLY";
- else if(!H5F_addr_defined(old_bt->right))
+ else if(!H5F_addr_defined(bt_ud->bt->right))
side = "RIGHT";
- else if(!H5F_addr_defined(old_bt->left))
+ else if(!H5F_addr_defined(bt_ud->bt->left))
side = "LEFT";
else
side = "MIDDLE";
@@ -445,9 +455,9 @@ H5B_split(H5F_t *f, hid_t dxpl_id, H5B_t *old_bt, unsigned *old_bt_flags,
* Decide how to split the children of the old node among the old node
* and the new node.
*/
- if(!H5F_addr_defined(old_bt->right))
+ if(!H5F_addr_defined(bt_ud->bt->right))
nleft = (unsigned)((double)shared->two_k * split_ratios[2]); /*right*/
- else if(!H5F_addr_defined(old_bt->left))
+ else if(!H5F_addr_defined(bt_ud->bt->left))
nleft = (unsigned)((double)shared->two_k * split_ratios[0]); /*left*/
else
nleft = (unsigned)((double)shared->two_k * split_ratios[1]); /*middle*/
@@ -470,69 +480,66 @@ H5B_split(H5F_t *f, hid_t dxpl_id, H5B_t *old_bt, unsigned *old_bt_flags,
/*
* Create the new B-tree node.
*/
- if(H5B_create(f, dxpl_id, shared->type, udata, new_addr_p/*out*/) < 0)
+ if(H5B_create(f, dxpl_id, shared->type, udata, &split_bt_ud->addr/*out*/) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to create B-tree")
cache_udata.f = f;
cache_udata.type = shared->type;
- cache_udata.rc_shared = old_bt->rc_shared;
- if(NULL == (new_bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, *new_addr_p, &cache_udata, H5AC_WRITE)))
+ cache_udata.rc_shared = bt_ud->bt->rc_shared;
+ if(NULL == (split_bt_ud->bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, split_bt_ud->addr, &cache_udata, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree")
- new_bt->level = old_bt->level;
+ split_bt_ud->bt->level = bt_ud->bt->level;
/*
* Copy data from the old node to the new node.
*/
- /* this function didn't used to mark the new bt entry as dirty. Since
- * we just inserted the entry, this doesn't matter unless the entry
- * somehow gets flushed between the insert and the protect. At present,
- * I don't think this can happen, but it doesn't hurt to mark the entry
- * dirty again.
- * -- JRM
- */
- new_bt_flags |= H5AC__DIRTIED_FLAG;
- HDmemcpy(new_bt->native,
- old_bt->native + nleft * shared->type->sizeof_nkey,
+ split_bt_ud->cache_flags = H5AC__DIRTIED_FLAG;
+ HDmemcpy(split_bt_ud->bt->native,
+ bt_ud->bt->native + nleft * shared->type->sizeof_nkey,
(nright + 1) * shared->type->sizeof_nkey);
- HDmemcpy(new_bt->child,
- &old_bt->child[nleft],
+ HDmemcpy(split_bt_ud->bt->child,
+ &bt_ud->bt->child[nleft],
nright * sizeof(haddr_t));
- new_bt->nchildren = nright;
+ split_bt_ud->bt->nchildren = nright;
/*
* Truncate the old node.
*/
- *old_bt_flags |= H5AC__DIRTIED_FLAG;
- old_bt->nchildren = nleft;
+ bt_ud->cache_flags |= H5AC__DIRTIED_FLAG;
+ bt_ud->bt->nchildren = nleft;
/*
* Update sibling pointers.
*/
- new_bt->left = old_addr;
- new_bt->right = old_bt->right;
+ split_bt_ud->bt->left = bt_ud->addr;
+ split_bt_ud->bt->right = bt_ud->bt->right;
- if(H5F_addr_defined(old_bt->right)) {
+ if(H5F_addr_defined(bt_ud->bt->right)) {
H5B_t *tmp_bt;
H5B_cache_ud_t cache_udata2; /* User-data for metadata cache callback */
cache_udata2.f = f;
cache_udata2.type = shared->type;
- cache_udata2.rc_shared = old_bt->rc_shared;
- if(NULL == (tmp_bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, old_bt->right, &cache_udata2, H5AC_WRITE)))
+ cache_udata2.rc_shared = bt_ud->bt->rc_shared;
+ if(NULL == (tmp_bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, bt_ud->bt->right, &cache_udata2, H5AC_WRITE)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load right sibling")
- tmp_bt->left = *new_addr_p;
+ tmp_bt->left = split_bt_ud->addr;
- if(H5AC_unprotect(f, dxpl_id, H5AC_BT, old_bt->right, tmp_bt, H5AC__DIRTIED_FLAG) < 0)
+ if(H5AC_unprotect(f, dxpl_id, H5AC_BT, bt_ud->bt->right, tmp_bt, H5AC__DIRTIED_FLAG) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
} /* end if */
- old_bt->right = *new_addr_p;
+ bt_ud->bt->right = split_bt_ud->addr;
done:
- if(new_bt && H5AC_unprotect(f, dxpl_id, H5AC_BT, *new_addr_p, new_bt, new_bt_flags) < 0)
- HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ if(ret_value < 0) {
+ if(split_bt_ud->bt && H5AC_unprotect(f, dxpl_id, H5AC_BT, split_bt_ud->addr, split_bt_ud->bt, split_bt_ud->cache_flags) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ split_bt_ud->bt = NULL;
+ split_bt_ud->addr = HADDR_UNDEF;
+ } /* end if */
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5B_split() */
@@ -541,8 +548,7 @@ done:
/*-------------------------------------------------------------------------
* Function: H5B_insert
*
- * Purpose: Adds a new item to the B-tree. If the root node of
- * the B-tree splits then the B-tree gets a new address.
+ * Purpose: Adds a new item to the B-tree.
*
* Return: Non-negative on success/Negative on failure
*
@@ -565,10 +571,11 @@ H5B_insert(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t addr,
uint8_t *rt_key=(uint8_t*)_rt_key;
hbool_t lt_key_changed = FALSE, rt_key_changed = FALSE;
- haddr_t child, old_root;
+ haddr_t old_root_addr = HADDR_UNDEF;
unsigned level;
- H5B_t *bt;
- H5B_t *new_bt; /* Copy of B-tree info */
+ H5B_ins_ud_t bt_ud = H5B_INS_UD_T_NULL; /* (Old) root node */
+ H5B_ins_ud_t split_bt_ud = H5B_INS_UD_T_NULL; /* Split B-tree node */
+ H5B_t *new_root_bt = NULL; /* New root node */
H5RC_t *rc_shared; /* Ref-counted shared info */
H5B_shared_t *shared; /* Pointer to shared B-tree info */
H5B_cache_ud_t cache_udata; /* User-data for metadata cache callback */
@@ -583,118 +590,110 @@ H5B_insert(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t addr,
HDassert(type->sizeof_nkey <= sizeof _lt_key);
HDassert(H5F_addr_defined(addr));
- if((int)(my_ins = H5B_insert_helper(f, dxpl_id, addr, type, lt_key,
- &lt_key_changed, md_key, udata, rt_key, &rt_key_changed, &child/*out*/)) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to insert key")
- if(H5B_INS_NOOP == my_ins)
- HGOTO_DONE(SUCCEED)
- HDassert(H5B_INS_RIGHT == my_ins);
-
/* Get shared info for B-tree */
if(NULL == (rc_shared = (type->get_shared)(f, udata)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTGET, FAIL, "can't retrieve B-tree's shared ref. count object")
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTGET, FAIL, "can't retrieve B-tree's shared ref. count object")
shared = (H5B_shared_t *)H5RC_GET_OBJ(rc_shared);
HDassert(shared);
- /* the current root */
+ /* Protect the root node */
cache_udata.f = f;
cache_udata.type = type;
cache_udata.rc_shared = rc_shared;
- if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, &cache_udata, H5AC_READ)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to locate root of B-tree")
+ bt_ud.addr = addr;
+ if(NULL == (bt_ud.bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, &cache_udata, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to locate root of B-tree")
+
+ /* Insert the object */
+ if((int)(my_ins = H5B_insert_helper(f, dxpl_id, &bt_ud, type, lt_key,
+ &lt_key_changed, md_key, udata, rt_key, &rt_key_changed,
+ &split_bt_ud/*out*/)) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to insert key")
+ if(H5B_INS_NOOP == my_ins) {
+ HDassert(!split_bt_ud.bt);
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+ HDassert(H5B_INS_RIGHT == my_ins);
+ HDassert(split_bt_ud.bt);
+ HDassert(H5F_addr_defined(split_bt_ud.addr));
- level = bt->level;
+ /* Get level of old root */
+ level = bt_ud.bt->level;
+ /* update left and right keys */
if(!lt_key_changed)
- HDmemcpy(lt_key, H5B_NKEY(bt,shared,0), type->sizeof_nkey);
-
- if(H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release new child")
- bt = NULL;
-
- /* the new node */
- if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, child, &cache_udata, H5AC_READ)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load new node")
-
+ HDmemcpy(lt_key, H5B_NKEY(bt_ud.bt,shared,0), type->sizeof_nkey);
if(!rt_key_changed)
- HDmemcpy(rt_key, H5B_NKEY(bt,shared,bt->nchildren), type->sizeof_nkey);
-
- if(H5AC_unprotect(f, dxpl_id, H5AC_BT, child, bt, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release new child")
- bt = NULL;
+ HDmemcpy(rt_key, H5B_NKEY(split_bt_ud.bt,shared,split_bt_ud.bt->nchildren), type->sizeof_nkey);
/*
- * Copy the old root node to some other file location and make the new
- * root at the old root's previous address. This prevents the B-tree
- * from "moving".
+ * Copy the old root node to some other file location and make the new root
+ * at the old root's previous address. This prevents the B-tree from
+ * "moving".
*/
H5_CHECK_OVERFLOW(shared->sizeof_rnode,size_t,hsize_t);
- if(HADDR_UNDEF == (old_root = H5MF_alloc(f, H5FD_MEM_BTREE, dxpl_id, (hsize_t)shared->sizeof_rnode)))
+ if(HADDR_UNDEF == (old_root_addr = H5MF_alloc(f, H5FD_MEM_BTREE, dxpl_id, (hsize_t)shared->sizeof_rnode)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "unable to allocate file space to move root")
- /* update the new child's left pointer */
- if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, child, &cache_udata, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load new child")
-
- bt->left = old_root;
-
- if(H5AC_unprotect(f, dxpl_id, H5AC_BT, child, bt, H5AC__DIRTIED_FLAG) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release new child")
- bt = NULL; /* Make certain future references will be caught */
-
/*
- * Move the node to the new location by checking it out & checking it in
- * at the new location -QAK
+ * Move the node to the new location
*/
- /* Bring the old root into the cache if it's not already */
- if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, &cache_udata, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load new child")
-
- /* Make certain the old root info is marked as dirty before moving it, */
- /* so it is certain to be written out at the new location */
/* Make a copy of the old root information */
- if(NULL == (new_bt = H5B_copy(bt))) {
- HCOMMON_ERROR(H5E_BTREE, H5E_CANTCOPY, "unable to copy old root");
-
- if(H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__DIRTIED_FLAG) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release new child")
-
- HGOTO_DONE(FAIL)
- } /* end if */
+ if(NULL == (new_root_bt = H5B_copy(bt_ud.bt)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to copy old root");
- if(H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__DIRTIED_FLAG) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release new child")
- bt = NULL; /* Make certain future references will be caught */
+ /* Unprotect the old root so we can move it. Also force it to be marked
+ * dirty so it is written to the new location. */
+ if(H5AC_unprotect(f, dxpl_id, H5AC_BT, bt_ud.addr, bt_ud.bt, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release old root")
+ bt_ud.bt = NULL; /* Make certain future references will be caught */
/* Move the location of the old root on the disk */
- if(H5AC_move_entry(f, H5AC_BT, addr, old_root) < 0)
+ if(H5AC_move_entry(f, H5AC_BT, bt_ud.addr, old_root_addr) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to move B-tree root node")
+ bt_ud.addr = old_root_addr;
+
+ /* Update the split b-tree's left pointer to point to the new location */
+ split_bt_ud.bt->left = bt_ud.addr;
+ split_bt_ud.cache_flags |= H5AC__DIRTIED_FLAG;
/* clear the old root info at the old address (we already copied it) */
- new_bt->left = HADDR_UNDEF;
- new_bt->right = HADDR_UNDEF;
+ new_root_bt->left = HADDR_UNDEF;
+ new_root_bt->right = HADDR_UNDEF;
/* Set the new information for the copy */
- new_bt->level = level + 1;
- new_bt->nchildren = 2;
+ new_root_bt->level = level + 1;
+ new_root_bt->nchildren = 2;
- new_bt->child[0] = old_root;
- HDmemcpy(H5B_NKEY(new_bt, shared, 0), lt_key, shared->type->sizeof_nkey);
+ new_root_bt->child[0] = bt_ud.addr;
+ HDmemcpy(H5B_NKEY(new_root_bt, shared, 0), lt_key, shared->type->sizeof_nkey);
- new_bt->child[1] = child;
- HDmemcpy(H5B_NKEY(new_bt, shared, 1), md_key, shared->type->sizeof_nkey);
- HDmemcpy(H5B_NKEY(new_bt, shared, 2), rt_key, shared->type->sizeof_nkey);
+ new_root_bt->child[1] = split_bt_ud.addr;
+ HDmemcpy(H5B_NKEY(new_root_bt, shared, 1), md_key, shared->type->sizeof_nkey);
+ HDmemcpy(H5B_NKEY(new_root_bt, shared, 2), rt_key, shared->type->sizeof_nkey);
/* Insert the modified copy of the old root into the file again */
- if(H5AC_insert_entry(f, dxpl_id, H5AC_BT, addr, new_bt, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFLUSH, FAIL, "unable to flush old B-tree root node")
+ if(H5AC_insert_entry(f, dxpl_id, H5AC_BT, addr, new_root_bt, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFLUSH, FAIL, "unable to add old B-tree root node to cache")
#ifdef H5B_DEBUG
H5B_assert(f, dxpl_id, addr, type, udata);
#endif
done:
+ if(ret_value < 0)
+ if(new_root_bt && H5B_node_dest(new_root_bt) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTRELEASE, FAIL, "unable to free B-tree root node");
+
+ if(bt_ud.bt)
+ if(H5AC_unprotect(f, dxpl_id, H5AC_BT, bt_ud.addr, bt_ud.bt, bt_ud.cache_flags) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to unprotect old root")
+
+ if(split_bt_ud.bt)
+ if(H5AC_unprotect(f, dxpl_id, H5AC_BT, split_bt_ud.addr, split_bt_ud.bt, split_bt_ud.cache_flags) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to unprotect new child")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5B_insert() */
@@ -725,6 +724,7 @@ H5B_insert_child(H5B_t *bt, unsigned *bt_flags, unsigned idx,
HDassert(bt);
HDassert(bt_flags);
+ HDassert(H5F_addr_defined(child));
shared = (H5B_shared_t *)H5RC_GET_OBJ(bt->rc_shared);
HDassert(shared);
HDassert(bt->nchildren < shared->two_k);
@@ -803,20 +803,21 @@ H5B_insert_child(H5B_t *bt, unsigned *bt_flags, unsigned idx,
*-------------------------------------------------------------------------
*/
static H5B_ins_t
-H5B_insert_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type,
+H5B_insert_helper(H5F_t *f, hid_t dxpl_id, H5B_ins_ud_t *bt_ud,
+ const H5B_class_t *type,
uint8_t *lt_key, hbool_t *lt_key_changed,
uint8_t *md_key, void *udata,
uint8_t *rt_key, hbool_t *rt_key_changed,
- haddr_t *new_node_p/*out*/)
+ H5B_ins_ud_t *split_bt_ud/*out*/)
{
- unsigned bt_flags = H5AC__NO_FLAGS_SET, twin_flags = H5AC__NO_FLAGS_SET;
- H5B_t *bt = NULL, *twin = NULL;
+ H5B_t *bt; /* Convenience pointer to B-tree */
H5RC_t *rc_shared; /* Ref-counted shared info */
- H5B_shared_t *shared; /* Pointer to shared B-tree info */
+ H5B_shared_t *shared; /* Pointer to shared B-tree info */
H5B_cache_ud_t cache_udata; /* User-data for metadata cache callback */
unsigned lt = 0, idx = 0, rt; /* Left, final & right index values */
int cmp = -1; /* Key comparison value */
- haddr_t child_addr = HADDR_UNDEF;
+ H5B_ins_ud_t child_bt_ud = H5B_INS_UD_T_NULL; /* Child B-tree */
+ H5B_ins_ud_t new_child_bt_ud = H5B_INS_UD_T_NULL; /* Newly split child B-tree */
H5B_ins_t my_ins = H5B_INS_ERROR;
H5B_ins_t ret_value = H5B_INS_ERROR; /* Return value */
@@ -826,7 +827,9 @@ H5B_insert_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type
* Check arguments
*/
HDassert(f);
- HDassert(H5F_addr_defined(addr));
+ HDassert(bt_ud);
+ HDassert(bt_ud->bt);
+ HDassert(H5F_addr_defined(bt_ud->addr));
HDassert(type);
HDassert(type->decode);
HDassert(type->cmp3);
@@ -835,7 +838,12 @@ H5B_insert_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type
HDassert(lt_key_changed);
HDassert(rt_key);
HDassert(rt_key_changed);
- HDassert(new_node_p);
+ HDassert(split_bt_ud);
+ HDassert(!split_bt_ud->bt);
+ HDassert(!H5F_addr_defined(split_bt_ud->addr));
+ HDassert(split_bt_ud->cache_flags == H5AC__NO_FLAGS_SET);
+
+ bt = bt_ud->bt;
*lt_key_changed = FALSE;
*rt_key_changed = FALSE;
@@ -851,11 +859,6 @@ H5B_insert_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type
* data. When the search completes IDX points to the child that
* should get the new data.
*/
- cache_udata.f = f;
- cache_udata.type = type;
- cache_udata.rc_shared = rc_shared;
- if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, &cache_udata, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, H5B_INS_ERROR, "unable to load node")
rt = bt->nchildren;
while(lt < rt && cmp) {
@@ -866,6 +869,11 @@ H5B_insert_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type
lt = idx + 1;
} /* end while */
+ /* Set up user data for cache callbacks */
+ cache_udata.f = f;
+ cache_udata.type = type;
+ cache_udata.rc_shared = rc_shared;
+
if(0 == bt->nchildren) {
/*
* The value being inserted will be the only value in this tree. We
@@ -876,13 +884,13 @@ H5B_insert_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type
H5B_NKEY(bt, shared, 1), bt->child + 0/*out*/) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, H5B_INS_ERROR, "unable to create leaf node")
bt->nchildren = 1;
- bt_flags |= H5AC__DIRTIED_FLAG;
+ bt_ud->cache_flags |= H5AC__DIRTIED_FLAG;
idx = 0;
if(type->follow_min) {
if((int)(my_ins = (type->insert)(f, dxpl_id, bt->child[idx], H5B_NKEY(bt, shared, idx),
lt_key_changed, md_key, udata, H5B_NKEY(bt, shared, idx + 1),
- rt_key_changed, &child_addr/*out*/)) < 0)
+ rt_key_changed, &new_child_bt_ud.addr/*out*/)) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, H5B_INS_ERROR, "unable to insert first leaf node")
} /* end if */
else
@@ -893,10 +901,14 @@ H5B_insert_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type
* The value being inserted is less than any value in this tree.
* Follow the minimum branch out of this node to a subtree.
*/
- if((int)(my_ins = H5B_insert_helper(f, dxpl_id, bt->child[idx], type,
+ child_bt_ud.addr = bt->child[idx];
+ if(NULL == (child_bt_ud.bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, child_bt_ud.addr, &cache_udata, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, H5B_INS_ERROR, "unable to load node")
+
+ if((int)(my_ins = H5B_insert_helper(f, dxpl_id, &child_bt_ud, type,
H5B_NKEY(bt,shared,idx), lt_key_changed, md_key,
udata, H5B_NKEY(bt, shared, idx + 1), rt_key_changed,
- &child_addr/*out*/)) < 0)
+ &new_child_bt_ud/*out*/)) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, H5B_INS_ERROR, "can't insert minimum subtree")
} else if(type->follow_min) {
/*
@@ -906,7 +918,7 @@ H5B_insert_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type
*/
if((int)(my_ins = (type->insert)(f, dxpl_id, bt->child[idx], H5B_NKEY(bt, shared, idx),
lt_key_changed, md_key, udata, H5B_NKEY(bt, shared, idx + 1),
- rt_key_changed, &child_addr/*out*/)) < 0)
+ rt_key_changed, &new_child_bt_ud.addr/*out*/)) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, H5B_INS_ERROR, "can't insert minimum leaf node")
} else {
/*
@@ -917,7 +929,7 @@ H5B_insert_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type
my_ins = H5B_INS_LEFT;
HDmemcpy(md_key, H5B_NKEY(bt,shared,idx), type->sizeof_nkey);
if((type->new_node)(f, dxpl_id, H5B_INS_LEFT, H5B_NKEY(bt, shared, idx), udata,
- md_key, &child_addr/*out*/) < 0)
+ md_key, &new_child_bt_ud.addr/*out*/) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, H5B_INS_ERROR, "can't insert minimum leaf node")
*lt_key_changed = TRUE;
} /* end else */
@@ -935,9 +947,14 @@ H5B_insert_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type
* Follow the maximum branch out of this node to a subtree.
*/
idx = bt->nchildren - 1;
- if((int)(my_ins = H5B_insert_helper(f, dxpl_id, bt->child[idx], type,
+ child_bt_ud.addr = bt->child[idx];
+ if(NULL == (child_bt_ud.bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, child_bt_ud.addr, &cache_udata, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, H5B_INS_ERROR, "unable to load node")
+
+ if((int)(my_ins = H5B_insert_helper(f, dxpl_id, &child_bt_ud, type,
H5B_NKEY(bt, shared, idx), lt_key_changed, md_key, udata,
- H5B_NKEY(bt, shared, idx + 1), rt_key_changed, &child_addr/*out*/)) < 0)
+ H5B_NKEY(bt, shared, idx + 1), rt_key_changed,
+ &new_child_bt_ud/*out*/)) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, H5B_INS_ERROR, "can't insert maximum subtree")
} else if(type->follow_max) {
/*
@@ -948,7 +965,7 @@ H5B_insert_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type
idx = bt->nchildren - 1;
if((int)(my_ins = (type->insert)(f, dxpl_id, bt->child[idx], H5B_NKEY(bt, shared, idx),
lt_key_changed, md_key, udata, H5B_NKEY(bt, shared, idx + 1),
- rt_key_changed, &child_addr/*out*/)) < 0)
+ rt_key_changed, &new_child_bt_ud.addr/*out*/)) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, H5B_INS_ERROR, "can't insert maximum leaf node")
} else {
/*
@@ -960,7 +977,7 @@ H5B_insert_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type
my_ins = H5B_INS_RIGHT;
HDmemcpy(md_key, H5B_NKEY(bt, shared, idx + 1), type->sizeof_nkey);
if((type->new_node)(f, dxpl_id, H5B_INS_RIGHT, md_key, udata,
- H5B_NKEY(bt, shared, idx + 1), &child_addr/*out*/) < 0)
+ H5B_NKEY(bt, shared, idx + 1), &new_child_bt_ud.addr/*out*/) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, H5B_INS_ERROR, "can't insert maximum leaf node")
*rt_key_changed = TRUE;
} /* end else */
@@ -985,9 +1002,13 @@ H5B_insert_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type
* Follow a branch out of this node to another subtree.
*/
HDassert(idx < bt->nchildren);
- if((int)(my_ins = H5B_insert_helper(f, dxpl_id, bt->child[idx], type,
+ child_bt_ud.addr = bt->child[idx];
+ if(NULL == (child_bt_ud.bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, child_bt_ud.addr, &cache_udata, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, H5B_INS_ERROR, "unable to load node")
+
+ if((int)(my_ins = H5B_insert_helper(f, dxpl_id, &child_bt_ud, type,
H5B_NKEY(bt, shared, idx), lt_key_changed, md_key, udata,
- H5B_NKEY(bt, shared, idx + 1), rt_key_changed, &child_addr/*out*/)) < 0)
+ H5B_NKEY(bt, shared, idx + 1), rt_key_changed, &new_child_bt_ud/*out*/)) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, H5B_INS_ERROR, "can't insert subtree")
} else {
/*
@@ -996,7 +1017,7 @@ H5B_insert_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type
HDassert(idx < bt->nchildren);
if((int)(my_ins = (type->insert)(f, dxpl_id, bt->child[idx], H5B_NKEY(bt, shared, idx),
lt_key_changed, md_key, udata, H5B_NKEY(bt, shared, idx + 1),
- rt_key_changed, &child_addr/*out*/)) < 0)
+ rt_key_changed, &new_child_bt_ud.addr/*out*/)) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, H5B_INS_ERROR, "can't insert leaf node")
}
HDassert((int)my_ins >= 0);
@@ -1005,18 +1026,20 @@ H5B_insert_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type
* Update the left and right keys of the current node.
*/
if(*lt_key_changed) {
- bt_flags |= H5AC__DIRTIED_FLAG;
+ bt_ud->cache_flags |= H5AC__DIRTIED_FLAG;
if(idx > 0) {
HDassert(type->critical_key == H5B_LEFT);
+ HDassert(!(H5B_INS_LEFT == my_ins || H5B_INS_RIGHT == my_ins));
*lt_key_changed = FALSE;
} /* end if */
else
HDmemcpy(lt_key, H5B_NKEY(bt, shared, idx), type->sizeof_nkey);
} /* end if */
if(*rt_key_changed) {
- bt_flags |= H5AC__DIRTIED_FLAG;
+ bt_ud->cache_flags |= H5AC__DIRTIED_FLAG;
if(idx + 1 < bt->nchildren) {
HDassert(type->critical_key == H5B_RIGHT);
+ HDassert(!(H5B_INS_LEFT == my_ins || H5B_INS_RIGHT == my_ins));
*rt_key_changed = FALSE;
} /* end if */
else
@@ -1026,9 +1049,10 @@ H5B_insert_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type
/*
* The insertion simply changed the address for the child.
*/
- bt->child[idx] = child_addr;
- bt_flags |= H5AC__DIRTIED_FLAG;
- ret_value = H5B_INS_NOOP;
+ HDassert(!child_bt_ud.bt);
+ HDassert(bt->level == 0);
+ bt->child[idx] = new_child_bt_ud.addr;
+ bt_ud->cache_flags |= H5AC__DIRTIED_FLAG;
} else if(H5B_INS_LEFT == my_ins || H5B_INS_RIGHT == my_ins) {
hbool_t *tmp_bt_flags_ptr = NULL;
H5B_t *tmp_bt;
@@ -1037,26 +1061,24 @@ H5B_insert_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type
* If this node is full then split it before inserting the new child.
*/
if(bt->nchildren == shared->two_k) {
- if(H5B_split(f, dxpl_id, bt, &bt_flags, addr, idx, udata, new_node_p/*out*/) < 0)
+ if(H5B_split(f, dxpl_id, bt_ud, idx, udata, split_bt_ud/*out*/) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, H5B_INS_ERROR, "unable to split node")
- if(NULL == (twin = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, *new_node_p, &cache_udata, H5AC_WRITE)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, H5B_INS_ERROR, "unable to load node")
if(idx < bt->nchildren) {
tmp_bt = bt;
- tmp_bt_flags_ptr = &bt_flags;
+ tmp_bt_flags_ptr = &bt_ud->cache_flags;
} else {
idx -= bt->nchildren;
- tmp_bt = twin;
- tmp_bt_flags_ptr = &twin_flags;
+ tmp_bt = split_bt_ud->bt;
+ tmp_bt_flags_ptr = &split_bt_ud->cache_flags;
}
} /* end if */
else {
tmp_bt = bt;
- tmp_bt_flags_ptr = &bt_flags;
+ tmp_bt_flags_ptr = &bt_ud->cache_flags;
} /* end else */
/* Insert the child */
- if(H5B_insert_child(tmp_bt, tmp_bt_flags_ptr, idx, child_addr, my_ins, md_key) < 0)
+ if(H5B_insert_child(tmp_bt, tmp_bt_flags_ptr, idx, new_child_bt_ud.addr, my_ins, md_key) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, H5B_INS_ERROR, "can't insert child")
}
@@ -1064,8 +1086,8 @@ H5B_insert_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type
* If this node split, return the mid key (the one that is shared
* by the left and right node).
*/
- if(twin) {
- HDmemcpy(md_key, H5B_NKEY(twin, shared, 0), type->sizeof_nkey);
+ if(split_bt_ud->bt) {
+ HDmemcpy(md_key, H5B_NKEY(split_bt_ud->bt, shared, 0), type->sizeof_nkey);
ret_value = H5B_INS_RIGHT;
#ifdef H5B_DEBUG
/*
@@ -1073,7 +1095,7 @@ H5B_insert_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type
* in the new node.
*/
cmp = (type->cmp2)(H5B_NKEY(bt, shared, bt->nchildren), udata,
- H5B_NKEY(twin, shared, 0));
+ H5B_NKEY(split_bt_ud->bt, shared, 0));
HDassert(0 == cmp);
#endif
} /* end if */
@@ -1081,12 +1103,13 @@ H5B_insert_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type
ret_value = H5B_INS_NOOP;
done:
- {
- herr_t e1 = (bt && H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, bt_flags) < 0);
- herr_t e2 = (twin && H5AC_unprotect(f, dxpl_id, H5AC_BT, *new_node_p, twin, twin_flags) < 0);
- if(e1 || e2) /*use vars to prevent short-circuit of side effects */
- HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, H5B_INS_ERROR, "unable to release node(s)")
- }
+ if(child_bt_ud.bt)
+ if(H5AC_unprotect(f, dxpl_id, H5AC_BT, child_bt_ud.addr, child_bt_ud.bt, child_bt_ud.cache_flags) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, H5B_INS_ERROR, "unable to unprotect child")
+
+ if(new_child_bt_ud.bt)
+ if(H5AC_unprotect(f, dxpl_id, H5AC_BT, new_child_bt_ud.addr, new_child_bt_ud.bt, new_child_bt_ud.cache_flags) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, H5B_INS_ERROR, "unable to unprotect new child")
FUNC_LEAVE_NOAPI(ret_value)
}
diff --git a/src/H5C.c b/src/H5C.c
index 5b7984b..9a7ba81 100644
--- a/src/H5C.c
+++ b/src/H5C.c
@@ -5018,6 +5018,137 @@ H5C_stats__reset(H5C_t UNUSED * cache_ptr)
/*-------------------------------------------------------------------------
+ * Function: H5C_dump_cache
+ *
+ * Purpose: Print a summary of the contents of the metadata cache for
+ * debugging purposes.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 10/10/10
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5C_dump_cache(H5C_t * cache_ptr,
+ const char * cache_name)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+ int i;
+ H5C_cache_entry_t * entry_ptr = NULL;
+ H5SL_t * slist_ptr = NULL;
+ H5SL_node_t * node_ptr = NULL;
+
+ FUNC_ENTER_NOAPI(H5C_dump_cache, FAIL)
+
+ HDassert(cache_ptr != NULL);
+ HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC);
+ HDassert(cache_name != NULL );
+
+ /* First, create a skip list */
+ slist_ptr = H5SL_create(H5SL_TYPE_HADDR);
+
+ if ( slist_ptr == NULL ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTCREATE, FAIL, "can't create skip list.")
+ }
+
+ /* Next, scan the index, and insert all entries in the skip list.
+ * Do this, as we want to display cache entries in increasing address
+ * order.
+ */
+ for ( i = 0; i < H5C__HASH_TABLE_LEN; i++ ) {
+
+ entry_ptr = cache_ptr->index[i];
+
+ while ( entry_ptr != NULL ) {
+
+ HDassert( entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC );
+
+ if ( H5SL_insert(slist_ptr, entry_ptr, &(entry_ptr->addr)) < 0 ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, \
+ "Can't insert entry in skip list")
+ }
+
+ entry_ptr = entry_ptr->ht_next;
+ }
+ }
+
+ /* If we get this far, all entries in the cache are listed in the
+ * skip list -- scan the skip list generating the desired output.
+ */
+
+ HDfprintf(stdout, "\n\nDump of metadata cache \"%s\".\n", cache_name);
+ HDfprintf(stdout,
+ "Num: Addr: Len: Type: Prot: Pinned: Dirty:\n");
+
+ i = 0;
+
+ node_ptr = H5SL_first(slist_ptr);
+
+ if ( node_ptr != NULL ) {
+
+ entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
+
+ } else {
+
+ entry_ptr = NULL;
+ }
+
+ while ( entry_ptr != NULL ) {
+
+ HDassert( entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC );
+
+ HDfprintf(stdout,
+ "%s%d 0x%08llx 0x%3llx %2d %d %d %d\n",
+ cache_ptr->prefix, i,
+ (long long)(entry_ptr->addr),
+ (long long)(entry_ptr->size),
+ (int)(entry_ptr->type->id),
+ (int)(entry_ptr->is_protected),
+ (int)(entry_ptr->is_pinned),
+ (int)(entry_ptr->is_dirty));
+
+ /* increment node_ptr before we delete its target */
+ node_ptr = H5SL_next(node_ptr);
+
+ /* remove the first item in the skip list */
+ if ( H5SL_remove(slist_ptr, &(entry_ptr->addr)) != entry_ptr ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, \
+ "Can't delete entry from skip list.")
+ }
+
+ if ( node_ptr != NULL ) {
+
+ entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
+
+ } else {
+
+ entry_ptr = NULL;
+ }
+
+ i++;
+ }
+
+ HDfprintf(stdout, "\n\n");
+
+ /* Finally, discard the skip list */
+
+ HDassert( H5SL_count(slist_ptr) == 0 );
+
+ H5SL_close(slist_ptr);
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C_dump_cache() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5C_unpin_entry_from_client()
*
* Purpose: Internal routine to unpin a cache entry from a client action.
@@ -7792,7 +7923,7 @@ end_of_inner_loop:
*/
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
- "Pinned entry count not decreasing.")
+ "Pinned entry count not decreasing, cur_pel_len = %d, old_pel_len = %d", (int)cur_pel_len, (int)old_pel_len)
} else if ( ( cur_pel_len == 0 ) && ( old_pel_len == 0 ) ) {
diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h
index 9f10409..0c7631a 100644
--- a/src/H5Cprivate.h
+++ b/src/H5Cprivate.h
@@ -1180,6 +1180,9 @@ H5_DLL herr_t H5C_stats(H5C_t * cache_ptr,
H5_DLL void H5C_stats__reset(H5C_t * cache_ptr);
+H5_DLL herr_t H5C_dump_cache(H5C_t * cache_ptr,
+ const char * cache_name);
+
H5_DLL herr_t H5C_unpin_entry(void *thing);
H5_DLL herr_t H5C_destroy_flush_dependency(void *parent_thing, void *child_thing);
diff --git a/src/H5D.c b/src/H5D.c
index 91a7c3e..667fe1fb 100644
--- a/src/H5D.c
+++ b/src/H5D.c
@@ -256,6 +256,20 @@ H5Dcreate_anon(hid_t loc_id, hid_t type_id, hid_t space_id, hid_t dcpl_id,
HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register dataset")
done:
+ /* Release the dataset's object header, if it was created */
+ if(dset) {
+ H5O_loc_t *oloc; /* Object location for dataset */
+
+ /* Get the new dataset's object location */
+ if(NULL == (oloc = H5D_oloc(dset)))
+ HDONE_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get object location of dataset")
+
+ /* Decrement refcount on dataset's object header in memory */
+ if(H5O_dec_rc_by_loc(oloc, H5AC_dxpl_id) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to decrement refcount on newly created object")
+ } /* end if */
+
+ /* Cleanup on failure */
if(ret_value < 0)
if(dset && H5D_close(dset) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataset")
diff --git a/src/H5Dbtree.c b/src/H5Dbtree.c
index 9fcf1fd..e61811d 100644
--- a/src/H5Dbtree.c
+++ b/src/H5Dbtree.c
@@ -825,7 +825,7 @@ done:
*/
static herr_t
H5D_btree_idx_init(const H5D_chk_idx_info_t *idx_info, const H5S_t UNUSED *space,
- haddr_t UNUSED dset_ohdr_addr)
+ haddr_t dset_ohdr_addr)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -839,6 +839,8 @@ H5D_btree_idx_init(const H5D_chk_idx_info_t *idx_info, const H5S_t UNUSED *space
HDassert(idx_info->storage);
HDassert(H5F_addr_defined(dset_ohdr_addr));
+ idx_info->storage->u.btree.dset_ohdr_addr = dset_ohdr_addr;
+
/* Allocate the shared structure */
if(H5D_btree_shared_create(idx_info->f, idx_info->storage, idx_info->layout->ndims) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create wrapper for shared B-tree info")
diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c
index b14d28d..c0ce03d 100644
--- a/src/H5Dchunk.c
+++ b/src/H5Dchunk.c
@@ -108,7 +108,7 @@ typedef struct H5D_chunk_it_ud1_t {
const H5D_chk_idx_info_t *idx_info; /* Chunked index info */
const H5D_io_info_t *io_info; /* I/O info for dataset operation */
const hsize_t *space_dim; /* New dataset dimensions */
- const hbool_t *shrunk_dim; /* Dimensions which have been shrunk */
+ const hbool_t *shrunk_dim; /* Dimensions which have been shrunk */
H5S_t *chunk_space; /* Dataspace for a chunk */
uint32_t elmts_per_chunk;/* Elements in chunk */
hsize_t *hyper_start; /* Starting location of hyperslab */
@@ -2298,6 +2298,7 @@ H5D_chunk_lookup(const H5D_t *dset, hid_t dxpl_id, const hsize_t *chunk_offset,
udata->common.layout = &(dset->shared->layout.u.chunk);
udata->common.storage = &(dset->shared->layout.storage.u.chunk);
udata->common.offset = chunk_offset;
+ udata->common.rdcc = &(dset->shared->cache.chunk);
/* Reset information about the chunk we are looking for */
udata->nbytes = 0;
@@ -2311,7 +2312,8 @@ H5D_chunk_lookup(const H5D_t *dset, hid_t dxpl_id, const hsize_t *chunk_offset,
ent = dset->shared->cache.chunk.slot[udata->idx_hint];
if(ent)
- for(u = 0, found = TRUE; u < dset->shared->layout.u.chunk.ndims; u++)
+ for(u = 0, found = TRUE; u < dset->shared->layout.u.chunk.ndims - 1;
+ u++)
if(chunk_offset[u] != ent->offset[u]) {
found = FALSE;
break;
@@ -2398,6 +2400,7 @@ H5D_chunk_flush_entry(const H5D_t *dset, hid_t dxpl_id, const H5D_dxpl_cache_t *
udata.common.layout = &dset->shared->layout.u.chunk;
udata.common.storage = &dset->shared->layout.storage.u.chunk;
udata.common.offset = ent->offset;
+ udata.common.rdcc = &(dset->shared->cache.chunk);
udata.filter_mask = 0;
udata.nbytes = dset->shared->layout.u.chunk.size;
udata.addr = ent->chunk_addr;
@@ -3616,7 +3619,7 @@ H5D_chunk_allocate(H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite,
} /* end if */
carry = FALSE;
- } /* end if */
+ } /* end else */
while(!carry) {
#ifndef NDEBUG
@@ -3697,6 +3700,7 @@ H5D_chunk_allocate(H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite,
udata.common.layout = &layout->u.chunk;
udata.common.storage = &layout->storage.u.chunk;
udata.common.offset = chunk_offset;
+ udata.common.rdcc = NULL;
H5_ASSIGN_OVERFLOW(udata.nbytes, chunk_size, size_t, uint32_t);
udata.filter_mask = filter_mask;
udata.addr = HADDR_UNDEF;
@@ -3780,9 +3784,9 @@ H5D_chunk_allocate(H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite,
} /* end for */
} /* end while(!carry) */
- /* Adjust max_unalloc_dim_idx so we don't allocate the same chunk twice.
- * Also check if this dimension started from 0 (and hence allocated all
- * of the chunks. */
+ /* Adjust max_unalloc so we don't allocate the same chunk twice. Also
+ * check if this dimension started from 0 (and hence allocated all of
+ * the chunks. */
if(min_unalloc[op_dim] == 0)
break;
else
@@ -4349,6 +4353,7 @@ H5D_chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id, const hsize_t *old_dim)
HDmemset(&udata, 0, sizeof udata);
udata.common.layout = &layout->u.chunk;
udata.common.storage = &layout->storage.u.chunk;
+ udata.common.rdcc = rdcc;
udata.io_info = &chk_io_info;
udata.idx_info = &idx_info;
udata.space_dim = space_dim;
@@ -4679,7 +4684,8 @@ H5D_chunk_addrmap(const H5D_io_info_t *io_info, haddr_t chunk_addr[])
HDmemset(&udata, 0, sizeof(udata));
udata.common.layout = &dset->shared->layout.u.chunk;
udata.common.storage = &dset->shared->layout.storage.u.chunk;
- udata.chunk_addr = chunk_addr;
+ udata.common.rdcc = &(dset->shared->cache.chunk);
+ udata.chunk_addr = chunk_addr;
/* Compose chunked index info struct */
idx_info.f = dset->oloc.file;
@@ -5026,6 +5032,7 @@ H5D_chunk_copy_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata)
udata_dst.common.layout = udata->idx_info_dst->layout;
udata_dst.common.storage = udata->idx_info_dst->storage;
udata_dst.common.offset = chunk_rec->offset;
+ udata_dst.common.rdcc = NULL;
udata_dst.nbytes = chunk_rec->nbytes;
udata_dst.filter_mask = chunk_rec->filter_mask;
udata_dst.addr = HADDR_UNDEF;
@@ -5289,6 +5296,7 @@ H5D_chunk_copy(H5F_t *f_src, H5O_storage_chunk_t *storage_src,
HDmemset(&udata, 0, sizeof udata);
udata.common.layout = layout_src;
udata.common.storage = storage_src;
+ udata.common.rdcc = NULL;
udata.file_src = f_src;
udata.idx_info_dst = &idx_info_dst;
udata.buf = buf;
diff --git a/src/H5Dint.c b/src/H5Dint.c
index 46f15ea..2b2715b 100644
--- a/src/H5Dint.c
+++ b/src/H5Dint.c
@@ -890,7 +890,7 @@ H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset, hid_t dapl_id)
ohdr_size += layout->storage.u.compact.size;
/* Create an object header for the dataset */
- if(H5O_create(file, dxpl_id, ohdr_size, dset->shared->dcpl_id, oloc/*out*/) < 0)
+ if(H5O_create(file, dxpl_id, ohdr_size, (size_t)1, dset->shared->dcpl_id, oloc/*out*/) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create dataset object header")
HDassert(file == dset->oloc.file);
@@ -1177,6 +1177,8 @@ done:
if(new_dset->shared->type && H5I_dec_ref(new_dset->shared->type_id) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, NULL, "unable to release datatype")
if(H5F_addr_defined(new_dset->oloc.addr)) {
+ if(H5O_dec_rc_by_loc(&(new_dset->oloc), dxpl_id) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, NULL, "unable to decrement refcount on newly created object")
if(H5O_close(&(new_dset->oloc)) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, NULL, "unable to release object header")
if(file) {
diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h
index 45e9870..673dac3 100644
--- a/src/H5Dpkg.h
+++ b/src/H5Dpkg.h
@@ -274,6 +274,9 @@ typedef struct H5D_chunk_common_ud_t {
const H5O_layout_chunk_t *layout; /* Chunk layout description */
const H5O_storage_chunk_t *storage; /* Chunk storage description */
const hsize_t *offset; /* Logical offset of chunk */
+ const struct H5D_rdcc_t *rdcc; /* Chunk cache. Only necessary if the index may
+ * be modified, and if any chunks in the dset
+ * may be cached */
} H5D_chunk_common_ud_t;
/* B-tree callback info for various operations */
diff --git a/src/H5E.c b/src/H5E.c
index 01dd35b..7a81d32 100644
--- a/src/H5E.c
+++ b/src/H5E.c
@@ -170,13 +170,20 @@ H5E_set_default_auto(H5E_t *stk)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5E_set_default_auto)
-#ifdef H5_USE_16_API
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+#ifdef H5_USE_16_API_DEFAULT
stk->auto_op.vers = 1;
- stk->auto_op.u.func1 = (H5E_auto1_t)H5Eprint1;
#else /* H5_USE_16_API */
stk->auto_op.vers = 2;
- stk->auto_op.u.func2 = (H5E_auto2_t)H5Eprint2;
-#endif /* H5_USE_16_API */
+#endif /* H5_USE_16_API_DEFAULT */
+
+ stk->auto_op.func1 = stk->auto_op.func1_default = (H5E_auto1_t)H5Eprint1;
+ stk->auto_op.func2 = stk->auto_op.func2_default = (H5E_auto2_t)H5Eprint2;
+ stk->auto_op.is_default = TRUE;
+#else /* H5_NO_DEPRECATED_SYMBOLS */
+ stk->auto_op.func2 = (H5E_auto2_t)H5Eprint2;
+#endif /* H5_NO_DEPRECATED_SYMBOLS */
+
stk->auto_data = NULL;
FUNC_LEAVE_NOAPI(SUCCEED)
@@ -1555,6 +1562,11 @@ done:
* Programmer: Robb Matzke
* Saturday, February 28, 1998
*
+ * Modification:Raymond Lu
+ * 4 October 2010
+ * If the printing function isn't the default H5Eprint1 or 2,
+ * and H5Eset_auto1 has been called to set the old style
+ * printing function, a call to H5Eget_auto2 should fail.
*-------------------------------------------------------------------------
*/
herr_t
@@ -1578,8 +1590,15 @@ H5Eget_auto2(hid_t estack_id, H5E_auto2_t *func, void **client_data)
/* Get the automatic error reporting information */
if(H5E_get_auto(estack, &op, client_data) < 0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get automatic error info")
+
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+ /* Fail if the printing function isn't the default(user-set) and set through H5Eset_auto1 */
+ if(!op.is_default && op.vers == 1)
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "wrong API function, H5Eset_auto1 has been called")
+#endif /* H5_NO_DEPRECATED_SYMBOLS */
+
if(func)
- *func = op.u.func2;
+ *func = op.func2;
done:
FUNC_LEAVE_API(ret_value)
@@ -1606,6 +1625,9 @@ done:
* Programmer: Robb Matzke
* Friday, February 27, 1998
*
+ * Modification:Raymond Lu
+ * 4 October 2010
+ * If the FUNC is H5Eprint2, put the IS_DEFAULT flag on.
*-------------------------------------------------------------------------
*/
herr_t
@@ -1627,9 +1649,23 @@ H5Eset_auto2(hid_t estack_id, H5E_auto2_t func, void *client_data)
if(NULL == (estack = (H5E_t *)H5I_object_verify(estack_id, H5I_ERROR_STACK)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID")
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+ /* Get the automatic error reporting information */
+ if(H5E_get_auto(estack, &op, NULL) < 0)
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get automatic error info")
+
/* Set the automatic error reporting information */
+ if(func != op.func2_default)
+ op.is_default = FALSE;
+ else
+ op.is_default = TRUE;
+
op.vers = 2;
- op.u.func2 = func;
+#endif /* H5_NO_DEPRECATED_SYMBOLS */
+
+ /* Set the automatic error reporting function */
+ op.func2 = func;
+
if(H5E_set_auto(estack, &op, client_data) < 0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "can't set automatic error info")
@@ -1672,7 +1708,11 @@ H5Eauto_is_v2(hid_t estack_id, unsigned *is_stack)
/* Check if the error stack reporting function is the "newer" stack type */
if(is_stack)
+#ifndef H5_NO_DEPRECATED_SYMBOLS
*is_stack = estack->auto_op.vers > 1;
+#else
+ *is_stack = 1;
+#endif
done:
FUNC_LEAVE_API(ret_value)
diff --git a/src/H5Edeprec.c b/src/H5Edeprec.c
index 30f3ae9..0a028d9 100644
--- a/src/H5Edeprec.c
+++ b/src/H5Edeprec.c
@@ -370,6 +370,11 @@ done:
* Programmer: Raymond Lu
* Sep 16, 2003
*
+ * Modification:Raymond Lu
+ * 4 October 2010
+ * If the printing function isn't the default H5Eprint1 or 2,
+ * and H5Eset_auto2 has been called to set the new style
+ * printing function, a call to H5Eget_auto1 should fail.
*-------------------------------------------------------------------------
*/
herr_t
@@ -389,8 +394,13 @@ H5Eget_auto1(H5E_auto1_t *func, void **client_data)
/* Get the automatic error reporting information */
if(H5E_get_auto(estack, &auto_op, client_data) < 0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get automatic error info")
+
+ /* Fail if the printing function isn't the default(user-set) and set through H5Eset_auto2 */
+ if(!auto_op.is_default && auto_op.vers == 2)
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "wrong API function, H5Eset_auto2 has been called")
+
if(func)
- *func = auto_op.u.func1;
+ *func = auto_op.func1;
done:
FUNC_LEAVE_API(ret_value)
@@ -418,6 +428,9 @@ done:
* Programmer: Raymond Lu
* Sep 16, 2003
*
+ * Modification:Raymond Lu
+ * 4 October 2010
+ * If the FUNC is H5Eprint2, put the IS_DEFAULT flag on.
*-------------------------------------------------------------------------
*/
herr_t
@@ -434,9 +447,18 @@ H5Eset_auto1(H5E_auto1_t func, void *client_data)
if(NULL == (estack = H5E_get_my_stack())) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */
HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack")
+ /* Get the automatic error reporting information */
+ if(H5E_get_auto(estack, &auto_op, NULL) < 0)
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get automatic error info")
+
/* Set the automatic error reporting information */
auto_op.vers = 1;
- auto_op.u.func1 = func;
+ if(func != auto_op.func1_default)
+ auto_op.is_default = FALSE;
+ else
+ auto_op.is_default = TRUE;
+ auto_op.func1 = func;
+
if(H5E_set_auto(estack, &auto_op, client_data) < 0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "can't set automatic error info")
diff --git a/src/H5Eint.c b/src/H5Eint.c
index 584ba40..f650581 100644
--- a/src/H5Eint.c
+++ b/src/H5Eint.c
@@ -1011,18 +1011,20 @@ H5E_dump_api_stack(hbool_t is_api)
H5E_t *estack = H5E_get_my_stack();
HDassert(estack);
+
+#ifdef H5_NO_DEPRECATED_SYMBOLS
+ if(estack->auto_op.func2)
+ (void)((estack->auto_op.func2)(H5E_DEFAULT, estack->auto_data));
+#else /* H5_NO_DEPRECATED_SYMBOLS */
if(estack->auto_op.vers == 1) {
-#ifndef H5_NO_DEPRECATED_SYMBOLS
- if(estack->auto_op.u.func1)
- (void)((estack->auto_op.u.func1)(estack->auto_data));
-#else /* H5_NO_DEPRECATED_SYMBOLS */
- HDassert(0 && "version 1 error stack dump without deprecated symbols!");
-#endif /* H5_NO_DEPRECATED_SYMBOLS */
+ if(estack->auto_op.func1)
+ (void)((estack->auto_op.func1)(estack->auto_data));
} /* end if */
else {
- if(estack->auto_op.u.func2)
- (void)((estack->auto_op.u.func2)(H5E_DEFAULT, estack->auto_data));
+ if(estack->auto_op.func2)
+ (void)((estack->auto_op.func2)(H5E_DEFAULT, estack->auto_data));
} /* end else */
+#endif /* H5_NO_DEPRECATED_SYMBOLS */
} /* end if */
done:
diff --git a/src/H5Epkg.h b/src/H5Epkg.h
index a85ddc9..9a1163a 100644
--- a/src/H5Epkg.h
+++ b/src/H5Epkg.h
@@ -68,15 +68,20 @@
/****************************/
/* Some syntactic sugar to make the compiler happy with two different kinds of callbacks */
-typedef struct {
- unsigned vers; /* Which version callback to use */
- union {
#ifndef H5_NO_DEPRECATED_SYMBOLS
- H5E_auto1_t func1; /* Old-style callback, NO error stack param. */
-#endif /* H5_NO_DEPRECATED_SYMBOLS */
- H5E_auto2_t func2; /* New-style callback, with error stack param. */
- }u;
+typedef struct {
+ unsigned vers; /* Which version callback to use */
+ hbool_t is_default; /* If the printing function is the library's own. */
+ H5E_auto1_t func1; /* Old-style callback, NO error stack param. */
+ H5E_auto2_t func2; /* New-style callback, with error stack param. */
+ H5E_auto1_t func1_default; /* The saved library's default function - old style. */
+ H5E_auto2_t func2_default; /* The saved library's default function - new style. */
+} H5E_auto_op_t;
+#else /* H5_NO_DEPRECATED_SYMBOLS */
+typedef struct {
+ H5E_auto_t func2; /* Only the new style callback function is available. */
} H5E_auto_op_t;
+#endif /* H5_NO_DEPRECATED_SYMBOLS */
/* Some syntactic sugar to make the compiler happy with two different kinds of callbacks */
typedef struct {
diff --git a/src/H5F.c b/src/H5F.c
index a465759..c32400f 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -1048,7 +1048,7 @@ H5F_dest(H5F_t *f, hid_t dxpl_id, hbool_t flush)
} /* end if */
/* Destroy other components of the file */
- if(H5F_accum_reset(f, dxpl_id) < 0)
+ if(H5F_accum_reset(f, dxpl_id, TRUE) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
if(H5FO_dest(f) < 0)
diff --git a/src/H5Faccum.c b/src/H5Faccum.c
index 2fc53ea..c89ff33 100644
--- a/src/H5Faccum.c
+++ b/src/H5Faccum.c
@@ -111,11 +111,11 @@ H5FL_BLK_DEFINE_STATIC(meta_accum);
*
*-------------------------------------------------------------------------
*/
-htri_t
+herr_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 */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5F_accum_read, FAIL)
@@ -124,90 +124,135 @@ H5F_accum_read(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr,
HDassert(buf);
/* Check if this information is in the metadata accumulator */
- if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && type != H5FD_MEM_DRAW
- && size < H5F_ACCUM_MAX_SIZE) {
- /* Sanity check */
- HDassert(!f->shared->accum.buf || (f->shared->accum.alloc_size >= f->shared->accum.size));
-
- /* Current read adjoins or overlaps with metadata accumulator */
- if(H5F_addr_overlap(addr, size, f->shared->accum.loc, f->shared->accum.size)
- || ((addr + size) == f->shared->accum.loc)
- || (f->shared->accum.loc + f->shared->accum.size) == addr) {
- size_t amount_before; /* Amount to read before current accumulator */
- haddr_t new_addr; /* New address of the accumulator buffer */
- size_t new_size; /* New size of the accumulator buffer */
-
- /* Compute new values for accumulator */
- new_addr = MIN(addr, f->shared->accum.loc);
- new_size = (size_t)(MAX((addr + size), (f->shared->accum.loc + f->shared->accum.size))
- - new_addr);
-
- /* Check if we need more buffer space */
- if(new_size > f->shared->accum.alloc_size) {
- size_t new_alloc_size; /* New size of accumulator */
-
- /* Adjust the buffer size to be a power of 2 that is large enough to hold data */
- new_alloc_size = (size_t)1 << (1 + H5V_log2_gen((uint64_t)(new_size - 1)));
-
- /* Reallocate the metadata accumulator buffer */
- if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, new_alloc_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_alloc_size;
+ if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && type != H5FD_MEM_DRAW) {
+ if(size < H5F_ACCUM_MAX_SIZE) {
+ /* Sanity check */
+ HDassert(!f->shared->accum.buf || (f->shared->accum.alloc_size >= f->shared->accum.size));
+
+ /* Current read adjoins or overlaps with metadata accumulator */
+ if(H5F_addr_overlap(addr, size, f->shared->accum.loc, f->shared->accum.size)
+ || ((addr + size) == f->shared->accum.loc)
+ || (f->shared->accum.loc + f->shared->accum.size) == addr) {
+ size_t amount_before; /* Amount to read before current accumulator */
+ haddr_t new_addr; /* New address of the accumulator buffer */
+ size_t new_size; /* New size of the accumulator buffer */
+
+ /* Compute new values for accumulator */
+ new_addr = MIN(addr, f->shared->accum.loc);
+ new_size = (size_t)(MAX((addr + size), (f->shared->accum.loc + f->shared->accum.size))
+ - new_addr);
+
+ /* Check if we need more buffer space */
+ if(new_size > f->shared->accum.alloc_size) {
+ size_t new_alloc_size; /* New size of accumulator */
+
+ /* Adjust the buffer size to be a power of 2 that is large enough to hold data */
+ new_alloc_size = (size_t)1 << (1 + H5V_log2_gen((uint64_t)(new_size - 1)));
+
+ /* Reallocate the metadata accumulator buffer */
+ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, new_alloc_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_alloc_size;
#ifdef H5_CLEAR_MEMORY
-HDmemset(f->shared->accum.buf + f->shared->accum.size, 0, (f->shared->accum.alloc_size - f->shared->accum.size));
+ 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 */
+ } /* end if */
- /* Read the part before the metadata accumulator */
- if(addr < f->shared->accum.loc) {
- /* Set the amount to read */
- H5_ASSIGN_OVERFLOW(amount_before, (f->shared->accum.loc - addr), hsize_t, size_t);
+ /* Read the part before the metadata accumulator */
+ if(addr < f->shared->accum.loc) {
+ /* Set the amount to read */
+ H5_ASSIGN_OVERFLOW(amount_before, (f->shared->accum.loc - addr), hsize_t, size_t);
- /* Make room for the metadata to read in */
- HDmemmove(f->shared->accum.buf + amount_before, f->shared->accum.buf, f->shared->accum.size);
+ /* Make room for the metadata to read in */
+ HDmemmove(f->shared->accum.buf + amount_before, f->shared->accum.buf, f->shared->accum.size);
- /* Adjust dirty region tracking info, if present */
- if(f->shared->accum.dirty)
- f->shared->accum.dirty_off += amount_before;
+ /* Adjust dirty region tracking info, if present */
+ if(f->shared->accum.dirty)
+ f->shared->accum.dirty_off += amount_before;
- /* Dispatch to driver */
- if(H5FD_read(f->shared->lf, dxpl_id, type, addr, amount_before, f->shared->accum.buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed")
- } /* end if */
- else
- amount_before = 0;
+ /* Dispatch to driver */
+ if(H5FD_read(f->shared->lf, dxpl_id, type, addr, amount_before, f->shared->accum.buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed")
+ } /* end if */
+ else
+ amount_before = 0;
- /* Read the part after the metadata accumulator */
- if((addr + size) > (f->shared->accum.loc + f->shared->accum.size)) {
- size_t amount_after; /* Amount to read at a time */
+ /* Read the part after the metadata accumulator */
+ if((addr + size) > (f->shared->accum.loc + f->shared->accum.size)) {
+ size_t amount_after; /* Amount to read at a time */
- /* Set the amount to read */
- H5_ASSIGN_OVERFLOW(amount_after, ((addr + size) - (f->shared->accum.loc + f->shared->accum.size)), hsize_t, size_t);
+ /* Set the amount to read */
+ H5_ASSIGN_OVERFLOW(amount_after, ((addr + size) - (f->shared->accum.loc + f->shared->accum.size)), hsize_t, size_t);
- /* Dispatch to driver */
- if(H5FD_read(f->shared->lf, dxpl_id, type, (f->shared->accum.loc + f->shared->accum.size), amount_after, (f->shared->accum.buf + f->shared->accum.size + amount_before)) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed")
- } /* end if */
+ /* Dispatch to driver */
+ if(H5FD_read(f->shared->lf, dxpl_id, type, (f->shared->accum.loc + f->shared->accum.size), amount_after, (f->shared->accum.buf + f->shared->accum.size + amount_before)) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed")
+ } /* end if */
- /* Copy the data out of the buffer */
- HDmemcpy(buf, f->shared->accum.buf + (addr - new_addr), size);
+ /* Copy the data out of the buffer */
+ HDmemcpy(buf, f->shared->accum.buf + (addr - new_addr), size);
- /* Adjust the accumulator address & size */
- f->shared->accum.loc = new_addr;
- f->shared->accum.size = new_size;
+ /* Adjust the accumulator address & size */
+ f->shared->accum.loc = new_addr;
+ f->shared->accum.size = new_size;
+ } /* end if */
+ /* Current read doesn't overlap with metadata accumulator, read it from file */
+ 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 if */
- /* Current read doesn't overlap with metadata accumulator, read it from file */
else {
- /* Dispatch to driver */
+ /* 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 */
- /* Indicate success */
- HGOTO_DONE(TRUE);
+ /* Check for overlap w/dirty accumulator */
+ /* (Note that this could be improved by updating the non-dirty
+ * information in the accumulator with [some of] the information
+ * just read in. -QAK)
+ */
+ if(f->shared->accum.dirty &&
+ H5F_addr_overlap(addr, size, f->shared->accum.loc + f->shared->accum.dirty_off, f->shared->accum.dirty_len)) {
+ haddr_t dirty_loc = f->shared->accum.loc + f->shared->accum.dirty_off; /* File offset of dirty information */
+ size_t buf_off; /* Offset of dirty region in buffer */
+ size_t dirty_off; /* Offset within dirty region */
+ size_t overlap_size; /* Size of overlap with dirty region */
+
+ /* Check for read starting before beginning dirty region */
+ if(H5F_addr_le(addr, dirty_loc)) {
+ /* Compute offset of dirty region within buffer */
+ buf_off = (size_t)(dirty_loc - addr);
+
+ /* Compute offset within dirty region */
+ dirty_off = 0;
+
+ /* Check for read ending within dirty region */
+ if(H5F_addr_lt(addr + size, dirty_loc + f->shared->accum.dirty_len))
+ overlap_size = (size_t)((addr + size) - buf_off);
+ else /* Access covers whole dirty region */
+ overlap_size = f->shared->accum.dirty_len;
+ } /* end if */
+ else { /* Read starts after beginning of dirty region */
+ /* Compute dirty offset within buffer and overlap size */
+ buf_off = 0;
+ dirty_off = (size_t)(addr - dirty_loc);
+ overlap_size = (size_t)((dirty_loc + f->shared->accum.dirty_len) - addr);
+ } /* end else */
+
+ /* Copy the dirty region to buffer */
+ HDmemcpy((unsigned char *)buf + buf_off, (unsigned char *)f->shared->accum.buf + f->shared->accum.dirty_off + dirty_off, overlap_size);
+ } /* end if */
+ } /* end else */
} /* end if */
+ else {
+ /* 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)
@@ -312,12 +357,6 @@ H5F_accum_adjust(H5F_meta_accum_t *accum, H5FD_t *lf, hid_t dxpl_id,
accum->dirty = FALSE;
} /* end if */
- /* Move remnant of accumulator down */
- HDmemmove(accum->buf, (accum->buf + shrink_size), remnant_size);
-
- /* Adjust accumulator's location */
- accum->loc += shrink_size;
-
/* Adjust dirty region tracking info */
accum->dirty_off -= shrink_size;
} /* end else */
@@ -325,6 +364,15 @@ H5F_accum_adjust(H5F_meta_accum_t *accum, H5FD_t *lf, hid_t dxpl_id,
/* Trim the accumulator's use of its buffer */
accum->size = remnant_size;
+
+ /* When appending, need to adjust location of accumulator */
+ if(H5F_ACCUM_APPEND == adjust) {
+ /* Move remnant of accumulator down */
+ HDmemmove(accum->buf, (accum->buf + shrink_size), remnant_size);
+
+ /* Adjust accumulator's location */
+ accum->loc += shrink_size;
+ } /* end if */
} /* end if */
/* Check for accumulator needing to be reallocated */
@@ -352,8 +400,8 @@ done:
/*-------------------------------------------------------------------------
* Function: H5F_accum_write
*
- * Purpose: Attempts to read some data from the metadata accumulator for
- * a file into a buffer.
+ * Purpose: Attempts to write some data to the metadata accumulator for
+ * a file from a buffer.
*
* Return: Non-negative on success/Negative on failure
*
@@ -363,11 +411,11 @@ done:
*
*-------------------------------------------------------------------------
*/
-htri_t
+herr_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 */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5F_accum_write, FAIL)
@@ -377,248 +425,284 @@ H5F_accum_write(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr,
HDassert(buf);
/* Check for accumulating metadata */
- if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && type != H5FD_MEM_DRAW
- && size < H5F_ACCUM_MAX_SIZE) {
- /* Sanity check */
- HDassert(!f->shared->accum.buf || (f->shared->accum.alloc_size >= f->shared->accum.size));
-
- /* Check if there is already metadata in the accumulator */
- if(f->shared->accum.size > 0) {
- /* Check if the new metadata adjoins the beginning of the current accumulator */
- if((addr + size) == f->shared->accum.loc) {
- /* Check if we need to adjust accumulator size */
- if(H5F_accum_adjust(&f->shared->accum, f->shared->lf, dxpl_id, H5F_ACCUM_PREPEND, size) < 0)
- HGOTO_ERROR(H5E_IO, H5E_CANTRESIZE, FAIL, "can't adjust metadata accumulator")
-
- /* 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;
-
- /* Adjust the dirty region and mark accumulator dirty */
- if(f->shared->accum.dirty)
- f->shared->accum.dirty_len = size + f->shared->accum.dirty_off
- + f->shared->accum.dirty_len;
- else {
- f->shared->accum.dirty_len = size;
- f->shared->accum.dirty = TRUE;
- } /* end else */
- f->shared->accum.dirty_off = 0;
- } /* 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 to adjust accumulator size */
- if(H5F_accum_adjust(&f->shared->accum, f->shared->lf, dxpl_id, H5F_ACCUM_APPEND, size) < 0)
- HGOTO_ERROR(H5E_IO, H5E_CANTRESIZE, FAIL, "can't adjust metadata accumulator")
+ if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && type != H5FD_MEM_DRAW) {
+ if(size < H5F_ACCUM_MAX_SIZE) {
+ /* Sanity check */
+ HDassert(!f->shared->accum.buf || (f->shared->accum.alloc_size >= f->shared->accum.size));
+
+ /* Check if there is already metadata in the accumulator */
+ if(f->shared->accum.size > 0) {
+ /* Check if the new metadata adjoins the beginning of the current accumulator */
+ if((addr + size) == f->shared->accum.loc) {
+ /* Check if we need to adjust accumulator size */
+ if(H5F_accum_adjust(&f->shared->accum, f->shared->lf, dxpl_id, H5F_ACCUM_PREPEND, size) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTRESIZE, FAIL, "can't adjust metadata accumulator")
- /* Copy the new metadata to the end */
- HDmemcpy(f->shared->accum.buf + f->shared->accum.size, buf, size);
+ /* Move the existing metadata to the proper location */
+ HDmemmove(f->shared->accum.buf + size, f->shared->accum.buf, f->shared->accum.size);
- /* Adjust the dirty region and mark accumulator dirty */
- if(f->shared->accum.dirty)
- f->shared->accum.dirty_len = size + (f->shared->accum.size -
- f->shared->accum.dirty_off);
- else {
- f->shared->accum.dirty_off = f->shared->accum.size;
- f->shared->accum.dirty_len = size;
- f->shared->accum.dirty = TRUE;
- } /* end else */
+ /* Copy the new metadata at the front */
+ HDmemcpy(f->shared->accum.buf, buf, size);
- /* Set the new size of the metadata accumulator */
- f->shared->accum.size += size;
- } /* end if */
- /* Check if the piece of metadata being written overlaps the metadata accumulator */
- else if(H5F_addr_overlap(addr, size, f->shared->accum.loc, f->shared->accum.size)) {
- size_t add_size; /* New size of the accumulator buffer */
+ /* Set the new size & location of the metadata accumulator */
+ f->shared->accum.loc = addr;
+ f->shared->accum.size += size;
- /* Check if the new metadata is entirely within the current accumulator */
- if(addr >= f->shared->accum.loc && (addr + size) <= (f->shared->accum.loc + f->shared->accum.size)) {
- size_t dirty_off = (size_t)(addr - f->shared->accum.loc);
+ /* Adjust the dirty region and mark accumulator dirty */
+ if(f->shared->accum.dirty)
+ f->shared->accum.dirty_len = size + f->shared->accum.dirty_off
+ + f->shared->accum.dirty_len;
+ else {
+ f->shared->accum.dirty_len = size;
+ f->shared->accum.dirty = TRUE;
+ } /* end else */
+ f->shared->accum.dirty_off = 0;
+ } /* 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 to adjust accumulator size */
+ if(H5F_accum_adjust(&f->shared->accum, f->shared->lf, dxpl_id, H5F_ACCUM_APPEND, size) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTRESIZE, FAIL, "can't adjust metadata accumulator")
- /* Copy the new metadata to the proper location within the accumulator */
- HDmemcpy(f->shared->accum.buf + dirty_off, buf, size);
+ /* Copy the new metadata to the end */
+ HDmemcpy(f->shared->accum.buf + f->shared->accum.size, buf, size);
/* Adjust the dirty region and mark accumulator dirty */
- if(f->shared->accum.dirty) {
- /* Check for new metadata starting before current dirty region */
- if(dirty_off <= f->shared->accum.dirty_off) {
- if((dirty_off + size) <= (f->shared->accum.dirty_off + f->shared->accum.dirty_len))
- f->shared->accum.dirty_len = (f->shared->accum.dirty_off + f->shared->accum.dirty_len) - dirty_off;
- else
- f->shared->accum.dirty_len = size;
- f->shared->accum.dirty_off = dirty_off;
- } /* end if */
- else {
- if((dirty_off + size) <= (f->shared->accum.dirty_off + f->shared->accum.dirty_len))
- ; /* f->shared->accum.dirty_len doesn't change */
- else
- f->shared->accum.dirty_len = (dirty_off + size) - f->shared->accum.dirty_off;
- } /* end else */
- } /* end if */
+ if(f->shared->accum.dirty)
+ f->shared->accum.dirty_len = size + (f->shared->accum.size -
+ f->shared->accum.dirty_off);
else {
- f->shared->accum.dirty_off = dirty_off;
+ f->shared->accum.dirty_off = f->shared->accum.size;
f->shared->accum.dirty_len = size;
f->shared->accum.dirty = TRUE;
} /* end else */
+
+ /* Set the new size of the metadata accumulator */
+ f->shared->accum.size += size;
} /* 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)) {
- size_t old_offset; /* Offset of old data within the accumulator buffer */
+ /* Check if the piece of metadata being written overlaps the metadata accumulator */
+ else if(H5F_addr_overlap(addr, size, f->shared->accum.loc, f->shared->accum.size)) {
+ size_t add_size; /* New size of the accumulator buffer */
+
+ /* Check if the new metadata is entirely within the current accumulator */
+ if(addr >= f->shared->accum.loc && (addr + size) <= (f->shared->accum.loc + f->shared->accum.size)) {
+ size_t dirty_off = (size_t)(addr - f->shared->accum.loc);
+
+ /* Copy the new metadata to the proper location within the accumulator */
+ HDmemcpy(f->shared->accum.buf + dirty_off, buf, size);
+
+ /* Adjust the dirty region and mark accumulator dirty */
+ if(f->shared->accum.dirty) {
+ /* Check for new metadata starting before current dirty region */
+ if(dirty_off <= f->shared->accum.dirty_off) {
+ if((dirty_off + size) <= (f->shared->accum.dirty_off + f->shared->accum.dirty_len))
+ f->shared->accum.dirty_len = (f->shared->accum.dirty_off + f->shared->accum.dirty_len) - dirty_off;
+ else
+ f->shared->accum.dirty_len = size;
+ f->shared->accum.dirty_off = dirty_off;
+ } /* end if */
+ else {
+ if((dirty_off + size) <= (f->shared->accum.dirty_off + f->shared->accum.dirty_len))
+ ; /* f->shared->accum.dirty_len doesn't change */
+ else
+ f->shared->accum.dirty_len = (dirty_off + size) - f->shared->accum.dirty_off;
+ } /* end else */
+ } /* end if */
+ else {
+ f->shared->accum.dirty_off = dirty_off;
+ f->shared->accum.dirty_len = size;
+ f->shared->accum.dirty = TRUE;
+ } /* end else */
+ } /* 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)) {
+ size_t old_offset; /* Offset of old data within the accumulator buffer */
- /* Calculate the amount we will need to add to the accumulator size, based on the amount of overlap */
- H5_ASSIGN_OVERFLOW(add_size, (f->shared->accum.loc - addr), hsize_t, size_t);
+ /* Calculate the amount we will need to add to the accumulator size, based on the amount of overlap */
+ H5_ASSIGN_OVERFLOW(add_size, (f->shared->accum.loc - addr), hsize_t, size_t);
- /* Check if we need to adjust accumulator size */
- if(H5F_accum_adjust(&f->shared->accum, f->shared->lf, dxpl_id, H5F_ACCUM_PREPEND, add_size) < 0)
- HGOTO_ERROR(H5E_IO, H5E_CANTRESIZE, FAIL, "can't adjust metadata accumulator")
+ /* Check if we need to adjust accumulator size */
+ if(H5F_accum_adjust(&f->shared->accum, f->shared->lf, dxpl_id, H5F_ACCUM_PREPEND, add_size) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTRESIZE, FAIL, "can't adjust metadata accumulator")
- /* Calculate the proper offset of the existing metadata */
- H5_ASSIGN_OVERFLOW(old_offset, (addr + size) - f->shared->accum.loc, hsize_t, size_t);
+ /* 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));
+ /* 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);
+ /* 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 += add_size;
+ /* Set the new size & location of the metadata accumulator */
+ f->shared->accum.loc = addr;
+ f->shared->accum.size += add_size;
- /* Adjust the dirty region and mark accumulator dirty */
- if(f->shared->accum.dirty) {
- size_t curr_dirty_end = add_size + f->shared->accum.dirty_off + f->shared->accum.dirty_len;
+ /* Adjust the dirty region and mark accumulator dirty */
+ if(f->shared->accum.dirty) {
+ size_t curr_dirty_end = add_size + f->shared->accum.dirty_off + f->shared->accum.dirty_len;
- f->shared->accum.dirty_off = 0;
- if(size <= curr_dirty_end)
- f->shared->accum.dirty_len = curr_dirty_end;
- else
+ f->shared->accum.dirty_off = 0;
+ if(size <= curr_dirty_end)
+ f->shared->accum.dirty_len = curr_dirty_end;
+ else
+ f->shared->accum.dirty_len = size;
+ } /* end if */
+ else {
+ f->shared->accum.dirty_off = 0;
f->shared->accum.dirty_len = size;
+ f->shared->accum.dirty = TRUE;
+ } /* end else */
} /* end if */
- else {
- f->shared->accum.dirty_off = 0;
- f->shared->accum.dirty_len = size;
- f->shared->accum.dirty = TRUE;
- } /* end else */
- } /* 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)) {
- size_t dirty_off = (size_t)(addr - f->shared->accum.loc);
+ /* 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)) {
+ size_t dirty_off; /* Offset of dirty region */
- /* Calculate the amount we will need to add to the accumulator size, based on the amount of overlap */
- H5_ASSIGN_OVERFLOW(add_size, (addr + size) - (f->shared->accum.loc + f->shared->accum.size), hsize_t, size_t);
+ /* Calculate the amount we will need to add to the accumulator size, based on the amount of overlap */
+ H5_ASSIGN_OVERFLOW(add_size, (addr + size) - (f->shared->accum.loc + f->shared->accum.size), hsize_t, size_t);
- /* Check if we need to adjust accumulator size */
- if(H5F_accum_adjust(&f->shared->accum, f->shared->lf, dxpl_id, H5F_ACCUM_APPEND, add_size) < 0)
- HGOTO_ERROR(H5E_IO, H5E_CANTRESIZE, FAIL, "can't adjust metadata accumulator")
+ /* Check if we need to adjust accumulator size */
+ if(H5F_accum_adjust(&f->shared->accum, f->shared->lf, dxpl_id, H5F_ACCUM_APPEND, add_size) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTRESIZE, FAIL, "can't adjust metadata accumulator")
- /* Copy the new metadata to the end */
- HDmemcpy(f->shared->accum.buf + dirty_off, buf, size);
+ /* Compute offset of dirty region (after adjusting accumulator) */
+ dirty_off = (size_t)(addr - f->shared->accum.loc);
- /* Set the new size of the metadata accumulator */
- f->shared->accum.size += add_size;
+ /* Copy the new metadata to the end */
+ HDmemcpy(f->shared->accum.buf + dirty_off, buf, size);
- /* Adjust the dirty region and mark accumulator dirty */
- if(f->shared->accum.dirty) {
- /* Check for new metadata starting before current dirty region */
- if(dirty_off <= f->shared->accum.dirty_off) {
- f->shared->accum.dirty_off = dirty_off;
- f->shared->accum.dirty_len = size;
+ /* Set the new size of the metadata accumulator */
+ f->shared->accum.size += add_size;
+
+ /* Adjust the dirty region and mark accumulator dirty */
+ if(f->shared->accum.dirty) {
+ /* Check for new metadata starting before current dirty region */
+ if(dirty_off <= f->shared->accum.dirty_off) {
+ f->shared->accum.dirty_off = dirty_off;
+ f->shared->accum.dirty_len = size;
+ } /* end if */
+ else {
+ f->shared->accum.dirty_len = (dirty_off + size) - f->shared->accum.dirty_off;
+ } /* end else */
} /* end if */
else {
- f->shared->accum.dirty_len = (dirty_off + size) - f->shared->accum.dirty_off;
+ f->shared->accum.dirty_off = dirty_off;
+ f->shared->accum.dirty_len = size;
+ f->shared->accum.dirty = TRUE;
} /* end else */
} /* end if */
+ /* New metadata overlaps both ends of the current accumulator */
else {
- f->shared->accum.dirty_off = dirty_off;
+ /* Check if we need more buffer space */
+ if(size > f->shared->accum.alloc_size) {
+ size_t new_alloc_size; /* New size of accumulator */
+
+ /* Adjust the buffer size to be a power of 2 that is large enough to hold data */
+ new_alloc_size = (size_t)1 << (1 + H5V_log2_gen((uint64_t)(size - 1)));
+
+ /* Reallocate the metadata accumulator buffer */
+ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, new_alloc_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_alloc_size;
+#ifdef H5_CLEAR_MEMORY
+HDmemset(f->shared->accum.buf + size, 0, (f->shared->accum.alloc_size - size));
+#endif /* H5_CLEAR_MEMORY */
+ } /* end if */
+
+ /* Copy the new metadata to the buffer */
+ 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;
+
+ /* Adjust the dirty region and mark accumulator dirty */
+ f->shared->accum.dirty_off = 0;
f->shared->accum.dirty_len = size;
f->shared->accum.dirty = TRUE;
} /* end else */
} /* end if */
- /* New metadata overlaps both ends of the current accumulator */
+ /* New piece of metadata doesn't adjoin or overlap the existing accumulator */
else {
- /* Check if we need more buffer space */
+ /* 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.dirty_off, f->shared->accum.dirty_len, f->shared->accum.buf + f->shared->accum.dirty_off) < 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) {
- size_t new_alloc_size; /* New size of accumulator */
+ size_t new_size; /* New size of accumulator */
/* Adjust the buffer size to be a power of 2 that is large enough to hold data */
- new_alloc_size = (size_t)1 << (1 + H5V_log2_gen((uint64_t)(size - 1)));
+ new_size = (size_t)1 << (1 + H5V_log2_gen((uint64_t)(size - 1)));
- /* Reallocate the metadata accumulator buffer */
- if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, new_alloc_size)))
+ /* Grow the metadata 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_alloc_size;
+ f->shared->accum.alloc_size = new_size;
#ifdef H5_CLEAR_MEMORY
-HDmemset(f->shared->accum.buf + size, 0, (f->shared->accum.alloc_size - size));
+{
+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 */
- /* Copy the new metadata to the buffer */
- HDmemcpy(f->shared->accum.buf, buf, size);
+ /* 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")
- /* Set the new size & location of the metadata accumulator */
+ /* 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;
+ /* Store the piece of metadata in the accumulator */
+ HDmemcpy(f->shared->accum.buf, buf, size);
+
/* Adjust the dirty region and mark accumulator dirty */
f->shared->accum.dirty_off = 0;
f->shared->accum.dirty_len = size;
f->shared->accum.dirty = TRUE;
} /* end else */
} /* end if */
- /* New piece of metadata doesn't adjoin or overlap the existing accumulator */
+ /* No metadata in the accumulator, grab this piece and keep it */
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.dirty_off, f->shared->accum.dirty_len, f->shared->accum.buf + f->shared->accum.dirty_off) < 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 */
+ /* Check if we need to reallocate the buffer */
if(size > f->shared->accum.alloc_size) {
size_t new_size; /* New size of accumulator */
/* Adjust the buffer size to be a power of 2 that is large enough to hold data */
new_size = (size_t)1 << (1 + H5V_log2_gen((uint64_t)(size - 1)));
- /* Grow the metadata accumulator buffer */
+ /* Reallocate the metadata 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;
#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));
-}
+HDmemset(f->shared->accum.buf + size, 0, (f->shared->accum.alloc_size - 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;
@@ -633,42 +717,96 @@ HDmemset(f->shared->accum.buf + clear_size, 0, (f->shared->accum.alloc_size - cl
f->shared->accum.dirty = TRUE;
} /* 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) {
- size_t new_size; /* New size of accumulator */
+ /* 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")
+
+ /* Check for overlap w/accumulator */
+ /* (Note that this could be improved by updating the accumulator
+ * with [some of] the information just read in. -QAK)
+ */
+ if(H5F_addr_overlap(addr, size, f->shared->accum.loc, f->shared->accum.size)) {
+ /* Check for write starting before beginning of accumulator */
+ if(H5F_addr_le(addr, f->shared->accum.loc)) {
+ /* Check for write ending within accumulator */
+ if(H5F_addr_le(addr + size, f->shared->accum.loc + f->shared->accum.size)) {
+ size_t overlap_size; /* Size of overlapping region */
+
+ /* Compute overlap size */
+ overlap_size = (size_t)((addr + size) - f->shared->accum.loc);
+
+ /* Check for dirty region */
+ if(f->shared->accum.dirty) {
+ haddr_t dirty_start = f->shared->accum.loc + f->shared->accum.dirty_off; /* File address of start of dirty region */
+ haddr_t dirty_end = dirty_start + f->shared->accum.dirty_len; /* File address of end of dirty region */
+
+ /* Check if entire dirty region is overwritten */
+ if(H5F_addr_le(dirty_end, addr + size)) {
+ f->shared->accum.dirty = FALSE;
+ f->shared->accum.dirty_len = 0;
+ } /* end if */
+ else {
+ /* Check for dirty region falling after write */
+ if(H5F_addr_le(addr + size, dirty_start))
+ f->shared->accum.dirty_off = overlap_size;
+ else { /* Dirty region overlaps w/written region */
+ f->shared->accum.dirty_off = 0;
+ f->shared->accum.dirty_len -= (size_t)((addr + size) - dirty_start);
+ } /* end else */
+ } /* end if */
+ } /* end if */
- /* Adjust the buffer size to be a power of 2 that is large enough to hold data */
- new_size = (size_t)1 << (1 + H5V_log2_gen((uint64_t)(size - 1)));
+ /* Trim bottom of accumulator off */
+ f->shared->accum.loc += overlap_size;
+ f->shared->accum.size -= overlap_size;
+ HDmemmove(f->shared->accum.buf, f->shared->accum.buf + overlap_size, f->shared->accum.size);
+ } /* end if */
+ else { /* Access covers whole accumulator */
+ /* Reset accumulator, but don't flush */
+ if(H5F_accum_reset(f, dxpl_id, FALSE) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTRESET, FAIL, "can't reset accumulator")
+ } /* end else */
+ } /* end if */
+ else { /* Write starts after beginning of accumulator */
+ size_t overlap_size; /* Size of overlapping region */
- /* Reallocate the metadata 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")
+ /* Sanity check */
+ HDassert(H5F_addr_gt(addr + size, f->shared->accum.loc + f->shared->accum.size));
- /* Note the new buffer size */
- f->shared->accum.alloc_size = new_size;
-#ifdef H5_CLEAR_MEMORY
-HDmemset(f->shared->accum.buf + size, 0, (f->shared->accum.alloc_size - size));
-#endif /* H5_CLEAR_MEMORY */
- } /* end if */
+ /* Compute overlap size */
+ overlap_size = (size_t)((f->shared->accum.loc + f->shared->accum.size) - addr);
- /* Update the metadata accumulator information */
- f->shared->accum.loc = addr;
- f->shared->accum.size = size;
+ /* Check for dirty region */
+ if(f->shared->accum.dirty) {
+ haddr_t dirty_start = f->shared->accum.loc + f->shared->accum.dirty_off; /* File address of start of dirty region */
+ haddr_t dirty_end = dirty_start + f->shared->accum.dirty_len; /* File address of end of dirty region */
- /* Store the piece of metadata in the accumulator */
- HDmemcpy(f->shared->accum.buf, buf, size);
+ /* Check if entire dirty region is overwritten */
+ if(H5F_addr_ge(dirty_start, addr)) {
+ f->shared->accum.dirty = FALSE;
+ f->shared->accum.dirty_len = 0;
+ } /* end if */
+ else {
+ /* Check for dirty region falling before write */
+ if(H5F_addr_le(dirty_end, addr))
+ ; /* noop */
+ else /* Dirty region overlaps w/written region */
+ f->shared->accum.dirty_len = (size_t)(addr - dirty_start);
+ } /* end if */
+ } /* end if */
- /* Adjust the dirty region and mark accumulator dirty */
- f->shared->accum.dirty_off = 0;
- f->shared->accum.dirty_len = size;
- f->shared->accum.dirty = TRUE;
+ /* Trim top of accumulator off */
+ f->shared->accum.size -= overlap_size;
+ } /* end else */
+ } /* end if */
} /* end else */
-
- /* Indicate success */
- HGOTO_DONE(TRUE);
} /* end if */
+ else {
+ /* 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)
@@ -775,22 +913,20 @@ H5F_accum_free(H5F_t *f, hid_t dxpl_id, H5FD_mem_t UNUSED type, haddr_t addr,
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
} /* end if */
/* Block to free overlaps with some/all of dirty region */
- else {
+ /* Check for unfreed dirty region to write */
+ else if(H5F_addr_lt(tail_addr, dirty_end)) {
size_t write_size;
+ size_t dirty_delta;
write_size = (size_t)(dirty_end - tail_addr);
+ dirty_delta = f->shared->accum.dirty_len - write_size;
- /* Check for unfreed dirty region to write */
- if(write_size > 0) {
- size_t dirty_delta;
-
- dirty_delta = f->shared->accum.dirty_len - write_size;
+ HDassert(write_size > 0);
- /* Write out the unfreed dirty region of the accumulator */
- if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, dirty_start + dirty_delta, write_size, f->shared->accum.buf + f->shared->accum.dirty_off + dirty_delta) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
- } /* end if */
- } /* end else */
+ /* Write out the unfreed dirty region of the accumulator */
+ if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, dirty_start + dirty_delta, write_size, f->shared->accum.buf + f->shared->accum.dirty_off + dirty_delta) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
+ } /* end if */
/* Reset dirty flag */
f->shared->accum.dirty = FALSE;
@@ -800,19 +936,16 @@ H5F_accum_free(H5F_t *f, hid_t dxpl_id, H5FD_mem_t UNUSED type, haddr_t addr,
/* Check if block to free ends before end of dirty region */
if(H5F_addr_lt(tail_addr, dirty_end)) {
size_t write_size;
+ size_t dirty_delta;
write_size = (size_t)(dirty_end - tail_addr);
+ dirty_delta = f->shared->accum.dirty_len - write_size;
- /* Check for unfreed dirty region to write */
- if(write_size > 0) {
- size_t dirty_delta;
+ HDassert(write_size > 0);
- dirty_delta = f->shared->accum.dirty_len - write_size;
-
- /* Write out the unfreed end of the dirty region of the accumulator */
- if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, dirty_start + dirty_delta, write_size, f->shared->accum.buf + f->shared->accum.dirty_off + dirty_delta) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
- } /* end if */
+ /* Write out the unfreed end of the dirty region of the accumulator */
+ if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, dirty_start + dirty_delta, write_size, f->shared->accum.buf + f->shared->accum.dirty_off + dirty_delta) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
} /* end if */
/* Check for block to free beginning at same location as dirty region */
@@ -822,7 +955,7 @@ H5F_accum_free(H5F_t *f, hid_t dxpl_id, H5FD_mem_t UNUSED type, haddr_t addr,
} /* end if */
/* Block to free eliminates end of dirty region */
else {
- f->shared->accum.dirty_len = (addr - dirty_start);
+ f->shared->accum.dirty_len = (size_t)(addr - dirty_start);
} /* end else */
} /* end else */
@@ -852,7 +985,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5F_accum_flush(H5F_t *f, hid_t dxpl_id)
+H5F_accum_flush(const H5F_t *f, hid_t dxpl_id)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -890,7 +1023,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5F_accum_reset(H5F_t *f, hid_t dxpl_id)
+H5F_accum_reset(const H5F_t *f, hid_t dxpl_id, hbool_t flush)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -899,9 +1032,10 @@ H5F_accum_reset(H5F_t *f, hid_t dxpl_id)
HDassert(f);
HDassert(f->shared);
- /* Flush any dirty data in accumulator */
- if(H5F_accum_flush(f, dxpl_id) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "can't flush metadata accumulator")
+ /* Flush any dirty data in accumulator, if requested */
+ if(flush)
+ if(H5F_accum_flush(f, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "can't flush metadata accumulator")
/* Check if we need to reset the metadata accumulator information */
if(f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) {
diff --git a/src/H5Fio.c b/src/H5Fio.c
index 407f950..231c4c9 100644
--- a/src/H5Fio.c
+++ b/src/H5Fio.c
@@ -95,7 +95,6 @@ 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)
@@ -108,14 +107,9 @@ H5F_block_read(const H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
if(H5F_addr_le(f->shared->tmp_addr, (addr + size)))
HGOTO_ERROR(H5E_IO, H5E_BADRANGE, FAIL, "attempting I/O in temporary file space")
- /* 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 */
+ /* Pass through metadata accumulator layer */
+ if(H5F_accum_read(f, dxpl_id, type, addr, size, buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "read through metadata accumulator failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -141,7 +135,6 @@ 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)
@@ -158,14 +151,9 @@ HDfprintf(stderr, "%s: write to addr = %a, size = %Zu\n", FUNC, addr, size);
if(H5F_addr_le(f->shared->tmp_addr, (addr + size)))
HGOTO_ERROR(H5E_IO, H5E_BADRANGE, FAIL, "attempting I/O in temporary file space")
- /* 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 */
+ /* Pass through metadata accumulator layer */
+ if(H5F_accum_write(f, dxpl_id, type, addr, size, buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "write through metadata accumulator failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index 0d30e53..5bff8c6 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -310,17 +310,18 @@ H5_DLL herr_t H5F_super_free(H5F_super_t *sblock);
H5_DLL herr_t H5F_super_ext_open(H5F_t *f, haddr_t ext_addr, H5O_loc_t *ext_ptr);
H5_DLL herr_t H5F_super_ext_write_msg(H5F_t *f, hid_t dxpl_id, void *mesg, unsigned id, hbool_t may_create);
H5_DLL herr_t H5F_super_ext_remove_msg(H5F_t *f, hid_t dxpl_id, unsigned id);
-H5_DLL herr_t H5F_super_ext_close(H5F_t *f, H5O_loc_t *ext_ptr);
+H5_DLL herr_t H5F_super_ext_close(H5F_t *f, H5O_loc_t *ext_ptr, hid_t dxpl_id,
+ hbool_t was_created);
/* Metadata accumulator routines */
-H5_DLL htri_t H5F_accum_read(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type,
+H5_DLL herr_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,
+H5_DLL herr_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, hid_t dxpl_id);
+H5_DLL herr_t H5F_accum_flush(const H5F_t *f, hid_t dxpl_id);
+H5_DLL herr_t H5F_accum_reset(const H5F_t *f, hid_t dxpl_id, hbool_t flush);
/* Shared file list related routines */
H5_DLL herr_t H5F_sfile_add(H5F_file_t *shared);
diff --git a/src/H5Fsuper.c b/src/H5Fsuper.c
index a259dde..2510487 100644
--- a/src/H5Fsuper.c
+++ b/src/H5Fsuper.c
@@ -204,7 +204,7 @@ H5F_super_ext_create(H5F_t *f, hid_t dxpl_id, H5O_loc_t *ext_ptr)
* extension.
*/
H5O_loc_reset(ext_ptr);
- if(H5O_create(f, dxpl_id, 0, H5P_GROUP_CREATE_DEFAULT, ext_ptr) < 0)
+ if(H5O_create(f, dxpl_id, 0, (size_t)1, H5P_GROUP_CREATE_DEFAULT, ext_ptr) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, FAIL, "unable to create superblock extension")
/* Record the address of the superblock extension */
@@ -267,7 +267,8 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5F_super_ext_close(H5F_t *f, H5O_loc_t *ext_ptr)
+H5F_super_ext_close(H5F_t *f, H5O_loc_t *ext_ptr, hid_t dxpl_id,
+ hbool_t was_created)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -277,6 +278,17 @@ H5F_super_ext_close(H5F_t *f, H5O_loc_t *ext_ptr)
HDassert(f);
HDassert(ext_ptr);
+ /* Check if extension was created */
+ if(was_created) {
+ /* Increment link count on superblock extension's object header */
+ if(H5O_link(ext_ptr, 1, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_LINKCOUNT, FAIL, "unable to increment hard link count")
+
+ /* Decrement refcount on superblock extension's object header in memory */
+ if(H5O_dec_rc_by_loc(ext_ptr, dxpl_id) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "unable to decrement refcount on superblock extension")
+ } /* end if */
+
/* Twiddle the number of open objects to avoid closing the file. */
f->nopen_objs++;
if(H5O_close(ext_ptr) < 0)
@@ -384,7 +396,9 @@ H5F_super_init(H5F_t *f, hid_t dxpl_id)
hsize_t superblock_size; /* Size of superblock, in bytes */
size_t driver_size; /* Size of driver info block (bytes) */
unsigned super_vers = HDF5_SUPERBLOCK_VERSION_DEF; /* Superblock version for file */
+ H5O_loc_t ext_loc; /* Superblock extension object location */
hbool_t need_ext; /* Whether the superblock extension is needed */
+ hbool_t ext_created = FALSE; /* Whether the extension has been created */
herr_t ret_value = SUCCEED; /* Return Value */
FUNC_ENTER_NOAPI_TAG(H5F_super_init, dxpl_id, H5AC__SUPERBLOCK_TAG, FAIL)
@@ -545,8 +559,6 @@ H5F_super_init(H5F_t *f, hid_t dxpl_id)
/* Create the superblock extension for "extra" superblock data, if necessary. */
if(need_ext) {
- H5O_loc_t ext_loc; /* Superblock extension object location */
-
/* The superblock extension isn't actually a group, but the
* default group creation list should work fine.
* If we don't supply a size for the object header, HDF5 will
@@ -557,6 +569,7 @@ H5F_super_init(H5F_t *f, hid_t dxpl_id)
*/
if(H5F_super_ext_create(f, dxpl_id, &ext_loc) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, FAIL, "unable to create superblock extension")
+ ext_created = TRUE;
/* Create the Shared Object Header Message table and register it with
* the metadata cache, if this file supports shared messages.
@@ -615,13 +628,13 @@ H5F_super_init(H5F_t *f, hid_t dxpl_id)
if(H5O_msg_create(&ext_loc, H5O_FSINFO_ID, H5O_MSG_FLAG_DONTSHARE, H5O_UPDATE_TIME, &fsinfo, dxpl_id) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to update free-space info header message")
} /* end if */
-
- /* Close superblock extension */
- if(H5F_super_ext_close(f, &ext_loc) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to close file's superblock extension")
} /* end if */
done:
+ /* Close superblock extension, if it was created */
+ if(ext_created && H5F_super_ext_close(f, &ext_loc, dxpl_id, ext_created) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to close file's superblock extension")
+
/* Cleanup on failure */
if(ret_value < 0) {
/* Check if the superblock has been allocated yet */
@@ -786,7 +799,8 @@ done:
herr_t
H5F_super_ext_write_msg(H5F_t *f, hid_t dxpl_id, void *mesg, unsigned id, hbool_t may_create)
{
- hbool_t sblock_dirty = FALSE; /* Whether superblock was dirtied */
+ hbool_t ext_created = FALSE; /* Whether superblock extension was created */
+ hbool_t ext_opened = FALSE; /* Whether superblock extension was opened */
H5O_loc_t ext_loc; /* "Object location" for superblock extension */
htri_t status; /* Indicate whether the message exists or not */
herr_t ret_value = SUCCEED; /* Return value */
@@ -807,9 +821,10 @@ H5F_super_ext_write_msg(H5F_t *f, hid_t dxpl_id, void *mesg, unsigned id, hbool_
HDassert(may_create);
if(H5F_super_ext_create(f, dxpl_id, &ext_loc) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, FAIL, "unable to create file's superblock extension")
- sblock_dirty = TRUE;
+ ext_created = TRUE;
} /* end else */
HDassert(H5F_addr_defined(ext_loc.addr));
+ ext_opened = TRUE;
/* Check if message with ID does not exist in the object header */
if((status = H5O_msg_exists(&ext_loc, id, dxpl_id)) < 0)
@@ -833,15 +848,14 @@ H5F_super_ext_write_msg(H5F_t *f, hid_t dxpl_id, void *mesg, unsigned id, hbool_
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to write the message in object header")
} /* end else */
- /* Close the superblock extension object header */
- if(H5F_super_ext_close(f, &ext_loc) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to close file's superblock extension")
-
done:
- /* Mark superblock dirty in cache, if necessary */
- if(sblock_dirty)
- if(H5AC_mark_entry_dirty(f->shared->sblock) < 0)
- HDONE_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty")
+ /* Close the superblock extension, if it was opened */
+ if(ext_opened && H5F_super_ext_close(f, &ext_loc, dxpl_id, ext_created) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to close file's superblock extension")
+
+ /* Mark superblock dirty in cache, if superblock extension was created */
+ if(ext_created && H5AC_mark_entry_dirty(f->shared->sblock) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5F_super_ext_write_msg() */
@@ -861,9 +875,10 @@ done:
herr_t
H5F_super_ext_remove_msg(H5F_t *f, hid_t dxpl_id, unsigned id)
{
- htri_t status; /* Indicate whether the message exists or not */
H5O_loc_t ext_loc; /* "Object location" for superblock extension */
+ hbool_t ext_opened = FALSE; /* Whether the superblock extension was opened */
int null_count = 0; /* # of null messages */
+ htri_t status; /* Indicate whether the message exists or not */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5F_super_ext_remove_msg, FAIL)
@@ -874,6 +889,7 @@ H5F_super_ext_remove_msg(H5F_t *f, hid_t dxpl_id, unsigned id)
/* Open superblock extension object header */
if(H5F_super_ext_open(f, f->shared->sblock->ext_addr, &ext_loc) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "error in starting file's superblock extension")
+ ext_opened = TRUE;
/* Check if message with ID exists in the object header */
if((status = H5O_msg_exists(&ext_loc, id, dxpl_id)) < 0)
@@ -902,10 +918,11 @@ H5F_super_ext_remove_msg(H5F_t *f, hid_t dxpl_id, unsigned id)
} /* end if */
} /* end if */
- /* Close superblock extension object header */
- if(H5F_super_ext_close(f, &ext_loc) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to close file's superblock extension")
done:
+ /* Close superblock extension object header, if opened */
+ if(ext_opened && H5F_super_ext_close(f, &ext_loc, dxpl_id, FALSE) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to close file's superblock extension")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* H5F_super_ext_remove_msg() */
diff --git a/src/H5Fsuper_cache.c b/src/H5Fsuper_cache.c
index 4212f97..946fcad 100644
--- a/src/H5Fsuper_cache.c
+++ b/src/H5Fsuper_cache.c
@@ -601,7 +601,7 @@ H5F_sblock_load(H5F_t *f, hid_t dxpl_id, haddr_t UNUSED addr, void *_udata)
} /* end if */
/* Close superblock extension */
- if(H5F_super_ext_close(f, &ext_loc) < 0)
+ if(H5F_super_ext_close(f, &ext_loc, dxpl_id, FALSE) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, NULL, "unable to close file's superblock extension")
} /* end if */
@@ -800,7 +800,7 @@ H5F_sblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t UNUSED addr,
HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "unable to update driver info header message")
/* Close the superblock extension object header */
- if(H5F_super_ext_close(f, &ext_loc) < 0)
+ if(H5F_super_ext_close(f, &ext_loc, dxpl_id, FALSE) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close file's superblock extension")
} /* end if */
} /* end if */
diff --git a/src/H5G.c b/src/H5G.c
index 18e6403..6da8ec6 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -353,6 +353,20 @@ H5Gcreate_anon(hid_t loc_id, hid_t gcpl_id, hid_t gapl_id)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group")
done:
+ /* Release the group's object header, if it was created */
+ if(grp) {
+ H5O_loc_t *oloc; /* Object location for group */
+
+ /* Get the new group's object location */
+ if(NULL == (oloc = H5G_oloc(grp)))
+ HDONE_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get object location of group")
+
+ /* Decrement refcount on group's object header in memory */
+ if(H5O_dec_rc_by_loc(oloc, H5AC_dxpl_id) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "unable to decrement refcount on newly created object")
+ } /* end if */
+
+ /* Cleanup on failure */
if(ret_value < 0)
if(grp && H5G_close(grp) < 0)
HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "unable to release group")
@@ -901,6 +915,8 @@ done:
if(ret_value == NULL) {
/* Check if we need to release the file-oriented symbol table info */
if(oloc_init) {
+ if(H5O_dec_rc_by_loc(&(grp->oloc), dxpl_id) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "unable to decrement refcount on newly created object")
if(H5O_close(&(grp->oloc)) < 0)
HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, NULL, "unable to release object header")
if(H5O_delete(file, dxpl_id, grp->oloc.addr) < 0)
diff --git a/src/H5Gobj.c b/src/H5Gobj.c
index ce11990..b0add06 100644
--- a/src/H5Gobj.c
+++ b/src/H5Gobj.c
@@ -160,8 +160,7 @@ H5G_obj_create(H5F_t *f, hid_t dxpl_id, H5G_obj_create_t *gcrt_info,
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get group info")
/* Call the "real" group creation routine now */
- if(H5G_obj_create_real(f, dxpl_id, &ginfo, &linfo, &pline, gcrt_info, oloc)
- < 0)
+ if(H5G_obj_create_real(f, dxpl_id, &ginfo, &linfo, &pline, gcrt_info, oloc) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, FAIL, "unable to create group")
done:
@@ -264,7 +263,7 @@ H5G_obj_create_real(H5F_t *f, hid_t dxpl_id, const H5O_ginfo_t *ginfo,
* since nothing refers to it yet. The link count will be
* incremented if the object is added to the group directed graph.
*/
- if(H5O_create(f, dxpl_id, hdr_size, gcpl_id, oloc/*out*/) < 0)
+ if(H5O_create(f, dxpl_id, hdr_size, (size_t)1, gcpl_id, oloc/*out*/) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create header")
/* Check for format of group to create */
diff --git a/src/H5Groot.c b/src/H5Groot.c
index a79a5dd..b8ba0fd 100644
--- a/src/H5Groot.c
+++ b/src/H5Groot.c
@@ -148,6 +148,10 @@ H5G_mkroot(H5F_t *f, hid_t dxpl_id, hbool_t create_root)
if(1 != H5O_link(root_loc.oloc, 1, dxpl_id))
HGOTO_ERROR(H5E_SYM, H5E_LINKCOUNT, FAIL, "internal error (wrong link count)")
+ /* Decrement refcount on root group's object header in memory */
+ if(H5O_dec_rc_by_loc(root_loc.oloc, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "unable to decrement refcount on root group's object header")
+
/* Mark superblock dirty, so root group info is flushed */
sblock_dirty = TRUE;
diff --git a/src/H5Gtraverse.c b/src/H5Gtraverse.c
index 4016068..bb8e590 100644
--- a/src/H5Gtraverse.c
+++ b/src/H5Gtraverse.c
@@ -792,15 +792,17 @@ H5G_traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target,
gcrt_info.gcpl_id = H5P_GROUP_CREATE_DEFAULT;
gcrt_info.cache_type = H5G_NOTHING_CACHED;
HDmemset(&gcrt_info.cache, 0, sizeof(gcrt_info.cache));
- if(H5G_obj_create_real(grp_oloc.file, dxpl_id, ginfo, linfo,
- pline, &gcrt_info, obj_loc.oloc/*out*/) < 0)
+ if(H5G_obj_create_real(grp_oloc.file, dxpl_id, ginfo, linfo, pline, &gcrt_info, obj_loc.oloc/*out*/) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create group entry")
/* Insert new group into current group's symbol table */
- if(H5G_loc_insert(&grp_loc, H5G_comp_g, &obj_loc,
- H5O_TYPE_GROUP, &gcrt_info, dxpl_id) < 0)
+ if(H5G_loc_insert(&grp_loc, H5G_comp_g, &obj_loc, H5O_TYPE_GROUP, &gcrt_info, dxpl_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert intermediate group")
+ /* Decrement refcount on intermediate group's object header in memory */
+ if(H5O_dec_rc_by_loc(obj_loc.oloc, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "unable to decrement refcount on newly created object")
+
/* Close new group */
if(H5O_close(obj_loc.oloc) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to close")
diff --git a/src/H5L.c b/src/H5L.c
index 64e194a..9319e2c 100644
--- a/src/H5L.c
+++ b/src/H5L.c
@@ -1664,8 +1664,9 @@ H5L_link_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t UNUSED
H5G_t *grp = NULL; /* H5G_t for this group, opened to pass to user callback */
hid_t grp_id = FAIL; /* Id for this group (passed to user callback */
H5G_loc_t temp_loc; /* For UD callback */
- hbool_t temp_loc_init = FALSE;
- herr_t ret_value = SUCCEED; /* Return value */
+ hbool_t temp_loc_init = FALSE; /* Temporary location for UD callback (temp_loc) has been initialized */
+ hbool_t obj_created = FALSE; /* Whether an object was created (through a hard link) */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5L_link_cb)
@@ -1690,6 +1691,9 @@ H5L_link_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t UNUSED
/* Set object path to use for setting object name (below) */
udata->path = new_loc.path;
+
+ /* Indicate that an object was created */
+ obj_created = TRUE;
} /* end if */
else {
/* Check that both objects are in same file */
@@ -1763,6 +1767,20 @@ H5L_link_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t UNUSED
} /* end if */
done:
+ /* Check if an object was created */
+ if(obj_created) {
+ H5O_loc_t oloc; /* Object location for created object */
+
+ /* Set up object location */
+ HDmemset(&oloc, 0, sizeof(oloc));
+ oloc.file = grp_loc->oloc->file;
+ oloc.addr = udata->lnk->u.hard.addr;
+
+ /* Decrement refcount on superblock extension's object header in memory */
+ if(H5O_dec_rc_by_loc(&oloc, udata->dxpl_id) < 0)
+ HDONE_ERROR(H5E_LINK, H5E_CANTDEC, FAIL, "unable to decrement refcount on newly created object")
+ } /* end if */
+
/* Close the location given to the user callback if it was created */
if(grp_id >= 0) {
if(H5I_dec_app_ref(grp_id) < 0)
diff --git a/src/H5O.c b/src/H5O.c
index 91fad55..2b26963 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -1107,14 +1107,15 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, hid_t ocpl_id,
- H5O_loc_t *loc/*out*/)
+H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, size_t initial_rc,
+ hid_t ocpl_id, H5O_loc_t *loc/*out*/)
{
H5P_genplist_t *oc_plist; /* Object creation property list */
H5O_t *oh = NULL; /* Object header created */
haddr_t oh_addr; /* Address of initial object header */
size_t oh_size; /* Size of initial object header */
uint8_t oh_flags; /* Object header's initial status flags */
+ unsigned insert_flags = H5AC__NO_FLAGS_SET; /* Flags for inserting object header into cache */
hbool_t store_msg_crt_idx; /* Whether to always store message creation indices for this file */
herr_t ret_value = SUCCEED; /* return value */
@@ -1244,11 +1245,18 @@ H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, hid_t ocpl_id,
oh->mesg[0].raw_size = size_hint - (size_t)H5O_SIZEOF_MSGHDR_OH(oh);
oh->mesg[0].chunkno = 0;
+ /* Check for non-zero initial refcount on the object header */
+ if(initial_rc > 0) {
+ /* Set the initial refcount & pin the header when its inserted */
+ oh->rc = initial_rc;
+ insert_flags |= H5AC__PIN_ENTRY_FLAG;
+ } /* end if */
+
/* Set metadata tag in dxpl_id */
H5_BEGIN_TAG(dxpl_id, oh_addr, FAIL);
/* Cache object header */
- if(H5AC_insert_entry(f, dxpl_id, H5AC_OHDR, oh_addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ if(H5AC_insert_entry(f, dxpl_id, H5AC_OHDR, oh_addr, oh, insert_flags) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "unable to cache object header")
oh = NULL;
@@ -3423,6 +3431,49 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5O_dec_rc_by_loc
+ *
+ * Purpose: Decrement the refcount of an object header, using its
+ * object location information.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Oct 08 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_dec_rc_by_loc(const H5O_loc_t *loc, hid_t dxpl_id)
+{
+ H5O_t *oh = NULL; /* Object header */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5O_dec_rc_by_loc, FAIL)
+
+ /* check args */
+ HDassert(loc);
+
+ /* Get header */
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header")
+
+ /* Decrement the reference count on the object header */
+ /* (which will unpin it, if appropriate) */
+ if(H5O_dec_rc(oh) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "unable to decrement reference count on object header")
+
+done:
+ /* Release the object header from the cache */
+ if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_dec_rc_by_loc() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5O_free
*
* Purpose: Destroys an object header.
diff --git a/src/H5Ocache.c b/src/H5Ocache.c
index 9e909a6..e64262b 100644
--- a/src/H5Ocache.c
+++ b/src/H5Ocache.c
@@ -560,6 +560,21 @@ done:
* koziol@ncsa.uiuc.edu
* Mar 20 2003
*
+ * Changes: In the parallel case, there is the possibility that the
+ * the object header may be flushed by different processes
+ * over the life of the computation. Thus we must ensure
+ * that the chunk images are up to date before we mark the
+ * messages clean -- as otherwise we may overwrite valid
+ * data with a blank section of a chunk image.
+ *
+ * To deal with this, I have added code to call
+ * H5O_chunk_serialize() for all chunks before we
+ * mark all messages as clean if we are not destroying the
+ * object. Do this in the parallel case only, as the problem
+ * can only occur in this context.
+ *
+ * JRM -- 10/12/10
+ *
*-------------------------------------------------------------------------
*/
static herr_t
@@ -573,6 +588,30 @@ H5O_clear(H5F_t *f, H5O_t *oh, hbool_t destroy)
/* check args */
HDassert(oh);
+#ifdef H5_HAVE_PARALLEL
+ if ( ( oh->cache_info.is_dirty ) && ( ! destroy ) ) {
+
+ size_t i;
+
+ /* scan through all chunks associated with the object header,
+ * and cause them to update their images for all entries currently
+ * marked dirty. Must do this in the parallel case, as it is possible
+ * that this processor may clear this object header several times
+ * before flushing it -- thus causing undefined sections of the image
+ * to be written to disk overwriting valid data.
+ */
+
+ for ( i = 0; i < oh->nchunks; i++ ) {
+
+ if ( H5O_chunk_serialize(f, oh, i) < 0 ) {
+
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL,
+ "unable to serialize object header chunk")
+ }
+ }
+ }
+#endif /* H5_HAVE_PARALLEL */
+
/* Mark messages as clean */
for(u = 0; u < oh->nmesgs; u++)
oh->mesg[u].dirty = FALSE;
@@ -830,6 +869,30 @@ done:
* koziol@hdfgroup.org
* July 12, 2008
*
+ * Changes: In the parallel case, there is the possibility that the
+ * the object header chunk may be flushed by different
+ * processes over the life of the computation. Thus we must
+ * ensure that the chunk image is up to date before we mark its
+ * messages clean -- as otherwise we may overwrite valid
+ * data with a blank section of a chunk image.
+ *
+ * To deal with this, I have added code to call
+ * H5O_chunk_serialize() for this chunk before we
+ * mark all messages as clean if we are not destroying the
+ * chunk.
+ *
+ * Do this in the parallel case only, as the problem
+ * can only occur in this context.
+ *
+ * Note that at present at least, it seems that this fix
+ * is not necessary, as we don't seem to be able to
+ * generate a dirty chunk without creating a dirty object
+ * header. However, the object header code will be changing
+ * a lot in the near future, so I'll leave this fix in
+ * for now, unless Quincey requests otherwise.
+ *
+ * JRM -- 10/12/10
+ *
*-------------------------------------------------------------------------
*/
static herr_t
@@ -843,6 +906,17 @@ H5O_cache_chk_clear(H5F_t *f, H5O_chunk_proxy_t *chk_proxy, hbool_t destroy)
/* check args */
HDassert(chk_proxy);
+#ifdef H5_HAVE_PARALLEL
+ if ( ( chk_proxy->oh->cache_info.is_dirty ) && ( ! destroy ) ) {
+
+ if ( H5O_chunk_serialize(f, chk_proxy->oh, chk_proxy->chunkno) < 0 ) {
+
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL,
+ "unable to serialize object header chunk")
+ }
+ }
+#endif /* H5_HAVE_PARALLEL */
+
/* Mark messages in chunk as clean */
for(u = 0; u < chk_proxy->oh->nmesgs; u++)
if(chk_proxy->oh->mesg[u].chunkno == chk_proxy->chunkno)
diff --git a/src/H5Opkg.h b/src/H5Opkg.h
index 68b70a5..49cecfd 100644
--- a/src/H5Opkg.h
+++ b/src/H5Opkg.h
@@ -613,6 +613,7 @@ H5_DLL herr_t H5O_num_attrs_test(hid_t oid, hsize_t *nattrs);
H5_DLL herr_t H5O_attr_dense_info_test(hid_t oid, hsize_t *name_count, hsize_t *corder_count);
H5_DLL herr_t H5O_check_msg_marked_test(hid_t oid, hbool_t flag_val);
H5_DLL herr_t H5O_expunge_chunks_test(const H5O_loc_t *oloc, hid_t dxpl_id);
+H5_DLL herr_t H5O_get_rc(const H5O_loc_t *oloc, hid_t dxpl_id, unsigned *rc);
#endif /* H5O_TESTING */
/* Object header debugging routines */
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index 0d10fb9..b4d0e8d 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -392,6 +392,7 @@ typedef struct H5O_storage_contig_t {
} H5O_storage_contig_t;
typedef struct H5O_storage_chunk_btree_t {
+ haddr_t dset_ohdr_addr; /* File address dataset's object header */
H5RC_t *shared; /* Ref-counted shared info for B-tree nodes */
} H5O_storage_chunk_btree_t;
@@ -714,13 +715,14 @@ struct H5P_genplist_t;
/* Object header routines */
H5_DLL herr_t H5O_init(void);
H5_DLL herr_t H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint,
- hid_t ocpl_id, H5O_loc_t *loc/*out*/);
+ size_t initial_rc, hid_t ocpl_id, H5O_loc_t *loc/*out*/);
H5_DLL herr_t H5O_open(H5O_loc_t *loc);
H5_DLL herr_t H5O_close(H5O_loc_t *loc);
H5_DLL int H5O_link(const H5O_loc_t *loc, int adjust, hid_t dxpl_id);
H5_DLL H5O_t *H5O_protect(const H5O_loc_t *loc, hid_t dxpl_id, H5AC_protect_t prot);
H5_DLL H5O_t *H5O_pin(const H5O_loc_t *loc, hid_t dxpl_id);
H5_DLL herr_t H5O_unpin(H5O_t *oh);
+H5_DLL herr_t H5O_dec_rc_by_loc(const H5O_loc_t *loc, hid_t dxpl_id);
H5_DLL herr_t H5O_unprotect(const H5O_loc_t *loc, hid_t dxpl_id, H5O_t *oh,
unsigned oh_flags);
H5_DLL herr_t H5O_touch(const H5O_loc_t *loc, hbool_t force, hid_t dxpl_id);
diff --git a/src/H5Otest.c b/src/H5Otest.c
index 557ac9e..883bfcd 100644
--- a/src/H5Otest.c
+++ b/src/H5Otest.c
@@ -536,3 +536,52 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5O_expunge_chunks_test() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5O_get_rc
+ PURPOSE
+ Retrieve the refcount for the object header
+ USAGE
+ herr_t H5O_expunge_chunks_test(loc, dxpl_id, rc)
+ const H5O_loc_t *loc; IN: Object location for object header to query
+ hid_t dxpl_id; IN: DXPL to use for operation
+ unsigned *rc; OUT: Pointer to refcount for object header
+ RETURNS
+ Non-negative on success, negative on failure
+ DESCRIPTION
+ Protects object header, retrieves the object header's refcount, and
+ unprotects object header.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ DO NOT USE THIS FUNCTION FOR ANYTHING EXCEPT TESTING
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5O_get_rc(const H5O_loc_t *loc, hid_t dxpl_id, unsigned *rc)
+{
+ H5O_t *oh = NULL; /* Object header */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5O_get_rc, FAIL)
+
+ /* Sanity check */
+ HDassert(loc);
+ HDassert(rc);
+
+ /* Get the object header */
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header")
+
+ /* Save the refcount for the object header */
+ *rc = oh->nlink;
+
+done:
+ /* Release the object header */
+ if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5O_expunge_chunks_test() */
+
diff --git a/src/H5Tcommit.c b/src/H5Tcommit.c
index b924b61..e109f95 100644
--- a/src/H5Tcommit.c
+++ b/src/H5Tcommit.c
@@ -302,6 +302,19 @@ H5Tcommit_anon(hid_t loc_id, hid_t type_id, hid_t tcpl_id, hid_t tapl_id)
if(H5T_commit(loc.oloc->file, type, tcpl_id, H5AC_dxpl_id) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to commit datatype")
+ /* Release the datatype's object header */
+ {
+ H5O_loc_t *oloc; /* Object location for datatype */
+
+ /* Get the new committed datatype's object location */
+ if(NULL == (oloc = H5T_oloc(type)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to get object location of committed datatype")
+
+ /* Decrement refcount on committed datatype's object header in memory */
+ if(H5O_dec_rc_by_loc(oloc, H5AC_dxpl_id) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "unable to decrement refcount on newly created object")
+ } /* end if */
+
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Tcommit_anon() */
@@ -379,7 +392,7 @@ H5T_commit(H5F_t *file, H5T_t *type, hid_t tcpl_id, hid_t dxpl_id)
* Create the object header and open it for write access. Insert the data
* type message and then give the object header a name.
*/
- if(H5O_create(file, dxpl_id, dtype_size, tcpl_id, &temp_oloc) < 0)
+ if(H5O_create(file, dxpl_id, dtype_size, (size_t)1, tcpl_id, &temp_oloc) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to create datatype object header")
if(H5O_msg_create(&temp_oloc, H5O_DTYPE_ID, H5O_MSG_FLAG_CONSTANT | H5O_MSG_FLAG_DONTSHARE, H5O_UPDATE_TIME, type, dxpl_id) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to update type header message")
@@ -415,6 +428,8 @@ done:
H5G_name_free(&temp_path);
} /* end if */
if((type->shared->state == H5T_STATE_TRANSIENT || type->shared->state == H5T_STATE_RDONLY) && (type->sh_loc.type == H5O_SHARE_TYPE_COMMITTED)) {
+ if(H5O_dec_rc_by_loc(&(type->oloc), dxpl_id) < 0)
+ HDONE_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "unable to decrement refcount on newly created object")
if(H5O_close(&(type->oloc)) < 0)
HDONE_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to release object header")
if(H5O_delete(file, dxpl_id, type->sh_loc.u.loc.oh_addr) < 0)
diff --git a/src/H5public.h b/src/H5public.h
index 4fc8c7e..b536e0e 100644
--- a/src/H5public.h
+++ b/src/H5public.h
@@ -75,10 +75,10 @@ extern "C" {
/* Version numbers */
#define H5_VERS_MAJOR 1 /* For major interface/format changes */
#define H5_VERS_MINOR 9 /* For minor interface/format changes */
-#define H5_VERS_RELEASE 76 /* For tweaks, bug-fixes, or development */
+#define H5_VERS_RELEASE 77 /* For tweaks, bug-fixes, or development */
#define H5_VERS_SUBRELEASE "FA_a5" /* For pre-releases like snap0 */
/* Empty string for real releases. */
-#define H5_VERS_INFO "HDF5 library version: 1.9.76-FA_a5" /* Full version string */
+#define H5_VERS_INFO "HDF5 library version: 1.9.77-FA_a5" /* Full version string */
#define H5check() H5check_version(H5_VERS_MAJOR,H5_VERS_MINOR, \
H5_VERS_RELEASE)
diff --git a/src/Makefile.in b/src/Makefile.in
index d668dc0..4d3e088 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -457,7 +457,7 @@ CHECK_CLEANFILES = *.chkexe *.chklog *.clog
# Add libtool shared library version numbers to the HDF5 library
# See libtool versioning documentation online.
LT_VERS_INTERFACE = 6
-LT_VERS_REVISION = 66
+LT_VERS_REVISION = 67
LT_VERS_AGE = 0
H5detect_CFLAGS = -g $(AM_CFLAGS)