[svn-r129] Changes since 19970916

----------------------

./config/depend.in
	Fixed backslashes in sed script because the H5Gnode.c
	dependency info was disappearing.  You'll have to rerun
	config.status to rebuild the Makefiles unless you use gnu
	make.

./config/conclude.in
	Also removes emacs backup files, TAGS, and svf backup files.

./config/linux
	Grouped gcc flags and added provisions for debugging vs. production.

./html/H5.format.html
	Updated messages 0x0008, 0x0009, and 0x000A.

./html/storage.html
	Documentation describing storage schemes.

./src/Makefile.in
./test/Makefile.in
	New source files.

./src/H5A.c
./src/H5Apublic.h
./src/H5C.c
	Changed VOIDP to void* in a couple places.

./src/H5AC.c
./src/H5ACprivate.h
./src/H5B.c
./src/H5Bprivate.h
./src/H5G.c
./src/H5Gnode.c
./src/H5Gprivate.h
./src/H5H.c
./src/H5O.c
	Removed `const' from some variables because H5G_node_found() wanted
	to modify it's udata argument. Removing const there caused it
	to cascade to these other locations.

./src/H5AC.c
./src/H5ACprivate.h
./src/H5B.c
./src/H5Gnode.c
./src/H5Gstab.c
./src/H5H.c
./src/H5O.c
	Added an extra argument to H5AC_find_f() and H5AC_protect(). This
	arg gets passed to the load() method.  Also added an extra
	argument to the H5AC_find() macro.

./src/H5B.c
./src/H5Bprivate.h
./src/H5Gnode.c
	Extra argument passed to the sizeof_rkey() method.

./src/H5Fprivate.c
./src/H5Fistore.c (new)
	Added indexed I/O operations.

./src/H5G.c
./src/H5Gnode.c
./src/H5Gprivate.h
	Beginning to add H5G_open/close and related bug fixes.

./src/H5Oprivate.h
./src/H5Oistore.c (new)
	Added the H5O_ISTORE messsage (0x0008) for indexed storage of
	objects.

./src/H5private.h
	Added extra braces around both sides of the FUNC_ENTER() and
	FUNC_LEAVE() macros so FUNC_ENTER() can appear before
	declarations or after executable statements the second case is
	used by H5G_namei() to initialize output arguments to sane
	values before FUNC_ENTER() might return failure.

		int f ()
		{
		   int decl1;
		   printf ("This happens before FUNC_ENTER()\n");
		   FUNC_ENTER (...);
		   int another_declaration;

./src/H5B.c
./src/H5Bprivate.h
./src/H5Gnode.c
	Extra arguments for key encoding and decoding.

./src/H5E.c
./src/H5Epublic.h
./src/H5Fistore.c
./src/H5Oistore.c
./src/H5Oprivate.h
	Indexed, chunked, sparse storage (not ready for general consumption
	yet).

./src/H5V.c		(new)
./src/H5Vprivate.h	(new)
./test/hyperslab.c	(new)
	Vector, array, and hyperslab functions.

./src/H5B.c
./src/H5Bprivate.h
./src/H5Fistore.c
./src/H5Gnode.c
./src/H5V.c
./src/H5Vprivate.h
./test/hyperslab.c
	Added functionality for indexed storage.

./src/H5F.c
	Fixed problems with seek optimizing.  Recommend we disable it
	until we can implement it in the file/address class since all
	of HDF5 must be aware of it.

./src/H5O.c
	Fixed comeent speling erorr :-)

./MANIFEST
	Added new files.

./config/conclude.in
	Added the word `Testing' to the test cases.  So if a test
	program is called hyperslab then the make output will contain
	the line `Testing hyperslab'.

./config/linux
	The default file I/O library is Posix section 2 on my linux
	machine so I can do some I/O performance testing.

./src/H5C.c
./src/H5Cprivate.h
./src/H5Cpublic.h
	Added ability to set size of indexed-storage B-tree.

./src/H5D.c
./src/H5E.c
./src/H5Epublic.h
./src/H5F.c
./src/H5Fprivate.h
./src/H5G.c
./src/H5Gnode.c
./src/H5Gpkg.h
./src/H5Gprivate.h
./src/H5Gpublic.h
./src/H5Gshad.c
./src/H5Gstab.c
./test/stab.c
	Changed `directory' to `group' in numerous places.

./src/H5private.h
	The FILELIB constant can be set on the compile command-line.

./src/istore.c		     NEW
	Tests for indexed storage.
This commit is contained in:
Robb Matzke 1997-10-20 18:14:35 -05:00
parent dc4961d072
commit 56ad55117a
43 changed files with 3952 additions and 672 deletions

View File

@ -48,6 +48,7 @@
./src/H5Eprivate.h
./src/H5Epublic.h
./src/H5F.c
./src/H5Fistore.c
./src/H5Fprivate.h
./src/H5Fpublic.h
./src/H5G.c
@ -72,6 +73,7 @@
./src/H5Mpublic.h
./src/H5O.c
./src/H5Ocont.c
./src/H5Oistore.c
./src/H5Oname.c
./src/H5Onull.c
./src/H5Oprivate.h
@ -88,10 +90,14 @@
./src/H5T.c
./src/H5Tprivate.h
./src/H5Tpublic.h
./src/H5V.c
./src/H5Vprivate.h
./src/hdf5.h
./src/Makefile.in
./src/Naming-Conventions
./test/Makefile.in
./test/hyperslab.c
./test/istore.c
./test/testhdf5.c
./test/testhdf5.h
./test/tfile.c

View File

@ -73,7 +73,7 @@ distclean:
(cd $$d && $(MAKE) $@) || exit 1; \
done
$(RM) config/commence config/conclude config/depend
$(RM) config.cache config.log config.status src/config.h
$(RM) config.cache config.log config.status src/H5config.h
$(RM) Makefile
maintainer-clean:
@ -82,8 +82,8 @@ maintainer-clean:
@@SETX@; for d in $(SUBDIRS); do \
(cd $$d && $(MAKE) $@) || exit 1; \
done
$(RM) config.cache config.log config.status src/config.h
$(RM) configure src/config.h.in
$(RM) config.cache config.log config.status src/H5config.h
$(RM) configure src/H5config.h.in
# This file does not end with the `CONCLUDE' statement since it has

5
acconfig.h Normal file
View File

@ -0,0 +1,5 @@
/* Define if the __attribute__(()) extension is present */
/* #define HAVE_ATTRIBUTE */
/* Define if the compiler understands the __FUNCTION__ keyword. */
/* #define HAVE_FUNCTION */

View File

@ -23,7 +23,7 @@ TAGS: $(LIB_SRC)
test: $(PROGS)
@for test in $(TESTS) dummy; do \
if test $$test != dummy; then \
echo "$$test $(TEST_FLAGS)"; \
echo "Testing $$test $(TEST_FLAGS)"; \
$$test $(TEST_FLAGS) || exit 1; \
fi; \
done;
@ -68,7 +68,7 @@ clean: mostlyclean
# in the distribution.
#
distclean: clean
$(RM) .depend TAGS
$(RM) .depend TAGS *~ core *.bak *.old *.new
@if test -f Makefile.in; then \
(set -x; $(RM) Makefile); \
fi

View File

@ -1,6 +1,17 @@
# Site configuration -- do not distribute this file.
CFLAGS_WARN="-Wall -Wshadow -Wpointer-arith -Wcast-qual -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs"
CFLAGS_DEBUG="-g -DH5AC_DEBUG_PROTECT -DFILELIB=1 -fverbose-asm"
CFLAGS_PROFILE="-pg"
CFLAGS_PRODUCTION="-O3 -UH5AC_DEBUG_PROTECT -DNDEBUG -finline-functions -funroll-loops -malign-double -fomit-frame-pointer"
if test "x$CFLAGS" = "x"; then
CFLAGS="-g -DH5AC_DEBUG_PROTECT -Wall -Wshadow -Wpointer-arith -Wcast-qual -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs"
# Uncomment the following line for a production version of the library.
#CFLAGS="-pipe $CFLAGS_PRODUCTION $CFLAGS_WARN"
# Uncomment the following line for normal development
CFLAGS="-pipe $CFLAGS_DEBUG $CFLAGS_WARN"
fi

636
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -105,9 +105,21 @@ AC_CHECK_SIZEOF(double, 8)
dnl ----------------------------------------------------------------------
dnl AC_FUNC_MEMCMP
dnl AC_C_CONST
dnl AC_C_INLINE
dnl Check compiler characteristics
dnl
AC_C_CONST
AC_C_INLINE
AC_MSG_CHECKING(for __attribute__ extension)
AC_TRY_COMPILE(,[int __attribute__((unused)) f(void){return 1;}],
AC_DEFINE(HAVE_ATTRIBUTE) AC_MSG_RESULT(yes),
AC_MSG_RESULT(no))
AC_MSG_CHECKING(for __FUNCTION__ extension)
AC_TRY_COMPILE(,[int f(void){return __FUNCTION__;}],
AC_DEFINE(HAVE_FUNCTION) AC_MSG_RESULT(yes),
AC_MSG_RESULT(no))

View File

