mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-02-17 16:10:24 +08:00
[svn-r714] Changes since 19980911
---------------------- This checkin is to fix a couple bugs for Jim Reus. Some features are not fully implemented but it shouldn't break anything. ./config/conclude.in ./test/Makefile.in `make clean' removes object files from the test directory as well as a couple more *.h5 temp files. ./config/hpux9.03 [NEW] New config file for HP/UX 9.03 ./src/H5B.c ./src/H5Bprivate.h ./src/H5Fistore.c ./src/H5G.c ./src/H5Gnode.c ./src/H5Gpkg.h ./src/H5Gprivate.h ./src/H5Gstab.c Not-yet-complete version of object removal. ./src/H5Fistore.c ./src/H5Fprivate.h Experimental optimizations, disabled by default. ./src/H5Fprivate.h Default low-level driver was changed to H5F_LOW_SEC instead of H5F_LOW_STDIO because the sec2 driver is much easier to debug. ./src/H5Fsplit.c ./src/H5G.c ./src/H5Z.c Changed a couple return statements to HRETURN. ./src/H5Odtype.c Removed a check for nested compound data types from back when they weren't implemented that raised an error. ./tools/h5tools.c Increased temp buffer sizes and added a check for buffer overflow so we fail an assertion (hopefully). This really needs to be fixed sometime. Added support for printing H5T_STRING data types.
This commit is contained in:
parent
b20de8612a
commit
6d9af58391
@ -69,7 +69,7 @@ uninstall:
|
||||
# remove things like object files but not libraries or executables.
|
||||
#
|
||||
mostlyclean:
|
||||
$(RM) $(LIB_OBJ) $(PROG_OBJ) $(MOSTLYCLEAN)
|
||||
$(RM) $(LIB_OBJ) $(TEST_OBJ) $(PROG_OBJ) $(MOSTLYCLEAN)
|
||||
|
||||
# Like `mostlyclean' except it also removes the final targets: things like
|
||||
# libraries and executables. This target doesn't remove any file that
|
||||
|
38
config/hpux9.03
Normal file
38
config/hpux9.03
Normal file
@ -0,0 +1,38 @@
|
||||
# -*- shell-script -*-
|
||||
#
|
||||
# This file is part of the HDF5 build script. It is processed shortly
|
||||
# after configure starts and defines, among other things, flags for
|
||||
# the various compile modes.
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Compiler flags. The CPPFLAGS values should not include package debug
|
||||
# flags like `-DH5G_DEBUG' since these are added with the
|
||||
# `--enable-debug' switch of configure.
|
||||
|
||||
# What must *always* be present for things to compile correctly?
|
||||
CFLAGS="$CFLAGS -Ae"
|
||||
#CPPFLAGS="$CPPFLAGS -I."
|
||||
|
||||
# What compiler flags should be used for code development?
|
||||
DEBUG_CFLAGS=-g
|
||||
DEBUG_CPPFLAGS=
|
||||
|
||||
# What compiler flags should be used for building a production
|
||||
# library?
|
||||
PROD_CFLAGS=
|
||||
PROD_CPPFLAGS=
|
||||
|
||||
# What compiler flags enable code profiling?
|
||||
PROFILE_CFLAGS=
|
||||
PROFILE_CPPFLAGS=
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Values for overriding configuration tests when cross compiling.
|
||||
# This includes compiling on some machines where the serial front end
|
||||
# compiles for a parallel back end.
|
||||
|
||||
# Set this to `yes' or `no' depending on whether the target is big
|
||||
# endian or little endian.
|
||||
#ac_cv_c_bigendian=${ac_cv_c_bigendian='yes'}
|
291
src/H5B.c
291
src/H5B.c
@ -539,16 +539,17 @@ H5B_find(H5F_t *f, const H5B_class_t *type, const haddr_t *addr, void *udata)
|
||||
}
|
||||
/* compare */
|
||||
if ((cmp = (type->cmp3) (f, bt->key[idx].nkey, udata,
|
||||
bt->key[idx + 1].nkey)) < 0) {
|
||||
bt->key[idx+1].nkey)) < 0) {
|
||||
rt = idx;
|
||||
} else {
|
||||
lt = idx + 1;
|
||||
lt = idx+1;
|
||||
}
|
||||
}
|
||||
if (cmp) {
|
||||
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL,
|
||||
"B-tree key not found");
|
||||
}
|
||||
|
||||
/*
|
||||
* Follow the link to the subtree or to the data node.
|
||||
*/
|
||||
@ -560,7 +561,7 @@ H5B_find(H5F_t *f, const H5B_class_t *type, const haddr_t *addr, void *udata)
|
||||
}
|
||||
} else {
|
||||
ret_value = (type->found) (f, bt->child + idx, bt->key[idx].nkey,
|
||||
udata, bt->key[idx + 1].nkey);
|
||||
udata, bt->key[idx+1].nkey);
|
||||
if (ret_value < 0) {
|
||||
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL,
|
||||
"key not found in leaf node");
|
||||
@ -647,17 +648,17 @@ H5B_split(H5F_t *f, const H5B_class_t *type, H5B_t *old_bt,
|
||||
k * recsize + new_bt->sizeof_rkey);
|
||||
HDmemcpy(new_bt->native,
|
||||
old_bt->native + k * type->sizeof_nkey,
|
||||
(k + 1) * type->sizeof_nkey);
|
||||
(k+1) * type->sizeof_nkey);
|
||||
|
||||
for (i = 0; i <= k; i++) {
|
||||
/* key */
|
||||
new_bt->key[i].dirty = old_bt->key[k + i].dirty;
|
||||
if (old_bt->key[k + i].nkey) {
|
||||
new_bt->key[i].dirty = old_bt->key[k+i].dirty;
|
||||
if (old_bt->key[k+i].nkey) {
|
||||
new_bt->key[i].nkey = new_bt->native + i * type->sizeof_nkey;
|
||||
}
|
||||
/* child */
|
||||
if (i < k) {
|
||||
new_bt->child[i] = old_bt->child[k + i];
|
||||
new_bt->child[i] = old_bt->child[k+i];
|
||||
}
|
||||
}
|
||||
new_bt->ndirty = new_bt->nchildren = k;
|
||||
@ -757,7 +758,7 @@ H5B_decode_keys(H5F_t *f, H5B_t *bt, intn idx)
|
||||
HRETURN_ERROR(H5E_BTREE, H5E_CANTDECODE, FAIL,
|
||||
"unable to decode key");
|
||||
}
|
||||
if (!bt->key[idx + 1].nkey && H5B_decode_key(f, bt, idx + 1) < 0) {
|
||||
if (!bt->key[idx+1].nkey && H5B_decode_key(f, bt, idx+1) < 0) {
|
||||
HRETURN_ERROR(H5E_BTREE, H5E_CANTDECODE, FAIL,
|
||||
"unable to decode key");
|
||||
}
|
||||
@ -972,20 +973,20 @@ H5B_insert_child(H5F_t *f, const H5B_class_t *type, H5B_t *bt,
|
||||
/*
|
||||
* The MD_KEY is the left key of the new node.
|
||||
*/
|
||||
HDmemmove(bt->page + H5B_SIZEOF_HDR(f) + (idx + 1) * recsize,
|
||||
HDmemmove(bt->page + H5B_SIZEOF_HDR(f) + (idx+1) * recsize,
|
||||
bt->page + H5B_SIZEOF_HDR(f) + idx * recsize,
|
||||
(bt->nchildren - idx) * recsize + bt->sizeof_rkey);
|
||||
|
||||
HDmemmove(bt->native + (idx + 1) * type->sizeof_nkey,
|
||||
HDmemmove(bt->native + (idx+1) * type->sizeof_nkey,
|
||||
bt->native + idx * type->sizeof_nkey,
|
||||
((bt->nchildren - idx) + 1) * type->sizeof_nkey);
|
||||
|
||||
for (i = bt->nchildren; i >= idx; --i) {
|
||||
bt->key[i + 1].dirty = bt->key[i].dirty;
|
||||
bt->key[i+1].dirty = bt->key[i].dirty;
|
||||
if (bt->key[i].nkey) {
|
||||
bt->key[i + 1].nkey = bt->native + (i + 1) * type->sizeof_nkey;
|
||||
bt->key[i+1].nkey = bt->native + (i+1) * type->sizeof_nkey;
|
||||
} else {
|
||||
bt->key[i + 1].nkey = NULL;
|
||||
bt->key[i+1].nkey = NULL;
|
||||
}
|
||||
}
|
||||
bt->key[idx].dirty = TRUE;
|
||||
@ -997,26 +998,26 @@ H5B_insert_child(H5F_t *f, const H5B_class_t *type, H5B_t *bt,
|
||||
* The MD_KEY is the right key of the new node.
|
||||
*/
|
||||
HDmemmove(bt->page + (H5B_SIZEOF_HDR(f) +
|
||||
(idx + 1) * recsize + bt->sizeof_rkey),
|
||||
(idx+1) * recsize + bt->sizeof_rkey),
|
||||
bt->page + (H5B_SIZEOF_HDR(f) +
|
||||
idx * recsize + bt->sizeof_rkey),
|
||||
(bt->nchildren - idx) * recsize);
|
||||
|
||||
HDmemmove(bt->native + (idx + 2) * type->sizeof_nkey,
|
||||
bt->native + (idx + 1) * type->sizeof_nkey,
|
||||
HDmemmove(bt->native + (idx+2) * type->sizeof_nkey,
|
||||
bt->native + (idx+1) * type->sizeof_nkey,
|
||||
(bt->nchildren - idx) * type->sizeof_nkey);
|
||||
|
||||
for (i = bt->nchildren; i > idx; --i) {
|
||||
bt->key[i + 1].dirty = bt->key[i].dirty;
|
||||
bt->key[i+1].dirty = bt->key[i].dirty;
|
||||
if (bt->key[i].nkey) {
|
||||
bt->key[i + 1].nkey = bt->native + (i + 1) * type->sizeof_nkey;
|
||||
bt->key[i+1].nkey = bt->native + (i+1) * type->sizeof_nkey;
|
||||
} else {
|
||||
bt->key[i + 1].nkey = NULL;
|
||||
bt->key[i+1].nkey = NULL;
|
||||
}
|
||||
}
|
||||
bt->key[idx + 1].dirty = TRUE;
|
||||
bt->key[idx + 1].nkey = bt->native + (idx + 1) * type->sizeof_nkey;
|
||||
HDmemcpy(bt->key[idx + 1].nkey, md_key, type->sizeof_nkey);
|
||||
bt->key[idx+1].dirty = TRUE;
|
||||
bt->key[idx+1].nkey = bt->native + (idx+1) * type->sizeof_nkey;
|
||||
HDmemcpy(bt->key[idx+1].nkey, md_key, type->sizeof_nkey);
|
||||
}
|
||||
|
||||
HDmemmove(bt->child + idx + 1,
|
||||
@ -1111,7 +1112,7 @@ H5B_insert_helper(H5F_t *f, const haddr_t *addr, const H5B_class_t *type,
|
||||
"unable to decode key");
|
||||
}
|
||||
if ((cmp = (type->cmp3) (f, bt->key[idx].nkey, udata,
|
||||
bt->key[idx + 1].nkey)) < 0) {
|
||||
bt->key[idx+1].nkey)) < 0) {
|
||||
rt = idx;
|
||||
} else {
|
||||
lt = idx + 1;
|
||||
@ -1255,9 +1256,9 @@ H5B_insert_helper(H5F_t *f, const haddr_t *addr, const H5B_class_t *type,
|
||||
"unable to decode key");
|
||||
}
|
||||
my_ins = H5B_INS_RIGHT;
|
||||
HDmemcpy(md_key, bt->key[idx + 1].nkey, type->sizeof_nkey);
|
||||
HDmemcpy(md_key, bt->key[idx+1].nkey, type->sizeof_nkey);
|
||||
if ((type->new_node) (f, H5B_INS_RIGHT, md_key, udata,
|
||||
bt->key[idx + 1].nkey, &child_addr/*out*/) < 0) {
|
||||
bt->key[idx+1].nkey, &child_addr/*out*/) < 0) {
|
||||
HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, H5B_INS_ERROR,
|
||||
"can't insert maximum leaf node");
|
||||
}
|
||||
@ -1268,7 +1269,8 @@ H5B_insert_helper(H5F_t *f, const haddr_t *addr, const H5B_class_t *type,
|
||||
* We couldn't figure out which branch to follow out of this node. THIS
|
||||
* IS A MAJOR PROBLEM THAT NEEDS TO BE FIXED --rpm.
|
||||
*/
|
||||
assert("INTERNAL HDF5 ERROR (see rpm)" && 0);
|
||||
assert("INTERNAL HDF5 ERROR (contact rpm)" && 0);
|
||||
HDabort();
|
||||
|
||||
} else if (bt->level > 0) {
|
||||
/*
|
||||
@ -1278,8 +1280,8 @@ H5B_insert_helper(H5F_t *f, const haddr_t *addr, const H5B_class_t *type,
|
||||
if ((my_ins = H5B_insert_helper(f, bt->child + idx, type,
|
||||
bt->key[idx].nkey, lt_key_changed,
|
||||
md_key, udata,
|
||||
bt->key[idx + 1].nkey, rt_key_changed,
|
||||
&child_addr /*out */ )) < 0) {
|
||||
bt->key[idx+1].nkey, rt_key_changed,
|
||||
&child_addr/*out*/)) < 0) {
|
||||
HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, H5B_INS_ERROR,
|
||||
"can't insert subtree");
|
||||
}
|
||||
@ -1312,11 +1314,11 @@ H5B_insert_helper(H5F_t *f, const haddr_t *addr, const H5B_class_t *type,
|
||||
}
|
||||
if (*rt_key_changed) {
|
||||
bt->dirty = TRUE;
|
||||
bt->key[idx + 1].dirty = TRUE;
|
||||
if (idx + 1 < bt->nchildren) {
|
||||
bt->key[idx+1].dirty = TRUE;
|
||||
if (idx+1 < bt->nchildren) {
|
||||
*rt_key_changed = FALSE;
|
||||
} else {
|
||||
HDmemcpy(rt_key, bt->key[idx + 1].nkey, type->sizeof_nkey);
|
||||
HDmemcpy(rt_key, bt->key[idx+1].nkey, type->sizeof_nkey);
|
||||
}
|
||||
}
|
||||
if (H5B_INS_CHANGE == my_ins) {
|
||||
@ -1325,7 +1327,7 @@ H5B_insert_helper(H5F_t *f, const haddr_t *addr, const H5B_class_t *type,
|
||||
*/
|
||||
bt->child[idx] = child_addr;
|
||||
bt->dirty = TRUE;
|
||||
bt->ndirty = MAX(bt->ndirty, idx + 1);
|
||||
bt->ndirty = MAX(bt->ndirty, idx+1);
|
||||
ret_value = H5B_INS_NOOP;
|
||||
|
||||
} else if (H5B_INS_LEFT == my_ins || H5B_INS_RIGHT == my_ins) {
|
||||
@ -1363,6 +1365,7 @@ H5B_insert_helper(H5F_t *f, const haddr_t *addr, const H5B_class_t *type,
|
||||
"can't insert child");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If this node split, return the mid key (the one that is shared
|
||||
* by the left and right node).
|
||||
@ -1498,6 +1501,228 @@ H5B_iterate (H5F_t *f, const H5B_class_t *type, const haddr_t *addr,
|
||||
FUNC_LEAVE(ret_value);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5B_remove_helper
|
||||
*
|
||||
* Purpose: The recursive part of removing an item from a B-tree. The
|
||||
* sub B-tree that is being considered is located at ADDR and
|
||||
* the item to remove is described by UDATA. If the removed
|
||||
* item falls at the left or right end of the current level then
|
||||
* it might be necessary to adjust the left and/or right keys.
|
||||
*
|
||||
* Return: Success: SUCCEED
|
||||
*
|
||||
* Failure: FAIL
|
||||
*
|
||||
* Programmer: Robb Matzke
|
||||
* Wednesday, September 16, 1998
|
||||
*
|
||||
* Modifications:
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static H5B_ins_t
|
||||
H5B_remove_helper(H5F_t *f, const haddr_t *addr, const H5B_class_t *type,
|
||||
uint8 *lt_key/*out*/, hbool_t *lt_key_changed/*out*/,
|
||||
uint8 *md_key/*out*/, void *udata, uint8 *rt_key/*out*/,
|
||||
hbool_t *rt_key_changed/*out*/)
|
||||
{
|
||||
H5B_t *bt = NULL;
|
||||
H5B_ins_t ret_value = H5B_INS_ERROR;
|
||||
intn idx=-1, lt=0, rt, cmp=1;
|
||||
|
||||
FUNC_ENTER(H5B_remove_helper, FAIL);
|
||||
assert(f);
|
||||
assert(addr && H5F_addr_defined(addr));
|
||||
assert(type);
|
||||
assert(type->decode);
|
||||
assert(type->cmp3);
|
||||
assert(type->found);
|
||||
assert(lt_key && lt_key_changed);
|
||||
assert(md_key);
|
||||
assert(udata);
|
||||
assert(rt_key && rt_key_changed);
|
||||
|
||||
/*
|
||||
* Perform a binary search to locate the child which contains the thing
|
||||
* for which we're searching.
|
||||
*/
|
||||
if (NULL==(bt=H5AC_protect(f, H5AC_BT, addr, type, udata))) {
|
||||
HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL,
|
||||
"unable to load B-tree node");
|
||||
}
|
||||
rt = bt->nchildren;
|
||||
while (lt<rt && cmp) {
|
||||
idx = (lt+rt)/2;
|
||||
if (H5B_decode_keys(f, bt, idx)<0) {
|
||||
HGOTO_ERROR(H5E_BTREE, H5E_CANTDECODE, FAIL,
|
||||
"unable to decode B-tree key(s)");
|
||||
}
|
||||
if ((cmp=(type->cmp3)(f, bt->key[idx].nkey, udata,
|
||||
bt->key[idx+1].nkey))<0) {
|
||||
rt = idx;
|
||||
} else {
|
||||
lt = idx+1;
|
||||
}
|
||||
}
|
||||
if (cmp) {
|
||||
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "B-tree key not found");
|
||||
}
|
||||
|
||||
/*
|
||||
* Follow the link to the subtree or to the data node. The return value
|
||||
* will be one of H5B_INS_ERROR, H5B_INS_NOOP, or H5B_INS_REMOVE.
|
||||
*/
|
||||
assert(idx>=0 && idx<bt->nchildren);
|
||||
if (bt->level>0) {
|
||||
if ((ret_value=H5B_remove_helper(f,
|
||||
bt->child+idx,
|
||||
type,
|
||||
bt->key[idx].nkey/*out*/,
|
||||
lt_key_changed/*out*/,
|
||||
md_key/*out*/,
|
||||
udata,
|
||||
bt->key[idx+1].nkey/*out*/,
|
||||
rt_key_changed/*out*/))<0) {
|
||||
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL,
|
||||
"key not found in subtree");
|
||||
}
|
||||
} else if (type->remove) {
|
||||
if ((ret_value=(type->remove)(f,
|
||||
bt->child+idx,
|
||||
bt->key[idx].nkey,
|
||||
lt_key_changed,
|
||||
md_key,
|
||||
udata,
|
||||
bt->key[idx+1].nkey,
|
||||
rt_key_changed))<0) {
|
||||
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL,
|
||||
"key not found in leaf node");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Update left and right key dirty bits if the subtree indicates that they
|
||||
* have changed. If the subtree's left key changed and the subtree is the
|
||||
* left-most child of the current node then we must update the key in our
|
||||
* parent and indicate that it changed. Similarly, if the rigt subtree
|
||||
* key changed and it's the right most key of this node we must update
|
||||
* our right key and indicate that it changed.
|
||||
*/
|
||||
if (*lt_key_changed) {
|
||||
bt->dirty = TRUE;
|
||||
bt->key[idx].dirty = TRUE;
|
||||
if (idx>0) {
|
||||
*lt_key_changed = FALSE;
|
||||
} else {
|
||||
HDmemcpy(lt_key, bt->key[idx].nkey, type->sizeof_nkey);
|
||||
}
|
||||
}
|
||||
if (*rt_key_changed) {
|
||||
bt->dirty = TRUE;
|
||||
if (idx+1<bt->nchildren) {
|
||||
*rt_key_changed = FALSE;
|
||||
} else {
|
||||
HDmemcpy(rt_key, bt->key[idx+1].nkey, type->sizeof_nkey);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the subtree returned H5B_INS_REMOVE then we should remove the
|
||||
* subtree entry from the current node. There are four cases:
|
||||
*
|
||||
* 1: If the subtree is the only child of this node then remove both
|
||||
* keys and the subtree and return H5B_INS_REMOVE.
|
||||
*
|
||||
* 2: If the subtree is the left-most child of this node then we
|
||||
* discard the left-most key and the left-most child (the child has
|
||||
* already been freed) and shift everything down by one. We copy
|
||||
* the new left-most key into lt_key and notify the caller that the
|
||||
* left key has changed. Return H5B_INS_NOOP.
|
||||
*
|
||||
* 3: If the subtree is the right-most child of this node then we
|
||||
* discard the right-most key and the right-most child (the child
|
||||
* has already been freed). We copy the new right-most key into
|
||||
* rt_key and notify the caller that the right key has changed.
|
||||
* Return H5B_INS_NOOP.
|
||||
*
|
||||
* 4: There are subtrees out of this node to both the left and right of
|
||||
* the subtree being removed. The key to the left of the subtree
|
||||
* and the subtree are removed from this node and all keys and nodes
|
||||
* to the right are shifted left by one place. The subtree has
|
||||
* already been freed). Return H5B_INS_NOOP.
|
||||
*/
|
||||
if (1==bt->nchildren) {
|
||||
HGOTO_ERROR(H5E_BTREE, H5E_UNSUPPORTED, FAIL,
|
||||
"not implemented yet (all node removal)");
|
||||
} else if (0==idx) {
|
||||
HGOTO_ERROR(H5E_BTREE, H5E_UNSUPPORTED, FAIL,
|
||||
"not implemented yet (first node removal)");
|
||||
} else if (idx+1==bt->nchildren) {
|
||||
HGOTO_ERROR(H5E_BTREE, H5E_UNSUPPORTED, FAIL,
|
||||
"not implemented yet (last node removal)");
|
||||
} else {
|
||||
HGOTO_ERROR(H5E_BTREE, H5E_UNSUPPORTED, FAIL,
|
||||
"not implemented yet (middle node removal)");
|
||||
}
|
||||
|
||||
done:
|
||||
if (bt && H5AC_unprotect(f, H5AC_BT, addr, bt)<0) {
|
||||
HRETURN_ERROR(H5E_BTREE, H5E_PROTECT, FAIL,
|
||||
"unable to release node");
|
||||
}
|
||||
FUNC_LEAVE(ret_value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5B_remove
|
||||
*
|
||||
* Purpose: Removes an item from a B-tree.
|
||||
*
|
||||
* Note: The current version does not attempt to rebalance the tree.
|
||||
*
|
||||
* Return: Success: SUCCEED
|
||||
*
|
||||
* Failure: FAIL. Failure includes not being able to
|
||||
* find the object which is to be removed.
|
||||
*
|
||||
* Programmer: Robb Matzke
|
||||
* Wednesday, September 16, 1998
|
||||
*
|
||||
* Modifications:
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5B_remove(H5F_t *f, const H5B_class_t *type, const haddr_t *addr,
|
||||
void *udata)
|
||||
{
|
||||
/* These are defined this way to satisfy alignment constraints */
|
||||
uint64 _lt_key[128], _md_key[128], _rt_key[128];
|
||||
uint8 *lt_key = (uint8*)_lt_key; /*left key*/
|
||||
uint8 *md_key = (uint8*)_md_key; /*middle key*/
|
||||
uint8 *rt_key = (uint8*)_rt_key; /*right key*/
|
||||
hbool_t lt_key_changed = FALSE; /*left key changed?*/
|
||||
hbool_t rt_key_changed = FALSE; /*right key changed?*/
|
||||
|
||||
FUNC_ENTER(H5B_remove, FAIL);
|
||||
assert(f);
|
||||
assert(type);
|
||||
assert(type->sizeof_nkey <= sizeof _lt_key);
|
||||
assert(addr && H5F_addr_defined(addr));
|
||||
|
||||
if (H5B_remove_helper(f, addr, type, lt_key, <_key_changed, md_key,
|
||||
udata, rt_key, &rt_key_changed)<0) {
|
||||
HRETURN_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL,
|
||||
"unable to remove entry from B-tree");
|
||||
}
|
||||
|
||||
FUNC_LEAVE(SUCCEED);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5B_nodesize
|
||||
@ -1744,7 +1969,7 @@ H5B_assert(H5F_t *f, const haddr_t *addr, const H5B_class_t *type,
|
||||
status = H5B_decode_keys(f, bt, i);
|
||||
assert(status >= 0);
|
||||
cmp = (type->cmp2) (f, bt->key[i].nkey, udata,
|
||||
bt->key[i + 1].nkey);
|
||||
bt->key[i+1].nkey);
|
||||
assert(cmp < 0);
|
||||
}
|
||||
}
|
||||
|
131
src/H5Bprivate.h
131
src/H5Bprivate.h
@ -1,14 +1,14 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
* Copyright (C) 1997 National Center for Supercomputing Applications.
|
||||
* All rights reserved.
|
||||
* Copyright (C) 1997 National Center for Supercomputing Applications.
|
||||
* All rights reserved.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
* Created: H5Bprivate.h
|
||||
* Jul 10 1997
|
||||
* Robb Matzke <matzke@llnl.gov>
|
||||
* Created: H5Bprivate.h
|
||||
* Jul 10 1997
|
||||
* Robb Matzke <matzke@llnl.gov>
|
||||
*
|
||||
* Purpose: Private non-prototype header.
|
||||
* Purpose: Private non-prototype header.
|
||||
*
|
||||
* Modifications:
|
||||
*
|
||||
@ -17,7 +17,7 @@
|
||||
#ifndef _H5Bprivate_H
|
||||
#define _H5Bprivate_H
|
||||
|
||||
#include <H5Bpublic.h> /*API prototypes */
|
||||
#include <H5Bpublic.h> /*API prototypes */
|
||||
|
||||
/* Private headers needed by this file */
|
||||
#include <H5private.h>
|
||||
@ -25,35 +25,36 @@
|
||||
|
||||
/*
|
||||
* Feature: Define this constant if you want to check B-tree consistency
|
||||
* after each B-tree operation. Note that this slows down the
|
||||
* library considerably! Debugging the B-tree depends on assert()
|
||||
* being enabled.
|
||||
* after each B-tree operation. Note that this slows down the
|
||||
* library considerably! Debugging the B-tree depends on assert()
|
||||
* being enabled.
|
||||
*/
|
||||
#ifdef NDEBUG
|
||||
# undef H5B_DEBUG
|
||||
#endif
|
||||
#define H5B_MAGIC "TREE" /*tree node magic number */
|
||||
#define H5B_SIZEOF_MAGIC 4 /*size of magic number */
|
||||
#define H5B_SIZEOF_HDR(F) \
|
||||
(H5B_SIZEOF_MAGIC + /*magic number */ \
|
||||
4 + /*type, level, num entries */ \
|
||||
2*H5F_SIZEOF_ADDR(F)) /*left and right sibling addresses */
|
||||
#define H5B_MAGIC "TREE" /*tree node magic number */
|
||||
#define H5B_SIZEOF_MAGIC 4 /*size of magic number */
|
||||
#define H5B_SIZEOF_HDR(F) \
|
||||
(H5B_SIZEOF_MAGIC + /*magic number */ \
|
||||
4 + /*type, level, num entries */ \
|
||||
2*H5F_SIZEOF_ADDR(F)) /*left and right sibling addresses */
|
||||
|
||||
#define H5B_K(F,TYPE) /*K value given file and Btree subclass */ \
|
||||
#define H5B_K(F,TYPE) /*K value given file and Btree subclass */ \
|
||||
((F)->shared->create_parms->btree_k[(TYPE)->id])
|
||||
|
||||
typedef enum H5B_ins_t {
|
||||
H5B_INS_ERROR = -1, /*error return value */
|
||||
H5B_INS_NOOP = 0, /*insert made no changes */
|
||||
H5B_INS_LEFT = 1, /*insert new node to left of cur node */
|
||||
H5B_INS_RIGHT = 2, /*insert new node to right of cur node */
|
||||
H5B_INS_CHANGE = 3, /*change child address for cur node */
|
||||
H5B_INS_FIRST = 4 /*insert first node in (sub)tree */
|
||||
H5B_INS_ERROR = -1, /*error return value */
|
||||
H5B_INS_NOOP = 0, /*insert made no changes */
|
||||
H5B_INS_LEFT = 1, /*insert new node to left of cur node */
|
||||
H5B_INS_RIGHT = 2, /*insert new node to right of cur node */
|
||||
H5B_INS_CHANGE = 3, /*change child address for cur node */
|
||||
H5B_INS_FIRST = 4, /*insert first node in (sub)tree */
|
||||
H5B_INS_REMOVE = 5 /*remove current node */
|
||||
} H5B_ins_t;
|
||||
|
||||
typedef enum H5B_subid_t {
|
||||
H5B_SNODE_ID = 0, /*B-tree is for symbol table nodes */
|
||||
H5B_ISTORE_ID = 1 /*B-tree is for indexed object storage */
|
||||
H5B_SNODE_ID = 0, /*B-tree is for symbol table nodes */
|
||||
H5B_ISTORE_ID = 1 /*B-tree is for indexed object storage */
|
||||
} H5B_subid_t;
|
||||
|
||||
/*
|
||||
@ -63,66 +64,72 @@ typedef enum H5B_subid_t {
|
||||
* has an array of K values indexed by the `id' class field below. The
|
||||
* array is initialized with the HDF5_BTREE_K_DEFAULT macro.
|
||||
*/
|
||||
struct H5B_t; /*forward decl */
|
||||
struct H5B_t; /*forward decl */
|
||||
|
||||
typedef struct H5B_class_t {
|
||||
H5B_subid_t id; /*id as found in file*/
|
||||
size_t sizeof_nkey; /*size of native (memory) key*/
|
||||
size_t (*get_sizeof_rkey) (H5F_t*, const void*); /*raw key size */
|
||||
herr_t (*new_node) (H5F_t*, H5B_ins_t, void*, void*, void*, haddr_t*);
|
||||
intn (*cmp2) (H5F_t*, void*, void*, void*); /*compare 2 keys */
|
||||
intn (*cmp3) (H5F_t*, void*, void*, void*); /*compare 3 keys */
|
||||
herr_t (*found) (H5F_t*, const haddr_t*, const void*, void*,
|
||||
const void*);
|
||||
|
||||
/* insert new data */
|
||||
H5B_ins_t (*insert) (H5F_t*, const haddr_t*, void*, hbool_t*,
|
||||
void*, void*, void*, hbool_t*, haddr_t*);
|
||||
H5B_subid_t id; /*id as found in file*/
|
||||
size_t sizeof_nkey; /*size of native (memory) key*/
|
||||
size_t (*get_sizeof_rkey)(H5F_t*, const void*); /*raw key size */
|
||||
herr_t (*new_node) (H5F_t*, H5B_ins_t, void*, void*, void*, haddr_t*);
|
||||
intn (*cmp2)(H5F_t*, void*, void*, void*); /*compare 2 keys */
|
||||
intn (*cmp3)(H5F_t*, void*, void*, void*); /*compare 3 keys */
|
||||
herr_t (*found)(H5F_t*, const haddr_t*, const void*, void*,
|
||||
const void*);
|
||||
|
||||
/* insert new data */
|
||||
H5B_ins_t (*insert)(H5F_t*, const haddr_t*, void*, hbool_t*,
|
||||
void*, void*, void*, hbool_t*, haddr_t*);
|
||||
|
||||
/* min insert uses min leaf, not new(), similarily for max insert */
|
||||
hbool_t follow_min;
|
||||
hbool_t follow_max;
|
||||
hbool_t follow_min;
|
||||
hbool_t follow_max;
|
||||
|
||||
herr_t (*list) (H5F_t*, const haddr_t*, void*); /*walk leaf nodes*/
|
||||
herr_t (*decode) (H5F_t*, struct H5B_t*, uint8*, void*);
|
||||
herr_t (*encode) (H5F_t*, struct H5B_t*, uint8*, void*);
|
||||
herr_t (*debug_key)(FILE*, intn, intn, const void*, const void*);
|
||||
/* remove existing data */
|
||||
H5B_ins_t (*remove)(H5F_t*, const haddr_t*, void*, hbool_t*,
|
||||
void*, void*, void*, hbool_t*);
|
||||
|
||||
herr_t (*list)(H5F_t*, const haddr_t*, void*); /*walk leaf nodes*/
|
||||
herr_t (*decode)(H5F_t*, struct H5B_t*, uint8*, void*);
|
||||
herr_t (*encode)(H5F_t*, struct H5B_t*, uint8*, void*);
|
||||
herr_t (*debug_key)(FILE*, intn, intn, const void*, const void*);
|
||||
} H5B_class_t;
|
||||
|
||||
/*
|
||||
* The B-tree node as stored in memory...
|
||||
*/
|
||||
typedef struct H5B_key_t {
|
||||
hbool_t dirty; /*native key is more recent than raw key */
|
||||
uint8 *rkey; /*ptr into node->page for raw key */
|
||||
void *nkey; /*null or ptr into node->native for key */
|
||||
hbool_t dirty; /*native key is more recent than raw key */
|
||||
uint8 *rkey; /*ptr into node->page for raw key */
|
||||
void *nkey; /*null or ptr into node->native for key */
|
||||
} H5B_key_t;
|
||||
|
||||
typedef struct H5B_t {
|
||||
const H5B_class_t *type; /*type of tree */
|
||||
size_t sizeof_rkey; /*size of raw (disk) key */
|
||||
hbool_t dirty; /*something in the tree is dirty */
|
||||
intn ndirty; /*num child ptrs to emit */
|
||||
intn level; /*node level */
|
||||
haddr_t left; /*address of left sibling */
|
||||
haddr_t right; /*address of right sibling */
|
||||
intn nchildren; /*number of child pointers */
|
||||
uint8 *page; /*disk page */
|
||||
uint8 *native; /*array of keys in native format */
|
||||
H5B_key_t *key; /*2k+1 key entries */
|
||||
haddr_t *child; /*2k child pointers */
|
||||
const H5B_class_t *type; /*type of tree */
|
||||
size_t sizeof_rkey; /*size of raw (disk) key */
|
||||
hbool_t dirty; /*something in the tree is dirty */
|
||||
intn ndirty; /*num child ptrs to emit */
|
||||
intn level; /*node level */
|
||||
haddr_t left; /*address of left sibling */
|
||||
haddr_t right; /*address of right sibling */
|
||||
intn nchildren; /*number of child pointers */
|
||||
uint8 *page; /*disk page */
|
||||
uint8 *native; /*array of keys in native format */
|
||||
H5B_key_t *key; /*2k+1 key entries */
|
||||
haddr_t *child; /*2k child pointers */
|
||||
} H5B_t;
|
||||
|
||||
/*
|
||||
* Library prototypes.
|
||||
*/
|
||||
herr_t H5B_debug (H5F_t *f, const haddr_t *addr, FILE * stream, intn indent,
|
||||
intn fwidth, const H5B_class_t *type, void *udata);
|
||||
intn fwidth, const H5B_class_t *type, void *udata);
|
||||
herr_t H5B_create (H5F_t *f, const H5B_class_t *type, void *udata, haddr_t *);
|
||||
herr_t H5B_find (H5F_t *f, const H5B_class_t *type, const haddr_t *addr,
|
||||
void *udata);
|
||||
void *udata);
|
||||
herr_t H5B_insert (H5F_t *f, const H5B_class_t *type, const haddr_t *addr,
|
||||
void *udata);
|
||||
void *udata);
|
||||
herr_t H5B_remove(H5F_t *f, const H5B_class_t *type, const haddr_t *addr,
|
||||
void *udata);
|
||||
herr_t H5B_iterate (H5F_t *f, const H5B_class_t *type, const haddr_t *addr,
|
||||
void *udata);
|
||||
#endif
|
||||
|
153
src/H5Distore.c
153
src/H5Distore.c
@ -107,6 +107,7 @@ H5B_class_t H5B_ISTORE[1] = {{
|
||||
H5F_istore_insert, /*insert */
|
||||
FALSE, /*follow min branch? */
|
||||
FALSE, /*follow max branch? */
|
||||
NULL, /*remove */
|
||||
NULL, /*list */
|
||||
H5F_istore_decode_key, /*decode */
|
||||
H5F_istore_encode_key, /*encode */
|
||||
@ -850,11 +851,20 @@ H5F_istore_flush (H5F_t *f)
|
||||
|
||||
FUNC_ENTER (H5F_istore_flush, FAIL);
|
||||
|
||||
#ifdef H5F_RDCC_NEW
|
||||
for (i=0; i<rdcc->nslots; i++) {
|
||||
if (rdcc->slot[i].chunk &&
|
||||
H5F_istore_flush_entry(f, rdcc->slot+i, FALSE)<0) {
|
||||
nerrors++;
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (i=0; i<rdcc->nused; i++) {
|
||||
if (H5F_istore_flush_entry (f, rdcc->slot+i, FALSE)<0) {
|
||||
nerrors++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (nerrors) {
|
||||
HRETURN_ERROR (H5E_IO, H5E_CANTFLUSH, FAIL,
|
||||
"unable to flush one or more raw data chunks");
|
||||
@ -886,6 +896,14 @@ H5F_istore_preempt (H5F_t *f, intn idx)
|
||||
H5F_rdcc_ent_t *ent = rdcc->slot + idx;
|
||||
|
||||
FUNC_ENTER (H5F_istore_preempt, FAIL);
|
||||
|
||||
#ifdef H5F_RDCC_NEW
|
||||
assert(idx>=0 && idx<rdcc->nslots);
|
||||
assert (!ent->locked);
|
||||
|
||||
H5F_istore_flush_entry(f, ent, TRUE);
|
||||
rdcc->nbytes -= ent->chunk_size;
|
||||
#else
|
||||
assert (idx>=0 && idx<rdcc->nused);
|
||||
assert (!ent->locked);
|
||||
|
||||
@ -894,7 +912,8 @@ H5F_istore_preempt (H5F_t *f, intn idx)
|
||||
(rdcc->nused-(idx+1)) * sizeof(H5F_rdcc_ent_t));
|
||||
rdcc->nused -= 1;
|
||||
rdcc->nbytes -= ent->chunk_size;
|
||||
|
||||
#endif
|
||||
|
||||
FUNC_LEAVE (SUCCEED);
|
||||
}
|
||||
|
||||
@ -924,11 +943,20 @@ H5F_istore_dest (H5F_t *f)
|
||||
|
||||
FUNC_ENTER (H5F_istore_dest, FAIL);
|
||||
|
||||
#ifdef H5F_RDCC_NEW
|
||||
for (i=0; i<rdcc->nslots; i++) {
|
||||
if (rdcc->slot[i].chunk &&
|
||||
H5F_istore_preempt(f, i)<0) {
|
||||
nerrors++;
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (i=rdcc->nused-1; i>=0; --i) {
|
||||
if (H5F_istore_preempt(f, i)<0) {
|
||||
nerrors++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (nerrors) {
|
||||
HRETURN_ERROR (H5E_IO, H5E_CANTFLUSH, FAIL,
|
||||
"unable to flush one or more raw data chunks");
|
||||
@ -961,14 +989,31 @@ H5F_istore_dest (H5F_t *f)
|
||||
static herr_t
|
||||
H5F_istore_prune (H5F_t *f, size_t size)
|
||||
{
|
||||
#ifdef H5F_RDCC_NEW
|
||||
intn i, nerrors=0;
|
||||
static intn place=0;
|
||||
H5F_rdcc_t *rdcc = &(f->shared->rdcc);
|
||||
H5F_rdcc_ent_t *ent = NULL;
|
||||
size_t total = f->shared->access_parms->rdcc_nbytes;
|
||||
#else
|
||||
intn i, meth0, meth1, nerrors=0;
|
||||
H5F_rdcc_t *rdcc = &(f->shared->rdcc);
|
||||
H5F_rdcc_ent_t *ent0, *ent1;
|
||||
double w0 = f->shared->access_parms->rdcc_w0;
|
||||
size_t total = f->shared->access_parms->rdcc_nbytes;
|
||||
|
||||
#endif
|
||||
|
||||
FUNC_ENTER (H5F_istore_prune, FAIL);
|
||||
|
||||
#ifdef H5F_RDCC_NEW
|
||||
for (i=0; rdcc->nbytes+size>total && i<rdcc->nslots; i++, place++) {
|
||||
if (place>=rdcc->nslots) place = 0;
|
||||
ent = rdcc->slot+place;
|
||||
if (ent->chunk && !ent->locked) {
|
||||
if (H5F_istore_preempt(f, place)<0) nerrors++;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* We have two pointers that slide down the cache beginning at the least
|
||||
* recently used entry. The distance between the pointers represents the
|
||||
@ -1003,6 +1048,7 @@ H5F_istore_prune (H5F_t *f, size_t size)
|
||||
if (H5F_istore_preempt (f, meth1)<0) nerrors++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (nerrors) {
|
||||
HRETURN_ERROR (H5E_IO, H5E_CANTFLUSH, FAIL,
|
||||
"unable to preempt one or more raw data cache entry");
|
||||
@ -1015,11 +1061,14 @@ H5F_istore_prune (H5F_t *f, size_t size)
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5F_istore_lock
|
||||
*
|
||||
* Purpose: Return a pointer to a file chunk chunk. The pointer
|
||||
* points directly into the chunk cache and should not be freed
|
||||
* Purpose: Return a pointer to a dataset chunk. The pointer points
|
||||
* directly into the chunk cache and should not be freed
|
||||
* by the caller but will be valid until it is unlocked. The
|
||||
* input value IDX_HINT is used to speed up cache lookups and
|
||||
* it's output value should be given to H5F_rdcc_unlock().
|
||||
* IDX_HINT is ignored if it is out of range, and if it points
|
||||
* to the wrong entry then we fall back to the normal search
|
||||
* method.
|
||||
*
|
||||
* If RELAX is non-zero and the chunk isn't in the cache then
|
||||
* don't try to read it from the file, but just allocate an
|
||||
@ -1043,19 +1092,41 @@ H5F_istore_lock (H5F_t *f, const H5O_layout_t *layout,
|
||||
const H5O_pline_t *pline, const hssize_t offset[],
|
||||
hbool_t relax, intn *idx_hint/*in,out*/)
|
||||
{
|
||||
H5F_rdcc_t *rdcc = &(f->shared->rdcc);
|
||||
H5F_rdcc_ent_t *ent = NULL;
|
||||
intn i, j, found = -1;
|
||||
#ifdef H5F_RDCC_NEW
|
||||
uintn idx;
|
||||
#endif
|
||||
H5F_rdcc_t *rdcc = &(f->shared->rdcc);/*raw data chunk cache*/
|
||||
H5F_rdcc_ent_t *ent = NULL; /*cache entry */
|
||||
intn i, j, found = -1; /*counters */
|
||||
H5F_istore_ud1_t udata; /*B-tree pass-through */
|
||||
size_t chunk_size=0; /*size of a chunk */
|
||||
size_t chunk_alloc=0; /*allocated chunk size */
|
||||
herr_t status; /*func return status */
|
||||
void *chunk=NULL; /*the file chunk */
|
||||
void *ret_value=NULL; /*return value */
|
||||
|
||||
|
||||
FUNC_ENTER (H5F_istore_lock, NULL);
|
||||
|
||||
/* First use the hint */
|
||||
#ifdef H5F_RDCC_NEW
|
||||
if (rdcc->nslots>0) {
|
||||
idx = layout->addr.offset;
|
||||
for (i=0; i<layout->ndims; i++) idx ^= offset[i];
|
||||
idx %= rdcc->nslots;
|
||||
ent = rdcc->slot + idx;
|
||||
|
||||
if (ent->chunk &&
|
||||
layout->ndims==ent->layout->ndims &&
|
||||
H5F_addr_eq(&(layout->addr), &(ent->layout->addr))) {
|
||||
for (i=0, found=idx; i<ent->layout->ndims; i++) {
|
||||
if (offset[i]!=ent->offset[i]) {
|
||||
found = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* First use the hint because that's O(1) */
|
||||
if (idx_hint && *idx_hint>=0 && *idx_hint<rdcc->nused) {
|
||||
ent = rdcc->slot + *idx_hint;
|
||||
if (layout->ndims==ent->layout->ndims &&
|
||||
@ -1066,7 +1137,7 @@ H5F_istore_lock (H5F_t *f, const H5O_layout_t *layout,
|
||||
}
|
||||
}
|
||||
|
||||
/* Then look at all the entries */
|
||||
/* If the hint is wrong then search the cache, O(n) */
|
||||
for (i=0; found<0 && i<rdcc->nused; i++) {
|
||||
ent = rdcc->slot + i;
|
||||
if (layout->ndims==ent->layout->ndims &&
|
||||
@ -1076,7 +1147,7 @@ H5F_istore_lock (H5F_t *f, const H5O_layout_t *layout,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (found>=0) {
|
||||
/*
|
||||
@ -1146,6 +1217,39 @@ H5F_istore_lock (H5F_t *f, const H5O_layout_t *layout,
|
||||
}
|
||||
|
||||
assert (found>=0 || chunk_size>0);
|
||||
#ifdef H5F_RDCC_NEW
|
||||
if (found<0 && rdcc->nslots>0 &&
|
||||
chunk_size<=f->shared->access_parms->rdcc_nbytes &&
|
||||
(NULL==ent->chunk || !ent->locked)) {
|
||||
/*
|
||||
* Add the chunk to the cache only if the slot is not already locked.
|
||||
* Preempt enough things from the cache to make room.
|
||||
*/
|
||||
if (H5F_istore_prune(f, chunk_size)<0) {
|
||||
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL,
|
||||
"unable to preempt chunk(s) from cache");
|
||||
}
|
||||
if (rdcc->slot[idx].chunk &&
|
||||
H5F_istore_preempt(f, idx)<0) {
|
||||
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL,
|
||||
"unable to preempt chunk from cache");
|
||||
}
|
||||
ent = rdcc->slot + idx;
|
||||
ent->locked = 0;
|
||||
ent->dirty = FALSE;
|
||||
ent->chunk_size = chunk_size;
|
||||
ent->alloc_size = chunk_size;
|
||||
ent->layout = H5O_copy(H5O_LAYOUT, layout, NULL);
|
||||
ent->pline = H5O_copy(H5O_PLINE, pline, NULL);
|
||||
for (i=0; i<layout->ndims; i++) {
|
||||
ent->offset[i] = offset[i];
|
||||
}
|
||||
ent->rd_count = chunk_size;
|
||||
ent->wr_count = chunk_size;
|
||||
ent->chunk = chunk;
|
||||
found = idx;
|
||||
}
|
||||
#else
|
||||
if (found<0 && chunk_size<=f->shared->access_parms->rdcc_nbytes) {
|
||||
/*
|
||||
* Add the chunk to the beginning of the cache after pruning the cache
|
||||
@ -1183,8 +1287,9 @@ H5F_istore_lock (H5F_t *f, const H5O_layout_t *layout,
|
||||
ent->wr_count = chunk_size;
|
||||
ent->chunk = chunk;
|
||||
found = 0;
|
||||
|
||||
} else if (found<0) {
|
||||
}
|
||||
#endif
|
||||
else if (found<0) {
|
||||
/*
|
||||
* The chunk is larger than the entire cache so we don't cache it.
|
||||
* This is the reason all those arguments have to be repeated for the
|
||||
@ -1192,7 +1297,8 @@ H5F_istore_lock (H5F_t *f, const H5O_layout_t *layout,
|
||||
*/
|
||||
ent = NULL;
|
||||
found = -999;
|
||||
|
||||
|
||||
#ifndef H5F_RDCC_NEW
|
||||
} else if (found>0) {
|
||||
/*
|
||||
* The chunk is not at the beginning of the cache; move it forward by
|
||||
@ -1202,17 +1308,24 @@ H5F_istore_lock (H5F_t *f, const H5O_layout_t *layout,
|
||||
rdcc->slot[found] = rdcc->slot[found-1];
|
||||
rdcc->slot[found-1] = x;
|
||||
ent = rdcc->slot + --found;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Lock the chunk into the cache */
|
||||
if (ent) {
|
||||
assert (!ent->locked);
|
||||
ent->locked = TRUE;
|
||||
#ifndef H5F_RDCC_NEW
|
||||
if (idx_hint) *idx_hint = found;
|
||||
#endif
|
||||
chunk = ent->chunk;
|
||||
}
|
||||
|
||||
#ifdef H5F_RDCC_NEW
|
||||
if (idx_hint) *idx_hint = found;
|
||||
#endif
|
||||
ret_value = chunk;
|
||||
|
||||
done:
|
||||
if (!ret_value) H5MM_xfree (chunk);
|
||||
FUNC_LEAVE (ret_value);
|
||||
@ -1257,6 +1370,15 @@ H5F_istore_unlock (H5F_t *f, const H5O_layout_t *layout,
|
||||
|
||||
FUNC_ENTER (H5F_istore_unlock, FAIL);
|
||||
|
||||
#ifdef H5F_RDCC_NEW
|
||||
if (-999==*idx_hint) {
|
||||
/*not in cache*/
|
||||
} else {
|
||||
assert(*idx_hint>=0 && *idx_hint<rdcc->nslots);
|
||||
assert(rdcc->slot[*idx_hint].chunk==chunk);
|
||||
found = *idx_hint;
|
||||
}
|
||||
#else
|
||||
/* First look at the hint */
|
||||
if (idx_hint && *idx_hint>=0 && *idx_hint<rdcc->nused) {
|
||||
if (rdcc->slot[*idx_hint].chunk==chunk) found = *idx_hint;
|
||||
@ -1266,7 +1388,8 @@ H5F_istore_unlock (H5F_t *f, const H5O_layout_t *layout,
|
||||
for (i=0; found<0 && i<rdcc->nused; i++) {
|
||||
if (rdcc->slot[i].chunk==chunk) found = i;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (found<0) {
|
||||
/*
|
||||
* It's not in the cache, probably because it's too big. If it's
|
||||
|
153
src/H5Fistore.c
153
src/H5Fistore.c
@ -107,6 +107,7 @@ H5B_class_t H5B_ISTORE[1] = {{
|
||||
H5F_istore_insert, /*insert */
|
||||
FALSE, /*follow min branch? */
|
||||
FALSE, /*follow max branch? */
|
||||
NULL, /*remove */
|
||||
NULL, /*list */
|
||||
H5F_istore_decode_key, /*decode */
|
||||
H5F_istore_encode_key, /*encode */
|
||||
@ -850,11 +851,20 @@ H5F_istore_flush (H5F_t *f)
|
||||
|
||||
FUNC_ENTER (H5F_istore_flush, FAIL);
|
||||
|
||||
#ifdef H5F_RDCC_NEW
|
||||
for (i=0; i<rdcc->nslots; i++) {
|
||||
if (rdcc->slot[i].chunk &&
|
||||
H5F_istore_flush_entry(f, rdcc->slot+i, FALSE)<0) {
|
||||
nerrors++;
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (i=0; i<rdcc->nused; i++) {
|
||||
if (H5F_istore_flush_entry (f, rdcc->slot+i, FALSE)<0) {
|
||||
nerrors++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (nerrors) {
|
||||
HRETURN_ERROR (H5E_IO, H5E_CANTFLUSH, FAIL,
|
||||
"unable to flush one or more raw data chunks");
|
||||
@ -886,6 +896,14 @@ H5F_istore_preempt (H5F_t *f, intn idx)
|
||||
H5F_rdcc_ent_t *ent = rdcc->slot + idx;
|
||||
|
||||
FUNC_ENTER (H5F_istore_preempt, FAIL);
|
||||
|
||||
#ifdef H5F_RDCC_NEW
|
||||
assert(idx>=0 && idx<rdcc->nslots);
|
||||
assert (!ent->locked);
|
||||
|
||||
H5F_istore_flush_entry(f, ent, TRUE);
|
||||
rdcc->nbytes -= ent->chunk_size;
|
||||
#else
|
||||
assert (idx>=0 && idx<rdcc->nused);
|
||||
assert (!ent->locked);
|
||||
|
||||
@ -894,7 +912,8 @@ H5F_istore_preempt (H5F_t *f, intn idx)
|
||||
(rdcc->nused-(idx+1)) * sizeof(H5F_rdcc_ent_t));
|
||||
rdcc->nused -= 1;
|
||||
rdcc->nbytes -= ent->chunk_size;
|
||||
|
||||
#endif
|
||||
|
||||
FUNC_LEAVE (SUCCEED);
|
||||
}
|
||||
|
||||
@ -924,11 +943,20 @@ H5F_istore_dest (H5F_t *f)
|
||||
|
||||
FUNC_ENTER (H5F_istore_dest, FAIL);
|
||||
|
||||
#ifdef H5F_RDCC_NEW
|
||||
for (i=0; i<rdcc->nslots; i++) {
|
||||
if (rdcc->slot[i].chunk &&
|
||||
H5F_istore_preempt(f, i)<0) {
|
||||
nerrors++;
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (i=rdcc->nused-1; i>=0; --i) {
|
||||
if (H5F_istore_preempt(f, i)<0) {
|
||||
nerrors++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (nerrors) {
|
||||
HRETURN_ERROR (H5E_IO, H5E_CANTFLUSH, FAIL,
|
||||
"unable to flush one or more raw data chunks");
|
||||
@ -961,14 +989,31 @@ H5F_istore_dest (H5F_t *f)
|
||||
static herr_t
|
||||
H5F_istore_prune (H5F_t *f, size_t size)
|
||||
{
|
||||
#ifdef H5F_RDCC_NEW
|
||||
intn i, nerrors=0;
|
||||
static intn place=0;
|
||||
H5F_rdcc_t *rdcc = &(f->shared->rdcc);
|
||||
H5F_rdcc_ent_t *ent = NULL;
|
||||
size_t total = f->shared->access_parms->rdcc_nbytes;
|
||||
#else
|
||||
intn i, meth0, meth1, nerrors=0;
|
||||
H5F_rdcc_t *rdcc = &(f->shared->rdcc);
|
||||
H5F_rdcc_ent_t *ent0, *ent1;
|
||||
double w0 = f->shared->access_parms->rdcc_w0;
|
||||
size_t total = f->shared->access_parms->rdcc_nbytes;
|
||||
|
||||
#endif
|
||||
|
||||
FUNC_ENTER (H5F_istore_prune, FAIL);
|
||||
|
||||
#ifdef H5F_RDCC_NEW
|
||||
for (i=0; rdcc->nbytes+size>total && i<rdcc->nslots; i++, place++) {
|
||||
if (place>=rdcc->nslots) place = 0;
|
||||
ent = rdcc->slot+place;
|
||||
if (ent->chunk && !ent->locked) {
|
||||
if (H5F_istore_preempt(f, place)<0) nerrors++;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* We have two pointers that slide down the cache beginning at the least
|
||||
* recently used entry. The distance between the pointers represents the
|
||||
@ -1003,6 +1048,7 @@ H5F_istore_prune (H5F_t *f, size_t size)
|
||||
if (H5F_istore_preempt (f, meth1)<0) nerrors++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (nerrors) {
|
||||
HRETURN_ERROR (H5E_IO, H5E_CANTFLUSH, FAIL,
|
||||
"unable to preempt one or more raw data cache entry");
|
||||
@ -1015,11 +1061,14 @@ H5F_istore_prune (H5F_t *f, size_t size)
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5F_istore_lock
|
||||
*
|
||||
* Purpose: Return a pointer to a file chunk chunk. The pointer
|
||||
* points directly into the chunk cache and should not be freed
|
||||
* Purpose: Return a pointer to a dataset chunk. The pointer points
|
||||
* directly into the chunk cache and should not be freed
|
||||
* by the caller but will be valid until it is unlocked. The
|
||||
* input value IDX_HINT is used to speed up cache lookups and
|
||||
* it's output value should be given to H5F_rdcc_unlock().
|
||||
* IDX_HINT is ignored if it is out of range, and if it points
|
||||
* to the wrong entry then we fall back to the normal search
|
||||
* method.
|
||||
*
|
||||
* If RELAX is non-zero and the chunk isn't in the cache then
|
||||
* don't try to read it from the file, but just allocate an
|
||||
@ -1043,19 +1092,41 @@ H5F_istore_lock (H5F_t *f, const H5O_layout_t *layout,
|
||||
const H5O_pline_t *pline, const hssize_t offset[],
|
||||
hbool_t relax, intn *idx_hint/*in,out*/)
|
||||
{
|
||||
H5F_rdcc_t *rdcc = &(f->shared->rdcc);
|
||||
H5F_rdcc_ent_t *ent = NULL;
|
||||
intn i, j, found = -1;
|
||||
#ifdef H5F_RDCC_NEW
|
||||
uintn idx;
|
||||
#endif
|
||||
H5F_rdcc_t *rdcc = &(f->shared->rdcc);/*raw data chunk cache*/
|
||||
H5F_rdcc_ent_t *ent = NULL; /*cache entry */
|
||||
intn i, j, found = -1; /*counters */
|
||||
H5F_istore_ud1_t udata; /*B-tree pass-through */
|
||||
size_t chunk_size=0; /*size of a chunk */
|
||||
size_t chunk_alloc=0; /*allocated chunk size */
|
||||
herr_t status; /*func return status */
|
||||
void *chunk=NULL; /*the file chunk */
|
||||
void *ret_value=NULL; /*return value */
|
||||
|
||||
|
||||
FUNC_ENTER (H5F_istore_lock, NULL);
|
||||
|
||||
/* First use the hint */
|
||||
#ifdef H5F_RDCC_NEW
|
||||
if (rdcc->nslots>0) {
|
||||
idx = layout->addr.offset;
|
||||
for (i=0; i<layout->ndims; i++) idx ^= offset[i];
|
||||
idx %= rdcc->nslots;
|
||||
ent = rdcc->slot + idx;
|
||||
|
||||
if (ent->chunk &&
|
||||
layout->ndims==ent->layout->ndims &&
|
||||
H5F_addr_eq(&(layout->addr), &(ent->layout->addr))) {
|
||||
for (i=0, found=idx; i<ent->layout->ndims; i++) {
|
||||
if (offset[i]!=ent->offset[i]) {
|
||||
found = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* First use the hint because that's O(1) */
|
||||
if (idx_hint && *idx_hint>=0 && *idx_hint<rdcc->nused) {
|
||||
ent = rdcc->slot + *idx_hint;
|
||||
if (layout->ndims==ent->layout->ndims &&
|
||||
@ -1066,7 +1137,7 @@ H5F_istore_lock (H5F_t *f, const H5O_layout_t *layout,
|
||||
}
|
||||
}
|
||||
|
||||
/* Then look at all the entries */
|
||||
/* If the hint is wrong then search the cache, O(n) */
|
||||
for (i=0; found<0 && i<rdcc->nused; i++) {
|
||||
ent = rdcc->slot + i;
|
||||
if (layout->ndims==ent->layout->ndims &&
|
||||
@ -1076,7 +1147,7 @@ H5F_istore_lock (H5F_t *f, const H5O_layout_t *layout,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (found>=0) {
|
||||
/*
|
||||
@ -1146,6 +1217,39 @@ H5F_istore_lock (H5F_t *f, const H5O_layout_t *layout,
|
||||
}
|
||||
|
||||
assert (found>=0 || chunk_size>0);
|
||||
#ifdef H5F_RDCC_NEW
|
||||
if (found<0 && rdcc->nslots>0 &&
|
||||
chunk_size<=f->shared->access_parms->rdcc_nbytes &&
|
||||
(NULL==ent->chunk || !ent->locked)) {
|
||||
/*
|
||||
* Add the chunk to the cache only if the slot is not already locked.
|
||||
* Preempt enough things from the cache to make room.
|
||||
*/
|
||||
if (H5F_istore_prune(f, chunk_size)<0) {
|
||||
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL,
|
||||
"unable to preempt chunk(s) from cache");
|
||||
}
|
||||
if (rdcc->slot[idx].chunk &&
|
||||
H5F_istore_preempt(f, idx)<0) {
|
||||
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL,
|
||||
"unable to preempt chunk from cache");
|
||||
}
|
||||
ent = rdcc->slot + idx;
|
||||
ent->locked = 0;
|
||||
ent->dirty = FALSE;
|
||||
ent->chunk_size = chunk_size;
|
||||
ent->alloc_size = chunk_size;
|
||||
ent->layout = H5O_copy(H5O_LAYOUT, layout, NULL);
|
||||
ent->pline = H5O_copy(H5O_PLINE, pline, NULL);
|
||||
for (i=0; i<layout->ndims; i++) {
|
||||
ent->offset[i] = offset[i];
|
||||
}
|
||||
ent->rd_count = chunk_size;
|
||||
ent->wr_count = chunk_size;
|
||||
ent->chunk = chunk;
|
||||
found = idx;
|
||||
}
|
||||
#else
|
||||
if (found<0 && chunk_size<=f->shared->access_parms->rdcc_nbytes) {
|
||||
/*
|
||||
* Add the chunk to the beginning of the cache after pruning the cache
|
||||
@ -1183,8 +1287,9 @@ H5F_istore_lock (H5F_t *f, const H5O_layout_t *layout,
|
||||
ent->wr_count = chunk_size;
|
||||
ent->chunk = chunk;
|
||||
found = 0;
|
||||
|
||||
} else if (found<0) {
|
||||
}
|
||||
#endif
|
||||
else if (found<0) {
|
||||
/*
|
||||
* The chunk is larger than the entire cache so we don't cache it.
|
||||
* This is the reason all those arguments have to be repeated for the
|
||||
@ -1192,7 +1297,8 @@ H5F_istore_lock (H5F_t *f, const H5O_layout_t *layout,
|
||||
*/
|
||||
ent = NULL;
|
||||
found = -999;
|
||||
|
||||
|
||||
#ifndef H5F_RDCC_NEW
|
||||
} else if (found>0) {
|
||||
/*
|
||||
* The chunk is not at the beginning of the cache; move it forward by
|
||||
@ -1202,17 +1308,24 @@ H5F_istore_lock (H5F_t *f, const H5O_layout_t *layout,
|
||||
rdcc->slot[found] = rdcc->slot[found-1];
|
||||
rdcc->slot[found-1] = x;
|
||||
ent = rdcc->slot + --found;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Lock the chunk into the cache */
|
||||
if (ent) {
|
||||
assert (!ent->locked);
|
||||
ent->locked = TRUE;
|
||||
#ifndef H5F_RDCC_NEW
|
||||
if (idx_hint) *idx_hint = found;
|
||||
#endif
|
||||
chunk = ent->chunk;
|
||||
}
|
||||
|
||||
#ifdef H5F_RDCC_NEW
|
||||
if (idx_hint) *idx_hint = found;
|
||||
#endif
|
||||
ret_value = chunk;
|
||||
|
||||
done:
|
||||
if (!ret_value) H5MM_xfree (chunk);
|
||||
FUNC_LEAVE (ret_value);
|
||||
@ -1257,6 +1370,15 @@ H5F_istore_unlock (H5F_t *f, const H5O_layout_t *layout,
|
||||
|
||||
FUNC_ENTER (H5F_istore_unlock, FAIL);
|
||||
|
||||
#ifdef H5F_RDCC_NEW
|
||||
if (-999==*idx_hint) {
|
||||
/*not in cache*/
|
||||
} else {
|
||||
assert(*idx_hint>=0 && *idx_hint<rdcc->nslots);
|
||||
assert(rdcc->slot[*idx_hint].chunk==chunk);
|
||||
found = *idx_hint;
|
||||
}
|
||||
#else
|
||||
/* First look at the hint */
|
||||
if (idx_hint && *idx_hint>=0 && *idx_hint<rdcc->nused) {
|
||||
if (rdcc->slot[*idx_hint].chunk==chunk) found = *idx_hint;
|
||||
@ -1266,7 +1388,8 @@ H5F_istore_unlock (H5F_t *f, const H5O_layout_t *layout,
|
||||
for (i=0; found<0 && i<rdcc->nused; i++) {
|
||||
if (rdcc->slot[i].chunk==chunk) found = i;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (found<0) {
|
||||
/*
|
||||
* It's not in the cache, probably because it's too big. If it's
|
||||
|
@ -400,7 +400,7 @@ typedef struct H5F_low_t {
|
||||
|
||||
/* What types of low-level files are there? */
|
||||
#ifndef H5F_LOW_DFLT
|
||||
# define H5F_LOW_DFLT H5F_LOW_STDIO /* The default type */
|
||||
# define H5F_LOW_DFLT H5F_LOW_SEC2 /* The default type */
|
||||
#endif
|
||||
extern const H5F_low_class_t H5F_LOW_SEC2_g[]; /* Posix section 2 */
|
||||
extern const H5F_low_class_t H5F_LOW_STDIO_g[]; /* Posix stdio */
|
||||
@ -419,7 +419,9 @@ typedef struct H5F_rdcc_t {
|
||||
uintn nflushes;/* Number of cache flushes */
|
||||
size_t nbytes; /* Current cached raw data in bytes */
|
||||
intn nslots; /* Number of chunk slots allocated */
|
||||
#ifndef H5F_RDCC_NEW
|
||||
intn nused; /* Number of chunk slots in use */
|
||||
#endif
|
||||
struct H5F_rdcc_ent_t *slot; /* Chunk slots, each points to a chunk */
|
||||
} H5F_rdcc_t;
|
||||
|
||||
|
@ -501,10 +501,10 @@ H5F_split_alloc (H5F_low_t *lf, intn op, hsize_t alignment, hsize_t threshold,
|
||||
|
||||
switch (op) {
|
||||
case H5MF_META:
|
||||
if (blk->addr.offset & lf->u.split.mask) return FAIL;
|
||||
if (blk->addr.offset & lf->u.split.mask) HRETURN(FAIL);
|
||||
break;
|
||||
case H5MF_RAW:
|
||||
if (0==(blk->addr.offset & lf->u.split.mask)) return FAIL;
|
||||
if (0==(blk->addr.offset & lf->u.split.mask)) HRETURN(FAIL);
|
||||
break;
|
||||
}
|
||||
|
||||
|
121
src/H5G.c
121
src/H5G.c
@ -618,13 +618,25 @@ H5Glink(hid_t loc_id, H5G_link_t type, const char *cur_name,
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5Gunlink(hid_t __unused__ loc_id, const char __unused__ *name)
|
||||
H5Gunlink(hid_t loc_id, const char *name)
|
||||
{
|
||||
H5G_entry_t *loc = NULL;
|
||||
|
||||
FUNC_ENTER (H5Gunlink, FAIL);
|
||||
H5TRACE2("e","is",loc_id,name);
|
||||
|
||||
HRETURN_ERROR (H5E_SYM, H5E_UNSUPPORTED, FAIL,
|
||||
"unable to unlink name (not implemented yet)");
|
||||
/* Check arguments */
|
||||
if (NULL==(loc=H5G_loc(loc_id))) {
|
||||
HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location");
|
||||
}
|
||||
if (!name || !*name) {
|
||||
HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name");
|
||||
}
|
||||
|
||||
/* Unlink */
|
||||
if (H5G_unlink(loc, name)<0) {
|
||||
HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to unlink object");
|
||||
}
|
||||
|
||||
FUNC_LEAVE (SUCCEED);
|
||||
}
|
||||
@ -905,6 +917,50 @@ H5G_component(const char *name, size_t *size_p)
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5G_basename
|
||||
*
|
||||
* Purpose: Returns a pointer to the last component of the specified
|
||||
* name. The length of the component is returned through SIZE_P.
|
||||
* The base name is followed by zero or more slashes and a null
|
||||
* terminator, but SIZE_P does not count the slashes or the null
|
||||
* terminator.
|
||||
*
|
||||
* Note: The base name of the root directory is a single slash.
|
||||
*
|
||||
* Return: Success: Ptr to base name.
|
||||
*
|
||||
* Failure: Ptr to the null terminator.
|
||||
*
|
||||
* Programmer: Robb Matzke
|
||||
* Thursday, September 17, 1998
|
||||
*
|
||||
* Modifications:
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static const char *
|
||||
H5G_basename(const char *name, size_t *size_p)
|
||||
{
|
||||
size_t i, end;
|
||||
|
||||
FUNC_ENTER(H5G_basename, NULL);
|
||||
|
||||
/* Find the end of the base name */
|
||||
i = strlen(name);
|
||||
while (i>0 && '/'==name[i-1]) --i;
|
||||
end = i;
|
||||
|
||||
/* Skip backward over base name */
|
||||
while (i>0 && '/'!=name[i-1]) --i;
|
||||
|
||||
/* Watch out for root special case */
|
||||
if ('/'==name[i] && size_p) *size_p = 1;
|
||||
|
||||
FUNC_LEAVE(name+i);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5G_namei
|
||||
@ -930,9 +986,9 @@ H5G_component(const char *name, size_t *size_p)
|
||||
* undefined object header address if the search failed at the
|
||||
* root object. For instance, if NAME is `/foo/bar/baz' and the
|
||||
* root directory exists and contains an entry for `foo', and
|
||||
* foo is a group that contains an entry for baz, but baz is not
|
||||
* foo is a group that contains an entry for bar, but bar is not
|
||||
* a group, then the results will be that REST points to `baz',
|
||||
* GRP_ENT has an undefined object header address, and GRP_ENT
|
||||
* OBJ_ENT has an undefined object header address, and GRP_ENT
|
||||
* is the symbol table entry for `bar' in `/foo'.
|
||||
*
|
||||
* Every file has a root group whose name is `/'. Components of
|
||||
@ -1131,7 +1187,7 @@ H5G_traverse_slink (H5G_entry_t *grp_ent/*in,out*/,
|
||||
*
|
||||
* Purpose: Creates a root group in an empty file and opens it. If a
|
||||
* root group is already open then this function immediately
|
||||
* returnes. If ENT is non-null then it's the symbol table
|
||||
* returns. If ENT is non-null then it's the symbol table
|
||||
* entry for an existing group which will be opened as the root
|
||||
* group. Otherwise a new root group is created and then
|
||||
* opened.
|
||||
@ -1158,7 +1214,7 @@ H5G_mkroot (H5F_t *f, H5G_entry_t *ent)
|
||||
|
||||
/* check args */
|
||||
assert(f);
|
||||
if (f->shared->root_grp) return SUCCEED;
|
||||
if (f->shared->root_grp) HRETURN(SUCCEED);
|
||||
|
||||
/*
|
||||
* If there is no root object then create one. The root group always has
|
||||
@ -1663,7 +1719,7 @@ H5G_insert(H5G_entry_t *loc, const char *name, H5G_entry_t *ent)
|
||||
}
|
||||
|
||||
/*
|
||||
* The object into a symbol table.
|
||||
* Insert the object into a symbol table.
|
||||
*/
|
||||
if (H5O_link(ent, 1) < 0) {
|
||||
HRETURN_ERROR(H5E_SYM, H5E_LINK, FAIL, "link inc failure");
|
||||
@ -2278,3 +2334,52 @@ H5G_get_comment(H5G_entry_t *loc, const char *name, size_t bufsize, char *buf)
|
||||
FUNC_LEAVE(retval);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5G_unlink
|
||||
*
|
||||
* Purpose: Unlink a name from a group.
|
||||
*
|
||||
* Return: Success: SUCCEED
|
||||
*
|
||||
* Failure: FAIL
|
||||
*
|
||||
* Programmer: Robb Matzke
|
||||
* Thursday, September 17, 1998
|
||||
*
|
||||
* Modifications:
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5G_unlink(H5G_entry_t *loc, const char *name)
|
||||
{
|
||||
H5G_entry_t grp_ent, obj_ent;
|
||||
size_t len;
|
||||
const char *base=NULL;
|
||||
|
||||
FUNC_ENTER(H5G_unlink, FAIL);
|
||||
assert(loc);
|
||||
assert(name && *name);
|
||||
|
||||
/* Get the entry for the group that contains the object to be unlinked */
|
||||
if (H5G_namei(loc, name, NULL, &grp_ent, &obj_ent, FALSE, NULL)<0) {
|
||||
HRETURN_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found");
|
||||
}
|
||||
if (!H5F_addr_defined(&(grp_ent.header))) {
|
||||
HRETURN_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL,
|
||||
"no containing group specified");
|
||||
}
|
||||
if (NULL==(base=H5G_basename(name, &len)) || '/'==*base) {
|
||||
HRETURN_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL,
|
||||
"problems obtaining object base name");
|
||||
}
|
||||
|
||||
/* Remove the name from the symbol table */
|
||||
if (H5G_stab_remove(&grp_ent, base)<0) {
|
||||
HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL,
|
||||
"unable to unlink name from symbol table");
|
||||
}
|
||||
|
||||
FUNC_LEAVE(SUCCEED);
|
||||
}
|
||||
|
@ -80,6 +80,7 @@ H5B_class_t H5B_SNODE[1] = {{
|
||||
H5G_node_insert, /*insert */
|
||||
TRUE, /*follow min branch? */
|
||||
TRUE, /*follow max branch? */
|
||||
NULL, /*remove */
|
||||
H5G_node_iterate, /*list */
|
||||
H5G_node_decode_key, /*decode */
|
||||
H5G_node_encode_key, /*encode */
|
||||
|
@ -70,8 +70,9 @@ typedef struct H5G_cwgstk_t {
|
||||
* H5G_node layer through the B-tree layer.
|
||||
*/
|
||||
typedef enum H5G_oper_t {
|
||||
H5G_OPER_FIND = 0, /*find a symbol */
|
||||
H5G_OPER_INSERT = 1 /*insert a new symbol */
|
||||
H5G_OPER_FIND = 0, /*find a symbol */
|
||||
H5G_OPER_INSERT = 1, /*insert a new symbol */
|
||||
H5G_OPER_REMOVE = 2 /*remove existing symbol */
|
||||
} H5G_oper_t;
|
||||
|
||||
/*
|
||||
@ -125,6 +126,8 @@ herr_t H5G_stab_find (H5G_entry_t *grp_ent, const char *name,
|
||||
H5G_entry_t *obj_ent/*out*/);
|
||||
herr_t H5G_stab_insert (H5G_entry_t *grp_ent, const char *name,
|
||||
H5G_entry_t *obj_ent);
|
||||
herr_t H5G_stab_remove(H5G_entry_t *grp_ent, const char *name);
|
||||
|
||||
/*
|
||||
* Functions that understand symbol table entries.
|
||||
*/
|
||||
|
@ -121,6 +121,7 @@ herr_t H5G_set_comment(H5G_entry_t *loc, const char *name, const char *buf);
|
||||
intn H5G_get_comment(H5G_entry_t *loc, const char *name, size_t bufsize,
|
||||
char *buf);
|
||||
herr_t H5G_insert (H5G_entry_t *loc, const char *name, H5G_entry_t *ent);
|
||||
herr_t H5G_unlink(H5G_entry_t *loc, const char *name);
|
||||
herr_t H5G_find (H5G_entry_t *loc, const char *name,
|
||||
H5G_entry_t *grp_ent/*out*/, H5G_entry_t *ent/*out*/);
|
||||
herr_t H5G_traverse_slink (H5G_entry_t *grp_ent/*in,out*/,
|
||||
|
@ -203,10 +203,54 @@ H5G_stab_insert(H5G_entry_t *grp_ent, const char *name, H5G_entry_t *obj_ent)
|
||||
|
||||
/* insert */
|
||||
if (H5B_insert(grp_ent->file, H5B_SNODE, &(stab.btree_addr), &udata) < 0) {
|
||||
HRETURN_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "can't insert entry");
|
||||
HRETURN_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert entry");
|
||||
}
|
||||
|
||||
/* update the name offset in the entry */
|
||||
obj_ent->name_off = udata.ent.name_off;
|
||||
FUNC_LEAVE(SUCCEED);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5G_stab_remove
|
||||
*
|
||||
* Purpose: Remove NAME from a symbol table.
|
||||
*
|
||||
* Return: Success: SUCCEED
|
||||
*
|
||||
* Failure: FAIL
|
||||
*
|
||||
* Programmer: Robb Matzke
|
||||
* Thursday, September 17, 1998
|
||||
*
|
||||
* Modifications:
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5G_stab_remove(H5G_entry_t *grp_ent, const char *name)
|
||||
{
|
||||
H5O_stab_t stab; /*symbol table message */
|
||||
H5G_bt_ud1_t udata; /*data to pass through B-tree */
|
||||
|
||||
FUNC_ENTER(H5G_stab_remove, FAIL);
|
||||
assert(grp_ent && grp_ent->file);
|
||||
assert(name && *name);
|
||||
|
||||
/* initialize data to pass through B-tree */
|
||||
if (NULL==H5O_read(grp_ent, H5O_STAB, 0, &stab)) {
|
||||
HRETURN_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "not a symbol table");
|
||||
}
|
||||
udata.operation = H5G_OPER_REMOVE;
|
||||
udata.name = name;
|
||||
udata.heap_addr = stab.heap_addr;
|
||||
HDmemset(&(udata.ent), 0, sizeof(udata.ent));
|
||||
|
||||
/* remove */
|
||||
if (H5B_remove(grp_ent->file, H5B_SNODE, &(stab.btree_addr), &udata)<0) {
|
||||
HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to remove entry");
|
||||
}
|
||||
|
||||
FUNC_LEAVE(SUCCEED);
|
||||
}
|
||||
|
@ -203,10 +203,8 @@ H5O_dtype_decode_helper(const uint8 **pp, H5T_t *dt)
|
||||
"memory allocation failed");
|
||||
}
|
||||
H5F_addr_undef (&(dt->u.compnd.memb[i].type->ent.header));
|
||||
if (H5O_dtype_decode_helper(pp, dt->u.compnd.memb[i].type) < 0 ||
|
||||
H5T_COMPOUND == dt->u.compnd.memb[i].type->type) {
|
||||
for (j = 0; j <= i; j++)
|
||||
H5MM_xfree(dt->u.compnd.memb[i].name);
|
||||
if (H5O_dtype_decode_helper(pp, dt->u.compnd.memb[i].type)<0) {
|
||||
for (j=0; j<=i; j++) H5MM_xfree(dt->u.compnd.memb[j].name);
|
||||
H5MM_xfree(dt->u.compnd.memb);
|
||||
HRETURN_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL,
|
||||
"can't decode member type");
|
||||
|
@ -349,7 +349,7 @@ H5Z_find(H5Z_filter_t id)
|
||||
|
||||
for (i=0; i<H5Z_table_used_g; i++) {
|
||||
if (H5Z_table_g[i].id == id) {
|
||||
return H5Z_table_g + i;
|
||||
HRETURN(H5Z_table_g+i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ MOSTLYCLEAN=cmpd_dset.h5 dataset.h5 extend.h5 istore.h5 tfile1.h5 tfile2.h5 \
|
||||
gheap1.h5 gheap2.h5 gheap3.h5 gheap4.h5 shtype0.h5 shtype1.h5 \
|
||||
shtype2a.h5 shtype2b.h5 shtype3.h5 links.h5 chunk.h5 big.data \
|
||||
big[0-9][0-9][0-9][0-9][0-9].h5 dtypes1.h5 dtypes2.h5 tattr.h5 \
|
||||
tselect.h5 mtime.h5 ragged.h5
|
||||
tselect.h5 mtime.h5 ragged.h5 grptime.h5
|
||||
CLEAN=$(TIMINGS)
|
||||
|
||||
# Source and object files for programs... The TEST_SRC list contains all the
|
||||
@ -35,7 +35,7 @@ TEST_SRC=testhdf5.c tattr.c tfile.c theap.c tmeta.c tohdr.c tselect.c tstab.c \
|
||||
th5s.c dtypes.c hyperslab.c istore.c dsets.c cmpd_dset.c extend.c \
|
||||
external.c iopipe.c gheap.c shtype.c big.c links.c chunk.c bittests.c \
|
||||
mtime.c ragged.c
|
||||
TEST_OBJ=$(PROG_SRC:.c=.o)
|
||||
TEST_OBJ=$(TEST_SRC:.c=.o)
|
||||
|
||||
# Private header files (not to be installed)...
|
||||
PRIVATE_HDR=testhdf5.h
|
||||
|
100
tools/h5tools.c
100
tools/h5tools.c
@ -108,14 +108,19 @@ static void
|
||||
h5dump_sprint(char *s/*out*/, const h5dump_t *info, hid_t type, void *vp)
|
||||
{
|
||||
size_t i, n, offset, size, dims[4], nelmts;
|
||||
char temp[1024], *name;
|
||||
unsigned overflow = 0xaaaaaaaa;
|
||||
char temp[8192];
|
||||
char *name, quote='\0';
|
||||
hid_t memb;
|
||||
int nmembs, j, k, ndims;
|
||||
const int repeat_threshold = 8;
|
||||
|
||||
if (H5Tequal(type, H5T_NATIVE_DOUBLE)) {
|
||||
sprintf(temp, "%g", *((double*)vp));
|
||||
|
||||
} else if (H5Tequal(type, H5T_NATIVE_FLOAT)) {
|
||||
sprintf(temp, "%g", *((float*)vp));
|
||||
|
||||
} else if (H5Tequal(type, H5T_NATIVE_CHAR) ||
|
||||
H5Tequal(type, H5T_NATIVE_UCHAR)) {
|
||||
switch (*((char*)vp)) {
|
||||
@ -145,18 +150,93 @@ h5dump_sprint(char *s/*out*/, const h5dump_t *info, hid_t type, void *vp)
|
||||
else sprintf(temp, "\\%03o", *((unsigned char*)vp));
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (H5T_STRING==H5Tget_class(type)) {
|
||||
size = H5Tget_size(type);
|
||||
temp[0] = '\0';
|
||||
quote = '\0';
|
||||
|
||||
for (i=0; i<size; i++) {
|
||||
|
||||
/* Count how many times the next character repeats */
|
||||
j=1;
|
||||
while (i+j<size && ((char*)vp)[i]==((char*)vp)[i+j]) j++;
|
||||
|
||||
/*
|
||||
* Print the opening quote. If the repeat count is high enough
|
||||
* to warrant printing the number of repeats instead of
|
||||
* enumerating the characters, then make sure the character to be
|
||||
* repeated is in it's own quote.
|
||||
*/
|
||||
if (j>repeat_threshold) {
|
||||
if (quote) sprintf(temp+strlen(temp), "%c", quote);
|
||||
quote = '\'';
|
||||
sprintf(temp+strlen(temp), "%s%c", i?" ":"", quote);
|
||||
} else if (!quote) {
|
||||
quote = '"';
|
||||
sprintf(temp+strlen(temp), "%s%c", i?" ":"", quote);
|
||||
}
|
||||
|
||||
/* Print the character */
|
||||
switch (((char*)vp)[i]) {
|
||||
case '"':
|
||||
strcat(temp, "\\\"");
|
||||
break;
|
||||
case '\\':
|
||||
strcat(temp, "\\\\");
|
||||
break;
|
||||
case '\b':
|
||||
strcat(temp, "\\b");
|
||||
break;
|
||||
case '\f':
|
||||
strcat(temp, "\\f");
|
||||
break;
|
||||
case '\n':
|
||||
strcat(temp, "\\n");
|
||||
break;
|
||||
case '\r':
|
||||
strcat(temp, "\\r");
|
||||
break;
|
||||
case '\t':
|
||||
strcat(temp, "\\t");
|
||||
break;
|
||||
default:
|
||||
if (isprint(((char*)vp)[i])) {
|
||||
sprintf(temp+strlen(temp), "%c", ((char*)vp)[i]);
|
||||
} else {
|
||||
sprintf(temp+strlen(temp), "\\%03o",
|
||||
((unsigned char*)vp)[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Print the repeat count */
|
||||
if (j>repeat_threshold) {
|
||||
sprintf(temp+strlen(temp), "%c repeats %d times", quote, j-1);
|
||||
quote = '\0';
|
||||
i += j-1;
|
||||
}
|
||||
}
|
||||
if (quote) sprintf(temp+strlen(temp), "%c", quote);
|
||||
|
||||
} else if (H5Tequal(type, H5T_NATIVE_SHORT)) {
|
||||
sprintf(temp, "%d", *((short*)vp));
|
||||
|
||||
} else if (H5Tequal(type, H5T_NATIVE_USHORT)) {
|
||||
sprintf(temp, "%u", *((unsigned short*)vp));
|
||||
|
||||
} else if (H5Tequal(type, H5T_NATIVE_INT)) {
|
||||
sprintf(temp, "%d", *((int*)vp));
|
||||
|
||||
} else if (H5Tequal(type, H5T_NATIVE_UINT)) {
|
||||
sprintf(temp, "%u", *((unsigned*)vp));
|
||||
|
||||
} else if (H5Tequal(type, H5T_NATIVE_LONG)) {
|
||||
sprintf(temp, "%ld", *((long*)vp));
|
||||
|
||||
} else if (H5Tequal(type, H5T_NATIVE_ULONG)) {
|
||||
sprintf(temp, "%lu", *((unsigned long*)vp));
|
||||
|
||||
} else if (H5Tequal(type, H5T_NATIVE_HSSIZE)) {
|
||||
if (sizeof(hssize_t)==sizeof(long)) {
|
||||
sprintf(temp, "%ld", *((long*)vp));
|
||||
@ -167,6 +247,7 @@ h5dump_sprint(char *s/*out*/, const h5dump_t *info, hid_t type, void *vp)
|
||||
strcat(fmt, "d");
|
||||
sprintf(temp, fmt, *((long long*)vp));
|
||||
}
|
||||
|
||||
} else if (H5Tequal(type, H5T_NATIVE_HSIZE)) {
|
||||
if (sizeof(hsize_t)==sizeof(long)) {
|
||||
sprintf(temp, "%lu", *((unsigned long*)vp));
|
||||
@ -177,6 +258,7 @@ h5dump_sprint(char *s/*out*/, const h5dump_t *info, hid_t type, void *vp)
|
||||
strcat(fmt, "u");
|
||||
sprintf(temp, fmt, *((unsigned long long*)vp));
|
||||
}
|
||||
|
||||
} else if (H5T_COMPOUND==H5Tget_class(type)) {
|
||||
nmembs = H5Tget_nmembers(type);
|
||||
strcpy(temp, OPT(info->cmpd_pre, "{"));
|
||||
@ -206,6 +288,7 @@ h5dump_sprint(char *s/*out*/, const h5dump_t *info, hid_t type, void *vp)
|
||||
H5Tclose(memb);
|
||||
}
|
||||
strcat(temp, OPT(info->cmpd_suf, "}"));
|
||||
|
||||
} else {
|
||||
strcpy(temp, "0x");
|
||||
n = H5Tget_size(type);
|
||||
@ -215,6 +298,12 @@ h5dump_sprint(char *s/*out*/, const h5dump_t *info, hid_t type, void *vp)
|
||||
}
|
||||
|
||||
sprintf(s, OPT(info->elmt_fmt, "%s"), temp);
|
||||
|
||||
/*
|
||||
* We should really fix this so it's not possible to overflow the `temp'
|
||||
* buffer.
|
||||
*/
|
||||
assert(overflow==0xaaaaaaaa);
|
||||
}
|
||||
|
||||
|
||||
@ -250,7 +339,7 @@ h5dump_simple(FILE *stream, const h5dump_t *info, hid_t dset, hid_t p_type)
|
||||
hsize_t p_max_idx[8]; /*max selected index */
|
||||
size_t p_type_nbytes; /*size of memory type */
|
||||
hsize_t p_nelmts; /*total selected elmts */
|
||||
char p_buf[256]; /*output string */
|
||||
char p_buf[8192]; /*output string */
|
||||
size_t p_column=0; /*output column */
|
||||
size_t p_ncolumns=80; /*default num columns */
|
||||
char p_prefix[1024]; /*line prefix string */
|
||||
@ -444,6 +533,12 @@ h5dump_fixtype(hid_t f_type)
|
||||
}
|
||||
break;
|
||||
|
||||
case H5T_STRING:
|
||||
m_type = H5Tcopy(f_type);
|
||||
H5Tset_cset(m_type, H5T_CSET_ASCII);
|
||||
H5Tset_strpad(m_type, H5T_STR_NULLPAD);
|
||||
break;
|
||||
|
||||
case H5T_COMPOUND:
|
||||
/*
|
||||
* We have to do this in two steps. The first step scans the file
|
||||
@ -494,7 +589,6 @@ h5dump_fixtype(hid_t f_type)
|
||||
break;
|
||||
|
||||
case H5T_TIME:
|
||||
case H5T_STRING:
|
||||
case H5T_BITFIELD:
|
||||
case H5T_OPAQUE:
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user