[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:
Robb Matzke 1998-09-22 10:27:26 -05:00
parent b20de8612a
commit 6d9af58391
17 changed files with 914 additions and 150 deletions

View File

@ -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
View 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
View File

@ -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, &lt_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);
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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
View File

@ -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);
}

View File

@ -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 */

View File

@ -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.
*/

View File

@ -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*/,

View File

@ -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);
}

View File

@ -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");

View File

@ -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);
}
}

View File

@ -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

View File

@ -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:
/*