@ -276,7 +276,7 @@ done:
*******************************************************************************/
hid_t H5Aregister_atom(group_t grp, /* IN: Group to register the object in */
const VOIDP object /* IN: Object to attach to atom */
const void *object /* IN: Object to attach to atom */
)
{
atom_group_t *grp_ptr=NULL; /* ptr to the atomic group */

View File

@ -143,10 +143,12 @@ H5AC_dest (H5F_t *f)
*
* Purpose: Given an object type and the address at which that object
* is located in the file, return a pointer to the object.
* The optional UDATA structure is passed down to the function
* that is responsible for loading the object into memory.
* The pointer is guaranteed to be valid until the next call
* to an H5AC function (if you want a pointer which is valid
* The optional UDATA1 and UDATA2 structures are passed down to
* the function that is responsible for loading the object into
* memory.
*
* The returned pointer is guaranteed to be valid until the next
* call to an H5AC function (if you want a pointer which is valid
* indefinately then see H5AC_protect()).
*
* If H5AC_DEBUG_PROTECT is defined then this function also
@ -175,7 +177,8 @@ H5AC_dest (H5F_t *f)
*-------------------------------------------------------------------------
*/
void *
H5AC_find_f (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *udata)
H5AC_find_f (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
void *udata1, void *udata2)
{
unsigned idx;
herr_t status;
@ -228,7 +231,7 @@ H5AC_find_f (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *udata)
* Load a new thing. If it can't be loaded, then return an error
* without preempting anything.
*/
if (NULL==(thing=(type->load)(f, addr, udata))) {
if (NULL==(thing=(type->load)(f, addr, udata1, udata2))) {
HRETURN_ERROR (H5E_CACHE, H5E_CANTLOAD, NULL);
}
@ -272,7 +275,7 @@ H5AC_find_f (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *udata)
* Failure: never fails
*
* Programmer: Robb Matzke
* robb@maya.nuance.com
* matzke@llnl.gov
* Aug 12 1997
*
* Modifications:
@ -604,7 +607,7 @@ H5AC_rename (H5F_t *f, const H5AC_class_t *type,
* Failure: NULL
*
* Programmer: Robb Matzke
* robb@maya.nuance.com
* matzke@llnl.gov
* Sep 2 1997
*
* Modifications:
@ -612,7 +615,8 @@ H5AC_rename (H5F_t *f, const H5AC_class_t *type,
*-------------------------------------------------------------------------
*/
void *
H5AC_protect (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *udata)
H5AC_protect (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
void *udata1, void *udata2)
{
int idx;
void *thing = NULL;
@ -663,7 +667,7 @@ H5AC_protect (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *udata)
* Load a new thing. If it can't be loaded, then return an error
* without preempting anything.
*/
if (NULL==(thing=(type->load)(f, addr, udata))) {
if (NULL==(thing=(type->load)(f, addr, udata1, udata2))) {
HRETURN_ERROR (H5E_CACHE, H5E_CANTLOAD, NULL);
}
}
@ -706,7 +710,7 @@ H5AC_protect (H5F_t *f, const H5AC_class_t *type, haddr_t addr, void *udata)
* Failure: FAIL
*
* Programmer: Robb Matzke
* robb@maya.nuance.com
* matzke@llnl.gov
* Sep 2 1997
*
* Modifications:

View File

@ -39,7 +39,7 @@
* by the LOAD method if the DEST argument is non-zero.
*/
typedef struct H5AC_class_t {
void *(*load)(H5F_t*, haddr_t addr, void *udata);
void *(*load)(H5F_t*, haddr_t addr, void *udata1, void *udata2);
herr_t (*flush)(H5F_t*, hbool_t dest, haddr_t addr, void *thing);
} H5AC_class_t;
@ -78,9 +78,9 @@ typedef struct H5AC_t {
*/
herr_t H5AC_dest (H5F_t *f);
void *H5AC_find_f (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
void *udata);
void *udata1, void *udata2);
void * H5AC_protect (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
void *udata);
void *udata1, void *udata2);
herr_t H5AC_unprotect (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
void *thing);
herr_t H5AC_flush (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
@ -91,11 +91,11 @@ herr_t H5AC_rename (H5F_t *f, const H5AC_class_t *type, haddr_t old,
herr_t H5AC_set (H5F_t *f, const H5AC_class_t *type, haddr_t addr,
void *thing);
#define H5AC_find(F,TYPE,ADDR,UDATA) \
#define H5AC_find(F,TYPE,ADDR,UDATA1,UDATA2) \
(((F)->shared->cache->slot[H5AC_HASH(F,ADDR)].type==(TYPE) && \
(F)->shared->cache->slot[H5AC_HASH(F,ADDR)].addr==(ADDR)) ? \
(F)->shared->cache->slot[H5AC_HASH(F,ADDR)].thing : \
H5AC_find_f (F, TYPE, ADDR, UDATA))
H5AC_find_f (F, TYPE, ADDR, UDATA1, UDATA2))
#endif /* !_H5ACprivate_H */

View File

@ -110,7 +110,7 @@ intn H5Adestroy_group(group_t grp /* IN: Group to destroy */
*******************************************************************************/
hid_t H5Aregister_atom(group_t grp, /* IN: Group to register the object in */
const VOIDP object /* IN: Object to attach to atom */
const void *object /* IN: Object to attach to atom */
);
/******************************************************************************

373
src/H5B.c
View File

@ -100,21 +100,23 @@
/* PRIVATE PROTOTYPES */
static haddr_t H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
H5B_ins_t *anchor,
uint8 *lt_key, hbool_t *lt_key_changed,
uint8 *md_key, void *udata,
uint8 *rt_key, hbool_t *rt_key_changed);
static herr_t H5B_insert_child (H5F_t *f, const H5B_class_t *type,
H5B_t *bt, intn idx, haddr_t child,
intn anchor, void *md_key);
H5B_ins_t anchor, void *md_key);
static herr_t H5B_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5B_t *b);
static H5B_t *H5B_load (H5F_t *f, haddr_t addr, void *_data);
static H5B_t *H5B_load (H5F_t *f, haddr_t addr, void *_type, void *udata);
static herr_t H5B_decode_key (H5F_t *f, H5B_t *bt, intn idx);
static herr_t H5B_decode_keys (H5F_t *f, H5B_t *bt, intn idx);
static size_t H5B_nodesize (H5F_t *f, const H5B_class_t *type,
size_t *total_nkey_size, size_t sizeof_rkey);
/* H5B inherits cache-like properties from H5AC */
static const H5AC_class_t H5AC_BT[1] = {{
(void*(*)(H5F_t*,haddr_t,void*))H5B_load,
(void*(*)(H5F_t*,haddr_t,void*,void*))H5B_load,
(herr_t(*)(H5F_t*,hbool_t,haddr_t,void*))H5B_flush,
}};
@ -125,7 +127,9 @@ static interface_initialize_g = FALSE;
/*-------------------------------------------------------------------------
* Function: H5B_new
*
* Purpose: Creates a new empty B-tree leaf node.
* Purpose: Creates a new empty B-tree leaf node. The UDATA pointer is
* passed as an argument to the sizeof_rkey() method for the
* B-tree.
*
* Return: Success: address of new node.
*
@ -140,7 +144,7 @@ static interface_initialize_g = FALSE;
*-------------------------------------------------------------------------
*/
haddr_t
H5B_new (H5F_t *f, const H5B_class_t *type)
H5B_new (H5F_t *f, const H5B_class_t *type, void *udata)
{
H5B_t *bt=NULL;
haddr_t addr;
@ -159,7 +163,7 @@ H5B_new (H5F_t *f, const H5B_class_t *type)
/*
* Allocate file and memory data structures.
*/
sizeof_rkey = (type->get_sizeof_rkey)(f);
sizeof_rkey = (type->get_sizeof_rkey)(f, udata);
size = H5B_nodesize (f, type, &total_native_keysize, sizeof_rkey);
if ((addr = H5MF_alloc (f, size))<0) {
HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL);
@ -229,9 +233,9 @@ H5B_new (H5F_t *f, const H5B_class_t *type)
*-------------------------------------------------------------------------
*/
static H5B_t *
H5B_load (H5F_t *f, haddr_t addr, void *_data)
H5B_load (H5F_t *f, haddr_t addr, void *_type, void *udata)
{
const H5B_class_t *type = (H5B_class_t *)_data;
const H5B_class_t *type = (H5B_class_t *)_type;
size_t size, total_nkey_size;
H5B_t *bt = NULL;
intn i;
@ -247,7 +251,7 @@ H5B_load (H5F_t *f, haddr_t addr, void *_data)
assert (type->get_sizeof_rkey);
bt = H5MM_xmalloc (sizeof(H5B_t));
bt->sizeof_rkey = (type->get_sizeof_rkey)(f);
bt->sizeof_rkey = (type->get_sizeof_rkey)(f, udata);
size = H5B_nodesize (f, type, &total_nkey_size, bt->sizeof_rkey);
bt->type = type;
bt->dirty = FALSE;
@ -375,7 +379,8 @@ H5B_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5B_t *bt)
assert (bt->key[i].rkey == p);
if (bt->key[i].dirty) {
if (bt->key[i].nkey) {
if ((bt->type->encode)(f, bt->key[i].rkey, bt->key[i].nkey)<0) {
if ((bt->type->encode)(f, bt, bt->key[i].rkey,
bt->key[i].nkey)<0) {
HRETURN_ERROR (H5E_BTREE, H5E_CANTENCODE, FAIL);
}
}
@ -464,21 +469,14 @@ H5B_find (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
* 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))) {
if (NULL==(bt=H5AC_protect (f, H5AC_BT, addr, type, udata))) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
}
rt = bt->nchildren;
while (lt<rt && cmp) {
idx = (lt + rt) / 2;
/* the left key */
if (!bt->key[idx].nkey && H5B_decode_key (f, bt, idx)<0) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
}
/* the right key */
if (!bt->key[idx+1].nkey && H5B_decode_key (f, bt, idx+1)<0) {
if (H5B_decode_keys (f, bt, idx)<0) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
}
@ -522,9 +520,11 @@ done:
* Function: H5B_split
*
* Purpose: Split a single node into two nodes. If anchor is
* H5B_ANCHOR_LT then the new node gets the right half of
* the old node. If anchor is H5B_ANCHOR_RT then the
* new node gets the left half of the old node.
* H5B_INS_RIGHT then the new node gets the right half of
* the old node. If anchor is H5B_INS_LEFT then the
* new node gets the left half of the old node. The UDATA
* pointer is passed to the sizeof_rkey() method but is
* otherwise unused.
*
* The OLD_BT argument is a pointer to a protected B-tree
* node.
@ -543,7 +543,7 @@ done:
*/
static haddr_t
H5B_split (H5F_t *f, H5B_class_t *type, H5B_t *old_bt, haddr_t old_addr,
intn anchor)
H5B_ins_t anchor, void *udata)
{
H5B_t *new_bt=NULL, *tmp_bt=NULL;
haddr_t ret_value=FAIL, new_addr=FAIL;
@ -558,21 +558,22 @@ H5B_split (H5F_t *f, H5B_class_t *type, H5B_t *old_bt, haddr_t old_addr,
assert (f);
assert (type);
assert (old_addr>=0);
assert (H5B_INS_LEFT==anchor || H5B_INS_RIGHT==anchor);
/*
* Initialize variables.
*/
assert (old_bt->nchildren == 2*H5B_K(f,type));
recsize = old_bt->sizeof_rkey + H5F_SIZEOF_OFFSET(f);
delta = H5B_ANCHOR_LT==anchor ? H5B_K(f,type) : 0;
delta = H5B_INS_RIGHT==anchor ? H5B_K(f,type) : 0;
/*
* Create the new B-tree node.
*/
if ((new_addr = H5B_new (f, type))<0) {
if ((new_addr = H5B_new (f, type, udata))<0) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTINIT, FAIL);
}
if (NULL==(new_bt=H5AC_protect (f, H5AC_BT, new_addr, type))) {
if (NULL==(new_bt=H5AC_protect (f, H5AC_BT, new_addr, type, udata))) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
}
new_bt->level = old_bt->level;
@ -606,12 +607,12 @@ H5B_split (H5F_t *f, H5B_class_t *type, H5B_t *old_bt, haddr_t old_addr,
/*
* Truncate the old node.
*/
delta = H5B_ANCHOR_LT==anchor ? 0 : H5B_K(f,type);
delta = H5B_INS_RIGHT==anchor ? 0 : H5B_K(f,type);
old_bt->dirty = TRUE;
old_bt->ndirty = BOUND (0, old_bt->ndirty-delta, H5B_K(f,type));
old_bt->nchildren = H5B_K(f,type);
if (H5B_ANCHOR_RT==anchor) {
if (H5B_INS_LEFT==anchor) {
HDmemcpy (old_bt->page + H5B_SIZEOF_HDR(f),
old_bt->page + H5B_SIZEOF_HDR(f) + delta*recsize,
H5B_K(f,type) * recsize);
@ -642,12 +643,13 @@ H5B_split (H5F_t *f, H5B_class_t *type, H5B_t *old_bt, haddr_t old_addr,
/*
* Update sibling pointers.
*/
if (H5B_ANCHOR_LT==anchor) {
if (H5B_INS_RIGHT==anchor) {
new_bt->left = old_addr;
new_bt->right = old_bt->right;
if (old_bt->right) {
if (NULL==(tmp_bt=H5AC_find (f, H5AC_BT, old_bt->right, type))) {
if (NULL==(tmp_bt=H5AC_find (f, H5AC_BT, old_bt->right, type,
udata))) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
}
tmp_bt->dirty = TRUE;
@ -659,7 +661,8 @@ H5B_split (H5F_t *f, H5B_class_t *type, H5B_t *old_bt, haddr_t old_addr,
new_bt->right = old_addr;
if (old_bt->left) {
if (NULL==(tmp_bt=H5AC_find (f, H5AC_BT, old_bt->left, type))) {
if (NULL==(tmp_bt=H5AC_find (f, H5AC_BT, old_bt->left, type,
udata))) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
}
tmp_bt->dirty = TRUE;
@ -702,7 +705,44 @@ H5B_decode_key (H5F_t *f, H5B_t *bt, intn idx)
FUNC_ENTER (H5B_decode_key, NULL, FAIL);
bt->key[idx].nkey = bt->native + idx * bt->type->sizeof_nkey;
if ((bt->type->decode)(f, bt->key[idx].rkey, bt->key[idx].nkey)<0) {
if ((bt->type->decode)(f, bt, bt->key[idx].rkey,
bt->key[idx].nkey)<0) {
HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
}
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5B_decode_keys
*
* Purpose: Decode keys on either side of the specified branch.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Tuesday, October 14, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static herr_t
H5B_decode_keys (H5F_t *f, H5B_t *bt, intn idx)
{
FUNC_ENTER (H5B_decode_keys, NULL, FAIL);
assert (f);
assert (bt);
assert (idx>=0 && idx<bt->nchildren);
if (!bt->key[idx].nkey && H5B_decode_key (f, bt, idx)<0) {
HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
}
if (!bt->key[idx+1].nkey && H5B_decode_key (f, bt, idx+1)<0) {
HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
}
@ -741,6 +781,7 @@ H5B_insert (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
size_t size;
uint8 *buf;
haddr_t tmp_addr;
H5B_ins_t anchor = H5B_INS_ERROR;
FUNC_ENTER (H5B_insert, NULL, FAIL);
@ -749,17 +790,18 @@ H5B_insert (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
*/
assert (f);
assert (type);
assert (type->sizeof_nkey < sizeof lt_key);
assert (type->sizeof_nkey <= sizeof lt_key);
child = H5B_insert_helper (f, addr, type, lt_key, &lt_key_changed,
child = H5B_insert_helper (f, addr, type, &anchor, lt_key, &lt_key_changed,
md_key, udata, rt_key, &rt_key_changed);
if (child<0) {
if (child<0 || anchor<0) {
HRETURN_ERROR (H5E_BTREE, H5E_CANTINIT, FAIL);
}
if (0==child) HRETURN (addr);
if (H5B_INS_NOOP==anchor) HRETURN (addr);
assert (H5B_INS_RIGHT==anchor);
/* the current root */
if (NULL==(bt = H5AC_find (f, H5AC_BT, addr, type))) {
if (NULL==(bt = H5AC_find (f, H5AC_BT, addr, type, udata))) {
HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
}
level = bt->level;
@ -771,7 +813,7 @@ H5B_insert (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
}
/* the new node */
if (NULL==(bt = H5AC_find (f, H5AC_BT, child, type))) {
if (NULL==(bt = H5AC_find (f, H5AC_BT, child, type, udata))) {
HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
}
if (!rt_key_changed) {
@ -812,14 +854,14 @@ H5B_insert (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
addr = tmp_addr;
/* update the new child's left pointer */
if (NULL==(bt=H5AC_find (f, H5AC_BT, child, type))) {
if (NULL==(bt=H5AC_find (f, H5AC_BT, child, type, udata))) {
HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
}
bt->dirty = TRUE;
bt->left = addr;
/* clear the old root at the old address */
if (NULL==(bt=H5AC_find (f, H5AC_BT, new_root, type))) {
if (NULL==(bt=H5AC_find (f, H5AC_BT, new_root, type, udata))) {
HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
}
bt->dirty = TRUE;
@ -830,7 +872,7 @@ H5B_insert (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
/* the new root */
if (NULL==(bt = H5AC_find (f, H5AC_BT, new_root, type))) {
if (NULL==(bt = H5AC_find (f, H5AC_BT, new_root, type, udata))) {
HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
}
bt->dirty = TRUE;
@ -877,7 +919,7 @@ H5B_insert (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
*/
static herr_t
H5B_insert_child (H5F_t *f, const H5B_class_t *type, H5B_t *bt,
intn idx, haddr_t child, intn anchor, void *md_key)
intn idx, haddr_t child, H5B_ins_t anchor, void *md_key)
{
size_t recsize;
intn i;
@ -888,7 +930,7 @@ H5B_insert_child (H5F_t *f, const H5B_class_t *type, H5B_t *bt,
bt->dirty = TRUE;
recsize = bt->sizeof_rkey + H5F_SIZEOF_OFFSET(f);
if (H5B_ANCHOR_LT==anchor) {
if (H5B_INS_RIGHT==anchor) {
/*
* The MD_KEY is the left key of the new node.
*/
@ -950,6 +992,7 @@ H5B_insert_child (H5F_t *f, const H5B_class_t *type, H5B_t *bt,
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5B_insert_helper
@ -985,6 +1028,7 @@ H5B_insert_child (H5F_t *f, const H5B_class_t *type, H5B_t *bt,
*/
static haddr_t
H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
H5B_ins_t *parent_ins,
uint8 *lt_key, hbool_t *lt_key_changed,
uint8 *md_key, void *udata,
uint8 *rt_key, hbool_t *rt_key_changed)
@ -992,7 +1036,7 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
H5B_t *bt=NULL, *twin=NULL, *tmp_bt=NULL;
intn lt=0, idx=-1, rt, cmp=-1;
haddr_t child_addr=0, twin_addr=0, ret_value=FAIL;
intn anchor;
H5B_ins_t my_ins = H5B_INS_ERROR;
FUNC_ENTER (H5B_insert_helper, NULL, FAIL);
@ -1005,35 +1049,30 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
assert (type->decode);
assert (type->cmp);
assert (type->new);
assert (parent_ins && H5B_INS_ERROR==*parent_ins);
assert (lt_key);
assert (lt_key_changed);
assert (rt_key);
assert (rt_key_changed);
*lt_key_changed = FALSE;
*rt_key_changed = FALSE;
/*
* Use a binary search to find the child that will receive the new
* data. When the search completes IDX points to the child that
* should get the new data.
*/
if (NULL==(bt=H5AC_protect (f, H5AC_BT, addr, type))) {
if (NULL==(bt=H5AC_protect (f, H5AC_BT, addr, type, udata))) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
}
rt = bt->nchildren;
while (lt<rt && cmp) {
idx = (lt + rt) / 2;
/* left key */
if (!bt->key[idx].nkey && H5B_decode_key (f, bt, idx)<0) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
if (H5B_decode_keys (f, bt, idx)<0) {
HRETURN_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
}
/* right key */
if (!bt->key[idx+1].nkey && H5B_decode_key (f, bt, idx+1)<0) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
}
/* compare */
if ((cmp=(type->cmp)(f, bt->key[idx].nkey, udata,
bt->key[idx+1].nkey))<0) {
rt = idx;
@ -1042,46 +1081,14 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
}
}
if (cmp<0 && idx<=0) {
/*
* Boundary condition: the value to insert is the new minimum
* value in the B-tree. Insert the value in the left-most node.
*/
idx = 0;
cmp = 0;
} else if (cmp>0 && idx+1>=bt->nchildren) {
/*
* Boundary condition: the value to insert is the new maximum
* value in the B-tree. Insert the value in the right-most node.
*/
idx = bt->nchildren-1;
cmp = 0;
}
assert (0==cmp);
/*
* Ensure that both native keys exist since we may have made boundary
* condition adjustments.
*/
if (bt->nchildren) {
if (!bt->key[idx].nkey && H5B_decode_key (f, bt, idx)<0) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
}
if (!bt->key[idx+1].nkey && H5B_decode_key (f, bt, idx+1)<0) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
}
}
/*
* If there are no children, then create a new child. This can only
* happen at the root of the B-tree. The left and right native keys
* are output values from the node creation function.
*/
if (0==bt->nchildren) {
/*
* The value being inserted will be the only value in this tree. We
* must necessarily be at level zero.
*/
assert (0==bt->level);
bt->key[0].nkey = bt->native;
bt->key[1].nkey = bt->native + type->sizeof_nkey;
if ((child_addr=(type->new)(f, bt->key[0].nkey, udata,
bt->key[1].nkey))<0) {
bt->key[0].nkey = bt->key[1].nkey = NULL;
@ -1091,28 +1098,142 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
bt->dirty = TRUE;
bt->ndirty = 1;
bt->child[0] = child_addr;
bt->key[0].dirty = TRUE;
bt->key[1].dirty = TRUE;
idx = 0;
}
/*
* Insert the new data in the child B-tree node or in the data node.
*/
if (bt->level > 0) {
child_addr = H5B_insert_helper (f, bt->child[idx], type,
if (type->follow_min) {
child_addr = (type->insert)(f, bt->child[idx], &my_ins,
bt->key[idx].nkey, lt_key_changed,
md_key, udata,
bt->key[idx+1].nkey, rt_key_changed);
} else {
my_ins = H5B_INS_NOOP;
}
} else if (cmp<0 && idx<=0 && bt->level>0) {
/*
* The value being inserted is less than any value in this tree. Follow
* the minimum branch out of this node to a subtree.
*/
idx = 0;
if (H5B_decode_keys (f, bt, idx)<0) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
}
child_addr = H5B_insert_helper (f, bt->child[idx], type, &my_ins,
bt->key[idx].nkey, lt_key_changed,
md_key, udata,
bt->key[idx+1].nkey, rt_key_changed);
anchor = H5B_ANCHOR_LT;
} else {
child_addr = (type->insert)(f, bt->child[idx], &anchor,
} else if (cmp<0 && idx<=0 && type->follow_min) {
/*
* The value being inserted is less than any leaf node out of this
* current node. Follow the minimum branch to a leaf node and let the
* subclass handle the problem.
*/
idx = 0;
if (H5B_decode_keys (f, bt, idx)<0) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
}
child_addr = (type->insert)(f, bt->child[idx], &my_ins,
bt->key[idx].nkey, lt_key_changed,
md_key, udata,
bt->key[idx+1].nkey, rt_key_changed);
} else if (cmp<0 && idx<=0) {
/*
* The value being inserted is less than any leaf node out of the
* current node. Create a new minimum leaf node out of this B-tree
* node. This node is not empty (handled above).
*/
idx = 0;
if (H5B_decode_keys (f, bt, idx)<0) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
}
my_ins = H5B_INS_LEFT;
HDmemcpy (md_key, bt->key[idx].nkey, type->sizeof_nkey);
child_addr = (type->new)(f, bt->key[idx].nkey, udata, md_key);
*lt_key_changed = TRUE;
} else if (cmp>0 && idx+1>=bt->nchildren && bt->level>0) {
/*
* The value being inserted is larger than any value in this tree.
* Follow the maximum branch out of this node to a subtree.
*/
idx = bt->nchildren - 1;
if (H5B_decode_keys (f, bt, idx)<0) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
}
child_addr = H5B_insert_helper (f, bt->child[idx], type, &my_ins,
bt->key[idx].nkey, lt_key_changed,
md_key, udata,
bt->key[idx+1].nkey, rt_key_changed);
} else if (cmp>0 && idx+1>=bt->nchildren && type->follow_max) {
/*
* The value being inserted is larger than any leaf node out of the
* current node. Follow the maximum branch to a leaf node and let the
* subclass handle the problem.
*/
idx = bt->nchildren - 1;
if (H5B_decode_keys (f, bt, idx)<0) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
}
child_addr = (type->insert)(f, bt->child[idx], &my_ins,
bt->key[idx].nkey, lt_key_changed,
md_key, udata,
bt->key[idx+1].nkey, rt_key_changed);
} else if (cmp>0 && idx+1>=bt->nchildren) {
/*
* The value being inserted is larger than any leaf node out of the
* current node. Create a new maximum leaf node out of this B-tree
* node.
*/
idx = bt->nchildren - 1;
if (H5B_decode_keys (f, bt, idx)<0) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
}
my_ins = H5B_INS_RIGHT;
HDmemcpy (md_key, bt->key[idx+1].nkey, type->sizeof_nkey);
child_addr = (type->new)(f, md_key, udata, bt->key[idx+1].nkey);
*rt_key_changed = TRUE;
} else if (cmp) {
/*
* 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);
} else if (bt->level>0) {
/*
* Follow a branch out of this node to another subtree.
*/
assert (idx>=0 && idx<bt->nchildren);
child_addr = H5B_insert_helper (f, bt->child[idx], type, &my_ins,
bt->key[idx].nkey, lt_key_changed,
md_key, udata,
bt->key[idx+1].nkey, rt_key_changed);
} else {
/*
* Follow a branch out of this node to a leaf node of some other type.
*/
assert (idx>=0 && idx<bt->nchildren);
child_addr = (type->insert)(f, bt->child[idx], &my_ins,
bt->key[idx].nkey, lt_key_changed,
md_key, udata,
bt->key[idx+1].nkey, rt_key_changed);
}
if (child_addr<0) HGOTO_ERROR (H5E_BTREE, H5E_CANTINSERT, FAIL);
if (child_addr<0 || my_ins<0) {
/* Insertion failed */
HGOTO_ERROR (H5E_BTREE, H5E_CANTINSERT, FAIL);
}
/*
* Update the left and right keys of the current node.
@ -1136,36 +1257,43 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
}
}
/*
* Insert the child, splitting the current node if necessary.
*/
if (child_addr) {
if (H5B_INS_CHANGE==my_ins) {
/*
* If the child split and the left node is anchored, then the new
* The insertion simply changed the address for the child.
*/
bt->child[idx] = child_addr;
bt->dirty = TRUE;
bt->ndirty = MAX (bt->ndirty, idx+1);
*parent_ins = H5B_INS_NOOP;
} else if (H5B_INS_LEFT==my_ins || H5B_INS_RIGHT==my_ins) {
/*
* The child split. If the left node is anchored, then the new
* child node gets inserted to the right of our current position.
*/
if (H5B_ANCHOR_LT==anchor) idx++;
if (H5B_INS_RIGHT==my_ins) idx++;
if (bt->nchildren==2*H5B_K(f,type)) {
/* Split the current node */
if ((twin_addr = H5B_split (f, type, bt, addr, anchor))<0) {
if ((twin_addr = H5B_split (f, type, bt, addr, my_ins, udata))<0) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTSPLIT, FAIL);
}
if (NULL==(twin=H5AC_protect (f, H5AC_BT, twin_addr, type))) {
if (NULL==(twin=H5AC_protect (f, H5AC_BT, twin_addr, type,
udata))) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
}
if (idx<=H5B_K(f,type)) {
tmp_bt = H5B_ANCHOR_LT==anchor ? bt : twin;
tmp_bt = H5B_INS_RIGHT==my_ins ? bt : twin;
} else {
idx -= H5B_K (f, type);
tmp_bt = H5B_ANCHOR_LT==anchor ? twin : bt;
tmp_bt = H5B_INS_RIGHT==my_ins ? twin : bt;
}
} else {
tmp_bt = bt;
}
if (H5B_insert_child (f, type, tmp_bt, idx, child_addr, anchor,
if (H5B_insert_child (f, type, tmp_bt, idx, child_addr, my_ins,
md_key)<0) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTINSERT, FAIL);
}
@ -1177,7 +1305,7 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
* by the left and right node).
*/
if (twin) {
if (H5B_ANCHOR_LT==anchor) {
if (H5B_INS_RIGHT==my_ins) {
if (!twin->key[0].nkey && H5B_decode_key (f, twin, 0)<0) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL);
}
@ -1188,7 +1316,11 @@ H5B_insert_helper (H5F_t *f, haddr_t addr, H5B_class_t *type,
}
HDmemcpy (md_key, bt->key[0].nkey, type->sizeof_nkey);
}
*parent_ins = H5B_INS_RIGHT;
} else {
*parent_ins = H5B_INS_NOOP;
}
HGOTO_DONE (twin_addr);
done:
@ -1241,7 +1373,7 @@ H5B_list (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
assert (addr>=0);
assert (udata);
if (NULL==(bt = H5AC_find (f, H5AC_BT, addr, type))) {
if (NULL==(bt = H5AC_find (f, H5AC_BT, addr, type, udata))) {
HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
}
@ -1254,7 +1386,7 @@ H5B_list (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata)
} else {
for (/*void*/; addr>0; addr=next_addr) {
if (NULL==(bt=H5AC_protect (f, H5AC_BT, addr, type))) {
if (NULL==(bt=H5AC_protect (f, H5AC_BT, addr, type, udata))) {
HGOTO_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
}
@ -1318,6 +1450,7 @@ H5B_nodesize (H5F_t *f, const H5B_class_t *type,
assert (f);
assert (type);
assert (sizeof_rkey>0);
assert (H5B_K (f, type)>0);
/*
* Total native key size.
@ -1356,7 +1489,7 @@ H5B_nodesize (H5F_t *f, const H5B_class_t *type,
*/
herr_t
H5B_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent,
intn fwidth, H5B_class_t *type)
intn fwidth, H5B_class_t *type, void *udata)
{
H5B_t *bt = NULL;
int i;
@ -1376,7 +1509,7 @@ H5B_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent,
/*
* Load the tree node.
*/
if (NULL==(bt=H5AC_find (f, H5AC_BT, addr, type))) {
if (NULL==(bt=H5AC_find (f, H5AC_BT, addr, type, udata))) {
HRETURN_ERROR (H5E_BTREE, H5E_CANTLOAD, FAIL);
}

View File

@ -33,11 +33,17 @@
#define H5B_K(F,TYPE) /*K value given file and Btree subclass */ \
((F)->shared->file_create_parms.btree_k[(TYPE)->id])
#define H5B_ANCHOR_LT 0 /* left node is anchored, right is new */
#define H5B_ANCHOR_RT 1 /* right node is anchored, left is new */
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_t;
typedef enum H5B_subid_t {
H5B_SNODE_ID =0 /*B-tree is for symbol table nodes */
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;
@ -48,18 +54,21 @@ 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*/
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*);
haddr_t (*new)(H5F_t*,void*,void*,void*);
intn (*cmp)(H5F_t*,void*,void*,void*);
size_t (*get_sizeof_rkey)(H5F_t*,const void*);/*raw key size */
haddr_t (*new)(H5F_t*,void*,void*,void*); /*create new leaf */
intn (*cmp)(H5F_t*,void*,void*,void*); /*compare keys */
herr_t (*found)(H5F_t*,haddr_t,const void*,void*,const void*);
haddr_t (*insert)(H5F_t*,haddr_t,int*,void*,hbool_t*,void*,void*,
void*,hbool_t*);
herr_t (*list)(H5F_t*,haddr_t,void*);
herr_t (*decode)(H5F_t*,uint8*,void*);
herr_t (*encode)(H5F_t*,uint8*,void*);
haddr_t (*insert)(H5F_t*,haddr_t,H5B_ins_t*,void*,hbool_t*,void*,void*,
void*,hbool_t*); /*insert new data */
hbool_t follow_min; /*min insert uses min leaf, not new() */
hbool_t follow_max; /*max insert uses max leaf, not new() */
herr_t (*list)(H5F_t*,haddr_t,void*); /*traverse leaf nodes */
herr_t (*decode)(H5F_t*,struct H5B_t*,uint8*,void*);
herr_t (*encode)(H5F_t*,struct H5B_t*,uint8*,void*);
} H5B_class_t;
/*
@ -91,8 +100,8 @@ typedef struct H5B_t {
* Library prototypes.
*/
herr_t H5B_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent,
intn fwidth, H5B_class_t *type);
haddr_t H5B_new (H5F_t *f, const H5B_class_t *type);
intn fwidth, H5B_class_t *type, void *udata);
haddr_t H5B_new (H5F_t *f, const H5B_class_t *type, void *udata);
herr_t H5B_find (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata);
haddr_t H5B_insert (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata);
herr_t H5B_list (H5F_t *f, H5B_class_t *type, haddr_t addr, void *udata);

View File

@ -146,7 +146,7 @@ hid_t H5C_get_default_atom(hobjtype_t type)
case H5_TEMPLATE:
if(default_file_id==FAIL)
{
if((default_file_id=H5Aregister_atom(H5_TEMPLATE, (const VOIDP)&default_file_create))==FAIL)
if((default_file_id=H5Aregister_atom(H5_TEMPLATE, (const void *)&default_file_create))==FAIL)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL);
} /* end else */
HGOTO_DONE(default_file_id);
@ -324,6 +324,9 @@ done:
Robb Matzke, 13 Aug 1997
Removed H5_BTREE_SIZE and replaced it with H5_SYM_LEAF_K and
H5_SYM_INTERN_K.
Robb Matzke, 17 Oct 1997
Added H5_ISTORE_K.
--------------------------------------------------------------------------*/
herr_t H5Cgetparm(hid_t tid, file_create_param_t parm, VOIDP buf)
{
@ -365,6 +368,10 @@ herr_t H5Cgetparm(hid_t tid, file_create_param_t parm, VOIDP buf)
*(uintn *)buf = template->btree_k[H5B_SNODE_ID];
break;
case H5_ISTORE_K:
*(uintn *)buf = template->btree_k[H5B_ISTORE_ID];
break;
case H5_BOOTBLOCK_VER:
*(uint8 *)buf=template->bootblock_ver;
break;
@ -430,6 +437,9 @@ done:
Robb Matzke, 15 Sep 1997
Fixed the power-of-two test to work with any size integer.
Robb Matzke, 17 Oct 1997
Added H5_ISTORE_K.
--------------------------------------------------------------------------*/
herr_t H5Csetparm(hid_t tid, file_create_param_t parm, const VOIDP buf)
{
@ -494,6 +504,14 @@ herr_t H5Csetparm(hid_t tid, file_create_param_t parm, const VOIDP buf)
}
template->btree_k[H5B_SNODE_ID] = val;
break;
case H5_ISTORE_K:
val = *(const uintn *)buf;
if (val<2) {
HGOTO_ERROR (H5E_ARGS, H5E_BADRANGE, FAIL);
}
template->btree_k[H5B_ISTORE_ID] = val;
break;
case H5_BOOTBLOCK_VER: /* this should be range checked */
template->bootblock_ver=*(const uint8 *)buf;

View File

@ -34,7 +34,7 @@
#define H5C_BTREE_K_DEFAULT { \
16, /* Symbol table internal nodes */ \
0, /* unused */ \
32, /* Indexed storage intern nodes */ \
0, /* unused */ \
0, /* unused */ \
0, /* unused */ \

View File

@ -37,6 +37,7 @@ typedef enum {
H5_LENGTH_SIZE, /* (uint8) Number of bytes for lengths */
H5_SYM_LEAF_K, /* (uintn) 1/2 rank for symbol table leaf nodes */
H5_SYM_INTERN_K, /* (uintn) 1/2 rank for symbol table internal nodes */
H5_ISTORE_K, /* (uintn) 1/2 rank for indexed storage nodes */
H5_BOOTBLOCK_VER, /* (uint8) Version # of the boot-block format */
H5_SMALLOBJECT_VER, /* (uint8) Version # of the small-object heap format */
H5_FREESPACE_VER, /* (uint8) Version # of the free-space info format */

View File

@ -158,7 +158,7 @@ hid_t H5D_create(hid_t owner_id, hobjtype_t type, const char *name)
/* Open (and create) a new file object */
if (NULL==(new_dset->ent = H5G_create (file, name, H5D_MINHDR_SIZE))) {
HGOTO_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL);
HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL);
}
/* Register the new datatype and get an ID for it */
@ -183,14 +183,14 @@ done:
Get the OID for accessing an existing HDF5 dataset object
USAGE
hoid_t H5D_find_name(grp_id, type, name)
hid_t grp_id; IN: Atom for directory to search for dataset
hid_t grp_id; IN: Atom for group to search for dataset
hobjtype_t type; IN: Type of object to search for (dataset in
this case)
const char *name; IN: Name of the object to search for
RETURNS
Returns ID (atom) on success, FAIL on failure
DESCRIPTION
This function finds for a dataset by name in a directory.
This function finds for a dataset by name in a group.
--------------------------------------------------------------------------*/
hid_t H5D_find_name(hid_t grp_id, hobjtype_t obj_type, const char *name)
{
@ -215,7 +215,7 @@ hid_t H5D_find_name(hid_t grp_id, hobjtype_t obj_type, const char *name)
if(NULL==(dset=HDcalloc(1, sizeof(H5D_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL);
/* Initialize file, directory, name fields */
/* Initialize file, group, name fields */
dset->file = file;
dset->dirty = FALSE;

740
src/H5Distore.c Normal file
View File

@ -0,0 +1,740 @@
/*
* Copyright (C) 1997 Spizella Software
* All rights reserved.
*
* Programmer: Robb Matzke <robb@arborea.spizella.com>
* Wednesday, October 8, 1997
*/
#include <H5private.h>
#include <H5Eprivate.h>
#include <H5Fprivate.h>
#include <H5MFprivate.h>
#include <H5MMprivate.h>
#include <H5Oprivate.h>
#include <H5Vprivate.h>
typedef enum H5F_isop_t {
H5F_ISTORE_READ, /*read from file to memory */
H5F_ISTORE_WRITE /*write from memory to file */
} H5F_isop_t;
/* Does the array domain include negative indices? */
#undef H5F_ISTORE_NEGATIVE_DOMAIN
#define PABLO_MASK H5F_istore_mask
/* Is the interface initialized? */
static hbool_t interface_initialize_g = FALSE;
/* PRIVATE PROTOTYPES */
static size_t H5F_istore_sizeof_rkey (H5F_t *f, const void *_udata);
static haddr_t H5F_istore_new (H5F_t *f, void *_lt_key, void *_udata,
void *_rt_key);
static intn H5F_istore_cmp (H5F_t *f, void *_lt_key, void *_udata,
void *_rt_key);
static herr_t H5F_istore_found (H5F_t *f, haddr_t addr, const void *_lt_key,
void *_udata, const void *_rt_key);
static haddr_t H5F_istore_insert (H5F_t *f, haddr_t addr, H5B_ins_t *anchor,
void *_lt_key, hbool_t *lt_key_changed,
void *_md_key, void *_udata,
void *_rt_key, hbool_t *rt_key_changed);
static herr_t H5F_istore_decode_key (H5F_t *f, H5B_t *bt, uint8 *raw,
void *_key);
static herr_t H5F_istore_encode_key (H5F_t *f, H5B_t *bt, uint8 *raw,
void *_key);
static herr_t H5F_istore_copy_hyperslab (H5F_t *f, H5O_istore_t *istore,
H5F_isop_t op, size_t offset_f[],
size_t size[], size_t offset_m[],
size_t size_m[], void *buf);
/*
* B-tree key. A key contains the minimum logical N-dimensional address and
* the logical size of the chunk to which this key refers. The
* fastest-varying dimension is assumed to reference individual bytes of the
* array, so a 100-element 1-d array of 4-byte integers would really be a 2-d
* array with the slow varying dimension of size 100 and the fast varying
* dimension of size 4 (the storage dimensionality has very little to do with
* the real dimensionality).
*
* Only the first few values of the OFFSET and SIZE fields are actually
* stored on disk, depending on the dimensionality.
*
* The storage file address is part of the B-tree and not part of the key.
*/
typedef struct H5F_istore_key_t {
size_t offset[H5O_ISTORE_NDIMS]; /*logical offset to start*/
size_t size[H5O_ISTORE_NDIMS]; /*logical chunk size */
} H5F_istore_key_t;
typedef struct H5F_istore_ud1_t {
H5F_istore_key_t key; /*key values */
haddr_t addr; /*file address of chunk */
H5O_istore_t mesg; /*storage message */
} H5F_istore_ud1_t;
/* inherits B-tree like properties from H5B */
H5B_class_t H5B_ISTORE[1] = {{
H5B_ISTORE_ID, /*id */
sizeof (H5F_istore_key_t), /*sizeof_nkey */
H5F_istore_sizeof_rkey, /*get_sizeof_rkey */
H5F_istore_new, /*new */
H5F_istore_cmp, /*cmp */
H5F_istore_found, /*found */
H5F_istore_insert, /*insert */
FALSE, /*follow min branch? */
FALSE, /*follow max branch? */
NULL, /*list */
H5F_istore_decode_key, /*decode */
H5F_istore_encode_key, /*encode */
}};
/*-------------------------------------------------------------------------
* Function: H5F_istore_sizeof_rkey
*
* Purpose: Returns the size of a raw key for the specified UDATA. The
* size of the key is dependent on the number of dimensions for
* the object to which this B-tree points. The dimensionality
* of the UDATA is the only portion that's referenced here.
*
* Return: Success: Size of raw key in bytes.
*
* Failure: abort()
*
* Programmer: Robb Matzke
* Wednesday, October 8, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static size_t
H5F_istore_sizeof_rkey (H5F_t *f, const void *_udata)
{
const H5F_istore_ud1_t *udata = (const H5F_istore_ud1_t *)_udata;
assert (udata);
assert (udata->mesg.ndims>0 && udata->mesg.ndims<=H5O_ISTORE_NDIMS);
return udata->mesg.ndims * (4 + 4);
}
/*-------------------------------------------------------------------------
* Function: H5F_istore_decode_key
*
* Purpose: Decodes a raw key into a native key for the B-tree
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Friday, October 10, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static herr_t
H5F_istore_decode_key (H5F_t *f, H5B_t *bt, uint8 *raw, void *_key)
{
H5F_istore_key_t *key = (H5F_istore_key_t *)_key;
int i;
int ndims = bt->sizeof_rkey / 8;
FUNC_ENTER (H5F_istore_decode_key, NULL, FAIL);
/* check args */
assert (f);
assert (bt);
assert (raw);
assert (key);
assert (ndims>0 && ndims<=H5O_ISTORE_NDIMS && 8*ndims==bt->sizeof_rkey);
/* decode */
for (i=0; i<ndims; i++) {
UINT32DECODE (raw, key->offset[i]);
UINT32DECODE (raw, key->size[i]);
}
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5F_istore_encode_key
*
* Purpose: Encode a key from native format to raw format.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Friday, October 10, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static herr_t
H5F_istore_encode_key (H5F_t *f, H5B_t *bt, uint8 *raw, void *_key)
{
H5F_istore_key_t *key = (H5F_istore_key_t *)_key;
intn ndims = bt->sizeof_rkey / 8;
intn i;
FUNC_ENTER (H5F_istore_encode_key, NULL, FAIL);
/* check args */
assert (f);
assert (bt);
assert (raw);
assert (key);
assert (ndims>0 && ndims<=H5O_ISTORE_NDIMS && 8*ndims==bt->sizeof_rkey);
/* encode */
for (i=0; i<ndims; i++) {
UINT32ENCODE (raw, key->offset[i]);
UINT32ENCODE (raw, key->size[i]);
}
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5F_istore_cmp
*
* Purpose: Compare the requested datum UDATA with the left and right
* keys of the B-tree.
*
* Return: Success: negative if the min_corner of UDATA is less
* than the min_corner of LT_KEY.
*
* positive if the min_corner of UDATA is
* greater than or equal the min_corner of
* RT_KEY.
*
* zero otherwise. The min_corner of UDATA is
* not necessarily contained within the address
* space represented by LT_KEY, but a key that
* would describe the UDATA min_corner address
* would fall lexicographically between LT_KEY
* and RT_KEY.
*
* Failure: FAIL (same as UDATA < LT_KEY)
*
* Programmer: Robb Matzke
* Wednesday, October 8, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static intn
H5F_istore_cmp (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
{
H5F_istore_key_t *lt_key = (H5F_istore_key_t *)_lt_key;
H5F_istore_key_t *rt_key = (H5F_istore_key_t *)_rt_key;
H5F_istore_ud1_t *udata = (H5F_istore_ud1_t *)_udata;
assert (lt_key);
assert (rt_key);
assert (udata);
assert (udata->mesg.ndims>0 && udata->mesg.ndims<=H5O_ISTORE_NDIMS);
if (H5V_vector_lt (udata->mesg.ndims, udata->key.offset, lt_key->offset)) {
return -1;
} else if (H5V_vector_ge (udata->mesg.ndims, udata->key.offset,
rt_key->offset)) {
return 1;
} else {
return 0;
}
}
/*-------------------------------------------------------------------------
* Function: H5F_istore_new
*
* Purpose: Adds a new entry to an i-storage B-tree. We can assume that
* the domain represented by UDATA doesn't intersect the domain
* already represented by the B-tree.
*
* Return: Success: Address of leaf, which is passed in from the
* UDATA pointer.
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Tuesday, October 14, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static haddr_t
H5F_istore_new (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
{
H5F_istore_key_t *lt_key = (H5F_istore_key_t *)_lt_key;
H5F_istore_key_t *rt_key = (H5F_istore_key_t *)_rt_key;
H5F_istore_ud1_t *udata = (H5F_istore_ud1_t *)_udata;
size_t nbytes;
intn i;
FUNC_ENTER (H5F_istore_new, NULL, FAIL);
/* check args */
assert (f);
assert (lt_key);
assert (rt_key);
assert (udata);
assert (udata->mesg.ndims>=0 && udata->mesg.ndims<H5O_ISTORE_NDIMS);
/* Allocate new storage */
nbytes = H5V_vector_reduce_product (udata->mesg.ndims, udata->key.size);
assert (nbytes>0);
if ((udata->addr=H5MF_alloc (f, nbytes))<0) {
/* Couldn't allocate new file storage */
HRETURN_ERROR (H5E_IO, H5E_CANTINIT, FAIL);
}
/* left key describes the UDATA, right key is a zero-size "edge" */
for (i=0; i<udata->mesg.ndims; i++) {
lt_key->offset[i] = udata->key.offset[i];
lt_key->size[i] = udata->key.size[i];
assert (udata->key.size[i]>0);
rt_key->offset[i] = udata->key.offset[i] + udata->key.size[i];
rt_key->size[i] = 0;
}
FUNC_LEAVE (udata->addr);
}
/*-------------------------------------------------------------------------
* Function: H5F_istore_found
*
* Purpose: This function is called when the B-tree search engine has
* found the leaf entry that points to a chunk of storage that
* contains the beginning of the logical address space
* represented by UDATA. The LT_KEY is the left key (the one
* that describes the chunk) and RT_KEY is the right key (the
* one that describes the next or last chunk).
*
* Return: Success: SUCCEED with information about the chunk
* returned through the UDATA argument.
*
* Failure: FAIL if not found.
*
* Programmer: Robb Matzke
* Thursday, October 9, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static herr_t
H5F_istore_found (H5F_t *f, haddr_t addr, const void *_lt_key,
void *_udata, const void *_rt_key)
{
H5F_istore_ud1_t *udata = (H5F_istore_ud1_t *)_udata;
const H5F_istore_key_t *lt_key = (const H5F_istore_key_t *)_lt_key;
const H5F_istore_key_t *rt_key = (const H5F_istore_key_t *)_rt_key;
int i;
FUNC_ENTER (H5F_istore_found, NULL, FAIL);
/* Check arguments */
assert (f);
assert (addr>=0);
assert (udata);
assert (lt_key);
assert (rt_key);
/* Initialize return values */
udata->addr = addr;
for (i=0; i<udata->mesg.ndims; i++) {
udata->key.offset[i] = lt_key->offset[i];
udata->key.size[i] = lt_key->size[i];
assert (lt_key->size[i]>0);
}
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5F_istore_insert
*
* Purpose: This function is called when the B-tree insert engine finds
* the node to use to insert new data. The UDATA argument
* points to a struct that describes the logical addresses being
* added to the file. This function allocates space for the
* data and returns information through UDATA describing a
* file chunk to receive (part of) the data.
*
* The LT_KEY is always the key describing the chunk of file
* memory at address ADDR. On entry, UDATA describes the logical
* addresses for which storage is being requested (through the
* `offset' and `size' fields). On return, UDATA describes the
* logical addresses contained in a chunk on disk.
*
* Return: Success: SUCCEED, with UDATA containing information
* about the (newly allocated) chunk.
*
* If the storage address has changed then the
* new address is returned.
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Thursday, October 9, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static haddr_t
H5F_istore_insert (H5F_t *f, haddr_t addr, H5B_ins_t *parent_ins,
void *_lt_key, hbool_t *lt_key_changed,
void *_md_key, void *_udata,
void *_rt_key, hbool_t *rt_key_changed)
{
H5F_istore_key_t *lt_key = (H5F_istore_key_t *)_lt_key;
H5F_istore_key_t *md_key = (H5F_istore_key_t *)_md_key;
H5F_istore_key_t *rt_key = (H5F_istore_key_t *)_rt_key;
H5F_istore_ud1_t *udata = (H5F_istore_ud1_t *)_udata;
intn i, cmp;
haddr_t ret_value = 0;
size_t nbytes;
FUNC_ENTER (H5F_istore_insert, NULL, FAIL);
/* check args */
assert (f);
assert (addr>=0);
assert (parent_ins);
assert (lt_key);
assert (lt_key_changed);
assert (md_key);
assert (udata);
assert (rt_key);
assert (rt_key_changed);
cmp = H5F_istore_cmp (f, lt_key, udata, rt_key);
assert (cmp<=0);
if (cmp<0) {
/* Negative indices not supported yet */
assert ("HDF5 INTERNAL ERROR -- see rpm" && 0);
HRETURN_ERROR (H5E_STORAGE, H5E_UNSUPPORTED, FAIL);
} else if (H5V_hyper_eq (udata->mesg.ndims,
udata->key.offset, udata->key.size,
lt_key->offset, lt_key->size)) {
/*
* Already exists. Just return the info.
*/
udata->addr = addr;
*parent_ins = H5B_INS_NOOP;
} else if (H5V_hyper_disjointp (udata->mesg.ndims,
lt_key->offset, lt_key->size,
udata->key.offset, udata->key.size)) {
assert (H5V_hyper_disjointp (udata->mesg.ndims,
rt_key->offset, rt_key->size,
udata->key.offset, udata->key.size));
/*
* Split this node, inserting the new new node to the right of the
* current node. The MD_KEY is where the split occurs.
*/
for (i=0, nbytes=1; i<udata->mesg.ndims; i++) {
assert (0==udata->key.offset[i] % udata->mesg.alignment[i]);
assert (udata->key.size[i] == udata->mesg.alignment[i]);
md_key->offset[i] = udata->key.offset[i];
md_key->size[i] = udata->key.size[i];
nbytes *= udata->key.size[i];
}
/*
* Allocate storage for the new chunk
*/
if ((udata->addr=ret_value=H5MF_alloc (f, nbytes))<=0) {
HRETURN_ERROR (H5E_IO, H5E_CANTINIT, FAIL);
}
*parent_ins = H5B_INS_RIGHT;
} else {
assert ("HDF5 INTERNAL ERROR -- see rpm" && 0);
HRETURN_ERROR (H5E_IO, H5E_UNSUPPORTED, FAIL);
}
FUNC_LEAVE (ret_value);
}
/*-------------------------------------------------------------------------
* Function: H5F_istore_copy_hyperslab
*
* Purpose: Reads or writes a hyperslab to disk depending on whether OP
* is H5F_ISTORE_READ or H5F_ISTORE_WRITE. The hyperslab
* storage is described with ISTORE and exists in file F. The
* file hyperslab begins at location OFFSET_F[] (an N-dimensional
* point in the domain in terms of elements) in the file and
* OFFSET_M[] in memory pointed to by BUF. Its size is SIZE[]
* elements. The dimensionality of memory is assumed to be the
* same as the file and the total size of the multi-dimensional
* memory buffer is SIZE_M[].
*
* The slowest varying dimension is always listed first in the
* various offset and size arrays.
*
* A `chunk' is a hyperslab of the disk array which is stored
* contiguously. I/O occurs in units of chunks where the size of
* a chunk is determined by the alignment constraints specified
* in ISTORE.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Friday, October 17, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static herr_t
H5F_istore_copy_hyperslab (H5F_t *f, H5O_istore_t *istore, H5F_isop_t op,
size_t offset_f[], size_t size[],
size_t offset_m[], size_t size_m[], void *buf)
{
intn i, carry;
size_t idx_cur[H5O_ISTORE_NDIMS];
size_t idx_min[H5O_ISTORE_NDIMS];
size_t idx_max[H5O_ISTORE_NDIMS];
size_t sub_size[H5O_ISTORE_NDIMS];
size_t sub_offset_f[H5O_ISTORE_NDIMS];
size_t sub_offset_m[H5O_ISTORE_NDIMS];
size_t sub_offset_ch[H5O_ISTORE_NDIMS];
size_t chunk_size;
uint8 *chunk=NULL;
H5F_istore_ud1_t udata;
herr_t status;
herr_t ret_value = FAIL;
FUNC_ENTER (H5F_istore_copy_hyperslab, NULL, FAIL);
/* check args */
assert (f);
assert (istore);
assert (istore->ndims>0 && istore->ndims<=H5O_ISTORE_NDIMS);
assert (H5F_ISTORE_READ==op || H5F_ISTORE_WRITE==op);
assert (size);
assert (size_m);
assert (buf);
#ifndef NDEBUG
for (i=0; i<istore->ndims; i++) {
assert (!offset_f || offset_f[i]>=0);/*neg domains unsupported */
assert (!offset_m || offset_m[i]>=0);/*mem array offset never neg */
assert (size[i]>=0); /*size may be zero, implies no-op */
assert (size_m[i]>0); /*destination must exist */
/*hyperslab must fit in BUF*/
assert ((offset_m?offset_m[i]:0)+size[i]<=size_m[i]);
assert (istore->alignment[i]>0);
}
#endif
/*
* Does the B-tree exist?
*/
if (istore->btree_addr<=0) {
if (H5F_ISTORE_WRITE==op) {
udata.mesg.ndims = istore->ndims;
if ((istore->btree_addr=H5B_new (f, H5B_ISTORE, &udata))<0) {
/* Can't create B-tree */
HGOTO_ERROR (H5E_IO, H5E_CANTINIT, FAIL);
}
} else {
H5V_hyper_fill (istore->ndims, size, size_m, offset_m, buf, 0);
HRETURN (SUCCEED);
}
}
/* Initialize indices */
for (i=0; i<istore->ndims; i++) {
idx_min[i] = (offset_f?offset_f[i]:0) / istore->alignment[i];
idx_max[i] = ((offset_f?offset_f[i]:0)+size[i]-1)/istore->alignment[i]+1;
idx_cur[i] = idx_min[i];
}
/* Allocate buffers */
for (i=0, chunk_size=1; i<istore->ndims; i++) {
chunk_size *= istore->alignment[i];
}
chunk = H5MM_xmalloc (chunk_size);
/* Initialize non-changing part of udata */
udata.mesg = *istore;
/* Loop over all chunks */
while (1) {
/* Read/Write chunk or create it if it doesn't exist */
udata.mesg.ndims = istore->ndims;
for (i=0; i<istore->ndims; i++) {
udata.key.offset[i] = idx_cur[i] * istore->alignment[i];
udata.key.size[i] = istore->alignment[i];
sub_offset_f[i] = MAX ((offset_f?offset_f[i]:0), udata.key.offset[i]);
sub_offset_m[i] = (offset_m?offset_m[i]:0) +
sub_offset_f[i] - (offset_f?offset_f[i]:0);
sub_size[i] = (idx_cur[i]+1)*istore->alignment[i]-sub_offset_f[i];
sub_offset_ch[i] = sub_offset_f[i] - udata.key.offset[i];
}
if (H5F_ISTORE_WRITE==op) {
status = H5B_insert (f, H5B_ISTORE, istore->btree_addr, &udata);
assert (status>=0);
} else {
status = H5B_find (f, H5B_ISTORE, istore->btree_addr, &udata);
}
/*
* If the operation is reading from the disk or if we are writing a
* partial chunk then load the chunk from disk.
*/
if (H5F_ISTORE_READ==op ||
!H5V_hyper_eq (istore->ndims,
udata.key.offset, udata.key.size,
sub_offset_f, sub_size)) {
if (status>=0) {
if (H5F_block_read (f, udata.addr, chunk_size, chunk)<0) {
HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL);
}
} else {
HDmemset (chunk, 0, chunk_size);
}
}
/* Transfer data to/from the chunk */
if (H5F_ISTORE_WRITE==op) {
H5V_hyper_copy (istore->ndims, sub_size,
udata.key.size, sub_offset_ch, chunk,
size_m, sub_offset_m, buf);
if (H5F_block_write (f, udata.addr, chunk_size, chunk)<0) {
HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL);
}
} else {
H5V_hyper_copy (istore->ndims, sub_size,
size_m, sub_offset_m, buf,
udata.key.size, sub_offset_ch, chunk);
}
/* Increment indices */
for (i=istore->ndims-1, carry=1; i>=0 && carry; --i) {
if (++idx_cur[i]>=idx_max[i]) idx_cur[i] = idx_min[i];
else carry = 0;
}
if (carry) break;
}
ret_value = SUCCEED;
done:
chunk = H5MM_xfree (chunk);
FUNC_LEAVE (ret_value);
}
/*-------------------------------------------------------------------------
* Function: H5F_istore_read
*
* Purpose: Reads a multi-dimensional buffer from (part of) an indexed raw
* storage array.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Wednesday, October 15, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5F_istore_read (H5F_t *f, struct H5O_istore_t *istore,
size_t offset[], size_t size[], void *buf)
{
FUNC_ENTER (H5F_istore_read, NULL, FAIL);
/* Check args */
assert (f);
assert (istore);
assert (istore->ndims>0 && istore->ndims<=H5O_ISTORE_NDIMS);
assert (size);
assert (buf);
if (H5F_istore_copy_hyperslab (f, istore, H5F_ISTORE_READ,
offset, size, H5V_ZERO, size, buf)<0) {
/* hyperslab output failure */
HRETURN_ERROR (H5E_IO, H5E_READERROR, FAIL);
}
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5F_istore_write
*
* Purpose: Writes a multi-dimensional buffer to (part of) an indexed raw
* storage array.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Wednesday, October 15, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5F_istore_write (H5F_t *f, struct H5O_istore_t *istore,
size_t offset[], size_t size[], void *buf)
{
FUNC_ENTER (H5F_istore_write, NULL, FAIL);
/* Check args */
assert (f);
assert (istore);
assert (istore->ndims>0 && istore->ndims<=H5O_ISTORE_NDIMS);
assert (size);
assert (buf);
if (H5F_istore_copy_hyperslab (f, istore, H5F_ISTORE_WRITE,
offset, size, H5V_ZERO, size, buf)<0) {
/* hyperslab output failure */
HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL);
}
FUNC_LEAVE (SUCCEED);
}

View File

@ -59,10 +59,10 @@ static const hdf_maj_error_messages_t hdf_maj_error_messages[] =
{H5E_SYM, "Symbol Table"},
{H5E_HEAP, "Heap"},
{H5E_OHDR, "Object Header"},
{H5E_DIRECTORY, "Directory"},
{H5E_DATATYPE, "Datatype"},
{H5E_DATASPACE, "Dataspace"},
{H5E_DATASET, "Dataset"}
{H5E_DATASET, "Dataset"},
{H5E_STORAGE, "Data Storage"},
};
static const hdf_min_error_messages_t hdf_min_error_messages[] =
@ -104,6 +104,7 @@ static const hdf_min_error_messages_t hdf_min_error_messages[] =
{H5E_ALIGNMENT, "Alignment error"},
{H5E_BADMESG, "Unrecognized message"},
{H5E_COMPLEN, "Name component is too long"},
{H5E_CWG, "Problem with current working group"},
{H5E_LINK, "Link count failure"},
};

View File

@ -38,10 +38,10 @@ typedef enum
H5E_SYM, /* Symbol Table */
H5E_HEAP, /* Heap */
H5E_OHDR, /* Object Header */
H5E_DIRECTORY, /* Directory */
H5E_DATATYPE, /* Datatype */
H5E_DATASPACE, /* Dataspace */
H5E_DATASET /* Dataset */
H5E_DATASPACE, /* Dataspace */
H5E_DATASET, /* Dataset */
H5E_STORAGE /* Data storage */
}
hdf_maj_err_code_t;
@ -102,9 +102,10 @@ typedef enum
H5E_ALIGNMENT, /* Alignment error */
H5E_BADMESG, /* Unrecognized message */
/* Directory related errors */
/* Group related errors */
H5E_CANTOPENOBJ, /* Can't open object */
H5E_COMPLEN, /* Name component is too long */
H5E_CWG, /* Problem with current working group */
H5E_LINK /* Link count failure */
}
hdf_min_err_code_t;

View File

@ -69,7 +69,6 @@ static herr_t H5F_init_interface(void);
static H5F_t *H5F_new (H5F_file_t *shared);
static H5F_t *H5F_dest (H5F_t *f);
static herr_t H5F_flush (H5F_t *f, hbool_t invalidate);
static herr_t H5F_close (H5F_t *f);
/*--------------------------------------------------------------------------
NAME
@ -500,7 +499,7 @@ H5F_dest (H5F_t *f)
* block is written. This operation will fail
* if the file is already open.
*
* Unlinking the file name from the directory hierarchy while
* Unlinking the file name from the group directed graph while
* the file is opened causes the file to continue to exist but
* one will not be able to upgrade the file from read-only
* access to read-write access by reopening it. Disk resources
@ -508,13 +507,20 @@ H5F_dest (H5F_t *f)
* closed. NOTE: This paragraph probably only applies to Unix;
* deleting the file name in other OS's has undefined results.
*
* The CREATE_PARMS argument is optional. A null pointer will
* cause the default file creation parameters to be used.
*
* Errors:
* ATOM BADATOM Can't unatomize default template
* id.
* FILE BADVALUE Can't create file without write
* intent.
* FILE BADVALUE Can't truncate without write intent.
* FILE CANTCREATE Can't create file.
* FILE CANTCREATE Can't stat file.
* FILE CANTCREATE Can't truncate file.
* FILE CANTINIT Can't get default file create template
* id.
* FILE CANTINIT Can't write file boot block.
* FILE CANTINIT Cannot determine file size.
* FILE CANTOPENFILE Bad boot block version number.
@ -550,7 +556,7 @@ H5F_dest (H5F_t *f)
*
*-------------------------------------------------------------------------
*/
static H5F_t *
H5F_t *
H5F_open (const char *name, uintn flags,
const file_create_temp_t *create_parms)
{
@ -572,6 +578,21 @@ H5F_open (const char *name, uintn flags,
assert (name && *name);
/*
* If no file creation parameters are supplied then use defaults.
*/
if (!create_parms) {
hid_t create_temp = H5C_get_default_atom (H5_TEMPLATE);
if (create_temp<0) {
/* Can't get default file create template id */
HRETURN_ERROR (H5E_FILE, H5E_CANTINIT, NULL);
}
if (NULL==(create_parms=H5Aatom_object (create_temp))) {
/* Can't unatomize default template id */
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL);
}
}
/*
* Does the file exist? If so, get the device and i-node values so we can
* compare them with other files already open. On Unix (and other systems
@ -984,11 +1005,6 @@ hid_t H5Fcreate(const char *filename, uintn flags, hid_t create_temp,
hid_t H5Fopen(const char *filename, uintn flags, hid_t access_temp)
{
H5F_t *new_file=NULL; /* file struct for new file */
hid_t create_temp; /* file-creation template ID */
const file_create_temp_t *f_create_parms; /* pointer to the parameters
* to use when creating the
* file
*/
hid_t ret_value = FAIL;
FUNC_ENTER(H5Fopen, H5F_init_interface, FAIL);
@ -999,10 +1015,6 @@ hid_t H5Fopen(const char *filename, uintn flags, hid_t access_temp)
HGOTO_ERROR (H5E_ARGS, H5E_BADRANGE, FAIL);/*invalid file name*/
flags = flags & H5ACC_WRITE ? H5F_ACC_WRITE : 0;
create_temp = H5C_get_default_atom (H5_TEMPLATE);
if (NULL==(f_create_parms=H5Aatom_object(create_temp)))
HGOTO_ERROR (H5E_ATOM, H5E_BADATOM, FAIL);/*can't unatomize template*/
#ifdef LATER
if (access_temp<=0)
access_temp = H5CPget_default_atom (H5_TEMPLATE);
@ -1011,7 +1023,7 @@ hid_t H5Fopen(const char *filename, uintn flags, hid_t access_temp)
#endif
/* Open the file */
if (NULL==(new_file=H5F_open (filename, flags, f_create_parms))) {
if (NULL==(new_file=H5F_open (filename, flags, NULL))) {
HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, FAIL); /*cant open file*/
}
@ -1188,7 +1200,7 @@ H5Fflush (hid_t fid, hbool_t invalidate)
*
*-------------------------------------------------------------------------
*/
static herr_t
herr_t
H5F_close (H5F_t *f)
{
herr_t ret_value = FAIL;

740
src/H5Fistore.c Normal file
View File

@ -0,0 +1,740 @@
/*
* Copyright (C) 1997 Spizella Software
* All rights reserved.
*
* Programmer: Robb Matzke <robb@arborea.spizella.com>
* Wednesday, October 8, 1997
*/
#include <H5private.h>
#include <H5Eprivate.h>
#include <H5Fprivate.h>
#include <H5MFprivate.h>
#include <H5MMprivate.h>
#include <H5Oprivate.h>
#include <H5Vprivate.h>
typedef enum H5F_isop_t {
H5F_ISTORE_READ, /*read from file to memory */
H5F_ISTORE_WRITE /*write from memory to file */
} H5F_isop_t;
/* Does the array domain include negative indices? */
#undef H5F_ISTORE_NEGATIVE_DOMAIN
#define PABLO_MASK H5F_istore_mask
/* Is the interface initialized? */
static hbool_t interface_initialize_g = FALSE;
/* PRIVATE PROTOTYPES */
static size_t H5F_istore_sizeof_rkey (H5F_t *f, const void *_udata);
static haddr_t H5F_istore_new (H5F_t *f, void *_lt_key, void *_udata,
void *_rt_key);
static intn H5F_istore_cmp (H5F_t *f, void *_lt_key, void *_udata,
void *_rt_key);
static herr_t H5F_istore_found (H5F_t *f, haddr_t addr, const void *_lt_key,
void *_udata, const void *_rt_key);
static haddr_t H5F_istore_insert (H5F_t *f, haddr_t addr, H5B_ins_t *anchor,
void *_lt_key, hbool_t *lt_key_changed,
void *_md_key, void *_udata,
void *_rt_key, hbool_t *rt_key_changed);
static herr_t H5F_istore_decode_key (H5F_t *f, H5B_t *bt, uint8 *raw,
void *_key);
static herr_t H5F_istore_encode_key (H5F_t *f, H5B_t *bt, uint8 *raw,
void *_key);
static herr_t H5F_istore_copy_hyperslab (H5F_t *f, H5O_istore_t *istore,
H5F_isop_t op, size_t offset_f[],
size_t size[], size_t offset_m[],
size_t size_m[], void *buf);
/*
* B-tree key. A key contains the minimum logical N-dimensional address and
* the logical size of the chunk to which this key refers. The
* fastest-varying dimension is assumed to reference individual bytes of the
* array, so a 100-element 1-d array of 4-byte integers would really be a 2-d
* array with the slow varying dimension of size 100 and the fast varying
* dimension of size 4 (the storage dimensionality has very little to do with
* the real dimensionality).
*
* Only the first few values of the OFFSET and SIZE fields are actually
* stored on disk, depending on the dimensionality.
*
* The storage file address is part of the B-tree and not part of the key.
*/
typedef struct H5F_istore_key_t {
size_t offset[H5O_ISTORE_NDIMS]; /*logical offset to start*/
size_t size[H5O_ISTORE_NDIMS]; /*logical chunk size */
} H5F_istore_key_t;
typedef struct H5F_istore_ud1_t {
H5F_istore_key_t key; /*key values */
haddr_t addr; /*file address of chunk */
H5O_istore_t mesg; /*storage message */
} H5F_istore_ud1_t;
/* inherits B-tree like properties from H5B */
H5B_class_t H5B_ISTORE[1] = {{
H5B_ISTORE_ID, /*id */
sizeof (H5F_istore_key_t), /*sizeof_nkey */
H5F_istore_sizeof_rkey, /*get_sizeof_rkey */
H5F_istore_new, /*new */
H5F_istore_cmp, /*cmp */
H5F_istore_found, /*found */
H5F_istore_insert, /*insert */
FALSE, /*follow min branch? */
FALSE, /*follow max branch? */
NULL, /*list */
H5F_istore_decode_key, /*decode */
H5F_istore_encode_key, /*encode */
}};
/*-------------------------------------------------------------------------
* Function: H5F_istore_sizeof_rkey
*
* Purpose: Returns the size of a raw key for the specified UDATA. The
* size of the key is dependent on the number of dimensions for
* the object to which this B-tree points. The dimensionality
* of the UDATA is the only portion that's referenced here.
*
* Return: Success: Size of raw key in bytes.
*
* Failure: abort()
*
* Programmer: Robb Matzke
* Wednesday, October 8, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static size_t
H5F_istore_sizeof_rkey (H5F_t *f, const void *_udata)
{
const H5F_istore_ud1_t *udata = (const H5F_istore_ud1_t *)_udata;
assert (udata);
assert (udata->mesg.ndims>0 && udata->mesg.ndims<=H5O_ISTORE_NDIMS);
return udata->mesg.ndims * (4 + 4);
}
/*-------------------------------------------------------------------------
* Function: H5F_istore_decode_key
*
* Purpose: Decodes a raw key into a native key for the B-tree
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Friday, October 10, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static herr_t
H5F_istore_decode_key (H5F_t *f, H5B_t *bt, uint8 *raw, void *_key)
{
H5F_istore_key_t *key = (H5F_istore_key_t *)_key;
int i;
int ndims = bt->sizeof_rkey / 8;
FUNC_ENTER (H5F_istore_decode_key, NULL, FAIL);
/* check args */
assert (f);
assert (bt);
assert (raw);
assert (key);
assert (ndims>0 && ndims<=H5O_ISTORE_NDIMS && 8*ndims==bt->sizeof_rkey);
/* decode */
for (i=0; i<ndims; i++) {
UINT32DECODE (raw, key->offset[i]);
UINT32DECODE (raw, key->size[i]);
}
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5F_istore_encode_key
*
* Purpose: Encode a key from native format to raw format.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Friday, October 10, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static herr_t
H5F_istore_encode_key (H5F_t *f, H5B_t *bt, uint8 *raw, void *_key)
{
H5F_istore_key_t *key = (H5F_istore_key_t *)_key;
intn ndims = bt->sizeof_rkey / 8;
intn i;
FUNC_ENTER (H5F_istore_encode_key, NULL, FAIL);
/* check args */
assert (f);
assert (bt);
assert (raw);
assert (key);
assert (ndims>0 && ndims<=H5O_ISTORE_NDIMS && 8*ndims==bt->sizeof_rkey);
/* encode */
for (i=0; i<ndims; i++) {
UINT32ENCODE (raw, key->offset[i]);
UINT32ENCODE (raw, key->size[i]);
}
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5F_istore_cmp
*
* Purpose: Compare the requested datum UDATA with the left and right
* keys of the B-tree.
*
* Return: Success: negative if the min_corner of UDATA is less
* than the min_corner of LT_KEY.
*
* positive if the min_corner of UDATA is
* greater than or equal the min_corner of
* RT_KEY.
*
* zero otherwise. The min_corner of UDATA is
* not necessarily contained within the address
* space represented by LT_KEY, but a key that
* would describe the UDATA min_corner address
* would fall lexicographically between LT_KEY
* and RT_KEY.
*
* Failure: FAIL (same as UDATA < LT_KEY)
*
* Programmer: Robb Matzke
* Wednesday, October 8, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static intn
H5F_istore_cmp (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
{
H5F_istore_key_t *lt_key = (H5F_istore_key_t *)_lt_key;
H5F_istore_key_t *rt_key = (H5F_istore_key_t *)_rt_key;
H5F_istore_ud1_t *udata = (H5F_istore_ud1_t *)_udata;
assert (lt_key);
assert (rt_key);
assert (udata);
assert (udata->mesg.ndims>0 && udata->mesg.ndims<=H5O_ISTORE_NDIMS);
if (H5V_vector_lt (udata->mesg.ndims, udata->key.offset, lt_key->offset)) {
return -1;
} else if (H5V_vector_ge (udata->mesg.ndims, udata->key.offset,
rt_key->offset)) {
return 1;
} else {
return 0;
}
}
/*-------------------------------------------------------------------------
* Function: H5F_istore_new
*
* Purpose: Adds a new entry to an i-storage B-tree. We can assume that
* the domain represented by UDATA doesn't intersect the domain
* already represented by the B-tree.
*
* Return: Success: Address of leaf, which is passed in from the
* UDATA pointer.
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Tuesday, October 14, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static haddr_t
H5F_istore_new (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key)
{
H5F_istore_key_t *lt_key = (H5F_istore_key_t *)_lt_key;
H5F_istore_key_t *rt_key = (H5F_istore_key_t *)_rt_key;
H5F_istore_ud1_t *udata = (H5F_istore_ud1_t *)_udata;
size_t nbytes;
intn i;
FUNC_ENTER (H5F_istore_new, NULL, FAIL);
/* check args */
assert (f);
assert (lt_key);
assert (rt_key);
assert (udata);
assert (udata->mesg.ndims>=0 && udata->mesg.ndims<H5O_ISTORE_NDIMS);
/* Allocate new storage */
nbytes = H5V_vector_reduce_product (udata->mesg.ndims, udata->key.size);
assert (nbytes>0);
if ((udata->addr=H5MF_alloc (f, nbytes))<0) {
/* Couldn't allocate new file storage */
HRETURN_ERROR (H5E_IO, H5E_CANTINIT, FAIL);
}
/* left key describes the UDATA, right key is a zero-size "edge" */
for (i=0; i<udata->mesg.ndims; i++) {
lt_key->offset[i] = udata->key.offset[i];
lt_key->size[i] = udata->key.size[i];
assert (udata->key.size[i]>0);
rt_key->offset[i] = udata->key.offset[i] + udata->key.size[i];
rt_key->size[i] = 0;
}
FUNC_LEAVE (udata->addr);
}
/*-------------------------------------------------------------------------
* Function: H5F_istore_found
*
* Purpose: This function is called when the B-tree search engine has
* found the leaf entry that points to a chunk of storage that
* contains the beginning of the logical address space
* represented by UDATA. The LT_KEY is the left key (the one
* that describes the chunk) and RT_KEY is the right key (the
* one that describes the next or last chunk).
*
* Return: Success: SUCCEED with information about the chunk
* returned through the UDATA argument.
*
* Failure: FAIL if not found.
*
* Programmer: Robb Matzke
* Thursday, October 9, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static herr_t
H5F_istore_found (H5F_t *f, haddr_t addr, const void *_lt_key,
void *_udata, const void *_rt_key)
{
H5F_istore_ud1_t *udata = (H5F_istore_ud1_t *)_udata;
const H5F_istore_key_t *lt_key = (const H5F_istore_key_t *)_lt_key;
const H5F_istore_key_t *rt_key = (const H5F_istore_key_t *)_rt_key;
int i;
FUNC_ENTER (H5F_istore_found, NULL, FAIL);
/* Check arguments */
assert (f);
assert (addr>=0);
assert (udata);
assert (lt_key);
assert (rt_key);
/* Initialize return values */
udata->addr = addr;
for (i=0; i<udata->mesg.ndims; i++) {
udata->key.offset[i] = lt_key->offset[i];
udata->key.size[i] = lt_key->size[i];
assert (lt_key->size[i]>0);
}
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5F_istore_insert
*
* Purpose: This function is called when the B-tree insert engine finds
* the node to use to insert new data. The UDATA argument
* points to a struct that describes the logical addresses being
* added to the file. This function allocates space for the
* data and returns information through UDATA describing a
* file chunk to receive (part of) the data.
*
* The LT_KEY is always the key describing the chunk of file
* memory at address ADDR. On entry, UDATA describes the logical
* addresses for which storage is being requested (through the
* `offset' and `size' fields). On return, UDATA describes the
* logical addresses contained in a chunk on disk.
*
* Return: Success: SUCCEED, with UDATA containing information
* about the (newly allocated) chunk.
*
* If the storage address has changed then the
* new address is returned.
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Thursday, October 9, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static haddr_t
H5F_istore_insert (H5F_t *f, haddr_t addr, H5B_ins_t *parent_ins,
void *_lt_key, hbool_t *lt_key_changed,
void *_md_key, void *_udata,
void *_rt_key, hbool_t *rt_key_changed)
{
H5F_istore_key_t *lt_key = (H5F_istore_key_t *)_lt_key;
H5F_istore_key_t *md_key = (H5F_istore_key_t *)_md_key;
H5F_istore_key_t *rt_key = (H5F_istore_key_t *)_rt_key;
H5F_istore_ud1_t *udata = (H5F_istore_ud1_t *)_udata;
intn i, cmp;
haddr_t ret_value = 0;
size_t nbytes;
FUNC_ENTER (H5F_istore_insert, NULL, FAIL);
/* check args */
assert (f);
assert (addr>=0);
assert (parent_ins);
assert (lt_key);
assert (lt_key_changed);
assert (md_key);
assert (udata);
assert (rt_key);
assert (rt_key_changed);
cmp = H5F_istore_cmp (f, lt_key, udata, rt_key);
assert (cmp<=0);
if (cmp<0) {
/* Negative indices not supported yet */
assert ("HDF5 INTERNAL ERROR -- see rpm" && 0);
HRETURN_ERROR (H5E_STORAGE, H5E_UNSUPPORTED, FAIL);
} else if (H5V_hyper_eq (udata->mesg.ndims,
udata->key.offset, udata->key.size,
lt_key->offset, lt_key->size)) {
/*
* Already exists. Just return the info.
*/
udata->addr = addr;
*parent_ins = H5B_INS_NOOP;
} else if (H5V_hyper_disjointp (udata->mesg.ndims,
lt_key->offset, lt_key->size,
udata->key.offset, udata->key.size)) {
assert (H5V_hyper_disjointp (udata->mesg.ndims,
rt_key->offset, rt_key->size,
udata->key.offset, udata->key.size));
/*
* Split this node, inserting the new new node to the right of the
* current node. The MD_KEY is where the split occurs.
*/
for (i=0, nbytes=1; i<udata->mesg.ndims; i++) {
assert (0==udata->key.offset[i] % udata->mesg.alignment[i]);
assert (udata->key.size[i] == udata->mesg.alignment[i]);
md_key->offset[i] = udata->key.offset[i];
md_key->size[i] = udata->key.size[i];
nbytes *= udata->key.size[i];
}
/*
* Allocate storage for the new chunk
*/
if ((udata->addr=ret_value=H5MF_alloc (f, nbytes))<=0) {
HRETURN_ERROR (H5E_IO, H5E_CANTINIT, FAIL);
}
*parent_ins = H5B_INS_RIGHT;
} else {
assert ("HDF5 INTERNAL ERROR -- see rpm" && 0);
HRETURN_ERROR (H5E_IO, H5E_UNSUPPORTED, FAIL);
}
FUNC_LEAVE (ret_value);
}
/*-------------------------------------------------------------------------
* Function: H5F_istore_copy_hyperslab
*
* Purpose: Reads or writes a hyperslab to disk depending on whether OP
* is H5F_ISTORE_READ or H5F_ISTORE_WRITE. The hyperslab
* storage is described with ISTORE and exists in file F. The
* file hyperslab begins at location OFFSET_F[] (an N-dimensional
* point in the domain in terms of elements) in the file and
* OFFSET_M[] in memory pointed to by BUF. Its size is SIZE[]
* elements. The dimensionality of memory is assumed to be the
* same as the file and the total size of the multi-dimensional
* memory buffer is SIZE_M[].
*
* The slowest varying dimension is always listed first in the
* various offset and size arrays.
*
* A `chunk' is a hyperslab of the disk array which is stored
* contiguously. I/O occurs in units of chunks where the size of
* a chunk is determined by the alignment constraints specified
* in ISTORE.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Friday, October 17, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static herr_t
H5F_istore_copy_hyperslab (H5F_t *f, H5O_istore_t *istore, H5F_isop_t op,
size_t offset_f[], size_t size[],
size_t offset_m[], size_t size_m[], void *buf)
{
intn i, carry;
size_t idx_cur[H5O_ISTORE_NDIMS];
size_t idx_min[H5O_ISTORE_NDIMS];
size_t idx_max[H5O_ISTORE_NDIMS];
size_t sub_size[H5O_ISTORE_NDIMS];
size_t sub_offset_f[H5O_ISTORE_NDIMS];
size_t sub_offset_m[H5O_ISTORE_NDIMS];
size_t sub_offset_ch[H5O_ISTORE_NDIMS];
size_t chunk_size;
uint8 *chunk=NULL;
H5F_istore_ud1_t udata;
herr_t status;
herr_t ret_value = FAIL;
FUNC_ENTER (H5F_istore_copy_hyperslab, NULL, FAIL);
/* check args */
assert (f);
assert (istore);
assert (istore->ndims>0 && istore->ndims<=H5O_ISTORE_NDIMS);
assert (H5F_ISTORE_READ==op || H5F_ISTORE_WRITE==op);
assert (size);
assert (size_m);
assert (buf);
#ifndef NDEBUG
for (i=0; i<istore->ndims; i++) {
assert (!offset_f || offset_f[i]>=0);/*neg domains unsupported */
assert (!offset_m || offset_m[i]>=0);/*mem array offset never neg */
assert (size[i]>=0); /*size may be zero, implies no-op */
assert (size_m[i]>0); /*destination must exist */
/*hyperslab must fit in BUF*/
assert ((offset_m?offset_m[i]:0)+size[i]<=size_m[i]);
assert (istore->alignment[i]>0);
}
#endif
/*
* Does the B-tree exist?
*/
if (istore->btree_addr<=0) {
if (H5F_ISTORE_WRITE==op) {
udata.mesg.ndims = istore->ndims;
if ((istore->btree_addr=H5B_new (f, H5B_ISTORE, &udata))<0) {
/* Can't create B-tree */
HGOTO_ERROR (H5E_IO, H5E_CANTINIT, FAIL);
}
} else {
H5V_hyper_fill (istore->ndims, size, size_m, offset_m, buf, 0);
HRETURN (SUCCEED);
}
}
/* Initialize indices */
for (i=0; i<istore->ndims; i++) {
idx_min[i] = (offset_f?offset_f[i]:0) / istore->alignment[i];
idx_max[i] = ((offset_f?offset_f[i]:0)+size[i]-1)/istore->alignment[i]+1;
idx_cur[i] = idx_min[i];
}
/* Allocate buffers */
for (i=0, chunk_size=1; i<istore->ndims; i++) {
chunk_size *= istore->alignment[i];
}
chunk = H5MM_xmalloc (chunk_size);
/* Initialize non-changing part of udata */
udata.mesg = *istore;
/* Loop over all chunks */
while (1) {
/* Read/Write chunk or create it if it doesn't exist */
udata.mesg.ndims = istore->ndims;
for (i=0; i<istore->ndims; i++) {
udata.key.offset[i] = idx_cur[i] * istore->alignment[i];
udata.key.size[i] = istore->alignment[i];
sub_offset_f[i] = MAX ((offset_f?offset_f[i]:0), udata.key.offset[i]);
sub_offset_m[i] = (offset_m?offset_m[i]:0) +
sub_offset_f[i] - (offset_f?offset_f[i]:0);
sub_size[i] = (idx_cur[i]+1)*istore->alignment[i]-sub_offset_f[i];
sub_offset_ch[i] = sub_offset_f[i] - udata.key.offset[i];
}
if (H5F_ISTORE_WRITE==op) {
status = H5B_insert (f, H5B_ISTORE, istore->btree_addr, &udata);
assert (status>=0);
} else {
status = H5B_find (f, H5B_ISTORE, istore->btree_addr, &udata);
}
/*
* If the operation is reading from the disk or if we are writing a
* partial chunk then load the chunk from disk.
*/
if (H5F_ISTORE_READ==op ||
!H5V_hyper_eq (istore->ndims,
udata.key.offset, udata.key.size,
sub_offset_f, sub_size)) {
if (status>=0) {
if (H5F_block_read (f, udata.addr, chunk_size, chunk)<0) {
HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL);
}
} else {
HDmemset (chunk, 0, chunk_size);
}
}
/* Transfer data to/from the chunk */
if (H5F_ISTORE_WRITE==op) {
H5V_hyper_copy (istore->ndims, sub_size,
udata.key.size, sub_offset_ch, chunk,
size_m, sub_offset_m, buf);
if (H5F_block_write (f, udata.addr, chunk_size, chunk)<0) {
HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL);
}
} else {
H5V_hyper_copy (istore->ndims, sub_size,
size_m, sub_offset_m, buf,
udata.key.size, sub_offset_ch, chunk);
}
/* Increment indices */
for (i=istore->ndims-1, carry=1; i>=0 && carry; --i) {
if (++idx_cur[i]>=idx_max[i]) idx_cur[i] = idx_min[i];
else carry = 0;
}
if (carry) break;
}
ret_value = SUCCEED;
done:
chunk = H5MM_xfree (chunk);
FUNC_LEAVE (ret_value);
}
/*-------------------------------------------------------------------------
* Function: H5F_istore_read
*
* Purpose: Reads a multi-dimensional buffer from (part of) an indexed raw
* storage array.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Wednesday, October 15, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5F_istore_read (H5F_t *f, struct H5O_istore_t *istore,
size_t offset[], size_t size[], void *buf)
{
FUNC_ENTER (H5F_istore_read, NULL, FAIL);
/* Check args */
assert (f);
assert (istore);
assert (istore->ndims>0 && istore->ndims<=H5O_ISTORE_NDIMS);
assert (size);
assert (buf);
if (H5F_istore_copy_hyperslab (f, istore, H5F_ISTORE_READ,
offset, size, H5V_ZERO, size, buf)<0) {
/* hyperslab output failure */
HRETURN_ERROR (H5E_IO, H5E_READERROR, FAIL);
}
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5F_istore_write
*
* Purpose: Writes a multi-dimensional buffer to (part of) an indexed raw
* storage array.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Wednesday, October 15, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5F_istore_write (H5F_t *f, struct H5O_istore_t *istore,
size_t offset[], size_t size[], void *buf)
{
FUNC_ENTER (H5F_istore_write, NULL, FAIL);
/* Check args */
assert (f);
assert (istore);
assert (istore->ndims>0 && istore->ndims<=H5O_ISTORE_NDIMS);
assert (size);
assert (buf);
if (H5F_istore_copy_hyperslab (f, istore, H5F_ISTORE_WRITE,
offset, size, H5V_ZERO, size, buf)<0) {
/* hyperslab output failure */
HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL);
}
FUNC_LEAVE (SUCCEED);
}

View File

@ -20,7 +20,7 @@
#define _H5Fprivate_H
#include <H5Fpublic.h>
/* Private headers needed by this file */
/* This is a near top-level header! Try not to include much! */
#include <H5private.h>
/* Maximum size of boot-block buffer */
@ -397,6 +397,7 @@ typedef struct H5F_t {
uintn intent; /* The flags passed to H5F_open() */
char *name; /* Name used to open file */
H5F_file_t *shared; /* The shared file info */
struct H5G_cwgstk_t *cwg_stack; /* CWG stack for push/pop functions */
} H5F_t;
@ -446,12 +447,20 @@ typedef struct H5F_t {
case 2: UINT16DECODE(p,l); break; \
}
struct H5O_istore_t; /*forward decl for prototype arguments*/
/* Private functions, not part of the publicly documented API */
void H5F_encode_length_unusual(const H5F_t *f, uint8 **p, uint8 *l);
void H5F_encode_offset_unusual(const H5F_t *f, uint8 **p, uint8 *o);
H5F_t *H5F_open (const char *name, uintn flags,
const file_create_temp_t *create_parms);
herr_t H5F_close (H5F_t *f);
herr_t H5F_block_read (H5F_t *f, haddr_t addr, size_t size, void *buf);
herr_t H5F_block_write (H5F_t *f, haddr_t addr, size_t size, void *buf);
herr_t H5F_istore_read (H5F_t *f, struct H5O_istore_t *mesg,
size_t offset[], size_t size[], void *buf);
herr_t H5F_istore_write (H5F_t *f, struct H5O_istore_t *mesg,
size_t offset[], size_t size[], void *buf);
herr_t H5F_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent,
intn fwidth);

801
src/H5G.c

File diff suppressed because it is too large Load Diff

View File

@ -410,7 +410,7 @@ H5G_ent_encode (H5F_t *f, uint8 **pp, H5G_entry_t *ent)
* Failure: FAIL
*
* Programmer: Robb Matzke
* robb@maya.nuance.com
* matzke@llnl.gov
* Aug 29 1997
*
* Modifications:

View File

@ -39,29 +39,32 @@
#define PABLO_MASK H5G_node_mask
/* PRIVATE PROTOTYPES */
static herr_t H5G_node_decode_key (H5F_t *f, uint8 *raw, void *_key);
static herr_t H5G_node_encode_key (H5F_t *f, uint8 *raw, void *_key);
static herr_t H5G_node_decode_key (H5F_t *f, H5B_t *bt, uint8 *raw,
void *_key);
static herr_t H5G_node_encode_key (H5F_t *f, H5B_t *bt, uint8 *raw,
void *_key);
static size_t H5G_node_size (H5F_t *f);
static haddr_t H5G_node_new (H5F_t *f, void *_lt_key, void *_udata,
void *_rt_key);
static herr_t H5G_node_flush (H5F_t *f, hbool_t destroy, haddr_t addr,
H5G_node_t *sym);
static H5G_node_t *H5G_node_load (H5F_t *f, haddr_t addr, void *_data);
static H5G_node_t *H5G_node_load (H5F_t *f, haddr_t addr, void *_udata1,
void *_udata2);
static intn H5G_node_cmp (H5F_t *f, void *_lt_key, void *_udata,
void *_rt_key);
static herr_t H5G_node_found (H5F_t *f, haddr_t addr,
const void *_lt_key, void *_udata,
const void *_rt_key);
static haddr_t H5G_node_insert (H5F_t *f, haddr_t addr, intn *anchor,
static haddr_t H5G_node_insert (H5F_t *f, haddr_t addr, H5B_ins_t *anchor,
void *_lt_key, hbool_t *lt_key_changed,
void *_md_key, void *_udata,
void *_rt_key, hbool_t *rt_key_changed);
static herr_t H5G_node_list (H5F_t *f, haddr_t addr, void *_udata);
static size_t H5G_node_sizeof_rkey (H5F_t *f);
static size_t H5G_node_sizeof_rkey (H5F_t *f, const void *_udata);
/* H5G inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_SNODE[1] = {{
(void*(*)(H5F_t*,haddr_t,void*))H5G_node_load,
(void*(*)(H5F_t*,haddr_t,void*,void*))H5G_node_load,
(herr_t(*)(H5F_t*,hbool_t,haddr_t,void*))H5G_node_flush,
}};
@ -74,6 +77,8 @@ H5B_class_t H5B_SNODE[1] = {{
H5G_node_cmp, /*cmp */
H5G_node_found, /*found */
H5G_node_insert, /*insert */
TRUE, /*follow min branch? */
TRUE, /*follow max branch? */
H5G_node_list, /*list */
H5G_node_decode_key, /*decode */
H5G_node_encode_key, /*encode */
@ -102,7 +107,7 @@ static intn interface_initialize_g = FALSE;
*-------------------------------------------------------------------------
*/
static size_t
H5G_node_sizeof_rkey (H5F_t *f)
H5G_node_sizeof_rkey (H5F_t *f, const void *udata __attribute__((unused)))
{
return H5F_SIZEOF_OFFSET(f);
}
@ -126,7 +131,7 @@ H5G_node_sizeof_rkey (H5F_t *f)
*-------------------------------------------------------------------------
*/
static herr_t
H5G_node_decode_key (H5F_t *f, uint8 *raw, void *_key)
H5G_node_decode_key (H5F_t *f, H5B_t *bt, uint8 *raw, void *_key)
{
H5G_node_key_t *key = (H5G_node_key_t *)_key;
@ -160,7 +165,7 @@ H5G_node_decode_key (H5F_t *f, uint8 *raw, void *_key)
*-------------------------------------------------------------------------
*/
static herr_t
H5G_node_encode_key (H5F_t *f, uint8 *raw, void *_key)
H5G_node_encode_key (H5F_t *f, H5B_t *bt, uint8 *raw, void *_key)
{
H5G_node_key_t *key = (H5G_node_key_t *)_key;
@ -378,12 +383,12 @@ H5G_node_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym)
*-------------------------------------------------------------------------
*/
static H5G_node_t *
H5G_node_load (H5F_t *f, haddr_t addr, void *_udata)
H5G_node_load (H5F_t *f, haddr_t addr, void *_udata1, void *_udata2)
{
H5G_node_t *sym = NULL;
size_t size = 0;
uint8 *buf = NULL, *p = NULL;
H5G_ac_ud1_t *ac_udata = (H5G_ac_ud1_t*)_udata;
H5G_ac_ud1_t *ac_udata = (H5G_ac_ud1_t*)_udata1;
H5G_node_t *ret_value = NULL; /*for error handling*/
FUNC_ENTER (H5G_node_load, NULL, NULL);
@ -394,6 +399,7 @@ H5G_node_load (H5F_t *f, haddr_t addr, void *_udata)
assert (f);
assert (addr>=0);
assert (ac_udata);
assert (NULL==_udata2);
/*
* Initialize variables.
@ -453,21 +459,21 @@ H5G_node_load (H5F_t *f, haddr_t addr, void *_udata)
/*-------------------------------------------------------------------------
* Function: H5G_node_cmp
*
* Purpose: Compares two keys from a B-tree node (LEFT and RIGHT)
* Purpose: Compares two keys from a B-tree node (LT_KEY and RT_KEY)
* against another key (not necessarily the same type)
* pointed to by UDATA.
*
* Return: Success: negative if the UDATA key is less than
* or equal to the LEFT key.
* or equal to the LT_KEY
*
* positive if the UDATA key is greater
* than the RIGHT key.
* than the RT_KEY.
*
* zero if the UDATA key falls between
* the LEFT key (exclusive) and the
* RIGHT key (inclusive).
* the LT_KEY (exclusive) and the
* RT_KEY (inclusive).
*
* Failure: FAIL (same as LT < RT)
* Failure: FAIL (same as UDATA < LT_KEY)
*
* Programmer: Robb Matzke
* matzke@llnl.gov
@ -551,13 +557,13 @@ H5G_node_found (H5F_t *f, haddr_t addr, const void *_lt_key,
assert (addr>=0);
assert (bt_udata);
ac_udata.dir_addr = bt_udata->dir_addr;
ac_udata.grp_addr = bt_udata->grp_addr;
ac_udata.heap_addr = bt_udata->heap_addr;
/*
* Load the symbol table node for exclusive access.
*/
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata))) {
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata, NULL))) {
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL);
}
@ -656,7 +662,7 @@ done:
*-------------------------------------------------------------------------
*/
static haddr_t
H5G_node_insert (H5F_t *f, haddr_t addr, intn *anchor,
H5G_node_insert (H5F_t *f, haddr_t addr, H5B_ins_t *anchor,
void *_lt_key, hbool_t *lt_key_changed,
void *_md_key, void *_udata,
void *_rt_key, hbool_t *rt_key_changed)
@ -692,20 +698,12 @@ H5G_node_insert (H5F_t *f, haddr_t addr, intn *anchor,
bt_udata->node_ptr = NULL;
bt_udata->entry_ptr = NULL;
/*
* Symbol tables are always split so the new symbol table node is
* to the right of the old one.
*/
*anchor = H5B_ANCHOR_LT;
*lt_key_changed = FALSE;
*rt_key_changed = FALSE;
/*
* Load the symbol node.
*/
ac_udata.dir_addr = bt_udata->dir_addr;
ac_udata.grp_addr = bt_udata->grp_addr;
ac_udata.heap_addr = bt_udata->heap_addr;
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata))) {
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata, NULL))) {
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL);
}
@ -746,12 +744,13 @@ H5G_node_insert (H5F_t *f, haddr_t addr, intn *anchor,
* node and return the address of the new right node (the
* left node is at the same address as the original node).
*/
*anchor = H5B_INS_RIGHT;
/* The right node */
if ((new_node = H5G_node_new (f, NULL, NULL, NULL))<0) {
HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL);
}
if (NULL==(snrt=H5AC_find (f, H5AC_SNODE, new_node, &ac_udata))) {
if (NULL==(snrt=H5AC_find (f, H5AC_SNODE, new_node, &ac_udata, NULL))) {
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL);
}
HDmemcpy (snrt->entry, sn->entry + H5G_NODE_K(f),
@ -789,6 +788,7 @@ H5G_node_insert (H5F_t *f, haddr_t addr, intn *anchor,
} else {
/* Where to insert the new entry? */
*anchor = H5B_INS_NOOP;
sn->dirty = TRUE;
insert_into = sn;
insert_addr = addr;
@ -809,7 +809,7 @@ H5G_node_insert (H5F_t *f, haddr_t addr, intn *anchor,
H5G_shadow_move (f, bt_udata->entry.shadow,
bt_udata->name,
insert_into->entry + idx,
bt_udata->dir_addr);
bt_udata->grp_addr);
}
/* Move entries */
@ -837,7 +837,8 @@ done:
if (H5AC_unprotect (f, H5AC_SNODE, addr, sn)<0) {
HRETURN_ERROR (H5E_SYM, H5E_PROTECT, FAIL);
}
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, insert_addr, &ac_udata))) {
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, insert_addr, &ac_udata,
NULL))) {
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL);
}
assert (sn==bt_udata->node_ptr);
@ -852,7 +853,7 @@ done:
/*-------------------------------------------------------------------------
* Function: H5G_node_list
*
* Purpose: This function gets called during a directory list operation.
* Purpose: This function gets called during a group list operation.
* It should fill in data in the UDATA struct.
*
* Return: Success: SUCCEED
@ -886,9 +887,9 @@ H5G_node_list (H5F_t *f, haddr_t addr, void *_udata)
assert (addr>=0);
assert (bt_udata);
ac_udata.dir_addr = bt_udata->dir_addr;
ac_udata.grp_addr = bt_udata->grp_addr;
ac_udata.heap_addr = bt_udata->heap_addr;
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata))) {
if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata, NULL))) {
HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL);
}
@ -978,21 +979,21 @@ H5G_node_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent,
* We have absolutely no idea where the object header for the symbol table
* to which this node belongs is located. In fact, if the file is corrupt,
* there may not even be an object header for that symbol table. So we
* supply `-1' as the directory address which causes no open objects to be
* supply `-1' as the group address which causes no open objects to be
* associated with the node. For that reason, we flush this node from the
* cache when we're done so if some later caller knows the header address
* they'll be able to access the open objects.
*/
ac_udata.dir_addr = -1;
ac_udata.grp_addr = -1;
ac_udata.heap_addr = heap;
/*
* If we couldn't load the symbol table node, then try loading the
* B-tree node.
*/
if (NULL==(sn=H5AC_find(f, H5AC_SNODE, addr, &ac_udata))) {
if (NULL==(sn=H5AC_find(f, H5AC_SNODE, addr, &ac_udata, NULL))) {
H5ECLEAR; /*discard that error*/
status = H5B_debug (f, addr, stream, indent, fwidth, H5B_SNODE);
status = H5B_debug (f, addr, stream, indent, fwidth, H5B_SNODE, NULL);
if (status<0) HRETURN_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL);
HRETURN (SUCCEED);
}

View File

@ -20,7 +20,7 @@
#include <H5Gprivate.h>
#define H5G_NODE_VERS 1 /*symbol table node version number */
#define H5G_SIZE_HINT 1024 /*default root dir size hint */
#define H5G_SIZE_HINT 1024 /*default root grp size hint */
#define H5G_NODE_K(F) ((F)->shared->file_create_parms.sym_leaf_k)
#define H5G_NODE_SIZEOF_HDR(F) (H5G_NODE_SIZEOF_MAGIC + 4)
#define H5G_DEFAULT_ROOT_SIZE 32
@ -44,7 +44,7 @@ struct H5G_entry_t {
* A symbol table node is a collection of symbol table entries. It can
* be thought of as the lowest level of the B-link tree that points to
* a collection of symbol table entries that belong to a specific symbol
* table or directory.
* table or group.
*/
typedef struct H5G_node_t {
hbool_t dirty; /*has cache been modified? */
@ -61,7 +61,7 @@ typedef struct H5G_node_t {
*/
struct H5G_shadow_t {
char *name; /*name for this entry */
haddr_t dir_addr; /*hdr addr for dir containing shadow */
haddr_t grp_addr; /*hdr addr for group containing shadow */
uintn nrefs; /*reference counter */
H5G_entry_t entry; /*local copy of symbol table entry */
H5G_entry_t *main; /*main entry in stab node if cached */
@ -77,6 +77,16 @@ typedef struct H5G_node_key_t {
off_t offset; /*offset into heap for name */
} H5G_node_key_t;
/*
* Each file has a stack of open groups with the latest entry on the
* stack the current working group. If the stack is empty then the
* current working group is the root object.
*/
typedef struct H5G_cwgstk_t {
H5G_entry_t *handle; /*a handle to an open group */
struct H5G_cwgstk_t *next; /*next item (earlier) on stack */
} H5G_cwgstk_t;
/*
* These operations can be passed down from the H5G_stab layer to the
* H5G_node layer through the B-tree layer.
@ -96,7 +106,7 @@ typedef struct H5G_bt_ud1_t {
/* downward */
H5G_oper_t operation; /*what operation to perform */
const char *name; /*points to temporary memory */
haddr_t dir_addr; /*symbol table header address */
haddr_t grp_addr; /*symbol table header address */
haddr_t heap_addr; /*symbol table heap address */
/* downward for INSERT */
@ -119,7 +129,7 @@ typedef struct H5G_bt_ud2_t {
H5G_entry_t *entry; /*array of entries, alloc'd by caller */
char **name; /*array of string ptrs, allocd by caller*/
intn maxentries; /*size of the ADDR and NAME arrays */
haddr_t dir_addr; /*symbol table header address */
haddr_t grp_addr; /*symbol table header address */
haddr_t heap_addr; /*heap address */
/* upward */
@ -137,15 +147,15 @@ extern H5B_class_t H5B_SNODE[1];
*/
typedef struct H5G_ac_ud1_t {
haddr_t heap_addr;
haddr_t dir_addr;
haddr_t grp_addr;
} H5G_ac_ud1_t;
/* The cache subclass */
extern const H5AC_class_t H5AC_SNODE[1];
/*
* Functions that understand symbol tables but not directories. The
* functions that understand directories are exported to the rest of
* Functions that understand symbol tables but not names. The
* functions that understand names are exported to the rest of
* the library and appear in H5Gprivate.h.
*/
haddr_t H5G_stab_new (H5F_t *f, H5G_entry_t *self, size_t init);
@ -160,7 +170,7 @@ intn H5G_stab_list (H5F_t *f, H5G_entry_t *self, intn maxentries,
* Functions that understand shadow entries.
*/
herr_t H5G_shadow_sync (H5G_entry_t *ent);
H5G_entry_t *H5G_shadow_open (H5F_t *f, H5G_entry_t *dir,
H5G_entry_t *H5G_shadow_open (H5F_t *f, H5G_entry_t *grp,
H5G_entry_t *ent);
herr_t H5G_shadow_close (H5F_t *f, H5G_entry_t *ent);
hbool_t H5G_shadow_p (H5G_entry_t *ent);
@ -170,7 +180,7 @@ herr_t H5G_shadow_assoc_node (H5F_t *f, H5G_node_t *sym,
H5G_shadow_t *H5G_shadow_list (H5F_t *f, haddr_t stab_header_addr);
herr_t H5G_shadow_move (H5F_t *f, H5G_shadow_t *shadow,
const char *new_name, H5G_entry_t *new_entry,
haddr_t dir_addr);
haddr_t grp_addr);
/*
* Functions that understand symbol table entries.

View File

@ -82,14 +82,15 @@ typedef struct H5G_entry_t H5G_entry_t;
* Library prototypes... These are the ones that other packages routinely
* call.
*/
H5G_entry_t *H5G_mkdir (H5F_t *f, const char *name, size_t size_hint);
herr_t H5G_pushd (H5F_t *f, const char *name);
herr_t H5G_popd (H5F_t *f);
H5G_entry_t *H5G_new (H5F_t *f, const char *name, size_t size_hint);
herr_t H5G_set (H5F_t *f, const char *name);
herr_t H5G_push (H5F_t *f, const char *name);
herr_t H5G_pop (H5F_t *f);
H5G_entry_t *H5G_create (H5F_t *f, const char *name, size_t ohdr_hint);
H5G_entry_t *H5G_open (H5F_t *f, const char *name);
herr_t H5G_close (H5F_t *f, H5G_entry_t *ent);
herr_t H5G_find (H5F_t *f, H5G_entry_t *cwd, H5G_entry_t *dir_ent,
const char *name, H5G_entry_t *ent);
herr_t H5G_find (H5F_t *f, const char *name, H5G_entry_t *grp_ent,
H5G_entry_t *ent);
herr_t H5G_ent_encode (H5F_t *f, uint8 **pp, H5G_entry_t *ent);
herr_t H5G_ent_decode (H5F_t *f, uint8 **pp, H5G_entry_t *ent);

View File

@ -19,15 +19,19 @@
#define _H5Gpublic_H
/* Public headers needed by this file */
#include <sys/types.h>
#include <H5public.h>
/* Default root directory size */
#define H5G_DEFAULT_ROOT SIZE 256
#include <H5Apublic.h>
#ifdef __cplusplus
extern "C" {
#endif
herr_t H5Gnew (hid_t file, const char *name, size_t size_hint);
herr_t H5Gset (hid_t file, const char *name);
herr_t H5Gpush (hid_t file, const char *name);
herr_t H5Gpop (hid_t file);
#ifdef __cplusplus
}
#endif

View File

@ -29,7 +29,7 @@
static hbool_t interface_initialize_g = FALSE;
typedef struct H5G_hash_t {
haddr_t dir_addr;
haddr_t grp_addr;
H5G_shadow_t *head;
struct H5G_hash_t *next;
struct H5G_hash_t *prev;
@ -81,15 +81,15 @@ H5G_shadow_check (H5F_t *f)
shadow_error = TRUE;
}
/* Valid directory addresses */
if (shadow->dir_addr<0 || (shadow->dir_addr==0 && idx!=0)) {
fprintf (stderr, "dir_addr=%lu, ",
(unsigned long)(shadow->dir_addr));
/* Valid group addresses */
if (shadow->grp_addr<0 || (shadow->grp_addr==0 && idx!=0)) {
fprintf (stderr, "grp_addr=%lu, ",
(unsigned long)(shadow->grp_addr));
shadow_error = TRUE;
} else if (shadow->dir_addr!=hash->dir_addr) {
fprintf (stderr, "dir_addr=%lu (not %lu), ",
(unsigned long)(shadow->dir_addr),
(unsigned long)(hash->dir_addr));
} else if (shadow->grp_addr!=hash->grp_addr) {
fprintf (stderr, "grp_addr=%lu (not %lu), ",
(unsigned long)(shadow->grp_addr),
(unsigned long)(hash->grp_addr));
}
/* Linked to symbol table entry */
@ -107,9 +107,9 @@ H5G_shadow_check (H5F_t *f)
/* If an error occurred then print other info */
if (shadow_error) {
fprintf (stderr, "idx=%u, shadow=0x%08lx, dir_addr=%lu\n",
fprintf (stderr, "idx=%u, shadow=0x%08lx, grp_addr=%lu\n",
idx, (unsigned long)shadow,
(unsigned long)(shadow->dir_addr));
(unsigned long)(shadow->grp_addr));
nerrors++;
}
}
@ -247,7 +247,7 @@ H5G_shadow_sync (H5G_entry_t *ent)
* Function: H5G_shadow_list
*
* Purpose: Returns a doubly linked list of shadows for the symbol
* table whose header address is DIR_ADDR.
* table whose header address is GRP_ADDR.
*
* Return: Success: Ptr shadow list or null.
*
@ -261,15 +261,15 @@ H5G_shadow_sync (H5G_entry_t *ent)
*-------------------------------------------------------------------------
*/
H5G_shadow_t *
H5G_shadow_list (H5F_t *f, haddr_t dir_addr)
H5G_shadow_list (H5F_t *f, haddr_t grp_addr)
{
uintn idx = dir_addr % f->shared->nshadows;
uintn idx = grp_addr % f->shared->nshadows;
H5G_hash_t *bucket = NULL;
FUNC_ENTER (H5G_shadows, NULL, NULL);
for (bucket=f->shared->shadow[idx]; bucket; bucket=bucket->next) {
if (bucket->dir_addr==dir_addr) {
if (bucket->grp_addr==grp_addr) {
HRETURN (bucket->head);
}
}
@ -317,7 +317,7 @@ H5G_shadow_assoc_node (H5F_t *f, H5G_node_t *sym, H5G_ac_ud1_t *ac_udata)
H5G_shadow_check (f);
#endif
if ((shadow=H5G_shadow_list (f, ac_udata->dir_addr))) {
if ((shadow=H5G_shadow_list (f, ac_udata->grp_addr))) {
heap_addr = ac_udata->heap_addr;
while (i<sym->nsyms && shadow) {
@ -352,7 +352,7 @@ H5G_shadow_assoc_node (H5F_t *f, H5G_node_t *sym, H5G_ac_ud1_t *ac_udata)
* object, open the object (again) and return a handle
* to it.
*
* DIR can be the null pointer if `ent' is the root entry.
* GRP can be the null pointer if `ent' is the root entry.
*
* Return: Success: Handle to open object
*
@ -366,7 +366,7 @@ H5G_shadow_assoc_node (H5F_t *f, H5G_node_t *sym, H5G_ac_ud1_t *ac_udata)
*-------------------------------------------------------------------------
*/
H5G_entry_t *
H5G_shadow_open (H5F_t *f, H5G_entry_t *dir, H5G_entry_t *ent)
H5G_shadow_open (H5F_t *f, H5G_entry_t *grp, H5G_entry_t *ent)
{
H5G_shadow_t *shadow = NULL;
H5O_stab_t stab;
@ -376,15 +376,15 @@ H5G_shadow_open (H5F_t *f, H5G_entry_t *dir, H5G_entry_t *ent)
uintn idx;
H5O_name_t name_mesg = {NULL};
H5G_entry_t *ret_value = NULL;
haddr_t dir_addr;
haddr_t grp_addr;
FUNC_ENTER (H5G_shadow_open, NULL, NULL);
/* check args */
assert (f);
assert (ent==f->shared->root_sym || dir);
assert (ent==f->shared->root_sym || grp);
assert (ent);
dir_addr = dir ? dir->header : 0;
grp_addr = grp ? grp->header : 0;
if ((shadow = ent->shadow)) {
/*
@ -396,7 +396,7 @@ H5G_shadow_open (H5F_t *f, H5G_entry_t *dir, H5G_entry_t *ent)
shadow = H5MM_xcalloc (1, sizeof(H5G_shadow_t));
if (ent==f->shared->root_sym && 0==dir_addr) {
if (ent==f->shared->root_sym && 0==grp_addr) {
/*
* We're opening the root entry.
*/
@ -411,7 +411,7 @@ H5G_shadow_open (H5F_t *f, H5G_entry_t *dir, H5G_entry_t *ent)
/*
* Some entry other than the root.
*/
if (NULL==H5O_read (f, NO_ADDR, dir, H5O_STAB, 0, &stab)) {
if (NULL==H5O_read (f, NO_ADDR, grp, H5O_STAB, 0, &stab)) {
HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, NULL);
}
if (NULL==(s=H5H_peek (f, stab.heap_addr, ent->name_off))) {
@ -428,18 +428,18 @@ H5G_shadow_open (H5F_t *f, H5G_entry_t *dir, H5G_entry_t *ent)
shadow->nrefs = 1;
shadow->entry = *ent;
shadow->entry.dirty = FALSE;
shadow->dir_addr = dir_addr;
shadow->grp_addr = grp_addr;
/*
* Link it into the shadow heap
*/
idx = dir_addr % f->shared->nshadows;
idx = grp_addr % f->shared->nshadows;
for (hash=f->shared->shadow[idx]; hash; hash=hash->next) {
if (hash->dir_addr==dir_addr) break;
if (hash->grp_addr==grp_addr) break;
}
if (!hash) {
hash = H5MM_xcalloc (1, sizeof(H5G_hash_t));
hash->dir_addr = dir_addr;
hash->grp_addr = grp_addr;
hash->next = f->shared->shadow[idx];
f->shared->shadow[idx] = hash;
if (hash->next) hash->next->prev = hash;
@ -524,7 +524,7 @@ H5G_shadow_close (H5F_t *f, H5G_entry_t *ent)
/* clean the shadow */
if (1==shadow->nrefs && ent->dirty) {
if (!shadow->main &&
NULL==H5G_stab_find (f, shadow->dir_addr, NULL, shadow->name)) {
NULL==H5G_stab_find (f, shadow->grp_addr, NULL, shadow->name)) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
}
assert (shadow->main);
@ -540,9 +540,9 @@ H5G_shadow_close (H5F_t *f, H5G_entry_t *ent)
H5G_shadow_dissociate (ent);
/* find symtabs shadow list */
idx = shadow->dir_addr % f->shared->nshadows;
idx = shadow->grp_addr % f->shared->nshadows;
for (hash=f->shared->shadow[idx]; hash; hash=hash->next) {
if (hash->dir_addr==shadow->dir_addr) break;
if (hash->grp_addr==shadow->grp_addr) break;
}
assert (hash);
@ -577,7 +577,7 @@ H5G_shadow_close (H5F_t *f, H5G_entry_t *ent)
* Function: H5G_shadow_move
*
* Purpose: Moves the SHADOW for some entry to correspond to a
* NEW_ENTRY. The DIR_ADDR is the address for the directory
* NEW_ENTRY. The GRP_ADDR is the address for the group
* which contains NEW_ENTRY.
*
* Return: Success: SUCCEED
@ -593,7 +593,7 @@ H5G_shadow_close (H5F_t *f, H5G_entry_t *ent)
*/
herr_t
H5G_shadow_move (H5F_t *f, H5G_shadow_t *shadow, const char *new_name,
H5G_entry_t *new_entry, haddr_t dir_addr)
H5G_entry_t *new_entry, haddr_t grp_addr)
{
H5G_hash_t *hash;
uintn idx;
@ -602,29 +602,29 @@ H5G_shadow_move (H5F_t *f, H5G_shadow_t *shadow, const char *new_name,
assert (shadow);
assert (new_entry);
assert (dir_addr>0);
assert (grp_addr>0);
if (0==shadow->dir_addr) {
if (0==shadow->grp_addr) {
/*
* We're moving the shadow for the root object. This simplifies things
* greatly since it implies that this is the only shadow currently
* defined for the entire file.
*/
idx = dir_addr % f->shared->nshadows;
idx = grp_addr % f->shared->nshadows;
assert (NULL==f->shared->shadow[idx]); /*Nothing at new idx... */
hash = f->shared->shadow[0];
assert (hash); /*..but root idx has something. */
assert (0==hash->dir_addr); /*..and it's the root something */
assert (0==hash->grp_addr); /*..and it's the root something */
assert (NULL==hash->next); /*..and just that */
assert (hash->head==shadow); /*..and exactly that */
/* Move root entry to new hash bucket */
f->shared->shadow[idx] = hash;
f->shared->shadow[0] = NULL;
hash->dir_addr = dir_addr;
hash->grp_addr = grp_addr;
/* Associate SHADOW with NEW_ENTRY */
shadow->dir_addr = dir_addr;
shadow->grp_addr = grp_addr;
shadow->main = new_entry;
new_entry->shadow = shadow;
@ -636,7 +636,7 @@ H5G_shadow_move (H5F_t *f, H5G_shadow_t *shadow, const char *new_name,
/*
* Other shadows never move.
*/
assert (shadow->dir_addr==dir_addr);
assert (shadow->grp_addr==grp_addr);
shadow->main = new_entry;
new_entry->shadow = shadow;
}
@ -682,7 +682,7 @@ H5G_shadow_flush (H5F_t *f, hbool_t invalidate)
*/
if (shadow->entry.dirty) {
if (!shadow->main &&
NULL==H5G_stab_find (f, shadow->dir_addr, NULL,
NULL==H5G_stab_find (f, shadow->grp_addr, NULL,
shadow->name)) {
HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL);
}
@ -698,12 +698,12 @@ H5G_shadow_flush (H5F_t *f, hbool_t invalidate)
* some object before closing the file. Since this is hard to
* debug, we'll be nice and print the names here. We don't know
* the full name, but we'll print the file address (relative to
* the boot block) of the object header for the directory that
* the boot block) of the object header for the group that
* contains the open object.
*/
if (invalidate) {
fprintf (stderr, "Open object <%lu>/%s",
(unsigned long)(shadow->dir_addr),
fprintf (stderr, "Warning: open object <%lu>/%s",
(unsigned long)(shadow->grp_addr),
shadow->name);
if (shadow->nrefs>1) {
fprintf (stderr, " (%d times)", shadow->nrefs);

View File

@ -87,14 +87,14 @@ H5G_stab_new (H5F_t *f, H5G_entry_t *self, size_t init)
}
/* Create the B-tree */
if ((stab.btree_addr = H5B_new (f, H5B_SNODE))<0) {
if ((stab.btree_addr = H5B_new (f, H5B_SNODE, NULL))<0) {
HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*can't create B-tree*/
}
/*
* Create symbol table object header. It has a zero link count
* since nothing refers to it yet. The link count will be
* incremented if the object is added to the directory hierarchy.
* incremented if the object is added to the group directed graph.
*/
if ((addr = H5O_new (f, 0, 4+2*H5F_SIZEOF_OFFSET(f)))<0) {
HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*can't create header*/
@ -169,7 +169,7 @@ H5G_stab_find (H5F_t *f, haddr_t addr, H5G_entry_t *self,
udata.operation = H5G_OPER_FIND;
udata.name = name;
udata.heap_addr = stab.heap_addr;
udata.dir_addr = addr;
udata.grp_addr = addr;
udata.node_ptr = NULL;
/* search the B-tree */
@ -245,7 +245,7 @@ H5G_stab_insert (H5F_t *f, H5G_entry_t *self, const char *name,
udata.operation = H5G_OPER_INSERT;
udata.name = name;
udata.heap_addr = stab.heap_addr;
udata.dir_addr = self->header;
udata.grp_addr = self->header;
udata.entry = *ent;
udata.entry.name_off = -1;
udata.node_ptr = NULL;
@ -326,7 +326,7 @@ H5G_stab_list (H5F_t *f, H5G_entry_t *self, intn maxentries,
}
udata.entry = entries;
udata.name = names;
udata.dir_addr = self->header;
udata.grp_addr = self->header;
udata.heap_addr = stab.heap_addr;
udata.maxentries = maxentries;
udata.nsyms = 0;

View File

@ -45,14 +45,14 @@ typedef struct H5H_t {
} H5H_t;
/* PRIVATE PROTOTYPES */
static H5H_t *H5H_load (H5F_t *f, haddr_t addr, void *udata);
static H5H_t *H5H_load (H5F_t *f, haddr_t addr, void *udata1, void *udata2);
static herr_t H5H_flush (H5F_t *f, hbool_t dest, haddr_t addr, H5H_t *heap);
/*
* H5H inherits cache-like properties from H5AC
*/
static const H5AC_class_t H5AC_HEAP[1] = {{
(void*(*)(H5F_t*,haddr_t,void*))H5H_load,
(void*(*)(H5F_t*,haddr_t,void*,void*))H5H_load,
(herr_t(*)(H5F_t*,hbool_t,haddr_t,void*))H5H_flush,
}};
@ -161,7 +161,7 @@ H5H_new (H5F_t *f, H5H_type_t heap_type, size_t size_hint)
*-------------------------------------------------------------------------
*/
static H5H_t *
H5H_load (H5F_t *f, haddr_t addr, void *udata)
H5H_load (H5F_t *f, haddr_t addr, void *udata1, void *udata2)
{
uint8 hdr[20], *p;
H5H_t *heap=NULL;
@ -175,7 +175,8 @@ H5H_load (H5F_t *f, haddr_t addr, void *udata)
assert (f);
assert (addr>0);
assert (H5H_SIZEOF_HDR(f) <= sizeof hdr);
assert (!udata);
assert (!udata1);
assert (!udata2);
if (H5F_block_read (f, addr, H5H_SIZEOF_HDR(f), hdr)<0) {
HRETURN_ERROR (H5E_HEAP, H5E_READERROR, NULL);
@ -395,7 +396,7 @@ H5H_read (H5F_t *f, haddr_t addr, off_t offset, size_t size, void *buf)
assert (addr>0);
assert (offset>=0);
if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL))) {
if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL, NULL))) {
HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL);
}
assert (offset<heap->mem_alloc);
@ -455,7 +456,7 @@ H5H_peek (H5F_t *f, haddr_t addr, off_t offset)
assert (addr>0);
assert (offset>=0);
if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL))) {
if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL, NULL))) {
HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL);
}
assert (offset<heap->mem_alloc);
@ -536,7 +537,7 @@ H5H_insert (H5F_t *f, haddr_t addr, size_t buf_size, const void *buf)
need = buf_size;
H5H_ALIGN (need);
if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL))) {
if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL, NULL))) {
HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, FAIL);
}
heap->dirty += 1;
@ -686,7 +687,7 @@ H5H_write (H5F_t *f, haddr_t addr, off_t offset, size_t size,
assert (offset>=0);
assert (buf);
if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL))) {
if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL, NULL))) {
HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, FAIL);
}
assert (offset<heap->mem_alloc);
@ -748,7 +749,7 @@ H5H_remove (H5F_t *f, haddr_t addr, off_t offset, size_t size)
assert (offset>=0);
assert (size>0);
if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL))) {
if (NULL==(heap=H5AC_find (f, H5AC_HEAP, addr, NULL, NULL))) {
HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, FAIL);
}
assert (offset<heap->mem_alloc);
@ -864,7 +865,7 @@ H5H_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent, intn fwidth)
assert (indent>=0);
assert (fwidth>=0);
if (NULL==(h=H5AC_find (f, H5AC_HEAP, addr, NULL))) {
if (NULL==(h=H5AC_find (f, H5AC_HEAP, addr, NULL, NULL))) {
HRETURN_ERROR (H5E_HEAP, H5E_CANTLOAD, FAIL);
}

View File

@ -26,7 +26,7 @@
/* PRIVATE PROTOTYPES */
static herr_t H5O_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5O_t *oh);
static H5O_t *H5O_load (H5F_t *f, haddr_t addr, void *_data);
static H5O_t *H5O_load (H5F_t *f, haddr_t addr, void *_udata1, void *_udata2);
static intn H5O_find_in_ohdr (H5F_t *f, haddr_t addr,
const H5O_class_t **type_p, intn sequence);
static intn H5O_alloc (H5F_t *f, H5O_t *oh, const H5O_class_t *type,
@ -36,7 +36,7 @@ static intn H5O_alloc_new_chunk (H5F_t *f, H5O_t *oh, size_t size);
/* H5O inherits cache-like properties from H5AC */
static const H5AC_class_t H5AC_OHDR[1] = {{
(void*(*)(H5F_t*,haddr_t,void*))H5O_load,
(void*(*)(H5F_t*,haddr_t,void*,void*))H5O_load,
(herr_t(*)(H5F_t*,hbool_t,haddr_t,void*))H5O_flush,
}};
@ -45,17 +45,17 @@ static intn interface_initialize_g = FALSE;
/* ID to type mapping */
static const H5O_class_t *const message_type_g[] = {
H5O_NULL, /*0x0000 Null */
H5O_SIM_DIM, /*0x0001 Simple dimensionality */
H5O_NULL, /*0x0000 Null */
H5O_SIM_DIM, /*0x0001 Simple dimensionality */
NULL, /*0x0002 Data space (fiber bundle?) */
H5O_SIM_DTYPE, /*0x0003 Simple data type */
H5O_SIM_DTYPE, /*0x0003 Simple data type */
NULL, /*0x0004 Compound data type */
H5O_STD_STORE, /*0x0005 Data storage -- standard object */
H5O_STD_STORE, /*0x0005 Data storage -- standard object */
NULL, /*0x0006 Data storage -- compact object */
NULL, /*0x0007 Data storage -- external object */
NULL, /*0x0008 Data storage -- indexed object */
NULL, /*0x0009 Data storage -- chunked object */
NULL, /*0x000A Data storage -- sparse object */
H5O_ISTORE, /*0x0008 Data storage -- indexed object */
NULL, /*0x0009 Not assigned */
NULL, /*0x000A Not assigned */
NULL, /*0x000B Data storage -- compressed object */
NULL, /*0x000C Attribute list */
H5O_NAME, /*0x000D Object name */
@ -105,7 +105,7 @@ H5O_new (H5F_t *f, intn nlink, size_t size_hint)
HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL);
}
/* allocate the object header in fill in header fields */
/* allocate the object header and fill in header fields */
oh = H5MM_xcalloc (1, sizeof(H5O_t));
oh->dirty = TRUE;
oh->version = H5O_VERSION;
@ -165,7 +165,7 @@ H5O_new (H5F_t *f, intn nlink, size_t size_hint)
*-------------------------------------------------------------------------
*/
static H5O_t *
H5O_load (H5F_t *f, haddr_t addr, void *_data)
H5O_load (H5F_t *f, haddr_t addr, void *_udata1, void *_udata2)
{
H5O_t *oh = NULL;
H5O_t *ret_value = (void*)1; /*kludge for HGOTO_ERROR*/
@ -182,7 +182,8 @@ H5O_load (H5F_t *f, haddr_t addr, void *_data)
/* check args */
assert (f);
assert (addr>=0);
assert (!_data);
assert (!_udata1);
assert (!_udata2);
/* allocate ohdr and init chunk list */
oh = H5MM_xcalloc (1, sizeof(H5O_t));
@ -454,7 +455,7 @@ H5O_flush (H5F_t *f, hbool_t destroy, haddr_t addr, H5O_t *oh)
* Failure: FAIL
*
* Programmer: Robb Matzke
* robb@maya.nuance.com
* matzke@llnl.gov
* Aug 12 1997
*
* Modifications:
@ -513,7 +514,7 @@ H5O_link (H5F_t *f, H5G_entry_t *ent, intn adjust)
addr = H5G_ent_addr (ent);
/* get header */
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) {
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL, NULL))) {
HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL);
}
@ -600,7 +601,7 @@ H5O_read (H5F_t *f, haddr_t addr, H5G_entry_t *ent,
#endif
/* copy the message to the user-supplied buffer */
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) {
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL, NULL))) {
HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, NULL);
}
retval = (type->copy)(oh->mesg[idx].native, mesg);
@ -643,7 +644,7 @@ H5O_find_in_ohdr (H5F_t *f, haddr_t addr, const H5O_class_t **type_p,
assert (type_p);
/* load the object header */
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) {
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL, NULL))) {
HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL);
}
@ -710,7 +711,7 @@ H5O_peek (H5F_t *f, haddr_t addr, const H5O_class_t *type, intn sequence)
if ((idx = H5O_find_in_ohdr (f, addr, &type, sequence))<0) {
HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, NULL);
}
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) {
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL, NULL))) {
HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, NULL);
}
@ -767,7 +768,7 @@ H5O_modify (H5F_t *f, haddr_t addr, H5G_entry_t *ent,
assert (mesg);
if (addr<=0) addr = H5G_ent_addr (ent);
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) {
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL, NULL))) {
HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL);
}
@ -842,7 +843,7 @@ H5O_modify (H5F_t *f, haddr_t addr, H5G_entry_t *ent,
* Failure: FAIL
*
* Programmer: Robb Matzke
* robb@maya.nuance.com
* matzke@llnl.gov
* Aug 28 1997
*
* Modifications:
@ -865,7 +866,7 @@ H5O_remove (H5F_t *f, haddr_t addr, H5G_entry_t *ent,
if (addr<=0) addr = H5G_ent_addr (ent);
/* load the object header */
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) {
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL, NULL))) {
HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL);
}
@ -1309,7 +1310,7 @@ H5O_debug (H5F_t *f, haddr_t addr, FILE *stream, intn indent, intn fwidth)
assert (indent>=0);
assert (fwidth>=0);
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL))) {
if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL, NULL))) {
HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL);
}

271
src/H5Oistore.c Normal file
View File

@ -0,0 +1,271 @@
/*
* Copyright (C) 1997 NCSA
* All rights reserved.
*
* Programmer: Robb Matzke <matzke@llnl.gov>
* Wednesday, October 8, 1997
*/
#include <H5private.h>
#include <H5Eprivate.h>
#include <H5MMprivate.h>
#include <H5Oprivate.h>
#define PABLO_MASK H5O_istore_mask
/* PRIVATE PROTOTYPES */
static void *H5O_istore_decode (H5F_t *f, size_t raw_size, const uint8 *p);
static herr_t H5O_istore_encode (H5F_t *f, size_t size, uint8 *p,
const void *_mesg);
static void *H5O_istore_copy (const void *_mesg, void *_dest);
static size_t H5O_istore_size (H5F_t *f, const void *_mesg);
static herr_t H5O_istore_debug (H5F_t *f, const void *_mesg, FILE *stream,
intn indent, intn fwidth);
/* This message derives from H5O */
const H5O_class_t H5O_ISTORE[1] = {{
H5O_ISTORE_ID, /*message id number */
"istore", /*message name for debugging */
sizeof(H5O_istore_t), /*native message size */
H5G_NOTHING_CACHED, /*symtab entry `type' field */
H5O_istore_decode, /*decode message */
H5O_istore_encode, /*encode message */
NULL, /*get messsage from stab entry */
NULL, /*put message into stab entry */
H5O_istore_copy, /*copy the native value */
H5O_istore_size, /*size of message on disk */
NULL, /*reset method */
H5O_istore_debug, /*debug the message */
}};
/* Is the interface initialized? */
static hbool_t interface_initialize_g = FALSE;
/*-------------------------------------------------------------------------
* Function: H5O_istore_decode
*
* Purpose: Decode an indexed storage message and return a pointer to a
* new one created with malloc().
*
* Return: Success: Ptr to new message in native order.
*
* Failure: NULL
*
* Programmer: Robb Matzke
* Wednesday, October 8, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static void *
H5O_istore_decode (H5F_t *f, size_t raw_size, const uint8 *p)
{
H5O_istore_t *mesg = NULL;
intn i;
FUNC_ENTER (H5O_istore_decode, NULL, NULL);
/* check args */
assert (f);
assert (p);
/* decode */
mesg = H5MM_xcalloc (1, sizeof(H5O_istore_t));
H5F_decode_offset (f, p, mesg->btree_addr);
mesg->ndims = *p++;
assert (raw_size == H5O_istore_size (f, mesg));
/* Reserved bytes */
p += 7;
/* Read the min_corner, max_corner, and alignment values */
for (i=0; i<mesg->ndims; i++) {
UINT32DECODE (p, mesg->alignment[i]);
}
FUNC_LEAVE (mesg);
}
/*-------------------------------------------------------------------------
* Function: H5O_istore_encode
*
* Purpose: Encodes a message.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Wednesday, October 8, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static herr_t
H5O_istore_encode (H5F_t *f, size_t raw_size, uint8 *p, const void *_mesg)
{
const H5O_istore_t *mesg = (const H5O_istore_t *)_mesg;
int i;
FUNC_ENTER (H5O_istore_encode, NULL, FAIL);
/* check args */
assert (f);
assert (mesg);
assert (mesg->ndims>0 && mesg->ndims<=H5O_ISTORE_NDIMS);
assert (raw_size == H5O_istore_size (f, _mesg));
assert (p);
/* encode B-tree offset */
H5F_encode_offset (f, p, mesg->btree_addr);
/* number of dimensions */
*p++ = mesg->ndims;
/* reserved bytes should be zero */
for (i=0; i<7; i++) *p++ = 0;
/* min_corner, max_corner, and alignment */
for (i=0; i<mesg->ndims; i++) {
UINT32ENCODE (p, mesg->alignment[i]);
}
FUNC_LEAVE (SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5O_istore_copy
*
* Purpose: Copies a message from _MESG to _DEST, allocating _DEST if
* necessary.
*
* Return: Success: Ptr to _DEST
*
* Failure: NULL
*
* Programmer: Robb Matzke
* Wednesday, October 8, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static void *
H5O_istore_copy (const void *_mesg, void *_dest)
{
const H5O_istore_t *mesg = (const H5O_istore_t *)_mesg;
H5O_istore_t *dest = (H5O_istore_t *)_dest;
FUNC_ENTER (H5O_istore_copy, NULL, NULL);
/* check args */
assert (mesg);
if (!dest) dest = H5MM_xcalloc (1, sizeof(H5O_istore_t));
/* copy */
*dest = *mesg;
FUNC_LEAVE ((void*)dest);
}
/*-------------------------------------------------------------------------
* Function: H5O_istore_size
*
* Purpose: Returns the size of the raw message in bytes not counting the
* message type or size fields, but only the data fields. This
* function doesn't take into account message alignment.
*
* Return: Success: Message data size in bytes
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Wednesday, October 8, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static size_t
H5O_istore_size (H5F_t *f, const void *_mesg)
{
const H5O_istore_t *mesg = (const H5O_istore_t *)_mesg;
size_t ret_value = FAIL;
FUNC_ENTER (H5O_istore_size, NULL, FAIL);
/* check args */
assert (f);
assert (mesg);
assert (mesg->ndims>0 && mesg->ndims<=H5O_ISTORE_NDIMS);
ret_value = H5F_SIZEOF_OFFSET (f) + /* B-tree address */
1 + /* max dimension index */
7 + /* reserved bytes */
mesg->ndims * 4; /* alignment */
FUNC_LEAVE (ret_value);
}
/*-------------------------------------------------------------------------
* Function: H5O_istore_debug
*
* Purpose: Prints debugging info for a message.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Wednesday, October 8, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static herr_t
H5O_istore_debug (H5F_t *f, const void *_mesg, FILE *stream, intn indent,
intn fwidth)
{
const H5O_istore_t *mesg = (const H5O_istore_t *)_mesg;
intn i;
FUNC_ENTER (H5O_istore_debug, NULL, FAIL);
/* check args */
assert (f);
assert (mesg);
assert (stream);
assert (indent>=0);
assert (fwidth>=0);
fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
"B-tree address:",
(unsigned long)(mesg->btree_addr));
fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth,
"Number of dimensions:",
(unsigned long)(mesg->ndims));
/* Alignment */
fprintf (stream, "%*s%-*s {", indent, "", fwidth,
"Alignment:");
for (i=0; i<mesg->ndims; i++) {
fprintf (stream, "%s%lu", i?", ":"",
(unsigned long)(mesg->alignment[i]));
}
fprintf (stream, "}\n");
FUNC_LEAVE (SUCCEED);
}

View File

@ -6,7 +6,7 @@
*
* Created: H5Oname.c
* Aug 12 1997
* Robb Matzke <robb@maya.nuance.com>
* Robb Matzke <matzke@llnl.gov>
*
* Purpose: Object name message.
*
@ -62,7 +62,7 @@ static hbool_t interface_initialize_g = FALSE;
* Failure: NULL
*
* Programmer: Robb Matzke
* robb@maya.nuance.com
* matzke@llnl.gov
* Aug 12 1997
*
* Modifications:
@ -101,7 +101,7 @@ H5O_name_decode (H5F_t *f, size_t raw_size, const uint8 *p)
* Failure: FAIL
*
* Programmer: Robb Matzke
* robb@maya.nuance.com
* matzke@llnl.gov
* Aug 12 1997
*
* Modifications:
@ -144,7 +144,7 @@ H5O_name_encode (H5F_t *f, size_t raw_size, uint8 *p, const void *_mesg)
* Failure: NULL
*
* Programmer: Robb Matzke
* robb@maya.nuance.com
* matzke@llnl.gov
* Aug 12 1997
*
* Modifications:
@ -184,7 +184,7 @@ H5O_name_copy (const void *_mesg, void *_dest)
* Failure: FAIL
*
* Programmer: Robb Matzke
* robb@maya.nuance.com
* matzke@llnl.gov
* Aug 12 1997
*
* Modifications:
@ -219,7 +219,7 @@ H5O_name_size (H5F_t *f, const void *_mesg)
* Failure: FAIL
*
* Programmer: Robb Matzke
* robb@maya.nuance.com
* matzke@llnl.gov
* Aug 12 1997
*
* Modifications:
@ -253,7 +253,7 @@ H5O_name_reset (void *_mesg)
* Failure: FAIL
*
* Programmer: Robb Matzke
* robb@maya.nuance.com
* matzke@llnl.gov
* Aug 12 1997
*
* Modifications:

View File

@ -115,10 +115,23 @@ typedef h5_atomic_type_t H5O_sim_dtype_t;
#define H5O_STD_STORE_ID 0x0005
extern const H5O_class_t H5O_STD_STORE[1];
typedef struct H5O_std_store {
haddr_t off;
haddr_t len;
} H5O_std_store_t;
typedef struct H5O_std_store_t {
haddr_t off;
haddr_t len;
} H5O_std_store_t;
/*
* Indexed Data Storage message.
*/
#define H5O_ISTORE_ID 0x0008
#define H5O_ISTORE_NDIMS 32
extern const H5O_class_t H5O_ISTORE[1];
typedef struct H5O_istore_t {
haddr_t btree_addr; /*file address of B-tree */
uintn ndims; /*num dimensions in stored data */
size_t alignment[H5O_ISTORE_NDIMS]; /*algn in logical space */
} H5O_istore_t;
/*
* Object name message.

View File

@ -205,7 +205,7 @@ H5O_sim_dtype_fast (const H5G_cache_t *cache, void *mesg)
method is required for simple datatypes, as they can be cached in the
symbol-table entry)
--------------------------------------------------------------------------*/
static herr_t
static hbool_t
H5O_sim_dtype_cache (H5G_type_t *cache_type, H5G_cache_t *cache,
const void *mesg)
{

View File

@ -1,5 +1,11 @@
/* src/H5config.h.in. Generated automatically from configure.in by autoheader. */
/* Define to empty if the keyword does not work. */
#undef const
/* Define as __inline if that's what the C compiler calls it. */
#undef inline
/* Define to `long' if <sys/types.h> doesn't define. */
#undef off_t
@ -13,6 +19,12 @@
byte first (like Motorola and SPARC, unlike Intel and VAX). */
#undef WORDS_BIGENDIAN
/* Define if the __attribute__(()) extension is present */
/* #define HAVE_ATTRIBUTE */
/* Define if the compiler understands the __FUNCTION__ keyword. */
/* #define HAVE_FUNCTION */
/* The number of bytes in a double. */
#undef SIZEOF_DOUBLE

View File

@ -63,8 +63,19 @@
#define MACIO 2
#define WINNTIO 3
#define PAGEBUFIO 4
#define FILELIB POSIXBUFIO
#ifndef FILELIB
# define FILELIB POSIXBUFIO
#endif
/* Does the compiler support the __attribute__(()) syntax? */
#ifndef HAVE_ATTRIBUTE
# define __attribute__(X) /*void*/
#endif
/* Does the compiler expand __FUNCTION__? */
#ifndef HAVE_FUNCTION
# define __FUNCTION__ "NoFuntionName"
#endif
/* number of members in an array */
#ifndef NELMTS
@ -359,6 +370,7 @@ typedef off_t haddr_t;
/*
* And now for a couple non-Posix functions...
*/
extern char *strdup (const char *s);
#define HDstrdup(S) strdup(S)
/*-------------------------------------------------------------------------

View File

@ -14,10 +14,10 @@ LIB=libhdf5.a
PROGS=debug
# Source and object files for the library (lexicographically)...
LIB_SRC=H5.c H5A.c H5AC.c H5B.c H5C.c H5D.c H5Dconv.c H5E.c H5F.c H5G.c \
H5Gent.c H5Gnode.c H5Gshad.c H5Gstab.c H5H.c H5M.c H5MF.c H5MM.c \
H5O.c H5Ocont.c H5Oname.c H5Onull.c H5Osdtyp.c H5Osdim.c H5Ostab.c \
H5Ostdst.c H5P.c H5T.c
LIB_SRC=H5.c H5A.c H5AC.c H5B.c H5C.c H5D.c H5Dconv.c H5E.c H5F.c H5Fistore.c \
H5G.c H5Gent.c H5Gnode.c H5Gshad.c H5Gstab.c H5H.c H5M.c H5MF.c \
H5MM.c H5O.c H5Ocont.c H5Oistore.c H5Oname.c H5Onull.c H5Osdtyp.c \
H5Osdim.c H5Ostab.c H5Ostdst.c H5P.c H5T.c H5V.c
LIB_OBJ=$(LIB_SRC:.c=.o)
@ -35,7 +35,7 @@ PUB_HDR=H5public.h H5Apublic.h H5ACpublic.h H5Bpublic.h H5Cpublic.h \
PRIVATE_HDR=H5private.h H5Aprivate.h H5ACprivate.h H5Bprivate.h \
H5Cprivate.h H5Dprivate.h H5Eprivate.h H5Fprivate.h H5Gprivate.h \
H5Gpkg.h H5Hprivate.h H5Mprivate.h H5MFprivate.h H5MMprivate.h \
H5Oprivate.h H5Pprivate.h H5Tprivate.h
H5Oprivate.h H5Pprivate.h H5Tprivate.h H5Vprivate.h
# How to build the programs...
debug: debug.o $(LIB)

View File

@ -10,18 +10,38 @@
CPPFLAGS=-I. -I../src @CPPFLAGS@
# These are our main targets:
PROGS=testhdf5
PROGS=testhdf5 hyperslab istore
TESTS=$(PROGS)
# Source and object files for programs...
PROG_SRC=testhdf5.c tfile.c theap.c tmeta.c tohdr.c tstab.c th5t.c th5p.c th5d.c
# Source and object files for programs... The PROG_SRC list contains all the
# source files and is used for things like dependencies, archiving, etc. The
# other source lists are for the individual tests, the files of which may
# overlap with other tests.
PROG_SRC=testhdf5.c tfile.c theap.c tmeta.c tohdr.c tstab.c th5t.c th5p.c \
th5d.c hyperslab.c istore.c
PROG_OBJ=$(PROG_SRC:.c=.o)
TESTHDF5_SRC=testhdf5.c tfile.c theap.c tmeta.c tohdr.c tstab.c th5t.c \
th5p.c th5d.c
TESTHDF5_OBJ=$(TESTHDF5_SRC:.c=.o)
HYPERSLAB_SRC=hyperslab.c
HYPERSLAB_OBJ=$(HYPERSLAB_SRC:.c=.o)
ISTORE_SRC=istore.c
ISTORE_OBJ=$(ISTORE_SRC:.c=.o)
# Private header files (not to be installed)...
PRIVATE_HDR=testhdf5.h
# How to build the programs...
testhdf5: $(PROG_OBJ) ../src/libhdf5.a
$(CC) $(CFLAGS) -o $@ $(PROG_OBJ) ../src/libhdf5.a $(LIBS)
testhdf5: $(TESTHDF5_OBJ) ../src/libhdf5.a
$(CC) $(CFLAGS) -o $@ $(TESTHDF5_OBJ) ../src/libhdf5.a $(LIBS)
hyperslab: $(HYPERSLAB_OBJ) ../src/libhdf5.a
$(CC) $(CFLAGS) -o $@ $(HYPERSLAB_OBJ) ../src/libhdf5.a $(LIBS)
istore: $(ISTORE_OBJ) ../src/libhdf5.a
$(CC) $(CFLAGS) -o $@ $(ISTORE_OBJ) ../src/libhdf5.a $(LIBS)
@CONCLUDE@

431
test/istore.c Normal file
View File

@ -0,0 +1,431 @@
/*
* Copyright (C) 1997 NCSA
* All rights reserved.
*
* Programmer: Robb Matzke <matzke@llnl.gov>
* Wednesday, October 15, 1997
*
* Purpose: Tests various aspects of indexed raw data storage.
*/
#include <H5private.h>
#include <H5Fprivate.h>
#include <H5Gprivate.h>
#include <H5MMprivate.h>
#include <H5Oprivate.h>
#include <H5Vprivate.h>
#define FILENAME "istore.h5"
#define AT() printf (" at %s:%d in %s()...\n", \
__FILE__, __LINE__, __FUNCTION__);
/*-------------------------------------------------------------------------
* Function: print_array
*
* Purpose: Prints the values in an array
*
* Return: void
*
* Programmer: Robb Matzke
* Friday, October 10, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static void
print_array (uint8 *array, size_t nx, size_t ny, size_t nz)
{
int i, j, k;
for (i=0; i<nx; i++) {
if (nz>1) {
printf ("i=%d:\n", i);
} else {
printf ("%03d:", i);
}
for (j=0; j<ny; j++) {
if (nz>1) printf ("%03d:", j);
for (k=0; k<nz; k++) {
printf (" %3d", *array++);
}
if (nz>1) printf ("\n");
}
printf ("\n");
}
}
/*-------------------------------------------------------------------------
* Function: new_object
*
* Purpose: Creates a new object that refers to a indexed storage of raw
* data. No raw data is stored.
*
* Return: Success: Handle to a new open object.
*
* Failure: NULL, error message printed.
*
* Programmer: Robb Matzke
* Wednesday, October 15, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static H5G_entry_t *
new_object (H5F_t *f, const char *name, size_t ndims)
{
H5G_entry_t *handle = NULL;
H5O_istore_t istore;
intn i;
/* Create the object symbol table entry and header */
if (NULL==(handle=H5G_create (f, name, 64))) {
puts ("*FAILED*");
if (!isatty (1)) {
AT ();
printf (" H5G_create (f, name=\"%s\") = NULL\n", name);
}
return NULL;
}
/* Add the indexed-storage message */
memset (&istore, 0, sizeof istore);
istore.ndims = ndims;
for (i=0; i<ndims; i++) istore.alignment[i] = 2;
if (H5O_modify (f, H5O_NO_ADDR, handle, H5O_ISTORE, H5O_NEW_MESG,
&istore)<0) {
printf ("*FAILED*\n");
if (!isatty (1)) {
AT();
printf (" H5G_modify istore message failure\n");
}
return NULL;
}
return handle;
}
/*-------------------------------------------------------------------------
* Function: test_create
*
* Purpose: Creates a named object that refers to indexed storage of raw
* data. No raw data is stored.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Wednesday, October 15, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static herr_t
test_create (H5F_t *f, const char *prefix)
{
H5G_entry_t *handle = NULL;
intn i;
char name[256];
printf ("%-70s", "Testing istore create");
fflush (stdout);
for (i=1; i<=H5O_ISTORE_NDIMS; i++) {
sprintf (name, "%s_%02d", prefix, i);
if (NULL==(handle=new_object (f, name, i))) return FAIL;
H5G_close (f, handle);
}
puts (" PASSED");
return SUCCEED;
}
/*-------------------------------------------------------------------------
* Function: test_extend
*
* Purpose: Creates an empty object and then writes to it in such a way
* as to always extend the object's domain.
*
* Return: Success: SUCCEED
*
* Failure: FAIL
*
* Programmer: Robb Matzke
* Wednesday, October 15, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static herr_t
test_extend (H5F_t *f, const char *prefix,
size_t nx, size_t ny, size_t nz)
{
H5G_entry_t *handle = NULL;
int i, j, k, ndims, ctr;
uint8 *buf=NULL, *check=NULL, *whole=NULL;
char dims[64], s[256], name[256];
size_t offset[3];
size_t max_corner[3];
size_t size[3];
size_t whole_size[3];
H5O_istore_t istore;
if (!nz) {
if (!ny) {
ndims = 1;
ny = nz = 1;
sprintf (dims, "%d", nx);
} else {
ndims = 2;
nz = 1;
sprintf (dims, "%dx%d", nx, ny);
}
} else {
ndims = 3;
sprintf (dims, "%dx%dx%d", nx, ny, nz);
}
sprintf (s, "Testing istore extend: %s", dims);
printf ("%-70s", s);
fflush (stdout);
buf = H5MM_xmalloc (nx*ny*nz);
check = H5MM_xmalloc (nx*ny*nz);
whole = H5MM_xcalloc (nx*ny*nz, 1);
/* Build the new empty object */
sprintf (name, "%s_%s", prefix, dims);
if (NULL==(handle=new_object (f, name, ndims))) {
if (!isatty (1)) {
AT ();
printf (" Cannot create %d-d object `%s'\n", ndims, name);
}
goto error;
}
if (NULL==H5O_read (f, H5O_NO_ADDR, handle, H5O_ISTORE, 0, &istore)) {
puts ("*FAILED*");
if (!isatty (1)) {
AT ();
printf (" Unable to read istore message\n");
}
goto error;
}
if (ndims!=istore.ndims) {
puts ("*FAILED*");
if (!isatty (1)) {
AT ();
printf (" Header read error: istore.ndims != %d\n", ndims);
}
goto error;
}
whole_size[0] = nx;
whole_size[1] = ny;
whole_size[2] = nz;
max_corner[0] = 0;
max_corner[1] = 0;
max_corner[2] = 0;
for (ctr=0; H5V_vector_lt (ndims, max_corner, whole_size); ctr++) {
/* Size and location */
if (0==ctr) {
offset[0] = offset[1] = offset[2] = 0;
size[0] = size[1] = size[2] = 1;
} else {
for (i=0; i<ndims; i++) {
if (ctr % ndims == i) {
offset[i] = max_corner[i];
size[i] = 1;
if (offset[i]+size[i]>whole_size[i]) continue;
} else {
offset[i] = 0;
size[i] = max_corner[i];
}
}
}
#if 0
if (0==ctr) printf ("\n");
printf (" Insert: ctr=%d, corner=(%d", ctr, offset[0]);
if (ndims>1) printf (",%d", offset[1]);
if (ndims>2) printf (",%d", offset[2]);
printf ("), size=(%d", size[0]);
if (ndims>1) printf (",%d", size[1]);
if (ndims>2) printf (",%d", size[2]);
printf (")\n");
#endif
/* Fill the source array */
memset (buf, 128+ctr, size[0]*size[1]*size[2]);
/* Write to disk */
if (H5F_istore_write (f, &istore, offset, size, buf)<0) {
puts ("*FAILED*");
if (!isatty (1)) {
AT ();
printf (" Write failed: ctr=%d\n", ctr);
}
goto error;
}
/* Read from disk */
memset (check, 0xff, size[0]*size[1]*size[2]);
if (H5F_istore_read (f, &istore, offset, size, check)<0) {
puts ("*FAILED*");
if (!isatty (1)) {
AT ();
printf (" Read failed: ctr=%d\n", ctr);
}
goto error;
}
if (memcmp (buf, check, size[0]*size[1]*size[2])) {
puts ("*FAILED*");
if (!isatty (1)) {
AT ();
printf (" Read check failed: ctr=%d\n", ctr);
printf (" Wrote:\n");
print_array (buf, size[0], size[1], size[2]);
printf (" Read:\n");
print_array (buf, size[0], size[1], size[2]);
}
goto error;
}
/* Write to `whole' buffer for later checking */
H5V_hyper_copy (ndims, size,
whole_size, offset, whole, /*dst*/
size, H5V_ZERO, buf); /*src*/
/* Update max corner */
for (i=0; i<ndims; i++) {
max_corner[i] = MAX (max_corner[i], offset[i]+size[i]);
}
}
/* Update the object header */
H5O_modify (f, H5O_NO_ADDR, handle, H5O_ISTORE, 0, &istore);
/* Now read the entire array back out and check it */
memset (buf, 0xff, nx*ny*nz);
if (H5F_istore_read (f, &istore, H5V_ZERO, whole_size, buf)<0) {
puts ("*FAILED*");
if (!isatty (1)) {
AT ();
printf (" Read failed for whole array\n");
}
goto error;
}
for (i=0; i<nx; i++) {
for (j=0; j<ny; j++) {
for (k=0; k<nz; k++) {
if (whole[i*ny*nz + j*nz + k] != buf[i*ny*nz + j*nz + k]) {
puts ("*FAILED*");
if (!isatty (1)) {
AT ();
printf (" Check failed at i=%d", i);
if (ndims>1) printf (", j=%d", j);
if (ndims>2) printf (", k=%d\n", k);
printf (" Check array is:\n");
print_array (whole, nx, ny, nz);
printf (" Value read is:\n");
print_array (buf, nx, ny, nz);
}
goto error;
}
}
}
}
H5G_close (f, handle);
puts (" PASSED");
H5MM_xfree (buf);
H5MM_xfree (check);
H5MM_xfree (whole);
return SUCCEED;
error:
H5MM_xfree (buf);
H5MM_xfree (check);
H5MM_xfree (whole);
return FAIL;
}
/*-------------------------------------------------------------------------
* Function: main
*
* Purpose: Tests indexed storage stuff.
*
* Return: Success: exit(0)
*
* Failure: exit(non-zero)
*
* Programmer: Robb Matzke
* Wednesday, October 15, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
int
main (void)
{
H5F_t *f;
herr_t status;
int nerrors = 0;
/* Create the test file */
if (NULL==(f=H5F_open (FILENAME, H5F_ACC_CREAT|H5F_ACC_WRITE|H5F_ACC_TRUNC,
NULL))) {
printf ("Cannot create file %s; test aborted\n", FILENAME);
exit (1);
}
/*----------------------
* INDEXED STORAGE TESTS
*----------------------
*/
status = test_create (f, "test_create_1");
nerrors += status<0 ? 1 : 0;
status = test_extend (f, "test_extend_1", 10, 0, 0);
nerrors += status<0 ? 1 : 0;
status = test_extend (f, "test_extend_1", 10, 10, 0);
nerrors += status<0 ? 1 : 0;
status = test_extend (f, "test_extend_1", 10, 10, 10);
nerrors += status<0 ? 1 : 0;
/* Close the test file and exit */
H5F_close (f);
if (nerrors) {
printf ("***** %d I-STORE TEST%s FAILED! *****\n",
nerrors, 1==nerrors?"":"S");
if (isatty (1)) {
printf ("(Redirect output to a pager or a file to see "
"debug output)\n");
}
exit (1);
}
printf ("All i-store tests passed.\n");
exit (0);
}

View File

@ -84,7 +84,7 @@ test_1 (void)
*/
HDmemset (&dir_ent, 0, sizeof(H5G_entry_t));
HDmemset (&ent1, 0, sizeof(H5G_entry_t));
status = H5G_find (f, NULL, &dir_ent, "/", &ent1);
status = H5G_find (f, "/", &dir_ent, &ent1);
CHECK_I (status, "H5G_find");
VERIFY (dir_ent.header, 0, "H5G_find");
VERIFY (ent1.header, obj1->header, "H5G_find");
@ -107,7 +107,7 @@ test_1 (void)
/* try to read the first object */
HDmemset (&ent1, 0, sizeof(H5G_entry_t));
status = H5G_find (f, NULL, NULL, "/Root Object", &ent1);
status = H5G_find (f, "/Root Object", NULL, &ent1);
CHECK_I (status, "H5G_find");
VERIFY (ent1.header, obj1->header, "H5G_find");
@ -151,7 +151,7 @@ test_1 (void)
*/
HDmemset (&dir_ent, 0, sizeof(H5G_entry_t));
HDmemset (&ent1, 0, sizeof(H5G_entry_t));
status = H5G_find (f, NULL, &dir_ent, "/", &ent1);
status = H5G_find (f, "/", &dir_ent, &ent1);
CHECK_I (status, "H5G_find");
VERIFY (dir_ent.header, 0, "H5G_find");
VERIFY (ent1.header, obj1->header, "H5G_find");
@ -163,7 +163,7 @@ test_1 (void)
/* now as `/foo' */
HDmemset (&dir_ent, 0, sizeof(H5G_entry_t));
HDmemset (&ent1, 0, sizeof(H5G_entry_t));
status = H5G_find (f, NULL, &dir_ent, "/foo", &ent1);
status = H5G_find (f, "/foo", &dir_ent, &ent1);
CHECK_I (status, "H5G_find");
VERIFY (dir_ent.header, 0, "H5G_find");
VERIFY (ent1.header, obj1->header, "H5G_find");
@ -185,7 +185,7 @@ test_1 (void)
/* try to read the first object */
HDmemset (&ent1, 0, sizeof(H5G_entry_t));
status = H5G_find (f, NULL, NULL, "/foo", &ent1);
status = H5G_find (f, "/foo", NULL, &ent1);
CHECK_I (status, "H5G_find");
VERIFY (ent1.header, obj1->header, "H5G_find");
@ -243,7 +243,7 @@ test_2 (void)
* Create a directory that has so many entries that the root
* of the B-tree ends up splitting.
*/
obj1 = H5G_mkdir (f, "/big", nsyms*12+2);
obj1 = H5G_new (f, "/big", nsyms*12+2);
CHECK_PTR (obj1, "H5G_mkdir");
H5G_close (f, obj1);
obj1 = NULL;